summaryrefslogtreecommitdiffstats
path: root/views/focus/focus_manager.h
diff options
context:
space:
mode:
authorben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-08 00:34:05 +0000
committerben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-08 00:34:05 +0000
commit2362e4fe2905ab75d3230ebc3e307ae53e2b8362 (patch)
treee6d88357a2021811e0e354f618247217be8bb3da /views/focus/focus_manager.h
parentdb23ac3e713dc17509b2b15d3ee634968da45715 (diff)
downloadchromium_src-2362e4fe2905ab75d3230ebc3e307ae53e2b8362.zip
chromium_src-2362e4fe2905ab75d3230ebc3e307ae53e2b8362.tar.gz
chromium_src-2362e4fe2905ab75d3230ebc3e307ae53e2b8362.tar.bz2
Move src/chrome/views to src/views. RS=darin http://crbug.com/11387
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@15604 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'views/focus/focus_manager.h')
-rw-r--r--views/focus/focus_manager.h343
1 files changed, 343 insertions, 0 deletions
diff --git a/views/focus/focus_manager.h b/views/focus/focus_manager.h
new file mode 100644
index 0000000..8c33036
--- /dev/null
+++ b/views/focus/focus_manager.h
@@ -0,0 +1,343 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef VIEWS_FOCUS_FOCUS_MANAGER_H_
+#define VIEWS_FOCUS_FOCUS_MANAGER_H_
+
+#include "base/basictypes.h"
+
+#if defined(OS_WIN)
+#include <windows.h>
+#endif
+#include <vector>
+#include <map>
+
+#include "views/accelerator.h"
+
+// The FocusManager class is used to handle focus traversal, store/restore
+// focused views and handle keyboard accelerators.
+//
+// There are 2 types of focus:
+// - the native focus, which is the focus that an HWND has.
+// - the view focus, which is the focus that a views::View has.
+//
+// Each native view must register with their Focus Manager so the focus manager
+// gets notified when they are focused (and keeps track of the native focus) and
+// as well so that the tab key events can be intercepted.
+// They can provide when they register a View that is kept in synch in term of
+// focus. This is used in NativeControl for example, where a View wraps an
+// actual native window.
+// This is already done for you if you subclass the NativeControl class or if
+// you use the HWNDView class.
+//
+// When creating a top window, if it derives from WidgetWin, the
+// |has_own_focus_manager| of the Init method lets you specify whether that
+// window should have its own focus manager (so focus traversal stays confined
+// in that window). If you are not deriving from WidgetWin or one of its
+// derived classes (Window, FramelessWindow, ConstrainedWindow), you must
+// create a FocusManager when the window is created (it is automatically deleted
+// when the window is destroyed).
+//
+// The FocusTraversable interface exposes the methods a class should implement
+// in order to be able to be focus traversed when tab key is pressed.
+// RootViews implement FocusTraversable.
+// The FocusManager contains a top FocusTraversable instance, which is the top
+// RootView.
+//
+// If you just use views, then the focus traversal is handled for you by the
+// RootView. The default traversal order is the order in which the views have
+// been added to their container. You can modify this order by using the View
+// method SetNextFocusableView().
+//
+// If you are embedding a native view containing a nested RootView (for example
+// by adding a NativeControl that contains a WidgetWin as its native
+// component), then you need to:
+// - override the View::GetFocusTraversable() method in your outter component.
+// It should return the RootView of the inner component. This is used when
+// the focus traversal traverse down the focus hierarchy to enter the nested
+// RootView. In the example mentioned above, the NativeControl overrides
+// GetFocusTraversable() and returns hwnd_view_container_->GetRootView().
+// - call RootView::SetFocusTraversableParent() on the nested RootView and point
+// it to the outter RootView. This is used when the focus goes out of the
+// nested RootView. In the example:
+// hwnd_view_container_->GetRootView()->SetFocusTraversableParent(
+// native_control->GetRootView());
+// - call RootView::SetFocusTraversableParentView() on the nested RootView with
+// the parent view that directly contains the native window. This is needed
+// when traversing up from the nested RootView to know which view to start
+// with when going to the next/previous view.
+// In our example:
+// hwnd_view_container_->GetRootView()->SetFocusTraversableParent(
+// native_control);
+//
+// Note that FocusTraversable do not have to be RootViews: TabContents is
+// FocusTraversable.
+
+namespace views {
+
+class View;
+class RootView;
+
+// The FocusTraversable interface is used by components that want to process
+// focus traversal events (due to Tab/Shift-Tab key events).
+class FocusTraversable {
+ public:
+ // The direction in which the focus traversal is going.
+ // TODO (jcampan): add support for lateral (left, right) focus traversal. The
+ // goal is to switch to focusable views on the same level when using the arrow
+ // keys (ala Windows: in a dialog box, arrow keys typically move between the
+ // dialog OK, Cancel buttons).
+ enum Direction {
+ UP = 0,
+ DOWN
+ };
+
+ // Should find the next view that should be focused and return it. If a
+ // FocusTraversable is found while searching for the focusable view, NULL
+ // should be returned, focus_traversable should be set to the FocusTraversable
+ // and focus_traversable_view should be set to the view associated with the
+ // FocusTraversable.
+ // This call should return NULL if the end of the focus loop is reached.
+ // - |starting_view| is the view that should be used as the starting point
+ // when looking for the previous/next view. It may be NULL (in which case
+ // the first/last view should be used depending if normal/reverse).
+ // - |reverse| whether we should find the next (reverse is false) or the
+ // previous (reverse is true) view.
+ // - |direction| specifies whether we are traversing down (meaning we should
+ // look into child views) or traversing up (don't look at child views).
+ // - |dont_loop| if true specifies that if there is a loop in the focus
+ // hierarchy, we should keep traversing after the last view of the loop.
+ // - |focus_traversable| is set to the focus traversable that should be
+ // traversed if one is found (in which case the call returns NULL).
+ // - |focus_traversable_view| is set to the view associated with the
+ // FocusTraversable set in the previous parameter (it is used as the
+ // starting view when looking for the next focusable view).
+
+ virtual View* FindNextFocusableView(View* starting_view,
+ bool reverse,
+ Direction direction,
+ bool dont_loop,
+ FocusTraversable** focus_traversable,
+ View** focus_traversable_view) = 0;
+
+ // Should return the parent FocusTraversable.
+ // The top RootView which is the top FocusTraversable returns NULL.
+ virtual FocusTraversable* GetFocusTraversableParent() = 0;
+
+ // This should return the View this FocusTraversable belongs to.
+ // It is used when walking up the view hierarchy tree to find which view
+ // should be used as the starting view for finding the next/previous view.
+ virtual View* GetFocusTraversableParentView() = 0;
+};
+
+// The KeystrokeListener interface is used by components (such as the
+// ExternalTabContainer class) which need a crack at handling all
+// keystrokes.
+class KeystrokeListener {
+ public:
+ // If this returns true, then the component handled the keystroke and ate
+ // it.
+#if defined(OS_WIN)
+ virtual bool ProcessKeyStroke(HWND window, UINT message, WPARAM wparam,
+ LPARAM lparam) = 0;
+#endif
+};
+
+// This interface should be implemented by classes that want to be notified when
+// the focus is about to change. See the Add/RemoveFocusChangeListener methods.
+class FocusChangeListener {
+ public:
+ virtual void FocusWillChange(View* focused_before, View* focused_now) = 0;
+};
+
+class FocusManager {
+ public:
+#if defined(OS_WIN)
+ // Creates a FocusManager for the specified window. Top level windows
+ // must invoked this when created.
+ // The RootView specified should be the top RootView of the window.
+ // This also invokes InstallFocusSubclass.
+ static FocusManager* CreateFocusManager(HWND window, RootView* root_view);
+
+ // Subclasses the specified window. The subclassed window procedure listens
+ // for WM_SETFOCUS notification and keeps the FocusManager's focus owner
+ // property in sync.
+ // It's not necessary to explicitly invoke Uninstall, it's automatically done
+ // when the window is destroyed and Uninstall wasn't invoked.
+ static void InstallFocusSubclass(HWND window, View* view);
+
+ // Uninstalls the window subclass installed by InstallFocusSubclass.
+ static void UninstallFocusSubclass(HWND window);
+
+ static FocusManager* GetFocusManager(HWND window);
+
+ // Message handlers (for messages received from registered windows).
+ // Should return true if the message should be forwarded to the window
+ // original proc function, false otherwise.
+ bool OnSetFocus(HWND window);
+ bool OnNCDestroy(HWND window);
+ // OnKeyDown covers WM_KEYDOWN and WM_SYSKEYDOWN.
+ bool OnKeyDown(HWND window,
+ UINT message,
+ WPARAM wparam,
+ LPARAM lparam);
+ bool OnKeyUp(HWND window,
+ UINT message,
+ WPARAM wparam,
+ LPARAM lparam);
+ // OnPostActivate is called after WM_ACTIVATE has been propagated to the
+ // DefWindowProc.
+ bool OnPostActivate(HWND window, int activation_state, int minimized_state);
+#endif
+
+ // Returns true is the specified is part of the hierarchy of the window
+ // associated with this FocusManager.
+ bool ContainsView(View* view);
+
+ // Advances the focus (backward if reverse is true).
+ void AdvanceFocus(bool reverse);
+
+ // The FocusManager is handling the selected view for the RootView.
+ View* GetFocusedView() const { return focused_view_; }
+ void SetFocusedView(View* view);
+
+ // Clears the focused view. The window associated with the top root view gets
+ // the native focus (so we still get keyboard events).
+ void ClearFocus();
+
+ // Clears the HWND that has the focus by focusing the HWND from the top
+ // RootView (so we still get keyboard events).
+ // Note that this does not change the currently focused view.
+ void ClearHWNDFocus();
+
+#if defined(OS_WIN)
+ // Focus the specified |hwnd| without changing the focused view.
+ void FocusHWND(HWND hwnd);
+#endif
+
+ // Validates the focused view, clearing it if the window it belongs too is not
+ // attached to the window hierarchy anymore.
+ void ValidateFocusedView();
+
+#if defined(OS_WIN)
+ // Returns the view associated with the specified window if any.
+ // If |look_in_parents| is true, it goes up the window parents until it find
+ // a view.
+ static View* GetViewForWindow(HWND window, bool look_in_parents);
+#endif
+
+ // Stores and restores the focused view. Used when the window becomes
+ // active/inactive.
+ void StoreFocusedView();
+ void RestoreFocusedView();
+
+ // Clears the stored focused view.
+ void ClearStoredFocusedView();
+
+ // Returns the FocusManager of the parent window of the window that is the
+ // root of this FocusManager. This is useful with ConstrainedWindows that have
+ // their own FocusManager and need to return focus to the browser when closed.
+ FocusManager* GetParentFocusManager() const;
+
+ // Register a keyboard accelerator for the specified target. If an
+ // AcceleratorTarget is already registered for that accelerator, it is
+ // returned.
+ // Note that we are currently limited to accelerators that are either:
+ // - a key combination including Ctrl or Alt
+ // - the escape key
+ // - the enter key
+ // - any F key (F1, F2, F3 ...)
+ // - any browser specific keys (as available on special keyboards)
+ AcceleratorTarget* RegisterAccelerator(const Accelerator& accelerator,
+ AcceleratorTarget* target);
+
+ // Unregister the specified keyboard accelerator for the specified target.
+ void UnregisterAccelerator(const Accelerator& accelerator,
+ AcceleratorTarget* target);
+
+ // Unregister all keyboard accelerator for the specified target.
+ void UnregisterAccelerators(AcceleratorTarget* target);
+
+ // Activate the target associated with the specified accelerator if any.
+ // Returns true if an accelerator was activated.
+ bool ProcessAccelerator(const Accelerator& accelerator);
+
+ // Called by a RootView when a view within its hierarchy is removed from its
+ // parent. This will only be called by a RootView in a hierarchy of Widgets
+ // that this FocusManager is attached to the parent Widget of.
+ void ViewRemoved(View* parent, View* removed);
+
+ void AddKeystrokeListener(KeystrokeListener* listener);
+ void RemoveKeystrokeListener(KeystrokeListener* listener);
+
+ // Adds/removes a listener. The FocusChangeListener is notified every time
+ // the focused view is about to change.
+ void AddFocusChangeListener(FocusChangeListener* listener);
+ void RemoveFocusChangeListener(FocusChangeListener* listener);
+
+ // Returns the AcceleratorTarget that should be activated for the specified
+ // keyboard accelerator, or NULL if no view is registered for that keyboard
+ // accelerator.
+ // TODO(finnur): http://b/1307173 Make this private once the bug is fixed.
+ AcceleratorTarget* GetTargetForAccelerator(
+ const Accelerator& accelerator) const;
+
+ private:
+#if defined(OS_WIN)
+ explicit FocusManager(HWND root, RootView* root_view);
+#endif
+ ~FocusManager();
+
+ // Returns the next focusable view.
+ View* GetNextFocusableView(View* starting_view, bool reverse, bool dont_loop);
+
+ // Returns the last view of the focus traversal hierarchy.
+ View* FindLastFocusableView();
+
+ // Returns the focusable view found in the FocusTraversable specified starting
+ // at the specified view. This traverses down along the FocusTraversable
+ // hierarchy.
+ // Returns NULL if no focusable view were found.
+ View* FindFocusableView(FocusTraversable* focus_traversable,
+ View* starting_view,
+ bool reverse,
+ bool dont_loop);
+
+ // The RootView of the window associated with this FocusManager.
+ RootView* top_root_view_;
+
+ // The view that currently is focused.
+ View* focused_view_;
+
+ // The storage id used in the ViewStorage to store/restore the view that last
+ // had focus.
+ int stored_focused_view_storage_id_;
+
+#if defined(OS_WIN)
+ // The window associated with this focus manager.
+ HWND root_;
+#endif
+
+ // Used to allow setting the focus on an HWND without changing the currently
+ // focused view.
+ bool ignore_set_focus_msg_;
+
+ // The accelerators and associated targets.
+ typedef std::map<Accelerator, AcceleratorTarget*> AcceleratorMap;
+ AcceleratorMap accelerators_;
+
+ // The list of registered keystroke listeners
+ typedef std::vector<KeystrokeListener*> KeystrokeListenerList;
+ KeystrokeListenerList keystroke_listeners_;
+
+ // The list of registered FocusChange listeners.
+ typedef std::vector<FocusChangeListener*> FocusChangeListenerList;
+ FocusChangeListenerList focus_change_listeners_;
+
+ DISALLOW_COPY_AND_ASSIGN(FocusManager);
+};
+
+} // namespace views
+
+#endif // VIEWS_FOCUS_FOCUS_MANAGER_H_