FLAws: FP7 drops click events

To begin the FLAws series, I’d like to shine some light on what looks to be a major Flash Player 7 bug. This issue has had Beau and I ripping our hair out for the past few weeks, as we have sought workarounds for it.
Description
In short, Flash Player 7 will sporadically fail to register Release events under high strain situations. This causes huge problems, as users must click buttons and components multiple times before they will register the click – talk about a usability nightmare.
Read on for a more in-depth description, and the workarounds that we found.

We still haven’t isolated this problem 100% (time is limited, and chasing MM’s bugs doesn’t pay the bills), but here’s what we’ve found:
Symptoms and details
1) It is not an ActionScript issue (ie. the AS code is not dropping actions), rather it is a player issue. MovieClips are simply not receiving Release events from the player. For instance, in a high strain environment, the following trace will execute sporadically when the user clicks on myClip:

myClip.onRelease = function() { trace("blah"); }

2) The scales proportionately to the amount of stress placed on the player (CPU). As the complexity of the application increases (which happens very quickly with the new component architecture), the frequency with which Release events are dropped increases. It is not merely the complexity of a single SWF that causes problems, as increasing stress by having multiple SWFs open will also cause the issue to manifest.
3) The issue is present in all FP7 players that we have tested to date, including the ActiveX control, standalone, IDE and plug-in players.
4) As far as I can tell, only Release events are affected. Press, RollOver, etc events continue to be triggered without any problems.
5) Occassionally, the MovieClip that was clicked will display what appears to be a quick re-draw, where it flashes white momentarily, then re-appears. This is not an ActionScript redraw, but more of a system redraw. This behaviour only occurs when the Release event is dropped.
6) The stresses required to make this issue obvious are quite high – we had about 200 components on screen – but it will manifest in lower stress situations. However, developers and users are likely to attribute an occasional lost click to user error or other causes. Unfortunately, with real applications, it will not be uncommon to have in excess of 200 components, particularly with forms-based development (which instantiates all components used in the swf at once), and with accordion or window layouts.
Work-arounds
I have only found two partial work-arounds to this issue so far, both of which you may have ascertained from the details above.
1) Decrease the stress placed on the player by reducing the number of components on-screen at one time, and removing/optimizing idle processes. I’m not sure why MM components sitting on the stage doing nothing place so much stress on the player, but they do. We did not have any idle processes in our application, but this FLAw was still very evident. I’ll go into more details in my next post on how to reduce stress on the player, but briefly: avoid form-based development, unless your application uses less than 50 components total; avoid idle processes by taking advantage of events; and be sure to remove any content that isn’t being used, especially if it includes components. You have to actually remove the content, not just hide it – remember, hidden content uses almost as much resources as visible content.
2) Change all Release events to Press events. This is hardly an ideal solution, but it does work. If you’re using components, you can overwrite SimpleButton.as and make modifications so that most components will use Press for their “click” events. I’d make them myself, and post the results, but then I’d be violating the EULA.
Again, I’d like to re-iterate the point that I welcome community input on these posts. I don’t have enough time to chase around these bugs, isolate them, replicate them, document them, etc. so there’s a very good chance I’ve missed something.
If you see anything wrong, have a work-around, can confirm/replicate the issue, can add more details, or know of a related problem, please don’t hesitate to post in the comments for the benefit of the community.

Grant Skinner

The "g" in gskinner. Also the "skinner".

@gskinner

24 Comments

  1. Is this a FP7 only issue? I had similar problems with FP6 when building large dynamic menus in “action-packed” environments. Haven’t done much with FP7 yet, but it seems like it’s still there then.

  2. Sean, I never ran into any problems in FP6 personally, but it would be interesting to know if this is a carry-over from the previous version.

    This problem will definitely be exacerbated with F04, due to the huge overhead of the new components.

  3. Lower your framerate. I’ve had Remoting calls, XMLSocket messages, etc. not come back simply because my framerate was so high. Don’t have to keep it there, just try it and see the results.

  4. Jesse,

    Thanks for the suggestion. Tried it on an old build, but it didn’t make a difference (at least not a very noticeable difference). I would expect it to make some difference though, as it would reduce the strain on the player.

  5. I’m pretty sure the bug has been in the player for a while. I hit it in FP6 when dealing with listBoxes, but never narrowed it down. It definitely affected onReleaseOutside as well (possibly onMouseUp too).

    Now, the issue here is : What’s your system CPU like in this situation? Maxed? How many movie clips total?

  6. Nigel,

    Did some testing… definite correlation between CPU utilization and dropped clicks in the player.

    On my 1ghz PowerBook G4 (768MB), when CPU utilization is around 50%, I get occasional drops, but when it approaches 100% nearly 2/3 of clicks are dropped for me.

    The old version of our app uses between 25-35% of CPU sitting idle (ie. pure component overhead, no idle processes) in the standalone player. The new version uses 15-20% while idle.

  7. You are saying that only onRelease is affected, right? RollOver, RollOut, Press, DragOut, Dragover all fire, correct?

    I am not sure what your ‘high strain’ environment includes besides a heavy amount of components – and a high framerate.

    I assume (maybe incorrectly) that to create the ‘fail’ behavior, you’re also rapidly clicking random components? Or the other way round, are you sure the mouse is actually still over the component when you release?

    Point is – onRelease only(!) fires if you release over the component/button/movieclip. If your mouse has moved since then, it fires onReleaseOutside, which we generally ignore.

    In a high strain environment – meaning CPU at 100% Flash is not able to handle all events in real time, there is a lag in response. if you use a custom mouse cursor, you will see the lag in movement.

    so I would expect that if Flash is under such stress, by the time the release event is registered by the Flash player (not necessarily the exact moment it happens), you may have moved the mouse, leading to an onReleaseOutside event being triggered.

    If you want Flash to being able accurately respond to mouse events, your movie can’t be maxing out the CPU, otherwise a disparity is bound to happen.

    Not sure if you have tried for this (if you actually get onReleaseOutside when waiting for onRelease), but I think it’s certainly worth a shot. If you release onReleaseOutside, make sure you record the mouse coordinates and do a hitTest as well, just to see what’s going on.

  8. Andreas,

    I am well aware of lag in high strain scenarios with Flash, and this is definitely not a manifestation of it. Our testing was with a real application, using very targetted clicking – I even went so far as to test by pressing and holding for 1 second, then releasing and keeping the cursor over the element for an extended period – the Release event is never fired.

    As in my previous post, this issue occurs even when the processor is not maxed out (though with much less frequency), and frame rate has little effect (other than lowering the CPU utilization slightly).

    Also, as Nigel mentioned, it appears to affect ReleaseOutside as well.

    Thanks for the discussion. Cheers!

  9. I have hit this issue as well. It wasn’t in a code intensive environment, but rather a design intensive one. The design itself was using alphas, gradients, and all the other lovelies that designers love and Flash hates. This was coupled with around 50 dynamically created mcs, each with two inner mcs (a frame1 swf and an optionaly frame2.swf) each with loaded content. I had the code processes isolated and shut off, but the onRelease wouldn’t fire everytime. This was a flash 6 project. I solved it by switching over to onPress events.

  10. FLAcunes, première partie

    Ouf! Je l’avais bien prédit tout à l’heure, la série de Skinner vaut de l’or! Premier article maintenant disponible. Il y traite d’un bug assez majeur avec le player 7, qui lorsqu’on lui en demande trop trop à la fois…

  11. Yeah, for me, onMouseUp was also definitely not firing. Anyone confirm?

    I’m doing a little research into this, so the more fine-grain the info is (ie. a conclusive list of events and some easy-to-repro test cases) the better, so I can get this raised with the player gurus and make it worth their while.

  12. Flash Player 7 drops click events

    Grant Skinner have been looking at some flaws, very recently he came up with a write up on the issue of the Flash player which drops click events under stress condition….

  13. I have another shot in the dark, and it may not be related at all. Let’s assume this is not directly related to the processor use.

    The other question that Nigel raised is – how many clips total do you have?

    By removing invisible idle components, you not only reduce CPU use, but also the clip-count rather drastically.

    Components use a rather high number of clips for skins, getting the overall clip count high pretty quickly. Generally, Flash has a magic number of around 16,000. If you go above weird things may start to happen.

  14. Without writing code to iterate through and count the individual clips, I couldn’t rightly say what the total is, but that explanation would fall short regardless.

    The two contravening pieces of evidence I have available are:

    1) The intensity of the problem scales in a largely linear fashion with CPU usage.

    2) This issue is intensified by other swfs running in the player, or other processor intensive tasks like playing a movie (this is obviously related to #1). So an swf with moderate complexity (ie. definitely < 16000 clips) would stil be affected if CPU usage was high enough.

  15. Can you make this happen if you have a movie with one single button, then spiking the CPU doing something completely unrelated to Flash?

    That would totally prove your point, and would be a perfect test case.

    “This issue is intensified by other swfs running in the player” – I believe Flash may still have a problem with the number of total instances, even when split over multiple swfs running in the same player. I believe that magic number is for the player, not a movie, but I could be rather wrong.

    Adding to that problem – maybe – is that different Flash Player instances use some shared memory, plugins, standalone player, authoring tool (panels, live preview), test movie. I would hope that each instance has it’s own limit, and that the shared memory is unrelated from the issue – but who knows?

  16. so I am trying to proof my theory, but of course am unable to.

    I created a movie that has just a button and a label in it.

    On click, I create 100 new buttons. With every click, the whole process takes longer (minutes evenutally), but even after creating 1700 new buttons, click still fires. (assuming that one button includes 10 or more skin-clips)

    There is however a way for it to misfire.

    Let’s say I switch to another app. When Flash is done, I don’t switch back, but just minimize the other app. My button shows, I can rollover, I click, nothing happens.

    In this case, what actually happens is the system takes over, snatching the release event, giving Flash focus, and the event never goes through to the button.

    This behavior – as annoying it is – is not unique to Flash, it seems to happen in any Windows app, e.g. it happens any time to me when I switch in and out of Word for a string of copy and paste.

    I assume however this is not what you are experiencing.

  17. Grant,

    any update on this? Things seem to have died off for this thread but we are still experiencing this problem. We are working around it by splitting our SWF into a series of smaller ones which get loaded as needed but this seems weird to be forced along this path.

  18. I’m seeing the same issues described here, so I put this example together:

    http://www.oddhammer.com/flash/textarea_component_bug.html

    I have a movieclip on the stage with an onPress event handler and a mouse event

    listener applied to the movie. It works just fine until I drop a TextArea

    component on the stage.

    When I do that and the client types something in one of the TextAreas then the

    button events aren’t properly firing. The example has several extra text

    fields on the stage, but the problem shows up even if it’s just the single

    TextArea and the button (and I trace the output).

    Also.. if I comment out the mouse listener and have _only_ the myButton.onPress

    event handler then the button still doesn’t work all the time. I just added

    the listener to show that the button is getting pressed and something is

    registering it.

    I’m pretty sure I saw something a month or so back on a blog where they tracked this down to a problem in the components.. but I can’t find it anywhere.

  19. I am experiencing a similar problem. Before I load an FLV using actionscript, the button works fine, because I can see the hit color change, when I keep the mouse still and continuously left click. However, after I load the FLV, the button does not show the hit color unless I move the mouse a bit before left clicking again. It will also work if I double-click, but I don’t want users to have to double-click or move the mouse before each successive click.

  20. Ok, I’m starting to wonder if you do a setFocus if that will fix the issue. I notice if I have the error happening and I look at a different window (like a messenger) and then focus back on flash everything works again.

    I’ll try this out and see if that fixes the issue.

  21. Fix: (atleast for me)

    blah.onRelease = function() {

    this._focusrect = false;

    Selection.setFocus(this);

    //do whatever your button was doing

    }

  22. I have a similar issue, but not with components, or even an event assigned to a movie clip. But with an actionscript driven timeline animation with 118 items and regular button items. Under certain conditions which are heavy loads it simply stops registering on(release) events. That is until I move the mouse at least one pixel. They magically come back. Beating my head on the desk. Trying to see if the on(press) changes this.

    — jrawk

  23. Thanks for this great post.

    I do have the same problem but

    – the “press” trick does not solve it

    – lower the CPU usage is not really an option in my case (it is just dynamically build forms in V2 architecture)

    It seems that the problem occurs when :

    – the mouse is over a button, button is highlighted

    – a textInput gets the focus,while the mouse is still over the button (usage of tab)

    – then the button loose the highlight

    – if I click, the button regains the hioghlight but does not fire the “press” event

    Any other/new ideas ?

    Thanks in advance

  24. This problem seems to exist in Flash 8 form applications as well.

    Here is how it manifested itself:

    I have a button that when click, changes a text field, then creates several text fields dynamically on a different component, after doing so if you do not move the mouse it will not register another onRelease event.

    THE SOLUTION: set the focus back to the button using the following command:

    Selection.SetFocus(buttoninstancename);

    Before you set the focus if you dont like big ugly yellow boxes you should use this command to eliminate the focus rectangle:

    buttoninstancename._focusrect = false;

    After doing this I am no longer experiencing any onRelease event drops

Comments are closed.