Re: focus


Subject: Re: focus
From: Paul Rohr (paul@abisource.com)
Date: Fri Mar 24 2000 - 16:41:55 CST


Aaron,

I agree with your general assessment. Currently, the AbiWord UI
more-or-less behaves as if there were four targets for focus in the world:

  A. someplace other than AbiWord
  B. dialogs
  C. specific toolbar controls
  D. the "rest" of AbiWord (views and commands)

Like you, I currently don't really care whether other parts of the AbiWord
interface are allowed to gain focus, too. Once we get the current model
working consistently, it should be clear how to add more instances of case
C -- or even some hypothetical case E inside AbiWord -- on an as-needed
basis.

For example, some platforms' menu widgets temporarily take focus to allow
keyboard navigation via the arrow keys, which would introduce a new focus
category:

  M. the menu widgets for a frame

You're pointing to a place in our GTK implementation where the difference
between B and C gets fuzzy, and thus some keyboard events which should go to
C don't. This sounds like an easily-localized bug which should definitely
be fixed. AFAIK, there are no reported problems on other platforms with
keystrokes getting misrouted.

I was referring to a more general issue -- we also get sloppy about visual
indications for focus in other places:

  - Essentially, all AbiWord views always draw as if they had focus (D).
  - However, if focus is somewhere else (A-C) they shouldn't.
  - Also, even in case D only one view really has focus. The rest don't.

In short, say we have the following configuration of windows which could
potentially take focus:

  - a few non-AbiWord windows (A*)
  - one AbiWord frame (1C*, 1D, 1M)
  - a second AbiWord frame (2C*, 2D, 2M)
  - another AbiWord frame with a modal dialog raised (3B, 3C*, 3D, 3M)

In this example, at most one of the three AbiWord frames (either 1D or 2D)
should be drawing focus-driven indicators at any given time, but only if
that frame has focus. Any time the focus is elsewhere (A*, B, C*), then
none of the frames should be blinking cursors, etc.

An obvious exception to this rule is 3D while 3B has the focus. In certain
cases, dialogs like find or spell work better if the underlying view does
still show the active selection or insertion point. However, even in this
case, the cursor shouldn't blink.

the bug
-------
We currently draw selections and blink cursors in 1D, 2D, and 3D no matter
*where* the focus really is, which is very confusing and most definitely
does not Just Work.

In addition, it's a source of cursor dirt when restacking windows. (On
Windows, I've even seen dirt due to menu drop-downs because of this.)

a modest proposal
-----------------
Here's how I think our focus behavior should look. Each view has one of
four appearances:

  selected
  blinking cursor
  non-blinking cursor
  nothing
  
To figure out which appearance should be used for the current view, we'll
need to pay attention to where the focus is relative to the window hierarchy
for that view.

*. Selections shouldn't be drawn unless there is one (the current
behavior). In addition, they shouldn't be drawn unless the toplevel window
for the window which currently has focus is this view's frame.

In other words, the view(s) for 3D draw existing selections iff focus is
somewhere in that frame's window hierarchy (3B, 3C*, 3D, 3M). Any time
focus moves anywhere else the selection isn't drawn at all.

**. Likewise, cursors shouldn't be drawn at all if there's a selection (the
current behavior). In addition, the cursor shouldn't be drawn if focus is
outside that frame's window hierarchy.

In other words, the view(s) for 3D draw a cursor iff focus is somewhere in
that frame (3B, 3C*, 3D, 3M). Any time focus moves anywhere else the cursor
isn't drawn at all.

***. Finally, cursors shouldn't blink unless the relevant prefs item allows
it (the current behavior). In addition, they shouldn't blink unless that
frame itself has the focus.

In other words, the views for 3D don't blink unless 3D has the focus.

bottom line
-----------
Do we have consensus that this is the desired behavior on all platforms?

If so, it should be fairly simple to come up with an XP mechanism to express
which of the three equivalence classes of focus states we're currently in:

  FV_FOCUS_HERE /* in this frame */
  FV_FOCUS_NEARBY /* on another window in this frame */
  FV_FOCUS_NONE /* not this frame, somewhere else */

Then the job of each platform-specific implementation will be to detect any
changes to this state and notify the view accordingly, so it can update the
view accordingly. For example, any time a frame's widgets really took or
lost focus, they'd notify the frame accordingly:

  pFrame->focusChanged(FV_FOCUS_NEARBY);

In turn, the frame could filter redundant changes and just pass the
interesting ones along to its views:

  pView->focusChanged(FV_FOCUS_NEARBY);

I'm assuming that the XP implementation in FV_View for each of these
equivalence classes is obvious, given the descriptions above.

  FV_FOCUS_HERE -- draw selection or blinking cursor (if prefs allow)
  FV_FOCUS_NEARBY -- draw selection or unblinking cursor
  FV_FOCUS_NONE -- don't draw either

Does that make sense?

Paul



This archive was generated by hypermail 2b25 : Fri Mar 24 2000 - 16:36:23 CST