[mutter] window: Keep windows with placement rule attached to parent



commit 5376c31a33020d7dc5a69b129f2dd4f42d0890a1
Author: Jonas Ådahl <jadahl gmail com>
Date:   Wed Aug 22 21:54:16 2018 +0200

    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, &current_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, &current_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);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]