chrome ui源码剖析-Accelerator(快捷键)
生活随笔
收集整理的這篇文章主要介紹了
chrome ui源码剖析-Accelerator(快捷键)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
?
好久沒有自己寫東西了,chrome有著取之不盡的技術精華供學習,記錄一下.
源碼目錄:
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_; };定義了快捷鍵屬性
主要有三個屬性
二.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() {} };注冊快捷鍵的對象,
三.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ù)結構為一個Accelerator對應一個AcceleratorTargets列表,bool用來表示優(yōu)先級
Process方法用來處理快捷鍵流程
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; }再來看下Register方法,新注冊的快捷鍵都排到前面來了,這個是比較關鍵的
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); }測試代碼:
1.注冊一個快捷鍵
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.注冊多個快捷鍵
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()); }?
簡單的用以上關系來表達三者之間的關系,其實邏輯還是比較清晰的,使用map查找起來速度也比較快,不會存在什么性能上面的問題,Register方法都是push_front也保證了時效性,所以其還是滿足了快捷鍵使用的需求,非常輕巧
總結
以上是生活随笔為你收集整理的chrome ui源码剖析-Accelerator(快捷键)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 阿里技术嘉年华-aDev内容感悟
- 下一篇: s5pv210 uboot-2012-1