Commit 36ac353
13
plików
+141
dodanych
-446
usuniętych
@@ -67,3 +67,10 @@ pagbuild recipes/core/acl/PAGBUILD.yaml
67
67
## Narzędzia
68
68
69
69
- `migrate-recipes.py` — konwertuje receptury `cards` (Pkgfile) na `PAGBUILD.yaml`
70
+
71
+## Polityka forków
72
+
73
+Fork-first w całym repo: [`../../FORK-POLICY.md`](../../FORK-POLICY.md).
74
+Krótko: co możemy zrobić forkiem, robimy forkiem — źródła w repo, pakiet
75
+`-pagan`, lokalny tarball + wyliczony sha256 (build bez sieci) i adnotacja
76
+licencyjna o statusie forka (`FORK.md` + `NOTICE`).
@@ -1,29 +1,41 @@
1
+# GENEROWANY PLIK — nie edytować ręcznie.
2
+# Źródło prawdy: config/ i session/ (dom projektu PaganBuild/PaganDE).
3
+# Regeneracja: make tarball-meta && make recipe
4
+
1
5
pkgname: pagande
2
-pkgver: '0.1.0'
3
-pkgrel: 2
4
-pkgdesc: PaganDE — nowoczesne, modułowe środowisko Wayland z pływającymi oknami (własny shell, bez GTK/Qt)
6
+pkgver: '0.2.0'
7
+pkgrel: 1
8
+pkgdesc: 'PaganDE — lekkie środowisko Wayland: fork labwc-pagan (rc.ini + live reload), wlroots-pagan, Catppuccin Mocha (waybar, rofi, mako, foot, kanshi, swaybg, swaylock)'
5
9
url: 'https://paganlinux.eu'
6
10
arch: x86_64
7
11
license:
8
12
- MIT
9
13
depends:
14
+- cantarell-fonts
15
+- catppuccin-gtk-theme
16
+- foot
17
+- kanshi
10
18
- labwc-pagan
11
-- pagande-shell
19
+- mako
20
+- network-manager-applet
21
+- papirus-icon-theme
22
+- pavucontrol
12
23
- pipewire
13
24
- polkit-gnome
14
-- network-manager-applet
25
+- rofi
26
+- swaybg
27
+- swaylock
28
+- thunar
29
+- thunar-archive-plugin
30
+- waybar
31
+- xcursor-dmz
15
32
- xdg-desktop-portal
16
33
- xdg-desktop-portal-gtk
17
-- papirus-icon-theme
18
-- cantarell-fonts
19
-- xcursor-dmz
20
-- alacritty
21
-- thunar
22
34
makedepends: []
23
35
source:
24
36
- pagande-${pkgver}.tar.gz
25
37
sha256sums:
26
-- 5a59c3503f4cfd52280a500aff530e29830f57d375d02c4483e6ebb9af1aa870
38
+- '8ebe4df2514491a50a6485db5d4f790f6c81f6d6fc50b999806e2413b204e1d1'
27
39
build: |
28
40
cd ${pkgname}
29
41
@@ -34,13 +46,18 @@ build: |
34
46
install -dm755 "${PKGDIR}/usr/share/wayland-sessions"
35
47
install -m644 session/pagande.desktop "${PKGDIR}/usr/share/wayland-sessions/pagande.desktop"
36
48
37
- # ── Motyw okien (fork labwc) ────────────────────────────────
49
+ # ── Motyw okien labwc (config/theme/* → /usr/share/themes) ─
38
50
install -dm755 "${PKGDIR}/usr/share/themes"
39
- cp -a config/theme/pagan "${PKGDIR}/usr/share/themes/pagan"
51
+ cp -a config/theme/. "${PKGDIR}/usr/share/themes/"
40
52
41
53
# ── Domyślne konfiguracje (sesja rozkłada je do ~/.config) ─
42
54
install -dm755 "${PKGDIR}/etc/xdg/pagande"
43
55
cp -a config/labwc "${PKGDIR}/etc/xdg/pagande/labwc"
44
- cp -a config/shell "${PKGDIR}/etc/xdg/pagande/shell"
56
+ cp -a config/waybar "${PKGDIR}/etc/xdg/pagande/waybar"
57
+ cp -a config/rofi "${PKGDIR}/etc/xdg/pagande/rofi"
58
+ cp -a config/mako "${PKGDIR}/etc/xdg/pagande/mako"
59
+ cp -a config/foot "${PKGDIR}/etc/xdg/pagande/foot"
60
+ cp -a config/kanshi "${PKGDIR}/etc/xdg/pagande/kanshi"
61
+ cp -a config/gtk-3.0 "${PKGDIR}/etc/xdg/pagande/gtk-3.0"
45
62
package: |
46
63
true
47
64
deleted file mode 100644
48
65
Binary files a/de/pagande/pagande-0.1.0.tar.gz and /dev/null differ
49
66
new file mode 100644
50
67
Binary files /dev/null and b/de/pagande/pagande-0.2.0.tar.gz differ
51
68
new file mode 100644
@@ -0,0 +1,25 @@
1
+pkgname: catppuccin-gtk-theme
2
+pkgver: '1.0.3'
3
+pkgrel: '1'
4
+pkgdesc: 'Catppuccin GTK (Mocha, Blue, Standard) - motyw GTK3/GTK4 spójny z paleta PaganDE (dark/light w srodku)'
5
+url: 'https://github.com/catppuccin/gtk'
6
+arch: x86_64
7
+license:
8
+- MIT
9
+depends: []
10
+makedepends:
11
+- unzip
12
+source:
13
+- 'https://github.com/catppuccin/gtk/releases/download/v${pkgver}/catppuccin-mocha-blue-standard+default.zip'
14
+sha256sums:
15
+- SKIP
16
+build: |
17
+ # Asset z release'u: kompletny motyw (gtk-3.0, gtk-4.0, gnome-shell, ...).
18
+ # Instalujemy pod nazwa uzywana przez PaganDE (config/gtk-3.0/settings.ini
19
+ # oraz GTK_THEME w config/labwc/environment).
20
+ mkdir -p "${PKGDIR}/usr/share/themes"
21
+ unzip -q catppuccin-mocha-blue-standard+default.zip
22
+ mv catppuccin-mocha-blue-standard+default \
23
+ "${PKGDIR}/usr/share/themes/Catppuccin-Mocha-Standard-Blue-Dark"
24
+package: |
25
+ true
0
26
new file mode 100644
@@ -0,0 +1,25 @@
1
+pkgname: kanshi
2
+pkgver: '1.2.0'
3
+pkgrel: '1'
4
+pkgdesc: 'Kanshi - automatyczne profile monitorow dla Wayland (PaganDE: profile w ~/.config/kanshi/config)'
5
+url: 'https://github.com/emersion/kanshi'
6
+arch: x86_64
7
+license:
8
+- MIT
9
+depends:
10
+- wayland
11
+makedepends:
12
+- meson
13
+- ninja
14
+- wayland-protocols
15
+source:
16
+- 'https://github.com/emersion/kanshi/archive/refs/tags/v${pkgver}.tar.gz'
17
+sha256sums:
18
+- SKIP
19
+build: |
20
+ cd kanshi-${pkgver}
21
+ meson setup build --prefix=/usr -Dman-pages=disabled
22
+ ninja -C build
23
+ DESTDIR=${PKGDIR} ninja -C build install
24
+package: |
25
+ true
@@ -7,7 +7,7 @@ arch: x86_64
7
7
license:
8
8
- GPL-2.0-only
9
9
depends:
10
-- wlroots
10
+- wlroots-pagan
11
11
- libxkbcommon
12
12
- xorg-libdrm
13
13
- libxml2
@@ -27,7 +27,7 @@ makedepends:
27
27
source:
28
28
- labwc-pagan-${pkgver}.tar.gz
29
29
sha256sums:
30
-- e1e8726326cf362193d48bef7363bfad63d9d1d5930aa208d48a6e63615351a3
30
+- 3119b39714853dc1a66eeffe745a053fad068c6c491d4980412297b1968e1b5b
31
31
build: |
32
32
cd ${pkgname}
33
33
34
34
Binary files a/gui/labwc-pagan/labwc-pagan-0.20.2.tar.gz and b/gui/labwc-pagan/labwc-pagan-0.20.2.tar.gz differ
35
35
new file mode 100644
@@ -0,0 +1,49 @@
1
+pkgname: wlroots-pagan
2
+pkgver: '0.20.2'
3
+pkgrel: 1
4
+pkgdesc: 'Wlroots PaganDE (fork) - fundament kompozytora labwc-pagan: zaokraglone rogi okien (rounded clip) + poprawka kanalow BGR888; zrodla w paganDE/compositor/wlroots'
5
+url: 'https://paganlinux.eu'
6
+arch: x86_64
7
+license:
8
+- MIT
9
+depends:
10
+- wayland
11
+- xorg-libdrm
12
+- libinput
13
+- libxkbcommon
14
+- xorg-pixman
15
+- mesa
16
+- libdisplay-info
17
+- libliftoff
18
+- seatd
19
+- hwdata
20
+- systemd
21
+makedepends:
22
+- meson
23
+- ninja
24
+- wayland-protocols
25
+- systemd
26
+source:
27
+- wlroots-pagan-${pkgver}.tar.gz
28
+sha256sums:
29
+- 6b7664a16f942094d4a222ac0a33321895c2db1d817b4f1ef06c87cb95ca3f6b
30
+build: |
31
+ cd ${pkgname}
32
+
33
+ # Nasz fork: zmiany PaganDE (rounded clip + BGR888) sa juz wpiete w zrodla,
34
+ # nie nakladamy patche w buildzie. Patrz paganDE/compositor/wlroots/pagan/FORK.md.
35
+ # pagbuild dodaje -D_GNU_SOURCE do CFLAGS, a wlroots sam go definiuje
36
+ # (render/allocator/udmabuf.c) -> "_GNU_SOURCE redefined" + -Werror = blad.
37
+ # -std=gnu17 i tak implikuje _GNU_SOURCE, wiec usuwamy nadmiarowa definicje.
38
+ CFLAGS="${CFLAGS/-D_GNU_SOURCE/}" CPPFLAGS="${CPPFLAGS/-D_GNU_SOURCE/}" \
39
+ meson setup build --prefix=/usr \
40
+ -Dexamples=false \
41
+ -Drenderers=gles2 \
42
+ -Dbackends=drm,libinput \
43
+ -Dxwayland=disabled \
44
+ -Dcolor-management=disabled
45
+
46
+ ninja -C build
47
+ DESTDIR=${PKGDIR} ninja -C build install
48
+package: |
49
+ true
0
50
new file mode 100644
1
51
Binary files /dev/null and b/gui/wlroots-pagan/wlroots-pagan-0.20.2.tar.gz differ
@@ -1,7 +1,7 @@
1
1
pkgname: wlroots
2
2
pkgver: '0.20.2'
3
-pkgrel: 3
4
-pkgdesc: 'Modular Wayland compositor library (fundament labwc; patch PaganDE: zaokrąglone rogi okien + poprawka kanałów BGR888)'
3
+pkgrel: 4
4
+pkgdesc: 'Modular Wayland compositor library (upstream, bez zmian PaganDE; nasz fork z poprawkami: wlroots-pagan)'
5
5
url: https://gitlab.freedesktop.org/wlroots/wlroots
6
6
arch: x86_64
7
7
license:
@@ -25,26 +25,11 @@ makedepends:
25
25
- systemd
26
26
source:
27
27
- https://gitlab.freedesktop.org/wlroots/wlroots/-/archive/${pkgver}/${pkgname}-${pkgver}.tar.gz
28
-- wlroots-0.20.2-rounded-clip.patch
29
-- wlroots-0.20.2-bgr888-read-pixels.patch
30
28
sha256sums:
31
29
- SKIP
32
-- SKIP
33
-- SKIP
34
30
build: |
35
31
cd ${pkgname}
36
32
37
- # PaganDE: wlr_scene_buffer_set_rounded_clip() — renderer gles2 przycina
38
- # tekstury do prostokąta z zaokrąglonymi rogami (używane przez labwc-pagan
39
- # do zaokrąglania treści okien; patrz paganDE/compositor/labwc/pagan/FORK.md).
40
- patch -p1 -i ../wlroots-0.20.2-rounded-clip.patch
41
-
42
- # PaganDE: glReadPixels(GL_RGB) dla DRM_FORMAT_BGR888 zwraca bajty R,G,B,
43
- # a układ BGR888 oczekuje B,G,R — bez tego screencopy/zrzuty miały zamienione
44
- # kanały czerwony i niebieski (widoczne na llvmpipe, gdzie preferred read
45
- # format to BGR888).
46
- patch -p1 -i ../wlroots-0.20.2-bgr888-read-pixels.patch
47
-
48
33
# pagbuild dodaje -D_GNU_SOURCE do CFLAGS, a wlroots sam go definiuje
49
34
# (render/allocator/udmabuf.c) -> "_GNU_SOURCE redefined" + -Werror = błąd.
50
35
# -std=gnu17 i tak implikuje _GNU_SOURCE, więc usuwamy nadmiarową definicję.
51
36
deleted file mode 100644
@@ -1,45 +0,0 @@
1
-From: PaganDE <dev@paganlinux.org>
2
-Subject: [PATCH] gles2: fix R/B swap when reading DRM_FORMAT_BGR888
3
-
4
-GLES2 has no GL_BGR, so wlroots maps DRM_FORMAT_BGR888 to
5
-glReadPixels(GL_RGB, GL_UNSIGNED_BYTE). GL_RGB returns bytes in
6
-R,G,B order while the BGR888 layout expects B,G,R - the resulting
7
-buffer ends up with red and blue swapped.
8
-
9
-On llvmpipe the implementation read format is GL_RGB, so
10
-wlr_output_preferred_read_format() reports BGR888 and screencopy
11
-clients receive a buffer with inverted channels.
12
-
13
-Origin: PaganDE fork of wlroots 0.20.2
14
- render/gles2/texture.c | 19 +++++++++++++++++++
15
- 1 file changed, 19 insertions(+)
16
-
17
-+++ b/render/gles2/texture.c 2026-08-31 14:04:58.836879583 +0200
18
-@@ -225,6 +225,25 @@
19
- }
20
- }
21
-
22
-+ /*
23
-+ * DRM_FORMAT_BGR888 has no GLES2 equivalent: we read it as GL_RGB,
24
-+ * which returns bytes in R,G,B order, while the BGR888 layout
25
-+ * expects B,G,R. Swap the channels so the buffer actually contains
26
-+ * BGR data. Otherwise screencopy/screenshot clients see red and
27
-+ * blue swapped (visible on llvmpipe, where the preferred read
28
-+ * format is BGR888).
29
-+ */
30
-+ if (drm_fmt->drm_format == DRM_FORMAT_BGR888) {
31
-+ for (int32_t i = 0; i < src.height; ++i) {
32
-+ unsigned char *row = p + (size_t)i * options->stride;
33
-+ for (int32_t x = 0; x < src.width; ++x) {
34
-+ unsigned char tmp = row[x * 3];
35
-+ row[x * 3] = row[x * 3 + 2];
36
-+ row[x * 3 + 2] = tmp;
37
-+ }
38
-+ }
39
-+ }
40
-+
41
- wlr_egl_restore_context(&prev_ctx);
42
- pop_gles2_debug(texture->renderer);
43
-
44
0
deleted file mode 100644
@@ -1,368 +0,0 @@
1
-diff -ruN a/include/render/gles2.h b/include/render/gles2.h
2
-+++ b/include/render/gles2.h 2026-08-31 12:49:04.008068765 +0200
3
-@@ -35,6 +35,12 @@
4
- GLint tex;
5
- GLint alpha;
6
- GLint pos_attrib;
7
-+ /* PaganDE: rounded clip */
8
-+ GLint rounded;
9
-+ GLint box_pos;
10
-+ GLint box_size;
11
-+ GLint radius;
12
-+ GLint corners;
13
- };
14
-
15
- struct wlr_gles2_renderer {
16
-diff -ruN a/include/wlr/render/pass.h b/include/wlr/render/pass.h
17
-+++ b/include/wlr/render/pass.h 2026-08-31 12:49:04.007446160 +0200
18
-@@ -84,6 +84,14 @@
19
- WLR_SCALE_FILTER_NEAREST,
20
- };
21
-
22
-+/* PaganDE: rounded corners bitmask (see corner_radius below) */
23
-+enum wlr_rounded_corner {
24
-+ WLR_ROUNDED_CORNER_TOP_LEFT = 1 << 0,
25
-+ WLR_ROUNDED_CORNER_TOP_RIGHT = 1 << 1,
26
-+ WLR_ROUNDED_CORNER_BOTTOM_RIGHT = 1 << 2,
27
-+ WLR_ROUNDED_CORNER_BOTTOM_LEFT = 1 << 3,
28
-+};
29
-+
30
- struct wlr_render_texture_options {
31
- /* Source texture */
32
- struct wlr_texture *texture;
33
-@@ -95,6 +103,12 @@
34
- const float *alpha;
35
- /* Clip region, leave NULL to disable clipping */
36
- const pixman_region32_t *clip;
37
-+ /* PaganDE: rounded corners. When corner_radius > 0 and rounded_corners != 0,
38
-+ * the texture is clipped to a rectangle with rounded corners (bitmask of
39
-+ * enum wlr_rounded_corner). Renderers that do not support this feature
40
-+ * must ignore these fields. */
41
-+ float corner_radius;
42
-+ uint32_t rounded_corners;
43
- /* Transform applied to the source texture */
44
- enum wl_output_transform transform;
45
- /* Filtering */
46
-diff -ruN a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h
47
-+++ b/include/wlr/types/wlr_scene.h 2026-08-31 12:49:04.007705726 +0200
48
-@@ -215,6 +215,11 @@
49
-
50
- // True if the underlying buffer is a wlr_single_pixel_buffer_v1
51
- bool is_single_pixel_buffer;
52
-+
53
-+ // PaganDE: rounded clip applied when rendering this buffer
54
-+ // (see wlr_scene_buffer_set_rounded_clip)
55
-+ float clip_radius;
56
-+ uint32_t clip_corners;
57
- // If is_single_pixel_buffer is set, contains the color of the buffer
58
- // as {R, G, B, A} where the max value of each component is UINT32_MAX
59
- uint32_t single_pixel_buffer_color[4];
60
-@@ -549,6 +554,16 @@
61
- enum wl_output_transform transform);
62
-
63
- /**
64
-+ * PaganDE: clip the buffer to a rectangle with rounded corners.
65
-+ *
66
-+ * radius is the corner radius in output pixels; corners is a bitmask of
67
-+ * enum wlr_rounded_corner. Passing radius 0 (or corners 0) disables the clip.
68
-+ * Renderers without support (e.g. pixman) ignore this.
69
-+ */
70
-+void wlr_scene_buffer_set_rounded_clip(struct wlr_scene_buffer *scene_buffer,
71
-+ float radius, uint32_t corners);
72
-+
73
-+/**
74
- * Sets the opacity of this buffer
75
- */
76
- void wlr_scene_buffer_set_opacity(struct wlr_scene_buffer *scene_buffer,
77
-diff -ruN a/render/gles2/pass.c b/render/gles2/pass.c
78
-+++ b/render/gles2/pass.c 2026-08-31 12:53:51.197412809 +0200
79
-@@ -247,6 +247,19 @@
80
- set_proj_matrix(shader->proj, pass->projection_matrix, &dst_box);
81
- set_tex_matrix(shader->tex_proj, options->transform, &src_fbox);
82
-
83
-+ bool rounded = options->corner_radius > 0 && options->rounded_corners != 0;
84
-+ glUniform1f(shader->rounded, rounded ? 1.0f : 0.0f);
85
-+ if (rounded) {
86
-+ glUniform2f(shader->box_pos, dst_box.x, dst_box.y);
87
-+ glUniform2f(shader->box_size, dst_box.width, dst_box.height);
88
-+ glUniform1f(shader->radius, options->corner_radius);
89
-+ glUniform4f(shader->corners,
90
-+ (options->rounded_corners & WLR_ROUNDED_CORNER_TOP_LEFT) ? 1.0f : 0.0f,
91
-+ (options->rounded_corners & WLR_ROUNDED_CORNER_TOP_RIGHT) ? 1.0f : 0.0f,
92
-+ (options->rounded_corners & WLR_ROUNDED_CORNER_BOTTOM_RIGHT) ? 1.0f : 0.0f,
93
-+ (options->rounded_corners & WLR_ROUNDED_CORNER_BOTTOM_LEFT) ? 1.0f : 0.0f);
94
-+ }
95
-+
96
- render(&dst_box, options->clip, shader->pos_attrib);
97
-
98
- glBindTexture(texture->target, 0);
99
-diff -ruN a/render/gles2/renderer.c b/render/gles2/renderer.c
100
-+++ b/render/gles2/renderer.c 2026-08-31 12:49:04.008364833 +0200
101
-@@ -652,6 +652,11 @@
102
- renderer->shaders.tex_rgba.tex = glGetUniformLocation(prog, "tex");
103
- renderer->shaders.tex_rgba.alpha = glGetUniformLocation(prog, "alpha");
104
- renderer->shaders.tex_rgba.pos_attrib = glGetAttribLocation(prog, "pos");
105
-+ renderer->shaders.tex_rgba.rounded = glGetUniformLocation(prog, "u_rounded");
106
-+ renderer->shaders.tex_rgba.box_pos = glGetUniformLocation(prog, "u_box_pos");
107
-+ renderer->shaders.tex_rgba.box_size = glGetUniformLocation(prog, "u_box_size");
108
-+ renderer->shaders.tex_rgba.radius = glGetUniformLocation(prog, "u_radius");
109
-+ renderer->shaders.tex_rgba.corners = glGetUniformLocation(prog, "u_corners");
110
-
111
- renderer->shaders.tex_rgbx.program = prog =
112
- link_program(renderer, common_vert_src, tex_rgbx_frag_src);
113
-@@ -663,6 +668,11 @@
114
- renderer->shaders.tex_rgbx.tex = glGetUniformLocation(prog, "tex");
115
- renderer->shaders.tex_rgbx.alpha = glGetUniformLocation(prog, "alpha");
116
- renderer->shaders.tex_rgbx.pos_attrib = glGetAttribLocation(prog, "pos");
117
-+ renderer->shaders.tex_rgbx.rounded = glGetUniformLocation(prog, "u_rounded");
118
-+ renderer->shaders.tex_rgbx.box_pos = glGetUniformLocation(prog, "u_box_pos");
119
-+ renderer->shaders.tex_rgbx.box_size = glGetUniformLocation(prog, "u_box_size");
120
-+ renderer->shaders.tex_rgbx.radius = glGetUniformLocation(prog, "u_radius");
121
-+ renderer->shaders.tex_rgbx.corners = glGetUniformLocation(prog, "u_corners");
122
-
123
- if (renderer->exts.OES_egl_image_external) {
124
- renderer->shaders.tex_ext.program = prog =
125
-@@ -675,6 +685,11 @@
126
- renderer->shaders.tex_ext.tex = glGetUniformLocation(prog, "tex");
127
- renderer->shaders.tex_ext.alpha = glGetUniformLocation(prog, "alpha");
128
- renderer->shaders.tex_ext.pos_attrib = glGetAttribLocation(prog, "pos");
129
-+ renderer->shaders.tex_ext.rounded = glGetUniformLocation(prog, "u_rounded");
130
-+ renderer->shaders.tex_ext.box_pos = glGetUniformLocation(prog, "u_box_pos");
131
-+ renderer->shaders.tex_ext.box_size = glGetUniformLocation(prog, "u_box_size");
132
-+ renderer->shaders.tex_ext.radius = glGetUniformLocation(prog, "u_radius");
133
-+ renderer->shaders.tex_ext.corners = glGetUniformLocation(prog, "u_corners");
134
- }
135
-
136
- pop_gles2_debug(renderer);
137
-diff -ruN a/render/gles2/shaders/tex_external.frag b/render/gles2/shaders/tex_external.frag
138
-+++ b/render/gles2/shaders/tex_external.frag 2026-08-31 12:53:34.209558298 +0200
139
-@@ -10,6 +10,51 @@
140
- uniform samplerExternalOES texture0;
141
- uniform float alpha;
142
-
143
-+
144
-+// PaganDE: rounded clip (discard fragments outside the rounded rect)
145
-+// GLSL ES 1.00: tylko floaty (bez bitowych operacji); maska rogów w vec4.
146
-+uniform float u_rounded;
147
-+uniform vec2 u_box_pos;
148
-+uniform vec2 u_box_size;
149
-+uniform float u_radius;
150
-+uniform vec4 u_corners; /* x=TL y=TR z=BR w=BL, 1.0 = zaokrąglony */
151
-+
152
-+void rounded_clip() {
153
-+ if (u_rounded == 0.0) {
154
-+ return;
155
-+ }
156
-+ vec2 p = gl_FragCoord.xy - u_box_pos;
157
-+ float r = u_radius;
158
-+ /* top-left */
159
-+ if (u_corners.x > 0.5) {
160
-+ if (p.x <= r && p.y <= r && distance(p, vec2(r, r)) > r) {
161
-+ discard;
162
-+ }
163
-+ }
164
-+ /* top-right */
165
-+ if (u_corners.y > 0.5) {
166
-+ if (p.x >= u_box_size.x - r && p.y <= r
167
-+ && distance(p, vec2(u_box_size.x - r, r)) > r) {
168
-+ discard;
169
-+ }
170
-+ }
171
-+ /* bottom-right */
172
-+ if (u_corners.z > 0.5) {
173
-+ if (p.x >= u_box_size.x - r && p.y >= u_box_size.y - r
174
-+ && distance(p, vec2(u_box_size.x - r, u_box_size.y - r)) > r) {
175
-+ discard;
176
-+ }
177
-+ }
178
-+ /* bottom-left */
179
-+ if (u_corners.w > 0.5) {
180
-+ if (p.x <= r && p.y >= u_box_size.y - r
181
-+ && distance(p, vec2(r, u_box_size.y - r)) > r) {
182
-+ discard;
183
-+ }
184
-+ }
185
-+}
186
-+
187
- void main() {
188
-+ rounded_clip();
189
- gl_FragColor = texture2D(texture0, v_texcoord) * alpha;
190
- }
191
-diff -ruN a/render/gles2/shaders/tex_rgba.frag b/render/gles2/shaders/tex_rgba.frag
192
-+++ b/render/gles2/shaders/tex_rgba.frag 2026-08-31 12:53:34.209518897 +0200
193
-@@ -8,6 +8,51 @@
194
- uniform sampler2D tex;
195
- uniform float alpha;
196
-
197
-+
198
-+// PaganDE: rounded clip (discard fragments outside the rounded rect)
199
-+// GLSL ES 1.00: tylko floaty (bez bitowych operacji); maska rogów w vec4.
200
-+uniform float u_rounded;
201
-+uniform vec2 u_box_pos;
202
-+uniform vec2 u_box_size;
203
-+uniform float u_radius;
204
-+uniform vec4 u_corners; /* x=TL y=TR z=BR w=BL, 1.0 = zaokrąglony */
205
-+
206
-+void rounded_clip() {
207
-+ if (u_rounded == 0.0) {
208
-+ return;
209
-+ }
210
-+ vec2 p = gl_FragCoord.xy - u_box_pos;
211
-+ float r = u_radius;
212
-+ /* top-left */
213
-+ if (u_corners.x > 0.5) {
214
-+ if (p.x <= r && p.y <= r && distance(p, vec2(r, r)) > r) {
215
-+ discard;
216
-+ }
217
-+ }
218
-+ /* top-right */
219
-+ if (u_corners.y > 0.5) {
220
-+ if (p.x >= u_box_size.x - r && p.y <= r
221
-+ && distance(p, vec2(u_box_size.x - r, r)) > r) {
222
-+ discard;
223
-+ }
224
-+ }
225
-+ /* bottom-right */
226
-+ if (u_corners.z > 0.5) {
227
-+ if (p.x >= u_box_size.x - r && p.y >= u_box_size.y - r
228
-+ && distance(p, vec2(u_box_size.x - r, u_box_size.y - r)) > r) {
229
-+ discard;
230
-+ }
231
-+ }
232
-+ /* bottom-left */
233
-+ if (u_corners.w > 0.5) {
234
-+ if (p.x <= r && p.y >= u_box_size.y - r
235
-+ && distance(p, vec2(r, u_box_size.y - r)) > r) {
236
-+ discard;
237
-+ }
238
-+ }
239
-+}
240
-+
241
- void main() {
242
-+ rounded_clip();
243
- gl_FragColor = texture2D(tex, v_texcoord) * alpha;
244
- }
245
-diff -ruN a/render/gles2/shaders/tex_rgbx.frag b/render/gles2/shaders/tex_rgbx.frag
246
-+++ b/render/gles2/shaders/tex_rgbx.frag 2026-08-31 12:53:34.209462266 +0200
247
-@@ -8,6 +8,51 @@
248
- uniform sampler2D tex;
249
- uniform float alpha;
250
-
251
-+
252
-+// PaganDE: rounded clip (discard fragments outside the rounded rect)
253
-+// GLSL ES 1.00: tylko floaty (bez bitowych operacji); maska rogów w vec4.
254
-+uniform float u_rounded;
255
-+uniform vec2 u_box_pos;
256
-+uniform vec2 u_box_size;
257
-+uniform float u_radius;
258
-+uniform vec4 u_corners; /* x=TL y=TR z=BR w=BL, 1.0 = zaokrąglony */
259
-+
260
-+void rounded_clip() {
261
-+ if (u_rounded == 0.0) {
262
-+ return;
263
-+ }
264
-+ vec2 p = gl_FragCoord.xy - u_box_pos;
265
-+ float r = u_radius;
266
-+ /* top-left */
267
-+ if (u_corners.x > 0.5) {
268
-+ if (p.x <= r && p.y <= r && distance(p, vec2(r, r)) > r) {
269
-+ discard;
270
-+ }
271
-+ }
272
-+ /* top-right */
273
-+ if (u_corners.y > 0.5) {
274
-+ if (p.x >= u_box_size.x - r && p.y <= r
275
-+ && distance(p, vec2(u_box_size.x - r, r)) > r) {
276
-+ discard;
277
-+ }
278
-+ }
279
-+ /* bottom-right */
280
-+ if (u_corners.z > 0.5) {
281
-+ if (p.x >= u_box_size.x - r && p.y >= u_box_size.y - r
282
-+ && distance(p, vec2(u_box_size.x - r, u_box_size.y - r)) > r) {
283
-+ discard;
284
-+ }
285
-+ }
286
-+ /* bottom-left */
287
-+ if (u_corners.w > 0.5) {
288
-+ if (p.x <= r && p.y >= u_box_size.y - r
289
-+ && distance(p, vec2(r, u_box_size.y - r)) > r) {
290
-+ discard;
291
-+ }
292
-+ }
293
-+}
294
-+
295
- void main() {
296
-+ rounded_clip();
297
- gl_FragColor = vec4(texture2D(tex, v_texcoord).rgb, 1.0) * alpha;
298
- }
299
-diff -ruN a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c
300
-+++ b/types/scene/wlr_scene.c 2026-08-31 12:49:04.007960213 +0200
301
-@@ -1124,6 +1124,18 @@
302
- }
303
- }
304
-
305
-+void wlr_scene_buffer_set_rounded_clip(struct wlr_scene_buffer *scene_buffer,
306
-+ float radius, uint32_t corners) {
307
-+ if (scene_buffer->clip_radius == radius
308
-+ && scene_buffer->clip_corners == corners) {
309
-+ return;
310
-+ }
311
-+ assert(radius >= 0);
312
-+ scene_buffer->clip_radius = radius;
313
-+ scene_buffer->clip_corners = corners;
314
-+ scene_node_update(&scene_buffer->node, NULL);
315
-+}
316
-+
317
- void wlr_scene_buffer_set_opacity(struct wlr_scene_buffer *scene_buffer,
318
- float opacity) {
319
- if (scene_buffer->opacity == opacity) {
320
-@@ -1499,6 +1511,26 @@
321
- case WLR_SCENE_NODE_BUFFER:;
322
- struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node);
323
-
324
-+ bool rounded = scene_buffer->clip_radius > 0
325
-+ && scene_buffer->clip_corners != 0;
326
-+ if (rounded) {
327
-+ /* Corner areas are no longer opaque: exclude them from the
328
-+ * opaque region so occlusion and blending stay correct. */
329
-+ int r = (int)scene_buffer->clip_radius;
330
-+ pixman_region32_t corners;
331
-+ pixman_region32_init(&corners);
332
-+ pixman_region32_union_rect(&corners, &corners,
333
-+ x, y, r, r);
334
-+ pixman_region32_union_rect(&corners, &corners,
335
-+ x + dst_box.width - r, y, r, r);
336
-+ pixman_region32_union_rect(&corners, &corners,
337
-+ x + dst_box.width - r, y + dst_box.height - r, r, r);
338
-+ pixman_region32_union_rect(&corners, &corners,
339
-+ x, y + dst_box.height - r, r, r);
340
-+ pixman_region32_subtract(&opaque, &opaque, &corners);
341
-+ pixman_region32_fini(&corners);
342
-+ }
343
-+
344
- if (scene_buffer->is_single_pixel_buffer) {
345
- // Render the buffer as a rect, this is likely to be more efficient
346
- wlr_render_pass_add_rect(data->render_pass, &(struct wlr_render_rect_options){
347
-@@ -1544,9 +1576,11 @@
348
- .dst_box = dst_box,
349
- .transform = transform,
350
- .clip = &render_region,
351
-+ .corner_radius = scene_buffer->clip_radius,
352
-+ .rounded_corners = scene_buffer->clip_corners,
353
- .alpha = &scene_buffer->opacity,
354
- .filter_mode = scene_buffer->filter_mode,
355
-- .blend_mode = !data->output->scene->calculate_visibility ||
356
-+ .blend_mode = rounded || !data->output->scene->calculate_visibility ||
357
- !pixman_region32_empty(&opaque) ?
358
- WLR_RENDER_BLEND_MODE_PREMULTIPLIED : WLR_RENDER_BLEND_MODE_NONE,
359
- .transfer_function = scene_buffer->transfer_function,