summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSamuel Rødal <samuel.rodal@nokia.com>2011-05-18 12:27:50 +0200
committerSamuel Rødal <samuel.rodal@nokia.com>2011-05-18 12:28:09 +0200
commit2a5cc5fc625350b77d7b82eaa8c43bce0d446cd1 (patch)
tree0b29db747dff38690d0c2008998302f411d0ddce /src
parent864815ef2efbc3b5dca2a645c1b63f9bb67285d0 (diff)
Support Qt::WindowStaysOnTopHint and other window flags in XCB backend.
Diffstat (limited to 'src')
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp109
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.h6
2 files changed, 111 insertions, 4 deletions
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index eeec59c868..35c9efc1d9 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -73,6 +73,8 @@
#include "../eglconvenience/qxlibeglintegration.h"
#endif
+//#ifdef NET_WM_STATE_DEBUG
+
// Returns true if we should set WM_TRANSIENT_FOR on \a w
static inline bool isTransient(const QWindow *w)
{
@@ -285,10 +287,15 @@ void QXcbWindow::show()
}
// update _MOTIF_WM_HINTS
- updateMotifWmHintsBeforeShow();
+ updateMotifWmHintsBeforeMap();
+
+ // update _NET_WM_STATE
+ updateNetWmStateBeforeMap();
}
Q_XCB_CALL(xcb_map_window(xcb_connection(), m_window));
+ xcb_flush(xcb_connection());
+
connection()->sync();
}
@@ -299,7 +306,6 @@ void QXcbWindow::hide()
// send synthetic UnmapNotify event according to icccm 4.1.4
xcb_unmap_notify_event_t event;
event.response_type = XCB_UNMAP_NOTIFY;
- event.sequence = 0; // does this matter?
event.event = m_screen->root();
event.window = m_window;
event.from_configure = false;
@@ -389,6 +395,75 @@ static void setMotifWmHints(QXcbConnection *c, xcb_window_t window, const QtMoti
}
}
+void QXcbWindow::printNetWmState(const QVector<xcb_atom_t> &state)
+{
+ printf("_NET_WM_STATE (%d): ", state.size());
+ for (int i = 0; i < state.size(); ++i) {
+#define CHECK_WM_STATE(state_atom) \
+ if (state.at(i) == atom(QXcbAtom::state_atom))\
+ printf(#state_atom " ");
+ CHECK_WM_STATE(_NET_WM_STATE_ABOVE)
+ CHECK_WM_STATE(_NET_WM_STATE_BELOW)
+ CHECK_WM_STATE(_NET_WM_STATE_FULLSCREEN)
+ CHECK_WM_STATE(_NET_WM_STATE_MAXIMIZED_HORZ)
+ CHECK_WM_STATE(_NET_WM_STATE_MAXIMIZED_VERT)
+ CHECK_WM_STATE(_NET_WM_STATE_MODAL)
+ CHECK_WM_STATE(_NET_WM_STATE_STAYS_ON_TOP)
+ CHECK_WM_STATE(_NET_WM_STATE_DEMANDS_ATTENTION)
+#undef CHECK_WM_STATE
+ }
+ printf("\n");
+}
+
+QVector<xcb_atom_t> QXcbWindow::getNetWmState()
+{
+ QVector<xcb_atom_t> result;
+
+ xcb_get_property_cookie_t get_cookie =
+ xcb_get_property(xcb_connection(), 0, m_window, atom(QXcbAtom::_NET_WM_STATE),
+ XCB_ATOM_ATOM, 0, 1024);
+
+ xcb_generic_error_t *error;
+
+ xcb_get_property_reply_t *reply =
+ xcb_get_property_reply(xcb_connection(), get_cookie, &error);
+
+ if (reply && reply->format == 32 && reply->type == XCB_ATOM_ATOM) {
+ result.resize(reply->length);
+
+ memcpy(result.data(), xcb_get_property_value(reply), reply->length * sizeof(xcb_atom_t));
+
+#ifdef NET_WM_STATE_DEBUG
+ printf("getting net wm state (%x)\n", m_window);
+ printNetWmState(result);
+#endif
+
+ free(reply);
+ } else if (error) {
+ connection()->handleXcbError(error);
+ free(error);
+ } else {
+#ifdef NET_WM_STATE_DEBUG
+ printf("getting net wm state (%x), empty\n", m_window);
+#endif
+ }
+
+ return result;
+}
+
+void QXcbWindow::setNetWmState(const QVector<xcb_atom_t> &atoms)
+{
+ if (atoms.isEmpty()) {
+ Q_XCB_CALL(xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_NET_WM_STATE)));
+ } else {
+ Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
+ atom(QXcbAtom::_NET_WM_STATE), XCB_ATOM_ATOM, 32,
+ atoms.count(), atoms.constData()));
+ }
+ xcb_flush(xcb_connection());
+}
+
+
Qt::WindowFlags QXcbWindow::setWindowFlags(Qt::WindowFlags flags)
{
Qt::WindowType type = static_cast<Qt::WindowType>(int(flags & Qt::WindowType_Mask));
@@ -601,7 +676,7 @@ void QXcbWindow::setNetWmWindowTypes(Qt::WindowFlags flags)
windowTypes.count(), windowTypes.constData()));
}
-void QXcbWindow::updateMotifWmHintsBeforeShow()
+void QXcbWindow::updateMotifWmHintsBeforeMap()
{
QtMotifWmHints mwmhints = getMotifWmHints(connection(), m_window);
@@ -657,6 +732,34 @@ void QXcbWindow::updateMotifWmHintsBeforeShow()
setMotifWmHints(connection(), m_window, mwmhints);
}
+void QXcbWindow::updateNetWmStateBeforeMap()
+{
+ QVector<xcb_atom_t> netWmState;
+
+ Qt::WindowFlags flags = window()->windowFlags();
+ if (flags & Qt::WindowStaysOnTopHint) {
+ netWmState.append(atom(QXcbAtom::_NET_WM_STATE_ABOVE));
+ netWmState.append(atom(QXcbAtom::_NET_WM_STATE_STAYS_ON_TOP));
+ } else if (flags & Qt::WindowStaysOnBottomHint) {
+ netWmState.append(atom(QXcbAtom::_NET_WM_STATE_BELOW));
+ }
+
+ if (window()->windowState() & Qt::WindowFullScreen) {
+ netWmState.append(atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN));
+ }
+
+ if (window()->windowState() & Qt::WindowMaximized) {
+ netWmState.append(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ));
+ netWmState.append(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_VERT));
+ }
+
+ if (window()->windowModality() != Qt::NonModal) {
+ netWmState.append(atom(QXcbAtom::_NET_WM_STATE_MODAL));
+ }
+
+ setNetWmState(netWmState);
+}
+
WId QXcbWindow::winId() const
{
return m_window;
diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h
index 9827a808cc..9996188714 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.h
+++ b/src/plugins/platforms/xcb/qxcbwindow.h
@@ -96,8 +96,12 @@ public:
private:
void setNetWmWindowTypes(Qt::WindowFlags flags);
void changeNetWmState(bool set, xcb_atom_t one, xcb_atom_t two = 0);
+ QVector<xcb_atom_t> getNetWmState();
+ void setNetWmState(const QVector<xcb_atom_t> &atoms);
+ void printNetWmState(const QVector<xcb_atom_t> &state);
- void updateMotifWmHintsBeforeShow();
+ void updateMotifWmHintsBeforeMap();
+ void updateNetWmStateBeforeMap();
void show();
void hide();