Firefox is the only browser I use, so when things don’t work, I get worried. We’re looking at Flash as a delivery vehicle for some of our applications for people with disabilities and ran into two potential show stoppers:
- Flash doesn’t get focus unless you click on it with the mouse; many of our potential users don’t use mice!
- Flash doesn’t allow access to right click; many switch interfaces generate left and right click events to signal the user pressing the mover or chooser switch.
I surfed around a bit expecting to find some quick solution and only found despair. It seems that lots of people have encountered these problems in various forms and haven’t found a solution.
I’ve found a very simple approach that works just fine for what we need; perhaps it will help someone else. The high bit is I’m using the Flash ExternalInterface object to allow JavaScript to catch keyboard and mouse events and then tell Flash about them. Flash never gets the focus and doesn’t need it.
I have attached an archive with the various pieces. If you download this and activate the HTML your browser may pop up a Flash security dialog; if so, you’ll have to allow Flash to access the folder containing the code, or put it all on a web server someplace to get around the security model.
The Flash movie is just a trivial demo. I created a Dynamic Text control on the stage and gave it the id MyText. On Frame 1 I inserted the following ActionScript code:
import flash.external.*;
function showMsg(txt) {
MyText.text = txt;
}
var connection = ExternalInterface.addCallback("callMe", this, showMsg);
if(connection) {
showMsg('ExternalInterface ok');
} else {
/* this apparently happens when the security model is violated */
showMsg('ExternalInterface failed');
}
You can export as many different functions as you like with ExternalInterface.addCallback. Of course, you’d likely want different functions for keyboard and mouse events in a real application.
In the HTML I have some JavaScript that:
- catches keydown and keyup events,
- catches mousedown and mouseup events,
- informs the Flash movie about them using the function exported above, and
- disables the right-click context menu.
Here is the HTML with the JavaScript embedded.
<html>
<head>
<script type="text/javascript">
var myMovie;
function killEvent(eventObject) {
if (eventObject && eventObject.stopPropagation) eventObject.stopPropagation();
if (window.event && window.event.cancelBubble ) window.event.cancelBubble = true;
if (eventObject && eventObject.preventDefault) eventObject.preventDefault();
if (window.event) window.event.returnValue = false;
if(eventObject.preventCapture) eventObject.preventCapture();
if(eventObject.preventBubble) eventObject.preventBubble();
}
function keyCallback(msgtxt) {
return function(ev) {
var kcode = ev.which;
var kchar = String.fromCharCode(kcode);
var txt = msgtxt + ' ' + kcode + ' ' + kchar;
myMovie.callMe(txt);
}
}
function mouseCallback(msgtxt) {
return function(ev) {
var txt = msgtxt + ' ' + ev.button;
if (ev.button != 0) killEvent(ev);
myMovie.callMe(txt);
}
}
function setup() {
window.addEventListener("mousedown", mouseCallback('mouse down'), true);
window.addEventListener("mouseup", mouseCallback('mouse up'), true);
window.addEventListener("keydown", keyCallback('key down'), true);
window.addEventListener("keyup", keyCallback('key up'), true);
window.addEventListener("contextmenu",killEvent, true);
myMovie = document.fev1;
}
</script>
</head>
<body onload="setup()">
<embed src="fev1.swf"
quality="high"
bgcolor="#ffffff"
width="550"
height="400"
name="fev1"
align="middle"
wmode="transparent"
allowScriptAccess="always"
swLiveConnect="true"
type="application/x-shockwave-flash"
pluginspage="http://www.macromedia.com/go/getflashplayer" />
</body>
</html>
I emphasized what I think are the critical bits for the ExternalInterface in red and for killing the right-click context menu in blue. The rest is pretty straightforward JavaScript code. I won’t be surprised if someone who knows Flash and JavaScript can do this much better.
When you run this, you should see “External Interface OK” in the Flash movie; if you don’t then you’ve got to figure out your security settings to allow the ExternalInterface object to properly initialize. Assuming you got past that, typing should show you the key code and letter on both key down and key up. Likewise, clicking with the mouse should show which button you’re pressing and should allow you to click anywhere in the window without popping up either the Firefox or Flash context menus.
I think this approach could be made to work in IE. Besides the usual differences in accessing the DOM, turning off the right-click context menu is likely the only part that will be different. I’ve seen suggestions of using a transparent shield layer over the Flash movie to catch those events.
That’s really all there is to it. I’d be very pleased to hear about improvements to this method. I suspect that a Flash programmer truly skilled in the arts could synthesize Key and Mouse events so that normal listeners would be invoked. If you do that, I’d love to learn how!
30 comments
Gary, thanks for the tip. We do use this technique to capture keyboard events, and we do in fact turn them back into MouseEvents and dispatch them from the Flash side, where they get picked up by event listeners.
I did some testing with wmode=transparent some time back. It does make it possible to solve some problems by floating HTML on top of Flash, but it causes terrible flickering when the window is resized. I know there are other problems it introduces too, but I can’t remember them off the top of my head. The net is we decided it wasn’t usable for our app.
Good luck with the good fight against Firefox’s limitations.
You are welcome and thank you for the heads up about problems with using a shield layer in IE. We’re willing to require Firefox for the first phase of our project.
great but i don’t see how it resolved this point :
1. Flash doesn’t get focus unless you click on it with the mouse; many of our potential users don’t use mice!
With your solution flash can know if the user use the tab key to move focus but i don’t see how actualy get the focus or give the focus back to the page
With the approach I describe Flash doesn’t need the focus and doesn’t get it. The page keeps the focus and forwards events into Flash. My student has it working in IE as well. I’ll post that solution soon.
ok if i have well understand you want to use some function in the flash movie with a keyboard shortcut without the need to focus the flash movie with the mouse first.
Great but there is still a different problem, blind or disabled people can use keyboard to go trough the links of the page with the tab key but in firefox they can’t go trough the flash movie (and this way know what exactly is in the movie) without first using the mouse to focus the flash movie and then use the mouse again to focus out of the flash movie.
Yes, you are correct. Our solution does not address the issue of tabbing into and out of general Flash objects. We turned the problem on its head for our special case of Flash applications written especially for people who are blind or otherwise unable to use the mouse. My student is writing a application to enable children with various motor and other disabilities to write. We developed the method described here to allow his Flash application to work without first requiring a mouse click. We also enabled right click because some devices produce left and right mouse clicks.
Thanks for this - I found this really useful. Would love to see the solution for IE though.
I’ve stumbled across this blog in search of the solution to a similar problem - my Flassh App has a draggable widget, but if the user drags & releases outside the flash content, the flash obviously loses focus, requiring the user to click once before being able to drag again! Very annoying!
Have any of you found a workaround that might be applied to this problem?
I found that in Firefox 2.0.0.9 and IE 6.0.29 the following works:
(foo being the id of the tag)
I think I read somewhere once that in Firefox the ‘L’ in onLoad must be capitalized.
I’m way too lazy to troubleshoot it out.
I could be wrong about this, but it’s working for me, hope it helps someone out there.
I don’t know about the right click case but you could focus the flash without any problem using javascripts. Just use the “setFocus()” function to focus the flash movie object. Its works.
Not in Firefox, at least not last I tried it.
Many thanks for the HTML with the JavaScript embedded. It´s very usefully 4 me. Thanks for sharing it
Buzzword seems to have solved the first issue. Any idea how they did it?
jw: Thanks for reference.
Below is a javascript function from mz_keyboard.js at Buzzword.
function MZReturnFocusToBuzzWord()
{
// This doesn’t work. Apparently the Mozilla plugin API doesn’t allow programatically setting focus to a plugin (Flash in this case).
// It actually causes problems such as requiring two clicks to focus in a text box -syost
// setTimeout(’document.getElementById(appName).focus();’, 0);
}
In Firefox, setting the wMode to ‘window’ solves this problem:
When you mouse down in flash and you get a mouse up outside the browser or stage, you get the correct behavior in flash. If the wMode is not ‘window’, flash never gets the mouse up.
When the wMode is ‘window’, controlling the focus is a little more difficult. For Firefox, you must set the focus to an html textarea within the document and handle key events. You must also set the focus to the flash object. When browser windows such as the address bar have focus, you must make sure the flash object gets the focus when clicked on. This varies among browsers, but in Firefox, setting the focus back to the textarea fixes this problem.
Note that when wMode is not ‘window’ in Firefox, you do not need to use a textarea but the mouse up issue becomes a problem.
This application gets the focus without being clicked on in a variety of browsers in windows. This has not been tested on Linux or Mac. Use any user name.
http://sms.pangolin.com/vflash/Venus.html
Thanks for posting. Your trick almost works on Ubuntu and OS X except I get no echo so I have to type blind. But it is capturing the key events without clicking.
I apparently can’t use tab to get to the gender field or out of the login text box for that matter.
But this is good progress.
Gary, Thanks for the heads up on linux VM
In the test application, I front end the TextField to fix these 3 problems:
1) The normal TextField caret keeps blinking when you are entering text. This is very annoying and not user friendly.
2) Scroll had or still has a bug in which the caret disappears.
3) When entering spaces at the right edge of a TextField the caret disappears to the right of the TextField. Geeze, get with it Adobe.
In the process of doing this, I set the TextField to an extreme size to prevent ScrollEvents from occurring. Well apparently my size was too extreme for Linux and caused the disappearing act for the text. This has been fixed. The actual focus problem was not related to this.
Tabbing is an application issue and not related to the focus problem.
The focus handling seems pretty good now in Linux Firefox. I have noticed when Firefox is not in focus and you click on the caption/title bar, the app does not get the focus so I need to check this. Also I need to choose a better font.
This can be checked at: http://sms.pangolin.com/vflash/Venus.html
So far the most ‘different’ browser in this respect has been Safari. But at least under windows it works. Of course I am very interested in any input on this. Please post back to Gary’s blog regarding this issue.
Browsers tested and working under windows:
IE 6 & 7, Firefox, Opera, Netscape 8, Advant, SlimBrowser, Flock
……
Browsers tested and NOT working under windows:
Netscape 7.2 - no ExternalInterface available
Safari beta 3.04 - wMode not ‘window’ focus works but no mouse up outside stage, wMode = ‘window’ focus not reliable but mouse up works. I have reported both conditions to Apple.
……
Browsers tested and working on mac and linux:
Firefox has been tested and working and perhaps others.
……
Once you have reliable keyboard focus, the issue of tabbing becomes just an application issue. Currently I filter them out.
Sarfari beta 3.04 is now working well for the focus issue…
…..
Some notes about wmode:
…..
When wmode is ‘window’ your flash application is put into an actual OS window. For windows this would be an HWND window. Given this, one would think it would be easy for Adobe to direct the focus properly to the flash application but this is not the case. ‘window’ wmode does solve some problems. 1) You always get the correct mouse up outside the stage. This is important when you have started selecting text. If flash does not get the mouse up it thinks you are still selecting and no amount of dispatchEvent will fix it as far as I can tell. 2) When you right click in Opera you get the flash context menu instead of the Opera context menu which is at least consistent. If wmode is not ‘window’ in Opera you will get the opera context menu. This can also happen in Firefox depending on user settings but ‘window’ wmode fixes it in all cases. If wmode is not ‘window’ in Netscape 7 you can just about forget about your flash app working correctly when selecting with the mouse.
…..
‘window’ wmode can cause problems with other HTML elements on the page. That is, you cannot overlay a ‘real’ window with an HTML element. In some cases an IFRAME may work in this regard. In my case, I take over the entire browser page and so this is not an issue. I am currently always using wmode ‘window’. Flash is somewhat lacking at the time being for complete page layout but I am going with it and hopefully it will get better. I am very tired of the HTML ‘foolishness’.
…..
‘window’ wmode will prevent you completely from intercepting ‘right click’. Adobe wants the user to be able to adjust settings thru this menu. I have complained along with many others to them about this. They capture the right click but don’t seem to be able to set the focus correctly. Remeber, when wmode is ‘window’ and a real HWND exist, they should have alot of control and should have no problem setting the correct focus in any browser. About the only resolution that would work is to use an ActiveX control that installs a mouse hook. This will fix it but then you have installation issues.
…..
When wmode is not ‘window’, the focus problem can still be solved but not without some side effects in some browsers including Firefox. The worst problem is not getting the correct mouse up outside the stage. This occurs in about half the browsers tested when wmode is not ‘window’. Another problem in Opera and sometimes Firefox, is that on ‘right click’ the browser context menu may come up insteal of the flash context menu witch is not consistent.
…..
It is all a bit complex, especially when you need an editor with a caret blinking in the flash app, but I have boiled it down to some clean code. It takes management and the ability to take keyboard input both externally and internally to the flash app. I will update with some actual details eventually as time permits.
Here is a sample app that demonstrates more precisely the focus solution. It is simple with a bare bones editor with no caret and no control codes etc. I intend to make the source code for this available, but first I want feedback. It needs more testing on Linux and Mac. I would like the results for any OS and any browser whether it works or not so I can maintain a record. Please include the OS and browser version tested. If it does not work please also include a brief explaination and I will look into it.
…..
If there is sufficient response I will post the source code.
…..
http://sms.pangolin.com/FocusSample/FocusSample.html
…..
P.S. Right Click of course is easy to get rid of when the flash object is within an application (exe) and not the browser. This maybe useful to some as this is easy to accomplish. You can still use the http address of the swf within the exe and so all is good.
I forgot to mention that the FocusSample also demonstrates tabbing.
Don,
It works fine on Ubuntu in Firefox 2 and on my Mac in Firefox 2 and Safari. Good work. Please put the source out there so people can benefit from your work.
The source code for keyboard focus without mouseclick can be found here:
…..
http://sms.pangolin.com/FocusSample/focussample.zip
…..
Note that all testing and the FLA file is flash 9 ActionScript 3. This may be ported to AS2 but I have no idea on that as I do not use AS2 at all.
…..
Browsers tested and working under windows:
IE 6 & 7, Firefox, Opera, Netscape 8, Netscape 9, Advant, SlimBrowser, Flock, and Safari
……
Browsers tested and NOT working under windows:
Netscape 7.2 - no ExternalInterface available
……
Browsers tested and working on Mac:
Firefox and Safari
…..
Browsers tested and working on linux:
Firefox and I did not test Netscape 9 on linux but it is Firefox and registers as Firefox so it should be fine.
…..
The worst browser tested and working was Netscape 8. Netscape 9 is in essence Firefox with a little nicer UI and works well.
…..
The easiest was IE
…..
The most unique was Safari do to its event handling of Cut, Copy, Paste, and Select
…..
The code uses a heuristic approach to solve the problem. Pay attention to what I have said previously about the wmode.
…..
Use the code as you wish but please keep the required text block within the code.
…..
The documentation is in with the code and should stay there. If there are changes or improvements please post them here.
donmoir@comcast.net
Hello Mr Don, I can say honestly that your code works fine as I have tried it in your Venus chat.
I can’t wait to try it in my own app, as I hope it will make it work as fine as it does on yours.
I will keep you inform as I make my own experiments, but I don’t think I will be able to improve, cause you are a genious !!
Thank you for the kind words Samba, but no amount of intelligence can overcome raw determination
…..
The sample provided is not intended to solve all the issues with keyboard handling for everyone. Each case may be different and depends on your needs. The browser and flash situations are just abismal. If all you need is keystrokes and do not need to provide for an internal editor, then this is much simpler and all keyboard handling can be done nearly 100%. In this case, the flash app never gets the keyboard focus, not in IE or for any browser and this should work well for you. Anytime the flash app tries to get the focus say thru mousedown, just refuse it and set it back to the external editor. Samba brings up the issue of spanish characters such as ¿ . These characters are generated with Alt+(3 digit code) on my keyboard. Well this seems to be another combination issue with flash and the browser. Interanally I do not get Alt sequences from flash. I am looking into this more. These characters are readily available thru the external editor. So whats the catch ? If you always set the external editor to have focus and do not want mouse support then all should be good. If within your flash app, you need to allow selection with the mouse, then the flash app must be allowed to have focus. Also it is worse if you need to provide a text editing environment. In this case you cannot relinquish the foucs on mouseup back to the external editor. This causes the selection highlight to disappear. Note you can set the TextField to always show focus in a grayed sort of way but other issues arise… If we have gotten this far we must be crazy lol… IE in particular does not like its focus switched around like may be suggested. It likes it focus more or less placed into the flash app and all is good except now you do not get Alt+ characters and other things crazy happen in IE with Alt except when an external textarea has the focus.
…..
To summarize:
If all you need is complete keyboard support, always use the external editor and keep it in focus the best you can.
…
If you also need mouse selection support than you are going to have problems.
…..
More research is going into this and I will post back whenever.
Alt key handling required a few minor changes. When the Alt key is down, some browsers also pass the numbers from the number pad as keypress events, others do not. So when the Alt key is down, no numbers are passed. In Flash, the Alt key extended characters are passed as keyup events. Also backspace is now handled in the keydown event. Some browsers do not pass backspace in the keypress event. I made the changes to the sample code and it can be found here:
…..
http://sms.pangolin.com/FocusSample/focussample.zip
…..
For a complete working example you can go here:
…..
http://sms.pangolin.com/vflash/Venus.html
…..
Keep in mind that there are some situations when the browser windows such as the address bar have focus. In these cases, there is not alot that is practical to do. You can steal the focus away from these windows, but then you are fighting the user and that is probably not a good thing.
…..
donmoir@comcast.net
Reading this interesting story because i have some trouble getting a flash scrollbar working (using the scrollwheel on the mouse) without clicking the swf first.
I tried adding a javascript in the body tag: onLoad=”window.document.secarchitecten.focus();”
but without luck.
Is there a way to set the focus to the swf - in a way that the scrollwheel will work immediately without clicking the swf?
And by the way, the flash is written in AS2.
For working example you can visit the following link: http://www.secarchitecten.com/nieuw/
Stewart
Hi Don,
Your work looks amazing. I tried it out immediately.
In the example webpages you have mentioned, the behavior is as expected but when I used your html wrapper in a local flex project, it did not make any difference.
Flex Builder - 2.0.1
Firefox - 2.0.0.13
Steps -
Create new project FocusSample.
Added a textinput to it.
Copied your html and js file to the bin folder.
Opened the html in browser.
Is there a call back method required in
the swf file to accomplish this?
Has anybody else used it successfully in their projects?
~Peeyush
Hi Peeyush, Thanks for the comment…
….
I do not use flex because I don’t want to give Adobe more of a chance to screw up ! lol So this means pretty much everything I do is custom and everything works as expected…
….
Perhaps if Adobe added a focus() function to the flash object this could be fixed by them. I could be wrong here but seems reasonable. So the problem is that all browsers except IE do not provide this function when wmode is ‘window’. In Firefox when wmode is not ‘window’ it also has the focus function but other things don’t work… Seems like grade school stuff… If you have ever used Flash CS3 Professional, the damn doesn’t know if it’s coming or going lol. Painting all the time and sure as hell has trouble keeping track of the focus as well as color code highlighting etc. It’s no wonder there are problems.
…..
Now IE does mangage to get it right, and the other browsers do not. But Adobe, when wmodw is ‘window’ you have a hell of alot of control so whats up ?
Peeyush,
I am not sure if I read you clearly. It is not necessarily that the TextInput will actually gain the focus, but it will have the appearance of having the focus. In a real app this does require a good piece of work. Study the FocusSample.fla file.
Leave a Comment