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>
dev
Jonas Ådahl 5 years ago committed by Link Mauve
parent eff793ab46
commit a76d2053d0
  1. 103
      libweston-desktop/xdg-shell.c

@ -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");

Loading…
Cancel
Save