summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authormichi_cc <michi_cc@openttd.org>2013-08-05 20:36:20 +0000
committermichi_cc <michi_cc@openttd.org>2013-08-05 20:36:20 +0000
commit923eb009e8e3dafb224747e443fb366e76ec6b84 (patch)
treea2127a419e27327c3ef5ccc98e0717ef237829d1 /src
parent8b476de3bfa2864b51435e7fb4988e1550cf1d3a (diff)
downloadopenttd-923eb009e8e3dafb224747e443fb366e76ec6b84.tar.xz
(svn r25667) -Fix: [Win32] Only forward key presses to the IME system if an edit box has the input focus.
Diffstat (limited to 'src')
-rw-r--r--src/video/win32_v.cpp68
-rw-r--r--src/window.cpp2
-rw-r--r--src/window_func.h2
3 files changed, 57 insertions, 15 deletions
diff --git a/src/video/win32_v.cpp b/src/video/win32_v.cpp
index 922f8ba89..814fdc4b9 100644
--- a/src/video/win32_v.cpp
+++ b/src/video/win32_v.cpp
@@ -21,9 +21,15 @@
#include "../texteff.hpp"
#include "../thread/thread.h"
#include "../progress.h"
+#include "../window_func.h"
#include "win32_v.h"
#include <windows.h>
+/* Missing define in MinGW headers. */
+#ifndef MAPVK_VK_TO_CHAR
+#define MAPVK_VK_TO_CHAR (2)
+#endif
+
static struct {
HWND main_wnd;
HBITMAP dib_sect;
@@ -432,6 +438,20 @@ static void PaintWindowThread(void *)
_draw_thread->Exit();
}
+/** Forward key presses to the window system. */
+static LRESULT HandleCharMsg(uint keycode, uint charcode)
+{
+#if !defined(UNICODE)
+ wchar_t w;
+ int len = MultiByteToWideChar(_codepage, 0, (char*)&charcode, 1, &w, 1);
+ charcode = len == 1 ? w : 0;
+#endif /* UNICODE */
+
+ HandleKeypress(GB(charcode, 0, 16) | (keycode << 16));
+
+ return 0;
+}
+
static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static uint32 keycode = 0;
@@ -592,31 +612,50 @@ static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP
return 0;
}
-#if !defined(UNICODE)
- wchar_t w;
- int len = MultiByteToWideChar(_codepage, 0, (char*)&charcode, 1, &w, 1);
- charcode = len == 1 ? w : 0;
-#endif /* UNICODE */
+ /* IMEs and other input methods sometimes send a WM_CHAR without a WM_KEYDOWN,
+ * clear the keycode so a previous WM_KEYDOWN doesn't become 'stuck'. */
+ uint cur_keycode = keycode;
+ keycode = 0;
- /* No matter the keyboard layout, we will map the '~' to the console */
- scancode = scancode == 41 ? (int)WKC_BACKQUOTE : keycode;
- HandleKeypress(GB(charcode, 0, 16) | (scancode << 16));
- return 0;
+ return HandleCharMsg(cur_keycode, charcode);
}
case WM_KEYDOWN: {
- keycode = MapWindowsKey(wParam);
+ /* No matter the keyboard layout, we will map the '~' to the console. */
+ uint scancode = GB(lParam, 16, 8);
+ keycode = scancode == 41 ? WKC_BACKQUOTE : MapWindowsKey(wParam);
/* Silently drop all messages handled by WM_CHAR. */
MSG msg;
if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
- if (msg.message == WM_CHAR && GB(lParam, 16, 8) == GB(msg.lParam, 16, 8)) {
+ if ((msg.message == WM_CHAR || msg.message == WM_DEADCHAR) && GB(lParam, 16, 8) == GB(msg.lParam, 16, 8)) {
return 0;
}
}
- HandleKeypress(0 | (keycode << 16));
- return 0;
+ uint charcode = MapVirtualKey(wParam, MAPVK_VK_TO_CHAR);
+
+ /* No character translation? */
+ if (charcode == 0) {
+ HandleKeypress(0 | (keycode << 16));
+ return 0;
+ }
+
+ /* Is the console key a dead key? If yes, ignore the first key down event. */
+ if (HasBit(charcode, 31) && !console) {
+ if (scancode == 41) {
+ console = true;
+ return 0;
+ }
+ }
+ console = false;
+
+ /* IMEs and other input methods sometimes send a WM_CHAR without a WM_KEYDOWN,
+ * clear the keycode so a previous WM_KEYDOWN doesn't become 'stuck'. */
+ uint cur_keycode = keycode;
+ keycode = 0;
+
+ return HandleCharMsg(cur_keycode, LOWORD(charcode));
}
case WM_SYSKEYDOWN: // user presses F10 or Alt, both activating the title-menu
@@ -979,7 +1018,8 @@ void VideoDriver_Win32::MainLoop()
while (PeekMessage(&mesg, NULL, 0, 0, PM_REMOVE)) {
InteractiveRandom(); // randomness
- TranslateMessage(&mesg);
+ /* Convert key messages to char messages if we want text input. */
+ if (EditBoxInGlobalFocus()) TranslateMessage(&mesg);
DispatchMessage(&mesg);
}
if (_exit_game) return;
diff --git a/src/window.cpp b/src/window.cpp
index 9e64087b0..d3d9baadd 100644
--- a/src/window.cpp
+++ b/src/window.cpp
@@ -350,7 +350,7 @@ void SetFocusedWindow(Window *w)
* has a edit box as focused widget, or if a console is focused.
* @return returns true if an edit box is in global focus or if the focused window is a console, else false
*/
-static bool EditBoxInGlobalFocus()
+bool EditBoxInGlobalFocus()
{
if (_focused_window == NULL) return false;
diff --git a/src/window_func.h b/src/window_func.h
index 704885b9a..ee494592b 100644
--- a/src/window_func.h
+++ b/src/window_func.h
@@ -52,4 +52,6 @@ void SetWindowClassesDirty(WindowClass cls);
void DeleteWindowById(WindowClass cls, WindowNumber number, bool force = true);
void DeleteWindowByClass(WindowClass cls);
+bool EditBoxInGlobalFocus();
+
#endif /* WINDOW_FUNC_H */