diff options
author | finnur@chromium.org <finnur@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-02-23 13:00:55 +0000 |
---|---|---|
committer | finnur@chromium.org <finnur@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-02-23 13:00:55 +0000 |
commit | f553247ebf96528afde64b205cc4fb8733fb08ce (patch) | |
tree | 025fa9618eb4bec03f93e58a35fbf2b97dfa5a76 /ui/base | |
parent | 92e713a7e3b2b5a2458876f81a053d0c6b7ce5fd (diff) | |
download | chromium_src-f553247ebf96528afde64b205cc4fb8733fb08ce.zip chromium_src-f553247ebf96528afde64b205cc4fb8733fb08ce.tar.gz chromium_src-f553247ebf96528afde64b205cc4fb8733fb08ce.tar.bz2 |
Experimental Extension Keybinding (first cut).
Implemented in this cut:
- End-to-end extension keybinding -- in one dimension, that is -- no UI, just basic functionality, such as:
- Manifest changes to specify keybinding.
- A simple parser to parse the keybinding from the manifest.
- An Extension Keybinding Registry object.
- The ability to open browser action popups, page action popups and send named events to the Extension.
Not implemented:
- All non-Windows specific code.
- Install-success-bubble UI changes (that notify the user of new keybinding -- or of keybinding conflict)
- A UI to show all keybindings and keybinding conflicts, allowing user to reconfigure keybindings.
BUG=27702
TEST=This is tested by an automated test and requires an extension to test manually (one that registers keybinding shortcuts).
Review URL: https://chromiumcodereview.appspot.com/9402018
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@123228 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/base')
-rw-r--r-- | ui/base/accelerators/accelerator_manager.cc | 53 | ||||
-rw-r--r-- | ui/base/accelerators/accelerator_manager.h | 26 |
2 files changed, 70 insertions, 9 deletions
diff --git a/ui/base/accelerators/accelerator_manager.cc b/ui/base/accelerators/accelerator_manager.cc index d2d70c9..034593d 100644 --- a/ui/base/accelerators/accelerator_manager.cc +++ b/ui/base/accelerators/accelerator_manager.cc @@ -17,11 +17,29 @@ AcceleratorManager::~AcceleratorManager() { } void AcceleratorManager::Register(const Accelerator& accelerator, + HandlerPriority priority, AcceleratorTarget* target) { - AcceleratorTargetList& targets = accelerators_[accelerator]; + AcceleratorTargetList& targets = accelerators_[accelerator].second; DCHECK(std::find(targets.begin(), targets.end(), target) == targets.end()) << "Registering the same target multiple times"; - targets.push_front(target); + + // All priority accelerators go to the front of the line. + if (priority) { + DCHECK(!accelerators_[accelerator].first) + << "Only one _priority_ handler can be registered"; + targets.push_front(target); + // Mark that we have a priority accelerator at the front. + accelerators_[accelerator].first = true; + return; + } + + // We are registering a normal priority handler. If no priority accelerator + // handler has been registered before us, just add the new handler to the + // front. Otherwise, register it after the first (only) priority handler. + if (!accelerators_[accelerator].first) + targets.push_front(target); + else + targets.insert(++targets.begin(), target); } void AcceleratorManager::Unregister(const Accelerator& accelerator, @@ -32,7 +50,7 @@ void AcceleratorManager::Unregister(const Accelerator& accelerator, return; } - AcceleratorTargetList* targets = &map_iter->second; + AcceleratorTargetList* targets = &map_iter->second.second; AcceleratorTargetList::iterator target_iter = std::find(targets->begin(), targets->end(), target); if (target_iter == targets->end()) { @@ -40,13 +58,19 @@ void AcceleratorManager::Unregister(const Accelerator& accelerator, return; } + // Check to see if we have a priority handler and whether we are removing it. + if (accelerators_[accelerator].first && target_iter == targets->begin()) { + // We've are taking the priority accelerator away, flip the priority flag. + accelerators_[accelerator].first = false; + } + targets->erase(target_iter); } void AcceleratorManager::UnregisterAll(AcceleratorTarget* target) { for (AcceleratorMap::iterator map_iter = accelerators_.begin(); map_iter != accelerators_.end(); ++map_iter) { - AcceleratorTargetList* targets = &map_iter->second; + AcceleratorTargetList* targets = &map_iter->second.second; targets->remove(target); } } @@ -57,7 +81,7 @@ bool AcceleratorManager::Process(const Accelerator& accelerator) { if (map_iter != accelerators_.end() && ShouldHandle(accelerator)) { // We have to copy the target list here, because an AcceleratorPressed // event handler may modify the list. - AcceleratorTargetList targets(map_iter->second); + AcceleratorTargetList targets(map_iter->second.second); for (AcceleratorTargetList::iterator iter = targets.begin(); iter != targets.end(); ++iter) { if ((*iter)->CanHandleAccelerators() && @@ -74,9 +98,24 @@ bool AcceleratorManager::Process(const Accelerator& accelerator) { AcceleratorTarget* AcceleratorManager::GetCurrentTarget( const Accelerator& accelerator) const { AcceleratorMap::const_iterator map_iter = accelerators_.find(accelerator); - if (map_iter == accelerators_.end() || map_iter->second.empty()) + if (map_iter == accelerators_.end() || map_iter->second.second.empty()) return NULL; - return map_iter->second.front(); + return map_iter->second.second.front(); +} + +bool AcceleratorManager::HasPriorityHandler( + const Accelerator& accelerator) const { + AcceleratorMap::const_iterator map_iter = accelerators_.find(accelerator); + if (map_iter == accelerators_.end() || map_iter->second.second.empty()) + return false; + + // Check if we have a priority handler. If not, there's no more work needed. + if (!map_iter->second.first) + return false; + + // If the priority handler says it cannot handle the accelerator, we must not + // count it as one. + return map_iter->second.second.front()->CanHandleAccelerators(); } bool AcceleratorManager::ShouldHandle(const Accelerator& accelerator) const { diff --git a/ui/base/accelerators/accelerator_manager.h b/ui/base/accelerators/accelerator_manager.h index c54ea1d..7164acb 100644 --- a/ui/base/accelerators/accelerator_manager.h +++ b/ui/base/accelerators/accelerator_manager.h @@ -8,6 +8,7 @@ #include <list> #include <map> +#include <utility> #include "base/basictypes.h" #include "ui/base/accelerators/accelerator.h" @@ -19,19 +20,34 @@ namespace ui { // The AcceleratorManger is used to handle keyboard accelerators. class UI_EXPORT AcceleratorManager { public: + enum HandlerPriority { + kNormalPriority, + kHighPriority, + }; + AcceleratorManager(); ~AcceleratorManager(); // Register a keyboard accelerator for the specified target. If multiple // targets are registered for an accelerator, a target registered later has // higher priority. + // |accelerator| is the accelerator to register. + // |priority| denotes the priority of the handler. + // NOTE: In almost all cases, you should specify kPriorityNormal for this + // parameter. Setting it to kPriorityHigh prevents Chrome from sending the + // shortcut to the webpage if the renderer has focus, which is not desirable + // except for very isolated cases. + // |target| is the AcceleratorTarget that handles the event once the + // accelerator is pressed. // Note that we are currently limited to accelerators that are either: // - a key combination including Ctrl or Alt // - the escape key // - the enter key // - any F key (F1, F2, F3 ...) // - any browser specific keys (as available on special keyboards) - void Register(const Accelerator& accelerator, AcceleratorTarget* target); + void Register(const Accelerator& accelerator, + HandlerPriority priority, + AcceleratorTarget* target); // Unregister the specified keyboard accelerator for the specified target. void Unregister(const Accelerator& accelerator, AcceleratorTarget* target); @@ -52,12 +68,18 @@ class UI_EXPORT AcceleratorManager { // accelerator. AcceleratorTarget* GetCurrentTarget(const Accelerator& accelertor) const; + // Whether the given |accelerator| has a priority handler associated with it. + bool HasPriorityHandler(const Accelerator& accelerator) const; + private: bool ShouldHandle(const Accelerator& accelerator) const; // The accelerators and associated targets. typedef std::list<AcceleratorTarget*> AcceleratorTargetList; - typedef std::map<Accelerator, AcceleratorTargetList> AcceleratorMap; + // This construct pairs together a |bool| (denoting whether the list contains + // a priority_handler at the front) with the list of AcceleratorTargets. + typedef std::pair<bool, AcceleratorTargetList> AcceleratorTargets; + typedef std::map<Accelerator, AcceleratorTargets> AcceleratorMap; AcceleratorMap accelerators_; // An event passed to Process() last time. |