Python

Python Multi-head X (Nvidia TwinView / Dual Monitor) Development Notes

Preface

The following development notes were written after researching the underlying handling of dual monitors in the X window system on Linux. I’ve included a code snippet that I built to help demonstrate behavior and create a proof of concept to show I can determine which monitor a window is on using only python and no statically set coordinates.

Introduction

I mentioned in my previous post that I’m using an nVidia video card with “TwinView” software that outputs my video as if it were one screen, which it technically is, one X screen. This means that the distinction between monitors is not mapped in the X tree, it’s handled by the window manager. Unlike Xinerama, which has an x session per monitor and stitches them together. Xinerama, however, has is being deprecated in favor of RandR but regardless, TwinView is my choice and is not an option for me to change to.

With all of that said, the decision to bridge python to c that interfaces with compiz is a deadend and would be better implemented based on the new 0.9.0 C++ api. It would be nice to be able to return a list of windows from a “monitor” object. However, that’s beyond my current scope. I was able to whip up some python that to show that implementing the monitor management in python using the gtk module isn’t /that/ hacky. I emphasize because I read some posts that claimed window decorations could be an issue in accurate calculations.

Some Code

Read the comment on line 2. Learn more about pygtk here

#!/usr/bin/python
# Print some information about the X environment, the monitor setup, currently active window and cursor position
import gtk.gdk
 
screen = gtk.gdk.screen_get_default()
print "X default screen size: %d x %d" % (screen.get_width(), screen.get_height())
print "xid of root window: %d" % screen.get_root_window().xid
 
monitors = int(screen.get_n_monitors())
print "== %d monitors ==" % monitors
for m in range(0, monitors):
    print " - geometry of monitor %d: %s" % (m, screen.get_monitor_geometry(m))
 
window = screen.get_active_window()
win_x, win_y, win_w, win_h, win_bit_depth = window.get_geometry()
print "active window on monitor: %d" % screen.get_monitor_at_point((win_x+(win_w/2)),(win_y+(win_h/2)))
print "window geometry (x,y,w,h): %d, %d, %d, %d" % (win_x,win_y,win_w,win_h)
 
display = gtk.gdk.display_get_default()
pointer = display.get_pointer()
print "cursor position (x, y): %d, %d" % (pointer[1], pointer[2])
print "cursor on monitor: %d" % screen.get_monitor_at_point(pointer[1],pointer[2])

thanks to those in #compiz-dev and #python on freenode who helped me come around to create this snippet. I hope it will help others looking to develop for multi-head setups in Linux. Please let me know if I missed anything or did something incorrectly, this is new territory for me.

New Python eBook, Much Better, Down and Dirty

Some friends recommended a book that’s a quicker pace with some better programming practices. Learn Python The Hard way (or quick way :-P ). It reads more like a walk-through tutorial / quick reference and gives you easily repeatable programming practices that will get you a stronger feel for the language. It’s probably best used in combination with the Python Documentation. Also, a fair warning, Dive Into Python has war declared against it.