From 3261bbdce6cc0fa494c257849cb69c640f1aeade Mon Sep 17 00:00:00 2001 From: Victor Kareh Date: Tue, 9 Sep 2025 10:34:49 -0400 Subject: theme: Include shadow and resize borders Extend MetaFrameBorders to include shadow and resize borders to calculate invisible border size. Also added border caching to prevent recalculating borders on every frame operation. This is a backport of the following commits from Metacity: - https://gitlab.gnome.org/GNOME/metacity/-/commit/21e664af - https://gitlab.gnome.org/GNOME/metacity/-/commit/3c6e269b - https://gitlab.gnome.org/GNOME/metacity/-/commit/700e87ea --- src/core/frame-private.h | 4 ++++ src/core/frame.c | 46 ++++++++++++++++++++++++++++++++++++++-------- src/core/window-private.h | 2 ++ src/core/window.c | 36 ++++++++++++++++++++++++++++++++++-- 4 files changed, 78 insertions(+), 10 deletions(-) (limited to 'src/core') diff --git a/src/core/frame-private.h b/src/core/frame-private.h index 8c2a2eeb..77216420 100644 --- a/src/core/frame-private.h +++ b/src/core/frame-private.h @@ -48,9 +48,13 @@ struct _MetaFrame int right_width; int bottom_height; + /* valid if borders_cached is set */ + MetaFrameBorders cached_borders; + guint mapped : 1; guint need_reapply_frame_shape : 1; guint is_flashing : 1; /* used by the visual bell flash */ + guint borders_cached : 1; }; void meta_window_ensure_frame (MetaWindow *window); diff --git a/src/core/frame.c b/src/core/frame.c index e1eec2a4..a8ba65c0 100644 --- a/src/core/frame.c +++ b/src/core/frame.c @@ -85,6 +85,7 @@ meta_window_ensure_frame (MetaWindow *window) frame->mapped = FALSE; frame->need_reapply_frame_shape = TRUE; frame->is_flashing = FALSE; + frame->borders_cached = FALSE; meta_verbose ("Frame geometry %d,%d %dx%d\n", frame->rect.x, frame->rect.y, @@ -302,22 +303,51 @@ meta_frame_get_flags (MetaFrame *frame) return flags; } +static void +clear_border (GtkBorder *border) +{ + border->left = 0; + border->right = 0; + border->top = 0; + border->bottom = 0; +} + void -meta_frame_borders_clear (MetaFrameBorders *self) +meta_frame_borders_clear (MetaFrameBorders *borders) { - self->visible.top = self->invisible.top = self->total.top = 0; - self->visible.bottom = self->invisible.bottom = self->total.bottom = 0; - self->visible.left = self->invisible.left = self->total.left = 0; - self->visible.right = self->invisible.right = self->total.right = 0; + clear_border (&borders->visible); + clear_border (&borders->shadow); + clear_border (&borders->resize); + clear_border (&borders->invisible); + clear_border (&borders->total); } void meta_frame_calc_borders (MetaFrame *frame, MetaFrameBorders *borders) { - meta_ui_get_frame_borders (frame->window->screen->ui, - frame->xwindow, - borders); + if (frame == NULL) + { + meta_frame_borders_clear (borders); + } + else + { + if (!frame->borders_cached) + { + meta_ui_get_frame_borders (frame->window->screen->ui, + frame->xwindow, + &frame->cached_borders); + frame->borders_cached = TRUE; + } + + *borders = frame->cached_borders; + } +} + +void +meta_frame_clear_cached_borders (MetaFrame *frame) +{ + frame->borders_cached = FALSE; } static gboolean diff --git a/src/core/window-private.h b/src/core/window-private.h index 52864a86..06d4fd65 100644 --- a/src/core/window-private.h +++ b/src/core/window-private.h @@ -687,6 +687,8 @@ const char* meta_window_get_startup_id (MetaWindow *window); void meta_window_recalc_features (MetaWindow *window); void meta_window_recalc_window_type (MetaWindow *window); +void meta_window_frame_size_changed (MetaWindow *window); + void meta_window_stack_just_below (MetaWindow *window, MetaWindow *below_this_one); diff --git a/src/core/window.c b/src/core/window.c index 050c89f8..ae0fa791 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -2593,6 +2593,8 @@ meta_window_maximize_internal (MetaWindow *window, window->maximized_vertically = window->maximized_vertically || maximize_vertically; + meta_window_frame_size_changed (window); + /* Fix for #336850: If the frame shape isn't reapplied, it is * possible that the frame will retains its rounded corners. That * happens if the client's size when maximized equals the unmaximized @@ -2725,6 +2727,13 @@ meta_window_tile (MetaWindow *window) */ meta_window_queue (window, META_QUEUE_MOVE_RESIZE); + /* Clear cached frame bounds that depend on invisible border calculations */ + if (window->frame_bounds) + { + cairo_region_destroy (window->frame_bounds); + window->frame_bounds = NULL; + } + set_allowed_actions_hint (window); } @@ -2808,6 +2817,8 @@ meta_window_unmaximize (MetaWindow *window, window->maximized_vertically = window->maximized_vertically && !unmaximize_vertically; + meta_window_frame_size_changed (window); + /* Unmaximize to the saved_rect position in the direction(s) * being unmaximized. */ @@ -2932,6 +2943,8 @@ meta_window_make_above (MetaWindow *window) meta_window_update_layer (window); meta_window_raise (window); set_net_wm_state (window); + + meta_window_frame_size_changed (window); } void @@ -2941,6 +2954,8 @@ meta_window_unmake_above (MetaWindow *window) meta_window_raise (window); meta_window_update_layer (window); set_net_wm_state (window); + + meta_window_frame_size_changed (window); } void @@ -3071,7 +3086,8 @@ meta_window_shade (MetaWindow *window, { window->shaded = TRUE; - meta_window_queue(window, META_QUEUE_MOVE_RESIZE | META_QUEUE_CALC_SHOWING); + meta_window_queue (window, META_QUEUE_MOVE_RESIZE | META_QUEUE_CALC_SHOWING); + meta_window_frame_size_changed (window); set_allowed_actions_hint (window); @@ -3096,7 +3112,9 @@ meta_window_unshade (MetaWindow *window, if (window->shaded) { window->shaded = FALSE; - meta_window_queue(window, META_QUEUE_MOVE_RESIZE | META_QUEUE_CALC_SHOWING); + + meta_window_queue (window, META_QUEUE_MOVE_RESIZE | META_QUEUE_CALC_SHOWING); + meta_window_frame_size_changed (window); set_allowed_actions_hint (window); @@ -4531,6 +4549,8 @@ window_stick_impl (MetaWindow *window) */ window->on_all_workspaces = TRUE; + meta_window_frame_size_changed (window); + /* We do, however, change the MRU lists of all the workspaces */ tmp = window->screen->workspaces; @@ -4561,6 +4581,8 @@ window_unstick_impl (MetaWindow *window) window->on_all_workspaces = FALSE; + meta_window_frame_size_changed (window); + /* Remove window from MRU lists that it doesn't belong in */ tmp = window->screen->workspaces; while (tmp) @@ -5587,6 +5609,7 @@ static void meta_window_appears_focused_changed (MetaWindow *window) { set_net_wm_state (window); + meta_window_frame_size_changed (window); if (window->frame) meta_frame_queue_draw (window->frame); @@ -6583,6 +6606,13 @@ recalc_window_type (MetaWindow *window) } } +void +meta_window_frame_size_changed (MetaWindow *window) +{ + if (window->frame) + meta_frame_clear_cached_borders (window->frame); +} + static void set_allowed_actions_hint (MetaWindow *window) { @@ -6877,6 +6907,8 @@ recalc_window_features (MetaWindow *window) old_always_sticky != window->always_sticky) set_allowed_actions_hint (window); + meta_window_frame_size_changed (window); + /* FIXME perhaps should ensure if we don't have a shade func, * we aren't shaded, etc. */ -- cgit v1.2.1