In addition to having a scrollbar, add methods to a Window to allow dragging to scroll contents, as if you were using a browser on mobile.
Hello,
I think we can include this in more general "touch screen" support for dear imgui.
Right now a possible workaround on a per-window basis:
#include "imgui_internal.h"
void ScrollWhenDraggingOnVoid(const ImVec2& delta)
{
ImGuiContext& g = *ImGui::GetCurrentContext();
ImGuiWindow* window = g.CurrentWindow;
bool hovered = false;
bool held = false;
if (g.HoveredId == 0) // If nothing hovered so far in the frame (not same as IsAnyItemHovered()!)
ImGui::ButtonBehavior(window->Rect(), window->GetID("##scrolldraggingoverlay"), &hovered, &held, ImGuiButtonFlags_MouseButtonLeft);
if (held)
{
window->Scroll.x += delta.x;
window->Scroll.y += delta.y;
}
}
Call before End(), e.g. only scroll vertically:
ImVec2 mouse_delta = ImGui::GetIO().MouseDelta;
ScrollWhenDraggingOnVoid(ImVec2(0.0f, -mouse_delta.y));
[[
Note for myself: there's currently an issue if you tried to call SetScrollX to queue a scroll request instead of poking directly in Scroll value: CalcNextScrollFromScrollTargetAndClamp() is having some undesirable snapping on top/bottom in the (0..WindowPadding.y) region - which makes sense for _some_ higher-level function calls but not most - and this is making it stuck on edge if not initially moving fast enough. That's an issue I've been aiming to fix separately. Reducing WindowPadding or adding a workaround to clamp the value submitted with ImClamp(new_scroll, window->WindowPadding.y, window->ScrollMax.y - window->WindowPadding.y) should fix it.
if (delta.y != 0.0f)
{
float new_scroll_y = window->Scroll.y + delta.y;
// FIXME: Workaround to bypass WindowPadding Scroll snapping (should fix in core)
if (delta.y < 0.0f)
new_scroll_y = ImMin(new_scroll_y, window->ScrollMax.y - window->WindowPadding.y - 1.0f);
else
new_scroll_y = ImMax(new_scroll_y, window->WindowPadding.y + 1.0f);
ImGui::SetScrollY(window, new_scroll_y);
}
]]
Will post here and other related issue when I get to finish the work to remove this snapping.
FYI have fixed to snapped issue mentioned above, so I can confirm that this work-around will work:
#include "imgui_internal.h"
void ScrollWhenDraggingOnVoid(const ImVec2& delta, ImGuiMouseButton mouse_button)
{
ImGuiContext& g = *ImGui::GetCurrentContext();
ImGuiWindow* window = g.CurrentWindow;
bool hovered = false;
bool held = false;
ImGuiButtonFlags button_flags = (mouse_button == 0) ? ImGuiButtonFlags_MouseButtonLeft : (mouse_button == 1) ? ImGuiButtonFlags_MouseButtonRight : ImGuiButtonFlags_MouseButtonMiddle;
if (g.HoveredId == 0) // If nothing hovered so far in the frame (not same as IsAnyItemHovered()!)
ImGui::ButtonBehavior(window->Rect(), window->GetID("##scrolldraggingoverlay"), &hovered, &held, button_flags);
if (held && delta.x != 0.0f)
ImGui::SetScrollX(window, window->Scroll.x + delta.x);
if (held && delta.y != 0.0f)
ImGui::SetScrollY(window, window->Scroll.y + delta.y);
}
Needs to be called JUST before ImGui::End().
ImVec2 mouse_delta = ImGui::GetIO().MouseDelta;
ScrollWhenDraggingOnVoid(ImVec2(0.0f, -mouse_delta.y), ImGuiMouseButton_Middle);
ImGui::End();
I think we can probably easily implement something globally as desired, it's mostly a matter of design. If we have config options to scroll this way it may hinder other inputs. I'll have to think of what is the safest way to design that option.
Is this method only available in the root window?
I seem to be unable to use this method to drag and drop the child window in the child window?
@YuDang1024 I have confirmed that the code in #3379 works perfectly with child window.
Make sure you call it JUST before EndChild(), see details above.
Most helpful comment
FYI have fixed to snapped issue mentioned above, so I can confirm that this work-around will work:
Needs to be called JUST before ImGui::End().
I think we can probably easily implement something globally as desired, it's mostly a matter of design. If we have config options to scroll this way it may hinder other inputs. I'll have to think of what is the safest way to design that option.