/* (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 /* FIXME */ #include #include #include /* FIXME */ #include #include #include #include #include #include #include #include D_DEBUG_DOMAIN( UniQuE_Window, "UniQuE/Window", "UniQuE's Window" ); static const ReactionFunc unique_window_globals[] = { _unique_wm_module_window_listener, NULL }; /**************************************************************************************************/ typedef struct { DirectLink link; int magic; DFBInputDeviceKeySymbol symbol; DFBInputDeviceModifierMask modifiers; UniqueInputFilter *filter; } KeyFilter; /**************************************************************************************************/ static DFBResult add_key_filter ( UniqueWindow *window, DFBInputDeviceKeySymbol symbol, DFBInputDeviceModifierMask modifiers, UniqueInputFilter *filter ); static DFBResult remove_key_filter ( UniqueWindow *window, DFBInputDeviceKeySymbol symbol, DFBInputDeviceModifierMask modifiers ); static void remove_all_filters( UniqueWindow *window ); /**************************************************************************************************/ static DFBResult create_regions ( UniqueWindow *window ); static void insert_window ( UniqueContext *context, UniqueWindow *window ); static void remove_window ( UniqueWindow *window ); static void update_foo_frame( UniqueWindow *window, UniqueContext *context, WMShared *shared ); static DFBResult update_window ( UniqueWindow *window, const DFBRegion *region, DFBSurfaceFlipFlags flags, bool complete ); static void update_flags ( UniqueWindow *window ); static void set_opacity ( UniqueWindow *window, u8 opacity ); static DFBResult move_window ( UniqueWindow *window, int dx, int dy ); static DFBResult resize_window ( UniqueWindow *window, int width, int height ); static DFBResult restack_window ( UniqueWindow *window, UniqueWindow *relative, int relation, DFBWindowStackingClass stacking ); /**************************************************************************************************/ static inline int get_priority( DFBWindowCapabilities caps, DFBWindowStackingClass stacking ); /**************************************************************************************************/ static void window_destructor( FusionObject *object, bool zombie, void *ctx ) { int i; UniqueContext *context; UniqueWindow *window = (UniqueWindow*) object; D_MAGIC_ASSERT( window, UniqueWindow ); D_DEBUG_AT( UniQuE_Window, "destroying %p (%dx%d - %dx%d)%s\n", window, DFB_RECTANGLE_VALS( &window->bounds ), zombie ? " (ZOMBIE)" : ""); context = window->context; D_MAGIC_ASSERT( context, UniqueContext ); D_FLAGS_SET( window->flags, UWF_DESTROYED ); unique_window_notify( window, UWNF_DESTROYED ); set_opacity( window, 0 ); remove_window( window ); for (i=0; i<8; i++) { if (window->foos[i]) stret_region_destroy( window->foos[i] ); } stret_region_destroy( window->region ); stret_region_destroy( window->frame ); remove_all_filters( window ); unique_input_switch_drop( context->input_switch, window->channel ); unique_input_channel_detach_global( window->channel, &window->channel_reaction ); unique_input_channel_destroy( window->channel ); if (window->surface) dfb_surface_unlink( &window->surface ); unique_context_unlink( &window->context ); dfb_window_unlink( &window->window ); D_MAGIC_CLEAR( window ); fusion_object_destroy( object ); } FusionObjectPool * unique_window_pool_create( const FusionWorld *world ) { return fusion_object_pool_create( "UniQuE Window Pool", sizeof(UniqueWindow), sizeof(UniqueWindowNotification), window_destructor, NULL, world ); } /**************************************************************************************************/ DFBResult unique_window_create( CoreDFB *core, CoreWindow *window, UniqueContext *context, DFBWindowCapabilities caps, const CoreWindowConfig *config, UniqueWindow **ret_window ) { DFBResult ret; UniqueWindow *uniwin; WMShared *shared; CoreSurface *surface; DFBRectangle bounds; D_ASSERT( window != NULL ); D_ASSERT( ret_window != NULL ); D_MAGIC_ASSERT( context, UniqueContext ); shared = context->shared; D_MAGIC_ASSERT( shared, WMShared ); surface = dfb_window_surface( window ); D_ASSERT( surface != NULL || (caps & DWCAPS_INPUTONLY)); uniwin = unique_wm_create_window(); if (!uniwin) return DFB_FUSION; bounds = config->bounds; /*if (bounds.x == 0 && bounds.y == 0) { bounds.x = (context->width - bounds.w) / 2; bounds.y = (context->height - bounds.h) / 2; }*/ /* Initialize window data. */ uniwin->shared = context->shared; uniwin->caps = caps; uniwin->flags = UWF_NONE; uniwin->bounds = bounds; uniwin->opacity = config->opacity; uniwin->stacking = config->stacking; uniwin->priority = get_priority( caps, config->stacking ); uniwin->options = config->options; uniwin->events = config->events; uniwin->color_key = config->color_key; uniwin->opaque = config->opaque; if (dfb_config->decorations && ! (caps & (DWCAPS_INPUTONLY | DWCAPS_NODECORATION))) { uniwin->flags |= UWF_DECORATED; uniwin->insets = shared->insets; } dfb_rectangle_from_rectangle_plus_insets( &uniwin->full, &uniwin->bounds, &uniwin->insets ); ret = dfb_window_link( &uniwin->window, window ); if (ret) goto error; ret = unique_context_link( &uniwin->context, context ); if (ret) goto error; if (surface) { ret = dfb_surface_link( &uniwin->surface, surface ); if (ret) goto error; } ret = unique_input_channel_create( core, context, &uniwin->channel ); if (ret) goto error; ret = unique_input_channel_attach_global( uniwin->channel, UNIQUE_WINDOW_INPUT_CHANNEL_LISTENER, uniwin, &uniwin->channel_reaction ); if (ret) goto error; D_MAGIC_SET( uniwin, UniqueWindow ); ret = create_regions( uniwin ); if (ret) { D_MAGIC_CLEAR( uniwin ); goto error; } /* Change global reaction lock. */ fusion_object_set_lock( &uniwin->object, &context->stack->context->lock ); /* activate object */ fusion_object_activate( &uniwin->object ); /* Actually add the window to the stack. */ insert_window( context, uniwin ); /* Possibly switch focus to the new window. */ //unique_context_update_focus( context ); /* return the new context */ *ret_window = uniwin; return DFB_OK; error: if (uniwin->channel_reaction.attached) unique_input_channel_detach_global( uniwin->channel, &uniwin->channel_reaction ); if (uniwin->channel) unique_input_channel_destroy( uniwin->channel ); if (uniwin->surface) dfb_surface_unlink( &uniwin->surface ); if (uniwin->context) unique_context_unlink( &uniwin->context ); if (uniwin->window) dfb_window_unlink( &uniwin->window ); fusion_object_destroy( &uniwin->object ); return ret; } DFBResult unique_window_close( UniqueWindow *window ) { D_MAGIC_ASSERT( window, UniqueWindow ); D_UNIMPLEMENTED(); return DFB_OK; } DFBResult unique_window_destroy( UniqueWindow *window ) { D_MAGIC_ASSERT( window, UniqueWindow ); D_UNIMPLEMENTED(); return DFB_OK; } DFBResult unique_window_notify( UniqueWindow *window, UniqueWindowNotificationFlags flags ) { UniqueWindowNotification notification; D_MAGIC_ASSERT( window, UniqueWindow ); D_ASSERT( flags != UWNF_NONE ); D_ASSERT( ! (flags & ~UWNF_ALL) ); notification.flags = flags; notification.window = window; return unique_window_dispatch( window, ¬ification, unique_window_globals ); } DFBResult unique_window_update( UniqueWindow *window, const DFBRegion *region, DFBSurfaceFlipFlags flags ) { D_MAGIC_ASSERT( window, UniqueWindow ); DFB_REGION_ASSERT_IF( region ); return update_window( window, region, flags, false ); } DFBResult unique_window_post_event( UniqueWindow *window, DFBWindowEvent *event ) { UniqueContext *context; D_MAGIC_ASSERT( window, UniqueWindow ); D_ASSERT( event != NULL ); if (!D_FLAGS_IS_SET( window->events, event->type )) return DFB_OK; context = window->context; D_MAGIC_ASSERT( context, UniqueContext ); dfb_window_post_event( window->window, event ); return DFB_OK; } DFBResult unique_window_set_config( UniqueWindow *window, const CoreWindowConfig *config, CoreWindowConfigFlags flags ) { D_MAGIC_ASSERT( window, UniqueWindow ); if (flags & CWCF_OPTIONS) { window->options = config->options; update_flags( window ); } if (flags & CWCF_EVENTS) window->events = config->events; if (flags & CWCF_COLOR) return DFB_UNSUPPORTED; if (flags & CWCF_COLOR_KEY) window->color_key = config->color_key; if (flags & CWCF_OPAQUE) window->opaque = config->opaque; if (flags & CWCF_OPACITY && !config->opacity) set_opacity( window, config->opacity ); if (flags & CWCF_POSITION) move_window( window, config->bounds.x - window->bounds.x, config->bounds.y - window->bounds.y ); if (flags & CWCF_STACKING) restack_window( window, window, 0, config->stacking ); if (flags & CWCF_OPACITY && config->opacity) set_opacity( window, config->opacity ); if (flags & CWCF_SIZE) return resize_window( window, config->bounds.w, config->bounds.h ); return DFB_OK; } DFBResult unique_window_get_config( UniqueWindow *window, CoreWindowConfig *config ) { D_MAGIC_ASSERT( window, UniqueWindow ); D_ASSERT( config != NULL ); config->bounds = window->bounds; config->opacity = window->opacity; config->stacking = window->stacking; config->options = window->options; config->events = window->events; config->color_key = window->color_key; config->opaque = window->opaque; return DFB_OK; } DFBResult unique_window_restack( UniqueWindow *window, UniqueWindow *relative, int relation ) { D_MAGIC_ASSERT( window, UniqueWindow ); return restack_window( window, relative, relation, window->stacking ); } DFBResult unique_window_grab( UniqueWindow *window, const CoreWMGrab *grab ) { UniqueContext *context; D_MAGIC_ASSERT( window, UniqueWindow ); context = window->context; D_MAGIC_ASSERT( context, UniqueContext ); switch (grab->target) { case CWMGT_KEYBOARD: return unique_input_switch_set( context->input_switch, UDCI_KEYBOARD, window->channel ); case CWMGT_POINTER: return unique_input_switch_set( context->input_switch, UDCI_POINTER, window->channel ); case CWMGT_KEY: { DFBResult ret; UniqueInputEvent event; UniqueInputFilter *filter; event.keyboard.key_code = -1; event.keyboard.key_symbol = grab->symbol; event.keyboard.modifiers = grab->modifiers; ret = unique_input_switch_set_filter( context->input_switch, UDCI_KEYBOARD, window->channel, &event, &filter ); if (ret) { D_DERROR( ret, "UniQuE/Window: Could not set input filter for key grab!\n" ); return ret; } ret = add_key_filter( window, grab->symbol, grab->modifiers, filter ); if (ret) { unique_input_switch_unset_filter( context->input_switch, filter ); return ret; } break; } default: D_BUG( "unknown grab target" ); break; } return DFB_OK; } DFBResult unique_window_ungrab( UniqueWindow *window, const CoreWMGrab *grab ) { UniqueContext *context; D_MAGIC_ASSERT( window, UniqueWindow ); context = window->context; D_MAGIC_ASSERT( context, UniqueContext ); switch (grab->target) { case CWMGT_KEYBOARD: return unique_input_switch_unset( context->input_switch, UDCI_KEYBOARD, window->channel ); case CWMGT_POINTER: return unique_input_switch_unset( context->input_switch, UDCI_POINTER, window->channel ); case CWMGT_KEY: return remove_key_filter( window, grab->symbol, grab->modifiers ); default: D_BUG( "unknown grab target" ); break; } return DFB_OK; } DFBResult unique_window_request_focus( UniqueWindow *window ) { UniqueContext *context; D_MAGIC_ASSERT( window, UniqueWindow ); context = window->context; D_MAGIC_ASSERT( context, UniqueContext ); return unique_input_switch_select( context->input_switch, UDCI_KEYBOARD, window->channel ); } /**************************************************************************************************/ static DFBResult add_key_filter( UniqueWindow *window, DFBInputDeviceKeySymbol symbol, DFBInputDeviceModifierMask modifiers, UniqueInputFilter *filter ) { KeyFilter *key; UniqueContext *context; D_MAGIC_ASSERT( window, UniqueWindow ); context = window->context; D_MAGIC_ASSERT( context, UniqueContext ); key = SHCALLOC( context->shmpool, 1, sizeof(KeyFilter) ); if (!key) return D_OOSHM(); key->symbol = symbol; key->modifiers = modifiers; key->filter = filter; direct_list_append( &window->filters, &key->link ); D_MAGIC_SET( key, KeyFilter ); return DFB_OK; } static DFBResult remove_key_filter( UniqueWindow *window, DFBInputDeviceKeySymbol symbol, DFBInputDeviceModifierMask modifiers ) { KeyFilter *key; UniqueContext *context; D_MAGIC_ASSERT( window, UniqueWindow ); context = window->context; D_MAGIC_ASSERT( context, UniqueContext ); direct_list_foreach (key, window->filters) { D_MAGIC_ASSERT( key, KeyFilter ); if (key->symbol == symbol && key->modifiers == modifiers) break; } if (!key) return DFB_ITEMNOTFOUND; unique_input_switch_unset_filter( context->input_switch, key->filter ); direct_list_remove( &window->filters, &key->link ); D_MAGIC_CLEAR( key ); SHFREE( context->shmpool, key ); return DFB_OK; } static void remove_all_filters( UniqueWindow *window ) { DirectLink *n; KeyFilter *key; UniqueContext *context; D_MAGIC_ASSERT( window, UniqueWindow ); context = window->context; D_MAGIC_ASSERT( context, UniqueContext ); direct_list_foreach_safe (key, n, window->filters) { D_MAGIC_ASSERT( key, KeyFilter ); unique_input_switch_unset_filter( context->input_switch, key->filter ); D_MAGIC_CLEAR( key ); SHFREE( context->shmpool, key ); } window->filters = NULL; } /**************************************************************************************************/ static void dispatch_motion( UniqueWindow *window, const UniqueInputEvent *event ) { DFBWindowEvent evt; D_MAGIC_ASSERT( window, UniqueWindow ); D_ASSERT( event != NULL ); evt.type = DWET_MOTION; evt.cx = event->pointer.x; evt.cy = event->pointer.y; evt.x = event->pointer.x - window->bounds.x; evt.y = event->pointer.y - window->bounds.y; evt.buttons = event->pointer.buttons; dfb_window_post_event( window->window, &evt ); } static void dispatch_button( UniqueWindow *window, const UniqueInputEvent *event ) { DFBWindowEvent evt; D_MAGIC_ASSERT( window, UniqueWindow ); D_ASSERT( event != NULL ); evt.type = event->pointer.press ? DWET_BUTTONDOWN : DWET_BUTTONUP; evt.cx = event->pointer.x; evt.cy = event->pointer.y; evt.x = event->pointer.x - window->bounds.x; evt.y = event->pointer.y - window->bounds.y; evt.button = event->pointer.button; evt.buttons = event->pointer.buttons; dfb_window_post_event( window->window, &evt ); } static void dispatch_wheel( UniqueWindow *window, const UniqueInputEvent *event ) { DFBWindowEvent evt; D_MAGIC_ASSERT( window, UniqueWindow ); D_ASSERT( event != NULL ); evt.type = DWET_WHEEL; evt.step = event->wheel.value; dfb_window_post_event( window->window, &evt ); } static void dispatch_key( UniqueWindow *window, const UniqueInputEvent *event ) { DFBWindowEvent evt; D_MAGIC_ASSERT( window, UniqueWindow ); D_ASSERT( event != NULL ); evt.type = event->keyboard.press ? DWET_KEYDOWN : DWET_KEYUP; evt.key_code = event->keyboard.key_code; evt.key_id = event->keyboard.key_id; evt.key_symbol = event->keyboard.key_symbol; evt.modifiers = event->keyboard.modifiers; evt.locks = event->keyboard.locks; dfb_window_post_event( window->window, &evt ); } static void dispatch_channel( UniqueWindow *window, const UniqueInputEvent *event ) { DFBWindowEvent evt; D_MAGIC_ASSERT( window, UniqueWindow ); D_ASSERT( event != NULL ); switch (event->channel.index) { case UDCI_POINTER: evt.type = event->channel.selected ? DWET_ENTER : DWET_LEAVE; break; case UDCI_KEYBOARD: evt.type = event->channel.selected ? DWET_GOTFOCUS : DWET_LOSTFOCUS; break; default: return; } evt.cx = event->channel.x; evt.cy = event->channel.y; evt.x = event->channel.x - window->bounds.x; evt.y = event->channel.y - window->bounds.y; dfb_window_post_event( window->window, &evt ); } ReactionResult _unique_window_input_channel_listener( const void *msg_data, void *ctx ) { const UniqueInputEvent *event = msg_data; UniqueWindow *window = ctx; D_MAGIC_ASSERT( window, UniqueWindow ); D_ASSERT( event != NULL ); D_DEBUG_AT( UniQuE_Window, "_unique_window_input_channel_listener( %p, %p )\n", event, window ); switch (event->type) { case UIET_MOTION: dispatch_motion( window, event ); break; case UIET_BUTTON: dispatch_button( window, event ); break; case UIET_WHEEL: dispatch_wheel( window, event ); break; case UIET_KEY: dispatch_key( window, event ); break; case UIET_CHANNEL: dispatch_channel( window, event ); break; default: D_ONCE( "unknown event type" ); break; } return RS_OK; } /**************************************************************************************************/ static inline int get_priority( DFBWindowCapabilities caps, DFBWindowStackingClass stacking ) { switch (stacking) { case DWSC_UPPER: return 1; case DWSC_MIDDLE: return 0; case DWSC_LOWER: return -1; default: D_BUG( "unknown stacking class" ); break; } return 0; } static inline int get_index( UniqueWindow *window ) { UniqueContext *context; D_MAGIC_ASSERT( window, UniqueWindow ); context = window->context; D_MAGIC_ASSERT( context, UniqueContext ); D_ASSERT( fusion_vector_contains( &context->windows, window ) ); return fusion_vector_index_of( &context->windows, window ); } static DFBResult update_window( UniqueWindow *window, const DFBRegion *region, DFBSurfaceFlipFlags flags, bool complete ) { DFBRegion regions[32]; int num_regions; D_MAGIC_ASSERT( window, UniqueWindow ); DFB_REGION_ASSERT_IF( region ); if (complete || stret_region_visible( window->region, region, true, regions, 32, &num_regions )) { if (region) { DFBRegion area = DFB_REGION_INIT_TRANSLATED( region, window->bounds.x, window->bounds.y ); unique_context_update( window->context, &area, 1, flags ); } else { DFBRegion area = DFB_REGION_INIT_FROM_RECTANGLE( &window->bounds ); unique_context_update( window->context, &area, 1, flags ); } } else if (num_regions > 0) unique_context_update( window->context, regions, num_regions, flags ); return DFB_OK; } static DFBResult update_frame( UniqueWindow *window, const DFBRegion *region, DFBSurfaceFlipFlags flags, bool complete ) { DFBRegion regions[32]; int num_regions; D_MAGIC_ASSERT( window, UniqueWindow ); DFB_REGION_ASSERT_IF( region ); if (complete || stret_region_visible( window->frame, region, true, regions, 32, &num_regions )) { if (region) { DFBRegion area = DFB_REGION_INIT_TRANSLATED( region, window->full.x, window->full.y ); unique_context_update( window->context, &area, 1, flags ); } else { DFBRegion area = DFB_REGION_INIT_FROM_RECTANGLE( &window->full ); unique_context_update( window->context, &area, 1, flags ); } } else if (num_regions > 0) unique_context_update( window->context, regions, num_regions, flags ); return DFB_OK; } /**************************************************************************************************/ /**************************************************************************************************/ static void insert_window( UniqueContext *context, UniqueWindow *window ) { int index; UniqueWindow *other; D_MAGIC_ASSERT( context, UniqueContext ); D_MAGIC_ASSERT( window, UniqueWindow ); /* * Iterate from bottom to top, * stopping at the first window with a higher priority. */ fusion_vector_foreach (other, index, context->windows) { D_MAGIC_ASSERT( other, UniqueWindow ); if (other->priority > window->priority) break; } /* Insert the window at the acquired position. */ fusion_vector_insert( &context->windows, window, index ); stret_region_restack( window->frame, index ); } static void remove_window( UniqueWindow *window ) { int index; UniqueContext *context; D_MAGIC_ASSERT( window, UniqueWindow ); context = window->context; D_MAGIC_ASSERT( context, UniqueContext ); D_ASSERT( fusion_vector_contains( &context->windows, window ) ); index = fusion_vector_index_of( &context->windows, window ); fusion_vector_remove( &context->windows, index ); } /**************************************************************************************************/ static DFBResult move_window( UniqueWindow *window, int dx, int dy ) { DFBWindowEvent evt; UniqueContext *context; D_MAGIC_ASSERT( window, UniqueWindow ); context = window->context; D_MAGIC_ASSERT( context, UniqueContext ); dfb_rectangle_translate( &window->bounds, dx, dy ); dfb_rectangle_translate( &window->full, dx, dy ); stret_region_move( window->frame, dx, dy ); if (D_FLAGS_IS_SET( window->flags, UWF_VISIBLE )) { DFBRegion region = { 0, 0, window->full.w - 1, window->full.h - 1 }; if (dx > 0) region.x1 -= dx; else if (dx < 0) region.x2 -= dx; if (dy > 0) region.y1 -= dy; else if (dy < 0) region.y2 -= dy; update_frame( window, ®ion, DSFLIP_NONE, false ); } /* Send new position */ evt.type = DWET_POSITION; evt.x = window->bounds.x; evt.y = window->bounds.y; unique_window_post_event( window, &evt ); return DFB_OK; } static DFBResult resize_window( UniqueWindow *window, int width, int height ) { DFBResult ret; DFBWindowEvent evt; int ow; int oh; UniqueContext *context; WMShared *shared; DFBRectangle *sizes; D_MAGIC_ASSERT( window, UniqueWindow ); D_ASSERT( width > 0 ); D_ASSERT( height > 0 ); context = window->context; D_MAGIC_ASSERT( context, UniqueContext ); shared = context->shared; D_MAGIC_ASSERT( shared, WMShared ); sizes = shared->foo_rects; if (width > 4096 || height > 4096) return DFB_LIMITEXCEEDED; if (window->surface) { ret = dfb_surface_reformat( window->surface, width, height, window->surface->config.format ); if (ret) return ret; } ow = window->bounds.w; oh = window->bounds.h; window->bounds.w = width; window->bounds.h = height; window->full.w += width - ow; window->full.h += height - oh; stret_region_resize( window->frame, window->full.w, window->full.h ); stret_region_resize( window->region, window->bounds.w, window->bounds.h ); update_foo_frame( window, window->context, window->shared ); if (D_FLAGS_IS_SET( window->flags, UWF_VISIBLE )) { int dw = ow - width; int dh = oh - height; if (D_FLAGS_IS_SET( window->flags, UWF_DECORATED )) { int bw = dw - sizes[UFI_NE].w + sizes[UFI_E].w; int bh = dh - sizes[UFI_SW].h + sizes[UFI_S].h; DFBInsets *in = &window->insets; if (bw < 0) { DFBRegion region = { in->l + width + bw, 0, in->l + width - 1, in->t - 1 }; update_frame( window, ®ion, 0, false ); } if (bh < 0) { DFBRegion region = { 0, in->t + height + bh, in->l - 1, in->t + height - 1 }; update_frame( window, ®ion, 0, false ); } if (dw < 0) dw = 0; if (dh < 0) dh = 0; dw += in->r; dh += in->b; if (dw > 0) { DFBRegion region = { in->l + width, 0, in->l + width + dw - 1, in->t + height - 1 }; update_frame( window, ®ion, 0, false ); } if (dh > 0) { DFBRegion region = { 0, in->t + height, in->l + width + dw - 1, in->t + height + dh - 1 }; update_frame( window, ®ion, 0, false ); } } else { if (dw < 0) dw = 0; if (dh < 0) dh = 0; if (dw > 0) { DFBRegion region = { width, 0, width + dw - 1, height - 1 }; update_frame( window, ®ion, 0, false ); } if (dh > 0) { DFBRegion region = { 0, height, width + dw - 1, height + dh - 1 }; update_frame( window, ®ion, 0, false ); } } } /* Send new size */ evt.type = DWET_SIZE; evt.w = window->bounds.w; evt.h = window->bounds.h; unique_window_post_event( window, &evt ); unique_input_switch_update( context->input_switch, window->channel ); //unique_context_update_focus( context ); return DFB_OK; } static DFBResult restack_window( UniqueWindow *window, UniqueWindow *relative, int relation, DFBWindowStackingClass stacking ) { int old; int index; int priority; UniqueContext *context; D_MAGIC_ASSERT( window, UniqueWindow ); D_MAGIC_ASSERT_IF( relative, UniqueWindow ); D_ASSERT( relative == NULL || relative == window || relation != 0); context = window->context; D_MAGIC_ASSERT( context, UniqueContext ); /* Change stacking class. */ if (stacking != window->stacking) { window->stacking = stacking; window->priority = get_priority( window->caps, stacking ); } /* Get the (new) priority. */ priority = window->priority; /* Get the old index. */ old = get_index( window ); /* Calculate the desired index. */ if (relative) { index = get_index( relative ); if (relation > 0) { if (old < index) index--; } else if (relation < 0) { if (old > index) index++; } index += relation; if (index < 0) index = 0; else if (index > fusion_vector_size( &context->windows ) - 1) index = fusion_vector_size( &context->windows ) - 1; } else if (relation) index = fusion_vector_size( &context->windows ) - 1; else index = 0; /* Assure window won't be above any window with a higher priority. */ while (index > 0) { int below = (old < index) ? index : index - 1; UniqueWindow *other = fusion_vector_at( &context->windows, below ); D_MAGIC_ASSERT( other, UniqueWindow ); if (priority < other->priority) index--; else break; } /* Assure window won't be below any window with a lower priority. */ while (index < fusion_vector_size( &context->windows ) - 1) { int above = (old > index) ? index : index + 1; UniqueWindow *other = fusion_vector_at( &context->windows, above ); D_MAGIC_ASSERT( other, UniqueWindow ); if (priority > other->priority) index++; else break; } /* Return if index hasn't changed. */ if (index == old) return DFB_OK; /* Actually change the stacking order now. */ fusion_vector_move( &context->windows, old, index ); stret_region_restack( window->frame, index ); update_frame( window, NULL, DSFLIP_NONE, (index < old) ); if (index < old) unique_input_switch_update( context->input_switch, window->channel ); return DFB_OK; } static void set_opacity( UniqueWindow *window, u8 opacity ) { u8 old; UniqueContext *context; D_MAGIC_ASSERT( window, UniqueWindow ); context = window->context; D_MAGIC_ASSERT( context, UniqueContext ); old = window->opacity; if (!dfb_config->translucent_windows && opacity) opacity = 0xFF; if (old != opacity) { bool show = !old && opacity; bool hide = old && !opacity; window->opacity = opacity; if (show) { stret_region_enable( window->frame, SRF_ACTIVE ); D_FLAGS_SET( window->flags, UWF_VISIBLE ); } if (hide) D_FLAGS_CLEAR( window->flags, UWF_VISIBLE ); if (! (window->options & (DWOP_ALPHACHANNEL | DWOP_COLORKEYING))) { if (opacity == 0xff && old != 0xff) stret_region_enable( window->region, SRF_OPAQUE ); else if (opacity != 0xff && old == 0xff) stret_region_disable( window->region, SRF_OPAQUE ); } update_frame( window, NULL, DSFLIP_NONE, false ); /* Check focus after window appeared or disappeared */ if (/*show ||*/ hide) unique_input_switch_update( context->input_switch, window->channel ); // unique_context_update_focus( context ); /* If window disappeared... */ if (hide) { stret_region_disable( window->frame, SRF_ACTIVE ); /* Ungrab pointer/keyboard, release focus */ unique_input_switch_drop( context->input_switch, window->channel ); } } } /**************************************************************************************************/ static void foo_rects( UniqueWindow *window, UniqueContext *context, WMShared *shared, DFBRectangle *ret_rects ) { int width; int height; DFBRectangle *sizes; D_MAGIC_ASSERT( window, UniqueWindow ); D_MAGIC_ASSERT( context, UniqueContext ); D_MAGIC_ASSERT( shared, WMShared ); D_ASSERT( ret_rects != NULL ); width = window->full.w; height = window->full.h; sizes = shared->foo_rects; if (width <= sizes[UFI_NW].w + sizes[UFI_NE].w) width = sizes[UFI_NW].w + sizes[UFI_NE].w + 1; if (width <= sizes[UFI_SW].w + sizes[UFI_SE].w) width = sizes[UFI_SW].w + sizes[UFI_SE].w + 1; if (height <= sizes[UFI_NW].h + sizes[UFI_SW].h) height = sizes[UFI_NW].h + sizes[UFI_SW].h + 1; if (height <= sizes[UFI_NE].h + sizes[UFI_SE].h) height = sizes[UFI_NE].h + sizes[UFI_SE].h + 1; ret_rects[UFI_N].x = sizes[UFI_NW].w; ret_rects[UFI_N].y = 0; ret_rects[UFI_N].w = width - sizes[UFI_NW].w - sizes[UFI_NE].w; ret_rects[UFI_N].h = sizes[UFI_N].h; ret_rects[UFI_NE].x = width - sizes[UFI_NE].w; ret_rects[UFI_NE].y = 0; ret_rects[UFI_NE].w = sizes[UFI_NE].w; ret_rects[UFI_NE].h = sizes[UFI_NE].h; ret_rects[UFI_E].x = width - sizes[UFI_E].w; ret_rects[UFI_E].y = sizes[UFI_NE].h; ret_rects[UFI_E].w = sizes[UFI_E].w; ret_rects[UFI_E].h = height - sizes[UFI_NE].h - sizes[UFI_SE].h; ret_rects[UFI_SE].x = width - sizes[UFI_SE].w; ret_rects[UFI_SE].y = height - sizes[UFI_SE].h; ret_rects[UFI_SE].w = sizes[UFI_SE].w; ret_rects[UFI_SE].h = sizes[UFI_SE].h; ret_rects[UFI_S].x = sizes[UFI_SW].w; ret_rects[UFI_S].y = height - sizes[UFI_S].h; ret_rects[UFI_S].w = width - sizes[UFI_SE].w - sizes[UFI_SW].w; ret_rects[UFI_S].h = sizes[UFI_S].h; ret_rects[UFI_SW].x = 0; ret_rects[UFI_SW].y = height - sizes[UFI_SW].h; ret_rects[UFI_SW].w = sizes[UFI_SW].w; ret_rects[UFI_SW].h = sizes[UFI_SW].h; ret_rects[UFI_W].x = 0; ret_rects[UFI_W].y = sizes[UFI_NW].h; ret_rects[UFI_W].w = sizes[UFI_W].w; ret_rects[UFI_W].h = height - sizes[UFI_NW].h - sizes[UFI_SW].h; ret_rects[UFI_NW].x = 0; ret_rects[UFI_NW].y = 0; ret_rects[UFI_NW].w = sizes[UFI_NW].w; ret_rects[UFI_NW].h = sizes[UFI_NW].h; } static void update_foo_frame( UniqueWindow *window, UniqueContext *context, WMShared *shared ) { int i; DFBRectangle rects[8]; D_MAGIC_ASSERT( window, UniqueWindow ); D_MAGIC_ASSERT( context, UniqueContext ); D_MAGIC_ASSERT( shared, WMShared ); if (!window->foos[0]) return; foo_rects( window, context, shared, rects ); for (i=0; i<8; i++) window->foos[i]->bounds = DFB_REGION_INIT_FROM_RECTANGLE( &rects[i] ); } static void update_flags( UniqueWindow *window ) { int i; D_MAGIC_ASSERT( window, UniqueWindow ); if (! (window->options & DWOP_GHOST)) { if (window->foos[0]) { for (i=0; i<8; i++) window->foos[i]->flags |= SRF_INPUT; } window->region->flags |= SRF_INPUT; } else { if (window->foos[0]) { for (i=0; i<8; i++) window->foos[i]->flags &= ~SRF_INPUT; } window->region->flags &= ~SRF_INPUT; } } static DFBResult create_foos( UniqueWindow *window, UniqueContext *context, WMShared *shared ) { int i; DFBResult ret; DFBRectangle rects[8]; StretRegionFlags flags = SRF_ACTIVE | SRF_OUTPUT; D_MAGIC_ASSERT( window, UniqueWindow ); D_MAGIC_ASSERT( context, UniqueContext ); D_MAGIC_ASSERT( shared, WMShared ); foo_rects( window, context, shared, rects ); if (! (window->options & DWOP_GHOST)) flags |= SRF_INPUT; for (i=0; i<8; i++) { ret = stret_region_create( shared->region_classes[URCI_FOO], window, i, flags, 1, DFB_RECTANGLE_VALS( &rects[i] ), window->frame, UNFL_FOREGROUND, context->shmpool, &window->foos[i] ); if (ret) goto error; } return DFB_OK; error: for (--i; i>0; --i) stret_region_destroy( window->foos[i] ); return ret; } static DFBResult create_regions( UniqueWindow *window ) { DFBResult ret; UniqueContext *context; WMShared *shared; StretRegionFlags flags = SRF_ACTIVE; D_MAGIC_ASSERT( window, UniqueWindow ); context = window->context; D_MAGIC_ASSERT( context, UniqueContext ); shared = context->shared; D_MAGIC_ASSERT( shared, WMShared ); if (! (window->options & DWOP_GHOST)) flags |= SRF_INPUT; if (! (window->caps & DWCAPS_INPUTONLY)) flags |= SRF_OUTPUT; if (window->options & DWOP_SHAPED) flags |= SRF_SHAPED; /* Frame */ ret = stret_region_create( shared->region_classes[URCI_FRAME], window, 0, SRF_NONE, _UNFL_NUM, DFB_RECTANGLE_VALS( &window->full ), context->root, UNRL_USER, context->shmpool, &window->frame ); if (ret) return ret; /* Content */ ret = stret_region_create( shared->region_classes[URCI_WINDOW], window, true, flags, 1, window->insets.l, window->insets.t, window->bounds.w, window->bounds.h, window->frame, UNFL_CONTENT, context->shmpool, &window->region ); if (ret) { stret_region_destroy( window->frame ); return ret; } /* Foos */ if (D_FLAGS_IS_SET( window->flags, UWF_DECORATED )) { ret = create_foos( window, context, shared ); if (ret) { stret_region_destroy( window->region ); stret_region_destroy( window->frame ); return ret; } } return DFB_OK; }