xcb: set SM_CLIENT_ID property

SM_CLIENT_ID is required by kwin for proper session management.

- move client leader initialization from screen to connection
- add SM_CLIENT_ID property to client leader

Change-Id: I19fb0d098811c865f6f13d5bc3e59a173c596a65
Task-number: QTBUG-46310
Reviewed-by: Alexander Volkov <a.volkov@rusbitech.ru>
Reviewed-by: Uli Schlachter <psychon@znc.in>
Reviewed-by: Shawn Rutledge <shawn.rutledge@theqtcompany.com>
This commit is contained in:
Stefan Becker 2015-05-25 17:46:49 +03:00 committed by Alexander Volkov
parent 27bf6df294
commit 61a0656eb4
5 changed files with 57 additions and 37 deletions

View File

@ -454,6 +454,7 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra
, has_xkb(false) , has_xkb(false)
, m_buttons(0) , m_buttons(0)
, m_focusWindow(0) , m_focusWindow(0)
, m_clientLeader(0)
, m_systemTrayTracker(0) , m_systemTrayTracker(0)
, m_glIntegration(Q_NULLPTR) , m_glIntegration(Q_NULLPTR)
, m_xiGrab(false) , m_xiGrab(false)
@ -1336,6 +1337,58 @@ xcb_window_t QXcbConnection::rootWindow()
return s ? s->root() : 0; return s ? s->root() : 0;
} }
xcb_window_t QXcbConnection::clientLeader()
{
if (m_clientLeader == 0) {
m_clientLeader = xcb_generate_id(xcb_connection());
QXcbScreen *screen = primaryScreen();
Q_XCB_CALL(xcb_create_window(xcb_connection(),
XCB_COPY_FROM_PARENT,
m_clientLeader,
screen->root(),
0, 0, 1, 1,
0,
XCB_WINDOW_CLASS_INPUT_OUTPUT,
screen->screen()->root_visual,
0, 0));
#ifndef QT_NO_DEBUG
QByteArray ba("Qt client leader window");
Q_XCB_CALL(xcb_change_property(xcb_connection(),
XCB_PROP_MODE_REPLACE,
m_clientLeader,
atom(QXcbAtom::_NET_WM_NAME),
atom(QXcbAtom::UTF8_STRING),
8,
ba.length(),
ba.constData()));
#endif
Q_XCB_CALL(xcb_change_property(xcb_connection(),
XCB_PROP_MODE_REPLACE,
m_clientLeader,
atom(QXcbAtom::WM_CLIENT_LEADER),
XCB_ATOM_WINDOW,
32,
1,
&m_clientLeader));
#if !defined(QT_NO_SESSIONMANAGER) && defined(XCB_USE_SM)
// If we are session managed, inform the window manager about it
QByteArray session = qGuiApp->sessionId().toLatin1();
if (!session.isEmpty()) {
Q_XCB_CALL(xcb_change_property(xcb_connection(),
XCB_PROP_MODE_REPLACE,
m_clientLeader,
atom(QXcbAtom::SM_CLIENT_ID),
XCB_ATOM_STRING,
8,
session.length(),
session.constData()));
}
#endif
}
return m_clientLeader;
}
#ifdef XCB_USE_XLIB #ifdef XCB_USE_XLIB
void *QXcbConnection::xlib_display() const void *QXcbConnection::xlib_display() const
{ {

View File

@ -403,6 +403,7 @@ public:
QXcbWMSupport *wmSupport() const { return m_wmSupport.data(); } QXcbWMSupport *wmSupport() const { return m_wmSupport.data(); }
xcb_window_t rootWindow(); xcb_window_t rootWindow();
xcb_window_t clientLeader();
bool hasDefaultVisualId() const { return m_defaultVisualId != UINT_MAX; } bool hasDefaultVisualId() const { return m_defaultVisualId != UINT_MAX; }
xcb_visualid_t defaultVisualId() const { return m_defaultVisualId; } xcb_visualid_t defaultVisualId() const { return m_defaultVisualId; }
@ -640,6 +641,7 @@ private:
QXcbWindow *m_focusWindow; QXcbWindow *m_focusWindow;
xcb_window_t m_clientLeader;
QByteArray m_startupId; QByteArray m_startupId;
QXcbSystemTrayTracker *m_systemTrayTracker; QXcbSystemTrayTracker *m_systemTrayTracker;
QXcbGlIntegration *m_glIntegration; QXcbGlIntegration *m_glIntegration;

View File

@ -170,38 +170,6 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDe
else else
m_syncRequestSupported = true; m_syncRequestSupported = true;
m_clientLeader = xcb_generate_id(xcb_connection());
Q_XCB_CALL2(xcb_create_window(xcb_connection(),
XCB_COPY_FROM_PARENT,
m_clientLeader,
screen()->root,
0, 0, 1, 1,
0,
XCB_WINDOW_CLASS_INPUT_OUTPUT,
screen()->root_visual,
0, 0), connection);
#ifndef QT_NO_DEBUG
QByteArray ba("Qt client leader window for screen ");
ba += m_outputName.toUtf8();
Q_XCB_CALL2(xcb_change_property(xcb_connection(),
XCB_PROP_MODE_REPLACE,
m_clientLeader,
atom(QXcbAtom::_NET_WM_NAME),
atom(QXcbAtom::UTF8_STRING),
8,
ba.length(),
ba.constData()), connection);
#endif
Q_XCB_CALL2(xcb_change_property(xcb_connection(),
XCB_PROP_MODE_REPLACE,
m_clientLeader,
atom(QXcbAtom::WM_CLIENT_LEADER),
XCB_ATOM_WINDOW,
32,
1,
&m_clientLeader), connection);
xcb_depth_iterator_t depth_iterator = xcb_depth_iterator_t depth_iterator =
xcb_screen_allowed_depths_iterator(screen()); xcb_screen_allowed_depths_iterator(screen());

View File

@ -116,8 +116,6 @@ public:
xcb_randr_crtc_t crtc() const { return m_crtc; } xcb_randr_crtc_t crtc() const { return m_crtc; }
xcb_randr_mode_t mode() const { return m_mode; } xcb_randr_mode_t mode() const { return m_mode; }
xcb_window_t clientLeader() const { return m_clientLeader; }
void windowShown(QXcbWindow *window); void windowShown(QXcbWindow *window);
QString windowManagerName() const { return m_windowManagerName; } QString windowManagerName() const { return m_windowManagerName; }
bool syncRequestSupported() const { return m_syncRequestSupported; } bool syncRequestSupported() const { return m_syncRequestSupported; }
@ -173,7 +171,6 @@ private:
Qt::ScreenOrientation m_orientation; Qt::ScreenOrientation m_orientation;
QString m_windowManagerName; QString m_windowManagerName;
bool m_syncRequestSupported; bool m_syncRequestSupported;
xcb_window_t m_clientLeader;
QMap<xcb_visualid_t, xcb_visualtype_t> m_visuals; QMap<xcb_visualid_t, xcb_visualtype_t> m_visuals;
QMap<xcb_visualid_t, quint8> m_visualDepths; QMap<xcb_visualid_t, quint8> m_visualDepths;
QXcbCursor *m_cursor; QXcbCursor *m_cursor;

View File

@ -622,7 +622,7 @@ void QXcbWindow::create()
xcb_set_wm_hints(xcb_connection(), m_window, &hints); xcb_set_wm_hints(xcb_connection(), m_window, &hints);
xcb_window_t leader = platformScreen->clientLeader(); xcb_window_t leader = connection()->clientLeader();
Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
atom(QXcbAtom::WM_CLIENT_LEADER), XCB_ATOM_WINDOW, 32, atom(QXcbAtom::WM_CLIENT_LEADER), XCB_ATOM_WINDOW, 32,
1, &leader)); 1, &leader));
@ -874,7 +874,7 @@ void QXcbWindow::show()
// Default to client leader if there is no transient parent, else modal dialogs can // Default to client leader if there is no transient parent, else modal dialogs can
// be hidden by their parents. // be hidden by their parents.
if (!transientXcbParent) if (!transientXcbParent)
transientXcbParent = xcbScreen()->clientLeader(); transientXcbParent = connection()->clientLeader();
if (transientXcbParent) { // ICCCM 4.1.2.6 if (transientXcbParent) { // ICCCM 4.1.2.6
Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, 32, XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, 32,