Initial Fedora brightness automation setup
This commit is contained in:
204
bin/brightness-osd
Executable file
204
bin/brightness-osd
Executable file
@@ -0,0 +1,204 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import signal
|
||||
import sys
|
||||
import time
|
||||
|
||||
import gi
|
||||
|
||||
gi.require_version("Gtk", "4.0")
|
||||
gi.require_version("Adw", "1")
|
||||
from gi.repository import Adw, Gdk, GLib, Gtk
|
||||
|
||||
try:
|
||||
gi.require_version("Gtk4LayerShell", "1.0")
|
||||
from gi.repository import Gtk4LayerShell
|
||||
except (ImportError, ValueError):
|
||||
Gtk4LayerShell = None
|
||||
|
||||
|
||||
BACKLIGHT_PATH = os.environ.get(
|
||||
"BRIGHTNESS_OSD_BACKLIGHT", "/sys/class/backlight/intel_backlight"
|
||||
)
|
||||
PID_FILE = os.environ.get("BRIGHTNESS_OSD_PID", "/tmp/brightness-osd.pid")
|
||||
VALUE_FILE = os.environ.get("BRIGHTNESS_OSD_VALUE", "/tmp/brightness-osd.value")
|
||||
VISIBLE_MS = int(os.environ.get("BRIGHTNESS_OSD_VISIBLE_MS", "1400"))
|
||||
|
||||
|
||||
def read_percent():
|
||||
if len(sys.argv) > 1:
|
||||
return max(0, min(100, int(round(float(sys.argv[1])))))
|
||||
|
||||
with open(os.path.join(BACKLIGHT_PATH, "brightness"), encoding="utf-8") as handle:
|
||||
current = int(handle.read().strip())
|
||||
|
||||
with open(os.path.join(BACKLIGHT_PATH, "max_brightness"), encoding="utf-8") as handle:
|
||||
maximum = int(handle.read().strip())
|
||||
|
||||
return max(0, min(100, round(current * 100 / maximum)))
|
||||
|
||||
|
||||
def read_existing_pid():
|
||||
try:
|
||||
with open(PID_FILE, encoding="utf-8") as handle:
|
||||
return int(handle.read().strip())
|
||||
except (FileNotFoundError, ValueError):
|
||||
return None
|
||||
|
||||
|
||||
def process_exists(pid):
|
||||
try:
|
||||
os.kill(pid, 0)
|
||||
return True
|
||||
except ProcessLookupError:
|
||||
return False
|
||||
except PermissionError:
|
||||
return True
|
||||
|
||||
|
||||
def signal_existing(percent):
|
||||
pid = None
|
||||
for _attempt in range(5):
|
||||
pid = read_existing_pid()
|
||||
if pid and pid != os.getpid() and process_exists(pid):
|
||||
break
|
||||
time.sleep(0.03)
|
||||
else:
|
||||
return False
|
||||
|
||||
with open(VALUE_FILE, "w", encoding="utf-8") as handle:
|
||||
handle.write(str(percent))
|
||||
|
||||
try:
|
||||
os.kill(pid, signal.SIGUSR1)
|
||||
return True
|
||||
except ProcessLookupError:
|
||||
return False
|
||||
|
||||
|
||||
class BrightnessOsd(Adw.Application):
|
||||
def __init__(self, percent):
|
||||
super().__init__(application_id="local.brightness.osd")
|
||||
self.percent = percent
|
||||
self.label = None
|
||||
self.bar = None
|
||||
self.timeout_id = None
|
||||
|
||||
def update_percent(self, percent):
|
||||
self.percent = max(0, min(100, percent))
|
||||
|
||||
if self.label:
|
||||
self.label.set_label(f"{self.percent}%")
|
||||
if self.bar:
|
||||
self.bar.set_value(self.percent)
|
||||
|
||||
if self.timeout_id:
|
||||
GLib.source_remove(self.timeout_id)
|
||||
self.timeout_id = GLib.timeout_add(VISIBLE_MS, self.quit)
|
||||
|
||||
def handle_refresh(self, *_args):
|
||||
try:
|
||||
with open(VALUE_FILE, encoding="utf-8") as handle:
|
||||
percent = int(handle.read().strip())
|
||||
except (FileNotFoundError, ValueError):
|
||||
percent = read_percent()
|
||||
|
||||
GLib.idle_add(self.update_percent, percent)
|
||||
|
||||
def do_activate(self):
|
||||
with open(PID_FILE, "w", encoding="utf-8") as handle:
|
||||
handle.write(str(os.getpid()))
|
||||
|
||||
window = Gtk.ApplicationWindow(application=self)
|
||||
window.set_title("Brightness")
|
||||
window.set_decorated(False)
|
||||
window.set_resizable(False)
|
||||
window.set_default_size(190, 58)
|
||||
window.set_opacity(0.92)
|
||||
window.set_hide_on_close(True)
|
||||
|
||||
if Gtk4LayerShell is not None:
|
||||
Gtk4LayerShell.init_for_window(window)
|
||||
Gtk4LayerShell.set_layer(window, Gtk4LayerShell.Layer.OVERLAY)
|
||||
Gtk4LayerShell.set_anchor(window, Gtk4LayerShell.Edge.TOP, True)
|
||||
Gtk4LayerShell.set_margin(window, Gtk4LayerShell.Edge.TOP, 28)
|
||||
Gtk4LayerShell.set_keyboard_mode(window, Gtk4LayerShell.KeyboardMode.NONE)
|
||||
|
||||
css = Gtk.CssProvider()
|
||||
css.load_from_data(
|
||||
b"""
|
||||
window {
|
||||
background: transparent;
|
||||
}
|
||||
.osd {
|
||||
background: alpha(@window_fg_color, 0.88);
|
||||
color: @window_bg_color;
|
||||
border-radius: 15px;
|
||||
padding: 10px 14px;
|
||||
box-shadow: 0 10px 34px alpha(black, 0.34);
|
||||
}
|
||||
.osd image {
|
||||
color: @window_bg_color;
|
||||
}
|
||||
.percent {
|
||||
font-size: 15px;
|
||||
font-weight: 700;
|
||||
}
|
||||
levelbar trough {
|
||||
min-height: 6px;
|
||||
border-radius: 999px;
|
||||
background: alpha(@window_bg_color, 0.24);
|
||||
}
|
||||
levelbar block.filled {
|
||||
min-height: 6px;
|
||||
border-radius: 999px;
|
||||
background: @window_bg_color;
|
||||
}
|
||||
"""
|
||||
)
|
||||
Gtk.StyleContext.add_provider_for_display(
|
||||
Gdk.Display.get_default(), css, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
|
||||
)
|
||||
|
||||
box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
|
||||
box.add_css_class("osd")
|
||||
box.set_halign(Gtk.Align.CENTER)
|
||||
box.set_valign(Gtk.Align.START)
|
||||
box.set_margin_top(28)
|
||||
|
||||
icon = Gtk.Image.new_from_icon_name("display-brightness-symbolic")
|
||||
icon.set_pixel_size(22)
|
||||
|
||||
self.label = Gtk.Label(label=f"{self.percent}%")
|
||||
self.label.add_css_class("percent")
|
||||
self.label.set_width_chars(4)
|
||||
|
||||
self.bar = Gtk.LevelBar.new_for_interval(0, 100)
|
||||
self.bar.set_value(self.percent)
|
||||
self.bar.set_size_request(96, -1)
|
||||
self.bar.set_valign(Gtk.Align.CENTER)
|
||||
|
||||
box.append(icon)
|
||||
box.append(self.bar)
|
||||
box.append(self.label)
|
||||
window.set_child(box)
|
||||
|
||||
signal.signal(signal.SIGUSR1, self.handle_refresh)
|
||||
window.present()
|
||||
self.timeout_id = GLib.timeout_add(VISIBLE_MS, self.quit)
|
||||
|
||||
|
||||
def main():
|
||||
percent = read_percent()
|
||||
if signal_existing(percent):
|
||||
return 0
|
||||
|
||||
with open(PID_FILE, "w", encoding="utf-8") as handle:
|
||||
handle.write(str(os.getpid()))
|
||||
|
||||
app = BrightnessOsd(percent)
|
||||
return app.run([])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user