Operating Systems

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.

compiz_comparison_chart

Compiz 0.9.0 Released – Completely Rewritten in C++

I was doing some in depth research / code hacking regarding the support of multi-headed output (dual monitors) on Linux. I won’t get into details but my video is being output to my monitors as “one screen” with a virtual distinctions handled by the window manager. Because of this, figuring out which of the monitors you are on isn’t as straight forward as you might think. Originally I was looking for a way to access the c functions in compiz through python but that point is now moot (likely for the better).

The first unstable release of the Compiz 0.9 series, completely rewritten in C++. As said, this “brings a whole new developer API, splits rendering into plugins, switches the buildsystem from automake to cmake and brings minor functionality improvements. This release represents the first developer and tester preview of what will eventually make the 0.10.x stable series. Please note that as such, it is not yet ready for general use as there are a number of known ssues, regressions and incomplete functionality.”

Here is a SLIGHTLY DATED graph I got from Santiance.com.

This is a really interesting turning point for the project and I’m glad I came across this while doing my research for multi-head handling in compiz. Knowing where the future lies could drastically change where I put my efforts in developing to support them.

Fastest way to install the media essentials in ubuntu

If you’re coming from Windows, or like me, find yourself living in a live CD while you figure out which step went wrong; you’ll be interested in the essential media codecs, flash, java, Microsoft fonts, etc.

I thought I’d share the way I did this as quickly as possible in in Ubuntu 10.04 using the command line.

Open up terminal, using ctrl+alt+t (Which I’m very happy about as this has been my default since 8.04). Alternativelty from the main menu -> Applications > Accessories > Terminal

Make a backup in case you’re scared, then remove the comments from repositories you need to unlock to access the restricted (proprietary) packages.

ubuntu@ubuntu:~$ sudo cp /etc/apt/sources.list .
ubuntu@ubuntu:~$ sudo sed -i 's/^# deb/deb/' /etc/apt/sources.list

We do this be matching the first 2 characters with ‘# ‘ and replacing them with ” (nothing). See the diff below (> indicate original lines, < are changed).

 
ubuntu@ubuntu:~$ diff sources.list /etc/apt/sources.list
18,23c18,23
< # deb http://archive.ubuntu.com/ubuntu lucid universe
< # deb-src http://archive.ubuntu.com/ubuntu lucid universe
< # deb http://archive.ubuntu.com/ubuntu lucid-updates universe
< # deb-src http://archive.ubuntu.com/ubuntu lucid-updates universe
< # deb http://security.ubuntu.com/ubuntu lucid-security universe
< # deb-src http://security.ubuntu.com/ubuntu lucid-security universe
---
> deb http://archive.ubuntu.com/ubuntu lucid universe
> deb-src http://archive.ubuntu.com/ubuntu lucid universe
> deb http://archive.ubuntu.com/ubuntu lucid-updates universe
> deb-src http://archive.ubuntu.com/ubuntu lucid-updates universe
> deb http://security.ubuntu.com/ubuntu lucid-security universe
> deb-src http://security.ubuntu.com/ubuntu lucid-security universe
30,35c30,35
< # deb http://archive.ubuntu.com/ubuntu lucid multiverse
< # deb-src http://archive.ubuntu.com/ubuntu lucid multiverse
< # deb http://archive.ubuntu.com/ubuntu lucid-updates multiverse
< # deb-src http://archive.ubuntu.com/ubuntu lucid-updates multiverse
< # deb http://security.ubuntu.com/ubuntu lucid-security multiverse
< # deb-src http://security.ubuntu.com/ubuntu lucid-security multiverse
---
> deb http://archive.ubuntu.com/ubuntu lucid multiverse
> deb-src http://archive.ubuntu.com/ubuntu lucid multiverse
> deb http://archive.ubuntu.com/ubuntu lucid-updates multiverse
> deb-src http://archive.ubuntu.com/ubuntu lucid-updates multiverse
> deb http://security.ubuntu.com/ubuntu lucid-security multiverse
> deb-src http://security.ubuntu.com/ubuntu lucid-security multiverse
>
 
 
<pre lang="bash">

Now that we uncommented these lines, they will be read next time we update, so lets go ahead and do that now. Once that is done, we can install the extras.

ubuntu@ubuntu:~$ sudo apt-get update
ubuntu@ubuntu:~$ sudo apt-get install ubuntu-restricted-extras

Rock and roll.