10

I'm working on developing a python application for Ubuntu that enables a user to have their desired resolution without requiring graphics drivers.
In order to do this I've been using xrandr, which so far, has been pretty useful

However, I now have a problem; how can I detect the monitor name? I was intending to use a terminal command through os.system, modifying the terminal output to get the required monitor output, and then storing it within the program. Unfortunately, despite much searching, I have been unable to find out how I can do this.

Is there any way in which I can do this?

To sum it up: I'm looking for a terminal command that gives me the monitor name, such VGA1 or DVI-0

14

I am not sure how you are going to apply it in your application ("enable a user to have their desired resolution without requiring graphics drivers" ?), but:

A terminal command to list connected screens

xrandr | grep " connected " | awk '{ print$1 }'

This wil give you the connected screens for further processing, like:

VGA-0
DVI-I-1

Since you mention python, the snippet below will also list connected screens:

#!/usr/bin/env python3
import subprocess

def screens():
    output = [l for l in subprocess.check_output(["xrandr"]).decode("utf-8").splitlines()]
    return [l.split()[0] for l in output if " connected " in l]

print(screens())

This wil also give you the connected screens, like:

['VGA-0', 'DVI-I-1']

Note

Note the spaces around " connected " in the searched string. They are needed to prevent mismatches with disconnected.

EDIT 2019

Using python, not necessary to use xrandr or any other system call at all. Better use Gdk:

#!/usr/bin/env python3
import gi
gi.require_version("Gdk", "3.0")
from gi.repository import Gdk

allmonitors = []

gdkdsp = Gdk.Display.get_default()
for i in range(gdkdsp.get_n_monitors()):
    monitor = gdkdsp.get_monitor(i)
    scale = monitor.get_scale_factor()
    geo = monitor.get_geometry()
    allmonitors.append([
        monitor.get_model()] + [n * scale for n in [
            geo.x, geo.y, geo.width, geo.height
        ]
    ])

print(allmonitors)

Example output:

[['eDP-1', 0, 0, 3840, 2160], ['DP-2', 3840, 562, 1680, 1050]]

Depending on the desired info, you can make your choice from https://lazka.github.io/pgi-docs/Gdk-3.0/classes/Monitor.html

3
  • @WinEunuuchs2Unix see updated answer :) – Jacob Vlijm Nov 24 '19 at 15:10
  • @WinEunuuchs2Unix Huh? What is your Ubuntu version? Tkinter has nothing to do with this, and python3 links to python3 since, well, too long to remember when it didn't. – Jacob Vlijm Nov 24 '19 at 18:35
  • I deleted earlier comments and wrote an answer below solving all my problems. Note it is probably the solution for another user here: github.com/UbuntuBudgie/window-shuffler/issues/3 – WinEunuuchs2Unix Jan 12 '20 at 17:50
7

You can use the bash command with popen:

import os
list_display = os.popen("xrandr --listmonitors | grep '*' | awk {'print $4'}").read().splitlines()
# or based on the comment of this answer 
list_display = os.popen("xrandr --listmonitors | grep '+' | awk {'print $4'}").read().splitlines()

or I wrote a old gist on the subject https://gist.github.com/antoinebou13/7a212ccd84cc95e040b2dd0e14662445

3
  • 2
    How does this answer the question? – Stephen Rauch Jun 24 '18 at 4:20
  • 3
    +1 for using xrandr --listmonitors :) – simon Jan 26 '19 at 2:04
  • Grepping on * only returns primary monitor. Grepping on + will return all connected monitors like OP wants. – WinEunuuchs2Unix Nov 24 '19 at 15:07
6

You can use python and just python to get the connected monitor names:

$ python3 -c 'from gi.repository import Gdk; screen=Gdk.Screen.get_default(); \
[print(screen.get_monitor_plug_name(i)) for i in range(screen.get_n_monitors())]'
DP1
LVDS1
2
  • 1
    Nice! didn't know this one. – Jacob Vlijm Jun 22 '15 at 19:10
  • I get a couple of warnings: "<string>:2: DeprecationWarning: Gdk.Screen.get_n_monitors is deprecated <string>:2: DeprecationWarning: Gdk.Screen.get_monitor_plug_name is deprecated" in Xubuntu 20.04 – jarno Dec 25 '20 at 16:23
0

My first Python project is under development and one of the functions changes resolution:

wman6 change resolution.png


The xrandr route

Like yourself at first I did everything in xrandr calls from Python. Today I've begun converting to an Gnome methodology. The reason being support for future Wayland plus Mac and MS Windows.

Here's my xrandr calls from Python which works perfectly:

''' Create monitors list '''

# Monitor Fields (monitor) within list of all connected (monitors)
monitor = []
MON_X=0; MON_Y=1; MON_W=2; MON_H=3; MON_N=4
# X-offset, Y-offset, width, Height, Monitor Name from `xrandr`
MON_CNT=5
monitors = []
MON_Ndx=0
monitors_cnt = 0

list_display = os.popen("xrandr --listactivemonitors | grep '+' | \
                        awk {'print $3, $4'}").read().splitlines()

for l in list_display:
    monitors_cnt += 1
    # 1920/382x1080/215+3840+2160  eDP-1-1      <---- sample
    # ['3840' '2160' '1920' '1080' 'eDP-1-1']   <---- convert to list
    a = l.split(" ") # Default split on space
    name = a[1]
    b = a[0].split("+")
    x = int (b[1])
    y = int (b[2])
    c = b[0].split("x")
    d = c[0].split("/")
    w = int (d[0])
    d = c[1].split("/")
    h = int (d[0])
    monitors.extend ([x, y, w, h, name])

Gnome wasn't built in a day but...

Gnome wasn't built in a day but... it burned in an overnight update.

A tale of two Pythons

Ubuntu wasn't difficult enough supporting all versions because some are in Python 2 and some are in Python 3. So your program header has to contain something like this:

try:
    import tkinter as tk
    import tkinter.ttk as ttk
    import tkinter.font as font
    PYTHON_VER="3"
except ImportError: # Python 2
    import Tkinter as tk
    import ttk
    import tkFont as font
    PYTHON_VER="2"

A tale of two Gnomes

With Gnome on Ubuntu 16.04 the version is 3.18 but on Ubuntu 18.04 the Gnome version is 3.22 and things that work in 16.04 break in 18.04 as a consequence. We have two answers posted on this thread:

Sylvain's answer uses Python 3 and Gnome 3.18 from Ubuntu 16.04:

[print(screen.get_monitor_plug_name(i)) for i in range(screen.get_n_monitors())]

Jacob's answer also uses Python 3 but uses Gnome 3.22 from Ubuntu 18.04:

gdkdsp = Gdk.Display.get_default()
for i in range(gdkdsp.get_n_monitors()):
    monitor = gdkdsp.get_monitor(i)

Four solutions in one

My approach is to support either Python 2 or Python 3 and Gnome 3.18 or Gnome 3.22:

def build_monitors_from_gdk():
    monitors = []
    try:
        display = Gdk.Display.get_default()
        try:
            # Gnome 3.22
            num_monitors = display.get_n_monitors()
        except:
            # Gnome 3.18
            screen = display.get_default_screen()
            num_monitors = screen.get_n_monitors()

        for i in range(0, num_monitors):
            try:
                # Gnome 3.22
                monitor = display.get_monitor(i)
                monitor_rect = monitor.get_geometry()
                name = monitor.get_monitor_plug_name()
            except:
                # Gnome 3.18
                monitor_rect = screen.get_monitor_geometry (i)
                name = screen.get_monitor_plug_name(i)

            monitors.append([
                monitor_rect.x,
                monitor_rect.y,
                monitor_rect.width,
                monitor_rect.height,
                name
            ])
    except Exception as e:
        print('Error: error parsing monitors (Gdk)')
        import traceback
        traceback.print_exc()
        monitors = None
    return monitors 

monitors2 = build_monitors_from_gdk()
print (monitors2)

Output

[[0, 0, 1920, 1080, 'HDMI-0'], [1920, 0, 3840, 2160, 'DP-1-1'], [3840, 2160, 1920, 1080, 'eDP-1-1']]

Design philosophy

Write one program that supports all versions that are not EOL. Ubuntu 20.04 is due April 2020 and Windows Subsystem for Linux 2 is due May 2020 so I want my first Python project to support those as well.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.