aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/sway/scene_descriptor.h1
-rw-r--r--include/sway/tree/view.h46
-rw-r--r--sway/desktop/output.c8
-rw-r--r--sway/desktop/xdg_shell.c113
-rw-r--r--sway/input/cursor.c13
-rw-r--r--sway/tree/view.c272
6 files changed, 81 insertions, 372 deletions
diff --git a/include/sway/scene_descriptor.h b/include/sway/scene_descriptor.h
index 970adaa5..43991f77 100644
--- a/include/sway/scene_descriptor.h
+++ b/include/sway/scene_descriptor.h
@@ -16,6 +16,7 @@ enum sway_scene_descriptor_type {
SWAY_SCENE_DESC_CONTAINER,
SWAY_SCENE_DESC_VIEW,
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 4aaed9e3..467d912f 100644
--- a/include/sway/tree/view.h
+++ b/include/sway/tree/view.h
@@ -123,8 +123,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;
@@ -191,43 +189,12 @@ struct sway_xwayland_unmanaged {
struct wl_listener override_redirect;
};
#endif
-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);
-};
-
-/**
- * A view child is a surface in the view tree, such as a subsurface or a popup.
- */
-struct sway_view_child {
- const struct sway_view_child_impl *impl;
- struct wl_list link;
-
- struct sway_view *view;
- 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 sway_xdg_popup {
- struct sway_view_child child;
+ struct sway_view *view;
+ struct wlr_scene_tree *scene_tree;
+ struct wlr_scene_tree *xdg_surface_tree;
struct wlr_xdg_popup *wlr_xdg_popup;
struct wl_listener surface_commit;
@@ -339,13 +306,6 @@ void view_unmap(struct sway_view *view);
void view_update_size(struct sway_view *view);
void view_center_surface(struct sway_view *view);
-void view_child_init(struct sway_view_child *child,
- const struct sway_view_child_impl *impl, struct sway_view *view,
- struct wlr_surface *surface);
-
-void view_child_destroy(struct sway_view_child *child);
-
-
struct sway_view *view_from_wlr_xdg_surface(
struct wlr_xdg_surface *xdg_surface);
#if HAVE_XWAYLAND
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index 942bc780..a5184484 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -289,8 +289,14 @@ static void send_frame_done_iterator(struct wlr_scene_buffer *buffer,
}
struct wlr_scene_node *current = &buffer->node;
-
while (true) {
+ struct sway_view *view = scene_descriptor_try_get(current,
+ SWAY_SCENE_DESC_VIEW);
+ if (view) {
+ view_max_render_time = view->max_render_time;
+ break;
+ }
+
if (!current->parent) {
break;
}
diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c
index 11c112be..fed820cf 100644
--- a/sway/desktop/xdg_shell.c
+++ b/sway/desktop/xdg_shell.c
@@ -7,7 +7,7 @@
#include <wlr/util/edges.h>
#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"
@@ -19,41 +19,29 @@
#include "sway/tree/workspace.h"
#include "sway/xdg_decoration.h"
-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;
+static struct sway_xdg_popup *popup_create(
+ struct wlr_xdg_popup *wlr_popup, struct sway_view *view,
+ struct wlr_scene_tree *parent);
- 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_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->view, popup->xdg_surface_tree);
}
-static void popup_destroy(struct sway_view_child *child) {
- if (!sway_assert(child->impl == &popup_impl,
- "Expected an xdg_shell popup")) {
- return;
- }
- struct sway_xdg_popup *popup = (struct sway_xdg_popup *)child;
- wl_list_remove(&popup->surface_commit.link);
+static void popup_handle_destroy(struct wl_listener *listener, void *data) {
+ struct sway_xdg_popup *popup = wl_container_of(listener, popup, destroy);
+
wl_list_remove(&popup->new_popup.link);
wl_list_remove(&popup->destroy.link);
+ wl_list_remove(&popup->surface_commit.link);
+ wlr_scene_node_destroy(&popup->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);
-
static void popup_unconstrain(struct sway_xdg_popup *popup) {
- struct sway_view *view = popup->child.view;
+ struct sway_view *view = popup->view;
struct wlr_xdg_popup *wlr_popup = popup->wlr_xdg_popup;
struct sway_workspace *workspace = view->container->pending.workspace;
@@ -83,29 +71,44 @@ static void popup_handle_surface_commit(struct wl_listener *listener, void *data
}
}
-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);
-}
-
-static void popup_handle_destroy(struct wl_listener *listener, void *data) {
- struct sway_xdg_popup *popup = wl_container_of(listener, popup, destroy);
- view_child_destroy(&popup->child);
-}
-
-static struct sway_xdg_popup *popup_create(
- struct wlr_xdg_popup *wlr_popup, struct sway_view *view) {
+static struct sway_xdg_popup *popup_create(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 =
- calloc(1, sizeof(struct sway_xdg_popup));
- if (popup == NULL) {
+ struct sway_xdg_popup *popup = calloc(1, sizeof(struct sway_xdg_popup));
+ if (!popup) {
return NULL;
}
- view_child_init(&popup->child, &popup_impl, view, xdg_surface->surface);
+
popup->wlr_xdg_popup = wlr_popup;
+ popup->view = view;
+
+ popup->scene_tree = wlr_scene_tree_create(parent);
+ if (!popup->scene_tree) {
+ free(popup);
+ return NULL;
+ }
+
+ popup->xdg_surface_tree = wlr_scene_xdg_surface_create(
+ popup->scene_tree, xdg_surface);
+ if (!popup->xdg_surface_tree) {
+ wlr_scene_node_destroy(&popup->scene_tree->node);
+ free(popup);
+ return NULL;
+ }
+
+ if (!scene_descriptor_assign(&popup->scene_tree->node,
+ SWAY_SCENE_DESC_POPUP, popup)) {
+ sway_log(SWAY_ERROR, "Failed to allocate a popup scene descriptor");
+ wlr_scene_node_destroy(&popup->scene_tree->node);
+ free(popup);
+ return NULL;
+ }
+
+ 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;
wl_signal_add(&xdg_surface->surface->events.commit, &popup->surface_commit);
popup->surface_commit.notify = popup_handle_surface_commit;
@@ -114,9 +117,6 @@ static struct sway_xdg_popup *popup_create(
wl_signal_add(&wlr_popup->events.destroy, &popup->destroy);
popup->destroy.notify = popup_handle_destroy;
- wl_signal_add(&xdg_surface->surface->events.map, &popup->child.surface_map);
- wl_signal_add(&xdg_surface->surface->events.unmap, &popup->child.surface_unmap);
-
return popup;
}
@@ -317,7 +317,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);
@@ -330,15 +329,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) {
@@ -360,7 +356,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->view->content_tree->node, &lx, &ly);
+ wlr_scene_node_set_position(&popup->scene_tree->node, lx, ly);
}
static void handle_request_maximize(struct wl_listener *listener, void *data) {
@@ -567,5 +572,7 @@ void handle_xdg_shell_toplevel(struct wl_listener *listener, void *data) {
xdg_shell_view->destroy.notify = handle_destroy;
wl_signal_add(&xdg_toplevel->events.destroy, &xdg_shell_view->destroy);
+ wlr_scene_xdg_surface_create(xdg_shell_view->view.content_tree, xdg_toplevel->base);
+
xdg_toplevel->base->data = xdg_shell_view;
}
diff --git a/sway/input/cursor.c b/sway/input/cursor.c
index 30df76f4..fd8f50d4 100644
--- a/sway/input/cursor.c
+++ b/sway/input/cursor.c
@@ -80,6 +80,7 @@ struct sway_node *node_at_coords(
while (true) {
struct sway_container *con = scene_descriptor_try_get(current,
SWAY_SCENE_DESC_CONTAINER);
+
if (!con) {
struct sway_view *view = scene_descriptor_try_get(current,
SWAY_SCENE_DESC_VIEW);
@@ -88,12 +89,18 @@ struct sway_node *node_at_coords(
}
}
- if (con) {
- if (!con->view || con->view->surface) {
- return &con->node;
+ if (!con) {
+ struct sway_xdg_popup *popup =
+ scene_descriptor_try_get(current, SWAY_SCENE_DESC_POPUP);
+ if (popup) {
+ con = popup->view->container;
}
}
+ if (con && (!con->view || con->view->surface)) {
+ return &con->node;
+ }
+
if (scene_descriptor_try_get(current, SWAY_SCENE_DESC_LAYER_SHELL)) {
// We don't want to feed through the current workspace on
// layer shells
diff --git a/sway/tree/view.c b/sway/tree/view.c
index 7af2fd3f..ee25faf1 100644
--- a/sway/tree/view.c
+++ b/sway/tree/view.c
@@ -488,24 +488,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) {
@@ -826,11 +808,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);
}
@@ -897,8 +874,6 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface,
void view_unmap(struct sway_view *view) {
wl_signal_emit_mutable(&view->events.unmap, view);
- wl_list_remove(&view->surface_new_subsurface.link);
-
view->executed_criteria->length = 0;
if (view->urgent_timer) {
@@ -962,253 +937,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_try_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) {
- child->impl = impl;
- 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) {
- surface_enter_output(child->surface, workspace->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;
- }
-
- struct sway_view_child *subchild, *tmpchild;
- 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 {
- free(child);
- }
-}
-
struct sway_view *view_from_wlr_surface(struct wlr_surface *wlr_surface) {
struct wlr_xdg_surface *xdg_surface;
if ((xdg_surface = wlr_xdg_surface_try_from_wlr_surface(wlr_surface))) {