xdg-shell: Add support for popup repositioning
This adds support for xdg-shell v3, which adds support for repositioning popups. This adds support for explicit popup repositioning, as weston doesn't yet apply any constraining to popups, thus cannot implicitly reposition. Signed-off-by: Jonas Ådahl <jadahl@gmail.com> Tested-by: Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
This commit is contained in:
@@ -37,6 +37,7 @@
|
||||
|
||||
#include <libweston-desktop/libweston-desktop.h>
|
||||
#include "internal.h"
|
||||
#include "shared/helpers.h"
|
||||
|
||||
/************************************************************************************
|
||||
* WARNING: This file implements the stable xdg shell protocol.
|
||||
@@ -44,7 +45,7 @@
|
||||
* implements the older unstable xdg shell v6 protocol.
|
||||
************************************************************************************/
|
||||
|
||||
#define WD_XDG_SHELL_PROTOCOL_VERSION 1
|
||||
#define WD_XDG_SHELL_PROTOCOL_VERSION 3
|
||||
|
||||
static const char *weston_desktop_xdg_toplevel_role = "xdg_toplevel";
|
||||
static const char *weston_desktop_xdg_popup_role = "xdg_popup";
|
||||
@@ -129,10 +130,15 @@ struct weston_desktop_xdg_popup {
|
||||
struct weston_desktop_xdg_surface *parent;
|
||||
struct weston_desktop_seat *seat;
|
||||
struct weston_geometry geometry;
|
||||
|
||||
bool pending_reposition;
|
||||
uint32_t pending_reposition_token;
|
||||
};
|
||||
|
||||
#define weston_desktop_surface_role_biggest_size (sizeof(struct weston_desktop_xdg_toplevel))
|
||||
#define weston_desktop_surface_configure_biggest_size (sizeof(struct weston_desktop_xdg_toplevel))
|
||||
#define weston_desktop_surface_role_biggest_size \
|
||||
MAX(sizeof(struct weston_desktop_xdg_toplevel), \
|
||||
sizeof(struct weston_desktop_xdg_popup))
|
||||
#define weston_desktop_surface_configure_biggest_size weston_desktop_surface_role_biggest_size
|
||||
|
||||
|
||||
static struct weston_geometry
|
||||
@@ -301,6 +307,27 @@ weston_desktop_xdg_positioner_protocol_set_offset(struct wl_client *wl_client,
|
||||
positioner->offset.y = y;
|
||||
}
|
||||
|
||||
static void
|
||||
weston_desktop_xdg_positioner_protocol_set_reactive(struct wl_client *wl_client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
weston_desktop_xdg_positioner_protocol_set_parent_size(struct wl_client *wl_client,
|
||||
struct wl_resource *resource,
|
||||
int32_t width,
|
||||
int32_t height)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
weston_desktop_xdg_positioner_protocol_set_parent_configure(struct wl_client *wl_client,
|
||||
struct wl_resource *resource,
|
||||
uint32_t serial)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
weston_desktop_xdg_positioner_destroy(struct wl_resource *resource)
|
||||
{
|
||||
@@ -318,6 +345,9 @@ static const struct xdg_positioner_interface weston_desktop_xdg_positioner_imple
|
||||
.set_gravity = weston_desktop_xdg_positioner_protocol_set_gravity,
|
||||
.set_constraint_adjustment = weston_desktop_xdg_positioner_protocol_set_constraint_adjustment,
|
||||
.set_offset = weston_desktop_xdg_positioner_protocol_set_offset,
|
||||
.set_reactive = weston_desktop_xdg_positioner_protocol_set_reactive,
|
||||
.set_parent_size = weston_desktop_xdg_positioner_protocol_set_parent_size,
|
||||
.set_parent_configure = weston_desktop_xdg_positioner_protocol_set_parent_configure,
|
||||
};
|
||||
|
||||
static void
|
||||
@@ -852,9 +882,60 @@ weston_desktop_xdg_popup_protocol_grab(struct wl_client *wl_client,
|
||||
popup->seat, serial);
|
||||
}
|
||||
|
||||
static bool
|
||||
is_positioner_valid(struct weston_desktop_xdg_positioner *positioner)
|
||||
{
|
||||
/* Checking whether the size and anchor rect both have a positive size
|
||||
* is enough to verify both have been correctly set */
|
||||
if (positioner->size.width == 0 || positioner->anchor_rect.width == 0)
|
||||
return false;
|
||||
|
||||
if (positioner->anchor_rect.height == 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
weston_desktop_xdg_popup_protocol_reposition(struct wl_client *wl_client,
|
||||
struct wl_resource *resource,
|
||||
struct wl_resource *positioner_resource,
|
||||
uint32_t token)
|
||||
{
|
||||
struct weston_desktop_surface *dsurface =
|
||||
wl_resource_get_user_data(resource);
|
||||
struct weston_desktop_xdg_popup *popup =
|
||||
weston_desktop_surface_get_implementation_data(dsurface);
|
||||
struct weston_desktop_xdg_positioner *positioner =
|
||||
wl_resource_get_user_data(positioner_resource);
|
||||
struct weston_desktop_surface *parent_dsurface;
|
||||
|
||||
if (!is_positioner_valid(positioner)) {
|
||||
wl_resource_post_error(resource,
|
||||
XDG_WM_BASE_ERROR_INVALID_POSITIONER,
|
||||
"positioner object is not complete");
|
||||
return;
|
||||
}
|
||||
|
||||
parent_dsurface = popup->parent->desktop_surface;
|
||||
popup->geometry =
|
||||
weston_desktop_xdg_positioner_get_geometry(positioner,
|
||||
dsurface,
|
||||
parent_dsurface);
|
||||
popup->pending_reposition = true;
|
||||
popup->pending_reposition_token = token;
|
||||
if (popup->committed)
|
||||
weston_desktop_xdg_surface_schedule_configure(&popup->base);
|
||||
}
|
||||
|
||||
static void
|
||||
weston_desktop_xdg_popup_send_configure(struct weston_desktop_xdg_popup *popup)
|
||||
{
|
||||
if (popup->pending_reposition) {
|
||||
popup->pending_reposition = false;
|
||||
xdg_popup_send_repositioned(popup->resource,
|
||||
popup->pending_reposition_token);
|
||||
}
|
||||
xdg_popup_send_configure(popup->resource,
|
||||
popup->geometry.x,
|
||||
popup->geometry.y,
|
||||
@@ -887,6 +968,16 @@ static void
|
||||
weston_desktop_xdg_popup_update_position(struct weston_desktop_surface *dsurface,
|
||||
void *user_data)
|
||||
{
|
||||
struct weston_desktop_xdg_popup *popup =
|
||||
weston_desktop_surface_get_implementation_data(dsurface);
|
||||
struct weston_desktop_surface *parent_dsurface;
|
||||
|
||||
parent_dsurface = popup->parent->desktop_surface;
|
||||
weston_desktop_surface_set_relative_to(popup->base.desktop_surface,
|
||||
parent_dsurface,
|
||||
popup->geometry.x,
|
||||
popup->geometry.y,
|
||||
true);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -932,6 +1023,7 @@ weston_desktop_xdg_popup_resource_destroy(struct wl_resource *resource)
|
||||
static const struct xdg_popup_interface weston_desktop_xdg_popup_implementation = {
|
||||
.destroy = weston_desktop_destroy_request,
|
||||
.grab = weston_desktop_xdg_popup_protocol_grab,
|
||||
.reposition = weston_desktop_xdg_popup_protocol_reposition,
|
||||
};
|
||||
|
||||
static void
|
||||
@@ -1110,10 +1202,7 @@ weston_desktop_xdg_surface_protocol_get_popup(struct wl_client *wl_client,
|
||||
parent_surface = wl_resource_get_user_data(parent_resource);
|
||||
parent = weston_desktop_surface_get_implementation_data(parent_surface);
|
||||
|
||||
/* Checking whether the size and anchor rect both have a positive size
|
||||
* is enough to verify both have been correctly set */
|
||||
if (positioner->size.width == 0 || positioner->anchor_rect.width == 0 ||
|
||||
positioner->anchor_rect.height == 0) {
|
||||
if (!is_positioner_valid(positioner)) {
|
||||
wl_resource_post_error(resource,
|
||||
XDG_WM_BASE_ERROR_INVALID_POSITIONER,
|
||||
"positioner object is not complete");
|
||||
|
||||
Reference in New Issue
Block a user