[RFC weston 6/6] libweston-desktop: Implement xdg_shell_v6

Quentin Glidic sardemff7+wayland at sardemff7.net
Sun Jul 17 08:59:23 UTC 2016


From: Quentin Glidic <sardemff7+git at sardemff7.net>

Signed-off-by: Quentin Glidic <sardemff7+git at sardemff7.net>
---
 Makefile.am                           |   6 +-
 libweston-desktop/libweston-desktop.c |  10 +
 libweston-desktop/xdg-shell-v6.c      | 884 ++++++++++++++++++++++++++++++++++
 3 files changed, 899 insertions(+), 1 deletion(-)
 create mode 100644 libweston-desktop/xdg-shell-v6.c

diff --git a/Makefile.am b/Makefile.am
index 59d22f5..9861d0f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -120,12 +120,16 @@ libweston_desktop_la_SOURCES =				\
 	libweston-desktop/surface.c			\
 	libweston-desktop/wl-shell.c			\
 	libweston-desktop/xdg-shell-v5.c		\
+	libweston-desktop/xdg-shell-v6.c		\
 	libweston-desktop/xwayland.c
 
 nodist_libweston_desktop_la_SOURCES =				\
 	protocol/xdg-shell-unstable-v5-protocol.c		\
-	protocol/xdg-shell-unstable-v5-server-protocol.h
+	protocol/xdg-shell-unstable-v5-server-protocol.h	\
+	protocol/xdg-shell-unstable-v6-protocol.c		\
+	protocol/xdg-shell-unstable-v6-server-protocol.h
 
+libweston-desktop.la libweston-desktop/xdg-shell-v6.lo: protocol/xdg-shell-unstable-v6-server-protocol.h
 libweston-desktop.la libweston-desktop/xdg-shell-v5.lo: protocol/xdg-shell-unstable-v5-server-protocol.h
 
 if SYSTEMD_NOTIFY_SUPPORT
diff --git a/libweston-desktop/libweston-desktop.c b/libweston-desktop/libweston-desktop.c
index 5c6fcbb..9919701 100644
--- a/libweston-desktop/libweston-desktop.c
+++ b/libweston-desktop/libweston-desktop.c
@@ -40,6 +40,7 @@ struct weston_desktop {
     struct weston_compositor *compositor;
     struct weston_desktop_api api;
     void *user_data;
+    struct wl_global *xdg_shell_v6;
     struct wl_global *xdg_shell_v5;
     struct wl_global *wl_shell;
 };
@@ -66,6 +67,13 @@ weston_desktop_create(struct weston_compositor *compositor, const struct weston_
         self->api.struct_size = api->struct_size;
     memcpy(&self->api, api, self->api.struct_size);
 
+    self->xdg_shell_v6 = weston_desktop_xdg_shell_v6_create(self, self->compositor->wl_display);
+    if ( self->xdg_shell_v6 == NULL )
+    {
+        weston_desktop_destroy(self);
+        return NULL;
+    }
+
     self->xdg_shell_v5 = weston_desktop_xdg_shell_v5_create(self, self->compositor->wl_display);
     if ( self->xdg_shell_v5 == NULL )
     {
@@ -96,6 +104,8 @@ weston_desktop_destroy(struct weston_desktop *self)
         wl_global_destroy(self->wl_shell);
     if ( self->xdg_shell_v5 != NULL )
         wl_global_destroy(self->xdg_shell_v5);
+    if ( self->xdg_shell_v6 != NULL )
+        wl_global_destroy(self->xdg_shell_v6);
 
     free(self);
 }
diff --git a/libweston-desktop/xdg-shell-v6.c b/libweston-desktop/xdg-shell-v6.c
new file mode 100644
index 0000000..bc5bedf
--- /dev/null
+++ b/libweston-desktop/xdg-shell-v6.c
@@ -0,0 +1,884 @@
+/*
+ * Copyright © 2010-2012 Intel Corporation
+ * Copyright © 2011-2012 Collabora, Ltd.
+ * Copyright © 2013 Raspberry Pi Foundation
+ * Copyright © 2016 Quentin "Sardem FF7" Glidic
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "config.h"
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#include <stdbool.h>
+
+#include <wayland-server.h>
+
+#include "compositor.h"
+#include "zalloc.h"
+#include "protocol/xdg-shell-unstable-v6-server-protocol.h"
+
+#include "libweston-desktop.h"
+#include "internal.h"
+
+#define WD_XDG_SHELL_PROTOCOL_VERSION 1
+
+struct weston_desktop_xdg_positioner {
+    struct weston_desktop *desktop;
+    struct weston_desktop_client *client;
+    struct wl_resource *resource;
+
+    struct weston_desktop_surface_size size;
+    struct weston_desktop_surface_geometry anchor_rect;
+    enum zxdg_positioner_v6_anchor anchor;
+    enum zxdg_positioner_v6_gravity gravity;
+    enum zxdg_positioner_v6_constrain_adjustment constrain_adjustment;
+    struct weston_desktop_surface_position offset;
+};
+
+enum weston_desktop_xdg_surface_role {
+     WESTON_DESKTOP_XDG_SURFACE_ROLE_NONE,
+     WESTON_DESKTOP_XDG_SURFACE_ROLE_TOPLEVEL,
+     WESTON_DESKTOP_XDG_SURFACE_ROLE_POPUP,
+};
+
+struct weston_desktop_xdg_surface {
+    struct wl_resource *resource;
+    struct weston_desktop *desktop;
+    struct weston_desktop_client *client;
+    struct weston_surface *surface;
+    struct weston_desktop_surface *desktop_surface;
+    bool configured;
+    struct wl_event_source *configure_idle;
+    uint32_t configure_serial;
+
+    bool has_geometry;
+    struct weston_desktop_surface_geometry next_geometry, geometry;
+
+    enum weston_desktop_xdg_surface_role role;
+};
+
+struct weston_desktop_xdg_toplevel {
+    struct weston_desktop_xdg_surface base;
+
+    struct wl_resource *resource;
+    struct weston_desktop_xdg_surface *surface;
+    struct weston_desktop_surface_size requested_size;
+    struct {
+        bool maximized;
+        bool fullscreen;
+        bool resizing;
+        bool activated;
+    } requested_state, next_state, state;
+    struct weston_desktop_surface_size next_max_size, max_size, next_min_size, min_size;
+};
+
+struct weston_desktop_xdg_popup {
+    struct weston_desktop_xdg_surface base;
+
+    struct wl_resource *resource;
+    struct weston_desktop_xdg_surface *surface;
+    struct weston_desktop_xdg_surface *parent;
+    struct weston_desktop_seat *seat;
+};
+
+#define weston_desktop_surface_role_biggest_size (sizeof(struct weston_desktop_xdg_toplevel))
+
+
+static struct weston_desktop_surface_position
+_weston_desktop_xdg_positioner_get_position(struct weston_desktop_xdg_positioner *self, struct weston_desktop_surface *surface, struct weston_desktop_surface *parent)
+{
+    struct weston_desktop_surface_position position = {
+        .x = self->anchor_rect.x + self->offset.x,
+        .y = self->anchor_rect.y + self->offset.y,
+    };
+
+    if ( self->constrain_adjustment == ZXDG_POSITIONER_V6_CONSTRAIN_ADJUSTMENT_NONE )
+        return position;
+
+    /* TODO: add compositor policy configuration and the code here */
+
+    return position;
+}
+
+static void
+_weston_desktop_xdg_positioner_protocol_set_size(struct wl_client *wl_client, struct wl_resource *resource, int32_t width, int32_t height)
+{
+    struct weston_desktop_xdg_positioner *self = wl_resource_get_user_data(resource);
+
+    self->size.width = width;
+    self->size.height = height;
+}
+
+static void
+_weston_desktop_xdg_positioner_protocol_set_anchor_rect(struct wl_client *wl_client, struct wl_resource *resource, int32_t x, int32_t y, int32_t width, int32_t height)
+{
+    struct weston_desktop_xdg_positioner *self = wl_resource_get_user_data(resource);
+
+    self->anchor_rect.x = x;
+    self->anchor_rect.y = y;
+    self->anchor_rect.width = width;
+    self->anchor_rect.height = height;
+}
+
+static void
+_weston_desktop_xdg_positioner_protocol_set_anchor(struct wl_client *wl_client, struct wl_resource *resource, enum zxdg_positioner_v6_anchor anchor)
+{
+    struct weston_desktop_xdg_positioner *self = wl_resource_get_user_data(resource);
+
+    self->anchor = anchor;
+}
+
+static void
+_weston_desktop_xdg_positioner_protocol_set_gravity(struct wl_client *wl_client, struct wl_resource *resource, enum zxdg_positioner_v6_gravity gravity)
+{
+    struct weston_desktop_xdg_positioner *self = wl_resource_get_user_data(resource);
+
+    self->gravity = gravity;
+}
+
+static void
+_weston_desktop_xdg_positioner_protocol_set_constrain_adjustment(struct wl_client *wl_client, struct wl_resource *resource, enum zxdg_positioner_v6_constrain_adjustment constrain_adjustment)
+{
+    struct weston_desktop_xdg_positioner *self = wl_resource_get_user_data(resource);
+
+    self->constrain_adjustment = constrain_adjustment;
+}
+
+static void
+_weston_desktop_xdg_positioner_protocol_set_offset(struct wl_client *wl_client, struct wl_resource *resource, int32_t x, int32_t y)
+{
+    struct weston_desktop_xdg_positioner *self = wl_resource_get_user_data(resource);
+
+    self->offset.x = x;
+    self->offset.y = y;
+}
+
+
+static void
+_weston_desktop_xdg_positioner_destroy(struct wl_resource *resource)
+{
+    struct weston_desktop_xdg_positioner *self = wl_resource_get_user_data(resource);
+
+    free(self);
+}
+
+static const struct zxdg_positioner_v6_interface _weston_desktop_xdg_positioner_implementation = {
+    .destroy                  = weston_desktop_destroy_request,
+    .set_size                 = _weston_desktop_xdg_positioner_protocol_set_size,
+    .set_anchor_rect          = _weston_desktop_xdg_positioner_protocol_set_anchor_rect,
+    .set_anchor               = _weston_desktop_xdg_positioner_protocol_set_anchor,
+    .set_gravity              = _weston_desktop_xdg_positioner_protocol_set_gravity,
+    .set_constrain_adjustment = _weston_desktop_xdg_positioner_protocol_set_constrain_adjustment,
+    .set_offset               = _weston_desktop_xdg_positioner_protocol_set_offset,
+};
+
+
+static void _weston_desktop_xdg_surface_schedule_configure(struct weston_desktop_xdg_surface *self);
+
+
+static void
+_weston_desktop_xdg_toplevel_protocol_set_parent(struct wl_client *wl_client, struct wl_resource *resource, struct wl_resource *parent_resource)
+{
+    struct weston_desktop_surface *surface = wl_resource_get_user_data(resource);
+    struct weston_desktop_xdg_toplevel *self = weston_desktop_surface_get_implementation_data(surface);
+    struct weston_desktop_surface *parent = wl_resource_get_user_data(parent_resource);
+
+    weston_desktop_api_set_parent(self->surface->desktop, surface, parent);
+}
+
+static void
+_weston_desktop_xdg_toplevel_protocol_set_title(struct wl_client *wl_client, struct wl_resource *resource, const char *title)
+{
+    struct weston_desktop_surface *self = wl_resource_get_user_data(resource);
+
+    weston_desktop_surface_set_title(self, title);
+}
+
+static void
+_weston_desktop_xdg_toplevel_protocol_set_app_id(struct wl_client *wl_client, struct wl_resource *resource, const char *app_id)
+{
+    struct weston_desktop_surface *self = wl_resource_get_user_data(resource);
+
+    weston_desktop_surface_set_app_id(self, app_id);
+}
+
+static void
+_weston_desktop_xdg_toplevel_protocol_show_window_menu(struct wl_client *wl_client, struct wl_resource *resource, struct wl_resource *seat_resource, uint32_t serial, int32_t x, int32_t y)
+{
+    struct weston_desktop_surface *surface = wl_resource_get_user_data(resource);
+    struct weston_seat *seat = wl_resource_get_user_data(seat_resource);
+    struct weston_desktop_xdg_toplevel *self = weston_desktop_surface_get_implementation_data(surface);
+
+    weston_desktop_api_show_window_menu(self->surface->desktop, surface, seat, x, y);
+}
+
+static void
+_weston_desktop_xdg_toplevel_protocol_move(struct wl_client *wl_client, struct wl_resource *resource, struct wl_resource *seat_resource, uint32_t serial)
+{
+    struct weston_desktop_surface *surface = wl_resource_get_user_data(resource);
+    struct weston_seat *seat = wl_resource_get_user_data(seat_resource);
+    struct weston_desktop_xdg_toplevel *self = weston_desktop_surface_get_implementation_data(surface);
+
+    weston_desktop_api_move(self->surface->desktop, surface, seat, serial);
+}
+
+static void
+_weston_desktop_xdg_toplevel_protocol_resize(struct wl_client *wl_client, struct wl_resource *resource, struct wl_resource *seat_resource, uint32_t serial, enum zxdg_toplevel_v6_resize_edge edges)
+{
+    struct weston_desktop_surface *surface = wl_resource_get_user_data(resource);
+    struct weston_seat *seat = wl_resource_get_user_data(seat_resource);
+    struct weston_desktop_xdg_toplevel *self = weston_desktop_surface_get_implementation_data(surface);
+
+    weston_desktop_api_resize(self->surface->desktop, surface, seat, serial, edges);
+}
+
+static void
+_weston_desktop_xdg_toplevel_ack_configure(struct weston_desktop_xdg_toplevel *self)
+{
+    self->next_state = self->requested_state;
+}
+
+static void
+_weston_desktop_xdg_toplevel_protocol_set_min_size(struct wl_client *wl_client, struct wl_resource *resource, int32_t width, int32_t height)
+{
+    struct weston_desktop_surface *surface = wl_resource_get_user_data(resource);
+    struct weston_desktop_xdg_toplevel *self = weston_desktop_surface_get_implementation_data(surface);
+
+    self->next_min_size.width = width;
+    self->next_min_size.height = height;
+}
+
+static void
+_weston_desktop_xdg_toplevel_protocol_set_max_size(struct wl_client *wl_client, struct wl_resource *resource, int32_t width, int32_t height)
+{
+    struct weston_desktop_surface *surface = wl_resource_get_user_data(resource);
+    struct weston_desktop_xdg_toplevel *self = weston_desktop_surface_get_implementation_data(surface);
+
+    self->next_max_size.width = width;
+    self->next_max_size.height = height;
+}
+
+static void
+_weston_desktop_xdg_toplevel_protocol_set_maximized(struct wl_client *wl_client, struct wl_resource *resource)
+{
+    struct weston_desktop_surface *surface = wl_resource_get_user_data(resource);
+    struct weston_desktop_xdg_toplevel *self = weston_desktop_surface_get_implementation_data(surface);
+
+    weston_desktop_api_ask_maximized(self->surface->desktop, surface, true);
+}
+
+static void
+_weston_desktop_xdg_toplevel_protocol_unset_maximized(struct wl_client *wl_client, struct wl_resource *resource)
+{
+    struct weston_desktop_surface *surface = wl_resource_get_user_data(resource);
+    struct weston_desktop_xdg_toplevel *self = weston_desktop_surface_get_implementation_data(surface);
+
+    weston_desktop_api_ask_maximized(self->surface->desktop, surface, false);
+}
+
+static void
+_weston_desktop_xdg_toplevel_protocol_set_fullscreen(struct wl_client *wl_client, struct wl_resource *resource, struct wl_resource *output_resource)
+{
+    struct weston_desktop_surface *surface = wl_resource_get_user_data(resource);
+    struct weston_desktop_xdg_toplevel *self = weston_desktop_surface_get_implementation_data(surface);
+
+    weston_desktop_api_ask_fullscreen(self->surface->desktop, surface, true);
+}
+
+static void
+_weston_desktop_xdg_toplevel_protocol_unset_fullscreen(struct wl_client *wl_client, struct wl_resource *resource)
+{
+    struct weston_desktop_surface *surface = wl_resource_get_user_data(resource);
+    struct weston_desktop_xdg_toplevel *self = weston_desktop_surface_get_implementation_data(surface);
+
+    weston_desktop_api_ask_fullscreen(self->surface->desktop, surface, false);
+}
+
+static void
+_weston_desktop_xdg_toplevel_protocol_set_minimized(struct wl_client *wl_client, struct wl_resource *resource)
+{
+    struct weston_desktop_surface *surface = wl_resource_get_user_data(resource);
+    struct weston_desktop_xdg_toplevel *self = weston_desktop_surface_get_implementation_data(surface);
+
+    weston_desktop_api_ask_minimized(self->surface->desktop, surface);
+}
+
+
+static void
+_weston_desktop_xdg_toplevel_send_configure(struct weston_desktop_xdg_toplevel *self)
+{
+    uint32_t *s;
+    struct wl_array states;
+
+    wl_array_init(&states);
+    if ( self->requested_state.maximized )
+    {
+        s = wl_array_add(&states, sizeof(uint32_t));
+        *s = ZXDG_TOPLEVEL_V6_STATE_MAXIMIZED;
+    }
+    if ( self->requested_state.fullscreen )
+    {
+        s = wl_array_add(&states, sizeof(uint32_t));
+        *s = ZXDG_TOPLEVEL_V6_STATE_FULLSCREEN;
+    }
+    if ( self->requested_state.resizing )
+    {
+        s = wl_array_add(&states, sizeof(uint32_t));
+        *s = ZXDG_TOPLEVEL_V6_STATE_RESIZING;
+    }
+    if ( self->requested_state.activated )
+    {
+        s = wl_array_add(&states, sizeof(uint32_t));
+        *s = ZXDG_TOPLEVEL_V6_STATE_ACTIVATED;
+    }
+
+    zxdg_toplevel_v6_send_configure(self->resource, self->requested_size.width, self->requested_size.height, &states);
+
+    wl_array_release(&states);
+};
+
+static void
+_weston_desktop_xdg_toplevel_set_maximized(struct weston_desktop_surface *surface, void *user_data, bool maximized)
+{
+    struct weston_desktop_xdg_toplevel *self = user_data;
+
+    if ( self->state.maximized == maximized )
+        return;
+
+    self->requested_state.maximized = maximized;
+    _weston_desktop_xdg_surface_schedule_configure(&self->base);
+}
+
+static void
+_weston_desktop_xdg_toplevel_set_fullscreen(struct weston_desktop_surface *surface, void *user_data, bool fullscreen)
+{
+    struct weston_desktop_xdg_toplevel *self = user_data;
+
+    if ( self->state.fullscreen == fullscreen )
+        return;
+
+    self->requested_state.fullscreen = fullscreen;
+    _weston_desktop_xdg_surface_schedule_configure(&self->base);
+}
+
+static void
+_weston_desktop_xdg_toplevel_set_resizing(struct weston_desktop_surface *surface, void *user_data, bool resizing)
+{
+    struct weston_desktop_xdg_toplevel *self = user_data;
+
+    if ( self->state.resizing == resizing )
+        return;
+
+    self->requested_state.resizing = resizing;
+    _weston_desktop_xdg_surface_schedule_configure(&self->base);
+}
+
+static void
+_weston_desktop_xdg_toplevel_set_activated(struct weston_desktop_surface *surface, void *user_data, bool activated)
+{
+    struct weston_desktop_xdg_toplevel *self = user_data;
+
+    if ( self->state.activated == activated )
+        return;
+
+    self->requested_state.activated = activated;
+    _weston_desktop_xdg_surface_schedule_configure(&self->base);
+}
+
+static void
+_weston_desktop_xdg_toplevel_set_size(struct weston_desktop_surface *surface, void *user_data, int32_t width, int32_t height)
+{
+    struct weston_desktop_xdg_toplevel *self = user_data;
+    struct weston_surface *wsurface = weston_desktop_surface_get_surface(self->surface->desktop_surface);
+
+    if ( ( wsurface->width == width ) && ( wsurface->height == height ) )
+        return;
+
+    self->requested_size.width = width;
+    self->requested_size.height = height;
+    _weston_desktop_xdg_surface_schedule_configure(&self->base);
+}
+
+static void
+_weston_desktop_xdg_toplevel_commit(struct weston_desktop_xdg_toplevel *self, int32_t sx, int32_t sy)
+{
+    struct weston_surface *wsurface = weston_desktop_surface_get_surface(self->surface->desktop_surface);
+    bool reconfigure = false;
+
+    if ( self->next_state.maximized || self->next_state.fullscreen )
+        reconfigure = ( ( self->requested_size.width != wsurface->width ) || ( self->requested_size.height != wsurface->height ) );
+    if ( reconfigure )
+        _weston_desktop_xdg_surface_schedule_configure(&self->base);
+    else
+    {
+        self->state = self->next_state;
+        self->min_size = self->next_min_size;
+        self->max_size = self->next_max_size;
+
+        weston_desktop_api_commit(self->surface->desktop, self->surface->desktop_surface, sx, sy);
+    }
+}
+
+static void
+_weston_desktop_xdg_toplevel_close(struct weston_desktop_xdg_toplevel *self)
+{
+    zxdg_toplevel_v6_send_close(self->resource);
+}
+
+static bool
+_weston_desktop_xdg_toplevel_get_maximized(struct weston_desktop_surface *surface, void *user_data)
+{
+    struct weston_desktop_xdg_toplevel *self = user_data;
+
+    return self->state.maximized;
+}
+
+static bool
+_weston_desktop_xdg_toplevel_get_fullscreen(struct weston_desktop_surface *surface, void *user_data)
+{
+    struct weston_desktop_xdg_toplevel *self = user_data;
+
+    return self->state.fullscreen;
+}
+
+static bool
+_weston_desktop_xdg_toplevel_get_resizing(struct weston_desktop_surface *surface, void *user_data)
+{
+    struct weston_desktop_xdg_toplevel *self = user_data;
+
+    return self->state.resizing;
+}
+
+static bool
+_weston_desktop_xdg_toplevel_get_activated(struct weston_desktop_surface *surface, void *user_data)
+{
+    struct weston_desktop_xdg_toplevel *self = user_data;
+
+    return self->state.activated;
+}
+
+static void
+_weston_desktop_xdg_toplevel_free(struct weston_desktop_xdg_toplevel *self)
+{
+    weston_desktop_api_surface_free(self->surface->desktop, self->surface->desktop_surface);
+}
+
+static void
+_weston_desktop_xdg_toplevel_destroy(struct wl_resource *resource)
+{
+    struct weston_desktop_surface *surface = wl_resource_get_user_data(resource);
+
+    if ( surface != NULL )
+        weston_desktop_surface_resource_destroy(resource);
+}
+
+
+static const struct zxdg_toplevel_v6_interface _weston_desktop_xdg_toplevel_implementation = {
+    .destroy             = weston_desktop_destroy_request,
+    .set_parent          = _weston_desktop_xdg_toplevel_protocol_set_parent,
+    .set_title           = _weston_desktop_xdg_toplevel_protocol_set_title,
+    .set_app_id          = _weston_desktop_xdg_toplevel_protocol_set_app_id,
+    .show_window_menu    = _weston_desktop_xdg_toplevel_protocol_show_window_menu,
+    .move                = _weston_desktop_xdg_toplevel_protocol_move,
+    .resize              = _weston_desktop_xdg_toplevel_protocol_resize,
+    .set_min_size        = _weston_desktop_xdg_toplevel_protocol_set_min_size,
+    .set_max_size        = _weston_desktop_xdg_toplevel_protocol_set_max_size,
+    .set_maximized       = _weston_desktop_xdg_toplevel_protocol_set_maximized,
+    .unset_maximized     = _weston_desktop_xdg_toplevel_protocol_unset_maximized,
+    .set_fullscreen      = _weston_desktop_xdg_toplevel_protocol_set_fullscreen,
+    .unset_fullscreen    = _weston_desktop_xdg_toplevel_protocol_unset_fullscreen,
+    .set_minimized       = _weston_desktop_xdg_toplevel_protocol_set_minimized,
+};
+
+
+static void
+_weston_desktop_xdg_popup_protocol_grab(struct wl_client *wl_client, struct wl_resource *resource, struct wl_resource *seat_resource, uint32_t serial)
+{
+    struct weston_desktop_surface *surface = wl_resource_get_user_data(resource);
+    struct weston_desktop_xdg_popup *self = weston_desktop_surface_get_implementation_data(surface);
+    struct weston_desktop_xdg_popup *parent_popup;
+    struct weston_seat *wseat = wl_resource_get_user_data(seat_resource);
+    struct weston_desktop_seat *seat = weston_seat_get_desktop_seat(wseat);
+
+
+    if ( self->parent->role == WESTON_DESKTOP_XDG_SURFACE_ROLE_POPUP )
+    {
+        parent_popup = (struct weston_desktop_xdg_popup *) self->parent;
+        if ( parent_popup->parent->role == WESTON_DESKTOP_XDG_SURFACE_ROLE_POPUP )
+        {
+            wl_resource_post_error(self->resource, ZXDG_SHELL_V6_ERROR_NOT_THE_TOPMOST_POPUP, "xdg_popup was not created on the topmost popup");
+            return;
+        }
+    }
+
+    self->seat = seat;
+    weston_desktop_surface_grab(self->surface->desktop_surface, self->seat, serial);
+}
+
+
+static void
+_weston_desktop_xdg_popup_close(struct weston_desktop_xdg_popup *self)
+{
+    zxdg_popup_v6_send_popup_done(self->resource);
+}
+
+static void
+_weston_desktop_xdg_popup_free(struct weston_desktop_xdg_popup *self)
+{
+    if ( weston_desktop_surface_get_grab(self->base.desktop_surface) )
+    {
+        struct weston_desktop_surface *topmost;
+        struct wl_resource *resource = weston_desktop_client_get_resource(self->base.client);
+
+        topmost = weston_desktop_seat_grab_get_topmost_surface(self->seat);
+        if ( topmost != self->base.desktop_surface )
+            wl_resource_post_error(resource, ZXDG_SHELL_V6_ERROR_NOT_THE_TOPMOST_POPUP, "xdg_popup was destroyed while it was not the topmost popup.");
+        weston_desktop_surface_ungrab(self->base.desktop_surface, self->seat);
+    }
+}
+
+static void
+_weston_desktop_xdg_popup_destroy(struct wl_resource *resource)
+{
+    struct weston_desktop_surface *surface = wl_resource_get_user_data(resource);
+
+    if ( surface != NULL )
+        weston_desktop_surface_resource_destroy(resource);
+}
+
+static const struct zxdg_popup_v6_interface _weston_desktop_xdg_popup_implementation = {
+    .destroy             = weston_desktop_destroy_request,
+    .grab                = _weston_desktop_xdg_popup_protocol_grab,
+};
+
+
+static void
+_weston_desktop_xdg_surface_send_configure(void *user_data)
+{
+    struct weston_desktop_xdg_surface *self = user_data;
+
+    self->configure_idle = NULL;
+    self->configure_serial = wl_display_next_serial(weston_desktop_get_display(self->desktop));
+
+    switch ( self->role )
+    {
+    case WESTON_DESKTOP_XDG_SURFACE_ROLE_NONE:
+    break;
+    case WESTON_DESKTOP_XDG_SURFACE_ROLE_TOPLEVEL:
+        _weston_desktop_xdg_toplevel_send_configure((struct weston_desktop_xdg_toplevel *) self);
+    break;
+    case WESTON_DESKTOP_XDG_SURFACE_ROLE_POPUP:
+        //_weston_desktop_xdg_popup_send_configure((struct weston_desktop_xdg_popup *) self);
+    break;
+    }
+
+    zxdg_surface_v6_send_configure(self->resource, self->configure_serial);
+}
+
+static void
+_weston_desktop_xdg_surface_schedule_configure(struct weston_desktop_xdg_surface *self)
+{
+    struct wl_display *display = weston_desktop_get_display(self->desktop);
+    struct wl_event_loop *loop = wl_display_get_event_loop(display);
+    if ( self->configure_idle != NULL )
+        return;
+    self->configure_idle = wl_event_loop_add_idle(loop, _weston_desktop_xdg_surface_send_configure, self);
+}
+
+static void
+_weston_desktop_xdg_surface_protocol_get_toplevel(struct wl_client *wl_client, struct wl_resource *resource, uint32_t id)
+{
+    struct weston_desktop_surface *surface = wl_resource_get_user_data(resource);
+    struct weston_desktop_xdg_toplevel *self = weston_desktop_surface_get_implementation_data(surface);
+
+    self->resource = weston_desktop_surface_add_resource(self->surface->desktop_surface, &zxdg_toplevel_v6_interface, &_weston_desktop_xdg_toplevel_implementation, id, _weston_desktop_xdg_toplevel_destroy);
+    if ( self->resource == NULL )
+        return;
+}
+
+static void
+_weston_desktop_xdg_surface_protocol_get_popup(struct wl_client *wl_client, struct wl_resource *resource, uint32_t id, struct wl_resource *parent_resource, struct wl_resource *positioner_resource)
+{
+    struct weston_desktop_surface *surface = wl_resource_get_user_data(resource);
+    struct weston_desktop_xdg_popup *self = weston_desktop_surface_get_implementation_data(surface);
+    struct weston_desktop_surface *parent_surface = wl_resource_get_user_data(parent_resource);
+    struct weston_desktop_xdg_surface *parent = weston_desktop_surface_get_implementation_data(parent_surface);
+    struct weston_desktop_xdg_positioner *positioner = wl_resource_get_user_data(positioner_resource);
+    struct weston_desktop_surface_position position;
+
+    self->resource = weston_desktop_surface_add_resource(self->surface->desktop_surface, &zxdg_popup_v6_interface, &_weston_desktop_xdg_popup_implementation, id, _weston_desktop_xdg_popup_destroy);
+    if ( self->resource == NULL )
+        return;
+
+    self->parent = parent;
+
+    position = _weston_desktop_xdg_positioner_get_position(positioner, surface, parent_surface);
+
+    weston_desktop_surface_set_parent(self->surface->desktop_surface, parent_surface, position.x, position.y);
+}
+
+static void
+_weston_desktop_xdg_surface_protocol_set_window_geometry(struct wl_client *wl_client, struct wl_resource *resource, int32_t x, int32_t y, int32_t width, int32_t height)
+{
+    struct weston_desktop_surface *surface = wl_resource_get_user_data(resource);
+    struct weston_desktop_xdg_surface *self = weston_desktop_surface_get_implementation_data(surface);
+
+    self->has_geometry = true;
+    self->next_geometry.x = x;
+    self->next_geometry.y = y;
+    self->next_geometry.width = width;
+    self->next_geometry.height = height;
+}
+
+static void
+_weston_desktop_xdg_surface_protocol_ack_configure(struct wl_client *wl_client, struct wl_resource *resource, uint32_t serial)
+{
+    struct weston_desktop_surface *surface = wl_resource_get_user_data(resource);
+    struct weston_desktop_xdg_surface *self = weston_desktop_surface_get_implementation_data(surface);
+
+    if ( self->configure_serial != serial )
+    {
+        /* TODO: check better if serial is newer or older */
+        if ( self->configure_serial < serial )
+            _weston_desktop_xdg_surface_schedule_configure(self);
+        return;
+    }
+
+    self->configured = true;
+
+    switch ( self->role )
+    {
+    case WESTON_DESKTOP_XDG_SURFACE_ROLE_NONE:
+    break;
+    case WESTON_DESKTOP_XDG_SURFACE_ROLE_TOPLEVEL:
+        _weston_desktop_xdg_toplevel_ack_configure((struct weston_desktop_xdg_toplevel *) self);
+    break;
+    case WESTON_DESKTOP_XDG_SURFACE_ROLE_POPUP:
+        //_weston_desktop_xdg_popup_ack_configure((struct weston_desktop_xdg_popup *) self);
+    break;
+    }
+}
+
+
+static void
+_weston_desktop_xdg_surface_ping(struct weston_desktop_surface *surface, void *user_data)
+{
+    struct weston_desktop_xdg_surface *self = user_data;
+    uint32_t serial;
+
+    serial = weston_desktop_client_ping(self->client, self->desktop_surface);
+    if ( serial != 0 )
+        zxdg_shell_v6_send_ping(weston_desktop_client_get_resource(self->client), serial);
+}
+
+static void
+_weston_desktop_xdg_surface_commit(struct weston_desktop_surface *surface, void *user_data, int32_t sx, int32_t sy)
+{
+    struct weston_desktop_xdg_surface *self = user_data;
+
+    if ( ! self->configured )
+    {
+        wl_resource_post_error(self->resource, ZXDG_SURFACE_V6_ERROR_UNCONFIGURED_BUFFER, "xdg_surface has never been configured");
+        return;
+    }
+
+    if ( self->has_geometry )
+        self->geometry = self->next_geometry;
+
+    switch ( self->role )
+    {
+    case WESTON_DESKTOP_XDG_SURFACE_ROLE_NONE:
+    break;
+    case WESTON_DESKTOP_XDG_SURFACE_ROLE_TOPLEVEL:
+        _weston_desktop_xdg_toplevel_commit((struct weston_desktop_xdg_toplevel *) self, sx, sy);
+    break;
+    case WESTON_DESKTOP_XDG_SURFACE_ROLE_POPUP:
+        //_weston_desktop_xdg_popup_commit((struct weston_desktop_xdg_popup *) self);
+    break;
+    }
+}
+
+static void
+_weston_desktop_xdg_surface_close(struct weston_desktop_surface *surface, void *user_data)
+{
+    struct weston_desktop_xdg_surface *self = user_data;
+
+    switch ( self->role )
+    {
+    case WESTON_DESKTOP_XDG_SURFACE_ROLE_NONE:
+    break;
+    case WESTON_DESKTOP_XDG_SURFACE_ROLE_TOPLEVEL:
+        _weston_desktop_xdg_toplevel_close((struct weston_desktop_xdg_toplevel *) self);
+    break;
+    case WESTON_DESKTOP_XDG_SURFACE_ROLE_POPUP:
+        _weston_desktop_xdg_popup_close((struct weston_desktop_xdg_popup *) self);
+    break;
+    }
+}
+
+static struct weston_desktop_surface_geometry
+_weston_desktop_xdg_surface_get_geometry(struct weston_desktop_surface *surface, void *user_data)
+{
+    struct weston_desktop_xdg_surface *self = user_data;
+
+    if ( self->has_geometry )
+        return self->geometry;
+    return weston_surface_get_bounding_box(weston_desktop_surface_get_surface(self->desktop_surface));
+}
+
+static void
+_weston_desktop_xdg_surface_free(struct weston_desktop_surface *surface, void *user_data)
+{
+    struct weston_desktop_xdg_surface *self = user_data;
+
+
+    switch ( self->role )
+    {
+    case WESTON_DESKTOP_XDG_SURFACE_ROLE_NONE:
+    break;
+    case WESTON_DESKTOP_XDG_SURFACE_ROLE_TOPLEVEL:
+        _weston_desktop_xdg_toplevel_free((struct weston_desktop_xdg_toplevel *) self);
+    break;
+    case WESTON_DESKTOP_XDG_SURFACE_ROLE_POPUP:
+        _weston_desktop_xdg_popup_free((struct weston_desktop_xdg_popup *) self);
+    break;
+    }
+
+    if ( self->configure_idle != NULL )
+        wl_event_source_remove(self->configure_idle);
+
+    free(self);
+}
+
+
+static const struct zxdg_surface_v6_interface _weston_desktop_xdg_surface_implementation = {
+    .destroy             = weston_desktop_destroy_request,
+    .get_toplevel        = _weston_desktop_xdg_surface_protocol_get_toplevel,
+    .get_popup           = _weston_desktop_xdg_surface_protocol_get_popup,
+    .set_window_geometry = _weston_desktop_xdg_surface_protocol_set_window_geometry,
+    .ack_configure       = _weston_desktop_xdg_surface_protocol_ack_configure,
+};
+
+static const struct weston_desktop_surface_implementation _weston_desktop_xdg_surface_internal_implementation = {
+    /* These are used for toplevel only */
+    .set_maximized = _weston_desktop_xdg_toplevel_set_maximized,
+    .set_fullscreen = _weston_desktop_xdg_toplevel_set_fullscreen,
+    .set_resizing = _weston_desktop_xdg_toplevel_set_resizing,
+    .set_activated = _weston_desktop_xdg_toplevel_set_activated,
+    .set_size = _weston_desktop_xdg_toplevel_set_size,
+
+    .get_maximized = _weston_desktop_xdg_toplevel_get_maximized,
+    .get_fullscreen = _weston_desktop_xdg_toplevel_get_fullscreen,
+    .get_resizing = _weston_desktop_xdg_toplevel_get_resizing,
+    .get_activated = _weston_desktop_xdg_toplevel_get_activated,
+
+    /* Common API */
+    .commit =_weston_desktop_xdg_surface_commit,
+    .ping = _weston_desktop_xdg_surface_ping,
+    .close = _weston_desktop_xdg_surface_close,
+
+    .get_geometry =_weston_desktop_xdg_surface_get_geometry,
+
+    .free = _weston_desktop_xdg_surface_free,
+};
+
+static void
+_weston_desktop_xdg_shell_protocol_create_positioner(struct wl_client *wl_client, struct wl_resource *resource, uint32_t id)
+{
+    struct weston_desktop_client *client = wl_resource_get_user_data(resource);
+    struct weston_desktop_xdg_surface *self;
+
+    self = zalloc(sizeof(struct weston_desktop_xdg_positioner));
+    if ( self == NULL )
+    {
+        wl_client_post_no_memory(wl_client);
+        return;
+    }
+
+    self->client = client;
+    self->desktop = weston_desktop_client_get_desktop(self->client);
+
+    self->resource = wl_resource_create(wl_client, &zxdg_positioner_v6_interface, wl_resource_get_version(resource), id);
+    if ( self->resource == NULL )
+    {
+        wl_client_post_no_memory(wl_client);
+        free(self);
+        return;
+    }
+    wl_resource_set_implementation(self->resource, &_weston_desktop_xdg_positioner_implementation, self, _weston_desktop_xdg_positioner_destroy);
+}
+
+static void
+_weston_desktop_xdg_shell_protocol_get_xdg_surface(struct wl_client *wl_client, struct wl_resource *resource, uint32_t id, struct wl_resource *surface_resource)
+{
+    struct weston_desktop_client *client = wl_resource_get_user_data(resource);
+    struct weston_surface *surface = wl_resource_get_user_data(surface_resource);
+    struct weston_desktop_xdg_surface *self;
+
+    self = zalloc(weston_desktop_surface_role_biggest_size);
+    if ( self == NULL )
+    {
+        wl_client_post_no_memory(wl_client);
+        return;
+    }
+
+    self->client = client;
+    self->desktop = weston_desktop_client_get_desktop(self->client);
+    self->surface = surface;
+
+    self->desktop_surface = weston_desktop_surface_create(self->desktop, self->client, self->surface, &_weston_desktop_xdg_surface_internal_implementation, self);
+    if ( self->desktop_surface == NULL )
+    {
+        free(self);
+        return;
+    }
+}
+
+static void
+_weston_desktop_xdg_shell_protocol_pong(struct wl_client *wl_client, struct wl_resource *resource, uint32_t serial)
+{
+    struct weston_desktop_client *client = wl_resource_get_user_data(resource);
+
+    weston_desktop_client_pong(client, serial);
+}
+
+static const struct zxdg_shell_v6_interface _weston_desktop_xdg_shell_implementation = {
+    .destroy = weston_desktop_destroy_request,
+    .create_positioner = _weston_desktop_xdg_shell_protocol_create_positioner,
+    .get_xdg_surface = _weston_desktop_xdg_shell_protocol_get_xdg_surface,
+    .pong = _weston_desktop_xdg_shell_protocol_pong,
+};
+
+static void
+_weston_desktop_xdg_shell_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id)
+{
+    struct weston_desktop *desktop = data;
+
+    weston_desktop_client_create(desktop, client, NULL, &zxdg_shell_v6_interface, &_weston_desktop_xdg_shell_implementation, version, id);
+}
+
+struct wl_global *
+weston_desktop_xdg_shell_v6_create(struct weston_desktop *desktop, struct wl_display *display)
+{
+    return wl_global_create(display, &zxdg_shell_v6_interface, WD_XDG_SHELL_PROTOCOL_VERSION, desktop, _weston_desktop_xdg_shell_bind);
+}
-- 
2.9.0



More information about the wayland-devel mailing list