From 1e37681072a69decce7441e762cb5f4ce1a80d73 Mon Sep 17 00:00:00 2001 From: Giovanni Campagna Date: Wed, 21 Aug 2013 09:53:26 +0200 Subject: [PATCH 12/38] xwayland: handle global object destruction Certain global objects, such as outputs, can be destroyed during the session. We must handle that and not crash. --- hw/xfree86/xwayland/xwayland-drm.c | 7 ++++++ hw/xfree86/xwayland/xwayland-input.c | 7 ++++++ hw/xfree86/xwayland/xwayland-output.c | 40 +++++++++++++++++++++++++++++++--- hw/xfree86/xwayland/xwayland-private.h | 6 ++++- hw/xfree86/xwayland/xwayland.c | 17 +++++++++++---- 5 files changed, 69 insertions(+), 8 deletions(-) diff --git a/hw/xfree86/xwayland/xwayland-drm.c b/hw/xfree86/xwayland/xwayland-drm.c index ce56e4c..6e4c778 100644 --- a/hw/xfree86/xwayland/xwayland-drm.c +++ b/hw/xfree86/xwayland/xwayland-drm.c @@ -119,8 +119,15 @@ drm_handler(void *data, struct wl_registry *registry, uint32_t id, } } +static void +global_remove(void *data, struct wl_registry *registry, uint32_t name) +{ + /* Nothing to do here, wl_drm should not be removed */ +} + static const struct wl_registry_listener drm_listener = { drm_handler, + global_remove }; int diff --git a/hw/xfree86/xwayland/xwayland-input.c b/hw/xfree86/xwayland/xwayland-input.c index 2f8e0c7..d031b34 100644 --- a/hw/xfree86/xwayland/xwayland-input.c +++ b/hw/xfree86/xwayland/xwayland-input.c @@ -597,8 +597,15 @@ input_handler(void *data, struct wl_registry *registry, uint32_t id, } } +static void +global_remove(void *data, struct wl_registry *registry, uint32_t name) +{ + /* FIXME */ +} + static const struct wl_registry_listener input_listener = { input_handler, + global_remove, }; void diff --git a/hw/xfree86/xwayland/xwayland-output.c b/hw/xfree86/xwayland/xwayland-output.c index 8f087f6..46238f4 100644 --- a/hw/xfree86/xwayland/xwayland-output.c +++ b/hw/xfree86/xwayland/xwayland-output.c @@ -95,6 +95,14 @@ crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data) { } +static void +crtc_destroy(xf86CrtcPtr crtc) +{ + /* Nothing to do here, we only destroy CRTCs when instructed to do + so by wl_output changes + */ +} + static const xf86CrtcFuncsRec crtc_funcs = { .dpms = crtc_dpms, .set_mode_major = crtc_set_mode_major, @@ -106,7 +114,7 @@ static const xf86CrtcFuncsRec crtc_funcs = { .shadow_create = crtc_shadow_create, .shadow_allocate = crtc_shadow_allocate, .shadow_destroy = crtc_shadow_destroy, - .destroy = NULL, /* XXX */ + .destroy = crtc_destroy, }; static void @@ -246,7 +254,7 @@ display_handle_geometry(void *data, struct wl_output *wl_output, int x, int y, xwl_output->x = x; xwl_output->y = y; - xwl_screen->xwl_output = xwl_output; + xorg_list_append (&xwl_output->link, &xwl_screen->output_list); } static void @@ -277,13 +285,39 @@ global_handler(void *data, struct wl_registry *registry, uint32_t id, xwl_output = xwl_output_create(xwl_screen); xwl_output->output = wl_registry_bind(registry, id, &wl_output_interface, 1); + xwl_output->name = id; wl_output_add_listener(xwl_output->output, &output_listener, xwl_output); } } +void +xwl_output_remove(struct xwl_output *xwl_output) +{ + xorg_list_del (&xwl_output->link); + xf86OutputDestroy (xwl_output->xf86output); + xf86CrtcDestroy (xwl_output->xf86crtc); + + wl_output_destroy (xwl_output->output); +} + +static void +global_remove(void *data, struct wl_registry *registry, uint32_t name) +{ + struct xwl_screen *xwl_screen = data; + struct xwl_output *xwl_output, *tmp; + + xorg_list_for_each_entry_safe (xwl_output, tmp, &xwl_screen->output_list, link) { + if (xwl_output->name == name) { + xwl_output_remove(xwl_output); + break; + } + } +} + static const struct wl_registry_listener global_listener = { global_handler, + global_remove }; void @@ -299,7 +333,7 @@ xwayland_screen_preinit_output(struct xwl_screen *xwl_screen, ScrnInfoPtr scrnin wl_registry_add_listener(xwl_screen->output_registry, &global_listener, xwl_screen); - while (!xwl_screen->xwl_output) { + while (xwl_screen->output_list.next == &xwl_screen->output_list) { ret = wl_display_roundtrip(xwl_screen->display); if (ret == -1) FatalError("failed to dispatch Wayland events: %s\n", strerror(errno)); diff --git a/hw/xfree86/xwayland/xwayland-private.h b/hw/xfree86/xwayland/xwayland-private.h index e427316..7005db2 100644 --- a/hw/xfree86/xwayland/xwayland-private.h +++ b/hw/xfree86/xwayland/xwayland-private.h @@ -44,7 +44,6 @@ struct xwl_screen { ScrnInfoPtr scrninfo; int drm_fd; int wayland_fd; - struct xwl_output *xwl_output; struct wl_display *display; struct wl_registry *registry; struct wl_registry *drm_registry; @@ -58,6 +57,7 @@ struct xwl_screen { uint32_t flags; char *device_name; uint32_t authenticated; + struct xorg_list output_list; struct xorg_list seat_list; struct xorg_list damage_window_list; struct xorg_list window_list; @@ -74,12 +74,14 @@ struct xwl_screen { }; struct xwl_output { + struct xorg_list link; struct wl_output *output; struct xwl_screen *xwl_screen; int32_t x, y, width, height; xf86Monitor xf86monitor; xf86OutputPtr xf86output; xf86CrtcPtr xf86crtc; + int32_t name; }; @@ -127,6 +129,8 @@ Bool xwl_drm_initialised(struct xwl_screen *screen); void xwl_seat_set_cursor(struct xwl_seat *xwl_seat); +void xwl_output_remove(struct xwl_output *output); + extern const struct xserver_listener xwl_server_listener; #endif /* _XWAYLAND_PRIVATE_H_ */ diff --git a/hw/xfree86/xwayland/xwayland.c b/hw/xfree86/xwayland/xwayland.c index 880b7ec..2047a85 100644 --- a/hw/xfree86/xwayland/xwayland.c +++ b/hw/xfree86/xwayland/xwayland.c @@ -103,8 +103,15 @@ registry_global(void *data, struct wl_registry *registry, uint32_t id, } } +static void +global_remove(void *data, struct wl_registry *registry, uint32_t name) +{ + /* Nothing to do here, wl_compositor and wl_shm should not be removed */ +} + static const struct wl_registry_listener registry_listener = { registry_global, + global_remove }; static void @@ -230,6 +237,7 @@ xwl_screen_pre_init(ScrnInfoPtr scrninfo, struct xwl_screen *xwl_screen, return FALSE; } + xorg_list_init(&xwl_screen->output_list); xorg_list_init(&xwl_screen->seat_list); xorg_list_init(&xwl_screen->damage_window_list); xorg_list_init(&xwl_screen->window_list); @@ -318,12 +326,13 @@ void xwl_screen_close(struct xwl_screen *xwl_screen) void xwl_screen_destroy(struct xwl_screen *xwl_screen) { - if (xwl_screen->xwl_output) { - xf86OutputDestroy(xwl_screen->xwl_output->xf86output); - xf86CrtcDestroy(xwl_screen->xwl_output->xf86crtc); + struct xwl_output *xwl_output, *tmp; + + xorg_list_for_each_entry_safe (xwl_output, tmp, &xwl_screen->output_list, link) { + xwl_output_remove(xwl_output); + break; } - free(xwl_screen->xwl_output); free(xwl_screen); } -- 1.8.4.2