mutter/tools/get-state.py

173 lines
5.3 KiB
Python
Executable File

#!/usr/bin/env python3
import argparse
import enum
import subprocess
import sys
from gi.repository import GLib
class Source(enum.Enum):
DBUS = 1
FILE = 2
def transform_to_string(transform):
match transform:
case 0: return 'normal'
case 1: return '90'
case 2: return '180'
case 3: return '270'
case 4: return 'flipped'
case 5: return 'flipped-90'
case 6: return 'flipped-180'
case 7: return 'flipped-270'
def print_data(level, is_last, lines, data):
if is_last:
link = ''
else:
link = ''
padding = ' '
if level >= 0:
indent = level
buffer = f'{link:{padding}>{indent * 4}}──{data}'
buffer = list(buffer)
for line in lines:
if line == level:
continue
index = line * 4
if line > 0:
index -= 1
buffer[index] = ''
buffer = ''.join(buffer)
else:
buffer = data
print(buffer)
if is_last and level in lines:
lines.remove(level)
elif not is_last and level not in lines:
lines.append(level)
def print_properties(level, lines, properties):
property_list = list(properties)
print_data(level, True, lines, f'Properties: ({len(property_list)})')
for property in property_list:
is_last = property == property_list[-1]
print_data(level + 1, is_last, lines,
f'{property}{properties[property]}')
def print_current_state(args):
if args.file:
source = Source.FILE
path = args.file
else:
source = Source.DBUS
short = args.short
type_signature = '(ua((ssss)a(siiddada{sv})a{sv})a(iiduba(ssss)a{sv})a{sv})'
variant_type = GLib.VariantType.new(type_signature)
if source == Source.DBUS:
command = 'gdbus call -e '\
'-d org.gnome.Mutter.DisplayConfig '\
'-o /org/gnome/Mutter/DisplayConfig '\
'-m org.gnome.Mutter.DisplayConfig.GetCurrentState'
result = subprocess.run(command,
shell=True, check=True, capture_output=True, text=True)
data = result.stdout
else:
if path == '-':
data = sys.stdin.read()
else:
with open(path) as file:
data = file.read()
variant = GLib.variant_parse(variant_type, data)
print('Serial: {}'.format(variant[0]))
print()
print('Monitors:')
monitors = variant[1]
lines = []
for monitor in monitors:
is_last = monitor == monitors[-1]
spec = monitor[0]
modes = monitor[1]
properties = monitor[2]
print_data(0, is_last, lines, 'Monitor {}'.format(spec[0]))
print_data(
1, False, lines, f'EDID: vendor: {spec[1]}, product: {spec[2]}, serial: {spec[3]}')
mode_count = len(modes)
if short:
modes = [mode for mode in modes if len(mode[6]) > 0]
print_data(1, False, lines,
f'Modes ({len(modes)}, {mode_count - len(modes)} omitted)')
else:
print_data(1, False, lines,
f'Modes ({len(modes)})')
for mode in modes:
is_last = mode == modes[-1]
print_data(2, is_last, lines, f'{mode[0]}')
print_data(3, False, lines, f'Dimension: {mode[1]}x{mode[2]}')
print_data(3, False, lines, f'Refresh rate: {mode[3]}')
print_data(3, False, lines, f'Preferred scale: {mode[4]}')
print_data(3, False, lines, f'Supported scales: {mode[5]}')
mode_properties = mode[6]
print_properties(3, lines, mode_properties)
print_properties(1, lines, properties)
print()
print('Logical monitors:')
logical_monitors = variant[2]
index = 1
for logical_monitor in logical_monitors:
is_last = logical_monitor == logical_monitors[-1]
properties = logical_monitor[2]
print_data(0, is_last, lines, f'Logical monitor #{index}')
print_data(1, False, lines,
f'Position: ({logical_monitor[0]}, {logical_monitor[1]})')
print_data(1, False, lines,
f'Scale: {logical_monitor[2]}')
print_data(1, False, lines,
f'Transform: {transform_to_string(logical_monitor[3])}')
print_data(1, False, lines,
f'Primary: {logical_monitor[4]}')
monitors = logical_monitor[5]
print_data(1, False, lines,
f'Monitors: ({len(monitors)})')
for monitor in monitors:
is_last = monitor == monitors[-1]
print_data(2, is_last, lines,
f'{monitor[0]} ({monitor[1]}, {monitor[2]}, {monitor[3]})')
properties = logical_monitor[6]
print_properties(1, lines, properties)
index += 1
properties = variant[3]
print()
print_properties(-1, lines, properties)
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Get display state')
parser.add_argument('file', metavar='FILE', type=str, nargs='?',
help='Read the output from gdbus call instead of calling D-Bus')
parser.add_argument('--short', action='store_true')
args = parser.parse_args()
print_current_state(args)