Skip to content

Commit

Permalink
Windows, Style: Added style.WindowBorderHoverPadding setting to confi…
Browse files Browse the repository at this point in the history
…gure inner/outer padding applied to hit-testing of windows borders.

Amend 3c7177c, 59f3c4f, ae7f833.
Could be latched inside windows to be multi-dpi friendly, but likely won't matter soon.
  • Loading branch information
ocornut committed Feb 7, 2025
1 parent 914fbcf commit 4982602
Show file tree
Hide file tree
Showing 5 changed files with 19 additions and 13 deletions.
3 changes: 3 additions & 0 deletions docs/CHANGELOG.txt
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ Other changes:

- Fixed IsItemDeactivatedAfterEdit() signal being broken for Checkbox(),
RadioButton(), Selectable(). Regression from 2025/01/13. (#8370)
- Windows, Style: Added style.WindowBorderHoverPadding setting to configure
inner/outer padding applied to hit-testing of windows borders and detection
of hovered window.
- InputTextWithHint(): Fixed buffer-overflow (luckily often with no visible effect)
when a user callback modified the buffer contents in a way that altered the
visibility of the preview/hint buffer. (#8368) [@m9710797, @ocornut]
Expand Down
21 changes: 10 additions & 11 deletions imgui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1167,11 +1167,7 @@ CODE
// When using CTRL+TAB (or Gamepad Square+L/R) we delay the visual a little in order to reduce visual noise doing a fast switch.
static const float NAV_WINDOWING_HIGHLIGHT_DELAY = 0.20f; // Time before the highlight and screen dimming starts fading in
static const float NAV_WINDOWING_LIST_APPEAR_DELAY = 0.15f; // Time before the window list starts to appear

static const float NAV_ACTIVATE_HIGHLIGHT_TIMER = 0.10f; // Time to highlight an item activated by a shortcut.

// Window resizing from edges (when io.ConfigWindowsResizeFromEdges = true and ImGuiBackendFlags_HasMouseCursors is set in io.BackendFlags by backend)
static const float WINDOWS_HOVER_PADDING = 4.0f; // Extend outside window for hovering/resizing (maxxed with TouchPadding) and inside windows for borders. Affect FindHoveredWindow().
static const float WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER = 0.04f; // Reduce visual noise by only highlighting the border after a certain time.
static const float WINDOWS_MOUSE_WHEEL_SCROLL_LOCK_TIMER = 0.70f; // Lock scrolled window (so it doesn't pick child windows that are scrolling through) for a certain time, unless mouse moved.

Expand Down Expand Up @@ -1318,6 +1314,7 @@ ImGuiStyle::ImGuiStyle()
WindowPadding = ImVec2(8,8); // Padding within a window
WindowRounding = 0.0f; // Radius of window corners rounding. Set to 0.0f to have rectangular windows. Large values tend to lead to variety of artifacts and are not recommended.
WindowBorderSize = 1.0f; // Thickness of border around windows. Generally set to 0.0f or 1.0f. Other values not well tested.
WindowBorderHoverPadding = 4.0f; // Hit-testing extent outside/inside resizing border. Also extend determination of hovered window. Generally meaningfully larger than WindowBorderSize to make it easy to reach borders.
WindowMinSize = ImVec2(32,32); // Minimum window size
WindowTitleAlign = ImVec2(0.0f,0.5f);// Alignment for title bar text
WindowMenuButtonPosition = ImGuiDir_Left; // Position of the collapsing/docking button in the title bar (left/right). Defaults to ImGuiDir_Left.
Expand Down Expand Up @@ -1379,6 +1376,7 @@ void ImGuiStyle::ScaleAllSizes(float scale_factor)
WindowPadding = ImTrunc(WindowPadding * scale_factor);
WindowRounding = ImTrunc(WindowRounding * scale_factor);
WindowMinSize = ImTrunc(WindowMinSize * scale_factor);
WindowBorderHoverPadding = ImTrunc(WindowBorderHoverPadding * scale_factor);
ChildRounding = ImTrunc(ChildRounding * scale_factor);
PopupRounding = ImTrunc(PopupRounding * scale_factor);
FramePadding = ImTrunc(FramePadding * scale_factor);
Expand Down Expand Up @@ -5037,7 +5035,7 @@ void ImGui::UpdateHoveredWindowAndCaptureFlags()

// FIXME-DPI: This storage was added on 2021/03/31 for test engine, but if we want to multiply WINDOWS_HOVER_PADDING
// by DpiScale, we need to make this window-agnostic anyhow, maybe need storing inside ImGuiWindow.
g.WindowsHoverPadding = ImMax(g.Style.TouchExtraPadding, ImVec2(WINDOWS_HOVER_PADDING, WINDOWS_HOVER_PADDING));
g.WindowsBorderHoverPadding = ImMax(ImMax(g.Style.TouchExtraPadding.x, g.Style.TouchExtraPadding.y), g.Style.WindowBorderHoverPadding);

// Find the window hovered by mouse:
// - Child windows can extend beyond the limit of their parent so we need to derive HoveredRootWindow from HoveredWindow.
Expand Down Expand Up @@ -5800,7 +5798,7 @@ void ImGui::FindHoveredWindowEx(const ImVec2& pos, bool find_first_and_in_any_vi
hovered_window = g.MovingWindow;

ImVec2 padding_regular = g.Style.TouchExtraPadding;
ImVec2 padding_for_resize = g.IO.ConfigWindowsResizeFromEdges ? g.WindowsHoverPadding : padding_regular;
ImVec2 padding_for_resize = ImMax(g.Style.TouchExtraPadding, ImVec2(g.Style.WindowBorderHoverPadding, g.Style.WindowBorderHoverPadding));
for (int i = g.Windows.Size - 1; i >= 0; i--)
{
ImGuiWindow* window = g.Windows[i];
Expand Down Expand Up @@ -6502,7 +6500,7 @@ static int ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& si
int ret_auto_fit_mask = 0x00;
const float grip_draw_size = IM_TRUNC(ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f));
const float grip_hover_inner_size = (resize_grip_count > 0) ? IM_TRUNC(grip_draw_size * 0.75f) : 0.0f;
const float grip_hover_outer_size = g.IO.ConfigWindowsResizeFromEdges ? WINDOWS_HOVER_PADDING : 0.0f;
const float grip_hover_outer_size = g.WindowsBorderHoverPadding;

ImRect clamp_rect = visibility_rect;
const bool window_move_from_title_bar = g.IO.ConfigWindowsMoveFromTitleBarOnly && !(window->Flags & ImGuiWindowFlags_NoTitleBar);
Expand Down Expand Up @@ -6570,7 +6568,7 @@ static int ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& si
const ImGuiAxis axis = (border_n == ImGuiDir_Left || border_n == ImGuiDir_Right) ? ImGuiAxis_X : ImGuiAxis_Y;

bool hovered, held;
ImRect border_rect = GetResizeBorderRect(window, border_n, grip_hover_inner_size, WINDOWS_HOVER_PADDING);
ImRect border_rect = GetResizeBorderRect(window, border_n, grip_hover_inner_size, g.WindowsBorderHoverPadding);
ImGuiID border_id = window->GetID(border_n + 4); // == GetWindowResizeBorderID()
ItemAdd(border_rect, border_id, NULL, ImGuiItemFlags_NoNav);
ButtonBehavior(border_rect, border_id, &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_NoNavFocus);
Expand Down Expand Up @@ -6608,7 +6606,7 @@ static int ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& si

const ImVec2 border_curr = (window->Pos + ImMin(def.SegmentN1, def.SegmentN2) * window->Size);
const float border_target_rel_mode_for_axis = border_curr[axis] + g.IO.MouseDelta[axis];
const float border_target_abs_mode_for_axis = g.IO.MousePos[axis] - g.ActiveIdClickOffset[axis] + WINDOWS_HOVER_PADDING; // Match ButtonBehavior() padding above.
const float border_target_abs_mode_for_axis = g.IO.MousePos[axis] - g.ActiveIdClickOffset[axis] + g.WindowsBorderHoverPadding; // Match ButtonBehavior() padding above.

// Use absolute mode position
ImVec2 border_target = window->Pos;
Expand Down Expand Up @@ -6697,7 +6695,7 @@ static int ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& si

// Recalculate next expected border expected coordinates
if (*border_held != -1)
g.WindowResizeBorderExpectedRect = GetResizeBorderRect(window, *border_held, grip_hover_inner_size, WINDOWS_HOVER_PADDING);
g.WindowResizeBorderExpectedRect = GetResizeBorderRect(window, *border_held, grip_hover_inner_size, g.WindowsBorderHoverPadding);

return ret_auto_fit_mask;
}
Expand Down Expand Up @@ -10184,7 +10182,8 @@ static void ImGui::ErrorCheckNewFrameSanityChecks()
IM_ASSERT(g.Style.CurveTessellationTol > 0.0f && "Invalid style setting!");
IM_ASSERT(g.Style.CircleTessellationMaxError > 0.0f && "Invalid style setting!");
IM_ASSERT(g.Style.Alpha >= 0.0f && g.Style.Alpha <= 1.0f && "Invalid style setting!"); // Allows us to avoid a few clamps in color computations
IM_ASSERT(g.Style.WindowMinSize.x >= 1.0f && g.Style.WindowMinSize.y >= 1.0f && "Invalid style setting.");
IM_ASSERT(g.Style.WindowMinSize.x >= 1.0f && g.Style.WindowMinSize.y >= 1.0f && "Invalid style setting!");
IM_ASSERT(g.Style.WindowBorderHoverPadding > 0.0f && "Invalid style setting!"); // Required otherwise cannot resize from borders.
IM_ASSERT(g.Style.WindowMenuButtonPosition == ImGuiDir_None || g.Style.WindowMenuButtonPosition == ImGuiDir_Left || g.Style.WindowMenuButtonPosition == ImGuiDir_Right);
IM_ASSERT(g.Style.ColorButtonPosition == ImGuiDir_Left || g.Style.ColorButtonPosition == ImGuiDir_Right);

Expand Down
1 change: 1 addition & 0 deletions imgui.h
Original file line number Diff line number Diff line change
Expand Up @@ -2146,6 +2146,7 @@ struct ImGuiStyle
ImVec2 WindowPadding; // Padding within a window.
float WindowRounding; // Radius of window corners rounding. Set to 0.0f to have rectangular windows. Large values tend to lead to variety of artifacts and are not recommended.
float WindowBorderSize; // Thickness of border around windows. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly).
float WindowBorderHoverPadding; // Hit-testing extent outside/inside resizing border. Also extend determination of hovered window. Generally meaningfully larger than WindowBorderSize to make it easy to reach borders.
ImVec2 WindowMinSize; // Minimum window size. This is a global setting. If you want to constrain individual windows, use SetNextWindowSizeConstraints().
ImVec2 WindowTitleAlign; // Alignment for title bar text. Defaults to (0.0f,0.5f) for left-aligned,vertically centered.
ImGuiDir WindowMenuButtonPosition; // Side of the collapsing/docking button in the title bar (None/Left/Right). Defaults to ImGuiDir_Left.
Expand Down
5 changes: 4 additions & 1 deletion imgui_demo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7985,11 +7985,14 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
ImGui::SliderAngle("TableAngledHeadersAngle", &style.TableAngledHeadersAngle, -50.0f, +50.0f);
ImGui::SliderFloat2("TableAngledHeadersTextAlign", (float*)&style.TableAngledHeadersTextAlign, 0.0f, 1.0f, "%.2f");

ImGui::SeparatorText("Widgets");
ImGui::SeparatorText("Windows");
ImGui::SliderFloat2("WindowTitleAlign", (float*)&style.WindowTitleAlign, 0.0f, 1.0f, "%.2f");
ImGui::SliderFloat("WindowBorderHoverPadding", &style.WindowBorderHoverPadding, 1.0f, 20.0f, "%.0f");
int window_menu_button_position = style.WindowMenuButtonPosition + 1;
if (ImGui::Combo("WindowMenuButtonPosition", (int*)&window_menu_button_position, "None\0Left\0Right\0"))
style.WindowMenuButtonPosition = (ImGuiDir)(window_menu_button_position - 1);

ImGui::SeparatorText("Widgets");
ImGui::Combo("ColorButtonPosition", (int*)&style.ColorButtonPosition, "Left\0Right\0");
ImGui::SliderFloat2("ButtonTextAlign", (float*)&style.ButtonTextAlign, 0.0f, 1.0f, "%.2f");
ImGui::SameLine(); HelpMarker("Alignment applies when a button is larger than its text content.");
Expand Down
2 changes: 1 addition & 1 deletion imgui_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -2083,7 +2083,7 @@ struct ImGuiContext
ImVector<ImGuiWindowStackData> CurrentWindowStack;
ImGuiStorage WindowsById; // Map window's ImGuiID to ImGuiWindow*
int WindowsActiveCount; // Number of unique windows submitted by frame
ImVec2 WindowsHoverPadding; // Padding around resizable windows for which hovering on counts as hovering the window == ImMax(style.TouchExtraPadding, WINDOWS_HOVER_PADDING).
float WindowsBorderHoverPadding; // Padding around resizable windows for which hovering on counts as hovering the window == ImMax(style.TouchExtraPadding, style.WindowBorderHoverPadding). This isn't so multi-dpi friendly.
ImGuiID DebugBreakInWindow; // Set to break in Begin() call.
ImGuiWindow* CurrentWindow; // Window being drawn into
ImGuiWindow* HoveredWindow; // Window the mouse is hovering. Will typically catch mouse inputs.
Expand Down

0 comments on commit 4982602

Please sign in to comment.