@@ -11,14 +11,11 @@ _G.DialogKeyNS = ns -- expose ourselves to the world :)
1111local DialogKey = LibStub (" AceAddon-3.0" ):NewAddon (name , " AceEvent-3.0" , " AceHook-3.0" )
1212ns .Core = DialogKey
1313
14- local defaultPopupBlacklist = { -- If a confirmation dialog contains one of these strings, don't accept it
15- -- "Are you sure you want to go back to Shal'Aran?", -- Withered Training Scenario -- why exclude this?
16- -- "Are you sure you want to return to your current timeline?", -- Leave Chromie Time -- why exclude this?
17- -- "You will be removed from Timewalking Campaigns once you use this scroll.", -- "A New Adventure Awaits" Chromie Time scroll -- why exclude this?
14+ local defaultPopupBlacklist = { -- If a popup dialog contains one of these strings, don't click it
1815 AREA_SPIRIT_HEAL , -- Prevents cancelling the resurrection
1916 TOO_MANY_LUA_ERRORS ,
20- END_BOUND_TRADEABLE ,
21- ADDON_ACTION_FORBIDDEN ,
17+ END_BOUND_TRADEABLE , -- Probably quite reasonable to make the user click on this one
18+ ADDON_ACTION_FORBIDDEN , -- Don't disable and reload UI on errors
2219}
2320
2421local function callFrameMethod (frame , method , ...)
@@ -46,11 +43,6 @@ function DialogKey:GetFrameByName(frameName)
4643end
4744
4845DialogKey .playerChoiceButtons = {}
49- DialogKey .handledCustomFrames = {}
50- DialogKey .ignoreCheckCustomFrames = false
51- DialogKey .proxyFrames = {}
52- DialogKey .proxyFrameNamePrefix = " DialogKeyNumy_ProxyFrame_"
53- DialogKey .proxyFrameIndex = 0
5446DialogKey .activeOverrideBindings = {}
5547
5648function DialogKey :OnInitialize ()
@@ -68,19 +60,7 @@ function DialogKey:OnInitialize()
6860 self :RegisterEvent (" PLAYER_REGEN_DISABLED" )
6961 self :RegisterEvent (" ADDON_LOADED" )
7062
71- self :SecureHook (" CreateFrame" , " CheckCustomFrames" )
72-
73- self .frame = CreateFrame (" Frame" , nil , UIParent )
74- self .frame :SetScript (" OnKeyDown" , function (_ , ...) self :HandleKey (... ) end )
75- self .frame :SetFrameStrata (" TOOLTIP" ) -- Ensure we receive keyboard events first
76- self .frame :EnableKeyboard (true )
77- self .frame :SetPropagateKeyboardInput (true )
78-
79- for i = 1 , 4 do
80- self :SecureHookScript (_G [" StaticPopup" .. i ], " OnShow" , " OnPopupShow" )
81- self :SecureHookScript (_G [" StaticPopup" .. i ], " OnUpdate" , " OnPopupUpdate" )
82- self :SecureHookScript (_G [" StaticPopup" .. i ], " OnHide" , " OnPopupHide" )
83- end
63+ self :InitMainProxyFrame ()
8464
8565 self :SecureHook (" QuestInfoItem_OnClick" , " SelectItemReward" )
8666 self :SecureHook (GossipFrame , " Update" , " OnGossipFrameUpdate" )
@@ -109,7 +89,6 @@ function DialogKey:ADDON_LOADED(_, addon)
10989 self :SecureHook (PlayerChoiceFrame , " TryShow" , " OnPlayerChoiceShow" )
11090 self :SecureHookScript (PlayerChoiceFrame , " OnHide" , " OnPlayerChoiceHide" )
11191 end
112- self :CheckCustomFrames ()
11392end
11493
11594function DialogKey :QUEST_COMPLETE ()
@@ -142,6 +121,31 @@ function DialogKey:InitGlowFrame()
142121 self .glowFrame .tex :SetColorTexture (1 ,1 ,0 ,0.5 )
143122end
144123
124+ function DialogKey :InitMainProxyFrame ()
125+ local frame = CreateFrame (" Button" , " DialogKey_Numy_MainClickProxyFrame" , UIParent , " InsecureActionButtonTemplate" )
126+ frame :RegisterForClicks (" AnyUp" , " AnyDown" )
127+ frame :SetAttribute (" type" , " click" )
128+ frame :SetAttribute (" typerelease" , " click" )
129+ frame :SetAttribute (" pressAndHoldAction" , " 1" )
130+ frame :SetScript (" PreClick" , function ()
131+ if InCombatLockdown () then return end
132+ self :ClearOverrideBindings (frame )
133+ local clickButton = frame :GetAttribute (" clickbutton" )
134+ self :Glow (clickButton )
135+ end )
136+ frame :HookScript (" OnClick" , function ()
137+ if InCombatLockdown () then return end
138+ frame :SetAttribute (" clickbutton" , nil )
139+ frame :SetPropagateKeyboardInput (true )
140+ end )
141+ frame :SetScript (" OnKeyDown" , function (_ , ...) self :HandleKey (... ) end )
142+ frame :SetFrameStrata (" TOOLTIP" ) -- Ensure we receive keyboard events first
143+ frame :EnableKeyboard (true )
144+ frame :SetPropagateKeyboardInput (true )
145+
146+ self .frame = frame
147+ end
148+
145149function DialogKey :OnPlayerChoiceShow ()
146150 if not self .db .handlePlayerChoice then return end
147151 local frame = PlayerChoiceFrame ;
@@ -181,7 +185,7 @@ function DialogKey:OnGossipFrameUpdate(gossipFrame)
181185
182186 local n = 1
183187 for _ , frame in scrollbox :EnumerateFrames () do
184- local data = frame .GetElementData and frame . GetElementData ()
188+ local data = frame .GetElementData and frame : GetElementData ()
185189 local tag
186190 if data .buttonType == GOSSIP_BUTTON_TYPE_OPTION then
187191 tag = " name"
@@ -195,7 +199,9 @@ function DialogKey:OnGossipFrameUpdate(gossipFrame)
195199 end
196200 if n > 10 then break end
197201 end
198- scrollbox :OnSizeChanged ()
202+ local oldScale = scrollbox :GetScale ()
203+ scrollbox :SetScale (oldScale + 0.002 ) -- trigger OnSizeChanged
204+ RunNextFrame (function () scrollbox :SetScale (oldScale ) end ) -- OnSizeChanged only fires if the size actually changed at the end of the frame
199205end
200206
201207--- @return StaticPopupTemplate | nil
244250
245251function DialogKey :ShouldIgnoreInput ()
246252 if InCombatLockdown () then return true end
247- self .frame :SetPropagateKeyboardInput (true )
248253
249254 if self .db .ignoreWithModifier and (IsShiftKeyDown () or IsControlKeyDown () or IsAltKeyDown ()) then return true end
250255 -- Ignore input while typing, unless at the Send Mail confirmation while typing into it!
@@ -358,165 +363,73 @@ function DialogKey:SetOverrideBindings(owner, targetName, keys)
358363 end
359364end
360365
361- function DialogKey :CheckCustomFrames ()
362- if self .ignoreCheckCustomFrames then return end
363- for frameName , _ in pairs (self .db .customFrames ) do
364- local frame = self :GetFrameByName (frameName )
365- if frame and not self .handledCustomFrames [frame ] then
366- self .handledCustomFrames [frame ] = frameName
367- self :SecureHookScript (frame , " OnShow" , " OnCustomFrameShow" )
368- self :SecureHookScript (frame , " OnHide" , " OnCustomFrameHide" )
369- if frame :IsVisible () then
370- self :OnCustomFrameShow (frame )
371- end
372- end
373- end
374- end
375-
376- --- @param frame Frame
377- --- @return Button , string
378- function DialogKey :AcquireProxyButton (frame )
379- local proxyButton = self .proxyFrames [frame ]
380- if not proxyButton then
381- self .proxyFrameIndex = self .proxyFrameIndex + 1
382- local proxyName = self .proxyFrameNamePrefix .. self .proxyFrameIndex
383- self .ignoreCheckCustomFrames = true
384- proxyButton = CreateFrame (" Button" , proxyName , nil , " SecureActionButtonTemplate" )
385- self .ignoreCheckCustomFrames = false
386- proxyButton :SetAttribute (" type" , " click" )
387- proxyButton :SetAttribute (" typerelease" , " click" )
388- proxyButton :SetAttribute (" clickbutton" , frame )
389- proxyButton :RegisterForClicks (" AnyUp" , " AnyDown" )
390- proxyButton :SetAttribute (" pressAndHoldAction" , " 1" )
391- proxyButton :HookScript (" OnClick" , function () self :Glow (frame ) end )
392- proxyButton .name = proxyName
393- proxyButton .target = frame
394- self .proxyFrames [frame ] = proxyButton
395- end
396- return proxyButton , proxyButton .name
397- end
398-
399- function DialogKey :OnCustomFrameShow (frame )
400- if InCombatLockdown () or not self .db .customFrames [self .handledCustomFrames [frame ]] then return end
401-
402- local proxyButton , proxyName = self :AcquireProxyButton (frame )
403-
404- self :SetOverrideBindings (proxyButton , proxyName , self .db .keys )
405- end
406-
407- function DialogKey :OnCustomFrameHide (frame )
366+ function DialogKey :SetClickbuttonBinding (frame , key )
408367 if InCombatLockdown () then return end
368+ self .frame :SetAttribute (" clickbutton" , frame )
369+ self :SetOverrideBindings (self .frame , self .frame :GetName (), {key })
409370
410- local proxyButton = self :AcquireProxyButton (frame )
411-
412- self :ClearOverrideBindings (proxyButton )
413- end
414-
415- DialogKey .checkOnUpdate = {}
416- --- @param popupFrame StaticPopupTemplate # One of the StaticPopup1-4 frames
417- function DialogKey :OnPopupShow (popupFrame )
418- -- Todo: consider supporting DialogKey.db.ignoreDisabledButtons option
419- -- right now disabled buttons *are* clicked, but clicking them does nothing (although the key press is still eaten regardless)
420- self .checkOnUpdate [popupFrame ] = false
421- -- only act if the popup is both visible, and the first visible one
422- if InCombatLockdown () or popupFrame ~= self :GetFirstVisiblePopup () then return end
423-
424- local button = self :GetPopupButton (popupFrame )
425- self :ClearOverrideBindings (popupFrame )
426- if button == false then
427- -- false means that the text is empty, and we should check again OnUpdate, for the text to be filled
428- self .checkOnUpdate [popupFrame ] = true
429- return
430- end
431- if not button then return end
432-
433- self :SetOverrideBindings (popupFrame , button :GetName (), self .db .keys )
434- end
435-
436- --- @param popupFrame StaticPopupTemplate # One of the StaticPopup1-4 frames
437- function DialogKey :OnPopupUpdate (popupFrame )
438- if not self .checkOnUpdate [popupFrame ] then return end
439-
440- self :OnPopupShow (popupFrame )
441- end
442-
443- --- @param popupFrame StaticPopupTemplate # One of the StaticPopup1-4 frames
444- function DialogKey :OnPopupHide (popupFrame )
445- if InCombatLockdown () then return end
446-
447- self :ClearOverrideBindings (popupFrame )
371+ -- just in case something goes horribly wrong, we do NOT want to get the user stuck in a situation where the keyboard stops working
372+ RunNextFrame (function () self :ClearOverrideBindings (self .frame ) end )
448373end
449374
450375function DialogKey :HandleKey (key )
451- if self :ShouldIgnoreInput () then return end
452-
376+ if not InCombatLockdown () then self .frame :SetPropagateKeyboardInput (true ) end
453377 local doAction = (key == self .db .keys [1 ] or key == self .db .keys [2 ])
454378 local keynum = doAction and 1 or tonumber (key )
455379 if key == " 0" then
456380 keynum = 10
457381 end
382+ if not doAction and not keynum then return end
383+ if self :ShouldIgnoreInput () then return end
458384 -- DialogKey pressed, interact with popups, accepts..
459385 if doAction then
460-
461- -- Click Popup - the actual click is performed via OverrideBindings
386+ -- Popups
462387 local popupFrame = self :GetFirstVisiblePopup ()
463388 local popupButton = popupFrame and self :GetPopupButton (popupFrame )
464389 if popupButton then
465- self .frame :SetPropagateKeyboardInput (true )
466- self :Glow (popupButton )
390+ self :SetClickbuttonBinding (popupButton , key )
467391 return
468392 end
469393
470394 -- Crafting Orders
471395 local craftingOrderFrame = self :GetFirstVisibleCraftingOrderFrame ()
472396 if craftingOrderFrame then
473- self .frame :SetPropagateKeyboardInput (false )
474- self :Glow (craftingOrderFrame )
475- craftingOrderFrame :Click ()
397+ self :SetClickbuttonBinding (craftingOrderFrame , key )
476398 return
477399 end
478400
479401 -- Custom Frames
480402 local customFrame = self :GetFirstVisibleCustomFrame ()
481403 if customFrame then
482- self . frame : SetPropagateKeyboardInput ( true )
404+ self : SetClickbuttonBinding ( customFrame , key )
483405 return
484406 end
485407
486408 -- Auction House
487409 if self .db .postAuctions and AuctionHouseFrame and AuctionHouseFrame :IsVisible () then
488410 if AuctionHouseFrame .displayMode == AuctionHouseFrameDisplayMode .CommoditiesSell then
489- self .frame :SetPropagateKeyboardInput (false )
490- self :Glow (AuctionHouseFrame .CommoditiesSellFrame .PostButton )
491- AuctionHouseFrame .CommoditiesSellFrame :PostItem ()
411+ self :SetClickbuttonBinding (AuctionHouseFrame .CommoditiesSellFrame .PostButton , key )
492412 return
493413 elseif AuctionHouseFrame .displayMode == AuctionHouseFrameDisplayMode .ItemSell then
494- self .frame :SetPropagateKeyboardInput (false )
495- self :Glow (AuctionHouseFrame .ItemSellFrame .PostButton )
496- AuctionHouseFrame .ItemSellFrame :PostItem ()
414+ self :SetClickbuttonBinding (AuctionHouseFrame .ItemSellFrame .PostButton , key )
497415 return
498416 end
499417 end
500418
501419 -- Complete Quest
502420 if QuestFrameProgressPanel :IsVisible () then
503- self .frame :SetPropagateKeyboardInput (false )
504421 if not QuestFrameCompleteButton :IsEnabled () and self .db .ignoreDisabledButtons then
505422 -- click "Cencel" button when "Complete" is disabled on progress panel
506- self :Glow (QuestFrameGoodbyeButton )
507- CloseQuest ()
423+ self :SetClickbuttonBinding (QuestFrameGoodbyeButton , key )
508424 else
509- self :Glow (QuestFrameCompleteButton )
510- CompleteQuest ()
425+ self :SetClickbuttonBinding (QuestFrameCompleteButton , key )
511426 end
512427 return
513428 -- Accept Quest
514429 elseif QuestFrameDetailPanel :IsVisible () then
515- self .frame :SetPropagateKeyboardInput (false )
516- self :Glow (QuestFrameAcceptButton )
517- AcceptQuest ()
430+ self :SetClickbuttonBinding (QuestFrameAcceptButton , key )
518431 return
519- -- Take Quest Reward
432+ -- Take Quest Reward - using manual API
520433 elseif QuestFrameRewardPanel :IsVisible () then
521434 self .frame :SetPropagateKeyboardInput (false )
522435 if self .itemChoice == - 1 and GetNumQuestChoices () > 1 then
@@ -533,9 +446,7 @@ function DialogKey:HandleKey(key)
533446 if self .db .handlePlayerChoice and next (self .playerChoiceButtons ) and (doAction or self .db .numKeysForPlayerChoice ) then
534447 local button = self .playerChoiceButtons [keynum ]
535448 if button then
536- self .frame :SetPropagateKeyboardInput (false )
537- self :Glow (button )
538- button :Click ()
449+ self :SetClickbuttonBinding (button , key )
539450 return
540451 end
541452 end
@@ -548,9 +459,7 @@ function DialogKey:HandleKey(key)
548459 if doAction and choice and choice .info and choice .info .questID and choice .activeQuestButton and not choice .info .isComplete and self .db .ignoreDisabledButtons then
549460 keynum = keynum + 1
550461 else
551- self .frame :SetPropagateKeyboardInput (false )
552- self :Glow (self .frames [keynum ])
553- self .frames [keynum ]:Click ()
462+ self :SetClickbuttonBinding (self .frames [keynum ], key )
554463 return
555464 end
556465 end
@@ -567,19 +476,17 @@ function DialogKey:HandleKey(key)
567476 keynum = 1
568477 end
569478 else
570- self .frame :SetPropagateKeyboardInput (false )
571- self :Glow (self .frames [keynum ])
572- self .frames [keynum ]:Click ()
479+ self :SetClickbuttonBinding (self .frames [keynum ], key )
573480 return
574481 end
575482 end
576483 end
577484
578485 -- QuestReward Frame (select item)
579486 if self .db .numKeysForQuestRewards and keynum and keynum <= GetNumQuestChoices () and QuestFrameRewardPanel :IsVisible () then
580- self .frame :SetPropagateKeyboardInput (false )
581487 self .itemChoice = keynum
582- GetClickFrame (" QuestInfoRewardsFrameQuestInfoItem" .. key ):Click ()
488+ self :SetClickbuttonBinding (GetClickFrame (" QuestInfoRewardsFrameQuestInfoItem" .. key ), key )
489+ return
583490 end
584491end
585492
@@ -684,10 +591,6 @@ function DialogKey:AddFrame(frameName)
684591 self .db .customFrames [frameName ] = true
685592 self :Glow (frame , 0.25 , true )
686593 self :print (" Added frame:" , frameName , " . Remove it again with /dialogkey remove; or in the options UI." )
687- self :CheckCustomFrames ()
688- if frame :IsVisible () then
689- self :OnCustomFrameShow (frame )
690- end
691594end
692595
693596function DialogKey :RemoveFrame (frameName )
@@ -706,7 +609,6 @@ function DialogKey:RemoveFrame(frameName)
706609 self .db .customFrames [frameName ] = nil
707610 self :Glow (frame , 0.25 , true )
708611 self :print (" Removed frame:" , frameName )
709- self :OnCustomFrameHide (frame )
710612end
711613
712614--- Returns the first clickable frame that has mouse focus
0 commit comments