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

Reply via email to