diff options
Diffstat (limited to 'src/plugins/platforms/xcb/qxcbwindow.cpp')
-rw-r--r-- | src/plugins/platforms/xcb/qxcbwindow.cpp | 260 |
1 files changed, 112 insertions, 148 deletions
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 59b06d543e..d42d95f890 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -70,6 +70,9 @@ #undef class #include <xcb/xfixes.h> #include <xcb/shape.h> +#if QT_CONFIG(xcb_xinput) +#include <xcb/xinput.h> +#endif // xcb-icccm 3.8 support #ifdef XCB_ICCCM_NUM_WM_SIZE_HINTS_ELEMENTS @@ -109,11 +112,6 @@ #undef register #endif -#if QT_CONFIG(xinput2) -#include <X11/extensions/XInput2.h> -#include <X11/extensions/XI2proto.h> -#endif - #define XCOORD_MAX 16383 enum { defaultWindowWidth = 160, @@ -200,11 +198,6 @@ void QXcbWindow::setImageFormatForVisual(const xcb_visualtype_t *visual) } } -static inline bool positionIncludesFrame(QWindow *w) -{ - return qt_window_private(w)->positionPolicy == QWindowPrivate::WindowFrameInclusive; -} - #if QT_CONFIG(xcb_xlib) static inline XTextProperty* qstringToXTP(Display *dpy, const QString& s) { @@ -308,6 +301,7 @@ void QXcbWindow::create() destroy(); m_windowState = Qt::WindowNoState; + m_trayIconWindow = window()->objectName() == QLatin1String("QSystemTrayIconSysWindow"); Qt::WindowType type = window()->type(); @@ -334,9 +328,6 @@ void QXcbWindow::create() return; } - // Parameters to XCreateWindow() are frame corner + inner size. - // This fits in case position policy is frame inclusive. There is - // currently no way to implement it for frame-exclusive geometries. QPlatformWindow::setGeometry(rect); if (platformScreen != currentScreen) @@ -368,7 +359,9 @@ void QXcbWindow::create() const xcb_visualtype_t *visual = nullptr; - if (connection()->hasDefaultVisualId()) { + if (m_trayIconWindow && connection()->systemTrayTracker()) { + visual = platformScreen->visualForId(connection()->systemTrayTracker()->visualId()); + } else if (connection()->hasDefaultVisualId()) { visual = platformScreen->visualForId(connection()->defaultVisualId()); if (!visual) qWarning() << "Failed to use requested visual id."; @@ -458,9 +451,7 @@ void QXcbWindow::create() properties[propertyCount++] = atom(QXcbAtom::WM_TAKE_FOCUS); properties[propertyCount++] = atom(QXcbAtom::_NET_WM_PING); - m_usingSyncProtocol = platformScreen->syncRequestSupported(); - - if (m_usingSyncProtocol) + if (connection()->hasXSync()) properties[propertyCount++] = atom(QXcbAtom::_NET_WM_SYNC_REQUEST); if (window()->flags() & Qt::WindowContextHelpButtonHint) @@ -484,7 +475,7 @@ void QXcbWindow::create() XCB_ATOM_STRING, 8, wmClass.size(), wmClass.constData()); } - if (m_usingSyncProtocol) { + if (connection()->hasXSync()) { m_syncCounter = xcb_generate_id(xcb_connection()); xcb_sync_create_counter(xcb_connection(), m_syncCounter, m_syncValue); @@ -504,6 +495,13 @@ void QXcbWindow::create() atom(QXcbAtom::_NET_WM_PID), XCB_ATOM_CARDINAL, 32, 1, &pid); + const QByteArray clientMachine = QSysInfo::machineHostName().toLocal8Bit(); + if (!clientMachine.isEmpty()) { + xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, + atom(QXcbAtom::WM_CLIENT_MACHINE), XCB_ATOM_STRING, 8, + clientMachine.size(), clientMachine.constData()); + } + xcb_wm_hints_t hints; memset(&hints, 0, sizeof(hints)); xcb_wm_hints_set_normal(&hints); @@ -524,7 +522,7 @@ void QXcbWindow::create() atom(QXcbAtom::_XEMBED_INFO), 32, 2, (void *)data); -#if QT_CONFIG(xinput2) +#if QT_CONFIG(xcb_xinput) if (connection()->hasXInput2()) { if (connection()->xi2MouseEventsDisabled()) connection()->xi2SelectDeviceEventsCompatibility(m_window); @@ -562,6 +560,9 @@ void QXcbWindow::create() QByteArray wmWindowRole = window()->property(wm_window_role_property_id).toByteArray(); setWmWindowRole(wmWindowRole); } + + if (m_trayIconWindow) + m_embedded = requestSystemTrayWindowDock(); } QXcbWindow::~QXcbWindow() @@ -587,7 +588,7 @@ void QXcbWindow::destroy() if (connection()->mouseGrabber() == this) connection()->setMouseGrabber(nullptr); - if (m_syncCounter && m_usingSyncProtocol) + if (m_syncCounter && connection()->hasXSync()) xcb_sync_destroy_counter(xcb_connection(), m_syncCounter); if (m_window) { if (m_netWmUserTimeWindow) { @@ -623,25 +624,23 @@ void QXcbWindow::setGeometry(const QRect &rect) if (!newScreen) newScreen = xcbScreen(); - const QRect wmGeometry = windowToWmGeometry(rect); - if (newScreen != currentScreen) QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->QPlatformScreen::screen()); if (qt_window_private(window())->positionAutomatic) { const quint32 mask = XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT; const qint32 values[] = { - qBound<qint32>(1, wmGeometry.width(), XCOORD_MAX), - qBound<qint32>(1, wmGeometry.height(), XCOORD_MAX), + qBound<qint32>(1, rect.width(), XCOORD_MAX), + qBound<qint32>(1, rect.height(), XCOORD_MAX), }; 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[] = { - qBound<qint32>(-XCOORD_MAX, wmGeometry.x(), XCOORD_MAX), - qBound<qint32>(-XCOORD_MAX, wmGeometry.y(), XCOORD_MAX), - qBound<qint32>(1, wmGeometry.width(), XCOORD_MAX), - qBound<qint32>(1, wmGeometry.height(), XCOORD_MAX), + qBound<qint32>(-XCOORD_MAX, rect.x(), XCOORD_MAX), + qBound<qint32>(-XCOORD_MAX, rect.y(), XCOORD_MAX), + qBound<qint32>(1, rect.width(), XCOORD_MAX), + qBound<qint32>(1, rect.height(), XCOORD_MAX), }; xcb_configure_window(xcb_connection(), m_window, mask, reinterpret_cast<const quint32*>(values)); if (window()->parent() && !window()->transientParent()) { @@ -764,9 +763,6 @@ void QXcbWindow::show() xcb_set_wm_hints(xcb_connection(), m_window, &hints); - m_gravity = positionIncludesFrame(window()) ? - XCB_GRAVITY_NORTH_WEST : XCB_GRAVITY_STATIC; - // update WM_NORMAL_HINTS propagateSizeHints(); @@ -801,7 +797,7 @@ void QXcbWindow::show() else if (connection()->time() != XCB_TIME_CURRENT_TIME) updateNetWmUserTime(connection()->time()); - if (window()->objectName() == QLatin1String("QSystemTrayIconSysWindow")) + if (m_trayIconWindow) return; // defer showing until XEMBED_EMBEDDED_NOTIFY xcb_map_window(xcb_connection(), m_window); @@ -819,7 +815,7 @@ void QXcbWindow::hide() 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); + q_padded_xcb_event<xcb_unmap_notify_event_t> event = {}; event.response_type = XCB_UNMAP_NOTIFY; event.event = xcbScreen()->root(); event.window = m_window; @@ -1364,17 +1360,10 @@ void QXcbWindow::updateNetWmUserTime(xcb_timestamp_t timestamp) 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"); - 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 + + QXcbWindow::setWindowTitle(connection(), m_netWmUserTimeWindow, + QStringLiteral("Qt NET_WM User Time Window")); + } else if (!isSupportedByWM) { // WM no longer supports it, then we should remove the // _NET_WM_USER_TIME_WINDOW atom. @@ -1452,24 +1441,7 @@ void QXcbWindow::setParent(const QPlatformWindow *parent) void QXcbWindow::setWindowTitle(const QString &title) { - QString fullTitle = formatWindowTitle(title, QString::fromUtf8(" \xe2\x80\x94 ")); // unicode character U+2014, EM DASH - const QByteArray ba = std::move(fullTitle).toUtf8(); - 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()); - -#if QT_CONFIG(xcb_xlib) - Display *dpy = static_cast<Display *>(connection()->xlib_display()); - XTextProperty *text = qstringToXTP(dpy, title); - if (text) - XSetWMName(dpy, m_window, text); -#endif - xcb_flush(xcb_connection()); + setWindowTitle(connection(), m_window, title); } void QXcbWindow::setWindowIconText(const QString &title) @@ -1541,38 +1513,28 @@ void QXcbWindow::lower() xcb_configure_window(xcb_connection(), m_window, mask, values); } -// Adapt the geometry to match the WM expection with regards -// to gravity. -QRect QXcbWindow::windowToWmGeometry(QRect r) const -{ - if (m_dirtyFrameMargins || m_frameMargins.isNull()) - return r; - const bool frameInclusive = positionIncludesFrame(window()); - // XCB_GRAVITY_STATIC requires the inner geometry, whereas - // XCB_GRAVITY_NORTH_WEST requires the frame geometry - if (frameInclusive && m_gravity == XCB_GRAVITY_STATIC) { - r.translate(m_frameMargins.left(), m_frameMargins.top()); - } else if (!frameInclusive && m_gravity == XCB_GRAVITY_NORTH_WEST) { - r.translate(-m_frameMargins.left(), -m_frameMargins.top()); - } - return r; -} - void QXcbWindow::propagateSizeHints() { // update WM_NORMAL_HINTS xcb_size_hints_t hints; memset(&hints, 0, sizeof(hints)); - const QRect xRect = windowToWmGeometry(geometry()); + const QRect rect = geometry(); + QWindowPrivate *win = qt_window_private(window()); + + if (!win->positionAutomatic) + xcb_size_hints_set_position(&hints, true, rect.x(), rect.y()); + if (rect.width() < QWINDOWSIZE_MAX || rect.height() < QWINDOWSIZE_MAX) + xcb_size_hints_set_size(&hints, true, rect.width(), rect.height()); - QWindow *win = window(); + /* Gravity describes how to interpret x and y values the next time + window needs to be positioned on a screen. + XCB_GRAVITY_STATIC : the left top corner of the client window + XCB_GRAVITY_NORTH_WEST : the left top corner of the frame window */ + auto gravity = win->positionPolicy == QWindowPrivate::WindowFrameInclusive + ? XCB_GRAVITY_NORTH_WEST : XCB_GRAVITY_STATIC; - if (!qt_window_private(win)->positionAutomatic) - xcb_size_hints_set_position(&hints, true, xRect.x(), xRect.y()); - if (xRect.width() < QWINDOWSIZE_MAX || xRect.height() < QWINDOWSIZE_MAX) - xcb_size_hints_set_size(&hints, true, xRect.width(), xRect.height()); - xcb_size_hints_set_win_gravity(&hints, m_gravity); + xcb_size_hints_set_win_gravity(&hints, gravity); QSize minimumSize = windowMinimumSize(); QSize maximumSize = windowMaximumSize(); @@ -1836,12 +1798,6 @@ void QXcbWindow::setWmWindowRole(const QByteArray &role) role.size(), role.constData()); } -void QXcbWindow::setParentRelativeBackPixmapStatic(QWindow *window) -{ - if (window->handle()) - static_cast<QXcbWindow *>(window->handle())->setParentRelativeBackPixmap(); -} - void QXcbWindow::setParentRelativeBackPixmap() { const quint32 mask = XCB_CW_BACK_PIXMAP; @@ -1849,14 +1805,7 @@ void QXcbWindow::setParentRelativeBackPixmap() xcb_change_window_attributes(xcb_connection(), m_window, mask, values); } -bool QXcbWindow::requestSystemTrayWindowDockStatic(const QWindow *window) -{ - if (window->handle()) - return static_cast<QXcbWindow *>(window->handle())->requestSystemTrayWindowDock(); - return false; -} - -bool QXcbWindow::requestSystemTrayWindowDock() const +bool QXcbWindow::requestSystemTrayWindowDock() { if (!connection()->systemTrayTracker()) return false; @@ -1864,20 +1813,6 @@ bool QXcbWindow::requestSystemTrayWindowDock() const return true; } -QRect QXcbWindow::systemTrayWindowGlobalGeometryStatic(const QWindow *window) -{ - if (window->handle()) - return static_cast<QXcbWindow *>(window->handle())->systemTrayWindowGlobalGeometry(); - return QRect(); -} - -QRect QXcbWindow::systemTrayWindowGlobalGeometry() const -{ - if (!connection()->systemTrayTracker()) - return QRect(); - return connection()->systemTrayTracker()->systemTrayWindowGlobalGeometry(m_window); -} - class ExposeCompressor { public: @@ -1977,7 +1912,7 @@ void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *even connection()->setTime(event->data.data32[1]); m_syncValue.lo = event->data.data32[2]; m_syncValue.hi = event->data.data32[3]; - if (m_usingSyncProtocol) + if (connection()->hasXSync()) m_syncState = SyncReceived; #ifndef QT_NO_WHATSTHIS } else if (protocolAtom == atom(QXcbAtom::_NET_WM_CONTEXT_HELP)) { @@ -2052,7 +1987,7 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t * } m_oldWindowSize = actualGeometry.size(); - if (m_usingSyncProtocol && m_syncState == SyncReceived) + if (connection()->hasXSync() && m_syncState == SyncReceived) m_syncState = SyncAndConfigureReceived; m_dirtyFrameMargins = true; @@ -2137,7 +2072,7 @@ void QXcbWindow::handleButtonPressEvent(int event_x, int event_y, int root_x, in updateNetWmUserTime(timestamp); - if (m_embedded) { + if (m_embedded && !m_trayIconWindow) { if (window() != QGuiApplication::focusWindow()) { const QXcbWindow *container = static_cast<const QXcbWindow *>(parent()); Q_ASSERT(container != 0); @@ -2149,7 +2084,7 @@ void QXcbWindow::handleButtonPressEvent(int event_x, int event_y, int root_x, in QPoint global(root_x, root_y); if (isWheel) { -#if QT_CONFIG(xinput2) +#if QT_CONFIG(xcb_xinput) if (!connection()->isAtLeastXI21()) { #endif QPoint angleDelta; @@ -2164,7 +2099,7 @@ void QXcbWindow::handleButtonPressEvent(int event_x, int event_y, int root_x, in if (modifiers & Qt::AltModifier) std::swap(angleDelta.rx(), angleDelta.ry()); QWindowSystemInterface::handleWheelEvent(window(), timestamp, local, global, QPoint(), angleDelta, modifiers); -#if QT_CONFIG(xinput2) +#if QT_CONFIG(xcb_xinput) } #endif return; @@ -2204,7 +2139,7 @@ static inline bool doCheckUnGrabAncestor(QXcbConnection *conn) if (conn) { const bool mouseButtonsPressed = (conn->buttonState() != Qt::NoButton); -#if QT_CONFIG(xinput2) +#if QT_CONFIG(xcb_xinput) return mouseButtonsPressed || (conn->hasXInput2() && !conn->xi2MouseEventsDisabled()); #else return mouseButtonsPressed; @@ -2258,7 +2193,7 @@ void QXcbWindow::handleEnterNotifyEvent(int event_x, int event_y, int root_x, in if (ignoreEnterEvent(mode, detail, connection()) || connection()->mousePressWindow()) return; -#ifdef XCB_USE_XINPUT21 +#if QT_CONFIG(xcb_xinput) // Updates scroll valuators, as user might have done some scrolling outside our X client. connection()->xi2UpdateScrollingDevices(); #endif @@ -2330,16 +2265,18 @@ void QXcbWindow::handleMotionNotifyEvent(const xcb_motion_notify_event_t *event) event->time, QEvent::MouseMove); } -#if QT_CONFIG(xinput2) -static inline int fixed1616ToInt(FP1616 val) +#if QT_CONFIG(xcb_xinput) +static inline int fixed1616ToInt(xcb_input_fp1616_t val) { return int(qreal(val) / 0x10000); } +#define qt_xcb_mask_is_set(ptr, event) (((unsigned char*)(ptr))[(event)>>3] & (1 << ((event) & 7))) + void QXcbWindow::handleXIMouseEvent(xcb_ge_event_t *event, Qt::MouseEventSource source) { QXcbConnection *conn = connection(); - xXIDeviceEvent *ev = reinterpret_cast<xXIDeviceEvent *>(event); + auto *ev = reinterpret_cast<xcb_input_button_press_event_t *>(event); if (ev->buttons_len > 0) { unsigned char *buttonMask = (unsigned char *) &ev[1]; @@ -2347,16 +2284,16 @@ void QXcbWindow::handleXIMouseEvent(xcb_ge_event_t *event, Qt::MouseEventSource // XIPointerEmulated being set: https://bugs.freedesktop.org/show_bug.cgi?id=98188 // Filter them out by other attributes: when their source device is a touch screen // and the LMB is pressed. - if (XIMaskIsSet(buttonMask, 1) && conn->isTouchScreen(ev->sourceid)) { + if (qt_xcb_mask_is_set(buttonMask, 1) && conn->isTouchScreen(ev->sourceid)) { if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled())) qCDebug(lcQpaXInput, "XI2 mouse event from touch device %d was ignored", ev->sourceid); return; } for (int i = 1; i <= 15; ++i) - conn->setButtonState(conn->translateMouseButton(i), XIMaskIsSet(buttonMask, i)); + conn->setButtonState(conn->translateMouseButton(i), qt_xcb_mask_is_set(buttonMask, i)); } - const Qt::KeyboardModifiers modifiers = conn->keyboard()->translateModifiers(ev->mods.effective_mods); + const Qt::KeyboardModifiers modifiers = conn->keyboard()->translateModifiers(ev->mods.effective); const int event_x = fixed1616ToInt(ev->event_x); const int event_y = fixed1616ToInt(ev->event_y); const int root_x = fixed1616ToInt(ev->root_x); @@ -2373,47 +2310,47 @@ void QXcbWindow::handleXIMouseEvent(xcb_ge_event_t *event, Qt::MouseEventSource sourceName = me.valueToKey(source); } - switch (ev->evtype) { - case XI_ButtonPress: + switch (ev->event_type) { + case XCB_INPUT_BUTTON_PRESS: if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled())) qCDebug(lcQpaXInputEvents, "XI2 mouse press, button %d, time %d, source %s", button, ev->time, sourceName); conn->setButtonState(button, true); handleButtonPressEvent(event_x, event_y, root_x, root_y, ev->detail, modifiers, ev->time, QEvent::MouseButtonPress, source); break; - case XI_ButtonRelease: + case XCB_INPUT_BUTTON_RELEASE: if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled())) qCDebug(lcQpaXInputEvents, "XI2 mouse release, button %d, time %d, source %s", button, ev->time, sourceName); conn->setButtonState(button, false); handleButtonReleaseEvent(event_x, event_y, root_x, root_y, ev->detail, modifiers, ev->time, QEvent::MouseButtonRelease, source); break; - case XI_Motion: + case XCB_INPUT_MOTION: if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled())) qCDebug(lcQpaXInputEvents, "XI2 mouse motion %d,%d, time %d, source %s", event_x, event_y, ev->time, sourceName); handleMotionNotifyEvent(event_x, event_y, root_x, root_y, modifiers, ev->time, QEvent::MouseMove, source); break; default: - qWarning() << "Unrecognized XI2 mouse event" << ev->evtype; + qWarning() << "Unrecognized XI2 mouse event" << ev->event_type; break; } } void QXcbWindow::handleXIEnterLeave(xcb_ge_event_t *event) { - xXIEnterEvent *ev = reinterpret_cast<xXIEnterEvent *>(event); + auto *ev = reinterpret_cast<xcb_input_enter_event_t *>(event); // Compare the window with current mouse grabber to prevent deliver events to any other windows. // If leave event occurs and the window is under mouse - allow to deliver the leave event. QXcbWindow *mouseGrabber = connection()->mouseGrabber(); if (mouseGrabber && mouseGrabber != this - && (ev->evtype != XI_Leave || QGuiApplicationPrivate::currentMouseWindow != window())) { + && (ev->event_type != XCB_INPUT_LEAVE || QGuiApplicationPrivate::currentMouseWindow != window())) { return; } const int root_x = fixed1616ToInt(ev->root_x); const int root_y = fixed1616ToInt(ev->root_y); - switch (ev->evtype) { - case XI_Enter: { + switch (ev->event_type) { + case XCB_INPUT_ENTER: { const int event_x = fixed1616ToInt(ev->event_x); const int event_y = fixed1616ToInt(ev->event_y); qCDebug(lcQpaXInputEvents, "XI2 mouse enter %d,%d, mode %d, detail %d, time %d", @@ -2421,7 +2358,7 @@ void QXcbWindow::handleXIEnterLeave(xcb_ge_event_t *event) handleEnterNotifyEvent(event_x, event_y, root_x, root_y, ev->mode, ev->detail, ev->time); break; } - case XI_Leave: + case XCB_INPUT_LEAVE: qCDebug(lcQpaXInputEvents, "XI2 mouse leave, mode %d, detail %d, time %d", ev->mode, ev->detail, ev->time); connection()->keyboard()->updateXKBStateFromXI(&ev->mods, &ev->group); @@ -2523,7 +2460,7 @@ void QXcbWindow::updateSyncRequestCounter() // window manager does not expect a sync event yet. return; } - if (m_usingSyncProtocol && (m_syncValue.lo != 0 || m_syncValue.hi != 0)) { + if (connection()->hasXSync() && (m_syncValue.lo != 0 || m_syncValue.hi != 0)) { xcb_sync_set_counter(xcb_connection(), m_syncCounter, m_syncValue); xcb_flush(xcb_connection()); @@ -2563,7 +2500,7 @@ bool QXcbWindow::setMouseGrabEnabled(bool grab) if (grab && !connection()->canGrab()) return false; -#if QT_CONFIG(xinput2) +#if QT_CONFIG(xcb_xinput) if (connection()->hasXInput2() && !connection()->xi2MouseEventsDisabled()) { bool result = connection()->xi2SetMouseGrabEnabled(m_window, grab); if (grab && result) @@ -2591,11 +2528,11 @@ bool QXcbWindow::setMouseGrabEnabled(bool grab) return result; } -void QXcbWindow::windowEvent(QEvent *event) +bool QXcbWindow::windowEvent(QEvent *event) { switch (event->type()) { case QEvent::FocusIn: - if (m_embedded && !event->spontaneous()) { + if (m_embedded && !m_trayIconWindow && !event->spontaneous()) { QFocusEvent *focusEvent = static_cast<QFocusEvent *>(event); switch (focusEvent->reason()) { case Qt::TabFocusReason: @@ -2617,7 +2554,7 @@ void QXcbWindow::windowEvent(QEvent *event) default: break; } - QPlatformWindow::windowEvent(event); + return QPlatformWindow::windowEvent(event); } bool QXcbWindow::startSystemResize(const QPoint &pos, Qt::Corner corner) @@ -2638,7 +2575,7 @@ bool QXcbWindow::startSystemMoveResize(const QPoint &pos, int corner) return false; const QPoint globalPos = QHighDpi::toNativePixels(window()->mapToGlobal(pos), window()->screen()); -#ifdef XCB_USE_XINPUT22 +#if QT_CONFIG(xcb_xinput) // ### FIXME QTBUG-53389 bool startedByTouch = connection()->startSystemMoveResizeForTouchBegin(m_window, globalPos, corner); if (startedByTouch) { @@ -2659,6 +2596,7 @@ bool QXcbWindow::startSystemMoveResize(const QPoint &pos, int corner) return true; } + void QXcbWindow::doStartSystemMoveResize(const QPoint &globalPos, int corner) { const xcb_atom_t moveResize = connection()->atom(QXcbAtom::_NET_WM_MOVERESIZE); @@ -2728,11 +2666,6 @@ void QXcbWindow::handleXEmbedMessage(const xcb_client_message_event_t *event) case XEMBED_EMBEDDED_NOTIFY: 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. - xcb_clear_area(xcb_connection(), false, m_window, 0, 0, geometry().width(), geometry().height()); - xcb_flush(xcb_connection()); break; case XEMBED_FOCUS_IN: Qt::FocusReason reason; @@ -2846,6 +2779,28 @@ QXcbScreen *QXcbWindow::xcbScreen() const return static_cast<QXcbScreen *>(screen()); } +void QXcbWindow::setWindowTitle(const QXcbConnection *conn, xcb_window_t window, const QString &title) +{ + QString fullTitle = formatWindowTitle(title, QString::fromUtf8(" \xe2\x80\x94 ")); // unicode character U+2014, EM DASH + const QByteArray ba = std::move(fullTitle).toUtf8(); + xcb_change_property(conn->xcb_connection(), + XCB_PROP_MODE_REPLACE, + window, + conn->atom(QXcbAtom::_NET_WM_NAME), + conn->atom(QXcbAtom::UTF8_STRING), + 8, + ba.length(), + ba.constData()); + +#if QT_CONFIG(xcb_xlib) + Display *dpy = static_cast<Display *>(conn->xlib_display()); + XTextProperty *text = qstringToXTP(dpy, title); + if (text) + XSetWMName(dpy, window, text); +#endif + xcb_flush(conn->xcb_connection()); +} + QString QXcbWindow::windowTitle(const QXcbConnection *conn, xcb_window_t window) { const xcb_atom_t utf8Atom = conn->atom(QXcbAtom::UTF8_STRING); @@ -2856,6 +2811,15 @@ QString QXcbWindow::windowTitle(const QXcbConnection *conn, xcb_window_t window) const char *name = reinterpret_cast<const char *>(xcb_get_property_value(reply.get())); return QString::fromUtf8(name, xcb_get_property_value_length(reply.get())); } + + reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, conn->xcb_connection(), + false, window, conn->atom(QXcbAtom::WM_NAME), + XCB_ATOM_STRING, 0, 1024); + if (reply && reply->format == 8 && reply->type == XCB_ATOM_STRING) { + const char *name = reinterpret_cast<const char *>(xcb_get_property_value(reply.get())); + return QString::fromLatin1(name, xcb_get_property_value_length(reply.get())); + } + return QString(); } |