Skip to content

Commit 79e3566

Browse files
committed
Introduce WorkspaceHideTracker
1 parent b56a2bf commit 79e3566

File tree

2 files changed

+146
-1
lines changed

2 files changed

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

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)