From 4179679239301a4479d246da9409c4b675a5e006 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Tue, 5 Sep 2023 00:54:04 +0200 Subject: [PATCH] x11: Adopt code to focus stage window on Clutter key focus We currently offer the mechanism for GNOME Shell to implement, and while this is not exercised often (our entries are typically surrounded by a ClutterGrab ensuring key events, so this is reserved to grab-less entries, probably there are some in extensions), this is arguably something Mutter should cover by itself without GNOME Shell guidance. This is only necessary on the X11 backend, although it is conceptually more tied to the MetaX11Display connection, so perform the focus tracking there only if not running as a Wayland compositor (i.e. --x11). This avoids the only case where the low-level meta_x11_display_set_input_focus_xwindow() function is used, or rather makes it completely a MetaX11Display implementation detail, leaving only the MetaDisplay API as the high-level entry points to handle window key focus. The public API that allowed GNOME Shell to implement these mechanisms is also gone in this commit. Part-of: --- src/compositor/compositor.c | 47 ------------------ src/meta/compositor-mutter.h | 7 --- src/x11/meta-x11-display-private.h | 4 -- src/x11/meta-x11-display.c | 80 +++++++++++++++++++++++++++++- 4 files changed, 79 insertions(+), 59 deletions(-) diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c index eb8dca7af..6fe6fadb9 100644 --- a/src/compositor/compositor.c +++ b/src/compositor/compositor.c @@ -330,53 +330,6 @@ meta_get_window_actors (MetaDisplay *display) return priv->windows; } -void -meta_focus_stage_window (MetaDisplay *display, - guint32 timestamp) -{ -#ifdef HAVE_X11_CLIENT - ClutterStage *stage; - Window window; - - stage = CLUTTER_STAGE (meta_get_stage_for_display (display)); - if (!stage) - return; - - window = meta_x11_get_stage_window (stage); - - if (window == None) - return; - - meta_x11_display_set_input_focus_xwindow (display->x11_display, - window, - timestamp); -#endif -} - -gboolean -meta_stage_is_focused (MetaDisplay *display) -{ - if (meta_is_wayland_compositor ()) - return TRUE; - -#ifdef HAVE_X11_CLIENT - ClutterStage *stage = CLUTTER_STAGE (meta_get_stage_for_display (display)); - Window window; - - if (!stage) - return FALSE; - - window = meta_x11_get_stage_window (stage); - - if (window == None) - return FALSE; - - return (display->x11_display->focus_xwindow == window); -#else - return FALSE; -#endif -} - void meta_compositor_grab_begin (MetaCompositor *compositor) { diff --git a/src/meta/compositor-mutter.h b/src/meta/compositor-mutter.h index a6064e11c..fac2d6467 100644 --- a/src/meta/compositor-mutter.h +++ b/src/meta/compositor-mutter.h @@ -49,10 +49,3 @@ void meta_disable_unredirect_for_display (MetaDisplay *display); META_EXPORT void meta_enable_unredirect_for_display (MetaDisplay *display); - -META_EXPORT -void meta_focus_stage_window (MetaDisplay *display, - guint32 timestamp); - -META_EXPORT -gboolean meta_stage_is_focused (MetaDisplay *display); diff --git a/src/x11/meta-x11-display-private.h b/src/x11/meta-x11-display-private.h index b0ed65ec9..0e8820d88 100644 --- a/src/x11/meta-x11-display-private.h +++ b/src/x11/meta-x11-display-private.h @@ -232,10 +232,6 @@ void meta_x11_display_create_guard_window (MetaX11Display *x11_display); guint32 meta_x11_display_get_current_time_roundtrip (MetaX11Display *x11_display); -void meta_x11_display_set_input_focus_xwindow (MetaX11Display *x11_display, - Window window, - guint32 timestamp); - int meta_x11_display_logical_monitor_to_xinerama_index (MetaX11Display *x11_display, MetaLogicalMonitor *logical_monitor); diff --git a/src/x11/meta-x11-display.c b/src/x11/meta-x11-display.c index 4e98203dd..17be6f4f2 100644 --- a/src/x11/meta-x11-display.c +++ b/src/x11/meta-x11-display.c @@ -105,6 +105,10 @@ static void meta_x11_display_init_frames_client (MetaX11Display *x11_display); static void meta_x11_display_remove_cursor_later (MetaX11Display *x11_display); +static void meta_x11_display_set_input_focus_xwindow (MetaX11Display *x11_display, + Window window, + guint32 timestamp); + static MetaBackend * backend_from_x11_display (MetaX11Display *x11_display) { @@ -1123,6 +1127,61 @@ on_frames_client_died (GObject *source, } } +#ifdef HAVE_X11 +static gboolean +stage_is_focused (MetaX11Display *x11_display) +{ + MetaDisplay *display = x11_display->display; + ClutterStage *stage = CLUTTER_STAGE (meta_get_stage_for_display (display)); + Window xwindow = meta_x11_get_stage_window (stage); + + return x11_display->focus_xwindow == xwindow; +} + +static void +on_focus_window_changed (MetaX11Display *x11_display) +{ + MetaDisplay *display = x11_display->display; + ClutterStage *stage = CLUTTER_STAGE (meta_get_stage_for_display (display)); + + if (!stage_is_focused (x11_display)) + clutter_stage_set_key_focus (stage, NULL); +} + +static void +on_stage_key_focus_changed (MetaX11Display *x11_display) +{ + MetaDisplay *display = x11_display->display; + ClutterStage *stage = CLUTTER_STAGE (meta_get_stage_for_display (display)); + ClutterActor *key_focus; + uint32_t timestamp; + gboolean has_actor_focus, has_stage_focus; + + key_focus = clutter_stage_get_key_focus (stage); + + has_actor_focus = key_focus != CLUTTER_ACTOR (stage); + has_stage_focus = stage_is_focused (x11_display); + if (has_actor_focus == has_stage_focus) + return; + + timestamp = meta_display_get_current_time_roundtrip (display); + + if (has_actor_focus) + { + Window xwindow; + + xwindow = meta_x11_get_stage_window (stage); + meta_x11_display_set_input_focus_xwindow (display->x11_display, + xwindow, + timestamp); + } + else + { + meta_display_focus_default_window (display, timestamp); + } +} +#endif + static void meta_x11_display_init_frames_client (MetaX11Display *x11_display) { @@ -1274,6 +1333,25 @@ meta_x11_display_new (MetaDisplay *display, G_CONNECT_SWAPPED); update_cursor_theme (x11_display); +#ifdef HAVE_XWAYLAND + if (!meta_is_wayland_compositor ()) +#endif + { + ClutterStage *stage = + CLUTTER_STAGE (meta_get_stage_for_display (display)); + + g_signal_connect_object (display, + "notify::focus-window", + G_CALLBACK (on_focus_window_changed), + x11_display, + G_CONNECT_SWAPPED); + g_signal_connect_object (stage, + "notify::key-focus", + G_CALLBACK (on_stage_key_focus_changed), + x11_display, + G_CONNECT_SWAPPED); + } + x11_display->xids = g_hash_table_new (meta_unsigned_long_hash, meta_unsigned_long_equal); x11_display->alarms = g_hash_table_new (meta_unsigned_long_hash, @@ -2032,7 +2110,7 @@ meta_x11_display_set_input_focus (MetaX11Display *x11_display, meta_x11_error_trap_pop (x11_display); } -void +static void meta_x11_display_set_input_focus_xwindow (MetaX11Display *x11_display, Window window, guint32 timestamp)