commit ec48a73

Michael Forney  ·  2014-01-23 01:29:14 +0000 UTC
parent f743751
Implement panels
10 files changed,  +489, -2
+1, -1
1@@ -48,7 +48,7 @@ pkgconfig   = $(sort $(foreach pkg,$(1),$(if $($(pkg)_$(3)),$($(pkg)_$(3)), \
2 
3 include $(SUBDIRS:%=%/local.mk)
4 
5-$(foreach dir,BIN LIB INCLUDE PKGCONFIG,$(DESTDIR)$($(dir)DIR)):
6+$(foreach dir,BIN LIB INCLUDE PKGCONFIG,$(DESTDIR)$($(dir)DIR)) $(DESTDIR)$(DATADIR)/swc:
7 	mkdir -p "$@"
8 
9 .PHONY: check-dependencies
+1, -0
1@@ -4,6 +4,7 @@ PREFIX          = /usr/local
2 BINDIR          = $(PREFIX)/bin
3 LIBDIR          = $(PREFIX)/lib
4 INCLUDEDIR      = $(PREFIX)/include
5+DATADIR         = $(PREFIX)/share
6 PKGCONFIGDIR    = $(LIBDIR)/pkgconfig
7 
8 CC              = gcc
+4, -0
 1@@ -44,6 +44,8 @@ SWC_SOURCES =                       \
 2     libswc/launch.c                 \
 3     libswc/mode.c                   \
 4     libswc/output.c                 \
 5+    libswc/panel.c                  \
 6+    libswc/panel_manager.c          \
 7     libswc/pointer.c                \
 8     libswc/region.c                 \
 9     libswc/screen.c                 \
10@@ -58,6 +60,7 @@ SWC_SOURCES =                       \
11     libswc/wayland_buffer.c         \
12     libswc/window.c                 \
13     libswc/xkb.c                    \
14+    protocol/swc-protocol.c         \
15     protocol/wayland-drm-protocol.c
16 
17 ifeq ($(ENABLE_HOTPLUGGING),1)
18@@ -85,6 +88,7 @@ SWC_SHARED_OBJECTS = $(SWC_SOURCES:%.c=%.lo)
19 objects = $(foreach obj,$(1),$(dir)/$(obj).o $(dir)/$(obj).lo)
20 $(call objects,drm drm_buffer): protocol/wayland-drm-server-protocol.h
21 $(call objects,xserver): protocol/xserver-server-protocol.h
22+$(call objects,panel_manager panel): protocol/swc-server-protocol.h
23 $(call objects,pointer): cursor/cursor_data.h
24 
25 $(dir)/libswc.a: $(SWC_STATIC_OBJECTS)
+261, -0
  1@@ -0,0 +1,261 @@
  2+/* swc: libswc/panel.c
  3+ *
  4+ * Copyright (c) 2013, 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 "panel.h"
 26+#include "compositor.h"
 27+#include "internal.h"
 28+#include "keyboard.h"
 29+#include "output.h"
 30+#include "screen.h"
 31+#include "seat.h"
 32+#include "surface.h"
 33+#include "util.h"
 34+#include "view.h"
 35+#include "protocol/swc-server-protocol.h"
 36+
 37+#include <assert.h>
 38+#include <stdlib.h>
 39+
 40+static void update_position(struct swc_panel * panel)
 41+{
 42+    int32_t x, y;
 43+    struct swc_rectangle * screen = &panel->screen->base.geometry,
 44+                         * view = &panel->surface->view->geometry;
 45+
 46+    switch (panel->edge)
 47+    {
 48+        case SWC_PANEL_EDGE_TOP:
 49+            x = screen->x + panel->offset;
 50+            y = screen->y;
 51+            break;
 52+        case SWC_PANEL_EDGE_BOTTOM:
 53+            x = screen->x + panel->offset;
 54+            y = screen->y + screen->height - view->height;
 55+            break;
 56+        case SWC_PANEL_EDGE_LEFT:
 57+            x = screen->x;
 58+            y = screen->y + screen->height - view->height - panel->offset;
 59+            break;
 60+        case SWC_PANEL_EDGE_RIGHT:
 61+            x = screen->x + screen->width - view->width;
 62+            y = screen->y + panel->offset;
 63+            break;
 64+    }
 65+
 66+    swc_view_move(panel->surface->view, x, y);
 67+}
 68+
 69+static void dock(struct wl_client * client, struct wl_resource * resource,
 70+                 uint32_t edge, struct wl_resource * output_resource,
 71+                 uint32_t focus)
 72+{
 73+    struct swc_panel * panel = wl_resource_get_user_data(resource);
 74+    struct swc_output * output = output_resource
 75+        ? wl_resource_get_user_data(output_resource) : NULL;
 76+    struct swc_screen_internal * screen = output
 77+        ? output->screen : CONTAINER_OF(swc.screens.next,
 78+                                        struct swc_screen_internal, link);
 79+    bool screen_changed = screen != panel->screen;
 80+    uint32_t length;
 81+
 82+    if (panel->docked)
 83+        wl_list_remove(&panel->view_listener.link);
 84+
 85+    if (panel->screen && screen_changed)
 86+    {
 87+        wl_list_remove(&panel->modifier.link);
 88+        swc_screen_update_usable_geometry(panel->screen);
 89+    }
 90+
 91+    panel->screen = screen;
 92+    panel->edge = edge;
 93+    panel->docked = true;
 94+
 95+    switch (edge)
 96+    {
 97+        case SWC_PANEL_EDGE_TOP:
 98+        case SWC_PANEL_EDGE_BOTTOM:
 99+            length = panel->screen->base.geometry.width;
100+            break;
101+        case SWC_PANEL_EDGE_LEFT:
102+        case SWC_PANEL_EDGE_RIGHT:
103+            length = panel->screen->base.geometry.height;
104+            break;
105+    }
106+
107+    swc_compositor_add_surface(panel->surface);
108+    update_position(panel);
109+    swc_compositor_surface_show(panel->surface);
110+    wl_signal_add(&panel->surface->view->event_signal, &panel->view_listener);
111+    wl_list_insert(&screen->modifiers, &panel->modifier.link);
112+
113+    if (focus)
114+        swc_keyboard_set_focus(swc.seat->keyboard, panel->surface);
115+
116+    swc_panel_send_docked(resource, length);
117+}
118+
119+static void set_offset(struct wl_client * client, struct wl_resource * resource,
120+                       uint32_t offset)
121+{
122+    struct swc_panel * panel = wl_resource_get_user_data(resource);
123+
124+    panel->offset = offset;
125+
126+    if (panel->docked)
127+        update_position(panel);
128+}
129+
130+static void set_strut(struct wl_client * client, struct wl_resource * resource,
131+                      uint32_t size, uint32_t begin, uint32_t end)
132+{
133+    struct swc_panel * panel = wl_resource_get_user_data(resource);
134+
135+    panel->strut_size = size;
136+
137+    if (panel->docked)
138+        swc_screen_update_usable_geometry(panel->screen);
139+}
140+
141+static const struct swc_panel_interface panel_implementation = {
142+    .dock = &dock,
143+    .set_offset = &set_offset,
144+    .set_strut = &set_strut
145+};
146+
147+static void modify(struct swc_screen_modifier * modifier,
148+                   const struct swc_rectangle * geometry,
149+                   pixman_region32_t * usable)
150+{
151+    struct swc_panel * panel = CONTAINER_OF(modifier, typeof(*panel), modifier);
152+    pixman_box32_t box = {
153+        .x1 = geometry->x, .y1 = geometry->y,
154+        .x2 = geometry->x + geometry->width,
155+        .y2 = geometry->y + geometry->height
156+    };
157+
158+    assert(panel->docked);
159+
160+    DEBUG("Original geometry { x1: %d, y1: %d, x2: %d, y2: %d }\n",
161+          box.x1, box.y1, box.x2, box.y2);
162+
163+    switch (panel->edge)
164+    {
165+        case SWC_PANEL_EDGE_TOP:
166+            box.y1 = MAX(box.y1, geometry->y + panel->strut_size);
167+            break;
168+        case SWC_PANEL_EDGE_BOTTOM:
169+            box.y2 = MIN(box.y2, geometry->y + geometry->height
170+                         - panel->strut_size);
171+            break;
172+        case SWC_PANEL_EDGE_LEFT:
173+            box.x1 = MAX(box.x1, geometry->x + panel->strut_size);
174+            break;
175+        case SWC_PANEL_EDGE_RIGHT:
176+            box.x2 = MIN(box.x2, geometry->x + geometry->width
177+                         - panel->strut_size);
178+            break;
179+    }
180+
181+    DEBUG("Usable region { x1: %d, y1: %d, x2: %d, y2: %d }\n",
182+          box.x1, box.y1, box.x2, box.y2);
183+
184+    pixman_region32_reset(usable, &box);
185+}
186+
187+static void destroy_panel(struct wl_resource * resource)
188+{
189+    struct swc_panel * panel = wl_resource_get_user_data(resource);
190+
191+    if (panel->docked)
192+    {
193+        wl_list_remove(&panel->view_listener.link);
194+        wl_list_remove(&panel->modifier.link);
195+        swc_screen_update_usable_geometry(panel->screen);
196+        swc_compositor_remove_surface(panel->surface);
197+    }
198+
199+    free(panel);
200+}
201+
202+static void handle_view_event(struct wl_listener * listener, void * data)
203+{
204+    struct swc_panel * panel;
205+    struct swc_event * event = data;
206+
207+    panel = CONTAINER_OF(listener, typeof(*panel), view_listener);
208+
209+    switch (event->type)
210+    {
211+        case SWC_VIEW_EVENT_RESIZED:
212+            update_position(panel);
213+            break;
214+    }
215+}
216+
217+static void handle_surface_destroy(struct wl_listener * listener, void * data)
218+{
219+    struct swc_panel * panel;
220+
221+    panel = CONTAINER_OF(listener, typeof(*panel), surface_destroy_listener);
222+    wl_resource_destroy(panel->resource);
223+}
224+
225+struct swc_panel * swc_panel_new(struct wl_client * client, uint32_t id,
226+                                 struct swc_surface * surface)
227+{
228+    struct swc_panel * panel;
229+
230+    panel = malloc(sizeof *panel);
231+
232+    if (!panel)
233+        goto error0;
234+
235+    panel->resource = wl_resource_create(client, &swc_panel_interface, 1, id);
236+
237+    if (!panel->resource)
238+        goto error1;
239+
240+    wl_resource_set_implementation(panel->resource, &panel_implementation,
241+                                   panel, &destroy_panel);
242+
243+    panel->surface = surface;
244+    panel->surface_destroy_listener.notify = &handle_surface_destroy;
245+    panel->view_listener.notify = &handle_view_event;
246+    panel->modifier.modify = &modify;
247+    panel->screen = NULL;
248+    panel->offset = 0;
249+    panel->strut_size = 0;
250+    panel->docked = false;
251+
252+    wl_resource_add_destroy_listener(surface->resource,
253+                                     &panel->surface_destroy_listener);
254+
255+    return panel;
256+
257+  error1:
258+    free(panel);
259+  error0:
260+    return NULL;
261+}
262+
+50, -0
 1@@ -0,0 +1,50 @@
 2+/* swc: libswc/panel.h
 3+ *
 4+ * Copyright (c) 2013, 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_PANEL_H
26+#define SWC_PANEL_H
27+
28+#include "screen.h"
29+
30+#include <stdbool.h>
31+#include <wayland-server.h>
32+
33+struct swc_panel
34+{
35+    struct wl_resource * resource;
36+
37+    struct swc_surface * surface;
38+    struct wl_listener surface_destroy_listener;
39+    struct wl_listener view_listener;
40+    struct swc_screen_internal * screen;
41+    struct swc_screen_modifier modifier;
42+    uint32_t edge;
43+    uint32_t offset, strut_size;
44+    bool docked;
45+};
46+
47+struct swc_panel * swc_panel_new(struct wl_client * client, uint32_t id,
48+                                 struct swc_surface * surface);
49+
50+#endif
51+
+82, -0
 1@@ -0,0 +1,82 @@
 2+/* swc: libswc/panel_manager.c
 3+ *
 4+ * Copyright (c) 2013, 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 "panel_manager.h"
26+#include "internal.h"
27+#include "panel.h"
28+
29+#include <wayland-server.h>
30+#include "protocol/swc-server-protocol.h"
31+
32+static struct
33+{
34+    struct wl_global * global;
35+    struct wl_resource * resource;
36+} panel_manager;
37+
38+static void create_panel(struct wl_client * client,
39+                         struct wl_resource * resource, uint32_t id,
40+                         struct wl_resource * surface_resource)
41+{
42+    struct swc_surface * surface = wl_resource_get_user_data(surface_resource);
43+    struct swc_panel * panel;
44+
45+    panel = swc_panel_new(client, id, surface);
46+
47+    if (!panel)
48+        wl_client_post_no_memory(client);
49+}
50+
51+static const struct swc_panel_manager_interface panel_manager_implementation = {
52+    .create_panel = &create_panel
53+};
54+
55+static void bind_panel_manager(struct wl_client * client, void * data,
56+                               uint32_t version, uint32_t id)
57+{
58+    struct wl_resource * resource;
59+
60+    resource = wl_resource_create(client, &swc_panel_manager_interface, 1, id);
61+    wl_resource_set_implementation(resource, &panel_manager_implementation,
62+                                   NULL, NULL);
63+}
64+
65+bool swc_panel_manager_initialize()
66+{
67+    panel_manager.global = wl_global_create(swc.display,
68+                                            &swc_panel_manager_interface, 1,
69+                                            NULL, &bind_panel_manager);
70+
71+    if (!panel_manager.global)
72+        return false;
73+
74+    return true;
75+}
76+
77+void swc_panel_manager_finalize()
78+{
79+    wl_global_destroy(panel_manager.global);
80+}
81+
82+// vim: fdm=syntax fo=croql et sw=4 sts=4 ts=8
83+
+33, -0
 1@@ -0,0 +1,33 @@
 2+/* swc: libswc/panel_manager.h
 3+ *
 4+ * Copyright (c) 2013 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_PANEL_MANAGER_H
26+#define SWC_PANEL_MANAGER_H
27+
28+#include <stdbool.h>
29+
30+bool swc_panel_manager_initialize();
31+void swc_panel_manager_finalize();
32+
33+#endif
34+
+13, -1
 1@@ -29,6 +29,7 @@
 2 #include "internal.h"
 3 #include "launch.h"
 4 #include "keyboard.h"
 5+#include "panel_manager.h"
 6 #include "pointer.h"
 7 #include "screen.h"
 8 #include "seat.h"
 9@@ -147,11 +148,17 @@ bool swc_initialize(struct wl_display * display,
10         goto error8;
11     }
12 
13+    if (!swc_panel_manager_initialize())
14+    {
15+        ERROR("Could not initialize panel manager\n");
16+        goto error9;
17+    }
18+
19 #ifdef ENABLE_XWAYLAND
20     if (!swc_xserver_initialize())
21     {
22         ERROR("Could not initialize xwayland\n");
23-        goto error9;
24+        goto error10;
25     }
26 #endif
27 
28@@ -159,6 +166,10 @@ bool swc_initialize(struct wl_display * display,
29 
30     return true;
31 
32+#ifdef ENABLE_XWAYLAND
33+  error10:
34+    swc_panel_manager_finalize();
35+#endif
36   error9:
37     swc_shell_finalize();
38   error8:
39@@ -187,6 +198,7 @@ void swc_finalize()
40 #ifdef ENABLE_XWAYLAND
41     swc_xserver_finalize();
42 #endif
43+    swc_panel_manager_finalize();
44     swc_shell_finalize();
45     swc_seat_finalize();
46     swc_data_device_manager_finalize();
+4, -0
 1@@ -3,6 +3,7 @@
 2 dir := protocol
 3 
 4 PROTOCOL_EXTENSIONS =           \
 5+    $(dir)/swc.xml              \
 6     $(dir)/wayland-drm.xml      \
 7     $(dir)/xserver.xml
 8 
 9@@ -15,5 +16,8 @@ $(dir)/%-protocol.c: $(dir)/%.xml
10 $(dir)/%-server-protocol.h: $(dir)/%.xml
11 	$(call quiet,GEN,$(WAYLAND_SCANNER)) server-header < $< > $@
12 
13+install-protocol: | $(DESTDIR)$(DATADIR)/swc
14+	install -m0644 protocol/swc.xml "$(DESTDIR)$(DATADIR)/swc"
15+
16 include common.mk
17 
+40, -0
 1@@ -0,0 +1,40 @@
 2+<?xml version="1.0" encoding="UTF-8"?>
 3+<protocol name="swc">
 4+    <interface name="swc_panel_manager" version="1">
 5+        <request name="create_panel">
 6+            <arg name="id" type="new_id" interface="swc_panel" />
 7+            <arg name="surface" type="object" interface="wl_surface" />
 8+        </request>
 9+    </interface>
10+
11+    <interface name="swc_panel" version="1">
12+        <enum name="edge">
13+            <entry name="top" value="0" />
14+            <entry name="bottom" value="1" />
15+            <entry name="left" value="2" />
16+            <entry name="right" value="3" />
17+        </enum>
18+
19+        <request name="dock">
20+            <arg name="edge" type="uint" />
21+            <arg name="output" type="object" interface="wl_output"
22+                 allow-null="true" />
23+            <arg name="focus" type="uint" />
24+        </request>
25+
26+        <request name="set_offset">
27+            <arg name="offset" type="uint" />
28+        </request>
29+
30+        <request name="set_strut">
31+            <arg name="size" type="uint" />
32+            <arg name="begin" type="uint" />
33+            <arg name="end" type="uint" />
34+        </request>
35+
36+        <event name="docked">
37+            <arg name="length" type="uint" />
38+        </event>
39+    </interface>
40+</protocol>
41+