tags:

views:

918

answers:

3

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.

+1  A: 

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>
maclema
Thanks for the code - I actually didn't need to do the hidden window part because the preventDefault on the CLOSING event handled that for me. The main issue I had was with the EXITING event. I just had to add a loop to close all windows on the EXITING event. For some reason, calling preventDefault ont he CLOSING event made it so even when I called nativeApplication.exit() in the EXITING event, the app would remain open.
Chris R
+2  A: 

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&amp;catid=670&amp;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();
   }
 });
WillyCornbread
The EXITING vs CLOSING events are very helpful (for some reason, Flex Builder doesn't show an exiting option in auto-complete for WindowedApplication components). This worked for me.
Chris R
Thanks! I've been struggling with this issue for months! I had no idea it was an updater issue. This is the thread that mentions it: http://forums.adobe.com/thread/246228?tstart=0
leolobato
A: 

OOOHHHHH my god thanks a lot my friend I was looking for this everywhere, this is just what I need. thanks again

harvey