summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/xcb
diff options
context:
space:
mode:
authorAlexander Bersenev <bay@hackerdom.ru>2015-11-06 01:39:27 +0500
committerBłażej Szczygieł <spaz16@wp.pl>2016-02-06 09:59:17 +0000
commit8eaf3352590690079735eda9fb872ec8c9c58f0a (patch)
treeb6deb0129efa57da0c8e38aa1d5d2b39c311d6fc /src/plugins/platforms/xcb
parentb9f76db30d261421e4da58f29053181af04ceb4d (diff)
xcb: Fix not delivering focusIn event on hide/show
Consider a window which was hidden and shown with hide() and show() methods and mouse pointer was in window when hide() was called. At first, window got focusOutEvent and then Qt library sends X server a message to unmap the window. Then X server will send client two messages: 1) FocusOut(10) detail=Nonlinear(0x03) 2) FocusIn(9) detail=Pointer(0x05) QXcbWindow has a logic for not seting active window to 0 if there is a FocusIn coming (see QXcbWindow::doFocusOut). So QGuiApplicationPrivate::focus_window still points to the current window. Then when show() is called, qt compares previous focus with new focus and, since they are equal, doesn't do anything. Event focusInEvent isn't delivered to the window. Here are two links why X server sends FocusIn just after FocusOut: http://lists.freedesktop.org/archives/xorg/2008-December/041684.html https://tronche.com/gui/x/xlib/events/input-focus/normal-and-grabbed.html Proposed fix ignores FocusIn events with detail==Pointer. The text of explaining comment is taken from the Chromium project: https://chromium.googlesource.com/chromium/src/+/master/ui/views/widget/desktop_aura/x11_desktop_handler.cc from X11DesktopHandler::ProcessXEvent function. [ChangeLog][module][Linux/XCB] Fix not delivering focusIn event on hide/show with XCB Task-number: QTBUG-49071 Change-Id: I433c8b638834c25f113cc134ee4185778c44f540 Reviewed-by: André Hartmann <aha_1980@gmx.de> Reviewed-by: Lisandro Damián Nicanor Pérez Meyer <perezmeyer@gmail.com> Reviewed-by: Shawn Rutledge <shawn.rutledge@theqtcompany.com>
Diffstat (limited to 'src/plugins/platforms/xcb')
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp21
1 files changed, 17 insertions, 4 deletions
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 354c29152f..46b7b70f80 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -894,8 +894,13 @@ static bool focusInPeeker(QXcbConnection *connection, xcb_generic_event_t *event
return true;
}
uint response_type = event->response_type & ~0x80;
- if (response_type == XCB_FOCUS_IN)
- return true;
+ if (response_type == XCB_FOCUS_IN) {
+ // Ignore focus events that are being sent only because the pointer is over
+ // our window, even if the input focus is in a different window.
+ xcb_focus_in_event_t *e = (xcb_focus_in_event_t *) event;
+ if (e->detail != XCB_NOTIFY_DETAIL_POINTER)
+ return true;
+ }
/* We are also interested in XEMBED_FOCUS_IN events */
if (response_type == XCB_CLIENT_MESSAGE) {
@@ -2415,14 +2420,22 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev
}
}
-void QXcbWindow::handleFocusInEvent(const xcb_focus_in_event_t *)
+void QXcbWindow::handleFocusInEvent(const xcb_focus_in_event_t *event)
{
+ // Ignore focus events that are being sent only because the pointer is over
+ // our window, even if the input focus is in a different window.
+ if (event->detail == XCB_NOTIFY_DETAIL_POINTER)
+ return;
doFocusIn();
}
-void QXcbWindow::handleFocusOutEvent(const xcb_focus_out_event_t *)
+void QXcbWindow::handleFocusOutEvent(const xcb_focus_out_event_t *event)
{
+ // Ignore focus events that are being sent only because the pointer is over
+ // our window, even if the input focus is in a different window.
+ if (event->detail == XCB_NOTIFY_DETAIL_POINTER)
+ return;
doFocusOut();
}