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

View File

@ -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.

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(
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