diff --git a/src/core/display-private.h b/src/core/display-private.h index 86284fe10..3d2e08d5d 100644 --- a/src/core/display-private.h +++ b/src/core/display-private.h @@ -138,6 +138,14 @@ struct _MetaDisplay */ guint allow_terminal_deactivation : 1; + /* If true, server->focus_serial refers to us changing the focus; in + * this case, we can ignore focus events that have exactly focus_serial, + * since we take care to make another request immediately afterwards. + * But if focus is being changed by another client, we have to accept + * multiple events with the same serial. + */ + guint focused_by_us : 1; + guint static_gravity_works : 1; /*< private-ish >*/ diff --git a/src/core/display.c b/src/core/display.c index c9ffb4716..a9385156d 100644 --- a/src/core/display.c +++ b/src/core/display.c @@ -1865,9 +1865,11 @@ static void update_focus_window (MetaDisplay *display, MetaWindow *window, Window xwindow, - gulong serial) + gulong serial, + gboolean focused_by_us) { display->focus_serial = serial; + display->focused_by_us = focused_by_us; if (display->focus_xwindow == xwindow) return; @@ -1978,7 +1980,8 @@ request_xserver_input_focus_change (MetaDisplay *display, update_focus_window (display, meta_window, xwindow, - serial); + serial, + TRUE); meta_error_trap_pop (display); @@ -2092,12 +2095,20 @@ 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, focus_window, focus_window ? focus_window->xwindow : None, - display->server_focus_serial); + display->server_focus_serial, + FALSE); } } @@ -2167,7 +2178,8 @@ event_callback (XEvent *event, 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)) { @@ -2176,7 +2188,8 @@ event_callback (XEvent *event, update_focus_window (display, 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);