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.

fltk-1_v4.3.x-keyboard-win32.patch 8.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. diff -ur fltk-1.3.0r9293.org/src/Fl_win32.cxx fltk-1.3.0r9293/src/Fl_win32.cxx
  2. --- fltk-1.3.0r9293.org/src/Fl_win32.cxx 2012-06-18 09:07:56.522314557 +0200
  3. +++ fltk-1.3.0r9293/src/Fl_win32.cxx 2012-06-18 09:08:07.392836285 +0200
  4. @@ -87,6 +87,8 @@
  5. static Fl_Display_Device fl_gdi_display(&fl_gdi_driver);
  6. Fl_Display_Device *Fl_Display_Device::_display = &fl_gdi_display; // the platform display
  7. +bool use_simple_keyboard = false;
  8. +
  9. // dynamic wsock dll handling api:
  10. #if defined(__CYGWIN__) && !defined(SOCKET)
  11. # define SOCKET int
  12. @@ -120,6 +122,8 @@
  13. * size and link dependencies.
  14. */
  15. static HMODULE s_imm_module = 0;
  16. +typedef BOOL (WINAPI* flTypeImmAssociateContextEx)(HWND, HIMC, DWORD);
  17. +static flTypeImmAssociateContextEx flImmAssociateContextEx = 0;
  18. typedef HIMC (WINAPI* flTypeImmGetContext)(HWND);
  19. static flTypeImmGetContext flImmGetContext = 0;
  20. typedef BOOL (WINAPI* flTypeImmSetCompositionWindow)(HIMC, LPCOMPOSITIONFORM);
  21. @@ -135,6 +139,7 @@
  22. if (!s_imm_module)
  23. Fl::fatal("FLTK Lib Error: IMM32.DLL file not found!\n\n"
  24. "Please check your input method manager library accessibility.");
  25. + flImmAssociateContextEx = (flTypeImmAssociateContextEx)GetProcAddress(s_imm_module, "ImmAssociateContextEx");
  26. flImmGetContext = (flTypeImmGetContext)GetProcAddress(s_imm_module, "ImmGetContext");
  27. flImmSetCompositionWindow = (flTypeImmSetCompositionWindow)GetProcAddress(s_imm_module, "ImmSetCompositionWindow");
  28. flImmReleaseContext = (flTypeImmReleaseContext)GetProcAddress(s_imm_module, "ImmReleaseContext");
  29. @@ -413,7 +418,12 @@
  30. }
  31. }
  32. - TranslateMessage(&fl_msg);
  33. + // Don't bother with key to character translation as we do
  34. + // it manually for simpley keyboard widgets. In fact, calling
  35. + // TranslateMessage() just makes it more difficult as it sets
  36. + // a bunch of internal state.
  37. + if (!use_simple_keyboard)
  38. + TranslateMessage(&fl_msg);
  39. DispatchMessageW(&fl_msg);
  40. have_message = PeekMessageW(&fl_msg, NULL, 0, 0, PM_REMOVE);
  41. }
  42. @@ -638,6 +648,49 @@
  43. }
  44. }
  45. +void fl_update_focus(void)
  46. +{
  47. + Fl_Widget *focus;
  48. + Fl_Window *win;
  49. +
  50. + get_imm_module();
  51. +
  52. + focus = Fl::grab();
  53. + if (!focus)
  54. + focus = Fl::focus();
  55. + if (!focus)
  56. + return;
  57. +
  58. + // Grabs are special in that events are sent to the first
  59. + // available window
  60. + if (focus == Fl::grab())
  61. + win = Fl::first_window();
  62. + else {
  63. + win = focus->as_window();
  64. + if (!win)
  65. + win = focus->window();
  66. + }
  67. +
  68. + if (!win) {
  69. + Fl::warning("Cannot find window for widget receiving focus");
  70. + return;
  71. + }
  72. +
  73. + // No Win32 window created yet
  74. + if (!Fl_X::i(win) || !fl_xid(win))
  75. + return;
  76. +
  77. + if (focus->simple_keyboard()) {
  78. + use_simple_keyboard = true;
  79. + if (flImmGetContext(fl_xid(win)) != 0)
  80. + flImmAssociateContextEx(fl_xid(win), 0, 0);
  81. + } else {
  82. + use_simple_keyboard = false;
  83. + if (flImmGetContext(fl_xid(win)) == 0)
  84. + flImmAssociateContextEx(fl_xid(win), 0, IACE_DEFAULT);
  85. + }
  86. +}
  87. +
  88. HWND fl_capture;
  89. static int mouse_event(Fl_Window *window, int what, int button,
  90. @@ -785,6 +838,27 @@
  91. return extended ? extendedlut[vk] : vklut[vk];
  92. }
  93. +static xchar msdead2fltk(xchar in)
  94. +{
  95. + switch (in) {
  96. + case 0x0060: // GRAVE ACCENT
  97. + return 0x0300; // COMBINING GRAVE ACCENT
  98. + case 0x00b4: // ACUTE ACCENT
  99. + return 0x0301; // COMBINING ACUTE ACCENT
  100. + case 0x005e: // CIRCUMFLEX ACCENT
  101. + return 0x0302; // COMBINING CIRCUMFLEX ACCENT
  102. + case 0x007e: // TILDE
  103. + return 0x0303; // COMBINING TILDE
  104. + case 0x00a8: // DIAERESIS
  105. + return 0x0308; // COMBINING DIAERESIS
  106. + // FIXME: Windows dead key behaviour isn't documented and I don't have
  107. + // any more keyboards to test with...
  108. + }
  109. +
  110. + // hope that Windows gave us something proper to begin with
  111. + return in;
  112. +}
  113. +
  114. #if USE_COLORMAP
  115. extern HPALETTE fl_select_palette(void); // in fl_color_win32.cxx
  116. #endif
  117. @@ -846,6 +920,8 @@
  118. //fl_msg.pt = ???
  119. //fl_msg.lPrivate = ???
  120. + MSG fl_orig_msg = fl_msg;
  121. +
  122. Fl_Window *window = fl_find(hWnd);
  123. if (window) switch (uMsg) {
  124. @@ -1025,23 +1101,82 @@
  125. if (GetKeyState(VK_SCROLL)) state |= FL_SCROLL_LOCK;
  126. Fl::e_state = state;
  127. static char buffer[1024];
  128. - if (uMsg == WM_CHAR || uMsg == WM_SYSCHAR) {
  129. + if (use_simple_keyboard) {
  130. + BYTE keystate[256];
  131. + WCHAR wbuf[8];
  132. + int ret;
  133. +
  134. + // I'm not sure if we ever get WM_CHAR (& friends) without an initial
  135. + // WM_KEYDOWN (& friends), but if we do then we should not send such
  136. + // side band events to simple keyboard widgets.
  137. + if ((fl_orig_msg.message != WM_KEYDOWN) &&
  138. + (fl_orig_msg.message != WM_SYSKEYDOWN) &&
  139. + (fl_orig_msg.message != WM_KEYUP) &&
  140. + (fl_orig_msg.message != WM_SYSKEYUP))
  141. + break;
  142. +
  143. + GetKeyboardState(keystate);
  144. +
  145. + // Pressing Ctrl wreaks havoc with the symbol lookup, so turn that off.
  146. + // But AltGr shows up as Ctrl+Alt in Windows, so keep Ctrl if Alt is
  147. + // active.
  148. + if (!(keystate[VK_MENU] & 0x80))
  149. + keystate[VK_CONTROL] = keystate[VK_LCONTROL] = keystate[VK_RCONTROL] = 0;
  150. +
  151. + // We cannot inspect or modify Windows' internal state of the keyboard
  152. + // so we have to try to infer information from ToUnicode() and wedge
  153. + // things into a known state.
  154. + for (int i = 0;i < 2;i++) {
  155. + ret = ToUnicode(fl_orig_msg.wParam, 0, keystate, wbuf,
  156. + sizeof(wbuf)/sizeof(wbuf[0]), 0);
  157. +
  158. + // No symbol for this key (or unexpected length)
  159. + if ((ret == 0) || (ret < -1)) {
  160. + buffer[0] = 0;
  161. + Fl::e_length = 0;
  162. + break;
  163. + }
  164. +
  165. + // A dead key. Convert this to a Unicode combining character so
  166. + // that the application can tell the difference between dead and
  167. + // normal keys.
  168. + if (ret == -1) {
  169. + xchar u = (xchar) msdead2fltk(wbuf[0]);
  170. + Fl::e_length = fl_utf8fromwc(buffer, 1024, &u, 1);
  171. + buffer[Fl::e_length] = 0;
  172. + break;
  173. + }
  174. +
  175. + // If we have two characters (or more) from ToUnicode(), that's
  176. + // an invalid sequence. One character chould mean a proper symbol,
  177. + // or it could mean a composed one. In both cases we need to call
  178. + // ToUnicode() again to get something sane.
  179. + if (i == 0)
  180. + continue;
  181. +
  182. + // We should now have something sane. Give whatever we have to the
  183. + // application.
  184. + Fl::e_length = fl_utf8fromwc(buffer, 1024, wbuf, ret);
  185. + buffer[Fl::e_length] = 0;
  186. + }
  187. + } else if (uMsg == WM_CHAR || uMsg == WM_SYSCHAR) {
  188. xchar u = (xchar) wParam;
  189. // Fl::e_length = fl_unicode2utf(&u, 1, buffer);
  190. Fl::e_length = fl_utf8fromwc(buffer, 1024, &u, 1);
  191. buffer[Fl::e_length] = 0;
  192. + } else {
  193. + buffer[0] = 0;
  194. + Fl::e_length = 0;
  195. + }
  196. -
  197. - } else if (Fl::e_keysym >= FL_KP && Fl::e_keysym <= FL_KP_Last) {
  198. - if (state & FL_NUM_LOCK) {
  199. - // Convert to regular keypress...
  200. - buffer[0] = Fl::e_keysym-FL_KP;
  201. - Fl::e_length = 1;
  202. - } else {
  203. - // Convert to special keypress...
  204. - buffer[0] = 0;
  205. - Fl::e_length = 0;
  206. + // The keypad area is a bit odd in that we need to change the keysym
  207. + // to properly indicate what the user meant, unlike other keys where
  208. + // we normally change the text and keep keysym stable.
  209. + if (Fl::e_keysym >= FL_KP && Fl::e_keysym <= FL_KP_Last) {
  210. + // The initial mapping tables give us a keysym that corresponds to
  211. + // numlock being on, so we only do something when it is off.
  212. + if (!(state & FL_NUM_LOCK)) {
  213. switch (Fl::e_keysym) {
  214. case FL_KP + '0' :
  215. Fl::e_keysym = FL_Insert;
  216. @@ -1073,30 +1208,10 @@
  217. case FL_KP + '.' :
  218. Fl::e_keysym = FL_Delete;
  219. break;
  220. - case FL_KP + '/' :
  221. - case FL_KP + '*' :
  222. - case FL_KP + '-' :
  223. - case FL_KP + '+' :
  224. - buffer[0] = Fl::e_keysym-FL_KP;
  225. - Fl::e_length = 1;
  226. - break;
  227. }
  228. }
  229. - } else if ((lParam & (1<<31))==0) {
  230. -#ifdef FLTK_PREVIEW_DEAD_KEYS
  231. - if ((lParam & (1<<24))==0) { // clear if dead key (always?)
  232. - xchar u = (xchar) wParam;
  233. - Fl::e_length = fl_utf8fromwc(buffer, 1024, &u, 1);
  234. - buffer[Fl::e_length] = 0;
  235. - } else { // set if "extended key" (never printable?)
  236. - buffer[0] = 0;
  237. - Fl::e_length = 0;
  238. - }
  239. -#else
  240. - buffer[0] = 0;
  241. - Fl::e_length = 0;
  242. -#endif
  243. }
  244. +
  245. Fl::e_text = buffer;
  246. if (lParam & (1<<31)) { // key up events.
  247. if (Fl::handle(FL_KEYUP, window)) return 0;