mirror of
https://github.com/Drezil/imgui.git
synced 2024-11-21 19:37:01 +00:00
Windows: use relative mouse movement for border resize when the border geometry has moved. (#1710)
(e.g. resizing a child window triggering parent scroll) to avoid resizing feedback loop.
This commit is contained in:
parent
9235352400
commit
f1d1a8d32b
@ -96,6 +96,9 @@ Other changes:
|
|||||||
to false when popup is closed in ways other than clicking the close button. (#6900)
|
to false when popup is closed in ways other than clicking the close button. (#6900)
|
||||||
- Double-clicking lower-left resize grip auto-resize (like lower-rightone).
|
- Double-clicking lower-left resize grip auto-resize (like lower-rightone).
|
||||||
- Double-clicking bottom or right window border auto-resize on a singles axis.
|
- Double-clicking bottom or right window border auto-resize on a singles axis.
|
||||||
|
- Use relative mouse movement for border resize when the border geometry has moved
|
||||||
|
(e.g. resizing a child window triggering parent scroll) in order to avoid resizing
|
||||||
|
feedback loops. Unless manually mouse-wheeling while border resizing. (#1710)
|
||||||
- Separators:
|
- Separators:
|
||||||
- Altered end-points to use more standard boundaries. (#205, #4787, #1643)
|
- Altered end-points to use more standard boundaries. (#205, #4787, #1643)
|
||||||
Left position is always current cursor X position, right position is always work-rect
|
Left position is always current cursor X position, right position is always work-rect
|
||||||
|
44
imgui.cpp
44
imgui.cpp
@ -5964,7 +5964,7 @@ static int ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& si
|
|||||||
ImGuiID border_id = window->GetID(border_n + 4); // == GetWindowResizeBorderID()
|
ImGuiID border_id = window->GetID(border_n + 4); // == GetWindowResizeBorderID()
|
||||||
ItemAdd(border_rect, border_id, NULL, ImGuiItemFlags_NoNav);
|
ItemAdd(border_rect, border_id, NULL, ImGuiItemFlags_NoNav);
|
||||||
ButtonBehavior(border_rect, border_id, &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_NoNavFocus);
|
ButtonBehavior(border_rect, border_id, &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_NoNavFocus);
|
||||||
//GetForegroundDrawLists(window)->AddRect(border_rect.Min, border_rect.Max, IM_COL32(255, 255, 0, 255));
|
//GetForegroundDrawList(window)->AddRect(border_rect.Min, border_rect.Max, IM_COL32(255, 255, 0, 255));
|
||||||
if (hovered && g.HoveredIdTimer <= WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER)
|
if (hovered && g.HoveredIdTimer <= WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER)
|
||||||
hovered = false;
|
hovered = false;
|
||||||
if (hovered || held)
|
if (hovered || held)
|
||||||
@ -5983,14 +5983,44 @@ static int ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& si
|
|||||||
}
|
}
|
||||||
else if (held)
|
else if (held)
|
||||||
{
|
{
|
||||||
|
// Switch to relative resizing mode when border geometry moved (e.g. resizing a child altering parent scroll), in order to avoid resizing feedback loop.
|
||||||
|
// Currently only using relative mode on resizable child windows, as the problem to solve is more likely noticeable for them, but could apply for all windows eventually.
|
||||||
|
// FIXME: May want to generalize this idiom at lower-level, so more widgets can use it!
|
||||||
|
const bool just_scrolled_manually_while_resizing = (g.WheelingWindow != NULL && g.WheelingWindowScrolledFrame == g.FrameCount && IsWindowChildOf(window, g.WheelingWindow, false));
|
||||||
|
if (g.ActiveIdIsJustActivated || just_scrolled_manually_while_resizing)
|
||||||
|
{
|
||||||
|
g.WindowResizeBorderExpectedRect = border_rect;
|
||||||
|
g.WindowResizeRelativeMode = false;
|
||||||
|
}
|
||||||
|
if ((window->Flags & ImGuiWindowFlags_ChildWindow) && memcmp(&g.WindowResizeBorderExpectedRect, &border_rect, sizeof(ImRect)) != 0)
|
||||||
|
g.WindowResizeRelativeMode = true;
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
// Use absolute mode position
|
||||||
|
ImVec2 border_target = window->Pos;
|
||||||
|
border_target[axis] = border_target_abs_mode_for_axis;
|
||||||
|
|
||||||
|
// Use relative mode target for child window, ignore resize when moving back toward the ideal absolute position.
|
||||||
|
bool ignore_resize = false;
|
||||||
|
if (g.WindowResizeRelativeMode)
|
||||||
|
{
|
||||||
|
//GetForegroundDrawList()->AddText(GetMainViewport()->WorkPos, IM_COL32_WHITE, "Relative Mode");
|
||||||
|
border_target[axis] = border_target_rel_mode_for_axis;
|
||||||
|
if (g.IO.MouseDelta[axis] == 0.0f || (g.IO.MouseDelta[axis] > 0.0f) == (border_target_rel_mode_for_axis > border_target_abs_mode_for_axis))
|
||||||
|
ignore_resize = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clamp, apply
|
||||||
ImVec2 clamp_min(border_n == ImGuiDir_Right ? clamp_rect.Min.x : -FLT_MAX, border_n == ImGuiDir_Down || (border_n == ImGuiDir_Up && window_move_from_title_bar) ? clamp_rect.Min.y : -FLT_MAX);
|
ImVec2 clamp_min(border_n == ImGuiDir_Right ? clamp_rect.Min.x : -FLT_MAX, border_n == ImGuiDir_Down || (border_n == ImGuiDir_Up && window_move_from_title_bar) ? clamp_rect.Min.y : -FLT_MAX);
|
||||||
ImVec2 clamp_max(border_n == ImGuiDir_Left ? clamp_rect.Max.x : +FLT_MAX, border_n == ImGuiDir_Up ? clamp_rect.Max.y : +FLT_MAX);
|
ImVec2 clamp_max(border_n == ImGuiDir_Left ? clamp_rect.Max.x : +FLT_MAX, border_n == ImGuiDir_Up ? clamp_rect.Max.y : +FLT_MAX);
|
||||||
ImVec2 border_target = window->Pos;
|
|
||||||
border_target[axis] = g.IO.MousePos[axis] - g.ActiveIdClickOffset[axis] + WINDOWS_HOVER_PADDING;
|
|
||||||
border_target = ImClamp(border_target, clamp_min, clamp_max);
|
border_target = ImClamp(border_target, clamp_min, clamp_max);
|
||||||
if (window->Flags & ImGuiWindowFlags_ChildWindow) // Clamp resizing of childs within parent
|
if (window->Flags & ImGuiWindowFlags_ChildWindow) // Clamp resizing of childs within parent
|
||||||
border_target = ImClamp(border_target, window->ParentWindow->InnerClipRect.Min, window->ParentWindow->InnerClipRect.Max);
|
border_target = ImClamp(border_target, window->ParentWindow->InnerClipRect.Min, window->ParentWindow->InnerClipRect.Max);
|
||||||
CalcResizePosSizeFromAnyCorner(window, border_target, ImMin(def.SegmentN1, def.SegmentN2), &pos_target, &size_target);
|
if (!ignore_resize)
|
||||||
|
CalcResizePosSizeFromAnyCorner(window, border_target, ImMin(def.SegmentN1, def.SegmentN2), &pos_target, &size_target);
|
||||||
}
|
}
|
||||||
if (hovered)
|
if (hovered)
|
||||||
*border_hovered = border_n;
|
*border_hovered = border_n;
|
||||||
@ -6043,6 +6073,10 @@ static int ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& si
|
|||||||
if (size_target.x != FLT_MAX || size_target.y != FLT_MAX || pos_target.x != FLT_MAX || pos_target.y != FLT_MAX)
|
if (size_target.x != FLT_MAX || size_target.y != FLT_MAX || pos_target.x != FLT_MAX || pos_target.y != FLT_MAX)
|
||||||
MarkIniSettingsDirty(window);
|
MarkIniSettingsDirty(window);
|
||||||
|
|
||||||
|
// Recalculate next expected border expected coordinates
|
||||||
|
if (*border_held != -1)
|
||||||
|
g.WindowResizeBorderExpectedRect = GetResizeBorderRect(window, *border_held, grip_hover_inner_size, WINDOWS_HOVER_PADDING);
|
||||||
|
|
||||||
return ret_auto_fit_mask;
|
return ret_auto_fit_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8931,6 +8965,7 @@ void ImGui::UpdateMouseWheel()
|
|||||||
float max_step = window->InnerRect.GetWidth() * 0.67f;
|
float max_step = window->InnerRect.GetWidth() * 0.67f;
|
||||||
float scroll_step = ImTrunc(ImMin(2 * window->CalcFontSize(), max_step));
|
float scroll_step = ImTrunc(ImMin(2 * window->CalcFontSize(), max_step));
|
||||||
SetScrollX(window, window->Scroll.x - wheel.x * scroll_step);
|
SetScrollX(window, window->Scroll.x - wheel.x * scroll_step);
|
||||||
|
g.WheelingWindowScrolledFrame = g.FrameCount;
|
||||||
}
|
}
|
||||||
if (do_scroll[ImGuiAxis_Y])
|
if (do_scroll[ImGuiAxis_Y])
|
||||||
{
|
{
|
||||||
@ -8938,6 +8973,7 @@ void ImGui::UpdateMouseWheel()
|
|||||||
float max_step = window->InnerRect.GetHeight() * 0.67f;
|
float max_step = window->InnerRect.GetHeight() * 0.67f;
|
||||||
float scroll_step = ImTrunc(ImMin(5 * window->CalcFontSize(), max_step));
|
float scroll_step = ImTrunc(ImMin(5 * window->CalcFontSize(), max_step));
|
||||||
SetScrollY(window, window->Scroll.y - wheel.y * scroll_step);
|
SetScrollY(window, window->Scroll.y - wheel.y * scroll_step);
|
||||||
|
g.WheelingWindowScrolledFrame = g.FrameCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1899,6 +1899,7 @@ struct ImGuiContext
|
|||||||
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.
|
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.
|
||||||
ImVec2 WheelingWindowRefMousePos;
|
ImVec2 WheelingWindowRefMousePos;
|
||||||
int WheelingWindowStartFrame; // This may be set one frame before WheelingWindow is != NULL
|
int WheelingWindowStartFrame; // This may be set one frame before WheelingWindow is != NULL
|
||||||
|
int WheelingWindowScrolledFrame;
|
||||||
float WheelingWindowReleaseTimer;
|
float WheelingWindowReleaseTimer;
|
||||||
ImVec2 WheelingWindowWheelRemainder;
|
ImVec2 WheelingWindowWheelRemainder;
|
||||||
ImVec2 WheelingAxisAvg;
|
ImVec2 WheelingAxisAvg;
|
||||||
@ -2091,6 +2092,8 @@ struct ImGuiContext
|
|||||||
ImU32 ColorEditSavedColor; // RGB value with alpha set to 0.
|
ImU32 ColorEditSavedColor; // RGB value with alpha set to 0.
|
||||||
ImVec4 ColorPickerRef; // Initial/reference color at the time of opening the color picker.
|
ImVec4 ColorPickerRef; // Initial/reference color at the time of opening the color picker.
|
||||||
ImGuiComboPreviewData ComboPreviewData;
|
ImGuiComboPreviewData ComboPreviewData;
|
||||||
|
ImRect WindowResizeBorderExpectedRect; // Expected border rect, switch to relative edit if moving
|
||||||
|
bool WindowResizeRelativeMode;
|
||||||
float SliderGrabClickOffset;
|
float SliderGrabClickOffset;
|
||||||
float SliderCurrentAccum; // Accumulated slider delta when using navigation controls.
|
float SliderCurrentAccum; // Accumulated slider delta when using navigation controls.
|
||||||
bool SliderCurrentAccumDirty; // Has the accumulated slider delta changed since last time we tried to apply it?
|
bool SliderCurrentAccumDirty; // Has the accumulated slider delta changed since last time we tried to apply it?
|
||||||
@ -2187,7 +2190,7 @@ struct ImGuiContext
|
|||||||
HoveredWindowUnderMovingWindow = NULL;
|
HoveredWindowUnderMovingWindow = NULL;
|
||||||
MovingWindow = NULL;
|
MovingWindow = NULL;
|
||||||
WheelingWindow = NULL;
|
WheelingWindow = NULL;
|
||||||
WheelingWindowStartFrame = -1;
|
WheelingWindowStartFrame = WheelingWindowScrolledFrame = -1;
|
||||||
WheelingWindowReleaseTimer = 0.0f;
|
WheelingWindowReleaseTimer = 0.0f;
|
||||||
|
|
||||||
DebugHookIdInfo = 0;
|
DebugHookIdInfo = 0;
|
||||||
@ -2289,6 +2292,7 @@ struct ImGuiContext
|
|||||||
ColorEditCurrentID = ColorEditSavedID = 0;
|
ColorEditCurrentID = ColorEditSavedID = 0;
|
||||||
ColorEditSavedHue = ColorEditSavedSat = 0.0f;
|
ColorEditSavedHue = ColorEditSavedSat = 0.0f;
|
||||||
ColorEditSavedColor = 0;
|
ColorEditSavedColor = 0;
|
||||||
|
WindowResizeRelativeMode = false;
|
||||||
SliderGrabClickOffset = 0.0f;
|
SliderGrabClickOffset = 0.0f;
|
||||||
SliderCurrentAccum = 0.0f;
|
SliderCurrentAccum = 0.0f;
|
||||||
SliderCurrentAccumDirty = false;
|
SliderCurrentAccumDirty = false;
|
||||||
|
Loading…
Reference in New Issue
Block a user