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