diff --git a/INSTALL.md b/INSTALL.md
index f0c4e47..fb97281 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -59,6 +59,29 @@ _Make a ZIP package for GNOME Shell:_
./autogen.sh && make && make zip-file
```
+### Local development (GNOME Shell 45+)
+_Run the extension directly from a local checkout:_
+```sh
+mkdir -p ~/.local/share/gnome-shell/extensions
+ln -snf "$(pwd)" ~/.local/share/gnome-shell/extensions/cpufreq@konkor
+```
+Then enable it:
+```sh
+gnome-extensions enable cpufreq@konkor
+```
+If GNOME Shell doesn't pick up changes, log out/in (Wayland) or restart GNOME Shell.
+
+_Alternatively, install a fresh bundle:_
+```sh
+gnome-extensions pack . --force
+# installs into ~/.local/share/gnome-shell/extensions
+gnome-extensions install --force ./cpufreq@konkor.shell-extension.zip
+```
+If settings are missing, rebuild schemas:
+```sh
+glib-compile-schemas schemas/
+```
+
## Complete uninstall and removing of stored settings.
It can be useful if you have saved broken settings values or to clean up previous installation.
diff --git a/Makefile.am b/Makefile.am
index ef87a99..d567252 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -16,6 +16,7 @@ js_DATA = \
convenience.js \
extension.js \
prefs.js \
+ prefs_legacy.js \
metadata.json \
stylesheet.css \
konkor.cpufreq.policy \
diff --git a/common/Preferences.js b/common/Preferences.js
index ac9899a..7330078 100644
--- a/common/Preferences.js
+++ b/common/Preferences.js
@@ -17,7 +17,7 @@ const Lang = imports.lang;
const APPDIR = getCurrentFile ()[1];
-const Prefs = imports.prefs;
+const Prefs = imports.prefs_legacy;
var Preferences = new Lang.Class ({
Name: 'Preferences',
diff --git a/extension.js b/extension.js
index 7522e2c..82f758f 100644
--- a/extension.js
+++ b/extension.js
@@ -8,34 +8,27 @@
* with this program. If not, see .
*/
-const Lang = imports.lang;
-const GObject = imports.gi.GObject;
-const GLib = imports.gi.GLib;
-const Gio = imports.gi.Gio;
-const St = imports.gi.St;
-const Main = imports.ui.main;
-const PanelMenu = imports.ui.panelMenu;
-
-const ExtensionUtils = imports.misc.extensionUtils;
-
-const Me = ExtensionUtils.getCurrentExtension ();
-const Logger = Me.imports.common.Logger;
-const Convenience = Me.imports.convenience;
-const EXTENSIONDIR = Me.dir.get_path ();
-const APP_PATH = EXTENSIONDIR + "/cpufreq-application";
+import GObject from 'gi://GObject';
+import GLib from 'gi://GLib';
+import Gio from 'gi://Gio';
+import St from 'gi://St';
+
+import * as Main from 'resource:///org/gnome/shell/ui/main.js';
+import * as PanelMenu from 'resource:///org/gnome/shell/ui/panelMenu.js';
+import {Extension} from 'resource:///org/gnome/shell/extensions/extension.js';
const SAVE_SETTINGS_KEY = 'save-settings';
-const EXTENSION_MODE_KEY= 'extension-mode';
-const SHOW_SPLASH_KEY = 'show-splash';
-const PROFILE_ID_KEY = 'profile-id';
-const MONITOR_KEY = 'monitor';
-const EPROFILES_KEY = 'event-profiles';
-const LABEL_KEY = 'label'
-const LABEL_SHOW_KEY = 'label-show';
-const UNITS_SHOW_KEY = 'units-show';
-const FREQ_SHOW_KEY = 'frequency-show';
-const GOVS_SHOW_KEY = 'governors-show';
-const LOAD_SHOW_KEY = 'load-show';
+const EXTENSION_MODE_KEY = 'extension-mode';
+const SHOW_SPLASH_KEY = 'show-splash';
+const PROFILE_ID_KEY = 'profile-id';
+const MONITOR_KEY = 'monitor';
+const EPROFILES_KEY = 'event-profiles';
+const LABEL_KEY = 'label';
+const LABEL_SHOW_KEY = 'label-show';
+const UNITS_SHOW_KEY = 'units-show';
+const FREQ_SHOW_KEY = 'frequency-show';
+const GOVS_SHOW_KEY = 'governors-show';
+const LOAD_SHOW_KEY = 'load-show';
const COLOR_SHOW_KEY = 'color-show';
const COLOR_SHOW_CUSTOM_KEY = 'color-show-custom';
@@ -43,499 +36,593 @@ const COLOR_SHOW_CUSTOM_NORMAL_KEY = 'color-show-custom-normal';
const COLOR_SHOW_CUSTOM_WARNING_KEY = 'color-show-custom-warning';
const COLOR_SHOW_CUSTOM_CRITICAL_KEY = 'color-show-custom-critical';
-let color_show = false;
-let color_show_custom = false;
-let color_show_default_normal = ''; //'#33d552';
-let color_show_default_warning = 'orange';
-let color_show_default_critical = 'red';
-let color_show_custom_normal = '#ebebeb';
-let color_show_custom_warning = '#ebebeb';
-let color_show_custom_critical = '#ff0000';
-
-//const SETTINGS_ID = 'org.gnome.shell.extensions.cpufreq';
-
-let event = 0;
-let event_style = 0;
-let monitor_event = 0;
-let settingsID, powerID, scheduleID;
-
-let save = false;
-let extmode = true;
-let splash = true;
-let label_text = "";
-let label_show = false;
-let units_show = true;
-let frequency_show = true;
-let governor_show = false;
-let load_show = false;
-let title_text = "\u26A0";
-let title_style = "";
-let monitor_timeout = 500;
-let eprofiles = [
- {percent:0, event:0, guid:""},
- {percent:100, event:1, guid:""}
-];
-let first_boot = true;
-let guid_battery = "";
-
const UP_BUS_NAME = 'org.freedesktop.UPower';
const UP_OBJECT_PATH = '/org/freedesktop/UPower/devices/DisplayDevice';
-const DisplayDeviceInterface = ' \
- \
- \
- \
- \
- \
- \
- \
- \
- \
-';
+const DisplayDeviceInterface = `
+
+
+
+
+
+
+
+
+
+`;
const PowerManagerProxy = Gio.DBusProxy.makeProxyWrapper(DisplayDeviceInterface);
const BUS_NAME = 'org.konkor.cpufreq.service';
const OBJECT_PATH = '/org/konkor/cpufreq/service';
-const CpufreqServiceIface = ' \
- \
- \
- \
- \
- \
- \
- \
- \
- \
- \
- \
- \
-';
-const CpufreqServiceProxy = Gio.DBusProxy.makeProxyWrapper (CpufreqServiceIface);
-
-const CpuFreq = {
- init: function () {
- this.settings = Convenience.getSettings();
- this.on_settings (null, null);
-
- this.statusLabel = new St.Label ({
- text: title_text, y_expand: true, y_align: 2, style_class:'cpufreq-text'
+const CpufreqServiceIface = `
+
+
+
+
+
+
+
+
+
+
+
+
+`;
+const CpufreqServiceProxy = Gio.DBusProxy.makeProxyWrapper(CpufreqServiceIface);
+
+function byteArrayToString(value) {
+ if (typeof value === 'string')
+ return value;
+
+ if (value instanceof Uint8Array)
+ return new TextDecoder().decode(value);
+
+ return String(value);
+}
+
+function getUiGroup() {
+ return Main.uiGroup ?? Main.layoutManager?.uiGroup;
+}
+
+function addChild(container, child) {
+ if (!container)
+ return;
+
+ if (container.add_child)
+ container.add_child(child);
+ else if (container.add_actor)
+ container.add_actor(child);
+}
+
+function removeChild(container, child) {
+ if (!container)
+ return;
+
+ if (container.remove_child)
+ container.remove_child(child);
+ else if (container.remove_actor)
+ container.remove_actor(child);
+}
+
+function removeActor(actor) {
+ if (!actor)
+ return false;
+
+ let parent = actor.get_parent?.();
+ removeChild(parent ?? getUiGroup(), actor);
+ actor.destroy();
+ return false;
+}
+
+function sessionBusNameHasOwner(name) {
+ try {
+ const result = Gio.DBus.session.call_sync(
+ 'org.freedesktop.DBus',
+ '/org/freedesktop/DBus',
+ 'org.freedesktop.DBus',
+ 'NameHasOwner',
+ new GLib.Variant('(s)', [name]),
+ null,
+ Gio.DBusCallFlags.NONE,
+ -1,
+ null
+ );
+
+ return result?.deepUnpack?.()?.[0] ?? false;
+ } catch {
+ return false;
+ }
+}
+
+const FrequencyIndicator = GObject.registerClass(
+class FrequencyIndicator extends PanelMenu.Button {
+ _init(extension) {
+ super._init(0.0, 'CPU Frequency Indicator', false);
+
+ this._extension = extension;
+ this._extensionDir = extension.path;
+ this._appPath = `${this._extensionDir}/cpufreq-application`;
+
+ this._event = 0;
+ this._eventStyle = 0;
+ this._monitorEventId = 0;
+ this._settingsChangedId = 0;
+ this._powerChangedId = 0;
+ this._scheduleId = 0;
+
+ this._titleText = '⚠';
+ this._titleStyle = '';
+
+ this._colorShow = false;
+ this._colorShowCustom = false;
+ this._colorShowDefaultNormal = '';
+ this._colorShowDefaultWarning = 'orange';
+ this._colorShowDefaultCritical = 'red';
+ this._colorShowCustomNormal = '#ebebeb';
+ this._colorShowCustomWarning = '#ebebeb';
+ this._colorShowCustomCritical = '#ff0000';
+
+ this._save = false;
+ this._extensionMode = true;
+ this._splashEnabled = true;
+ this._labelText = '';
+ this._labelShow = false;
+ this._unitsShow = true;
+ this._frequencyShow = true;
+ this._governorShow = false;
+ this._loadShow = false;
+
+ this._monitorTimeout = 500;
+ this._eprofiles = [
+ {percent: 0, event: 0, guid: ''},
+ {percent: 100, event: 1, guid: ''},
+ ];
+
+ this._firstBoot = true;
+ this._guidBattery = '';
+ this._guid = '';
+
+ this._settings = this._extension.getSettings();
+ this._onSettingsChanged(null, null);
+
+ this._statusLabel = new St.Label({
+ text: this._titleText,
+ y_expand: true,
+ y_align: 2,
+ style_class: 'cpufreq-text',
});
- this.statusLabel.style = title_style;
- let _box = new St.BoxLayout();
- _box.add_actor (this.statusLabel);
- this.add_actor (_box);
- this.connect ('button-press-event', () => {
- var args = extmode ? "--extension" : "";
- if (splash)
- if (!this.app_running) this.show_splash ();
- if (!guid_battery || (guid_battery == this.guid)) this.launch_app (args);
- else this.launch_app (args + " --no-save");
+ this._statusLabel.style = this._titleStyle;
+
+ let box = new St.BoxLayout();
+ addChild(box, this._statusLabel);
+ addChild(this, box);
+
+ this.connect('button-press-event', () => {
+ let args = this._extensionMode ? '--extension' : '';
+ if (this._splashEnabled && !this.app_running)
+ this.show_splash();
+
+ if (!this._guidBattery || this._guidBattery === this._guid)
+ this.launch_app(args);
+ else
+ this.launch_app(`${args} --no-save`);
});
- if (!monitor_timeout) this.statusLabel.set_text (this.get_title ());
- this.add_event ();
+ if (!this._monitorTimeout)
+ this._statusLabel.set_text(this.get_title());
- //TODO: Workaround updating title
- this.settings.set_boolean (SAVE_SETTINGS_KEY, !save);
- this.settings.set_boolean (SAVE_SETTINGS_KEY, save);
+ this.add_event();
- if (settingsID) this.settings.disconnect (settingsID);
- settingsID = this.settings.connect ("changed", this.on_settings.bind (this));
+ // Workaround: force a settings change to update title.
+ this._settings.set_boolean(SAVE_SETTINGS_KEY, !this._save);
+ this._settings.set_boolean(SAVE_SETTINGS_KEY, this._save);
- this.power = new PowerManagerProxy (Gio.DBus.system, UP_BUS_NAME, UP_OBJECT_PATH, (proxy, e) => {
- if (e) {
- error (e.message);
- return;
- }
- this.on_power_state (proxy.State, proxy.Percentage);
- if (save && first_boot && !guid_battery) this.launch_app ("-p user");
- first_boot = false;
- GLib.timeout_add (0, 8000, () => {
- powerID = this.power.connect ('g-properties-changed', (o,a) => {
- //a = a{sv}
- this.on_power_state (this.power.State, this.power.Percentage);
+ this._settingsChangedId = this._settings.connect(
+ 'changed',
+ this._onSettingsChanged.bind(this)
+ );
+
+ this._power = new PowerManagerProxy(
+ Gio.DBus.system,
+ UP_BUS_NAME,
+ UP_OBJECT_PATH,
+ (proxy, error) => {
+ if (error) {
+ logError(error, '[cpufreq] UPower proxy error');
+ return;
+ }
+
+ this.on_power_state(proxy.State, proxy.Percentage);
+ if (this._save && this._firstBoot && !this._guidBattery)
+ this.launch_app('-p user');
+ this._firstBoot = false;
+
+ GLib.timeout_add(GLib.PRIORITY_DEFAULT, 8000, () => {
+ this._powerChangedId = this._power.connect(
+ 'g-properties-changed',
+ () => this.on_power_state(this._power.State, this._power.Percentage)
+ );
+ return GLib.SOURCE_REMOVE;
});
- });
- });
- },
+ }
+ );
+ }
- on_settings: function (o, key) {
+ _onSettingsChanged(_settings, key) {
let s;
- o = o || this.settings;
+ let settings = _settings || this._settings;
if (!key) {
- this.guid = o.get_string (PROFILE_ID_KEY);
- monitor_timeout = o.get_int (MONITOR_KEY);
- save = o.get_boolean (SAVE_SETTINGS_KEY);
- extmode = o.get_boolean (EXTENSION_MODE_KEY);
- splash = o.get_boolean (SHOW_SPLASH_KEY);
- label_text = o.get_string (LABEL_KEY);
- label_show = o.get_boolean (LABEL_SHOW_KEY);
- units_show = o.get_boolean (UNITS_SHOW_KEY);
- frequency_show = o.get_boolean (FREQ_SHOW_KEY);
- governor_show = o.get_boolean (GOVS_SHOW_KEY);
- load_show = o.get_boolean (LOAD_SHOW_KEY);
- color_show = o.get_boolean (COLOR_SHOW_KEY);
- color_show_custom = o.get_boolean (COLOR_SHOW_CUSTOM_KEY);
- color_show_custom_normal = o.get_string (COLOR_SHOW_CUSTOM_NORMAL_KEY);
- color_show_custom_warning = o.get_string (COLOR_SHOW_CUSTOM_WARNING_KEY);
- color_show_custom_critical = o.get_string (COLOR_SHOW_CUSTOM_CRITICAL_KEY);
- s = o.get_string (EPROFILES_KEY);
- if (s) eprofiles = JSON.parse (s);
+ this._guid = settings.get_string(PROFILE_ID_KEY);
+ this._monitorTimeout = settings.get_int(MONITOR_KEY);
+ this._save = settings.get_boolean(SAVE_SETTINGS_KEY);
+ this._extensionMode = settings.get_boolean(EXTENSION_MODE_KEY);
+ this._splashEnabled = settings.get_boolean(SHOW_SPLASH_KEY);
+ this._labelText = settings.get_string(LABEL_KEY);
+ this._labelShow = settings.get_boolean(LABEL_SHOW_KEY);
+ this._unitsShow = settings.get_boolean(UNITS_SHOW_KEY);
+ this._frequencyShow = settings.get_boolean(FREQ_SHOW_KEY);
+ this._governorShow = settings.get_boolean(GOVS_SHOW_KEY);
+ this._loadShow = settings.get_boolean(LOAD_SHOW_KEY);
+
+ this._colorShow = settings.get_boolean(COLOR_SHOW_KEY);
+ this._colorShowCustom = settings.get_boolean(COLOR_SHOW_CUSTOM_KEY);
+ this._colorShowCustomNormal = settings.get_string(COLOR_SHOW_CUSTOM_NORMAL_KEY);
+ this._colorShowCustomWarning = settings.get_string(COLOR_SHOW_CUSTOM_WARNING_KEY);
+ this._colorShowCustomCritical = settings.get_string(COLOR_SHOW_CUSTOM_CRITICAL_KEY);
+
+ s = settings.get_string(EPROFILES_KEY);
+ if (s)
+ this._eprofiles = JSON.parse(s);
}
- if (key == MONITOR_KEY) {
- monitor_timeout = o.get_int (MONITOR_KEY);
- if (monitor_event) {
- GLib.source_remove (monitor_event);
- monitor_event = 0;
+ if (key === MONITOR_KEY) {
+ this._monitorTimeout = settings.get_int(MONITOR_KEY);
+ if (this._monitorEventId) {
+ GLib.source_remove(this._monitorEventId);
+ this._monitorEventId = 0;
}
- monitor_event = GLib.timeout_add (100, 1000, this.add_event.bind (this));
- } else if (key == PROFILE_ID_KEY) {
- this.guid = o.get_string (PROFILE_ID_KEY);
- } else if (key == EPROFILES_KEY) {
- s = o.get_string (EPROFILES_KEY);
- if (s) eprofiles = JSON.parse (s);
- } else if (key == EXTENSION_MODE_KEY) {
- extmode = o.get_boolean (EXTENSION_MODE_KEY);
- } else if (key == SHOW_SPLASH_KEY) {
- splash = o.get_boolean (SHOW_SPLASH_KEY);
- } else if (key == LABEL_KEY) {
- label_text = o.get_string (LABEL_KEY);
- } else if (key == LABEL_SHOW_KEY) {
- label_show = o.get_boolean (LABEL_SHOW_KEY);
- } else if (key == UNITS_SHOW_KEY) {
- units_show = o.get_boolean (UNITS_SHOW_KEY);
- } else if (key == FREQ_SHOW_KEY) {
- frequency_show = o.get_boolean (FREQ_SHOW_KEY);
- } else if (key == GOVS_SHOW_KEY) {
- governor_show = o.get_boolean (GOVS_SHOW_KEY);
- } else if (key == LOAD_SHOW_KEY) {
- load_show = o.get_boolean (LOAD_SHOW_KEY);
- }else if (key == COLOR_SHOW_KEY) {
- color_show = o.get_boolean (COLOR_SHOW_KEY);
- } else if (key == COLOR_SHOW_CUSTOM_KEY) {
- color_show_custom = o.get_boolean (COLOR_SHOW_CUSTOM_KEY);
- } else if (key == COLOR_SHOW_CUSTOM_NORMAL_KEY) {
- color_show_custom_normal = o.get_string (COLOR_SHOW_CUSTOM_NORMAL_KEY);
- } else if (key == COLOR_SHOW_CUSTOM_WARNING_KEY) {
- color_show_custom_warning = o.get_string (COLOR_SHOW_CUSTOM_WARNING_KEY);
- } else if (key == COLOR_SHOW_CUSTOM_CRITICAL_KEY) {
- color_show_custom_critical = o.get_string (COLOR_SHOW_CUSTOM_CRITICAL_KEY);
+ this._monitorEventId = GLib.timeout_add(
+ GLib.PRIORITY_DEFAULT,
+ 1000,
+ this.add_event.bind(this)
+ );
+ } else if (key === PROFILE_ID_KEY) {
+ this._guid = settings.get_string(PROFILE_ID_KEY);
+ } else if (key === EPROFILES_KEY) {
+ s = settings.get_string(EPROFILES_KEY);
+ if (s)
+ this._eprofiles = JSON.parse(s);
+ } else if (key === EXTENSION_MODE_KEY) {
+ this._extensionMode = settings.get_boolean(EXTENSION_MODE_KEY);
+ } else if (key === SHOW_SPLASH_KEY) {
+ this._splashEnabled = settings.get_boolean(SHOW_SPLASH_KEY);
+ } else if (key === LABEL_KEY) {
+ this._labelText = settings.get_string(LABEL_KEY);
+ } else if (key === LABEL_SHOW_KEY) {
+ this._labelShow = settings.get_boolean(LABEL_SHOW_KEY);
+ } else if (key === UNITS_SHOW_KEY) {
+ this._unitsShow = settings.get_boolean(UNITS_SHOW_KEY);
+ } else if (key === FREQ_SHOW_KEY) {
+ this._frequencyShow = settings.get_boolean(FREQ_SHOW_KEY);
+ } else if (key === GOVS_SHOW_KEY) {
+ this._governorShow = settings.get_boolean(GOVS_SHOW_KEY);
+ } else if (key === LOAD_SHOW_KEY) {
+ this._loadShow = settings.get_boolean(LOAD_SHOW_KEY);
+ } else if (key === COLOR_SHOW_KEY) {
+ this._colorShow = settings.get_boolean(COLOR_SHOW_KEY);
+ } else if (key === COLOR_SHOW_CUSTOM_KEY) {
+ this._colorShowCustom = settings.get_boolean(COLOR_SHOW_CUSTOM_KEY);
+ } else if (key === COLOR_SHOW_CUSTOM_NORMAL_KEY) {
+ this._colorShowCustomNormal = settings.get_string(COLOR_SHOW_CUSTOM_NORMAL_KEY);
+ } else if (key === COLOR_SHOW_CUSTOM_WARNING_KEY) {
+ this._colorShowCustomWarning = settings.get_string(COLOR_SHOW_CUSTOM_WARNING_KEY);
+ } else if (key === COLOR_SHOW_CUSTOM_CRITICAL_KEY) {
+ this._colorShowCustomCritical = settings.get_string(COLOR_SHOW_CUSTOM_CRITICAL_KEY);
}
- //TODO: statusLabel
- if ((key == LABEL_KEY) && !monitor_timeout) this.statusLabel.set_text (this.get_title ());
-
- /*if ((key == "power-state") || (key == "power-percentage")) {
- debug ("power-state changed...");
- this.on_power_state (o.get_uint ("power-state"), o.get_double ("power-percentage"));
- }*/
- },
-
- on_power_state: function (state, percentage) {
- let id = eprofiles[1].guid;
- //debug ("on_power_state: %s %s%%".format (this.power.State, this.power.Percentage));
- debug ("on_power_state: %s %s%%".format (state, percentage));
- if (!id) return;
- if (state == 2) {
- //on battery
- if (id == guid_battery) return;
- if (percentage < eprofiles[1].percent) {
- this.schedule_profile ('--no-save -p ' + id);
- guid_battery = id;
+ if (key === LABEL_KEY && !this._monitorTimeout)
+ this._statusLabel.set_text(this.get_title());
+ }
+
+ on_power_state(state, percentage) {
+ let id = this._eprofiles?.[1]?.guid;
+ if (!id)
+ return;
+
+ if (state === 2) {
+ // On battery.
+ if (id === this._guidBattery)
+ return;
+ if (percentage < this._eprofiles[1].percent) {
+ this.schedule_profile(`--no-save -p ${id}`);
+ this._guidBattery = id;
}
} else {
- //restoring prev state
- if (guid_battery == this.guid) return;
- this.schedule_profile ('-p user');
- guid_battery = this.guid;
+ // Restoring previous state.
+ if (this._guidBattery === this._guid)
+ return;
+ this.schedule_profile('-p user');
+ this._guidBattery = this._guid;
}
- },
-
- unschedule_profile: function () {
- GLib.source_remove (scheduleID);
- scheduleID = 0;
- },
-
- schedule_profile: function (options) {
- if (scheduleID) this.unschedule_profile ();
- scheduleID = GLib.timeout_add (0, 5000, () => {
- this.launch_app (options);
- scheduleID = 0;
+ }
+
+ unschedule_profile() {
+ if (!this._scheduleId)
+ return;
+ GLib.source_remove(this._scheduleId);
+ this._scheduleId = 0;
+ }
+
+ schedule_profile(options) {
+ if (this._scheduleId)
+ this.unschedule_profile();
+
+ this._scheduleId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 5000, () => {
+ this.launch_app(options);
+ this._scheduleId = 0;
+ return GLib.SOURCE_REMOVE;
});
- },
-
- launch_app: function (options) {
- let extra = "";
- /*if (Logger.debug_lvl == 2) extra = " --debug";
- else if (Logger.debug_lvl == 1) extra = " --verbose";*/
- options = options || "";
- info ("launch_app " + options + extra);
- GLib.spawn_command_line_async ("%s %s".format (APP_PATH, options + extra));
- },
-
- get app_running () {
- let res = GLib.spawn_command_line_sync ("ps -A");
- let o, n;
- if (res[0]) o = Convenience.byteArrayToString (res[1]).toString().split("\n");
- for (let i = 0; i < o.length; i++) {
- if (o[i].indexOf ("cpufreq-app") > -1) {
- n = parseInt (o[i].trim().split(" ")[0]);
- if (Number.isInteger(n) && n > 0) return n;
+ }
+
+ launch_app(options) {
+ options = options || '';
+ try {
+ GLib.spawn_command_line_async(`${this._appPath} ${options}`.trim());
+ } catch (error) {
+ logError(error, '[cpufreq] Failed to launch application');
+ }
+ }
+
+ get app_running() {
+ try {
+ let [ok, stdout] = GLib.spawn_command_line_sync('ps -A');
+ if (!ok)
+ return 0;
+ let lines = byteArrayToString(stdout).toString().split('\n');
+ for (let line of lines) {
+ if (line.includes('cpufreq-app')) {
+ let pid = parseInt(line.trim().split(' ')[0]);
+ if (Number.isInteger(pid) && pid > 0)
+ return pid;
+ }
}
+ } catch (error) {
+ // Ignore; best-effort check only.
}
return 0;
- },
+ }
- get_title: function (text) {
- if (!text) return title_text;
- let metrics = JSON.parse (text), s = "", f = 0, units;
- if (frequency_show) {
+ get_title(text) {
+ if (!text)
+ return this._titleText;
+
+ let metrics = JSON.parse(text);
+ let s = '';
+ let f = 0;
+
+ if (this._frequencyShow) {
f = metrics.frequency_maximum;
- if (f) if (f < 1000000) {
- units = " \u3392";
- s = (f / 1000).toFixed(0).toString ();
- } else {
- units = "\u3393";
- s = (f / 1000000).toFixed(2).toString ();
+ if (f) {
+ let units;
+ if (f < 1000000) {
+ units = ' ㎒';
+ s = (f / 1000).toFixed(0).toString();
+ } else {
+ units = '㎓';
+ s = (f / 1000000).toFixed(2).toString();
+ }
+ if (this._unitsShow)
+ s += units;
}
- if (units_show) s += units;
}
- if (governor_show && metrics.governor) {
- s += " " + this.get_governor_symbolyc (metrics.governor);
- }
- if (load_show && Number.isInteger (metrics.state))
- s += ' ' + this.get_state_symbolyc (metrics.state);
- if (label_show) s += ' ' + label_text;
- if (s) title_text = s.trim ();
- else title_text = label_text;
-
- if (color_show && Number.isInteger (metrics.state)) {
- s = this.get_stylestring (metrics.state);
- } else title_style = "";
- if (s != title_style) {
- title_style = s;
- this.statusLabel.style = title_style;
+
+ if (this._governorShow && metrics.governor)
+ s += ` ${this.get_governor_symbolyc(metrics.governor)}`;
+
+ if (this._loadShow && Number.isInteger(metrics.state))
+ s += ` ${this.get_state_symbolyc(metrics.state)}`;
+
+ if (this._labelShow)
+ s += ` ${this._labelText}`;
+
+ if (s)
+ this._titleText = s.trim();
+ else
+ this._titleText = this._labelText;
+
+ if (this._colorShow && Number.isInteger(metrics.state))
+ s = this.get_stylestring(metrics.state);
+ else
+ this._titleStyle = '';
+
+ if (s !== this._titleStyle) {
+ this._titleStyle = s;
+ this._statusLabel.style = this._titleStyle;
}
- return title_text;
- },
- get_governor_symbolyc: function (name) {
+ return this._titleText;
+ }
+
+ get_governor_symbolyc(name) {
let g = name;
- if (g == "mixed") g = "\u25cd";
- else if (g == "powersave") g = "\uf06c";
- else if (g == "performance") g = "\uf197";
- else if (g == "ondemand") g = "\uf0e7";
- else if (g == "conservative") g = "\ue976";
- else if (g == "schedutil") g = "\ue953";
- else if (g == "userspace") g = "\uf007";
- else g = "\uf0e7";
+ if (g === 'mixed')
+ g = '◍';
+ else if (g === 'powersave')
+ g = '';
+ else if (g === 'performance')
+ g = '';
+ else if (g === 'ondemand')
+ g = '';
+ else if (g === 'conservative')
+ g = '';
+ else if (g === 'schedutil')
+ g = '';
+ else if (g === 'userspace')
+ g = '';
+ else
+ g = '';
return g;
- },
+ }
- get_state_symbolyc: function (state) {
- let g = "☺";
- if (state == 1) g = "";
- else if (state == 2) g = "☹";
+ get_state_symbolyc(state) {
+ let g = '☺';
+ if (state === 1)
+ g = '';
+ else if (state === 2)
+ g = '☹';
return g;
- },
+ }
- get_stylestring: function (state) {
+ get_stylestring(state) {
let s;
- if (color_show_custom) state += 3;
+ if (this._colorShowCustom)
+ state += 3;
+
switch (state) {
- case 0:
- s = "color:" + color_show_default_normal + ";";
- break;
- case 1:
- s = "color:" + color_show_default_warning + ";";
- break;
- case 2:
- s = "color:" + color_show_default_critical + ";";
- break;
- case 3:
- s = "color:" + color_show_custom_normal + ";";
- break;
- case 4:
- s = "color:" + color_show_custom_warning + ";";
- break;
- case 5:
- s = "color:" + color_show_custom_critical + ";";
- break;
- default:
- s = "";
+ case 0:
+ s = `color:${this._colorShowDefaultNormal};`;
+ break;
+ case 1:
+ s = `color:${this._colorShowDefaultWarning};`;
+ break;
+ case 2:
+ s = `color:${this._colorShowDefaultCritical};`;
+ break;
+ case 3:
+ s = `color:${this._colorShowCustomNormal};`;
+ break;
+ case 4:
+ s = `color:${this._colorShowCustomWarning};`;
+ break;
+ case 5:
+ s = `color:${this._colorShowCustomCritical};`;
+ break;
+ default:
+ s = '';
}
+
return s;
- },
+ }
- add_event: function () {
- this.remove_proxy ();
- if (monitor_timeout > 0) {
- if (!GLib.spawn_command_line_async (EXTENSIONDIR + "/cpufreq-service")) {
- //error ("Unable to start cpufreq service...");
- return;
- }
- this.proxy = new CpufreqServiceProxy (Gio.DBus.session, BUS_NAME, OBJECT_PATH, (proxy, e) => {
- if (e) {
- error (e.message);
- return;
+ add_event() {
+ this.remove_proxy();
+
+ if (this._monitorTimeout > 0) {
+ // Only try to spawn the service if it isn't already running.
+ // If spawning fails (already running, missing binary, etc.) still attempt
+ // to connect to the existing DBus name.
+ if (!sessionBusNameHasOwner(BUS_NAME)) {
+ try {
+ GLib.spawn_command_line_async(`${this._extensionDir}/cpufreq-service`);
+ } catch (error) {
+ logError(error, '[cpufreq] Unable to start cpufreq-service');
}
- event = this.proxy.connectSignal ('MonitorEvent', (o, s, metrics) => {
- if (metrics) this.statusLabel.set_text (this.get_title (metrics.toString ()));
- });
- event_style = this.proxy.connectSignal ('StyleChanged', (o, s, style) => {
- if (style) {
- title_style = style.toString ();
- this.statusLabel.style = title_style;
+ }
+
+ this._proxy = new CpufreqServiceProxy(
+ Gio.DBus.session,
+ BUS_NAME,
+ OBJECT_PATH,
+ (proxy, error) => {
+ if (error) {
+ logError(error, '[cpufreq] DBus proxy error');
+ return;
}
- });
- });
- }
- monitor_event = 0;
- // cpufreq-service should stop auto on disabled monitors
- //else GLib.spawn_command_line_async ("killall cpufreq-service");
- },
-
- remove_proxy: function () {
- if (this.proxy) {
- if (event) this.proxy.disconnectSignal (event);
- if (event_style) this.proxy.disconnectSignal (event_style);
- delete this.proxy;
+
+ this._event = this._proxy.connectSignal('MonitorEvent', (_o, _s, metrics) => {
+ if (metrics)
+ this._statusLabel.set_text(this.get_title(metrics.toString()));
+ });
+
+ this._eventStyle = this._proxy.connectSignal('StyleChanged', (_o, _s, style) => {
+ if (!style)
+ return;
+ this._titleStyle = style.toString();
+ this._statusLabel.style = this._titleStyle;
+ });
+ }
+ );
}
- this.proxy = null;
- event = 0;
- event_style = 0;
- },
-
- remove_events: function () {
- this.remove_proxy ();
- if (settingsID) this.settings.disconnect (settingsID);
- if (powerID) this.power.disconnect (powerID);
- if (monitor_event) GLib.source_remove (monitor_event);
- event = 0; monitor_event = 0;
- settingsID = 0; powerID = 0;
- //GLib.spawn_command_line_async ("killall cpufreq-service");
- },
-
- show_splash: function () {
- let monitor = Main.layoutManager.focusMonitor;
- let height = monitor.height < monitor.width ? monitor.height : monitor.width;
- let width = 512 * height / 1200;
- if (!this.splash)
- this.splash = Gio.icon_new_for_string (EXTENSIONDIR + "/data/splash.svg");
- let splash = new St.Icon ({gicon: this.splash, icon_size: width});
- Main.uiGroup.add_actor (splash);
-
- splash.set_position (Math.floor (monitor.width / 2 - splash.width / 2),
- Math.floor (monitor.height / 2 - splash.height / 2));
-
- if (splash.ease) splash.ease ({
- opacity: 20, mode: 8, duration: 1200,
- onComplete: () => { remove_actor (splash)}
- }); else GLib.timeout_add (0, 1200, () => { return remove_actor (splash)});
+
+ this._monitorEventId = 0;
+ return GLib.SOURCE_REMOVE;
}
-};
-
-let FrequencyIndicator = null;
-
-try {
- FrequencyIndicator = GObject.registerClass({}, class FrequencyIndicator extends PanelMenu.Button {
- _init() {
- super._init (0.0, "CPU Frequency Indicator", false);
-
- this.on_settings = CpuFreq.on_settings.bind (this);
- this.on_power_state = CpuFreq.on_power_state.bind (this);
- this.unschedule_profile = CpuFreq.unschedule_profile.bind (this);
- this.schedule_profile = CpuFreq.schedule_profile.bind (this);
- this.launch_app = CpuFreq.launch_app.bind (this);
- this.get_title = CpuFreq.get_title.bind (this);
- this.get_governor_symbolyc = CpuFreq.get_governor_symbolyc.bind (this);
- this.get_state_symbolyc = CpuFreq.get_state_symbolyc.bind (this);
- this.get_stylestring = CpuFreq.get_stylestring.bind (this);
- this.add_event = CpuFreq.add_event.bind (this);
- this.remove_proxy = CpuFreq.remove_proxy.bind (this);
- this.remove_events = CpuFreq.remove_events.bind (this);
- this.show_splash = CpuFreq.show_splash.bind (this);
-
- CpuFreq.init.bind (this) ();
- }
- });
-} catch (error) {
- log ('Gnome Shell version < 40!', error);
-
- FrequencyIndicator = new Lang.Class({
- Name: 'CpuFreq',
- Extends: PanelMenu.Button,
-
- _init: function() {
- this.parent (0.0, "CPU Frequency Indicator", false);
-
- this.on_settings = CpuFreq.on_settings.bind (this);
- this.on_power_state = CpuFreq.on_power_state.bind (this);
- this.unschedule_profile = CpuFreq.unschedule_profile.bind (this);
- this.schedule_profile = CpuFreq.schedule_profile.bind (this);
- this.launch_app = CpuFreq.launch_app.bind (this);
- this.get_title = CpuFreq.get_title.bind (this);
- this.get_governor_symbolyc = CpuFreq.get_governor_symbolyc.bind (this);
- this.get_state_symbolyc = CpuFreq.get_state_symbolyc.bind (this);
- this.get_stylestring = CpuFreq.get_stylestring.bind (this);
- this.add_event = CpuFreq.add_event.bind (this);
- this.remove_proxy = CpuFreq.remove_proxy.bind (this);
- this.remove_events = CpuFreq.remove_events.bind (this);
- this.show_splash = CpuFreq.show_splash.bind (this);
-
- CpuFreq.init.bind (this) ();
+
+ remove_proxy() {
+ if (this._proxy) {
+ if (this._event)
+ this._proxy.disconnectSignal(this._event);
+ if (this._eventStyle)
+ this._proxy.disconnectSignal(this._eventStyle);
}
- });
-}
-function remove_actor (o) {
- Main.uiGroup.remove_actor (o);
- o.destroy ();
- return false;
-}
+ this._proxy = null;
+ this._event = 0;
+ this._eventStyle = 0;
+ }
-function show_notify (message, style) {
- //var text = new St.Label ({text: message, style_class: style?style:'cpufreq-notify'});
- var text = new St.Label ({text: message, style_class: "modal-dialog audio-selection-content restart-message"});
- text.opacity = 255;
- Main.uiGroup.add_actor (text);
+ remove_events() {
+ this.remove_proxy();
- text.set_position (Math.floor (Main.layoutManager.primaryMonitor.width / 2 - text.width / 2),
- Math.floor (Main.layoutManager.primaryMonitor.height / 2 - text.height / 2));
+ if (this._settingsChangedId)
+ this._settings.disconnect(this._settingsChangedId);
+ this._settingsChangedId = 0;
- GLib.timeout_add (0, 1200, () => { return remove_actor (text)});
-}
+ if (this._powerChangedId)
+ this._power?.disconnect(this._powerChangedId);
+ this._powerChangedId = 0;
-function show_warn (message) {
- show_notify (message, "warn-label");
-}
+ if (this._monitorEventId)
+ GLib.source_remove(this._monitorEventId);
+ this._monitorEventId = 0;
-let monitor;
-Logger.init (Logger.LEVEL.ERROR, true);
+ if (this._scheduleId)
+ this.unschedule_profile();
+ }
-function info (msg) {
- Logger.info ("extension", msg);
-}
+ show_splash() {
+ let monitor = Main.layoutManager.focusMonitor ?? Main.layoutManager.primaryMonitor;
+ if (!monitor && Main.layoutManager.monitors?.length)
+ monitor = Main.layoutManager.monitors[0];
+ if (!monitor)
+ return;
-function debug (msg) {
- Logger.debug ("extension", msg);
-}
+ let height = monitor.height < monitor.width ? monitor.height : monitor.width;
+ let width = 512 * height / 1200;
-function error (msg) {
- Logger.error ("extension", msg);
-}
+ if (!this._splash)
+ this._splash = Gio.icon_new_for_string(`${this._extensionDir}/data/splash.svg`);
-function init () {
-}
+ let splash = new St.Icon({gicon: this._splash, icon_size: width});
+ addChild(getUiGroup(), splash);
-function enable () {
- monitor = new FrequencyIndicator ();
- Main.panel.addToStatusArea ('cpufreq-indicator', monitor);
-}
+ splash.set_position(
+ Math.floor(monitor.width / 2 - splash.width / 2),
+ Math.floor(monitor.height / 2 - splash.height / 2)
+ );
-function disable () {
- monitor.remove_events ();
- monitor.destroy ();
- monitor = null;
+ if (splash.ease) {
+ splash.ease({
+ opacity: 20,
+ mode: 8,
+ duration: 1200,
+ onComplete: () => removeActor(splash),
+ });
+ } else {
+ GLib.timeout_add(GLib.PRIORITY_DEFAULT, 1200, () => removeActor(splash));
+ }
+ }
+});
+
+export default class CPUFreqExtension extends Extension {
+ enable() {
+ this._indicator = new FrequencyIndicator(this);
+ Main.panel.addToStatusArea('cpufreq-indicator', this._indicator);
+ }
+
+ disable() {
+ this._indicator?.remove_events();
+ this._indicator?.destroy();
+ this._indicator = null;
+ }
}
diff --git a/metadata.json b/metadata.json
index 707b9be..fafc20b 100644
--- a/metadata.json
+++ b/metadata.json
@@ -3,7 +3,7 @@
"name": "cpufreq",
"settings-schema": "org.gnome.shell.extensions.cpufreq",
"shell-version": [
- "3.14","3.16","3.18","3.20","3.22","3.24","3.26","3.28","3.30","3.32","3.34","3.36","3.38","40","41","42","43","44"
+ "45","46","47","48","49"
],
"url": "https://github.com/konkor/cpufreq",
"uuid": "cpufreq@konkor",
diff --git a/metadata.json.in b/metadata.json.in
index 99fe4d7..b323019 100644
--- a/metadata.json.in
+++ b/metadata.json.in
@@ -3,7 +3,7 @@
"name": "cpufreq",
"settings-schema": "org.gnome.shell.extensions.cpufreq",
"shell-version": [
- "3.14","3.16","3.18","3.20","3.22","3.24","3.26","3.28","3.30","3.32","3.34","3.36","3.38","40","41","42","43","44"
+ "45","46","47","48","49"
],
"url": "https://github.com/konkor/cpufreq",
"uuid": "cpufreq@konkor",
diff --git a/prefs.js b/prefs.js
index b6f366d..606e36b 100644
--- a/prefs.js
+++ b/prefs.js
@@ -1,6 +1,6 @@
/*
* This is a part of CPUFreq Manager
- * Copyright (C) 2016-2019 konkor
+ * Copyright (C) 2016-2025 konkor
*
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
@@ -8,543 +8,32 @@
* with this program. If not, see .
*/
-const Lang = imports.lang;
-const GObject = imports.gi.GObject;
-const GLib = imports.gi.GLib;
-const Gio = imports.gi.Gio;
-const Gtk = imports.gi.Gtk;
-const Gdk = imports.gi.Gdk;
+import GLib from 'gi://GLib';
-var Format = imports.format;
-String.prototype.format = Format.format;
+import {ExtensionPreferences} from 'resource:///org/gnome/shell/extensions/prefs.js';
-const APPDIR = get_appdir ();
-imports.searchPath.unshift(APPDIR);
-const Logger = imports.common.Logger;
-
-const SAVE_SETTINGS_KEY = 'save-settings';
-const NOTIFY_KEY = 'notifications';
-const DARK_THEME_KEY = 'dark-theme';
-const PROFILES_KEY = 'profiles';
-const EPROFILES_KEY = 'event-profiles';
-const MONITOR_KEY = 'monitor';
-const LABEL_KEY = 'label';
-const LABEL_SHOW_KEY = 'label-show';
-const UNITS_SHOW_KEY = 'units-show';
-const LOAD_SHOW_KEY = 'load-show';
-const GOVS_SHOW_KEY = 'governors-show';
-const FREQ_SHOW_KEY = 'frequency-show';
-
-const COLOR_SHOW_KEY = 'color-show';
-const COLOR_SHOW_CUSTOM_KEY = 'color-show-custom';
-const COLOR_SHOW_CUSTOM_NORMAL_KEY = 'color-show-custom-normal';
-const COLOR_SHOW_CUSTOM_WARNING_KEY = 'color-show-custom-warning';
-const COLOR_SHOW_CUSTOM_CRITICAL_KEY = 'color-show-custom-critical';
-
-const Gettext = imports.gettext.domain ('org-konkor-cpufreq');
-const _ = Gettext.gettext;
-
-const EXTENSIONDIR = getCurrentFile ()[1];
-imports.searchPath.unshift (EXTENSIONDIR);
-const Convenience = imports.convenience;
-
-var EventType = {
-CHARGING: 0,
-DISCHARGING: 1
-};
-
-const suggestions = ["☃","⚡","㎒","㎓","","","","","","","","CPU"];
-
-let save = false;
-let dark = false;
-let profiles = [];
-let monitor_timeout = 500;
-let label_text = "\u269b";
-let label_show = false;
-let frequency_show = true;
-let governor_show = false;
-let load_show = false;
-let units_show = true;
-let system_notifications = false;
-
-let auto_profiles = [
- {name:_("Battery"), guid:"battery"},
- {name:_("Balanced"), guid:"balanced"},
- {name:_("High Performance"), guid:"performance"}
-];
-
-let color_show = false;
-let color_show_custom = false;
-let color_show_custom_normal = '#ebebeb';
-let color_show_custom_warning = '#ebebeb';
-let color_show_custom_critical = '#ff0000';
-
-let eprofiles = [
- {percent:0, event:EventType.CHARGING, guid:""},
- {percent:100, event:EventType.DISCHARGING, guid:""}
-];
-
-let settings = false;
-
-var CPUFreqPreferences = new Lang.Class({
- Name: 'CPUFreqPreferences',
-
- _init: function () {
- this.parent (0.0, "CPUFreq Preferences", false);
- let label, s;
-
- settings = Convenience.getSettings ();
- save = settings.get_boolean (SAVE_SETTINGS_KEY);
- dark = settings.get_boolean (DARK_THEME_KEY);
- monitor_timeout = settings.get_int (MONITOR_KEY);
- label_text = settings.get_string (LABEL_KEY);
- label_show = settings.get_boolean (LABEL_SHOW_KEY);
- load_show = settings.get_boolean (LOAD_SHOW_KEY);
- governor_show = settings.get_boolean (GOVS_SHOW_KEY);
- frequency_show = settings.get_boolean (FREQ_SHOW_KEY);
- units_show = settings.get_boolean (UNITS_SHOW_KEY);
- system_notifications = settings.get_boolean (NOTIFY_KEY);
-
- color_show = settings.get_boolean (COLOR_SHOW_KEY);
- color_show_custom = settings.get_boolean (COLOR_SHOW_CUSTOM_KEY);
- color_show_custom_normal = settings.get_string (COLOR_SHOW_CUSTOM_NORMAL_KEY);
- color_show_custom_warning = settings.get_string (COLOR_SHOW_CUSTOM_WARNING_KEY);
- color_show_custom_critical = settings.get_string (COLOR_SHOW_CUSTOM_CRITICAL_KEY);
-
- s = settings.get_string (EPROFILES_KEY);
- if (s) try {
- eprofiles = JSON.parse (s);
- } catch (e) {
- Logger.error ("%s\nPARSING DATA: %s".format (e.message, s));
- }
- s = settings.get_string (PROFILES_KEY);
- if (s) try {
- profiles = JSON.parse (s);
- } catch (e) {
- Logger.error ("%s\nPARSING DATA: %s".format (e.message, s));
- }
-
- this.notebook = new Gtk.Notebook ({expand:true});
- let cssp = get_css_provider ();
- if (cssp) {
- Gtk.StyleContext.add_provider_for_screen (
- this.notebook.get_screen(), cssp, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
- }
-
- this.general = new PageGeneralCPUFreq ();
- this.notebook.add (this.general);
- label = new Gtk.Label ({label: _("General")});
- this.notebook.set_tab_label (this.general, label);
-
- this.monitor_page = new PageMonitorCPUFreq ();
- this.notebook.add (this.monitor_page);
- label = new Gtk.Label ({label: _("Monitor")});
- this.notebook.set_tab_label (this.monitor_page, label);
-
- this.power = new PagePowerCPUFreq ();
- this.notebook.add (this.power);
- label = new Gtk.Label ({label: _("Power Events")});
- this.notebook.set_tab_label (this.power, label);
-
- this.notebook.show_all ();
- }
-});
-
-
-var PageGeneralCPUFreq = new Lang.Class({
- Name: 'PageGeneralCPUFreq',
- Extends: Gtk.Box,
-
- _init: function () {
- this.parent ({orientation:Gtk.Orientation.VERTICAL, margin:6});
- this.border_width = 6;
-
- this.add (new Gtk.Label ({label: "" + _("System") + (""), use_markup:true, xalign:0, margin_top:8}));
- this.cb_startup = Gtk.CheckButton.new_with_label (_("Remember settings"));
- this.cb_startup.tooltip_text = _("Check to restore settings on startup");
- this.cb_startup.margin = 6;
- this.add (this.cb_startup);
- this.cb_startup.active = save;
- this.cb_startup.connect ('toggled', () => {
- save = this.cb_startup.active;
- settings.set_boolean (SAVE_SETTINGS_KEY, save);
- });
-
- this.cb_notify = Gtk.CheckButton.new_with_label (_("Notifications"));
- this.cb_notify.tooltip_text = _("Show System Notifications on Critical States");
- this.cb_notify.margin = 6;
- this.add (this.cb_notify);
- this.cb_notify.active = system_notifications;
- this.cb_notify.connect ('toggled', () => {
- system_notifications = this.cb_notify.active;
- settings.set_boolean (NOTIFY_KEY, system_notifications);
- });
-
- this.add (new Gtk.Label ({label: _("Extension"), use_markup:true, xalign:0, margin_top:12}));
- this.cb_mode = Gtk.CheckButton.new_with_label (_("Extension mode"));
- this.cb_mode.tooltip_text = _("Run main application without window decorations");
- this.cb_mode.margin = 6;
- this.add (this.cb_mode);
- this.cb_mode.active = settings.get_boolean ("extension-mode");;
- this.cb_mode.connect ('toggled', () => {
- settings.set_boolean ("extension-mode", this.cb_mode.active);
- });
- this.cb_splash = Gtk.CheckButton.new_with_label (_("Splash Screen"));
- this.cb_splash.tooltip_text = _("Show a splash screen on selecting main application");
- this.cb_splash.margin = 6;
- this.add (this.cb_splash);
- this.cb_splash.active = settings.get_boolean ("show-splash");;
- this.cb_splash.connect ('toggled', () => {
- settings.set_boolean ("show-splash", this.cb_splash.active);
- });
-
- this.add (new Gtk.Label ({label: _("User Interface"), use_markup:true, xalign:0, margin_top:12}));
- this.cb_dark = Gtk.CheckButton.new_with_label (_("Dark theme"));
- this.cb_dark.tooltip_text = _("Prefer dark theme");
- this.cb_dark.margin = 6;
- this.add (this.cb_dark);
- this.cb_dark.active = dark;
- this.cb_dark.connect ('toggled', () => {
- dark = this.cb_dark.active;
- settings.set_boolean (DARK_THEME_KEY, dark);
- });
-
- this.show_all ();
- }
-});
-
-var PageMonitorCPUFreq = new Lang.Class({
- Name: 'PageMonitorCPUFreq',
- Extends: Gtk.Box,
-
- _init: function () {
- this.parent ({orientation:Gtk.Orientation.VERTICAL, margin:6});
- let id = 0, i = 0, rb;
- this.border_width = 6;
-
- let hbox = new Gtk.Box ({orientation:Gtk.Orientation.HORIZONTAL, margin:8});
- this.pack_start (hbox, false, false, 0);
- hbox.add (new Gtk.Label ({label: _("Monitoring Interval (ms)")}));
- this.timeout = Gtk.SpinButton.new_with_range (0, 1000000, 50);
- this.timeout.tooltip_text = _("1000ms - default, 0 - disable");
- this.timeout.value = monitor_timeout;
- this.timeout.connect ('value_changed', () => {
- monitor_timeout = this.timeout.value;
- settings.set_int (MONITOR_KEY, monitor_timeout);
- });
- hbox.pack_end (this.timeout, false, false, 0);
-
- hbox = new Gtk.Box ({orientation:Gtk.Orientation.HORIZONTAL, margin:6, margin_left:32});
- this.pack_start (hbox, false, false, 0);
- hbox.pack_start (new Gtk.Label ({label: _("Show"), xalign:0.0}), false, false, 0);
-
- let cb_units = Gtk.CheckButton.new_with_label (_("Frequency"));
- cb_units.tooltip_text = _("Monitor frequency");
- cb_units.margin_start = 32;
- cb_units.active = frequency_show;
- hbox.pack_start (cb_units, true, true, 8);
- cb_units.connect ('toggled', (o) => {
- frequency_show = o.active;
- settings.set_boolean (FREQ_SHOW_KEY, frequency_show);
- });
-
- cb_units = Gtk.CheckButton.new_with_label (_("Governors"));
- cb_units.tooltip_text = _("Monitor governors");
- cb_units.active = governor_show;
- hbox.pack_start (cb_units, true, true, 8);
- cb_units.connect ('toggled', (o) => {
- governor_show = o.active;
- settings.set_boolean (GOVS_SHOW_KEY, governor_show);
- });
-
- cb_units = Gtk.CheckButton.new_with_label (_("Loading"));
- cb_units.tooltip_text = _("Monitor system loading");
- cb_units.active = load_show;
- hbox.pack_start (cb_units, true, true, 8);
- cb_units.connect ('toggled', (o) => {
- load_show = o.active;
- settings.set_boolean (LOAD_SHOW_KEY, load_show);
- });
-
- this.cb_units = Gtk.CheckButton.new_with_label (_("Show Measurement Units"));
- this.cb_units.tooltip_text = _("Show measurement units for frequencies");
- this.cb_units.margin = 6;
- this.add (this.cb_units);
- this.cb_units.active = units_show;
- this.cb_units.connect ('toggled', (o) => {
- units_show = o.active;
- settings.set_boolean (UNITS_SHOW_KEY, units_show);
- });
-
- this.cb_label = Gtk.CheckButton.new_with_label (_("Show Custom Label"));
- this.cb_label.tooltip_text = _("Always show the custom label");
- this.cb_label.margin = 6;
- this.add (this.cb_label);
- this.cb_label.active = label_show;
- this.cb_label.connect ('toggled', (o) => {
- label_show = o.active;
- settings.set_boolean (LABEL_SHOW_KEY, label_show);
- });
-
- hbox = new Gtk.Box ({orientation:Gtk.Orientation.HORIZONTAL, margin:8});
- this.pack_start (hbox, false, false, 0);
- hbox.add (new Gtk.Label ({label: _("Custom label when monitoring disabled")}));
- this.store = new Gtk.ListStore ();
- this.store.set_column_types ([GObject.TYPE_STRING]);
- this.completion = new Gtk.EntryCompletion ();
- this.completion.minimum_key_length = 0;
- this.completion.set_model (this.store);
- this.completion.set_text_column (0);
- suggestions.forEach ( l => {
- this.store.set (this.store.append (), [0], [l]);
- });
-
- this.label = new Gtk.Entry ();
- this.label.set_completion (this.completion);
- this.label.get_style_context().add_class ("cpufreq-text");
- this.label.tooltip_text = _("Label or just a symbol to show when monitor disabled");
- this.label.set_text (label_text);
- this.label.connect ('changed', (o) => {
- var s = o.text;
- settings.set_string (LABEL_KEY, s);
- });
-
- hbox.pack_end (this.label, false, false, 0);
-
- hbox = new Gtk.Box ({orientation:Gtk.Orientation.HORIZONTAL, margin:6});
- this.pack_start (hbox, false, false, 0);
- this.cb_color = Gtk.CheckButton.new_with_label (_("Use color"));
- this.cb_color.tooltip_text = _("Colorful Monitor's title depending on warning state");
- this.cb_color.active = color_show;
- hbox.pack_start (this.cb_color, true, true, 0);
- this.cb_color.connect ('toggled', (o) => {
- color_show = o.active;
- settings.set_boolean (COLOR_SHOW_KEY, color_show);
- this.colorbox.sensitive = color_show && color_show_custom;
- });
- rb = Gtk.RadioButton.new_with_label_from_widget (null, _("Default colors"));
- rb.active = !settings.get_boolean (COLOR_SHOW_CUSTOM_KEY);
- rb.id = 0;
- hbox.pack_start(rb, true, true, 8);
- rb.connect ('toggled', (o) => {
- color_show_custom = !o.active;
- settings.set_boolean (COLOR_SHOW_CUSTOM_KEY, color_show_custom);
- });
- rb = Gtk.RadioButton.new_with_label_from_widget (rb, _("Custom colors"));
- rb.active = settings.get_boolean (COLOR_SHOW_CUSTOM_KEY);
- rb.id = 1;
- hbox.pack_start (rb, true, true, 8);
- rb.connect ('toggled', (o) => {
- color_show_custom = o.active;
- settings.set_boolean (COLOR_SHOW_CUSTOM_KEY, color_show_custom);
- this.colorbox.sensitive = color_show && color_show_custom;
- });
-
- this.colorbox = new Gtk.Box ({orientation:Gtk.Orientation.HORIZONTAL, margin:8});
- this.pack_start (this.colorbox, false, false, 0);
-
- this.colorbox.add (new Gtk.Label ({label: _("Normal")}));
- let [ ,color] = Gdk.Color.parse (color_show_custom_normal);
- this.color_normal = Gtk.ColorButton.new_with_color (color);
- this.color_normal.connect ('color-set', (o) => {
- settings.set_string (COLOR_SHOW_CUSTOM_NORMAL_KEY, this.color_string (o.rgba));
- });
- this.colorbox.pack_start (this.color_normal, true, false, 0);
-
- this.colorbox.add (new Gtk.Label ({label: _("Warning")}));
- [ ,color] = Gdk.Color.parse (color_show_custom_warning);
- this.color_warning = Gtk.ColorButton.new_with_color (color);
- this.color_warning.connect ('color-set', (o) => {
- settings.set_string (COLOR_SHOW_CUSTOM_WARNING_KEY, this.color_string (o.rgba));
- });
- this.colorbox.pack_start (this.color_warning, true, false, 0);
-
- this.colorbox.add (new Gtk.Label ({label: _("Critical")}));
- [ ,color] = Gdk.Color.parse (color_show_custom_critical);
- this.color_critical = Gtk.ColorButton.new_with_color (color);
- this.color_critical.connect ('color-set', (o) => {
- settings.set_string (COLOR_SHOW_CUSTOM_CRITICAL_KEY, this.color_string (o.rgba));
- });
- this.colorbox.pack_start (this.color_critical, true, false, 0);
- this.colorbox.sensitive = color_show && color_show_custom;
-
- this.show_all ();
- },
-
- color_string: function (rgba) {
- let s = "#%02x%02x%02x".format (
- this.scale_round (rgba.red),
- this.scale_round (rgba.green),
- this.scale_round (rgba.blue)
- );
- return s;
- },
-
- scale_round: function (val) {
- val = Math.floor (val * 255 + 0.5);
- val = Math.max (val, 0);
- val = Math.min (val, 255);
- return val;
- }
-});
-
-var PagePowerCPUFreq = new Lang.Class({
- Name: 'PagePowerCPUFreq',
- Extends: Gtk.Box,
-
- _init: function () {
- this.parent ({orientation:Gtk.Orientation.VERTICAL, margin:6});
- this.border_width = 6;
-
- this.unplug = new PowerProfile (eprofiles[EventType.DISCHARGING],
- _("On Battery"),
- _("You can set less than 100% of the battery level. ") +
- _("It will do not apply \"Powersaving Profile\" immediately on the event. ") +
- _("It could be helpful on temporary disconnections, issues with a power connector, etc.")
- );
- this.add (this.unplug);
- this.unplug.combo.connect ('changed', (o) => {
- if (o.active == 0)
- eprofiles[EventType.DISCHARGING].guid = "";
- else if (o.active <= auto_profiles.length)
- eprofiles[EventType.DISCHARGING].guid = auto_profiles[o.active - 1].guid;
- else
- eprofiles[EventType.DISCHARGING].guid = profiles[o.active - auto_profiles.length - 1].guid;
- //this.unplug.slider.set_value (100);
- settings.set_string (EPROFILES_KEY, JSON.stringify (eprofiles));
- });
- this.unplug.slider.connect ('value_changed', (o) => {
- eprofiles[EventType.DISCHARGING].percent = Math.round (o.get_value ());
- settings.set_string (EPROFILES_KEY, JSON.stringify (eprofiles));
- });
-
- this.show_all ();
- }
-});
-
-var PowerProfile = new Lang.Class({
- Name: 'PowerProfile',
- Extends: Gtk.Box,
-
- _init: function (profile, text, tooltip) {
- this.parent ({orientation:Gtk.Orientation.VERTICAL, margin:6});
- this.tooltip_text = tooltip;
- this.border_width = 6;
- let id = 0, i = 1;
-
- let hbox = new Gtk.Box ({orientation:Gtk.Orientation.HORIZONTAL});
- this.pack_start (hbox, false, false, 0);
- hbox.add (new Gtk.Label ({label:""+text+"",use_markup:true,xalign:0}));
- this.combo = new Gtk.ComboBoxText ();
- this.combo.tooltip_text = _("Power Profile");
- this.combo.append_text (_("do nothing"));
- auto_profiles.forEach (s => {
- this.combo.append_text (s.name);
- if (s.guid == profile.guid) id = i;
- i++;
- });
- profiles.forEach (s => {
- this.combo.append_text (s.name + " (user profile)");
- if (s.guid == profile.guid) id = i;
- i++;
- });
- this.combo.active = id;
- hbox.pack_end (this.combo, false, false, 0);
-
- hbox = new Gtk.Box ({orientation:Gtk.Orientation.HORIZONTAL});
- hbox.margin_top = 8;
- this.add (hbox);
- this.label = new Gtk.Label ({label:_("Level"), use_markup:true, xalign:0});
- hbox.pack_start (this.label, true, true, 0);
- this.info = new Gtk.Label ({label:""+profile.percent+"%", use_markup:true});
- hbox.pack_end (this.info, false, false, 0);
- this.slider = Gtk.Scale.new_with_range (Gtk.Orientation.HORIZONTAL, 0, 100, 1);
- this.slider.draw_value = false;
- this.slider.set_value (profile.percent);
- this.add (this.slider);
- this.slider.connect('value_changed', (o) => {
- this.update_info (Math.round (o.get_value ()).toString ());
- });
-
- this.show_all ();
- },
-
- update_info: function (info) {
- this.info.set_markup ("" + info + "%");
- }
-});
-
-const css_theme = " \
-.cpufreq-text { font-family: cpufreq, roboto, cantarell} \
-";
-
-function get_css_provider () {
- let cssp = new Gtk.CssProvider ();
+export default class CPUFreqPreferences extends ExtensionPreferences {
+ fillPreferencesWindow(window) {
try {
- cssp.load_from_data (css_theme);
- } catch (e) {
- print (e);
- cssp = null;
- }
- return cssp;
-}
-
-function getCurrentFile () {
- let stack = (new Error()).stack;
- let stackLine = stack.split('\n')[1];
- if (!stackLine)
- throw new Error ('Could not find current file');
- let match = new RegExp ('@(.+):\\d+').exec(stackLine);
- if (!match)
- throw new Error ('Could not find current file');
- let path = match[1];
- let file = Gio.File.new_for_path (path);
- return [file.get_path(), file.get_parent().get_path(), file.get_basename()];
-}
-
-function debug (msg) {
- if (msg) print ("[cpufreq][prefs] " + msg);
-}
-
-function error (msg) {
- log ("[cpufreq][prefs] (EE) " + msg);
-}
-
-function init () {
- Convenience.initTranslations ();
-}
-
-function buildPrefsWidget () {
- if (Gtk.MAJOR_VERSION > 3) {
- GLib.spawn_command_line_async (APPDIR + "/cpufreq-preferences");
- let widget = new DumpWidget ();
- return widget;
- }
- let widget = new CPUFreqPreferences ();
- return widget.notebook;
-}
-
-var DumpWidget = new Lang.Class({
- Name: 'DumpWidget',
- Extends: Gtk.Box,
-
- _init: function () {
- this.parent ({});
- /*this.connect ('realize', () => {
- this.get_parent ().get_parent ().close ();
- });*/
- }
-});
-
-function get_appdir () {
- let s = getCurrentFile ()[1];
- if (GLib.file_test (s + "/prefs.js", GLib.FileTest.EXISTS)) return s;
- s = GLib.get_home_dir () + "/.local/share/gnome-shell/extensions/cpufreq@konkor";
- if (GLib.file_test (s + "/prefs.js", GLib.FileTest.EXISTS)) return s;
- s = "/usr/local/share/gnome-shell/extensions/cpufreq@konkor";
- if (GLib.file_test (s + "/prefs.js", GLib.FileTest.EXISTS)) return s;
- s = "/usr/share/gnome-shell/extensions/cpufreq@konkor";
- if (GLib.file_test (s + "/prefs.js", GLib.FileTest.EXISTS)) return s;
- throw "CPUFreq installation not found...";
- return s;
+ // CPUFreq's dedicated Gtk3 preferences UI is not compatible with GNOME Shell 45+
+ // preferences hosting; open the manager app instead.
+ GLib.spawn_command_line_async(`${this.path}/cpufreq-application`);
+ } catch (error) {
+ logError(error, '[cpufreq] Failed to launch cpufreq-application');
+ }
+
+ // CPUFreq uses a dedicated preferences app; close the stub window.
+ GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => {
+ try {
+ window.close();
+ } catch {
+ try {
+ window.destroy();
+ } catch {
+ // ignore
+ }
+ }
+ return GLib.SOURCE_REMOVE;
+ });
+ }
}
diff --git a/prefs_legacy.js b/prefs_legacy.js
new file mode 100644
index 0000000..1028c94
--- /dev/null
+++ b/prefs_legacy.js
@@ -0,0 +1,559 @@
+/*
+ * Legacy GTK3 preferences implementation.
+ *
+ * This file exists for the standalone `cpufreq-preferences` app (Gtk3/GJS classic
+ * imports). GNOME Shell 45+ loads `prefs.js` as an ES module.
+ */
+
+/*
+ * This is a part of CPUFreq Manager
+ * Copyright (C) 2016-2019 konkor
+ *
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see .
+ */
+
+const Lang = imports.lang;
+const GObject = imports.gi.GObject;
+const GLib = imports.gi.GLib;
+const Gio = imports.gi.Gio;
+const Gtk = imports.gi.Gtk;
+const Gdk = imports.gi.Gdk;
+
+var Format = imports.format;
+String.prototype.format = Format.format;
+
+const APPDIR = get_appdir ();
+imports.searchPath.unshift(APPDIR);
+const Logger = imports.common.Logger;
+
+const SAVE_SETTINGS_KEY = 'save-settings';
+const NOTIFY_KEY = 'notifications';
+const DARK_THEME_KEY = 'dark-theme';
+const PROFILES_KEY = 'profiles';
+const EPROFILES_KEY = 'event-profiles';
+const MONITOR_KEY = 'monitor';
+const LABEL_KEY = 'label';
+const LABEL_SHOW_KEY = 'label-show';
+const UNITS_SHOW_KEY = 'units-show';
+const LOAD_SHOW_KEY = 'load-show';
+const GOVS_SHOW_KEY = 'governors-show';
+const FREQ_SHOW_KEY = 'frequency-show';
+
+const COLOR_SHOW_KEY = 'color-show';
+const COLOR_SHOW_CUSTOM_KEY = 'color-show-custom';
+const COLOR_SHOW_CUSTOM_NORMAL_KEY = 'color-show-custom-normal';
+const COLOR_SHOW_CUSTOM_WARNING_KEY = 'color-show-custom-warning';
+const COLOR_SHOW_CUSTOM_CRITICAL_KEY = 'color-show-custom-critical';
+
+const Gettext = imports.gettext.domain ('org-konkor-cpufreq');
+const _ = Gettext.gettext;
+
+const EXTENSIONDIR = getCurrentFile ()[1];
+imports.searchPath.unshift (EXTENSIONDIR);
+const Convenience = imports.convenience;
+
+var EventType = {
+CHARGING: 0,
+DISCHARGING: 1
+};
+
+const suggestions = ["☃","⚡","㎒","㎓","","","","","","","","CPU"];
+
+let save = false;
+let dark = false;
+let profiles = [];
+let monitor_timeout = 500;
+let label_text = "\u269b";
+let label_show = false;
+let frequency_show = true;
+let governor_show = false;
+let load_show = false;
+let units_show = true;
+let system_notifications = false;
+
+let auto_profiles = [
+ {name:_("Battery"), guid:"battery"},
+ {name:_("Balanced"), guid:"balanced"},
+ {name:_("High Performance"), guid:"performance"}
+];
+
+let color_show = false;
+let color_show_custom = false;
+let color_show_custom_normal = '#ebebeb';
+let color_show_custom_warning = '#ebebeb';
+let color_show_custom_critical = '#ff0000';
+
+let eprofiles = [
+ {percent:0, event:EventType.CHARGING, guid:""},
+ {percent:100, event:EventType.DISCHARGING, guid:""}
+];
+
+let settings = false;
+
+var CPUFreqPreferences = new Lang.Class({
+ Name: 'CPUFreqPreferences',
+
+ _init: function () {
+ this.parent (0.0, "CPUFreq Preferences", false);
+ let label, s;
+
+ settings = Convenience.getSettings ();
+ save = settings.get_boolean (SAVE_SETTINGS_KEY);
+ dark = settings.get_boolean (DARK_THEME_KEY);
+ monitor_timeout = settings.get_int (MONITOR_KEY);
+ label_text = settings.get_string (LABEL_KEY);
+ label_show = settings.get_boolean (LABEL_SHOW_KEY);
+ load_show = settings.get_boolean (LOAD_SHOW_KEY);
+ governor_show = settings.get_boolean (GOVS_SHOW_KEY);
+ frequency_show = settings.get_boolean (FREQ_SHOW_KEY);
+ units_show = settings.get_boolean (UNITS_SHOW_KEY);
+ system_notifications = settings.get_boolean (NOTIFY_KEY);
+
+ color_show = settings.get_boolean (COLOR_SHOW_KEY);
+ color_show_custom = settings.get_boolean (COLOR_SHOW_CUSTOM_KEY);
+ color_show_custom_normal = settings.get_string (COLOR_SHOW_CUSTOM_NORMAL_KEY);
+ color_show_custom_warning = settings.get_string (COLOR_SHOW_CUSTOM_WARNING_KEY);
+ color_show_custom_critical = settings.get_string (COLOR_SHOW_CUSTOM_CRITICAL_KEY);
+
+ s = settings.get_string (EPROFILES_KEY);
+ if (s) try {
+ eprofiles = JSON.parse (s);
+ } catch (e) {
+ Logger.error ("%s\nPARSING DATA: %s".format (e.message, s));
+ }
+ s = settings.get_string (PROFILES_KEY);
+ if (s) try {
+ profiles = JSON.parse (s);
+ } catch (e) {
+ Logger.error ("%s\nPARSING DATA: %s".format (e.message, s));
+ }
+
+ this.notebook = new Gtk.Notebook ({expand:true});
+ let cssp = get_css_provider ();
+ if (cssp) {
+ Gtk.StyleContext.add_provider_for_screen (
+ this.notebook.get_screen(), cssp, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
+ }
+
+ this.general = new PageGeneralCPUFreq ();
+ this.notebook.add (this.general);
+ label = new Gtk.Label ({label: _("General")});
+ this.notebook.set_tab_label (this.general, label);
+
+ this.monitor_page = new PageMonitorCPUFreq ();
+ this.notebook.add (this.monitor_page);
+ label = new Gtk.Label ({label: _("Monitor")});
+ this.notebook.set_tab_label (this.monitor_page, label);
+
+ this.power = new PagePowerCPUFreq ();
+ this.notebook.add (this.power);
+ label = new Gtk.Label ({label: _("Power Events")});
+ this.notebook.set_tab_label (this.power, label);
+
+ this.notebook.show_all ();
+ }
+});
+
+
+var PageGeneralCPUFreq = new Lang.Class({
+ Name: 'PageGeneralCPUFreq',
+ Extends: Gtk.Box,
+
+ _init: function () {
+ this.parent ({orientation:Gtk.Orientation.VERTICAL, margin:6});
+ this.border_width = 6;
+
+ this.add (new Gtk.Label ({label: "" + _("System") + (""), use_markup:true, xalign:0, margin_top:8}));
+ this.cb_startup = Gtk.CheckButton.new_with_label (_("Remember settings"));
+ this.cb_startup.tooltip_text = _("Check to restore settings on startup");
+ this.cb_startup.margin = 6;
+ this.add (this.cb_startup);
+ this.cb_startup.active = save;
+ this.cb_startup.connect ('toggled', () => {
+ save = this.cb_startup.active;
+ settings.set_boolean (SAVE_SETTINGS_KEY, save);
+ });
+
+ this.cb_notify = Gtk.CheckButton.new_with_label (_("Notifications"));
+ this.cb_notify.tooltip_text = _("Show System Notifications on Critical States");
+ this.cb_notify.margin = 6;
+ this.add (this.cb_notify);
+ this.cb_notify.active = system_notifications;
+ this.cb_notify.connect ('toggled', () => {
+ system_notifications = this.cb_notify.active;
+ settings.set_boolean (NOTIFY_KEY, system_notifications);
+ });
+
+ this.add (new Gtk.Label ({label: _("Extension"), use_markup:true, xalign:0, margin_top:12}));
+ this.cb_mode = Gtk.CheckButton.new_with_label (_("Extension mode"));
+ this.cb_mode.tooltip_text = _("Run main application without window decorations");
+ this.cb_mode.margin = 6;
+ this.add (this.cb_mode);
+ this.cb_mode.active = settings.get_boolean ("extension-mode");;
+ this.cb_mode.connect ('toggled', () => {
+ settings.set_boolean ("extension-mode", this.cb_mode.active);
+ });
+ this.cb_splash = Gtk.CheckButton.new_with_label (_("Splash Screen"));
+ this.cb_splash.tooltip_text = _("Show a splash screen on selecting main application");
+ this.cb_splash.margin = 6;
+ this.add (this.cb_splash);
+ this.cb_splash.active = settings.get_boolean ("show-splash");;
+ this.cb_splash.connect ('toggled', () => {
+ settings.set_boolean ("show-splash", this.cb_splash.active);
+ });
+
+
+ this.add (new Gtk.Label ({label: _("User Interface"), use_markup:true, xalign:0, margin_top:12}));
+ this.cb_dark = Gtk.CheckButton.new_with_label (_("Dark theme"));
+ this.cb_dark.tooltip_text = _("Prefer dark theme");
+ this.cb_dark.margin = 6;
+ this.add (this.cb_dark);
+ this.cb_dark.active = dark;
+ this.cb_dark.connect ('toggled', () => {
+ dark = this.cb_dark.active;
+ settings.set_boolean (DARK_THEME_KEY, dark);
+ });
+
+ this.show_all ();
+ }
+});
+
+var PageMonitorCPUFreq = new Lang.Class({
+ Name: 'PageMonitorCPUFreq',
+ Extends: Gtk.Box,
+
+ _init: function () {
+ this.parent ({orientation:Gtk.Orientation.VERTICAL, margin:6});
+ let id = 0, i = 0, rb;
+ this.border_width = 6;
+
+ let hbox = new Gtk.Box ({orientation:Gtk.Orientation.HORIZONTAL, margin:8});
+ this.pack_start (hbox, false, false, 0);
+ hbox.add (new Gtk.Label ({label: _("Monitoring Interval (ms)")}));
+ this.timeout = Gtk.SpinButton.new_with_range (0, 1000000, 50);
+ this.timeout.tooltip_text = _("1000ms - default, 0 - disable");
+ this.timeout.value = monitor_timeout;
+ this.timeout.connect ('value_changed', () => {
+ monitor_timeout = this.timeout.value;
+ settings.set_int (MONITOR_KEY, monitor_timeout);
+ });
+ hbox.pack_end (this.timeout, false, false, 0);
+
+ hbox = new Gtk.Box ({orientation:Gtk.Orientation.HORIZONTAL, margin:6, margin_left:32});
+ this.pack_start (hbox, false, false, 0);
+ hbox.pack_start (new Gtk.Label ({label: _("Show"), xalign:0.0}), false, false, 0);
+
+ let cb_units = Gtk.CheckButton.new_with_label (_("Frequency"));
+ cb_units.tooltip_text = _("Monitor frequency");
+ cb_units.margin_start = 32;
+ cb_units.active = frequency_show;
+ hbox.pack_start (cb_units, true, true, 8);
+ cb_units.connect ('toggled', (o) => {
+ frequency_show = o.active;
+ settings.set_boolean (FREQ_SHOW_KEY, frequency_show);
+ });
+
+ cb_units = Gtk.CheckButton.new_with_label (_("Governors"));
+ cb_units.tooltip_text = _("Monitor governors");
+ cb_units.active = governor_show;
+ hbox.pack_start (cb_units, true, true, 8);
+ cb_units.connect ('toggled', (o) => {
+ governor_show = o.active;
+ settings.set_boolean (GOVS_SHOW_KEY, governor_show);
+ });
+
+ cb_units = Gtk.CheckButton.new_with_label (_("Loading"));
+ cb_units.tooltip_text = _("Monitor system loading");
+ cb_units.active = load_show;
+ hbox.pack_start (cb_units, true, true, 8);
+ cb_units.connect ('toggled', (o) => {
+ load_show = o.active;
+ settings.set_boolean (LOAD_SHOW_KEY, load_show);
+ });
+
+ this.cb_units = Gtk.CheckButton.new_with_label (_("Show Measurement Units"));
+ this.cb_units.tooltip_text = _("Show measurement units for frequencies");
+ this.cb_units.margin = 6;
+ this.add (this.cb_units);
+ this.cb_units.active = units_show;
+ this.cb_units.connect ('toggled', (o) => {
+ units_show = o.active;
+ settings.set_boolean (UNITS_SHOW_KEY, units_show);
+ });
+
+ this.cb_label = Gtk.CheckButton.new_with_label (_("Show Custom Label"));
+ this.cb_label.tooltip_text = _("Always show the custom label");
+ this.cb_label.margin = 6;
+ this.add (this.cb_label);
+ this.cb_label.active = label_show;
+ this.cb_label.connect ('toggled', (o) => {
+ label_show = o.active;
+ settings.set_boolean (LABEL_SHOW_KEY, label_show);
+ });
+
+ hbox = new Gtk.Box ({orientation:Gtk.Orientation.HORIZONTAL, margin:8});
+ this.pack_start (hbox, false, false, 0);
+ hbox.add (new Gtk.Label ({label: _("Custom label when monitoring disabled")}));
+ this.store = new Gtk.ListStore ();
+ this.store.set_column_types ([GObject.TYPE_STRING]);
+ this.completion = new Gtk.EntryCompletion ();
+ this.completion.minimum_key_length = 0;
+ this.completion.set_model (this.store);
+ this.completion.set_text_column (0);
+ suggestions.forEach ( l => {
+ this.store.set (this.store.append (), [0], [l]);
+ });
+
+ this.label = new Gtk.Entry ();
+ this.label.set_completion (this.completion);
+ this.label.get_style_context().add_class ("cpufreq-text");
+ this.label.tooltip_text = _("Label or just a symbol to show when monitor disabled");
+ this.label.set_text (label_text);
+ this.label.connect ('changed', (o) => {
+ var s = o.text;
+ settings.set_string (LABEL_KEY, s);
+ });
+
+ hbox.pack_end (this.label, false, false, 0);
+
+ hbox = new Gtk.Box ({orientation:Gtk.Orientation.HORIZONTAL, margin:6});
+ this.pack_start (hbox, false, false, 0);
+ this.cb_color = Gtk.CheckButton.new_with_label (_("Use color"));
+ this.cb_color.tooltip_text = _("Colorful Monitor's title depending on warning state");
+ this.cb_color.active = color_show;
+ hbox.pack_start (this.cb_color, true, true, 0);
+ this.cb_color.connect ('toggled', (o) => {
+ color_show = o.active;
+ settings.set_boolean (COLOR_SHOW_KEY, color_show);
+ this.colorbox.sensitive = color_show && color_show_custom;
+ });
+ rb = Gtk.RadioButton.new_with_label_from_widget (null, _("Default colors"));
+ rb.active = !settings.get_boolean (COLOR_SHOW_CUSTOM_KEY);
+ rb.id = 0;
+ hbox.pack_start(rb, true, true, 8);
+ rb.connect ('toggled', (o) => {
+ color_show_custom = !o.active;
+ settings.set_boolean (COLOR_SHOW_CUSTOM_KEY, color_show_custom);
+ });
+ rb = Gtk.RadioButton.new_with_label_from_widget (rb, _("Custom colors"));
+ rb.active = settings.get_boolean (COLOR_SHOW_CUSTOM_KEY);
+ rb.id = 1;
+ hbox.pack_start (rb, true, true, 8);
+ rb.connect ('toggled', (o) => {
+ color_show_custom = o.active;
+ settings.set_boolean (COLOR_SHOW_CUSTOM_KEY, color_show_custom);
+ this.colorbox.sensitive = color_show && color_show_custom;
+ });
+
+ this.colorbox = new Gtk.Box ({orientation:Gtk.Orientation.HORIZONTAL, margin:8});
+ this.pack_start (this.colorbox, false, false, 0);
+
+ this.colorbox.add (new Gtk.Label ({label: _("Normal")}));
+ let [ ,color] = Gdk.Color.parse (color_show_custom_normal);
+ this.color_normal = Gtk.ColorButton.new_with_color (color);
+ this.color_normal.connect ('color-set', (o) => {
+ settings.set_string (COLOR_SHOW_CUSTOM_NORMAL_KEY, this.color_string (o.rgba));
+ });
+ this.colorbox.pack_start (this.color_normal, true, false, 0);
+
+ this.colorbox.add (new Gtk.Label ({label: _("Warning")}));
+ [ ,color] = Gdk.Color.parse (color_show_custom_warning);
+ this.color_warning = Gtk.ColorButton.new_with_color (color);
+ this.color_warning.connect ('color-set', (o) => {
+ settings.set_string (COLOR_SHOW_CUSTOM_WARNING_KEY, this.color_string (o.rgba));
+ });
+ this.colorbox.pack_start (this.color_warning, true, false, 0);
+
+ this.colorbox.add (new Gtk.Label ({label: _("Critical")}));
+ [ ,color] = Gdk.Color.parse (color_show_custom_critical);
+ this.color_critical = Gtk.ColorButton.new_with_color (color);
+ this.color_critical.connect ('color-set', (o) => {
+ settings.set_string (COLOR_SHOW_CUSTOM_CRITICAL_KEY, this.color_string (o.rgba));
+ });
+ this.colorbox.pack_start (this.color_critical, true, false, 0);
+ this.colorbox.sensitive = color_show && color_show_custom;
+
+ this.show_all ();
+ },
+
+ color_string: function (rgba) {
+ let s = "#%02x%02x%02x".format (
+ this.scale_round (rgba.red),
+ this.scale_round (rgba.green),
+ this.scale_round (rgba.blue)
+ );
+ return s;
+ },
+
+ scale_round: function (val) {
+ val = Math.floor (val * 255 + 0.5);
+ val = Math.max (val, 0);
+ val = Math.min (val, 255);
+ return val;
+ }
+});
+
+var PagePowerCPUFreq = new Lang.Class({
+ Name: 'PagePowerCPUFreq',
+ Extends: Gtk.Box,
+
+ _init: function () {
+ this.parent ({orientation:Gtk.Orientation.VERTICAL, margin:6});
+ this.border_width = 6;
+
+ this.unplug = new PowerProfile (eprofiles[EventType.DISCHARGING],
+ _("On Battery"),
+
+ _("You can set less than 100% of the battery level. ") +
+ _("It will do not apply \"Powersaving Profile\" immediately on the event. ") +
+ _("It could be helpful on temporary disconnections, issues with a power connector, etc.")
+ );
+ this.add (this.unplug);
+ this.unplug.combo.connect ('changed', (o) => {
+ if (o.active == 0)
+ eprofiles[EventType.DISCHARGING].guid = "";
+ else if (o.active <= auto_profiles.length)
+ eprofiles[EventType.DISCHARGING].guid = auto_profiles[o.active - 1].guid;
+ else
+ eprofiles[EventType.DISCHARGING].guid = profiles[o.active - auto_profiles.length - 1].guid;
+ //this.unplug.slider.set_value (100);
+ settings.set_string (EPROFILES_KEY, JSON.stringify (eprofiles));
+ });
+ this.unplug.slider.connect ('value_changed', (o) => {
+ eprofiles[EventType.DISCHARGING].percent = Math.round (o.get_value ());
+ settings.set_string (EPROFILES_KEY, JSON.stringify (eprofiles));
+ });
+
+ this.show_all ();
+ }
+});
+
+var PowerProfile = new Lang.Class({
+ Name: 'PowerProfile',
+ Extends: Gtk.Box,
+
+ _init: function (profile, text, tooltip) {
+ this.parent ({orientation:Gtk.Orientation.VERTICAL, margin:6});
+ this.tooltip_text = tooltip;
+ this.border_width = 6;
+ let id = 0, i = 1;
+
+ let hbox = new Gtk.Box ({orientation:Gtk.Orientation.HORIZONTAL});
+ this.pack_start (hbox, false, false, 0);
+ hbox.add (new Gtk.Label ({label:""+text+"",use_markup:true,xalign:0}));
+ this.combo = new Gtk.ComboBoxText ();
+ this.combo.tooltip_text = _("Power Profile");
+ this.combo.append_text (_("do nothing"));
+ auto_profiles.forEach (s => {
+ this.combo.append_text (s.name);
+ if (s.guid == profile.guid) id = i;
+ i++;
+ });
+ profiles.forEach (s => {
+ this.combo.append_text (s.name + " (user profile)");
+ if (s.guid == profile.guid) id = i;
+ i++;
+ });
+ this.combo.active = id;
+ hbox.pack_end (this.combo, false, false, 0);
+
+ hbox = new Gtk.Box ({orientation:Gtk.Orientation.HORIZONTAL});
+ hbox.margin_top = 8;
+ this.add (hbox);
+ this.label = new Gtk.Label ({label:_("Level"), use_markup:true, xalign:0});
+ hbox.pack_start (this.label, true, true, 0);
+ this.info = new Gtk.Label ({label:""+profile.percent+"%", use_markup:true});
+ hbox.pack_end (this.info, false, false, 0);
+ this.slider = Gtk.Scale.new_with_range (Gtk.Orientation.HORIZONTAL, 0, 100, 1);
+ this.slider.draw_value = false;
+ this.slider.set_value (profile.percent);
+ this.add (this.slider);
+ this.slider.connect('value_changed', (o) => {
+ this.update_info (Math.round (o.get_value ()).toString ());
+ });
+
+ this.show_all ();
+ },
+
+ update_info: function (info) {
+ this.info.set_markup ("" + info + "%");
+ }
+});
+
+const css_theme = " \
+.cpufreq-text { font-family: cpufreq, roboto, cantarell} \
+";
+
+function get_css_provider () {
+ let cssp = new Gtk.CssProvider ();
+ try {
+ cssp.load_from_data (css_theme);
+ } catch (e) {
+ print (e);
+ cssp = null;
+ }
+ return cssp;
+}
+
+function getCurrentFile () {
+ let stack = (new Error()).stack;
+ let stackLine = stack.split('\n')[1];
+ if (!stackLine)
+ throw new Error ('Could not find current file');
+ let match = new RegExp ('@(.+):\\d+').exec(stackLine);
+ if (!match)
+ throw new Error ('Could not find current file');
+ let path = match[1];
+ let file = path.startsWith('file://') ? Gio.File.new_for_uri(path) : Gio.File.new_for_path (path);
+ return [file.get_path(), file.get_parent().get_path(), file.get_basename()];
+}
+
+function debug (msg) {
+ if (msg) print ("[cpufreq][prefs] " + msg);
+}
+
+function error (msg) {
+ log ("[cpufreq][prefs] (EE) " + msg);
+}
+
+function init () {
+ Convenience.initTranslations ();
+}
+
+function buildPrefsWidget () {
+ if (Gtk.MAJOR_VERSION > 3) {
+ GLib.spawn_command_line_async (APPDIR + "/cpufreq-preferences");
+ let widget = new DumpWidget ();
+ return widget;
+ }
+ let widget = new CPUFreqPreferences ();
+ return widget.notebook;
+}
+
+var DumpWidget = new Lang.Class({
+ Name: 'DumpWidget',
+ Extends: Gtk.Box,
+
+ _init: function () {
+ this.parent ({});
+ /*this.connect ('realize', () => {
+ this.get_parent ().get_parent ().close ();
+ });*/
+ }
+});
+
+function get_appdir () {
+ let s = getCurrentFile ()[1];
+ if (GLib.file_test (s + "/prefs.js", GLib.FileTest.EXISTS)) return s;
+ s = GLib.get_home_dir () + "/.local/share/gnome-shell/extensions/cpufreq@konkor";
+ if (GLib.file_test (s + "/prefs.js", GLib.FileTest.EXISTS)) return s;
+ s = "/usr/local/share/gnome-shell/extensions/cpufreq@konkor";
+ if (GLib.file_test (s + "/prefs.js", GLib.FileTest.EXISTS)) return s;
+ s = "/usr/share/gnome-shell/extensions/cpufreq@konkor";
+ if (GLib.file_test (s + "/prefs.js", GLib.FileTest.EXISTS)) return s;
+ throw "CPUFreq installation not found...";
+ return s;
+}