Initial QPlatformWindow window state setting API and xcb implementation.
This commit is contained in:
parent
6697f2a899
commit
850b602c7a
@ -116,6 +116,17 @@ Qt::WindowFlags QPlatformWindow::setWindowFlags(Qt::WindowFlags flags)
|
||||
return flags;
|
||||
}
|
||||
|
||||
/*!
|
||||
Requests setting the window state of this surface
|
||||
to \a type. Returns the actual state set.
|
||||
|
||||
Qt::WindowActive can be ignored.
|
||||
*/
|
||||
Qt::WindowState QPlatformWindow::setWindowState(Qt::WindowState)
|
||||
{
|
||||
return Qt::WindowNoState;
|
||||
}
|
||||
|
||||
/*!
|
||||
Reimplement in subclasses to return a handle to the native window
|
||||
*/
|
||||
|
@ -71,6 +71,8 @@ public:
|
||||
|
||||
virtual void setVisible(bool visible);
|
||||
virtual Qt::WindowFlags setWindowFlags(Qt::WindowFlags flags);
|
||||
virtual Qt::WindowState setWindowState(Qt::WindowState state);
|
||||
|
||||
virtual WId winId() const;
|
||||
virtual void setParent(const QPlatformWindow *window);
|
||||
|
||||
|
@ -89,6 +89,8 @@ void QWindow::create()
|
||||
d->windowFlags = d->platformWindow->setWindowFlags(d->windowFlags);
|
||||
if (!d->windowTitle.isNull())
|
||||
d->platformWindow->setWindowTitle(d->windowTitle);
|
||||
if (d->windowState != Qt::WindowNoState)
|
||||
d->windowState = d->platformWindow->setWindowState(d->windowState);
|
||||
|
||||
QObjectList childObjects = children();
|
||||
for (int i = 0; i < childObjects.size(); i ++) {
|
||||
@ -232,16 +234,24 @@ void QWindow::requestActivateWindow()
|
||||
}
|
||||
}
|
||||
|
||||
Qt::WindowStates QWindow::windowState() const
|
||||
Qt::WindowState QWindow::windowState() const
|
||||
{
|
||||
qDebug() << "unimplemented:" << __FILE__ << __LINE__;
|
||||
return Qt::WindowNoState;
|
||||
Q_D(const QWindow);
|
||||
return d->windowState;
|
||||
}
|
||||
|
||||
void QWindow::setWindowState(Qt::WindowStates state)
|
||||
void QWindow::setWindowState(Qt::WindowState state)
|
||||
{
|
||||
Q_UNUSED(state);
|
||||
qDebug() << "unimplemented:" << __FILE__ << __LINE__;
|
||||
if (state == Qt::WindowActive) {
|
||||
requestActivateWindow();
|
||||
return;
|
||||
}
|
||||
|
||||
Q_D(QWindow);
|
||||
if (d->platformWindow)
|
||||
d->windowState = d->platformWindow->setWindowState(state);
|
||||
else
|
||||
d->windowState = state;
|
||||
}
|
||||
|
||||
QSize QWindow::minimumSize() const
|
||||
|
@ -111,8 +111,8 @@ public:
|
||||
void setOpacity(qreal level);
|
||||
void requestActivateWindow();
|
||||
|
||||
Qt::WindowStates windowState() const;
|
||||
void setWindowState(Qt::WindowStates state);
|
||||
Qt::WindowState windowState() const;
|
||||
void setWindowState(Qt::WindowState state);
|
||||
|
||||
QSize minimumSize() const;
|
||||
QSize maximumSize() const;
|
||||
|
@ -64,6 +64,7 @@ public:
|
||||
, visible(false)
|
||||
, glContext(0)
|
||||
, surface(0)
|
||||
, windowState(Qt::WindowNoState)
|
||||
{
|
||||
isWindow = true;
|
||||
}
|
||||
@ -82,6 +83,7 @@ public:
|
||||
QRect geometry;
|
||||
QWindowContext *glContext;
|
||||
QWindowSurface *surface;
|
||||
Qt::WindowState windowState;
|
||||
};
|
||||
|
||||
|
||||
|
@ -90,6 +90,7 @@ static inline bool isTransient(const QWidget *w)
|
||||
QXcbWindow::QXcbWindow(QWindow *window)
|
||||
: QPlatformWindow(window)
|
||||
, m_context(0)
|
||||
, m_windowState(Qt::WindowNoState)
|
||||
{
|
||||
m_screen = static_cast<QXcbScreen *>(QGuiApplicationPrivate::platformIntegration()->screens().at(0));
|
||||
|
||||
@ -424,6 +425,84 @@ Qt::WindowFlags QXcbWindow::setWindowFlags(Qt::WindowFlags flags)
|
||||
return flags;
|
||||
}
|
||||
|
||||
void QXcbWindow::changeNetWmState(bool set, xcb_atom_t one, xcb_atom_t two)
|
||||
{
|
||||
xcb_client_message_event_t event;
|
||||
|
||||
event.response_type = XCB_CLIENT_MESSAGE;
|
||||
event.format = 32;
|
||||
event.window = m_window;
|
||||
event.type = atom(QXcbAtom::_NET_WM_STATE);
|
||||
event.data.data32[0] = set ? 1 : 0;
|
||||
event.data.data32[1] = one;
|
||||
event.data.data32[2] = two;
|
||||
event.data.data32[3] = 0;
|
||||
event.data.data32[4] = 0;
|
||||
|
||||
Q_XCB_CALL(xcb_send_event(xcb_connection(), 0, m_screen->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event));
|
||||
}
|
||||
|
||||
Qt::WindowState QXcbWindow::setWindowState(Qt::WindowState state)
|
||||
{
|
||||
if (state == m_windowState)
|
||||
return state;
|
||||
|
||||
// unset old state
|
||||
switch (m_windowState) {
|
||||
case Qt::WindowMinimized:
|
||||
Q_XCB_CALL(xcb_map_window(xcb_connection(), m_window));
|
||||
break;
|
||||
case Qt::WindowMaximized:
|
||||
changeNetWmState(false,
|
||||
atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ),
|
||||
atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_VERT));
|
||||
break;
|
||||
case Qt::WindowFullScreen:
|
||||
changeNetWmState(false, atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// set new state
|
||||
switch (state) {
|
||||
case Qt::WindowMinimized:
|
||||
{
|
||||
xcb_client_message_event_t event;
|
||||
|
||||
event.response_type = XCB_CLIENT_MESSAGE;
|
||||
event.format = 32;
|
||||
event.window = m_window;
|
||||
event.type = atom(QXcbAtom::WM_CHANGE_STATE);
|
||||
event.data.data32[0] = XCB_WM_STATE_ICONIC;
|
||||
event.data.data32[1] = 0;
|
||||
event.data.data32[2] = 0;
|
||||
event.data.data32[3] = 0;
|
||||
event.data.data32[4] = 0;
|
||||
|
||||
Q_XCB_CALL(xcb_send_event(xcb_connection(), 0, m_screen->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event));
|
||||
}
|
||||
break;
|
||||
case Qt::WindowMaximized:
|
||||
changeNetWmState(true,
|
||||
atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ),
|
||||
atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_VERT));
|
||||
break;
|
||||
case Qt::WindowFullScreen:
|
||||
changeNetWmState(true, atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN));
|
||||
break;
|
||||
case Qt::WindowNoState:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
connection()->sync();
|
||||
|
||||
m_windowState = state;
|
||||
return m_windowState;
|
||||
}
|
||||
|
||||
void QXcbWindow::setNetWmWindowTypes(Qt::WindowFlags flags)
|
||||
{
|
||||
// in order of decreasing priority
|
||||
|
@ -62,6 +62,7 @@ public:
|
||||
|
||||
void setVisible(bool visible);
|
||||
Qt::WindowFlags setWindowFlags(Qt::WindowFlags flags);
|
||||
Qt::WindowState setWindowState(Qt::WindowState state);
|
||||
WId winId() const;
|
||||
void setParent(const QPlatformWindow *window);
|
||||
|
||||
@ -93,6 +94,7 @@ public:
|
||||
|
||||
private:
|
||||
void setNetWmWindowTypes(Qt::WindowFlags flags);
|
||||
void changeNetWmState(bool set, xcb_atom_t one, xcb_atom_t two = 0);
|
||||
|
||||
QXcbScreen *m_screen;
|
||||
|
||||
@ -103,6 +105,7 @@ private:
|
||||
xcb_sync_counter_t m_syncCounter;
|
||||
|
||||
bool m_hasReceivedSyncRequest;
|
||||
Qt::WindowState m_windowState;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -443,7 +443,7 @@ void QWidgetPrivate::setFullScreenSize_helper()
|
||||
data.in_set_window_state = old_state;
|
||||
}
|
||||
|
||||
static Qt::WindowStates effectiveState(Qt::WindowStates state)
|
||||
static Qt::WindowState effectiveState(Qt::WindowStates state)
|
||||
{
|
||||
if (state & Qt::WindowMinimized)
|
||||
return Qt::WindowMinimized;
|
||||
@ -466,8 +466,8 @@ void QWidget::setWindowState(Qt::WindowStates newstate)
|
||||
data->window_state = newstate;
|
||||
data->in_set_window_state = 1;
|
||||
bool needShow = false;
|
||||
Qt::WindowStates newEffectiveState = effectiveState(newstate);
|
||||
Qt::WindowStates oldEffectiveState = effectiveState(oldstate);
|
||||
Qt::WindowState newEffectiveState = effectiveState(newstate);
|
||||
Qt::WindowState oldEffectiveState = effectiveState(oldstate);
|
||||
if (isWindow() && newEffectiveState != oldEffectiveState) {
|
||||
d->createTLExtra();
|
||||
if (oldEffectiveState == Qt::WindowNoState) { //normal
|
||||
@ -479,24 +479,32 @@ void QWidget::setWindowState(Qt::WindowStates newstate)
|
||||
needShow = true;
|
||||
}
|
||||
|
||||
if (newEffectiveState == Qt::WindowMinimized) {
|
||||
//### not ideal...
|
||||
hide();
|
||||
needShow = false;
|
||||
} else if (newEffectiveState == Qt::WindowFullScreen) {
|
||||
d->topData()->savedFlags = windowFlags();
|
||||
setParent(0, Qt::FramelessWindowHint | (windowFlags() & Qt::WindowStaysOnTopHint));
|
||||
d->setFullScreenSize_helper();
|
||||
raise();
|
||||
needShow = true;
|
||||
} else if (newEffectiveState == Qt::WindowMaximized) {
|
||||
createWinId();
|
||||
d->setMaxWindowState_helper();
|
||||
} else { //normal
|
||||
QRect r = d->topData()->normalGeometry;
|
||||
if (r.width() >= 0) {
|
||||
d->topData()->normalGeometry = QRect(0,0,-1,-1);
|
||||
setGeometry(r);
|
||||
Q_ASSERT(windowHandle());
|
||||
windowHandle()->setWindowState(newEffectiveState);
|
||||
bool supported = windowHandle()->windowState() == newEffectiveState;
|
||||
|
||||
if (!supported) {
|
||||
// emulate the window state
|
||||
if (newEffectiveState == Qt::WindowMinimized) {
|
||||
//### not ideal...
|
||||
hide();
|
||||
needShow = false;
|
||||
} else if (newEffectiveState == Qt::WindowFullScreen) {
|
||||
d->topData()->savedFlags = windowFlags();
|
||||
setParent(0, Qt::FramelessWindowHint | (windowFlags() & Qt::WindowStaysOnTopHint));
|
||||
d->setFullScreenSize_helper();
|
||||
raise();
|
||||
needShow = true;
|
||||
} else if (newEffectiveState == Qt::WindowMaximized) {
|
||||
createWinId();
|
||||
d->setMaxWindowState_helper();
|
||||
} else if (newEffectiveState == Qt::WindowNoState) {
|
||||
// reset old geometry
|
||||
QRect r = d->topData()->normalGeometry;
|
||||
if (r.width() >= 0) {
|
||||
d->topData()->normalGeometry = QRect(0,0,-1,-1);
|
||||
setGeometry(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user