Skip to content
Open
Show file tree
Hide file tree
Changes from all 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 (() => 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