Skip to content

Commit 8a44c31

Browse files
committed
Scrolling: Further reduce unrelease mouse-wheel locked window timer + misc refactor (#2604, #3795, #4559)
The refactor are designed to minimize the diff for changes needed for #3795
1 parent dfa1bb0 commit 8a44c31

File tree

2 files changed

+23
-20
lines changed

2 files changed

+23
-20
lines changed

imgui.cpp

+21-18
Original file line numberDiff line numberDiff line change
@@ -953,7 +953,7 @@ static const float NAV_WINDOWING_LIST_APPEAR_DELAY = 0.15f; // Time
953953
// Window resizing from edges (when io.ConfigWindowsResizeFromEdges = true and ImGuiBackendFlags_HasMouseCursors is set in io.BackendFlags by backend)
954954
static const float WINDOWS_HOVER_PADDING = 4.0f; // Extend outside window for hovering/resizing (maxxed with TouchPadding) and inside windows for borders. Affect FindHoveredWindow().
955955
static const float WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER = 0.04f; // Reduce visual noise by only highlighting the border after a certain time.
956-
static const float WINDOWS_MOUSE_WHEEL_SCROLL_LOCK_TIMER = 1.50f; // Lock scrolled window (so it doesn't pick child windows that are scrolling through) for a certain time, unless mouse moved.
956+
static const float WINDOWS_MOUSE_WHEEL_SCROLL_LOCK_TIMER = 0.80f; // Lock scrolled window (so it doesn't pick child windows that are scrolling through) for a certain time, unless mouse moved.
957957

958958
//-------------------------------------------------------------------------
959959
// [SECTION] FORWARD DECLARATIONS
@@ -4268,7 +4268,7 @@ static void ImGui::UpdateMouseInputs()
42684268
static void LockWheelingWindow(ImGuiWindow* window)
42694269
{
42704270
ImGuiContext& g = *GImGui;
4271-
g.WheelingWindowTimer = window ? WINDOWS_MOUSE_WHEEL_SCROLL_LOCK_TIMER : 0.0f;
4271+
g.WheelingWindowReleaseTimer = window ? WINDOWS_MOUSE_WHEEL_SCROLL_LOCK_TIMER : 0.0f;
42724272
if (g.WheelingWindow == window)
42734273
return;
42744274
IMGUI_DEBUG_LOG_IO("LockWheelingWindow() \"%s\"\n", window ? window->Name : "NULL");
@@ -4283,20 +4283,21 @@ void ImGui::UpdateMouseWheel()
42834283
// Reset the locked window if we move the mouse or after the timer elapses
42844284
if (g.WheelingWindow != NULL)
42854285
{
4286-
g.WheelingWindowTimer -= g.IO.DeltaTime;
4286+
g.WheelingWindowReleaseTimer -= g.IO.DeltaTime;
42874287
if (IsMousePosValid() && ImLengthSqr(g.IO.MousePos - g.WheelingWindowRefMousePos) > g.IO.MouseDragThreshold * g.IO.MouseDragThreshold)
4288-
g.WheelingWindowTimer = 0.0f;
4289-
if (g.WheelingWindowTimer <= 0.0f)
4288+
g.WheelingWindowReleaseTimer = 0.0f;
4289+
if (g.WheelingWindowReleaseTimer <= 0.0f)
42904290
LockWheelingWindow(NULL);
42914291
}
42924292

42934293
const bool hovered_id_using_mouse_wheel = (g.HoveredIdPreviousFrame != 0 && g.HoveredIdPreviousFrameUsingMouseWheel);
42944294
const bool active_id_using_mouse_wheel_x = g.ActiveIdUsingKeyInputMask.TestBit(ImGuiKey_MouseWheelX);
42954295
const bool active_id_using_mouse_wheel_y = g.ActiveIdUsingKeyInputMask.TestBit(ImGuiKey_MouseWheelY);
42964296

4297-
float wheel_x = (!hovered_id_using_mouse_wheel && !active_id_using_mouse_wheel_x) ? g.IO.MouseWheelH : 0.0f;
4298-
float wheel_y = (!hovered_id_using_mouse_wheel && !active_id_using_mouse_wheel_y) ? g.IO.MouseWheel : 0;
4299-
if (wheel_x == 0.0f && wheel_y == 0.0f)
4297+
ImVec2 wheel;
4298+
wheel.x = (!hovered_id_using_mouse_wheel && !active_id_using_mouse_wheel_x) ? g.IO.MouseWheelH : 0.0f;
4299+
wheel.y = (!hovered_id_using_mouse_wheel && !active_id_using_mouse_wheel_y) ? g.IO.MouseWheel : 0;
4300+
if (wheel.x == 0.0f && wheel.y == 0.0f)
43004301
return;
43014302

43024303
//IMGUI_DEBUG_LOG("MouseWheel X:%.3f Y:%.3f\n", wheel_x, wheel_y);
@@ -4306,7 +4307,7 @@ void ImGui::UpdateMouseWheel()
43064307

43074308
// Zoom / Scale window
43084309
// FIXME-OBSOLETE: This is an old feature, it still works but pretty much nobody is using it and may be best redesigned.
4309-
if (wheel_y != 0.0f && g.IO.KeyCtrl && g.IO.FontAllowUserScaling)
4310+
if (wheel.y != 0.0f && g.IO.KeyCtrl && g.IO.FontAllowUserScaling)
43104311
{
43114312
LockWheelingWindow(mouse_window);
43124313
ImGuiWindow* window = mouse_window;
@@ -4322,23 +4323,25 @@ void ImGui::UpdateMouseWheel()
43224323
}
43234324
return;
43244325
}
4325-
4326-
// Mouse wheel scrolling
4327-
// If a child window has the ImGuiWindowFlags_NoScrollWithMouse flag, we give a chance to scroll its parent
43284326
if (g.IO.KeyCtrl)
43294327
return;
43304328

4329+
// Mouse wheel scrolling
43314330
// As a standard behavior holding SHIFT while using Vertical Mouse Wheel triggers Horizontal scroll instead
43324331
// (we avoid doing it on OSX as it the OS input layer handles this already)
43334332
const bool swap_axis = g.IO.KeyShift && !g.IO.ConfigMacOSXBehaviors;
43344333
if (swap_axis)
43354334
{
4336-
wheel_x = wheel_y;
4337-
wheel_y = 0.0f;
4335+
wheel.x = wheel.y;
4336+
wheel.y = 0.0f;
43384337
}
43394338

43404339
// Vertical Mouse Wheel scrolling
4341-
if (wheel_y != 0.0f)
4340+
// Bubble up into parent window if:
4341+
// - a child window doesn't allow any scrolling.
4342+
// - a child window doesn't need scrolling because it is already at the edge for the direction we are going in.
4343+
// - a child window has the ImGuiWindowFlags_NoScrollWithMouse flag.
4344+
if (wheel.y != 0.0f)
43424345
{
43434346
ImGuiWindow* window = mouse_window;
43444347
while ((window->Flags & ImGuiWindowFlags_ChildWindow) && ((window->ScrollMax.y == 0.0f) || ((window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs))))
@@ -4348,12 +4351,12 @@ void ImGui::UpdateMouseWheel()
43484351
LockWheelingWindow(mouse_window);
43494352
float max_step = window->InnerRect.GetHeight() * 0.67f;
43504353
float scroll_step = ImFloor(ImMin(5 * window->CalcFontSize(), max_step));
4351-
SetScrollY(window, window->Scroll.y - wheel_y * scroll_step);
4354+
SetScrollY(window, window->Scroll.y - wheel.y * scroll_step);
43524355
}
43534356
}
43544357

43554358
// Horizontal Mouse Wheel scrolling, or Vertical Mouse Wheel w/ Shift held
4356-
if (wheel_x != 0.0f)
4359+
if (wheel.x != 0.0f)
43574360
{
43584361
ImGuiWindow* window = mouse_window;
43594362
while ((window->Flags & ImGuiWindowFlags_ChildWindow) && ((window->ScrollMax.x == 0.0f) || ((window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs))))
@@ -4363,7 +4366,7 @@ void ImGui::UpdateMouseWheel()
43634366
LockWheelingWindow(mouse_window);
43644367
float max_step = window->InnerRect.GetWidth() * 0.67f;
43654368
float scroll_step = ImFloor(ImMin(2 * window->CalcFontSize(), max_step));
4366-
SetScrollX(window, window->Scroll.x - wheel_x * scroll_step);
4369+
SetScrollX(window, window->Scroll.x - wheel.x * scroll_step);
43674370
}
43684371
}
43694372
}

imgui_internal.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -1631,7 +1631,7 @@ struct ImGuiContext
16311631
ImGuiWindow* MovingWindow; // Track the window we clicked on (in order to preserve focus). The actual window that is moved is generally MovingWindow->RootWindow.
16321632
ImGuiWindow* WheelingWindow; // Track the window we started mouse-wheeling on. Until a timer elapse or mouse has moved, generally keep scrolling the same window even if during the course of scrolling the mouse ends up hovering a child window.
16331633
ImVec2 WheelingWindowRefMousePos;
1634-
float WheelingWindowTimer;
1634+
float WheelingWindowReleaseTimer;
16351635

16361636
// Item/widgets state and tracking information
16371637
ImGuiID DebugHookIdInfo; // Will call core hooks: DebugHookIdInfo() from GetID functions, used by Stack Tool [next HoveredId/ActiveId to not pull in an extra cache-line]
@@ -1885,7 +1885,7 @@ struct ImGuiContext
18851885
HoveredWindowUnderMovingWindow = NULL;
18861886
MovingWindow = NULL;
18871887
WheelingWindow = NULL;
1888-
WheelingWindowTimer = 0.0f;
1888+
WheelingWindowReleaseTimer = 0.0f;
18891889

18901890
DebugHookIdInfo = 0;
18911891
HoveredId = HoveredIdPreviousFrame = 0;

0 commit comments

Comments
 (0)