Add support for _NET_ACTIVE_WINDOW on xcb
authorJan Arne Petersen <jpetersen@openismus.com>
Tue, 28 Feb 2012 09:54:34 +0000 (10:54 +0100)
committerQt by Nokia <qt-info@nokia.com>
Thu, 1 Mar 2012 11:16:57 +0000 (12:16 +0100)
Use a _NET_ACTIVE_WINDOW client message instead of xcb_set_input_focus
for activating toplevel windows on xcb.

According to the Extended Window Manager Hints the right way to activate
a top-level window is using _NET_ACTIVE_WINDOW (when it is supported by
the WM). Other approaches like calling xcb_set_input_focus should be
avoided when possible, since the WM cannot intercept them.

Change-Id: I9be4901f56cbcfb563baf73ccd71ff17a9bdc1d2
Reviewed-by: Uli Schlachter <psychon@znc.in>
Reviewed-by: Samuel Rødal <samuel.rodal@nokia.com>
Reviewed-by: Robin Burchell <robin+qt@viroteck.net>
src/plugins/platforms/xcb/qxcbwindow.cpp

index 6b7e73d..1688fdf 100644 (file)
@@ -1168,10 +1168,31 @@ void QXcbWindow::propagateSizeHints()
 
 void QXcbWindow::requestActivateWindow()
 {
-    if (m_mapped){
-        updateNetWmUserTime(connection()->time());
+    if (!m_mapped)
+        return;
+
+    updateNetWmUserTime(connection()->time());
+
+    if (window()->isTopLevel()
+        && connection()->wmSupport()->isSupportedByWM(atom(QXcbAtom::_NET_ACTIVE_WINDOW))) {
+        xcb_client_message_event_t event;
+
+        event.response_type = XCB_CLIENT_MESSAGE;
+        event.format = 32;
+        event.window = m_window;
+        event.type = atom(QXcbAtom::_NET_ACTIVE_WINDOW);
+        event.data.data32[0] = 1;
+        event.data.data32[1] = connection()->time();
+        QWindow *focusWindow = QGuiApplication::focusWindow();
+        event.data.data32[2] = focusWindow ? focusWindow->winId() : XCB_NONE;
+        event.data.data32[3] = 0;
+        event.data.data32[4] = 0;
+
+        Q_XCB_CALL(xcb_send_event(xcb_connection(), 0, m_screen->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()));
     }
+
     connection()->sync();
 }