From e9c68f36bdff63a49589a5eb76c02a1e98451331 Mon Sep 17 00:00:00 2001 From: Alain Knaff Date: Fri, 22 May 2020 13:56:20 +0100 Subject: [PATCH] [x11] Send a valid timestamp in TakeFocus messages Kwin sends out undated WM_TAKE_FOCUS client messages. Gtk based applications such as Firefox react to these by handing focus to one of their subwindows using XSetInputFocus(), and pass on the null time field that they received in the client message to XSetInputFocus(). If for whatever reason the application (firefox) is slow to process the event, it might issue that XSetInputFocus() message at a time when it has already lost focus to the next application. This results in Firefox stealing back the focus from the next application. Normally, such an occurrence would not happen, as the server could tell by the time field that the message is stale. Until 2016 (e73e331f35b9da4bbb99c80c5c1eedd2ae99422b) kwin *used* to send a valid timestamp, but this got deliberately broken to appease some Java Applications which were "extremely picky" and would refuse focus. This was based on the assumption that no other toolkit used the timestamp from take focus events which is now proven to be false. ICCCM document states: Windows with the atom WM_TAKE_FOCUS in their WM_PROTOCOLS property may receive a ClientMessage event from the window manager (as described in section 4.2.8) with WM_TAKE_FOCUS in its data[0] field and a valid timestamp (i.e. not CurrentTime ) in its data[1] field." BUG: 421068 --- x11client.cpp | 7 ++++--- x11client.h | 3 +-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/x11client.cpp b/x11client.cpp index 6e2509d3cf..00cd48ac35 100644 --- a/x11client.cpp +++ b/x11client.cpp @@ -1705,7 +1705,7 @@ void X11Client::updateHiddenPreview() } } -void X11Client::sendClientMessage(xcb_window_t w, xcb_atom_t a, xcb_atom_t protocol, uint32_t data1, uint32_t data2, uint32_t data3, xcb_timestamp_t timestamp) +void X11Client::sendClientMessage(xcb_window_t w, xcb_atom_t a, xcb_atom_t protocol, uint32_t data1, uint32_t data2, uint32_t data3) { xcb_client_message_event_t ev; memset(&ev, 0, sizeof(ev)); @@ -1714,7 +1714,7 @@ void X11Client::sendClientMessage(xcb_window_t w, xcb_atom_t a, xcb_atom_t proto ev.type = a; ev.format = 32; ev.data.data32[0] = protocol; - ev.data.data32[1] = timestamp; + ev.data.data32[1] = xTime(); ev.data.data32[2] = data1; ev.data.data32[3] = data2; ev.data.data32[4] = data3; @@ -2029,7 +2029,8 @@ void X11Client::takeFocus() else demandAttention(false); // window cannot take input, at least withdraw urgency if (info->supportsProtocol(NET::TakeFocusProtocol)) { - sendClientMessage(window(), atoms->wm_protocols, atoms->wm_take_focus, 0, 0, 0, XCB_CURRENT_TIME); + updateXTime(); + sendClientMessage(window(), atoms->wm_protocols, atoms->wm_take_focus); } workspace()->setShouldGetFocus(this); diff --git a/x11client.h b/x11client.h index 268f6aaaa5..8d5f193c45 100644 --- a/x11client.h +++ b/x11client.h @@ -426,8 +426,7 @@ private: void killProcess(bool ask, xcb_timestamp_t timestamp = XCB_TIME_CURRENT_TIME); void updateUrgency(); static void sendClientMessage(xcb_window_t w, xcb_atom_t a, xcb_atom_t protocol, - uint32_t data1 = 0, uint32_t data2 = 0, uint32_t data3 = 0, - xcb_timestamp_t timestamp = xTime()); + uint32_t data1 = 0, uint32_t data2 = 0, uint32_t data3 = 0); void embedClient(xcb_window_t w, xcb_visualid_t visualid, xcb_colormap_t colormap, uint8_t depth); void detectNoBorder();