Skip to content

Commit 60445a1

Browse files
authored
Merge pull request #2016 from LarryThiessen/fix-2013-fit-batch
#2013 Batch the macro-box fit pushes; hard-hide the box scrollbar
2 parents a7b564d + 8552116 commit 60445a1

1 file changed

Lines changed: 72 additions & 51 deletions

File tree

GSE_GUI/Editor.lua

Lines changed: 72 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -549,40 +549,13 @@ local function GetEditorScrollContainer(frame)
549549
return editor and editor.scrollContainer
550550
end
551551

552-
-- When the macro edit box has focus, wheel scrolls inside it; otherwise
553-
-- forward to the editor's outer scroll container.
554-
local function ScrollFocusedMacroEditor(macroEditBox, delta)
555-
local editBox = macroEditBox and macroEditBox.editBox
556-
if not (editBox and editBox.HasFocus and editBox:HasFocus()) then return false end
557-
558-
local scrollFrame = macroEditBox.scrollFrame
559-
if not (scrollFrame and scrollFrame.GetVerticalScroll and scrollFrame.SetVerticalScroll) then return true end
560-
561-
local range = (scrollFrame.GetVerticalScrollRange and scrollFrame:GetVerticalScrollRange()) or 0
562-
if range <= 0 then return true end
563-
564-
local current = scrollFrame:GetVerticalScroll() or 0
565-
local wheelDelta = delta or 0
566-
if wheelDelta > 0 then
567-
wheelDelta = 1
568-
elseif wheelDelta < 0 then
569-
wheelDelta = -1
570-
end
571-
local step = math.max(1, math.min(MACRO_EDITOR_SCROLL_PIXELS, range / 10))
572-
local target = current - (wheelDelta * step)
573-
if target < 0 then
574-
target = 0
575-
elseif target > range then
576-
target = range
577-
end
578-
scrollFrame:SetVerticalScroll(target)
579-
return true
580-
end
581-
582552
local function MacroEditor_OnMouseWheel(mouseFrame, delta)
553+
-- Macro boxes auto-fit their content (#1998), so there is nothing left to
554+
-- scroll INSIDE one: the wheel always drives the outer block list, making
555+
-- scrolling identical wherever the cursor hovers in the editor. (The old
556+
-- focused-box inner scroll predates the auto-fit and made wheel behaviour
557+
-- change depending on what the mouse happened to be over.)
583558
local macroEditBox = mouseFrame and mouseFrame.gseWheelForwardWidget
584-
if ScrollFocusedMacroEditor(macroEditBox, delta) then return end
585-
586559
local scrollContainer = GetEditorScrollContainer(macroEditBox and macroEditBox.gseWheelForwardFrame)
587560
if scrollContainer and scrollContainer.MoveScroll then
588561
scrollContainer:MoveScroll(delta)
@@ -637,6 +610,61 @@ local MACRO_BOX_MIN_INNER = 40
637610
local function MacroBoxRowsHeight(rows, oneRow, spacing)
638611
return rows * oneRow + math.max(rows - 1, 0) * spacing
639612
end
613+
-- The ancestor push a fitted box needs, run OUTSIDE the frame that drew it.
614+
-- Walking the ancestors per box DURING the draw was the version-click stall:
615+
-- the walk itself costs almost no Lua, but each mid-draw ancestor resize
616+
-- feeds the engine's layout/anchor invalidation, and per-box walks multiplied
617+
-- that into a 0.5-1.2 s blocked frame (proven by bisection: draw with the
618+
-- walk skipped is stall-free, everything else unchanged). Pushes are queued
619+
-- and flushed in ONE batch per frame instead.
620+
-- ...and ONLY within the block. The first auto-height ancestor is the block
621+
-- panel, which recomputes its height from its children; everything above it
622+
-- (the block list, the scroll frame, the window) is SHARED chrome -- resizing
623+
-- those per block collapsed the editor (issue #2002). Past that boundary we
624+
-- only re-lay out, never resize.
625+
-- layoutQueue/layoutSeen: the shared ancestors (block list, scroll frame...)
626+
-- are common to EVERY box, and re-laying them out once per box is the SetPoint
627+
-- storm that stalled the client. Each container is queued ONCE per flush, in
628+
-- discovery order (inner containers first), and laid out after all height
629+
-- pushes have been applied.
630+
local function ApplyFitPush(macroEditBox, delta, layoutQueue, layoutSeen)
631+
local parent = macroEditBox.parent
632+
local sharedChrome = false
633+
while parent do
634+
if parent.autoAdjustHeight then sharedChrome = true end
635+
if not sharedChrome and delta ~= 0 and parent.explicitHeight
636+
and parent.height and parent.SetHeight then
637+
parent:SetHeight(parent.height + delta)
638+
elseif parent.DoLayout and not layoutSeen[parent] then
639+
layoutSeen[parent] = true
640+
layoutQueue[#layoutQueue + 1] = parent
641+
end
642+
parent = parent.parent
643+
end
644+
end
645+
local pendingFitPushes = {}
646+
local fitFlushDriver = CreateFrame("Frame")
647+
fitFlushDriver:Hide()
648+
fitFlushDriver:SetScript("OnUpdate", function(self)
649+
local pushes = pendingFitPushes
650+
pendingFitPushes = {}
651+
self:Hide()
652+
local layoutQueue, layoutSeen = {}, {}
653+
for _, push in ipairs(pushes) do
654+
-- A widget released (or pooled) since queueing has no parent chain of
655+
-- its own any more; its push is meaningless, skip it.
656+
if push[1].parent then
657+
ApplyFitPush(push[1], push[2], layoutQueue, layoutSeen)
658+
end
659+
end
660+
for _, container in ipairs(layoutQueue) do
661+
container:DoLayout()
662+
end
663+
end)
664+
local function QueueFitPush(macroEditBox, delta)
665+
pendingFitPushes[#pendingFitPushes + 1] = { macroEditBox, delta }
666+
fitFlushDriver:Show()
667+
end
640668
local function FitMacroEditBoxToContent(macroEditBox, text)
641669
if not (macroEditBox and macroEditBox.SetHeight) then return end
642670
local eb = macroEditBox.editBox or macroEditBox.editbox
@@ -678,7 +706,17 @@ local function FitMacroEditBoxToContent(macroEditBox, text)
678706
-- 255-char block cannot realistically reach the row cap; one that did needs
679707
-- rethinking, not a scrollbar.)
680708
local bar = macroEditBox.scrollBar
681-
if bar and bar.Hide then bar:Hide() end
709+
if bar and bar.Hide then
710+
bar:Hide()
711+
-- The scroll template re-Shows the bar whenever the text's scroll
712+
-- range changes (SetText on a reused box, typing past the cap...).
713+
-- A one-time Hide loses that race, so make Show itself hide: the bar
714+
-- stays dead for the widget's whole life, pooled reuses included.
715+
if not bar.gseHardHidden then
716+
bar.gseHardHidden = true
717+
bar.Show = bar.Hide
718+
end
719+
end
682720
textHeight =
683721
math.max(
684722
MacroBoxRowsHeight(MACRO_BOX_MIN_LINES, oneRow, spacing),
@@ -697,24 +735,7 @@ local function FitMacroEditBoxToContent(macroEditBox, text)
697735
-- macroFields, macroBody -- sized at draw time); auto-height ancestors
698736
-- above them only follow if those grow too. Push the delta up through
699737
-- every fixed-height ancestor, relaying out as we go.
700-
-- ...but ONLY within this block. The first auto-height ancestor is the block
701-
-- panel, which recomputes its height from its children; everything above it
702-
-- (the block list, the scroll frame, the window) is SHARED chrome. Resizing
703-
-- those by the delta made every block on load shrink the same containers
704-
-- again, collapsing the list so it no longer filled the window. Past that
705-
-- boundary we only re-lay out, never resize.
706-
local parent = macroEditBox.parent
707-
local sharedChrome = false
708-
while parent do
709-
if parent.autoAdjustHeight then sharedChrome = true end
710-
if not sharedChrome and delta ~= 0 and parent.explicitHeight
711-
and parent.height and parent.SetHeight then
712-
parent:SetHeight(parent.height + delta)
713-
elseif parent.DoLayout then
714-
parent:DoLayout()
715-
end
716-
parent = parent.parent
717-
end
738+
QueueFitPush(macroEditBox, delta)
718739
end
719740

720741
local function SetMacroCountText(macroEditBox, lenMacro)

0 commit comments

Comments
 (0)