diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 59f268ff0..062b1bc90 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -81,11 +81,15 @@ Other Changes: - TextLink() underline thickness. - ColorButton() border thickness. - Separator() thickness, via scaling newly added style.SeparatorSize. (#2657, #9263) -- Demo: fixed IMGUI_DEMO_MARKER locations for examples applets. (#9261, #3689) [@pthom] - Clipper: - Clear `DisplayStart`/`DisplayEnd` fields when `Step()` returns false. - Added `UserIndex` helper storage. This is solely a convenience for cases where you may want to carry an index around. +- Scrollbar: + - Implemented a custom tweak to extend hit-testing bounding box when window is sitting + at the edge of a viewport (e.g. fullscreen or docked window), so that e.g. mouse the + mouse at the extreme of the screen will reach the scrollbar. (#9276) +- Demo: fixed IMGUI_DEMO_MARKER locations for examples applets. (#9261, #3689) [@pthom] - Backends: - SDLGPU3: removed unnecessary call to SDL_WaitForGPUIdle when releasing vertex/index buffers. (#9262) [@jaenis] diff --git a/imgui_internal.h b/imgui_internal.h index 0d229e6c2..ee9847393 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -3643,6 +3643,7 @@ namespace ImGui IMGUI_API ImGuiID GetWindowScrollbarID(ImGuiWindow* window, ImGuiAxis axis); IMGUI_API ImGuiID GetWindowResizeCornerID(ImGuiWindow* window, int n); // 0..3: corners IMGUI_API ImGuiID GetWindowResizeBorderID(ImGuiWindow* window, ImGuiDir dir); + IMGUI_API void ExtendHitBoxWhenNearViewportEdge(ImGuiWindow* window, ImRect* bb, float threshold, ImGuiAxis axis); // Widgets low-level behaviors IMGUI_API bool ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags = 0); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index f1837920c..97e297caa 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -974,6 +974,16 @@ ImRect ImGui::GetWindowScrollbarRect(ImGuiWindow* window, ImGuiAxis axis) return ImRect(ImMax(outer_rect.Min.x, outer_rect.Max.x - border_size - scrollbar_size), inner_rect.Min.y + border_top, outer_rect.Max.x - border_size, inner_rect.Max.y - border_size); } +void ImGui::ExtendHitBoxWhenNearViewportEdge(ImGuiWindow* window, ImRect* bb, float threshold, ImGuiAxis axis) +{ + ImRect window_rect = window->RootWindow->Rect(); + ImRect viewport_rect = window->Viewport->GetMainRect(); + if (window_rect.Min[axis] == viewport_rect.Min[axis] && bb->Min[axis] > window_rect.Min[axis] && bb->Min[axis] - threshold <= window_rect.Min[axis]) + bb->Min[axis] = window_rect.Min[axis]; + if (window_rect.Max[axis] == viewport_rect.Max[axis] && bb->Max[axis] < window_rect.Max[axis] && bb->Max[axis] + threshold >= window_rect.Max[axis]) + bb->Max[axis] = window_rect.Max[axis]; +} + void ImGui::Scrollbar(ImGuiAxis axis) { ImGuiContext& g = *GImGui; @@ -1035,11 +1045,15 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, ImS6 const float grab_h_pixels = ImClamp(scrollbar_size_v * ((float)size_visible_v / (float)win_size_v), grab_h_minsize, scrollbar_size_v); const float grab_h_norm = grab_h_pixels / scrollbar_size_v; + // As a special thing, we allow scrollbar near the edge of a screen/viewport to be reachable with mouse at the extreme edge (#9276) + ImRect bb_hit = bb_frame; + ExtendHitBoxWhenNearViewportEdge(window, &bb_hit, g.Style.WindowBorderSize, (ImGuiAxis)(axis ^ 1)); + // Handle input right away. None of the code of Begin() is relying on scrolling position before calling Scrollbar(). bool held = false; bool hovered = false; ItemAdd(bb_frame, id, NULL, ImGuiItemFlags_NoNav); - ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_NoNavFocus); + ButtonBehavior(bb_hit, id, &hovered, &held, ImGuiButtonFlags_NoNavFocus); const ImS64 scroll_max = ImMax((ImS64)1, size_contents_v - size_visible_v); float scroll_ratio = ImSaturate((float)*p_scroll_v / (float)scroll_max);