Source

fsgamer / fsgamer / xorgutils.py

Full commit
import utils
import signal
import subprocess
import os
import weakref






class XorgProcess(object):
    """
    Wrapper around a few simple tasks to do with Xorg
    """
    with_displays = []

    def __init__(self, pid, tty, display=None):
        self.pid = pid
        self.tty = tty
        self.display = display

        # NOTE: Can this ever be not a number?
        print "THIS IS ME, and my TTY!", tty
        try:
            self.tty_number = int(self.tty.strip('tty'))
        except ValueError:
            utils.warning("Got an invalid tty: '%s'" % tty)
            self.tty_number = 0

    def key_combo(self):
        return "Ctrl+Alt+F%i"%self.tty_number

    def killwait(self, seconds=5):
        INC = 0.5
        times = int(seconds/INC)
        i = 0
        while os.path.exists('/proc/%i' % self.pid):
            if i > times:
                return False
            i += 1
        return True

    def set_display(self, display_number):
        self.display_number = display_number
        self.with_displays.append(weakref.ref(self))

    def kill(self):
        SIG_TERM = 15
        SIG_KILL = 9
        try:
            os.kill(self.pid, SIG_TERM)
        except OSError:
            # Did not kill anything
            return False
        if self.killwait():
            # Waits 5 seconds, then forcekill
            os.kill(self.pid, SIG_KILL)

    
    @classmethod
    def killall_userstarted(cls):
        for ref in self.with_displays:
            xorg = ref()
            if xorg and xorg.display_number:
                xorg.kill()

def guess_my_xorg():
    # TODO I don't know an easy way to know for sure which one I am on
    xorgs = get_xorgs()
    if not xorgs:
        utils.warning("Could not find x server. Everything probably break.")
        return None

    # Otherwise, just assume its the lowest numbered
    return xorgs[0]

def get_xorgs():
    """
    Runs ps and looks for Xorg processes running
    """
    xorgs = []
    xorg_bins = ['Xorg', utils.shell_run.which('Xorg'), 'X']
    result = subprocess.check_output(["/bin/ps", "-e", "-o", "pid,tty,comm"])
    for line in result.splitlines():
        pid, tty, binary = line.strip().split()[:3]
        if binary in xorg_bins:
            xorgs.append(XorgProcess(int(pid), tty))
    return xorgs
    
def get_active_displays(limit=10):
    displays = set()
    # Seriously, could there be more than 10? :P
    for i in range(0, limit):
        if os.path.exists('/tmp/.X%i-lock'%i):
            displays.add(i)

    if not displays:
        # Empty, something went wrong... let's just assume that 0 at least is
        # taken
        utils.warning("Warning: did not find any .X0-lock. Assuming nonetheless that "+
                ":0 is unavailable.")
        displays.add(0)

    return displays

# To get an XorgProcess object, wrap an xinit with the following:
def before_launching_xinit():
    next_free_display = max(get_active_displays())+1
    xorg_list = get_xorgs()
    return next_free_display, xorg_list

def after_launching_xinit(next_free_display, xorg_list):
    new_xorg_list = get_xorgs()
    old_pids = set(map(lambda x: x.pid, xorg_list))
    new_xorgs = filter(lambda x: x.pid not in old_pids, new_xorg_list)

    print "THIS IS NEW_XORGS", new_xorgs, new_xorg_list, old_pids, xorg_list

    if len(new_xorgs) != 1:
        utils.error("xorg", "Could not find the new X server.", True)
    else:
        xorg = new_xorgs[0]
        xorg.set_display(next_free_display)
        return xorg