mirror of
https://github.com/swaywm/sway.git
synced 2026-04-23 06:46:27 -04:00
scene_graph: Port xdg_shell
This commit is contained in:
parent
8d6080bd5a
commit
c3615a8b57
6 changed files with 58 additions and 287 deletions
|
|
@ -7,6 +7,7 @@ enum sway_scene_descriptor_type {
|
||||||
SWAY_SCENE_DESC_NON_INTERACTIVE,
|
SWAY_SCENE_DESC_NON_INTERACTIVE,
|
||||||
SWAY_SCENE_DESC_CONTAINER,
|
SWAY_SCENE_DESC_CONTAINER,
|
||||||
SWAY_SCENE_DESC_LAYER_SHELL,
|
SWAY_SCENE_DESC_LAYER_SHELL,
|
||||||
|
SWAY_SCENE_DESC_POPUP,
|
||||||
SWAY_SCENE_DESC_DRAG_ICON,
|
SWAY_SCENE_DESC_DRAG_ICON,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -122,8 +122,6 @@ struct sway_view {
|
||||||
struct wl_signal unmap;
|
struct wl_signal unmap;
|
||||||
} events;
|
} events;
|
||||||
|
|
||||||
struct wl_listener surface_new_subsurface;
|
|
||||||
|
|
||||||
int max_render_time; // In milliseconds
|
int max_render_time; // In milliseconds
|
||||||
|
|
||||||
enum seat_config_shortcuts_inhibit shortcuts_inhibit;
|
enum seat_config_shortcuts_inhibit shortcuts_inhibit;
|
||||||
|
|
@ -188,7 +186,6 @@ struct sway_xwayland_unmanaged {
|
||||||
struct sway_view_child;
|
struct sway_view_child;
|
||||||
|
|
||||||
struct sway_view_child_impl {
|
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);
|
void (*destroy)(struct sway_view_child *child);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -203,20 +200,9 @@ struct sway_view_child {
|
||||||
struct sway_view_child *parent;
|
struct sway_view_child *parent;
|
||||||
struct wl_list children; // sway_view_child::link
|
struct wl_list children; // sway_view_child::link
|
||||||
struct wlr_surface *surface;
|
struct wlr_surface *surface;
|
||||||
bool mapped;
|
|
||||||
|
|
||||||
struct wl_listener surface_commit;
|
struct wlr_scene_tree *scene_tree;
|
||||||
struct wl_listener surface_new_subsurface;
|
struct wlr_scene_tree *xdg_surface_tree;
|
||||||
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_xdg_popup {
|
||||||
|
|
|
||||||
|
|
@ -273,7 +273,20 @@ static void send_frame_done_iterator(struct wlr_scene_buffer *buffer,
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (current->data) {
|
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) {
|
if (!current->parent) {
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
#include <wlr/util/edges.h>
|
#include <wlr/util/edges.h>
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "sway/decoration.h"
|
#include "sway/decoration.h"
|
||||||
#include "sway/desktop.h"
|
#include "sway/scene_descriptor.h"
|
||||||
#include "sway/desktop/transaction.h"
|
#include "sway/desktop/transaction.h"
|
||||||
#include "sway/input/cursor.h"
|
#include "sway/input/cursor.h"
|
||||||
#include "sway/input/input-manager.h"
|
#include "sway/input/input-manager.h"
|
||||||
|
|
@ -21,17 +21,6 @@
|
||||||
|
|
||||||
static const struct sway_view_child_impl popup_impl;
|
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) {
|
static void popup_destroy(struct sway_view_child *child) {
|
||||||
if (!sway_assert(child->impl == &popup_impl,
|
if (!sway_assert(child->impl == &popup_impl,
|
||||||
"Expected an xdg_shell popup")) {
|
"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;
|
struct sway_xdg_popup *popup = (struct sway_xdg_popup *)child;
|
||||||
wl_list_remove(&popup->new_popup.link);
|
wl_list_remove(&popup->new_popup.link);
|
||||||
wl_list_remove(&popup->destroy.link);
|
wl_list_remove(&popup->destroy.link);
|
||||||
|
|
||||||
|
wlr_scene_node_destroy(&child->scene_tree->node);
|
||||||
|
|
||||||
free(popup);
|
free(popup);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct sway_view_child_impl popup_impl = {
|
static const struct sway_view_child_impl popup_impl = {
|
||||||
.get_view_coords = popup_get_view_coords,
|
|
||||||
.destroy = popup_destroy,
|
.destroy = popup_destroy,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct sway_xdg_popup *popup_create(
|
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) {
|
static void popup_handle_new_popup(struct wl_listener *listener, void *data) {
|
||||||
struct sway_xdg_popup *popup =
|
struct sway_xdg_popup *popup =
|
||||||
wl_container_of(listener, popup, new_popup);
|
wl_container_of(listener, popup, new_popup);
|
||||||
struct wlr_xdg_popup *wlr_popup = data;
|
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) {
|
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(
|
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 wlr_xdg_surface *xdg_surface = wlr_popup->base;
|
||||||
|
|
||||||
struct sway_xdg_popup *popup =
|
struct sway_xdg_popup *popup =
|
||||||
|
|
@ -90,19 +83,30 @@ static struct sway_xdg_popup *popup_create(
|
||||||
if (popup == NULL) {
|
if (popup == NULL) {
|
||||||
return 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);
|
view_child_init(&popup->child, &popup_impl, view, xdg_surface->surface);
|
||||||
popup->wlr_xdg_popup = xdg_surface->popup;
|
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);
|
wl_signal_add(&xdg_surface->events.new_popup, &popup->new_popup);
|
||||||
popup->new_popup.notify = popup_handle_new_popup;
|
popup->new_popup.notify = popup_handle_new_popup;
|
||||||
wl_signal_add(&xdg_surface->events.destroy, &popup->destroy);
|
wl_signal_add(&xdg_surface->events.destroy, &popup->destroy);
|
||||||
popup->destroy.notify = popup_handle_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);
|
popup_unconstrain(popup);
|
||||||
|
|
||||||
return 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
|
// The client changed its surface size in this commit. For floating
|
||||||
// containers, we resize the container to match. For tiling containers,
|
// containers, we resize the container to match. For tiling containers,
|
||||||
// we only recenter the surface.
|
// we only recenter the surface.
|
||||||
desktop_damage_view(view);
|
|
||||||
memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box));
|
memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box));
|
||||||
if (container_is_floating(view->container)) {
|
if (container_is_floating(view->container)) {
|
||||||
view_update_size(view);
|
view_update_size(view);
|
||||||
|
|
@ -292,15 +295,12 @@ static void handle_commit(struct wl_listener *listener, void *data) {
|
||||||
} else {
|
} else {
|
||||||
view_center_surface(view);
|
view_center_surface(view);
|
||||||
}
|
}
|
||||||
desktop_damage_view(view);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (view->container->node.instruction) {
|
if (view->container->node.instruction) {
|
||||||
transaction_notify_view_ready_by_serial(view,
|
transaction_notify_view_ready_by_serial(view,
|
||||||
xdg_surface->current.configure_serial);
|
xdg_surface->current.configure_serial);
|
||||||
}
|
}
|
||||||
|
|
||||||
view_damage_from(view);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_set_title(struct wl_listener *listener, void *data) {
|
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 =
|
struct sway_xdg_shell_view *xdg_shell_view =
|
||||||
wl_container_of(listener, xdg_shell_view, new_popup);
|
wl_container_of(listener, xdg_shell_view, new_popup);
|
||||||
struct wlr_xdg_popup *wlr_popup = data;
|
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) {
|
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);
|
free(xdg_shell_view);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
xdg_shell_view->view.wlr_xdg_toplevel = xdg_surface->toplevel;
|
|
||||||
|
|
||||||
xdg_shell_view->map.notify = handle_map;
|
xdg_shell_view->map.notify = handle_map;
|
||||||
wl_signal_add(&xdg_surface->events.map, &xdg_shell_view->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;
|
xdg_shell_view->destroy.notify = handle_destroy;
|
||||||
wl_signal_add(&xdg_surface->events.destroy, &xdg_shell_view->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;
|
xdg_surface->data = xdg_shell_view;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,10 @@ struct sway_node *node_at_coords(
|
||||||
// We don't want to feed through the current workspace on
|
// We don't want to feed through the current workspace on
|
||||||
// layer shells
|
// layer shells
|
||||||
return NULL;
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
244
sway/tree/view.c
244
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);
|
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,
|
static bool view_has_executed_criteria(struct sway_view *view,
|
||||||
struct criteria *criteria) {
|
struct criteria *criteria) {
|
||||||
for (int i = 0; i < view->executed_criteria->length; ++i) {
|
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");
|
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) {
|
if (decoration) {
|
||||||
view_update_csd_from_client(view, 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) {
|
void view_unmap(struct sway_view *view) {
|
||||||
wl_signal_emit(&view->events.unmap, view);
|
wl_signal_emit(&view->events.unmap, view);
|
||||||
|
|
||||||
wl_list_remove(&view->surface_new_subsurface.link);
|
|
||||||
|
|
||||||
if (view->urgent_timer) {
|
if (view->urgent_timer) {
|
||||||
wl_event_source_remove(view->urgent_timer);
|
wl_event_source_remove(view->urgent_timer);
|
||||||
view->urgent_timer = NULL;
|
view->urgent_timer = NULL;
|
||||||
|
|
@ -923,183 +898,6 @@ void view_center_surface(struct sway_view *view) {
|
||||||
(con->current.content_height - view->geometry.height) / 2);
|
(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,
|
void view_child_init(struct sway_view_child *child,
|
||||||
const struct sway_view_child_impl *impl, struct sway_view *view,
|
const struct sway_view_child_impl *impl, struct sway_view *view,
|
||||||
struct wlr_surface *surface) {
|
struct wlr_surface *surface) {
|
||||||
|
|
@ -1107,41 +905,9 @@ void view_child_init(struct sway_view_child *child,
|
||||||
child->view = view;
|
child->view = view;
|
||||||
child->surface = surface;
|
child->surface = surface;
|
||||||
wl_list_init(&child->children);
|
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) {
|
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) {
|
if (child->parent != NULL) {
|
||||||
wl_list_remove(&child->link);
|
wl_list_remove(&child->link);
|
||||||
child->parent = NULL;
|
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_for_each_safe(subchild, tmpchild, &child->children, link) {
|
||||||
wl_list_remove(&subchild->link);
|
wl_list_remove(&subchild->link);
|
||||||
subchild->parent = NULL;
|
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) {
|
if (child->impl && child->impl->destroy) {
|
||||||
child->impl->destroy(child);
|
child->impl->destroy(child);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue