From b2bab1af5c34b785a9b08db04af1330e61dd210c Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Sat, 19 Aug 2017 21:25:26 +0200 Subject: [PATCH] xwayland: split xwm structure out, initial xwm.c --- examples/compositor.c | 2 +- include/wlr/xwayland.h | 11 +++++- include/xwayland/internals.h | 16 +++++++++ meson.build | 2 ++ xwayland/meson.build | 4 ++- xwayland/xwayland.c | 18 ++++++++-- xwayland/xwm.c | 69 ++++++++++++++++++++++++++++++++++++ 7 files changed, 117 insertions(+), 5 deletions(-) create mode 100644 xwayland/xwm.c diff --git a/examples/compositor.c b/examples/compositor.c index be9fc5ca..e143099c 100644 --- a/examples/compositor.c +++ b/examples/compositor.c @@ -178,7 +178,7 @@ int main() { free(keymap); break; } - wlr_xwayland_init(&state.wlr_xwayland, compositor.display); + wlr_xwayland_init(&state.wlr_xwayland, compositor.display, state.wlr_compositor); compositor.keyboard_key_cb = handle_keyboard_key; diff --git a/include/wlr/xwayland.h b/include/wlr/xwayland.h index ef9cc887..f61a90bd 100644 --- a/include/wlr/xwayland.h +++ b/include/wlr/xwayland.h @@ -1,5 +1,11 @@ #ifndef _WLR_XWAYLAND_H #define _WLR_XWAYLAND_H +#include +#include +#include +#include + +struct wlr_xwm; struct wlr_xwayland { pid_t pid; @@ -7,11 +13,14 @@ struct wlr_xwayland { int x_fd[2], wl_fd[2], wm_fd[2]; struct wl_client *client; struct wl_display *wl_display; + struct wlr_compositor *compositor; time_t server_start; + + struct wlr_xwm *xwm; }; void wlr_xwayland_finish(struct wlr_xwayland *wlr_xwayland); bool wlr_xwayland_init(struct wlr_xwayland *wlr_xwayland, - struct wl_display *wl_display); + struct wl_display *wl_display, struct wlr_compositor *compositor); #endif diff --git a/include/xwayland/internals.h b/include/xwayland/internals.h index b91f7930..46158bd0 100644 --- a/include/xwayland/internals.h +++ b/include/xwayland/internals.h @@ -1,6 +1,22 @@ #ifndef XWAYLAND_INTERNALS_H #define XWAYLAND_INTERNALS_H +#include +#include +#include + +struct wlr_xwm { + struct wlr_xwayland *xwayland; + struct wl_event_source *event_source; + struct wl_listener surface_listener; + + xcb_connection_t *xcb_connection; + xcb_screen_t *xcb_screen; +}; void unlink_sockets(int display); int open_display_sockets(int socks[2]); + +void xwm_destroy(struct wlr_xwm *xwm); +struct wlr_xwm *xwm_create(struct wlr_xwayland *wlr_xwayland); + #endif diff --git a/meson.build b/meson.build index b3706dbc..a7baacf9 100644 --- a/meson.build +++ b/meson.build @@ -32,6 +32,7 @@ libinput = dependency('libinput') xkbcommon = dependency('xkbcommon') udev = dependency('libudev') pixman = dependency('pixman-1') +xcb = dependency('xcb') libcap = dependency('libcap', required: false) systemd = dependency('libsystemd', required: false) math = cc.find_library('m', required: false) @@ -65,6 +66,7 @@ wlr_deps = [ xkbcommon, udev, pixman, + xcb, libcap, systemd, math, diff --git a/xwayland/meson.build b/xwayland/meson.build index d43ace9b..6f75e23a 100644 --- a/xwayland/meson.build +++ b/xwayland/meson.build @@ -1,5 +1,7 @@ lib_wlr_xwayland = static_library('wlr_xwayland', files( 'sockets.c', 'xwayland.c', + 'xwm.c', ), - include_directories: wlr_inc) + include_directories: wlr_inc, + dependencies: [wayland_server, xcb, pixman]) diff --git a/xwayland/xwayland.c b/xwayland/xwayland.c index 49173ace..e9bdfcc5 100644 --- a/xwayland/xwayland.c +++ b/xwayland/xwayland.c @@ -76,6 +76,8 @@ static void exec_xwayland(struct wlr_xwayland *wlr_xwayland) { wlr_xwayland->display, wlr_xwayland->x_fd[0], wlr_xwayland->x_fd[1], wlr_xwayland->wm_fd[1]); + // TODO: close stdout/err depending on log level + execvpe("Xwayland", argv, envp); } @@ -88,7 +90,8 @@ static void xwayland_destroy_event(struct wl_listener *listener, void *data) { wlr_xwayland_finish(wlr_xwayland); if (wlr_xwayland->server_start - time(NULL) > 5) { - wlr_xwayland_init(wlr_xwayland, wlr_xwayland->wl_display); + wlr_xwayland_init(wlr_xwayland, wlr_xwayland->wl_display, + wlr_xwayland->compositor); } } @@ -103,6 +106,8 @@ void wlr_xwayland_finish(struct wlr_xwayland *wlr_xwayland) { wl_client_destroy(wlr_xwayland->client); } + xwm_destroy(wlr_xwayland->xwm); + safe_close(wlr_xwayland->x_fd[0]); safe_close(wlr_xwayland->x_fd[1]); safe_close(wlr_xwayland->wl_fd[0]); @@ -116,8 +121,10 @@ void wlr_xwayland_finish(struct wlr_xwayland *wlr_xwayland) { } bool wlr_xwayland_init(struct wlr_xwayland *wlr_xwayland, - struct wl_display *wl_display) { + struct wl_display *wl_display, struct wlr_compositor *compositor) { + memset(wlr_xwayland, 0, sizeof(struct wlr_xwayland)); wlr_xwayland->wl_display = wl_display; + wlr_xwayland->compositor = compositor; wlr_xwayland->x_fd[0] = wlr_xwayland->x_fd[1] = -1; wlr_xwayland->wl_fd[0] = wlr_xwayland->wl_fd[1] = -1; wlr_xwayland->wm_fd[0] = wlr_xwayland->wm_fd[1] = -1; @@ -162,9 +169,16 @@ bool wlr_xwayland_init(struct wlr_xwayland *wlr_xwayland, if (!(wlr_xwayland->client = wl_client_create(wl_display, wlr_xwayland->wl_fd[0]))) { wlr_log_errno(L_ERROR, "wl_client_create failed"); wlr_xwayland_finish(wlr_xwayland); + return false; } wl_client_add_destroy_listener(wlr_xwayland->client, &xwayland_destroy_listener); + wlr_xwayland->xwm = xwm_create(wlr_xwayland); + if (!wlr_xwayland->xwm) { + wlr_xwayland_finish(wlr_xwayland); + return false; + } + return true; } diff --git a/xwayland/xwm.c b/xwayland/xwm.c new file mode 100644 index 00000000..d39527c5 --- /dev/null +++ b/xwayland/xwm.c @@ -0,0 +1,69 @@ +#include +#include "wlr/util/log.h" +#include "wlr/types/wlr_surface.h" +#include "wlr/xwayland.h" +#include "xwayland/internals.h" + +#define SEND_EVENT_MASK 0x80 +static int x11_event_handler(int fd, uint32_t mask, void *data) { + int count = 0; + xcb_generic_event_t *event; + struct wlr_xwayland *wlr_xwayland = data; + struct wlr_xwm *xwm = wlr_xwayland->xwm; + + while ((event = xcb_poll_for_event(xwm->xcb_connection))) { + wlr_log(L_DEBUG, "X11 event: %d", event->response_type & ~SEND_EVENT_MASK); + count++; + // TODO: actually do stuff! + } + return count; +} + +static void create_surface_handler(struct wl_listener *listener, void *data) +{ + struct wlr_surface *surface = data; + struct wlr_xwm *xwm = wl_container_of(listener, xwm, surface_listener); + + if (wl_resource_get_client(surface->resource) != xwm->xwayland->client) { + return; + } + + wlr_log(L_DEBUG, "new x11 surface: %p", surface); + + // TODO: look for unpaired window, and assign +} + +void xwm_destroy(struct wlr_xwm *xwm) { + if (xwm->event_source) { + wl_event_source_remove(xwm->event_source); + } + + free(xwm); +} + +struct wlr_xwm *xwm_create(struct wlr_xwayland *wlr_xwayland) { + struct wlr_xwm *xwm = calloc(1, sizeof(struct wlr_xwm)); + + xwm->xwayland = wlr_xwayland; + + xwm->xcb_connection = xcb_connect_to_fd(wlr_xwayland->wm_fd[0], NULL); + if (xcb_connection_has_error(xwm->xcb_connection)) { + return NULL; + } + + // TODO more xcb init + // xcb_prefetch_extension_data(xwm->xcb_connection, &xcb_composite_id); + + struct wl_event_loop *event_loop = wl_display_get_event_loop(wlr_xwayland->wl_display); + xwm->event_source = wl_event_loop_add_fd(event_loop, wlr_xwayland->wm_fd[0], + WL_EVENT_READABLE, x11_event_handler, wlr_xwayland); + // probably not needed + // wl_event_source_check(xwm->event_source); + + + xwm->surface_listener.notify = create_surface_handler; + //wl_signal_add(&wlr_xwayland->compositor->create_surface_signal, + // &xwm->surface_listener); + + return xwm; +}