summaryrefslogtreecommitdiff
path: root/Source/DirectFB/systems/vnc/primary.c
diff options
context:
space:
mode:
Diffstat (limited to 'Source/DirectFB/systems/vnc/primary.c')
-rwxr-xr-xSource/DirectFB/systems/vnc/primary.c993
1 files changed, 993 insertions, 0 deletions
diff --git a/Source/DirectFB/systems/vnc/primary.c b/Source/DirectFB/systems/vnc/primary.c
new file mode 100755
index 0000000..17de20e
--- /dev/null
+++ b/Source/DirectFB/systems/vnc/primary.c
@@ -0,0 +1,993 @@
+/*
+ (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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+
+#include <directfb.h>
+#include <directfb_util.h>
+
+#include <fusion/fusion.h>
+#include <fusion/shmalloc.h>
+
+#include <core/core.h>
+#include <core/coredefs.h>
+#include <core/coretypes.h>
+#include <core/gfxcard.h>
+#include <core/layers.h>
+#include <core/palette.h>
+#include <core/state.h>
+#include <core/surface.h>
+#include <core/system.h>
+#include <core/input.h>
+
+#include <gfx/convert.h>
+#include <gfx/util.h>
+
+#include <misc/conf.h>
+
+#include <direct/memcpy.h>
+#include <direct/messages.h>
+#include <direct/thread.h>
+
+#include <rfb/rfb.h>
+#include <rfb/keysym.h>
+#include "vnc.h"
+#include "primary.h"
+
+
+D_DEBUG_DOMAIN( VNC_Layer, "VNC/Layer", "VNC Layer" );
+
+/**********************************************************************************************************************/
+
+/******************************************************************************/
+/*VNC server setup*/
+/* Here we create a structure so that every client has it's own pointer */
+
+typedef struct ClientData {
+ DFBVNC *vnc;
+ int oldButtonMask;
+ int oldx,oldy;
+} ClientData;
+
+static void process_key_event(rfbBool down, rfbKeySym key, struct _rfbClientRec* cl);
+static void process_pointer_event(int buttonMask, int x, int y, struct _rfbClientRec* cl);
+static bool translate_key(rfbKeySym key, DFBInputEvent *evt );
+static void clientgone(rfbClientPtr cl);
+static enum rfbNewClientAction newclient(rfbClientPtr cl);
+
+extern CoreInputDevice *vncInputDevice;
+
+/******************************************************************************/
+
+static DFBResult
+primaryInitScreen( CoreScreen *screen,
+ CoreGraphicsDevice *device,
+ void *driver_data,
+ void *screen_data,
+ DFBScreenDescription *description )
+{
+ int argc = 0;
+ char **argv = NULL;
+ DFBVNC *vnc = driver_data;
+ DFBVNCShared *shared = vnc->shared;
+
+ /* Set the screen capabilities. */
+ description->caps = DSCCAPS_NONE;
+
+ /* Set the screen name. */
+ direct_snputs( description->name, "VNC Primary Screen", DFB_SCREEN_DESC_NAME_LENGTH );
+
+ /*
+ * Allocate shared memory for RFB screen frame buffer
+ */
+ shared->screen_buffer = SHCALLOC( dfb_core_shmpool_data(vnc->core), 2 * shared->screen_size.h, 4 * shared->screen_size.w );
+ if (!shared->screen_buffer)
+ return D_OOSHM();
+
+
+ /* Set video mode */
+ vnc->rfb_screen = rfbGetScreen( &argc, argv, shared->screen_size.w, shared->screen_size.h, 8, 3, 4 );
+ if (!vnc->rfb_screen) {
+ D_ERROR( "DirectFB/VNC: rfbGetScreen( %dx%d, 8, 3, 4 ) failed!\n", shared->screen_size.w, shared->screen_size.h );
+ SHFREE( dfb_core_shmpool_data(vnc->core), shared->screen_buffer );
+ return DFB_FAILURE;
+ }
+
+ vnc->rfb_screen->screenData = vnc;
+
+ rfbNewFramebuffer( vnc->rfb_screen, shared->screen_buffer, shared->screen_size.w, shared->screen_size.h, 8, 3, 4 );
+
+ vnc->rfb_screen->serverFormat.redShift = 16;
+ vnc->rfb_screen->serverFormat.greenShift = 8;
+ vnc->rfb_screen->serverFormat.blueShift = 0;
+ vnc->rfb_screen->serverFormat.redMax = 255;
+ vnc->rfb_screen->serverFormat.greenMax = 255;
+ vnc->rfb_screen->serverFormat.blueMax = 255;
+
+
+ /* Connect key handler */
+
+ vnc->rfb_screen->kbdAddEvent = process_key_event;
+ vnc->rfb_screen->ptrAddEvent = process_pointer_event;
+ vnc->rfb_screen->newClientHook = newclient;
+ vnc->rfb_screen->autoPort = TRUE;
+
+ /* Initialize VNC */
+
+ rfbInitServer(vnc->rfb_screen);
+
+ if (vnc->rfb_screen->listenSock == -1) {
+ D_ERROR( "DirectFB/VNC: rfbInitServer() failed to initialize listening socket!\n" );
+ SHFREE( dfb_core_shmpool_data(vnc->core), shared->screen_buffer );
+ return DFB_FAILURE;
+ }
+
+
+ DFBResult ret;
+ CoreSurfaceConfig config;
+
+ config.flags = CSCONF_SIZE | CSCONF_FORMAT | CSCONF_CAPS | CSCONF_PREALLOCATED;
+ config.size.w = shared->screen_size.w;
+ config.size.h = shared->screen_size.h;
+ config.format = DSPF_ARGB;
+ config.caps = DSCAPS_SYSTEMONLY | DSCAPS_DOUBLE;// | DSCAPS_SHARED;
+ config.preallocated[0].addr = shared->screen_buffer;
+ config.preallocated[0].pitch = shared->screen_size.w * 4;
+ config.preallocated[1].addr = shared->screen_buffer + shared->screen_size.w * 4 * shared->screen_size.h;
+ config.preallocated[1].pitch = shared->screen_size.w * 4;
+
+ ret = dfb_surface_create( vnc->core, &config, CSTF_PREALLOCATED, 0, NULL, &shared->screen_surface );
+ if (ret) {
+ D_DERROR( ret, "DirectFB/VNC: Could not create preallocated screen surface!\n" );
+ SHFREE( dfb_core_shmpool_data(vnc->core), shared->screen_buffer );
+ return ret;
+ }
+
+
+ rfbRunEventLoop( vnc->rfb_screen, -1, TRUE );
+
+ return DFB_OK;
+}
+/*
+static DFBResult
+primaryShutdownScreen( CoreScreen *screen,
+ void *driver_data,
+ void *screen_data )
+{
+ DFBVNC *vnc = driver_data;
+
+ rfbScreenCleanup( vnc->rfb_screen );
+
+ SHFREE( dfb_core_shmpool_data(vnc->core), vnc->shared->screen_buffer );
+
+ return DFB_OK;
+}
+*/
+static DFBResult
+primaryGetScreenSize( CoreScreen *screen,
+ void *driver_data,
+ void *screen_data,
+ int *ret_width,
+ int *ret_height )
+{
+ DFBVNC *vnc = driver_data;
+
+ *ret_width = vnc->shared->screen_size.w;
+ *ret_height = vnc->shared->screen_size.h;
+
+ return DFB_OK;
+}
+
+static const ScreenFuncs _vncPrimaryScreenFuncs = {
+ .InitScreen = primaryInitScreen,
+// .ShutdownScreen = primaryShutdownScreen,
+ .GetScreenSize = primaryGetScreenSize,
+};
+
+const ScreenFuncs *vncPrimaryScreenFuncs = &_vncPrimaryScreenFuncs;
+
+/******************************************************************************/
+
+static int
+primaryLayerDataSize( void )
+{
+ return sizeof(VNCLayerData);
+}
+
+static int
+primaryRegionDataSize( void )
+{
+ return 0;
+}
+
+static DFBResult
+primaryInitLayer( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ DFBDisplayLayerDescription *description,
+ DFBDisplayLayerConfig *config,
+ DFBColorAdjustment *adjustment )
+{
+ DFBVNC *vnc = driver_data;
+ VNCLayerData *data = layer_data;
+ const char *name;
+
+ D_DEBUG( "DirectFB/VNC: primaryInitLayer\n");
+
+ char *names[] = { "Primary", "Secondary", "Tertiary" };
+
+ if (vnc->layer_count < 3)
+ name = names[vnc->layer_count];
+ else
+ name = "Other";
+
+ data->layer_id = vnc->layer_count;
+
+ vnc->shared->layer_data[vnc->layer_count++] = data;
+
+
+ /* set capabilities and type */
+ description->caps = DLCAPS_SURFACE | DLCAPS_SCREEN_LOCATION | DLCAPS_ALPHACHANNEL | DLCAPS_OPACITY;
+ description->type = DLTF_GRAPHICS;
+
+ /* set name */
+ snprintf( description->name,
+ DFB_DISPLAY_LAYER_DESC_NAME_LENGTH, "VNC %s Layer", name );
+
+ /* fill out the default configuration */
+ config->flags = DLCONF_WIDTH | DLCONF_HEIGHT |
+ DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE;
+ config->buffermode = DLBM_FRONTONLY;
+ config->width = vnc->shared->screen_size.w;
+ config->height = vnc->shared->screen_size.h;
+
+ if (dfb_config->mode.format != DSPF_UNKNOWN)
+ config->pixelformat = dfb_config->mode.format;
+ else if (dfb_config->mode.depth > 0)
+ config->pixelformat = dfb_pixelformat_for_depth( dfb_config->mode.depth );
+ else
+ config->pixelformat = DSPF_RGB32;
+
+ return DFB_OK;
+}
+
+static DFBResult
+primaryTestRegion( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ CoreLayerRegionConfig *config,
+ CoreLayerRegionConfigFlags *failed )
+{
+ CoreLayerRegionConfigFlags fail = 0;
+
+ switch (config->buffermode) {
+ case DLBM_FRONTONLY:
+ case DLBM_BACKSYSTEM:
+ case DLBM_BACKVIDEO:
+ case DLBM_TRIPLE:
+ break;
+
+ default:
+ fail |= CLRCF_BUFFERMODE;
+ break;
+ }
+
+ if (config->options & ~(DLOP_ALPHACHANNEL | DLOP_OPACITY))
+ fail |= CLRCF_OPTIONS;
+
+ if (failed)
+ *failed = fail;
+
+ if (fail)
+ return DFB_UNSUPPORTED;
+
+ return DFB_OK;
+}
+
+static DFBResult
+primaryAddRegion( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ void *region_data,
+ CoreLayerRegionConfig *config )
+{
+ return DFB_OK;
+}
+
+static DFBResult
+UpdateScreen( DFBVNC *vnc,
+ const DFBRectangle *update )
+{
+ DFBVNCShared *shared = vnc->shared;
+ DFBRegion clip = { 0, 0, shared->screen_size.w - 1, shared->screen_size.h - 1 };
+ CardState state;
+ unsigned int i;
+
+ D_DEBUG_AT( VNC_Layer, "%s()\n", __FUNCTION__ );
+
+ if (update) {
+ if (!dfb_region_rectangle_intersect( &clip, update )) {
+ D_DEBUG_AT( VNC_Layer, " -> update not intersecting with screen area!\n" );
+ return DFB_OK;
+ }
+ }
+
+ dfb_state_init( &state, vnc->core );
+
+ state.destination = shared->screen_surface;
+ state.clip = clip;
+ state.src_blend = DSBF_ONE;
+ state.dst_blend = DSBF_INVSRCALPHA;
+
+ // FIXME: optimize out clear
+ DFBRectangle rect = {
+ 0, 0, shared->screen_size.w, shared->screen_size.h
+ };
+
+ dfb_gfxcard_fillrectangles( &rect, 1, &state );
+
+
+ for (i=0; i<VNC_MAX_LAYERS; i++) {
+ VNCLayerData *data = shared->layer_data[i];
+
+ if (data->surface) {
+ DFBRectangle src = data->config.source;
+ DFBRectangle dst = data->config.dest;
+
+ state.modified |= SMF_SOURCE | SMF_BLITTING_FLAGS;
+ state.source = data->surface;
+
+ /* emulate missing hw layer clipping */
+ if (dst.x + dst.w > shared->screen_size.w || dst.y + dst.h > shared->screen_size.h)
+ return DFB_ACCESSDENIED;
+
+
+ if (data->config.options & DLOP_ALPHACHANNEL) {
+ state.blittingflags = DSBLIT_BLEND_ALPHACHANNEL;
+
+ if (!(data->surface->config.caps & DSCAPS_PREMULTIPLIED))
+ state.blittingflags |= DSBLIT_SRC_PREMULTIPLY;
+ }
+ else
+ state.blittingflags = DSBLIT_NOFX;
+
+ if ((data->config.options & DLOP_OPACITY) && data->config.opacity != 0xff) {
+ state.blittingflags |= DSBLIT_BLEND_COLORALPHA;
+
+ if (data->surface->config.caps & DSCAPS_PREMULTIPLIED)
+ state.blittingflags |= DSBLIT_SRC_PREMULTCOLOR;
+
+
+ state.modified |= SMF_COLOR;
+ state.color.a = data->config.opacity;
+ }
+
+ dfb_gfxcard_stretchblit( &src, &dst, &state );
+ }
+ }
+
+ state.destination = NULL;
+ state.source = NULL;
+
+ dfb_state_destroy( &state );
+
+
+ dfb_back_to_front_copy( shared->screen_surface, &clip );
+
+
+ dfb_gfxcard_sync();
+
+ DirectResult ret;
+ DFBVNCMarkRectAsModified mark;
+
+ mark.region = clip;
+
+ ret = fusion_call_execute( &shared->call, FCEF_ONEWAY,
+ (int)((clip.x1 << 16) | clip.x2),
+ (void*)(long)((clip.y1 << 16) | clip.y2),
+ NULL );
+ if (ret) {
+ D_DERROR( ret, "DirectFB/VNC: fusion_call_execute2() failed!\n" );
+ return ret;
+ }
+
+ return DFB_OK;
+}
+
+static DFBResult
+primarySetRegion( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ void *region_data,
+ CoreLayerRegionConfig *config,
+ CoreLayerRegionConfigFlags updated,
+ CoreSurface *surface,
+ CorePalette *palette,
+ CoreSurfaceBufferLock *left_lock )
+{
+ DFBVNC *vnc = driver_data;
+ VNCLayerData *data = layer_data;
+
+ D_DEBUG_AT( VNC_Layer, "%s()\n", __FUNCTION__ );
+
+ data->config = *config;
+
+ if (updated & CLRCF_OPACITY)
+ D_DEBUG_AT( VNC_Layer, " -> opacity %d\n", config->opacity );
+
+ dfb_surface_link( &vnc->shared->layer_data[data->layer_id]->surface, surface );
+
+ if (data->shown)
+ return UpdateScreen( vnc, NULL );
+ else
+ D_DEBUG_AT( VNC_Layer, " -> not shown\n" );
+
+ return DFB_OK;
+}
+
+static DFBResult
+primaryRemoveRegion( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ void *region_data )
+{
+ DFBVNC *vnc = driver_data;
+ VNCLayerData *data = layer_data;
+
+ D_DEBUG_AT( VNC_Layer, "%s()\n", __FUNCTION__ );
+
+ D_DEBUG_AT( VNC_Layer, " -> setting shown to false\n" );
+
+ data->shown = false;
+
+ dfb_surface_unlink( &vnc->shared->layer_data[data->layer_id]->surface );
+
+ return UpdateScreen( vnc, NULL );
+}
+
+static DFBResult
+primaryFlipRegion( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ void *region_data,
+ CoreSurface *surface,
+ DFBSurfaceFlipFlags flags,
+ CoreSurfaceBufferLock *left_lock )
+{
+ DFBVNC *vnc = driver_data;
+ VNCLayerData *data = layer_data;
+
+ D_DEBUG_AT( VNC_Layer, "%s()\n", __FUNCTION__ );
+
+ dfb_surface_flip( surface, false );
+
+ D_DEBUG_AT( VNC_Layer, " -> setting shown to true\n" );
+
+ data->shown = true;
+
+ return UpdateScreen( vnc, &data->config.dest );
+}
+
+static DFBResult
+primaryUpdateRegion( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ void *region_data,
+ CoreSurface *surface,
+ const DFBRegion *left_update,
+ CoreSurfaceBufferLock *left_lock )
+{
+ DFBVNC *vnc = driver_data;
+ VNCLayerData *data = layer_data;
+
+ DFBRectangle update = data->config.dest;
+
+ D_DEBUG_AT( VNC_Layer, "%s()\n", __FUNCTION__ );
+
+ if (left_update) {
+ DFBRegion screen_update = {
+ left_update->x1 + data->config.dest.x,
+ left_update->y1 + data->config.dest.y,
+ left_update->x2 + data->config.dest.x,
+ left_update->y2 + data->config.dest.y
+ };
+
+ D_DEBUG_AT( VNC_Layer, " -> update %d,%d-%dx%d\n", DFB_RECTANGLE_VALS_FROM_REGION(&screen_update) );
+
+ if (!dfb_rectangle_intersect_by_region( &update, &screen_update )) {
+ D_DEBUG_AT( VNC_Layer, " -> no intersection with %d,%d-%dx%d!\n", DFB_RECTANGLE_VALS( &data->config.dest ) );
+
+ return DFB_OK;
+ }
+ }
+
+ D_DEBUG_AT( VNC_Layer, " -> setting shown to true\n" );
+
+ data->shown = true;
+
+ return UpdateScreen( vnc, &update );
+}
+
+static DFBResult
+primaryAllocateSurface( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ void *region_data,
+ CoreLayerRegionConfig *config,
+ CoreSurface **ret_surface )
+{
+ DFBVNC *vnc = driver_data;
+ CoreSurfaceConfig conf;
+
+ conf.flags = CSCONF_SIZE | CSCONF_FORMAT | CSCONF_CAPS;
+ conf.size.w = config->width;
+ conf.size.h = config->height;
+ conf.format = config->format;
+ conf.caps = DSCAPS_SYSTEMONLY;
+
+ if (config->buffermode != DLBM_FRONTONLY)
+ conf.caps |= DSCAPS_DOUBLE;
+
+ return dfb_surface_create( vnc->core, &conf, CSTF_LAYER, DLID_PRIMARY, NULL, ret_surface );
+}
+
+static DFBResult
+primaryReallocateSurface( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ void *region_data,
+ CoreLayerRegionConfig *config,
+ CoreSurface *surface )
+{
+ DFBResult ret;
+ CoreSurfaceConfig conf;
+
+ conf.flags = CSCONF_SIZE | CSCONF_FORMAT | CSCONF_CAPS;
+ conf.size.w = config->width;
+ conf.size.h = config->height;
+ conf.format = config->format;
+ conf.caps = DSCAPS_SYSTEMONLY;
+
+ if (config->buffermode != DLBM_FRONTONLY)
+ conf.caps |= DSCAPS_DOUBLE;
+
+ ret = dfb_surface_reconfig( surface, &conf );
+ if (ret)
+ return ret;
+
+ if (DFB_PIXELFORMAT_IS_INDEXED(config->format) && !surface->palette) {
+ DFBResult ret;
+ CorePalette *palette;
+
+ ret = dfb_palette_create( NULL, /* FIXME */
+ 1 << DFB_COLOR_BITS_PER_PIXEL( config->format ),
+ &palette );
+ if (ret)
+ return ret;
+
+ if (config->format == DSPF_LUT8)
+ dfb_palette_generate_rgb332_map( palette );
+
+ dfb_surface_set_palette( surface, palette );
+
+ dfb_palette_unref( palette );
+ }
+
+ return DFB_OK;
+}
+
+static const DisplayLayerFuncs _vncPrimaryLayerFuncs = {
+ .LayerDataSize = primaryLayerDataSize,
+ .RegionDataSize = primaryRegionDataSize,
+ .InitLayer = primaryInitLayer,
+
+ .TestRegion = primaryTestRegion,
+ .AddRegion = primaryAddRegion,
+ .SetRegion = primarySetRegion,
+ .RemoveRegion = primaryRemoveRegion,
+ .FlipRegion = primaryFlipRegion,
+ .UpdateRegion = primaryUpdateRegion,
+
+ .AllocateSurface = primaryAllocateSurface,
+ .ReallocateSurface = primaryReallocateSurface,
+};
+
+const DisplayLayerFuncs *vncPrimaryLayerFuncs = &_vncPrimaryLayerFuncs;
+
+
+/**********************************************************************************************************************/
+
+/**
+ VNC Server setup
+**/
+
+static void
+clientgone(rfbClientPtr cl)
+{
+ D_FREE( cl->clientData );
+}
+
+static enum rfbNewClientAction
+newclient(rfbClientPtr cl)
+{
+ ClientData *cd;
+ DFBVNC *vnc = cl->screen->screenData;
+
+ cd = D_CALLOC( 1, sizeof(ClientData) );
+ if (!cd) {
+ D_OOM();
+ return RFB_CLIENT_REFUSE;
+ }
+
+ cd->vnc = vnc;
+
+ cl->clientData = cd;
+ cl->clientGoneHook = clientgone;
+
+ return RFB_CLIENT_ACCEPT;
+}
+
+static void
+send_button_event( DFBInputDeviceButtonIdentifier button,
+ bool press )
+{
+ if (vncInputDevice) {
+ DFBInputEvent evt;
+
+ evt.flags = DIEF_NONE;
+ evt.type = press ? DIET_BUTTONPRESS : DIET_BUTTONRELEASE;
+ evt.button = button;
+
+ dfb_input_dispatch( vncInputDevice, &evt );
+ }
+}
+
+static void
+process_pointer_event(int buttonMask, int x, int y, rfbClientPtr cl)
+{
+ if (vncInputDevice) {
+ ClientData *cd = cl->clientData;
+ DFBInputEvent evt;
+
+ evt.type = DIET_AXISMOTION;
+ evt.flags = DIEF_AXISABS | DIEF_MIN | DIEF_MAX;
+
+ if (cd->oldx != x) {
+ cd->oldx = x;
+
+ evt.axis = DIAI_X;
+ evt.axisabs = x;
+ evt.min = 0;
+ evt.max = cd->vnc->shared->screen_size.w - 1;
+
+ dfb_input_dispatch( vncInputDevice, &evt );
+ }
+
+ if (cd->oldy != y) {
+ cd->oldy = y;
+
+ evt.axis = DIAI_Y;
+ evt.axisabs = y;
+ evt.min = 0;
+ evt.max = cd->vnc->shared->screen_size.h - 1;
+
+ dfb_input_dispatch( vncInputDevice, &evt );
+ }
+
+ if (buttonMask != cd->oldButtonMask) {
+ if ((buttonMask & (1 << 0)) != (cd->oldButtonMask & (1 << 0)))
+ send_button_event( DIBI_LEFT, !!(buttonMask & (1 << 0)) );
+
+ if ((buttonMask & (1 << 1)) != (cd->oldButtonMask & (1 << 1)))
+ send_button_event( DIBI_MIDDLE, !!(buttonMask & (1 << 1)) );
+
+ if ((buttonMask & (1 << 2)) != (cd->oldButtonMask & (1 << 2)))
+ send_button_event( DIBI_RIGHT, !!(buttonMask & (1 << 2)) );
+
+ cd->oldButtonMask = buttonMask;
+ }
+ }
+
+ rfbDefaultPtrAddEvent(buttonMask,x,y,cl);
+}
+
+/*
+ * declaration of private data
+ */
+static void
+process_key_event(rfbBool down, rfbKeySym key, rfbClientPtr cl)
+{
+ if (vncInputDevice) {
+ DFBInputEvent evt;
+
+ if (down)
+ evt.type = DIET_KEYPRESS;
+ else
+ evt.type = DIET_KEYRELEASE;
+
+ if (translate_key( key, &evt ))
+ dfb_input_dispatch( vncInputDevice, &evt );
+ }
+}
+
+
+static bool
+translate_key(rfbKeySym key, DFBInputEvent *evt )
+{
+ /* Unicode */
+ if (key <= 0xf000) {
+ evt->flags = DIEF_KEYSYMBOL;
+ evt->key_symbol = key;
+ return true;
+ }
+
+ /* Dead keys */
+ /* todo */
+
+ /* Numeric keypad */
+ if (key >= XK_KP_0 && key <= XK_KP_9) {
+ evt->flags = DIEF_KEYID;
+ evt->key_id = DIKI_KP_0 + key - XK_KP_0;
+ return true;
+ }
+
+ /* Function keys */
+ if (key >= XK_F1 && key <= XK_F11) {
+ evt->flags = DIEF_KEYID;
+ evt->key_id = DIKI_F1 + key - XK_F1;
+ return true;
+ }
+
+ switch (key) {
+ /* Numeric keypad */
+ case XK_KP_Decimal:
+ evt->flags = DIEF_KEYID;
+ evt->key_id = DIKI_KP_DECIMAL;
+ break;
+
+ case XK_KP_Separator:
+ evt->flags = DIEF_KEYID;
+ evt->key_id = DIKI_KP_SEPARATOR;
+ break;
+
+ case XK_KP_Divide:
+ evt->flags = DIEF_KEYID;
+ evt->key_id = DIKI_KP_DIV;
+ break;
+
+ case XK_KP_Multiply:
+ evt->flags = DIEF_KEYID;
+ evt->key_id = DIKI_KP_MULT;
+ break;
+
+ case XK_KP_Subtract:
+ evt->flags = DIEF_KEYID;
+ evt->key_id = DIKI_KP_MINUS;
+ break;
+
+ case XK_KP_Add:
+ evt->flags = DIEF_KEYID;
+ evt->key_id = DIKI_KP_PLUS;
+ break;
+
+ case XK_KP_Enter:
+ evt->flags = DIEF_KEYID;
+ evt->key_id = DIKI_KP_ENTER;
+ break;
+
+ case XK_KP_Equal:
+ evt->flags = DIEF_KEYID;
+ evt->key_id = DIKI_KP_EQUAL;
+ break;
+
+
+ /* Arrows + Home/End pad */
+ case XK_Up:
+ evt->flags = DIEF_KEYID;
+ evt->key_id = DIKI_UP;
+ break;
+
+ case XK_Down:
+ evt->flags = DIEF_KEYID;
+ evt->key_id = DIKI_DOWN;
+ break;
+
+ case XK_Right:
+ evt->flags = DIEF_KEYID;
+ evt->key_id = DIKI_RIGHT;
+ break;
+
+ case XK_Left:
+ evt->flags = DIEF_KEYID;
+ evt->key_id = DIKI_LEFT;
+ break;
+
+ case XK_Insert:
+ evt->flags = DIEF_KEYID;
+ evt->key_id = DIKI_INSERT;
+ break;
+
+ case XK_Delete:
+ evt->flags = DIEF_KEYID;
+ evt->key_id = DIKI_DELETE;
+ break;
+
+ case XK_Home:
+ evt->flags = DIEF_KEYID;
+ evt->key_id = DIKI_HOME;
+ break;
+
+ case XK_End:
+ evt->flags = DIEF_KEYID;
+ evt->key_id = DIKI_END;
+ break;
+
+ case XK_Page_Up:
+ evt->flags = DIEF_KEYID;
+ evt->key_id = DIKI_PAGE_UP;
+ break;
+
+ case XK_Page_Down:
+ evt->flags = DIEF_KEYID;
+ evt->key_id = DIKI_PAGE_DOWN;
+ break;
+
+
+ /* Key state modifier keys */
+ case XK_Num_Lock:
+ evt->flags = DIEF_KEYID;
+ evt->key_id = DIKI_NUM_LOCK;
+ break;
+
+ case XK_Caps_Lock:
+ evt->flags = DIEF_KEYID;
+ evt->key_id = DIKI_CAPS_LOCK;
+ break;
+
+ case XK_Scroll_Lock:
+ evt->flags = DIEF_KEYID;
+ evt->key_id = DIKI_SCROLL_LOCK;
+ break;
+
+ case XK_Shift_R:
+ evt->flags = DIEF_KEYID;
+ evt->key_id = DIKI_SHIFT_R;
+ break;
+
+ case XK_Shift_L:
+ evt->flags = DIEF_KEYID;
+ evt->key_id = DIKI_SHIFT_L;
+ break;
+
+ case XK_Control_R:
+ evt->flags = DIEF_KEYID;
+ evt->key_id = DIKI_CONTROL_R;
+ break;
+
+ case XK_Control_L:
+ evt->flags = DIEF_KEYID;
+ evt->key_id = DIKI_CONTROL_L;
+ break;
+
+ case XK_Alt_R:
+ evt->flags = DIEF_KEYID;
+ evt->key_id = DIKI_ALT_R;
+ break;
+
+ case XK_Alt_L:
+ evt->flags = DIEF_KEYID;
+ evt->key_id = DIKI_ALT_L;
+ break;
+
+ case XK_Meta_R:
+ evt->flags = DIEF_KEYID;
+ evt->key_id = DIKI_META_R;
+ break;
+
+ case XK_Meta_L:
+ evt->flags = DIEF_KEYID;
+ evt->key_id = DIKI_META_L;
+ break;
+
+ case XK_Super_L:
+ evt->flags = DIEF_KEYID;
+ evt->key_id = DIKI_SUPER_L;
+ break;
+
+ case XK_Super_R:
+ evt->flags = DIEF_KEYID;
+ evt->key_id = DIKI_SUPER_R;
+ break;
+
+ case XK_Hyper_L:
+ evt->flags = DIEF_KEYID;
+ evt->key_id = DIKI_HYPER_L;
+ break;
+
+ case XK_Hyper_R:
+ evt->flags = DIEF_KEYID;
+ evt->key_id = DIKI_HYPER_R;
+ break;
+
+ /*case ??:
+ evt->flags = DIEF_KEYID;
+ evt->key_id = DIKI_ALTGR;
+ break;*/
+
+ case XK_BackSpace:
+ evt->flags = DIEF_KEYID;
+ evt->key_id = DIKI_BACKSPACE;
+ break;
+
+ case XK_Tab:
+ evt->flags = DIEF_KEYID;
+ evt->key_id = DIKI_HYPER_L;
+ break;
+
+ case XK_Return:
+ evt->flags = DIEF_KEYID;
+ evt->key_id = DIKI_ENTER;
+ break;
+
+ case XK_Escape:
+ evt->flags = DIEF_KEYID;
+ evt->key_id = DIKI_ESCAPE;
+ break;
+
+ case XK_Pause:
+ evt->flags = DIEF_KEYID;
+ evt->key_id = DIKI_PAUSE;
+ break;
+
+ /* Miscellaneous function keys */
+ case XK_Help:
+ evt->flags = DIEF_KEYSYMBOL;
+ evt->key_symbol = DIKS_HELP;
+ break;
+
+ case XK_Print:
+ evt->flags = DIEF_KEYSYMBOL;
+ evt->key_symbol = DIKS_PRINT;
+ break;
+
+ case XK_Break:
+ evt->flags = DIEF_KEYSYMBOL;
+ evt->key_symbol = DIKS_BREAK;
+ break;
+
+ default:
+ return false;
+ }
+
+ return true;
+}
+