Mercurial > sdl-ios-xcode
view src/video/symbian/EKA2/SDL_epocevents.cpp @ 4170:092c0bc69155 SDL-1.2
Fixed bug #618
Description From Tim Angus 2008-08-30 12:23:56 (-) [reply]
As we all know SDL 1.2 doesn't handle dead keys well since one key press
potentially equals two (or more) characters. For example, on many layouts,
keying <backquote>,<space> results in <no character>,<backquote><space>. Since
the unicode member of the SDL_keysym struct only has room for one character,
only one can be returned.
On Linux, the first character is returned. On Windows however, unless the exact
number of characters generated by the keypress is 1, nothing is returned. The
following patch addresses this inconsistency.
Updated patch which includes a further fix to the handling of the numpad when
numlock is on. This further fix is courtesy Amanieu d'Antras.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Mon, 13 Apr 2009 08:42:09 +0000 |
parents | e85e65aec22f |
children |
line wrap: on
line source
#include "epoc_sdl.h" #include <stdio.h> #undef NULL extern "C" { //#define DEBUG_TRACE_ENABLED #include "SDL_error.h" #include "SDL_video.h" #include "SDL_keysym.h" #include "SDL_keyboard.h" #include "SDL_events_c.h" #include "SDL_timer.h" } /* extern "C" */ #include "SDL_epocvideo.h" #include "SDL_epocevents_c.h" #include "sdlepocapi.h" #include <eikenv.h> #include<bautils.h> extern "C" { static SDL_keysym *TranslateKey(_THIS, int scancode, SDL_keysym *keysym); } //extern "C" { /* The translation tables from a console scancode to a SDL keysym */ static SDLKey keymap[MAX_SCANCODE]; static SDL_keysym *TranslateKey(_THIS, int scancode, SDL_keysym *keysym); void DisableKeyBlocking(_THIS); //} /* extern "C" */ SDLKey* KeyMap() { return keymap; } TBool isCursorVisible = EFalse; void ResetKeyMap() { int i; /* Initialize the key translation table */ for ( i=0; i<SDL_TABLESIZE(keymap); ++i ) keymap[i] = SDLK_UNKNOWN; /* Numbers */ for ( i = 0; i<32; ++i ){ keymap[' ' + i] = (SDLKey)(SDLK_SPACE+i); } /* e.g. Alphabet keys */ for ( i = 0; i<32; ++i ){ keymap['A' + i] = (SDLKey)(SDLK_a+i); } keymap[EStdKeyBackspace] = SDLK_BACKSPACE; keymap[EStdKeyTab] = SDLK_TAB; keymap[EStdKeyEnter] = SDLK_RETURN; keymap[EStdKeyEscape] = SDLK_ESCAPE; keymap[EStdKeySpace] = SDLK_SPACE; keymap[EStdKeyPause] = SDLK_PAUSE; keymap[EStdKeyHome] = SDLK_HOME; keymap[EStdKeyEnd] = SDLK_END; keymap[EStdKeyPageUp] = SDLK_PAGEUP; keymap[EStdKeyPageDown] = SDLK_PAGEDOWN; keymap[EStdKeyDelete] = SDLK_DELETE; keymap[EStdKeyUpArrow] = SDLK_UP; keymap[EStdKeyDownArrow] = SDLK_DOWN; keymap[EStdKeyLeftArrow] = SDLK_LEFT; keymap[EStdKeyRightArrow] = SDLK_RIGHT; keymap[EStdKeyCapsLock] = SDLK_CAPSLOCK; keymap[EStdKeyLeftShift] = SDLK_LSHIFT; keymap[EStdKeyRightShift] = SDLK_RSHIFT; keymap[EStdKeyLeftAlt] = SDLK_LALT; keymap[EStdKeyRightAlt] = SDLK_RALT; keymap[EStdKeyLeftCtrl] = SDLK_LCTRL; keymap[EStdKeyRightCtrl] = SDLK_RCTRL; keymap[EStdKeyLeftFunc] = SDLK_LMETA; keymap[EStdKeyRightFunc] = SDLK_RMETA; keymap[EStdKeyInsert] = SDLK_INSERT; keymap[EStdKeyComma] = SDLK_COMMA; keymap[EStdKeyFullStop] = SDLK_PERIOD; keymap[EStdKeyForwardSlash] = SDLK_SLASH; keymap[EStdKeyBackSlash] = SDLK_BACKSLASH; keymap[EStdKeySemiColon] = SDLK_SEMICOLON; keymap[EStdKeySingleQuote] = SDLK_QUOTE; keymap[EStdKeyHash] = SDLK_HASH; keymap[EStdKeySquareBracketLeft] = SDLK_LEFTBRACKET; keymap[EStdKeySquareBracketRight] = SDLK_RIGHTBRACKET; keymap[EStdKeyMinus] = SDLK_MINUS; keymap[EStdKeyEquals] = SDLK_EQUALS; keymap[EStdKeyF1] = SDLK_F1; keymap[EStdKeyF2] = SDLK_F2; keymap[EStdKeyF3] = SDLK_F3; keymap[EStdKeyF4] = SDLK_F4; keymap[EStdKeyF5] = SDLK_F5; keymap[EStdKeyF6] = SDLK_F6; keymap[EStdKeyF7] = SDLK_F7; keymap[EStdKeyF8] = SDLK_F8; keymap[EStdKeyF9] = SDLK_F9; keymap[EStdKeyF10] = SDLK_F10; keymap[EStdKeyF11] = SDLK_F11; keymap[EStdKeyF12] = SDLK_F12; keymap[EStdKeyXXX] = SDLK_RETURN; /* "fire" key */ keymap[EStdKeyDevice3] = SDLK_RETURN; /* "fire" key */ keymap[EStdKeyNkpAsterisk] = SDLK_ASTERISK; keymap[EStdKeyYes] = SDLK_HOME; /* "call" key */ keymap[EStdKeyNo] = SDLK_END; /* "end call" key */ keymap[EStdKeyDevice0] = SDLK_SPACE; /* right menu key */ keymap[EStdKeyDevice1] = SDLK_ESCAPE; /* left menu key */ keymap[EStdKeyDevice2] = SDLK_POWER; /* power key */ keymap[EStdKeyMenu] = SDLK_MENU; // menu key keymap[EStdKeyDevice6] = SDLK_LEFT; // Rocker (joystick) left keymap[EStdKeyDevice7] = SDLK_RIGHT; // Rocker (joystick) right keymap[EStdKeyDevice8] = SDLK_UP; // Rocker (joystick) up keymap[EStdKeyDevice9] = SDLK_DOWN; // Rocker (joystick) down keymap[EStdKeyLeftFunc] = SDLK_LALT; //chr? keymap[EStdKeyRightFunc] = SDLK_RALT; keymap[EStdKeyDeviceA] = SDLK_RETURN; /* "fire" key */ /////////////////////////////////////////////////////////// /* RFs fs; if(KErrNone == fs.Connect()) { RArray<TInt> array; TRAPD(err, ReadL(fs, array)); if(err == KErrNone && array.Count() > 0) { SDLKey temp[MAX_SCANCODE]; Mem::Copy(temp, keymap, MAX_SCANCODE * sizeof(SDLKey)); for(TInt k = 0; k < array.Count(); k+= 2) { const TInt oldval = array[k]; const TInt newval = array[k + 1]; if(oldval >= 0 && oldval < MAX_SCANCODE && newval >= 0 && newval < MAX_SCANCODE) { keymap[oldval] = temp[newval]; } } } array.Close(); } fs.Close();*/ /////////////////////////////////////////////////////////// keymap[EStdKeyNumLock] = SDLK_NUMLOCK; keymap[EStdKeyScrollLock] = SDLK_SCROLLOCK; keymap[EStdKeyNkpForwardSlash] = SDLK_KP_DIVIDE; keymap[EStdKeyNkpAsterisk] = SDLK_KP_MULTIPLY; keymap[EStdKeyNkpMinus] = SDLK_KP_MINUS; keymap[EStdKeyNkpPlus] = SDLK_KP_PLUS; keymap[EStdKeyNkpEnter] = SDLK_KP_ENTER; keymap[EStdKeyNkp1] = SDLK_KP1; keymap[EStdKeyNkp2] = SDLK_KP2; keymap[EStdKeyNkp3] = SDLK_KP3; keymap[EStdKeyNkp4] = SDLK_KP4; keymap[EStdKeyNkp5] = SDLK_KP5; keymap[EStdKeyNkp6] = SDLK_KP6; keymap[EStdKeyNkp7] = SDLK_KP7; keymap[EStdKeyNkp8] = SDLK_KP8; keymap[EStdKeyNkp9] = SDLK_KP9; keymap[EStdKeyNkp0] = SDLK_KP0; keymap[EStdKeyNkpFullStop] = SDLK_KP_PERIOD; /* keymap[EStdKeyMenu] = SDLK_MENU; should be, but not yet keymap[EStdKeyBacklightOn] = keymap[EStdKeyBacklightOff] = keymap[EStdKeyBacklightToggle] = keymap[EStdKeyIncContrast] = keymap[EStdKeyDecContrast] = keymap[EStdKeySliderDown] = keymap[EStdKeySliderUp] = keymap[EStdKeyDictaphonePlay] = keymap[EStdKeyDictaphoneStop] = keymap[EStdKeyDictaphoneRecord] = keymap[EStdKeyHelp] = keymap[EStdKeyOff] = keymap[EStdKeyDial] = keymap[EStdKeyIncVolume] = keymap[EStdKeyDecVolume] = keymap[EStdKeyDevice0] = keymap[EStdKeyDevice1] = keymap[EStdKeyDevice2] = keymap[EStdKeyDevice3] = keymap[EStdKeyDevice4] = keymap[EStdKeyDevice5] = keymap[EStdKeyDevice6] = keymap[EStdKeyDevice7] = keymap[EStdKeyDevice8] = keymap[EStdKeyDevice9] = keymap[EStdKeyDeviceA] = keymap[EStdKeyDeviceB] = keymap[EStdKeyDeviceC] = keymap[EStdKeyDeviceD] = keymap[EStdKeyDeviceE] = keymap[EStdKeyDeviceF] = keymap[EStdKeyApplication0] = keymap[EStdKeyApplication1] = keymap[EStdKeyApplication2] = keymap[EStdKeyApplication3] = keymap[EStdKeyApplication4] = keymap[EStdKeyApplication5] = keymap[EStdKeyApplication6] = keymap[EStdKeyApplication7] = keymap[EStdKeyApplication8] = keymap[EStdKeyApplication9] = keymap[EStdKeyApplicationA] = keymap[EStdKeyApplicationB] = keymap[EStdKeyApplicationC] = keymap[EStdKeyApplicationD] = keymap[EStdKeyApplicationE] = keymap[EStdKeyApplicationF] = keymap[EStdKeyYes] = keymap[EStdKeyNo] = keymap[EStdKeyIncBrightness] = keymap[EStdKeyDecBrightness] = keymap[EStdKeyCaseOpen] = keymap[EStdKeyCaseClose] = */ } int EPOC_HandleWsEvent(_THIS, const TWsEvent& aWsEvent) { int posted = 0; SDL_keysym keysym; // SDL_TRACE1("hws %d", aWsEvent.Type()); switch (aWsEvent.Type()) { case EEventPointer: /* Mouse pointer events */ { /* const TPointerCursorMode mode = EpocSdlEnv::PointerMode(); if(mode == EPointerCursorNone) { return 0; //TODO: Find out why events are get despite of cursor should be off } */ const TPointerEvent* pointerEvent = aWsEvent.Pointer(); const TPoint mousePos = EpocSdlEnv::WindowCoordinates(pointerEvent->iPosition); /*!! TODO Pointer do not yet work properly //SDL_TRACE1("SDL: EPOC_HandleWsEvent, pointerEvent->iType=%d", pointerEvent->iType); //!! if (Private->EPOC_ShrinkedHeight) { mousePos.iY <<= 1; // Scale y coordinate to shrinked screen height } if (Private->EPOC_ShrinkedWidth) { mousePos.iX <<= 1; // Scale x coordinate to shrinked screen width } */ posted += SDL_PrivateMouseMotion(0, 0, mousePos.iX, mousePos.iY); /* Absolute position on screen */ switch (pointerEvent->iType) { case TPointerEvent::EButton1Down: posted += SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_LEFT, 0, 0); break; case TPointerEvent::EButton1Up: posted += SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_LEFT, 0, 0); break; case TPointerEvent::EButton2Down: posted += SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_RIGHT, 0, 0); break; case TPointerEvent::EButton2Up: posted += SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_RIGHT, 0, 0); break; case TPointerEvent::EButton3Down: posted += SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_MIDDLE, 0, 0); break; case TPointerEvent::EButton3Up: posted += SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_MIDDLE, 0, 0); break; } // switch break; } case EEventKeyDown: /* Key events */ { #ifdef SYMBIAN_CRYSTAL // special case: 9300/9500 rocker down, simulate left mouse button if (aWsEvent.Key()->iScanCode == EStdKeyDeviceA) { const TPointerCursorMode mode = Private->EPOC_WsSession.PointerCursorMode(); if(mode != EPointerCursorNone) posted += SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_LEFT, 0, 0); } #endif (void*)TranslateKey(_this, aWsEvent.Key()->iScanCode, &keysym); #ifndef DISABLE_JOYSTICK /* Special handling */ switch((int)keysym.sym) { case SDLK_CAPSLOCK: if (!isCursorVisible) { /* Enable virtual cursor */ HAL::Set(HAL::EMouseState, HAL::EMouseState_Visible); } else { /* Disable virtual cursor */ HAL::Set(HAL::EMouseState, HAL::EMouseState_Invisible); } isCursorVisible = !isCursorVisible; break; } #endif posted += SDL_PrivateKeyboard(SDL_PRESSED, &keysym); break; } case EEventKeyUp: /* Key events */ { #ifdef SYMBIAN_CRYSTAL // special case: 9300/9500 rocker up, simulate left mouse button if (aWsEvent.Key()->iScanCode == EStdKeyDeviceA) { posted += SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_LEFT, 0, 0); } #endif posted += SDL_PrivateKeyboard(SDL_RELEASED, TranslateKey(_this, aWsEvent.Key()->iScanCode, &keysym)); break; } case EEventFocusGained: /* SDL window got focus */ { Private->iIsWindowFocused = ETrue; posted += SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS|SDL_APPMOUSEFOCUS); /* Draw window background and screen buffer */ DisableKeyBlocking(_this); //Markus: guess why:-) //RedrawWindowL(_this); break; } case EEventFocusLost: /* SDL window lost focus */ { Private->iIsWindowFocused = EFalse; posted += SDL_PrivateAppActive(0, SDL_APPINPUTFOCUS|SDL_APPMOUSEFOCUS); break; } case EEventModifiersChanged: { TModifiersChangedEvent* modEvent = aWsEvent.ModifiersChanged(); TUint modstate = KMOD_NONE; if (modEvent->iModifiers == EModifierLeftShift) modstate |= KMOD_LSHIFT; if (modEvent->iModifiers == EModifierRightShift) modstate |= KMOD_RSHIFT; if (modEvent->iModifiers == EModifierLeftCtrl) modstate |= KMOD_LCTRL; if (modEvent->iModifiers == EModifierRightCtrl) modstate |= KMOD_RCTRL; if (modEvent->iModifiers == EModifierLeftAlt) modstate |= KMOD_LALT; if (modEvent->iModifiers == EModifierRightAlt) modstate |= KMOD_RALT; if (modEvent->iModifiers == EModifierLeftFunc) modstate |= KMOD_LMETA; if (modEvent->iModifiers == EModifierRightFunc) modstate |= KMOD_RMETA; if (modEvent->iModifiers == EModifierCapsLock) modstate |= KMOD_CAPS; SDL_SetModState(STATIC_CAST(SDLMod,(modstate | KMOD_LSHIFT))); break; } case EEventScreenDeviceChanged: { EpocSdlEnv::WaitDeviceChange(); } break; default: break; } return posted; } extern "C" { void EPOC_PumpEvents(_THIS) { MEventQueue& events = EpocSdlEnv::EventQueue(); while(events.HasData()) { events.Lock(); //there have to be a copy, so we can release //lock immediately. HandleWsEvent may cause //deadlock otherwise. const TWsEvent event = events.Shift(); events.Unlock(); // const TWsEvent& event = events.Top(); EPOC_HandleWsEvent(_this, event); // events.Shift(); } } void EPOC_InitOSKeymap(_THIS) { ResetKeyMap(); EpocSdlEnv::ObserverEvent(MSDLObserver::EEventKeyMapInit ,0); } static SDL_keysym *TranslateKey(_THIS, int scancode, SDL_keysym *keysym) { // char debug[256]; //SDL_TRACE1("SDL: TranslateKey, scancode=%d", scancode); //!! /* Set the keysym information */ keysym->scancode = scancode; if ((scancode >= MAX_SCANCODE) && ((scancode - ENonCharacterKeyBase + 0x0081) >= MAX_SCANCODE)) { SDL_SetError("Too big scancode"); keysym->scancode = SDLK_UNKNOWN; keysym->mod = KMOD_NONE; return keysym; } keysym->mod = SDL_GetModState(); /* Handle function keys: F1, F2, F3 ... */ if (keysym->mod & KMOD_META) { if (scancode >= 'A' && scancode < ('A' + 24)) { /* first 32 alphabet keys */ switch(scancode) { case 'Q': scancode = EStdKeyF1; break; case 'W': scancode = EStdKeyF2; break; case 'E': scancode = EStdKeyF3; break; case 'R': scancode = EStdKeyF4; break; case 'T': scancode = EStdKeyF5; break; case 'Y': scancode = EStdKeyF6; break; case 'U': scancode = EStdKeyF7; break; case 'I': scancode = EStdKeyF8; break; case 'A': scancode = EStdKeyF9; break; case 'S': scancode = EStdKeyF10; break; case 'D': scancode = EStdKeyF11; break; case 'F': scancode = EStdKeyF12; break; } keysym->sym = keymap[scancode]; } } if (scancode >= ENonCharacterKeyBase) { // Non character keys keysym->sym = keymap[scancode - ENonCharacterKeyBase + 0x0081]; // !!hard coded } else { keysym->sym = keymap[scancode]; } /* Remap the arrow keys if the device is rotated */ /* if (Private->EPOC_ScreenOrientation == CFbsBitGc::EGraphicsOrientationRotated270) { switch(keysym->sym) { case SDLK_UP: keysym->sym = SDLK_LEFT; break; case SDLK_DOWN: keysym->sym = SDLK_RIGHT; break; case SDLK_LEFT: keysym->sym = SDLK_DOWN; break; case SDLK_RIGHT:keysym->sym = SDLK_UP; break; } } */ /* If UNICODE is on, get the UNICODE value for the key */ keysym->unicode = 0; #if 0 // !!TODO:unicode if ( SDL_TranslateUNICODE ) { /* Populate the unicode field with the ASCII value */ keysym->unicode = scancode; } #endif //!! //sprintf(debug, "SDL: TranslateKey: keysym->scancode=%d, keysym->sym=%d, keysym->mod=%d", // keysym->scancode, keysym->sym, keysym->mod); //SDL_TRACE(debug); //!! return(keysym); } } /* extern "C" */