swc

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

commit 2011cc741cc12b50f6d85529a898b378ae78bd8d
parent 390414c4377966c1ac051bfb049d7c24c1a99eff
Author: Michael Forney <mforney@mforney.org>
Date:   Fri,  2 Nov 2018 19:02:57 -0700

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.

Diffstat:
MMakefile | 8--------
MREADME.md | 4----
Mconfig.mk | 1-
Mlibswc/internal.h | 4----
Mlibswc/local.mk | 9---------
Mlibswc/swc.c | 23-----------------------
Dlibswc/xserver.c | 319-------------------------------------------------------------------------------
Dlibswc/xserver.h | 36------------------------------------
Dlibswc/xwm.c | 538-------------------------------------------------------------------------------
Dlibswc/xwm.h | 32--------------------------------
10 files changed, 0 insertions(+), 974 deletions(-)

diff --git a/Makefile b/Makefile @@ -35,14 +35,6 @@ PACKAGES := \ wld \ xkbcommon -ifeq ($(ENABLE_XWAYLAND),1) -PACKAGES += \ - xcb \ - xcb-composite \ - xcb-ewmh \ - xcb-icccm -endif - ifeq ($(ENABLE_LIBUDEV),1) PACKAGES += libudev endif diff --git a/README.md b/README.md @@ -24,10 +24,6 @@ Dependencies For input hotplugging, the following is also required: * libudev -For XWayland support, the following are also required: -* libxcb -* xcb-util-wm - Implementing a window manager using swc --------------------------------------- You must implement two callback functions, `new_window` and `new_screen`, which diff --git a/config.mk b/config.mk @@ -17,5 +17,4 @@ ENABLE_DEBUG = 1 ENABLE_STATIC = 1 ENABLE_SHARED = 1 ENABLE_LIBUDEV = 1 -ENABLE_XWAYLAND = 1 diff --git a/libswc/internal.h b/libswc/internal.h @@ -45,10 +45,6 @@ struct swc { struct swc_compositor *const compositor; struct swc_shm *const shm; struct swc_drm *const drm; - -#ifdef ENABLE_XWAYLAND - const struct swc_xserver *const xserver; -#endif }; extern struct swc swc; diff --git a/libswc/local.mk b/libswc/local.mk @@ -62,15 +62,6 @@ $(dir)_CFLAGS += -DENABLE_LIBUDEV $(dir)_PACKAGES += libudev endif -ifeq ($(ENABLE_XWAYLAND),1) -$(dir)_CFLAGS += -DENABLE_XWAYLAND -$(dir)_PACKAGES += xcb xcb-composite xcb-ewmh xcb-icccm - -SWC_SOURCES += \ - libswc/xserver.c \ - libswc/xwm.c -endif - SWC_STATIC_OBJECTS = $(SWC_SOURCES:%.c=%.o) SWC_SHARED_OBJECTS = $(SWC_SOURCES:%.c=%.lo) diff --git a/libswc/swc.c b/libswc/swc.c @@ -40,9 +40,6 @@ #include "util.h" #include "window.h" #include "xdg_shell.h" -#ifdef ENABLE_XWAYLAND -# include "xserver.h" -#endif extern struct swc_launch swc_launch; extern const struct swc_seat swc_seat; @@ -50,9 +47,6 @@ extern const struct swc_bindings swc_bindings; extern struct swc_compositor swc_compositor; extern struct swc_drm swc_drm; extern struct swc_shm swc_shm; -#ifdef ENABLE_XWAYLAND -extern struct swc_xserver swc_xserver; -#endif extern struct pointer_handler screens_pointer_handler; @@ -62,9 +56,6 @@ struct swc swc = { .compositor = &swc_compositor, .drm = &swc_drm, .shm = &swc_shm, -#ifdef ENABLE_XWAYLAND - .xserver = &swc_xserver, -#endif }; static void @@ -179,21 +170,10 @@ swc_initialize(struct wl_display *display, struct wl_event_loop *event_loop, con goto error11; } -#ifdef ENABLE_XWAYLAND - if (!xserver_initialize()) { - ERROR("Could not initialize xwayland\n"); - goto error12; - } -#endif - setup_compositor(); return true; -#ifdef ENABLE_XWAYLAND -error12: - panel_manager_finalize(); -#endif error11: xdg_shell_finalize(); error10: @@ -223,9 +203,6 @@ error0: EXPORT void swc_finalize(void) { -#ifdef ENABLE_XWAYLAND - xserver_finalize(); -#endif panel_manager_finalize(); shell_finalize(); seat_finalize(); diff --git a/libswc/xserver.c b/libswc/xserver.c @@ -1,319 +0,0 @@ -/* swc: libswc/xserver.c - * - * Copyright (c) 2013 Michael Forney - * - * Based in part upon xwayland/launcher.c from weston, which is - * - * Copyright © 2011 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "xserver.h" -#include "internal.h" -#include "util.h" -#include "xwm.h" - -#include <signal.h> -#include <stdlib.h> -#include <stdio.h> -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> -#include <sys/stat.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <wayland-server.h> - -#define LOCK_FMT "/tmp/.X%d-lock" -#define SOCKET_DIR "/tmp/.X11-unix" -#define SOCKET_FMT SOCKET_DIR "/X%d" - -static struct { - struct wl_resource *resource; - struct wl_event_source *usr1_source; - int display; - char display_name[16]; - int abstract_fd, unix_fd, wm_fd; - bool xwm_initialized; -} xserver; - -struct swc_xserver swc_xserver; - -static int -open_socket(struct sockaddr_un *addr) -{ - int fd; - - if ((fd = socket(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0)) < 0) - goto error0; - - /* Unlink the socket location in case it was being used by a process which - * left around a stale lockfile. */ - unlink(addr->sun_path); - - if (bind(fd, (struct sockaddr *)addr, sizeof(*addr)) < 0) - goto error1; - - if (listen(fd, 1) < 0) - goto error2; - - return fd; - -error2: - if (addr->sun_path[0]) - unlink(addr->sun_path); -error1: - close(fd); -error0: - return -1; -} - -static bool -open_display(void) -{ - char lock_name[64], pid[12]; - int lock_fd; - struct sockaddr_un addr = {.sun_family = AF_LOCAL}; - - xserver.display = 0; - - /* Create X lockfile and server sockets */ - goto begin; - -retry2: - close(xserver.abstract_fd); -retry1: - unlink(lock_name); -retry0: - if (++xserver.display > 32) { - ERROR("No open display in first 32\n"); - return false; - } - -begin: - snprintf(lock_name, sizeof(lock_name), LOCK_FMT, xserver.display); - lock_fd = open(lock_name, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, 0444); - - if (lock_fd == -1) { - char *end; - pid_t owner; - - /* Check if the owning process is still alive. */ - if ((lock_fd = open(lock_name, O_RDONLY)) == -1) - goto retry0; - - if (read(lock_fd, pid, sizeof(pid) - 1) != sizeof(pid) - 1) - goto retry0; - - owner = strtol(pid, &end, 10); - - if (end != pid + 10) - goto retry0; - - if (kill(owner, 0) == 0 || errno != ESRCH) - goto retry0; - - if (unlink(lock_name) != 0) - goto retry0; - - goto begin; - } - - snprintf(pid, sizeof(pid), "%10d\n", getpid()); - if (write(lock_fd, pid, sizeof(pid) - 1) != sizeof(pid) - 1) { - ERROR("Failed to write PID file\n"); - unlink(lock_name); - close(lock_fd); - return false; - } - - close(lock_fd); - - /* Bind to abstract socket */ - addr.sun_path[0] = '\0'; - snprintf(addr.sun_path + 1, sizeof(addr.sun_path) - 1, SOCKET_FMT, xserver.display); - if ((xserver.abstract_fd = open_socket(&addr)) < 0) - goto retry1; - - /* Bind to unix socket */ - mkdir(SOCKET_DIR, 0777); - snprintf(addr.sun_path, sizeof(addr.sun_path), SOCKET_FMT, xserver.display); - if ((xserver.unix_fd = open_socket(&addr)) < 0) - goto retry2; - - snprintf(xserver.display_name, sizeof(xserver.display_name), ":%d", xserver.display); - setenv("DISPLAY", xserver.display_name, true); - - return true; -} - -static void -close_display(void) -{ - char path[64]; - - close(xserver.abstract_fd); - close(xserver.unix_fd); - - snprintf(path, sizeof(path), SOCKET_FMT, xserver.display); - unlink(path); - snprintf(path, sizeof(path), LOCK_FMT, xserver.display); - unlink(path); - - unsetenv("DISPLAY"); -} - -static int -handle_usr1(int signal_number, void *data) -{ - if (xwm_initialize(xserver.wm_fd)) { - xserver.xwm_initialized = true; - } else { - ERROR("Failed to initialize X window manager\n"); - /* XXX: How do we handle this case? */ - } - - wl_event_source_remove(xserver.usr1_source); - - return 0; -} - -static void -handle_client_destroy(struct wl_listener *listener, void *data) { - swc_xserver.client = NULL; -} - -static struct wl_listener client_destroy_listener = { - .notify = handle_client_destroy, -}; - -bool -xserver_initialize(void) -{ - int wl[2], wm[2]; - - /* Open an X display */ - if (!open_display()) { - ERROR("Failed to get X lockfile and sockets\n"); - goto error0; - } - - xserver.usr1_source = wl_event_loop_add_signal(swc.event_loop, SIGUSR1, &handle_usr1, NULL); - - if (!xserver.usr1_source) { - ERROR("Failed to create SIGUSR1 event source\n"); - goto error1; - } - - /* Open a socket for the Wayland connection from Xwayland. */ - if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, wl) != 0) { - ERROR("Failed to create socketpair: %s\n", strerror(errno)); - goto error2; - } - - /* Open a socket for the X connection to Xwayland. */ - if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, wm) != 0) { - ERROR("Failed to create socketpair: %s\n", strerror(errno)); - goto error3; - } - - if (!(swc_xserver.client = wl_client_create(swc.display, wl[0]))) - goto error4; - - wl_client_add_destroy_listener(swc_xserver.client, &client_destroy_listener); - xserver.wm_fd = wm[0]; - - /* Start the X server */ - switch (fork()) { - case 0: { - int fds[] = { wl[1], wm[1], xserver.abstract_fd, xserver.unix_fd }; - char strings[ARRAY_LENGTH(fds)][16]; - unsigned index; - struct sigaction action = {.sa_handler = SIG_IGN }; - - /* Unset the FD_CLOEXEC flag on the FDs that will get passed to Xwayland. */ - for (index = 0; index < ARRAY_LENGTH(fds); ++index) { - if (fcntl(fds[index], F_SETFD, 0) != 0) { - ERROR("fcntl() failed: %s\n", strerror(errno)); - goto fail; - } - - if (snprintf(strings[index], sizeof(strings[index]), "%d", fds[index]) >= sizeof(strings[index])) { - ERROR("FD is too large\n"); - goto fail; - } - } - - /* Ignore the USR1 signal so that Xwayland will send a USR1 signal to the - * parent process (us) after it finishes initializing. See Xserver(1) for - * more details. */ - if (sigaction(SIGUSR1, &action, NULL) != 0) { - ERROR("Failed to set SIGUSR1 handler to SIG_IGN: %s\n", strerror(errno)); - goto fail; - } - - setenv("WAYLAND_SOCKET", strings[0], true); - execlp("Xwayland", "Xwayland", - xserver.display_name, - "-rootless", - "-terminate", - "-listen", strings[2], - "-listen", strings[3], - "-wm", strings[1], - NULL); - - fail: - exit(EXIT_FAILURE); - } - case -1: - ERROR("fork() failed when trying to start X server: %s\n", strerror(errno)); - goto error5; - } - - close(wl[1]); - close(wm[1]); - - return true; - -error5: - wl_client_destroy(swc_xserver.client); -error4: - close(wm[1]); - close(wm[0]); -error3: - close(wl[1]); - close(wl[0]); -error2: - wl_event_source_remove(xserver.usr1_source); -error1: - close_display(); -error0: - return false; -} - -void -xserver_finalize(void) -{ - if (xserver.xwm_initialized) - xwm_finalize(); - if (swc_xserver.client) - wl_client_destroy(swc_xserver.client); - close_display(); -} diff --git a/libswc/xserver.h b/libswc/xserver.h @@ -1,36 +0,0 @@ -/* swc: libswc/xserver.h - * - * Copyright (c) 2013, 2014 Michael Forney - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef SWC_XSERVER_H -#define SWC_XSERVER_H - -#include <stdbool.h> - -struct swc_xserver { - struct wl_client *client; -}; - -bool xserver_initialize(void); -void xserver_finalize(void); - -#endif diff --git a/libswc/xwm.c b/libswc/xwm.c @@ -1,538 +0,0 @@ -/* swc: libswc/xwm.c - * - * Copyright (c) 2013, 2014 Michael Forney - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "xwm.h" -#include "compositor.h" -#include "internal.h" -#include "surface.h" -#include "swc.h" -#include "util.h" -#include "view.h" -#include "window.h" -#include "xserver.h" - -#include <stdio.h> -#include <xcb/composite.h> -#include <xcb/xcb_ewmh.h> -#include <xcb/xcb_icccm.h> - -struct xwl_window { - xcb_window_t id; - uint32_t surface_id; - bool override_redirect, supports_delete; - struct wl_list link; - - /* Only used for paired windows. */ - struct { - struct window window; - struct wl_listener surface_destroy_listener; - }; -}; - -enum atom { - ATOM_WL_SURFACE_ID, - ATOM_WM_DELETE_WINDOW, - ATOM_WM_PROTOCOLS, - ATOM_WM_S0, -}; - -static struct { - xcb_connection_t *connection; - xcb_ewmh_connection_t ewmh; - xcb_screen_t *screen; - xcb_window_t window; - struct xwl_window *focus; - struct wl_event_source *source; - struct wl_list windows, unpaired_windows; - union { - const char *name; - xcb_intern_atom_cookie_t cookie; - xcb_atom_t value; - } atoms[4]; -} xwm = { - .atoms = { - [ATOM_WL_SURFACE_ID] = "WL_SURFACE_ID", - [ATOM_WM_DELETE_WINDOW] = "WM_DELETE_WINDOW", - [ATOM_WM_PROTOCOLS] = "WM_PROTOCOLS", - [ATOM_WM_S0] = "WM_S0", - } -}; - -static void -update_name(struct xwl_window *xwl_window) -{ - xcb_get_property_cookie_t wm_name_cookie; - xcb_ewmh_get_utf8_strings_reply_t wm_name_reply; - - wm_name_cookie = xcb_ewmh_get_wm_name(&xwm.ewmh, xwl_window->id); - - if (xcb_ewmh_get_wm_name_reply(&xwm.ewmh, wm_name_cookie, &wm_name_reply, NULL)) { - window_set_title(&xwl_window->window, wm_name_reply.strings, wm_name_reply.strings_len); - xcb_ewmh_get_utf8_strings_reply_wipe(&wm_name_reply); - } else { - window_set_title(&xwl_window->window, NULL, 0); - } -} - -static void -update_protocols(struct xwl_window *xwl_window) -{ - xcb_get_property_cookie_t cookie; - xcb_icccm_get_wm_protocols_reply_t reply; - unsigned index; - - cookie = xcb_icccm_get_wm_protocols(xwm.connection, xwl_window->id, xwm.atoms[ATOM_WM_PROTOCOLS].value); - xwl_window->supports_delete = true; - - if (!xcb_icccm_get_wm_protocols_reply(xwm.connection, cookie, &reply, NULL)) - return; - - for (index = 0; index < reply.atoms_len; ++index) { - if (reply.atoms[index] == xwm.atoms[ATOM_WM_DELETE_WINDOW].value) - xwl_window->supports_delete = true; - } - - xcb_icccm_get_wm_protocols_reply_wipe(&reply); -} - -static struct xwl_window * -find_window(struct wl_list *list, xcb_window_t id) -{ - struct xwl_window *window; - - wl_list_for_each (window, list, link) { - if (window->id == id) - return window; - } - - return NULL; -} - -static struct xwl_window * -find_window_by_surface_id(struct wl_list *list, uint32_t id) -{ - struct xwl_window *window; - - wl_list_for_each (window, list, link) { - if (window->surface_id == id) - return window; - } - - return NULL; -} - -static void -move(struct window *window, int32_t x, int32_t y) -{ - uint32_t mask, values[2]; - struct xwl_window *xwl_window = wl_container_of(window, xwl_window, window); - - mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y; - values[0] = x; - values[1] = y; - - xcb_configure_window(xwm.connection, xwl_window->id, mask, values); - xcb_flush(xwm.connection); -} - -static void -configure(struct window *window, uint32_t width, uint32_t height) -{ - uint32_t mask, values[2]; - struct xwl_window *xwl_window = wl_container_of(window, xwl_window, window); - - mask = XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT; - values[0] = width; - values[1] = height; - - window->configure.acknowledged = true; - xcb_configure_window(xwm.connection, xwl_window->id, mask, values); - xcb_flush(xwm.connection); -} - -static void -focus(struct window *window) -{ - struct xwl_window *xwl_window = wl_container_of(window, xwl_window, window); - - xcb_set_input_focus(xwm.connection, XCB_INPUT_FOCUS_NONE, xwl_window->id, XCB_CURRENT_TIME); - xcb_flush(xwm.connection); - xwm.focus = xwl_window; -} - -static void -unfocus(struct window *window) -{ - struct xwl_window *xwl_window = wl_container_of(window, xwl_window, window); - - /* If the window we are unfocusing is the latest xwl_window to be focused, we - * know we have transitioned to some other window type, so the X11 focus can - * be set to XCB_NONE. Otherwise, we have transitioned to another X11 window, - * and the X11 focus has already been updated. */ - if (xwl_window == xwm.focus) { - xcb_set_input_focus(xwm.connection, XCB_INPUT_FOCUS_NONE, XCB_NONE, XCB_CURRENT_TIME); - xcb_flush(xwm.connection); - } -} - -static void -close(struct window *window) -{ - struct xwl_window *xwl_window = wl_container_of(window, xwl_window, window); - - if (xwl_window->supports_delete) { - xcb_client_message_event_t event = { - .response_type = XCB_CLIENT_MESSAGE, - .format = 32, - .window = xwl_window->id, - .type = xwm.atoms[ATOM_WM_PROTOCOLS].value, - .data.data32 = { - xwm.atoms[ATOM_WM_DELETE_WINDOW].value, - XCB_CURRENT_TIME, - }, - }; - - xcb_send_event(xwm.connection, false, xwl_window->id, XCB_EVENT_MASK_NO_EVENT, (const char *)&event); - } else { - xcb_kill_client(xwm.connection, xwl_window->id); - } - - xcb_flush(xwm.connection); -} - -static const struct window_impl xwl_window_handler = { - .move = move, - .configure = configure, - .focus = focus, - .unfocus = unfocus, - .close = close, -}; - -static void -handle_surface_destroy(struct wl_listener *listener, void *data) -{ - struct xwl_window *xwl_window = wl_container_of(listener, xwl_window, surface_destroy_listener); - - if (xwm.focus == xwl_window) - xwm.focus = NULL; - - window_finalize(&xwl_window->window); - wl_list_remove(&xwl_window->link); - wl_list_insert(&xwm.unpaired_windows, &xwl_window->link); - xwl_window->surface_id = 0; -} - -static bool -manage_window(struct xwl_window *xwl_window) -{ - struct wl_resource *resource; - struct surface *surface; - xcb_get_geometry_cookie_t geometry_cookie; - xcb_get_geometry_reply_t *geometry_reply; - - resource = wl_client_get_object(swc.xserver->client, xwl_window->surface_id); - - if (!resource) - return false; - - surface = wl_resource_get_user_data(resource); - geometry_cookie = xcb_get_geometry(xwm.connection, xwl_window->id); - - window_initialize(&xwl_window->window, &xwl_window_handler, surface); - xwl_window->surface_destroy_listener.notify = &handle_surface_destroy; - wl_resource_add_destroy_listener(surface->resource, &xwl_window->surface_destroy_listener); - - if ((geometry_reply = xcb_get_geometry_reply(xwm.connection, geometry_cookie, NULL))) { - view_move(surface->view, geometry_reply->x, geometry_reply->y); - free(geometry_reply); - } - - if (xwl_window->override_redirect) { - compositor_view_show(xwl_window->window.view); - } else { - uint32_t mask, values[1]; - - mask = XCB_CW_EVENT_MASK; - values[0] = XCB_EVENT_MASK_PROPERTY_CHANGE; - xcb_change_window_attributes(xwm.connection, xwl_window->id, mask, values); - mask = XCB_CONFIG_WINDOW_BORDER_WIDTH; - values[0] = 0; - xcb_configure_window(xwm.connection, xwl_window->id, mask, values); - update_name(xwl_window); - update_protocols(xwl_window); - window_manage(&xwl_window->window); - } - - wl_list_remove(&xwl_window->link); - wl_list_insert(&xwm.windows, &xwl_window->link); - - return true; -} - -static void -handle_new_surface(struct wl_listener *listener, void *data) -{ - struct surface *surface = data; - struct xwl_window *window; - - window = find_window_by_surface_id(&xwm.unpaired_windows, wl_resource_get_id(surface->resource)); - - if (!window) - return; - - manage_window(window); -} - -static struct wl_listener new_surface_listener = { - .notify = &handle_new_surface -}; - -/* X event handlers */ -static void -create_notify(xcb_create_notify_event_t *event) -{ - struct xwl_window *xwl_window; - - if (!(xwl_window = malloc(sizeof *xwl_window))) - return; - - xwl_window->id = event->window; - xwl_window->surface_id = 0; - xwl_window->override_redirect = event->override_redirect; - wl_list_insert(&xwm.unpaired_windows, &xwl_window->link); -} - -static void -destroy_notify(xcb_destroy_notify_event_t *event) -{ - struct xwl_window *xwl_window; - - if ((xwl_window = find_window(&xwm.windows, event->window))) { - wl_list_remove(&xwl_window->surface_destroy_listener.link); - window_finalize(&xwl_window->window); - } else if (!(xwl_window = find_window(&xwm.unpaired_windows, event->window))) { - return; - } - - wl_list_remove(&xwl_window->link); - free(xwl_window); -} - -static void -map_request(xcb_map_request_event_t *event) -{ - xcb_map_window(xwm.connection, event->window); -} - -static void -configure_request(xcb_configure_request_event_t *event) -{ -} - -static void -property_notify(xcb_property_notify_event_t *event) -{ - struct xwl_window *xwl_window; - - if (!(xwl_window = find_window(&xwm.windows, event->window))) - return; - - if (event->atom == xwm.ewmh._NET_WM_NAME && event->state == XCB_PROPERTY_NEW_VALUE) - update_name(xwl_window); - else if (event->atom == xwm.atoms[ATOM_WM_PROTOCOLS].value) - update_protocols(xwl_window); -} - -static void -client_message(xcb_client_message_event_t *event) -{ - if (event->type == xwm.atoms[ATOM_WL_SURFACE_ID].value) { - struct xwl_window *xwl_window; - - if (!(xwl_window = find_window(&xwm.unpaired_windows, event->window))) - return; - - xwl_window->surface_id = event->data.data32[0]; - manage_window(xwl_window); - } -} - -static int -connection_data(int fd, uint32_t mask, void *data) -{ - xcb_generic_event_t *event; - uint32_t count = 0; - - while ((event = xcb_poll_for_event(xwm.connection))) { - switch (event->response_type & ~0x80) { - case XCB_CREATE_NOTIFY: - create_notify((xcb_create_notify_event_t *)event); - break; - case XCB_DESTROY_NOTIFY: - destroy_notify((xcb_destroy_notify_event_t *)event); - break; - case XCB_MAP_REQUEST: - map_request((xcb_map_request_event_t *)event); - break; - case XCB_CONFIGURE_REQUEST: - configure_request((xcb_configure_request_event_t *)event); - break; - case XCB_PROPERTY_NOTIFY: - property_notify((xcb_property_notify_event_t *)event); - break; - case XCB_CLIENT_MESSAGE: - client_message((xcb_client_message_event_t *)event); - break; - } - - free(event); - ++count; - } - - xcb_flush(xwm.connection); - - return count; -} - -bool -xwm_initialize(int fd) -{ - const xcb_setup_t *setup; - xcb_screen_iterator_t screen_iterator; - uint32_t mask; - uint32_t values[1]; - xcb_void_cookie_t change_attributes_cookie, redirect_subwindows_cookie; - xcb_generic_error_t *error; - xcb_intern_atom_cookie_t *ewmh_cookies; - xcb_intern_atom_reply_t *atom_reply; - unsigned index; - const char *name; - const xcb_query_extension_reply_t *composite_extension; - - xwm.connection = xcb_connect_to_fd(fd, NULL); - - if (xcb_connection_has_error(xwm.connection)) { - ERROR("xwm: Could not connect to X server\n"); - goto error0; - } - - xcb_prefetch_extension_data(xwm.connection, &xcb_composite_id); - ewmh_cookies = xcb_ewmh_init_atoms(xwm.connection, &xwm.ewmh); - - if (!ewmh_cookies) { - ERROR("xwm: Failed to initialize EWMH atoms\n"); - goto error1; - } - - for (index = 0; index < ARRAY_LENGTH(xwm.atoms); ++index) { - name = xwm.atoms[index].name; - xwm.atoms[index].cookie = xcb_intern_atom(xwm.connection, 0, strlen(name), name); - } - - setup = xcb_get_setup(xwm.connection); - screen_iterator = xcb_setup_roots_iterator(setup); - xwm.screen = screen_iterator.data; - - /* Try to select for substructure redirect. */ - mask = XCB_CW_EVENT_MASK; - values[0] = XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT; - change_attributes_cookie = xcb_change_window_attributes(xwm.connection, xwm.screen->root, mask, values); - - xwm.source = wl_event_loop_add_fd(swc.event_loop, fd, WL_EVENT_READABLE, &connection_data, NULL); - wl_list_init(&xwm.windows); - wl_list_init(&xwm.unpaired_windows); - - if (!xwm.source) { - ERROR("xwm: Failed to create X connection event source\n"); - goto error2; - } - - composite_extension = xcb_get_extension_data(xwm.connection, &xcb_composite_id); - - if (!composite_extension->present) { - ERROR("xwm: X server does not have composite extension\n"); - goto error3; - } - - redirect_subwindows_cookie = xcb_composite_redirect_subwindows_checked(xwm.connection, xwm.screen->root, XCB_COMPOSITE_REDIRECT_MANUAL); - - if ((error = xcb_request_check(xwm.connection, change_attributes_cookie))) { - ERROR("xwm: Another window manager is running\n"); - free(error); - goto error3; - } - - if ((error = xcb_request_check(xwm.connection, redirect_subwindows_cookie))) { - ERROR("xwm: Could not redirect subwindows of root for compositing\n"); - free(error); - goto error3; - } - - xwm.window = xcb_generate_id(xwm.connection); - xcb_create_window(xwm.connection, 0, xwm.window, xwm.screen->root, - 0, 0, 1, 1, 0, XCB_WINDOW_CLASS_INPUT_ONLY, - XCB_COPY_FROM_PARENT, 0, NULL); - - xcb_ewmh_init_atoms_replies(&xwm.ewmh, ewmh_cookies, &error); - - if (error) { - ERROR("xwm: Failed to get EWMH atom replies: %u\n", error->error_code); - goto error3; - } - - for (index = 0; index < ARRAY_LENGTH(xwm.atoms); ++index) { - atom_reply = xcb_intern_atom_reply(xwm.connection, xwm.atoms[index].cookie, &error); - - if (error) { - ERROR("xwm: Failed to get atom reply: %u\n", error->error_code); - return false; - } - - xwm.atoms[index].value = atom_reply->atom; - free(atom_reply); - } - - xcb_set_selection_owner(xwm.connection, xwm.window, xwm.atoms[ATOM_WM_S0].value, XCB_CURRENT_TIME); - xcb_flush(xwm.connection); - - wl_signal_add(&swc.compositor->signal.new_surface, &new_surface_listener); - - return true; - -error3: - wl_event_source_remove(xwm.source); -error2: - xcb_ewmh_connection_wipe(&xwm.ewmh); -error1: - xcb_disconnect(xwm.connection); -error0: - return false; -} - -void -xwm_finalize(void) -{ - wl_event_source_remove(xwm.source); - xcb_ewmh_connection_wipe(&xwm.ewmh); - xcb_disconnect(xwm.connection); -} diff --git a/libswc/xwm.h b/libswc/xwm.h @@ -1,32 +0,0 @@ -/* swc: libswc/xwm.h - * - * Copyright (c) 2013 Michael Forney - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef SWC_XWM_H -#define SWC_XWM_H - -#include <stdbool.h> - -bool xwm_initialize(int fd); -void xwm_finalize(void); - -#endif