diff options
| author | Andre Weissflog <floooh@gmail.com> | 2024-01-27 15:30:43 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-01-27 15:30:43 +0100 |
| commit | 8cb249868012765ce57b151e12b02163bb5ce2b0 (patch) | |
| tree | 2a989750e3b236caf543d3e896efdb3323ff97e1 | |
| parent | f58a78539e6a972700579ee72cb3f2d66f07088f (diff) | |
| parent | a716d7e30cdf6cfe0f75f5aa0163653676127bdd (diff) | |
Merge pull request #975 from floooh/issue972-event-bubble-control
sokol_app.h emsc: optional event bubbling
| -rw-r--r-- | CHANGELOG.md | 18 | ||||
| -rw-r--r-- | README.md | 2 | ||||
| -rw-r--r-- | sokol_app.h | 157 |
3 files changed, 84 insertions, 93 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index e260de9e..cac643df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,22 @@ ## Updates -#### 23-Jan-2034 +#### 27-Jan-2024 + +- sokol_app.h web: The HTML5 event bubbling changes introduced in the 02-Jan-2024 + update have been reverted because they introduced some undesired side effects. + By default, most input events now *don't* bubble up (which restores the + old behaviour), but it's now possible to enable bubbling for categories + of input events (mouse, touch, wheel, keys and chars) during sokol-app setup. + It's then possible to control bubbling of individual events by calling + `sapp_consume_event()` from within the sokol-app event callback. + + See issue https://github.com/floooh/sokol/issues/972 for details and + PR https://github.com/floooh/sokol/pull/975 for the actual changes. + + Also check out the new doc section `INPUT EVENT BUBBLING ON THE WEB PLATFORM` + in the sokol_app.h header documentation block. + +#### 23-Jan-2024 - sokol_app.h android: Touch event coordinates are now using AMotionEvent_getX/Y() instead of AMotionEvent_getRawX/Y(). The raw functions don't work well in multi-window @@ -4,7 +4,7 @@ Simple [STB-style](https://github.com/nothings/stb/blob/master/docs/stb_howto.txt) cross-platform libraries for C and C++, written in C. -[**See what's new**](https://github.com/floooh/sokol/blob/master/CHANGELOG.md) (**06-Jan-2024**: some new size computation helper functions in sokol_gfx.h) +[**See what's new**](https://github.com/floooh/sokol/blob/master/CHANGELOG.md) (**27-Jan-2024**: restored old event bubbling behaviour in sokol_app.h html5) [](/../../actions/workflows/main.yml) [](/../../actions/workflows/gen_bindings.yml) [](https://github.com/floooh/sokol-zig/actions/workflows/main.yml) [](https://github.com/floooh/sokol-nim/actions/workflows/main.yml) [](https://github.com/floooh/sokol-odin/actions/workflows/main.yml)[](https://github.com/floooh/sokol-rust/actions/workflows/main.yml) diff --git a/sokol_app.h b/sokol_app.h index 884a2eaa..70c928e6 100644 --- a/sokol_app.h +++ b/sokol_app.h @@ -941,13 +941,46 @@ sapp_show_keyboard(false); - Note that on the web platform, the keyboard can only be shown from - inside an input handler. On such platforms, sapp_show_keyboard() - will only work as expected when it is called from inside the - sokol-app event callback function. When called from other places, - an internal flag will be set, and the onscreen keyboard will be - called at the next 'legal' opportunity (when the next input event - is handled). + Note that onscreen keyboard functionality is no longer supported + on the browser platform (the previous hacks and workarounds to make browser + keyboards work for on web applications that don't use HTML UIs + never really worked across browsers). + + INPUT EVENT BUBBLING ON THE WEB PLATFORM + ======================================== + By default, input event bubbling on the web platform is configured in + a way that makes the most sense for 'full-canvas' apps that cover the + entire browser client window area: + + - mouse, touch and wheel events do not bubble up, this prevents various + ugly side events, like: + - HTML text overlays being selected on double- or triple-click into + the canvas + - 'scroll bumping' even when the canvas covers the entire client area + - key_up/down events for 'character keys' *do* bubble up (otherwise + the browser will not generate UNICODE character events) + - all other key events *do not* bubble up by default (this prevents side effects + like F1 opening help, or F7 starting 'caret browsing') + - character events do no bubble up (although I haven't noticed any side effects + otherwise) + + Event bubbling can be enabled for input event categories during initialization + in the sapp_desc struct: + + sapp_desc sokol_main(int argc, char* argv[]) { + return (sapp_desc){ + //... + .html5_bubble_mouse_events = true, + .html5_bubble_touch_events = true, + .html5_bubble_wheel_events = true, + .html5_bubble_key_events = true, + .html5_bubble_char_events = true, + }; + } + + This basically opens the floodgates lets *all* input events bubble up to the browser. + To prevent individual events from bubbling, call sapp_consume_event() from within + the sokol_app.h event callback. OPTIONAL: DON'T HIJACK main() (#define SOKOL_NO_ENTRY) ====================================================== @@ -1101,10 +1134,7 @@ TEMP NOTE DUMP ============== - - onscreen keyboard support on Android requires Java :(, should we even bother? - sapp_desc needs a bool whether to initialize depth-stencil surface - - GL context initialization needs more control (at least what GL version to initialize) - - application icon - the Android implementation calls cleanup_cb() and destroys the egl context in onDestroy at the latest but should do it earlier, in onStop, as an app is "killable" after onStop on Android Honeycomb and later (it can't be done at the moment as the app may be started @@ -1676,6 +1706,11 @@ typedef struct sapp_desc { bool html5_preserve_drawing_buffer; // HTML5 only: whether to preserve default framebuffer content between frames bool html5_premultiplied_alpha; // HTML5 only: whether the rendered pixels use premultiplied alpha convention bool html5_ask_leave_site; // initial state of the internal html5_ask_leave_site flag (see sapp_html5_ask_leave_site()) + bool html5_bubble_mouse_events; // if true, mouse events will bubble up to the web page + bool html5_bubble_touch_events; // same for touch events + bool html5_bubble_wheel_events; // same for wheel events + bool html5_bubble_key_events; // if true, bubble up *all* key events to browser, not just key events that represent characters + bool html5_bubble_char_events; // if true, bubble up character events to browser bool ios_keyboard_resizes_canvas; // if true, showing the iOS keyboard shrinks the canvas } sapp_desc; @@ -5115,7 +5150,7 @@ _SOKOL_PRIVATE EM_BOOL _sapp_emsc_size_changed(int event_type, const EmscriptenU _SOKOL_PRIVATE EM_BOOL _sapp_emsc_mouse_cb(int emsc_type, const EmscriptenMouseEvent* emsc_event, void* user_data) { _SOKOL_UNUSED(user_data); - bool consume_event = false; + bool consume_event = !_sapp.desc.html5_bubble_mouse_events; _sapp.emsc.mouse_buttons = emsc_event->buttons; if (_sapp.mouse.locked) { _sapp.mouse.dx = (float) emsc_event->movementX; @@ -5176,7 +5211,7 @@ _SOKOL_PRIVATE EM_BOOL _sapp_emsc_mouse_cb(int emsc_type, const EmscriptenMouseE } else { _sapp.event.mouse_button = SAPP_MOUSEBUTTON_INVALID; } - consume_event = _sapp_call_event(&_sapp.event); + consume_event |= _sapp_call_event(&_sapp.event); } // mouse lock can only be activated in mouse button events (not in move, enter or leave) if (is_button_event) { @@ -5189,6 +5224,7 @@ _SOKOL_PRIVATE EM_BOOL _sapp_emsc_mouse_cb(int emsc_type, const EmscriptenMouseE _SOKOL_PRIVATE EM_BOOL _sapp_emsc_wheel_cb(int emsc_type, const EmscriptenWheelEvent* emsc_event, void* user_data) { _SOKOL_UNUSED(emsc_type); _SOKOL_UNUSED(user_data); + bool consume_event = !_sapp.desc.html5_bubble_wheel_events; _sapp.emsc.mouse_buttons = emsc_event->mouse.buttons; if (_sapp_events_enabled()) { _sapp_init_event(SAPP_EVENTTYPE_MOUSE_SCROLL); @@ -5203,12 +5239,10 @@ _SOKOL_PRIVATE EM_BOOL _sapp_emsc_wheel_cb(int emsc_type, const EmscriptenWheelE } _sapp.event.scroll_x = scale * (float)emsc_event->deltaX; _sapp.event.scroll_y = scale * (float)emsc_event->deltaY; - _sapp_call_event(&_sapp.event); + consume_event |= _sapp_call_event(&_sapp.event); } _sapp_emsc_update_mouse_lock_state(); - // NOTE: wheel events are always consumed because they try to scroll the - // page which looks pretty bad - return true; + return consume_event; } static struct { @@ -5332,6 +5366,12 @@ _SOKOL_PRIVATE sapp_keycode _sapp_emsc_translate_key(const char* str) { return SAPP_KEYCODE_INVALID; } +// returns true if the key code is a 'character key', this is used to decide +// if a key event needs to bubble up to create a char event +_SOKOL_PRIVATE bool _sapp_emsc_is_char_key(sapp_keycode key_code) { + return key_code < SAPP_KEYCODE_WORLD_1; +} + _SOKOL_PRIVATE EM_BOOL _sapp_emsc_key_cb(int emsc_type, const EmscriptenKeyboardEvent* emsc_event, void* user_data) { _SOKOL_UNUSED(user_data); bool consume_event = false; @@ -5359,6 +5399,7 @@ _SOKOL_PRIVATE EM_BOOL _sapp_emsc_key_cb(int emsc_type, const EmscriptenKeyboard if (type == SAPP_EVENTTYPE_CHAR) { // NOTE: charCode doesn't appear to be supported on Android Chrome _sapp.event.char_code = emsc_event->charCode; + consume_event |= !_sapp.desc.html5_bubble_char_events; } else { if (0 != emsc_event->code[0]) { // This code path is for desktop browsers which send untranslated 'physical' key code strings @@ -5383,83 +5424,17 @@ _SOKOL_PRIVATE EM_BOOL _sapp_emsc_key_cb(int emsc_type, const EmscriptenKeyboard { send_keyup_followup = true; } - // Only forward alpha-numeric keys to the browser (can further be suppressed by sapp_consume_event()) - // NOTE: it should be possible to disable this behaviour via sapp_desc to give apps more - // controls over input event bubbling. - switch (_sapp.event.key_code) { - case SAPP_KEYCODE_WORLD_1: - case SAPP_KEYCODE_WORLD_2: - case SAPP_KEYCODE_ESCAPE: - case SAPP_KEYCODE_ENTER: - case SAPP_KEYCODE_TAB: - case SAPP_KEYCODE_BACKSPACE: - case SAPP_KEYCODE_INSERT: - case SAPP_KEYCODE_DELETE: - case SAPP_KEYCODE_RIGHT: - case SAPP_KEYCODE_LEFT: - case SAPP_KEYCODE_DOWN: - case SAPP_KEYCODE_UP: - case SAPP_KEYCODE_PAGE_UP: - case SAPP_KEYCODE_PAGE_DOWN: - case SAPP_KEYCODE_HOME: - case SAPP_KEYCODE_END: - case SAPP_KEYCODE_CAPS_LOCK: - case SAPP_KEYCODE_SCROLL_LOCK: - case SAPP_KEYCODE_NUM_LOCK: - case SAPP_KEYCODE_PRINT_SCREEN: - case SAPP_KEYCODE_PAUSE: - case SAPP_KEYCODE_F1: - case SAPP_KEYCODE_F2: - case SAPP_KEYCODE_F3: - case SAPP_KEYCODE_F4: - case SAPP_KEYCODE_F5: - case SAPP_KEYCODE_F6: - case SAPP_KEYCODE_F7: - case SAPP_KEYCODE_F8: - case SAPP_KEYCODE_F9: - case SAPP_KEYCODE_F10: - case SAPP_KEYCODE_F11: - case SAPP_KEYCODE_F12: - case SAPP_KEYCODE_F13: - case SAPP_KEYCODE_F14: - case SAPP_KEYCODE_F15: - case SAPP_KEYCODE_F16: - case SAPP_KEYCODE_F17: - case SAPP_KEYCODE_F18: - case SAPP_KEYCODE_F19: - case SAPP_KEYCODE_F20: - case SAPP_KEYCODE_F21: - case SAPP_KEYCODE_F22: - case SAPP_KEYCODE_F23: - case SAPP_KEYCODE_F24: - case SAPP_KEYCODE_F25: - case SAPP_KEYCODE_LEFT_SHIFT: - case SAPP_KEYCODE_LEFT_CONTROL: - case SAPP_KEYCODE_LEFT_ALT: - case SAPP_KEYCODE_LEFT_SUPER: - case SAPP_KEYCODE_RIGHT_SHIFT: - case SAPP_KEYCODE_RIGHT_CONTROL: - case SAPP_KEYCODE_RIGHT_ALT: - case SAPP_KEYCODE_RIGHT_SUPER: - case SAPP_KEYCODE_MENU: - // consume the event - consume_event = true; - break; - default: - // forward key to browser - consume_event = false; - break; + + // 'character key events' will always need to bubble up, otherwise the browser + // wouldn't be able to generate character events. + if (!_sapp_emsc_is_char_key(_sapp.event.key_code)) { + consume_event |= !_sapp.desc.html5_bubble_key_events; } } - if (_sapp_call_event(&_sapp.event)) { - // event was consumed via sapp_consume_event() - consume_event = true; - } + consume_event |= _sapp_call_event(&_sapp.event); if (send_keyup_followup) { _sapp.event.type = SAPP_EVENTTYPE_KEY_UP; - if (_sapp_call_event(&_sapp.event)) { - consume_event = true; - } + consume_event |= _sapp_call_event(&_sapp.event); } } } @@ -5469,7 +5444,7 @@ _SOKOL_PRIVATE EM_BOOL _sapp_emsc_key_cb(int emsc_type, const EmscriptenKeyboard _SOKOL_PRIVATE EM_BOOL _sapp_emsc_touch_cb(int emsc_type, const EmscriptenTouchEvent* emsc_event, void* user_data) { _SOKOL_UNUSED(user_data); - bool consume_event = false; + bool consume_event = !_sapp.desc.html5_bubble_touch_events; if (_sapp_events_enabled()) { sapp_event_type type; switch (emsc_type) { @@ -5504,7 +5479,7 @@ _SOKOL_PRIVATE EM_BOOL _sapp_emsc_touch_cb(int emsc_type, const EmscriptenTouchE dst->pos_y = src->targetY * _sapp.dpi_scale; dst->changed = src->isChanged; } - consume_event = _sapp_call_event(&_sapp.event); + consume_event |= _sapp_call_event(&_sapp.event); } } return consume_event; |