By using this site, you agree to have cookies stored on your device, strictly for functional purposes, such as storing your session and preferences.

Dismiss

brightness: introduce applet

roundabout,
created on Wednesday, 17 December 2025, 20:58:43 (1766005123), received on Wednesday, 17 December 2025, 20:58:47 (1766005127)
Author identity: Vlad <vlad.muntoiu@gmail.com>

80b238b2f3109c009ee4b1876c62330271c1606e

applets/brightness/__init__.py

@@ -0,0 +1,106 @@

                                
                                
                                
                            
                                
                                    
                                        
                                        """
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        Screen brightness control applet for the Panorama panel.
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        Copyright 2025, roundabout-host.com <vlad@roundabout-host.com>
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        This program is free software: you can redistribute it and/or modify
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        it under the terms of the GNU General Public Licence as published by
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        the Free Software Foundation, either version 3 of the Licence, or
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        (at your option) any later version.
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        This program is distributed in the hope that it will be useful,
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        but WITHOUT ANY WARRANTY; without even the implied warranty of
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        GNU General Public Licence for more details.
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        You should have received a copy of the GNU General Public Licence
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        along with this program. If not, see <https://www.gnu.org/licenses/>.
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        """
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        import os
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        import panorama_panel
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        import pydbus
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        import locale
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        from pathlib import Path
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        from pyudev import Context, Monitor, MonitorObserver
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        import gi
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        gi.require_version("Gtk", "4.0")
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        from gi.repository import Gtk, GLib, Gio
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        module_directory = Path(__file__).resolve().parent
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        locale.bindtextdomain("panorama-panel-file-listing", module_directory / "locale")
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        _ = lambda x: locale.dgettext("panorama-panel-file-listing", x)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        def open_file_and_read_int(path: Path):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            with open(path) as f:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                return int(f.read().strip())
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        class ScreenBrightness(panorama_panel.Applet):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            name = _("Brightness")
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            description = _("Control display brightness")
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def __init__(self, orientation=Gtk.Orientation.HORIZONTAL, config=None):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                super().__init__(orientation=orientation, config=config)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                if config is None:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    config = {}
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.icon = Gtk.Image.new_from_icon_name("display-brightness-symbolic")
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.icon.set_pixel_size(config.get("icon_size", 24))
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.button = Gtk.MenuButton(child=self.icon, has_frame=False)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.append(self.button)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.popover = Gtk.Popover()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.box = Gtk.Box()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.popover.set_child(self.box)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.button.set_popover(self.popover)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.bus = pydbus.SystemBus()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.login1 = self.bus.get("org.freedesktop.login1", "/org/freedesktop/login1")
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.manager = self.bus.get("org.freedesktop.login1", "/org/freedesktop/login1")
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.session = self.bus.get("org.freedesktop.login1", self.manager.GetSessionByPID(os.getpid()))
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.backlights = [path for path in Path("/sys/class/backlight").iterdir()]
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                if not self.backlights:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    self.button.hide()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.adjustments = {}
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.sessions = self.manager.ListSessions()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.udev_context = Context()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.monitor = Monitor.from_netlink(self.udev_context)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.monitor.filter_by(subsystem="backlight")
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.observer = MonitorObserver(self.monitor, callback=self.process_notify)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.observer.start()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.update_backlights()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def process_notify(self, device):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                # Called when the brightness is updated in any way, even externally
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                path = Path("/sys/class/backlight") / device.sys_name
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                adjustment = self.adjustments.get(path)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                value = open_file_and_read_int(path / "brightness")
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                if not adjustment:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    return
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                def update():
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    adjustment.handler_block(adjustment.handler_id)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    adjustment.set_value(value)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    adjustment.handler_unblock(adjustment.handler_id)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    return False
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                GLib.idle_add(update)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def update_backlights(self):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                for backlight in self.backlights:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    max_brightness = open_file_and_read_int(backlight / "max_brightness")
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    current_brightness = open_file_and_read_int(backlight / "brightness")
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    adjustment = Gtk.Adjustment(lower=0, upper=max_brightness, value=current_brightness)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    adjustment.backlight = backlight
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    self.adjustments[backlight] = adjustment
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    adjustment.handler_id = adjustment.connect("value-changed", self.value_changed)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    scale = Gtk.Scale(adjustment=adjustment, width_request=200)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    self.box.append(scale)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def value_changed(self, adjustment, *args):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                name = adjustment.backlight.name
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.session.SetBrightness("backlight", name, int(adjustment.get_value()))
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def get_config(self):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                return {"icon_size": self.icon.get_pixel_size()}
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                            
                                

config.yaml

@@ -65,6 +65,8 @@ panels:

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    icon_size: 24
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    empty_icon_size: 16
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                right:
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            - ScreenBrightness:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                icon_size: 24
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                - BatteryMonitor:
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    icon_size: 24
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    low_threshold: 0.15