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