参考文章:http://www.360doc.com/content/14/0616/17/2036337_387230839.shtml
https://www.jianshu.com/p/4afe92418bd9
https://blog.csdn.net/LisztLee/article/details/8246795
一些基础概念整理:
在https://blog.csdn.net/LisztLee/article/details/8246795文章中完全拷贝了一些基础铺垫:
1、Widget
Widget 中管理着一个真窗口,用于接收事件消息,以及管理整个 UI 界面,在windows 下就是管理一个 HWND ,它通过NativeWidgetWin 中的 HWNDMessageHandler来实现。在 Widget中包含一个 RootView ,因此也可以算是整个view系统中的一层,同时,它也可以包含其他的Widgets。Widget中如果涉及到跟平台相关的处理,它会把他们隐藏起来实现,通过一个指定的NativeWidget去实现,具体实现如下:
在widget中同样使用了delegate,在NativeWidgetPrivate中会实现具体的跟窗口自己相关的操作,而当涉及到具体的业务逻辑相关的操作时则会调用到 NativeWidgetDelegate中去做具体的处理。而要如何创建一个窗口的实现也会通过 NativeWidgetDelegate 回调到NativeWidgetPrivate 中在去进行进一步的处理。 Chromium 中多出都使用了 delegate这种模式。用来实现 MVC 模式的处理。
2、View
在chromium中,它们自己实现了一套称作 View 的UI 系统,View负责界面的渲染,布局和消息传递。其中的 view的分层如下图:
这张图是从chromium的代码中截出来的,可以从这里看出chromium的注释写的有多强大,在chromium中这种用文字表述一个设计结构的方式随处可见。从上图可以看出,Widget可以说是整个UI层的根,RootView是整个View 控件树的根,Widget会接受系统消息并将其装换为view控件能够识别的消息,并将此消息传递给views::RootView,并通过RootView 将消息分发给下层的View,其中Widget和RootView是一一对应的。
下层的View 主要分为三种:
用于表示整个窗体非客户区的 NonClientView ,负责设置窗口边框大小。他也是其他两种 View 的父view,原因很简单:他管着整个窗体的边框,所以其他的View必须是它的子view。
用于表示非客户区的内容的 NonClientFrameView ,负责绘制非客户区里面的元素,如标题栏,关闭按钮等等。
用于表示客户区和其内容的 ClientView ,负责生成各种窗口元素。
上图中另外几个view的意义如下:
NativeFrameView ,用于生成默认的窗口。
CustomFrameView ,用于自绘窗口边框。
DialogClientView ,用于生成对话框的窗口。
3、WidgetDelegate
WidgetDelegate 是一个为Widget 显示窗口时提供信息的接口,比如说窗口的标题,图标,以及是否可以被重设大小。同时它也可以提供事件回调接口,
每个 Widget 都有一个WidgetDelegate 提供的 ContentsView,这个 view 是被插入在窗口的 client area中的。
BrowserView 是views::WidgetDelegate 的子类,可以由 BrowserView 来直接和Widget 之间通信。
在chromium中,直接在Widget初始化的时候定义non_client_view_ =new NonClientView;而BrowserNonClientFrameView是其NonClientFrameView,
包括GlassBrowserFrameView和OpaqueBrowserFrameView两种。BrowserView是其 ClientView。
具体可以通过 views Windowing进一步了解。
所有new出来的view 都无需自己进行释放,它们会在窗口收到最后一个消息时把view树中的所有对象都释放掉。
窗口创建
在widget中,有几个这样的一些实现:
static Widget* CreateWindowWithParentAndBounds(WidgetDelegate* delegate, gfx::NativeWindow parent, const gfx::Rect& bounds);
这些函数是通过指定的属性来创建出一个相应的窗口。在这个函数的实现中会先创建一个Widget,之后再将其中的NonClientView创建出来,并在其中通过SetContentsView将RootView与NonClientView关联起来。
在chromium中,Chromium在启动的时候就会在StartupBrowserCreatorImpl中创建出一个browser,并初始化。而在构造Browser的时候会调用CreateBrowserWindow,来创建BrowserView及BrowserFrame。而BrowserFrame是Widget的一个子类。
Chromium的主窗口browser window有几个对象相互联系共同组成,这些对象之间的关系如图:
Frame:
frame也是整个browser window的一部分,管理着浏览器主窗口中的"non-client"区域,如标题栏、边框及其他传统区域。
Chromium中提供了一个BrowserFrame的frame,BrowserFrame类继承自views::Widget类。
Browser View :
BrowserView 对象管理着所有与 frame类似的元素,包括 tab strip, toolbar, bookmarks bar及其它的 UI 元素。
这些元素都是整个 browser window 中不可或缺的以部分。
BrowserView 是抽象接口 BrowserWindow的一个具体实现,Browser对象会通过这个接口与View进行联系。
Browser :
Browser 是整个browser window的核心状态及命令执行组件,它会通过与Browser Window接口的交互来更新UI。
窗口布局
chromium中可以为每一个View创建了一个专门用于控制布局的LayoutManager 。
在layout目录中,可以发现 Chromium 还提供几种不同的布局策略:
FillLayout ,用于将第一个子 View保持和当前 View 一样大的策略。
GridLayout ,将子View 排布成表格状。
BoxLayout ,排布成一个贴一个的格子。
窗口释放
所有 new出来的 view 都无需自己进行释放,它们会在窗口收到最后一个消息时把 view 树中的所有对象都释放掉。
在windows编译了Chrome源码,并生成VS2017的解决方案。通过强大的VS调试工具,步调一下Chrome的源码,希望能够对Chrome UI有更深入的理解。
ChromeMain(HINSTANCE__ * instance, sandbox::SandboxInterfaceInfo * sandbox_info, __int64 exe_entry_point_ticks)
content::ContentMain(const content::ContentMainParams & params)
service_manager::Main(const service_manager::MainParams & params)
content::ContentServiceManagerMainDelegate::RunEmbedderProcess()
content::ContentMainRunnerImpl::Run(bool start_service_manager_only)
content::RunBrowserProcessMain(const content::MainFunctionParams & main_function_params, content::ContentMainDelegate * delegate)
content::BrowserMain(const content::MainFunctionParams & parameters)
content::BrowserMainRunnerImpl::Initialize(const content::MainFunctionParams & parameters)
content::BrowserMainLoop::CreateStartupTasks()
content::StartupTaskRunner::RunAllTasksNow()
content::BrowserMainLoop::PreMainMessageLoopRun()
ChromeBrowserMainParts::PreMainMessageLoopRun()
ChromeBrowserMainParts::PreMainMessageLoopRunImpl()
chrome.dll!StartupBrowserCreator::LaunchBrowserForLastProfiles(const base::CommandLine & command_line, const base::FilePath & cur_dir, bool process_startup, Profile * last_used_profile, const std::vector<Profile *,std::allocator<Profile *> > & last_opened_profiles)
chrome.dll!StartupBrowserCreator::LaunchBrowser(const base::CommandLine & command_line, Profile * profile, const base::FilePath & cur_dir, chrome::startup::IsProcessStartup process_startup, chrome::startup::IsFirstRun is_first_run)
StartupBrowserCreatorImpl::Launch(Profile * profile, const std::vector<GURL,std::allocator<GURL> > & urls_to_open, bool process_startup)
StartupBrowserCreatorImpl::DetermineURLsAndLaunch(bool process_startup, const std::vector<GURL,std::allocator<GURL> > & cmd_line_urls)
StartupBrowserCreatorImpl::BrowserOpenBehavior behavior, unsigned int restore_options, bool process_startup, bool is_post_crash_launch)
StartupBrowserCreatorImpl::RestoreOrCreateBrowser(const std::vector<StartupTab,std::allocator<StartupTab> > & tabs,
我们在下面这个链接中具体分析Browser的启动流程:
https://blog.csdn.net/weixin_37972910/article/details/104970023
StartupBrowserCreatorImpl::OpenTabsInBrowser(Browser * browser, bool process_startup, const std::vector<StartupTab,std::allocator<StartupTab> > & tabs)
CreateBrowserWindow(std::unique_ptr<Browser,std::default_delete<Browser> > browser, bool user_gesture)
Browser::Browser(const Browser::CreateParams & params)
BrowserWindow::CreateBrowserWindow(std::unique_ptr<Browser,std::default_delete<Browser> > browser, bool user_gesture)
views::Widget::Init(const views::Widget::InitParams & in_params)
BrowserFrame::InitBrowserFrame()
views::View::AddChildView(views::View * view)
views::internal::RootView::SetContentsView(views::View * contents_view)
views::View::AddChildViewAt(views::View * view, int index)
views::View::PropagateAddNotifications(const views::View::ViewHierarchyChangedDetails & details, bool is_added_to_widget)
views::View::ViewHierarchyChangedImpl(bool register_accelerators, const views::View::ViewHierarchyChangedDetails & details)
views::NonClientView::ViewHierarchyChanged(const views::View::ViewHierarchyChangedDetails & details)
views::View::AddChildViewAt(views::View * view, int index)
views::View::PropagateAddNotifications(const views::View::ViewHierarchyChangedDetails & details, bool is_added_to_widget)
views::View::ViewHierarchyChangedImpl(bool register_accelerators, const views::View::ViewHierarchyChangedDetails & details)
BrowserView::ViewHierarchyChanged(const views::View::ViewHierarchyChangedDetails & details)
BrowserView::InitViews()
ToolbarView::Init()
LocationBarView::LocationBarView(Browser * browser, Profile * profile, CommandUpdater * command_updater, LocationBarView::Delegate * delegate, bool is_popup_mode)
LocationBar::LocationBar(Profile * profile)
BrowserView的界面结构:
// BrowserView layout (LTR one is pictured here).
//
// --------------------------------------------------------------------
// | TopContainerView (top_container_) |
// | -------------------------------------------------------------- |
// | | Tabs (tabstrip_) | |
// | |------------------------------------------------------------| |
// | | Navigation buttons, address bar, menu (toolbar_) | |
// | -------------------------------------------------------------- |
// |------------------------------------------------------------------|
// | All infobars (infobar_container_) [1] |
// |------------------------------------------------------------------|
// | Bookmarks (bookmark_bar_view_) [1] |
// |------------------------------------------------------------------|
// | Contents container (contents_container_) |
// | -------------------------------------------------------------- |
// | | devtools_web_view_ | |
// | |------------------------------------------------------------| |
// | | contents_web_view_ | |
// | -------------------------------------------------------------- |
// |------------------------------------------------------------------|
// | Active downloads (download_shelf_) |
// --------------------------------------------------------------------
//