mirror of
				https://github.com/labwc/labwc.git
				synced 2025-11-03 09:01:51 -05:00 
			
		
		
		
	Decorations: handle results of kde-server-decoration negotiations
This commit is contained in:
		
							parent
							
								
									5ee2ec7fff
								
							
						
					
					
						commit
						ef30e3750d
					
				
					 6 changed files with 160 additions and 36 deletions
				
			
		
							
								
								
									
										132
									
								
								src/decorations/kde-deco.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								src/decorations/kde-deco.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,132 @@
 | 
			
		|||
// SPDX-License-Identifier: GPL-2.0-only
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <wlr/types/wlr_server_decoration.h>
 | 
			
		||||
#include "common/list.h"
 | 
			
		||||
#include "common/mem.h"
 | 
			
		||||
#include "decorations.h"
 | 
			
		||||
#include "labwc.h"
 | 
			
		||||
#include "view.h"
 | 
			
		||||
 | 
			
		||||
static struct wl_list decorations;
 | 
			
		||||
static struct wlr_server_decoration_manager *kde_deco_mgr;
 | 
			
		||||
 | 
			
		||||
struct kde_deco {
 | 
			
		||||
	struct wl_list link;  /* decorations */
 | 
			
		||||
	struct wlr_server_decoration *wlr_kde_decoration;
 | 
			
		||||
	struct view *view;
 | 
			
		||||
	struct wl_listener mode;
 | 
			
		||||
	struct wl_listener destroy;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
handle_destroy(struct wl_listener *listener, void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct kde_deco *kde_deco = wl_container_of(listener, kde_deco, destroy);
 | 
			
		||||
	wl_list_remove(&kde_deco->destroy.link);
 | 
			
		||||
	wl_list_remove(&kde_deco->mode.link);
 | 
			
		||||
	wl_list_remove(&kde_deco->link);
 | 
			
		||||
	free(kde_deco);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
handle_mode(struct wl_listener *listener, void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct kde_deco *kde_deco = wl_container_of(listener, kde_deco, mode);
 | 
			
		||||
	if (!kde_deco->view) {
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	enum wlr_server_decoration_manager_mode client_mode =
 | 
			
		||||
		kde_deco->wlr_kde_decoration->mode;
 | 
			
		||||
 | 
			
		||||
	switch (client_mode) {
 | 
			
		||||
	case WLR_SERVER_DECORATION_MANAGER_MODE_SERVER:
 | 
			
		||||
		kde_deco->view->ssd_preference = LAB_SSD_PREF_SERVER;
 | 
			
		||||
		break;
 | 
			
		||||
	case WLR_SERVER_DECORATION_MANAGER_MODE_NONE:
 | 
			
		||||
	case WLR_SERVER_DECORATION_MANAGER_MODE_CLIENT:
 | 
			
		||||
		kde_deco->view->ssd_preference = LAB_SSD_PREF_CLIENT;
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		wlr_log(WLR_ERROR, "Unspecified kde decoration variant "
 | 
			
		||||
			"requested: %u", client_mode);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	view_set_decorations(kde_deco->view,
 | 
			
		||||
		kde_deco->view->ssd_preference == LAB_SSD_PREF_SERVER);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
handle_new_server_decoration(struct wl_listener *listener, void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct wlr_server_decoration *wlr_deco = data;
 | 
			
		||||
	struct kde_deco *kde_deco = znew(*kde_deco);
 | 
			
		||||
	kde_deco->wlr_kde_decoration = wlr_deco;
 | 
			
		||||
 | 
			
		||||
	if (wlr_surface_is_xdg_surface(wlr_deco->surface)) {
 | 
			
		||||
		/*
 | 
			
		||||
		 * Depending on the application event flow, the supplied
 | 
			
		||||
		 * wlr_surface may already have been set up as a xdg_surface
 | 
			
		||||
		 * or not (e.g. for GTK4). In the second case, the xdg.c
 | 
			
		||||
		 * new_surface handler will try to set the view via
 | 
			
		||||
		 * kde_server_decoration_set_view().
 | 
			
		||||
		 */
 | 
			
		||||
		struct wlr_xdg_surface *xdg_surface =
 | 
			
		||||
			wlr_xdg_surface_from_wlr_surface(wlr_deco->surface);
 | 
			
		||||
		if (xdg_surface && xdg_surface->data) {
 | 
			
		||||
			kde_deco->view = (struct view *)xdg_surface->data;
 | 
			
		||||
			handle_mode(&kde_deco->mode, wlr_deco);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	wl_signal_add(&wlr_deco->events.destroy, &kde_deco->destroy);
 | 
			
		||||
	kde_deco->destroy.notify = handle_destroy;
 | 
			
		||||
 | 
			
		||||
	wl_signal_add(&wlr_deco->events.mode, &kde_deco->mode);
 | 
			
		||||
	kde_deco->mode.notify = handle_mode;
 | 
			
		||||
 | 
			
		||||
	wl_list_append(&decorations, &kde_deco->link);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
kde_server_decoration_set_view(struct view *view, struct wlr_surface *surface)
 | 
			
		||||
{
 | 
			
		||||
	struct kde_deco *kde_deco;
 | 
			
		||||
	wl_list_for_each(kde_deco, &decorations, link) {
 | 
			
		||||
		if (kde_deco->wlr_kde_decoration->surface == surface) {
 | 
			
		||||
			if (!kde_deco->view) {
 | 
			
		||||
				kde_deco->view = view;
 | 
			
		||||
				handle_mode(&kde_deco->mode, kde_deco->wlr_kde_decoration);
 | 
			
		||||
			}
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
kde_server_decoration_update_default(void)
 | 
			
		||||
{
 | 
			
		||||
	assert(kde_deco_mgr);
 | 
			
		||||
	wlr_server_decoration_manager_set_default_mode(kde_deco_mgr,
 | 
			
		||||
		rc.xdg_shell_server_side_deco
 | 
			
		||||
		? WLR_SERVER_DECORATION_MANAGER_MODE_SERVER
 | 
			
		||||
		: WLR_SERVER_DECORATION_MANAGER_MODE_CLIENT);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
kde_server_decoration_init(struct server *server)
 | 
			
		||||
{
 | 
			
		||||
	assert(!kde_deco_mgr);
 | 
			
		||||
	kde_deco_mgr = wlr_server_decoration_manager_create(server->wl_display);
 | 
			
		||||
	if (!kde_deco_mgr) {
 | 
			
		||||
		wlr_log(WLR_ERROR, "unable to create the kde server deco manager");
 | 
			
		||||
		exit(EXIT_FAILURE);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	wl_list_init(&decorations);
 | 
			
		||||
	kde_server_decoration_update_default();
 | 
			
		||||
 | 
			
		||||
	wl_signal_add(&kde_deco_mgr->events.new_decoration, &server->kde_server_decoration);
 | 
			
		||||
	server->kde_server_decoration.notify = handle_new_server_decoration;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1,3 +1,4 @@
 | 
			
		|||
labwc_sources += files(
 | 
			
		||||
  'kde-deco.c',
 | 
			
		||||
  'xdg-deco.c',
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										13
									
								
								src/server.c
									
										
									
									
									
								
							
							
						
						
									
										13
									
								
								src/server.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -53,6 +53,7 @@ reload_config_and_theme(void)
 | 
			
		|||
	menu_reconfigure(g_server);
 | 
			
		||||
	seat_reconfigure(g_server);
 | 
			
		||||
	regions_reconfigure(g_server);
 | 
			
		||||
	kde_server_decoration_update_default();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
| 
						 | 
				
			
			@ -310,18 +311,8 @@ server_init(struct server *server)
 | 
			
		|||
	wl_signal_add(&server->xdg_shell->events.new_surface,
 | 
			
		||||
		&server->new_xdg_surface);
 | 
			
		||||
 | 
			
		||||
	/* Disable CSD */
 | 
			
		||||
	kde_server_decoration_init(server);
 | 
			
		||||
	xdg_server_decoration_init(server);
 | 
			
		||||
	struct wlr_server_decoration_manager *deco_mgr = NULL;
 | 
			
		||||
	deco_mgr = wlr_server_decoration_manager_create(server->wl_display);
 | 
			
		||||
	if (!deco_mgr) {
 | 
			
		||||
		wlr_log(WLR_ERROR, "unable to create the server deco manager");
 | 
			
		||||
		exit(EXIT_FAILURE);
 | 
			
		||||
	}
 | 
			
		||||
	wlr_server_decoration_manager_set_default_mode(
 | 
			
		||||
		deco_mgr, rc.xdg_shell_server_side_deco
 | 
			
		||||
		? WLR_SERVER_DECORATION_MANAGER_MODE_SERVER
 | 
			
		||||
		: WLR_SERVER_DECORATION_MANAGER_MODE_CLIENT);
 | 
			
		||||
 | 
			
		||||
	server->xdg_activation = wlr_xdg_activation_v1_create(server->wl_display);
 | 
			
		||||
	if (!server->xdg_activation) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										42
									
								
								src/xdg.c
									
										
									
									
									
								
							
							
						
						
									
										42
									
								
								src/xdg.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,6 +1,7 @@
 | 
			
		|||
// SPDX-License-Identifier: GPL-2.0-only
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include "common/mem.h"
 | 
			
		||||
#include "decorations.h"
 | 
			
		||||
#include "labwc.h"
 | 
			
		||||
#include "node.h"
 | 
			
		||||
#include "view.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -48,38 +49,22 @@ handle_new_xdg_popup(struct wl_listener *listener, void *data)
 | 
			
		|||
static bool
 | 
			
		||||
has_ssd(struct view *view)
 | 
			
		||||
{
 | 
			
		||||
	/*
 | 
			
		||||
	 * view->ssd_preference may be set by the decoration implementation
 | 
			
		||||
	 * e.g. src/decorations/xdg-deco.c or src/decorations/kde-deco.c.
 | 
			
		||||
	 */
 | 
			
		||||
	switch (view->ssd_preference) {
 | 
			
		||||
	case LAB_SSD_PREF_SERVER:
 | 
			
		||||
		return true;
 | 
			
		||||
	case LAB_SSD_PREF_CLIENT:
 | 
			
		||||
		return false;
 | 
			
		||||
	default:
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!rc.xdg_shell_server_side_deco) {
 | 
			
		||||
		/*
 | 
			
		||||
		 * User prefers client side decorations and
 | 
			
		||||
		 * the view didn't negotiate server side ones.
 | 
			
		||||
		 * We don't know anything about the client preference
 | 
			
		||||
		 * so fall back to core.decoration settings in rc.xml
 | 
			
		||||
		 */
 | 
			
		||||
		return false;
 | 
			
		||||
		return rc.xdg_shell_server_side_deco;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Some XDG shells refuse to disable CSD in which case their
 | 
			
		||||
	 * geometry.{x,y} seems to be greater than zero. We filter on that
 | 
			
		||||
	 * on the assumption that this will remain true.
 | 
			
		||||
	 *
 | 
			
		||||
	 * TODO: Replace this with a proper implementation of
 | 
			
		||||
	 *       the KDE decoration variant as can be seen at
 | 
			
		||||
	 *       https://github.com/swaywm/sway/blob/master/sway/decoration.c
 | 
			
		||||
	 */
 | 
			
		||||
	struct wlr_xdg_surface_state *current =
 | 
			
		||||
		&xdg_surface_from_view(view)->current;
 | 
			
		||||
	if (current->geometry.x || current->geometry.y) {
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
| 
						 | 
				
			
			@ -560,9 +545,18 @@ xdg_surface_new(struct wl_listener *listener, void *data)
 | 
			
		|||
	node_descriptor_create(&view->scene_tree->node,
 | 
			
		||||
		LAB_NODE_DESC_VIEW, view);
 | 
			
		||||
 | 
			
		||||
	/* In support of xdg_toplevel_decoration */
 | 
			
		||||
	/* In support of xdg_toplevel_decoration and kde_server_decoration */
 | 
			
		||||
	xdg_surface->data = view;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * GTK4 initializes the decorations on the wl_surface before
 | 
			
		||||
	 * converting it into a xdg surface. This call takes care of
 | 
			
		||||
	 * connecting the view to an existing decoration. If there
 | 
			
		||||
	 * is no existing decoration object available for the
 | 
			
		||||
	 * wl_surface, this call is a no-op.
 | 
			
		||||
	 */
 | 
			
		||||
	kde_server_decoration_set_view(view, xdg_surface->surface);
 | 
			
		||||
 | 
			
		||||
	/* In support of xdg popups */
 | 
			
		||||
	xdg_surface->surface->data = tree;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue