diff --git a/src/core/display-private.h b/src/core/display-private.h index 169682ee8..a8fa75363 100644 --- a/src/core/display-private.h +++ b/src/core/display-private.h @@ -145,6 +145,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 0f20d143b..455db3120 100644 --- a/src/core/display.c +++ b/src/core/display.c @@ -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);