aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backend/drm/backend.c19
-rw-r--r--backend/drm/renderer.c4
-rw-r--r--backend/libinput/backend.c25
-rw-r--r--backend/multi/backend.c1
-rw-r--r--backend/session/session.c13
-rw-r--r--backend/wayland/backend.c16
-rw-r--r--backend/x11/backend.c139
-rw-r--r--include/backend/drm/drm.h1
-rw-r--r--include/backend/libinput.h1
-rw-r--r--include/backend/wayland.h1
-rw-r--r--include/backend/x11.h2
-rw-r--r--include/wlr/backend/session.h2
-rw-r--r--include/wlr/render/egl.h3
-rw-r--r--include/wlr/types/wlr_compositor.h7
-rw-r--r--include/wlr/types/wlr_data_device.h2
-rw-r--r--include/wlr/types/wlr_gamma_control.h4
-rw-r--r--include/wlr/types/wlr_output.h2
-rw-r--r--include/wlr/types/wlr_screenshooter.h4
-rw-r--r--include/wlr/types/wlr_seat.h1
-rw-r--r--include/wlr/types/wlr_server_decoration.h2
-rw-r--r--include/wlr/types/wlr_wl_shell.h2
-rw-r--r--include/wlr/types/wlr_xdg_shell_v6.h2
-rw-r--r--include/wlr/xwayland.h3
-rw-r--r--render/egl.c2
-rw-r--r--rootston/main.c2
-rw-r--r--types/wlr_compositor.c19
-rw-r--r--types/wlr_data_device.c26
-rw-r--r--types/wlr_gamma_control.c63
-rw-r--r--types/wlr_output.c11
-rw-r--r--types/wlr_screenshooter.c51
-rw-r--r--types/wlr_seat.c51
-rw-r--r--types/wlr_server_decoration.c47
-rw-r--r--types/wlr_wl_shell.c18
-rw-r--r--types/wlr_xdg_shell_v6.c13
-rw-r--r--xwayland/xwayland.c75
-rw-r--r--xwayland/xwm.c9
36 files changed, 445 insertions, 198 deletions
diff --git a/backend/drm/backend.c b/backend/drm/backend.c
index 87a4f708..6be5e5d5 100644
--- a/backend/drm/backend.c
+++ b/backend/drm/backend.c
@@ -34,6 +34,10 @@ static void wlr_drm_backend_destroy(struct wlr_backend *backend) {
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_renderer_finish(&drm->renderer);
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) {
- 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;
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) {
- 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);
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);
}
+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_session *session, int gpu_fd, struct wlr_backend *parent) {
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());
}
+ drm->display_destroy.notify = handle_display_destroy;
+ wl_display_add_destroy_listener(display, &drm->display_destroy);
+
return &drm->backend;
error_event:
diff --git a/backend/drm/renderer.c b/backend/drm/renderer.c
index 87064914..8a8d7d1f 100644
--- a/backend/drm/renderer.c
+++ b/backend/drm/renderer.c
@@ -39,7 +39,7 @@ bool wlr_drm_renderer_init(struct wlr_drm_backend *drm,
return true;
error_egl:
- wlr_egl_free(&renderer->egl);
+ wlr_egl_finish(&renderer->egl);
error_gbm:
gbm_device_destroy(renderer->gbm);
return false;
@@ -51,7 +51,7 @@ void wlr_drm_renderer_finish(struct wlr_drm_renderer *renderer) {
}
wlr_renderer_destroy(renderer->wlr_rend);
- wlr_egl_free(&renderer->egl);
+ wlr_egl_finish(&renderer->egl);
gbm_device_destroy(renderer->gbm);
}
diff --git a/backend/libinput/backend.c b/backend/libinput/backend.c
index 1028e238..c9352051 100644
--- a/backend/libinput/backend.c
+++ b/backend/libinput/backend.c
@@ -43,10 +43,12 @@ static void wlr_libinput_log(struct libinput *libinput_context,
}
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");
- 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) {
wlr_log(L_ERROR, "Failed to create libinput context");
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;
+
for (size_t i = 0; i < backend->wlr_device_lists.length; i++) {
struct wl_list *wlr_devices = backend->wlr_device_lists.items[i];
struct wlr_input_device *wlr_dev, *next;
@@ -108,6 +111,10 @@ static void wlr_libinput_backend_destroy(struct wlr_backend *_backend) {
}
free(wlr_devices);
}
+
+ wl_list_remove(&backend->display_destroy.link);
+ wl_list_remove(&backend->session_signal.link);
+
wlr_list_finish(&backend->wlr_device_lists);
wl_event_source_remove(backend->input_event);
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) {
- 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;
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_session *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;
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;
error_backend:
free(backend);
diff --git a/backend/multi/backend.c b/backend/multi/backend.c
index c35303e0..fc0c5b81 100644
--- a/backend/multi/backend.c
+++ b/backend/multi/backend.c
@@ -35,7 +35,6 @@ static void multi_backend_destroy(struct wlr_backend *_backend) {
wlr_backend_destroy(sub->backend);
free(sub);
}
- wlr_session_destroy(backend->session);
free(backend);
}
diff --git a/backend/session/session.c b/backend/session/session.c
index 657558fd..0ed54499 100644
--- a/backend/session/session.c
+++ b/backend/session/session.c
@@ -58,6 +58,12 @@ out:
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 *session = NULL;
const struct session_impl **iter;
@@ -100,6 +106,9 @@ struct wlr_session *wlr_session_create(struct wl_display *disp) {
goto error_mon;
}
+ session->display_destroy.notify = handle_display_destroy;
+ wl_display_add_destroy_listener(disp, &session->display_destroy);
+
return session;
error_mon:
@@ -107,7 +116,7 @@ error_mon:
error_udev:
udev_unref(session->udev);
error_session:
- wlr_session_destroy(session);
+ session->impl->destroy(session);
return NULL;
}
@@ -116,6 +125,8 @@ void wlr_session_destroy(struct wlr_session *session) {
return;
}
+ wl_list_remove(&session->display_destroy.link);
+
wl_event_source_remove(session->udev_event);
udev_monitor_unref(session->mon);
udev_unref(session->udev);
diff --git a/backend/wayland/backend.c b/backend/wayland/backend.c
index 1801f3e0..2bf155a5 100644
--- a/backend/wayland/backend.c
+++ b/backend/wayland/backend.c
@@ -78,10 +78,12 @@ static void wlr_wl_backend_destroy(struct wlr_backend *_backend) {
wlr_input_device_destroy(input_device);
}
+ wl_list_remove(&backend->local_display_destroy.link);
+
free(backend->seat_name);
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->shm) wl_shm_destroy(backend->shm);
if (backend->shell) zxdg_shell_v6_destroy(backend->shell);
@@ -117,6 +119,12 @@ struct wlr_wl_backend_output *wlr_wl_output_for_surface(
return NULL;
}
+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) {
wlr_log(L_INFO, "Creating wayland backend");
@@ -143,8 +151,12 @@ struct wlr_backend *wlr_wl_backend_create(struct wl_display *display) {
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);
+ backend->local_display_destroy.notify = handle_display_destroy;
+ wl_display_add_destroy_listener(display, &backend->local_display_destroy);
+
return &backend->backend;
}
diff --git a/backend/x11/backend.c b/backend/x11/backend.c
index 5fb54ffd..e8006a1a 100644
--- a/backend/x11/backend.c
+++ b/backend/x11/backend.c
@@ -184,69 +184,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);
}
-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) {
struct wlr_x11_backend *x11 = (struct wlr_x11_backend *)backend;
struct wlr_x11_output *output = &x11->output;
@@ -307,8 +244,10 @@ static void wlr_x11_backend_destroy(struct wlr_backend *backend) {
struct wlr_x11_output *output = &x11->output;
wlr_output_destroy(&output->wlr_output);
+ wl_list_remove(&x11->display_destroy.link);
+
wl_event_source_remove(x11->frame_timer);
- wlr_egl_free(&x11->egl);
+ wlr_egl_finish(&x11->egl);
xcb_disconnect(x11->xcb_conn);
free(x11);
@@ -329,6 +268,78 @@ static struct wlr_backend_impl backend_impl = {
.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,
int32_t height, int32_t refresh) {
struct wlr_x11_output *output = (struct wlr_x11_output *)wlr_output;
diff --git a/include/backend/drm/drm.h b/include/backend/drm/drm.h
index 4fad9678..1f70a103 100644
--- a/include/backend/drm/drm.h
+++ b/include/backend/drm/drm.h
@@ -91,6 +91,7 @@ struct wlr_drm_backend {
struct wl_display *display;
struct wl_event_source *drm_event;
+ struct wl_listener display_destroy;
struct wl_listener session_signal;
struct wl_listener drm_invalidated;
diff --git a/include/backend/libinput.h b/include/backend/libinput.h
index be2557ed..6ec718c6 100644
--- a/include/backend/libinput.h
+++ b/include/backend/libinput.h
@@ -16,6 +16,7 @@ struct wlr_libinput_backend {
struct libinput *libinput_context;
struct wl_event_source *input_event;
+ struct wl_listener display_destroy;
struct wl_listener session_signal;
struct wlr_list wlr_device_lists; // list of struct wl_list
diff --git a/include/backend/wayland.h b/include/backend/wayland.h
index 1e8a55d2..713c291c 100644
--- a/include/backend/wayland.h
+++ b/include/backend/wayland.h
@@ -21,6 +21,7 @@ struct wlr_wl_backend {
struct wl_list outputs;
struct wlr_egl egl;
size_t requested_outputs;
+ struct wl_listener local_display_destroy;
/* remote state */
struct wl_display *remote_display;
struct wl_event_source *remote_display_src;
diff --git a/include/backend/x11.h b/include/backend/x11.h
index f5ec56bc..31a5138b 100644
--- a/include/backend/x11.h
+++ b/include/backend/x11.h
@@ -51,6 +51,8 @@ struct wlr_x11_backend {
// The time we last received an event
xcb_timestamp_t time;
+
+ struct wl_listener display_destroy;
};
#endif
diff --git a/include/wlr/backend/session.h b/include/wlr/backend/session.h
index 5c822ea9..3242a13f 100644
--- a/include/wlr/backend/session.h
+++ b/include/wlr/backend/session.h
@@ -33,6 +33,8 @@ struct wlr_session {
struct wl_event_source *udev_event;
struct wl_list devices;
+
+ struct wl_listener display_destroy;
};
/*
diff --git a/include/wlr/render/egl.h b/include/wlr/render/egl.h
index 9ab4d9ce..67a81f37 100644
--- a/include/wlr/render/egl.h
+++ b/include/wlr/render/egl.h
@@ -4,6 +4,7 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <stdbool.h>
+#include <wayland-server.h>
struct wlr_egl {
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
* 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.
diff --git a/include/wlr/types/wlr_compositor.h b/include/wlr/types/wlr_compositor.h
index b2f5a972..ceeb64ca 100644
--- a/include/wlr/types/wlr_compositor.h
+++ b/include/wlr/types/wlr_compositor.h
@@ -9,7 +9,8 @@ struct wlr_compositor {
struct wl_list wl_resources;
struct wlr_renderer *renderer;
struct wl_list surfaces;
- struct wl_listener destroy_surface_listener;
+
+ struct wl_listener display_destroy;
struct {
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_renderer *renderer);
-struct wlr_surface;
-void wl_compositor_surface_destroyed(struct wlr_compositor *wlr_compositor,
- struct wlr_surface *surface);
-
#endif
diff --git a/include/wlr/types/wlr_data_device.h b/include/wlr/types/wlr_data_device.h
index 12b25e45..70d79a19 100644
--- a/include/wlr/types/wlr_data_device.h
+++ b/include/wlr/types/wlr_data_device.h
@@ -15,6 +15,8 @@ wlr_touch_grab_interface wlr_data_device_touch_drag_interface;
struct wlr_data_device_manager {
struct wl_global *global;
+
+ struct wl_listener display_destroy;
};
struct wlr_data_offer {
diff --git a/include/wlr/types/wlr_gamma_control.h b/include/wlr/types/wlr_gamma_control.h
index 59f18494..d3f4b8e5 100644
--- a/include/wlr/types/wlr_gamma_control.h
+++ b/include/wlr/types/wlr_gamma_control.h
@@ -5,7 +5,9 @@
struct wlr_gamma_control_manager {
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;
};
diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h
index 7f681ab7..abd7c285 100644
--- a/include/wlr/types/wlr_output.h
+++ b/include/wlr/types/wlr_output.h
@@ -75,6 +75,8 @@ struct wlr_output {
// the output position in layout space reported to clients
int32_t lx, ly;
+ struct wl_listener display_destroy;
+
void *data;
};
diff --git a/include/wlr/types/wlr_screenshooter.h b/include/wlr/types/wlr_screenshooter.h
index 4bda3d3c..4c66be3f 100644
--- a/include/wlr/types/wlr_screenshooter.h
+++ b/include/wlr/types/wlr_screenshooter.h
@@ -5,6 +5,9 @@
struct wlr_screenshooter {
struct wl_global *wl_global;
struct wlr_renderer *renderer;
+ struct wl_list screenshots; // wlr_screenshot::link
+
+ struct wl_listener display_destroy;
void *data;
};
@@ -12,6 +15,7 @@ struct wlr_screenshooter {
struct wlr_screenshot {
struct wl_resource *resource;
struct wl_resource *output_resource;
+ struct wl_list link;
struct wlr_output *output;
struct wlr_screenshooter *screenshooter;
diff --git a/include/wlr/types/wlr_seat.h b/include/wlr/types/wlr_seat.h
index 6c04380e..00fd8da1 100644
--- a/include/wlr/types/wlr_seat.h
+++ b/include/wlr/types/wlr_seat.h
@@ -184,6 +184,7 @@ struct wlr_seat {
struct wlr_seat_keyboard_state keyboard_state;
struct wlr_seat_touch_state touch_state;
+ struct wl_listener display_destroy;
struct wl_listener selection_data_source_destroy;
struct {
diff --git a/include/wlr/types/wlr_server_decoration.h b/include/wlr/types/wlr_server_decoration.h
index 474a9386..e457a0aa 100644
--- a/include/wlr/types/wlr_server_decoration.h
+++ b/include/wlr/types/wlr_server_decoration.h
@@ -33,6 +33,8 @@ struct wlr_server_decoration_manager {
uint32_t default_mode; // enum wlr_server_decoration_manager_mode
+ struct wl_listener display_destroy;
+
struct {
struct wl_signal new_decoration;
} events;
diff --git a/include/wlr/types/wlr_wl_shell.h b/include/wlr/types/wlr_wl_shell.h
index 986f92e8..29446b04 100644
--- a/include/wlr/types/wlr_wl_shell.h
+++ b/include/wlr/types/wlr_wl_shell.h
@@ -12,6 +12,8 @@ struct wlr_wl_shell {
struct wl_list popup_grabs;
uint32_t ping_timeout;
+ struct wl_listener display_destroy;
+
struct {
struct wl_signal new_surface;
} events;
diff --git a/include/wlr/types/wlr_xdg_shell_v6.h b/include/wlr/types/wlr_xdg_shell_v6.h
index 4eb957be..b723a950 100644
--- a/include/wlr/types/wlr_xdg_shell_v6.h
+++ b/include/wlr/types/wlr_xdg_shell_v6.h
@@ -11,6 +11,8 @@ struct wlr_xdg_shell_v6 {
struct wl_list popup_grabs;
uint32_t ping_timeout;
+ struct wl_listener display_destroy;
+
struct {
struct wl_signal new_surface;
} events;
diff --git a/include/wlr/xwayland.h b/include/wlr/xwayland.h
index 792d2b88..f6b43851 100644
--- a/include/wlr/xwayland.h
+++ b/include/wlr/xwayland.h
@@ -23,7 +23,8 @@ struct wlr_xwayland {
time_t server_start;
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_xwayland_cursor *cursor;
diff --git a/render/egl.c b/render/egl.c
index 22d58df2..e895df8d 100644
--- a/render/egl.c
+++ b/render/egl.c
@@ -141,7 +141,7 @@ error:
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);
if (egl->wl_display && eglUnbindWaylandDisplayWL) {
eglUnbindWaylandDisplayWL(egl->display, egl->wl_display);
diff --git a/rootston/main.c b/rootston/main.c
index 46548094..3b65a067 100644
--- a/rootston/main.c
+++ b/rootston/main.c
@@ -51,6 +51,7 @@ int main(int argc, char **argv) {
if (!wlr_backend_start(server.backend)) {
wlr_log(L_ERROR, "Failed to start backend");
wlr_backend_destroy(server.backend);
+ wl_display_destroy(server.wl_display);
return 1;
}
@@ -69,5 +70,6 @@ int main(int argc, char **argv) {
wl_display_run(server.wl_display);
wlr_backend_destroy(server.backend);
+ wl_display_destroy(server.wl_display);
return 0;
}
diff --git a/types/wlr_compositor.c b/types/wlr_compositor.c
index 986b7e60..cf8c3f8f 100644
--- a/types/wlr_compositor.c
+++ b/types/wlr_compositor.c
@@ -78,6 +78,10 @@ static void wl_compositor_bind(struct wl_client *wl_client, void *data,
}
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);
free(compositor);
}
@@ -151,6 +155,12 @@ static void subcompositor_bind(struct wl_client *client, void *data,
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_renderer *renderer) {
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,
&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->renderer = renderer;
@@ -173,5 +187,8 @@ struct wlr_compositor *wlr_compositor_create(struct wl_display *display,
wl_list_init(&compositor->surfaces);
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;
}
diff --git a/types/wlr_data_device.c b/types/wlr_data_device.c
index a8d69cc0..dacb2a45 100644
--- a/types/wlr_data_device.c
+++ b/types/wlr_data_device.c
@@ -949,6 +949,21 @@ static void data_device_manager_bind(struct wl_client *client,
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 wl_display *display) {
struct wlr_data_device_manager *manager =
@@ -967,13 +982,8 @@ struct wlr_data_device_manager *wlr_data_device_manager_create(
return NULL;
}
- return manager;
-}
+ manager->display_destroy.notify = handle_display_destroy;
+ wl_display_add_destroy_listener(display, &manager->display_destroy);
-void wlr_data_device_manager_destroy(struct wlr_data_device_manager *manager) {
- if (!manager) {
- return;
- }
- wl_global_destroy(manager->global);
- free(manager);
+ return manager;
}
diff --git a/types/wlr_gamma_control.c b/types/wlr_gamma_control.c
index 355e56a2..eb154b6b 100644
--- a/types/wlr_gamma_control.c
+++ b/types/wlr_gamma_control.c
@@ -12,6 +12,9 @@ static void resource_destroy(struct wl_client *client,
}
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_list_remove(&gamma_control->output_destroy_listener.link);
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,
struct wl_resource *gamma_control_manager_resource, uint32_t id,
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);
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_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,
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,
uint32_t version, uint32_t id) {
- struct wlr_gamma_control_manager *gamma_control_manager = data;
- assert(client && gamma_control_manager);
+ struct wlr_gamma_control_manager *manager = data;
+ assert(client && manager);
struct wl_resource *resource = wl_resource_create(client,
&gamma_control_manager_interface, version, id);
@@ -121,41 +124,49 @@ static void gamma_control_manager_bind(struct wl_client *client, void *data,
return;
}
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 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));
- if (!gamma_control_manager) {
+ if (!manager) {
return NULL;
}
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);
if (!wl_global) {
- free(gamma_control_manager);
+ free(manager);
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(
- 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);
+ return manager;
}
diff --git a/types/wlr_output.c b/types/wlr_output.c
index adade238..41c5954f 100644
--- a/types/wlr_output.c
+++ b/types/wlr_output.c
@@ -112,6 +112,12 @@ static void wl_output_bind(struct wl_client *wl_client, void *data,
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_display *display) {
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,
&wl_output_interface, 3, wlr_output, wl_output_bind);
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;
}
@@ -127,6 +137,7 @@ void wlr_output_destroy_global(struct wlr_output *wlr_output) {
if (wlr_output->wl_global == NULL) {
return;
}
+ wl_list_remove(&wlr_output->display_destroy.link);
struct wl_resource *resource, *tmp;
wl_resource_for_each_safe(resource, tmp, &wlr_output->wl_resources) {
struct wl_list *link = wl_resource_get_link(resource);
diff --git a/types/wlr_screenshooter.c b/types/wlr_screenshooter.c
index 94b45384..4d591c45 100644
--- a/types/wlr_screenshooter.c
+++ b/types/wlr_screenshooter.c
@@ -26,6 +26,21 @@ struct screenshot_state {
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) {
struct screenshot_state *state = wl_container_of(listener, state,
frame_listener);
@@ -102,7 +117,8 @@ static void screenshooter_shoot(struct wl_client *client,
return;
}
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,
screenshot->resource);
@@ -144,6 +160,25 @@ static void screenshooter_bind(struct wl_client *wl_client, void *data,
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_renderer *renderer) {
struct wlr_screenshooter *screenshooter =
@@ -153,6 +188,11 @@ struct wlr_screenshooter *wlr_screenshooter_create(struct wl_display *display,
}
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,
&orbital_screenshooter_interface, 1, screenshooter, screenshooter_bind);
if (screenshooter->wl_global == NULL) {
@@ -162,12 +202,3 @@ struct wlr_screenshooter *wlr_screenshooter_create(struct wl_display *display,
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);
-}
diff --git a/types/wlr_seat.c b/types/wlr_seat.c
index 05ea4745..84a7045d 100644
--- a/types/wlr_seat.c
+++ b/types/wlr_seat.c
@@ -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 = calloc(1, sizeof(struct wlr_seat));
if (!wlr_seat) {
@@ -427,27 +455,10 @@ 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_end);
- 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);
- }
+ wlr_seat->display_destroy.notify = handle_display_destroy;
+ wl_display_add_destroy_listener(display, &wlr_seat->display_destroy);
- 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);
+ return wlr_seat;
}
struct wlr_seat_client *wlr_seat_client_for_wl_client(struct wlr_seat *wlr_seat,
diff --git a/types/wlr_server_decoration.c b/types/wlr_server_decoration.c
index 60cc6369..09909bb6 100644
--- a/types/wlr_server_decoration.c
+++ b/types/wlr_server_decoration.c
@@ -140,6 +140,31 @@ static void server_decoration_manager_bind(struct wl_client *client, void *data,
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 wl_display *display) {
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->decorations);
wl_signal_init(&manager->events.new_decoration);
- 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);
+ manager->display_destroy.notify = handle_display_destroy;
+ wl_display_add_destroy_listener(display, &manager->display_destroy);
+
+ return manager;
}
diff --git a/types/wlr_wl_shell.c b/types/wlr_wl_shell.c
index ee72856c..5476ddb6 100644
--- a/types/wlr_wl_shell.c
+++ b/types/wlr_wl_shell.c
@@ -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));
}
+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 *wl_shell = calloc(1, sizeof(struct wlr_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->popup_grabs);
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;
}
@@ -588,14 +598,14 @@ void wlr_wl_shell_destroy(struct wlr_wl_shell *wlr_wl_shell) {
if (!wlr_wl_shell) {
return;
}
+ wl_list_remove(&wlr_wl_shell->display_destroy.link);
struct wl_resource *resource = NULL, *temp = NULL;
wl_resource_for_each_safe(resource, temp, &wlr_wl_shell->wl_resources) {
- struct wl_list *link = wl_resource_get_link(resource);
- wl_list_remove(link);
+ // shell_destroy will remove the resource from the list
+ wl_resource_destroy(resource);
}
// 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);
}
diff --git a/types/wlr_xdg_shell_v6.c b/types/wlr_xdg_shell_v6.c
index 2627246f..23d36b6f 100644
--- a/types/wlr_xdg_shell_v6.c
+++ b/types/wlr_xdg_shell_v6.c
@@ -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 *xdg_shell =
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);
+ xdg_shell->display_destroy.notify = handle_display_destroy;
+ wl_display_add_destroy_listener(display, &xdg_shell->display_destroy);
+
return xdg_shell;
}
@@ -1279,8 +1288,8 @@ void wlr_xdg_shell_v6_destroy(struct wlr_xdg_shell_v6 *xdg_shell) {
if (!xdg_shell) {
return;
}
- // TODO: this segfault (wl_display->registry_resource_list is not init)
- // wl_global_destroy(xdg_shell->wl_global);
+ wl_list_remove(&xdg_shell->display_destroy.link);
+ wl_global_destroy(xdg_shell->wl_global);
free(xdg_shell);
}
diff --git a/xwayland/xwayland.c b/xwayland/xwayland.c
index ecec785c..59851898 100644
--- a/xwayland/xwayland.c
+++ b/xwayland/xwayland.c
@@ -125,38 +125,25 @@ static void exec_xwayland(struct wlr_xwayland *wlr_xwayland) {
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) {
if (!wlr_xwayland || wlr_xwayland->display == -1) {
return;
}
+
+ if (wlr_xwayland->cursor != NULL) {
+ free(wlr_xwayland->cursor);
+ }
+
+ xwm_destroy(wlr_xwayland->xwm);
+
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);
}
if (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[1]);
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[1]);
+ wl_list_remove(&wlr_xwayland->display_destroy.link);
+
unlink_display_sockets(wlr_xwayland->display);
wlr_xwayland->display = -1;
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) {
struct wlr_xwayland *wlr_xwayland = data;
@@ -227,6 +249,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.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);
if (wlr_xwayland->display < 0) {
wlr_xwayland_finish(wlr_xwayland);
@@ -252,11 +277,13 @@ static bool wlr_xwayland_init(struct wlr_xwayland *wlr_xwayland,
wlr_xwayland->wl_fd[0] = -1; /* not ours anymore */
- wlr_xwayland->destroy_listener.notify = xwayland_destroy_event;
- wl_client_add_destroy_listener(wlr_xwayland->client, &wlr_xwayland->destroy_listener);
+ wlr_xwayland->client_destroy.notify = handle_client_destroy;
+ wl_client_add_destroy_listener(wlr_xwayland->client,
+ &wlr_xwayland->client_destroy);
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) {
/* Double-fork, but we need to forward SIGUSR1 once Xserver(1)
diff --git a/xwayland/xwm.c b/xwayland/xwm.c
index a86fbd0e..cb5d38d4 100644
--- a/xwayland/xwm.c
+++ b/xwayland/xwm.c
@@ -1075,6 +1075,12 @@ void xwm_destroy(struct wlr_xwm *xwm) {
if (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) {
wl_event_source_remove(xwm->event_source);
}
@@ -1082,6 +1088,9 @@ void xwm_destroy(struct wlr_xwm *xwm) {
wl_list_for_each_safe(xsurface, tmp, &xwm->surfaces, link) {
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);
xcb_disconnect(xwm->xcb_conn);