Skip to content

Commit c6e4ba4

Browse files
committed
Added some more magic to handle other addons adding protected frames into regular frames, which would otherwise cause an error when trying to close them with ESC in combat
1 parent 6e1db17 commit c6e4ba4

File tree

1 file changed

+45
-20
lines changed

1 file changed

+45
-20
lines changed

NoAutoclose.lua

Lines changed: 45 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
local addonName, ns = ...;
22

3+
--- @type { [ string ] : { checkFit: boolean, checkFitExtraWidth: number, checkFitExtraHeight: number } }
34
ns.hookedFrames = {};
45
ns.ignore = {
56
BarberShopFrame = true, -- barbershop frame, better to allow it to hide the UI
@@ -12,6 +13,7 @@ ns.ignore = {
1213
local uiSpecialFrameBlacklist = {
1314
PlayerSpellsFrame = true, -- cannot be safely closed with UISpecialFrames
1415
};
16+
NoAutoClose = ns;
1517

1618
local UpdateScaleForFit = UpdateScaleForFit or UIPanelUpdateScaleForFit or FrameUtil.UpdateScaleForFit;
1719

@@ -39,6 +41,10 @@ EventUtil.ContinueOnAddOnLoaded(addonName, function()
3941
ns:Init();
4042
end);
4143

44+
ns.escHandlerMap = {};
45+
ns.handlerFrameIndex = 0;
46+
ns.sharedAttributesFrame = CreateFrame('Frame', nil, nil, 'SecureHandlerBaseTemplate');
47+
4248
function ns:ShouldNotManuallyShowHide(frame, interfaceActionWasBlocked)
4349
local name = frame.GetName and frame:GetName();
4450
if
@@ -201,37 +207,52 @@ function ns:PLAYER_REGEN_ENABLED()
201207
wipe(self.combatLockdownQueue);
202208
end
203209

204-
local escHandlerMap = {};
205-
local handlerFrameIndex = 0;
206-
local sharedAttributesFrame = CreateFrame('Frame', nil, nil, 'SecureHandlerBaseTemplate');
207-
function ns:ConfigureSecureEscHandler(frame, alwaysSetBindinOnShow)
210+
function ns:PLAYER_REGEN_DISABLED()
211+
-- if any frame has become protected since it was last shown, we need to configure the secure esc handler
212+
--
213+
for frameName, _ in pairs(self.hookedFrames) do
214+
local frame = _G[frameName];
215+
if frame and frame.IsProtected and frame:IsProtected() then
216+
if not self.escHandlerMap[frame] then
217+
self:ConfigureSecureEscHandler(frame, false, true);
218+
end
219+
end
220+
end
221+
end
222+
223+
local function escHandlerOnEvent(handlerFrame, event)
224+
if event == 'PLAYER_REGEN_ENABLED' and not handlerFrame:GetAttribute('alwaysSetBindingOnShow') then
225+
ClearOverrideBindings(handlerFrame);
226+
elseif event == 'PLAYER_REGEN_DISABLED' and handlerFrame.panel:IsVisible() then
227+
SetOverrideBindingClick(handlerFrame, true, 'ESCAPE', handlerFrame.name);
228+
end
229+
end
230+
231+
--- @param frame Frame
232+
--- @param alwaysSetBindingOnShow boolean # if true, the ESC binding will always be set when the frame is shown, regardless of combat state
233+
--- @param callRegenDisabledCode boolean? # if true, the PLAYER_REGEN_DISABLED event will be called immediately
234+
function ns:ConfigureSecureEscHandler(frame, alwaysSetBindingOnShow, callRegenDisabledCode)
208235
--[[
209236
Since the UIPanel system no longer taintlessly hides protected panels, we need to create a secure handler, which will
210237
configure a temporary keybinding for ESC, to hide the panel. Once we leave combat, we unbind it again, to go back to normal.
211238
The downside of this approach, is that protected frames will close 1 by 1, and that hiding the frames takes priority over e.g. canceling spell casting.
212239
--]]
240+
if self.escHandlerMap[frame] then return; end
213241

214-
if escHandlerMap[frame] then return; end
215-
handlerFrameIndex = handlerFrameIndex + 1;
216-
local name = 'Numy_NoAutoClose_SecureEscapeHandlerFrame' .. handlerFrameIndex;
242+
self.handlerFrameIndex = self.handlerFrameIndex + 1;
243+
local name = 'Numy_NoAutoClose_SecureEscapeHandlerFrame' .. self.handlerFrameIndex;
217244
local escHandler = CreateFrame('Button', name, frame, 'SecureHandlerShowHideTemplate,SecureHandlerClickTemplate');
218-
escHandlerMap[frame] = escHandler;
245+
self.escHandlerMap[frame] = escHandler;
219246

220247
escHandler.name = name;
221248
escHandler.panel = frame;
222249
escHandler:SetFrameRef('panel', frame);
223250
escHandler:SetFrameRef('UIParent', UIParent);
224-
escHandler:SetFrameRef('sharedAttributesFrame', sharedAttributesFrame);
251+
escHandler:SetFrameRef('sharedAttributesFrame', self.sharedAttributesFrame);
225252
escHandler:RegisterEvent('PLAYER_REGEN_ENABLED');
226253
escHandler:RegisterEvent('PLAYER_REGEN_DISABLED');
227-
escHandler:HookScript('OnEvent', function(handlerFrame, event)
228-
if event == 'PLAYER_REGEN_ENABLED' then
229-
ClearOverrideBindings(handlerFrame);
230-
elseif event == 'PLAYER_REGEN_DISABLED' and frame:IsVisible() then
231-
SetOverrideBindingClick(handlerFrame, true, 'ESCAPE', handlerFrame.name);
232-
end
233-
end);
234-
escHandler:SetAttribute('alwaysSetBindingOnShow', alwaysSetBindinOnShow);
254+
escHandler:HookScript('OnEvent', escHandlerOnEvent);
255+
escHandler:SetAttribute('alwaysSetBindingOnShow', alwaysSetBindingOnShow);
235256
escHandler:SetAttribute('_onclick', [[
236257
self:ClearBindings(); -- clear the bindings, just in case something is preventing the _onhide from firing
237258
local panel = self:GetFrameRef('panel');
@@ -257,6 +278,9 @@ function ns:ConfigureSecureEscHandler(frame, alwaysSetBindinOnShow)
257278
end
258279
end
259280
]]);
281+
if callRegenDisabledCode then
282+
escHandlerOnEvent(escHandler, 'PLAYER_REGEN_DISABLED');
283+
end
260284
end
261285

262286
function ns:ADDON_LOADED()
@@ -312,6 +336,7 @@ function ns:Init()
312336
self.eventFrame:RegisterEvent('ADDON_LOADED');
313337
self.eventFrame:RegisterEvent('PLAYER_INTERACTION_MANAGER_FRAME_SHOW');
314338
self.eventFrame:RegisterEvent('PLAYER_INTERACTION_MANAGER_FRAME_HIDE');
339+
self.eventFrame:RegisterEvent('PLAYER_REGEN_DISABLED');
315340

316341
self.combatLockdownQueue = {};
317342

@@ -334,9 +359,9 @@ function ns:initOptions()
334359
end
335360
end
336361
local function updatePositionAttributes(anchor, x, y)
337-
sharedAttributesFrame:SetAttribute('anchor', anchor);
338-
sharedAttributesFrame:SetAttribute('x', x);
339-
sharedAttributesFrame:SetAttribute('y', y);
362+
self.sharedAttributesFrame:SetAttribute('anchor', anchor);
363+
self.sharedAttributesFrame:SetAttribute('x', x);
364+
self.sharedAttributesFrame:SetAttribute('y', y);
340365
end
341366

342367
local panel = CreateFrame('Frame');

0 commit comments

Comments
 (0)