Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: tell X to reserve screen space for application

Tags:

python

x11

I am trying to solve the issue of reserving space on the screen for an application with X Window Manager (i.e. Linux platforms). I have seen this issue addressed and solved for Gtk and I asked the prompted the same question using Qt. Since no one reacted to the Qt-specific question (which I also addressed in other forums), I thought I'd generalise my question:

Is there a universal, pythonic way to tell X to reserve screen space for an application?

Thanks,
Benjamin

like image 581
neydroydrec Avatar asked May 10 '11 11:05

neydroydrec


1 Answers

After some research i found the solution using Python-Xlib.

In the code that generates the window, it is possible to get the window ID, which is the reference for the window on X. Depending on the GUI kit used, the method to get this ID may vary. Qt4 provides QWidget.winId(), Gtk+2 has its own means to reserve space for a window, and i have not tried with Gtk+3, but i have been told there should be a window_id attribute.

Since the call to X to reserve space for the window can be done only once the window is displayed, in most cases it will be necessary to make the query after the main event loop was entered.

The example below shows a case example with Qt4 using PyQt4. In order to get the window once it is displayed, a thread is launched before the QApplication enters its main loop and that thread keeps polling X until it has managed to "grab" the window. In the following example space is reserved at the top of the screen, with a height equivalent to that of the QWidget we reserve space for.

def fix_window(self):
        set = False
        while set == False:
            try:
                window = myXwindow.Window(self.parent().winId())
                if window != None:
                    height = self.parent().height()
                    window.reserve_space(0, 0, height, 0)
                    set = True
                else:
                    self.sleep(1)
            except:
                raise

In the example here above, the myXwindow is a custom module using Python-Xlib. The following is the content of the module, where Xlib queries X for Display() and subsequently creates a window object which is an abstract model to reference our window as displayed by X. After changing the attributes of this model we can Display().sync() in order to apply changes. The method to reserve space is change_property() in which a series of arguments are passed according to the Freedesktop.org Standards.

class Window(object):
   
    def __init__(self, windowID):

        self._display = Display()
        self._window = self._display.create_resource_object('window', windowID)
    
    def reserve_space(self, left=0, right=0, top=0, bottom=0):

        LEFT    = left
        RIGHT   = right
        TOP     = top
        BOTTOM  = bottom

        self._window.change_property(self._display.intern_atom('_NET_WM_STRUT'),
                                    self._display.intern_atom('CARDINAL'),
                                    32, [LEFT, RIGHT, TOP, BOTTOM])
        self._display.sync()

NB: it is important to keep the same instance of Display() which has created the window object, in order to change the window properties, hence it is stored into a variable.

like image 136
neydroydrec Avatar answered Oct 20 '22 00:10

neydroydrec