commit bf972a9

Michael Forney  ·  2014-10-01 04:40:18 +0000 UTC
parent 8e1d3bf
Implement xdg-shell

Fixes #2
12 files changed,  +1140, -6
+2, -0
1@@ -6,6 +6,8 @@ protocol/swc-protocol.c
2 protocol/swc-server-protocol.h
3 protocol/wayland-drm-protocol.c
4 protocol/wayland-drm-server-protocol.h
5+protocol/xdg-shell-protocol.c
6+protocol/xdg-shell-server-protocol.h
7 
8 /.deps/
9 /swc.pc
+6, -1
 1@@ -56,9 +56,13 @@ SWC_SOURCES =                       \
 2     libswc/view.c                   \
 3     libswc/wayland_buffer.c         \
 4     libswc/window.c                 \
 5+    libswc/xdg_popup.c              \
 6+    libswc/xdg_shell.c              \
 7+    libswc/xdg_surface.c            \
 8     libswc/xkb.c                    \
 9     protocol/swc-protocol.c         \
10-    protocol/wayland-drm-protocol.c
11+    protocol/wayland-drm-protocol.c \
12+    protocol/xdg-shell-protocol.c
13 
14 ifeq ($(ENABLE_LIBINPUT),1)
15 $(dir)_CFLAGS += -DENABLE_LIBINPUT
16@@ -87,6 +91,7 @@ SWC_SHARED_OBJECTS = $(SWC_SOURCES:%.c=%.lo)
17 objects = $(foreach obj,$(1),$(dir)/$(obj).o $(dir)/$(obj).lo)
18 $(call objects,compositor panel_manager panel screen): protocol/swc-server-protocol.h
19 $(call objects,drm drm_buffer): protocol/wayland-drm-server-protocol.h
20+$(call objects,xdg_shell xdg_surface xdg_popup): protocol/xdg-shell-server-protocol.h
21 $(call objects,pointer): cursor/cursor_data.h
22 
23 $(dir)/libswc.a: $(SWC_STATIC_OBJECTS)
+12, -3
 1@@ -37,6 +37,7 @@
 2 #include "shm.h"
 3 #include "util.h"
 4 #include "window.h"
 5+#include "xdg_shell.h"
 6 #ifdef ENABLE_XWAYLAND
 7 # include "xserver.h"
 8 #endif
 9@@ -161,17 +162,23 @@ bool swc_initialize(struct wl_display * display,
10         goto error8;
11     }
12 
13+    if (!xdg_shell_initialize())
14+    {
15+        ERROR("Could not initialize XDG shell\n");
16+        goto error9;
17+    }
18+
19     if (!panel_manager_initialize())
20     {
21         ERROR("Could not initialize panel manager\n");
22-        goto error9;
23+        goto error10;
24     }
25 
26 #ifdef ENABLE_XWAYLAND
27     if (!xserver_initialize())
28     {
29         ERROR("Could not initialize xwayland\n");
30-        goto error10;
31+        goto error11;
32     }
33 #endif
34 
35@@ -180,9 +187,11 @@ bool swc_initialize(struct wl_display * display,
36     return true;
37 
38 #ifdef ENABLE_XWAYLAND
39-  error10:
40+  error11:
41     panel_manager_finalize();
42 #endif
43+  error10:
44+    xdg_shell_finalize();
45   error9:
46     swc_shell_finalize();
47   error8:
+1, -1
1@@ -54,7 +54,7 @@ struct window
2     struct compositor_view * view;
3     struct view_handler view_handler;
4     bool managed;
5-    enum window_mode mode;
6+    unsigned mode;
7 
8     struct
9     {
+111, -0
  1@@ -0,0 +1,111 @@
  2+/* swc: libswc/xdg_popup.c
  3+ *
  4+ * Copyright (c) 2014 Michael Forney
  5+ *
  6+ * Permission is hereby granted, free of charge, to any person obtaining a copy
  7+ * of this software and associated documentation files (the "Software"), to deal
  8+ * in the Software without restriction, including without limitation the rights
  9+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 10+ * copies of the Software, and to permit persons to whom the Software is
 11+ * furnished to do so, subject to the following conditions:
 12+ *
 13+ * The above copyright notice and this permission notice shall be included in
 14+ * all copies or substantial portions of the Software.
 15+ *
 16+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 17+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 18+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 19+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 20+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 21+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 22+ * SOFTWARE.
 23+ */
 24+
 25+#include "xdg_popup.h"
 26+#include "compositor.h"
 27+#include "surface.h"
 28+#include "util.h"
 29+#include "window.h"
 30+#include "protocol/xdg-shell-server-protocol.h"
 31+
 32+#include <stdlib.h>
 33+
 34+struct xdg_popup
 35+{
 36+    struct wl_resource * resource;
 37+    struct compositor_view * view;
 38+    struct wl_listener surface_destroy_listener;
 39+};
 40+
 41+static void destroy(struct wl_client * client, struct wl_resource * resource)
 42+{
 43+    wl_resource_destroy(resource);
 44+}
 45+
 46+static const struct xdg_popup_interface xdg_popup_implementation = {
 47+    .destroy = &destroy
 48+};
 49+
 50+static void handle_surface_destroy(struct wl_listener * listener, void * data)
 51+{
 52+    struct xdg_popup * popup
 53+        = wl_container_of(listener, popup, surface_destroy_listener);
 54+
 55+    wl_resource_destroy(popup->resource);
 56+}
 57+
 58+static void destroy_popup(struct wl_resource * resource)
 59+{
 60+    struct xdg_popup * popup = wl_resource_get_user_data(resource);
 61+
 62+    wl_list_remove(&popup->surface_destroy_listener.link);
 63+    compositor_view_destroy(popup->view);
 64+    free(popup);
 65+}
 66+
 67+struct xdg_popup * xdg_popup_new(struct wl_client * client,
 68+                                 uint32_t version, uint32_t id,
 69+                                 struct swc_surface * surface,
 70+                                 struct swc_surface * parent_surface,
 71+                                 int32_t x, int32_t y)
 72+{
 73+    struct xdg_popup * popup;
 74+    struct compositor_view * parent = compositor_view(parent_surface->view);
 75+
 76+    if (!parent)
 77+        goto error0;
 78+
 79+    popup = malloc(sizeof *popup);
 80+
 81+    if (!popup)
 82+        goto error0;
 83+
 84+    popup->resource = wl_resource_create(client, &xdg_popup_interface,
 85+                                         version, id);
 86+
 87+    if (!popup->resource)
 88+        goto error1;
 89+
 90+    popup->surface_destroy_listener.notify = &handle_surface_destroy;
 91+    wl_resource_add_destroy_listener(surface->resource,
 92+                                     &popup->surface_destroy_listener);
 93+    wl_resource_set_implementation(popup->resource, &xdg_popup_implementation,
 94+                                   popup, &destroy_popup);
 95+
 96+    if (!(popup->view = swc_compositor_create_view(surface)))
 97+        goto error2;
 98+
 99+    view_move(&popup->view->base,
100+              parent->base.geometry.x + x, parent->base.geometry.y + y);
101+    compositor_view_set_parent(popup->view, parent);
102+
103+    return popup;
104+
105+  error2:
106+    wl_resource_destroy(popup->resource);
107+  error1:
108+    free(popup);
109+  error0:
110+    return NULL;
111+}
112+
+39, -0
 1@@ -0,0 +1,39 @@
 2+/* swc: libswc/xdg_popup.h
 3+ *
 4+ * Copyright (c) 2014 Michael Forney
 5+ *
 6+ * Permission is hereby granted, free of charge, to any person obtaining a copy
 7+ * of this software and associated documentation files (the "Software"), to deal
 8+ * in the Software without restriction, including without limitation the rights
 9+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+ * copies of the Software, and to permit persons to whom the Software is
11+ * furnished to do so, subject to the following conditions:
12+ *
13+ * The above copyright notice and this permission notice shall be included in
14+ * all copies or substantial portions of the Software.
15+ *
16+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+ * SOFTWARE.
23+ */
24+
25+#ifndef SWC_XDG_POPUP_H
26+#define SWC_XDG_POPUP_H
27+
28+#include <stdint.h>
29+
30+struct swc_surface;
31+struct wl_client;
32+
33+struct xdg_popup * xdg_popup_new(struct wl_client * client,
34+                                 uint32_t version, uint32_t id,
35+                                 struct swc_surface * surface,
36+                                 struct swc_surface * parent,
37+                                 int32_t x, int32_t y);
38+
39+#endif
40+
+144, -0
  1@@ -0,0 +1,144 @@
  2+/* swc: libswc/xdg_shell.c
  3+ *
  4+ * Copyright (c) 2014 Michael Forney
  5+ *
  6+ * Permission is hereby granted, free of charge, to any person obtaining a copy
  7+ * of this software and associated documentation files (the "Software"), to deal
  8+ * in the Software without restriction, including without limitation the rights
  9+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 10+ * copies of the Software, and to permit persons to whom the Software is
 11+ * furnished to do so, subject to the following conditions:
 12+ *
 13+ * The above copyright notice and this permission notice shall be included in
 14+ * all copies or substantial portions of the Software.
 15+ *
 16+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 17+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 18+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 19+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 20+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 21+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 22+ * SOFTWARE.
 23+ */
 24+
 25+#include "xdg_shell.h"
 26+#include "internal.h"
 27+#include "xdg_popup.h"
 28+#include "xdg_surface.h"
 29+
 30+#include <assert.h>
 31+#include <wayland-server.h>
 32+#include "protocol/xdg-shell-server-protocol.h"
 33+
 34+#define XDG_SHELL_VERSION 4
 35+
 36+static_assert(XDG_SHELL_VERSION == XDG_SHELL_VERSION_CURRENT,
 37+              "xdg_shell implementation does not match protocol version");
 38+
 39+static struct
 40+{
 41+    struct wl_global * global;
 42+} shell;
 43+
 44+static void use_unstable_version(struct wl_client * client,
 45+                                 struct wl_resource * resource, int32_t version)
 46+{
 47+}
 48+
 49+static void get_xdg_surface(struct wl_client * client,
 50+                            struct wl_resource * resource, uint32_t id,
 51+                            struct wl_resource * surface_resource)
 52+{
 53+    struct swc_surface * surface = wl_resource_get_user_data(surface_resource);
 54+    struct xdg_surface * xdg_surface;
 55+
 56+    xdg_surface = xdg_surface_new(client, wl_resource_get_version(resource), id,
 57+                                  surface);
 58+
 59+    if (!xdg_surface)
 60+        wl_resource_post_no_memory(resource);
 61+}
 62+
 63+static void get_xdg_popup(struct wl_client * client,
 64+                          struct wl_resource * resource, uint32_t id,
 65+                          struct wl_resource * surface_resource,
 66+                          struct wl_resource * parent_resource,
 67+                          struct wl_resource * seat_resource,
 68+                          uint32_t serial, int32_t x, int32_t y, uint32_t flags)
 69+{
 70+    struct swc_surface * surface = wl_resource_get_user_data(surface_resource);
 71+    struct swc_surface * parent = wl_resource_get_user_data(parent_resource);
 72+    struct xdg_popup * popup;
 73+
 74+    popup = xdg_popup_new(client, wl_resource_get_version(resource), id,
 75+                          surface, parent, x, y);
 76+
 77+    if (!popup)
 78+        wl_resource_post_no_memory(resource);
 79+}
 80+
 81+static void pong(struct wl_client * client, struct wl_resource * resource,
 82+                 uint32_t serial)
 83+{
 84+}
 85+
 86+static const struct xdg_shell_interface shell_implementation = {
 87+    .use_unstable_version = &use_unstable_version,
 88+    .get_xdg_surface = &get_xdg_surface,
 89+    .get_xdg_popup = &get_xdg_popup,
 90+    .pong = &pong
 91+};
 92+
 93+static int unversioned_dispatch(const void * implementation, void * target,
 94+                                uint32_t opcode,
 95+                                const struct wl_message * message,
 96+                                union wl_argument * arguments)
 97+{
 98+    struct wl_resource * resource = target;
 99+
100+    if (opcode != 0)
101+    {
102+        wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
103+                               "use_unstable_version must be called first");
104+        return 0;
105+    }
106+
107+    if (arguments[0].i != XDG_SHELL_VERSION)
108+    {
109+        wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
110+                               "incompatible xdg_shell versions, "
111+                               "server: %d, client: %d",
112+                               XDG_SHELL_VERSION, arguments[0].i);
113+        return 0;
114+    }
115+
116+    wl_resource_set_implementation(resource, &shell_implementation, NULL, NULL);
117+    return 1;
118+}
119+
120+static void bind_shell(struct wl_client * client, void * data,
121+                       uint32_t version, uint32_t id)
122+{
123+    struct wl_resource * resource;
124+
125+    if (version >= 1)
126+        version = 1;
127+
128+    resource = wl_resource_create(client, &xdg_shell_interface, version, id);
129+    wl_resource_set_dispatcher(resource, &unversioned_dispatch,
130+                               NULL, NULL, NULL);
131+}
132+
133+bool xdg_shell_initialize()
134+{
135+    shell.global = wl_global_create(swc.display, &xdg_shell_interface, 1,
136+                                    NULL, &bind_shell);
137+
138+    return shell.global;
139+}
140+
141+void xdg_shell_finalize()
142+{
143+    wl_global_destroy(shell.global);
144+}
145+
+33, -0
 1@@ -0,0 +1,33 @@
 2+/* swc: libswc/xdg_shell.h
 3+ *
 4+ * Copyright (c) 2014 Michael Forney
 5+ *
 6+ * Permission is hereby granted, free of charge, to any person obtaining a copy
 7+ * of this software and associated documentation files (the "Software"), to deal
 8+ * in the Software without restriction, including without limitation the rights
 9+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+ * copies of the Software, and to permit persons to whom the Software is
11+ * furnished to do so, subject to the following conditions:
12+ *
13+ * The above copyright notice and this permission notice shall be included in
14+ * all copies or substantial portions of the Software.
15+ *
16+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+ * SOFTWARE.
23+ */
24+
25+#ifndef SWC_XDG_SHELL_H
26+#define SWC_XDG_SHELL_H
27+
28+#include <stdbool.h>
29+
30+bool xdg_shell_initialize();
31+void xdg_shell_finalize();
32+
33+#endif
34+
+340, -0
  1@@ -0,0 +1,340 @@
  2+/* swc: libswc/xdg_surface.c
  3+ *
  4+ * Copyright (c) 2014 Michael Forney
  5+ *
  6+ * Permission is hereby granted, free of charge, to any person obtaining a copy
  7+ * of this software and associated documentation files (the "Software"), to deal
  8+ * in the Software without restriction, including without limitation the rights
  9+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 10+ * copies of the Software, and to permit persons to whom the Software is
 11+ * furnished to do so, subject to the following conditions:
 12+ *
 13+ * The above copyright notice and this permission notice shall be included in
 14+ * all copies or substantial portions of the Software.
 15+ *
 16+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 17+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 18+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 19+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 20+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 21+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 22+ * SOFTWARE.
 23+ */
 24+
 25+#include "xdg_surface.h"
 26+#include "compositor.h"
 27+#include "internal.h"
 28+#include "seat.h"
 29+#include "surface.h"
 30+#include "util.h"
 31+#include "view.h"
 32+#include "window.h"
 33+#include "protocol/xdg-shell-server-protocol.h"
 34+
 35+#include <stdlib.h>
 36+
 37+struct xdg_surface
 38+{
 39+    struct window window;
 40+    struct wl_resource * resource;
 41+    struct wl_listener surface_destroy_listener;
 42+    struct wl_array states;
 43+    uint32_t configure_serial;
 44+};
 45+
 46+static bool add_state(struct xdg_surface * xdg_surface, uint32_t state)
 47+{
 48+    uint32_t * current_state;
 49+
 50+    wl_array_for_each(current_state, &xdg_surface->states)
 51+    {
 52+        if (*current_state == state)
 53+            return false;
 54+    }
 55+
 56+    if (!(current_state = wl_array_add(&xdg_surface->states, sizeof state)))
 57+    {
 58+        WARNING("xdg_surface: Failed to allocate new state\n");
 59+        return false;
 60+    }
 61+
 62+    *current_state = state;
 63+    return true;
 64+}
 65+
 66+static bool remove_state(struct xdg_surface * xdg_surface, uint32_t state)
 67+{
 68+    uint32_t * current_state;
 69+
 70+    wl_array_for_each(current_state, &xdg_surface->states)
 71+    {
 72+        if (*current_state == state)
 73+        {
 74+            swc_array_remove(&xdg_surface->states, current_state, sizeof state);
 75+            return true;
 76+        }
 77+    }
 78+
 79+    return false;
 80+}
 81+
 82+static void configure(struct window * window, uint32_t width, uint32_t height)
 83+{
 84+    struct xdg_surface * xdg_surface
 85+        = wl_container_of(window, xdg_surface, window);
 86+
 87+    window->configure.acknowledged = false;
 88+    xdg_surface->configure_serial = wl_display_next_serial(swc.display);
 89+    xdg_surface_send_configure(xdg_surface->resource, width, height,
 90+                               &xdg_surface->states,
 91+                               xdg_surface->configure_serial);
 92+}
 93+
 94+static void focus(struct window * window)
 95+{
 96+    struct xdg_surface * xdg_surface
 97+        = wl_container_of(window, xdg_surface, window);
 98+
 99+    add_state(xdg_surface, XDG_SURFACE_STATE_ACTIVATED);
100+    configure(window, window->configure.width, window->configure.height);
101+}
102+
103+static void unfocus(struct window * window)
104+{
105+    struct xdg_surface * xdg_surface
106+        = wl_container_of(window, xdg_surface, window);
107+
108+    remove_state(xdg_surface, XDG_SURFACE_STATE_ACTIVATED);
109+    configure(window, window->configure.width, window->configure.height);
110+}
111+
112+static void close(struct window * window)
113+{
114+    struct xdg_surface * xdg_surface
115+        = wl_container_of(window, xdg_surface, window);
116+
117+    xdg_surface_send_close(xdg_surface->resource);
118+}
119+
120+static void set_mode(struct window * window, unsigned mode)
121+{
122+    struct xdg_surface * xdg_surface
123+        = wl_container_of(window, xdg_surface, window);
124+
125+    switch (window->mode)
126+    {
127+        case WINDOW_MODE_TILED:
128+            remove_state(xdg_surface, XDG_SURFACE_STATE_MAXIMIZED);
129+            break;
130+        case WINDOW_MODE_FULLSCREEN:
131+            remove_state(xdg_surface, XDG_SURFACE_STATE_FULLSCREEN);
132+            break;
133+    }
134+
135+    switch (mode)
136+    {
137+        case WINDOW_MODE_TILED:
138+            add_state(xdg_surface, XDG_SURFACE_STATE_MAXIMIZED);
139+            break;
140+        case WINDOW_MODE_FULLSCREEN:
141+            add_state(xdg_surface, XDG_SURFACE_STATE_FULLSCREEN);
142+            break;
143+    }
144+}
145+
146+static const struct window_impl xdg_surface_window_impl = {
147+    .configure = &configure,
148+    .focus = &focus,
149+    .unfocus = &unfocus,
150+    .close = &close,
151+    .set_mode = &set_mode,
152+};
153+
154+static void destroy(struct wl_client * client, struct wl_resource * resource)
155+{
156+    wl_resource_destroy(resource);
157+}
158+
159+static void set_parent(struct wl_client * client, struct wl_resource * resource,
160+                       struct wl_resource * parent_resource)
161+{
162+    struct xdg_surface * xdg_surface = wl_resource_get_user_data(resource);
163+    struct swc_surface * parent_surface;
164+    struct compositor_view * parent_view;
165+    struct window * parent_window = NULL;
166+
167+    if (parent_resource)
168+    {
169+        parent_surface = wl_resource_get_user_data(parent_resource);
170+        parent_view = compositor_view(parent_surface->view);
171+        parent_window = parent_view->window;
172+    }
173+
174+    window_set_parent(&xdg_surface->window, parent_window);
175+}
176+
177+static void set_title(struct wl_client * client, struct wl_resource * resource,
178+                      const char * title)
179+{
180+    struct xdg_surface * xdg_surface = wl_resource_get_user_data(resource);
181+
182+    window_set_title(&xdg_surface->window, title, -1);
183+}
184+
185+static void set_app_id(struct wl_client * client, struct wl_resource * resource,
186+                       const char * app_id)
187+{
188+    struct xdg_surface * surface = wl_resource_get_user_data(resource);
189+
190+    window_set_class(&surface->window, app_id);
191+}
192+
193+static void show_window_menu(struct wl_client * client,
194+                             struct wl_resource * resource,
195+                             struct wl_resource * seat_resource,
196+                             uint32_t serial, int32_t x, int32_t y)
197+{
198+}
199+
200+static void move(struct wl_client * client, struct wl_resource * resource,
201+                 struct wl_resource * seat_resource, uint32_t serial)
202+{
203+    struct xdg_surface * xdg_surface = wl_resource_get_user_data(resource);
204+    struct button * button;
205+
206+    if (!(button = pointer_get_button(swc.seat->pointer, serial)))
207+        return;
208+
209+    window_begin_move(&xdg_surface->window, button);
210+}
211+
212+static void resize(struct wl_client * client, struct wl_resource * resource,
213+                   struct wl_resource * seat_resource, uint32_t serial,
214+                   uint32_t edges)
215+{
216+    struct xdg_surface * xdg_surface = wl_resource_get_user_data(resource);
217+    struct button * button;
218+
219+    if (!(button = pointer_get_button(swc.seat->pointer, serial)))
220+        return;
221+
222+    window_begin_resize(&xdg_surface->window, edges, button);
223+}
224+
225+static void ack_configure(struct wl_client * client,
226+                          struct wl_resource * resource, uint32_t serial)
227+{
228+    struct xdg_surface * xdg_surface = wl_resource_get_user_data(resource);
229+
230+    if (serial == xdg_surface->configure_serial)
231+        xdg_surface->window.configure.acknowledged = true;
232+}
233+
234+static void set_window_geometry(struct wl_client * client,
235+                                struct wl_resource * resource,
236+                                int32_t x, int32_t y,
237+                                int32_t width, int32_t height)
238+{
239+    /* TODO: Implement set_window_geometry. */
240+}
241+
242+static void set_maximized(struct wl_client * client,
243+                          struct wl_resource * resource)
244+{
245+    /* TODO: Implement set_maximized. */
246+}
247+
248+static void unset_maximized(struct wl_client * client,
249+                            struct wl_resource * resource)
250+{
251+    /* TODO: Implement unset_maximized. */
252+}
253+
254+static void set_fullscreen(struct wl_client * client,
255+                           struct wl_resource * resource,
256+                           struct wl_resource * output_resource)
257+{
258+    /* TODO: Implement set_fullscreen. */
259+}
260+
261+static void unset_fullscreen(struct wl_client * client,
262+                             struct wl_resource * resource)
263+{
264+    /* TODO: Implement unset_fullscreen. */
265+}
266+
267+static void set_minimized(struct wl_client * client,
268+                          struct wl_resource * resource)
269+{
270+    /* TODO: Implement set_minimized. */
271+}
272+
273+static const struct xdg_surface_interface xdg_surface_implementation = {
274+    .destroy = &destroy,
275+    .set_parent = &set_parent,
276+    .set_title = &set_title,
277+    .set_app_id = &set_app_id,
278+    .show_window_menu = &show_window_menu,
279+    .move = &move,
280+    .resize = &resize,
281+    .ack_configure = &ack_configure,
282+    .set_window_geometry = &set_window_geometry,
283+    .set_maximized = &set_maximized,
284+    .unset_maximized = &unset_maximized,
285+    .set_fullscreen = &set_fullscreen,
286+    .unset_fullscreen = &unset_fullscreen,
287+    .set_minimized = &set_minimized,
288+};
289+
290+static void handle_surface_destroy(struct wl_listener * listener, void * data)
291+{
292+    struct xdg_surface * xdg_surface
293+        = wl_container_of (listener, xdg_surface, surface_destroy_listener);
294+
295+    wl_resource_destroy(xdg_surface->resource);
296+}
297+
298+static void destroy_xdg_surface(struct wl_resource * resource)
299+{
300+    struct xdg_surface * xdg_surface = wl_resource_get_user_data(resource);
301+
302+    wl_list_remove(&xdg_surface->surface_destroy_listener.link);
303+    window_finalize(&xdg_surface->window);
304+    free(xdg_surface);
305+}
306+
307+struct xdg_surface * xdg_surface_new(struct wl_client * client,
308+                                     uint32_t version, uint32_t id,
309+                                     struct swc_surface * surface)
310+{
311+    struct xdg_surface * xdg_surface;
312+
313+    xdg_surface = malloc(sizeof *xdg_surface);
314+
315+    if (!xdg_surface)
316+        goto error0;
317+
318+    xdg_surface->resource = wl_resource_create(client, &xdg_surface_interface,
319+                                               version, id);
320+
321+    if (!xdg_surface->resource)
322+        goto error1;
323+
324+    window_initialize(&xdg_surface->window, &xdg_surface_window_impl, surface);
325+    xdg_surface->surface_destroy_listener.notify = &handle_surface_destroy;
326+    wl_array_init(&xdg_surface->states);
327+    wl_resource_add_destroy_listener(surface->resource,
328+                                     &xdg_surface->surface_destroy_listener);
329+    wl_resource_set_implementation(xdg_surface->resource,
330+                                   &xdg_surface_implementation,
331+                                   xdg_surface, &destroy_xdg_surface);
332+    window_manage(&xdg_surface->window);
333+
334+    return xdg_surface;
335+
336+  error1:
337+    free(xdg_surface);
338+  error0:
339+    return NULL;
340+}
341+
+37, -0
 1@@ -0,0 +1,37 @@
 2+/* swc: libswc/xdg_surface.h
 3+ *
 4+ * Copyright (c) 2014 Michael Forney
 5+ *
 6+ * Permission is hereby granted, free of charge, to any person obtaining a copy
 7+ * of this software and associated documentation files (the "Software"), to deal
 8+ * in the Software without restriction, including without limitation the rights
 9+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+ * copies of the Software, and to permit persons to whom the Software is
11+ * furnished to do so, subject to the following conditions:
12+ *
13+ * The above copyright notice and this permission notice shall be included in
14+ * all copies or substantial portions of the Software.
15+ *
16+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+ * SOFTWARE.
23+ */
24+
25+#ifndef SWC_XDG_SURFACE_H
26+#define SWC_XDG_SURFACE_H
27+
28+#include <stdint.h>
29+
30+struct swc_surface;
31+struct wl_client;
32+
33+struct xdg_surface * xdg_surface_new(struct wl_client * client,
34+                                     uint32_t version, uint32_t id,
35+                                     struct swc_surface * surface);
36+
37+#endif
38+
+2, -1
 1@@ -4,7 +4,8 @@ dir := protocol
 2 
 3 PROTOCOL_EXTENSIONS =           \
 4     $(dir)/swc.xml              \
 5-    $(dir)/wayland-drm.xml
 6+    $(dir)/wayland-drm.xml      \
 7+    $(dir)/xdg-shell.xml
 8 
 9 $(dir)_TARGETS := $(PROTOCOL_EXTENSIONS:%.xml=%-protocol.c) \
10                   $(PROTOCOL_EXTENSIONS:%.xml=%-server-protocol.h)
+413, -0
  1@@ -0,0 +1,413 @@
  2+<?xml version="1.0" encoding="UTF-8"?>
  3+<protocol name="xdg_shell">
  4+
  5+  <copyright>
  6+    Copyright © 2008-2013 Kristian Høgsberg
  7+    Copyright © 2013      Rafael Antognolli
  8+    Copyright © 2013      Jasper St. Pierre
  9+    Copyright © 2010-2013 Intel Corporation
 10+
 11+    Permission to use, copy, modify, distribute, and sell this
 12+    software and its documentation for any purpose is hereby granted
 13+    without fee, provided that the above copyright notice appear in
 14+    all copies and that both that copyright notice and this permission
 15+    notice appear in supporting documentation, and that the name of
 16+    the copyright holders not be used in advertising or publicity
 17+    pertaining to distribution of the software without specific,
 18+    written prior permission.  The copyright holders make no
 19+    representations about the suitability of this software for any
 20+    purpose.  It is provided "as is" without express or implied
 21+    warranty.
 22+
 23+    THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
 24+    SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
 25+    FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
 26+    SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 27+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
 28+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 29+    ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
 30+    THIS SOFTWARE.
 31+  </copyright>
 32+
 33+  <interface name="xdg_shell" version="1">
 34+    <description summary="create desktop-style surfaces">
 35+      This interface is implemented by servers that provide
 36+      desktop-style user interfaces.
 37+
 38+      It allows clients to associate a xdg_surface with
 39+      a basic surface.
 40+    </description>
 41+
 42+    <enum name="version">
 43+      <description summary="latest protocol version">
 44+	The 'current' member of this enum gives the version of the
 45+	protocol.  Implementations can compare this to the version
 46+	they implement using static_assert to ensure the protocol and
 47+	implementation versions match.
 48+      </description>
 49+      <entry name="current" value="4" summary="Always the latest version"/>
 50+    </enum>
 51+
 52+
 53+    <request name="use_unstable_version">
 54+      <description summary="enable use of this unstable version">
 55+	Negotiate the unstable version of the interface.  This
 56+	mechanism is in place to ensure client and server agree on the
 57+	unstable versions of the protocol that they speak or exit
 58+	cleanly if they don't agree.  This request will go away once
 59+	the xdg-shell protocol is stable.
 60+      </description>
 61+      <arg name="version" type="int"/>
 62+    </request>
 63+
 64+    <request name="get_xdg_surface">
 65+      <description summary="create a shell surface from a surface">
 66+	Create a shell surface for an existing surface.
 67+
 68+	Only one shell or popup surface can be associated with a given
 69+	surface.
 70+      </description>
 71+      <arg name="id" type="new_id" interface="xdg_surface"/>
 72+      <arg name="surface" type="object" interface="wl_surface"/>
 73+    </request>
 74+
 75+    <request name="get_xdg_popup">
 76+      <description summary="create a shell surface from a surface">
 77+	Create a popup surface for an existing surface.
 78+
 79+	Only one shell or popup surface can be associated with a given
 80+	surface.
 81+      </description>
 82+      <arg name="id" type="new_id" interface="xdg_popup"/>
 83+      <arg name="surface" type="object" interface="wl_surface"/>
 84+      <arg name="parent" type="object" interface="wl_surface"/>
 85+      <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat whose pointer is used"/>
 86+      <arg name="serial" type="uint" summary="serial of the implicit grab on the pointer"/>
 87+      <arg name="x" type="int"/>
 88+      <arg name="y" type="int"/>
 89+      <arg name="flags" type="uint"/>
 90+    </request>
 91+
 92+    <event name="ping">
 93+      <description summary="check if the client is alive">
 94+        The ping event asks the client if it's still alive. Pass the
 95+        serial specified in the event back to the compositor by sending
 96+        a "pong" request back with the specified serial.
 97+
 98+        Compositors can use this to determine if the client is still
 99+        alive. It's unspecified what will happen if the client doesn't
100+        respond to the ping request, or in what timeframe. Clients should
101+        try to respond in a reasonable amount of time.
102+      </description>
103+      <arg name="serial" type="uint" summary="pass this to the callback"/>
104+    </event>
105+
106+    <request name="pong">
107+      <description summary="respond to a ping event">
108+	A client must respond to a ping event with a pong request or
109+	the client may be deemed unresponsive.
110+      </description>
111+      <arg name="serial" type="uint" summary="serial of the ping event"/>
112+    </request>
113+  </interface>
114+
115+  <interface name="xdg_surface" version="1">
116+
117+    <description summary="desktop-style metadata interface">
118+      An interface that may be implemented by a wl_surface, for
119+      implementations that provide a desktop-style user interface.
120+
121+      It provides requests to treat surfaces like windows, allowing to set
122+      properties like maximized, fullscreen, minimized, and to move and resize
123+      them, and associate metadata like title and app id.
124+
125+      On the server side the object is automatically destroyed when
126+      the related wl_surface is destroyed.  On client side,
127+      xdg_surface.destroy() must be called before destroying
128+      the wl_surface object.
129+    </description>
130+
131+    <request name="destroy" type="destructor">
132+      <description summary="remove xdg_surface interface">
133+	The xdg_surface interface is removed from the wl_surface object
134+	that was turned into a xdg_surface with
135+	xdg_shell.get_xdg_surface request. The xdg_surface properties,
136+	like maximized and fullscreen, are lost. The wl_surface loses
137+	its role as a xdg_surface. The wl_surface is unmapped.
138+      </description>
139+    </request>
140+
141+    <request name="set_parent">
142+      <description summary="surface is a child of another surface">
143+	Child surfaces are stacked above their parents, and will be
144+	unmapped if the parent is unmapped too. They should not appear
145+	on task bars and alt+tab.
146+      </description>
147+      <arg name="parent" type="object" interface="wl_surface" allow-null="true"/>
148+    </request>
149+
150+    <request name="set_title">
151+      <description summary="set surface title">
152+	Set a short title for the surface.
153+
154+	This string may be used to identify the surface in a task bar,
155+	window list, or other user interface elements provided by the
156+	compositor.
157+
158+	The string must be encoded in UTF-8.
159+      </description>
160+      <arg name="title" type="string"/>
161+    </request>
162+
163+    <request name="set_app_id">
164+      <description summary="set surface class">
165+	Set an id for the surface.
166+
167+	The app id identifies the general class of applications to which
168+	the surface belongs.
169+
170+	It should be the ID that appears in the new desktop entry
171+	specification, the interface name.
172+      </description>
173+      <arg name="app_id" type="string"/>
174+    </request>
175+
176+    <request name="show_window_menu">
177+      <description summary="show the window menu">
178+        Clients implementing client-side decorations might want to show
179+        a context menu when right-clicking on the decorations, giving the
180+        user a menu that they can use to maximize or minimize the window.
181+
182+        This request asks the compositor to pop up such a window menu at
183+        the given position, relative to the parent surface. There are
184+        no guarantees as to what the window menu contains.
185+
186+        Your surface must have focus on the seat passed in to pop up the
187+        window menu.
188+      </description>
189+
190+      <arg name="seat" type="object" interface="wl_seat" summary="the seat to pop the window up on"/>
191+      <arg name="serial" type="uint" summary="serial of the event to pop up the window for"/>
192+      <arg name="x" type="int" summary="the x position to pop up the window menu at"/>
193+      <arg name="y" type="int" summary="the y position to pop up the window menu at"/>
194+    </request>
195+
196+    <request name="move">
197+      <description summary="start an interactive move">
198+	Start a pointer-driven move of the surface.
199+
200+	This request must be used in response to a button press event.
201+	The server may ignore move requests depending on the state of
202+	the surface (e.g. fullscreen or maximized).
203+      </description>
204+      <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat whose pointer is used"/>
205+      <arg name="serial" type="uint" summary="serial of the implicit grab on the pointer"/>
206+    </request>
207+
208+    <enum name="resize_edge">
209+      <description summary="edge values for resizing">
210+	These values are used to indicate which edge of a surface
211+	is being dragged in a resize operation. The server may
212+	use this information to adapt its behavior, e.g. choose
213+	an appropriate cursor image.
214+      </description>
215+      <entry name="none" value="0"/>
216+      <entry name="top" value="1"/>
217+      <entry name="bottom" value="2"/>
218+      <entry name="left" value="4"/>
219+      <entry name="top_left" value="5"/>
220+      <entry name="bottom_left" value="6"/>
221+      <entry name="right" value="8"/>
222+      <entry name="top_right" value="9"/>
223+      <entry name="bottom_right" value="10"/>
224+    </enum>
225+
226+    <request name="resize">
227+      <description summary="start an interactive resize">
228+	Start a pointer-driven resizing of the surface.
229+
230+	This request must be used in response to a button press event.
231+	The server may ignore resize requests depending on the state of
232+	the surface (e.g. fullscreen or maximized).
233+      </description>
234+      <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat whose pointer is used"/>
235+      <arg name="serial" type="uint" summary="serial of the implicit grab on the pointer"/>
236+      <arg name="edges" type="uint" summary="which edge or corner is being dragged"/>
237+    </request>
238+
239+    <enum name="state">
240+      <description summary="types of state on the surface">
241+        The different state values used on the surface. This is designed for
242+        state values like maximized, fullscreen. It is paired with the
243+        configure event to ensure that both the client and the compositor
244+        setting the state can be synchronized.
245+
246+        States set in this way are double-buffered. They will get applied on
247+        the next commit.
248+
249+        Desktop environments may extend this enum by taking up a range of
250+        values and documenting the range they chose in this description.
251+        They are not required to document the values for the range that they
252+        chose. Ideally, any good extensions from a desktop environment should
253+        make its way into standardization into this enum.
254+
255+        The current reserved ranges are:
256+
257+        0x0000 - 0x0FFF: xdg-shell core values, documented below.
258+        0x1000 - 0x1FFF: GNOME
259+      </description>
260+      <entry name="maximized" value="1" summary="the surface is maximized">
261+        The surface is maximized. The window geometry specified in the configure
262+        event must be obeyed by the client.
263+      </entry>
264+      <entry name="fullscreen" value="2" summary="the surface is fullscreen">
265+        The surface is fullscreen. The window geometry specified in the configure
266+        event must be obeyed by the client.
267+      </entry>
268+      <entry name="resizing" value="3">
269+        The surface is being resized. The window geometry specified in the
270+        configure event is a maximum; the client cannot resize beyond it.
271+        Clients that have aspect ratio or cell sizing configuration can use
272+        a smaller size, however.
273+      </entry>
274+      <entry name="activated" value="4">
275+        Client window decorations should be painted as if the window is
276+        active. Do not assume this means that the window actually has
277+        keyboard or pointer focus.
278+      </entry>
279+    </enum>
280+
281+    <event name="configure">
282+      <description summary="suggest a surface change">
283+	The configure event asks the client to resize its surface.
284+
285+	The width and height arguments specify a hint to the window
286+        about how its surface should be resized in window geometry
287+        coordinates. The states listed in the event specify how the
288+        width/height arguments should be interpreted.
289+
290+        A client should arrange a new surface, and then send a
291+        ack_configure request with the serial sent in this configure
292+        event before attaching a new surface.
293+
294+	If the client receives multiple configure events before it
295+        can respond to one, it is free to discard all but the last
296+        event it received.
297+      </description>
298+
299+      <arg name="width" type="int"/>
300+      <arg name="height" type="int"/>
301+      <arg name="states" type="array"/>
302+      <arg name="serial" type="uint"/>
303+    </event>
304+
305+    <request name="ack_configure">
306+      <description summary="ack a configure event">
307+        When a configure event is received, a client should then ack it
308+        using the ack_configure request to ensure that the compositor
309+        knows the client has seen the event.
310+
311+        By this point, the state is confirmed, and the next attach should
312+        contain the buffer drawn for the configure event you are acking.
313+      </description>
314+      <arg name="serial" type="uint" summary="a serial to configure for"/>
315+    </request>
316+
317+    <request name="set_window_geometry">
318+      <description summary="set the new window geometry">
319+        The window geometry of a window is its "visible bounds" from the
320+        user's perspective. Client-side decorations often have invisible
321+        portions like drop-shadows which should be ignored for the
322+        purposes of aligning, placing and constraining windows.
323+
324+        The default value is the full bounds of the surface, including any
325+        subsurfaces. Once the window geometry of the surface is set once,
326+        it is not possible to unset it, and it will remain the same until
327+        set_window_geometry is called again, even if a new subsurface or
328+        buffer is attached.
329+
330+        If responding to a configure event, the window geometry in here
331+        must respect the sizing negotiations specified by the states in
332+        the configure event.
333+      </description>
334+      <arg name="x" type="int"/>
335+      <arg name="y" type="int"/>
336+      <arg name="width" type="int"/>
337+      <arg name="height" type="int"/>
338+    </request>
339+
340+    <request name="set_maximized" />
341+    <request name="unset_maximized" />
342+
343+    <request name="set_fullscreen">
344+      <description summary="set the window as fullscreen on a monitor">
345+	Make the surface fullscreen.
346+
347+        You can specify an output that you would prefer to be fullscreen.
348+	If this value is NULL, it's up to the compositor to choose which
349+        display will be used to map this surface.
350+      </description>
351+      <arg name="output" type="object" interface="wl_output" allow-null="true"/>
352+    </request>
353+    <request name="unset_fullscreen" />
354+
355+    <request name="set_minimized" />
356+
357+    <event name="close">
358+      <description summary="surface wants to be closed">
359+        The close event is sent by the compositor when the user
360+        wants the surface to be closed. This should be equivalent to
361+        the user clicking the close button in client-side decorations,
362+        if your application has any...
363+
364+        This is only a request that the user intends to close your
365+        window. The client may choose to ignore this request, or show
366+        a dialog to ask the user to save their data...
367+      </description>
368+    </event>
369+  </interface>
370+
371+  <interface name="xdg_popup" version="1">
372+    <description summary="desktop-style metadata interface">
373+      An interface that may be implemented by a wl_surface, for
374+      implementations that provide a desktop-style popups/menus. A popup
375+      surface is a transient surface with an added pointer grab.
376+
377+      An existing implicit grab will be changed to owner-events mode,
378+      and the popup grab will continue after the implicit grab ends
379+      (i.e. releasing the mouse button does not cause the popup to be
380+      unmapped).
381+
382+      The popup grab continues until the window is destroyed or a mouse
383+      button is pressed in any other clients window. A click in any of
384+      the clients surfaces is reported as normal, however, clicks in
385+      other clients surfaces will be discarded and trigger the callback.
386+
387+      The x and y arguments specify the locations of the upper left
388+      corner of the surface relative to the upper left corner of the
389+      parent surface, in surface local coordinates.
390+
391+      xdg_popup surfaces are always transient for another surface.
392+    </description>
393+
394+    <request name="destroy" type="destructor">
395+      <description summary="remove xdg_surface interface">
396+	The xdg_surface interface is removed from the wl_surface object
397+	that was turned into a xdg_surface with
398+	xdg_shell.get_xdg_surface request. The xdg_surface properties,
399+	like maximized and fullscreen, are lost. The wl_surface loses
400+	its role as a xdg_surface. The wl_surface is unmapped.
401+      </description>
402+    </request>
403+
404+    <event name="popup_done">
405+      <description summary="popup interaction is done">
406+	The popup_done event is sent out when a popup grab is broken,
407+	that is, when the users clicks a surface that doesn't belong
408+	to the client owning the popup surface.
409+      </description>
410+      <arg name="serial" type="uint" summary="serial of the implicit grab on the pointer"/>
411+    </event>
412+
413+  </interface>
414+</protocol>