Skip to content

Commit a00cb8b

Browse files
authored
power applet/settings: Add support for ambient light sensor. (#13649)
When available via csd-power, adds a switch to the applet underneath the display backlight slider, and one in the backlight section in cinnamon-settings. Ref: linuxmint/cinnamon-settings-daemon#444
1 parent d7ee482 commit a00cb8b

3 files changed

Lines changed: 74 additions & 36 deletions

File tree

files/usr/share/cinnamon/applets/[email protected]/applet.js

Lines changed: 66 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const BrightnessBusName = "org.cinnamon.SettingsDaemon.Power.Screen";
1515
const KeyboardBusName = "org.cinnamon.SettingsDaemon.Power.Keyboard";
1616

1717
const CSD_BACKLIGHT_NOT_SUPPORTED_CODE = 1;
18+
const CSD_SCHEMA = "org.cinnamon.settings-daemon.plugins.power";
1819

1920
const PANEL_EDIT_MODE_KEY = "panel-edit-mode";
2021

@@ -88,21 +89,23 @@ class DeviceItem extends PopupMenu.PopupBaseMenuItem {
8889
}
8990

9091
class BrightnessSlider extends PopupMenu.PopupSliderMenuItem {
91-
constructor(applet, label, icon, busName, minimum_value) {
92+
constructor(applet, label, icon, busName, minimum_value, readyCallback) {
9293
super(0);
9394
this.actor.hide();
9495

9596
this._applet = applet;
9697
this._seeking = false;
9798
this._minimum_value = minimum_value;
9899
this._step = .05;
100+
this._readyCallback = readyCallback || null;
101+
this.proxy = null;
99102

100-
this.connect("drag-begin", Lang.bind(this, function () {
103+
this.connect("drag-begin", () => {
101104
this._seeking = true;
102-
}));
103-
this.connect("drag-end", Lang.bind(this, function () {
105+
});
106+
this.connect("drag-end", () => {
104107
this._seeking = false;
105-
}));
108+
});
106109

107110
this.icon = new St.Icon({ icon_name: icon, icon_type: St.IconType.SYMBOLIC, icon_size: 16 });
108111
this.removeActor(this._slider);
@@ -113,41 +116,45 @@ class BrightnessSlider extends PopupMenu.PopupSliderMenuItem {
113116
this.tooltipText = label;
114117
this.tooltip = new Tooltips.Tooltip(this.actor, this.tooltipText);
115118

116-
Interfaces.getDBusProxyAsync(busName, Lang.bind(this, function (proxy, error) {
117-
this._proxy = proxy;
118-
this._proxy.GetPercentageRemote(Lang.bind(this, this._dbusAcquired));
119-
}));
119+
Interfaces.getDBusProxyAsync(busName, this._dbusAcquired.bind(this));
120120
}
121121

122-
_dbusAcquired(b, error) {
122+
_dbusAcquired(proxy, error) {
123123
if (error)
124124
return;
125125

126+
this.proxy = proxy;
127+
128+
this.connect("value-changed", this._sliderChanged.bind(this));
129+
this.proxy.connectSignal('Changed', this._getBrightness.bind(this));
130+
this._applet.menu.connect("open-state-changed", this._getBrightnessForcedUpdate.bind(this));
131+
132+
if (this._readyCallback) {
133+
this._readyCallback();
134+
}
135+
136+
this.proxy.GetPercentageRemote((b, error) => {
137+
if (error)
138+
return;
139+
140+
this._updateBrightnessLabel(b);
141+
this.setValue(b / 100);
142+
this.actor.show();
143+
});
144+
126145
try {
127-
this._proxy.GetStepRemote((step, error) => {
146+
this.proxy.GetStepRemote((step, error) => {
128147
if (error != null) {
129148
if (error.code != CSD_BACKLIGHT_NOT_SUPPORTED_CODE) {
130-
global.logError(`Could not get backlight step for ${busName}: ${error.message}`);
131-
return;
132-
} else {
133-
this._step = .05;
149+
global.logError(`Could not get backlight step: ${error.message}`);
134150
}
151+
return;
135152
}
136153
this._step = (step / 100);
137154
});
138155
} catch (e) {
139-
this._step = .05;
156+
// step stays at default
140157
}
141-
142-
this._updateBrightnessLabel(b);
143-
this.setValue(b / 100);
144-
this.connect("value-changed", Lang.bind(this, this._sliderChanged));
145-
146-
this.actor.show();
147-
148-
//get notified
149-
this._proxy.connectSignal('Changed', Lang.bind(this, this._getBrightness));
150-
this._applet.menu.connect("open-state-changed", Lang.bind(this, this._getBrightnessForcedUpdate));
151158
}
152159

153160
_sliderChanged(slider, value) {
@@ -190,16 +197,16 @@ class BrightnessSlider extends PopupMenu.PopupSliderMenuItem {
190197
}
191198

192199
_getBrightnessForcedUpdate() {
193-
this._proxy.GetPercentageRemote(Lang.bind(this, function (b) {
200+
this.proxy.GetPercentageRemote((b) => {
194201
this._updateBrightnessLabel(b);
195202
this.setValue(b / 100);
196-
}));
203+
});
197204
}
198205

199206
_setBrightness(value) {
200-
this._proxy.SetPercentageRemote(value, Lang.bind(this, function (b) {
207+
this.proxy.SetPercentageRemote(value, (b) => {
201208
this._updateBrightnessLabel(b);
202-
}));
209+
});
203210
}
204211

205212
_updateBrightnessLabel(value) {
@@ -217,10 +224,10 @@ class BrightnessSlider extends PopupMenu.PopupSliderMenuItem {
217224
let direction = event.get_scroll_direction();
218225

219226
if (direction == Clutter.ScrollDirection.DOWN) {
220-
this._proxy.StepDownRemote(function () { });
227+
this.proxy.StepDownRemote(function () { });
221228
}
222229
else if (direction == Clutter.ScrollDirection.UP) {
223-
this._proxy.StepUpRemote(function () { });
230+
this.proxy.StepUpRemote(function () { });
224231
}
225232

226233
this._slider.queue_repaint();
@@ -253,11 +260,26 @@ class CinnamonPowerApplet extends Applet.TextIconApplet {
253260

254261
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
255262

256-
this.brightness = new BrightnessSlider(this, _("Brightness"), "display-brightness", BrightnessBusName, 0);
263+
this.brightness = new BrightnessSlider(this, _("Brightness"), "display-brightness", BrightnessBusName, 0, () => {
264+
this._updateAmbientVisibility();
265+
this.brightness.proxy.connect("g-properties-changed", () => this._updateAmbientVisibility());
266+
});
257267
this.keyboard = new BrightnessSlider(this, _("Keyboard backlight"), "keyboard-brightness", KeyboardBusName, 0);
258268
this.menu.addMenuItem(this.brightness);
259269
this.menu.addMenuItem(this.keyboard);
260270

271+
this._ambientItem = new PopupMenu.PopupSwitchMenuItem(_("Adjust automatically"), false);
272+
this._ambientItem.actor.hide();
273+
this.menu.addMenuItem(this._ambientItem);
274+
this._csdSettings = new Gio.Settings({ schema_id: CSD_SCHEMA });
275+
this._ambientItem.setToggleState(this._csdSettings.get_boolean("ambient-enabled"));
276+
this._ambientItem.connect("toggled", (item) => {
277+
this._csdSettings.set_boolean("ambient-enabled", item.state);
278+
});
279+
this._csdSettings.connect("changed::ambient-enabled", () => {
280+
this._ambientItem.setToggleState(this._csdSettings.get_boolean("ambient-enabled"));
281+
});
282+
261283
try {
262284
// Hadess interface
263285
let PowerProfilesInterface = `<node>
@@ -346,6 +368,14 @@ class CinnamonPowerApplet extends Applet.TextIconApplet {
346368
this.set_show_label_in_vertical_panels(false);
347369
}
348370

371+
_updateAmbientVisibility() {
372+
if (this.brightness.proxy && this.brightness.proxy.AmbientLightSupported) {
373+
this._ambientItem.actor.show();
374+
} else {
375+
this._ambientItem.actor.hide();
376+
}
377+
}
378+
349379
_onPanelEditModeChanged() {
350380
if (global.settings.get_boolean(PANEL_EDIT_MODE_KEY)) {
351381
if (!this.actor.visible) {
@@ -366,7 +396,7 @@ class CinnamonPowerApplet extends Applet.TextIconApplet {
366396
_onButtonPressEvent(actor, event) {
367397
//toggle keyboard brightness on middle click
368398
if (event.get_button() === 2) {
369-
this.keyboard._proxy.ToggleRemote(function () { });
399+
this.keyboard.proxy.ToggleRemote(function () { });
370400
}
371401
return Applet.Applet.prototype._onButtonPressEvent.call(this, actor, event);
372402
}
@@ -379,9 +409,9 @@ class CinnamonPowerApplet extends Applet.TextIconApplet {
379409
//adjust screen brightness on scroll
380410
let direction = event.get_scroll_direction();
381411
if (direction == Clutter.ScrollDirection.UP) {
382-
this.brightness._proxy.StepUpRemote(function () { });
412+
this.brightness.proxy.StepUpRemote(function () { });
383413
} else if (direction == Clutter.ScrollDirection.DOWN) {
384-
this.brightness._proxy.StepDownRemote(function () { });
414+
this.brightness.proxy.StepDownRemote(function () { });
385415
}
386416
this.brightness._getBrightnessForcedUpdate();
387417
}

files/usr/share/cinnamon/cinnamon-settings/modules/cs_power.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,13 @@ def on_module_selected(self):
267267
section = page.add_section(_("Screen brightness"))
268268
section.add_row(BrightnessSlider(section, proxy, _("Screen brightness")))
269269

270+
try:
271+
ambient_supported = proxy.get_cached_property("AmbientLightSupported")
272+
if ambient_supported is not None and ambient_supported.unpack():
273+
section.add_row(GSettingsSwitch(_("Adjust automatically"), CSD_SCHEMA, "ambient-enabled"))
274+
except Exception as e:
275+
print(f"Power module ambient light check failed: {e}")
276+
270277
section.add_row(GSettingsSwitch(_("On battery, dim screen when inactive"), CSD_SCHEMA, "idle-dim-battery"))
271278

272279
section.add_reveal_row(GSettingsComboBox(_("Brightness level when inactive"), CSD_SCHEMA, "idle-brightness", IDLE_BRIGHTNESS_OPTIONS, valtype=int, size_group=size_group), CSD_SCHEMA, "idle-dim-battery")

js/misc/interfaces.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ xml['org.cinnamon.SettingsDaemon.Power.Screen'] =
129129
<arg type='u' name='new_percentage' direction='out'/> \
130130
</method> \
131131
<signal name='Changed'/> \
132+
<property name='AmbientLightSupported' type='b' access='read'/> \
132133
</interface> \
133134
</node>",
134135
SETTINGS_DAEMON_POWER_NAME,

0 commit comments

Comments
 (0)