addEventListener stops working?!

Hey.
Im having a little bit of a problem with eventListeners.
I add
[AS]
MainStage.addEventListener( KeyboardEvent.KEY_DOWN, keyDownHandler );
[/AS]
when i first start the movie, i call it once.
This works just great, the movie detects my key presses and acts accordingly.

The problem occurs if you click outside the movie or open and close the browser the .swf is displayed in. It then no longer detects key presses, not even if i click back inside the movie.

Whats going on here?

P.S. i even tried to spam the add event listener every 100 ms with a timer function but that made no difference either.

any ideas? (bump)
This is still a problem and i dont understand why…

So I’ve been snooping around, and here’s a nice post I found by Wayne-Marsh. I tried his solution and it actually worked for me! Now, from my tests it didn’t break anything, but you might want to be careful just in case.

[INDENT] I feel that keyboard handling in AS3 is broken. In AS2 you could simply poll for key states with a static method, which is perfect for games. This is no longer available in AS3.

The AS3 way of doing keyboards is to add an event listener to an InteractiveObject, which will let you know when a key state changes when that interactive object has focus. That’s right - if you click off the object it will no longer receive keyboard events.

This SUCKS for games (and some other applications). Imagine you have a menu appearing when you pause. You click the resume button and… your keyboard no longer works, because the resume button stole focus.

Fortunately, the events propagate down to parent items in the display list, so something containing an InteractiveObject that has focus will get its key events too. Perfect, so if we just add the listener to the stage object (i.e. the root of the display list) we only need it in one place, right? No. This is where I feel that the whole system is especially broken:

You’ve clicked your resume button again, the pause menu disappears and you return to gameplay. Why can’t you control anything - oh, right, because the resume button is no longer on the display list, and the KeyboardEvent ends up nowhere. Argh!

So how do you deal with this?

The Wrong Solution

You could make sure that the stage is explicitly given focus each frame. Simple enough, stage.focus = stage However, focus is there for a reason, and you will find that this breaks things such as TextFields. Nightmare. Don’t do this.

The (hopefully) Correct Solution

If you poll the stage.focus property you can find out what currently has focus. All we need to do is check that whatever has focus has a valid root object on the display list - if not it means that the object is no longer on the display list and that you should set focus back to the stage. This is easily done, and as far as I can tell it doesn’t break anything.

if (stage.focus)
{
 if (stage != stage.focus)
 {
  if (!stage.focus.root)
  {
   stage.focus = stage;
  }
 }
}

It sucks that this sort of thing has to be done, and I’m wary about using it as a ‘fix’ (who can say for certain that it doesn’t screw something else up and that it is future-proof?), but needs dictate.

It’s nice that Adobe thought up this organised display list structure, but when it makes the system an unadaptable one for certain applications you have to wonder how much consideration they really put into it.[/INDENT]