Home | History | Annotate | Download | only in focus
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef UI_VIEWS_FOCUS_FOCUS_MANAGER_H_
      6 #define UI_VIEWS_FOCUS_FOCUS_MANAGER_H_
      7 
      8 #include <list>
      9 #include <map>
     10 
     11 #include "base/basictypes.h"
     12 #include "base/memory/scoped_ptr.h"
     13 #include "base/observer_list.h"
     14 #include "ui/base/accelerators/accelerator.h"
     15 #include "ui/base/accelerators/accelerator_manager.h"
     16 #include "ui/gfx/native_widget_types.h"
     17 #include "ui/views/views_export.h"
     18 
     19 // The FocusManager class is used to handle focus traversal, store/restore
     20 // focused views and handle keyboard accelerators.
     21 //
     22 // There are 2 types of focus:
     23 // - the native focus, which is the focus that an gfx::NativeView has.
     24 // - the view focus, which is the focus that a views::View has.
     25 //
     26 // Each native view must register with their Focus Manager so the focus manager
     27 // gets notified when they are focused (and keeps track of the native focus) and
     28 // as well so that the tab key events can be intercepted.
     29 // They can provide when they register a View that is kept in synch in term of
     30 // focus. This is used in NativeControl for example, where a View wraps an
     31 // actual native window.
     32 // This is already done for you if you subclass the NativeControl class or if
     33 // you use the NativeViewHost class.
     34 //
     35 // When creating a top window (derived from views::Widget) that is not a child
     36 // window, it creates and owns a FocusManager to manage the focus for itself and
     37 // all its child windows.
     38 //
     39 // The FocusTraversable interface exposes the methods a class should implement
     40 // in order to be able to be focus traversed when tab key is pressed.
     41 // RootViews implement FocusTraversable.
     42 // The FocusManager contains a top FocusTraversable instance, which is the top
     43 // RootView.
     44 //
     45 // If you just use views, then the focus traversal is handled for you by the
     46 // RootView. The default traversal order is the order in which the views have
     47 // been added to their container. You can modify this order by using the View
     48 // method SetNextFocusableView().
     49 //
     50 // If you are embedding a native view containing a nested RootView (for example
     51 // by adding a NativeControl that contains a NativeWidgetWin as its native
     52 // component), then you need to:
     53 // - override the View::GetFocusTraversable() method in your outer component.
     54 //   It should return the RootView of the inner component. This is used when
     55 //   the focus traversal traverse down the focus hierarchy to enter the nested
     56 //   RootView. In the example mentioned above, the NativeControl overrides
     57 //   GetFocusTraversable() and returns hwnd_view_container_->GetRootView().
     58 // - call Widget::SetFocusTraversableParent() on the nested RootView and point
     59 //   it to the outer RootView. This is used when the focus goes out of the
     60 //   nested RootView. In the example:
     61 //   hwnd_view_container_->GetWidget()->SetFocusTraversableParent(
     62 //      native_control->GetRootView());
     63 // - call RootView::SetFocusTraversableParentView() on the nested RootView with
     64 //   the parent view that directly contains the native window. This is needed
     65 //   when traversing up from the nested RootView to know which view to start
     66 //   with when going to the next/previous view.
     67 //   In our example:
     68 //   hwnd_view_container_->GetWidget()->SetFocusTraversableParent(
     69 //      native_control);
     70 //
     71 // Note that FocusTraversable do not have to be RootViews: AccessibleToolbarView
     72 // is FocusTraversable.
     73 
     74 namespace ui {
     75 class AcceleratorTarget;
     76 class AcceleratorManager;
     77 class KeyEvent;
     78 }
     79 
     80 namespace views {
     81 
     82 class FocusManagerDelegate;
     83 class FocusSearch;
     84 class RootView;
     85 class View;
     86 class Widget;
     87 
     88 // The FocusTraversable interface is used by components that want to process
     89 // focus traversal events (due to Tab/Shift-Tab key events).
     90 class VIEWS_EXPORT FocusTraversable {
     91  public:
     92   // Return a FocusSearch object that implements the algorithm to find
     93   // the next or previous focusable view.
     94   virtual FocusSearch* GetFocusSearch() = 0;
     95 
     96   // Should return the parent FocusTraversable.
     97   // The top RootView which is the top FocusTraversable returns NULL.
     98   virtual FocusTraversable* GetFocusTraversableParent() = 0;
     99 
    100   // This should return the View this FocusTraversable belongs to.
    101   // It is used when walking up the view hierarchy tree to find which view
    102   // should be used as the starting view for finding the next/previous view.
    103   virtual View* GetFocusTraversableParentView() = 0;
    104 
    105  protected:
    106   virtual ~FocusTraversable() {}
    107 };
    108 
    109 // This interface should be implemented by classes that want to be notified when
    110 // the focus is about to change.  See the Add/RemoveFocusChangeListener methods.
    111 class VIEWS_EXPORT FocusChangeListener {
    112  public:
    113   // No change to focus state has occurred yet when this function is called.
    114   virtual void OnWillChangeFocus(View* focused_before, View* focused_now) = 0;
    115 
    116   // Called after focus state has changed.
    117   virtual void OnDidChangeFocus(View* focused_before, View* focused_now) = 0;
    118 
    119  protected:
    120   virtual ~FocusChangeListener() {}
    121 };
    122 
    123 class VIEWS_EXPORT FocusManager {
    124  public:
    125   // The reason why the focus changed.
    126   enum FocusChangeReason {
    127     // The focus changed because the user traversed focusable views using
    128     // keys like Tab or Shift+Tab.
    129     kReasonFocusTraversal,
    130 
    131     // The focus changed due to restoring the focus.
    132     kReasonFocusRestore,
    133 
    134     // The focus changed due to a click or a shortcut to jump directly to
    135     // a particular view.
    136     kReasonDirectFocusChange
    137   };
    138 
    139   // TODO: use Direction in place of bool reverse throughout.
    140   enum Direction {
    141     kForward,
    142     kBackward
    143   };
    144 
    145   enum FocusCycleWrappingBehavior {
    146     kWrap,
    147     kNoWrap
    148   };
    149 
    150   FocusManager(Widget* widget, FocusManagerDelegate* delegate);
    151   virtual ~FocusManager();
    152 
    153   // Processes the passed key event for accelerators and keyboard traversal.
    154   // Returns false if the event has been consumed and should not be processed
    155   // further.
    156   bool OnKeyEvent(const ui::KeyEvent& event);
    157 
    158   // Returns true is the specified is part of the hierarchy of the window
    159   // associated with this FocusManager.
    160   bool ContainsView(View* view);
    161 
    162   // Advances the focus (backward if reverse is true).
    163   void AdvanceFocus(bool reverse);
    164 
    165   // The FocusManager keeps track of the focused view within a RootView.
    166   View* GetFocusedView() { return focused_view_; }
    167   const View* GetFocusedView() const { return focused_view_; }
    168 
    169   // Low-level methods to force the focus to change (and optionally provide
    170   // a reason). If the focus change should only happen if the view is
    171   // currenty focusable, enabled, and visible, call view->RequestFocus().
    172   void SetFocusedViewWithReason(View* view, FocusChangeReason reason);
    173   void SetFocusedView(View* view) {
    174     SetFocusedViewWithReason(view, kReasonDirectFocusChange);
    175   }
    176 
    177   // Get the reason why the focus most recently changed.
    178   FocusChangeReason focus_change_reason() const {
    179     return focus_change_reason_;
    180   }
    181 
    182   // Clears the focused view. The window associated with the top root view gets
    183   // the native focus (so we still get keyboard events).
    184   void ClearFocus();
    185 
    186   // Validates the focused view, clearing it if the window it belongs too is not
    187   // attached to the window hierarchy anymore.
    188   void ValidateFocusedView();
    189 
    190   // Stores the focused view. Used when the widget loses activation.
    191   // |clear_native_focus| indicates whether this should invoke ClearFocus().
    192   // Typically |true| should be passed in.
    193   void StoreFocusedView(bool clear_native_focus);
    194 
    195   // Restore the view saved with a previous call to StoreFocusedView(). Used
    196   // when the widget becomes active. Returns true when the previous view was
    197   // successfully refocused - otherwise false.
    198   bool RestoreFocusedView();
    199 
    200   // Sets the |view| to be restored when calling RestoreFocusView. This is used
    201   // to set where the focus should go on restoring a Window created without
    202   // focus being set.
    203   void SetStoredFocusView(View* view);
    204 
    205   // Returns the View that either currently has focus, or if no view has focus
    206   // the view that last had focus.
    207   View* GetStoredFocusView();
    208 
    209   // Clears the stored focused view.
    210   void ClearStoredFocusedView();
    211 
    212   // Returns true if in the process of changing the focused view.
    213   bool is_changing_focus() const { return is_changing_focus_; }
    214 
    215   // Disable shortcut handling.
    216   static void set_shortcut_handling_suspended(bool suspended) {
    217     shortcut_handling_suspended_ = suspended;
    218   }
    219   // Returns whether shortcut handling is currently suspended.
    220   bool shortcut_handling_suspended() { return shortcut_handling_suspended_; }
    221 
    222   // Register a keyboard accelerator for the specified target. If multiple
    223   // targets are registered for an accelerator, a target registered later has
    224   // higher priority.
    225   // |accelerator| is the accelerator to register.
    226   // |priority| denotes the priority of the handler.
    227   // NOTE: In almost all cases, you should specify kNormalPriority for this
    228   // parameter. Setting it to kHighPriority prevents Chrome from sending the
    229   // shortcut to the webpage if the renderer has focus, which is not desirable
    230   // except for very isolated cases.
    231   // |target| is the AcceleratorTarget that handles the event once the
    232   // accelerator is pressed.
    233   // Note that we are currently limited to accelerators that are either:
    234   // - a key combination including Ctrl or Alt
    235   // - the escape key
    236   // - the enter key
    237   // - any F key (F1, F2, F3 ...)
    238   // - any browser specific keys (as available on special keyboards)
    239   void RegisterAccelerator(const ui::Accelerator& accelerator,
    240                            ui::AcceleratorManager::HandlerPriority priority,
    241                            ui::AcceleratorTarget* target);
    242 
    243   // Unregister the specified keyboard accelerator for the specified target.
    244   void UnregisterAccelerator(const ui::Accelerator& accelerator,
    245                              ui::AcceleratorTarget* target);
    246 
    247   // Unregister all keyboard accelerator for the specified target.
    248   void UnregisterAccelerators(ui::AcceleratorTarget* target);
    249 
    250   // Activate the target associated with the specified accelerator.
    251   // First, AcceleratorPressed handler of the most recently registered target
    252   // is called, and if that handler processes the event (i.e. returns true),
    253   // this method immediately returns. If not, we do the same thing on the next
    254   // target, and so on.
    255   // Returns true if an accelerator was activated.
    256   bool ProcessAccelerator(const ui::Accelerator& accelerator);
    257 
    258   // Resets menu key state if |event| is not menu key release.
    259   // This is effective only on x11.
    260   void MaybeResetMenuKeyState(const ui::KeyEvent& key);
    261 
    262   // Called by a RootView when a view within its hierarchy is removed
    263   // from its parent. This will only be called by a RootView in a
    264   // hierarchy of Widgets that this FocusManager is attached to the
    265   // parent Widget of.
    266   void ViewRemoved(View* removed);
    267 
    268   // Adds/removes a listener.  The FocusChangeListener is notified every time
    269   // the focused view is about to change.
    270   void AddFocusChangeListener(FocusChangeListener* listener);
    271   void RemoveFocusChangeListener(FocusChangeListener* listener);
    272 
    273   // Returns the AcceleratorTarget that should be activated for the specified
    274   // keyboard accelerator, or NULL if no view is registered for that keyboard
    275   // accelerator.
    276   ui::AcceleratorTarget* GetCurrentTargetForAccelerator(
    277       const ui::Accelerator& accelertor) const;
    278 
    279   // Whether the given |accelerator| has a priority handler associated with it.
    280   bool HasPriorityHandler(const ui::Accelerator& accelerator) const;
    281 
    282   // Clears the native view having the focus.
    283   virtual void ClearNativeFocus();
    284 
    285   // Focuses the next keyboard-accessible pane, taken from the list of
    286   // views returned by WidgetDelegate::GetAccessiblePanes(). If there are
    287   // no panes, the widget's root view is treated as a single pane.
    288   // A keyboard-accessible pane should subclass from AccessiblePaneView in
    289   // order to trap keyboard focus within that pane. If |wrap| is kWrap,
    290   // it keeps cycling within this widget, otherwise it returns false after
    291   // reaching the last pane so that focus can cycle to another widget.
    292   bool RotatePaneFocus(Direction direction, FocusCycleWrappingBehavior wrap);
    293 
    294   // Convenience method that returns true if the passed |key_event| should
    295   // trigger tab traversal (if it is a TAB key press with or without SHIFT
    296   // pressed).
    297   static bool IsTabTraversalKeyEvent(const ui::KeyEvent& key_event);
    298 
    299   // Sets whether arrow key traversal is enabled. When enabled, right/down key
    300   // behaves like tab and left/up key behaves like shift-tab. Note when this
    301   // is enabled, the arrow key movement within grouped views are disabled.
    302   static void set_arrow_key_traversal_enabled(bool enabled) {
    303     arrow_key_traversal_enabled_ = enabled;
    304   }
    305   // Returns whether arrow key traversal is enabled.
    306   static bool arrow_key_traversal_enabled() {
    307     return arrow_key_traversal_enabled_;
    308   }
    309 
    310  private:
    311   // Returns the next focusable view.
    312   View* GetNextFocusableView(View* starting_view, bool reverse, bool dont_loop);
    313 
    314   // Returns the focusable view found in the FocusTraversable specified starting
    315   // at the specified view. This traverses down along the FocusTraversable
    316   // hierarchy.
    317   // Returns NULL if no focusable view were found.
    318   View* FindFocusableView(FocusTraversable* focus_traversable,
    319                           View* starting_view,
    320                           bool reverse);
    321 
    322   // Process arrow key traversal. Returns true if the event has been consumed
    323   // and should not be processed further.
    324   bool ProcessArrowKeyTraversal(const ui::KeyEvent& event);
    325 
    326   // Keeps track of whether shortcut handling is currently suspended.
    327   static bool shortcut_handling_suspended_;
    328 
    329   // Whether arrow key traversal is enabled.
    330   static bool arrow_key_traversal_enabled_;
    331 
    332   // The top-level Widget this FocusManager is associated with.
    333   Widget* widget_;
    334 
    335   // The object which handles an accelerator when |accelerator_manager_| doesn't
    336   // handle it.
    337   scoped_ptr<FocusManagerDelegate> delegate_;
    338 
    339   // The view that currently is focused.
    340   View* focused_view_;
    341 
    342   // The AcceleratorManager this FocusManager is associated with.
    343   scoped_ptr<ui::AcceleratorManager> accelerator_manager_;
    344 
    345   // The storage id used in the ViewStorage to store/restore the view that last
    346   // had focus.
    347   int stored_focused_view_storage_id_;
    348 
    349   // The reason why the focus most recently changed.
    350   FocusChangeReason focus_change_reason_;
    351 
    352   // The list of registered FocusChange listeners.
    353   ObserverList<FocusChangeListener, true> focus_change_listeners_;
    354 
    355   // See description above getter.
    356   bool is_changing_focus_;
    357 
    358   DISALLOW_COPY_AND_ASSIGN(FocusManager);
    359 };
    360 
    361 }  // namespace views
    362 
    363 #endif  // UI_VIEWS_FOCUS_FOCUS_MANAGER_H_
    364