summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonas Ådahl <jadahl@gmail.com>2018-08-22 21:54:16 +0200
committerJonas Ådahl <jadahl@gmail.com>2018-08-27 12:15:06 +0000
commit5376c31a33020d7dc5a69b129f2dd4f42d0890a1 (patch)
tree7f3b26fa097f9220af2fe173bc5bfcc407e90fc5
parentca5b27baf517f00354ff8811ba204fd90f1ddb38 (diff)
downloadmutter-5376c31a33020d7dc5a69b129f2dd4f42d0890a1.tar.gz
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
-rw-r--r--src/core/constraints.c42
-rw-r--r--src/core/window-private.h1
-rw-r--r--src/core/window.c21
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);