summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorfinnur@chromium.org <finnur@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-08 09:53:29 +0000
committerfinnur@chromium.org <finnur@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-08 09:53:29 +0000
commit5188dca135b28af1bfe2ac2d562fe8c42a86e795 (patch)
tree2de29d809c8b8c24bf9b7a556d921f8a30bc4fd1
parentc29c63a69ce698dc756ce155f90c1341a1303ba6 (diff)
downloadchromium_src-5188dca135b28af1bfe2ac2d562fe8c42a86e795.zip
chromium_src-5188dca135b28af1bfe2ac2d562fe8c42a86e795.tar.gz
chromium_src-5188dca135b28af1bfe2ac2d562fe8c42a86e795.tar.bz2
Config UI for Extension Commands (part 1).
This changes the current overlay so that input is possible (selecting which keyboard shortcut to use). It also suspends current Chrome keyboard handling (Views only), while capturing the shortcut, so that you can press ie. Ctrl-F without Chrome eating your keyboard assignment and instead showing the Find box. NOTE: This does not persist the user's choice (future changelist). BUG=121420 TEST=With a keybinding Extension installed, open chrome://extensions, click on Configure Commands, and notice that the shortcuts are listed in text boxes that are clickable and accept keyboard input. Review URL: https://chromiumcodereview.appspot.com/10514003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@141189 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/app/generated_resources.grd3
-rw-r--r--chrome/app/theme/theme_resources.grd1
-rw-r--r--chrome/browser/extensions/api/commands/command_service.h2
-rw-r--r--chrome/browser/extensions/extension_keybinding_registry.h4
-rw-r--r--chrome/browser/resources/extensions/extension_command_list.js184
-rw-r--r--chrome/browser/resources/extensions/extension_commands_overlay.css50
-rw-r--r--chrome/browser/resources/extensions/extension_commands_overlay.html11
-rw-r--r--chrome/browser/ui/gtk/extensions/extension_keybinding_registry_gtk.cc7
-rw-r--r--chrome/browser/ui/views/extensions/extension_keybinding_registry_views.cc7
-rw-r--r--chrome/browser/ui/views/frame/browser_view.cc3
-rw-r--r--chrome/browser/ui/webui/extensions/command_handler.cc27
-rw-r--r--chrome/browser/ui/webui/extensions/command_handler.h8
-rw-r--r--ui/views/focus/focus_manager.cc5
-rw-r--r--ui/views/focus/focus_manager.h10
14 files changed, 309 insertions, 13 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 9084547..b142717 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -4693,6 +4693,9 @@ Update checks have repeatedly failed for the extension "<ph name="EXTENSION_NAME
<message name="IDS_EXTENSION_COMMANDS_INACTIVE" desc="The text shown instead of the shortcut text (Ctrl+F) if the shortcut is inactive.">
Not set
</message>
+ <message name="IDS_EXTENSION_TYPE_SHORTCUT" desc="The text shown in a text box to instruct the user to start typing (to capture which shortcut to use for the extension command).">
+ Type a shortcut
+ </message>
<message name="IDS_EXTENSION_COMMANDS_GENERIC_ACTIVATE" desc="The generic 'activate extension' text used as description for some commands">
Activate the extension
</message>
diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd
index bf9f673..a29e246 100644
--- a/chrome/app/theme/theme_resources.grd
+++ b/chrome/app/theme/theme_resources.grd
@@ -101,6 +101,7 @@
<include name="IDR_DOWNLOAD_PROGRESS_BACKGROUND_32" file="default_100_percent/download_progress_background32.png" type="BINDATA" />
<include name="IDR_DOWNLOAD_PROGRESS_FOREGROUND_16" file="default_100_percent/download_progress_foreground16.png" type="BINDATA" />
<include name="IDR_DOWNLOAD_PROGRESS_FOREGROUND_32" file="default_100_percent/download_progress_foreground32.png" type="BINDATA" />
+ <include name="IDR_EXTENSION_COMMAND_CLOSE" file="default_100_percent/extension_command_close.png" type="BINDATA" />
<include name="IDR_EXTENSION_DEFAULT_ICON" file="default_100_percent/extension_default_icon.png" type="BINDATA" />
<include name="IDR_EXTENSIONS_FAVICON" file="default_100_percent/plugin.png" type="BINDATA" />
<include name="IDR_EXTENSIONS_RATING_STAR_HALF_LEFT" file="default_100_percent/extensions_rating_star_half_left.png" type="BINDATA" />
diff --git a/chrome/browser/extensions/api/commands/command_service.h b/chrome/browser/extensions/api/commands/command_service.h
index 7814792..a8d18812 100644
--- a/chrome/browser/extensions/api/commands/command_service.h
+++ b/chrome/browser/extensions/api/commands/command_service.h
@@ -46,7 +46,7 @@ class CommandService : public ProfileKeyedService,
// Register prefs for keybinding.
static void RegisterUserPrefs(PrefService* user_prefs);
- // Constructs an CommandService object for the given profile.
+ // Constructs a CommandService object for the given profile.
explicit CommandService(Profile* profile);
virtual ~CommandService();
diff --git a/chrome/browser/extensions/extension_keybinding_registry.h b/chrome/browser/extensions/extension_keybinding_registry.h
index 39ca0d9..ff0850e 100644
--- a/chrome/browser/extensions/extension_keybinding_registry.h
+++ b/chrome/browser/extensions/extension_keybinding_registry.h
@@ -28,6 +28,10 @@ class ExtensionKeybindingRegistry : public content::NotificationObserver {
explicit ExtensionKeybindingRegistry(Profile* profile);
virtual ~ExtensionKeybindingRegistry();
+ // Enables/Disables general shortcut handing in Chrome. Implemented in
+ // platform-specific ExtensionKeybindingsRegistry* files.
+ static void SetShortcutHandlingSuspended(bool suspended);
+
// Overridden from content::NotificationObserver:
virtual void Observe(int type,
const content::NotificationSource& source,
diff --git a/chrome/browser/resources/extensions/extension_command_list.js b/chrome/browser/resources/extensions/extension_command_list.js
index b69d44b..0ce00d88 100644
--- a/chrome/browser/resources/extensions/extension_command_list.js
+++ b/chrome/browser/resources/extensions/extension_command_list.js
@@ -13,9 +13,65 @@ cr.define('options', function() {
*/
var ExtensionCommandList = cr.ui.define('div');
+ /**
+ * Returns whether the passed in |keyCode| is a valid extension command
+ * char or not. This is restricted to A-Z and 0-9 (ignoring modifiers) at
+ * the moment.
+ * @param {int} keyCode The keycode to consider.
+ * @return {boolean} Returns whether the char is valid.
+ */
+ function validChar(keyCode) {
+ return (keyCode >= 'A'.charCodeAt(0) && keyCode <= 'Z'.charCodeAt(0)) ||
+ (keyCode >= '0'.charCodeAt(0) && keyCode <= '9'.charCodeAt(0));
+ }
+
+ /**
+ * Convert a keystroke event to string form, while taking into account
+ * (ignoring) invalid extension commands.
+ * @param {Event} event The keyboard event to convert.
+ * @return {string} The keystroke as a string.
+ */
+ function keystrokeToString(event) {
+ var output = '';
+ if (event.ctrlKey)
+ output = 'Ctrl + ';
+ if (!event.ctrlKey && event.altKey)
+ output += 'Alt + ';
+ if (event.shiftKey)
+ output += 'Shift + ';
+ if (validChar(event.keyCode))
+ output += String.fromCharCode('A'.charCodeAt(0) + event.keyCode - 65);
+ return output;
+ }
+
ExtensionCommandList.prototype = {
__proto__: HTMLDivElement.prototype,
+ /**
+ * While capturing, this records the current (last) keyboard event generated
+ * by the user. Will be |null| after capture and during capture when no
+ * keyboard event has been generated.
+ * @type: {keyboard event}.
+ * @private
+ */
+ currentKeyEvent_: null,
+
+ /**
+ * While capturing, this keeps track of the previous selection so we can
+ * revert back to if no valid assignment is made during capture.
+ * @type: {string}.
+ * @private
+ */
+ oldValue_: '',
+
+ /**
+ * While capturing, this keeps track of which element the user asked to
+ * change.
+ * @type: {HTMLElement}.
+ * @private
+ */
+ capturingElement_: null,
+
/** @inheritDoc */
decorate: function() {
this.textContent = '';
@@ -59,17 +115,137 @@ cr.define('options', function() {
var description = node.querySelector('.command-description');
description.textContent = command.description;
- var shortcut = node.querySelector('.command-shortcut');
+ var command_shortcut = node.querySelector('.command-shortcut');
+ command_shortcut.addEventListener('mouseup',
+ this.startCapture_.bind(this));
+ command_shortcut.addEventListener('blur', this.endCapture_.bind(this));
+ command_shortcut.addEventListener('keydown',
+ this.handleKeyDown_.bind(this));
+ command_shortcut.addEventListener('keyup', this.handleKeyUp_.bind(this));
+
if (!command.active) {
- shortcut.textContent =
+ command_shortcut.textContent =
loadTimeData.getString('extensionCommandsInactive');
- shortcut.classList.add('inactive-keybinding');
+ command_shortcut.classList.add('inactive-keybinding');
} else {
- shortcut.textContent = command.keybinding;
+ command_shortcut.textContent = command.keybinding;
}
this.appendChild(node);
},
+
+ /**
+ * Starts keystroke capture to determine which key to use for a particular
+ * extension command.
+ * @param {Event} event The keyboard event to consider.
+ * @private
+ */
+ startCapture_: function(event) {
+ if (this.capturingElement_)
+ return; // Already capturing.
+
+ chrome.send('setShortcutHandlingSuspended', [true]);
+
+ this.oldValue_ = event.target.textContent;
+ event.target.textContent =
+ loadTimeData.getString('extensionCommandsStartTyping');
+ event.target.classList.add('capturing');
+
+ this.capturingElement_ = event.target;
+ },
+
+ /**
+ * Ends keystroke capture and either restores the old value or (if valid
+ * value) sets the new value as active..
+ * @param {Event} event The keyboard event to consider.
+ * @private
+ */
+ endCapture_: function(event) {
+ if (!this.capturingElement_)
+ return; // Not capturing.
+
+ chrome.send('setShortcutHandlingSuspended', [false]);
+
+ this.capturingElement_.classList.remove('capturing');
+ this.capturingElement_.classList.remove('contains-chars');
+ if (!this.currentKeyEvent_ || !validChar(this.currentKeyEvent_.keyCode))
+ this.capturingElement_.textContent = this.oldValue_;
+
+ if (this.oldValue_ == '')
+ this.capturingElement_.classList.remove('clearable');
+ else
+ this.capturingElement_.classList.add('clearable');
+
+ this.oldValue_ = '';
+ this.capturingElement_ = null;
+ this.currentKeyEvent_ = null;
+ },
+
+ /**
+ * The KeyDown handler.
+ * @param {Event} event The keyboard event to consider.
+ * @private
+ */
+ handleKeyDown_: function(event) {
+ if (!this.capturingElement_)
+ this.startCapture_(event);
+
+ this.handleKey_(event);
+ },
+
+ /**
+ * The KeyUp handler.
+ * @param {Event} event The keyboard event to consider.
+ * @private
+ */
+ handleKeyUp_: function(event) {
+ // We want to make it easy to change from Ctrl+Shift+ to just Ctrl+ by
+ // releasing Shift, but we also don't want it to be easy to lose for
+ // example Ctrl+Shift+F to Ctrl+ just because you didn't release Ctrl
+ // as fast as the other two keys. Therefore, we process KeyUp until you
+ // have a valid combination and then stop processing it (meaning that once
+ // you have a valid combination, we won't change it until the next
+ // KeyDown message arrives).
+ if (!this.currentKeyEvent_ || !validChar(this.currentKeyEvent_.keyCode)) {
+ if (!event.ctrlKey && !event.altKey) {
+ // If neither Ctrl nor Alt is pressed then it is not a valid shortcut.
+ // That means we're back at the starting point so we should restart
+ // capture.
+ this.endCapture_(event);
+ this.startCapture_(event);
+ } else {
+ this.handleKey_(event);
+ }
+ }
+ },
+
+ /**
+ * A general key handler (used for both KeyDown and KeyUp).
+ * @param {Event} event The keyboard event to consider.
+ * @private
+ */
+ handleKey_: function(event) {
+ // While capturing, we prevent all events from bubbling, to prevent
+ // shortcuts lacking the right modifier (F3 for example) from activating
+ // and ending capture prematurely.
+ event.preventDefault();
+ event.stopPropagation();
+
+ if (!event.ctrlKey && !event.altKey)
+ return; // Ctrl or Alt is a must.
+
+ var keystroke = keystrokeToString(event);
+ event.target.textContent = keystroke;
+ event.target.classList.add('contains-chars');
+
+ if (validChar(event.keyCode)) {
+ this.oldValue_ = keystroke; // Forget what the old value was.
+ chrome.send('setExtensionCommandShortcut', ['id', keystroke]);
+ this.endCapture_(event);
+ }
+
+ this.currentKeyEvent_ = event;
+ },
};
return {
diff --git a/chrome/browser/resources/extensions/extension_commands_overlay.css b/chrome/browser/resources/extensions/extension_commands_overlay.css
index 32051f6..1869585 100644
--- a/chrome/browser/resources/extensions/extension_commands_overlay.css
+++ b/chrome/browser/resources/extensions/extension_commands_overlay.css
@@ -6,10 +6,56 @@
margin-left: 12px;
}
+.command-title {
+ display: inline-block;
+ margin-top: 1em;
+}
+
+.command-container {
+ -webkit-box-orient: horizontal;
+ display: -webkit-box;
+ width: 450px;
+}
+
+.command-description {
+ -webkit-box-flex: 1;
+ display: -webkit-box;
+ margin-top: 0.5em;
+ min-height: 2em;
+}
+
+.command-shortcut-container {
+ display: -webkit-box;
+ margin-top: 0.25em;
+ min-height: 2em;
+}
+
.command-shortcut {
- float: right;
+ border: solid 1px #BFBFBF;
+ border-radius: 2px;
+ color: rgb(48, 57, 66);
+ display: inline-block;
+ height: 1.4em;
+ min-width: 12.5em;
+ outline: none;
+ padding: 3px 0 1px 4px;
+}
+
+.clearable {
+ background: white url('chrome://theme/IDR_EXTENSION_COMMAND_CLOSE')
+ no-repeat right;
+}
+
+.capturing {
+ background: rgb(243, 244, 255);
+ border: solid 1px rgb(140, 147, 255);
+ color: #999;
+}
+
+.contains-chars {
+ color: rgb(48, 57, 66);
}
.inactive-keybinding {
- color: Gray;
+ color: #999;
}
diff --git a/chrome/browser/resources/extensions/extension_commands_overlay.html b/chrome/browser/resources/extensions/extension_commands_overlay.html
index 39f8fd1..03f22c1 100644
--- a/chrome/browser/resources/extensions/extension_commands_overlay.html
+++ b/chrome/browser/resources/extensions/extension_commands_overlay.html
@@ -4,6 +4,7 @@
* in the LICENSE file.
-->
<div id="extensionCommandsOverlay" class="page">
+ <div class="close-button"></div>
<h1 i18n-content="extensionCommandsOverlay"></h1>
<div class="content-area">
<div id="extension-command-list"
@@ -16,7 +17,7 @@
<div class="action-area">
<div class="action-area-right">
<div class="button-strip">
- <button id="extensionCommandsDismiss" i18n-content="close"></button>
+ <button id="extensionCommandsDismiss" i18n-content="ok"></button>
</div>
</div>
</div>
@@ -27,7 +28,7 @@
<div class="extension-command-list-extension-item">
<div class="extension-command-extension-details">
<div>
- <span class="extension-title"></span>
+ <span class="extension-title command-title"></span>
<div class="command-details"></div>
</div>
</div>
@@ -37,9 +38,11 @@
<div class="extension-command-list-command-item-wrapper">
<div class="extension-command-list-command-item">
<div class="extension-command-details">
- <div>
+ <div class="command-container">
<span class="command-description"></span>
- <span class="command-shortcut"></span>
+ <span class="command-shortcut-container">
+ <span class="command-shortcut clearable" tabindex="0" />
+ </span>
</div>
</div>
</div>
diff --git a/chrome/browser/ui/gtk/extensions/extension_keybinding_registry_gtk.cc b/chrome/browser/ui/gtk/extensions/extension_keybinding_registry_gtk.cc
index cb83e7b..c5cb371 100644
--- a/chrome/browser/ui/gtk/extensions/extension_keybinding_registry_gtk.cc
+++ b/chrome/browser/ui/gtk/extensions/extension_keybinding_registry_gtk.cc
@@ -12,6 +12,13 @@
#include "chrome/common/extensions/extension.h"
#include "ui/base/keycodes/keyboard_code_conversion_gtk.h"
+// static
+void extensions::ExtensionKeybindingRegistry::SetShortcutHandlingSuspended(
+ bool suspended) {
+ // TODO(finnur): Implement.
+ NOTIMPLEMENTED();
+}
+
ExtensionKeybindingRegistryGtk::ExtensionKeybindingRegistryGtk(
Profile* profile, gfx::NativeWindow window)
: ExtensionKeybindingRegistry(profile),
diff --git a/chrome/browser/ui/views/extensions/extension_keybinding_registry_views.cc b/chrome/browser/ui/views/extensions/extension_keybinding_registry_views.cc
index 6a319d6..1f70e16 100644
--- a/chrome/browser/ui/views/extensions/extension_keybinding_registry_views.cc
+++ b/chrome/browser/ui/views/extensions/extension_keybinding_registry_views.cc
@@ -7,11 +7,18 @@
#include "chrome/browser/extensions/api/commands/command_service.h"
#include "chrome/browser/extensions/api/commands/command_service_factory.h"
#include "chrome/browser/extensions/extension_browser_event_router.h"
+#include "chrome/browser/extensions/extension_keybinding_registry.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/extensions/extension.h"
#include "ui/views/focus/focus_manager.h"
+// static
+void extensions::ExtensionKeybindingRegistry::SetShortcutHandlingSuspended(
+ bool suspended) {
+ views::FocusManager::set_shortcut_handling_suspended(suspended);
+}
+
ExtensionKeybindingRegistryViews::ExtensionKeybindingRegistryViews(
Profile* profile, views::FocusManager* focus_manager)
: ExtensionKeybindingRegistry(profile),
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index d75e260..c3a7a10 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -1178,6 +1178,9 @@ bool BrowserView::PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event,
views::FocusManager* focus_manager = GetFocusManager();
DCHECK(focus_manager);
+ if (focus_manager->shortcut_handling_suspended())
+ return false;
+
ui::Accelerator accelerator(
static_cast<ui::KeyboardCode>(event.windowsKeyCode),
content::GetModifiersFromNativeWebKeyboardEvent(event));
diff --git a/chrome/browser/ui/webui/extensions/command_handler.cc b/chrome/browser/ui/webui/extensions/command_handler.cc
index 0b390bd..e42a261 100644
--- a/chrome/browser/ui/webui/extensions/command_handler.cc
+++ b/chrome/browser/ui/webui/extensions/command_handler.cc
@@ -8,6 +8,7 @@
#include "base/values.h"
#include "chrome/browser/extensions/api/commands/command_service.h"
#include "chrome/browser/extensions/api/commands/command_service_factory.h"
+#include "chrome/browser/extensions/extension_keybinding_registry.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/profiles/profile.h"
@@ -19,7 +20,6 @@
namespace extensions {
-
CommandHandler::CommandHandler() {
}
@@ -34,13 +34,21 @@ void CommandHandler::GetLocalizedValues(DictionaryValue* localized_strings) {
l10n_util::GetStringUTF16(IDS_EXTENSION_COMMANDS_EMPTY));
localized_strings->SetString("extensionCommandsInactive",
l10n_util::GetStringUTF16(IDS_EXTENSION_COMMANDS_INACTIVE));
- localized_strings->SetString("close", l10n_util::GetStringUTF16(IDS_CLOSE));
+ localized_strings->SetString("extensionCommandsStartTyping",
+ l10n_util::GetStringUTF16(IDS_EXTENSION_TYPE_SHORTCUT));
+ localized_strings->SetString("ok", l10n_util::GetStringUTF16(IDS_OK));
}
void CommandHandler::RegisterMessages() {
web_ui()->RegisterMessageCallback("extensionCommandsRequestExtensionsData",
base::Bind(&CommandHandler::HandleRequestExtensionsData,
base::Unretained(this)));
+ web_ui()->RegisterMessageCallback("setShortcutHandlingSuspended",
+ base::Bind(&CommandHandler::HandleSetShortcutHandlingSuspended,
+ base::Unretained(this)));
+ web_ui()->RegisterMessageCallback("setExtensionCommandShortcut",
+ base::Bind(&CommandHandler::HandleSetExtensionCommandShortcut,
+ base::Unretained(this)));
}
void CommandHandler::HandleRequestExtensionsData(const ListValue* args) {
@@ -50,6 +58,21 @@ void CommandHandler::HandleRequestExtensionsData(const ListValue* args) {
"ExtensionCommandsOverlay.returnExtensionsData", results);
}
+void CommandHandler::HandleSetExtensionCommandShortcut(
+ const base::ListValue* args) {
+ // TODO(finnur): Implement.
+}
+
+void CommandHandler::HandleSetShortcutHandlingSuspended(const ListValue* args) {
+#if !defined(OS_MACOSX)
+ bool suspended;
+ if (args->GetBoolean(0, &suspended))
+ ExtensionKeybindingRegistry::SetShortcutHandlingSuspended(suspended);
+#else
+ NOTIMPLEMENTED();
+#endif
+}
+
void CommandHandler::GetAllCommands(base::DictionaryValue* commands) {
ListValue* results = new ListValue;
diff --git a/chrome/browser/ui/webui/extensions/command_handler.h b/chrome/browser/ui/webui/extensions/command_handler.h
index bb9c1edb..090e254 100644
--- a/chrome/browser/ui/webui/extensions/command_handler.h
+++ b/chrome/browser/ui/webui/extensions/command_handler.h
@@ -42,6 +42,14 @@ class CommandHandler : public content::WebUIMessageHandler {
// Replies back through: ExtensionCommandsOverlay.returnExtensionsData.
void HandleRequestExtensionsData(const base::ListValue* args);
+ // Handles requests from javascript to set a particular keyboard shortcut
+ // for a given extension command.
+ void HandleSetExtensionCommandShortcut(const base::ListValue* args);
+
+ // Handles requests from javascript to temporarily disable general Chrome
+ // shortcut handling while the web page is capturing which shortcut to use.
+ void HandleSetShortcutHandlingSuspended(const base::ListValue* args);
+
// Fetches all known commands, active and inactive and returns them through
// |commands|.
void GetAllCommands(base::DictionaryValue* commands);
diff --git a/ui/views/focus/focus_manager.cc b/ui/views/focus/focus_manager.cc
index 3c2c8d7..db63206 100644
--- a/ui/views/focus/focus_manager.cc
+++ b/ui/views/focus/focus_manager.cc
@@ -21,6 +21,8 @@
namespace views {
+bool FocusManager::shortcut_handling_suspended_ = false;
+
FocusManager::FocusManager(Widget* widget, FocusManagerDelegate* delegate)
: widget_(widget),
delegate_(delegate),
@@ -76,6 +78,9 @@ bool FocusManager::OnKeyEvent(const KeyEvent& event) {
return false;
#endif
+ if (shortcut_handling_suspended())
+ return true;
+
int modifiers = ui::EF_NONE;
if (event.IsShiftDown())
modifiers |= ui::EF_SHIFT_DOWN;
diff --git a/ui/views/focus/focus_manager.h b/ui/views/focus/focus_manager.h
index a262180..e25c3ff 100644
--- a/ui/views/focus/focus_manager.h
+++ b/ui/views/focus/focus_manager.h
@@ -188,6 +188,13 @@ class VIEWS_EXPORT FocusManager {
// Returns true if in the process of changing the focused view.
bool is_changing_focus() const { return is_changing_focus_; }
+ // Disable shortcut handling.
+ static void set_shortcut_handling_suspended(bool suspended) {
+ shortcut_handling_suspended_ = suspended;
+ }
+ // Returns whether shortcut handling is currently suspended.
+ bool shortcut_handling_suspended() { return shortcut_handling_suspended_; }
+
// Register a keyboard accelerator for the specified target. If multiple
// targets are registered for an accelerator, a target registered later has
// higher priority.
@@ -268,6 +275,9 @@ class VIEWS_EXPORT FocusManager {
View* starting_view,
bool reverse);
+ // Keeps track of whether shortcut handling is currently suspended.
+ static bool shortcut_handling_suspended_;
+
// The top-level Widget this FocusManager is associated with.
Widget* widget_;