11local addonName , ns = ... ;
22
3+ --- @type { [ string ] : { checkFit : boolean , checkFitExtraWidth : number , checkFitExtraHeight : number } }
34ns .hookedFrames = {};
45ns .ignore = {
56 BarberShopFrame = true , -- barbershop frame, better to allow it to hide the UI
@@ -12,6 +13,7 @@ ns.ignore = {
1213local uiSpecialFrameBlacklist = {
1314 PlayerSpellsFrame = true , -- cannot be safely closed with UISpecialFrames
1415};
16+ NoAutoClose = ns ;
1517
1618local UpdateScaleForFit = UpdateScaleForFit or UIPanelUpdateScaleForFit or FrameUtil .UpdateScaleForFit ;
1719
@@ -39,6 +41,10 @@ EventUtil.ContinueOnAddOnLoaded(addonName, function()
3941 ns :Init ();
4042end );
4143
44+ ns .escHandlerMap = {};
45+ ns .handlerFrameIndex = 0 ;
46+ ns .sharedAttributesFrame = CreateFrame (' Frame' , nil , nil , ' SecureHandlerBaseTemplate' );
47+
4248function 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 );
202208end
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
260284end
261285
262286function 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