diff options
author | yusukes@chromium.org <yusukes@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-17 04:42:33 +0000 |
---|---|---|
committer | yusukes@chromium.org <yusukes@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-17 04:42:33 +0000 |
commit | e7293fa923c53d7e5ea3d38a0b94d6cbc0fb8486 (patch) | |
tree | 0c147ea2bd1e085f7b476445f0983d433261412d /ui | |
parent | 12ba80a36b9d69af9fdd7435da508c997749fddb (diff) | |
download | chromium_src-e7293fa923c53d7e5ea3d38a0b94d6cbc0fb8486.zip chromium_src-e7293fa923c53d7e5ea3d38a0b94d6cbc0fb8486.tar.gz chromium_src-e7293fa923c53d7e5ea3d38a0b94d6cbc0fb8486.tar.bz2 |
Let Chrome app handle Ash accelerators first if the app is launched as a window.
Currently, Ash accelerators are handled at a very early stage, right after a native key event is received by aura::RootWindowHost. This CL change the way of handling Ash accelerators as follows to make it more App friendly:
1. If no window is focused, handle an Ash accelerator immediately in ash/accelerators/accelerator_filter.cc in the same way as before.
2. Otherwise, do not handle it in ash/accelerators/accelerator_filter.cc but let a custom views::FocusManager handle it (see ash/shell.cc). There are 3 types of scenarios here depending on the type of the focused window:
2-a. If the focused window is a browser, and the browser is not for an app, let the custom focus manager pre-handle Ash accelerators before passing it to the browser (see PreHandleKeyboardEvent() in chrome/browser/ui/views/frame/browser_view.cc).
2-b. If the focused window is a browser, and the browser is for an app, let the app handle Ash accelerators first (see chrome/browser/ui/views/frame/browser_view.cc). If the accelerator is not consumed by the app, let the custom focus manager handle it.
2-c. If the focused window is not a browser, let the window handle Ash accelerators first. If the accelerator is not consumed by the window, then let the custom focus manager handle it. This means a WebView without the chrome/browser/ui/ layer can handle Ash accelerators first whenever needed.
Other changes:
chrome/browser/ui/views/frame/browser_view.cc:
Support ET_KEY_RELEASED accelerators in BrowserView::PreHandleKeyboardEvent().
ui/views/focus/focus_manager.cc:
Support ET_KEY_RELEASED accelerators. Also fix code for handing VKEY_MENU so that the Shift+Alt+ET_KEY_RELEASED accelerator for Ash could be handled correctly.
This CL depends on http://codereview.chromium.org/10377158/ (by jochen), https://chromiumcodereview.appspot.com/10388023, http://codereview.chromium.org/10389035/, and https://chromiumcodereview.appspot.com/10332051/, and should not be submitted until the 4 CLs are landed.
BUG=123856
TEST=ran aura_shell_unittests
TEST=manual; launch Chromoting app as a window, connect to a Chromoting server, focus Chrome on the remote machine, press Ctrl-n, confirm a new window is opened on the remote machine.
Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=135791
Review URL: https://chromiumcodereview.appspot.com/10134036
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@137629 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui')
-rw-r--r-- | ui/views/focus/focus_manager.cc | 105 | ||||
-rw-r--r-- | ui/views/focus/focus_manager.h | 7 | ||||
-rw-r--r-- | ui/views/focus/focus_manager_delegate.h | 40 | ||||
-rw-r--r-- | ui/views/focus/focus_manager_factory.cc | 4 | ||||
-rw-r--r-- | ui/views/focus/focus_manager_unittest.cc | 2 | ||||
-rw-r--r-- | ui/views/views.gyp | 1 |
6 files changed, 110 insertions, 49 deletions
diff --git a/ui/views/focus/focus_manager.cc b/ui/views/focus/focus_manager.cc index 1467f25..1799831 100644 --- a/ui/views/focus/focus_manager.cc +++ b/ui/views/focus/focus_manager.cc @@ -11,6 +11,7 @@ #include "build/build_config.h" #include "ui/base/accelerators/accelerator.h" #include "ui/base/keycodes/keyboard_codes.h" +#include "ui/views/focus/focus_manager_delegate.h" #include "ui/views/focus/focus_search.h" #include "ui/views/focus/view_storage.h" #include "ui/views/focus/widget_focus_manager.h" @@ -20,8 +21,9 @@ namespace views { -FocusManager::FocusManager(Widget* widget) +FocusManager::FocusManager(Widget* widget, FocusManagerDelegate* delegate) : widget_(widget), + delegate_(delegate), focused_view_(NULL), accelerator_manager_(new ui::AcceleratorManager), focus_change_reason_(kReasonDirectFocusChange), @@ -54,22 +56,23 @@ bool FocusManager::OnKeyEvent(const KeyEvent& event) { if (event.type() == ui::ET_KEY_PRESSED) { // VKEY_MENU is triggered by key release event. // FocusManager::OnKeyEvent() returns false when the key has been consumed. - if (key_code == ui::VKEY_MENU) { + if ((key_code == ui::VKEY_MENU) && + (event.flags() & ~ui::EF_ALT_DOWN) == 0) { should_handle_menu_key_release_ = true; return false; } - // Pass through to the reset of OnKeyEvent. + // Pass through to the rest of OnKeyEvent. } else if (key_code == ui::VKEY_MENU && should_handle_menu_key_release_ && (event.flags() & ~ui::EF_ALT_DOWN) == 0) { // Trigger VKEY_MENU when only this key is pressed and released, and both // press and release events are not handled by others. ui::Accelerator accelerator(ui::VKEY_MENU, false, false, false); return ProcessAccelerator(accelerator); - } else { + } else if (event.type() != ui::ET_KEY_RELEASED) { return false; } #else - if (event.type() != ui::ET_KEY_PRESSED) + if (event.type() != ui::ET_KEY_PRESSED && event.type() != ui::ET_KEY_RELEASED) return false; #endif @@ -77,53 +80,57 @@ bool FocusManager::OnKeyEvent(const KeyEvent& event) { event.IsShiftDown(), event.IsControlDown(), event.IsAltDown()); + accelerator.set_type(event.type()); + if (event.type() == ui::ET_KEY_PRESSED) { #if defined(OS_WIN) - // If the focused view wants to process the key event as is, let it be. - // This is not used for linux/aura. - if (focused_view_ && focused_view_->SkipDefaultKeyEventProcessing(event) && - !accelerator_manager_->HasPriorityHandler(accelerator)) - return true; + // If the focused view wants to process the key event as is, let it be. + // This is not used for linux/aura. + if (focused_view_ && focused_view_->SkipDefaultKeyEventProcessing(event) && + !accelerator_manager_->HasPriorityHandler(accelerator)) + return true; #endif - // Intercept Tab related messages for focus traversal. - // Note that we don't do 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. + // Intercept Tab related messages for focus traversal. + // Note that we don't do 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. #if defined(OS_WIN) && !defined(USE_AURA) - HWND top_window = widget_->GetNativeView(); - HWND active_window = ::GetActiveWindow(); - if ((active_window == top_window || ::IsChild(active_window, top_window)) && - IsTabTraversalKeyEvent(event)) { - AdvanceFocus(event.IsShiftDown()); - return false; - } + HWND top_window = widget_->GetNativeView(); + HWND active_window = ::GetActiveWindow(); + if ((active_window == top_window || ::IsChild(active_window, top_window)) && + IsTabTraversalKeyEvent(event)) { + AdvanceFocus(event.IsShiftDown()); + return false; + } #else - if (IsTabTraversalKeyEvent(event)) { - AdvanceFocus(event.IsShiftDown()); - return false; - } + if (IsTabTraversalKeyEvent(event)) { + AdvanceFocus(event.IsShiftDown()); + return false; + } #endif - // Intercept arrow key messages to switch between grouped views. - if (focused_view_ && focused_view_->GetGroup() != -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); - View::Views views; - focused_view_->parent()->GetViewsInGroup(focused_view_->GetGroup(), &views); - View::Views::const_iterator i( - std::find(views.begin(), views.end(), focused_view_)); - DCHECK(i != views.end()); - int index = static_cast<int>(i - 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; + // Intercept arrow key messages to switch between grouped views. + if (focused_view_ && focused_view_->GetGroup() != -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); + View::Views views; + focused_view_->parent()->GetViewsInGroup(focused_view_->GetGroup(), + &views); + View::Views::const_iterator i( + std::find(views.begin(), views.end(), focused_view_)); + DCHECK(i != views.end()); + int index = static_cast<int>(i - 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; + } + SetFocusedViewWithReason(views[index], kReasonFocusTraversal); + return false; } - SetFocusedViewWithReason(views[index], kReasonFocusTraversal); - return false; } // Process keyboard accelerators. @@ -420,7 +427,11 @@ void FocusManager::UnregisterAccelerators(ui::AcceleratorTarget* target) { } bool FocusManager::ProcessAccelerator(const ui::Accelerator& accelerator) { - return accelerator_manager_->Process(accelerator); + if (accelerator_manager_->Process(accelerator)) + return true; + if (delegate_.get()) + return delegate_->ProcessAccelerator(accelerator); + return false; } void FocusManager::MaybeResetMenuKeyState(const KeyEvent& key) { @@ -436,7 +447,11 @@ void FocusManager::MaybeResetMenuKeyState(const KeyEvent& key) { ui::AcceleratorTarget* FocusManager::GetCurrentTargetForAccelerator( const ui::Accelerator& accelerator) const { - return accelerator_manager_->GetCurrentTarget(accelerator); + ui::AcceleratorTarget* target = + accelerator_manager_->GetCurrentTarget(accelerator); + if (!target && delegate_.get()) + target = delegate_->GetCurrentTargetForAccelerator(accelerator); + return target; } bool FocusManager::HasPriorityHandler( diff --git a/ui/views/focus/focus_manager.h b/ui/views/focus/focus_manager.h index d8c60a6..cf6cb86 100644 --- a/ui/views/focus/focus_manager.h +++ b/ui/views/focus/focus_manager.h @@ -80,6 +80,7 @@ class AcceleratorManager; namespace views { +class FocusManagerDelegate; class FocusSearch; class RootView; class View; @@ -136,7 +137,7 @@ class VIEWS_EXPORT FocusManager { kReasonDirectFocusChange }; - explicit FocusManager(Widget* widget); + FocusManager(Widget* widget, FocusManagerDelegate* delegate); virtual ~FocusManager(); // Processes the passed key event for accelerators and tab traversal. @@ -270,6 +271,10 @@ class VIEWS_EXPORT FocusManager { // The top-level Widget this FocusManager is associated with. Widget* widget_; + // The object which handles an accelerator when |accelerator_manager_| doesn't + // handle it. + scoped_ptr<FocusManagerDelegate> delegate_; + // The view that currently is focused. View* focused_view_; diff --git a/ui/views/focus/focus_manager_delegate.h b/ui/views/focus/focus_manager_delegate.h new file mode 100644 index 0000000..1763ed2 --- /dev/null +++ b/ui/views/focus/focus_manager_delegate.h @@ -0,0 +1,40 @@ +// Copyright (c) 2012 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_DELEGATE_H_ +#define UI_VIEWS_FOCUS_FOCUS_MANAGER_DELEGATE_H_ +#pragma once + +#include "ui/views/views_export.h" + +namespace ui { +class Accelerator; +class AcceleratorTarget; +} + +namespace views { + +// Delegate interface for views::FocusManager. +class VIEWS_EXPORT FocusManagerDelegate { + public: + virtual ~FocusManagerDelegate() {} + + // 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. + virtual bool ProcessAccelerator(const ui::Accelerator& accelerator) = 0; + + // Returns the AcceleratorTarget that should be activated for the specified + // keyboard accelerator, or NULL if no view is registered for that keyboard + // accelerator. + virtual ui::AcceleratorTarget* GetCurrentTargetForAccelerator( + const ui::Accelerator& accelerator) const = 0; +}; + +} // namespace views + +#endif // UI_VIEWS_FOCUS_FOCUS_MANAGER_DELEGATE_H_ diff --git a/ui/views/focus/focus_manager_factory.cc b/ui/views/focus/focus_manager_factory.cc index e3ec805..b8e1a7a 100644 --- a/ui/views/focus/focus_manager_factory.cc +++ b/ui/views/focus/focus_manager_factory.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -18,7 +18,7 @@ class DefaultFocusManagerFactory : public views::FocusManagerFactory { protected: virtual FocusManager* CreateFocusManager(views::Widget* widget) OVERRIDE { - return new FocusManager(widget); + return new FocusManager(widget, NULL /* delegate */); } private: diff --git a/ui/views/focus/focus_manager_unittest.cc b/ui/views/focus/focus_manager_unittest.cc index 01a33ab..06b8448 100644 --- a/ui/views/focus/focus_manager_unittest.cc +++ b/ui/views/focus/focus_manager_unittest.cc @@ -502,7 +502,7 @@ class FocusManagerDtorTest : public FocusManagerTest { class FocusManagerDtorTracked : public FocusManager { public: FocusManagerDtorTracked(Widget* widget, DtorTrackVector* dtor_tracker) - : FocusManager(widget), + : FocusManager(widget, NULL /* delegate */), dtor_tracker_(dtor_tracker) { } diff --git a/ui/views/views.gyp b/ui/views/views.gyp index 47c1099..7d52dec 100644 --- a/ui/views/views.gyp +++ b/ui/views/views.gyp @@ -249,6 +249,7 @@ 'focus/external_focus_tracker.h', 'focus/focus_manager.cc', 'focus/focus_manager.h', + 'focus/focus_manager_delegate.h', 'focus/focus_manager_factory.cc', 'focus/focus_manager_factory.h', 'focus/focus_search.cc', |