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 ); }
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 ); }
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, ®ion, 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, ®ion, 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; }
/* * 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); } }
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; }
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, ®, flags ); } stack_unlock( stack ); }
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); }
/* * 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); }
void dfb_windowstack_repaint_all( CoreWindowStack *stack ) { DFBRegion region = { 0, 0, stack->width - 1, stack->height - 1 }; stack_lock( stack ); repaint_stack( stack, ®ion, 0 ); stack_unlock( stack ); }
/* * 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); }
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 ); }
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 ); }
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 ); }
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; }
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); }
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 ); }
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; }
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; }
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, ®ion, 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 ); } }
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, ®ion, 0 ); } /* Send new position */ evt.type = DWET_POSITION; evt.x = window->x; evt.y = window->y; dfb_window_dispatch( window, &evt ); stack_unlock( stack ); }
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; }
/* * 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); }
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; }
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); }
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 ); }