////////////////////////////////////////////////////////////////////////////////
//
//  Licensed to the Apache Software Foundation (ASF) under one or more
//  contributor license agreements.  See the NOTICE file distributed with
//  this work for additional information regarding copyright ownership.
//  The ASF licenses this file to You under the Apache License, Version 2.0
//  (the "License"); you may not use this file except in compliance with
//  the License.  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////

package mx.managers
{

import flash.accessibility.Accessibility;
import flash.accessibility.AccessibilityProperties;
import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.display.Graphics;
import flash.display.InteractiveObject;
import flash.display.Sprite;
import flash.display.Stage;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.system.Capabilities;

import mx.automation.IAutomationObject;
import mx.core.FlexGlobals;
import mx.core.FlexSprite;
import mx.core.FlexVersion;
import mx.core.IChildList;
import mx.core.IFlexDisplayObject;
import mx.core.IFlexModule;
import mx.core.IFlexModuleFactory;
import mx.core.IInvalidating;
import mx.core.ILayoutDirectionElement;
import mx.core.IUIComponent;
import mx.core.LayoutDirection;
import mx.core.UIComponent;
import mx.core.UIComponentGlobals;
import mx.core.mx_internal;
import mx.effects.Blur;
import mx.effects.Fade;
import mx.effects.IEffect;
import mx.events.DynamicEvent;
import mx.events.EffectEvent;
import mx.events.FlexEvent;
import mx.events.FlexMouseEvent;
import mx.events.Request;
import mx.managers.systemClasses.ActiveWindowManager;
import mx.styles.IStyleClient;

use namespace mx_internal;

[ExcludeClass]

/**
 *  @private
 *  The PopUpManager singleton class creates new top-level windows and
 *  places or removes those windows from the layer on top of all other
 *  visible windows.  See the SystemManager for a description of the layering.
 *  It is used for popup dialogs, menus, and dropdowns in the ComboBox control 
 *  and in similar components.
 * 
 *  <p>The PopUpManager also provides modality, so that windows below the popup
 *  cannot receive mouse events, and also provides an event if the user clicks
 *  the mouse outside the window so the developer can choose to dismiss
 *  the window or warn the user.</p>
 * 
 *  @see PopUpManagerChildList
 */
public class PopUpManagerImpl extends EventDispatcher implements IPopUpManager
{
    include "../core/Version.as";

    //--------------------------------------------------------------------------
    //
    //  Class variables
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     */
    private static var instance:IPopUpManager;
    
	/**
	 * @private
	 * 
	 * Place to hook in additional classes
	 */
	public static var mixins:Array;

    mx_internal static var popUpInfoClass:Class;

	mx_internal static function createPopUpData():PopUpData
    {
        if (!popUpInfoClass)
            return new PopUpData();
        return new popUpInfoClass() as PopUpData;
    }

    //--------------------------------------------------------------------------
    //
    //  Class methods
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     */
    private static function weakDependency():void { ActiveWindowManager };
    
    /**
     *  @private
     */
    public static function getInstance():IPopUpManager
    {
        if (!instance)
            instance = new PopUpManagerImpl();

        return instance;
    }

    //--------------------------------------------------------------------------
    //
    //  Constructor
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     */
    public function PopUpManagerImpl()
    {
        super();

		if (mixins)
		{
			var n:int = mixins.length;
			for (var i:int = 0; i < n; i++)
			{
				new mixins[i](this);
			}
		}

        if (hasEventListener("initialize"))
    		dispatchEvent(new Event("initialize"));
    }

    //--------------------------------------------------------------------------
    //
    //  Variables
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     *  The class used to create the shield that makes a window appear modal.
     */
    mx_internal var modalWindowClass:Class;

    /**
     *  @private
     *  An array of information about currently active popups
     */
    mx_internal var popupInfo:Array = [];

    //--------------------------------------------------------------------------
    //
    //  Methods
    //
    //--------------------------------------------------------------------------

    /**
     *  Creates a top-level window and places it above other windows in the
     *  z-order.
     *  It is good practice to call the <code>removePopUp()</code> method 
     *  to remove popups created by using the <code>createPopUp()</code> method.
     *
     *  If the class implements IFocusManagerContainer, the window will have its
     *  own FocusManager so that, if the user uses the TAB key to navigate between
     *  controls, only the controls in the window will be accessed.
     *
     *  <p><b>Example</b></p> 
     *
     *  <pre>pop = mx.managers.PopUpManager.createPopUp(pnl, TitleWindow, false); </pre>
     *  
     *  <p>Creates a popup window based on the TitleWindow class, using <code>pnl</code> as the MovieClip 
     *  for determining where to place the popup. It is defined to be a non-modal window 
     *  meaning that other windows can receive mouse events</p>
     *
     *  @param parent DisplayObject to be used for determining which SystemManager's layers
     *  to use and optionally the reference point for centering the new
     *  top level window.  It may not be the actual parent of the popup as all popups
     *  are parented by the SystemManager.
     * 
     *  @param className Class of object that is to be created for the popup.
     *  The class must implement IFlexDisplayObject.
     *
     *  @param modal If <code>true</code>, the window is modal which means that
     *  the user will not be able to interact with other popups until the window
     *  is removed.
     *
     *  @param childList The child list in which to add the popup.
     *  One of <code>PopUpManagerChildList.APPLICATION</code>, 
     *  <code>PopUpManagerChildList.POPUP</code>, 
     *  or <code>PopUpManagerChildList.PARENT</code> (default).
     *
     *  @param moduleFactory The moduleFactory where this pop-up should look for
     *  its embedded fonts and style manager.
     *
     *  @return Reference to new top-level window.
     *
     *  @see PopUpManagerChildList
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function createPopUp(parent:DisplayObject,
                                className:Class,
                                modal:Boolean = false,
                                childList:String = null,
                                moduleFactory:IFlexModuleFactory = null):IFlexDisplayObject
    {   
        const window:IUIComponent = new className();
        addPopUp(window, parent, modal, childList, moduleFactory);
        return window;
    }
    
    /**
     *  Pops up a top-level window.
     *  It is good practice to call <code>removePopUp()</code> to remove popups
     *  created by using the <code>createPopUp()</code> method.
     *  If the class implements IFocusManagerContainer, the window will have its
     *  own FocusManager so that, if the user uses the TAB key to navigate between
     *  controls, only the controls in the window will be accessed.
     *
     *  <p><b>Example</b></p> 
     *
     *  <pre>var tw = new TitleWindow();
     *    tw.title = "My Title";
     *    mx.managers.PopUpManager.addPopUp(tw, pnl, false);</pre>
     *
     *  <p>Creates a popup window using the <code>tw</code> instance of the 
     *  TitleWindow class and <code>pnl</code> as the Sprite for determining
     *  where to place the popup.
     *  It is defined to be a non-modal window.</p>
     *  
     *  @param window The IFlexDisplayObject to be popped up.
     *
     *  @param parent DisplayObject to be used for determining which SystemManager's layers
     *  to use and optionally  the reference point for centering the new
     *  top level window.  It may not be the actual parent of the popup as all popups
     *  are parented by the SystemManager. Also, it must not be a descendant of
     *  the popup.
     *
     *  @param modal If <code>true</code>, the window is modal which means that
     *  the user will not be able to interact with other popups until the window
     *  is removed.
     *
     *  @param childList The child list in which to add the pop-up.
     *  One of <code>PopUpManagerChildList.APPLICATION</code>, 
     *  <code>PopUpManagerChildList.POPUP</code>, 
     *  or <code>PopUpManagerChildList.PARENT</code> (default).
     *
     *  @param moduleFactory The moduleFactory where this pop-up should look for
     *  its embedded fonts and style manager.
     * 
     *  @see PopUpManagerChildList
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function addPopUp(window:IFlexDisplayObject,
                             parent:DisplayObject,
                             modal:Boolean = false,
                             childList:String = null,
                             moduleFactory:IFlexModuleFactory = null):void
    {
        // trace("POPUP: window is " + window);
        // All popups go on the local root.
        // trace("POPUP: root is " + parent.root);
        // trace("POPUP: initial parent is " + parent);
        
        const visibleFlag:Boolean = window.visible;
        
        if (parent is IUIComponent && window is IUIComponent &&
              IUIComponent(window).document == null)
              IUIComponent(window).document = IUIComponent(parent).document;

        if (window is IFlexModule && IFlexModule(window).moduleFactory == null)
        {
            if (moduleFactory) 
                IFlexModule(window).moduleFactory = moduleFactory;
            else if (parent is IUIComponent && IUIComponent(parent).document is IFlexModule)
                IFlexModule(window).moduleFactory = IFlexModule(IUIComponent(parent).document).moduleFactory;
        }
        
        var sm:ISystemManager = getTopLevelSystemManager(parent);
        var children:IChildList;
        var topMost:Boolean;

        if (!sm)
        {
            // check if parent is our sandbox root
            sm = ISystemManager(SystemManagerGlobals.topLevelSystemManagers[0]);
            if (sm.getSandboxRoot() != parent)
            {
                //trace("error: popup root was not SystemManager");
                return; // and maybe a nice error message
            }
        }

        // smp is the actual systemManager that will parent the popup
        // it might get changed by the request
        var smp:ISystemManager = sm;

        if (hasEventListener("addPopUp"))
        {
            var request:Request = new Request("addPopUp", false, true, { parent: parent, sm: sm, modal: modal, childList: childList} );
            if (!dispatchEvent(request))
                smp = request.value as ISystemManager;
        }
                
        if (window is IUIComponent)
            IUIComponent(window).isPopUp = true;
                
        if (!childList || childList == PopUpManagerChildList.PARENT)
            topMost = smp.popUpChildren.contains(parent);
        else
            topMost = (childList == PopUpManagerChildList.POPUP);
        
        children = topMost ? smp.popUpChildren : smp;
        
        if (DisplayObject(window).parent != children)
            children.addChild(DisplayObject(window));
                            
        window.visible = false;
        
        const o:PopUpData = createPopUpData();
        o.owner = DisplayObject(window);
        o.topMost = topMost;
        o.systemManager = smp;
        popupInfo.push(o);

        var awm:IActiveWindowManager = 
              IActiveWindowManager(smp.getImplementation("mx.managers::IActiveWindowManager"));

        if (window is IFocusManagerContainer)
        {
            if (IFocusManagerContainer(window).focusManager)
            {
                awm.addFocusManager(IFocusManagerContainer(window));
            }
            else
                // Popups get their own focus loop
                IFocusManagerContainer(window).focusManager =
                    new FocusManager(IFocusManagerContainer(window), true);
        }

        if (hasEventListener("addPlaceHolder"))
        {
            var event:DynamicEvent = new DynamicEvent("addPlaceHolder");
            event.sm = sm;
            event.window = window;
            dispatchEvent(event);
        }

        // force into automation hierarchy
        if (window is IAutomationObject)
            IAutomationObject(window).showInAutomationHierarchy = true;

        if (window is ILayoutManagerClient )
            UIComponentGlobals.layoutManager.validateClient(ILayoutManagerClient (window), true);
        
        o.parent = parent;
        
        if (window is IUIComponent)
        {
            IUIComponent(window).setActualSize(
                IUIComponent(window).getExplicitOrMeasuredWidth(),
                IUIComponent(window).getExplicitOrMeasuredHeight());            
        }
                    
        // The layout direction may have changed since last time the
        // popup was opened so need to reinit mirroring fields.
        if (FlexVersion.compatibilityVersion >= FlexVersion.VERSION_4_0)
        {
           if (window is ILayoutDirectionElement)
                ILayoutDirectionElement(window).invalidateLayoutDirection();
        }
        
        if (modal)
        {
			// handles accessibility for modal popUps.
			if(Capabilities.hasAccessibility && Accessibility.active)
				window.addEventListener(FlexEvent.CREATION_COMPLETE, modalPopUpCreationCompleteHandler, false, 0, true);

			// create a modal window shield which blocks input and sets up mouseDownOutside logic
            createModalWindow(parent, o, children, visibleFlag, smp, smp.getSandboxRoot());
        }
        else
        {
            o._mouseDownOutsideHandler  = nonmodalMouseDownOutsideHandler;
            o._mouseWheelOutsideHandler = nonmodalMouseWheelOutsideHandler;

            window.visible = visibleFlag;
        }

        // Add show/hide listener so mouse out listeners can be added when
        // a pop up is shown because applications can be launched and 
        // terminated between the time a pop up is hidden to when it is
        // shown again.         
        o.owner.addEventListener(FlexEvent.SHOW, showOwnerHandler);
        o.owner.addEventListener(FlexEvent.HIDE, hideOwnerHandler);

        addMouseOutEventListeners(o);
        
        // Listen for unload so we know to kill the window (and the modalWindow if modal)
        // this handles _all_ cleanup
        window.addEventListener(Event.REMOVED, popupRemovedHandler);
            
        if (window is IFocusManagerContainer && visibleFlag)
        {
            if (hasEventListener("addedPopUp"))
            {
                event = new DynamicEvent("addedPopUp", false, true);
                event.window = window;
                event.systemManager = smp;
                dispatchEvent(event);
            }
            else
                awm.activate(IFocusManagerContainer(window));
        }

        // trace("END POPUP: addPopUp" + parent);
    }


    mx_internal function getTopLevelSystemManager(parent:DisplayObject):ISystemManager
	{
	    var localRoot:DisplayObjectContainer;
		var sm:ISystemManager;
	
        if (hasEventListener("topLevelSystemManager"))
        {
		    var request:Request = new Request("topLevelSystemManager", false, true);
		    request.value = parent;
		    if (!dispatchEvent(request))
		        localRoot = request.value as DisplayObjectContainer;
        }
		if (!localRoot)
			localRoot = DisplayObjectContainer(parent.root);
			
        // If the parent isn't rooted yet,
        // Or the root is the stage (which is the case in a second AIR window)
        // use the global system manager instance.
        if ((!localRoot || localRoot is Stage) && parent is IUIComponent)
            localRoot = DisplayObjectContainer(IUIComponent(parent).systemManager);
        if (localRoot is ISystemManager)
        {
            sm = ISystemManager(localRoot);
            if (!sm.isTopLevel())
                sm = sm.topLevelSystemManager;
        }

		return sm;
	}

    /**
     *  Centers a popup window over whatever window was used in the call 
     *  to the <code>createPopUp()</code> or <code>addPopUp()</code> method.
     *
     *  <p>Note that the position of the popup window may not
     *  change immediately after this call since Flex may wait to measure and layout the
     *  popup window before centering it.</p>
     *
     *  @param The IFlexDisplayObject representing the popup.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function centerPopUp(popUp:IFlexDisplayObject):void
    {        
        if (popUp is IInvalidating)
            IInvalidating(popUp).validateNow();

        const o:PopUpData = findPopupInfoByOwner(popUp);
        
        // If we don't find the pop owner or if the owner's parent is not specified or is not on the
        // stage, then center based on the popUp's current parent.
		var popUpParent:DisplayObject = (o && o.parent && o.parent.stage) ? o.parent : popUp.parent;
		if (popUpParent)
		{
			//FLEX-28967 : https://issues.apache.org/jira/browse/FLEX-28967. Fix by miroslav.havrlent
			var systemManager:ISystemManager;
			if (o != null) {
				systemManager = o.systemManager;
			} else if (popUpParent.hasOwnProperty("systemManager")) {
				systemManager = popUpParent["systemManager"];
			} else if (popUpParent is ISystemManager) {
				systemManager = popUpParent as ISystemManager;
			}
			
			if (!systemManager)
				return; // or throw exception maybe ?
			
            var x:Number;
            var y:Number;
            var appWidth:Number;
            var appHeight:Number;
            var parentWidth:Number;
            var parentHeight:Number;
            var rect:Rectangle;
            var clippingOffset:Point = new Point();
            var pt:Point;
            var isTopLevelRoot:Boolean;
            var sbRoot:DisplayObject = systemManager.getSandboxRoot();

            var request:Request;
            if (hasEventListener("isTopLevelRoot"))
            {
    			request = new Request("isTopLevelRoot", false, true);
            }
			if (request && !dispatchEvent(request))
				isTopLevelRoot = Boolean(request.value);
            else
                isTopLevelRoot = systemManager.isTopLevelRoot();
                        
            if (isTopLevelRoot && (FlexVersion.compatibilityVersion < FlexVersion.VERSION_4_6))
            {
                // The sandbox root is the top level root.
                // The application width is just the screen width.
                var screen:Rectangle = systemManager.screen;
                appWidth = screen.width;
                appHeight = screen.height;
            }
            else
            {
                rect = systemManager.getVisibleApplicationRect();
                rect.topLeft = DisplayObject(systemManager).globalToLocal(rect.topLeft);
                rect.bottomRight = DisplayObject(systemManager).globalToLocal(rect.bottomRight);
            
                // Offset the top, left of the window to bring it into view.        
                clippingOffset = rect.topLeft.clone();
                appWidth = rect.width;
                appHeight = rect.height;
            } 

            // If parent is a UIComponent, check for clipping between
            // the object and its SystemManager
            if (popUpParent is UIComponent)
            {
                rect = UIComponent(popUpParent).getVisibleRect();
				if (UIComponent(popUpParent).systemManager != sbRoot)
					rect = UIComponent(popUpParent).systemManager.getVisibleApplicationRect(rect);
                var offset:Point = popUpParent.globalToLocal(rect.topLeft);
                clippingOffset.x += offset.x;
                clippingOffset.y += offset.y;
                parentWidth = rect.width;
                parentHeight = rect.height;              
            }   
            else
            {          
                parentWidth = popUpParent.width;
                parentHeight = popUpParent.height;
            }

            // The appWidth may smaller than parentWidth if the application is
            // clipped by the parent application.
            x = Math.max(0, (Math.min(appWidth, parentWidth) - popUp.width) / 2);
            y = Math.max(0, (Math.min(appHeight, parentHeight) - popUp.height) / 2);
            
            // If the layout has been mirrored, then 0,0 is the uppper
            // right corner; compensate here.
            if (FlexVersion.compatibilityVersion >= FlexVersion.VERSION_4_0)
            {
                // If popUp has layout direction different than the parent (or parent doesn't
                // have layout direction and popUp is RTL) flip it to the other side of the x axis.
                const popUpLDE:ILayoutDirectionElement = popUp as ILayoutDirectionElement;
                const parentLDE:ILayoutDirectionElement = popUpParent as ILayoutDirectionElement;
                
                if (popUpLDE)
                {
                    if ((parentLDE && parentLDE.layoutDirection != popUpLDE.layoutDirection) ||
                       (!parentLDE && popUpLDE.layoutDirection == LayoutDirection.RTL))
                    {
                        //(x = -x)  to flip it on the other side of the x axis.
                        //(-popUp.width)  because 0 is the right edge.
                        x = -x -popUp.width;
                    }

                    if (popUpLDE.layoutDirection == LayoutDirection.RTL)
                    {
                        //Corrects the x offset for RTL.
                        clippingOffset.x += popUpParent.width;
                    }
                }
            }
            
            pt = new Point(clippingOffset.x, clippingOffset.y);            
            pt = popUpParent.localToGlobal(pt);
            pt = popUp.parent.globalToLocal(pt);
            popUp.move(Math.round(x) + pt.x, Math.round(y) + pt.y);
        }
    }

    /**
     *  Removes a popup window popped up by 
     *  the <code>createPopUp()</code> or <code>addPopUp()</code> method.
     *  
     *  @param window The IFlexDisplayObject representing the popup window.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function removePopUp(popUp:IFlexDisplayObject):void
    {
        // all we want to do here is verify that this popup is one of ours
        // and remove it from the display list; the REMOVED handler will do the rest
        // (this is so that we never leak memory, popups will self-manage even if
        //  removePopUp is not called).
        if (popUp && popUp.parent)
        {
            const o:PopUpData = findPopupInfoByOwner(popUp);
            if (o)
            {
                var sm:ISystemManager = o.systemManager;
                if (!sm)
				{
					var iui:IUIComponent = popUp as IUIComponent;
					// cross-versioning error sometimes returns wrong parent
					if (iui)
						sm = ISystemManager(iui.systemManager);
					else
						return;
				}

                if (o.topMost)
                    sm.popUpChildren.removeChild(DisplayObject(popUp));
                else
                    sm.removeChild(DisplayObject(popUp));
            }
        }
    }
    
    /**
     *  Makes sure a popup window is higher than other objects in its child list
     *  The SystemManager does this automatically if the popup is a top level window
     *  and is moused on, 
     *  but otherwise you have to take care of this yourself.
     *
     *  @param The IFlexDisplayObject representing the popup.
     *  
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function bringToFront(popUp:IFlexDisplayObject):void
    {
        if (popUp && popUp.parent)
        {
            const o:PopUpData = findPopupInfoByOwner(popUp);
            if (o)
            {
                if (hasEventListener("bringToFront"))
                {
				    var dynamicEvent:DynamicEvent = new DynamicEvent("bringToFront", false, true);
				    dynamicEvent.popUpData = o;
				    dynamicEvent.popUp = popUp;
				    if (!dispatchEvent(dynamicEvent))
					    return;
                }
                const sm:ISystemManager = ISystemManager(popUp.parent);
                if (o.topMost)
                    sm.popUpChildren.setChildIndex(DisplayObject(popUp), sm.popUpChildren.numChildren - 1);
                else
                    sm.setChildIndex(DisplayObject(popUp), sm.numChildren - 1);
            }
        }
    }
    
    /**
     *  @private
     * 
     *  Create the modal window. 
     *  This is called in two different cases.
     *      1. Create a modal window for a local pop up.
     *      2. Create a modal window for a remote pop up. In this case o.owner will be null.
     */
    mx_internal function createModalWindow(parentReference:DisplayObject,
                                       o:PopUpData,
                                       childrenList:IChildList,
                                       visibleFlag:Boolean,
                                       sm:ISystemManager,
                                       sbRoot:DisplayObject):void
    {
        const popup:IFlexDisplayObject = IFlexDisplayObject(o.owner);

        const popupStyleClient:IStyleClient = popup as IStyleClient;
        var duration:Number = 0;
      
        // Create a modalWindow the size of the stage
        // that eats all mouse clicks.
        var modalWindow:Sprite;
        if (modalWindowClass)
        {
            modalWindow = new modalWindowClass();
        }
        else
        {
            modalWindow = new FlexSprite();
            modalWindow.name = "modalWindow";
        }
    
    	if (!sm && parentReference)
	        sm = IUIComponent(parentReference).systemManager;

		var awm:IActiveWindowManager = 
			IActiveWindowManager(sm.getImplementation("mx.managers::IActiveWindowManager"));
    	awm.numModalWindows++;

        // Add it to the collection just below the popup
        if (popup)
            childrenList.addChildAt(modalWindow,
                childrenList.getChildIndex(DisplayObject(popup)));
        else 
            childrenList.addChild(modalWindow);
        
        // force into the automation hierarchy
        if (popup is IAutomationObject)
            IAutomationObject(popup).showInAutomationHierarchy = true;
        
        o.modalWindow = modalWindow;

        if (popupStyleClient)
            modalWindow.alpha = popupStyleClient.getStyle("modalTransparency");
		else
			modalWindow.alpha = 0;
		
        modalWindow.tabEnabled = false;
        
        const screen:Rectangle = sm.screen;
        const g:Graphics = modalWindow.graphics;
        
        var c:Number = 0xFFFFFF;
        if (popupStyleClient)
        {
            c = popupStyleClient.getStyle("modalTransparencyColor");
        }
        
        if (hasEventListener("createModalWindow"))
        {
		    var dynamicEvent:DynamicEvent = new DynamicEvent("createModalWindow", false, true);
		    dynamicEvent.popUpData = o;
		    dynamicEvent.popUp = popup;
		    dynamicEvent.color = c;
            dynamicEvent.visibleFlag = visibleFlag;
		    dynamicEvent.childrenList = childrenList;
		    if (!dispatchEvent(dynamicEvent))
			    c = dynamicEvent.color;
        }

        // trace("createModalWindow: drawing modal " + s);
        g.clear();
        g.beginFill(c, 100);
		g.drawRect(screen.x-1, screen.y-1, screen.width+2, screen.height+2);
        g.endFill();

        if (hasEventListener("updateModalMask"))
        {
		    dynamicEvent = new DynamicEvent("updateModalMask");
		    dynamicEvent.popUpData = o;
		    dynamicEvent.popUp = popup;
		    dynamicEvent.childrenList = childrenList;
		    dispatchEvent(dynamicEvent);
        }

        // a modal mousedownoutside handler just dispatches the event
        o._mouseDownOutsideHandler  = dispatchMouseDownOutsideEvent;
        o._mouseWheelOutsideHandler = dispatchMouseWheelOutsideEvent;
        
        // the following handlers all get removed in REMOVED on the popup
        
        // Set the resize handler so the modal can stay the size of the screen
       	sm.addEventListener(Event.RESIZE, o.resizeHandler);

        if (popup)
        {
            // Listen for show so we know to show the modal window
            popup.addEventListener(FlexEvent.SHOW, popupShowHandler);
        
            // Listen for hide so we know to hide the modal window
            popup.addEventListener(FlexEvent.HIDE, popupHideHandler);
        }
        
        if (visibleFlag)
            showModalWindow(o, sm, false);
        else if(popup)
            popup.visible = visibleFlag;

        if (hasEventListener("createdModalWindow"))
        {
		    dynamicEvent = new DynamicEvent("createdModalWindow");
		    dynamicEvent.popUpData = o;
		    dynamicEvent.popUp = popup;
            dynamicEvent.visibleFlag = visibleFlag;
		    dynamicEvent.childrenList = childrenList;
		    dispatchEvent(dynamicEvent);
        }
    }
    
    
    /**
     *  @private
     */
    private function endEffects(o:PopUpData):void
    {
        if (o.fade)
        {
            o.fade.end();
            o.fade = null;
        }
        
        if (o.blur)
        {
            o.blur.end();
            o.blur = null;
        }
    }
    
    mx_internal function showModalWindow(o:PopUpData, sm:ISystemManager, sendRequest:Boolean = true):void
    {
    	const popUpStyleClient:IStyleClient = o.owner as IStyleClient;
        var duration:Number = 0;
        var alpha:Number = 0;
        
        if (popUpStyleClient)
        {
            duration = popUpStyleClient.getStyle("modalTransparencyDuration");
        }
        
        if (popUpStyleClient)
        {
            alpha = popUpStyleClient.getStyle("modalTransparency");
        }
            
	    var blurAmount:Number = 0;
	    
	    if (popUpStyleClient)
	    {
	    	blurAmount = popUpStyleClient.getStyle("modalTransparencyBlur");
	    }

		var transparencyColor:Number = 0xFFFFFF;
	    if (popUpStyleClient)
	    {
	    	transparencyColor = popUpStyleClient.getStyle("modalTransparencyColor");
	    }
   
        var sbRoot:DisplayObject = sm.getSandboxRoot();

        if (hasEventListener("showModalWindow"))
        {
		    var dynamicEvent:DynamicEvent = new DynamicEvent("showModalWindow", false, true);
		    dynamicEvent.popUpData = o;
		    dynamicEvent.sendRequest = sendRequest;
		    dynamicEvent.alpha = alpha;
		    dynamicEvent.blurAmount = blurAmount;
		    dynamicEvent.duration = duration;
            dynamicEvent.systemManager = sm;
		    dynamicEvent.transparencyColor = transparencyColor;
		    if (!dispatchEvent(dynamicEvent))
		    {
			    alpha = dynamicEvent.alpha;
			    blurAmount = dynamicEvent.blurAmount;
			    duration = dynamicEvent.duration;
			    transparencyColor = dynamicEvent.transparencyColor;
		    }
        }
		o.modalWindow.alpha = alpha;
			
        showModalWindowInternal(o, duration, alpha, transparencyColor, blurAmount, sm, sbRoot);
        
    }
    
    private function setModalPopupVisible(popup:DisplayObject, value:Boolean):void
    {
        popup.removeEventListener(FlexEvent.SHOW, popupShowHandler);
        popup.removeEventListener(FlexEvent.HIDE, popupHideHandler);
        
        popup.visible = value;
        
        popup.addEventListener(FlexEvent.SHOW, popupShowHandler);
        popup.addEventListener(FlexEvent.HIDE, popupHideHandler);
    }
    
    /**
     *  @private
     *  Show the modal transparency blocker, playing effects if needed.
     */
    private function showModalWindowInternal(o:PopUpData, 
    										 transparencyDuration:Number, 
    										 transparency:Number, 
    										 transparencyColor:Number,
    										 transparencyBlur:Number, 
    										 sm:ISystemManager,
    										 sbRoot:DisplayObject):void
    {
        // NO POPUP Data
        // End any effects that are currently playing for this popup.
        endEffects(o);

        if (transparencyDuration)
        {
            // Fade effect on the modal transparency blocker
            const fade:Fade = new Fade(o.modalWindow);

            fade.alphaFrom = 0;
            fade.alphaTo = transparency;
            fade.duration = transparencyDuration;
            fade.addEventListener(EffectEvent.EFFECT_END, fadeInEffectEndHandler);

            o.modalWindow.alpha = 0;
            o.modalWindow.visible = true;
            o.fade = fade;
            
            if (o.owner)
                setModalPopupVisible(o.owner, false);
            
            fade.play();
            
            // Blur effect on the application
            var blurAmount:Number = transparencyBlur;
            
            if (blurAmount)
            {
                // Ensure we blur the appropriate top level document.
                if (DisplayObject(sm).parent is Stage)
                {
                    // Checking this case first allows WindowedSystemManagers be the blur target.
                    o.blurTarget = sm.document;
                }
                else if (sm != sbRoot)
                {
                    // Get the application document of the sandbox root.
                    // Use a request to get the document so APIs may change
                    // between Flex versions.
                    var sbRootApp:Object;   // sbRoot.application;

                    if (hasEventListener("blurTarget"))
                    {
				        var request:Request = new Request("blurTarget", false, true, { popUpData: o });
                        if (!dispatchEvent(request))
                        {
					        o.blurTarget = request.value;
                        }
                    }
                }
				else
                    o.blurTarget = FlexGlobals.topLevelApplication;

                const blur:Blur = new Blur(o.blurTarget);
                blur.blurXFrom = blur.blurYFrom = 0;
                blur.blurXTo = blur.blurYTo = blurAmount;
                blur.duration = transparencyDuration;
                blur.addEventListener(EffectEvent.EFFECT_END, effectEndHandler);
                o.blur = blur;
                
                blur.play();
            }
        }
        else
        {
            if (o.owner)
                setModalPopupVisible(o.owner, true);
            o.modalWindow.visible = true;
        }
    }
    
    /**
     *  @private
     *  Hide the modal transparency blocker, playing effects if needed.
     * 
     */
    mx_internal function hideModalWindow(o:PopUpData, destroy:Boolean = false):void
    {
        const popUpStyleClient:IStyleClient = o.owner as IStyleClient;

        var duration:Number = 0;
        if (popUpStyleClient)
            duration = popUpStyleClient.getStyle("modalTransparencyDuration");
        
        // end any effects that are current playing for this popup
        endEffects(o);
        
        if (duration)
        {
            // Fade effect on the modal transparency blocker
            const fade:Fade = new Fade(o.modalWindow);

            fade.alphaFrom = o.modalWindow.alpha;
            fade.alphaTo = 0;
            fade.duration = duration;
            fade.addEventListener(EffectEvent.EFFECT_END, 
                destroy ? fadeOutDestroyEffectEndHandler : fadeOutCloseEffectEndHandler);

            o.modalWindow.visible = true;
            o.fade = fade;
            fade.play();
            
            var sm:ISystemManager = o.systemManager;
            var awm:IActiveWindowManager = 
                IActiveWindowManager(sm.getImplementation("mx.managers::IActiveWindowManager"));
            // don't remove blur unless this is the last modal window
            if (awm.numModalWindows == 1)
            {
                
                // Blur effect on the application
                const blurAmount:Number = popUpStyleClient.getStyle("modalTransparencyBlur");
                
                if (blurAmount)
                {
                    const blur:Blur = new Blur(o.blurTarget);
                    blur.blurXFrom = blur.blurYFrom = blurAmount;
                    blur.blurXTo = blur.blurYTo = 0;
                    blur.duration = duration;
                    blur.addEventListener(EffectEvent.EFFECT_END, effectEndHandler);
                    o.blur = blur;
                    
                    blur.play();
                }
            }
        }
        else
        {
            o.modalWindow.visible = false;
        }
        
        if (hasEventListener("hideModalWindow"))
        {
		    var dynamicEvent:DynamicEvent = new DynamicEvent("hideModalWindow", false, false);
		    dynamicEvent.popUpData = o;
		    dynamicEvent.destroy = destroy;
		    dispatchEvent(dynamicEvent);
        }
    }

	/**
	 *  @private
	 *  Returns the index position of the PopUpData in the popupInfo array (or -1) 
	 *  for a given popupInfo.owner
	 */
	private function findPopupInfoIndexByOwner(owner:Object):int
	{
		const n:int = popupInfo.length;
		for (var i:int = 0; i < n; i++)
		{
			var o:PopUpData = popupInfo[i];
			if (o.owner == owner)
				return i;
		}
		return -1;
	}
	
	/**
	 *  @private
	 *  Returns the PopUpData (or null) for a given popupInfo.owner
	 */
	private function findPopupInfoByOwner(owner:Object):PopUpData
	{
		var index:int = findPopupInfoIndexByOwner(owner);
		return index > -1 ? popupInfo[index] : null;
	}

    /**
     *  @private
     *  Add mouse out listeners for modal and non-modal windows.
     */
    private function addMouseOutEventListeners(o:PopUpData):void
    {
        var sbRoot:DisplayObject = o.systemManager.getSandboxRoot();
        if (o.modalWindow)
        {
            o.modalWindow.addEventListener(MouseEvent.MOUSE_DOWN,  o.mouseDownOutsideHandler);
            o.modalWindow.addEventListener(MouseEvent.MOUSE_WHEEL, o.mouseWheelOutsideHandler, true);
        }
        else
        {
            sbRoot.addEventListener(MouseEvent.MOUSE_DOWN,  o.mouseDownOutsideHandler);
            sbRoot.addEventListener(MouseEvent.MOUSE_WHEEL, o.mouseWheelOutsideHandler, true);
        }
        
        if (hasEventListener("addMouseOutEventListeners"))
        {
		    var dynamicEvent:DynamicEvent = new DynamicEvent("addMouseOutEventListeners", false, false);
		    dynamicEvent.popUpData = o;
		    dispatchEvent(dynamicEvent);
        }
    }
    
    /**
     *  @private
     *  Remove mouse out listeners for modal and non-modal windows.
     */
    private function removeMouseOutEventListeners(o:PopUpData):void
    {
        var sbRoot:DisplayObject = o.systemManager.getSandboxRoot();
        if (o.modalWindow)
        {
            o.modalWindow.removeEventListener(MouseEvent.MOUSE_DOWN,  o.mouseDownOutsideHandler);
            o.modalWindow.removeEventListener(MouseEvent.MOUSE_WHEEL, o.mouseWheelOutsideHandler, true);
        }
        else 
        {
            sbRoot.removeEventListener(MouseEvent.MOUSE_DOWN,  o.mouseDownOutsideHandler);
            sbRoot.removeEventListener(MouseEvent.MOUSE_WHEEL, o.mouseWheelOutsideHandler, true);
        }

        if (hasEventListener("removeMouseOutEventListeners"))
        {
		    var dynamicEvent:DynamicEvent = new DynamicEvent("removeMouseOutEventListeners", false, false);
		    dynamicEvent.popUpData = o;
		    dispatchEvent(dynamicEvent);
        }
    }

    //--------------------------------------------------------------------------
    //
    //  Event handlers
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     *  Set by PopUpManager on modal windows so they show when the parent shows.
     */
    private function popupShowHandler(event:FlexEvent):void
    {
        const o:PopUpData = findPopupInfoByOwner(event.target);
        if (o)
            showModalWindow(o, getTopLevelSystemManager(o.parent));
    }

    /**
     *  @private
     *  Set by PopUpManager on modal windows so they hide when the parent hide
     */
    private function popupHideHandler(event:FlexEvent):void
    {
        const o:PopUpData = findPopupInfoByOwner(event.target);
        if (o)
            hideModalWindow(o);
    }

    /**
     *  @private
     */
    private function showOwnerHandler(event:FlexEvent):void
    {
        const o:PopUpData = findPopupInfoByOwner(event.target);
        if (o)
        {
            // add mouse out listeners.
            addMouseOutEventListeners(o);            
        }
    }

    /**
     *  @private
     */
    private function hideOwnerHandler(event:FlexEvent):void
    {
        const o:PopUpData = findPopupInfoByOwner(event.target);
        if (o)
        {
            // remove mouse out listeners
            removeMouseOutEventListeners(o);
        }
    }

    
    /**
     *  @private
     *  Set by PopUpManager on modal windows to monitor when the parent window gets killed.
     *  PopUps self-manage their memory -- when they are removed using removePopUp OR
     *  manually removed with removeChild, they will clean themselves up when they leave the
     *  display list (including all references to PopUpManager).
     */
    private function popupRemovedHandler(event:Event):void
    {
        const n:int = popupInfo.length;
        for (var i:int = 0; i < n; i++)
        {
            var o:PopUpData               = popupInfo[i],
                popUp:DisplayObject       = o.owner;
                  
            if (popUp == event.target)
            {
                var popUpParent:DisplayObject = o.parent,
                    modalWindow:DisplayObject = o.modalWindow,
                    sm:ISystemManager         = o.systemManager;
                
				if (!sm.isTopLevel())
					sm = sm.topLevelSystemManager;

                if (popUp is IUIComponent)
                    IUIComponent(popUp).isPopUp = false;
                
				var awm:IActiveWindowManager = 
					IActiveWindowManager(sm.getImplementation("mx.managers::IActiveWindowManager"));
                if (popUp is IFocusManagerContainer)
				{
                    awm.removeFocusManager(IFocusManagerContainer(popUp));
				}
                
                popUp.removeEventListener(Event.REMOVED,  popupRemovedHandler);

                if (hasEventListener("removeMouseOutEventListeners"))
                {
				    var event2:DynamicEvent = new DynamicEvent("popUpRemoved");
				    event2.popUpData = o;
                    dispatchEvent(event2);
                }

				if (o.owner)
                {
                    o.owner.removeEventListener(FlexEvent.SHOW, showOwnerHandler);
                    o.owner.removeEventListener(FlexEvent.HIDE, hideOwnerHandler);
                }

                removeMouseOutEventListeners(o);
                
                // modal
                if (modalWindow)
                {
					// restore accessibility to document
					removeModalPopUpAccessibility(popUp);
					
					// clean up all handlers
					sm.removeEventListener(Event.RESIZE, o.resizeHandler);
                    
                    popUp.removeEventListener(FlexEvent.SHOW, popupShowHandler);
                    popUp.removeEventListener(FlexEvent.HIDE, popupHideHandler);
                    
                    hideModalWindow(o, true);
    				awm.numModalWindows--;
                }

                popupInfo.splice(i, 1);
                break;
            }
        }
    }
    
 
    /**
     *  @private
     *  Show the modal window after the fade effect finishes
     */
    private function fadeInEffectEndHandler(event:EffectEvent):void
    {
        effectEndHandler(event);
        
        const n:int = popupInfo.length;
        for (var i:int = 0; i < n; i++)
        {
            var o:PopUpData = popupInfo[i];
            if (o.owner && o.modalWindow == event.effectInstance.target)
            {
                setModalPopupVisible(o.owner, true);
                break;
            }
        }
    }
    
    /**
     *  @private
     *  Remove the modal window after the fade effect finishes
     */
    private function fadeOutDestroyEffectEndHandler(event:EffectEvent):void
    {
        effectEndHandler(event);

        const obj:DisplayObject = DisplayObject(event.effectInstance.target);

        var modalMask:DisplayObject = obj.mask;
        if (modalMask)
        {
            // modal mask is always added to the popupChildren list.
            obj.mask = null;
            sm.popUpChildren.removeChild(modalMask);
        }   

        if (obj.parent is ISystemManager)
        {
            const sm:ISystemManager = ISystemManager(obj.parent)
            if (sm.popUpChildren.contains(obj))
                sm.popUpChildren.removeChild(obj);
            else
                sm.removeChild(obj);
        }
        else
		{
			if (obj.parent)	// Mustella can already take you off stage
				obj.parent.removeChild(obj);
		}
		
    }
    
    /**
     *  @private
     *  Remove the modal window after the fade effect finishes
     */
    private function fadeOutCloseEffectEndHandler(event:EffectEvent):void
    {
        effectEndHandler(event);
        DisplayObject(event.effectInstance.target).visible = false;
    }
    
    /**
     *  @private
     */
    private function effectEndHandler(event:EffectEvent):void
    {
        const n:int = popupInfo.length;
        for (var i:int = 0; i < n; i++)
        {
            var o:PopUpData = popupInfo[i];
            var e:IEffect = event.effectInstance.effect;
            
            if (e == o.fade)
                o.fade = null;
            else if (e == o.blur)
                o.blur = null;
        }
    }
    
    /**
     *  @private
     *  If not modal, use this kind of mouseDownOutside logic
     */
    private static function nonmodalMouseDownOutsideHandler(owner:DisplayObject, evt:MouseEvent):void
    {
        // shapeFlag is false here for performance reasons
        if (owner.hitTestPoint(evt.stageX, evt.stageY, true))
		{
		}
        else
		{
			if (owner is IUIComponent)
				if (IUIComponent(owner).owns(DisplayObject(evt.target)))
					return;

            dispatchMouseDownOutsideEvent(owner, evt);
		}
    }
    
    /**
     *  @private
     *  If not modal, use this kind of mouseWheelOutside logic
     */
    private static function nonmodalMouseWheelOutsideHandler(owner:DisplayObject, evt:MouseEvent):void
    {
        // shapeFlag is false here for performance reasons
        if (owner.hitTestPoint(evt.stageX, evt.stageY, true))
        {
		}
        else
		{
			if (owner is IUIComponent)
				if (IUIComponent(owner).owns(DisplayObject(evt.target)))
					return;

            dispatchMouseWheelOutsideEvent(owner, evt);
		}
    }
    
    /**
     *  @private
     *  This mouseWheelOutside handler just dispatches the event.
     */
    private static function dispatchMouseWheelOutsideEvent(owner:DisplayObject, evt:MouseEvent):void
    {
        // this is a modal window without a popup owner to dispatch the message to. 
        if (!owner)
            return;
            
        const event:MouseEvent = new FlexMouseEvent(FlexMouseEvent.MOUSE_WHEEL_OUTSIDE);
        const pt:Point = owner.globalToLocal(new Point(evt.stageX, evt.stageY));
        event.localX = pt.x;
        event.localY = pt.y;
        event.buttonDown = evt.buttonDown;
        event.shiftKey = evt.shiftKey;
        event.altKey = evt.altKey;
        event.ctrlKey = evt.ctrlKey;
        event.delta = evt.delta;
        event.relatedObject = InteractiveObject(evt.target);
        owner.dispatchEvent(event);
    }
    
    /**
     *  @private
     *  This mouseDownOutside handler just dispatches the event.
     */
    private static function dispatchMouseDownOutsideEvent(owner:DisplayObject, evt:MouseEvent):void
    {
        
        // this is a modal window without a popup owner to dispatch the message to. 
        if (!owner)
            return;
        
        const event:MouseEvent = new FlexMouseEvent(FlexMouseEvent.MOUSE_DOWN_OUTSIDE);
        const pt:Point = owner.globalToLocal(new Point(evt.stageX, evt.stageY));
        event.localX = pt.x;
        event.localY = pt.y;
        event.buttonDown = evt.buttonDown;
        event.shiftKey = evt.shiftKey;
        event.altKey = evt.altKey;
        event.ctrlKey = evt.ctrlKey;
        event.delta = evt.delta;
        event.relatedObject = InteractiveObject(evt.target);
        owner.dispatchEvent(event);
    }

	/**
	 * @private
	 * This method handles the creation of a modal popUp
	 */
	private function modalPopUpCreationCompleteHandler(event:FlexEvent):void
	{
		event.target.removeEventListener(FlexEvent.CREATION_COMPLETE, modalPopUpCreationCompleteHandler);
		
		addModalPopUpAccessibility(event.currentTarget as DisplayObject);			
	}
	
	/**
	 * @private 
	 * This method handles the creation of a modal popUp when assistive 
	 * technology is active, by silencing the content of the top-level document.
	 */
	private function addModalPopUpAccessibility(popUp:DisplayObject):Boolean
	{		
		if (Capabilities.hasAccessibility && Accessibility.active) 
		{	
			const p:PopUpData = findPopupInfoByOwner(popUp);
			
			if (p)	
			{
				const n:int = popupInfo.length;
				for (var i:int = 0; i < n; i++)
				{
					var o:PopUpData = popupInfo[i];
					if (o && o != p && o.owner.accessibilityProperties)
					{
						o.owner.accessibilityProperties.silent = true;
					}
				}
				
				var sbRoot:Object = p.systemManager.getSandboxRoot(); // getTopLevelSystemManager(p.parent);
				
				if (!sbRoot.document.accessibilityProperties)
					sbRoot.document.accessibilityProperties = new AccessibilityProperties();
					
				// This hides top-level document content from assistive technology.	
				sbRoot.document.accessibilityProperties.silent = true;
				
				try {
					Accessibility.updateProperties();
				}
				catch(e:Error) {
					// Flash Player issue causes hasAccessibility and active to be true when accessibility is turned off 
				}
			}
			return true;
		}
		return false;
	}
	
	/**
	 * @private
	 * This method handles the removal of a modal popUp when assistive technology is active, 
	 * by exposing the content of the top-level document.
	 * 
	 * @return 
	 */
	private function removeModalPopUpAccessibility(popUp:DisplayObject):Boolean
	{
		if (Capabilities.hasAccessibility && Accessibility.active) 
		{			
			const p:PopUpData = findPopupInfoByOwner(popUp);
			
			if (p)	
			{	
				handleAccessibilityForNestedPopups(popUp);
								
				if (popupInfo.length<=1)
				{
					var sbRoot:Object = p.systemManager.getSandboxRoot();
					if (sbRoot.document.accessibilityProperties)
						sbRoot.document.accessibilityProperties.silent = false;
				}
				
				try {
					Accessibility.updateProperties();
				}
				catch(e:Error) {
					// Flash Player issue on windows causes hasAccessibility and active to be true when accessibility is turned off 
				}
			}
			return true;
		}
		return false;
	}
	
	/**
	 * @private
	 * This method handles accessibility for nested popUps. 
	 * If this method is called from outside removeModalPopUpAccessibility, 
	 * it is mandatory to invoke Accessibility.updateProperties() to communicate 
	 * the individual popup's accessibilityProperties change to the screen reader.
	 * 
	 * <p>This method should only come into play with modal popUps, in which case it will
	 * either expose accessibility of a modal popUp underneath the popUp being closed 
	 * without exposing the underlying content, or continue exposing accessibility 
	 * of popUps until there are no more to expose.</p>
	 */ 
	private function handleAccessibilityForNestedPopups(popUpBeingVisited:DisplayObject):void
	{
		if (!popUpBeingVisited)
			return;
		
		var index:int = findPopupInfoIndexByOwner(popUpBeingVisited);
		var popupData:PopUpData = index > -1 ? popupInfo[index] : null;
		var underneathPopUpData:PopUpData;
		
		
		if (index == 0)
		{	
			var sm:ISystemManager = getTopLevelSystemManager(popupData.parent);
			
			if (sm) 
			{
				// If this is the only popUp, we should expose accessibility 
				// of the top-level system manager's document
				if (sm.document.accessibilityProperties)
					sm.document.accessibilityProperties.silent = false;
				
				// We should also expose accessibility 
				// of the sandbox root's document.
				var sbRoot:Object = popupData.systemManager.getSandboxRoot();	
				if (sbRoot.document.accessibilityProperties)
					sbRoot.document.accessibilityProperties.silent = false;
			}
		}
		else if (index > 0)
		{
			// If more than one popUp is open, we should expose accessibility 
			// of the underlying popUp
			underneathPopUpData = popupInfo[index - 1];
			
			if (underneathPopUpData.owner.accessibilityProperties)
				underneathPopUpData.owner.accessibilityProperties.silent = false;
			
			// All the nested popUp's AccessibilityProperties 
			// changes should be handled by a single 
			// Accessibility.updateProperties 
			// call in removeModalPopUpAccessibility.
			
			// If the underlying popUp is modal, we should stop recursing.
			if (underneathPopUpData.modalWindow)
				return;
			
			
			handleAccessibilityForNestedPopups(underneathPopUpData.owner);
		}
	}

}

}
