openframeworks / openFrameworks

openFrameworks is a community-developed cross platform toolkit for creative coding in C++.
http://openframeworks.cc
Other
9.97k stars 2.55k forks source link

of*Window/ofEvents: pressedKeys accumulate in special cases #652

Open bakercp opened 13 years ago

bakercp commented 13 years ago

In some cases, when modifier keys are used, the pressedKeys set will accumulate keys.

This happens because "modifier-up" messages are not sent in the same way as normal and special keys.

To test, watch the size of the pressedKeys:

cout << pressedKeys.size() << " num pressed keys " << endl;

Press a modifier key and a normal key -- say ctrl-a. If the 'a' is lifted first, then the modified-a key int is removed from the pressedKeys set. If CTRL is released before the 'a', then the non-modified-a key-up int is sent, and it is not erased from the pressedKeys set. If this is repeated with different modifier+key downs / ups the accumulation occurs.

Ultimately, there needs to be better handling of modifier keys. Perhaps there is a way to use the modifier masks keep track of modifier keys with a call to glutGetModifiers() in the keyboard_cb and keyboard_up_cb static methods?

It looks like progress has been made toward this in ofConstants.h

#define OF_KEY_CTRL         0x0200
#define OF_KEY_ALT          0x0300
#define OF_KEY_SHIFT        0x0400

But it seems to have stopped there.

I'm happy to work on this -- any suggestions on a strategy? Perhaps this is already being addressed of 007?

bakercp commented 13 years ago

Perhaps this is obvious, but this issue ultimately stems from the fact that GLUT does not deliver stand-alone modifier keyup/keydown events like Java (or other windowing systems), making it difficult to keep track of such things ...

Here is an interesting post on the topic. http://old.nabble.com/Status-of-modifier-keys-%28shift-ctrl-alt%29-td6982098.html

bilderbuchi commented 12 years ago

is this being addressed by https://github.com/openframeworks/openFrameworks/pull/807 ?

bakercp commented 12 years ago

Hi bilderbuchi -- yes that modification is on the right track, but it probably won't work as expected because glutGetModifiers() wants to be called in the keyboard_cb and keyboard_up_cb methods (at least from my testing on OSX). It will dump lots of warnings that look something like:

1/7/12 12:18:17.273 PM BasicExampleDebug: GLUT Warning: glutCurrentModifiers: do not call outside core input callback.

gameoverhack's 807 pull request would be a very useful set of methods, but instead of calling the calling glutGetModifiers() it should probably work by checking "pressedKeys" set with a call that looks like:

ofGetKeyPressed(OF_KEY_CTRL);

etc.

Thus, for this to really work, there needs to be better modifier bookkeeping at the core site of the original glut callback.

As I said, I'm quite interested in getting this working and am happy to tackle it. Do you know if there are any other forks addressing the issue?

-- just copied some of these thoughts over to #807

bilderbuchi commented 12 years ago

I'm not aware of other work on that, but if gameoverhack's PR addresses at least part of the issue, I think it's best to comment there on how the PR/code could be improved. Then all the work on this kind of issue is kept in one place. PR's are there to be discussed, so don't be shy. ;-) I will drop a link to this issue there, in any case.

bakercp commented 12 years ago

I spent quite a while on this one and am beginning to wonder if it is possible to accurately keep track of keys via the pressedKeys set strategy. Ultimately the problem lies in the fact that GLUT is only delivering ascii coded values via it's keyboard callbacks. For any given physical key, these singular ascii values can be changed by modifier keys (like ctrl), meaning that in some situations (as described above ctrl+a, then release ctrl, then release a), keeping a simple list of ascii coded values will lead to unpredictable results -- basically all keyDowns are not guaranteed to have a matching keyUp. The ideal ways to keep track of pressedKeys is to have a keyEvent system that records keyboard activity based on physical keyCodes -- or at least some sense of VirtualKeys (i.e. VK_LEFT, etc). Examples include Java's KeyEvent system or a Javascript strategy like this. If we had input events at this level, it would also easily take care of issue here #807. In the mean-time, you can check out my proposed solution to keymodifier issue over at issue #807. At least it is possible to have a robust solution to that problem.

kylemcdonald commented 9 years ago

closing this issue since GLUT is not our primary windowing system anymore.

bakercp commented 9 years ago

This is still an issue w/ GLFW

bakercp commented 9 years ago

Just tested this again.

Keep an eye on the pressedKeys set.

cout << pressedKeys.size() << " num pressed keys " << endl;

Press CTRL-a.

Then lift the CTRL and keep a held.

then release a.

Then you'll still have a key in the pressed keys set.

To free it again,

Press CTRL-a

then release a, then release CTRL.

kylemcdonald commented 9 years ago

thanks for catching this @bakercp. there are some things that have changed so much since the issues were reported that most of them are irrelevant -- but here i can see why it's still a problem.

bakercp commented 9 years ago

I'm watching your whirlwind issue cleanup session with great appreciation :)

dimitre commented 7 years ago

Out of curiosity: is this a persistent issue on ofw master? I've been using only 0.9.8 Thank you

oxillo commented 4 years ago

Hi,

We are trying to clean out the many issues that we have. Many versions of OF have been released since this was issued.

Can you help us by checking if this issue is still present in the latest version ?

In case of inactivity, we'll close this issue by end of january, 2020.

Thanks

bakercp commented 4 years ago

This is still an issue. Can reproduce with the same instructions above.

bakercp commented 4 years ago

To reproduce:

ofApp:update()
{
    bool is1Pressed = ofGetKeyPressed(1);
    bool isCtrlPressed = ofGetKeyPressed(OF_KEY_CONTROL);
    bool isAPressed = ofGetKeyPressed('a');
    std::cout << is1Pressed << ", " << isCtrlPressed << ", " << isAPressed << std::endl;
}

Then ...

Press CTRL + a.

Then lift the CTRL and keep a held.

then release a.

Then you'll still have a key pressed.

To free it again,

Press CTRL + a

then release a, then release CTRL.

dimitre commented 4 years ago

I've finally understood the situation I've got OF_KEY_COMMAND pressed even when not pressed. in macOs I switch programs by using command + tab. if I come back to my software using command + tab it still thinks the key is pressed even after release. don't know if it helps but it now seems reproducible here. PS: one funny thing : I use command to overwrite my presets so lots of accidents here :)