From 7fe60435bce6595a9c58a9bfd8244d74b5320e96 Mon Sep 17 00:00:00 2001 From: Benjamin Franzke Date: Tue, 15 Jan 2013 08:46:13 +0100 Subject: Import DirectFB141_2k11R3_beta5 --- Source/DirectFB/src/idirectfb.c | 1965 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 1965 insertions(+) create mode 100755 Source/DirectFB/src/idirectfb.c (limited to 'Source/DirectFB/src/idirectfb.c') diff --git a/Source/DirectFB/src/idirectfb.c b/Source/DirectFB/src/idirectfb.c new file mode 100755 index 0000000..144eaad --- /dev/null +++ b/Source/DirectFB/src/idirectfb.c @@ -0,0 +1,1965 @@ +/* + (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 ); +} + -- cgit