[RFC weston 1/6] Introduce libweston-desktop
Quentin Glidic
sardemff7+wayland at sardemff7.net
Sun Jul 17 08:59:18 UTC 2016
From: Quentin Glidic <sardemff7+git at sardemff7.net>
Signed-off-by: Quentin Glidic <sardemff7+git at sardemff7.net>
---
Makefile.am | 26 ++
configure.ac | 1 +
libweston-desktop/client.c | 139 +++++++
libweston-desktop/internal.h | 109 +++++
libweston-desktop/libweston-desktop.c | 191 +++++++++
libweston-desktop/libweston-desktop.h | 111 ++++++
libweston-desktop/libweston-desktop.pc.in | 12 +
libweston-desktop/seat.c | 328 +++++++++++++++
libweston-desktop/surface.c | 525 ++++++++++++++++++++++++
libweston-desktop/wl-shell.c | 318 +++++++++++++++
libweston-desktop/xdg-shell-v5.c | 641 ++++++++++++++++++++++++++++++
libweston-desktop/xwayland.c | 287 +++++++++++++
12 files changed, 2688 insertions(+)
create mode 100644 libweston-desktop/client.c
create mode 100644 libweston-desktop/internal.h
create mode 100644 libweston-desktop/libweston-desktop.c
create mode 100644 libweston-desktop/libweston-desktop.h
create mode 100644 libweston-desktop/libweston-desktop.pc.in
create mode 100644 libweston-desktop/seat.c
create mode 100644 libweston-desktop/surface.c
create mode 100644 libweston-desktop/wl-shell.c
create mode 100644 libweston-desktop/xdg-shell-v5.c
create mode 100644 libweston-desktop/xwayland.c
diff --git a/Makefile.am b/Makefile.am
index 436bb1b..6c44f2b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -105,6 +105,29 @@ libweston_la_SOURCES = \
shared/platform.h \
libweston/weston-egl-ext.h
+lib_LTLIBRARIES += libweston-desktop.la
+libweston_desktop_la_CPPFLAGS = $(AM_CPPFLAGS) -DIN_WESTON
+libweston_desktop_la_CFLAGS = $(AM_CFLAGS) $(COMPOSITOR_CFLAGS)
+libweston_desktop_la_LIBADD = libweston.la $(COMPOSITOR_LIBS)
+libweston_desktop_la_LDFLAGS = -release ${LIBWESTON_ABI_VERSION}
+
+libweston_desktop_la_SOURCES = \
+ libweston-desktop/client.c \
+ libweston-desktop/internal.h \
+ libweston-desktop/libweston-desktop.c \
+ libweston-desktop/libweston-desktop.h \
+ libweston-desktop/seat.c \
+ libweston-desktop/surface.c \
+ libweston-desktop/wl-shell.c \
+ libweston-desktop/xdg-shell-v5.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
+
+libweston-desktop.la libweston-desktop/xdg-shell-v5.lo: protocol/xdg-shell-unstable-v5-server-protocol.h
+
if SYSTEMD_NOTIFY_SUPPORT
module_LTLIBRARIES += systemd-notify.la
systemd_notify_la_LDFLAGS = -module -avoid-version
@@ -246,6 +269,9 @@ libwestoninclude_HEADERS = \
shared/zalloc.h \
shared/platform.h
+libwestoninclude_HEADERS += \
+ libweston-desktop/libweston-desktop.h
+
westonincludedir = $(includedir)/weston
westoninclude_HEADERS = compositor/weston.h
diff --git a/configure.ac b/configure.ac
index 85a475a..f52e8f3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -638,6 +638,7 @@ AC_CONFIG_FILES([Makefile libweston/version.h compositor/weston.pc])
# AC_CONFIG_FILES needs the full name when running autoconf, so we need to use
# libweston_abi_version here, and outside [] because of m4 quoting rules
AC_CONFIG_FILES([libweston/libweston-]libweston_abi_version[.pc:libweston/libweston.pc.in])
+AC_CONFIG_FILES([libweston-desktop/libweston-desktop-]libweston_abi_version[.pc:libweston-desktop/libweston-desktop.pc.in])
AM_CONDITIONAL([HAVE_GIT_REPO], [test -f $srcdir/.git/logs/HEAD])
diff --git a/libweston-desktop/client.c b/libweston-desktop/client.c
new file mode 100644
index 0000000..8b73f71
--- /dev/null
+++ b/libweston-desktop/client.c
@@ -0,0 +1,139 @@
+/*
+ * 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 <wayland-server.h>
+
+#include "compositor.h"
+#include "zalloc.h"
+
+#include "libweston-desktop.h"
+#include "internal.h"
+
+struct weston_desktop_client {
+ struct weston_desktop *desktop;
+ struct wl_client *client;
+ struct wl_resource *resource;
+ uint32_t ping_serial;
+ struct wl_event_source *ping_timer;
+ struct weston_desktop_surface *ping_surface;
+};
+
+static void
+_weston_desktop_client_destroy(struct wl_resource *resource)
+{
+ struct weston_desktop_client *self = wl_resource_get_user_data(resource);
+
+ free(self);
+}
+
+static int
+_weston_desktop_client_ping_timeout(void *user_data)
+{
+ struct weston_desktop_client *self = user_data;
+
+ weston_desktop_api_timeout(self->desktop, self->ping_surface);
+ return 1;
+}
+
+void
+weston_desktop_client_create(struct weston_desktop *desktop, struct wl_client *client, wl_dispatcher_func_t dispatcher, const struct wl_interface *interface, const void *implementation, uint32_t version, uint32_t id)
+{
+ struct weston_desktop_client *self;
+ struct wl_display *display;
+ struct wl_event_loop *loop;
+
+ self = zalloc(sizeof(struct weston_desktop_client));
+ if ( self == NULL )
+ {
+ wl_client_post_no_memory(client);
+ return;
+ }
+
+ self->desktop = desktop;
+ self->client = client;
+
+ self->resource = wl_resource_create(client, interface, version, id);
+ if ( self->resource == NULL )
+ {
+ wl_client_post_no_memory(client);
+ free(self);
+ return ;
+ }
+
+ if ( dispatcher != NULL )
+ wl_resource_set_dispatcher(self->resource, dispatcher, _weston_desktop_client_destroy, self, _weston_desktop_client_destroy);
+ else
+ wl_resource_set_implementation(self->resource, implementation, self, _weston_desktop_client_destroy);
+
+ display = wl_client_get_display(self->client);
+ loop = wl_display_get_event_loop(display);
+ self->ping_timer = wl_event_loop_add_timer(loop, _weston_desktop_client_ping_timeout, self);
+ if ( self->ping_timer == NULL )
+ wl_client_post_no_memory(client);
+}
+
+struct weston_desktop *
+weston_desktop_client_get_desktop(struct weston_desktop_client *self)
+{
+ return self->desktop;
+}
+
+struct wl_client *
+weston_desktop_client_get_client(struct weston_desktop_client *self)
+{
+ return self->client;
+}
+
+struct wl_resource *
+weston_desktop_client_get_resource(struct weston_desktop_client *self)
+{
+ return self->resource;
+}
+
+uint32_t
+weston_desktop_client_ping(struct weston_desktop_client *self, struct weston_desktop_surface *surface)
+{
+ if ( self->ping_serial != 0 )
+ return 0;
+ self->ping_serial = wl_display_next_serial(wl_client_get_display(self->client));
+ wl_event_source_timer_update(self->ping_timer, 10000);
+ self->ping_surface = surface;
+ return self->ping_serial;
+}
+
+void
+weston_desktop_client_pong(struct weston_desktop_client *self, uint32_t serial)
+{
+ if ( self->ping_serial != serial )
+ return;
+
+ wl_event_source_timer_update(self->ping_timer, 0);
+ self->ping_serial = 0;
+ self->ping_surface = NULL;
+}
diff --git a/libweston-desktop/internal.h b/libweston-desktop/internal.h
new file mode 100644
index 0000000..169b23f
--- /dev/null
+++ b/libweston-desktop/internal.h
@@ -0,0 +1,109 @@
+/*
+ * 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.
+ */
+
+#ifndef WESTON_DESKTOP_INTERNAL_H
+#define WESTON_DESKTOP_INTERNAL_H
+
+#include "compositor.h"
+
+struct weston_desktop_seat;
+struct weston_desktop_client;
+
+struct weston_compositor *weston_desktop_get_compositor(struct weston_desktop *desktop);
+struct wl_display *weston_desktop_get_display(struct weston_desktop *desktop);
+
+void weston_desktop_api_timeout(struct weston_desktop *desktop, struct weston_desktop_surface *surface);
+void weston_desktop_api_surface_new(struct weston_desktop *desktop, struct weston_desktop_surface *surface);
+void weston_desktop_api_surface_free(struct weston_desktop *desktop, struct weston_desktop_surface *surface);
+void weston_desktop_api_commit(struct weston_desktop *desktop, struct weston_desktop_surface *surface, int32_t sx, int32_t sy);
+void weston_desktop_api_show_window_menu(struct weston_desktop *desktop, struct weston_desktop_surface *surface, struct weston_seat *seat, int32_t x, int32_t y);
+void weston_desktop_api_set_parent(struct weston_desktop *desktop, struct weston_desktop_surface *surface, struct weston_desktop_surface *parent);
+void weston_desktop_api_move(struct weston_desktop *desktop, struct weston_desktop_surface *surface, struct weston_seat *seat, uint32_t serial);
+void weston_desktop_api_resize(struct weston_desktop *desktop, struct weston_desktop_surface *surface, struct weston_seat *seat, uint32_t serial, enum weston_desktop_surface_edge edges);
+void weston_desktop_api_ask_fullscreen(struct weston_desktop *desktop, struct weston_desktop_surface *surface, bool fullscreen);
+void weston_desktop_api_ask_maximized(struct weston_desktop *desktop, struct weston_desktop_surface *surface, bool maximized);
+void weston_desktop_api_ask_minimized(struct weston_desktop *desktop, struct weston_desktop_surface *surface);
+
+struct weston_desktop_surface_geometry weston_surface_get_bounding_box(struct weston_surface *surface);
+
+struct weston_desktop_seat *weston_seat_get_desktop_seat(struct weston_seat *seat);
+
+struct weston_desktop_surface_implementation {
+ void (*set_activated)(struct weston_desktop_surface *surface, void *user_data, bool activated);
+ void (*set_fullscreen)(struct weston_desktop_surface *surface, void *user_data, bool fullscreen);
+ void (*set_maximized)(struct weston_desktop_surface *surface, void *user_data, bool maximized);
+ void (*set_resizing)(struct weston_desktop_surface *surface, void *user_data, bool resizing);
+ void (*set_size)(struct weston_desktop_surface *surface, void *user_data, int32_t width, int32_t height);
+ void (*commit)(struct weston_desktop_surface *surface, void *user_data, int32_t sx, int32_t sy);
+ void (*ping)(struct weston_desktop_surface *surface, void *user_data);
+ void (*close)(struct weston_desktop_surface *surface, void *user_data);
+
+ bool (*get_activated)(struct weston_desktop_surface *surface, void *user_data);
+ bool (*get_fullscreen)(struct weston_desktop_surface *surface, void *user_data);
+ bool (*get_maximized)(struct weston_desktop_surface *surface, void *user_data);
+ bool (*get_resizing)(struct weston_desktop_surface *surface, void *user_data);
+ struct weston_desktop_surface_geometry (*get_geometry)(struct weston_desktop_surface *surface, void *user_data);
+ struct weston_desktop_surface_size (*get_max_size)(struct weston_desktop_surface *surface, void *user_data);
+ struct weston_desktop_surface_size (*get_min_size)(struct weston_desktop_surface *surface, void *user_data);
+
+ void (*free)(struct weston_desktop_surface *surface, void *user_data);
+};
+
+void weston_desktop_client_create(struct weston_desktop *desktop, struct wl_client *client, wl_dispatcher_func_t dispatcher, const struct wl_interface *interface, const void *implementation, uint32_t version, uint32_t id);
+
+struct weston_desktop *weston_desktop_client_get_desktop(struct weston_desktop_client *client);
+struct wl_client *weston_desktop_client_get_client(struct weston_desktop_client *client);
+struct wl_resource *weston_desktop_client_get_resource(struct weston_desktop_client *client);
+
+uint32_t weston_desktop_client_ping(struct weston_desktop_client *client, struct weston_desktop_surface *surface);
+void weston_desktop_client_pong(struct weston_desktop_client *client, uint32_t serial);
+
+struct weston_desktop_surface *weston_desktop_surface_create(struct weston_desktop *desktop, struct weston_desktop_client *client, struct weston_surface *surface, const struct weston_desktop_surface_implementation *implementation, void *implementation_data);
+void weston_desktop_surface_resource_destroy(struct wl_resource *resource);
+struct wl_resource *weston_desktop_surface_add_resource(struct weston_desktop_surface *self, const struct wl_interface *interface, const void *implementation, uint32_t id, wl_resource_destroy_func_t destroy);
+struct weston_desktop_surface *weston_desktop_surface_from_grab_link(struct wl_list *grab_link);
+
+struct weston_desktop_client *weston_desktop_surface_get_client(struct weston_desktop_surface *surface);
+bool weston_desktop_surface_has_implementation(struct weston_desktop_surface *surface, const struct weston_desktop_surface_implementation *implementation);
+void *weston_desktop_surface_get_implementation_data(struct weston_desktop_surface *surface);
+struct weston_desktop_surface *weston_desktop_surface_get_parent(struct weston_desktop_surface *surface);
+bool weston_desktop_surface_get_grab(struct weston_desktop_surface *surface);
+
+void weston_desktop_surface_set_title(struct weston_desktop_surface *surface, const char *title);
+void weston_desktop_surface_set_app_id(struct weston_desktop_surface *surface, const char *app_id);
+void weston_desktop_surface_set_parent(struct weston_desktop_surface *self, struct weston_desktop_surface *surface, int32_t x, int32_t y);
+void weston_desktop_surface_grab(struct weston_desktop_surface *popup, struct weston_desktop_seat *seat, uint32_t serial);
+void weston_desktop_surface_ungrab(struct weston_desktop_surface *popup, struct weston_desktop_seat *seat);
+
+struct weston_desktop_surface *weston_desktop_seat_grab_get_topmost_surface(struct weston_desktop_seat *seat);
+bool weston_desktop_seat_grab_start(struct weston_desktop_seat *seat, struct wl_client *client, uint32_t serial);
+void weston_desktop_seat_grab_add_surface(struct weston_desktop_seat *seat, struct wl_list *link);
+void weston_desktop_seat_grab_remove_surface(struct weston_desktop_seat *seat, struct wl_list *link);
+
+void weston_desktop_destroy_request(struct wl_client *client, struct wl_resource *resource);
+struct wl_global *weston_desktop_xdg_shell_v6_create(struct weston_desktop *desktop, struct wl_display *display);
+struct wl_global *weston_desktop_xdg_shell_v5_create(struct weston_desktop *desktop, struct wl_display *display);
+struct wl_global *weston_desktop_wl_shell_create(struct weston_desktop *desktop, struct wl_display *display);
+void weston_desktop_xwayland_init(struct weston_desktop *desktop);
+
+#endif /* WESTON_DESKTOP_INTERNAL_H */
diff --git a/libweston-desktop/libweston-desktop.c b/libweston-desktop/libweston-desktop.c
new file mode 100644
index 0000000..5c6fcbb
--- /dev/null
+++ b/libweston-desktop/libweston-desktop.c
@@ -0,0 +1,191 @@
+/*
+ * 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 <wayland-server.h>
+
+#include "compositor.h"
+#include "zalloc.h"
+
+#include "libweston-desktop.h"
+#include "internal.h"
+
+
+struct weston_desktop {
+ struct weston_compositor *compositor;
+ struct weston_desktop_api api;
+ void *user_data;
+ struct wl_global *xdg_shell_v5;
+ struct wl_global *wl_shell;
+};
+
+void
+weston_desktop_destroy_request(struct wl_client *client, struct wl_resource *resource)
+{
+ wl_resource_destroy(resource);
+}
+
+WL_EXPORT
+struct weston_desktop *
+weston_desktop_create(struct weston_compositor *compositor, const struct weston_desktop_api *api, void *user_data)
+{
+ struct weston_desktop *self;
+
+ self = zalloc(sizeof(struct weston_desktop));
+ self->compositor = compositor;
+ self->user_data = user_data;
+
+ if ( sizeof(struct weston_desktop_api) < api->struct_size )
+ self->api.struct_size = sizeof(struct weston_desktop_api);
+ else
+ self->api.struct_size = api->struct_size;
+ memcpy(&self->api, api, self->api.struct_size);
+
+ self->xdg_shell_v5 = weston_desktop_xdg_shell_v5_create(self, self->compositor->wl_display);
+ if ( self->xdg_shell_v5 == NULL )
+ {
+ weston_desktop_destroy(self);
+ return NULL;
+ }
+
+ self->wl_shell = weston_desktop_wl_shell_create(self, self->compositor->wl_display);
+ if ( self->wl_shell == NULL )
+ {
+ weston_desktop_destroy(self);
+ return NULL;
+ }
+
+ weston_desktop_xwayland_init(self);
+
+ return self;
+}
+
+WL_EXPORT
+void
+weston_desktop_destroy(struct weston_desktop *self)
+{
+ if ( self == NULL )
+ return;
+
+ if ( self->wl_shell != NULL )
+ wl_global_destroy(self->wl_shell);
+ if ( self->xdg_shell_v5 != NULL )
+ wl_global_destroy(self->xdg_shell_v5);
+
+ free(self);
+}
+
+
+struct weston_compositor *
+weston_desktop_get_compositor(struct weston_desktop *self)
+{
+ return self->compositor;
+}
+
+struct wl_display *
+weston_desktop_get_display(struct weston_desktop *self)
+{
+ return self->compositor->wl_display;
+}
+
+void
+weston_desktop_api_timeout(struct weston_desktop *self, struct weston_desktop_surface *surface)
+{
+ if ( self->api.timeout != NULL )
+ self->api.timeout(surface, self->user_data);
+}
+
+void
+weston_desktop_api_surface_new(struct weston_desktop *self, struct weston_desktop_surface *surface)
+{
+ if ( self->api.surface_new != NULL )
+ self->api.surface_new(surface, self->user_data);
+}
+
+void
+weston_desktop_api_surface_free(struct weston_desktop *self, struct weston_desktop_surface *surface)
+{
+ if ( self->api.surface_free != NULL )
+ self->api.surface_free(surface, self->user_data);
+}
+
+void
+weston_desktop_api_commit(struct weston_desktop *self, struct weston_desktop_surface *surface, int32_t sx, int32_t sy)
+{
+ if ( self->api.commit != NULL )
+ self->api.commit(surface, sx, sy, self->user_data);
+}
+
+void
+weston_desktop_api_show_window_menu(struct weston_desktop *self, struct weston_desktop_surface *surface, struct weston_seat *seat, int32_t x, int32_t y)
+{
+ if ( self->api.show_window_menu != NULL )
+ self->api.show_window_menu(surface, seat, x, y, self->user_data);
+}
+
+void
+weston_desktop_api_set_parent(struct weston_desktop *self, struct weston_desktop_surface *surface, struct weston_desktop_surface *parent)
+{
+ if ( self->api.set_parent != NULL )
+ self->api.set_parent(surface, parent, self->user_data);
+}
+
+void
+weston_desktop_api_move(struct weston_desktop *self, struct weston_desktop_surface *surface, struct weston_seat *seat, uint32_t serial)
+{
+ if ( self->api.move != NULL )
+ self->api.move(surface, seat, serial, self->user_data);
+}
+
+void
+weston_desktop_api_resize(struct weston_desktop *self, struct weston_desktop_surface *surface, struct weston_seat *seat, uint32_t serial, enum weston_desktop_surface_edge edges)
+{
+ if ( self->api.resize != NULL )
+ self->api.resize(surface, seat, serial, edges, self->user_data);
+}
+
+void
+weston_desktop_api_ask_fullscreen(struct weston_desktop *self, struct weston_desktop_surface *surface, bool fullscreen)
+{
+ if ( self->api.ask_fullscreen != NULL )
+ self->api.ask_fullscreen(surface, fullscreen, self->user_data);
+}
+
+void
+weston_desktop_api_ask_maximized(struct weston_desktop *self, struct weston_desktop_surface *surface, bool maximized)
+{
+ if ( self->api.ask_maximized != NULL )
+ self->api.ask_maximized(surface, maximized, self->user_data);
+}
+
+void
+weston_desktop_api_ask_minimized(struct weston_desktop *self, struct weston_desktop_surface *surface)
+{
+ if ( self->api.ask_minimized != NULL )
+ self->api.ask_minimized(surface, self->user_data);
+}
diff --git a/libweston-desktop/libweston-desktop.h b/libweston-desktop/libweston-desktop.h
new file mode 100644
index 0000000..c0e4a56
--- /dev/null
+++ b/libweston-desktop/libweston-desktop.h
@@ -0,0 +1,111 @@
+/*
+ * 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.
+ */
+
+#ifndef WESTON_DESKTOP_H
+#define WESTON_DESKTOP_H
+
+#include "compositor.h"
+#include <pixman.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct weston_desktop_surface_geometry {
+ int32_t x, y;
+ int32_t width, height;
+};
+
+struct weston_desktop_surface_position {
+ int32_t x, y;
+};
+
+struct weston_desktop_surface_size {
+ int32_t width, height;
+};
+
+enum weston_desktop_surface_edge {
+ WESTON_DESKTOP_SURFACE_EDGE_NONE = 0,
+ WESTON_DESKTOP_SURFACE_EDGE_TOP = 1,
+ WESTON_DESKTOP_SURFACE_EDGE_BOTTOM = 2,
+ WESTON_DESKTOP_SURFACE_EDGE_LEFT = 4,
+ WESTON_DESKTOP_SURFACE_EDGE_TOP_LEFT = 5,
+ WESTON_DESKTOP_SURFACE_EDGE_BOTTOM_LEFT = 6,
+ WESTON_DESKTOP_SURFACE_EDGE_RIGHT = 8,
+ WESTON_DESKTOP_SURFACE_EDGE_TOP_RIGHT = 9,
+ WESTON_DESKTOP_SURFACE_EDGE_BOTTOM_RIGHT = 10,
+};
+
+struct weston_desktop;
+struct weston_desktop_surface;
+
+struct weston_desktop_api {
+ size_t struct_size;
+ void (*timeout)(struct weston_desktop_surface *surface, void *user_data);
+ void (*surface_new)(struct weston_desktop_surface *surface, void *user_data);
+ void (*surface_free)(struct weston_desktop_surface *surface, void *user_data);
+ void (*commit)(struct weston_desktop_surface *surface, int32_t sx, int32_t sy, void *user_data);
+ void (*show_window_menu)(struct weston_desktop_surface *surface, struct weston_seat *seat, int32_t x, int32_t y, void *user_data);
+ void (*set_parent)(struct weston_desktop_surface *surface, struct weston_desktop_surface *parent, void *user_data);
+ void (*move)(struct weston_desktop_surface *surface, struct weston_seat *seat, uint32_t serial, void *user_data);
+ void (*resize)(struct weston_desktop_surface *surface, struct weston_seat *seat, uint32_t serial, enum weston_desktop_surface_edge edges, void *user_data);
+ void (*ask_fullscreen)(struct weston_desktop_surface *surface, bool fullscreen, void *user_data);
+ void (*ask_maximized)(struct weston_desktop_surface *surface, bool maximized, void *user_data);
+ void (*ask_minimized)(struct weston_desktop_surface *surface, void *user_data);
+};
+
+struct weston_desktop *weston_desktop_create(struct weston_compositor *compositor, const struct weston_desktop_api *api, void *user_data);
+void weston_desktop_destroy(struct weston_desktop *desktop);
+
+bool weston_surface_is_desktop_surface(struct weston_surface *surface);
+struct weston_desktop_surface *weston_surface_get_desktop_surface(struct weston_surface *surface);
+
+void weston_desktop_surface_set_user_data(struct weston_desktop_surface *self, void *user_data);
+void weston_desktop_surface_update_layer(struct weston_desktop_surface *surface);
+void weston_desktop_surface_set_activated(struct weston_desktop_surface *surface, bool activated);
+void weston_desktop_surface_set_fullscreen(struct weston_desktop_surface *surface, bool fullscreen);
+void weston_desktop_surface_set_maximized(struct weston_desktop_surface *surface, bool maximized);
+void weston_desktop_surface_set_resizing(struct weston_desktop_surface *surface, bool resized);
+void weston_desktop_surface_set_size(struct weston_desktop_surface *surface, int32_t width, int32_t height);
+void weston_desktop_surface_ping(struct weston_desktop_surface *surface);
+void weston_desktop_surface_close(struct weston_desktop_surface *surface);
+
+void *weston_desktop_surface_get_user_data(struct weston_desktop_surface *surface);
+struct weston_surface *weston_desktop_surface_get_surface(struct weston_desktop_surface *surface);
+struct weston_view *weston_desktop_surface_get_view(struct weston_desktop_surface *surface);
+const char *weston_desktop_surface_get_title(struct weston_desktop_surface *surface);
+const char *weston_desktop_surface_get_app_id(struct weston_desktop_surface *surface);
+bool weston_desktop_surface_get_activated(struct weston_desktop_surface *surface);
+bool weston_desktop_surface_get_maximized(struct weston_desktop_surface *surface);
+bool weston_desktop_surface_get_fullscreen(struct weston_desktop_surface *surface);
+bool weston_desktop_surface_get_resizing(struct weston_desktop_surface *surface);
+struct weston_desktop_surface_geometry weston_desktop_surface_get_geometry(struct weston_desktop_surface *surface);
+struct weston_desktop_surface_size weston_desktop_surface_get_max_size(struct weston_desktop_surface *surface);
+struct weston_desktop_surface_size weston_desktop_surface_get_min_size(struct weston_desktop_surface *surface);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* WESTON_DESKTOP_H */
diff --git a/libweston-desktop/libweston-desktop.pc.in b/libweston-desktop/libweston-desktop.pc.in
new file mode 100644
index 0000000..dd14ee0
--- /dev/null
+++ b/libweston-desktop/libweston-desktop.pc.in
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+pkgincludedir=${includedir}/libweston- at LIBWESTON_ABI_VERSION@
+
+Name: libweston-desktop
+Description: Desktop shells abstraction library for libweston compositors
+Version: @WESTON_VERSION@
+Requires.private: libweston wayland-server
+Cflags: -I${pkgincludedir}
+Libs: -L${libdir} -lweston- at LIBWESTON_ABI_VERSION@
diff --git a/libweston-desktop/seat.c b/libweston-desktop/seat.c
new file mode 100644
index 0000000..2889508
--- /dev/null
+++ b/libweston-desktop/seat.c
@@ -0,0 +1,328 @@
+/*
+ * 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 <assert.h>
+
+#include <wayland-server.h>
+
+#include "compositor.h"
+#include "zalloc.h"
+
+#include "libweston-desktop.h"
+#include "internal.h"
+
+struct weston_desktop_seat {
+ struct wl_listener seat_destroy_listener;
+ struct weston_seat *seat;
+ struct weston_keyboard_grab keyboard_grab;
+ struct weston_pointer_grab pointer_grab;
+ struct weston_touch_grab touch_grab;
+ bool initial_up;
+ struct wl_client *client;
+ struct wl_list surfaces;
+};
+
+static void _weston_desktop_seat_grab_end(struct weston_desktop_seat *self);
+
+static void
+_weston_desktop_seat_keyboard_key(struct weston_keyboard_grab *grab, uint32_t time, uint32_t key, enum wl_keyboard_key_state state)
+{
+ grab->keyboard->default_grab.interface->key(grab, time, key, state);
+}
+
+static void
+_weston_desktop_seat_keyboard_modifiers(struct weston_keyboard_grab *grab, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group)
+{
+ grab->keyboard->default_grab.interface->modifiers(grab, serial, mods_depressed, mods_latched, mods_locked, group);
+}
+
+static void
+_weston_desktop_seat_keyboard_cancel(struct weston_keyboard_grab *grab)
+{
+ struct weston_desktop_seat *self = wl_container_of(grab, self, keyboard_grab);
+
+ _weston_desktop_seat_grab_end(self);
+}
+
+static const struct weston_keyboard_grab_interface _weston_desktop_seat_keyboard_grab_interface = {
+ .key = _weston_desktop_seat_keyboard_key,
+ .modifiers = _weston_desktop_seat_keyboard_modifiers,
+ .cancel = _weston_desktop_seat_keyboard_cancel,
+};
+
+static void
+_weston_desktop_seat_pointer_focus(struct weston_pointer_grab *grab)
+{
+ struct weston_desktop_seat *self = wl_container_of(grab, self, pointer_grab);
+ struct weston_pointer *pointer = grab->pointer;
+ struct weston_view *view;
+ wl_fixed_t sx, sy;
+
+ view = weston_compositor_pick_view(pointer->seat->compositor, pointer->x, pointer->y, &sx, &sy);
+
+ if ( ( view != NULL ) && ( view->surface->resource != NULL ) && ( wl_resource_get_client(view->surface->resource) == self->client ) )
+ weston_pointer_set_focus(pointer, view, sx, sy);
+ else
+ weston_pointer_clear_focus(pointer);
+}
+
+static void
+_weston_desktop_seat_pointer_motion(struct weston_pointer_grab *grab, uint32_t time, struct weston_pointer_motion_event *event)
+{
+ grab->pointer->default_grab.interface->motion(grab, time, event);
+}
+
+static void
+_weston_desktop_seat_pointer_button(struct weston_pointer_grab *grab, uint32_t time, uint32_t button, enum wl_pointer_button_state state)
+{
+ struct weston_desktop_seat *self = wl_container_of(grab, self, pointer_grab);
+ struct weston_pointer *pointer = grab->pointer;
+ struct weston_compositor *compositor = pointer->seat->compositor;
+ struct wl_resource *resource;
+ uint32_t serial;
+ struct wl_display *display = compositor->wl_display;
+ struct wl_list *resource_list = NULL;
+
+ if ( pointer->focus_client != NULL )
+ resource_list = &pointer->focus_client->pointer_resources;
+ if ( ( resource_list != NULL ) && ! wl_list_empty(resource_list) )
+ {
+ serial = wl_display_next_serial(display);
+ wl_resource_for_each(resource, resource_list)
+ wl_pointer_send_button(resource, serial, time, button, state);
+ }
+ else if ( ( state == WL_POINTER_BUTTON_STATE_RELEASED ) && ( self->initial_up || ( ( time - grab->pointer->grab_time ) > 500 ) ) )
+ _weston_desktop_seat_grab_end(self);
+
+ if ( state == WL_POINTER_BUTTON_STATE_RELEASED )
+ self->initial_up = true;
+}
+
+static void
+_weston_desktop_seat_pointer_axis(struct weston_pointer_grab *grab, uint32_t time, struct weston_pointer_axis_event *event)
+{
+ grab->pointer->default_grab.interface->axis(grab, time, event);
+}
+
+static void
+_weston_desktop_seat_pointer_axis_source(struct weston_pointer_grab *grab, uint32_t source)
+{
+ grab->pointer->default_grab.interface->axis_source(grab, source);
+}
+
+static void
+_weston_desktop_seat_pointer_frame(struct weston_pointer_grab *grab)
+{
+ grab->pointer->default_grab.interface->frame(grab);
+}
+
+static void
+_weston_desktop_seat_pointer_cancel(struct weston_pointer_grab *grab)
+{
+ struct weston_desktop_seat *self = wl_container_of(grab, self, pointer_grab);
+
+ _weston_desktop_seat_grab_end(self);
+}
+
+static const struct weston_pointer_grab_interface _weston_desktop_seat_pointer_grab_interface = {
+ .focus = _weston_desktop_seat_pointer_focus,
+ .motion = _weston_desktop_seat_pointer_motion,
+ .button = _weston_desktop_seat_pointer_button,
+ .axis = _weston_desktop_seat_pointer_axis,
+ .axis_source = _weston_desktop_seat_pointer_axis_source,
+ .frame = _weston_desktop_seat_pointer_frame,
+ .cancel = _weston_desktop_seat_pointer_cancel,
+};
+
+static void
+_weston_desktop_seat_touch_down(struct weston_touch_grab *grab, uint32_t time, int touch_id, wl_fixed_t sx, wl_fixed_t sy)
+{
+ grab->touch->default_grab.interface->down(grab, time, touch_id, sx, sy);
+}
+
+static void
+_weston_desktop_seat_touch_up(struct weston_touch_grab *grab, uint32_t time, int touch_id)
+{
+ grab->touch->default_grab.interface->up(grab, time, touch_id);
+}
+
+static void
+_weston_desktop_seat_touch_motion(struct weston_touch_grab *grab, uint32_t time, int touch_id, wl_fixed_t sx, wl_fixed_t sy)
+{
+ grab->touch->default_grab.interface->motion(grab, time, touch_id, sx, sy);
+}
+
+static void
+_weston_desktop_seat_touch_frame(struct weston_touch_grab *grab)
+{
+ grab->touch->default_grab.interface->frame(grab);
+}
+
+static void
+_weston_desktop_seat_touch_cancel(struct weston_touch_grab *grab)
+{
+ struct weston_desktop_seat *self = wl_container_of(grab, self, touch_grab);
+
+ _weston_desktop_seat_grab_end(self);
+}
+
+static const struct weston_touch_grab_interface _weston_desktop_seat_touch_grab_interface = {
+ .down = _weston_desktop_seat_touch_down,
+ .up = _weston_desktop_seat_touch_up,
+ .motion = _weston_desktop_seat_touch_motion,
+ .frame = _weston_desktop_seat_touch_frame,
+ .cancel = _weston_desktop_seat_touch_cancel,
+};
+
+static void
+_weston_desktop_seat_destroy(struct wl_listener *listener, void *data)
+{
+ struct weston_desktop_seat *self = wl_container_of(listener, self, seat_destroy_listener);
+
+ free(self);
+}
+
+struct weston_desktop_seat *
+weston_seat_get_desktop_seat(struct weston_seat *seat)
+{
+ struct wl_listener *listener;
+ struct weston_desktop_seat *self;
+
+ listener = wl_signal_get(&seat->destroy_signal, _weston_desktop_seat_destroy);
+ if ( listener != NULL )
+ return wl_container_of(listener, self, seat_destroy_listener);
+
+ self = zalloc(sizeof(struct weston_desktop_seat));
+ if ( self == NULL )
+ return NULL;
+
+ self->seat = seat;
+
+ self->seat_destroy_listener.notify = _weston_desktop_seat_destroy;
+ wl_signal_add(&seat->destroy_signal, &self->seat_destroy_listener);
+
+ self->keyboard_grab.interface = &_weston_desktop_seat_keyboard_grab_interface;
+ self->pointer_grab.interface = &_weston_desktop_seat_pointer_grab_interface;
+ self->touch_grab.interface = &_weston_desktop_seat_touch_grab_interface;
+
+ wl_list_init(&self->surfaces);
+
+ return self;
+}
+
+struct weston_desktop_surface *
+weston_desktop_seat_grab_get_topmost_surface(struct weston_desktop_seat *self)
+{
+ if ( wl_list_empty(&self->surfaces) )
+ return NULL;
+
+ struct wl_list *grab_link = self->surfaces.next;
+
+ return weston_desktop_surface_from_grab_link(grab_link);
+}
+
+bool
+weston_desktop_seat_grab_start(struct weston_desktop_seat *self, struct wl_client *client, uint32_t serial)
+{
+ assert(self->client == NULL || self->client == client);
+
+ struct weston_keyboard *keyboard = weston_seat_get_keyboard(self->seat);
+ struct weston_pointer *pointer = weston_seat_get_pointer(self->seat);
+ struct weston_touch *touch = weston_seat_get_touch(self->seat);
+
+ if ( ( keyboard != NULL ) && ( keyboard->grab_serial == serial ) )
+ {
+ if ( keyboard->grab->interface != &_weston_desktop_seat_keyboard_grab_interface )
+ weston_keyboard_start_grab(keyboard, &self->keyboard_grab);
+ }
+ else if ( ( pointer != NULL ) && ( pointer->grab_serial == serial ) )
+ {
+ if ( pointer->grab->interface != &_weston_desktop_seat_pointer_grab_interface )
+ weston_pointer_start_grab(pointer, &self->pointer_grab);
+ }
+ else if ( ( touch != NULL ) && ( touch->grab_serial == serial ) )
+ {
+ if ( touch->grab->interface != &_weston_desktop_seat_touch_grab_interface )
+ weston_touch_start_grab(touch, &self->touch_grab);
+ }
+ else
+ return false;
+
+ self->initial_up = false;
+ self->client = client;
+
+ return true;
+}
+
+static void
+_weston_desktop_seat_grab_end(struct weston_desktop_seat *self)
+{
+ struct weston_keyboard *keyboard = weston_seat_get_keyboard(self->seat);
+ struct weston_pointer *pointer = weston_seat_get_pointer(self->seat);
+ struct weston_touch *touch = weston_seat_get_touch(self->seat);
+
+ struct wl_list *link, *tmp_link;
+ for ( link = self->surfaces.prev, tmp_link = link->next ; link != &self->surfaces ; link = tmp_link, tmp_link = link->next )
+ {
+ struct weston_desktop_surface *surface = weston_desktop_surface_from_grab_link(link);
+ wl_list_remove(link);
+ wl_list_init(link);
+ weston_desktop_surface_close(surface);
+ }
+
+ if ( keyboard->grab->interface == &_weston_desktop_seat_keyboard_grab_interface )
+ weston_keyboard_end_grab(keyboard);
+ else if ( pointer->grab->interface == &_weston_desktop_seat_pointer_grab_interface )
+ weston_pointer_end_grab(pointer);
+ else if ( touch->grab->interface == &_weston_desktop_seat_touch_grab_interface )
+ weston_touch_end_grab(touch);
+
+ self->client = NULL;
+}
+
+void
+weston_desktop_seat_grab_add_surface(struct weston_desktop_seat *self, struct wl_list *link)
+{
+ assert(self->client != NULL);
+
+ wl_list_insert(&self->surfaces, link);
+}
+
+void
+weston_desktop_seat_grab_remove_surface(struct weston_desktop_seat *self, struct wl_list *link)
+{
+ assert(self->client != NULL);
+
+ wl_list_remove(link);
+ wl_list_init(link);
+ if ( wl_list_empty(&self->surfaces) )
+ _weston_desktop_seat_grab_end(self);
+}
diff --git a/libweston-desktop/surface.c b/libweston-desktop/surface.c
new file mode 100644
index 0000000..239c805
--- /dev/null
+++ b/libweston-desktop/surface.c
@@ -0,0 +1,525 @@
+/*
+ * 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 <assert.h>
+
+#include <wayland-server.h>
+
+#include "compositor.h"
+#include "zalloc.h"
+
+#include "libweston-desktop.h"
+#include "internal.h"
+
+struct weston_desktop_surface {
+ struct weston_desktop *desktop;
+ struct weston_desktop_client *client;
+ const struct weston_desktop_surface_implementation *implementation;
+ void *implementation_data;
+ void *user_data;
+ struct weston_surface *surface;
+ struct weston_view *view;
+ struct wl_listener surface_destroy_listener;
+ struct wl_listener view_destroy_listener;
+ struct wl_list children_list;
+
+ struct wl_list resources;
+ struct {
+ char *title;
+ char *app_id;
+ };
+ struct {
+ struct weston_desktop_surface *parent;
+ struct wl_list children_link;
+ int32_t x;
+ int32_t y;
+ };
+ struct {
+ struct wl_list grab_link;
+ };
+};
+
+struct weston_desktop_surface_geometry
+weston_surface_get_bounding_box(struct weston_surface *surface)
+{
+ pixman_region32_t region;
+ pixman_box32_t *box;
+ struct weston_subsurface *subsurface;
+
+ pixman_region32_init_rect(®ion, 0, 0, surface->width, surface->height);
+
+ wl_list_for_each(subsurface, &surface->subsurface_list, parent_link)
+ pixman_region32_union_rect(®ion, ®ion, subsurface->position.x, subsurface->position.y, subsurface->surface->width, subsurface->surface->height);
+
+ box = pixman_region32_extents(®ion);
+ struct weston_desktop_surface_geometry geometry = {
+ .x = box->x1,
+ .y = box->y1,
+ .width = box->x2 - box->x1,
+ .height = box->y2 - box->y1,
+ };
+
+ pixman_region32_fini(®ion);
+
+ return geometry;
+}
+
+static void
+_weston_desktop_surface_destroy(struct weston_desktop_surface *self)
+{
+ wl_list_remove(&self->view_destroy_listener.link);
+ wl_list_remove(&self->surface_destroy_listener.link);
+
+ if ( ! wl_list_empty(&self->resources) )
+ {
+ struct wl_resource *resource, *tmp;
+ wl_resource_for_each_safe(resource, tmp, &self->resources)
+ {
+ wl_resource_set_user_data(resource, NULL);
+ wl_list_remove(wl_resource_get_link(resource));
+ }
+ }
+
+ self->implementation->free(self, self->implementation_data);
+
+ wl_list_remove(&self->children_link);
+
+ free(self);
+}
+
+void
+weston_desktop_surface_resource_destroy(struct wl_resource *resource)
+{
+ struct weston_desktop_surface *self = wl_resource_get_user_data(resource);
+ if ( self != NULL )
+ _weston_desktop_surface_destroy(self);
+}
+
+static void
+_weston_desktop_surface_surface_destroyed(struct wl_listener *listener, void *data)
+{
+ struct weston_desktop_surface *self = wl_container_of(listener, self, surface_destroy_listener);
+
+ _weston_desktop_surface_destroy(self);
+}
+
+static void
+_weston_desktop_surface_view_destroyed(struct wl_listener *listener, void *data)
+{
+ struct weston_desktop_surface *self = wl_container_of(listener, self, view_destroy_listener);
+ struct weston_view *view = data;
+
+ weston_view_damage_below(view);
+ _weston_desktop_surface_destroy(self);
+}
+
+static void
+_weston_desktop_surface_configure(struct weston_surface *surface, int32_t sx, int32_t sy)
+{
+ struct weston_desktop_surface *self = surface->configure_private;
+
+ if ( self->parent != NULL )
+ {
+ weston_view_set_transform_parent(self->view, self->parent->view);
+ weston_view_set_position(self->view, self->x, self->y);
+ weston_desktop_surface_update_layer(self->parent);
+ }
+ else
+ {
+ if ( self->implementation->commit != NULL )
+ self->implementation->commit(self, self->implementation_data, sx, sy);
+ }
+}
+
+struct weston_desktop_surface *
+weston_desktop_surface_create(struct weston_desktop *desktop, struct weston_desktop_client *client, struct weston_surface *surface, const struct weston_desktop_surface_implementation *implementation, void *implementation_data)
+{
+ assert(implementation->free != NULL);
+
+ struct weston_desktop_surface *self;
+
+ self = zalloc(sizeof(struct weston_desktop_surface));
+ if ( self == NULL )
+ {
+ if ( client != NULL )
+ wl_client_post_no_memory(weston_desktop_client_get_client(client));
+ return NULL;
+ }
+
+ self->desktop = desktop;
+ self->implementation = implementation;
+ self->implementation_data = implementation_data;
+ self->client = client;
+ self->surface = surface;
+
+ self->view = weston_view_create(self->surface);
+ if ( self->view == NULL )
+ {
+ if ( client != NULL )
+ wl_client_post_no_memory(weston_desktop_client_get_client(client));
+ free(self);
+ return NULL;
+ }
+
+ surface->configure = _weston_desktop_surface_configure;
+ surface->configure_private = self;
+
+ self->surface_destroy_listener.notify = _weston_desktop_surface_surface_destroyed;
+ wl_signal_add(&self->surface->destroy_signal, &self->surface_destroy_listener);
+ self->view_destroy_listener.notify = _weston_desktop_surface_view_destroyed;
+ wl_signal_add(&self->view->destroy_signal, &self->view_destroy_listener);
+
+ wl_list_init(&self->resources);
+ wl_list_init(&self->children_list);
+ wl_list_init(&self->children_link);
+
+ return self;
+}
+
+struct wl_resource *
+weston_desktop_surface_add_resource(struct weston_desktop_surface *self, const struct wl_interface *interface, const void *implementation, uint32_t id, wl_resource_destroy_func_t destroy)
+{
+ assert(self->client != NULL);
+
+ struct wl_resource *client_resource = weston_desktop_client_get_resource(self->client);
+ struct wl_client *wl_client = weston_desktop_client_get_client(self->client);
+ struct wl_resource *resource;
+
+ resource = wl_resource_create(wl_client, interface, wl_resource_get_version(client_resource), id);
+ if ( resource == NULL )
+ {
+ wl_client_post_no_memory(wl_client);
+ goto error;
+ }
+ wl_resource_set_implementation(resource, implementation, self, ( destroy != NULL ) ? destroy : weston_desktop_surface_resource_destroy);
+ wl_list_insert(&self->resources, wl_resource_get_link(resource));
+
+ return resource;
+
+error:
+ weston_view_destroy(self->view);
+ free(self);
+ return NULL;
+}
+
+struct weston_desktop_surface *
+weston_desktop_surface_from_grab_link(struct wl_list *grab_link)
+{
+ struct weston_desktop_surface *self = wl_container_of(grab_link, self, grab_link);
+
+ return self;
+}
+
+WL_EXPORT
+bool
+weston_surface_is_desktop_surface(struct weston_surface *surface)
+{
+ return ( surface->configure == _weston_desktop_surface_configure );
+}
+
+WL_EXPORT
+struct weston_desktop_surface *
+weston_surface_get_desktop_surface(struct weston_surface *surface)
+{
+ if ( ! weston_surface_is_desktop_surface(surface) )
+ return NULL;
+ return surface->configure_private;
+}
+
+WL_EXPORT
+void
+weston_desktop_surface_set_user_data(struct weston_desktop_surface *self, void *user_data)
+{
+ self->user_data = user_data;
+}
+
+WL_EXPORT
+void
+weston_desktop_surface_update_layer(struct weston_desktop_surface *self)
+{
+ struct weston_desktop_surface *child;
+ struct wl_list *link = &self->view->layer_link.link;
+ wl_list_for_each_reverse(child, &self->children_list, children_link)
+ {
+ struct weston_layer_entry *prev = wl_container_of(link->prev, prev, link);
+ if ( prev == &child->view->layer_link )
+ continue;
+
+ weston_view_damage_below(child->view);
+ weston_view_geometry_dirty(child->view);
+ weston_layer_entry_remove(&child->view->layer_link);
+ weston_layer_entry_insert(prev, &child->view->layer_link);
+ weston_view_geometry_dirty(child->view);
+ weston_surface_damage(child->surface);
+ weston_view_update_transform(child->view);
+
+ weston_desktop_surface_update_layer(child);
+ }
+}
+
+WL_EXPORT
+void
+weston_desktop_surface_set_activated(struct weston_desktop_surface *self, bool activated)
+{
+ if ( self->implementation->set_activated != NULL )
+ self->implementation->set_activated(self, self->implementation_data, activated);
+}
+
+WL_EXPORT
+void
+weston_desktop_surface_set_fullscreen(struct weston_desktop_surface *self, bool fullscreen)
+{
+ if ( self->implementation->set_fullscreen != NULL )
+ self->implementation->set_fullscreen(self, self->implementation_data, fullscreen);
+}
+
+WL_EXPORT
+void
+weston_desktop_surface_set_maximized(struct weston_desktop_surface *self, bool maximized)
+{
+ if ( self->implementation->set_maximized != NULL )
+ self->implementation->set_maximized(self, self->implementation_data, maximized);
+}
+
+WL_EXPORT
+void
+weston_desktop_surface_set_resizing(struct weston_desktop_surface *self, bool resizing)
+{
+ if ( self->implementation->set_resizing != NULL )
+ self->implementation->set_resizing(self, self->implementation_data, resizing);
+}
+
+WL_EXPORT
+void
+weston_desktop_surface_set_size(struct weston_desktop_surface *self, int32_t width, int32_t height)
+{
+ if ( self->implementation->set_size != NULL )
+ self->implementation->set_size(self, self->implementation_data, width, height);
+}
+
+WL_EXPORT
+void
+weston_desktop_surface_ping(struct weston_desktop_surface *self)
+{
+ if ( self->implementation->ping != NULL )
+ self->implementation->ping(self, self->implementation_data);
+}
+
+WL_EXPORT
+void
+weston_desktop_surface_close(struct weston_desktop_surface *self)
+{
+ if ( self->implementation->close != NULL )
+ self->implementation->close(self, self->implementation_data);
+}
+
+struct weston_desktop_client *
+weston_desktop_surface_get_client(struct weston_desktop_surface *self)
+{
+ return self->client;
+}
+
+bool
+weston_desktop_surface_has_implementation(struct weston_desktop_surface *self, const struct weston_desktop_surface_implementation *implementation)
+{
+ return ( self->implementation == implementation );
+}
+
+void *
+weston_desktop_surface_get_implementation_data(struct weston_desktop_surface *self)
+{
+ return self->implementation_data;
+}
+
+struct weston_desktop_surface *
+weston_desktop_surface_get_parent(struct weston_desktop_surface *self)
+{
+ return self->parent;
+}
+
+bool
+weston_desktop_surface_get_grab(struct weston_desktop_surface *self)
+{
+ return ( ! wl_list_empty(&self->grab_link) );
+}
+
+WL_EXPORT
+void *
+weston_desktop_surface_get_user_data(struct weston_desktop_surface *self)
+{
+ return self->user_data;
+}
+
+WL_EXPORT
+struct weston_surface *
+weston_desktop_surface_get_surface(struct weston_desktop_surface *self)
+{
+ return self->surface;
+}
+
+WL_EXPORT
+struct weston_view *
+weston_desktop_surface_get_view(struct weston_desktop_surface *self)
+{
+ return self->view;
+}
+
+WL_EXPORT
+const char *
+weston_desktop_surface_get_title(struct weston_desktop_surface *self)
+{
+ return self->title;
+}
+
+WL_EXPORT
+const char *
+weston_desktop_surface_get_app_id(struct weston_desktop_surface *self)
+{
+ return self->app_id;
+}
+WL_EXPORT
+bool
+weston_desktop_surface_get_activated(struct weston_desktop_surface *self)
+{
+ if ( self->implementation->get_activated != NULL )
+ return self->implementation->get_activated(self, self->implementation_data);
+ return false;
+}
+
+WL_EXPORT
+bool
+weston_desktop_surface_get_resizing(struct weston_desktop_surface *self)
+{
+ if ( self->implementation->get_resizing != NULL )
+ return self->implementation->get_resizing(self, self->implementation_data);
+ return false;
+}
+
+WL_EXPORT
+bool
+weston_desktop_surface_get_maximized(struct weston_desktop_surface *self)
+{
+ if ( self->implementation->get_maximized != NULL )
+ return self->implementation->get_maximized(self, self->implementation_data);
+ return false;
+}
+
+WL_EXPORT
+bool
+weston_desktop_surface_get_fullscreen(struct weston_desktop_surface *self)
+{
+ if ( self->implementation->get_fullscreen != NULL )
+ return self->implementation->get_fullscreen(self, self->implementation_data);
+ return false;
+}
+
+WL_EXPORT
+struct weston_desktop_surface_geometry
+weston_desktop_surface_get_geometry(struct weston_desktop_surface *self)
+{
+ if ( self->implementation->get_geometry != NULL )
+ return self->implementation->get_geometry(self, self->implementation_data);
+ return weston_surface_get_bounding_box(self->surface);
+}
+
+WL_EXPORT
+struct weston_desktop_surface_size
+weston_desktop_surface_get_max_size(struct weston_desktop_surface *self)
+{
+ struct weston_desktop_surface_size size = { 0, 0 };
+ if ( self->implementation->get_max_size != NULL )
+ size = self->implementation->get_max_size(self, self->implementation_data);
+ return size;
+}
+
+WL_EXPORT
+struct weston_desktop_surface_size
+weston_desktop_surface_get_min_size(struct weston_desktop_surface *self)
+{
+ struct weston_desktop_surface_size size = { 0, 0 };
+ if ( self->implementation->get_min_size != NULL )
+ size = self->implementation->get_min_size(self, self->implementation_data);
+ return size;
+}
+
+void
+weston_desktop_surface_set_title(struct weston_desktop_surface *self, const char *title)
+{
+ char *tmp;
+
+ tmp = strdup(title);
+ if ( tmp == NULL )
+ return;
+
+ free(self->title);
+ self->title = tmp;
+}
+
+void
+weston_desktop_surface_set_app_id(struct weston_desktop_surface *self, const char *app_id)
+{
+ char *tmp;
+
+ tmp = strdup(app_id);
+ if ( tmp == NULL )
+ return;
+
+ free(self->app_id);
+ self->app_id = tmp;
+}
+
+void
+weston_desktop_surface_set_parent(struct weston_desktop_surface *self, struct weston_desktop_surface *parent, int32_t x, int32_t y)
+{
+ self->parent = NULL;
+ wl_list_remove(&self->children_link);
+ wl_list_init(&self->children_link);
+
+ if ( parent != NULL )
+ {
+ self->parent = parent;
+ self->x = x;
+ self->y = y;
+ wl_list_insert(&self->parent->children_list, &self->children_link);
+ }
+}
+
+void
+weston_desktop_surface_grab(struct weston_desktop_surface *self, struct weston_desktop_seat *seat, uint32_t serial)
+{
+ if ( weston_desktop_seat_grab_start(seat, weston_desktop_client_get_client(self->client), serial) )
+ weston_desktop_seat_grab_add_surface(seat, &self->grab_link);
+ else
+ weston_desktop_surface_close(self);
+}
+
+void
+weston_desktop_surface_ungrab(struct weston_desktop_surface *self, struct weston_desktop_seat *seat)
+{
+ weston_desktop_seat_grab_remove_surface(seat, &self->grab_link);
+}
diff --git a/libweston-desktop/wl-shell.c b/libweston-desktop/wl-shell.c
new file mode 100644
index 0000000..28e3ab4
--- /dev/null
+++ b/libweston-desktop/wl-shell.c
@@ -0,0 +1,318 @@
+/*
+ * 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 <wayland-server.h>
+
+#include "compositor.h"
+#include "zalloc.h"
+
+#include "libweston-desktop.h"
+#include "internal.h"
+
+#define WD_WL_SHELL_PROTOCOL_VERSION 1
+
+enum weston_desktop_wl_shell_surface_state {
+ NONE,
+ TOPLEVEL,
+ MAXIMIZED,
+ FULLSCREEN,
+ TRANSIENT,
+ POPUP,
+};
+
+struct weston_desktop_wl_shell_surface {
+ struct wl_resource *resource;
+ struct weston_desktop *desktop;
+ struct wl_display *display;
+ struct weston_desktop_surface *surface;
+ bool pushed;
+ enum weston_desktop_wl_shell_surface_state state;
+};
+
+static void
+_weston_desktop_wl_shell_surface_set_size(struct weston_desktop_surface *surface, void *user_data, int32_t width, int32_t height)
+{
+ struct weston_desktop_wl_shell_surface *self = user_data;
+ struct weston_surface *wsurface = weston_desktop_surface_get_surface(self->surface);
+
+ if ( ( wsurface->width == width ) && ( wsurface->height == height ) )
+ return;
+
+ wl_shell_surface_send_configure(self->resource, WL_SHELL_SURFACE_RESIZE_NONE, width, height);
+}
+
+static void
+_weston_desktop_wl_shell_surface_commit(struct weston_desktop_surface *surface, void *user_data, int32_t sx, int32_t sy)
+{
+ struct weston_desktop_wl_shell_surface *self = user_data;
+
+ weston_desktop_api_commit(self->desktop, self->surface, sx, sy);
+}
+
+static void
+_weston_desktop_wl_shell_surface_ping(struct weston_desktop_surface *surface, void *user_data)
+{
+ struct weston_desktop_wl_shell_surface *self = user_data;
+ uint32_t serial;
+
+ serial = weston_desktop_client_ping(weston_desktop_surface_get_client(self->surface), self->surface);
+ if ( serial != 0 )
+ wl_shell_surface_send_ping(self->resource, serial);
+}
+
+static void
+_weston_desktop_wl_shell_surface_close(struct weston_desktop_surface *surface, void *user_data)
+{
+ struct weston_desktop_wl_shell_surface *self = user_data;
+
+ if ( self->state == POPUP )
+ wl_shell_surface_send_popup_done(self->resource);
+}
+
+static bool
+_weston_desktop_wl_shell_surface_get_maximized(struct weston_desktop_surface *surface, void *user_data)
+{
+ struct weston_desktop_wl_shell_surface *self = user_data;
+
+ return ( self->state == MAXIMIZED );
+}
+
+static bool
+_weston_desktop_wl_shell_surface_get_fullscreen(struct weston_desktop_surface *surface, void *user_data)
+{
+ struct weston_desktop_wl_shell_surface *self = user_data;
+
+ return ( self->state == FULLSCREEN );
+}
+
+static void
+_weston_desktop_wl_shell_change_state(struct weston_desktop_wl_shell_surface *self, enum weston_desktop_wl_shell_surface_state state, struct weston_desktop_surface *parent, int32_t x, int32_t y)
+{
+ bool to_push = ( state == TOPLEVEL ) || ( state == FULLSCREEN ) || ( state == MAXIMIZED );
+
+ self->state = state;
+ if ( self->pushed == to_push )
+ return;
+
+ self->pushed = to_push;
+ weston_desktop_surface_set_parent(self->surface, parent, x, y);
+ if ( self->pushed )
+ weston_desktop_api_surface_new(self->desktop, self->surface);
+ else
+ weston_desktop_api_surface_free(self->desktop, self->surface);
+}
+
+static void
+_weston_desktop_wl_shell_surface_free(struct weston_desktop_surface *surface, void *user_data)
+{
+ struct weston_desktop_wl_shell_surface *self = user_data;
+
+ _weston_desktop_wl_shell_change_state(self, NONE, NULL, 0, 0);
+
+ free(self);
+}
+
+static void
+_weston_desktop_wl_shell_surface_protocol_pong(struct wl_client *wl_client, struct wl_resource *resource, uint32_t serial)
+{
+ struct weston_desktop_surface *self = wl_resource_get_user_data(resource);
+
+ weston_desktop_client_pong(weston_desktop_surface_get_client(self), serial);
+}
+
+static void
+_weston_desktop_wl_shell_surface_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_wl_shell_surface *self = weston_desktop_surface_get_implementation_data(surface);
+
+ weston_desktop_api_move(self->desktop, surface, seat, serial);
+}
+
+static void
+_weston_desktop_wl_shell_surface_protocol_resize(struct wl_client *wl_client, struct wl_resource *resource, struct wl_resource *seat_resource, uint32_t serial, enum wl_shell_surface_resize 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_wl_shell_surface *self = weston_desktop_surface_get_implementation_data(surface);
+
+ weston_desktop_api_resize(self->desktop, surface, seat, serial, edges);
+}
+
+static void
+_weston_desktop_wl_shell_surface_protocol_set_toplevel(struct wl_client *wl_client, struct wl_resource *resource)
+{
+ struct weston_desktop_surface *surface = wl_resource_get_user_data(resource);
+ struct weston_desktop_wl_shell_surface *self = weston_desktop_surface_get_implementation_data(surface);
+
+ _weston_desktop_wl_shell_change_state(self, TOPLEVEL, NULL, 0, 0);
+}
+
+static void
+_weston_desktop_wl_shell_surface_protocol_set_transient(struct wl_client *wl_client, struct wl_resource *resource, struct wl_resource *parent_resource, int32_t x, int32_t y, enum wl_shell_surface_transient flags)
+{
+ struct weston_desktop_surface *surface = wl_resource_get_user_data(resource);
+ struct weston_surface *parent = wl_resource_get_user_data(parent_resource);
+ struct weston_desktop_wl_shell_surface *self = weston_desktop_surface_get_implementation_data(surface);
+
+ if ( weston_surface_is_desktop_surface(parent) )
+ _weston_desktop_wl_shell_change_state(self, TRANSIENT, weston_surface_get_desktop_surface(parent), x, y);
+}
+
+static void
+_weston_desktop_wl_shell_surface_protocol_set_fullscreen(struct wl_client *wl_client, struct wl_resource *resource, enum wl_shell_surface_fullscreen_method method, uint32_t framerate, struct wl_resource *output_resource)
+{
+ struct weston_desktop_surface *surface = wl_resource_get_user_data(resource);
+ struct weston_desktop_wl_shell_surface *self = weston_desktop_surface_get_implementation_data(surface);
+
+ _weston_desktop_wl_shell_change_state(self, FULLSCREEN, NULL, 0, 0);
+ weston_desktop_api_ask_fullscreen(self->desktop, surface, true);
+}
+
+static void
+_weston_desktop_wl_shell_surface_protocol_set_popup(struct wl_client *wl_client, struct wl_resource *resource, struct wl_resource *seat_resource, uint32_t serial, struct wl_resource *parent_resource, int32_t x, int32_t y, enum wl_shell_surface_transient flags)
+{
+ struct weston_desktop_surface *surface = wl_resource_get_user_data(resource);
+ struct weston_seat *wseat = wl_resource_get_user_data(seat_resource);
+ struct weston_desktop_seat *seat = weston_seat_get_desktop_seat(wseat);
+ struct weston_surface *parent = wl_resource_get_user_data(parent_resource);
+ struct weston_desktop_wl_shell_surface *self = weston_desktop_surface_get_implementation_data(surface);
+
+ if ( weston_surface_is_desktop_surface(parent) && ( seat != NULL ) )
+ {
+ _weston_desktop_wl_shell_change_state(self, POPUP, weston_surface_get_desktop_surface(parent), x, y);
+ weston_desktop_surface_grab(self->surface, seat, serial);
+ }
+}
+
+static void
+_weston_desktop_wl_shell_surface_protocol_set_maximized(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_wl_shell_surface *self = weston_desktop_surface_get_implementation_data(surface);
+
+ _weston_desktop_wl_shell_change_state(self, MAXIMIZED, NULL, 0, 0);
+ weston_desktop_api_ask_maximized(self->desktop, surface, true);
+}
+
+static void
+_weston_desktop_wl_shell_surface_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_wl_shell_surface_protocol_set_class(struct wl_client *wl_client, struct wl_resource *resource, const char *class_)
+{
+ struct weston_desktop_surface *self = wl_resource_get_user_data(resource);
+
+ weston_desktop_surface_set_app_id(self, class_);
+}
+
+
+static const struct wl_shell_surface_interface _weston_desktop_wl_shell_surface_implementation = {
+ .pong = _weston_desktop_wl_shell_surface_protocol_pong,
+ .move = _weston_desktop_wl_shell_surface_protocol_move,
+ .resize = _weston_desktop_wl_shell_surface_protocol_resize,
+ .set_toplevel = _weston_desktop_wl_shell_surface_protocol_set_toplevel,
+ .set_transient = _weston_desktop_wl_shell_surface_protocol_set_transient,
+ .set_fullscreen = _weston_desktop_wl_shell_surface_protocol_set_fullscreen,
+ .set_popup = _weston_desktop_wl_shell_surface_protocol_set_popup,
+ .set_maximized = _weston_desktop_wl_shell_surface_protocol_set_maximized,
+ .set_title = _weston_desktop_wl_shell_surface_protocol_set_title,
+ .set_class = _weston_desktop_wl_shell_surface_protocol_set_class,
+};
+
+static const struct weston_desktop_surface_implementation _weston_desktop_wl_shell_surface_internal_implementation = {
+ .set_size = _weston_desktop_wl_shell_surface_set_size,
+ .commit = _weston_desktop_wl_shell_surface_commit,
+ .ping = _weston_desktop_wl_shell_surface_ping,
+ .close = _weston_desktop_wl_shell_surface_close,
+
+ .get_maximized = _weston_desktop_wl_shell_surface_get_maximized,
+ .get_fullscreen = _weston_desktop_wl_shell_surface_get_fullscreen,
+
+ .free = _weston_desktop_wl_shell_surface_free,
+};
+
+static void
+_weston_desktop_wl_shell_protocol_get_shell_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_wl_shell_surface *self;
+
+
+ if ( weston_surface_set_role(surface, "wl_shell_surface", resource, WL_SHELL_ERROR_ROLE) < 0 )
+ return;
+
+ self = zalloc(sizeof(struct weston_desktop_wl_shell_surface));
+ if ( self == NULL )
+ {
+ wl_client_post_no_memory(wl_client);
+ return;
+ }
+
+ self->desktop = weston_desktop_client_get_desktop(client);
+ self->display = weston_desktop_get_display(self->desktop);
+
+ self->surface = weston_desktop_surface_create(self->desktop, client, surface, &_weston_desktop_wl_shell_surface_internal_implementation, self);
+ if ( self->surface == NULL )
+ {
+ free(self);
+ return;
+ }
+
+ self->resource = weston_desktop_surface_add_resource(self->surface, &wl_shell_surface_interface, &_weston_desktop_wl_shell_surface_implementation, id, NULL);
+}
+
+
+static const struct wl_shell_interface _weston_desktop_wl_shell_implementation = {
+ .get_shell_surface = _weston_desktop_wl_shell_protocol_get_shell_surface,
+};
+
+static void
+_weston_desktop_wl_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, &wl_shell_interface, &_weston_desktop_wl_shell_implementation, version, id);
+}
+
+struct wl_global *
+weston_desktop_wl_shell_create(struct weston_desktop *desktop, struct wl_display *display)
+{
+ return wl_global_create(display, &wl_shell_interface, WD_WL_SHELL_PROTOCOL_VERSION, desktop, _weston_desktop_wl_shell_bind);
+}
diff --git a/libweston-desktop/xdg-shell-v5.c b/libweston-desktop/xdg-shell-v5.c
new file mode 100644
index 0000000..53e141c
--- /dev/null
+++ b/libweston-desktop/xdg-shell-v5.c
@@ -0,0 +1,641 @@
+/*
+ * 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-v5-server-protocol.h"
+
+#include "libweston-desktop.h"
+#include "internal.h"
+
+#define WD_XDG_SHELL_PROTOCOL_VERSION 1
+
+struct weston_desktop_xdg_surface {
+ struct wl_resource *resource;
+ struct weston_desktop_surface *surface;
+ struct weston_desktop_client *client;
+ struct weston_desktop *desktop;
+ struct wl_event_source *configure_idle;
+ uint32_t configure_serial;
+ struct weston_desktop_surface_size requested_size;
+ struct {
+ bool maximized;
+ bool fullscreen;
+ bool resizing;
+ bool activated;
+ } requested_state, next_state, state;
+ bool has_next_geometry, has_geometry;
+ struct weston_desktop_surface_geometry next_geometry, geometry;
+};
+
+struct weston_desktop_xdg_popup {
+ struct wl_resource *resource;
+ struct weston_desktop_surface *popup;
+ struct weston_desktop *desktop;
+ struct weston_desktop_seat *seat;
+ struct wl_display *display;
+};
+
+static void
+_weston_desktop_xdg_surface_send_configure(void *data)
+{
+ struct weston_desktop_xdg_surface *self = data;
+ uint32_t *s;
+ struct wl_array states;
+
+ self->configure_idle = NULL;
+
+ self->configure_serial = wl_display_next_serial(weston_desktop_get_display(self->desktop));
+
+ wl_array_init(&states);
+ if ( self->requested_state.maximized )
+ {
+ s = wl_array_add(&states, sizeof(uint32_t));
+ *s = XDG_SURFACE_STATE_MAXIMIZED;
+ }
+ if ( self->requested_state.fullscreen )
+ {
+ s = wl_array_add(&states, sizeof(uint32_t));
+ *s = XDG_SURFACE_STATE_FULLSCREEN;
+ }
+ if ( self->requested_state.resizing )
+ {
+ s = wl_array_add(&states, sizeof(uint32_t));
+ *s = XDG_SURFACE_STATE_RESIZING;
+ }
+ if ( self->requested_state.activated )
+ {
+ s = wl_array_add(&states, sizeof(uint32_t));
+ *s = XDG_SURFACE_STATE_ACTIVATED;
+ }
+
+ xdg_surface_send_configure(self->resource, self->requested_size.width, self->requested_size.height, &states, self->configure_serial);
+
+ wl_array_release(&states);
+};
+
+static void
+_weston_desktop_xdg_surface_schedule_configure(struct weston_desktop_xdg_surface *self)
+{
+ if ( self->configure_idle != NULL )
+ return;
+ self->configure_idle = wl_event_loop_add_idle(wl_display_get_event_loop(weston_desktop_get_display(self->desktop)), _weston_desktop_xdg_surface_send_configure, self);
+}
+
+static void
+_weston_desktop_xdg_surface_set_maximized(struct weston_desktop_surface *surface, void *user_data, bool maximized)
+{
+ struct weston_desktop_xdg_surface *self = user_data;
+
+ if ( self->state.maximized == maximized )
+ return;
+
+ self->requested_state.maximized = maximized;
+ _weston_desktop_xdg_surface_schedule_configure(self);
+}
+
+static void
+_weston_desktop_xdg_surface_set_fullscreen(struct weston_desktop_surface *surface, void *user_data, bool fullscreen)
+{
+ struct weston_desktop_xdg_surface *self = user_data;
+
+ if ( self->state.fullscreen == fullscreen )
+ return;
+
+ self->requested_state.fullscreen = fullscreen;
+ _weston_desktop_xdg_surface_schedule_configure(self);
+}
+
+static void
+_weston_desktop_xdg_surface_set_resizing(struct weston_desktop_surface *surface, void *user_data, bool resizing)
+{
+ struct weston_desktop_xdg_surface *self = user_data;
+
+ if ( self->state.resizing == resizing )
+ return;
+
+ self->requested_state.resizing = resizing;
+ _weston_desktop_xdg_surface_schedule_configure(self);
+}
+
+static void
+_weston_desktop_xdg_surface_set_activated(struct weston_desktop_surface *surface, void *user_data, bool activated)
+{
+ struct weston_desktop_xdg_surface *self = user_data;
+
+ if ( self->state.activated == activated )
+ return;
+
+ self->requested_state.activated = activated;
+ _weston_desktop_xdg_surface_schedule_configure(self);
+}
+
+static void
+_weston_desktop_xdg_surface_set_size(struct weston_desktop_surface *surface, void *user_data, int32_t width, int32_t height)
+{
+ struct weston_desktop_xdg_surface *self = user_data;
+ struct weston_surface *wsurface = weston_desktop_surface_get_surface(self->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);
+}
+
+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;
+ struct weston_surface *wsurface = weston_desktop_surface_get_surface(self->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);
+ else
+ {
+ self->state = self->next_state;
+ if ( self->has_next_geometry )
+ {
+ self->has_geometry = true;
+ self->geometry = self->next_geometry;
+ }
+
+ weston_desktop_api_commit(self->desktop, self->surface, sx, sy);
+ }
+}
+
+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->surface);
+ if ( serial != 0 )
+ xdg_shell_send_ping(weston_desktop_client_get_resource(self->client), serial);
+}
+
+static void
+_weston_desktop_xdg_surface_close(struct weston_desktop_surface *surface, void *user_data)
+{
+ struct weston_desktop_xdg_surface *self = user_data;
+
+ xdg_surface_send_close(self->resource);
+}
+
+static bool
+_weston_desktop_xdg_surface_get_maximized(struct weston_desktop_surface *surface, void *user_data)
+{
+ struct weston_desktop_xdg_surface *self = user_data;
+
+ return self->state.maximized;
+}
+
+static bool
+_weston_desktop_xdg_surface_get_fullscreen(struct weston_desktop_surface *surface, void *user_data)
+{
+ struct weston_desktop_xdg_surface *self = user_data;
+
+ return self->state.fullscreen;
+}
+
+static bool
+_weston_desktop_xdg_surface_get_resizing(struct weston_desktop_surface *surface, void *user_data)
+{
+ struct weston_desktop_xdg_surface *self = user_data;
+
+ return self->state.resizing;
+}
+
+static bool
+_weston_desktop_xdg_surface_get_activated(struct weston_desktop_surface *surface, void *user_data)
+{
+ struct weston_desktop_xdg_surface *self = user_data;
+
+ return self->state.activated;
+}
+
+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->surface));
+}
+
+static void
+_weston_desktop_xdg_surface_free(struct weston_desktop_surface *surface, void *user_data)
+{
+ struct weston_desktop_xdg_surface *self = user_data;
+
+ weston_desktop_api_surface_free(self->desktop, self->surface);
+
+ if ( self->configure_idle != NULL )
+ wl_event_source_remove(self->configure_idle);
+
+ free(self);
+}
+
+static void
+_weston_desktop_xdg_surface_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_surface *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->desktop, surface, parent);
+}
+
+static void
+_weston_desktop_xdg_surface_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_surface_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_surface_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_surface *self = weston_desktop_surface_get_implementation_data(surface);
+
+ weston_desktop_api_show_window_menu(self->desktop, surface, seat, x, y);
+}
+
+static void
+_weston_desktop_xdg_surface_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_surface *self = weston_desktop_surface_get_implementation_data(surface);
+
+ weston_desktop_api_move(self->desktop, surface, seat, serial);
+}
+
+static void
+_weston_desktop_xdg_surface_protocol_resize(struct wl_client *wl_client, struct wl_resource *resource, struct wl_resource *seat_resource, uint32_t serial, enum xdg_surface_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_surface *self = weston_desktop_surface_get_implementation_data(surface);
+
+ weston_desktop_api_resize(self->desktop, surface, seat, serial, edges);
+}
+
+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);
+
+ /* TODO: check if serial is newer or older */
+ if ( self->configure_serial != serial )
+ {
+ _weston_desktop_xdg_surface_schedule_configure(self);
+ return;
+ }
+
+ self->next_state = self->requested_state;
+}
+
+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_next_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_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_surface *self = weston_desktop_surface_get_implementation_data(surface);
+
+ weston_desktop_api_ask_maximized(self->desktop, surface, true);
+}
+
+static void
+_weston_desktop_xdg_surface_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_surface *self = weston_desktop_surface_get_implementation_data(surface);
+
+ weston_desktop_api_ask_maximized(self->desktop, surface, false);
+}
+
+static void
+_weston_desktop_xdg_surface_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_surface *self = weston_desktop_surface_get_implementation_data(surface);
+
+ weston_desktop_api_ask_fullscreen(self->desktop, surface, true);
+}
+
+static void
+_weston_desktop_xdg_surface_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_surface *self = weston_desktop_surface_get_implementation_data(surface);
+
+ weston_desktop_api_ask_fullscreen(self->desktop, surface, false);
+}
+
+static void
+_weston_desktop_xdg_surface_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_surface *self = weston_desktop_surface_get_implementation_data(surface);
+
+ weston_desktop_api_ask_minimized(self->desktop, surface);
+}
+
+static const struct xdg_surface_interface _weston_desktop_xdg_surface_implementation = {
+ .destroy = weston_desktop_destroy_request,
+ .set_parent = _weston_desktop_xdg_surface_protocol_set_parent,
+ .set_title = _weston_desktop_xdg_surface_protocol_set_title,
+ .set_app_id = _weston_desktop_xdg_surface_protocol_set_app_id,
+ .show_window_menu = _weston_desktop_xdg_surface_protocol_show_window_menu,
+ .move = _weston_desktop_xdg_surface_protocol_move,
+ .resize = _weston_desktop_xdg_surface_protocol_resize,
+ .ack_configure = _weston_desktop_xdg_surface_protocol_ack_configure,
+ .set_window_geometry = _weston_desktop_xdg_surface_protocol_set_window_geometry,
+ .set_maximized = _weston_desktop_xdg_surface_protocol_set_maximized,
+ .unset_maximized = _weston_desktop_xdg_surface_protocol_unset_maximized,
+ .set_fullscreen = _weston_desktop_xdg_surface_protocol_set_fullscreen,
+ .unset_fullscreen = _weston_desktop_xdg_surface_protocol_unset_fullscreen,
+ .set_minimized = _weston_desktop_xdg_surface_protocol_set_minimized,
+};
+
+static const struct weston_desktop_surface_implementation _weston_desktop_xdg_surface_internal_implementation = {
+ .set_maximized = _weston_desktop_xdg_surface_set_maximized,
+ .set_fullscreen = _weston_desktop_xdg_surface_set_fullscreen,
+ .set_resizing = _weston_desktop_xdg_surface_set_resizing,
+ .set_activated = _weston_desktop_xdg_surface_set_activated,
+ .set_size = _weston_desktop_xdg_surface_set_size,
+ .commit = _weston_desktop_xdg_surface_commit,
+ .ping = _weston_desktop_xdg_surface_ping,
+ .close = _weston_desktop_xdg_surface_close,
+
+ .get_maximized = _weston_desktop_xdg_surface_get_maximized,
+ .get_fullscreen = _weston_desktop_xdg_surface_get_fullscreen,
+ .get_resizing = _weston_desktop_xdg_surface_get_resizing,
+ .get_activated = _weston_desktop_xdg_surface_get_activated,
+ .get_geometry = _weston_desktop_xdg_surface_get_geometry,
+
+ .free = _weston_desktop_xdg_surface_free,
+};
+
+static void
+_weston_desktop_xdg_popup_close(struct weston_desktop_surface *surface, void *user_data)
+{
+ struct weston_desktop_xdg_popup *self = user_data;
+
+ xdg_popup_send_popup_done(self->resource);
+}
+
+static void
+_weston_desktop_xdg_popup_free(struct weston_desktop_surface *surface, void *user_data)
+{
+ struct weston_desktop_xdg_popup *self = user_data;
+
+ if ( weston_desktop_surface_get_grab(self->popup) )
+ {
+ struct weston_desktop_surface *topmost;
+ struct wl_resource *resource = weston_desktop_client_get_resource(weston_desktop_surface_get_client(self->popup));
+
+ topmost = weston_desktop_seat_grab_get_topmost_surface(self->seat);
+ if ( topmost != self->popup )
+ wl_resource_post_error(resource, XDG_SHELL_ERROR_NOT_THE_TOPMOST_POPUP, "xdg_popup was destroyed while it was not the topmost popup.");
+ weston_desktop_surface_ungrab(self->popup, self->seat);
+ }
+
+ free(self);
+}
+
+static const struct xdg_popup_interface _weston_desktop_xdg_popup_implementation = {
+ .destroy = weston_desktop_destroy_request,
+};
+
+static const struct weston_desktop_surface_implementation _weston_desktop_xdg_popup_internal_implementation = {
+ .close = _weston_desktop_xdg_popup_close,
+
+ .free = _weston_desktop_xdg_popup_free,
+};
+
+static void
+_weston_desktop_xdg_shell_protocol_use_unstable_version(struct wl_client *wl_client, struct wl_resource *resource, int32_t version)
+{
+ if ( version > 1 )
+ {
+ wl_resource_post_error(resource, 1, "xdg_shell version not supported");
+ return;
+ }
+}
+
+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;
+
+ if ( weston_surface_set_role(surface, "xdg_surface", resource, XDG_SHELL_ERROR_ROLE) < 0 )
+ return;
+
+ self = zalloc(sizeof(struct weston_desktop_xdg_surface));
+ 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 = weston_desktop_surface_create(self->desktop, self->client, surface, &_weston_desktop_xdg_surface_internal_implementation, self);
+ if ( self->surface == NULL )
+ {
+ free(self);
+ return;
+ }
+
+ self->resource = weston_desktop_surface_add_resource(self->surface, &xdg_surface_interface, &_weston_desktop_xdg_surface_implementation, id, NULL);
+ if ( self->resource == NULL )
+ return;
+
+ weston_desktop_api_surface_new(self->desktop, self->surface);
+}
+
+static void
+_weston_desktop_xdg_shell_protocol_get_xdg_popup(struct wl_client *wl_client, struct wl_resource *resource, uint32_t id, struct wl_resource *surface_resource, struct wl_resource *parent_resource, struct wl_resource *seat_resource, uint32_t serial, int32_t x, int32_t y)
+{
+ struct weston_desktop_client *client = wl_resource_get_user_data(resource);
+ struct weston_surface *surface = wl_resource_get_user_data(surface_resource);
+ struct weston_surface *wparent = wl_resource_get_user_data(parent_resource);
+ struct weston_seat *wseat = wl_resource_get_user_data(seat_resource);
+ struct weston_desktop_seat *seat = weston_seat_get_desktop_seat(wseat);
+ struct weston_desktop_surface *parent, *topmost;
+ bool parent_is_popup;
+ struct weston_desktop_xdg_popup *self;
+
+ if ( weston_surface_set_role(surface, "xdg_popup", resource, XDG_SHELL_ERROR_ROLE) < 0 )
+ return;
+
+ if ( ! weston_surface_is_desktop_surface(wparent) )
+ {
+ wl_resource_post_error(resource, XDG_SHELL_ERROR_INVALID_POPUP_PARENT, "xdg_popup parent was invalid");
+ return;
+ }
+
+ parent = weston_surface_get_desktop_surface(wparent);
+ parent_is_popup = weston_desktop_surface_has_implementation(parent, &_weston_desktop_xdg_popup_internal_implementation);
+
+ if ( ( ! weston_desktop_surface_has_implementation(parent, &_weston_desktop_xdg_surface_internal_implementation) ) && ( ! parent_is_popup ) )
+ {
+ wl_resource_post_error(resource, XDG_SHELL_ERROR_INVALID_POPUP_PARENT, "xdg_popup parent was invalid");
+ return;
+ }
+
+ topmost = weston_desktop_seat_grab_get_topmost_surface(seat);
+ if ( ( ( topmost == NULL ) && parent_is_popup ) || ( ( topmost != NULL ) && ( topmost != parent ) ) )
+ {
+ wl_resource_post_error(resource, XDG_SHELL_ERROR_NOT_THE_TOPMOST_POPUP, "xdg_popup was not created on the topmost popup");
+ return;
+ }
+
+ self = zalloc(sizeof(struct weston_desktop_xdg_popup));
+ if ( self == NULL )
+ {
+ wl_client_post_no_memory(wl_client);
+ return;
+ }
+
+ self->desktop = weston_desktop_client_get_desktop(client);
+ self->display = weston_desktop_get_display(self->desktop);
+ self->seat = seat;
+
+ self->popup = weston_desktop_surface_create(self->desktop, client, surface, &_weston_desktop_xdg_popup_internal_implementation, self);
+ if ( self->popup == NULL )
+ {
+ free(self);
+ return;
+ }
+
+ self->resource = weston_desktop_surface_add_resource(self->popup, &xdg_popup_interface, &_weston_desktop_xdg_popup_implementation, id, NULL);
+ if ( self->resource == NULL )
+ return;
+
+ weston_desktop_surface_set_parent(self->popup, parent, x, y);
+ weston_desktop_surface_grab(self->popup, self->seat, serial);
+}
+
+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 xdg_shell_interface _weston_desktop_xdg_shell_implementation = {
+ .destroy = weston_desktop_destroy_request,
+ .use_unstable_version = _weston_desktop_xdg_shell_protocol_use_unstable_version,
+ .get_xdg_surface = _weston_desktop_xdg_shell_protocol_get_xdg_surface,
+ .get_xdg_popup = _weston_desktop_xdg_shell_protocol_get_xdg_popup,
+ .pong = _weston_desktop_xdg_shell_protocol_pong,
+};
+
+
+static int
+xdg_shell_unversioned_dispatch(const void *implementation, void *_target, uint32_t opcode, const struct wl_message *message, union wl_argument *args)
+{
+ struct wl_resource *resource = _target;
+ struct weston_desktop_client *client = wl_resource_get_user_data(resource);
+
+ if ( opcode != 1 /* XDG_SHELL_USE_UNSTABLE_VERSION */ )
+ {
+ wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT, "must call use_unstable_version first");
+ return 0;
+ }
+
+#define XDG_SERVER_VERSION 5
+
+ if ( args[0].i != XDG_SERVER_VERSION )
+ {
+ wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT, "incompatible version, server is %d " "client wants %d", XDG_SERVER_VERSION, args[0].i);
+ return 0;
+ }
+
+ wl_resource_set_implementation(resource, &_weston_desktop_xdg_shell_implementation, client, implementation);
+
+ return 1;
+}
+
+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, xdg_shell_unversioned_dispatch, &xdg_shell_interface, NULL, version, id);
+}
+
+struct wl_global *
+weston_desktop_xdg_shell_v5_create(struct weston_desktop *desktop, struct wl_display *display)
+{
+ return wl_global_create(display, &xdg_shell_interface, WD_XDG_SHELL_PROTOCOL_VERSION, desktop, _weston_desktop_xdg_shell_bind);
+}
diff --git a/libweston-desktop/xwayland.c b/libweston-desktop/xwayland.c
new file mode 100644
index 0000000..e7a73d4
--- /dev/null
+++ b/libweston-desktop/xwayland.c
@@ -0,0 +1,287 @@
+/*
+ * 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 <wayland-server.h>
+
+#include "compositor.h"
+#include "zalloc.h"
+
+#include "libweston-desktop.h"
+#include "internal.h"
+
+enum shell_surface_state {
+ TOPLEVEL,
+ MAXIMIZED,
+ FULLSCREEN,
+ TRANSIENT,
+ XWAYLAND,
+};
+
+struct weston_desktop_xwayland {
+ struct weston_desktop *desktop;
+ struct weston_layer layer;
+ struct wl_listener transform_listener;
+};
+
+struct shell_surface {
+ struct weston_desktop_xwayland *xwayland;
+ struct weston_desktop *desktop;
+ struct weston_desktop_surface *surface;
+ const struct weston_shell_client *client;
+ struct weston_desktop_surface_geometry next_geometry;
+ struct weston_desktop_surface_geometry geometry;
+ bool has_geometry;
+ enum shell_surface_state state;
+};
+
+static void
+_weston_desktop_xwayland_surface_commit(struct weston_desktop_surface *surface, void *user_data, int32_t sx, int32_t sy)
+{
+ struct shell_surface *self = user_data;
+
+ if ( self->has_geometry )
+ self->geometry = self->next_geometry;
+
+ weston_desktop_api_commit(self->desktop, self->surface, sx, sy);
+}
+
+static void
+_weston_desktop_xwayland_surface_set_size(struct weston_desktop_surface *surface, void *user_data, int32_t width, int32_t height)
+{
+ struct shell_surface *self = user_data;
+
+ self->client->send_configure(weston_desktop_surface_get_surface(self->surface), width, height);
+}
+
+static void
+_weston_desktop_xwayland_surface_free(struct weston_desktop_surface *surface, void *user_data)
+{
+ struct shell_surface *self = user_data;
+
+ if ( ( self->state == TOPLEVEL ) || ( self->state == MAXIMIZED ) || ( self->state == FULLSCREEN ) )
+ weston_desktop_api_surface_free(self->desktop, self->surface);
+
+ free(self);
+}
+
+static bool
+_weston_desktop_xwayland_surface_get_maximized(struct weston_desktop_surface *surface, void *user_data)
+{
+ struct shell_surface *self = user_data;
+
+ return ( self->state == MAXIMIZED );
+}
+
+static bool
+_weston_desktop_xwayland_surface_get_fullscreen(struct weston_desktop_surface *surface, void *user_data)
+{
+ struct shell_surface *self = user_data;
+
+ return ( self->state == FULLSCREEN );
+}
+
+static struct weston_desktop_surface_geometry
+_weston_desktop_xwayland_surface_get_geometry(struct weston_desktop_surface *surface, void *user_data)
+{
+ struct shell_surface *self = user_data;
+
+ if ( self->has_geometry )
+ return self->geometry;
+ return weston_surface_get_bounding_box(weston_desktop_surface_get_surface(self->surface));
+}
+
+static const struct weston_desktop_surface_implementation _weston_desktop_xwayland_surface_internal_implementation = {
+ .commit = _weston_desktop_xwayland_surface_commit,
+ .set_size = _weston_desktop_xwayland_surface_set_size,
+
+ .get_maximized = _weston_desktop_xwayland_surface_get_maximized,
+ .get_fullscreen = _weston_desktop_xwayland_surface_get_fullscreen,
+ .get_geometry = _weston_desktop_xwayland_surface_get_geometry,
+
+ .free = _weston_desktop_xwayland_surface_free,
+};
+static struct shell_surface *
+create_shell_surface(void *shell, struct weston_surface *surface, const struct weston_shell_client *client)
+{
+ struct weston_desktop_xwayland *xwayland = shell;
+ struct shell_surface *self;
+
+ self = zalloc(sizeof(struct shell_surface));
+ if ( self == NULL )
+ return NULL;
+
+ self->xwayland = xwayland;
+ self->desktop = xwayland->desktop;
+ self->client = client;
+
+ self->surface = weston_desktop_surface_create(self->desktop, NULL, surface, &_weston_desktop_xwayland_surface_internal_implementation, self);
+ if ( self->surface == NULL )
+ {
+ free(self);
+ return NULL;
+ }
+
+ return self;
+}
+
+static void
+set_toplevel(struct shell_surface *self)
+{
+ weston_desktop_api_surface_new(self->desktop, self->surface);
+}
+
+
+static void
+set_transient(struct shell_surface *self, struct weston_surface *parent, int x, int y, uint32_t flags)
+{
+ if ( ! weston_surface_is_desktop_surface(parent) )
+ return;
+ self->state = TRANSIENT;
+ weston_desktop_surface_set_parent(self->surface, weston_surface_get_desktop_surface(parent), x, y);
+}
+
+static void
+set_fullscreen(struct shell_surface *self, uint32_t method, uint32_t framerate, struct weston_output *output)
+{
+ self->state = FULLSCREEN;
+ weston_desktop_api_surface_new(self->desktop, self->surface);
+}
+
+static void
+set_xwayland(struct shell_surface *self, int x, int y, uint32_t flags)
+{
+ struct weston_view *view = weston_desktop_surface_get_view(self->surface);
+
+ self->state = XWAYLAND;
+ weston_layer_entry_insert(&self->xwayland->layer.view_list, &view->layer_link);
+ weston_view_set_position(view, x, y);
+}
+
+static int
+move(struct shell_surface *self, struct weston_pointer *pointer)
+{
+ weston_desktop_api_move(self->desktop, self->surface, pointer->seat, pointer->grab_serial);
+ return 0;
+}
+
+static int
+resize(struct shell_surface *self, struct weston_pointer *pointer, uint32_t edges)
+{
+ weston_desktop_api_resize(self->desktop, self->surface, pointer->seat, pointer->grab_serial, edges);
+ return 0;
+}
+
+static void
+set_title(struct shell_surface *self, const char *title)
+{
+ weston_desktop_surface_set_title(self->surface, title);
+}
+
+static void
+set_window_geometry(struct shell_surface *self, int32_t x, int32_t y, int32_t width, int32_t height)
+{
+ 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
+set_maximized(struct shell_surface *self)
+{
+ self->state = MAXIMIZED;
+ weston_desktop_api_surface_new(self->desktop, self->surface);
+}
+
+static void
+set_pid(struct shell_surface *self, pid_t pid)
+{
+}
+
+static void
+transform_handler(struct wl_listener *listener, void *data)
+{
+ struct weston_surface *surface = data;
+ struct weston_desktop_surface *desktop_surface = weston_surface_get_desktop_surface(surface);
+ struct shell_surface *self;
+ struct weston_view *view;
+ int x, y;
+
+ if (!desktop_surface)
+ return;
+
+ if (!weston_desktop_surface_has_implementation(desktop_surface, &_weston_desktop_xwayland_surface_internal_implementation))
+ return;
+
+ self = weston_desktop_surface_get_implementation_data(desktop_surface);
+ view = weston_desktop_surface_get_view(desktop_surface);
+ if (!weston_view_is_mapped(view))
+ return;
+
+ x = view->geometry.x;
+ y = view->geometry.y;
+
+ self->client->send_position(surface, x, y);
+}
+
+
+void
+weston_desktop_xwayland_init(struct weston_desktop *desktop)
+{
+ struct weston_compositor *compositor = weston_desktop_get_compositor(desktop);
+ struct weston_desktop_xwayland *self;
+
+ self = zalloc(sizeof(struct weston_desktop_xwayland));
+ if ( self == NULL )
+ return;
+
+ self->desktop = desktop;
+
+ weston_layer_init(&self->layer, &compositor->cursor_layer.link);
+
+ self->transform_listener.notify = transform_handler;
+ wl_signal_add(&compositor->transform_signal, &self->transform_listener);
+
+ compositor->shell_interface.shell = self;
+ compositor->shell_interface.create_shell_surface = create_shell_surface;
+ compositor->shell_interface.set_toplevel = set_toplevel;
+ compositor->shell_interface.set_transient = set_transient;
+ compositor->shell_interface.set_fullscreen = set_fullscreen;
+ compositor->shell_interface.set_xwayland = set_xwayland;
+ compositor->shell_interface.move = move;
+ compositor->shell_interface.resize = resize;
+ compositor->shell_interface.set_title = set_title;
+ compositor->shell_interface.set_window_geometry = set_window_geometry;
+ compositor->shell_interface.set_maximized = set_maximized;
+ compositor->shell_interface.set_pid = set_pid;
+}
--
2.9.0
More information about the wayland-devel
mailing list