events: Ignore normal FocusIn events on the root window

GTK+ focuses its own windows with RevertToParent, which means that when
a GTK+ CSD window is destroyed, the X server will set the focus back to
the root window. The event stream that we is an UnmapNotify followed by
a FocusOut event. Our own UnmapNotify-handling code unmanages the window
and forcibly changes the focus to the next default window in the stack.

Since UnmapNotify events don't come with timestamps, we query for one,
and set the window focus using that.

But there's *still* a FocusOut event in the stack, with an older
timestamp and serial than our own focusing. We see this, throw it out
since it's older than the most recent focus, but then our own code that
notices the root has been focused kicks in and tries to focus the
default window... using a timestamp older than our most recent focusing.

meta_display_sanity_check_timestamps notices this, and (rightly so)
puts a warning in our face, telling something is awry.

Only let our workarounds kick in when the event is new enough, otherwise
our code will get confused over old events.

This stops the:

Window manager warning: last_focus_time (367917173) is greater than comparison timestamp (367917170).  This most likely represents a buggy client sending inaccurate timestamps in messages such as _NET_ACTIVE_WINDOW.  Trying to work around...

warning spam when closing a CSD window.
This commit is contained in:
Jasper St. Pierre 2014-09-16 20:16:23 -06:00
parent 35dd1e644d
commit ae292c856b

View File

@ -675,7 +675,7 @@ meta_spew_event (MetaDisplay *display,
g_free (extra);
}
static void
static gboolean
handle_window_focus_event (MetaDisplay *display,
MetaWindow *window,
XIEnterEvent *event)
@ -751,7 +751,7 @@ handle_window_focus_event (MetaDisplay *display,
{
meta_topic (META_DEBUG_FOCUS,
"Ignoring focus event generated by a grab or other weirdness\n");
return;
return FALSE;
}
if (event->evtype == XI_FocusIn)
@ -767,7 +767,7 @@ handle_window_focus_event (MetaDisplay *display,
/* This event means the client moved focus to a subwindow */
meta_topic (META_DEBUG_FOCUS,
"Ignoring focus out with NotifyInferior\n");
return;
return FALSE;
}
display->server_focus_window = None;
@ -775,7 +775,7 @@ handle_window_focus_event (MetaDisplay *display,
focus_window = NULL;
}
else
g_return_if_reached ();
g_assert_not_reached ();
/* If display->focused_by_us, then the focus_serial will be used only
* for a focus change we made and have already accounted for.
@ -791,6 +791,11 @@ handle_window_focus_event (MetaDisplay *display,
focus_window ? focus_window->xwindow : None,
display->server_focus_serial,
FALSE);
return TRUE;
}
else
{
return FALSE;
}
}
@ -874,13 +879,9 @@ handle_input_xevent (MetaDisplay *display,
break;
case XI_FocusIn:
case XI_FocusOut:
handle_window_focus_event (display, window, enter_event);
if (!window)
if (handle_window_focus_event (display, window, enter_event) &&
enter_event->event == enter_event->root)
{
/* Check if the window is a root window. */
if (enter_event->root != enter_event->event)
break;
if (enter_event->evtype == XI_FocusIn &&
enter_event->detail == XINotifyDetailNone)
{