void dfb_updates_add( DFBUpdates *updates, const DFBRegion *region ) { int i; D_MAGIC_ASSERT( updates, DFBUpdates ); DFB_REGION_ASSERT( region ); D_ASSERT( updates->regions != NULL ); D_ASSERT( updates->num_regions >= 0 ); D_ASSERT( updates->num_regions <= updates->max_regions ); D_DEBUG_AT( DFB_Updates, "%s( %p, %4d,%4d-%4dx%4d )\n", __FUNCTION__, (void*)updates, DFB_RECTANGLE_VALS_FROM_REGION(region) ); if (updates->num_regions == 0) { D_DEBUG_AT( DFB_Updates, " -> added as first\n" ); updates->regions[0] = updates->bounding = *region; updates->num_regions = 1; return; } for (i=0; i<updates->num_regions; i++) { if (dfb_region_region_extends( &updates->regions[i], region ) || dfb_region_region_intersects( &updates->regions[i], region )) { D_DEBUG_AT( DFB_Updates, " -> combined with [%d] %4d,%4d-%4dx%4d\n", i, DFB_RECTANGLE_VALS_FROM_REGION(&updates->regions[i]) ); dfb_region_region_union( &updates->regions[i], region ); dfb_region_region_union( &updates->bounding, region ); D_DEBUG_AT( DFB_Updates, " -> resulting in [%d] %4d,%4d-%4dx%4d\n", i, DFB_RECTANGLE_VALS_FROM_REGION(&updates->regions[i]) ); return; } } if (updates->num_regions == updates->max_regions) { dfb_region_region_union( &updates->bounding, region ); updates->regions[0] = updates->bounding; updates->num_regions = 1; D_DEBUG_AT( DFB_Updates, " -> collapsing to [0] %4d,%4d-%4dx%4d\n", DFB_RECTANGLE_VALS_FROM_REGION(&updates->regions[0]) ); } else { updates->regions[updates->num_regions++] = *region; dfb_region_region_union( &updates->bounding, region ); D_DEBUG_AT( DFB_Updates, " -> added as [%d] %4d,%4d-%4dx%4d\n", updates->num_regions - 1, DFB_RECTANGLE_VALS_FROM_REGION(&updates->regions[updates->num_regions - 1]) ); } }
void dfb_updates_add( DFBUpdates *updates, const DFBRegion *region ) { int i; D_MAGIC_ASSERT( updates, DFBUpdates ); DFB_REGION_ASSERT( region ); D_ASSERT( updates->regions != NULL ); D_ASSERT( updates->num_regions >= 0 ); D_ASSERT( updates->num_regions <= updates->max_regions ); if (updates->num_regions == 0) { updates->regions[0] = updates->bounding = *region; updates->num_regions = 1; return; } for (i=0; i<updates->num_regions; i++) { DFBRegion inter = updates->regions[i]; if (dfb_region_region_intersect( &inter, region )) { DFBRegion uni = updates->regions[i]; dfb_region_region_union( &uni, region ); updates->regions[i] = uni; dfb_region_region_union( &updates->bounding, &uni ); return; } } if (updates->num_regions == updates->max_regions) { dfb_region_region_union( &updates->bounding, region ); updates->regions[0] = updates->bounding; updates->num_regions = 1; } else { updates->regions[updates->num_regions++] = *region; dfb_region_region_union( &updates->bounding, region ); } }
static DFBResult dfb_sdl_update_screen_handler( const DFBRegion *region ) { DFBRegion update; CoreSurface *surface = dfb_sdl->primary; DFB_REGION_ASSERT_IF( region ); if (region) update = *region; else { update.x1 = 0; update.y1 = 0; update.x2 = surface->config.size.w - 1; update.y2 = surface->config.size.h - 1; } #if 0 pthread_mutex_lock( &dfb_sdl->update.lock ); if (dfb_sdl->update.pending) dfb_region_region_union( &dfb_sdl->update.region, &update ); else { dfb_sdl->update.region = update; dfb_sdl->update.pending = true; } pthread_cond_signal( &dfb_sdl->update.cond ); pthread_mutex_unlock( &dfb_sdl->update.lock ); #else if (surface->config.caps & DSCAPS_FLIPPING) SDL_Flip( dfb_sdl->screen ); else SDL_UpdateRect( dfb_sdl->screen, DFB_RECTANGLE_VALS_FROM_REGION(&update) ); #endif return DFB_OK; }
/* HACK: implementation dumped in here for now, will move into context */ static DFBResult wm_update_cursor( CoreWindowStack *stack, void *wm_data, void *stack_data, CoreCursorUpdateFlags flags ) { DFBResult ret; DFBRegion old_region; WMData *wmdata = wm_data; StackData *data = stack_data; bool restored = false; CoreLayer *layer; CoreLayerRegion *region; CardState *state; CoreSurface *surface; UniqueContext *context; D_ASSERT( stack != NULL ); D_ASSERT( stack->context != NULL ); D_ASSERT( wm_data != NULL ); D_ASSERT( stack_data != NULL ); D_MAGIC_ASSERT( data, StackData ); context = data->context; D_MAGIC_ASSERT( context, UniqueContext ); /* Optimize case of invisible cursor moving. */ if (!(flags & ~(CCUF_POSITION | CCUF_SHAPE)) && (!stack->cursor.opacity || !stack->cursor.enabled)) { context->cursor_bs_valid = false; return DFB_OK; } layer = dfb_layer_at( context->layer_id ); state = &layer->state; region = context->region; surface = context->surface; D_ASSERT( region != NULL ); D_ASSERT( surface != NULL ); if (flags & CCUF_ENABLE) { CoreSurface *cursor_bs; DFBSurfaceCapabilities caps = DSCAPS_NONE; dfb_surface_caps_apply_policy( stack->cursor.policy, &caps ); D_ASSERT( context->cursor_bs == NULL ); /* Create the cursor backing store surface. */ ret = dfb_surface_create_simple( wmdata->core, stack->cursor.size.w, stack->cursor.size.h, region->config.format, region->config.colorspace, caps, CSTF_SHARED | CSTF_CURSOR, 0, /* FIXME: no shared cursor objects, no cursor id */ NULL, &cursor_bs ); if (ret) { D_ERROR( "WM/Default: Failed creating backing store for cursor!\n" ); return ret; } ret = dfb_surface_globalize( cursor_bs ); D_ASSERT( ret == DFB_OK ); /* Ensure valid back buffer for now. * FIXME: Keep a flag to know when back/front have been swapped and need a sync. */ switch (region->config.buffermode) { case DLBM_BACKVIDEO: case DLBM_TRIPLE: dfb_gfx_copy( surface, surface, NULL ); break; default: break; } context->cursor_bs = cursor_bs; } else { D_ASSERT( context->cursor_bs != NULL ); /* restore region under cursor */ if (context->cursor_drawn) { DFBRectangle rect = { 0, 0, context->cursor_region.x2 - context->cursor_region.x1 + 1, context->cursor_region.y2 - context->cursor_region.y1 + 1 }; D_ASSERT( stack->cursor.opacity || (flags & CCUF_OPACITY) ); D_ASSERT( context->cursor_bs_valid ); dfb_gfx_copy_to( context->cursor_bs, surface, &rect, context->cursor_region.x1, context->cursor_region.y1, false ); context->cursor_drawn = false; old_region = context->cursor_region; restored = true; } if (flags & CCUF_SIZE) { ret = dfb_surface_reformat( context->cursor_bs, stack->cursor.size.w, stack->cursor.size.h, context->cursor_bs->config.format ); if (ret) { D_ERROR( "WM/Default: Failed resizing backing store for cursor!\n" ); return ret; } } } if (flags & (CCUF_ENABLE | CCUF_POSITION | CCUF_SIZE | CCUF_OPACITY)) { context->cursor_bs_valid = false; context->cursor_region.x1 = stack->cursor.x - stack->cursor.hot.x; context->cursor_region.y1 = stack->cursor.y - stack->cursor.hot.y; context->cursor_region.x2 = context->cursor_region.x1 + stack->cursor.size.w - 1; context->cursor_region.y2 = context->cursor_region.y1 + stack->cursor.size.h - 1; if (!dfb_region_intersect( &context->cursor_region, 0, 0, stack->width - 1, stack->height - 1 )) { D_BUG( "invalid cursor region" ); return DFB_BUG; } } D_ASSERT( context->cursor_bs != NULL ); if (flags & CCUF_DISABLE) { dfb_surface_unlink( &context->cursor_bs ); } else if (stack->cursor.opacity) { /* backup region under cursor */ if (!context->cursor_bs_valid) { DFBRectangle rect = DFB_RECTANGLE_INIT_FROM_REGION( &context->cursor_region ); D_ASSERT( !context->cursor_drawn ); /* FIXME: this requires using blitted flipping all the time, but fixing it seems impossible, for now DSFLIP_BLIT is forced in repaint_stack() when the cursor is enabled. */ dfb_gfx_copy_to( surface, context->cursor_bs, &rect, 0, 0, true ); context->cursor_bs_valid = true; } /* Set destination. */ state->destination = surface; state->modified |= SMF_DESTINATION; /* Set clipping region. */ dfb_state_set_clip( state, &context->cursor_region ); /* draw cursor */ unique_draw_cursor( stack, context, state, &context->cursor_region ); /* Reset destination. */ state->destination = NULL; state->modified |= SMF_DESTINATION; context->cursor_drawn = true; if (restored) { if (dfb_region_region_intersects( &old_region, &context->cursor_region )) dfb_region_region_union( &old_region, &context->cursor_region ); else dfb_layer_region_flip_update( region, &context->cursor_region, DSFLIP_BLIT ); dfb_layer_region_flip_update( region, &old_region, DSFLIP_BLIT ); } else dfb_layer_region_flip_update( region, &context->cursor_region, DSFLIP_BLIT ); } else if (restored) dfb_layer_region_flip_update( region, &old_region, DSFLIP_BLIT ); return DFB_OK; }
/* * Input thread reading from device. * Generates events on incoming data. */ static void* x11EventThread( DirectThread *thread, void *driver_data ) { X11InputData *data = driver_data; DFBX11 *x11 = data->x11; int x11_fd = ConnectionNumber(x11->display); XExposeEvent expose_event = { 0 }; fd_set in_fds; struct timeval tv; while (!data->stop) { unsigned int pull = 2000; XEvent xEvent; DFBInputEvent dfbEvent; static int nextKeyIsRepeat = false; /* FIXME: Detect key repeats, we're receiving KeyPress, KeyRelease, KeyPress, KeyRelease... !!?? */ if (expose_event.type) { // handle_expose_Async( x11, &expose_event ); expose_event.type = 0; } // Create a File Description Set containing x11_fd FD_ZERO(&in_fds); FD_SET(x11_fd, &in_fds); // Set our timer. tv.tv_sec = 0; tv.tv_usec = 20000; // Wait for X Event or a Timer if (select(x11_fd+1, &in_fds, 0, 0, &tv)) { XLockDisplay( x11->display ); while (!data->stop && pull-- && XPending( x11->display )) { XNextEvent( x11->display, &xEvent ); //D_INFO_LINE_MSG("x11 event %d",xEvent.type); /* is this key repeat? idea from GII */ if ( (xEvent.type == KeyRelease) && (XPending( x11->display )) ) { XEvent peekEvent; XPeekEvent( x11->display, &peekEvent ); if ( (peekEvent.type == KeyPress) && (peekEvent.xkey.keycode == xEvent.xkey.keycode) && (peekEvent.xkey.time - xEvent.xkey.time < 2) ) { nextKeyIsRepeat = true; } } XUnlockDisplay( x11->display ); D_DEBUG_AT( X11_Input, "Event received: %d\n", xEvent.type ); switch (xEvent.type) { case ButtonPress: case ButtonRelease: motion_realize( data ); case MotionNotify: handleMouseEvent( &xEvent, data, x11 ); // crash ??? break; case KeyPress: case KeyRelease: motion_realize( data ); dfbEvent.type = (xEvent.type == KeyPress) ? DIET_KEYPRESS : DIET_KEYRELEASE; dfbEvent.flags = DIEF_KEYCODE | DIEF_TIMESTAMP; dfbEvent.key_code = xEvent.xkey.keycode; dfbEvent.timestamp.tv_sec = xEvent.xkey.time / 1000; dfbEvent.timestamp.tv_usec = (xEvent.xkey.time % 1000) * 1000; if ( (xEvent.type == KeyPress) && nextKeyIsRepeat ) { nextKeyIsRepeat = false; dfbEvent.flags |= DIEF_REPEAT; } dfb_input_dispatch( data->device, &dfbEvent ); break; case Expose: //D_INFO_LINE_MSG("<- expose %d,%d-%dx%d", // xEvent.xexpose.x, xEvent.xexpose.y, xEvent.xexpose.width, xEvent.xexpose.height); if (expose_event.type != 0) { DFBRegion e1 = { expose_event.x, expose_event.y, expose_event.x + expose_event.width - 1, expose_event.y + expose_event.height - 1 }; DFBRegion e2 = { xEvent.xexpose.x, xEvent.xexpose.y, xEvent.xexpose.x + xEvent.xexpose.width - 1, xEvent.xexpose.y + xEvent.xexpose.height - 1 }; dfb_region_region_union( &e1, &e2 ); expose_event.x = e1.x1; expose_event.y = e1.y1; expose_event.width = e1.x2 - e1.x1 + 1; expose_event.height = e1.y2 - e1.y1 + 1; } else expose_event = xEvent.xexpose; //D_INFO_LINE_MSG("-> expose %d,%d-%dx%d", // expose_event.x, expose_event.y, expose_event.width, expose_event.height); break; case DestroyNotify: /* this event is mainly to unblock XNextEvent. */ break; default: break; } XLockDisplay( x11->display ); } XUnlockDisplay( x11->display ); if (!data->stop) motion_realize( data ); } } return NULL; }