mirror of
https://github.com/brl/mutter.git
synced 2025-08-10 18:34:42 +00:00
display: clean up focus_window vs expected_focus_window
Mutter previously defined display->focus_window as the window that the server says is focused, but kept display->expected_focus_window to indicate the window that we have requested to be focused. But it turns out that "expected_focus_window" was almost always what we wanted. Make MetaDisplay do a better job of tracking focus-related requests and events, and change display->focus_window to be our best guess of the "currently" focused window (ie, the window that will be focused at the time when the server processes the next request we send it). https://bugzilla.gnome.org/show_bug.cgi?id=647706
This commit is contained in:

committed by
Jasper St. Pierre

parent
4f1d62170b
commit
7a4c808e43
@@ -1754,16 +1754,6 @@ meta_window_unmanage (MetaWindow *window,
|
||||
window,
|
||||
timestamp);
|
||||
}
|
||||
else if (window->display->expected_focus_window == window)
|
||||
{
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Focusing default window since expected focus window freed %s\n",
|
||||
window->desc);
|
||||
window->display->expected_focus_window = NULL;
|
||||
meta_workspace_focus_default_window (window->screen->active_workspace,
|
||||
window,
|
||||
timestamp);
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
@@ -1771,6 +1761,8 @@ meta_window_unmanage (MetaWindow *window,
|
||||
window->desc);
|
||||
}
|
||||
|
||||
g_assert (window->display->focus_window != window);
|
||||
|
||||
if (window->struts)
|
||||
{
|
||||
meta_free_gslist_and_elements (window->struts);
|
||||
@@ -1793,12 +1785,6 @@ meta_window_unmanage (MetaWindow *window,
|
||||
|
||||
g_assert (window->display->grab_window != window);
|
||||
|
||||
if (window->display->focus_window == window)
|
||||
{
|
||||
window->display->focus_window = NULL;
|
||||
g_object_notify (G_OBJECT (window->display), "focus-window");
|
||||
}
|
||||
|
||||
if (window->maximized_horizontally || window->maximized_vertically)
|
||||
unmaximize_window_before_freeing (window);
|
||||
|
||||
@@ -3332,14 +3318,7 @@ meta_window_hide (MetaWindow *window)
|
||||
invalidate_work_areas (window);
|
||||
}
|
||||
|
||||
/* The check on expected_focus_window is a temporary workaround for
|
||||
* https://bugzilla.gnome.org/show_bug.cgi?id=597352
|
||||
* We may have already switched away from this window but not yet
|
||||
* gotten FocusIn/FocusOut events. A more complete comprehensive
|
||||
* fix for these type of issues is described in the bug.
|
||||
*/
|
||||
if (window->has_focus &&
|
||||
window == window->display->expected_focus_window)
|
||||
if (window->has_focus)
|
||||
{
|
||||
MetaWindow *not_this_one = NULL;
|
||||
MetaWorkspace *my_workspace = meta_window_get_workspace (window);
|
||||
@@ -5975,10 +5954,10 @@ meta_window_focus (MetaWindow *window,
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Sending WM_TAKE_FOCUS to %s since take_focus = true\n",
|
||||
window->desc);
|
||||
meta_window_send_icccm_message (window,
|
||||
window->display->atom_WM_TAKE_FOCUS,
|
||||
timestamp);
|
||||
window->display->expected_focus_window = window;
|
||||
|
||||
meta_display_request_take_focus (window->display,
|
||||
window,
|
||||
timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6518,7 +6497,7 @@ meta_window_configure_request (MetaWindow *window,
|
||||
if (event->xconfigurerequest.value_mask & CWStackMode)
|
||||
{
|
||||
MetaWindow *active_window;
|
||||
active_window = window->display->expected_focus_window;
|
||||
active_window = window->display->focus_window;
|
||||
if (meta_prefs_get_disable_workarounds ())
|
||||
{
|
||||
meta_topic (META_DEBUG_STACK,
|
||||
@@ -7197,8 +7176,7 @@ meta_window_propagate_focus_appearance (MetaWindow *window,
|
||||
parent->attached_focus_window = NULL;
|
||||
}
|
||||
|
||||
if (child_focus_state_changed && !parent->has_focus &&
|
||||
parent != window->display->expected_focus_window)
|
||||
if (child_focus_state_changed && !parent->has_focus)
|
||||
{
|
||||
meta_window_appears_focused_changed (parent);
|
||||
}
|
||||
@@ -7208,18 +7186,12 @@ meta_window_propagate_focus_appearance (MetaWindow *window,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
meta_window_set_focused_internal (MetaWindow *window,
|
||||
gboolean focused)
|
||||
{
|
||||
if (focused)
|
||||
{
|
||||
if (window == window->display->focus_window)
|
||||
return;
|
||||
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"* Focus --> %s\n", window->desc);
|
||||
window->display->focus_window = window;
|
||||
window->has_focus = TRUE;
|
||||
|
||||
/* Move to the front of the focusing workspace's MRU list.
|
||||
@@ -7278,7 +7250,6 @@ meta_window_set_focused_internal (MetaWindow *window,
|
||||
meta_display_ungrab_focus_window_button (window->display, window);
|
||||
|
||||
g_signal_emit (window, window_signals[FOCUS], 0);
|
||||
g_object_notify (G_OBJECT (window->display), "focus-window");
|
||||
|
||||
if (!window->attached_focus_window)
|
||||
meta_window_appears_focused_changed (window);
|
||||
@@ -7287,12 +7258,7 @@ meta_window_set_focused_internal (MetaWindow *window,
|
||||
}
|
||||
else
|
||||
{
|
||||
if (window != window->display->focus_window)
|
||||
return;
|
||||
|
||||
meta_window_propagate_focus_appearance (window, FALSE);
|
||||
window->display->focus_window = NULL;
|
||||
g_object_notify (G_OBJECT (window->display), "focus-window");
|
||||
window->has_focus = FALSE;
|
||||
|
||||
if (!window->attached_focus_window)
|
||||
@@ -7313,115 +7279,6 @@ meta_window_set_focused_internal (MetaWindow *window,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_lost_focus (MetaWindow *window)
|
||||
{
|
||||
meta_window_set_focused_internal (window, FALSE);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_window_notify_focus (MetaWindow *window,
|
||||
XIEnterEvent *event)
|
||||
{
|
||||
/* note the event can be on either the window or the frame,
|
||||
* we focus the frame for shaded windows
|
||||
*/
|
||||
|
||||
/* The event can be FocusIn, FocusOut, or UnmapNotify.
|
||||
* On UnmapNotify we have to pretend it's focus out,
|
||||
* because we won't get a focus out if it occurs, apparently.
|
||||
*/
|
||||
|
||||
/* We ignore grabs, though this is questionable.
|
||||
* It may be better to increase the intelligence of
|
||||
* the focus window tracking.
|
||||
*
|
||||
* The problem is that keybindings for windows are done with
|
||||
* XGrabKey, which means focus_window disappears and the front of
|
||||
* the MRU list gets confused from what the user expects once a
|
||||
* keybinding is used.
|
||||
*/
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Focus %s event received on %s 0x%lx (%s) "
|
||||
"mode %s detail %s\n",
|
||||
event->evtype == XI_FocusIn ? "in" :
|
||||
event->evtype == XI_FocusOut ? "out" :
|
||||
"???",
|
||||
window->desc, event->event,
|
||||
event->event == window->xwindow ?
|
||||
"client window" :
|
||||
(window->frame && event->event == window->frame->xwindow) ?
|
||||
"frame window" :
|
||||
"unknown window",
|
||||
meta_event_mode_to_string (event->mode),
|
||||
meta_event_detail_to_string (event->detail));
|
||||
|
||||
/* FIXME our pointer tracking is broken; see how
|
||||
* gtk+/gdk/x11/gdkevents-x11.c or XFree86/xc/programs/xterm/misc.c
|
||||
* handle it for the correct way. In brief you need to track
|
||||
* pointer focus and regular focus, and handle EnterNotify in
|
||||
* PointerRoot mode with no window manager. However as noted above,
|
||||
* accurate focus tracking will break things because we want to keep
|
||||
* windows "focused" when using keybindings on them, and also we
|
||||
* sometimes "focus" a window by focusing its frame or
|
||||
* no_focus_window; so this all needs rethinking massively.
|
||||
*
|
||||
* My suggestion is to change it so that we clearly separate
|
||||
* actual keyboard focus tracking using the xterm algorithm,
|
||||
* and mutter's "pretend" focus window, and go through all
|
||||
* the code and decide which one should be used in each place;
|
||||
* a hard bit is deciding on a policy for that.
|
||||
*
|
||||
* http://bugzilla.gnome.org/show_bug.cgi?id=90382
|
||||
*/
|
||||
|
||||
if ((event->evtype == XI_FocusIn ||
|
||||
event->evtype == XI_FocusOut) &&
|
||||
(event->mode == NotifyGrab ||
|
||||
event->mode == NotifyUngrab ||
|
||||
/* From WindowMaker, ignore all funky pointer root events */
|
||||
event->detail > NotifyNonlinearVirtual))
|
||||
{
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Ignoring focus event generated by a grab or other weirdness\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (event->evtype == XI_FocusIn)
|
||||
{
|
||||
if (window->override_redirect)
|
||||
{
|
||||
window->display->focus_window = NULL;
|
||||
g_object_notify (G_OBJECT (window->display), "focus-window");
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_window_set_focused_internal (window, TRUE);
|
||||
}
|
||||
}
|
||||
else if (event->evtype == XI_FocusOut)
|
||||
{
|
||||
if (event->detail == NotifyInferior)
|
||||
{
|
||||
/* This event means the client moved focus to a subwindow */
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Ignoring focus out on %s with NotifyInferior\n",
|
||||
window->desc);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_window_set_focused_internal (window, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Now set _NET_ACTIVE_WINDOW hint */
|
||||
meta_display_update_active_window_hint (window->display);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
process_property_notify (MetaWindow *window,
|
||||
XPropertyEvent *event)
|
||||
|
Reference in New Issue
Block a user