STR #2098: updated the keyboard handling for 10.5 to better handle composed keys. This now works at least for German and American keyboard mapping (I can finally type German text on my US keyboard again), but is still far from perfect. Also applied Ian's patch which I can't test due to missing OS. Thanks, Ian!

git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@6593 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
Matthias Melcher
2008-12-20 21:09:59 +00:00
parent 3db04d80a1
commit 47fbe07afe
2 changed files with 75 additions and 36 deletions
+1
View File
@@ -1,5 +1,6 @@
CHANGES IN FLTK 1.3.0 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. - Updated the bundled libpng to v1.2.33.
- Fixed callback would not be called when shortcut was used with - Fixed callback would not be called when shortcut was used with
radio and toggle buttons in default FL_RELEASE mode. radio and toggle buttons in default FL_RELEASE mode.
+69 -31
View File
@@ -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( static int keycodeToUnicode(
char * uniChars, int maxChars, char * uniChars, int maxChars,
EventKind eKind, EventKind eKind,
UInt32 keycode, UInt32 modifiers, 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 // first get the keyboard mapping in a post 10.2 way
@@ -1172,36 +1174,58 @@ static int keycodeToUnicode(
default: return 0; default: return 0;
} }
UInt32 deadKeyState = *deadKeyStatePtr;
if ((action==kUCKeyActionUp)&&(*deadKeyStatePtr))
deadKeyStatePtr = &deadKeyState;
status = UCKeyTranslate( status = UCKeyTranslate(
(const UCKeyboardLayout *) uchr, (const UCKeyboardLayout *) uchr,
keycode, action, modifiers, keyboardType, keycode, action, modifiers, keyboardType,
options, deadKeyStatePtr, 0, deadKeyStatePtr,
10, &actuallength, utext); 10, &actuallength, utext);
if ((0 == actuallength) && (0 != *deadKeyStatePtr)) {
/*
* More data later
*/
return 0;
}
*deadKeyStatePtr = 0;
if (noErr != status) { if (noErr != status) {
fprintf(stderr,"UCKeyTranslate failed: %d", (int) status); fprintf(stderr,"UCKeyTranslate failed: %d\n", (int) status);
actuallength = 0; actuallength = 0;
} }
// convert the list of unicode chars into utf8
// FIXME no bounds check (see maxchars) // FIXME no bounds check (see maxchars)
unsigned i; unsigned i;
for (i=0; i<actuallength; ++i) { for (i=0; i<actuallength; ++i) {
len += fl_utf8encode(utext[i], uniChars+len); len += fl_utf8encode(utext[i], uniChars+len);
} }
uniChars[len] = 0; uniChars[len] = 0;
return len;
return actuallength;
} }
/*
* 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 * handle carbon keyboard events
@@ -1234,7 +1258,7 @@ pascal OSStatus carbonKeyboardHandler(
GetEventParameter( event, kEventParamKeyMacCharCodes, typeChar, GetEventParameter( event, kEventParamKeyMacCharCodes, typeChar,
NULL, sizeof(char), NULL, &key ); NULL, sizeof(char), NULL, &key );
} }
/* output a human readbale event identifier for debugging /* output a human readable event identifier for debugging
const char *ev = ""; const char *ev = "";
switch (kind) { switch (kind) {
case kEventRawKeyDown: ev = "kEventRawKeyDown"; break; case kEventRawKeyDown: ev = "kEventRawKeyDown"; break;
@@ -1249,6 +1273,8 @@ pascal OSStatus carbonKeyboardHandler(
{ {
case kEventRawKeyDown: case kEventRawKeyDown:
case kEventRawKeyRepeat: 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 // 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 // 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". // giving us the code by sending a "space" after the "dead key".
@@ -1263,6 +1289,7 @@ pascal OSStatus carbonKeyboardHandler(
} else { } else {
Fl::e_state &= 0xbfffffff; // clear the deadkey flag Fl::e_state &= 0xbfffffff; // clear the deadkey flag
} }
*/
sendEvent = FL_KEYBOARD; sendEvent = FL_KEYBOARD;
// fall through // fall through
case kEventRawKeyUp: case kEventRawKeyUp:
@@ -1287,22 +1314,14 @@ pascal OSStatus carbonKeyboardHandler(
// Matt: to Carbon. The kEventKeyModifierNumLockMask is only set when // Matt: to Carbon. The kEventKeyModifierNumLockMask is only set when
// Matt: a numeric keypad key is pressed and does not correspond with // Matt: a numeric keypad key is pressed and does not correspond with
// Matt: the NumLock light in PowerBook keyboards. // Matt: the NumLock light in PowerBook keyboards.
#if 1
if ( (sym >= FL_KP && sym <= FL_KP_Last) || !(sym & 0xff00) || // Matt: attempt to get the correct Unicode character(s) from our keycode
sym == FL_Tab || sym == FL_Enter) { // imm: keycode_function function pointer added to allow us to use different functions
buffer[0] = key; // imm: depending on which OS version we are running on (tested and set in fl_open_display)
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
static UInt32 deadKeyState = 0; // must be cleared when losing focus static UInt32 deadKeyState = 0; // must be cleared when losing focus
Fl::e_length = keycodeToUnicode(buffer, 31, kind, keyCode, mods, &deadKeyState); Fl::e_length = (*keycode_function)(buffer, 31, kind, keyCode, mods, &deadKeyState, key, sym);
#endif
Fl::e_text = buffer; Fl::e_text = buffer;
// insert UnicodeHandling here! buffer[Fl::e_length] = 0; // just in case...
break; break;
case kEventRawKeyModifiersChanged: { case kEventRawKeyModifiersChanged: {
UInt32 tMods = prevMods ^ mods; UInt32 tMods = prevMods ^ mods;
@@ -1467,6 +1486,25 @@ void fl_open_display() {
CFRelease(execUrl); 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 ) if( !bundle )
{ {
// Earlier versions of this code tried to use weak linking, however it // Earlier versions of this code tried to use weak linking, however it