diff --git a/include/rootston/view.h b/include/rootston/view.h index 66a0cb3d..0844a6da 100644 --- a/include/rootston/view.h +++ b/include/rootston/view.h @@ -27,6 +27,8 @@ struct roots_xdg_surface_v6 { struct wl_listener destroy; struct wl_listener new_popup; + struct wl_listener map; + struct wl_listener unmap; struct wl_listener request_move; struct wl_listener request_resize; struct wl_listener request_maximize; diff --git a/include/wlr/types/wlr_xdg_shell_v6.h b/include/wlr/types/wlr_xdg_shell_v6.h index 7dc746ce..959d420f 100644 --- a/include/wlr/types/wlr_xdg_shell_v6.h +++ b/include/wlr/types/wlr_xdg_shell_v6.h @@ -107,8 +107,7 @@ struct wlr_xdg_surface_v6 { struct wl_list popups; // wlr_xdg_popup_v6::link - bool configured; - bool added; + bool added, configured, mapped; uint32_t configure_serial; struct wl_event_source *configure_idle; uint32_t configure_next_serial; @@ -127,6 +126,8 @@ struct wlr_xdg_surface_v6 { struct wl_signal destroy; struct wl_signal ping_timeout; struct wl_signal new_popup; + struct wl_signal map; + struct wl_signal unmap; struct wl_signal request_maximize; struct wl_signal request_fullscreen; diff --git a/rootston/desktop.c b/rootston/desktop.c index 66c7ac2b..278f4fea 100644 --- a/rootston/desktop.c +++ b/rootston/desktop.c @@ -54,7 +54,8 @@ void view_get_deco_box(const struct roots_view *view, struct wlr_box *box) { box->height += (view->border_width * 2 + view->titlebar_height); } -enum roots_deco_part view_get_deco_part(struct roots_view *view, double sx, double sy) { +enum roots_deco_part view_get_deco_part(struct roots_view *view, double sx, + double sy) { if (!view->decorated) { return ROOTS_DECO_PART_NONE; } @@ -94,9 +95,15 @@ enum roots_deco_part view_get_deco_part(struct roots_view *view, double sx, doub static void view_update_output(const struct roots_view *view, const struct wlr_box *before) { struct roots_desktop *desktop = view->desktop; - struct roots_output *output; + + if (view->wlr_surface == NULL) { + return; + } + struct wlr_box box; view_get_box(view, &box); + + struct roots_output *output; wl_list_for_each(output, &desktop->outputs, link) { bool intersected = before != NULL && wlr_output_layout_intersects( desktop->layout, output->wlr_output, before); @@ -479,7 +486,10 @@ void view_initial_focus(struct roots_view *view) { void view_setup(struct roots_view *view) { view_initial_focus(view); - view_center(view); + if (view->fullscreen_output == NULL) { + view_center(view); + } + view_update_output(view, NULL); } diff --git a/rootston/output.c b/rootston/output.c index 4d0a9c05..adcbb961 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -501,7 +501,9 @@ static void render_output(struct roots_output *output) { goto renderer_end; } - view_for_each_surface(view, render_surface, &data); + if (view->wlr_surface != NULL) { + view_for_each_surface(view, render_surface, &data); + } // During normal rendering the xwayland window tree isn't traversed // because all windows are rendered. Here we only want to render @@ -570,6 +572,9 @@ void output_damage_whole(struct roots_output *output) { static bool view_accept_damage(struct roots_output *output, struct roots_view *view) { + if (view->wlr_surface == NULL) { + return false; + } if (output->fullscreen_view == NULL) { return true; } diff --git a/rootston/xdg_shell_v6.c b/rootston/xdg_shell_v6.c index c49bd911..4591f642 100644 --- a/rootston/xdg_shell_v6.c +++ b/rootston/xdg_shell_v6.c @@ -243,6 +243,10 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) { struct roots_view *view = roots_surface->view; struct wlr_xdg_surface_v6 *surface = view->xdg_surface_v6; + if (!surface->mapped) { + return; + } + view_apply_damage(view); struct wlr_box size; @@ -277,6 +281,28 @@ static void handle_new_popup(struct wl_listener *listener, void *data) { popup_create(roots_xdg_surface->view, wlr_popup); } +static void handle_map(struct wl_listener *listener, void *data) { + struct roots_xdg_surface_v6 *roots_xdg_surface = + wl_container_of(listener, roots_xdg_surface, map); + struct roots_view *view = roots_xdg_surface->view; + + struct wlr_box box; + get_size(view, &box); + view->width = box.width; + view->height = box.height; + + view_map(view, view->xdg_surface_v6->surface); + view_setup(view); +} + +static void handle_unmap(struct wl_listener *listener, void *data) { + struct roots_xdg_surface_v6 *roots_xdg_surface = + wl_container_of(listener, roots_xdg_surface, unmap); + struct roots_view *view = roots_xdg_surface->view; + + view_unmap(view); +} + static void handle_destroy(struct wl_listener *listener, void *data) { struct roots_xdg_surface_v6 *roots_xdg_surface = wl_container_of(listener, roots_xdg_surface, destroy); @@ -317,6 +343,10 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { &roots_surface->surface_commit); roots_surface->destroy.notify = handle_destroy; wl_signal_add(&surface->events.destroy, &roots_surface->destroy); + roots_surface->map.notify = handle_map; + wl_signal_add(&surface->events.map, &roots_surface->map); + roots_surface->unmap.notify = handle_unmap; + wl_signal_add(&surface->events.unmap, &roots_surface->unmap); roots_surface->request_move.notify = handle_request_move; wl_signal_add(&surface->events.request_move, &roots_surface->request_move); roots_surface->request_resize.notify = handle_request_resize; @@ -347,12 +377,4 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { view->set_fullscreen = set_fullscreen; view->close = close; roots_surface->view = view; - - struct wlr_box box; - get_size(view, &box); - view->width = box.width; - view->height = box.height; - - view_map(view, surface->surface); - view_setup(view); } diff --git a/types/wlr_xdg_shell_v6.c b/types/wlr_xdg_shell_v6.c index e07d78a1..18f7393d 100644 --- a/types/wlr_xdg_shell_v6.c +++ b/types/wlr_xdg_shell_v6.c @@ -481,6 +481,7 @@ static void xdg_popup_resource_destroy(struct wl_resource *resource) { struct wlr_xdg_surface_v6 *surface = xdg_surface_from_xdg_popup_resource(resource); if (surface != NULL) { + // TODO: don't destroy the surface, unmap it xdg_surface_destroy(surface); } } @@ -792,6 +793,7 @@ static void xdg_toplevel_resource_destroy(struct wl_resource *resource) { struct wlr_xdg_surface_v6 *surface = xdg_surface_from_xdg_toplevel_resource(resource); if (surface != NULL) { + // TODO: don't destroy the surface, unmap it xdg_surface_destroy(surface); } } @@ -1172,9 +1174,19 @@ static void handle_wlr_surface_committed(struct wlr_surface *wlr_surface, break; } - if (surface->configured && !surface->added) { + if (!surface->added) { surface->added = true; - wlr_signal_emit_safe(&surface->client->shell->events.new_surface, surface); + wlr_signal_emit_safe(&surface->client->shell->events.new_surface, + surface); + } + if (surface->configured && wlr_surface_has_buffer(surface->surface) && + !surface->mapped) { + surface->mapped = true; + wlr_signal_emit_safe(&surface->events.map, surface); + } + if (surface->configured && !wlr_surface_has_buffer(surface->surface) && + surface->mapped) { + // TODO: unmap the surface } } @@ -1249,6 +1261,8 @@ static void xdg_shell_get_xdg_surface(struct wl_client *wl_client, wl_signal_init(&surface->events.destroy); wl_signal_init(&surface->events.ping_timeout); wl_signal_init(&surface->events.new_popup); + wl_signal_init(&surface->events.map); + wl_signal_init(&surface->events.unmap); wl_signal_add(&surface->surface->events.destroy, &surface->surface_destroy_listener);