Skip to content

Commit

Permalink
Window: Shrink close button hit-testing region when it covers an abno…
Browse files Browse the repository at this point in the history
…rmally high portion of the window visible area (e.g. when window is collapsed and moved in a corner)to facilitate moving the window away. (#3825)
  • Loading branch information
ocornut committed Feb 18, 2021
1 parent 0ecdf81 commit a8f76c2
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 5 deletions.
2 changes: 2 additions & 0 deletions docs/CHANGELOG.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ Other Changes:

- DragScalar: Fixed crash when using DragScalar() directly (not via common wrapper like DragFloat() etc.)
with ImGuiSliderFlags_AlwaysClamp + only one of either p_min or p_max set. (#3824) [@harry75369]
- Window: Shrink close button hit-testing region when it covers an abnormally high portion of the window visible
area (e.g. when window is collapsed + moved in a corner) to facilitate moving the window away. (#3825)
- ImDrawList: AddCircle, AddCircleFilled(): Tweaked default segment count calculation to honor MaxError
with more accuracy. Made default segment count always even for better looking result. (#3808) [@thedmd]
- ImDrawList: AddCircle, AddCircleFilled(): New default for style.
Expand Down
1 change: 1 addition & 0 deletions imgui_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,7 @@ struct IMGUI_API ImRect
ImVec2 GetSize() const { return ImVec2(Max.x - Min.x, Max.y - Min.y); }
float GetWidth() const { return Max.x - Min.x; }
float GetHeight() const { return Max.y - Min.y; }
float GetArea() const { return (Max.x - Min.x) * (Max.y - Min.y); }
ImVec2 GetTL() const { return Min; } // Top-left
ImVec2 GetTR() const { return ImVec2(Max.x, Min.y); } // Top-right
ImVec2 GetBL() const { return ImVec2(Min.x, Max.y); } // Bottom-left
Expand Down
18 changes: 13 additions & 5 deletions imgui_widgets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -782,22 +782,30 @@ bool ImGui::ArrowButton(const char* str_id, ImGuiDir dir)
}

// Button to close a window
bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos)//, float size)
bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;

// We intentionally allow interaction when clipped so that a mechanical Alt,Right,Validate sequence close a window.
// (this isn't the regular behavior of buttons, but it doesn't affect the user much because navigation tends to keep items visible).
// Tweak 1: Shrink hit-testing area if button covers an abnormally large proportion of the visible region. That's in order to facilitate moving the window away. (#3825)
// This may better be applied as a general hit-rect reduction mechanism for all widgets to ensure the area to move window is always accessible?
const ImRect bb(pos, pos + ImVec2(g.FontSize, g.FontSize) + g.Style.FramePadding * 2.0f);
bool is_clipped = !ItemAdd(bb, id);
ImRect bb_interact = bb;
const float area_to_visible_ratio = window->OuterRectClipped.GetArea() / bb.GetArea();
if (area_to_visible_ratio < 1.5f)
bb_interact.Expand(ImFloor(bb_interact.GetSize() * -0.25f));

// Tweak 2: We intentionally allow interaction when clipped so that a mechanical Alt,Right,Activate sequence can always close a window.
// (this isn't the regular behavior of buttons, but it doesn't affect the user much because navigation tends to keep items visible).
bool is_clipped = !ItemAdd(bb_interact, id);

bool hovered, held;
bool pressed = ButtonBehavior(bb, id, &hovered, &held);
bool pressed = ButtonBehavior(bb_interact, id, &hovered, &held);
if (is_clipped)
return pressed;

// Render
// FIXME: Clarify this mess
ImU32 col = GetColorU32(held ? ImGuiCol_ButtonActive : ImGuiCol_ButtonHovered);
ImVec2 center = bb.GetCenter();
if (hovered)
Expand Down

0 comments on commit a8f76c2

Please # to comment.