Chase wlroots: Unified mapping

Need to handle new unified mapping, where mapping is attached to the
wlr_surface objects instead of their parents. Also, most of them require
a new associate event for xsurface objects, their surface member will be
NULL before this event is received.

Refactored by jlindgren:
- add struct mappable
- unify map/unmap logic
This commit is contained in:
Christopher Snowhill 2023-06-15 02:35:43 -07:00 committed by Johan Malm
parent bf576e97de
commit d7dc6e01b4
10 changed files with 142 additions and 52 deletions

View file

@ -70,6 +70,13 @@ enum view_wants_focus {
struct view; struct view;
struct wlr_surface; struct wlr_surface;
/* Common to struct view and struct xwayland_unmanaged */
struct mappable {
bool connected;
struct wl_listener map;
struct wl_listener unmap;
};
/* Basic size hints (subset of XSizeHints from X11) */ /* Basic size hints (subset of XSizeHints from X11) */
struct view_size_hints { struct view_size_hints {
int min_width; int min_width;
@ -194,8 +201,8 @@ struct view {
struct wl_listener destroy; struct wl_listener destroy;
} toplevel; } toplevel;
struct wl_listener map; struct mappable mappable;
struct wl_listener unmap;
struct wl_listener destroy; struct wl_listener destroy;
struct wl_listener surface_destroy; struct wl_listener surface_destroy;
struct wl_listener commit; struct wl_listener commit;
@ -345,6 +352,10 @@ view_is_focusable(struct view *view) {
return view_is_focusable_from(view, NULL); return view_is_focusable_from(view, NULL);
} }
void mappable_connect(struct mappable *mappable, struct wlr_surface *surface,
wl_notify_func_t notify_map, wl_notify_func_t notify_unmap);
void mappable_disconnect(struct mappable *mappable);
void view_toggle_keybinds(struct view *view); void view_toggle_keybinds(struct view *view);
void view_set_activated(struct view *view, bool activated); void view_set_activated(struct view *view, bool activated);
@ -427,6 +438,7 @@ void view_adjust_size(struct view *view, int *w, int *h);
void view_evacuate_region(struct view *view); void view_evacuate_region(struct view *view);
void view_on_output_destroy(struct view *view); void view_on_output_destroy(struct view *view);
void view_connect_map(struct view *view, struct wlr_surface *surface);
void view_destroy(struct view *view); void view_destroy(struct view *view);
enum view_axis view_axis_parse(const char *direction); enum view_axis view_axis_parse(const char *direction);

View file

@ -13,12 +13,14 @@ struct xwayland_unmanaged {
struct wlr_scene_node *node; struct wlr_scene_node *node;
struct wl_list link; struct wl_list link;
struct mappable mappable;
struct wl_listener associate;
struct wl_listener dissociate;
struct wl_listener request_activate; struct wl_listener request_activate;
struct wl_listener request_configure; struct wl_listener request_configure;
/* struct wl_listener request_fullscreen; */ /* struct wl_listener request_fullscreen; */
struct wl_listener set_geometry; struct wl_listener set_geometry;
struct wl_listener map;
struct wl_listener unmap;
struct wl_listener destroy; struct wl_listener destroy;
struct wl_listener set_override_redirect; struct wl_listener set_override_redirect;
}; };
@ -28,6 +30,8 @@ struct xwayland_view {
struct wlr_xwayland_surface *xwayland_surface; struct wlr_xwayland_surface *xwayland_surface;
/* Events unique to XWayland views */ /* Events unique to XWayland views */
struct wl_listener associate;
struct wl_listener dissociate;
struct wl_listener request_activate; struct wl_listener request_activate;
struct wl_listener request_configure; struct wl_listener request_configure;
struct wl_listener set_class; struct wl_listener set_class;

View file

@ -89,9 +89,9 @@ drag_icon_create(struct seat *seat, struct wlr_drag_icon *wlr_icon)
self->events.unmap.notify = handle_icon_unmap; self->events.unmap.notify = handle_icon_unmap;
self->events.destroy.notify = handle_icon_destroy; self->events.destroy.notify = handle_icon_destroy;
wl_signal_add(&wlr_icon->events.map, &self->events.map); wl_signal_add(&wlr_icon->surface->events.map, &self->events.map);
wl_signal_add(&wlr_icon->surface->events.commit, &self->events.commit); wl_signal_add(&wlr_icon->surface->events.commit, &self->events.commit);
wl_signal_add(&wlr_icon->events.unmap, &self->events.unmap); wl_signal_add(&wlr_icon->surface->events.unmap, &self->events.unmap);
wl_signal_add(&wlr_icon->events.destroy, &self->events.destroy); wl_signal_add(&wlr_icon->events.destroy, &self->events.destroy);
} }

View file

@ -175,8 +175,8 @@ handle_surface_commit(struct wl_listener *listener, void *data)
process_keyboard_interactivity(layer); process_keyboard_interactivity(layer);
} }
if (committed || layer->mapped != layer_surface->mapped) { if (committed || layer->mapped != layer_surface->surface->mapped) {
layer->mapped = layer_surface->mapped; layer->mapped = layer_surface->surface->mapped;
output_update_usable_area(output); output_update_usable_area(output);
/* /*
* Update cursor focus here to ensure we * Update cursor focus here to ensure we
@ -401,10 +401,10 @@ handle_new_layer_surface(struct wl_listener *listener, void *data)
&surface->surface_commit); &surface->surface_commit);
surface->map.notify = handle_map; surface->map.notify = handle_map;
wl_signal_add(&layer_surface->events.map, &surface->map); wl_signal_add(&layer_surface->surface->events.map, &surface->map);
surface->unmap.notify = handle_unmap; surface->unmap.notify = handle_unmap;
wl_signal_add(&layer_surface->events.unmap, &surface->unmap); wl_signal_add(&layer_surface->surface->events.unmap, &surface->unmap);
surface->new_popup.notify = handle_new_popup; surface->new_popup.notify = handle_new_popup;
wl_signal_add(&layer_surface->events.new_popup, &surface->new_popup); wl_signal_add(&layer_surface->events.new_popup, &surface->new_popup);

View file

@ -42,10 +42,10 @@ refocus_output(struct session_lock_output *output)
struct session_lock_output *iter; struct session_lock_output *iter;
wl_list_for_each(iter, &output->lock->session_lock_outputs, link) { wl_list_for_each(iter, &output->lock->session_lock_outputs, link) {
if (iter == output || !iter->surface) { if (iter == output || !iter->surface || !iter->surface->surface) {
continue; continue;
} }
if (iter->surface->mapped) { if (iter->surface->surface->mapped) {
focus_surface(output->lock, iter->surface->surface); focus_surface(output->lock, iter->surface->surface);
return; return;
} }
@ -110,7 +110,7 @@ found_lock_output:
wl_signal_add(&lock_surface->events.destroy, &lock_output->surface_destroy); wl_signal_add(&lock_surface->events.destroy, &lock_output->surface_destroy);
lock_output->surface_map.notify = handle_surface_map; lock_output->surface_map.notify = handle_surface_map;
wl_signal_add(&lock_surface->events.map, &lock_output->surface_map); wl_signal_add(&lock_surface->surface->events.map, &lock_output->surface_map);
lock_output_reconfigure(lock_output); lock_output_reconfigure(lock_output);
} }

View file

@ -1605,6 +1605,55 @@ view_toggle_keybinds(struct view *view)
} }
} }
void
mappable_connect(struct mappable *mappable, struct wlr_surface *surface,
wl_notify_func_t notify_map, wl_notify_func_t notify_unmap)
{
assert(mappable);
assert(!mappable->connected);
mappable->map.notify = notify_map;
wl_signal_add(&surface->events.map, &mappable->map);
mappable->unmap.notify = notify_unmap;
wl_signal_add(&surface->events.unmap, &mappable->unmap);
mappable->connected = true;
}
void
mappable_disconnect(struct mappable *mappable)
{
assert(mappable);
assert(mappable->connected);
wl_list_remove(&mappable->map.link);
wl_list_remove(&mappable->unmap.link);
mappable->connected = false;
}
static void
handle_map(struct wl_listener *listener, void *data)
{
struct view *view = wl_container_of(listener, view, mappable.map);
view->impl->map(view);
}
static void
handle_unmap(struct wl_listener *listener, void *data)
{
struct view *view = wl_container_of(listener, view, mappable.unmap);
view->impl->unmap(view, /* client_request */ true);
}
/*
* TODO: after the release of wlroots 0.17, consider incorporating this
* function into a more general view_set_surface() function, which could
* connect other surface event handlers (like commit) as well.
*/
void
view_connect_map(struct view *view, struct wlr_surface *surface)
{
assert(view);
mappable_connect(&view->mappable, surface, handle_map, handle_unmap);
}
void void
view_destroy(struct view *view) view_destroy(struct view *view)
{ {
@ -1612,8 +1661,10 @@ view_destroy(struct view *view)
struct server *server = view->server; struct server *server = view->server;
bool need_cursor_update = false; bool need_cursor_update = false;
wl_list_remove(&view->map.link); if (view->mappable.connected) {
wl_list_remove(&view->unmap.link); mappable_disconnect(&view->mappable);
}
wl_list_remove(&view->request_move.link); wl_list_remove(&view->request_move.link);
wl_list_remove(&view->request_resize.link); wl_list_remove(&view->request_resize.link);
wl_list_remove(&view->request_minimize.link); wl_list_remove(&view->request_minimize.link);

View file

@ -163,20 +163,6 @@ set_pending_configure_serial(struct view *view, uint32_t serial)
CONFIGURE_TIMEOUT_MS); CONFIGURE_TIMEOUT_MS);
} }
static void
handle_map(struct wl_listener *listener, void *data)
{
struct view *view = wl_container_of(listener, view, map);
view->impl->map(view);
}
static void
handle_unmap(struct wl_listener *listener, void *data)
{
struct view *view = wl_container_of(listener, view, unmap);
view->impl->unmap(view, /* client_request */ true);
}
static void static void
handle_destroy(struct wl_listener *listener, void *data) handle_destroy(struct wl_listener *listener, void *data)
{ {
@ -688,8 +674,7 @@ xdg_surface_new(struct wl_listener *listener, void *data)
/* In support of xdg popups */ /* In support of xdg popups */
xdg_surface->surface->data = tree; xdg_surface->surface->data = tree;
CONNECT_SIGNAL(xdg_surface, view, map); view_connect_map(view, xdg_surface->surface);
CONNECT_SIGNAL(xdg_surface, view, unmap);
CONNECT_SIGNAL(xdg_surface, view, destroy); CONNECT_SIGNAL(xdg_surface, view, destroy);
struct wlr_xdg_toplevel *toplevel = xdg_surface->toplevel; struct wlr_xdg_toplevel *toplevel = xdg_surface->toplevel;

View file

@ -37,7 +37,7 @@ static void
handle_map(struct wl_listener *listener, void *data) handle_map(struct wl_listener *listener, void *data)
{ {
struct xwayland_unmanaged *unmanaged = struct xwayland_unmanaged *unmanaged =
wl_container_of(listener, unmanaged, map); wl_container_of(listener, unmanaged, mappable.map);
struct wlr_xwayland_surface *xsurface = unmanaged->xwayland_surface; struct wlr_xwayland_surface *xsurface = unmanaged->xwayland_surface;
assert(!unmanaged->node); assert(!unmanaged->node);
@ -95,7 +95,7 @@ static void
handle_unmap(struct wl_listener *listener, void *data) handle_unmap(struct wl_listener *listener, void *data)
{ {
struct xwayland_unmanaged *unmanaged = struct xwayland_unmanaged *unmanaged =
wl_container_of(listener, unmanaged, unmap); wl_container_of(listener, unmanaged, mappable.unmap);
struct wlr_xwayland_surface *xsurface = unmanaged->xwayland_surface; struct wlr_xwayland_surface *xsurface = unmanaged->xwayland_surface;
struct seat *seat = &unmanaged->server->seat; struct seat *seat = &unmanaged->server->seat;
assert(unmanaged->node); assert(unmanaged->node);
@ -116,16 +116,43 @@ handle_unmap(struct wl_listener *listener, void *data)
} }
} }
static void
handle_associate(struct wl_listener *listener, void *data)
{
struct xwayland_unmanaged *unmanaged =
wl_container_of(listener, unmanaged, associate);
assert(unmanaged->xwayland_surface &&
unmanaged->xwayland_surface->surface);
mappable_connect(&unmanaged->mappable,
unmanaged->xwayland_surface->surface,
handle_map, handle_unmap);
}
static void
handle_dissociate(struct wl_listener *listener, void *data)
{
struct xwayland_unmanaged *unmanaged =
wl_container_of(listener, unmanaged, dissociate);
mappable_disconnect(&unmanaged->mappable);
}
static void static void
handle_destroy(struct wl_listener *listener, void *data) handle_destroy(struct wl_listener *listener, void *data)
{ {
struct xwayland_unmanaged *unmanaged = struct xwayland_unmanaged *unmanaged =
wl_container_of(listener, unmanaged, destroy); wl_container_of(listener, unmanaged, destroy);
if (unmanaged->mappable.connected) {
mappable_disconnect(&unmanaged->mappable);
}
wl_list_remove(&unmanaged->associate.link);
wl_list_remove(&unmanaged->dissociate.link);
wl_list_remove(&unmanaged->request_configure.link); wl_list_remove(&unmanaged->request_configure.link);
wl_list_remove(&unmanaged->set_override_redirect.link); wl_list_remove(&unmanaged->set_override_redirect.link);
wl_list_remove(&unmanaged->request_activate.link); wl_list_remove(&unmanaged->request_activate.link);
wl_list_remove(&unmanaged->map.link);
wl_list_remove(&unmanaged->unmap.link);
wl_list_remove(&unmanaged->destroy.link); wl_list_remove(&unmanaged->destroy.link);
free(unmanaged); free(unmanaged);
} }
@ -139,9 +166,9 @@ handle_set_override_redirect(struct wl_listener *listener, void *data)
struct wlr_xwayland_surface *xsurface = unmanaged->xwayland_surface; struct wlr_xwayland_surface *xsurface = unmanaged->xwayland_surface;
struct server *server = unmanaged->server; struct server *server = unmanaged->server;
bool mapped = xsurface->mapped; bool mapped = xsurface->surface && xsurface->surface->mapped;
if (mapped) { if (mapped) {
handle_unmap(&unmanaged->unmap, NULL); handle_unmap(&unmanaged->mappable.unmap, NULL);
} }
handle_destroy(&unmanaged->destroy, NULL); handle_destroy(&unmanaged->destroy, NULL);
@ -155,7 +182,7 @@ handle_request_activate(struct wl_listener *listener, void *data)
struct xwayland_unmanaged *unmanaged = struct xwayland_unmanaged *unmanaged =
wl_container_of(listener, unmanaged, request_activate); wl_container_of(listener, unmanaged, request_activate);
struct wlr_xwayland_surface *xsurface = unmanaged->xwayland_surface; struct wlr_xwayland_surface *xsurface = unmanaged->xwayland_surface;
if (!xsurface->mapped) { if (!xsurface->surface || !xsurface->surface->mapped) {
return; return;
} }
struct server *server = unmanaged->server; struct server *server = unmanaged->server;
@ -191,14 +218,14 @@ xwayland_unmanaged_create(struct server *server,
*/ */
assert(!xsurface->data); assert(!xsurface->data);
CONNECT_SIGNAL(xsurface, unmanaged, map); CONNECT_SIGNAL(xsurface, unmanaged, associate);
CONNECT_SIGNAL(xsurface, unmanaged, unmap); CONNECT_SIGNAL(xsurface, unmanaged, dissociate);
CONNECT_SIGNAL(xsurface, unmanaged, destroy); CONNECT_SIGNAL(xsurface, unmanaged, destroy);
CONNECT_SIGNAL(xsurface, unmanaged, request_activate); CONNECT_SIGNAL(xsurface, unmanaged, request_activate);
CONNECT_SIGNAL(xsurface, unmanaged, request_configure); CONNECT_SIGNAL(xsurface, unmanaged, request_configure);
CONNECT_SIGNAL(xsurface, unmanaged, set_override_redirect); CONNECT_SIGNAL(xsurface, unmanaged, set_override_redirect);
if (mapped) { if (mapped) {
handle_map(&unmanaged->map, xsurface); handle_map(&unmanaged->mappable.map, NULL);
} }
} }

View file

@ -15,6 +15,8 @@
#include "workspaces.h" #include "workspaces.h"
#include "xwayland.h" #include "xwayland.h"
static void xwayland_view_unmap(struct view *view, bool client_request);
static struct view_size_hints static struct view_size_hints
xwayland_view_get_size_hints(struct view *view) xwayland_view_get_size_hints(struct view *view)
{ {
@ -225,17 +227,24 @@ handle_request_resize(struct wl_listener *listener, void *data)
} }
static void static void
handle_map(struct wl_listener *listener, void *data) handle_associate(struct wl_listener *listener, void *data)
{ {
struct view *view = wl_container_of(listener, view, map); struct xwayland_view *xwayland_view =
view->impl->map(view); wl_container_of(listener, xwayland_view, associate);
assert(xwayland_view->xwayland_surface &&
xwayland_view->xwayland_surface->surface);
view_connect_map(&xwayland_view->base,
xwayland_view->xwayland_surface->surface);
} }
static void static void
handle_unmap(struct wl_listener *listener, void *data) handle_dissociate(struct wl_listener *listener, void *data)
{ {
struct view *view = wl_container_of(listener, view, unmap); struct xwayland_view *xwayland_view =
view->impl->unmap(view, /* client_request */ true); wl_container_of(listener, xwayland_view, dissociate);
mappable_disconnect(&xwayland_view->base.mappable);
} }
static void static void
@ -275,6 +284,8 @@ handle_destroy(struct wl_listener *listener, void *data)
xwayland_view->xwayland_surface = NULL; xwayland_view->xwayland_surface = NULL;
/* Remove XWayland view specific listeners */ /* Remove XWayland view specific listeners */
wl_list_remove(&xwayland_view->associate.link);
wl_list_remove(&xwayland_view->dissociate.link);
wl_list_remove(&xwayland_view->request_activate.link); wl_list_remove(&xwayland_view->request_activate.link);
wl_list_remove(&xwayland_view->request_configure.link); wl_list_remove(&xwayland_view->request_configure.link);
wl_list_remove(&xwayland_view->set_class.link); wl_list_remove(&xwayland_view->set_class.link);
@ -434,9 +445,9 @@ handle_set_override_redirect(struct wl_listener *listener, void *data)
struct wlr_xwayland_surface *xsurface = xwayland_view->xwayland_surface; struct wlr_xwayland_surface *xsurface = xwayland_view->xwayland_surface;
struct server *server = view->server; struct server *server = view->server;
bool mapped = xsurface->mapped; bool mapped = xsurface->surface && xsurface->surface->mapped;
if (mapped) { if (mapped) {
handle_unmap(&view->unmap, xsurface); xwayland_view_unmap(view, /* client_request */ true);
} }
handle_destroy(&view->destroy, xsurface); handle_destroy(&view->destroy, xsurface);
/* view is invalid after this point */ /* view is invalid after this point */
@ -770,8 +781,6 @@ xwayland_view_create(struct server *server,
view->scene_tree = wlr_scene_tree_create(view->workspace->tree); view->scene_tree = wlr_scene_tree_create(view->workspace->tree);
node_descriptor_create(&view->scene_tree->node, LAB_NODE_DESC_VIEW, view); node_descriptor_create(&view->scene_tree->node, LAB_NODE_DESC_VIEW, view);
CONNECT_SIGNAL(xsurface, view, map);
CONNECT_SIGNAL(xsurface, view, unmap);
CONNECT_SIGNAL(xsurface, view, destroy); CONNECT_SIGNAL(xsurface, view, destroy);
CONNECT_SIGNAL(xsurface, view, request_minimize); CONNECT_SIGNAL(xsurface, view, request_minimize);
CONNECT_SIGNAL(xsurface, view, request_maximize); CONNECT_SIGNAL(xsurface, view, request_maximize);
@ -781,6 +790,8 @@ xwayland_view_create(struct server *server,
CONNECT_SIGNAL(xsurface, view, set_title); CONNECT_SIGNAL(xsurface, view, set_title);
/* Events specific to XWayland views */ /* Events specific to XWayland views */
CONNECT_SIGNAL(xsurface, xwayland_view, associate);
CONNECT_SIGNAL(xsurface, xwayland_view, dissociate);
CONNECT_SIGNAL(xsurface, xwayland_view, request_activate); CONNECT_SIGNAL(xsurface, xwayland_view, request_activate);
CONNECT_SIGNAL(xsurface, xwayland_view, request_configure); CONNECT_SIGNAL(xsurface, xwayland_view, request_configure);
CONNECT_SIGNAL(xsurface, xwayland_view, set_class); CONNECT_SIGNAL(xsurface, xwayland_view, set_class);

View file

@ -1,6 +1,6 @@
[wrap-git] [wrap-git]
url = https://gitlab.freedesktop.org/wlroots/wlroots.git url = https://gitlab.freedesktop.org/wlroots/wlroots.git
revision = 0bb574239d3b164596677bf4cec371ff0671dc4f revision = 26676c8c072f813dc2d7e2b2dfe9e2701ce361a7
[provide] [provide]
dependency_names = wlroots dependency_names = wlroots