Skip to content

Instantly share code, notes, and snippets.

@michael-pisman
Last active March 18, 2025 08:23
Show Gist options
  • Save michael-pisman/53cacea31f93c744ffc8afb583281cef to your computer and use it in GitHub Desktop.
Save michael-pisman/53cacea31f93c744ffc8afb583281cef to your computer and use it in GitHub Desktop.
A simple Qtile widget for controling display brightness with Xrandr
#!/usr/bin/env python3
"""
Brightness Control Widget for Qtile
This module provides a reusable brightness control widget for the Qtile window manager.
It uses the 'xrandr' command to adjust the screen brightness and stores the brightness level
in a configuration file. This file is located under the user's home directory in a folder
named ".screenlayout".
Requirements:
- xrandr must be installed and available in the system path.
- Qtile and its widget base (libqtile.widget.base) must be installed.
Usage:
As a command-line tool:
python brightness.py [brightness_value|up|down] [display_name]
Examples:
python brightness.py up eDP # Increase brightness by 10%
python brightness.py 75 # Set brightness to 75%
python brightness.py # Print current brightness
As a widget in Qtile, instantiate Brightness with the desired parameters.
"""
import sys
from os import system, path
from libqtile.widget import base
# Configuration: Use the current user's home directory for configuration files.
DEFAULT_CONFIG_PATH = path.expanduser("~/.screenlayout/")
DEFAULT_DISPLAY_FILE = 'eDP' # Default display identifier
class Brightness(base.InLoopPollText):
"""
A Qtile widget to control and display screen brightness.
This widget reads the brightness value from a configuration file upon initialization,
updates the screen brightness using 'xrandr', and allows interactive adjustment via
mouse scroll events. The brightness is stored as an integer percentage (1-100).
Configurable defaults:
- format: Format string for displaying the brightness percentage.
- padding: Padding around the widget text.
- theme_path: Optional path for icon assets.
- display: Display identifier (e.g., 'eDP' or 'DisplayPort-1').
- background: Background color for the widget.
"""
defaults = [
('format', ' {percent}% ', 'Display format for brightness level'),
('padding', 3, 'Padding on left and right'),
('theme_path', None, 'Path for icon assets (optional)'),
('display', 'eDP', 'Display identifier'),
('background', None, 'Background color for widget')
]
def __init__(self, **config):
"""
Initialize the Brightness widget.
This sets up the widget by reading the current brightness, updating the screen
brightness accordingly, and registering callbacks for mouse scroll events.
"""
# Initialize the parent class with an empty text value and the given configuration.
super().__init__("", **config)
self.add_defaults(self.defaults)
# Read the initial brightness value from the configuration file.
self.brightness = self.get_brightness(self.display)
self.text = str(self.brightness)
# Apply the brightness setting to the display.
self.set_brightness(self.brightness, self.display)
# Register callbacks for mouse scroll events to adjust brightness.
self.add_callbacks({
'Button4': lambda: self.set_brightness(self.brightness + 1, self.display),
'Button5': lambda: self.set_brightness(self.brightness - 1, self.display)
})
def set_brightness(self, new_brightness, display):
"""
Set the screen brightness for the specified display.
Uses the 'xrandr' command to adjust brightness. The new brightness value (an integer
between 1 and 100) is also saved to a configuration file.
Parameters:
new_brightness (int): New brightness level (1-100).
display (str): The display identifier (e.g., 'eDP').
"""
if 0 < new_brightness <= 100:
self.brightness = new_brightness
# xrandr expects a brightness value between 0 and 1.
system("xrandr --output {} --brightness {}".format(display, new_brightness / 100))
# Save the new brightness to the configuration file.
config_file = path.join(DEFAULT_CONFIG_PATH, display)
with open(config_file, 'w+') as f:
f.write(str(new_brightness))
else:
# Optionally, handle out-of-bound brightness values here.
pass
def get_brightness(self, display=DEFAULT_DISPLAY_FILE):
"""
Retrieve the current brightness level from the configuration file.
If the configuration file does not exist or contains invalid data, it is created or updated
with a default brightness value of 100.
Parameters:
display (str): The display identifier (e.g., 'eDP').
Returns:
int: The current brightness level (1-100).
"""
config_file = path.join(DEFAULT_CONFIG_PATH, display)
default_brightness = 100
if path.exists(config_file):
try:
with open(config_file, 'r') as f:
brightness = int(f.read())
if 0 < brightness <= 100:
return brightness
except Exception:
# In case of an error, fall back to the default brightness.
pass
# Write the default brightness if the file is missing or invalid.
with open(config_file, 'w+') as f:
f.write(str(default_brightness))
return default_brightness
def draw(self):
"""
Draw the widget on the Qtile bar.
Clears the current drawing area and renders the brightness text.
"""
# Clear the drawing area with the widget or bar background.
self.drawer.clear(self.background or self.bar.background)
# Use the parent class draw method to render the text.
base.InLoopPollText.draw(self)
# Finalize drawing.
self.drawer.draw(offsetx=self.offset, offsety=self.offsety, width=self.length)
def poll(self):
"""
Poll the brightness level for the widget display.
Returns:
str: A formatted string displaying the brightness percentage.
"""
try:
percent = self.brightness
except RuntimeError as e:
return 'Error: {}'.format(e)
return self.format.format(percent=percent)
def main():
"""
Command-line interface for the brightness widget.
This function enables the script to be used from the command line to either
adjust or display the current brightness setting.
Usage:
python brightness.py [brightness_value|up|down] [display_name]
Examples:
python brightness.py up eDP # Increase brightness by 10%
python brightness.py 75 # Set brightness to 75%
python brightness.py # Print current brightness
"""
# Determine the display identifier; default is 'eDP'.
display = "eDP"
if len(sys.argv) == 3:
display = sys.argv[2]
widget = Brightness(display=display)
if len(sys.argv) >= 2:
cmd = sys.argv[1]
if cmd.isdigit():
new_brightness = int(cmd)
elif cmd.lower() == "up":
new_brightness = widget.get_brightness() + 10
elif cmd.lower() == "down":
new_brightness = widget.get_brightness() - 10
elif cmd in ["eDP", "DisplayPort-1"]:
# If the command matches a display identifier, print its brightness.
print(widget.get_brightness(cmd))
return
else:
print("ERROR: Invalid command")
return
widget.set_brightness(new_brightness, display)
else:
# If no command-line arguments are provided, print the current brightness.
print(widget.get_brightness())
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment