summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVictor Kareh <[email protected]>2025-09-09 10:34:49 -0400
committerLuke from DC <[email protected]>2025-11-01 18:55:54 +0000
commit3261bbdce6cc0fa494c257849cb69c640f1aeade (patch)
treeb08c09c0f49f9f4b2b300eed6e68723b5ebe9e2b
parent158e2e64b7fe584ea8fe782e4608df25d6103fc3 (diff)
downloadmarco-3261bbdce6cc0fa494c257849cb69c640f1aeade.tar.bz2
marco-3261bbdce6cc0fa494c257849cb69c640f1aeade.tar.xz
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
-rw-r--r--src/core/frame-private.h4
-rw-r--r--src/core/frame.c46
-rw-r--r--src/core/window-private.h2
-rw-r--r--src/core/window.c36
-rw-r--r--src/include/common.h14
-rw-r--r--src/include/frame.h1
-rw-r--r--src/ui/theme.c50
-rw-r--r--src/ui/theme.h4
8 files changed, 126 insertions, 31 deletions
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.
*/
diff --git a/src/include/common.h b/src/include/common.h
index 031274f6..a0dfb69c 100644
--- a/src/include/common.h
+++ b/src/include/common.h
@@ -310,15 +310,11 @@ struct _MetaButtonLayout
typedef struct _MetaFrameBorders MetaFrameBorders;
struct _MetaFrameBorders
{
- /* The frame border is made up of two pieces - an inner visible portion
- * and an outer portion that is invisible but responds to events.
- */
- GtkBorder visible;
- GtkBorder invisible;
-
- /* For convenience, we have a "total" border which is equal to the sum
- * of the two borders above. */
- GtkBorder total;
+ GtkBorder visible; /* Visible window frame decoration */
+ GtkBorder shadow; /* Extra size needed for shadow */
+ GtkBorder resize; /* Extra size used for resize cursor area */
+ GtkBorder invisible; /* Max of shadow and resize borders */
+ GtkBorder total; /* Sum of visible and invisible borders */
};
/* sets all dimensions to zero */
diff --git a/src/include/frame.h b/src/include/frame.h
index 97314d4b..2deba88b 100644
--- a/src/include/frame.h
+++ b/src/include/frame.h
@@ -30,5 +30,6 @@
Window meta_frame_get_xwindow (MetaFrame *frame);
void meta_frame_calc_borders (MetaFrame *frame,
MetaFrameBorders *borders);
+void meta_frame_clear_cached_borders (MetaFrame *frame);
#endif
diff --git a/src/ui/theme.c b/src/ui/theme.c
index dadc9ab8..8bd144f2 100644
--- a/src/ui/theme.c
+++ b/src/ui/theme.c
@@ -328,10 +328,10 @@ meta_frame_layout_new (void)
layout->right_width = -1;
layout->bottom_height = -1;
- layout->invisible_border.left = 10;
- layout->invisible_border.right = 10;
- layout->invisible_border.bottom = 10;
- layout->invisible_border.top = 10;
+ layout->invisible_resize_border.left = 10;
+ layout->invisible_resize_border.right = 10;
+ layout->invisible_resize_border.bottom = 10;
+ layout->invisible_resize_border.top = 10;
init_border (&layout->title_border);
@@ -514,6 +514,7 @@ void
meta_frame_layout_get_borders (const MetaFrameLayout *layout,
int text_height,
MetaFrameFlags flags,
+ MetaFrameType type,
MetaFrameBorders *borders)
{
int buttons_height, title_height;
@@ -540,25 +541,52 @@ meta_frame_layout_get_borders (const MetaFrameLayout *layout,
borders->visible.right = layout->right_width;
borders->visible.bottom = layout->bottom_height;
+ borders->shadow.top = 0;
+ borders->shadow.left = 0;
+ borders->shadow.right = 0;
+ borders->shadow.bottom = 0;
+
if (flags & META_FRAME_ALLOWS_HORIZONTAL_RESIZE)
{
- borders->invisible.left = layout->invisible_border.left;
- borders->invisible.right = layout->invisible_border.right;
+ borders->resize.left = layout->invisible_resize_border.left;
+ borders->resize.right = layout->invisible_resize_border.right;
}
if (flags & META_FRAME_ALLOWS_VERTICAL_RESIZE)
{
- borders->invisible.bottom = layout->invisible_border.bottom;
- borders->invisible.top = layout->invisible_border.top;
+ borders->resize.bottom = layout->invisible_resize_border.bottom;
+
+ if (type != META_FRAME_TYPE_ATTACHED)
+ borders->resize.top = layout->invisible_resize_border.top;
}
- if (flags & META_FRAME_SHADED)
- borders->visible.bottom = borders->invisible.bottom = 0;
+ borders->invisible.left = MAX (borders->shadow.left, borders->resize.left);
+ borders->invisible.right = MAX (borders->shadow.right, borders->resize.right);
+ borders->invisible.bottom = MAX (borders->shadow.bottom, borders->resize.bottom);
+ borders->invisible.top = MAX (borders->shadow.top, borders->resize.top);
+
+ /* Maximized and tiled windows should not have invisible borders on the sides
+ * that touch the screen edges */
+ if (flags & (META_FRAME_MAXIMIZED | META_FRAME_TILED_LEFT | META_FRAME_TILED_RIGHT))
+ {
+ borders->invisible.top = 0;
+ borders->invisible.bottom = 0;
+ }
+ if (flags & (META_FRAME_MAXIMIZED | META_FRAME_TILED_LEFT))
+ borders->invisible.left = 0;
+ if (flags & (META_FRAME_MAXIMIZED | META_FRAME_TILED_RIGHT))
+ borders->invisible.right = 0;
+
+ if (type == META_FRAME_TYPE_ATTACHED)
+ borders->invisible.top = 0;
borders->total.left = borders->invisible.left + borders->visible.left;
borders->total.right = borders->invisible.right + borders->visible.right;
borders->total.bottom = borders->invisible.bottom + borders->visible.bottom;
borders->total.top = borders->invisible.top + borders->visible.top;
+
+ if (flags & META_FRAME_SHADED)
+ borders->visible.bottom = borders->invisible.bottom = 0;
}
static MetaButtonType
@@ -758,6 +786,7 @@ meta_frame_layout_calc_geometry (const MetaFrameLayout *layout,
meta_frame_layout_get_borders (layout, text_height,
flags,
+ META_FRAME_TYPE_NORMAL, /* Will be updated when type parameter is passed down */
&borders);
fgeom->borders = borders;
@@ -5947,6 +5976,7 @@ meta_theme_get_frame_borders (MetaTheme *theme,
meta_frame_layout_get_borders (style->layout,
text_height,
flags,
+ type,
borders);
}
diff --git a/src/ui/theme.h b/src/ui/theme.h
index b32690f1..c3c10810 100644
--- a/src/ui/theme.h
+++ b/src/ui/theme.h
@@ -92,8 +92,7 @@ struct _MetaFrameLayout
/** Size of bottom side */
int bottom_height;
- /** Invisible border */
- GtkBorder invisible_border;
+ GtkBorder invisible_resize_border;
/** Border of blue title region
* \bug (blue?!)
@@ -874,6 +873,7 @@ void meta_frame_layout_unref (MetaFrameLayout *layout)
void meta_frame_layout_get_borders (const MetaFrameLayout *layout,
int text_height,
MetaFrameFlags flags,
+ MetaFrameType type,
MetaFrameBorders *borders);
void meta_frame_layout_calc_geometry (const MetaFrameLayout *layout,
int text_height,