chrome UI排版绘制消息分发机制剖析.docx

上传人:b****3 文档编号:4155719 上传时间:2023-05-06 格式:DOCX 页数:166 大小:1.12MB
下载 相关 举报
chrome UI排版绘制消息分发机制剖析.docx_第1页
第1页 / 共166页
chrome UI排版绘制消息分发机制剖析.docx_第2页
第2页 / 共166页
chrome UI排版绘制消息分发机制剖析.docx_第3页
第3页 / 共166页
chrome UI排版绘制消息分发机制剖析.docx_第4页
第4页 / 共166页
chrome UI排版绘制消息分发机制剖析.docx_第5页
第5页 / 共166页
chrome UI排版绘制消息分发机制剖析.docx_第6页
第6页 / 共166页
chrome UI排版绘制消息分发机制剖析.docx_第7页
第7页 / 共166页
chrome UI排版绘制消息分发机制剖析.docx_第8页
第8页 / 共166页
chrome UI排版绘制消息分发机制剖析.docx_第9页
第9页 / 共166页
chrome UI排版绘制消息分发机制剖析.docx_第10页
第10页 / 共166页
chrome UI排版绘制消息分发机制剖析.docx_第11页
第11页 / 共166页
chrome UI排版绘制消息分发机制剖析.docx_第12页
第12页 / 共166页
chrome UI排版绘制消息分发机制剖析.docx_第13页
第13页 / 共166页
chrome UI排版绘制消息分发机制剖析.docx_第14页
第14页 / 共166页
chrome UI排版绘制消息分发机制剖析.docx_第15页
第15页 / 共166页
chrome UI排版绘制消息分发机制剖析.docx_第16页
第16页 / 共166页
chrome UI排版绘制消息分发机制剖析.docx_第17页
第17页 / 共166页
chrome UI排版绘制消息分发机制剖析.docx_第18页
第18页 / 共166页
chrome UI排版绘制消息分发机制剖析.docx_第19页
第19页 / 共166页
chrome UI排版绘制消息分发机制剖析.docx_第20页
第20页 / 共166页
亲,该文档总共166页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

chrome UI排版绘制消息分发机制剖析.docx

《chrome UI排版绘制消息分发机制剖析.docx》由会员分享,可在线阅读,更多相关《chrome UI排版绘制消息分发机制剖析.docx(166页珍藏版)》请在冰点文库上搜索。

chrome UI排版绘制消息分发机制剖析.docx

chromeUI排版绘制消息分发机制剖析

ChromeUI框架分析

一、总体结构

1、概述

代码结构

UI部分的通用代码放在src/chrome/views目录下。

其中:

control目录中为各种控件,如Label、Textfield等,这个目录最为庞大。

widget目录中为系统相关的UI底层细节,特别是UI消息机制。

window目录中为UIFrame相关的细节,例如窗口的标题栏、系统按钮以及、Frame、Dialog等的代理接口。

focus目录下为焦点管理、快捷键相关代码。

animation中为与动画相关的代码。

主要特点

1、采用DUI技术,大部分窗口和控件都是DUI的。

2、虚窗口的基类是View,每个View可以包含子View,他们组织成一棵树结构。

3、真窗口的基类是Widget,它处理与操作系统相关的最原始的消息,在windows上,它处理所有窗口消息。

Window是顶层窗口的基类,包括气泡、漂浮窗口、对话框、主窗口等。

4、View树的根节点是RootView,这个View的主要用途就是从Widget中接收UI消息,进行分发,包括排版与绘制,它是整个窗口树的根。

5、NonClientView表示整个实际的窗口树的根,是RootView唯一的子节点。

RootView向上和OS层打交道,而NonClientView则专注于下层的控件View。

NonClientView表示整个非客户区的View,包括标题栏、窗口图标、关闭按钮、最大化与最小化按钮、边框等,它负责非客户区的排版与绘制,这类可以被派生,以实现各种不同的客户区。

ClientView是客户区的根,负责客户区的排版与绘制。

6、排版由专门的LayoutManager负责。

7、界面绘制上,绘制引擎(Canvas)与窗框系统分开。

可以根据实际情况使用不同的图形引擎(Skia与D2D)。

一般情况下,绘图采用Skia,字体用windows的GDI,Skia保证可以跨平台。

绘制引擎提供了裁剪、平移变换等机制,使得View可以只重绘一部分,而且支持紧急与非紧急绘制。

8、控件消息的响应采用Listener模式。

9、绘制通过任务机制实现,从Task派生出一个PaintTask,其Run函数中实现绘制,该任务被放到MessagePumpForUI的任务队列中,每次消息循环的时候取出来执行。

10、广泛采用设计模式,顶层窗口的实现大类运用了代理模式,复杂的界面元素采用MVC模式实现界面(排版、绘制、界面消息响应)与逻辑的分离。

UI核心类与模块的关系如下图所示:

UI的基础代码可以分为消息循环(MessagePumpForUI与MessageLoopForUI)、真窗口(Widget以及派生类)、虚窗口(View以及派生类)、窗口树的根(RootView以及派生类,它实际上是View的派生类)、消息分发与响应、排版(LayoutManager)、绘制(Canvas、CanvasPaint等)、焦点与快捷键管理(FocusManager)组成。

这些是UI最底层、最核心的模块,控件建立在这些模块的基础之上。

类的继承关系图

View是所有控件、子窗口(虚窗口)的基类。

View类的派生关系图:

这其中有一个庞大的分支为各种控件,具体有:

按钮Button

菜单Menu

滚动条ScrollBar

表格TableView

树控件TreeView

组合框ComboBox

列表框ListBox

编辑框TextField

静态控件Label

超链接控件Link

其中,树控件、编辑框采用windows自己的原生控件,其他控件均为DUI的。

但是有些控件,如按钮等,chrome还包装了windows的原生控件。

Widget是所有真窗口的基类,它负责窗口的消息映射、子窗口的管理,每个Widget有一个RootView,作为窗口树的根,管理其子窗口。

Widget类的派生关系图:

WidgetWin有两类派生类,分别是气泡与漂浮窗口(地址栏自动提示窗口、标签拖出去形成的新窗口、信息气泡、菜单);有标题栏与边框的窗口(对话框、主窗口)。

WindowWin是所有有标题栏与边框的窗口的基类(对话框、主窗口)。

WindowWin中有客户区(client_view_)与非客户区(frame_view_),WindowWin通过配置不同的客户区,可以形成不同的窗口。

WindowImpl是对窗口创建、风格与扩展风格、窗口过程管理的封装。

窗口的结构

窗口中最大的子窗口是RootView,它是窗口树的根,它有唯一的一个孩子NonClientView。

NonClientView是逻辑上的根,它有两个孩子NonClientFrameView和ClientView,前者是窗口的非客户区,负责非客户区的绘制、消息响应;后者是窗口的客户区,负责客户区的绘制、消息响应。

这种结构如下图所示:

各个类之间的关系如下图所示(虚线为包含,实线为继承):

WidgetWin中有成员变量root_view_(RootView),为其窗口树的根,而窗口在初始化时RootView通过SetContentsView设置其孩子节点NonClientView。

NonClientView有两个节点frame_view_(NonClientFrameView)与client_view_(ClientView),分别是窗口的客户区与非客户区,各自处理客户区与非客户区的消息、绘制、排版等。

WindowWin继承自WidgetWin,是有边框的窗口,其中有成员变量non_client_view_。

而WidgetWin并没有该成员,这是因为对于气泡等漂浮窗口,没必要划分客户区与非客户区。

非客户区与客户区View的派生关系如下图所示(虚线为包含,实线为继承):

ClientView有两个派生类,分别是DialogClientView与BrowserView,前者是对话框的客户区,后者是浏览器主窗口的客户区。

NonClientFrameView有4个派生类,其中GlassBrowserFrameView为毛玻璃效果的窗口,OpaqueBrowserFrameView为非透明的窗口。

窗口的风格

窗口的风格、扩展风格的计算由WindowWin类的的两个函数CalculateWindowStyle、CalculateWindowExStyle统一完成,最基本的风格是WS_CLIPCHILDREN(裁剪孩子)、WS_CLIPSIBLINGS(裁剪兄弟)。

主窗口是WS_OVERLAPPED/WS_OVERLAPPEDWINDOW;对话框是WS_POPUP、DS_MODALFRAME;可缩放的窗口是WS_OVERLAPPED、WS_THICKFRAME;控件等原生窗口为WS_CHILD。

 

2、View

View是View层次结构中的一个矩形区域,是所有View的基类。

View是其他View的容器。

View有一些基本属性,用于缩放、排版、绘制、事件分发等。

View采用简单的盒式排版管理器,类似于XUL的SprocketLayout系统。

基类只提供了抽象的接口,很由子类负责实现绘制、与子类相关的属性、函数。

View的的继承关系

classView:

publicAcceleratorTarget

AcceleratorTarget是一个虚基类,它有唯一一个成员函数AcceleratorPressed,用于处理快捷键消息。

因此,所有View都可以处理快捷键

View的主要数据成员

是否Eanable:

boolenabled_;

是否能够获得焦点:

boolfocusable_;

View所占的区域:

gfx:

:

Rectbounds_;注意,该区域是相对于其父窗口的坐标系。

是否需要排版:

boolneeds_layout_;

父节点:

View*parent_;

子节点数组:

ViewListchild_views_;

排版管理器,永于对子窗口的排版:

scoped_ptrlayout_manager_;

是否可见:

boolis_visible_;

背景:

scoped_ptrbackground_;

边框:

scoped_ptrborder_;

是否被父亲拥有:

boolis_parent_owned_;

当可视区域改变时需要通知的后代View的列表:

scoped_ptrdescendants_to_notify_;

该View的名字:

std:

:

wstringaccessible_name_;

按Tab键时下一个获得焦点的View:

View*next_focusable_view_;

按Shift-Tab键时下一个获得焦点的View:

View*previous_focusable_view_;

焦点管理器:

FocusManager*accelerator_focus_manager_;

快捷键列表:

scoped_ptr

:

vector>accelerators_;

size_tregistered_accelerator_count_;

右键菜单管理器:

ContextMenuController*context_menu_controller_;

拖拽管理器,负责为View写拖拽数据,同时提供拖拽支持:

DragController*drag_controller_;

窗口树的组织(黄色为父节点指针,蓝色为子节点指针):

ContextMenuController右键菜单管理器为一个抽象接口,View中有这个成员,这使得所有View及其子类都具有显示、响应右键菜单的能力:

classContextMenuController{

public:

virtualvoidShowContextMenu(View*source,

constgfx:

:

Point&p,

boolis_mouse_gesture)=0;

protected:

virtual~ContextMenuController(){}

};

其中唯一一个成员函数是ShowContextMenu,用于为View显示右键菜单,其中source是要显示菜单的View的指针,p是菜单显示的位置,为屏幕坐标系。

DragController也是一个抽象的接口,负责为View的拖拽写数据,View中有这个成员,这使得所有View都支持拖拽。

classDragController{

public:

//Writesthedataforthedrag.

virtualvoidWriteDragData(View*sender,

constgfx:

:

Point&press_pt,

OSExchangeData*data)=0;

//Returnsthesupporteddragoperations(seeDragDropTypesforpossible

//values).Adragisonlystartedifthisreturnsanon-zerovalue.

virtualintGetDragOperations(View*sender,constgfx:

:

Point&p)=0;

//Returnstrueifadragoperationcanbestarted.

//|press_pt|representsthecoordinateswherethemousewasinitially

//presseddown.|p|isthecurrentmousecoordinates.

virtualboolCanStartDrag(View*sender,

constgfx:

:

Point&press_pt,

constgfx:

:

Point&p)=0;

protected:

virtual~DragController(){}

};

AcceleratorTarget为快捷键接收者,所有View都从其中派生,这使得所有View及其子类都具有处理快捷键的能力。

AcceleratorTarget的唯一一个成员函数为AcceleratorPressed,用于处理具体的快捷键,各个View可以重写此函数,用于处理自己的快捷键。

charView:

:

kViewClassName[]="views/View";

constintView:

:

kShowFolderDropMenuDelay=400;

View的主要成员函数

基本属性相关:

constgfx:

:

Rect&bounds()const{returnbounds_;}

constgfx:

:

Size&size()const{returnbounds_.size();}

voidSetBounds(constgfx:

:

Rect&bounds);

voidSetBounds(intx,inty,intwidth,intheight)

virtualgfx:

:

SizeGetPreferredSize();

virtualvoidSetVisible(boolflag);

virtualboolIsVisible()const{returnis_visible_;}

virtualvoidSetEnabled(boolflag);

virtualboolIsEnabled()const;

virtualboolIsPushed()const{returnfalse;}

排版相关:

virtualvoidLayout();

对本View进行排版,默认实现是调用排版管理器进行排版,这是一个虚函数,重载它可以实现各种不同的排版。

voidInvalidateLayout();

为本View和所有父节点设置需要重拍版标记,这可以确保下次调用Layout()时可以传播到本View,即使父View的大小不变。

LayoutManager*GetLayoutManager()const;

获取本View的焦点管理器。

voidSetLayoutManager(LayoutManager*layout);

为本View设置焦点管理器。

绘制相关的函数:

virtualvoidSchedulePaint(constgfx:

:

Rect&r,boolurgent);

将指定的区域标记为脏区域(需要重绘),如果urgent标志为true,则在当前事件处理完成后该区域马上被重绘,否则,会尽可能早的重绘。

virtualvoidSchedulePaint();

将整个View标记为脏,将尽可能早的重绘。

virtualvoidProcessPaint(gfx:

:

Canvas*canvas);

这是绘制本View及其孩子的主入口函数。

该函数被绘制系统调用,只有需要绘制子树时才调用此函数。

virtualvoidPaint(gfx:

:

Canvas*canvas);

绘制本View

virtualvoidPaintBackground(gfx:

:

Canvas*canvas);

绘制View的背景

virtualvoidPaintBorder(gfx:

:

Canvas*canvas);

绘制View的边框

virtualvoidPaintFocusBorder(gfx:

:

Canvas*canvas);

绘制焦点边框,如果本View有焦点。

默认的实现是在View周围绘制一个灰色的边框,重载该函数可以实现不同的效果。

virtualvoidPaintNow();

立刻绘制本View。

子节点、父节点操作相关的函数:

voidAddChildView(View*v);

voidAddChildView(intindex,View*v);

View*GetChildViewAt(intindex)const;

voidRemoveChildView(View*v);

voidRemoveAllChildViews(booldelete_views);

intGetChildViewCount()const;

boolHasChildView(View*a_view);

virtualView*GetViewForPoint(constgfx:

:

Point&point);

virtualWidget*GetWidget()const;

virtualWindow*GetWindow()const;

virtualboolContainsNativeView(gfx:

:

NativeViewnative_view)const;

virtualRootView*GetRootView();

View*GetParent()const{returnparent_;}

intGetChildIndex(constView*v)const;

boolIsParentOf(View*v)const;

virtualView*GetViewByID(intid)const;

voidSetID(intid);

intGetID()const;

voidSetGroup(intgid);

intGetGroup()const;

virtualboolIsGroupFocusTraversable()const{returntrue;}

voidGetViewsWithGroup(intgroup_id,std:

:

vector*out);

virtualView*GetSelectedViewForGroup(intgroup_id);

每个View的Layout函数用于定位它所有的子View。

当因为某些原因整个窗口需要重构时,根View调用Layout函数,然后递归调用每一个子View的Layout函数。

关于Chrome的Layout,Chrome还提供了一个GridLayout和FillLayout。

添加子节点的流程:

voidView:

:

AddChildView(intindex,View*v)

如果v有父节点,则先从其父节点中删除

设置v的前一个、后一个焦点view

将v插入本节点的子节点数组中,并将v的父节点设置为本节点

从本节点一直循环上溯到根节点,调用ViewHierarchyChangedImpl

PropagateAddNotifications

更新tooltips

为RootView调用RegisterChildrenForVisibleBoundsNotification

排版管理器调用ViewAdded

焦点、快捷键管理相关:

View*GetNextFocusableView();

View*GetPreviousFocusableView();

voidSetNextFocusableView(View*view);

virtualvoidSetFocusable(boolfocusable);

boolIsFocusableInRootView()const;

boolIsAccessibilityFocusableInRootView()const;

virtualvoidset_accessibility_focusable(boolaccessibility_focusable)

virtualFocusManager*GetFocusManager();

virtualvoidAddAccelerator(constAccelerator&accelerator);

virtualvoidRemoveAccelerator(constAccelerator&accelerator);

virtualvoidResetAccelerators();

virtualboolAcceleratorPressed(constAccelerator&accelerator)

virtualboolHasFocus();

工具函数:

staticvoidConvertPointToView(constView*src,

constView*dst,

gfx:

:

Point*point);

staticvoidConvertPointToWidget(constView*src,gfx:

:

Point*point);

staticvoidConvertPointFromWidget(constView*dest,gfx:

:

Point*p);

staticvoidConvertPointToScreen(constView*src,gfx:

:

Point*point);

事件处理函数:

virtualboolOnMousePressed(constMouseEvent&event);

virtualboolOnMouseDragged(constMouseEvent&event);

virtualvoidOnMouseReleased(constMouseEvent&event,boolcanceled);

virtualvoidOnMouseMoved(constMouseEvent&e);

virtualvoidOnMouseEntered(constMouseEvent&event);

virtualvoidOnMouseExited(constMouseEvent&event);

virtualvoidSetMouseHandler(View*new_mouse_handler);

virtualvoidRequestFocus();

virtualvoidWillGainFocus();

virtualvoidDidGainFocus();

virtualvoidWillLoseFocus();

virtualvoidAboutToRequestFocusFromTabTraversal(boolreverse)

virtualboolSkipDefaultKeyEventProcessing(constKeyEvent&e)

virtualboolOnKeyPressed(constKeyEvent&e);

virtualboolOnKeyReleased(constKeyEvent&e);

virtualboolOnMouseWheel(constMouseWheelEvent&e);

拖拽相关:

voidSetDragControl

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 表格模板 > 合同协议

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2