In the trunk irr::KEY_LSHIFT & irr::KEY_RSHIFT are now being sent for WM_KEYDOWN events. But it's still sending irr::KEY_SHIFT for a corresponding WM_KEYUP.
Before offering a patch, I can think of two ways to fix this:
1. Track shift key state between key events in the device class.
2. Add low level keyboard hookproc and post shift key events from there.
And while I'm in there - add in code for differentiating between left/right ctrl & alt keys.
Which would be preferred? Can anyone think of a better method?
[bug] win32 shift key events
After playing with this a bit more, it turns out:
1. Tracking state between events still won't be able to differentiate between left/right shift WM_KEYUP...
2. It appears SetWindowsHookEx isn't available on WinCE and for non WinCE it would require using a low-level hook (WH_KEYBOARD_LL) to get at the extended keys. Seems messy to me.
I was able to get up/down left/right shift key detection working by using:
In the CIrrDeviceWin32 constructor:
and in the WndProc:
Unfortunately this same logic won't work for the Ctrl & Alt/Menu keys because on the keyboards I tested, both the left/right virtual keys returned the same scan codes. However, this code that tests the extended key bit does appear to work:
1. Tracking state between events still won't be able to differentiate between left/right shift WM_KEYUP...
2. It appears SetWindowsHookEx isn't available on WinCE and for non WinCE it would require using a low-level hook (WH_KEYBOARD_LL) to get at the extended keys. Seems messy to me.
I was able to get up/down left/right shift key detection working by using:
In the CIrrDeviceWin32 constructor:
Code: Select all
// get scan code for virtual right shift keys.
// RShiftC statically defined (u32) in CIrrDeviceWin32.cpp
RShiftSC = MapVirtualKey(VK_RSHIFT, MAPVK_VK_TO_VSC);
Code: Select all
if (event.KeyInput.Key==irr::KEY_SHIFT)
{
u32 scan_code = (lParam & 0xFF0000) >> 16;
if (scan_code == RShiftSC)
event.KeyInput.Key=irr::KEY_RSHIFT;
else
event.KeyInput.Key=irr::KEY_LSHIFT;
}
Code: Select all
else if(event.KeyInput.Key == irr::KEY_CONTROL)
{
// extended key?
if (lParam & 0x1000000)
event.KeyInput.Key=irr::KEY_RCONTROL;
else
event.KeyInput.Key=irr::KEY_LCONTROL;
}
else if(event.KeyInput.Key == irr::KEY_MENU)
{
if (lParam & 0x1000000)
event.KeyInput.Key=irr::KEY_RMENU;
else
event.KeyInput.Key=irr::KEY_LMENU;
}
@pc0de: Thanks a lot. I spend on that whole morning, but didn't have the idea of checking that extended key bit. I've checked in now to trunk for svn release 1.6.
Though I have still one problem to which I found no solution so far. When both shift-keys are pressed until repeat starts then it seems I don't get the first up-event. It's simply missing.
Some test-code in case anyone wants to try (does a little more stuff for mouse-testing, but I'm too lazy now to remove that stuff):
Though I have still one problem to which I found no solution so far. When both shift-keys are pressed until repeat starts then it seems I don't get the first up-event. It's simply missing.
Some test-code in case anyone wants to try (does a little more stuff for mouse-testing, but I'm too lazy now to remove that stuff):
Code: Select all
#include <irrlicht.h>
#include <iostream>
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
#ifdef _IRR_WINDOWS_
#pragma comment(lib, "Irrlicht.lib")
#endif
struct SAppContext
{
IrrlichtDevice * device;
irr::gui::IGUIStaticText * info;
irr::gui::IGUIListBox * keyEvents;
};
void PrintMouseState(const SEvent& event, IrrlichtDevice * device, irr::core::stringw &result)
{
gui::ICursorControl * cursor = device->getCursorControl();
core::position2d<f32> relPos = cursor->getRelativePosition();
result += stringw(L"rel. X: ");
result += stringw(relPos.X);
result += stringw(L"\n");
result += stringw(L"rel. Y: ");
result += stringw(relPos.Y);
result += stringw(L"\n");
result += stringw(L"X: ");
result += stringw(event.MouseInput.X);
result += stringw(L"\n");
result += stringw(L": ");
result += stringw(event.MouseInput.Y);
result += stringw(L"\n");
result += stringw(L"Wheel: ");
result += stringw(event.MouseInput.Wheel);
result += stringw(L"\n");
result += stringw(L"Shift: ");
if ( event.MouseInput.Shift )
result += stringw(L"true\n");
else
result += stringw(L"false\n");
result += stringw(L"Control: ");
if ( event.MouseInput.Control )
result += stringw(L"true\n");
else
result += stringw(L"false\n");
result += stringw(L"ButtonStates: ");
result += stringw(event.MouseInput.ButtonStates);
result += stringw(L"\n");
result += stringw(L"isLeftPressed: ");
if ( event.MouseInput.isLeftPressed() )
result += stringw(L"true\n");
else
result += stringw(L"false\n");
result += stringw(L"isRightPressed: ");
if ( event.MouseInput.isRightPressed() )
result += stringw(L"true\n");
else
result += stringw(L"false\n");
result += stringw(L"isMiddlePressed: ");
if ( event.MouseInput.isMiddlePressed() )
result += stringw(L"true\n");
else
result += stringw(L"false\n");
result += stringw(L"Event: ");
switch ( event.MouseInput.Event )
{
case EMIE_LMOUSE_PRESSED_DOWN: result += stringw(L"EMIE_LMOUSE_PRESSED_DOWN\n"); break;
case EMIE_RMOUSE_PRESSED_DOWN: result += stringw(L"EMIE_RMOUSE_PRESSED_DOWN\n"); break;
case EMIE_MMOUSE_PRESSED_DOWN: result += stringw(L"EMIE_MMOUSE_PRESSED_DOWN\n"); break;
case EMIE_LMOUSE_LEFT_UP: result += stringw(L"EMIE_LMOUSE_LEFT_UP\n"); break;
case EMIE_RMOUSE_LEFT_UP: result += stringw(L"EMIE_RMOUSE_LEFT_UP\n"); break;
case EMIE_MMOUSE_LEFT_UP: result += stringw(L"EMIE_MMOUSE_LEFT_UP\n"); break;
case EMIE_MOUSE_MOVED: result += stringw(L"EMIE_MOUSE_MOVED\n"); break;
case EMIE_MOUSE_WHEEL: result += stringw(L"EMIE_MOUSE_WHEEL\n"); break;
}
result += stringw(L"\n");
}
class MyEventReceiver : public IEventReceiver
{
public:
MyEventReceiver(SAppContext & context) : Context(context) { }
virtual bool OnEvent(const SEvent& event)
{
if (event.EventType == EET_MOUSE_INPUT_EVENT)
{
irr::core::stringw infoText;
PrintMouseState(event, Context.device, infoText);
Context.info->setText(infoText.c_str());
}
else if ( event.EventType == EET_KEY_INPUT_EVENT )
{
irr::core::stringw wstr( event.KeyInput.PressedDown ? L"DOWN" : L"UP");
wstr += L" Key: ";
wstr += irr::core::stringw(event.KeyInput.Key);
Context.keyEvents->setSelected( Context.keyEvents->addItem( wstr.c_str() ) );
}
return false;
}
private:
SAppContext & Context;
};
int main()
{
video::E_DRIVER_TYPE driverType = video::EDT_OPENGL;
IrrlichtDevice * device = createDevice(driverType, core::dimension2d<u32>(800, 600), 16, false);
if (device == 0)
return 1; // could not create selected driver.
device->setResizable(true);
video::IVideoDriver* driver = device->getVideoDriver();
IGUIEnvironment* env = device->getGUIEnvironment();
SAppContext context;
context.device = device;
core::rect< s32 > rectInfo(10,10, 200, 400);
context.info = env->addStaticText (L"", rectInfo, true, true);
context.keyEvents = env->addListBox( core::rect<s32>( 210, 10, 410, 400 ) );
context.keyEvents->setAutoScrollEnabled(true);
MyEventReceiver receiver(context);
device->setEventReceiver(&receiver);
while(device->run() && driver)
{
if (device->isWindowActive())
{
static int triggerMousePos = 0;
if ( !(++triggerMousePos % 100) )
{
gui::ICursorControl * cursor = device->getCursorControl();
// core::position2d<s32> relPos2 = cursor->getPosition();
// cursor->setPosition(relPos2);
core::position2d<f32> relPos = cursor->getRelativePosition();
cursor->setPosition(relPos);
}
driver->beginScene(true, true, SColor(0,200,200,200));
env->drawAll();
driver->endScene();
}
}
device->drop();
return 0;
}
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
After wrestling with that for a couple of hours I wasn't able to find a solution either. SDL & CS also appear to have the same problem. Even Spy++ fails to report the WM_KEYUP when they are both held down and one of the keys is released.CuteAlien wrote:Though I have still one problem...
Fwiw I also tried RegisterHotKey(..., VK_LSHIFT) (returned success) but it didn't send any WM_HOTKEY messages.
For accuracy, I guess someone needs to make good on their DirectInput promise...
* edit *
Looks like RawInput/Message Loop is favored over DirectInput? :
Yes, sounds like that bug. Irrlicht 1.6.1. will be released soon (I hope still this year) and it's fixed in there.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm