After talking with CRB_Moenzuel, I’m starting to understand how the client’s window manager works, and how Addons can use it for their own purpose to track the windows of the Addon.

There’s a few steps that someone needs to implement in order to properly use the WindowManager, but one you understand the basics, it becomes a pretty powerful tool.

WindowManagementReady Event

This is the key event that an Addon needs to be listening for. It gets raised by the client once the WindowManager is ready to take requests for handling your windows. Most Addons, including those by Carbine register for this event in their OnDocumentReady call.


function MyAddon:OnDocumentReady()
  Apollo.RegisterEventHandler("WindowManagementReady", "OnWindowManagementReady", self)

function MyAddon:OnWindowManagementReady()
  Event_FireGenericEvent("WindowManagementRegister", {strName = "MyAddon", nSaveVersion = 1})
  Event_FireGenericEvent("WindowManagementAdd", { wnd = self.wndMain, strName = "MyAddon", nSaveVersion = 1})

The above example register our function to handle the asynchronous callback of the WindowManager and uses the opportunity to :

  1. Register our Addon in the WindowManager
  2. Register our Addon’s main window as the window to track.

The ideal situation as explained by CRB_Moenzuel:

Ideally Register happens in MyAddon:OnWindowManagementReady and Add happens when the window is created right before being shown. You also want to call MyAddon:OnWindowManagementReady after registering for the event to cover the case you are loading after the window management addon has loaded

Taking the above into account, your code will most likely look more like this:

-- Start loading the XML and continue when it's done.
function MyAddon:OnLoad()
   self.xmlDoc = XmlDoc.CreateFromFile("MyAddon.xml")
   self.xmlDoc:RegisterCallback("OnDocumentReady", self)

-- XML is loaded, start building our window and event handlers
function MyAddon:OnDocumentReady()
  if self.xmlDoc == nil then

  Apollo.RegisterEventHandler("WindowManagementUpdate", "OnWindowManagementUpdate", self)

  -- Do all stuff you need, including making your windows
  self.wndMain = Apollo.LoadForm(self.xmlDoc, "MainForm", "Window", self)

  Apollo.RegisterEventHandler("WindowManagementReady", "OnWindowManagementReady", self)
  self:OnWindowManagementReady() -- to beat the racing condition

-- This either gets called by the Windowmanager when the event is raised
-- or our Addon does it itself.
-- Either way, the window manager will handle duplicates.
function MyAddon:OnWindowManagementReady()
  Event_FireGenericEvent("WindowManagementRegister", {wnd = self.wndMain, strName = "MyAddon" })
  Event_FireGenericEvent("WindowManagementAdd", {wnd = self.wndMain, strName = "MyAddon"})

WindowManagementUpdate Event

This is a key event that get’s raised by the EventManager every time one of the following actions happens:

  • The tracked window is being moved by the User.
  • The user clicks the reset button of inside the Positioning window of the Interface Options

As with the WindowManagementReady event, the callback needs to be registered in the OnDocumentReady function of your Addon.

function MyAddon:OnDocumentReady()
  Apollo.RegisterEventHandler("WindowManagementUpdate", "OnWindowManagementUpdate", self)

function MyAddon:OnWindowManagementUpdate(tSettings)
  // do stuff

The callback of the event comes with a parameter called tSettings. This parameter is a table with the following properties:

  • tSettings.wnd : The window that has been moved or reset.
  • tSettings.bHasMoved : A boolean indicating whether the window was moved.
  • tSettings.strName : The name of the Window that has been moved or reset.
  • tSettings.bDefaultMoveable : A boolean indicating whether the window was moveable by default. (DEPRECATED?)
  • tSettings.bMoveable : A boolean indicating whether the window is moveable.
  • tSettings.bDefaultRequireMetaKeyToMove : A boolean indicating whether the window requires CTRL to move (DEPRECATED?)
  • tSettings.bRequireMetaKeyToMove : A boolean indicating whether the windows requires CTRL to move.
  • tSettings.tCurrentLoc : table containing the current location of the Window.
  • tSettings.nPosX : The x-coordinate of the Window
  • tSettings.nPosY : The y-coordinate of the Window

While you’re normally not required to do anything specific, you can use the available information to make your Addon respond to certain conditions.

WindowManagementRemove Event

This event needs to be raised by your Addon if you wish to remove it from the WindowManager. The event takes a single table containing the name of the window to be removed.

Event_FireGenericEvent("WindowManagementRemove", {strName = "MyAddon"})

Important:  You should call this when creating and adding a Window and later on destroying the window. Otherwise the manager keeps a reference to a window that no longer exists.