diff options
Diffstat (limited to 'Source/SaWMan/src/isawmanmanager.c')
-rwxr-xr-x | Source/SaWMan/src/isawmanmanager.c | 718 |
1 files changed, 718 insertions, 0 deletions
diff --git a/Source/SaWMan/src/isawmanmanager.c b/Source/SaWMan/src/isawmanmanager.c new file mode 100755 index 0000000..29779d1 --- /dev/null +++ b/Source/SaWMan/src/isawmanmanager.c @@ -0,0 +1,718 @@ +/* + (c) Copyright 2006-2007 directfb.org + + All rights reserved. + + Written by Denis Oliver Kropp <dok@directfb.org>. + + 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 <directfb_util.h> + +#include <direct/interface.h> +#include <direct/messages.h> + +#include <fusion/fusion.h> +#include <fusion/shmalloc.h> + +#include <core/wm.h> + +#include <sawman.h> +#include <sawman_internal.h> + +#include "isawmanmanager.h" + + + +D_DEBUG_DOMAIN( SaWMan_Manager, "SaWMan/Manager", "SaWMan Manager Interface" ); + + +static void +ISaWManManager_Destruct( ISaWManManager *thiz ) +{ + ISaWManManager_data *data = thiz->priv; + + (void) data; + + DIRECT_DEALLOCATE_INTERFACE( thiz ); +} + + +static DirectResult +ISaWManManager_AddRef( ISaWManManager *thiz ) +{ + DIRECT_INTERFACE_GET_DATA( ISaWManManager ) + + data->ref++; + + return DFB_OK; +} + +static DirectResult +ISaWManManager_Release( ISaWManManager *thiz ) +{ + DIRECT_INTERFACE_GET_DATA( ISaWManManager ) + + if (--data->ref == 0) + ISaWManManager_Destruct( thiz ); + + return DFB_OK; +} + +static DirectResult +ISaWManManager_QueueUpdate( ISaWManManager *thiz, + DFBWindowStackingClass stacking, + const DFBRegion *region ) +{ + SaWMan *sawman; + SaWManTier *tier; + DFBRegion update; + + DIRECT_INTERFACE_GET_DATA( ISaWManManager ) + + if (!DFB_REGION_CHECK_IF( region )) + return DFB_INVAREA; + + switch (stacking) { + case DWSC_LOWER: + case DWSC_MIDDLE: + case DWSC_UPPER: + break; + + default: + return DFB_INVARG; + } + + sawman = data->sawman; + D_MAGIC_ASSERT( sawman, SaWMan ); + + FUSION_SKIRMISH_ASSERT( &sawman->lock ); + + tier = sawman_tier_by_class( sawman, stacking ); + + update = DFB_REGION_INIT_FROM_DIMENSION( &tier->size ); + + if (region && !dfb_region_region_intersect( &update, region )) + return DFB_OK; + + dfb_updates_add( &tier->updates, &update ); + + return DFB_OK; +} + +static DirectResult +ISaWManManager_ProcessUpdates( ISaWManManager *thiz, + DFBSurfaceFlipFlags flags ) +{ + SaWMan *sawman; + + DIRECT_INTERFACE_GET_DATA( ISaWManManager ) + + sawman = data->sawman; + D_MAGIC_ASSERT( sawman, SaWMan ); + + FUSION_SKIRMISH_ASSERT( &sawman->lock ); + + return sawman_process_updates( sawman, flags ); +} + +static DirectResult +ISaWManManager_CloseWindow( ISaWManManager *thiz, + SaWManWindowHandle handle ) +{ + SaWMan *sawman; + DFBWindowEvent event; + SaWManWindow *window = (SaWManWindow*)handle; + + DIRECT_INTERFACE_GET_DATA( ISaWManManager ) + + if (!window) + return DFB_INVARG; + + sawman = data->sawman; + + D_MAGIC_ASSERT( sawman, SaWMan ); + D_MAGIC_ASSERT( window, SaWManWindow ); + + event.type = DWET_CLOSE; + + dfb_window_post_event( window->window, &event ); + + return DFB_OK; +} + +static DirectResult +ISaWManManager_SetVisible( ISaWManManager *thiz, + SaWManWindowHandle handle, + DFBBoolean visible ) +{ + SaWMan *sawman; + SaWManWindow *window = (SaWManWindow*)handle; + + DIRECT_INTERFACE_GET_DATA( ISaWManManager ) + + if (!window) + return DFB_INVARG; + + sawman = data->sawman; + + D_MAGIC_ASSERT( sawman, SaWMan ); + D_MAGIC_ASSERT( window, SaWManWindow ); + + FUSION_SKIRMISH_ASSERT( &sawman->lock ); + + D_UNIMPLEMENTED(); + + return DFB_UNIMPLEMENTED;// sawman_set_visible( sawman, window ); +} + +static DirectResult +ISaWManManager_SwitchFocus( ISaWManManager *thiz, + SaWManWindowHandle handle ) +{ + SaWMan *sawman; + SaWManWindow *window = (SaWManWindow*)handle; + + DIRECT_INTERFACE_GET_DATA( ISaWManManager ) + + if (!window) + return DFB_INVARG; + + sawman = data->sawman; + + D_MAGIC_ASSERT( sawman, SaWMan ); + D_MAGIC_ASSERT( window, SaWManWindow ); + + FUSION_SKIRMISH_ASSERT( &sawman->lock ); + + return sawman_switch_focus( sawman, window ); +} + +static DirectResult +ISaWManManager_GetSize( ISaWManManager *thiz, + DFBWindowStackingClass stacking, + DFBDimension *ret_size ) +{ + SaWMan *sawman; + SaWManTier *tier; + + DIRECT_INTERFACE_GET_DATA( ISaWManManager ) + + switch (stacking) { + case DWSC_LOWER: + case DWSC_MIDDLE: + case DWSC_UPPER: + break; + + default: + return DFB_INVARG; + } + + if (!ret_size) + return DFB_INVARG; + + sawman = data->sawman; + D_MAGIC_ASSERT( sawman, SaWMan ); + + FUSION_SKIRMISH_ASSERT( &sawman->lock ); + + tier = sawman_tier_by_class( sawman, stacking ); + + *ret_size = tier->size; + + return DFB_OK; +} + +static DirectResult +ISaWManManager_InsertWindow( ISaWManManager *thiz, + SaWManWindowHandle handle, + SaWManWindowHandle relative, + SaWManWindowRelation relation ) +{ + SaWMan *sawman; + SaWManWindow *window = (SaWManWindow*)handle; + SaWManWindow *sawrel = (SaWManWindow*)relative; + + DIRECT_INTERFACE_GET_DATA( ISaWManManager ) + + if (!window) + return DFB_INVARG; + + sawman = data->sawman; + + D_MAGIC_ASSERT( sawman, SaWMan ); + D_MAGIC_ASSERT( window, SaWManWindow ); + D_MAGIC_ASSERT_IF( sawrel, SaWManWindow ); + + FUSION_SKIRMISH_ASSERT( &sawman->lock ); + + return sawman_insert_window( sawman, window, sawrel, + (relation == SWMWR_TOP) ? DFB_TRUE : DFB_FALSE ); +} + +static DirectResult +ISaWManManager_RemoveWindow( ISaWManManager *thiz, + SaWManWindowHandle handle ) +{ + SaWMan *sawman; + SaWManWindow *window = (SaWManWindow*)handle; + + DIRECT_INTERFACE_GET_DATA( ISaWManManager ) + + if (!window) + return DFB_INVARG; + + sawman = data->sawman; + + D_MAGIC_ASSERT( sawman, SaWMan ); + D_MAGIC_ASSERT( window, SaWManWindow ); + + FUSION_SKIRMISH_ASSERT( &sawman->lock ); + + return sawman_remove_window( sawman, window ); +} + +static DirectResult +ISaWManManager_SetScalingMode( ISaWManManager *thiz, + SaWManScalingMode mode ) +{ + SaWMan *sawman; + + DIRECT_INTERFACE_GET_DATA( ISaWManManager ) + + if (mode != SWMSM_STANDARD && mode != SWMSM_SMOOTH_SW) + return DFB_INVARG; + + sawman = data->sawman; + D_MAGIC_ASSERT( sawman, SaWMan ); + + FUSION_SKIRMISH_ASSERT( &sawman->lock ); + + if (sawman->scaling_mode != mode) { + SaWManTier *tier; + + sawman->scaling_mode = mode; + + direct_list_foreach (tier, sawman->tiers) { + DFBRegion update = DFB_REGION_INIT_FROM_DIMENSION( &tier->size ); + + dfb_updates_add( &tier->updates, &update ); + } + } + + return DFB_OK; +} + +static void +reset_geometry_to_nonfollow( SaWManWindow *window ) +{ + if (window->window->config.dst_geometry.mode == DWGM_FOLLOW) + window->window->config.dst_geometry.mode = DWGM_DEFAULT; + + if (window->window->config.src_geometry.mode == DWGM_FOLLOW) + window->window->config.src_geometry.mode = DWGM_DEFAULT; +} + + +static DirectResult +ISaWManManager_SetWindowConfig ( ISaWManManager *thiz, + SaWManWindowHandle handle, + SaWManWindowConfigFlags flags, + SaWManWindowConfig *config ) +{ + DFBResult ret; + SaWMan *sawman; + SaWManWindow *sawwin = (SaWManWindow*)handle; + CoreWindow *window; + + /* + not yet implemented: + SWMCF_KEY_SELECTION + */ + + if (flags & ~(SWMCF_ALL - SWMCF_KEY_SELECTION)) + return DFB_INVARG; + + if( config == NULL ) + return DFB_INVARG; + + DIRECT_INTERFACE_GET_DATA( ISaWManManager ) + + sawman = data->sawman; + D_MAGIC_ASSERT( sawman, SaWMan ); + D_MAGIC_ASSERT( sawwin, SaWManWindow ); + + window = sawwin->window; + D_ASSERT( window != NULL ); + + FUSION_SKIRMISH_ASSERT( &sawman->lock ); + + if (flags & CWCF_OPTIONS) { + if ((window->config.options & DWOP_SCALE) && !(config->options & DWOP_SCALE) && window->surface) { + /* scaling turned off - see if we need to reallocate the surface */ + if (window->config.bounds.w != window->surface->config.size.w || + window->config.bounds.h != window->surface->config.size.h) + { + ret = dfb_surface_reformat( window->surface, + window->config.bounds.w, + window->config.bounds.h, + window->surface->config.format ); + if (ret) { + D_DERROR( ret, "WM/SaWMan: Could not resize surface " + "(%dx%d -> %dx%d) to remove DWOP_SCALE!\n", + window->surface->config.size.w, + window->surface->config.size.h, + window->config.bounds.w, + window->config.bounds.h ); + return ret; + } + } + } + + if (config->options & (DWOP_KEEP_ABOVE | DWOP_KEEP_UNDER)) { + D_ASSERT( sawwin->parent ); + + if (config->options & DWOP_KEEP_ABOVE) { + D_ASSERT( sawman_window_priority(sawwin->parent) <= sawman_window_priority(sawwin) ); + + sawman_insert_window( sawman, sawwin, sawwin->parent, true ); + } + else { + D_ASSERT( sawman_window_priority(sawwin->parent) >= sawman_window_priority(sawwin) ); + + sawman_insert_window( sawman, sawwin, sawwin->parent, false ); + } + + sawman_update_window( sawman, sawwin, NULL, DSFLIP_NONE, SWMUF_UPDATE_BORDER | SWMUF_FORCE_COMPLETE ); + } + + window->config.options = config->options; + } + + if (flags & CWCF_EVENTS) + window->config.events = config->events; + + if (flags & CWCF_COLOR) + window->config.color = config->color; + + if (flags & CWCF_COLOR_KEY) + window->config.color_key = config->color_key; + + if (flags & CWCF_OPAQUE) + window->config.opaque = config->opaque; + + if (flags & CWCF_STACKING) + sawman_restack_window( sawman, sawwin, sawwin, 0, config->stacking ); + + if (flags & CWCF_OPACITY) + sawman_set_opacity( sawman, sawwin, config->opacity ); + + if( flags & (SWMCF_POSITION | SWMCF_SIZE) ) { + if( flags == SWMCF_POSITION ) { + window->config.bounds.x = config->bounds.x; + window->config.bounds.y = config->bounds.y; + } + else if( flags == SWMCF_SIZE ) { + window->config.bounds.w = config->bounds.w; + window->config.bounds.h = config->bounds.h; + } + else + window->config.bounds = config->bounds; + } + + if (flags & CWCF_SRC_GEOMETRY) + window->config.src_geometry = config->src_geometry; + + if (flags & CWCF_DST_GEOMETRY) + window->config.dst_geometry = config->dst_geometry; + + if (flags & SWMCF_ASSOCIATION && window->config.association != config->association) { + SaWManWindow *parent = sawwin->parent; + + /* Dissociate first */ + if (sawwin->parent_window) { + int index; + + dfb_window_unlink( &sawwin->parent_window ); + + index = fusion_vector_index_of( &parent->children, sawwin ); + D_ASSERT( index >= 0 ); + D_ASSERT( index < parent->children.count ); + + fusion_vector_remove( &parent->children, index ); + + sawwin->parent = NULL; + + window->config.association = 0; + } + + + + /* Lookup new parent window. */ + if (config->association) { + D_DEBUG_AT( SaWMan_Manager, " -> new parent win id %u\n", config->association ); + + direct_list_foreach (parent, sawman->windows) { + D_MAGIC_ASSERT( parent, SaWManWindow ); + D_ASSERT( parent->window != NULL ); + + if (parent->id == config->association) + break; + } + + if (!parent) { + D_ERROR( "SaWMan/WM: Can't find parent window with ID %d!\n", config->association ); + reset_geometry_to_nonfollow( sawwin ); + return DFB_IDNOTFOUND; + } + + D_MAGIC_ASSERT( parent, SaWManWindow ); + D_ASSERT( parent->window != NULL ); + + if (parent->window->toplevel != window->toplevel) { + D_ERROR( "SaWMan/WM: Can't associate windows with different toplevel!\n" ); + reset_geometry_to_nonfollow( sawwin ); + return DFB_INVARG; + } + + D_DEBUG_AT( SaWMan_Manager, " -> parent window %p\n", parent ); + + + ret = dfb_window_link( &sawwin->parent_window, parent->window ); + if (ret) { + D_DERROR( ret, "SaWMan/WM: Can't link parent window with ID %d!\n", config->association ); + reset_geometry_to_nonfollow( sawwin ); + return ret; + } + + ret = fusion_vector_add( &parent->children, sawwin ); + if (ret) { + dfb_window_unlink( &sawwin->parent_window ); + reset_geometry_to_nonfollow( sawwin ); + return ret; + } + + + sawwin->parent = parent; + + /* Write back new association */ + window->config.association = config->association; + } + else + reset_geometry_to_nonfollow( sawwin ); + } + + if (flags & (CWCF_POSITION | CWCF_SIZE | CWCF_SRC_GEOMETRY | CWCF_DST_GEOMETRY | SWMCF_ASSOCIATION)) + sawman_update_geometry( sawwin ); + + /* Send notification to windows watchers */ + CoreLayer *layer = dfb_layer_at( sawwin->stack->context->layer_id ); + dfb_wm_dispatch_WindowConfig( layer->core, window, flags ); + + return DFB_OK; +} + + + +static DirectResult +ISaWManManager_SendWindowEvent( ISaWManManager *thiz, + SaWManWindowHandle handle, + const DFBWindowEvent *event ) +{ + SaWMan *sawman; + SaWManWindow *window = (SaWManWindow*)handle; + DFBWindowEvent evt; + + DIRECT_INTERFACE_GET_DATA( ISaWManManager ) + + if (!event || (handle == SAWMAN_WINDOW_NONE)) + return DFB_INVARG; + + /* Only key events! */ + if (event->type != DWET_KEYDOWN && event->type != DWET_KEYUP) + return DFB_UNSUPPORTED; + + /* Don't return same event twice! */ + if (event->flags & DWEF_RETURNED) + return DFB_LIMITEXCEEDED; + + sawman = data->sawman; + D_MAGIC_ASSERT( sawman, SaWMan ); + D_MAGIC_ASSERT( window, SaWManWindow ); + + FUSION_SKIRMISH_ASSERT( &sawman->lock ); + + evt = *event; + sawman_post_event( sawman, window, &evt ); + + return DFB_OK; +} + +static DirectResult +ISaWManManager_Lock( ISaWManManager *thiz ) +{ + SaWMan *sawman; + + DIRECT_INTERFACE_GET_DATA( ISaWManManager ) + + sawman = data->sawman; + D_MAGIC_ASSERT( sawman, SaWMan ); + + return sawman_lock( sawman ); +} + +static DirectResult +ISaWManManager_Unlock( ISaWManManager *thiz ) +{ + SaWMan *sawman; + + DIRECT_INTERFACE_GET_DATA( ISaWManManager ) + + sawman = data->sawman; + D_MAGIC_ASSERT( sawman, SaWMan ); + + FUSION_SKIRMISH_ASSERT( &sawman->lock ); + + return sawman_unlock( sawman ); +} + +static DirectResult +ISaWManManager_GetWindowInfo( ISaWManManager *thiz, + SaWManWindowHandle handle, + SaWManWindowInfo *info ) +{ + SaWMan *sawman; + SaWManWindow *sawwin = (SaWManWindow*)handle; + CoreWindow *window; + + DIRECT_INTERFACE_GET_DATA( ISaWManManager ) + + if (!info || (handle == SAWMAN_WINDOW_NONE)) + return DFB_INVARG; + + sawman = data->sawman; + D_MAGIC_ASSERT( sawman, SaWMan ); + D_MAGIC_ASSERT( sawwin, SaWManWindow ); + + window = sawwin->window; + D_ASSERT( window != NULL ); + + FUSION_SKIRMISH_ASSERT( &sawman->lock ); + + info->handle = handle; + info->caps = sawwin->caps; + SAWMANWINDOWCONFIG_COPY( &info->config, &window->config ) + info->config.key_selection = window->config.key_selection; + info->config.keys = window->config.keys; + info->config.num_keys = window->config.num_keys; + info->resource_id = window->resource_id; + info->win_id = window->id; + info->flags = sawwin->flags + | (window->flags & CWF_FOCUSED ? SWMWF_FOCUSED : 0) + | (window->flags & CWF_ENTERED ? SWMWF_ENTERED : 0); + + return DFB_OK; +} + +static DirectResult +ISaWManManager_GetProcessInfo( ISaWManManager *thiz, + SaWManWindowHandle handle, + SaWManProcess *process ) +{ + SaWMan *sawman; + SaWManWindow *sawwin = (SaWManWindow*)handle; + + DIRECT_INTERFACE_GET_DATA( ISaWManManager ) + + if (!process || (handle == SAWMAN_WINDOW_NONE)) + return DFB_INVARG; + + sawman = data->sawman; + D_MAGIC_ASSERT( sawman, SaWMan ); + D_MAGIC_ASSERT( sawwin, SaWManWindow ); + + FUSION_SKIRMISH_ASSERT( &sawman->lock ); + + *process = *sawwin->process; + + return DFB_OK; +} + +static DirectResult +ISaWManManager_IsWindowShowing( ISaWManManager *thiz, + SaWManWindowHandle handle, + DFBBoolean *ret_showing ) +{ + DFBResult ret; + bool showing; + SaWMan *sawman; + SaWManWindow *sawwin = (SaWManWindow*)handle; + + DIRECT_INTERFACE_GET_DATA( ISaWManManager ) + + if (!ret_showing) + return DFB_INVARG; + + sawman = data->sawman; + D_MAGIC_ASSERT( sawman, SaWMan ); + D_MAGIC_ASSERT( sawwin, SaWManWindow ); + + FUSION_SKIRMISH_ASSERT( &sawman->lock ); + + ret = sawman_showing_window( sawman, sawwin, &showing ); + if (ret) + return ret; + + *ret_showing = showing ? DFB_TRUE : DFB_FALSE; + + return DFB_OK; +} + +DirectResult +ISaWManManager_Construct( ISaWManManager *thiz, + SaWMan *sawman, + SaWManProcess *process ) +{ + DIRECT_ALLOCATE_INTERFACE_DATA( thiz, ISaWManManager ) + + data->ref = 1; + data->sawman = sawman; + data->process = process; + + thiz->AddRef = ISaWManManager_AddRef; + thiz->Release = ISaWManManager_Release; + thiz->QueueUpdate = ISaWManManager_QueueUpdate; + thiz->ProcessUpdates = ISaWManManager_ProcessUpdates; + thiz->CloseWindow = ISaWManManager_CloseWindow; + thiz->SetVisible = ISaWManManager_SetVisible; + thiz->SwitchFocus = ISaWManManager_SwitchFocus; + thiz->GetSize = ISaWManManager_GetSize; + thiz->InsertWindow = ISaWManManager_InsertWindow; + thiz->RemoveWindow = ISaWManManager_RemoveWindow; + thiz->SetScalingMode = ISaWManManager_SetScalingMode; + thiz->SetWindowConfig = ISaWManManager_SetWindowConfig; + thiz->SendWindowEvent = ISaWManManager_SendWindowEvent; + thiz->Lock = ISaWManManager_Lock; + thiz->Unlock = ISaWManManager_Unlock; + thiz->GetWindowInfo = ISaWManManager_GetWindowInfo; + thiz->GetProcessInfo = ISaWManManager_GetProcessInfo; + thiz->IsWindowShowing = ISaWManManager_IsWindowShowing; + + return DFB_OK; +} |