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/wm.c | 1440 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1440 insertions(+) create mode 100755 Source/DirectFB/src/core/wm.c (limited to 'Source/DirectFB/src/core/wm.c') diff --git a/Source/DirectFB/src/core/wm.c b/Source/DirectFB/src/core/wm.c new file mode 100755 index 0000000..fb9148c --- /dev/null +++ b/Source/DirectFB/src/core/wm.c @@ -0,0 +1,1440 @@ +/* + (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 + +#include +#include + + +DEFINE_MODULE_DIRECTORY( dfb_core_wm_modules, "wm", DFB_CORE_WM_ABI_VERSION ); + + +D_DEBUG_DOMAIN( Core_WM, "Core/WM", "DirectFB WM Core" ); + +/**********************************************************************************************************************/ + +typedef struct { + int magic; + + DirectLink *stacks; + + int abi; + + char *name; + CoreWMInfo info; + void *data; + + FusionSHMPoolShared *shmpool; + + FusionReactor *reactor; +} DFBWMCoreShared; + +struct __DFB_DFBWMCore { + int magic; + + CoreDFB *core; + + DFBWMCoreShared *shared; + + + DirectModuleEntry *module; + const CoreWMFuncs *funcs; + void *data; +}; + + +DFB_CORE_PART( wm_core, WMCore ); + +/**********************************************************************************************************************/ + +static DFBResult load_module( const char *name ); + +/**********************************************************************************************************************/ + +static DFBWMCore *wm_local = NULL; /* FIXME */ +static DFBWMCoreShared *wm_shared = NULL; /* FIXME */ + + +static DFBResult +dfb_wm_core_initialize( CoreDFB *core, + DFBWMCore *data, + DFBWMCoreShared *shared ) +{ + DFBResult ret; + + D_DEBUG_AT( Core_WM, "dfb_wm_core_initialize( %p, %p, %p )\n", core, data, shared ); + + D_ASSERT( data != NULL ); + D_ASSERT( shared != NULL ); + + data->core = core; + data->shared = shared; + + + wm_local = data; /* FIXME */ + wm_shared = shared; /* FIXME */ + + wm_shared->shmpool = dfb_core_shmpool( core ); + + /* Set ABI version for the session. */ + wm_shared->abi = DFB_CORE_WM_ABI_VERSION; + + /* Load the module. */ + ret = load_module( dfb_config->wm ); + if (ret) + goto error; + + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->GetWMInfo != NULL ); + D_ASSERT( wm_local->funcs->Initialize != NULL ); + + /* Query module information. */ + wm_local->funcs->GetWMInfo( &wm_shared->info ); + + D_INFO( "DirectFB/Core/WM: %s %d.%d (%s)\n", + wm_shared->info.name, wm_shared->info.version.major, + wm_shared->info.version.minor, wm_shared->info.vendor ); + + ret = DFB_NOSHAREDMEMORY; + + /* Store module name in shared memory. */ + wm_shared->name = SHSTRDUP( wm_shared->shmpool, wm_local->module->name ); + if (!wm_shared->name) { + D_OOSHM(); + goto error; + } + + /* Allocate shared window manager data. */ + if (wm_shared->info.wm_shared_size) { + wm_shared->data = SHCALLOC( wm_shared->shmpool, 1, wm_shared->info.wm_shared_size ); + if (!wm_shared->data) { + D_OOSHM(); + goto error; + } + } + + ret = DFB_NOSYSTEMMEMORY; + + /* Allocate local window manager data. */ + if (wm_shared->info.wm_data_size) { + wm_local->data = D_CALLOC( 1, wm_shared->info.wm_data_size ); + if (!wm_local->data) { + D_OOM(); + goto error; + } + } + + wm_shared->reactor = fusion_reactor_new( 0, "WM", dfb_core_world(core) ); + + /* Initialize window manager. */ + ret = wm_local->funcs->Initialize( core, wm_local->data, wm_shared->data ); + if (ret) { + D_DERROR( ret, "DirectFB/Core/WM: Could not initialize window manager!\n" ); + goto error; + } + + D_MAGIC_SET( data, DFBWMCore ); + D_MAGIC_SET( shared, DFBWMCoreShared ); + + return DFB_OK; + +error: + if (wm_local->data) + D_FREE( wm_local->data ); + + if (wm_shared->data) + SHFREE( wm_shared->shmpool, wm_shared->data ); + + if (wm_shared->name) + SHFREE( wm_shared->shmpool, wm_shared->name ); + + wm_local = NULL; + wm_shared = NULL; + + return ret; +} + +static DFBResult +dfb_wm_core_join( CoreDFB *core, + DFBWMCore *data, + DFBWMCoreShared *shared ) +{ + DFBResult ret; + CoreWMInfo info; + + D_DEBUG_AT( Core_WM, "dfb_wm_core_join( %p, %p, %p )\n", core, data, shared ); + + D_ASSERT( data != NULL ); + D_MAGIC_ASSERT( shared, DFBWMCoreShared ); + + data->core = core; + data->shared = shared; + + + wm_local = data; /* FIXME */ + wm_shared = shared; /* FIXME */ + + /* Check binary version numbers. */ + if (wm_shared->abi != DFB_CORE_WM_ABI_VERSION) { + D_ERROR( "DirectFB/Core/WM: ABI version of running core instance (%d) doesn't match %d!\n", + wm_shared->abi, DFB_CORE_WM_ABI_VERSION ); + ret = DFB_VERSIONMISMATCH; + goto error; + } + + /* Load the module that is used by the running session. */ + ret = load_module( wm_shared->name ); + if (ret) + goto error; + + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->GetWMInfo != NULL ); + D_ASSERT( wm_local->funcs->Join != NULL ); + + /* Query module information. */ + wm_local->funcs->GetWMInfo( &info ); + + /* Check binary version numbers. */ + if (info.version.binary != wm_shared->info.version.binary) { + D_ERROR( "DirectFB/Core/WM: ABI version of running module instance (%d) doesn't match %d!\n", + wm_shared->info.version.binary, info.version.binary ); + ret = DFB_VERSIONMISMATCH; + goto error; + } + + /* Allocate window manager data. */ + if (wm_shared->info.wm_data_size) { + wm_local->data = D_CALLOC( 1, wm_shared->info.wm_data_size ); + if (!wm_local->data) { + D_WARN( "out of memory" ); + ret = DFB_NOSYSTEMMEMORY; + goto error; + } + } + + /* Join window manager. */ + ret = wm_local->funcs->Join( core, wm_local->data, wm_shared->data ); + if (ret) { + D_DERROR( ret, "DirectFB/Core/WM: Could not join window manager!\n" ); + goto error; + } + + D_MAGIC_SET( data, DFBWMCore ); + + return DFB_OK; + +error: + if (wm_local->data) + D_FREE( wm_local->data ); + + wm_local = NULL; + wm_shared = NULL; + + return ret; +} + +static DFBResult +dfb_wm_core_shutdown( DFBWMCore *data, + bool emergency ) +{ + DFBResult ret; + DFBWMCoreShared *shared; + + D_DEBUG_AT( Core_WM, "dfb_wm_core_shutdown( %p, %semergency )\n", data, emergency ? "" : "no " ); + + D_MAGIC_ASSERT( data, DFBWMCore ); + D_MAGIC_ASSERT( data->shared, DFBWMCoreShared ); + + shared = data->shared; + + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->Shutdown != NULL ); + D_ASSERT( wm_shared != NULL ); + + fusion_reactor_destroy( wm_shared->reactor ); + + /* Shutdown window manager. */ + ret = wm_local->funcs->Shutdown( emergency, wm_local->data, wm_shared->data ); + + /* Unload the module. */ + direct_module_unref( wm_local->module ); + + /* Deallocate local window manager data. */ + if (wm_local->data) + D_FREE( wm_local->data ); + + /* Deallocate shared window manager data. */ + if (wm_shared->data) + SHFREE( wm_shared->shmpool, wm_shared->data ); + + /* Free module name in shared memory. */ + SHFREE( wm_shared->shmpool, wm_shared->name ); + + wm_local = NULL; + wm_shared = NULL; + + + D_MAGIC_CLEAR( data ); + D_MAGIC_CLEAR( shared ); + + return ret; +} + +static DFBResult +dfb_wm_core_leave( DFBWMCore *data, + bool emergency ) +{ + DFBResult ret; + DFBWMCoreShared *shared; + + D_DEBUG_AT( Core_WM, "dfb_wm_core_leave( %p, %semergency )\n", data, emergency ? "" : "no " ); + + D_MAGIC_ASSERT( data, DFBWMCore ); + D_MAGIC_ASSERT( data->shared, DFBWMCoreShared ); + + shared = data->shared; + + + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->Leave != NULL ); + D_ASSERT( wm_shared != NULL ); + + /* Leave window manager. */ + ret = wm_local->funcs->Leave( emergency, wm_local->data, wm_shared->data ); + + /* Unload the module. */ + direct_module_unref( wm_local->module ); + + /* Deallocate local window manager data. */ + if (wm_local->data) + D_FREE( wm_local->data ); + + wm_local = NULL; + wm_shared = NULL; + + + D_MAGIC_CLEAR( data ); + + return ret; +} + +static DFBResult +dfb_wm_core_suspend( DFBWMCore *data ) +{ + DFBWMCoreShared *shared; + + D_DEBUG_AT( Core_WM, "%s( %p )\n", __FUNCTION__, data ); + + D_MAGIC_ASSERT( data, DFBWMCore ); + D_MAGIC_ASSERT( data->shared, DFBWMCoreShared ); + + shared = data->shared; + + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->Suspend != NULL ); + D_ASSERT( wm_shared != NULL ); + + return wm_local->funcs->Suspend( wm_local->data, wm_shared->data ); +} + +static DFBResult +dfb_wm_core_resume( DFBWMCore *data ) +{ + DFBWMCoreShared *shared; + + D_DEBUG_AT( Core_WM, "%s( %p )\n", __FUNCTION__, data ); + + D_MAGIC_ASSERT( data, DFBWMCore ); + D_MAGIC_ASSERT( data->shared, DFBWMCoreShared ); + + shared = data->shared; + + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->Resume != NULL ); + D_ASSERT( wm_shared != NULL ); + + return wm_local->funcs->Resume( wm_local->data, wm_shared->data ); +} + +DFBResult +dfb_wm_close_all_stacks( void *data ) +{ + CoreLayerContext *context; + CoreWindowStack *stack, *next; + DFBWMCore *local; + DFBWMCoreShared *shared; + + D_DEBUG_AT( Core_WM, "%s( %p )\n", __FUNCTION__, data ); + + local = data; + + D_MAGIC_ASSERT( local, DFBWMCore ); + D_ASSERT( local->funcs != NULL ); + D_ASSERT( local->funcs->CloseStack != NULL ); + + shared = local->shared; + + D_MAGIC_ASSERT( shared, DFBWMCoreShared ); + + D_DEBUG_AT( Core_WM, " -> checking %d stacks...\n", direct_list_count_elements_EXPENSIVE(shared->stacks) ); + + direct_list_foreach_safe (stack, next, shared->stacks) { + D_DEBUG_AT( Core_WM, " -> checking %p...\n", stack ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + + context = stack->context; + D_MAGIC_ASSERT( context, CoreLayerContext ); + + D_DEBUG_AT( Core_WM, " -> ref context %p...\n", context ); + + dfb_layer_context_ref( context ); + + dfb_layer_context_lock( context ); + + if (stack->flags & CWSF_INITIALIZED) { + D_DEBUG_AT( Core_WM, " => CLOSING %p\n", stack ); + dfb_wm_close_stack( stack ); + } + + dfb_layer_context_unlock( context ); + + D_DEBUG_AT( Core_WM, " -> unref context %p...\n", context ); + + dfb_layer_context_unref( context ); + } + + return DFB_OK; +} + +/**************************************************************************************************/ + +static DFBResult +load_module( const char *name ) +{ + DirectLink *l; + + D_ASSERT( wm_local != NULL ); + + direct_modules_explore_directory( &dfb_core_wm_modules ); + + direct_list_foreach( l, dfb_core_wm_modules.entries ) { + DirectModuleEntry *module = (DirectModuleEntry*) l; + const CoreWMFuncs *funcs; + + funcs = direct_module_ref( module ); + if (!funcs) + continue; + + if (!name || !strcasecmp( name, module->name )) { + if (wm_local->module) + direct_module_unref( wm_local->module ); + + wm_local->module = module; + wm_local->funcs = funcs; + } + else + direct_module_unref( module ); + } + + if (!wm_local->module) { + if (name) + D_ERROR( "DirectFB/WM: Window manager module '%s' not found!\n", name ); + else + D_ERROR( "DirectFB/WM: No window manager module found!\n" ); + + return DFB_NOIMPL; + } + + return DFB_OK; +} + +/**************************************************************************************************/ + +static void +convert_config( DFBWindowConfig *config, + const CoreWindowConfig *from ) +{ + config->bounds = from->bounds; + config->opacity = from->opacity; + config->stacking = from->stacking; + config->options = from->options; + config->events = from->events; + config->color = from->color; + config->color_key = from->color_key; + config->opaque = from->opaque; +// config->key_selection = DWKS_ALL; // FIXME: implement +// config->keys = NULL; // FIXME: implement +// config->num_keys = 0; // FIXME: implement + config->association = from->association; + config->src_geometry = from->src_geometry; + config->dst_geometry = from->dst_geometry; + config->cursor_flags = from->cursor_flags; + config->cursor_resolution = from->cursor_resolution; +} + +static void +convert_state( DFBWindowState *state, + const CoreWindowFlags flags ) +{ + state->flags = DWSTATE_NONE; + + if (flags & CWF_INSERTED) + state->flags |= DWSTATE_INSERTED; + + if (flags & CWF_FOCUSED) + state->flags |= DWSTATE_FOCUSED; + + if (flags & CWF_ENTERED) + state->flags |= DWSTATE_ENTERED; +} + +/**************************************************************************************************/ + +typedef struct { + ReactionFunc func; + void *ctx; +} AttachContext; + +static DFBEnumerationResult +wm_window_attach_callback( CoreWindow *window, + void *ctx ) +{ + AttachContext *context = ctx; + + CoreWM_WindowAdd add; + + add.info.window_id = window->id; + add.info.caps = window->caps; + add.info.resource_id = window->resource_id; + + convert_config( &add.info.config, &window->config ); + + convert_state( &add.info.state, window->flags ); + + context->func( &add, context->ctx ); + + return DFENUM_OK; +} + +DFBResult +dfb_wm_attach( CoreDFB *core, + int channel, + ReactionFunc func, + void *ctx, + Reaction *reaction ) +{ + D_ASSERT( wm_shared != NULL ); + + if (channel == CORE_WM_WINDOW_ADD) { + CoreWindowStack *stack = (CoreWindowStack *) wm_shared->stacks; + + if (stack) { + DFBResult ret; + AttachContext context = { func, ctx }; + + dfb_windowstack_lock( stack ); + + ret = dfb_wm_enum_windows( stack, wm_window_attach_callback, &context ); + if (ret) + D_WARN( "could not enumerate windows" ); + + ret = fusion_reactor_attach_channel( wm_shared->reactor, channel, func, ctx, reaction ); + + dfb_windowstack_unlock( stack ); + + return ret; + } + } + + return fusion_reactor_attach_channel( wm_shared->reactor, channel, func, ctx, reaction ); +} + +DFBResult +dfb_wm_detach( CoreDFB *core, + Reaction *reaction ) +{ + D_ASSERT( wm_shared != NULL ); + + return fusion_reactor_detach( wm_shared->reactor, reaction ); +} + +DFBResult +dfb_wm_dispatch( CoreDFB *core, + int channel, + const void *data, + int size ) +{ + D_ASSERT( wm_shared != NULL ); + + return fusion_reactor_dispatch_channel( wm_shared->reactor, channel, data, size, true, NULL ); +} + +DFBResult +dfb_wm_dispatch_WindowAdd( CoreDFB *core, + CoreWindow *window ) +{ + CoreWM_WindowAdd add; + + add.info.window_id = window->id; + add.info.caps = window->caps; + add.info.resource_id = window->resource_id; + + convert_config( &add.info.config, &window->config ); + + convert_state( &add.info.state, window->flags ); + + return dfb_wm_dispatch( core, CORE_WM_WINDOW_ADD, &add, sizeof(add) ); +} + +DFBResult +dfb_wm_dispatch_WindowRemove( CoreDFB *core, + CoreWindow *window ) +{ + CoreWM_WindowRemove remove; + + remove.window_id = window->id; + + return dfb_wm_dispatch( core, CORE_WM_WINDOW_REMOVE, &remove, sizeof(remove) ); +} + +DFBResult +dfb_wm_dispatch_WindowConfig( CoreDFB *core, + CoreWindow *window, + DFBWindowConfigFlags flags ) +{ + CoreWM_WindowConfig config; + + config.window_id = window->id; + config.flags = flags; + + convert_config( &config.config, &window->config ); + + return dfb_wm_dispatch( core, CORE_WM_WINDOW_CONFIG, &config, sizeof(config) ); +} + +DFBResult +dfb_wm_dispatch_WindowState( CoreDFB *core, + CoreWindow *window ) +{ + CoreWM_WindowState state; + + state.window_id = window->id; + + convert_state( &state.state, window->flags ); + + return dfb_wm_dispatch( core, CORE_WM_WINDOW_STATE, &state, sizeof(state) ); +} + +DFBResult +dfb_wm_dispatch_WindowRestack( CoreDFB *core, + CoreWindow *window, + unsigned int index ) +{ + CoreWM_WindowRestack restack; + + restack.window_id = window->id; + restack.index = index; + + return dfb_wm_dispatch( core, CORE_WM_WINDOW_RESTACK, &restack, sizeof(restack) ); +} + +DFBResult +dfb_wm_dispatch_WindowFocus( CoreDFB *core, + CoreWindow *window ) +{ + CoreWM_WindowFocus focus; + + focus.window_id = window->id; + + return dfb_wm_dispatch( core, CORE_WM_WINDOW_FOCUS, &focus, sizeof(focus) ); +} + +/**************************************************************************************************/ + +void +dfb_wm_get_info( CoreWMInfo *info ) +{ + D_ASSERT( wm_shared != NULL ); + + D_ASSERT( info != NULL ); + + *info = wm_shared->info; +} + +DFBResult +dfb_wm_post_init( CoreDFB *core ) +{ + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->Resume != NULL ); + D_ASSERT( wm_shared != NULL ); + + return wm_local->funcs->PostInit( wm_local->data, wm_shared->data ); +} + +/**************************************************************************************************/ + +DFBResult +dfb_wm_init_stack( CoreWindowStack *stack ) +{ + DFBResult ret; + + D_DEBUG_AT( Core_WM, "%s( %p )\n", __FUNCTION__, stack ); + + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->InitStack != NULL ); + D_ASSERT( wm_shared != NULL ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + D_ASSERT( !(stack->flags & CWSF_INITIALIZED) ); + + D_MAGIC_ASSERT( stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &stack->context->lock ); + + /* Allocate shared stack data. */ + if (wm_shared->info.stack_data_size) { + if (stack->stack_data) + SHFREE( stack->shmpool, stack->stack_data ); + + stack->stack_data = SHCALLOC( stack->shmpool, 1, wm_shared->info.stack_data_size ); + if (!stack->stack_data) { + D_WARN( "out of (shared) memory" ); + return D_OOSHM(); + } + } + + /* Window manager specific initialization. */ + ret = wm_local->funcs->InitStack( stack, wm_local->data, stack->stack_data ); + if (ret) { + if (stack->stack_data) { + SHFREE( wm_shared->shmpool, stack->stack_data ); + stack->stack_data = NULL; + } + + return ret; + } + + stack->flags |= CWSF_INITIALIZED; + + /* Add window stack to list. */ + direct_list_append( &wm_shared->stacks, &stack->link ); + + return DFB_OK; +} + +DFBResult +dfb_wm_close_stack( CoreWindowStack *stack ) +{ + D_DEBUG_AT( Core_WM, "%s( %p )\n", __FUNCTION__, stack ); + + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->CloseStack != NULL ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + + D_ASSUME( stack->flags & CWSF_INITIALIZED ); + + if (!(stack->flags & CWSF_INITIALIZED)) { + D_ASSUME( !(stack->flags & CWSF_ACTIVATED) ); + return DFB_OK; + } + + D_MAGIC_ASSERT( stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &stack->context->lock ); + + /* Deactivate before deinitialization. */ + if (stack->flags & CWSF_ACTIVATED) + dfb_wm_set_active( stack, false ); + + /* + * Clear flag and remove stack first, because + * CloseStack() may cause the stack to be destroyed! + */ + stack->flags &= ~CWSF_INITIALIZED; + + /* Remove window stack from list. */ + direct_list_remove( &wm_shared->stacks, &stack->link ); + + /* Window manager specific deinitialization. */ + return wm_local->funcs->CloseStack( stack, wm_local->data, stack->stack_data ); +} + +DFBResult +dfb_wm_set_active( CoreWindowStack *stack, + bool active ) +{ + DFBResult ret; + + D_DEBUG_AT( Core_WM, "%s( %p, %sactive )\n", __FUNCTION__, stack, active ? "" : "in" ); + + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->SetActive != NULL ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + D_ASSERT( stack->flags & CWSF_INITIALIZED ); + + D_MAGIC_ASSERT( stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &stack->context->lock ); + + if (active) { + D_ASSUME( !(stack->flags & CWSF_ACTIVATED) ); + + if (stack->flags & CWSF_ACTIVATED) + return DFB_OK; + + ret = wm_local->funcs->SetActive( stack, wm_local->data, stack->stack_data, true ); + + stack->flags |= CWSF_ACTIVATED; + } + else { + D_ASSUME( stack->flags & CWSF_ACTIVATED ); + + if (!(stack->flags & CWSF_ACTIVATED)) + return DFB_OK; + + ret = wm_local->funcs->SetActive( stack, wm_local->data, stack->stack_data, false ); + + stack->flags &= ~CWSF_ACTIVATED; + } + + return ret; +} + +DFBResult +dfb_wm_resize_stack( CoreWindowStack *stack, + int width, + int height ) +{ + D_DEBUG_AT( Core_WM, "%s( %p, %dx%d )\n", __FUNCTION__, stack, width, height ); + + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->ResizeStack != NULL ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + D_ASSERT( stack->flags & CWSF_INITIALIZED ); + + D_MAGIC_ASSERT( stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &stack->context->lock ); + + /* Notify window manager about the new size. */ + return wm_local->funcs->ResizeStack( stack, wm_local->data, stack->stack_data, width, height ); +} + +DFBResult +dfb_wm_process_input( CoreWindowStack *stack, + const DFBInputEvent *event ) +{ + D_DEBUG_AT( Core_WM, "%s( %p, %p )\n", __FUNCTION__, stack, event ); + + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->ProcessInput != NULL ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + D_ASSERT( stack->flags & CWSF_INITIALIZED ); + + D_MAGIC_ASSERT( stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &stack->context->lock ); + + D_ASSERT( event != NULL ); + + /* Dispatch input event via window manager. */ + return wm_local->funcs->ProcessInput( stack, wm_local->data, stack->stack_data, event ); +} + +DFBResult +dfb_wm_flush_keys( CoreWindowStack *stack ) +{ + D_DEBUG_AT( Core_WM, "%s( %p )\n", __FUNCTION__, stack ); + + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->FlushKeys != NULL ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + D_ASSERT( stack->flags & CWSF_INITIALIZED ); + + D_MAGIC_ASSERT( stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &stack->context->lock ); + + return wm_local->funcs->FlushKeys( stack, wm_local->data, stack->stack_data ); +} + +DFBResult +dfb_wm_window_at( CoreWindowStack *stack, + int x, + int y, + CoreWindow **ret_window ) +{ + D_DEBUG_AT( Core_WM, "%s( %p, %d,%d )\n", __FUNCTION__, stack, x, y ); + + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->WindowAt != NULL ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + D_ASSERT( stack->flags & CWSF_INITIALIZED ); + + D_MAGIC_ASSERT( stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &stack->context->lock ); + + D_ASSERT( ret_window != NULL ); + + return wm_local->funcs->WindowAt( stack, wm_local->data, stack->stack_data, x, y, ret_window ); +} + +DFBResult +dfb_wm_window_lookup( CoreWindowStack *stack, + DFBWindowID window_id, + CoreWindow **ret_window ) +{ + D_DEBUG_AT( Core_WM, "%s( %p, %u )\n", __FUNCTION__, stack, window_id ); + + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->WindowLookup != NULL ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + D_ASSERT( stack->flags & CWSF_INITIALIZED ); + + D_MAGIC_ASSERT( stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &stack->context->lock ); + + D_ASSERT( ret_window != NULL ); + + return wm_local->funcs->WindowLookup( stack, wm_local->data, + stack->stack_data, window_id, ret_window ); +} + +DFBResult +dfb_wm_enum_windows( CoreWindowStack *stack, + CoreWMWindowCallback callback, + void *callback_ctx ) +{ + D_DEBUG_AT( Core_WM, "%s( %p, %p, %p )\n", __FUNCTION__, stack, callback, callback_ctx ); + + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->EnumWindows != NULL ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + D_ASSERT( stack->flags & CWSF_INITIALIZED ); + + D_MAGIC_ASSERT( stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &stack->context->lock ); + + D_ASSERT( callback != NULL ); + + return wm_local->funcs->EnumWindows( stack, wm_local->data, + stack->stack_data, callback, callback_ctx ); +} + +/** + * Give the wm a chance to specifiy a border + */ +DFBResult +dfb_wm_get_insets( CoreWindowStack *stack, + CoreWindow *window, + DFBInsets *insets) +{ + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->GetInsets != NULL ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + D_ASSERT( stack->flags & CWSF_INITIALIZED ); + + D_MAGIC_ASSERT( stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &stack->context->lock ); + + D_ASSERT( window != NULL ); + D_ASSERT( insets != NULL ); + + return wm_local->funcs->GetInsets( stack, window, insets ); +} + +/** + * Give the wm a chance to override the windows configuration + */ +DFBResult +dfb_wm_preconfigure_window( CoreWindowStack *stack, + CoreWindow *window ) +{ + DFBResult ret; + void *window_data = NULL; + + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_shared != NULL ); + D_MAGIC_ASSERT( stack, CoreWindowStack ); + D_ASSERT( stack->flags & CWSF_INITIALIZED ); + D_ASSERT( window != NULL ); + D_ASSERT( wm_local->funcs->PreConfigureWindow != NULL ); + + D_MAGIC_ASSERT( stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &stack->context->lock ); + + D_DEBUG_AT( Core_WM, "%s( %p, %p [%d,%d-%dx%d] )\n", __FUNCTION__, + stack, window, DFB_RECTANGLE_VALS(&window->config.bounds) ); + + /* Allocate shared window data. */ + if (wm_shared->info.window_data_size) { + window_data = SHCALLOC( wm_shared->shmpool, 1, wm_shared->info.window_data_size ); + if (!window_data) { + D_WARN( "out of (shared) memory" ); + return D_OOSHM(); + } + } + + /* Keep shared window data. */ + window->window_data = window_data; + + /* Tell window manager about the new window. */ + ret = wm_local->funcs->PreConfigureWindow( stack, wm_local->data, + stack->stack_data, window, window_data ); + if (ret) { + if (window_data) { + SHFREE( wm_shared->shmpool, window_data ); + window->window_data = NULL; + } + + return ret; + } + + return DFB_OK; +} + +DFBResult +dfb_wm_add_window( CoreWindowStack *stack, + CoreWindow *window ) +{ + DFBResult ret; + + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->AddWindow != NULL ); + D_ASSERT( wm_shared != NULL ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + D_ASSERT( stack->flags & CWSF_INITIALIZED ); + + D_MAGIC_ASSERT( stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &stack->context->lock ); + + D_ASSERT( window != NULL ); + + D_DEBUG_AT( Core_WM, "%s( %p, %p [%d,%d-%dx%d] )\n", __FUNCTION__, + stack, window, DFB_RECTANGLE_VALS(&window->config.bounds) ); + + /* Tell window manager about the new window. */ + ret = wm_local->funcs->AddWindow( stack, wm_local->data, + stack->stack_data, window, window->window_data ); + if (ret) { + if (window->window_data) + SHFREE( wm_shared->shmpool, window->window_data ); + return ret; + } + return DFB_OK; +} + +DFBResult +dfb_wm_remove_window( CoreWindowStack *stack, + CoreWindow *window ) +{ + DFBResult ret; + + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->RemoveWindow != NULL ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + D_ASSERT( stack->flags & CWSF_INITIALIZED ); + + D_MAGIC_ASSERT( stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &stack->context->lock ); + + D_ASSERT( window != NULL ); + + D_DEBUG_AT( Core_WM, "%s( %p, %p [%d,%d-%dx%d] )\n", __FUNCTION__, + stack, window, DFB_RECTANGLE_VALS(&window->config.bounds) ); + + /* Remove window from window manager. */ + ret = wm_local->funcs->RemoveWindow( stack, wm_local->data, + stack->stack_data, window, window->window_data ); + + /* Deallocate shared stack data. */ + if (window->window_data) + SHFREE( wm_shared->shmpool, window->window_data ); + + return ret; +} + +/** + * Let the wm set a property on a window + */ +DFBResult +dfb_wm_set_window_property( CoreWindowStack *stack, + CoreWindow *window, + const char *key, + void *value, + void **ret_old_value ) +{ + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->SetWindowProperty != NULL ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + D_ASSERT( stack->flags & CWSF_INITIALIZED ); + + D_MAGIC_ASSERT( stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &stack->context->lock ); + + D_ASSERT( window != NULL ); + D_ASSERT( key != NULL ); + + D_DEBUG_AT( Core_WM, "%s( %p, %p [%d,%d-%dx%d], '%s' = %p )\n", __FUNCTION__, + stack, window, DFB_RECTANGLE_VALS(&window->config.bounds), key, value ); + + return wm_local->funcs->SetWindowProperty( stack, wm_local->data, stack->stack_data, + window, window->window_data, + key, value, ret_old_value ); +} + +/** + * get the wm property on a window + */ +DFBResult +dfb_wm_get_window_property( CoreWindowStack *stack, + CoreWindow *window, + const char *key, + void **ret_value ) +{ + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->GetWindowProperty != NULL ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + D_ASSERT( stack->flags & CWSF_INITIALIZED ); + + D_MAGIC_ASSERT( stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &stack->context->lock ); + + D_ASSERT( window != NULL ); + D_ASSERT( key != NULL ); + + D_DEBUG_AT( Core_WM, "%s( %p, %p [%d,%d-%dx%d], '%s' )\n", __FUNCTION__, + stack, window, DFB_RECTANGLE_VALS(&window->config.bounds), key ); + + return wm_local->funcs->GetWindowProperty( stack, wm_local->data, stack->stack_data, + window, window->window_data, key, ret_value ); +} + +/** + * remove th wm property on a window + */ +DFBResult +dfb_wm_remove_window_property( CoreWindowStack *stack, + CoreWindow *window, + const char *key, + void **ret_value ) +{ + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->RemoveWindowProperty != NULL ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + D_ASSERT( stack->flags & CWSF_INITIALIZED ); + + D_MAGIC_ASSERT( stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &stack->context->lock ); + + D_ASSERT( window != NULL ); + D_ASSERT( key != NULL ); + + D_DEBUG_AT( Core_WM, "%s( %p, %p [%d,%d-%dx%d], '%s' )\n", __FUNCTION__, + stack, window, DFB_RECTANGLE_VALS(&window->config.bounds), key ); + + return wm_local->funcs->RemoveWindowProperty( stack, wm_local->data, stack->stack_data, + window, window->window_data, key, ret_value ); +} + +DFBResult +dfb_wm_set_window_config( CoreWindow *window, + const CoreWindowConfig *config, + CoreWindowConfigFlags flags ) +{ + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->SetWindowConfig != NULL ); + + D_ASSERT( window != NULL ); + D_ASSERT( config != NULL ); + + D_MAGIC_ASSERT( window->stack, CoreWindowStack ); + D_MAGIC_ASSERT( window->stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &window->stack->context->lock ); + + D_DEBUG_AT( Core_WM, "%s( %p [%d,%d-%dx%d], %p, 0x%x )\n", __FUNCTION__, + window, DFB_RECTANGLE_VALS(&window->config.bounds), config, flags ); + + return wm_local->funcs->SetWindowConfig( window, wm_local->data, + window->window_data, config, flags ); +} + +DFBResult +dfb_wm_restack_window( CoreWindow *window, + CoreWindow *relative, + int relation ) +{ + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->RestackWindow != NULL ); + + D_ASSERT( window != NULL ); + + D_MAGIC_ASSERT( window->stack, CoreWindowStack ); + D_MAGIC_ASSERT( window->stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &window->stack->context->lock ); + + D_ASSERT( relative == NULL || relative == window || relation != 0); + + D_DEBUG_AT( Core_WM, "%s( %p [%d,%d-%dx%d], %p, %d )\n", __FUNCTION__, + window, DFB_RECTANGLE_VALS(&window->config.bounds), relative, relation ); + + return wm_local->funcs->RestackWindow( window, wm_local->data, window->window_data, relative, + relative ? relative->window_data : NULL, relation ); +} + +DFBResult +dfb_wm_grab( CoreWindow *window, + CoreWMGrab *grab ) +{ + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->Grab != NULL ); + + D_ASSERT( window != NULL ); + + D_MAGIC_ASSERT( window->stack, CoreWindowStack ); + D_MAGIC_ASSERT( window->stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &window->stack->context->lock ); + + D_ASSERT( grab != NULL ); + + D_DEBUG_AT( Core_WM, "%s( %p [%d,%d-%dx%d], %d )\n", __FUNCTION__, + window, DFB_RECTANGLE_VALS(&window->config.bounds), grab->target ); + + return wm_local->funcs->Grab( window, wm_local->data, window->window_data, grab ); +} + +DFBResult +dfb_wm_ungrab( CoreWindow *window, + CoreWMGrab *grab ) +{ + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->Ungrab != NULL ); + + D_ASSERT( window != NULL ); + + D_MAGIC_ASSERT( window->stack, CoreWindowStack ); + D_MAGIC_ASSERT( window->stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &window->stack->context->lock ); + + D_ASSERT( grab != NULL ); + + D_DEBUG_AT( Core_WM, "%s( %p [%d,%d-%dx%d], %d )\n", __FUNCTION__, + window, DFB_RECTANGLE_VALS(&window->config.bounds), grab->target ); + + return wm_local->funcs->Ungrab( window, wm_local->data, window->window_data, grab ); +} + +DFBResult +dfb_wm_request_focus( CoreWindow *window ) +{ + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->RequestFocus != NULL ); + + D_ASSERT( window != NULL ); + + D_MAGIC_ASSERT( window->stack, CoreWindowStack ); + D_MAGIC_ASSERT( window->stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &window->stack->context->lock ); + + D_DEBUG_AT( Core_WM, "%s( %p [%d,%d-%dx%d] )\n", __FUNCTION__, + window, DFB_RECTANGLE_VALS(&window->config.bounds) ); + + return wm_local->funcs->RequestFocus( window, wm_local->data, window->window_data ); +} + +DFBResult +dfb_wm_begin_updates( CoreWindow *window, + const DFBRegion *update ) +{ + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->RequestFocus != NULL ); + + D_ASSERT( window != NULL ); + + D_MAGIC_ASSERT( window->stack, CoreWindowStack ); + D_MAGIC_ASSERT( window->stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &window->stack->context->lock ); + + D_DEBUG_AT( Core_WM, "%s( %p [%d,%d-%dx%d] )\n", __FUNCTION__, + window, DFB_RECTANGLE_VALS(&window->config.bounds) ); + + return wm_local->funcs->BeginUpdates( window, wm_local->data, window->window_data, update ); +} + +DFBResult +dfb_wm_set_cursor_position( CoreWindow *window, + int x, + int y ) +{ + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->SetCursorPosition != NULL ); + + D_ASSERT( window != NULL ); + + D_MAGIC_ASSERT( window->stack, CoreWindowStack ); + D_MAGIC_ASSERT( window->stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &window->stack->context->lock ); + + D_DEBUG_AT( Core_WM, "%s( %p [%d,%d] )\n", __FUNCTION__, window, x, y ); + + return wm_local->funcs->SetCursorPosition( window, wm_local->data, window->window_data, x, y ); +} + +DFBResult +dfb_wm_update_stack( CoreWindowStack *stack, + const DFBRegion *region, + DFBSurfaceFlipFlags flags ) +{ + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->UpdateStack != NULL ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + D_ASSERT( stack->flags & CWSF_INITIALIZED ); + + D_MAGIC_ASSERT( stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &stack->context->lock ); + + DFB_REGION_ASSERT( region ); + + D_DEBUG_AT( Core_WM, "%s( %p, [%d,%d-%dx%d], 0x%x )\n", __FUNCTION__, + stack, DFB_RECTANGLE_VALS_FROM_REGION(region), flags ); + + return wm_local->funcs->UpdateStack( stack, wm_local->data, + stack->stack_data, region, flags ); +} + +DFBResult +dfb_wm_update_window( CoreWindow *window, + const DFBRegion *region, + DFBSurfaceFlipFlags flags ) +{ + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->UpdateWindow != NULL ); + + D_ASSERT( window != NULL ); + + D_MAGIC_ASSERT( window->stack, CoreWindowStack ); + D_MAGIC_ASSERT( window->stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &window->stack->context->lock ); + + DFB_REGION_ASSERT_IF( region ); + + D_DEBUG_AT( Core_WM, "%s( %p [%d,%d-%dx%d], [%d,%d-%dx%d], 0x%x )\n", __FUNCTION__, + window, DFB_RECTANGLE_VALS(&window->config.bounds), + DFB_RECTANGLE_VALS_FROM_REGION(region), flags ); + + return wm_local->funcs->UpdateWindow( window, wm_local->data, + window->window_data, region, flags ); +} + +DFBResult +dfb_wm_update_cursor( CoreWindowStack *stack, + CoreCursorUpdateFlags flags ) +{ + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->UpdateStack != NULL ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + D_ASSERT( stack->flags & CWSF_INITIALIZED ); + + D_MAGIC_ASSERT( stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &stack->context->lock ); + + D_FLAGS_ASSERT( flags, CCUF_ALL ); + + if (dfb_config->no_cursor_updates) + return DFB_OK; + + return wm_local->funcs->UpdateCursor( stack, wm_local->data, + stack->stack_data, flags ); +} + -- cgit