This patch adds several new methods to X11Window which adds the ability
to set the shape mask for the window (either from a bitmask string or an
imlib2 image) and disable/enable windows decorations. I've also included
a test app that shows the new features in use.
Cheers
Adam
Index: display/src/x11window.c
===================================================================
--- display/src/x11window.c (revision 3235)
+++ display/src/x11window.c (working copy)
@@ -521,7 +521,112 @@
}
+PyObject *
+X11Window_PyObject__set_shape_mask(X11Window_PyObject * self, PyObject * args)
+{
+ const char *data;
+ Pixmap pix;
+ int allocated_bit_buffer = 0;
+ int len;
+ int x;
+ int y;
+ int width;
+ int height;
+
+
+ if (!PyArg_ParseTuple(args, "s#(ii)(ii)", &data, &len, &x, &y, &width, &height))
+ return NULL;
+
+ if ((width * height) == len)
+ {
+ int bit_count = 0;
+ int data_pos = 0;
+ int bit_buffer_pos = 0;
+ char *bit_buffer = malloc( ((width * height) + 7) / 8);
+ if (bit_buffer == NULL)
+ {
+ return NULL;
+ }
+
+ for (data_pos = 0; data_pos < len; data_pos ++)
+ {
+ bit_buffer[bit_buffer_pos] |= data[data_pos] << bit_count;
+ bit_count ++;
+ if (bit_count == 8)
+ {
+ bit_count = 0;
+ bit_buffer_pos ++;
+ bit_buffer[bit_buffer_pos] = 0;
+ }
+ }
+ data = bit_buffer;
+ allocated_bit_buffer = 1;
+ }
+
+ XLockDisplay(self->display);
+ // Construct a bitmap from the supplied data for passing to the XShape extension
+ pix = XCreateBitmapFromData(self->display, self->window, data, width, height);
+ if (pix != None)
+ {
+ XShapeCombineMask(self->display, self->window, ShapeBounding, x, y, pix, ShapeSet);
+ XFreePixmap(self->display, pix);
+ }
+ XUnlockDisplay(self->display);
+
+ if (allocated_bit_buffer)
+ {
+ free((void*)data);
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+PyObject *
+X11Window_PyObject__reset_shape_mask(X11Window_PyObject * self, PyObject * args)
+{
+ XLockDisplay(self->display);
+ XShapeCombineMask(self->display, self->window, ShapeBounding, 0, 0, None, ShapeSet);
+ XUnlockDisplay(self->display);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+PyObject *
+X11Window_PyObject__set_decorated(X11Window_PyObject * self, PyObject * args)
+{
+ int decorated = 1;
+ long data[1];
+ Atom _NET_WM_WINDOW_TYPE;
+
+ if (!PyArg_ParseTuple(args, "i", &decorated))
+ return NULL;
+
+
+ _NET_WM_WINDOW_TYPE = XInternAtom(self->display, "_NET_WM_WINDOW_TYPE", False);
+
+ if (decorated)
+ {
+ Atom _NET_WM_WINDOW_TYPE_NORMAL = XInternAtom(self->display, "_NET_WM_WINDOW_TYPE_NORMAL", False);
+
+ data[0] = (long) _NET_WM_WINDOW_TYPE_NORMAL;
+
+ }
+ else
+ {
+ Atom _NET_WM_WINDOW_TYPE_SPLASH = XInternAtom(self->display, "_NET_WM_WINDOW_TYPE_SPLASH", False);
+
+ data[0] = (long) _NET_WM_WINDOW_TYPE_SPLASH;
+ }
+
+ XLockDisplay(self->display);
+ XChangeProperty(self->display, self->window, _NET_WM_WINDOW_TYPE, XA_ATOM, 32, PropModeReplace, (char*)&data, 1);
+ XUnlockDisplay(self->display);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
PyMethodDef X11Window_PyObject_methods[] = {
{ "show", (PyCFunction)X11Window_PyObject__show, METH_VARARGS },
{ "hide", (PyCFunction)X11Window_PyObject__hide, METH_VARARGS },
@@ -534,11 +639,9 @@
{ "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 },
+ { "set_shape_mask", (PyCFunction)X11Window_PyObject__set_shape_mask, METH_VARARGS },
+ { "reset_shape_mask", (PyCFunction)X11Window_PyObject__reset_shape_mask, METH_VARARGS },
+ { "set_decorated", (PyCFunction)X11Window_PyObject__set_decorated, METH_VARARGS },
{ NULL, NULL }
};
Index: display/src/x11window.h
===================================================================
--- display/src/x11window.h (revision 3235)
+++ display/src/x11window.h (working copy)
@@ -36,6 +36,7 @@
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
+#include <X11/extensions/shape.h>
#include <stdint.h>
#define X11Window_PyObject_Check(v) ((v)->ob_type == &X11Window_PyObject_Type)
Index: display/src/x11.c
===================================================================
--- display/src/x11.c (revision 3235)
+++ display/src/x11.c (working copy)
@@ -248,8 +248,55 @@
#endif
}
+PyObject *set_shape_mask_from_imlib2_image(PyObject *self, PyObject *args)
+{
+#if defined(USE_IMLIB2_X11) && !defined(X_DISPLAY_MISSING)
+ X11Window_PyObject *window;
+ PyObject *pyimg;
+ Imlib_Image *img;
+ int x = 0, y = 0;
+ int threshold;
+ XWindowAttributes attrs;
+ Pixmap image_pixmap, mask_pixmap;
+
+ CHECK_IMAGE_PYOBJECT
+
+ if (!PyArg_ParseTuple(args, "O!O!|(ii)i",
+ &X11Window_PyObject_Type, &window,
+ Image_PyObject_Type, &pyimg,
+ &x, &y, &threshold))
+ return NULL;
+
+ img = imlib_image_from_pyobject(pyimg);
+
+ XGetWindowAttributes(window->display, window->window, &attrs);
+
+ imlib_context_set_display(window->display);
+ imlib_context_set_drawable(window->window);
+ imlib_context_set_visual(attrs.visual);
+ imlib_context_set_colormap(attrs.colormap);
+
+ imlib_context_set_image(img);
+ imlib_context_set_mask_alpha_threshold(threshold);
+
+ imlib_render_pixmaps_for_whole_image(&image_pixmap, &mask_pixmap);
+ if (mask_pixmap != None)
+ {
+ XShapeCombineMask(window->display, window->window, ShapeBounding, x, y, mask_pixmap, ShapeSet);
+ imlib_free_pixmap_and_mask(image_pixmap);
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+#else
+ PyErr_Format(PyExc_SystemError, "kaa-display compiled without imlib2 display support.");
+ return NULL;
+#endif
+}
+
PyMethodDef display_methods[] = {
{ "render_imlib2_image", (PyCFunction) render_imlib2_image, METH_VARARGS },
+ { "set_shape_mask_from_imlib2_image", (PyCFunction) set_shape_mask_from_imlib2_image, METH_VARARGS },
#ifdef ENABLE_ENGINE_SOFTWARE_X11
{ "new_evas_software_x11", (PyCFunction) new_evas_software_x11, METH_VARARGS | METH_KEYWORDS },
#endif
Index: display/src/x11.py
===================================================================
--- display/src/x11.py (revision 3235)
+++ display/src/x11.py (working copy)
@@ -467,6 +467,54 @@
return props
+ def set_shape_mask(self, mask, pos, size ):
+ """
+ Set the shape mask for a window using the XShape extension.
+
+ @param mask: A string containing either a bitmask or a byte-per-pixel
+ to use as the shape mask.
+ @param pos: X,Y Position in the window to apply the mask.
+ @param size: Width,Height of the mask.
+ """
+
+ if (len(mask) == ((size[0] * size[1]) + 7) / 8) or (len(mask) == size[0] * size[1]):
+ # Add 7 ensures that when we divided by 8 we have enough bytes to store
+ # all the bits needed. Take 3w * 3h = 9 bits, (3 * 3) + 7 = 16 bits
+ # ie 2 bytes.
+ self._window.set_shape_mask(mask, pos, size)
+ else:
+ raise ValueError('Mask is wrong length!')
+
+ def set_shape_mask_from_imlib2_image(self, image, pos, threshold=128):
+ """
+ Set the shape mask for the window based on the pixel alpha values.
+
+ @param image: Imlib2 image with per pixel alpha to use as the mask.
+ @param pos: X,Y Position in the window to apply the mask.
+ @param threshold: Pixels with alpha values >= to this will be shown.
+ """
+ if image.has_alpha:
+ _X11.set_shape_mask_from_imlib2_image(self._window, image._image, pos, threshold)
+ else:
+ raise ValueError('Image does not have an alpha channel!')
+
+ def reset_shape_mask(self):
+ """
+ Reset (remove) the shape mask of the window.
+ """
+ self._window.reset_shape_mask()
+
+ def set_decorated(self, setting):
+ """
+ Set whether the window manager should add a border and controls to the
+ window or not.
+
+ Note: Windows must be hidden or not yet shown before changing this setting.
+
+ @param setting: True if the window should be decorated, false if not.
+ """
+ self._window.set_decorated(setting)
+
class EvasX11Window(X11Window):
def __init__(self, gl = False, display = None, size = (640, 480),
--- /dev/null 2008-02-29 21:05:19.000000000 +0000
+++ display/test/shaped.py 2008-03-26 16:02:24.000000000 +0000
@@ -0,0 +1,55 @@
+from kaa import imlib2, display, main
+
+decorated = False
+shaped = True
+
+def redraw(regions):
+ window.render_imlib2_image(image)
+
+def key_pressed(key):
+ key = key.lower()
+ if key == 'esc' or key == 'q':
+ main.stop()
+
+ if key == 'd':
+ global decorated
+ decorated = not decorated
+ window.hide()
+ window.set_decorated(decorated)
+ window.show()
+
+ if key == 's':
+ global shaped
+ shaped = not shaped
+ if shaped:
+ window.set_shape_mask_from_imlib2_image(image, (0,0))
+ else:
+ window.reset_shape_mask()
+
+def mapped():
+ window.focus()
+
+window = display.X11Window(size = (800, 600), title = "Kaa Display Test")
+
+imlib2.add_font_path("data")
+
+image = imlib2.new((800,600))
+image.clear()
+image.draw_ellipse((400,300), (400, 300), (0,0,255,255))
+image.draw_text((10, 50), "This is a Kaa Display Shaped Window Test", (255,255,255,255), "VeraBd/24")
+
+window.signals['expose_event'].connect(redraw)
+window.signals['key_press_event'].connect(key_pressed)
+window.signals['map_event'].connect(mapped)
+
+window.set_decorated(decorated)
+window.set_shape_mask_from_imlib2_image(image, (0,0))
+window.show()
+
+
+print 'Shaped window test app'
+print 'Use the following keys to test features'
+print 'Esc or q = Quit'
+print 'd = Toggle Decorated'
+print 's = Toggle shaped'
+main.run()
-------------------------------------------------------------------------
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-devel mailing list
Freevo-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/freevo-devel