summaryrefslogtreecommitdiff
path: root/Source/DirectFB/src/core/windowstack.c
diff options
context:
space:
mode:
Diffstat (limited to 'Source/DirectFB/src/core/windowstack.c')
-rwxr-xr-xSource/DirectFB/src/core/windowstack.c998
1 files changed, 998 insertions, 0 deletions
diff --git a/Source/DirectFB/src/core/windowstack.c b/Source/DirectFB/src/core/windowstack.c
new file mode 100755
index 0000000..7a19f1c
--- /dev/null
+++ b/Source/DirectFB/src/core/windowstack.c
@@ -0,0 +1,998 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <string.h>
+
+#include <directfb.h>
+
+#include <direct/debug.h>
+#include <direct/list.h>
+#include <direct/messages.h>
+
+#include <fusion/reactor.h>
+#include <fusion/shmalloc.h>
+
+#include <core/core.h>
+#include <core/input.h>
+#include <core/layer_context.h>
+#include <core/layers_internal.h>
+#include <core/surface.h>
+#include <core/windows_internal.h>
+#include <core/windowstack.h>
+#include <core/wm.h>
+
+#include <misc/conf.h>
+
+#include <gfx/convert.h>
+#include <gfx/util.h>
+
+
+#define CURSORFILE DATADIR"/cursor.dat"
+
+
+D_DEBUG_DOMAIN( Core_WindowStack, "Core/WindowStack", "DirectFB Core WindowStack" );
+
+/**********************************************************************************************************************/
+
+typedef struct {
+ DirectLink link;
+
+ DFBInputDeviceID id;
+ Reaction reaction;
+} StackDevice;
+
+typedef struct {
+ DirectLink link;
+
+ DFBInputDeviceKeySymbol symbol;
+ DFBInputDeviceModifierMask modifiers;
+
+ CoreWindow *owner;
+} GrabbedKey;
+
+/**********************************************************************************************************************/
+
+static DFBResult load_default_cursor ( CoreDFB *core,
+ CoreWindowStack *stack );
+static DFBResult create_cursor_surface( CoreWindowStack *stack,
+ int width,
+ int height );
+
+/**********************************************************************************************************************/
+
+static DFBEnumerationResult stack_attach_devices( CoreInputDevice *device,
+ void *ctx );
+
+static ReactionResult stack_input_core_listener( const void *msg_data,
+ void *ctx );
+
+/**********************************************************************************************************************/
+
+/*
+ * Allocates and initializes a window stack.
+ */
+CoreWindowStack*
+dfb_windowstack_create( CoreLayerContext *context )
+{
+ DFBResult ret;
+ CoreWindowStack *stack;
+ CoreSurfacePolicy policy = CSP_SYSTEMONLY;
+ CoreLayer *layer;
+
+ D_DEBUG_AT( Core_WindowStack, "%s( %p )\n", __FUNCTION__, context );
+
+ D_ASSERT( context != NULL );
+
+ layer = dfb_layer_at( context->layer_id );
+
+ /* Allocate window stack data (completely shared) */
+ stack = (CoreWindowStack*) SHCALLOC( context->shmpool, 1, sizeof(CoreWindowStack) );
+ if (!stack) {
+ D_OOSHM();
+ return NULL;
+ }
+
+ stack->shmpool = context->shmpool;
+
+ /* Store context which we belong to. */
+ stack->context = context;
+
+ /* Set default acceleration */
+ stack->cursor.numerator = 2;
+ stack->cursor.denominator = 1;
+ stack->cursor.threshold = 4;
+
+ /* Choose cursor surface policy. */
+ if (context->config.buffermode != DLBM_BACKSYSTEM) {
+ CardCapabilities card_caps;
+
+ /* Use the explicitly specified policy? */
+ if (dfb_config->window_policy != -1)
+ policy = dfb_config->window_policy;
+ else {
+ /* Examine the hardware capabilities. */
+ dfb_gfxcard_get_capabilities( &card_caps );
+
+ if (card_caps.accel & DFXL_BLIT && card_caps.blitting & DSBLIT_BLEND_ALPHACHANNEL)
+ policy = CSP_VIDEOHIGH;
+ }
+ }
+
+ stack->cursor.policy = policy;
+ stack->cursor.opacity = 0xFF;
+
+ /* Set default background mode. */
+ stack->bg.mode = DLBM_DONTCARE;
+ stack->bg.color_index = -1;
+
+ D_MAGIC_SET( stack, CoreWindowStack );
+
+ /* Initialize window manager */
+ ret = dfb_wm_init_stack( stack );
+ if (ret) {
+ D_MAGIC_CLEAR( stack );
+ SHFREE( context->shmpool, stack );
+ return NULL;
+ }
+
+ if (dfb_core_is_master( layer->core ))
+ dfb_input_core_attach( layer->core, stack_input_core_listener, stack, &stack->input_core_reaction );
+
+ /* Attach to all input devices */
+ dfb_input_enumerate_devices( stack_attach_devices, stack, DICAPS_ALL );
+
+ D_DEBUG_AT( Core_WindowStack, " -> %p\n", stack );
+
+ return stack;
+}
+
+void
+dfb_windowstack_detach_devices( CoreWindowStack *stack )
+{
+ DirectLink *l;
+
+ D_DEBUG_AT( Core_WindowStack, "%s( %p )\n", __FUNCTION__, stack );
+
+ D_MAGIC_ASSERT( stack, CoreWindowStack );
+
+ /* Detach all input devices. */
+ l = stack->devices;
+ while (l) {
+ DirectLink *next = l->next;
+ StackDevice *device = (StackDevice*) l;
+
+ dfb_input_detach( dfb_input_device_at( device->id ),
+ &device->reaction );
+
+ SHFREE( stack->shmpool, device );
+
+ l = next;
+ }
+}
+
+void
+dfb_windowstack_destroy( CoreWindowStack *stack )
+{
+ D_DEBUG_AT( Core_WindowStack, "%s( %p )\n", __FUNCTION__, stack );
+
+ D_MAGIC_ASSERT( stack, CoreWindowStack );
+
+ if (stack->input_core_reaction.func)
+ dfb_input_core_detach( NULL, &stack->input_core_reaction );
+
+ /* Unlink cursor surface. */
+ if (stack->cursor.surface)
+ dfb_surface_unlink( &stack->cursor.surface );
+
+ /* Shutdown window manager? */
+ if (stack->flags & CWSF_INITIALIZED)
+ dfb_wm_close_stack( stack );
+
+ /* detach listener from background surface and unlink it */
+ if (stack->bg.image) {
+ dfb_surface_detach_global( stack->bg.image,
+ &stack->bg.image_reaction );
+
+ dfb_surface_unlink( &stack->bg.image );
+ }
+
+ /* Deallocate shared stack data. */
+ if (stack->stack_data) {
+ SHFREE( stack->shmpool, stack->stack_data );
+ stack->stack_data = NULL;
+ }
+
+ D_MAGIC_CLEAR( stack );
+
+ /* Free stack data. */
+ SHFREE( stack->shmpool, stack );
+}
+
+void
+dfb_windowstack_resize( CoreWindowStack *stack,
+ int width,
+ int height,
+ int rotation )
+{
+ D_DEBUG_AT( Core_WindowStack, "%s( %p, %dx%d, %d )\n", __FUNCTION__, stack, width, height, rotation );
+
+ D_MAGIC_ASSERT( stack, CoreWindowStack );
+
+ /* Lock the window stack. */
+ if (dfb_windowstack_lock( stack ))
+ return;
+
+ /* Store the width and height of the stack */
+ stack->width = width;
+ stack->height = height;
+ stack->rotation = rotation;
+
+ switch (stack->rotation) {
+ default:
+ D_BUG( "invalid rotation %d", stack->rotation );
+ case 0:
+ stack->rotated_blit = DSBLIT_NOFX;
+ stack->rotated_width = stack->width;
+ stack->rotated_height = stack->height;
+ break;
+
+ case 90:
+ stack->rotated_blit = DSBLIT_ROTATE90;
+ stack->rotated_width = stack->height;
+ stack->rotated_height = stack->width;
+ break;
+
+ case 180:
+ stack->rotated_blit = DSBLIT_ROTATE180;
+ stack->rotated_width = stack->width;
+ stack->rotated_height = stack->height;
+ break;
+
+ case 270:
+ stack->rotated_blit = DSBLIT_ROTATE270;
+ stack->rotated_width = stack->height;
+ stack->rotated_height = stack->width;
+ break;
+ }
+
+ /* Setup new cursor clipping region */
+ stack->cursor.region.x1 = 0;
+ stack->cursor.region.y1 = 0;
+ stack->cursor.region.x2 = width - 1;
+ stack->cursor.region.y2 = height - 1;
+
+ /* Notify the window manager. */
+ dfb_wm_resize_stack( stack, width, height );
+
+ /* Unlock the window stack. */
+ dfb_windowstack_unlock( stack );
+}
+
+/*
+ * Prohibit access to the window stack data.
+ * Waits until stack is accessible.
+ */
+DirectResult
+dfb_windowstack_lock( CoreWindowStack *stack )
+{
+ D_MAGIC_ASSERT( stack, CoreWindowStack );
+ D_ASSERT( stack->context != NULL );
+
+ return dfb_layer_context_lock( stack->context );
+}
+
+/*
+ * Allow access to the window stack data.
+ */
+DirectResult
+dfb_windowstack_unlock( CoreWindowStack *stack )
+{
+ D_MAGIC_ASSERT( stack, CoreWindowStack );
+ D_ASSERT( stack->context != NULL );
+
+ return dfb_layer_context_unlock( stack->context );
+}
+
+DFBResult
+dfb_windowstack_repaint_all( CoreWindowStack *stack )
+{
+ DFBResult ret;
+ DFBRegion region;
+
+ D_DEBUG_AT( Core_WindowStack, "%s( %p )\n", __FUNCTION__, stack );
+
+ D_MAGIC_ASSERT( stack, CoreWindowStack );
+
+ /* Lock the window stack. */
+ if (dfb_windowstack_lock( stack ))
+ return DFB_FUSION;
+
+ region.x1 = 0;
+ region.y1 = 0;
+ region.x2 = stack->rotated_width - 1;
+ region.y2 = stack->rotated_height - 1;
+
+ ret = dfb_wm_update_stack( stack, &region, 0 );
+
+ /* Unlock the window stack. */
+ dfb_windowstack_unlock( stack );
+
+ return ret;
+}
+
+/**********************************************************************************************************************/
+
+/*
+ * background handling
+ */
+
+DFBResult
+dfb_windowstack_set_background_mode ( CoreWindowStack *stack,
+ DFBDisplayLayerBackgroundMode mode )
+{
+ D_DEBUG_AT( Core_WindowStack, "%s( %p, %d )\n", __FUNCTION__, stack, mode );
+
+ D_MAGIC_ASSERT( stack, CoreWindowStack );
+
+ /* Lock the window stack. */
+ if (dfb_windowstack_lock( stack ))
+ return DFB_FUSION;
+
+ /* nothing to do if mode is the same */
+ if (mode != stack->bg.mode) {
+ /* for these modes a surface is required */
+ if ((mode == DLBM_IMAGE || mode == DLBM_TILE) && !stack->bg.image) {
+ dfb_windowstack_unlock( stack );
+ return DFB_MISSINGIMAGE;
+ }
+
+ /* set new mode */
+ stack->bg.mode = mode;
+
+ /* force an update of the window stack */
+ if (mode != DLBM_DONTCARE)
+ dfb_windowstack_repaint_all( stack );
+ }
+
+ /* Unlock the window stack. */
+ dfb_windowstack_unlock( stack );
+
+ return DFB_OK;
+}
+
+DFBResult
+dfb_windowstack_set_background_image( CoreWindowStack *stack,
+ CoreSurface *image )
+{
+ D_DEBUG_AT( Core_WindowStack, "%s( %p, %p )\n", __FUNCTION__, stack, image );
+
+ D_MAGIC_ASSERT( stack, CoreWindowStack );
+ D_ASSERT( image != NULL );
+
+ if (!(image->type & CSTF_SHARED))
+ return DFB_INVARG;
+
+ /* Lock the window stack. */
+ if (dfb_windowstack_lock( stack ))
+ return DFB_FUSION;
+
+ /* if the surface is changed */
+ if (stack->bg.image != image) {
+ /* detach listener from old surface and unlink it */
+ if (stack->bg.image) {
+ dfb_surface_detach_global( stack->bg.image,
+ &stack->bg.image_reaction );
+
+ dfb_surface_unlink( &stack->bg.image );
+ }
+
+ /* link surface object */
+ dfb_surface_link( &stack->bg.image, image );
+
+ /* attach listener to new surface */
+ dfb_surface_attach_global( image,
+ DFB_WINDOWSTACK_BACKGROUND_IMAGE_LISTENER,
+ stack, &stack->bg.image_reaction );
+ }
+
+ /* force an update of the window stack */
+ if (stack->bg.mode == DLBM_IMAGE || stack->bg.mode == DLBM_TILE)
+ dfb_windowstack_repaint_all( stack );
+
+ /* Unlock the window stack. */
+ dfb_windowstack_unlock( stack );
+
+ return DFB_OK;
+}
+
+DFBResult
+dfb_windowstack_set_background_color( CoreWindowStack *stack,
+ const DFBColor *color )
+{
+ D_ASSERT( color != NULL );
+
+ D_DEBUG_AT( Core_WindowStack, "%s( %p, 0x%08x )\n", __FUNCTION__, stack,
+ PIXEL_ARGB( color->a, color->r, color->g, color->b ) );
+
+ D_MAGIC_ASSERT( stack, CoreWindowStack );
+
+ /* Lock the window stack. */
+ if (dfb_windowstack_lock( stack ))
+ return DFB_FUSION;
+
+ /* do nothing if color didn't change */
+ if (!DFB_COLOR_EQUAL( stack->bg.color, *color )) {
+ /* set new color */
+ stack->bg.color = *color;
+
+ /* force an update of the window stack */
+ if (stack->bg.mode == DLBM_COLOR)
+ dfb_windowstack_repaint_all( stack );
+ }
+
+ /* Unlock the window stack. */
+ dfb_windowstack_unlock( stack );
+
+ return DFB_OK;
+}
+
+DFBResult
+dfb_windowstack_set_background_color_index( CoreWindowStack *stack,
+ int index )
+{
+ D_DEBUG_AT( Core_WindowStack, "%s( %p, %d )\n", __FUNCTION__, stack, index );
+
+ D_MAGIC_ASSERT( stack, CoreWindowStack );
+
+ /* Lock the window stack. */
+ if (dfb_windowstack_lock( stack ))
+ return DFB_FUSION;
+
+ /* do nothing if color didn't change */
+ if (stack->bg.color_index != index) {
+ /* set new color index */
+ stack->bg.color_index = index;
+
+ /* force an update of the window stack */
+ if (stack->bg.mode == DLBM_COLOR)
+ dfb_windowstack_repaint_all( stack );
+ }
+
+ /* Unlock the window stack. */
+ dfb_windowstack_unlock( stack );
+
+ return DFB_OK;
+}
+
+/**********************************************************************************************************************/
+
+/*
+ * cursor control
+ */
+
+DFBResult
+dfb_windowstack_cursor_enable( CoreDFB *core, CoreWindowStack *stack, bool enable )
+{
+ DFBResult ret;
+
+ D_DEBUG_AT( Core_WindowStack, "%s( %p, %s )\n", __FUNCTION__, stack, enable ? "enable" : "disable" );
+
+ D_MAGIC_ASSERT( stack, CoreWindowStack );
+
+ /* Lock the window stack. */
+ if (dfb_windowstack_lock( stack ))
+ return DFB_FUSION;
+
+ stack->cursor.set = true;
+
+ if (dfb_config->no_cursor || stack->cursor.enabled == enable) {
+ dfb_windowstack_unlock( stack );
+ return DFB_OK;
+ }
+
+ if (enable && !stack->cursor.surface) {
+ ret = load_default_cursor( core, stack );
+ if (ret) {
+ dfb_windowstack_unlock( stack );
+ return ret;
+ }
+ }
+
+ /* Keep state. */
+ stack->cursor.enabled = enable;
+
+ /* Notify WM. */
+ dfb_wm_update_cursor( stack, enable ? CCUF_ENABLE : CCUF_DISABLE );
+
+ /* Unlock the window stack. */
+ dfb_windowstack_unlock( stack );
+
+ return DFB_OK;
+}
+
+DFBResult
+dfb_windowstack_cursor_set_opacity( CoreWindowStack *stack, u8 opacity )
+{
+ D_DEBUG_AT( Core_WindowStack, "%s( %p, 0x%02x )\n", __FUNCTION__, stack, opacity );
+
+ D_MAGIC_ASSERT( stack, CoreWindowStack );
+
+ /* Lock the window stack. */
+ if (dfb_windowstack_lock( stack ))
+ return DFB_FUSION;
+
+ if (stack->cursor.opacity != opacity) {
+ /* Set new opacity. */
+ stack->cursor.opacity = opacity;
+
+ /* Notify WM. */
+ if (stack->cursor.enabled)
+ dfb_wm_update_cursor( stack, CCUF_OPACITY );
+ }
+
+ /* Unlock the window stack. */
+ dfb_windowstack_unlock( stack );
+
+ return DFB_OK;
+}
+
+DFBResult
+dfb_windowstack_cursor_set_shape( CoreWindowStack *stack,
+ CoreSurface *shape,
+ int hot_x,
+ int hot_y )
+{
+ DFBResult ret;
+ CoreSurface *cursor;
+ CoreCursorUpdateFlags flags = CCUF_SHAPE;
+
+ D_DEBUG_AT( Core_WindowStack, "%s( %p, %p, hot %d, %d ) <- size %dx%d\n",
+ __FUNCTION__, stack, shape, hot_x, hot_y,
+ shape->config.size.w, shape->config.size.h );
+
+ D_MAGIC_ASSERT( stack, CoreWindowStack );
+ D_ASSERT( shape != NULL );
+
+ if (dfb_config->no_cursor)
+ return DFB_OK;
+
+ /* Lock the window stack. */
+ if (dfb_windowstack_lock( stack ))
+ return DFB_FUSION;
+
+ cursor = stack->cursor.surface;
+ if (!cursor) {
+ D_ASSUME( !stack->cursor.enabled );
+
+ /* Create the a surface for the shape. */
+ ret = create_cursor_surface( stack, shape->config.size.w, shape->config.size.h );
+ if (ret) {
+ dfb_windowstack_unlock( stack );
+ return ret;
+ }
+
+ cursor = stack->cursor.surface;
+ }
+ else if (stack->cursor.size.w != shape->config.size.w || stack->cursor.size.h != shape->config.size.h) {
+ dfb_surface_unlink( &stack->cursor.surface );
+
+ /* Recreate the surface for the shape. */
+ ret = create_cursor_surface( stack, shape->config.size.w, shape->config.size.h );
+ if (ret) {
+ dfb_windowstack_unlock( stack );
+ return ret;
+ }
+
+ cursor = stack->cursor.surface;
+
+
+ stack->cursor.size.w = shape->config.size.w;
+ stack->cursor.size.h = shape->config.size.h;
+
+ /* Notify about new size/shape. */
+ flags |= CCUF_SIZE | CCUF_SHAPE;
+ }
+
+ if (stack->cursor.hot.x != hot_x || stack->cursor.hot.y != hot_y) {
+ stack->cursor.hot.x = hot_x;
+ stack->cursor.hot.y = hot_y;
+
+ /* Notify about new position. */
+ flags |= CCUF_POSITION;
+ }
+
+ /* Copy the content of the new shape. */
+ dfb_gfx_copy( shape, cursor, NULL );
+
+ cursor->config.caps = ((cursor->config.caps & ~DSCAPS_PREMULTIPLIED) | (shape->config.caps & DSCAPS_PREMULTIPLIED));
+
+ /* Notify the WM. */
+ if (stack->cursor.enabled)
+ dfb_wm_update_cursor( stack, flags );
+
+ /* Unlock the window stack. */
+ dfb_windowstack_unlock( stack );
+
+ return DFB_OK;
+}
+
+DFBResult
+dfb_windowstack_cursor_warp( CoreWindowStack *stack, int x, int y )
+{
+ D_DEBUG_AT( Core_WindowStack, "%s( %p, %d, %d )\n", __FUNCTION__, stack, x, y );
+
+ D_MAGIC_ASSERT( stack, CoreWindowStack );
+
+ /* Lock the window stack. */
+ if (dfb_windowstack_lock( stack ))
+ return DFB_FUSION;
+
+ if (x < 0)
+ x = 0;
+ else if (x > stack->width - 1)
+ x = stack->width - 1;
+
+ if (y < 0)
+ y = 0;
+ else if (y > stack->height - 1)
+ y = stack->height - 1;
+
+ if (stack->cursor.x != x || stack->cursor.y != y) {
+ stack->cursor.x = x;
+ stack->cursor.y = y;
+
+ /* Notify the WM. */
+ if (stack->cursor.enabled)
+ dfb_wm_update_cursor( stack, CCUF_POSITION );
+ }
+
+ /* Unlock the window stack. */
+ dfb_windowstack_unlock( stack );
+
+ return DFB_OK;
+}
+
+DFBResult
+dfb_windowstack_cursor_set_acceleration( CoreWindowStack *stack,
+ int numerator,
+ int denominator,
+ int threshold )
+{
+ D_DEBUG_AT( Core_WindowStack, "%s( %p, %d, %d, %d )\n",
+ __FUNCTION__, stack, numerator, denominator, threshold );
+
+ D_MAGIC_ASSERT( stack, CoreWindowStack );
+
+ /* Lock the window stack. */
+ if (dfb_windowstack_lock( stack ))
+ return DFB_FUSION;
+
+ stack->cursor.numerator = numerator;
+ stack->cursor.denominator = denominator;
+ stack->cursor.threshold = threshold;
+
+ /* Unlock the window stack. */
+ dfb_windowstack_unlock( stack );
+
+ return DFB_OK;
+}
+
+DFBResult
+dfb_windowstack_get_cursor_position( CoreWindowStack *stack, int *ret_x, int *ret_y )
+{
+ D_DEBUG_AT( Core_WindowStack, "%s( %p, %p, %p )\n", __FUNCTION__, stack, ret_x, ret_y );
+
+ D_MAGIC_ASSERT( stack, CoreWindowStack );
+ D_ASSUME( ret_x != NULL || ret_y != NULL );
+
+ /* Lock the window stack. */
+ if (dfb_windowstack_lock( stack ))
+ return DFB_FUSION;
+
+ if (ret_x)
+ *ret_x = stack->cursor.x;
+
+ if (ret_y)
+ *ret_y = stack->cursor.y;
+
+ /* Unlock the window stack. */
+ dfb_windowstack_unlock( stack );
+
+ return DFB_OK;
+}
+
+/**********************************************************************************************************************/
+
+static ReactionResult
+stack_input_core_listener( const void *msg_data,
+ void *ctx )
+{
+ const CoreInputCoreNotification *notification = msg_data;
+ CoreWindowStack *stack = ctx;
+
+ (void) notification;
+
+ D_DEBUG_AT( Core_WindowStack, "%s( %p, %p, %d )\n", __FUNCTION__, msg_data, ctx, notification->device_id );
+
+ D_ASSERT( msg_data != NULL );
+ D_MAGIC_ASSERT( stack, CoreWindowStack );
+
+ /* Lock the window stack. */
+ if (dfb_windowstack_lock( stack ))
+ return RS_REMOVE;
+
+ /* Attach to all input devices */
+ dfb_input_enumerate_devices( stack_attach_devices, stack, DICAPS_ALL );
+
+ /* Unlock the window stack. */
+ dfb_windowstack_unlock( stack );
+
+ return RS_OK;
+}
+
+ReactionResult
+_dfb_windowstack_inputdevice_listener( const void *msg_data,
+ void *ctx )
+{
+ const DFBInputEvent *event = msg_data;
+ CoreWindowStack *stack = ctx;
+
+ D_DEBUG_AT( Core_WindowStack, "%s( %p, %p )\n", __FUNCTION__, msg_data, ctx );
+
+ D_ASSERT( msg_data != NULL );
+ D_MAGIC_ASSERT( stack, CoreWindowStack );
+
+ /* Lock the window stack. */
+ if (dfb_windowstack_lock( stack ))
+ return RS_REMOVE;
+
+ /* Call the window manager to dispatch the event. */
+ if (dfb_layer_context_active( stack->context ))
+ dfb_wm_process_input( stack, event );
+
+ /* Unlock the window stack. */
+ dfb_windowstack_unlock( stack );
+
+ return RS_OK;
+}
+
+/*
+ * listen to the background image
+ */
+ReactionResult
+_dfb_windowstack_background_image_listener( const void *msg_data,
+ void *ctx )
+{
+ const CoreSurfaceNotification *notification = msg_data;
+ CoreWindowStack *stack = ctx;
+
+ D_DEBUG_AT( Core_WindowStack, "%s( %p, %p )\n", __FUNCTION__, msg_data, ctx );
+
+ D_ASSERT( notification != NULL );
+ D_MAGIC_ASSERT( stack, CoreWindowStack );
+
+ if (notification->flags & CSNF_DESTROY) {
+ if (stack->bg.image == notification->surface) {
+ D_ERROR( "Core/WindowStack: Surface for background vanished.\n" );
+
+ stack->bg.mode = DLBM_COLOR;
+ stack->bg.image = NULL;
+
+ dfb_windowstack_repaint_all( stack );
+ }
+
+ return RS_REMOVE;
+ }
+
+ if (notification->flags & (CSNF_FLIP | CSNF_SIZEFORMAT))
+ dfb_windowstack_repaint_all( stack );
+
+ return RS_OK;
+}
+
+/**********************************************************************************************************************/
+
+/*
+ * internals
+ */
+
+static DFBEnumerationResult
+stack_attach_devices( CoreInputDevice *device,
+ void *ctx )
+{
+ StackDevice *dev;
+ DFBInputDeviceID id = dfb_input_device_id( device );
+ CoreWindowStack *stack = (CoreWindowStack*) ctx;
+
+ D_MAGIC_ASSERT( stack, CoreWindowStack );
+
+ direct_list_foreach (dev, stack->devices) {
+ if (dev->id == id)
+ return DFENUM_OK;
+ }
+
+ dev = SHCALLOC( stack->shmpool, 1, sizeof(StackDevice) );
+ if (!dev) {
+ D_ERROR( "Core/WindowStack: Could not allocate %zu bytes\n", sizeof(StackDevice) );
+ return DFENUM_CANCEL;
+ }
+
+ dev->id = id;
+
+ direct_list_prepend( &stack->devices, &dev->link );
+
+ dfb_input_attach( device, _dfb_windowstack_inputdevice_listener, ctx, &dev->reaction );
+
+ return DFENUM_OK;
+}
+
+/*
+ * internal function that installs the cursor window
+ * and fills it with data from 'cursor.dat'
+ */
+static DFBResult
+load_default_cursor( CoreDFB *core, CoreWindowStack *stack )
+{
+ DFBResult ret;
+ int i;
+ FILE *f;
+ CoreSurfaceBufferLock lock;
+ void *data;
+
+ D_DEBUG_AT( Core_WindowStack, "%s( %p )\n", __FUNCTION__, stack );
+
+ D_MAGIC_ASSERT( stack, CoreWindowStack );
+
+ if (!stack->cursor.surface) {
+ ret = create_cursor_surface( stack, 40, 40 );
+ if (ret)
+ return ret;
+ }
+ else {
+ stack->cursor.hot.x = 0;
+ stack->cursor.hot.y = 0;
+ stack->cursor.size.w = 40;
+ stack->cursor.size.h = 40;
+ }
+
+ /* lock the cursor surface */
+ ret = dfb_surface_lock_buffer( stack->cursor.surface, CSBR_BACK, CSAID_CPU, CSAF_WRITE, &lock );
+ if (ret) {
+ D_ERROR( "Core/WindowStack: cannot lock the cursor surface!\n" );
+ return ret;
+ }
+
+ data = lock.addr;
+
+ /* initialize as empty cursor */
+ memset( data, 0, 40 * lock.pitch );
+
+ /* open the file containing the cursors image data */
+ f = fopen( CURSORFILE, "rb" );
+ if (!f) {
+ ret = errno2result( errno );
+
+ /* ignore a missing cursor file */
+ if (ret == DFB_FILENOTFOUND)
+ ret = DFB_OK;
+ else
+ D_PERROR( "Core/WindowStack: `" CURSORFILE "` could not be opened!\n" );
+
+ goto finish;
+ }
+
+ /* read from file directly into the cursor window surface */
+ for (i=0; i<40; i++) {
+ if (fread( data, MIN (40*4, lock.pitch), 1, f ) != 1) {
+ ret = errno2result( errno );
+
+ D_ERROR( "Core/WindowStack: unexpected end or read error of cursor data!\n" );
+
+ goto finish;
+ }
+#ifdef WORDS_BIGENDIAN
+ {
+ int i = MIN (40, lock.pitch/4);
+ u32 *tmp_data = data;
+
+ while (i--) {
+ *tmp_data = (*tmp_data & 0xFF000000) >> 24 |
+ (*tmp_data & 0x00FF0000) >> 8 |
+ (*tmp_data & 0x0000FF00) << 8 |
+ (*tmp_data & 0x000000FF) << 24;
+ ++tmp_data;
+ }
+ }
+#endif
+ data += lock.pitch;
+ }
+
+finish:
+ if (f)
+ fclose( f );
+
+ dfb_surface_unlock_buffer( stack->cursor.surface, &lock );
+
+ return ret;
+}
+
+static DFBResult
+create_cursor_surface( CoreWindowStack *stack,
+ int width,
+ int height )
+{
+ DFBResult ret;
+ CoreSurface *surface;
+ CoreLayer *layer;
+ CoreLayerContext *context;
+ DFBSurfaceCapabilities surface_caps = DSCAPS_NONE;
+
+ D_DEBUG_AT( Core_WindowStack, "%s( %p, %dx%d )\n", __FUNCTION__, stack, width, height );
+
+ D_MAGIC_ASSERT( stack, CoreWindowStack );
+ D_ASSERT( stack->cursor.surface == NULL );
+
+ context = stack->context;
+
+ D_ASSERT( context != NULL );
+
+ layer = dfb_layer_at( context->layer_id );
+
+ D_ASSERT( layer != NULL );
+
+ stack->cursor.x = stack->width / 2;
+ stack->cursor.y = stack->height / 2;
+ stack->cursor.hot.x = 0;
+ stack->cursor.hot.y = 0;
+ stack->cursor.size.w = width;
+ stack->cursor.size.h = height;
+
+ if (context->config.buffermode == DLBM_WINDOWS)
+ D_WARN( "cursor not yet visible with DLBM_WINDOWS" );
+
+ dfb_surface_caps_apply_policy( stack->cursor.policy, &surface_caps );
+
+ /* Create the cursor surface. */
+ ret = dfb_surface_create_simple( layer->core, width, height, DSPF_ARGB,
+ surface_caps, CSTF_SHARED | CSTF_CURSOR,
+ 0, /* FIXME: no shared cursor objects, no cursor id */
+ NULL, &surface );
+ if (ret) {
+ D_ERROR( "Core/WindowStack: Failed creating a surface for software cursor!\n" );
+ return ret;
+ }
+
+ dfb_surface_globalize( surface );
+
+ stack->cursor.surface = surface;
+
+ return DFB_OK;
+}
+