From d797c19cf714a0184b1d60f211472558e299801e Mon Sep 17 00:00:00 2001 From: Olivier Fourdan Date: Mon, 24 Mar 2025 16:57:40 +0100 Subject: [PATCH] Backport the pre-configure mechanism Resolves: https://issues.redhat.com/browse/RHEL-84702 --- ...arely-used-macros-with-func-equivale.patch | 436 +++++++ ...ndow-Use-getter-for-fullscreen-state.patch | 304 +++++ 0003-window-Add-a-MetaWindowConfig-type.patch | 395 ++++++ 0004-window-Use-the-fullscreen-API.patch | 34 + 0005-window-Use-the-MetaWindowConfig.patch | 1068 +++++++++++++++++ 0006-window-Add-a-configure-signal.patch | 94 ++ ...dow-helper-function-for-MetaWindowCo.patch | 61 + ...onfiguration-Add-MetaWindowConfig-su.patch | 126 ++ 0009-wayland-Emit-the-configure-signal.patch | 54 + ...window-x11-Emit-the-configure-signal.patch | 115 ++ mutter.spec | 14 + 11 files changed, 2701 insertions(+) create mode 100644 0001-window-Replace-barely-used-macros-with-func-equivale.patch create mode 100644 0002-window-Use-getter-for-fullscreen-state.patch create mode 100644 0003-window-Add-a-MetaWindowConfig-type.patch create mode 100644 0004-window-Use-the-fullscreen-API.patch create mode 100644 0005-window-Use-the-MetaWindowConfig.patch create mode 100644 0006-window-Add-a-configure-signal.patch create mode 100644 0007-window-Add-a-window-helper-function-for-MetaWindowCo.patch create mode 100644 0008-wayland-window-configuration-Add-MetaWindowConfig-su.patch create mode 100644 0009-wayland-Emit-the-configure-signal.patch create mode 100644 0010-window-x11-Emit-the-configure-signal.patch diff --git a/0001-window-Replace-barely-used-macros-with-func-equivale.patch b/0001-window-Replace-barely-used-macros-with-func-equivale.patch new file mode 100644 index 0000000..3ef5969 --- /dev/null +++ b/0001-window-Replace-barely-used-macros-with-func-equivale.patch @@ -0,0 +1,436 @@ +From c28f4e53b548b8094ddb83e6e69be835d6133e49 Mon Sep 17 00:00:00 2001 +From: Bilal Elmoussaoui +Date: Mon, 28 Oct 2024 09:44:40 +0100 +Subject: [PATCH 01/10] window: Replace barely used macros with func + equivalents + +To avoid mostly going through struct fields in macros as we might soon +move those first to a WindowConfiguration & maybe even make the window +struct private with time. + +Part-of: +(cherry picked from commit 8e5433d82a3f737374316fef9ea76d60f1125752) +--- + src/compositor/edge-resistance.c | 4 +- + src/compositor/meta-window-drag.c | 19 +++++----- + src/core/constraints.c | 17 +++++---- + src/core/keybindings.c | 6 +-- + src/core/window-private.h | 31 ++++----------- + src/core/window.c | 57 ++++++++++++++++++++++++---- + src/wayland/meta-wayland-gtk-shell.c | 6 +-- + src/wayland/meta-wayland-xdg-shell.c | 2 +- + src/wayland/meta-window-wayland.c | 2 +- + src/x11/session.c | 2 +- + 10 files changed, 88 insertions(+), 58 deletions(-) + +diff --git a/src/compositor/edge-resistance.c b/src/compositor/edge-resistance.c +index 36b448f9ca..f5386e5de5 100644 +--- a/src/compositor/edge-resistance.c ++++ b/src/compositor/edge-resistance.c +@@ -485,7 +485,7 @@ apply_edge_resistance_to_each_side (MetaEdgeResistanceData *edge_data, + auto_snap = flags & META_EDGE_RESISTANCE_SNAP; + keyboard_op = flags & META_EDGE_RESISTANCE_KEYBOARD_OP; + +- if (auto_snap && !META_WINDOW_TILED_SIDE_BY_SIDE (window)) ++ if (auto_snap && !meta_window_is_tiled_side_by_side (window)) + { + /* Do the auto snapping instead of normal edge resistance; in all + * cases, we allow snapping to opposite kinds of edges (e.g. left +@@ -520,7 +520,7 @@ apply_edge_resistance_to_each_side (MetaEdgeResistanceData *edge_data, + FALSE, + keyboard_op); + } +- else if (auto_snap && META_WINDOW_TILED_SIDE_BY_SIDE (window)) ++ else if (auto_snap && meta_window_is_tiled_side_by_side (window)) + { + MtkRectangle workarea; + guint i; +diff --git a/src/compositor/meta-window-drag.c b/src/compositor/meta-window-drag.c +index 786bfda0f1..2638da59d3 100644 +--- a/src/compositor/meta-window-drag.c ++++ b/src/compositor/meta-window-drag.c +@@ -102,12 +102,12 @@ update_tile_preview_timeout (MetaWindowDrag *window_drag) + { + case META_TILE_LEFT: + case META_TILE_RIGHT: +- if (!META_WINDOW_TILED_SIDE_BY_SIDE (window)) ++ if (!meta_window_is_tiled_side_by_side (window)) + needs_preview = TRUE; + break; + + case META_TILE_MAXIMIZED: +- if (!META_WINDOW_MAXIMIZED (window)) ++ if (!meta_window_is_maximized (window)) + needs_preview = TRUE; + break; + +@@ -1247,8 +1247,8 @@ update_move (MetaWindowDrag *window_drag, + window->tile_monitor_number = -1; + } + else if (meta_prefs_get_edge_tiling () && +- !META_WINDOW_MAXIMIZED (window) && +- !META_WINDOW_TILED_SIDE_BY_SIDE (window)) ++ !meta_window_is_maximized (window) && ++ !meta_window_is_tiled_side_by_side (window)) + { + update_move_maybe_tile (window_drag, shake_threshold, x, y); + } +@@ -1258,8 +1258,9 @@ update_move (MetaWindowDrag *window_drag, + * loose via X motion. + */ + +- if ((META_WINDOW_MAXIMIZED (window) && ABS (dy) >= shake_threshold) || +- (META_WINDOW_TILED_SIDE_BY_SIDE (window) && (MAX (ABS (dx), ABS (dy)) >= shake_threshold))) ++ if ((meta_window_is_maximized (window) && ABS (dy) >= shake_threshold) || ++ (meta_window_is_tiled_side_by_side (window) && ++ (MAX (ABS (dx), ABS (dy)) >= shake_threshold))) + { + double prop; + +@@ -1294,7 +1295,7 @@ update_move (MetaWindowDrag *window_drag, + /* remaximize window on another monitor if window has been shaken + * loose or it is still maximized (then move straight) + */ +- else if ((window_drag->shaken_loose || META_WINDOW_MAXIMIZED (window)) && ++ else if ((window_drag->shaken_loose || meta_window_is_maximized (window)) && + window->tile_mode != META_TILE_LEFT && window->tile_mode != META_TILE_RIGHT) + { + MetaDisplay *display = meta_window_get_display (window); +@@ -1368,7 +1369,7 @@ update_move (MetaWindowDrag *window_drag, + meta_window_get_frame_rect (window, &old); + + /* Don't allow movement in the maximized directions or while tiled */ +- if (window->maximized_horizontally || META_WINDOW_TILED_SIDE_BY_SIDE (window)) ++ if (window->maximized_horizontally || meta_window_is_tiled_side_by_side (window)) + new_x = old.x; + if (window->maximized_vertically) + new_y = old.y; +@@ -1599,7 +1600,7 @@ maybe_maximize_tiled_window (MetaWindow *window) + MtkRectangle work_area; + gint shake_threshold; + +- if (!META_WINDOW_TILED_SIDE_BY_SIDE (window)) ++ if (!meta_window_is_tiled_side_by_side (window)) + return; + + shake_threshold = meta_prefs_get_drag_threshold (); +diff --git a/src/core/constraints.c b/src/core/constraints.c +index 4017ecbe07..6f20d087e2 100644 +--- a/src/core/constraints.c ++++ b/src/core/constraints.c +@@ -1217,15 +1217,16 @@ constrain_maximization (MetaWindow *window, + + /* Determine whether constraint applies; exit if it doesn't */ + if ((!window->maximized_horizontally && !window->maximized_vertically) || +- META_WINDOW_TILED_SIDE_BY_SIDE (window)) ++ meta_window_is_tiled_side_by_side (window)) + return TRUE; + + /* Calculate target_size = maximized size of (window + frame) */ +- if (META_WINDOW_TILED_MAXIMIZED (window)) ++ if (meta_window_is_maximized (window) && ++ window->tile_mode == META_TILE_MAXIMIZED) + { + meta_window_get_tile_area (window, window->tile_mode, &target_size); + } +- else if (META_WINDOW_MAXIMIZED (window)) ++ else if (meta_window_is_maximized (window)) + { + target_size = info->work_area_monitor; + } +@@ -1304,7 +1305,7 @@ constrain_tiling (MetaWindow *window, + return TRUE; + + /* Determine whether constraint applies; exit if it doesn't */ +- if (!META_WINDOW_TILED_SIDE_BY_SIDE (window)) ++ if (!meta_window_is_tiled_side_by_side (window)) + return TRUE; + + /* Calculate target_size - as the tile previews need this as well, we +@@ -1391,8 +1392,8 @@ constrain_size_increments (MetaWindow *window, + return TRUE; + + /* Determine whether constraint applies; exit if it doesn't */ +- if (META_WINDOW_MAXIMIZED (window) || window->fullscreen || +- META_WINDOW_TILED_SIDE_BY_SIDE (window) || ++ if (meta_window_is_maximized (window) || window->fullscreen || ++ meta_window_is_tiled_side_by_side (window) || + info->action_type == ACTION_MOVE) + return TRUE; + +@@ -1522,8 +1523,8 @@ constrain_aspect_ratio (MetaWindow *window, + (double)window->size_hints.max_aspect.y; + constraints_are_inconsistent = minr > maxr; + if (constraints_are_inconsistent || +- META_WINDOW_MAXIMIZED (window) || window->fullscreen || +- META_WINDOW_TILED_SIDE_BY_SIDE (window) || ++ meta_window_is_maximized (window) || window->fullscreen || ++ meta_window_is_tiled_side_by_side (window) || + info->action_type == ACTION_MOVE) + return TRUE; + +diff --git a/src/core/keybindings.c b/src/core/keybindings.c +index 1304531ef5..41559c9719 100644 +--- a/src/core/keybindings.c ++++ b/src/core/keybindings.c +@@ -2198,8 +2198,8 @@ handle_toggle_tiled (MetaDisplay *display, + { + MetaTileMode mode = binding->handler->data; + +- if ((META_WINDOW_TILED_LEFT (window) && mode == META_TILE_LEFT) || +- (META_WINDOW_TILED_RIGHT (window) && mode == META_TILE_RIGHT)) ++ if ((meta_window_is_tiled_left (window) && mode == META_TILE_LEFT) || ++ (meta_window_is_tiled_right (window) && mode == META_TILE_RIGHT)) + { + meta_window_untile (window); + } +@@ -2224,7 +2224,7 @@ handle_toggle_maximized (MetaDisplay *display, + MetaKeyBinding *binding, + gpointer user_data) + { +- if (META_WINDOW_MAXIMIZED (window)) ++ if (meta_window_is_maximized (window)) + meta_window_unmaximize (window, META_MAXIMIZE_BOTH); + else if (window->has_maximize_func) + meta_window_maximize (window, META_MAXIMIZE_BOTH); +diff --git a/src/core/window-private.h b/src/core/window-private.h +index 07fb4d68b5..856ce53c17 100644 +--- a/src/core/window-private.h ++++ b/src/core/window-private.h +@@ -630,29 +630,6 @@ struct _MetaWindowClass + MtkRoundingStrategy rounding_strategy); + }; + +-/* These differ from window->has_foo_func in that they consider +- * the dynamic window state such as "maximized", not just the +- * window's type +- */ +-#define META_WINDOW_MAXIMIZED(w) ((w)->maximized_horizontally && \ +- (w)->maximized_vertically) +-#define META_WINDOW_MAXIMIZED_VERTICALLY(w) ((w)->maximized_vertically) +-#define META_WINDOW_MAXIMIZED_HORIZONTALLY(w) ((w)->maximized_horizontally) +-#define META_WINDOW_TILED_SIDE_BY_SIDE(w) ((w)->maximized_vertically && \ +- !(w)->maximized_horizontally && \ +- (w)->tile_mode != META_TILE_NONE) +-#define META_WINDOW_TILED_LEFT(w) (META_WINDOW_TILED_SIDE_BY_SIDE(w) && \ +- (w)->tile_mode == META_TILE_LEFT) +-#define META_WINDOW_TILED_RIGHT(w) (META_WINDOW_TILED_SIDE_BY_SIDE(w) && \ +- (w)->tile_mode == META_TILE_RIGHT) +-#define META_WINDOW_TILED_MAXIMIZED(w)(META_WINDOW_MAXIMIZED(w) && \ +- (w)->tile_mode == META_TILE_MAXIMIZED) +-#define META_WINDOW_ALLOWS_MOVE(w) ((w)->has_move_func && !(w)->fullscreen) +-#define META_WINDOW_ALLOWS_RESIZE_EXCEPT_HINTS(w) ((w)->has_resize_func && !META_WINDOW_MAXIMIZED (w) && !(w)->fullscreen) +-#define META_WINDOW_ALLOWS_RESIZE(w) (META_WINDOW_ALLOWS_RESIZE_EXCEPT_HINTS (w) && \ +- (((w)->size_hints.min_width < (w)->size_hints.max_width) || \ +- ((w)->size_hints.min_height < (w)->size_hints.max_height))) +- + void meta_window_unmanage (MetaWindow *window, + guint32 timestamp); + void meta_window_queue (MetaWindow *window, +@@ -909,3 +886,11 @@ void meta_window_protocol_to_stage_point (MetaWindow *window, + int *stage_x, + int *stage_y, + MtkRoundingStrategy rounding_strategy); ++ ++gboolean meta_window_is_maximized (MetaWindow *window); ++ ++gboolean meta_window_is_tiled_side_by_side (MetaWindow *window); ++ ++gboolean meta_window_is_tiled_left (MetaWindow *window); ++ ++gboolean meta_window_is_tiled_right (MetaWindow *window); +diff --git a/src/core/window.c b/src/core/window.c +index 5af39137cb..b1d6426987 100644 +--- a/src/core/window.c ++++ b/src/core/window.c +@@ -2695,7 +2695,7 @@ ensure_size_hints_satisfied (MtkRectangle *rect, + static void + meta_window_save_rect (MetaWindow *window) + { +- if (!(META_WINDOW_MAXIMIZED (window) || META_WINDOW_TILED_SIDE_BY_SIDE (window) || window->fullscreen)) ++ if (!(meta_window_is_maximized (window) || meta_window_is_tiled_side_by_side (window) || window->fullscreen)) + { + /* save size/pos as appropriate args for move_resize */ + if (!window->maximized_horizontally) +@@ -2837,6 +2837,18 @@ meta_window_get_maximized (MetaWindow *window) + (window->maximized_vertically ? META_MAXIMIZE_VERTICAL : 0)); + } + ++/** ++ * meta_window_is_maximized: ++ * @window: a #MetaWindow ++ * ++ * Return value: %TRUE if the window is maximized vertically and horizontally. ++ */ ++gboolean ++meta_window_is_maximized (MetaWindow *window) ++{ ++ return (window->maximized_horizontally && window->maximized_vertically); ++} ++ + /** + * meta_window_is_fullscreen: + * @window: a #MetaWindow +@@ -2937,7 +2949,7 @@ meta_window_get_tile_fraction (MetaWindow *window, + *fraction = 1.; + else if (tile_match) + *fraction = 1. - tile_match->tile_hfraction; +- else if (META_WINDOW_TILED_SIDE_BY_SIDE (window)) ++ else if (meta_window_is_tiled_side_by_side (window)) + { + if (window->tile_mode != tile_mode) + *fraction = 1. - window->tile_hfraction; +@@ -2957,7 +2969,7 @@ meta_window_update_tile_fraction (MetaWindow *window, + MtkRectangle work_area; + MetaWindowDrag *window_drag; + +- if (!META_WINDOW_TILED_SIDE_BY_SIDE (window)) ++ if (!meta_window_is_tiled_side_by_side (window)) + return; + + meta_window_get_work_area_for_monitor (window, +@@ -3031,6 +3043,28 @@ update_edge_constraints (MetaWindow *window) + } + } + ++gboolean ++meta_window_is_tiled_side_by_side (MetaWindow *window) ++{ ++ return window->maximized_vertically && ++ !window->maximized_horizontally && ++ window->tile_mode != META_TILE_NONE; ++} ++ ++gboolean ++meta_window_is_tiled_left (MetaWindow *window) ++{ ++ return window->tile_mode == META_TILE_LEFT && ++ meta_window_is_tiled_side_by_side (window); ++} ++ ++gboolean ++meta_window_is_tiled_right (MetaWindow *window) ++{ ++ return window->tile_mode == META_TILE_RIGHT && ++ meta_window_is_tiled_side_by_side (window); ++} ++ + void + meta_window_untile (MetaWindow *window) + { +@@ -4269,7 +4303,7 @@ adjust_size_for_tile_match (MetaWindow *window, + MtkRectangle work_area, rect; + MetaWindow *tile_match = window->tile_match; + +- if (!META_WINDOW_TILED_SIDE_BY_SIDE (window) || !tile_match) ++ if (!meta_window_is_tiled_side_by_side (window) || !tile_match) + return; + + meta_window_get_work_area_for_monitor (window, window->tile_monitor_number, &work_area); +@@ -6077,7 +6111,7 @@ meta_window_get_default_layer (MetaWindow *window) + { + if (window->wm_state_below) + return META_LAYER_BOTTOM; +- else if (window->wm_state_above && !META_WINDOW_MAXIMIZED (window)) ++ else if (window->wm_state_above && !meta_window_is_maximized (window)) + return META_LAYER_TOP; + else if (window->type == META_WINDOW_DESKTOP) + return META_LAYER_DESKTOP; +@@ -7476,13 +7510,22 @@ meta_window_is_above (MetaWindow *window) + gboolean + meta_window_allows_move (MetaWindow *window) + { +- return META_WINDOW_ALLOWS_MOVE (window); ++ return window->has_move_func && !meta_window_is_fullscreen (window); + } + + gboolean + meta_window_allows_resize (MetaWindow *window) + { +- return META_WINDOW_ALLOWS_RESIZE (window); ++ gboolean allows_resize_except_hints, allows_resize; ++ ++ allows_resize_except_hints = window->has_resize_func && ++ !meta_window_is_maximized (window) && ++ !meta_window_is_fullscreen (window); ++ allows_resize = allows_resize_except_hints && ++ (window->size_hints.min_width < window->size_hints.max_width || ++ window->size_hints.min_height < window->size_hints.max_height); ++ ++ return allows_resize; + } + + void +diff --git a/src/wayland/meta-wayland-gtk-shell.c b/src/wayland/meta-wayland-gtk-shell.c +index 9d38dd5cb0..8a82d3507a 100644 +--- a/src/wayland/meta-wayland-gtk-shell.c ++++ b/src/wayland/meta-wayland-gtk-shell.c +@@ -261,7 +261,7 @@ gtk_surface_titlebar_gesture (struct wl_client *client, + if (!window->has_maximize_func) + break; + +- if (META_WINDOW_MAXIMIZED (window)) ++ if (meta_window_is_maximized (window)) + meta_window_unmaximize (window, META_MAXIMIZE_BOTH); + else + meta_window_maximize (window, META_MAXIMIZE_BOTH); +@@ -271,7 +271,7 @@ gtk_surface_titlebar_gesture (struct wl_client *client, + if (!window->has_maximize_func) + break; + +- if (META_WINDOW_MAXIMIZED_HORIZONTALLY (window)) ++ if (meta_window_get_maximized (window) & META_MAXIMIZE_HORIZONTAL) + meta_window_unmaximize (window, META_MAXIMIZE_HORIZONTAL); + else + meta_window_maximize (window, META_MAXIMIZE_HORIZONTAL); +@@ -281,7 +281,7 @@ gtk_surface_titlebar_gesture (struct wl_client *client, + if (!window->has_maximize_func) + break; + +- if (META_WINDOW_MAXIMIZED_VERTICALLY (window)) ++ if (meta_window_get_maximized (window) & META_MAXIMIZE_VERTICAL) + meta_window_unmaximize (window, META_MAXIMIZE_VERTICAL); + else + meta_window_maximize (window, META_MAXIMIZE_VERTICAL); +diff --git a/src/wayland/meta-wayland-xdg-shell.c b/src/wayland/meta-wayland-xdg-shell.c +index fccd91a593..48f110b7c3 100644 +--- a/src/wayland/meta-wayland-xdg-shell.c ++++ b/src/wayland/meta-wayland-xdg-shell.c +@@ -722,7 +722,7 @@ fill_states (MetaWaylandXdgToplevel *xdg_toplevel, + window_drag = + meta_compositor_get_current_window_drag (window->display->compositor); + +- if (META_WINDOW_MAXIMIZED (window)) ++ if (meta_window_is_maximized (window)) + add_state_value (states, XDG_TOPLEVEL_STATE_MAXIMIZED); + if (meta_window_is_fullscreen (window)) + add_state_value (states, XDG_TOPLEVEL_STATE_FULLSCREEN); +diff --git a/src/wayland/meta-window-wayland.c b/src/wayland/meta-window-wayland.c +index 1fd7a0752b..48a6122a30 100644 +--- a/src/wayland/meta-window-wayland.c ++++ b/src/wayland/meta-window-wayland.c +@@ -397,7 +397,7 @@ meta_window_wayland_move_resize_internal (MetaWindow *window, + int bounds_height; + + if (!meta_wayland_surface_get_buffer (wl_window->surface) && +- !META_WINDOW_MAXIMIZED (window) && ++ !meta_window_is_maximized (window) && + window->tile_mode == META_TILE_NONE && + !meta_window_is_fullscreen (window)) + return; +diff --git a/src/x11/session.c b/src/x11/session.c +index 19c0a0236a..fc720d9bc7 100644 +--- a/src/x11/session.c ++++ b/src/x11/session.c +@@ -1029,7 +1029,7 @@ save_state (MetaContext *context) + fputs (" \n", outfile); + + /* Maximized */ +- if (META_WINDOW_MAXIMIZED (window)) ++ if (meta_window_is_maximized (window)) + { + fprintf (outfile, + " \n", +-- +2.49.0 + diff --git a/0002-window-Use-getter-for-fullscreen-state.patch b/0002-window-Use-getter-for-fullscreen-state.patch new file mode 100644 index 0000000..3f81a67 --- /dev/null +++ b/0002-window-Use-getter-for-fullscreen-state.patch @@ -0,0 +1,304 @@ +From 427e528f20d5f45075112341fb3dc2a7952cc9b0 Mon Sep 17 00:00:00 2001 +From: Bilal Elmoussaoui +Date: Mon, 28 Oct 2024 10:03:02 +0100 +Subject: [PATCH 02/10] window: Use getter for fullscreen state + +Avoids going through struct field directly as we might replace that with +a WindowConfiguration type soon-ish. + +Part-of: +(cherry picked from commit 0f5ec2ec16da933272833322023578aa029b888a) +--- + src/core/constraints.c | 23 +++++++++++++---------- + src/core/display.c | 2 +- + src/core/keybindings.c | 2 +- + src/core/place.c | 2 +- + src/core/window.c | 22 ++++++++++++---------- + src/x11/window-x11.c | 11 ++++++----- + 6 files changed, 34 insertions(+), 28 deletions(-) + +diff --git a/src/core/constraints.c b/src/core/constraints.c +index 6f20d087e2..200da009db 100644 +--- a/src/core/constraints.c ++++ b/src/core/constraints.c +@@ -461,7 +461,8 @@ setup_constraint_info (MetaBackend *backend, + logical_monitor, + &info->work_area_monitor); + +- if (window->fullscreen && meta_window_has_fullscreen_monitors (window)) ++ if (meta_window_is_fullscreen (window) && ++ meta_window_has_fullscreen_monitors (window)) + { + info->entire_monitor = window->fullscreen_monitors.top->rect; + mtk_rectangle_union (&info->entire_monitor, +@@ -482,7 +483,7 @@ setup_constraint_info (MetaBackend *backend, + else + { + info->entire_monitor = logical_monitor->rect; +- if (window->fullscreen) ++ if (meta_window_is_fullscreen (window)) + meta_window_adjust_fullscreen_monitor_rect (window, &info->entire_monitor); + } + +@@ -551,7 +552,7 @@ place_window_if_needed (MetaWindow *window, + !(window->maximized_horizontally || + window->maximized_vertically) && + !window->minimized && +- !window->fullscreen) ++ !meta_window_is_fullscreen (window)) + { + MetaMonitorManager *monitor_manager = + meta_backend_get_monitor_manager (info->backend); +@@ -670,7 +671,7 @@ update_onscreen_requirements (MetaWindow *window, + * the application sends a bunch of configurerequest events). See + * #353699. + */ +- if (window->fullscreen) ++ if (meta_window_is_fullscreen (window)) + return; + + /* USABILITY NOTE: Naturally, I only want the require_fully_onscreen, +@@ -1166,7 +1167,7 @@ constrain_modal_dialog (MetaWindow *window, + meta_window_get_placement_rule (window)) + return TRUE; + +- if (window->fullscreen) ++ if (meta_window_is_fullscreen (window)) + return TRUE; + + /* We want to center the dialog on the parent, including the decorations +@@ -1354,7 +1355,7 @@ constrain_fullscreen (MetaWindow *window, + return TRUE; + + /* Determine whether constraint applies; exit if it doesn't */ +- if (!window->fullscreen) ++ if (!meta_window_is_fullscreen (window)) + return TRUE; + + monitor = info->entire_monitor; +@@ -1392,7 +1393,8 @@ constrain_size_increments (MetaWindow *window, + return TRUE; + + /* Determine whether constraint applies; exit if it doesn't */ +- if (meta_window_is_maximized (window) || window->fullscreen || ++ if (meta_window_is_maximized (window) || ++ meta_window_is_fullscreen (window) || + meta_window_is_tiled_side_by_side (window) || + info->action_type == ACTION_MOVE) + return TRUE; +@@ -1523,7 +1525,8 @@ constrain_aspect_ratio (MetaWindow *window, + (double)window->size_hints.max_aspect.y; + constraints_are_inconsistent = minr > maxr; + if (constraints_are_inconsistent || +- meta_window_is_maximized (window) || window->fullscreen || ++ meta_window_is_maximized (window) || ++ meta_window_is_fullscreen (window) || + meta_window_is_tiled_side_by_side (window) || + info->action_type == ACTION_MOVE) + return TRUE; +@@ -1765,7 +1768,7 @@ constrain_fully_onscreen (MetaWindow *window, + */ + if (window->type == META_WINDOW_DESKTOP || + window->type == META_WINDOW_DOCK || +- window->fullscreen || ++ meta_window_is_fullscreen (window) || + !window->require_fully_onscreen || + info->is_user_action || + meta_window_get_placement_rule (window)) +@@ -1828,7 +1831,7 @@ constrain_titlebar_visible (MetaWindow *window, + */ + if (window->type == META_WINDOW_DESKTOP || + window->type == META_WINDOW_DOCK || +- window->fullscreen || ++ meta_window_is_fullscreen (window) || + !window->require_titlebar_visible || + unconstrained_user_action || + user_nonnorthern_resize || +diff --git a/src/core/display.c b/src/core/display.c +index 2ab30028fc..6e38d1979d 100644 +--- a/src/core/display.c ++++ b/src/core/display.c +@@ -3156,7 +3156,7 @@ check_fullscreen_func (gpointer data) + if (window->hidden) + continue; + +- if (window->fullscreen) ++ if (meta_window_is_fullscreen (window)) + { + covers_monitors = TRUE; + } +diff --git a/src/core/keybindings.c b/src/core/keybindings.c +index 41559c9719..614c96423c 100644 +--- a/src/core/keybindings.c ++++ b/src/core/keybindings.c +@@ -2170,7 +2170,7 @@ handle_toggle_fullscreen (MetaDisplay *display, + MetaKeyBinding *binding, + gpointer user_data) + { +- if (window->fullscreen) ++ if (meta_window_is_fullscreen (window)) + meta_window_unmake_fullscreen (window); + else if (window->has_fullscreen_func) + meta_window_make_fullscreen (window); +diff --git a/src/core/place.c b/src/core/place.c +index d420479b5e..1c84994666 100644 +--- a/src/core/place.c ++++ b/src/core/place.c +@@ -945,7 +945,7 @@ meta_window_place (MetaWindow *window, + * be maximized. + */ + if (window->has_maximize_func && window->decorated && +- !window->fullscreen) ++ !meta_window_is_fullscreen (window)) + { + MtkRectangle workarea; + MtkRectangle frame_rect; +diff --git a/src/core/window.c b/src/core/window.c +index b1d6426987..1782c884fa 100644 +--- a/src/core/window.c ++++ b/src/core/window.c +@@ -1461,7 +1461,7 @@ meta_window_unmanage (MetaWindow *window, + meta_window_on_all_workspaces_changed (window); + + #ifdef HAVE_X11_CLIENT +- if (window->fullscreen) ++ if (meta_window_is_fullscreen (window)) + { + MetaGroup *group = NULL; + /* If the window is fullscreen, it may be forcing +@@ -2695,7 +2695,9 @@ ensure_size_hints_satisfied (MtkRectangle *rect, + static void + meta_window_save_rect (MetaWindow *window) + { +- if (!(meta_window_is_maximized (window) || meta_window_is_tiled_side_by_side (window) || window->fullscreen)) ++ if (!(meta_window_is_maximized (window) || ++ meta_window_is_tiled_side_by_side (window) || ++ meta_window_is_fullscreen (window))) + { + /* save size/pos as appropriate args for move_resize */ + if (!window->maximized_horizontally) +@@ -2897,7 +2899,7 @@ meta_window_is_monitor_sized (MetaWindow *window) + if (!window->monitor) + return FALSE; + +- if (window->fullscreen) ++ if (meta_window_is_fullscreen (window)) + return TRUE; + + if (meta_window_is_screen_sized (window)) +@@ -3396,7 +3398,7 @@ meta_window_set_above (MetaWindow *window, + void + meta_window_make_fullscreen_internal (MetaWindow *window) + { +- if (!window->fullscreen) ++ if (!meta_window_is_fullscreen (window)) + { + meta_topic (META_DEBUG_WINDOW_OPS, + "Fullscreening %s", window->desc); +@@ -3426,7 +3428,7 @@ meta_window_make_fullscreen (MetaWindow *window) + g_return_if_fail (META_IS_WINDOW (window)); + g_return_if_fail (!window->override_redirect); + +- if (!window->fullscreen) ++ if (!meta_window_is_fullscreen (window)) + { + MtkRectangle old_frame_rect, old_buffer_rect; + +@@ -3453,7 +3455,7 @@ meta_window_unmake_fullscreen (MetaWindow *window) + g_return_if_fail (META_IS_WINDOW (window)); + g_return_if_fail (!window->override_redirect); + +- if (window->fullscreen) ++ if (meta_window_is_fullscreen (window)) + { + MtkRectangle old_frame_rect, old_buffer_rect, target_rect; + gboolean has_target_size; +@@ -3526,7 +3528,7 @@ meta_window_update_fullscreen_monitors (MetaWindow *window, + meta_window_clear_fullscreen_monitors (window); + } + +- if (window->fullscreen) ++ if (meta_window_is_fullscreen (window)) + { + meta_window_queue(window, META_QUEUE_MOVE_RESIZE); + } +@@ -4291,7 +4293,7 @@ meta_window_move_to_monitor (MetaWindow *window, + window->preferred_logical_monitor = + meta_logical_monitor_dup_id (window->monitor); + +- if (window->fullscreen || window->override_redirect) ++ if (meta_window_is_fullscreen (window) || window->override_redirect) + meta_display_queue_check_fullscreen (window->display); + } + +@@ -5740,7 +5742,7 @@ meta_window_recalc_features (MetaWindow *window) + * is not resizable purely due to fullscreen, we don't want to + * disable fullscreen mode. + */ +- if (window->fullscreen) ++ if (meta_window_is_fullscreen (window)) + { + window->has_move_func = FALSE; + window->has_resize_func = FALSE; +@@ -5762,7 +5764,7 @@ meta_window_recalc_features (MetaWindow *window) + meta_topic (META_DEBUG_WINDOW_OPS, + "Window %s fullscreen = %d not resizable, maximizable = %d fullscreenable = %d min size %dx%d max size %dx%d", + window->desc, +- window->fullscreen, ++ meta_window_is_fullscreen (window), + window->has_maximize_func, window->has_fullscreen_func, + window->size_hints.min_width, + window->size_hints.min_height, +diff --git a/src/x11/window-x11.c b/src/x11/window-x11.c +index b4a5472c61..8157b1c013 100644 +--- a/src/x11/window-x11.c ++++ b/src/x11/window-x11.c +@@ -2362,7 +2362,7 @@ meta_window_x11_set_net_wm_state (MetaWindow *window) + data[i] = x11_display->atom__NET_WM_STATE_MAXIMIZED_VERT; + ++i; + } +- if (window->fullscreen) ++ if (meta_window_is_fullscreen (window)) + { + data[i] = x11_display->atom__NET_WM_STATE_FULLSCREEN; + ++i; +@@ -2417,7 +2417,7 @@ meta_window_x11_set_net_wm_state (MetaWindow *window) + + mtk_x11_error_trap_pop (x11_display->xdisplay); + +- if (window->fullscreen) ++ if (meta_window_is_fullscreen (window)) + { + if (meta_window_has_fullscreen_monitors (window)) + { +@@ -2993,7 +2993,7 @@ meta_window_move_resize_request (MetaWindow *window, + (window->decorated || !priv->has_custom_frame_extents) && + mtk_rectangle_equal (&rect, &monitor_rect) && + window->has_fullscreen_func && +- !window->fullscreen) ++ !meta_window_is_fullscreen (window)) + { + /* + meta_topic (META_DEBUG_GEOMETRY, +@@ -3432,7 +3432,8 @@ meta_window_x11_client_message (MetaWindow *window, + gboolean make_fullscreen; + + make_fullscreen = (action == _NET_WM_STATE_ADD || +- (action == _NET_WM_STATE_TOGGLE && !window->fullscreen)); ++ (action == _NET_WM_STATE_TOGGLE && ++ !meta_window_is_fullscreen (window))); + if (make_fullscreen && window->has_fullscreen_func) + meta_window_make_fullscreen (window); + else +@@ -4602,7 +4603,7 @@ meta_window_x11_can_unredirect (MetaWindowX11 *window_x11) + if (!window->monitor) + return FALSE; + +- if (window->fullscreen) ++ if (meta_window_is_fullscreen (window)) + return TRUE; + + if (meta_window_is_screen_sized (window)) +-- +2.49.0 + diff --git a/0003-window-Add-a-MetaWindowConfig-type.patch b/0003-window-Add-a-MetaWindowConfig-type.patch new file mode 100644 index 0000000..cace9e1 --- /dev/null +++ b/0003-window-Add-a-MetaWindowConfig-type.patch @@ -0,0 +1,395 @@ +From 22e88d1d773bd71a62b70115c6ad5909d3128671 Mon Sep 17 00:00:00 2001 +From: Olivier Fourdan +Date: Tue, 1 Oct 2024 15:49:34 +0200 +Subject: [PATCH 03/10] window: Add a MetaWindowConfig type + +This is intended to be used in place of the window rect and fullscreen +flags. + +That will also allow for a pre-configuration signal to be added, passing +the configuration so that a plugin can tweak the configuration before it +gets applied first. + +Part-of: +(cherry picked from commit 7e098ae671d1a580139fa65e18702d56f169082f) +--- + src/core/meta-window-config-private.h | 23 +++ + src/core/meta-window-config.c | 219 ++++++++++++++++++++++++++ + src/meson.build | 2 + + src/meta/meson.build | 1 + + src/meta/meta-window-config.h | 72 +++++++++ + src/meta/types.h | 1 + + 6 files changed, 318 insertions(+) + create mode 100644 src/core/meta-window-config-private.h + create mode 100644 src/core/meta-window-config.c + create mode 100644 src/meta/meta-window-config.h + +diff --git a/src/core/meta-window-config-private.h b/src/core/meta-window-config-private.h +new file mode 100644 +index 0000000000..ea34b69998 +--- /dev/null ++++ b/src/core/meta-window-config-private.h +@@ -0,0 +1,23 @@ ++/* ++ * Copyright (C) 2024 Red Hat Inc. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of the ++ * License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see . ++ * ++ */ ++ ++#pragma once ++ ++#include "meta/meta-window-config.h" ++ ++MetaWindowConfig * meta_window_config_initial_new (void); +diff --git a/src/core/meta-window-config.c b/src/core/meta-window-config.c +new file mode 100644 +index 0000000000..74f5aa81f4 +--- /dev/null ++++ b/src/core/meta-window-config.c +@@ -0,0 +1,219 @@ ++/* ++ * Copyright (C) 2024 Red Hat Inc. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of the ++ * License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see . ++ * ++ */ ++ ++#include "config.h" ++ ++#include "core/meta-window-config-private.h" ++ ++/** ++ * MetaWindowConfig: ++ * ++ * An object representing the configuration of a top-level window ++ * ++ */ ++struct _MetaWindowConfig ++{ ++ GObject parent; ++ ++ /* Whether this is an initial window configuration, cannot be changed by the callee */ ++ gboolean is_initial; ++ ++ /* The window geometry */ ++ MtkRectangle rect; ++ ++ gboolean is_fullscreen; ++}; ++ ++G_DEFINE_FINAL_TYPE (MetaWindowConfig, meta_window_config, G_TYPE_OBJECT) ++ ++enum ++{ ++ PROP_0, ++ ++ PROP_RECT, ++ PROP_IS_FULLSCREEN, ++ ++ PROP_LAST, ++}; ++ ++static GParamSpec *obj_props[PROP_LAST]; ++ ++static void ++meta_window_config_get_property (GObject *object, ++ guint prop_id, ++ GValue *value, ++ GParamSpec *pspec) ++{ ++ MetaWindowConfig *window_config = META_WINDOW_CONFIG (object); ++ ++ switch (prop_id) ++ { ++ case PROP_RECT: ++ g_value_set_boxed (value, &window_config->rect); ++ break; ++ case PROP_IS_FULLSCREEN: ++ g_value_set_boolean (value, window_config->is_fullscreen); ++ break; ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); ++ break; ++ } ++} ++ ++static void ++meta_window_config_set_property (GObject *object, ++ guint prop_id, ++ const GValue *value, ++ GParamSpec *pspec) ++{ ++ MetaWindowConfig *window_config = META_WINDOW_CONFIG (object); ++ MtkRectangle *rect; ++ ++ switch (prop_id) ++ { ++ case PROP_RECT: ++ rect = g_value_get_boxed (value); ++ window_config->rect = *rect; ++ break; ++ case PROP_IS_FULLSCREEN: ++ window_config->is_fullscreen = g_value_get_boolean (value); ++ break; ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); ++ break; ++ } ++} ++ ++static void ++meta_window_config_class_init (MetaWindowConfigClass *klass) ++{ ++ GObjectClass *object_class = G_OBJECT_CLASS (klass); ++ ++ object_class->get_property = meta_window_config_get_property; ++ object_class->set_property = meta_window_config_set_property; ++ ++ obj_props[PROP_RECT] = ++ g_param_spec_boxed ("rect", NULL, NULL, ++ MTK_TYPE_RECTANGLE, ++ G_PARAM_READWRITE | ++ G_PARAM_STATIC_STRINGS); ++ ++ obj_props[PROP_IS_FULLSCREEN] = ++ g_param_spec_boolean ("is-fullscreen", NULL, NULL, ++ FALSE, ++ G_PARAM_READWRITE | ++ G_PARAM_STATIC_STRINGS); ++ ++ g_object_class_install_properties (object_class, PROP_LAST, obj_props); ++} ++ ++static void ++meta_window_config_init (MetaWindowConfig *window_config) ++{ ++ window_config->rect = MTK_RECTANGLE_INIT (0, 0, 0, 0); ++} ++ ++gboolean ++meta_window_config_get_is_initial (MetaWindowConfig *window_config) ++{ ++ return window_config->is_initial; ++} ++ ++void ++meta_window_config_set_rect (MetaWindowConfig *window_config, ++ MtkRectangle rect) ++{ ++ window_config->rect = rect; ++} ++ ++MtkRectangle ++meta_window_config_get_rect (MetaWindowConfig *window_config) ++{ ++ return window_config->rect; ++} ++ ++void ++meta_window_config_set_is_fullscreen (MetaWindowConfig *window_config, ++ gboolean is_fullscreen) ++{ ++ window_config->is_fullscreen = is_fullscreen; ++} ++ ++void ++meta_window_config_get_position (MetaWindowConfig *window_config, ++ int *x, ++ int *y) ++{ ++ if (x) ++ *x = window_config->rect.x; ++ if (y) ++ *y = window_config->rect.y; ++} ++ ++void ++meta_window_config_set_position (MetaWindowConfig *window_config, ++ int x, ++ int y) ++{ ++ window_config->rect.x = x; ++ window_config->rect.y = y; ++} ++ ++void ++meta_window_config_get_size (MetaWindowConfig *window_config, ++ int *width, ++ int *height) ++{ ++ if (width) ++ *width = window_config->rect.width; ++ if (height) ++ *height = window_config->rect.height; ++} ++ ++void ++meta_window_config_set_size (MetaWindowConfig *window_config, ++ int width, ++ int height) ++{ ++ window_config->rect.width = width; ++ window_config->rect.height = height; ++} ++ ++gboolean ++meta_window_config_get_is_fullscreen (MetaWindowConfig *window_config) ++{ ++ return window_config->is_fullscreen; ++} ++ ++MetaWindowConfig * ++meta_window_config_new (void) ++{ ++ return g_object_new (META_TYPE_WINDOW_CONFIG, ++ NULL); ++} ++ ++MetaWindowConfig * ++meta_window_config_initial_new (void) ++{ ++ MetaWindowConfig *window_config; ++ ++ window_config = meta_window_config_new (); ++ window_config->is_initial = TRUE; ++ ++ return window_config; ++} +diff --git a/src/meson.build b/src/meson.build +index e3c92aaf27..cd47e10b98 100644 +--- a/src/meson.build ++++ b/src/meson.build +@@ -377,6 +377,8 @@ mutter_sources = [ + 'core/meta-sound-player.c', + 'core/meta-tablet-action-mapper.c', + 'core/meta-tool-action-mapper.c', ++ 'core/meta-window-config.c', ++ 'core/meta-window-config-private.h', + 'core/meta-workspace-manager.c', + 'core/meta-workspace-manager-private.h', + 'core/place.c', +diff --git a/src/meta/meson.build b/src/meta/meson.build +index 388b756682..bc9b82c8e1 100644 +--- a/src/meta/meson.build ++++ b/src/meta/meson.build +@@ -40,6 +40,7 @@ mutter_public_headers = [ + 'meta-stage.h', + 'meta-startup-notification.h', + 'meta-window-actor.h', ++ 'meta-window-config.h', + 'meta-window-group.h', + 'meta-workspace-manager.h', + 'prefs.h', +diff --git a/src/meta/meta-window-config.h b/src/meta/meta-window-config.h +new file mode 100644 +index 0000000000..4e9d8ad3c3 +--- /dev/null ++++ b/src/meta/meta-window-config.h +@@ -0,0 +1,72 @@ ++/* ++ * Copyright (C) 2024 Red Hat Inc. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of the ++ * License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see . ++ * ++ */ ++ ++#pragma once ++ ++#include ++ ++#include "meta/common.h" ++ ++#define META_TYPE_WINDOW_CONFIG (meta_window_config_get_type ()) ++ ++META_EXPORT ++G_DECLARE_FINAL_TYPE (MetaWindowConfig, ++ meta_window_config, ++ META, ++ WINDOW_CONFIG, ++ GObject) ++ ++META_EXPORT ++MetaWindowConfig *meta_window_config_new (void); ++ ++META_EXPORT ++gboolean meta_window_config_get_is_initial (MetaWindowConfig *window_config); ++ ++META_EXPORT ++void meta_window_config_set_rect (MetaWindowConfig *window_config, ++ MtkRectangle rect); ++ ++META_EXPORT ++MtkRectangle meta_window_config_get_rect (MetaWindowConfig *window_config); ++ ++META_EXPORT ++void meta_window_config_get_position (MetaWindowConfig *window_config, ++ int *x, ++ int *y); ++ ++META_EXPORT ++void meta_window_config_set_position (MetaWindowConfig *window_config, ++ int x, ++ int y); ++ ++META_EXPORT ++void meta_window_config_get_size (MetaWindowConfig *window_config, ++ int *width, ++ int *height); ++ ++META_EXPORT ++void meta_window_config_set_size (MetaWindowConfig *window_config, ++ int width, ++ int height); ++ ++META_EXPORT ++void meta_window_config_set_is_fullscreen (MetaWindowConfig *window_config, ++ gboolean is_fullscreen); ++ ++META_EXPORT ++gboolean meta_window_config_get_is_fullscreen (MetaWindowConfig *window_config); +diff --git a/src/meta/types.h b/src/meta/types.h +index 437ae609e2..cf7432ec48 100644 +--- a/src/meta/types.h ++++ b/src/meta/types.h +@@ -36,3 +36,4 @@ typedef struct _MetaSettings MetaSettings; + typedef struct _MetaWorkspaceManager MetaWorkspaceManager; + typedef struct _MetaSelection MetaSelection; + typedef struct _MetaDebugControl MetaDebugControl; ++typedef struct _MetaWindowConfig MetaWindowConfig; +-- +2.49.0 + diff --git a/0004-window-Use-the-fullscreen-API.patch b/0004-window-Use-the-fullscreen-API.patch new file mode 100644 index 0000000..ea49ba0 --- /dev/null +++ b/0004-window-Use-the-fullscreen-API.patch @@ -0,0 +1,34 @@ +From 83124a7df40d08b7731842a866adb7249cd44d13 Mon Sep 17 00:00:00 2001 +From: Olivier Fourdan +Date: Fri, 25 Oct 2024 16:46:40 +0200 +Subject: [PATCH 04/10] window: Use the fullscreen API + +Use the meta_window_is_fullscreen() API instead of accessing the +fullscreen field of the MetaWindow structure directly. + +This is both a (small) cleanup and preparation work for the next commit. + +No function change (intended). + +Part-of: +(cherry picked from commit a7ef0b137e194f970975e2653e89630df260348f) +--- + src/core/window.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/core/window.c b/src/core/window.c +index 1782c884fa..d803fbdc1d 100644 +--- a/src/core/window.c ++++ b/src/core/window.c +@@ -368,7 +368,7 @@ meta_window_get_property(GObject *object, + g_value_set_boolean (value, win->decorated); + break; + case PROP_FULLSCREEN: +- g_value_set_boolean (value, win->fullscreen); ++ g_value_set_boolean (value, meta_window_is_fullscreen (win)); + break; + case PROP_MAXIMIZED_HORIZONTALLY: + g_value_set_boolean (value, win->maximized_horizontally); +-- +2.49.0 + diff --git a/0005-window-Use-the-MetaWindowConfig.patch b/0005-window-Use-the-MetaWindowConfig.patch new file mode 100644 index 0000000..aeaff6a --- /dev/null +++ b/0005-window-Use-the-MetaWindowConfig.patch @@ -0,0 +1,1068 @@ +From d770ad9a7062dfac12a7e8e97219f112dcd08b59 Mon Sep 17 00:00:00 2001 +From: Olivier Fourdan +Date: Mon, 21 Oct 2024 11:11:32 +0200 +Subject: [PATCH 05/10] window: Use the MetaWindowConfig + +This is a fairly large refactoring to replace the window rect and +fullscreen flag with the new MetaWindowConfig object. + +No functional change intended at this point. + +Part-of: +(cherry picked from commit 4c20584b11cab3561c93db64960774f5c8cc2372) +--- + src/compositor/compositor.c | 4 +- + src/compositor/meta-window-actor-wayland.c | 6 +- + src/compositor/meta-window-drag.c | 7 +- + src/core/constraints.c | 16 ++-- + src/core/window-private.h | 8 +- + src/core/window.c | 76 +++++++++++------- + src/tests/wayland-unit-tests.c | 22 ++++-- + .../meta-wayland-window-configuration.c | 6 +- + src/wayland/meta-wayland-xdg-session-state.c | 8 +- + src/wayland/meta-wayland-xdg-shell.c | 4 +- + src/wayland/meta-window-wayland.c | 77 ++++++++++--------- + src/wayland/meta-xwayland-dnd.c | 2 +- + src/x11/meta-x11-frame.c | 2 +- + src/x11/window-props.c | 10 ++- + src/x11/window-x11.c | 52 +++++++------ + 15 files changed, 176 insertions(+), 124 deletions(-) + +diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c +index deac79f915..c9ec062d14 100644 +--- a/src/compositor/compositor.c ++++ b/src/compositor/compositor.c +@@ -1376,11 +1376,13 @@ meta_compositor_flash_window (MetaCompositor *compositor, + CLUTTER_ACTOR (meta_window_actor_from_window (window)); + ClutterActor *flash; + ClutterTransition *transition; ++ int width, height; + + flash = clutter_actor_new (); + clutter_actor_set_accessible_name (flash, "Flash actor"); + clutter_actor_set_background_color (flash, &COGL_COLOR_INIT (0, 0, 0, 255)); +- clutter_actor_set_size (flash, window->rect.width, window->rect.height); ++ meta_window_config_get_size (window->config, &width, &height); ++ clutter_actor_set_size (flash, width, height); + clutter_actor_set_position (flash, + window->custom_frame_extents.left, + window->custom_frame_extents.top); +diff --git a/src/compositor/meta-window-actor-wayland.c b/src/compositor/meta-window-actor-wayland.c +index 2af094e340..b2254df6e8 100644 +--- a/src/compositor/meta-window-actor-wayland.c ++++ b/src/compositor/meta-window-actor-wayland.c +@@ -548,6 +548,7 @@ maybe_configure_black_background (MetaWindowActorWayland *self, + ClutterActorIter iter; + float max_width = 0; + float max_height = 0; ++ int width, height; + + if (!meta_window_wayland_is_acked_fullscreen (META_WINDOW_WAYLAND (window))) + return FALSE; +@@ -584,8 +585,9 @@ maybe_configure_black_background (MetaWindowActorWayland *self, + + *surfaces_width = max_width; + *surfaces_height = max_height; +- *background_width = window->rect.width / geometry_scale; +- *background_height = window->rect.height / geometry_scale; ++ meta_window_config_get_size (window->config, &width, &height); ++ *background_width = width / geometry_scale; ++ *background_height = height / geometry_scale; + return TRUE; + } + +diff --git a/src/compositor/meta-window-drag.c b/src/compositor/meta-window-drag.c +index 2638da59d3..04391b6130 100644 +--- a/src/compositor/meta-window-drag.c ++++ b/src/compositor/meta-window-drag.c +@@ -891,9 +891,6 @@ process_keyboard_resize_grab (MetaWindowDrag *window_drag, + if (process_keyboard_resize_grab_op_change (window_drag, window, event)) + return TRUE; + +- width = window->rect.width; +- height = window->rect.height; +- + meta_window_get_frame_rect (window, &frame_rect); + width = frame_rect.width; + height = frame_rect.height; +@@ -1599,6 +1596,7 @@ maybe_maximize_tiled_window (MetaWindow *window) + { + MtkRectangle work_area; + gint shake_threshold; ++ int width; + + if (!meta_window_is_tiled_side_by_side (window)) + return; +@@ -1608,7 +1606,8 @@ maybe_maximize_tiled_window (MetaWindow *window) + meta_window_get_work_area_for_monitor (window, + window->tile_monitor_number, + &work_area); +- if (window->rect.width >= work_area.width - shake_threshold) ++ meta_window_config_get_size (window->config, &width, NULL); ++ if (width >= work_area.width - shake_threshold) + meta_window_maximize (window, META_MAXIMIZE_BOTH); + } + +diff --git a/src/core/constraints.c b/src/core/constraints.c +index 200da009db..9c287c668d 100644 +--- a/src/core/constraints.c ++++ b/src/core/constraints.c +@@ -560,10 +560,12 @@ place_window_if_needed (MetaWindow *window, + MtkRectangle placed_rect; + MetaWorkspace *cur_workspace; + MetaLogicalMonitor *logical_monitor; ++ int x, y; + ++ meta_window_config_get_position (window->config, &x, &y); + placed_rect = (MtkRectangle) { +- .x = window->rect.x, +- .y = window->rect.y, ++ .x = x, ++ .y = y, + .width = info->current.width, + .height = info->current.height + }; +@@ -897,6 +899,7 @@ constrain_custom_rule (MetaWindow *window, + gboolean constraint_satisfied; + MtkRectangle temporary_rect; + MtkRectangle adjusted_unconstrained; ++ MtkRectangle parent_rect; + int adjusted_rel_x; + int adjusted_rel_y; + MetaPlacementRule current_rule; +@@ -911,10 +914,11 @@ constrain_custom_rule (MetaWindow *window, + return TRUE; + + parent = meta_window_get_transient_for (window); ++ parent_rect = meta_window_config_get_rect (parent->config); + if (window->placement.state == META_PLACEMENT_STATE_CONSTRAINED_FINISHED) + { +- placement_rule->parent_rect.x = parent->rect.x; +- placement_rule->parent_rect.y = parent->rect.y; ++ placement_rule->parent_rect.x = parent_rect.x; ++ placement_rule->parent_rect.y = parent_rect.y; + } + parent_x = placement_rule->parent_rect.x; + parent_y = placement_rule->parent_rect.y; +@@ -938,8 +942,8 @@ constrain_custom_rule (MetaWindow *window, + case META_PLACEMENT_STATE_CONSTRAINED_FINISHED: + case META_PLACEMENT_STATE_INVALIDATED: + temporary_rect = (MtkRectangle) { +- .x = parent->rect.x + window->placement.current.rel_x, +- .y = parent->rect.y + window->placement.current.rel_y, ++ .x = parent_rect.x + window->placement.current.rel_x, ++ .y = parent_rect.y + window->placement.current.rel_y, + .width = info->current.width, + .height = info->current.height, + }; +diff --git a/src/core/window-private.h b/src/core/window-private.h +index 856ce53c17..a03b156d67 100644 +--- a/src/core/window-private.h ++++ b/src/core/window-private.h +@@ -38,6 +38,7 @@ + #include "meta/meta-close-dialog.h" + #include "meta/util.h" + #include "meta/window.h" ++#include "meta/meta-window-config.h" + #include "wayland/meta-wayland-types.h" + + typedef struct _MetaWindowQueue MetaWindowQueue; +@@ -311,8 +312,8 @@ struct _MetaWindow + * comment at the top of meta_window_move_resize_internal() for more + * information. */ + +- /* The current window geometry of the window. */ +- MtkRectangle rect; ++ /* The current configuration of the window. */ ++ MetaWindowConfig *config; + + /* The geometry to restore when we unmaximize. */ + MtkRectangle saved_rect; +@@ -401,9 +402,6 @@ struct _MetaWindow + * that to toggle between normal/tiled or maximized/tiled states. */ + guint saved_maximize : 1; + +- /* Whether we're fullscreen */ +- guint fullscreen : 1; +- + /* Whether the window is marked as urgent */ + guint urgent : 1; + +diff --git a/src/core/window.c b/src/core/window.c +index d803fbdc1d..e9c005aeca 100644 +--- a/src/core/window.c ++++ b/src/core/window.c +@@ -331,6 +331,8 @@ meta_window_finalize (GObject *object) + g_clear_pointer (&window->preferred_logical_monitor, + meta_logical_monitor_id_free); + ++ g_clear_object (&window->config); ++ + g_free (window->startup_id); + g_free (window->role); + g_free (window->res_class); +@@ -1021,6 +1023,7 @@ meta_window_constructed (GObject *object) + MetaContext *context = meta_display_get_context (display); + MetaBackend *backend = meta_context_get_backend (context); + MetaWorkspaceManager *workspace_manager = display->workspace_manager; ++ MtkRectangle frame_rect; + + COGL_TRACE_BEGIN_SCOPED (MetaWindowSharedInit, + "Meta::Window::constructed()"); +@@ -1041,9 +1044,10 @@ meta_window_constructed (GObject *object) + meta_window_set_normal_hints (window, NULL); + + /* And this is our unmaximized size */ +- window->saved_rect = window->rect; +- window->saved_rect_fullscreen = window->rect; +- window->unconstrained_rect = window->rect; ++ frame_rect = meta_window_config_get_rect (window->config); ++ window->saved_rect = frame_rect; ++ window->saved_rect_fullscreen = frame_rect; ++ window->unconstrained_rect = frame_rect; + + window->title = NULL; + +@@ -1055,7 +1059,7 @@ meta_window_constructed (GObject *object) + window->maximize_horizontally_after_placement = FALSE; + window->maximize_vertically_after_placement = FALSE; + window->minimize_after_placement = FALSE; +- window->fullscreen = FALSE; ++ meta_window_config_set_is_fullscreen (window->config, FALSE); + window->require_fully_onscreen = TRUE; + window->require_on_single_monitor = TRUE; + window->require_titlebar_visible = TRUE; +@@ -1133,7 +1137,7 @@ meta_window_constructed (GObject *object) + + window->compositor_private = NULL; + +- if (window->rect.width > 0 && window->rect.height > 0) ++ if (frame_rect.width > 0 && frame_rect.height > 0) + { + window->monitor = meta_window_find_monitor_from_frame_rect (window); + window->highest_scale_monitor = +@@ -2076,6 +2080,7 @@ window_would_mostly_be_covered_by_always_above_window (MetaWindow *window) + GList *l; + g_autoptr (MtkRegion) region = NULL; + int window_area, intersection_area, visible_area; ++ MtkRectangle frame_rect; + + region = mtk_region_create (); + windows = meta_workspace_list_windows (workspace); +@@ -2083,13 +2088,15 @@ window_would_mostly_be_covered_by_always_above_window (MetaWindow *window) + { + MetaWindow *other_window = l->data; + ++ frame_rect = meta_window_config_get_rect (other_window->config); + if (other_window->wm_state_above && other_window != window) +- mtk_region_union_rectangle (region, &other_window->rect); ++ mtk_region_union_rectangle (region, &frame_rect); + } + +- window_area = window->rect.width * window->rect.height; ++ frame_rect = meta_window_config_get_rect (window->config); ++ window_area = frame_rect.width * frame_rect.height; + +- mtk_region_intersect_rectangle (region, &window->rect); ++ mtk_region_intersect_rectangle (region, &frame_rect); + intersection_area = calculate_region_area (region); + visible_area = window_area - intersection_area; + +@@ -2333,10 +2340,12 @@ meta_window_show (MetaWindow *window) + window->has_maximize_func) + { + MtkRectangle work_area; ++ MtkRectangle frame_rect; + int window_area; + int work_area_area; + +- window_area = window->rect.width * window->rect.height; ++ frame_rect = meta_window_config_get_rect (window->config); ++ window_area = frame_rect.width * frame_rect.height; + meta_window_get_work_area_current_monitor (window, &work_area); + work_area_area = work_area.width * work_area.height; + +@@ -2699,16 +2708,19 @@ meta_window_save_rect (MetaWindow *window) + meta_window_is_tiled_side_by_side (window) || + meta_window_is_fullscreen (window))) + { ++ MtkRectangle frame_rect; ++ ++ frame_rect = meta_window_config_get_rect (window->config); + /* save size/pos as appropriate args for move_resize */ + if (!window->maximized_horizontally) + { +- window->saved_rect.x = window->rect.x; +- window->saved_rect.width = window->rect.width; ++ window->saved_rect.x = frame_rect.x; ++ window->saved_rect.width = frame_rect.width; + } + if (!window->maximized_vertically) + { +- window->saved_rect.y = window->rect.y; +- window->saved_rect.height = window->rect.height; ++ window->saved_rect.y = frame_rect.y; ++ window->saved_rect.height = frame_rect.height; + } + } + } +@@ -2860,7 +2872,7 @@ meta_window_is_maximized (MetaWindow *window) + gboolean + meta_window_is_fullscreen (MetaWindow *window) + { +- return window->fullscreen; ++ return meta_window_config_get_is_fullscreen (window->config); + } + + /** +@@ -3192,7 +3204,7 @@ unmaximize_window_before_freeing (MetaWindow *window) + + if (window->withdrawn) /* See bug #137185 */ + { +- window->rect = window->saved_rect; ++ meta_window_config_set_rect (window->config, window->saved_rect); + set_net_wm_state (window); + } + #ifdef HAVE_WAYLAND +@@ -3403,9 +3415,9 @@ meta_window_make_fullscreen_internal (MetaWindow *window) + meta_topic (META_DEBUG_WINDOW_OPS, + "Fullscreening %s", window->desc); + +- window->saved_rect_fullscreen = window->rect; ++ window->saved_rect_fullscreen = meta_window_config_get_rect (window->config); + +- window->fullscreen = TRUE; ++ meta_window_config_set_is_fullscreen (window->config, TRUE); + + meta_stack_freeze (window->display->stack); + +@@ -3463,7 +3475,7 @@ meta_window_unmake_fullscreen (MetaWindow *window) + meta_topic (META_DEBUG_WINDOW_OPS, + "Unfullscreening %s", window->desc); + +- window->fullscreen = FALSE; ++ meta_window_config_set_is_fullscreen (window->config, FALSE); + target_rect = window->saved_rect_fullscreen; + + meta_window_frame_size_changed (window); +@@ -3693,11 +3705,14 @@ meta_window_updates_are_frozen (MetaWindow *window) + static void + meta_window_reposition (MetaWindow *window) + { ++ MtkRectangle frame_rect; ++ ++ frame_rect = meta_window_config_get_rect (window->config); + meta_window_move_resize (window, + (META_MOVE_RESIZE_MOVE_ACTION | + META_MOVE_RESIZE_RESIZE_ACTION | + META_MOVE_RESIZE_CONSTRAIN), +- window->rect); ++ frame_rect); + } + + static gboolean +@@ -3863,6 +3878,7 @@ meta_window_update_monitor (MetaWindow *window, + { + MetaWorkspaceManager *workspace_manager = window->display->workspace_manager; + const MetaLogicalMonitor *old, *old_highest_scale; ++ int frame_width, frame_height; + + old = window->monitor; + META_WINDOW_GET_CLASS (window)->update_main_monitor (window, flags); +@@ -3895,8 +3911,9 @@ meta_window_update_monitor (MetaWindow *window, + } + + old_highest_scale = window->highest_scale_monitor; ++ meta_window_config_get_size (window->config, &frame_width, &frame_height); + +- window->highest_scale_monitor = window->rect.width > 0 && window->rect.height > 0 ++ window->highest_scale_monitor = frame_width > 0 && frame_height > 0 + ? meta_window_find_highest_scale_monitor_from_frame_rect (window) + : window->monitor; + +@@ -3935,6 +3952,7 @@ meta_window_move_resize_internal (MetaWindow *window, + MtkRectangle unconstrained_rect; + MtkRectangle constrained_rect; + MtkRectangle temporary_rect; ++ MtkRectangle rect; + int rel_x = 0; + int rel_y = 0; + MetaMoveResizeResultFlags result = 0; +@@ -3954,6 +3972,7 @@ meta_window_move_resize_internal (MetaWindow *window, + + /* We don't need it in the idle queue anymore. */ + meta_window_unqueue (window, META_QUEUE_MOVE_RESIZE); ++ rect = meta_window_config_get_rect (window->config); + + if ((flags & META_MOVE_RESIZE_RESIZE_ACTION) && (flags & META_MOVE_RESIZE_MOVE_ACTION)) + { +@@ -3965,7 +3984,7 @@ meta_window_move_resize_internal (MetaWindow *window, + /* If this is only a resize, then ignore the position given in + * the parameters and instead calculate the new position from + * resizing the old rectangle with the given gravity. */ +- meta_rectangle_resize_with_gravity (&window->rect, ++ meta_rectangle_resize_with_gravity (&rect, + &unconstrained_rect, + gravity, + frame_rect.width, +@@ -3977,21 +3996,21 @@ meta_window_move_resize_internal (MetaWindow *window, + * just use the existing size of the window. */ + unconstrained_rect.x = frame_rect.x; + unconstrained_rect.y = frame_rect.y; +- unconstrained_rect.width = window->rect.width; +- unconstrained_rect.height = window->rect.height; ++ unconstrained_rect.width = rect.width; ++ unconstrained_rect.height = rect.height; + } + else if ((flags & META_MOVE_RESIZE_WAYLAND_FINISH_MOVE_RESIZE)) + { + /* This is a Wayland buffer acking our size. The new rect is + * just the existing one we have. Ignore the passed-in rect + * completely. */ +- unconstrained_rect = window->rect; ++ unconstrained_rect = rect; + } + else + g_assert_not_reached (); + + constrained_rect = unconstrained_rect; +- temporary_rect = window->rect; ++ temporary_rect = rect; + if (flags & META_MOVE_RESIZE_CONSTRAIN && window->monitor) + { + MtkRectangle old_rect; +@@ -4378,8 +4397,9 @@ gboolean + meta_window_geometry_contains_rect (MetaWindow *window, + MtkRectangle *rect) + { +- return mtk_rectangle_contains_rect (&window->rect, +- rect); ++ MtkRectangle frame_rect = meta_window_config_get_rect (window->config); ++ ++ return mtk_rectangle_contains_rect (&frame_rect, rect); + } + + /** +@@ -4513,7 +4533,7 @@ void + meta_window_get_frame_rect (const MetaWindow *window, + MtkRectangle *rect) + { +- *rect = window->rect; ++ *rect = meta_window_config_get_rect (window->config); + } + + /** +diff --git a/src/tests/wayland-unit-tests.c b/src/tests/wayland-unit-tests.c +index 9c6feee68c..21abad98a1 100644 +--- a/src/tests/wayland-unit-tests.c ++++ b/src/tests/wayland-unit-tests.c +@@ -691,6 +691,7 @@ toplevel_bounds_struts (void) + MetaWindow *window; + MtkRectangle logical_monitor_layout; + MtkRectangle work_area; ++ MtkRectangle frame_rect; + + /* + * This test case makes sure that setting and changing struts result in the +@@ -719,8 +720,9 @@ toplevel_bounds_struts (void) + g_assert_cmpint (work_area.width, ==, logical_monitor_layout.width); + g_assert_cmpint (work_area.height, ==, logical_monitor_layout.height - 10); + +- g_assert_cmpint (window->rect.width, ==, work_area.width - 10); +- g_assert_cmpint (window->rect.height, ==, work_area.height - 10); ++ frame_rect = meta_window_config_get_rect (window->config); ++ g_assert_cmpint (frame_rect.width, ==, work_area.width - 10); ++ g_assert_cmpint (frame_rect.height, ==, work_area.height - 10); + + meta_wayland_test_driver_emit_sync_event (test_driver, 0); + meta_wayland_test_client_finish (wayland_test_client); +@@ -739,8 +741,9 @@ toplevel_bounds_struts (void) + g_assert_cmpint (work_area.width, ==, logical_monitor_layout.width); + g_assert_cmpint (work_area.height, ==, logical_monitor_layout.height); + +- g_assert_cmpint (window->rect.width, ==, work_area.width - 10); +- g_assert_cmpint (window->rect.height, ==, work_area.height - 10); ++ frame_rect = meta_window_config_get_rect (window->config); ++ g_assert_cmpint (frame_rect.width, ==, work_area.width - 10); ++ g_assert_cmpint (frame_rect.height, ==, work_area.height - 10); + + meta_wayland_test_driver_emit_sync_event (test_driver, 0); + meta_wayland_test_client_finish (wayland_test_client); +@@ -774,6 +777,7 @@ toplevel_bounds_monitors (void) + MetaWaylandTestClient *wayland_test_client; + MtkRectangle logical_monitor_layout; + MtkRectangle work_area; ++ MtkRectangle frame_rect; + MetaWindow *window; + + /* +@@ -811,8 +815,9 @@ toplevel_bounds_monitors (void) + g_assert_cmpint (work_area.width, ==, logical_monitor_layout.width); + g_assert_cmpint (work_area.height, ==, logical_monitor_layout.height - 10); + +- g_assert_cmpint (window->rect.width, ==, work_area.width - 10); +- g_assert_cmpint (window->rect.height, ==, work_area.height - 10); ++ frame_rect = meta_window_config_get_rect (window->config); ++ g_assert_cmpint (frame_rect.width, ==, work_area.width - 10); ++ g_assert_cmpint (frame_rect.height, ==, work_area.height - 10); + + meta_wayland_test_driver_emit_sync_event (test_driver, 0); + meta_wayland_test_client_finish (wayland_test_client); +@@ -835,8 +840,9 @@ toplevel_bounds_monitors (void) + g_assert_cmpint (work_area.width, ==, 300); + g_assert_cmpint (work_area.height, ==, 200); + +- g_assert_cmpint (window->rect.width, ==, 300 - 10); +- g_assert_cmpint (window->rect.height, ==, 200 - 10); ++ frame_rect = meta_window_config_get_rect (window->config); ++ g_assert_cmpint (frame_rect.width, ==, 300 - 10); ++ g_assert_cmpint (frame_rect.height, ==, 200 - 10); + + meta_wayland_test_driver_emit_sync_event (test_driver, 0); + meta_wayland_test_client_finish (wayland_test_client); +diff --git a/src/wayland/meta-wayland-window-configuration.c b/src/wayland/meta-wayland-window-configuration.c +index 56fa77ad6b..889072da44 100644 +--- a/src/wayland/meta-wayland-window-configuration.c ++++ b/src/wayland/meta-wayland-window-configuration.c +@@ -34,6 +34,7 @@ meta_wayland_window_configuration_new (MetaWindow *window, + { + MetaWindowWayland *wl_window = META_WINDOW_WAYLAND (window); + MetaWaylandWindowConfiguration *configuration; ++ int x, y; + + configuration = g_new0 (MetaWaylandWindowConfiguration, 1); + *configuration = (MetaWaylandWindowConfiguration) { +@@ -50,9 +51,10 @@ meta_wayland_window_configuration_new (MetaWindow *window, + .is_suspended = meta_window_is_suspended (window), + }; + ++ meta_window_config_get_position (window->config, &x, &y); + if (flags & META_MOVE_RESIZE_MOVE_ACTION || +- window->rect.x != rect.x || +- window->rect.y != rect.y) ++ x != rect.x || ++ y != rect.y) + { + configuration->has_position = TRUE; + configuration->x = rect.x; +diff --git a/src/wayland/meta-wayland-xdg-session-state.c b/src/wayland/meta-wayland-xdg-session-state.c +index 33f39dd49a..69a6e250b5 100644 +--- a/src/wayland/meta-wayland-xdg-session-state.c ++++ b/src/wayland/meta-wayland-xdg-session-state.c +@@ -320,10 +320,12 @@ meta_wayland_xdg_session_state_save_window (MetaSessionState *state, + MetaWaylandXdgSessionState *xdg_session_state = + META_WAYLAND_XDG_SESSION_STATE (state); + MetaWaylandXdgToplevelState *toplevel_state; ++ MtkRectangle rect; + + toplevel_state = + meta_wayland_xdg_session_state_ensure_toplevel (xdg_session_state, + name); ++ rect = meta_window_config_get_rect (window->config); + + g_object_get (window, + "minimized", &toplevel_state->is_minimized, +@@ -334,7 +336,7 @@ meta_wayland_xdg_session_state_save_window (MetaSessionState *state, + { + toplevel_state->window_state = WINDOW_STATE_MAXIMIZED; + +- toplevel_state->tiled.rect = window->rect; ++ toplevel_state->tiled.rect = rect; + } + else if (window->tile_mode == META_TILE_LEFT || + window->tile_mode == META_TILE_RIGHT) +@@ -344,13 +346,13 @@ meta_wayland_xdg_session_state_save_window (MetaSessionState *state, + else if (window->tile_mode == META_TILE_RIGHT) + toplevel_state->window_state = WINDOW_STATE_TILED_RIGHT; + +- toplevel_state->tiled.rect = window->rect; ++ toplevel_state->tiled.rect = rect; + } + else + { + toplevel_state->window_state = WINDOW_STATE_FLOATING; + +- toplevel_state->floating.rect = window->rect; ++ toplevel_state->floating.rect = rect; + } + + toplevel_state->workspace_idx = meta_workspace_index (window->workspace); +diff --git a/src/wayland/meta-wayland-xdg-shell.c b/src/wayland/meta-wayland-xdg-shell.c +index 48f110b7c3..249f08b6dc 100644 +--- a/src/wayland/meta-wayland-xdg-shell.c ++++ b/src/wayland/meta-wayland-xdg-shell.c +@@ -878,8 +878,10 @@ meta_wayland_xdg_toplevel_apply_state (MetaWaylandSurfaceRole *surface_role, + { + MetaWaylandWindowConfiguration *configuration; + int bounds_width, bounds_height, geometry_scale; ++ MtkRectangle rect; + + geometry_scale = meta_window_wayland_get_geometry_scale (window); ++ rect = meta_window_config_get_rect (window->config); + + if (!meta_window_calculate_bounds (window, &bounds_width, &bounds_height)) + { +@@ -891,7 +893,7 @@ meta_wayland_xdg_toplevel_apply_state (MetaWaylandSurfaceRole *surface_role, + { + configuration = + meta_wayland_window_configuration_new (window, +- window->rect, ++ rect, + bounds_width, + bounds_height, + geometry_scale, +diff --git a/src/wayland/meta-window-wayland.c b/src/wayland/meta-window-wayland.c +index 48a6122a30..2171f4600c 100644 +--- a/src/wayland/meta-window-wayland.c ++++ b/src/wayland/meta-window-wayland.c +@@ -263,6 +263,7 @@ meta_window_wayland_move_resize_internal (MetaWindow *window, + MetaWindowWayland *wl_window = META_WINDOW_WAYLAND (window); + gboolean can_move_now = FALSE; + MtkRectangle configured_rect; ++ MtkRectangle frame_rect; + int geometry_scale; + int new_x; + int new_y; +@@ -281,6 +282,7 @@ meta_window_wayland_move_resize_internal (MetaWindow *window, + * coordinate space so that we can have a scale independent size to pass + * to the Wayland surface. */ + geometry_scale = meta_window_wayland_get_geometry_scale (window); ++ frame_rect = meta_window_config_get_rect (window->config); + + configured_rect.width = constrained_rect.width; + configured_rect.height = constrained_rect.height; +@@ -314,20 +316,21 @@ meta_window_wayland_move_resize_internal (MetaWindow *window, + new_width = unconstrained_rect.width; + new_height = unconstrained_rect.height; + } +- if (window->rect.width != new_width || +- window->rect.height != new_height) ++ if (frame_rect.width != new_width || ++ frame_rect.height != new_height) + { + *result |= META_MOVE_RESIZE_RESULT_RESIZED; +- window->rect.width = new_width; +- window->rect.height = new_height; ++ meta_window_config_set_size (window->config, ++ new_width, new_height); + } + ++ frame_rect = meta_window_config_get_rect (window->config); + window->buffer_rect.width = +- window->rect.width + ++ frame_rect.width + + window->custom_frame_extents.left + + window->custom_frame_extents.right; + window->buffer_rect.height = +- window->rect.height + ++ frame_rect.height + + window->custom_frame_extents.top + + window->custom_frame_extents.bottom; + +@@ -353,8 +356,8 @@ meta_window_wayland_move_resize_internal (MetaWindow *window, + if (flags & META_MOVE_RESIZE_PLACEMENT_CHANGED || + rel_x != wl_window->last_sent_rel_x || + rel_y != wl_window->last_sent_rel_y || +- constrained_rect.width != window->rect.width || +- constrained_rect.height != window->rect.height) ++ constrained_rect.width != frame_rect.width || ++ constrained_rect.height != frame_rect.height) + { + MetaWaylandWindowConfiguration *configuration; + +@@ -388,8 +391,8 @@ meta_window_wayland_move_resize_internal (MetaWindow *window, + break; + } + } +- else if (constrained_rect.width != window->rect.width || +- constrained_rect.height != window->rect.height || ++ else if (constrained_rect.width != frame_rect.width || ++ constrained_rect.height != frame_rect.height || + flags & META_MOVE_RESIZE_STATE_CHANGED) + { + MetaWaylandWindowConfiguration *configuration; +@@ -445,11 +448,10 @@ meta_window_wayland_move_resize_internal (MetaWindow *window, + !!(flags & META_MOVE_RESIZE_STATE_CHANGED); + } + +- if (new_x != window->rect.x || new_y != window->rect.y) ++ if (new_x != frame_rect.x || new_y != frame_rect.y) + { + *result |= META_MOVE_RESIZE_RESULT_MOVED; +- window->rect.x = new_x; +- window->rect.y = new_y; ++ meta_window_config_set_position (window->config, new_x, new_y); + } + + if (window->placement.rule && +@@ -526,7 +528,7 @@ meta_window_wayland_update_main_monitor (MetaWindow *window, + MetaLogicalMonitor *scaled_new; + float from_scale, to_scale; + float scale; +- MtkRectangle rect; ++ MtkRectangle frame_rect; + + from = window->monitor; + +@@ -540,7 +542,8 @@ meta_window_wayland_update_main_monitor (MetaWindow *window, + return; + } + +- if (window->rect.width == 0 || window->rect.height == 0) ++ frame_rect = meta_window_config_get_rect (window->config); ++ if (frame_rect.width == 0 || frame_rect.height == 0) + { + window->monitor = meta_window_find_monitor_from_id (window); + return; +@@ -587,10 +590,9 @@ meta_window_wayland_update_main_monitor (MetaWindow *window, + * changes the main monitor, wait until both the current and the new scale + * will result in the same main monitor. */ + scale = to_scale / from_scale; +- rect = window->rect; +- scale_rect_size (&rect, scale); ++ scale_rect_size (&frame_rect, scale); + scaled_new = +- meta_monitor_manager_get_logical_monitor_from_rect (monitor_manager, &rect); ++ meta_monitor_manager_get_logical_monitor_from_rect (monitor_manager, &frame_rect); + if (to != scaled_new) + return; + +@@ -606,6 +608,7 @@ meta_window_wayland_main_monitor_changed (MetaWindow *window, + int geometry_scale; + float scale_factor; + MetaWaylandSurface *surface; ++ MtkRectangle frame_rect; + + if (!window->monitor) + return; +@@ -629,7 +632,8 @@ meta_window_wayland_main_monitor_changed (MetaWindow *window, + scale_factor = (float) geometry_scale / old_geometry_scale; + + /* Window size. */ +- scale_rect_size (&window->rect, scale_factor); ++ frame_rect = meta_window_config_get_rect (window->config); ++ scale_rect_size (&frame_rect, scale_factor); + scale_rect_size (&window->unconstrained_rect, scale_factor); + scale_rect_size (&window->saved_rect, scale_factor); + scale_size (&window->size_hints.min_width, &window->size_hints.min_height, scale_factor); +@@ -649,9 +653,9 @@ meta_window_wayland_main_monitor_changed (MetaWindow *window, + /* Buffer rect. */ + scale_rect_size (&window->buffer_rect, scale_factor); + window->buffer_rect.x = +- window->rect.x - window->custom_frame_extents.left; ++ frame_rect.x - window->custom_frame_extents.left; + window->buffer_rect.y = +- window->rect.y - window->custom_frame_extents.top; ++ frame_rect.y - window->custom_frame_extents.top; + + meta_compositor_sync_window_geometry (window->display->compositor, + window, +@@ -861,10 +865,6 @@ meta_window_wayland_constructed (GObject *object) + window->client_type = META_WINDOW_CLIENT_TYPE_WAYLAND; + + window->override_redirect = FALSE; +- window->rect.x = 0; +- window->rect.y = 0; +- window->rect.width = 0; +- window->rect.height = 0; + /* size_hints are the "request" */ + window->size_hints.x = 0; + window->size_hints.y = 0; +@@ -878,6 +878,8 @@ meta_window_wayland_constructed (GObject *object) + window->decorated = FALSE; + window->hidden = TRUE; + ++ window->config = meta_window_config_new (); ++ + G_OBJECT_CLASS (meta_window_wayland_parent_class)->constructed (object); + } + +@@ -1105,9 +1107,7 @@ meta_window_wayland_is_resize (MetaWindowWayland *wl_window, + else + { + MetaWindow *window = META_WINDOW (wl_window); +- +- old_width = window->rect.width; +- old_height = window->rect.height; ++ meta_window_config_get_size (window->config, &old_width, &old_height); + } + + return !wl_window->has_last_sent_configuration || +@@ -1178,6 +1178,7 @@ meta_window_wayland_finish_move_resize (MetaWindow *window, + gboolean is_window_being_resized; + gboolean is_client_resize; + MetaWindowDrag *window_drag; ++ MtkRectangle frame_rect; + + /* new_geom is in the logical pixel coordinate space, but MetaWindow wants its + * rects to represent what in turn will end up on the stage, i.e. we need to +@@ -1225,9 +1226,10 @@ meta_window_wayland_finish_move_resize (MetaWindow *window, + meta_grab_op_is_resizing (meta_window_drag_get_grab_op (window_drag)) && + meta_window_drag_get_window (window_drag) == window); + ++ frame_rect = meta_window_config_get_rect (window->config); + rect = (MtkRectangle) { +- .x = window->rect.x, +- .y = window->rect.y, ++ .x = frame_rect.x, ++ .y = frame_rect.y, + .width = new_geom.width, + .height = new_geom.height + }; +@@ -1239,10 +1241,12 @@ meta_window_wayland_finish_move_resize (MetaWindow *window, + if (window->placement.rule) + { + MetaWindow *parent; ++ MtkRectangle parent_rect; + + parent = meta_window_get_transient_for (window); +- rect.x = parent->rect.x + acked_configuration->rel_x; +- rect.y = parent->rect.y + acked_configuration->rel_y; ++ parent_rect = meta_window_config_get_rect (parent->config); ++ rect.x = parent_rect.x + acked_configuration->rel_x; ++ rect.y = parent_rect.y + acked_configuration->rel_y; + } + else + { +@@ -1262,7 +1266,7 @@ meta_window_wayland_finish_move_resize (MetaWindow *window, + rect.x += dx; + rect.y += dy; + +- if (rect.x != window->rect.x || rect.y != window->rect.y) ++ if (rect.x != frame_rect.x || rect.y != frame_rect.y) + flags |= META_MOVE_RESIZE_MOVE_ACTION; + + if (wl_window->has_pending_state_change && acked_configuration) +@@ -1271,7 +1275,7 @@ meta_window_wayland_finish_move_resize (MetaWindow *window, + wl_window->has_pending_state_change = FALSE; + } + +- if (rect.width != window->rect.width || rect.height != window->rect.height) ++ if (rect.width != frame_rect.width || rect.height != frame_rect.height) + { + flags |= META_MOVE_RESIZE_RESIZE_ACTION; + +@@ -1310,8 +1314,9 @@ meta_window_place_with_placement_rule (MetaWindow *window, + window->placement.rule = g_new0 (MetaPlacementRule, 1); + *window->placement.rule = *placement_rule; + +- window->unconstrained_rect.x = window->rect.x; +- window->unconstrained_rect.y = window->rect.y; ++ meta_window_config_get_position (window->config, ++ &window->unconstrained_rect.x, ++ &window->unconstrained_rect.y); + window->unconstrained_rect.width = placement_rule->width; + window->unconstrained_rect.height = placement_rule->height; + +diff --git a/src/wayland/meta-xwayland-dnd.c b/src/wayland/meta-xwayland-dnd.c +index 19e09ce486..97ef4761b1 100644 +--- a/src/wayland/meta-xwayland-dnd.c ++++ b/src/wayland/meta-xwayland-dnd.c +@@ -834,7 +834,7 @@ repick_drop_surface (MetaWaylandCompositor *compositor, + + XMapRaised (xdisplay, dnd_window); + +- frame_rect = focus_window->rect; ++ frame_rect = meta_window_config_get_rect (focus_window->config); + meta_xwayland_stage_to_protocol_rect (manager, + &frame_rect, + &frame_rect); +diff --git a/src/x11/meta-x11-frame.c b/src/x11/meta-x11-frame.c +index 9030a92569..f1451bb655 100644 +--- a/src/x11/meta-x11-frame.c ++++ b/src/x11/meta-x11-frame.c +@@ -88,7 +88,7 @@ meta_window_x11_set_frame_xwindow (MetaWindow *window, + frame->window = window; + frame->xwindow = xframe; + +- frame->rect = window->rect; ++ frame->rect = meta_window_config_get_rect (window->config); + frame->child_x = 0; + frame->child_y = 0; + frame->bottom_height = 0; +diff --git a/src/x11/window-props.c b/src/x11/window-props.c +index 9ee56de715..a162ecd8c8 100644 +--- a/src/x11/window-props.c ++++ b/src/x11/window-props.c +@@ -344,7 +344,11 @@ meta_window_set_custom_frame_extents (MetaWindow *window, + */ + if (is_initial) + { +- meta_window_client_rect_to_frame_rect (window, &window->rect, &window->rect); ++ MtkRectangle frame_rect; ++ ++ frame_rect = meta_window_config_get_rect (window->config); ++ meta_window_client_rect_to_frame_rect (window, &frame_rect, &frame_rect); ++ meta_window_config_set_rect (window->config, frame_rect); + meta_window_client_rect_to_frame_rect (window, &window->unconstrained_rect, &window->unconstrained_rect); + } + } +@@ -791,7 +795,7 @@ reload_net_wm_state (MetaWindow *window, + + window->maximized_horizontally = FALSE; + window->maximized_vertically = FALSE; +- window->fullscreen = FALSE; ++ meta_window_config_set_is_fullscreen (window->config, FALSE); + priv->wm_state_modal = FALSE; + priv->wm_state_skip_taskbar = FALSE; + priv->wm_state_skip_pager = FALSE; +@@ -819,7 +823,7 @@ reload_net_wm_state (MetaWindow *window, + priv->wm_state_skip_pager = TRUE; + else if (value->v.atom_list.atoms[i] == x11_display->atom__NET_WM_STATE_FULLSCREEN) + { +- window->fullscreen = TRUE; ++ meta_window_config_set_is_fullscreen (window->config, TRUE); + g_object_notify (G_OBJECT (window), "fullscreen"); + } + else if (value->v.atom_list.atoms[i] == x11_display->atom__NET_WM_STATE_ABOVE) +diff --git a/src/x11/window-x11.c b/src/x11/window-x11.c +index 8157b1c013..d02ca97486 100644 +--- a/src/x11/window-x11.c ++++ b/src/x11/window-x11.c +@@ -671,14 +671,14 @@ meta_window_x11_initialize_state (MetaWindow *window) + } + + /* For override-redirect windows, save the client rect +- * directly. window->rect was assigned from the XWindowAttributes ++ * directly. window->config->rect was assigned from the XWindowAttributes + * in the main meta_window_shared_new. + * + * For normal windows, do a full ConfigureRequest based on the + * window hints, as that's what the ICCCM says to do. + */ +- priv->client_rect = window->rect; +- window->buffer_rect = window->rect; ++ priv->client_rect = meta_window_config_get_rect (window->config); ++ window->buffer_rect = meta_window_config_get_rect (window->config); + + if (!window->override_redirect) + { +@@ -1410,15 +1410,18 @@ meta_window_x11_move_resize_internal (MetaWindow *window, + gboolean configure_frame_first; + gboolean is_configure_request; + MetaWindowDrag *window_drag; ++ MtkRectangle frame_rect; + + is_configure_request = (flags & META_MOVE_RESIZE_CONFIGURE_REQUEST) != 0; + + meta_frame_calc_borders (priv->frame, &borders); + +- size_dx = constrained_rect.width - window->rect.width; +- size_dy = constrained_rect.height - window->rect.height; ++ frame_rect = meta_window_config_get_rect (window->config); ++ size_dx = constrained_rect.width - frame_rect.width; ++ size_dy = constrained_rect.height - frame_rect.height; + +- window->rect = constrained_rect; ++ meta_window_config_set_rect (window->config, constrained_rect); ++ frame_rect = meta_window_config_get_rect (window->config); + + if (priv->frame) + { +@@ -1426,8 +1429,8 @@ meta_window_x11_move_resize_internal (MetaWindow *window, + int new_x, new_y; + + /* Compute new frame size */ +- new_w = window->rect.width + borders.invisible.left + borders.invisible.right; +- new_h = window->rect.height + borders.invisible.top + borders.invisible.bottom; ++ new_w = frame_rect.width + borders.invisible.left + borders.invisible.right; ++ new_h = frame_rect.height + borders.invisible.top + borders.invisible.bottom; + + if (new_w != priv->frame->rect.width || + new_h != priv->frame->rect.height) +@@ -1438,8 +1441,8 @@ meta_window_x11_move_resize_internal (MetaWindow *window, + } + + /* Compute new frame coords */ +- new_x = window->rect.x - borders.invisible.left; +- new_y = window->rect.y - borders.invisible.top; ++ new_x = frame_rect.x - borders.invisible.left; ++ new_y = frame_rect.y - borders.invisible.top; + + if (new_x != priv->frame->rect.x || + new_y != priv->frame->rect.y) +@@ -2176,7 +2179,8 @@ meta_window_x11_constructed (GObject *object) + rect = MTK_RECTANGLE_INIT (attrs.x, attrs.y, attrs.width, attrs.height); + meta_window_protocol_to_stage_rect (window, &rect, &rect); + +- window->rect = rect; ++ window->config = meta_window_config_new (); ++ meta_window_config_set_rect (window->config, rect); + + /* size_hints are the "request" */ + window->size_hints.x = rect.x; +@@ -2729,12 +2733,11 @@ meta_window_x11_get_gravity_position (MetaWindow *window, + int w, h; + int x, y; + +- w = window->rect.width; +- h = window->rect.height; ++ meta_window_config_get_size (window->config, &w, &h); + + if (gravity == META_GRAVITY_STATIC) + { +- frame_extents = window->rect; ++ frame_extents = meta_window_config_get_rect (window->config); + if (priv->frame) + { + frame_extents.x = priv->frame->rect.x + priv->frame->child_x; +@@ -2744,7 +2747,7 @@ meta_window_x11_get_gravity_position (MetaWindow *window, + else + { + if (priv->frame == NULL) +- frame_extents = window->rect; ++ frame_extents = meta_window_config_get_rect (window->config); + else + frame_extents = priv->frame->rect; + } +@@ -2817,10 +2820,11 @@ meta_window_x11_get_session_geometry (MetaWindow *window, + window->size_hints.win_gravity, + x, y); + +- *width = (window->rect.width - window->size_hints.base_width) / +- window->size_hints.width_inc; +- *height = (window->rect.height - window->size_hints.base_height) / +- window->size_hints.height_inc; ++ meta_window_config_get_position (window->config, width, height); ++ *width -= window->size_hints.base_width; ++ *width /= window->size_hints.width_inc; ++ *height -= window->size_hints.base_height; ++ *height /= window->size_hints.height_inc; + } + + static void +@@ -2859,7 +2863,7 @@ meta_window_move_resize_request (MetaWindow *window, + * and otherwise use our current up-to-date position. + * + * Otherwise you get spurious position changes when the app changes +- * size, for example, if window->rect is not in sync with the ++ * size, for example, if window->config->rect is not in sync with the + * server-side position in effect when the configure request was + * generated. + */ +@@ -4347,6 +4351,7 @@ meta_window_x11_configure_notify (MetaWindow *window, + { + MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); + MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11); ++ MtkRectangle rect; + + g_assert (window->override_redirect); + g_assert (priv->frame == NULL); +@@ -4356,10 +4361,11 @@ meta_window_x11_configure_notify (MetaWindow *window, + event->y, + event->width, + event->height), +- &window->rect); ++ &rect); ++ meta_window_config_set_rect (window->config, rect); + +- priv->client_rect = window->rect; +- window->buffer_rect = window->rect; ++ priv->client_rect = rect; ++ window->buffer_rect = rect; + + meta_window_update_monitor (window, META_WINDOW_UPDATE_MONITOR_FLAGS_NONE); + +-- +2.49.0 + diff --git a/0006-window-Add-a-configure-signal.patch b/0006-window-Add-a-configure-signal.patch new file mode 100644 index 0000000..284667a --- /dev/null +++ b/0006-window-Add-a-configure-signal.patch @@ -0,0 +1,94 @@ +From e3c023240a6bc7479e9e7a95b083afbfaa08b98b Mon Sep 17 00:00:00 2001 +From: Olivier Fourdan +Date: Wed, 2 Oct 2024 17:21:40 +0200 +Subject: [PATCH 06/10] window: Add a "configure" signal + +This conveys the initial window configuration. + +Part-of: +(cherry picked from commit d44fd167bb62dc541c6b6215d14d26e84733ab5f) +--- + src/core/window-private.h | 4 ++++ + src/core/window.c | 23 +++++++++++++++++++++++ + 2 files changed, 27 insertions(+) + +diff --git a/src/core/window-private.h b/src/core/window-private.h +index a03b156d67..f7ebb2ad91 100644 +--- a/src/core/window-private.h ++++ b/src/core/window-private.h +@@ -34,6 +34,7 @@ + #include "backends/meta-logical-monitor.h" + #include "clutter/clutter.h" + #include "core/stack.h" ++#include "meta/meta-window-config.h" + #include "meta/compositor.h" + #include "meta/meta-close-dialog.h" + #include "meta/util.h" +@@ -812,6 +813,9 @@ void meta_window_ensure_close_dialog_timeout (MetaWindow *window); + + void meta_window_emit_size_changed (MetaWindow *window); + ++void meta_window_emit_configure (MetaWindow *window, ++ MetaWindowConfig *window_config); ++ + MetaPlacementRule *meta_window_get_placement_rule (MetaWindow *window); + + void meta_window_force_placement (MetaWindow *window, +diff --git a/src/core/window.c b/src/core/window.c +index e9c005aeca..9a70f79f95 100644 +--- a/src/core/window.c ++++ b/src/core/window.c +@@ -81,6 +81,7 @@ + #include "meta/meta-cursor-tracker.h" + #include "meta/meta-enum-types.h" + #include "meta/prefs.h" ++#include "meta/meta-window-config.h" + + #ifdef HAVE_X11_CLIENT + #include "mtk/mtk-x11.h" +@@ -241,6 +242,7 @@ enum + POSITION_CHANGED, + SHOWN, + HIGHEST_SCALE_MONITOR_CHANGED, ++ CONFIGURE, + + LAST_SIGNAL + }; +@@ -733,6 +735,20 @@ meta_window_class_init (MetaWindowClass *klass) + 0, + NULL, NULL, NULL, + G_TYPE_NONE, 0); ++ ++ /** ++ * MetaWindow::configure: ++ * @window: a #MetaWindow ++ * @window_config: a #MetaWindowConfig ++ */ ++ window_signals[CONFIGURE] = ++ g_signal_new ("configure", ++ G_TYPE_FROM_CLASS (object_class), ++ G_SIGNAL_RUN_LAST, ++ 0, ++ NULL, NULL, NULL, ++ G_TYPE_NONE, 1, ++ META_TYPE_WINDOW_CONFIG); + } + + static void +@@ -7590,6 +7606,13 @@ meta_window_get_placement_rule (MetaWindow *window) + return window->placement.rule; + } + ++void ++meta_window_emit_configure (MetaWindow *window, ++ MetaWindowConfig *window_config) ++{ ++ g_signal_emit (window, window_signals[CONFIGURE], 0, window_config); ++} ++ + void + meta_window_force_restore_shortcuts (MetaWindow *window, + ClutterInputDevice *source) +-- +2.49.0 + diff --git a/0007-window-Add-a-window-helper-function-for-MetaWindowCo.patch b/0007-window-Add-a-window-helper-function-for-MetaWindowCo.patch new file mode 100644 index 0000000..ec7dbd0 --- /dev/null +++ b/0007-window-Add-a-window-helper-function-for-MetaWindowCo.patch @@ -0,0 +1,61 @@ +From 05f341932f693e6776074ff7892eae7a1ca33b8c Mon Sep 17 00:00:00 2001 +From: Olivier Fourdan +Date: Tue, 12 Nov 2024 14:59:38 +0100 +Subject: [PATCH 07/10] window: Add a window helper function for + MetaWindowConfig + +The MetaWindowConfig can indicate whether the configuration reflects on +the initial configuration, before the window is first mapped. + +Add a smaller helper (private) window function to create the appropriate +"type" of MetaWindowConfig depending whether the window was already +showed or not. + +This is preparation work for the following commits where this function +will be used. + +Part-of: +(cherry picked from commit 5a231a4d2789e84d3222354b3fef0718a94c9561) +--- + src/core/window-private.h | 2 ++ + src/core/window.c | 10 ++++++++++ + 2 files changed, 12 insertions(+) + +diff --git a/src/core/window-private.h b/src/core/window-private.h +index f7ebb2ad91..ba1973bd95 100644 +--- a/src/core/window-private.h ++++ b/src/core/window-private.h +@@ -896,3 +896,5 @@ gboolean meta_window_is_tiled_side_by_side (MetaWindow *window); + gboolean meta_window_is_tiled_left (MetaWindow *window); + + gboolean meta_window_is_tiled_right (MetaWindow *window); ++ ++MetaWindowConfig * meta_window_new_window_config (MetaWindow *window); +diff --git a/src/core/window.c b/src/core/window.c +index 9a70f79f95..b0d937dc0e 100644 +--- a/src/core/window.c ++++ b/src/core/window.c +@@ -72,6 +72,7 @@ + #include "core/boxes-private.h" + #include "core/constraints.h" + #include "core/keybindings-private.h" ++#include "core/meta-window-config-private.h" + #include "core/meta-workspace-manager-private.h" + #include "core/place.h" + #include "core/stack.h" +@@ -8246,3 +8247,12 @@ meta_window_get_client_content_rect (MetaWindow *window, + meta_window_frame_rect_to_client_rect (window, rect, rect); + #endif + } ++ ++MetaWindowConfig * ++meta_window_new_window_config (MetaWindow *window) ++{ ++ if (window->showing_for_first_time) ++ return meta_window_config_initial_new (); ++ else ++ return meta_window_config_new (); ++} +-- +2.49.0 + diff --git a/0008-wayland-window-configuration-Add-MetaWindowConfig-su.patch b/0008-wayland-window-configuration-Add-MetaWindowConfig-su.patch new file mode 100644 index 0000000..02dc26b --- /dev/null +++ b/0008-wayland-window-configuration-Add-MetaWindowConfig-su.patch @@ -0,0 +1,126 @@ +From 6ca58583b7a53daa4ff97df403c20161a6da17a4 Mon Sep 17 00:00:00 2001 +From: Olivier Fourdan +Date: Wed, 16 Oct 2024 14:58:37 +0200 +Subject: [PATCH 08/10] wayland/window-configuration: Add MetaWindowConfig + support + +This allows to bridge MetaWaylandWindowConfiguration and +MetaWindowConfig. + +Part-of: +(cherry picked from commit c597feaa67fdcaa971a561e82b9937970c741bbf) +--- + .../meta-wayland-window-configuration.c | 69 +++++++++++++++++++ + .../meta-wayland-window-configuration.h | 8 +++ + 2 files changed, 77 insertions(+) + +diff --git a/src/wayland/meta-wayland-window-configuration.c b/src/wayland/meta-wayland-window-configuration.c +index 889072da44..f92c1b34a7 100644 +--- a/src/wayland/meta-wayland-window-configuration.c ++++ b/src/wayland/meta-wayland-window-configuration.c +@@ -18,6 +18,8 @@ + + #include "config.h" + ++#include "core/meta-window-config-private.h" ++#include "core/window-private.h" + #include "wayland/meta-wayland-window-configuration.h" + #include "wayland/meta-window-wayland.h" + +@@ -123,3 +125,70 @@ meta_wayland_window_configuration_free (MetaWaylandWindowConfiguration *configur + { + g_free (configuration); + } ++ ++MetaWindowConfig * ++meta_window_config_new_from_wayland_window_configuration (MetaWindow *window, ++ MetaWaylandWindowConfiguration *configuration) ++{ ++ MetaWindowConfig *window_config; ++ MtkRectangle rect; ++ ++ window_config = meta_window_new_window_config (window); ++ rect = meta_window_config_get_rect (window->config); ++ meta_window_config_set_rect (window_config, rect); ++ meta_window_config_set_is_fullscreen (window_config, ++ meta_window_config_get_is_fullscreen (window->config)); ++ ++ if (configuration->has_position) ++ meta_window_config_set_position (window_config, ++ configuration->x, ++ configuration->y); ++ ++ if (configuration->has_size && ++ configuration->width > 0 && ++ configuration->height > 0) ++ meta_window_config_set_size (window_config, ++ configuration->width, ++ configuration->height); ++ ++ return window_config; ++} ++ ++MetaWaylandWindowConfiguration * ++meta_wayland_window_configuration_apply_window_config (MetaWindow *window, ++ MetaWaylandWindowConfiguration *configuration, ++ MetaWindowConfig *window_config) ++{ ++ MtkRectangle rect; ++ int prev_x = configuration->x; ++ int prev_y = configuration->y; ++ int prev_width = configuration->width; ++ int prev_height = configuration->height; ++ gboolean is_fullscreen; ++ ++ rect = meta_window_config_get_rect (window_config); ++ configuration->x = rect.x; ++ configuration->y = rect.y; ++ configuration->width = rect.width; ++ configuration->height = rect.height; ++ ++ is_fullscreen = meta_window_config_get_is_fullscreen (window_config); ++ meta_window_config_set_is_fullscreen (window->config, is_fullscreen); ++ configuration->is_fullscreen = is_fullscreen; ++ ++ if (prev_x != configuration->x || prev_y != configuration->y) ++ { ++ configuration->has_position = TRUE; ++ meta_window_config_set_position (window->config, ++ configuration->x, ++ configuration->y); ++ window->placed = TRUE; ++ } ++ ++ if (prev_width != configuration->width || ++ prev_height != configuration->height) ++ configuration->has_size = (configuration->width > 0 && ++ configuration->height > 0); ++ ++ return configuration; ++} +diff --git a/src/wayland/meta-wayland-window-configuration.h b/src/wayland/meta-wayland-window-configuration.h +index fb26344bb0..762816e5ac 100644 +--- a/src/wayland/meta-wayland-window-configuration.h ++++ b/src/wayland/meta-wayland-window-configuration.h +@@ -22,6 +22,7 @@ + #include + + #include "core/window-private.h" ++#include "meta/meta-window-config.h" + #include "wayland/meta-wayland-types.h" + + struct _MetaWaylandWindowConfiguration +@@ -72,3 +73,10 @@ MetaWaylandWindowConfiguration * meta_wayland_window_configuration_new_empty (in + int scale); + + void meta_wayland_window_configuration_free (MetaWaylandWindowConfiguration *configuration); ++ ++MetaWindowConfig * meta_window_config_new_from_wayland_window_configuration (MetaWindow *window, ++ MetaWaylandWindowConfiguration *configuration); ++ ++MetaWaylandWindowConfiguration * meta_wayland_window_configuration_apply_window_config (MetaWindow *window, ++ MetaWaylandWindowConfiguration *configuration, ++ MetaWindowConfig *window_config); +-- +2.49.0 + diff --git a/0009-wayland-Emit-the-configure-signal.patch b/0009-wayland-Emit-the-configure-signal.patch new file mode 100644 index 0000000..8455972 --- /dev/null +++ b/0009-wayland-Emit-the-configure-signal.patch @@ -0,0 +1,54 @@ +From c80438f489b941496084e196aa2003077121e17e Mon Sep 17 00:00:00 2001 +From: Olivier Fourdan +Date: Wed, 9 Oct 2024 11:37:57 +0200 +Subject: [PATCH 09/10] wayland: Emit the configure signal + +Emit the configure signal from the xdg_toplevel's apply_state function. + +A plugin gets a chance to tweak the initial configuration before it gets +applied. + +Part-of: +(cherry picked from commit 9927eaa9638c4e678adeb8dbb39b5fbee7a00c86) +--- + src/wayland/meta-wayland-xdg-shell.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/src/wayland/meta-wayland-xdg-shell.c b/src/wayland/meta-wayland-xdg-shell.c +index 249f08b6dc..5ef548723a 100644 +--- a/src/wayland/meta-wayland-xdg-shell.c ++++ b/src/wayland/meta-wayland-xdg-shell.c +@@ -27,6 +27,7 @@ + #include "compositor/compositor-private.h" + #include "core/boxes-private.h" + #include "core/window-private.h" ++#include "meta/meta-window-config.h" + #include "wayland/meta-wayland-outputs.h" + #include "wayland/meta-wayland-popup.h" + #include "wayland/meta-wayland-private.h" +@@ -877,6 +878,7 @@ meta_wayland_xdg_toplevel_apply_state (MetaWaylandSurfaceRole *surface_role, + if (!xdg_surface_priv->configure_sent) + { + MetaWaylandWindowConfiguration *configuration; ++ g_autoptr (MetaWindowConfig) window_config = NULL; + int bounds_width, bounds_height, geometry_scale; + MtkRectangle rect; + +@@ -908,6 +910,14 @@ meta_wayland_xdg_toplevel_apply_state (MetaWaylandSurfaceRole *surface_role, + geometry_scale); + } + ++ window_config = ++ meta_window_config_new_from_wayland_window_configuration (window, ++ configuration); ++ meta_window_emit_configure (window, window_config); ++ meta_wayland_window_configuration_apply_window_config (window, ++ configuration, ++ window_config); ++ + meta_wayland_xdg_toplevel_send_configure (xdg_toplevel, configuration); + meta_wayland_window_configuration_free (configuration); + return; +-- +2.49.0 + diff --git a/0010-window-x11-Emit-the-configure-signal.patch b/0010-window-x11-Emit-the-configure-signal.patch new file mode 100644 index 0000000..d35efdd --- /dev/null +++ b/0010-window-x11-Emit-the-configure-signal.patch @@ -0,0 +1,115 @@ +From ab21ff48316e82543d2854f4c024a400ea1c374c Mon Sep 17 00:00:00 2001 +From: Olivier Fourdan +Date: Mon, 21 Oct 2024 10:24:09 +0200 +Subject: [PATCH 10/10] window-x11: Emit the configure signal + +Emit the configure signal for X11 windows as soon as they get created. + +The configuration values then get applied as initial values. + +Part-of: +(cherry picked from commit ad9a192455ed2502153bbb5b7960bafb2ed1fbb5) +--- + src/x11/events.c | 4 ++++ + src/x11/window-x11.c | 48 ++++++++++++++++++++++++++++++++++++++++++++ + src/x11/window-x11.h | 2 ++ + 3 files changed, 54 insertions(+) + +diff --git a/src/x11/events.c b/src/x11/events.c +index 05d04a8c1a..c72d00c3a7 100644 +--- a/src/x11/events.c ++++ b/src/x11/events.c +@@ -1450,6 +1450,8 @@ handle_other_xevent (MetaX11Display *x11_display, + { + window = meta_window_x11_new (display, event->xmap.window, + FALSE, META_COMP_EFFECT_CREATE); ++ if (window) ++ meta_window_x11_configure (window); + } + else if (window && window->restore_focus_on_map && + window->reparents_pending == 0) +@@ -1506,6 +1508,8 @@ handle_other_xevent (MetaX11Display *x11_display, + + window = meta_window_x11_new (display, event->xmaprequest.window, + FALSE, META_COMP_EFFECT_CREATE); ++ if (window) ++ meta_window_x11_configure (window); + } + else + { +diff --git a/src/x11/window-x11.c b/src/x11/window-x11.c +index d02ca97486..8ac7f147b3 100644 +--- a/src/x11/window-x11.c ++++ b/src/x11/window-x11.c +@@ -38,6 +38,7 @@ + #include "compositor/compositor-private.h" + #include "compositor/meta-window-actor-private.h" + #include "core/boxes-private.h" ++#include "core/meta-window-config-private.h" + #include "core/meta-workspace-manager-private.h" + #include "core/window-private.h" + #include "core/workspace-private.h" +@@ -4935,3 +4936,50 @@ meta_window_x11_shutdown_group (MetaWindow *window) + { + remove_window_from_group (window); + } ++ ++void ++meta_window_x11_configure (MetaWindow *window) ++{ ++ MtkRectangle prev_rect; ++ MtkRectangle new_rect; ++ MetaMoveResizeFlags flags; ++ gboolean is_fullscreen; ++ g_autoptr (MetaWindowConfig) window_config = NULL; ++ ++ window_config = meta_window_new_window_config (window); ++ prev_rect = meta_window_config_get_rect (window->config); ++ meta_window_config_set_rect (window_config, prev_rect); ++ is_fullscreen = meta_window_is_fullscreen (window); ++ meta_window_config_set_is_fullscreen (window_config, is_fullscreen); ++ ++ meta_window_emit_configure (window, window_config); ++ new_rect = meta_window_config_get_rect (window_config); ++ ++ meta_topic (META_DEBUG_GEOMETRY, ++ "Window %s pre-configured at (%i,%i) [%ix%i]", ++ window->desc, new_rect.x, new_rect.y, new_rect.width, new_rect.height); ++ ++ if (!mtk_rectangle_equal (&prev_rect, &new_rect)) ++ { ++ window->placed = TRUE; ++ ++ /* Update the size hints to match the new pre-configuration */ ++ window->size_hints.x = new_rect.x; ++ window->size_hints.y = new_rect.y; ++ window->size_hints.width = new_rect.width; ++ window->size_hints.height = new_rect.height; ++ ++ flags = (META_MOVE_RESIZE_MOVE_ACTION | ++ META_MOVE_RESIZE_RESIZE_ACTION | ++ META_MOVE_RESIZE_CONSTRAIN); ++ ++ meta_window_move_resize_internal (window, ++ flags, ++ META_PLACE_FLAG_NONE, ++ window->size_hints.win_gravity, ++ new_rect); ++ } ++ ++ if (meta_window_config_get_is_fullscreen (window_config)) ++ meta_window_make_fullscreen (window); ++} +diff --git a/src/x11/window-x11.h b/src/x11/window-x11.h +index 5fd8517b4c..c92b28b1a0 100644 +--- a/src/x11/window-x11.h ++++ b/src/x11/window-x11.h +@@ -116,3 +116,5 @@ gboolean meta_window_x11_has_alpha_channel (MetaWindow *window); + + META_EXPORT + Window meta_window_x11_get_xwindow (MetaWindow *window); ++ ++void meta_window_x11_configure (MetaWindow *window); +-- +2.49.0 + diff --git a/mutter.spec b/mutter.spec index 6099221..79b2a0c 100644 --- a/mutter.spec +++ b/mutter.spec @@ -73,6 +73,20 @@ Patch: 0002-stage-Track-overlay-damage-per-view.patch Patch: a11y-manager.patch Patch: 0001-backend-native-Fetch-a11y-manager-after-parent-post-.patch +# Backport pre-configure mechanism (RHEL-84702) from: +# https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/4076 +# https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/4111 +Patch: 0001-window-Replace-barely-used-macros-with-func-equivale.patch +Patch: 0002-window-Use-getter-for-fullscreen-state.patch +Patch: 0003-window-Add-a-MetaWindowConfig-type.patch +Patch: 0004-window-Use-the-fullscreen-API.patch +Patch: 0005-window-Use-the-MetaWindowConfig.patch +Patch: 0006-window-Add-a-configure-signal.patch +Patch: 0007-window-Add-a-window-helper-function-for-MetaWindowCo.patch +Patch: 0008-wayland-window-configuration-Add-MetaWindowConfig-su.patch +Patch: 0009-wayland-Emit-the-configure-signal.patch +Patch: 0010-window-x11-Emit-the-configure-signal.patch + BuildRequires: pkgconfig(gobject-introspection-1.0) >= 1.41.0 BuildRequires: pkgconfig(sm) BuildRequires: pkgconfig(libwacom)