Fix problems with focus tracking

When a client spontaneously focuses their window, perhaps in response
to WM_TAKE_FOCUS we'll get a FocusOut/FocusIn pair with same serial.
Updating display->focus_serial in response to FocusOut then was causing
us to ignore FocusIn and think that the focus was not on any window.

We need to distinguish this spontaneous case from the case where we
set the focus ourselves - when we set the focus ourselves, we're careful
to combine the SetFocus with a property change so that we know definitively
what focus events we have already accounted for.

https://bugzilla.gnome.org/show_bug.cgi?id=720558
This commit is contained in:
Owen W. Taylor
2013-12-16 16:01:04 -05:00
parent cb33e1942a
commit 9c1b972ca1
2 changed files with 27 additions and 6 deletions

View File

@ -1670,11 +1670,13 @@ update_focus_window (MetaDisplay *display,
MetaFocusType type,
MetaWindow *window,
Window xwindow,
gulong serial)
gulong serial,
gboolean focused_by_us)
{
MetaWaylandCompositor *compositor;
display->focus_serial = serial;
display->focused_by_us = focused_by_us;
if (display->focus_xwindow == xwindow &&
display->focus_type == type &&
@ -1811,7 +1813,8 @@ request_xserver_input_focus_change (MetaDisplay *display,
type,
meta_window,
xwindow,
serial);
serial,
TRUE);
meta_error_trap_pop (display);
@ -1940,13 +1943,21 @@ handle_window_focus_event (MetaDisplay *display,
else
g_return_if_reached ();
if (display->server_focus_serial > display->focus_serial)
/* If display->focused_by_us, then the focus_serial will be used only
* for a focus change we made and have already accounted for.
* (See request_xserver_input_focus_change().) Otherwise, we can get
* multiple focus events with the same serial.
*/
if (display->server_focus_serial > display->focus_serial ||
(!display->focused_by_us &&
display->server_focus_serial == display->focus_serial))
{
update_focus_window (display,
type,
focus_window,
focus_window ? focus_window->xwindow : None,
display->server_focus_serial);
display->server_focus_serial,
FALSE);
}
}
@ -3185,7 +3196,8 @@ meta_display_handle_xevent (MetaDisplay *display,
display->current_time = event_get_time (display, event);
display->monitor_cache_invalidated = TRUE;
if (event->xany.serial > display->focus_serial &&
if (display->focused_by_us &&
event->xany.serial > display->focus_serial &&
display->focus_window &&
!window_has_xwindow (display->focus_window, display->server_focus_window))
{
@ -3195,7 +3207,8 @@ meta_display_handle_xevent (MetaDisplay *display,
META_FOCUS_NONE,
meta_display_lookup_x_window (display, display->server_focus_window),
display->server_focus_window,
display->server_focus_serial);
display->server_focus_serial,
FALSE);
}
screen = meta_display_screen_for_root (display, event->xany.window);