diff options
author | oshima@chromium.org <oshima@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-05 20:43:41 +0000 |
---|---|---|
committer | oshima@chromium.org <oshima@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-05 20:43:41 +0000 |
commit | a9c060ca3ef4c5834955e94fe65bca94fb47c6a6 (patch) | |
tree | 4abc33f6679d789ff09a23dd92d564024b58874b | |
parent | 24845d70f3c481caa231cc24322927f636f3acd7 (diff) | |
download | chromium_src-a9c060ca3ef4c5834955e94fe65bca94fb47c6a6.zip chromium_src-a9c060ca3ef4c5834955e94fe65bca94fb47c6a6.tar.gz chromium_src-a9c060ca3ef4c5834955e94fe65bca94fb47c6a6.tar.bz2 |
AURA/X11: Handle VKEY_MENU accelerator on content area
-Moved the code to handle vkey_menu to focus manager.
-Unify the code between win/aura/gtk to handle unhandled web keyevent. We were using different code path for unhandled web keyboard for regular page and login. This should fix this issue also.
-Improved focus test not to use fixed wait. This should also speedup the test a bit.
-Removed OmniboxViewViews tests that runs only on views/gtk. This is no longer supported and we can re-enable for win when ready.
BUG=99861,106998, 108480, 108459
TEST=manual: set focus to content area and hit alt key. the focus should be set to wrench menu on release.
Review URL: http://codereview.chromium.org/8907029
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@116541 0039d316-1c4b-4281-b951-d872f2087c98
22 files changed, 270 insertions, 315 deletions
diff --git a/chrome/browser/browser_focus_uitest.cc b/chrome/browser/browser_focus_uitest.cc index 322f601..e50c933 100644 --- a/chrome/browser/browser_focus_uitest.cc +++ b/chrome/browser/browser_focus_uitest.cc @@ -1,9 +1,10 @@ -// 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. #include "build/build_config.h" +#include "base/bind.h" #include "base/file_util.h" #include "base/format_macros.h" #include "base/message_loop.h" @@ -77,6 +78,9 @@ namespace { // action we take. const int kActionDelayMs = 500; +// Maxiumum time to wait until the focus is moved to expected view. +const int kFocusChangeTimeoutMs = 500; + const char kSimplePage[] = "files/focus/page_with_focus.html"; const char kStealFocusPage[] = "files/focus/page_steals_focus.html"; const char kTypicalPage[] = "files/focus/typical_page.html"; @@ -126,6 +130,19 @@ bool ChromeInForeground() { #endif } +// Wait the focus change in message loop. +void CheckFocus(Browser* browser, ViewID id, const base::Time& timeout) { + if (ui_test_utils::IsViewFocused(browser, id) || + base::Time::Now() > timeout) { + MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::QuitClosure()); + } else { + MessageLoop::current()->PostDelayedTask( + FROM_HERE, + base::Bind(&CheckFocus, browser, id, timeout), + 10); + } +}; + class BrowserFocusTest : public InProcessBrowserTest { public: BrowserFocusTest() : @@ -147,6 +164,17 @@ class BrowserFocusTest : public InProcessBrowserTest { ui_test_utils::ClickOnView(browser(), vid); } + bool WaitForFocusChange(ViewID vid) { + const base::Time timeout = base::Time::Now() + + base::TimeDelta::FromMilliseconds(kFocusChangeTimeoutMs); + MessageLoop::current()->PostDelayedTask( + FROM_HERE, + base::Bind(&CheckFocus, browser(), vid, timeout), + 100); + ui_test_utils::RunMessageLoop(); + return IsViewFocused(vid); + } + ViewID location_bar_focus_view_id_; }; @@ -760,16 +788,7 @@ IN_PROC_BROWSER_TEST_F(BrowserFocusTest, FindFocusTest) { browser(), ui::VKEY_F, true, false, false, false)); #endif - // Ideally, we wouldn't sleep here and instead would intercept the - // RenderViewHostDelegate::HandleKeyboardEvent() callback. To do that, we - // could create a RenderViewHostDelegate wrapper and hook-it up by either: - // - creating a factory used to create the delegate - // - making the test a private and overwriting the delegate member directly. - MessageLoop::current()->PostDelayedTask( - FROM_HERE, MessageLoop::QuitClosure(), kActionDelayMs); - ui_test_utils::RunMessageLoop(); - - ASSERT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD)); + ASSERT_TRUE(WaitForFocusChange(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD)); browser()->FocusLocationBar(); ASSERT_TRUE(IsViewFocused(location_bar_focus_view_id_)); @@ -797,11 +816,7 @@ IN_PROC_BROWSER_TEST_F(BrowserFocusTest, FindFocusTest) { browser(), ui::VKEY_F, true, false, false, false)); #endif - // See remark above on why we wait. - MessageLoop::current()->PostDelayedTask( - FROM_HERE, MessageLoop::QuitClosure(), kActionDelayMs); - ui_test_utils::RunMessageLoop(); - ASSERT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD)); + ASSERT_TRUE(WaitForFocusChange(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD)); } // Makes sure the focus is in the right location when opening the different diff --git a/chrome/browser/chromeos/login/html_page_screen.cc b/chrome/browser/chromeos/login/html_page_screen.cc index a2d7f26..0d22ee4 100644 --- a/chrome/browser/chromeos/login/html_page_screen.cc +++ b/chrome/browser/chromeos/login/html_page_screen.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. @@ -11,7 +11,6 @@ #include "chrome/browser/chromeos/input_method/input_method_util.h" #include "chrome/browser/chromeos/login/screen_observer.h" #include "chrome/browser/profiles/profile_manager.h" -#include "chrome/browser/ui/views/handle_web_keyboard_event.h" #include "content/browser/renderer_host/render_view_host.h" #include "content/browser/site_instance.h" #include "googleurl/src/gurl.h" @@ -70,7 +69,8 @@ HTMLPageView* HTMLPageScreen::AllocateView() { } void HTMLPageScreen::HandleKeyboardEvent(const NativeWebKeyboardEvent& event) { - HandleWebKeyboardEvent(view()->GetWidget(), event); + unhandled_keyboard_handler_.HandleKeyboardEvent(event, + view()->GetFocusManager()); } /////////////////////////////////////////////////////////////////////////////// diff --git a/chrome/browser/chromeos/login/html_page_screen.h b/chrome/browser/chromeos/login/html_page_screen.h index f374afa..257611b 100644 --- a/chrome/browser/chromeos/login/html_page_screen.h +++ b/chrome/browser/chromeos/login/html_page_screen.h @@ -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. @@ -14,6 +14,7 @@ #include "chrome/browser/chromeos/login/view_screen.h" #include "chrome/browser/chromeos/login/web_page_screen.h" #include "chrome/browser/chromeos/login/web_page_view.h" +#include "chrome/browser/ui/views/unhandled_keyboard_event_handler.h" namespace chromeos { @@ -78,6 +79,8 @@ class HTMLPageScreen : public ViewScreen<HTMLPageView>, // URL to navigate. std::string url_; + UnhandledKeyboardEventHandler unhandled_keyboard_handler_; + DISALLOW_COPY_AND_ASSIGN(HTMLPageScreen); }; diff --git a/chrome/browser/chromeos/login/registration_screen.cc b/chrome/browser/chromeos/login/registration_screen.cc index 1229ef5..f4bf56e 100644 --- a/chrome/browser/chromeos/login/registration_screen.cc +++ b/chrome/browser/chromeos/login/registration_screen.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. @@ -10,7 +10,6 @@ #include "chrome/browser/chromeos/input_method/input_method_manager.h" #include "chrome/browser/chromeos/input_method/input_method_util.h" #include "chrome/browser/profiles/profile_manager.h" -#include "chrome/browser/ui/views/handle_web_keyboard_event.h" #include "chrome/common/url_constants.h" #include "content/browser/child_process_security_policy.h" #include "content/browser/renderer_host/render_view_host.h" @@ -131,7 +130,8 @@ WebContents* RegistrationScreen::OpenURLFromTab(WebContents* source, void RegistrationScreen::HandleKeyboardEvent( const NativeWebKeyboardEvent& event) { - HandleWebKeyboardEvent(view()->GetWidget(), event); + unhandled_keyboard_handler_.HandleKeyboardEvent(event, + view()->GetFocusManager()); } /////////////////////////////////////////////////////////////////////////////// diff --git a/chrome/browser/chromeos/login/registration_screen.h b/chrome/browser/chromeos/login/registration_screen.h index b02bb0a..b610e02 100644 --- a/chrome/browser/chromeos/login/registration_screen.h +++ b/chrome/browser/chromeos/login/registration_screen.h @@ -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. @@ -14,6 +14,7 @@ #include "chrome/browser/chromeos/login/view_screen.h" #include "chrome/browser/chromeos/login/web_page_screen.h" #include "chrome/browser/chromeos/login/web_page_view.h" +#include "chrome/browser/ui/views/unhandled_keyboard_event_handler.h" class GURL; class Profile; @@ -91,6 +92,8 @@ class RegistrationScreen : public ViewScreen<RegistrationView>, // WebPageScreen implementation: virtual void CloseScreen(ScreenObserver::ExitCodes code) OVERRIDE; + UnhandledKeyboardEventHandler unhandled_keyboard_handler_; + DISALLOW_COPY_AND_ASSIGN(RegistrationScreen); }; diff --git a/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc b/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc index 336b218..1782625 100644 --- a/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc +++ b/chrome/browser/ui/omnibox/omnibox_view_browsertest.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. @@ -1334,79 +1334,3 @@ IN_PROC_BROWSER_TEST_F(OmniboxViewTest, FLAKY_PasteReplacingAll) { ASSERT_EQ(ASCIIToUTF16("abc"), omnibox_view->GetText()); } #endif - -// TODO(beng): enable on windows once it actually works. -// No need to run extra pure views tests on aura. -#if defined(TOOLKIT_VIEWS) && !defined(OS_WIN) && !defined(USE_AURA) -class OmniboxViewViewsTest : public OmniboxViewTest { - public: - OmniboxViewViewsTest() { - views::Widget::SetPureViews(true); - } -}; - -IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest, - FLAKY_BrowserAccelerators) { - BrowserAcceleratorsTest(); -} - -IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest, MAYBE_PopupAccelerators) { - PopupAcceleratorsTest(); -} - -IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest, BackspaceInKeywordMode) { - BackspaceInKeywordModeTest(); -} - -IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest, Escape) { - EscapeTest(); -} - -IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest, DesiredTLD) { - DesiredTLDTest(); -} - -IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest, AltEnter) { - AltEnterTest(); -} - -IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest, EnterToSearch) { - EnterToSearchTest(); -} - -IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest, EscapeToDefaultMatch) { - EscapeToDefaultMatchTest(); -} - -IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest, BasicTextOperations) { - BasicTextOperationsTest(); -} - -IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest, AcceptKeywordBySpace) { - AcceptKeywordBySpaceTest(); -} - -IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest, - NonSubstitutingKeywordTest) { - NonSubstitutingKeywordTest(); -} - -IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest, DeleteItem) { - DeleteItemTest(); -} - -IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest, TabMoveCursorToEnd) { - TabMoveCursorToEndTest(); -} - -IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest, - PersistKeywordModeOnTabSwitch) { - PersistKeywordModeOnTabSwitch(); -} - -IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest, - CtrlKeyPressedWithInlineAutocompleteTest) { - CtrlKeyPressedWithInlineAutocompleteTest(); -} - -#endif diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index b45a85a..4bee539 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc @@ -122,7 +122,6 @@ #include "ui/views/widget/native_widget_win.h" #elif defined(TOOLKIT_USES_GTK) #include "chrome/browser/ui/views/accelerator_table.h" -#include "chrome/browser/ui/views/handle_web_keyboard_event.h" #endif #if defined(OS_CHROMEOS) @@ -1285,13 +1284,8 @@ bool BrowserView::PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event, } void BrowserView::HandleKeyboardEvent(const NativeWebKeyboardEvent& event) { - // TODO(ben): figure out why are these two code paths so different -#if defined(TOOLKIT_USES_GTK) - HandleWebKeyboardEvent(GetWidget(), event); -#else unhandled_keyboard_event_handler_.HandleKeyboardEvent(event, GetFocusManager()); -#endif } // TODO(devint): http://b/issue?id=1117225 Cut, Copy, and Paste are always diff --git a/chrome/browser/ui/views/handle_web_keyboard_event.h b/chrome/browser/ui/views/handle_web_keyboard_event.h deleted file mode 100644 index c32fc2b..0000000 --- a/chrome/browser/ui/views/handle_web_keyboard_event.h +++ /dev/null @@ -1,18 +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 CHROME_BROWSER_UI_VIEWS_HANDLE_WEB_KEYBOARD_EVENT_H_ -#define CHROME_BROWSER_UI_VIEWS_HANDLE_WEB_KEYBOARD_EVENT_H_ -#pragma once - -namespace views { -class Widget; -} - -struct NativeWebKeyboardEvent; - -void HandleWebKeyboardEvent(views::Widget* widget, - const NativeWebKeyboardEvent& event); - -#endif // CHROME_BROWSER_UI_VIEWS_HANDLE_WEB_KEYBOARD_EVENT_H_ diff --git a/chrome/browser/ui/views/handle_web_keyboard_event_aura.cc b/chrome/browser/ui/views/handle_web_keyboard_event_aura.cc deleted file mode 100644 index 76795e0..0000000 --- a/chrome/browser/ui/views/handle_web_keyboard_event_aura.cc +++ /dev/null @@ -1,13 +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 "chrome/browser/ui/views/handle_web_keyboard_event.h" - -#include "ui/views/widget/widget.h" - -void HandleWebKeyboardEvent(views::Widget* widget, - const NativeWebKeyboardEvent& event) { - // TODO(saintlou): Handle event forwarding in Aura: crbug.com/99861. - NOTIMPLEMENTED(); -} diff --git a/chrome/browser/ui/views/handle_web_keyboard_event_gtk.cc b/chrome/browser/ui/views/handle_web_keyboard_event_gtk.cc deleted file mode 100644 index c20f873..0000000 --- a/chrome/browser/ui/views/handle_web_keyboard_event_gtk.cc +++ /dev/null @@ -1,17 +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 "chrome/browser/ui/views/handle_web_keyboard_event.h" - -#include "content/public/browser/native_web_keyboard_event.h" -#include "ui/views/widget/native_widget_gtk.h" - -void HandleWebKeyboardEvent(views::Widget* widget, - const NativeWebKeyboardEvent& event) { - if (widget && event.os_event && !event.skip_in_browser) { - views::KeyEvent views_event(reinterpret_cast<GdkEvent*>(event.os_event)); - static_cast<views::NativeWidgetGtk*>(widget->native_widget())-> - HandleKeyboardEvent(views_event); - } -} diff --git a/chrome/browser/ui/views/unhandled_keyboard_event_handler.cc b/chrome/browser/ui/views/unhandled_keyboard_event_handler.cc index fdf17e3..b89cb93 100644 --- a/chrome/browser/ui/views/unhandled_keyboard_event_handler.cc +++ b/chrome/browser/ui/views/unhandled_keyboard_event_handler.cc @@ -1,66 +1,8 @@ -// 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. #include "chrome/browser/ui/views/unhandled_keyboard_event_handler.h" -#include "base/logging.h" -#include "ui/views/focus/focus_manager.h" - -UnhandledKeyboardEventHandler::UnhandledKeyboardEventHandler() { - ignore_next_char_event_ = false; -} - UnhandledKeyboardEventHandler::~UnhandledKeyboardEventHandler() { } - -void UnhandledKeyboardEventHandler::HandleKeyboardEvent( - const NativeWebKeyboardEvent& event, - views::FocusManager* focus_manager) { - if (!focus_manager) { - NOTREACHED(); - return; - } - // Previous calls to TranslateMessage can generate Char events as well as - // RawKeyDown events, even if the latter triggered an accelerator. In these - // cases, we discard the Char events. - if (event.type == WebKit::WebInputEvent::Char && ignore_next_char_event_) { - ignore_next_char_event_ = false; - return; - } - // It's necessary to reset this flag, because a RawKeyDown event may not - // always generate a Char event. - ignore_next_char_event_ = false; - - if (event.type == WebKit::WebInputEvent::RawKeyDown) { - ui::Accelerator accelerator( - static_cast<ui::KeyboardCode>(event.windowsKeyCode), - (event.modifiers & NativeWebKeyboardEvent::ShiftKey) == - NativeWebKeyboardEvent::ShiftKey, - (event.modifiers & NativeWebKeyboardEvent::ControlKey) == - NativeWebKeyboardEvent::ControlKey, - (event.modifiers & NativeWebKeyboardEvent::AltKey) == - NativeWebKeyboardEvent::AltKey); - - // This is tricky: we want to set ignore_next_char_event_ if - // ProcessAccelerator returns true. But ProcessAccelerator might delete - // |this| if the accelerator is a "close tab" one. So we speculatively - // set the flag and fix it if no event was handled. - ignore_next_char_event_ = true; - - if (focus_manager->ProcessAccelerator(accelerator)) { - return; - } - - // ProcessAccelerator didn't handle the accelerator, so we know both - // that |this| is still valid, and that we didn't want to set the flag. - ignore_next_char_event_ = false; - } - -#if defined(OS_WIN) && !defined(USE_AURA) - // Any unhandled keyboard/character messages should be defproced. - // This allows stuff like F10, etc to work correctly. - DefWindowProc(event.os_event.hwnd, event.os_event.message, - event.os_event.wParam, event.os_event.lParam); -#endif -} diff --git a/chrome/browser/ui/views/unhandled_keyboard_event_handler.h b/chrome/browser/ui/views/unhandled_keyboard_event_handler.h index 41f1a84..dd04639 100644 --- a/chrome/browser/ui/views/unhandled_keyboard_event_handler.h +++ b/chrome/browser/ui/views/unhandled_keyboard_event_handler.h @@ -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. @@ -24,6 +24,7 @@ class UnhandledKeyboardEventHandler { views::FocusManager* focus_manager); private: +#if defined(OS_WIN) // Whether to ignore the next Char keyboard event. // If a RawKeyDown event was handled as a shortcut key, then we're done // handling it and should eat any Char event that the translate phase may @@ -31,6 +32,7 @@ class UnhandledKeyboardEventHandler { // such as a beep if DefWindowProc() has no default handling for the given // Char.) bool ignore_next_char_event_; +#endif DISALLOW_COPY_AND_ASSIGN(UnhandledKeyboardEventHandler); }; diff --git a/chrome/browser/ui/views/unhandled_keyboard_event_handler_aurax11.cc b/chrome/browser/ui/views/unhandled_keyboard_event_handler_aurax11.cc new file mode 100644 index 0000000..7fbfffe --- /dev/null +++ b/chrome/browser/ui/views/unhandled_keyboard_event_handler_aurax11.cc @@ -0,0 +1,29 @@ +// 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. + +#include "chrome/browser/ui/views/unhandled_keyboard_event_handler.h" + +#include "base/logging.h" +#include "content/public/browser/native_web_keyboard_event.h" +#include "ui/aura/event.h" +#include "ui/views/focus/focus_manager.h" + +UnhandledKeyboardEventHandler::UnhandledKeyboardEventHandler() { +} + +void UnhandledKeyboardEventHandler::HandleKeyboardEvent( + const NativeWebKeyboardEvent& event, + views::FocusManager* focus_manager) { + if (!focus_manager) { + NOTREACHED(); + return; + } + // A false char event may be sent to the renderer if the key + // event changed the focus. See crbug.com/108480. + if (event.os_event && !event.skip_in_browser && + !static_cast<aura::KeyEvent*>(event.os_event)->is_char()) { + views::KeyEvent views_event(event.os_event); + focus_manager->OnKeyEvent(views_event); + } +} diff --git a/chrome/browser/ui/views/unhandled_keyboard_event_handler_gtk.cc b/chrome/browser/ui/views/unhandled_keyboard_event_handler_gtk.cc new file mode 100644 index 0000000..2980d17 --- /dev/null +++ b/chrome/browser/ui/views/unhandled_keyboard_event_handler_gtk.cc @@ -0,0 +1,25 @@ +// 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. + +#include "chrome/browser/ui/views/unhandled_keyboard_event_handler.h" + +#include "base/logging.h" +#include "content/public/browser/native_web_keyboard_event.h" +#include "ui/views/focus/focus_manager.h" + +UnhandledKeyboardEventHandler::UnhandledKeyboardEventHandler() { +} + +void UnhandledKeyboardEventHandler::HandleKeyboardEvent( + const NativeWebKeyboardEvent& event, + views::FocusManager* focus_manager) { + if (!focus_manager) { + NOTREACHED(); + return; + } + if (event.os_event && !event.skip_in_browser) { + const views::KeyEvent views_event(event.os_event); + focus_manager->OnKeyEvent(views_event); + } +} diff --git a/chrome/browser/ui/views/unhandled_keyboard_event_handler_win.cc b/chrome/browser/ui/views/unhandled_keyboard_event_handler_win.cc new file mode 100644 index 0000000..8a6449e --- /dev/null +++ b/chrome/browser/ui/views/unhandled_keyboard_event_handler_win.cc @@ -0,0 +1,63 @@ +// 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. + +#include "chrome/browser/ui/views/unhandled_keyboard_event_handler.h" + +#include "base/logging.h" +#include "ui/views/focus/focus_manager.h" + +UnhandledKeyboardEventHandler::UnhandledKeyboardEventHandler() { + ignore_next_char_event_ = false; +} + +void UnhandledKeyboardEventHandler::HandleKeyboardEvent( + const NativeWebKeyboardEvent& event, + views::FocusManager* focus_manager) { + if (!focus_manager) { + NOTREACHED(); + return; + } + // Previous calls to TranslateMessage can generate Char events as well as + // RawKeyDown events, even if the latter triggered an accelerator. In these + // cases, we discard the Char events. + if (event.type == WebKit::WebInputEvent::Char && ignore_next_char_event_) { + ignore_next_char_event_ = false; + return; + } + // It's necessary to reset this flag, because a RawKeyDown event may not + // always generate a Char event. + ignore_next_char_event_ = false; + + if (event.type == WebKit::WebInputEvent::RawKeyDown) { + ui::Accelerator accelerator( + static_cast<ui::KeyboardCode>(event.windowsKeyCode), + (event.modifiers & NativeWebKeyboardEvent::ShiftKey) == + NativeWebKeyboardEvent::ShiftKey, + (event.modifiers & NativeWebKeyboardEvent::ControlKey) == + NativeWebKeyboardEvent::ControlKey, + (event.modifiers & NativeWebKeyboardEvent::AltKey) == + NativeWebKeyboardEvent::AltKey); + + // This is tricky: we want to set ignore_next_char_event_ if + // ProcessAccelerator returns true. But ProcessAccelerator might delete + // |this| if the accelerator is a "close tab" one. So we speculatively + // set the flag and fix it if no event was handled. + ignore_next_char_event_ = true; + + if (focus_manager->ProcessAccelerator(accelerator)) { + return; + } + + // ProcessAccelerator didn't handle the accelerator, so we know both + // that |this| is still valid, and that we didn't want to set the flag. + ignore_next_char_event_ = false; + } + +#if defined(OS_WIN) && !defined(USE_AURA) + // Any unhandled keyboard/character messages should be defproced. + // This allows stuff like F10, etc to work correctly. + DefWindowProc(event.os_event.hwnd, event.os_event.message, + event.os_event.wParam, event.os_event.lParam); +#endif +} diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index acb765b..3cb8f55 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -3527,9 +3527,6 @@ 'browser/ui/views/generic_info_view.h', 'browser/ui/views/global_error_bubble_view.cc', 'browser/ui/views/global_error_bubble_view.h', - 'browser/ui/views/handle_web_keyboard_event_aura.cc', - 'browser/ui/views/handle_web_keyboard_event_gtk.cc', - 'browser/ui/views/handle_web_keyboard_event.h', 'browser/ui/views/html_dialog_view.cc', 'browser/ui/views/html_dialog_view.h', 'browser/ui/views/hung_renderer_view.cc', @@ -3699,6 +3696,9 @@ 'browser/ui/views/toolbar_view.h', 'browser/ui/views/unhandled_keyboard_event_handler.cc', 'browser/ui/views/unhandled_keyboard_event_handler.h', + 'browser/ui/views/unhandled_keyboard_event_handler_aurax11.cc', + 'browser/ui/views/unhandled_keyboard_event_handler_gtk.cc', + 'browser/ui/views/unhandled_keyboard_event_handler_win.cc', 'browser/ui/views/uninstall_view.cc', 'browser/ui/views/uninstall_view.h', 'browser/ui/views/update_recommended_message_box.cc', @@ -4947,8 +4947,9 @@ ['include', '^browser/ui/views/fullscreen_exit_bubble_views.h'], ['include', '^browser/ui/views/global_error_bubble_view.cc'], ['include', '^browser/ui/views/global_error_bubble_view.h'], - ['include', '^browser/ui/views/handle_web_keyboard_event_gtk.cc'], - ['include', '^browser/ui/views/handle_web_keyboard_event.h'], + ['include', '^browser/ui/views/unhandled_keyboard_event_handler.cc'], + ['include', '^browser/ui/views/unhandled_keyboard_event_handler.h'], + ['include', '^browser/ui/views/unhandled_keyboard_event_handler_gtk.cc'], ['include', '^browser/ui/views/html_dialog_view.cc'], ['include', '^browser/ui/views/html_dialog_view.h'], ['include', '^browser/ui/views/infobars/*'], @@ -5048,8 +5049,6 @@ ['include', '^browser/ui/views/theme_background.h'], ['include', '^browser/ui/views/toolbar_view.cc'], ['include', '^browser/ui/views/toolbar_view.h'], - ['include', '^browser/ui/views/unhandled_keyboard_event_handler.cc'], - ['include', '^browser/ui/views/unhandled_keyboard_event_handler.h'], ['include', '^browser/ui/views/update_recommended_message_box.cc'], ['include', '^browser/ui/views/update_recommended_message_box.h'], ['include', '^browser/ui/views/web_intent_picker_view.cc'], @@ -5296,6 +5295,8 @@ ['include', '^browser/ui/views/importer/import_lock_dialog_view.cc'], ['include', '^browser/ui/views/native_constrained_window_aura.cc'], ['include', '^browser/ui/views/stubs_aura.cc'], + ['include', '^browser/ui/views/unhandled_keyboard_event_handler.cc'], + ['include', '^browser/ui/views/unhandled_keyboard_event_handler_aurax11.cc'], ], }], # Build Aura with ChromeOS. @@ -5318,8 +5319,6 @@ ['exclude', '^browser/chromeos/login/views_login_display_host.cc'], ['exclude', '^browser/chromeos/login/wizard_in_process_browser_test.cc'], ['exclude', '^browser/chromeos/notifications/'], - ['include', '^browser/ui/views/handle_web_keyboard_event_aura.cc'], - ['include', '^browser/ui/views/handle_web_keyboard_event.h'], ], }], [ 'use_openssl==1', { diff --git a/ui/views/focus/focus_manager.cc b/ui/views/focus/focus_manager.cc index d6d1c1e..4ec263c 100644 --- a/ui/views/focus/focus_manager.cc +++ b/ui/views/focus/focus_manager.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. @@ -26,6 +26,9 @@ FocusManager::FocusManager(Widget* widget) focused_view_(NULL), accelerator_manager_(new ui::AcceleratorManager), focus_change_reason_(kReasonDirectFocusChange), +#if defined(USE_X11) + should_handle_menu_key_release_(false), +#endif is_changing_focus_(false) { DCHECK(widget_); stored_focused_view_storage_id_ = @@ -36,6 +39,41 @@ FocusManager::~FocusManager() { } bool FocusManager::OnKeyEvent(const KeyEvent& event) { + const int key_code = event.key_code(); + +#if defined(USE_X11) + // TODO(ben): beng believes that this should be done in + // RootWindowHosLinux for aura/linux. + + // Always reset |should_handle_menu_key_release_| unless we are handling a + // VKEY_MENU key release event. It ensures that VKEY_MENU accelerator can only + // be activated when handling a VKEY_MENU key release event which is preceded + // by an un-handled VKEY_MENU key press event. + if (key_code != ui::VKEY_MENU || event.type() != ui::ET_KEY_RELEASED) + should_handle_menu_key_release_ = false; + + 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) { + should_handle_menu_key_release_ = true; + return false; + } + // Pass through to the reset 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 { + return false; + } +#else + if (event.type() != ui::ET_KEY_PRESSED) + return false; +#endif + #if defined(OS_WIN) // 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 @@ -64,7 +102,6 @@ bool FocusManager::OnKeyEvent(const KeyEvent& event) { #endif // Intercept arrow key messages to switch between grouped views. - ui::KeyboardCode key_code = event.key_code(); 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)) { @@ -254,6 +291,10 @@ void FocusManager::ClearFocus() { } void FocusManager::StoreFocusedView() { +#if defined(USE_X11) + // Forget menu key state when the window lost focus. + should_handle_menu_key_release_ = false; +#endif ViewStorage* view_storage = ViewStorage::GetInstance(); if (!view_storage) { // This should never happen but bug 981648 seems to indicate it could. @@ -287,6 +328,9 @@ void FocusManager::StoreFocusedView() { } void FocusManager::RestoreFocusedView() { +#if defined(USE_X11) + DCHECK(!should_handle_menu_key_release_); +#endif ViewStorage* view_storage = ViewStorage::GetInstance(); if (!view_storage) { // This should never happen but bug 981648 seems to indicate it could. @@ -378,6 +422,23 @@ bool FocusManager::ProcessAccelerator(const ui::Accelerator& accelerator) { return accelerator_manager_->Process(accelerator); } +void FocusManager::MaybeResetMenuKeyState(const KeyEvent& key) { +#if defined(USE_X11) + // Always reset |should_handle_menu_key_release_| unless we are handling a + // VKEY_MENU key release event. It ensures that VKEY_MENU accelerator can only + // be activated when handling a VKEY_MENU key release event which is preceded + // by an unhandled VKEY_MENU key press event. See also HandleKeyboardEvent(). + if (key.key_code() != ui::VKEY_MENU || key.type() != ui::ET_KEY_RELEASED) + should_handle_menu_key_release_ = false; +#endif +} + +#if defined(TOOLKIT_USES_GTK) +void FocusManager::ResetMenuKeyState() { + should_handle_menu_key_release_ = false; +} +#endif + ui::AcceleratorTarget* FocusManager::GetCurrentTargetForAccelerator( const ui::Accelerator& accelerator) const { return accelerator_manager_->GetCurrentTarget(accelerator); diff --git a/ui/views/focus/focus_manager.h b/ui/views/focus/focus_manager.h index 0cb4671..1f45bc8 100644 --- a/ui/views/focus/focus_manager.h +++ b/ui/views/focus/focus_manager.h @@ -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. @@ -213,6 +213,15 @@ class VIEWS_EXPORT FocusManager { // Returns true if an accelerator was activated. bool ProcessAccelerator(const ui::Accelerator& accelerator); + // Resets menu key state if |event| is not menu key release. + // This is effective only on x11. + void MaybeResetMenuKeyState(const KeyEvent& key); + +#if defined(TOOLKIT_USES_GTK) + // Resets menu key state. TODO(oshima): Remove this when views/gtk is removed. + void ResetMenuKeyState(); +#endif + // 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 @@ -269,6 +278,11 @@ class VIEWS_EXPORT FocusManager { // The list of registered FocusChange listeners. ObserverList<FocusChangeListener, true> focus_change_listeners_; +#if defined(USE_X11) + // Indicates if we should handle the upcoming Alt key release event. + bool should_handle_menu_key_release_; +#endif + // See description above getter. bool is_changing_focus_; diff --git a/ui/views/widget/native_widget_aura.cc b/ui/views/widget/native_widget_aura.cc index b314228..2c5c2c1 100644 --- a/ui/views/widget/native_widget_aura.cc +++ b/ui/views/widget/native_widget_aura.cc @@ -129,9 +129,6 @@ NativeWidgetAura::NativeWidgetAura(internal::NativeWidgetDelegate* delegate) ownership_(Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET), ALLOW_THIS_IN_INITIALIZER_LIST(close_widget_factory_(this)), can_activate_(true), -#if defined(USE_X11) - should_handle_menu_key_release_(false), -#endif cursor_(gfx::kNullCursor), saved_window_state_(ui::SHOW_STATE_DEFAULT) { } @@ -589,42 +586,12 @@ void NativeWidgetAura::SetVisibilityChangedAnimationsEnabled(bool value) { // NativeWidgetAura, views::InputMethodDelegate implementation: void NativeWidgetAura::DispatchKeyEventPostIME(const KeyEvent& key) { - if (delegate_->OnKeyEvent(key) || !GetWidget()->GetFocusManager()) + FocusManager* focus_manager = GetWidget()->GetFocusManager(); + if (focus_manager) + focus_manager->MaybeResetMenuKeyState(key); + if (delegate_->OnKeyEvent(key) || !focus_manager) return; - -#if defined(USE_X11) - // TODO(oshima): This is copied from native_widget_gtk for now. - // RenderWidgetHostViewAura doesn't work and needs more work. - // oshima thinks this should be moved to focus manager (see - // crbug.com/106998), but beng believes that this should be done - // in RootWindowHosLinux for aura/linux. - const int key_code = key.key_code(); - - // Always reset |should_handle_menu_key_release_| unless we are handling a - // VKEY_MENU key release event. It ensures that VKEY_MENU accelerator can only - // be activated when handling a VKEY_MENU key release event which is preceded - // by an un-handled VKEY_MENU key press event. - if (key_code != ui::VKEY_MENU || key.type() != ui::ET_KEY_RELEASED) - should_handle_menu_key_release_ = false; - - if (key.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) - GetWidget()->GetFocusManager()->OnKeyEvent(key); - else - should_handle_menu_key_release_ = true; - } else if (key_code == ui::VKEY_MENU && should_handle_menu_key_release_ && - (key.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); - GetWidget()->GetFocusManager()->ProcessAccelerator(accelerator); - } -#else - if (key.type() == ui::ET_KEY_PRESSED) - GetWidget()->GetFocusManager()->OnKeyEvent(key); -#endif + focus_manager->OnKeyEvent(key); } //////////////////////////////////////////////////////////////////////////////// @@ -643,9 +610,6 @@ void NativeWidgetAura::OnBoundsChanged(const gfx::Rect& old_bounds, } void NativeWidgetAura::OnFocus() { -#if defined(USE_X11) - should_handle_menu_key_release_ = false; -#endif Widget* widget = GetWidget(); if (widget->is_top_level()) { InputMethod* input_method = widget->GetInputMethod(); diff --git a/ui/views/widget/native_widget_aura.h b/ui/views/widget/native_widget_aura.h index c026715..a4eb003 100644 --- a/ui/views/widget/native_widget_aura.h +++ b/ui/views/widget/native_widget_aura.h @@ -174,11 +174,6 @@ class VIEWS_EXPORT NativeWidgetAura : public internal::NativeWidgetPrivate, // Can we be made active? bool can_activate_; -#if defined(USE_X11) - // Indicates if we should handle the upcoming Alt key release event. - bool should_handle_menu_key_release_; -#endif - gfx::NativeCursor cursor_; // The saved window state for exiting full screen state. diff --git a/ui/views/widget/native_widget_gtk.cc b/ui/views/widget/native_widget_gtk.cc index 772d780..7471ae7 100644 --- a/ui/views/widget/native_widget_gtk.cc +++ b/ui/views/widget/native_widget_gtk.cc @@ -355,7 +355,6 @@ NativeWidgetGtk::NativeWidgetGtk(internal::NativeWidgetDelegate* delegate) has_focus_(false), always_on_top_(false), is_double_buffered_(false), - should_handle_menu_key_release_(false), dragged_view_(NULL), painted_(false), has_pointer_grab_(false), @@ -562,33 +561,7 @@ void NativeWidgetGtk::ActiveWindowChanged(GdkWindow* active_window) { bool NativeWidgetGtk::HandleKeyboardEvent(const KeyEvent& key) { if (!GetWidget()->GetFocusManager()) return false; - - const int key_code = key.key_code(); - bool handled = false; - - // Always reset |should_handle_menu_key_release_| unless we are handling a - // VKEY_MENU key release event. It ensures that VKEY_MENU accelerator can only - // be activated when handling a VKEY_MENU key release event which is preceded - // by an un-handled VKEY_MENU key press event. - if (key_code != ui::VKEY_MENU || key.type() != ui::ET_KEY_RELEASED) - should_handle_menu_key_release_ = false; - - if (key.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) - handled = !GetWidget()->GetFocusManager()->OnKeyEvent(key); - else - should_handle_menu_key_release_ = true; - } else if (key_code == ui::VKEY_MENU && should_handle_menu_key_release_ && - (key.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); - handled = GetWidget()->GetFocusManager()->ProcessAccelerator(accelerator); - } - - return handled; + return GetWidget()->GetFocusManager()->OnKeyEvent(key); } bool NativeWidgetGtk::SuppressFreezeUpdates() { @@ -1606,18 +1579,22 @@ gboolean NativeWidgetGtk::OnScroll(GtkWidget* widget, GdkEventScroll* event) { return delegate_->OnMouseEvent(mouse_event); } -gboolean NativeWidgetGtk::OnFocusIn(GtkWidget* widget, GdkEventFocus* event) { +gboolean NativeWidgetGtk::OnFocusIn(GtkWidget* gtk_widget, + GdkEventFocus* event) { if (has_focus_) return false; // This is the second focus-in event in a row, ignore it. has_focus_ = true; - should_handle_menu_key_release_ = false; + Widget* widget = GetWidget(); - if (!GetWidget()->is_top_level()) + if (widget->GetFocusManager()) + widget->GetFocusManager()->ResetMenuKeyState(); + + if (!widget->is_top_level()) return false; // Only top-level Widget should have an InputMethod instance. - InputMethod* input_method = GetWidget()->GetInputMethod(); + InputMethod* input_method = widget->GetInputMethod(); if (input_method) input_method->OnFocus(); @@ -1627,7 +1604,7 @@ gboolean NativeWidgetGtk::OnFocusIn(GtkWidget* widget, GdkEventFocus* event) { // Sets initial focus here. On X11/Gtk, window creation // is asynchronous and a focus request has to be made after a window // gets created. - GetWidget()->SetInitialFocus(); + widget->SetInitialFocus(); } return false; } @@ -1772,12 +1749,8 @@ void NativeWidgetGtk::ScheduleDraw() { } void NativeWidgetGtk::DispatchKeyEventPostIME(const KeyEvent& key) { - // Always reset |should_handle_menu_key_release_| unless we are handling a - // VKEY_MENU key release event. It ensures that VKEY_MENU accelerator can only - // be activated when handling a VKEY_MENU key release event which is preceded - // by an unhandled VKEY_MENU key press event. See also HandleKeyboardEvent(). - if (key.key_code() != ui::VKEY_MENU || key.type() != ui::ET_KEY_RELEASED) - should_handle_menu_key_release_ = false; + if (GetWidget()->GetFocusManager()) + GetWidget()->GetFocusManager()->MaybeResetMenuKeyState(key); // Send the key event to View hierarchy first. bool handled = delegate_->OnKeyEvent(key); diff --git a/ui/views/widget/native_widget_gtk.h b/ui/views/widget/native_widget_gtk.h index d3437d4..dd0f8d7 100644 --- a/ui/views/widget/native_widget_gtk.h +++ b/ui/views/widget/native_widget_gtk.h @@ -441,9 +441,6 @@ class VIEWS_EXPORT NativeWidgetGtk : public internal::NativeWidgetPrivate, // This is false by default. bool is_double_buffered_; - // Indicates if we should handle the upcoming Alt key release event. - bool should_handle_menu_key_release_; - // Valid for the lifetime of StartDragForViewFromMouseEvent, indicates the // view the drag started from. View* dragged_view_; |