Skip to content

Commit 87b7321

Browse files
committed
ShellClients: Wait and reveal in sync on session start
1 parent 0117141 commit 87b7321

File tree

4 files changed

+69
-13
lines changed

4 files changed

+69
-13
lines changed

src/ShellClients/HideTracker.vala

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,13 @@ public class Gala.HideTracker : Object {
147147
});
148148
}
149149

150-
private void update_overlap () {
150+
/**
151+
* Immediately updates the overlap. Usually {@link schedule_update} should be used instead which
152+
* internally calls this but throttles it since it's a somewhat expensive operation.
153+
* On very rare use cases however it is required to update immediately. In that case you can call
154+
* this directly.
155+
*/
156+
public void update_overlap () {
151157
overlap = false;
152158
focus_overlap = false;
153159
focus_maximized_overlap = false;

src/ShellClients/PanelClone.vala

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ public class Gala.PanelClone : Object {
99
private const int ANIMATION_DURATION = 250;
1010

1111
public WindowManager wm { get; construct; }
12-
public unowned PanelWindow panel { get; construct; }
12+
public unowned PanelWindow? panel { get; construct; }
1313

1414
public Pantheon.Desktop.HideMode hide_mode {
1515
get {
@@ -35,6 +35,8 @@ public class Gala.PanelClone : Object {
3535
private SafeWindowClone clone;
3636
private Meta.WindowActor actor;
3737

38+
private bool window_ready = false;
39+
3840
private HideTracker? hide_tracker;
3941

4042
public PanelClone (WindowManager wm, PanelWindow panel) {
@@ -67,16 +69,38 @@ public class Gala.PanelClone : Object {
6769
// https://github.com/elementary/gala/issues/2080
6870
panel.window.focused.connect (update_visible);
6971

72+
panel.window.unmanaging.connect (() => panel = null);
73+
7074
update_visible ();
7175
update_clone_position ();
7276

73-
Idle.add_once (() => {
74-
if (hide_mode == NEVER) {
75-
show ();
76-
} else {
77-
hide_tracker.schedule_update ();
78-
}
79-
});
77+
if (Meta.Util.is_wayland_compositor ()) {
78+
// We want to wait for the window to be actually shown before revealing and then still a bit
79+
// more since at the beginning it might be doing some relayouting (e.g. the dock only knows
80+
// its size after it got a dbus connection to gala) which disrupts the animation.
81+
panel.window.shown.connect (() => Timeout.add (100, () => {
82+
if (panel == null) {
83+
return Source.REMOVE; // The window was unmanaged while we were waiting
84+
}
85+
86+
window_ready = true;
87+
// In the best case we are ready before the manager stops waiting so the on_ready usually
88+
// doesn't do anything. However if the client stalls for some reason or it crashed and has now
89+
// been restarted it will show immediately.
90+
on_ready ();
91+
92+
ShellClientsManager.get_instance ().notify_client_ready ();
93+
94+
return Source.REMOVE;
95+
}));
96+
} else {
97+
// On X the window was already shown when it requests being a panel so just mark it ready
98+
window_ready = true;
99+
on_ready ();
100+
ShellClientsManager.get_instance ().notify_client_ready ();
101+
}
102+
103+
ShellClientsManager.get_instance ().notify["is-waiting"].connect (on_ready);
80104
}
81105

82106
private void update_visible () {
@@ -142,7 +166,7 @@ public class Gala.PanelClone : Object {
142166
}
143167

144168
private void show () {
145-
if (!panel_hidden) {
169+
if (!panel_hidden || !window_ready || ShellClientsManager.get_instance ().is_waiting) {
146170
return;
147171
}
148172

@@ -163,4 +187,12 @@ public class Gala.PanelClone : Object {
163187
panel_hidden = false;
164188
}
165189
}
190+
191+
private void on_ready () {
192+
if (hide_mode == NEVER) {
193+
show ();
194+
} else {
195+
hide_tracker.update_overlap ();
196+
}
197+
}
166198
}

src/ShellClients/ShellClientsManager.vala

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ public class Gala.ShellClientsManager : Object {
2020
return instance;
2121
}
2222

23+
public bool is_waiting { get; private set; default = true; } // On session start wait a bit for a synchronized and smooth reveal
24+
2325
public WindowManager wm { get; construct; }
2426

2527
private NotificationsClient notifications_client;
@@ -28,6 +30,8 @@ public class Gala.ShellClientsManager : Object {
2830
private GLib.HashTable<Meta.Window, PanelWindow> panel_windows = new GLib.HashTable<Meta.Window, PanelWindow> (null, null);
2931
private GLib.HashTable<Meta.Window, WindowPositioner> positioned_windows = new GLib.HashTable<Meta.Window, WindowPositioner> (null, null);
3032

33+
private uint currently_starting_panels = 0;
34+
3135
private ShellClientsManager (WindowManager wm) {
3236
Object (wm: wm);
3337
}
@@ -149,6 +153,8 @@ public class Gala.ShellClientsManager : Object {
149153
return;
150154
}
151155

156+
currently_starting_panels++;
157+
152158
make_dock (window);
153159
// TODO: Return if requested by window that's not a trusted client?
154160

@@ -207,6 +213,18 @@ public class Gala.ShellClientsManager : Object {
207213
return positioned;
208214
}
209215

216+
//Called by the WM once it has initialized
217+
public void notify_stage_ready () {
218+
Timeout.add_seconds_once (5, () => is_waiting = false); // Failsafe if a client stalls to still show the others
219+
}
220+
221+
// Called by the {@link PanelClone} when the window it manages is ready.
222+
public void notify_client_ready () {
223+
currently_starting_panels--;
224+
225+
is_waiting &= currently_starting_panels > 0;
226+
}
227+
210228
//X11 only
211229
private void parse_mutter_hints (Meta.Window window) requires (!Meta.Util.is_wayland_compositor ()) {
212230
if (window.mutter_hints == null) {

src/WindowManager.vala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -367,13 +367,13 @@ namespace Gala {
367367

368368
stage.show ();
369369

370-
Idle.add (() => {
370+
Idle.add_once (() => {
371371
// let the session manager move to the next phase
372372
#if WITH_SYSTEMD
373373
Systemd.Daemon.notify (true, "READY=1");
374374
#endif
375-
display.get_context ().notify_ready ();
376-
return GLib.Source.REMOVE;
375+
get_display ().get_context ().notify_ready ();
376+
ShellClientsManager.get_instance ().notify_stage_ready ();
377377
});
378378
}
379379

0 commit comments

Comments
 (0)