mirror of
				https://github.com/labwc/labwc.git
				synced 2025-11-03 09:01:51 -05:00 
			
		
		
		
	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:
		
							parent
							
								
									15a7910a02
								
							
						
					
					
						commit
						d54a998dd8
					
				
					 7 changed files with 196 additions and 78 deletions
				
			
		| 
						 | 
				
			
			@ -231,6 +231,7 @@ struct view {
 | 
			
		|||
	struct wl_listener request_configure;
 | 
			
		||||
	struct wl_listener request_maximize;
 | 
			
		||||
	struct wl_listener new_popup;		/* xdg-shell only */
 | 
			
		||||
	struct wl_listener new_subsurface;	/* xdg-shell only */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if HAVE_XWAYLAND
 | 
			
		||||
| 
						 | 
				
			
			@ -248,18 +249,33 @@ struct xwayland_unmanaged {
 | 
			
		|||
};
 | 
			
		||||
#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 view_child view_child;
 | 
			
		||||
	struct wlr_xdg_popup *wlr_popup;
 | 
			
		||||
	struct view *view;
 | 
			
		||||
 | 
			
		||||
	struct wl_listener destroy;
 | 
			
		||||
	struct wl_listener commit;
 | 
			
		||||
	struct wl_listener map;
 | 
			
		||||
	struct wl_listener unmap;
 | 
			
		||||
	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_surface_new(struct wl_listener *listener, void *data);
 | 
			
		||||
 | 
			
		||||
#if HAVE_XWAYLAND
 | 
			
		||||
| 
						 | 
				
			
			@ -268,6 +284,11 @@ void xwayland_unmanaged_create(struct server *server,
 | 
			
		|||
	struct wlr_xwayland_surface *xsurface);
 | 
			
		||||
#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(struct view *view, double x, double y);
 | 
			
		||||
void view_minimize(struct view *view);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,9 +12,12 @@ labwc_sources = files(
 | 
			
		|||
  'output.c',
 | 
			
		||||
  'seat.c',
 | 
			
		||||
  'server.c',
 | 
			
		||||
  'subsurface.c',
 | 
			
		||||
  'theme.c',
 | 
			
		||||
  'view.c',
 | 
			
		||||
  'view-child.c',
 | 
			
		||||
  'xdg.c',
 | 
			
		||||
  'xdg-popup.c',
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
if have_xwayland
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										34
									
								
								src/subsurface.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/subsurface.c
									
										
									
									
									
										Normal 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
									
								
							
							
						
						
									
										46
									
								
								src/view-child.c
									
										
									
									
									
										Normal 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);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
#include "labwc.h"
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
view_move_resize(struct view *view, struct wlr_box geo)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										74
									
								
								src/xdg-popup.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								src/xdg-popup.c
									
										
									
									
									
										Normal 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() */
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										86
									
								
								src/xdg.c
									
										
									
									
									
								
							
							
						
						
									
										86
									
								
								src/xdg.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -52,78 +52,6 @@ xdg_toplevel_decoration(struct wl_listener *listener, void *data)
 | 
			
		|||
	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 */
 | 
			
		||||
static void
 | 
			
		||||
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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
has_ssd(struct view *view)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -348,9 +284,12 @@ xdg_toplevel_view_map(struct view *view)
 | 
			
		|||
	}
 | 
			
		||||
	view->been_mapped = true;
 | 
			
		||||
 | 
			
		||||
	view->commit.notify = handle_commit;
 | 
			
		||||
	wl_signal_add(&view->xdg_surface->surface->events.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);
 | 
			
		||||
	damage_all_outputs(view->server);
 | 
			
		||||
| 
						 | 
				
			
			@ -362,6 +301,7 @@ xdg_toplevel_view_unmap(struct view *view)
 | 
			
		|||
	view->mapped = false;
 | 
			
		||||
	damage_all_outputs(view->server);
 | 
			
		||||
	wl_list_remove(&view->commit.link);
 | 
			
		||||
	wl_list_remove(&view->new_subsurface.link);
 | 
			
		||||
	desktop_focus_topmost_mapped_view(view->server);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue