how to adjust monitor brightness from command line ?

Hi all, It's been an exciting few months for me. I graduated with a Masters from University of North Carolina at Chapel Hill and moved to Boston in order to work as a Software Engineer at TripAdvisor. In my first week at work, I shifted to a standing desk to avoid sitting for long hours. One of the first challenges I faced while working was how to constantly adjust my monitor brightness so that my eyes don't hurt. I had to lean forward awkwardly (due to the standing desk) to adjust the brightness manually. So, I started digging on how to build a small tool which would allow me to change the monitor brightness from command line and this post describes my findings.

xrandr

All of the google search queries pointed me to a powerful command line tool called xrandr (Xorg RandR) used to configure which display ports are enabled (e.g. LCD, VGA and DVI), and to configure display modes and properties such as orientation, reflection and DPI . xrandr is the command line interface to the RandR X extension. The man pages are your best bet at finding help with xrandr.

Querying the current state of display

First, let's query the current display state of the system. This can be done by running command xrandr -q.

[ravikirn@rk-dell-xps ~]# xrandr -q
Screen 0: minimum 320 x 200, current 1920 x 1080, maximum 32767 x 32767
LVDS1 connected 1920x1080+0+0 (normal left inverted right x axis y axis) 344mm x 193mm
   1920x1080      60.0*+   59.9
   1680x1050      60.0     59.9
   1600x1024      60.2
   1400x1050      60.0
   1280x1024      60.0
   1440x900       59.9
   1280x960       60.0
   1360x768       59.8     60.0
   1152x864       60.0
   1024x768       60.0
   800x600        60.3     56.2
   640x480        59.9
VGA1 disconnected (normal left inverted right x axis y axis)
HDMI1 disconnected (normal left inverted right x axis y axis)
DP1 disconnected (normal left inverted right x axis y axis)

The current connected display is LVDS1 which has connected written next to it.

Extracting the active display

To extract the name of the active display, you can grep for connected, limit to 1 by piping to head command further piped to cut command and extract the first field.

[ravikirn@rk-dell-xps ~]# xrandr -q | grep ' connected' |  head -n 1 | cut -d ' ' -f1
LVDS1

Change brightness of the active display

We can change the brightness of a display using xrandr by typing the below command.

xrandr --output <displayName> --brightness <value (0.0 to 1.0)>

Here value is a floating point number between 0.0 to 1.0. It's easier to think of the value as a brightness percentage where 1.0 indicates 100% and 0.0 indicates 0%. To change our active display brightness to 85% of it's maximum brightness, we can execute the below command:-

xrandr --output LVDS1 --brightness 0.85

Bash function

We can create a neat little bash function and put it in your ~/.bashrc so that we can execute it on command line.

function brightness(){
    if [ $# -gt 0 ]; then
        # set brightnessValue
        brightnessValue=$1
        # get activeDisplay
        activeDisplay=`xrandr -q | grep ' connected' | head -n 1 | cut -d ' ' -f1`
        # change brightness if $activeDisplay is not empty
        if [ "$activeDisplay" != "" ]; then
            xrandr --output $activeDisplay --brightness $brightnessValue
        else
            echo "Could not determine active display, run 'xrandr --verbose' for detailed info"
        fi
    else
        echo -e "Error!!! Syntax: brightness <value (0.0 to 1.0)>"
    fi
}

In the above bash function brightness, we first check if the user passed in the brightness value by checking $# is greater than 0. We set $1 as the brightnessValue (no validation done). Next, we assign the current active display to a variable activeDisplay. If $activeDisplay is not empty, we try executing the xrandr command to change brightness.

Now source your ~/.bashrc file with the command source ~/.bashrc and you can change the monitor brightness by brightness 0.85.

This is fine but I need something better to fine-tune brightness

Frankly I was very happy with this command line tool, it was better than awkwardly bending to reach the monitor in order to change brightness, however, I frequently found myself tweaking the brightness between 80-90% (0.80-0.90) and after a couple of adjustments I would settle down.

I had recently worked with PyGTK3 in order to develop an RSI prevention tool for myself called breakmywork. So, I decided to develop a very simple UI with a slider, so that on pressing the left and right arrow keys the brightness should decrease and increase respectively. The GUI should close on pressing escape key.

Extract current brightness

When I first show the slider to the user, I need to set it to current brightness level and we can extract that using below command.

[ravikirn@rk-dell-xps ~]# xrandr --verbose | grep -i brightness
        Brightness: 0.84
[ravikirn@rk-dell-xps ~]# xrandr --verbose | grep -i brightness | cut -f2 -d ' '
0.84

Connecting them all together

Now, all we need to do is put everything together. I won't go into details of the UI building and event handling, however, if you are interested, there is neat documentation at Python GTK+ 3 Tutorial. The code itself is very simple and should be self explanatory.

#!/usr/bin/env python
from gi.repository import Gtk
import subprocess
class BrightnessScale:
    def __init__(self):
        # get active monitor and current brightness
        self.monitor = self.getActiveMonitor()
        self.currB = self.getCurrentBrightness()
    def initUI(self):
        # initliaze and configure window
        window = Gtk.Window()
        window.set_title('Brightness Scale')
        window.set_default_size(250, 50)
        window.set_position(Gtk.WindowPosition.CENTER)
        window.set_border_width(10)
        # slider configuration
        self.adjustment = Gtk.Adjustment(self.currB, 0, 100, 1, 10, 0)
        self.scale = Gtk.HScale()
        self.scale.set_adjustment(self.adjustment)
        self.scale.set_digits(0)
        # close Gtk thread on closing window
        window.connect("destroy", lambda w: Gtk.main_quit())
        # setup event handler on value-changed
        self.scale.connect("value-changed", self.scale_moved)
        # add the scale to window
        window.add(self.scale)
        # show all components in window
        window.show_all()
        # close window on pressing escape key
        accGroup = Gtk.AccelGroup()
        key, modifier = Gtk.accelerator_parse('Escape')
        accGroup.connect(key, modifier, Gtk.AccelFlags.VISIBLE, Gtk.main_quit)
        window.add_accel_group(accGroup)
    def showErrDialog(self):
        self.errDialog = Gtk.MessageDialog(None,
                                           Gtk.DialogFlags.MODAL,
                                           Gtk.MessageType.ERROR,
                                           Gtk.ButtonsType.OK,
                                           "Unable to detect active monitor, run 'xrandr --verbose' on command-line for more info")
        self.errDialog.set_title("brightness control error")
        self.errDialog.run()
        self.errDialog.destroy()
    def initStatus(self):
        if(self.monitor == "" or self.currB == ""):
            return False
        return True
    def getActiveMonitor(self):
        #Find display monitor
        monitor = subprocess.check_output("xrandr -q | grep ' connected' | cut -d ' ' -f1", shell=True)
        if(monitor != ""):
            monitor = monitor.split('\n')[0]
        return monitor
    def getCurrentBrightness(self):
        #Find current brightness
        currB = subprocess.check_output("xrandr --verbose | grep -i brightness | cut -f2 -d ' '", shell=True)
        if(currB != ""):
            currB = currB.split('\n')[0]
            currB = int(float(currB) * 100)
        else:
            currB = ""
        return currB
    def scale_moved(self, event):
        #Change brightness
        newBrightness = float(self.scale.get_value())/100
        cmd = "xrandr --output %s --brightness %.2f" % (self.monitor, newBrightness)
        cmdStatus = subprocess.check_output(cmd, shell=True)
if __name__ == "__main__":
    # new instance of BrightnessScale
    brcontrol = BrightnessScale()
    if(brcontrol.initStatus()):
        # if everything ok, invoke UI and start Gtk thread loop
        brcontrol.initUI()
        Gtk.main()
    else:
        # show error dialog
        brcontrol.showErrDialog()


In your ~/.bashrc you can alias brightness to execute the above python file or alternatively you can create a symlink of the file and place it in /usr/bin.

alias brightness='python <path-to-file>/brightness.py'


On executing the command it should launch a neat UI like below and you can control brightness via left/right arrow keys, once done adjusting it, press escape key to quit.

brightness control ui screenshot

The code can be found on github at https://github.com/ravikiranj/brightness-control. Please note that if you have multiple displays enabled, you will need to run a loop to change the brightness of each one of them.

Comments

Comments powered by Disqus