int _XTranslateKey( register Display *dpy, KeyCode keycode, register unsigned int modifiers, unsigned int *modifiers_return, KeySym *keysym_return) { int per; register KeySym *syms; KeySym sym, lsym, usym; if ((! dpy->keysyms) && (! _XKeyInitialize(dpy))) return 0; *modifiers_return = ((ShiftMask|LockMask) | dpy->mode_switch | dpy->num_lock); if (((int)keycode < dpy->min_keycode) || ((int)keycode > dpy->max_keycode)) { *keysym_return = NoSymbol; return 1; } per = dpy->keysyms_per_keycode; syms = &dpy->keysyms[(keycode - dpy->min_keycode) * per]; while ((per > 2) && (syms[per - 1] == NoSymbol)) per--; if ((per > 2) && (modifiers & dpy->mode_switch)) { syms += 2; per -= 2; } if ((modifiers & dpy->num_lock) && (per > 1 && (IsKeypadKey(syms[1]) || IsPrivateKeypadKey(syms[1])))) { if ((modifiers & ShiftMask) || ((modifiers & LockMask) && (dpy->lock_meaning == XK_Shift_Lock))) *keysym_return = syms[0]; else *keysym_return = syms[1]; } else if (!(modifiers & ShiftMask) && (!(modifiers & LockMask) || (dpy->lock_meaning == NoSymbol))) { if ((per == 1) || (syms[1] == NoSymbol)) XConvertCase(syms[0], keysym_return, &usym); else *keysym_return = syms[0]; } else if (!(modifiers & LockMask) || (dpy->lock_meaning != XK_Caps_Lock)) { if ((per == 1) || ((usym = syms[1]) == NoSymbol)) XConvertCase(syms[0], &lsym, &usym); *keysym_return = usym; } else { if ((per == 1) || ((sym = syms[1]) == NoSymbol)) sym = syms[0]; XConvertCase(sym, &lsym, &usym); if (!(modifiers & ShiftMask) && (sym != syms[0]) && ((sym != usym) || (lsym == usym))) XConvertCase(syms[0], &lsym, &usym); *keysym_return = usym; } if (*keysym_return == XK_VoidSymbol) *keysym_return = NoSymbol; return 1; }
static KeySym KeyCodetoKeySym(register Display *dpy, KeyCode keycode, int col) { register int per = dpy->keysyms_per_keycode; register KeySym *syms; KeySym lsym, usym; if ((col < 0) || ((col >= per) && (col > 3)) || ((int)keycode < dpy->min_keycode) || ((int)keycode > dpy->max_keycode)) return NoSymbol; syms = &dpy->keysyms[(keycode - dpy->min_keycode) * per]; if (col < 4) { if (col > 1) { while ((per > 2) && (syms[per - 1] == NoSymbol)) per--; if (per < 3) col -= 2; } if ((per <= (col|1)) || (syms[col|1] == NoSymbol)) { XConvertCase(syms[col&~1], &lsym, &usym); if (!(col & 1)) return lsym; else if (usym == lsym) return NoSymbol; else return usym; } } return syms[col]; }
static KeySym __XkbDefaultToUpper(KeySym sym) { KeySym lower,upper; XConvertCase(sym, &lower, &upper); return upper; }
xkb_keysym_t xkb_keysym_to_upper(xkb_keysym_t ks) { xkb_keysym_t lower, upper; XConvertCase(ks, &lower, &upper); return upper; }
void sendChar(char c) { KeySym ks, sks, *kss, ksl, ksu; KeyCode kc, skc; int Delay = 10; int syms; #ifdef DEBUG int i; #endif sks=XK_Shift_L; ks=XStringToKeysym(chartbl[0][(unsigned char)c]); if ( ( kc = XKeysymToKeycode ( RemoteDpy, ks ) ) == 0 ) { std::cerr << "No keycode on remote display found for char: " << c << std::endl; return; } if ( ( skc = XKeysymToKeycode ( RemoteDpy, sks ) ) == 0 ) { std::cerr << "No keycode on remote display found for XK_Shift_L!" << std::endl; return; } kss=XGetKeyboardMapping(RemoteDpy, kc, 1, &syms); if (!kss) { std::cerr << "XGetKeyboardMapping failed on the remote display (keycode: " << kc << ")" << std::endl; return; } for (; syms && (!kss[syms-1]); syms--); if (!syms) { std::cerr << "XGetKeyboardMapping failed on the remote display (no syms) (keycode: " << kc << ")" << std::endl; XFree(kss); return; } XConvertCase(ks,&ksl,&ksu); #ifdef DEBUG std::cout << "kss: "; for (i=0; i<syms; i++) std::cout << kss[i] << " "; std::cout << "(" << ks << " l: " << ksl << " h: " << ksu << ")" << std::endl; #endif if (ks==kss[0] && (ks==ksl && ks==ksu)) sks=NoSymbol; if (ks==ksl && ks!=ksu) sks=NoSymbol; if (sks!=NoSymbol) XTestFakeKeyEvent ( RemoteDpy, skc, True, Delay ); XTestFakeKeyEvent ( RemoteDpy, kc, True, Delay ); XFlush ( RemoteDpy ); XTestFakeKeyEvent ( RemoteDpy, kc, False, Delay ); if (sks!=NoSymbol) XTestFakeKeyEvent ( RemoteDpy, skc, False, Delay ); XFlush ( RemoteDpy ); XFree(kss); }
bool xkb_keysym_is_upper(xkb_keysym_t ks) { xkb_keysym_t lower, upper; XConvertCase(ks, &lower, &upper); if (lower == upper) return false; return (ks == upper ? true : false); }
KeyCode char2KeyCode(char c, bool &need_shift){ char buf[2]; buf[0]=c;buf[1]='\0'; KeySym sym = XStringToKeysym(buf); need_shift=false; KeySym ksl, ksu; XConvertCase(sym, &ksl, &ksu); if(sym==ksu && ksl!=ksu) need_shift=true; KeyCode kc = XKeysymToKeycode(display, sym); return kc; }
static KeySym chooseSymbolForXKeyEvent(const XKeyEvent* event, bool* useUpperCase) { KeySym firstSymbol = XLookupKeysym(const_cast<XKeyEvent*>(event), 0); KeySym secondSymbol = XLookupKeysym(const_cast<XKeyEvent*>(event), 1); KeySym lowerCaseSymbol, upperCaseSymbol, chosenSymbol; XConvertCase(firstSymbol, &lowerCaseSymbol, &upperCaseSymbol); bool numLockModifier = event->state & Mod2Mask; bool capsLockModifier = event->state & LockMask; bool shiftModifier = event->state & ShiftMask; if (numLockModifier && isKeypadKeysym(secondSymbol)) { chosenSymbol = shiftModifier ? firstSymbol : secondSymbol; } else if (lowerCaseSymbol == upperCaseSymbol) { chosenSymbol = shiftModifier ? secondSymbol : firstSymbol; } else if (shiftModifier == capsLockModifier) chosenSymbol = firstSymbol; else chosenSymbol = secondSymbol; *useUpperCase = (lowerCaseSymbol != upperCaseSymbol && chosenSymbol == upperCaseSymbol); XConvertCase(chosenSymbol, &lowerCaseSymbol, &upperCaseSymbol); return upperCaseSymbol; }
EXPORT int x_event_keyboard_key(Display* display) { //KeySym XKeycodeToKeysym(Display *display, KeyCode keycode, int index); KeyCode kc; KeySym ks, ksHigh, ksLow; char buf[16]; XComposeStatus composeStatus; kc = globalEvent.xkey.keycode; if (0 != XLookupString(&globalEvent.xkey, buf, 1, &ks, &composeStatus)) { return (int)buf[0]; } ks = XKeycodeToKeysym(display, kc, 0); if (ks > 0xFF00) { return ks & 0xFF; } XConvertCase(ks, &ksLow, &ksHigh); if (globalEvent.xkey.state & 3) { /*shift or capslock?*/ return ksHigh; } else { return ksLow; } }
void UXViewport::Tick() { guard(UXViewport::Tick); UXClient* Client = GetOuterUXClient(); if (!XWindow) return; // Keyboard. EInputKey Key; KeySym LowerCase, UpperCase; // Mouse movement management. UBOOL MouseMoved; INT BaseX = SizeX/2; INT BaseY = SizeY/2; INT DX = 0, DY = 0; XEvent Event; while( XPending(XDisplay) ) { XNextEvent(XDisplay, &Event); switch( Event.type ) { case CreateNotify: // Window has been created. ViewportStatus = X_ViewportNormal; // Make this viewport current and update its title bar. GetOuterUClient()->MakeCurrent( this ); break; case DestroyNotify: // Window has been destroyed. if( BlitFlags & BLIT_Fullscreen ) EndFullscreen(); if( ViewportStatus == X_ViewportNormal ) { // Closed normally. ViewportStatus = X_ViewportClosing; delete this; } break; case Expose: // Redraw the window. break; case KeyPress: // Reset timer. RepeatTimer = appSeconds(); LastKey = True; // Get key code. Key = (EInputKey) XKeycodeToKeysym( XDisplay, Event.xkey.keycode, 0 ); XConvertCase( Key, &LowerCase, &UpperCase ); Key = (EInputKey) UpperCase; // Check the Keysym map. if (KeysymMap[Key] != 0) Key = (EInputKey) KeysymMap[Key]; // Send key to input system. CauseInputEvent( Key, IST_Press ); // Emulate WM_CHAR. // Check for shift modifier. if (Event.xkey.state & ShiftMask) { Key = (EInputKey) UpperCase; if (ShiftMaskMap[Key] != 0) Key = (EInputKey) ShiftMaskMap[Key]; } else Key = (EInputKey) LowerCase; if (Key == XK_BackSpace) Key = IK_Backspace; if (Key == XK_Tab) Key = IK_Tab; if (Key == XK_Return) Key = IK_Enter; if (WMCharMap[Key] == 1) { KeyRepeatMap[Key] = 1; Client->Engine->Key( this, Key ); } break; case KeyRelease: // Get key code. Key = (EInputKey) XKeycodeToKeysym( XDisplay, Event.xkey.keycode, 0 ); XConvertCase( Key, &LowerCase, &UpperCase ); Key = (EInputKey) UpperCase; // Check the Keysym map. if (KeysymMap[Key] != 0) Key = (EInputKey) KeysymMap[Key]; // Send key to input system. CauseInputEvent( Key, IST_Release ); // Release all types of this key. if (Key == XK_BackSpace) Key = IK_Backspace; if (Key == XK_Tab) Key = IK_Tab; if (Key == XK_Return) Key = IK_Enter; KeyRepeatMap[Key] = 0; KeyRepeatMap[ShiftMaskMap[Key]] = 0; KeyRepeatMap[ShiftMaskMap[(EInputKey) LowerCase]] = 0; KeyRepeatMap[(EInputKey) LowerCase] = 0; break; case ButtonPress: switch (Event.xbutton.button) { case 1: Key = IK_LeftMouse; break; case 2: Key = IK_MiddleMouse; break; case 3: Key = IK_RightMouse; break; case 4: Key = IK_MouseWheelUp; break; case 5: Key = IK_MouseWheelDown; break; } // Send to input system. CauseInputEvent( Key, IST_Press ); break; case ButtonRelease: switch (Event.xbutton.button) { case 1: Key = IK_LeftMouse; break; case 2: Key = IK_MiddleMouse; break; case 3: Key = IK_RightMouse; break; case 4: Key = IK_MouseWheelUp; break; case 5: Key = IK_MouseWheelDown; break; } // Send to input system. CauseInputEvent( Key, IST_Release ); break; case MotionNotify: MouseMoved = True; if (UseDGA) { if (abs(Event.xmotion.x_root) > 1) DX += Event.xmotion.x_root * 2; else DX += Event.xmotion.x_root; if (abs(Event.xmotion.y_root) > 1) DY += Event.xmotion.y_root * 2; else DY += Event.xmotion.y_root; } else { DX += Event.xmotion.x - BaseX; DY += Event.xmotion.y - BaseY; BaseX = Event.xmotion.x; BaseY = Event.xmotion.y; } break; case ResizeRequest: // Eventually resize and setres. break; case MapNotify: if (Iconified) { guard(Uniconify); Iconified = false; // Unpause the game if applicable. Exec( TEXT("SETPAUSE 0"), *this ); // Reset the input buffer. Input->ResetInput(); // Snag the mouse again. SetMouseCapture( 1, 1, 0 ); // Make this viewport current. GetOuterUClient()->MakeCurrent( this ); // Turn off that damn auto repeat. XAutoRepeatOff( XDisplay ); // Return to fullscreen. if( BlitFlags & BLIT_Fullscreen ) TryRenderDevice( TEXT("ini:Engine.Engine.GameRenderDevice"), INDEX_NONE, INDEX_NONE, ColorBytes, 1 ); unguard; } break; case UnmapNotify: if (!Iconified) Iconify(); break; case FocusIn: break; case FocusOut: Iconify(); break; } } if (Iconified) return; // Deliver mouse behavior to the engine. if (MouseMoved) { if (!UseDGA) { XWarpPointer(XDisplay, None, XWindow, 0, 0, 0, 0, SizeX/2, SizeY/2); // Clear out the warp. XEvent MouseEvent; while( XCheckWindowEvent(XDisplay, XWindow, ButtonMotionMask | PointerMotionMask, &MouseEvent) ) { // Do Nothing. } } // Send to input subsystem. if( DX ) CauseInputEvent( IK_MouseX, IST_Axis, +DX ); if( DY ) CauseInputEvent( IK_MouseY, IST_Axis, -DY ); } // Send WM_CHAR for down keys. if ( LastKey && (appSeconds() - RepeatTimer < 0.5) ) return; LastKey = False; if ( appSeconds() - RepeatTimer < 0.1 ) return; RepeatTimer = appSeconds(); for (INT i=0; i<256; i++) if (KeyRepeatMap[i] != 0) { if (i == IK_Backspace) { CauseInputEvent( i, IST_Press ); CauseInputEvent( i, IST_Release ); } else Client->Engine->Key( this, (EInputKey) i ); } unguard; }
// this code taken straight from SFML-1.6 u32 X11KeyToXWL( KeySym sym ) { // First convert to uppercase (to avoid dealing with two different keysyms for the same key) KeySym Lower, Key; XConvertCase(sym, &Lower, &Key); switch (Key) { case XK_Shift_L : return XWLK_LSHIFT; case XK_Shift_R : return XWLK_RSHIFT; case XK_Control_L : return XWLK_LCONTROL; case XK_Control_R : return XWLK_RCONTROL; case XK_Alt_L : return XWLK_LALT; case XK_Alt_R : return XWLK_RALT; case XK_Super_L : return XWLK_LSYSTEM; case XK_Super_R : return XWLK_RSYSTEM; case XK_Menu : return XWLK_MENU; case XK_Escape : return XWLK_ESCAPE; case XK_semicolon : return XWLK_SEMICOLON; case XK_slash : return XWLK_SLASH; case XK_equal : return XWLK_EQUALS; case XK_minus : return XWLK_MINUS; case XK_bracketleft : return XWLK_LBRACKET; case XK_bracketright : return XWLK_RBRACKET; case XK_comma : return XWLK_COMMA; case XK_period : return XWLK_PERIOD; case XK_apostrophe : return XWLK_QUOTE; case XK_backslash : return XWLK_BACKSLASH; case XK_grave : return XWLK_TILDE; case XK_space : return XWLK_SPACE; case XK_Return : return XWLK_RETURN; case XK_KP_Enter : return XWLK_RETURN; case XK_BackSpace : return XWLK_BACKSPACE; case XK_Tab : return XWLK_TAB; case XK_Prior : return XWLK_PAGEUP; case XK_Next : return XWLK_PAGEDN; case XK_End : return XWLK_END; case XK_Home : return XWLK_HOME; case XK_Insert : return XWLK_INSERT; case XK_Delete : return XWLK_DELETE; case XK_KP_Add : return XWLK_ADD; case XK_KP_Subtract : return XWLK_SUBTRACT; case XK_KP_Multiply : return XWLK_MULTIPLY; case XK_KP_Divide : return XWLK_DIVIDE; case XK_Pause : return XWLK_PAUSE; case XK_F1 : return XWLK_F1; case XK_F2 : return XWLK_F2; case XK_F3 : return XWLK_F3; case XK_F4 : return XWLK_F4; case XK_F5 : return XWLK_F5; case XK_F6 : return XWLK_F6; case XK_F7 : return XWLK_F7; case XK_F8 : return XWLK_F8; case XK_F9 : return XWLK_F9; case XK_F10 : return XWLK_F10; case XK_F11 : return XWLK_F11; case XK_F12 : return XWLK_F12; case XK_F13 : return XWLK_F13; case XK_F14 : return XWLK_F14; case XK_F15 : return XWLK_F15; case XK_Left : return XWLK_LEFT; case XK_Right : return XWLK_RIGHT; case XK_Up : return XWLK_UP; case XK_Down : return XWLK_DOWN; case XK_KP_0 : return XWLK_NUMPAD0; case XK_KP_1 : return XWLK_NUMPAD1; case XK_KP_2 : return XWLK_NUMPAD2; case XK_KP_3 : return XWLK_NUMPAD3; case XK_KP_4 : return XWLK_NUMPAD4; case XK_KP_5 : return XWLK_NUMPAD5; case XK_KP_6 : return XWLK_NUMPAD6; case XK_KP_7 : return XWLK_NUMPAD7; case XK_KP_8 : return XWLK_NUMPAD8; case XK_KP_9 : return XWLK_NUMPAD9; case XK_A : return XWLK_A; case XK_Z : return XWLK_Z; case XK_E : return XWLK_E; case XK_R : return XWLK_R; case XK_T : return XWLK_T; case XK_Y : return XWLK_Y; case XK_U : return XWLK_U; case XK_I : return XWLK_I; case XK_O : return XWLK_O; case XK_P : return XWLK_P; case XK_Q : return XWLK_Q; case XK_S : return XWLK_S; case XK_D : return XWLK_D; case XK_F : return XWLK_F; case XK_G : return XWLK_G; case XK_H : return XWLK_H; case XK_J : return XWLK_J; case XK_K : return XWLK_K; case XK_L : return XWLK_L; case XK_M : return XWLK_M; case XK_W : return XWLK_W; case XK_X : return XWLK_X; case XK_C : return XWLK_C; case XK_V : return XWLK_V; case XK_B : return XWLK_B; case XK_N : return XWLK_N; case XK_0 : return XWLK_0; case XK_1 : return XWLK_1; case XK_2 : return XWLK_2; case XK_3 : return XWLK_3; case XK_4 : return XWLK_4; case XK_5 : return XWLK_5; case XK_6 : return XWLK_6; case XK_7 : return XWLK_7; case XK_8 : return XWLK_8; case XK_9 : return XWLK_9; } printf( "Unknown Key: %u\n", (unsigned int)Key ); return 0; }
static void Keyaction(Widget w, XEvent *e, String *p, Cardinal *np) { static unsigned char compose[5]; static int composing = -2; int kind = Kraw; int c, len, minmod; KeySym k, mk; Charfunc f; Modifiers md; char buf[100] = {0}; c = 0; len = 0; /* Translate the keycode into a key symbol. */ if(e->xany.type != KeyPress) return; XkbTranslateKeyCode(xkb, (KeyCode)e->xkey.keycode, e->xkey.state, &md, &k); XkbTranslateKeySym(e->xany.display, &k, e->xkey.state, buf, sizeof(buf) - 1, &len); /* Check to see if it's a specially-handled key first. */ for (Keymapping *m = keymappings; m; m = m->next){ KeySym u = NoSymbol; KeySym l = NoSymbol; XConvertCase(k, &l, &u); /* Note that magic bit manipulation here - we want to check that the * modifiers that are specified for the binding are all pressed, but * we allow other modifiers to be as well. This is because when NumLock * is on, it's always added to the modifier mask. */ if (l == m->s || m->s == XK_VoidSymbol){ if (m->m == 0 || (m->m & ~e->xkey.state) == 0){ switch (m->c){ case Cnone: return; case Cdefault: continue; default: f = ((GwinWidget)w)->gwin.gotchar; if (f) (*f)(m->c, m->k, Tcurrent, 0, 0, m->a); return; } } } } /* * The following song and dance is so we can have our chosen * modifier key behave like a compose key, i.e, press and release * and then type the compose sequence, like Plan 9. We have * to find out which key is the compose key first though. */ if (IsModifierKey(k) && ((GwinWidget)w)->gwin.compose && composing == -2 && modmap) { minmod = (((GwinWidget)w)->gwin.compose+2)*keypermod; for (c = minmod; c < minmod+keypermod; c++) { XtTranslateKeycode(e->xany.display, modmap->modifiermap[c], e->xkey.state, &md, &mk); if (k == mk) { composing = -1; break; } } return; } /* Handle Multi_key separately, since it isn't a modifier */ if(k == XK_Multi_key) { composing = -1; return; } if(k == NoSymbol || k > 0xff00) return; /* Check to see if we are in a composition sequence */ if (!((GwinWidget)w)->gwin.compose && (e->xkey.state & Mod1Mask) && composing == -2) composing = -1; if (composing > -2) { compose[++composing] = k; if ((*compose == 'X') && (composing > 0)) { if ((k < '0') || (k > 'f') || ((k > '9') && (k < 'a'))) { STUFFCOMPOSE(); c = (uint16_t)k; composing = -2; } else if (composing == 4) { c = unicode(compose); if (c == -1) { STUFFCOMPOSE(); c = (uint16_t)compose[4]; } composing = -2; } } else if (composing == 1) { c = (int)latin1(compose); if (c == -1) { STUFFCOMPOSE(); c = (uint16_t)compose[1]; } composing = -2; } } else { if (composing >= 0) { composing++; STUFFCOMPOSE(); } c = keysymtoshort(k); composing = -2; } if (composing >= -1) return; f = ((GwinWidget)w)->gwin.gotchar; if(f) (*f)(c, kind, Tcurrent, 0, 0, NULL); }
JNIEXPORT jlong JNICALL Java_org_lwjgl_opengl_LinuxKeyboard_toUpper(JNIEnv *env, jclass unused, jlong keysym) { KeySym lower_case, upper_case; XConvertCase(keysym, &lower_case, &upper_case); return upper_case; }
bool Gosu::TextInput::feedXEvent(void* display, void* event) { XEvent* ev = static_cast<XEvent*>(event); if (ev->type != KeyPress) return false; bool ctrlDown = (ev->xkey.state & ControlMask); bool shiftDown = (ev->xkey.state & ShiftMask); KeySym lower, upper; XConvertCase(XKeycodeToKeysym((Display*)display, ev->xkey.keycode, 0), &lower, &upper); wchar_t ch = static_cast<wchar_t>(shiftDown ? upper : lower); if (ch >= 32 && ch != 127 && ch <= 255) { // Delete (overwrite) previous selection. if (CARET_POS != SEL_START) { unsigned min = std::min(CARET_POS, SEL_START); unsigned max = std::max(CARET_POS, SEL_START); pimpl->text.erase(pimpl->text.begin() + min, pimpl->text.begin() + max); CARET_POS = SEL_START = min; } wchar_t text[] = { ch, 0 }; std::wstring filteredText = filter(text); pimpl->text.insert(pimpl->text.begin() + CARET_POS, filteredText.begin(), filteredText.end()); CARET_POS += filteredText.length(); SEL_START = CARET_POS; return true; } // Char left if (ch == kbLeft && !ctrlDown) { if (CARET_POS > 0) CARET_POS -= 1; if (!shiftDown) SEL_START = CARET_POS; return true; } // Char right if (ch == kbRight && !ctrlDown) { if (CARET_POS < pimpl->text.length()) CARET_POS += 1; if (!shiftDown) SEL_START = CARET_POS; return true; } // Home if (ch == kbHome) { CARET_POS = 0; if (!shiftDown) SEL_START = CARET_POS; return true; } // End if (ch == kbEnd) { CARET_POS = pimpl->text.length(); if (!shiftDown) SEL_START = CARET_POS; return true; } // Word left if (ch == kbLeft && ctrlDown) { if (CARET_POS == pimpl->text.length()) --CARET_POS; while (CARET_POS > 0 && iswspace(pimpl->text.at(CARET_POS - 1))) --CARET_POS; while (CARET_POS > 0 && !iswspace(pimpl->text.at(CARET_POS - 1))) --CARET_POS; if (!shiftDown) SEL_START = CARET_POS; return true; } // Word right if (ch == kbRight && ctrlDown) { while (CARET_POS < pimpl->text.length() && iswspace(pimpl->text.at(CARET_POS))) ++CARET_POS; while (CARET_POS < pimpl->text.length() && !iswspace(pimpl->text.at(CARET_POS))) ++CARET_POS; if (!shiftDown) SEL_START = CARET_POS; return true; } // Delete existant selection if (ch == kbBackspace) { if (SEL_START != CARET_POS) { unsigned min = std::min(CARET_POS, SEL_START); unsigned max = std::max(CARET_POS, SEL_START); pimpl->text.erase(pimpl->text.begin() + min, pimpl->text.begin() + max); SEL_START = CARET_POS = min; } else if (CARET_POS > 0) { unsigned oldCaret = CARET_POS; CARET_POS -= 1; pimpl->text.erase(pimpl->text.begin() + CARET_POS, pimpl->text.begin() + oldCaret); SEL_START = CARET_POS; } return true; } // Delete existant selection if (ch == kbDelete) { if (SEL_START != CARET_POS) { unsigned min = std::min(CARET_POS, SEL_START); unsigned max = std::max(CARET_POS, SEL_START); pimpl->text.erase(pimpl->text.begin() + min, pimpl->text.begin() + max); SEL_START = CARET_POS = min; } else if (CARET_POS < pimpl->text.length()) { unsigned oldCaret = CARET_POS; CARET_POS += 1; pimpl->text.erase(pimpl->text.begin() + oldCaret, pimpl->text.begin() + CARET_POS); SEL_START = CARET_POS = oldCaret; } return true; } return false; }
//////////////////////////////////////////////////////////// /// Convert a X11 keysym to SFML key code //////////////////////////////////////////////////////////// Key::Code WindowImplX11::KeysymToSF(KeySym Sym) { // First convert to uppercase (to avoid dealing with two different keysyms for the same key) KeySym Lower, Key; XConvertCase(Sym, &Lower, &Key); switch (Key) { case XK_Shift_L : return Key::LShift; case XK_Shift_R : return Key::RShift; case XK_Control_L : return Key::LControl; case XK_Control_R : return Key::RControl; case XK_Alt_L : return Key::LAlt; case XK_Alt_R : return Key::RAlt; case XK_Super_L : return Key::LSystem; case XK_Super_R : return Key::RSystem; case XK_Menu : return Key::Menu; case XK_Escape : return Key::Escape; case XK_semicolon : return Key::SemiColon; case XK_slash : return Key::Slash; case XK_equal : return Key::Equal; case XK_minus : return Key::Dash; case XK_bracketleft : return Key::LBracket; case XK_bracketright : return Key::RBracket; case XK_comma : return Key::Comma; case XK_period : return Key::Period; case XK_dead_acute : return Key::Quote; case XK_backslash : return Key::BackSlash; case XK_dead_grave : return Key::Tilde; case XK_space : return Key::Space; case XK_Return : return Key::Return; case XK_KP_Enter : return Key::Return; case XK_BackSpace : return Key::Back; case XK_Tab : return Key::Tab; case XK_Prior : return Key::PageUp; case XK_Next : return Key::PageDown; case XK_End : return Key::End; case XK_Home : return Key::Home; case XK_Insert : return Key::Insert; case XK_Delete : return Key::Delete; case XK_KP_Add : return Key::Add; case XK_KP_Subtract : return Key::Subtract; case XK_KP_Multiply : return Key::Multiply; case XK_KP_Divide : return Key::Divide; case XK_Pause : return Key::Pause; case XK_F1 : return Key::F1; case XK_F2 : return Key::F2; case XK_F3 : return Key::F3; case XK_F4 : return Key::F4; case XK_F5 : return Key::F5; case XK_F6 : return Key::F6; case XK_F7 : return Key::F7; case XK_F8 : return Key::F8; case XK_F9 : return Key::F9; case XK_F10 : return Key::F10; case XK_F11 : return Key::F11; case XK_F12 : return Key::F12; case XK_F13 : return Key::F13; case XK_F14 : return Key::F14; case XK_F15 : return Key::F15; case XK_Left : return Key::Left; case XK_Right : return Key::Right; case XK_Up : return Key::Up; case XK_Down : return Key::Down; case XK_KP_0 : return Key::Numpad0; case XK_KP_1 : return Key::Numpad1; case XK_KP_2 : return Key::Numpad2; case XK_KP_3 : return Key::Numpad3; case XK_KP_4 : return Key::Numpad4; case XK_KP_5 : return Key::Numpad5; case XK_KP_6 : return Key::Numpad6; case XK_KP_7 : return Key::Numpad7; case XK_KP_8 : return Key::Numpad8; case XK_KP_9 : return Key::Numpad9; case XK_A : return Key::A; case XK_Z : return Key::Z; case XK_E : return Key::E; case XK_R : return Key::R; case XK_T : return Key::T; case XK_Y : return Key::Y; case XK_U : return Key::U; case XK_I : return Key::I; case XK_O : return Key::O; case XK_P : return Key::P; case XK_Q : return Key::Q; case XK_S : return Key::S; case XK_D : return Key::D; case XK_F : return Key::F; case XK_G : return Key::G; case XK_H : return Key::H; case XK_J : return Key::J; case XK_K : return Key::K; case XK_L : return Key::L; case XK_M : return Key::M; case XK_W : return Key::W; case XK_X : return Key::X; case XK_C : return Key::C; case XK_V : return Key::V; case XK_B : return Key::B; case XK_N : return Key::N; case XK_0 : return Key::Num0; case XK_1 : return Key::Num1; case XK_2 : return Key::Num2; case XK_3 : return Key::Num3; case XK_4 : return Key::Num4; case XK_5 : return Key::Num5; case XK_6 : return Key::Num6; case XK_7 : return Key::Num7; case XK_8 : return Key::Num8; case XK_9 : return Key::Num9; } return Key::Code(0); }
static int translateKey(int keycode) { KeySym key, key_lc, key_uc; // Try secondary keysym, for numeric keypad keys // Note: This way we always force "NumLock = ON", which at least // enables GLFW users to detect numeric keypad keys key = XKeycodeToKeysym(display, keycode, 1); switch( key ) { // Numeric keypad case XK_KP_0: return MKEY_KP0; case XK_KP_1: return MKEY_KP1; case XK_KP_2: return MKEY_KP2; case XK_KP_3: return MKEY_KP3; case XK_KP_4: return MKEY_KP4; case XK_KP_5: return MKEY_KP5; case XK_KP_6: return MKEY_KP6; case XK_KP_7: return MKEY_KP7; case XK_KP_8: return MKEY_KP8; case XK_KP_9: return MKEY_KP9; case XK_KP_Enter: return MKEY_KP_ENTER; default: break; } // Now try pimary keysym key = XKeycodeToKeysym(display, keycode, 0); switch( key ) { // Special keys (non character keys) case XK_Escape: return MKEY_ESCAPE; case XK_Tab: return MKEY_TAB; case XK_Shift_L: return MKEY_LSHIFT; case XK_Shift_R: return MKEY_RSHIFT; case XK_Control_L: return MKEY_LCONTROL; case XK_Control_R: return MKEY_RCONTROL; case XK_Meta_L: case XK_Alt_L: return MKEY_LALT; case XK_Mode_switch: // Mapped to Alt_R on many keyboards case XK_Meta_R: case XK_ISO_Level3_Shift: // AltGr on at least some machines case XK_Alt_R: return MKEY_RALT; case XK_Super_L: return MKEY_LSUPER; case XK_Super_R: return MKEY_RSUPER; case XK_Menu: return MKEY_MENU; case XK_Num_Lock: return MKEY_NUMLOCK; //case XK_Caps_Lock: return MKEY_CAPS_LOCK; //case XK_Scroll_Lock: return MKEY_SCROLL; case XK_Pause: return MKEY_PAUSE; case XK_KP_Delete: case XK_Delete: return MKEY_DELETE; case XK_BackSpace: return MKEY_BACKSPACE; case XK_Return: return MKEY_RETURN; case XK_KP_Home: case XK_Home: return MKEY_HOME; case XK_KP_End: case XK_End: return MKEY_END; case XK_KP_Page_Up: case XK_Page_Up: return MKEY_PAGEUP; case XK_KP_Page_Down: case XK_Page_Down: return MKEY_PAGEDOWN; case XK_KP_Insert: case XK_Insert: return MKEY_INSERT; case XK_KP_Left: case XK_Left: return MKEY_LEFT; case XK_KP_Right: case XK_Right: return MKEY_RIGHT; case XK_KP_Down: case XK_Down: return MKEY_DOWN; case XK_KP_Up: case XK_Up: return MKEY_UP; case XK_F1: return MKEY_F1; case XK_F2: return MKEY_F2; case XK_F3: return MKEY_F3; case XK_F4: return MKEY_F4; case XK_F5: return MKEY_F5; case XK_F6: return MKEY_F6; case XK_F7: return MKEY_F7; case XK_F8: return MKEY_F8; case XK_F9: return MKEY_F9; case XK_F10: return MKEY_F10; case XK_F11: return MKEY_F11; case XK_F12: return MKEY_F12; // Numeric keypad (should have been detected in secondary keysym!) case XK_KP_Subtract: return MKEY_SUB; case XK_KP_Add: return MKEY_ADD; case XK_KP_Enter: return MKEY_KP_ENTER; // The rest (should be printable keys) default: { // Make uppercase XConvertCase( key, &key_lc, &key_uc ); key = key_uc; // Valid ISO 8859-1 character? if( (key >= 32 && key <= 126) || (key >= 160 && key <= 255) ) { return (int) key; } return -1; } } }
void X11EventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom, jlong windowDeleteAtom) { Atom wm_delete_atom = (Atom)windowDeleteAtom; int num_events = 100; int autoRepeatModifiers = 0; if ( NULL == dpy ) { return; } // Periodically take a break while( num_events > 0 ) { jobject jwindow = NULL; XEvent evt; KeySym keySym = 0; jint modifiers = 0; char keyChar = 0; char text[255]; // XEventsQueued(dpy, X): // QueuedAlready == XQLength(): No I/O Flush or system call doesn't work on some cards (eg ATI) ?) // QueuedAfterFlush == XPending(): I/O Flush only if no already queued events are available // QueuedAfterReading : QueuedAlready + if queue==0, attempt to read more .. // if ( 0 >= XPending(dpy) ) if ( 0 >= XEventsQueued(dpy, QueuedAfterFlush) ) { // DBG_PRINT( "X11: DispatchMessages 0x%X - Leave 1\n", dpy); return; } XNextEvent(dpy, &evt); num_events--; if(dpy!=evt.xany.display) { NewtCommon_throwNewRuntimeException(env, "wrong display, bail out!"); return ; } if( 0==evt.xany.window ) { DBG_PRINT( "X11: DispatchMessages dpy %p, Event %d - Window NULL, ignoring\n", (void*)dpy, (int)evt.type); continue; } // DBG_PRINT( "X11: DispatchMessages dpy %p, win %p, Event %d\n", (void*)dpy, (void*)evt.xany.window, (int)evt.type); jwindow = getJavaWindowProperty(env, dpy, evt.xany.window, javaObjectAtom, #ifdef VERBOSE_ON True #else False #endif ); if(NULL==jwindow) { fprintf(stderr, "Warning: NEWT X11 DisplayDispatch %p, Couldn't handle event %d for X11 window %p\n", (void*)dpy, evt.type, (void*)evt.xany.window); continue; } switch(evt.type) { case KeyRelease: if (XEventsQueued(dpy, QueuedAfterReading)) { XEvent nevt; XPeekEvent(dpy, &nevt); if (nevt.type == KeyPress && nevt.xkey.time == evt.xkey.time && nevt.xkey.keycode == evt.xkey.keycode) { autoRepeatModifiers |= EVENT_AUTOREPEAT_MASK; } else { autoRepeatModifiers &= ~EVENT_AUTOREPEAT_MASK; } } // fall through intended case KeyPress: if(XLookupString(&evt.xkey,text,255,&keySym,0)==1) { KeySym lower_return = 0, upper_return = 0; keyChar=text[0]; XConvertCase(keySym, &lower_return, &upper_return); // always return upper case, set modifier masks (SHIFT, ..) keySym = X11KeySym2NewtVKey(upper_return); } else { keyChar=0; keySym = X11KeySym2NewtVKey(keySym); } modifiers |= X11InputState2NewtModifiers(evt.xkey.state) | autoRepeatModifiers; break; case ButtonPress: case ButtonRelease: case MotionNotify: modifiers |= X11InputState2NewtModifiers(evt.xbutton.state); break; default: break; } switch(evt.type) { case ButtonPress: (*env)->CallVoidMethod(env, jwindow, requestFocusID, JNI_FALSE); #ifdef USE_SENDIO_DIRECT (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED, modifiers, (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/); #else (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_PRESSED, modifiers, (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/); #endif break; case ButtonRelease: #ifdef USE_SENDIO_DIRECT (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_RELEASED, modifiers, (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/); #else (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_RELEASED, modifiers, (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/); #endif break; case MotionNotify: #ifdef USE_SENDIO_DIRECT (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_MOVED, modifiers, (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jint) 0, 0 /*rotation*/); #else (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_MOVED, modifiers, (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jint) 0, 0 /*rotation*/); #endif break; case EnterNotify: DBG_PRINT( "X11: event . EnterNotify call %p %d/%d\n", (void*)evt.xcrossing.window, evt.xcrossing.x, evt.xcrossing.y); #ifdef USE_SENDIO_DIRECT (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_ENTERED, modifiers, (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0 /*rotation*/); #else (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_ENTERED, modifiers, (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0 /*rotation*/); #endif break; case LeaveNotify: DBG_PRINT( "X11: event . LeaveNotify call %p %d/%d\n", (void*)evt.xcrossing.window, evt.xcrossing.x, evt.xcrossing.y); #ifdef USE_SENDIO_DIRECT (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_EXITED, modifiers, (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0 /*rotation*/); #else (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_EXITED, modifiers, (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0 /*rotation*/); #endif break; case KeyPress: #ifdef USE_SENDIO_DIRECT (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_PRESSED, modifiers, keySym, (jchar) -1); #else (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_PRESSED, modifiers, keySym, (jchar) -1); #endif break; case KeyRelease: #ifdef USE_SENDIO_DIRECT (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_RELEASED, modifiers, keySym, (jchar) -1); (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_TYPED, modifiers, keySym, (jchar) keyChar); #else (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_RELEASED, modifiers, keySym, (jchar) -1); (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_TYPED, modifiers, keySym, (jchar) keyChar); #endif break; case DestroyNotify: DBG_PRINT( "X11: event . DestroyNotify call %p, parent %p, child-event: %d\n", (void*)evt.xdestroywindow.window, (void*)evt.xdestroywindow.event, evt.xdestroywindow.window != evt.xdestroywindow.event); if ( evt.xdestroywindow.window == evt.xdestroywindow.event ) { // ignore child destroy notification } break; case CreateNotify: DBG_PRINT( "X11: event . CreateNotify call %p, parent %p, child-event: 1\n", (void*)evt.xcreatewindow.window, (void*) evt.xcreatewindow.parent); break; case ConfigureNotify: DBG_PRINT( "X11: event . ConfigureNotify call %p (parent %p, above %p) %d/%d %dx%d %d, child-event: %d\n", (void*)evt.xconfigure.window, (void*)evt.xconfigure.event, (void*)evt.xconfigure.above, evt.xconfigure.x, evt.xconfigure.y, evt.xconfigure.width, evt.xconfigure.height, evt.xconfigure.override_redirect, evt.xconfigure.window != evt.xconfigure.event); if ( evt.xconfigure.window == evt.xconfigure.event ) { // ignore child window change notification { // update insets int left, right, top, bottom; NewtWindows_updateInsets(env, jwindow, dpy, evt.xany.window, &left, &right, &top, &bottom); } (*env)->CallVoidMethod(env, jwindow, sizeChangedID, JNI_FALSE, (jint) evt.xconfigure.width, (jint) evt.xconfigure.height, JNI_FALSE); (*env)->CallVoidMethod(env, jwindow, positionChangedID, JNI_FALSE, (jint) evt.xconfigure.x, (jint) evt.xconfigure.y); } break; case ClientMessage: if (evt.xclient.send_event==True && evt.xclient.data.l[0]==wm_delete_atom) { // windowDeleteAtom jboolean closed; DBG_PRINT( "X11: event . ClientMessage call %p type 0x%X ..\n", (void*)evt.xclient.window, (unsigned int)evt.xclient.message_type); closed = (*env)->CallBooleanMethod(env, jwindow, windowDestroyNotifyID, JNI_FALSE); DBG_PRINT( "X11: event . ClientMessage call %p type 0x%X, closed: %d\n", (void*)evt.xclient.window, (unsigned int)evt.xclient.message_type, (int)closed); // Called by Window.java: CloseWindow(); num_events = 0; // end loop in case of destroyed display } break; case FocusIn: DBG_PRINT( "X11: event . FocusIn call %p\n", (void*)evt.xvisibility.window); (*env)->CallVoidMethod(env, jwindow, focusChangedID, JNI_FALSE, JNI_TRUE); break; case FocusOut: DBG_PRINT( "X11: event . FocusOut call %p\n", (void*)evt.xvisibility.window); (*env)->CallVoidMethod(env, jwindow, focusChangedID, JNI_FALSE, JNI_FALSE); break; case Expose: DBG_PRINT( "X11: event . Expose call %p %d/%d %dx%d count %d\n", (void*)evt.xexpose.window, evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height, evt.xexpose.count); if (evt.xexpose.count == 0 && evt.xexpose.width > 0 && evt.xexpose.height > 0) { (*env)->CallVoidMethod(env, jwindow, windowRepaintID, JNI_FALSE, evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height); } break; case MapNotify: DBG_PRINT( "X11: event . MapNotify call Event %p, Window %p, override_redirect %d, child-event: %d\n", (void*)evt.xmap.event, (void*)evt.xmap.window, (int)evt.xmap.override_redirect, evt.xmap.event!=evt.xmap.window); if( evt.xmap.event == evt.xmap.window ) { // ignore child window notification { // update insets int left, right, top, bottom; NewtWindows_updateInsets(env, jwindow, dpy, evt.xany.window, &left, &right, &top, &bottom); } (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE, JNI_TRUE); } break; case UnmapNotify: DBG_PRINT( "X11: event . UnmapNotify call Event %p, Window %p, from_configure %d, child-event: %d\n", (void*)evt.xunmap.event, (void*)evt.xunmap.window, (int)evt.xunmap.from_configure, evt.xunmap.event!=evt.xunmap.window); if( evt.xunmap.event == evt.xunmap.window ) { // ignore child window notification (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE, JNI_FALSE); } break; case ReparentNotify: { jlong parentResult; // 0 if root, otherwise proper value Window winRoot, winTopParent; #ifdef VERBOSE_ON Window oldParentRoot, oldParentTopParent; Window parentRoot, parentTopParent; if( 0 == NewtWindows_getRootAndParent(dpy, evt.xreparent.event, &oldParentRoot, &oldParentTopParent) ) { oldParentRoot=0; oldParentTopParent = 0; } if( 0 == NewtWindows_getRootAndParent(dpy, evt.xreparent.parent, &parentRoot, &parentTopParent) ) { parentRoot=0; parentTopParent = 0; } #endif if( 0 == NewtWindows_getRootAndParent(dpy, evt.xreparent.window, &winRoot, &winTopParent) ) { winRoot=0; winTopParent = 0; } if(evt.xreparent.parent == winRoot) { parentResult = 0; // our java indicator for root window } else { parentResult = (jlong) (intptr_t) evt.xreparent.parent; } #ifdef VERBOSE_ON DBG_PRINT( "X11: event . ReparentNotify: call %d/%d OldParent %p (root %p, top %p), NewParent %p (root %p, top %p), Window %p (root %p, top %p)\n", evt.xreparent.x, evt.xreparent.y, (void*)evt.xreparent.event, (void*)oldParentRoot, (void*)oldParentTopParent, (void*)evt.xreparent.parent, (void*)parentRoot, (void*)parentTopParent, (void*)evt.xreparent.window, (void*)winRoot, (void*)winTopParent); #endif (*env)->CallVoidMethod(env, jwindow, reparentNotifyID, (jlong)evt.xreparent.parent); } break; // unhandled events .. yet .. default: DBG_PRINT("X11: event . unhandled %d 0x%X call %p\n", (int)evt.type, (unsigned int)evt.type, (void*)evt.xunmap.window); } } }
int X11OpenGLWindow::getAsciiCodeFromVirtualKeycode(int keycode) { KeySym key, key_lc, key_uc; key = XKeycodeToKeysym( m_data->m_dpy, keycode, 0 ); switch( key ) { case XK_Escape: return B3G_ESCAPE; case XK_Control_L: case XK_Control_R: { return B3G_CONTROL; } case XK_Alt_L: case XK_Alt_R: { return B3G_ALT; } case XK_Shift_L: case XK_Shift_R: return B3G_SHIFT; case XK_F1: return B3G_F1; case XK_F2: return B3G_F2; case XK_F3: return B3G_F3; case XK_F4: return B3G_F4; case XK_F5: return B3G_F5; case XK_F6: return B3G_F6; case XK_F7: return B3G_F7; case XK_F8: return B3G_F8; case XK_F9: return B3G_F9; case XK_F10: return B3G_F10; case XK_F11: return B3G_F11; case XK_F12: return B3G_F12; case XK_F13: return B3G_F13; case XK_F14: return B3G_F14; case XK_F15: return B3G_F15; default: // Make uppercase XConvertCase( key, &key_lc, &key_uc ); key = key_uc; // Valid ISO 8859-1 character? if( (key >= 32 && key <= 126) ||(key >= 160 && key <= 255) ) { return (int) key; } return -1; } return 0; }