Commit d38e1fdf authored by DailyShana's avatar DailyShana

add char input event for i18n

only tested on win32 platform, probably not work on others
parent 3fb9852c
......@@ -34,6 +34,9 @@ namespace irr
IrrlichtDevice::postEventFromUser. They take the same path as mouse events. */
EET_KEY_INPUT_EVENT,
//! A character input event.
EET_CHAR_INPUT_EVENT,
//! A joystick (joypad, gamepad) input event.
/** Joystick events are created by polling all connected joysticks once per
device run() and then passing the events to IrrlichtDevice::postEventFromUser.
......@@ -315,9 +318,6 @@ struct SEvent
//! Any kind of keyboard event.
struct SKeyInput
{
//! Character corresponding to the key (0, if not a character)
wchar_t Char;
//! Key which has been pressed or released
EKEY_CODE Key;
......@@ -331,6 +331,12 @@ struct SEvent
bool Control:1;
};
//! Character input event
struct SCharInput
{
wchar_t Char;
};
//! A joystick event.
/** Unlike other events, joystick events represent the result of polling
* each connected joystick once per run() of the device. Joystick events will
......@@ -417,6 +423,7 @@ struct SEvent
struct SGUIEvent GUIEvent;
struct SMouseInput MouseInput;
struct SKeyInput KeyInput;
struct SCharInput CharInput;
struct SJoystickEvent JoystickEvent;
struct SLogEvent LogEvent;
struct SUserEvent UserEvent;
......
......@@ -240,6 +240,9 @@ bool CGUIEditBox::OnEvent(const SEvent& event)
if (processKey(event))
return true;
break;
case EET_CHAR_INPUT_EVENT:
inputChar(event.CharInput.Char);
return true;
case EET_MOUSE_INPUT_EVENT:
if (processMouse(event))
return true;
......@@ -266,13 +269,6 @@ bool CGUIEditBox::processKey(const SEvent& event)
if (event.KeyInput.Control)
{
// german backlash '\' entered with control + '?'
if ( event.KeyInput.Char == '\\' )
{
inputChar(event.KeyInput.Char);
return true;
}
switch(event.KeyInput.Key)
{
case KEY_KEY_A:
......@@ -686,7 +682,6 @@ bool CGUIEditBox::processKey(const SEvent& event)
return false;
default:
inputChar(event.KeyInput.Char);
return true;
}
......
......@@ -394,6 +394,7 @@ bool CGUIEnvironment::OnEvent(const SEvent& event)
if (UserReceiver
&& (event.EventType != EET_MOUSE_INPUT_EVENT)
&& (event.EventType != EET_KEY_INPUT_EVENT)
&& (event.EventType != EET_CHAR_INPUT_EVENT)
&& (event.EventType != EET_GUI_EVENT || event.GUIEvent.Caller != this))
{
ret = UserReceiver->OnEvent(event);
......@@ -599,6 +600,12 @@ bool CGUIEnvironment::postEventFromUser(const SEvent& event)
}
break;
case EET_CHAR_INPUT_EVENT:
{
if (Focus && Focus->OnEvent(event))
return true;
}
break;
default:
break;
} // end switch
......
......@@ -303,7 +303,10 @@ bool CGUIListBox::OnEvent(const SEvent& event)
}
return true;
}
else if (event.KeyInput.PressedDown && event.KeyInput.Char)
break;
case EET_CHAR_INPUT_EVENT:
if (event.CharInput.Char)
{
// change selection based on text as it is typed.
u32 now = os::Timer::getTime();
......@@ -311,16 +314,16 @@ bool CGUIListBox::OnEvent(const SEvent& event)
if (now - LastKeyTime < 500)
{
// add to key buffer if it isn't a key repeat
if (!(KeyBuffer.size() == 1 && KeyBuffer[0] == event.KeyInput.Char))
if (!(KeyBuffer.size() == 1 && KeyBuffer[0] == event.CharInput.Char))
{
KeyBuffer += L" ";
KeyBuffer[KeyBuffer.size()-1] = event.KeyInput.Char;
KeyBuffer[KeyBuffer.size()-1] = event.CharInput.Char;
}
}
else
{
KeyBuffer = L" ";
KeyBuffer[0] = event.KeyInput.Char;
KeyBuffer[0] = event.CharInput.Char;
}
LastKeyTime = now;
......
......@@ -231,7 +231,10 @@ bool CIrrDeviceConsole::run()
e.KeyInput.Control = (in.Event.KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) != 0;
e.KeyInput.Shift = (in.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED) != 0;
e.KeyInput.Key = EKEY_CODE(in.Event.KeyEvent.wVirtualKeyCode);
e.KeyInput.Char = in.Event.KeyEvent.uChar.UnicodeChar;
postEventFromUser(e);
e.EventType = EET_CHAR_INPUT_EVENT;
e.CharInput.Char = in.Event.KeyEvent.uChar.UnicodeChar;
postEventFromUser(e);
break;
}
......
......@@ -1042,10 +1042,12 @@ bool CIrrDeviceLinux::run()
char buf[8]={0};
XLookupString(&event.xkey, buf, sizeof(buf), &mp.X11Key, NULL);
irrevent.EventType = irr::EET_CHAR_INPUT_EVENT;
irrevent.CharInput.Char = irr::core::stringw(buf).c_str();
postEventFromUser(irrevent);
irrevent.EventType = irr::EET_KEY_INPUT_EVENT;
irrevent.KeyInput.PressedDown = (event.type == KeyPress);
// mbtowc(&irrevent.KeyInput.Char, buf, sizeof(buf));
irrevent.KeyInput.Char = ((wchar_t*)(buf))[0];
irrevent.KeyInput.Control = (event.xkey.state & ControlMask) != 0;
irrevent.KeyInput.Shift = (event.xkey.state & ShiftMask) != 0;
......
......@@ -409,7 +409,6 @@ bool CIrrDeviceSDL::run()
}
#endif
irrevent.EventType = irr::EET_KEY_INPUT_EVENT;
irrevent.KeyInput.Char = SDL_event.key.keysym.unicode;
irrevent.KeyInput.Key = key;
irrevent.KeyInput.PressedDown = (SDL_event.type == SDL_KEYDOWN);
irrevent.KeyInput.Shift = (SDL_event.key.keysym.mod & KMOD_SHIFT) != 0;
......@@ -418,6 +417,14 @@ bool CIrrDeviceSDL::run()
}
break;
case SDL_TEXTINPUT:
{
irrevent.EventType = irr::EET_CHAR_INPUT_EVENT;
irrevent.CharInput.Char = irr::core::stringw(SDL_event.text).c_str();
postEventFromUser(irrevent);
}
break;
case SDL_QUIT:
Close = true;
break;
......
......@@ -20,6 +20,8 @@
#include "COSOperator.h"
#include "dimension2d.h"
#include "IGUISpriteBank.h"
#include "IGUIEnvironment.h"
#include "IGUIElement.h"
#include <winuser.h>
#if defined(_IRR_COMPILE_WITH_JOYSTICK_EVENTS_)
#ifdef _IRR_COMPILE_WITH_DIRECTINPUT_JOYSTICK_
......@@ -28,6 +30,7 @@
#ifdef _MSC_VER
#pragma comment(lib, "dinput8.lib")
#pragma comment(lib, "dxguid.lib")
#pragma comment(lib, "imm32.lib")
#endif
#else
#ifdef _MSC_VER
......@@ -749,6 +752,26 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
return 0;
}
{
dev = getDeviceFromHWnd(hWnd);
if (dev)
{
irr::gui::IGUIElement* ele = dev->getGUIEnvironment() ? dev->getGUIEnvironment()->getFocus() : 0;
if (!ele || (ele->getType() != irr::gui::EGUIET_EDIT_BOX) || !ele->isEnabled())
{
HIMC hIMC = ImmGetContext(hWnd);
if (hIMC)
{
ImmNotifyIME(hIMC, NI_COMPOSITIONSTR, CPS_COMPLETE, 0);
ImmReleaseContext(hWnd, hIMC);
}
ImmAssociateContextEx(hWnd, NULL, 0);
}
else
ImmAssociateContextEx(hWnd, NULL, IACE_DEFAULT);
}
}
switch (message)
{
case WM_PAINT:
......@@ -762,6 +785,18 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
case WM_ERASEBKGND:
return 0;
case WM_CHAR:
{
if (wParam < 32 || (wParam > 126 && wParam < 160))
return 0;
event.EventType = irr::EET_CHAR_INPUT_EVENT;
event.CharInput.Char = (wchar_t)wParam;
dev = getDeviceFromHWnd(hWnd);
if (dev)
dev->postEventFromUser(event);
return 0;
}
case WM_SYSKEYDOWN:
case WM_SYSKEYUP:
case WM_KEYDOWN:
......@@ -773,22 +808,20 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
event.KeyInput.Key = (irr::EKEY_CODE)wParam;
event.KeyInput.PressedDown = (message==WM_KEYDOWN || message == WM_SYSKEYDOWN);
const UINT MY_MAPVK_VSC_TO_VK_EX = 3; // MAPVK_VSC_TO_VK_EX should be in SDK according to MSDN, but isn't in mine.
if ( event.KeyInput.Key == irr::KEY_SHIFT )
{
// this will fail on systems before windows NT/2000/XP, not sure _what_ will return there instead.
event.KeyInput.Key = (irr::EKEY_CODE)MapVirtualKey( ((lParam>>16) & 255), MY_MAPVK_VSC_TO_VK_EX );
event.KeyInput.Key = (irr::EKEY_CODE)MapVirtualKey( ((lParam>>16) & 255), MAPVK_VSC_TO_VK_EX );
}
if ( event.KeyInput.Key == irr::KEY_CONTROL )
{
event.KeyInput.Key = (irr::EKEY_CODE)MapVirtualKey( ((lParam>>16) & 255), MY_MAPVK_VSC_TO_VK_EX );
event.KeyInput.Key = (irr::EKEY_CODE)MapVirtualKey( ((lParam>>16) & 255), MAPVK_VSC_TO_VK_EX );
// some keyboards will just return LEFT for both - left and right keys. So also check extend bit.
if (lParam & 0x1000000)
event.KeyInput.Key = irr::KEY_RCONTROL;
}
if ( event.KeyInput.Key == irr::KEY_MENU )
{
event.KeyInput.Key = (irr::EKEY_CODE)MapVirtualKey( ((lParam>>16) & 255), MY_MAPVK_VSC_TO_VK_EX );
event.KeyInput.Key = (irr::EKEY_CODE)MapVirtualKey( ((lParam>>16) & 255), MAPVK_VSC_TO_VK_EX );
if (lParam & 0x1000000)
event.KeyInput.Key = irr::KEY_RMENU;
}
......@@ -798,26 +831,6 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
event.KeyInput.Shift = ((allKeys[VK_SHIFT] & 0x80)!=0);
event.KeyInput.Control = ((allKeys[VK_CONTROL] & 0x80)!=0);
// Handle unicode and deadkeys in a way that works since Windows 95 and nt4.0
// Using ToUnicode instead would be shorter, but would to my knowledge not run on 95 and 98.
WORD keyChars[2];
UINT scanCode = HIWORD(lParam);
int conversionResult = ToAsciiEx(wParam,scanCode,allKeys,keyChars,0,KEYBOARD_INPUT_HKL);
if (conversionResult == 1)
{
WORD unicodeChar;
MultiByteToWideChar(
KEYBOARD_INPUT_CODEPAGE,
MB_PRECOMPOSED, // default
(LPCSTR)keyChars,
sizeof(keyChars),
(WCHAR*)&unicodeChar,
1 );
event.KeyInput.Char = unicodeChar;
}
else
event.KeyInput.Char = 0;
// allow composing characters like '@' with Alt Gr on non-US keyboards
if ((allKeys[VK_MENU] & 0x80) != 0)
event.KeyInput.Control = 0;
......@@ -826,10 +839,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
if (dev)
dev->postEventFromUser(event);
if (message == WM_SYSKEYDOWN || message == WM_SYSKEYUP)
return DefWindowProc(hWnd, message, wParam, lParam);
else
return 0;
break;
}
case WM_SIZE:
......@@ -904,6 +914,20 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
KEYBOARD_INPUT_HKL = GetKeyboardLayout(0);
KEYBOARD_INPUT_CODEPAGE = LocaleIdToCodepage( LOWORD(KEYBOARD_INPUT_HKL) );
return 0;
case WM_IME_STARTCOMPOSITION:
{
dev = getDeviceFromHWnd(hWnd);
irr::gui::IGUIElement* ele = dev->getGUIEnvironment()->getFocus();
if (!ele)
break;
irr::core::position2di pos = ele->getAbsolutePosition().UpperLeftCorner;
HIMC hIMC = ImmGetContext(hWnd);
COMPOSITIONFORM CompForm = { CFS_POINT, { pos.X, pos.Y + ele->getAbsolutePosition().getHeight() } };
ImmSetCompositionWindow(hIMC, &CompForm);
ImmReleaseContext(hWnd, hIMC);
}
break;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
......@@ -1797,8 +1821,7 @@ void CIrrDeviceWin32::handleSystemMessages()
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
// No message translation because we don't use WM_CHAR and it would conflict with our
// deadkey handling.
TranslateMessage(&msg);
if (ExternalWindow && msg.hwnd == HWnd)
WndProc(HWnd, msg.message, msg.wParam, msg.lParam);
......
......@@ -305,7 +305,6 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
*/
// event.KeyInput.Shift = ((allKeys[VK_SHIFT] & 0x80)!=0);
// event.KeyInput.Control = ((allKeys[VK_CONTROL] & 0x80)!=0);
// event.KeyInput.Char = (KeyAsc & 0x00ff); //KeyAsc >= 0 ? KeyAsc : 0;
if (dev)
dev->postEventFromUser(event);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment