From c3615a8b57a608db80d70f794229a1f271f1ad15 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Wed, 31 Aug 2022 21:44:19 -0400 Subject: [PATCH] scene_graph: Port xdg_shell --- include/sway/scene_descriptor.h | 1 + include/sway/tree/view.h | 18 +-- sway/desktop/output.c | 15 +- sway/desktop/xdg_shell.c | 63 +++++---- sway/input/cursor.c | 4 + sway/tree/view.c | 244 -------------------------------- 6 files changed, 58 insertions(+), 287 deletions(-) diff --git a/include/sway/scene_descriptor.h b/include/sway/scene_descriptor.h index 3f96338aa..746ae7d8b 100644 --- a/include/sway/scene_descriptor.h +++ b/include/sway/scene_descriptor.h @@ -7,6 +7,7 @@ enum sway_scene_descriptor_type { SWAY_SCENE_DESC_NON_INTERACTIVE, SWAY_SCENE_DESC_CONTAINER, SWAY_SCENE_DESC_LAYER_SHELL, + SWAY_SCENE_DESC_POPUP, SWAY_SCENE_DESC_DRAG_ICON, }; diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 48dc53368..f1c1ee087 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -122,8 +122,6 @@ struct sway_view { struct wl_signal unmap; } events; - struct wl_listener surface_new_subsurface; - int max_render_time; // In milliseconds enum seat_config_shortcuts_inhibit shortcuts_inhibit; @@ -188,7 +186,6 @@ struct sway_xwayland_unmanaged { struct sway_view_child; struct sway_view_child_impl { - void (*get_view_coords)(struct sway_view_child *child, int *sx, int *sy); void (*destroy)(struct sway_view_child *child); }; @@ -203,20 +200,9 @@ struct sway_view_child { struct sway_view_child *parent; struct wl_list children; // sway_view_child::link struct wlr_surface *surface; - bool mapped; - struct wl_listener surface_commit; - struct wl_listener surface_new_subsurface; - struct wl_listener surface_map; - struct wl_listener surface_unmap; - struct wl_listener surface_destroy; - struct wl_listener view_unmap; -}; - -struct sway_subsurface { - struct sway_view_child child; - - struct wl_listener destroy; + struct wlr_scene_tree *scene_tree; + struct wlr_scene_tree *xdg_surface_tree; }; struct sway_xdg_popup { diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 4fd1d2c2d..0932e5b97 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -273,7 +273,20 @@ static void send_frame_done_iterator(struct wlr_scene_buffer *buffer, while (true) { if (current->data) { - + struct sway_scene_descriptor *desc = current->data; + + if (desc->type == SWAY_SCENE_DESC_CONTAINER) { + struct sway_container *con = desc->data; + + // We can be dealing with a title bar without owned by a + // container without a view. This will happen if you have a + // nested tabbed view for example. + if (con->view) { + view_max_render_time = con->view->max_render_time; + } + + break; + } } if (!current->parent) { diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index 9ce7d611c..faac1ec72 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -7,7 +7,7 @@ #include #include "log.h" #include "sway/decoration.h" -#include "sway/desktop.h" +#include "sway/scene_descriptor.h" #include "sway/desktop/transaction.h" #include "sway/input/cursor.h" #include "sway/input/input-manager.h" @@ -21,17 +21,6 @@ static const struct sway_view_child_impl popup_impl; -static void popup_get_view_coords(struct sway_view_child *child, - int *sx, int *sy) { - struct sway_xdg_popup *popup = (struct sway_xdg_popup *)child; - struct wlr_xdg_popup *wlr_popup = popup->wlr_xdg_popup; - - wlr_xdg_popup_get_toplevel_coords(wlr_popup, - wlr_popup->current.geometry.x - wlr_popup->base->current.geometry.x, - wlr_popup->current.geometry.y - wlr_popup->base->current.geometry.y, - sx, sy); -} - static void popup_destroy(struct sway_view_child *child) { if (!sway_assert(child->impl == &popup_impl, "Expected an xdg_shell popup")) { @@ -40,22 +29,25 @@ static void popup_destroy(struct sway_view_child *child) { struct sway_xdg_popup *popup = (struct sway_xdg_popup *)child; wl_list_remove(&popup->new_popup.link); wl_list_remove(&popup->destroy.link); + + wlr_scene_node_destroy(&child->scene_tree->node); + free(popup); } static const struct sway_view_child_impl popup_impl = { - .get_view_coords = popup_get_view_coords, .destroy = popup_destroy, }; static struct sway_xdg_popup *popup_create( - struct wlr_xdg_popup *wlr_popup, struct sway_view *view); + struct wlr_xdg_popup *wlr_popup, struct sway_view *view, + struct wlr_scene_tree *parent); static void popup_handle_new_popup(struct wl_listener *listener, void *data) { struct sway_xdg_popup *popup = wl_container_of(listener, popup, new_popup); struct wlr_xdg_popup *wlr_popup = data; - popup_create(wlr_popup, popup->child.view); + popup_create(wlr_popup, popup->child.view, popup->child.xdg_surface_tree); } static void popup_handle_destroy(struct wl_listener *listener, void *data) { @@ -82,7 +74,8 @@ static void popup_unconstrain(struct sway_xdg_popup *popup) { } static struct sway_xdg_popup *popup_create( - struct wlr_xdg_popup *wlr_popup, struct sway_view *view) { + struct wlr_xdg_popup *wlr_popup, struct sway_view *view, + struct wlr_scene_tree *parent) { struct wlr_xdg_surface *xdg_surface = wlr_popup->base; struct sway_xdg_popup *popup = @@ -90,19 +83,30 @@ static struct sway_xdg_popup *popup_create( if (popup == NULL) { return NULL; } + + struct wlr_scene_tree *scene_tree = wlr_scene_tree_create(parent); + if (!scene_tree) { + free(popup); + return NULL; + } + + scene_descriptor_assign(&scene_tree->node, SWAY_SCENE_DESC_POPUP, popup); + view_child_init(&popup->child, &popup_impl, view, xdg_surface->surface); popup->wlr_xdg_popup = xdg_surface->popup; + struct sway_xdg_shell_view *shell_view = wl_container_of(view, shell_view, view); + xdg_surface->data = shell_view; + + popup->child.scene_tree = scene_tree; + popup->child.xdg_surface_tree = + wlr_scene_xdg_surface_create(scene_tree, xdg_surface); wl_signal_add(&xdg_surface->events.new_popup, &popup->new_popup); popup->new_popup.notify = popup_handle_new_popup; wl_signal_add(&xdg_surface->events.destroy, &popup->destroy); popup->destroy.notify = popup_handle_destroy; - wl_signal_add(&xdg_surface->events.map, &popup->child.surface_map); - wl_signal_add(&xdg_surface->events.unmap, &popup->child.surface_unmap); - popup_unconstrain(popup); - return popup; } @@ -284,7 +288,6 @@ static void handle_commit(struct wl_listener *listener, void *data) { // The client changed its surface size in this commit. For floating // containers, we resize the container to match. For tiling containers, // we only recenter the surface. - desktop_damage_view(view); memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box)); if (container_is_floating(view->container)) { view_update_size(view); @@ -292,15 +295,12 @@ static void handle_commit(struct wl_listener *listener, void *data) { } else { view_center_surface(view); } - desktop_damage_view(view); } if (view->container->node.instruction) { transaction_notify_view_ready_by_serial(view, xdg_surface->current.configure_serial); } - - view_damage_from(view); } static void handle_set_title(struct wl_listener *listener, void *data) { @@ -322,7 +322,16 @@ static void handle_new_popup(struct wl_listener *listener, void *data) { struct sway_xdg_shell_view *xdg_shell_view = wl_container_of(listener, xdg_shell_view, new_popup); struct wlr_xdg_popup *wlr_popup = data; - popup_create(wlr_popup, &xdg_shell_view->view); + + struct sway_xdg_popup *popup = popup_create(wlr_popup, + &xdg_shell_view->view, root->layers.popup); + if (!popup) { + return; + } + + int lx, ly; + wlr_scene_node_coords(&popup->child.view->content_tree->node, &lx, &ly); + wlr_scene_node_set_position(&popup->child.scene_tree->node, lx, ly); } static void handle_request_maximize(struct wl_listener *listener, void *data) { @@ -523,7 +532,6 @@ void handle_xdg_shell_surface(struct wl_listener *listener, void *data) { free(xdg_shell_view); return; } - xdg_shell_view->view.wlr_xdg_toplevel = xdg_surface->toplevel; xdg_shell_view->map.notify = handle_map; wl_signal_add(&xdg_surface->events.map, &xdg_shell_view->map); @@ -534,5 +542,8 @@ void handle_xdg_shell_surface(struct wl_listener *listener, void *data) { xdg_shell_view->destroy.notify = handle_destroy; wl_signal_add(&xdg_surface->events.destroy, &xdg_shell_view->destroy); + xdg_shell_view->view.wlr_xdg_toplevel = xdg_surface->toplevel; + wlr_scene_xdg_surface_create(xdg_shell_view->view.content_tree, xdg_surface); + xdg_surface->data = xdg_shell_view; } diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 4cbec3bc6..2ec284267 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -81,6 +81,10 @@ struct sway_node *node_at_coords( // We don't want to feed through the current workspace on // layer shells return NULL; + } else if (desc->type == SWAY_SCENE_DESC_POPUP) { + struct sway_xdg_popup *popup = desc->data; + struct sway_container *con = popup->child.view->container; + return &con->node; } } diff --git a/sway/tree/view.c b/sway/tree/view.c index 8185666cc..459d71440 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -472,24 +472,6 @@ void view_for_each_popup_surface(struct sway_view *view, view->impl->for_each_popup_surface(view, iterator, user_data); } } - -static void view_subsurface_create(struct sway_view *view, - struct wlr_subsurface *subsurface); - -static void view_init_subsurfaces(struct sway_view *view, - struct wlr_surface *surface); - -static void view_child_init_subsurfaces(struct sway_view_child *view_child, - struct wlr_surface *surface); - -static void view_handle_surface_new_subsurface(struct wl_listener *listener, - void *data) { - struct sway_view *view = - wl_container_of(listener, view, surface_new_subsurface); - struct wlr_subsurface *subsurface = data; - view_subsurface_create(view, subsurface); -} - static bool view_has_executed_criteria(struct sway_view *view, struct criteria *criteria) { for (int i = 0; i < view->executed_criteria->length; ++i) { @@ -788,11 +770,6 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface, } ipc_event_window(view->container, "new"); - view_init_subsurfaces(view, wlr_surface); - wl_signal_add(&wlr_surface->events.new_subsurface, - &view->surface_new_subsurface); - view->surface_new_subsurface.notify = view_handle_surface_new_subsurface; - if (decoration) { view_update_csd_from_client(view, decoration); } @@ -860,8 +837,6 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface, void view_unmap(struct sway_view *view) { wl_signal_emit(&view->events.unmap, view); - wl_list_remove(&view->surface_new_subsurface.link); - if (view->urgent_timer) { wl_event_source_remove(view->urgent_timer); view->urgent_timer = NULL; @@ -923,183 +898,6 @@ void view_center_surface(struct sway_view *view) { (con->current.content_height - view->geometry.height) / 2); } -static const struct sway_view_child_impl subsurface_impl; - -static void subsurface_get_view_coords(struct sway_view_child *child, - int *sx, int *sy) { - struct wlr_surface *surface = child->surface; - if (child->parent && child->parent->impl && - child->parent->impl->get_view_coords) { - child->parent->impl->get_view_coords(child->parent, sx, sy); - } else { - *sx = *sy = 0; - } - struct wlr_subsurface *subsurface = - wlr_subsurface_from_wlr_surface(surface); - *sx += subsurface->current.x; - *sy += subsurface->current.y; -} - -static void subsurface_destroy(struct sway_view_child *child) { - if (!sway_assert(child->impl == &subsurface_impl, - "Expected a subsurface")) { - return; - } - struct sway_subsurface *subsurface = (struct sway_subsurface *)child; - wl_list_remove(&subsurface->destroy.link); - free(subsurface); -} - -static const struct sway_view_child_impl subsurface_impl = { - .get_view_coords = subsurface_get_view_coords, - .destroy = subsurface_destroy, -}; - -static void subsurface_handle_destroy(struct wl_listener *listener, - void *data) { - struct sway_subsurface *subsurface = - wl_container_of(listener, subsurface, destroy); - struct sway_view_child *child = &subsurface->child; - view_child_destroy(child); -} - -static void view_child_damage(struct sway_view_child *child, bool whole); - -static void view_subsurface_create(struct sway_view *view, - struct wlr_subsurface *wlr_subsurface) { - struct sway_subsurface *subsurface = - calloc(1, sizeof(struct sway_subsurface)); - if (subsurface == NULL) { - sway_log(SWAY_ERROR, "Allocation failed"); - return; - } - view_child_init(&subsurface->child, &subsurface_impl, view, - wlr_subsurface->surface); - - wl_signal_add(&wlr_subsurface->events.destroy, &subsurface->destroy); - subsurface->destroy.notify = subsurface_handle_destroy; - - subsurface->child.mapped = true; - - view_child_damage(&subsurface->child, true); -} - -static void view_child_subsurface_create(struct sway_view_child *child, - struct wlr_subsurface *wlr_subsurface) { - struct sway_subsurface *subsurface = - calloc(1, sizeof(struct sway_subsurface)); - if (subsurface == NULL) { - sway_log(SWAY_ERROR, "Allocation failed"); - return; - } - subsurface->child.parent = child; - wl_list_insert(&child->children, &subsurface->child.link); - view_child_init(&subsurface->child, &subsurface_impl, child->view, - wlr_subsurface->surface); - - wl_signal_add(&wlr_subsurface->events.destroy, &subsurface->destroy); - subsurface->destroy.notify = subsurface_handle_destroy; - - subsurface->child.mapped = true; - - view_child_damage(&subsurface->child, true); -} - -static bool view_child_is_mapped(struct sway_view_child *child) { - while (child) { - if (!child->mapped) { - return false; - } - child = child->parent; - } - return true; -} - -static void view_child_damage(struct sway_view_child *child, bool whole) { - if (!child || !view_child_is_mapped(child) || !child->view || !child->view->container) { - return; - } - int sx, sy; - child->impl->get_view_coords(child, &sx, &sy); - desktop_damage_surface(child->surface, - child->view->container->pending.content_x - - child->view->geometry.x + sx, - child->view->container->pending.content_y - - child->view->geometry.y + sy, whole); -} - -static void view_child_handle_surface_commit(struct wl_listener *listener, - void *data) { - struct sway_view_child *child = - wl_container_of(listener, child, surface_commit); - view_child_damage(child, false); -} - -static void view_child_handle_surface_new_subsurface( - struct wl_listener *listener, void *data) { - struct sway_view_child *child = - wl_container_of(listener, child, surface_new_subsurface); - struct wlr_subsurface *subsurface = data; - view_child_subsurface_create(child, subsurface); -} - -static void view_child_handle_surface_destroy(struct wl_listener *listener, - void *data) { - struct sway_view_child *child = - wl_container_of(listener, child, surface_destroy); - view_child_destroy(child); -} - -static void view_init_subsurfaces(struct sway_view *view, - struct wlr_surface *surface) { - struct wlr_subsurface *subsurface; - wl_list_for_each(subsurface, &surface->current.subsurfaces_below, - current.link) { - view_subsurface_create(view, subsurface); - } - wl_list_for_each(subsurface, &surface->current.subsurfaces_above, - current.link) { - view_subsurface_create(view, subsurface); - } -} - -static void view_child_init_subsurfaces(struct sway_view_child *view_child, - struct wlr_surface *surface) { - struct wlr_subsurface *subsurface; - wl_list_for_each(subsurface, &surface->current.subsurfaces_below, - current.link) { - view_child_subsurface_create(view_child, subsurface); - } - wl_list_for_each(subsurface, &surface->current.subsurfaces_above, - current.link) { - view_child_subsurface_create(view_child, subsurface); - } -} - -static void view_child_handle_surface_map(struct wl_listener *listener, - void *data) { - struct sway_view_child *child = - wl_container_of(listener, child, surface_map); - child->mapped = true; - view_child_damage(child, true); -} - -static void view_child_handle_surface_unmap(struct wl_listener *listener, - void *data) { - struct sway_view_child *child = - wl_container_of(listener, child, surface_unmap); - view_child_damage(child, true); - child->mapped = false; -} - -static void view_child_handle_view_unmap(struct wl_listener *listener, - void *data) { - struct sway_view_child *child = - wl_container_of(listener, child, view_unmap); - view_child_damage(child, true); - child->mapped = false; -} - void view_child_init(struct sway_view_child *child, const struct sway_view_child_impl *impl, struct sway_view *view, struct wlr_surface *surface) { @@ -1107,41 +905,9 @@ void view_child_init(struct sway_view_child *child, child->view = view; child->surface = surface; wl_list_init(&child->children); - - wl_signal_add(&surface->events.commit, &child->surface_commit); - child->surface_commit.notify = view_child_handle_surface_commit; - wl_signal_add(&surface->events.new_subsurface, - &child->surface_new_subsurface); - child->surface_new_subsurface.notify = - view_child_handle_surface_new_subsurface; - wl_signal_add(&surface->events.destroy, &child->surface_destroy); - child->surface_destroy.notify = view_child_handle_surface_destroy; - - // Not all child views have a map/unmap event - child->surface_map.notify = view_child_handle_surface_map; - wl_list_init(&child->surface_map.link); - child->surface_unmap.notify = view_child_handle_surface_unmap; - wl_list_init(&child->surface_unmap.link); - - wl_signal_add(&view->events.unmap, &child->view_unmap); - child->view_unmap.notify = view_child_handle_view_unmap; - - struct sway_container *container = child->view->container; - if (container != NULL) { - struct sway_workspace *workspace = container->pending.workspace; - if (workspace) { - wlr_surface_send_enter(child->surface, workspace->output->wlr_output); - } - } - - view_child_init_subsurfaces(child, surface); } void view_child_destroy(struct sway_view_child *child) { - if (view_child_is_mapped(child) && child->view->container != NULL) { - view_child_damage(child, true); - } - if (child->parent != NULL) { wl_list_remove(&child->link); child->parent = NULL; @@ -1151,18 +917,8 @@ void view_child_destroy(struct sway_view_child *child) { wl_list_for_each_safe(subchild, tmpchild, &child->children, link) { wl_list_remove(&subchild->link); subchild->parent = NULL; - // The subchild lost its parent link, so it cannot see that the parent - // is unmapped. Unmap it directly. - subchild->mapped = false; } - wl_list_remove(&child->surface_commit.link); - wl_list_remove(&child->surface_destroy.link); - wl_list_remove(&child->surface_map.link); - wl_list_remove(&child->surface_unmap.link); - wl_list_remove(&child->view_unmap.link); - wl_list_remove(&child->surface_new_subsurface.link); - if (child->impl && child->impl->destroy) { child->impl->destroy(child); } else {