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..053ef8f09de7555bff185c3974414a07aba1c2e0 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,13 @@ enum KeyModifier { |
| ALT = 4 |
| }; |
| +const int kChromeChannelPollTimerMs = 100; |
| +const UINT_PTR kChromeChannelPollTimerId = 0xdeadbabe; |
| +static const wchar_t kChromeAppViewAshInstanceProp[] = |
| + L"ChromeAppViewAshInstance"; |
| +static const wchar_t kChromeChannelListenerProp[] = |
| + L"ChromeChannelListenerProp"; |
| + |
| // Helper function to send keystrokes via the SendInput function. |
| // mnemonic_char: The keystroke to be sent. |
| // modifiers: Combination with Alt, Ctrl, Shift, etc. |
| @@ -678,52 +684,32 @@ 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. |
| + ::SetProp(core_window_hwnd_, kChromeAppViewAshInstanceProp, this); |
| + ::SetProp(core_window_hwnd_, kChromeChannelListenerProp, |
| + &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)); |
| - |
| - 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); |
| + UINT_PTR channel_setup_timer_id = |
| + ::SetTimer(core_window_hwnd_, |
| + kChromeChannelPollTimerId, |
| + kChromeChannelPollTimerMs, |
| + &ChromeAppViewAsh::StartChromeOSMode); |
| - // 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 +1061,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 +1099,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 +1125,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 +1153,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 +1170,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 +1192,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 +1214,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 +1271,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 +1294,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 +1405,82 @@ 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( |
|
scottmg
2014/09/24 02:40:32
WaitForChromeIPCConnection isn't used any more, sh
ananta
2014/09/24 18:22:33
Done.
|
| + win8::kMetroViewerIPCChannelName) && ms_elapsed < 10000) { |
| + ms_elapsed += 100; |
| + return; |
| + } |
| + |
| + if (!IPC::Channel::IsNamedServerInitialized( |
| + win8::kMetroViewerIPCChannelName)) { |
| + DVLOG(1) << "Failed to connect to chrome channel : " |
| + << win8::kMetroViewerIPCChannelName; |
| + DVLOG(1) << "Exiting..."; |
| + PostMessage(core_window, WM_CLOSE, 0, 0); |
| + ::RemoveProp(core_window, kChromeAppViewAshInstanceProp); |
|
scottmg
2014/09/24 02:40:32
why do we need window props instead of plain globa
ananta
2014/09/24 18:22:33
Good point. Done.
|
| + ::RemoveProp(core_window, kChromeChannelListenerProp); |
| + ::KillTimer(core_window, kChromeChannelPollTimerId); |
|
scottmg
2014/09/24 02:40:32
killtimer here and below can move out above the if
ananta
2014/09/24 18:22:33
Done.
|
| + return; |
| + } |
| + |
| + ::KillTimer(core_window, kChromeChannelPollTimerId); |
| + |
| + DVLOG(1) << "Found channel : " << win8::kMetroViewerIPCChannelName; |
| + |
| + ChromeAppViewAsh* instance = reinterpret_cast<ChromeAppViewAsh*>( |
| + ::GetProp(core_window, kChromeAppViewAshInstanceProp)); |
| + DCHECK(instance); |
| + |
| + ChromeChannelListener* listener = reinterpret_cast<ChromeChannelListener*>( |
| + ::GetProp(core_window, kChromeChannelListenerProp)); |
| + DCHECK(listener); |
| + |
| + // In Aura mode we create an IPC channel to the browser, then ask it to |
| + // connect to us. |
| + instance->ui_channel_ = |
| + IPC::ChannelProxy::Create(win8::kMetroViewerIPCChannelName, |
| + IPC::Channel::MODE_NAMED_CLIENT, |
| + listener, |
| + 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. |
| + instance->ui_channel_->Send(new MetroViewerHostMsg_SetTargetSurface( |
| + gfx::NativeViewId(core_window), |
| + 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); |
| + instance->ui_channel_->Send( |
| + new MetroViewerHostMsg_WindowSizeChanged(rect.right - rect.left, |
| + rect.bottom - rect.top)); |
| + |
| + instance->input_source_ = metro_driver::InputSource::Create(); |
| + if (instance->input_source_) { |
| + instance->input_source_->AddObserver(instance); |
| + // Send an initial input source. |
| + instance->OnInputSourceChanged(); |
| + } |
| + |
| + // Start receiving IME popup window notifications. |
| + metro_driver::AddImePopupObserver(instance); |
| + |
| + ::RemoveProp(core_window, kChromeAppViewAshInstanceProp); |
| + ::RemoveProp(core_window, kChromeChannelListenerProp); |
| + |
| + DVLOG(1) << "Channel setup complete"; |
| +} |
| + |
| /////////////////////////////////////////////////////////////////////////////// |
| ChromeAppViewFactory::ChromeAppViewFactory( |