//////////////////////////////////////////////////////////////////////////////// // // 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.marshalClasses { import flash.display.DisplayObject; import flash.events.Event; import flash.events.FocusEvent; import flash.events.IEventDispatcher; import flash.events.KeyboardEvent; import flash.ui.Keyboard; import mx.events.FlexEvent; import mx.events.FocusRequestDirection; import mx.events.SWFBridgeEvent; import mx.events.SWFBridgeRequest; import mx.managers.FocusManager; import mx.managers.IMarshalSystemManager; import mx.managers.ISystemManager; import mx.managers.SystemManager; import mx.managers.SystemManagerProxy; import mx.core.IFlexModuleFactory; import mx.core.ISWFBridgeProvider; import mx.core.ISWFBridgeGroup; import mx.core.ISWFLoader; import mx.core.mx_internal; import mx.core.SWFBridgeGroup; use namespace mx_internal; [ExcludeClass] [Mixin] /** * @private * MarshallingSupport for FocusManager */ public class FocusManagerMarshalMixin { include "../../core/Version.as"; //-------------------------------------------------------------------------- // // Class Method // //-------------------------------------------------------------------------- public static function init(fbs:IFlexModuleFactory):void { if (!FocusManager.mixins) FocusManager.mixins = []; if (FocusManager.mixins.indexOf(FocusManagerMarshalMixin) == -1) FocusManager.mixins.push(FocusManagerMarshalMixin); } //-------------------------------------------------------------------------- // // Constructor // //-------------------------------------------------------------------------- /** * Constructor. */ public function FocusManagerMarshalMixin(owner:FocusManager = null) { super(); if (!owner) return; this.focusManager = owner; marshalSystemManager = IMarshalSystemManager(focusManager.form.systemManager.getImplementation("mx.managers::IMarshalSystemManager")); focusManager.addEventListener("initialize", initializeHandler); focusManager.addEventListener("showFocusIndicator", showFocusIndicatorHandler); focusManager.addEventListener("setFocus", setFocusHandler); focusManager.addEventListener(FocusEvent.FOCUS_IN, focusInHandler); focusManager.addEventListener("activateFM", activateHandler); focusManager.addEventListener("deactivateFM", deactivateHandler); focusManager.addEventListener("focusWrapping", focusWrappingHandler); focusManager.addEventListener("setFocusToComponent", setFocusToComponentHandler); focusManager.addEventListener("setFocusToNextIndex", focusWrappingHandler); // yes, this is the same code snippet so reuse handler focusManager.addEventListener("getTopLevelFocusTarget", getTopLevelFocusTargetHandler); focusManager.addEventListener("keyFocusChange", keyFocusChangeHandler); focusManager.addEventListener("browserFocusComponent", browserFocusComponentHandler); focusManager.addEventListener("keyDownFM", keyDownHandler); focusManager.addEventListener("defaultButtonKeyHandler", defaultButtonKeyHandler); focusManager.addEventListener("mouseDownFM", mouseDownHandler); focusManager.addEventListener("addChildBridge", addChildBridgeHandler); focusManager.addEventListener("removeChildBridge", removeChildBridgeHandler); focusManager.addEventListener(FlexEvent.FLEX_WINDOW_ACTIVATE, forwardWindowActivationEventsToChildrenHandler); focusManager.addEventListener(FlexEvent.FLEX_WINDOW_DEACTIVATE, forwardWindowActivationEventsToChildrenHandler); } //-------------------------------------------------------------------------- // // Properties // //-------------------------------------------------------------------------- /** * @private * * Test if the focus was set locally in this focus manager (true) or * if focus was transfer to another focus manager (false) */ private var focusSetLocally:Boolean; /** * @private */ private var focusManager:FocusManager; /** * @private */ private var marshalSystemManager:IMarshalSystemManager; /** * @private * * The focus manager maintains its own bridges so a focus manager in a pop * up can move focus to another focus manager in the same pop up. That is, * A pop ups can be a collection of focus managers working together just * as is done in the System Manager's document. */ private var swfBridgeGroup:SWFBridgeGroup; /** * @private * * bridge handle of the last active focus manager. */ private var lastActiveFocusManager:FocusManager; /** * @private * * Used when a the skip parameter can't be passed into * dispatchEventFromSWFBridges() because the caller doesn't take * a skip parameter. */ private var skipBridge:IEventDispatcher; //-------------------------------------------------------------------------- // // Methods // //-------------------------------------------------------------------------- public function initializeHandler(event:Event):void { try { var sm:ISystemManager = focusManager.form.systemManager; // Set up our swfBridgeGroup. If this is a pop up then the parent // bridge is empty, otherwise its the form's system manager's bridge. swfBridgeGroup = new SWFBridgeGroup(sm); if (!focusManager.popup) swfBridgeGroup.parentBridge = marshalSystemManager.swfBridgeGroup.parentBridge; // add ourselves to our parent focus manager if this is a bridged // application not a dialog or other popup. if (marshalSystemManager.useSWFBridge()) { sm.addEventListener(SWFBridgeEvent.BRIDGE_APPLICATION_UNLOADING, removeFromParentBridge); // have the child listen to move requests from the parent. var bridge:IEventDispatcher = swfBridgeGroup.parentBridge; if (bridge) { bridge.addEventListener(SWFBridgeRequest.MOVE_FOCUS_REQUEST, focusRequestMoveHandler); bridge.addEventListener(SWFBridgeRequest.SET_SHOW_FOCUS_INDICATOR_REQUEST, setShowFocusIndicatorRequestHandler); bridge.addEventListener(SWFBridgeEvent.BRIDGE_AIR_WINDOW_ACTIVATE, windowActivationEventHandler); bridge.addEventListener(SWFBridgeEvent.BRIDGE_AIR_WINDOW_DEACTIVATE, windowActivationEventHandler); } // add listener activate/deactivate requests if (bridge && !(focusManager.form.systemManager is SystemManagerProxy)) { bridge.addEventListener(SWFBridgeRequest.ACTIVATE_FOCUS_REQUEST, focusRequestActivateHandler); bridge.addEventListener(SWFBridgeRequest.DEACTIVATE_FOCUS_REQUEST, focusRequestDeactivateHandler); bridge.addEventListener(SWFBridgeEvent.BRIDGE_FOCUS_MANAGER_ACTIVATE, bridgeEventActivateHandler); } // listen when the container has been added to the stage so we can add the focusable // children focusManager.form.addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler); } } catch (e:Error) { // ignore null pointer errors caused by container using a // systemManager from another sandbox. } } /** * After the form is added to the stage, if there are no focusable objects, * add the form and its children to the list of focuable objects because * this application may have been loaded before the * top-level system manager was added to the stage. */ private function addedToStageHandler(event:Event):void { focusManager.form.removeEventListener(Event.ADDED_TO_STAGE, addedToStageHandler); if (focusManager.focusableObjects.length == 0) { focusManager.addFocusables(DisplayObject(focusManager.form)); focusManager.calculateCandidates = true; } } private function setFocusHandler(event:Event):void { focusSetLocally = true; } public function showFocusIndicatorHandler(event:Event):void { if (!focusManager.popup && swfBridgeGroup) dispatchSetShowFocusIndicatorRequest(focusManager.showFocusIndicator, null); } public function focusInHandler(event:FocusEvent):void { // if the target is in a bridged application, let it handle the click. if (marshalSystemManager.isDisplayObjectInABridgedApplication(DisplayObject(event.relatedObject))) event.preventDefault(); } public function activateHandler(event:Event):void { // activate children in compatibility mode or in sandboxes. dispatchEventFromSWFBridges(new SWFBridgeRequest(SWFBridgeRequest.ACTIVATE_FOCUS_REQUEST), skipBridge); } public function deactivateHandler(event:Event):void { // deactivate children in compatibility mode or in sandboxes. dispatchEventFromSWFBridges(new SWFBridgeRequest(SWFBridgeRequest.DEACTIVATE_FOCUS_REQUEST), skipBridge); } // parameter is FocusEvent just so we don't have to define a class // to pass a object reference. public function focusWrappingHandler(event:FocusEvent):void { if (getParentBridge()) { moveFocusToParent(event.shiftKey); event.preventDefault();; } } // parameter is FocusEvent just so we don't have to define a class // to pass a object reference. public function setFocusToComponentHandler(event:FocusEvent):void { var o:Object = event.relatedObject; if (o is ISWFLoader && ISWFLoader(o).swfBridge) { // send message to child swf to move focus. // trace("pass focus from " + this.form.systemManager.loaderInfo.url + " to " + DisplayObject(o).loaderInfo.url); var request:SWFBridgeRequest = new SWFBridgeRequest(SWFBridgeRequest.MOVE_FOCUS_REQUEST, false, true, null, event.shiftKey ? FocusRequestDirection.BOTTOM : FocusRequestDirection.TOP); var sandboxBridge:IEventDispatcher = ISWFLoader(o).swfBridge; if (sandboxBridge) { sandboxBridge.dispatchEvent(request); focusManager.focusChanged = request.data; } event.preventDefault(); } } // parameter is FocusEvent just so we don't have to define a class // to pass a object reference. public function getTopLevelFocusTargetHandler(event:FocusEvent):void { var o:Object = event.relatedObject; // if we cross a boundry into a bridged application, then return null so // the target is only processed at the lowest level if (o is ISWFLoader) { if (ISWFLoader(o).swfBridge) event.preventDefault(); } } // parameter is FocusEvent just so we don't have to define a class // to pass a object reference. public function keyFocusChangeHandler(event:FocusEvent):void { var o:Object = event.relatedObject; // if the target is in a bridged application, let it handle the click. if (marshalSystemManager.isDisplayObjectInABridgedApplication(DisplayObject(o))) event.preventDefault(); } // parameter is FocusEvent just so we don't have to define a class // to pass a object reference. public function browserFocusComponentHandler(event:FocusEvent):void { if (marshalSystemManager.useSWFBridge()) { // out of children, pass focus to parent moveFocusToParent(event.shiftKey); if (focusManager.focusChanged) event.preventDefault(); } } // parameter is FocusEvent just so we don't have to define a class // to pass a object reference. public function keyDownHandler(event:FocusEvent):void { if (marshalSystemManager.isDisplayObjectInABridgedApplication(DisplayObject(event.relatedObject))) event.preventDefault(); } // parameter is FocusEvent just so we don't have to define a class // to pass a object reference. public function defaultButtonKeyHandler(event:FocusEvent):void { // if the target is in a bridged application, let it handle the click. if (marshalSystemManager.isDisplayObjectInABridgedApplication(DisplayObject(event.relatedObject))) event.preventDefault(); } // parameter is FocusEvent just so we don't have to define a class // to pass a object reference. public function mouseDownHandler(event:FocusEvent):void { var o:Object = event.relatedObject; // if in a sandbox, create a focus-in event and dispatch. if (!focusManager.lastFocus && o is IEventDispatcher && marshalSystemManager.useSWFBridge()) IEventDispatcher(o).dispatchEvent(new FocusEvent(FocusEvent.FOCUS_IN)); dispatchActivatedFocusManagerEvent(null); lastActiveFocusManager = focusManager; } /** * @private * * A request across a bridge from another FocusManager to change the * focus. */ private function focusRequestMoveHandler(event:Event):void { // trace("focusRequestHandler in = " + this._form.systemManager.loaderInfo.url); // ignore messages we send to ourselves. if (event is SWFBridgeRequest) { // trace("ignored focus in " + this._form.systemManager.loaderInfo.url); return; } focusSetLocally = false; var request:SWFBridgeRequest = SWFBridgeRequest.marshal(event); if (request.data == FocusRequestDirection.TOP || request.data == FocusRequestDirection.BOTTOM) { // move focus to the top or bottom child. If there are no children then // send focus back up to the parent. if (focusManager.focusableObjects.length == 0) { // trace("focusRequestMoveHandler: no focusable objects, setting focus back to parent"); moveFocusToParent(request.data == FocusRequestDirection.TOP ? false : true); event["data"] = focusManager.focusChanged; return; } if (request.data == FocusRequestDirection.TOP) { setFocusToTop(); } else { setFocusToBottom(); } event["data"] = focusManager.focusChanged; } else { // move forward or backward var startingPosition:DisplayObject = DisplayObject(swfBridgeGroup.getChildBridgeProvider(IEventDispatcher(event.target))); moveFocus(request.data as String, startingPosition); event["data"] = focusManager.focusChanged; } if (focusSetLocally) { dispatchActivatedFocusManagerEvent(null); lastActiveFocusManager = focusManager; } } private function focusRequestActivateHandler(event:Event):void { // trace("FM focusRequestActivateHandler"); skipBridge = IEventDispatcher(event.target); focusManager.activate(); skipBridge = null; } private function focusRequestDeactivateHandler(event:Event):void { // trace("FM focusRequestDeactivateHandler"); skipBridge = IEventDispatcher(event.target); focusManager.deactivate(); skipBridge = null; } private function bridgeEventActivateHandler(event:Event):void { // ignore message to self if (event is SWFBridgeEvent) return; //trace("FM bridgeEventActivateHandler for " + form.systemManager.loaderInfo.url); // clear last focus if we aren't active. lastActiveFocusManager = null; focusManager.lastFocus = null; dispatchActivatedFocusManagerEvent(IEventDispatcher(event.target)); } /** * @private * * A request across a bridge from another FocusManager to change the * value of the setShowFocusIndicator property. */ private function setShowFocusIndicatorRequestHandler(event:Event):void { // ignore messages we send to ourselves. if (event is SWFBridgeRequest) return; var request:SWFBridgeRequest = SWFBridgeRequest.marshal(event); focusManager._showFocusIndicator = request.data; // relay the message to parent and children dispatchSetShowFocusIndicatorRequest(focusManager.showFocusIndicator, IEventDispatcher(event.target)); } /** * This is called on the top-level focus manager and the parent focus * manager for each new bridge of focusable content created. * When the parent focus manager of the new focusable content is * called, focusable content will become part of the tab order. * When the top-level focus manager is called the bridge becomes * one of the focus managers managed by the top-level focus manager. */ public function addSWFBridge(bridge:IEventDispatcher, owner:DisplayObject):void { // trace("FocusManager.addFocusManagerBridge: in = " + this._form.systemManager.loaderInfo.url); if (!owner) return; var sm:ISystemManager = focusManager.form.systemManager; if (focusManager.focusableObjects.indexOf(owner) == -1) { focusManager.focusableObjects.push(owner); focusManager.calculateCandidates = true; } // listen for move requests from the bridge. swfBridgeGroup.addChildBridge(bridge, ISWFBridgeProvider(owner)); bridge.addEventListener(SWFBridgeRequest.MOVE_FOCUS_REQUEST, focusRequestMoveHandler); bridge.addEventListener(SWFBridgeRequest.SET_SHOW_FOCUS_INDICATOR_REQUEST, setShowFocusIndicatorRequestHandler); bridge.addEventListener(SWFBridgeEvent.BRIDGE_FOCUS_MANAGER_ACTIVATE, bridgeEventActivateHandler); } /** * @inheritdoc */ public function removeSWFBridge(bridge:IEventDispatcher):void { var sm:ISystemManager = focusManager.form.systemManager; var displayObject:DisplayObject = DisplayObject(swfBridgeGroup.getChildBridgeProvider(bridge)); if (displayObject) { var index:int = focusManager.focusableObjects.indexOf(displayObject); if (index != -1) { focusManager.focusableObjects.splice(index, 1); focusManager.calculateCandidates = true; } } else throw new Error(); // should never get here. bridge.removeEventListener(SWFBridgeEvent.BRIDGE_AIR_WINDOW_ACTIVATE, windowActivationEventHandler); bridge.removeEventListener(SWFBridgeEvent.BRIDGE_AIR_WINDOW_DEACTIVATE, windowActivationEventHandler); bridge.removeEventListener(SWFBridgeRequest.MOVE_FOCUS_REQUEST, focusRequestMoveHandler); bridge.removeEventListener(SWFBridgeRequest.SET_SHOW_FOCUS_INDICATOR_REQUEST, setShowFocusIndicatorRequestHandler); bridge.removeEventListener(SWFBridgeEvent.BRIDGE_FOCUS_MANAGER_ACTIVATE, bridgeEventActivateHandler); swfBridgeGroup.removeChildBridge(bridge); } /** */ private function removeFromParentBridge(event:Event):void { // add ourselves to our parent focus manager if this is a bridged // application not a dialog or other popup. var sm:ISystemManager = focusManager.form.systemManager; if (marshalSystemManager.useSWFBridge()) { sm.removeEventListener(SWFBridgeEvent.BRIDGE_APPLICATION_UNLOADING, removeFromParentBridge); // have the child listen to move requests from the parent. var bridge:IEventDispatcher = swfBridgeGroup.parentBridge; if (bridge) { bridge.removeEventListener(SWFBridgeRequest.MOVE_FOCUS_REQUEST, focusRequestMoveHandler); bridge.removeEventListener(SWFBridgeRequest.SET_SHOW_FOCUS_INDICATOR_REQUEST, setShowFocusIndicatorRequestHandler); } // add listener activate/deactivate requests if (bridge && !(focusManager.form.systemManager is SystemManagerProxy)) { bridge.removeEventListener(SWFBridgeRequest.ACTIVATE_FOCUS_REQUEST, focusRequestActivateHandler); bridge.removeEventListener(SWFBridgeRequest.DEACTIVATE_FOCUS_REQUEST, focusRequestDeactivateHandler); bridge.removeEventListener(SWFBridgeEvent.BRIDGE_FOCUS_MANAGER_ACTIVATE, bridgeEventActivateHandler); } } } /** * @private * * Send a message to the parent to move focus a component in the parent. * * @param shiftKey - if true move focus to a component * * @return true if focus moved to parent, false otherwise. */ private function moveFocusToParent(shiftKey:Boolean):Boolean { // trace("pass focus from " + this.form.systemManager.loaderInfo.url + " to parent "); var request:SWFBridgeRequest = new SWFBridgeRequest(SWFBridgeRequest.MOVE_FOCUS_REQUEST, false, true, null, shiftKey ? FocusRequestDirection.BACKWARD : FocusRequestDirection.FORWARD); var sandboxBridge:IEventDispatcher = marshalSystemManager.swfBridgeGroup.parentBridge; // the handler will set the data property to whether focus changed sandboxBridge.dispatchEvent(request); focusManager.focusChanged = request.data; return focusManager.focusChanged; } /** * Get the bridge to the parent focus manager. * * @return parent bridge or null if there is no parent bridge. */ private function getParentBridge():IEventDispatcher { if (swfBridgeGroup) return swfBridgeGroup.parentBridge; return null; } /** * @private * * Send a request for all other focus managers to update * their ShowFocusIndicator property. */ private function dispatchSetShowFocusIndicatorRequest(value:Boolean, skip:IEventDispatcher):void { var request:SWFBridgeRequest = new SWFBridgeRequest( SWFBridgeRequest.SET_SHOW_FOCUS_INDICATOR_REQUEST, false, false, null, // bridge is set before it is dispatched value); dispatchEventFromSWFBridges(request, skip); } /** * @private * * Broadcast an ACTIVATED_FOCUS_MANAGER message. * * @param eObj if a SandboxBridgeEvent, then propagate the message, * if null, start a new message. */ private function dispatchActivatedFocusManagerEvent(skip:IEventDispatcher = null):void { // Don't send the ACTIVATED_FOCUS_MANAGER message if we are already // active. if (lastActiveFocusManager == focusManager) { // trace("FM: dispatchActivatedFocusManagerEvent already active, skipping messages"); return; // already active } var event:SWFBridgeEvent = new SWFBridgeEvent(SWFBridgeEvent.BRIDGE_FOCUS_MANAGER_ACTIVATE); dispatchEventFromSWFBridges(event, skip); } /** * A Focus Manager has its own set of child bridges that may be different from the child * bridges of its System Manager if the Focus Manager is managing a pop up. In the case of * a pop up don't send messages to the SM parent bridge because that will be the form. But * do send the messages to the bridges in bridgeFocusManagers dictionary. */ private function dispatchEventFromSWFBridges(event:Event, skip:IEventDispatcher = null):void { var clone:Event; // trace(">>dispatchEventFromSWFBridges", this, event.type); var sm:ISystemManager = focusManager.form.systemManager; if (!focusManager.popup) { var parentBridge:IEventDispatcher = swfBridgeGroup.parentBridge; if (parentBridge && parentBridge != skip) { // Ensure the requestor property has the correct bridge. clone = event.clone(); if (clone is SWFBridgeRequest) SWFBridgeRequest(clone).requestor = parentBridge; parentBridge.dispatchEvent(clone); } } var children:Array = swfBridgeGroup.getChildBridges(); for (var i:int = 0; i < children.length; i++) { if (children[i] != skip) { // trace("send to child", i, event.type); clone = event.clone(); // Ensure the requestor property has the correct bridge. if (clone is SWFBridgeRequest) SWFBridgeRequest(clone).requestor = IEventDispatcher(children[i]); IEventDispatcher(children[i]).dispatchEvent(clone); } } // trace("<direction argument. * * @param direction FocusRequestDirection.FORWARD moves to * from the control that currently has focus to controls with a higher tab index. * If more than one control has the same index, the next control * in the flow of the document is visited. * FocusRequestDirection.BACKWARD moves to controls with * a lower tab index. * FocusRequestDirection.TOP move the focus to the control * with the lowest tab index. If more than one control has the same index, * focus is moved to the first control in the flow of the document. * FocusRequestDirection.BOTTOM move the focus to the control * with the highest tab index. If more than one control has the same index, * focus is moved to the last control in the flow of the document. * * @param fromDisplayObject The starting point from which focus is moved. * If an object is provided, this overrides the default behavior * where focus is moved from the object that currently has focus. */ public function moveFocus(direction:String, fromDisplayObject:DisplayObject = null):void { if (direction == FocusRequestDirection.TOP) { setFocusToTop(); return; } if (direction == FocusRequestDirection.BOTTOM) { setFocusToBottom(); return; } var keyboardEvent:KeyboardEvent = new KeyboardEvent(KeyboardEvent.KEY_DOWN); keyboardEvent.keyCode = Keyboard.TAB; keyboardEvent.shiftKey = (direction == FocusRequestDirection.FORWARD) ? false : true; focusManager.fauxFocus = fromDisplayObject; focusManager.keyDownHandler(keyboardEvent); var focusEvent:FocusEvent = new FocusEvent(FocusEvent.KEY_FOCUS_CHANGE); focusEvent.keyCode = Keyboard.TAB; focusEvent.shiftKey = (direction == FocusRequestDirection.FORWARD) ? false : true; focusManager.keyFocusChangeHandler(focusEvent); focusManager.fauxFocus = null; } /** * @private */ private function setFocusToTop():void { focusManager.setFocusToNextIndex(-1, false); } /** * @private */ private function setFocusToBottom():void { focusManager.setFocusToNextIndex(focusManager.focusableObjects.length, true); } private function addChildBridgeHandler(event:Event):void { var bridge:IEventDispatcher = event["bridge"]; addSWFBridge(bridge, event["owner"]); } private function removeChildBridgeHandler(event:Event):void { var bridge:IEventDispatcher = event["bridge"]; removeSWFBridge(bridge); } private function forwardWindowActivationEventsToChildrenHandler(event:Event):void { var ourEvent:SWFBridgeEvent; if (event.type == FlexEvent.FLEX_WINDOW_ACTIVATE) ourEvent = new SWFBridgeEvent(SWFBridgeEvent.BRIDGE_AIR_WINDOW_ACTIVATE); else if (event.type == FlexEvent.FLEX_WINDOW_DEACTIVATE) ourEvent = new SWFBridgeEvent(SWFBridgeEvent.BRIDGE_AIR_WINDOW_DEACTIVATE); dispatchEventFromSWFBridges(ourEvent, swfBridgeGroup.parentBridge) } private function windowActivationEventHandler(event:Event):void { var ourEvent:FlexEvent; if (event.type == SWFBridgeEvent.BRIDGE_AIR_WINDOW_ACTIVATE) ourEvent = new FlexEvent(FlexEvent.FLEX_WINDOW_ACTIVATE); else if (event.type == SWFBridgeEvent.BRIDGE_AIR_WINDOW_DEACTIVATE) ourEvent = new FlexEvent(FlexEvent.FLEX_WINDOW_DEACTIVATE); focusManager.dispatchEvent(ourEvent); // restore focus if this focus manager had last focus if (focusManager.lastFocus && !focusManager.browserMode) focusManager.lastFocus.setFocus(); focusManager.lastAction = "ACTIVATE"; } } }