April 29, 2004
One of my first orders or duty in coming over to work for Grant has been to contribute to Daedelus, a project we'll be releasing in the coming weeks (sounds mysterious, doesn't it ;) While in the process of coding parts of it, I ran across an issue which had me completely stumped for a couple of hours. After trying everything I could think of, I noticed that the behavior was only manifesting itself when I was using a Macromedia (MM) V2 component in the same file.
From what I can tell, this issue could potentially have serious ramifications on any project that uses a V2 component in combination with plain movieclips and buttons.
So here's the deal…my scenario had my Flash movie dropping click events, kinda reminiscent of what Grant described in a blog entry way back. However, in this case, it isn't a random occurance and it doesn't depend on processor strain. It turns out that there is a specific situation where clicks get dropped.
One of the really cool features of MM's V2 component set is that it's got strong focus management, so that components can receive and lose focus via clicks or key events. Unfortunately, this is the cause of the problem. Ever notice that if you use say, a TextArea component, and you select some text in it, then use the scroll thumb to scroll the text, when you release the thumb, the selection magically restores itself? Yeah, that's pretty cool. Well, it seems that this magic happens primarily via mx.managers.FocusManager. Basically, all it does is store the beginIndex and endIndex of the selected textfield when the mouse is pressed (oh, and did you know that if you use the V2 components, every onMouseDown, onMouseUp, and onMouseMove event has code that runs on those events?) and restore the selection on release. Sounds nice, but there is one major issue that arises. It seems that somewhere in the code that does all of this, something occurs that prevents onPress and onRelease events from being fired if a textfield has focus.
Here is an example…
If you look at the first example, you can click on the text field at the right and then click the blue button a few times without moving your mouse (frequency of clicks doesn't matter) and you notice that all click events fire properly (onPress in this case).
Then, in the second example (identical to the first, except this one has an MM button component on the stage – it doesn't actually do anything), if you set focus to the textfield and then try clicking the blue button, again without moving your mouse, all of a sudden, it doesn't fire all of the onPress events properly (it only fires a new event when you click after moving your mouse to a new position).
After hunting through some of the component code, I noticed that UIComponent actually contains 2 methods, pressFocus and releaseFocus that all onPress and onRelease handlers should call respectively. In fact, it seems that all MM's components do call these, and so if you click on any MM component while a textfield is focused, you don't have these same issues (if you click on the MM button in the example 2 above, you'll see that the blue button reponds properly thereafter). That's fine and dandy if you are writing classes that inherit from UIComponent, but what if you just want to create a simple movieclip or button. In these cases, it seems that if a textfield has focus, this bug will pretty much always manifest itself.
The very quick way to circumvent this bug is to just call:
from inside your onPress handler. This will remove focus from the textfield and your onPress and onRelease events won't be dropped. The following example adds this one line of code.
If you were clever, you could even write some code to save the selection and restore it onRelease (kinda like what MM does).
Does this affect your project? If you're using any MM components in your app, you can do this simple test:
Click on a textfield (any textfield) in your movie and then click on any NON-MM component (i.e., any movieclip or button that has an onPress or onRelease event), cross your fingers and check the results…