Before reading this article, plz read http://luxtella.blogspot.de/2013/05/chromium-launching-process.html
Create MessagePump needed for TYPE_UI MessageLoops.
aura uses g_main_context for event source. why does aura depend on glib although creating pure X Window. It is just because of convenience. aura developers just did not want to reinvent timer and event source. let's look at how to integrate g_main_context and XDisplay events.MessagePumpGlib plays a role to create g_main_context and event sources to receive tasks from another thread. MessagePumpGlib is reused by MessagePumpGtk.
MessagePumpGlib::MessagePumpGlib() : state_(NULL), context_(g_main_context_default()), wakeup_gpollfd_(new GPollFD) { ... }
Before looking at MessagePumpAuraX11, let's look at MessagePumpGtk.
MessagePumpGtk plays a role to dispatch input events to main context.
MessagePumpGtk::MessagePumpGtk() : MessagePumpGlib() { gdk_event_handler_set(&EventDispatcher, this, NULL); }
So we can expect MessagePumpAuraX11's role is to dispatching X Display events to main loop. how to cast magic?
InitXSource() is crucial. It creates g event source monitoring X Display. When g_main_context handles the event source, XSourceDispatch() will be called. how smart!
MessagePumpAuraX11::MessagePumpAuraX11() : MessagePumpGlib(), x_source_(NULL) { InitializeXInput2(); InitializeXkb(); InitXSource(); // Can't put this in the initializer list because g_xdisplay may not exist // until after InitXSource(). x_root_window_ = DefaultRootWindow(g_xdisplay); } void MessagePumpAuraX11::InitXSource() { Display* display = GetDefaultXDisplay(); x_poll_.reset(new GPollFD()); x_poll_->fd = ConnectionNumber(display); x_poll_->events = G_IO_IN; x_source_ = g_source_new(&XSourceFuncs, sizeof(GSource)); g_source_add_poll(x_source_, x_poll_.get()); g_source_set_can_recurse(x_source_, TRUE); g_source_set_callback(x_source_, NULL, this, NULL); g_source_attach(x_source_, g_main_context_default()); } GSourceFuncs XSourceFuncs = { XSourcePrepare, XSourceCheck, XSourceDispatch, NULL }; gboolean XSourceDispatch(GSource* source, GSourceFunc unused_func, gpointer data) { base::MessagePumpAuraX11* pump = static_cast{base::MessagePumpAuraX11*}(data); return pump->DispatchXEvents(); }
base::MessagePumpGlib::MessagePumpGlib() at message_pump_glib.cc:142 0x4d5ec6 base::MessagePumpAuraX11::MessagePumpAuraX11() at message_pump_aurax11.cc:132 0x4d8510 base::MessageLoop::MessageLoop() at message_loop.cc:182 0x471fbb content::BrowserMainLoop::MainMessageLoopStart() at browser_main_loop.cc:370 0x81aa6e content::BrowserMainRunnerImpl::Initialize() at browser_main_runner.cc:94 0x6010f0 ShellBrowserMain() at shell_browser_main.cc:116 0x43cb76 content::ShellMainDelegate::RunProcess() at shell_main_delegate.cc:155 0x422892 content::RunNamedProcessTypeMain() at content_main_runner.cc:421 0xf12728 content::ContentMainRunnerImpl::Run() at content_main_runner.cc:756 0xf13833 content::ContentMain() at content_main.cc:35 0xf11b2f main() at shell_main.cc:36 0x4220cd
Main loop
MessagePumpGlib::RunWithDispatcher() is main loop. Chromium does not use glib main loop because chromium want to run chromium's own tasks without starvation.
X Display input events are handled by g_main_context_iteration(context_, block), because the input events are bound to glib event source.
void MessagePumpGlib::RunWithDispatcher(Delegate* delegate, MessagePumpDispatcher* dispatcher) { .. for (;;) { .. more_work_is_plausible = g_main_context_iteration(context_, block); .. more_work_is_plausible |= state_->delegate->DoWork(); .. more_work_is_plausible |= state_->delegate->DoDelayedWork(&delayed_work_time_); .. more_work_is_plausible = state_->delegate->DoIdleWork(); .. } .. }
base::MessagePumpGlib::RunWithDispatcher() at message_pump_glib.cc:199 0x4d6282 base::MessagePumpGlib::Run() at message_pump_glib.cc:296 0x4d67be base::MessageLoop::RunInternal() at message_loop.cc:441 0x47385a base::MessageLoop::RunHandler() at message_loop.cc:414 0x473704 base::RunLoop::Run() at run_loop.cc:45 0x497abc content::BrowserMainLoop::MainMessageLoopRun() at browser_main_loop.cc:873 0x81c6d7 content::BrowserMainLoop::RunMainMessageLoopParts() at browser_main_loop.cc:571 0x81b85e content::BrowserMainRunnerImpl::Run() at browser_main_runner.cc:125 0x6012bc ShellBrowserMain() at shell_browser_main.cc:180 0x43cfe3 content::ShellMainDelegate::RunProcess() at shell_main_delegate.cc:155 0x422892 content::RunNamedProcessTypeMain() at content_main_runner.cc:421 0xf12728 content::ContentMainRunnerImpl::Run() at content_main_runner.cc:756 0xf13833 content::ContentMain() at content_main.cc:35 0xf11b2f main() at shell_main.cc:36 0x4220cd
Create WebContentesViewAura.
This callstack is almost same to it of content_shell gtk. aura::Window is not related to native window or widget. It is something like cc::Layer + window event handler.
aura::Window::Window() at window.cc:51 0x51cfaa content::WebContentsViewAura::CreateView() at web_contents_view_aura.cc:944 0x7dab1b content::WebContentsImpl::Init() at web_contents_impl.cc:1,193 0x7bdcae content::WebContentsImpl::CreateWithOpener() at web_contents_impl.cc:405 0x7b897a content::WebContents::Create() at web_contents_impl.cc:262 0x7b78ed content::Shell::CreateNewWindow() at shell.cc:165 0x44db67 content::ShellBrowserMainParts::PreMainMessageLoopRun() at shell_browser_main_parts.cc:132 0x453289 content::BrowserMainLoop::CreateThreads() at browser_main_loop.cc:554 0x81b792 content::BrowserMainRunnerImpl::Initialize() at browser_main_runner.cc:112 0x601108 ShellBrowserMain() at shell_browser_main.cc:116 0x43cb76 content::ShellMainDelegate::RunProcess() at shell_main_delegate.cc:155 0x422892 content::RunNamedProcessTypeMain() at content_main_runner.cc:421 0xf12728 content::ContentMainRunnerImpl::Run() at content_main_runner.cc:756 0xf13833 content::ContentMain() at content_main.cc:35 0xf11b2f main() at shell_main.cc:36 0x4220cd
On the other hands, when loading another page, new RenderWidgetHostViewAura is created and new aura::Window is also created.
aura::Window::Window() at window.cc:51 0x51cfaa content::RenderWidgetHostViewAura::RenderWidgetHostViewAura() at render_widget_host_view_aura.cc:626 0x75f75d content::RenderWidgetHostView::CreateViewForWidget() at render_widget_host_view_aura.cc:2,992 0x769eb5 content::WebContentsViewAura::CreateViewForWidget() at web_contents_view_aura.cc:992 0x7dae49 content::WebContentsImpl::CreateRenderViewForRenderManager() at web_contents_impl.cc:3,481 0x7c7895 content::RenderViewHostManager::InitRenderView() at render_view_host_manager.cc:663 0x9c7720 content::RenderViewHostManager::Navigate() at render_view_host_manager.cc:140 0x9c5a6d ...
Create XWindow and RootWindow
Create XWindow
void DesktopRootWindowHostX11::InitX11Window( const Widget::InitParams& params) { .. xwindow_ = XCreateWindow( xdisplay_, x_root_window_, .. &swa); base::MessagePumpAuraX11::Current()->AddDispatcherForWindow(this, xwindow_); // TODO(erg): Maybe need to set a ViewProp here like in RWHL::RWHL(). long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask | KeyPressMask | KeyReleaseMask | EnterWindowMask | LeaveWindowMask | ExposureMask | VisibilityChangeMask | StructureNotifyMask | PropertyChangeMask | PointerMotionMask; XSelectInput(xdisplay_, xwindow_, event_mask); .. }
views::DesktopRootWindowHostX11::InitX11Window() at desktop_root_window_host_x11.cc:157 0xce36cb views::DesktopRootWindowHostX11::Init() at desktop_root_window_host_x11.cc:357 0xce45c1 views::DesktopNativeWidgetAura::InitNativeWidget() at desktop_native_widget_aura.cc:239 0xcdf031 views::Widget::Init() at widget.cc:374 0xcf5219 views::Widget::CreateWindowWithBounds() at widget.cc:239 0xcf4b5d content::Shell::PlatformCreateWindow() at shell_aura.cc:348 0x450379 content::Shell::CreateShell() at shell.cc:105 0x44d753 content::Shell::CreateNewWindow() at shell.cc:166 0x44db82 content::ShellBrowserMainParts::PreMainMessageLoopRun() at shell_browser_main_parts.cc:132 0x453289 content::BrowserMainLoop::CreateThreads() at browser_main_loop.cc:554 0x81b792 content::BrowserMainRunnerImpl::Initialize() at browser_main_runner.cc:112 0x601108 ShellBrowserMain() at shell_browser_main.cc:116 0x43cb76 content::ShellMainDelegate::RunProcess() at shell_main_delegate.cc:155 0x422892 content::RunNamedProcessTypeMain() at content_main_runner.cc:421 0xf12728 content::ContentMainRunnerImpl::Run() at content_main_runner.cc:756 0xf13833 content::ContentMain() at content_main.cc:35 0xf11b2f main() at shell_main.cc:36 0x4220cd
Create RootWindow
DesktopRootWindowHostX11 creates aura::RootWindow. RootWindow owns Compositor. FYI, chrome can create multi RootWindows. For example, context menu requires a XWindow and RootWindow.
RootWindow::RootWindow(const CreateParams& params) : Window(NULL), .. repostable_event_factory_(this) { .. compositor_.reset(new ui::Compositor(this, host_->GetAcceleratedWidget())); .. }
aura::RootWindow::RootWindow() at root_window.cc:162 0x512ef4 views::DesktopRootWindowHostX11::InitRootWindow() at desktop_root_window_host_x11.cc:230 0xce3add views::DesktopRootWindowHostX11::Init() at desktop_root_window_host_x11.cc:358 0xce45d4 views::DesktopNativeWidgetAura::InitNativeWidget() at desktop_native_widget_aura.cc:239 0xcdf031 ....
Handle mouse event
XDisplay input event is dispatched to MessagePumpAuraX11::DispatchXEvents(), because XDisplay events are bound with glib event source. Refer to "Create MessagePump needed for TYPE_UI MessageLoops."
DispatchXEvents() consumes all pending X events.
bool MessagePumpAuraX11::DispatchXEvents() { ... while (XPending(display)) { XEvent xev; XNextEvent(display, &xev); if (dispatcher && ProcessXEvent(dispatcher, &xev)) return TRUE; } return TRUE; }
DesktopRootWindowHostX11 installed dispatcher into MessagePumpAuraX11, so X event is dispatched to DesktopRootWindowHostX11 that owns specific X Window.
DesktopRootWindowHostX11::Dispatch(const base::NativeEvent& event) converts X Event to ui::Event.
And then finally aura::RootWindow::OnHostMouseEvent() handles ui::MouseEvent.
aura::RootWindow::OnHostMouseEvent() at root_window.cc:902 0x516c2d views::DesktopRootWindowHostX11::DispatchMouseEvent() at desktop_root_window_host_x11.cc:560 0xce540b views::DesktopRootWindowHostX11::Dispatch() at desktop_root_window_host_x11.cc:1,075 0xce7632 base::MessagePumpAuraX11::Dispatch() at message_pump_aurax11.cc:304 0x4d92cb base::MessagePumpAuraX11::ProcessXEvent() at message_pump_aurax11.cc:249 0x4d8f09 base::MessagePumpAuraX11::DispatchXEvents() at message_pump_aurax11.cc:191 0x4d8876 () at message_pump_aurax11.cc:33 0x4d8002 g_main_dispatch() at gmain.c:2,715 0x7ffff6973ab5 g_main_context_dispatch() at gmain.c:3,219 0x7ffff6973ab5 g_main_context_iterate() at gmain.c:3,290 0x7ffff6973de8 g_main_context_iteration() at gmain.c:3,351 0x7ffff6973ea4 base::MessagePumpGlib::RunWithDispatcher() at message_pump_glib.cc:199 0x4d6282 base::MessagePumpGlib::Run() at message_pump_glib.cc:296 0x4d67be base::MessageLoop::RunInternal() at message_loop.cc:441 0x47385a base::MessageLoop::RunHandler() at message_loop.cc:414 0x473704 base::RunLoop::Run() at run_loop.cc:45 0x497abc content::BrowserMainLoop::MainMessageLoopRun() at browser_main_loop.cc:873 0x81c6d7 content::BrowserMainLoop::RunMainMessageLoopParts() at browser_main_loop.cc:571 0x81b85e content::BrowserMainRunnerImpl::Run() at browser_main_runner.cc:125 0x6012bc ShellBrowserMain() at shell_browser_main.cc:180 0x43cfe3 content::ShellMainDelegate::RunProcess() at shell_main_delegate.cc:155 0x422892 content::RunNamedProcessTypeMain() at content_main_runner.cc:421 0xf12728 content::ContentMainRunnerImpl::Run() at content_main_runner.cc:756 0xf13833 content::ContentMain() at content_main.cc:35 0xf11b2f main() at shell_main.cc:36 0x4220cd
No comments:
Post a Comment