Skip to content

Commit a292379

Browse files
authored
Blur: Don't hardcode dock border-radius (#458)
Introduces RenderNodeWalker that walks through all the render nodes on startup and gets correct border radius
1 parent 1536d2b commit a292379

File tree

4 files changed

+227
-5
lines changed

4 files changed

+227
-5
lines changed

data/Application.css

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
dock {
77
background: alpha(@bg_color, 0.8);
8-
border-radius: 9px;
98
box-shadow:
109
inset 0 -1px 0 0 alpha(@highlight_color, 0.4),
1110
inset 0 1px 0 0 alpha(@highlight_color, 0.6),
@@ -15,7 +14,13 @@ dock {
1514
0 1px 3px alpha(black, 0.2),
1615
0 3px 9px alpha(black, 0.3);
1716
opacity: 0.6;
18-
padding: 9px;
17+
18+
border-radius: 9px;
19+
/* This is required to correctly get border-radius
20+
* If the size on startup is < border-radius * 2, the blur radius will be set incorrectly
21+
*/
22+
min-width: 18px;
23+
min-height: 18px;
1924
}
2025

2126
.reduce-transparency dock {

src/MainWindow.vala

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ public class Dock.MainWindow : Gtk.ApplicationWindow {
1616

1717
// Matches top margin in Launcher.css
1818
private const int TOP_MARGIN = 64;
19-
private const int BORDER_RADIUS = 9;
2019

2120
private Settings transparency_settings;
2221
private static Settings settings = new Settings ("io.elementary.dock");
@@ -26,6 +25,7 @@ public class Dock.MainWindow : Gtk.ApplicationWindow {
2625

2726
private WindowDragManager window_drag_manager;
2827
private bool initialized_blur = false;
28+
private int border_radius = 0;
2929

3030
class construct {
3131
set_css_name ("dock-window");
@@ -135,10 +135,19 @@ public class Dock.MainWindow : Gtk.ApplicationWindow {
135135
return;
136136
}
137137

138+
var new_snapshot = new Gtk.Snapshot ();
139+
snapshot (new_snapshot);
140+
141+
var widget_border_radius = RenderNodeWalker.get_first_border_radius (new_snapshot.free_to_node (), null);
142+
143+
if (widget_border_radius != null) {
144+
border_radius = widget_border_radius;
145+
}
146+
138147
initialized_blur = true;
139148

140149
if (panel != null) {
141-
panel.add_blur (0, 0, 0, BottomMargin.get_size (), BORDER_RADIUS);
150+
panel.add_blur (0, 0, 0, BottomMargin.get_size (), border_radius);
142151
} else {
143152
update_panel_x11 ();
144153
}
@@ -174,7 +183,7 @@ public class Dock.MainWindow : Gtk.ApplicationWindow {
174183
var value = "anchor=8:hide-mode=%d:restore-previous-region=1:visible-in-multitasking-view=1".printf (settings.get_enum ("autohide-mode"));
175184

176185
if (initialized_blur) {
177-
value += ":blur=0,0,0,%d,%d".printf (BottomMargin.get_size (), BORDER_RADIUS);
186+
value += ":blur=0,0,0,%d,%d".printf (BottomMargin.get_size (), border_radius);
178187
}
179188

180189
xdisplay.change_property (window, prop, X.XA_STRING, 8, 0, (uchar[]) value, value.length);

src/RenderNodeWalker.vala

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
/*
2+
* SPDX-License-Identifier: GPL-3.0
3+
* SPDX-FileCopyrightText: 2025 elementary, Inc. (https://elementary.io)
4+
*/
5+
6+
public class Dock.RenderNodeWalker : GLib.Object {
7+
public static int? get_first_border_radius (Gsk.RenderNode main_node, out int depth) {
8+
depth = 0;
9+
10+
var main_node_type = main_node.get_node_type ();
11+
12+
if (main_node_type == Gsk.RenderNodeType.ROUNDED_CLIP_NODE) {
13+
return (int) ((Gsk.RoundedClipNode) main_node).get_clip ().corner[0].width;
14+
}
15+
16+
depth++;
17+
18+
if (main_node_type == Gsk.RenderNodeType.CONTAINER_NODE) {
19+
var container_node = (Gsk.ContainerNode) main_node;
20+
21+
var min_child_depth = int.MAX;
22+
int? min_border_radius = null;
23+
24+
for (var i = 0; i < container_node.get_n_children (); i++) {
25+
var child_node = container_node.get_child (i);
26+
27+
int child_depth;
28+
var border_radius = get_first_border_radius (child_node, out child_depth);
29+
30+
if (child_depth < min_child_depth && border_radius != null) {
31+
min_child_depth = child_depth;
32+
min_border_radius = border_radius;
33+
}
34+
}
35+
36+
depth += min_child_depth;
37+
return min_border_radius;
38+
}
39+
40+
if (main_node_type == Gsk.RenderNodeType.GL_SHADER_NODE) {
41+
var gl_shader_node = (Gsk.GLShaderNode) main_node;
42+
43+
var min_child_depth = int.MAX;
44+
int? min_border_radius = null;
45+
46+
for (var i = 0; i < gl_shader_node.get_n_children (); i++) {
47+
var child_node = gl_shader_node.get_child (i);
48+
49+
int child_depth;
50+
var border_radius = get_first_border_radius (child_node, out child_depth);
51+
52+
if (child_depth < min_child_depth && border_radius != null) {
53+
min_child_depth = child_depth;
54+
min_border_radius = border_radius;
55+
}
56+
}
57+
58+
depth += min_child_depth;
59+
return min_border_radius;
60+
}
61+
62+
if (main_node_type == Gsk.RenderNodeType.TRANSFORM_NODE) {
63+
var child_node = ((Gsk.TransformNode) main_node).get_child ();
64+
65+
int child_depth;
66+
var border_radius = get_first_border_radius (child_node, out child_depth);
67+
68+
if (border_radius != null) {
69+
depth += child_depth;
70+
}
71+
72+
return border_radius;
73+
}
74+
75+
if (main_node_type == Gsk.RenderNodeType.OPACITY_NODE) {
76+
var child_node = ((Gsk.OpacityNode) main_node).get_child ();
77+
78+
int child_depth;
79+
var border_radius = get_first_border_radius (child_node, out child_depth);
80+
81+
if (border_radius != null) {
82+
depth += child_depth;
83+
}
84+
85+
return border_radius;
86+
}
87+
88+
if (main_node_type == Gsk.RenderNodeType.COLOR_MATRIX_NODE) {
89+
var child_node = ((Gsk.ColorMatrixNode) main_node).get_child ();
90+
91+
int child_depth;
92+
var border_radius = get_first_border_radius (child_node, out child_depth);
93+
94+
if (border_radius != null) {
95+
depth += child_depth;
96+
}
97+
98+
return border_radius;
99+
}
100+
101+
if (main_node_type == Gsk.RenderNodeType.REPEAT_NODE) {
102+
var child_node = ((Gsk.RepeatNode) main_node).get_child ();
103+
104+
int child_depth;
105+
var border_radius = get_first_border_radius (child_node, out child_depth);
106+
107+
if (border_radius != null) {
108+
depth += child_depth;
109+
}
110+
111+
return border_radius;
112+
}
113+
114+
if (main_node_type == Gsk.RenderNodeType.CLIP_NODE) {
115+
var child_node = ((Gsk.ClipNode) main_node).get_child ();
116+
117+
int child_depth;
118+
var border_radius = get_first_border_radius (child_node, out child_depth);
119+
120+
if (border_radius != null) {
121+
depth += child_depth;
122+
}
123+
124+
return border_radius;
125+
}
126+
127+
if (main_node_type == Gsk.RenderNodeType.SHADOW_NODE) {
128+
var child_node = ((Gsk.ShadowNode) main_node).get_child ();
129+
130+
int child_depth;
131+
var border_radius = get_first_border_radius (child_node, out child_depth);
132+
133+
if (border_radius != null) {
134+
depth += child_depth;
135+
}
136+
137+
return border_radius;
138+
}
139+
140+
if (main_node_type == Gsk.RenderNodeType.BLUR_NODE) {
141+
var child_node = ((Gsk.BlurNode) main_node).get_child ();
142+
143+
int child_depth;
144+
var border_radius = get_first_border_radius (child_node, out child_depth);
145+
146+
if (border_radius != null) {
147+
depth += child_depth;
148+
}
149+
150+
return border_radius;
151+
}
152+
153+
if (main_node_type == Gsk.RenderNodeType.DEBUG_NODE) {
154+
var child_node = ((Gsk.DebugNode) main_node).get_child ();
155+
156+
int child_depth;
157+
var border_radius = get_first_border_radius (child_node, out child_depth);
158+
159+
if (border_radius != null) {
160+
depth += child_depth;
161+
}
162+
163+
return border_radius;
164+
}
165+
166+
if (main_node_type == Gsk.RenderNodeType.FILL_NODE) {
167+
var child_node = ((Gsk.FillNode) main_node).get_child ();
168+
169+
int child_depth;
170+
var border_radius = get_first_border_radius (child_node, out child_depth);
171+
172+
if (border_radius != null) {
173+
depth += child_depth;
174+
}
175+
176+
return border_radius;
177+
}
178+
179+
if (main_node_type == Gsk.RenderNodeType.STROKE_NODE) {
180+
var child_node = ((Gsk.StrokeNode) main_node).get_child ();
181+
182+
int child_depth;
183+
var border_radius = get_first_border_radius (child_node, out child_depth);
184+
185+
if (border_radius != null) {
186+
depth += child_depth;
187+
}
188+
189+
return border_radius;
190+
}
191+
192+
if (main_node_type == Gsk.RenderNodeType.SUBSURFACE_NODE) {
193+
var child_node = ((Gsk.SubsurfaceNode) main_node).get_child ();
194+
195+
int child_depth;
196+
var border_radius = get_first_border_radius (child_node, out child_depth);
197+
198+
if (border_radius != null) {
199+
depth += child_depth;
200+
}
201+
202+
return border_radius;
203+
}
204+
205+
return null;
206+
}
207+
}

src/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ sources = [
55
'BottomMargin.vala',
66
'ItemManager.vala',
77
'MainWindow.vala',
8+
'RenderNodeWalker.vala',
89
'AppSystem' / 'App.vala',
910
'AppSystem' / 'AppSystem.vala',
1011
'AppSystem' / 'Launcher.vala',

0 commit comments

Comments
 (0)