diff --git a/files/usr/share/cinnamon/applets/power@cinnamon.org/applet.js b/files/usr/share/cinnamon/applets/power@cinnamon.org/applet.js index 17fa358f91..46d99892ef 100644 --- a/files/usr/share/cinnamon/applets/power@cinnamon.org/applet.js +++ b/files/usr/share/cinnamon/applets/power@cinnamon.org/applet.js @@ -12,8 +12,6 @@ const Settings = imports.ui.settings; const BrightnessBusName = "org.cinnamon.SettingsDaemon.Power.Screen"; const KeyboardBusName = "org.cinnamon.SettingsDaemon.Power.Keyboard"; -const PowerProfilesBusName = "net.hadess.PowerProfiles"; -const PowerProfilesBusPath = "/net/hadess/PowerProfiles"; const CSD_BACKLIGHT_NOT_SUPPORTED_CODE = 1; @@ -32,17 +30,6 @@ const POWER_PROFILES = { "performance": _("Performance") }; -const PowerProfilesInterface = ` - - - - - - -`; - -const PowerProfilesProxy = Gio.DBusProxy.makeProxyWrapper(PowerProfilesInterface); - function deviceLevelToString(level) { switch (level) { case UPDeviceLevel.FULL: @@ -402,12 +389,36 @@ class CinnamonPowerApplet extends Applet.TextIconApplet { this.menu.addMenuItem(this.keyboard); try { - this._profilesProxy = new PowerProfilesProxy(Gio.DBus.system, PowerProfilesBusName, PowerProfilesBusPath); - } catch (error) { - this._profilesProxy = null; + // Hadess interface + let PowerProfilesInterface = ` + + + + + + + `; + let PowerProfilesProxy = Gio.DBusProxy.makeProxyWrapper(PowerProfilesInterface); + this._profilesProxy = new PowerProfilesProxy(Gio.DBus.system, "net.haess.PowerProfiles", "/net/hadess/PowerProfiles"); + // Upower if hadess doesn't work.. + if (!this._profilesProxy.Profiles) { + // UPower interface + let PowerProfilesInterface = ` + + + + + + + `; + let PowerProfilesProxy = Gio.DBusProxy.makeProxyWrapper(PowerProfilesInterface); + this._profilesProxy = new PowerProfilesProxy(Gio.DBus.system, "org.freedesktop.UPower.PowerProfiles", "/org/freedesktop/UPower/PowerProfiles"); + } + } catch { + this._profilesProxy = null; } - - if (this._profilesProxy.Profiles) { + + if (this._profilesProxy && this._profilesProxy.Profiles) { this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); this.contentSection = new PopupMenu.PopupMenuSection(); diff --git a/files/usr/share/cinnamon/cinnamon-settings/modules/cs_power.py b/files/usr/share/cinnamon/cinnamon-settings/modules/cs_power.py index 1a9ee9105d..46ed6bd038 100755 --- a/files/usr/share/cinnamon/cinnamon-settings/modules/cs_power.py +++ b/files/usr/share/cinnamon/cinnamon-settings/modules/cs_power.py @@ -45,6 +45,12 @@ (0, _("Never")) ] +POWER_PROFILES = { + "power-saver": _("Power Saver"), + "balanced": _("Balanced"), + "performance": _("Performance") +} + (UP_ID, UP_VENDOR, UP_MODEL, UP_TYPE, UP_ICON, UP_PERCENTAGE, UP_STATE, UP_BATTERY_LEVEL, UP_SECONDS) = range(9) try: @@ -140,7 +146,7 @@ def on_module_selected(self): power_page = SettingsPage() - section = power_page.add_section(_("Power Options")) + section = power_page.add_section(_("Power options")) lid_options, button_power_options, critical_options, can_suspend, can_hybrid_sleep, can_hibernate = get_available_options(self.up_client) @@ -198,6 +204,26 @@ def on_module_selected(self): self.sth_switch.content_widget.connect("notify::active", self.on_sth_toggled) section.add_row(self.sth_switch) + # Power mode + connection = Gio.bus_get_sync(Gio.BusType.SYSTEM, None) + proxy = None + profiles = None + for dbus_name in ["net.hadess.PowerProfiles", "org.freedesktop.UPower.PowerProfiles"]: + try: + dbus_path = "/" + dbus_name.replace(".", "/") + proxy = Gio.DBusProxy.new_sync(connection, Gio.DBusProxyFlags.NONE, None, + dbus_name, dbus_path, "org.freedesktop.DBus.Properties", None) + profiles = proxy.Get('(ss)', dbus_name, "Profiles") + print(f"Found power profiles on Dbus at {dbus_name}") + break + except: + pass + + if profiles: + combo = PowerModeComboBox(proxy, dbus_name, profiles) + combo.set_tooltip_text(_("Power mode controls the power usage of your computer. It can impact performance, battery life and fan noise.")) + section.add_row(combo) + # Batteries self.battery_page = SettingsPage() @@ -294,7 +320,6 @@ def build_battery_page(self, *args): # UPowerGlib segfaults when trying to get device. Use CSD instead devices = self.csd_power_proxy.GetDevices() - have_primary = False ups_as_primary = False have_keyboard = False @@ -817,3 +842,70 @@ def on_my_setting_changed2(self, *args): def add_to_size_group(self, group): group.add_widget(self.content_widget1) group.add_widget(self.content_widget2) + + +class PowerModeComboBox(SettingsWidget): + def __init__(self, proxy, dbus_name, profiles, dep_key=None, size_group=None): + super(PowerModeComboBox, self).__init__(dep_key=dep_key) + + self.proxy = proxy + self.dbus_name = dbus_name + + try: + profiles_options = [] + for profile in profiles: + name = profile["Profile"] + label = name + if name in POWER_PROFILES.keys(): + label = POWER_PROFILES[name] + profiles_options.append([name, label]) + + self.option_map = {} + + self.label = Gtk.Label.new(_("Power mode")) + self.model = Gtk.ListStore(str, str) + + for option in profiles_options: + iter = self.model.insert_before(None, None) + self.model.set_value(iter, 0, option[0]) + self.model.set_value(iter, 1, option[1]) + self.option_map[option[0]] = iter + + self.content_widget = Gtk.ComboBox.new_with_model(self.model) + renderer_text = Gtk.CellRendererText() + self.content_widget.pack_start(renderer_text, True) + self.content_widget.add_attribute(renderer_text, "text", 1) + + self.pack_start(self.label, False, False, 0) + self.pack_end(self.content_widget, False, True, 0) + + self.content_widget.connect('changed', self.on_my_value_changed) + self.proxy.connect('g-signal', self.on_dbus_changed) + self.on_my_setting_changed() + + if size_group: + self.add_to_size_group(size_group) + except GLib.Error as e: + print(f"Power profiles options not available: {e.message}") + + def on_my_value_changed(self, widget): + tree_iter = widget.get_active_iter() + if tree_iter is not None: + profile = self.model[tree_iter][0] + value = GLib.Variant.new_string(profile) + self.proxy.Set('(ssv)', self.dbus_name, "ActiveProfile", value) + + def on_dbus_changed(self, proxy, sender, signal, params): + if signal == "PropertiesChanged": + self.on_my_setting_changed() + + def on_my_setting_changed(self): + try: + active_profile = self.proxy.Get('(ss)', self.dbus_name, "ActiveProfile") + self.content_widget.set_active_iter(self.option_map[active_profile]) + except Exception as e: + print(e) + self.content_widget.set_active_iter(None) + + def add_to_size_group(self, group): + group.add_widget(self.content_widget)