diff options
author | tfarina@chromium.org <tfarina@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-26 20:52:36 +0000 |
---|---|---|
committer | tfarina@chromium.org <tfarina@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-26 20:52:36 +0000 |
commit | aca5148cbb5c19f23c20e8421ce4e74d3bbd7a05 (patch) | |
tree | 6b6dfa178f15c227bfe6cc2afb61e033d4b1c414 /ui/views/focus | |
parent | d1735a7513c5516d2a14eaa8355100e4d7a90cef (diff) | |
download | chromium_src-aca5148cbb5c19f23c20e8421ce4e74d3bbd7a05.zip chromium_src-aca5148cbb5c19f23c20e8421ce4e74d3bbd7a05.tar.gz chromium_src-aca5148cbb5c19f23c20e8421ce4e74d3bbd7a05.tar.bz2 |
Remove src/ui/views.
BUG=101590
R=pkasting@chromium.org
Review URL: http://codereview.chromium.org/8395036
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@107428 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/views/focus')
-rw-r--r-- | ui/views/focus/accelerator_handler.h | 68 | ||||
-rw-r--r-- | ui/views/focus/accelerator_handler_win.cc | 59 | ||||
-rw-r--r-- | ui/views/focus/focus_manager.cc | 461 | ||||
-rw-r--r-- | ui/views/focus/focus_manager.h | 303 | ||||
-rw-r--r-- | ui/views/focus/focus_search.cc | 273 | ||||
-rw-r--r-- | ui/views/focus/focus_search.h | 122 |
6 files changed, 0 insertions, 1286 deletions
diff --git a/ui/views/focus/accelerator_handler.h b/ui/views/focus/accelerator_handler.h deleted file mode 100644 index 3d0c5e0..0000000 --- a/ui/views/focus/accelerator_handler.h +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) 2011 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 UI_VIEWS_FOCUS_ACCELERATOR_HANDLER_H_ -#define UI_VIEWS_FOCUS_ACCELERATOR_HANDLER_H_ -#pragma once - -#include "build/build_config.h" - -#if defined(TOOLKIT_USES_GTK) -#include <gdk/gdk.h> -#endif - -#include <set> -#include <vector> - -#include "base/message_loop.h" - -namespace ui { - -#if defined(TOUCH_UI) -// Dispatch an XEvent to the RootView. Return true if the event was dispatched -// and handled, false otherwise. -bool DispatchXEvent(XEvent* xevent); - -// Keep a list of touch devices so that it is possible to determine if a pointer -// event is a touch-event or a mouse-event. -void SetTouchDeviceList(std::vector<unsigned int>& devices); -#endif // TOUCH_UI - -//////////////////////////////////////////////////////////////////////////////// -// AcceleratorHandler class -// -// An object that pre-screens all UI messages for potential accelerators. -// Registered accelerators are processed regardless of focus within a given -// Widget or Window. -// -// This processing is done at the Dispatcher level rather than on the Widget -// because of the global nature of this processing, and the fact that not all -// controls within a window need to be Widgets - some are native controls from -// the underlying toolkit wrapped by NativeViewHost. -// -class AcceleratorHandler : public MessageLoopForUI::Dispatcher { - public: - AcceleratorHandler(); - // Dispatcher method. This returns true if an accelerator was processed by the - // focus manager -#if defined(OS_WIN) - virtual bool Dispatch(const MSG& msg); -#elif defined(TOUCH_UI) - virtual MesasgePumpDispatcher::DispatchStatus Dispatch(XEvent* xev); -#else - virtual bool Dispatch(GdkEvent* event); -#endif - - private: -#if defined(OS_WIN) - // The keys currently pressed and consumed by the FocusManager. - std::set<WPARAM> pressed_keys_; -#endif - - DISALLOW_COPY_AND_ASSIGN(AcceleratorHandler); -}; - -} // namespace ui - -#endif // UI_VIEWS_FOCUS_ACCELERATOR_HANDLER_H_ diff --git a/ui/views/focus/accelerator_handler_win.cc b/ui/views/focus/accelerator_handler_win.cc deleted file mode 100644 index ab059ec..0000000 --- a/ui/views/focus/accelerator_handler_win.cc +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) 2011 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. - -#include "ui/views/focus/accelerator_handler.h" - -#include "ui/base/keycodes/keyboard_codes.h" -#include "ui/base/keycodes/keyboard_code_conversion_win.h" -#include "ui/views/events/event.h" -#include "ui/views/focus/focus_manager.h" -#include "ui/views/widget/widget.h" - -namespace ui { - -AcceleratorHandler::AcceleratorHandler() { -} - -bool AcceleratorHandler::Dispatch(const MSG& msg) { - bool process_message = true; - - if (msg.message >= WM_KEYFIRST && msg.message <= WM_KEYLAST) { - Widget* widget = Widget::GetTopLevelWidgetForNativeView(msg.hwnd); - FocusManager* focus_manager = widget ? widget->GetFocusManager() : NULL; - if (focus_manager) { - switch (msg.message) { - case WM_KEYDOWN: - case WM_SYSKEYDOWN: { - process_message = focus_manager->OnKeyEvent(KeyEvent(msg)); - if (!process_message) { - // Record that this key is pressed so we can remember not to - // translate and dispatch the associated WM_KEYUP. - pressed_keys_.insert(msg.wParam); - } - break; - } - case WM_KEYUP: - case WM_SYSKEYUP: { - std::set<WPARAM>::iterator iter = pressed_keys_.find(msg.wParam); - if (iter != pressed_keys_.end()) { - // Don't translate/dispatch the KEYUP since we have eaten the - // associated KEYDOWN. - pressed_keys_.erase(iter); - return true; - } - break; - } - } - } - } - - if (process_message) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - - return true; -} - -} // namespace ui diff --git a/ui/views/focus/focus_manager.cc b/ui/views/focus/focus_manager.cc deleted file mode 100644 index efe65b1..0000000 --- a/ui/views/focus/focus_manager.cc +++ /dev/null @@ -1,461 +0,0 @@ -// Copyright (c) 2011 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. - -#include "ui/views/focus/focus_manager.h" - -#include <algorithm> - -#include "build/build_config.h" - -#if defined(TOOLKIT_USES_GTK) -#include <gtk/gtk.h> -#endif - -#include "base/logging.h" -#include "ui/base/keycodes/keyboard_codes.h" -#include "ui/views/events/event.h" -#include "ui/views/focus/focus_search.h" -#include "ui/views/view.h" -#include "ui/views/widget/root_view.h" -#include "ui/views/widget/native_widget.h" -#include "ui/views/widget/widget.h" - -namespace ui { - -namespace { - -FocusEvent::TraversalDirection DirectionFromBool(bool forward) { - return forward ? FocusEvent::DIRECTION_FORWARD - : FocusEvent::DIRECTION_REVERSE; -} - -FocusEvent::TraversalDirection DirectionFromKeyEvent(const KeyEvent& event) { - return DirectionFromBool(!event.IsShiftDown()); -} - -bool IsTraverseForward(FocusEvent::TraversalDirection direction) { - return direction == FocusEvent::DIRECTION_FORWARD; -} - -#if defined(OS_WIN) -// Don't allow focus traversal if the root window is not part of the active -// window hierarchy as this would mean we have no focused view and would focus -// the first focusable view. -bool CanTraverseFocus(Widget* widget) { - HWND top_window = widget->native_widget()->GetNativeView(); - HWND active_window = ::GetActiveWindow(); - return active_window == top_window || ::IsChild(active_window, top_window); -} -#else -bool CanTraverseFocus(Widget* widget) { - return true; -} -#endif - -} - -// FocusManager::WidgetFocusManager --------------------------------- - -void FocusManager::WidgetFocusManager::AddFocusChangeListener( - WidgetFocusChangeListener* listener) { - DCHECK(std::find(focus_change_listeners_.begin(), - focus_change_listeners_.end(), listener) == - focus_change_listeners_.end()) << - "Adding a WidgetFocusChangeListener twice."; - focus_change_listeners_.push_back(listener); -} - -void FocusManager::WidgetFocusManager::RemoveFocusChangeListener( - WidgetFocusChangeListener* listener) { - WidgetFocusChangeListenerList::iterator iter(std::find( - focus_change_listeners_.begin(), - focus_change_listeners_.end(), - listener)); - if (iter != focus_change_listeners_.end()) { - focus_change_listeners_.erase(iter); - } else { - NOTREACHED() << - "Attempting to remove an unregistered WidgetFocusChangeListener."; - } -} - -void FocusManager::WidgetFocusManager::OnWidgetFocusEvent( - gfx::NativeView focused_before, - gfx::NativeView focused_now) { - if (!enabled_) - return; - - // Perform a safe iteration over the focus listeners, as the array - // may change during notification. - WidgetFocusChangeListenerList local_listeners(focus_change_listeners_); - WidgetFocusChangeListenerList::iterator iter(local_listeners.begin()); - for (;iter != local_listeners.end(); ++iter) { - (*iter)->NativeFocusWillChange(focused_before, focused_now); - } -} - -// static -FocusManager::WidgetFocusManager* -FocusManager::WidgetFocusManager::GetInstance() { - return Singleton<WidgetFocusManager>::get(); -} - -FocusManager::WidgetFocusManager::WidgetFocusManager() : enabled_(true) {} - -FocusManager::WidgetFocusManager::~WidgetFocusManager() {} - -//////////////////////////////////////////////////////////////////////////////// -// FocusManager, public: - -FocusManager::FocusManager(Widget* widget) - : widget_(widget), - focused_view_(NULL) { - DCHECK(widget_); -} - -FocusManager::~FocusManager() { - // If there are still registered FocusChange listeners, chances are they were - // leaked so warn about them. - DCHECK(focus_change_listeners_.empty()); -} - -// static -FocusManager::WidgetFocusManager* FocusManager::GetWidgetFocusManager() { - return WidgetFocusManager::GetInstance(); -} - -bool FocusManager::OnKeyEvent(const KeyEvent& event) { - // If the focused view wants to process the key event as is, let it be. - // On Linux we always dispatch key events to the focused view first, so - // we should not do this check here. See also NativeWidgetGtk::OnKeyEvent(). - if (focused_view_ && focused_view_->SkipDefaultKeyEventProcessing(event)) - return true; - - // Intercept Tab related messages for focus traversal. - if (CanTraverseFocus(widget_) && IsTabTraversalKeyEvent(event)) { - AdvanceFocus(DirectionFromKeyEvent(event)); - return false; - } - - // Intercept arrow key messages to switch between grouped views. - // TODO(beng): Perhaps make this a FocusTraversable that is created for - // Views that have a group set? - ui::KeyboardCode key_code = event.key_code(); - if (focused_view_ && focused_view_->group() != -1 && - (key_code == ui::VKEY_UP || key_code == ui::VKEY_DOWN || - key_code == ui::VKEY_LEFT || key_code == ui::VKEY_RIGHT)) { - bool next = (key_code == ui::VKEY_RIGHT || key_code == ui::VKEY_DOWN); - std::vector<View*> views; - focused_view_->parent()->GetViewsInGroup(focused_view_->group(), &views); - std::vector<View*>::const_iterator iter = std::find(views.begin(), - views.end(), - focused_view_); - DCHECK(iter != views.end()); - int index = static_cast<int>(iter - views.begin()); - index += next ? 1 : -1; - if (index < 0) { - index = static_cast<int>(views.size()) - 1; - } else if (index >= static_cast<int>(views.size())) { - index = 0; - } - SetFocusedViewWithReasonAndDirection(views[index], - FocusEvent::REASON_TRAVERSAL, - DirectionFromBool(next)); - return false; - } - - // Process keyboard accelerators. - // If the key combination matches an accelerator, the accelerator is - // triggered, otherwise the key event is processed as usual. - Accelerator accelerator(event.key_code(), event.GetModifiers()); - if (ProcessAccelerator(accelerator)) { - // If a shortcut was activated for this keydown message, do not propagate - // the event further. - return false; - } - return true; -} - -bool FocusManager::ContainsView(View* view) const { - Widget* widget = view->GetWidget(); - return widget ? widget->GetFocusManager() == this : false; -} - -void FocusManager::RemoveView(View* view) { - // Clear focus if the removed child was focused. - if (focused_view_ == view) - ClearFocus(); -} - -void FocusManager::AdvanceFocus(FocusEvent::TraversalDirection direction) { - View* view = GetNextFocusableView(focused_view_, direction, false); - // Note: Do not skip this next block when v == focused_view_. If the user - // tabs past the last focusable element in a web page, we'll get here, and if - // the TabContentsContainerView is the only focusable view (possible in - // full-screen mode), we need to run this block in order to cycle around to - // the first element on the page. - if (view) { - SetFocusedViewWithReasonAndDirection(view, FocusEvent::REASON_TRAVERSAL, - direction); - } -} - -void FocusManager::SetFocusedViewWithReasonAndDirection( - View* view, - FocusEvent::Reason reason, - FocusEvent::TraversalDirection direction) { - if (focused_view_ == view) - return; - - View* prev_focused_view = focused_view_; - if (focused_view_) { - focused_view_->OnBlur( - FocusEvent(FocusEvent::TYPE_FOCUS_OUT, reason, direction)); - focused_view_->Invalidate(); - } - - // Notified listeners that the focus changed. - FocusChangeListenerList::const_iterator iter; - for (iter = focus_change_listeners_.begin(); - iter != focus_change_listeners_.end(); ++iter) { - (*iter)->FocusWillChange(prev_focused_view, view); - } - - focused_view_ = view; - - if (view) { - view->Invalidate(); - view->OnFocus(FocusEvent(FocusEvent::TYPE_FOCUS_IN, reason, direction)); - // The view might be deleted now. - } -} - -void FocusManager::ClearFocus() { - SetFocusedView(NULL); - widget_->native_widget()->FocusNativeView(NULL); -} - -void FocusManager::ValidateFocusedView() { - if (focused_view_) { - if (!ContainsView(focused_view_)) - ClearFocus(); - } -} - -void FocusManager::RegisterAccelerator( - const Accelerator& accelerator, - AcceleratorTarget* target) { - AcceleratorTargetList& targets = accelerators_[accelerator]; - DCHECK(std::find(targets.begin(), targets.end(), target) == targets.end()) - << "Registering the same target multiple times"; - targets.push_front(target); -} - -void FocusManager::UnregisterAccelerator(const Accelerator& accelerator, - AcceleratorTarget* target) { - AcceleratorMap::iterator map_iter = accelerators_.find(accelerator); - if (map_iter == accelerators_.end()) { - NOTREACHED() << "Unregistering non-existing accelerator"; - return; - } - - AcceleratorTargetList* targets = &map_iter->second; - AcceleratorTargetList::iterator target_iter = - std::find(targets->begin(), targets->end(), target); - if (target_iter == targets->end()) { - NOTREACHED() << "Unregistering accelerator for wrong target"; - return; - } - - targets->erase(target_iter); -} - -void FocusManager::UnregisterAccelerators(AcceleratorTarget* target) { - for (AcceleratorMap::iterator map_iter = accelerators_.begin(); - map_iter != accelerators_.end(); ++map_iter) { - AcceleratorTargetList* targets = &map_iter->second; - targets->remove(target); - } -} - -bool FocusManager::ProcessAccelerator(const Accelerator& accelerator) { - AcceleratorMap::iterator map_iter = accelerators_.find(accelerator); - if (map_iter != accelerators_.end()) { - // We have to copy the target list here, because an AcceleratorPressed - // event handler may modify the list. - AcceleratorTargetList targets(map_iter->second); - for (AcceleratorTargetList::iterator iter = targets.begin(); - iter != targets.end(); ++iter) { - if ((*iter)->AcceleratorPressed(accelerator)) - return true; - } - } - return false; -} - -void FocusManager::AddFocusChangeListener(FocusChangeListener* listener) { - DCHECK(std::find(focus_change_listeners_.begin(), - focus_change_listeners_.end(), listener) == - focus_change_listeners_.end()) << "Adding a listener twice."; - focus_change_listeners_.push_back(listener); -} - -void FocusManager::RemoveFocusChangeListener(FocusChangeListener* listener) { - FocusChangeListenerList::iterator place = - std::find(focus_change_listeners_.begin(), focus_change_listeners_.end(), - listener); - if (place == focus_change_listeners_.end()) { - NOTREACHED() << "Removing a listener that isn't registered."; - return; - } - focus_change_listeners_.erase(place); -} - -AcceleratorTarget* FocusManager::GetCurrentTargetForAccelerator( - const Accelerator& accelerator) const { - AcceleratorMap::const_iterator map_iter = accelerators_.find(accelerator); - if (map_iter == accelerators_.end() || map_iter->second.empty()) - return NULL; - return map_iter->second.front(); -} - -// static -bool FocusManager::IsTabTraversalKeyEvent(const KeyEvent& key_event) { - return key_event.key_code() == ui::VKEY_TAB && - !key_event.IsControlDown(); -} - -//////////////////////////////////////////////////////////////////////////////// -// FocusManager, private: - -View* FocusManager::GetNextFocusableView( - View* original_starting_view, - FocusEvent::TraversalDirection direction, - bool dont_loop) { - FocusTraversable* focus_traversable = NULL; - - // Let's re-validate the focused view. - ValidateFocusedView(); - - View* starting_view = NULL; - if (original_starting_view) { - // Search up the containment hierarchy to see if a view is acting as - // a pane, and wants to implement its own focus traversable to keep - // the focus trapped within that pane. - View* pane_search = original_starting_view; - while (pane_search) { - focus_traversable = pane_search->GetPaneFocusTraversable(); - if (focus_traversable) { - starting_view = original_starting_view; - break; - } - pane_search = pane_search->parent(); - } - - if (!focus_traversable) { - if (IsTraverseForward(direction)) { - // If the starting view has a focus traversable, use it. - // This is the case with NativeWidgetWins for example. - focus_traversable = original_starting_view->GetFocusTraversable(); - - // Otherwise default to the root view. - if (!focus_traversable) { - focus_traversable = - original_starting_view->GetWidget()->GetFocusTraversable(); - starting_view = original_starting_view; - } - } else { - // When you are going back, starting view's FocusTraversable - // should not be used. - focus_traversable = - original_starting_view->GetWidget()->GetFocusTraversable(); - starting_view = original_starting_view; - } - } - } else { - focus_traversable = widget_->GetFocusTraversable(); - } - - // Traverse the FocusTraversable tree down to find the focusable view. - View* v = FindFocusableView(focus_traversable, starting_view, direction); - if (v) { - return v; - } else { - // Let's go up in the FocusTraversable tree. - FocusTraversable* parent_focus_traversable = - focus_traversable->GetFocusTraversableParent(); - starting_view = focus_traversable->GetFocusTraversableParentView(); - while (parent_focus_traversable) { - FocusTraversable* new_focus_traversable = NULL; - View* new_starting_view = NULL; - // When we are going backward, the parent view might gain the next focus. - bool check_starting_view = !IsTraverseForward(direction); - v = parent_focus_traversable->GetFocusSearch()->FindNextFocusableView( - starting_view, !IsTraverseForward(direction), FocusSearch::UP, - check_starting_view, &new_focus_traversable, &new_starting_view); - - if (new_focus_traversable) { - DCHECK(!v); - - // There is a FocusTraversable, traverse it down. - v = FindFocusableView(new_focus_traversable, NULL, direction); - } - - if (v) - return v; - - starting_view = focus_traversable->GetFocusTraversableParentView(); - parent_focus_traversable = - parent_focus_traversable->GetFocusTraversableParent(); - } - - // If we get here, we have reached the end of the focus hierarchy, let's - // loop. Make sure there was at least a view to start with, to prevent - // infinitely looping in empty windows. - if (!dont_loop && original_starting_view) { - // Easy, just clear the selection and press tab again. - // By calling with NULL as the starting view, we'll start from the - // top_root_view. - return GetNextFocusableView(NULL, direction, true); - } - } - return NULL; -} - -// Find the next focusable view for the specified FocusTraversable, starting at -// the specified view, traversing down the FocusTraversable hierarchy in -// |direction|. -View* FocusManager::FindFocusableView( - FocusTraversable* focus_traversable, - View* starting_view, - FocusEvent::TraversalDirection direction) { - FocusTraversable* new_focus_traversable = NULL; - View* new_starting_view = NULL; - View* v = focus_traversable->GetFocusSearch()->FindNextFocusableView( - starting_view, - !IsTraverseForward(direction), - FocusSearch::DOWN, - false, - &new_focus_traversable, - &new_starting_view); - - // Let's go down the FocusTraversable tree as much as we can. - while (new_focus_traversable) { - DCHECK(!v); - focus_traversable = new_focus_traversable; - starting_view = new_starting_view; - new_focus_traversable = NULL; - starting_view = NULL; - v = focus_traversable->GetFocusSearch()->FindNextFocusableView( - starting_view, - !IsTraverseForward(direction), - FocusSearch::DOWN, - false, - &new_focus_traversable, - &new_starting_view); - } - return v; -} - -} // namespace ui diff --git a/ui/views/focus/focus_manager.h b/ui/views/focus/focus_manager.h deleted file mode 100644 index 2236619..0000000 --- a/ui/views/focus/focus_manager.h +++ /dev/null @@ -1,303 +0,0 @@ -// Copyright (c) 2011 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 UI_VIEWS_FOCUS_FOCUS_MANAGER_H_ -#define UI_VIEWS_FOCUS_FOCUS_MANAGER_H_ -#pragma once - -#include <list> -#include <map> -#include <vector> - -#include "base/basictypes.h" -#include "base/memory/singleton.h" -#include "ui/gfx/native_widget_types.h" -#include "ui/views/events/accelerator.h" -#include "ui/views/events/focus_event.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 gfx::NativeView 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 NativeViewHost class. -// -// When creating a top window (derived from views::Widget) that is not a child -// window, it creates and owns a FocusManager to manage the focus for itself and -// all its child windows. -// -// 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 NativeWidgetWin as its native -// component), then you need to: -// - override the View::GetFocusTraversable() method in your outer 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: AccessibleToolbarView -// is FocusTraversable. - -namespace ui { - -class FocusSearch; -class RootView; -class View; -class Widget; - -// The FocusTraversable interface is used by components that want to process -// focus traversal events (due to Tab/Shift-Tab key events). -class FocusTraversable { - public: - // Return a FocusSearch object that implements the algorithm to find - // the next or previous focusable view. - virtual const FocusSearch* GetFocusSearch() const = 0; - - // Should return the parent FocusTraversable. - // The top RootView which is the top FocusTraversable returns NULL. - virtual FocusTraversable* GetFocusTraversableParent() const = 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() const = 0; - - protected: - virtual ~FocusTraversable() {} -}; - -// 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; - - protected: - virtual ~FocusChangeListener() {} -}; - -// This interface should be implemented by classes that want to be notified when -// the native focus is about to change. Listeners implementing this interface -// will be invoked for all native focus changes across the entire Chrome -// application. FocusChangeListeners are only called for changes within the -// children of a single top-level native-view. -class WidgetFocusChangeListener { - public: - virtual void NativeFocusWillChange(gfx::NativeView focused_before, - gfx::NativeView focused_now) = 0; - - protected: - virtual ~WidgetFocusChangeListener() {} -}; - -class FocusManager { - public: - class WidgetFocusManager { - public: - // Returns the singleton instance. - static WidgetFocusManager* GetInstance(); - - // Adds/removes a WidgetFocusChangeListener |listener| to the set of - // active listeners. - void AddFocusChangeListener(WidgetFocusChangeListener* listener); - void RemoveFocusChangeListener(WidgetFocusChangeListener* listener); - - // To be called when native-focus shifts from |focused_before| to - // |focused_now|. - // TODO(port) : Invocations to this routine are only implemented for - // the Win32 platform. Calls need to be placed appropriately for - // non-Windows environments. - void OnWidgetFocusEvent(gfx::NativeView focused_before, - gfx::NativeView focused_now); - - // Enable/Disable notification of registered listeners during calls - // to OnWidgetFocusEvent. Used to prevent unwanted focus changes from - // propagating notifications. - void EnableNotifications() { enabled_ = true; } - void DisableNotifications() { enabled_ = false; } - - private: - WidgetFocusManager(); - ~WidgetFocusManager(); - - typedef std::vector<WidgetFocusChangeListener*> - WidgetFocusChangeListenerList; - WidgetFocusChangeListenerList focus_change_listeners_; - - bool enabled_; - - friend struct DefaultSingletonTraits<WidgetFocusManager>; - DISALLOW_COPY_AND_ASSIGN(WidgetFocusManager); - }; - - explicit FocusManager(Widget* widget); - virtual ~FocusManager(); - - // Returns the global WidgetFocusManager instance for the running application. - static WidgetFocusManager* GetWidgetFocusManager(); - - // Processes the passed key event for accelerators and tab traversal. - // Returns false if the event has been consumed and should not be processed - // further. - bool OnKeyEvent(const KeyEvent& event); - - // Returns true is the specified is part of the hierarchy of the window - // associated with this FocusManager. - bool ContainsView(View* view) const; - - // Stops tracking this View in the focus manager. If the View is focused, - // focus is cleared. - void RemoveView(View* view); - - // Advances the focus (backward if reverse is true). - void AdvanceFocus(FocusEvent::TraversalDirection direction); - - // The FocusManager keeps track of the focused view within a RootView. - View* focused_view() const { return focused_view_; } - - // Low-level methods to force the focus to change. If the focus change should - // only happen if the view is currently focusable, enabled, and visible, call - // view->RequestFocus(). - void SetFocusedViewWithReasonAndDirection( - View* view, - FocusEvent::Reason reason, - FocusEvent::TraversalDirection direction); - void SetFocusedView(View* view) { - SetFocusedViewWithReasonAndDirection(view, FocusEvent::REASON_DIRECT, - FocusEvent::DIRECTION_NONE); - } - - // Clears the focused view. The window associated with the top root view gets - // the native focus (so we still get keyboard events). - void ClearFocus(); - - // Validates the focused view, clearing it if the window it belongs too is not - // attached to the window hierarchy anymore. - void ValidateFocusedView(); - - // Register a keyboard accelerator for the specified target. If multiple - // targets are registered for an accelerator, a target registered later has - // higher priority. - // 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) - void 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. - // First, AcceleratorPressed handler of the most recently registered target - // is called, and if that handler processes the event (i.e. returns true), - // this method immediately returns. If not, we do the same thing on the next - // target, and so on. - // Returns true if an accelerator was activated. - bool ProcessAccelerator(const Accelerator& accelerator); - - // 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. - AcceleratorTarget* GetCurrentTargetForAccelerator( - const Accelerator& accelertor) const; - - // Convenience method that returns true if the passed |key_event| should - // trigger tab traversal (if it is a TAB key press with or without SHIFT - // pressed). - static bool IsTabTraversalKeyEvent(const KeyEvent& key_event); - - private: - // Returns the next focusable view. - View* GetNextFocusableView(View* starting_view, - FocusEvent::TraversalDirection direction, - bool dont_loop); - - // 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, - FocusEvent::TraversalDirection direction); - - // The top-level Widget this FocusManager is associated with. - Widget* widget_; - - // The view that currently is focused. - View* focused_view_; - - // The accelerators and associated targets. - typedef std::list<AcceleratorTarget*> AcceleratorTargetList; - typedef std::map<Accelerator, AcceleratorTargetList> AcceleratorMap; - AcceleratorMap accelerators_; - - // The list of registered FocusChange listeners. - typedef std::vector<FocusChangeListener*> FocusChangeListenerList; - FocusChangeListenerList focus_change_listeners_; - - DISALLOW_COPY_AND_ASSIGN(FocusManager); -}; - -// A basic helper class that is used to disable native focus change -// notifications within a scope. -class AutoNativeNotificationDisabler { - public: - AutoNativeNotificationDisabler() { - FocusManager::GetWidgetFocusManager()->DisableNotifications(); - } - - ~AutoNativeNotificationDisabler() { - FocusManager::GetWidgetFocusManager()->EnableNotifications(); - } - private: - DISALLOW_COPY_AND_ASSIGN(AutoNativeNotificationDisabler); -}; - -} // namespace ui - -#endif // UI_VIEWS_FOCUS_FOCUS_MANAGER_H_ diff --git a/ui/views/focus/focus_search.cc b/ui/views/focus/focus_search.cc deleted file mode 100644 index 083fc7c..0000000 --- a/ui/views/focus/focus_search.cc +++ /dev/null @@ -1,273 +0,0 @@ -// Copyright (c) 2011 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. - -#include "base/logging.h" -#include "ui/views/focus/focus_manager.h" -#include "ui/views/focus/focus_search.h" -#include "ui/views/view.h" - -namespace ui { - -FocusSearch::FocusSearch(View* root, bool cycle, bool accessibility_mode) - : root_(root), - cycle_(cycle), - accessibility_mode_(accessibility_mode) { -} - -View* FocusSearch::FindNextFocusableView(View* starting_view, - bool reverse, - Direction direction, - bool check_starting_view, - FocusTraversable** focus_traversable, - View** focus_traversable_view) const { - *focus_traversable = NULL; - *focus_traversable_view = NULL; - - if (root_->children_empty()) { - NOTREACHED(); - // Nothing to focus on here. - return NULL; - } - - View* initial_starting_view = starting_view; - int starting_view_group = -1; - if (starting_view) - starting_view_group = starting_view->group(); - - if (!starting_view) { - // Default to the first/last child - starting_view = - reverse ? - root_->child_at(root_->children_size() - 1) : - root_->child_at(0); - // If there was no starting view, then the one we select is a potential - // focus candidate. - check_starting_view = true; - } else { - // The starting view should be a direct or indirect child of the root. - DCHECK(root_->Contains(*starting_view)); - } - - View* v = NULL; - if (!reverse) { - v = FindNextFocusableViewImpl(starting_view, check_starting_view, - true, - (direction == DOWN) ? true : false, - starting_view_group, - focus_traversable, - focus_traversable_view); - } else { - // If the starting view is focusable, we don't want to go down, as we are - // traversing the view hierarchy tree bottom-up. - bool can_go_down = (direction == DOWN) && !IsFocusable(starting_view); - v = FindPreviousFocusableViewImpl(starting_view, check_starting_view, - true, - can_go_down, - starting_view_group, - focus_traversable, - focus_traversable_view); - } - - // Don't set the focus to something outside of this view hierarchy. - if (v && v != root_ && !root_->Contains(*v)) - v = NULL; - - // If |cycle_| is true, prefer to keep cycling rather than returning NULL. - if (cycle_ && !v && initial_starting_view) { - v = FindNextFocusableView(NULL, reverse, direction, check_starting_view, - focus_traversable, focus_traversable_view); - DCHECK(IsFocusable(v)); - return v; - } - - // Doing some sanity checks. - if (v) { - DCHECK(IsFocusable(v)); - return v; - } - if (*focus_traversable) { - DCHECK(*focus_traversable_view); - return NULL; - } - // Nothing found. - return NULL; -} - -bool FocusSearch::IsViewFocusableCandidate(View* v, int skip_group_id) const { - return IsFocusable(v) && - (v->IsGroupFocusTraversable() || skip_group_id == -1 || - v->group() != skip_group_id); -} - -bool FocusSearch::IsFocusable(View* v) const { - if (accessibility_mode_) - return v && v->IsAccessibilityFocusableInRootView(); - - return v && v->IsFocusableInRootView(); -} - -View* FocusSearch::FindSelectedViewForGroup(View* view) const { - // No group for that view. - if (view->IsGroupFocusTraversable() || view->group() == -1) - return view; - - View* selected_view = view->GetSelectedViewForGroup(view->group()); - if (selected_view) - return selected_view; - - // No view selected for that group, default to the specified view. - return view; -} - -View* FocusSearch::GetParent(View* v) const { - return root_->Contains(*v) ? v->parent() : NULL; -} - -// Strategy for finding the next focusable view: -// - keep going down the first child, stop when you find a focusable view or -// a focus traversable view (in that case return it) or when you reach a view -// with no children. -// - go to the right sibling and start the search from there (by invoking -// FindNextFocusableViewImpl on that view). -// - if the view has no right sibling, go up the parents until you find a parent -// with a right sibling and start the search from there. -View* FocusSearch::FindNextFocusableViewImpl( - View* starting_view, - bool check_starting_view, - bool can_go_up, - bool can_go_down, - int skip_group_id, - FocusTraversable** focus_traversable, - View** focus_traversable_view) const { - if (check_starting_view) { - if (IsViewFocusableCandidate(starting_view, skip_group_id)) { - View* v = FindSelectedViewForGroup(starting_view); - // The selected view might not be focusable (if it is disabled for - // example). - if (IsFocusable(v)) - return v; - } - - *focus_traversable = starting_view->GetFocusTraversable(); - if (*focus_traversable) { - *focus_traversable_view = starting_view; - return NULL; - } - } - - // First let's try the left child. - if (can_go_down) { - if (!starting_view->children_empty()) { - View* v = FindNextFocusableViewImpl(starting_view->child_at(0), - true, false, true, skip_group_id, - focus_traversable, - focus_traversable_view); - if (v || *focus_traversable) - return v; - } - } - - // Then try the right sibling. - View* sibling = starting_view->GetNextFocusableView(); - if (sibling) { - View* v = FindNextFocusableViewImpl(sibling, - true, false, true, skip_group_id, - focus_traversable, - focus_traversable_view); - if (v || *focus_traversable) - return v; - } - - // Then go up to the parent sibling. - if (can_go_up) { - View* parent = GetParent(starting_view); - while (parent) { - sibling = parent->GetNextFocusableView(); - if (sibling) { - return FindNextFocusableViewImpl(sibling, - true, true, true, - skip_group_id, - focus_traversable, - focus_traversable_view); - } - parent = GetParent(parent); - } - } - - // We found nothing. - return NULL; -} - -// Strategy for finding the previous focusable view: -// - keep going down on the right until you reach a view with no children, if it -// it is a good candidate return it. -// - start the search on the left sibling. -// - if there are no left sibling, start the search on the parent (without going -// down). -View* FocusSearch::FindPreviousFocusableViewImpl( - View* starting_view, - bool check_starting_view, - bool can_go_up, - bool can_go_down, - int skip_group_id, - FocusTraversable** focus_traversable, - View** focus_traversable_view) const { - // Let's go down and right as much as we can. - if (can_go_down) { - // Before we go into the direct children, we have to check if this view has - // a FocusTraversable. - *focus_traversable = starting_view->GetFocusTraversable(); - if (*focus_traversable) { - *focus_traversable_view = starting_view; - return NULL; - } - - if (!starting_view->children_empty()) { - View* view = starting_view->child_at(starting_view->children_size() - 1); - View* v = FindPreviousFocusableViewImpl(view, true, false, true, - skip_group_id, - focus_traversable, - focus_traversable_view); - if (v || *focus_traversable) - return v; - } - } - - // Then look at this view. Here, we do not need to see if the view has - // a FocusTraversable, since we do not want to go down any more. - if (check_starting_view && - IsViewFocusableCandidate(starting_view, skip_group_id)) { - View* v = FindSelectedViewForGroup(starting_view); - // The selected view might not be focusable (if it is disabled for - // example). - if (IsFocusable(v)) - return v; - } - - // Then try the left sibling. - View* sibling = starting_view->GetPreviousFocusableView(); - if (sibling) { - return FindPreviousFocusableViewImpl(sibling, - true, true, true, - skip_group_id, - focus_traversable, - focus_traversable_view); - } - - // Then go up the parent. - if (can_go_up) { - View* parent = GetParent(starting_view); - if (parent) - return FindPreviousFocusableViewImpl(parent, - true, true, false, - skip_group_id, - focus_traversable, - focus_traversable_view); - } - - // We found nothing. - return NULL; -} - -} // namespace ui diff --git a/ui/views/focus/focus_search.h b/ui/views/focus/focus_search.h deleted file mode 100644 index 3cda790..0000000 --- a/ui/views/focus/focus_search.h +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright (c) 2011 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 UI_VIEWS_FOCUS_FOCUS_SEARCH_H_ -#define UI_VIEWS_FOCUS_FOCUS_SEARCH_H_ -#pragma once - -#include "ui/views/view.h" - -namespace ui { - -class FocusTraversable; - -// FocusSearch is an object that implements the algorithm to find the -// next view to focus. -class FocusSearch { - 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 - }; - - // Constructor. - // - |root| is the root of the view hierarchy to traverse. Focus will be - // trapped inside. - // - |cycle| should be true if you want FindNextFocusableView to cycle back - // to the first view within this root when the traversal reaches - // the end. If this is true, then if you pass a valid starting - // view to FindNextFocusableView you will always get a valid view - // out, even if it's the same view. - // - |accessibility_mode| should be true if full keyboard accessibility is - // needed and you want to check IsAccessibilityFocusableInRootView(), - // rather than IsFocusableInRootView(). - FocusSearch(View* root, bool cycle, bool accessibility_mode); - virtual ~FocusSearch() {} - - // Finds the next view that should be focused and returns it. If a - // FocusTraversable is found while searching for the focusable view, - // returns NULL and sets |focus_traversable| to the FocusTraversable - // and |focus_traversable_view| to the view associated with the - // FocusTraversable. - // - // Return NULL if the end of the focus loop is reached, unless this object - // was initialized with |cycle|=true, in which case it goes back to the - // beginning when it reaches the end of the traversal. - // - |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). - // - |check_starting_view| is true if starting_view may obtain the next focus. - // - |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 check_starting_view, - FocusTraversable** focus_traversable, - View** focus_traversable_view) const; - - private: - // Convenience method that returns true if a view is focusable and does not - // belong to the specified group. - bool IsViewFocusableCandidate(View* v, int skip_group_id) const; - - // Convenience method; returns true if a view is not NULL and is focusable - // (checking IsAccessibilityFocusableInRootView() if accessibility_mode_ is - // true). - bool IsFocusable(View* v) const; - - // Returns the view selected for the group of the selected view. If the view - // does not belong to a group or if no view is selected in the group, the - // specified view is returned. - View* FindSelectedViewForGroup(View* view) const; - - // Get the parent, but stay within the root. Returns NULL if asked for - // the parent of root_. - View* GetParent(View* view) const; - - // Returns the next focusable view or view containing a FocusTraversable - // (NULL if none was found), starting at the starting_view. - // |check_starting_view|, |can_go_up| and |can_go_down| controls the - // traversal of the views hierarchy. |skip_group_id| specifies a group_id, - // -1 means no group. All views from a group are traversed in one pass. - View* FindNextFocusableViewImpl(View* starting_view, - bool check_starting_view, - bool can_go_up, - bool can_go_down, - int skip_group_id, - FocusTraversable** focus_traversable, - View** focus_traversable_view) const; - - // Same as FindNextFocusableViewImpl but returns the previous focusable view. - View* FindPreviousFocusableViewImpl(View* starting_view, - bool check_starting_view, - bool can_go_up, - bool can_go_down, - int skip_group_id, - FocusTraversable** focus_traversable, - View** focus_traversable_view) const; - - View* root_; - bool cycle_; - bool accessibility_mode_; - - DISALLOW_COPY_AND_ASSIGN(FocusSearch); -}; - -} // namespace ui - -#endif // UI_VIEWS_FOCUS_FOCUS_SEARCH_H_ |