//////////////////////////////////////////////////////////////////////////////// // // Licensed to the Apache Software Foundation (ASF) under one or more // contributor license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright ownership. // The ASF licenses this file to You under the Apache License, Version 2.0 // (the "License"); you may not use this file except in compliance with // the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package mx.managers { import flash.display.DisplayObject; import flash.display.DisplayObjectContainer; import flash.display.Graphics; import flash.display.InteractiveObject; import flash.display.Loader; import flash.display.LoaderInfo; import flash.display.MovieClip; import flash.display.Sprite; import flash.display.Stage; import flash.display.StageAlign; import flash.display.StageScaleMode; import flash.events.Event; import flash.events.IEventDispatcher; import flash.events.MouseEvent; import flash.geom.Point; import flash.geom.Rectangle; import flash.net.getClassByAlias; import flash.net.registerClassAlias; import flash.system.ApplicationDomain; import flash.text.Font; import flash.text.TextFormat; import flash.ui.ContextMenu; import flash.utils.ByteArray; import flash.utils.Dictionary; import mx.core.EventPriority; import mx.core.FlexSprite; import mx.core.IChildList; import mx.core.IFlexDisplayObject; import mx.core.IFlexModule; import mx.core.IFlexModuleFactory; import mx.core.IUIComponent; import mx.core.RSLData; import mx.core.Singleton; import mx.core.IWindow; import mx.core.mx_internal; import mx.events.SandboxMouseEvent; import mx.events.DynamicEvent; import mx.events.FlexEvent; import mx.events.EventListenerRequest; import mx.events.Request; import mx.managers.systemClasses.ChildManager; import mx.styles.ISimpleStyleClient; import mx.styles.IStyleClient; import mx.utils.NameUtil; import mx.utils.ObjectUtil; use namespace mx_internal; /** * The WindowedSystemManager class manages any non-Application windows in a * Flex-based AIR application. This includes all windows that are instances of * the Window component or a Window subclass, but not a WindowedApplication * window. For those windows, the WindowedSystemManager serves the same role * that a SystemManager serves for a WindowedApplication instance or an * Application instance in a browser-based Flex application. * *

As this comparison suggests, the WindowedSystemManager class serves * many roles. For instance, it is the root display object of a Window, and * manages tooltips, cursors, popups, and other content for the Window.

* * @see mx.managers.SystemManager * * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public class WindowedSystemManager extends MovieClip implements ISystemManager { public function WindowedSystemManager(rootObj:IUIComponent) { super(); _topLevelSystemManager = this; topLevelWindow = rootObj; SystemManagerGlobals.topLevelSystemManagers.push(this); childManager = new ChildManager(this); //docFrameHandler(null); addEventListener(Event.ADDED, docFrameHandler); } mx_internal var topLevel:Boolean = true; private var initialized:Boolean = false; /** * @private * The top level window. */ mx_internal var topLevelWindow:IUIComponent; /** * @private * pointer to Window, for cleanup */ private var myWindow:IWindow; /** * @private */ private var _topLevelSystemManager:ISystemManager; /** * @private * The childAdded/removed code */ mx_internal var childManager:ISystemManagerChildManager; /** * @private * Whether we are the stage root or not. * We are only the stage root if we were the root * of the first SWF that got loaded by the player. * Otherwise we could be top level but not stage root * if we are loaded by some other non-Flex shell * or are sandboxed. */ private var isStageRoot:Boolean = true; /** * @private * Number of frames since the last mouse or key activity. */ mx_internal var idleCounter:int = 0; /** * @private * Whether we are the first SWF loaded into a bootstrap * and therefore, the topLevelRoot */ private var isBootstrapRoot:Boolean = false; /** * Depth of this object in the containment hierarchy. * This number is used by the measurement and layout code. * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ mx_internal var nestLevel:int = 0; /** * @private * The mouseCatcher is the 0th child of the SystemManager, * behind the application, which is child 1. * It is the same size as the stage and is filled with * transparent pixels; i.e., they've been drawn, but with alpha 0. * * Its purpose is to make every part of the stage * able to detect the mouse. * For example, a Button puts a mouseUp handler on the SystemManager * in order to capture mouseUp events that occur outside the Button. * But if the children of the SystemManager don't have "drawn-on" * pixels everywhere, the player won't dispatch the mouseUp. * We can't simply fill the SystemManager itself with * transparent pixels, because the player's pixel detection * logic doesn't look at pixels drawn into the root DisplayObject. * * Here is an example of what would happen without the mouseCatcher: * Run a fixed-size Application (e.g. width="600" height="600") * in the standalone player. Make the player window larger * to reveal part of the stage. Press a Button, drag off it * into the stage area, and release the mouse button. * Without the mouseCatcher, the Button wouldn't return to its "up" state. */ private var mouseCatcher:Sprite; //---------------------------------- // applicationIndex //---------------------------------- /** * @private * Storage for the applicationIndex property. */ private var _applicationIndex:int = 1; /** * @private * The index of the main mx.core.Application window, which is * effectively its z-order. */ mx_internal function get applicationIndex():int { return _applicationIndex; } /** * @private */ mx_internal function set applicationIndex(value:int):void { _applicationIndex = value; } //----------------------------------- // ISystemManager implementations //----------------------------------- //---------------------------------- // allowDomainsInNewRSLs //---------------------------------- /** * @private */ private var _allowDomainsInNewRSLs:Boolean = true; /** * @inheritDoc * * @langversion 3.0 * @playerversion Flash 10.2 * @playerversion AIR 2.6 * @productversion Flex 4.5 */ public function get allowDomainsInNewRSLs():Boolean { return _allowDomainsInNewRSLs; } /** * @private */ public function set allowDomainsInNewRSLs(value:Boolean):void { _allowDomainsInNewRSLs = value; } //---------------------------------- // allowInsecureDomainsInNewRSLs //---------------------------------- /** * @private */ private var _allowInsecureDomainsInNewRSLs:Boolean = true; /** * @inheritDoc * * @langversion 3.0 * @playerversion Flash 10.2 * @playerversion AIR 2.6 * @productversion Flex 4.5 */ public function get allowInsecureDomainsInNewRSLs():Boolean { return _allowInsecureDomainsInNewRSLs; } /** * @private */ public function set allowInsecureDomainsInNewRSLs(value:Boolean):void { _allowInsecureDomainsInNewRSLs = value; } //---------------------------------- // cursorChildren //---------------------------------- /** * @private * Storage for the cursorChildren property. */ private var _cursorChildren:WindowedSystemChildrenList; /** * @inheritDoc * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get cursorChildren():IChildList { if (!topLevel) return _topLevelSystemManager.cursorChildren; if (!_cursorChildren) { _cursorChildren = new WindowedSystemChildrenList(this, new QName(mx_internal, "toolTipIndex"), new QName(mx_internal, "cursorIndex")); } return _cursorChildren; } //---------------------------------- // cursorIndex //---------------------------------- /** * @private * Storage for the toolTipIndex property. */ private var _cursorIndex:int = 0; /** * @private * The index of the highest child that is a cursor. */ mx_internal function get cursorIndex():int { return _cursorIndex; } /** * @private */ mx_internal function set cursorIndex(value:int):void { var delta:int = value - _cursorIndex; _cursorIndex = value; } //---------------------------------- // document //---------------------------------- /** * @private * Storage for the document property. */ private var _document:Object; /** * @inheritDoc * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get document():Object { return _document; } /** * @private */ public function set document(value:Object):void { _document = value; } //---------------------------------- // embeddedFontList //---------------------------------- /** * @private * Storage for the fontList property. */ private var _fontList:Object = null; /** * A table of embedded fonts in this application. The * object is a table indexed by the font name. * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get embeddedFontList():Object { if (_fontList == null) { _fontList = {}; var o:Object = info()["fonts"]; var p:String; for (p in o) { _fontList[p] = o[p]; } // Top level systemManager may not be defined if SWF is loaded // as a background image in download progress bar. if (!topLevel && _topLevelSystemManager) { var fl:Object = _topLevelSystemManager.embeddedFontList; for (p in fl) { _fontList[p] = fl[p]; } } } return _fontList; } //---------------------------------- // focusPane //---------------------------------- /** * @private */ private var _focusPane:Sprite; /** * @copy mx.core.UIComponent#focusPane * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get focusPane():Sprite { return _focusPane; } /** * @private */ public function set focusPane(value:Sprite):void { if (value) { addChild(value); value.x = 0; value.y = 0; value.scrollRect = null; _focusPane = value; } else { removeChild(_focusPane); _focusPane = null; } } //---------------------------------- // isProxy //---------------------------------- /** * True if SystemManager is a proxy and not a root class */ public function get isProxy():Boolean { return false; } //---------------------------------- // $numChildren //---------------------------------- /** * @private * This property allows access to the Player's native implementation * of the numChildren property, which can be useful since components * can override numChildren and thereby hide the native implementation. * Note that this "base property" is final and cannot be overridden, * so you can count on it to reflect what is happening at the player level. */ mx_internal final function get $numChildren():int { return super.numChildren; } //---------------------------------- // numModalWindows //---------------------------------- /** * @private * Storage for the numModalWindows property. */ private var _numModalWindows:int = 0; /** * The number of modal windows. Modal windows don't allow * clicking in another windows which would normally * activate the FocusManager in that window. The PopUpManager * modifies this count as it creates and destroys modal windows. * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get numModalWindows():int { return _numModalWindows; } /** * @private */ public function set numModalWindows(value:int):void { _numModalWindows = value; } //---------------------------------- // popUpChildren //---------------------------------- /** * @private * Storage for the popUpChildren property. */ private var _popUpChildren:WindowedSystemChildrenList; //---------------------------------- // preloadedRSLs //---------------------------------- /** * @private * * This is a stub to satisfy the IFlexModuleFactory interface. */ public function get preloadedRSLs():Dictionary { return null; } /** * @inheritDoc * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get popUpChildren():IChildList { if (!topLevel) return _topLevelSystemManager.popUpChildren; if (!_popUpChildren) { _popUpChildren = new WindowedSystemChildrenList(this, new QName(mx_internal, "noTopMostIndex"), new QName(mx_internal, "topMostIndex")); } return _popUpChildren; } //---------------------------------- // noTopMostIndex //---------------------------------- /** * @private * Storage for the noTopMostIndex property. */ private var _noTopMostIndex:int = 0; /** * @private * The index of the highest child that isn't a topmost/popup window */ mx_internal function get noTopMostIndex():int { return _noTopMostIndex; } /** * @private */ mx_internal function set noTopMostIndex(value:int):void { var delta:int = value - _noTopMostIndex; _noTopMostIndex = value; topMostIndex += delta; } //---------------------------------- // rawChildren //---------------------------------- /** * @private * Storage for the rawChildren property. */ private var _rawChildren:WindowedSystemRawChildrenList; /** * @inheritDoc * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get rawChildren():IChildList { if (!topLevel) return _topLevelSystemManager.rawChildren; if (!_rawChildren) _rawChildren = new WindowedSystemRawChildrenList(this); return _rawChildren; } //-------------------------------------------------------------------------- // screen //-------------------------------------------------------------------------- /** * @private * Storage for the screen property. */ mx_internal var _screen:Rectangle; /** * @inheritDoc * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get screen():Rectangle { if (!_screen) _screen = new Rectangle(); _screen.x = 0; _screen.y = 0; _screen.width = stage.stageWidth; //Capabilities.screenResolutionX; _screen.height = stage.stageHeight; //Capabilities.screenResolutionY; return _screen; } //---------------------------------- // toolTipChildren //---------------------------------- /** * @private * Storage for the toolTipChildren property. */ private var _toolTipChildren:WindowedSystemChildrenList; /** * @inheritDoc * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get toolTipChildren():IChildList { if (!topLevel) return _topLevelSystemManager.toolTipChildren; if (!_toolTipChildren) { _toolTipChildren = new WindowedSystemChildrenList(this, new QName(mx_internal, "topMostIndex"), new QName(mx_internal, "toolTipIndex")); } return _toolTipChildren; } //---------------------------------- // toolTipIndex //---------------------------------- /** * @private * Storage for the toolTipIndex property. */ private var _toolTipIndex:int = 0; /** * @private * The index of the highest child that is a tooltip */ mx_internal function get toolTipIndex():int { return _toolTipIndex; } /** * @private */ mx_internal function set toolTipIndex(value:int):void { var delta:int = value - _toolTipIndex; _toolTipIndex = value; cursorIndex += delta; } //---------------------------------- // topLevelSystemManager //---------------------------------- /** * Returns the SystemManager responsible for the application window. This will be * the same SystemManager unless this application has been loaded into another * application. * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get topLevelSystemManager():ISystemManager { if (topLevel) return this; return _topLevelSystemManager; } //---------------------------------- // topMostIndex //---------------------------------- /** * @private * Storage for the topMostIndex property. */ private var _topMostIndex:int = 0; /** * @private * The index of the highest child that is a topmost/popup window */ mx_internal function get topMostIndex():int { return _topMostIndex; } mx_internal function set topMostIndex(value:int):void { var delta:int = value - _topMostIndex; _topMostIndex = value; toolTipIndex += delta; } //---------------------------------- // width //---------------------------------- /** * @private */ private var _width:Number; /** * The width of this object. For the SystemManager * this should always be the width of the stage unless the application was loaded * into another application. If the application was not loaded * into another application, setting this value will have no effect. * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ override public function get width():Number { return _width; } //---------------------------------- // window //---------------------------------- /** * @private */ private var _window:IWindow = null; mx_internal function get window():IWindow { return _window; } mx_internal function set window(value:IWindow):void { _window = value; } //---------------------------------- // height //---------------------------------- /** * @private */ private var _height:Number; /** * The height of this object. For the SystemManager * this should always be the width of the stage unless the application was loaded * into another application. If the application was not loaded * into another application, setting this value has no effect. * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ override public function get height():Number { return _height; } /** * @inheritdoc * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get childAllowsParent():Boolean { try { return loaderInfo.childAllowsParent; } catch (error:Error) { //Error #2099: The loading object is not sufficiently loaded to provide this information. } return false; // assume the worst } /** * @inheritdoc * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get parentAllowsChild():Boolean { try { return loaderInfo.parentAllowsChild; } catch (error:Error) { //Error #2099: The loading object is not sufficiently loaded to provide this information. } return false; // assume the worst } //-------------------------------------------------------------------------- // // Methods: Access to overridden methods of base classes // //-------------------------------------------------------------------------- /** * @private * This method allows access to the Player's native implementation * of addChild(), which can be useful since components * can override addChild() and thereby hide the native implementation. * Note that this "base method" is final and cannot be overridden, * so you can count on it to reflect what is happening at the player level. */ mx_internal final function $addChild(child:DisplayObject):DisplayObject { return super.addChild(child); } /** * @private * This method allows access to the Player's native implementation * of addChildAt(), which can be useful since components * can override addChildAt() and thereby hide the native implementation. * Note that this "base method" is final and cannot be overridden, * so you can count on it to reflect what is happening at the player level. */ mx_internal final function $addChildAt(child:DisplayObject, index:int):DisplayObject { return super.addChildAt(child, index); } /** * @private * This method allows access to the Player's native implementation * of removeChild(), which can be useful since components * can override removeChild() and thereby hide the native implementation. * Note that this "base method" is final and cannot be overridden, * so you can count on it to reflect what is happening at the player level. */ mx_internal final function $removeChild(child:DisplayObject):DisplayObject { return super.removeChild(child); } /** * @private * This method allows access to the Player's native implementation * of removeChildAt(), which can be useful since components * can override removeChildAt() and thereby hide the native implementation. * Note that this "base method" is final and cannot be overridden, * so you can count on it to reflect what is happening at the player level. */ mx_internal final function $removeChildAt(index:int):DisplayObject { return super.removeChildAt(index); } //-------------------------------------------------------------------------- // // Methods: Initialization // //-------------------------------------------------------------------------- /** * This method should not be called on WindowedSystemManager. * It is here as part of the contract for IFlexModuleFactory. */ public function callInContext(fn:Function, thisArg:Object, argArray:Array, returns:Boolean = true):* { if (returns) return fn.apply(thisArg, argArray); else fn.apply(thisArg, argArray); } /** * This method is overridden in the autogenerated subclass. * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function create(... params):Object { var mainClassName:String = String(params[0]); var mainClass:Class = Class(getDefinitionByName(mainClassName)); if (!mainClass) throw new Error("Class '" + mainClassName + "' not found."); var instance:Object = new mainClass(); if (instance is IFlexModule) (IFlexModule(instance)).moduleFactory = this; return instance; } /** * @private * This is attached as the framescript at the end of frame 2. * When this function is called, we know that the application * class has been defined and read in by the Player. */ protected function docFrameHandler(event:Event = null):void { removeEventListener(Event.ADDED, docFrameHandler); // Register singleton classes. // Note: getDefinitionByName() will return null // if the class can't be found. /* Singleton.registerClass("mx.managers::ICursorManager", Class(getDefinitionByName("mx.managers::CursorManagerImpl"))); Singleton.registerClass("mx.managers::IDragManager", Class(getDefinitionByName("mx.managers::DragManagerImpl"))); Singleton.registerClass("mx.managers::IHistoryManager", Class(getDefinitionByName("mx.managers::HistoryManagerImpl"))); Singleton.registerClass("mx.managers::ILayoutManager", Class(getDefinitionByName("mx.managers::LayoutManager"))); Singleton.registerClass("mx.managers::IPopUpManager", Class(getDefinitionByName("mx.managers::PopUpManagerImpl"))); Singleton.registerClass("mx.styles::IStyleManager", Class(getDefinitionByName("mx.styles::StyleManagerImpl"))); Singleton.registerClass("mx.styles::IStyleManager2", Class(getDefinitionByName("mx.styles::StyleManagerImpl"))); Singleton.registerClass("mx.managers::IToolTipManager2", Class(getDefinitionByName("mx.managers::ToolTipManagerImpl")));*/ // executeCallbacks(); // doneExecutingInitCallbacks = true; // Loaded SWFs don't get a stage right away // and shouldn't override the main SWF's setting anyway. if (stage) { stage.scaleMode = StageScaleMode.NO_SCALE; stage.align = StageAlign.TOP_LEFT; } var mixinList:Array = info()["mixins"]; if (mixinList && mixinList.length > 0) { var n:int = mixinList.length; for (var i:int = 0; i < n; ++i) { // trace("initializing mixin " + mixinList[i]); var c:Class = Class(getDefinitionByName(mixinList[i])); c["init"](this); } } c = Singleton.getClass("mx.managers::IActiveWindowManager"); if (c) { registerImplementation("mx.managers::IActiveWindowManager", new c(this)); } // depends on having IActiveWindowManager installed first c = Singleton.getClass("mx.managers::IMarshalSystemManager"); if (c) { registerImplementation("mx.managers::IMarshalSystemManager", new c(this)); } // installCompiledResourceBundles(); initializeTopLevelWindow(null); if (Singleton.getClass("mx.managers::IDragManager").getInstance() is NativeDragManagerImpl) NativeDragManagerImpl(Singleton.getClass("mx.managers::IDragManager").getInstance()).registerSystemManager(this); } /** * @private * Instantiates an instance of the top level window * and adds it as a child of the SystemManager. */ protected function initializeTopLevelWindow(event:Event):void { initialized = true; // This listener is intended to run before any other KeyboardEvent listeners // so that it can redispatch a cancelable=true copy of the event. if (getSandboxRoot() == this) { // keydown events on AIR are cancelable so we don't need to add a listener. addEventListener(MouseEvent.MOUSE_WHEEL, mouseEventHandler, true, 1000); addEventListener(MouseEvent.MOUSE_DOWN, mouseEventHandler, true, 1000); } if (isTopLevelRoot() && stage) { // keydown events on AIR are cancelable so we don't need to add a listener. stage.addEventListener(MouseEvent.MOUSE_WHEEL, mouseEventHandler, false, 1000); stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseEventHandler, false, 1000); } if (!parent) return; initContextMenu(); if (!topLevel) { // We are not top-level and don't have a parent. This can happen // when the application has already been unloaded by the time // we get to this point. if (!parent) return; var obj:DisplayObjectContainer = parent.parent; // if there is no grandparent at this point, we might have been removed and // are about to be killed so just bail. Other code that runs after // this point expects us to be grandparented. Another scenario // is that someone loaded us but not into a parented loader, but that // is not allowed. if (!obj) return; while (obj) { if (obj is IUIComponent) { _topLevelSystemManager = IUIComponent(obj).systemManager; break; } obj = obj.parent; } } // if (topLevel && stage) stage.addEventListener(Event.RESIZE, Stage_resizeHandler, false, 0, true); var app:IUIComponent; // Create a new instance of the toplevel class document = app = topLevelWindow;// = IUIComponent(create()); if (document) { if (topLevel && stage) { // LoaderConfig._url = loaderInfo.url; // LoaderConfig._parameters = loaderInfo.parameters; // stageWidth/stageHeight may have changed between initialize() and now, // so refresh our _width and _height here. _width = stage.stageWidth; _height = stage.stageHeight; //trace("width", _width); IFlexDisplayObject(app).setActualSize(stage.stageWidth, stage.stageHeight); } else { IFlexDisplayObject(app).setActualSize(loaderInfo.width, loaderInfo.height); } // Wait for the app to finish its initialization sequence // before doing an addChild(). // Otherwise, the measurement/layout code will cause the // player to do a bunch of unnecessary screen repaints, // which slows application startup time. // Pass in the application instance to the preloader using registerApplication // preloader.registerApplication(app); // The Application doesn't get added to the SystemManager in the standard way. // We want to recursively create the entire application subtree and process // it with the LayoutManager before putting the Application on the display list. // So here we what would normally happen inside an override of addChild(). // Leter, when we actually attach the Application instance, // we call super.addChild(), which is the bare player method. addingChild(DisplayObject(app)); childAdded(DisplayObject(app)); // calls app.createChildren() } else { document = this; } // because we have no preload done handler, we need to // do that work elsewhere addChildAndMouseCatcher(); } /** * @private * Same as SystemManager's preload done handler. It adds * the window to the application (and a mouse catcher) * * Called from initializeTopLevelWindow() */ private function addChildAndMouseCatcher():void { var app:IUIComponent = topLevelWindow; // Add the mouseCatcher as child 0. mouseCatcher = new FlexSprite(); mouseCatcher.name = "mouseCatcher"; // Must use addChildAt because a creationComplete handler can create a // dialog and insert it at 0. noTopMostIndex++; super.addChildAt(mouseCatcher, 0); resizeMouseCatcher(); // topLevel seems to always be true, but keeping it here just in case if (!topLevel) { mouseCatcher.visible = false; mask = mouseCatcher; } noTopMostIndex++; super.addChild(DisplayObject(app)); } //---------------------------------- // info //---------------------------------- /** * @private */ public function info():Object { return { currentDomain: ApplicationDomain.currentDomain }; } /** * @private * Disable all the built-in items except "Print...". */ private function initContextMenu():void { var defaultMenu:ContextMenu = new ContextMenu(); defaultMenu.hideBuiltInItems(); defaultMenu.builtInItems.print = true; contextMenu = defaultMenu; } /** * @inheritdoc * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function isTopLevelRoot():Boolean { return isStageRoot || isBootstrapRoot; } /** * Go up our parent chain to get the top level system manager. * * returns null if we are not on the display list or we don't have * access to the top level system manager. * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function getTopLevelRoot():DisplayObject { // work our say up the parent chain to the root. This way we // don't have to rely on this object being added to the stage. try { var sm:ISystemManager = this; if (sm.topLevelSystemManager) sm = ISystemManager(sm.topLevelSystemManager); var parent:DisplayObject = DisplayObject(sm).parent; var lastParent:DisplayObject = DisplayObject(sm); while (parent) { if (parent is Stage) return lastParent; lastParent = parent; parent = parent.parent; } } catch (error:SecurityError) { } return null; } /** * Go up our parent chain to get the top level system manager in this * SecurityDomain * * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function getSandboxRoot():DisplayObject { // work our say up the parent chain to the root. This way we // don't have to rely on this object being added to the stage. var sm:ISystemManager = this; try { if (sm.topLevelSystemManager) sm = ISystemManager(sm.topLevelSystemManager); var parent:DisplayObject = DisplayObject(sm).parent; if (parent is Stage) return DisplayObject(sm); // test to see if parent is a Bootstrap if (parent && !parent.dispatchEvent(new Event("mx.managers.SystemManager.isBootstrapRoot", false, true))) return this; var lastParent:DisplayObject = this; while (parent) { if (parent is Stage) return lastParent; // test to see if parent is a Bootstrap if (!parent.dispatchEvent(new Event("mx.managers.SystemManager.isBootstrapRoot", false, true))) return lastParent; // Test if the childAllowsParent so we know there is mutual trust between // the sandbox root and this sm. // The parentAllowsChild is taken care of by the player because it returns null // for the parent if we do not have access. if (parent is Loader) { var loader:Loader = Loader(parent); var loaderInfo:LoaderInfo = loader.contentLoaderInfo; if (!loaderInfo.childAllowsParent) return loaderInfo.content; } // If an object is listening for system manager request we assume it is a sandbox // root. If not, don't assign lastParent to this parent because it may be a // non-Flex application. We only want Flex apps to be returned as sandbox roots. if (parent.hasEventListener("systemManagerRequest")) lastParent = parent; parent = parent.parent; } } catch (error:Error) { // Either we don't have security access to a parent or // the swf is unloaded and loaderInfo.childAllowsParent is throwing Error #2099. } return lastParent != null ? lastParent : DisplayObject(sm); } /** * @private * A map of fully-qualified interface names, * such as "mx.managers::IPopUpManager", * to implementation classes which produce singleton instances, * such as mx.managers.PopUpManagerImpl. */ private var implMap:Object = {}; /** * @private * Adds an interface-name-to-implementation-class mapping to the registry, * if a class hasn't already been registered for the specified interface. * The class must implement a getInstance() method which returns * its singleton instance. */ public function registerImplementation(interfaceName:String, impl:Object):void { var c:Object = implMap[interfaceName]; if (!c) implMap[interfaceName] = impl; } /** * @private * Returns the singleton instance of the implementation class * that was registered for the specified interface, * by looking up the class in the registry * and calling its getInstance() method. * * This method should not be called at static initialization time, * because the factory class may not have called registerClass() yet. */ public function getImplementation(interfaceName:String):Object { var c:Object = implMap[interfaceName]; return c; } /** * @inheritdoc * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function getVisibleApplicationRect(bounds:Rectangle = null, skipToSandboxRoot:Boolean = false):Rectangle { var request:Request = new Request("getVisibleApplicationRect", false, true); if (!dispatchEvent(request)) return Rectangle(request.value); if (skipToSandboxRoot && !topLevel) return topLevelSystemManager.getVisibleApplicationRect(bounds, skipToSandboxRoot); if (!bounds) { bounds = getBounds(DisplayObject(this)); var s:Rectangle = screen; var pt:Point = new Point(Math.max(0, bounds.x), Math.max(0, bounds.y)); pt = localToGlobal(pt); bounds.x = pt.x; bounds.y = pt.y; bounds.width = s.width; bounds.height = s.height; } if (!topLevel) { var obj:DisplayObjectContainer = parent.parent; if ("getVisibleApplicationRect" in obj) { var visibleRect:Rectangle = obj["getVisibleApplicationRect"](true); bounds = bounds.intersection(visibleRect); } } return bounds; } /** * @inheritDoc * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function deployMouseShields(deploy:Boolean):void { var dynamicEvent:DynamicEvent = new DynamicEvent("deployMouseShields"); dynamicEvent.deploy = deploy; dispatchEvent(dynamicEvent); } /** * @private * * This is a stub to satisfy the IFlexModuleFactory interface. */ public function addPreloadedRSL(loaderInfo:LoaderInfo, rsl:Vector.):void { } /** * @private * * This is a stub to satisfy the IFlexModuleFactory interface. * * Calls Security.allowDomain() for the SWF associated with this SystemManager * plus all the SWFs assocatiated with RSLs preloaded by this SystemManager. * */ public function allowDomain(... domains):void { } /** * @private * * This is a stub to satisfy the IFlexModuleFactory interface. * * Calls Security.allowInsecureDomain() for the SWF associated with this SystemManager * plus all the SWFs assocatiated with RSLs preloaded by this SystemManager. * */ public function allowInsecureDomain(... domains):void { } /** * Returns true if the given DisplayObject is the * top-level window. * * @param object * * @return true if the given DisplayObject is the * top-level window. * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function isTopLevelWindow(object:DisplayObject):Boolean { return object is IUIComponent && IUIComponent(object) == topLevelWindow; } /** * @inheritDoc * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function getDefinitionByName(name:String):Object { var domain:ApplicationDomain = ApplicationDomain.currentDomain; !topLevel && parent is Loader ? Loader(parent).contentLoaderInfo.applicationDomain : info()["currentDomain"] as ApplicationDomain; //trace("SysMgr.getDefinitionByName domain",domain,"currentDomain",info()["currentDomain"]); var definition:Object; if (domain.hasDefinition(name)) { definition = domain.getDefinition(name); //trace("SysMgr.getDefinitionByName got definition",definition,"name",name); } return definition; } /** * @inheritDoc * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function isTopLevel():Boolean { return topLevel; } /** * @inheritDoc * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function isFontFaceEmbedded(textFormat:TextFormat):Boolean { var fontName:String = textFormat.font; var fl:Array = Font.enumerateFonts(); for (var f:int = 0; f < fl.length; ++f) { var font:Font = Font(fl[f]); if (font.fontName == fontName) { var style:String = "regular"; if (textFormat.bold && textFormat.italic) style = "boldItalic"; else if (textFormat.bold) style = "bold"; else if (textFormat.italic) style = "italic"; if (font.fontStyle == style) return true; } } if (!fontName || !embeddedFontList || !embeddedFontList[fontName]) { return false; } var info:Object = embeddedFontList[fontName]; return !((textFormat.bold && !info.bold) || (textFormat.italic && !info.italic) || (!textFormat.bold && !textFormat.italic && !info.regular)); } /** * @private * Keep track of the size and position of the stage. */ private function Stage_resizeHandler(event:Event = null):void { var w:Number = stage.stageWidth; var h:Number = stage.stageHeight; var y:Number = 0; var x:Number = 0; if (!_screen) _screen = new Rectangle(); _screen.x = x; _screen.y = y; _screen.width = w; _screen.height = h; _width = stage.stageWidth; _height = stage.stageHeight; //trace(_width, event.type); if (event) { resizeMouseCatcher(); dispatchEvent(event); } } /** * @private * * Get the index of an object in a given child list. * * @return index of f in childList, -1 if f is not in childList. */ private static function getChildListIndex(childList:IChildList, f:Object):int { var index:int = -1; try { index = childList.getChildIndex(DisplayObject(f)); } catch (e:ArgumentError) { // index has been preset to -1 so just continue. } return index; } /** * @private * Makes the mouseCatcher the same size as the stage, * filling it with transparent pixels. */ private function resizeMouseCatcher():void { if (mouseCatcher) { var g:Graphics = mouseCatcher.graphics; g.clear(); g.beginFill(0x000000, 0); g.drawRect(0, 0, stage.stageWidth, stage.stageHeight); g.endFill(); } } /** * @private * * true if redipatching a resize event. */ private var isDispatchingResizeEvent:Boolean; //-------------------------------------------------------------------------- // // Overridden methods: EventDispatcher // //-------------------------------------------------------------------------- /** * @private * allows marshal implementation to add events */ mx_internal final function $addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void { super.addEventListener(type, listener, useCapture, priority, useWeakReference); } /** * @private * Only create idle events if someone is listening. */ override public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void { if (type == MouseEvent.MOUSE_MOVE || type == MouseEvent.MOUSE_UP || type == MouseEvent.MOUSE_DOWN || type == Event.ACTIVATE || type == Event.DEACTIVATE) { // also listen to stage if allowed try { if (stage) { // Use weak listener because we don't always know when we // no longer need this listener stage.addEventListener(type, stageEventHandler, false, 0, true); } } catch (error:SecurityError) { } } if (hasEventListener("addEventListener")) { var request:DynamicEvent = new DynamicEvent("addEventListener", false, true); request.eventType = type; request.listener = listener; request.useCapture = useCapture; request.priority = priority; request.useWeakReference = useWeakReference; if (!dispatchEvent(request)) return; } if (type == SandboxMouseEvent.MOUSE_UP_SOMEWHERE) { // If someone wants this event, also listen for mouseLeave. // Use weak listener because we don't always know when we // no longer need this listener try { if (stage) { stage.addEventListener(Event.MOUSE_LEAVE, mouseLeaveHandler, false, 0, true); } else { super.addEventListener(Event.MOUSE_LEAVE, mouseLeaveHandler, false, 0, true); } } catch (error:SecurityError) { super.addEventListener(Event.MOUSE_LEAVE, mouseLeaveHandler, false, 0, true); } } // These two events will dispatched to applications in sandboxes. if (type == FlexEvent.RENDER || type == FlexEvent.ENTER_FRAME) { if (type == FlexEvent.RENDER) type = Event.RENDER; else type = Event.ENTER_FRAME; try { if (stage) stage.addEventListener(type, listener, useCapture, priority, useWeakReference); else super.addEventListener(type, listener, useCapture, priority, useWeakReference); } catch (error:SecurityError) { super.addEventListener(type, listener, useCapture, priority, useWeakReference); } if (stage && type == Event.RENDER) stage.invalidate(); return; } super.addEventListener(type, listener, useCapture, priority, useWeakReference); } /** * @private */ mx_internal final function $removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void { super.removeEventListener(type, listener, useCapture); } /** * @private */ override public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void { if (hasEventListener("removeEventListener")) { var request:DynamicEvent = new DynamicEvent("removeEventListener", false, true); request.eventType = type; request.listener = listener; request.useCapture = useCapture; if (!dispatchEvent(request)) return; } // These two events will dispatched to applications in sandboxes. if (type == FlexEvent.RENDER || type == FlexEvent.ENTER_FRAME) { if (type == FlexEvent.RENDER) type = Event.RENDER; else type = Event.ENTER_FRAME; try { if (stage) stage.removeEventListener(type, listener, useCapture); } catch (error:SecurityError) { } // Remove both listeners in case the system manager was added // or removed from the stage after the listener was added. super.removeEventListener(type, listener, useCapture); return; } super.removeEventListener(type, listener, useCapture); if (type == MouseEvent.MOUSE_MOVE || type == MouseEvent.MOUSE_UP || type == MouseEvent.MOUSE_DOWN || type == Event.ACTIVATE || type == Event.DEACTIVATE) { if (!hasEventListener(type)) { // also listen to stage if allowed try { if (stage) { stage.removeEventListener(type, stageEventHandler, false); } } catch (error:SecurityError) { } } } if (type == SandboxMouseEvent.MOUSE_UP_SOMEWHERE) { if (!hasEventListener(SandboxMouseEvent.MOUSE_UP_SOMEWHERE)) { // nobody wants this event any more for now try { if (stage) { stage.removeEventListener(Event.MOUSE_LEAVE, mouseLeaveHandler); } } catch (error:SecurityError) { } // Remove both listeners in case the system manager was added // or removed from the stage after the listener was added. super.removeEventListener(Event.MOUSE_LEAVE, mouseLeaveHandler); } } } //-------------------------------------------------------------------------- // // Overridden methods: DisplayObjectContainer // //-------------------------------------------------------------------------- /** * @private */ override public function addChild(child:DisplayObject):DisplayObject { // Adjust the partition indexes // before the "added" event is dispatched. noTopMostIndex++; return rawChildren_addChildAt(child, noTopMostIndex - 1); } //---------------------------------- // numChildren //---------------------------------- /** * The number of non-floating windows. This is the main application window * plus any other windows added to the SystemManager that are not popups, * tooltips or cursors. * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ override public function get numChildren():int { return noTopMostIndex - applicationIndex; } /** * @private */ override public function addChildAt(child:DisplayObject, index:int):DisplayObject { // Adjust the partition indexes // before the "added" event is dispatched. noTopMostIndex++; return rawChildren_addChildAt(child, applicationIndex + index); } /** * @private */ override public function removeChild(child:DisplayObject):DisplayObject { // Adjust the partition indexes // before the "removed" event is dispatched. noTopMostIndex--; return rawChildren_removeChild(child); } /** * @private */ override public function removeChildAt(index:int):DisplayObject { // Adjust the partition indexes // before the "removed" event is dispatched. noTopMostIndex--; return rawChildren_removeChildAt(applicationIndex + index); } /** * @private */ override public function getChildAt(index:int):DisplayObject { return super.getChildAt(applicationIndex + index); } /** * @private */ override public function getChildByName(name:String):DisplayObject { return super.getChildByName(name); } /** * @private */ override public function getChildIndex(child:DisplayObject):int { return super.getChildIndex(child) - applicationIndex; } /** * @private */ override public function setChildIndex(child:DisplayObject, newIndex:int):void { super.setChildIndex(child, applicationIndex + newIndex); } /** * @private */ override public function getObjectsUnderPoint(point:Point):Array { var children:Array = []; // Get all the children that aren't tooltips and cursors. var n:int = topMostIndex; for (var i:int = 0; i < n; i++) { var child:DisplayObject = super.getChildAt(i); if (child is DisplayObjectContainer) { var temp:Array = DisplayObjectContainer(child).getObjectsUnderPoint(point); if (temp) children = children.concat(temp); } } return children; } //-------------------------------------------------------------------------- // // Methods: Child management // //-------------------------------------------------------------------------- /** * @private */ mx_internal function addingChild(child:DisplayObject):void { var newNestLevel:int = 1; if (!topLevel) { // non-topLevel SystemManagers are buried by Flash.display.Loader and // other non-framework layers so we have to figure out the nestlevel // by searching up the parent chain. var obj:DisplayObjectContainer = parent.parent; while (obj) { if (obj is ILayoutManagerClient) { newNestLevel = ILayoutManagerClient(obj).nestLevel + 1; break; } obj = obj.parent; } } nestLevel = newNestLevel; if (child is IUIComponent) IUIComponent(child).systemManager = this; // Local variables for certain classes we need to check against below. // This is the backdoor way around linking in the class in question. var uiComponentClassName:Class = Class(getDefinitionByName("mx.core.UIComponent")); // If the document property isn't already set on the child, // set it to be the same as this component's document. // The document setter will recursively set it on any // descendants of the child that exist. if (child is IUIComponent && !IUIComponent(child).document) { IUIComponent(child).document = document; } // Set the nestLevel of the child to be one greater // than the nestLevel of this component. // The nestLevel setter will recursively set it on any // descendants of the child that exist. if (child is ILayoutManagerClient) ILayoutManagerClient(child).nestLevel = nestLevel + 1; if (child is InteractiveObject) if (doubleClickEnabled) InteractiveObject(child).doubleClickEnabled = true; if (child is IUIComponent) IUIComponent(child).parentChanged(this); // Sets up the inheritingStyles and nonInheritingStyles objects // and their proto chains so that getStyle() works. // If this object already has some children, // then reinitialize the children's proto chains. if (child is IStyleClient) IStyleClient(child).regenerateStyleCache(true); if (child is ISimpleStyleClient) ISimpleStyleClient(child).styleChanged(null); if (child is IStyleClient) IStyleClient(child).notifyStyleChangeInChildren(null, true); // Need to check to see if the child is an UIComponent // without actually linking in the UIComponent class. if (uiComponentClassName && child is uiComponentClassName) uiComponentClassName(child).initThemeColor(); // Inform the component that it's style properties // have been fully initialized. Most components won't care, // but some need to react to even this early change. if (uiComponentClassName && child is uiComponentClassName) uiComponentClassName(child).stylesInitialized(); } /** * @private */ mx_internal function childAdded(child:DisplayObject):void { if (child.hasEventListener(FlexEvent.ADD)) child.dispatchEvent(new FlexEvent(FlexEvent.ADD)); if (child is IUIComponent) IUIComponent(child).initialize(); // calls child.createChildren() } /** * @private */ mx_internal function removingChild(child:DisplayObject):void { if (child.hasEventListener(FlexEvent.REMOVE)) child.dispatchEvent(new FlexEvent(FlexEvent.REMOVE)); } /** * @private */ mx_internal function childRemoved(child:DisplayObject):void { if (child is IUIComponent) IUIComponent(child).parentChanged(null); } //-------------------------------------------------------------------------- // // Methods: Support for rawChildren access // //-------------------------------------------------------------------------- /** * @private */ mx_internal function rawChildren_addChild(child:DisplayObject):DisplayObject { childManager.addingChild(child); super.addChild(child); childManager.childAdded(child); // calls child.createChildren() return child; } /** * @private */ mx_internal function rawChildren_addChildAt(child:DisplayObject, index:int):DisplayObject { // preloader goes through here before childManager is set up if (childManager) childManager.addingChild(child); super.addChildAt(child, index); if (childManager) childManager.childAdded(child); // calls child.createChildren() return child; } /** * @private */ mx_internal function rawChildren_removeChild(child:DisplayObject):DisplayObject { childManager.removingChild(child); super.removeChild(child); childManager.childRemoved(child); return child; } /** * @private */ mx_internal function rawChildren_removeChildAt(index:int):DisplayObject { var child:DisplayObject = super.getChildAt(index); childManager.removingChild(child); super.removeChildAt(index); childManager.childRemoved(child); return child; } /** * @private */ mx_internal function rawChildren_getChildAt(index:int):DisplayObject { return super.getChildAt(index); } /** * @private */ mx_internal function rawChildren_getChildByName(name:String):DisplayObject { return super.getChildByName(name); } /** * @private */ mx_internal function rawChildren_getChildIndex(child:DisplayObject):int { return super.getChildIndex(child); } /** * @private */ mx_internal function rawChildren_setChildIndex(child:DisplayObject, newIndex:int):void { super.setChildIndex(child, newIndex); } /** * @private */ mx_internal function rawChildren_getObjectsUnderPoint(pt:Point):Array { return super.getObjectsUnderPoint(pt); } /** * @private */ mx_internal function rawChildren_contains(child:DisplayObject):Boolean { return super.contains(child); } // fake out mouseX/mouseY mx_internal var _mouseX:*; mx_internal var _mouseY:*; /** * @private */ override public function get mouseX():Number { if (_mouseX === undefined) return super.mouseX; return _mouseX; } /** * @private */ override public function get mouseY():Number { if (_mouseY === undefined) return super.mouseY; return _mouseY; } /** * Return the object the player sees as having focus. * * @return An object of type InteractiveObject that the * player sees as having focus. If focus is currently * in a sandbox the caller does not have access to * null will be returned. * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function getFocus():InteractiveObject { try { return stage.focus; } catch (e:SecurityError) { // trace("SM getFocus(): ignoring security error " + e); } return null; } /** * @private * Cleans up references to Window. Also removes self from topLevelSystemManagers list. */ mx_internal function cleanup(e:Event):void { if (Singleton.getClass("mx.managers::IDragManager").getInstance() is NativeDragManagerImpl) NativeDragManagerImpl(Singleton.getClass("mx.managers::IDragManager").getInstance()).unregisterSystemManager(this); SystemManagerGlobals.topLevelSystemManagers.splice(SystemManagerGlobals.topLevelSystemManagers.indexOf(this), 1); myWindow.nativeWindow.removeEventListener(Event.CLOSE, cleanup); myWindow = null; } /** * @private * only registers Window for later cleanup. */ mx_internal function addWindow(win:IWindow):void { myWindow = win; myWindow.nativeWindow.addEventListener(Event.CLOSE, cleanup); } /** * @private * dispatch certain stage events from sandbox root */ private function stageEventHandler(event:Event):void { if (event.target is Stage) dispatchEvent(event); } /** * @private * convert MOUSE_LEAVE to MOUSE_UP_SOMEWHERE */ private function mouseLeaveHandler(event:Event):void { dispatchEvent(new SandboxMouseEvent(SandboxMouseEvent.MOUSE_UP_SOMEWHERE)); } /** * Attempts to notify the parent SWFLoader that the * Application's size has may have changed. Not needed * for WindowedSystemManager so does nothing * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ public function invalidateParentSizeAndDisplayList():void { } //-------------------------------------------------------------------------- // // Event Handlers // //-------------------------------------------------------------------------- /** * NOTE: The keyDownHandler in SystemManager is not needed in AIR because * AIR keyDown events are cancelable. */ /** * @private * We want to re-dispatch * mouse events that are cancellable. Currently we are only doing * this for a few mouse events and not all of them (MOUSE_WHEEL and * MOUSE_DOWN). */ private function mouseEventHandler(e:MouseEvent):void { if (!e.cancelable) { e.stopImmediatePropagation(); var cancelableEvent:MouseEvent = new MouseEvent(e.type, e.bubbles, true, e.localX, e.localY, e.relatedObject, e.ctrlKey, e.altKey, e.shiftKey, e.buttonDown, e.delta, e.commandKey, e.controlKey, e.clickCount); e.target.dispatchEvent(cancelableEvent); } } } }