理解了chromium中的一些进程和线程的设计后,目前代码阅读的方向转变到chromium的UI。
chromium的ui框架是跨平台的,chromium中与ui相关的所有控件,几乎都继承自View(ui/views/view.h),通过树形结构,views组成一个控件或一个页面。在chromium中view的分层如下图所示,Widget可以说是整个UI的根,RootView是整个View控件树的根,Widget会接受系统消息并将其装换为view控件能够识别的消息,并将此消息传递给views::RootView,并通过RootView将消息分发给下层的View。
下层的View包括以下三种:
- 表示整个窗体非客户区的NonClientView ,负责设置窗口边框大小。它是NonClientFrameView和ClientView的父view,由于它管着整个窗体的边框,所以其他的View必须是它的子view。
- 表示非客户区的内容的NonClientFrameView ,负责绘制非客户区里面的元素,如标题栏,关闭按钮等等。
- 表示客户区和其内容的ClientView ,负责生成各种窗口元素。
chromium UI的类图如下图所示,接下来会讲解这些类是怎么体现上图中的分层思想。
在构造Browser的时候会调用BrowserWindow::CreateBrowserWindow,创建BrowserView及BrowserFrame。而BrowserFrame是Widget的一个子类,所以它包含RootView和NonClientView,而NonClientView也会包含NonClientFrameView以及ClientView。
NonClientFrameView由Widget::CreateNonClientFrameView函数生成,通过接口继承,在BrowserFrame中是由函数BrowserFrame::CreateNonClientFrameView生成的,它是GlassBrowserFrameView或者OpaqueBrowserFrameView中的某一个。
ClientView由WidgetDelegate::CreateClientView函数生成,通过接口继承,在BrowserView中返回的是指向自身的指针,所以BrowserFrame中的ClientView就是BrowserView。
在BrowserFrame构建过程中会把NonClientFrameView和ClientView都加到Widget的NonClientView下,完成层次的构建。
chromium的主UI可以画成如下的一个图。主窗口的组件都分布在BrowserView类中,在BrowserView::InitViews函数中,创建了这些组件。BrowserView的组件主要是标签栏、导航栏、网页视图等,这些组件都继承了View。BrowserView中的结构如左图所示,BrowserView下包含top_container_、infobar_container_、bookmark_bar_view_、contents_container_和download_shelf_等组件,top_container_下包含tabstrip_和toolbar_,contents_container_下包含devtools_web_view_和contents_web_view_。