Blame SOURCES/add-power-profiles-menu.patch

0999a2
From 2103c5fcf994bb6aebd978553b338436e85fa7ed Mon Sep 17 00:00:00 2001
0999a2
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
0999a2
Date: Wed, 7 Jul 2021 22:05:25 +0200
0999a2
Subject: [PATCH 1/2] status/powerProfiles: Add power mode selection
0999a2
0999a2
Settings' power panel gained support for switchable power profiles
0999a2
in GNOME 40. It's useful to have that functionality more readily
0999a2
available, so expose it in the system status menu as well.
0999a2
0999a2
https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/3944
0999a2
0999a2
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1907>
0999a2
---
0999a2
 .../net.hadess.PowerProfiles.xml              |  76 ++++++++++++
0999a2
 .../gnome-shell-dbus-interfaces.gresource.xml |   1 +
0999a2
 js/js-resources.gresource.xml                 |   1 +
0999a2
 js/ui/panel.js                                |   4 +
0999a2
 js/ui/status/powerProfiles.js                 | 111 ++++++++++++++++++
0999a2
 po/POTFILES.in                                |   1 +
0999a2
 6 files changed, 194 insertions(+)
0999a2
 create mode 100644 data/dbus-interfaces/net.hadess.PowerProfiles.xml
0999a2
 create mode 100644 js/ui/status/powerProfiles.js
0999a2
0999a2
diff --git a/data/dbus-interfaces/net.hadess.PowerProfiles.xml b/data/dbus-interfaces/net.hadess.PowerProfiles.xml
0999a2
new file mode 100644
0999a2
index 000000000..fce04a86d
0999a2
--- /dev/null
0999a2
+++ b/data/dbus-interfaces/net.hadess.PowerProfiles.xml
0999a2
@@ -0,0 +1,76 @@
0999a2
+
0999a2
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
0999a2
+
0999a2
+<node>
0999a2
+
0999a2
+  
0999a2
+      net.hadess.PowerProfiles:
0999a2
+      @short_description: Power Profiles daemon
0999a2
+
0999a2
+      The power-profiles-daemon API is meant to be used by parts of the OS or
0999a2
+      desktop environment to switch system power profiles based on user choice,
0999a2
+      or user intent.
0999a2
+
0999a2
+      OS components would typically use the "Profiles" property to construct
0999a2
+      their UI (2 or 3 profiles available), and monitor the "ActiveProfile"
0999a2
+      and the "PerformanceInhibited" properties to update that UI. The UI
0999a2
+      would try to set the "ActiveProfile" property if the user selected
0999a2
+      a different one.
0999a2
+
0999a2
+      Note that the reason why the project exists and how it is different from
0999a2
+      existing projects is explained <ulink href=" https://gitlab.freedesktop.org/hadess/power-profiles-daemon/-/blob/master/README.md">
0999a2
+      in the project's README file</ulink>.
0999a2
+
0999a2
+      The object path will be "/net/hadess/PowerProfiles".
0999a2
+  -->
0999a2
+  <interface name="net.hadess.PowerProfiles">
0999a2
+    
0999a2
+        ActiveProfile:
0999a2
+
0999a2
+        The type of the currently active profile. It might change automatically
0999a2
+        if the "performance" profile was selected but it got inhibited, in which
0999a2
+        case the "PerformanceInhibited" property will reflect the reason.
0999a2
+    -->
0999a2
+    <property name="ActiveProfile" type="s" access="readwrite"/>
0999a2
+
0999a2
+    
0999a2
+        PerformanceInhibited:
0999a2
+
0999a2
+        This will be set if the performance power profile is unavailable, with
0999a2
+        the value being used to identify the reason for unavailability. As new
0999a2
+        reasons can be added, it is recommended that front-ends show a generic
0999a2
+        reason if they do not recognise the value. Possible values are:
0999a2
+        - "lap-detected" (the computer is sitting on the user's lap)
0999a2
+        - "high-operating-temperature" (the computer is close to overheating)
0999a2
+        - "" (the empty string, if not inhibited)
0999a2
+    -->
0999a2
+    <property name="PerformanceInhibited" type="s" access="read"/>
0999a2
+
0999a2
+    
0999a2
+        Profiles:
0999a2
+
0999a2
+        An array of key-pair values representing each profile. The key named
0999a2
+        "Driver" (s) identifies the power-profiles-daemon backend code used to
0999a2
+        implement the profile.
0999a2
+
0999a2
+        The key named "Profile" (s) will be one of:
0999a2
+        - "power-saver" (battery saving profile)
0999a2
+        - "balanced" (the default  profile)
0999a2
+        - "performance" (a profile that does not care about noise or battery consumption)
0999a2
+
0999a2
+        Only one of each type of profile will be listed, with the daemon choosing the
0999a2
+        more appropriate "driver" for each profile type.
0999a2
+    -->
0999a2
+    <property name="Profiles" type="aa{sv}" access="read"/>
0999a2
+
0999a2
+    
0999a2
+        Actions:
0999a2
+
0999a2
+        An array of strings listing each one of the "actions" implemented in
0999a2
+        the running daemon. This is used by API users to figure out whether
0999a2
+        particular functionality is available in a version of the daemon.
0999a2
+    -->
0999a2
+    <property name="Actions" type="as" access="read"/>
0999a2
+
0999a2
+  </interface>
0999a2
+</node>
0999a2
diff --git a/data/gnome-shell-dbus-interfaces.gresource.xml b/data/gnome-shell-dbus-interfaces.gresource.xml
0999a2
index e7972f6cb..6682c462d 100644
0999a2
--- a/data/gnome-shell-dbus-interfaces.gresource.xml
0999a2
+++ b/data/gnome-shell-dbus-interfaces.gresource.xml
0999a2
@@ -1,6 +1,7 @@
0999a2
 
0999a2
 <gresources>
0999a2
   <gresource prefix="/org/gnome/shell/dbus-interfaces">
0999a2
+    <file preprocess="xml-stripblanks">net.hadess.PowerProfiles.xml</file>
0999a2
     <file preprocess="xml-stripblanks">net.hadess.SensorProxy.xml</file>
0999a2
     <file preprocess="xml-stripblanks">net.reactivated.Fprint.Device.xml</file>
0999a2
     <file preprocess="xml-stripblanks">net.reactivated.Fprint.Manager.xml</file>
0999a2
diff --git a/js/js-resources.gresource.xml b/js/js-resources.gresource.xml
0999a2
index b2c603a55..7a94e2ff1 100644
0999a2
--- a/js/js-resources.gresource.xml
0999a2
+++ b/js/js-resources.gresource.xml
0999a2
@@ -134,6 +134,7 @@
0999a2
     <file>ui/status/nightLight.js</file>
0999a2
     <file>ui/status/network.js</file>
0999a2
     <file>ui/status/power.js</file>
0999a2
+    <file>ui/status/powerProfiles.js</file>
0999a2
     <file>ui/status/rfkill.js</file>
0999a2
     <file>ui/status/volume.js</file>
0999a2
     <file>ui/status/bluetooth.js</file>
0999a2
diff --git a/js/ui/panel.js b/js/ui/panel.js
0999a2
index ad11f4ba2..84668e96e 100644
0999a2
--- a/js/ui/panel.js
0999a2
+++ b/js/ui/panel.js
0999a2
@@ -693,6 +693,7 @@ class AggregateMenu extends PanelMenu.Button {
0999a2
 
0999a2
         this._remoteAccess = new imports.ui.status.remoteAccess.RemoteAccessApplet();
0999a2
         this._power = new imports.ui.status.power.Indicator();
0999a2
+        this._powerProfiles = new imports.ui.status.powerProfiles.Indicator();
0999a2
         this._rfkill = new imports.ui.status.rfkill.Indicator();
0999a2
         this._volume = new imports.ui.status.volume.Indicator();
0999a2
         this._brightness = new imports.ui.status.brightness.Indicator();
0999a2
@@ -712,6 +713,7 @@ class AggregateMenu extends PanelMenu.Button {
0999a2
         this._indicators.add_child(this._rfkill);
0999a2
         this._indicators.add_child(this._volume);
0999a2
         this._indicators.add_child(this._power);
0999a2
+        this._indicators.add_child(this._powerProfiles);
0999a2
 
0999a2
         this.menu.addMenuItem(this._volume.menu);
0999a2
         this.menu.addMenuItem(this._brightness.menu);
0999a2
@@ -726,6 +728,7 @@ class AggregateMenu extends PanelMenu.Button {
0999a2
         this.menu.addMenuItem(this._location.menu);
0999a2
         this.menu.addMenuItem(this._rfkill.menu);
0999a2
         this.menu.addMenuItem(this._power.menu);
0999a2
+        this.menu.addMenuItem(this._powerProfiles.menu);
0999a2
         this.menu.addMenuItem(this._nightLight.menu);
0999a2
         this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
0999a2
         this.menu.addMenuItem(this._system.menu);
0999a2
@@ -733,6 +736,7 @@ class AggregateMenu extends PanelMenu.Button {
0999a2
         menuLayout.addSizeChild(this._location.menu.actor);
0999a2
         menuLayout.addSizeChild(this._rfkill.menu.actor);
0999a2
         menuLayout.addSizeChild(this._power.menu.actor);
0999a2
+        menuLayout.addSizeChild(this._powerProfiles.menu.actor);
0999a2
         menuLayout.addSizeChild(this._system.menu.actor);
0999a2
     }
0999a2
 });
0999a2
diff --git a/js/ui/status/powerProfiles.js b/js/ui/status/powerProfiles.js
0999a2
new file mode 100644
0999a2
index 000000000..f6bc5835b
0999a2
--- /dev/null
0999a2
+++ b/js/ui/status/powerProfiles.js
0999a2
@@ -0,0 +1,111 @@
0999a2
+// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
0999a2
+/* exported Indicator */
0999a2
+
0999a2
+const { Gio, GObject } = imports.gi;
0999a2
+
0999a2
+const Main = imports.ui.main;
0999a2
+const PanelMenu = imports.ui.panelMenu;
0999a2
+const PopupMenu = imports.ui.popupMenu;
0999a2
+
0999a2
+const { loadInterfaceXML } = imports.misc.fileUtils;
0999a2
+
0999a2
+const BUS_NAME = 'net.hadess.PowerProfiles';
0999a2
+const OBJECT_PATH = '/net/hadess/PowerProfiles';
0999a2
+
0999a2
+const PowerProfilesIface = loadInterfaceXML('net.hadess.PowerProfiles');
0999a2
+const PowerProfilesProxy = Gio.DBusProxy.makeProxyWrapper(PowerProfilesIface);
0999a2
+
0999a2
+const PROFILE_LABELS = {
0999a2
+    'performance': _('Performance Mode'),
0999a2
+    'balanced': _('Balanced Power'),
0999a2
+    'power-saver': _('Power Saver'),
0999a2
+};
0999a2
+const PROFILE_ICONS = {
0999a2
+    'performance': 'power-profile-performance-symbolic',
0999a2
+    'balanced': 'power-profile-balanced-symbolic',
0999a2
+    'power-saver': 'power-profile-power-saver-symbolic',
0999a2
+};
0999a2
+
0999a2
+var Indicator = GObject.registerClass(
0999a2
+class Indicator extends PanelMenu.SystemIndicator {
0999a2
+    _init() {
0999a2
+        super._init();
0999a2
+
0999a2
+        this._profileItems = new Map();
0999a2
+        this._updateProfiles = true;
0999a2
+
0999a2
+        this._proxy = new PowerProfilesProxy(Gio.DBus.system, BUS_NAME, OBJECT_PATH,
0999a2
+            (proxy, error) => {
0999a2
+                if (error) {
0999a2
+                    log(error.message);
0999a2
+                } else {
0999a2
+                    this._proxy.connect('g-properties-changed',
0999a2
+                        (p, properties) => {
0999a2
+                            const propertyNames = properties.deep_unpack();
0999a2
+                            this._updateProfiles = 'Profiles' in propertyNames;
0999a2
+                            this._sync();
0999a2
+                        });
0999a2
+                }
0999a2
+                this._sync();
0999a2
+            });
0999a2
+
0999a2
+        this._item = new PopupMenu.PopupSubMenuMenuItem('', true);
0999a2
+
0999a2
+        this._profileSection = new PopupMenu.PopupMenuSection();
0999a2
+        this._item.menu.addMenuItem(this._profileSection);
0999a2
+        this._item.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
0999a2
+        this._item.menu.addSettingsAction(_('Power Settings'),
0999a2
+            'gnome-power-panel.desktop');
0999a2
+        this.menu.addMenuItem(this._item);
0999a2
+
0999a2
+        Main.sessionMode.connect('updated', this._sessionUpdated.bind(this));
0999a2
+        this._sessionUpdated();
0999a2
+        this._sync();
0999a2
+    }
0999a2
+
0999a2
+    _sessionUpdated() {
0999a2
+        const sensitive = !Main.sessionMode.isLocked && !Main.sessionMode.isGreeter;
0999a2
+        this.menu.setSensitive(sensitive);
0999a2
+    }
0999a2
+
0999a2
+    _sync() {
0999a2
+        this._item.visible = this._proxy.g_name_owner !== null;
0999a2
+
0999a2
+        if (!this._item.visible)
0999a2
+            return;
0999a2
+
0999a2
+        if (this._updateProfiles) {
0999a2
+            this._profileSection.removeAll();
0999a2
+            this._profileItems.clear();
0999a2
+
0999a2
+            const profiles = this._proxy.Profiles
0999a2
+                .map(p => p.Profile.unpack())
0999a2
+                .reverse();
0999a2
+            for (const profile of profiles) {
0999a2
+                const label = PROFILE_LABELS[profile];
0999a2
+                if (!label)
0999a2
+                    continue;
0999a2
+
0999a2
+                const item = new PopupMenu.PopupMenuItem(label);
0999a2
+                item.connect('activate',
0999a2
+                    () => (this._proxy.ActiveProfile = profile));
0999a2
+                this._profileItems.set(profile, item);
0999a2
+                this._profileSection.addMenuItem(item);
0999a2
+            }
0999a2
+            this._updateProfiles = false;
0999a2
+        }
0999a2
+
0999a2
+        for (const [profile, item] of this._profileItems) {
0999a2
+            item.setOrnament(profile === this._proxy.ActiveProfile
0999a2
+                ? PopupMenu.Ornament.DOT
0999a2
+                : PopupMenu.Ornament.NONE);
0999a2
+        }
0999a2
+
0999a2
+        const perfItem = this._profileItems.get('performance');
0999a2
+        if (perfItem)
0999a2
+            perfItem.sensitive = this._proxy.PerformanceInhibited === '';
0999a2
+
0999a2
+        this._item.label.text = PROFILE_LABELS[this._proxy.ActiveProfile];
0999a2
+        this._item.icon.icon_name = PROFILE_ICONS[this._proxy.ActiveProfile];
0999a2
+    }
0999a2
+});
0999a2
diff --git a/po/POTFILES.in b/po/POTFILES.in
0999a2
index cb279c1ee..727cb01a8 100644
0999a2
--- a/po/POTFILES.in
0999a2
+++ b/po/POTFILES.in
0999a2
@@ -61,6 +61,7 @@ js/ui/status/location.js
0999a2
 js/ui/status/network.js
0999a2
 js/ui/status/nightLight.js
0999a2
 js/ui/status/power.js
0999a2
+js/ui/status/powerProfiles.js
0999a2
 js/ui/status/remoteAccess.js
0999a2
 js/ui/status/rfkill.js
0999a2
 js/ui/status/system.js
0999a2
-- 
0999a2
2.31.1
0999a2
0999a2
0999a2
From 0f8a2e2c6c3119492670efce5aff1224f2c3c47f Mon Sep 17 00:00:00 2001
0999a2
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
0999a2
Date: Fri, 6 Aug 2021 21:04:24 +0200
0999a2
Subject: [PATCH 2/2] powerProfiles: Tweak profile names
0999a2
0999a2
After some more discussion, we settled on slightly different
0999a2
profile names.
0999a2
0999a2
https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/4530
0999a2
0999a2
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1939>
0999a2
---
0999a2
 js/ui/status/powerProfiles.js | 6 +++---
0999a2
 1 file changed, 3 insertions(+), 3 deletions(-)
0999a2
0999a2
diff --git a/js/ui/status/powerProfiles.js b/js/ui/status/powerProfiles.js
0999a2
index f6bc5835b..61205bbc6 100644
0999a2
--- a/js/ui/status/powerProfiles.js
0999a2
+++ b/js/ui/status/powerProfiles.js
0999a2
@@ -16,9 +16,9 @@ const PowerProfilesIface = loadInterfaceXML('net.hadess.PowerProfiles');
0999a2
 const PowerProfilesProxy = Gio.DBusProxy.makeProxyWrapper(PowerProfilesIface);
0999a2
 
0999a2
 const PROFILE_LABELS = {
0999a2
-    'performance': _('Performance Mode'),
0999a2
-    'balanced': _('Balanced Power'),
0999a2
-    'power-saver': _('Power Saver'),
0999a2
+    'performance': C_('Power profile', 'Performance'),
0999a2
+    'balanced': C_('Power profile', 'Balanced'),
0999a2
+    'power-saver': C_('Power profile', 'Power Saver'),
0999a2
 };
0999a2
 const PROFILE_ICONS = {
0999a2
     'performance': 'power-profile-performance-symbolic',
0999a2
-- 
0999a2
2.31.1
0999a2