actionscript-3apache-flexairfocusmanager

How to remove focus from control when window does not have focus?(otherwise it will be restored when window gains focus again)


I need to remove focus from TextInput while Adobe Air window does not have focus. But I can't find normal way to do this.

Here is a sample app:

<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
                       xmlns:s="library://ns.adobe.com/flex/spark" 
                       xmlns:mx="library://ns.adobe.com/flex/mx"

                       >
    <fx:Script>
        <![CDATA[
            protected function onFocusIn(event:FocusEvent):void{
                input.appendText('I');
            }

            protected function onFocusOut(event:FocusEvent):void{
                input.appendText('o');
            //  input.focusManager.deactivate();
            //  stage.focus = null;  
            //  focusManager.setFocus(input2);
            //  stage.focus = stage; 
            }

        ]]>
    </fx:Script>
    <s:VGroup>      
        <s:TextInput id="input" focusIn="onFocusIn(event)" focusOut="onFocusOut(event)" />
        <s:TextInput id="input2" /> 
    </s:VGroup>

  1. stage.focus = null does not work - stage.focus is already null when window does not have focus, so it does not work.

  2. input.focusManager.deativate() does the trick, but it seems that this manager is used for other controls, so this is not a good option. It is said in the documentation that

    The SystemManager activates and deactivates a FocusManager if more than one IFocusManagerContainer is visible at the same time.

    but in this sample app I have two TextInputs and when I deactivate focusManager for first one, second one does not restore focus on alt-tab any more.

  3. I can set focus to something else, but creating special 'dummy' input is some kind of monkey patch, and I prefer to avoid using it until it is inescapable.

  4. Setting stage.focus to some parent of TextInput does not have any effect either.

    So, do you know any better way to remove focus from component while window does not have focus?


Solution

  • Ok, I found the solution that satisfies me:

    FocusManager(focusManager).mx_internal::lastFocus = null;

    It's not perfect as it uses mx_internal namespace property which can be changed in future sdk releases.

    This solution works because focus is restored by FocusManager on windows activation(nice code with commented out lines...):

        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";
            }
        }
    

    Unfortunately is not a part of focusIn handler stack trace, so it took time to find who is restoring focus on windows activation.