summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES1
-rw-r--r--src/Fl_mac.cxx110
2 files changed, 75 insertions, 36 deletions
diff --git a/CHANGES b/CHANGES
index b24d6b6cf..d7ff4a44c 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,6 @@
CHANGES IN FLTK 1.3.0
+ - Improved handling of composed keys in OS X 10.5 and up
- Updated the bundled libpng to v1.2.33.
- Fixed callback would not be called when shortcut was used with
radio and toggle buttons in default FL_RELEASE mode.
diff --git a/src/Fl_mac.cxx b/src/Fl_mac.cxx
index 7edb07bea..7db76cbdf 100644
--- a/src/Fl_mac.cxx
+++ b/src/Fl_mac.cxx
@@ -1096,13 +1096,15 @@ static unsigned short keycode_to_sym( UInt32 keyCode, UInt32 mods, unsigned shor
}
/*
- *
+ * keycode_function for post-10.5 systems, allows more sophisticated decoding of keys
*/
static int keycodeToUnicode(
char * uniChars, int maxChars,
EventKind eKind,
UInt32 keycode, UInt32 modifiers,
- UInt32 * deadKeyStatePtr)
+ UInt32 * deadKeyStatePtr,
+ unsigned char, // not used in this function
+ unsigned short) // not used in this function
{
// first get the keyboard mapping in a post 10.2 way
@@ -1171,37 +1173,59 @@ static int keycodeToUnicode(
case kEventRawKeyRepeat: action = kUCKeyActionAutoKey; break;
default: return 0;
}
-
+
+ UInt32 deadKeyState = *deadKeyStatePtr;
+ if ((action==kUCKeyActionUp)&&(*deadKeyStatePtr))
+ deadKeyStatePtr = &deadKeyState;
+
status = UCKeyTranslate(
(const UCKeyboardLayout *) uchr,
keycode, action, modifiers, keyboardType,
- options, deadKeyStatePtr,
+ 0, deadKeyStatePtr,
10, &actuallength, utext);
-
- if ((0 == actuallength) && (0 != *deadKeyStatePtr)) {
- /*
- * More data later
- */
-
- return 0;
- }
-
- *deadKeyStatePtr = 0;
-
+
if (noErr != status) {
- fprintf(stderr,"UCKeyTranslate failed: %d", (int) status);
+ fprintf(stderr,"UCKeyTranslate failed: %d\n", (int) status);
actuallength = 0;
}
+
+ // convert the list of unicode chars into utf8
// FIXME no bounds check (see maxchars)
unsigned i;
for (i=0; i<actuallength; ++i) {
len += fl_utf8encode(utext[i], uniChars+len);
}
uniChars[len] = 0;
-
- return actuallength;
+ return len;
}
+/*
+ * keycode_function for pre-10.5 systems, this is the "historic" fltk Mac key handling
+ */
+static int keycode_wrap_old(
+ char * buffer,
+ int, EventKind, UInt32, // not used in this function
+ UInt32, UInt32 *, // not used in this function
+ unsigned char key,
+ unsigned short sym)
+{
+ if ( (sym >= FL_KP && sym <= FL_KP_Last) || !(sym & 0xff00) ||
+ sym == FL_Tab || sym == FL_Enter) {
+ buffer[0] = key;
+ return 1;
+ } else {
+ buffer[0] = 0;
+ return 0;
+ }
+} /* keycode_wrap_old */
+/*
+ * Stub pointer to select appropriate keycode_function per operating system version. This function pointer
+ * is initialised in fl_open_display, based on the runtime identification of the host OS version. This is
+ * intended to allow us to utilise 10.5 services dynamically to improve Unicode handling, whilst still
+ * allowing code to run satisfactorily on older systems.
+ */
+static int (*keycode_function)(char*, int, EventKind, UInt32, UInt32, UInt32*, unsigned char, unsigned short) = keycode_wrap_old;
+
/**
* handle carbon keyboard events
@@ -1234,7 +1258,7 @@ pascal OSStatus carbonKeyboardHandler(
GetEventParameter( event, kEventParamKeyMacCharCodes, typeChar,
NULL, sizeof(char), NULL, &key );
}
- /* output a human readbale event identifier for debugging
+ /* output a human readable event identifier for debugging
const char *ev = "";
switch (kind) {
case kEventRawKeyDown: ev = "kEventRawKeyDown"; break;
@@ -1249,6 +1273,8 @@ pascal OSStatus carbonKeyboardHandler(
{
case kEventRawKeyDown:
case kEventRawKeyRepeat:
+/*
+ // FIXME Matt: For 10.5, the keycode_function will handle all this. This is untested for ealier versions of OS X.
// When the user presses a "dead key", no information is send about
// which dead key symbol was created. So we need to trick Carbon into
// giving us the code by sending a "space" after the "dead key".
@@ -1263,6 +1289,7 @@ pascal OSStatus carbonKeyboardHandler(
} else {
Fl::e_state &= 0xbfffffff; // clear the deadkey flag
}
+*/
sendEvent = FL_KEYBOARD;
// fall through
case kEventRawKeyUp:
@@ -1287,22 +1314,14 @@ pascal OSStatus carbonKeyboardHandler(
// Matt: to Carbon. The kEventKeyModifierNumLockMask is only set when
// Matt: a numeric keypad key is pressed and does not correspond with
// Matt: the NumLock light in PowerBook keyboards.
-#if 1
- if ( (sym >= FL_KP && sym <= FL_KP_Last) || !(sym & 0xff00) ||
- sym == FL_Tab || sym == FL_Enter) {
- buffer[0] = key;
- Fl::e_length = 1;
- } else {
- buffer[0] = 0;
- Fl::e_length = 0;
- }
-#else
- // Matt: attempt to get the correct Unicode character(S) from our keycode
+
+ // Matt: attempt to get the correct Unicode character(s) from our keycode
+ // imm: keycode_function function pointer added to allow us to use different functions
+ // imm: depending on which OS version we are running on (tested and set in fl_open_display)
static UInt32 deadKeyState = 0; // must be cleared when losing focus
- Fl::e_length = keycodeToUnicode(buffer, 31, kind, keyCode, mods, &deadKeyState);
-#endif
+ Fl::e_length = (*keycode_function)(buffer, 31, kind, keyCode, mods, &deadKeyState, key, sym);
Fl::e_text = buffer;
- // insert UnicodeHandling here!
+ buffer[Fl::e_length] = 0; // just in case...
break;
case kEventRawKeyModifiersChanged: {
UInt32 tMods = prevMods ^ mods;
@@ -1467,12 +1486,31 @@ void fl_open_display() {
CFRelease(execUrl);
}
+ // imm: keycode handler stub setting - use Gestalt to determine the running system version,
+ // then set the keycode_function pointer accordingly
+ SInt32 MacVersion;
+ if (Gestalt(gestaltSystemVersion, &MacVersion) == noErr)
+ {
+// SInt32 maj, min, fix;
+// Gestalt(gestaltSystemVersionMajor, &maj); // e.g. 10
+// Gestalt(gestaltSystemVersionMinor, &min); // e.g. 4
+// Gestalt(gestaltSystemVersionBugFix, &fix); // e.g. 11
+ if(MacVersion >= 0x1050) { // 10.5.0 or later
+ keycode_function = keycodeToUnicode;
+ }
+ else {
+ keycode_function = keycode_wrap_old; // pre-10.5 mechanism
+ }
+ }
+ // else our default handler will be used (keycode_wrap_old)
+
+
if( !bundle )
{
// Earlier versions of this code tried to use weak linking, however it
- // appears that this does not work on 10.2. Since 10.3 and higher provide
- // both TransformProcessType and CPSEnableForegroundOperation, the following
- // conditional code compiled on 10.2 will still work on newer releases...
+ // appears that this does not work on 10.2. Since 10.3 and higher provide
+ // both TransformProcessType and CPSEnableForegroundOperation, the following
+ // conditional code compiled on 10.2 will still work on newer releases...
OSErr err;
#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2