keyboard input

Zini

28-10-2007 18:04:52

I am having some trouble with handling of keyboard input. The key event args only contain information about the key pressed, but not about the modifiers (shift, ctrl, ...). Let's say I am interested in Ctrl-Left. How I am supposed to tell the difference between the left cursor key with ctrl down and the left cursor key without ctrl down?

Unless I am overlooking something, the key event system is lacking some functionality here.

btw. I know I was against auto-repeat for key input in QuickGUI. But now we already have auto-repeat for mouse input (scrollbars and such). Looks a bit inconsistent to me. Maybe the key-auto-repeat feature should be added after all.

mr.Zog

28-10-2007 19:01:17

I don't know if this helps you, but we solved a similar problem we had with our player control- function through "bitmasks"

so you basicall rebuild your bitmask evertime a key is pressed or released and then check it with somthing like

if( ( bitmask & KP_PRESSED_CTRL ) == KP_PRESSED_CTRL )
..then you know ctrl is pressed ;)


and the KP_ enum could look like

enum KEY_PRESSED //name might be taken?
{
KP_PRESSED_CTRL = 0x0001,
KP_PRESSED_SHIFT = 0x0002
etc.
}

Zini

28-10-2007 19:05:32

Yes, but that would need to be implemented inside QuickGUI. Can't be done before injecting input into QuickGUI and it can't be done in QuickGUI's event handlers.

Edit: Might be possible outside QuickGUI. But I still think it would be better placed inside QuickGUI.

kungfoomasta

28-10-2007 23:46:14

Haven't run into this area of development yet, I'm not sure if it is something QGUI should be handling. You can always do this outside of QGUI using event handlers, and querying the OIS keyboard if a current key is pressed.


myWidget->addEventHandler(EVENT_KEY_PRESSED,&myClass::myFunction,this);
...
void myClass::myFunction(const EventArgs& args)
{
const KeyEventArgs& kea = dynamic_cast<const EventArgs&>(args);
if( kea.scancode == OIS::KC_LEFT )
{
// unsure if "isKeyDown" is the proper function name..
if( mInputManager->getKeyboard->isKeyDown(OIS::KC_CTRL) )
{
...
}
else
{
...
}
}
}


The only thing I can think of to accomplish this in QGUI is:
- Maintain a list of what keys are currently injected as pressed down, and allow easy querying of this. (this isn't bad, but redundant.. OIS does all this for you)

Regarding the auto key repeat, I should probably add this in at some point, I agree.

Zini

28-10-2007 23:53:38

I think the code you have given won't work. The key events are buffered. isKeyDown is not buffered. So, if the user presses ctrl-left and the handling of the left key is delayed after the user has released ctrl, it will only produce a simple left without ctrl.

I am not sure any more either, if QuickGUI should handle it entirely. But at least it should take an additional modifier bit-mask for keyboard input injection, which is then passed through with the key event args.

kungfoomasta

29-10-2007 00:14:00

would bit masking be as simple as this?

unsigned int systemKeys;

I haven't done anything along bit masking and useage.

What I could do is something like GUIManager::mSystemKeys, and manage it through "injectKeyDown" and "injectKeyUp". And incorporate it into the KeyEventArgs, to remove the need to query the state from GUIManager.

mr.Zog

29-10-2007 07:20:19

...Can't be done before injecting input into QuickGUI and it can't be done in QuickGUI's event handlers.
...


I think the main question is: what functionality do you want when pressing CTRL + L for example.

The thing I can think of is, to open some sort of context window.
So basically you don't need to inject a Key.

in pseudo code:

IF ctrl key pressed:
{
if L key pressed:
{
show window
}
}

ELSE:
{
QuickGUI::injectKey
}



My understanding of injectKey: for user text input. (like entering a name or password - but maybe I am wrong here ;) )

Zini

29-10-2007 08:48:27

would bit masking be as simple as this?

unsigned int systemKeys;

I haven't done anything along bit masking and useage.


Yes, an unsigned int would do, though I wouldn't call it systemKeys, Maybe modifier or modifierKeys.


What I could do is something like GUIManager::mSystemKeys, and manage it through "injectKeyDown" and "injectKeyUp". And incorporate it into the KeyEventArgs, to remove the need to query the state from GUIManager.


That is what I had in mind. Maybe you could even do without theGUIManager::mSystemKeys, since you are already passing it to the handler with the KeyEventArgs.

Zini

29-10-2007 08:53:53



My understanding of injectKey: for user text input. (like entering a name or password - but maybe I am wrong here ;) )


Not necessary. Currently I am handling the non-window related input outside of QuickGUI (that includes things like opening and closing windows).

But you might want to have other keyboard-shortcuts in a window (let's say a RPG style inventory, that can be navigated with the cursor keys or think of selecting a specific inventory category depending on the key pressed). .

mr.Zog

29-10-2007 08:56:09


But you might want to have other keyboard-shortcuts in a window (let's say a RPG style inventory, that can be navigated with the cursor keys or think of selecting a specific inventory category depending on the key pressed). .


Thats a good point!
(haven't thought that far ;) )

Zini

29-10-2007 16:03:06

Just noticed that I can't use the numeric keypad when entering text into a TextBox. Looks like we have another problem here.

kungfoomasta

29-10-2007 16:06:40

Ok, I'll try to add this in tonight. :)

mModifierKeys sounds more appropriate, thanks for the suggestion.

Maybe you could even do without theGUIManager::mSystemKeys, since you are already passing it to the handler with the KeyEventArgs.

That thought occurred to me, but it won't work properly.

*Injected pressing Ctrl* - modifierKeys set, storing that ctrl is pressed down, and the event is fired.
*Injected pressing Left* - modifierKeys left at default, and event is fired.

The modifier keys state has to persist outside the injections.

Just noticed that I can't use the numeric keypad when entering text into a TextBox. Looks like we have another problem here.

I'll look into it.

kungfoomasta

29-10-2007 16:12:15

What Keys should be included in the set of modifier keys? Anything other than Ctrl/Alt/Shift?

Zini

29-10-2007 16:14:05

Ctrl/Alt/Shift sounds right.

kungfoomasta

11-11-2007 19:31:25

I have this implemented now, committed in revision 258.

unsigned int GUIManager::mKeyModifiers

KeyEventArgs and MouseEventArgs have the following public member:

unsigned int keyModifiers

enum


//! Enum of bit position of modifer
enum KeyModifier
{
SHIFT = 0x0000001,
CTRL = 0x0000010,
ALT = 0x0000100
};


And keyModifier detection is as simple as:


if( keyModifier & QuickGUI::SHIFT )
...


And also

bool GUIManager::isKeyModifierDown(KeyModifier k);

All of this code was taken from OIS (and then minorly tweaked), so major thanks to pjcast. :D