SecureStateDriver is a mechanism that allows secure handlers to register to be notified when conditions that are expressible using macro conditionals change. The handler can then respond by executing a snippet in the restricted environment, allowing (restricted) addon code to alter protected values while in combat.
The implementation is included as part of FrameXML in FrameXML/SecureStateDriver.lua. Conditionals are generally evaluated every 0.2 seconds, and in response to events guaranteed to alter some secure conditionals.
There are two functions provided by the Secure State Driver API: RegisterUnitWatch is the unit-frame special case, and RegisterStateDriver is the generic implementation.
RegisterStateDriver(frame, stateid, conditional)
- Is the generic state driver -- you can register to be notified when an arbitrary macro conditional evaluates to a different values. Updates are delivered via attributes; handle OnAttributeChanged or use SecureHandlerStateTemplate with a corresponding snippet to respond from a restricted environment.
- Frame-derived widget - notifications will be delivered to this frame.
- String - an arbitrary identifier string for this conditional (coerced into lower case), or "visibility". The latter is a special state -- rather than delivering an update through attribute changes, it shows and hides the frame when the conditional evaluates to "show" or "hide" respectively.
- String - macro conditional parsable by SecureCmdOptionParse. The value this conditional evaluates to will be set as the value of the "state-stateid" attribute on the frame.
- Assists in controlling unit frames -- can either show/hide the frame based on whether its unit exists; or deliver that information via a state attribute.
- Frame-derived widget - The frame to be shown/hidden/notified when its unit exists / does not exist.
- Boolean - if true, the "state-unitexists" attribute will be set to a boolean value denoting whether the unit exists; if false, the frame will be shown if its unit exists, and hidden if it does not.
Showing/hiding a unit frame
local frame = CreateFrame("BUTTON", "MyParty1", UIParent, "SecureUnitButtonTemplate"); frame:SetAttribute("unit", "party1"); frame:SetWidth(50); frame:SetHeight(50); frame:SetPoint("CENTER"); local tex = frame:CreateTexture(); tex:SetAllPoints(); tex:SetTexture(1,0,0); RegisterUnitWatch(frame);
The snippet above will display a clickable unit frame for the "party1" unit (consisting solely of a red square in the center of your screen) only when one exists.
Responding to custom states
local frame = CreateFrame("FRAME", "MyStatefulFrame", UIParent, "SecureHandlerStateTemplate"); frame:SetAttribute("_onstate-petstate", [[ -- arguments: self, stateid, newstate if newstate == "nopet" then print("Where are you, kitty?"); elseif newstate == "mypet" then print("Oh hai, kitty!"); elseif newstate == "mcpet" then print("Curse your sudden but inevitable betrayal, kitty!"); -- Your pet is hostile to you. end ]]); RegisterStateDriver(frame, "petstate", "[target=pet,noexists] nopet;" .. " [target=pet,help] mypet; [target=pet,harm] mcpet");
The snippet above will print text to your chat frame when the state of your pet changes.