Handle wlr_surface->events.new_subsurface

Add view-child.c, xdg-popup.c, subsurface.c in order to track damage
associated with new XDG subsurfaces.
This commit is contained in:
Johan Malm 2021-03-02 20:37:23 +00:00
parent 15a7910a02
commit d54a998dd8
7 changed files with 196 additions and 78 deletions

View file

@ -231,6 +231,7 @@ struct view {
struct wl_listener request_configure; struct wl_listener request_configure;
struct wl_listener request_maximize; struct wl_listener request_maximize;
struct wl_listener new_popup; /* xdg-shell only */ struct wl_listener new_popup; /* xdg-shell only */
struct wl_listener new_subsurface; /* xdg-shell only */
}; };
#if HAVE_XWAYLAND #if HAVE_XWAYLAND
@ -248,18 +249,33 @@ struct xwayland_unmanaged {
}; };
#endif #endif
struct view_child {
struct wlr_surface *surface;
struct view *parent;
struct wl_listener commit;
struct wl_listener new_subsurface;
};
struct view_subsurface {
struct view_child view_child;
struct wlr_subsurface *subsurface;
struct wl_listener destroy;
};
struct xdg_popup { struct xdg_popup {
struct view_child view_child;
struct wlr_xdg_popup *wlr_popup; struct wlr_xdg_popup *wlr_popup;
struct view *view;
struct wl_listener destroy; struct wl_listener destroy;
struct wl_listener commit;
struct wl_listener map; struct wl_listener map;
struct wl_listener unmap; struct wl_listener unmap;
struct wl_listener new_popup; struct wl_listener new_popup;
}; };
void xdg_popup_create(struct view *view, struct wlr_xdg_popup *wlr_popup);
void xdg_toplevel_decoration(struct wl_listener *listener, void *data); void xdg_toplevel_decoration(struct wl_listener *listener, void *data);
void xdg_surface_new(struct wl_listener *listener, void *data); void xdg_surface_new(struct wl_listener *listener, void *data);
#if HAVE_XWAYLAND #if HAVE_XWAYLAND
@ -268,6 +284,11 @@ void xwayland_unmanaged_create(struct server *server,
struct wlr_xwayland_surface *xsurface); struct wlr_xwayland_surface *xsurface);
#endif #endif
void view_child_init(struct view_child *child, struct view *view,
struct wlr_surface *wlr_surface);
void view_child_finish(struct view_child *child);
void subsurface_create(struct view *view, struct wlr_subsurface *wlr_subsurface);
void view_move_resize(struct view *view, struct wlr_box geo); void view_move_resize(struct view *view, struct wlr_box geo);
void view_move(struct view *view, double x, double y); void view_move(struct view *view, double x, double y);
void view_minimize(struct view *view); void view_minimize(struct view *view);

View file

@ -12,9 +12,12 @@ labwc_sources = files(
'output.c', 'output.c',
'seat.c', 'seat.c',
'server.c', 'server.c',
'subsurface.c',
'theme.c', 'theme.c',
'view.c', 'view.c',
'view-child.c',
'xdg.c', 'xdg.c',
'xdg-popup.c',
) )
if have_xwayland if have_xwayland

34
src/subsurface.c Normal file
View file

@ -0,0 +1,34 @@
/*
* Copyright (C) 2020 the sway authors
* This file is only needed in support of tracking damage
*/
#include "labwc.h"
static void
subsurface_handle_destroy(struct wl_listener *listener, void *data)
{
struct view_subsurface *subsurface = wl_container_of(listener,
subsurface, destroy);
struct view_child *view_child = (struct view_child *)subsurface;
if (!view_child) {
return;
}
wl_list_remove(&subsurface->destroy.link);
view_child_finish(&subsurface->view_child);
free(subsurface);
}
void
subsurface_create(struct view *view, struct wlr_subsurface *wlr_subsurface)
{
struct view_subsurface *subsurface = calloc(1, sizeof(struct view_subsurface));
if (!subsurface) {
return;
}
view_child_init(&subsurface->view_child, view, wlr_subsurface->surface);
subsurface->subsurface = wlr_subsurface;
subsurface->destroy.notify = subsurface_handle_destroy;
wl_signal_add(&wlr_subsurface->events.destroy, &subsurface->destroy);
}

46
src/view-child.c Normal file
View file

@ -0,0 +1,46 @@
/*
* Copyright (C) 2020 the sway authors
* This file is only needed in support of tracking damage
*/
#include "labwc.h"
static void
view_child_handle_commit(struct wl_listener *listener, void *data)
{
struct view_child *child = wl_container_of(listener, child, commit);
damage_view_part(child->parent);
}
static void
view_child_handle_new_subsurface(struct wl_listener *listener, void *data)
{
struct view_child *child;
child = wl_container_of(listener, child, new_subsurface);
struct wlr_subsurface *wlr_subsurface = data;
subsurface_create(child->parent, wlr_subsurface);
}
void
view_child_finish(struct view_child *child)
{
if (!child) {
return;
}
damage_view_whole(child->parent);
wl_list_remove(&child->commit.link);
wl_list_remove(&child->new_subsurface.link);
}
void
view_child_init(struct view_child *child, struct view *view,
struct wlr_surface *wlr_surface)
{
child->parent = view;
child->surface = wlr_surface;
child->commit.notify = view_child_handle_commit;
wl_signal_add(&wlr_surface->events.commit, &child->commit);
child->new_subsurface.notify = view_child_handle_new_subsurface;
wl_signal_add(&wlr_surface->events.new_subsurface, &child->new_subsurface);
}

View file

@ -1,7 +1,7 @@
#include "labwc.h" #include "labwc.h"
#include <stdio.h> #include <stdio.h>
#include <assert.h>
void void
view_move_resize(struct view *view, struct wlr_box geo) view_move_resize(struct view *view, struct wlr_box geo)
{ {

74
src/xdg-popup.c Normal file
View file

@ -0,0 +1,74 @@
/*
* Copyright (C) 2020 the sway authors
* This file is only needed in support of tracking damage
*/
#include "labwc.h"
static void
xdg_popup_destroy(struct view_child *view_child)
{
if (!view_child) {
return;
}
struct xdg_popup *popup = (struct xdg_popup *)view_child;
wl_list_remove(&popup->destroy.link);
wl_list_remove(&popup->map.link);
wl_list_remove(&popup->unmap.link);
wl_list_remove(&popup->new_popup.link);
view_child_finish(&popup->view_child);
free(popup);
}
static void
handle_xdg_popup_map(struct wl_listener *listener, void *data)
{
struct xdg_popup *popup = wl_container_of(listener, popup, map);
damage_view_whole(popup->view_child.parent);
}
static void
handle_xdg_popup_unmap(struct wl_listener *listener, void *data)
{
struct xdg_popup *popup = wl_container_of(listener, popup, unmap);
damage_view_whole(popup->view_child.parent);
}
static void
handle_xdg_popup_destroy(struct wl_listener *listener, void *data)
{
struct xdg_popup *popup = wl_container_of(listener, popup, destroy);
struct view_child *view_child = (struct view_child *)popup;
xdg_popup_destroy(view_child);
}
static void
popup_handle_new_xdg_popup(struct wl_listener *listener, void *data)
{
struct xdg_popup *popup = wl_container_of(listener, popup, new_popup);
struct wlr_xdg_popup *wlr_popup = data;
xdg_popup_create(popup->view_child.parent, wlr_popup);
}
void
xdg_popup_create(struct view *view, struct wlr_xdg_popup *wlr_popup)
{
struct xdg_popup *popup = calloc(1, sizeof(struct xdg_popup));
if (!popup) {
return;
}
popup->wlr_popup = wlr_popup;
view_child_init(&popup->view_child, view, wlr_popup->base->surface);
popup->destroy.notify = handle_xdg_popup_destroy;
wl_signal_add(&wlr_popup->base->events.destroy, &popup->destroy);
popup->map.notify = handle_xdg_popup_map;
wl_signal_add(&wlr_popup->base->events.map, &popup->map);
popup->unmap.notify = handle_xdg_popup_unmap;
wl_signal_add(&wlr_popup->base->events.unmap, &popup->unmap);
popup->new_popup.notify = popup_handle_new_xdg_popup;
wl_signal_add(&wlr_popup->base->events.new_popup, &popup->new_popup);
/* TODO: popup_unconstrain() */
}

View file

@ -52,78 +52,6 @@ xdg_toplevel_decoration(struct wl_listener *listener, void *data)
xdg_deco_request_mode(&xdg_deco->request_mode, wlr_decoration); xdg_deco_request_mode(&xdg_deco->request_mode, wlr_decoration);
} }
static void
handle_xdg_popup_commit(struct wl_listener *listener, void *data)
{
struct xdg_popup *popup = wl_container_of(listener, popup, map);
/* TODO */
}
static void
handle_xdg_popup_map(struct wl_listener *listener, void *data)
{
struct xdg_popup *popup = wl_container_of(listener, popup, map);
/* damagage whole output here as popup might go outside view */
damage_all_outputs(popup->view->server);
}
static void
handle_xdg_popup_unmap(struct wl_listener *listener, void *data)
{
struct xdg_popup *popup = wl_container_of(listener, popup, unmap);
damage_all_outputs(popup->view->server);
}
static void
handle_xdg_popup_destroy(struct wl_listener *listener, void *data)
{
struct xdg_popup *popup = wl_container_of(listener, popup, destroy);
wl_list_remove(&popup->destroy.link);
wl_list_remove(&popup->commit.link);
wl_list_remove(&popup->map.link);
wl_list_remove(&popup->unmap.link);
wl_list_remove(&popup->new_popup.link);
free(popup);
}
static void xdg_popup_create(struct view *view, struct wlr_xdg_popup *wlr_popup);
static void
popup_handle_new_xdg_popup(struct wl_listener *listener, void *data)
{
struct xdg_popup *popup = wl_container_of(listener, popup, new_popup);
struct wlr_xdg_popup *wlr_popup = data;
xdg_popup_create(popup->view, wlr_popup);
}
/*
* We need to pass view to this function for damage tracking.
* TODO: Could we just damage surface or whole output?
* That would allow us to only have one 'handle_new_*'
*/
static void
xdg_popup_create(struct view *view, struct wlr_xdg_popup *wlr_popup)
{
struct xdg_popup *popup = calloc(1, sizeof(struct xdg_popup));
if (!popup) {
return;
}
popup->wlr_popup = wlr_popup;
popup->view = view;
popup->destroy.notify = handle_xdg_popup_destroy;
wl_signal_add(&wlr_popup->base->events.destroy, &popup->destroy);
popup->commit.notify = handle_xdg_popup_commit;
wl_signal_add(&wlr_popup->base->surface->events.commit, &popup->commit);
popup->map.notify = handle_xdg_popup_map;
wl_signal_add(&wlr_popup->base->events.map, &popup->map);
popup->unmap.notify = handle_xdg_popup_unmap;
wl_signal_add(&wlr_popup->base->events.unmap, &popup->unmap);
popup->new_popup.notify = popup_handle_new_xdg_popup;
wl_signal_add(&wlr_popup->base->events.new_popup, &popup->new_popup);
}
/* This is merely needed to track damage */ /* This is merely needed to track damage */
static void static void
handle_new_xdg_popup(struct wl_listener *listener, void *data) handle_new_xdg_popup(struct wl_listener *listener, void *data)
@ -133,6 +61,14 @@ handle_new_xdg_popup(struct wl_listener *listener, void *data)
xdg_popup_create(view, wlr_popup); xdg_popup_create(view, wlr_popup);
} }
static void
new_subsurface_notify(struct wl_listener *listener, void *data)
{
struct view *view = wl_container_of(listener, view, new_subsurface);
struct wlr_subsurface *wlr_subsurface = data;
subsurface_create(view, wlr_subsurface);
}
static bool static bool
has_ssd(struct view *view) has_ssd(struct view *view)
{ {
@ -348,9 +284,12 @@ xdg_toplevel_view_map(struct view *view)
} }
view->been_mapped = true; view->been_mapped = true;
view->commit.notify = handle_commit;
wl_signal_add(&view->xdg_surface->surface->events.commit, wl_signal_add(&view->xdg_surface->surface->events.commit,
&view->commit); &view->commit);
view->commit.notify = handle_commit; view->new_subsurface.notify = new_subsurface_notify;
wl_signal_add(&view->surface->events.new_subsurface,
&view->new_subsurface);
desktop_focus_view(&view->server->seat, view); desktop_focus_view(&view->server->seat, view);
damage_all_outputs(view->server); damage_all_outputs(view->server);
@ -362,6 +301,7 @@ xdg_toplevel_view_unmap(struct view *view)
view->mapped = false; view->mapped = false;
damage_all_outputs(view->server); damage_all_outputs(view->server);
wl_list_remove(&view->commit.link); wl_list_remove(&view->commit.link);
wl_list_remove(&view->new_subsurface.link);
desktop_focus_topmost_mapped_view(view->server); desktop_focus_topmost_mapped_view(view->server);
} }