/* (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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* FIXME */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include D_DEBUG_DOMAIN( IDFB, "IDirectFB", "DirectFB Main Interface" ); /**********************************************************************************************************************/ typedef struct { DFBScreenCallback callback; void *callback_ctx; } EnumScreens_Context; typedef struct { IDirectFBScreen **interface; DFBScreenID id; DFBResult ret; } GetScreen_Context; typedef struct { DFBDisplayLayerCallback callback; void *callback_ctx; } EnumDisplayLayers_Context; typedef struct { IDirectFBDisplayLayer **interface; DFBDisplayLayerID id; DFBResult ret; CoreDFB *core; } GetDisplayLayer_Context; typedef struct { DFBInputDeviceCallback callback; void *callback_ctx; } EnumInputDevices_Context; typedef struct { IDirectFBInputDevice **interface; DFBInputDeviceID id; DFBResult ret; } GetInputDevice_Context; typedef struct { IDirectFBEventBuffer **interface; DFBInputDeviceCapabilities caps; } CreateEventBuffer_Context; /**********************************************************************************************************************/ static DFBEnumerationResult EnumScreens_Callback ( CoreScreen *screen, void *ctx ); static DFBEnumerationResult GetScreen_Callback ( CoreScreen *screen, void *ctx ); static DFBEnumerationResult EnumDisplayLayers_Callback( CoreLayer *layer, void *ctx ); static DFBEnumerationResult GetDisplayLayer_Callback ( CoreLayer *layer, void *ctx ); static DFBEnumerationResult EnumInputDevices_Callback ( CoreInputDevice *device, void *ctx ); static DFBEnumerationResult GetInputDevice_Callback ( CoreInputDevice *device, void *ctx ); static DFBEnumerationResult CreateEventBuffer_Callback( CoreInputDevice *device, void *ctx ); static ReactionResult focus_listener( const void *msg_data, void *ctx ); static bool input_filter_local( DFBEvent *evt, void *ctx ); static bool input_filter_global( DFBEvent *evt, void *ctx ); static void drop_window( IDirectFB_data *data ); /**********************************************************************************************************************/ /* * Destructor * * Free data structure and set the pointer to NULL, * to indicate the dead interface. */ void IDirectFB_Destruct( IDirectFB *thiz ) { int i; IDirectFB_data *data = (IDirectFB_data*)thiz->priv; D_DEBUG_AT( IDFB, "%s( %p )\n", __FUNCTION__, thiz ); drop_window( data ); if (data->primary.context) dfb_layer_context_unref( data->primary.context ); dfb_layer_context_unref( data->context ); for (i=0; ilayers[i].context) { if (data->layers[i].palette) dfb_palette_unref( data->layers[i].palette ); dfb_surface_unref( data->layers[i].surface ); dfb_layer_region_unref( data->layers[i].region ); dfb_layer_context_unref( data->layers[i].context ); } } dfb_core_destroy( data->core, false ); idirectfb_singleton = NULL; DIRECT_DEALLOCATE_INTERFACE( thiz ); direct_shutdown(); } static DirectResult IDirectFB_AddRef( IDirectFB *thiz ) { DIRECT_INTERFACE_GET_DATA(IDirectFB) D_DEBUG_AT( IDFB, "%s( %p )\n", __FUNCTION__, thiz ); data->ref++; return DFB_OK; } static DirectResult IDirectFB_Release( IDirectFB *thiz ) { DIRECT_INTERFACE_GET_DATA(IDirectFB) D_DEBUG_AT( IDFB, "%s( %p )\n", __FUNCTION__, thiz ); if (--data->ref == 0) IDirectFB_Destruct( thiz ); return DFB_OK; } static DFBResult IDirectFB_SetCooperativeLevel( IDirectFB *thiz, DFBCooperativeLevel level ) { DFBResult ret; CoreLayerContext *context; DIRECT_INTERFACE_GET_DATA(IDirectFB) D_DEBUG_AT( IDFB, "%s( %p, %d )\n", __FUNCTION__, thiz, level ); if (level == data->level) return DFB_OK; switch (level) { case DFSCL_NORMAL: data->primary.focused = false; dfb_layer_context_unref( data->primary.context ); data->primary.context = NULL; break; case DFSCL_FULLSCREEN: case DFSCL_EXCLUSIVE: if (dfb_config->force_windowed || dfb_config->force_desktop) return DFB_ACCESSDENIED; if (data->level == DFSCL_NORMAL) { ret = dfb_layer_create_context( data->layer, &context ); if (ret) return ret; ret = dfb_layer_activate_context( data->layer, context ); if (ret) { dfb_layer_context_unref( context ); return ret; } drop_window( data ); data->primary.context = context; } data->primary.focused = true; break; default: return DFB_INVARG; } data->level = level; return DFB_OK; } static DFBResult IDirectFB_GetDeviceDescription( IDirectFB *thiz, DFBGraphicsDeviceDescription *ret_desc ) { GraphicsDeviceInfo device_info; GraphicsDriverInfo driver_info; DIRECT_INTERFACE_GET_DATA(IDirectFB) D_DEBUG_AT( IDFB, "%s( %p )\n", __FUNCTION__, thiz ); if (!ret_desc) return DFB_INVARG; dfb_gfxcard_get_device_info( &device_info ); dfb_gfxcard_get_driver_info( &driver_info ); ret_desc->acceleration_mask = device_info.caps.accel; ret_desc->blitting_flags = device_info.caps.blitting; ret_desc->drawing_flags = device_info.caps.drawing; ret_desc->video_memory = dfb_gfxcard_memory_length(); snprintf( ret_desc->name, DFB_GRAPHICS_DEVICE_DESC_NAME_LENGTH, device_info.name ); snprintf( ret_desc->vendor, DFB_GRAPHICS_DEVICE_DESC_NAME_LENGTH, device_info.vendor ); ret_desc->driver.major = driver_info.version.major; ret_desc->driver.minor = driver_info.version.minor; snprintf( ret_desc->driver.name, DFB_GRAPHICS_DRIVER_INFO_NAME_LENGTH, driver_info.name ); snprintf( ret_desc->driver.vendor, DFB_GRAPHICS_DRIVER_INFO_VENDOR_LENGTH, driver_info.vendor ); return DFB_OK; } static DFBResult IDirectFB_EnumVideoModes( IDirectFB *thiz, DFBVideoModeCallback callbackfunc, void *callbackdata ) { VideoMode *m; DIRECT_INTERFACE_GET_DATA(IDirectFB) D_DEBUG_AT( IDFB, "%s( %p, %p, %p )\n", __FUNCTION__, thiz, callbackfunc, callbackdata ); if (!callbackfunc) return DFB_INVARG; m = dfb_system_modes(); while (m) { if (callbackfunc( m->xres, m->yres, m->bpp, callbackdata ) == DFENUM_CANCEL) break; m = m->next; } return DFB_OK; } static DFBResult IDirectFB_SetVideoMode( IDirectFB *thiz, int width, int height, int bpp ) { DFBResult ret; DFBSurfacePixelFormat format; DIRECT_INTERFACE_GET_DATA(IDirectFB) D_DEBUG_AT( IDFB, "%s( %p, %dx%d %dbit )\n", __FUNCTION__, thiz, width, height, bpp ); if (width < 1 || height < 1 || bpp < 1) return DFB_INVARG; format = dfb_pixelformat_for_depth( bpp ); if (format == DSPF_UNKNOWN) return DFB_INVARG; switch (data->level) { case DFSCL_NORMAL: if (data->primary.window) { ret = dfb_window_resize( data->primary.window, width, height ); if (ret) return ret; } break; case DFSCL_FULLSCREEN: case DFSCL_EXCLUSIVE: { DFBResult ret; DFBDisplayLayerConfig config; config.flags = DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT; config.width = width; config.height = height; config.pixelformat = format; ret = dfb_layer_context_set_configuration( data->primary.context, &config ); if (ret) return ret; break; } } data->primary.width = width; data->primary.height = height; data->primary.format = format; return DFB_OK; } static void init_palette( CoreSurface *surface, const DFBSurfaceDescription *desc ) { int num; CorePalette *palette = surface->palette; if (!palette || !(desc->flags & DSDESC_PALETTE)) return; num = MIN( desc->palette.size, palette->num_entries ); direct_memcpy( palette->entries, desc->palette.entries, num * sizeof(DFBColor)); dfb_palette_update( palette, 0, num - 1 ); } static DFBResult IDirectFB_CreateSurface( IDirectFB *thiz, const DFBSurfaceDescription *desc, IDirectFBSurface **interface ) { IDirectFBSurface *iface; DFBResult ret; int width = 256; int height = 256; DFBSurfacePixelFormat format; DFBSurfaceCapabilities caps = DSCAPS_NONE; CoreSurface *surface = NULL; unsigned long resource_id = 0; DFBDisplayLayerConfig config; DIRECT_INTERFACE_GET_DATA(IDirectFB) D_DEBUG_AT( IDFB, "%s( %p )\n", __FUNCTION__, thiz ); if (data->primary.context) dfb_layer_context_get_configuration( data->primary.context, &config ); else dfb_layer_context_get_configuration( data->context, &config ); if (desc->flags & DSDESC_HINTS && desc->hints & DSHF_FONT) { format = dfb_config->font_format; if (dfb_config->font_premult) caps = DSCAPS_PREMULTIPLIED; } else format = config.pixelformat; if (!desc || !interface) return DFB_INVARG; D_DEBUG_AT( IDFB, " -> flags 0x%08x\n", desc->flags ); if (desc->flags & DSDESC_WIDTH) { D_DEBUG_AT( IDFB, " -> width %d\n", desc->width ); width = desc->width; if (width < 1 || width > 20480) return DFB_INVARG; } if (desc->flags & DSDESC_HEIGHT) { D_DEBUG_AT( IDFB, " -> height %d\n", desc->height ); height = desc->height; if (height < 1 || height > 20480) return DFB_INVARG; } if (desc->flags & DSDESC_PALETTE) if (!desc->palette.entries || !desc->palette.size) return DFB_INVARG; if (desc->flags & DSDESC_CAPS) { D_DEBUG_AT( IDFB, " -> caps 0x%08x\n", desc->caps ); caps = desc->caps; } if (desc->flags & DSDESC_PIXELFORMAT) { D_DEBUG_AT( IDFB, " -> format %s\n", dfb_pixelformat_name(desc->pixelformat) ); format = desc->pixelformat; } if (desc->flags & DSDESC_RESOURCE_ID) resource_id = desc->resource_id; switch (format) { case DSPF_A1: case DSPF_A4: case DSPF_A8: case DSPF_ARGB: case DSPF_ARGB1555: case DSPF_ARGB1666: case DSPF_ARGB6666: case DSPF_ARGB2554: case DSPF_ARGB4444: case DSPF_RGBA4444: case DSPF_AYUV: case DSPF_AiRGB: case DSPF_I420: case DSPF_LUT2: case DSPF_LUT8: case DSPF_ALUT44: case DSPF_RGB16: case DSPF_RGB18: case DSPF_RGB24: case DSPF_RGB32: case DSPF_RGB332: case DSPF_UYVY: case DSPF_YUY2: case DSPF_YV12: case DSPF_NV12: case DSPF_NV21: case DSPF_NV16: case DSPF_RGB444: case DSPF_RGB555: case DSPF_BGR555: break; default: return DFB_INVARG; } if (caps & DSCAPS_PRIMARY) { if (desc->flags & DSDESC_PREALLOCATED) return DFB_INVARG; if (desc->flags & DSDESC_PIXELFORMAT) format = desc->pixelformat; else if (data->primary.format) format = data->primary.format; else if (dfb_config->mode.format) format = dfb_config->mode.format; else format = config.pixelformat; if (desc->flags & DSDESC_WIDTH) width = desc->width; else if (data->primary.width) width = data->primary.width; else if (dfb_config->mode.width) width = dfb_config->mode.width; else width = config.width; if (desc->flags & DSDESC_HEIGHT) height = desc->height; else if (data->primary.height) height = data->primary.height; else if (dfb_config->mode.height) height = dfb_config->mode.height; else height = config.height; /* FIXME: should we allow to create more primaries in windowed mode? should the primary surface be a singleton? or should we return an error? */ switch (data->level) { case DFSCL_NORMAL: if (dfb_config->force_desktop) { CoreSurface *surface; /* Source compatibility with older programs */ if ((caps & DSCAPS_FLIPPING) == DSCAPS_FLIPPING) caps &= ~DSCAPS_TRIPLE; ret = dfb_surface_create_simple( data->core, width, height, format, caps, CSTF_SHARED, resource_id, NULL, &surface ); if (ret) return ret; surface->notifications |= CSNF_FLIP; init_palette( surface, desc ); DIRECT_ALLOCATE_INTERFACE( iface, IDirectFBSurface ); ret = IDirectFBSurface_Construct( iface, NULL, NULL, NULL, NULL, surface, caps, data->core ); if (ret == DFB_OK) { dfb_windowstack_set_background_image( data->stack, surface ); dfb_windowstack_set_background_mode( data->stack, DLBM_IMAGE ); } dfb_surface_unref( surface ); if (!ret) *interface = iface; return ret; } else { CoreWindow *window; DFBWindowDescription wd; if ((caps & DSCAPS_FLIPPING) == DSCAPS_TRIPLE) return DFB_UNSUPPORTED; memset( &wd, 0, sizeof(wd) ); wd.flags = DWDESC_POSX | DWDESC_POSY | DWDESC_WIDTH | DWDESC_HEIGHT | DWDESC_PIXELFORMAT | DWDESC_SURFACE_CAPS | DWDESC_CAPS | DWDESC_RESOURCE_ID; if (dfb_config->scaled.width && dfb_config->scaled.height) { wd.posx = (config.width - dfb_config->scaled.width) / 2; wd.posy = (config.height - dfb_config->scaled.height) / 2; } else { wd.posx = (config.width - width) / 2; wd.posy = (config.height - height) / 2; } wd.width = width; wd.height = height; wd.pixelformat = format; wd.surface_caps = caps & ~DSCAPS_FLIPPING; wd.resource_id = resource_id; switch (format) { case DSPF_ARGB4444: case DSPF_RGBA4444: case DSPF_ARGB2554: case DSPF_ARGB1555: case DSPF_ARGB: case DSPF_AYUV: case DSPF_AiRGB: wd.caps |= DWCAPS_ALPHACHANNEL; break; default: break; } if ((caps & DSCAPS_FLIPPING) == DSCAPS_DOUBLE) wd.caps |= DWCAPS_DOUBLEBUFFER; ret = dfb_layer_context_create_window( data->core, data->context, &wd, &window ); if (ret) return ret; drop_window( data ); data->primary.window = window; dfb_window_attach( window, focus_listener, data, &data->primary.reaction ); dfb_window_change_options( window, DWOP_NONE, DWOP_SCALE ); if (dfb_config->scaled.width && dfb_config->scaled.height) dfb_window_resize( window, dfb_config->scaled.width, dfb_config->scaled.height ); init_palette( window->surface, desc ); DIRECT_ALLOCATE_INTERFACE( iface, IDirectFBSurface ); ret = IDirectFBSurface_Window_Construct( iface, NULL, NULL, NULL, window, caps, data->core ); if (!ret) *interface = iface; return ret; } case DFSCL_FULLSCREEN: case DFSCL_EXCLUSIVE: { CoreLayerRegion *region; CoreLayerContext *context = data->primary.context; config.flags |= DLCONF_BUFFERMODE | DLCONF_PIXELFORMAT | DLCONF_WIDTH | DLCONF_HEIGHT; /* Source compatibility with older programs */ if ((caps & DSCAPS_FLIPPING) == DSCAPS_FLIPPING) caps &= ~DSCAPS_TRIPLE; if (caps & DSCAPS_PREMULTIPLIED) { config.flags |= DLCONF_SURFACE_CAPS; config.surface_caps = DSCAPS_PREMULTIPLIED; } if (caps & DSCAPS_TRIPLE) { if (caps & DSCAPS_SYSTEMONLY) return DFB_UNSUPPORTED; config.buffermode = DLBM_TRIPLE; } else if (caps & DSCAPS_DOUBLE) { if (caps & DSCAPS_SYSTEMONLY) config.buffermode = DLBM_BACKSYSTEM; else config.buffermode = DLBM_BACKVIDEO; } else config.buffermode = DLBM_FRONTONLY; config.pixelformat = format; config.width = width; config.height = height; ret = dfb_layer_context_set_configuration( context, &config ); if (ret) { if (!(caps & (DSCAPS_SYSTEMONLY | DSCAPS_VIDEOONLY)) && config.buffermode == DLBM_BACKVIDEO) { config.buffermode = DLBM_BACKSYSTEM; ret = dfb_layer_context_set_configuration( context, &config ); if (ret) return ret; } else return ret; } ret = dfb_layer_context_get_primary_region( context, true, ®ion ); if (ret) return ret; ret = dfb_layer_region_get_surface( region, &surface ); if (ret) { dfb_layer_region_unref( region ); return ret; } /* FIXME_SC_3 if ((caps & DSCAPS_DEPTH) && !(surface->config.caps & DSCAPS_DEPTH)) { ret = dfb_surface_allocate_depth( surface ); if (ret) { dfb_surface_unref( surface ); dfb_layer_region_unref( region ); return ret; } } else if (!(caps & DSCAPS_DEPTH) && (surface->config.caps & DSCAPS_DEPTH)) { dfb_surface_deallocate_depth( surface ); } */ init_palette( surface, desc ); DIRECT_ALLOCATE_INTERFACE( iface, IDirectFBSurface ); ret = IDirectFBSurface_Layer_Construct( iface, NULL, NULL, NULL, region, caps, data->core ); dfb_surface_unref( surface ); dfb_layer_region_unref( region ); if (!ret) *interface = iface; return ret; } } } /* Source compatibility with older programs */ if ((caps & DSCAPS_FLIPPING) == DSCAPS_FLIPPING) caps &= ~DSCAPS_TRIPLE; if (caps & DSCAPS_TRIPLE) return DFB_UNSUPPORTED; if (desc->flags & DSDESC_PREALLOCATED) { int min_pitch; CoreSurfaceConfig config; if (caps & DSCAPS_VIDEOONLY) return DFB_INVARG; min_pitch = DFB_BYTES_PER_LINE(format, width); if (!desc->preallocated[0].data || desc->preallocated[0].pitch < min_pitch) { return DFB_INVARG; } if ((caps & DSCAPS_DOUBLE) && (!desc->preallocated[1].data || desc->preallocated[1].pitch < min_pitch)) { return DFB_INVARG; } config.flags = CSCONF_SIZE | CSCONF_FORMAT | CSCONF_CAPS | CSCONF_PREALLOCATED; config.size.w = width; config.size.h = height; config.format = format; config.caps = caps; config.preallocated[0].addr = desc->preallocated[0].data; config.preallocated[0].pitch = desc->preallocated[0].pitch; config.preallocated[1].addr = desc->preallocated[1].data; config.preallocated[1].pitch = desc->preallocated[1].pitch; ret = dfb_surface_create( data->core, &config, CSTF_PREALLOCATED, resource_id, NULL, &surface ); if (ret) return ret; } else { CoreSurfaceConfig config; config.flags = CSCONF_SIZE | CSCONF_FORMAT | CSCONF_CAPS; config.size.w = width; config.size.h = height; config.format = format; config.caps = caps; ret = dfb_surface_create( data->core, &config, CSTF_NONE, resource_id, NULL, &surface ); if (ret) return ret; } init_palette( surface, desc ); DIRECT_ALLOCATE_INTERFACE( iface, IDirectFBSurface ); ret = IDirectFBSurface_Construct( iface, NULL, NULL, NULL, NULL, surface, caps, data->core ); dfb_surface_unref( surface ); if (!ret) *interface = iface; return ret; } static DFBResult IDirectFB_CreatePalette( IDirectFB *thiz, const DFBPaletteDescription *desc, IDirectFBPalette **interface ) { DFBResult ret; IDirectFBPalette *iface; unsigned int size = 256; CorePalette *palette = NULL; DIRECT_INTERFACE_GET_DATA(IDirectFB) D_DEBUG_AT( IDFB, "%s( %p )\n", __FUNCTION__, thiz ); if (!interface) return DFB_INVARG; if (desc && desc->flags & DPDESC_SIZE) { if (!desc->size) return DFB_INVARG; size = desc->size; } ret = dfb_palette_create( data->core, size, &palette ); if (ret) return ret; if (desc && desc->flags & DPDESC_ENTRIES) { direct_memcpy( palette->entries, desc->entries, size * sizeof(DFBColor)); dfb_palette_update( palette, 0, size - 1 ); } else dfb_palette_generate_rgb332_map( palette ); DIRECT_ALLOCATE_INTERFACE( iface, IDirectFBPalette ); ret = IDirectFBPalette_Construct( iface, palette ); dfb_palette_unref( palette ); if (!ret) *interface = iface; return ret; } static DFBResult IDirectFB_EnumScreens( IDirectFB *thiz, DFBScreenCallback callbackfunc, void *callbackdata ) { EnumScreens_Context context; DIRECT_INTERFACE_GET_DATA(IDirectFB) D_DEBUG_AT( IDFB, "%s( %p )\n", __FUNCTION__, thiz ); if (!callbackfunc) return DFB_INVARG; context.callback = callbackfunc; context.callback_ctx = callbackdata; dfb_screens_enumerate( EnumScreens_Callback, &context ); return DFB_OK; } static DFBResult IDirectFB_GetScreen( IDirectFB *thiz, DFBScreenID id, IDirectFBScreen **interface ) { IDirectFBScreen *iface; GetScreen_Context context; DIRECT_INTERFACE_GET_DATA(IDirectFB) D_DEBUG_AT( IDFB, "%s( %p, %d )\n", __FUNCTION__, thiz, id ); if (!interface) return DFB_INVARG; if (dfb_config->primary_only && id != DLID_PRIMARY) return DFB_IDNOTFOUND; context.interface = &iface; context.id = id; context.ret = DFB_IDNOTFOUND; dfb_screens_enumerate( GetScreen_Callback, &context ); if (!context.ret) *interface = iface; return context.ret; } static DFBResult IDirectFB_EnumDisplayLayers( IDirectFB *thiz, DFBDisplayLayerCallback callbackfunc, void *callbackdata ) { EnumDisplayLayers_Context context; DIRECT_INTERFACE_GET_DATA(IDirectFB) D_DEBUG_AT( IDFB, "%s( %p )\n", __FUNCTION__, thiz ); if (!callbackfunc) return DFB_INVARG; context.callback = callbackfunc; context.callback_ctx = callbackdata; dfb_layers_enumerate( EnumDisplayLayers_Callback, &context ); return DFB_OK; } static DFBResult IDirectFB_GetDisplayLayer( IDirectFB *thiz, DFBDisplayLayerID id, IDirectFBDisplayLayer **interface ) { IDirectFBDisplayLayer *iface; GetDisplayLayer_Context context; DIRECT_INTERFACE_GET_DATA(IDirectFB) D_DEBUG_AT( IDFB, "%s( %p, %d )\n", __FUNCTION__, thiz, id ); if (!interface) return DFB_INVARG; if (dfb_config->primary_only && id != DLID_PRIMARY) return DFB_IDNOTFOUND; context.interface = &iface; context.id = id; context.ret = DFB_IDNOTFOUND; context.core = data->core; dfb_layers_enumerate( GetDisplayLayer_Callback, &context ); if (!context.ret) *interface = iface; return context.ret; } static DFBResult IDirectFB_EnumInputDevices( IDirectFB *thiz, DFBInputDeviceCallback callbackfunc, void *callbackdata ) { EnumInputDevices_Context context; DIRECT_INTERFACE_GET_DATA(IDirectFB) D_DEBUG_AT( IDFB, "%s( %p )\n", __FUNCTION__, thiz ); if (!callbackfunc) return DFB_INVARG; context.callback = callbackfunc; context.callback_ctx = callbackdata; dfb_input_enumerate_devices( EnumInputDevices_Callback, &context, DICAPS_ALL ); return DFB_OK; } static DFBResult IDirectFB_GetInputDevice( IDirectFB *thiz, DFBInputDeviceID id, IDirectFBInputDevice **interface ) { IDirectFBInputDevice *iface; GetInputDevice_Context context; DIRECT_INTERFACE_GET_DATA(IDirectFB) D_DEBUG_AT( IDFB, "%s( %p, %d )\n", __FUNCTION__, thiz, id ); if (!interface) return DFB_INVARG; context.interface = &iface; context.id = id; context.ret = DFB_IDNOTFOUND; dfb_input_enumerate_devices( GetInputDevice_Callback, &context, DICAPS_ALL ); if (!context.ret) *interface = iface; return context.ret; } static DFBResult IDirectFB_CreateEventBuffer( IDirectFB *thiz, IDirectFBEventBuffer **interface) { DFBResult ret; IDirectFBEventBuffer *iface; DIRECT_INTERFACE_GET_DATA(IDirectFB) D_DEBUG_AT( IDFB, "%s( %p )\n", __FUNCTION__, thiz ); if (!interface) return DFB_INVARG; DIRECT_ALLOCATE_INTERFACE( iface, IDirectFBEventBuffer ); ret = IDirectFBEventBuffer_Construct( iface, NULL, NULL ); if (!ret) *interface = iface; return ret; } static DFBResult IDirectFB_CreateInputEventBuffer( IDirectFB *thiz, DFBInputDeviceCapabilities caps, DFBBoolean global, IDirectFBEventBuffer **interface) { DFBResult ret; IDirectFBEventBuffer *iface; CreateEventBuffer_Context context; DIRECT_INTERFACE_GET_DATA(IDirectFB) D_DEBUG_AT( IDFB, "%s( %p )\n", __FUNCTION__, thiz ); if (!interface) return DFB_INVARG; DIRECT_ALLOCATE_INTERFACE( iface, IDirectFBEventBuffer ); ret = IDirectFBEventBuffer_Construct( iface, global ? input_filter_global : input_filter_local, data ); if (ret) return ret; context.caps = caps; context.interface = &iface; dfb_input_enumerate_devices( CreateEventBuffer_Callback, &context, caps ); *interface = iface; return DFB_OK; } static DFBResult IDirectFB_CreateImageProvider( IDirectFB *thiz, const char *filename, IDirectFBImageProvider **interface ) { DFBResult ret; DFBDataBufferDescription desc; IDirectFBDataBuffer *databuffer; IDirectFBImageProvider *iface; DIRECT_INTERFACE_GET_DATA(IDirectFB) D_DEBUG_AT( IDFB, "%s( %p, '%s' )\n", __FUNCTION__, thiz, filename ); /* Check arguments */ if (!filename || !interface) return DFB_INVARG; /* Create a data buffer. */ desc.flags = DBDESC_FILE; desc.file = filename; ret = thiz->CreateDataBuffer( thiz, &desc, &databuffer ); if (ret) return ret; /* Create (probing) the image provider. */ ret = IDirectFBImageProvider_CreateFromBuffer( databuffer, data->core, &iface ); /* We don't need it anymore, image provider has its own reference. */ databuffer->Release( databuffer ); if (!ret) *interface = iface; return ret; } static DFBResult IDirectFB_CreateVideoProvider( IDirectFB *thiz, const char *filename, IDirectFBVideoProvider **interface ) { DFBResult ret; DFBDataBufferDescription desc; IDirectFBDataBuffer *databuffer; IDirectFBVideoProvider *iface; DIRECT_INTERFACE_GET_DATA(IDirectFB) D_DEBUG_AT( IDFB, "%s( %p, '%s' )\n", __FUNCTION__, thiz, filename ); /* Check arguments */ if (!interface || !filename) return DFB_INVARG; /* Create a data buffer. */ desc.flags = DBDESC_FILE; desc.file = filename; ret = thiz->CreateDataBuffer( thiz, &desc, &databuffer ); if (ret) return ret; /* Create (probing) the video provider. */ ret = IDirectFBVideoProvider_CreateFromBuffer( databuffer, data->core, &iface ); /* We don't need it anymore, video provider has its own reference. */ databuffer->Release( databuffer ); if (!ret) *interface = iface; return ret; } static DFBResult IDirectFB_CreateFont( IDirectFB *thiz, const char *filename, const DFBFontDescription *desc, IDirectFBFont **interface ) { DFBResult ret; DFBDataBufferDescription dbdesc; IDirectFBDataBuffer *databuffer; IDirectFBFont *font; DIRECT_INTERFACE_GET_DATA(IDirectFB) D_DEBUG_AT( IDFB, "%s( %p, '%s' )\n", __FUNCTION__, thiz, filename ); /* Check arguments */ if (!interface) return DFB_INVARG; if (desc) { if ((desc->flags & DFDESC_HEIGHT) && desc->height < 1) return DFB_INVARG; if ((desc->flags & DFDESC_WIDTH) && desc->width < 1) return DFB_INVARG; } if (filename) { if (!desc) return DFB_INVARG; if (access( filename, R_OK ) != 0) return errno2result( errno ); } /* Create a data buffer. */ dbdesc.flags = DBDESC_FILE; dbdesc.file = filename; ret = thiz->CreateDataBuffer( thiz, &dbdesc, &databuffer ); if (ret) return ret; /* Create (probing) the font. */ ret = IDirectFBFont_CreateFromBuffer( databuffer, data->core, desc, &font ); /* We don't need it anymore, font has its own reference. */ databuffer->Release( databuffer ); if (!ret) *interface = font; return ret; } static DFBResult IDirectFB_CreateDataBuffer( IDirectFB *thiz, const DFBDataBufferDescription *desc, IDirectFBDataBuffer **interface ) { DFBResult ret = DFB_INVARG; IDirectFBDataBuffer *iface; DIRECT_INTERFACE_GET_DATA(IDirectFB) D_DEBUG_AT( IDFB, "%s( %p )\n", __FUNCTION__, thiz ); if (!interface) return DFB_INVARG; if (!desc) { DIRECT_ALLOCATE_INTERFACE( iface, IDirectFBDataBuffer ); ret = IDirectFBDataBuffer_Streamed_Construct( iface, data->core ); } else if (desc->flags & DBDESC_FILE) { if (!desc->file) return DFB_INVARG; DIRECT_ALLOCATE_INTERFACE( iface, IDirectFBDataBuffer ); ret = IDirectFBDataBuffer_File_Construct( iface, desc->file, data->core ); } else if (desc->flags & DBDESC_MEMORY) { if (!desc->memory.data || !desc->memory.length) return DFB_INVARG; DIRECT_ALLOCATE_INTERFACE( iface, IDirectFBDataBuffer ); ret = IDirectFBDataBuffer_Memory_Construct( iface, desc->memory.data, desc->memory.length, data->core ); } else return DFB_INVARG; if (!ret) *interface = iface; return ret; } static DFBResult IDirectFB_SetClipboardData( IDirectFB *thiz, const char *mime_type, const void *clip_data, unsigned int size, struct timeval *timestamp ) { DFBClipboardCore *clip_core; DIRECT_INTERFACE_GET_DATA(IDirectFB) D_DEBUG_AT( IDFB, "%s( %p )\n", __FUNCTION__, thiz ); if (!mime_type || !data || !size) return DFB_INVARG; clip_core = DFB_CORE( data->core, CLIPBOARD ); if (!clip_core) return DFB_NOCORE; return dfb_clipboard_set( clip_core, mime_type, clip_data, size, timestamp ); } static DFBResult IDirectFB_GetClipboardData( IDirectFB *thiz, char **mime_type, void **clip_data, unsigned int *size ) { DFBClipboardCore *clip_core; DIRECT_INTERFACE_GET_DATA(IDirectFB) D_DEBUG_AT( IDFB, "%s( %p )\n", __FUNCTION__, thiz ); if (!mime_type && !data && !size) return DFB_INVARG; clip_core = DFB_CORE( data->core, CLIPBOARD ); if (!clip_core) return DFB_NOCORE; return dfb_clipboard_get( clip_core, mime_type, clip_data, size ); } static DFBResult IDirectFB_GetClipboardTimeStamp( IDirectFB *thiz, struct timeval *timestamp ) { DFBClipboardCore *clip_core; DIRECT_INTERFACE_GET_DATA(IDirectFB) D_DEBUG_AT( IDFB, "%s( %p )\n", __FUNCTION__, thiz ); if (!timestamp) return DFB_INVARG; clip_core = DFB_CORE( data->core, CLIPBOARD ); if (!clip_core) return DFB_NOCORE; return dfb_clipboard_get_timestamp( clip_core, timestamp ); } static DFBResult IDirectFB_Suspend( IDirectFB *thiz ) { DIRECT_INTERFACE_GET_DATA(IDirectFB) D_DEBUG_AT( IDFB, "%s( %p )\n", __FUNCTION__, thiz ); return dfb_core_suspend( data->core ); } static DFBResult IDirectFB_Resume( IDirectFB *thiz ) { DIRECT_INTERFACE_GET_DATA(IDirectFB) D_DEBUG_AT( IDFB, "%s( %p )\n", __FUNCTION__, thiz ); return dfb_core_resume( data->core ); } static DFBResult IDirectFB_WaitIdle( IDirectFB *thiz ) { DIRECT_INTERFACE_GET_DATA(IDirectFB) D_DEBUG_AT( IDFB, "%s( %p )\n", __FUNCTION__, thiz ); dfb_gfxcard_sync(); return DFB_OK; } static DFBResult IDirectFB_WaitForSync( IDirectFB *thiz ) { DIRECT_INTERFACE_GET_DATA(IDirectFB) D_DEBUG_AT( IDFB, "%s( %p )\n", __FUNCTION__, thiz ); dfb_layer_wait_vsync( data->layer ); return DFB_OK; } static DFBResult IDirectFB_GetInterface( IDirectFB *thiz, const char *type, const char *implementation, void *arg, void **interface ) { DFBResult ret; DirectInterfaceFuncs *funcs = NULL; void *iface; DIRECT_INTERFACE_GET_DATA(IDirectFB) D_DEBUG_AT( IDFB, "%s( %p, '%s' )\n", __FUNCTION__, thiz, type ); if (!type || !interface) return DFB_INVARG; ret = DirectGetInterface( &funcs, type, implementation, DirectProbeInterface, arg ); if (ret) return ret; ret = funcs->Allocate( &iface ); if (ret) return ret; ret = funcs->Construct( iface, arg, data->core ); if (!ret) *interface = iface; return ret; } static DFBResult IDirectFB_RescanInputDevices( IDirectFB *thiz ) { DIRECT_INTERFACE_GET_DATA(IDirectFB) D_DEBUG_AT( IDFB, "%s( %p )\n", __FUNCTION__, thiz ); return dfb_input_rescan_devices( data->core ); } static void LoadBackgroundImage( IDirectFB *dfb, CoreWindowStack *stack, DFBConfigLayer *conf ) { DFBResult ret; DFBSurfaceDescription desc; IDirectFBImageProvider *provider; IDirectFBSurface *image; IDirectFBSurface_data *image_data; ret = dfb->CreateImageProvider( dfb, conf->background.filename, &provider ); if (ret) { D_DERROR( ret, "Failed loading background image '%s'!\n", conf->background.filename ); return; } if (conf->background.mode == DLBM_IMAGE) { desc.flags = DSDESC_WIDTH | DSDESC_HEIGHT; desc.width = conf->config.width; desc.height = conf->config.height; } else { provider->GetSurfaceDescription( provider, &desc ); } desc.flags |= DSDESC_CAPS | DSDESC_PIXELFORMAT; desc.caps = DSCAPS_SHARED; desc.pixelformat = conf->config.pixelformat; ret = dfb->CreateSurface( dfb, &desc, &image ); if (ret) { DirectFBError( "Failed creating surface for background image", ret ); provider->Release( provider ); return; } ret = provider->RenderTo( provider, image, NULL ); if (ret) { DirectFBError( "Failed loading background image", ret ); image->Release( image ); provider->Release( provider ); return; } provider->Release( provider ); image_data = (IDirectFBSurface_data*) image->priv; dfb_windowstack_set_background_image( stack, image_data->surface ); image->Release( image ); } static DFBResult InitLayerPalette( IDirectFB_data *data, DFBConfigLayer *conf, CoreSurface *surface, CorePalette **ret_palette ) { DFBResult ret; CorePalette *palette; ret = dfb_palette_create( data->core, 256, &palette ); if (ret) { D_DERROR( ret, "InitLayerPalette: Could not create palette!\n" ); return ret; } direct_memcpy( palette->entries, conf->palette, sizeof(DFBColor) * 256 ); ret = dfb_surface_set_palette( surface, palette ); if (ret) { D_DERROR( ret, "InitLayerPalette: Could not set palette!\n" ); dfb_palette_unref( palette ); return ret; } *ret_palette = palette; return DFB_OK; } static DFBResult InitLayers( IDirectFB *dfb, IDirectFB_data *data ) { DFBResult ret; int i; int num = dfb_layer_num(); for (i=0; ilayers[i]; if (conf->init) { CoreLayerContext *context; CoreWindowStack *stack; CardCapabilities caps; DFBDisplayLayerConfigFlags fail; ret = dfb_layer_get_primary_context( layer, false, &context ); if (ret) { D_DERROR( ret, "InitLayers: Could not get context of layer %d!\n", i ); goto error; } stack = dfb_layer_context_windowstack( context ); D_ASSERT( stack != NULL ); /* set default desktop configuration */ if (!(conf->config.flags & DLCONF_BUFFERMODE)) { dfb_gfxcard_get_capabilities( &caps ); conf->config.flags |= DLCONF_BUFFERMODE; conf->config.buffermode = (caps.accel & DFXL_BLIT) ? DLBM_BACKVIDEO : DLBM_BACKSYSTEM; } if (dfb_layer_context_test_configuration( context, &conf->config, &fail )) { if (fail & (DLCONF_WIDTH | DLCONF_HEIGHT)) { D_ERROR( "DirectFB/DirectFBCreate: " "Setting desktop resolution to %dx%d failed!\n" " -> Using default resolution.\n", conf->config.width, conf->config.height ); conf->config.flags &= ~(DLCONF_WIDTH | DLCONF_HEIGHT); } if (fail & DLCONF_PIXELFORMAT) { D_ERROR( "DirectFB/DirectFBCreate: " "Setting desktop format failed!\n" " -> Using default format.\n" ); conf->config.flags &= ~DLCONF_PIXELFORMAT; } if (fail & DLCONF_BUFFERMODE) { D_ERROR( "DirectFB/DirectFBCreate: " "Setting desktop buffer mode failed!\n" " -> No virtual resolution support or not enough memory?\n" " Falling back to system back buffer.\n" ); conf->config.buffermode = DLBM_BACKSYSTEM; if (dfb_layer_context_test_configuration( context, &conf->config, &fail )) { D_ERROR( "DirectFB/DirectFBCreate: " "Setting system memory desktop back buffer failed!\n" " -> Using front buffer only mode.\n" ); conf->config.flags &= ~DLCONF_BUFFERMODE; } } } if (conf->config.flags) { ret = dfb_layer_context_set_configuration( context, &conf->config ); if (ret) { D_DERROR( ret, "InitLayers: Could not set configuration for layer %d!\n", i ); dfb_layer_context_unref( context ); goto error; } } ret = dfb_layer_context_get_configuration( context, &conf->config ); D_ASSERT( ret == DFB_OK ); ret = dfb_layer_context_get_primary_region( context, true, &data->layers[i].region ); if (ret) { D_DERROR( ret, "InitLayers: Could not get primary region of layer %d!\n", i ); dfb_layer_context_unref( context ); goto error; } ret = dfb_layer_region_get_surface( data->layers[i].region, &data->layers[i].surface ); if (ret) { D_DERROR( ret, "InitLayers: Could not get surface of primary region of layer %d!\n", i ); dfb_layer_region_unref( data->layers[i].region ); dfb_layer_context_unref( context ); goto error; } if (conf->palette_set) InitLayerPalette( data, conf, data->layers[i].surface, &data->layers[i].palette ); if (conf->src_key_index >= 0 && conf->src_key_index < D_ARRAY_SIZE(conf->palette)) { dfb_layer_context_set_src_colorkey( context, conf->palette[conf->src_key_index].r, conf->palette[conf->src_key_index].g, conf->palette[conf->src_key_index].b, conf->src_key_index ); } else dfb_layer_context_set_src_colorkey( context, conf->src_key.r, conf->src_key.g, conf->src_key.b, -1 ); switch (conf->background.mode) { case DLBM_COLOR: dfb_windowstack_set_background_color( stack, &conf->background.color ); dfb_windowstack_set_background_color_index( stack, conf->background.color_index ); break; case DLBM_IMAGE: case DLBM_TILE: LoadBackgroundImage( dfb, stack, conf ); break; default: break; } dfb_windowstack_set_background_mode( stack, conf->background.mode ); data->layers[i].context = context; } data->layers[i].layer = layer; } for (i=0; ilayers[i].context) dfb_layer_activate_context( data->layers[i].layer, data->layers[i].context ); } return DFB_OK; error: for (i=num-1; i>=0; i--) { if (data->layers[i].context) { if (data->layers[i].palette) dfb_palette_unref( data->layers[i].palette ); dfb_surface_unref( data->layers[i].surface ); dfb_layer_region_unref( data->layers[i].region ); dfb_layer_context_unref( data->layers[i].context ); data->layers[i].context = NULL; } } return ret; } /* * Constructor * * Fills in function pointers and intializes data structure. */ DFBResult IDirectFB_Construct( IDirectFB *thiz, CoreDFB *core ) { DFBResult ret; DIRECT_ALLOCATE_INTERFACE_DATA(thiz, IDirectFB) D_DEBUG_AT( IDFB, "%s( %p, %p )\n", __FUNCTION__, thiz, core ); data->ref = 1; data->core = core; data->level = DFSCL_NORMAL; if (dfb_layer_num() < 1) { D_ERROR( "%s: No layers available! Missing driver?\n", __FUNCTION__ ); return DFB_UNSUPPORTED; } data->layer = dfb_layer_at_translated( DLID_PRIMARY ); ret = dfb_layer_get_primary_context( data->layer, true, &data->context ); if (ret) { D_ERROR( "%s: Could not get default context of primary layer!\n", __FUNCTION__ ); DIRECT_DEALLOCATE_INTERFACE(thiz); return ret; } data->stack = dfb_layer_context_windowstack( data->context ); thiz->AddRef = IDirectFB_AddRef; thiz->Release = IDirectFB_Release; thiz->SetCooperativeLevel = IDirectFB_SetCooperativeLevel; thiz->GetDeviceDescription = IDirectFB_GetDeviceDescription; thiz->EnumVideoModes = IDirectFB_EnumVideoModes; thiz->SetVideoMode = IDirectFB_SetVideoMode; thiz->CreateSurface = IDirectFB_CreateSurface; thiz->CreatePalette = IDirectFB_CreatePalette; thiz->EnumScreens = IDirectFB_EnumScreens; thiz->GetScreen = IDirectFB_GetScreen; thiz->EnumDisplayLayers = IDirectFB_EnumDisplayLayers; thiz->GetDisplayLayer = IDirectFB_GetDisplayLayer; thiz->EnumInputDevices = IDirectFB_EnumInputDevices; thiz->GetInputDevice = IDirectFB_GetInputDevice; thiz->CreateEventBuffer = IDirectFB_CreateEventBuffer; thiz->CreateInputEventBuffer = IDirectFB_CreateInputEventBuffer; thiz->CreateImageProvider = IDirectFB_CreateImageProvider; thiz->CreateVideoProvider = IDirectFB_CreateVideoProvider; thiz->CreateFont = IDirectFB_CreateFont; thiz->CreateDataBuffer = IDirectFB_CreateDataBuffer; thiz->SetClipboardData = IDirectFB_SetClipboardData; thiz->GetClipboardData = IDirectFB_GetClipboardData; thiz->GetClipboardTimeStamp = IDirectFB_GetClipboardTimeStamp; thiz->Suspend = IDirectFB_Suspend; thiz->Resume = IDirectFB_Resume; thiz->WaitIdle = IDirectFB_WaitIdle; thiz->WaitForSync = IDirectFB_WaitForSync; thiz->GetInterface = IDirectFB_GetInterface; thiz->RescanInputDevices = IDirectFB_RescanInputDevices; if (dfb_core_is_master( core )) { ret = InitLayers( thiz, data ); if (ret) { dfb_layer_context_unref( data->context ); DIRECT_DEALLOCATE_INTERFACE(thiz); return ret; } } return DFB_OK; } DFBResult IDirectFB_SetAppFocus( IDirectFB *thiz, DFBBoolean focused ) { DIRECT_INTERFACE_GET_DATA(IDirectFB) D_DEBUG_AT( IDFB, "%s( %p, %s )\n", __FUNCTION__, thiz, focused ? "true" : "false" ); data->app_focus = focused; return DFB_OK; } /* * internal functions */ static DFBEnumerationResult EnumScreens_Callback( CoreScreen *screen, void *ctx ) { DFBScreenDescription desc; DFBScreenID id; EnumScreens_Context *context = (EnumScreens_Context*) ctx; id = dfb_screen_id_translated( screen ); if (dfb_config->primary_only && id != DSCID_PRIMARY) return DFENUM_OK; dfb_screen_get_info( screen, NULL, &desc ); return context->callback( id, desc, context->callback_ctx ); } static DFBEnumerationResult GetScreen_Callback( CoreScreen *screen, void *ctx ) { GetScreen_Context *context = (GetScreen_Context*) ctx; if (dfb_screen_id_translated( screen ) != context->id) return DFENUM_OK; DIRECT_ALLOCATE_INTERFACE( *context->interface, IDirectFBScreen ); context->ret = IDirectFBScreen_Construct( *context->interface, screen ); return DFENUM_CANCEL; } static DFBEnumerationResult EnumDisplayLayers_Callback( CoreLayer *layer, void *ctx ) { DFBDisplayLayerDescription desc; DFBDisplayLayerID id; EnumDisplayLayers_Context *context = (EnumDisplayLayers_Context*) ctx; id = dfb_layer_id_translated( layer ); if (dfb_config->primary_only && id != DLID_PRIMARY) return DFENUM_OK; dfb_layer_get_description( layer, &desc ); return context->callback( id, desc, context->callback_ctx ); } static DFBEnumerationResult GetDisplayLayer_Callback( CoreLayer *layer, void *ctx ) { GetDisplayLayer_Context *context = (GetDisplayLayer_Context*) ctx; if (dfb_layer_id_translated( layer ) != context->id) return DFENUM_OK; DIRECT_ALLOCATE_INTERFACE( *context->interface, IDirectFBDisplayLayer ); context->ret = IDirectFBDisplayLayer_Construct( *context->interface, layer, context->core ); return DFENUM_CANCEL; } static DFBEnumerationResult EnumInputDevices_Callback( CoreInputDevice *device, void *ctx ) { DFBInputDeviceDescription desc; EnumInputDevices_Context *context = (EnumInputDevices_Context*) ctx; dfb_input_device_description( device, &desc ); return context->callback( dfb_input_device_id( device ), desc, context->callback_ctx ); } static DFBEnumerationResult GetInputDevice_Callback( CoreInputDevice *device, void *ctx ) { GetInputDevice_Context *context = (GetInputDevice_Context*) ctx; if (dfb_input_device_id( device ) != context->id) return DFENUM_OK; DIRECT_ALLOCATE_INTERFACE( *context->interface, IDirectFBInputDevice ); context->ret = IDirectFBInputDevice_Construct( *context->interface, device ); return DFENUM_CANCEL; } static DFBEnumerationResult CreateEventBuffer_Callback( CoreInputDevice *device, void *ctx ) { DFBInputDeviceDescription desc; CreateEventBuffer_Context *context = (CreateEventBuffer_Context*) ctx; dfb_input_device_description( device, &desc ); IDirectFBEventBuffer_AttachInputDevice( *context->interface, device ); return DFENUM_OK; } static ReactionResult focus_listener( const void *msg_data, void *ctx ) { const DFBWindowEvent *evt = msg_data; IDirectFB_data *data = ctx; switch (evt->type) { case DWET_DESTROYED: dfb_window_unref( data->primary.window ); data->primary.window = NULL; data->primary.focused = false; return RS_REMOVE; case DWET_GOTFOCUS: data->primary.focused = true; break; case DWET_LOSTFOCUS: data->primary.focused = false; break; default: break; } return RS_OK; } static bool input_filter_local( DFBEvent *evt, void *ctx ) { IDirectFB_data *data = (IDirectFB_data*) ctx; if (evt->clazz == DFEC_INPUT) { DFBInputEvent *event = &evt->input; if (!data->primary.focused && !data->app_focus) return true; switch (event->type) { case DIET_BUTTONPRESS: if (data->primary.window) dfb_windowstack_cursor_enable( data->core, data->stack, false ); break; case DIET_KEYPRESS: if (data->primary.window) dfb_windowstack_cursor_enable( data->core, data->stack, (event->key_symbol == DIKS_ESCAPE) || (event->modifiers & DIMM_META) ); break; default: break; } } return false; } static bool input_filter_global( DFBEvent *evt, void *ctx ) { IDirectFB_data *data = (IDirectFB_data*) ctx; if (evt->clazz == DFEC_INPUT) { DFBInputEvent *event = &evt->input; if (!data->primary.focused && !data->app_focus) event->flags |= DIEF_GLOBAL; } return false; } static void drop_window( IDirectFB_data *data ) { if (!data->primary.window) return; dfb_window_detach( data->primary.window, &data->primary.reaction ); dfb_window_unref( data->primary.window ); data->primary.window = NULL; data->primary.focused = false; dfb_windowstack_cursor_enable( data->core, data->stack, true ); }