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/systems/x11/x11input.c | 768 +++++++++++++++++++++++++++++++++ 1 file changed, 768 insertions(+) create mode 100755 Source/DirectFB/systems/x11/x11input.c (limited to 'Source/DirectFB/systems/x11/x11input.c') diff --git a/Source/DirectFB/systems/x11/x11input.c b/Source/DirectFB/systems/x11/x11input.c new file mode 100755 index 0000000..0b711e0 --- /dev/null +++ b/Source/DirectFB/systems/x11/x11input.c @@ -0,0 +1,768 @@ +/* + (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 "xwindow.h" + +#include "primary.h" +#include "x11.h" + +#define DFB_INPUTDRIVER_HAS_SENSITIVITY + +#include + +D_DEBUG_DOMAIN( X11_Input, "X11/Input", "X11 Input/Key/Mouse handling" ); + +DFB_INPUT_DRIVER( x11input ) + + +extern DFBX11 *dfb_x11; + +/* + * declaration of private data + */ +typedef struct { + CoreInputDevice* device; + DirectThread* thread; + DFBX11* x11; + bool stop; +} X11InputData; + + +static DFBInputEvent motionX = { + .type = DIET_UNKNOWN, + .axisabs = 0, +}; + +static DFBInputEvent motionY = { + .type = DIET_UNKNOWN, + .axisabs = 0, +}; + +static void +motion_compress( int x, int y, const XEvent *xEvent ) +{ + if (motionX.axisabs != x) { + motionX.type = DIET_AXISMOTION; + motionX.flags = DIEF_AXISABS | DIEF_TIMESTAMP; + motionX.axis = DIAI_X; + motionX.axisabs = x; + + motionX.timestamp.tv_sec = xEvent->xmotion.time / 1000; + motionX.timestamp.tv_usec = (xEvent->xmotion.time % 1000) * 1000; + } + + if (motionY.axisabs != y) { + motionY.type = DIET_AXISMOTION; + motionY.flags = DIEF_AXISABS | DIEF_TIMESTAMP; + motionY.axis = DIAI_Y; + motionY.axisabs = y; + + motionY.timestamp.tv_sec = xEvent->xmotion.time / 1000; + motionY.timestamp.tv_usec = (xEvent->xmotion.time % 1000) * 1000; + } +} + +static void +motion_realize( X11InputData *data ) +{ + if (motionX.type != DIET_UNKNOWN) { + if (motionY.type != DIET_UNKNOWN) + motionX.flags |= DIEF_FOLLOW; + + if (dfb_x11->shared->xw) { + motionX.flags |= DIEF_MIN | DIEF_MAX; + motionX.min = 0; + motionX.max = dfb_x11->shared->xw->width - 1; + } + + dfb_input_dispatch( data->device, &motionX ); + + motionX.type = DIET_UNKNOWN; + } + + if (motionY.type != DIET_UNKNOWN) { + if (dfb_x11->shared->xw) { + motionY.flags |= DIEF_MIN | DIEF_MAX; + motionY.min = 0; + motionY.max = dfb_x11->shared->xw->height - 1; + } + + dfb_input_dispatch( data->device, &motionY ); + + motionY.type = DIET_UNKNOWN; + } +} + +static DFBInputDeviceKeyIdentifier +xsymbol_to_id( KeySym xKeySymbol ) +{ + switch (xKeySymbol) { + case XK_a : return DIKI_A; + case XK_b : return DIKI_B; + case XK_c : return DIKI_C; + case XK_d : return DIKI_D; + case XK_e : return DIKI_E; + case XK_f : return DIKI_F; + case XK_g : return DIKI_G; + case XK_h : return DIKI_H; + case XK_i : return DIKI_I; + case XK_j : return DIKI_J; + case XK_k : return DIKI_K; + case XK_l : return DIKI_L; + case XK_m : return DIKI_M; + case XK_n : return DIKI_N; + case XK_o : return DIKI_O; + case XK_p : return DIKI_P; + case XK_q : return DIKI_Q; + case XK_r : return DIKI_R; + case XK_s : return DIKI_S; + case XK_t : return DIKI_T; + case XK_u : return DIKI_U; + case XK_v : return DIKI_V; + case XK_w : return DIKI_W; + case XK_x : return DIKI_X; + case XK_y : return DIKI_Y; + case XK_z : return DIKI_Z; + case XK_0 : return DIKI_0; + case XK_1 : return DIKI_1; + case XK_2 : return DIKI_2; + case XK_3 : return DIKI_3; + case XK_4 : return DIKI_4; + case XK_5 : return DIKI_5; + case XK_6 : return DIKI_6; + case XK_7 : return DIKI_7; + case XK_8 : return DIKI_8; + case XK_9 : return DIKI_9; + case XK_F1 : return DIKI_F1; + case XK_F2 : return DIKI_F2; + case XK_F3 : return DIKI_F3; + case XK_F4 : return DIKI_F4; + case XK_F5 : return DIKI_F5; + case XK_F6 : return DIKI_F6; + case XK_F7 : return DIKI_F7; + case XK_F8 : return DIKI_F8; + case XK_F9 : return DIKI_F9; + case XK_F10 : return DIKI_F10; + case XK_F11 : return DIKI_F11; + case XK_F12 : return DIKI_F12; + + case XK_Shift_L : return DIKI_SHIFT_L; + case XK_Shift_R : return DIKI_SHIFT_R; + case XK_Control_L : return DIKI_CONTROL_L; + case XK_Control_R : return DIKI_CONTROL_R; + case XK_Alt_L : return DIKI_ALT_L; + case XK_Alt_R : return DIKI_ALT_R; + case XK_Meta_L : return DIKI_META_L; + case XK_Meta_R : return DIKI_META_R; + case XK_Super_L : return DIKI_SUPER_L; + case XK_Super_R : return DIKI_SUPER_R; + case XK_Hyper_L : return DIKI_HYPER_L; + case XK_Hyper_R : return DIKI_HYPER_R; + case XK_Mode_switch : return DIKI_ALT_R; + + case XK_Caps_Lock : return DIKI_CAPS_LOCK; + case XK_Num_Lock : return DIKI_NUM_LOCK; + case XK_Scroll_Lock : return DIKI_SCROLL_LOCK; + + case XK_Escape : return DIKI_ESCAPE; + case XK_Left : return DIKI_LEFT; + case XK_Right : return DIKI_RIGHT; + case XK_Up : return DIKI_UP; + case XK_Down : return DIKI_DOWN; + + case XK_Tab : return DIKI_TAB; + case XK_ISO_Left_Tab : return DIKI_TAB; + case XK_Return : return DIKI_ENTER; + case XK_space : return DIKI_SPACE; + case XK_BackSpace : return DIKI_BACKSPACE; + case XK_Insert : return DIKI_INSERT; + case XK_Delete : return DIKI_DELETE; + case XK_Home : return DIKI_HOME; + case XK_End : return DIKI_END; + case XK_Page_Up : return DIKI_PAGE_UP; + case XK_Page_Down : return DIKI_PAGE_DOWN; + case XK_Print : return DIKI_PRINT; + case XK_Pause : return DIKI_PAUSE; + + /* The labels on these keys depend on the type of keyboard. + * We've choosen the names from a US keyboard layout. The + * comments refer to the ISO 9995 terminology. + */ + case XK_quoteleft : return DIKI_QUOTE_LEFT; /* TLDE */ + case XK_minus : return DIKI_MINUS_SIGN; /* AE11 */ + case XK_equal : return DIKI_EQUALS_SIGN; /* AE12 */ + case XK_bracketleft : return DIKI_BRACKET_LEFT; /* AD11 */ + case XK_bracketright : return DIKI_BRACKET_RIGHT;/* AD12 */ + case XK_backslash : return DIKI_BACKSLASH; /* BKSL */ + case XK_semicolon : return DIKI_SEMICOLON; /* AC10 */ + case XK_quoteright : return DIKI_QUOTE_RIGHT; /* AC11 */ + case XK_comma : return DIKI_COMMA; /* AB08 */ + case XK_period : return DIKI_PERIOD; /* AB09 */ + case XK_slash : return DIKI_SLASH; /* AB10 */ + case XK_less : return DIKI_LESS_SIGN; /* 103rd */ + + case XK_KP_Divide : return DIKI_KP_DIV; + case XK_KP_Multiply : return DIKI_KP_MULT; + case XK_KP_Subtract : return DIKI_KP_MINUS; + case XK_KP_Add : return DIKI_KP_PLUS; + case XK_KP_Enter : return DIKI_KP_ENTER; + case XK_KP_Space : return DIKI_KP_SPACE; + case XK_KP_Tab : return DIKI_KP_TAB; + case XK_KP_F1 : return DIKI_KP_F1; + case XK_KP_F2 : return DIKI_KP_F2; + case XK_KP_F3 : return DIKI_KP_F3; + case XK_KP_F4 : return DIKI_KP_F4; + case XK_KP_Equal : return DIKI_KP_EQUAL; + case XK_KP_Separator : return DIKI_KP_SEPARATOR; + + case XK_KP_Delete : return DIKI_KP_DECIMAL; + case XK_KP_Insert : return DIKI_KP_0; + case XK_KP_End : return DIKI_KP_1; + case XK_KP_Down : return DIKI_KP_2; + case XK_KP_Page_Down : return DIKI_KP_3; + case XK_KP_Left : return DIKI_KP_4; + case XK_KP_Begin : return DIKI_KP_5; + case XK_KP_Right : return DIKI_KP_6; + case XK_KP_Home : return DIKI_KP_7; + case XK_KP_Up : return DIKI_KP_8; + case XK_KP_Page_Up : return DIKI_KP_9; + + case XK_KP_Decimal : return DIKI_KP_DECIMAL; + case XK_KP_0 : return DIKI_KP_0; + case XK_KP_1 : return DIKI_KP_1; + case XK_KP_2 : return DIKI_KP_2; + case XK_KP_3 : return DIKI_KP_3; + case XK_KP_4 : return DIKI_KP_4; + case XK_KP_5 : return DIKI_KP_5; + case XK_KP_6 : return DIKI_KP_6; + case XK_KP_7 : return DIKI_KP_7; + case XK_KP_8 : return DIKI_KP_8; + case XK_KP_9 : return DIKI_KP_9; + + case 0 : break; + + default: + D_DEBUG_AT( X11_Input, "Unknown key symbol 0x%lx\n", xKeySymbol); + } + + return DIKI_UNKNOWN; +} + +static DFBInputDeviceKeySymbol +xsymbol_to_symbol( KeySym xKeySymbol ) +{ + if (xKeySymbol >= 0x20 && xKeySymbol <= 0xff) + return xKeySymbol; + + if (xKeySymbol >= XK_F1 && xKeySymbol <= XK_F35) + return DFB_FUNCTION_KEY( xKeySymbol - XK_F1 + 1 ); + + switch (xKeySymbol) { + case XK_Shift_L : return DIKS_SHIFT; + case XK_Shift_R : return DIKS_SHIFT; + case XK_Control_L : return DIKS_CONTROL; + case XK_Control_R : return DIKS_CONTROL; + case XK_Alt_L : return DIKS_ALT; + case XK_Alt_R : return DIKS_ALT; + case XK_Meta_L : return DIKS_META; + case XK_Meta_R : return DIKS_META; + case XK_Super_L : return DIKS_SUPER; + case XK_Super_R : return DIKS_SUPER; + case XK_Hyper_L : return DIKS_HYPER; + case XK_Hyper_R : return DIKS_HYPER; + case XK_Mode_switch : return DIKS_ALTGR; + + case XK_Caps_Lock : return DIKS_CAPS_LOCK; + case XK_Num_Lock : return DIKS_NUM_LOCK; + case XK_Scroll_Lock : return DIKS_SCROLL_LOCK; + + case XK_Escape : return DIKS_ESCAPE; + case XK_Left : return DIKS_CURSOR_LEFT; + case XK_Right : return DIKS_CURSOR_RIGHT; + case XK_Up : return DIKS_CURSOR_UP; + case XK_Down : return DIKS_CURSOR_DOWN; + + case XK_Tab : return DIKS_TAB; + case XK_ISO_Left_Tab : return DIKS_TAB; + case XK_Return : return DIKS_ENTER; + case XK_space : return DIKS_SPACE; + case XK_BackSpace : return DIKS_BACKSPACE; + case XK_Insert : return DIKS_INSERT; + case XK_Delete : return DIKS_DELETE; + case XK_Home : return DIKS_HOME; + case XK_End : return DIKS_END; + case XK_Page_Up : return DIKS_PAGE_UP; + case XK_Page_Down : return DIKS_PAGE_DOWN; + case XK_Print : return DIKS_PRINT; + case XK_Pause : return DIKS_PAUSE; + + case XK_KP_Divide : return DIKS_SLASH; + case XK_KP_Multiply : return DIKS_ASTERISK; + case XK_KP_Subtract : return DIKS_MINUS_SIGN; + case XK_KP_Add : return DIKS_PLUS_SIGN; + case XK_KP_Enter : return DIKS_ENTER; + case XK_KP_Space : return DIKS_SPACE; + case XK_KP_Tab : return DIKS_TAB; + case XK_KP_F1 : return DIKS_F1; + case XK_KP_F2 : return DIKS_F2; + case XK_KP_F3 : return DIKS_F3; + case XK_KP_F4 : return DIKS_F4; + case XK_KP_Equal : return DIKS_EQUALS_SIGN; + case XK_KP_Separator : return DIKS_COLON; /* FIXME: what is a separator */ + + case XK_KP_Delete : return DIKS_DELETE; + case XK_KP_Insert : return DIKS_INSERT; + case XK_KP_End : return DIKS_END; + case XK_KP_Down : return DIKS_CURSOR_DOWN; + case XK_KP_Page_Down : return DIKS_PAGE_DOWN; + case XK_KP_Left : return DIKS_CURSOR_LEFT; + case XK_KP_Begin : return DIKS_BEGIN; + case XK_KP_Right : return DIKS_CURSOR_RIGHT; + case XK_KP_Home : return DIKS_HOME; + case XK_KP_Up : return DIKS_CURSOR_UP; + case XK_KP_Page_Up : return DIKS_PAGE_UP; + + case XK_KP_Decimal : return DIKS_PERIOD; + case XK_KP_0 : return DIKS_0; + case XK_KP_1 : return DIKS_1; + case XK_KP_2 : return DIKS_2; + case XK_KP_3 : return DIKS_3; + case XK_KP_4 : return DIKS_4; + case XK_KP_5 : return DIKS_5; + case XK_KP_6 : return DIKS_6; + case XK_KP_7 : return DIKS_7; + case XK_KP_8 : return DIKS_8; + case XK_KP_9 : return DIKS_9; + + case 0 : break; + + default: + D_DEBUG("X11: Unknown key symbol 0x%lx\n", xKeySymbol); + } + + return DIKS_NULL; +} + + + +static void handleMouseEvent(XEvent* pXEvent, X11InputData* pData) +{ + static int iMouseEventCount = 0; + DFBInputEvent dfbEvent; + if (pXEvent->type == MotionNotify) { + motion_compress( pXEvent->xmotion.x, pXEvent->xmotion.y, pXEvent ); + ++iMouseEventCount; + } + + if ( pXEvent->type == ButtonPress || pXEvent->type == ButtonRelease ) { + if ( pXEvent->type == ButtonPress ) + dfbEvent.type = DIET_BUTTONPRESS; + else + dfbEvent.type = DIET_BUTTONRELEASE; + + dfbEvent.flags = DIEF_TIMESTAMP; + + /* Get pressed button */ + switch ( pXEvent->xbutton.button ) { + case 1: + dfbEvent.button = DIBI_LEFT; + break; + case 2: + dfbEvent.button = DIBI_MIDDLE; + break; + case 3: + dfbEvent.button = DIBI_RIGHT; + break; + //Wheel events + case 4: /*up*/ + case 5: /*down*/ + case 6: /*left*/ + case 7: /*right*/ + if (pXEvent->type == ButtonPress) { + dfbEvent.type = DIET_AXISMOTION; + dfbEvent.flags = DIEF_AXISREL; + dfbEvent.axis = DIAI_Z; + /*SCROLL UP*/ + if ( pXEvent->xbutton.button == 4 ) { + dfbEvent.axisrel = -1; + } + /*SCROLL DOWN */ + else if (pXEvent->xbutton.button == 5) { + dfbEvent.axisrel = 1; + } + /*SCROLL LEFT*/ + else if (pXEvent->xbutton.button == 6) { + dfbEvent.axis = DIAI_X; + dfbEvent.axisrel = -1; + } + /*SCROLL RIGHT*/ + else if (pXEvent->xbutton.button == 7 ) { + dfbEvent.axis = DIAI_X; + dfbEvent.axisrel = 1; + } + } + else + return; + break; + default: + break; + } + + dfbEvent.timestamp.tv_sec = pXEvent->xbutton.time / 1000; + dfbEvent.timestamp.tv_usec = (pXEvent->xbutton.time % 1000) * 1000; + + dfb_input_dispatch( pData->device, &dfbEvent ); + ++iMouseEventCount; + } +} + +static void +handle_expose( const XExposeEvent *expose ) +{ + CoreLayer *layer = dfb_layer_at( DLID_PRIMARY ); + const DisplayLayerFuncs *funcs = layer->funcs; + CoreLayerContext *context; + + D_ASSERT( funcs != NULL ); + D_ASSERT( funcs->UpdateRegion != NULL ); + + /* Get the currently active context. */ + if (dfb_layer_get_active_context( layer, &context ) == DFB_OK) { + CoreLayerRegion *region; + + /* Get the first region. */ + if (dfb_layer_context_get_primary_region( context, + false, ®ion ) == DFB_OK) + { + /* Lock the region to avoid tearing due to concurrent updates. */ + dfb_layer_region_lock( region ); + + /* Get the surface of the region. */ + if (region->surface && region->surface_lock.buffer) { + DFBRegion update = { expose->x, expose->y, + expose->x + expose->width - 1, + expose->y + expose->height - 1 }; + + funcs->UpdateRegion( layer, layer->driver_data, layer->layer_data, + region->region_data, region->surface, &update, ®ion->surface_lock ); + } + + /* Unlock the region. */ + dfb_layer_region_unlock( region ); + + /* Release the region. */ + dfb_layer_region_unref( region ); + } + + /* Release the context. */ + dfb_layer_context_unref( context ); + } +} + +/* + * Input thread reading from device. + * Generates events on incoming data. + */ +static void* +x11EventThread( DirectThread *thread, void *driver_data ) +{ + X11InputData *data = driver_data; + DFBX11 *x11 = data->x11; + DFBX11Shared *shared = x11->shared; + + while (!data->stop) { + unsigned int pull = 23; + XEvent xEvent; + DFBInputEvent dfbEvent; + + /* FIXME: Detect key repeats, we're receiving KeyPress, KeyRelease, KeyPress, KeyRelease... !!?? */ + + if (!shared->xw || !shared->xw->window) { + /* no window, so no event */ + usleep( 50000 ); + continue; + } + + usleep( 10000 ); + + XLockDisplay( x11->display ); + + while (!data->stop && pull-- && XPending( x11->display )) { + XNextEvent( x11->display, &xEvent ); + + XUnlockDisplay( x11->display ); + + D_DEBUG_AT( X11_Input, "Event received: %d\n", xEvent.type ); + + switch (xEvent.type) { + case ButtonPress: + case ButtonRelease: + motion_realize( data ); + case MotionNotify: + handleMouseEvent( &xEvent, data ); // crash ??? + break; + + case KeyPress: + case KeyRelease: { + motion_realize( data ); + + dfbEvent.type = (xEvent.type == KeyPress) ? DIET_KEYPRESS : DIET_KEYRELEASE; + dfbEvent.flags = DIEF_KEYCODE | DIEF_TIMESTAMP; + dfbEvent.key_code = xEvent.xkey.keycode; + + dfbEvent.timestamp.tv_sec = xEvent.xkey.time / 1000; + dfbEvent.timestamp.tv_usec = (xEvent.xkey.time % 1000) * 1000; + + dfb_input_dispatch( data->device, &dfbEvent ); + break; + } + + case Expose: + handle_expose( &xEvent.xexpose ); + break; + + case DestroyNotify: + /* this event is mainly to unblock XNextEvent. */ + break; + + default: + break; + } + + XLockDisplay( x11->display ); + } + + XUnlockDisplay( x11->display ); + + if (!data->stop) + motion_realize( data ); + } + + return NULL; +} + +/* exported symbols */ + +/* + * Return the number of available devices. + * Called once during initialization of DirectFB. + */ +static int +driver_get_available( void ) +{ + return dfb_system_type() == CORE_X11; +} + +/* + * Fill out general information about this driver. + * Called once during initialization of DirectFB. + */ +static void +driver_get_info( InputDriverInfo *info ) +{ + /* fill driver info structure */ + snprintf ( info->name, DFB_INPUT_DRIVER_INFO_NAME_LENGTH, "X11 Input Driver" ); + snprintf ( info->vendor, DFB_INPUT_DRIVER_INFO_VENDOR_LENGTH, "directfb.org" ); + + info->version.major = 0; + info->version.minor = 1; +} + +/* + * Open the device, fill out information about it, + * allocate and fill private data, start input thread. + * Called during initialization, resuming or taking over mastership. + */ +static DFBResult +driver_open_device( CoreInputDevice *device, + unsigned int number, + InputDeviceInfo *info, + void **driver_data ) +{ + X11InputData *data; + DFBX11 *x11 = dfb_system_data(); + DFBX11Shared *shared = x11->shared; + + D_DEBUG_AT( X11_Input, "%s()\n", __FUNCTION__ ); + + fusion_skirmish_prevail( &shared->lock ); + + fusion_skirmish_dismiss( &shared->lock ); + + /* set device vendor and name */ + snprintf( info->desc.vendor, DFB_INPUT_DEVICE_DESC_VENDOR_LENGTH, "XServer" ); + snprintf( info->desc.name, DFB_INPUT_DEVICE_DESC_NAME_LENGTH, "X11 Input" ); + + /* set one of the primary input device IDs */ + info->prefered_id = DIDID_KEYBOARD; + + /* set type flags */ + info->desc.type = DIDTF_JOYSTICK | DIDTF_KEYBOARD | DIDTF_MOUSE; + + /* set capabilities */ + info->desc.caps = DICAPS_ALL; + + /* enable translation of fake raw hardware keycodes */ + info->desc.min_keycode = 8; + info->desc.max_keycode = 255; + + + /* allocate and fill private data */ + data = D_CALLOC( 1, sizeof(X11InputData) ); + + data->device = device; + data->x11 = x11; + + /* start input thread */ + data->thread = direct_thread_create( DTT_INPUT, x11EventThread, data, "X11 Input" ); + + /* set private data pointer */ + *driver_data = data; + + return DFB_OK; +} + +/* + * Fetch one entry from the device's keymap if supported. + * this does a fake mapping based on the orginal DFB code + */ +static DFBResult +driver_get_keymap_entry( CoreInputDevice *device, + void *driver_data, + DFBInputDeviceKeymapEntry *entry ) +{ + int i; + X11InputData *data = driver_data; + DFBX11 *x11 = data->x11; + + XLockDisplay( x11->display ); + + for (i=0; i<4; i++) { + KeySym xSymbol = XKeycodeToKeysym( x11->display, entry->code, i ); + + if (i == 0) + entry->identifier = xsymbol_to_id( xSymbol ); + + entry->symbols[i] = xsymbol_to_symbol( xSymbol ); + } + + XUnlockDisplay( x11->display ); + + /* is CapsLock effective? */ + if (entry->identifier >= DIKI_A && entry->identifier <= DIKI_Z) + entry->locks |= DILS_CAPS; + + /* is NumLock effective? */ + if (entry->identifier >= DIKI_KP_DECIMAL && entry->identifier <= DIKI_KP_9) + entry->locks |= DILS_NUM; + + return DFB_OK; +} + +/* + * End thread, close device and free private data. + */ +static DFBResult +driver_set_sensitivity( CoreInputDevice *device, + void *driver_data, + int sensitivity ) +{ + D_DEBUG_AT( X11_Input, "%s( %d )\n", __FUNCTION__, sensitivity ); + + return DFB_OK; +} + +/* + * End thread, close device and free private data. + */ +static void +driver_close_device( void *driver_data ) +{ + X11InputData *data = driver_data; + DFBX11 *x11 = data->x11; + DFBX11Shared *shared = x11->shared; + + D_DEBUG_AT( X11_Input, "%s()\n", __FUNCTION__ ); + + /* stop input thread */ + data->stop = true; + + XLockDisplay( x11->display ); + + if (shared->xw) { + XWindow *xw = shared->xw; + + shared->xw = NULL; + + /* the window must generate an event, otherwise the input thread will not end */ + dfb_x11_close_window( x11, xw ); + } + + XSync( x11->display, False ); + + XUnlockDisplay( x11->display ); + + /* it is possible that this "close" function is called from the same + * thread that the input device is actually running on. + * This happens when you e.g. click the close box with your mouse. + * As a fix, we check if we are this thread. */ + if (data->thread != direct_thread_self()) { + direct_thread_join( data->thread ); + direct_thread_destroy( data->thread ); + } + + /* free private data */ + D_FREE ( data ); +} + -- cgit