commit 031fb17

hovercats  ·  2026-03-13 07:50:04 +0000 UTC
parent e91e180
swc: include another patch from neuswc.
I have no idea why, but when I rebased the patches earlier, I omited the screenshot patch, it broke swalls ability to set wallpapers.
15 files changed,  +623, -77
+8, -1
 1@@ -30,8 +30,12 @@ waylandproto('protocol/server-decoration.xml', {
 2 	code='server-decoration-protocol.c',
 3 })
 4 
 5+waylandproto('protocol/swc_snap.xml', {
 6+       server='include/swc_snap-server-protocol.h',
 7+       code='swc_snap-protocol.c',
 8+})
 9+
10 waylandproto('protocol/swc_wallpaper.xml', {
11-       client='include/swc_wallpaper-client-protocol.h',
12        server='include/swc_wallpaper-server-protocol.h',
13        code='swc_wallpaper-protocol.c',
14 })
15@@ -56,6 +60,7 @@ build('convert_font', '$outdir/cursor/cursor_data.h', {'$srcdir/cursor/cursor.pc
16 
17 pkg.deps = {
18 	'$gendir/headers',
19+	'$outdir/include/swc_snap-server-protocol.h',
20 	'$outdir/include/swc_wallpaper-server-protocol.h',
21 	'$outdir/wayland-drm-server-protocol.h',
22 	'$outdir/cursor/cursor_data.h',
23@@ -96,6 +101,7 @@ lib('libswc.a', [[
24 		shell_surface.c
25 		seat.c
26 		shm.c
27+		snap.c
28 		subcompositor.c
29 		subsurface.c
30 		surface.c
31@@ -111,6 +117,7 @@ lib('libswc.a', [[
32 	launch/protocol.c.o
33 	server-decoration-protocol.c.o
34 	swc-protocol.c.o
35+	swc_snap-protocol.c.o
36 	swc_wallpaper-protocol.c.o
37 	$builddir/(
38 		pkg/libinput/libinput.a.d
R pkg/swc/patch/0009-custom-cursors-add-support-for-custom-cursor-images-.patch => pkg/swc/patch/0007-custom-cursors-add-support-for-custom-cursor-images-.patch
+2, -2
 1@@ -1,4 +1,4 @@
 2-From b89f8f1c30e8d92e33d977ebd8a014281aa4d340 Mon Sep 17 00:00:00 2001
 3+From ac353c5601b7e774ae4465e432ce1d6de1a755de Mon Sep 17 00:00:00 2001
 4 From: shrub <maybeshrub@gmail.com>
 5 Date: Wed, 17 Dec 2025 02:04:55 +0000
 6 Subject: [PATCH] custom cursors add support for custom cursor images from
 7@@ -174,7 +174,7 @@ index cb2582c..cff6bb6 100644
 8  		surface_set_view(pointer->cursor.surface, NULL);
 9  		wl_list_remove(&pointer->cursor.destroy_listener.link);
10 diff --git a/libswc/swc.h b/libswc/swc.h
11-index dde7ef0..29638d9 100644
12+index 2aa06c8..03c3cbc 100644
13 --- a/libswc/swc.h
14 +++ b/libswc/swc.h
15 @@ -63,6 +63,49 @@ void swc_pointer_send_button(uint32_t time, uint32_t button, uint32_t state);
R pkg/swc/patch/0013-add-wallpaper-support.patch => pkg/swc/patch/0008-add-wallpaper-support-this-was-the-initial-wallpaper.patch
+8, -6
 1@@ -1,7 +1,9 @@
 2-From 73322f31c68b0ef38e16534b80aae31a75ef712c Mon Sep 17 00:00:00 2001
 3+From 42b049150c64e99da7e5ccaea0bba87dfbf7e102 Mon Sep 17 00:00:00 2001
 4 From: dalem <lain@dalem.foo>
 5 Date: Sat, 20 Dec 2025 21:09:41 +0100
 6-Subject: [PATCH] add wallpaper support.
 7+Subject: [PATCH] add wallpaper support this was the initial wallpaper
 8+ implementation using stb image header. it has since been changed and mostly
 9+ moved to the client.
10 
11 ---
12  libswc/compositor.c |  8 ++++++--
13@@ -11,10 +13,10 @@ Subject: [PATCH] add wallpaper support.
14  create mode 100644 libswc/wallpaper.c
15 
16 diff --git a/libswc/compositor.c b/libswc/compositor.c
17-index 0f978d9..d70377d 100644
18+index 263da39..fae7991 100644
19 --- a/libswc/compositor.c
20 +++ b/libswc/compositor.c
21-@@ -287,10 +287,14 @@ renderer_repaint(struct target *target, pixman_region32_t *damage, pixman_region
22+@@ -283,10 +283,14 @@ renderer_repaint(struct target *target, pixman_region32_t *damage, pixman_region
23  
24  	wld_set_target_surface(swc.drm->renderer, target->surface);
25  
26@@ -32,10 +34,10 @@ index 0f978d9..d70377d 100644
27  
28  	wl_list_for_each_reverse (view, views, link) {
29 diff --git a/libswc/swc.h b/libswc/swc.h
30-index 505391d..a23e556 100644
31+index 03c3cbc..bbade8f 100644
32 --- a/libswc/swc.h
33 +++ b/libswc/swc.h
34-@@ -436,6 +436,29 @@ int swc_add_axis_binding(uint32_t modifiers, uint32_t axis, swc_axis_binding_han
35+@@ -410,6 +410,29 @@ int swc_add_axis_binding(uint32_t modifiers, uint32_t axis, swc_axis_binding_han
36  
37  /* }}} */
38  
R pkg/swc/patch/0014-this-adds-wallpaper-scaling-to-the-initial-wallpaper.patch => pkg/swc/patch/0009-add-wallpaper-scaling-to-the-initial-wallpaper-imple.patch
+2, -2
 1@@ -1,7 +1,7 @@
 2-From 5be9ee4cbc06aefed8fe11360df8cc9d045c3587 Mon Sep 17 00:00:00 2001
 3+From 8e7afcd98a761cdf53006de0db703412dac56310 Mon Sep 17 00:00:00 2001
 4 From: shrub <maybeshrub@gmail.com>
 5 Date: Sat, 20 Dec 2025 20:40:26 +0000
 6-Subject: [PATCH] this adds wallpaper scaling to the initial wallpaper
 7+Subject: [PATCH] add wallpaper scaling to the initial wallpaper
 8  implementation, so the wallpaper scales to screen size.
 9 
10 ---
+475, -0
  1@@ -0,0 +1,475 @@
  2+From a6b60a7c94dd00a9900b05e932e2ffb8612f05bd Mon Sep 17 00:00:00 2001
  3+From: shrub <maybeshrub@gmail.com>
  4+Date: Mon, 29 Dec 2025 20:58:33 +0000
  5+Subject: [PATCH] screenshots initial implementation of swc_snap screenshot
  6+ protocol
  7+
  8+---
  9+ libswc/compositor.c   | 116 +++++++++++++++++++++++++
 10+ libswc/compositor.h   |  15 ++++
 11+ libswc/internal.h     |   1 +
 12+ libswc/snap.c         | 193 ++++++++++++++++++++++++++++++++++++++++++
 13+ libswc/snap.h         |   9 ++
 14+ libswc/swc.c          |  14 ++-
 15+ protocol/swc_snap.xml |  15 ++++
 16+ 7 files changed, 361 insertions(+), 2 deletions(-)
 17+ create mode 100644 libswc/snap.c
 18+ create mode 100644 libswc/snap.h
 19+ create mode 100644 protocol/swc_snap.xml
 20+
 21+diff --git a/libswc/compositor.c b/libswc/compositor.c
 22+index fae7991..0bf3210 100644
 23+--- a/libswc/compositor.c
 24++++ b/libswc/compositor.c
 25+@@ -1189,3 +1189,119 @@ compositor_finalize(void)
 26+ 	pixman_region32_fini(&compositor.opaque);
 27+ 	wl_global_destroy(compositor.global);
 28+ }
 29++
 30++struct wld_buffer *
 31++compositor_get_buffer(struct screen *screen)
 32++{
 33++	struct target *target = target_get(screen);
 34++	if (!target)
 35++		return NULL;
 36++	return target->current_buffer;
 37++}
 38++
 39++struct wld_buffer *
 40++compositor_render_to_shm(struct screen *screen)
 41++{
 42++	uint32_t width = screen->base.geometry.width;
 43++	uint32_t height = screen->base.geometry.height;
 44++	struct wld_buffer *buffer;
 45++	struct compositor_view *view;
 46++	pixman_region32_t region;
 47++	pixman_region32_t damage;
 48++	uint32_t caps;
 49++
 50++	/* create shm buf */
 51++	buffer = wld_create_buffer(swc.shm->context, width, height,
 52++	                           WLD_FORMAT_ARGB8888, WLD_FLAG_MAP);
 53++	if (!buffer)
 54++		return NULL;
 55++
 56++	caps = wld_capabilities(swc.shm->renderer, buffer);
 57++	if (!(caps & WLD_CAPABILITY_WRITE) ||
 58++	    !wld_set_target_buffer(swc.shm->renderer, buffer)) {
 59++		wld_buffer_unreference(buffer);
 60++		return NULL;
 61++	}
 62++
 63++	/* set reigon */
 64++	pixman_region32_init_rect(&region, 0, 0, width, height);
 65++	pixman_region32_init_rect(&damage, screen->base.geometry.x, screen->base.geometry.y, width, height);
 66++
 67++	/* background */
 68++	if (wallbuf)
 69++		wld_copy_region(swc.shm->renderer, wallbuf, 0, 0, &region);
 70++	else
 71++		wld_fill_region(swc.shm->renderer, bgcolor, &region);
 72++
 73++	wl_list_for_each_reverse(view, &compositor.views, link) {
 74++		struct wld_buffer *src = view->buffer;
 75++
 76++		if (!view->visible)
 77++			continue;
 78++
 79++		if (src && !(wld_capabilities(swc.shm->renderer, src) & WLD_CAPABILITY_READ))
 80++			src = view->base.buffer;
 81++
 82++		if (src && (wld_capabilities(swc.shm->renderer, src) & WLD_CAPABILITY_READ)) {
 83++			int32_t x = view->base.geometry.x - screen->base.geometry.x;
 84++			int32_t y = view->base.geometry.y - screen->base.geometry.y;
 85++
 86++			wld_copy_rectangle(swc.shm->renderer, src,
 87++			                   x, y, 0, 0,
 88++			                   view->base.geometry.width, view->base.geometry.height);
 89++		}
 90++
 91++		if ((view->border.outwidth > 0 || view->border.inwidth > 0) && view->base.buffer) {
 92++			pixman_region32_t view_region, view_damage, border_damage;
 93++			const struct swc_rectangle *geom = &view->base.geometry;
 94++			const struct swc_rectangle *target_geom = &screen->base.geometry;
 95++
 96++			pixman_region32_init_rect(&view_region, geom->x, geom->y, geom->width, geom->height);
 97++			pixman_region32_init_with_extents(&view_damage, &view->extents);
 98++			pixman_region32_init(&border_damage);
 99++
100++			pixman_region32_intersect(&view_damage, &view_damage, &damage);
101++			pixman_region32_subtract(&view_damage, &view_damage, &view->clip);
102++			pixman_region32_subtract(&border_damage, &view_damage, &view_region);
103++
104++			pixman_region32_t in_rect;
105++			pixman_region32_init_rect(&in_rect,
106++			                          geom->x - view->border.inwidth,
107++			                          geom->y - view->border.inwidth,
108++			                          geom->width + (2 * view->border.inwidth),
109++			                          geom->height + (2 * view->border.inwidth));
110++
111++			pixman_region32_t out_border;
112++			pixman_region32_init(&out_border);
113++			pixman_region32_subtract(&out_border, &border_damage, &in_rect);
114++
115++			pixman_region32_t in_border;
116++			pixman_region32_init(&in_border);
117++			pixman_region32_subtract(&in_border, &in_rect, &view_region);
118++			pixman_region32_intersect(&in_border, &in_border, &border_damage);
119++
120++			if (view->border.outwidth > 0 && pixman_region32_not_empty(&out_border)) {
121++				pixman_region32_translate(&out_border, -target_geom->x, -target_geom->y);
122++				wld_fill_region(swc.shm->renderer, view->border.outcolor, &out_border);
123++			}
124++
125++			if (view->border.inwidth > 0 && pixman_region32_not_empty(&in_border)) {
126++				pixman_region32_translate(&in_border, -target_geom->x, -target_geom->y);
127++				wld_fill_region(swc.shm->renderer, view->border.incolor, &in_border);
128++			}
129++
130++			pixman_region32_fini(&border_damage);
131++			pixman_region32_fini(&view_region);
132++			pixman_region32_fini(&view_damage);
133++			pixman_region32_fini(&in_rect);
134++			pixman_region32_fini(&out_border);
135++			pixman_region32_fini(&in_border);
136++		}
137++	}
138++
139++	wld_flush(swc.shm->renderer);
140++	pixman_region32_fini(&region);
141++	pixman_region32_fini(&damage);
142++
143++	return buffer;
144++}
145+diff --git a/libswc/compositor.h b/libswc/compositor.h
146+index 9046f0b..2e70b38 100644
147+--- a/libswc/compositor.h
148++++ b/libswc/compositor.h
149+@@ -30,6 +30,9 @@
150+ #include <pixman.h>
151+ #include <wayland-server.h>
152+ 
153++struct screen;
154++struct wld_buffer;
155++
156+ struct swc_compositor {
157+ 	struct pointer_handler *const pointer_handler;
158+ 	struct {
159+@@ -97,4 +100,16 @@ void compositor_view_hide(struct compositor_view *view);
160+ void compositor_view_set_border_color(struct compositor_view *view, uint32_t outcolor, uint32_t incolor);
161+ void compositor_view_set_border_width(struct compositor_view *view, uint32_t outwidth, uint32_t inwidth);
162+ 
163++/**
164++ * get the current composited buffer for a screen for screenshotss.
165++ * returns null if no buffer
166++ */
167++struct wld_buffer *compositor_get_buffer(struct screen *screen);
168++
169++/**
170++ * render the compositor scene into a shm buffer 
171++ * caller must free with wld_buffer_unreference()
172++ */
173++struct wld_buffer *compositor_render_to_shm(struct screen *screen);
174++
175+ #endif
176+diff --git a/libswc/internal.h b/libswc/internal.h
177+index 8efba6d..243b75f 100644
178+--- a/libswc/internal.h
179++++ b/libswc/internal.h
180+@@ -49,6 +49,7 @@ struct swc {
181+ 	struct wl_global *kde_decoration_manager;
182+ 	struct wl_global *panel_manager;
183+ 	struct wl_global *shell;
184++	struct wl_global *snap_manager;
185+ 	struct wl_global *subcompositor;
186+ 	struct wl_global *xdg_decoration_manager;
187+ 	struct wl_global *xdg_shell;
188+diff --git a/libswc/snap.c b/libswc/snap.c
189+new file mode 100644
190+index 0000000..f977649
191+--- /dev/null
192++++ b/libswc/snap.c
193+@@ -0,0 +1,193 @@
194++#include "snap.h"
195++#include "internal.h"
196++#include "screen.h"
197++#include "compositor.h"
198++#include "shm.h"
199++#include "seat.h"
200++#include "pointer.h"
201++
202++#include <stdio.h>
203++#include <stdlib.h>
204++#include <stdint.h>
205++#include <string.h>
206++#include <unistd.h>
207++#include <wayland-server.h>
208++#include <wld/wld.h>
209++#include "swc_snap-server-protocol.h"
210++
211++static void
212++ppm(int fd, const uint8_t *pixels, uint32_t width, uint32_t height,
213++    uint32_t pitch)
214++{
215++	FILE *f = fdopen(fd, "wb");
216++	if (!f) {
217++		close(fd);
218++		return;
219++	}
220++
221++	/* ppm  header */
222++	fprintf(f, "P6\n%u %u\n255\n", width, height);
223++
224++	/* pixel data convert argb8888 to rgb) */
225++	for (uint32_t y = 0; y < height; y++) {
226++		const uint32_t *row = (const uint32_t *)(pixels + ((size_t)y * pitch));
227++
228++		for (uint32_t x = 0; x < width; x++) {
229++			uint32_t pixel = row[x];
230++			unsigned char rgb[3] = {
231++				(pixel >> 16) & 0xFF,  
232++				(pixel >> 8) & 0xFF,   
233++				pixel & 0xFF           
234++			};
235++			fwrite(rgb, 1, 3, f);
236++		}
237++	}
238++
239++	fclose(f); 
240++}
241++
242++
243++/* get cursor */
244++static void
245++cursor(uint8_t *dst, uint32_t dst_width, uint32_t dst_height,
246++       uint32_t dst_pitch, struct screen *screen)
247++{
248++	struct pointer *pointer = swc.seat ? swc.seat->pointer : NULL;
249++	struct wld_buffer *cursor_buf;
250++	const uint8_t *src;
251++	int32_t dst_x, dst_y;
252++	int32_t src_x = 0, src_y = 0;
253++	uint32_t copy_w, copy_h;
254++
255++	if (!pointer || !pointer->cursor.buffer || !pointer->cursor.view.buffer)
256++		return;
257++
258++	if (!(pointer->cursor.view.screens & screen_mask(screen)))
259++		return;
260++
261++	cursor_buf = pointer->cursor.buffer;
262++	if (!wld_map(cursor_buf) || !cursor_buf->map)
263++		return;
264++
265++	dst_x = pointer->cursor.view.geometry.x - screen->base.geometry.x;
266++	dst_y = pointer->cursor.view.geometry.y - screen->base.geometry.y;
267++
268++	if (dst_x >= (int32_t)dst_width || dst_y >= (int32_t)dst_height ||
269++	    dst_x + (int32_t)cursor_buf->width <= 0 ||
270++	    dst_y + (int32_t)cursor_buf->height <= 0) {
271++		wld_unmap(cursor_buf);
272++		return;
273++	}
274++
275++	if (dst_x < 0) {
276++		src_x = -dst_x;
277++		dst_x = 0;
278++	}
279++	if (dst_y < 0) {
280++		src_y = -dst_y;
281++		dst_y = 0;
282++	}
283++
284++	copy_w = cursor_buf->width - (uint32_t)src_x;
285++	if (copy_w > dst_width - (uint32_t)dst_x)
286++		copy_w = dst_width - (uint32_t)dst_x;
287++	copy_h = cursor_buf->height - (uint32_t)src_y;
288++	if (copy_h > dst_height - (uint32_t)dst_y)
289++		copy_h = dst_height - (uint32_t)dst_y;
290++
291++	src = cursor_buf->map;
292++
293++	for (uint32_t y = 0; y < copy_h; y++) {
294++		const uint32_t *src_row = (const uint32_t *)(src + ((size_t)(src_y + (int32_t)y) * cursor_buf->pitch)) + src_x;
295++		uint32_t *dst_row = (uint32_t *)(dst + ((size_t)(dst_y + (int32_t)y) * dst_pitch)) + dst_x;
296++
297++		for (uint32_t x = 0; x < copy_w; x++) {
298++			uint32_t src_px = src_row[x];
299++			uint32_t a = src_px >> 24;
300++
301++			if (a == 0)
302++				continue;
303++			if (a == 255) {
304++				dst_row[x] = 0xFF000000 | (src_px & 0x00FFFFFF);
305++				continue;
306++			}
307++
308++			uint32_t dst_px = dst_row[x];
309++			uint32_t inv = 255 - a;
310++			uint32_t r = ((src_px >> 16) & 0xFF) + ((((dst_px >> 16) & 0xFF) * inv + 127) / 255);
311++			uint32_t g = ((src_px >> 8) & 0xFF) + ((((dst_px >> 8) & 0xFF) * inv + 127) / 255);
312++			uint32_t b = (src_px & 0xFF) + (((dst_px & 0xFF) * inv + 127) / 255);
313++
314++			dst_row[x] = 0xFF000000 | (r << 16) | (g << 8) | b;
315++		}
316++	}
317++
318++	wld_unmap(cursor_buf);
319++}
320++
321++static void
322++capture(struct wl_client *client, struct wl_resource *resource, int32_t fd)
323++{
324++	struct screen *screen;
325++	struct wld_buffer *shm_buffer;
326++	uint8_t *pixels;
327++	uint32_t width, height;
328++
329++	if (wl_list_empty(&swc.screens)) {
330++		fprintf(stderr, "snap: no screens available\n");
331++		close(fd);
332++		return;
333++	}
334++
335++	screen = wl_container_of(swc.screens.next, screen, link);
336++	width = screen->base.geometry.width;
337++	height = screen->base.geometry.height;
338++
339++	/* put compositor in shm*/
340++	shm_buffer = compositor_render_to_shm(screen);
341++	if (!shm_buffer) {
342++		fprintf(stderr, "snap: failed to render to SHM\n");
343++		close(fd);
344++		return;
345++	}
346++
347++	/* get pixel data from shm */
348++	if (!wld_map(shm_buffer) || !shm_buffer->map) {
349++		fprintf(stderr, "snap: failed to map buffer data\n");
350++		wld_buffer_unreference(shm_buffer);
351++		close(fd);
352++		return;
353++	}
354++
355++	pixels = shm_buffer->map;
356++
357++	cursor(pixels, width, height, shm_buffer->pitch, screen);
358++
359++	ppm(fd, pixels, width, height, shm_buffer->pitch);
360++
361++	wld_unmap(shm_buffer);
362++	wld_buffer_unreference(shm_buffer);
363++}
364++
365++static const struct swc_snap_interface snap_impl = {
366++	.capture = capture,
367++};
368++
369++static void
370++bind_snap(struct wl_client *client, void *data, uint32_t version, uint32_t id)
371++{
372++	struct wl_resource *resource;
373++
374++	resource = wl_resource_create(client, &swc_snap_interface, version, id);
375++	if (!resource) {
376++		wl_client_post_no_memory(client);
377++		return;
378++	}
379++	wl_resource_set_implementation(resource, &snap_impl, NULL, NULL);
380++}
381++
382++struct wl_global *
383++snap_manager_create(struct wl_display *display)
384++{
385++	return wl_global_create(display, &swc_snap_interface, 1, NULL, &bind_snap);
386++}
387+diff --git a/libswc/snap.h b/libswc/snap.h
388+new file mode 100644
389+index 0000000..62c6fe5
390+--- /dev/null
391++++ b/libswc/snap.h
392+@@ -0,0 +1,9 @@
393++#ifndef SWC_SNAP_H
394++#define SWC_SNAP_H
395++
396++struct wl_display;
397++struct wl_global;
398++
399++struct wl_global *snap_manager_create(struct wl_display *display);
400++
401++#endif
402+diff --git a/libswc/swc.c b/libswc/swc.c
403+index cf82913..6d3f871 100644
404+--- a/libswc/swc.c
405++++ b/libswc/swc.c
406+@@ -37,6 +37,7 @@
407+ #include "seat.h"
408+ #include "shell.h"
409+ #include "shm.h"
410++#include "snap.h"
411+ #include "subcompositor.h"
412+ #include "util.h"
413+ #include "window.h"
414+@@ -215,10 +216,16 @@ swc_initialize(struct wl_display *display, struct wl_event_loop *event_loop, con
415+ 		goto error13;
416+ 	}
417+ 
418++	swc.snap_manager = snap_manager_create(display);
419++	if (!swc.snap_manager) {
420++		ERROR("Could not initialize snap manager\n");
421++		goto error14;
422++	}
423++
424+ #ifdef ENABLE_XWAYLAND
425+ 	if (!xserver_initialize()) {
426+ 		ERROR("Could not initialize xwayland\n");
427+-		goto error14;
428++		goto error15;
429+ 	}
430+ #endif
431+ 
432+@@ -227,9 +234,11 @@ swc_initialize(struct wl_display *display, struct wl_event_loop *event_loop, con
433+ 	return true;
434+ 
435+ #ifdef ENABLE_XWAYLAND
436++error15:
437++	wl_global_destroy(swc.snap_manager);
438++#endif
439+ error14:
440+ 	wl_global_destroy(swc.panel_manager);
441+-#endif
442+ error13:
443+ 	wl_global_destroy(swc.kde_decoration_manager);
444+ error12:
445+@@ -266,6 +275,7 @@ swc_finalize(void)
446+ #ifdef ENABLE_XWAYLAND
447+ 	xserver_finalize();
448+ #endif
449++	wl_global_destroy(swc.snap_manager);
450+ 	wl_global_destroy(swc.panel_manager);
451+ 	wl_global_destroy(swc.xdg_decoration_manager);
452+ 	wl_global_destroy(swc.xdg_shell);
453+diff --git a/protocol/swc_snap.xml b/protocol/swc_snap.xml
454+new file mode 100644
455+index 0000000..e8d8622
456+--- /dev/null
457++++ b/protocol/swc_snap.xml
458+@@ -0,0 +1,15 @@
459++<?xml version="1.0" encoding="UTF-8"?>
460++<protocol name="swc_snap">
461++    <interface name="swc_snap" version="1">
462++        <description summary="simple screenshot to file descriptor">
463++            provides a minimal screenshot capability.
464++        </description>
465++
466++        <request name="capture">
467++            <description summary="capture screenshot to fd">
468++                captures the current screen and writes it as ppm formay
469++            </description>
470++            <arg name="fd" type="fd" summary="file descriptor to write ppm data"/>
471++        </request>
472++    </interface>
473++</protocol>
474+-- 
475+2.49.0
476+
R pkg/swc/patch/0010-swc_window_get_pid-add-api-to-query-a-window-s-clien.patch => pkg/swc/patch/0011-swc_window_get_pid-add-api-to-query-a-window-s-clien.patch
+5, -5
 1@@ -1,4 +1,4 @@
 2-From d7cc5eb216965f3a9ed14542d25f557aab6042d1 Mon Sep 17 00:00:00 2001
 3+From ebae7966352bca2ad16f0ca6a1df988b61b1a198 Mon Sep 17 00:00:00 2001
 4 From: shrub <maybeshrub@gmail.com>
 5 Date: Sat, 10 Jan 2026 00:20:19 +0000
 6 Subject: [PATCH] swc_window_get_pid add api to query a window's client pid
 7@@ -9,7 +9,7 @@ Subject: [PATCH] swc_window_get_pid add api to query a window's client pid
 8  2 files changed, 33 insertions(+)
 9 
10 diff --git a/libswc/swc.h b/libswc/swc.h
11-index 29638d9..f3bd453 100644
12+index bbade8f..5d0d9a0 100644
13 --- a/libswc/swc.h
14 +++ b/libswc/swc.h
15 @@ -26,6 +26,7 @@
16@@ -20,7 +20,7 @@ index 29638d9..f3bd453 100644
17  
18  #ifdef __cplusplus
19  extern "C" {
20-@@ -325,6 +326,13 @@ void swc_window_set_geometry(struct swc_window *window, const struct swc_rectang
21+@@ -320,6 +321,13 @@ void swc_window_set_geometry(struct swc_window *window, const struct swc_rectang
22   */
23  bool swc_window_get_geometry(const struct swc_window *window, struct swc_rectangle *geometry);
24  
25@@ -35,7 +35,7 @@ index 29638d9..f3bd453 100644
26   * Set the window's border color and width.
27   *
28 diff --git a/libswc/window.c b/libswc/window.c
29-index 60432ae..3e3a714 100644
30+index b1fdeb9..f46793d 100644
31 --- a/libswc/window.c
32 +++ b/libswc/window.c
33 @@ -27,12 +27,14 @@
34@@ -53,7 +53,7 @@ index 60432ae..3e3a714 100644
35  
36  #define INTERNAL(w) ((struct window *)(w))
37  
38-@@ -583,3 +585,26 @@ window_begin_resize(struct window *window, uint32_t edges, struct button *button
39+@@ -519,3 +521,26 @@ window_begin_resize(struct window *window, uint32_t edges, struct button *button
40  	window->resize.offset.y = geometry->y - py + ((edges & SWC_WINDOW_EDGE_BOTTOM) ? geometry->height : 0);
41  	window->resize.edges = edges;
42  }
R pkg/swc/patch/0011-zoom-swc_set_zoom-and-get_zoom-api-added-zoom-does-a.patch => pkg/swc/patch/0012-zoom-swc_set_zoom-and-get_zoom-api-added-zoom-does-a.patch
+8, -8
 1@@ -1,4 +1,4 @@
 2-From 6d3e048dfc11209f32891ef9fc39586b83eff974 Mon Sep 17 00:00:00 2001
 3+From 840a07ecb240c2944f359cbde277c10ab65aa135 Mon Sep 17 00:00:00 2001
 4 From: shrub <maybeshrub@gmail.com>
 5 Date: Tue, 20 Jan 2026 22:31:55 +0000
 6 Subject: [PATCH] zoom! swc_set_zoom and get_zoom api added zoom does a
 7@@ -10,7 +10,7 @@ Subject: [PATCH] zoom! swc_set_zoom and get_zoom api added zoom does a
 8  2 files changed, 254 insertions(+), 8 deletions(-)
 9 
10 diff --git a/libswc/compositor.c b/libswc/compositor.c
11-index 263da39..0f978d9 100644
12+index 0bf3210..c8786b5 100644
13 --- a/libswc/compositor.c
14 +++ b/libswc/compositor.c
15 @@ -108,6 +108,10 @@ static struct {
16@@ -24,7 +24,7 @@ index 263da39..0f978d9 100644
17  } compositor;
18  
19  static struct {
20-@@ -452,6 +456,17 @@ schedule_updates(uint32_t screens)
21+@@ -456,6 +460,17 @@ schedule_updates(uint32_t screens)
22  			screens |= screen_mask(screen);
23  	}
24  
25@@ -42,7 +42,7 @@ index 263da39..0f978d9 100644
26  	compositor.scheduled_updates |= screens;
27  }
28  
29-@@ -499,6 +514,202 @@ swc_overlay_clear(void)
30+@@ -503,6 +518,202 @@ swc_overlay_clear(void)
31  	schedule_updates(-1);
32  }
33  
34@@ -245,7 +245,7 @@ index 263da39..0f978d9 100644
35  static bool
36  update(struct view *base)
37  {
38-@@ -992,14 +1203,32 @@ update_screen(struct screen *screen)
39+@@ -996,14 +1207,32 @@ update_screen(struct screen *screen)
40  		return;
41  	}
42  
43@@ -286,7 +286,7 @@ index 263da39..0f978d9 100644
44  
45  	switch (target_swap_buffers(target)) {
46  	case -EACCES:
47-@@ -1158,6 +1387,8 @@ compositor_initialize(void)
48+@@ -1162,6 +1391,8 @@ compositor_initialize(void)
49  	compositor.scheduled_updates = 0;
50  	compositor.pending_flips = 0;
51  	compositor.updating = false;
52@@ -295,7 +295,7 @@ index 263da39..0f978d9 100644
53  	pixman_region32_init(&compositor.damage);
54  	pixman_region32_init(&compositor.opaque);
55  	wl_list_init(&compositor.views);
56-@@ -1181,6 +1412,8 @@ compositor_initialize(void)
57+@@ -1185,6 +1416,8 @@ compositor_initialize(void)
58  void
59  compositor_finalize(void)
60  {
61@@ -305,7 +305,7 @@ index 263da39..0f978d9 100644
62  	pixman_region32_fini(&compositor.opaque);
63  	wl_global_destroy(compositor.global);
64 diff --git a/libswc/swc.h b/libswc/swc.h
65-index f3bd453..505391d 100644
66+index 5d0d9a0..b95fc4c 100644
67 --- a/libswc/swc.h
68 +++ b/libswc/swc.h
69 @@ -121,6 +121,19 @@ void swc_overlay_set_box(int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint32_
R pkg/swc/patch/0012-add-fullscreen-support.patch => pkg/swc/patch/0013-add-fullscreen-support.patch
+4, -4
 1@@ -1,4 +1,4 @@
 2-From 3a2c4c613b15106497ea464b2ee613a30ca2f112 Mon Sep 17 00:00:00 2001
 3+From 52e195daf74388d29d3b20d1ffd9ca3ffbfe929f Mon Sep 17 00:00:00 2001
 4 From: dalem <lain@dalem.foo>
 5 Date: Tue, 27 Jan 2026 17:36:27 +0100
 6 Subject: [PATCH] add fullscreen support
 7@@ -9,10 +9,10 @@ Subject: [PATCH] add fullscreen support
 8  2 files changed, 21 insertions(+), 5 deletions(-)
 9 
10 diff --git a/libswc/window.c b/libswc/window.c
11-index 3e3a714..6322502 100644
12+index f46793d..84e97b0 100644
13 --- a/libswc/window.c
14 +++ b/libswc/window.c
15-@@ -239,12 +239,23 @@ EXPORT void
16+@@ -194,12 +194,23 @@ EXPORT void
17  swc_window_set_fullscreen(struct swc_window *base, struct swc_screen *screen)
18  {
19  	struct window *window = INTERNAL(base);
20@@ -42,7 +42,7 @@ index 3e3a714..6322502 100644
21  
22  EXPORT void
23 diff --git a/libswc/window.h b/libswc/window.h
24-index d6684a8..71a597f 100644
25+index 08c9d36..d8f6bfa 100644
26 --- a/libswc/window.h
27 +++ b/libswc/window.h
28 @@ -52,6 +52,11 @@ struct window {
R pkg/swc/patch/0016-initial-subsurface-implementation-add-basic-wl_subsu.patch => pkg/swc/patch/0014-initial-subsurface-implementation-add-basic-wl_subsu.patch
+6, -6
 1@@ -1,4 +1,4 @@
 2-From c04d6b835bc440cb56babfc63e45c705c1723820 Mon Sep 17 00:00:00 2001
 3+From 53714281024d80814f9884a01ba232cf0342e15b Mon Sep 17 00:00:00 2001
 4 From: shrub <maybeshrub@gmail.com>
 5 Date: Sat, 31 Jan 2026 21:34:22 +0000
 6 Subject: [PATCH] initial subsurface implementation add basic wl_subsurface
 7@@ -19,7 +19,7 @@ Subject: [PATCH] initial subsurface implementation add basic wl_subsurface
 8  9 files changed, 346 insertions(+), 21 deletions(-)
 9 
10 diff --git a/libswc/compositor.c b/libswc/compositor.c
11-index d70377d..d2321b9 100644
12+index c8786b5..477af8b 100644
13 --- a/libswc/compositor.c
14 +++ b/libswc/compositor.c
15 @@ -219,11 +219,18 @@ repaint_view(struct target *target, struct compositor_view *view, pixman_region3
16@@ -189,10 +189,10 @@ index d70377d..d2321b9 100644
17  	pixman_region32_fini(&surface_opaque);
18  }
19 diff --git a/libswc/compositor.h b/libswc/compositor.h
20-index 9046f0b..e079d92 100644
21+index 2e70b38..1d6b9e2 100644
22 --- a/libswc/compositor.h
23 +++ b/libswc/compositor.h
24-@@ -52,6 +52,8 @@ struct compositor_view {
25+@@ -55,6 +55,8 @@ struct compositor_view {
26  	struct wld_buffer *buffer;
27  	struct window *window;
28  	struct compositor_view *parent;
29@@ -623,10 +623,10 @@ index 039ed4c..5eb751c 100644
30  
31  struct surface *surface_new(struct wl_client *client, uint32_t version, uint32_t id);
32 diff --git a/libswc/window.c b/libswc/window.c
33-index 6322502..728243d 100644
34+index 84e97b0..d539d3c 100644
35 --- a/libswc/window.c
36 +++ b/libswc/window.c
37-@@ -450,8 +450,14 @@ window_initialize(struct window *window, const struct window_impl *impl, struct
38+@@ -395,8 +395,14 @@ window_initialize(struct window *window, const struct window_impl *impl, struct
39  	window->base.app_id = NULL;
40  	window->base.parent = NULL;
41  
+3, -3
 1@@ -1,4 +1,4 @@
 2-From 108719f480ad292252721ac3c90b75081e1152e5 Mon Sep 17 00:00:00 2001
 3+From d783f4c858eb415946abc02fbacf5632d2eb2aab Mon Sep 17 00:00:00 2001
 4 From: dalem <lain@dalem.foo>
 5 Date: Sun, 8 Feb 2026 03:33:43 +0100
 6 Subject: [PATCH] Rename swc_wallpaper_init to swc_wallpaper_set
 7@@ -10,10 +10,10 @@ this change makes it appear as more consistent
 8  2 files changed, 3 insertions(+), 3 deletions(-)
 9 
10 diff --git a/libswc/swc.h b/libswc/swc.h
11-index a23e556..033bdd4 100644
12+index b95fc4c..1f4ada4 100644
13 --- a/libswc/swc.h
14 +++ b/libswc/swc.h
15-@@ -443,10 +443,10 @@ extern struct wld_buffer *wallbuf;
16+@@ -438,10 +438,10 @@ extern struct wld_buffer *wallbuf;
17  
18  /**
19   * Set wallpaper to image from fs path.
R pkg/swc/patch/0017-fix-subsurfaces-so-they-can-actually-work-fix-subsur.patch => pkg/swc/patch/0016-fix-subsurfaces-so-they-can-actually-work-fix-subsur.patch
+4, -4
 1@@ -1,4 +1,4 @@
 2-From 13a2200f15510e837ce2631592856f4f0a0ede2b Mon Sep 17 00:00:00 2001
 3+From 78df047f81cf877eab899fe44b3f350f13015703 Mon Sep 17 00:00:00 2001
 4 From: shrub <maybeshrub@gmail.com>
 5 Date: Tue, 10 Feb 2026 21:34:58 +0000
 6 Subject: [PATCH] fix subsurfaces, so they can actually work fix subsurface
 7@@ -18,7 +18,7 @@ Subject: [PATCH] fix subsurfaces, so they can actually work fix subsurface
 8  8 files changed, 383 insertions(+), 80 deletions(-)
 9 
10 diff --git a/libswc/compositor.c b/libswc/compositor.c
11-index d2321b9..4875af8 100644
12+index 477af8b..4333d99 100644
13 --- a/libswc/compositor.c
14 +++ b/libswc/compositor.c
15 @@ -41,6 +41,7 @@
16@@ -309,10 +309,10 @@ index d2321b9..4875af8 100644
17  
18  	pixman_region32_fini(&surface_opaque);
19 diff --git a/libswc/compositor.h b/libswc/compositor.h
20-index e079d92..529c360 100644
21+index 1d6b9e2..94de9e3 100644
22 --- a/libswc/compositor.h
23 +++ b/libswc/compositor.h
24-@@ -92,6 +92,7 @@ void compositor_view_destroy(struct compositor_view *view);
25+@@ -95,6 +95,7 @@ void compositor_view_destroy(struct compositor_view *view);
26  struct compositor_view *compositor_view(struct view *view);
27  
28  void compositor_view_set_parent(struct compositor_view *view, struct compositor_view *parent);
R pkg/swc/patch/0007-add-motion-throttle.patch => pkg/swc/patch/0017-add-motion-throttle.patch
+14, -14
  1@@ -1,4 +1,4 @@
  2-From 6c4cfa23f28c67ae588423bdb2f3842848972ac7 Mon Sep 17 00:00:00 2001
  3+From ed94892107d6a6a84c4c68910c702708f18508a6 Mon Sep 17 00:00:00 2001
  4 From: uint <abhinav.prsai@gmail.com>
  5 Date: Sun, 15 Feb 2026 12:40:13 +0000
  6 Subject: [PATCH] add motion throttle
  7@@ -13,10 +13,10 @@ def_motion_throttle_ms=60 and should even fix some
  8  3 files changed, 30 insertions(+)
  9 
 10 diff --git a/libswc/swc.h b/libswc/swc.h
 11-index 2aa06c8..3776929 100644
 12+index 1f4ada4..058ff2c 100644
 13 --- a/libswc/swc.h
 14 +++ b/libswc/swc.h
 15-@@ -192,6 +192,7 @@ struct swc_window {
 16+@@ -249,6 +249,7 @@ struct swc_window {
 17  	char *app_id;
 18  
 19  	struct swc_window *parent;
 20@@ -25,10 +25,10 @@ index 2aa06c8..3776929 100644
 21  
 22  /**
 23 diff --git a/libswc/window.c b/libswc/window.c
 24-index b1fdeb9..bfbbbbd 100644
 25+index d539d3c..1e9ee2b 100644
 26 --- a/libswc/window.c
 27 +++ b/libswc/window.c
 28-@@ -36,8 +36,23 @@
 29+@@ -38,8 +38,23 @@
 30  
 31  #define INTERNAL(w) ((struct window *)(w))
 32  
 33@@ -52,7 +52,7 @@ index b1fdeb9..bfbbbbd 100644
 34  static void
 35  handle_window_enter(struct wl_listener *listener, void *data)
 36  {
 37-@@ -299,6 +314,10 @@ static bool
 38+@@ -312,6 +327,10 @@ static bool
 39  move_motion(struct pointer_handler *handler, uint32_t time, wl_fixed_t fx, wl_fixed_t fy)
 40  {
 41  	struct window *window = wl_container_of(handler, window, move.interaction.handler);
 42@@ -63,7 +63,7 @@ index b1fdeb9..bfbbbbd 100644
 43  	int32_t x = wl_fixed_to_int(fx) + window->move.offset.x,
 44  	        y = wl_fixed_to_int(fy) + window->move.offset.y;
 45  
 46-@@ -313,6 +332,9 @@ resize_motion(struct pointer_handler *handler, uint32_t time, wl_fixed_t fx, wl_
 47+@@ -326,6 +345,9 @@ resize_motion(struct pointer_handler *handler, uint32_t time, wl_fixed_t fx, wl_
 48  	const struct swc_rectangle *geometry = &window->view->base.geometry;
 49  	uint32_t width = geometry->width, height = geometry->height;
 50  
 51@@ -73,7 +73,7 @@ index b1fdeb9..bfbbbbd 100644
 52  	if (window->resize.edges & SWC_WINDOW_EDGE_LEFT)
 53  		width -= wl_fixed_to_int(fx) + window->resize.offset.x - geometry->x;
 54  	else if (window->resize.edges & SWC_WINDOW_EDGE_RIGHT)
 55-@@ -389,9 +411,11 @@ window_initialize(struct window *window, const struct window_impl *impl, struct
 56+@@ -408,9 +430,11 @@ window_initialize(struct window *window, const struct window_impl *impl, struct
 57  	window->handler = &null_handler;
 58  	window->view_handler.impl = &view_handler_impl;
 59  	window->view->window = window;
 60@@ -85,7 +85,7 @@ index b1fdeb9..bfbbbbd 100644
 61  	window->move.interaction.active = false;
 62  	window->move.interaction.handler = (struct pointer_handler){
 63  		.motion = move_motion,
 64-@@ -405,6 +429,7 @@ window_initialize(struct window *window, const struct window_impl *impl, struct
 65+@@ -424,6 +448,7 @@ window_initialize(struct window *window, const struct window_impl *impl, struct
 66  		.motion = resize_motion,
 67  		.button = handle_button,
 68  	};
 69@@ -93,7 +93,7 @@ index b1fdeb9..bfbbbbd 100644
 70  
 71  	wl_list_insert(&window->view->base.handlers, &window->view_handler.link);
 72  
 73-@@ -491,6 +516,7 @@ window_begin_move(struct window *window, struct button *button)
 74+@@ -510,6 +535,7 @@ window_begin_move(struct window *window, struct button *button)
 75  	        py = wl_fixed_to_int(swc.seat->pointer->y);
 76  
 77  	begin_interaction(&window->move.interaction, button);
 78@@ -101,7 +101,7 @@ index b1fdeb9..bfbbbbd 100644
 79  	window->move.offset.x = geometry->x - px;
 80  	window->move.offset.y = geometry->y - py;
 81  }
 82-@@ -509,6 +535,7 @@ window_begin_resize(struct window *window, uint32_t edges, struct button *button
 83+@@ -528,6 +554,7 @@ window_begin_resize(struct window *window, uint32_t edges, struct button *button
 84  	        py = wl_fixed_to_int(swc.seat->pointer->y);
 85  
 86  	begin_interaction(&window->resize.interaction, button);
 87@@ -110,10 +110,10 @@ index b1fdeb9..bfbbbbd 100644
 88  	if (!edges) {
 89  		edges |= (px < geometry->x + geometry->width / 2) ? SWC_WINDOW_EDGE_LEFT : SWC_WINDOW_EDGE_RIGHT;
 90 diff --git a/libswc/window.h b/libswc/window.h
 91-index 08c9d36..d6684a8 100644
 92+index d8f6bfa..71a597f 100644
 93 --- a/libswc/window.h
 94 +++ b/libswc/window.h
 95-@@ -61,6 +61,7 @@ struct window {
 96+@@ -66,6 +66,7 @@ struct window {
 97  
 98  		bool pending;
 99  		int32_t x, y;
100@@ -121,7 +121,7 @@ index 08c9d36..d6684a8 100644
101  	} move;
102  
103  	struct {
104-@@ -69,6 +70,7 @@ struct window {
105+@@ -74,6 +75,7 @@ struct window {
106  			int32_t x, y;
107  		} offset;
108  		uint32_t edges;
R pkg/swc/patch/0008-add-min-max-window-width-height.patch => pkg/swc/patch/0018-add-min-max-window-width-height.patch
+8, -8
 1@@ -1,4 +1,4 @@
 2-From af4e4ebba3d7fd5840c200c26e339246242bbee7 Mon Sep 17 00:00:00 2001
 3+From a86a27f5fac950e085a5069f72d4737f26ded3ba Mon Sep 17 00:00:00 2001
 4 From: uint <abhinav.prsai@gmail.com>
 5 Date: Sun, 15 Feb 2026 14:24:18 +0000
 6 Subject: [PATCH] add min/max window width/height
 7@@ -11,10 +11,10 @@ fixes swc wm dying if resize value is too large
 8  2 files changed, 41 insertions(+)
 9 
10 diff --git a/libswc/swc.h b/libswc/swc.h
11-index 3776929..dde7ef0 100644
12+index 058ff2c..033bdd4 100644
13 --- a/libswc/swc.h
14 +++ b/libswc/swc.h
15-@@ -193,6 +193,10 @@ struct swc_window {
16+@@ -250,6 +250,10 @@ struct swc_window {
17  
18  	struct swc_window *parent;
19  	uint32_t motion_throttle_ms;
20@@ -26,10 +26,10 @@ index 3776929..dde7ef0 100644
21  
22  /**
23 diff --git a/libswc/window.c b/libswc/window.c
24-index bfbbbbd..60432ae 100644
25+index 1e9ee2b..728243d 100644
26 --- a/libswc/window.c
27 +++ b/libswc/window.c
28-@@ -53,6 +53,36 @@ should_throttle_motion(uint32_t throttle_ms, uint32_t *last_time, uint32_t time)
29+@@ -55,6 +55,36 @@ should_throttle_motion(uint32_t throttle_ms, uint32_t *last_time, uint32_t time)
30  	return false;
31  }
32  
33@@ -66,7 +66,7 @@ index bfbbbbd..60432ae 100644
34  static void
35  handle_window_enter(struct wl_listener *listener, void *data)
36  {
37-@@ -241,6 +271,8 @@ swc_window_set_size(struct swc_window *base, uint32_t width, uint32_t height)
38+@@ -254,6 +284,8 @@ swc_window_set_size(struct swc_window *base, uint32_t width, uint32_t height)
39  	struct window *window = INTERNAL(base);
40  	struct swc_rectangle *geom = &window->view->base.geometry;
41  
42@@ -75,7 +75,7 @@ index bfbbbbd..60432ae 100644
43  	if ((window->configure.pending && width == window->configure.width && height == window->configure.height)
44  	 || (!window->configure.pending && width == geom->width && height == geom->height))
45  	{
46-@@ -345,6 +377,7 @@ resize_motion(struct pointer_handler *handler, uint32_t time, wl_fixed_t fx, wl_
47+@@ -358,6 +390,7 @@ resize_motion(struct pointer_handler *handler, uint32_t time, wl_fixed_t fx, wl_
48  	else if (window->resize.edges & SWC_WINDOW_EDGE_BOTTOM)
49  		height = wl_fixed_to_int(fy) + window->resize.offset.y - geometry->y;
50  
51@@ -83,7 +83,7 @@ index bfbbbbd..60432ae 100644
52  	window->impl->configure(window, width, height);
53  
54  	return true;
55-@@ -412,6 +445,10 @@ window_initialize(struct window *window, const struct window_impl *impl, struct
56+@@ -431,6 +464,10 @@ window_initialize(struct window *window, const struct window_impl *impl, struct
57  	window->view_handler.impl = &view_handler_impl;
58  	window->view->window = window;
59  	window->base.motion_throttle_ms = def_motion_throttle_ms;
R pkg/swc/patch/0018-add-wallpaper-protocol-with-separate-screen-buffers-.patch => pkg/swc/patch/0019-add-wallpaper-protocol-with-separate-screen-buffers-.patch
+75, -13
  1@@ -1,23 +1,26 @@
  2-From 40e72dcbb90be5d92615aea647810a56dd0c878a Mon Sep 17 00:00:00 2001
  3+From f9d37ac047966356dbe1bde645e6729c7d8c3d48 Mon Sep 17 00:00:00 2001
  4 From: uint <abhinav.prsai@gmail.com>
  5 Date: Wed, 18 Feb 2026 06:07:03 +0000
  6 Subject: [PATCH] add wallpaper protocol with separate screen buffers support
  7 
  8+add wallpaper protocol
  9+> swc just uses a buffer, processing is done on client
 10+removed STB
 11 ---
 12- libswc/compositor.c        |  39 ++++++++--
 13+ libswc/compositor.c        |  45 ++++++++++--
 14  libswc/compositor.h        |   1 +
 15  libswc/internal.h          |   1 +
 16- libswc/swc.c               |   1 +
 17+ libswc/swc.c               |  14 +++-
 18  libswc/swc.h               |  17 +++--
 19  libswc/wallpaper.c         | 147 +++++++++++++++++++++++--------------
 20  libswc/wallpaper.h         |  12 +++
 21  protocol/swc_wallpaper.xml |  19 +++++
 22- 8 files changed, 170 insertions(+), 67 deletions(-)
 23+ 8 files changed, 185 insertions(+), 71 deletions(-)
 24  create mode 100644 libswc/wallpaper.h
 25  create mode 100644 protocol/swc_wallpaper.xml
 26 
 27 diff --git a/libswc/compositor.c b/libswc/compositor.c
 28-index 4875af8..cb7863b 100644
 29+index 4333d99..fd52973 100644
 30 --- a/libswc/compositor.c
 31 +++ b/libswc/compositor.c
 32 @@ -44,6 +44,7 @@
 33@@ -130,11 +133,31 @@ index 4875af8..cb7863b 100644
 34  	if (compositor.zoom_buffer)
 35  		wld_buffer_unreference(compositor.zoom_buffer);
 36  	pixman_region32_fini(&compositor.damage);
 37+@@ -1539,6 +1566,7 @@ compositor_render_to_shm(struct screen *screen)
 38+ 	pixman_region32_t region;
 39+ 	pixman_region32_t damage;
 40+ 	uint32_t caps;
 41++	struct wld_buffer *background;
 42+ 
 43+ 	/* create shm buf */
 44+ 	buffer = wld_create_buffer(swc.shm->context, width, height,
 45+@@ -1558,8 +1586,9 @@ compositor_render_to_shm(struct screen *screen)
 46+ 	pixman_region32_init_rect(&damage, screen->base.geometry.x, screen->base.geometry.y, width, height);
 47+ 
 48+ 	/* background */
 49+-	if (wallbuf)
 50+-		wld_copy_region(swc.shm->renderer, wallbuf, 0, 0, &region);
 51++	background = swc_wallpaper_buffer_for_screen(screen);
 52++	if (background)
 53++		wld_copy_region(swc.shm->renderer, background, 0, 0, &region);
 54+ 	else
 55+ 		wld_fill_region(swc.shm->renderer, bgcolor, &region);
 56+ 
 57 diff --git a/libswc/compositor.h b/libswc/compositor.h
 58-index 529c360..6c938ac 100644
 59+index 94de9e3..a404534 100644
 60 --- a/libswc/compositor.h
 61 +++ b/libswc/compositor.h
 62-@@ -45,6 +45,7 @@ struct swc_compositor {
 63+@@ -48,6 +48,7 @@ struct swc_compositor {
 64  
 65  bool compositor_initialize(void);
 66  void compositor_finalize(void);
 67@@ -143,29 +166,68 @@ index 529c360..6c938ac 100644
 68  struct compositor_view {
 69  	struct view base;
 70 diff --git a/libswc/internal.h b/libswc/internal.h
 71-index 8efba6d..6d2b0a1 100644
 72+index 243b75f..a238a3d 100644
 73 --- a/libswc/internal.h
 74 +++ b/libswc/internal.h
 75-@@ -50,6 +50,7 @@ struct swc {
 76- 	struct wl_global *panel_manager;
 77+@@ -51,6 +51,7 @@ struct swc {
 78  	struct wl_global *shell;
 79+ 	struct wl_global *snap_manager;
 80  	struct wl_global *subcompositor;
 81 +	struct wl_global *wallpaper_manager;
 82  	struct wl_global *xdg_decoration_manager;
 83  	struct wl_global *xdg_shell;
 84  
 85 diff --git a/libswc/swc.c b/libswc/swc.c
 86-index 8814c13..1035ef3 100644
 87+index 6d3f871..6647c65 100644
 88 --- a/libswc/swc.c
 89 +++ b/libswc/swc.c
 90-@@ -39,6 +39,7 @@
 91- #include "shm.h"
 92+@@ -40,6 +40,7 @@
 93+ #include "snap.h"
 94  #include "subcompositor.h"
 95  #include "util.h"
 96 +#include "wallpaper.h"
 97  #include "window.h"
 98  #include "xdg_decoration.h"
 99  #include "xdg_shell.h"
100+@@ -222,10 +223,16 @@ swc_initialize(struct wl_display *display, struct wl_event_loop *event_loop, con
101+ 		goto error14;
102+ 	}
103+ 
104++	swc.wallpaper_manager = swc_wallpaper_manager_create(display);
105++	if (!swc.wallpaper_manager) {
106++		ERROR("Could not initialize wallpaper manager\n");
107++		goto error15;
108++	}
109++
110+ #ifdef ENABLE_XWAYLAND
111+ 	if (!xserver_initialize()) {
112+ 		ERROR("Could not initialize xwayland\n");
113+-		goto error15;
114++		goto error16;
115+ 	}
116+ #endif
117+ 
118+@@ -234,9 +241,11 @@ swc_initialize(struct wl_display *display, struct wl_event_loop *event_loop, con
119+ 	return true;
120+ 
121+ #ifdef ENABLE_XWAYLAND
122++error16:
123++	wl_global_destroy(swc.wallpaper_manager);
124++#endif
125+ error15:
126+ 	wl_global_destroy(swc.snap_manager);
127+-#endif
128+ error14:
129+ 	wl_global_destroy(swc.panel_manager);
130+ error13:
131+@@ -275,6 +284,7 @@ swc_finalize(void)
132+ #ifdef ENABLE_XWAYLAND
133+ 	xserver_finalize();
134+ #endif
135++	wl_global_destroy(swc.wallpaper_manager);
136+ 	wl_global_destroy(swc.snap_manager);
137+ 	wl_global_destroy(swc.panel_manager);
138+ 	wl_global_destroy(swc.xdg_decoration_manager);
139 diff --git a/libswc/swc.h b/libswc/swc.h
140 index 033bdd4..f2a8ae1 100644
141 --- a/libswc/swc.h
+1, -1
1@@ -1 +1 @@
2-9a20014 r3
3+9a20014 r4