好久没有自己写东西了,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_;
};

定义了快捷键属性

主要有三个属性

  1. key_code_:按下的键盘键
  2. type_:触发的事件,比如keydown,keyup
  3. modifiers_:特殊组合按钮

二.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() {}
};

注册快捷键的对象,

  1. AcceleratorPressed方法为处理快捷键事件,返回true则表明处理完毕
  2. CanHandleAccelerators方法是处理快捷键之前的状态检查

三.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_

数据结构为一个Accelerator对应一个AcceleratorTargets列表,bool用来表示优先级

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);
else
targets.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(快捷键)的更多相关文章

  1. chrome ui源码剖析-ViewProp

      先熟悉set的find原理 http://www.cnblogs.com/Clingingboy/p/3252136.html 这个类改造下,还是非常实用的,可以对于不同的类型做数据存储 一.Vi ...

  2. Google Chrome源码剖析【序】

    [序(本人什么都没做,完全转载)] 开源是口好东西,它让这个充斥着大量工业垃圾代码和教材玩具代码的行业,多了一些艺术气息和美的潜质.它使得每个人,无论你来自米国纽约还是中国铁岭,都有机会站在巨人的肩膀 ...

  3. Spark源码剖析 - SparkContext的初始化(三)_创建并初始化Spark UI

    3. 创建并初始化Spark UI 任何系统都需要提供监控功能,用浏览器能访问具有样式及布局并提供丰富监控数据的页面无疑是一种简单.高效的方式.SparkUI就是这样的服务. 在大型分布式系统中,采用 ...

  4. Chrome V8 引擎源码剖析

    Chrome V8 引擎源码剖析 V8 https://github.com/v8/v8 array & sort https://github.com/v8/v8/search?l=Java ...

  5. (升级版)Spark从入门到精通(Scala编程、案例实战、高级特性、Spark内核源码剖析、Hadoop高端)

    本课程主要讲解目前大数据领域最热门.最火爆.最有前景的技术——Spark.在本课程中,会从浅入深,基于大量案例实战,深度剖析和讲解Spark,并且会包含完全从企业真实复杂业务需求中抽取出的案例实战.课 ...

  6. Appuim源码剖析(Bootstrap)

    Appuim源码剖析(Bootstrap) SkySeraph Jan. 26th 2017 Email:skyseraph00@163.com 更多精彩请直接访问SkySeraph个人站点:www. ...

  7. 老李推荐:第14章1节《MonkeyRunner源码剖析》 HierarchyViewer实现原理-面向控件编程VS面向坐标编程

    老李推荐:第14章1节<MonkeyRunner源码剖析> HierarchyViewer实现原理-面向控件编程VS面向坐标编程   poptest是国内唯一一家培养测试开发工程师的培训机 ...

  8. 老李推荐:第2章2节《MonkeyRunner源码剖析》了解你的测试对象: NotePad窗口Activity之NotesList简介

    老李推荐:第2章2节<MonkeyRunner源码剖析>了解你的测试对象: NotePad窗口Activity之NotesList简介   NotePad窗口Activity之NotesL ...

  9. 老李推荐: 第1章1节《MonkeyRunner源码剖析》概述:前言

    老李推荐: 第1章1节<MonkeyRunner源码剖析>概述:前言   前言 相信大家做过安卓移动平台UI自动化开发的必然会用过,至少听过MonkeyRunner这个名字.MonkeyR ...

随机推荐

  1. docker 构建带健康检查的redis镜像

    =============================================== 2018/11/5_第1次修改                       ccb_warlock == ...

  2. jexus - 分析日志文件

    1.统计IP访问次数 awk '{print $3}' default |sort -n|uniq -c|sort -rn|head

  3. ASP.NET Web配置使用HTTPS实用案例

    Step by Step 配置使用HTTPS的ASP.NET Web应用 有关HTTPS.SSL以及SSL证书的工作原理,参见 <HTTPS那些事(一)HTTPS原理> <HTTPS ...

  4. C# 各版本新特性

    C# 2.0 泛型(Generics) 泛型是CLR 2.0中引入的最重要的新特性,使得可以在类.方法中对使用的类型进行参数化. 例如,这里定义了一个泛型类: class MyCollection&l ...

  5. 发布构件到Maven中央仓库

    一.注册jira账号 访问如下网址: https://issues.sonatype.org/secure/Signup.jspa 记住邮箱,用户名,密码以备以后使用,一定牢记. 二.创建一个issu ...

  6. SVN使用过程中遇到的一些问题

    更新svn的客户端TortoiseSVN后 ,之前使用svn管理的文件的关联图标消失了 说明:下面的解决方法及图片来自博客:装了SVN,你的关联图标变了没有? 解决办法:在同步的文件点击右键如下图   ...

  7. SpringMVC高级参数绑定(数组和List)

    本节内容: 参数绑定之数组 将表单的数据绑定到List 复制下上篇博客中的工程,作为今天开发的工程. 一.参数绑定之数组 1. 需求 在商品列表页面选中多个商品,然后删除. 2. 需求分析 功能要求商 ...

  8. Java第三阶段学习(五、流的操作规律、Properties流、序列化流与反序列化流、打印流、commons-IO jar包)

    一.流的操作规律 四个明确: 明确一:明确要操作的数据是数据源还是数据目的地 源:InputStream   Reader 目的地:OutputStream Writer 先根据需求明确是要读还是写 ...

  9. hive1.2.1安装步骤(在hadoop2.6.4集群上)

    hive1.2.1在hadoop2.6.4集群上的安装 hive只需在一个节点上安装即可,这里再hadoop1上安装 1.上传hive安装包到/usr/local/目录下 2.解压 tar -zxvf ...

  10. Pandas常用命令

    一.数据导入和导出 (一)读取csv文件 1.本地读取 import pandas as pd df = pd.read_csv('tips.csv') #根据自己数据文件保存的路径填写(p.s. p ...