Author: tack
Date: Fri Jan 11 20:23:03 2008
New Revision: 2966

Log:
New methods for X11Display: get_root_window; new methods for X11Window:
set_title, get_title, get_children, get_properties.

X11Window.get_geometry() and get_pos() now take an optional absolute arg, which
if True returns coordinates relative to the root window; Defer creation of
invisible mouse cursor pixmap until needed.


Modified:
   trunk/display/src/x11.py
   trunk/display/src/x11display.c
   trunk/display/src/x11window.c
   trunk/display/src/x11window.h

Modified: trunk/display/src/x11.py
==============================================================================
--- trunk/display/src/x11.py    (original)
+++ trunk/display/src/x11.py    Fri Jan 11 20:23:03 2008
@@ -31,6 +31,7 @@
 
 # python imports
 import weakref
+import struct
 
 # kaa notifier for the socket callback
 import kaa.notifier
@@ -166,6 +167,8 @@
     def composite_supported(self):
         return self._display.composite_supported()
 
+    def get_root_window(self):
+        return X11Window(window = self._display.get_root_id())
 
 
 X11Display.XEVENT_WINDOW_EVENTS_LIST = filter(lambda x: x.find("XEVENT_") != 
-1, dir(X11Display))
@@ -240,6 +243,9 @@
             "resize_event",    # window resized
             "configure_event") # ?
 
+    def __str__(self):
+        return '<X11Window object id=0x%x>' % self._window.wid
+
     def get_display(self):
         return self._display
 
@@ -266,7 +272,7 @@
             self.hide()
 
     def get_visible(self):
-        return self._window.get_visible()
+        return self._window.get_visible() != 0
 
     def render_imlib2_image(self, i, dst_pos = (0, 0), src_pos = (0, 0),
                             size = (-1, -1), dither = True, blend = False):
@@ -337,14 +343,29 @@
         self._display.handle_events()
         return True
 
-    def get_geometry(self):
-        return self._window.get_geometry()
+    def get_geometry(self, absolute = False):
+        """
+        Returns 2-tuple of position and size (x, y), (width, height)
+        of the window.  If absolute is False (default), (x, y) are relative
+        to the window's parent.  If absolute is True, coordinates are
+        relative to the root window.
+        """
+        return self._window.get_geometry(absolute)
+
+    def get_parent(self):
+        """
+        Returns the parent of the window.  If no parent exists (i.e. root 
window)
+        None is returned.
+        """
+        wid = self._window.get_parent()
+        if wid:
+            return X11Window(window = self._window.get_parent())
 
     def get_size(self):
         return self.get_geometry()[1]
 
-    def get_pos(self):
-        return self.get_geometry()[0]
+    def get_pos(self, absolute = False):
+        return self.get_geometry(absolute)[0]
 
     def set_cursor_visible(self, visible):
         self._window.set_cursor_visible(visible)
@@ -391,6 +412,62 @@
     def focus(self):
         return self._window.focus()
 
+    def set_title(self, title):
+        return self._window.set_title(title)
+
+    def get_title(self):
+        return self._window.get_title()
+
+    def get_children(self, recursive = False, visible_only = False, 
titled_only = False):
+        """
+        Returns all child windows as X11Window objects.  If recursive is True,
+        all descendants will be returned.  If visible_only is True, only those
+        children which are visible are included (unmapped children or mapped 
+        children that are offscreen are not included).  If titled_only is True,
+        only those windows with titles set will be included.
+        """
+        return [ X11Window(window = wid) for wid in 
self._window.get_children(recursive, visible_only, titled_only) ]
+
+    def get_properties(self):
+        """
+        Returns a dictionary of X properties associated with this window.
+        Properties are converted to the appropriate python type, although if
+        the given property type is not supported, the value for that property
+        will be a 4-tuple of (type, format, n_items, data) where type is a
+        string representing the type of the atom, format is 8 for character,
+        16 for short, and 32 for int, n_items is the number of items of the
+        given format in the data buffer.
+        """
+        props = {}
+        for (name, type, format, n_items, data) in 
self._window.get_properties():
+            struct_format = {
+                'INTEGER': 'i',
+                'CARDINAL': 'L',
+                'WINDOW': 'L',
+                'STRING': 's',
+                'UTF8_STRING': 's'
+            }.get(type, None)
+
+            if struct_format:
+                struct_format = '%d%s' % (n_items, struct_format)
+                buflen = struct.calcsize(struct_format)
+                data = struct.unpack(struct_format, data[:buflen])
+                if len(data) == 1:
+                    data = data[0]
+                if type in ('STRING', 'UTF8_STRING'):
+                    data = data.strip('\x00').split('\x00')
+                    if type == 'UTF8_STRING':
+                        data = [ x.decode('utf-8') for x in data]
+                    if len(data) == 1:
+                        data = data[0]
+            else:
+                # Unsupported type, we just pass the raw buffer back to the 
user.
+                pass
+
+            props[name] = data
+
+        return props
+
 
 class EvasX11Window(X11Window):
     def __init__(self, gl = False, display = None, size = (640, 480),

Modified: trunk/display/src/x11display.c
==============================================================================
--- trunk/display/src/x11display.c      (original)
+++ trunk/display/src/x11display.c      Fri Jan 11 20:23:03 2008
@@ -265,6 +265,12 @@
 #endif
 }
 
+PyObject *
+X11Display_PyObject__get_root_id(X11Display_PyObject * self, PyObject * args)
+{
+    return Py_BuildValue("k", DefaultRootWindow(self->display));
+}
+
 PyMethodDef X11Display_PyObject_methods[] = {
     { "handle_events", ( PyCFunction ) X11Display_PyObject__handle_events, 
METH_VARARGS },
     { "sync", ( PyCFunction ) X11Display_PyObject__sync, METH_VARARGS },
@@ -275,6 +281,7 @@
     { "glx_supported", ( PyCFunction ) X11Display_PyObject__glx_supported, 
METH_VARARGS },
     { "composite_supported", ( PyCFunction ) 
X11Display_PyObject__composite_supported, METH_VARARGS },
     { "composite_redirect", ( PyCFunction ) 
X11Display_PyObject__composite_redirect, METH_VARARGS },
+    { "get_root_id", ( PyCFunction ) X11Display_PyObject__get_root_id, 
METH_VARARGS },
     { NULL, NULL }
 };
 

Modified: trunk/display/src/x11window.c
==============================================================================
--- trunk/display/src/x11window.c       (original)
+++ trunk/display/src/x11window.c       Fri Jan 11 20:23:03 2008
@@ -137,9 +137,9 @@
 
         if (window_title)
             XStoreName(self->display, self->window, window_title);
+        self->owner = True;
     }
     self->wid = PyLong_FromUnsignedLong(self->window);
-    _make_invisible_cursor(self);
     XUnlockDisplay(self->display);
     return (PyObject *)self;
 }
@@ -154,12 +154,13 @@
 void
 X11Window_PyObject__dealloc(X11Window_PyObject * self)
 {
-    printf("X11Window dealloc\n");
-    if (self->window) {
+    if (self->window ) {
         XLockDisplay(self->display);
-        XDestroyWindow(self->display, self->window);
+        if (self->owner)
+            XDestroyWindow(self->display, self->window);
         Py_XDECREF(self->wid);
-        XFreeCursor(self->display, self->invisible_cursor);
+        if (self->invisible_cursor)
+            XFreeCursor(self->display, self->invisible_cursor);
         XUnlockDisplay(self->display);
     }
     Py_XDECREF(self->display_pyobject);
@@ -245,9 +246,11 @@
         return NULL;
 
     XLockDisplay(self->display);
-    if (!visible)
+    if (!visible) {
+        if (!self->invisible_cursor)
+            _make_invisible_cursor(self);
         XDefineCursor(self->display, self->window, self->invisible_cursor);
-    else
+    } else
         XUndefineCursor(self->display, self->window);
     XUnlockDisplay(self->display);
 
@@ -257,9 +260,24 @@
 PyObject *
 X11Window_PyObject__get_geometry(X11Window_PyObject * self, PyObject * args)
 {
-    XWindowAttributes attrs;
+    int absolute;
+    if (!PyArg_ParseTuple(args, "i", &absolute))
+        return NULL;
+
+    XWindowAttributes attrs, parent_attrs;
     XLockDisplay(self->display);
     XGetWindowAttributes(self->display, self->window, &attrs);
+    if (absolute) {
+        Window w = self->window, root, parent = 0, *children;
+        unsigned int n_children;
+        while (parent != root) {
+            XQueryTree(self->display, w, &root, &parent, &children, 
&n_children);
+            XGetWindowAttributes(self->display, parent, &parent_attrs);
+            attrs.x += parent_attrs.x;
+            attrs.y += parent_attrs.y;
+            w = parent;
+        }
+    }
     XUnlockDisplay(self->display);
     return Py_BuildValue("((ii)(ii))", attrs.x, attrs.y, attrs.width,
                          attrs.height);
@@ -312,7 +330,7 @@
     XLockDisplay(self->display);
     XGetWindowAttributes(self->display, self->window, &attrs);
     XUnlockDisplay(self->display);
-    return Py_BuildValue("i", attrs.map_state);
+    return Py_BuildValue("i", attrs.map_state == IsViewable);
 }
 
 PyObject *
@@ -325,6 +343,184 @@
     return Py_None;
 }
 
+PyObject *
+X11Window_PyObject__set_title(X11Window_PyObject * self, PyObject * args)
+{
+    char *title;
+    if (!PyArg_ParseTuple(args, "s", &title))
+        return NULL;
+    XLockDisplay(self->display);
+    XStoreName(self->display, self->window, title);
+    XUnlockDisplay(self->display);
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+PyObject *
+X11Window_PyObject__get_title(X11Window_PyObject * self, PyObject * args)
+{
+    char *title;
+    PyObject *pytitle;
+
+    XLockDisplay(self->display);
+    XFetchName(self->display, self->window, &title);
+    XUnlockDisplay(self->display);
+    Py_INCREF(Py_None);
+
+    pytitle = Py_BuildValue("s", title);
+    XFree(title);
+    return pytitle;
+}
+
+static void
+_walk_children(Display *display, Window window, PyObject *pychildren, 
+               int scr_w, int scr_h, int x, int y,
+               int recursive, int visible_only, int titled_only)
+{
+    Window root, parent, *children;
+    unsigned int n_children, i;
+    XWindowAttributes attrs;
+    char *title;
+
+    XQueryTree(display, window, &root, &parent, &children, &n_children);
+
+    for (i = 0; i < n_children; i++) {
+        int child_x = x, child_y = y;
+        if (visible_only) {
+            XGetWindowAttributes(display, children[i], &attrs);
+            // Make x, y absolute for this child.
+            child_x = x + attrs.x;
+            child_y = y + attrs.y;
+
+            if (attrs.map_state != IsViewable || (child_y + attrs.height < 0 
|| child_y > scr_h) ||
+                (child_x + attrs.width < 0 || child_x > scr_w))
+                continue;
+        }
+        if (titled_only) {
+            XFetchName(display, children[i], &title);
+            if (title)
+                XFree(title);
+        }
+
+        if (!titled_only || title) {
+            PyObject *wid = Py_BuildValue("k", children[i]);
+            PyList_Append(pychildren, wid);
+            Py_DECREF(wid);
+        }
+
+        if (recursive)
+            _walk_children(display, children[i], pychildren, scr_w, scr_h, 
+                           child_x, child_y, recursive, visible_only, 
titled_only);
+    }
+}
+
+
+PyObject *
+X11Window_PyObject__get_children(X11Window_PyObject * self, PyObject * args)
+{
+    int recursive, visible_only, titled_only;
+    PyObject *pychildren;
+    XWindowAttributes attrs;
+
+    if (!PyArg_ParseTuple(args, "iii", &recursive, &visible_only, 
&titled_only))
+        return NULL;
+
+    // Fetch screen size
+    XGetWindowAttributes(self->display, self->window, &attrs);
+    pychildren = PyList_New(0);
+    XLockDisplay(self->display);
+    _walk_children(self->display, self->window, pychildren, 
attrs.screen->width, attrs.screen->height, 
+                   attrs.x, attrs.y, recursive, visible_only, titled_only);
+    XUnlockDisplay(self->display);
+
+    return pychildren;
+}
+
+PyObject *
+X11Window_PyObject__get_parent(X11Window_PyObject * self, PyObject * args)
+{
+    Window root, parent, *children;
+    unsigned int n_children;
+
+    XLockDisplay(self->display);
+    XQueryTree(self->display, self->window, &root, &parent, &children, 
&n_children);
+    XUnlockDisplay(self->display);
+
+    return Py_BuildValue("k", parent);
+}
+
+PyObject *
+X11Window_PyObject__get_properties(X11Window_PyObject * self, PyObject * args)
+{
+    Atom *properties, type;
+    int n_props, i, format;
+    unsigned long n_items, bytes_left;
+    char **property_names, *type_name;
+    unsigned char *data;
+    PyObject *list = PyList_New(0);
+
+    XLockDisplay(self->display);
+    properties = XListProperties(self->display, self->window, &n_props);
+    if (!properties) {
+        XUnlockDisplay(self->display);
+        return list;
+    }
+
+    // allocate a chunk of memory for atom values
+    data = malloc(8192); 
+    property_names = (char **)malloc(sizeof(char *) * n_props);
+    XGetAtomNames(self->display, properties, n_props, property_names);
+
+    // Iterate over all properties and make a list containing 5-tuples of:
+    // (atom name, atom type, format, number of items, data)
+    for (i = 0; i < n_props; i++) {
+        PyObject *tuple = PyTuple_New(5), *pydata;
+        int field_len = 1, n;
+        XGetWindowProperty(self->display, self->window, properties[i], 0, 256, 
False, AnyPropertyType, 
+                           &type, &format, &n_items, &bytes_left, &data);
+
+        field_len = format == 16 ? sizeof(short) : sizeof(long);
+        type_name = XGetAtomName(self->display, type);
+
+        if (!strcmp(type_name, "ATOM")) {
+            // For ATOM types, resolve atoms to their names.
+            pydata = PyList_New(0);
+            for (n = 0; n < n_items; n++, data += field_len) {
+                char *atom_name = XGetAtomName(self->display, *((Atom *)data));
+                PyObject *pyatom_name = PyString_FromString(atom_name);
+                PyList_Append(pydata, pyatom_name);
+                XFree(atom_name);
+                Py_DECREF(pyatom_name);
+            }
+        } else {
+            // For other types, just return the raw buffer and we will parse
+            // it in python space.
+            void *buffer_ptr;
+            int buffer_len;
+            pydata = PyBuffer_New(n_items * field_len + bytes_left);
+            PyObject_AsWriteBuffer(pydata, &buffer_ptr, &buffer_len);
+            memmove(buffer_ptr, data, n_items * field_len);
+            // TODO: if bytes_left > 0, need to fetch the rest.
+        }
+
+        PyTuple_SET_ITEM(tuple, 0, PyString_FromString(property_names[i]));
+        PyTuple_SET_ITEM(tuple, 1, PyString_FromString(type_name));
+        PyTuple_SET_ITEM(tuple, 2, PyLong_FromLong(format));
+        PyTuple_SET_ITEM(tuple, 3, PyLong_FromLong(n_items));
+        PyTuple_SET_ITEM(tuple, 4, pydata);
+
+        PyList_Append(list, tuple);
+        XFree(type_name);
+        XFree(property_names[i]);
+    }
+    free(property_names);
+    free(data);
+    XFree(properties);
+    XUnlockDisplay(self->display);
+    return list;
+}
+
+
 
 PyMethodDef X11Window_PyObject_methods[] = {
     { "show", (PyCFunction)X11Window_PyObject__show, METH_VARARGS },
@@ -338,6 +534,11 @@
     { "set_transient_for", 
(PyCFunction)X11Window_PyObject__set_transient_for_hint, METH_VARARGS },
     { "get_visible", (PyCFunction)X11Window_PyObject__get_visible, 
METH_VARARGS },
     { "focus", (PyCFunction)X11Window_PyObject__focus, METH_VARARGS },
+    { "set_title", (PyCFunction)X11Window_PyObject__set_title, METH_VARARGS },
+    { "get_title", (PyCFunction)X11Window_PyObject__get_title, METH_VARARGS },
+    { "get_children", (PyCFunction)X11Window_PyObject__get_children, 
METH_VARARGS },
+    { "get_parent", (PyCFunction)X11Window_PyObject__get_parent, METH_VARARGS 
},
+    { "get_properties", (PyCFunction)X11Window_PyObject__get_properties, 
METH_VARARGS },
     { NULL, NULL }
 };
 

Modified: trunk/display/src/x11window.h
==============================================================================
--- trunk/display/src/x11window.h       (original)
+++ trunk/display/src/x11window.h       Fri Jan 11 20:23:03 2008
@@ -49,6 +49,7 @@
     Cursor   invisible_cursor;
 
     PyObject *wid;
+    int owner;
 } X11Window_PyObject;
 
 extern PyTypeObject X11Window_PyObject_Type;

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace
_______________________________________________
Freevo-cvslog mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/freevo-cvslog

Reply via email to