diff options
author | Liang Qi <liang.qi@qt.io> | 2018-10-26 10:28:24 +0000 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2018-10-26 10:28:24 +0000 |
commit | 00b2e45a97205975ee91aa43f00e3dbef1a8907b (patch) | |
tree | ed44e50bc893e87434d72470c2c809b1fb34de72 /src/plugins/platforms/xcb/qxcbwindow.cpp | |
parent | 9cd527bc1f384926985d63c741641316a66f17a4 (diff) | |
parent | e28e91ae99b8c3859899e04cc9370534c7c7b86d (diff) |
Merge "Merge remote-tracking branch 'origin/5.12' into dev" into refs/staging/dev
Diffstat (limited to 'src/plugins/platforms/xcb/qxcbwindow.cpp')
-rw-r--r-- | src/plugins/platforms/xcb/qxcbwindow.cpp | 203 |
1 files changed, 45 insertions, 158 deletions
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 69fc6c2951..e56f6b13d8 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -118,8 +118,6 @@ enum { defaultWindowHeight = 160 }; -//#ifdef NET_WM_STATE_DEBUG - QT_BEGIN_NAMESPACE Q_DECLARE_TYPEINFO(xcb_rectangle_t, Q_PRIMITIVE_TYPE); @@ -499,12 +497,10 @@ void QXcbWindow::create() clientMachine.size(), clientMachine.constData()); } + // Create WM_HINTS property on the window, so we can xcb_get_wm_hints*() + // from various setter functions for adjusting the hints. xcb_wm_hints_t hints; memset(&hints, 0, sizeof(hints)); - xcb_wm_hints_set_normal(&hints); - - xcb_wm_hints_set_input(&hints, !(window()->flags() & Qt::WindowDoesNotAcceptFocus)); - xcb_set_wm_hints(xcb_connection(), m_window, &hints); xcb_window_t leader = connection()->clientLeader(); @@ -532,9 +528,6 @@ void QXcbWindow::create() setWindowFlags(window()->flags()); setWindowTitle(window()->title()); - if (window()->flags() & Qt::WindowTransparentForInput) - setTransparentForMouseEvents(true); - #if QT_CONFIG(xcb_xlib) // force sync to read outstanding requests - see QTBUG-29106 XSync(static_cast<Display*>(platformScreen->connection()->xlib_display()), false); @@ -739,20 +732,6 @@ void QXcbWindow::show() { if (window()->isTopLevel()) { - xcb_get_property_cookie_t cookie = xcb_get_wm_hints_unchecked(xcb_connection(), m_window); - - xcb_wm_hints_t hints; - xcb_get_wm_hints_reply(xcb_connection(), cookie, &hints, NULL); - - if (window()->windowStates() & Qt::WindowMinimized) - xcb_wm_hints_set_iconic(&hints); - else - xcb_wm_hints_set_normal(&hints); - - xcb_wm_hints_set_input(&hints, !(window()->flags() & Qt::WindowDoesNotAcceptFocus)); - - xcb_set_wm_hints(xcb_connection(), m_window, &hints); - // update WM_NORMAL_HINTS propagateSizeHints(); @@ -775,9 +754,6 @@ void QXcbWindow::show() if (!transientXcbParent) xcb_delete_property(xcb_connection(), m_window, XCB_ATOM_WM_TRANSIENT_FOR); - // update _MOTIF_WM_HINTS - updateMotifWmHintsBeforeMap(); - // update _NET_WM_STATE updateNetWmStateBeforeMap(); } @@ -928,8 +904,6 @@ void QXcbWindow::doFocusOut() struct QtMotifWmHints { quint32 flags, functions, decorations; - qint32 input_mode; - quint32 status; }; enum { @@ -951,50 +925,8 @@ enum { MWM_DECOR_MENU = (1L << 4), MWM_DECOR_MINIMIZE = (1L << 5), MWM_DECOR_MAXIMIZE = (1L << 6), - - MWM_HINTS_INPUT_MODE = (1L << 2), - - MWM_INPUT_MODELESS = 0L, - MWM_INPUT_PRIMARY_APPLICATION_MODAL = 1L, - MWM_INPUT_FULL_APPLICATION_MODAL = 3L }; -static QtMotifWmHints getMotifWmHints(QXcbConnection *c, xcb_window_t window) -{ - QtMotifWmHints hints; - - auto reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, c->xcb_connection(), 0, window, - c->atom(QXcbAtom::_MOTIF_WM_HINTS), c->atom(QXcbAtom::_MOTIF_WM_HINTS), 0, 20); - - if (reply && reply->format == 32 && reply->type == c->atom(QXcbAtom::_MOTIF_WM_HINTS)) { - hints = *((QtMotifWmHints *)xcb_get_property_value(reply.get())); - } else { - hints.flags = 0L; - hints.functions = MWM_FUNC_ALL; - hints.decorations = MWM_DECOR_ALL; - hints.input_mode = 0L; - hints.status = 0L; - } - - return hints; -} - -static void setMotifWmHints(QXcbConnection *c, xcb_window_t window, const QtMotifWmHints &hints) -{ - if (hints.flags != 0l) { - xcb_change_property(c->xcb_connection(), - XCB_PROP_MODE_REPLACE, - window, - c->atom(QXcbAtom::_MOTIF_WM_HINTS), - c->atom(QXcbAtom::_MOTIF_WM_HINTS), - 32, - 5, - &hints); - } else { - xcb_delete_property(c->xcb_connection(), window, c->atom(QXcbAtom::_MOTIF_WM_HINTS)); - } -} - QXcbWindow::NetWmStates QXcbWindow::netWmStates() { NetWmStates result(0); @@ -1023,9 +955,7 @@ QXcbWindow::NetWmStates QXcbWindow::netWmStates() if (statesEnd != std::find(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_DEMANDS_ATTENTION))) result |= NetWmStateDemandsAttention; } else { -#ifdef NET_WM_STATE_DEBUG - printf("getting net wm state (%x), empty\n", m_window); -#endif + qCDebug(lcQpaXcb, "getting net wm state (%x), empty\n", m_window); } return result; @@ -1098,22 +1028,18 @@ void QXcbWindow::setWindowFlags(Qt::WindowFlags flags) setWmWindowType(wmWindowTypes, flags); setNetWmStateWindowFlags(flags); - setMotifWindowFlags(flags); + setMotifWmHints(flags); setTransparentForMouseEvents(flags & Qt::WindowTransparentForInput); updateDoesNotAcceptFocus(flags & Qt::WindowDoesNotAcceptFocus); } -void QXcbWindow::setMotifWindowFlags(Qt::WindowFlags flags) +void QXcbWindow::setMotifWmHints(Qt::WindowFlags flags) { Qt::WindowType type = static_cast<Qt::WindowType>(int(flags & Qt::WindowType_Mask)); QtMotifWmHints mwmhints; - mwmhints.flags = 0L; - mwmhints.functions = 0L; - mwmhints.decorations = 0; - mwmhints.input_mode = 0L; - mwmhints.status = 0L; + memset(&mwmhints, 0, sizeof(mwmhints)); if (type != Qt::SplashScreen) { mwmhints.flags |= MWM_HINTS_DECORATIONS; @@ -1171,7 +1097,18 @@ void QXcbWindow::setMotifWindowFlags(Qt::WindowFlags flags) mwmhints.decorations = 0; } - setMotifWmHints(connection(), m_window, mwmhints); + if (mwmhints.flags) { + xcb_change_property(xcb_connection(), + XCB_PROP_MODE_REPLACE, + m_window, + atom(QXcbAtom::_MOTIF_WM_HINTS), + atom(QXcbAtom::_MOTIF_WM_HINTS), + 32, + 5, + &mwmhints); + } else { + xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_MOTIF_WM_HINTS)); + } } void QXcbWindow::changeNetWmState(bool set, xcb_atom_t one, xcb_atom_t two) @@ -1230,64 +1167,18 @@ void QXcbWindow::setWindowState(Qt::WindowStates state) changeNetWmState(state & Qt::WindowFullScreen, atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN)); } - connection()->sync(); - m_windowState = state; -} - -void QXcbWindow::updateMotifWmHintsBeforeMap() -{ - QtMotifWmHints mwmhints = getMotifWmHints(connection(), m_window); - - if (window()->modality() != Qt::NonModal) { - switch (window()->modality()) { - case Qt::WindowModal: - mwmhints.input_mode = MWM_INPUT_PRIMARY_APPLICATION_MODAL; - break; - case Qt::ApplicationModal: - default: - mwmhints.input_mode = MWM_INPUT_FULL_APPLICATION_MODAL; - break; - } - mwmhints.flags |= MWM_HINTS_INPUT_MODE; - } else { - mwmhints.input_mode = MWM_INPUT_MODELESS; - mwmhints.flags &= ~MWM_HINTS_INPUT_MODE; - } - - if (windowMinimumSize() == windowMaximumSize()) { - // fixed size, remove the resize handle (since mwm/dtwm - // isn't smart enough to do it itself) - mwmhints.flags |= MWM_HINTS_FUNCTIONS; - if (mwmhints.functions == MWM_FUNC_ALL) { - mwmhints.functions = MWM_FUNC_MOVE; - } else { - mwmhints.functions &= ~MWM_FUNC_RESIZE; - } - - if (mwmhints.decorations == MWM_DECOR_ALL) { - mwmhints.flags |= MWM_HINTS_DECORATIONS; - mwmhints.decorations = (MWM_DECOR_BORDER - | MWM_DECOR_TITLE - | MWM_DECOR_MENU); - } else { - mwmhints.decorations &= ~MWM_DECOR_RESIZEH; - } - } - - if (window()->flags() & Qt::WindowMinimizeButtonHint) { - mwmhints.flags |= MWM_HINTS_DECORATIONS; - mwmhints.decorations |= MWM_DECOR_MINIMIZE; - mwmhints.functions |= MWM_FUNC_MINIMIZE; - } - if (window()->flags() & Qt::WindowMaximizeButtonHint) { - mwmhints.flags |= MWM_HINTS_DECORATIONS; - mwmhints.decorations |= MWM_DECOR_MAXIMIZE; - mwmhints.functions |= MWM_FUNC_MAXIMIZE; + xcb_get_property_cookie_t cookie = xcb_get_wm_hints_unchecked(xcb_connection(), m_window); + xcb_wm_hints_t hints; + if (xcb_get_wm_hints_reply(xcb_connection(), cookie, &hints, nullptr)) { + if (state & Qt::WindowMinimized) + xcb_wm_hints_set_iconic(&hints); + else + xcb_wm_hints_set_normal(&hints); + xcb_set_wm_hints(xcb_connection(), m_window, &hints); } - if (window()->flags() & Qt::WindowCloseButtonHint) - mwmhints.functions |= MWM_FUNC_CLOSE; - setMotifWmHints(connection(), m_window, mwmhints); + connection()->sync(); + m_windowState = state; } void QXcbWindow::updateNetWmStateBeforeMap() @@ -1402,9 +1293,8 @@ void QXcbWindow::updateDoesNotAcceptFocus(bool doesNotAcceptFocus) xcb_get_property_cookie_t cookie = xcb_get_wm_hints_unchecked(xcb_connection(), m_window); xcb_wm_hints_t hints; - if (!xcb_get_wm_hints_reply(xcb_connection(), cookie, &hints, NULL)) { + if (!xcb_get_wm_hints_reply(xcb_connection(), cookie, &hints, nullptr)) return; - } xcb_wm_hints_set_input(&hints, !doesNotAcceptFocus); xcb_set_wm_hints(xcb_connection(), m_window, &hints); @@ -1818,21 +1708,20 @@ void QXcbWindow::handleExposeEvent(const xcb_expose_event_t *event) m_exposeRegion |= rect; bool pending = true; - xcb_generic_event_t *e = nullptr; - do { // compress expose events - e = connection()->checkEvent([this, &pending](xcb_generic_event_t *event, int type) { - if (type != XCB_EXPOSE) - return false; - auto expose = reinterpret_cast<xcb_expose_event_t *>(event); - if (expose->window != m_window) - return false; - if (expose->count == 0) - pending = false; - m_exposeRegion |= QRect(expose->x, expose->y, expose->width, expose->height); - return true; - }); - free(e); - } while (e); + + connection()->eventQueue()->peek(QXcbEventQueue::PeekRemoveMatchContinue, + [this, &pending](xcb_generic_event_t *event, int type) { + if (type != XCB_EXPOSE) + return false; + auto expose = reinterpret_cast<xcb_expose_event_t *>(event); + if (expose->window != m_window) + return false; + if (expose->count == 0) + pending = false; + m_exposeRegion |= QRect(expose->x, expose->y, expose->width, expose->height); + free(expose); + return true; + }); // if count is non-zero there are more expose events pending if (event->count == 0 || !pending) { @@ -2152,13 +2041,11 @@ void QXcbWindow::handleLeaveNotifyEvent(int root_x, int root_y, return; // check if enter event is buffered - auto event = connection()->checkEvent([](xcb_generic_event_t *event, int type) { + auto event = connection()->eventQueue()->peek([](xcb_generic_event_t *event, int type) { if (type != XCB_ENTER_NOTIFY) return false; auto enter = reinterpret_cast<xcb_enter_notify_event_t *>(event); - if (ignoreEnterEvent(enter->mode, enter->detail)) - return false; - return true; + return !ignoreEnterEvent(enter->mode, enter->detail); }); auto enter = reinterpret_cast<xcb_enter_notify_event_t *>(event); QXcbWindow *enterWindow = enter ? connection()->platformWindowFromId(enter->event) : nullptr; |