Thread Tools Display Modes
04-03-10, 03:51 AM   #1
corveroth
A Fallenroot Satyr
AddOn Author - Click to view addons
Join Date: Apr 2006
Posts: 29
Hiding Secure Frames

I've recently turned up a bug in my addon CRAP. CRAP functions as a replacement for Blizzard's companions UI (the Companions and Mounts tabs of the Pets frame), and to get my setup into place, I found it most convenient to simply hide Blizzard's bits and pieces (the PetPaperDollFrameCompanionFrame) and hook the OnClick scripts for the Mounts/Pets tab buttons.

The PetPaperDollFrameCompanionFrame is implicitly protected by the twelve CompanionButtonNs. In order to keep those and the PPDFCF hidden, I (along with the help of some kind folks over at WowAce) came up with this snippet, which seemed to keep everything hidden nicely.
Code:
for i=1,12 do
    SecureHandlerWrapScript(_G["CompanionButton"..i], "OnShow", _G["CompanionButton"..i],
        [[ self:Hide() self:GetParent():Hide() ]])
end
And I just recently discovered that it's not quite working perfectly. First, this is the snippet that manages hooking the tab buttons:
Code:
-- "Pet" button
PetPaperDollFrameTab1:HookScript("OnClick", function(self)
    FUR:Hide(); -- FUR is the frame that I use for listing companions/mounts
end)

-- "Companions" button
PetPaperDollFrameTab2:HookScript("OnClick", function(self)
    COMPANIONTYPE = "CRITTER"
    sortbutton:Disable()
    scrollbar:SetMinMaxValues(0, math.max(0, GetNumCompanions(COMPANIONTYPE) - NUMROWS))
    scrollbar:SetValue(0)
    Show(); -- This just does a bit of background work before calling FUR:Show()
end)

-- "Mounts" button
PetPaperDollFrameTab3:HookScript("OnClick", function(self)
    COMPANIONTYPE = "MOUNT"
    sortbutton:Enable()
    scrollbar:SetMinMaxValues(0, math.max(0, GetNumCompanions(COMPANIONTYPE) - NUMROWS))
    scrollbar:SetValue(0)
    Show();
end)
When my frame first shows, the script on CompanionButton1 fires. However, it seems to die at that point - if you click on Tab2 or Tab3, the script on Button2 (and only Button2) will fire. So on and so forth until after twelve clicks on Tab2 and/or Tab3, there are no more CompanionButtons firing their script and the Blizzard UI shows up underneath mine. Interestingly, only the PPDFCF shows up - the CompanionButtons remain hidden.

So, what the hell am I doing wrong, what have I missed? I've got a hunch this has something to do with tainting issues, simply because secure frames are involved, and quite honestly, I'm lost when it comes to secure handlers/headers (and I'm not really sure what those terms are or mean). I'd appreciate any guidance.
  Reply With Quote
04-03-10, 06:45 AM   #2
nightcracker
A Molten Giant
 
nightcracker's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2009
Posts: 716
Fairly simple: use the same handler script for the blizzard companion UI frame.
__________________
Three things are certain,
Death, taxes and site not found,
You, victim of one.
  Reply With Quote
04-03-10, 11:15 AM   #3
corveroth
A Fallenroot Satyr
AddOn Author - Click to view addons
Join Date: Apr 2006
Posts: 29
That was my initial approach, but the PPDFCF isn't itself secure, so I can't use SecureHandlerWrapScript on it. It's implicitly protected by its children, which is why the script I was wrapping on them calls self:GetParent():Hide().
  Reply With Quote
04-03-10, 01:07 PM   #4
Slakah
A Molten Giant
 
Slakah's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2007
Posts: 863
try replacing:
Code:
for i=1,12 do
    SecureHandlerWrapScript(_G["CompanionButton"..i], "OnShow", _G["CompanionButton"..i],
        [[ self:Hide() self:GetParent():Hide() ]])
end
with just

Code:
CompanionButton1:WrapScript("OnShow", [[self:GetParent():Hide()]])
  Reply With Quote
04-04-10, 01:32 AM   #5
corveroth
A Fallenroot Satyr
AddOn Author - Click to view addons
Join Date: Apr 2006
Posts: 29
Originally Posted by Slakah View Post
try replacing:
Code:
for i=1,12 do
    SecureHandlerWrapScript(_G["CompanionButton"..i], "OnShow", _G["CompanionButton"..i],
        [[ self:Hide() self:GetParent():Hide() ]])
end
with just

Code:
CompanionButton1:WrapScript("OnShow", [[self:GetParent():Hide()]])
*blink* Well, that works. And from a bit of tinkering, the problem was that I was hiding the button and then its parent... how did that even work in the first place?

Thank you regardless =) If I could ask one more favor, could you describe "headers" and "handlers" in your own terms? I've read over Iriel's guide several times, but some fresh wording might help me wrap my mind around matters better.
  Reply With Quote
04-04-10, 04:41 AM   #6
Foxlit
A Warpwood Thunder Caller
AddOn Author - Click to view addons
Join Date: Nov 2006
Posts: 91
Originally Posted by corveroth View Post
Thank you regardless =) If I could ask one more favor, could you describe "headers" and "handlers" in your own terms? I've read over Iriel's guide several times, but some fresh wording might help me wrap my mind around matters better.
http://www.wowwiki.com/SecureHandlers should work.

Personally, I think the easier way to hide a protected frame is to reparent it to a hidden frame rather than mucking about with secure handlers:
Code:
local jail = CreateFrame("Frame"); jail:Hide();
for i=1,12 do
 _G["CompanionButton"..i]:SetParent(jail);
end
As long as nothing attempts to change the parent again (and, in most cases, nothing will), your frame will remain hidden without any incurring additional per-Show() costs.
__________________
... and you do get used to it, after a while.
  Reply With Quote
04-04-10, 02:19 PM   #7
corveroth
A Fallenroot Satyr
AddOn Author - Click to view addons
Join Date: Apr 2006
Posts: 29
Originally Posted by Foxlit View Post
As long as nothing attempts to change the parent again (and, in most cases, nothing will), your frame will remain hidden without any incurring additional per-Show() costs.
But, won't that taint the CompanionButtons?
  Reply With Quote
04-04-10, 05:15 PM   #8
Grimsin
A Molten Giant
 
Grimsin's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2006
Posts: 990
What i would like to know is how to go about making a button to hide/show a secure frame like the bag bar or an action button bar.
__________________
"Are we there yet?"

GrimUI
[SIGPIC][/SIGPIC]
  Reply With Quote
04-04-10, 05:22 PM   #9
Foxlit
A Warpwood Thunder Caller
AddOn Author - Click to view addons
Join Date: Nov 2006
Posts: 91
Originally Posted by corveroth View Post
But, won't that taint the CompanionButtons?
Nope, it should be fine -- changing a frame's parent does not taint the frame. The only limitation is that you would have to call SetParent out of combat, but you can easily achieve that while your addon is loading.

Originally Posted by Grimsin View Post
What i would like to know is how to go about making a button to hide/show a secure frame like the bag bar or an action button bar.
That matches the example on http://www.wowwiki.com/SecureHandlerClickTemplate almost exactly. Summarized, the answer is: you use a securehandler snippet to do it.
__________________
... and you do get used to it, after a while.
  Reply With Quote
04-04-10, 07:21 PM   #10
Grimsin
A Molten Giant
 
Grimsin's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2006
Posts: 990
yea except who ever wrote that assumed you knew a lot more then i do about how that works.......

i need it more simple then what was posted there.
__________________
"Are we there yet?"

GrimUI
[SIGPIC][/SIGPIC]
  Reply With Quote
04-04-10, 07:41 PM   #11
corveroth
A Fallenroot Satyr
AddOn Author - Click to view addons
Join Date: Apr 2006
Posts: 29
I know how you feel; much of the literature on secure frames is a bit more technical than much of the rest of the WoW-related documentation lying around. Not that technical is bad, but it's less friendly to relative beginners. I think I can explain this, though.

First, a frame is created, pretty standard stuff - fourth argument signifies that it inherits the SecureHandlerClickTemplate. The next command sets a script to execute when the frame is clicked on. That script is provided as a string (using the [=[ and ]=] delimiters here, so that quotation marks can be used inside without having to escape them). Presumably, the reason that the "onclick" function is provided as a string (instead of, say, an anonymous function) is to prevent it from violating any of the restrictions on secure frames - some part of the UI will go through the string and check to make sure it doesn't contain any banned keywords, etc. The script provided is mostly straightforward.

SetFrameRef appears to take two arguments, a name (string) and a reference to a frame. The reason it's necessary is that normally, within the onclick script, "MyClickButton" can't just access other frames at will. SetFrameRef essentially gives them aliases ("frame1" and "frame2") by which they can be referred to via GetFrameRef within the script.

That's the explanation I can give, and I wish I understood why parts of this architecture are there. Someone more knowledgeable is welcome to correct me.
Code:
local frame = CreateFrame("BUTTON", "MyClickButton", UIParent, "SecureHandlerClickTemplate");
frame:SetAttribute("_onclick", [=[
 local show, i, ref = button == "LeftButton", 2, self:GetFrameRef("frame1");
 while ref do
  if show then ref:Show(); else ref:Hide(); end
  i, ref = i + 1, self:GetFrameRef("frame" .. i);
 end
]=]); 
frame:RegisterForClicks("AnyUp");
frame:SetFrameRef("frame1", PlayerFrame);
frame:SetFrameRef("frame2", TargetFrame);
-- ...
  Reply With Quote
04-04-10, 07:54 PM   #12
Grimsin
A Molten Giant
 
Grimsin's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2006
Posts: 990
So what would i do to the wow wiki method to seperate the clicks? so that i have toggle with both left button for one frame and right button for the other?

im confused. I got it to work for the most part just not sure how to separate the clicks now...


I tried to do the right button in secure code and the left buton with a setscript lol i take it you can not do setattrib onclick and setscript onclicks on the same frame?

th is is what i have so far

lua Code:
  1. BackpackButton:SetAttribute("_onclick", [=[
  2.  local show, i, ref = button == "RightButton", 2, self:GetFrameRef("frame1");
  3.  while ref do
  4.   if show and ref:IsVisible() then ref:Hide(); else ref:Show(); end
  5.   i, ref = i + 1, self:GetFrameRef("frame" .. i);
  6.  end
  7. ]=]);
  8. BackpackButton:RegisterForClicks('LeftButtonUp', 'RightButtonUp');
  9. BackpackButton:SetFrameRef("frame1", GrimBackpackBar);
  10.  
  11. --BackpackButton:SetScript("OnClick", function(self, button)
  12. --  if button == 'LeftButton' then
  13. --      Baggins:ToggleBackpack()
  14. --  end
  15. --end)
__________________
"Are we there yet?"

GrimUI
[SIGPIC][/SIGPIC]
  Reply With Quote
04-04-10, 08:20 PM   #13
Slakah
A Molten Giant
 
Slakah's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2007
Posts: 863
I'm guessing it's because when you call :SetScript("OnClick", <blah>) your overwriting the secure _onclick which uses the :SetScript("OnClick") thing.

lua Code:
  1. BackpackButton:SetFrameRef("GrimBackpackBar", GrimBackpackBar)
  2. BackpackButton:Execute([[GrimBackpackBar = self:GetFrameRef("GrimBackpackBar")]])
  3. BackpackButton:SetAttribute("_onclick", [=[
  4.     if button == "RightButton" then
  5.         if GrimBackpackBar:IsShown() then
  6.             GrimBackpackBar:Hide()
  7.         else
  8.             GrimBackpackBar:Show()
  9.         end
  10.     end
  11. ]=])
  12. BackpackButton:RegisterForClicks('LeftButtonUp', 'RightButtonUp')
  13.  
  14.  
  15. BackpackButton:HookScript("OnClick", function(self, button) --Hook script because we don't want to overwrite _onclick
  16.     if button == "LeftButton" then
  17.         Baggins:ToggleBackpack()
  18.     end
  19. end)

I could be wrong as it's been a while since I read the code in FrameXML.
  Reply With Quote
04-04-10, 09:04 PM   #14
Grimsin
A Molten Giant
 
Grimsin's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2006
Posts: 990
i have gotten this to work save for one flaw. On left click the bagbar toggles as well as the baggins frame. No idea why. Right click toggles it to.

lua Code:
  1. BackpackButton:SetAttribute("_onclick", [=[
  2.     local ref = self:GetFrameRef("frame1");
  3.     if button == "RightButton" and ref:IsVisible() then ref:Hide(); else ref:Show(); end
  4. ]=]);
  5. BackpackButton:RegisterForClicks('LeftButtonUp', 'RightButtonUp');
  6. BackpackButton:SetFrameRef("frame1", GrimBackpackBar);
  7.  
  8.  
  9. BackpackButton:HookScript("OnClick", function(self, button) --Hook script because we don't want to overwrite _onclick
  10.     if button == "LeftButton" then
  11.         Baggins:ToggleBackpack()
  12.     end
  13. end)
__________________
"Are we there yet?"

GrimUI
[SIGPIC][/SIGPIC]
  Reply With Quote
04-04-10, 09:19 PM   #15
Grimsin
A Molten Giant
 
Grimsin's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2006
Posts: 990
figured it out thanks everyone!
__________________
"Are we there yet?"

GrimUI
[SIGPIC][/SIGPIC]
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Hiding Secure Frames


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off