summaryrefslogtreecommitdiff
path: root/directfb.c
diff options
context:
space:
mode:
authorAnas Nashif <anas.nashif@intel.com>2012-12-07 02:53:31 -0800
committerAnas Nashif <anas.nashif@intel.com>2012-12-07 02:53:31 -0800
commitcbb6286cb92020dd7ae88798ed831ed76fd2130e (patch)
tree782a01c00d5e064aa67ea3f9241a8ef1de1060c6 /directfb.c
downloadlinks-cbb6286cb92020dd7ae88798ed831ed76fd2130e.tar.gz
links-cbb6286cb92020dd7ae88798ed831ed76fd2130e.tar.bz2
links-cbb6286cb92020dd7ae88798ed831ed76fd2130e.zip
Imported Upstream version 2.6upstream/2.6upstream
Diffstat (limited to 'directfb.c')
-rw-r--r--directfb.c891
1 files changed, 891 insertions, 0 deletions
diff --git a/directfb.c b/directfb.c
new file mode 100644
index 0000000..23668b3
--- /dev/null
+++ b/directfb.c
@@ -0,0 +1,891 @@
+/* directfb.c
+ * DirectFB graphics driver
+ * (c) 2002 Sven Neumann <sven@directfb.org>
+ *
+ * This file is a part of the Links program, released under GPL.
+ */
+
+/* TODO:
+ * - Store window size as driver params (?)
+ * - Fix wrong colors on big-endian systems (fixed?)
+ * - Make everything work correctly ;-)
+ *
+ * KNOWN PROBLEMS:
+ * - If mouse drags don't work for you, update DirectFB
+ * (the upcoming 0.9.14 release fixes this).
+ */
+
+
+#include "cfg.h"
+
+#ifdef GRDRV_DIRECTFB
+
+#include <netinet/in.h> /* for htons */
+
+#include <directfb.h>
+
+#include "links.h"
+#include "directfb_cursors.h"
+
+
+#define FOCUSED_OPACITY 0xFF
+#define UNFOCUSED_OPACITY 0xC0
+
+#define DIRECTFB_HASH_TABLE_SIZE 23
+static struct graphics_device **directfb_hash_table[DIRECTFB_HASH_TABLE_SIZE];
+
+typedef struct _DFBDeviceData DFBDeviceData;
+struct _DFBDeviceData
+{
+ DFBWindowID id;
+ IDirectFBWindow *window;
+ IDirectFBSurface *surface;
+ DFBRegion flip_region;
+ int flip_pending;
+};
+
+
+extern struct graphics_driver directfb_driver;
+
+static IDirectFB *dfb = NULL;
+static IDirectFBDisplayLayer *layer = NULL;
+static IDirectFBSurface *arrow = NULL;
+static IDirectFBEventBuffer *events = NULL;
+static DFBSurfacePixelFormat pixelformat = DSPF_UNKNOWN;
+static int event_timer = -1;
+
+
+static inline void directfb_set_color (IDirectFBSurface *surface, long color);
+static void directfb_register_flip (DFBDeviceData *data,
+ int x, int y, int w, int h);
+static void directfb_flip_surface (void *pointer);
+static void directfb_check_events (void *pointer);
+static void directfb_translate_key (DFBWindowEvent *event,
+ int *key, int *flag);
+static void directfb_add_to_table (struct graphics_device *gd);
+static void directfb_remove_from_table (struct graphics_device *gd);
+static struct graphics_device * directfb_lookup_in_table (DFBWindowID id);
+
+
+static unsigned char *
+directfb_fb_init_driver (unsigned char *param, unsigned char *display)
+{
+ DFBDisplayLayerConfig config;
+ DFBResult ret;
+ unsigned char *error;
+ unsigned char *result;
+
+ DirectFBInit (&g_argc, (char ***)(void *)&g_argv);
+ if ((ret = DirectFBCreate (&dfb)) != DFB_OK) {
+ error = (unsigned char *)DirectFBErrorString(ret);
+ goto ret;
+ }
+
+ if ((ret = dfb->GetDisplayLayer (dfb, DLID_PRIMARY, &layer)) != DFB_OK) {
+ error = (unsigned char *)DirectFBErrorString(ret);
+ goto ret_dfb;
+ }
+
+ if ((ret = layer->GetConfiguration (layer, &config)) != DFB_OK) {
+ error = (unsigned char *)DirectFBErrorString(ret);
+ goto ret_layer;
+ }
+
+ pixelformat = config.pixelformat;
+
+ directfb_driver.depth = (((DFB_BYTES_PER_PIXEL (pixelformat) & 0x7)) |
+ ((DFB_COLOR_BITS_PER_PIXEL (pixelformat) & 0x1F) << 3));
+
+ if (directfb_driver.depth == 4)
+ directfb_driver.depth = 196;
+
+ /* endian test */
+ if (htons (0x1234) == 0x1234) {
+ if ((directfb_driver.depth & 0x7) == 2)
+ directfb_driver.depth |= 0x100;
+ if ((directfb_driver.depth & 0x7) == 4)
+ directfb_driver.depth |= 0x200;
+ }
+
+ if (!get_color_fn(directfb_driver.depth)) {
+ error = "Unsupported color depth";
+ goto ret_layer;
+ }
+
+ directfb_driver.x = config.width;
+ directfb_driver.y = config.height;
+
+ memset (directfb_hash_table, 0, sizeof (directfb_hash_table));
+
+ if ((ret = dfb->CreateEventBuffer (dfb, &events)) != DFB_OK) {
+ error = (unsigned char *)DirectFBErrorString(ret);
+ goto ret_layer;
+ }
+
+ event_timer = install_timer (20, directfb_check_events, events);
+
+ if (dfb->CreateSurface (dfb, directfb_get_arrow_desc(), &arrow) != DFB_OK)
+ arrow = NULL;
+
+ return NULL;
+
+ret_layer:
+ layer->Release(layer);
+ret_dfb:
+ dfb->Release(dfb);
+ret:
+ result = init_str();
+ add_to_strn(&result, error);
+ add_to_strn(&result, "\n");
+ return result;
+}
+
+static struct graphics_device *
+directfb_init_device (void)
+{
+ struct graphics_device *gd;
+ DFBDeviceData *data;
+ IDirectFBWindow *window;
+ DFBWindowDescription desc;
+
+ desc.flags = DWDESC_WIDTH | DWDESC_HEIGHT | DWDESC_POSX | DWDESC_POSY;
+ desc.width = directfb_driver.x;
+ desc.height = directfb_driver.y;
+ desc.posx = 0;
+ desc.posy = 0;
+
+ retry:
+ if (layer->CreateWindow (layer, &desc, &window) != DFB_OK) {
+ if (out_of_memory(NULL, 0))
+ goto retry;
+ return NULL;
+ }
+
+ gd = mem_alloc (sizeof (struct graphics_device));
+
+ gd->size.x1 = 0;
+ gd->size.y1 = 0;
+ window->GetSize (window, &gd->size.x2, &gd->size.y2);
+
+ gd->clip = gd->size;
+
+ data = mem_alloc (sizeof (DFBDeviceData));
+
+ data->window = window;
+ data->flip_pending = 0;
+
+ if (arrow)
+ window->SetCursorShape (window, arrow, arrow_hot_x, arrow_hot_y);
+
+ window->GetSurface (window, &data->surface);
+ window->GetID (window, &data->id);
+
+ gd->driver_data = data;
+ gd->user_data = NULL;
+
+ directfb_add_to_table (gd);
+
+ window->AttachEventBuffer (window, events);
+
+ window->SetOpacity (window, FOCUSED_OPACITY);
+
+ return gd;
+}
+
+static void
+directfb_shutdown_device (struct graphics_device *gd)
+{
+ DFBDeviceData *data;
+
+ if (!gd)
+ return;
+
+ data = gd->driver_data;
+
+ unregister_bottom_half (directfb_flip_surface, data);
+ directfb_remove_from_table (gd);
+
+ data->surface->Release (data->surface);
+ data->window->Destroy (data->window);
+ data->window->Release (data->window);
+
+ mem_free (data);
+ mem_free (gd);
+}
+
+static void
+directfb_shutdown_driver (void)
+{
+ int i;
+
+ kill_timer (event_timer);
+ events->Release (events);
+ events = NULL;
+
+ if (arrow)
+ arrow->Release (arrow);
+
+ layer->Release (layer);
+ dfb->Release (dfb);
+
+ for (i = 0; i < DIRECTFB_HASH_TABLE_SIZE; i++)
+ if (directfb_hash_table[i])
+ mem_free (directfb_hash_table[i]);
+
+ dfb = NULL;
+}
+
+static unsigned char *
+directfb_get_driver_param (void)
+{
+ return NULL;
+}
+
+static int
+directfb_get_empty_bitmap (struct bitmap *bmp)
+{
+ IDirectFBSurface *surface;
+ DFBSurfaceDescription desc;
+
+ bmp->data = bmp->flags = NULL;
+
+ desc.flags = DSDESC_WIDTH | DSDESC_HEIGHT;
+ desc.width = bmp->x;
+ desc.height = bmp->y;
+
+ retry:
+ if (dfb->CreateSurface (dfb, &desc, &surface) != DFB_OK) {
+ if (out_of_memory(NULL, 0))
+ goto retry;
+ return -1;
+ }
+
+ surface->Lock (surface, DSLF_READ | DSLF_WRITE, &bmp->data, &bmp->skip);
+
+ bmp->flags = surface;
+
+ return 0;
+}
+
+/*
+static int
+directfb_get_filled_bitmap (struct bitmap *bmp, long color)
+{
+ IDirectFBSurface *surface;
+ DFBSurfaceDescription desc;
+
+ bmp->data = bmp->flags = NULL;
+
+ desc.flags = DSDESC_WIDTH | DSDESC_HEIGHT;
+ desc.width = bmp->x;
+ desc.height = bmp->y;
+
+ retry:
+ if (dfb->CreateSurface (dfb, &desc, &surface) != DFB_OK) {
+ if (out_of_memory(NULL, 0))
+ goto retry;
+ return 0;
+ }
+
+ directfb_set_color (surface, color);
+ surface->FillRectangle (surface, 0, 0, bmp->x, bmp->y);
+ surface->Lock (surface, DSLF_READ | DSLF_WRITE, &bmp->data, &bmp->skip);
+
+ bmp->flags = surface;
+
+ return 0;
+}
+*/
+
+static void
+directfb_register_bitmap (struct bitmap *bmp)
+{
+ IDirectFBSurface *surface = bmp->flags;
+ if (!surface) return;
+
+ surface->Unlock (surface);
+ bmp->data = NULL;
+}
+
+static void *
+directfb_prepare_strip (struct bitmap *bmp, int top, int lines)
+{
+ IDirectFBSurface *surface = bmp->flags;
+ if (!surface) return NULL;
+
+ surface->Lock (surface, DSLF_READ | DSLF_WRITE, &bmp->data, &bmp->skip);
+
+ return ((unsigned char *) bmp->data + top * bmp->skip);
+}
+
+static void
+directfb_commit_strip (struct bitmap *bmp, int top, int lines)
+{
+ IDirectFBSurface *surface = bmp->flags;
+ if (!surface) return;
+
+ surface->Unlock (surface);
+ bmp->data = NULL;
+}
+
+static void
+directfb_unregister_bitmap (struct bitmap *bmp)
+{
+ IDirectFBSurface *surface = bmp->flags;
+ if (!surface) return;
+
+ surface->Release (surface);
+}
+
+static void
+directfb_draw_bitmap (struct graphics_device *gd, struct bitmap *bmp,
+ int x, int y)
+{
+ DFBDeviceData *data = gd->driver_data;
+ IDirectFBSurface *src = bmp->flags;
+ if (!src) return;
+
+ if (gd->clip.x1 >= gd->clip.x2 ||
+ gd->clip.y1 >= gd->clip.y2) return;
+
+ data->surface->Blit (data->surface, src, NULL, x, y);
+
+ directfb_register_flip (data, x, y, bmp->x, bmp->y);
+}
+
+#if 0
+static void
+directfb_draw_bitmaps (struct graphics_device *gd, struct bitmap **bmps,
+ int n, int x, int y)
+{
+ DFBDeviceData *data = gd->driver_data;
+ struct bitmap *bmp = *bmps;
+ int x1 = x;
+ int h = 0;
+
+ if (n < 1)
+ return;
+
+ do
+ {
+ IDirectFBSurface *src = bmp->flags;
+
+ if (src)
+ data->surface->Blit (data->surface, src, NULL, x, y);
+
+ if (h < bmp->y)
+ h = bmp->y;
+
+ x += bmp->x;
+ bmp++;
+ }
+ while (--n);
+
+ directfb_register_flip (data, x1, y, x - x1, h);
+}
+#endif
+
+static long
+directfb_get_color (int rgb)
+{
+ return rgb;
+}
+
+
+static void
+directfb_fill_area (struct graphics_device *gd,
+ int x1, int y1, int x2, int y2, long color)
+{
+ DFBDeviceData *data = gd->driver_data;
+ int w = x2 - x1;
+ int h = y2 - y1;
+
+ directfb_set_color (data->surface, color);
+ data->surface->FillRectangle (data->surface, x1, y1, w, h);
+
+ directfb_register_flip (data, x1, y1, w, h);
+}
+
+static void
+directfb_draw_hline (struct graphics_device *gd,
+ int left, int y, int right, long color)
+{
+ DFBDeviceData *data = gd->driver_data;
+
+ if (right <= left) return;
+
+ right--;
+
+ directfb_set_color (data->surface, color);
+ data->surface->DrawLine (data->surface, left, y, right, y);
+
+ directfb_register_flip (data, left, y, right - left, 1);
+}
+
+static void
+directfb_draw_vline (struct graphics_device *gd,
+ int x, int top, int bottom, long color)
+{
+ DFBDeviceData *data = gd->driver_data;
+
+ if (bottom <= top) return;
+
+ bottom--;
+
+ directfb_set_color (data->surface, color);
+ data->surface->DrawLine (data->surface, x, top, x, bottom);
+
+ directfb_register_flip (data, x, top, 1, bottom - top);
+}
+
+static void
+directfb_set_clip_area (struct graphics_device *gd, struct rect *r)
+{
+ DFBDeviceData *data = gd->driver_data;
+ DFBRegion region;
+ region.x1 = r->x1;
+ region.y1 = r->y1;
+ region.x2 = r->x2 - 1;
+ region.y2 = r->y2 - 1;
+
+ gd->clip = *r;
+
+ data->surface->SetClip (data->surface, &region);
+}
+
+static int
+directfb_hscroll (struct graphics_device *gd, struct rect_set **set, int sc)
+{
+ DFBDeviceData *data = gd->driver_data;
+ DFBRectangle rect;
+
+ *set = NULL;
+ if (!sc)
+ return 0;
+
+ rect.x = gd->clip.x1;
+ rect.y = gd->clip.y1;
+ rect.w = gd->clip.x2 - rect.x;
+ rect.h = gd->clip.y2 - rect.y;
+
+ data->surface->Blit (data->surface,
+ data->surface, &rect, rect.x + sc, rect.y);
+
+ directfb_register_flip (data, rect.x, rect.y, rect.w, rect.h);
+
+ return 1;
+}
+
+static int
+directfb_vscroll (struct graphics_device *gd, struct rect_set **set, int sc)
+{
+ DFBDeviceData *data = gd->driver_data;
+ DFBRectangle rect;
+
+ *set = NULL;
+ if (!sc)
+ return 0;
+
+ rect.x = gd->clip.x1;
+ rect.y = gd->clip.y1;
+ rect.w = gd->clip.x2 - rect.x;
+ rect.h = gd->clip.y2 - rect.y;
+
+ data->surface->Blit (data->surface,
+ data->surface, &rect, rect.x, rect.y + sc);
+
+ directfb_register_flip (data, rect.x, rect.y, rect.w, rect.h);
+
+ return 1;
+}
+
+struct graphics_driver directfb_driver =
+{
+ "directfb",
+ directfb_fb_init_driver,
+ directfb_init_device,
+ directfb_shutdown_device,
+ directfb_shutdown_driver,
+ directfb_get_driver_param,
+ directfb_get_empty_bitmap,
+ /*directfb_get_filled_bitmap,*/
+ directfb_register_bitmap,
+ directfb_prepare_strip,
+ directfb_commit_strip,
+ directfb_unregister_bitmap,
+ directfb_draw_bitmap,
+ /*directfb_draw_bitmaps,*/
+ directfb_get_color,
+ directfb_fill_area,
+ directfb_draw_hline,
+ directfb_draw_vline,
+ directfb_hscroll,
+ directfb_vscroll,
+ directfb_set_clip_area,
+ dummy_block,
+ dummy_unblock,
+ NULL, /* set_title */
+ NULL, /* exec */
+ NULL, /* set_clipboard_text */
+ NULL, /* get_clipboard_text */
+ 0, /* depth */
+ 0, 0, /* size */
+ GD_NO_OS_SHELL, /* flags */
+ 0, /* codepage */
+ NULL, /* shell */
+};
+
+
+static inline void directfb_set_color (IDirectFBSurface *surface, long color)
+{
+ surface->SetColor (surface,
+ (color & 0xFF0000) >> 16,
+ (color & 0xFF00) >> 8,
+ (color & 0xFF),
+ 0xFF);
+}
+
+static void directfb_register_flip (DFBDeviceData *data,
+ int x, int y, int w, int h)
+{
+ if (x < 0 || y < 0 || w < 1 || h < 1)
+ return;
+
+ w = x + w - 1;
+ h = y + h - 1;
+
+ if (data->flip_pending)
+ {
+ if (data->flip_region.x1 > x) data->flip_region.x1 = x;
+ if (data->flip_region.y1 > y) data->flip_region.y1 = y;
+ if (data->flip_region.x2 < w) data->flip_region.x2 = w;
+ if (data->flip_region.y2 < h) data->flip_region.y2 = h;
+ }
+ else
+ {
+ data->flip_region.x1 = x;
+ data->flip_region.y1 = y;
+ data->flip_region.x2 = w;
+ data->flip_region.y2 = h;
+
+ data->flip_pending = 1;
+
+ register_bottom_half (directfb_flip_surface, data);
+ }
+}
+
+static void
+directfb_flip_surface (void *pointer)
+{
+ DFBDeviceData *data = pointer;
+
+ if (!data->flip_pending)
+ return;
+
+ data->surface->Flip (data->surface, &data->flip_region, 0);
+
+ data->flip_pending = 0;
+}
+
+static void
+directfb_check_events (void *pointer)
+{
+ struct graphics_device *gd = NULL;
+ DFBDeviceData *data = NULL;
+ DFBWindowEvent event;
+ DFBWindowEvent next;
+
+ while (events->GetEvent (events, DFB_EVENT (&event)) == DFB_OK)
+ {
+ switch (event.type)
+ {
+ case DWET_GOTFOCUS:
+ case DWET_LOSTFOCUS:
+ case DWET_POSITION_SIZE:
+ case DWET_SIZE:
+ case DWET_KEYDOWN:
+ case DWET_BUTTONDOWN:
+ case DWET_BUTTONUP:
+ case DWET_WHEEL:
+ case DWET_MOTION:
+ break;
+ default:
+ continue;
+ }
+
+ if (!data || data->id != event.window_id)
+ {
+ gd = directfb_lookup_in_table (event.window_id);
+ if (!gd)
+ continue;
+ }
+
+ data = gd->driver_data;
+
+ switch (event.type)
+ {
+#if 0
+ case DWET_GOTFOCUS:
+ data->window->SetOpacity (data->window, FOCUSED_OPACITY);
+ break;
+
+ case DWET_LOSTFOCUS:
+ data->window->SetOpacity (data->window, UNFOCUSED_OPACITY);
+ break;
+#endif
+
+ case DWET_POSITION_SIZE:
+ case DWET_SIZE:
+ while ((events->PeekEvent (events, DFB_EVENT (&next)) == DFB_OK) &&
+ (next.type == DWET_SIZE || next.type == DWET_POSITION_SIZE) &&
+ (next.window_id == data->id))
+ events->GetEvent (events, DFB_EVENT (&event));
+
+ gd->size.x2 = event.w;
+ gd->size.y2 = event.h;
+ gd->resize_handler (gd);
+ break;
+
+ case DWET_KEYDOWN:
+ {
+ int key, flag;
+
+ directfb_translate_key (&event, &key, &flag);
+ if (key)
+ gd->keyboard_handler (gd, key, flag);
+ }
+ break;
+
+ case DWET_BUTTONDOWN:
+ case DWET_BUTTONUP:
+ {
+ int flags;
+
+ /*
+ * For unknown reason, we get the event twice
+ */
+ while ((events->PeekEvent (events, DFB_EVENT (&next)) == DFB_OK) &&
+ (next.type == event.type && next.button == event.button &&
+ next.x == event.x && next.y == event.y && next.window_id == data->id))
+ events->GetEvent (events, DFB_EVENT (&event));
+
+ if (event.type == DWET_BUTTONUP)
+ {
+ flags = B_UP;
+ data->window->UngrabPointer (data->window);
+ }
+ else
+ {
+ flags = B_DOWN;
+ data->window->GrabPointer (data->window);
+ }
+
+ switch (event.button)
+ {
+ case DIBI_LEFT:
+ flags |= B_LEFT;
+ break;
+ case DIBI_RIGHT:
+ flags |= B_RIGHT;
+ break;
+ case DIBI_MIDDLE:
+ flags |= B_MIDDLE;
+ break;
+ default:
+ continue;
+ }
+
+ gd->mouse_handler (gd, event.x, event.y, flags);
+ }
+ break;
+
+ case DWET_WHEEL:
+ gd->mouse_handler (gd, event.x, event.y,
+ B_MOVE |
+ (event.step > 0 ? B_WHEELUP : B_WHEELDOWN));
+ break;
+
+ case DWET_MOTION:
+ {
+ int flags;
+
+ while ((events->PeekEvent (events, DFB_EVENT (&next)) == DFB_OK) &&
+ (next.type == DWET_MOTION) &&
+ (next.window_id == data->id))
+ events->GetEvent (events, DFB_EVENT (&event));
+
+ switch (event.buttons)
+ {
+ case DIBM_LEFT:
+ flags = B_DRAG | B_LEFT;
+ break;
+ case DIBM_RIGHT:
+ flags = B_DRAG | B_RIGHT;
+ break;
+ case DIBM_MIDDLE:
+ flags = B_DRAG | B_MIDDLE;
+ break;
+ default:
+ flags = B_MOVE;
+ break;
+ }
+
+ gd->mouse_handler (gd, event.x, event.y, flags);
+ }
+ break;
+
+ case DWET_CLOSE:
+ gd->keyboard_handler (gd, KBD_CLOSE, 0);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ event_timer = install_timer (20, directfb_check_events, events);
+}
+
+static void
+directfb_translate_key (DFBWindowEvent *event, int *key, int *flag)
+{
+ *key = 0;
+ *flag = 0;
+
+ if (event->modifiers & DIMM_CONTROL && event->key_id == DIKI_C)
+ {
+ *key = KBD_CTRL_C;
+ return;
+ }
+
+ /* setting Shift seems to break things
+ *
+ * if (event->modifiers & DIMM_SHIFT)
+ * *flag |= KBD_SHIFT;
+ */
+ if (event->modifiers & DIMM_CONTROL)
+ *flag |= KBD_CTRL;
+ if (event->modifiers & DIMM_ALT)
+ *flag |= KBD_ALT;
+
+ switch (event->key_symbol)
+ {
+ case DIKS_ENTER: *key = KBD_ENTER; break;
+ case DIKS_BACKSPACE: *key = KBD_BS; break;
+ case DIKS_TAB: *key = KBD_TAB; break;
+ case DIKS_ESCAPE: *key = KBD_ESC; break;
+ case DIKS_CURSOR_UP: *key = KBD_UP; break;
+ case DIKS_CURSOR_DOWN: *key = KBD_DOWN; break;
+ case DIKS_CURSOR_LEFT: *key = KBD_LEFT; break;
+ case DIKS_CURSOR_RIGHT: *key = KBD_RIGHT; break;
+ case DIKS_INSERT: *key = KBD_INS; break;
+ case DIKS_DELETE: *key = KBD_DEL; break;
+ case DIKS_HOME: *key = KBD_HOME; break;
+ case DIKS_END: *key = KBD_END; break;
+ case DIKS_PAGE_UP: *key = KBD_PAGE_UP; break;
+ case DIKS_PAGE_DOWN: *key = KBD_PAGE_DOWN; break;
+ case DIKS_F1: *key = KBD_F1; break;
+ case DIKS_F2: *key = KBD_F2; break;
+ case DIKS_F3: *key = KBD_F3; break;
+ case DIKS_F4: *key = KBD_F4; break;
+ case DIKS_F5: *key = KBD_F5; break;
+ case DIKS_F6: *key = KBD_F6; break;
+ case DIKS_F7: *key = KBD_F7; break;
+ case DIKS_F8: *key = KBD_F8; break;
+ case DIKS_F9: *key = KBD_F9; break;
+ case DIKS_F10: *key = KBD_F10; break;
+ case DIKS_F11: *key = KBD_F11; break;
+ case DIKS_F12: *key = KBD_F12; break;
+
+ default:
+ if (DFB_KEY_TYPE (event->key_symbol) == DIKT_UNICODE)
+ *key = event->key_symbol;
+ break;
+ }
+}
+
+static void
+directfb_add_to_table (struct graphics_device *gd)
+{
+ DFBDeviceData *data = gd->driver_data;
+ struct graphics_device **devices;
+ int i;
+
+ i = data->id % DIRECTFB_HASH_TABLE_SIZE;
+
+ devices = directfb_hash_table[i];
+
+ if (devices)
+ {
+ int c = 0;
+
+ while (devices[c++])
+ if (c == MAXINT) overalloc();
+
+ if ((unsigned)c > MAXINT / sizeof(void *) - 1) overalloc();
+ devices = mem_realloc (devices, (c + 1) * sizeof (void *));
+ devices[c-1] = gd;
+ devices[c] = NULL;
+ }
+ else
+ {
+ devices = mem_alloc (2 * sizeof (void *));
+ devices[0] = gd;
+ devices[1] = NULL;
+ }
+
+ directfb_hash_table[i] = devices;
+}
+
+static void
+directfb_remove_from_table (struct graphics_device *gd)
+{
+ DFBDeviceData *data = gd->driver_data;
+ struct graphics_device **devices;
+ int i, j, c;
+
+ i = data->id % DIRECTFB_HASH_TABLE_SIZE;
+
+ devices = directfb_hash_table[i];
+ if (!devices)
+ return;
+
+ for (j = 0, c = -1; devices[j]; j++)
+ if (devices[j] == gd)
+ c = j;
+
+ if (c < 0)
+ return;
+
+ memmove (devices + c, devices + c + 1, (j - c) * sizeof (void *));
+ devices = mem_realloc (devices, j * sizeof (void *));
+
+ directfb_hash_table[i] = devices;
+}
+
+static struct graphics_device *
+directfb_lookup_in_table (DFBWindowID id)
+{
+ struct graphics_device **devices;
+ int i;
+
+ i = id % DIRECTFB_HASH_TABLE_SIZE;
+
+ devices = directfb_hash_table[i];
+ if (!devices)
+ return NULL;
+
+ while (*devices)
+ {
+ DFBDeviceData *data = (*devices)->driver_data;
+
+ if (data->id == id)
+ return *devices;
+
+ devices++;
+ }
+
+ return NULL;
+}
+
+#endif /* GRDRV_DIRECTFB */