Как наблюдать за изменениями в подключенных мониторах через Xlib?

Я пытаюсь написать программу, которая будет обнаруживать подключенные внешние мониторы и автоматически включать и настраивать их через Xlib. Я знаю, что есть расширение XRandr, которое позволяет это. Мой вопрос: как включить получение событий XRandr в мое приложение? Какую маску события следует использовать? Я знаю, что приложение xev может это сделать.


person kyku    schedule 01.05.2012    source источник
comment
Вы смотрели в источнике xev?   -  person n. 1.8e9-where's-my-share m.    schedule 01.05.2012
comment
Вот что говорит man 3 Xrandr: XRRScreenChangeNotifyEvent отправляется клиенту, запросившему уведомление, при каждом изменении конфигурации экрана. Клиент может выполнить этот запрос, вызвав XRRSelectInput, передав дисплей, корневое окно и маску RRScreenChangeNotifyMask.   -  person n. 1.8e9-where's-my-share m.    schedule 02.05.2012


Ответы (2)



Для второй части я выдаю конфигурацию напрямую в nvidia-settings.

Я собрал первую часть из частей, которые мне удалось найти, чтобы моя система HTPC, подключенная к телевизору, который ужасно пересканирован, могла сбрасывать среду экрана при включении телевизора.

Мне было бы интересно увидеть чистый порт C моих усилий...

#!/usr/bin/python2

"""
Send RESET_COMMAND via os.system() call when xbc.randr reports
that a small screen (main monitor) has just changed configuration.
ie The secondary (TV) monitor has just been turned on.
"""

# Could also be xrandr settings, if need be #
# These values came from the nvidia-settings GUI with Base Mosaic enable with custom scaling on HDMI-0 determined experiementally
RESET_COMMAND = 'nvidia-settings --assign CurrentMetaMode="GPU-08c5ca05-d3cc-b022-4fab-3acab0500b7c.VGA-0: 1280x1024 +0+0, GPU-08c5ca05-d3cc-b022-4fab-3acab0500b7c.HDMI-0: 1920x1080 +1280+0 {viewportin=1920x1080, viewportout=1774x998+73+41}"'

MAIN_MONITOR_HEIGHT = 1024
MAIN_MONITOR_WIDTH = 1280

import os
# Do one reset at startup (login) - this may be a shortcoming of LXDM that has things wrong after the first login #
os.system(RESET_COMMAND)

import xcb
from xcb.xproto import *

import xcb.randr as RandR
from xcb.randr import NotifyMask, ScreenChangeNotifyEvent


def startup():
    """Hook up XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE"""
    # In the xcb.randr module, the result of
    # key = xcb.ExtensionKey('RANDR')
    # xcb._add_ext(key, randrExtension, _events, _errors)
    # is stored in xcb.randr.key and retrieved in some very odd manner =>
    randr = conn(RandR.key)
    randr.SelectInput(root.root, NotifyMask.ScreenChange)
    # may as well flush()
    conn.flush()



def run():
    """Listen for XCB_RANDR_SCREEN_CHANGE_NOTIFY"""
    currentTimestamp = 0
    connected = False
    startup()

    while True:
        try:
            event = conn.wait_for_event()
            connected = True
        except xcb.ProtocolException, error:
            print "Protocol error %s received!" % error.__class__.__name__
            break
        except Exception, error:
            print "Unexpected error received: %s" % error.message
            break

        # Once the ScreenChangeNotify Event arrives, filter down to the one we care about. #
        if isinstance(event, ScreenChangeNotifyEvent):
            # 3 consecutive events arrive with the same timestamp, #
            if currentTimestamp != event.config_timestamp:
                # so mask off the next two and #
                currentTimestamp = event.config_timestamp
                # mask off the disconnect altogether by looking at the initial screen size. #
                if ((event.width == MAIN_MONITOR_WIDTH) and (event.height == MAIN_MONITOR_HEIGHT)):
                    os.system(RESET_COMMAND)

    # won't really get here, will we?
    if connected:
        conn.disconnect()



conn = xcb.connect()
setup = conn.get_setup()
# setup.roots holds a list of screens (just one in our case) #
root = setup.roots[0]

run()
person Barton    schedule 01.02.2014
comment
Большое спасибо за это. Вот реализация вашей программы на C. - person mafrasi2; 28.10.2016