summaryrefslogtreecommitdiffstats
path: root/macosx/tkMacOSXKeyboard.c
diff options
context:
space:
mode:
Diffstat (limited to 'macosx/tkMacOSXKeyboard.c')
-rw-r--r--macosx/tkMacOSXKeyboard.c812
1 files changed, 486 insertions, 326 deletions
diff --git a/macosx/tkMacOSXKeyboard.c b/macosx/tkMacOSXKeyboard.c
index e568e9f..24ada94 100644
--- a/macosx/tkMacOSXKeyboard.c
+++ b/macosx/tkMacOSXKeyboard.c
@@ -1,7 +1,7 @@
/*
* tkMacOSXKeyboard.c --
*
- * Routines to support keyboard events on the Macintosh.
+ * Routines to support keyboard events on the Macintosh.
*
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
* Copyright 2001, Apple Computer, Inc.
@@ -9,7 +9,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkMacOSXKeyboard.c,v 1.5.2.1 2003/11/21 13:05:09 cc_benny Exp $
+ * RCS: @(#) $Id: tkMacOSXKeyboard.c,v 1.5.2.2 2004/02/16 00:42:34 wolfsuit Exp $
*/
#include "tkInt.h"
@@ -18,11 +18,31 @@
#include <Carbon/Carbon.h>
#include "tkMacOSXInt.h"
#include "tkMacOSXEvent.h" /* TkMacOSXKeycodeToUnicode() FIXME: That
- * function should probably move here */
+ * function should probably move here. */
+
+/*
+ * A couple of simple definitions to make code a bit more self-explaining.
+ *
+ * For the assignments of Mod1==alt==command and Mod2==meta==option, see also
+ * tkMacOSXMouseEvent.c.
+ */
+
+#define LATIN1_MAX 255
+#define MAC_KEYCODE_MAX 0x7F
+#define MAC_KEYCODE_MASK 0x7F
+#define ALT_MASK Mod1Mask
+#define OPTION_MASK Mod2Mask
+
+
+/*
+ * Tables enumerating the special keys defined on Mac keyboards. These are
+ * necessary for correct keysym mappings for all keys where the keysyms are
+ * not identical with their ASCII or Latin-1 code points.
+ */
typedef struct {
- int keycode; /* Macintosh keycode */
- KeySym keysym; /* X windows Keysym */
+ int keycode; /* Macintosh keycode. */
+ KeySym keysym; /* X windows keysym. */
} KeyInfo;
/*
@@ -30,61 +50,73 @@ typedef struct {
*
* 0x34, XK_Return - Powerbooks use this and some keymaps define it.
*
+ * 0x4C, XK_Return - XFree86 and Apple's X11 call this one XK_KP_Enter.
+ *
* 0x47, XK_Clear - This key is NumLock when used on PCs, but Mac
- * applications don't use it like that.
+ * applications don't use it like that, nor does Apple's X11.
*
* All other keycodes are taken from the published ADB keyboard layouts.
*/
static KeyInfo keyArray[] = {
- {0x4C, XK_Return},
- {0x24, XK_Return},
- {0x34, XK_Return},
- {0x33, XK_BackSpace},
- {0x75, XK_Delete},
- {0x30, XK_Tab},
- {0x74, XK_Page_Up},
- {0x79, XK_Page_Down},
- {0x73, XK_Home},
- {0x77, XK_End},
- {0x7B, XK_Left},
- {0x7C, XK_Right},
- {0x7E, XK_Up},
- {0x7D, XK_Down},
- {0x72, XK_Help},
- {0x35, XK_Escape},
- {0x47, XK_Clear},
- {0, 0}
+ {0x24, XK_Return},
+ {0x30, XK_Tab},
+ {0x33, XK_BackSpace},
+ {0x34, XK_Return},
+ {0x35, XK_Escape},
+
+ {0x47, XK_Clear},
+ {0x4C, XK_Return},
+
+ {0x72, XK_Help},
+ {0x73, XK_Home},
+ {0x74, XK_Page_Up},
+ {0x75, XK_Delete},
+ {0x77, XK_End},
+ {0x79, XK_Page_Down},
+
+ {0x7B, XK_Left},
+ {0x7C, XK_Right},
+ {0x7D, XK_Down},
+ {0x7E, XK_Up},
+
+ {0, 0}
};
-static KeyInfo vituralkeyArray[] = {
- {122, XK_F1},
- {120, XK_F2},
- {99, XK_F3},
- {118, XK_F4},
- {96, XK_F5},
- {97, XK_F6},
- {98, XK_F7},
- {100, XK_F8},
- {101, XK_F9},
- {109, XK_F10},
- {103, XK_F11},
- {111, XK_F12},
- {105, XK_F13},
- {107, XK_F14},
- {113, XK_F15},
- {0, 0}
+static KeyInfo virtualkeyArray[] = {
+ {122, XK_F1},
+ {120, XK_F2},
+ {99, XK_F3},
+ {118, XK_F4},
+ {96, XK_F5},
+ {97, XK_F6},
+ {98, XK_F7},
+ {100, XK_F8},
+ {101, XK_F9},
+ {109, XK_F10},
+ {103, XK_F11},
+ {111, XK_F12},
+ {105, XK_F13},
+ {107, XK_F14},
+ {113, XK_F15},
+ {0, 0}
};
static int initialized = 0;
-static Tcl_HashTable keycodeTable; /* keyArray hashed by keycode value. */
-static Tcl_HashTable vkeyTable; /* vituralkeyArray hashed by virtual
- keycode value. */
+static Tcl_HashTable keycodeTable; /* keyArray hashed by keycode value. */
+static Tcl_HashTable vkeyTable; /* virtualkeyArray hashed by virtual
+ * keycode value. */
+
+static int latin1Table[LATIN1_MAX+1]; /* Reverse mapping table for
+ * controls, ASCII and Latin-1. */
/*
* Prototypes for static functions used in this file.
*/
-static void InitKeyMaps _ANSI_ARGS_((void));
+
+static void InitKeyMaps (void);
+static void InitLatin1Table(Display *display);
+static int XKeysymToMacKeycode(Display *display, KeySym keysym);
/*
@@ -92,13 +124,17 @@ static void InitKeyMaps _ANSI_ARGS_((void));
*
* InitKeyMaps --
*
- * Creates hash tables used by some of the functions in this file.
+ * Creates hash tables used by some of the functions in this file.
+ *
+ * FIXME: As keycodes are defined to be in the limited range 0-127, it
+ * would be easier and more efficient to use directly initialized plain
+ * arrays and drop this function.
*
* Results:
- * None.
+ * None.
*
* Side effects:
- * Allocates memory & creates some hash tables.
+ * Allocates memory & creates some hash tables.
*
*----------------------------------------------------------------------
*/
@@ -109,18 +145,18 @@ InitKeyMaps()
Tcl_HashEntry *hPtr;
KeyInfo *kPtr;
int dummy;
-
+
Tcl_InitHashTable(&keycodeTable, TCL_ONE_WORD_KEYS);
for (kPtr = keyArray; kPtr->keycode != 0; kPtr++) {
- hPtr = Tcl_CreateHashEntry(&keycodeTable, (char *) kPtr->keycode,
- &dummy);
- Tcl_SetHashValue(hPtr, kPtr->keysym);
+ hPtr = Tcl_CreateHashEntry(&keycodeTable, (char *) kPtr->keycode,
+ &dummy);
+ Tcl_SetHashValue(hPtr, kPtr->keysym);
}
Tcl_InitHashTable(&vkeyTable, TCL_ONE_WORD_KEYS);
- for (kPtr = vituralkeyArray; kPtr->keycode != 0; kPtr++) {
- hPtr = Tcl_CreateHashEntry(&vkeyTable, (char *) kPtr->keycode,
- &dummy);
- Tcl_SetHashValue(hPtr, kPtr->keysym);
+ for (kPtr = virtualkeyArray; kPtr->keycode != 0; kPtr++) {
+ hPtr = Tcl_CreateHashEntry(&vkeyTable, (char *) kPtr->keycode,
+ &dummy);
+ Tcl_SetHashValue(hPtr, kPtr->keysym);
}
initialized = 1;
}
@@ -128,16 +164,92 @@ InitKeyMaps()
/*
*----------------------------------------------------------------------
*
+ * InitLatin1Table --
+ *
+ * Creates a simple table to be used for mapping from keysyms to
+ * keycodes. Always needs to be called before using latin1Table,
+ * because the keyboard layout may have changed, and than the table must
+ * be re-computed.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Sets the global latin1Table.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+InitLatin1Table(
+ Display *display)
+{
+ static Boolean latin1_initialized = false;
+ static SInt16 lastKeyLayoutID = -1;
+
+ SInt16 keyScript;
+ SInt16 keyLayoutID;
+
+ keyScript = GetScriptManagerVariable(smKeyScript);
+ keyLayoutID = GetScriptVariable(keyScript,smScriptKeys);
+
+ if (!latin1_initialized || (lastKeyLayoutID != keyLayoutID)) {
+ int keycode;
+ KeySym keysym;
+ int state;
+ int modifiers;
+
+ latin1_initialized = true;
+ lastKeyLayoutID = keyLayoutID;
+
+ memset(latin1Table, 0, sizeof(latin1Table));
+
+ /*
+ * In the common X11 implementations, a keymap has four columns
+ * "plain", "Shift", "Mode_switch" and "Mode_switch + Shift". We
+ * don't use "Mode_switch", but we use "Option" instead. (This is
+ * similar to Apple's X11 implementation, where "Mode_switch" is used
+ * as an alias for "Option".)
+ *
+ * So here we go through all 4 columns of the keymap and find all
+ * Latin-1 compatible keycodes. We go through the columns
+ * back-to-front from the more exotic columns to the more simple, so
+ * that simple keycode-modifier combinations are preferred in the
+ * resulting table.
+ */
+
+ for (state = 3; state >= 0; state--) {
+ modifiers = 0;
+ if (state & 1) {
+ modifiers |= shiftKey;
+ }
+ if (state & 2) {
+ modifiers |= optionKey;
+ }
+
+ for (keycode = 0; keycode <= MAC_KEYCODE_MAX; keycode++) {
+ keysym = XKeycodeToKeysym(display,keycode<<16,state);
+ if (keysym <= LATIN1_MAX) {
+ latin1Table[keysym] = keycode | modifiers;
+ }
+ }
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* XKeycodeToKeysym --
*
- * Translate from a system-dependent keycode to a
- * system-independent keysym.
+ * Translate from a system-dependent keycode to a system-independent
+ * keysym.
*
* Results:
- * Returns the translated keysym, or NoSymbol on failure.
+ * Returns the translated keysym, or NoSymbol on failure.
*
* Side effects:
- * None.
+ * None.
*
*----------------------------------------------------------------------
*/
@@ -146,68 +258,61 @@ KeySym
XKeycodeToKeysym(
Display* display,
KeyCode keycode,
- int index)
+ int index)
{
register Tcl_HashEntry *hPtr;
- int c;
- int virtualKey;
int newKeycode;
UniChar newChar;
+ (void) display; /*unused*/
+
if (!initialized) {
- InitKeyMaps();
- }
- if (keycode == 0) {
- /*
- * This means we had a pure modifier keypress or
- * something similar which is a TO DO.
- */
- return NoSymbol;
- }
-
- virtualKey = keycode >> 16;
- c = (keycode) & 0xffff;
- if (c > 255) {
- return NoSymbol;
+ InitKeyMaps();
}
/*
- * When determining what keysym to produce we first check to see if
- * the key is a function key. We then check to see if the character
- * is another non-printing key. Finally, we return the key syms
- * for all ASCII chars.
+ * When determining what keysym to produce we first check to see if the
+ * key is a function key. We then check to see if the character is
+ * another non-printing key. Finally, we return the key syms for all
+ * ASCII and Latin-1 chars.
*/
- if (c == 0x10) {
- hPtr = Tcl_FindHashEntry(&vkeyTable, (char *) virtualKey);
- if (hPtr != NULL) {
+
+ newKeycode = keycode >> 16;
+
+ if ((keycode & 0xFFFF) == 0x10) {
+ hPtr = Tcl_FindHashEntry(&vkeyTable, (char *) newKeycode);
+ if (hPtr != NULL) {
return (KeySym) Tcl_GetHashValue(hPtr);
- }
+ }
}
- hPtr = Tcl_FindHashEntry(&keycodeTable, (char *) virtualKey);
+ hPtr = Tcl_FindHashEntry(&keycodeTable, (char *) newKeycode);
if (hPtr != NULL) {
- return (KeySym) Tcl_GetHashValue(hPtr);
+ return (KeySym) Tcl_GetHashValue(hPtr);
}
/*
- * Recompute the character based on the Shift key only.
- * TODO: The index may also specify the NUM_LOCK.
+ * Add in the Mac modifier flags for shift and option.
*/
- newKeycode = virtualKey;
- if (index & 0x01) {
- newKeycode += 0x0200;
+
+ if (index & 1) {
+ newKeycode |= shiftKey;
+ }
+ if (index & 2) {
+ newKeycode |= optionKey;
}
newChar = 0;
TkMacOSXKeycodeToUnicode(
- &newChar, 1, kEventRawKeyDown,
- newKeycode & 0x00FF, newKeycode & 0xFF00, NULL);
+ &newChar, 1, kEventRawKeyDown,
+ newKeycode & 0x00FF, newKeycode & 0xFF00, NULL);
/*
* X11 keysyms are identical to Unicode for ASCII and Latin-1. Give up
* for other characters for now.
*/
- if (newChar >= XK_space && newChar <= 0x255) {
- return newChar;
+
+ if ((newChar >= XK_space) && (newChar <= LATIN1_MAX)) {
+ return newChar;
}
return NoSymbol;
@@ -218,24 +323,24 @@ XKeycodeToKeysym(
*
* TkpGetString --
*
- * Retrieve the string equivalent for the given keyboard event.
+ * Retrieve the string equivalent for the given keyboard event.
*
* Results:
- * Returns the UTF string.
+ * Returns the UTF string.
*
* Side effects:
- * None.
+ * None.
*
*----------------------------------------------------------------------
*/
char *
TkpGetString(
- TkWindow *winPtr, /* Window where event occurred: needed to
- * get input context. */
- XEvent *eventPtr, /* X keyboard event. */
- Tcl_DString *dsPtr) /* Uninitialized or empty string to hold
- * result. */
+ TkWindow *winPtr, /* Window where event occurred: Needed to get
+ * input context. */
+ XEvent *eventPtr, /* X keyboard event. */
+ Tcl_DString *dsPtr) /* Uninitialized or empty string to hold
+ * result. */
{
(void) winPtr; /*unused*/
Tcl_DStringInit(dsPtr);
@@ -247,13 +352,13 @@ TkpGetString(
*
* XGetModifierMapping --
*
- * Fetch the current keycodes used as modifiers.
+ * Fetch the current keycodes used as modifiers.
*
* Results:
- * Returns a new modifier map.
+ * Returns a new modifier map.
*
* Side effects:
- * Allocates a new modifier map data structure.
+ * Allocates a new modifier map data structure.
*
*----------------------------------------------------------------------
*/
@@ -264,6 +369,13 @@ XGetModifierMapping(
{
XModifierKeymap * modmap;
+ (void) display; /*unused*/
+
+ /*
+ * MacOSX doesn't use the key codes for the modifiers for anything, and
+ * we don't generate them either. So there is no modifier map.
+ */
+
modmap = (XModifierKeymap *) ckalloc(sizeof(XModifierKeymap));
modmap->max_keypermod = 0;
modmap->modifiermap = NULL;
@@ -275,14 +387,13 @@ XGetModifierMapping(
*
* XFreeModifiermap --
*
- * Deallocate a modifier map that was created by
- * XGetModifierMapping.
+ * Deallocate a modifier map that was created by XGetModifierMapping.
*
* Results:
- * None.
+ * None.
*
* Side effects:
- * Frees the datastructure referenced by modmap.
+ * Frees the datastructure referenced by modmap.
*
*----------------------------------------------------------------------
*/
@@ -292,7 +403,7 @@ XFreeModifiermap(
XModifierKeymap *modmap)
{
if (modmap->modifiermap != NULL) {
- ckfree((char *) modmap->modifiermap);
+ ckfree((char *) modmap->modifiermap);
}
ckfree((char *) modmap);
}
@@ -302,16 +413,16 @@ XFreeModifiermap(
*
* XKeysymToString, XStringToKeysym --
*
- * These X window functions map Keysyms to strings & strings to
- * keysyms. However, Tk already does this for the most common keysyms.
- * Therefor, these functions only need to support keysyms that will be
- * specific to the Macintosh. Currently, there are none.
+ * These X window functions map keysyms to strings & strings to keysyms.
+ * However, Tk already does this for the most common keysyms.
+ * Therefore, these functions only need to support keysyms that will be
+ * specific to the Macintosh. Currently, there are none.
*
* Results:
- * None.
+ * None.
*
* Side effects:
- * None.
+ * None.
*
*----------------------------------------------------------------------
*/
@@ -325,7 +436,7 @@ XKeysymToString(
KeySym
XStringToKeysym(
- const char* string)
+ const char* string)
{
return NoSymbol;
}
@@ -333,19 +444,83 @@ XStringToKeysym(
/*
*----------------------------------------------------------------------
*
+ * XKeysymToMacKeycode --
+ *
+ * An internal function like XKeysymToKeycode but only generating the
+ * Mac specific keycode plus the modifiers Shift and Option.
+ *
+ * Results:
+ * A Mac keycode with the actual keycode in the low byte and Mac-style
+ * modifier bits in the high byte.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+XKeysymToMacKeycode(
+ Display *display,
+ KeySym keysym)
+{
+ if (keysym <= LATIN1_MAX) {
+
+ /*
+ * Handle keysyms in the Latin-1 range where keysym and Unicode
+ * character code point are the same.
+ */
+
+ InitLatin1Table(display);
+ return latin1Table[keysym];
+
+ } else {
+
+ /*
+ * Handle special keys from our exception tables. Don't mind if this
+ * is slow, neither the test suite nor [event generate] need to be
+ * optimized (we hope).
+ */
+
+ KeyInfo *kPtr;
+
+ for (kPtr = keyArray; kPtr->keycode != 0; kPtr++) {
+ if (kPtr->keysym == keysym) {
+ return kPtr->keycode;
+ }
+ }
+ for (kPtr = virtualkeyArray; kPtr->keycode != 0; kPtr++) {
+ if (kPtr->keysym == keysym) {
+ return kPtr->keycode;
+ }
+ }
+
+ /*
+ * For other keysyms (not Latin-1 and not special keys), we'd need a
+ * generic keysym-to-unicode table. We don't have that, so we give
+ * up here.
+ */
+
+ return 0;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* XKeysymToKeycode --
*
- * The function XKeysymToKeycode is only used by tkTest.c and
- * currently only implementes the support for keys used in the
- * Tk test suite.
- * FIXME - This is no longer true. This function is now used in
- * "event generate" so we really should make it work.
+ * The function XKeysymToKeycode takes an X11 keysym and converts it
+ * into a Mac keycode. It is in the stubs table for compatibility but
+ * not used anywhere in the core.
*
* Results:
- * None.
+ * A 32 bit keycode with the the mac keycode (without modifiers) in the
+ * higher 16 bits of the keycode and the ASCII or Latin-1 code in the
+ * lower 8 bits of the keycode.
*
* Side effects:
- * None.
+ * None.
*
*----------------------------------------------------------------------
*/
@@ -355,9 +530,28 @@ XKeysymToKeycode(
Display* display,
KeySym keysym)
{
- KeyCode keycode = 0;
- char virtualKeyCode = 0;
+ int macKeycode = XKeysymToMacKeycode(display, keysym);
+ KeyCode result;
+ /*
+ * See also TkpSetKeycodeAndState. The 0x0010 magic is used in
+ * XKeycodeToKeysym. For special keys like XK_Return the lower 8 bits of
+ * the keysym are usually a related ASCII control code.
+ */
+
+ if ((keysym >= XK_F1) && (keysym <= XK_F35)) {
+ result = 0x0010;
+ } else {
+ result = 0x00FF & keysym;
+ }
+ result |= (macKeycode & MAC_KEYCODE_MASK) << 16;
+
+ return result;
+}
+
+/*
+NB: Keep this commented code for a moment for reference.
+
if ((keysym >= XK_space) && (XK_asciitilde)) {
if (keysym == 'a') {
virtualKeyCode = 0x00;
@@ -375,54 +569,72 @@ XKeysymToKeycode(
virtualKeyCode = 0x24;
keysym = '\r';
}
- keycode = keysym + (virtualKeyCode <<16);
+ keycode = keysym + (virtualKeyCode <<16);
}
return keycode;
-}
+*/
/*
- * When mapping from a keysym to a keycode, need
- * information about the modifier state that should be used
- * so that when they call XKeycodeToKeysym taking into
- * account the xkey.state, they will get back the original
- * keysym.
+ *----------------------------------------------------------------------
+ *
+ * TkpSetKeycodeAndState --
+ *
+ * The function TkpSetKeycodeAndState takes a keysym and fills in the
+ * appropriate members of an XEvent. It is similar to XKeysymToKeycode,
+ * but it also sets the modifier mask in the XEvent. It is used by
+ * [event generate] and it is in the stubs table.
+ *
+ * Results:
+ * Fills an XEvent, sets the member xkey.keycode with a keycode
+ * formatted the same as XKeysymToKeycode and the member xkey.state with
+ * the modifiers implied by the keysym. Also fills in xkey.trans_chars,
+ * so that the actual characters can be retrieved later.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
*/
void
-TkpSetKeycodeAndState(tkwin, keySym, eventPtr)
- Tk_Window tkwin;
- KeySym keySym;
- XEvent *eventPtr;
+TkpSetKeycodeAndState(
+ Tk_Window tkwin,
+ KeySym keysym,
+ XEvent *eventPtr)
{
- Display *display;
- int state;
- KeyCode keycode;
-
- display = Tk_Display(tkwin);
-
- if (keySym == NoSymbol) {
- keycode = 0;
+ if (keysym == NoSymbol) {
+ eventPtr->xkey.keycode = 0;
} else {
- keycode = XKeysymToKeycode(display, keySym);
- }
- if (keycode != 0) {
- for (state = 0; state < 4; state++) {
- if (XKeycodeToKeysym(display, keycode, state) == keySym) {
- if (state & 1) {
- eventPtr->xkey.state |= ShiftMask;
- }
- if (state & 2) {
- TkDisplay *dispPtr;
-
- dispPtr = ((TkWindow *) tkwin)->dispPtr;
- eventPtr->xkey.state |= dispPtr->modeModMask;
- }
- break;
- }
- }
+ Display *display = Tk_Display(tkwin);
+ int macKeycode = XKeysymToMacKeycode(display, keysym);
+
+ /*
+ * See also XKeysymToKeycode.
+ */
+
+ if ((keysym >= XK_F1) && (keysym <= XK_F35)) {
+ eventPtr->xkey.keycode = 0x0010;
+ } else {
+ eventPtr->xkey.keycode = 0x00FF & keysym;
+ }
+ eventPtr->xkey.keycode |= (macKeycode & MAC_KEYCODE_MASK) << 16;
+
+ if (shiftKey & macKeycode) {
+ eventPtr->xkey.state |= ShiftMask;
+ }
+ if (optionKey & macKeycode) {
+ eventPtr->xkey.state |= OPTION_MASK;
+ }
+
+ if (keysym <= LATIN1_MAX) {
+ int done;
+ done = Tcl_UniCharToUtf(keysym,eventPtr->xkey.trans_chars);
+ eventPtr->xkey.trans_chars[done] = 0;
+ } else {
+ eventPtr->xkey.trans_chars[0] = 0;
+ }
}
- eventPtr->xkey.keycode = keycode;
}
/*
@@ -430,105 +642,132 @@ TkpSetKeycodeAndState(tkwin, keySym, eventPtr)
*
* TkpGetKeySym --
*
- * Given an X KeyPress or KeyRelease event, map the
- * keycode in the event into a KeySym.
+ * Given an X KeyPress or KeyRelease event, map the keycode in the event
+ * into a keysym.
*
* Results:
- * The return value is the KeySym corresponding to
- * eventPtr, or NoSymbol if no matching Keysym could be
- * found.
+ * The return value is the keysym corresponding to eventPtr, or NoSymbol
+ * if no matching keysym could be found.
*
* Side effects:
- * In the first call for a given display, keycode-to-
- * KeySym maps get loaded.
+ * In the first call for a given display, keycode-to-keysym maps get
+ * loaded.
*
*----------------------------------------------------------------------
*/
KeySym
-TkpGetKeySym(dispPtr, eventPtr)
- TkDisplay *dispPtr; /* Display in which to
- * map keycode. */
- XEvent *eventPtr; /* Description of X event. */
+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
+ * Refresh the mapping information if it's stale.
*/
if (dispPtr->bindInfoStale) {
- TkpInitKeymapInfo(dispPtr);
+ 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.
+ * 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;
- if (eventPtr->xkey.state & dispPtr->modeModMask) {
- index = 2;
+
+ /*
+ * 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;
- }
- if (eventPtr->xany.send_event == -1) {
- /* We use -1 as a special signal for a pure modifier */
- 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;
- }
+ || (/* (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.
+ * 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 = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode,
- index);
- }
+ /*&& (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.
+ * 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);
+ sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode,
+ index & ~1);
}
return sym;
}
@@ -538,127 +777,48 @@ TkpGetKeySym(dispPtr, eventPtr)
*
* TkpInitKeymapInfo --
*
- * This procedure is invoked to scan keymap information
- * to recompute stuff that's important for binding, such
- * as the modifier key (if any) that corresponds to "mode
- * switch".
+ * This procedure is invoked to scan keymap information to recompute
+ * stuff that's important for binding, such as the modifier key (if any)
+ * that corresponds to the "Mode_switch" keysym.
*
* Results:
- * None.
+ * None.
*
* Side effects:
- * Keymap-related information in dispPtr is updated.
+ * Keymap-related information in dispPtr is updated.
*
*--------------------------------------------------------------
*/
void
-TkpInitKeymapInfo(dispPtr)
- TkDisplay *dispPtr; /* Display for which to recompute keymap
- * information. */
+TkpInitKeymapInfo(
+ TkDisplay *dispPtr) /* Display for which to recompute keymap
+ * information. */
{
- XModifierKeymap *modMapPtr;
- KeyCode *codePtr;
- KeySym keysym;
- int count, i, j, max, arraySize;
-#define KEYCODE_ARRAY_SIZE 20
-
dispPtr->bindInfoStale = 0;
- modMapPtr = XGetModifierMapping(dispPtr->display);
-
- /*
- * Check the keycodes associated with the Lock modifier. If
- * any of them is associated with the XK_Shift_Lock modifier,
- * then Lock has to be interpreted as Shift Lock, not Caps Lock.
- */
-
- dispPtr->lockUsage = LU_IGNORE;
- codePtr = modMapPtr->modifiermap + modMapPtr->max_keypermod*LockMapIndex;
- for (count = modMapPtr->max_keypermod; count > 0; count--, codePtr++) {
- if (*codePtr == 0) {
- continue;
- }
- keysym = XKeycodeToKeysym(dispPtr->display, *codePtr, 0);
- if (keysym == XK_Shift_Lock) {
- dispPtr->lockUsage = LU_SHIFT;
- break;
- }
- if (keysym == XK_Caps_Lock) {
- dispPtr->lockUsage = LU_CAPS;
- break;
- }
- }
/*
- * Look through the keycodes associated with modifiers to see if
- * the the "mode switch", "meta", or "alt" keysyms are associated
- * with any modifiers. If so, remember their modifier mask bits.
+ * Behaviours that are variable on X11 are defined constant on MacOSX.
+ * lockUsage is only used above in TkpGetKeySym(), nowhere else
+ * currently. There is no offical "Mode_switch" key.
*/
+ dispPtr->lockUsage = LU_CAPS;
dispPtr->modeModMask = 0;
- dispPtr->metaModMask = 0;
- dispPtr->altModMask = 0;
- codePtr = modMapPtr->modifiermap;
- max = 8*modMapPtr->max_keypermod;
- for (i = 0; i < max; i++, codePtr++) {
- if (*codePtr == 0) {
- continue;
- }
- keysym = XKeycodeToKeysym(dispPtr->display, *codePtr, 0);
- if (keysym == XK_Mode_switch) {
- dispPtr->modeModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
- }
- if ((keysym == XK_Meta_L) || (keysym == XK_Meta_R)) {
- dispPtr->metaModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
- }
- if ((keysym == XK_Alt_L) || (keysym == XK_Alt_R)) {
- dispPtr->altModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
- }
- }
+ dispPtr->altModMask = ALT_MASK;
+ dispPtr->metaModMask = OPTION_MASK;
/*
- * Create an array of the keycodes for all modifier keys.
+ * MacOSX doesn't use the keycodes for the modifiers for anything, and we
+ * don't generate them either (the keycodes actually given in the
+ * simulated modifier events are bogus). So there is no modifier map.
+ * If we ever want to simulate real modifier keycodes, the list will be
+ * constant in the Carbon implementation.
*/
if (dispPtr->modKeyCodes != NULL) {
- ckfree((char *) dispPtr->modKeyCodes);
+ ckfree((char *) dispPtr->modKeyCodes);
}
dispPtr->numModKeyCodes = 0;
- arraySize = KEYCODE_ARRAY_SIZE;
- dispPtr->modKeyCodes = (KeyCode *) ckalloc((unsigned)
- (KEYCODE_ARRAY_SIZE * sizeof(KeyCode)));
- for (i = 0, codePtr = modMapPtr->modifiermap; i < max; i++, codePtr++) {
- if (*codePtr == 0) {
- continue;
- }
-
- /*
- * Make sure that the keycode isn't already in the array.
- */
-
- for (j = 0; j < dispPtr->numModKeyCodes; j++) {
- if (dispPtr->modKeyCodes[j] == *codePtr) {
- goto nextModCode;
- }
- }
- if (dispPtr->numModKeyCodes >= arraySize) {
- KeyCode *new;
-
- /*
- * Ran out of space in the array; grow it.
- */
-
- arraySize *= 2;
- new = (KeyCode *) ckalloc((unsigned)
- (arraySize * sizeof(KeyCode)));
- memcpy((VOID *) new, (VOID *) dispPtr->modKeyCodes,
- (dispPtr->numModKeyCodes * sizeof(KeyCode)));
- ckfree((char *) dispPtr->modKeyCodes);
- dispPtr->modKeyCodes = new;
- }
- dispPtr->modKeyCodes[dispPtr->numModKeyCodes] = *codePtr;
- dispPtr->numModKeyCodes++;
- nextModCode: continue;
- }
- XFreeModifiermap(modMapPtr);
+ dispPtr->modKeyCodes = NULL;
}