Merge branch 'master' into xwm-selection

This commit is contained in:
emersion 2017-12-14 23:59:04 +01:00
commit 6b42bfad18
No known key found for this signature in database
GPG key ID: 0FDE7BE0E88F5E48
45 changed files with 560 additions and 274 deletions

View file

@ -34,6 +34,10 @@ static void wlr_drm_backend_destroy(struct wlr_backend *backend) {
wlr_output_destroy(&conn->output); wlr_output_destroy(&conn->output);
} }
wl_list_remove(&drm->display_destroy.link);
wl_list_remove(&drm->session_signal.link);
wl_list_remove(&drm->drm_invalidated.link);
wlr_drm_resources_free(drm); wlr_drm_resources_free(drm);
wlr_drm_renderer_finish(&drm->renderer); wlr_drm_renderer_finish(&drm->renderer);
wlr_session_close_file(drm->session, drm->fd); wlr_session_close_file(drm->session, drm->fd);
@ -57,7 +61,8 @@ bool wlr_backend_is_drm(struct wlr_backend *b) {
} }
static void session_signal(struct wl_listener *listener, void *data) { static void session_signal(struct wl_listener *listener, void *data) {
struct wlr_drm_backend *drm = wl_container_of(listener, drm, session_signal); struct wlr_drm_backend *drm =
wl_container_of(listener, drm, session_signal);
struct wlr_session *session = data; struct wlr_session *session = data;
if (session->active) { if (session->active) {
@ -84,7 +89,8 @@ static void session_signal(struct wl_listener *listener, void *data) {
} }
static void drm_invalidated(struct wl_listener *listener, void *data) { static void drm_invalidated(struct wl_listener *listener, void *data) {
struct wlr_drm_backend *drm = wl_container_of(listener, drm, drm_invalidated); struct wlr_drm_backend *drm =
wl_container_of(listener, drm, drm_invalidated);
char *name = drmGetDeviceNameFromFd2(drm->fd); char *name = drmGetDeviceNameFromFd2(drm->fd);
wlr_log(L_DEBUG, "%s invalidated", name); wlr_log(L_DEBUG, "%s invalidated", name);
@ -93,6 +99,12 @@ static void drm_invalidated(struct wl_listener *listener, void *data) {
wlr_drm_scan_connectors(drm); wlr_drm_scan_connectors(drm);
} }
static void handle_display_destroy(struct wl_listener *listener, void *data) {
struct wlr_drm_backend *drm =
wl_container_of(listener, drm, display_destroy);
wlr_drm_backend_destroy(&drm->backend);
}
struct wlr_backend *wlr_drm_backend_create(struct wl_display *display, struct wlr_backend *wlr_drm_backend_create(struct wl_display *display,
struct wlr_session *session, int gpu_fd, struct wlr_backend *parent) { struct wlr_session *session, int gpu_fd, struct wlr_backend *parent) {
assert(display && session && gpu_fd >= 0); assert(display && session && gpu_fd >= 0);
@ -150,6 +162,9 @@ struct wlr_backend *wlr_drm_backend_create(struct wl_display *display,
wlr_log(L_INFO, "Failed to bind egl/wl display: %s", egl_error()); wlr_log(L_INFO, "Failed to bind egl/wl display: %s", egl_error());
} }
drm->display_destroy.notify = handle_display_destroy;
wl_display_add_destroy_listener(display, &drm->display_destroy);
return &drm->backend; return &drm->backend;
error_event: error_event:

View file

@ -565,8 +565,7 @@ static bool wlr_drm_connector_set_cursor(struct wlr_output *output,
enum wl_output_transform transform = enum wl_output_transform transform =
wlr_output_transform_invert(output->transform); wlr_output_transform_invert(output->transform);
struct wlr_box transformed_hotspot; struct wlr_box transformed_hotspot;
wlr_output_transform_apply_to_box(transform, &hotspot, wlr_box_transform(&hotspot, transform, &transformed_hotspot);
&transformed_hotspot);
plane->cursor_hotspot_x = transformed_hotspot.x; plane->cursor_hotspot_x = transformed_hotspot.x;
plane->cursor_hotspot_y = transformed_hotspot.y; plane->cursor_hotspot_y = transformed_hotspot.y;
@ -628,7 +627,7 @@ static bool wlr_drm_connector_move_cursor(struct wlr_output *output,
enum wl_output_transform transform = enum wl_output_transform transform =
wlr_output_transform_invert(output->transform); wlr_output_transform_invert(output->transform);
struct wlr_box transformed_box; struct wlr_box transformed_box;
wlr_output_transform_apply_to_box(transform, &box, &transformed_box); wlr_box_transform(&box, transform, &transformed_box);
if (plane != NULL) { if (plane != NULL) {
transformed_box.x -= plane->cursor_hotspot_x; transformed_box.x -= plane->cursor_hotspot_x;

View file

@ -39,7 +39,7 @@ bool wlr_drm_renderer_init(struct wlr_drm_backend *drm,
return true; return true;
error_egl: error_egl:
wlr_egl_free(&renderer->egl); wlr_egl_finish(&renderer->egl);
error_gbm: error_gbm:
gbm_device_destroy(renderer->gbm); gbm_device_destroy(renderer->gbm);
return false; return false;
@ -51,7 +51,7 @@ void wlr_drm_renderer_finish(struct wlr_drm_renderer *renderer) {
} }
wlr_renderer_destroy(renderer->wlr_rend); wlr_renderer_destroy(renderer->wlr_rend);
wlr_egl_free(&renderer->egl); wlr_egl_finish(&renderer->egl);
gbm_device_destroy(renderer->gbm); gbm_device_destroy(renderer->gbm);
} }

View file

@ -43,10 +43,12 @@ static void wlr_libinput_log(struct libinput *libinput_context,
} }
static bool wlr_libinput_backend_start(struct wlr_backend *_backend) { static bool wlr_libinput_backend_start(struct wlr_backend *_backend) {
struct wlr_libinput_backend *backend = (struct wlr_libinput_backend *)_backend; struct wlr_libinput_backend *backend =
(struct wlr_libinput_backend *)_backend;
wlr_log(L_DEBUG, "Initializing libinput"); wlr_log(L_DEBUG, "Initializing libinput");
backend->libinput_context = libinput_udev_create_context(&libinput_impl, backend,
backend->session->udev); backend->libinput_context = libinput_udev_create_context(&libinput_impl,
backend, backend->session->udev);
if (!backend->libinput_context) { if (!backend->libinput_context) {
wlr_log(L_ERROR, "Failed to create libinput context"); wlr_log(L_ERROR, "Failed to create libinput context");
return false; return false;
@ -99,6 +101,7 @@ static void wlr_libinput_backend_destroy(struct wlr_backend *_backend) {
} }
struct wlr_libinput_backend *backend = struct wlr_libinput_backend *backend =
(struct wlr_libinput_backend *)_backend; (struct wlr_libinput_backend *)_backend;
for (size_t i = 0; i < backend->wlr_device_lists.length; i++) { for (size_t i = 0; i < backend->wlr_device_lists.length; i++) {
struct wl_list *wlr_devices = backend->wlr_device_lists.items[i]; struct wl_list *wlr_devices = backend->wlr_device_lists.items[i];
struct wlr_input_device *wlr_dev, *next; struct wlr_input_device *wlr_dev, *next;
@ -108,6 +111,10 @@ static void wlr_libinput_backend_destroy(struct wlr_backend *_backend) {
} }
free(wlr_devices); free(wlr_devices);
} }
wl_list_remove(&backend->display_destroy.link);
wl_list_remove(&backend->session_signal.link);
wlr_list_finish(&backend->wlr_device_lists); wlr_list_finish(&backend->wlr_device_lists);
wl_event_source_remove(backend->input_event); wl_event_source_remove(backend->input_event);
libinput_unref(backend->libinput_context); libinput_unref(backend->libinput_context);
@ -124,7 +131,8 @@ bool wlr_backend_is_libinput(struct wlr_backend *b) {
} }
static void session_signal(struct wl_listener *listener, void *data) { static void session_signal(struct wl_listener *listener, void *data) {
struct wlr_libinput_backend *backend = wl_container_of(listener, backend, session_signal); struct wlr_libinput_backend *backend =
wl_container_of(listener, backend, session_signal);
struct wlr_session *session = data; struct wlr_session *session = data;
if (!backend->libinput_context) { if (!backend->libinput_context) {
@ -138,6 +146,12 @@ static void session_signal(struct wl_listener *listener, void *data) {
} }
} }
static void handle_display_destroy(struct wl_listener *listener, void *data) {
struct wlr_libinput_backend *backend =
wl_container_of(listener, backend, display_destroy);
wlr_libinput_backend_destroy(&backend->backend);
}
struct wlr_backend *wlr_libinput_backend_create(struct wl_display *display, struct wlr_backend *wlr_libinput_backend_create(struct wl_display *display,
struct wlr_session *session) { struct wlr_session *session) {
assert(display && session); assert(display && session);
@ -160,6 +174,9 @@ struct wlr_backend *wlr_libinput_backend_create(struct wl_display *display,
backend->session_signal.notify = session_signal; backend->session_signal.notify = session_signal;
wl_signal_add(&session->session_signal, &backend->session_signal); wl_signal_add(&session->session_signal, &backend->session_signal);
backend->display_destroy.notify = handle_display_destroy;
wl_display_add_destroy_listener(display, &backend->display_destroy);
return &backend->backend; return &backend->backend;
error_backend: error_backend:
free(backend); free(backend);

View file

@ -35,7 +35,6 @@ static void multi_backend_destroy(struct wlr_backend *_backend) {
wlr_backend_destroy(sub->backend); wlr_backend_destroy(sub->backend);
free(sub); free(sub);
} }
wlr_session_destroy(backend->session);
free(backend); free(backend);
} }

View file

@ -58,6 +58,12 @@ out:
return 1; return 1;
} }
static void handle_display_destroy(struct wl_listener *listener, void *data) {
struct wlr_session *session =
wl_container_of(listener, session, display_destroy);
wlr_session_destroy(session);
}
struct wlr_session *wlr_session_create(struct wl_display *disp) { struct wlr_session *wlr_session_create(struct wl_display *disp) {
struct wlr_session *session = NULL; struct wlr_session *session = NULL;
const struct session_impl **iter; const struct session_impl **iter;
@ -100,6 +106,9 @@ struct wlr_session *wlr_session_create(struct wl_display *disp) {
goto error_mon; goto error_mon;
} }
session->display_destroy.notify = handle_display_destroy;
wl_display_add_destroy_listener(disp, &session->display_destroy);
return session; return session;
error_mon: error_mon:
@ -107,7 +116,7 @@ error_mon:
error_udev: error_udev:
udev_unref(session->udev); udev_unref(session->udev);
error_session: error_session:
wlr_session_destroy(session); session->impl->destroy(session);
return NULL; return NULL;
} }
@ -116,6 +125,8 @@ void wlr_session_destroy(struct wlr_session *session) {
return; return;
} }
wl_list_remove(&session->display_destroy.link);
wl_event_source_remove(session->udev_event); wl_event_source_remove(session->udev_event);
udev_monitor_unref(session->mon); udev_monitor_unref(session->mon);
udev_unref(session->udev); udev_unref(session->udev);

View file

@ -79,10 +79,12 @@ static void wlr_wl_backend_destroy(struct wlr_backend *_backend) {
wlr_input_device_destroy(input_device); wlr_input_device_destroy(input_device);
} }
wl_list_remove(&backend->local_display_destroy.link);
free(backend->seat_name); free(backend->seat_name);
wl_event_source_remove(backend->remote_display_src); wl_event_source_remove(backend->remote_display_src);
wlr_egl_free(&backend->egl); wlr_egl_finish(&backend->egl);
if (backend->seat) wl_seat_destroy(backend->seat); if (backend->seat) wl_seat_destroy(backend->seat);
if (backend->shm) wl_shm_destroy(backend->shm); if (backend->shm) wl_shm_destroy(backend->shm);
if (backend->shell) zxdg_shell_v6_destroy(backend->shell); if (backend->shell) zxdg_shell_v6_destroy(backend->shell);
@ -150,6 +152,12 @@ void wlr_wl_output_layout_get_box(struct wlr_wl_backend *backend,
box->height = max_y - min_y; box->height = max_y - min_y;
} }
static void handle_display_destroy(struct wl_listener *listener, void *data) {
struct wlr_wl_backend *backend =
wl_container_of(listener, backend, local_display_destroy);
wlr_wl_backend_destroy(&backend->backend);
}
struct wlr_backend *wlr_wl_backend_create(struct wl_display *display) { struct wlr_backend *wlr_wl_backend_create(struct wl_display *display) {
wlr_log(L_INFO, "Creating wayland backend"); wlr_log(L_INFO, "Creating wayland backend");
@ -176,8 +184,12 @@ struct wlr_backend *wlr_wl_backend_create(struct wl_display *display) {
return false; return false;
} }
wlr_egl_init(&backend->egl, EGL_PLATFORM_WAYLAND_EXT, WL_SHM_FORMAT_ARGB8888, backend->remote_display); wlr_egl_init(&backend->egl, EGL_PLATFORM_WAYLAND_EXT,
WL_SHM_FORMAT_ARGB8888, backend->remote_display);
wlr_egl_bind_display(&backend->egl, backend->local_display); wlr_egl_bind_display(&backend->egl, backend->local_display);
backend->local_display_destroy.notify = handle_display_destroy;
wl_display_add_destroy_listener(display, &backend->local_display_destroy);
return &backend->backend; return &backend->backend;
} }

View file

@ -60,7 +60,8 @@ static void pointer_handle_motion(void *data, struct wl_pointer *wl_pointer,
box.x = wl_fixed_to_int(surface_x); box.x = wl_fixed_to_int(surface_x);
box.y = wl_fixed_to_int(surface_y); box.y = wl_fixed_to_int(surface_y);
struct wlr_box transformed; struct wlr_box transformed;
wlr_output_transform_apply_to_box(wlr_output->transform, &box, &transformed);
wlr_box_transform(&box, wlr_output->transform, &transformed);
box.x /= wlr_output->scale; box.x /= wlr_output->scale;
box.y /= wlr_output->scale; box.y /= wlr_output->scale;

View file

@ -183,69 +183,6 @@ static void init_atom(struct wlr_x11_backend *x11, struct wlr_x11_atom *atom,
atom->reply = xcb_intern_atom_reply(x11->xcb_conn, atom->cookie, NULL); atom->reply = xcb_intern_atom_reply(x11->xcb_conn, atom->cookie, NULL);
} }
struct wlr_backend *wlr_x11_backend_create(struct wl_display *display,
const char *x11_display) {
struct wlr_x11_backend *x11 = calloc(1, sizeof(*x11));
if (!x11) {
return NULL;
}
wlr_backend_init(&x11->backend, &backend_impl);
x11->wl_display = display;
x11->xlib_conn = XOpenDisplay(x11_display);
if (!x11->xlib_conn) {
wlr_log(L_ERROR, "Failed to open X connection");
return NULL;
}
x11->xcb_conn = XGetXCBConnection(x11->xlib_conn);
if (!x11->xcb_conn || xcb_connection_has_error(x11->xcb_conn)) {
wlr_log(L_ERROR, "Failed to open xcb connection");
goto error_x11;
}
XSetEventQueueOwner(x11->xlib_conn, XCBOwnsEventQueue);
int fd = xcb_get_file_descriptor(x11->xcb_conn);
struct wl_event_loop *ev = wl_display_get_event_loop(display);
int events = WL_EVENT_READABLE | WL_EVENT_ERROR | WL_EVENT_HANGUP;
x11->event_source = wl_event_loop_add_fd(ev, fd, events, x11_event, x11);
if (!x11->event_source) {
wlr_log(L_ERROR, "Could not create event source");
goto error_x11;
}
x11->frame_timer = wl_event_loop_add_timer(ev, signal_frame, x11);
x11->screen = xcb_setup_roots_iterator(xcb_get_setup(x11->xcb_conn)).data;
if (!wlr_egl_init(&x11->egl, EGL_PLATFORM_X11_KHR,
x11->screen->root_visual, x11->xlib_conn)) {
goto error_event;
}
wlr_input_device_init(&x11->keyboard_dev, WLR_INPUT_DEVICE_KEYBOARD,
NULL, "X11 keyboard", 0, 0);
wlr_keyboard_init(&x11->keyboard, NULL);
x11->keyboard_dev.keyboard = &x11->keyboard;
wlr_input_device_init(&x11->pointer_dev, WLR_INPUT_DEVICE_POINTER,
NULL, "X11 pointer", 0, 0);
wlr_pointer_init(&x11->pointer, NULL);
x11->pointer_dev.pointer = &x11->pointer;
return &x11->backend;
error_event:
wl_event_source_remove(x11->event_source);
error_x11:
xcb_disconnect(x11->xcb_conn);
XCloseDisplay(x11->xlib_conn);
free(x11);
return NULL;
}
static bool wlr_x11_backend_start(struct wlr_backend *backend) { static bool wlr_x11_backend_start(struct wlr_backend *backend) {
struct wlr_x11_backend *x11 = (struct wlr_x11_backend *)backend; struct wlr_x11_backend *x11 = (struct wlr_x11_backend *)backend;
struct wlr_x11_output *output = &x11->output; struct wlr_x11_output *output = &x11->output;
@ -306,8 +243,10 @@ static void wlr_x11_backend_destroy(struct wlr_backend *backend) {
struct wlr_x11_output *output = &x11->output; struct wlr_x11_output *output = &x11->output;
wlr_output_destroy(&output->wlr_output); wlr_output_destroy(&output->wlr_output);
wl_list_remove(&x11->display_destroy.link);
wl_event_source_remove(x11->frame_timer); wl_event_source_remove(x11->frame_timer);
wlr_egl_free(&x11->egl); wlr_egl_finish(&x11->egl);
xcb_disconnect(x11->xcb_conn); xcb_disconnect(x11->xcb_conn);
free(x11); free(x11);
@ -328,6 +267,78 @@ static struct wlr_backend_impl backend_impl = {
.get_egl = wlr_x11_backend_get_egl, .get_egl = wlr_x11_backend_get_egl,
}; };
static void handle_display_destroy(struct wl_listener *listener, void *data) {
struct wlr_x11_backend *x11 =
wl_container_of(listener, x11, display_destroy);
wlr_x11_backend_destroy(&x11->backend);
}
struct wlr_backend *wlr_x11_backend_create(struct wl_display *display,
const char *x11_display) {
struct wlr_x11_backend *x11 = calloc(1, sizeof(*x11));
if (!x11) {
return NULL;
}
wlr_backend_init(&x11->backend, &backend_impl);
x11->wl_display = display;
x11->xlib_conn = XOpenDisplay(x11_display);
if (!x11->xlib_conn) {
wlr_log(L_ERROR, "Failed to open X connection");
return NULL;
}
x11->xcb_conn = XGetXCBConnection(x11->xlib_conn);
if (!x11->xcb_conn || xcb_connection_has_error(x11->xcb_conn)) {
wlr_log(L_ERROR, "Failed to open xcb connection");
goto error_x11;
}
XSetEventQueueOwner(x11->xlib_conn, XCBOwnsEventQueue);
int fd = xcb_get_file_descriptor(x11->xcb_conn);
struct wl_event_loop *ev = wl_display_get_event_loop(display);
int events = WL_EVENT_READABLE | WL_EVENT_ERROR | WL_EVENT_HANGUP;
x11->event_source = wl_event_loop_add_fd(ev, fd, events, x11_event, x11);
if (!x11->event_source) {
wlr_log(L_ERROR, "Could not create event source");
goto error_x11;
}
x11->frame_timer = wl_event_loop_add_timer(ev, signal_frame, x11);
x11->screen = xcb_setup_roots_iterator(xcb_get_setup(x11->xcb_conn)).data;
if (!wlr_egl_init(&x11->egl, EGL_PLATFORM_X11_KHR,
x11->screen->root_visual, x11->xlib_conn)) {
goto error_event;
}
wlr_input_device_init(&x11->keyboard_dev, WLR_INPUT_DEVICE_KEYBOARD,
NULL, "X11 keyboard", 0, 0);
wlr_keyboard_init(&x11->keyboard, NULL);
x11->keyboard_dev.keyboard = &x11->keyboard;
wlr_input_device_init(&x11->pointer_dev, WLR_INPUT_DEVICE_POINTER,
NULL, "X11 pointer", 0, 0);
wlr_pointer_init(&x11->pointer, NULL);
x11->pointer_dev.pointer = &x11->pointer;
x11->display_destroy.notify = handle_display_destroy;
wl_display_add_destroy_listener(display, &x11->display_destroy);
return &x11->backend;
error_event:
wl_event_source_remove(x11->event_source);
error_x11:
xcb_disconnect(x11->xcb_conn);
XCloseDisplay(x11->xlib_conn);
free(x11);
return NULL;
}
static bool output_set_custom_mode(struct wlr_output *wlr_output, int32_t width, static bool output_set_custom_mode(struct wlr_output *wlr_output, int32_t width,
int32_t height, int32_t refresh) { int32_t height, int32_t refresh) {
struct wlr_x11_output *output = (struct wlr_x11_output *)wlr_output; struct wlr_x11_output *output = (struct wlr_x11_output *)wlr_output;

View file

@ -91,6 +91,7 @@ struct wlr_drm_backend {
struct wl_display *display; struct wl_display *display;
struct wl_event_source *drm_event; struct wl_event_source *drm_event;
struct wl_listener display_destroy;
struct wl_listener session_signal; struct wl_listener session_signal;
struct wl_listener drm_invalidated; struct wl_listener drm_invalidated;

View file

@ -16,6 +16,7 @@ struct wlr_libinput_backend {
struct libinput *libinput_context; struct libinput *libinput_context;
struct wl_event_source *input_event; struct wl_event_source *input_event;
struct wl_listener display_destroy;
struct wl_listener session_signal; struct wl_listener session_signal;
struct wlr_list wlr_device_lists; // list of struct wl_list struct wlr_list wlr_device_lists; // list of struct wl_list

View file

@ -22,6 +22,7 @@ struct wlr_wl_backend {
struct wl_list outputs; struct wl_list outputs;
struct wlr_egl egl; struct wlr_egl egl;
size_t requested_outputs; size_t requested_outputs;
struct wl_listener local_display_destroy;
/* remote state */ /* remote state */
struct wl_display *remote_display; struct wl_display *remote_display;
struct wl_event_source *remote_display_src; struct wl_event_source *remote_display_src;

View file

@ -51,6 +51,8 @@ struct wlr_x11_backend {
// The time we last received an event // The time we last received an event
xcb_timestamp_t time; xcb_timestamp_t time;
struct wl_listener display_destroy;
}; };
#endif #endif

View file

@ -33,6 +33,8 @@ struct wlr_session {
struct wl_event_source *udev_event; struct wl_event_source *udev_event;
struct wl_list devices; struct wl_list devices;
struct wl_listener display_destroy;
}; };
/* /*

View file

@ -34,8 +34,4 @@ struct wl_global *wlr_output_create_global(struct wlr_output *wlr_output,
struct wl_display *display); struct wl_display *display);
void wlr_output_destroy_global(struct wlr_output *wlr_output); void wlr_output_destroy_global(struct wlr_output *wlr_output);
void wlr_output_transform_apply_to_box(enum wl_output_transform transform,
struct wlr_box *box, struct wlr_box *dest);
enum wl_output_transform wlr_output_transform_invert(enum wl_output_transform);
#endif #endif

View file

@ -4,6 +4,7 @@
#include <EGL/egl.h> #include <EGL/egl.h>
#include <EGL/eglext.h> #include <EGL/eglext.h>
#include <stdbool.h> #include <stdbool.h>
#include <wayland-server.h>
struct wlr_egl { struct wlr_egl {
EGLDisplay display; EGLDisplay display;
@ -27,7 +28,7 @@ bool wlr_egl_init(struct wlr_egl *egl, EGLenum platform, EGLint visual_id, void
* Frees all related egl resources, makes the context not-current and * Frees all related egl resources, makes the context not-current and
* unbinds a bound wayland display. * unbinds a bound wayland display.
*/ */
void wlr_egl_free(struct wlr_egl *egl); void wlr_egl_finish(struct wlr_egl *egl);
/** /**
* Binds the given display to the egl instance. * Binds the given display to the egl instance.

View file

@ -10,6 +10,8 @@ void wlr_matrix_rotate(float (*output)[16], float radians);
void wlr_matrix_mul(const float (*x)[16], const float (*y)[16], float (*product)[16]); void wlr_matrix_mul(const float (*x)[16], const float (*y)[16], float (*product)[16]);
enum wl_output_transform; enum wl_output_transform;
void wlr_matrix_transform(float mat[static 16],
enum wl_output_transform transform);
void wlr_matrix_texture(float mat[static 16], int32_t width, int32_t height, void wlr_matrix_texture(float mat[static 16], int32_t width, int32_t height,
enum wl_output_transform transform); enum wl_output_transform transform);

View file

@ -18,4 +18,8 @@ bool wlr_box_contains_point(struct wlr_box *box, double x, double y);
bool wlr_box_empty(struct wlr_box *box); bool wlr_box_empty(struct wlr_box *box);
enum wl_output_transform;
void wlr_box_transform(struct wlr_box *box, enum wl_output_transform transform,
struct wlr_box *dest);
#endif #endif

View file

@ -9,7 +9,8 @@ struct wlr_compositor {
struct wl_list wl_resources; struct wl_list wl_resources;
struct wlr_renderer *renderer; struct wlr_renderer *renderer;
struct wl_list surfaces; struct wl_list surfaces;
struct wl_listener destroy_surface_listener;
struct wl_listener display_destroy;
struct { struct {
struct wl_signal create_surface; struct wl_signal create_surface;
@ -20,8 +21,4 @@ void wlr_compositor_destroy(struct wlr_compositor *wlr_compositor);
struct wlr_compositor *wlr_compositor_create(struct wl_display *display, struct wlr_compositor *wlr_compositor_create(struct wl_display *display,
struct wlr_renderer *renderer); struct wlr_renderer *renderer);
struct wlr_surface;
void wl_compositor_surface_destroyed(struct wlr_compositor *wlr_compositor,
struct wlr_surface *surface);
#endif #endif

View file

@ -15,6 +15,8 @@ wlr_touch_grab_interface wlr_data_device_touch_drag_interface;
struct wlr_data_device_manager { struct wlr_data_device_manager {
struct wl_global *global; struct wl_global *global;
struct wl_listener display_destroy;
}; };
struct wlr_data_offer { struct wlr_data_offer {

View file

@ -5,7 +5,9 @@
struct wlr_gamma_control_manager { struct wlr_gamma_control_manager {
struct wl_global *wl_global; struct wl_global *wl_global;
struct wl_list controls; // list of wlr_gamma_control struct wl_list controls; // wlr_gamma_control::link
struct wl_listener display_destroy;
void *data; void *data;
}; };

View file

@ -77,6 +77,8 @@ struct wlr_output {
// the output position in layout space reported to clients // the output position in layout space reported to clients
int32_t lx, ly; int32_t lx, ly;
struct wl_listener display_destroy;
void *data; void *data;
}; };
@ -115,4 +117,6 @@ bool wlr_output_cursor_move(struct wlr_output_cursor *cursor,
double x, double y); double x, double y);
void wlr_output_cursor_destroy(struct wlr_output_cursor *cursor); void wlr_output_cursor_destroy(struct wlr_output_cursor *cursor);
enum wl_output_transform wlr_output_transform_invert(enum wl_output_transform);
#endif #endif

View file

@ -5,6 +5,9 @@
struct wlr_screenshooter { struct wlr_screenshooter {
struct wl_global *wl_global; struct wl_global *wl_global;
struct wlr_renderer *renderer; struct wlr_renderer *renderer;
struct wl_list screenshots; // wlr_screenshot::link
struct wl_listener display_destroy;
void *data; void *data;
}; };
@ -12,6 +15,7 @@ struct wlr_screenshooter {
struct wlr_screenshot { struct wlr_screenshot {
struct wl_resource *resource; struct wl_resource *resource;
struct wl_resource *output_resource; struct wl_resource *output_resource;
struct wl_list link;
struct wlr_output *output; struct wlr_output *output;
struct wlr_screenshooter *screenshooter; struct wlr_screenshooter *screenshooter;

View file

@ -184,6 +184,7 @@ struct wlr_seat {
struct wlr_seat_keyboard_state keyboard_state; struct wlr_seat_keyboard_state keyboard_state;
struct wlr_seat_touch_state touch_state; struct wlr_seat_touch_state touch_state;
struct wl_listener display_destroy;
struct wl_listener selection_data_source_destroy; struct wl_listener selection_data_source_destroy;
struct { struct {

View file

@ -33,6 +33,8 @@ struct wlr_server_decoration_manager {
uint32_t default_mode; // enum wlr_server_decoration_manager_mode uint32_t default_mode; // enum wlr_server_decoration_manager_mode
struct wl_listener display_destroy;
struct { struct {
struct wl_signal new_decoration; struct wl_signal new_decoration;
} events; } events;

View file

@ -12,6 +12,8 @@ struct wlr_wl_shell {
struct wl_list popup_grabs; struct wl_list popup_grabs;
uint32_t ping_timeout; uint32_t ping_timeout;
struct wl_listener display_destroy;
struct { struct {
struct wl_signal new_surface; struct wl_signal new_surface;
} events; } events;

View file

@ -11,6 +11,8 @@ struct wlr_xdg_shell_v6 {
struct wl_list popup_grabs; struct wl_list popup_grabs;
uint32_t ping_timeout; uint32_t ping_timeout;
struct wl_listener display_destroy;
struct { struct {
struct wl_signal new_surface; struct wl_signal new_surface;
} events; } events;

View file

@ -25,7 +25,8 @@ struct wlr_xwayland {
time_t server_start; time_t server_start;
struct wl_event_source *sigusr1_source; struct wl_event_source *sigusr1_source;
struct wl_listener destroy_listener; struct wl_listener client_destroy;
struct wl_listener display_destroy;
struct wlr_xwm *xwm; struct wlr_xwm *xwm;
struct wlr_xwayland_cursor *cursor; struct wlr_xwayland_cursor *cursor;

View file

@ -141,7 +141,7 @@ error:
return false; return false;
} }
void wlr_egl_free(struct wlr_egl *egl) { void wlr_egl_finish(struct wlr_egl *egl) {
eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (egl->wl_display && eglUnbindWaylandDisplayWL) { if (egl->wl_display && eglUnbindWaylandDisplayWL) {
eglUnbindWaylandDisplayWL(egl->display, egl->wl_display); eglUnbindWaylandDisplayWL(egl->display, egl->wl_display);

View file

@ -86,38 +86,55 @@ void wlr_matrix_mul(const float (*x)[16], const float (*y)[16], float (*product)
static const float transforms[][4] = { static const float transforms[][4] = {
[WL_OUTPUT_TRANSFORM_NORMAL] = { [WL_OUTPUT_TRANSFORM_NORMAL] = {
1.0f, 0.0f, 1.0f, 0.0f,
0.0f, -1.0f, 0.0f, 1.0f,
}, },
[WL_OUTPUT_TRANSFORM_90] = { [WL_OUTPUT_TRANSFORM_90] = {
0.0f, -1.0f, 0.0f, -1.0f,
-1.0f, 0.0f, 1.0f, 0.0f,
}, },
[WL_OUTPUT_TRANSFORM_180] = { [WL_OUTPUT_TRANSFORM_180] = {
-1.0f, 0.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.0f, -1.0f,
}, },
[WL_OUTPUT_TRANSFORM_270] = { [WL_OUTPUT_TRANSFORM_270] = {
0.0f, 1.0f, 0.0f, 1.0f,
1.0f, 0.0f, -1.0f, 0.0f,
}, },
[WL_OUTPUT_TRANSFORM_FLIPPED] = { [WL_OUTPUT_TRANSFORM_FLIPPED] = {
-1.0f, 0.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f, 1.0f,
}, },
[WL_OUTPUT_TRANSFORM_FLIPPED_90] = { [WL_OUTPUT_TRANSFORM_FLIPPED_90] = {
0.0f, 1.0f, 0.0f, -1.0f,
-1.0f, 0.0f, -1.0f, 0.0f,
}, },
[WL_OUTPUT_TRANSFORM_FLIPPED_180] = { [WL_OUTPUT_TRANSFORM_FLIPPED_180] = {
1.0f, 0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f, -1.0f,
}, },
[WL_OUTPUT_TRANSFORM_FLIPPED_270] = { [WL_OUTPUT_TRANSFORM_FLIPPED_270] = {
0.0f, -1.0f, 0.0f, 1.0f,
1.0f, 0.0f, 1.0f, 0.0f,
}, },
}; };
void wlr_matrix_transform(float mat[static 16],
enum wl_output_transform transform) {
memset(mat, 0, sizeof(*mat) * 16);
const float *t = transforms[transform];
// Rotation + reflection
mat[0] = t[0];
mat[1] = t[1];
mat[4] = t[2];
mat[5] = t[3];
// Identity
mat[10] = 1.0f;
mat[15] = 1.0f;
}
// Equivilent to glOrtho(0, width, 0, height, 1, -1) with the transform applied // Equivilent to glOrtho(0, width, 0, height, 1, -1) with the transform applied
void wlr_matrix_texture(float mat[static 16], int32_t width, int32_t height, void wlr_matrix_texture(float mat[static 16], int32_t width, int32_t height,
enum wl_output_transform transform) { enum wl_output_transform transform) {
@ -127,11 +144,11 @@ void wlr_matrix_texture(float mat[static 16], int32_t width, int32_t height,
float x = 2.0f / width; float x = 2.0f / width;
float y = 2.0f / height; float y = 2.0f / height;
// Rotation + relection // Rotation + reflection
mat[0] = x * t[0]; mat[0] = x * t[0];
mat[1] = x * t[1]; mat[1] = x * t[1];
mat[4] = y * t[2]; mat[4] = y * -t[2];
mat[5] = y * t[3]; mat[5] = y * -t[3];
// Translation // Translation
mat[3] = -copysign(1.0f, mat[0] + mat[1]); mat[3] = -copysign(1.0f, mat[0] + mat[1]);

View file

@ -294,10 +294,8 @@ static bool view_at(struct roots_view *view, double lx, double ly,
struct wlr_surface_state *state = view->wlr_surface->current; struct wlr_surface_state *state = view->wlr_surface->current;
struct wlr_box box = { struct wlr_box box = {
.x = 0, .x = 0, .y = 0,
.y = 0, .width = state->width, .height = state->height,
.width = state->buffer_width / state->scale,
.height = state->buffer_height / state->scale,
}; };
if (view->rotation != 0.0) { if (view->rotation != 0.0) {
// Coordinates relative to the center of the view // Coordinates relative to the center of the view

View file

@ -51,6 +51,7 @@ int main(int argc, char **argv) {
if (!wlr_backend_start(server.backend)) { if (!wlr_backend_start(server.backend)) {
wlr_log(L_ERROR, "Failed to start backend"); wlr_log(L_ERROR, "Failed to start backend");
wlr_backend_destroy(server.backend); wlr_backend_destroy(server.backend);
wl_display_destroy(server.wl_display);
return 1; return 1;
} }
@ -72,5 +73,6 @@ int main(int argc, char **argv) {
wl_display_run(server.wl_display); wl_display_run(server.wl_display);
wlr_backend_destroy(server.backend); wlr_backend_destroy(server.backend);
wl_display_destroy(server.wl_display);
return 0; return 0;
} }

View file

@ -48,24 +48,43 @@ static void render_surface(struct wlr_surface *surface,
lx, ly, lx + render_width, ly + render_height)) { lx, ly, lx + render_width, ly + render_height)) {
float matrix[16]; float matrix[16];
float translate_origin[16]; float translate_center[16];
wlr_matrix_translate(&translate_origin, wlr_matrix_translate(&translate_center,
(int)ox + render_width / 2, (int)oy + render_height / 2, 0); (int)ox + render_width / 2, (int)oy + render_height / 2, 0);
float rotate[16]; float rotate[16];
wlr_matrix_rotate(&rotate, rotation); wlr_matrix_rotate(&rotate, rotation);
float translate_center[16]; float translate_origin[16];
wlr_matrix_translate(&translate_center, -render_width / 2, wlr_matrix_translate(&translate_origin, -render_width / 2,
-render_height / 2, 0); -render_height / 2, 0);
float scale[16]; float scale[16];
wlr_matrix_scale(&scale, render_width, render_height, 1); wlr_matrix_scale(&scale, render_width, render_height, 1);
float transform[16]; float transform[16];
wlr_matrix_mul(&translate_origin, &rotate, &transform); wlr_matrix_mul(&translate_center, &rotate, &transform);
wlr_matrix_mul(&transform, &translate_center, &transform); wlr_matrix_mul(&transform, &translate_origin, &transform);
wlr_matrix_mul(&transform, &scale, &transform); wlr_matrix_mul(&transform, &scale, &transform);
if (surface->current->transform != WL_OUTPUT_TRANSFORM_NORMAL) {
float surface_translate_center[16];
wlr_matrix_translate(&surface_translate_center, 0.5, 0.5, 0);
float surface_transform[16];
wlr_matrix_transform(surface_transform,
wlr_output_transform_invert(surface->current->transform));
float surface_translate_origin[16];
wlr_matrix_translate(&surface_translate_origin, -0.5, -0.5, 0);
wlr_matrix_mul(&transform, &surface_translate_center,
&transform);
wlr_matrix_mul(&transform, &surface_transform, &transform);
wlr_matrix_mul(&transform, &surface_translate_origin,
&transform);
}
wlr_matrix_mul(&wlr_output->transform_matrix, &transform, &matrix); wlr_matrix_mul(&wlr_output->transform_matrix, &transform, &matrix);
wlr_render_with_matrix(desktop->server->renderer, surface->texture, wlr_render_with_matrix(desktop->server->renderer, surface->texture,

View file

@ -2,6 +2,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <math.h> #include <math.h>
#include <stdbool.h> #include <stdbool.h>
#include <wayland-server-protocol.h>
#include <wlr/types/wlr_box.h> #include <wlr/types/wlr_box.h>
#include <wlr/util/log.h> #include <wlr/util/log.h>
@ -65,3 +66,49 @@ bool wlr_box_contains_point(struct wlr_box *box, double x, double y) {
y >= box->y && y <= box->y + box->height; y >= box->y && y <= box->y + box->height;
} }
} }
void wlr_box_transform(struct wlr_box *box,
enum wl_output_transform transform, struct wlr_box *dest) {
if (transform % 2 == 0) {
dest->width = box->width;
dest->height = box->height;
} else {
dest->width = box->height;
dest->height = box->width;
}
switch (transform) {
case WL_OUTPUT_TRANSFORM_NORMAL:
dest->x = box->x;
dest->y = box->y;
break;
case WL_OUTPUT_TRANSFORM_90:
dest->x = box->y;
dest->y = box->width - box->x;
break;
case WL_OUTPUT_TRANSFORM_180:
dest->x = box->width - box->x;
dest->y = box->height - box->y;
break;
case WL_OUTPUT_TRANSFORM_270:
dest->x = box->height - box->y;
dest->y = box->x;
break;
case WL_OUTPUT_TRANSFORM_FLIPPED:
dest->x = box->width - box->x;
dest->y = box->y;
break;
case WL_OUTPUT_TRANSFORM_FLIPPED_90:
dest->x = box->height - box->y;
dest->y = box->width - box->x;
break;
case WL_OUTPUT_TRANSFORM_FLIPPED_180:
dest->x = box->x;
dest->y = box->height - box->y;
break;
case WL_OUTPUT_TRANSFORM_FLIPPED_270:
dest->x = box->y;
dest->y = box->x;
break;
}
}

View file

@ -78,6 +78,10 @@ static void wl_compositor_bind(struct wl_client *wl_client, void *data,
} }
void wlr_compositor_destroy(struct wlr_compositor *compositor) { void wlr_compositor_destroy(struct wlr_compositor *compositor) {
if (compositor == NULL) {
return;
}
wl_list_remove(&compositor->display_destroy.link);
wl_global_destroy(compositor->wl_global); wl_global_destroy(compositor->wl_global);
free(compositor); free(compositor);
} }
@ -151,6 +155,12 @@ static void subcompositor_bind(struct wl_client *client, void *data,
compositor, NULL); compositor, NULL);
} }
static void handle_display_destroy(struct wl_listener *listener, void *data) {
struct wlr_compositor *compositor =
wl_container_of(listener, compositor, display_destroy);
wlr_compositor_destroy(compositor);
}
struct wlr_compositor *wlr_compositor_create(struct wl_display *display, struct wlr_compositor *wlr_compositor_create(struct wl_display *display,
struct wlr_renderer *renderer) { struct wlr_renderer *renderer) {
struct wlr_compositor *compositor = struct wlr_compositor *compositor =
@ -162,7 +172,11 @@ struct wlr_compositor *wlr_compositor_create(struct wl_display *display,
struct wl_global *compositor_global = wl_global_create(display, struct wl_global *compositor_global = wl_global_create(display,
&wl_compositor_interface, 4, compositor, wl_compositor_bind); &wl_compositor_interface, 4, compositor, wl_compositor_bind);
if (!compositor_global) {
wlr_log_errno(L_ERROR, "Could not allocate compositor global");
free(compositor);
return NULL;
}
compositor->wl_global = compositor_global; compositor->wl_global = compositor_global;
compositor->renderer = renderer; compositor->renderer = renderer;
@ -173,5 +187,8 @@ struct wlr_compositor *wlr_compositor_create(struct wl_display *display,
wl_list_init(&compositor->surfaces); wl_list_init(&compositor->surfaces);
wl_signal_init(&compositor->events.create_surface); wl_signal_init(&compositor->events.create_surface);
compositor->display_destroy.notify = handle_display_destroy;
wl_display_add_destroy_listener(display, &compositor->display_destroy);
return compositor; return compositor;
} }

View file

@ -949,6 +949,21 @@ static void data_device_manager_bind(struct wl_client *client,
NULL, NULL); NULL, NULL);
} }
void wlr_data_device_manager_destroy(struct wlr_data_device_manager *manager) {
if (!manager) {
return;
}
wl_list_remove(&manager->display_destroy.link);
wl_global_destroy(manager->global);
free(manager);
}
static void handle_display_destroy(struct wl_listener *listener, void *data) {
struct wlr_data_device_manager *manager =
wl_container_of(listener, manager, display_destroy);
wlr_data_device_manager_destroy(manager);
}
struct wlr_data_device_manager *wlr_data_device_manager_create( struct wlr_data_device_manager *wlr_data_device_manager_create(
struct wl_display *display) { struct wl_display *display) {
struct wlr_data_device_manager *manager = struct wlr_data_device_manager *manager =
@ -967,13 +982,8 @@ struct wlr_data_device_manager *wlr_data_device_manager_create(
return NULL; return NULL;
} }
manager->display_destroy.notify = handle_display_destroy;
wl_display_add_destroy_listener(display, &manager->display_destroy);
return manager; return manager;
} }
void wlr_data_device_manager_destroy(struct wlr_data_device_manager *manager) {
if (!manager) {
return;
}
wl_global_destroy(manager->global);
free(manager);
}

View file

@ -12,6 +12,9 @@ static void resource_destroy(struct wl_client *client,
} }
static void gamma_control_destroy(struct wlr_gamma_control *gamma_control) { static void gamma_control_destroy(struct wlr_gamma_control *gamma_control) {
if (gamma_control == NULL) {
return;
}
wl_signal_emit(&gamma_control->events.destroy, gamma_control); wl_signal_emit(&gamma_control->events.destroy, gamma_control);
wl_list_remove(&gamma_control->output_destroy_listener.link); wl_list_remove(&gamma_control->output_destroy_listener.link);
wl_resource_set_user_data(gamma_control->resource, NULL); wl_resource_set_user_data(gamma_control->resource, NULL);
@ -67,7 +70,7 @@ static const struct gamma_control_interface gamma_control_impl = {
static void gamma_control_manager_get_gamma_control(struct wl_client *client, static void gamma_control_manager_get_gamma_control(struct wl_client *client,
struct wl_resource *gamma_control_manager_resource, uint32_t id, struct wl_resource *gamma_control_manager_resource, uint32_t id,
struct wl_resource *output_resource) { struct wl_resource *output_resource) {
struct wlr_gamma_control_manager *gamma_control_manager = struct wlr_gamma_control_manager *manager =
wl_resource_get_user_data(gamma_control_manager_resource); wl_resource_get_user_data(gamma_control_manager_resource);
struct wlr_output *output = wl_resource_get_user_data(output_resource); struct wlr_output *output = wl_resource_get_user_data(output_resource);
@ -99,7 +102,7 @@ static void gamma_control_manager_get_gamma_control(struct wl_client *client,
gamma_control->output_destroy_listener.notify = gamma_control->output_destroy_listener.notify =
gamma_control_handle_output_destroy; gamma_control_handle_output_destroy;
wl_list_insert(&gamma_control_manager->controls, &gamma_control->link); wl_list_insert(&manager->controls, &gamma_control->link);
gamma_control_send_gamma_size(gamma_control->resource, gamma_control_send_gamma_size(gamma_control->resource,
wlr_output_get_gamma_size(output)); wlr_output_get_gamma_size(output));
@ -111,8 +114,8 @@ static struct gamma_control_manager_interface gamma_control_manager_impl = {
static void gamma_control_manager_bind(struct wl_client *client, void *data, static void gamma_control_manager_bind(struct wl_client *client, void *data,
uint32_t version, uint32_t id) { uint32_t version, uint32_t id) {
struct wlr_gamma_control_manager *gamma_control_manager = data; struct wlr_gamma_control_manager *manager = data;
assert(client && gamma_control_manager); assert(client && manager);
struct wl_resource *resource = wl_resource_create(client, struct wl_resource *resource = wl_resource_create(client,
&gamma_control_manager_interface, version, id); &gamma_control_manager_interface, version, id);
@ -121,41 +124,49 @@ static void gamma_control_manager_bind(struct wl_client *client, void *data,
return; return;
} }
wl_resource_set_implementation(resource, &gamma_control_manager_impl, wl_resource_set_implementation(resource, &gamma_control_manager_impl,
gamma_control_manager, NULL); manager, NULL);
}
void wlr_gamma_control_manager_destroy(
struct wlr_gamma_control_manager *manager) {
if (!manager) {
return;
}
wl_list_remove(&manager->display_destroy.link);
struct wlr_gamma_control *gamma_control, *tmp;
wl_list_for_each_safe(gamma_control, tmp, &manager->controls, link) {
gamma_control_destroy(gamma_control);
}
wl_global_destroy(manager->wl_global);
free(manager);
}
static void handle_display_destroy(struct wl_listener *listener, void *data) {
struct wlr_gamma_control_manager *manager =
wl_container_of(listener, manager, display_destroy);
wlr_gamma_control_manager_destroy(manager);
} }
struct wlr_gamma_control_manager *wlr_gamma_control_manager_create( struct wlr_gamma_control_manager *wlr_gamma_control_manager_create(
struct wl_display *display) { struct wl_display *display) {
struct wlr_gamma_control_manager *gamma_control_manager = struct wlr_gamma_control_manager *manager =
calloc(1, sizeof(struct wlr_gamma_control_manager)); calloc(1, sizeof(struct wlr_gamma_control_manager));
if (!gamma_control_manager) { if (!manager) {
return NULL; return NULL;
} }
struct wl_global *wl_global = wl_global_create(display, struct wl_global *wl_global = wl_global_create(display,
&gamma_control_manager_interface, 1, gamma_control_manager, &gamma_control_manager_interface, 1, manager,
gamma_control_manager_bind); gamma_control_manager_bind);
if (!wl_global) { if (!wl_global) {
free(gamma_control_manager); free(manager);
return NULL; return NULL;
} }
gamma_control_manager->wl_global = wl_global; manager->wl_global = wl_global;
wl_list_init(&gamma_control_manager->controls); wl_list_init(&manager->controls);
return gamma_control_manager; manager->display_destroy.notify = handle_display_destroy;
} wl_display_add_destroy_listener(display, &manager->display_destroy);
void wlr_gamma_control_manager_destroy( return manager;
struct wlr_gamma_control_manager *gamma_control_manager) {
if (!gamma_control_manager) {
return;
}
struct wlr_gamma_control *gamma_control, *tmp;
wl_list_for_each_safe(gamma_control, tmp, &gamma_control_manager->controls,
link) {
gamma_control_destroy(gamma_control);
}
// TODO: this segfault (wl_display->registry_resource_list is not init)
// wl_global_destroy(gamma_control_manager->wl_global);
free(gamma_control_manager);
} }

View file

@ -112,6 +112,12 @@ static void wl_output_bind(struct wl_client *wl_client, void *data,
wl_output_send_to_resource(wl_resource); wl_output_send_to_resource(wl_resource);
} }
static void handle_display_destroy(struct wl_listener *listener, void *data) {
struct wlr_output *output =
wl_container_of(listener, output, display_destroy);
wlr_output_destroy_global(output);
}
struct wl_global *wlr_output_create_global(struct wlr_output *wlr_output, struct wl_global *wlr_output_create_global(struct wlr_output *wlr_output,
struct wl_display *display) { struct wl_display *display) {
if (wlr_output->wl_global != NULL) { if (wlr_output->wl_global != NULL) {
@ -120,6 +126,10 @@ struct wl_global *wlr_output_create_global(struct wlr_output *wlr_output,
struct wl_global *wl_global = wl_global_create(display, struct wl_global *wl_global = wl_global_create(display,
&wl_output_interface, 3, wlr_output, wl_output_bind); &wl_output_interface, 3, wlr_output, wl_output_bind);
wlr_output->wl_global = wl_global; wlr_output->wl_global = wl_global;
wlr_output->display_destroy.notify = handle_display_destroy;
wl_display_add_destroy_listener(display, &wlr_output->display_destroy);
return wl_global; return wl_global;
} }
@ -127,6 +137,7 @@ void wlr_output_destroy_global(struct wlr_output *wlr_output) {
if (wlr_output->wl_global == NULL) { if (wlr_output->wl_global == NULL) {
return; return;
} }
wl_list_remove(&wlr_output->display_destroy.link);
struct wl_resource *resource, *tmp; struct wl_resource *resource, *tmp;
wl_resource_for_each_safe(resource, tmp, &wlr_output->wl_resources) { wl_resource_for_each_safe(resource, tmp, &wlr_output->wl_resources) {
struct wl_list *link = wl_resource_get_link(resource); struct wl_list *link = wl_resource_get_link(resource);
@ -702,52 +713,6 @@ void wlr_output_cursor_destroy(struct wlr_output_cursor *cursor) {
free(cursor); free(cursor);
} }
void wlr_output_transform_apply_to_box(enum wl_output_transform transform,
struct wlr_box *box, struct wlr_box *dest) {
if (transform % 2 == 0) {
dest->width = box->width;
dest->height = box->height;
} else {
dest->width = box->height;
dest->height = box->width;
}
switch (transform) {
case WL_OUTPUT_TRANSFORM_NORMAL:
dest->x = box->x;
dest->y = box->y;
break;
case WL_OUTPUT_TRANSFORM_90:
dest->x = box->y;
dest->y = box->width - box->x;
break;
case WL_OUTPUT_TRANSFORM_180:
dest->x = box->width - box->x;
dest->y = box->height - box->y;
break;
case WL_OUTPUT_TRANSFORM_270:
dest->x = box->height - box->y;
dest->y = box->x;
break;
case WL_OUTPUT_TRANSFORM_FLIPPED:
dest->x = box->width - box->x;
dest->y = box->y;
break;
case WL_OUTPUT_TRANSFORM_FLIPPED_90:
dest->x = box->y;
dest->y = box->x;
break;
case WL_OUTPUT_TRANSFORM_FLIPPED_180:
dest->x = box->x;
dest->y = box->height - box->y;
break;
case WL_OUTPUT_TRANSFORM_FLIPPED_270:
dest->x = box->height - box->y;
dest->y = box->width - box->x;
break;
}
}
enum wl_output_transform wlr_output_transform_invert( enum wl_output_transform wlr_output_transform_invert(
enum wl_output_transform transform) { enum wl_output_transform transform) {
if ((transform & WL_OUTPUT_TRANSFORM_90) && if ((transform & WL_OUTPUT_TRANSFORM_90) &&

View file

@ -26,6 +26,21 @@ struct screenshot_state {
struct wl_listener frame_listener; struct wl_listener frame_listener;
}; };
static void screenshot_destroy(struct wlr_screenshot *screenshot) {
wl_list_remove(&screenshot->link);
wl_resource_set_user_data(screenshot->resource, NULL);
free(screenshot);
}
static void handle_screenshot_resource_destroy(
struct wl_resource *screenshot_resource) {
struct wlr_screenshot *screenshot =
wl_resource_get_user_data(screenshot_resource);
if (screenshot != NULL) {
screenshot_destroy(screenshot);
}
}
static void output_frame_notify(struct wl_listener *listener, void *_data) { static void output_frame_notify(struct wl_listener *listener, void *_data) {
struct screenshot_state *state = wl_container_of(listener, state, struct screenshot_state *state = wl_container_of(listener, state,
frame_listener); frame_listener);
@ -102,7 +117,8 @@ static void screenshooter_shoot(struct wl_client *client,
return; return;
} }
wl_resource_set_implementation(screenshot->resource, NULL, screenshot, wl_resource_set_implementation(screenshot->resource, NULL, screenshot,
NULL); handle_screenshot_resource_destroy);
wl_list_insert(&screenshooter->screenshots, &screenshot->link);
wlr_log(L_DEBUG, "new screenshot %p (res %p)", screenshot, wlr_log(L_DEBUG, "new screenshot %p (res %p)", screenshot,
screenshot->resource); screenshot->resource);
@ -144,6 +160,25 @@ static void screenshooter_bind(struct wl_client *wl_client, void *data,
screenshooter, NULL); screenshooter, NULL);
} }
void wlr_screenshooter_destroy(struct wlr_screenshooter *screenshooter) {
if (!screenshooter) {
return;
}
wl_list_remove(&screenshooter->display_destroy.link);
struct wlr_screenshot *screenshot, *tmp;
wl_list_for_each_safe(screenshot, tmp, &screenshooter->screenshots, link) {
screenshot_destroy(screenshot);
}
wl_global_destroy(screenshooter->wl_global);
free(screenshooter);
}
static void handle_display_destroy(struct wl_listener *listener, void *data) {
struct wlr_screenshooter *screenshooter =
wl_container_of(listener, screenshooter, display_destroy);
wlr_screenshooter_destroy(screenshooter);
}
struct wlr_screenshooter *wlr_screenshooter_create(struct wl_display *display, struct wlr_screenshooter *wlr_screenshooter_create(struct wl_display *display,
struct wlr_renderer *renderer) { struct wlr_renderer *renderer) {
struct wlr_screenshooter *screenshooter = struct wlr_screenshooter *screenshooter =
@ -153,6 +188,11 @@ struct wlr_screenshooter *wlr_screenshooter_create(struct wl_display *display,
} }
screenshooter->renderer = renderer; screenshooter->renderer = renderer;
wl_list_init(&screenshooter->screenshots);
screenshooter->display_destroy.notify = handle_display_destroy;
wl_display_add_destroy_listener(display, &screenshooter->display_destroy);
screenshooter->wl_global = wl_global_create(display, screenshooter->wl_global = wl_global_create(display,
&orbital_screenshooter_interface, 1, screenshooter, screenshooter_bind); &orbital_screenshooter_interface, 1, screenshooter, screenshooter_bind);
if (screenshooter->wl_global == NULL) { if (screenshooter->wl_global == NULL) {
@ -162,12 +202,3 @@ struct wlr_screenshooter *wlr_screenshooter_create(struct wl_display *display,
return screenshooter; return screenshooter;
} }
void wlr_screenshooter_destroy(struct wlr_screenshooter *screenshooter) {
if (!screenshooter) {
return;
}
// TODO: this segfault (wl_display->registry_resource_list is not init)
// wl_global_destroy(screenshooter->wl_global);
free(screenshooter);
}

View file

@ -346,6 +346,34 @@ static const struct wlr_touch_grab_interface default_touch_grab_impl = {
}; };
void wlr_seat_destroy(struct wlr_seat *wlr_seat) {
if (!wlr_seat) {
return;
}
wl_list_remove(&wlr_seat->display_destroy.link);
struct wlr_seat_client *client, *tmp;
wl_list_for_each_safe(client, tmp, &wlr_seat->clients, link) {
// will destroy other resources as well
wl_resource_destroy(client->wl_resource);
}
wl_global_destroy(wlr_seat->wl_global);
free(wlr_seat->pointer_state.default_grab);
free(wlr_seat->keyboard_state.default_grab);
free(wlr_seat->touch_state.default_grab);
free(wlr_seat->data_device);
free(wlr_seat->name);
free(wlr_seat);
}
static void handle_display_destroy(struct wl_listener *listener, void *data) {
struct wlr_seat *seat =
wl_container_of(listener, seat, display_destroy);
wlr_seat_destroy(seat);
}
struct wlr_seat *wlr_seat_create(struct wl_display *display, const char *name) { struct wlr_seat *wlr_seat_create(struct wl_display *display, const char *name) {
struct wlr_seat *wlr_seat = calloc(1, sizeof(struct wlr_seat)); struct wlr_seat *wlr_seat = calloc(1, sizeof(struct wlr_seat));
if (!wlr_seat) { if (!wlr_seat) {
@ -427,29 +455,12 @@ struct wlr_seat *wlr_seat_create(struct wl_display *display, const char *name) {
wl_signal_init(&wlr_seat->events.touch_grab_begin); wl_signal_init(&wlr_seat->events.touch_grab_begin);
wl_signal_init(&wlr_seat->events.touch_grab_end); wl_signal_init(&wlr_seat->events.touch_grab_end);
wlr_seat->display_destroy.notify = handle_display_destroy;
wl_display_add_destroy_listener(display, &wlr_seat->display_destroy);
return wlr_seat; return wlr_seat;
} }
void wlr_seat_destroy(struct wlr_seat *wlr_seat) {
if (!wlr_seat) {
return;
}
struct wlr_seat_client *client, *tmp;
wl_list_for_each_safe(client, tmp, &wlr_seat->clients, link) {
// will destroy other resources as well
wl_resource_destroy(client->wl_resource);
}
wl_global_destroy(wlr_seat->wl_global);
free(wlr_seat->pointer_state.default_grab);
free(wlr_seat->keyboard_state.default_grab);
free(wlr_seat->touch_state.default_grab);
free(wlr_seat->data_device);
free(wlr_seat->name);
free(wlr_seat);
}
struct wlr_seat_client *wlr_seat_client_for_wl_client(struct wlr_seat *wlr_seat, struct wlr_seat_client *wlr_seat_client_for_wl_client(struct wlr_seat *wlr_seat,
struct wl_client *wl_client) { struct wl_client *wl_client) {
assert(wlr_seat); assert(wlr_seat);

View file

@ -140,6 +140,31 @@ static void server_decoration_manager_bind(struct wl_client *client, void *data,
manager->default_mode); manager->default_mode);
} }
void wlr_server_decoration_manager_destroy(
struct wlr_server_decoration_manager *manager) {
if (manager == NULL) {
return;
}
wl_list_remove(&manager->display_destroy.link);
struct wlr_server_decoration *decoration, *tmp_decoration;
wl_list_for_each_safe(decoration, tmp_decoration, &manager->decorations,
link) {
server_decoration_destroy(decoration);
}
struct wl_resource *resource, *tmp_resource;
wl_resource_for_each_safe(resource, tmp_resource, &manager->wl_resources) {
server_decoration_manager_destroy_resource(resource);
}
wl_global_destroy(manager->wl_global);
free(manager);
}
static void handle_display_destroy(struct wl_listener *listener, void *data) {
struct wlr_server_decoration_manager *manager =
wl_container_of(listener, manager, display_destroy);
wlr_server_decoration_manager_destroy(manager);
}
struct wlr_server_decoration_manager *wlr_server_decoration_manager_create( struct wlr_server_decoration_manager *wlr_server_decoration_manager_create(
struct wl_display *display) { struct wl_display *display) {
struct wlr_server_decoration_manager *manager = struct wlr_server_decoration_manager *manager =
@ -158,23 +183,9 @@ struct wlr_server_decoration_manager *wlr_server_decoration_manager_create(
wl_list_init(&manager->wl_resources); wl_list_init(&manager->wl_resources);
wl_list_init(&manager->decorations); wl_list_init(&manager->decorations);
wl_signal_init(&manager->events.new_decoration); wl_signal_init(&manager->events.new_decoration);
manager->display_destroy.notify = handle_display_destroy;
wl_display_add_destroy_listener(display, &manager->display_destroy);
return manager; return manager;
} }
void wlr_server_decoration_manager_destroy(
struct wlr_server_decoration_manager *manager) {
if (manager == NULL) {
return;
}
struct wlr_server_decoration *decoration, *tmp_decoration;
wl_list_for_each_safe(decoration, tmp_decoration, &manager->decorations,
link) {
server_decoration_destroy(decoration);
}
struct wl_resource *resource, *tmp_resource;
wl_resource_for_each_safe(resource, tmp_resource, &manager->wl_resources) {
server_decoration_manager_destroy_resource(resource);
}
wl_global_destroy(manager->wl_global);
free(manager);
}

View file

@ -564,6 +564,12 @@ static void shell_bind(struct wl_client *wl_client, void *data,
wl_list_insert(&wl_shell->wl_resources, wl_resource_get_link(wl_resource)); wl_list_insert(&wl_shell->wl_resources, wl_resource_get_link(wl_resource));
} }
static void handle_display_destroy(struct wl_listener *listener, void *data) {
struct wlr_wl_shell *wl_shell =
wl_container_of(listener, wl_shell, display_destroy);
wlr_wl_shell_destroy(wl_shell);
}
struct wlr_wl_shell *wlr_wl_shell_create(struct wl_display *display) { struct wlr_wl_shell *wlr_wl_shell_create(struct wl_display *display) {
struct wlr_wl_shell *wl_shell = calloc(1, sizeof(struct wlr_wl_shell)); struct wlr_wl_shell *wl_shell = calloc(1, sizeof(struct wlr_wl_shell));
if (!wl_shell) { if (!wl_shell) {
@ -581,6 +587,10 @@ struct wlr_wl_shell *wlr_wl_shell_create(struct wl_display *display) {
wl_list_init(&wl_shell->surfaces); wl_list_init(&wl_shell->surfaces);
wl_list_init(&wl_shell->popup_grabs); wl_list_init(&wl_shell->popup_grabs);
wl_signal_init(&wl_shell->events.new_surface); wl_signal_init(&wl_shell->events.new_surface);
wl_shell->display_destroy.notify = handle_display_destroy;
wl_display_add_destroy_listener(display, &wl_shell->display_destroy);
return wl_shell; return wl_shell;
} }
@ -588,14 +598,14 @@ void wlr_wl_shell_destroy(struct wlr_wl_shell *wlr_wl_shell) {
if (!wlr_wl_shell) { if (!wlr_wl_shell) {
return; return;
} }
wl_list_remove(&wlr_wl_shell->display_destroy.link);
struct wl_resource *resource = NULL, *temp = NULL; struct wl_resource *resource = NULL, *temp = NULL;
wl_resource_for_each_safe(resource, temp, &wlr_wl_shell->wl_resources) { wl_resource_for_each_safe(resource, temp, &wlr_wl_shell->wl_resources) {
struct wl_list *link = wl_resource_get_link(resource); // shell_destroy will remove the resource from the list
wl_list_remove(link); wl_resource_destroy(resource);
} }
// TODO: destroy surfaces // TODO: destroy surfaces
// TODO: this segfault (wl_display->registry_resource_list is not init) wl_global_destroy(wlr_wl_shell->wl_global);
// wl_global_destroy(wlr_wl_shell->wl_global);
free(wlr_wl_shell); free(wlr_wl_shell);
} }

View file

@ -1250,6 +1250,12 @@ static void xdg_shell_bind(struct wl_client *wl_client, void *data,
} }
} }
static void handle_display_destroy(struct wl_listener *listener, void *data) {
struct wlr_xdg_shell_v6 *xdg_shell =
wl_container_of(listener, xdg_shell, display_destroy);
wlr_xdg_shell_v6_destroy(xdg_shell);
}
struct wlr_xdg_shell_v6 *wlr_xdg_shell_v6_create(struct wl_display *display) { struct wlr_xdg_shell_v6 *wlr_xdg_shell_v6_create(struct wl_display *display) {
struct wlr_xdg_shell_v6 *xdg_shell = struct wlr_xdg_shell_v6 *xdg_shell =
calloc(1, sizeof(struct wlr_xdg_shell_v6)); calloc(1, sizeof(struct wlr_xdg_shell_v6));
@ -1272,6 +1278,9 @@ struct wlr_xdg_shell_v6 *wlr_xdg_shell_v6_create(struct wl_display *display) {
wl_signal_init(&xdg_shell->events.new_surface); wl_signal_init(&xdg_shell->events.new_surface);
xdg_shell->display_destroy.notify = handle_display_destroy;
wl_display_add_destroy_listener(display, &xdg_shell->display_destroy);
return xdg_shell; return xdg_shell;
} }
@ -1279,8 +1288,8 @@ void wlr_xdg_shell_v6_destroy(struct wlr_xdg_shell_v6 *xdg_shell) {
if (!xdg_shell) { if (!xdg_shell) {
return; return;
} }
// TODO: this segfault (wl_display->registry_resource_list is not init) wl_list_remove(&xdg_shell->display_destroy.link);
// wl_global_destroy(xdg_shell->wl_global); wl_global_destroy(xdg_shell->wl_global);
free(xdg_shell); free(xdg_shell);
} }

View file

@ -125,38 +125,25 @@ static void exec_xwayland(struct wlr_xwayland *wlr_xwayland) {
execvp("Xwayland", argv); execvp("Xwayland", argv);
} }
static bool wlr_xwayland_init(struct wlr_xwayland *wlr_xwayland,
struct wl_display *wl_display, struct wlr_compositor *compositor);
static void wlr_xwayland_finish(struct wlr_xwayland *wlr_xwayland);
static void xwayland_destroy_event(struct wl_listener *listener, void *data) {
struct wlr_xwayland *wlr_xwayland = wl_container_of(listener, wlr_xwayland, destroy_listener);
/* don't call client destroy */
wlr_xwayland->client = NULL;
wl_list_remove(&wlr_xwayland->destroy_listener.link);
wlr_xwayland_finish(wlr_xwayland);
if (time(NULL) - wlr_xwayland->server_start > 5) {
wlr_xwayland_init(wlr_xwayland, wlr_xwayland->wl_display,
wlr_xwayland->compositor);
}
}
static void wlr_xwayland_finish(struct wlr_xwayland *wlr_xwayland) { static void wlr_xwayland_finish(struct wlr_xwayland *wlr_xwayland) {
if (!wlr_xwayland || wlr_xwayland->display == -1) { if (!wlr_xwayland || wlr_xwayland->display == -1) {
return; return;
} }
if (wlr_xwayland->cursor != NULL) {
free(wlr_xwayland->cursor);
}
xwm_destroy(wlr_xwayland->xwm);
if (wlr_xwayland->client) { if (wlr_xwayland->client) {
wl_list_remove(&wlr_xwayland->destroy_listener.link); wl_list_remove(&wlr_xwayland->client_destroy.link);
wl_client_destroy(wlr_xwayland->client); wl_client_destroy(wlr_xwayland->client);
} }
if (wlr_xwayland->sigusr1_source) { if (wlr_xwayland->sigusr1_source) {
wl_event_source_remove(wlr_xwayland->sigusr1_source); wl_event_source_remove(wlr_xwayland->sigusr1_source);
} }
xwm_destroy(wlr_xwayland->xwm);
safe_close(wlr_xwayland->x_fd[0]); safe_close(wlr_xwayland->x_fd[0]);
safe_close(wlr_xwayland->x_fd[1]); safe_close(wlr_xwayland->x_fd[1]);
safe_close(wlr_xwayland->wl_fd[0]); safe_close(wlr_xwayland->wl_fd[0]);
@ -164,6 +151,8 @@ static void wlr_xwayland_finish(struct wlr_xwayland *wlr_xwayland) {
safe_close(wlr_xwayland->wm_fd[0]); safe_close(wlr_xwayland->wm_fd[0]);
safe_close(wlr_xwayland->wm_fd[1]); safe_close(wlr_xwayland->wm_fd[1]);
wl_list_remove(&wlr_xwayland->display_destroy.link);
unlink_display_sockets(wlr_xwayland->display); unlink_display_sockets(wlr_xwayland->display);
wlr_xwayland->display = -1; wlr_xwayland->display = -1;
unsetenv("DISPLAY"); unsetenv("DISPLAY");
@ -173,6 +162,39 @@ static void wlr_xwayland_finish(struct wlr_xwayland *wlr_xwayland) {
*/ */
} }
static bool wlr_xwayland_init(struct wlr_xwayland *wlr_xwayland,
struct wl_display *wl_display, struct wlr_compositor *compositor);
static void handle_client_destroy(struct wl_listener *listener, void *data) {
struct wlr_xwayland *wlr_xwayland =
wl_container_of(listener, wlr_xwayland, client_destroy);
// Don't call client destroy: it's being destroyed already
wlr_xwayland->client = NULL;
wl_list_remove(&wlr_xwayland->client_destroy.link);
wlr_xwayland_finish(wlr_xwayland);
if (time(NULL) - wlr_xwayland->server_start > 5) {
wlr_log(L_INFO, "Restarting Xwayland");
wlr_xwayland_init(wlr_xwayland, wlr_xwayland->wl_display,
wlr_xwayland->compositor);
}
}
static void handle_display_destroy(struct wl_listener *listener, void *data) {
struct wlr_xwayland *wlr_xwayland =
wl_container_of(listener, wlr_xwayland, display_destroy);
// Don't call client destroy: the display is being destroyed, it's too late
if (wlr_xwayland->client) {
wlr_xwayland->client = NULL;
wl_list_remove(&wlr_xwayland->client_destroy.link);
}
wlr_xwayland_destroy(wlr_xwayland);
}
static int xserver_handle_ready(int signal_number, void *data) { static int xserver_handle_ready(int signal_number, void *data) {
struct wlr_xwayland *wlr_xwayland = data; struct wlr_xwayland *wlr_xwayland = data;
@ -231,6 +253,9 @@ static bool wlr_xwayland_init(struct wlr_xwayland *wlr_xwayland,
wl_signal_init(&wlr_xwayland->events.new_surface); wl_signal_init(&wlr_xwayland->events.new_surface);
wl_signal_init(&wlr_xwayland->events.ready); wl_signal_init(&wlr_xwayland->events.ready);
wlr_xwayland->display_destroy.notify = handle_display_destroy;
wl_display_add_destroy_listener(wl_display, &wlr_xwayland->display_destroy);
wlr_xwayland->display = open_display_sockets(wlr_xwayland->x_fd); wlr_xwayland->display = open_display_sockets(wlr_xwayland->x_fd);
if (wlr_xwayland->display < 0) { if (wlr_xwayland->display < 0) {
wlr_xwayland_finish(wlr_xwayland); wlr_xwayland_finish(wlr_xwayland);
@ -256,11 +281,13 @@ static bool wlr_xwayland_init(struct wlr_xwayland *wlr_xwayland,
wlr_xwayland->wl_fd[0] = -1; /* not ours anymore */ wlr_xwayland->wl_fd[0] = -1; /* not ours anymore */
wlr_xwayland->destroy_listener.notify = xwayland_destroy_event; wlr_xwayland->client_destroy.notify = handle_client_destroy;
wl_client_add_destroy_listener(wlr_xwayland->client, &wlr_xwayland->destroy_listener); wl_client_add_destroy_listener(wlr_xwayland->client,
&wlr_xwayland->client_destroy);
struct wl_event_loop *loop = wl_display_get_event_loop(wl_display); struct wl_event_loop *loop = wl_display_get_event_loop(wl_display);
wlr_xwayland->sigusr1_source = wl_event_loop_add_signal(loop, SIGUSR1, xserver_handle_ready, wlr_xwayland); wlr_xwayland->sigusr1_source = wl_event_loop_add_signal(loop, SIGUSR1,
xserver_handle_ready, wlr_xwayland);
if ((wlr_xwayland->pid = fork()) == 0) { if ((wlr_xwayland->pid = fork()) == 0) {
/* Double-fork, but we need to forward SIGUSR1 once Xserver(1) /* Double-fork, but we need to forward SIGUSR1 once Xserver(1)

View file

@ -1093,6 +1093,12 @@ void xwm_destroy(struct wlr_xwm *xwm) {
if (xwm->cursor) { if (xwm->cursor) {
xcb_free_cursor(xwm->xcb_conn, xwm->cursor); xcb_free_cursor(xwm->xcb_conn, xwm->cursor);
} }
if (xwm->colormap) {
xcb_free_colormap(xwm->xcb_conn, xwm->colormap);
}
if (xwm->window) {
xcb_destroy_window(xwm->xcb_conn, xwm->window);
}
if (xwm->event_source) { if (xwm->event_source) {
wl_event_source_remove(xwm->event_source); wl_event_source_remove(xwm->event_source);
} }
@ -1100,6 +1106,9 @@ void xwm_destroy(struct wlr_xwm *xwm) {
wl_list_for_each_safe(xsurface, tmp, &xwm->surfaces, link) { wl_list_for_each_safe(xsurface, tmp, &xwm->surfaces, link) {
wlr_xwayland_surface_destroy(xsurface); wlr_xwayland_surface_destroy(xsurface);
} }
wl_list_for_each_safe(xsurface, tmp, &xwm->unpaired_surfaces, link) {
wlr_xwayland_surface_destroy(xsurface);
}
wl_list_remove(&xwm->compositor_surface_create.link); wl_list_remove(&xwm->compositor_surface_create.link);
xcb_disconnect(xwm->xcb_conn); xcb_disconnect(xwm->xcb_conn);