mirror of
https://github.com/brl/mutter.git
synced 2024-11-25 01:20:42 -05:00
wayland/xdg-shell: Add support for explicit popup repositioning
This commit completes the implementation of `xdg_wm_base` version 3, which introduces support for synchronized implicit and explicit popup repositioning. Explicit repositioning works by the client providing a new `xdg_positioner` object via a new request `xdg_popup.reposition`. If the repositioning is done in combination with the parent itself being reconfigured, the to be committed state of the parent is provided by the client via the `xdg_positioner` object, using `xdg_positioner.set__parent_configure`. https://gitlab.gnome.org/GNOME/mutter/merge_requests/705
This commit is contained in:
parent
5c37f5104e
commit
f97804f4f4
@ -37,7 +37,7 @@
|
|||||||
/* Global/master objects (version exported by wl_registry and negotiated through bind) */
|
/* Global/master objects (version exported by wl_registry and negotiated through bind) */
|
||||||
#define META_WL_COMPOSITOR_VERSION 4
|
#define META_WL_COMPOSITOR_VERSION 4
|
||||||
#define META_WL_DATA_DEVICE_MANAGER_VERSION 3
|
#define META_WL_DATA_DEVICE_MANAGER_VERSION 3
|
||||||
#define META_XDG_WM_BASE_VERSION 2
|
#define META_XDG_WM_BASE_VERSION 3
|
||||||
#define META_ZXDG_SHELL_V6_VERSION 1
|
#define META_ZXDG_SHELL_V6_VERSION 1
|
||||||
#define META_WL_SHELL_VERSION 1
|
#define META_WL_SHELL_VERSION 1
|
||||||
#define META_WL_SEAT_VERSION 5
|
#define META_WL_SEAT_VERSION 5
|
||||||
|
@ -68,6 +68,13 @@ typedef struct _MetaWaylandXdgPositioner
|
|||||||
int32_t offset_y;
|
int32_t offset_y;
|
||||||
|
|
||||||
gboolean is_reactive;
|
gboolean is_reactive;
|
||||||
|
|
||||||
|
gboolean has_parent_size;
|
||||||
|
int32_t parent_width;
|
||||||
|
int32_t parent_height;
|
||||||
|
|
||||||
|
gboolean acked_parent_configure;
|
||||||
|
uint32_t parent_configure_serial;
|
||||||
} MetaWaylandXdgPositioner;
|
} MetaWaylandXdgPositioner;
|
||||||
|
|
||||||
typedef struct _MetaWaylandXdgSurfaceConstructor
|
typedef struct _MetaWaylandXdgSurfaceConstructor
|
||||||
@ -112,6 +119,9 @@ struct _MetaWaylandXdgPopup
|
|||||||
MetaWaylandSurface *parent_surface;
|
MetaWaylandSurface *parent_surface;
|
||||||
gulong parent_surface_unmapped_handler_id;
|
gulong parent_surface_unmapped_handler_id;
|
||||||
|
|
||||||
|
uint32_t pending_reposition_token;
|
||||||
|
gboolean pending_repositioned;
|
||||||
|
|
||||||
MetaWaylandPopup *popup;
|
MetaWaylandPopup *popup;
|
||||||
|
|
||||||
gboolean dismissed_by_client;
|
gboolean dismissed_by_client;
|
||||||
@ -153,6 +163,10 @@ static void
|
|||||||
meta_wayland_xdg_surface_send_configure (MetaWaylandXdgSurface *xdg_surface,
|
meta_wayland_xdg_surface_send_configure (MetaWaylandXdgSurface *xdg_surface,
|
||||||
MetaWaylandWindowConfiguration *configuration);
|
MetaWaylandWindowConfiguration *configuration);
|
||||||
|
|
||||||
|
static void
|
||||||
|
scale_placement_rule (MetaPlacementRule *placement_rule,
|
||||||
|
MetaWaylandSurface *surface);
|
||||||
|
|
||||||
static MetaWaylandSurface *
|
static MetaWaylandSurface *
|
||||||
surface_from_xdg_surface_resource (struct wl_resource *resource)
|
surface_from_xdg_surface_resource (struct wl_resource *resource)
|
||||||
{
|
{
|
||||||
@ -566,9 +580,45 @@ xdg_popup_grab (struct wl_client *client,
|
|||||||
xdg_popup->setup.grab_serial = serial;
|
xdg_popup->setup.grab_serial = serial;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
xdg_popup_reposition (struct wl_client *client,
|
||||||
|
struct wl_resource *resource,
|
||||||
|
struct wl_resource *positioner_resource,
|
||||||
|
uint32_t token)
|
||||||
|
{
|
||||||
|
MetaWaylandXdgPopup *xdg_popup =
|
||||||
|
META_WAYLAND_XDG_POPUP (wl_resource_get_user_data (resource));
|
||||||
|
MetaWaylandSurfaceRole *surface_role =
|
||||||
|
META_WAYLAND_SURFACE_ROLE (xdg_popup);
|
||||||
|
MetaWaylandSurface *surface =
|
||||||
|
meta_wayland_surface_role_get_surface (surface_role);
|
||||||
|
MetaWindow *window;
|
||||||
|
MetaWindow *parent_window;
|
||||||
|
MetaWaylandXdgPositioner *xdg_positioner;
|
||||||
|
MetaPlacementRule placement_rule;
|
||||||
|
|
||||||
|
window = meta_wayland_surface_get_window (surface);
|
||||||
|
if (!window)
|
||||||
|
return;
|
||||||
|
|
||||||
|
parent_window = meta_wayland_surface_get_window (xdg_popup->parent_surface);
|
||||||
|
|
||||||
|
xdg_positioner = wl_resource_get_user_data (positioner_resource);
|
||||||
|
placement_rule = meta_wayland_xdg_positioner_to_placement (xdg_positioner,
|
||||||
|
parent_window);
|
||||||
|
|
||||||
|
xdg_popup->pending_reposition_token = token;
|
||||||
|
xdg_popup->pending_repositioned = TRUE;
|
||||||
|
|
||||||
|
scale_placement_rule (&placement_rule, surface);
|
||||||
|
|
||||||
|
meta_window_update_placement_rule (window, &placement_rule);
|
||||||
|
}
|
||||||
|
|
||||||
static const struct xdg_popup_interface meta_wayland_xdg_popup_interface = {
|
static const struct xdg_popup_interface meta_wayland_xdg_popup_interface = {
|
||||||
xdg_popup_destroy,
|
xdg_popup_destroy,
|
||||||
xdg_popup_grab,
|
xdg_popup_grab,
|
||||||
|
xdg_popup_reposition,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1150,6 +1200,12 @@ meta_wayland_xdg_popup_configure (MetaWaylandShellSurface *shell_surface,
|
|||||||
geometry_scale = meta_window_wayland_get_geometry_scale (parent_window);
|
geometry_scale = meta_window_wayland_get_geometry_scale (parent_window);
|
||||||
x = configuration->rel_x / geometry_scale;
|
x = configuration->rel_x / geometry_scale;
|
||||||
y = configuration->rel_y / geometry_scale;
|
y = configuration->rel_y / geometry_scale;
|
||||||
|
if (xdg_popup->pending_repositioned)
|
||||||
|
{
|
||||||
|
xdg_popup_send_repositioned (xdg_popup->resource,
|
||||||
|
xdg_popup->pending_reposition_token);
|
||||||
|
xdg_popup->pending_repositioned = FALSE;
|
||||||
|
}
|
||||||
xdg_popup_send_configure (xdg_popup->resource,
|
xdg_popup_send_configure (xdg_popup->resource,
|
||||||
x, y,
|
x, y,
|
||||||
configuration->width, configuration->height);
|
configuration->width, configuration->height);
|
||||||
@ -1905,6 +1961,50 @@ meta_wayland_xdg_positioner_to_placement (MetaWaylandXdgPositioner *xdg_position
|
|||||||
|
|
||||||
meta_window_get_frame_rect (parent_window, &parent_rect);
|
meta_window_get_frame_rect (parent_window, &parent_rect);
|
||||||
|
|
||||||
|
if (xdg_positioner->acked_parent_configure)
|
||||||
|
{
|
||||||
|
MetaWindowWayland *parent_wl_window = META_WINDOW_WAYLAND (parent_window);
|
||||||
|
uint32_t serial;
|
||||||
|
MetaWaylandWindowConfiguration *configuration;
|
||||||
|
|
||||||
|
serial = xdg_positioner->parent_configure_serial;
|
||||||
|
configuration = meta_window_wayland_peek_configuration (parent_wl_window,
|
||||||
|
serial);
|
||||||
|
|
||||||
|
if (configuration)
|
||||||
|
{
|
||||||
|
if (configuration->flags & META_MOVE_RESIZE_STATE_CHANGED)
|
||||||
|
{
|
||||||
|
if (configuration->has_position)
|
||||||
|
{
|
||||||
|
parent_rect.x = configuration->x;
|
||||||
|
parent_rect.y = configuration->y;
|
||||||
|
}
|
||||||
|
if (configuration->has_size)
|
||||||
|
{
|
||||||
|
parent_rect.width = configuration->width;
|
||||||
|
parent_rect.height = configuration->height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (xdg_positioner->has_parent_size)
|
||||||
|
{
|
||||||
|
meta_rectangle_resize_with_gravity (&parent_rect,
|
||||||
|
&parent_rect,
|
||||||
|
configuration->gravity,
|
||||||
|
xdg_positioner->parent_width,
|
||||||
|
xdg_positioner->parent_height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (xdg_positioner->has_parent_size)
|
||||||
|
{
|
||||||
|
meta_rectangle_resize_with_gravity (&parent_rect,
|
||||||
|
&parent_rect,
|
||||||
|
META_GRAVITY_SOUTH_EAST,
|
||||||
|
xdg_positioner->parent_width,
|
||||||
|
xdg_positioner->parent_height);
|
||||||
|
}
|
||||||
|
|
||||||
return (MetaPlacementRule) {
|
return (MetaPlacementRule) {
|
||||||
.anchor_rect = xdg_positioner->anchor_rect,
|
.anchor_rect = xdg_positioner->anchor_rect,
|
||||||
.gravity = positioner_gravity_to_placement_gravity (xdg_positioner->gravity),
|
.gravity = positioner_gravity_to_placement_gravity (xdg_positioner->gravity),
|
||||||
@ -2050,6 +2150,30 @@ xdg_positioner_set_reactive (struct wl_client *client,
|
|||||||
positioner->is_reactive = TRUE;
|
positioner->is_reactive = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
xdg_positioner_set_parent_size (struct wl_client *client,
|
||||||
|
struct wl_resource *resource,
|
||||||
|
int32_t parent_width,
|
||||||
|
int32_t parent_height)
|
||||||
|
{
|
||||||
|
MetaWaylandXdgPositioner *positioner = wl_resource_get_user_data (resource);
|
||||||
|
|
||||||
|
positioner->has_parent_size = TRUE;
|
||||||
|
positioner->parent_width = parent_width;
|
||||||
|
positioner->parent_height = parent_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
xdg_positioner_set_parent_configure (struct wl_client *client,
|
||||||
|
struct wl_resource *resource,
|
||||||
|
uint32_t serial)
|
||||||
|
{
|
||||||
|
MetaWaylandXdgPositioner *positioner = wl_resource_get_user_data (resource);
|
||||||
|
|
||||||
|
positioner->acked_parent_configure = TRUE;
|
||||||
|
positioner->parent_configure_serial = serial;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct xdg_positioner_interface meta_wayland_xdg_positioner_interface = {
|
static const struct xdg_positioner_interface meta_wayland_xdg_positioner_interface = {
|
||||||
xdg_positioner_destroy,
|
xdg_positioner_destroy,
|
||||||
xdg_positioner_set_size,
|
xdg_positioner_set_size,
|
||||||
@ -2059,6 +2183,8 @@ static const struct xdg_positioner_interface meta_wayland_xdg_positioner_interfa
|
|||||||
xdg_positioner_set_constraint_adjustment,
|
xdg_positioner_set_constraint_adjustment,
|
||||||
xdg_positioner_set_offset,
|
xdg_positioner_set_offset,
|
||||||
xdg_positioner_set_reactive,
|
xdg_positioner_set_reactive,
|
||||||
|
xdg_positioner_set_parent_size,
|
||||||
|
xdg_positioner_set_parent_configure,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -800,6 +800,23 @@ meta_window_wayland_new (MetaDisplay *display,
|
|||||||
return window;
|
return window;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MetaWaylandWindowConfiguration *
|
||||||
|
meta_window_wayland_peek_configuration (MetaWindowWayland *wl_window,
|
||||||
|
uint32_t serial)
|
||||||
|
{
|
||||||
|
GList *l;
|
||||||
|
|
||||||
|
for (l = wl_window->pending_configurations; l; l = l->next)
|
||||||
|
{
|
||||||
|
MetaWaylandWindowConfiguration *configuration = l->data;
|
||||||
|
|
||||||
|
if (configuration->serial == serial)
|
||||||
|
return configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static MetaWaylandWindowConfiguration *
|
static MetaWaylandWindowConfiguration *
|
||||||
acquire_acked_configuration (MetaWindowWayland *wl_window,
|
acquire_acked_configuration (MetaWindowWayland *wl_window,
|
||||||
MetaWaylandSurfaceState *pending)
|
MetaWaylandSurfaceState *pending)
|
||||||
|
@ -56,6 +56,10 @@ void meta_window_place_with_placement_rule (MetaWindow *window,
|
|||||||
void meta_window_update_placement_rule (MetaWindow *window,
|
void meta_window_update_placement_rule (MetaWindow *window,
|
||||||
MetaPlacementRule *placement_rule);
|
MetaPlacementRule *placement_rule);
|
||||||
|
|
||||||
|
MetaWaylandWindowConfiguration *
|
||||||
|
meta_window_wayland_peek_configuration (MetaWindowWayland *wl_window,
|
||||||
|
uint32_t serial);
|
||||||
|
|
||||||
void meta_window_wayland_set_min_size (MetaWindow *window,
|
void meta_window_wayland_set_min_size (MetaWindow *window,
|
||||||
int width,
|
int width,
|
||||||
int height);
|
int height);
|
||||||
|
Loading…
Reference in New Issue
Block a user