diff options
Diffstat (limited to 'src/plugins/platforms/xcb/qxcbwindow.cpp')
-rw-r--r-- | src/plugins/platforms/xcb/qxcbwindow.cpp | 565 |
1 files changed, 250 insertions, 315 deletions
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index f6fa903ec2..3d8c6de72f 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -410,6 +410,19 @@ void QXcbWindow::create() qWarning() << "Failed to use requested visual id."; } + if (parent()) { + // When using a Vulkan QWindow via QWidget::createWindowContainer() we + // must make sure the visuals are compatible. Now, the parent will be + // of RasterGLSurface which typically chooses a GLX/EGL compatible + // visual which may not be what the Vulkan window would choose. + // Therefore, take the parent's visual. + if (window()->surfaceType() == QSurface::VulkanSurface + && parent()->window()->surfaceType() != QSurface::VulkanSurface) + { + visual = platformScreen->visualForId(static_cast<QXcbWindow *>(parent())->visualId()); + } + } + if (!visual) visual = createVisual(); @@ -435,11 +448,11 @@ void QXcbWindow::create() if ((window()->supportsOpenGL() && haveOpenGL) || m_format.hasAlpha()) { m_cmap = xcb_generate_id(xcb_connection()); - Q_XCB_CALL(xcb_create_colormap(xcb_connection(), - XCB_COLORMAP_ALLOC_NONE, - m_cmap, - xcb_parent_id, - m_visualId)); + xcb_create_colormap(xcb_connection(), + XCB_COLORMAP_ALLOC_NONE, + m_cmap, + xcb_parent_id, + m_visualId); mask |= XCB_CW_COLORMAP; } @@ -455,23 +468,23 @@ void QXcbWindow::create() }; m_window = xcb_generate_id(xcb_connection()); - Q_XCB_CALL(xcb_create_window(xcb_connection(), - m_depth, - m_window, // window id - xcb_parent_id, // parent window id - rect.x(), - rect.y(), - rect.width(), - rect.height(), - 0, // border width - XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class - m_visualId, // visual - mask, - values)); + xcb_create_window(xcb_connection(), + m_depth, + m_window, // window id + xcb_parent_id, // parent window id + rect.x(), + rect.y(), + rect.width(), + rect.height(), + 0, // border width + XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class + m_visualId, // visual + mask, + values); connection()->addWindowEventListener(m_window, this); - Q_XCB_CALL(xcb_change_window_attributes(xcb_connection(), m_window, mask, values)); + xcb_change_window_attributes(xcb_connection(), m_window, mask, values); propagateSizeHints(); @@ -489,43 +502,43 @@ void QXcbWindow::create() if (window()->flags() & Qt::WindowContextHelpButtonHint) properties[propertyCount++] = atom(QXcbAtom::_NET_WM_CONTEXT_HELP); - Q_XCB_CALL(xcb_change_property(xcb_connection(), - XCB_PROP_MODE_REPLACE, - m_window, - atom(QXcbAtom::WM_PROTOCOLS), - XCB_ATOM_ATOM, - 32, - propertyCount, - properties)); + xcb_change_property(xcb_connection(), + XCB_PROP_MODE_REPLACE, + m_window, + atom(QXcbAtom::WM_PROTOCOLS), + XCB_ATOM_ATOM, + 32, + propertyCount, + properties); m_syncValue.hi = 0; m_syncValue.lo = 0; const QByteArray wmClass = QXcbIntegration::instance()->wmClass(); if (!wmClass.isEmpty()) { - Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, - m_window, atom(QXcbAtom::WM_CLASS), - XCB_ATOM_STRING, 8, wmClass.size(), wmClass.constData())); + xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, + m_window, atom(QXcbAtom::WM_CLASS), + XCB_ATOM_STRING, 8, wmClass.size(), wmClass.constData()); } if (m_usingSyncProtocol) { m_syncCounter = xcb_generate_id(xcb_connection()); - Q_XCB_CALL(xcb_sync_create_counter(xcb_connection(), m_syncCounter, m_syncValue)); + xcb_sync_create_counter(xcb_connection(), m_syncCounter, m_syncValue); - Q_XCB_CALL(xcb_change_property(xcb_connection(), - XCB_PROP_MODE_REPLACE, - m_window, - atom(QXcbAtom::_NET_WM_SYNC_REQUEST_COUNTER), - XCB_ATOM_CARDINAL, - 32, - 1, - &m_syncCounter)); + xcb_change_property(xcb_connection(), + XCB_PROP_MODE_REPLACE, + m_window, + atom(QXcbAtom::_NET_WM_SYNC_REQUEST_COUNTER), + XCB_ATOM_CARDINAL, + 32, + 1, + &m_syncCounter); } // set the PID to let the WM kill the application if unresponsive quint32 pid = getpid(); - Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, - atom(QXcbAtom::_NET_WM_PID), XCB_ATOM_CARDINAL, 32, - 1, &pid)); + xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, + atom(QXcbAtom::_NET_WM_PID), XCB_ATOM_CARDINAL, 32, + 1, &pid); xcb_wm_hints_t hints; memset(&hints, 0, sizeof(hints)); @@ -536,23 +549,23 @@ void QXcbWindow::create() xcb_set_wm_hints(xcb_connection(), m_window, &hints); xcb_window_t leader = connection()->clientLeader(); - Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, - atom(QXcbAtom::WM_CLIENT_LEADER), XCB_ATOM_WINDOW, 32, - 1, &leader)); + xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, + atom(QXcbAtom::WM_CLIENT_LEADER), XCB_ATOM_WINDOW, 32, + 1, &leader); /* Add XEMBED info; this operation doesn't initiate the embedding. */ quint32 data[] = { XEMBED_VERSION, XEMBED_MAPPED }; - Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, - atom(QXcbAtom::_XEMBED_INFO), - atom(QXcbAtom::_XEMBED_INFO), - 32, 2, (void *)data)); + xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, + atom(QXcbAtom::_XEMBED_INFO), + atom(QXcbAtom::_XEMBED_INFO), + 32, 2, (void *)data); #if defined(XCB_USE_XINPUT2) connection()->xi2Select(m_window); #endif - setWindowState(window()->windowState()); + setWindowState(window()->windowStates()); setWindowFlags(window()->flags()); setWindowTitle(window()->title()); @@ -604,7 +617,7 @@ void QXcbWindow::destroy() connection()->setMouseGrabber(Q_NULLPTR); if (m_syncCounter && m_usingSyncProtocol) - Q_XCB_CALL(xcb_sync_destroy_counter(xcb_connection(), m_syncCounter)); + xcb_sync_destroy_counter(xcb_connection(), m_syncCounter); if (m_window) { if (m_netWmUserTimeWindow) { xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_NET_WM_USER_TIME_WINDOW)); @@ -615,7 +628,7 @@ void QXcbWindow::destroy() m_netWmUserTimeWindow = XCB_NONE; } connection()->removeWindowEventListener(m_window); - Q_XCB_CALL(xcb_destroy_window(xcb_connection(), m_window)); + xcb_destroy_window(xcb_connection(), m_window); m_window = 0; } if (m_cmap) { @@ -650,7 +663,7 @@ void QXcbWindow::setGeometry(const QRect &rect) qBound<qint32>(1, wmGeometry.width(), XCOORD_MAX), qBound<qint32>(1, wmGeometry.height(), XCOORD_MAX), }; - Q_XCB_CALL(xcb_configure_window(xcb_connection(), m_window, mask, reinterpret_cast<const quint32*>(values))); + xcb_configure_window(xcb_connection(), m_window, mask, reinterpret_cast<const quint32*>(values)); } else { const quint32 mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT; const qint32 values[] = { @@ -659,7 +672,7 @@ void QXcbWindow::setGeometry(const QRect &rect) qBound<qint32>(1, wmGeometry.width(), XCOORD_MAX), qBound<qint32>(1, wmGeometry.height(), XCOORD_MAX), }; - Q_XCB_CALL(xcb_configure_window(xcb_connection(), m_window, mask, reinterpret_cast<const quint32*>(values))); + xcb_configure_window(xcb_connection(), m_window, mask, reinterpret_cast<const quint32*>(values)); } xcb_flush(xcb_connection()); @@ -669,12 +682,10 @@ QMargins QXcbWindow::frameMargins() const { if (m_dirtyFrameMargins) { if (connection()->wmSupport()->isSupportedByWM(atom(QXcbAtom::_NET_FRAME_EXTENTS))) { - xcb_get_property_cookie_t cookie = xcb_get_property(xcb_connection(), false, m_window, - atom(QXcbAtom::_NET_FRAME_EXTENTS), XCB_ATOM_CARDINAL, 0, 4); - QScopedPointer<xcb_get_property_reply_t, QScopedPointerPodDeleter> reply( - xcb_get_property_reply(xcb_connection(), cookie, NULL)); + auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(), false, m_window, + atom(QXcbAtom::_NET_FRAME_EXTENTS), XCB_ATOM_CARDINAL, 0, 4); if (reply && reply->type == XCB_ATOM_CARDINAL && reply->format == 32 && reply->value_len == 4) { - quint32 *data = (quint32 *)xcb_get_property_value(reply.data()); + quint32 *data = (quint32 *)xcb_get_property_value(reply.get()); // _NET_FRAME_EXTENTS format is left, right, top, bottom m_frameMargins = QMargins(data[0], data[2], data[1], data[3]); m_dirtyFrameMargins = false; @@ -693,9 +704,7 @@ QMargins QXcbWindow::frameMargins() const connection()->wmSupport()->virtualRoots(); while (!foundRoot) { - xcb_query_tree_cookie_t cookie = xcb_query_tree_unchecked(xcb_connection(), parent); - - xcb_query_tree_reply_t *reply = xcb_query_tree_reply(xcb_connection(), cookie, NULL); + auto reply = Q_XCB_REPLY_UNCHECKED(xcb_query_tree, xcb_connection(), parent); if (reply) { if (reply->root == reply->parent || virtualRoots.indexOf(reply->parent) != -1 || reply->parent == XCB_WINDOW_NONE) { foundRoot = true; @@ -703,8 +712,6 @@ QMargins QXcbWindow::frameMargins() const window = parent; parent = reply->parent; } - - free(reply); } else { m_dirtyFrameMargins = false; m_frameMargins = QMargins(); @@ -714,23 +721,12 @@ QMargins QXcbWindow::frameMargins() const QPoint offset; - xcb_translate_coordinates_reply_t *reply = - xcb_translate_coordinates_reply( - xcb_connection(), - xcb_translate_coordinates(xcb_connection(), window, parent, 0, 0), - NULL); - + auto reply = Q_XCB_REPLY(xcb_translate_coordinates, xcb_connection(), window, parent, 0, 0); if (reply) { offset = QPoint(reply->dst_x, reply->dst_y); - free(reply); } - xcb_get_geometry_reply_t *geom = - xcb_get_geometry_reply( - xcb_connection(), - xcb_get_geometry(xcb_connection(), parent), - NULL); - + auto geom = Q_XCB_REPLY(xcb_get_geometry, xcb_connection(), parent); if (geom) { // -- // add the border_width for the window managers frame... some window managers @@ -747,8 +743,6 @@ QMargins QXcbWindow::frameMargins() const int bottom = geom->height + geom->border_width - geometry().height() - offset.y(); m_frameMargins = QMargins(left, top, right, bottom); - - free(geom); } m_dirtyFrameMargins = false; @@ -775,12 +769,13 @@ static inline bool testShowWithoutActivating(const QWindow *window) 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()->windowState() & Qt::WindowMinimized) + if (window()->windowStates() & Qt::WindowMinimized) xcb_wm_hints_set_iconic(&hints); else xcb_wm_hints_set_normal(&hints); @@ -806,13 +801,13 @@ void QXcbWindow::show() if (!transientXcbParent) transientXcbParent = connection()->clientLeader(); if (transientXcbParent) { // ICCCM 4.1.2.6 - Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, - XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, 32, - 1, &transientXcbParent)); + xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, + XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, 32, + 1, &transientXcbParent); } } if (!transientXcbParent) - Q_XCB_CALL(xcb_delete_property(xcb_connection(), m_window, XCB_ATOM_WM_TRANSIENT_FOR)); + xcb_delete_property(xcb_connection(), m_window, XCB_ATOM_WM_TRANSIENT_FOR); // update _MOTIF_WM_HINTS updateMotifWmHintsBeforeMap(); @@ -829,7 +824,7 @@ void QXcbWindow::show() if (window()->objectName() == QLatin1String("QSystemTrayIconSysWindow")) return; // defer showing until XEMBED_EMBEDDED_NOTIFY - Q_XCB_CALL(xcb_map_window(xcb_connection(), m_window)); + xcb_map_window(xcb_connection(), m_window); if (QGuiApplication::modalWindow() == window()) requestActivateWindow(); @@ -841,7 +836,7 @@ void QXcbWindow::show() void QXcbWindow::hide() { - Q_XCB_CALL(xcb_unmap_window(xcb_connection(), m_window)); + xcb_unmap_window(xcb_connection(), m_window); // send synthetic UnmapNotify event according to icccm 4.1.4 Q_DECLARE_XCB_EVENT(event, xcb_unmap_notify_event_t); @@ -849,8 +844,8 @@ void QXcbWindow::hide() event.event = xcbScreen()->root(); event.window = m_window; event.from_configure = false; - Q_XCB_CALL(xcb_send_event(xcb_connection(), false, xcbScreen()->root(), - XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event)); + xcb_send_event(xcb_connection(), false, xcbScreen()->root(), + XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event); xcb_flush(xcb_connection()); @@ -1000,15 +995,11 @@ static QtMotifWmHints getMotifWmHints(QXcbConnection *c, xcb_window_t window) { QtMotifWmHints hints; - xcb_get_property_cookie_t get_cookie = - xcb_get_property_unchecked(c->xcb_connection(), 0, window, c->atom(QXcbAtom::_MOTIF_WM_HINTS), - c->atom(QXcbAtom::_MOTIF_WM_HINTS), 0, 20); - - xcb_get_property_reply_t *reply = - xcb_get_property_reply(c->xcb_connection(), get_cookie, NULL); + 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)); + hints = *((QtMotifWmHints *)xcb_get_property_value(reply.get())); } else { hints.flags = 0L; hints.functions = MWM_FUNC_ALL; @@ -1017,24 +1008,22 @@ static QtMotifWmHints getMotifWmHints(QXcbConnection *c, xcb_window_t window) hints.status = 0L; } - free(reply); - return hints; } static void setMotifWmHints(QXcbConnection *c, xcb_window_t window, const QtMotifWmHints &hints) { if (hints.flags != 0l) { - Q_XCB_CALL2(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), c); + 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 { - Q_XCB_CALL2(xcb_delete_property(c->xcb_connection(), window, c->atom(QXcbAtom::_MOTIF_WM_HINTS)), c); + xcb_delete_property(c->xcb_connection(), window, c->atom(QXcbAtom::_MOTIF_WM_HINTS)); } } @@ -1042,15 +1031,12 @@ QXcbWindow::NetWmStates QXcbWindow::netWmStates() { NetWmStates result(0); - xcb_get_property_cookie_t get_cookie = - xcb_get_property_unchecked(xcb_connection(), 0, m_window, atom(QXcbAtom::_NET_WM_STATE), - XCB_ATOM_ATOM, 0, 1024); - - xcb_get_property_reply_t *reply = - xcb_get_property_reply(xcb_connection(), get_cookie, NULL); + auto reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, xcb_connection(), + 0, m_window, atom(QXcbAtom::_NET_WM_STATE), + XCB_ATOM_ATOM, 0, 1024); if (reply && reply->format == 32 && reply->type == XCB_ATOM_ATOM) { - const xcb_atom_t *states = static_cast<const xcb_atom_t *>(xcb_get_property_value(reply)); + const xcb_atom_t *states = static_cast<const xcb_atom_t *>(xcb_get_property_value(reply.get())); const xcb_atom_t *statesEnd = states + reply->length; if (statesEnd != std::find(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_ABOVE))) result |= NetWmStateAbove; @@ -1068,7 +1054,6 @@ QXcbWindow::NetWmStates QXcbWindow::netWmStates() result |= NetWmStateStaysOnTop; if (statesEnd != std::find(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_DEMANDS_ATTENTION))) result |= NetWmStateDemandsAttention; - free(reply); } else { #ifdef NET_WM_STATE_DEBUG printf("getting net wm state (%x), empty\n", m_window); @@ -1082,21 +1067,15 @@ void QXcbWindow::setNetWmStates(NetWmStates states) { QVector<xcb_atom_t> atoms; - xcb_get_property_cookie_t get_cookie = - xcb_get_property_unchecked(xcb_connection(), 0, m_window, atom(QXcbAtom::_NET_WM_STATE), - XCB_ATOM_ATOM, 0, 1024); - - xcb_get_property_reply_t *reply = - xcb_get_property_reply(xcb_connection(), get_cookie, NULL); - + auto reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, xcb_connection(), + 0, m_window, atom(QXcbAtom::_NET_WM_STATE), + XCB_ATOM_ATOM, 0, 1024); if (reply && reply->format == 32 && reply->type == XCB_ATOM_ATOM && reply->value_len > 0) { - const xcb_atom_t *data = static_cast<const xcb_atom_t *>(xcb_get_property_value(reply)); + const xcb_atom_t *data = static_cast<const xcb_atom_t *>(xcb_get_property_value(reply.get())); atoms.resize(reply->value_len); memcpy((void *)&atoms.first(), (void *)data, reply->value_len * sizeof(xcb_atom_t)); } - free(reply); - if (states & NetWmStateAbove && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_ABOVE))) atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_ABOVE)); if (states & NetWmStateBelow && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_BELOW))) @@ -1115,11 +1094,11 @@ void QXcbWindow::setNetWmStates(NetWmStates states) atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_DEMANDS_ATTENTION)); if (atoms.isEmpty()) { - Q_XCB_CALL(xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_NET_WM_STATE))); + 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_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()); } @@ -1242,67 +1221,48 @@ void QXcbWindow::changeNetWmState(bool set, xcb_atom_t one, xcb_atom_t two) event.data.data32[3] = 0; event.data.data32[4] = 0; - Q_XCB_CALL(xcb_send_event(xcb_connection(), 0, xcbScreen()->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event)); + xcb_send_event(xcb_connection(), 0, xcbScreen()->root(), + XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, + (const char *)&event); } -void QXcbWindow::setWindowState(Qt::WindowState state) +void QXcbWindow::setWindowState(Qt::WindowStates state) { if (state == m_windowState) return; - // 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; + if ((m_windowState & Qt::WindowMinimized) && !(state & Qt::WindowMinimized)) { + xcb_map_window(xcb_connection(), m_window); + } else if (!(m_windowState & Qt::WindowMinimized) && (state & Qt::WindowMinimized)) { + xcb_client_message_event_t event; + + event.response_type = XCB_CLIENT_MESSAGE; + event.format = 32; + event.sequence = 0; + 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; + + xcb_send_event(xcb_connection(), 0, xcbScreen()->root(), + XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, + (const char *)&event); + m_minimized = true; } - // set new state - switch (state) { - case Qt::WindowMinimized: - { - xcb_client_message_event_t event; - - event.response_type = XCB_CLIENT_MESSAGE; - event.format = 32; - event.sequence = 0; - 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, xcbScreen()->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), + if ((m_windowState ^ state) & Qt::WindowMaximized) { + changeNetWmState(state & Qt::WindowMaximized, 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(); + if ((m_windowState ^ state) & Qt::WindowFullScreen) { + changeNetWmState(state & Qt::WindowFullScreen, atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN)); + } + connection()->sync(); m_windowState = state; } @@ -1374,10 +1334,10 @@ void QXcbWindow::updateNetWmStateBeforeMap() states |= NetWmStateBelow; } - if (window()->windowState() & Qt::WindowFullScreen) + if (window()->windowStates() & Qt::WindowFullScreen) states |= NetWmStateFullScreen; - if (window()->windowState() & Qt::WindowMaximized) { + if (window()->windowStates() & Qt::WindowMaximized) { states |= NetWmStateMaximizedHorz; states |= NetWmStateMaximizedVert; } @@ -1410,30 +1370,30 @@ void QXcbWindow::updateNetWmUserTime(xcb_timestamp_t timestamp) if (m_netWmUserTimeWindow || isSupportedByWM) { if (!m_netWmUserTimeWindow) { m_netWmUserTimeWindow = xcb_generate_id(xcb_connection()); - Q_XCB_CALL(xcb_create_window(xcb_connection(), - XCB_COPY_FROM_PARENT, // depth -- same as root - m_netWmUserTimeWindow, // window id - m_window, // parent window id - -1, -1, 1, 1, - 0, // border width - XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class - m_visualId, // visual - 0, // value mask - 0)); // value list + xcb_create_window(xcb_connection(), + XCB_COPY_FROM_PARENT, // depth -- same as root + m_netWmUserTimeWindow, // window id + m_window, // parent window id + -1, -1, 1, 1, + 0, // border width + XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class + m_visualId, // visual + 0, // value mask + 0); // value list wid = m_netWmUserTimeWindow; xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, atom(QXcbAtom::_NET_WM_USER_TIME_WINDOW), XCB_ATOM_WINDOW, 32, 1, &m_netWmUserTimeWindow); xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_NET_WM_USER_TIME)); #ifndef QT_NO_DEBUG QByteArray ba("Qt NET_WM user time window"); - Q_XCB_CALL(xcb_change_property(xcb_connection(), - XCB_PROP_MODE_REPLACE, - m_netWmUserTimeWindow, - atom(QXcbAtom::_NET_WM_NAME), - atom(QXcbAtom::UTF8_STRING), - 8, - ba.length(), - ba.constData())); + xcb_change_property(xcb_connection(), + XCB_PROP_MODE_REPLACE, + m_netWmUserTimeWindow, + atom(QXcbAtom::_NET_WM_NAME), + atom(QXcbAtom::UTF8_STRING), + 8, + ba.length(), + ba.constData()); #endif } else if (!isSupportedByWM) { // WM no longer supports it, then we should remove the @@ -1507,21 +1467,21 @@ void QXcbWindow::setParent(const QPlatformWindow *parent) xcb_parent_id = xcbScreen()->root(); m_embedded = false; } - Q_XCB_CALL(xcb_reparent_window(xcb_connection(), xcb_window(), xcb_parent_id, topLeft.x(), topLeft.y())); + xcb_reparent_window(xcb_connection(), xcb_window(), xcb_parent_id, topLeft.x(), topLeft.y()); } void QXcbWindow::setWindowTitle(const QString &title) { const QString fullTitle = formatWindowTitle(title, QString::fromUtf8(" \xe2\x80\x94 ")); // unicode character U+2014, EM DASH const QByteArray ba = fullTitle.toUtf8(); - Q_XCB_CALL(xcb_change_property(xcb_connection(), + xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, atom(QXcbAtom::_NET_WM_NAME), atom(QXcbAtom::UTF8_STRING), 8, ba.length(), - ba.constData())); + ba.constData()); #ifdef XCB_USE_XLIB XTextProperty *text = qstringToXTP(DISPLAY_FROM_XCB(this), title); @@ -1534,14 +1494,14 @@ void QXcbWindow::setWindowTitle(const QString &title) void QXcbWindow::setWindowIconText(const QString &title) { const QByteArray ba = title.toUtf8(); - Q_XCB_CALL(xcb_change_property(xcb_connection(), - XCB_PROP_MODE_REPLACE, - m_window, - atom(QXcbAtom::_NET_WM_ICON_NAME), - atom(QXcbAtom::UTF8_STRING), - 8, - ba.length(), - ba.constData())); + xcb_change_property(xcb_connection(), + XCB_PROP_MODE_REPLACE, + m_window, + atom(QXcbAtom::_NET_WM_ICON_NAME), + atom(QXcbAtom::UTF8_STRING), + 8, + ba.length(), + ba.constData()); } void QXcbWindow::setWindowIcon(const QIcon &icon) @@ -1571,18 +1531,18 @@ void QXcbWindow::setWindowIcon(const QIcon &icon) } if (!icon_data.isEmpty()) { - Q_XCB_CALL(xcb_change_property(xcb_connection(), - XCB_PROP_MODE_REPLACE, - m_window, - atom(QXcbAtom::_NET_WM_ICON), - atom(QXcbAtom::CARDINAL), - 32, - icon_data.size(), - (unsigned char *) icon_data.data())); + xcb_change_property(xcb_connection(), + XCB_PROP_MODE_REPLACE, + m_window, + atom(QXcbAtom::_NET_WM_ICON), + atom(QXcbAtom::CARDINAL), + 32, + icon_data.size(), + (unsigned char *) icon_data.data()); } else { - Q_XCB_CALL(xcb_delete_property(xcb_connection(), - m_window, - atom(QXcbAtom::_NET_WM_ICON))); + xcb_delete_property(xcb_connection(), + m_window, + atom(QXcbAtom::_NET_WM_ICON)); } } @@ -1590,14 +1550,14 @@ void QXcbWindow::raise() { const quint32 mask = XCB_CONFIG_WINDOW_STACK_MODE; const quint32 values[] = { XCB_STACK_MODE_ABOVE }; - Q_XCB_CALL(xcb_configure_window(xcb_connection(), m_window, mask, values)); + xcb_configure_window(xcb_connection(), m_window, mask, values); } void QXcbWindow::lower() { const quint32 mask = XCB_CONFIG_WINDOW_STACK_MODE; const quint32 values[] = { XCB_STACK_MODE_BELOW }; - Q_XCB_CALL(xcb_configure_window(xcb_connection(), m_window, mask, values)); + xcb_configure_window(xcb_connection(), m_window, mask, values); } // Adapt the geometry to match the WM expection with regards @@ -1691,9 +1651,11 @@ void QXcbWindow::requestActivateWindow() event.data.data32[3] = 0; event.data.data32[4] = 0; - Q_XCB_CALL(xcb_send_event(xcb_connection(), 0, xcbScreen()->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event)); + xcb_send_event(xcb_connection(), 0, xcbScreen()->root(), + XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, + (const char *)&event); } else { - Q_XCB_CALL(xcb_set_input_focus(xcb_connection(), XCB_INPUT_FOCUS_PARENT, m_window, connection()->time())); + xcb_set_input_focus(xcb_connection(), XCB_INPUT_FOCUS_PARENT, m_window, connection()->time()); } connection()->sync(); @@ -1737,15 +1699,11 @@ QXcbWindowFunctions::WmWindowTypes QXcbWindow::wmWindowTypes() const { QXcbWindowFunctions::WmWindowTypes result(0); - xcb_get_property_cookie_t get_cookie = - xcb_get_property_unchecked(xcb_connection(), 0, m_window, atom(QXcbAtom::_NET_WM_WINDOW_TYPE), - XCB_ATOM_ATOM, 0, 1024); - - xcb_get_property_reply_t *reply = - xcb_get_property_reply(xcb_connection(), get_cookie, NULL); - + auto reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, xcb_connection(), + 0, m_window, atom(QXcbAtom::_NET_WM_WINDOW_TYPE), + XCB_ATOM_ATOM, 0, 1024); if (reply && reply->format == 32 && reply->type == XCB_ATOM_ATOM) { - const xcb_atom_t *types = static_cast<const xcb_atom_t *>(xcb_get_property_value(reply)); + const xcb_atom_t *types = static_cast<const xcb_atom_t *>(xcb_get_property_value(reply.get())); const xcb_atom_t *types_end = types + reply->length; for (; types != types_end; types++) { QXcbAtom::Atom type = connection()->qatom(*types); @@ -1799,7 +1757,6 @@ QXcbWindowFunctions::WmWindowTypes QXcbWindow::wmWindowTypes() const break; } } - free(reply); } return result; } @@ -1882,20 +1839,20 @@ void QXcbWindow::setWmWindowType(QXcbWindowFunctions::WmWindowTypes types, Qt::W atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_NORMAL)); if (atoms.isEmpty()) { - Q_XCB_CALL(xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_NET_WM_WINDOW_TYPE))); + xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_NET_WM_WINDOW_TYPE)); } else { - Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, - atom(QXcbAtom::_NET_WM_WINDOW_TYPE), XCB_ATOM_ATOM, 32, - atoms.count(), atoms.constData())); + xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, + atom(QXcbAtom::_NET_WM_WINDOW_TYPE), XCB_ATOM_ATOM, 32, + atoms.count(), atoms.constData()); } xcb_flush(xcb_connection()); } void QXcbWindow::setWmWindowRole(const QByteArray &role) { - Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, - atom(QXcbAtom::WM_WINDOW_ROLE), XCB_ATOM_STRING, 8, - role.size(), role.constData())); + xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, + atom(QXcbAtom::WM_WINDOW_ROLE), XCB_ATOM_STRING, 8, + role.size(), role.constData()); } void QXcbWindow::setParentRelativeBackPixmapStatic(QWindow *window) @@ -1908,7 +1865,7 @@ void QXcbWindow::setParentRelativeBackPixmap() { const quint32 mask = XCB_CW_BACK_PIXMAP; const quint32 values[] = { XCB_BACK_PIXMAP_PARENT_RELATIVE }; - Q_XCB_CALL(xcb_change_window_attributes(xcb_connection(), m_window, mask, values)); + xcb_change_window_attributes(xcb_connection(), m_window, mask, values); } bool QXcbWindow::requestSystemTrayWindowDockStatic(const QWindow *window) @@ -2085,13 +2042,11 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t * QPoint pos(event->x, event->y); if (!parent() && !fromSendEvent) { // Do not trust the position, query it instead. - xcb_translate_coordinates_cookie_t cookie = xcb_translate_coordinates(xcb_connection(), xcb_window(), - xcbScreen()->root(), 0, 0); - xcb_translate_coordinates_reply_t *reply = xcb_translate_coordinates_reply(xcb_connection(), cookie, NULL); + auto reply = Q_XCB_REPLY(xcb_translate_coordinates, xcb_connection(), + xcb_window(), xcbScreen()->root(), 0, 0); if (reply) { pos.setX(reply->dst_x); pos.setY(reply->dst_y); - free(reply); } } @@ -2146,15 +2101,12 @@ QPoint QXcbWindow::mapToGlobal(const QPoint &pos) const return pos; QPoint ret; - xcb_translate_coordinates_cookie_t cookie = - xcb_translate_coordinates(xcb_connection(), xcb_window(), xcbScreen()->root(), - pos.x(), pos.y()); - xcb_translate_coordinates_reply_t *reply = - xcb_translate_coordinates_reply(xcb_connection(), cookie, NULL); + auto reply = Q_XCB_REPLY(xcb_translate_coordinates, xcb_connection(), + xcb_window(), xcbScreen()->root(), + pos.x(), pos.y()); if (reply) { ret.setX(reply->dst_x); ret.setY(reply->dst_y); - free(reply); } return ret; @@ -2166,15 +2118,12 @@ QPoint QXcbWindow::mapFromGlobal(const QPoint &pos) const return pos; QPoint ret; - xcb_translate_coordinates_cookie_t cookie = - xcb_translate_coordinates(xcb_connection(), xcbScreen()->root(), xcb_window(), - pos.x(), pos.y()); - xcb_translate_coordinates_reply_t *reply = - xcb_translate_coordinates_reply(xcb_connection(), cookie, NULL); + auto reply = Q_XCB_REPLY(xcb_translate_coordinates, xcb_connection(), + xcbScreen()->root(), xcb_window(), + pos.x(), pos.y()); if (reply) { ret.setX(reply->dst_x); ret.setY(reply->dst_y); - free(reply); } return ret; @@ -2525,44 +2474,33 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev if (propertyDeleted) return; - Qt::WindowState newState = Qt::WindowNoState; - if (event->atom == atom(QXcbAtom::WM_STATE)) { // WM_STATE: Quick check for 'Minimize'. - const xcb_get_property_cookie_t get_cookie = - xcb_get_property(xcb_connection(), 0, m_window, atom(QXcbAtom::WM_STATE), - XCB_ATOM_ANY, 0, 1024); - - xcb_get_property_reply_t *reply = - xcb_get_property_reply(xcb_connection(), get_cookie, NULL); + Qt::WindowStates newState = Qt::WindowNoState; + if (event->atom == atom(QXcbAtom::WM_STATE)) { // WM_STATE: Quick check for 'Minimize'. + auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(), + 0, m_window, atom(QXcbAtom::WM_STATE), + XCB_ATOM_ANY, 0, 1024); if (reply && reply->format == 32 && reply->type == atom(QXcbAtom::WM_STATE)) { - const quint32 *data = (const quint32 *)xcb_get_property_value(reply); - if (reply->length != 0) { - if (data[0] == XCB_WM_STATE_ICONIC - || (data[0] == XCB_WM_STATE_WITHDRAWN - && m_lastWindowStateEvent == Qt::WindowMinimized)) { - newState = Qt::WindowMinimized; - } - } + const quint32 *data = (const quint32 *)xcb_get_property_value(reply.get()); + if (reply->length != 0) + m_minimized = (data[0] == XCB_WM_STATE_ICONIC + || (data[0] == XCB_WM_STATE_WITHDRAWN && m_minimized)); } - free(reply); - } else { // _NET_WM_STATE can't change minimized state - if (m_lastWindowStateEvent == Qt::WindowMinimized) - newState = Qt::WindowMinimized; - } - - if (newState != Qt::WindowMinimized) { // Something else changed, get _NET_WM_STATE. - const NetWmStates states = netWmStates(); - if (states & NetWmStateFullScreen) - newState = Qt::WindowFullScreen; - else if ((states & NetWmStateMaximizedHorz) && (states & NetWmStateMaximizedVert)) - newState = Qt::WindowMaximized; } + if (m_minimized) + newState = Qt::WindowMinimized; + + const NetWmStates states = netWmStates(); + if (states & NetWmStateFullScreen) + newState |= Qt::WindowFullScreen; + if ((states & NetWmStateMaximizedHorz) && (states & NetWmStateMaximizedVert)) + newState |= Qt::WindowMaximized; // Send Window state, compress events in case other flags (modality, etc) are changed. if (m_lastWindowStateEvent != newState) { QWindowSystemInterface::handleWindowStateChanged(window(), newState); m_lastWindowStateEvent = newState; m_windowState = newState; - if (m_windowState == Qt::WindowMinimized && connection()->mouseGrabber() == this) + if ((m_windowState & Qt::WindowMinimized) && connection()->mouseGrabber() == this) connection()->setMouseGrabber(Q_NULLPTR); } return; @@ -2597,7 +2535,7 @@ void QXcbWindow::updateSyncRequestCounter() return; } if (m_usingSyncProtocol && (m_syncValue.lo != 0 || m_syncValue.hi != 0)) { - Q_XCB_CALL(xcb_sync_set_counter(xcb_connection(), m_syncCounter, m_syncValue)); + xcb_sync_set_counter(xcb_connection(), m_syncCounter, m_syncValue); xcb_flush(xcb_connection()); m_syncValue.lo = 0; @@ -2621,13 +2559,11 @@ bool QXcbWindow::setKeyboardGrabEnabled(bool grab) xcb_ungrab_keyboard(xcb_connection(), XCB_TIME_CURRENT_TIME); return true; } - xcb_grab_keyboard_cookie_t cookie = xcb_grab_keyboard(xcb_connection(), false, - m_window, XCB_TIME_CURRENT_TIME, - XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC); - xcb_grab_keyboard_reply_t *reply = xcb_grab_keyboard_reply(xcb_connection(), cookie, NULL); - bool result = !(!reply || reply->status != XCB_GRAB_STATUS_SUCCESS); - free(reply); - return result; + + auto reply = Q_XCB_REPLY(xcb_grab_keyboard, xcb_connection(), false, + m_window, XCB_TIME_CURRENT_TIME, + XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC); + return reply && reply->status == XCB_GRAB_STATUS_SUCCESS; } bool QXcbWindow::setMouseGrabEnabled(bool grab) @@ -2649,16 +2585,16 @@ bool QXcbWindow::setMouseGrabEnabled(bool grab) xcb_ungrab_pointer(xcb_connection(), XCB_TIME_CURRENT_TIME); return true; } - xcb_grab_pointer_cookie_t cookie = xcb_grab_pointer(xcb_connection(), false, m_window, - (XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE - | XCB_EVENT_MASK_BUTTON_MOTION | XCB_EVENT_MASK_ENTER_WINDOW - | XCB_EVENT_MASK_LEAVE_WINDOW | XCB_EVENT_MASK_POINTER_MOTION), - XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, - XCB_WINDOW_NONE, XCB_CURSOR_NONE, - XCB_TIME_CURRENT_TIME); - xcb_grab_pointer_reply_t *reply = xcb_grab_pointer_reply(xcb_connection(), cookie, NULL); - bool result = !(!reply || reply->status != XCB_GRAB_STATUS_SUCCESS); - free(reply); + + auto reply = Q_XCB_REPLY(xcb_grab_pointer, xcb_connection(), + false, m_window, + (XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE + | XCB_EVENT_MASK_BUTTON_MOTION | XCB_EVENT_MASK_ENTER_WINDOW + | XCB_EVENT_MASK_LEAVE_WINDOW | XCB_EVENT_MASK_POINTER_MOTION), + XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, + XCB_WINDOW_NONE, XCB_CURSOR_NONE, + XCB_TIME_CURRENT_TIME); + bool result = reply && reply->status == XCB_GRAB_STATUS_SUCCESS; if (result) connection()->setMouseGrabber(this); return result; @@ -2766,8 +2702,7 @@ void QXcbWindow::sendXEmbedMessage(xcb_window_t window, quint32 message, event.data.data32[2] = detail; event.data.data32[3] = data1; event.data.data32[4] = data2; - Q_XCB_CALL(xcb_send_event(xcb_connection(), false, window, - XCB_EVENT_MASK_NO_EVENT, (const char *)&event)); + xcb_send_event(xcb_connection(), false, window, XCB_EVENT_MASK_NO_EVENT, (const char *)&event); } static bool activeWindowChangeQueued(const QWindow *window) @@ -2789,12 +2724,12 @@ void QXcbWindow::handleXEmbedMessage(const xcb_client_message_event_t *event) case XEMBED_WINDOW_DEACTIVATE: break; case XEMBED_EMBEDDED_NOTIFY: - Q_XCB_CALL(xcb_map_window(xcb_connection(), m_window)); + xcb_map_window(xcb_connection(), m_window); xcbScreen()->windowShown(this); // Without Qt::WA_TranslucentBackground, we use a ParentRelative BackPixmap. // Clear the whole tray icon window to its background color as early as possible // so that we can get a clean result from grabWindow() later. - Q_XCB_CALL(xcb_clear_area(xcb_connection(), false, m_window, 0, 0, geometry().width(), geometry().height())); + xcb_clear_area(xcb_connection(), false, m_window, 0, 0, geometry().width(), geometry().height()); xcb_flush(xcb_connection()); break; case XEMBED_FOCUS_IN: @@ -2841,14 +2776,14 @@ void QXcbWindow::setOpacity(qreal level) quint32 value = qRound64(qBound(qreal(0), level, qreal(1)) * 0xffffffff); - Q_XCB_CALL(xcb_change_property(xcb_connection(), - XCB_PROP_MODE_REPLACE, - m_window, - atom(QXcbAtom::_NET_WM_WINDOW_OPACITY), - XCB_ATOM_CARDINAL, - 32, - 1, - (uchar *)&value)); + xcb_change_property(xcb_connection(), + XCB_PROP_MODE_REPLACE, + m_window, + atom(QXcbAtom::_NET_WM_WINDOW_OPACITY), + XCB_ATOM_CARDINAL, + 32, + 1, + (uchar *)&value); } void QXcbWindow::setMask(const QRegion ®ion) |