Keep the scroll arrows skinned when the list refreshes

The scroll frame re-shows the button's own native art whenever it
recalculates, and one skinning pass can't hold against it: ElvUI's
HandleNextPrevButton guards on isSkinned, so a second call does nothing.

The talent frame already carried the answer -- re-hide the art by file
from OnUpdate and pin the three state textures -- so it moves into the
shared layer as Skin:ScrollArrow and the Challenges list scrolls take it
too. Routing the talent frame through it also picks up the
disabled-hover fix every other button already has.
This commit is contained in:
2026-08-22 16:59:59 +02:00
parent 013fe665ab
commit 63e179e96e
2 changed files with 69 additions and 65 deletions
+67 -2
View File
@@ -428,6 +428,71 @@ local function ThumbOnMouseUp(thumb)
SetThumbColor(thumb, SCROLL_THUMB_ALPHA) SetThumbColor(thumb, SCROLL_THUMB_ALPHA)
end end
-- The arrows re-art themselves the same way the track and thumb do, and one
-- pass can't hold against it: S:HandleNextPrevButton guards on its own
-- isSkinned flag, so calling it a second time does nothing at all. What comes
-- back isn't the ElvUI arrow being overwritten either -- that texture is still
-- in place underneath (probed: the native "scrollbarproportional" region shown
-- alongside ArrowUp). It's the button's own art, which StripTextures only hid,
-- and the scroll frame shows it again whenever it recalculates.
--
-- So the native art is re-hidden by file from OnUpdate, the same answer the
-- track, the thumb and the tab art all needed and for the same reason: nothing
-- fires when it happens. The three state textures are captured and their
-- setters noop'd as well -- still worth closing off, since whatever refreshes
-- these is free to swap in a fresh texture object and orphan the three.
--
-- Matched by file rather than as "any region that isn't one of ours": ElvUI's
-- own panel and border pieces are regions of the button too, so hiding
-- everything unrecognised would take the ElvUI square with it. Compared
-- case-insensitively -- the client hands paths back from GetTexture in whatever
-- case it stored them, not the case they were set in.
local ARROW_TEXTURE = E.Media.Textures.ArrowUp:lower()
local NATIVE_SCROLL_ART = "scrollbar"
local function RestoreArrow(button)
for i = 1, button:GetNumRegions() do
local region = select(i, button:GetRegions())
local texture = region.GetTexture and region:GetTexture()
if texture and tostring(texture):lower():find(NATIVE_SCROLL_ART) and region:IsShown() then
region:Hide()
end
end
for _, texture in ipairs(button.CoAArrowTextures) do
local current = texture:GetTexture()
if not current or tostring(current):lower() ~= ARROW_TEXTURE then
texture:SetTexture(E.Media.Textures.ArrowUp)
texture:SetInside(button)
texture:SetTexCoord(0, 1, 0, 1)
texture:SetRotation(S.ArrowRotation[button.CoAArrowDirection])
end
end
end
function Skin:ScrollArrow(button, direction)
if not button or button.CoAArrowSkinned then return end
button.CoAArrowSkinned = true
self:NextPrevButton(button, direction)
button.CoAArrowDirection = direction
button.CoAArrowTextures = {
button:GetNormalTexture(),
button:GetPushedTexture(),
button:GetDisabledTexture(),
}
button.SetNormalTexture = E.noop
button.SetPushedTexture = E.noop
button.SetDisabledTexture = E.noop
button.SetHighlightTexture = E.noop
button:HookScript("OnUpdate", RestoreArrow)
end
function Skin:ScrollBar(bar, thumb, up, down) function Skin:ScrollBar(bar, thumb, up, down)
if not bar or bar.CoASkinned then return end if not bar or bar.CoASkinned then return end
bar.CoASkinned = true bar.CoASkinned = true
@@ -466,13 +531,13 @@ function Skin:ScrollBar(bar, thumb, up, down)
-- lines up with the track, and a second point left in place would stretch the -- lines up with the track, and a second point left in place would stretch the
-- button between the two. -- button between the two.
if up then if up then
self:NextPrevButton(up, "up") self:ScrollArrow(up, "up")
up:ClearAllPoints() up:ClearAllPoints()
up:Point("BOTTOM", bar, "TOP", 0, SCROLL_BUTTON_GAP) up:Point("BOTTOM", bar, "TOP", 0, SCROLL_BUTTON_GAP)
end end
if down then if down then
self:NextPrevButton(down, "down") self:ScrollArrow(down, "down")
down:ClearAllPoints() down:ClearAllPoints()
down:Point("TOP", bar, "BOTTOM", 0, -SCROLL_BUTTON_GAP) down:Point("TOP", bar, "BOTTOM", 0, -SCROLL_BUTTON_GAP)
end end
+2 -63
View File
@@ -471,67 +471,6 @@ local function SkinScrollThumb(thumb, thumbName)
end) end)
end end
-- The scroll arrows come back as Blizzard chevrons after the list refreshes,
-- and it isn't the ElvUI arrow being overwritten -- that texture is still in
-- place underneath. The button's native art is a region StripTextures hid, and
-- the scroll frame shows it again whenever it recalculates.
--
-- Matched by file rather than as "any region that isn't one of ours": on this
-- client ElvUI's own panel and border pieces are regions of the button too, so
-- hiding everything unrecognised would take the ElvUI square with it.
--
-- Compared case-insensitively: the client hands paths back from GetTexture in
-- whatever case it stored them, not the case they were set in.
local ARROW_TEXTURE = E.Media.Textures.ArrowUp:lower()
local NATIVE_SCROLL_ART = "scrollbar"
local function RestoreArrow(button)
for i = 1, button:GetNumRegions() do
local region = select(i, button:GetRegions())
local texture = region.GetTexture and region:GetTexture()
if texture and texture:lower():find(NATIVE_SCROLL_ART) and region:IsShown() then
region:Hide()
end
end
-- The arrow itself is re-pointed as well, in case a refresh reaches the
-- state textures and not only the art it re-shows.
for _, texture in ipairs(button.CoAArrowTextures) do
local current = texture:GetTexture()
if not current or current:lower() ~= ARROW_TEXTURE then
texture:SetTexture(E.Media.Textures.ArrowUp)
texture:SetInside(button)
texture:SetTexCoord(0, 1, 0, 1)
texture:SetRotation(S.ArrowRotation[button.CoAArrowDirection])
end
end
end
local function SkinArrow(button, direction)
if not button or button.CoASkinned then return end
button.CoASkinned = true
S:HandleNextPrevButton(button, direction)
button.CoAArrowDirection = direction
button.CoAArrowTextures = {
button:GetNormalTexture(),
button:GetPushedTexture(),
button:GetDisabledTexture()
}
-- Still worth closing off: whatever refreshes these would otherwise be free
-- to swap in a fresh texture object and orphan the three above.
button.SetNormalTexture = E.noop
button.SetPushedTexture = E.noop
button.SetDisabledTexture = E.noop
button.SetHighlightTexture = E.noop
button:HookScript("OnUpdate", RestoreArrow)
end
-- The list inside each dropdown popup: a scroll frame with the framed inset -- The list inside each dropdown popup: a scroll frame with the framed inset
-- and overlay art around it. The arrows are named off the scroll frame rather -- and overlay art around it. The arrows are named off the scroll frame rather
-- than off the scrollbar, so they're looked up here instead. -- than off the scrollbar, so they're looked up here instead.
@@ -558,13 +497,13 @@ local function SkinMenuScroll(listName)
local up = _G[listName.."ScrollFrameScrollUpButton"] local up = _G[listName.."ScrollFrameScrollUpButton"]
if up then if up then
up:Point("BOTTOM", scrollBar, "TOP", 0, 1) up:Point("BOTTOM", scrollBar, "TOP", 0, 1)
SkinArrow(up, "up") Skin:ScrollArrow(up, "up")
end end
local down = _G[listName.."ScrollFrameScrollDownButton"] local down = _G[listName.."ScrollFrameScrollDownButton"]
if down then if down then
down:Point("TOP", scrollBar, "BOTTOM", 0, -1) down:Point("TOP", scrollBar, "BOTTOM", 0, -1)
SkinArrow(down, "down") Skin:ScrollArrow(down, "down")
end end
local thumbName = listName.."ScrollFrameScrollBarThumb" local thumbName = listName.."ScrollFrameScrollBarThumb"