1
0
Fork 0

(svn r25667) -Fix: [Win32] Only forward key presses to the IME system if an edit box has the input focus.

release/1.4
michi_cc 2013-08-05 20:36:20 +00:00
parent 8b476de3bf
commit 923eb009e8
3 changed files with 57 additions and 15 deletions

View File

@ -21,9 +21,15 @@
#include "../texteff.hpp" #include "../texteff.hpp"
#include "../thread/thread.h" #include "../thread/thread.h"
#include "../progress.h" #include "../progress.h"
#include "../window_func.h"
#include "win32_v.h" #include "win32_v.h"
#include <windows.h> #include <windows.h>
/* Missing define in MinGW headers. */
#ifndef MAPVK_VK_TO_CHAR
#define MAPVK_VK_TO_CHAR (2)
#endif
static struct { static struct {
HWND main_wnd; HWND main_wnd;
HBITMAP dib_sect; HBITMAP dib_sect;
@ -432,6 +438,20 @@ static void PaintWindowThread(void *)
_draw_thread->Exit(); _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 LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{ {
static uint32 keycode = 0; static uint32 keycode = 0;
@ -592,31 +612,50 @@ static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP
return 0; return 0;
} }
#if !defined(UNICODE) /* IMEs and other input methods sometimes send a WM_CHAR without a WM_KEYDOWN,
wchar_t w; * clear the keycode so a previous WM_KEYDOWN doesn't become 'stuck'. */
int len = MultiByteToWideChar(_codepage, 0, (char*)&charcode, 1, &w, 1); uint cur_keycode = keycode;
charcode = len == 1 ? w : 0; keycode = 0;
#endif /* UNICODE */
/* No matter the keyboard layout, we will map the '~' to the console */ return HandleCharMsg(cur_keycode, charcode);
scancode = scancode == 41 ? (int)WKC_BACKQUOTE : keycode;
HandleKeypress(GB(charcode, 0, 16) | (scancode << 16));
return 0;
} }
case WM_KEYDOWN: { 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. */ /* Silently drop all messages handled by WM_CHAR. */
MSG msg; MSG msg;
if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) { 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; return 0;
} }
} }
HandleKeypress(0 | (keycode << 16)); uint charcode = MapVirtualKey(wParam, MAPVK_VK_TO_CHAR);
return 0;
/* 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 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)) { while (PeekMessage(&mesg, NULL, 0, 0, PM_REMOVE)) {
InteractiveRandom(); // randomness InteractiveRandom(); // randomness
TranslateMessage(&mesg); /* Convert key messages to char messages if we want text input. */
if (EditBoxInGlobalFocus()) TranslateMessage(&mesg);
DispatchMessage(&mesg); DispatchMessage(&mesg);
} }
if (_exit_game) return; if (_exit_game) return;

View File

@ -350,7 +350,7 @@ void SetFocusedWindow(Window *w)
* has a edit box as focused widget, or if a console is focused. * 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 * @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; if (_focused_window == NULL) return false;

View File

@ -52,4 +52,6 @@ void SetWindowClassesDirty(WindowClass cls);
void DeleteWindowById(WindowClass cls, WindowNumber number, bool force = true); void DeleteWindowById(WindowClass cls, WindowNumber number, bool force = true);
void DeleteWindowByClass(WindowClass cls); void DeleteWindowByClass(WindowClass cls);
bool EditBoxInGlobalFocus();
#endif /* WINDOW_FUNC_H */ #endif /* WINDOW_FUNC_H */