最近负责改进浏览器的输入法,现在改进基本完成,做一个总结,这一篇先总结一下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. 最牛逼的核心框架,没有之一!
  2. 送福利 | 送书5本《ASP.NET Core项目开发实战入门》带你走进ASP.NET Core开发
  3. C语言中#if,#if defined ,#ifdef,extern的用法描述
  4. 提升安全性WindowsXP必禁的十大服务
  5. php如何让B链接在当前页面打,javascript - 如何实现点击链接 A 弹出窗口 X,点击链接 B 继续在弹出窗口 X (刷新)打开?...
  6. 【二维码、条码识别】【Python+OpenCV】基于OpenCV库的二维码、条形码识别识别【含源码 1-1】
  7. PDO和MySQLi , MySQL区别与选择?
  8. ddwrt php,DD-WRT官方支持设备列表_ddwrt
  9. 程序框图计算机算法语言应用,数学之算法与程序框图
  10. QT图形显示和处理7
  11. 计算机如何永久删除文件无法找回,怎么找回永久删除文件 找回永久删除文件方法【详细步骤】...
  12. #发现你#小说的交互——交互故事性
  13. html5 制作书架展示 PHP,html5制作转盘的详解及实例
  14. (附源码)php遵义旅游管理系统 毕业设计091801
  15. 计算机科学家的名言警句,有关写数学的名言警句
  16. TL138-EVM U-Boot启动方法及启动参数详解
  17. 把一个数的分子分母化简
  18. PHPQrcode生成的二维码如何转换为base64
  19. 如何测试CTS4.0
  20. 常用HANA函数解释

热门文章

  1. 图解offsetX、offsetY和clientX、clientY和pageX、pageY和screenX、screenY的区别
  2. 物联网卡可以当做流量卡使用吗?
  3. Pytorch LSTM 代码解读及自定义双向 LSTM 算子
  4. VR全景旅游是景区发展的方向,也是旅游的延伸
  5. Pregel体系结构
  6. 中国医学影像开启“绝代双骄”时代
  7. TED演讲靠什么吸引人
  8. Linux中Tomcat中的Cronolog日志分割工具配置
  9. python函数参数定义不合法_面试题 - Operater - 博客园
  10. matlab取余和取商方法