You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

03-str2599-fltk-1.3.x-keyboard-osx.patch 12KB

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