swc

Unnamed repository; edit this file 'description' to name the repository.
git clone git://git.nihaljere.xyz/swc
Log | Files | Refs | README | LICENSE

commit bf972a9f912d94ca4426cb956650654236d2bddb
parent 8e1d3bf12a4cdeda4de3dd3e6da8474108fb247e
Author: Michael Forney <mforney@mforney.org>
Date:   Tue, 30 Sep 2014 21:40:18 -0700

Implement xdg-shell

Fixes #2

Diffstat:
M.gitignore | 2++
Mlibswc/local.mk | 7++++++-
Mlibswc/swc.c | 15++++++++++++---
Mlibswc/window.h | 2+-
Alibswc/xdg_popup.c | 111+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alibswc/xdg_popup.h | 39+++++++++++++++++++++++++++++++++++++++
Alibswc/xdg_shell.c | 144+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alibswc/xdg_shell.h | 33+++++++++++++++++++++++++++++++++
Alibswc/xdg_surface.c | 340+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alibswc/xdg_surface.h | 37+++++++++++++++++++++++++++++++++++++
Mprotocol/local.mk | 3++-
Aprotocol/xdg-shell.xml | 413+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12 files changed, 1140 insertions(+), 6 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -6,6 +6,8 @@ protocol/swc-protocol.c protocol/swc-server-protocol.h protocol/wayland-drm-protocol.c protocol/wayland-drm-server-protocol.h +protocol/xdg-shell-protocol.c +protocol/xdg-shell-server-protocol.h /.deps/ /swc.pc diff --git a/libswc/local.mk b/libswc/local.mk @@ -56,9 +56,13 @@ SWC_SOURCES = \ libswc/view.c \ libswc/wayland_buffer.c \ libswc/window.c \ + libswc/xdg_popup.c \ + libswc/xdg_shell.c \ + libswc/xdg_surface.c \ libswc/xkb.c \ protocol/swc-protocol.c \ - protocol/wayland-drm-protocol.c + protocol/wayland-drm-protocol.c \ + protocol/xdg-shell-protocol.c ifeq ($(ENABLE_LIBINPUT),1) $(dir)_CFLAGS += -DENABLE_LIBINPUT @@ -87,6 +91,7 @@ SWC_SHARED_OBJECTS = $(SWC_SOURCES:%.c=%.lo) objects = $(foreach obj,$(1),$(dir)/$(obj).o $(dir)/$(obj).lo) $(call objects,compositor panel_manager panel screen): protocol/swc-server-protocol.h $(call objects,drm drm_buffer): protocol/wayland-drm-server-protocol.h +$(call objects,xdg_shell xdg_surface xdg_popup): protocol/xdg-shell-server-protocol.h $(call objects,pointer): cursor/cursor_data.h $(dir)/libswc.a: $(SWC_STATIC_OBJECTS) diff --git a/libswc/swc.c b/libswc/swc.c @@ -37,6 +37,7 @@ #include "shm.h" #include "util.h" #include "window.h" +#include "xdg_shell.h" #ifdef ENABLE_XWAYLAND # include "xserver.h" #endif @@ -161,17 +162,23 @@ bool swc_initialize(struct wl_display * display, goto error8; } + if (!xdg_shell_initialize()) + { + ERROR("Could not initialize XDG shell\n"); + goto error9; + } + if (!panel_manager_initialize()) { ERROR("Could not initialize panel manager\n"); - goto error9; + goto error10; } #ifdef ENABLE_XWAYLAND if (!xserver_initialize()) { ERROR("Could not initialize xwayland\n"); - goto error10; + goto error11; } #endif @@ -180,9 +187,11 @@ bool swc_initialize(struct wl_display * display, return true; #ifdef ENABLE_XWAYLAND - error10: + error11: panel_manager_finalize(); #endif + error10: + xdg_shell_finalize(); error9: swc_shell_finalize(); error8: diff --git a/libswc/window.h b/libswc/window.h @@ -54,7 +54,7 @@ struct window struct compositor_view * view; struct view_handler view_handler; bool managed; - enum window_mode mode; + unsigned mode; struct { diff --git a/libswc/xdg_popup.c b/libswc/xdg_popup.c @@ -0,0 +1,111 @@ +/* swc: libswc/xdg_popup.c + * + * Copyright (c) 2014 Michael Forney + * + * 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 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 "xdg_popup.h" +#include "compositor.h" +#include "surface.h" +#include "util.h" +#include "window.h" +#include "protocol/xdg-shell-server-protocol.h" + +#include <stdlib.h> + +struct xdg_popup +{ + struct wl_resource * resource; + struct compositor_view * view; + struct wl_listener surface_destroy_listener; +}; + +static void destroy(struct wl_client * client, struct wl_resource * resource) +{ + wl_resource_destroy(resource); +} + +static const struct xdg_popup_interface xdg_popup_implementation = { + .destroy = &destroy +}; + +static void handle_surface_destroy(struct wl_listener * listener, void * data) +{ + struct xdg_popup * popup + = wl_container_of(listener, popup, surface_destroy_listener); + + wl_resource_destroy(popup->resource); +} + +static void destroy_popup(struct wl_resource * resource) +{ + struct xdg_popup * popup = wl_resource_get_user_data(resource); + + wl_list_remove(&popup->surface_destroy_listener.link); + compositor_view_destroy(popup->view); + free(popup); +} + +struct xdg_popup * xdg_popup_new(struct wl_client * client, + uint32_t version, uint32_t id, + struct swc_surface * surface, + struct swc_surface * parent_surface, + int32_t x, int32_t y) +{ + struct xdg_popup * popup; + struct compositor_view * parent = compositor_view(parent_surface->view); + + if (!parent) + goto error0; + + popup = malloc(sizeof *popup); + + if (!popup) + goto error0; + + popup->resource = wl_resource_create(client, &xdg_popup_interface, + version, id); + + if (!popup->resource) + goto error1; + + popup->surface_destroy_listener.notify = &handle_surface_destroy; + wl_resource_add_destroy_listener(surface->resource, + &popup->surface_destroy_listener); + wl_resource_set_implementation(popup->resource, &xdg_popup_implementation, + popup, &destroy_popup); + + if (!(popup->view = swc_compositor_create_view(surface))) + goto error2; + + view_move(&popup->view->base, + parent->base.geometry.x + x, parent->base.geometry.y + y); + compositor_view_set_parent(popup->view, parent); + + return popup; + + error2: + wl_resource_destroy(popup->resource); + error1: + free(popup); + error0: + return NULL; +} + diff --git a/libswc/xdg_popup.h b/libswc/xdg_popup.h @@ -0,0 +1,39 @@ +/* swc: libswc/xdg_popup.h + * + * Copyright (c) 2014 Michael Forney + * + * 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 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 SWC_XDG_POPUP_H +#define SWC_XDG_POPUP_H + +#include <stdint.h> + +struct swc_surface; +struct wl_client; + +struct xdg_popup * xdg_popup_new(struct wl_client * client, + uint32_t version, uint32_t id, + struct swc_surface * surface, + struct swc_surface * parent, + int32_t x, int32_t y); + +#endif + diff --git a/libswc/xdg_shell.c b/libswc/xdg_shell.c @@ -0,0 +1,144 @@ +/* swc: libswc/xdg_shell.c + * + * Copyright (c) 2014 Michael Forney + * + * 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 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 "xdg_shell.h" +#include "internal.h" +#include "xdg_popup.h" +#include "xdg_surface.h" + +#include <assert.h> +#include <wayland-server.h> +#include "protocol/xdg-shell-server-protocol.h" + +#define XDG_SHELL_VERSION 4 + +static_assert(XDG_SHELL_VERSION == XDG_SHELL_VERSION_CURRENT, + "xdg_shell implementation does not match protocol version"); + +static struct +{ + struct wl_global * global; +} shell; + +static void use_unstable_version(struct wl_client * client, + struct wl_resource * resource, int32_t version) +{ +} + +static void get_xdg_surface(struct wl_client * client, + struct wl_resource * resource, uint32_t id, + struct wl_resource * surface_resource) +{ + struct swc_surface * surface = wl_resource_get_user_data(surface_resource); + struct xdg_surface * xdg_surface; + + xdg_surface = xdg_surface_new(client, wl_resource_get_version(resource), id, + surface); + + if (!xdg_surface) + wl_resource_post_no_memory(resource); +} + +static void get_xdg_popup(struct wl_client * 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, uint32_t flags) +{ + struct swc_surface * surface = wl_resource_get_user_data(surface_resource); + struct swc_surface * parent = wl_resource_get_user_data(parent_resource); + struct xdg_popup * popup; + + popup = xdg_popup_new(client, wl_resource_get_version(resource), id, + surface, parent, x, y); + + if (!popup) + wl_resource_post_no_memory(resource); +} + +static void pong(struct wl_client * client, struct wl_resource * resource, + uint32_t serial) +{ +} + +static const struct xdg_shell_interface shell_implementation = { + .use_unstable_version = &use_unstable_version, + .get_xdg_surface = &get_xdg_surface, + .get_xdg_popup = &get_xdg_popup, + .pong = &pong +}; + +static int unversioned_dispatch(const void * implementation, void * target, + uint32_t opcode, + const struct wl_message * message, + union wl_argument * arguments) +{ + struct wl_resource * resource = target; + + if (opcode != 0) + { + wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT, + "use_unstable_version must be called first"); + return 0; + } + + if (arguments[0].i != XDG_SHELL_VERSION) + { + wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT, + "incompatible xdg_shell versions, " + "server: %d, client: %d", + XDG_SHELL_VERSION, arguments[0].i); + return 0; + } + + wl_resource_set_implementation(resource, &shell_implementation, NULL, NULL); + return 1; +} + +static void bind_shell(struct wl_client * client, void * data, + uint32_t version, uint32_t id) +{ + struct wl_resource * resource; + + if (version >= 1) + version = 1; + + resource = wl_resource_create(client, &xdg_shell_interface, version, id); + wl_resource_set_dispatcher(resource, &unversioned_dispatch, + NULL, NULL, NULL); +} + +bool xdg_shell_initialize() +{ + shell.global = wl_global_create(swc.display, &xdg_shell_interface, 1, + NULL, &bind_shell); + + return shell.global; +} + +void xdg_shell_finalize() +{ + wl_global_destroy(shell.global); +} + diff --git a/libswc/xdg_shell.h b/libswc/xdg_shell.h @@ -0,0 +1,33 @@ +/* swc: libswc/xdg_shell.h + * + * Copyright (c) 2014 Michael Forney + * + * 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 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 SWC_XDG_SHELL_H +#define SWC_XDG_SHELL_H + +#include <stdbool.h> + +bool xdg_shell_initialize(); +void xdg_shell_finalize(); + +#endif + diff --git a/libswc/xdg_surface.c b/libswc/xdg_surface.c @@ -0,0 +1,340 @@ +/* swc: libswc/xdg_surface.c + * + * Copyright (c) 2014 Michael Forney + * + * 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 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 "xdg_surface.h" +#include "compositor.h" +#include "internal.h" +#include "seat.h" +#include "surface.h" +#include "util.h" +#include "view.h" +#include "window.h" +#include "protocol/xdg-shell-server-protocol.h" + +#include <stdlib.h> + +struct xdg_surface +{ + struct window window; + struct wl_resource * resource; + struct wl_listener surface_destroy_listener; + struct wl_array states; + uint32_t configure_serial; +}; + +static bool add_state(struct xdg_surface * xdg_surface, uint32_t state) +{ + uint32_t * current_state; + + wl_array_for_each(current_state, &xdg_surface->states) + { + if (*current_state == state) + return false; + } + + if (!(current_state = wl_array_add(&xdg_surface->states, sizeof state))) + { + WARNING("xdg_surface: Failed to allocate new state\n"); + return false; + } + + *current_state = state; + return true; +} + +static bool remove_state(struct xdg_surface * xdg_surface, uint32_t state) +{ + uint32_t * current_state; + + wl_array_for_each(current_state, &xdg_surface->states) + { + if (*current_state == state) + { + swc_array_remove(&xdg_surface->states, current_state, sizeof state); + return true; + } + } + + return false; +} + +static void configure(struct window * window, uint32_t width, uint32_t height) +{ + struct xdg_surface * xdg_surface + = wl_container_of(window, xdg_surface, window); + + window->configure.acknowledged = false; + xdg_surface->configure_serial = wl_display_next_serial(swc.display); + xdg_surface_send_configure(xdg_surface->resource, width, height, + &xdg_surface->states, + xdg_surface->configure_serial); +} + +static void focus(struct window * window) +{ + struct xdg_surface * xdg_surface + = wl_container_of(window, xdg_surface, window); + + add_state(xdg_surface, XDG_SURFACE_STATE_ACTIVATED); + configure(window, window->configure.width, window->configure.height); +} + +static void unfocus(struct window * window) +{ + struct xdg_surface * xdg_surface + = wl_container_of(window, xdg_surface, window); + + remove_state(xdg_surface, XDG_SURFACE_STATE_ACTIVATED); + configure(window, window->configure.width, window->configure.height); +} + +static void close(struct window * window) +{ + struct xdg_surface * xdg_surface + = wl_container_of(window, xdg_surface, window); + + xdg_surface_send_close(xdg_surface->resource); +} + +static void set_mode(struct window * window, unsigned mode) +{ + struct xdg_surface * xdg_surface + = wl_container_of(window, xdg_surface, window); + + switch (window->mode) + { + case WINDOW_MODE_TILED: + remove_state(xdg_surface, XDG_SURFACE_STATE_MAXIMIZED); + break; + case WINDOW_MODE_FULLSCREEN: + remove_state(xdg_surface, XDG_SURFACE_STATE_FULLSCREEN); + break; + } + + switch (mode) + { + case WINDOW_MODE_TILED: + add_state(xdg_surface, XDG_SURFACE_STATE_MAXIMIZED); + break; + case WINDOW_MODE_FULLSCREEN: + add_state(xdg_surface, XDG_SURFACE_STATE_FULLSCREEN); + break; + } +} + +static const struct window_impl xdg_surface_window_impl = { + .configure = &configure, + .focus = &focus, + .unfocus = &unfocus, + .close = &close, + .set_mode = &set_mode, +}; + +static void destroy(struct wl_client * client, struct wl_resource * resource) +{ + wl_resource_destroy(resource); +} + +static void set_parent(struct wl_client * client, struct wl_resource * resource, + struct wl_resource * parent_resource) +{ + struct xdg_surface * xdg_surface = wl_resource_get_user_data(resource); + struct swc_surface * parent_surface; + struct compositor_view * parent_view; + struct window * parent_window = NULL; + + if (parent_resource) + { + parent_surface = wl_resource_get_user_data(parent_resource); + parent_view = compositor_view(parent_surface->view); + parent_window = parent_view->window; + } + + window_set_parent(&xdg_surface->window, parent_window); +} + +static void set_title(struct wl_client * client, struct wl_resource * resource, + const char * title) +{ + struct xdg_surface * xdg_surface = wl_resource_get_user_data(resource); + + window_set_title(&xdg_surface->window, title, -1); +} + +static void set_app_id(struct wl_client * client, struct wl_resource * resource, + const char * app_id) +{ + struct xdg_surface * surface = wl_resource_get_user_data(resource); + + window_set_class(&surface->window, app_id); +} + +static void show_window_menu(struct wl_client * client, + struct wl_resource * resource, + struct wl_resource * seat_resource, + uint32_t serial, int32_t x, int32_t y) +{ +} + +static void move(struct wl_client * client, struct wl_resource * resource, + struct wl_resource * seat_resource, uint32_t serial) +{ + struct xdg_surface * xdg_surface = wl_resource_get_user_data(resource); + struct button * button; + + if (!(button = pointer_get_button(swc.seat->pointer, serial))) + return; + + window_begin_move(&xdg_surface->window, button); +} + +static void resize(struct wl_client * client, struct wl_resource * resource, + struct wl_resource * seat_resource, uint32_t serial, + uint32_t edges) +{ + struct xdg_surface * xdg_surface = wl_resource_get_user_data(resource); + struct button * button; + + if (!(button = pointer_get_button(swc.seat->pointer, serial))) + return; + + window_begin_resize(&xdg_surface->window, edges, button); +} + +static void ack_configure(struct wl_client * client, + struct wl_resource * resource, uint32_t serial) +{ + struct xdg_surface * xdg_surface = wl_resource_get_user_data(resource); + + if (serial == xdg_surface->configure_serial) + xdg_surface->window.configure.acknowledged = true; +} + +static void set_window_geometry(struct wl_client * client, + struct wl_resource * resource, + int32_t x, int32_t y, + int32_t width, int32_t height) +{ + /* TODO: Implement set_window_geometry. */ +} + +static void set_maximized(struct wl_client * client, + struct wl_resource * resource) +{ + /* TODO: Implement set_maximized. */ +} + +static void unset_maximized(struct wl_client * client, + struct wl_resource * resource) +{ + /* TODO: Implement unset_maximized. */ +} + +static void set_fullscreen(struct wl_client * client, + struct wl_resource * resource, + struct wl_resource * output_resource) +{ + /* TODO: Implement set_fullscreen. */ +} + +static void unset_fullscreen(struct wl_client * client, + struct wl_resource * resource) +{ + /* TODO: Implement unset_fullscreen. */ +} + +static void set_minimized(struct wl_client * client, + struct wl_resource * resource) +{ + /* TODO: Implement set_minimized. */ +} + +static const struct xdg_surface_interface xdg_surface_implementation = { + .destroy = &destroy, + .set_parent = &set_parent, + .set_title = &set_title, + .set_app_id = &set_app_id, + .show_window_menu = &show_window_menu, + .move = &move, + .resize = &resize, + .ack_configure = &ack_configure, + .set_window_geometry = &set_window_geometry, + .set_maximized = &set_maximized, + .unset_maximized = &unset_maximized, + .set_fullscreen = &set_fullscreen, + .unset_fullscreen = &unset_fullscreen, + .set_minimized = &set_minimized, +}; + +static void handle_surface_destroy(struct wl_listener * listener, void * data) +{ + struct xdg_surface * xdg_surface + = wl_container_of (listener, xdg_surface, surface_destroy_listener); + + wl_resource_destroy(xdg_surface->resource); +} + +static void destroy_xdg_surface(struct wl_resource * resource) +{ + struct xdg_surface * xdg_surface = wl_resource_get_user_data(resource); + + wl_list_remove(&xdg_surface->surface_destroy_listener.link); + window_finalize(&xdg_surface->window); + free(xdg_surface); +} + +struct xdg_surface * xdg_surface_new(struct wl_client * client, + uint32_t version, uint32_t id, + struct swc_surface * surface) +{ + struct xdg_surface * xdg_surface; + + xdg_surface = malloc(sizeof *xdg_surface); + + if (!xdg_surface) + goto error0; + + xdg_surface->resource = wl_resource_create(client, &xdg_surface_interface, + version, id); + + if (!xdg_surface->resource) + goto error1; + + window_initialize(&xdg_surface->window, &xdg_surface_window_impl, surface); + xdg_surface->surface_destroy_listener.notify = &handle_surface_destroy; + wl_array_init(&xdg_surface->states); + wl_resource_add_destroy_listener(surface->resource, + &xdg_surface->surface_destroy_listener); + wl_resource_set_implementation(xdg_surface->resource, + &xdg_surface_implementation, + xdg_surface, &destroy_xdg_surface); + window_manage(&xdg_surface->window); + + return xdg_surface; + + error1: + free(xdg_surface); + error0: + return NULL; +} + diff --git a/libswc/xdg_surface.h b/libswc/xdg_surface.h @@ -0,0 +1,37 @@ +/* swc: libswc/xdg_surface.h + * + * Copyright (c) 2014 Michael Forney + * + * 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 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 SWC_XDG_SURFACE_H +#define SWC_XDG_SURFACE_H + +#include <stdint.h> + +struct swc_surface; +struct wl_client; + +struct xdg_surface * xdg_surface_new(struct wl_client * client, + uint32_t version, uint32_t id, + struct swc_surface * surface); + +#endif + diff --git a/protocol/local.mk b/protocol/local.mk @@ -4,7 +4,8 @@ dir := protocol PROTOCOL_EXTENSIONS = \ $(dir)/swc.xml \ - $(dir)/wayland-drm.xml + $(dir)/wayland-drm.xml \ + $(dir)/xdg-shell.xml $(dir)_TARGETS := $(PROTOCOL_EXTENSIONS:%.xml=%-protocol.c) \ $(PROTOCOL_EXTENSIONS:%.xml=%-server-protocol.h) diff --git a/protocol/xdg-shell.xml b/protocol/xdg-shell.xml @@ -0,0 +1,413 @@ +<?xml version="1.0" encoding="UTF-8"?> +<protocol name="xdg_shell"> + + <copyright> + Copyright © 2008-2013 Kristian Høgsberg + Copyright © 2013 Rafael Antognolli + Copyright © 2013 Jasper St. Pierre + Copyright © 2010-2013 Intel Corporation + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that copyright notice and this permission + notice appear in supporting documentation, and that the name of + the copyright holders not be used in advertising or publicity + pertaining to distribution of the software without specific, + written prior permission. The copyright holders make no + representations about the suitability of this software for any + purpose. It is provided "as is" without express or implied + warranty. + + THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, + ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF + THIS SOFTWARE. + </copyright> + + <interface name="xdg_shell" version="1"> + <description summary="create desktop-style surfaces"> + This interface is implemented by servers that provide + desktop-style user interfaces. + + It allows clients to associate a xdg_surface with + a basic surface. + </description> + + <enum name="version"> + <description summary="latest protocol version"> + The 'current' member of this enum gives the version of the + protocol. Implementations can compare this to the version + they implement using static_assert to ensure the protocol and + implementation versions match. + </description> + <entry name="current" value="4" summary="Always the latest version"/> + </enum> + + + <request name="use_unstable_version"> + <description summary="enable use of this unstable version"> + Negotiate the unstable version of the interface. This + mechanism is in place to ensure client and server agree on the + unstable versions of the protocol that they speak or exit + cleanly if they don't agree. This request will go away once + the xdg-shell protocol is stable. + </description> + <arg name="version" type="int"/> + </request> + + <request name="get_xdg_surface"> + <description summary="create a shell surface from a surface"> + Create a shell surface for an existing surface. + + Only one shell or popup surface can be associated with a given + surface. + </description> + <arg name="id" type="new_id" interface="xdg_surface"/> + <arg name="surface" type="object" interface="wl_surface"/> + </request> + + <request name="get_xdg_popup"> + <description summary="create a shell surface from a surface"> + Create a popup surface for an existing surface. + + Only one shell or popup surface can be associated with a given + surface. + </description> + <arg name="id" type="new_id" interface="xdg_popup"/> + <arg name="surface" type="object" interface="wl_surface"/> + <arg name="parent" type="object" interface="wl_surface"/> + <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat whose pointer is used"/> + <arg name="serial" type="uint" summary="serial of the implicit grab on the pointer"/> + <arg name="x" type="int"/> + <arg name="y" type="int"/> + <arg name="flags" type="uint"/> + </request> + + <event name="ping"> + <description summary="check if the client is alive"> + The ping event asks the client if it's still alive. Pass the + serial specified in the event back to the compositor by sending + a "pong" request back with the specified serial. + + Compositors can use this to determine if the client is still + alive. It's unspecified what will happen if the client doesn't + respond to the ping request, or in what timeframe. Clients should + try to respond in a reasonable amount of time. + </description> + <arg name="serial" type="uint" summary="pass this to the callback"/> + </event> + + <request name="pong"> + <description summary="respond to a ping event"> + A client must respond to a ping event with a pong request or + the client may be deemed unresponsive. + </description> + <arg name="serial" type="uint" summary="serial of the ping event"/> + </request> + </interface> + + <interface name="xdg_surface" version="1"> + + <description summary="desktop-style metadata interface"> + An interface that may be implemented by a wl_surface, for + implementations that provide a desktop-style user interface. + + It provides requests to treat surfaces like windows, allowing to set + properties like maximized, fullscreen, minimized, and to move and resize + them, and associate metadata like title and app id. + + On the server side the object is automatically destroyed when + the related wl_surface is destroyed. On client side, + xdg_surface.destroy() must be called before destroying + the wl_surface object. + </description> + + <request name="destroy" type="destructor"> + <description summary="remove xdg_surface interface"> + The xdg_surface interface is removed from the wl_surface object + that was turned into a xdg_surface with + xdg_shell.get_xdg_surface request. The xdg_surface properties, + like maximized and fullscreen, are lost. The wl_surface loses + its role as a xdg_surface. The wl_surface is unmapped. + </description> + </request> + + <request name="set_parent"> + <description summary="surface is a child of another surface"> + Child surfaces are stacked above their parents, and will be + unmapped if the parent is unmapped too. They should not appear + on task bars and alt+tab. + </description> + <arg name="parent" type="object" interface="wl_surface" allow-null="true"/> + </request> + + <request name="set_title"> + <description summary="set surface title"> + Set a short title for the surface. + + This string may be used to identify the surface in a task bar, + window list, or other user interface elements provided by the + compositor. + + The string must be encoded in UTF-8. + </description> + <arg name="title" type="string"/> + </request> + + <request name="set_app_id"> + <description summary="set surface class"> + Set an id for the surface. + + The app id identifies the general class of applications to which + the surface belongs. + + It should be the ID that appears in the new desktop entry + specification, the interface name. + </description> + <arg name="app_id" type="string"/> + </request> + + <request name="show_window_menu"> + <description summary="show the window menu"> + Clients implementing client-side decorations might want to show + a context menu when right-clicking on the decorations, giving the + user a menu that they can use to maximize or minimize the window. + + This request asks the compositor to pop up such a window menu at + the given position, relative to the parent surface. There are + no guarantees as to what the window menu contains. + + Your surface must have focus on the seat passed in to pop up the + window menu. + </description> + + <arg name="seat" type="object" interface="wl_seat" summary="the seat to pop the window up on"/> + <arg name="serial" type="uint" summary="serial of the event to pop up the window for"/> + <arg name="x" type="int" summary="the x position to pop up the window menu at"/> + <arg name="y" type="int" summary="the y position to pop up the window menu at"/> + </request> + + <request name="move"> + <description summary="start an interactive move"> + Start a pointer-driven move of the surface. + + This request must be used in response to a button press event. + The server may ignore move requests depending on the state of + the surface (e.g. fullscreen or maximized). + </description> + <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat whose pointer is used"/> + <arg name="serial" type="uint" summary="serial of the implicit grab on the pointer"/> + </request> + + <enum name="resize_edge"> + <description summary="edge values for resizing"> + These values are used to indicate which edge of a surface + is being dragged in a resize operation. The server may + use this information to adapt its behavior, e.g. choose + an appropriate cursor image. + </description> + <entry name="none" value="0"/> + <entry name="top" value="1"/> + <entry name="bottom" value="2"/> + <entry name="left" value="4"/> + <entry name="top_left" value="5"/> + <entry name="bottom_left" value="6"/> + <entry name="right" value="8"/> + <entry name="top_right" value="9"/> + <entry name="bottom_right" value="10"/> + </enum> + + <request name="resize"> + <description summary="start an interactive resize"> + Start a pointer-driven resizing of the surface. + + This request must be used in response to a button press event. + The server may ignore resize requests depending on the state of + the surface (e.g. fullscreen or maximized). + </description> + <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat whose pointer is used"/> + <arg name="serial" type="uint" summary="serial of the implicit grab on the pointer"/> + <arg name="edges" type="uint" summary="which edge or corner is being dragged"/> + </request> + + <enum name="state"> + <description summary="types of state on the surface"> + The different state values used on the surface. This is designed for + state values like maximized, fullscreen. It is paired with the + configure event to ensure that both the client and the compositor + setting the state can be synchronized. + + States set in this way are double-buffered. They will get applied on + the next commit. + + Desktop environments may extend this enum by taking up a range of + values and documenting the range they chose in this description. + They are not required to document the values for the range that they + chose. Ideally, any good extensions from a desktop environment should + make its way into standardization into this enum. + + The current reserved ranges are: + + 0x0000 - 0x0FFF: xdg-shell core values, documented below. + 0x1000 - 0x1FFF: GNOME + </description> + <entry name="maximized" value="1" summary="the surface is maximized"> + The surface is maximized. The window geometry specified in the configure + event must be obeyed by the client. + </entry> + <entry name="fullscreen" value="2" summary="the surface is fullscreen"> + The surface is fullscreen. The window geometry specified in the configure + event must be obeyed by the client. + </entry> + <entry name="resizing" value="3"> + The surface is being resized. The window geometry specified in the + configure event is a maximum; the client cannot resize beyond it. + Clients that have aspect ratio or cell sizing configuration can use + a smaller size, however. + </entry> + <entry name="activated" value="4"> + Client window decorations should be painted as if the window is + active. Do not assume this means that the window actually has + keyboard or pointer focus. + </entry> + </enum> + + <event name="configure"> + <description summary="suggest a surface change"> + The configure event asks the client to resize its surface. + + The width and height arguments specify a hint to the window + about how its surface should be resized in window geometry + coordinates. The states listed in the event specify how the + width/height arguments should be interpreted. + + A client should arrange a new surface, and then send a + ack_configure request with the serial sent in this configure + event before attaching a new surface. + + If the client receives multiple configure events before it + can respond to one, it is free to discard all but the last + event it received. + </description> + + <arg name="width" type="int"/> + <arg name="height" type="int"/> + <arg name="states" type="array"/> + <arg name="serial" type="uint"/> + </event> + + <request name="ack_configure"> + <description summary="ack a configure event"> + When a configure event is received, a client should then ack it + using the ack_configure request to ensure that the compositor + knows the client has seen the event. + + By this point, the state is confirmed, and the next attach should + contain the buffer drawn for the configure event you are acking. + </description> + <arg name="serial" type="uint" summary="a serial to configure for"/> + </request> + + <request name="set_window_geometry"> + <description summary="set the new window geometry"> + The window geometry of a window is its "visible bounds" from the + user's perspective. Client-side decorations often have invisible + portions like drop-shadows which should be ignored for the + purposes of aligning, placing and constraining windows. + + The default value is the full bounds of the surface, including any + subsurfaces. Once the window geometry of the surface is set once, + it is not possible to unset it, and it will remain the same until + set_window_geometry is called again, even if a new subsurface or + buffer is attached. + + If responding to a configure event, the window geometry in here + must respect the sizing negotiations specified by the states in + the configure event. + </description> + <arg name="x" type="int"/> + <arg name="y" type="int"/> + <arg name="width" type="int"/> + <arg name="height" type="int"/> + </request> + + <request name="set_maximized" /> + <request name="unset_maximized" /> + + <request name="set_fullscreen"> + <description summary="set the window as fullscreen on a monitor"> + Make the surface fullscreen. + + You can specify an output that you would prefer to be fullscreen. + If this value is NULL, it's up to the compositor to choose which + display will be used to map this surface. + </description> + <arg name="output" type="object" interface="wl_output" allow-null="true"/> + </request> + <request name="unset_fullscreen" /> + + <request name="set_minimized" /> + + <event name="close"> + <description summary="surface wants to be closed"> + The close event is sent by the compositor when the user + wants the surface to be closed. This should be equivalent to + the user clicking the close button in client-side decorations, + if your application has any... + + This is only a request that the user intends to close your + window. The client may choose to ignore this request, or show + a dialog to ask the user to save their data... + </description> + </event> + </interface> + + <interface name="xdg_popup" version="1"> + <description summary="desktop-style metadata interface"> + An interface that may be implemented by a wl_surface, for + implementations that provide a desktop-style popups/menus. A popup + surface is a transient surface with an added pointer grab. + + An existing implicit grab will be changed to owner-events mode, + and the popup grab will continue after the implicit grab ends + (i.e. releasing the mouse button does not cause the popup to be + unmapped). + + The popup grab continues until the window is destroyed or a mouse + button is pressed in any other clients window. A click in any of + the clients surfaces is reported as normal, however, clicks in + other clients surfaces will be discarded and trigger the callback. + + The x and y arguments specify the locations of the upper left + corner of the surface relative to the upper left corner of the + parent surface, in surface local coordinates. + + xdg_popup surfaces are always transient for another surface. + </description> + + <request name="destroy" type="destructor"> + <description summary="remove xdg_surface interface"> + The xdg_surface interface is removed from the wl_surface object + that was turned into a xdg_surface with + xdg_shell.get_xdg_surface request. The xdg_surface properties, + like maximized and fullscreen, are lost. The wl_surface loses + its role as a xdg_surface. The wl_surface is unmapped. + </description> + </request> + + <event name="popup_done"> + <description summary="popup interaction is done"> + The popup_done event is sent out when a popup grab is broken, + that is, when the users clicks a surface that doesn't belong + to the client owning the popup surface. + </description> + <arg name="serial" type="uint" summary="serial of the implicit grab on the pointer"/> + </event> + + </interface> +</protocol>