Skip to content

Commit 77df187

Browse files
committed
Introduce WorkspaceHideTracker
1 parent 79c9ff1 commit 77df187

File tree

2 files changed

+153
-1
lines changed

2 files changed

+153
-1
lines changed
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
/*
2+
* SPDX-License-Identifier: GPL-3.0-or-later
3+
* SPDX-FileCopyrightText: 2025 elementary, Inc. (https://elementary.io)
4+
*/
5+
6+
public class Gala.WorkspaceHideTracker : Object {
7+
public delegate double ComputeWorkspaceProgress (Meta.Workspace workspace);
8+
9+
public signal void switching_workspace_progress_updated (double new_progress);
10+
public signal void window_state_changed_progress_updated (double new_progress);
11+
12+
public Meta.Display display { private get; construct; }
13+
14+
private ComputeWorkspaceProgress? compute_func = null;
15+
private double switch_workspace_progress = 0.0;
16+
private double[] workspace_hide_progress_cache = {};
17+
18+
public WorkspaceHideTracker (Meta.Display display) {
19+
Object (display: display);
20+
}
21+
22+
construct {
23+
display.list_all_windows ().foreach (setup_window);
24+
display.window_created.connect (setup_window);
25+
26+
unowned var monitor_manager = display.get_context ().get_backend ().get_monitor_manager ();
27+
monitor_manager.monitors_changed.connect (recalculate_all_workspaces);
28+
29+
unowned var workspace_manager = display.get_workspace_manager ();
30+
workspace_manager.workspace_added.connect (recalculate_all_workspaces);
31+
workspace_manager.workspace_removed.connect (recalculate_all_workspaces);
32+
33+
recalculate_all_workspaces ();
34+
}
35+
36+
public void set_compute_func (ComputeWorkspaceProgress? new_compute_func) {
37+
compute_func = new_compute_func;
38+
}
39+
40+
private void setup_window (Meta.Window window) {
41+
window.notify["window-type"].connect (on_window_type_changed);
42+
43+
if (!Utils.get_window_is_normal (window)) {
44+
return;
45+
}
46+
47+
if (window.on_all_workspaces) {
48+
recalculate_all_workspaces ();
49+
} else {
50+
recalculate_workspace (window);
51+
}
52+
53+
window.position_changed.connect (recalculate_workspace);
54+
window.size_changed.connect (recalculate_workspace);
55+
window.workspace_changed.connect (recalculate_all_workspaces);
56+
window.focused.connect (recalculate_workspace);
57+
window.notify["on-all-workspaces"].connect (recalculate_all_workspaces);
58+
window.notify["fullscreen"].connect (recalculate_workspace_pspec);
59+
window.notify["minimized"].connect (recalculate_workspace_pspec);
60+
window.notify["above"].connect (recalculate_workspace_pspec);
61+
window.unmanaged.connect (recalculate_workspace);
62+
}
63+
64+
private void on_window_type_changed (Object obj, ParamSpec pspec) {
65+
var window = (Meta.Window) obj;
66+
67+
window.notify["window-type"].disconnect (on_window_type_changed);
68+
window.position_changed.disconnect (recalculate_workspace);
69+
window.size_changed.disconnect (recalculate_workspace);
70+
window.workspace_changed.disconnect (recalculate_all_workspaces);
71+
window.focused.disconnect (recalculate_workspace);
72+
window.notify["on-all-workspaces"].disconnect (recalculate_all_workspaces);
73+
window.notify["fullscreen"].disconnect (recalculate_workspace_pspec);
74+
window.notify["minimized"].disconnect (recalculate_workspace_pspec);
75+
window.notify["above"].disconnect (recalculate_workspace_pspec);
76+
window.unmanaged.disconnect (recalculate_workspace);
77+
78+
setup_window (window);
79+
}
80+
81+
82+
/**
83+
* Updates progress, it will do nothing if update_type is COMMIT or action is not SWITCH_WORKSPACE.
84+
*/
85+
public void update (GestureTarget.UpdateType update_type, GestureAction action, double progress) {
86+
if (action != SWITCH_WORKSPACE || update_type == COMMIT) {
87+
return;
88+
}
89+
90+
var new_switch_workspace_progress = progress.abs ();
91+
92+
// When number of workspaces changes, we get phantom SWITCH_WORKSPACE propagations
93+
if (switch_workspace_progress == new_switch_workspace_progress) {
94+
return;
95+
}
96+
97+
switch_workspace_progress = new_switch_workspace_progress;
98+
switching_workspace_progress_updated (get_hidden_progress ());
99+
}
100+
101+
private double get_hidden_progress () {
102+
var n_workspaces = workspace_hide_progress_cache.length;
103+
104+
var left_workspace = int.max ((int) Math.floor (switch_workspace_progress), 0);
105+
var right_workspace = int.min ((int) Math.ceil (switch_workspace_progress), n_workspaces - 1);
106+
107+
var relative_progress = switch_workspace_progress - left_workspace;
108+
109+
return (
110+
workspace_hide_progress_cache[left_workspace] * (1 - relative_progress) +
111+
workspace_hide_progress_cache[right_workspace] * relative_progress
112+
);
113+
}
114+
115+
/**
116+
* Trigger recalculation of all workspaces
117+
*/
118+
public void recalculate_all_workspaces () {
119+
unowned var workspace_manager = display.get_workspace_manager ();
120+
workspace_hide_progress_cache = new double[workspace_manager.n_workspaces];
121+
foreach (unowned var workspace in workspace_manager.get_workspaces ()) {
122+
internal_recalculate_workspace (workspace, false);
123+
}
124+
125+
window_state_changed_progress_updated (get_hidden_progress ());
126+
}
127+
128+
private void internal_recalculate_workspace (Meta.Workspace? workspace, bool send_signal) {
129+
if (
130+
workspace == null ||
131+
workspace.workspace_index >= workspace_hide_progress_cache.length ||
132+
compute_func == null
133+
) {
134+
return;
135+
}
136+
137+
workspace_hide_progress_cache[workspace.workspace_index] = compute_func (workspace);
138+
139+
if (send_signal) {
140+
window_state_changed_progress_updated (get_hidden_progress ());
141+
}
142+
}
143+
144+
private void recalculate_workspace (Meta.Window window) {
145+
internal_recalculate_workspace (window.get_workspace (), true);
146+
}
147+
148+
private void recalculate_workspace_pspec (Object obj, ParamSpec pspec) {
149+
internal_recalculate_workspace (((Meta.Window) obj).get_workspace (), true);
150+
}
151+
}

lib/meson.build

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ gala_lib_sources = files(
3636
'Gestures/ScrollBackend.vala',
3737
'Gestures/SpringTimeline.vala',
3838
'Gestures/ToucheggBackend.vala',
39-
'Gestures/TouchpadBackend.vala'
39+
'Gestures/TouchpadBackend.vala',
40+
'Gestures/WorkspaceHideTracker.vala'
4041
) + gala_common_enums
4142

4243
gala_resources = gnome.compile_resources(

0 commit comments

Comments
 (0)