From 7fe60435bce6595a9c58a9bfd8244d74b5320e96 Mon Sep 17 00:00:00 2001 From: Benjamin Franzke Date: Tue, 15 Jan 2013 08:46:13 +0100 Subject: Import DirectFB141_2k11R3_beta5 --- Source/DirectFB/src/core/windowstack.c | 998 +++++++++++++++++++++++++++++++++ 1 file changed, 998 insertions(+) create mode 100755 Source/DirectFB/src/core/windowstack.c (limited to 'Source/DirectFB/src/core/windowstack.c') 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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 + +#include + +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + + +#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, ®ion, 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; +} + -- cgit