summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSamuel Rødal <samuel.rodal@nokia.com>2011-05-13 11:51:41 +0200
committerSamuel Rødal <samuel.rodal@nokia.com>2011-05-13 15:13:15 +0200
commit850b602c7a72635eb37a998089ee085d5d505c34 (patch)
tree7cce231c1293888e98b9c661f9960ecd8d4999a2
parent6697f2a899fac47a65122a85691b2cfe63c6152c (diff)
Initial QPlatformWindow window state setting API and xcb implementation.
-rw-r--r--src/gui/kernel/qplatformwindow_qpa.cpp11
-rw-r--r--src/gui/kernel/qplatformwindow_qpa.h2
-rw-r--r--src/gui/kernel/qwindow.cpp22
-rw-r--r--src/gui/kernel/qwindow.h4
-rw-r--r--src/gui/kernel/qwindow_p.h2
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp79
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.h3
-rw-r--r--src/widgets/kernel/qwidget_qpa.cpp50
8 files changed, 144 insertions, 29 deletions
diff --git a/src/gui/kernel/qplatformwindow_qpa.cpp b/src/gui/kernel/qplatformwindow_qpa.cpp
index 24c337cf57..d7d1d96f42 100644
--- a/src/gui/kernel/qplatformwindow_qpa.cpp
+++ b/src/gui/kernel/qplatformwindow_qpa.cpp
@@ -117,6 +117,17 @@ Qt::WindowFlags QPlatformWindow::setWindowFlags(Qt::WindowFlags 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
*/
WId QPlatformWindow::winId() const { return WId(0); }
diff --git a/src/gui/kernel/qplatformwindow_qpa.h b/src/gui/kernel/qplatformwindow_qpa.h
index 1730f3d85e..c74e96695d 100644
--- a/src/gui/kernel/qplatformwindow_qpa.h
+++ b/src/gui/kernel/qplatformwindow_qpa.h
@@ -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);
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
index 7faf49395a..897b370cf5 100644
--- a/src/gui/kernel/qwindow.cpp
+++ b/src/gui/kernel/qwindow.cpp
@@ -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
diff --git a/src/gui/kernel/qwindow.h b/src/gui/kernel/qwindow.h
index f2fde2d532..70227106b1 100644
--- a/src/gui/kernel/qwindow.h
+++ b/src/gui/kernel/qwindow.h
@@ -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;
diff --git a/src/gui/kernel/qwindow_p.h b/src/gui/kernel/qwindow_p.h
index 6f1038e8c4..b6227741ba 100644
--- a/src/gui/kernel/qwindow_p.h
+++ b/src/gui/kernel/qwindow_p.h
@@ -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;
};
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index f6d9c2f762..dd28d13eb5 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -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
diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h
index 3ed58b33d3..831c25bdfb 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.h
+++ b/src/plugins/platforms/xcb/qxcbwindow.h
@@ -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
diff --git a/src/widgets/kernel/qwidget_qpa.cpp b/src/widgets/kernel/qwidget_qpa.cpp
index f6833915ec..b7b502a35f 100644
--- a/src/widgets/kernel/qwidget_qpa.cpp
+++ b/src/widgets/kernel/qwidget_qpa.cpp
@@ -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);
+ }
}
}
}