swc

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

commit 390414c4377966c1ac051bfb049d7c24c1a99eff
parent 5b20050872f8ad29cfc97729f8af47b6b3df5393
Author: Michael Forney <mforney@mforney.org>
Date:   Sat, 26 May 2018 11:36:07 -0700

Update to stable xdg-shell protocol

For now, xdg_positioner is just a stub.

Diffstat:
M.gitignore | 4++--
Mlibswc/local.mk | 6++----
Mlibswc/swc.c | 2+-
Dlibswc/xdg_popup.c | 104-------------------------------------------------------------------------------
Dlibswc/xdg_popup.h | 35-----------------------------------
Mlibswc/xdg_shell.c | 495++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
Mlibswc/xdg_shell.h | 2+-
Dlibswc/xdg_surface.c | 334-------------------------------------------------------------------------------
Dlibswc/xdg_surface.h | 34----------------------------------
Mprotocol/local.mk | 2+-
10 files changed, 450 insertions(+), 568 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -6,8 +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-unstable-v5-protocol.c -protocol/xdg-shell-unstable-v5-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 @@ -52,12 +52,10 @@ SWC_SOURCES = \ libswc/view.c \ libswc/wayland_buffer.c \ libswc/window.c \ - libswc/xdg_popup.c \ libswc/xdg_shell.c \ - libswc/xdg_surface.c \ protocol/swc-protocol.c \ protocol/wayland-drm-protocol.c \ - protocol/xdg-shell-unstable-v5-protocol.c + protocol/xdg-shell-protocol.c ifeq ($(ENABLE_LIBUDEV),1) $(dir)_CFLAGS += -DENABLE_LIBUDEV @@ -80,7 +78,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-unstable-v5-server-protocol.h +$(call objects,xdg_shell): protocol/xdg-shell-server-protocol.h $(call objects,pointer): cursor/cursor_data.h $(dir)/libswc-internal.o: $(SWC_STATIC_OBJECTS) diff --git a/libswc/swc.c b/libswc/swc.c @@ -1,6 +1,6 @@ /* swc: libswc/swc.c * - * Copyright (c) 2013, 2014 Michael Forney + * Copyright (c) 2013, 2014, 2018 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 diff --git a/libswc/xdg_popup.c b/libswc/xdg_popup.c @@ -1,104 +0,0 @@ -/* 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 <stdlib.h> -#include "xdg-shell-unstable-v5-server-protocol.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 surface *surface, struct 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 = 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 @@ -1,35 +0,0 @@ -/* 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 surface; -struct wl_client; - -struct xdg_popup *xdg_popup_new(struct wl_client *client, uint32_t version, uint32_t id, - struct surface *surface, struct surface *parent, int32_t x, int32_t y); - -#endif diff --git a/libswc/xdg_shell.c b/libswc/xdg_shell.c @@ -1,6 +1,6 @@ /* swc: libswc/xdg_shell.c * - * Copyright (c) 2014 Michael Forney + * Copyright (c) 2014, 2018 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 @@ -23,21 +23,33 @@ #include "xdg_shell.h" #include "internal.h" -#include "xdg_popup.h" -#include "xdg_surface.h" +#include "seat.h" +#include "surface.h" +#include "util.h" +#include "window.h" #include <assert.h> +#include <stdlib.h> #include <wayland-server.h> -#include "xdg-shell-unstable-v5-server-protocol.h" +#include "xdg-shell-server-protocol.h" -#define XDG_SHELL_VERSION 5 +struct xdg_surface { + struct wl_resource *resource, *role; + struct surface *surface; + struct wl_listener surface_destroy_listener; + uint32_t configure_serial; +}; -static_assert(XDG_SHELL_VERSION == XDG_SHELL_VERSION_CURRENT, - "xdg_shell implementation does not match protocol version"); +struct xdg_positioner { + struct wl_resource *resource; +}; -static struct { - struct wl_global *global; -} shell; +struct xdg_toplevel { + struct window window; + struct wl_resource *resource; + struct wl_array states; + struct xdg_surface *xdg_surface; +}; static void destroy(struct wl_client *client, struct wl_resource *resource) @@ -45,90 +57,469 @@ destroy(struct wl_client *client, struct wl_resource *resource) wl_resource_destroy(resource); } +/* xdg_positioner */ static void -use_unstable_version(struct wl_client *client, struct wl_resource *resource, int32_t version) +destroy_positioner(struct wl_resource *resource) { + struct xdg_positioner *positioner = wl_resource_get_user_data(resource); + + free(positioner); } static void -get_xdg_surface(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *surface_resource) +set_size(struct wl_client *client, struct wl_resource *resource, int32_t width, int32_t height) { - struct 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 +set_anchor_rect(struct wl_client *client, struct wl_resource *resource, int32_t x, int32_t y, int32_t width, int32_t height) +{ } 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) +set_anchor(struct wl_client *client, struct wl_resource *resource, uint32_t anchor) { - struct surface *surface = wl_resource_get_user_data(surface_resource); - struct 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); +static void +set_gravity(struct wl_client *client, struct wl_resource *resource, uint32_t gravity) +{ +} - if (!popup) - wl_resource_post_no_memory(resource); +static void +set_constraint_adjustment(struct wl_client *client, struct wl_resource *resource, uint32_t adjustment) +{ } static void -pong(struct wl_client *client, struct wl_resource *resource, uint32_t serial) +set_offset(struct wl_client *client, struct wl_resource *resource, int32_t x, int32_t y) { } -static const struct xdg_shell_interface shell_implementation = { +static const struct xdg_positioner_interface positioner_implementation = { .destroy = destroy, - .use_unstable_version = use_unstable_version, - .get_xdg_surface = get_xdg_surface, - .get_xdg_popup = get_xdg_popup, - .pong = pong, + .set_size = set_size, + .set_anchor_rect = set_anchor_rect, + .set_anchor = set_anchor, + .set_gravity = set_gravity, + .set_constraint_adjustment = set_constraint_adjustment, + .set_offset = set_offset, }; -static int -unversioned_dispatch(const void *implementation, void *target, - uint32_t opcode, const struct wl_message *message, union wl_argument *arguments) +/* xdg_toplevel */ +static void +destroy_toplevel(struct wl_resource *resource) +{ + struct xdg_toplevel *toplevel = wl_resource_get_user_data(resource); + + window_finalize(&toplevel->window); + free(toplevel); +} + +static bool +add_state(struct xdg_toplevel *toplevel, uint32_t state) +{ + uint32_t *current_state; + + wl_array_for_each (current_state, &toplevel->states) { + if (*current_state == state) + return false; + } + + if (!(current_state = wl_array_add(&toplevel->states, sizeof(state)))) { + WARNING("xdg_toplevel: Failed to allocate new state\n"); + return false; + } + + *current_state = state; + return true; +} + +static bool +remove_state(struct xdg_toplevel *toplevel, uint32_t state) +{ + uint32_t *current_state; + + wl_array_for_each (current_state, &toplevel->states) { + if (*current_state == state) { + array_remove(&toplevel->states, current_state, sizeof(state)); + return true; + } + } + + return false; +} + +static uint32_t +send_configure(struct xdg_toplevel *toplevel, int32_t width, int32_t height) { + uint32_t serial = wl_display_next_serial(swc.display); + + if (width < 0) + width = toplevel->window.configure.width; + if (height < 0) + height = toplevel->window.configure.height; + + xdg_toplevel_send_configure(toplevel->resource, width, height, &toplevel->states); + xdg_surface_send_configure(toplevel->xdg_surface->resource, serial); + + return serial; +} + +static void +configure(struct window *window, uint32_t width, uint32_t height) +{ + struct xdg_toplevel *toplevel = wl_container_of(window, toplevel, window); + + window->configure.acknowledged = false; + toplevel->xdg_surface->configure_serial = send_configure(toplevel, width, height); +} + +static void +focus(struct window *window) +{ + struct xdg_toplevel *toplevel = wl_container_of(window, toplevel, window); + + add_state(toplevel, XDG_TOPLEVEL_STATE_ACTIVATED); + send_configure(toplevel, -1, -1); +} + +static void +unfocus(struct window *window) { - struct wl_resource *resource = target; + struct xdg_toplevel *toplevel = wl_container_of(window, toplevel, window); - if (opcode != 1) { - wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT, - "use_unstable_version must be called first"); - return 0; + remove_state(toplevel, XDG_TOPLEVEL_STATE_ACTIVATED); + send_configure(toplevel, -1, -1); +} + +static void +close(struct window *window) +{ + struct xdg_toplevel *toplevel = wl_container_of(window, toplevel, window); + + xdg_toplevel_send_close(toplevel->resource); +} + +static void +set_mode(struct window *window, unsigned mode) +{ + struct xdg_toplevel *toplevel = wl_container_of(window, toplevel, window); + + switch (window->mode) { + case WINDOW_MODE_TILED: + remove_state(toplevel, XDG_TOPLEVEL_STATE_MAXIMIZED); + break; + case WINDOW_MODE_FULLSCREEN: + remove_state(toplevel, XDG_TOPLEVEL_STATE_FULLSCREEN); + break; } - 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; + switch (mode) { + case WINDOW_MODE_TILED: + add_state(toplevel, XDG_TOPLEVEL_STATE_MAXIMIZED); + break; + case WINDOW_MODE_FULLSCREEN: + add_state(toplevel, XDG_TOPLEVEL_STATE_FULLSCREEN); + break; } - wl_resource_set_implementation(resource, &shell_implementation, NULL, NULL); - return 1; + send_configure(toplevel, -1, -1); } +static const struct window_impl toplevel_window_impl = { + .configure = configure, + .focus = focus, + .unfocus = unfocus, + .close = close, + .set_mode = set_mode, +}; + static void -bind_shell(struct wl_client *client, void *data, uint32_t version, uint32_t id) +set_parent(struct wl_client *client, struct wl_resource *resource, struct wl_resource *parent_resource) +{ + struct xdg_toplevel *toplevel = wl_resource_get_user_data(resource), *parent = NULL; + + if (parent_resource) + parent = wl_resource_get_user_data(parent_resource); + window_set_parent(&toplevel->window, parent ? &parent->window : NULL); +} + +static void +set_title(struct wl_client *client, struct wl_resource *resource, const char *title) +{ + struct xdg_toplevel *toplevel = wl_resource_get_user_data(resource); + window_set_title(&toplevel->window, title, -1); +} + +static void +set_app_id(struct wl_client *client, struct wl_resource *resource, const char *app_id) +{ + struct xdg_toplevel *toplevel = wl_resource_get_user_data(resource); + window_set_app_id(&toplevel->window, app_id); +} + +static void +show_window_menu(struct wl_client *client, struct wl_resource *resource, struct wl_resource *seat, uint32_t serial, int32_t x, int32_t y) +{ +} + +static void +move(struct wl_client *client, struct wl_resource *resource, struct wl_resource *seat, uint32_t serial) +{ + struct xdg_toplevel *toplevel = wl_resource_get_user_data(resource); + struct button *button; + + button = pointer_get_button(swc.seat->pointer, serial); + if (button) + window_begin_move(&toplevel->window, button); +} + +static void +resize(struct wl_client *client, struct wl_resource *resource, struct wl_resource *seat, uint32_t serial, uint32_t edges) +{ + struct xdg_toplevel *toplevel = wl_resource_get_user_data(resource); + struct button *button; + + button = pointer_get_button(swc.seat->pointer, serial); + if (button) + window_begin_resize(&toplevel->window, edges, button); +} + +static void +set_max_size(struct wl_client *client, struct wl_resource *resource, int32_t width, int32_t height) +{ +} + +static void +set_min_size(struct wl_client *client, struct wl_resource *resource, int32_t width, int32_t height) +{ +} + +static void +set_maximized(struct wl_client *client, struct wl_resource *resource) +{ +} + +static void +unset_maximized(struct wl_client *client, struct wl_resource *resource) +{ +} + +static void +set_fullscreen(struct wl_client *client, struct wl_resource *resource, struct wl_resource *output) +{ +} + +static void +unset_fullscreen(struct wl_client *client, struct wl_resource *resource) +{ +} + +static void +set_minimized(struct wl_client *client, struct wl_resource *resource) +{ +} + +static const struct xdg_toplevel_interface toplevel_impl = { + .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, + .set_max_size = set_max_size, + .set_min_size = set_min_size, + .set_maximized = set_maximized, + .unset_maximized = unset_maximized, + .set_fullscreen = set_fullscreen, + .unset_fullscreen = unset_fullscreen, + .set_minimized = set_minimized, +}; + +static struct xdg_toplevel * +xdg_toplevel_new(struct wl_client *client, uint32_t version, uint32_t id, struct xdg_surface *xdg_surface) +{ + struct xdg_toplevel *toplevel; + + toplevel = malloc(sizeof(*toplevel)); + if (!toplevel) + goto error0; + toplevel->xdg_surface = xdg_surface; + toplevel->resource = wl_resource_create(client, &xdg_toplevel_interface, version, id); + if (!toplevel->resource) + goto error1; + window_initialize(&toplevel->window, &toplevel_window_impl, xdg_surface->surface); + wl_array_init(&toplevel->states); + wl_resource_set_implementation(toplevel->resource, &toplevel_impl, toplevel, &destroy_toplevel); + window_manage(&toplevel->window); + + return toplevel; + +error1: + free(toplevel); +error0: + return NULL; +} + +/* xdg_surface */ +static void +get_toplevel(struct wl_client *client, struct wl_resource *resource, uint32_t id) +{ + struct xdg_surface *xdg_surface = wl_resource_get_user_data(resource); + struct xdg_toplevel *toplevel; + + toplevel = xdg_toplevel_new(client, wl_resource_get_version(resource), id, xdg_surface); + if (!toplevel) { + wl_client_post_no_memory(client); + return; + } + xdg_surface->role = toplevel->resource; +} + +static void +get_popup(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *parent, struct wl_resource *positioner) +{ +} + +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); + struct window *window; + + if (!xdg_surface->role) + return; + window = wl_resource_get_user_data(xdg_surface->role); + if (window && serial == xdg_surface->configure_serial) + 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) +{ +} + +static const struct xdg_surface_interface xdg_surface_impl = { + .destroy = destroy, + .get_toplevel = get_toplevel, + .get_popup = get_popup, + .ack_configure = ack_configure, + .set_window_geometry = set_window_geometry, +}; + +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); + wl_resource_destroy(xdg_surface->role); + free(xdg_surface); +} + +static struct xdg_surface * +xdg_surface_new(struct wl_client *client, uint32_t version, uint32_t id, struct 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; + xdg_surface->surface = surface; + xdg_surface->surface_destroy_listener.notify = &handle_surface_destroy; + wl_resource_add_destroy_listener(surface->resource, &xdg_surface->surface_destroy_listener); + wl_resource_set_implementation(xdg_surface->resource, &xdg_surface_impl, xdg_surface, destroy_xdg_surface); + + return xdg_surface; + +error1: + free(xdg_surface); +error0: + return NULL; +} + +/* xdg_shell */ +static struct { + struct wl_global *global; +} shell; + +static void +create_positioner(struct wl_client *client, struct wl_resource *resource, uint32_t id) +{ + struct xdg_positioner *positioner; + uint32_t version; + + positioner = malloc(sizeof(*positioner)); + if (!positioner) + goto error0; + version = wl_resource_get_version(resource); + positioner->resource = wl_resource_create(client, &xdg_positioner_interface, version, id); + if (!positioner->resource) + goto error1; + wl_resource_set_implementation(positioner->resource, &positioner_implementation, positioner, &destroy_positioner); + return; + +error1: + free(positioner); +error0: + wl_resource_post_no_memory(resource); +} + +static void +get_xdg_surface(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *surface_resource) +{ + struct xdg_surface *xdg_surface; + struct surface *surface = wl_resource_get_user_data(surface_resource); + + xdg_surface = xdg_surface_new(client, wl_resource_get_version(resource), id, surface); + if (!xdg_surface) + wl_client_post_no_memory(client); +} + +static void +pong(struct wl_client *client, struct wl_resource *resource, uint32_t serial) +{ +} + +static const struct xdg_wm_base_interface wm_base_impl = { + .destroy = destroy, + .create_positioner = create_positioner, + .get_xdg_surface = get_xdg_surface, + .pong = pong, +}; + +static void +bind_wm_base(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); + resource = wl_resource_create(client, &xdg_wm_base_interface, version, id); + if (!resource) { + wl_client_post_no_memory(client); + return; + } + wl_resource_set_implementation(resource, &wm_base_impl, NULL, NULL); } bool xdg_shell_initialize(void) { - shell.global = wl_global_create(swc.display, &xdg_shell_interface, 1, NULL, &bind_shell); + shell.global = wl_global_create(swc.display, &xdg_wm_base_interface, 1, NULL, &bind_wm_base); return shell.global; } diff --git a/libswc/xdg_shell.h b/libswc/xdg_shell.h @@ -1,6 +1,6 @@ /* swc: libswc/xdg_shell.h * - * Copyright (c) 2014 Michael Forney + * Copyright (c) 2018 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 diff --git a/libswc/xdg_surface.c b/libswc/xdg_surface.c @@ -1,334 +0,0 @@ -/* 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 <stdlib.h> -#include "xdg-shell-unstable-v5-server-protocol.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) { - array_remove(&xdg_surface->states, current_state, sizeof(state)); - return true; - } - } - - return false; -} - -static uint32_t -send_configure(struct xdg_surface *xdg_surface, int32_t width, int32_t height) { - uint32_t serial = wl_display_next_serial(swc.display); - - if (width < 0) - width = xdg_surface->window.configure.width; - if (height < 0) - height = xdg_surface->window.configure.height; - - xdg_surface_send_configure(xdg_surface->resource, width, height, &xdg_surface->states, serial); - - return serial; -} - -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 = send_configure(xdg_surface, width, height); -} - -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); - send_configure(xdg_surface, -1, -1); -} - -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); - send_configure(xdg_surface, -1, -1); -} - -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; - } - - send_configure(xdg_surface, -1, -1); -} - -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), *parent_surface; - struct window *parent_window = NULL; - - if (parent_resource) { - parent_surface = wl_resource_get_user_data(parent_resource); - parent_window = &parent_surface->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_app_id(&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 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 @@ -1,34 +0,0 @@ -/* 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 surface; -struct wl_client; - -struct xdg_surface *xdg_surface_new(struct wl_client *client, uint32_t version, uint32_t id, struct surface *surface); - -#endif diff --git a/protocol/local.mk b/protocol/local.mk @@ -6,7 +6,7 @@ wayland_protocols := $(call pkgconfig,wayland-protocols,variable=pkgdatadir,DATA PROTOCOL_EXTENSIONS = \ $(dir)/swc.xml \ $(dir)/wayland-drm.xml \ - $(wayland_protocols)/unstable/xdg-shell/xdg-shell-unstable-v5.xml + $(wayland_protocols)/stable/xdg-shell/xdg-shell.xml $(dir)_PACKAGES := wayland-server