Bagshui 1.6.5

- Changelog: release the Right/Top anchor UI-scale fix as 1.6.5
- Defer inventory redraws while a window is being dragged
- Cache class-callback event ids in QueueClassCallback (less garbage per BAG_UPDATE)
This commit is contained in:
2026-11-01 02:26:58 +00:00
parent 05fa6e3dd9
commit 36fc7acdeb
5 changed files with 61 additions and 4 deletions
+1 -1
View File
@@ -2,7 +2,7 @@
## Title: Bagshui
## Notes: |cffdb4e97Feng shui for your bags|r|nAll-in-one autosorting inventory replacement|nWoW 1.18.1 Clients fork - requires ClassicAPI
## Author: veechs | txtsd | WoW 1.18.1 Clients fork
## Version: 1.6.4
## Version: 1.6.5
## OptionalDeps: AtlasLoot, ItemRack, Outfitter, pfUI, !!!ClassicAPI
## RequiredMods: ClassicAPI.dll (https://github.com/brues-code/ClassicAPI)
## SavedVariables: BagshuiData
+6 -1
View File
@@ -1,10 +1,15 @@
# Bagshui Changelog
## Unreleased
## 1.6.5 - 2026-10-31
### Fixed
- A window anchored to the Right or Top jumped toward the left/bottom edge whenever it refreshed if the game's UI scale wasn't 1. The saved position is now calculated the same way it is restored.
- Possible hitch while dragging a window: a full redraw (for example from bag changes while looting or in combat) could run while the window was moving. Redraws are now held until the window is dropped, then run once. If the drop is missed, updates resume after 10 seconds.
### Performance
- Queuing an inventory update (on every bag change) no longer builds a new string each time, which cuts garbage collection work.
## 1.6.4 - 2026-10-27
+15 -2
View File
@@ -91,9 +91,22 @@ Bagshui:LoadComponent(
---@param arg2 any? Parameter for `Bagshui:QueueEvent()`.
---@param arg3 any? Parameter for `Bagshui:QueueEvent()`.
---@param arg4 any? Parameter for `Bagshui:QueueEvent()`.
-- Cache of event ids for class callbacks: classCallbackIds[classInstance][classFunction] = eventId.
-- QueueUpdate() runs on every BAG_UPDATE, so building the id string each time made garbage.
local classCallbackIds = setmetatable({}, { __mode = "k" })
function Bagshui:QueueClassCallback(classInstance, classFunction, delaySeconds, noReset, arg1, arg2, arg3, arg4)
-- Create a unique identifier for this event since it's not a predefined event string.
local eventId = tostring(classInstance) .. ":" .. tostring(classFunction)
-- Create (once) a unique identifier for this event since it's not a predefined event string.
local idsForInstance = classCallbackIds[classInstance]
if not idsForInstance then
idsForInstance = {}
classCallbackIds[classInstance] = idsForInstance
end
local eventId = idsForInstance[classFunction]
if not eventId then
eventId = tostring(classInstance) .. ":" .. tostring(classFunction)
idsForInstance[classFunction] = eventId
end
if self:QueueEvent(eventId, delaySeconds, noReset, arg1, arg2, arg3, arg4) then
-- When the event is successfully queued, store callback information so RaiseEvent()
-- knows to handle this as a class callback, not a standard event.
+9
View File
@@ -27,6 +27,15 @@ Bagshui:AddComponent(function()
return
end
-- Don't redraw while the window is being dragged. A full redraw (for example from a BAG_UPDATE
-- while looting in combat) resizes and re-lays out every button of a frame that is moving,
-- which shows up as a hitch. The update runs as soon as the window is dropped.
if self:IsDragInProgress() then
self.updateDeferredByDrag = true
self.updateDeferredByDragCascade = self.updateDeferredByDragCascade or cascade
return
end
-- Update is only needed if the window is visible.
if not self:Visible() and not self.forceCacheUpdate then
self.windowUpdateBlocked = false
+30
View File
@@ -1144,6 +1144,7 @@ Bagshui:AddComponent(function()
-- 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
self:RunUpdateDeferredByDrag()
self:ClearSearch()
self:CloseMenusAndClearFocuses()
self:ClearEditModeCursor()
@@ -1164,6 +1165,7 @@ Bagshui:AddComponent(function()
elseif not self.settings.windowLocked then
-- 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()
end
end
@@ -1182,6 +1184,34 @@ Bagshui:AddComponent(function()
-- instead of saving an unreachable position.
self:RescueWindow()
self:NotifySkinOfPositionChange()
-- Catch up on anything that changed while the window was moving.
self:RunUpdateDeferredByDrag()
if self.dockedInventory then
self.dockedInventory:RunUpdateDeferredByDrag()
end
end
end
--- Is this window (or the window it's docked to) being dragged right now?
--- Gives up after 10 seconds in case OnDragStop never fired (game hitch while releasing the mouse),
--- so updates can't stay paused.
---@return boolean
function Inventory:IsDragInProgress()
local owner = self.dockTo and Bagshui.components[self.dockTo] or self
return (
owner.dragInProgress
and owner.dragStartedAt
and (_G.GetTime() - owner.dragStartedAt) < 10
) and true or false
end
--- Run an `Update()` that was skipped because the window was being dragged.
function Inventory:RunUpdateDeferredByDrag()
if self.updateDeferredByDrag then
local cascade = self.updateDeferredByDragCascade
self.updateDeferredByDrag = false
self.updateDeferredByDragCascade = nil
self:QueueUpdate(nil, cascade)
end
end