From 169dd2fb7add99af8da532504bf88d8faf1a4cdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Sat, 29 Jan 2022 00:49:50 +0100 Subject: [PATCH] window: Move some display level window processing to MetaDisplay meta_window_(un)queue() was implemented with global arrays in window.c that managed MetaLater handle IDs and lists of window queues. In order to rely less on scattered static variables and making it clearer that we're dealing with per display window management and not something specific to a single window, move the window resize/calc-showing queue management to MetaDisplay. Part-of: --- src/core/display-private.h | 8 + src/core/display.c | 203 ++++++++++++++++++++ src/core/meta-private-enums.h | 6 + src/core/stack.c | 2 + src/core/window-private.h | 17 +- src/core/window.c | 348 ++++------------------------------ src/x11/meta-x11-display.c | 23 +++ 7 files changed, 284 insertions(+), 323 deletions(-) diff --git a/src/core/display-private.h b/src/core/display-private.h index 6b7821412..e91d73035 100644 --- a/src/core/display-private.h +++ b/src/core/display-private.h @@ -432,4 +432,12 @@ gboolean meta_display_init_x11_finish (MetaDisplay *display, void meta_display_shutdown_x11 (MetaDisplay *display); +void meta_display_queue_window (MetaDisplay *display, + MetaWindow *window, + MetaQueueType queue_types); + +void meta_display_unqueue_window (MetaDisplay *display, + MetaWindow *window, + MetaQueueType queue_types); + #endif diff --git a/src/core/display.c b/src/core/display.c index be1d85b20..5f99578a6 100644 --- a/src/core/display.c +++ b/src/core/display.c @@ -124,6 +124,9 @@ typedef struct typedef struct _MetaDisplayPrivate { MetaContext *context; + + guint queue_later_ids[META_N_QUEUE_TYPES]; + GList *queue_windows[META_N_QUEUE_TYPES]; } MetaDisplayPrivate; G_DEFINE_TYPE_WITH_PRIVATE (MetaDisplay, meta_display, G_TYPE_OBJECT) @@ -163,6 +166,7 @@ enum WORKAREAS_CHANGED, CLOSING, INIT_XSERVER, + WINDOW_VISIBILITY_UPDATED, LAST_SIGNAL }; @@ -525,6 +529,16 @@ meta_display_class_init (MetaDisplayClass *klass) NULL, NULL, G_TYPE_BOOLEAN, 1, G_TYPE_TASK); + display_signals[WINDOW_VISIBILITY_UPDATED] = + g_signal_new ("window-visibility-updated", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, 3, + G_TYPE_POINTER, + G_TYPE_POINTER, + G_TYPE_POINTER); + g_object_class_install_property (object_class, PROP_COMPOSITOR_MODIFIERS, g_param_spec_flags ("compositor-modifiers", @@ -3933,3 +3947,192 @@ meta_display_get_selection (MetaDisplay *display) { return display->selection; } + +#ifdef WITH_VERBOSE_MODE +static const char* meta_window_queue_names[META_N_QUEUE_TYPES] = + { + "calc-showing", + "move-resize", + }; +#endif + +static int +window_stack_cmp (gconstpointer a, + gconstpointer b) +{ + MetaWindow *aw = (gpointer) a; + MetaWindow *bw = (gpointer) b; + + return meta_stack_windows_cmp (aw->display->stack, + aw, bw); +} + +static void +warn_on_incorrectly_unmanaged_window (MetaWindow *window) +{ + g_warn_if_fail (!window->unmanaging); +} + +static gboolean +update_window_visibilities_idle (gpointer user_data) +{ + MetaDisplay *display = META_DISPLAY (user_data); + MetaDisplayPrivate *priv = meta_display_get_instance_private (display); + int queue_idx; + g_autoptr (GList) windows = NULL; + g_autoptr (GList) unplaced = NULL; + g_autoptr (GList) should_show = NULL; + g_autoptr (GList) should_hide = NULL; + GList *l; + + COGL_TRACE_BEGIN_SCOPED (MetaDisplayUpdateVisibility, + "Display: Update visibility"); + + queue_idx = __builtin_ctz (META_QUEUE_CALC_SHOWING); + + windows = g_steal_pointer (&priv->queue_windows[queue_idx]); + priv->queue_later_ids[queue_idx] = 0; + + for (l = windows; l; l = l->next) + { + MetaWindow *window = l->data; + + if (!window->placed) + unplaced = g_list_prepend (unplaced, window); + else if (meta_window_should_be_showing (window)) + should_show = g_list_prepend (should_show, window); + else + should_hide = g_list_prepend (should_hide, window); + } + + /* Sort bottom to top */ + unplaced = g_list_sort (unplaced, window_stack_cmp); + should_hide = g_list_sort (should_hide, window_stack_cmp); + + /* Sort top to bottom */ + should_show = g_list_sort (should_show, window_stack_cmp); + should_show = g_list_reverse (should_show); + + COGL_TRACE_BEGIN (MetaDisplayShowUnplacedWindows, + "Display: Show unplaced windows"); + g_list_foreach (unplaced, (GFunc) meta_window_update_visibility, NULL); + COGL_TRACE_END (MetaDisplayShowUnplacedWindows); + + meta_stack_freeze (display->stack); + + COGL_TRACE_BEGIN (MetaDisplayShowWindows, "Display: Show windows"); + g_list_foreach (should_show, (GFunc) meta_window_update_visibility, NULL); + COGL_TRACE_END (MetaDisplayShowWindows); + + COGL_TRACE_BEGIN (MetaDisplayHideWindows, "Display: Show windows"); + g_list_foreach (should_hide, (GFunc) meta_window_update_visibility, NULL); + COGL_TRACE_END (MetaDisplayHideWindows); + + meta_stack_thaw (display->stack); + + g_list_foreach (windows, (GFunc) meta_window_clear_queued, NULL); + + g_signal_emit (display, display_signals[WINDOW_VISIBILITY_UPDATED], 0, + unplaced, should_show, should_hide); + + g_list_foreach (windows, (GFunc) warn_on_incorrectly_unmanaged_window, NULL); + + return G_SOURCE_REMOVE; +} + +static gboolean +move_resize_idle (gpointer user_data) +{ + MetaDisplay *display = META_DISPLAY (user_data); + MetaDisplayPrivate *priv = meta_display_get_instance_private (display); + int queue_idx; + g_autoptr (GList) windows = NULL; + + queue_idx = __builtin_ctz (META_QUEUE_MOVE_RESIZE); + + windows = g_steal_pointer (&priv->queue_windows[queue_idx]); + priv->queue_later_ids[queue_idx] = 0; + + g_list_foreach (windows, (GFunc) meta_window_update_layout, NULL); + g_list_foreach (windows, (GFunc) warn_on_incorrectly_unmanaged_window, NULL); + + return G_SOURCE_REMOVE; +} + +void +meta_display_queue_window (MetaDisplay *display, + MetaWindow *window, + MetaQueueType queue_types) +{ + MetaDisplayPrivate *priv = meta_display_get_instance_private (display); + MetaCompositor *compositor = display->compositor; + MetaLaters *laters = meta_compositor_get_laters (compositor); + int queue_idx; + + for (queue_idx = 0; queue_idx < META_N_QUEUE_TYPES; queue_idx++) + { + const MetaLaterType window_queue_later_when[META_N_QUEUE_TYPES] = + { + META_LATER_CALC_SHOWING, + META_LATER_RESIZE, + }; + + const GSourceFunc window_queue_later_handler[META_N_QUEUE_TYPES] = + { + update_window_visibilities_idle, + move_resize_idle, + }; + + if (!(queue_types & 1 << queue_idx)) + continue; + + meta_topic (META_DEBUG_WINDOW_STATE, + "Queueing %s for window '%s'", + meta_window_queue_names[queue_idx], + meta_window_get_description (window)); + + priv->queue_windows[queue_idx] = + g_list_prepend (priv->queue_windows[queue_idx], window); + + if (!priv->queue_later_ids[queue_idx]) + { + meta_laters_add (laters, + window_queue_later_when[queue_idx], + window_queue_later_handler[queue_idx], + display, NULL); + + } + } +} + +void +meta_display_unqueue_window (MetaDisplay *display, + MetaWindow *window, + MetaQueueType queue_types) +{ + MetaDisplayPrivate *priv = meta_display_get_instance_private (display); + MetaCompositor *compositor = display->compositor; + MetaLaters *laters = meta_compositor_get_laters (compositor); + int queue_idx; + + for (queue_idx = 0; queue_idx < META_N_QUEUE_TYPES; queue_idx++) + { + if (!(queue_types & 1 << queue_idx)) + continue; + + meta_topic (META_DEBUG_WINDOW_STATE, + "Unqueuing %s for window '%s'", + meta_window_queue_names[queue_idx], + window->desc); + + priv->queue_windows[queue_idx] = + g_list_remove (priv->queue_windows[queue_idx], window); + + if (!priv->queue_windows[queue_idx] && priv->queue_later_ids[queue_idx]) + { + meta_laters_remove (laters, + priv->queue_later_ids[queue_idx]); + priv->queue_later_ids[queue_idx] = 0; + } + } +} diff --git a/src/core/meta-private-enums.h b/src/core/meta-private-enums.h index 1a361c782..ae6a9bbe5 100644 --- a/src/core/meta-private-enums.h +++ b/src/core/meta-private-enums.h @@ -28,4 +28,10 @@ typedef enum _MetaX11DisplayPolicy META_X11_DISPLAY_POLICY_DISABLED, } MetaX11DisplayPolicy; +typedef enum +{ + META_QUEUE_CALC_SHOWING = 1 << 0, + META_QUEUE_MOVE_RESIZE = 1 << 1, +} MetaQueueType; + #endif /* META_PRIVATE_ENUMS_H */ diff --git a/src/core/stack.c b/src/core/stack.c index 1af59f5be..481e72232 100644 --- a/src/core/stack.c +++ b/src/core/stack.c @@ -416,6 +416,8 @@ meta_stack_thaw (MetaStack *stack) { g_return_if_fail (stack->freeze_count > 0); + COGL_TRACE_BEGIN_SCOPED (MetaStackThaw, "Stack: thaw"); + stack->freeze_count -= 1; meta_stack_changed (stack); meta_stack_update_window_tile_matches (stack, NULL); diff --git a/src/core/window-private.h b/src/core/window-private.h index 258445d98..ad1dd5a86 100644 --- a/src/core/window-private.h +++ b/src/core/window-private.h @@ -56,13 +56,7 @@ typedef enum META_CLIENT_TYPE_MAX_RECOGNIZED = 2 } MetaClientType; -typedef enum -{ - META_QUEUE_CALC_SHOWING = 1 << 0, - META_QUEUE_MOVE_RESIZE = 1 << 1, -} MetaQueueType; - -#define NUMBER_OF_QUEUES 2 +#define META_N_QUEUE_TYPES 2 typedef enum { @@ -397,9 +391,6 @@ struct _MetaWindow /* Are we in meta_window_new()? */ guint constructing : 1; - /* Are we in the various queues? (Bitfield: see META_WINDOW_IS_IN_QUEUE) */ - guint is_in_queues : NUMBER_OF_QUEUES; - /* Used by keybindings.c */ guint keys_grabbed : 1; /* normal keybindings grabbed */ guint grab_on_frame : 1; /* grabs are on the frame */ @@ -915,4 +906,10 @@ gboolean meta_window_unit_cgroup_equal (MetaWindow *window1, void meta_window_check_alive_on_event (MetaWindow *window, uint32_t timestamp); +void meta_window_update_visibility (MetaWindow *window); + +void meta_window_clear_queued (MetaWindow *window); + +void meta_window_update_layout (MetaWindow *window); + #endif diff --git a/src/core/window.c b/src/core/window.c index eacde2b47..4a0c6242e 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -109,8 +109,6 @@ #define SNAP_SECURITY_LABEL_PREFIX "snap." -static int destroying_windows_disallowed = 0; - /* Each window has a "stamp" which is a non-recycled 64-bit ID. They * start after the end of the XID space so that, for stacking * we can keep a guint64 that represents one or the other @@ -131,8 +129,6 @@ static void meta_window_save_rect (MetaWindow *window); static void ensure_mru_position_after (MetaWindow *window, MetaWindow *after_this_one); -static void meta_window_move_resize_now (MetaWindow *window); - static void meta_window_unqueue (MetaWindow *window, MetaQueueType queuebits); @@ -170,17 +166,12 @@ static MetaWindow * meta_window_find_tile_match (MetaWindow *window, MetaTileMode mode); static void update_edge_constraints (MetaWindow *window); -/* Idle handlers for the three queues (run with meta_later_add()). The - * "data" parameter in each case will be a GINT_TO_POINTER of the - * index into the queue arrays to use. - * - * TODO: Possibly there is still some code duplication among these, which we - * need to sort out at some point. - */ -static gboolean idle_calc_showing (gpointer data); -static gboolean idle_move_resize (gpointer data); +typedef struct _MetaWindowPrivate +{ + MetaQueueType queued_types; +} MetaWindowPrivate; -G_DEFINE_ABSTRACT_TYPE (MetaWindow, meta_window, G_TYPE_OBJECT); +G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaWindow, meta_window, G_TYPE_OBJECT) enum { @@ -1083,7 +1074,6 @@ _meta_window_shared_new (MetaDisplay *display, window->placed = ((window->mapped && !window->hidden) || window->override_redirect); window->denied_focus_and_not_transient = FALSE; window->unmanaging = FALSE; - window->is_in_queues = 0; window->keys_grabbed = FALSE; window->grab_on_frame = FALSE; window->all_keys_grabbed = FALSE; @@ -1458,10 +1448,6 @@ meta_window_unmanage (MetaWindow *window, meta_compositor_remove_window (window->display->compositor, window); window->known_to_compositor = FALSE; - if (destroying_windows_disallowed > 0) - meta_bug ("Tried to destroy window %s while destruction was not allowed", - window->desc); - meta_display_unregister_stamp (window->display, window->stamp); if (meta_prefs_get_attach_modal_dialogs ()) @@ -1774,289 +1760,65 @@ implement_showing (MetaWindow *window, sync_client_window_mapped (window); } -static void -meta_window_calc_showing (MetaWindow *window) +void +meta_window_update_visibility (MetaWindow *window) { implement_showing (window, meta_window_should_be_showing (window)); } -static guint queue_later[NUMBER_OF_QUEUES] = {}; -static GSList *queue_pending[NUMBER_OF_QUEUES] = {}; - -static int -stackcmp (gconstpointer a, gconstpointer b) +void +meta_window_clear_queued (MetaWindow *window) { - MetaWindow *aw = (gpointer) a; - MetaWindow *bw = (gpointer) b; + MetaWindowPrivate *priv = meta_window_get_instance_private (window); - return meta_stack_windows_cmp (aw->display->stack, - aw, bw); + priv->queued_types &= ~META_QUEUE_CALC_SHOWING; } -static gboolean -idle_calc_showing (gpointer data) -{ - MetaDisplay *display = meta_get_display (); - GSList *tmp; - GSList *copy; - GSList *should_show; - GSList *should_hide; - GSList *unplaced; - GSList *displays; - guint queue_index = GPOINTER_TO_INT (data); - - COGL_TRACE_BEGIN_SCOPED (MetaWindowCalcShowing, "Window: Calc showing"); - - g_return_val_if_fail (queue_pending[queue_index] != NULL, FALSE); - - meta_topic (META_DEBUG_WINDOW_STATE, - "Clearing the calc_showing queue"); - - /* Work with a copy, for reentrancy. The allowed reentrancy isn't - * complete; destroying a window while we're in here would result in - * badness. But it's OK to queue/unqueue calc_showings. - */ - copy = g_slist_copy (queue_pending[queue_index]); - g_slist_free (queue_pending[queue_index]); - queue_pending[queue_index] = NULL; - queue_later[queue_index] = 0; - - destroying_windows_disallowed += 1; - - /* We map windows from top to bottom and unmap from bottom to - * top, to avoid extra expose events. The exception is - * for unplaced windows, which have to be mapped from bottom to - * top so placement works. - */ - should_show = NULL; - should_hide = NULL; - unplaced = NULL; - displays = NULL; - - COGL_TRACE_BEGIN (MetaWindowCalcShowingCalc, "Window: Calc showing (calc)"); - - tmp = copy; - while (tmp != NULL) - { - MetaWindow *window; - - window = tmp->data; - - if (!window->placed) - unplaced = g_slist_prepend (unplaced, window); - else if (meta_window_should_be_showing (window)) - should_show = g_slist_prepend (should_show, window); - else - should_hide = g_slist_prepend (should_hide, window); - - tmp = tmp->next; - } - - /* bottom to top */ - unplaced = g_slist_sort (unplaced, stackcmp); - should_hide = g_slist_sort (should_hide, stackcmp); - /* top to bottom */ - should_show = g_slist_sort (should_show, stackcmp); - should_show = g_slist_reverse (should_show); - - COGL_TRACE_END (MetaWindowCalcShowingCalc); - - COGL_TRACE_BEGIN (MetaWindowCalcShowingUnplaced, - "Window: Calc showing (calc unplaced)"); - - tmp = unplaced; - while (tmp != NULL) - { - MetaWindow *window; - - window = tmp->data; - - meta_window_calc_showing (window); - - tmp = tmp->next; - } - - COGL_TRACE_END (MetaWindowCalcShowingUnplaced); - - meta_stack_freeze (display->stack); - - COGL_TRACE_BEGIN (MetaWindowCalcShowingShow, "Window: Calc showing (show)"); - tmp = should_show; - while (tmp != NULL) - { - MetaWindow *window; - - window = tmp->data; - - implement_showing (window, TRUE); - - tmp = tmp->next; - } - COGL_TRACE_END (MetaWindowCalcShowingShow); - - COGL_TRACE_BEGIN (MetaWindowCalcShowingHide, "Window: Calc showing (hide)"); - tmp = should_hide; - while (tmp != NULL) - { - MetaWindow *window; - - window = tmp->data; - - implement_showing (window, FALSE); - - tmp = tmp->next; - } - COGL_TRACE_END (MetaWindowCalcShowingHide); - - COGL_TRACE_BEGIN (MetaWindowCalcShowingSync, - "Window: Calc showing (sync stack)"); - meta_stack_thaw (display->stack); - COGL_TRACE_END (MetaWindowCalcShowingSync); - - tmp = copy; - while (tmp != NULL) - { - MetaWindow *window; - - window = tmp->data; - - /* important to set this here for reentrancy - - * if we queue a window again while it's in "copy", - * then queue_calc_showing will just return since - * we are still in the calc_showing queue - */ - window->is_in_queues &= ~META_QUEUE_CALC_SHOWING; - - tmp = tmp->next; - } - - if (meta_prefs_get_focus_mode () != G_DESKTOP_FOCUS_MODE_CLICK) - { - /* When display->mouse_mode is false, we want to ignore - * EnterNotify events unless they come from mouse motion. To do - * that, we set a sentinel property on the root window if we're - * not in mouse_mode. - */ - tmp = should_show; - while (tmp != NULL) - { - MetaWindow *window = tmp->data; - MetaDisplay *display = window->display; - - if (display->x11_display && !display->mouse_mode) - meta_x11_display_increment_focus_sentinel (display->x11_display); - - tmp = tmp->next; - } - } - - g_slist_free (copy); - - g_slist_free (unplaced); - g_slist_free (should_show); - g_slist_free (should_hide); - g_slist_free (displays); - - destroying_windows_disallowed -= 1; - - return FALSE; -} - -#ifdef WITH_VERBOSE_MODE -static const gchar* meta_window_queue_names[NUMBER_OF_QUEUES] = - {"calc_showing", "move_resize", }; -#endif - static void meta_window_unqueue (MetaWindow *window, - MetaQueueType queuebits) + MetaQueueType queue_types) { - int queuenum; + MetaWindowPrivate *priv = meta_window_get_instance_private (window); - for (queuenum = 0; queuenum < NUMBER_OF_QUEUES; queuenum++) - { - if ((queuebits & 1 << queuenum) && - (window->is_in_queues & 1 << queuenum)) - { + queue_types &= priv->queued_types; - meta_topic (META_DEBUG_WINDOW_STATE, - "Removing %s from the %s queue", - window->desc, - meta_window_queue_names[queuenum]); + if (!queue_types) + return; - queue_pending[queuenum] = g_slist_remove (queue_pending[queuenum], window); - window->is_in_queues &= ~(1 << queuenum); - - if (queue_pending[queuenum] == NULL && queue_later[queuenum] != 0) - { - meta_later_remove (queue_later[queuenum]); - queue_later[queuenum] = 0; - } - } - } + meta_display_unqueue_window (window->display, window, queue_types); + priv->queued_types &= ~queue_types; } static void meta_window_flush_calc_showing (MetaWindow *window) { - if (window->is_in_queues & META_QUEUE_CALC_SHOWING) + MetaWindowPrivate *priv = meta_window_get_instance_private (window); + + if (priv->queued_types & META_QUEUE_CALC_SHOWING) { meta_window_unqueue (window, META_QUEUE_CALC_SHOWING); - meta_window_calc_showing (window); + meta_window_update_visibility (window); } } void meta_window_queue (MetaWindow *window, - MetaQueueType queuebits) + MetaQueueType queue_types) { - unsigned int queuenum; + MetaWindowPrivate *priv = meta_window_get_instance_private (window); g_return_if_fail (!window->override_redirect || - (queuebits & META_QUEUE_MOVE_RESIZE) == 0); + (queue_types & META_QUEUE_MOVE_RESIZE) == 0); - for (queuenum = 0; queuenum < NUMBER_OF_QUEUES; queuenum++) - { - if (queuebits & 1 << queuenum) - { - const MetaLaterType window_queue_later_when[NUMBER_OF_QUEUES] = - { - META_LATER_CALC_SHOWING, - META_LATER_RESIZE, - }; + if (window->unmanaging) + return; - const GSourceFunc window_queue_later_handler[NUMBER_OF_QUEUES] = - { - idle_calc_showing, - idle_move_resize, - }; + queue_types &= ~priv->queued_types; + if (!queue_types) + return; - if (window->unmanaging) - break; - - if (window->is_in_queues & 1 << queuenum) - break; - - meta_topic (META_DEBUG_WINDOW_STATE, - "Putting %s in the %s queue", - window->desc, - meta_window_queue_names[queuenum]); - - window->is_in_queues |= 1 << queuenum; - - if (queue_later[queuenum] == 0) - { - queue_later[queuenum] = - meta_later_add (window_queue_later_when[queuenum], - window_queue_later_handler[queuenum], - GUINT_TO_POINTER (queuenum), - NULL); - } - - queue_pending[queuenum] = g_slist_prepend (queue_pending[queuenum], - window); - } - } + priv->queued_types |= queue_types; + meta_display_queue_window (window->display, window, queue_types); } static gboolean @@ -4090,7 +3852,7 @@ meta_window_move_resize_internal (MetaWindow *window, } /* If we did placement, then we need to save the position that the window - * was placed at to make sure that meta_window_move_resize_now places the + * was placed at to make sure that meta_window_update_layout() places the * window correctly. */ if (did_placement) @@ -4367,8 +4129,8 @@ meta_window_resize_frame_with_gravity (MetaWindow *window, meta_window_move_resize_internal (window, flags, gravity, rect); } -static void -meta_window_move_resize_now (MetaWindow *window) +void +meta_window_update_layout (MetaWindow *window) { meta_window_move_resize_frame (window, FALSE, window->unconstrained_rect.x, @@ -4377,46 +4139,6 @@ meta_window_move_resize_now (MetaWindow *window) window->unconstrained_rect.height); } -static gboolean -idle_move_resize (gpointer data) -{ - GSList *tmp; - GSList *copy; - guint queue_index = GPOINTER_TO_INT (data); - - meta_topic (META_DEBUG_GEOMETRY, "Clearing the move_resize queue"); - - /* Work with a copy, for reentrancy. The allowed reentrancy isn't - * complete; destroying a window while we're in here would result in - * badness. But it's OK to queue/unqueue move_resizes. - */ - copy = g_slist_copy (queue_pending[queue_index]); - g_slist_free (queue_pending[queue_index]); - queue_pending[queue_index] = NULL; - queue_later[queue_index] = 0; - - destroying_windows_disallowed += 1; - - tmp = copy; - while (tmp != NULL) - { - MetaWindow *window; - - window = tmp->data; - - /* As a side effect, sets window->move_resize_queued = FALSE */ - meta_window_move_resize_now (window); - - tmp = tmp->next; - } - - g_slist_free (copy); - - destroying_windows_disallowed -= 1; - - return FALSE; -} - void meta_window_get_gravity_position (MetaWindow *window, MetaGravity gravity, diff --git a/src/x11/meta-x11-display.c b/src/x11/meta-x11-display.c index 7b89cac24..d4b5ff425 100644 --- a/src/x11/meta-x11-display.c +++ b/src/x11/meta-x11-display.c @@ -1104,6 +1104,25 @@ meta_x11_init_gdk_display (GError **error) return TRUE; } +static void +on_window_visibility_updated (MetaDisplay *display, + GList *placed_windows, + GList *shown_windows, + GList *hidden_windows, + MetaX11Display *x11_display) +{ + GList *l; + + if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK) + return; + + if (display->mouse_mode) + return; + + for (l = shown_windows; l; l = l->next) + meta_x11_display_increment_focus_sentinel (x11_display); +} + /** * meta_x11_display_new: * @@ -1236,6 +1255,10 @@ meta_x11_display_new (MetaDisplay *display, GError **error) G_CALLBACK (update_cursor_theme), x11_display, G_CONNECT_SWAPPED); + g_signal_connect_object (display, + "window-visibility-updated", + G_CALLBACK (on_window_visibility_updated), + x11_display, 0); update_cursor_theme (x11_display);