Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/DBus/EndSessionDialogServer.vala
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public class QuickSettings.EndSessionDialogServer : Object {
}

[DBus (visible = false)]
public signal void show_dialog (uint type, uint32 triggering_event_timestamp);
public signal void show_dialog (uint type);

public signal void confirmed_logout ();
public signal void confirmed_reboot ();
Expand All @@ -47,6 +47,6 @@ public class QuickSettings.EndSessionDialogServer : Object {
throw new DBusError.NOT_SUPPORTED ("Hibernate, suspend and hybrid sleep are not supported actions yet");
}

show_dialog (type, timestamp);
show_dialog (type);
}
}
45 changes: 45 additions & 0 deletions src/DBus/Login1Manager.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* SPDX-License-Identifier: GPL-3.0-or-later
* SPDX-FileCopyrightText: 2024-2025 elementary, Inc. (https://elementary.io)
*/

public class QuickSettings.Login1Manager : Object {
public struct UserInfo {
uint32 uid;
string user_name;
ObjectPath? user_object;
}

[DBus (name = "org.freedesktop.login1.Manager")]
public interface Login1ManagerInterface : Object {
public abstract void suspend (bool interactive) throws GLib.Error;
public abstract void reboot (bool interactive) throws GLib.Error;
public abstract void power_off (bool interactive) throws GLib.Error;
public abstract void reboot_with_flags (uint64 flags) throws GLib.Error;
public abstract void power_off_with_flags (uint64 flags) throws GLib.Error;

public abstract UserInfo[] list_users () throws GLib.Error;
public abstract string can_suspend () throws GLib.Error;
}

public Login1ManagerInterface object;

private static GLib.Once<Login1Manager> instance;
public static unowned Login1Manager get_default () {
return instance.once (() => { return new Login1Manager (); });
}

private Login1Manager () {}

construct {
try {
object = Bus.get_proxy_sync<Login1ManagerInterface> (
SYSTEM,
"org.freedesktop.login1",
"/org/freedesktop/login1"
);
} catch (Error e) {
critical (e.message);
}
}
}
22 changes: 0 additions & 22 deletions src/DBus/SystemInterface.vala

This file was deleted.

50 changes: 50 additions & 0 deletions src/Indicator.vala
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
public class QuickSettings.Indicator : Wingpanel.Indicator {
public Wingpanel.IndicatorManager.ServerType server_type { get; construct; }

private EndSessionDialog? current_dialog;
private PopoverWidget? popover_widget;

public Indicator (Wingpanel.IndicatorManager.ServerType server_type) {
Expand All @@ -23,6 +24,55 @@ public class QuickSettings.Indicator : Wingpanel.Indicator {
// Prevent a race that skips automatic resource loading
// https://github.com/elementary/wingpanel-indicator-bluetooth/issues/203
Gtk.IconTheme.get_default ().add_resource_path ("/org/elementary/wingpanel/icons");

EndSessionDialogServer.init ();
EndSessionDialogServer.get_default ().show_dialog.connect (
(type) => show_dialog ((EndSessionDialogType) type)
);
}

private void show_dialog (EndSessionDialogType type) {
((Gtk.Popover?) popover_widget?.get_ancestor (typeof (Gtk.Popover)))?.popdown ();

if (current_dialog != null) {
if (current_dialog.dialog_type != type) {
current_dialog.destroy ();
} else {
return;
}
}

unowned var server = EndSessionDialogServer.get_default ();

current_dialog = new EndSessionDialog (type);
current_dialog.destroy.connect (() => {
server.closed ();
current_dialog = null;
});

current_dialog.cancelled.connect (() => server.canceled ());
current_dialog.logout.connect (() => server.confirmed_logout ());
current_dialog.shutdown.connect (() => {
try {
// See https://www.freedesktop.org/software/systemd/man/latest/org.freedesktop.login1.html for flags values
// #define SD_LOGIND_ROOT_CHECK_INHIBITORS (UINT64_C(1) << 0) == 1
Login1Manager.get_default ().object.power_off_with_flags (1);
} catch (Error e) {
warning ("Unable to shutdown: %s", e.message);
}
});

current_dialog.reboot.connect (() => {
try {
// See https://www.freedesktop.org/software/systemd/man/latest/org.freedesktop.login1.html for flags values
// #define SD_LOGIND_KEXEC_REBOOT (UINT64_C(1) << 1) == 2
Login1Manager.get_default ().object.reboot_with_flags (2);
} catch (Error e) {
warning ("Unable to reboot: %s", e.message);
}
});

current_dialog.present ();
}

public override Gtk.Widget get_display_widget () {
Expand Down
56 changes: 22 additions & 34 deletions src/Services/UserManager.vala
Original file line number Diff line number Diff line change
Expand Up @@ -21,42 +21,34 @@ public enum UserState {
}

public class QuickSettings.UserManager : Object {
private const string LOGIN_IFACE = "org.freedesktop.login1";
private const string LOGIN_PATH = "/org/freedesktop/login1";

private static string active_user_real_name;
private static SystemInterface? login_proxy;

private static async void init_login_proxy () {
try {
login_proxy = yield Bus.get_proxy (BusType.SYSTEM, LOGIN_IFACE, LOGIN_PATH, DBusProxyFlags.NONE);
} catch (IOError e) {
critical ("Failed to create login1 dbus proxy: %s", e.message);
}
}
private static string? active_user_real_name;

public static async UserState get_user_state (uid_t uuid) {
if (login_proxy == null) {
yield init_login_proxy ();
}

try {
UserInfo[] users = login_proxy.list_users ();
var users = Login1Manager.get_default ().object.list_users ();
if (users == null) {
return UserState.OFFLINE;
}

foreach (UserInfo user in users) {
if (((uid_t) user.uid) == uuid) {
if (user.user_object == null) {
return UserState.OFFLINE;
}
UserInterface? user_interface = yield Bus.get_proxy (BusType.SYSTEM, LOGIN_IFACE, user.user_object, DBusProxyFlags.NONE);
if (user_interface == null) {
return UserState.OFFLINE;
}
return UserState.to_enum (user_interface.state);
foreach (var user in users) {
if (((uid_t) user.uid) != uuid) {
continue;
}

if (user.user_object == null) {
return UserState.OFFLINE;
}

var user_interface = yield Bus.get_proxy<UserInterface> (
SYSTEM,
"org.freedesktop.login1",
user.user_object
);
if (user_interface == null) {
return UserState.OFFLINE;
}

return UserState.to_enum (user_interface.state);
}

} catch (GLib.Error e) {
Expand All @@ -67,13 +59,9 @@ public class QuickSettings.UserManager : Object {
}

public static async UserState get_guest_state () {
if (login_proxy == null) {
return UserState.OFFLINE;
}

try {
UserInfo[] users = login_proxy.list_users ();
foreach (UserInfo user in users) {
var users = Login1Manager.get_default ().object.list_users ();
foreach (var user in users) {
var state = yield get_user_state (user.uid);
if (user.user_name.has_prefix ("guest-")
&& state == UserState.ACTIVE) {
Expand Down
88 changes: 8 additions & 80 deletions src/Widgets/SessionBox.vala
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@
public class QuickSettings.SessionBox : Gtk.Box {
public Wingpanel.IndicatorManager.ServerType server_type { get; construct; }

private EndSessionDialog? current_dialog = null;
private Gtk.Popover? popover;
private SystemInterface system_interface;

public SessionBox (Wingpanel.IndicatorManager.ServerType server_type) {
Object (server_type: server_type);
Expand Down Expand Up @@ -66,21 +64,17 @@ public class QuickSettings.SessionBox : Gtk.Box {

shutdown_button.clicked.connect (() => {
popover.popdown ();
show_dialog (EndSessionDialogType.RESTART);
EndSessionDialogServer.get_default ().show_dialog (EndSessionDialogType.RESTART);
});

setup_system_interface.begin ((obj, res) => {
system_interface = setup_system_interface.end (res);

suspend_button.clicked.connect (() => {
popover.popdown ();
suspend_button.clicked.connect (() => {
popover.popdown ();

try {
system_interface.suspend (true);
} catch (GLib.Error e) {
critical ("Unable to suspend: %s", e.message);
}
});
try {
Login1Manager.get_default ().object.suspend (true);
} catch (GLib.Error e) {
critical ("Unable to suspend: %s", e.message);
}
});

var keybinding_settings = new Settings ("org.gnome.settings-daemon.plugins.media-keys");
Expand All @@ -95,11 +89,6 @@ public class QuickSettings.SessionBox : Gtk.Box {
);
});

EndSessionDialogServer.init ();
EndSessionDialogServer.get_default ().show_dialog.connect (
(type, timestamp) => show_dialog ((EndSessionDialogType) type)
);

settings_button.clicked.connect (() => {
popover.popdown ();

Expand All @@ -111,15 +100,6 @@ public class QuickSettings.SessionBox : Gtk.Box {
});
}

private async SystemInterface? setup_system_interface () {
try {
return yield Bus.get_proxy (BusType.SYSTEM, "org.freedesktop.login1", "/org/freedesktop/login1");
} catch (IOError e) {
critical ("Unable to connect to the login interface: %s", e.message);
return null;
}
}

private async LockInterface? setup_lock_interface () {
try {
return yield Bus.get_proxy (BusType.SESSION, "org.gnome.ScreenSaver", "/org/gnome/ScreenSaver");
Expand All @@ -128,56 +108,4 @@ public class QuickSettings.SessionBox : Gtk.Box {
return null;
}
}

private void show_dialog (EndSessionDialogType type) {
popover.popdown ();

if (current_dialog != null) {
if (current_dialog.dialog_type != type) {
current_dialog.destroy ();
} else {
return;
}
}

unowned var server = EndSessionDialogServer.get_default ();

current_dialog = new EndSessionDialog (type) {
transient_for = (Gtk.Window) get_toplevel ()
};
current_dialog.destroy.connect (() => {
server.closed ();
current_dialog = null;
});

current_dialog.cancelled.connect (() => {
server.canceled ();
});

current_dialog.logout.connect (() => {
server.confirmed_logout ();
});

current_dialog.shutdown.connect (() => {
try {
// See https://www.freedesktop.org/software/systemd/man/latest/org.freedesktop.login1.html for flags values
// #define SD_LOGIND_ROOT_CHECK_INHIBITORS (UINT64_C(1) << 0) == 1
system_interface.power_off_with_flags (1);
} catch (Error e) {
warning ("Unable to shutdown: %s", e.message);
}
});

current_dialog.reboot.connect (() => {
try {
// See https://www.freedesktop.org/software/systemd/man/latest/org.freedesktop.login1.html for flags values
// #define SD_LOGIND_KEXEC_REBOOT (UINT64_C(1) << 1) == 2
system_interface.reboot_with_flags (2);
} catch (Error e) {
warning ("Unable to reboot: %s", e.message);
}
});

current_dialog.present ();
}
}
2 changes: 1 addition & 1 deletion src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ sources = [
'PopoverWidget.vala',
'DBus' / 'EndSessionDialogServer.vala',
'DBus' / 'LockInterface.vala',
'DBus' / 'Login1Manager.vala',
'DBus' / 'SeatInterface.vala',
'DBus' / 'SensorProxy.vala',
'DBus' / 'SessionInterface.vala',
'DBus' / 'SystemInterface.vala',
'DBus' / 'UserInterface.vala',
'Services' / 'UserManager.vala',
'Widgets' / 'AvatarButton.vala',
Expand Down