views:

322

answers:

2

When I listen for key up and key down events with wmode="transparent", I receive 2 key down events followed by a single key up event for the following keys: F-keys, arrow keys, ins, del, home, end, page up, page down, pause, print screen, application key, windows key, and the equivalent numeric keypad keys. The other keys work normally. This is occurring with FF 3.5, but not with IE 6.

Below is a simple Flex application that illustrates the problem if you run it with wmode="transparent".

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" applicationComplete="init()">
<mx:Script>
 <![CDATA[
 import mx.controls.Label;
 private function init():void {
  stage.addEventListener(KeyboardEvent.KEY_DOWN, onKey);
  stage.addEventListener(KeyboardEvent.KEY_UP, onKey);
 }
 private function onKey(event:KeyboardEvent):void {
  var msg:Label = new Label();
  msg.text = event.toString();
  eventLog.addChildAt(msg, 0);
 }
]]>
</mx:Script>
<mx:VBox width="100%" height="100%">
 <mx:TextInput width="100%" text="Hello"/>
 <mx:VBox id="eventLog" width="100%" height="100%"/>
</mx:VBox>
</mx:Application>

Our application requires wmode="transparent" and needs to handle both key up and key down events for the problematic keys, so I'm looking for the best way to solve this. What would be the best workaround for this problem? Is there some Flash player parameter that I can use to get this working? (FF configuration changes aren't viable for our application, but might be interesting for understanding the cause of this.)

A: 

By the way, the workaround I'm currently favoring is to discard additional key down events for a key during a brief dead-band (maybe 50-100 ms) following its initial key down event. This solution has the merits of being relatively simple to implement while still supporting key repeats, though with an additional delay before repeat begins.

Here's basically what I've added to the test code:

private var keyDownTs:Array = new Array();

private function onKey(event:KeyboardEvent):void {
    var msg:Label = new Label();
    msg.text = getTimer() + "-" + (isDead(event) ? "**DEAD**" : "") + event.toString();
    eventLog.addChildAt(msg, 0);
}

private function isDead(event:KeyboardEvent):Boolean {
    var dead:Boolean = false;
    switch (event.type) {
     case KeyboardEvent.KEY_DOWN:
      var ts:int = keyDownTs[event.keyCode];
      if (ts == 0) {
       // save timestamp for the initial key down event
       keyDownTs[event.keyCode] = getTimer();
      } else if (getTimer() - ts < 50) {
       // this key down is within the dead-band of the initial key down
       dead = true;
      }
      break;
     case KeyboardEvent.KEY_UP:
      // clear previous key down timestamp
      keyDownTs[event.keyCode] = 0;
      break;
    }
    return dead;
}

On my system, the spurious key down events are happening within a few ms of the initial key down (2-6 ms), so 50 ms is looking like a pretty good value. For my production implementation, I think I'm going to put this logic into an EventDispatcher that KeyboardEvent listeners will use instead of listening to the stage directly.

Kevin Condon
A: 

I don't have an answer for you, but can confirm that wmode="transparent" has caused this exact same behaviour with an item on our website. Using transparent and opaque wmodes was causing this unidentified (until now) double keypress behaviour. Due to the numerous issues with opaque and transparent modes, we instead worked around all the other issues that surround using standard mode, because it's the only mode in which keyboard IO works correctly.

Other issues include incorrect key mappings, issues with screen-reading/accessibility software, flash movie does not start executing until it is scrolled into the viewport and others.

If there's any way you can survive without wmode transparent, then consider it, because otherwise, as far as I could see, everything is borked.

The reason we initially chose transparent mode was so we could overlay other HTML elements over the Flash movie. Now instead, if we're going to overlay, we "hide" the flash:

Don't use css display:none because this resets the movie (but not using AX version in IE). The movie can be hidden by either setting its height to 0.001px via css or to visibility:hidden in css, or both.

spender
This mustn't affect many applications, because there's very little that I turned up in my web searches for the problem. It's reassuring to find someone else has encountered it. Thanks for the heads up about other items to watch for.I agree with you, we'd avoid transparent mode if we could. Unfortunately, we need to display HTML elements over just a portion of our Flash movie, so that the user can still view and interact with the Flash. So we can't do the simple hide approach.
Kevin Condon
I'm sure you've probably seen some of these. The last link is a particularly depressing read.http://blog.headlondon.com/2006/06/02/no-wmode-please-were-british/http://www.last-child.com/make-flash-accessible-to-screen-readers-in-transparent-window-mode/http://groups.google.com/group/swfobject/msg/412f90e9a96694ec?pli=1
spender