From 6f482054d74423501420d94cb40edb6bd1a19dc9 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Thu, 21 Apr 2022 14:07:19 +0400 Subject: [PATCH] xcb: set _NET_STARTUP_ID at client leader window This should help to overcome WM's focus prevention mechanism Fixes: QTBUG-96276 Change-Id: Ic5fb46f7ce54f0df29850725bafa364b74e30d25 Reviewed-by: Qt CI Bot Reviewed-by: Liang Qi (cherry picked from commit ba8c4b4ac6df8c4318e3dd8c886aa0135628d33c) Reviewed-by: Qt Cherry-pick Bot --- src/plugins/platforms/xcb/qxcbatom.cpp | 1 + src/plugins/platforms/xcb/qxcbatom.h | 1 + src/plugins/platforms/xcb/qxcbconnection.cpp | 28 ++++++++++++++++++-- src/plugins/platforms/xcb/qxcbconnection.h | 5 ++-- src/plugins/platforms/xcb/qxcbscreen.cpp | 2 +- 5 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbatom.cpp b/src/plugins/platforms/xcb/qxcbatom.cpp index 8f984c72809..fb5c97fe389 100644 --- a/src/plugins/platforms/xcb/qxcbatom.cpp +++ b/src/plugins/platforms/xcb/qxcbatom.cpp @@ -114,6 +114,7 @@ static const char *xcb_atomnames = { "_NET_STARTUP_INFO\0" "_NET_STARTUP_INFO_BEGIN\0" + "_NET_STARTUP_ID\0" "_NET_SUPPORTING_WM_CHECK\0" diff --git a/src/plugins/platforms/xcb/qxcbatom.h b/src/plugins/platforms/xcb/qxcbatom.h index 48924dd626e..2171875e001 100644 --- a/src/plugins/platforms/xcb/qxcbatom.h +++ b/src/plugins/platforms/xcb/qxcbatom.h @@ -115,6 +115,7 @@ public: _NET_STARTUP_INFO, _NET_STARTUP_INFO_BEGIN, + _NET_STARTUP_ID, _NET_SUPPORTING_WM_CHECK, diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 51530e00553..07509697038 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -81,8 +81,8 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra m_drag = new QXcbDrag(this); #endif - m_startupId = qgetenv("DESKTOP_STARTUP_ID"); - if (!m_startupId.isNull()) + setStartupId(qgetenv("DESKTOP_STARTUP_ID")); + if (!startupId().isNull()) qunsetenv("DESKTOP_STARTUP_ID"); const int focusInDelay = 100; @@ -771,6 +771,28 @@ void QXcbConnection::setMousePressWindow(QXcbWindow *w) m_mousePressWindow = w; } +QByteArray QXcbConnection::startupId() const +{ + return m_startupId; +} +void QXcbConnection::setStartupId(const QByteArray &nextId) +{ + m_startupId = nextId; + if (m_clientLeader) { + if (!nextId.isEmpty()) + xcb_change_property(xcb_connection(), + XCB_PROP_MODE_REPLACE, + clientLeader(), + atom(QXcbAtom::_NET_STARTUP_ID), + atom(QXcbAtom::UTF8_STRING), + 8, + nextId.length(), + nextId.constData()); + else + xcb_delete_property(xcb_connection(), clientLeader(), atom(QXcbAtom::_NET_STARTUP_ID)); + } +} + void QXcbConnection::grabServer() { if (m_canGrabServer) @@ -917,6 +939,8 @@ xcb_window_t QXcbConnection::clientLeader() session.constData()); } #endif + + setStartupId(startupId()); } return m_clientLeader; } diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 2d55524f6ff..24e684866d8 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -170,9 +170,8 @@ public: QXcbWindow *mousePressWindow() const { return m_mousePressWindow; } void setMousePressWindow(QXcbWindow *); - QByteArray startupId() const { return m_startupId; } - void setStartupId(const QByteArray &nextId) { m_startupId = nextId; } - void clearStartupId() { m_startupId.clear(); } + QByteArray startupId() const; + void setStartupId(const QByteArray &nextId); void grabServer(); void ungrabServer(); diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index 2a538c9b6ea..95802503a9e 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -796,7 +796,7 @@ void QXcbScreen::windowShown(QXcbWindow *window) // Freedesktop.org Startup Notification if (!connection()->startupId().isEmpty() && window->window()->isTopLevel()) { sendStartupMessage(QByteArrayLiteral("remove: ID=") + connection()->startupId()); - connection()->clearStartupId(); + connection()->setStartupId({}); } }