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

MouseWheel vs track pad (macOS) #6103

Closed
ypujante opened this issue Jan 20, 2023 · 3 comments
Closed

MouseWheel vs track pad (macOS) #6103

ypujante opened this issue Jan 20, 2023 · 3 comments
Labels

Comments

@ypujante
Copy link
Contributor

Although I know that ImGui::GetIO().MouseWheel is an internal API (lives in imgui.h but under a section marked Internal), I am using it to detect when the mouse wheel is used (see this issue #6051 (comment) I closed a few moments ago).

The code I am using is something like:

  if(ImGui::IsItemHovered())
  {
    auto mouseVerticalWheel = ImGui::GetIO().MouseWheel;
    if(mouseVerticalWheel != 0)
    {
      iCanvas.zoomBy(mouseVerticalWheel > 0 ? 0.9f : 1.1f, iCanvas.getCanvasMousePos());
    }
  }

On my mac desktop with a real mouse, when I use the mouse wheel and just go up/down one "notch" I just get one mouse wheel "event" and so it behaves really great.

On my mac laptop, using the 2 fingers swipe on the trackpad I get a ton of events thus making the zoom way too fast.

  1. although it is flagged as an internal API, I did not find any other way to truly access the mouse wheel. Is there an API I missed?
  2. is there a way to know whether it is a track pad or a real mouse? Or am I using the API entirely wrong? What would you recommend?

Thank you

@ocornut ocornut added the inputs label Jan 20, 2023
@ocornut
Copy link
Owner

ocornut commented Jan 20, 2023

  1. It is technically not exposed but that's fine to use and not going anywhere anytime soon. I might end up exposing GetKeyData() since the struct is public anyway, in which case you would use GetKeyData(ImGuiKey_MouseWheelY)->AnalogValue;, but I suggest sticking to io.MouseWheel.
  2. It is not currently possible to differenciate them but we should be adding that data soon (coincidentically this was discussed earier today Emscripten mouse wheeling (was: GLFW Emscripten fixes) #6096 and your case is same as Emscripten mouse wheeling (was: GLFW Emscripten fixes) #6096 (comment)). Generally note the value of MouseWheel.y will be ~-1/+1 on a typical mouse setup and many smaller values on a setup with smooth scrolling like a Mac. You may react differently based on the intensity of that signal. You can visualize the values in Demo>Tools>Debug Log>IO (see Debug Tools page).

@ypujante
Copy link
Contributor Author

So I ran the tool you suggested, and there is no real difference in terms of value: both produce value of 0.1 for each event. What is different is the timing. With the real mouse wheel I get one event per "notch", but with the track pad, of course I get one event (of the same amplitude) per frame during the entire swipe.

// with real mouse wheel: exactly 3 notches up (slowly)
[...]
[05698] Processed: MousePos (944.0, 538.0)
[05699] Processed: MousePos (944.0, 537.0)
[05824] Processed: MouseWheel (0.000, 0.100)
[05880] Processed: MouseWheel (0.000, 0.100)
[05953] Processed: MouseWheel (0.000, 0.100)
[06627] Processed: MousePos (944.0, 536.0)
[06628] Processed: MousePos (934.0, 526.0)
[...]

// with trackpad (different computer) small double finger swipe up
[...]
[01517] Processed: MousePos (1075.0, 499.0)
[01519] Processed: MousePos (1076.0, 500.0)
[01776] Processed: MouseWheel (0.000, -0.100)
[01777] Processed: MouseWheel (0.000, -0.100)
[01778] Processed: MouseWheel (0.000, -0.100)
[01779] Processed: MouseWheel (0.000, -0.100)
[01780] Processed: MouseWheel (0.000, -0.100)
[01781] Processed: MouseWheel (0.000, -0.100)
[01782] Processed: MouseWheel (0.000, -0.100)
[01783] Processed: MouseWheel (0.000, -0.100)
[01784] Processed: MouseWheel (-0.100, -0.100)
[01785] Processed: MouseWheel (0.000, -0.100)
[01786] Processed: MouseWheel (0.000, -0.100)
[01787] Processed: MouseWheel (0.000, -0.100)
[01788] Processed: MouseWheel (-0.100, -0.100)
[01789] Processed: MouseWheel (0.000, -0.100)
[01790] Processed: MouseWheel (-0.100, -0.100)
[01791] Processed: MouseWheel (-0.100, -0.100)
[01792] Processed: MouseWheel (0.000, -0.100)
[01793] Processed: MouseWheel (-0.100, -0.100)
[01794] Processed: MouseWheel (0.000, -0.100)
[01795] Processed: MouseWheel (-0.100, -0.100)
[01796] Processed: MouseWheel (0.000, -0.100)
[01797] Processed: MouseWheel (-0.100, -0.100)
[01798] Processed: MouseWheel (0.000, -0.100)
[01799] Processed: MouseWheel (0.000, -0.100)
[02103] Processed: MousePos (1067.0, 489.0)
[02104] Processed: MousePos (1048.0, 469.0)
[...]

I ran another test, in which I move the mouse wheel really fast (several notches up without stopping in between):

// with real mouse wheel: several  notches up (real fast)
[...]
[00928] Processed: MousePos (1091.0, 511.0)
[01205] Processed: MouseWheel (0.000, -0.100)
[01207] Processed: MouseWheel (0.000, -0.900)
[01208] Processed: MouseWheel (0.000, -3.736)
[01209] Processed: MouseWheel (0.000, -5.518)
[01210] Processed: MouseWheel (0.000, -6.312)
[01211] Processed: MouseWheel (0.000, -6.925)
[01214] Processed: MouseWheel (0.000, -7.325)
[01844] Processed: MousePos (1082.0, 506.0)
[...]

In this case, the values are getting bigger (in absolute terms) from frame to frame

  1. were you expecting this kind of output? or are you seeing something off?
  2. Based on this results, I just don't see an obvious algorithm I can use to process this differences to extract meaning for my use case.
  3. The scrollbar behavior implemented by ImGui both with the mouse wheel (slow/fast) and the trackpad seems right to me. So that proves that the data must be right. I am going to dig in this code to see if I can make sense of it and somehow implement a similar behavior, but any pointer appreciated (is there an API that I am missing?)

@ypujante
Copy link
Contributor Author

Just to wrap up my findings:

  1. (unless I am wrong), the main code that handles scrolling from the mouse wheel in ImGui is
  // from ImGui::UpdateMouseWheel() method
  // [...]
  float max_step = window->InnerRect.GetHeight() * 0.67f;
  float scroll_step = ImFloor(ImMin(5 * window->CalcFontSize(), max_step));
  SetScrollY(window, window->Scroll.y - wheel.y * scroll_step);

so clearly there is no "magic" or special handling whether it is a true mouse wheel or a track pad

  1. I applied a similar logic to my code (using the actual value as a factor instead of a trigger)
    auto mouseVerticalWheel = ImGui::GetIO().MouseWheel;
    if(mouseVerticalWheel != 0)
    {
      auto zoomPercent = 1.0f - mouseVerticalWheel * 0.05f;
      iCanvas.zoomBy(zoomPercent, iCanvas.getCanvasMousePos());
    }

The 0.05f factor was determined by trial and error (I made it into a static variable tied to a SliderFloat and tweaked until it "felt" right)

It works "naturally" both with a mouse wheel and a track pad!

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

No branches or pull requests

2 participants