diff --git a/include/rootston/desktop.h b/include/rootston/desktop.h index 467de8ab..61fe47b0 100644 --- a/include/rootston/desktop.h +++ b/include/rootston/desktop.h @@ -71,14 +71,16 @@ struct roots_output *desktop_output_from_wlr_output( struct roots_view *desktop_view_at(struct roots_desktop *desktop, double lx, double ly, struct wlr_surface **surface, double *sx, double *sy); -void view_init(struct roots_view *view, struct roots_desktop *desktop); -void view_finish(struct roots_view *view); +struct roots_view *view_create(struct roots_desktop *desktop); +void view_destroy(struct roots_view *view); void view_activate(struct roots_view *view, bool activate); void view_apply_damage(struct roots_view *view); void view_damage_whole(struct roots_view *view); void view_update_position(struct roots_view *view, double x, double y); void view_update_size(struct roots_view *view, uint32_t width, uint32_t height); void view_initial_focus(struct roots_view *view); +void view_map(struct roots_view *view, struct wlr_surface *surface); +void view_unmap(struct roots_view *view); void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data); void handle_xdg_shell_surface(struct wl_listener *listener, void *data); diff --git a/include/rootston/view.h b/include/rootston/view.h index ff5ef44a..66a0cb3d 100644 --- a/include/rootston/view.h +++ b/include/rootston/view.h @@ -181,7 +181,6 @@ struct roots_xdg_popup { struct wl_listener new_popup; }; -struct roots_view *view_create(); void view_get_box(const struct roots_view *view, struct wlr_box *box); void view_activate(struct roots_view *view, bool active); void view_move(struct roots_view *view, double x, double y); diff --git a/rootston/desktop.c b/rootston/desktop.c index 3628b051..66c7ac2b 100644 --- a/rootston/desktop.c +++ b/rootston/desktop.c @@ -23,13 +23,15 @@ #include "rootston/view.h" #include "rootston/xcursor.h" - -struct roots_view *view_create() { +struct roots_view *view_create(struct roots_desktop *desktop) { struct roots_view *view = calloc(1, sizeof(struct roots_view)); if (!view) { return NULL; } + view->desktop = desktop; view->alpha = 1.0f; + wl_signal_init(&view->events.destroy); + wl_list_init(&view->children); return view; } @@ -402,20 +404,18 @@ struct roots_subsurface *subsurface_create(struct roots_view *view, return subsurface; } -void view_finish(struct roots_view *view) { - view_damage_whole(view); +void view_destroy(struct roots_view *view) { + if (view == NULL) { + return; + } + + if (view->wlr_surface != NULL) { + view_unmap(view); + } + wl_signal_emit(&view->events.destroy, view); - wl_list_remove(&view->new_subsurface.link); - - struct roots_view_child *child, *tmp; - wl_list_for_each_safe(child, tmp, &view->children, link) { - child->destroy(child); - } - - if (view->fullscreen_output) { - view->fullscreen_output->fullscreen_view = NULL; - } + free(view); } static void view_handle_new_subsurface(struct wl_listener *listener, @@ -425,12 +425,10 @@ static void view_handle_new_subsurface(struct wl_listener *listener, subsurface_create(view, wlr_subsurface); } -void view_init(struct roots_view *view, struct roots_desktop *desktop) { - assert(view->wlr_surface); +void view_map(struct roots_view *view, struct wlr_surface *surface) { + assert(view->wlr_surface == NULL); - view->desktop = desktop; - wl_signal_init(&view->events.destroy); - wl_list_init(&view->children); + view->wlr_surface = surface; struct wlr_subsurface *subsurface; wl_list_for_each(subsurface, &view->wlr_surface->subsurface_list, @@ -442,9 +440,33 @@ void view_init(struct roots_view *view, struct roots_desktop *desktop) { wl_signal_add(&view->wlr_surface->events.new_subsurface, &view->new_subsurface); + wl_list_insert(&view->desktop->views, &view->link); view_damage_whole(view); } +void view_unmap(struct roots_view *view) { + assert(view->wlr_surface != NULL); + + view_damage_whole(view); + wl_list_remove(&view->link); + + wl_list_remove(&view->new_subsurface.link); + + struct roots_view_child *child, *tmp; + wl_list_for_each_safe(child, tmp, &view->children, link) { + child->destroy(child); + } + + if (view->fullscreen_output != NULL) { + output_damage_whole(view->fullscreen_output); + view->fullscreen_output->fullscreen_view = NULL; + view->fullscreen_output = NULL; + } + + view->wlr_surface = NULL; + view->width = view->height = 0; +} + void view_initial_focus(struct roots_view *view) { struct roots_input *input = view->desktop->server->input; // TODO what seat gets focus? the one with the last input event? diff --git a/rootston/wl_shell.c b/rootston/wl_shell.c index 899df1c6..6326d9d7 100644 --- a/rootston/wl_shell.c +++ b/rootston/wl_shell.c @@ -181,9 +181,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) { wl_list_remove(&roots_surface->request_fullscreen.link); wl_list_remove(&roots_surface->set_state.link); wl_list_remove(&roots_surface->surface_commit.link); - wl_list_remove(&roots_surface->view->link); - view_finish(roots_surface->view); - free(roots_surface->view); + view_destroy(roots_surface->view); free(roots_surface); } @@ -227,7 +225,7 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { roots_surface->surface_commit.notify = handle_surface_commit; wl_signal_add(&surface->surface->events.commit, &roots_surface->surface_commit); - struct roots_view *view = view_create(); + struct roots_view *view = view_create(desktop); if (!view) { free(roots_surface); return; @@ -238,13 +236,11 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { view->wl_shell_surface = surface; view->roots_wl_shell_surface = roots_surface; - view->wlr_surface = surface->surface; view->resize = resize; view->close = close; roots_surface->view = view; - view_init(view, desktop); - wl_list_insert(&desktop->views, &view->link); + view_map(view, surface->surface); view_setup(view); if (surface->state == WLR_WL_SHELL_SURFACE_STATE_TRANSIENT) { diff --git a/rootston/xdg_shell.c b/rootston/xdg_shell.c index 9368ce0b..1733eb4e 100644 --- a/rootston/xdg_shell.c +++ b/rootston/xdg_shell.c @@ -287,9 +287,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) { wl_list_remove(&roots_xdg_surface->request_resize.link); wl_list_remove(&roots_xdg_surface->request_maximize.link); wl_list_remove(&roots_xdg_surface->request_fullscreen.link); - wl_list_remove(&roots_xdg_surface->view->link); - view_finish(roots_xdg_surface->view); - free(roots_xdg_surface->view); + view_destroy(roots_xdg_surface->view); free(roots_xdg_surface); } @@ -333,7 +331,7 @@ void handle_xdg_shell_surface(struct wl_listener *listener, void *data) { roots_surface->new_popup.notify = handle_new_popup; wl_signal_add(&surface->events.new_popup, &roots_surface->new_popup); - struct roots_view *view = view_create(); + struct roots_view *view = view_create(desktop); if (!view) { free(roots_surface); return; @@ -342,7 +340,6 @@ void handle_xdg_shell_surface(struct wl_listener *listener, void *data) { view->xdg_surface = surface; view->roots_xdg_surface = roots_surface; - view->wlr_surface = surface->surface; view->activate = activate; view->resize = resize; view->move_resize = move_resize; @@ -356,8 +353,6 @@ void handle_xdg_shell_surface(struct wl_listener *listener, void *data) { view->width = box.width; view->height = box.height; - view_init(view, desktop); - wl_list_insert(&desktop->views, &view->link); - + view_map(view, surface->surface); view_setup(view); } diff --git a/rootston/xdg_shell_v6.c b/rootston/xdg_shell_v6.c index eda349cb..c49bd911 100644 --- a/rootston/xdg_shell_v6.c +++ b/rootston/xdg_shell_v6.c @@ -287,9 +287,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) { wl_list_remove(&roots_xdg_surface->request_resize.link); wl_list_remove(&roots_xdg_surface->request_maximize.link); wl_list_remove(&roots_xdg_surface->request_fullscreen.link); - wl_list_remove(&roots_xdg_surface->view->link); - view_finish(roots_xdg_surface->view); - free(roots_xdg_surface->view); + view_destroy(roots_xdg_surface->view); free(roots_xdg_surface); } @@ -333,7 +331,7 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { roots_surface->new_popup.notify = handle_new_popup; wl_signal_add(&surface->events.new_popup, &roots_surface->new_popup); - struct roots_view *view = view_create(); + struct roots_view *view = view_create(desktop); if (!view) { free(roots_surface); return; @@ -342,7 +340,6 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { view->xdg_surface_v6 = surface; view->roots_xdg_surface_v6 = roots_surface; - view->wlr_surface = surface->surface; view->activate = activate; view->resize = resize; view->move_resize = move_resize; @@ -356,8 +353,6 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { view->width = box.width; view->height = box.height; - view_init(view, desktop); - wl_list_insert(&desktop->views, &view->link); - + view_map(view, surface->surface); view_setup(view); } diff --git a/rootston/xwayland.c b/rootston/xwayland.c index 56f068ea..f95e5f81 100644 --- a/rootston/xwayland.c +++ b/rootston/xwayland.c @@ -109,8 +109,6 @@ static void set_fullscreen(struct roots_view *view, bool fullscreen) { static void handle_destroy(struct wl_listener *listener, void *data) { struct roots_xwayland_surface *roots_surface = wl_container_of(listener, roots_surface, destroy); - struct wlr_xwayland_surface *xwayland_surface = - roots_surface->view->xwayland_surface; wl_list_remove(&roots_surface->destroy.link); wl_list_remove(&roots_surface->request_configure.link); wl_list_remove(&roots_surface->request_move.link); @@ -118,11 +116,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) { wl_list_remove(&roots_surface->request_maximize.link); wl_list_remove(&roots_surface->map_notify.link); wl_list_remove(&roots_surface->unmap_notify.link); - if (xwayland_surface->mapped) { - wl_list_remove(&roots_surface->view->link); - } - view_finish(roots_surface->view); - free(roots_surface->view); + view_destroy(roots_surface->view); free(roots_surface); } @@ -231,22 +225,13 @@ static void handle_map_notify(struct wl_listener *listener, void *data) { wl_container_of(listener, roots_surface, map_notify); struct wlr_xwayland_surface *xsurface = data; struct roots_view *view = roots_surface->view; - struct roots_desktop *desktop = view->desktop; - view->wlr_surface = xsurface->surface; view->x = xsurface->x; view->y = xsurface->y; view->width = xsurface->surface->current->width; view->height = xsurface->surface->current->height; - wl_list_insert(&desktop->views, &view->link); - struct wlr_subsurface *subsurface; - wl_list_for_each(subsurface, &view->wlr_surface->subsurface_list, - parent_link) { - subsurface_create(view, subsurface); - } - - view_damage_whole(view); + view_map(view, xsurface->surface); roots_surface->surface_commit.notify = handle_surface_commit; wl_signal_add(&xsurface->surface->events.commit, @@ -260,22 +245,7 @@ static void handle_unmap_notify(struct wl_listener *listener, void *data) { wl_list_remove(&roots_surface->surface_commit.link); - view_damage_whole(view); - - struct roots_view_child *child, *tmp; - wl_list_for_each_safe(child, tmp, &view->children, link) { - child->destroy(child); - } - - if (view->fullscreen_output != NULL) { - output_damage_whole(view->fullscreen_output); - view->fullscreen_output->fullscreen_view = NULL; - view->fullscreen_output = NULL; - } - - view->wlr_surface = NULL; - view->width = view->height = 0; - wl_list_remove(&view->link); + view_unmap(view); } void handle_xwayland_surface(struct wl_listener *listener, void *data) { @@ -317,7 +287,7 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { wl_signal_add(&surface->surface->events.commit, &roots_surface->surface_commit); - struct roots_view *view = view_create(); + struct roots_view *view = view_create(desktop); if (view == NULL) { free(roots_surface); return; @@ -330,7 +300,6 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { view->xwayland_surface = surface; view->roots_xwayland_surface = roots_surface; - view->wlr_surface = surface->surface; view->activate = activate; view->resize = resize; view->move = move; @@ -339,8 +308,8 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { view->set_fullscreen = set_fullscreen; view->close = close; roots_surface->view = view; - view_init(view, desktop); - wl_list_insert(&desktop->views, &view->link); + + view_map(view, surface->surface); if (!surface->override_redirect) { if (surface->decorations == WLR_XWAYLAND_SURFACE_DECORATIONS_ALL) {