summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/display-private.h8
-rw-r--r--src/core/display.c25
2 files changed, 27 insertions, 6 deletions
diff --git a/src/core/display-private.h b/src/core/display-private.h
index c9e919e4..b2ed8f38 100644
--- a/src/core/display-private.h
+++ b/src/core/display-private.h
@@ -128,6 +128,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;
+
/*< private-ish >*/
guint error_trap_synced_at_last_pop : 1;
MetaEventQueue *events;
diff --git a/src/core/display.c b/src/core/display.c
index 63a93b02..17324b5f 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -1423,9 +1423,11 @@ button_press_event_new (XEvent *xevent,
static void
update_focus_window (MetaDisplay *display,
MetaWindow *window,
- gulong serial)
+ gulong serial,
+ gboolean focused_by_us)
{
display->focus_serial = serial;
+ display->focused_by_us = focused_by_us;
if (window == display->focus_window)
return;
@@ -1535,7 +1537,8 @@ request_xserver_input_focus_change (MetaDisplay *display,
update_focus_window (display,
meta_window,
- serial);
+ serial,
+ TRUE);
meta_error_trap_pop (display);
@@ -1645,10 +1648,18 @@ 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,
- display->server_focus_serial);
+ display->server_focus_serial,
+ FALSE);
}
}
@@ -1693,7 +1704,8 @@ event_callback (XEvent *event,
display->current_time = event_get_time (display, event);
display->xinerama_cache_invalidated = TRUE;
- if (event->xany.serial > display->focus_serial &&
+ if (display->focused_by_us &&
+ event->xany.serial > display->focus_serial &&
display->focus_window &&
display->focus_window->xwindow != display->server_focus_window)
{
@@ -1701,7 +1713,8 @@ event_callback (XEvent *event,
display->focus_window->desc);
update_focus_window (display,
meta_display_lookup_x_window (display, display->server_focus_window),
- display->server_focus_serial);
+ display->server_focus_serial,
+ FALSE);
}
modified = event_get_modified_window (display, event);