最近负责改进浏览器的输入法,现在改进基本完成,做一个总结,这一篇先总结一下chromium的事件传递部分,同时也介绍一下chromium中的IME模块。

chromium中有几个处理事件的组件:

1.PlatformEventSource:chromium事件源,负责将Platform事件接入到浏览器中,维护一个 PlatformEventDispatcher 列表,并通过遍历这个列表来下发事件,是一个单例类;

class EVENTS_EXPORT PlatformEventSource {
public:// 添加 PlatformEventDispatcher 到 dispatcher list 中
void AddPlatformEventDispatcher(PlatformEventDispatcher* dispatcher);
protected:
PlatformEventSource();
// 遍历 dispatcher list 让每一个 dispatcher 分别分发事件,核心方法
virtual uint32_t DispatchEvent(PlatformEvent platform_event);
private:
// chromium 中定义的 ObserserList 模板,不是一个普通的STL模板,它支持通知在通知期间加入的观察者
typedef base::ObserverList<PlatformEventDispatcher> PlatformEventDispatcherList;
PlatformEventDispatcherList dispatchers_;
static PlatformEventSource *instance_;
};
//核心方法的实现
uint32_t PlatformEventSource::DispatchEvent(PlatformEvent platform_event) {
...
if ((action & POST_DISPATCH_PERFORM_DEFAULT) && dispatchers_.might_have_observers()) {
base::ObserverList<PlatformEventDispatcher>::Iterator iter(&dispatchers_);
while (PlatformEventDispatcher* dispatcher = iter.GetNext()) {
if (dispatcher->CanDispatchEvent(platform_event))
action = dispatcher->DispatchEvent(platform_event);
// 事件被处理就停止分发,在此通过返回值确定
if (action & POST_DISPATCH_STOP_PROPAGATION)
break;
}
...
}

2.PlatformEventDispatcher:chromium中的事件分发者,要回去chromium中的事件,就是继承这个类,并且将注册到PlatformEventSource的dispatcher列表中;

class EVENTS_EXPORT PlatformDispatcher{
public:
...
// 判断是否分发这个事件
virtual bool CanDispatchEvent(const PlatformEvent& event) = 0;
// 传递事件,返回值表示事件是否继续传递,停止,返回POST_DISPATCH_STOP_PROPAGATION
// 继续传递:POST_DISPATCH_PERFORM_DEFAULT 或者 0都可以
virtual uint32_t DispatchEvent(const PlatformEvent& event) = 0;
...
};

3.BrowserWindow:浏览器的主窗体,也就是UI部分,使用chromium的Aura UI实现,Aura UI封装了win、mac以及gtk等的实现,具有良好跨平台的能力。由于UI也需要接收事件,所以也会继承 PlatformEventDispatcher,实现以上两个方法就可以得到传入 chromium 的事件 ,不属于UI部分处理的事件,将会传递到后续的dispatcher;

4.WindowTreeHost:PlatformEventDispatcher的子类,拥有分发事件的能力,主要负责将事件传递到IME或者render进程(页面);将事件发送到chromium的EventHandler,然后会将事件转换成WebKit事件,发送到render,由WebKit处理。这部分后续单独总结。

InputMethod:声明了输入相关的接口,包括显示键盘,处理输入,以及事件转发等。

InputMethodBase:实现 InputMethod 中平台独立性的接口。

InputMethodMinimal:InputMethodBase的子类,chromium中在使用Aura UI时默认生成的IME组件;不同平台上的IME继承自InputMethodBase,实现平台相关的事件转换。

TextInputClient:声明输入框的逻辑接口。

默认事件处理流程:

1、来自系统的事件,首先被送到PlatformEventSource;

2、PlatformEventSource  将分发事件,遍历 PlatformEventDispatcher 列表。

3、首先调用 dispatcher 的 CanDispatchEvent 方法,若该dispatcher 支持当前事件,则继续调用的 DispatcherEvent() 方法,进一步处理事件,否则跳过当前dispatcher;

4、Aura UI 封装了平台相关的UI组件,网页实际就是显示在一个封装的 Navtie widget 中,而其中就有个 WindowTreeHost;

5、WindowTreeHost创建时将自身注册到 PlatformSourceEvent 的 dispatcher 列表中,所以当事件来到时,先经过WindowTreeHost;

6、WindowTreeHost首先将事件传送到 IME 模块中,若当前输入状态,则 IME 处理事件,否则,将事件通过WIndowTreeHost(IME的delegate)重新发送到 事件处理器,

若处于输入状态,则通过事件获取输入的字符,然后显示到输入的地方(默认情况下,只支持USB键盘的事件处理),然后事件停止,不在继续发送和处理。

以上就是一个默认的处理输入的流程。

实际场景中,目前是针对电视机的基于chromium的浏览器,除了USB键盘,还支持了对遥控器和USB鼠标事件的响应。

所以实际流程是这样的:

1、使用Aura UI实现了一个browser界面、以及界面内部的OSK,将browser界面继承自 PlatformEventDispatcher,同时注册到 PlatformEventSource 的 dispatcher列表。

2、当事件达到时,先有browser界面处理,若处理,则事件停止传送,否则,将通过WindowTreeHost 将事件分发到IME,然后是页面;

3、问题一,OSK属于browser界面,运行在browser端的UI线程,当使用OSK向页面输入时,需要通过开启一组额外的IPC,使处理逻辑变得复杂

4、问题二,当使用USB键盘输入时,事件直接通过IME组件,然后输入内容发送到页面,这容易出现输入内容不同步的问题;

5、问题三, 当使用遥控器和USB鼠标时,事件同样先有browser界面中的OSK处理,然后通过IPC传给页面。

所以需要进行改进,将OSK以及输入事件的处理同意起来,解决输入的同步问题。

解决思路:

1、将IME模块独立出来,让其最先接收事件,若是输入事件,直接处理,否则将事件继续往下发送;

2、OSK的显示仍然有browser界面管理,但是其输入的操作合并到IME中,让输入事件统一处理,输入结果统一设置,解决输入不同步的问题。

解决方案:

1、创建一个 ImeEventHandler 类(一下称 handler),继承自PlatformEventDispatcher,第一个注册到 PlatformEventSource 的dispatcher 列表中;

2、OSK保持事件处理能力,但是事件来源是handler,而不是browser UI;

3、USB键盘的输入也一样,事件来源于handler,不再是WindowTreeHost。

新的处理流程:

1、创建ImeEventHandler,注册为 PatformEventSource 的第一个dispatcher。

2、当事件到来,根据事件的类型,分别发送的响应的处理函数;

3、若是USB Keyboard 输入事件,直接从Event中获取要输入的字符,若是遥控器或者USB 鼠标类型,传到OSK处理事件,将输入结果返回到handler,统一输入。

4、不是输入事件,仍然抛到 browser UI 或者是 WindowTreeHost 去处理。

此处用 ImeEventHandler 来实现IME的工作流程,将输入事件的传递与其他UI和页面分离开来,有handler来完成主要的输入功能。

说明一下,在使用遥控器和USB鼠标时,产生的事件并没有要输入的字符,而是在遥控器和USB鼠标触发点击按钮之后,将事件传送到OSK,通过事件的位置来判断点击了哪一个按键,然后产生响应的结果。

以上是一个思路和方案的总结,若有不当之处,请指正。

在后面,还将为OSK添加一个外接的输入法框架,可以接入多种语言的输入引擎,同时该输入法框架运行在browser之外,与browser通过IPC进行通信。

chromium IME相关推荐

  1. 针对chromium IME的外接输入法框架

    前一篇文章中记录在开发基于chromium输入法过程中对chromium IME模块的学习和使用,由于目前比较特殊需求环境,在chromium  IME的基础之上,为其开发了一款输入法框架,该框架的功 ...

  2. 如何让代码看起来有万佛朝宗的气势

    1.使用全限定作用域 ::std::string user_name;::std::find('daniu',user_name.begin(), user_name.end()); 使用全限定作用域 ...

  3. Chromium浏览器(CEF)的命令行列表说明

    找到的Chromium浏览器的命令行说明列表,转放在这里以方便查看. List of Chromium Command Line Switches There are lots of command ...

  4. Chromium命令行开关列表2

    Chromium命令行开关列表 Google Chrome浏览器可以使用很多命令行. 一些更改功能的行为,其他用于调试或试验. 该页面列出了可用的开关,包括其条件和说明. 上一次自动更新发生在2020 ...

  5. Chromium分发输入事件给WebKit处理的过程分析

    Chromium的Render进程接收到Browser进程分发过来的输入事件之后,会在Compoistor线程中处理掉滑动和捏合手势这两种特殊的输入事件,其它类型的输入事件则交给Main线程处理.Ma ...

  6. 微软浏览器适配问题前端_「图」微软新贡献:修复Chromium浏览器的奇怪触控板手势问题...

    去年微软宣布计划成为Chromium项目的重要贡献者之一,希望为包括Edge和Chrome在内所有基于Chromium的浏览器带来更多改进和功能.在增强鼠标滚动和搜索功能之外,微软现在将部分精力放在部 ...

  7. 构建基于Chromium的应用程序(Winform程序加载Html页面)

    chromium是google chrome浏览器所采用的内核,最开始由苹果的webkit发展而出,由于webkit在发展上存在分歧,而google希望在开发上有更大的自由度,2013年google决 ...

  8. 微软“叛变”谷歌 Chromium!

    去年,微软工程师在公开演示 Azure 服务时,微软 Edge 浏览器频频崩溃,逼得他只能在众目睽睽的尴尬局面下,使用 Edge 下载 Chrome 浏览器来继续他的演示. 一年之后的今天,Edge ...

  9. Windows:安装Chrome OS/Chromium OS/CloudReady 到虚拟机VMware/VirtualBox

    很早之前就听说了ChromeBook,以及ChromeBook上搭载的Chrome OS系统,一直没机会去操作.今天碰巧看到了一篇讲 FydeOS .于是就想在自己的电脑上装Chrome OS,体验一 ...

最新文章

  1. TCP/IP详解 笔记八
  2. javascript等待异步线程完成_JavaScript 中的异步原理
  3. 转:Webkit Flex伸缩盒模型属性备忘
  4. 智慧交通day02-车流量检测实现04:卡尔曼滤波器
  5. Linux的实际操作:关机shutdown、重启reboot、用户注销logout
  6. mt4 指标 涨跌幅 颜色k线_通达信精选指标——彩色K线指标
  7. mysql连接多个存储存储_Mysql(三):多表查询和存储程序
  8. 雪城大学信息安全讲义 4.1~4.2
  9. 年轻就是程序员的资本?我不敢苟同!
  10. bvp解算器是什么_几种飞控的姿态解算算法
  11. hdu 1251 字典树,指针版
  12. ps打开闪退_PS教程派 | 水花四溅的草莓切块效果,如此简单!
  13. UML建模工具最近更新(-2022年7月)(1)Papyrus、EA
  14. 一、HTML基础(笔记)
  15. 计算机毕业设计Java宠物收养管理系统(源码+系统+mysql数据库+lw文档)
  16. java美团购物车,仿美团详情页与购物车源码-订单页
  17. 重整旗鼓学java之java基础
  18. python去掉json中的转义符_企业微信表情符自动转义怎么用?企业微信电脑版这样做...
  19. 【超图】SuperMap iClient3D 11i for WebGL新产品食用指南(一)
  20. 你了解世界上功能最强大的开源数据库吗?

热门文章

  1. Android动画(实现抛物线运动)
  2. python的sleep怎么实现的_sleep实现原理
  3. 项目文档之项目可行性研究
  4. 图的深度优先和广度优先
  5. win10出现驱动强制签名_错误代码:0xc0000428以及引导文件如何修复
  6. Linux日志分割软件,Linux 日志切割工具cronolog
  7. 几何光学学习笔记(27)-6.2 发光强度
  8. 摘要算法与数字签名和数字信封
  9. Android MP3播放器实例--------MusicActivity类以及MusicService类详细讲解
  10. 德国码农开发抢厕纸神器,再也不用愁了