2012-05-01 78 views
3

我試圖編寫一個程序來檢測外部監視器被插入,並通過Xlib自動啓用和配置它們。我知道有XRandr擴展允許這個。我的問題是,如何啓用接收XRandr事件到我的應用程序?我應該使用什麼事件掩碼?我知道xev應用程序能夠做到這一點。如何通過Xlib觀察連接的顯示器的變化?

+1

你有沒有在xev的來源看? –

+4

這是'man 3 Xrandr'所說的: A ** XRRScreenChangeNotifyEvent **被髮送到已經請求通知的客戶端,只要屏幕配置被更改。客戶端可以通過調用** XRRSelectInput **,傳遞顯示,根窗口和** RRScreenChangeNotifyMask **掩碼來執行此請求。 –

回答

3

對於第二部分,我直接發出的配置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() 
+1

非常感謝。 [這裏](https://gist.github.com/mafrasi2/4ee01e0ba4dad20cf7a80ae463f32fca)是你的程序的C實現。 – mafrasi2