diff --git a/include/rootston/view.h b/include/rootston/view.h index 7d297329..1a0de6de 100644 --- a/include/rootston/view.h +++ b/include/rootston/view.h @@ -34,6 +34,8 @@ struct roots_xwayland_surface { // TODO: Maybe destroy listener should go in roots_view struct wl_listener destroy; struct wl_listener request_configure; + struct wl_listener map_notify; + struct wl_listener unmap_notify; }; enum roots_view_type { diff --git a/include/wlr/xwayland.h b/include/wlr/xwayland.h index 3d5a204c..efee3d9f 100644 --- a/include/wlr/xwayland.h +++ b/include/wlr/xwayland.h @@ -99,6 +99,8 @@ struct wlr_xwayland_surface { struct { struct wl_signal destroy; struct wl_signal request_configure; + struct wl_signal map_notify; + struct wl_signal unmap_notify; struct wl_signal set_title; struct wl_signal set_class; struct wl_signal set_parent; diff --git a/rootston/xwayland.c b/rootston/xwayland.c index 1149b966..d43618c3 100644 --- a/rootston/xwayland.c +++ b/rootston/xwayland.c @@ -44,6 +44,8 @@ static void handle_destroy(struct wl_listener *listener, void *data) { struct roots_xwayland_surface *roots_surface = wl_container_of(listener, roots_surface, destroy); wl_list_remove(&roots_surface->destroy.link); + wl_list_remove(&roots_surface->map_notify.link); + wl_list_remove(&roots_surface->unmap_notify.link); view_destroy(roots_surface->view); free(roots_surface); } @@ -62,6 +64,34 @@ static void handle_request_configure(struct wl_listener *listener, void *data) { xwayland_surface, event->x, event->y, event->width, event->height); } +static void handle_map_notify(struct wl_listener *listener, void *data) { + struct roots_xwayland_surface *roots_surface = + wl_container_of(listener, roots_surface, map_notify); + struct roots_view *view = roots_surface->view; + struct wlr_xwayland_surface *xsurface = view->xwayland_surface; + struct roots_desktop *desktop = view->desktop; + + view->wlr_surface = xsurface->surface; + view->x = (double)xsurface->x; + view->y = (double)xsurface->y; + + wlr_list_push(desktop->views, roots_surface->view); +} + +static void handle_unmap_notify(struct wl_listener *listener, void *data) { + struct roots_xwayland_surface *roots_surface = + wl_container_of(listener, roots_surface, unmap_notify); + struct roots_desktop *desktop = roots_surface->view->desktop; + roots_surface->view->wlr_surface = NULL; + + for (size_t i = 0; i < desktop->views->length; i++) { + if (desktop->views->items[i] == roots_surface->view) { + wlr_list_del(desktop->views, i); + break; + } + } +} + void handle_xwayland_surface(struct wl_listener *listener, void *data) { struct roots_desktop *desktop = wl_container_of(listener, desktop, xwayland_surface); @@ -77,10 +107,17 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { } roots_surface->destroy.notify = handle_destroy; wl_signal_add(&surface->events.destroy, &roots_surface->destroy); + roots_surface->request_configure.notify = handle_request_configure; wl_signal_add(&surface->events.request_configure, &roots_surface->request_configure); + roots_surface->map_notify.notify = handle_map_notify; + wl_signal_add(&surface->events.map_notify, &roots_surface->map_notify); + + roots_surface->unmap_notify.notify = handle_unmap_notify; + wl_signal_add(&surface->events.unmap_notify, &roots_surface->unmap_notify); + struct roots_view *view = calloc(1, sizeof(struct roots_view)); if (view == NULL) { free(roots_surface); diff --git a/xwayland/xwm.c b/xwayland/xwm.c index 7d676987..6850f56b 100644 --- a/xwayland/xwm.c +++ b/xwayland/xwm.c @@ -75,6 +75,8 @@ static struct wlr_xwayland_surface *wlr_xwayland_surface_create( surface->state = wlr_list_create(); wl_signal_init(&surface->events.destroy); wl_signal_init(&surface->events.request_configure); + wl_signal_init(&surface->events.map_notify); + wl_signal_init(&surface->events.unmap_notify); wl_signal_init(&surface->events.set_class); wl_signal_init(&surface->events.set_title); wl_signal_init(&surface->events.set_parent); @@ -474,6 +476,7 @@ static void map_shell_surface(struct wlr_xwm *xwm, wl_signal_add(&surface->events.destroy, &xsurface->surface_destroy); xsurface->mapped = true; + wl_signal_emit(&xsurface->events.map_notify, xsurface); } /* xcb event handlers */ @@ -551,13 +554,6 @@ static void handle_map_request(struct wlr_xwm *xwm, static void handle_map_notify(struct wlr_xwm *xwm, xcb_map_notify_event_t *ev) { wlr_log(L_DEBUG, "XCB_MAP_NOTIFY (%u)", ev->window); - struct wlr_xwayland_surface *surface = lookup_surface(xwm, ev->window); - if (surface != NULL) { - surface->override_redirect = ev->override_redirect; - } else { - wlr_xwayland_surface_create(xwm, ev->window, 0, 0, 1, 1, - ev->override_redirect); - } } static void handle_unmap_notify(struct wlr_xwm *xwm, @@ -579,10 +575,11 @@ static void handle_unmap_notify(struct wlr_xwm *xwm, if (xsurface->surface) { wl_list_remove(&xsurface->surface_commit.link); wl_list_remove(&xsurface->surface_destroy.link); - xsurface->surface = NULL; } + xsurface->surface = NULL; - wlr_xwayland_surface_destroy(xsurface); + xsurface->mapped = false; + wl_signal_emit(&xsurface->events.unmap_notify, xsurface); } static void handle_property_notify(struct wlr_xwm *xwm, @@ -696,12 +693,12 @@ static void handle_compositor_surface_create(struct wl_listener *listener, wlr_log(L_DEBUG, "New xwayland surface: %p", surface); uint32_t surface_id = wl_resource_get_id(surface->resource); - struct wlr_xwayland_surface *xwayland_surface; - wl_list_for_each(xwayland_surface, &xwm->unpaired_surfaces, unpaired_link) { - if (xwayland_surface->surface_id == surface_id) { - map_shell_surface(xwm, xwayland_surface, surface); - xwayland_surface->surface_id = 0; - wl_list_remove(&xwayland_surface->unpaired_link); + struct wlr_xwayland_surface *xsurface; + wl_list_for_each(xsurface, &xwm->unpaired_surfaces, unpaired_link) { + if (xsurface->surface_id == surface_id) { + map_shell_surface(xwm, xsurface, surface); + xsurface->surface_id = 0; + wl_list_remove(&xsurface->unpaired_link); xcb_flush(xwm->xcb_conn); return; }