Chromium Code Reviews| Index: win8/metro_driver/chrome_app_view_ash.cc |
| diff --git a/win8/metro_driver/chrome_app_view_ash.cc b/win8/metro_driver/chrome_app_view_ash.cc |
| index db2d9f30c4e66cfdd04b7b275fae33bde260a6c4..117b753da4976e9c7a781c61acc8011e263aa82b 100644 |
| --- a/win8/metro_driver/chrome_app_view_ash.cc |
| +++ b/win8/metro_driver/chrome_app_view_ash.cc |
| @@ -14,7 +14,6 @@ |
| #include "base/files/file_path.h" |
| #include "base/message_loop/message_loop.h" |
| #include "base/path_service.h" |
| -#include "base/threading/thread.h" |
| #include "base/win/metro.h" |
| #include "base/win/win_util.h" |
| #include "base/win/windows_version.h" |
| @@ -87,6 +86,9 @@ enum KeyModifier { |
| ALT = 4 |
| }; |
| +const int kChromeChannelPollTimerMs = 100; |
| +const UINT_PTR kChromeChannelPollTimerId = 0xdeadbabe; |
| + |
| // Helper function to send keystrokes via the SendInput function. |
| // mnemonic_char: The keystroke to be sent. |
| // modifiers: Combination with Alt, Ctrl, Shift, etc. |
| @@ -273,16 +275,6 @@ class ChromeChannelListener : public IPC::Listener { |
| ChromeAppViewAsh* app_view_; |
| }; |
| -bool WaitForChromeIPCConnection(const std::string& channel_name) { |
| - int ms_elapsed = 0; |
| - while (!IPC::Channel::IsNamedServerInitialized(channel_name) && |
| - ms_elapsed < 10000) { |
| - ms_elapsed += 100; |
| - Sleep(100); |
| - } |
| - return IPC::Channel::IsNamedServerInitialized(channel_name); |
| -} |
| - |
| void RunMessageLoop(winui::Core::ICoreDispatcher* dispatcher) { |
| // We're entering a nested message loop, let's allow dispatching |
| // tasks while we're in there. |
| @@ -359,6 +351,8 @@ bool LaunchChromeBrowserProcess(const wchar_t* additional_parameters, |
| return true; |
| } |
| +ChromeChannelListener* g_ui_channel_listener = NULL; |
|
scottmg
2014/09/24 19:33:35
could this be a member of ChromeAppViewAsh too so
ananta
2014/09/24 19:57:18
Done.
|
| + |
| } // namespace |
| // This class helps decoding the pointer properties of an event. |
| @@ -525,6 +519,8 @@ class ChromeAppViewAsh::PointerInfoHandler { |
| DISALLOW_COPY_AND_ASSIGN(PointerInfoHandler); |
| }; |
| +ChromeAppViewAsh* ChromeAppViewAsh::g_instance_ = NULL; |
| + |
| ChromeAppViewAsh::ChromeAppViewAsh() |
| : mouse_down_flags_(ui::EF_NONE), |
| ui_channel_(nullptr), |
| @@ -535,6 +531,9 @@ ChromeAppViewAsh::ChromeAppViewAsh() |
| DVLOG(1) << __FUNCTION__; |
| globals.previous_state = |
| winapp::Activation::ApplicationExecutionState_NotRunning; |
| + DCHECK(!g_instance_); |
| + |
| + g_instance_ = this; |
| } |
| ChromeAppViewAsh::~ChromeAppViewAsh() { |
| @@ -678,52 +677,30 @@ ChromeAppViewAsh::Run() { |
| CheckHR(hr, "Dispatcher failed."); |
| // Create the IPC channel IO thread. It needs to out-live the ChannelProxy. |
| - base::Thread io_thread("metro_IO_thread"); |
| + io_thread_.reset(new base::Thread("metro_IO_thread")); |
| base::Thread::Options options; |
| options.message_loop_type = base::MessageLoop::TYPE_IO; |
| - io_thread.StartWithOptions(options); |
| - |
| - // Start up Chrome and wait for the desired IPC server connection to exist. |
| - WaitForChromeIPCConnection(win8::kMetroViewerIPCChannelName); |
| + io_thread_->StartWithOptions(options); |
| - // In Aura mode we create an IPC channel to the browser, then ask it to |
| - // connect to us. |
| ChromeChannelListener ui_channel_listener(&ui_loop_, this); |
| - scoped_ptr<IPC::ChannelProxy> channel = |
| - IPC::ChannelProxy::Create(win8::kMetroViewerIPCChannelName, |
| - IPC::Channel::MODE_NAMED_CLIENT, |
| - &ui_channel_listener, |
| - io_thread.message_loop_proxy()); |
| - ui_channel_ = channel.get(); |
| - // Upon receipt of the MetroViewerHostMsg_SetTargetSurface message the |
| - // browser will use D3D from the browser process to present to our Window. |
| - ui_channel_->Send(new MetroViewerHostMsg_SetTargetSurface( |
| - gfx::NativeViewId(core_window_hwnd_), win32_dpi_scale_)); |
| - DVLOG(1) << "ICoreWindow sent " << core_window_hwnd_; |
| + // We can't do anything until the Chrome browser IPC channel is initialized. |
| + // Lazy initialization in a timer. |
| + g_ui_channel_listener = &ui_channel_listener; |
| - // Send an initial size message so that the Ash root window host gets sized |
| - // correctly. |
| - RECT rect = {0}; |
| - ::GetWindowRect(core_window_hwnd_, &rect); |
| - ui_channel_->Send( |
| - new MetroViewerHostMsg_WindowSizeChanged(rect.right - rect.left, |
| - rect.bottom - rect.top)); |
| + UINT_PTR channel_setup_timer_id = |
| + ::SetTimer(core_window_hwnd_, |
| + kChromeChannelPollTimerId, |
| + kChromeChannelPollTimerMs, |
| + &ChromeAppViewAsh::StartChromeOSMode); |
| - input_source_ = metro_driver::InputSource::Create(); |
| - if (input_source_) { |
| - input_source_->AddObserver(this); |
| - // Send an initial input source. |
| - OnInputSourceChanged(); |
| - } |
| - |
| - // Start receiving IME popup window notifications. |
| - metro_driver::AddImePopupObserver(this); |
| - |
| - // And post the task that'll do the inner Metro message pumping to it. |
| + // Post the task that'll do the inner Metro message pumping to it. |
| ui_loop_.PostTask(FROM_HERE, base::Bind(&RunMessageLoop, dispatcher.Get())); |
| ui_loop_.Run(); |
| + io_thread_.reset(NULL); |
| + ui_channel_.reset(NULL); |
| + |
| DVLOG(0) << "ProcessEvents done, hr=" << hr; |
| return hr; |
| } |
| @@ -1075,6 +1052,9 @@ HRESULT ChromeAppViewAsh::OnActivate( |
| HRESULT ChromeAppViewAsh::OnPointerMoved(winui::Core::ICoreWindow* sender, |
| winui::Core::IPointerEventArgs* args) { |
| + if (!ui_channel_) |
| + return S_OK; |
| + |
| PointerInfoHandler pointer(metro_dpi_scale_, win32_dpi_scale_); |
| HRESULT hr = pointer.Init(args); |
| if (FAILED(hr)) |
| @@ -1110,6 +1090,9 @@ HRESULT ChromeAppViewAsh::OnPointerMoved(winui::Core::ICoreWindow* sender, |
| HRESULT ChromeAppViewAsh::OnPointerPressed( |
| winui::Core::ICoreWindow* sender, |
| winui::Core::IPointerEventArgs* args) { |
| + if (!ui_channel_) |
| + return S_OK; |
| + |
| PointerInfoHandler pointer(metro_dpi_scale_, win32_dpi_scale_); |
| HRESULT hr = pointer.Init(args); |
| if (FAILED(hr)) |
| @@ -1133,6 +1116,9 @@ HRESULT ChromeAppViewAsh::OnPointerPressed( |
| HRESULT ChromeAppViewAsh::OnPointerReleased( |
| winui::Core::ICoreWindow* sender, |
| winui::Core::IPointerEventArgs* args) { |
| + if (!ui_channel_) |
| + return S_OK; |
| + |
| PointerInfoHandler pointer(metro_dpi_scale_, win32_dpi_scale_); |
| HRESULT hr = pointer.Init(args); |
| if (FAILED(hr)) |
| @@ -1158,6 +1144,9 @@ HRESULT ChromeAppViewAsh::OnPointerReleased( |
| HRESULT ChromeAppViewAsh::OnWheel( |
| winui::Core::ICoreWindow* sender, |
| winui::Core::IPointerEventArgs* args) { |
| + if (!ui_channel_) |
| + return S_OK; |
| + |
| PointerInfoHandler pointer(metro_dpi_scale_, win32_dpi_scale_); |
| HRESULT hr = pointer.Init(args); |
| if (FAILED(hr)) |
| @@ -1172,6 +1161,9 @@ HRESULT ChromeAppViewAsh::OnWheel( |
| HRESULT ChromeAppViewAsh::OnKeyDown( |
| winui::Core::ICoreWindow* sender, |
| winui::Core::IKeyEventArgs* args) { |
| + if (!ui_channel_) |
| + return S_OK; |
| + |
| winsys::VirtualKey virtual_key; |
| HRESULT hr = args->get_VirtualKey(&virtual_key); |
| if (FAILED(hr)) |
| @@ -1191,6 +1183,9 @@ HRESULT ChromeAppViewAsh::OnKeyDown( |
| HRESULT ChromeAppViewAsh::OnKeyUp( |
| winui::Core::ICoreWindow* sender, |
| winui::Core::IKeyEventArgs* args) { |
| + if (!ui_channel_) |
| + return S_OK; |
| + |
| winsys::VirtualKey virtual_key; |
| HRESULT hr = args->get_VirtualKey(&virtual_key); |
| if (FAILED(hr)) |
| @@ -1210,6 +1205,9 @@ HRESULT ChromeAppViewAsh::OnKeyUp( |
| HRESULT ChromeAppViewAsh::OnAcceleratorKeyDown( |
| winui::Core::ICoreDispatcher* sender, |
| winui::Core::IAcceleratorKeyEventArgs* args) { |
| + if (!ui_channel_) |
| + return S_OK; |
| + |
| winsys::VirtualKey virtual_key; |
| HRESULT hr = args->get_VirtualKey(&virtual_key); |
| if (FAILED(hr)) |
| @@ -1264,6 +1262,9 @@ HRESULT ChromeAppViewAsh::OnAcceleratorKeyDown( |
| HRESULT ChromeAppViewAsh::OnCharacterReceived( |
| winui::Core::ICoreWindow* sender, |
| winui::Core::ICharacterReceivedEventArgs* args) { |
| + if (!ui_channel_) |
| + return S_OK; |
| + |
| unsigned int char_code = 0; |
| HRESULT hr = args->get_KeyCode(&char_code); |
| if (FAILED(hr)) |
| @@ -1284,6 +1285,9 @@ HRESULT ChromeAppViewAsh::OnCharacterReceived( |
| HRESULT ChromeAppViewAsh::OnWindowActivated( |
| winui::Core::ICoreWindow* sender, |
| winui::Core::IWindowActivatedEventArgs* args) { |
| + if (!ui_channel_) |
| + return S_OK; |
| + |
| if (args) { |
| winui::Core::CoreWindowActivationState state; |
| HRESULT hr = args->get_WindowActivationState(&state); |
| @@ -1392,6 +1396,71 @@ HRESULT ChromeAppViewAsh::OnSizeChanged(winui::Core::ICoreWindow* sender, |
| return S_OK; |
| } |
| +// static |
| +void CALLBACK ChromeAppViewAsh::StartChromeOSMode(HWND core_window, |
| + UINT message, |
| + UINT_PTR timer_id, |
| + DWORD time) { |
| + static int ms_elapsed = 0; |
| + if (!IPC::Channel::IsNamedServerInitialized( |
| + win8::kMetroViewerIPCChannelName) && ms_elapsed < 10000) { |
| + ms_elapsed += 100; |
| + return; |
| + } |
| + |
| + ::KillTimer(core_window, kChromeChannelPollTimerId); |
| + |
| + if (!IPC::Channel::IsNamedServerInitialized( |
| + win8::kMetroViewerIPCChannelName)) { |
| + DVLOG(1) << "Failed to connect to chrome channel : " |
| + << win8::kMetroViewerIPCChannelName; |
| + DVLOG(1) << "Exiting. Elapsed time :" << ms_elapsed; |
| + PostMessage(core_window, WM_CLOSE, 0, 0); |
| + return; |
| + } |
| + |
| + DVLOG(1) << "Found channel : " << win8::kMetroViewerIPCChannelName; |
| + |
| + DCHECK(g_instance_); |
| + DCHECK(g_ui_channel_listener); |
| + |
| + // In Aura mode we create an IPC channel to the browser, then ask it to |
| + // connect to us. |
| + g_instance_->ui_channel_ = |
| + IPC::ChannelProxy::Create(win8::kMetroViewerIPCChannelName, |
| + IPC::Channel::MODE_NAMED_CLIENT, |
| + g_ui_channel_listener, |
| + g_instance_->io_thread_->message_loop_proxy()); |
| + DVLOG(1) << "Created channel proxy"; |
| + |
| + // Upon receipt of the MetroViewerHostMsg_SetTargetSurface message the |
| + // browser will use D3D from the browser process to present to our Window. |
| + g_instance_->ui_channel_->Send(new MetroViewerHostMsg_SetTargetSurface( |
| + gfx::NativeViewId(core_window), |
| + g_instance_->win32_dpi_scale_)); |
| + DVLOG(1) << "ICoreWindow sent " << core_window; |
| + |
| + // Send an initial size message so that the Ash root window host gets sized |
| + // correctly. |
| + RECT rect = {0}; |
| + ::GetWindowRect(core_window, &rect); |
| + g_instance_->ui_channel_->Send( |
| + new MetroViewerHostMsg_WindowSizeChanged(rect.right - rect.left, |
| + rect.bottom - rect.top)); |
| + |
| + g_instance_->input_source_ = metro_driver::InputSource::Create(); |
| + if (g_instance_->input_source_) { |
| + g_instance_->input_source_->AddObserver(g_instance_); |
| + // Send an initial input source. |
| + g_instance_->OnInputSourceChanged(); |
| + } |
| + |
| + // Start receiving IME popup window notifications. |
| + metro_driver::AddImePopupObserver(g_instance_); |
| + |
| + DVLOG(1) << "Channel setup complete"; |
| +} |
| + |
| /////////////////////////////////////////////////////////////////////////////// |
| ChromeAppViewFactory::ChromeAppViewFactory( |