You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by ah...@apache.org on 2016/06/03 17:55:23 UTC

[4/6] git commit: [flex-asjs] [refs/heads/spark] - clean compile of MX for swf

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/4f3802ef/frameworks/projects/MX/src/main/flex/mx/managers/FocusManager.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/MX/src/main/flex/mx/managers/FocusManager.as b/frameworks/projects/MX/src/main/flex/mx/managers/FocusManager.as
new file mode 100644
index 0000000..105c979
--- /dev/null
+++ b/frameworks/projects/MX/src/main/flex/mx/managers/FocusManager.as
@@ -0,0 +1,2359 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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
+{
+
+COMPILE::AS3
+{
+import flash.display.DisplayObject;
+import flash.display.DisplayObjectContainer;
+import flash.display.InteractiveObject;
+import flash.display.Stage;
+import flash.events.Event;
+import flash.events.EventDispatcher;
+import flash.events.FocusEvent;
+import flash.events.KeyboardEvent;
+import flash.events.MouseEvent;
+import flash.system.Capabilities;
+import flash.system.IME;
+import flash.text.TextField;
+import flash.ui.Keyboard;
+}
+
+COMPILE::LATER
+{
+import mx.core.FlexSprite;
+import mx.core.ISWFLoader;
+import mx.core.IVisualElement;
+}
+import mx.core.IButton;
+import mx.core.IChildList;
+import mx.core.IIMESupport;
+import mx.core.IRawChildrenContainer;
+import mx.core.IToggleButton;
+import mx.core.IUIComponent;
+import mx.core.mx_internal;
+import mx.events.FlexEvent;
+import mx.utils.Platform;
+
+import flex.display.Sprite;
+
+import org.apache.flex.core.IUIBase;
+
+use namespace mx_internal;
+
+/**
+ *  The FocusManager class manages the focus on components in response to mouse
+ *  activity or keyboard activity (Tab key).  There can be several FocusManager
+ *  instances in an application.  Each FocusManager instance 
+ *  is responsible for a set of components that comprise a "tab loop".  If you
+ *  hit Tab enough times, focus traverses through a set of components and
+ *  eventually get back to the first component that had focus.  That is a "tab loop"
+ *  and a FocusManager instance manages that loop.  If there are popup windows
+ *  with their own set of components in a "tab loop" those popup windows will have
+ *  their own FocusManager instances.  The main application always has a
+ *  FocusManager instance.
+ *
+ *  <p>The FocusManager manages focus from the "component level".
+ *  In Flex, a UITextField in a component is the only way to allow keyboard entry
+ *  of text. To the Flash Player or AIR, that UITextField has focus. However, from the 
+ *  FocusManager's perspective the component that parents the UITextField has focus.
+ *  Thus there is a distinction between component-level focus and player-level focus.
+ *  Application developers generally only have to deal with component-level focus while
+ *  component developers must understand player-level focus.</p>
+ *
+ *  <p>All components that can be managed by the FocusManager must implement
+ *  mx.managers.IFocusManagerComponent, whereas objects managed by player-level focus do not.</p>  
+ *
+ *  <p>The FocusManager also managers the concept of a defaultButton, which is
+ *  the Button on a form that dispatches a click event when the Enter key is pressed
+ *  depending on where focus is at that time.</p>
+ *  
+ *  @langversion 3.0
+ *  @playerversion Flash 9
+ *  @playerversion AIR 1.1
+ *  @productversion Flex 3
+ */
+public class FocusManager extends EventDispatcher implements IFocusManager
+{
+    include "../core/Version.as";
+
+	//--------------------------------------------------------------------------
+	//
+	//  Class constants
+	//
+	//--------------------------------------------------------------------------
+
+	/**
+	 * @private
+	 * 
+	 * Default value of parameter, ignore. 
+	 */
+	private static const FROM_INDEX_UNSPECIFIED:int = -2;
+	
+	//--------------------------------------------------------------------------
+	//
+	//  Class variables
+	//
+	//--------------------------------------------------------------------------
+
+	/**
+	 * @private
+	 * 
+	 * Place to hook in additional classes
+	 */
+	public static var mixins:Array;
+
+    // flag to turn on/off some ie specific behavior
+    mx_internal static var ieshifttab:Boolean = true;
+
+    //--------------------------------------------------------------------------
+    //
+    //  Constructor
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  Constructor.
+     *
+     *  <p>A FocusManager manages the focus within the children of an IFocusManagerContainer.
+     *  It installs itself in the IFocusManagerContainer during execution
+     *  of the constructor.</p>
+     *
+     *  @param container An IFocusManagerContainer that hosts the FocusManager.
+     *
+     *  @param popup If <code>true</code>, indicates that the container
+     *  is a popup component and not the main application.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function FocusManager(container:IFocusManagerContainer, popup:Boolean = false)
+    {
+        super();
+
+		this.popup = popup;
+
+        IMEEnabled = true;
+		// Only <= IE8 supported focus cycling out of the SWF
+        browserMode = Capabilities.playerType == "ActiveX" && !popup;
+        desktopMode = Platform.isAir && !popup;
+        // Flash main windows come up activated, AIR main windows don't
+        windowActivated = !desktopMode;
+    
+        container.focusManager = this; // this property name is reserved in the parent
+
+        // trace("FocusManager constructor " + container + ".focusManager");
+        
+        _form = container;
+        
+        focusableObjects = [];
+
+        focusPane = new Sprite();
+        focusPane.name = "focusPane";
+
+        addFocusables(DisplayObject(container));
+        
+        // Listen to the stage so we know when the root application is loaded.
+        container.addEventListener(Event.ADDED, addedHandler);
+        container.addEventListener(Event.REMOVED, removedHandler);
+        container.addEventListener(FlexEvent.SHOW, showHandler);
+        container.addEventListener(FlexEvent.HIDE, hideHandler);
+        container.addEventListener(FlexEvent.HIDE, childHideHandler, true);
+        container.addEventListener("_navigationChange_",viewHideHandler, true);
+        
+        //special case application and window
+        if (container.systemManager is SystemManager)
+        {
+            // special case application.  It shouldn't need to be made
+            // active and because we defer appCreationComplete, this 
+            // would steal focus back from any popups created during
+            // instantiation
+            if (container != SystemManager(container.systemManager).application)
+                container.addEventListener(FlexEvent.CREATION_COMPLETE,
+                                       creationCompleteHandler);
+        }
+        
+		if (mixins)
+		{
+			var n:int = mixins.length;
+			for (var i:int = 0; i < n; i++)
+			{
+				new mixins[i](this);
+			}
+		}
+
+        // Make sure the SystemManager is running so it can tell us about
+        // mouse clicks and stage size changes.
+		try
+		{
+			var awm:IActiveWindowManager = 
+				IActiveWindowManager(container.systemManager.getImplementation("mx.managers::IActiveWindowManager"));
+			if (awm)
+        		awm.addFocusManager(container); // build a message that does the equal
+
+            if (hasEventListener("initialize"))
+		    	dispatchEvent(new Event("initialize"));
+
+		}
+		catch (e:Error)
+		{
+			// ignore null pointer errors caused by container using a 
+			// systemManager from another sandbox.
+		}
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    //  Variables
+    //
+    //--------------------------------------------------------------------------
+
+    private var LARGE_TAB_INDEX:int = 99999;
+
+    mx_internal var calculateCandidates:Boolean = true;
+
+	/**
+	 * @private
+	 * 
+	 * True if this focus manager is a popup, false if it is a main application.
+	 * 
+	 */
+	mx_internal var popup:Boolean;
+
+    /**
+     * @private
+     * 
+     * True if this focus manager will try to enable/disable the IME based on
+     * whether the focused control uses IME.  Leaving this as a backdoor just in case.
+     * 
+     */
+    mx_internal var IMEEnabled:Boolean;
+
+    /**
+     *  @private
+     *  We track whether we've been last activated or saw a TAB
+     *  This is used in browser tab management
+     */
+    mx_internal var lastAction:String;
+
+    /**
+     *  @private
+     *  Tab management changes based on whether were in a browser or not
+     *  This value is also affected by whether you are a modal dialog or not
+     */
+    public var browserMode:Boolean;
+
+    /**
+     *  @private
+     *  Activation changes depending on whether we're running in AIR or not
+     */
+    public var desktopMode:Boolean;
+
+    /**
+     *  @private
+     *  Tab management changes based on whether were in a browser or not
+     *  If non-null, this is the object that will
+     *  lose focus to the browser
+     */
+    private var browserFocusComponent:InteractiveObject;
+
+    /**
+     *  @private
+     *  Total set of all objects that can receive focus
+     *  but might be disabled or invisible.
+     */
+    mx_internal var focusableObjects:Array;
+    
+    /**
+     *  @private
+     *  Filtered set of objects that can receive focus right now.
+     */
+    private var focusableCandidates:Array;
+
+    /**
+     *  @private
+     */
+    private var activated:Boolean;
+    /**
+     *  @private
+     */
+    private var windowActivated:Boolean;
+    
+    /**
+     * 	@private
+     * 
+     * 	true if focus was changed to one of focusable objects. False if focus passed to 
+     * 	the browser.
+     */
+	mx_internal var focusChanged:Boolean;
+
+    /**
+	 * 	@private
+	 * 
+	 * 	if non-null, the location to move focus from instead of the object 
+	 *  that has focus in the stage.
+	 */
+	mx_internal var fauxFocus:DisplayObject;
+	 
+	 
+	//--------------------------------------------------------------------------
+    //
+    //  Properties
+    //
+    //--------------------------------------------------------------------------
+
+    //----------------------------------
+    //  showFocusIndicator
+    //----------------------------------
+
+    /**
+     *  @private
+     *  Storage for the showFocusIndicator property.
+     */
+    mx_internal var _showFocusIndicator:Boolean = false;
+    
+    /**
+     *  @inheritDoc
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get showFocusIndicator():Boolean
+    {
+        return _showFocusIndicator;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set showFocusIndicator(value:Boolean):void
+    {
+        var changed:Boolean = _showFocusIndicator != value;
+        // trace("FM " + this + " showFocusIndicator = " + value);
+        _showFocusIndicator = value;
+
+        if (hasEventListener("showFocusIndicator"))
+            dispatchEvent(new Event("showFocusIndicator"));
+    }
+
+    //----------------------------------
+    //  defaultButton
+    //----------------------------------
+
+    /**
+     *  @private
+     *  The current default button.
+     */
+    private var defButton:IButton;
+
+    /**
+     *  @private
+     */
+    private var _defaultButton:IButton;
+
+    /**
+     *  @inheritDoc
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get defaultButton():IButton
+    {
+		return _defaultButton;
+    }
+
+    /**
+     *  @private
+     *  We don't type the value as Button for dependency reasons
+     */
+    public function set defaultButton(value:IButton):void
+    {
+		var button:IButton = value ? IButton(value) : null;
+
+        if (button != _defaultButton)
+        {
+            if (_defaultButton)
+                _defaultButton.emphasized = false;
+            
+            if (defButton)  
+                defButton.emphasized = false;
+            
+            _defaultButton = button;
+            
+            if (defButton != _lastFocus || _lastFocus == _defaultButton)
+            {
+            	defButton = button;
+            
+           		if (button)
+                	button.emphasized = true;
+        	}
+    	}
+    }
+
+    //----------------------------------
+    //  defaultButtonEnabled
+    //----------------------------------
+
+    /**
+     *  @private
+     *  Storage for the defaultButtonEnabled property.
+     */
+    private var _defaultButtonEnabled:Boolean = true;
+
+    /**
+     *  @inheritDoc
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get defaultButtonEnabled():Boolean
+    {
+        return _defaultButtonEnabled;
+    }
+    
+    /**
+     *  @private
+     */
+    public function set defaultButtonEnabled(value:Boolean):void
+    {
+        _defaultButtonEnabled = value;
+        
+        // Synchronize with the new value. We ensure that our 
+        // default button is de-emphasized if defaultButtonEnabled
+        // is false.
+        if (defButton)
+            defButton.emphasized = value;
+    }
+    
+    //----------------------------------
+    //  focusPane
+    //----------------------------------
+
+    /**
+     *  @private
+     *  Storage for the focusPane property.
+     */
+    private var _focusPane:Sprite;
+
+    /**
+     *  @inheritDoc
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get focusPane():Sprite
+    {
+        return _focusPane;
+    }
+
+    /**
+     *  @private
+     */
+    public function set focusPane(value:Sprite):void
+    {
+        _focusPane = value;
+    }
+
+    //----------------------------------
+    //  form
+    //----------------------------------
+
+    /**
+     *  @private
+     *  Storage for the form property.
+     */
+    private var _form:IFocusManagerContainer;
+    
+    /**
+     *  @private
+     *  The form is the property where we store the IFocusManagerContainer
+     *  that hosts this FocusManager.
+     */
+    mx_internal function get form():IFocusManagerContainer
+    {
+        return _form;
+    }
+    
+    /**
+     *  @private
+     */
+    mx_internal function set form (value:IFocusManagerContainer):void
+    {
+        _form = value;
+    }
+
+
+    //----------------------------------
+    //  _lastFocus
+    //----------------------------------
+    
+    /**
+     *  @private
+     *  the object that last had focus
+     */
+    private var _lastFocus:IFocusManagerComponent;
+
+
+	/**
+	 * 	@private
+	 */
+	mx_internal function get lastFocus():IFocusManagerComponent
+	{
+		return _lastFocus;
+	}
+	 
+	/**
+	 * 	@private
+	 */
+	mx_internal function set lastFocus(value:IFocusManagerComponent):void
+	{
+		_lastFocus = value;
+	}
+
+    //----------------------------------
+    //  nextTabIndex
+    //----------------------------------
+
+    /**
+     *  @inheritDoc
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function get nextTabIndex():int
+    {
+        return getMaxTabIndex() + 1;
+    }
+
+    /**
+     *  Gets the highest tab index currently used in this Focus Manager's form or subform.
+     *
+     *  @return Highest tab index currently used.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    private function getMaxTabIndex():int
+    {
+        var z:Number = 0;
+
+        var n:int = focusableObjects.length;
+        for (var i:int = 0; i < n; i++)
+        {
+            var t:Number = focusableObjects[i].tabIndex;
+            if (!isNaN(t))
+                z = Math.max(z, t);
+        }
+        
+        return z;
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    //  Methods
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  @inheritDoc
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function getFocus():IFocusManagerComponent
+    {
+        var stage:Stage = form.systemManager.stage;
+        
+        if (!stage)
+            return null;
+            
+        var o:InteractiveObject = stage.focus;
+		var i:IUIBase;
+		while (o != null)
+		{
+			if (o is IUIBase)
+			{
+				i = o as IUIBase;
+				break;
+			}
+			o = o.parent;
+		}
+        
+        // If a Stage* object (such as StageText or StageWebView) has focus,
+        // stage.focus will be set to null. Much of the focus framework is not
+        // set up to handle this. So, if stage.focus is null, we return the last
+        // IFocusManagerComponent that had focus.  In ADL, focus works slightly
+        // different than it does on device when using StageText.  In ADL, when
+        // the focus is a StageText component, a TextField whose parent is the 
+        // stage is assigned focus.  
+        if ((!o && _lastFocus) || (o is TextField && o.parent == stage))
+            return _lastFocus;
+        
+        return findFocusManagerComponent(i);
+    }
+
+    /**
+     *  @inheritDoc
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function setFocus(o:IFocusManagerComponent):void
+    {
+        // trace("FM " + this + " setting focus to " + o);
+
+        o.setFocus();
+        
+        if (hasEventListener("setFocus"))
+    		dispatchEvent(new Event("setFocus"));
+        // trace("FM set focus");
+    }
+
+    /**
+     *  @private
+     */
+    private function focusInHandler(event:FocusEvent):void
+    {
+        var target:InteractiveObject = InteractiveObject(event.target);
+        // trace("FocusManager focusInHandler in  = " + this._form.systemManager.loaderInfo.url);
+        // trace("FM " + this + " focusInHandler " + target);
+
+		// dispatch cancelable FocusIn to see if Marshal Plan mixin wants it
+        if (hasEventListener(FocusEvent.FOCUS_IN))
+    		if (!dispatchEvent(new FocusEvent(FocusEvent.FOCUS_IN, false, true, target)))
+    			return;
+
+        if (isParent(DisplayObjectContainer(form), target))
+        {
+            if (_defaultButton)
+            {
+                if (target is IButton && target != _defaultButton 
+                    && !(target is IToggleButton))
+                    _defaultButton.emphasized = false;
+                else if (_defaultButtonEnabled)
+                    _defaultButton.emphasized = true;
+            }
+ 
+			var o:InteractiveObject = target;
+			var i:IUIBase;
+			while (o != null)
+			{
+				if (o is IUIBase)
+				{
+					i = o as IUIBase;
+					break;
+				}
+				o = o.parent;
+			}
+            // trace("FM " + this + " setting last focus " + target);
+            _lastFocus = findFocusManagerComponent(i);
+            
+			if (Capabilities.hasIME)
+            {
+                var usesIME:Boolean;
+                if (_lastFocus is IIMESupport)
+                {
+                    var imeFocus:IIMESupport = IIMESupport(_lastFocus);
+                    if (imeFocus.enableIME)
+                        usesIME = true;
+                }
+                if (IMEEnabled)
+                    IME.enabled = usesIME;
+            }
+            
+			// handle default button here
+			// we can't check for Button because of cross-versioning so
+			// for now we just check for an emphasized property
+            if (_lastFocus is IButton && !(_lastFocus is IToggleButton))
+			{
+                defButton = _lastFocus as IButton;
+			}
+			else
+			{
+				// restore the default button to be the original one
+				if (defButton && defButton != _defaultButton)
+					defButton = _defaultButton;
+			}
+		}
+	}
+
+    /**
+     *  @private  Useful for debugging
+     */
+    private function focusOutHandler(event:FocusEvent):void
+    {
+        var target:InteractiveObject = InteractiveObject(event.target);
+        // trace("FocusManager focusOutHandler in  = " + this._form.systemManager.loaderInfo.url);
+        // trace("FM " + this + " focusOutHandler " + target);
+    }
+
+    /**
+     *  @private
+     *  restore focus to whoever had it last
+     */
+    private function activateHandler(event:Event):void
+    {
+//        var target:InteractiveObject = InteractiveObject(event.target);
+        // trace("FM " + this + " activateHandler ", _lastFocus);
+		
+        // if we were the active FM when we were deactivated
+        // and we're not running in AIR, then dispatch the event now
+        // otherwise wait for the AIR events to fire
+        if (activated && !desktopMode)
+        {
+            dispatchEvent(new FlexEvent(FlexEvent.FLEX_WINDOW_ACTIVATE));
+		    // restore focus if this focus manager had last focus
+            if (_lastFocus && (!browserMode || ieshifttab))
+	    	    _lastFocus.setFocus();
+	        lastAction = "ACTIVATE";
+        }
+    }
+
+    /**
+     *  @private  
+     *  Dispatch event if we're not running in AIR.  AIR will
+     *  dispatch windowDeactivate that we respond to instead
+     */
+    private function deactivateHandler(event:Event):void
+    {
+        // var target:InteractiveObject = InteractiveObject(event.target);
+        // trace("FM " + this + " deactivateHandler ", _lastFocus);
+
+        // if we are the active FM when we were deactivated
+        // and we're not running in AIR, then dispatch the event now
+        // otherwise wait for the AIR events to fire
+        if (activated && !desktopMode)
+        {
+            dispatchEvent(new FlexEvent(FlexEvent.FLEX_WINDOW_DEACTIVATE));
+        }
+    }
+
+    /**
+     *  @private
+     *  restore focus to whoever had it last
+     */
+    private function activateWindowHandler(event:Event):void
+    {
+//        var target:InteractiveObject = InteractiveObject(event.target);
+        // trace("FM " + this + " activateWindowHandler ", _lastFocus);
+		
+        windowActivated = true;
+
+        if (activated)
+        {
+            dispatchEvent(new FlexEvent(FlexEvent.FLEX_WINDOW_ACTIVATE));
+		    // restore focus if this focus manager had last focus
+	        if (_lastFocus && !browserMode)
+	    	    _lastFocus.setFocus();
+	        lastAction = "ACTIVATE";
+        }
+    }
+
+    /**
+     *  @private  
+     *  If we're responsible for the focused control, remove focus from it
+     *  so it gets the same events as it would if the whole app lost focus
+     */
+    private function deactivateWindowHandler(event:Event):void
+    {
+        // var target:InteractiveObject = InteractiveObject(event.target);
+        // trace("FM " + this + " deactivateWindowHandler ", _lastFocus);
+
+        windowActivated = false;
+
+        if (activated)
+        {
+            dispatchEvent(new FlexEvent(FlexEvent.FLEX_WINDOW_DEACTIVATE));
+            if (form.systemManager.stage)
+                form.systemManager.stage.focus = null;
+        }
+    }   
+
+    /**
+     *  @inheritDoc
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function showFocus():void
+    {
+        if (!showFocusIndicator)
+        {
+            showFocusIndicator = true;
+            if (_lastFocus)
+                _lastFocus.drawFocus(true);
+        }
+    }
+
+    /**
+     *  @inheritDoc
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function hideFocus():void
+    {
+        // trace("FOcusManger " + this + " Hide Focus");
+        if (showFocusIndicator)
+        {
+            showFocusIndicator = false;
+            if (_lastFocus)
+                _lastFocus.drawFocus(false);
+        }
+        // trace("END FOcusManger Hide Focus");
+    }
+    
+    /**
+     *  The SystemManager activates and deactivates a FocusManager
+     *  if more than one IFocusManagerContainer is visible at the same time.
+     *  If the mouse is clicked in an IFocusManagerContainer with a deactivated
+     *  FocusManager, the SystemManager will call 
+     *  the <code>activate()</code> method on that FocusManager.
+     *  The FocusManager that was activated will have its <code>deactivate()</code> method
+     *  called prior to the activation of another FocusManager.
+     *
+     *  <p>The FocusManager adds event handlers that allow it to monitor
+     *  focus related keyboard and mouse activity.</p>
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function activate():void
+    {
+        // we can get a double activation if we're popping up and becoming visible
+        // like the second time a menu appears
+        if (activated)
+        {
+        	// trace("FocusManager is already active " + this);
+            return;
+        }
+
+        // trace("FocusManager activating = " + this._form.systemManager.loaderInfo.url);
+        // trace("FocusManager activating " + this);
+
+        // listen for focus changes, use weak references for the stage
+		// form.systemManager can be null if the form is created in a sandbox and 
+		// added as a child to the root system manager.
+		var sm:ISystemManager = form.systemManager;
+		if (sm)
+		{
+			if (sm.isTopLevelRoot())
+			{
+		        sm.stage.addEventListener(FocusEvent.MOUSE_FOCUS_CHANGE, mouseFocusChangeHandler, false, 0, true);
+		        sm.stage.addEventListener(FocusEvent.KEY_FOCUS_CHANGE, keyFocusChangeHandler, false, 0, true);
+	    	    sm.stage.addEventListener(Event.ACTIVATE, activateHandler, false, 0, true);
+	        	sm.stage.addEventListener(Event.DEACTIVATE, deactivateHandler, false, 0, true);
+	  		}
+	  		else
+	  		{
+		        sm.addEventListener(FocusEvent.MOUSE_FOCUS_CHANGE, mouseFocusChangeHandler, false, 0, true);
+		        sm.addEventListener(FocusEvent.KEY_FOCUS_CHANGE, keyFocusChangeHandler, false, 0, true);
+	    	    sm.addEventListener(Event.ACTIVATE, activateHandler, false, 0, true);
+	        	sm.addEventListener(Event.DEACTIVATE, deactivateHandler, false, 0, true);	  			
+	  		}
+		}      
+	        
+        form.addEventListener(FocusEvent.FOCUS_IN, focusInHandler, true);
+        form.addEventListener(FocusEvent.FOCUS_OUT, focusOutHandler, true);
+        form.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler); 
+        form.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownCaptureHandler, true); 
+        form.addEventListener(KeyboardEvent.KEY_DOWN, defaultButtonKeyHandler);
+        form.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler, true);
+        if (sm)
+        {
+            // AIR Window events, but don't want to link in AIREvent
+            // use capture phase because these get sent by the main Window
+            // and we might be managing a popup in that window
+            sm.addEventListener("windowActivate", activateWindowHandler, true, 0, true);
+            sm.addEventListener("windowDeactivate", deactivateWindowHandler, true, 0, true);
+        }
+
+        activated = true;
+        dispatchEvent(new FlexEvent(FlexEvent.FLEX_WINDOW_ACTIVATE));
+        
+        // Restore focus to the last control that had it if there was one.
+        if (_lastFocus)
+            setFocus(_lastFocus);
+
+        if (hasEventListener("activateFM"))
+    		dispatchEvent(new Event("activateFM"));
+
+    }
+
+    /**
+     *  The SystemManager activates and deactivates a FocusManager
+     *  if more than one IFocusManagerContainer is visible at the same time.
+     *  If the mouse is clicked in an IFocusManagerContainer with a deactivated
+     *  FocusManager, the SystemManager will call 
+     *  the <code>activate()</code> method on that FocusManager.
+     *  The FocusManager that was activated will have its <code>deactivate()</code> method
+     *  called prior to the activation of another FocusManager.
+     *
+     *  <p>The FocusManager removes event handlers that allow it to monitor
+     *  focus related keyboard and mouse activity.</p>
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function deactivate():void
+    {
+        // trace("FocusManager deactivating " + this);
+        // trace("FocusManager deactivating = " + this._form.systemManager.loaderInfo.url);
+         
+        // listen for focus changes
+		var sm:ISystemManager = form.systemManager;
+        if (sm)
+        {
+			if (sm.isTopLevelRoot())
+			{
+		        sm.stage.removeEventListener(FocusEvent.MOUSE_FOCUS_CHANGE, mouseFocusChangeHandler);
+		        sm.stage.removeEventListener(FocusEvent.KEY_FOCUS_CHANGE, keyFocusChangeHandler);
+	    	    sm.stage.removeEventListener(Event.ACTIVATE, activateHandler);
+	        	sm.stage.removeEventListener(Event.DEACTIVATE, deactivateHandler);
+	  		}
+	  		else
+	  		{
+		        sm.removeEventListener(FocusEvent.MOUSE_FOCUS_CHANGE, mouseFocusChangeHandler);
+		        sm.removeEventListener(FocusEvent.KEY_FOCUS_CHANGE, keyFocusChangeHandler);
+	    	    sm.removeEventListener(Event.ACTIVATE, activateHandler);
+	        	sm.removeEventListener(Event.DEACTIVATE, deactivateHandler);	  			
+	  		}
+        }
+
+        form.removeEventListener(FocusEvent.FOCUS_IN, focusInHandler, true);
+        form.removeEventListener(FocusEvent.FOCUS_OUT, focusOutHandler, true);
+        form.removeEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler); 
+        form.removeEventListener(MouseEvent.MOUSE_DOWN, mouseDownCaptureHandler, true); 
+        form.removeEventListener(KeyboardEvent.KEY_DOWN, defaultButtonKeyHandler);
+        // stop listening for default button in Capture phase
+        form.removeEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler, true);
+
+        activated = false;
+        dispatchEvent(new FlexEvent(FlexEvent.FLEX_WINDOW_DEACTIVATE));
+
+        if (hasEventListener("deactivateFM"))
+    		dispatchEvent(new Event("deactivateFM"));
+    }
+
+    /**
+     *  @inheritDoc
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function findFocusManagerComponent(
+                            o:IUIBase):IFocusManagerComponent
+    {
+    	return findFocusManagerComponent2(o as InteractiveObject) as IFocusManagerComponent;
+    }
+    
+    
+    /**
+    * @private
+    * 
+    * This version of the method differs from the old one to support SWFLoader
+    * being in the focusableObjects list but not being a component that
+    * gets focus. SWFLoader is in the list of focusable objects so
+    * focus may be passed over a bridge to the components on the other
+    * side of the bridge.
+    */
+    private function findFocusManagerComponent2(
+                            o:InteractiveObject):DisplayObject
+
+    {
+    	try
+    	{
+	        while (o)
+	        {
+				COMPILE::LATER
+				{
+	            if ((o is IFocusManagerComponent && IFocusManagerComponent(o).focusEnabled) ||
+	            	 o is ISWFLoader)
+	                return o;
+				}
+				if (o is IFocusManagerComponent && IFocusManagerComponent(o).focusEnabled)
+					return o as DisplayObject;
+				
+	            o = o.parent;
+	        }
+	    }
+	    catch (error:SecurityError)
+	    {
+	    	// can happen in a loaded child swf
+	    	// trace("findFocusManagerComponent: handling security error");
+	    }
+
+        // tab was set somewhere else
+        return null;
+    }
+
+    /**
+     *  @private
+     *  Returns true if p is a parent of o.
+     */
+    private function isParent(p:DisplayObjectContainer, o:DisplayObject):Boolean
+    {
+        if (p == o)
+            return false;
+        
+        if (p is IRawChildrenContainer)
+            return IRawChildrenContainer(p).rawChildren.contains(o);
+        
+        return p.contains(o);
+    }
+    
+    private function isEnabledAndVisible(o:DisplayObject):Boolean
+    {
+        var formParent:DisplayObjectContainer = DisplayObjectContainer(form);
+        
+        while (o != formParent)
+        {
+            if (o is IUIComponent)
+                if (!IUIComponent(o).enabled)
+                    return false;
+            
+			COMPILE::LATER
+			{
+            if (o is IVisualElement)
+                if (IVisualElement(o).designLayer && !IVisualElement(o).designLayer.effectiveVisibility)
+                    return false;
+			}
+			
+            if (!o.visible) 
+                return false;
+            o = o.parent;
+
+            // if no parent, then not on display list
+            if (!o)
+                return false;
+        }
+        return true;
+    }
+
+    /**
+     *  @private
+     */
+    private function sortByTabIndex(a:InteractiveObject, b:InteractiveObject):int
+    {
+        var aa:int = a.tabIndex;
+        var bb:int = b.tabIndex;
+
+        if (aa == -1)
+            aa = int.MAX_VALUE;
+        if (bb == -1)
+            bb = int.MAX_VALUE;
+
+        return (aa > bb ? 1 :
+                aa < bb ? -1 : sortByDepth(DisplayObject(a), DisplayObject(b)));
+    }
+
+    /**
+     *  @private
+     */
+    private function sortFocusableObjectsTabIndex():void
+    {
+        // trace("FocusableObjectsTabIndex");
+        
+        focusableCandidates = [];
+        
+        var n:int = focusableObjects.length;
+        for (var i:int = 0; i < n; i++)
+        {
+            var c:IFocusManagerComponent = focusableObjects[i] as IFocusManagerComponent;
+			COMPILE::LATER
+			{
+				if ((c && c.tabIndex && !isNaN(Number(c.tabIndex))) ||
+					focusableObjects[i] is ISWFLoader)
+				{
+					// if we get here, it is a candidate
+					focusableCandidates.push(focusableObjects[i]);
+				}
+			}
+			if (c && c.tabIndex && !isNaN(Number(c.tabIndex)))
+			{
+				// if we get here, it is a candidate
+				focusableCandidates.push(focusableObjects[i]);
+			}
+        }
+        
+        focusableCandidates.sort(sortByTabIndex);
+    }
+
+    /**
+     *  @private
+     */
+    private function sortByDepth(aa:DisplayObject, bb:DisplayObject):Number
+    {
+        var val1:String = "";
+        var val2:String = "";
+        var index:int;
+        var tmp:String;
+        var tmp2:String;
+        var zeros:String = "0000";
+
+        var a:DisplayObject = DisplayObject(aa);
+        var b:DisplayObject = DisplayObject(bb);
+
+		// TODO (egreenfi):  If a component lives inside of a group, we care about not its display object index, but
+		// its index within the group. See SDK-25144
+		
+        while (a != DisplayObject(form) && a.parent)
+        {
+            index = getChildIndex(a.parent, a);
+            tmp = index.toString(16);
+            if (tmp.length < 4)
+            {
+                tmp2 = zeros.substring(0, 4 - tmp.length) + tmp;
+            }
+            val1 = tmp2 + val1;
+            a = a.parent;
+        }
+        
+        while (b != DisplayObject(form) && b.parent)
+        {
+            index = getChildIndex(b.parent, b);
+            tmp = index.toString(16);
+            if (tmp.length < 4)
+            {
+                tmp2 = zeros.substring(0, 4 - tmp.length) + tmp;
+            }
+            val2 = tmp2 + val2;
+            b = b.parent;
+        }
+
+        return val1 > val2 ? 1 : val1 < val2 ? -1 : 0;
+    }
+
+    private function getChildIndex(parent:DisplayObjectContainer, child:DisplayObject):int
+    {
+        try 
+        {
+            return parent.getChildIndex(child);
+        }
+        catch(e:Error)
+        {
+            if (parent is IRawChildrenContainer)
+                return IRawChildrenContainer(parent).rawChildren.getChildIndex(child);
+            throw e;
+        }
+        throw new Error("FocusManager.getChildIndex failed");   // shouldn't ever get here
+    }
+
+    /**
+     *  @private
+     *  Calculate what focusableObjects are valid tab candidates.
+     */
+    private function sortFocusableObjects():void
+    {
+        // trace("FocusableObjects " + focusableObjects.length.toString());
+        focusableCandidates = [];
+        
+        var n:int = focusableObjects.length;
+        for (var i:int = 0; i < n; i++)
+        {
+            var c:InteractiveObject = focusableObjects[i];
+            // trace("  " + c);
+            if (c.tabIndex && !isNaN(Number(c.tabIndex)) && c.tabIndex > 0)
+            {
+                sortFocusableObjectsTabIndex();
+                return;
+            }
+            focusableCandidates.push(c);
+        }
+        
+        focusableCandidates.sort(sortByDepth);
+    }
+
+    /**
+     *  Call this method to make the system
+     *  think the Enter key was pressed and the defaultButton was clicked
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    mx_internal function sendDefaultButtonEvent():void
+    {
+        // trace("FocusManager.sendDefaultButtonEvent " + defButton);
+        defButton.dispatchEvent(new MouseEvent("click"));
+    }
+
+    /**
+     *  @private
+     *  Do a tree walk and add all children you can find.
+     */
+    mx_internal function addFocusables(o:DisplayObject, skipTopLevel:Boolean = false):void
+    {
+        // trace(">>addFocusables " + o);
+        if ((o is IFocusManagerComponent) && !skipTopLevel)
+        {
+			
+			var addToFocusables:Boolean = false;
+        	if (o is IFocusManagerComponent)
+        	{
+	            var focusable:IFocusManagerComponent = IFocusManagerComponent(o);
+	            if (focusable.focusEnabled)
+	            {
+	                if (focusable.tabFocusEnabled && isTabVisible(o))
+	                {
+						addToFocusables = true;	                	
+	                }
+                }
+            }
+
+			if (addToFocusables)
+			{            
+               	if (focusableObjects.indexOf(o) == -1)
+            	{
+                    focusableObjects.push(o);
+	                calculateCandidates = true;
+    	            // trace("FM added " + o);
+    	        }
+   			}
+            o.addEventListener("tabFocusEnabledChange", tabFocusEnabledChangeHandler);
+            o.addEventListener("tabIndexChange", tabIndexChangeHandler);
+
+        }
+        
+        if (o is DisplayObjectContainer)
+        {
+            var doc:DisplayObjectContainer = DisplayObjectContainer(o);
+            // Even if they aren't focusable now,
+            // listen in case they become later.
+            var checkChildren:Boolean;
+
+            if (o is IFocusManagerComponent)
+            {
+                o.addEventListener("hasFocusableChildrenChange", hasFocusableChildrenChangeHandler);
+                checkChildren = IFocusManagerComponent(o).hasFocusableChildren;
+            }
+            else
+            {
+                o.addEventListener("tabChildrenChange", tabChildrenChangeHandler);
+                checkChildren = doc.tabChildren;
+            }
+
+            if (checkChildren)
+            {
+                if (o is IRawChildrenContainer)
+                {
+                    // trace("using view rawChildren");
+                    var rawChildren:IChildList = IRawChildrenContainer(o).rawChildren;
+                    // recursively visit and add children of components
+                    // we don't do this for containers because we get individual
+                    // adds for the individual children
+                    var i:int;
+                    for (i = 0; i < rawChildren.numChildren; i++)
+                    {
+                        try
+                        {
+                            addFocusables(rawChildren.getChildAt(i));
+                        }
+                        catch(error:SecurityError)
+                        {
+                            // Ignore this child if we can't access it
+                            // trace("addFocusables: ignoring security error getting child from rawChildren: " + error);
+                        }
+                    }
+
+                }
+                else
+                {
+                    // trace("using container's children");
+                    // recursively visit and add children of components
+                    // we don't do this for containers because we get individual
+                    // adds for the individual children
+                    for (i = 0; i < doc.numChildren; i++)
+                    {
+                        try
+                        {
+                            addFocusables(doc.getChildAt(i));
+                        }
+                        catch(error:SecurityError)
+                        {
+                            // Ignore this child if we can't access it
+                            // trace("addFocusables: ignoring security error getting child at document." + error);
+                        }
+                    }
+                }
+            }
+        }
+        // trace("<<addFocusables " + o);
+    }
+
+    /**
+     *  @private
+     *  is it really tabbable?
+     */
+    private function isTabVisible(o:DisplayObject):Boolean
+    {
+        var s:DisplayObject = DisplayObject(form.systemManager);
+        if (!s) return false;
+
+        var p:DisplayObjectContainer = o.parent;
+        while (p && p != s)
+        {
+            if (!p.tabChildren)
+                return false;
+            if (p is IFocusManagerComponent && !(IFocusManagerComponent(p).hasFocusableChildren))
+                return false;
+            p = p.parent;
+        }
+        return true;
+    }
+
+    private function isValidFocusCandidate(o:DisplayObject, g:String):Boolean
+    {
+        if (o is IFocusManagerComponent)
+            if (!IFocusManagerComponent(o).focusEnabled)
+                return false;
+
+        if (!isEnabledAndVisible(o))
+            return false;
+
+        if (o is IFocusManagerGroup)
+        {
+            // reject if it is in the same tabgroup
+            var tg:IFocusManagerGroup = IFocusManagerGroup(o);
+            if (g == tg.groupName) return false;
+        }
+        return true;
+    }
+    
+    private function getIndexOfFocusedObject(o:DisplayObject):int
+    {
+        if (!o)
+            return -1;
+
+        var n:int = focusableCandidates.length;
+        // trace(" focusableCandidates " + n);
+        var i:int = 0;
+        for (i = 0; i < n; i++)
+        {
+            // trace(" comparing " + focusableCandidates[i]);
+            if (focusableCandidates[i] == o)
+                return i;
+        }
+
+        // no match?  try again with a slower match for certain
+        // cases like DG editors
+        for (i = 0; i < n; i++)
+        {
+            var iui:IUIComponent = focusableCandidates[i] as IUIComponent;
+            if (iui && iui.owns(o))
+                return i;
+        }
+
+        return -1;
+    }
+
+
+    private function getIndexOfNextObject(i:int, shiftKey:Boolean, bSearchAll:Boolean, groupName:String):int
+    {
+        var n:int = focusableCandidates.length;
+        var start:int = i;
+
+        while (true)
+        {
+            if (shiftKey)
+                i--;
+            else
+                i++;
+            if (bSearchAll)
+            {
+                if (shiftKey && i < 0)
+                    break;
+                if (!shiftKey && i == n)
+                    break;
+            }
+            else
+            {
+                i = (i + n) % n;
+                // came around and found the original
+                if (start == i)
+                    break;
+                // if start is -1, set start to first valid value of i
+                if (start == -1)
+                    start = i;
+            }
+            // trace("testing " + focusableCandidates[i]);
+            if (isValidFocusCandidate(focusableCandidates[i], groupName))
+            {
+                // trace(" stopped at " + i);
+                var o:DisplayObject = DisplayObject(findFocusManagerComponent2(focusableCandidates[i]));     
+                if (o is IFocusManagerGroup)
+                {
+                    
+                    // when landing on an element that is part of group, try to
+                    // advance selection to the selected group element
+                    var j:int;
+                    var obj:DisplayObject;
+                    var tg1:IFocusManagerGroup = IFocusManagerGroup(o);
+                    var tg2:IFocusManagerGroup;
+                    
+                    // normalize the "no selected group element" case
+                    // to the "first group element selected" case
+                    // (respecting the tab direction)
+                    var groupElementToFocus:IFocusManagerGroup = null;
+                    for (j = 0; j < focusableCandidates.length; j++)
+                    {
+                        obj = focusableCandidates[j];
+                        if (obj is IFocusManagerGroup)
+                        {
+                            tg2 = IFocusManagerGroup(obj);
+                            if (tg2.groupName == tg1.groupName && isEnabledAndVisible(obj) &&
+                                tg2["document"] == tg1["document"])
+                            {
+                                if (tg2.selected) 
+                                {
+                                    groupElementToFocus = tg2;
+                                    break;
+                                }
+                                if ((!shiftKey && groupElementToFocus == null) || shiftKey)
+                                    groupElementToFocus = tg2;
+                            }
+                        }
+                    }
+                    
+                    if (tg1 != groupElementToFocus)
+                    {
+                        var foundAnotherGroup:Boolean = false;
+                        // cycle the entire focusable candidates array forward or backward,
+                        // wrapping around boundaries, searching for our focus candidate
+                        j = i;
+                        for (var k:int = 0; k < focusableCandidates.length - 1; k++)
+                        {
+                            
+                            if (!shiftKey) 
+                            {
+                                j++;
+                                if (j == focusableCandidates.length)
+                                    j = 0;
+                            }
+                            else
+                            {
+                                j--;
+                                if (j == -1)
+                                    j = focusableCandidates.length - 1;
+                            }
+                            
+                            obj = focusableCandidates[j];
+                            if (isEnabledAndVisible(obj))
+                            {
+                                if (foundAnotherGroup)
+                                {
+                                    // we're now just trying to find a selected member of this group
+                                    if (obj is IFocusManagerGroup)
+                                    {
+                                        tg2 = IFocusManagerGroup(obj);
+                                        if (tg2.groupName == tg1.groupName && tg2["document"] == tg1["document"])
+                                        {
+                                            if (tg2.selected)
+                                            {
+                                                i = j;
+                                                break;
+                                            }
+                                        }
+                                    }
+                                }
+                                else if (obj is IFocusManagerGroup)
+                                {
+                                    tg2 = IFocusManagerGroup(obj);
+                                    if (tg2.groupName == tg1.groupName && tg2["document"] == tg1["document"])
+                                    {
+                                        if (tg2 == groupElementToFocus)
+                                        {
+                                            // if objects of same group have different tab index
+                                            // skip you aren't selected.
+                                            if (InteractiveObject(obj).tabIndex != InteractiveObject(o).tabIndex && !tg1.selected)
+                                                return getIndexOfNextObject(i, shiftKey, bSearchAll, groupName);
+                                            i = j;
+                                            break;
+                                        }
+                                    }
+                                    else
+                                    {
+                                        // switch to new group and hunt for selected item
+                                        tg1 = tg2;
+                                        i = j;
+                                        // element is part of another group, stop if selected
+                                        if (tg2.selected)
+                                            break;
+                                        else
+                                            foundAnotherGroup = true;
+                                    }
+                                }
+                                else
+                                {
+                                    // element isn't part of any group, stop
+                                    i = j;
+                                    break;
+                                }
+                            }
+                        }
+                    }
+                }
+                return i;
+            }
+        }
+        return i;
+    }
+
+    /**
+     *  @private
+     */
+    private function setFocusToNextObject(event:FocusEvent):void
+    {
+     	focusChanged = false;
+        if (focusableObjects.length == 0)
+            return;
+
+		var focusInfo:FocusInfo = getNextFocusManagerComponent2(event.shiftKey, fauxFocus);
+		// trace("winner = ", focusInfo.displayObject);
+
+		// If we are about to wrap focus around, send focus back to the parent.
+		if (!popup && (focusInfo.wrapped || !focusInfo.displayObject))
+		{
+            if (hasEventListener("focusWrapping"))
+	    		if (!dispatchEvent(new FocusEvent("focusWrapping", false, true, null, event.shiftKey)))
+		    		return;
+		}
+		
+		if (!focusInfo.displayObject)
+		{
+			event.preventDefault();
+			return;
+		}
+
+		setFocusToComponent(focusInfo.displayObject, event.shiftKey);		
+	}
+
+	private function setFocusToComponent(o:Object, shiftKey:Boolean):void
+	{
+		focusChanged = false;
+		if (o)
+		{
+            if (hasEventListener("setFocusToComponent"))
+    			if (!dispatchEvent(new FocusEvent("setFocusToComponent", false, true, InteractiveObject(o), shiftKey)))
+	    			return;
+
+			if (o is IFocusManagerComplexComponent)
+			{
+				IFocusManagerComplexComponent(o).assignFocus(shiftKey ? "bottom" : "top");
+				focusChanged = true;
+			}
+			else if (o is IFocusManagerComponent)
+			{
+				setFocus(IFocusManagerComponent(o));
+				focusChanged = true;
+			}
+				
+		}
+		
+	}
+
+	/**
+	 *  @private
+	 */
+	mx_internal function setFocusToNextIndex(index:int, shiftKey:Boolean):void
+	{
+		if (focusableObjects.length == 0)
+			return;
+			
+        // I think we'll have time to do this here instead of at creation time
+        // this makes and orders the focusableCandidates array
+        if (calculateCandidates)
+        {
+            sortFocusableObjects();
+            calculateCandidates = false;
+        }
+
+		var focusInfo:FocusInfo = getNextFocusManagerComponent2(shiftKey, null, index);			
+
+		// If we are about to wrap focus around, send focus back to the parent.
+		if (!popup && focusInfo.wrapped)
+		{
+            if (hasEventListener("setFocusToNextIndex"))
+    			if (!dispatchEvent(new FocusEvent("setFocusToNextIndex", false, true, null, shiftKey)))
+	    			return;
+		}
+		
+		setFocusToComponent(focusInfo.displayObject, shiftKey);
+	}
+	
+    /**
+     *  @inheritDoc
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    public function getNextFocusManagerComponent(
+                            backward:Boolean = false):IFocusManagerComponent
+	{
+        const focusInfo:FocusInfo = getNextFocusManagerComponent2(backward, fauxFocus); 
+        return focusInfo ? focusInfo.displayObject as IFocusManagerComponent : null; 
+	}
+	
+	/**
+	 * Find the next object to set focus to.
+	 * 
+	 * @param backward true if moving in the backwards in the tab order, false if moving forward.
+	 * @param fromObject object to move focus from, if null move from the current focus.
+	 * @param formIndex index to move focus from, if specified use fromIndex to find the 
+	 * 		   			object, not fromObject.
+	 *  
+	 *  @langversion 3.0
+	 *  @playerversion Flash 9
+	 *  @playerversion AIR 1.1
+	 *  @productversion Flex 3
+	 */
+	private function getNextFocusManagerComponent2(
+                            backward:Boolean = false, 
+                            fromObject:DisplayObject = null,
+                            fromIndex:int = FROM_INDEX_UNSPECIFIED):FocusInfo
+                            
+    {
+        if (focusableObjects.length == 0)
+            return null;
+
+        // I think we'll have time to do this here instead of at creation time
+        // this makes and orders the focusableCandidates array
+        if (calculateCandidates)
+        {
+            sortFocusableObjects();
+            calculateCandidates = false;
+        }
+
+        // trace("focus was at " + fromObject);
+        // trace("focusableObjects " + focusableObjects.length);
+        var i:int = fromIndex;
+        if (fromIndex == FROM_INDEX_UNSPECIFIED)
+        {
+	        // if there is no passed in object, then get the object that has the focus
+    	    var o:DisplayObject = fromObject; 
+        	if (!o)
+        		o = form.systemManager.stage.focus;
+            else if (o == form.systemManager.stage)
+                o == null;
+        
+	        o = DisplayObject(findFocusManagerComponent2(InteractiveObject(o)));
+	
+	        var g:String = "";
+	        if (o is IFocusManagerGroup)
+	        {
+	            var tg:IFocusManagerGroup = IFocusManagerGroup(o);
+	            g = tg.groupName;
+	        }
+	        i = getIndexOfFocusedObject(o);
+        }
+        
+        // trace(" starting at " + i);
+        var bSearchAll:Boolean = false;
+        var start:int = i;
+        if (i == -1) // we didn't find it
+        {
+            if (backward)
+                i = focusableCandidates.length;
+            bSearchAll = true;
+            // trace("search all " + i);
+        }
+
+        var j:int = getIndexOfNextObject(i, backward, bSearchAll, g);
+
+        // if we wrapped around, get if we have a parent we should pass
+        // focus to.
+        var wrapped:Boolean = false;
+        if (backward)
+        {
+        	if (j >= i)
+        		wrapped = true;
+        }
+        else if (j <= i)
+      		wrapped = true;
+
+		var focusInfo:FocusInfo = new FocusInfo();
+		
+		focusInfo.displayObject = findFocusManagerComponent2(focusableCandidates[j]);
+		focusInfo.wrapped = wrapped;
+		
+        return focusInfo;
+    }
+
+
+    /**
+     *  @private
+     */
+    private function getTopLevelFocusTarget(o:InteractiveObject):InteractiveObject
+    {
+        while (o != InteractiveObject(form))
+        {
+            if (o is IFocusManagerComponent &&
+                IFocusManagerComponent(o).focusEnabled &&
+                IFocusManagerComponent(o).mouseFocusEnabled &&
+                (o is IUIComponent ? IUIComponent(o).enabled : true))
+                return o;
+
+            if (hasEventListener("getTopLevelFocusTarget"))
+    			if (!dispatchEvent(new FocusEvent("getTopLevelFocusTarget", false, true, o.parent)))
+			    	return null;
+
+            o = o.parent;
+
+            if (o == null)
+                break;
+        }
+
+        return null;
+    }
+
+    /**
+     *  Returns a String representation of the component hosting the FocusManager object, 
+     *  with the String <code>".focusManager"</code> appended to the end of the String.
+     *
+     *  @return Returns a String representation of the component hosting the FocusManager object, 
+     *  with the String <code>".focusManager"</code> appended to the end of the String.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 9
+     *  @playerversion AIR 1.1
+     *  @productversion Flex 3
+     */
+    override public function toString():String
+    {
+        return Object(form).toString() + ".focusManager";
+    }
+    
+    /**
+     *  @private
+     * 
+     *  Clear the browser focus component and undo any tab index we may have set.
+     */
+    private function clearBrowserFocusComponent():void
+    {
+        if (browserFocusComponent)
+        {
+            if (browserFocusComponent.tabIndex == LARGE_TAB_INDEX)
+                browserFocusComponent.tabIndex = -1;
+            
+            browserFocusComponent = null;
+        }
+    }
+    
+    //--------------------------------------------------------------------------
+    //
+    //  Event handlers
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  @private
+     *  Listen for children being added
+     *  and see if they are focus candidates.
+     */
+    private function addedHandler(event:Event):void
+    {
+        var target:DisplayObject = DisplayObject(event.target);
+        
+        // trace("FM: addedHandler: got added for " + target);
+        
+        // if it is truly parented, add it, otherwise it will get added when the top of the tree
+        // gets parented.
+        if (target.stage)
+        {
+            // trace("FM: addedHandler: adding focusables");
+            addFocusables(DisplayObject(event.target));
+        }
+    }
+
+    /**
+     *  @private
+     *  Listen for children being removed.
+     */
+    private function removedHandler(event:Event):void
+    {
+        var i:int;
+        var o:DisplayObject = DisplayObject(event.target);
+        var focusPaneParent:DisplayObject = focusPane ? focusPane.parent : null;
+
+        // Remove the focusPane to allow the focusOwner to be garbage collected.
+        // Avoid recursion by not processing the removal of the focusPane itself.        
+        if (focusPaneParent && o != focusPane)
+        {
+            if (o is DisplayObjectContainer && 
+                isParent(DisplayObjectContainer(o), focusPane))
+            {
+                if (focusPaneParent is ISystemManager)
+                    ISystemManager(focusPaneParent).focusPane = null;
+                else
+                    IUIComponent(focusPaneParent).focusPane = null;
+            }
+        }
+            
+        // trace("FM got added for " + event.target);
+
+        if (o is IFocusManagerComponent)
+        {
+            for (i = 0; i < focusableObjects.length; i++)
+            {
+                if (o == focusableObjects[i])
+                {
+                    if (o == _lastFocus)
+                    {
+                        _lastFocus.drawFocus(false);
+                        _lastFocus = null;
+                    }
+                    // trace("FM removed " + o);
+                    focusableObjects.splice(i, 1);
+                    focusableCandidates = [];
+                    calculateCandidates = true;                 
+                    break;
+                }
+            }
+            o.removeEventListener("tabFocusEnabledChange", tabFocusEnabledChangeHandler);
+            o.removeEventListener("tabIndexChange", tabIndexChangeHandler);
+        }
+        removeFocusables(o, false);
+    }
+
+    /**
+     *  @private
+     */
+    private function removeFocusables(o:DisplayObject, dontRemoveTabChildrenHandler:Boolean):void
+    {
+        var i:int;
+        if (o is DisplayObjectContainer)
+        {
+            if (!dontRemoveTabChildrenHandler)
+            {
+                o.removeEventListener("tabChildrenChange", tabChildrenChangeHandler);
+                o.removeEventListener("hasFocusableChildrenChange", hasFocusableChildrenChangeHandler);
+            }
+
+            for (i = 0; i < focusableObjects.length; i++)
+            {
+                if (isParent(DisplayObjectContainer(o), focusableObjects[i]))
+                {
+                    if (focusableObjects[i] == _lastFocus)
+                    {
+                        _lastFocus.drawFocus(false);
+                        _lastFocus = null;
+                    }
+                    // trace("FM removed " + focusableObjects[i]);
+                    focusableObjects[i].removeEventListener(
+                        "tabFocusEnabledChange", tabFocusEnabledChangeHandler);
+                    focusableObjects[i].removeEventListener(
+                        "tabIndexChange", tabIndexChangeHandler);
+                    focusableObjects.splice(i, 1);
+                    i = i - 1;  // because increment would skip one
+                    
+                    focusableCandidates = [];
+                    calculateCandidates = true;                 
+                }
+            }
+        }
+    }
+
+    /**
+     *  @private
+     */
+    private function showHandler(event:Event):void
+    {
+		var awm:IActiveWindowManager = 
+			IActiveWindowManager(form.systemManager.getImplementation("mx.managers::IActiveWindowManager"));
+		if (awm)
+        	awm.activate(form); // build a message that does the equal
+    }
+
+    /**
+     *  @private
+     */
+    private function hideHandler(event:Event):void
+    {
+		var awm:IActiveWindowManager = 
+			IActiveWindowManager(form.systemManager.getImplementation("mx.managers::IActiveWindowManager"));
+		if (awm)
+        	awm.deactivate(form); // build a message that does the equal
+    }
+
+    /**
+     *  @private
+     */
+    private function childHideHandler(event:Event):void
+    {
+        var target:DisplayObject = DisplayObject(event.target);
+        // trace("FocusManager focusInHandler in  = " + this._form.systemManager.loaderInfo.url);
+        // trace("FM " + this + " focusInHandler " + target);
+
+        if (lastFocus && !isEnabledAndVisible(DisplayObject(lastFocus)) && DisplayObject(form).stage)
+        {
+            DisplayObject(form).stage.focus = null;
+            lastFocus = null;
+        }
+    }
+    
+    /**
+     *  @private
+     */
+    private function viewHideHandler(event:Event):void
+    {
+        // Target is the active view that is about to be hidden
+        var target:DisplayObjectContainer = event.target as DisplayObjectContainer;
+        var lastFocusDO:DisplayObject = lastFocus as DisplayObject;
+       
+        // If the lastFocus is in the view about to be hidden, clear focus
+        if (target && lastFocusDO && target.contains(lastFocusDO))
+            lastFocus = null;
+    }
+
+    /**
+     *  @private
+     */
+    private function creationCompleteHandler(event:FlexEvent):void
+    {
+        var o:DisplayObject = DisplayObject(form);
+        if (o.parent && o.visible && !activated)
+		{
+			var awm:IActiveWindowManager = 
+				IActiveWindowManager(form.systemManager.getImplementation("mx.managers::IActiveWindowManager"));
+			if (awm)
+	        	awm.activate(form); // build a message that does the equal
+		}
+    }
+
+    /**
+     *  @private
+     *  Add or remove if tabbing properties change.
+     */
+    private function tabIndexChangeHandler(event:Event):void
+    {
+        calculateCandidates = true;
+    }
+
+    /**
+     *  @private
+     *  Add or remove if tabbing properties change.
+     */
+    private function tabFocusEnabledChangeHandler(event:Event):void
+    {
+        calculateCandidates = true;
+
+        var o:IFocusManagerComponent = IFocusManagerComponent(event.target);
+        var n:int = focusableObjects.length;
+        for (var i:int = 0; i < n; i++)
+        {
+            if (focusableObjects[i] == o)
+                break;
+        }
+        if (o.tabFocusEnabled)
+        {
+            if (i == n && isTabVisible(DisplayObject(o)))
+            {
+                // trace("FM tpc added " + o);
+                // add it if were not already
+               	if (focusableObjects.indexOf(o) == -1)
+	                focusableObjects.push(o);
+            }
+        }
+        else
+        {
+            // remove it
+            if (i < n)
+            {
+                // trace("FM tpc removed " + o);
+                focusableObjects.splice(i, 1);
+            }
+        }
+    }
+
+    /**
+     *  @private
+     *  Add or remove if tabbing properties change.
+     */
+    private function tabChildrenChangeHandler(event:Event):void
+    {
+        if (event.target != event.currentTarget)
+            return;
+
+        calculateCandidates = true;
+
+        var o:DisplayObjectContainer = DisplayObjectContainer(event.target);
+        if (o.tabChildren)
+        {
+            addFocusables(o, true);
+        }
+        else
+        {
+            removeFocusables(o, true);
+        }
+    }
+
+    /**
+     *  @private
+     *  Add or remove if tabbing properties change.
+     */
+    private function hasFocusableChildrenChangeHandler(event:Event):void
+    {
+        if (event.target != event.currentTarget)
+            return;
+
+        calculateCandidates = true;
+
+        var o:IFocusManagerComponent = IFocusManagerComponent(event.target);
+        if (o.hasFocusableChildren)
+        {
+            addFocusables(DisplayObject(o), true);
+        }
+        else
+        {
+            removeFocusables(DisplayObject(o), true);
+        }
+    }
+
+    /**
+     *  @private
+     *  This gets called when mouse clicks on a focusable object.
+     *  We block player behavior
+     */
+    private function mouseFocusChangeHandler(event:FocusEvent):void
+    {
+        // trace("FocusManager: mouseFocusChangeHandler  in  = " + this._form.systemManager.loaderInfo.url);
+    	// trace("FocusManager: mouseFocusChangeHandler " + event);
+        
+        if (event.isDefaultPrevented())
+            return;
+
+        // If relatedObject is null because we don't have access to the 
+        // object getting focus then allow the Player to set focus
+        // to the object. The isRelatedObjectInaccessible property is 
+        // Player 10 only so we have to test if it is available. We
+        // will only see isRelatedObjectInaccessible if we are a version "10" swf
+        // (-target-player=10). Version "9" swfs will not see the property
+        // even if running in Player 10.
+        if (event.relatedObject == null && 
+            "isRelatedObjectInaccessible" in event &&
+            event["isRelatedObjectInaccessible"] == true)
+        {
+            // lost focus to a control in different sandbox.
+            return;
+        }
+        
+        if (event.relatedObject is TextField)
+        {
+            var tf:TextField = event.relatedObject as TextField;
+            if (tf.type == "input" || tf.selectable)
+            {
+                return; // pass it on
+            }
+        }
+
+        event.preventDefault();
+    }
+
+    /**
+     *  @private
+     *  This gets called when the tab key is hit.
+     */
+    mx_internal function keyFocusChangeHandler(event:FocusEvent):void
+    {
+        // trace("keyFocusChangeHandler handled by " + this);
+    	// trace("keyFocusChangeHandler event = " + event);
+    	
+    	var sm:ISystemManager = form.systemManager;
+
+        if (hasEventListener("keyFocusChange"))
+    		if (!dispatchEvent(new FocusEvent("keyFocusChange", false, true, InteractiveObject(event.target))))
+	    		return;
+
+        showFocusIndicator = true;
+		focusChanged = false;
+
+        var haveBrowserFocusComponent:Boolean = (browserFocusComponent != null);
+        if (browserFocusComponent)
+            clearBrowserFocusComponent();
+        
+        // see if we got here from a tab.  We also need to check for 
+        // keyCode == 0 because in IE sometimes the first time you tab 
+        // in to the flash player, you get keyCode == 0 instead of TAB.
+        // Flash Player bug #2295688.
+        if ((event.keyCode == Keyboard.TAB || (browserMode && event.keyCode == 0)) 
+                && !event.isDefaultPrevented())
+        {
+            if (haveBrowserFocusComponent)
+            {
+                if (hasEventListener("browserFocusComponent"))
+	    			dispatchEvent(new FocusEvent("browserFocusComponent", false, false, InteractiveObject(event.target)));
+				
+                return;
+            }
+
+            if (ieshifttab && lastAction == "ACTIVATE")
+            {
+                // IE seems to now require that we set focus to something during activate
+                // but then we get this keyFocusChange event.  I think we used to not
+                // need to set focus on activate and we still got the keyFocusChange
+                // and then stage.focus was null and we'd use the keyFocusChange event
+                // to determine which control (first or last) got focus based on
+                // the shift key.
+                // If we set focus on activate, then we get this keyFocusChange which moves
+                // the focus somewhere else, so we set fauxFocus to the stage as a signal
+                // to the setFocusToNextObject logic that it shouldn't use the stage.focus
+                // as the starting point.
+                fauxFocus = sm.stage;
+            }
+            // trace("tabHandled by " + this);
+            setFocusToNextObject(event);
+            if (ieshifttab && lastAction == "ACTIVATE")
+            {
+                fauxFocus = null;
+            }
+
+            // if we changed focus or if we're the main app
+            // eat the event
+			if (focusChanged || sm == sm.getTopLevelRoot())
+            	event.preventDefault();
+        }
+    }
+
+    /**
+     *  @private
+     *  Watch for TAB keys.
+     */
+    mx_internal function keyDownHandler(event:KeyboardEvent):void
+    {
+        // trace("onKeyDown handled by " + this);
+    	// trace("onKeyDown event = " + event);
+		// if the target is in a bridged application, let it handle the click.
+		var sm:ISystemManager = form.systemManager;
+
+        if (hasEventListener("keyDownFM"))
+    		if (!dispatchEvent(new FocusEvent("keyDownFM", false, true, InteractiveObject(event.target))))
+   	    		return;
+
+        if (sm is SystemManager)
+            SystemManager(sm).idleCounter = 0;
+
+        if (event.keyCode == Keyboard.TAB)
+        {
+            lastAction = "KEY";
+
+            // I think we'll have time to do this here instead of at creation time
+            // this makes and orders the focusableCandidates array
+            if (calculateCandidates)
+            {
+                sortFocusableObjects();
+                calculateCandidates = false;
+            }
+        }
+
+        if (browserMode)
+        {
+            if (browserFocusComponent)
+                clearBrowserFocusComponent();
+            
+            if (event.keyCode == Keyboard.TAB && focusableCandidates.length > 0)
+            {
+                // get the object that has the focus
+                var o:DisplayObject = fauxFocus;
+				if (!o)
+				{
+					o = form.systemManager.stage.focus;
+				}
+				
+                // trace("focus was at " + o);
+                // trace("focusableObjects " + focusableObjects.length);
+                o = DisplayObject(findFocusManagerComponent2(InteractiveObject(o)));
+                var g:String = "";
+                if (o is IFocusManagerGroup)
+                {
+                    var tg:IFocusManagerGroup = IFocusManagerGroup(o);
+                    g = tg.groupName;
+                }
+
+                var i:int = getIndexOfFocusedObject(o);
+                var j:int = getIndexOfNextObject(i, event.shiftKey, false, g);
+                if (event.shiftKey)
+                {
+                    if (j >= i)
+                    {
+                        // we wrapped so let browser have it
+                        browserFocusComponent = getBrowserFocusComponent(event.shiftKey);
+                        if (browserFocusComponent.tabIndex == -1)
+                            browserFocusComponent.tabIndex = 0;
+                    }
+                }
+                else
+                {
+                    if (j <= i)
+                    {
+                        // we wrapped so let browser have it
+                        browserFocusComponent = getBrowserFocusComponent(event.shiftKey);
+                        if (browserFocusComponent.tabIndex == -1)
+                            browserFocusComponent.tabIndex = LARGE_TAB_INDEX;
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     *  @private
+     *  Watch for ENTER key.
+     */
+    private function defaultButtonKeyHandler(event:KeyboardEvent):void
+    {        
+        var sm:ISystemManager = form.systemManager;
+        if (hasEventListener("defaultButtonKeyHandler"))
+    		if (!dispatchEvent(new FocusEvent("defaultButtonKeyHandler", false, true)))
+	    		return;
+            
+        if (defaultButtonEnabled && event.keyCode == Keyboard.ENTER &&
+			defButton && defButton.enabled)
+        {
+            sendDefaultButtonEvent();
+    	}
+    }
+
+    /**
+     *  @private
+     *  This gets called when the focus changes due to a mouse click.
+     *
+     *  Note: If the focus is changing to a TextField, we don't call
+     *  setFocus() on it because the player handles it;
+     *  calling setFocus() on a TextField which has scrollable text
+     *  causes the text to autoscroll to the end, making the
+     *  mouse click set the insertion point in the wrong place.
+     */
+    private function mouseDownCaptureHandler(event:MouseEvent):void
+    {
+        // trace("FocusManager mouseDownCaptureHandler in  = " + this._form.systemManager.loaderInfo.url);
+        // trace("FocusManager mouseDownCaptureHandler target " + event.target);
+        showFocusIndicator = false;
+    }
+
+    /**
+     *  @private
+     *  This gets called when the focus changes due to a mouse click.
+     *
+     *  Note: If the focus is changing to a TextField, we don't call
+     *  setFocus() on it because the player handles it;
+     *  calling setFocus() on a TextField which has scrollable text
+     *  causes the text to autoscroll to the end, making the
+     *  mouse click set the insertion point in the wrong place.
+     */
+    private function mouseDownHandler(event:MouseEvent):void
+    {
+        // trace("FocusManager mouseDownHandler in  = " + this._form.systemManager.loaderInfo.url);
+        // trace("FocusManager mouseDownHandler target " + event.target);
+        
+		// if the target is in a bridged application, let it handle the click.
+		var sm:ISystemManager = form.systemManager;
+        var o:DisplayObject = getTopLevelFocusTarget(
+            InteractiveObject(event.target));
+
+        if (!o)
+            return;
+
+        // trace("FocusManager mouseDownHandler on " + o);
+        
+        // Make sure the containing component gets notified.
+        // As the note above says, we don't set focus to a TextField ever
+        // because the player already did and took care of where
+        // the insertion point is, and we also don't call setfocus
+        // on a component that last the last focused object unless
+        // the last action was just to activate the player and didn't
+        // involve tabbing or clicking on a component
+        if ((o != _lastFocus || lastAction == "ACTIVATE") && !(o is TextField))
+            setFocus(IFocusManagerComponent(o));
+		else if (_lastFocus)
+		{
+			// trace("FM: skipped setting focus to " + _lastFocus);
+		}
+		
+        if (hasEventListener("mouseDownFM"))
+    		dispatchEvent(new FocusEvent("mouseDownFM", false, false, InteractiveObject(o)));
+
+        lastAction = "MOUSEDOWN";
+	
+    }
+	
+	private function getBrowserFocusComponent(shiftKey:Boolean):InteractiveObject
+	{
+    	var focusComponent:InteractiveObject = form.systemManager.stage.focus;
+		
+		// if the focus is null it means focus is in an application we
+		// don't have access to. Use either the last object or the first
+		// object in this focus manager's list.
+		if (!focusComponent)
+		{
+			var index:int = shiftKey ? 0 : focusableCandidates.length - 1;
+			focusComponent = focusableCandidates[index];
+		}
+		
+		return focusComponent;
+	}	
+}
+
+}
+
+import flash.display.DisplayObject;
+
+/** 
+ * @private
+ * 
+ *  Plain old class to return multiple items of info about the potential
+ *  change in focus.
+ */
+class FocusInfo
+{
+	public var displayObject:DisplayObject;	// object to get focus
+	public var wrapped:Boolean;				// true if focus wrapped around
+}

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/4f3802ef/frameworks/projects/MX/src/main/flex/mx/managers/IFocusManagerComplexComponent.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/MX/src/main/flex/mx/managers/IFocusManagerComplexComponent.as b/frameworks/projects/MX/src/main/flex/mx/managers/IFocusManagerComplexComponent.as
new file mode 100644
index 0000000..c6400ee
--- /dev/null
+++ b/frameworks/projects/MX/src/main/flex/mx/managers/IFocusManagerComplexComponent.as
@@ -0,0 +1,82 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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
+{
+
+/**
+ *  The IFocusManagerComplexComponent interface defines the interface 
+ *  that components that can have more than one internal focus target
+ *  should implement in order to
+ *  receive focus from the FocusManager.
+ *  
+ *  @langversion 3.0
+ *  @playerversion Flash 9
+ *  @playerversion AIR 1.1
+ *  @productversion Flex 3
+ */
+public interface IFocusManagerComplexComponent extends IFocusManagerComponent
+{
+	//--------------------------------------------------------------------------
+	//
+	//  Properties
+	//
+	//--------------------------------------------------------------------------
+
+	//----------------------------------
+	//  hasFocusableContent
+	//----------------------------------
+
+	/**
+	 *  A flag that indicates whether the component currently has internal
+	 *  focusable targets
+	 * 
+	 *  
+	 *  @langversion 3.0
+	 *  @playerversion Flash 9
+	 *  @playerversion AIR 1.1
+	 *  @productversion Flex 3
+	 */
+	function get hasFocusableContent():Boolean;
+	
+	//--------------------------------------------------------------------------
+	//
+	//  Methods
+	//
+	//--------------------------------------------------------------------------
+
+	/**
+	 *  Called by the FocusManager when the component receives focus.
+	 *  The component may in turn set focus to an internal component.
+	 *  The components setFocus() method will still be called when focused by
+	 *  the mouse, but this method will be used when focus changes via the
+	 *  keyboard
+	 *
+	 *  @param direction "bottom" if TAB used with SHIFT key, "top" otherwise
+	 *  
+	 *  @langversion 3.0
+	 *  @playerversion Flash 9
+	 *  @playerversion AIR 1.1
+	 *  @productversion Flex 3
+	 */
+	function assignFocus(direction:String):void;
+
+}
+
+}

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/4f3802ef/frameworks/projects/MX/src/main/flex/mx/managers/IFocusManagerGroup.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/MX/src/main/flex/mx/managers/IFocusManagerGroup.as b/frameworks/projects/MX/src/main/flex/mx/managers/IFocusManagerGroup.as
new file mode 100644
index 0000000..97192bd
--- /dev/null
+++ b/frameworks/projects/MX/src/main/flex/mx/managers/IFocusManagerGroup.as
@@ -0,0 +1,85 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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
+{
+
+/**
+ *  The IFocusManagerGroup interface defines the interface that 
+ *  any component must implement if it is grouped in sets,
+ *  where only one member of the set can be selected at any given time.
+ *  For example, a RadioButton implements IFocusManagerGroup
+ *  because a set of RadioButtons in the same group 
+ *  can only have one RadioButton selected at any one time,
+ *  and the FocusManager will make sure not to give focus to the RadioButtons
+ *  that are not selected in response to moving focus via the Tab key.
+ *  
+ *  @langversion 3.0
+ *  @playerversion Flash 9
+ *  @playerversion AIR 1.1
+ *  @productversion Flex 3
+ */
+public interface IFocusManagerGroup
+{
+	//--------------------------------------------------------------------------
+	//
+	//  Properties
+	//
+	//--------------------------------------------------------------------------
+
+	//----------------------------------
+	//  groupName
+	//----------------------------------
+
+	/**
+	 *	The name of the group of controls to which the control belongs.
+	 *  
+	 *  @langversion 3.0
+	 *  @playerversion Flash 9
+	 *  @playerversion AIR 1.1
+	 *  @productversion Flex 3
+	 */
+	function get groupName():String;
+
+	/**
+	 *  @private
+	 */
+	function set groupName(value:String):void;
+
+	//----------------------------------
+	//  selected
+	//----------------------------------
+
+	/**
+	 *	A flag that indicates whether this control is selected.
+	 *  
+	 *  @langversion 3.0
+	 *  @playerversion Flash 9
+	 *  @playerversion AIR 1.1
+	 *  @productversion Flex 3
+	 */
+	function get selected():Boolean;
+
+	/**
+	 *  @private
+	 */
+	function set selected(value:Boolean):void;
+}
+
+}

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/4f3802ef/frameworks/projects/MX/src/main/flex/mx/managers/ISystemManager.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/MX/src/main/flex/mx/managers/ISystemManager.as b/frameworks/projects/MX/src/main/flex/mx/managers/ISystemManager.as
index 072c0cc..35e5800 100644
--- a/frameworks/projects/MX/src/main/flex/mx/managers/ISystemManager.as
+++ b/frameworks/projects/MX/src/main/flex/mx/managers/ISystemManager.as
@@ -24,6 +24,7 @@ COMPILE::AS3
 {
 	import flash.display.DisplayObject;
 	import flash.display.Sprite;		
+	import flash.display.Stage;		
 }
 COMPILE::JS
 {
@@ -506,6 +507,23 @@ public interface ISystemManager extends IEventDispatcher, IChildList, IFlexModul
      */
     function invalidateParentSizeAndDisplayList():void;
 
+	
+	//----------------------------------
+	//  stage
+	//----------------------------------
+	
+	/**
+	 *  The flash.display.Stage that represents the application window
+	 *  mapped to this SystemManager
+	 *  
+	 *  @langversion 3.0
+	 *  @playerversion Flash 9
+	 *  @playerversion AIR 1.1
+	 *  @productversion Flex 3
+	 */
+	COMPILE::AS3
+	function get stage():Stage
+
 }
 
 }

http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/4f3802ef/frameworks/projects/MX/src/main/flex/mx/states/AddItems.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/MX/src/main/flex/mx/states/AddItems.as b/frameworks/projects/MX/src/main/flex/mx/states/AddItems.as
index 68be25a..3254346 100644
--- a/frameworks/projects/MX/src/main/flex/mx/states/AddItems.as
+++ b/frameworks/projects/MX/src/main/flex/mx/states/AddItems.as
@@ -38,7 +38,7 @@ import mx.core.IDeferredContentOwner;
 import mx.core.IMXMLObject;
 import mx.core.ITransientDeferredInstance;
 import mx.core.IUIComponent;
-import mx.core.IVisualElement;
+import org.apache.flex.core.IVisualElement;
 import mx.core.IVisualElementContainer;
 import mx.core.UIComponent;