A possible solution to the stolen-focus problem

2007-12-05 23:06:03 -08:00

Jeff Atwood posted an article today titled Please Don’t Steal My Focus, about dialog boxes coming up while you’re typing.

The problem, in a nutshell, is that these dialog boxes steal keyboard focus. Sometimes it’s for a text field; sometimes it’s just for Full Keyboard Access (i.e., a button gets the focus—usually, these are alert boxes). Regardless of what control gets keyboard focus, it gets it by stealing it from your app, which is a problem if the user is typing when that happens. Most likely, either some text will go to the wrong place, or the dialog box will beep for every keystroke; either result will annoy the user.

We’ve had the same problem for a long time in Adium: we’ll throw up a dialog box, but the user is typing a message, and notices that half his message isn’t in the inputline. We believe we’ve fixed most of these, but we still get complaints about this problem from time to time.

Currently, we solve the problem by simply ordering the dialog front without making it key. This works for most people, but it doesn’t help people who really do need Full Keyboard Access, since you have to click on the dialog box to dismiss it (or make it key) if it isn’t key. We (by which I mean Mac programmers, not just Adium) need a better solution.

I propose an addition to NSAlert. Here’s how it would work:

  1. From the creation of the NSAlert instance, it watches for key events.
  2. When any key goes down, the alert resets the timer (if one is present) and sets a flag.
  3. When all keys are up, the alert creates and starts the timer (with an interval of, say, a couple of seconds).
  4. If you tell the alert to show, it checks the flag. If the flag is clear, it simply performs makeKeyAndOrderFront: like usual. If the flag is set, it only orders front, and it sets a second flag.
  5. When the timer fires, the alert clears the first flag, and if the second flag is set, makes itself key.

From the user’s perspective, this results in the alert waiting a couple of seconds for them to pause in their typing before it takes keyboard focus.

Does anybody know of an existing free implementation of this, or plan to write it themselves?

5 Responses to “A possible solution to the stolen-focus problem”

  1. Sören Kuklau Says:

    The problem with that proposal (no, I don’t know of an existing interpretation, but I imagine it would be a relatively simple category) is that it assumes the user looks at the screen while typing. ‘Proficient typists’ like us indeed tend to do that; the average user, I assure you, does not. I can think of many people who open a browser window and assume (without checking) that they can type in a URL; if a dialog comes up or the location bar isn’t in focus for whatever other reason, they will easily have typed dozens of characters for no reason, only to look up at the screen and cringe (or, worse, wonder WTF just happened and WhereTF their typing went). Waiting for several seconds of no keypresses would help if the user happens to look up, but they might be too preoccupied looking at the keyboard (or elsewhere).

    So, I don’t think a little “get the user’s attention that something else has been happening while he was busy typing ahead” sound beep is avoidable in this case.

  2. Alan Says:

    Surely the point of a dialog popping up is that immediate (ish) attention is required? It may be annoying, for example, to have your dialog box wait for you to stop typing before popping up and telling you that you have been disconnected, for example.

    Perhaps you could solve this (and alleviate Kuklau’s concern about an unavoidable sound beep) by flashing a non-obtrusive yet easy to see icon on screen, telling the user that something is wrong, similar in style to growl? That would allow a user to continue typing if they wish/do not see the problem, and it would notify an alert user that they might want to stop and let the dialog manifest itself.

  3. Alan Says:

    For example.


  4. Anonymous Says:

    Let the window come up, but pass key events down to where they came until an unused keystroke is seen; say Escape, or Ctrl-Enter.

  5. Paul Kim Says:

    I suggested something like this for Sparkle/Sparkle+. Basically, some people were annoyed by an update popping up an alert at an inopportune time. Since, in this case, the alert was not urgent, my suggestion was to check the user’s idle time and only pop it up after some idle time. It was never implemented but the idea is still there.

Leave a Reply

Do not delete the second sentence.