Skip to content

Commit dc06dc4

Browse files
committed
Daemon/WindowListener: Prevent auto-suspend/idle when going fullscreen
Adds two methods to the gala daemon that are triggered by gala itself via dbus, because the WindowListener is not inside a GTK Application. One method used when any window goes fullscreen, to mark it as "inhibiting"automatic sleep to the session manager. The other method is to "unhibit" for the given window when it exits fullscreen. Multiple windows can inhibit sleeping, they all must exit fullscreen to restore auto-sleep. NB: If any window is fullscreen, auto sleep is disabled, even if it is not on the current virtual desktop. TODO: add gschema setting for disabling auto suspend when fullscreen
1 parent 4d1b6a7 commit dc06dc4

5 files changed

Lines changed: 175 additions & 2 deletions

File tree

daemon-gtk3/DBus.vala

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ public class Gala.Daemon.DBus : GLib.Object {
3232

3333
private List<MonitorLabel> monitor_labels = new List<MonitorLabel> ();
3434

35+
private Gee.HashMap<string, uint> suspend_cookies = new Gee.HashMap<string, uint> ();
36+
private Gee.HashMap<string, uint> idle_cookies = new Gee.HashMap<string, uint> ();
37+
3538
construct {
3639
Bus.watch_name (BusType.SESSION, DBUS_NAME, BusNameWatcherFlags.NONE, gala_appeared, lost_gala);
3740
}
@@ -114,6 +117,69 @@ public class Gala.Daemon.DBus : GLib.Object {
114117
}
115118
}
116119

120+
public void prevent_sleep (uint64 window_id) throws GLib.DBusError, GLib.IOError {
121+
unowned var application = (Gtk.Application) GLib.Application.get_default ();
122+
123+
// TODO add gschema setting for disabling auto suspend when fullscreen
124+
if (application != null) {
125+
var window_id_str = window_id.to_string ();
126+
info ("preventing auto-suspend and auto-idle because a window [%s] went fullscreen", window_id_str);
127+
// Ask the session manager to not automatically turn off the screen or put the system to sleep
128+
prevent_sleep_while_fullscreen (window_id_str, application);
129+
}
130+
}
131+
132+
public void unprevent_sleep (uint64 window_id) throws GLib.DBusError, GLib.IOError {
133+
unowned var application = (Gtk.Application) GLib.Application.get_default ();
134+
135+
// Inform the session manager we do not want to prevent turning off the screen or sleeping
136+
if (application != null) {
137+
var window_id_str = window_id.to_string ();
138+
info ("unpreventing auto-suspend and auto-idle by window [%s] because it exited fullscreen",
139+
window_id_str);
140+
141+
if (suspend_cookies.has_key (window_id_str)) {
142+
end_prevent_suspend_while_fullscreen (window_id_str, application);
143+
}
144+
if (idle_cookies.has_key (window_id_str)) {
145+
end_prevent_idle_while_fullscreen (window_id_str, application);
146+
}
147+
}
148+
}
149+
150+
private void prevent_sleep_while_fullscreen (string window_id_str, Gtk.Application application) {
151+
// If window was already marked as preventing fullscreen, unhinibit before inhibiting
152+
if (suspend_cookies.has_key (window_id_str)) {
153+
end_prevent_suspend_while_fullscreen (window_id_str, application);
154+
}
155+
if (idle_cookies.has_key (window_id_str)) {
156+
end_prevent_idle_while_fullscreen (window_id_str, application);
157+
}
158+
159+
suspend_cookies.set (window_id_str, application.inhibit (
160+
null,
161+
Gtk.ApplicationInhibitFlags.SUSPEND,
162+
"Prevent session from suspending while fullscreen"
163+
));
164+
idle_cookies.set (window_id_str, application.inhibit (
165+
null,
166+
Gtk.ApplicationInhibitFlags.IDLE,
167+
"Prevent session from idle while fullscreen"
168+
));
169+
}
170+
171+
private void end_prevent_suspend_while_fullscreen (string window_id_str, Gtk.Application application) {
172+
uint suspend_cookie = suspend_cookies.get (window_id_str);
173+
application.uninhibit (suspend_cookie);
174+
suspend_cookies.unset (window_id_str);
175+
}
176+
177+
private void end_prevent_idle_while_fullscreen (string window_id_str, Gtk.Application application) {
178+
uint idle_cookie = idle_cookies.get (window_id_str);
179+
application.uninhibit (idle_cookie);
180+
idle_cookies.unset (window_id_str);
181+
}
182+
117183
public void show_monitor_labels (MonitorLabelInfo[] label_infos) throws GLib.DBusError, GLib.IOError {
118184
hide_monitor_labels ();
119185

daemon/DBus.vala

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ public class Gala.Daemon.DBus : GLib.Object {
3636

3737
private List<MonitorLabel> monitor_labels = new List<MonitorLabel> ();
3838

39+
private Gee.HashMap<string, uint> suspend_cookies = new Gee.HashMap<string, uint> ();
40+
private Gee.HashMap<string, uint> idle_cookies = new Gee.HashMap<string, uint> ();
41+
3942
construct {
4043
Bus.watch_name (BusType.SESSION, DBUS_NAME, BusNameWatcherFlags.NONE, gala_appeared, lost_gala);
4144

@@ -155,6 +158,69 @@ public class Gala.Daemon.DBus : GLib.Object {
155158
});
156159
}
157160

161+
public void prevent_sleep (uint64 window_id) throws GLib.DBusError, GLib.IOError {
162+
unowned var application = (Gtk.Application) GLib.Application.get_default ();
163+
164+
// TODO add gschema setting for disabling auto suspend when fullscreen
165+
if (application != null) {
166+
var window_id_str = window_id.to_string ();
167+
info ("preventing auto-suspend and auto-idle because a window [%s] went fullscreen", window_id_str);
168+
// Ask the session manager to not automatically turn off the screen or put the system to sleep
169+
prevent_sleep_while_fullscreen (window_id_str, application);
170+
}
171+
}
172+
173+
public void unprevent_sleep (uint64 window_id) throws GLib.DBusError, GLib.IOError {
174+
unowned var application = (Gtk.Application) GLib.Application.get_default ();
175+
176+
// Inform the session manager we do not want to prevent turning off the screen or sleeping
177+
if (application != null) {
178+
var window_id_str = window_id.to_string ();
179+
info ("unpreventing auto-suspend and auto-idle by window [%s] because it exited fullscreen",
180+
window_id_str);
181+
182+
if (suspend_cookies.has_key (window_id_str)) {
183+
end_prevent_suspend_while_fullscreen (window_id_str, application);
184+
}
185+
if (idle_cookies.has_key (window_id_str)) {
186+
end_prevent_idle_while_fullscreen (window_id_str, application);
187+
}
188+
}
189+
}
190+
191+
private void prevent_sleep_while_fullscreen (string window_id_str, Gtk.Application application) {
192+
// If window was already marked as preventing fullscreen, unhinibit before inhibiting
193+
if (suspend_cookies.has_key (window_id_str)) {
194+
end_prevent_suspend_while_fullscreen (window_id_str, application);
195+
}
196+
if (idle_cookies.has_key (window_id_str)) {
197+
end_prevent_idle_while_fullscreen (window_id_str, application);
198+
}
199+
200+
suspend_cookies.set (window_id_str, application.inhibit (
201+
null,
202+
Gtk.ApplicationInhibitFlags.SUSPEND,
203+
"Prevent session from suspending while fullscreen"
204+
));
205+
idle_cookies.set (window_id_str, application.inhibit (
206+
null,
207+
Gtk.ApplicationInhibitFlags.IDLE,
208+
"Prevent session from idle while fullscreen"
209+
));
210+
}
211+
212+
private void end_prevent_suspend_while_fullscreen (string window_id_str, Gtk.Application application) {
213+
uint suspend_cookie = suspend_cookies.get (window_id_str);
214+
application.uninhibit (suspend_cookie);
215+
suspend_cookies.unset (window_id_str);
216+
}
217+
218+
private void end_prevent_idle_while_fullscreen (string window_id_str, Gtk.Application application) {
219+
uint idle_cookie = idle_cookies.get (window_id_str);
220+
application.uninhibit (idle_cookie);
221+
idle_cookies.unset (window_id_str);
222+
}
223+
158224
public void show_monitor_labels (MonitorLabelInfo[] label_infos) throws GLib.DBusError, GLib.IOError {
159225
hide_monitor_labels ();
160226

src/DaemonManager.vala

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ public class Gala.DaemonManager : GLib.Object {
1414
public interface Daemon: GLib.Object {
1515
public abstract async void show_window_menu (WindowFlags flags, int width, int height, int x, int y) throws Error;
1616
public abstract async void show_desktop_menu (int display_width, int display_height, int x, int y) throws Error;
17+
public abstract async void prevent_sleep (uint64 window_id) throws Error;
18+
public abstract async void unprevent_sleep (uint64 window_id) throws Error;
1719
}
1820

1921
public Meta.Display display { get; construct; }
@@ -128,4 +130,32 @@ public class Gala.DaemonManager : GLib.Object {
128130
warning ("Error invoking MenuManager: %s", e.message);
129131
}
130132
}
133+
134+
public async void prevent_sleep (uint64 window_id) {
135+
if (daemon_proxy == null) {
136+
return;
137+
}
138+
139+
try {
140+
debug ("Sending dbus message to daemon to prevent auto-suspend and auto-idle because a window [%" +
141+
uint64.FORMAT + "] went fullscreen", window_id);
142+
yield daemon_proxy.prevent_sleep (window_id);
143+
} catch (Error e) {
144+
warning ("Error invoking MenuManager: %s", e.message);
145+
}
146+
}
147+
148+
public async void unprevent_sleep (uint64 window_id) {
149+
if (daemon_proxy == null) {
150+
return;
151+
}
152+
153+
try {
154+
debug ("Sending dbus message to daemon to unprevent auto-suspend and auto-idle by window [%" +
155+
uint64.FORMAT + "] because it exited fullscreen", window_id);
156+
yield daemon_proxy.unprevent_sleep (window_id);
157+
} catch (Error e) {
158+
warning ("Error invoking MenuManager: %s", e.message);
159+
}
160+
}
131161
}

src/WindowListener.vala

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,16 @@ public class Gala.WindowListener : Object {
2222
}
2323

2424
private static WindowListener? instance = null;
25+
private static unowned DaemonManager shared_daemon_manager;
2526

26-
public static void init (Meta.Display display) {
27+
public static void init (Meta.Display display, DaemonManager daemon_manager) {
2728
if (instance != null)
2829
return;
2930

3031
instance = new WindowListener ();
3132

33+
shared_daemon_manager = daemon_manager;
34+
3235
#if HAS_MUTTER48
3336
unowned List<Meta.WindowActor> actors = display.get_compositor ().get_window_actors ();
3437
#else
@@ -92,6 +95,14 @@ public class Gala.WindowListener : Object {
9295
break;
9396
case "fullscreen":
9497
window_fullscreen_changed (window);
98+
if (window.fullscreen) {
99+
// Only prevent sleep for windows on the main monitor
100+
if (window.is_on_primary_monitor ()) {
101+
shared_daemon_manager.prevent_sleep (window.get_id ());
102+
}
103+
} else {
104+
shared_daemon_manager.unprevent_sleep (window.get_id ());
105+
}
95106
break;
96107
}
97108
}

src/WindowManager.vala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ namespace Gala {
206206
private void show_stage () {
207207
unowned Meta.Display display = get_display ();
208208

209-
WindowListener.init (display);
209+
WindowListener.init (display, daemon_manager);
210210
keyboard_manager = new KeyboardManager (display);
211211
window_tracker = new WindowTracker ();
212212
WindowStateSaver.init (window_tracker);

0 commit comments

Comments
 (0)