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( |