Exemple #1
0
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;
}