diff options
Diffstat (limited to 'contrib/fltk/03-str2599-fltk-1.3.x-keyboard-osx.patch')
-rw-r--r-- | contrib/fltk/03-str2599-fltk-1.3.x-keyboard-osx.patch | 375 |
1 files changed, 375 insertions, 0 deletions
diff --git a/contrib/fltk/03-str2599-fltk-1.3.x-keyboard-osx.patch b/contrib/fltk/03-str2599-fltk-1.3.x-keyboard-osx.patch new file mode 100644 index 00000000..cf13aad7 --- /dev/null +++ b/contrib/fltk/03-str2599-fltk-1.3.x-keyboard-osx.patch @@ -0,0 +1,375 @@ +diff -ur fltk-1.3.0r9619.org/configure.in fltk-1.3.0r9619/configure.in +--- fltk-1.3.0r9619.org/configure.in 2012-04-22 04:45:09.000000000 +0200 ++++ fltk-1.3.0r9619/configure.in 2012-06-18 13:47:33.290447462 +0200 +@@ -865,6 +865,8 @@ + Darwin*) + # MacOS X uses Cocoa for graphics. + LIBS="$LIBS -framework Cocoa" ++ # And some Carbon for keyboard handling ++ LIBS="$LIBS -framework Carbon" + + if test x$have_pthread = xyes; then + AC_DEFINE(HAVE_PTHREAD) +diff -ur fltk-1.3.0r9619.org/src/Fl_cocoa.mm fltk-1.3.0r9619/src/Fl_cocoa.mm +--- fltk-1.3.0r9619.org/src/Fl_cocoa.mm 2012-06-16 10:49:52.000000000 +0200 ++++ fltk-1.3.0r9619/src/Fl_cocoa.mm 2012-06-18 13:47:42.944910782 +0200 +@@ -53,6 +53,7 @@ + #include <math.h> + + #import <Cocoa/Cocoa.h> ++#import <Carbon/Carbon.h> + + #ifndef NSINTEGER_DEFINED // appears with 10.5 in NSObjCRuntime.h + #if defined(__LP64__) && __LP64__ +@@ -114,6 +115,8 @@ + extern Fl_Window* fl_xmousewin; + #endif + ++bool use_simple_keyboard = false; ++ + enum { FLTKTimerEvent = 1, FLTKDataReadyEvent }; + + +@@ -130,6 +133,39 @@ + { + } + ++// Undocumented voodoo. Taken from Mozilla. ++#define ENABLE_ROMAN_KYBDS_ONLY -23 ++ ++void fl_update_focus(void) ++{ ++ Fl_Widget *focus; ++ ++ focus = Fl::grab(); ++ if (!focus) ++ focus = Fl::focus(); ++ if (!focus) ++ return; ++ ++ if (focus->simple_keyboard()) ++ use_simple_keyboard = true; ++ else ++ use_simple_keyboard = false; ++ ++ // Force a "Roman" or "ASCII" keyboard, which both the Mozilla and ++ // Safari people seem to think implies turning off advanced IME stuff ++ // (see nsTSMManager::SyncKeyScript in Mozilla and enableSecureTextInput ++ // in Safari/Webcore). Should be good enough for us then... ++#if (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5) ++ CFArrayRef inputSources = TISCreateASCIICapableInputSourceList(); ++ TSMSetDocumentProperty(TSMGetActiveDocument(), ++ kTSMDocumentEnabledInputSourcesPropertyTag, ++ sizeof(CFArrayRef), &inputSources); ++ CFRelease(inputSources); ++#else ++ KeyScript(use_simple_keyboard ? ENABLE_ROMAN_KYBDS_ONLY : smKeyEnableKybds); ++#endif ++} ++ + /* + * Mac keyboard lookup table + */ +@@ -908,6 +944,25 @@ + } + @end + ++static const char* cocoaDead2FLTK(const char *in) ++{ ++ if (strcmp(in, "\140") == 0) // GRAVE ACCENT ++ return "\314\200"; // COMBINING GRAVE ACCENT ++ if (strcmp(in, "\302\264") == 0) // ACUTE ACCENT ++ return "\314\201"; // COMBINING ACUTE ACCENT ++ if (strcmp(in, "\136") == 0) // CIRCUMFLEX ACCENT ++ return "\314\202"; // COMBINING CIRCUMFLEX ACCENT ++ if (strcmp(in, "\176") == 0) // TILDE ++ return "\314\203"; // COMBINING TILDE ++ if (strcmp(in, "\302\250") == 0) // DIAERESIS ++ return "\314\210"; // COMBINING DIAERESIS ++ // FIXME: OS X dead key behaviour isn't documented and I don't have ++ // any more keyboards to test with... ++ ++ // hope that OS X gave us something proper to begin with ++ return in; ++} ++ + /* + Handle cocoa keyboard events + Events during a character composition sequence: +@@ -1648,6 +1703,7 @@ + - (void)rightMouseDragged:(NSEvent *)theEvent; + - (void)otherMouseDragged:(NSEvent *)theEvent; + - (void)scrollWheel:(NSEvent *)theEvent; +++ (NSString *)keyTranslate:(UInt16)keyCode withModifierFlags:(UInt32)modifierFlags; + - (BOOL)handleKeyDown:(NSEvent *)theEvent; + - (void)keyDown:(NSEvent *)theEvent; + - (void)keyUp:(NSEvent *)theEvent; +@@ -1726,6 +1782,130 @@ + - (void)scrollWheel:(NSEvent *)theEvent { + cocoaMouseWheelHandler(theEvent); + } +++ (NSString *)keyTranslate:(UInt16)keyCode withModifierFlags:(UInt32)modifierFlags { ++ const UCKeyboardLayout *layout; ++ OSStatus err; ++ ++ layout = NULL; ++ ++#if (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5) ++ TISInputSourceRef keyboard; ++ CFDataRef uchr; ++ ++ keyboard = TISCopyCurrentKeyboardInputSource(); ++ uchr = (CFDataRef)TISGetInputSourceProperty(keyboard, ++ kTISPropertyUnicodeKeyLayoutData); ++ if (uchr == NULL) ++ return nil; ++ ++ layout = (const UCKeyboardLayout*)CFDataGetBytePtr(uchr); ++#else ++ KeyboardLayoutRef old_layout; ++ int kind; ++ ++ err = KLGetCurrentKeyboardLayout(&old_layout); ++ if (err != noErr) ++ return nil; ++ ++ err = KLGetKeyboardLayoutProperty(old_layout, kKLKind, ++ (const void**)&kind); ++ if (err != noErr) ++ return nil; ++ ++ // Old, crufty layout format? ++ if (kind == kKLKCHRKind) { ++ void *kchr_layout; ++ ++ UInt32 chars, state; ++ char buf[3]; ++ ++ unichar result[16]; ++ ByteCount in_len, out_len; ++ ++ err = KLGetKeyboardLayoutProperty(old_layout, kKLKCHRData, ++ (const void**)&kchr_layout); ++ if (err != noErr) ++ return nil; ++ ++ state = 0; ++ ++ keyCode &= 0x7f; ++ modifierFlags &= 0xff00; ++ ++ chars = KeyTranslate(kchr_layout, keyCode | modifierFlags, &state); ++ ++ buf[0] = (chars >> 16) & 0xff; ++ buf[1] = chars & 0xff; ++ buf[2] = '\0'; ++ ++ if (buf[0] == '\0') { ++ buf[0] = buf[1]; ++ buf[1] = '\0'; ++ } ++ ++ // The data is now in some layout specific encoding. Need to convert ++ // this to unicode. ++ ++ ScriptCode script; ++ TextEncoding encoding; ++ TECObjectRef converter; ++ ++ script = (ScriptCode)GetScriptManagerVariable(smKeyScript); ++ ++ err = UpgradeScriptInfoToTextEncoding(script, kTextLanguageDontCare, ++ kTextRegionDontCare, NULL, ++ &encoding); ++ if (err != noErr) ++ return nil; ++ ++ err = TECCreateConverter(&converter, encoding, kTextEncodingUnicodeV4_0); ++ if (err != noErr) ++ return nil; ++ ++ in_len = strlen(buf); ++ out_len = sizeof(result); ++ ++ err = TECConvertText(converter, (ConstTextPtr)buf, in_len, &in_len, ++ (TextPtr)result, out_len, &out_len); ++ ++ TECDisposeConverter(converter); ++ ++ if (err != noErr) ++ return nil; ++ ++ return [NSString stringWithCharacters:result ++ length:(out_len / sizeof(unichar))]; ++ } ++ ++ if ((kind != kKLKCHRuchrKind) && (kind != kKLuchrKind)) ++ return nil; ++ ++ err = KLGetKeyboardLayoutProperty(old_layout, kKLuchrData, ++ (const void**)&layout); ++ if (err != noErr) ++ return nil; ++#endif ++ ++ if (layout == NULL) ++ return nil; ++ ++ UInt32 dead_state; ++ UniCharCount max_len, actual_len; ++ UniChar string[255]; ++ ++ dead_state = 0; ++ max_len = sizeof(string)/sizeof(*string); ++ ++ modifierFlags = (modifierFlags >> 8) & 0xff; ++ ++ err = UCKeyTranslate(layout, keyCode, kUCKeyActionDown, modifierFlags, ++ LMGetKbdType(), 0, &dead_state, max_len, &actual_len, ++ string); ++ if (err != noErr) ++ return nil; ++ ++ return [NSString stringWithCharacters:string length:actual_len]; ++} + - (BOOL)handleKeyDown:(NSEvent *)theEvent { + //NSLog(@"handleKeyDown"); + fl_lock_function(); +@@ -1752,14 +1932,47 @@ + break; + } + } +- if (!no_text_key && !(Fl::e_state & FL_META) ) { +- // Don't send cmd-<key> to interpretKeyEvents because it beeps. ++ if (!no_text_key) { ++ // The simple keyboard model will ignore insertText, so we need to grab ++ // the symbol directly from the event. Note that we still use setMarkedText. ++ if (use_simple_keyboard) { ++ NSString *simple_chars; ++ UInt32 modifiers; ++ ++ // We want a "normal" symbol out of the event, which basically means ++ // we only respect the shift and alt/altgr modifiers. Cocoa can help ++ // us if we only wanted shift, but as we also want alt/altgr, we'll ++ // have to do some lookup ourselves. This matches our behaviour on ++ // other platforms. ++ ++ modifiers = 0; ++ if ([theEvent modifierFlags] & NSAlphaShiftKeyMask) ++ modifiers |= alphaLock; ++ if ([theEvent modifierFlags] & NSShiftKeyMask) ++ modifiers |= shiftKey; ++ if ([theEvent modifierFlags] & NSAlternateKeyMask) ++ modifiers |= optionKey; ++ ++ simple_chars = [FLView keyTranslate:[theEvent keyCode] ++ withModifierFlags:modifiers]; ++ if (simple_chars == nil) { ++ // Something went wrong. Fall back to what Cocoa gave us... ++ simple_chars = [theEvent charactersIgnoringModifiers]; ++ } ++ ++ [FLView prepareEtext:simple_chars]; ++ } ++ + // Then we can let the OS have a stab at it and see if it thinks it + // should result in some text +- NSText *edit = [[theEvent window] fieldEditor:YES forObject:nil]; +- in_key_event = true; +- [edit interpretKeyEvents:[NSArray arrayWithObject:theEvent]]; +- in_key_event = false; ++ ++ // Don't send cmd-<key> to interpretKeyEvents because it beeps. ++ if (!(Fl::e_state & FL_META)) { ++ NSText *edit = [[theEvent window] fieldEditor:YES forObject:nil]; ++ in_key_event = true; ++ [edit interpretKeyEvents:[NSArray arrayWithObject:theEvent]]; ++ in_key_event = false; ++ } + } + //NSLog(@"to text=%@ l=%d", [NSString stringWithUTF8String:Fl::e_text], Fl::e_length); + int handled = Fl::handle(FL_KEYDOWN, window); +@@ -1937,21 +2150,30 @@ + //NSLog(@"insertText: received=%@",received); + + if (!in_key_event) fl_lock_function(); ++ ++ // Simple keyboard widgets do not want these side channel inputs. ++ if (use_simple_keyboard) ++ goto end; ++ + [FLView prepareEtext:received]; ++ + // We can get called outside of key events (e.g. from the character +- // palette). Transform such actions to FL_PASTE events. ++ // palette). We need to fake our own key event at that point. + if (!in_key_event) { + Fl_Window *target = [(FLWindow*)[self window] getFl_Window]; +- Fl::handle(FL_PASTE, target); ++ Fl::e_keysym = Fl::e_original_keysym = 0; ++ Fl::handle(FL_KEYDOWN, target); + // for some reason, the window does not redraw until the next mouse move or button push + // sending a 'redraw()' or 'awake()' does not solve the issue! + Fl::flush(); + } ++ ++end: + if (!in_key_event) fl_unlock_function(); + } + + - (void)setMarkedText:(id)aString selectedRange:(NSRange)newSelection { +- NSString *received; ++ NSString *received, *current, *aggregate; + if (newSelection.location == 0) { + [self unmarkText]; + return; +@@ -1962,11 +2184,47 @@ + received = (NSString*)aString; + } + //NSLog(@"setMarkedText: %@ %d %d",received,newSelection.location,newSelection.length); ++ ++ fl_lock_function(); ++ ++ // Simple keyboard widgets generally do not want these side channel ++ // inputs, but we have no other way of getting dead keys so we make ++ // an exception in that case. ++ if (use_simple_keyboard) { ++ if (in_key_event && (Fl::e_length == 0)) { ++ [FLView prepareEtext:received]; ++ ++ Fl::e_text = (char*)cocoaDead2FLTK(Fl::e_text); ++ Fl::e_length = strlen(Fl::e_text); ++ } ++ goto end; ++ } ++ + // This code creates the OS X behaviour of seeing dead keys as things + // are being composed. ++ // ++ // Note: The concatenation thing is because of how OS X deals with ++ // invalid sequences. At that point it will spit out one call ++ // to insertText with the now aborted sequence, and one new ++ // call to setMarkedText with the new sequence. Since we want ++ // both to be visible, we need to concatenate. + next_compose_length = newSelection.location; +- [FLView prepareEtext:received]; +- //NSLog(@"Fl::e_text=%@ Fl::e_length=%d next_compose_length=%d", received, Fl::e_length, next_compose_length); ++ current = [NSString stringWithUTF8String:Fl::e_text]; ++ aggregate = [current stringByAppendingString:received]; ++ ++ [FLView prepareEtext:aggregate]; ++ //NSLog(@"Fl::e_text=%@ Fl::e_length=%d next_compose_length=%d", aggregate, Fl::e_length, next_compose_length); ++ ++ // We can get called outside of key events (e.g. from the character ++ // palette). We need to fake our own key event at that point. ++ if (!in_key_event) { ++ Fl_Window *target = [(FLWindow*)[self window] getFl_Window]; ++ Fl::e_keysym = Fl::e_original_keysym = 0; ++ Fl::handle(FL_KEYDOWN, target); ++ } ++ ++end: ++ fl_unlock_function(); + } + + - (void)unmarkText { |