Get display count and resolution for each display in Python without xrandr

14,210

Solution 1

xrandr is just a client to access the "RandR" X11 extension from the command line. You can access the functionality directly from Python-Xlib. Here's an example (from Python-Xlib's own code!).

Just in case the URL changes again, here's a minimal piece of code that gets us the display modes. We need to create window (it doesn't matter the size, etc):

from __future__ import print_function
from Xlib import X, display
from Xlib.ext import randr

d = display.Display()
s = d.screen()
window = s.root.create_window(0, 0, 1, 1, 1, s.root_depth)

Then we can query the screen resources using it. Eg, following OP's example:

res = randr.get_screen_resources(window)
for mode in res.modes:
    w, h = mode.width, mode.height
    print("Width: {}, height: {}".format(w, h))

In my computer I get:

$ python minimal.py 
Xlib.protocol.request.QueryExtension
Width: 1600, height: 900
Width: 1440, height: 900
Width: 1360, height: 768
Width: 1360, height: 768
Width: 1152, height: 864
Width: 1024, height: 768
Width: 800, height: 600
Width: 800, height: 600
Width: 640, height: 480

Solution 2

Latest snippet. It extracts all modes with current resolution from all connected monitors.

from Xlib import display
from Xlib.ext import randr

def find_mode(id, modes):
   for mode in modes:
       if id == mode.id:
           return "{}x{}".format(mode.width, mode.height)

def get_display_info():
    d = display.Display(':0')
    screen_count = d.screen_count()
    default_screen = d.get_default_screen()
    result = []
    screen = 0
    info = d.screen(screen)
    window = info.root

    res = randr.get_screen_resources(window)
    for output in res.outputs:
        params = d.xrandr_get_output_info(output, res.config_timestamp)
        if not params.crtc:
           continue
        crtc = d.xrandr_get_crtc_info(params.crtc, res.config_timestamp)
        modes = set()
        for mode in params.modes:
            modes.add(find_mode(mode, res.modes))
        result.append({
            'name': params.name,
            'resolution': "{}x{}".format(crtc.width, crtc.height),
            'available_resolutions': list(modes)
        })

    return result

print(get_display_info())
Share:
14,210
Wolkenarchitekt
Author by

Wolkenarchitekt

https://github.com/wolkenarchitekt

Updated on June 15, 2022

Comments

  • Wolkenarchitekt
    Wolkenarchitekt almost 2 years

    I'm running Ubuntu and I want to get the number of attached displays, their current resolution and, if possible, their position in relation to each other. Because I don't like parsing Console output of xrandr - at least not if I don't have to - I would like to do that with Python-XLib or a similar Pythonic approach.

    This is the xrandr output for my display config:

    $ xrandr
    Screen 0: minimum 320 x 200, current 2960 x 1050, maximum 8192 x 8192
    DVI-0 connected 1680x1050+0+0 (normal left inverted right x axis y axis) 473mm x 296mm
       1680x1050      60.0*+
       1400x1050      60.0  
       1280x1024      75.0     60.0  
       1440x900       59.9  
       1280x960       75.0     60.0  
       1152x864       75.0  
       1280x720       75.0  
       1024x768       75.1     70.1     60.0  
       832x624        74.6  
       800x600        72.2     75.0     60.3     56.2  
       640x480        72.8     75.0     66.7     60.0  
       720x400        70.1  
    VGA-0 connected 1280x1024+1680+26 (normal left inverted right x axis y axis) 376mm x 301mm
       1280x1024      60.0 +   75.0* 
       1024x768       75.1     70.1     60.0  
       832x624        74.6  
       800x600        72.2     75.0     60.3     56.2  
       640x480        72.8     75.0     66.7     60.0  
       720x400        70.1  
    

    I want to get these values with Python, in a way like this:

    displays = get_displays()
    print displays[0].width # out: 1680
    print displays[1].width # out: 1280
    print displays[0].x_position # out: 0
    print displays[1].x_position # out: 1680
    

    When trying to get informations via Python-XLib (or other libs like pyGTK and pygame), it seems that all displays are always handled as one single display. For example this is what I got with XLib so far:

    import Xlib
    import Xlib.display
    
    display = Xlib.display.Display(':0')
    
    print display.screen_count()        # output: 1
    root = display.screen().root
    print root.get_geometry().width     # output: 2960 -> no way to get width of single display?
    print root.get_geometry().height    # output: 1050
    

    I know how to get display informations calling xrandr within Python:

    import subprocess
    output = subprocess.Popen('xrandr | grep "\*" | cut -d" " -f4',shell=True, stdout=subprocess.PIPE).communicate()[0]
    
    displays = output.strip().split('\n')
    for display in displays:
        values = display.split('x')
        width = values[0]
        height = values[1]
        print "Width:" + width + ",height:" + height
    

    But as I said I would prefer a cleaner approach without having to parse Console output. Is there really no way to get (detailed) Display informations with Python without having to parse xrandr output?

  • Ben Davis
    Ben Davis over 9 years
    Any ideas how to get the connected output names from xilb/xrandr?
  • Ricardo Cárdenes
    Ricardo Cárdenes over 9 years
    @BenDavis you could get the possible outputs querying randr.get_screen_resources(window).outputs (returns a list of integers), and then get info about the output using randr.get_output_info(window, ID, timestamp) (I've used timestamp=0). From the "output info" you should be able to figure out if an output is connected
  • Martlark
    Martlark over 4 years
    Not really an answer to the question on linux, but handy for bad google searching.
  • delica
    delica over 4 years
    @Martlark indeed! That's why I wrote this 'answer'. For those who arrive here looking for a windows solution.
  • winbina
    winbina over 3 years
    This seems to be the entire logical screen, i.e. all monitors added together into one screen. I have 3 monitors, but this just prints 1 screen that's 2640x2520.
  • Rob
    Rob over 3 years
    I arrived here from Review Posts and recommended deletion for not answering the question.
  • WinEunuuchs2Unix
    WinEunuuchs2Unix almost 3 years
    Just having a quick glance at the code and it seems like mode.width, mode.height should be prefaced by mode.x, mode.y for the monitors' coordinates on extended desktop?
  • WinEunuuchs2Unix
    WinEunuuchs2Unix almost 3 years
    Answer posted below yours may never be updated, I wonder if you would consider incorporating it along with my comment below his answer into an all-inclusive answer?
  • Kalma
    Kalma about 2 years
    HI @Max Ivanov! This was really useful! I'm having troubles with res.config_timestamp in xrandr_get_crtc_info() on LXDE (though surprisingly NOT in xrandr_get_output_info() and NOT in other Desktop environments). Can you please point where to find info about these "xrandr_*" methods so I can investigate?