From 5376c31a33020d7dc5a69b129f2dd4f42d0890a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Wed, 22 Aug 2018 21:54:16 +0200 Subject: window: Keep windows with placement rule attached to parent A window placed using a placement rule should keep that relative position even if the parent window moves, as the position tied to the parent window, not to the stage. Thus, if the parent window moves, the child window should move with it. In the implementation in this commit, the constraints engine is not used when repositioning the children; the window is simply positioned according to the effective placement rule that was derived from the initial constraining, as the a xdg_popup at the moment cannot move (relative its parent) after being mapped. Closes: https://gitlab.gnome.org/GNOME/mutter/issues/274 --- src/core/constraints.c | 42 +++++++++++++++++++++++++++++------------- src/core/window-private.h | 1 + src/core/window.c | 21 ++++++++++++++++----- 3 files changed, 46 insertions(+), 18 deletions(-) diff --git a/src/core/constraints.c b/src/core/constraints.c index 73b4b96ea..82e19ee29 100644 --- a/src/core/constraints.c +++ b/src/core/constraints.c @@ -787,7 +787,7 @@ constrain_custom_rule (MetaWindow *window, MetaPlacementRule *placement_rule; MetaRectangle intersection; gboolean constraint_satisfied; - MetaPlacementRule current_rule; + MetaPlacementRule *current_rule; if (priority > PRIORITY_CUSTOM_RULE) return TRUE; @@ -796,6 +796,14 @@ constrain_custom_rule (MetaWindow *window, if (!placement_rule) return TRUE; + if (window->constrained_placement_rule) + { + meta_window_process_placement (window, + window->constrained_placement_rule, + &info->current.x, &info->current.y); + return TRUE; + } + meta_rectangle_intersect (&info->current, &info->work_area_monitor, &intersection); @@ -803,24 +811,28 @@ constrain_custom_rule (MetaWindow *window, placement_rule, &intersection); - if (constraint_satisfied || check_only) + if (check_only) return constraint_satisfied; - current_rule = *placement_rule; + current_rule = g_new0 (MetaPlacementRule, 1); + *current_rule = *placement_rule; + + if (constraint_satisfied) + goto done; if (info->current.width != intersection.width && - (current_rule.constraint_adjustment & + (current_rule->constraint_adjustment & META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_X)) { - try_flip_window_position (window, info, ¤t_rule, + try_flip_window_position (window, info, current_rule, META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_X, &info->current, &intersection); } if (info->current.height != intersection.height && - (current_rule.constraint_adjustment & + (current_rule->constraint_adjustment & META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_Y)) { - try_flip_window_position (window, info, ¤t_rule, + try_flip_window_position (window, info, current_rule, META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_Y, &info->current, &intersection); } @@ -832,9 +844,9 @@ constrain_custom_rule (MetaWindow *window, &intersection); if (constraint_satisfied) - return TRUE; + goto done; - if (current_rule.constraint_adjustment & + if (current_rule->constraint_adjustment & META_PLACEMENT_CONSTRAINT_ADJUSTMENT_SLIDE_X) { if (info->current.x != intersection.x) @@ -842,7 +854,7 @@ constrain_custom_rule (MetaWindow *window, else if (info->current.width != intersection.width) info->current.x -= info->current.width - intersection.width; } - if (current_rule.constraint_adjustment & + if (current_rule->constraint_adjustment & META_PLACEMENT_CONSTRAINT_ADJUSTMENT_SLIDE_Y) { if (info->current.y != intersection.y) @@ -858,21 +870,25 @@ constrain_custom_rule (MetaWindow *window, &intersection); if (constraint_satisfied) - return TRUE; + goto done; - if (current_rule.constraint_adjustment & + if (current_rule->constraint_adjustment & META_PLACEMENT_CONSTRAINT_ADJUSTMENT_RESIZE_X) { info->current.x = intersection.x; info->current.width = intersection.width; } - if (current_rule.constraint_adjustment & + if (current_rule->constraint_adjustment & META_PLACEMENT_CONSTRAINT_ADJUSTMENT_RESIZE_Y) { info->current.y = intersection.y; info->current.height = intersection.height; } +done: + g_clear_pointer (&window->constrained_placement_rule, g_free); + window->constrained_placement_rule = current_rule; + return TRUE; } diff --git a/src/core/window-private.h b/src/core/window-private.h index 76c454417..c47de087a 100644 --- a/src/core/window-private.h +++ b/src/core/window-private.h @@ -521,6 +521,7 @@ struct _MetaWindow guint bypass_compositor; MetaPlacementRule *placement_rule; + MetaPlacementRule *constrained_placement_rule; }; struct _MetaWindowClass diff --git a/src/core/window.c b/src/core/window.c index f8b0e0128..c06f52c86 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -313,6 +313,7 @@ meta_window_finalize (GObject *object) g_free (window->gtk_app_menu_object_path); g_free (window->gtk_menubar_object_path); g_free (window->placement_rule); + g_free (window->constrained_placement_rule); G_OBJECT_CLASS (meta_window_parent_class)->finalize (object); } @@ -3752,13 +3753,23 @@ meta_window_updates_are_frozen (MetaWindow *window) return FALSE; } +static void +meta_window_reposition (MetaWindow *window) +{ + meta_window_move_resize_internal (window, + (META_MOVE_RESIZE_MOVE_ACTION | + META_MOVE_RESIZE_RESIZE_ACTION), + NorthWestGravity, + window->rect); +} + static gboolean -maybe_move_attached_dialog (MetaWindow *window, +maybe_move_attached_window (MetaWindow *window, void *data) { - if (meta_window_is_attached_dialog (window)) - /* It ignores x,y for such a dialog */ - meta_window_move_frame (window, FALSE, 0, 0); + if (meta_window_is_attached_dialog (window) || + meta_window_get_placement_rule (window)) + meta_window_reposition (window); return FALSE; } @@ -4061,7 +4072,7 @@ meta_window_move_resize_internal (MetaWindow *window, window->frame_bounds = NULL; } - meta_window_foreach_transient (window, maybe_move_attached_dialog, NULL); + meta_window_foreach_transient (window, maybe_move_attached_window, NULL); meta_stack_update_window_tile_matches (window->display->stack, workspace_manager->active_workspace); -- cgit v1.2.1