Skip to content

Commit

Permalink
ShellClients: Wait and reveal in sync on session start
Browse files Browse the repository at this point in the history
  • Loading branch information
leolost2605 committed Nov 29, 2024
1 parent d567f05 commit f20fe7a
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 13 deletions.
8 changes: 7 additions & 1 deletion src/ShellClients/HideTracker.vala
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,13 @@ public class Gala.HideTracker : Object {
});
}

private void update_overlap () {
/**
* Immediately updates the overlap. Usually {@link schedule_update} should be used instead which
* internally calls this but throttles it since it's a somewhat expensive operation.
* On very rare use cases however it is required to update immediately. In that case you can call
* this directly.
*/
public void update_overlap () {
overlap = false;
focus_overlap = false;
focus_maximized_overlap = false;
Expand Down
50 changes: 41 additions & 9 deletions src/ShellClients/PanelClone.vala
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public class Gala.PanelClone : Object {
private const int ANIMATION_DURATION = 250;

public WindowManager wm { get; construct; }
public unowned PanelWindow panel { get; construct; }
public unowned PanelWindow? panel { get; construct; }

public Pantheon.Desktop.HideMode hide_mode {
get {
Expand All @@ -35,6 +35,8 @@ public class Gala.PanelClone : Object {
private SafeWindowClone clone;
private Meta.WindowActor actor;

private bool window_ready = false;

private HideTracker? hide_tracker;

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

panel.window.unmanaging.connect (() => panel = null);

update_visible ();
update_clone_position ();

Idle.add_once (() => {
if (hide_mode == NEVER) {
show ();
} else {
hide_tracker.schedule_update ();
}
});
if (Meta.Util.is_wayland_compositor ()) {
// We want to wait for the window to be actually shown before revealing and then still a bit
// more since at the beginning it might be doing some relayouting (e.g. the dock only knows
// its size after it got a dbus connection to gala) which disrupts the animation.
panel.window.shown.connect (() => Timeout.add (100, () => {
if (panel == null) {
return Source.REMOVE; // The window was unmanaged while we were waiting
}

window_ready = true;
// In the best case we are ready before the manager stops waiting so the on_ready usually
// doesn't do anything. However if the client stalls for some reason or it crashed and has now
// been restarted it will show immediately.
on_ready ();

ShellClientsManager.get_instance ().notify_client_ready ();

return Source.REMOVE;
}));
} else {
// On X the window was already shown when it requests being a panel so just mark it ready
window_ready = true;
on_ready ();
ShellClientsManager.get_instance ().notify_client_ready ();
}

ShellClientsManager.get_instance ().notify["is-waiting"].connect (on_ready);
}

private void update_visible () {
Expand Down Expand Up @@ -142,7 +166,7 @@ public class Gala.PanelClone : Object {
}

private void show () {
if (!panel_hidden) {
if (!panel_hidden || !window_ready || ShellClientsManager.get_instance ().is_waiting) {
return;
}

Expand All @@ -163,4 +187,12 @@ public class Gala.PanelClone : Object {
panel_hidden = false;
}
}

private void on_ready () {
if (hide_mode == NEVER) {
show ();
} else {
hide_tracker.update_overlap ();
}
}
}
18 changes: 18 additions & 0 deletions src/ShellClients/ShellClientsManager.vala
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ public class Gala.ShellClientsManager : Object {
return instance;
}

public bool is_waiting { get; private set; default = true; } // On session start wait a bit for a synchronized and smooth reveal

public WindowManager wm { get; construct; }

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

private uint currently_starting_panels = 0;

private ShellClientsManager (WindowManager wm) {
Object (wm: wm);
}
Expand Down Expand Up @@ -149,6 +153,8 @@ public class Gala.ShellClientsManager : Object {
return;
}

currently_starting_panels++;

make_dock (window);
// TODO: Return if requested by window that's not a trusted client?

Expand Down Expand Up @@ -207,6 +213,18 @@ public class Gala.ShellClientsManager : Object {
return positioned;
}

//Called by the WM once it has initialized
public void notify_stage_ready () {
Timeout.add_seconds_once (5, () => is_waiting = false); // Failsafe if a client stalls to still show the others
}

// Called by the {@link PanelClone} when the window it manages is ready.
public void notify_client_ready () {
currently_starting_panels--;

is_waiting &= currently_starting_panels > 0;
}

//X11 only
private void parse_mutter_hints (Meta.Window window) requires (!Meta.Util.is_wayland_compositor ()) {
if (window.mutter_hints == null) {
Expand Down
6 changes: 3 additions & 3 deletions src/WindowManager.vala
Original file line number Diff line number Diff line change
Expand Up @@ -367,13 +367,13 @@ namespace Gala {

stage.show ();

Idle.add (() => {
Idle.add_once (() => {
// let the session manager move to the next phase
#if WITH_SYSTEMD
Systemd.Daemon.notify (true, "READY=1");
#endif
display.get_context ().notify_ready ();
return GLib.Source.REMOVE;
get_display ().get_context ().notify_ready ();
ShellClientsManager.get_instance ().notify_stage_ready ();
});
}

Expand Down

0 comments on commit f20fe7a

Please sign in to comment.