summaryrefslogtreecommitdiffstats
path: root/macosx/tkMacOSXKeyEvent.c
diff options
context:
space:
mode:
Diffstat (limited to 'macosx/tkMacOSXKeyEvent.c')
-rw-r--r--macosx/tkMacOSXKeyEvent.c89
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;
}