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>
This commit is contained in:
parent
b9f76db30d
commit
8eaf335259
@ -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();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user