commit a96a4eb
uint
·
2026-02-18 06:07:03 +0000 UTC
parent 76db202
add wallpaper protocol with separate screen buffers support add wallpaper protocol > swc just uses a buffer, processing is done on client removed STB
11 files changed,
+197,
-71
M
Makefile
+7,
-0
1@@ -97,6 +97,7 @@ PROTO_EXTENSIONS= \
2 protocol/server-decoration.xml \
3 protocol/swc.xml \
4 protocol/swc_snap.xml \
5+ protocol/swc_wallpaper.xml \
6 protocol/wayland-drm.xml \
7 ${WAYLAND_PROTOCOLS_DATADIR}/stable/xdg-shell/xdg-shell.xml \
8 ${WAYLAND_PROTOCOLS_DATADIR}/unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml \
9@@ -124,6 +125,7 @@ PROTO_GEN_C= \
10 protocol/server-decoration-protocol.c \
11 protocol/swc-protocol.c \
12 protocol/swc_snap-protocol.c \
13+ protocol/swc_wallpaper-protocol.c \
14 protocol/wayland-drm-protocol.c \
15 protocol/xdg-decoration-unstable-v1-protocol.c \
16 protocol/xdg-shell-protocol.c
17@@ -137,6 +139,8 @@ PROTO_GEN_H= \
18 protocol/swc-client-protocol.h \
19 protocol/swc_snap-server-protocol.h \
20 protocol/swc_snap-client-protocol.h \
21+ protocol/swc_wallpaper-server-protocol.h \
22+ protocol/swc_wallpaper-client-protocol.h \
23 protocol/wayland-drm-server-protocol.h \
24 protocol/wayland-drm-client-protocol.h \
25 protocol/xdg-decoration-unstable-v1-server-protocol.h \
26@@ -213,6 +217,7 @@ SWC_SOURCES= \
27 protocol/server-decoration-protocol.c \
28 protocol/swc-protocol.c \
29 protocol/swc_snap-protocol.c \
30+ protocol/swc_wallpaper-protocol.c \
31 protocol/wayland-drm-protocol.c \
32 protocol/xdg-decoration-unstable-v1-protocol.c \
33 protocol/xdg-shell-protocol.c
34@@ -275,11 +280,13 @@ install: build
35 install -d ${DESTDIR}${BINDIR}
36 install -d ${DESTDIR}${LIBDIR}
37 install -d ${DESTDIR}${INCLUDEDIR}
38+ install -d ${DESTDIR}${DATADIR}/swc
39 install -d ${DESTDIR}${PKGCONFIGDIR}
40 install -m 4755 launch/swc-launch ${DESTDIR}${BINDIR}/
41 install -m 644 libswc/libswc.a ${DESTDIR}${LIBDIR}/
42 install -m 644 libswc/swc.h ${DESTDIR}${INCLUDEDIR}/
43 install -m 644 ${PROTO_GEN_H} ${DESTDIR}${INCLUDEDIR}/
44+ install -m 644 protocol/swc.xml protocol/swc_snap.xml protocol/swc_wallpaper.xml ${DESTDIR}${DATADIR}/swc/
45 install -m 644 swc.pc ${DESTDIR}${PKGCONFIGDIR}/
46
47 clean:
+37,
-8
1@@ -44,6 +44,7 @@
2 #include "subsurface.h"
3 #include "util.h"
4 #include "view.h"
5+#include "wallpaper.h"
6 #include "window.h"
7
8 #include <errno.h>
9@@ -109,6 +110,7 @@ static struct {
10
11 bool updating;
12 struct wl_global *global;
13+ bool initialized;
14
15 /* zoom level (1.0 = normal, >1 = zoomed in, <1 = zoomed out) */
16 float zoom;
17@@ -302,7 +304,7 @@ repaint_view(struct target *target, struct compositor_view *view, pixman_region3
18 }
19
20 static void
21-renderer_repaint(struct target *target, pixman_region32_t *damage, pixman_region32_t *base_damage, struct wl_list *views)
22+renderer_repaint(struct target *target, pixman_region32_t *damage, pixman_region32_t *base_damage, struct wl_list *views, struct screen *screen)
23 {
24 struct compositor_view *view;
25 const struct swc_rectangle *target_geom = &target->view->geometry;
26@@ -314,10 +316,12 @@ renderer_repaint(struct target *target, pixman_region32_t *damage, pixman_region
27 wld_set_target_surface(swc.drm->renderer, target->surface);
28
29 if (pixman_region32_not_empty(base_damage)) {
30+ struct wld_buffer *background = swc_wallpaper_buffer_for_screen(screen);
31+
32 pixman_region32_translate(base_damage, -target->view->geometry.x, -target->view->geometry.y);
33
34- if(wallbuf)
35- wld_copy_region(swc.drm->renderer, wallbuf, 0, 0, base_damage);
36+ if (background)
37+ wld_copy_region(swc.drm->renderer, background, 0, 0, base_damage);
38
39 else
40 wld_fill_region(swc.drm->renderer, bgcolor, base_damage);
41@@ -508,6 +512,23 @@ schedule_updates(uint32_t screens)
42 compositor.scheduled_updates |= screens;
43 }
44
45+void
46+compositor_damage_all(void)
47+{
48+ struct screen *screen;
49+
50+ if (!compositor.initialized)
51+ return;
52+
53+ wl_list_for_each (screen, &swc.screens, link) {
54+ pixman_region32_union_rect(&compositor.damage, &compositor.damage,
55+ screen->base.geometry.x, screen->base.geometry.y,
56+ screen->base.geometry.width, screen->base.geometry.height);
57+ }
58+
59+ schedule_updates(-1);
60+}
61+
62 static void
63 overlay_damage_region(int32_t x, int32_t y, uint32_t width, uint32_t height, uint32_t border_width)
64 {
65@@ -597,6 +618,7 @@ render_zoomed_to_shm(struct screen *screen, float zoom)
66 int32_t cx = screen_x + width / 2;
67 int32_t cy = screen_y + height / 2;
68 struct compositor_view *view;
69+ struct wld_buffer *background;
70
71 struct wld_buffer *buffer = wld_create_buffer(swc.shm->context,
72 width, height, WLD_FORMAT_XRGB8888, WLD_FLAG_MAP);
73@@ -610,8 +632,9 @@ render_zoomed_to_shm(struct screen *screen, float zoom)
74
75 pixman_region32_t full;
76 pixman_region32_init_rect(&full, 0, 0, width, height);
77- if (wallbuf)
78- wld_copy_region(swc.shm->renderer, wallbuf, 0, 0, &full);
79+ background = swc_wallpaper_buffer_for_screen(screen);
80+ if (background)
81+ wld_copy_region(swc.shm->renderer, background, 0, 0, &full);
82 else
83 wld_fill_region(swc.shm->renderer, bgcolor, &full);
84 pixman_region32_fini(&full);
85@@ -1327,7 +1350,7 @@ update_screen(struct screen *screen)
86 pixman_region32_translate(&damage, geom->x, geom->y);
87 pixman_region32_init(&base_damage);
88 pixman_region32_subtract(&base_damage, &damage, &compositor.opaque);
89- renderer_repaint(target, &damage, &base_damage, &compositor.views);
90+ renderer_repaint(target, &damage, &base_damage, &compositor.views, screen);
91 pixman_region32_fini(&damage);
92 pixman_region32_fini(&base_damage);
93 }
94@@ -1508,12 +1531,16 @@ compositor_initialize(void)
95 for (keysym = XKB_KEY_XF86Switch_VT_1; keysym <= XKB_KEY_XF86Switch_VT_12; ++keysym)
96 swc_add_binding(SWC_BINDING_KEY, SWC_MOD_ANY, keysym, &handle_switch_vt, NULL);
97
98+ compositor.initialized = true;
99+
100 return true;
101 }
102
103 void
104 compositor_finalize(void)
105 {
106+ compositor.initialized = false;
107+
108 if (compositor.zoom_buffer)
109 wld_buffer_unreference(compositor.zoom_buffer);
110 pixman_region32_fini(&compositor.damage);
111@@ -1540,6 +1567,7 @@ compositor_render_to_shm(struct screen *screen)
112 pixman_region32_t region;
113 pixman_region32_t damage;
114 uint32_t caps;
115+ struct wld_buffer *background;
116
117 /* create shm buf */
118 buffer = wld_create_buffer(swc.shm->context, width, height,
119@@ -1559,8 +1587,9 @@ compositor_render_to_shm(struct screen *screen)
120 pixman_region32_init_rect(&damage, screen->base.geometry.x, screen->base.geometry.y, width, height);
121
122 /* background */
123- if (wallbuf)
124- wld_copy_region(swc.shm->renderer, wallbuf, 0, 0, ®ion);
125+ background = swc_wallpaper_buffer_for_screen(screen);
126+ if (background)
127+ wld_copy_region(swc.shm->renderer, background, 0, 0, ®ion);
128 else
129 wld_fill_region(swc.shm->renderer, bgcolor, ®ion);
130
+1,
-0
1@@ -48,6 +48,7 @@ struct swc_compositor {
2
3 bool compositor_initialize(void);
4 void compositor_finalize(void);
5+void compositor_damage_all(void);
6
7 struct compositor_view {
8 struct view base;
+1,
-0
1@@ -51,6 +51,7 @@ struct swc {
2 struct wl_global *shell;
3 struct wl_global *snap_manager;
4 struct wl_global *subcompositor;
5+ struct wl_global *wallpaper_manager;
6 struct wl_global *xdg_decoration_manager;
7 struct wl_global *xdg_shell;
8
+2,
-0
1@@ -61,6 +61,7 @@ SWC_SOURCES = \
2 protocol/server-decoration-protocol.c \
3 protocol/swc-protocol.c \
4 protocol/swc_snap-protocol.c \
5+ protocol/swc_wallpaper-protocol.c \
6 protocol/wayland-drm-protocol.c \
7 protocol/xdg-decoration-unstable-v1-protocol.c \
8 protocol/xdg-shell-protocol.c
9@@ -113,6 +114,7 @@ $(call objects,dmabuf): protocol/linux-dmabuf-unstable-v1-server-protocol.h
10 $(call objects,drm drm_buffer): protocol/wayland-drm-server-protocol.h
11 $(call objects,kde_decoration): protocol/server-decoration-server-protocol.h
12 $(call objects,snap): protocol/swc_snap-server-protocol.h
13+$(call objects,wallpaper): protocol/swc_wallpaper-server-protocol.h
14 $(call objects,xdg_decoration): protocol/xdg-decoration-unstable-v1-server-protocol.h
15 $(call objects,xdg_shell): protocol/xdg-shell-server-protocol.h
16 $(call objects,pointer): cursor/cursor_data.h
+12,
-2
1@@ -40,6 +40,7 @@
2 #include "snap.h"
3 #include "subcompositor.h"
4 #include "util.h"
5+#include "wallpaper.h"
6 #include "window.h"
7 #include "xdg_decoration.h"
8 #include "xdg_shell.h"
9@@ -222,10 +223,16 @@ swc_initialize(struct wl_display *display, struct wl_event_loop *event_loop, con
10 goto error14;
11 }
12
13+ swc.wallpaper_manager = swc_wallpaper_manager_create(display);
14+ if (!swc.wallpaper_manager) {
15+ ERROR("Could not initialize wallpaper manager\n");
16+ goto error15;
17+ }
18+
19 #ifdef ENABLE_XWAYLAND
20 if (!xserver_initialize()) {
21 ERROR("Could not initialize xwayland\n");
22- goto error15;
23+ goto error16;
24 }
25 #endif
26
27@@ -234,9 +241,11 @@ swc_initialize(struct wl_display *display, struct wl_event_loop *event_loop, con
28 return true;
29
30 #ifdef ENABLE_XWAYLAND
31+error16:
32+ wl_global_destroy(swc.wallpaper_manager);
33+#endif
34 error15:
35 wl_global_destroy(swc.snap_manager);
36-#endif
37 error14:
38 wl_global_destroy(swc.panel_manager);
39 error13:
40@@ -275,6 +284,7 @@ swc_finalize(void)
41 #ifdef ENABLE_XWAYLAND
42 xserver_finalize();
43 #endif
44+ wl_global_destroy(swc.wallpaper_manager);
45 wl_global_destroy(swc.snap_manager);
46 wl_global_destroy(swc.panel_manager);
47 wl_global_destroy(swc.xdg_decoration_manager);
+10,
-7
1@@ -35,6 +35,7 @@ extern "C" {
2 struct libinput_device;
3 struct wl_display;
4 struct wl_event_loop;
5+struct wld_buffer;
6
7 /**
8 * gett the current cursor position
9@@ -438,19 +439,21 @@ int swc_add_axis_binding(uint32_t modifiers, uint32_t axis, swc_axis_binding_han
10
11 /* Wallpaper {{{ */
12
13-extern unsigned char *wallpaper;
14-extern struct wld_buffer *wallbuf;
15-
16 /**
17- * Set wallpaper to image from fs path.
18- * TODO: tiling, maybe diff image for each screen
19+ * Set fallback wallpaper buffer for all screens that dom't have an override.
20 */
21+void swc_wallpaper_set_buffer(struct wld_buffer *buffer);
22
23-void swc_wallpaper_set(char* path);
24+/**
25+ * Set wallpaper buffer for specified screen id.
26+ *
27+ * Passing NULL clears the override for that screen.
28+ */
29+void swc_wallpaper_set_buffer_for_screen(uint8_t screen_id, struct wld_buffer *buffer);
30
31 /**
32 * Set wallpaper to a single color
33- * pretty much ignored if wallpaper is set to image
34+ * used when no wallpaper buffer is set
35 * defaults to black
36 */
37
+93,
-54
1@@ -1,77 +1,116 @@
2-#include <pixman.h>
3 #include <wld/wld.h>
4
5-#define STB_IMAGE_IMPLEMENTATION
6-#define STBI_NO_HDR
7-#include "../stb/stb_image.h"
8-
9-#define STB_IMAGE_RESIZE_IMPLEMENTATION
10-#include "../stb/stb_image_resize2.h"
11-
12 #include "swc.h"
13-#include "internal.h"
14-#include "drm.h"
15-#include "util.h"
16-#include "shm.h"
17+#include "compositor.h"
18 #include "screen.h"
19+#include "util.h"
20+#include "wayland_buffer.h"
21+#include "wallpaper.h"
22+#include "swc_wallpaper-server-protocol.h"
23
24-unsigned char *wallpaper = NULL;
25-struct wld_buffer *wallbuf = NULL;
26+#define MAX_WALLPAPER_SCREENS 32
27
28+static struct wld_buffer *wallbuf = NULL;
29+static struct wld_buffer *screen_wallbuf[MAX_WALLPAPER_SCREENS];
30 uint32_t bgcolor = 0xff000000;
31
32+static void
33+set_buffer_slot(struct wld_buffer **slot, struct wld_buffer *buffer)
34+{
35+ if (buffer)
36+ wld_buffer_reference(buffer);
37+ if (*slot)
38+ wld_buffer_unreference(*slot);
39+
40+ *slot = buffer;
41+}
42+
43+struct wld_buffer *
44+swc_wallpaper_buffer_for_screen(struct screen *screen)
45+{
46+ if (screen
47+ && screen->id < ARRAY_LENGTH(screen_wallbuf)
48+ && screen_wallbuf[screen->id])
49+ return screen_wallbuf[screen->id];
50+
51+ return wallbuf;
52+}
53+
54 EXPORT void
55-swc_wallpaper_set(char* path)
56+swc_wallpaper_set_buffer(struct wld_buffer *buffer)
57 {
58- int width, height, chan;
59- unsigned char *loaded;
60- struct screen *screen;
61- int target_width = 0, target_height = 0;
62+ set_buffer_slot(&wallbuf, buffer);
63+ compositor_damage_all();
64+}
65
66- loaded = stbi_load(path, &width, &height, &chan, 4);
67- if (!loaded)
68+EXPORT void
69+swc_wallpaper_set_buffer_for_screen(uint8_t screen_id, struct wld_buffer *buffer)
70+{
71+ if (screen_id >= ARRAY_LENGTH(screen_wallbuf))
72 return;
73
74- /* get screen dimensions */
75- wl_list_for_each(screen, &swc.screens, link) {
76- target_width = screen->base.geometry.width;
77- target_height = screen->base.geometry.height;
78- break;
79- }
80+ set_buffer_slot(&screen_wallbuf[screen_id], buffer);
81+ compositor_damage_all();
82+}
83+
84+EXPORT void
85+swc_wallpaper_color_set(uint32_t color)
86+{
87+ bgcolor = color;
88+ compositor_damage_all();
89+}
90+
91+static void
92+set_buffer(struct wl_client *client, struct wl_resource *resource,
93+ int32_t screen_id, struct wl_resource *buffer_resource)
94+{
95+ struct wld_buffer *buffer = NULL;
96
97- /* If we have a screen and dimensions wrong scale */
98- if (target_width > 0 && target_height > 0 &&
99- (width != target_width || height != target_height)) {
100- wallpaper = stbir_resize_uint8_srgb(loaded, width, height, 0,
101- NULL, target_width, target_height, 0,
102- STBIR_RGBA);
103- stbi_image_free(loaded);
104- width = target_width;
105- height = target_height;
106- } else {
107- wallpaper = loaded;
108+ (void)client;
109+
110+ if (buffer_resource) {
111+ buffer = wayland_buffer_get(buffer_resource);
112+ if (!buffer) {
113+ wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
114+ "buffer is not a wl_buffer");
115+ return;
116+ }
117 }
118
119- /* swap color channels to be compatible */
120- for(int i = 0; i < width * height; i++) {
121- unsigned char r = wallpaper[i*4];
122- wallpaper[i*4] = wallpaper[(i*4)+2];
123- wallpaper[(i*4)+2] = r;
124+ if (screen_id == -1) {
125+ swc_wallpaper_set_buffer(buffer);
126+ return;
127 }
128
129- union wld_object obj;
130- obj.ptr = (uint32_t*)wallpaper;
131+ if (screen_id < 0 || screen_id >= ARRAY_LENGTH(screen_wallbuf))
132+ return;
133
134- wallbuf = wld_import_buffer(swc.shm->context,
135- WLD_OBJECT_DATA,
136- obj,
137- width, height,
138- WLD_FORMAT_ARGB8888,
139- width * 4);
140+ swc_wallpaper_set_buffer_for_screen((uint8_t)screen_id, buffer);
141 }
142
143-EXPORT void
144-swc_wallpaper_color_set(uint32_t color)
145+static const struct swc_wallpaper_interface wallpaper_impl = {
146+ .destroy = destroy_resource,
147+ .set_buffer = set_buffer,
148+};
149+
150+static void
151+bind_wallpaper(struct wl_client *client, void *data, uint32_t version, uint32_t id)
152 {
153- bgcolor = color;
154+ (void)data;
155+
156+ struct wl_resource *resource;
157+
158+ resource = wl_resource_create(client, &swc_wallpaper_interface, version, id);
159+ if (!resource) {
160+ wl_client_post_no_memory(client);
161+ return;
162+ }
163+
164+ wl_resource_set_implementation(resource, &wallpaper_impl, NULL, NULL);
165+}
166+
167+struct wl_global *
168+swc_wallpaper_manager_create(struct wl_display *display)
169+{
170+ return wl_global_create(display, &swc_wallpaper_interface, 1, NULL, bind_wallpaper);
171 }
+12,
-0
1@@ -0,0 +1,12 @@
2+#ifndef SWC_WALLPAPER_H
3+#define SWC_WALLPAPER_H
4+
5+struct wl_display;
6+struct wl_global;
7+struct wld_buffer;
8+struct screen;
9+
10+struct wl_global *swc_wallpaper_manager_create(struct wl_display *display);
11+struct wld_buffer *swc_wallpaper_buffer_for_screen(struct screen *screen);
12+
13+#endif
+3,
-0
1@@ -7,6 +7,7 @@ PROTOCOL_EXTENSIONS = \
2 $(dir)/server-decoration.xml\
3 $(dir)/swc.xml \
4 $(dir)/swc_snap.xml \
5+ $(dir)/swc_wallpaper.xml \
6 $(dir)/wayland-drm.xml \
7 $(wayland_protocols)/stable/xdg-shell/xdg-shell.xml \
8 $(wayland_protocols)/unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml \
9@@ -29,5 +30,7 @@ CLEAN_FILES += ${dir}/${proto_base}-protocol.c \
10
11 install-$(dir): | $(DESTDIR)$(DATADIR)/swc
12 install -m 644 protocol/swc.xml $(DESTDIR)$(DATADIR)/swc
13+ install -m 644 protocol/swc_snap.xml $(DESTDIR)$(DATADIR)/swc
14+ install -m 644 protocol/swc_wallpaper.xml $(DESTDIR)$(DATADIR)/swc
15
16 include common.mk
+19,
-0
1@@ -0,0 +1,19 @@
2+<?xml version="1.0" encoding="UTF-8"?>
3+<protocol name="swc_wallpaper">
4+ <interface name="swc_wallpaper" version="1">
5+ <description summary="set compositor wallpaper">
6+ Allows clients to set wallpaper buffers.
7+ </description>
8+
9+ <request name="destroy" type="destructor" />
10+
11+ <request name="set_buffer">
12+ <description summary="set or clear wallpaper buffer">
13+ screen_id=-1 targets global fallback wallpaper.
14+ Any other screen_id targets that id.
15+ </description>
16+ <arg name="screen_id" type="int" />
17+ <arg name="buffer" type="object" interface="wl_buffer" allow-null="true" />
18+ </request>
19+ </interface>
20+</protocol>