Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sokol_app.h : allow the user to query a robust keyboard / mouse button state #785

Open
Toctave opened this issue Feb 7, 2023 · 4 comments

Comments

@Toctave
Copy link

Toctave commented Feb 7, 2023

Hi,

For now, the only way (that I know of) to check whether a particular key or mouse button is being pressed is to manage an application-side flag that will change on up/down events. This isn't robust : e.g. with the X11 backend, if a keydown -> window defocus -> keyup -> window focus sequence happens, the key will appear to stay down.

A more robust approach would be to allow for e.g. a bool sapp_is_key_down(sapp_keycode key) function, which would be implemented using e.g. XQueryKeymap for X11. Or, even simpler, just allow the user to query a whole sapp_keyboard_state struct with a bitmask of all pressed keys.

In case some backends only provide event-based input, this API could be implemented using up/down events, while handling edge cases as well as possible without letting the user re-implement it.

@floooh
Copy link
Owner

floooh commented Feb 9, 2023

It's a good idea but I think that would be tricky to implement on other platforms that don't offer such a polling feature.

I usually implemented a 'polling layer' outside of sokol_app.h, by maintaining such a bitmap of pressed key by listening for KEY_DOWN and KEY_UP events, and clearing the entire bitmap when the window becomes UNFOCUSED or ICONIFIED.

Mouse buttons are a bit special since somewhat recently in that they are reported as modifiers in most events (in addition to Shift, Ctrl, Alt and Super):

sokol/sokol_app.h

Lines 1349 to 1361 in dc6814b

/*
These are currently pressed modifier keys (and mouse buttons) which are
passed in the event struct field sapp_event.modifiers.
*/
enum {
SAPP_MODIFIER_SHIFT = 0x1, // left or right shift key
SAPP_MODIFIER_CTRL = 0x2, // left or right control key
SAPP_MODIFIER_ALT = 0x4, // left or right alt key
SAPP_MODIFIER_SUPER = 0x8, // left or right 'super' key
SAPP_MODIFIER_LMB = 0x100, // left mouse button
SAPP_MODIFIER_RMB = 0x200, // right mouse button
SAPP_MODIFIER_MMB = 0x400, // middle mouse button
};

PS: what I do have in mind for quite some time is a separate sokol header which provides such a polling layer on top of the sokol-app evented input, probably with integrated gamepad support.

@Toctave
Copy link
Author

Toctave commented Feb 9, 2023

What I was thinking of was to implement it natively on the platforms where it's possible, and to do what you suggest on the others, while providing the same API.

Thinking about it some more, I'm not sure it's such a great idea because it'll increase the surface for platform discrepancies.

Why should the polling layer be its own header though ? Since it depends only on sokol-app, it might as well be part of it I think. If you want to make it optional it could be hidden behind an ifdef.

I'm likely going to implement something of the sort very soon, should I add a pull request when I do ?

@floooh
Copy link
Owner

floooh commented Feb 10, 2023

Why should the polling layer be its own header though ?

Because of feature-creep in sokol_app.h, which is already a bit of a problem (e.g. sokol_app.h requires by far the most maintenance work of all sokol headers because it's a grab bag of window-system related stuff).

It's easier to maintain optional features in separate libs, unless the new feature absolutely needs to access private details of another library (which isn't required in this case because the polling layer would just listen to the regular events).

@Toctave
Copy link
Author

Toctave commented Feb 11, 2023

Fair enough. I'm not sure how having two separate headers that must be kept in sync improves the maintenance situation, but I don't mind it either.

I've implemented a very basic polling layer here, let me know what you think.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants