Skip to content

Commit b344862

Browse files
committed
Merge branch 'main' into lenemter/shorten-keybinding-lines
2 parents 27edd58 + c839164 commit b344862

File tree

249 files changed

+12761
-8668
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

249 files changed

+12761
-8668
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,4 @@ po/Rules-quot
4747
po/stamp-po
4848
src/gala
4949
build
50+
debian

daemon-gtk3/WindowMenu.vala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,12 +174,12 @@ public class Gala.Daemon.WindowMenu : Gtk.Menu {
174174
SignalHandler.unblock (always_on_top, always_on_top_sid);
175175
SignalHandler.unblock (on_visible_workspace, on_visible_workspace_sid);
176176

177-
move_right.sensitive = !on_visible_workspace.active;
177+
move_right.sensitive = !on_visible_workspace.active && Gala.WindowFlags.ALLOWS_MOVE_RIGHT in flags;
178178
if (move_right.sensitive) {
179179
move_right_accellabel.accel_string = keybind_settings.get_strv ("move-to-workspace-right")[0];
180180
}
181181

182-
move_left.sensitive = !on_visible_workspace.active;
182+
move_left.sensitive = !on_visible_workspace.active && Gala.WindowFlags.ALLOWS_MOVE_LEFT in flags;
183183
if (move_left.sensitive) {
184184
move_left_accellabel.accel_string = keybind_settings.get_strv ("move-to-workspace-left")[0];
185185
}

daemon/DBus.vala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@ public enum Gala.WindowFlags {
3636
ALWAYS_ON_TOP,
3737
ON_ALL_WORKSPACES,
3838
CAN_CLOSE,
39-
IS_TILED
39+
IS_TILED,
40+
ALLOWS_MOVE_LEFT,
41+
ALLOWS_MOVE_RIGHT
4042
}
4143

4244
[DBus (name = "org.pantheon.gala")]

daemon/WindowMenu.vala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,12 +200,12 @@ public class Gala.Daemon.WindowMenu : Gtk.Popover {
200200
SignalHandler.unblock (always_on_top, always_on_top_sid);
201201
SignalHandler.unblock (on_visible_workspace, on_visible_workspace_sid);
202202

203-
move_right.sensitive = !on_visible_workspace.active;
203+
move_right.sensitive = !on_visible_workspace.active && Gala.WindowFlags.ALLOWS_MOVE_RIGHT in flags;
204204
if (move_right.sensitive) {
205205
move_right_accellabel.accel_string = keybind_settings.get_strv ("move-to-workspace-right")[0];
206206
}
207207

208-
move_left.sensitive = !on_visible_workspace.active;
208+
move_left.sensitive = !on_visible_workspace.active && Gala.WindowFlags.ALLOWS_MOVE_LEFT in flags;
209209
if (move_left.sensitive) {
210210
move_left_accellabel.accel_string = keybind_settings.get_strv ("move-to-workspace-left")[0];
211211
}

data/gala.gschema.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,11 @@
194194
<summary>Cycle to previous keyboard layout</summary>
195195
<description></description>
196196
</key>
197+
<key type="as" name="toggle-multitasking-view">
198+
<default><![CDATA[['<Super>Down','<Super>s']]]></default>
199+
<summary>Toggle multitasking view</summary>
200+
<description></description>
201+
</key>
197202
<key type="as" name="pip">
198203
<default><![CDATA[['<Super>f']]]></default>
199204
<summary>The shortcut to enable picture-in-picture window</summary>

data/gala.metainfo.xml.in

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,26 +27,74 @@
2727
<update_contact>contact_at_elementary.io</update_contact>
2828

2929
<releases>
30-
<release version="8.2.0" date="2025-03-25" urgency="medium">
30+
<release version="8.2.3" date="2025-05-20" urgency="medium">
31+
<description>
32+
<p>Improvements:</p>
33+
<ul>
34+
<li>Updated translations</li>
35+
</ul>
36+
</description>
37+
<issues>
38+
<issue url="https://github.com/elementary/gala/issues/2400">Switching workspaces makes the windows move down with multiple monitors</issue>
39+
</issues>
40+
</release>
41+
42+
<release version="8.2.2" date="2025-05-17" urgency="medium">
43+
<description>
44+
<p>Improvements:</p>
45+
<ul>
46+
<li>Updated translations</li>
47+
</ul>
48+
</description>
49+
<issues>
50+
<issue url="https://github.com/elementary/gala/issues/2387">Update broke secondary display workspace</issue>
51+
</issues>
52+
</release>
53+
54+
<release version="8.2.1" date="2025-05-15" urgency="medium">
55+
<description>
56+
<p>Improvements:</p>
57+
<ul>
58+
<li>Updated translations</li>
59+
</ul>
60+
</description>
61+
<issues>
62+
<issue url="https://github.com/elementary/gala/issues/2322">Workspace Switch</issue>
63+
<issue url="https://github.com/elementary/gala/issues/2357">Very rough shadows around the workspace switcher in HiDPI mode.</issue>
64+
<issue url="https://github.com/elementary/gala/issues/2380">ShadowEffect: corner radius doesn't use monitor scale</issue>
65+
</issues>
66+
</release>
67+
68+
<release version="8.2.0" date="2025-05-13" urgency="medium">
3169
<description>
3270
<p>Improvements:</p>
3371
<ul>
3472
<li>Updated translations</li>
3573
<li>Window state is now saved on sleep and shutdown</li>
74+
<li>Remove scaling effect from menus</li>
75+
<li>Swipe up to close windows in Multitasking View</li>
3676
</ul>
3777
</description>
3878
<issues>
3979
<issue url="https://github.com/elementary/gala/issues/137">Send a persistent notification after taking a screenshot</issue>
4080
<issue url="https://github.com/elementary/gala/issues/321">Use org.gnome.desktop.interface enable-animations</issue>
4181
<issue url="https://github.com/elementary/gala/issues/544">Multitasking View. Wingpanel shows for brief moment if a fullscreen wokspace is selected after coming from a wokspace that shows the wingpanel.</issue>
82+
<issue url="https://github.com/elementary/gala/issues/823">Check for redacted font</issue>
4283
<issue url="https://github.com/elementary/gala/issues/898">Super+Number. When workspace doesn't exist, switch to last workspace instead.</issue>
84+
<issue url="https://github.com/elementary/gala/issues/1121">Postman app is captured partially (and without a shadow)</issue>
4385
<issue url="https://github.com/elementary/gala/issues/1202">Touchpad desktop switching gesture is sometimes unresponsive</issue>
86+
<issue url="https://github.com/elementary/gala/issues/1235">Overview window title should follow keyboard focus</issue>
4487
<issue url="https://github.com/elementary/gala/issues/1661">Better post-screenshot animation</issue>
4588
<issue url="https://github.com/elementary/gala/issues/2114">Wrong context menu placement</issue>
89+
<issue url="https://github.com/elementary/gala/issues/2172">Override redirect Popup menu type window under Xwayland can not be displayed on the second XMapWindow</issue>
4690
<issue url="https://github.com/elementary/gala/issues/2199">Swiping in the multitasking view can close applications</issue>
4791
<issue url="https://github.com/elementary/gala/issues/2260">Ghost of window on another workspace appears when cancelling workspace swipe</issue>
4892
<issue url="https://github.com/elementary/gala/issues/2267">Dock crash may crash Gala</issue>
4993
<issue url="https://github.com/elementary/gala/issues/2279">Can't reveal dock when animations are disabled</issue>
94+
<issue url="https://github.com/elementary/gala/issues/2294">Unlocking firewall settings leads to crash</issue>
95+
<issue url="https://github.com/elementary/gala/issues/2341">Lutris Flatpak crashes gala with GE setup</issue>
96+
<issue url="https://github.com/elementary/gala/issues/2366">Menus only show once</issue>
97+
<issue url="https://github.com/elementary/portals/issues/97">False detection of "background activity" for some Flatpak apps</issue>
5098
</issues>
5199
</release>
52100

lib/ShadowEffect.vala

Lines changed: 103 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
*/
66

77
public class Gala.ShadowEffect : Clutter.Effect {
8+
private const float INITIAL_OPACITY = 0.25f;
9+
810
private class Shadow {
911
public int users;
1012
public Cogl.Texture texture;
@@ -38,13 +40,13 @@ public class Gala.ShadowEffect : Clutter.Effect {
3840
_css_class = value;
3941
switch (value) {
4042
case "workspace-switcher":
41-
shadow_size = 6;
43+
shadow_size = 3;
4244
break;
4345
case "window":
44-
shadow_size = 55;
46+
shadow_size = 26;
4547
break;
4648
default:
47-
shadow_size = 18;
49+
shadow_size = 9;
4850
break;
4951
}
5052
}
@@ -83,9 +85,9 @@ public class Gala.ShadowEffect : Clutter.Effect {
8385
}
8486
}
8587

86-
private Cogl.Texture? get_shadow (Cogl.Context context, int width, int height, int shadow_size) {
88+
private Cogl.Texture? get_shadow (Cogl.Context context, int width, int height, int shadow_size, int border_radius) {
8789
var old_key = current_key;
88-
current_key = "%ix%i:%i".printf (width, height, shadow_size);
90+
current_key = "%ix%i:%i:%i".printf (width, height, shadow_size, border_radius);
8991
if (old_key == current_key) {
9092
return null;
9193
}
@@ -100,58 +102,26 @@ public class Gala.ShadowEffect : Clutter.Effect {
100102
return shadow.texture;
101103
}
102104

103-
// fill a new texture for this size
104-
var buffer = new Drawing.BufferSurface (width, height);
105-
Drawing.Utilities.cairo_rounded_rectangle (
106-
buffer.context,
107-
shadow_size,
108-
shadow_size,
109-
width - shadow_size * 2,
110-
height - shadow_size * 2,
111-
border_radius
112-
);
113-
114-
buffer.context.set_source_rgba (0, 0, 0, 0.7);
115-
buffer.context.fill ();
116-
117-
buffer.exponential_blur (shadow_size / 2);
118-
119-
var surface = new Cairo.ImageSurface (Cairo.Format.ARGB32, width, height);
120-
var cr = new Cairo.Context (surface);
121-
cr.set_source_surface (buffer.surface, 0, 0);
122-
cr.paint ();
123-
124-
cr.save ();
125-
cr.set_operator (Cairo.Operator.CLEAR);
126-
var size = shadow_size * monitor_scale;
127-
Drawing.Utilities.cairo_rounded_rectangle (cr, size, size, actor.width, actor.height, border_radius);
128-
cr.fill ();
129-
cr.restore ();
130-
131-
try {
132-
var texture = new Cogl.Texture2D.from_data (context, width, height, Cogl.PixelFormat.BGRA_8888_PRE,
133-
surface.get_stride (), surface.get_data ());
105+
var texture = get_shadow_texture (context, width, height, shadow_size, border_radius);
106+
if (texture != null) {
134107
shadow_cache.@set (current_key, new Shadow (texture));
135-
136-
return texture;
137-
} catch (Error e) {
138-
debug (e.message);
139-
return null;
140108
}
109+
110+
return texture;
141111
}
142112

143113
public override void paint (Clutter.PaintNode node, Clutter.PaintContext context, Clutter.EffectPaintFlags flags) {
144114
var bounding_box = get_bounding_box ();
145115
var width = (int) (bounding_box.x2 - bounding_box.x1);
146116
var height = (int) (bounding_box.y2 - bounding_box.y1);
147117

148-
var shadow = get_shadow (context.get_framebuffer ().get_context (), width, height, shadow_size);
118+
var shadow = get_shadow (context.get_framebuffer ().get_context (), width, height, Utils.scale_to_int (shadow_size, monitor_scale), Utils.scale_to_int (border_radius, monitor_scale));
149119
if (shadow != null) {
150120
pipeline.set_layer_texture (0, shadow);
151121
}
152122

153-
var opacity = actor.get_paint_opacity () * shadow_opacity / 255.0f;
154-
var alpha = Cogl.Color.from_4f (1.0f, 1.0f, 1.0f, opacity / 255.0f);
123+
var opacity = actor.get_paint_opacity () * shadow_opacity * INITIAL_OPACITY / 255.0f / 255.0f;
124+
var alpha = Cogl.Color.from_4f (1.0f, 1.0f, 1.0f, opacity);
155125
alpha.premultiply ();
156126

157127
pipeline.set_color (alpha);
@@ -162,9 +132,9 @@ public class Gala.ShadowEffect : Clutter.Effect {
162132
}
163133

164134
private Clutter.ActorBox get_bounding_box () {
165-
var size = shadow_size * monitor_scale;
166-
var bounding_box = Clutter.ActorBox ();
135+
var size = Utils.scale_to_int (shadow_size, monitor_scale);
167136

137+
var bounding_box = Clutter.ActorBox ();
168138
bounding_box.set_origin (-size, -size);
169139
bounding_box.set_size (actor.width + size * 2, actor.height + size * 2);
170140

@@ -221,4 +191,91 @@ public class Gala.ShadowEffect : Clutter.Effect {
221191
return Source.REMOVE;
222192
});
223193
}
194+
195+
private Cogl.Texture? get_shadow_texture (Cogl.Context context, int width, int height, int shadow_size, int corner_radius) {
196+
var data = new uint8[width * height];
197+
198+
// use fast Gaussian blur approximation
199+
var precomputed_colors = new uint8[shadow_size + 1];
200+
for (var i = 0; i <= shadow_size; i++) {
201+
var normalized = (double) i / shadow_size;
202+
precomputed_colors[i] = (uint8) (normalized * normalized * (3.0 - 2.0 * normalized) * 255.0);
203+
}
204+
205+
var total_offset = shadow_size + corner_radius;
206+
207+
var target_row = height - total_offset;
208+
for (var row = total_offset; row < target_row; row++) {
209+
var current_row = row * width;
210+
var current_row_end = current_row + width - 1;
211+
for (int i = 0; i <= shadow_size; i++) {
212+
var current_color = precomputed_colors[i];
213+
214+
data[current_row + i] = current_color;
215+
data[current_row_end - i] = current_color;
216+
}
217+
}
218+
219+
var target_col = width - total_offset;
220+
for (var row = 0; row <= shadow_size; row++) {
221+
var current_row = row * width;
222+
var end_row = (height - row) * width - 1;
223+
var current_color = precomputed_colors[row];
224+
225+
for (var col = total_offset; col < target_col; col++) {
226+
data[current_row + col] = current_color;
227+
data[end_row - col] = current_color;
228+
}
229+
}
230+
231+
var target_square = shadow_size + corner_radius;
232+
for (var y = 0; y < target_square; y++) {
233+
var current_row = width * y;
234+
var current_row_end = current_row + width - 1;
235+
var end_row = (height - 1 - y) * width;
236+
var end_row_end = end_row + width - 1;
237+
238+
var dy = target_square - y;
239+
var dy_squared = dy * dy;
240+
241+
for (var x = 0; x < target_square; x++) {
242+
var dx = target_square - x;
243+
var squared_distance = dx * dx + dy_squared;
244+
245+
if (squared_distance > target_square * target_square) {
246+
continue;
247+
}
248+
249+
if (squared_distance >= corner_radius * corner_radius) {
250+
double sin, cos;
251+
Math.sincos (Math.atan2 (dy, dx), out sin, out cos);
252+
253+
var real_dx = dx - corner_radius * cos;
254+
var real_dy = dy - corner_radius * sin;
255+
256+
// use fast Gaussian blur approximation
257+
var normalized = (double) Math.sqrt (real_dx * real_dx + real_dy * real_dy) / shadow_size;
258+
var current_color = (uint8) (1.0 - normalized * normalized * (3.0 - 2.0 * normalized) * 255.0);
259+
260+
// when we're very close to the rounded corner, our real_distance can be wrong (idk why).
261+
// If we're here, we're not inside the corner yet and that means we must draw something
262+
if (current_color == 0) {
263+
current_color = 255;
264+
}
265+
266+
data[current_row + x] = current_color;
267+
data[current_row_end - x] = current_color;
268+
data[end_row + x] = current_color;
269+
data[end_row_end - x] = current_color;
270+
}
271+
}
272+
}
273+
274+
try {
275+
return new Cogl.Texture2D.from_data (context, width, height, Cogl.PixelFormat.A_8, width, data);
276+
} catch (Error e) {
277+
warning ("ShadowEffect: Couldn't create texture");
278+
return null;
279+
}
280+
}
224281
}

0 commit comments

Comments
 (0)