summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorananta@chromium.org <ananta@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-12 20:38:49 +0000
committerananta@chromium.org <ananta@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-12 20:38:49 +0000
commit3f70c1e17d42cccd53e1b827d239c86d1ed701da (patch)
treed1af746656d76471d38ae178375debdcb0a686ae
parentab8089b5a8442d10b85fd12b40b8771c86c81b8d (diff)
downloadchromium_src-3f70c1e17d42cccd53e1b827d239c86d1ed701da.zip
chromium_src-3f70c1e17d42cccd53e1b827d239c86d1ed701da.tar.gz
chromium_src-3f70c1e17d42cccd53e1b827d239c86d1ed701da.tar.bz2
Unhandled keyboard messages coming back from the host browser running ChromeFrame need to process
accelerators. Currently accelerators are processed by the focus manager. We already have code in browser_view to process unhandled keyboard messages coming back from the renderer. Moved this code to a new class UnhandledKeyboardEventHandler which maintains state about whether the next character event has to be ignored, etc. This class is now used by BrowserView and the ExternalTabContainer to process unhandled keyboard messages. To support accelerators in ChromeFrame, the ExternalTabContainer needs to implement an Accelerator target. I also added a minimal accelerator table for Chromeframe in the chrome_dll.rc and chrome_dll_resource.h files. This fixes bug http://code.google.com/p/chromium/issues/detail?id=31672 Bug=31672 Review URL: http://codereview.chromium.org/536023 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@36037 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/app/chrome_dll.rc13
-rw-r--r--chrome/app/chrome_dll_resource.h1
-rw-r--r--chrome/browser/external_tab_container.cc85
-rw-r--r--chrome/browser/external_tab_container.h15
-rw-r--r--chrome/browser/views/frame/browser_view.cc55
-rw-r--r--chrome/browser/views/frame/browser_view.h11
-rw-r--r--chrome/browser/views/unhandled_keyboard_event_handler.cc75
-rw-r--r--chrome/browser/views/unhandled_keyboard_event_handler.h39
-rwxr-xr-xchrome/chrome_browser.gypi4
9 files changed, 235 insertions, 63 deletions
diff --git a/chrome/app/chrome_dll.rc b/chrome/app/chrome_dll.rc
index 1e6d185..57c2f50 100644
--- a/chrome/app/chrome_dll.rc
+++ b/chrome/app/chrome_dll.rc
@@ -137,6 +137,19 @@ BEGIN
VK_ADD, IDC_ZOOM_PLUS, VIRTKEY, CONTROL
END
+IDR_CHROMEFRAME ACCELERATORS
+BEGIN
+ "I", IDC_DEV_TOOLS, VIRTKEY, CONTROL, SHIFT
+ "J", IDC_DEV_TOOLS_CONSOLE, VIRTKEY, CONTROL, SHIFT
+ VK_OEM_MINUS, IDC_ZOOM_MINUS, VIRTKEY, CONTROL
+ VK_OEM_MINUS, IDC_ZOOM_MINUS, VIRTKEY, CONTROL, SHIFT
+ VK_SUBTRACT, IDC_ZOOM_MINUS, VIRTKEY, CONTROL
+ "0", IDC_ZOOM_NORMAL, VIRTKEY, CONTROL
+ VK_NUMPAD0, IDC_ZOOM_NORMAL, VIRTKEY, CONTROL
+ VK_OEM_PLUS, IDC_ZOOM_PLUS, VIRTKEY, CONTROL
+ VK_OEM_PLUS, IDC_ZOOM_PLUS, VIRTKEY, CONTROL, SHIFT
+ VK_ADD, IDC_ZOOM_PLUS, VIRTKEY, CONTROL
+END
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/app/chrome_dll_resource.h b/chrome/app/chrome_dll_resource.h
index df8ed80..d0eb82f 100644
--- a/chrome/app/chrome_dll_resource.h
+++ b/chrome/app/chrome_dll_resource.h
@@ -11,6 +11,7 @@
//
#define IDR_MAINFRAME 101
+#define IDR_CHROMEFRAME 200
#define IDI_THROBBER_01 102
#define IDI_THROBBER_02 103
diff --git a/chrome/browser/external_tab_container.cc b/chrome/browser/external_tab_container.cc
index 153c5f9a..26da69f 100644
--- a/chrome/browser/external_tab_container.cc
+++ b/chrome/browser/external_tab_container.cc
@@ -10,6 +10,7 @@
#include "app/win_util.h"
#include "base/logging.h"
#include "base/win_util.h"
+#include "chrome/app/chrome_dll_resource.h"
#include "chrome/browser/automation/automation_provider.h"
#include "chrome/browser/automation/automation_extension_function.h"
#include "chrome/browser/browser_window.h"
@@ -25,6 +26,7 @@
#include "chrome/browser/views/tab_contents/tab_contents_container.h"
#include "chrome/common/bindings_policy.h"
#include "chrome/common/chrome_constants.h"
+#include "chrome/common/native_web_keyboard_event.h"
#include "chrome/common/notification_service.h"
#include "chrome/test/automation/automation_messages.h"
#include "grit/generated_resources.h"
@@ -149,6 +151,7 @@ bool ExternalTabContainer::Init(Profile* profile,
disabled_context_menu_ids_.push_back(
IDS_CONTENT_CONTEXT_OPENLINKOFFTHERECORD);
+ LoadAccelerators();
return true;
}
@@ -173,6 +176,11 @@ void ExternalTabContainer::Uninitialize() {
tab_contents_ = NULL;
}
+ views::FocusManager* focus_manager = GetFocusManager();
+ if (focus_manager) {
+ focus_manager->UnregisterAccelerators(this);
+ }
+
request_context_ = NULL;
}
@@ -216,7 +224,10 @@ void ExternalTabContainer::SetTabHandle(int handle) {
}
void ExternalTabContainer::ProcessUnhandledAccelerator(const MSG& msg) {
- DefWindowProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
+ NativeWebKeyboardEvent keyboard_event(msg.hwnd, msg.message, msg.wParam,
+ msg.lParam);
+ unhandled_keyboard_event_handler_.HandleKeyboardEvent(keyboard_event,
+ GetFocusManager());
}
void ExternalTabContainer::FocusThroughTabTraversal(bool reverse) {
@@ -713,6 +724,43 @@ views::Window* ExternalTabContainer::GetWindow() {
return NULL;
}
+bool ExternalTabContainer::AcceleratorPressed(
+ const views::Accelerator& accelerator) {
+ std::map<views::Accelerator, int>::const_iterator iter =
+ accelerator_table_.find(accelerator);
+ DCHECK(iter != accelerator_table_.end());
+
+ if (!tab_contents_ || !tab_contents_->render_view_host()) {
+ NOTREACHED();
+ return false;
+ }
+
+ int command_id = iter->second;
+ switch (command_id) {
+ case IDC_ZOOM_PLUS:
+ tab_contents_->render_view_host()->Zoom(PageZoom::ZOOM_IN);
+ break;
+ case IDC_ZOOM_NORMAL:
+ tab_contents_->render_view_host()->Zoom(PageZoom::RESET);
+ break;
+ case IDC_ZOOM_MINUS:
+ tab_contents_->render_view_host()->Zoom(PageZoom::ZOOM_OUT);
+ break;
+ case IDC_DEV_TOOLS:
+ DevToolsManager::GetInstance()->ToggleDevToolsWindow(
+ tab_contents_->render_view_host(), false);
+ break;
+ case IDC_DEV_TOOLS_CONSOLE:
+ DevToolsManager::GetInstance()->ToggleDevToolsWindow(
+ tab_contents_->render_view_host(), true);
+ break;
+ default:
+ NOTREACHED() << "Unsupported accelerator: " << command_id;
+ return false;
+ }
+ return true;
+}
+
void ExternalTabContainer::Navigate(const GURL& url, const GURL& referrer) {
if (!tab_contents_) {
NOTREACHED();
@@ -743,3 +791,38 @@ void ExternalTabContainer::InitializeAutomationRequestContext(
DCHECK(request_context_.get() != NULL);
tab_contents_->set_request_context(request_context_.get());
}
+
+void ExternalTabContainer::LoadAccelerators() {
+ HACCEL accelerator_table = AtlLoadAccelerators(IDR_CHROMEFRAME);
+ DCHECK(accelerator_table);
+
+ // We have to copy the table to access its contents.
+ int count = CopyAcceleratorTable(accelerator_table, 0, 0);
+ if (count == 0) {
+ // Nothing to do in that case.
+ return;
+ }
+
+ scoped_ptr<ACCEL> scoped_accelerators(new ACCEL[count]);
+ ACCEL* accelerators = scoped_accelerators.get();
+ DCHECK(accelerators != NULL);
+
+ CopyAcceleratorTable(accelerator_table, accelerators, count);
+
+ views::FocusManager* focus_manager = GetFocusManager();
+ DCHECK(focus_manager);
+
+ // Let's fill our own accelerator table.
+ for (int i = 0; i < count; ++i) {
+ bool alt_down = (accelerators[i].fVirt & FALT) == FALT;
+ bool ctrl_down = (accelerators[i].fVirt & FCONTROL) == FCONTROL;
+ bool shift_down = (accelerators[i].fVirt & FSHIFT) == FSHIFT;
+ views::Accelerator accelerator(
+ static_cast<base::KeyboardCode>(accelerators[i].key),
+ shift_down, ctrl_down, alt_down);
+ accelerator_table_[accelerator] = accelerators[i].cmd;
+
+ // Also register with the focus manager.
+ focus_manager->RegisterAccelerator(accelerator, this);
+ }
+}
diff --git a/chrome/browser/external_tab_container.h b/chrome/browser/external_tab_container.h
index 7388177..698d15b 100644
--- a/chrome/browser/external_tab_container.h
+++ b/chrome/browser/external_tab_container.h
@@ -13,9 +13,11 @@
#include "chrome/browser/browser.h"
#include "chrome/browser/net/chrome_url_request_context.h"
#include "chrome/browser/tab_contents/tab_contents_delegate.h"
+#include "chrome/browser/views/unhandled_keyboard_event_handler.h"
#include "chrome/common/navigation_types.h"
#include "chrome/common/notification_observer.h"
#include "chrome/common/notification_registrar.h"
+#include "views/accelerator.h"
#include "views/widget/widget_win.h"
class AutomationProvider;
@@ -34,7 +36,8 @@ struct NavigationInfo;
class ExternalTabContainer : public TabContentsDelegate,
public NotificationObserver,
public views::WidgetWin,
- public base::RefCounted<ExternalTabContainer> {
+ public base::RefCounted<ExternalTabContainer>,
+ public views::AcceleratorTarget {
public:
typedef std::map<intptr_t, scoped_refptr<ExternalTabContainer> > PendingTabs;
@@ -169,6 +172,9 @@ class ExternalTabContainer : public TabContentsDelegate,
// Overridden from views::WidgetWin:
virtual views::Window* GetWindow();
+ // Handles the specified |accelerator| being pressed.
+ bool AcceleratorPressed(const views::Accelerator& accelerator);
+
protected:
// Overridden from views::WidgetWin:
virtual LRESULT OnCreate(LPCREATESTRUCT create_struct);
@@ -193,6 +199,8 @@ class ExternalTabContainer : public TabContentsDelegate,
bool ProcessUnhandledKeyStroke(HWND window, UINT message, WPARAM wparam,
LPARAM lparam);
+ void LoadAccelerators();
+
TabContents* tab_contents_;
scoped_refptr<AutomationProvider> automation_;
@@ -239,6 +247,11 @@ class ExternalTabContainer : public TabContentsDelegate,
// The URL request context to be used for this tab. Can be NULL.
scoped_refptr<ChromeURLRequestContextGetter> request_context_;
+ UnhandledKeyboardEventHandler unhandled_keyboard_event_handler_;
+
+ // A mapping between accelerators and commands.
+ std::map<views::Accelerator, int> accelerator_table_;
+
DISALLOW_COPY_AND_ASSIGN(ExternalTabContainer);
};
diff --git a/chrome/browser/views/frame/browser_view.cc b/chrome/browser/views/frame/browser_view.cc
index 197ac7c..b03129e 100644
--- a/chrome/browser/views/frame/browser_view.cc
+++ b/chrome/browser/views/frame/browser_view.cc
@@ -421,7 +421,6 @@ BrowserView::BrowserView(Browser* browser)
#if defined(OS_WIN)
hung_window_detector_(&hung_plugin_action_),
ticker_(0),
- ignore_next_char_event_(false),
#endif
extension_shelf_(NULL),
last_focused_view_storage_id_(
@@ -1234,58 +1233,8 @@ bool BrowserView::PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event,
}
void BrowserView::HandleKeyboardEvent(const NativeWebKeyboardEvent& event) {
-#if defined(OS_WIN)
- // 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;
-#endif
-
- if (event.type == WebKit::WebInputEvent::RawKeyDown) {
- views::FocusManager* focus_manager = GetFocusManager();
- DCHECK(focus_manager);
-
- views::Accelerator accelerator(
- static_cast<base::KeyboardCode>(event.windowsKeyCode),
- (event.modifiers & NativeWebKeyboardEvent::ShiftKey) ==
- NativeWebKeyboardEvent::ShiftKey,
- (event.modifiers & NativeWebKeyboardEvent::ControlKey) ==
- NativeWebKeyboardEvent::ControlKey,
- (event.modifiers & NativeWebKeyboardEvent::AltKey) ==
- NativeWebKeyboardEvent::AltKey);
-
-#if defined(OS_WIN)
- // 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;
-#endif
-
- if (focus_manager->ProcessAccelerator(accelerator)) {
- // DANGER: |this| could be deleted now!
- return;
- }
-
-#if defined(OS_WIN)
- // 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;
-#endif
- }
-
-#if defined(OS_WIN)
- // 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
+ unhandled_keyboard_event_handler_.HandleKeyboardEvent(event,
+ GetFocusManager());
}
#if defined(TOOLKIT_VIEWS)
diff --git a/chrome/browser/views/frame/browser_view.h b/chrome/browser/views/frame/browser_view.h
index d06c388..651e9c7 100644
--- a/chrome/browser/views/frame/browser_view.h
+++ b/chrome/browser/views/frame/browser_view.h
@@ -19,6 +19,7 @@
#include "chrome/browser/tabs/tab_strip_model.h"
#include "chrome/browser/views/frame/browser_frame.h"
#include "chrome/browser/views/tabs/tab_strip.h"
+#include "chrome/browser/views/unhandled_keyboard_event_handler.h"
#include "views/window/client_view.h"
#include "views/window/window_delegate.h"
@@ -537,14 +538,6 @@ class BrowserView : public BrowserWindow,
// The custom JumpList for Windows 7.
scoped_ptr<JumpList> jumplist_;
-
- // 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
- // have produced from it. (Handling this event may cause undesirable effects,
- // such as a beep if DefWindowProc() has no default handling for the given
- // Char.)
- bool ignore_next_char_event_;
#endif
// The timer used to update frames for the Loading Animation.
@@ -564,6 +557,8 @@ class BrowserView : public BrowserWindow,
// Last focused view that issued a tab traversal.
int last_focused_view_storage_id_;
+ UnhandledKeyboardEventHandler unhandled_keyboard_event_handler_;
+
DISALLOW_COPY_AND_ASSIGN(BrowserView);
};
diff --git a/chrome/browser/views/unhandled_keyboard_event_handler.cc b/chrome/browser/views/unhandled_keyboard_event_handler.cc
new file mode 100644
index 0000000..cc29354
--- /dev/null
+++ b/chrome/browser/views/unhandled_keyboard_event_handler.cc
@@ -0,0 +1,75 @@
+// Copyright (c) 2010 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/views/unhandled_keyboard_event_handler.h"
+
+#include "base/logging.h"
+#include "views/focus/focus_manager.h"
+
+UnhandledKeyboardEventHandler::UnhandledKeyboardEventHandler() {
+#if defined(OS_WIN)
+ ignore_next_char_event_ = false;
+#endif
+}
+
+UnhandledKeyboardEventHandler::~UnhandledKeyboardEventHandler() {
+}
+
+void UnhandledKeyboardEventHandler::HandleKeyboardEvent(
+ const NativeWebKeyboardEvent& event,
+ views::FocusManager* focus_manager) {
+ if (!focus_manager) {
+ NOTREACHED();
+ return;
+ }
+#if defined(OS_WIN)
+ // 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;
+#endif
+
+ if (event.type == WebKit::WebInputEvent::RawKeyDown) {
+ views::Accelerator accelerator(
+ static_cast<base::KeyboardCode>(event.windowsKeyCode),
+ (event.modifiers & NativeWebKeyboardEvent::ShiftKey) ==
+ NativeWebKeyboardEvent::ShiftKey,
+ (event.modifiers & NativeWebKeyboardEvent::ControlKey) ==
+ NativeWebKeyboardEvent::ControlKey,
+ (event.modifiers & NativeWebKeyboardEvent::AltKey) ==
+ NativeWebKeyboardEvent::AltKey);
+
+#if defined(OS_WIN)
+ // 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;
+#endif
+
+ if (focus_manager->ProcessAccelerator(accelerator)) {
+ return;
+ }
+
+#if defined(OS_WIN)
+ // 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;
+#endif
+ }
+
+#if defined(OS_WIN)
+ // 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/views/unhandled_keyboard_event_handler.h b/chrome/browser/views/unhandled_keyboard_event_handler.h
new file mode 100644
index 0000000..4873bcd
--- /dev/null
+++ b/chrome/browser/views/unhandled_keyboard_event_handler.h
@@ -0,0 +1,39 @@
+// Copyright (c) 2006-2010 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_VIEWS_UNHANDLED_KEYBOARD_EVENT_HANDLER_H_
+#define CHROME_BROWSER_VIEWS_UNHANDLED_KEYBOARD_EVENT_HANDLER_H_
+
+#include "views/view.h"
+#include "chrome/common/native_web_keyboard_event.h"
+
+namespace views {
+class FocusManager;
+} // namespace views
+
+// This class handles unhandled keyboard messages coming back from the renderer
+// process.
+class UnhandledKeyboardEventHandler {
+ public:
+ UnhandledKeyboardEventHandler();
+ ~UnhandledKeyboardEventHandler();
+
+ void HandleKeyboardEvent(const NativeWebKeyboardEvent& event,
+ 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
+ // have produced from it. (Handling this event may cause undesirable effects,
+ // 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);
+};
+
+#endif // CHROME_BROWSER_VIEWS_UNHANDLED_KEYBOARD_EVENT_HANDLER_H_
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 643bca7..d3e488b 100755
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1847,6 +1847,8 @@
'browser/views/uninstall_view.h',
'browser/views/url_picker.cc',
'browser/views/url_picker.h',
+ 'browser/views/unhandled_keyboard_event_handler.cc',
+ 'browser/views/unhandled_keyboard_event_handler.h',
'browser/views/user_data_dir_dialog.cc',
'browser/views/user_data_dir_dialog.h',
'browser/visitedlink_master.cc',
@@ -2288,6 +2290,8 @@
['include', '^browser/views/theme_background.h'],
['include', '^browser/views/toolbar_view.cc'],
['include', '^browser/views/toolbar_view.h'],
+ ['include', '^browser/views/unhandled_keyboard_event_handler.cc'],
+ ['include', '^browser/views/unhandled_keyboard_event_handler.h'],
['include', '^browser/window_sizer.cc'],
['include', '^browser/window_sizer.h'],