blob: cf13aad74becb3471292666c116109a85b7de7fd [file] [log] [blame]
Pierre Ossman2f11bd92014-08-22 14:43:33 +02001diff -ur fltk-1.3.0r9619.org/configure.in fltk-1.3.0r9619/configure.in
2--- fltk-1.3.0r9619.org/configure.in 2012-04-22 04:45:09.000000000 +0200
3+++ fltk-1.3.0r9619/configure.in 2012-06-18 13:47:33.290447462 +0200
4@@ -865,6 +865,8 @@
5 Darwin*)
6 # MacOS X uses Cocoa for graphics.
7 LIBS="$LIBS -framework Cocoa"
8+ # And some Carbon for keyboard handling
9+ LIBS="$LIBS -framework Carbon"
10
11 if test x$have_pthread = xyes; then
12 AC_DEFINE(HAVE_PTHREAD)
13diff -ur fltk-1.3.0r9619.org/src/Fl_cocoa.mm fltk-1.3.0r9619/src/Fl_cocoa.mm
14--- fltk-1.3.0r9619.org/src/Fl_cocoa.mm 2012-06-16 10:49:52.000000000 +0200
15+++ fltk-1.3.0r9619/src/Fl_cocoa.mm 2012-06-18 13:47:42.944910782 +0200
16@@ -53,6 +53,7 @@
17 #include <math.h>
18
19 #import <Cocoa/Cocoa.h>
20+#import <Carbon/Carbon.h>
21
22 #ifndef NSINTEGER_DEFINED // appears with 10.5 in NSObjCRuntime.h
23 #if defined(__LP64__) && __LP64__
24@@ -114,6 +115,8 @@
25 extern Fl_Window* fl_xmousewin;
26 #endif
27
28+bool use_simple_keyboard = false;
29+
30 enum { FLTKTimerEvent = 1, FLTKDataReadyEvent };
31
32
33@@ -130,6 +133,39 @@
34 {
35 }
36
37+// Undocumented voodoo. Taken from Mozilla.
38+#define ENABLE_ROMAN_KYBDS_ONLY -23
39+
40+void fl_update_focus(void)
41+{
42+ Fl_Widget *focus;
43+
44+ focus = Fl::grab();
45+ if (!focus)
46+ focus = Fl::focus();
47+ if (!focus)
48+ return;
49+
50+ if (focus->simple_keyboard())
51+ use_simple_keyboard = true;
52+ else
53+ use_simple_keyboard = false;
54+
55+ // Force a "Roman" or "ASCII" keyboard, which both the Mozilla and
56+ // Safari people seem to think implies turning off advanced IME stuff
57+ // (see nsTSMManager::SyncKeyScript in Mozilla and enableSecureTextInput
58+ // in Safari/Webcore). Should be good enough for us then...
59+#if (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5)
60+ CFArrayRef inputSources = TISCreateASCIICapableInputSourceList();
61+ TSMSetDocumentProperty(TSMGetActiveDocument(),
62+ kTSMDocumentEnabledInputSourcesPropertyTag,
63+ sizeof(CFArrayRef), &inputSources);
64+ CFRelease(inputSources);
65+#else
66+ KeyScript(use_simple_keyboard ? ENABLE_ROMAN_KYBDS_ONLY : smKeyEnableKybds);
67+#endif
68+}
69+
70 /*
71 * Mac keyboard lookup table
72 */
73@@ -908,6 +944,25 @@
74 }
75 @end
76
77+static const char* cocoaDead2FLTK(const char *in)
78+{
79+ if (strcmp(in, "\140") == 0) // GRAVE ACCENT
80+ return "\314\200"; // COMBINING GRAVE ACCENT
81+ if (strcmp(in, "\302\264") == 0) // ACUTE ACCENT
82+ return "\314\201"; // COMBINING ACUTE ACCENT
83+ if (strcmp(in, "\136") == 0) // CIRCUMFLEX ACCENT
84+ return "\314\202"; // COMBINING CIRCUMFLEX ACCENT
85+ if (strcmp(in, "\176") == 0) // TILDE
86+ return "\314\203"; // COMBINING TILDE
87+ if (strcmp(in, "\302\250") == 0) // DIAERESIS
88+ return "\314\210"; // COMBINING DIAERESIS
89+ // FIXME: OS X dead key behaviour isn't documented and I don't have
90+ // any more keyboards to test with...
91+
92+ // hope that OS X gave us something proper to begin with
93+ return in;
94+}
95+
96 /*
97 Handle cocoa keyboard events
98 Events during a character composition sequence:
99@@ -1648,6 +1703,7 @@
100 - (void)rightMouseDragged:(NSEvent *)theEvent;
101 - (void)otherMouseDragged:(NSEvent *)theEvent;
102 - (void)scrollWheel:(NSEvent *)theEvent;
103++ (NSString *)keyTranslate:(UInt16)keyCode withModifierFlags:(UInt32)modifierFlags;
104 - (BOOL)handleKeyDown:(NSEvent *)theEvent;
105 - (void)keyDown:(NSEvent *)theEvent;
106 - (void)keyUp:(NSEvent *)theEvent;
107@@ -1726,6 +1782,130 @@
108 - (void)scrollWheel:(NSEvent *)theEvent {
109 cocoaMouseWheelHandler(theEvent);
110 }
111++ (NSString *)keyTranslate:(UInt16)keyCode withModifierFlags:(UInt32)modifierFlags {
112+ const UCKeyboardLayout *layout;
113+ OSStatus err;
114+
115+ layout = NULL;
116+
117+#if (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5)
118+ TISInputSourceRef keyboard;
119+ CFDataRef uchr;
120+
121+ keyboard = TISCopyCurrentKeyboardInputSource();
122+ uchr = (CFDataRef)TISGetInputSourceProperty(keyboard,
123+ kTISPropertyUnicodeKeyLayoutData);
124+ if (uchr == NULL)
125+ return nil;
126+
127+ layout = (const UCKeyboardLayout*)CFDataGetBytePtr(uchr);
128+#else
129+ KeyboardLayoutRef old_layout;
130+ int kind;
131+
132+ err = KLGetCurrentKeyboardLayout(&old_layout);
133+ if (err != noErr)
134+ return nil;
135+
136+ err = KLGetKeyboardLayoutProperty(old_layout, kKLKind,
137+ (const void**)&kind);
138+ if (err != noErr)
139+ return nil;
140+
141+ // Old, crufty layout format?
142+ if (kind == kKLKCHRKind) {
143+ void *kchr_layout;
144+
145+ UInt32 chars, state;
146+ char buf[3];
147+
148+ unichar result[16];
149+ ByteCount in_len, out_len;
150+
151+ err = KLGetKeyboardLayoutProperty(old_layout, kKLKCHRData,
152+ (const void**)&kchr_layout);
153+ if (err != noErr)
154+ return nil;
155+
156+ state = 0;
157+
158+ keyCode &= 0x7f;
159+ modifierFlags &= 0xff00;
160+
161+ chars = KeyTranslate(kchr_layout, keyCode | modifierFlags, &state);
162+
163+ buf[0] = (chars >> 16) & 0xff;
164+ buf[1] = chars & 0xff;
165+ buf[2] = '\0';
166+
167+ if (buf[0] == '\0') {
168+ buf[0] = buf[1];
169+ buf[1] = '\0';
170+ }
171+
172+ // The data is now in some layout specific encoding. Need to convert
173+ // this to unicode.
174+
175+ ScriptCode script;
176+ TextEncoding encoding;
177+ TECObjectRef converter;
178+
179+ script = (ScriptCode)GetScriptManagerVariable(smKeyScript);
180+
181+ err = UpgradeScriptInfoToTextEncoding(script, kTextLanguageDontCare,
182+ kTextRegionDontCare, NULL,
183+ &encoding);
184+ if (err != noErr)
185+ return nil;
186+
187+ err = TECCreateConverter(&converter, encoding, kTextEncodingUnicodeV4_0);
188+ if (err != noErr)
189+ return nil;
190+
191+ in_len = strlen(buf);
192+ out_len = sizeof(result);
193+
194+ err = TECConvertText(converter, (ConstTextPtr)buf, in_len, &in_len,
195+ (TextPtr)result, out_len, &out_len);
196+
197+ TECDisposeConverter(converter);
198+
199+ if (err != noErr)
200+ return nil;
201+
202+ return [NSString stringWithCharacters:result
203+ length:(out_len / sizeof(unichar))];
204+ }
205+
206+ if ((kind != kKLKCHRuchrKind) && (kind != kKLuchrKind))
207+ return nil;
208+
209+ err = KLGetKeyboardLayoutProperty(old_layout, kKLuchrData,
210+ (const void**)&layout);
211+ if (err != noErr)
212+ return nil;
213+#endif
214+
215+ if (layout == NULL)
216+ return nil;
217+
218+ UInt32 dead_state;
219+ UniCharCount max_len, actual_len;
220+ UniChar string[255];
221+
222+ dead_state = 0;
223+ max_len = sizeof(string)/sizeof(*string);
224+
225+ modifierFlags = (modifierFlags >> 8) & 0xff;
226+
227+ err = UCKeyTranslate(layout, keyCode, kUCKeyActionDown, modifierFlags,
228+ LMGetKbdType(), 0, &dead_state, max_len, &actual_len,
229+ string);
230+ if (err != noErr)
231+ return nil;
232+
233+ return [NSString stringWithCharacters:string length:actual_len];
234+}
235 - (BOOL)handleKeyDown:(NSEvent *)theEvent {
236 //NSLog(@"handleKeyDown");
237 fl_lock_function();
238@@ -1752,14 +1932,47 @@
239 break;
240 }
241 }
242- if (!no_text_key && !(Fl::e_state & FL_META) ) {
243- // Don't send cmd-<key> to interpretKeyEvents because it beeps.
244+ if (!no_text_key) {
245+ // The simple keyboard model will ignore insertText, so we need to grab
246+ // the symbol directly from the event. Note that we still use setMarkedText.
247+ if (use_simple_keyboard) {
248+ NSString *simple_chars;
249+ UInt32 modifiers;
250+
251+ // We want a "normal" symbol out of the event, which basically means
252+ // we only respect the shift and alt/altgr modifiers. Cocoa can help
253+ // us if we only wanted shift, but as we also want alt/altgr, we'll
254+ // have to do some lookup ourselves. This matches our behaviour on
255+ // other platforms.
256+
257+ modifiers = 0;
258+ if ([theEvent modifierFlags] & NSAlphaShiftKeyMask)
259+ modifiers |= alphaLock;
260+ if ([theEvent modifierFlags] & NSShiftKeyMask)
261+ modifiers |= shiftKey;
262+ if ([theEvent modifierFlags] & NSAlternateKeyMask)
263+ modifiers |= optionKey;
264+
265+ simple_chars = [FLView keyTranslate:[theEvent keyCode]
266+ withModifierFlags:modifiers];
267+ if (simple_chars == nil) {
268+ // Something went wrong. Fall back to what Cocoa gave us...
269+ simple_chars = [theEvent charactersIgnoringModifiers];
270+ }
271+
272+ [FLView prepareEtext:simple_chars];
273+ }
274+
275 // Then we can let the OS have a stab at it and see if it thinks it
276 // should result in some text
277- NSText *edit = [[theEvent window] fieldEditor:YES forObject:nil];
278- in_key_event = true;
279- [edit interpretKeyEvents:[NSArray arrayWithObject:theEvent]];
280- in_key_event = false;
281+
282+ // Don't send cmd-<key> to interpretKeyEvents because it beeps.
283+ if (!(Fl::e_state & FL_META)) {
284+ NSText *edit = [[theEvent window] fieldEditor:YES forObject:nil];
285+ in_key_event = true;
286+ [edit interpretKeyEvents:[NSArray arrayWithObject:theEvent]];
287+ in_key_event = false;
288+ }
289 }
290 //NSLog(@"to text=%@ l=%d", [NSString stringWithUTF8String:Fl::e_text], Fl::e_length);
291 int handled = Fl::handle(FL_KEYDOWN, window);
292@@ -1937,21 +2150,30 @@
293 //NSLog(@"insertText: received=%@",received);
294
295 if (!in_key_event) fl_lock_function();
296+
297+ // Simple keyboard widgets do not want these side channel inputs.
298+ if (use_simple_keyboard)
299+ goto end;
300+
301 [FLView prepareEtext:received];
302+
303 // We can get called outside of key events (e.g. from the character
304- // palette). Transform such actions to FL_PASTE events.
305+ // palette). We need to fake our own key event at that point.
306 if (!in_key_event) {
307 Fl_Window *target = [(FLWindow*)[self window] getFl_Window];
308- Fl::handle(FL_PASTE, target);
309+ Fl::e_keysym = Fl::e_original_keysym = 0;
310+ Fl::handle(FL_KEYDOWN, target);
311 // for some reason, the window does not redraw until the next mouse move or button push
312 // sending a 'redraw()' or 'awake()' does not solve the issue!
313 Fl::flush();
314 }
315+
316+end:
317 if (!in_key_event) fl_unlock_function();
318 }
319
320 - (void)setMarkedText:(id)aString selectedRange:(NSRange)newSelection {
321- NSString *received;
322+ NSString *received, *current, *aggregate;
323 if (newSelection.location == 0) {
324 [self unmarkText];
325 return;
326@@ -1962,11 +2184,47 @@
327 received = (NSString*)aString;
328 }
329 //NSLog(@"setMarkedText: %@ %d %d",received,newSelection.location,newSelection.length);
330+
331+ fl_lock_function();
332+
333+ // Simple keyboard widgets generally do not want these side channel
334+ // inputs, but we have no other way of getting dead keys so we make
335+ // an exception in that case.
336+ if (use_simple_keyboard) {
337+ if (in_key_event && (Fl::e_length == 0)) {
338+ [FLView prepareEtext:received];
339+
340+ Fl::e_text = (char*)cocoaDead2FLTK(Fl::e_text);
341+ Fl::e_length = strlen(Fl::e_text);
342+ }
343+ goto end;
344+ }
345+
346 // This code creates the OS X behaviour of seeing dead keys as things
347 // are being composed.
348+ //
349+ // Note: The concatenation thing is because of how OS X deals with
350+ // invalid sequences. At that point it will spit out one call
351+ // to insertText with the now aborted sequence, and one new
352+ // call to setMarkedText with the new sequence. Since we want
353+ // both to be visible, we need to concatenate.
354 next_compose_length = newSelection.location;
355- [FLView prepareEtext:received];
356- //NSLog(@"Fl::e_text=%@ Fl::e_length=%d next_compose_length=%d", received, Fl::e_length, next_compose_length);
357+ current = [NSString stringWithUTF8String:Fl::e_text];
358+ aggregate = [current stringByAppendingString:received];
359+
360+ [FLView prepareEtext:aggregate];
361+ //NSLog(@"Fl::e_text=%@ Fl::e_length=%d next_compose_length=%d", aggregate, Fl::e_length, next_compose_length);
362+
363+ // We can get called outside of key events (e.g. from the character
364+ // palette). We need to fake our own key event at that point.
365+ if (!in_key_event) {
366+ Fl_Window *target = [(FLWindow*)[self window] getFl_Window];
367+ Fl::e_keysym = Fl::e_original_keysym = 0;
368+ Fl::handle(FL_KEYDOWN, target);
369+ }
370+
371+end:
372+ fl_unlock_function();
373 }
374
375 - (void)unmarkText {