[mutter] window: Implement asynchronous popup moving
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter] window: Implement asynchronous popup moving
- Date: Sat, 29 Feb 2020 21:09:08 +0000 (UTC)
commit d08a8de2657c8a305847d625908eea0dd7bc8404
Author: Jonas Ã…dahl <jadahl gmail com>
Date: Fri Feb 14 10:41:38 2020 +0100
window: Implement asynchronous popup moving
This commits adds support on the MetaWindow and constraints engine side
for asynchronously repositioning a window with a placement rule, either
due to environmental changes (e.g. parent moved) or explicitly done so
via `meta_window_update_placement_rule()`.
This is so far unused, as placement rules where this functionality is
triggered are not yet constructed by the xdg-shell implementation, and
no users of `meta_window_update_placement_rule()` exists yet.
To summarize, it works by making it possible to produce placement rules
with the parent rectangle a window should be placed against, while
creating a pending configuration that is not applied until acknowledged
by the client using the xdg-shell configure/ack_configure mechanisms.
An "temporary" constrain result is added to deal with situations
where the client window *must* move immediately even though it has not yet
acknowledged a new configuration that was sent. This happens for example
when the parent window is moved, causing the popup window to change its
relative position e.g. because it ended up partially off-screen. In this
situation, the temporary position corresponds to the result of the
movement of the parent, while the pending (asynchronously configured)
position is the relative one given the new constraining result.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/705
src/core/constraints.c | 129 ++++++++++++++++++------
src/core/constraints.h | 1 +
src/core/window-private.h | 18 +++-
src/core/window.c | 8 +-
src/wayland/meta-wayland-xdg-shell.c | 17 +++-
src/wayland/meta-window-wayland.c | 187 +++++++++++++++++++++++++----------
src/wayland/meta-window-wayland.h | 3 +
src/x11/window-x11.c | 1 +
8 files changed, 275 insertions(+), 89 deletions(-)
---
diff --git a/src/core/constraints.c b/src/core/constraints.c
index 79019b902..51006614f 100644
--- a/src/core/constraints.c
+++ b/src/core/constraints.c
@@ -123,6 +123,7 @@ typedef struct
{
MetaRectangle orig;
MetaRectangle current;
+ MetaRectangle temporary;
int rel_x;
int rel_y;
ActionType action_type;
@@ -147,6 +148,8 @@ typedef struct
*/
GList *usable_screen_region;
GList *usable_monitor_region;
+
+ MetaMoveResizeFlags flags;
} ConstraintInfo;
static gboolean do_screen_and_monitor_relative_constraints (MetaWindow *window,
@@ -284,6 +287,7 @@ meta_window_constrain (MetaWindow *window,
MetaGravity resize_gravity,
const MetaRectangle *orig,
MetaRectangle *new,
+ MetaRectangle *temporary,
int *rel_x,
int *rel_y)
{
@@ -322,6 +326,7 @@ meta_window_constrain (MetaWindow *window,
/* Make sure we use the constrained position */
*new = info.current;
+ *temporary = info.temporary;
*rel_x = info.rel_x;
*rel_y = info.rel_y;
@@ -348,8 +353,10 @@ setup_constraint_info (ConstraintInfo *info,
info->orig = *orig;
info->current = *new;
+ info->temporary = *orig;
info->rel_x = 0;
info->rel_y = 0;
+ info->flags = flags;
if (info->current.width < 1)
info->current.width = 1;
@@ -500,16 +507,11 @@ place_window_if_needed(MetaWindow *window,
if (window->placement.rule)
{
- MetaWindow *parent = meta_window_get_transient_for (window);
- MetaRectangle parent_rect;
-
meta_window_process_placement (window,
window->placement.rule,
&info->rel_x, &info->rel_y);
- meta_window_get_frame_rect (parent, &parent_rect);
-
- placed_rect.x = parent_rect.x + info->rel_x;
- placed_rect.y = parent_rect.y + info->rel_y;
+ placed_rect.x = window->placement.rule->parent_rect.x + info->rel_x;
+ placed_rect.y = window->placement.rule->parent_rect.y + info->rel_y;
}
else
{
@@ -825,12 +827,13 @@ constrain_custom_rule (MetaWindow *window,
MetaPlacementRule *placement_rule;
MetaRectangle intersection;
gboolean constraint_satisfied;
+ MetaRectangle temporary_rect;
MetaRectangle adjusted_unconstrained;
int adjusted_rel_x;
int adjusted_rel_y;
MetaPlacementRule current_rule;
MetaWindow *parent;
- MetaRectangle parent_rect;
+ int parent_x, parent_y;
if (priority > PRIORITY_CUSTOM_RULE)
return TRUE;
@@ -839,25 +842,72 @@ constrain_custom_rule (MetaWindow *window,
if (!placement_rule)
return TRUE;
- adjusted_unconstrained = info->current;
-
parent = meta_window_get_transient_for (window);
- meta_window_get_frame_rect (parent, &parent_rect);
+ 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;
+ }
+ parent_x = placement_rule->parent_rect.x;
+ parent_y = placement_rule->parent_rect.y;
+
+ /*
+ * Calculate the temporary position, meaning a position that will be
+ * applied if the new constrained position requires asynchronous
+ * configuration of the window. This happens for example when the parent
+ * moves, causing this window to change relative position, meaning it can
+ * only have its newly constrained position applied when the configuration is
+ * acknowledged.
+ */
switch (window->placement.state)
{
case META_PLACEMENT_STATE_UNCONSTRAINED:
- adjusted_rel_x = window->rect.x - parent->rect.x;
- adjusted_rel_y = window->rect.y - parent->rect.y;
+ temporary_rect = info->current;
break;
- case META_PLACEMENT_STATE_CONSTRAINED:
- adjusted_unconstrained.x =
- parent->rect.x + window->placement.current.rel_x;
- adjusted_unconstrained.y =
- parent->rect.y + window->placement.current.rel_y;
+ case META_PLACEMENT_STATE_CONSTRAINED_CONFIGURED:
+ case META_PLACEMENT_STATE_CONSTRAINED_PENDING:
+ case META_PLACEMENT_STATE_CONSTRAINED_FINISHED:
+ case META_PLACEMENT_STATE_INVALIDATED:
+ temporary_rect = (MetaRectangle) {
+ .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,
+ };
+ break;
+ }
+
+ /*
+ * Calculate an adjusted current position. Depending on the rule
+ * configuration and placement state, this may result in window being
+ * reconstrained.
+ */
+
+ adjusted_unconstrained = temporary_rect;
+
+ if (window->placement.state == META_PLACEMENT_STATE_INVALIDATED ||
+ window->placement.state == META_PLACEMENT_STATE_UNCONSTRAINED ||
+ (window->placement.state == META_PLACEMENT_STATE_CONSTRAINED_FINISHED &&
+ placement_rule->is_reactive))
+ {
+ meta_window_process_placement (window, placement_rule,
+ &adjusted_rel_x,
+ &adjusted_rel_y);
+ adjusted_unconstrained.x = parent_x + adjusted_rel_x;
+ adjusted_unconstrained.y = parent_y + adjusted_rel_y;
+ }
+ else if (window->placement.state == META_PLACEMENT_STATE_CONSTRAINED_PENDING)
+ {
+ adjusted_rel_x = window->placement.pending.rel_x;
+ adjusted_rel_y = window->placement.pending.rel_y;
+ adjusted_unconstrained.x = window->placement.pending.x;
+ adjusted_unconstrained.y = window->placement.pending.y;
+ }
+ else
+ {
adjusted_rel_x = window->placement.current.rel_x;
adjusted_rel_y = window->placement.current.rel_y;
- break;
}
meta_rectangle_intersect (&adjusted_unconstrained, &info->work_area_monitor,
@@ -872,30 +922,43 @@ constrain_custom_rule (MetaWindow *window,
if (check_only)
return constraint_satisfied;
- current_rule = *placement_rule;
+ info->current = adjusted_unconstrained;
+ info->rel_x = adjusted_rel_x;
+ info->rel_y = adjusted_rel_y;
+ info->temporary = temporary_rect;
switch (window->placement.state)
{
- case META_PLACEMENT_STATE_CONSTRAINED:
- info->current = adjusted_unconstrained;
- info->rel_x = adjusted_rel_x;
- info->rel_y = adjusted_rel_y;
- goto done;
+ case META_PLACEMENT_STATE_CONSTRAINED_FINISHED:
+ if (!placement_rule->is_reactive)
+ return TRUE;
+ break;
+ case META_PLACEMENT_STATE_CONSTRAINED_PENDING:
+ case META_PLACEMENT_STATE_CONSTRAINED_CONFIGURED:
+ return TRUE;
case META_PLACEMENT_STATE_UNCONSTRAINED:
+ case META_PLACEMENT_STATE_INVALIDATED:
break;
}
if (constraint_satisfied)
goto done;
+ /*
+ * Process the placement rule in order either until constraints are
+ * satisfied, or there are no more rules to process.
+ */
+
+ current_rule = *placement_rule;
+
if (info->current.width != intersection.width &&
(current_rule.constraint_adjustment &
META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_X))
{
try_flip_window_position (window, info, ¤t_rule,
META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_X,
- parent_rect.x,
- parent_rect.y,
+ parent_x,
+ parent_y,
&info->current,
&info->rel_x,
&info->rel_y,
@@ -907,8 +970,8 @@ constrain_custom_rule (MetaWindow *window,
{
try_flip_window_position (window, info, ¤t_rule,
META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_Y,
- parent_rect.x,
- parent_rect.y,
+ parent_x,
+ parent_y,
&info->current,
&info->rel_x,
&info->rel_y,
@@ -1010,10 +1073,12 @@ constrain_custom_rule (MetaWindow *window,
}
done:
- window->placement.state = META_PLACEMENT_STATE_CONSTRAINED;
+ window->placement.state = META_PLACEMENT_STATE_CONSTRAINED_PENDING;
- window->placement.current.rel_x = info->rel_x;
- window->placement.current.rel_y = info->rel_y;
+ window->placement.pending.rel_x = info->rel_x;
+ window->placement.pending.rel_y = info->rel_y;
+ window->placement.pending.x = info->current.x;
+ window->placement.pending.y = info->current.y;
return TRUE;
}
diff --git a/src/core/constraints.h b/src/core/constraints.h
index 1517aa060..eaa4e4594 100644
--- a/src/core/constraints.h
+++ b/src/core/constraints.h
@@ -32,6 +32,7 @@ void meta_window_constrain (MetaWindow *window,
MetaGravity resize_gravity,
const MetaRectangle *orig,
MetaRectangle *new,
+ MetaRectangle *intermediate,
int *rel_x,
int *rel_y);
diff --git a/src/core/window-private.h b/src/core/window-private.h
index 04216113e..07f316e90 100644
--- a/src/core/window-private.h
+++ b/src/core/window-private.h
@@ -85,6 +85,7 @@ typedef enum
META_MOVE_RESIZE_FORCE_MOVE = 1 << 8,
META_MOVE_RESIZE_WAYLAND_STATE_CHANGED = 1 << 9,
META_MOVE_RESIZE_FORCE_UPDATE_MONITOR = 1 << 10,
+ META_MOVE_RESIZE_PLACEMENT_CHANGED = 1 << 11,
} MetaMoveResizeFlags;
typedef enum
@@ -141,12 +142,19 @@ typedef struct _MetaPlacementRule
int offset_y;
int width;
int height;
+
+ gboolean is_reactive;
+
+ MetaRectangle parent_rect;
} MetaPlacementRule;
typedef enum _MetaPlacementState
{
META_PLACEMENT_STATE_UNCONSTRAINED,
- META_PLACEMENT_STATE_CONSTRAINED,
+ META_PLACEMENT_STATE_CONSTRAINED_PENDING,
+ META_PLACEMENT_STATE_CONSTRAINED_CONFIGURED,
+ META_PLACEMENT_STATE_CONSTRAINED_FINISHED,
+ META_PLACEMENT_STATE_INVALIDATED,
} MetaPlacementState;
typedef enum
@@ -538,6 +546,13 @@ struct _MetaWindow
MetaPlacementRule *rule;
MetaPlacementState state;
+ struct {
+ int x;
+ int y;
+ int rel_x;
+ int rel_y;
+ } pending;
+
struct {
int rel_x;
int rel_y;
@@ -569,6 +584,7 @@ struct _MetaWindowClass
MetaGravity gravity,
MetaRectangle unconstrained_rect,
MetaRectangle constrained_rect,
+ MetaRectangle temporary_rect,
int rel_x,
int rel_y,
MetaMoveResizeFlags flags,
diff --git a/src/core/window.c b/src/core/window.c
index 6573c217e..5a9341578 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -4001,6 +4001,7 @@ meta_window_move_resize_internal (MetaWindow *window,
gboolean did_placement;
MetaRectangle unconstrained_rect;
MetaRectangle constrained_rect;
+ MetaRectangle temporary_rect;
int rel_x = 0;
int rel_y = 0;
MetaMoveResizeResultFlags result = 0;
@@ -4057,6 +4058,7 @@ meta_window_move_resize_internal (MetaWindow *window,
g_assert_not_reached ();
constrained_rect = unconstrained_rect;
+ temporary_rect = window->rect;
if (flags & (META_MOVE_RESIZE_MOVE_ACTION | META_MOVE_RESIZE_RESIZE_ACTION) &&
!(flags & META_MOVE_RESIZE_WAYLAND_FINISH_MOVE_RESIZE) &&
window->monitor)
@@ -4069,13 +4071,14 @@ meta_window_move_resize_internal (MetaWindow *window,
gravity,
&old_rect,
&constrained_rect,
+ &temporary_rect,
&rel_x,
&rel_y);
}
else if (window->placement.rule)
{
- rel_x = window->placement.current.rel_x;
- rel_y = window->placement.current.rel_y;
+ rel_x = window->placement.pending.rel_x;
+ rel_y = window->placement.pending.rel_y;
}
/* If we did placement, then we need to save the position that the window
@@ -4093,6 +4096,7 @@ meta_window_move_resize_internal (MetaWindow *window,
gravity,
unconstrained_rect,
constrained_rect,
+ temporary_rect,
rel_x,
rel_y,
flags, &result);
diff --git a/src/wayland/meta-wayland-xdg-shell.c b/src/wayland/meta-wayland-xdg-shell.c
index 89e33d5d3..8f4b7a0e7 100644
--- a/src/wayland/meta-wayland-xdg-shell.c
+++ b/src/wayland/meta-wayland-xdg-shell.c
@@ -138,7 +138,8 @@ G_DEFINE_TYPE_WITH_CODE (MetaWaylandXdgPopup,
popup_surface_iface_init));
static MetaPlacementRule
-meta_wayland_xdg_positioner_to_placement (MetaWaylandXdgPositioner *xdg_positioner);
+meta_wayland_xdg_positioner_to_placement (MetaWaylandXdgPositioner *xdg_positioner,
+ MetaWindow *parent_window);
static struct wl_resource *
meta_wayland_xdg_surface_get_wm_base_resource (MetaWaylandXdgSurface *xdg_surface);
@@ -1745,6 +1746,7 @@ xdg_surface_constructor_get_popup (struct wl_client *client,
struct wl_resource *xdg_surface_resource = constructor->resource;
MetaWaylandSurface *parent_surface =
surface_from_xdg_surface_resource (parent_resource);
+ MetaWindow *parent_window;
MetaWaylandXdgPositioner *xdg_positioner;
MetaWaylandXdgPopup *xdg_popup;
MetaWaylandXdgSurface *xdg_surface;
@@ -1783,9 +1785,11 @@ xdg_surface_constructor_get_popup (struct wl_client *client,
xdg_surface = META_WAYLAND_XDG_SURFACE (xdg_popup);
meta_wayland_xdg_surface_constructor_finalize (constructor, xdg_surface);
+ parent_window = meta_wayland_surface_get_window (parent_surface);
+
xdg_positioner = wl_resource_get_user_data (positioner_resource);
xdg_popup->setup.placement_rule =
- meta_wayland_xdg_positioner_to_placement (xdg_positioner);
+ meta_wayland_xdg_positioner_to_placement (xdg_positioner, parent_window);
xdg_popup->setup.parent_surface = parent_surface;
}
@@ -1892,8 +1896,13 @@ positioner_gravity_to_placement_gravity (uint32_t gravity)
}
static MetaPlacementRule
-meta_wayland_xdg_positioner_to_placement (MetaWaylandXdgPositioner *xdg_positioner)
+meta_wayland_xdg_positioner_to_placement (MetaWaylandXdgPositioner *xdg_positioner,
+ MetaWindow *parent_window)
{
+ MetaRectangle parent_rect;
+
+ meta_window_get_frame_rect (parent_window, &parent_rect);
+
return (MetaPlacementRule) {
.anchor_rect = xdg_positioner->anchor_rect,
.gravity = positioner_gravity_to_placement_gravity (xdg_positioner->gravity),
@@ -1903,6 +1912,8 @@ meta_wayland_xdg_positioner_to_placement (MetaWaylandXdgPositioner *xdg_position
.offset_y = xdg_positioner->offset_y,
.width = xdg_positioner->width,
.height = xdg_positioner->height,
+
+ .parent_rect = parent_rect,
};
}
diff --git a/src/wayland/meta-window-wayland.c b/src/wayland/meta-window-wayland.c
index e86378995..80be4b7a3 100644
--- a/src/wayland/meta-window-wayland.c
+++ b/src/wayland/meta-window-wayland.c
@@ -222,18 +222,23 @@ meta_window_wayland_move_resize_internal (MetaWindow *window,
MetaGravity gravity,
MetaRectangle unconstrained_rect,
MetaRectangle constrained_rect,
+ MetaRectangle temporary_rect,
int rel_x,
int rel_y,
MetaMoveResizeFlags flags,
MetaMoveResizeResultFlags *result)
{
MetaWindowWayland *wl_window = META_WINDOW_WAYLAND (window);
- gboolean can_move_now;
+ gboolean can_move_now = FALSE;
int configured_x;
int configured_y;
int configured_width;
int configured_height;
int geometry_scale;
+ int new_x;
+ int new_y;
+ int new_buffer_x;
+ int new_buffer_y;
g_assert (window->frame == NULL);
@@ -300,14 +305,61 @@ meta_window_wayland_move_resize_internal (MetaWindow *window,
/* This is a commit of an attach. We should move the window to match the
* new position the client wants. */
can_move_now = TRUE;
+ if (window->placement.state == META_PLACEMENT_STATE_CONSTRAINED_CONFIGURED)
+ window->placement.state = META_PLACEMENT_STATE_CONSTRAINED_FINISHED;
}
else
{
- /* If the size changed, or the state changed, then we have to wait until
- * the client acks our configure before moving the window. */
- if (constrained_rect.width != window->rect.width ||
- constrained_rect.height != window->rect.height ||
- (flags & META_MOVE_RESIZE_STATE_CHANGED))
+ if (window->placement.rule)
+ {
+ switch (window->placement.state)
+ {
+ case META_PLACEMENT_STATE_UNCONSTRAINED:
+ case META_PLACEMENT_STATE_CONSTRAINED_CONFIGURED:
+ case META_PLACEMENT_STATE_INVALIDATED:
+ can_move_now = FALSE;
+ break;
+ case META_PLACEMENT_STATE_CONSTRAINED_PENDING:
+ {
+ 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)
+ {
+ MetaWaylandWindowConfiguration *configuration;
+
+ configuration =
+ meta_wayland_window_configuration_new_relative (rel_x,
+ rel_y,
+ configured_width,
+ configured_height);
+ meta_window_wayland_configure (wl_window, configuration);
+
+ wl_window->last_sent_rel_x = rel_x;
+ wl_window->last_sent_rel_y = rel_y;
+
+ window->placement.state = META_PLACEMENT_STATE_CONSTRAINED_CONFIGURED;
+
+ can_move_now = FALSE;
+ }
+ else
+ {
+ window->placement.state =
+ META_PLACEMENT_STATE_CONSTRAINED_FINISHED;
+
+ can_move_now = TRUE;
+ }
+ break;
+ }
+ case META_PLACEMENT_STATE_CONSTRAINED_FINISHED:
+ can_move_now = TRUE;
+ break;
+ }
+ }
+ else if (constrained_rect.width != window->rect.width ||
+ constrained_rect.height != window->rect.height ||
+ flags & META_MOVE_RESIZE_STATE_CHANGED)
{
MetaWaylandWindowConfiguration *configuration;
@@ -328,32 +380,18 @@ meta_window_wayland_move_resize_internal (MetaWindow *window,
constrained_rect.height == 1)
return;
- if (window->placement.rule)
- {
- configuration =
- meta_wayland_window_configuration_new_relative (rel_x,
- rel_y,
- configured_width,
- configured_height);
- }
- else
- {
- configuration =
- meta_wayland_window_configuration_new (configured_x,
- configured_y,
- configured_width,
- configured_height,
- flags,
- gravity);
- }
-
+ configuration =
+ meta_wayland_window_configuration_new (configured_x,
+ configured_y,
+ configured_width,
+ configured_height,
+ flags,
+ gravity);
meta_window_wayland_configure (wl_window, configuration);
can_move_now = FALSE;
}
else
{
- /* We're just moving the window, so we don't need to wait for a configure
- * and then ack to simply move the window. */
can_move_now = TRUE;
}
}
@@ -365,33 +403,46 @@ meta_window_wayland_move_resize_internal (MetaWindow *window,
if (can_move_now)
{
- int new_x = constrained_rect.x;
- int new_y = constrained_rect.y;
-
- if (new_x != window->rect.x || new_y != window->rect.y)
- {
- *result |= META_MOVE_RESIZE_RESULT_MOVED;
- window->rect.x = new_x;
- window->rect.y = new_y;
- }
+ new_x = constrained_rect.x;
+ new_y = constrained_rect.y;
+ }
+ else
+ {
+ new_x = temporary_rect.x;
+ new_y = temporary_rect.y;
- int new_buffer_x = new_x - window->custom_frame_extents.left;
- int new_buffer_y = new_y - window->custom_frame_extents.top;
+ wl_window->has_pending_state_change |=
+ !!(flags & META_MOVE_RESIZE_STATE_CHANGED);
+ }
- if (new_buffer_x != window->buffer_rect.x || new_buffer_y != window->buffer_rect.y)
- {
- *result |= META_MOVE_RESIZE_RESULT_MOVED;
- window->buffer_rect.x = new_buffer_x;
- window->buffer_rect.y = new_buffer_y;
- }
+ if (new_x != window->rect.x || new_y != window->rect.y)
+ {
+ *result |= META_MOVE_RESIZE_RESULT_MOVED;
+ window->rect.x = new_x;
+ window->rect.y = new_y;
+ }
- if (flags & META_MOVE_RESIZE_WAYLAND_STATE_CHANGED)
- *result |= META_MOVE_RESIZE_RESULT_STATE_CHANGED;
+ if (window->placement.rule &&
+ window->placement.state == META_PLACEMENT_STATE_CONSTRAINED_FINISHED)
+ {
+ window->placement.current.rel_x = rel_x;
+ window->placement.current.rel_y = rel_y;
}
- else
+
+ new_buffer_x = new_x - window->custom_frame_extents.left;
+ new_buffer_y = new_y - window->custom_frame_extents.top;
+
+ if (new_buffer_x != window->buffer_rect.x ||
+ new_buffer_y != window->buffer_rect.y)
{
- wl_window->has_pending_state_change = (flags & META_MOVE_RESIZE_STATE_CHANGED) != 0;
+ *result |= META_MOVE_RESIZE_RESULT_MOVED;
+ window->buffer_rect.x = new_buffer_x;
+ window->buffer_rect.y = new_buffer_y;
}
+
+ if (can_move_now &&
+ flags & META_MOVE_RESIZE_WAYLAND_STATE_CHANGED)
+ *result |= META_MOVE_RESIZE_RESULT_STATE_CHANGED;
}
static void
@@ -857,8 +908,19 @@ meta_window_wayland_finish_move_resize (MetaWindow *window,
{
if (acked_configuration)
{
- rect.x = acked_configuration->x;
- rect.y = acked_configuration->y;
+ if (window->placement.rule)
+ {
+ MetaWindow *parent;
+
+ 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;
+ }
+ else
+ {
+ rect.x = acked_configuration->x;
+ rect.y = acked_configuration->y;
+ }
}
else
{
@@ -872,6 +934,14 @@ meta_window_wayland_finish_move_resize (MetaWindow *window,
if (rect.x != window->rect.x || rect.y != window->rect.y)
flags |= META_MOVE_RESIZE_MOVE_ACTION;
}
+ else
+ {
+ if (acked_configuration)
+ {
+ rect.x = acked_configuration->x;
+ rect.y = acked_configuration->y;
+ }
+ }
if (wl_window->has_pending_state_change && acked_configuration)
{
@@ -918,9 +988,24 @@ 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;
window->unconstrained_rect.width = placement_rule->width;
window->unconstrained_rect.height = placement_rule->height;
- meta_window_force_placement (window, FALSE);
+ meta_window_move_resize_internal (window,
+ (META_MOVE_RESIZE_MOVE_ACTION |
+ META_MOVE_RESIZE_RESIZE_ACTION |
+ META_MOVE_RESIZE_PLACEMENT_CHANGED),
+ META_GRAVITY_NORTH_WEST,
+ window->unconstrained_rect);
+}
+
+void
+meta_window_update_placement_rule (MetaWindow *window,
+ MetaPlacementRule *placement_rule)
+{
+ window->placement.state = META_PLACEMENT_STATE_INVALIDATED;
+ meta_window_place_with_placement_rule (window, placement_rule);
}
void
diff --git a/src/wayland/meta-window-wayland.h b/src/wayland/meta-window-wayland.h
index 0e18d4fe1..22824a6ae 100644
--- a/src/wayland/meta-window-wayland.h
+++ b/src/wayland/meta-window-wayland.h
@@ -53,6 +53,9 @@ void meta_window_wayland_place_relative_to (MetaWindow *window,
void meta_window_place_with_placement_rule (MetaWindow *window,
MetaPlacementRule *placement_rule);
+void meta_window_update_placement_rule (MetaWindow *window,
+ MetaPlacementRule *placement_rule);
+
void meta_window_wayland_set_min_size (MetaWindow *window,
int width,
int height);
diff --git a/src/x11/window-x11.c b/src/x11/window-x11.c
index fcd06f632..2c745f4aa 100644
--- a/src/x11/window-x11.c
+++ b/src/x11/window-x11.c
@@ -1312,6 +1312,7 @@ meta_window_x11_move_resize_internal (MetaWindow *window,
MetaGravity gravity,
MetaRectangle unconstrained_rect,
MetaRectangle constrained_rect,
+ MetaRectangle intermediate_rect,
int rel_x,
int rel_y,
MetaMoveResizeFlags flags,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]