Backends: GLFW: Registering custom low-level mouse wheel handler to get more accurate scrolling impulses on Emscripten. (#4019, #6096)

Namely, GLFW JS emulation seems to quantize values to a min of -1/+1 which breaks modern OSX/Windows emulating smoothness with stepping wheels (slow steps are sending sub-1.0 values)
+ Massage changelog.
This commit is contained in:
ocornut 2023-02-03 15:00:41 +01:00
parent 6584de4a78
commit d0b1aaa076
2 changed files with 46 additions and 19 deletions

View File

@ -16,7 +16,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2023-02-02: Inputs: Scaling X value on Emscripten (bug?). (#4019, #6096)
// 2023-02-03: Emscripten: Registering custom low-level mouse wheel handler to get more accurate scrolling impulses on Emscripten. (#4019, #6096)
// 2023-01-04: Inputs: Fixed mods state on Linux when using Alt-GR text input (e.g. German keyboard layout), could lead to broken text input. Revert a 2022/01/17 change were we resumed using mods provided by GLFW, turns out they were faulty.
// 2022-11-22: Perform a dummy glfwGetError() read to cancel missing names with glfwGetKeyName(). (#5908)
// 2022-10-18: Perform a dummy glfwGetError() read to cancel missing mouse cursors errors. Using GLFW_VERSION_COMBINED directly. (#5785)
@ -76,6 +76,11 @@
#include <GLFW/glfw3native.h> // for glfwGetWin32Window
#endif
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#include <emscripten/html5.h>
#endif
// We gather version tests as define in order to easily see which features are version-dependent.
#define GLFW_VERSION_COMBINED (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 + GLFW_VERSION_REVISION)
#ifdef GLFW_RESIZE_NESW_CURSOR // Let's be nice to people who pulled GLFW between 2019-04-16 (3.4 define) and 2019-11-29 (cursors defines) // FIXME: Remove when GLFW 3.4 is released?
@ -285,7 +290,8 @@ void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yo
bd->PrevUserCallbackScroll(window, xoffset, yoffset);
#ifdef __EMSCRIPTEN__
xoffset /= 100.0;
// Ignore GLFW events: will be processed in ImGui_ImplEmscripten_WheelCallback().
return;
#endif
ImGuiIO& io = ImGui::GetIO();
@ -406,6 +412,24 @@ void ImGui_ImplGlfw_MonitorCallback(GLFWmonitor*, int)
// Unused in 'master' branch but 'docking' branch will use this, so we declare it ahead of it so if you have to install callbacks you can install this one too.
}
#ifdef __EMSCRIPTEN__
static EM_BOOL ImGui_ImplEmscripten_WheelCallback(int, const EmscriptenWheelEvent* ev, void*)
{
// Mimic Emscripten_HandleWheel() in SDL.
// Corresponding equivalent in GLFW JS emulation layer has incorrect quantizing preventing small values. See #6096
float multiplier = 0.0f;
if (ev->deltaMode == DOM_DELTA_PIXEL) { multiplier = 1.0f / 100.0f; } // 100 pixels make up a step.
else if (ev->deltaMode == DOM_DELTA_LINE) { multiplier = 1.0f / 3.0f; } // 3 lines make up a step.
else if (ev->deltaMode == DOM_DELTA_PAGE) { multiplier = 80.0f; } // A page makes up 80 steps.
float wheel_x = ev->deltaX * -multiplier;
float wheel_y = ev->deltaY * -multiplier;
ImGuiIO& io = ImGui::GetIO();
io.AddMouseWheelEvent(wheel_x, wheel_y);
//IMGUI_DEBUG_LOG("[Emsc] mode %d dx: %.2f, dy: %.2f, dz: %.2f --> feed %.2f %.2f\n", (int)ev->deltaMode, ev->deltaX, ev->deltaY, ev->deltaZ, wheel_x, wheel_y);
return EM_TRUE;
}
#endif
void ImGui_ImplGlfw_InstallCallbacks(GLFWwindow* window)
{
ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
@ -503,6 +527,13 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
if (install_callbacks)
ImGui_ImplGlfw_InstallCallbacks(window);
// Register Emscripten Wheel callback to workaround issue in Emscripten GLFW Emulation (#6096)
// We intentionally do not check 'if (install_callbacks)' here, as some users may set it to false and call GLFW callback themselves.
// FIXME: May break chaining in case user registered their own Emscripten callback?
#ifdef __EMSCRIPTEN__
emscripten_set_wheel_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, NULL, false, ImGui_ImplEmscripten_WheelCallback);
#endif
bd->ClientApi = client_api;
return true;
}

View File

@ -35,36 +35,26 @@ HOW TO UPDATE?
VERSION 1.89.3 (In Progress)
-----------------------------------------------------------------------
Breaking changes:
All changes:
- Inputs, Scrolling: Made horizontal scroll wheel and horizontal scroll direction consistent
accross backends/os. (#4019, #6096, #1463) [@PathogenDavid, @ocornut, @rokups]
- Clarified that 'wheel_y > 0.0f' scrolls Up, 'wheel_y > 0.0f' scrolls Down.
- Clarified that 'wheel_x > 0.0f' scrolls Left, 'wheel_x > 0.0f' scrolls Right.
- Backends: Win32: flipping WM_MOUSEHWHEEL value to match other backends and
offer consistent horizontal scrolling direction. (#4019)
- Backends: SDL: flipping SDL_MOUSEWHEEL 'wheel.x' value to match other backends and
offer consistent horizontal scrolling direction. (#4019)
Clarified that 'wheel_x > 0.0f' scrolls Left, 'wheel_x > 0.0f' scrolls Right.
- Backends: Fixed horizontal scroll direction for Win32 and SDL backends. (#4019)
- Shift+WheelY support on non-OSX machines was already correct. (#2424, #1463)
(whereaas on OSX machines Shift+WheelY turns into WheelX at the OS level).
- If you use a custom-backend, you should verify that:
- Wheel up (*) emit wheel_y > 0.0f values and scrolls up.
- Wheel down (*) emit wheel_y < 0.0f values and scrolls down.
- Wheel left (*) or mod+wheel up emit wheel_x > 0.0f values and scroll Left.
- Wheel right (*) or mod+wheel down emits wheel_x < 0.0f values and scroll Right.
- (*) both axises flipped on OSX for mouse and touchpad when 'Natural Scrolling' is on.
- (*) both axises flipped On Windows for touchpad only when 'Settings->Touchpad->Down motion scrolls up' is set.
- If you use a custom-backend, you should verify horizontal wheel direction.
- Axises are flipped by OSX for mouse & touchpad when 'Natural Scrolling' is on.
- Axises are flipped by Windows for touchpad when 'Settings->Touchpad->Down motion scrolls up' is on.
- You can use 'Demo->Tools->Debug Log->IO" to visualize values submitted to Dear ImGui.
- Known issues remaining with Emscripten:
- The magnitude of wheeling values on Emscripten setups is still not great. (#6096)
- The magnitude of wheeling values on Emscripten was improved but isn't perfect. (#6096)
- When running the Emscripten app on a Mac with a mouse, SHIFT+WheelY doesn't turn into WheelX.
This is because we don't know that we are running on Mac and apply our own Shift+swapping
on top of OSX' own swapping, so wheel axises are swapped twice. Emscripten apps may need
to find a way to detect this and set io.ConfigMacOSXBehaviors manually (if you know a way
let us know!), or offer the "OSX-style behavior" option to their user.
All changes:
- Window: Avoid rendering shapes for hidden resize grips.
- Tables: Raised max Columns count from 64 to 512. (#6094, #5305, #4876, #3572)
The previous limit was due to using 64-bit integers but we moved to bits-array
@ -89,11 +79,17 @@ All changes:
can exacerbate that. (#6114, #3644)
- Backends: OSX: Fixed scroll/wheel scaling for devices emitting events with
hasPreciseScrollingDeltas==false (e.g. non-Apple mices).
- Backends: Win32: flipping WM_MOUSEHWHEEL value to match other backends and
offer consistent horizontal scrolling direction. (#4019)
- Backends: SDL: flipping SDL_MOUSEWHEEL 'wheel.x' value to match other backends and
offer consistent horizontal scrolling direction. (#4019)
- Backends: SDL: Removed SDL_MOUSEWHEEL value clamping. (#4019, #6096, #6081)
- Backends: SDL: Added support for SDL 2.0.18+ preciseX/preciseY mouse wheel data
for smooth scrolling as reported by SDL. (#4019, #6096)
- Backends: SDL: Avoid calling SDL_SetCursor() when cursor has not changed, as the function
is surprisingly costly on Mac with latest SDL (may be fixed in next SDL version). (#6113)
- Backends: GLFW: Registering custom low-level mouse wheel handler to get more accurate
scrolling impulses on Emscripten. (#4019, #6096) [@ocornut, @wolfpld, @tolopolarity]
- Backends: WebGPU: Fix building for latest WebGPU specs (remove implicit layout generation).
(#6117, #4116, #3632) [@tonygrue, @bfierz]
- Examples: refactord all examples to use a "MainLoopStep()" function. This is in order