summaryrefslogtreecommitdiffstats
path: root/contrib/fltk/03-str2599-fltk-1.3.x-keyboard-osx.patch
diff options
context:
space:
mode:
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.patch375
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 {