|OK, I have tried to reconcile everyone's points to create a revised set of rules (apols if I've missed some subtleties).|
There are two basic ways of resolving the differences between the OS implementation of focus and our streamlined version:
1. We can move OS focus to refer to the window where keypresses will be first used
2. We can leave focus where the OS puts it and shuffle keypress events around internally from there.
I think it's clear that the first approach is best - the OS will then be in sync with the app and focus indication as shown by title bars will be more correct. The rules are defined on that basis.
"Window" is any gui element derived from a window; typically a control but could be a dialog or anything.
"Focus" means the focus window pointer maintained by the OS/wxWidgets. That window is said to "own" the focus and is given first refusal of any keypress events generated.
The "Active View" is the Camelot document view window in which the user has selected nodes and in which selection blobs are being shown OR the Camelot document view window that last had input focus.
"Modeless" == "Non-modal"
To "Claim" an event means to prevent it being sent on to other windows in the command chain.
Focus Handling Rules Revision 1:
1. A modal dialog owning or containing focus obviously consumes all keypresses. The window owning the focus gets the first chance to use the keypress, then parent windows recursively until the modal dialog itself. (This should be the natural behaviour assuming the modal dialog is a "Top Level Window".)
2. The active view can usually make better use of keypresses than any modeless window and so a modeless window should claim the minimal number of keypresses possible.
3. A modeless window owning the focus should only use keypresses if its ownership of the focus is more prominently shown to the user than the selection in the active view. (E.g. flashing caret, boldly shown selected item or popped-up selector window)
4. A modeless window owning the focus should claim only the keypresses the user expects to work in it, even if some of those keypresses are ignored. For instance, a text edit control may claim all alphanumeric chars even though it only uses digits. All unclaimed keypresses should be passed on through a chain in this order: window, window parents (recursively), active view, active document, application. A modeless dialog which owns or contains focus should not use Escape to close itself or Return to commit uncommited values (see notes below).
5. A modeless window should release focus when it has done its immediate job - it must not hold focus assuming the user will want it in that window again. This includes the focus given to a modeless top level window (e.g. colour editor) when it is dragged by its title bar - if it's not going to use that focus it should hand it back to the previous owner so that focus indication correctly shows where focus really is. The meaning of "immediate job" is defined by the window but a typical example is when the user presses Return after entering text into an edit control.
6. The user must be warned about any destructive operation caused by a keypress in a modeless window (unless the data concerned is owned by the window itself).
7. A window only gets focus as the result of deliberate action by the user such as clicking or pressing tab. The application should never move focus into a modeless window by itself.
8. A window should not take focus if it has no use for keypresses. Further, a control in a modeless window should only take focus if keypresses are essential to its operation.
9. A window should indicate whether it owns or contains input focus (or not) in the standard way for the native OS. This is usually indicated using the title bar or tab control. A window which can show selected items when it does not have focus and which uses keypresses to act on those items when it does have focus must render the selected items more boldly when it has focus than when it hasn't. This helps the user see that his keypresses will do something different when the window has focus.
10. Mouse wheel events have nothing to do with focus or active windows - they are sent to whatever control the mouse is over. Important: Neither the OS, nor the application or any layer in between must be allowed to set focus because of wheel events or because the mouse has been idle over the window for any period!
* All modeless dialogs should be dockable.
* All modeless dialogs should ideally immediately affect the active drawing (e.g. the colour editor) or have Apply and Close buttons. It is not correct for modeless dialogs to have OK and Cancel buttons.
* I'm assuming that there is a mechanism (OnSetFocus event?) which allows a window to accept or reject focus.
I am mindful of getting all this stuff working in a platform neutral way. As Alex points out it may be difficult to prevent the OS giving focus to a window when it is clicked on and I don't think we should try to fight that because it will lead to unreliable code and difficulty in porting. Instead, we should rely on the focus handling rules set out below sending keypresses to the appropriate location.
IMPORTANT: If you have comments, please make sure they include a suggested revision to the rules to help us "focus" on resolving this stuff.