Skip to content

Commit eea8754

Browse files
authored
Merge branch 'main' into lenemter/search-apps-by-pid-more-cleverly
2 parents d4594a2 + 9d0e352 commit eea8754

16 files changed

+414
-482
lines changed

lib/Utils.vala

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,5 +400,50 @@ namespace Gala {
400400

401401
return texture;
402402
}
403+
404+
private static HashTable<Meta.Window, X.XserverRegion?> regions = new HashTable<Meta.Window, X.XserverRegion?> (null, null);
405+
406+
public static void x11_set_window_pass_through (Meta.Window window) {
407+
unowned var x11_display = window.display.get_x11_display ();
408+
409+
#if HAS_MUTTER46
410+
var x_window = x11_display.lookup_xwindow (window);
411+
#else
412+
var x_window = window.get_xwindow ();
413+
#endif
414+
unowned var xdisplay = x11_display.get_xdisplay ();
415+
416+
regions[window] = X.Fixes.create_region_from_window (xdisplay, x_window, 0);
417+
418+
X.Xrectangle rect = {};
419+
420+
var region = X.Fixes.create_region (xdisplay, {rect});
421+
422+
X.Fixes.set_window_shape_region (xdisplay, x_window, 2, 0, 0, region);
423+
424+
X.Fixes.destroy_region (xdisplay, region);
425+
}
426+
427+
public static void x11_unset_window_pass_through (Meta.Window window) {
428+
unowned var x11_display = window.display.get_x11_display ();
429+
430+
#if HAS_MUTTER46
431+
var x_window = x11_display.lookup_xwindow (window);
432+
#else
433+
var x_window = window.get_xwindow ();
434+
#endif
435+
unowned var xdisplay = x11_display.get_xdisplay ();
436+
437+
var region = regions[window];
438+
439+
if (region == null) {
440+
return;
441+
}
442+
443+
X.Fixes.set_window_shape_region (xdisplay, x_window, 2, 0, 0, region);
444+
445+
regions.remove (window);
446+
X.Fixes.destroy_region (xdisplay, region);
447+
}
403448
}
404449
}
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
/*
2+
* Copyright 2024 elementary, Inc. (https://elementary.io)
3+
* SPDX-License-Identifier: GPL-3.0-or-later
4+
*
5+
* Authored by: Leonhard Kargl <[email protected]>
6+
*/
7+
8+
/**
9+
* A class that will animate a property of a {@link Clutter.Actor} one to one with a gesture or
10+
* with easing without a gesture. Respects the enable animation setting.
11+
*/
12+
public class Gala.GesturePropertyTransition : Object {
13+
public delegate void DoneCallback ();
14+
15+
/**
16+
* The actor whose property will be animated.
17+
*/
18+
public Clutter.Actor actor { get; construct; }
19+
20+
public GestureTracker gesture_tracker { get; construct; }
21+
22+
/**
23+
* The property that will be animated. To be properly animated it has to be marked as
24+
* animatable in the Clutter documentation and should be numeric.
25+
*/
26+
public string property { get; construct; }
27+
28+
/**
29+
* The starting value of the animation or null to use the current value. The value
30+
* has to be of the same type as the property.
31+
*/
32+
public Value? from_value { get; construct set; }
33+
34+
/**
35+
* The value to animate to. It has to be of the same type as the property.
36+
*/
37+
public Value to_value { get; construct set; }
38+
39+
/**
40+
* If not null this can be used to have an intermediate step before animating back to the origin.
41+
* Therefore using this makes mostly sense if {@link to_value} equals {@link from_value}.
42+
* This is mostly used for the nudge animations when trying to switch workspaces where there isn't one anymore.
43+
*/
44+
public Value? intermediate_value { get; construct; }
45+
46+
/**
47+
* This is the from value that's actually used when calculating the animation movement.
48+
* If {@link from_value} isn't null this will be the same, otherwise it will be set to the current
49+
* value of the target property, when calling {@link start}.
50+
*/
51+
private Value actual_from_value;
52+
53+
private DoneCallback? done_callback;
54+
55+
public GesturePropertyTransition (
56+
Clutter.Actor actor,
57+
GestureTracker gesture_tracker,
58+
string property,
59+
Value? from_value,
60+
Value to_value,
61+
Value? intermediate_value = null
62+
) {
63+
Object (
64+
actor: actor,
65+
gesture_tracker: gesture_tracker,
66+
property: property,
67+
from_value: from_value,
68+
to_value: to_value,
69+
intermediate_value: intermediate_value
70+
);
71+
}
72+
73+
/**
74+
* Starts animating the property from {@link from_value} to {@link to_value}. If with_gesture is true
75+
* it will connect to the gesture trackers signals and animate according to the input finishing with an easing
76+
* to the final position. If with_gesture is false it will just ease to the {@link to_value}.
77+
* #this will keep itself alive until the animation finishes so it is safe to immediatly unref it after creation and calling start.
78+
*
79+
* @param done_callback a callback for when the transition finishes. It is guaranteed to be called exactly once.
80+
*/
81+
public void start (bool with_gesture, owned DoneCallback? done_callback = null) {
82+
ref ();
83+
84+
this.done_callback = (owned) done_callback;
85+
86+
Value current_value = {};
87+
actor.get_property (property, ref current_value);
88+
89+
actual_from_value = from_value ?? current_value;
90+
91+
if (actual_from_value.type () != current_value.type ()) {
92+
warning ("from_value of type %s is not of the same type as the property %s which is %s. Can't animate.", from_value.type_name (), property, current_value.type_name ());
93+
finish ();
94+
return;
95+
}
96+
97+
if (current_value.type () != to_value.type ()) {
98+
warning ("to_value of type %s is not of the same type as the property %s which is %s. Can't animate.", to_value.type_name (), property, current_value.type_name ());
99+
finish ();
100+
return;
101+
}
102+
103+
GestureTracker.OnBegin on_animation_begin = () => {
104+
actor.set_property (property, actual_from_value);
105+
};
106+
107+
GestureTracker.OnUpdate on_animation_update = (percentage) => {
108+
var animation_value = GestureTracker.animation_value (value_to_float (actual_from_value), value_to_float (intermediate_value ?? to_value), percentage);
109+
actor.set_property (property, value_from_float (animation_value));
110+
};
111+
112+
GestureTracker.OnEnd on_animation_end = (percentage, cancel_action, calculated_duration) => {
113+
actor.save_easing_state ();
114+
actor.set_easing_mode (EASE_OUT_QUAD);
115+
actor.set_easing_duration (AnimationsSettings.get_animation_duration (calculated_duration));
116+
actor.set_property (property, cancel_action ? actual_from_value : to_value);
117+
actor.restore_easing_state ();
118+
119+
unowned var transition = actor.get_transition (property);
120+
if (transition == null) {
121+
finish ();
122+
} else {
123+
transition.stopped.connect (finish);
124+
}
125+
};
126+
127+
if (with_gesture && AnimationsSettings.get_enable_animations ()) {
128+
gesture_tracker.connect_handlers (on_animation_begin, on_animation_update, on_animation_end);
129+
} else {
130+
on_animation_begin (0);
131+
if (intermediate_value != null) {
132+
actor.save_easing_state ();
133+
actor.set_easing_mode (EASE_OUT_QUAD);
134+
actor.set_easing_duration (AnimationsSettings.get_animation_duration (gesture_tracker.min_animation_duration));
135+
actor.set_property (property, intermediate_value);
136+
actor.restore_easing_state ();
137+
138+
unowned var transition = actor.get_transition (property);
139+
if (transition == null) {
140+
on_animation_end (1, false, gesture_tracker.min_animation_duration);
141+
} else {
142+
transition.stopped.connect (() => on_animation_end (1, false, gesture_tracker.min_animation_duration));
143+
}
144+
} else {
145+
on_animation_end (1, false, gesture_tracker.min_animation_duration);
146+
}
147+
}
148+
}
149+
150+
private void finish () {
151+
if (done_callback != null) {
152+
done_callback ();
153+
}
154+
155+
unref ();
156+
}
157+
158+
private float value_to_float (Value val) {
159+
Value float_val = Value (typeof (float));
160+
if (val.transform (ref float_val)) {
161+
return float_val.get_float ();
162+
}
163+
164+
critical ("Non numeric property specified");
165+
return 0;
166+
}
167+
168+
private Value value_from_float (float f) {
169+
var float_val = Value (typeof (float));
170+
float_val.set_float (f);
171+
172+
var val = Value (actual_from_value.type ());
173+
174+
if (!float_val.transform (ref val)) {
175+
warning ("Failed to transform float to give type");
176+
}
177+
178+
return val;
179+
}
180+
}

src/PantheonShell.vala

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -243,25 +243,7 @@ namespace Gala {
243243
return;
244244
}
245245

246-
Meta.Side side = TOP;
247-
switch (anchor) {
248-
case TOP:
249-
break;
250-
251-
case BOTTOM:
252-
side = BOTTOM;
253-
break;
254-
255-
case LEFT:
256-
side = LEFT;
257-
break;
258-
259-
case RIGHT:
260-
side = RIGHT;
261-
break;
262-
}
263-
264-
ShellClientsManager.get_instance ().set_anchor (window, side);
246+
ShellClientsManager.get_instance ().set_anchor (window, anchor);
265247
}
266248

267249
internal static void focus_panel (Wl.Client client, Wl.Resource resource) {

src/ShellClients/DelegateActor.vala

Lines changed: 0 additions & 42 deletions
This file was deleted.

src/ShellClients/HideTracker.vala

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,7 @@ public class Gala.HideTracker : Object {
1616
public Meta.Display display { get; construct; }
1717
public unowned PanelWindow panel { get; construct; }
1818

19-
private Pantheon.Desktop.HideMode _hide_mode = NEVER;
20-
public Pantheon.Desktop.HideMode hide_mode {
21-
get {
22-
return _hide_mode;
23-
}
24-
set {
25-
_hide_mode = value;
26-
27-
setup_barrier ();
28-
}
29-
}
19+
public Pantheon.Desktop.HideMode hide_mode { get; set; }
3020

3121
private Clutter.PanAction pan_action;
3222

@@ -97,6 +87,16 @@ public class Gala.HideTracker : Object {
9787
pan_action.pan.connect (on_pan);
9888

9989
display.get_stage ().add_action_full ("panel-swipe-gesture", CAPTURE, pan_action);
90+
91+
panel.notify["anchor"].connect (setup_barrier);
92+
93+
var monitor_manager = display.get_context ().get_backend ().get_monitor_manager ();
94+
monitor_manager.monitors_changed.connect (() => {
95+
setup_barrier (); //Make sure barriers are still on the primary monitor
96+
schedule_update ();
97+
});
98+
99+
setup_barrier ();
100100
}
101101

102102
#if !HAS_MUTTER45
@@ -171,7 +171,7 @@ public class Gala.HideTracker : Object {
171171
continue;
172172
}
173173

174-
if (!panel.get_custom_window_rect ().overlap (window.get_frame_rect ())) {
174+
if (!panel.window.get_frame_rect ().overlap (window.get_frame_rect ())) {
175175
continue;
176176
}
177177

src/ShellClients/PanelClone.vala

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ public class Gala.PanelClone : Object {
4848
actor = (Meta.WindowActor) panel.window.get_compositor_private ();
4949
// WindowActor position and Window position aren't necessarily the same.
5050
// The clone needs the actor position
51-
panel.delegate_actor.notify["x"].connect (update_clone_position);
52-
panel.delegate_actor.notify["y"].connect (update_clone_position);
51+
actor.notify["x"].connect (update_clone_position);
52+
actor.notify["y"].connect (update_clone_position);
5353
// Actor visibility might be changed by something else e.g. workspace switch
5454
// but we want to keep it in sync with us
5555
actor.notify["visible"].connect (update_visible);
@@ -97,7 +97,7 @@ public class Gala.PanelClone : Object {
9797
switch (panel.anchor) {
9898
case TOP:
9999
case BOTTOM:
100-
return panel.delegate_actor.x;
100+
return actor.x;
101101
default:
102102
return 0;
103103
}
@@ -106,9 +106,9 @@ public class Gala.PanelClone : Object {
106106
private float calculate_clone_y (bool hidden) {
107107
switch (panel.anchor) {
108108
case TOP:
109-
return hidden ? panel.delegate_actor.y - actor.height : panel.delegate_actor.y;
109+
return hidden ? actor.y - actor.height : actor.y;
110110
case BOTTOM:
111-
return hidden ? panel.delegate_actor.y + actor.height : panel.delegate_actor.y;
111+
return hidden ? actor.y + actor.height : actor.y;
112112
default:
113113
return 0;
114114
}
@@ -128,7 +128,7 @@ public class Gala.PanelClone : Object {
128128
panel_hidden = true;
129129

130130
if (!Meta.Util.is_wayland_compositor ()) {
131-
panel.window.move_frame (false, DelegateActor.OUT_OF_BOUNDS, DelegateActor.OUT_OF_BOUNDS);
131+
Utils.x11_set_window_pass_through (panel.window);
132132
}
133133

134134
if (panel.anchor != TOP && panel.anchor != BOTTOM) {
@@ -151,7 +151,7 @@ public class Gala.PanelClone : Object {
151151
}
152152

153153
if (!Meta.Util.is_wayland_compositor ()) {
154-
panel.window.move_frame (false, panel.delegate_actor.actual_x, panel.delegate_actor.actual_y);
154+
Utils.x11_unset_window_pass_through (panel.window);
155155
}
156156

157157
clone.save_easing_state ();

0 commit comments

Comments
 (0)