2
votes

I have an AIR application running on a Mac and I want to have the behavior of hiding the window when someone "closes" the app (e.g. hits the red "x" button or cmd-w). However, if someone hits cmd-q or chooses "Quit" from the dock context menu or top level menu, I want the app to actually close.

I can preventDefault on the "closing" event sent by the application, however, this causes all "close" methods to just hide the window. The only way for someone to close the application at that point is ForceQuit (or through a separate interface I provide, like a context menu option on the dock icon).

I have also tried capturing the cmd-q keyDown event manually, but it doesn't get sent. Also, this wouldn't help for the case when people try to quit the app using the menu options.

Furthermore, if I preventDefault on the closing method, it causes my application to cancel a shut down process immediately (which is a terrible user experience).

Is there a way to detect different methods of closing an AIR application? I want to be able to tell the difference between these closing methods and react to the appropriately.

2
Please clarify: you're trying to implement the standard Mac behavior where closing the window is not synonymous with closing the application? Hiding is something you do to an app, and it is different from closing the app or a window of the app.user57368

2 Answers

6
votes

Try this for the closing, from what I understand there was / is a bug in the framework so that if you include the AIR updater it breaks cmd-q support, the thread used to be here: http://www.adobe.com/cfusion/webforums/forum/messageview.cfm?forumid=72&catid=670&threadid=1373568

This may or may not be applicable to your situation.

NativeApplication.nativeApplication.addEventListener(Event.EXITING, 
        function(e:Event):void {
            var opened:Array = NativeApplication.nativeApplication.openedWindows;
            for (var i:int = 0; i < opened.length; i ++) {
                opened[i].close();
            }
    });
1
votes

Try this, I am sure there must be a better way of handling this but this has worked for me.

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="onCreationComplete()">
    <mx:Script>
        <![CDATA[
            import mx.core.Application;
            import mx.events.AIREvent;
            import mx.core.Window;

            private function onCreationComplete():void {
                addMacSupport();
            }

            private var macsupport_allowExit:Boolean = false;

            private function addMacSupport():void {
                if ( Capabilities.os.indexOf("Mac") == 0 ) {
                    //open a hidden window that will prevent the application from
                    //exiting when the user presses Cmd+W
                    var win:Window = new Window();
                    win.visible = false;
                    win.open(false);

                    //add a closing listener on the hidden window, this event will only
                    //be fired when the user pressed Cmd+Q or selects quit from the menu
                    //then set macsupport_allowExit to true
                    win.addEventListener(Event.CLOSING, function(e:Event):void {
                        macsupport_allowExit = true;
                    });

                    //add an event listener to this window on closing
                    addEventListener(Event.CLOSING, function(e:Event):void {
                        //always preventDefault
                        e.preventDefault();

                        //wait one frame, then check the macsupport_allowExit variable
                        //if it is true, we nedd to exit the app, otherwise just hide
                        //the app window
                        callLater(function():void {
                            if ( macsupport_allowExit ) {
                                nativeApplication.exit();
                            }
                            else {
                                nativeWindow.visible = false;
                            }
                        });
                    });

                    //add an event listener for INVOKE to show our main app window
                    //when the dock icon is clicked.
                    addEventListener(InvokeEvent.INVOKE, function(e:InvokeEvent):void {
                        if ( nativeWindow && !nativeWindow.visible ) {
                            nativeWindow.visible = true;
                            nativeWindow.activate();
                        }
                    });
                }
            }
        ]]>
    </mx:Script>
</mx:WindowedApplication>