chrome ui源码剖析-Accelerator(快捷键)
?
好久沒(méi)有自己寫(xiě)東西了,chrome有著取之不盡的技術(shù)精華供學(xué)習(xí),記錄一下.
源碼目錄:
http://src.chromium.org/viewvc/chrome/trunk/src/ui/base/accelerators/
一.Accelerator 類
// This class describe a keyboard accelerator (or keyboard shortcut). // Keyboard accelerators are registered with the FocusManager. // It has a copy constructor and assignment operator so that it can be copied. // It also defines the < operator so that it can be used as a key in a std::map. //#ifndef UI_BASE_ACCELERATORS_ACCELERATOR_H_ #define UI_BASE_ACCELERATORS_ACCELERATOR_H_ namespace ui {class PlatformAccelerator;// This is a cross-platform class for accelerator keys used in menus. // |platform_accelerator| should be used to store platform specific data. class UI_EXPORT Accelerator {public:Accelerator();Accelerator(ui::KeyboardCode keycode, int modifiers);Accelerator(const Accelerator& accelerator);~Accelerator(); ui::KeyboardCode key_code() const { return key_code_; }// Sets the event type if the accelerator should be processed on an event// other than ui::ET_KEY_PRESSED.void set_type(ui::EventType type) { type_ = type; }ui::EventType type() const { return type_; }int modifiers() const { return modifiers_; }bool IsShiftDown() const;bool IsCtrlDown() const;bool IsAltDown() const;bool IsCmdDown() const;protected:// The keycode (VK_...).KeyboardCode key_code_;// The event type (usually ui::ET_KEY_PRESSED).EventType type_;// The state of the Shift/Ctrl/Alt keys.int modifiers_;// Stores platform specific data. May be NULL.scoped_ptr<PlatformAccelerator> platform_accelerator_; };定義了快捷鍵屬性
主要有三個(gè)屬性
二.AcceleratorTarget
?
// An interface that classes that want to register for keyboard accelerators // should implement. class UI_EXPORT AcceleratorTarget {public:// Should return true if the accelerator was processed.virtual bool AcceleratorPressed(const Accelerator& accelerator) = 0;// Should return true if the target can handle the accelerator events. The// AcceleratorPressed method is invoked only for targets for which// CanHandleAccelerators returns true.virtual bool CanHandleAccelerators() const = 0;protected:virtual ~AcceleratorTarget() {} };注冊(cè)快捷鍵的對(duì)象,
三.AcceleratorManager
#ifndef UI_BASE_ACCELERATORS_ACCELERATOR_MANAGER_H_ #define UI_BASE_ACCELERATORS_ACCELERATOR_MANAGER_H_#include <list> #include <map> #include <utility> 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 kNormalPriority for this// parameter. Setting it to kHighPriority 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,HandlerPriority priority,AcceleratorTarget* target);// Unregister the specified keyboard accelerator for the specified target.void Unregister(const Accelerator& accelerator, AcceleratorTarget* target);// Unregister all keyboard accelerator for the specified target.void UnregisterAll(AcceleratorTarget* target);// Activate the target associated with the specified accelerator.// First, AcceleratorPressed handler of the most recently registered target// is called, and if that handler processes the event (i.e. returns true),// this method immediately returns. If not, we do the same thing on the next// target, and so on.// Returns true if an accelerator was activated.bool Process(const Accelerator& accelerator);// Returns the AcceleratorTarget that should be activated for the specified// keyboard accelerator, or NULL if no view is registered for that keyboard// 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:// The accelerators and associated targets.typedef std::list<AcceleratorTarget*> AcceleratorTargetList;// 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_;DISALLOW_COPY_AND_ASSIGN(AcceleratorManager); };} // namespace ui#endif // UI_BASE_ACCELERATORS_ACCELERATOR_MANAGER_H_
數(shù)據(jù)結(jié)構(gòu)為一個(gè)Accelerator對(duì)應(yīng)一個(gè)AcceleratorTargets列表,bool用來(lái)表示優(yōu)先級(jí)
Process方法用來(lái)處理快捷鍵流程
bool AcceleratorManager::Process(const Accelerator& accelerator) {bool result = false;AcceleratorMap::iterator map_iter = accelerators_.find(accelerator);if (map_iter != accelerators_.end()) {// We have to copy the target list here, because an AcceleratorPressed// event handler may modify the list.AcceleratorTargetList targets(map_iter->second.second);for (AcceleratorTargetList::iterator iter = targets.begin();iter != targets.end(); ++iter) {if ((*iter)->CanHandleAccelerators() &&(*iter)->AcceleratorPressed(accelerator)) {result = true;break;}}}return result; }再來(lái)看下Register方法,新注冊(cè)的快捷鍵都排到前面來(lái)了,這個(gè)是比較關(guān)鍵的
void AcceleratorManager::Register(const Accelerator& accelerator,HandlerPriority priority,AcceleratorTarget* target) {AcceleratorTargetList& targets = accelerators_[accelerator].second;DCHECK(std::find(targets.begin(), targets.end(), target) == targets.end())<< "Registering the same target multiple times";// 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);elsetargets.insert(++targets.begin(), target); }測(cè)試代碼:
1.注冊(cè)一個(gè)快捷鍵
TEST_F(AcceleratorManagerTest, Register) {const Accelerator accelerator_a(VKEY_A, EF_NONE);TestTarget target;manager_.Register(accelerator_a, AcceleratorManager::kNormalPriority,&target);// The registered accelerator is processed.EXPECT_TRUE(manager_.Process(accelerator_a));EXPECT_EQ(1, target.accelerator_pressed_count()); }2.注冊(cè)多個(gè)快捷鍵
TEST_F(AcceleratorManagerTest, RegisterMultipleTarget) {const Accelerator accelerator_a(VKEY_A, EF_NONE);TestTarget target1;manager_.Register(accelerator_a, AcceleratorManager::kNormalPriority,&target1);TestTarget target2;manager_.Register(accelerator_a, AcceleratorManager::kNormalPriority,&target2);// If multiple targets are registered with the same accelerator, the target// registered later processes the accelerator.EXPECT_TRUE(manager_.Process(accelerator_a));EXPECT_EQ(0, target1.accelerator_pressed_count());EXPECT_EQ(1, target2.accelerator_pressed_count()); }?
簡(jiǎn)單的用以上關(guān)系來(lái)表達(dá)三者之間的關(guān)系,其實(shí)邏輯還是比較清晰的,使用map查找起來(lái)速度也比較快,不會(huì)存在什么性能上面的問(wèn)題,Register方法都是push_front也保證了時(shí)效性,所以其還是滿足了快捷鍵使用的需求,非常輕巧
總結(jié)
以上是生活随笔為你收集整理的chrome ui源码剖析-Accelerator(快捷键)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 阿里技术嘉年华-aDev内容感悟
- 下一篇: s5pv210 uboot-2012-1