Drag inventory windows with an outline to stop drag freezes
Moving the real window made the client re-lay out every item button, texture and cooldown model on each mouse movement, freezing the game for seconds with the Bags and Bank open (profiling showed almost no Lua time during the freezes). A single empty outline frame now follows the mouse, and the window is moved once on drop. Clicking the outline finishes a move whose drop was missed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019W3rwt5PZSpEDkXYzRuRhH
This commit is contained in:
@@ -1141,6 +1141,7 @@ Bagshui:AddComponent(function()
|
||||
--- - If there's a frame docked to this one, close it.
|
||||
function Inventory:UiFrame_OnHide()
|
||||
self.uiFrame:StopMovingOrSizing()
|
||||
self:ReleaseDragOutline()
|
||||
-- If the mouse button was released while the game hitched, OnDragStop may never have fired.
|
||||
-- A stuck flag would make FixWindowPosition() (and window rescue) skip this window forever.
|
||||
self.dragInProgress = false
|
||||
@@ -1158,6 +1159,55 @@ Bagshui:AddComponent(function()
|
||||
end
|
||||
end
|
||||
|
||||
-- Outline that follows the mouse while an inventory window is dragged.
|
||||
-- Moving the real window makes the game re-position every item button, texture and cooldown
|
||||
-- inside it on each mouse movement, which froze the whole game for seconds with the Bags and
|
||||
-- Bank open. The outline is a single empty frame, and the real window moves once, on drop.
|
||||
local dragOutline
|
||||
|
||||
local function GetDragOutline()
|
||||
if not dragOutline then
|
||||
dragOutline = _G.CreateFrame("Frame", "BagshuiDragOutline", _G.UIParent)
|
||||
dragOutline:SetFrameStrata("FULLSCREEN_DIALOG")
|
||||
dragOutline:SetMovable(true)
|
||||
dragOutline:EnableMouse(true)
|
||||
if dragOutline.SetClampedToScreen then
|
||||
dragOutline:SetClampedToScreen(true)
|
||||
end
|
||||
dragOutline:SetBackdrop({
|
||||
bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
|
||||
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
|
||||
tile = true,
|
||||
tileSize = 16,
|
||||
edgeSize = 16,
|
||||
insets = { left = 4, right = 4, top = 4, bottom = 4 },
|
||||
})
|
||||
dragOutline:SetBackdropColor(0, 0, 0, 0.3)
|
||||
dragOutline:SetBackdropBorderColor(1, 1, 1, 0.9)
|
||||
-- If the drop was ever missed, clicking the outline finishes the move.
|
||||
dragOutline:SetScript("OnMouseUp", function()
|
||||
if dragOutline.owner then
|
||||
dragOutline.owner:UiFrame_OnDragStop()
|
||||
end
|
||||
end)
|
||||
dragOutline:Hide()
|
||||
end
|
||||
return dragOutline
|
||||
end
|
||||
|
||||
--- Stop and hide the drag outline if this window owns it.
|
||||
---@return number? left, number? top Where the outline was dropped (window coordinates).
|
||||
function Inventory:ReleaseDragOutline()
|
||||
if not dragOutline or dragOutline.owner ~= self then
|
||||
return
|
||||
end
|
||||
dragOutline:StopMovingOrSizing()
|
||||
local left, top = dragOutline:GetLeft(), dragOutline:GetTop()
|
||||
dragOutline:Hide()
|
||||
dragOutline.owner = nil
|
||||
return left, top
|
||||
end
|
||||
|
||||
--- Handle dragging (start).
|
||||
function Inventory:UiFrame_OnDragStart()
|
||||
if self.dockTo then
|
||||
@@ -1166,7 +1216,23 @@ Bagshui:AddComponent(function()
|
||||
-- Has to be self instead of "this" because it can be called from docked windows.
|
||||
self.dragInProgress = true
|
||||
self.dragStartedAt = _G.GetTime()
|
||||
self.uiFrame:StartMoving()
|
||||
|
||||
local frame = self.uiFrame
|
||||
local left, top = frame:GetLeft(), frame:GetTop()
|
||||
if left and top then
|
||||
-- Same parent and scale as the window, so both use the same coordinates.
|
||||
local outline = GetDragOutline()
|
||||
outline.owner = self
|
||||
outline:SetScale(frame:GetScale())
|
||||
outline:SetWidth(frame:GetWidth())
|
||||
outline:SetHeight(frame:GetHeight())
|
||||
outline:ClearAllPoints()
|
||||
outline:SetPoint("TOPLEFT", _G.UIParent, "BOTTOMLEFT", left, top)
|
||||
outline:Show()
|
||||
outline:StartMoving()
|
||||
else
|
||||
frame:StartMoving()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1176,8 +1242,18 @@ Bagshui:AddComponent(function()
|
||||
Bagshui.components[self.dockTo]:UiFrame_OnDragStop()
|
||||
elseif not self.settings.windowLocked then
|
||||
-- Has to be self instead of "this" because it can be called from docked windows.
|
||||
if not self.dragInProgress then
|
||||
return
|
||||
end
|
||||
self.dragInProgress = false
|
||||
self.uiFrame:StopMovingOrSizing()
|
||||
local left, top = self:ReleaseDragOutline()
|
||||
if left and top then
|
||||
-- Move the real window once, to where the outline was dropped.
|
||||
self.uiFrame:ClearAllPoints()
|
||||
self.uiFrame:SetPoint("TOPLEFT", _G.UIParent, "BOTTOMLEFT", left, top)
|
||||
else
|
||||
self.uiFrame:StopMovingOrSizing()
|
||||
end
|
||||
self:FixSettingsMenuPosition()
|
||||
self:SaveWindowPosition()
|
||||
-- If the window was dropped (nearly) off the screen, bring it back right away
|
||||
|
||||
Reference in New Issue
Block a user