commit 2011cc7
Michael Forney
·
2018-11-03 02:02:57 +0000 UTC
parent 390414c
Remove xwayland support I'm not using any X applications under swc anymore, so this code is likely to become broken without anyone using it.
10 files changed,
+0,
-974
M
Makefile
+0,
-8
1@@ -35,14 +35,6 @@ PACKAGES := \
2 wld \
3 xkbcommon
4
5-ifeq ($(ENABLE_XWAYLAND),1)
6-PACKAGES += \
7- xcb \
8- xcb-composite \
9- xcb-ewmh \
10- xcb-icccm
11-endif
12-
13 ifeq ($(ENABLE_LIBUDEV),1)
14 PACKAGES += libudev
15 endif
+0,
-4
1@@ -24,10 +24,6 @@ Dependencies
2 For input hotplugging, the following is also required:
3 * libudev
4
5-For XWayland support, the following are also required:
6-* libxcb
7-* xcb-util-wm
8-
9 Implementing a window manager using swc
10 ---------------------------------------
11 You must implement two callback functions, `new_window` and `new_screen`, which
+0,
-1
1@@ -17,5 +17,4 @@ ENABLE_DEBUG = 1
2 ENABLE_STATIC = 1
3 ENABLE_SHARED = 1
4 ENABLE_LIBUDEV = 1
5-ENABLE_XWAYLAND = 1
6
+0,
-4
1@@ -45,10 +45,6 @@ struct swc {
2 struct swc_compositor *const compositor;
3 struct swc_shm *const shm;
4 struct swc_drm *const drm;
5-
6-#ifdef ENABLE_XWAYLAND
7- const struct swc_xserver *const xserver;
8-#endif
9 };
10
11 extern struct swc swc;
+0,
-9
1@@ -62,15 +62,6 @@ $(dir)_CFLAGS += -DENABLE_LIBUDEV
2 $(dir)_PACKAGES += libudev
3 endif
4
5-ifeq ($(ENABLE_XWAYLAND),1)
6-$(dir)_CFLAGS += -DENABLE_XWAYLAND
7-$(dir)_PACKAGES += xcb xcb-composite xcb-ewmh xcb-icccm
8-
9-SWC_SOURCES += \
10- libswc/xserver.c \
11- libswc/xwm.c
12-endif
13-
14 SWC_STATIC_OBJECTS = $(SWC_SOURCES:%.c=%.o)
15 SWC_SHARED_OBJECTS = $(SWC_SOURCES:%.c=%.lo)
16
+0,
-23
1@@ -40,9 +40,6 @@
2 #include "util.h"
3 #include "window.h"
4 #include "xdg_shell.h"
5-#ifdef ENABLE_XWAYLAND
6-# include "xserver.h"
7-#endif
8
9 extern struct swc_launch swc_launch;
10 extern const struct swc_seat swc_seat;
11@@ -50,9 +47,6 @@ extern const struct swc_bindings swc_bindings;
12 extern struct swc_compositor swc_compositor;
13 extern struct swc_drm swc_drm;
14 extern struct swc_shm swc_shm;
15-#ifdef ENABLE_XWAYLAND
16-extern struct swc_xserver swc_xserver;
17-#endif
18
19 extern struct pointer_handler screens_pointer_handler;
20
21@@ -62,9 +56,6 @@ struct swc swc = {
22 .compositor = &swc_compositor,
23 .drm = &swc_drm,
24 .shm = &swc_shm,
25-#ifdef ENABLE_XWAYLAND
26- .xserver = &swc_xserver,
27-#endif
28 };
29
30 static void
31@@ -179,21 +170,10 @@ swc_initialize(struct wl_display *display, struct wl_event_loop *event_loop, con
32 goto error11;
33 }
34
35-#ifdef ENABLE_XWAYLAND
36- if (!xserver_initialize()) {
37- ERROR("Could not initialize xwayland\n");
38- goto error12;
39- }
40-#endif
41-
42 setup_compositor();
43
44 return true;
45
46-#ifdef ENABLE_XWAYLAND
47-error12:
48- panel_manager_finalize();
49-#endif
50 error11:
51 xdg_shell_finalize();
52 error10:
53@@ -223,9 +203,6 @@ error0:
54 EXPORT void
55 swc_finalize(void)
56 {
57-#ifdef ENABLE_XWAYLAND
58- xserver_finalize();
59-#endif
60 panel_manager_finalize();
61 shell_finalize();
62 seat_finalize();
+0,
-319
1@@ -1,319 +0,0 @@
2-/* swc: libswc/xserver.c
3- *
4- * Copyright (c) 2013 Michael Forney
5- *
6- * Based in part upon xwayland/launcher.c from weston, which is
7- *
8- * Copyright © 2011 Intel Corporation
9- *
10- * Permission is hereby granted, free of charge, to any person obtaining a copy
11- * of this software and associated documentation files (the "Software"), to deal
12- * in the Software without restriction, including without limitation the rights
13- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14- * copies of the Software, and to permit persons to whom the Software is
15- * furnished to do so, subject to the following conditions:
16- *
17- * The above copyright notice and this permission notice shall be included in
18- * all copies or substantial portions of the Software.
19- *
20- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26- * SOFTWARE.
27- */
28-
29-#include "xserver.h"
30-#include "internal.h"
31-#include "util.h"
32-#include "xwm.h"
33-
34-#include <signal.h>
35-#include <stdlib.h>
36-#include <stdio.h>
37-#include <unistd.h>
38-#include <fcntl.h>
39-#include <errno.h>
40-#include <sys/stat.h>
41-#include <sys/socket.h>
42-#include <sys/un.h>
43-#include <wayland-server.h>
44-
45-#define LOCK_FMT "/tmp/.X%d-lock"
46-#define SOCKET_DIR "/tmp/.X11-unix"
47-#define SOCKET_FMT SOCKET_DIR "/X%d"
48-
49-static struct {
50- struct wl_resource *resource;
51- struct wl_event_source *usr1_source;
52- int display;
53- char display_name[16];
54- int abstract_fd, unix_fd, wm_fd;
55- bool xwm_initialized;
56-} xserver;
57-
58-struct swc_xserver swc_xserver;
59-
60-static int
61-open_socket(struct sockaddr_un *addr)
62-{
63- int fd;
64-
65- if ((fd = socket(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0)) < 0)
66- goto error0;
67-
68- /* Unlink the socket location in case it was being used by a process which
69- * left around a stale lockfile. */
70- unlink(addr->sun_path);
71-
72- if (bind(fd, (struct sockaddr *)addr, sizeof(*addr)) < 0)
73- goto error1;
74-
75- if (listen(fd, 1) < 0)
76- goto error2;
77-
78- return fd;
79-
80-error2:
81- if (addr->sun_path[0])
82- unlink(addr->sun_path);
83-error1:
84- close(fd);
85-error0:
86- return -1;
87-}
88-
89-static bool
90-open_display(void)
91-{
92- char lock_name[64], pid[12];
93- int lock_fd;
94- struct sockaddr_un addr = {.sun_family = AF_LOCAL};
95-
96- xserver.display = 0;
97-
98- /* Create X lockfile and server sockets */
99- goto begin;
100-
101-retry2:
102- close(xserver.abstract_fd);
103-retry1:
104- unlink(lock_name);
105-retry0:
106- if (++xserver.display > 32) {
107- ERROR("No open display in first 32\n");
108- return false;
109- }
110-
111-begin:
112- snprintf(lock_name, sizeof(lock_name), LOCK_FMT, xserver.display);
113- lock_fd = open(lock_name, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, 0444);
114-
115- if (lock_fd == -1) {
116- char *end;
117- pid_t owner;
118-
119- /* Check if the owning process is still alive. */
120- if ((lock_fd = open(lock_name, O_RDONLY)) == -1)
121- goto retry0;
122-
123- if (read(lock_fd, pid, sizeof(pid) - 1) != sizeof(pid) - 1)
124- goto retry0;
125-
126- owner = strtol(pid, &end, 10);
127-
128- if (end != pid + 10)
129- goto retry0;
130-
131- if (kill(owner, 0) == 0 || errno != ESRCH)
132- goto retry0;
133-
134- if (unlink(lock_name) != 0)
135- goto retry0;
136-
137- goto begin;
138- }
139-
140- snprintf(pid, sizeof(pid), "%10d\n", getpid());
141- if (write(lock_fd, pid, sizeof(pid) - 1) != sizeof(pid) - 1) {
142- ERROR("Failed to write PID file\n");
143- unlink(lock_name);
144- close(lock_fd);
145- return false;
146- }
147-
148- close(lock_fd);
149-
150- /* Bind to abstract socket */
151- addr.sun_path[0] = '\0';
152- snprintf(addr.sun_path + 1, sizeof(addr.sun_path) - 1, SOCKET_FMT, xserver.display);
153- if ((xserver.abstract_fd = open_socket(&addr)) < 0)
154- goto retry1;
155-
156- /* Bind to unix socket */
157- mkdir(SOCKET_DIR, 0777);
158- snprintf(addr.sun_path, sizeof(addr.sun_path), SOCKET_FMT, xserver.display);
159- if ((xserver.unix_fd = open_socket(&addr)) < 0)
160- goto retry2;
161-
162- snprintf(xserver.display_name, sizeof(xserver.display_name), ":%d", xserver.display);
163- setenv("DISPLAY", xserver.display_name, true);
164-
165- return true;
166-}
167-
168-static void
169-close_display(void)
170-{
171- char path[64];
172-
173- close(xserver.abstract_fd);
174- close(xserver.unix_fd);
175-
176- snprintf(path, sizeof(path), SOCKET_FMT, xserver.display);
177- unlink(path);
178- snprintf(path, sizeof(path), LOCK_FMT, xserver.display);
179- unlink(path);
180-
181- unsetenv("DISPLAY");
182-}
183-
184-static int
185-handle_usr1(int signal_number, void *data)
186-{
187- if (xwm_initialize(xserver.wm_fd)) {
188- xserver.xwm_initialized = true;
189- } else {
190- ERROR("Failed to initialize X window manager\n");
191- /* XXX: How do we handle this case? */
192- }
193-
194- wl_event_source_remove(xserver.usr1_source);
195-
196- return 0;
197-}
198-
199-static void
200-handle_client_destroy(struct wl_listener *listener, void *data) {
201- swc_xserver.client = NULL;
202-}
203-
204-static struct wl_listener client_destroy_listener = {
205- .notify = handle_client_destroy,
206-};
207-
208-bool
209-xserver_initialize(void)
210-{
211- int wl[2], wm[2];
212-
213- /* Open an X display */
214- if (!open_display()) {
215- ERROR("Failed to get X lockfile and sockets\n");
216- goto error0;
217- }
218-
219- xserver.usr1_source = wl_event_loop_add_signal(swc.event_loop, SIGUSR1, &handle_usr1, NULL);
220-
221- if (!xserver.usr1_source) {
222- ERROR("Failed to create SIGUSR1 event source\n");
223- goto error1;
224- }
225-
226- /* Open a socket for the Wayland connection from Xwayland. */
227- if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, wl) != 0) {
228- ERROR("Failed to create socketpair: %s\n", strerror(errno));
229- goto error2;
230- }
231-
232- /* Open a socket for the X connection to Xwayland. */
233- if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, wm) != 0) {
234- ERROR("Failed to create socketpair: %s\n", strerror(errno));
235- goto error3;
236- }
237-
238- if (!(swc_xserver.client = wl_client_create(swc.display, wl[0])))
239- goto error4;
240-
241- wl_client_add_destroy_listener(swc_xserver.client, &client_destroy_listener);
242- xserver.wm_fd = wm[0];
243-
244- /* Start the X server */
245- switch (fork()) {
246- case 0: {
247- int fds[] = { wl[1], wm[1], xserver.abstract_fd, xserver.unix_fd };
248- char strings[ARRAY_LENGTH(fds)][16];
249- unsigned index;
250- struct sigaction action = {.sa_handler = SIG_IGN };
251-
252- /* Unset the FD_CLOEXEC flag on the FDs that will get passed to Xwayland. */
253- for (index = 0; index < ARRAY_LENGTH(fds); ++index) {
254- if (fcntl(fds[index], F_SETFD, 0) != 0) {
255- ERROR("fcntl() failed: %s\n", strerror(errno));
256- goto fail;
257- }
258-
259- if (snprintf(strings[index], sizeof(strings[index]), "%d", fds[index]) >= sizeof(strings[index])) {
260- ERROR("FD is too large\n");
261- goto fail;
262- }
263- }
264-
265- /* Ignore the USR1 signal so that Xwayland will send a USR1 signal to the
266- * parent process (us) after it finishes initializing. See Xserver(1) for
267- * more details. */
268- if (sigaction(SIGUSR1, &action, NULL) != 0) {
269- ERROR("Failed to set SIGUSR1 handler to SIG_IGN: %s\n", strerror(errno));
270- goto fail;
271- }
272-
273- setenv("WAYLAND_SOCKET", strings[0], true);
274- execlp("Xwayland", "Xwayland",
275- xserver.display_name,
276- "-rootless",
277- "-terminate",
278- "-listen", strings[2],
279- "-listen", strings[3],
280- "-wm", strings[1],
281- NULL);
282-
283- fail:
284- exit(EXIT_FAILURE);
285- }
286- case -1:
287- ERROR("fork() failed when trying to start X server: %s\n", strerror(errno));
288- goto error5;
289- }
290-
291- close(wl[1]);
292- close(wm[1]);
293-
294- return true;
295-
296-error5:
297- wl_client_destroy(swc_xserver.client);
298-error4:
299- close(wm[1]);
300- close(wm[0]);
301-error3:
302- close(wl[1]);
303- close(wl[0]);
304-error2:
305- wl_event_source_remove(xserver.usr1_source);
306-error1:
307- close_display();
308-error0:
309- return false;
310-}
311-
312-void
313-xserver_finalize(void)
314-{
315- if (xserver.xwm_initialized)
316- xwm_finalize();
317- if (swc_xserver.client)
318- wl_client_destroy(swc_xserver.client);
319- close_display();
320-}
+0,
-36
1@@ -1,36 +0,0 @@
2-/* swc: libswc/xserver.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_XSERVER_H
26-#define SWC_XSERVER_H
27-
28-#include <stdbool.h>
29-
30-struct swc_xserver {
31- struct wl_client *client;
32-};
33-
34-bool xserver_initialize(void);
35-void xserver_finalize(void);
36-
37-#endif
+0,
-538
1@@ -1,538 +0,0 @@
2-/* swc: libswc/xwm.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 "xwm.h"
26-#include "compositor.h"
27-#include "internal.h"
28-#include "surface.h"
29-#include "swc.h"
30-#include "util.h"
31-#include "view.h"
32-#include "window.h"
33-#include "xserver.h"
34-
35-#include <stdio.h>
36-#include <xcb/composite.h>
37-#include <xcb/xcb_ewmh.h>
38-#include <xcb/xcb_icccm.h>
39-
40-struct xwl_window {
41- xcb_window_t id;
42- uint32_t surface_id;
43- bool override_redirect, supports_delete;
44- struct wl_list link;
45-
46- /* Only used for paired windows. */
47- struct {
48- struct window window;
49- struct wl_listener surface_destroy_listener;
50- };
51-};
52-
53-enum atom {
54- ATOM_WL_SURFACE_ID,
55- ATOM_WM_DELETE_WINDOW,
56- ATOM_WM_PROTOCOLS,
57- ATOM_WM_S0,
58-};
59-
60-static struct {
61- xcb_connection_t *connection;
62- xcb_ewmh_connection_t ewmh;
63- xcb_screen_t *screen;
64- xcb_window_t window;
65- struct xwl_window *focus;
66- struct wl_event_source *source;
67- struct wl_list windows, unpaired_windows;
68- union {
69- const char *name;
70- xcb_intern_atom_cookie_t cookie;
71- xcb_atom_t value;
72- } atoms[4];
73-} xwm = {
74- .atoms = {
75- [ATOM_WL_SURFACE_ID] = "WL_SURFACE_ID",
76- [ATOM_WM_DELETE_WINDOW] = "WM_DELETE_WINDOW",
77- [ATOM_WM_PROTOCOLS] = "WM_PROTOCOLS",
78- [ATOM_WM_S0] = "WM_S0",
79- }
80-};
81-
82-static void
83-update_name(struct xwl_window *xwl_window)
84-{
85- xcb_get_property_cookie_t wm_name_cookie;
86- xcb_ewmh_get_utf8_strings_reply_t wm_name_reply;
87-
88- wm_name_cookie = xcb_ewmh_get_wm_name(&xwm.ewmh, xwl_window->id);
89-
90- if (xcb_ewmh_get_wm_name_reply(&xwm.ewmh, wm_name_cookie, &wm_name_reply, NULL)) {
91- window_set_title(&xwl_window->window, wm_name_reply.strings, wm_name_reply.strings_len);
92- xcb_ewmh_get_utf8_strings_reply_wipe(&wm_name_reply);
93- } else {
94- window_set_title(&xwl_window->window, NULL, 0);
95- }
96-}
97-
98-static void
99-update_protocols(struct xwl_window *xwl_window)
100-{
101- xcb_get_property_cookie_t cookie;
102- xcb_icccm_get_wm_protocols_reply_t reply;
103- unsigned index;
104-
105- cookie = xcb_icccm_get_wm_protocols(xwm.connection, xwl_window->id, xwm.atoms[ATOM_WM_PROTOCOLS].value);
106- xwl_window->supports_delete = true;
107-
108- if (!xcb_icccm_get_wm_protocols_reply(xwm.connection, cookie, &reply, NULL))
109- return;
110-
111- for (index = 0; index < reply.atoms_len; ++index) {
112- if (reply.atoms[index] == xwm.atoms[ATOM_WM_DELETE_WINDOW].value)
113- xwl_window->supports_delete = true;
114- }
115-
116- xcb_icccm_get_wm_protocols_reply_wipe(&reply);
117-}
118-
119-static struct xwl_window *
120-find_window(struct wl_list *list, xcb_window_t id)
121-{
122- struct xwl_window *window;
123-
124- wl_list_for_each (window, list, link) {
125- if (window->id == id)
126- return window;
127- }
128-
129- return NULL;
130-}
131-
132-static struct xwl_window *
133-find_window_by_surface_id(struct wl_list *list, uint32_t id)
134-{
135- struct xwl_window *window;
136-
137- wl_list_for_each (window, list, link) {
138- if (window->surface_id == id)
139- return window;
140- }
141-
142- return NULL;
143-}
144-
145-static void
146-move(struct window *window, int32_t x, int32_t y)
147-{
148- uint32_t mask, values[2];
149- struct xwl_window *xwl_window = wl_container_of(window, xwl_window, window);
150-
151- mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y;
152- values[0] = x;
153- values[1] = y;
154-
155- xcb_configure_window(xwm.connection, xwl_window->id, mask, values);
156- xcb_flush(xwm.connection);
157-}
158-
159-static void
160-configure(struct window *window, uint32_t width, uint32_t height)
161-{
162- uint32_t mask, values[2];
163- struct xwl_window *xwl_window = wl_container_of(window, xwl_window, window);
164-
165- mask = XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
166- values[0] = width;
167- values[1] = height;
168-
169- window->configure.acknowledged = true;
170- xcb_configure_window(xwm.connection, xwl_window->id, mask, values);
171- xcb_flush(xwm.connection);
172-}
173-
174-static void
175-focus(struct window *window)
176-{
177- struct xwl_window *xwl_window = wl_container_of(window, xwl_window, window);
178-
179- xcb_set_input_focus(xwm.connection, XCB_INPUT_FOCUS_NONE, xwl_window->id, XCB_CURRENT_TIME);
180- xcb_flush(xwm.connection);
181- xwm.focus = xwl_window;
182-}
183-
184-static void
185-unfocus(struct window *window)
186-{
187- struct xwl_window *xwl_window = wl_container_of(window, xwl_window, window);
188-
189- /* If the window we are unfocusing is the latest xwl_window to be focused, we
190- * know we have transitioned to some other window type, so the X11 focus can
191- * be set to XCB_NONE. Otherwise, we have transitioned to another X11 window,
192- * and the X11 focus has already been updated. */
193- if (xwl_window == xwm.focus) {
194- xcb_set_input_focus(xwm.connection, XCB_INPUT_FOCUS_NONE, XCB_NONE, XCB_CURRENT_TIME);
195- xcb_flush(xwm.connection);
196- }
197-}
198-
199-static void
200-close(struct window *window)
201-{
202- struct xwl_window *xwl_window = wl_container_of(window, xwl_window, window);
203-
204- if (xwl_window->supports_delete) {
205- xcb_client_message_event_t event = {
206- .response_type = XCB_CLIENT_MESSAGE,
207- .format = 32,
208- .window = xwl_window->id,
209- .type = xwm.atoms[ATOM_WM_PROTOCOLS].value,
210- .data.data32 = {
211- xwm.atoms[ATOM_WM_DELETE_WINDOW].value,
212- XCB_CURRENT_TIME,
213- },
214- };
215-
216- xcb_send_event(xwm.connection, false, xwl_window->id, XCB_EVENT_MASK_NO_EVENT, (const char *)&event);
217- } else {
218- xcb_kill_client(xwm.connection, xwl_window->id);
219- }
220-
221- xcb_flush(xwm.connection);
222-}
223-
224-static const struct window_impl xwl_window_handler = {
225- .move = move,
226- .configure = configure,
227- .focus = focus,
228- .unfocus = unfocus,
229- .close = close,
230-};
231-
232-static void
233-handle_surface_destroy(struct wl_listener *listener, void *data)
234-{
235- struct xwl_window *xwl_window = wl_container_of(listener, xwl_window, surface_destroy_listener);
236-
237- if (xwm.focus == xwl_window)
238- xwm.focus = NULL;
239-
240- window_finalize(&xwl_window->window);
241- wl_list_remove(&xwl_window->link);
242- wl_list_insert(&xwm.unpaired_windows, &xwl_window->link);
243- xwl_window->surface_id = 0;
244-}
245-
246-static bool
247-manage_window(struct xwl_window *xwl_window)
248-{
249- struct wl_resource *resource;
250- struct surface *surface;
251- xcb_get_geometry_cookie_t geometry_cookie;
252- xcb_get_geometry_reply_t *geometry_reply;
253-
254- resource = wl_client_get_object(swc.xserver->client, xwl_window->surface_id);
255-
256- if (!resource)
257- return false;
258-
259- surface = wl_resource_get_user_data(resource);
260- geometry_cookie = xcb_get_geometry(xwm.connection, xwl_window->id);
261-
262- window_initialize(&xwl_window->window, &xwl_window_handler, surface);
263- xwl_window->surface_destroy_listener.notify = &handle_surface_destroy;
264- wl_resource_add_destroy_listener(surface->resource, &xwl_window->surface_destroy_listener);
265-
266- if ((geometry_reply = xcb_get_geometry_reply(xwm.connection, geometry_cookie, NULL))) {
267- view_move(surface->view, geometry_reply->x, geometry_reply->y);
268- free(geometry_reply);
269- }
270-
271- if (xwl_window->override_redirect) {
272- compositor_view_show(xwl_window->window.view);
273- } else {
274- uint32_t mask, values[1];
275-
276- mask = XCB_CW_EVENT_MASK;
277- values[0] = XCB_EVENT_MASK_PROPERTY_CHANGE;
278- xcb_change_window_attributes(xwm.connection, xwl_window->id, mask, values);
279- mask = XCB_CONFIG_WINDOW_BORDER_WIDTH;
280- values[0] = 0;
281- xcb_configure_window(xwm.connection, xwl_window->id, mask, values);
282- update_name(xwl_window);
283- update_protocols(xwl_window);
284- window_manage(&xwl_window->window);
285- }
286-
287- wl_list_remove(&xwl_window->link);
288- wl_list_insert(&xwm.windows, &xwl_window->link);
289-
290- return true;
291-}
292-
293-static void
294-handle_new_surface(struct wl_listener *listener, void *data)
295-{
296- struct surface *surface = data;
297- struct xwl_window *window;
298-
299- window = find_window_by_surface_id(&xwm.unpaired_windows, wl_resource_get_id(surface->resource));
300-
301- if (!window)
302- return;
303-
304- manage_window(window);
305-}
306-
307-static struct wl_listener new_surface_listener = {
308- .notify = &handle_new_surface
309-};
310-
311-/* X event handlers */
312-static void
313-create_notify(xcb_create_notify_event_t *event)
314-{
315- struct xwl_window *xwl_window;
316-
317- if (!(xwl_window = malloc(sizeof *xwl_window)))
318- return;
319-
320- xwl_window->id = event->window;
321- xwl_window->surface_id = 0;
322- xwl_window->override_redirect = event->override_redirect;
323- wl_list_insert(&xwm.unpaired_windows, &xwl_window->link);
324-}
325-
326-static void
327-destroy_notify(xcb_destroy_notify_event_t *event)
328-{
329- struct xwl_window *xwl_window;
330-
331- if ((xwl_window = find_window(&xwm.windows, event->window))) {
332- wl_list_remove(&xwl_window->surface_destroy_listener.link);
333- window_finalize(&xwl_window->window);
334- } else if (!(xwl_window = find_window(&xwm.unpaired_windows, event->window))) {
335- return;
336- }
337-
338- wl_list_remove(&xwl_window->link);
339- free(xwl_window);
340-}
341-
342-static void
343-map_request(xcb_map_request_event_t *event)
344-{
345- xcb_map_window(xwm.connection, event->window);
346-}
347-
348-static void
349-configure_request(xcb_configure_request_event_t *event)
350-{
351-}
352-
353-static void
354-property_notify(xcb_property_notify_event_t *event)
355-{
356- struct xwl_window *xwl_window;
357-
358- if (!(xwl_window = find_window(&xwm.windows, event->window)))
359- return;
360-
361- if (event->atom == xwm.ewmh._NET_WM_NAME && event->state == XCB_PROPERTY_NEW_VALUE)
362- update_name(xwl_window);
363- else if (event->atom == xwm.atoms[ATOM_WM_PROTOCOLS].value)
364- update_protocols(xwl_window);
365-}
366-
367-static void
368-client_message(xcb_client_message_event_t *event)
369-{
370- if (event->type == xwm.atoms[ATOM_WL_SURFACE_ID].value) {
371- struct xwl_window *xwl_window;
372-
373- if (!(xwl_window = find_window(&xwm.unpaired_windows, event->window)))
374- return;
375-
376- xwl_window->surface_id = event->data.data32[0];
377- manage_window(xwl_window);
378- }
379-}
380-
381-static int
382-connection_data(int fd, uint32_t mask, void *data)
383-{
384- xcb_generic_event_t *event;
385- uint32_t count = 0;
386-
387- while ((event = xcb_poll_for_event(xwm.connection))) {
388- switch (event->response_type & ~0x80) {
389- case XCB_CREATE_NOTIFY:
390- create_notify((xcb_create_notify_event_t *)event);
391- break;
392- case XCB_DESTROY_NOTIFY:
393- destroy_notify((xcb_destroy_notify_event_t *)event);
394- break;
395- case XCB_MAP_REQUEST:
396- map_request((xcb_map_request_event_t *)event);
397- break;
398- case XCB_CONFIGURE_REQUEST:
399- configure_request((xcb_configure_request_event_t *)event);
400- break;
401- case XCB_PROPERTY_NOTIFY:
402- property_notify((xcb_property_notify_event_t *)event);
403- break;
404- case XCB_CLIENT_MESSAGE:
405- client_message((xcb_client_message_event_t *)event);
406- break;
407- }
408-
409- free(event);
410- ++count;
411- }
412-
413- xcb_flush(xwm.connection);
414-
415- return count;
416-}
417-
418-bool
419-xwm_initialize(int fd)
420-{
421- const xcb_setup_t *setup;
422- xcb_screen_iterator_t screen_iterator;
423- uint32_t mask;
424- uint32_t values[1];
425- xcb_void_cookie_t change_attributes_cookie, redirect_subwindows_cookie;
426- xcb_generic_error_t *error;
427- xcb_intern_atom_cookie_t *ewmh_cookies;
428- xcb_intern_atom_reply_t *atom_reply;
429- unsigned index;
430- const char *name;
431- const xcb_query_extension_reply_t *composite_extension;
432-
433- xwm.connection = xcb_connect_to_fd(fd, NULL);
434-
435- if (xcb_connection_has_error(xwm.connection)) {
436- ERROR("xwm: Could not connect to X server\n");
437- goto error0;
438- }
439-
440- xcb_prefetch_extension_data(xwm.connection, &xcb_composite_id);
441- ewmh_cookies = xcb_ewmh_init_atoms(xwm.connection, &xwm.ewmh);
442-
443- if (!ewmh_cookies) {
444- ERROR("xwm: Failed to initialize EWMH atoms\n");
445- goto error1;
446- }
447-
448- for (index = 0; index < ARRAY_LENGTH(xwm.atoms); ++index) {
449- name = xwm.atoms[index].name;
450- xwm.atoms[index].cookie = xcb_intern_atom(xwm.connection, 0, strlen(name), name);
451- }
452-
453- setup = xcb_get_setup(xwm.connection);
454- screen_iterator = xcb_setup_roots_iterator(setup);
455- xwm.screen = screen_iterator.data;
456-
457- /* Try to select for substructure redirect. */
458- mask = XCB_CW_EVENT_MASK;
459- values[0] = XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT;
460- change_attributes_cookie = xcb_change_window_attributes(xwm.connection, xwm.screen->root, mask, values);
461-
462- xwm.source = wl_event_loop_add_fd(swc.event_loop, fd, WL_EVENT_READABLE, &connection_data, NULL);
463- wl_list_init(&xwm.windows);
464- wl_list_init(&xwm.unpaired_windows);
465-
466- if (!xwm.source) {
467- ERROR("xwm: Failed to create X connection event source\n");
468- goto error2;
469- }
470-
471- composite_extension = xcb_get_extension_data(xwm.connection, &xcb_composite_id);
472-
473- if (!composite_extension->present) {
474- ERROR("xwm: X server does not have composite extension\n");
475- goto error3;
476- }
477-
478- redirect_subwindows_cookie = xcb_composite_redirect_subwindows_checked(xwm.connection, xwm.screen->root, XCB_COMPOSITE_REDIRECT_MANUAL);
479-
480- if ((error = xcb_request_check(xwm.connection, change_attributes_cookie))) {
481- ERROR("xwm: Another window manager is running\n");
482- free(error);
483- goto error3;
484- }
485-
486- if ((error = xcb_request_check(xwm.connection, redirect_subwindows_cookie))) {
487- ERROR("xwm: Could not redirect subwindows of root for compositing\n");
488- free(error);
489- goto error3;
490- }
491-
492- xwm.window = xcb_generate_id(xwm.connection);
493- xcb_create_window(xwm.connection, 0, xwm.window, xwm.screen->root,
494- 0, 0, 1, 1, 0, XCB_WINDOW_CLASS_INPUT_ONLY,
495- XCB_COPY_FROM_PARENT, 0, NULL);
496-
497- xcb_ewmh_init_atoms_replies(&xwm.ewmh, ewmh_cookies, &error);
498-
499- if (error) {
500- ERROR("xwm: Failed to get EWMH atom replies: %u\n", error->error_code);
501- goto error3;
502- }
503-
504- for (index = 0; index < ARRAY_LENGTH(xwm.atoms); ++index) {
505- atom_reply = xcb_intern_atom_reply(xwm.connection, xwm.atoms[index].cookie, &error);
506-
507- if (error) {
508- ERROR("xwm: Failed to get atom reply: %u\n", error->error_code);
509- return false;
510- }
511-
512- xwm.atoms[index].value = atom_reply->atom;
513- free(atom_reply);
514- }
515-
516- xcb_set_selection_owner(xwm.connection, xwm.window, xwm.atoms[ATOM_WM_S0].value, XCB_CURRENT_TIME);
517- xcb_flush(xwm.connection);
518-
519- wl_signal_add(&swc.compositor->signal.new_surface, &new_surface_listener);
520-
521- return true;
522-
523-error3:
524- wl_event_source_remove(xwm.source);
525-error2:
526- xcb_ewmh_connection_wipe(&xwm.ewmh);
527-error1:
528- xcb_disconnect(xwm.connection);
529-error0:
530- return false;
531-}
532-
533-void
534-xwm_finalize(void)
535-{
536- wl_event_source_remove(xwm.source);
537- xcb_ewmh_connection_wipe(&xwm.ewmh);
538- xcb_disconnect(xwm.connection);
539-}
+0,
-32
1@@ -1,32 +0,0 @@
2-/* swc: libswc/xwm.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_XWM_H
26-#define SWC_XWM_H
27-
28-#include <stdbool.h>
29-
30-bool xwm_initialize(int fd);
31-void xwm_finalize(void);
32-
33-#endif