Exemple #1
0
void
dfb_window_putbelow( CoreWindow *window,
                     CoreWindow *upper )
{
     int              index;
     int              upper_index;
     bool             update = false;
     CoreWindowStack *stack  = window->stack;

     stack_lock( stack );

     index = get_window_index( window );
     if (index < 0) {
          stack_unlock( stack );
          return;
     }

     upper_index = get_window_index( upper );
     if (upper_index < 0) {
          stack_unlock( stack );
          return;
     }

     if (index > upper_index)
          update = window_restack( stack, index, upper_index );
     else
          update = window_restack( stack, index, upper_index - 1 );

     if (update)
          window_restacked( window );
     
     stack_unlock( stack );
}
Exemple #2
0
void
dfb_window_putatop( CoreWindow *window,
                    CoreWindow *lower )
{
     int              index;
     int              lower_index;
     bool             update = false;
     CoreWindowStack *stack  = window->stack;

     stack_lock( stack );

     index = get_window_index( window );
     if (index < 0) {
          stack_unlock( stack );
          return;
     }

     lower_index = get_window_index( lower );
     if (lower_index < 0) {
          stack_unlock( stack );
          return;
     }

     if (index < lower_index)
          update = window_restack( stack, index, lower_index );
     else
          update = window_restack( stack, index, lower_index + 1 );

     if (update)
          window_restacked( window );

     stack_unlock( stack );
}
Exemple #3
0
DFBResult
dfb_window_resize( CoreWindow   *window,
                   int           width,
                   int           height )
{
     DFBWindowEvent   evt;
     CoreWindowStack *stack = window->stack;
     int              ow    = window->width;
     int              oh    = window->height;

     stack_lock( stack );

     if (window->surface) {
          DFBResult ret = dfb_surface_reformat( window->surface,
                                                width, height,
                                                window->surface->format );
          if (ret) {
               stack_unlock( stack );
               return ret;
          }

          window->width = window->surface->width;
          window->height = window->surface->height;
     } else {
          window->width  = width;
          window->height = height;
     }

     if (VISIBLE_WINDOW (window)) {
          if (ow > window->width) {
               DFBRegion region = { window->x + window->width, window->y,
                                    window->x + ow - 1,
                                    window->y + MIN(window->height, oh) - 1 };
								
               repaint_stack( stack, &region, 0 );
          }

          if (oh > window->height) {
               DFBRegion region = { window->x, window->y + window->height,
                                    window->x + MAX(window->width, ow) - 1,
                                    window->y + oh - 1 };
		
               repaint_stack( stack, &region, 0 );
          }
     }

     /* Send new size */
     evt.type = DWET_SIZE;
     evt.w = window->width;
     evt.h = window->height;
     dfb_window_dispatch( window, &evt );

     stack_unlock( stack );
     
     return DFB_OK;
}
Exemple #4
0
/*
 *	stack_collect:
 *
 *	Free excess kernel stacks, may
 *	block.
 */
void
stack_collect(void)
{
	if (stack_collect_tick != last_stack_tick) {
		unsigned int	target;
		vm_offset_t		stack;
		spl_t			s;

		s = splsched();
		stack_lock();

		target = stack_free_target + (STACK_CACHE_SIZE * processor_count);
		target += (stack_free_delta >= 0)? stack_free_delta: -stack_free_delta;

		while (stack_free_count > target) {
			stack = stack_free_list;
			stack_free_list = stack_next(stack);
			stack_free_count--; stack_total--;
			stack_unlock();
			splx(s);

			/*
			 * Get the stack base address, then decrement by one page
			 * to account for the lower guard page.  Add two extra pages
			 * to the size to account for the guard pages on both ends
			 * that were originally requested when the stack was allocated
			 * back in stack_alloc().
			 */

			stack = (vm_offset_t)vm_map_trunc_page(
				stack,
				VM_MAP_PAGE_MASK(kernel_map));
			stack -= PAGE_SIZE;
			if (vm_map_remove(
				    kernel_map,
				    stack,
				    stack + kernel_stack_size+(2*PAGE_SIZE),
				    VM_MAP_REMOVE_KUNWIRE)
			    != KERN_SUCCESS)
				panic("stack_collect: vm_map_remove");
			stack = 0;

			s = splsched();
			stack_lock();

			target = stack_free_target + (STACK_CACHE_SIZE * processor_count);
			target += (stack_free_delta >= 0)? stack_free_delta: -stack_free_delta;
		}

		last_stack_tick = stack_collect_tick;

		stack_unlock();
		splx(s);
	}
}
Exemple #5
0
void
stack_fake_zone_info(int *count, 
		     vm_size_t *cur_size, vm_size_t *max_size, vm_size_t *elem_size, vm_size_t *alloc_size,
		     uint64_t *sum_size, int *collectable, int *exhaustable, int *caller_acct)
{
	unsigned int	total, hiwat, free;
	unsigned long long all;
	spl_t			s;

	s = splsched();
	stack_lock();
	all = stack_allocs;
	total = stack_total;
	hiwat = stack_hiwat;
	free = stack_free_count;
	stack_unlock();
	splx(s);

	*count      = total - free;
	*cur_size   = kernel_stack_size * total;
	*max_size   = kernel_stack_size * hiwat;
	*elem_size  = kernel_stack_size;
	*alloc_size = kernel_stack_size;
	*sum_size = all * kernel_stack_size;

	*collectable = 1;
	*exhaustable = 0;
	*caller_acct = 1;
}
Exemple #6
0
void
dfb_window_repaint( CoreWindow          *window,
                    DFBRegion           *region,
                    DFBSurfaceFlipFlags  flags )
{
     CoreWindowStack *stack = window->stack;

     if (!VISIBLE_WINDOW(window))
          return;

     stack_lock( stack );
     
     if (region) {
          region->x1 += window->x;
          region->x2 += window->x;
          region->y1 += window->y;
          region->y2 += window->y;

          repaint_stack( stack, region, flags );
     }
     else {
          DFBRegion reg = { window->x, window->y,
                            window->x + window->width - 1,
                            window->y + window->height - 1 };

          repaint_stack( stack, &reg, flags );
     }
     
     stack_unlock( stack );
}
Exemple #7
0
void
stack_free_stack(
	vm_offset_t		stack)
{
	struct stack_cache	*cache;
	spl_t				s;

	s = splsched();
	cache = &PROCESSOR_DATA(current_processor(), stack_cache);
	if (cache->count < STACK_CACHE_SIZE) {
		stack_next(stack) = cache->free;
		cache->free = stack;
		cache->count++;
	}
	else {
		stack_lock();
		stack_next(stack) = stack_free_list;
		stack_free_list = stack;
		if (++stack_free_count > stack_free_hiwat)
			stack_free_hiwat = stack_free_count;
		stack_free_delta++;
		stack_unlock();
	}
	splx(s);
}
Exemple #8
0
/*
 *	stack_alloc_try:
 *
 *	Non-blocking attempt to allocate a
 *	stack for a thread.
 *
 *	Returns TRUE on success.
 *
 *	Called at splsched.
 */
boolean_t
stack_alloc_try(
	thread_t		thread)
{
	struct stack_cache	*cache;
	vm_offset_t			stack;

	cache = &PROCESSOR_DATA(current_processor(), stack_cache);
	stack = cache->free;
	if (stack != 0) {
		cache->free = stack_next(stack);
		cache->count--;
	}
	else {
		if (stack_free_list != 0) {
			stack_lock();
			stack = stack_free_list;
			if (stack != 0) {
				stack_free_list = stack_next(stack);
				stack_free_count--;
				stack_free_delta--;
			}
			stack_unlock();
		}
	}

	if (stack != 0 || (stack = thread->reserved_stack) != 0) {
		machine_stack_attach(thread, stack);
		return (TRUE);
	}

	return (FALSE);
}
Exemple #9
0
void
dfb_windowstack_repaint_all( CoreWindowStack *stack )
{
     DFBRegion region = { 0, 0, stack->width - 1, stack->height - 1 };

     stack_lock( stack );
     repaint_stack( stack, &region, 0 );
     stack_unlock( stack );
}
Exemple #10
0
/*
 *	stack_alloc:
 *
 *	Allocate a stack for a thread, may
 *	block.
 */
void
stack_alloc(
	thread_t	thread)
{
	vm_offset_t		stack;
	spl_t			s;
	int			guard_flags;

	assert(thread->kernel_stack == 0);

	s = splsched();
	stack_lock();
	stack = stack_free_list;
	if (stack != 0) {
		stack_free_list = stack_next(stack);
		stack_free_count--;
	}
	else {
		if (++stack_total > stack_hiwat)
			stack_hiwat = stack_total;
		stack_new_count++;
	}
	stack_free_delta--;
	stack_unlock();
	splx(s);
		
	if (stack == 0) {

		/*
		 * Request guard pages on either side of the stack.  Ask
		 * kernel_memory_allocate() for two extra pages to account
		 * for these.
		 */

		guard_flags = KMA_GUARD_FIRST | KMA_GUARD_LAST;
		if (kernel_memory_allocate(kernel_map, &stack,
					   KERNEL_STACK_SIZE + (2*PAGE_SIZE),
					   stack_addr_mask,
					   KMA_KOBJECT | guard_flags)
		    != KERN_SUCCESS)
			panic("stack_alloc: kernel_memory_allocate");

		/*
		 * The stack address that comes back is the address of the lower
		 * guard page.  Skip past it to get the actual stack base address.
		 */

		stack += PAGE_SIZE;
	}

	machine_stack_attach(thread, stack);
}
Exemple #11
0
void
dfb_window_request_focus( CoreWindow *window )
{
     CoreWindowStack *stack = window->stack;

     DFB_ASSERT( !(window->options & DWOP_GHOST) );

     stack_lock( stack );
     
     switch_focus( stack, window );
     
     stack_unlock( stack );
}
Exemple #12
0
void
dfb_window_raisetotop( CoreWindow *window )
{
     int              index;
     bool             update = false;
     CoreWindowStack *stack  = window->stack;

     stack_lock( stack );

     index = get_window_index( window );
     if (index < 0) {
          stack_unlock( stack );
          return;
     }

     update = window_restack( stack, index, stack->num_windows - 1 );

     if (update)
          window_restacked( window );
     
     stack_unlock( stack );
}
Exemple #13
0
void
dfb_window_lowertobottom( CoreWindow *window )
{
     int              index;
     bool             update = false;
     CoreWindowStack *stack  = window->stack;

     stack_lock( stack );

     index = get_window_index( window );
     if (index < 0) {
          stack_unlock( stack );
          return;
     }

     update = window_restack( stack, index, 0 );

     if (update)
          window_restacked( window );

     stack_unlock( stack );
}
Exemple #14
0
DFBResult
dfb_window_ungrab_keyboard( CoreWindow *window )
{
     CoreWindowStack *stack = window->stack;

     stack_lock( stack );

     if (stack->keyboard_window == window)
          stack->keyboard_window = NULL;

     stack_unlock( stack );

     return DFB_OK;
}
Exemple #15
0
void
dfb_window_deinit( CoreWindow *window )
{
     CoreWindowStack *stack = window->stack;

     DEBUGMSG("DirectFB/core/windows: dfb_window_deinit (%p) entered\n", window);

     if (stack) {
          stack_lock( stack );
          window_remove( window );
          stack_unlock( stack );
     }
     
     DEBUGMSG("DirectFB/core/windows: dfb_window_deinit (%p) exitting\n", window);
}
Exemple #16
0
void
dfb_window_init( CoreWindow *window )
{
     int i;
     CoreWindowStack *stack = window->stack;

     stack_lock( stack );
     
     for (i=0; i<stack->num_windows; i++)
          if (stack->windows[i]->caps & DWHC_TOPMOST)
               break;

     window_insert( window, i );
     
     stack_unlock( stack );
}
Exemple #17
0
DFBResult
dfb_window_ungrab_pointer( CoreWindow *window )
{
     CoreWindowStack *stack = window->stack;

     stack_lock( stack );

     if (stack->pointer_window == window) {
          stack->pointer_window = NULL;

          handle_enter_leave_focus( stack );
     }

     stack_unlock( stack );
     
     return DFB_OK;
}
Exemple #18
0
DFBResult
dfb_window_grab_pointer( CoreWindow *window )
{
     DFBResult        retval = DFB_OK;
     CoreWindowStack *stack  = window->stack;

     stack_lock( stack );

     if (stack->pointer_window)
          retval = DFB_LOCKED;
     else
          stack->pointer_window = window;

     stack_unlock( stack );

     return retval;
}
Exemple #19
0
void
dfb_window_set_opacity( CoreWindow *window,
                        __u8        opacity )
{
     int              old_opacity = window->opacity;
     CoreWindowStack *stack       = window->stack;

     if (!dfb_config->translucent_windows && opacity)
          opacity = 0xFF;

     if (old_opacity != opacity) {
          DFBRegion region = { window->x, window->y,
                               window->x + window->width - 1,
                               window->y + window->height - 1 };

          stack_lock( stack );
          
          window->opacity = opacity;

          repaint_stack( stack, &region, 0 );

          /* Check focus after window appeared or disappeared */
          if ((!old_opacity && opacity) || !opacity)
               handle_enter_leave_focus( stack );
          
          /* If window disappeared... */
          if (!opacity) {
               /* Detract focus if it's still focused */
               if (stack->focused_window == window)
                    switch_focus( stack, NULL );
               
               /* Ungrab pointer/keyboard */
               window_withdraw( window );
          }
          
          /* Always try to have a focused window */
          ensure_focus( stack );
          
          stack_unlock( stack );
     }
}
Exemple #20
0
void
dfb_window_move( CoreWindow *window,
                 int         dx,
                 int         dy )
{
     DFBWindowEvent   evt;
     CoreWindowStack *stack = window->stack;

     stack_lock( stack );
     
     window->x += dx;
     window->y += dy;

     if (VISIBLE_WINDOW(window)) {
          DFBRegion region = { window->x, window->y,
                               window->x + window->width - 1,
                               window->y + window->height - 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;

          repaint_stack( stack, &region, 0 );
     }

     /* Send new position */
     evt.type = DWET_POSITION;
     evt.x = window->x;
     evt.y = window->y;
     dfb_window_dispatch( window, &evt );

     stack_unlock( stack );
}
Exemple #21
0
void
stack_fake_zone_info(int *count, vm_size_t *cur_size, vm_size_t *max_size, vm_size_t *elem_size,
		     vm_size_t *alloc_size, int *collectable, int *exhaustable)
{
	unsigned int	total, hiwat, free;
	spl_t			s;

	s = splsched();
	stack_lock();
	total = stack_total;
	hiwat = stack_hiwat;
	free = stack_free_count;
	stack_unlock();
	splx(s);

	*count      = total - free;
	*cur_size   = KERNEL_STACK_SIZE * total;
	*max_size   = KERNEL_STACK_SIZE * hiwat;
	*elem_size  = KERNEL_STACK_SIZE;
	*alloc_size = KERNEL_STACK_SIZE;
	*collectable = 1;
	*exhaustable = 0;
}
Exemple #22
0
/*
 *	compute_stack_target:
 *
 *	Computes a new target free list count
 *	based on recent alloc / free activity.
 *
 *	Limits stack collection to once per
 *	computation period.
 */
void
compute_stack_target(
__unused void		*arg)
{
	spl_t		s;

	s = splsched();
	stack_lock();

	if (stack_free_target > 5)
		stack_free_target = (4 * stack_free_target) / 5;
	else
	if (stack_free_target > 0)
		stack_free_target--;

	stack_free_target += (stack_free_delta >= 0)? stack_free_delta: -stack_free_delta;

	stack_free_delta = 0;
	stack_collect_tick++;

	stack_unlock();
	splx(s);
}
Exemple #23
0
static ReactionResult
stack_inputdevice_react( const void *msg_data,
                         void       *ctx )
{
     const DFBInputEvent *evt = (DFBInputEvent*)msg_data;

     DFBWindowEvent   we;
     CoreWindow      *window = NULL;
     CoreWindowStack *stack  = (CoreWindowStack*)ctx;
     DisplayLayer    *layer  = dfb_layer_at( stack->layer_id );

     /* FIXME: this is a bad check for exclusive access */
     if (dfb_layer_lease( layer ) )
          return RS_OK;

     dfb_layer_release( layer, false );

     if (stack->wm_hack) {
          switch (evt->type) {
               case DIET_KEYRELEASE:
                    switch (evt->key_symbol) {
                         case DIKS_CAPS_LOCK:
                              stack->wm_hack = 0;
                              stack_lock( stack );
                              handle_enter_leave_focus( stack );
                              stack_unlock( stack );
                              break;

                         case DIKS_CONTROL:
                              stack->wm_hack = 1;
                              return RS_OK;

                         default:
                              ;
                    }
                    break;

               case DIET_KEYPRESS:
                    switch (DFB_LOWER_CASE(evt->key_symbol)) {
                         case DIKS_CONTROL:
                              stack->wm_hack = 2;
                              return RS_OK;

                         case DIKS_SMALL_C:
                              if (stack->entered_window) {
                                   DFBWindowEvent evt;
                                   evt.type = DWET_CLOSE;
                                   dfb_window_dispatch( stack->entered_window, &evt );
                              }
                              return RS_OK;

                         case DIKS_SMALL_D: {
                              CoreWindow *window = stack->entered_window;

                              if (window &&
                                  !(window->options & DWOP_INDESTRUCTIBLE))
                              {
                                   dfb_window_deinit( window );
                                   dfb_window_destroy( window, true );
                              }

                              return RS_OK;
                         }

                         default:
                              ;
                    }
                    break;

               case DIET_BUTTONRELEASE:
                    return RS_OK;

               case DIET_BUTTONPRESS:
                    if (stack->entered_window &&
                        !(stack->entered_window->options & DWOP_KEEP_STACKING))
                         dfb_window_raisetotop( stack->entered_window );
                    return RS_OK;

               default:
                    ;
          }
     }

     switch (evt->type) {
          case DIET_KEYPRESS:
               if (evt->key_id == DIKI_CAPS_LOCK)
                    stack->wm_hack = 1;
               /* fall through */
          case DIET_KEYRELEASE:
               stack_lock( stack );
               
               window = (stack->keyboard_window ?
                         stack->keyboard_window : stack->focused_window);

               if (window) {
                    we.type = (evt->type == DIET_KEYPRESS) ? DWET_KEYDOWN :
                                                             DWET_KEYUP;
                    we.key_code   = evt->key_code;
                    we.key_id     = evt->key_id;
                    we.key_symbol = evt->key_symbol;
                    we.modifiers  = evt->modifiers; /* FIXME: handle mult. devices */
                    we.locks      = evt->locks; /* FIXME: handle mult. devices */

                    dfb_window_dispatch( window, &we );
               }
               
               stack_unlock( stack );

               break;
          case DIET_BUTTONPRESS:
          case DIET_BUTTONRELEASE:
               if (!stack->cursor.enabled)
                    break;

               stack_lock( stack );
               
               window = (stack->pointer_window ?
                         stack->pointer_window : stack->entered_window);

               if (window) {
                    we.type = (evt->type == DIET_BUTTONPRESS) ? DWET_BUTTONDOWN :
                                                                DWET_BUTTONUP;
                    we.button  = evt->button;
                    we.buttons = evt->buttons; /* FIXME: handle mult. devices */
                    we.cx      = stack->cursor.x;
                    we.cy      = stack->cursor.y;
                    we.x       = we.cx - window->x;
                    we.y       = we.cy - window->y;

                    dfb_window_dispatch( window, &we );
               }

               stack_unlock( stack );
               
               break;
          case DIET_AXISMOTION:
               if (evt->flags & DIEF_AXISREL) {
                    int rel = evt->axisrel;

                    /* handle cursor acceleration */
                    if (rel > stack->cursor.threshold)
                         rel += (rel - stack->cursor.threshold)
                                   * stack->cursor.numerator
                                   / stack->cursor.denominator;
                    else if (rel < -stack->cursor.threshold)
                         rel += (rel + stack->cursor.threshold)
                                   * stack->cursor.numerator
                                   / stack->cursor.denominator;

                    switch (evt->axis) {
                         case DIAI_X:
                              dfb_windowstack_handle_motion( stack, rel, 0 );
                              break;
                         case DIAI_Y:
                              dfb_windowstack_handle_motion( stack, 0, rel );
                              break;
                         case DIAI_Z:
                              handle_wheel( stack, - evt->axisrel );
                              break;
                         default:
                              return RS_OK;
                    }
               }
               else if (evt->flags & DIEF_AXISABS) {
                    switch (evt->axis) {
                         case DIAI_X:
                              dfb_windowstack_handle_motion( stack,
                                                             evt->axisabs - stack->cursor.x, 0 );
                              break;
                         case DIAI_Y:
                              dfb_windowstack_handle_motion( stack, 0,
                                                             evt->axisabs - stack->cursor.y);
                              break;
                         default:
                              return RS_OK;
                    }
               }
               break;
          default:
               break;
     }

     return RS_OK;
}
Exemple #24
0
void
dfb_windowstack_handle_motion( CoreWindowStack *stack,
                               int              dx,
                               int              dy )
{
     int            new_cx, new_cy;
     DFBWindowEvent we;

     DFB_ASSERT( stack != NULL );

     if (!stack->cursor.enabled)
          return;

     new_cx = MIN( stack->cursor.x + dx, stack->cursor.region.x2);
     new_cy = MIN( stack->cursor.y + dy, stack->cursor.region.y2);

     new_cx = MAX( new_cx, stack->cursor.region.x1 );
     new_cy = MAX( new_cy, stack->cursor.region.y1 );

     if (new_cx == stack->cursor.x  &&  new_cy == stack->cursor.y) {
          stack_unlock( stack );
          return;
     }

     dx = new_cx - stack->cursor.x;
     dy = new_cy - stack->cursor.y;

     stack->cursor.x = new_cx;
     stack->cursor.y = new_cy;

     DFB_ASSERT( stack->cursor.window != NULL );

     dfb_window_move( stack->cursor.window, dx, dy );

     switch (stack->wm_hack) {
          case 2: {
               CoreWindow *window = stack->entered_window;
               
               if (window && !(window->options & DWOP_KEEP_SIZE)) {
                    int width  = window->width  + dx;
                    int height = window->height + dy;

                    if (width  <   48) width  = 48;
                    if (height <   48) height = 48;
                    if (width  > 2048) width  = 2048;
                    if (height > 2048) height = 2048;

                    if (width != window->width || height != window->height)
                         dfb_window_resize( window, width, height );
               }

               break;
          }

          case 1: {
               CoreWindow *window = stack->entered_window;

               if (window && !(window->options & DWOP_KEEP_POSITION))
                    dfb_window_move( window, dx, dy );

               break;
          }

          case 0:
               stack_lock( stack );

               we.cx   = stack->cursor.x;
               we.cy   = stack->cursor.y;

               if (stack->pointer_window) {
                    we.type = DWET_MOTION;
                    we.x    = we.cx - stack->pointer_window->x;
                    we.y    = we.cy - stack->pointer_window->y;
          
                    dfb_window_dispatch( stack->pointer_window, &we );
               }
               else {
                    if (!handle_enter_leave_focus( stack )
                        && stack->entered_window)
                    {
                         we.type = DWET_MOTION;
                         we.x    = we.cx - stack->entered_window->x;
                         we.y    = we.cy - stack->entered_window->y;
          
                         dfb_window_dispatch( stack->entered_window, &we );
                    }
               }

               stack_unlock( stack );

               break;

          default:
               ;
     }

     HEAVYDEBUGMSG("DirectFB/windows: mouse at %d, %d\n", stack->cursor.x, stack->cursor.y);
}
Exemple #25
0
void
dfb_window_change_stacking( CoreWindow             *window,
                            DFBWindowStackingClass  stacking )
{
     int              index, i;
     bool             update = false;
     CoreWindowStack *stack  = window->stack;

     stack_lock( stack );

     if (stacking == window->stacking) {
          stack_unlock( stack );
          return;
     }
     
     index = get_window_index( window );
     if (index < 0) {
          stack_unlock( stack );
          return;
     }

     switch (stacking) {
          case DWSC_LOWER:
               /* become the top lower class window */
               for (i=index; i>0; i--) {
                    if (stack->windows[i-1]->stacking == DWSC_LOWER)
                         break;
               }
               break;

          case DWSC_UPPER:
               /* become the bottom upper class window */
               for (i=index; i<stack->num_windows-1; i++) {
                    if (stack->windows[i+1]->stacking == DWSC_UPPER)
                         break;
               }
               break;

          case DWSC_MIDDLE:
               if (window->stacking == DWSC_UPPER) {
                    /* become the top middle class window */
                    for (i=index; i>0; i--) {
                         if (stack->windows[i-1]->stacking != DWSC_UPPER)
                              break;
                    }
               }
               else {
                    /* become the bottom middle class window */
                    for (i=index; i<stack->num_windows-1; i++) {
                         if (stack->windows[i+1]->stacking != DWSC_LOWER)
                              break;
                    }
               }
               break;
          
          default:
               BUG("unknown stacking class");
               stack_unlock( stack );
               return;
     }

     update = window_restack( stack, index, i );

     if (update)
          window_restacked( window );
     
     stack_unlock( stack );
}