diff options
Diffstat (limited to 'macosx/tkMacOSXKeyEvent.c')
-rw-r--r-- | macosx/tkMacOSXKeyEvent.c | 89 |
1 files changed, 85 insertions, 4 deletions
diff --git a/macosx/tkMacOSXKeyEvent.c b/macosx/tkMacOSXKeyEvent.c index 7c3474c..a8d2711 100644 --- a/macosx/tkMacOSXKeyEvent.c +++ b/macosx/tkMacOSXKeyEvent.c @@ -76,7 +76,8 @@ static Tk_Window gKeyboardWinPtr = NULL; /* Current keyboard grab window. */ static int GenerateKeyEvent _ANSI_ARGS_(( EventKind eKind, KeyEventData * e, Window window, - UInt32 savedKeyCode)); + UInt32 savedKeyCode, + UInt32 savedModifiers)); /* *---------------------------------------------------------------------- * @@ -99,6 +100,7 @@ int TkMacOSXProcessKeyboardEvent( MacEventStatus * statusPtr) { static UInt32 savedKeyCode = 0; + static UInt32 savedModifiers = 0; OSStatus status; KeyEventData keyEventData; Window window; @@ -115,6 +117,26 @@ int TkMacOSXProcessKeyboardEvent( keyEventData.global = keyEventData.local; LocalToGlobal(&keyEventData.global); keyEventData.state = TkMacOSXButtonKeyState(); +#if 0 + /* + * This block of code seems like a good idea, to trap + * key-bindings which point directly to menus, but it + * has a number of problems: + * (1) when grabs are present we definitely don't want + * to do this. + * (2) Tk's semantics define accelerator keystrings in + * menus as a purely visual adornment, and require that + * the developer create separate bindings to trigger + * them. This breaks those semantics. (i.e. Tk will + * behave differently on Aqua to the behaviour on Unix/Win). + * (3) Tk's bindings depend on the current window's bindtags, + * which may be completely different to what happens to be + * in some global menu (agreed, it shouldn't be that different, + * but it often is). + * + * While a better middleground might be possible, the best, most + * compatible, approach at present is to disable this block. + */ if (IsMenuKeyEvent(NULL, eventPtr->eventRef, kNilOptions, &menuRef, &menuItemIndex)) { int oldMode; @@ -138,6 +160,7 @@ int TkMacOSXProcessKeyboardEvent( Tcl_SetServiceMode(oldMode); return 0; /* TODO: may not be on event on queue. */ } +#endif status = GetEventParameter(eventPtr->eventRef, kEventParamKeyMacCharCodes, @@ -174,7 +197,8 @@ int TkMacOSXProcessKeyboardEvent( window = TkMacOSXGetXWindow(keyEventData.whichWindow); eventGenerated = GenerateKeyEvent(eventPtr->eKind, &keyEventData, - window, savedKeyCode); + window, savedKeyCode, savedModifiers); + savedModifiers = keyEventData.keyModifiers; if (eventGenerated == 0) { savedKeyCode = keyEventData.message; @@ -212,7 +236,8 @@ int GenerateKeyEvent( EventKind eKind, KeyEventData * e, Window window, - UInt32 savedKeyCode ) + UInt32 savedKeyCode, + UInt32 savedModifiers ) { Tk_Window tkwin; XEvent event; @@ -240,7 +265,23 @@ GenerateKeyEvent( EventKind eKind, return -1; } byte = (e->message&charCodeMask); - if ((savedKeyCode == 0) && + if (byte == 0) { + /* + * Either we have a pure-modifier change, or perhaps + * a dead-key (e.g. opt-e) was pressed. In the former case we do + * want to generate an event, in the latter I'm not sure + * what to do. + */ + if (eKind == kEventRawKeyModifiersChanged) { + /* Drop through to the event code below */ + } else { + /* + * What shall we do here? We certainly aren't dealing + * with deadkeys at present. Is this where they come? + */ + return 0; + } + } else if ((savedKeyCode == 0) && (Tcl_ExternalToUtf(NULL, TkMacOSXCarbonEncoding, (char *) &byte, 1, 0, NULL, buf, sizeof(buf), NULL, NULL, NULL) != TCL_OK)) { @@ -262,6 +303,30 @@ GenerateKeyEvent( EventKind eKind, Tk_TopCoordsToWindow(tkwin, e->local.h, e->local.v, &event.xkey.x, &event.xkey.y); + /* + * Now, we may have a problem here. How do we handle 'Option-char' + * keypresses? The problem is that we might want to bind to some of + * these (e.g. Cmd-Opt-d is 'uncomment' in Alpha), but Option-d + * generates a 'delta' symbol with some keycode unrelated to 'd', and so + * the binding never triggers. In any case, the delta that is produced + * is never mapped to an 'XK_Greek_DELTA' keysym so bindings on that + * won't work either (a general KeyPress binding will of course trigger, + * but a specific binding on XK_Greek_DELTA will not). + * + * I think what we want is for the event to contain information on + * both the 'Opt-d' side of things and the 'delta'. Then a binding + * on Opt-d will trigger, but the ascii/string representation of the + * event will be a delta. + * + * A different way to look at this is that 'Opt-d' is delta, but that + * Command-Opt-d is nothing to do with delta, but I'm not sure that is + * helpful. + * + * Also some keypresses (Opt-e) are dead-keys to add accents to + * letters. We don't handle them yet. + * + * Help needed! + */ event.xkey.keycode = byte | ((savedKeyCode & charCodeMask) << 8) | ((e->message&keyCodeMask) << 8); @@ -287,6 +352,22 @@ GenerateKeyEvent( EventKind eKind, event.xany.type = KeyPress; Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); break; + case kEventRawKeyModifiersChanged: + if (savedModifiers > e->keyModifiers) { + event.xany.type = KeyRelease; + } else { + event.xany.type = KeyPress; + } + /* + * Use special '-1' to signify a special keycode to + * our platform specific code in tkMacOSXKeyboard.c. + * This is rather like what happens on Windows. + */ + event.xany.send_event = -1; + /* Set keycode (which was zero) to the changed modifier */ + event.xkey.keycode = (e->keyModifiers ^ savedModifiers); + Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); + break; default: break; } |