dde-dock/technology-overview.md
石博文 e9dda3caef
doc: update document, add PopupWindow & DBus
Change-Id: I00c271a9579929e5c418ffea922e6e728e8c7371
2018-07-31 17:24:04 +08:00

89 lines
5.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 框架设计
`dde-dock` 主要分为两部分,即主界面 `frame` 部分与插件 `plugins` 部分。
## 主界面
主界面是指 dock 栏的主窗口。主窗口负责 dock 显示的位置、形状及相关的动画与特效处理。
主面板(MainPanel)是主窗口(MainWindow)的唯一子控件,它是一个 BoxLayout负责容纳 dock 上存放的所有项目。根据设置的不同,它的排版方向有水平和竖直两种。
### Item
dock 上所存放的所有条目都继承自 `Item` 类。这样设计的原因是简化 dock 布局,使得 dock 主面板的布局上所有条目的管理都能统一起来。
目前 dock 上的 Items 有以下几类:
- DockItem 所有 Item 的基类,抽象类。
- LauncherItem 启动器类型的 Item。
- AppItem 关联所有应用程序的 Item。
- PlaceholderItem 占位空间,用于在交换、拖拽 Item 时,显示一个临时的、空白的 Item。
- StretchItem 在时尚模式下,充当中间的可伸缩空白区域。
- ContainerItem 容器空间,用于存放被收纳隐藏的插件 Item。
- PluginsItem 插件条目,每个插件可以注册 0 个或多个 PluginsItem 用于显示数据。
Dock 上从左至右(或从上至下)有不同的 Items 区域,在不同的显示模式下,不同工作区的显示状态或者调整策略都不一样,将它们统一为 Items 进行管理,可以极大的减小在这方面的工作。
### Item Controller
`DockItemController` 类是控制与管理所有 Items 的地方。任何 Item 的创建、销毁操作,移动、交换、刷新等信号的起始点都从这里开始。
其中AppItem 的相关数据是从后端获取的。这些与后端通信的操作被封装在了 AppItem 中。Item Controller 并不处理这些具体某个 Item 的事情。
### DockItem Controller
由于插件的复杂性与特殊性专门为插件管理加了一层包装。DockItem Controller 是 ItemController 的一部分,专门负责插件类型的 Items 的创建、排序等相关操作。同时,也是作为 dock 主程序到插件之间的一个 proxy 的作用。
### MainPanel
`MainPanel` 是主界面上的唯一控件,是容纳所有 Items 的地方。这个类接受来自 ItemController 的控制消息,来更新界面上的 Items 列表。
它主动进行的操作只有两种:
- d&d 操作的处理。它接受 drag & drop 事件,对事件进行处理并显示动画。中间过程全部是临时数据。当用户操作完毕后,它将最终的控制信号发送给 ItemsController并由接收它发送的信号来更新界面顺序。
- 布局调整处理。在 dock 位置、大小、Items 数量等发生变化后MainPanel 负责调整每个 Item 的大小并刷新布局。
需要注意的是,主面板类并不直接去控制 Items 列表的顺序,更不会去添加与销毁某个 Item。为了保证解耦功能上不能与 Controller 混淆,所以对 Item 的控制操作应该 __全部__ 来自于 ItemController 的控制信号。
### Popup Window
`Popup Window` 是一个特殊的控件。它是所有 Item 中用来显示提示信息,或是显示弹出式控件、列表的一个容器。但是考虑到这种控件使用频率非常高,如果在每个 Item 中创建多个的话很浪费内存,所以将 `PopupWindow` 设计为一个全局的控件,所有的 Item 共用这个控件。
## 插件
插件是符合标准的 Qt Plugins。插件的开发不必熟悉 dock 的所有代码,只需要熟悉一般的 Qt 插件开发过程,并了解 dock 所提供的接口。dock 的接口安装 `dde-dock-dev` 包即可。这也是方便插件开发者在无需配置完整的 dock 开发环境的情况下,更方便的进行 dock 插件的开发。
### 插件开发中的调试方法
在加载插件失败时,主程序会打印相关信息,仔细参考相关日志即可发现大部分问题。一般就是对应插件的 so 中有某些符号没有解析成功,或是插件版本与主程序的版本不相同。
如果插件可以成功加载,即可使用 gdb 等程序进行调试。
# 接口设计
## 插件接口
插件接口定义在 `interfaces/*.h` 中,参考具体类或函数的注释。
## DBus 接口
dock 主程序提供了一个 DBus 服务,可供外部访问到 dock 的 geometryRect 信息。这个信息也可以从后端的接口中读取,创建这个接口的最初目的是用作调试。当 dock 位置不正确时,可以比对此接口的信息与后端的信息。
其中后端的信息代表了 dock 主程序计算的结果,如果这个数据错误,就说明 dock 在位置计算的部分有 bug。
如果后端信息正确,而本接口中的数据错误,那就是计算正确,但是在向 X Server 发送对应的控制请求时出错。
通过检查两个接口的数据是否相同,也是一个进行自我检查的方法。目前在 `MainWindow::positionCheck` 中就进行了这样的操作,当发现两个数据不相同时,就重新向 X Server 发送请求,以此来 workaround 某些情况下 dock 位置不正确的问题。
# 优化
## MainWindow
目前所有的动画都被放在了 `MainWindow` 中进行处理。经过多次的改动,现在 `MainWindow` 中已经有很多动画相关的代码,这使得在进行窗口管理时不得不考虑动画的很多事情。
以后可以尝试将动画部分剔除出来,`MainWindow` 只进行窗口位置、大小等操作,尤其是应该把涉及到 `MainPanel` 动画的部分移动到 `MainPanel` 类中去,以此来减少在 `MainWindow` 中控制其它控件所带来的混乱。
## Popup Window
共用 `PopupWindow` 带来了很多好处,但是如果在使用时没有好好处理 data race、或是在 Tips Window 与 Model Window 切换中没有处理好顺序,就会造成很难调试,也很难处理的问题。可以尝试在这方面做一些优化。