Skip to content

Commit 4948ae6

Browse files
committed
Merge branch 'main' into leolost/windowclone-allocate
2 parents 60daa5c + 9d0e352 commit 4948ae6

12 files changed

+354
-423
lines changed
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/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

0 commit comments

Comments
 (0)