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