diff options
-rw-r--r-- | src/plugins/platforms/xcb/qxcbwindow.cpp | 109 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbwindow.h | 6 |
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(); |