@@ -549,40 +549,13 @@ local function GetEditorScrollContainer(frame)
549549 return editor and editor .scrollContainer
550550end
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-
582552local 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
637610local function MacroBoxRowsHeight (rows , oneRow , spacing )
638611 return rows * oneRow + math.max (rows - 1 , 0 ) * spacing
639612end
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
640668local 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 )
718739end
719740
720741local function SetMacroCountText (macroEditBox , lenMacro )
0 commit comments