KeySym TkpGetKeySym( TkDisplay *dispPtr, /* Display in which to map keycode. */ XEvent *eventPtr) /* Description of X event. */ { KeySym sym; int index; TkKeyEvent* kePtr = (TkKeyEvent*) eventPtr; #ifdef TK_USE_INPUT_METHODS /* * If input methods are active, we may already have determined a keysym. * Return it. */ if (eventPtr->type == KeyPress && dispPtr && (dispPtr->flags & TK_DISPLAY_USE_IM)) { if (kePtr->charValuePtr == NULL) { Tcl_DString ds; TkWindow *winPtr = (TkWindow *) Tk_IdToWindow(eventPtr->xany.display, eventPtr->xany.window); Tcl_DStringInit(&ds); (void) TkpGetString(winPtr, eventPtr, &ds); Tcl_DStringFree(&ds); } if (kePtr->charValuePtr != NULL) { return kePtr->keysym; } } #endif /* * Refresh the mapping information if it's stale */ if (dispPtr->bindInfoStale) { TkpInitKeymapInfo(dispPtr); } /* * Figure out which of the four slots in the keymap vector to use for this * key. Refer to Xlib documentation for more info on how this computation * works. */ index = 0; if (eventPtr->xkey.state & dispPtr->modeModMask) { index = 2; } if ((eventPtr->xkey.state & ShiftMask) || ((dispPtr->lockUsage != LU_IGNORE) && (eventPtr->xkey.state & LockMask))) { index += 1; } sym = XkbKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode, 0, index); /* * Special handling: if the key was shifted because of Lock, but lock is * only caps lock, not shift lock, and the shifted keysym isn't upper-case * alphabetic, then switch back to the unshifted keysym. */ if ((index & 1) && !(eventPtr->xkey.state & ShiftMask) && (dispPtr->lockUsage == LU_CAPS)) { if (!(((sym >= XK_A) && (sym <= XK_Z)) || ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis)) || ((sym >= XK_Ooblique) && (sym <= XK_Thorn)))) { index &= ~1; sym = XkbKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode, 0, index); } } /* * Another bit of special handling: if this is a shifted key and there is * no keysym defined, then use the keysym for the unshifted key. */ if ((index & 1) && (sym == NoSymbol)) { sym = XkbKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode, 0, index & ~1); } return sym; }
KeySym TkpGetKeySym( TkDisplay *dispPtr, /* Display in which to map keycode. */ XEvent *eventPtr) /* Description of X event. */ { KeySym sym; int index; /* * Refresh the mapping information if it's stale. */ if (dispPtr->bindInfoStale) { TkpInitKeymapInfo(dispPtr); } /* * Handle pure modifier keys specially. We use -1 as a signal for * this. */ if (eventPtr->xany.send_event == -1) { int modifier = eventPtr->xkey.keycode; if (modifier == cmdKey) { return XK_Alt_L; } else if (modifier == shiftKey) { return XK_Shift_L; } else if (modifier == alphaLock) { return XK_Caps_Lock; } else if (modifier == optionKey) { return XK_Meta_L; } else if (modifier == controlKey) { return XK_Control_L; } else if (modifier == rightShiftKey) { return XK_Shift_R; } else if (modifier == rightOptionKey) { return XK_Meta_R; } else if (modifier == rightControlKey) { return XK_Control_R; } else { /* * If we get here, we probably need to implement something new. */ return NoSymbol; } } /* * Figure out which of the four slots in the keymap vector to use for * this key. Refer to Xlib documentation for more info on how this * computation works. (Note: We use "Option" in keymap columns 2 and 3 * where other implementations have "Mode_switch".) */ index = 0; /* * We want Option key combinations to use their base chars as keysyms, so * we ignore the option modifier here. */ #if 0 if (eventPtr->xkey.state & OPTION_MASK) { index |= 2; } #endif if ((eventPtr->xkey.state & ShiftMask) || (/* (dispPtr->lockUsage != LU_IGNORE) && */ (eventPtr->xkey.state & LockMask))) { index |= 1; } /* * First try of the actual translation. */ sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode, index); /* * Special handling: If the key was shifted because of Lock, but lock is * only caps lock, not shift lock, and the shifted keysym isn't * upper-case alphabetic, then switch back to the unshifted keysym. */ if ((index & 1) && !(eventPtr->xkey.state & ShiftMask) /*&& (dispPtr->lockUsage == LU_CAPS)*/ ) { /* * FIXME: Keysyms are only identical to Unicode for ASCII and * Latin-1, so we can't use Tcl_UniCharIsUpper() for keysyms outside * that range. This may be a serious problem here. */ if ((sym == NoSymbol) || (sym > LATIN1_MAX) || !Tcl_UniCharIsUpper(sym)) { index &= ~1; sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode, index); } } /* * Another bit of special handling: If this is a shifted key and there is * no keysym defined, then use the keysym for the unshifted key. */ if ((index & 1) && (sym == NoSymbol)) { sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode, index & ~1); } return sym; }