To make choice of focus window consistent for each focus method, a
number of guidelines should be followed.  The basics are easy:

Focus method  Behavior
    click     When a user clicks on a window, focus it
   sloppy     When an EnterNotify is received, focus the window
    mouse     Same as sloppy, but also defocus on LeaveNotify

However, there are a number of cases where the current focus window
becomes invalid and another should be chosen.  Some examples are when
a focused window is closed or minimized, or when the user changes
workspaces.  In these cases, there needs to be a rule consistent with
the above about the new window to choose.

Focus method  Behavior
    click     Focus the most recently used window (same as toplevel
              window)
   sloppy     Focus the window containing the pointer if there is such
              a window, otherwise focus the most recently used window.
    mouse     Focus the window containing the pointer if there is one,
              otherwise focus the designated "no_focus_window".

Also, sometimes a new window will be mapped (e.g. unminimizing a
window or launching a new application).  Most users want to interact
with new windows right away, so these should typically be focused.
This does potentially conflict with the "focused window==mouse window"
behavior found in sloppy and mouse focus modes, so this wouldn't be
true for a strict-pointer-focus mode.  For all other modes
(non-strict-pointer-focus modes), there are only two cases in which a
new window shouldn't be focused:

  1) If the window takes a while to launch and the user starts
     interacting with a different application, the new window should
     not take focus.
  2) If the window that will appear was not launched by the user
     (error dialogs, Instant Messaging windows, etc.), then the window
     should not take focus when it appears.

To handle these cases, Metacity compares timestamps of the event that
caused the launch and the timestamp of the last interaction with the
focused window.  (Case 2 is handled by providing a special timestamp
of 0 for the launch time, which ensures that the window that appears
doesn't get focus)

If the newly launched window isn't focused, some things should be done
to alert the user that there is a window to work with:
  1) The _NET_WM_DEMANDS_ATTENTION hint should be set
  2) If the new window isn't modal for the focused window, it should
     appear below the focused window so that it doesn't obscure the
     focused window that the user is interacting with.
  3) If the new window is modal to the focused window, the currently
     focused window should lose focus but the modal window should
     appear on top.

Finally, the user may decide to use the keyboard instead of the mouse
to navigate between windows (referred to as "keynav").  This poses no
problems for click-to-focus, but for sloppy and mouse focus it means
that EnterNotify and LeaveNotify events should be ignored (they can be
generated without using the mouse, for example, by grabs).





To read more about the bugs that inspired these choices:
  - When a focused window becomes invalid and another should be chosen
    http://bugzilla.gnome.org/show_bug.cgi?id=135810
  - When a new window is mapped
    http://bugzilla.gnome.org/show_bug.cgi?id=118372
  - Modal vs. non-modal dialogs that get denied focus when mapped
    http://bugzilla.gnome.org/show_bug.cgi?id=151996
  - Ignoring EnterNotify and LeaveNotify events during keynav
    http://bugzilla.gnome.org/show_bug.cgi?id=101190

There were many bugs which had to be fixed to get all the above
working; they helped form these policies and/or show the difficulties
in implementing this policy (my apologies in advance for producing a
list heavily lopsided to what I've done; it's just that these bugs are
the ones I'm the most familiar with):
  bug  72314  ignore LeaveNotify events from grabs
  bug  82921  focus windows on map
  bug  87531  only show focus for sticky windows on active workspace (pager)
  bug  95747  should ignore EnterNotify events with NotifyInferior detail set
  bug  97635  sticky windows always keep focus when switching workspaces
  bug 102665  a window unminimized from the tasklist should be focused
  bug 108643  focus in MRU order instead of stack order
  bug 110970  moving a window to another workspace loses focus
  bug 112031  closing a dialog can result in a strange focus window
  bug 115650  add _NET_WM_USER_TIME support to gtk+ (see also 150502)
  bug 120100  panel shouldn't be focused after workspace applet usage
  bug 123803  need final EnterNotify after workspace switch (see also 124798)
  bug 124981  focus clicked window in pager only if on current workspace
  bug 128200  focus correct window on libwnck window minimize (see 107681 too)
  bug 131582  fix race condition on window minimize/close
  bug 133120  wrong window focused when changing workspaces
  bug 135024  _NET_ACTIVE_WINDOW messages need timestamps
  bug 135786  middle-clicking on focused window to lower it should defocus too
  bug 136581  window minimization vs. activation for mouse focus
  bug 144900  fix focus choice on "un-showing" the desktop
  bug 147475  don't lock keyboard on workspace change
  bug 148364  DEMANDS_ATTENTION support for metacity & libwnck (and other stuff)
  bug 149028  focus-stealing-prevention for metacity-dialog (and other stuff)
  bug 149366  windows denied focus on map occur in wrong order in alt-tab list
  bug 149543  consistent focus window when unshowing desktop
  bug 149589  race in focus choice from libwnck messages
  bug 150271  make sure "run application" dialog gets focused
  bug 150668  update gtk+ _NET_ACTIVE_WINDOW support
  bug 151245  application startup notification forwarding (partially rejected)
  bug 151984  Soeren's idea--backup timestamp when startup notification not used
  bug 151990  prevent focus inconsistencies by only providing one focus method
  bug 151996  modal dialogs denied focus should not be lowered
  bug 152000  fix race on window close followed by rapid mouse movement
