From dcd15a2d3dd93e057fe702238eb21dd70331b44f Mon Sep 17 00:00:00 2001 From: emersion Date: Thu, 5 Apr 2018 11:38:14 -0400 Subject: [PATCH] Implement shell views --- include/sway/tree/view.h | 104 ++++++++++++++---------------- sway/desktop/wl_shell.c | 79 ++++++++++++----------- sway/desktop/xdg_shell_v6.c | 110 +++++++++++++++++--------------- sway/desktop/xwayland.c | 123 +++++++++++++++++++----------------- sway/tree/view.c | 13 ++-- 5 files changed, 225 insertions(+), 204 deletions(-) diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index f32ccc5a..d4dace4a 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -8,10 +8,47 @@ #include "sway/input/seat.h" struct sway_container; -struct sway_view; -struct sway_xdg_surface_v6 { - struct sway_view *view; +enum sway_view_type { + SWAY_VIEW_WL_SHELL, + SWAY_VIEW_XDG_SHELL_V6, + SWAY_VIEW_XWAYLAND, +}; + +enum sway_view_prop { + VIEW_PROP_TITLE, + VIEW_PROP_APP_ID, + VIEW_PROP_CLASS, + VIEW_PROP_INSTANCE, +}; + +struct sway_view_impl { + const char *(*get_prop)(struct sway_view *view, + enum sway_view_prop prop); + void (*configure)(struct sway_view *view, double ox, double oy, int width, + int height); + void (*set_activated)(struct sway_view *view, bool activated); + void (*close)(struct sway_view *view); + void (*destroy)(struct sway_view *view); +}; + +struct sway_view { + enum sway_view_type type; + const struct sway_view_impl *impl; + + struct sway_container *swayc; // NULL for unmanaged views + struct wlr_surface *surface; // NULL for unmapped views + int width, height; + + union { + struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6; + struct wlr_xwayland_surface *wlr_xwayland_surface; + struct wlr_wl_shell_surface *wlr_wl_shell_surface; + }; +}; + +struct sway_xdg_shell_v6_view { + struct sway_view view; struct wl_listener commit; struct wl_listener request_move; @@ -24,8 +61,8 @@ struct sway_xdg_surface_v6 { int pending_width, pending_height; }; -struct sway_xwayland_surface { - struct sway_view *view; +struct sway_xwayland_view { + struct sway_view view; struct wl_listener commit; struct wl_listener request_move; @@ -46,8 +83,8 @@ struct sway_xwayland_unmanaged { struct wl_listener destroy; }; -struct sway_wl_shell_surface { - struct sway_view *view; +struct sway_wl_shell_view { + struct sway_view view; struct wl_listener commit; struct wl_listener request_move; @@ -58,54 +95,6 @@ struct sway_wl_shell_surface { int pending_width, pending_height; }; -enum sway_view_type { - SWAY_VIEW_WL_SHELL, - SWAY_VIEW_XDG_SHELL_V6, - SWAY_VIEW_XWAYLAND, -}; - -enum sway_view_prop { - VIEW_PROP_TITLE, - VIEW_PROP_APP_ID, - VIEW_PROP_CLASS, - VIEW_PROP_INSTANCE, -}; - -struct sway_view_impl { - const char *(*get_prop)(struct sway_view *view, - enum sway_view_prop prop); - void (*configure)(struct sway_view *view, double ox, double oy, int width, - int height); - void (*set_activated)(struct sway_view *view, bool activated); - void (*close)(struct sway_view *view); -}; - -struct sway_view { - enum sway_view_type type; - const struct sway_view_impl *impl; - - struct sway_container *swayc; // NULL for unmanaged views - struct wlr_surface *surface; // NULL for unmapped views - int width, height; - - union { - struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6; - struct wlr_xwayland_surface *wlr_xwayland_surface; - struct wlr_wl_shell_surface *wlr_wl_shell_surface; - }; - - union { - struct sway_xdg_surface_v6 *sway_xdg_surface_v6; - struct sway_xwayland_surface *sway_xwayland_surface; - struct sway_wl_shell_surface *sway_wl_shell_surface; - }; -}; - -struct sway_view *view_create(enum sway_view_type type, - const struct sway_view_impl *impl); - -void view_destroy(struct sway_view *view); - const char *view_get_title(struct sway_view *view); const char *view_get_app_id(struct sway_view *view); @@ -127,6 +116,11 @@ void view_damage_from(struct sway_view *view); // view implementation +void view_init(struct sway_view *view, enum sway_view_type type, + const struct sway_view_impl *impl); + +void view_destroy(struct sway_view *view); + void view_map(struct sway_view *view, struct wlr_surface *wlr_surface); void view_unmap(struct sway_view *view); diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c index a470674d..5955fa9d 100644 --- a/sway/desktop/wl_shell.c +++ b/sway/desktop/wl_shell.c @@ -11,13 +11,17 @@ #include "sway/input/input-manager.h" #include "log.h" -static bool assert_wl_shell(struct sway_view *view) { - return sway_assert(view->type == SWAY_VIEW_WL_SHELL, - "Expecting wl_shell view!"); +static struct sway_wl_shell_view *wl_shell_view_from_view( + struct sway_view *view) { + if (!sway_assert(view->type == SWAY_VIEW_WL_SHELL, + "Expected wl_shell view")) { + return NULL; + } + return (struct sway_wl_shell_view *)view; } static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) { - if (!assert_wl_shell(view)) { + if (wl_shell_view_from_view(view) == NULL) { return NULL; } switch (prop) { @@ -32,23 +36,34 @@ static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) { static void configure(struct sway_view *view, double ox, double oy, int width, int height) { - if (!assert_wl_shell(view)) { + struct sway_wl_shell_view *wl_shell_view = wl_shell_view_from_view(view); + if (wl_shell_view == NULL) { return; } view_update_position(view, ox, oy); - view->sway_wl_shell_surface->pending_width = width; - view->sway_wl_shell_surface->pending_height = height; + wl_shell_view->pending_width = width; + wl_shell_view->pending_height = height; wlr_wl_shell_surface_configure(view->wlr_wl_shell_surface, 0, width, height); } static void _close(struct sway_view *view) { - if (!assert_wl_shell(view)) { + if (wl_shell_view_from_view(view) == NULL) { return; } wl_client_destroy(view->wlr_wl_shell_surface->client); } +static void destroy(struct sway_view *view) { + struct sway_wl_shell_view *wl_shell_view = wl_shell_view_from_view(view); + if (wl_shell_view == NULL) { + return; + } + wl_list_remove(&wl_shell_view->commit.link); + wl_list_remove(&wl_shell_view->destroy.link); + free(wl_shell_view); +} + static const struct sway_view_impl view_impl = { .get_prop = get_prop, .configure = configure, @@ -56,23 +71,20 @@ static const struct sway_view_impl view_impl = { }; static void handle_commit(struct wl_listener *listener, void *data) { - struct sway_wl_shell_surface *sway_surface = - wl_container_of(listener, sway_surface, commit); - struct sway_view *view = sway_surface->view; + struct sway_wl_shell_view *wl_shell_view = + wl_container_of(listener, wl_shell_view, commit); + struct sway_view *view = &wl_shell_view->view; // NOTE: We intentionally discard the view's desired width here // TODO: Let floating views do whatever - view_update_size(view, sway_surface->pending_width, - sway_surface->pending_height); + view_update_size(view, wl_shell_view->pending_width, + wl_shell_view->pending_height); view_damage_from(view); } static void handle_destroy(struct wl_listener *listener, void *data) { - struct sway_wl_shell_surface *sway_surface = - wl_container_of(listener, sway_surface, destroy); - wl_list_remove(&sway_surface->commit.link); - wl_list_remove(&sway_surface->destroy.link); - view_destroy(sway_surface->view); - free(sway_surface); + struct sway_wl_shell_view *wl_shell_view = + wl_container_of(listener, wl_shell_view, destroy); + view_destroy(&wl_shell_view->view); } void handle_wl_shell_surface(struct wl_listener *listener, void *data) { @@ -82,42 +94,37 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { if (shell_surface->state == WLR_WL_SHELL_SURFACE_STATE_POPUP) { // popups don't get views + wlr_log(L_DEBUG, "New wl_shell popup"); return; } - // TODO make transient windows floating + // TODO: make transient windows floating wlr_log(L_DEBUG, "New wl_shell toplevel title='%s' app_id='%s'", shell_surface->title, shell_surface->class); wlr_wl_shell_surface_ping(shell_surface); - struct sway_wl_shell_surface *sway_surface = - calloc(1, sizeof(struct sway_wl_shell_surface)); - if (!sway_assert(sway_surface, "Failed to allocate surface!")) { + struct sway_wl_shell_view *wl_shell_view = + calloc(1, sizeof(struct sway_wl_shell_view)); + if (!sway_assert(wl_shell_view, "Failed to allocate view")) { return; } - struct sway_view *view = view_create(SWAY_VIEW_WL_SHELL, &view_impl); - if (!sway_assert(view, "Failed to allocate view")) { - return; - } - view->wlr_wl_shell_surface = shell_surface; - view->sway_wl_shell_surface = sway_surface; - sway_surface->view = view; + view_init(&wl_shell_view->view, SWAY_VIEW_WL_SHELL, &view_impl); + wl_shell_view->view.wlr_wl_shell_surface = shell_surface; // TODO: // - Wire up listeners - // - Handle popups // - Look up pid and open on appropriate workspace // - Set new view to maximized so it behaves nicely // - Criteria - sway_surface->commit.notify = handle_commit; + wl_shell_view->commit.notify = handle_commit; wl_signal_add(&shell_surface->surface->events.commit, - &sway_surface->commit); + &wl_shell_view->commit); - sway_surface->destroy.notify = handle_destroy; - wl_signal_add(&shell_surface->events.destroy, &sway_surface->destroy); + wl_shell_view->destroy.notify = handle_destroy; + wl_signal_add(&shell_surface->events.destroy, &wl_shell_view->destroy); - view_map(view, shell_surface->surface); + view_map(&wl_shell_view->view, shell_surface->surface); } diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 5cdb8f9f..7b9d5fb7 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -11,13 +11,17 @@ #include "sway/input/input-manager.h" #include "log.h" -static bool assert_xdg(struct sway_view *view) { - return sway_assert(view->type == SWAY_VIEW_XDG_SHELL_V6, - "Expected xdg shell v6 view!"); +static struct sway_xdg_shell_v6_view *xdg_shell_v6_view_from_view( + struct sway_view *view) { + if (!sway_assert(view->type == SWAY_VIEW_XDG_SHELL_V6, + "Expected xdg_shell_v6 view")) { + return NULL; + } + return (struct sway_xdg_shell_v6_view *)view; } static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) { - if (!assert_xdg(view)) { + if (xdg_shell_v6_view_from_view(view) == NULL) { return NULL; } switch (prop) { @@ -32,18 +36,20 @@ static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) { static void configure(struct sway_view *view, double ox, double oy, int width, int height) { - if (!assert_xdg(view)) { + struct sway_xdg_shell_v6_view *xdg_shell_v6_view = + xdg_shell_v6_view_from_view(view); + if (xdg_shell_v6_view == NULL) { return; } view_update_position(view, ox, oy); - view->sway_xdg_surface_v6->pending_width = width; - view->sway_xdg_surface_v6->pending_height = height; + xdg_shell_v6_view->pending_width = width; + xdg_shell_v6_view->pending_height = height; wlr_xdg_toplevel_v6_set_size(view->wlr_xdg_surface_v6, width, height); } static void set_activated(struct sway_view *view, bool activated) { - if (!assert_xdg(view)) { + if (xdg_shell_v6_view_from_view(view) == NULL) { return; } struct wlr_xdg_surface_v6 *surface = view->wlr_xdg_surface_v6; @@ -53,7 +59,7 @@ static void set_activated(struct sway_view *view, bool activated) { } static void _close(struct sway_view *view) { - if (!assert_xdg(view)) { + if (xdg_shell_v6_view_from_view(view) == NULL) { return; } struct wlr_xdg_surface_v6 *surface = view->wlr_xdg_surface_v6; @@ -62,6 +68,19 @@ static void _close(struct sway_view *view) { } } +static void destroy(struct sway_view *view) { + struct sway_xdg_shell_v6_view *xdg_shell_v6_view = + xdg_shell_v6_view_from_view(view); + if (xdg_shell_v6_view == NULL) { + return; + } + wl_list_remove(&xdg_shell_v6_view->commit.link); + wl_list_remove(&xdg_shell_v6_view->destroy.link); + wl_list_remove(&xdg_shell_v6_view->map.link); + wl_list_remove(&xdg_shell_v6_view->unmap.link); + free(xdg_shell_v6_view); +} + static const struct sway_view_impl view_impl = { .get_prop = get_prop, .configure = configure, @@ -70,83 +89,74 @@ static const struct sway_view_impl view_impl = { }; static void handle_commit(struct wl_listener *listener, void *data) { - struct sway_xdg_surface_v6 *sway_surface = - wl_container_of(listener, sway_surface, commit); - struct sway_view *view = sway_surface->view; + struct sway_xdg_shell_v6_view *xdg_shell_v6_view = + wl_container_of(listener, xdg_shell_v6_view, commit); + struct sway_view *view = &xdg_shell_v6_view->view; // NOTE: We intentionally discard the view's desired width here // TODO: Store this for restoration when moving to floating plane // TODO: Let floating views do whatever - view_update_size(view, sway_surface->pending_width, - sway_surface->pending_height); + view_update_size(view, xdg_shell_v6_view->pending_width, + xdg_shell_v6_view->pending_height); view_damage_from(view); } static void handle_unmap(struct wl_listener *listener, void *data) { - struct sway_xdg_surface_v6 *sway_surface = - wl_container_of(listener, sway_surface, unmap); - view_unmap(sway_surface->view); + struct sway_xdg_shell_v6_view *xdg_shell_v6_view = + wl_container_of(listener, xdg_shell_v6_view, unmap); + view_unmap(&xdg_shell_v6_view->view); } static void handle_map(struct wl_listener *listener, void *data) { - struct sway_xdg_surface_v6 *sway_surface = - wl_container_of(listener, sway_surface, map); - struct sway_view *view = sway_surface->view; + struct sway_xdg_shell_v6_view *xdg_shell_v6_view = + wl_container_of(listener, xdg_shell_v6_view, map); + struct sway_view *view = &xdg_shell_v6_view->view; view_map(view, view->wlr_xdg_surface_v6->surface); } static void handle_destroy(struct wl_listener *listener, void *data) { - struct sway_xdg_surface_v6 *sway_xdg_surface = - wl_container_of(listener, sway_xdg_surface, destroy); - wl_list_remove(&sway_xdg_surface->commit.link); - wl_list_remove(&sway_xdg_surface->destroy.link); - wl_list_remove(&sway_xdg_surface->map.link); - wl_list_remove(&sway_xdg_surface->unmap.link); - view_destroy(sway_xdg_surface->view); - free(sway_xdg_surface); + struct sway_xdg_shell_v6_view *xdg_shell_v6_view = + wl_container_of(listener, xdg_shell_v6_view, destroy); + view_destroy(&xdg_shell_v6_view->view); } void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { - struct sway_server *server = wl_container_of( - listener, server, xdg_shell_v6_surface); + struct sway_server *server = wl_container_of(listener, server, + xdg_shell_v6_surface); struct wlr_xdg_surface_v6 *xdg_surface = data; if (xdg_surface->role == WLR_XDG_SURFACE_V6_ROLE_POPUP) { - // TODO: popups + wlr_log(L_DEBUG, "New xdg_shell_v6 popup"); return; } wlr_log(L_DEBUG, "New xdg_shell_v6 toplevel title='%s' app_id='%s'", - xdg_surface->toplevel->title, xdg_surface->toplevel->app_id); + xdg_surface->toplevel->title, xdg_surface->toplevel->app_id); wlr_xdg_surface_v6_ping(xdg_surface); wlr_xdg_toplevel_v6_set_maximized(xdg_surface, true); - struct sway_xdg_surface_v6 *sway_surface = - calloc(1, sizeof(struct sway_xdg_surface_v6)); - if (!sway_assert(sway_surface, "Failed to allocate surface!")) { + struct sway_xdg_shell_v6_view *xdg_shell_v6_view = + calloc(1, sizeof(struct sway_xdg_shell_v6_view)); + if (!sway_assert(xdg_shell_v6_view, "Failed to allocate view")) { return; } - struct sway_view *view = view_create(SWAY_VIEW_XDG_SHELL_V6, &view_impl); - if (!sway_assert(view, "Failed to allocate view")) { - return; - } - view->wlr_xdg_surface_v6 = xdg_surface; - view->sway_xdg_surface_v6 = sway_surface; - sway_surface->view = view; + view_init(&xdg_shell_v6_view->view, SWAY_VIEW_XDG_SHELL_V6, &view_impl); + xdg_shell_v6_view->view.wlr_xdg_surface_v6 = xdg_surface; // TODO: // - Look up pid and open on appropriate workspace // - Criteria - sway_surface->commit.notify = handle_commit; - wl_signal_add(&xdg_surface->surface->events.commit, &sway_surface->commit); + xdg_shell_v6_view->commit.notify = handle_commit; + wl_signal_add(&xdg_surface->surface->events.commit, + &xdg_shell_v6_view->commit); - sway_surface->map.notify = handle_map; - wl_signal_add(&xdg_surface->events.map, &sway_surface->map); + xdg_shell_v6_view->map.notify = handle_map; + wl_signal_add(&xdg_surface->events.map, &xdg_shell_v6_view->map); - sway_surface->unmap.notify = handle_unmap; - wl_signal_add(&xdg_surface->events.unmap, &sway_surface->unmap); + xdg_shell_v6_view->unmap.notify = handle_unmap; + wl_signal_add(&xdg_surface->events.unmap, &xdg_shell_v6_view->unmap); - sway_surface->destroy.notify = handle_destroy; - wl_signal_add(&xdg_surface->events.destroy, &sway_surface->destroy); + xdg_shell_v6_view->destroy.notify = handle_destroy; + wl_signal_add(&xdg_surface->events.destroy, &xdg_shell_v6_view->destroy); } diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index a793928c..384f4236 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -41,13 +41,17 @@ static void create_unmanaged(struct wlr_xwayland_surface *xsurface) { } -static bool assert_xwayland(struct sway_view *view) { - return sway_assert(view->type == SWAY_VIEW_XWAYLAND, - "Expected xwayland view!"); +static struct sway_xwayland_view *xwayland_view_from_view( + struct sway_view *view) { + if (!sway_assert(view->type == SWAY_VIEW_XWAYLAND, + "Expected xwayland view")) { + return NULL; + } + return (struct sway_xwayland_view *)view; } static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) { - if (!assert_xwayland(view)) { + if (xwayland_view_from_view(view) == NULL) { return NULL; } switch (prop) { @@ -62,7 +66,8 @@ static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) { static void configure(struct sway_view *view, double ox, double oy, int width, int height) { - if (!assert_xwayland(view)) { + struct sway_xwayland_view *xwayland_view = xwayland_view_from_view(view); + if (xwayland_view == NULL) { return; } struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; @@ -84,14 +89,14 @@ static void configure(struct sway_view *view, double ox, double oy, int width, view_update_position(view, ox, oy); - view->sway_xwayland_surface->pending_width = width; - view->sway_xwayland_surface->pending_height = height; + xwayland_view->pending_width = width; + xwayland_view->pending_height = height; wlr_xwayland_surface_configure(xsurface, ox + loutput->x, oy + loutput->y, width, height); } static void set_activated(struct sway_view *view, bool activated) { - if (!assert_xwayland(view)) { + if (xwayland_view_from_view(view) == NULL) { return; } struct wlr_xwayland_surface *surface = view->wlr_xwayland_surface; @@ -99,12 +104,24 @@ static void set_activated(struct sway_view *view, bool activated) { } static void _close(struct sway_view *view) { - if (!assert_xwayland(view)) { + if (xwayland_view_from_view(view) == NULL) { return; } wlr_xwayland_surface_close(view->wlr_xwayland_surface); } +static void destroy(struct sway_view *view) { + struct sway_xwayland_view *xwayland_view = xwayland_view_from_view(view); + if (xwayland_view == NULL) { + return; + } + wl_list_remove(&xwayland_view->destroy.link); + wl_list_remove(&xwayland_view->request_configure.link); + wl_list_remove(&xwayland_view->map.link); + wl_list_remove(&xwayland_view->unmap.link); + free(xwayland_view); +} + static const struct sway_view_impl view_impl = { .get_prop = get_prop, .configure = configure, @@ -113,50 +130,50 @@ static const struct sway_view_impl view_impl = { }; static void handle_commit(struct wl_listener *listener, void *data) { - struct sway_xwayland_surface *sway_surface = - wl_container_of(listener, sway_surface, commit); - struct sway_view *view = sway_surface->view; + struct sway_xwayland_view *xwayland_view = + wl_container_of(listener, xwayland_view, commit); + struct sway_view *view = &xwayland_view->view; // NOTE: We intentionally discard the view's desired width here // TODO: Let floating views do whatever - view_update_size(view, sway_surface->pending_width, - sway_surface->pending_height); + view_update_size(view, xwayland_view->pending_width, + xwayland_view->pending_height); view_damage_from(view); } static void handle_destroy(struct wl_listener *listener, void *data) { - struct sway_xwayland_surface *sway_surface = - wl_container_of(listener, sway_surface, destroy); - wl_list_remove(&sway_surface->commit.link); - wl_list_remove(&sway_surface->destroy.link); - wl_list_remove(&sway_surface->request_configure.link); - wl_list_remove(&sway_surface->map.link); - wl_list_remove(&sway_surface->unmap.link); - view_destroy(sway_surface->view); - free(sway_surface); + struct sway_xwayland_view *xwayland_view = + wl_container_of(listener, xwayland_view, destroy); + view_destroy(&xwayland_view->view); } static void handle_unmap(struct wl_listener *listener, void *data) { - struct sway_xwayland_surface *sway_surface = - wl_container_of(listener, sway_surface, unmap); - view_unmap(sway_surface->view); + struct sway_xwayland_view *xwayland_view = + wl_container_of(listener, xwayland_view, unmap); + wl_list_remove(&xwayland_view->commit.link); + view_unmap(&xwayland_view->view); } static void handle_map(struct wl_listener *listener, void *data) { - struct sway_xwayland_surface *sway_surface = - wl_container_of(listener, sway_surface, map); + struct sway_xwayland_view *xwayland_view = + wl_container_of(listener, xwayland_view, map); struct wlr_xwayland_surface *xsurface = data; - struct sway_view *view = sway_surface->view; + struct sway_view *view = &xwayland_view->view; + + // Wire up the commit listener here, because xwayland map/unmap can change + // the underlying wlr_surface + wl_signal_add(&xsurface->surface->events.commit, &xwayland_view->commit); + xwayland_view->commit.notify = handle_commit; - // put it back into the tree + // Put it back into the tree wlr_xwayland_surface_set_maximized(xsurface, true); view_map(view, xsurface->surface); } static void handle_request_configure(struct wl_listener *listener, void *data) { - struct sway_xwayland_surface *sway_surface = - wl_container_of(listener, sway_surface, request_configure); + struct sway_xwayland_view *xwayland_view = + wl_container_of(listener, xwayland_view, request_configure); struct wlr_xwayland_surface_configure_event *ev = data; - struct sway_view *view = sway_surface->view; + struct sway_view *view = &xwayland_view->view; struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; // TODO: floating windows are allowed to move around like this, but make // sure tiling windows always stay in place. @@ -165,8 +182,8 @@ static void handle_request_configure(struct wl_listener *listener, void *data) { } void handle_xwayland_surface(struct wl_listener *listener, void *data) { - struct sway_server *server = wl_container_of( - listener, server, xwayland_surface); + struct sway_server *server = wl_container_of(listener, server, + xwayland_surface); struct wlr_xwayland_surface *xsurface = data; if (wlr_xwayland_surface_is_unmanaged(xsurface) || @@ -179,39 +196,31 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { wlr_log(L_DEBUG, "New xwayland surface title='%s' class='%s'", xsurface->title, xsurface->class); - struct sway_xwayland_surface *sway_surface = - calloc(1, sizeof(struct sway_xwayland_surface)); - if (!sway_assert(sway_surface, "Failed to allocate surface")) { + struct sway_xwayland_view *xwayland_view = + calloc(1, sizeof(struct sway_xwayland_view)); + if (!sway_assert(xwayland_view, "Failed to allocate view")) { return; } - struct sway_view *view = view_create(SWAY_VIEW_XWAYLAND, &view_impl); - if (!sway_assert(view, "Failed to allocate view")) { - return; - } - view->wlr_xwayland_surface = xsurface; - view->sway_xwayland_surface = sway_surface; - sway_surface->view = view; + view_init(&xwayland_view->view, SWAY_VIEW_XWAYLAND, &view_impl); + xwayland_view->view.wlr_xwayland_surface = xsurface; // TODO: // - Look up pid and open on appropriate workspace // - Criteria - wl_signal_add(&xsurface->surface->events.commit, &sway_surface->commit); - sway_surface->commit.notify = handle_commit; - - wl_signal_add(&xsurface->events.destroy, &sway_surface->destroy); - sway_surface->destroy.notify = handle_destroy; + wl_signal_add(&xsurface->events.destroy, &xwayland_view->destroy); + xwayland_view->destroy.notify = handle_destroy; wl_signal_add(&xsurface->events.request_configure, - &sway_surface->request_configure); - sway_surface->request_configure.notify = handle_request_configure; + &xwayland_view->request_configure); + xwayland_view->request_configure.notify = handle_request_configure; - wl_signal_add(&xsurface->events.unmap, &sway_surface->unmap); - sway_surface->unmap.notify = handle_unmap; + wl_signal_add(&xsurface->events.unmap, &xwayland_view->unmap); + xwayland_view->unmap.notify = handle_unmap; - wl_signal_add(&xsurface->events.map, &sway_surface->map); - sway_surface->map.notify = handle_map; + wl_signal_add(&xsurface->events.map, &xwayland_view->map); + xwayland_view->map.notify = handle_map; - handle_map(&sway_surface->map, xsurface); + handle_map(&xwayland_view->map, xsurface); } diff --git a/sway/tree/view.c b/sway/tree/view.c index aa010a40..3927c195 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -7,15 +7,10 @@ #include "sway/tree/layout.h" #include "sway/tree/view.h" -struct sway_view *view_create(enum sway_view_type type, +void view_init(struct sway_view *view, enum sway_view_type type, const struct sway_view_impl *impl) { - struct sway_view *view = calloc(1, sizeof(struct sway_view)); - if (view == NULL) { - return NULL; - } view->type = type; view->impl = impl; - return view; } void view_destroy(struct sway_view *view) { @@ -28,6 +23,12 @@ void view_destroy(struct sway_view *view) { } container_destroy(view->swayc); + + if (view->impl->destroy) { + view->impl->destroy(view); + } else { + free(view); + } } const char *view_get_title(struct sway_view *view) {