| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "win8/metro_driver/stdafx.h" | |
| 6 #include "win8/metro_driver/chrome_app_view_ash.h" | |
| 7 | |
| 8 #include <corewindow.h> | |
| 9 #include <shellapi.h> | |
| 10 #include <stdint.h> | |
| 11 #include <windows.foundation.h> | |
| 12 | |
| 13 #include "base/bind.h" | |
| 14 #include "base/command_line.h" | |
| 15 #include "base/files/file_path.h" | |
| 16 #include "base/macros.h" | |
| 17 #include "base/message_loop/message_loop.h" | |
| 18 #include "base/path_service.h" | |
| 19 #include "base/single_thread_task_runner.h" | |
| 20 #include "base/win/windows_version.h" | |
| 21 #include "chrome/common/chrome_switches.h" | |
| 22 #include "ipc/ipc_channel.h" | |
| 23 #include "ipc/ipc_channel_proxy.h" | |
| 24 #include "ipc/ipc_sender.h" | |
| 25 #include "ui/events/gesture_detection/motion_event.h" | |
| 26 #include "ui/events/win/system_event_state_lookup.h" | |
| 27 #include "ui/gfx/geometry/point_conversions.h" | |
| 28 #include "ui/gfx/win/dpi.h" | |
| 29 #include "ui/metro_viewer/metro_viewer_messages.h" | |
| 30 #include "win8/metro_driver/file_picker_ash.h" | |
| 31 #include "win8/metro_driver/ime/ime_popup_monitor.h" | |
| 32 #include "win8/metro_driver/ime/input_source.h" | |
| 33 #include "win8/metro_driver/ime/text_service.h" | |
| 34 #include "win8/metro_driver/metro_driver.h" | |
| 35 #include "win8/metro_driver/winrt_utils.h" | |
| 36 #include "win8/viewer/metro_viewer_constants.h" | |
| 37 | |
| 38 typedef winfoundtn::ITypedEventHandler< | |
| 39 winapp::Core::CoreApplicationView*, | |
| 40 winapp::Activation::IActivatedEventArgs*> ActivatedHandler; | |
| 41 | |
| 42 typedef winfoundtn::ITypedEventHandler< | |
| 43 winui::Core::CoreWindow*, | |
| 44 winui::Core::PointerEventArgs*> PointerEventHandler; | |
| 45 | |
| 46 typedef winfoundtn::ITypedEventHandler< | |
| 47 winui::Core::CoreWindow*, | |
| 48 winui::Core::KeyEventArgs*> KeyEventHandler; | |
| 49 | |
| 50 typedef winfoundtn::ITypedEventHandler< | |
| 51 winui::Core::CoreDispatcher*, | |
| 52 winui::Core::AcceleratorKeyEventArgs*> AcceleratorKeyEventHandler; | |
| 53 | |
| 54 typedef winfoundtn::ITypedEventHandler< | |
| 55 winui::Core::CoreWindow*, | |
| 56 winui::Core::CharacterReceivedEventArgs*> CharEventHandler; | |
| 57 | |
| 58 typedef winfoundtn::ITypedEventHandler< | |
| 59 winui::Core::CoreWindow*, | |
| 60 winui::Core::WindowActivatedEventArgs*> WindowActivatedHandler; | |
| 61 | |
| 62 typedef winfoundtn::ITypedEventHandler< | |
| 63 winui::Core::CoreWindow*, | |
| 64 winui::Core::WindowSizeChangedEventArgs*> SizeChangedHandler; | |
| 65 | |
| 66 typedef winfoundtn::ITypedEventHandler< | |
| 67 winui::Input::EdgeGesture*, | |
| 68 winui::Input::EdgeGestureEventArgs*> EdgeEventHandler; | |
| 69 | |
| 70 // This function is exported by chrome.exe. | |
| 71 typedef int (__cdecl *BreakpadExceptionHandler)(EXCEPTION_POINTERS* info); | |
| 72 | |
| 73 // Global information used across the metro driver. | |
| 74 struct Globals { | |
| 75 winapp::Activation::ApplicationExecutionState previous_state; | |
| 76 winapp::Core::ICoreApplicationExit* app_exit; | |
| 77 BreakpadExceptionHandler breakpad_exception_handler; | |
| 78 } globals; | |
| 79 | |
| 80 extern float GetModernUIScale(); | |
| 81 | |
| 82 namespace { | |
| 83 | |
| 84 enum KeyModifier { | |
| 85 NONE, | |
| 86 SHIFT = 1, | |
| 87 CONTROL = 2, | |
| 88 ALT = 4 | |
| 89 }; | |
| 90 | |
| 91 const int kChromeChannelPollTimerMs = 100; | |
| 92 | |
| 93 // Helper function to send keystrokes via the SendInput function. | |
| 94 // mnemonic_char: The keystroke to be sent. | |
| 95 // modifiers: Combination with Alt, Ctrl, Shift, etc. | |
| 96 void SendKeySequence( | |
| 97 WORD mnemonic_char, KeyModifier modifiers) { | |
| 98 INPUT keys[4] = {}; // Keyboard events | |
| 99 int key_count = 0; // Number of generated events | |
| 100 | |
| 101 if (modifiers & SHIFT) { | |
| 102 keys[key_count].type = INPUT_KEYBOARD; | |
| 103 keys[key_count].ki.wVk = VK_SHIFT; | |
| 104 keys[key_count].ki.wScan = MapVirtualKey(VK_SHIFT, 0); | |
| 105 key_count++; | |
| 106 } | |
| 107 | |
| 108 if (modifiers & CONTROL) { | |
| 109 keys[key_count].type = INPUT_KEYBOARD; | |
| 110 keys[key_count].ki.wVk = VK_CONTROL; | |
| 111 keys[key_count].ki.wScan = MapVirtualKey(VK_CONTROL, 0); | |
| 112 key_count++; | |
| 113 } | |
| 114 | |
| 115 if (modifiers & ALT) { | |
| 116 keys[key_count].type = INPUT_KEYBOARD; | |
| 117 keys[key_count].ki.wVk = VK_MENU; | |
| 118 keys[key_count].ki.wScan = MapVirtualKey(VK_MENU, 0); | |
| 119 key_count++; | |
| 120 } | |
| 121 | |
| 122 keys[key_count].type = INPUT_KEYBOARD; | |
| 123 keys[key_count].ki.wVk = mnemonic_char; | |
| 124 keys[key_count].ki.wScan = MapVirtualKey(mnemonic_char, 0); | |
| 125 key_count++; | |
| 126 | |
| 127 bool should_sleep = key_count > 1; | |
| 128 | |
| 129 // Send key downs. | |
| 130 for (int i = 0; i < key_count; i++) { | |
| 131 SendInput(1, &keys[ i ], sizeof(keys[0])); | |
| 132 keys[i].ki.dwFlags |= KEYEVENTF_KEYUP; | |
| 133 if (should_sleep) | |
| 134 Sleep(10); | |
| 135 } | |
| 136 | |
| 137 // Now send key ups in reverse order. | |
| 138 for (int i = key_count; i; i--) { | |
| 139 SendInput(1, &keys[ i - 1 ], sizeof(keys[0])); | |
| 140 if (should_sleep) | |
| 141 Sleep(10); | |
| 142 } | |
| 143 } | |
| 144 | |
| 145 class ChromeChannelListener : public IPC::Listener { | |
| 146 public: | |
| 147 ChromeChannelListener(base::MessageLoop* ui_loop, ChromeAppViewAsh* app_view) | |
| 148 : ui_task_runner_(ui_loop->task_runner()), app_view_(app_view) {} | |
| 149 | |
| 150 bool OnMessageReceived(const IPC::Message& message) override { | |
| 151 IPC_BEGIN_MESSAGE_MAP(ChromeChannelListener, message) | |
| 152 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_ActivateDesktop, | |
| 153 OnActivateDesktop) | |
| 154 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_MetroExit, OnMetroExit) | |
| 155 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_OpenURLOnDesktop, | |
| 156 OnOpenURLOnDesktop) | |
| 157 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_SetCursor, OnSetCursor) | |
| 158 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_DisplayFileOpen, | |
| 159 OnDisplayFileOpenDialog) | |
| 160 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_DisplayFileSaveAs, | |
| 161 OnDisplayFileSaveAsDialog) | |
| 162 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_DisplaySelectFolder, | |
| 163 OnDisplayFolderPicker) | |
| 164 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_SetCursorPos, OnSetCursorPos) | |
| 165 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_ImeCancelComposition, | |
| 166 OnImeCancelComposition) | |
| 167 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_ImeTextInputClientUpdated, | |
| 168 OnImeTextInputClientChanged) | |
| 169 IPC_MESSAGE_UNHANDLED(__debugbreak()) | |
| 170 IPC_END_MESSAGE_MAP() | |
| 171 return true; | |
| 172 } | |
| 173 | |
| 174 void OnChannelError() override { | |
| 175 DVLOG(1) << "Channel error. Exiting."; | |
| 176 ui_task_runner_->PostTask( | |
| 177 FROM_HERE, | |
| 178 base::Bind(&ChromeAppViewAsh::OnMetroExit, base::Unretained(app_view_), | |
| 179 TERMINATE_USING_KEY_SEQUENCE)); | |
| 180 | |
| 181 // In early Windows 8 versions the code above sometimes fails so we call | |
| 182 // it a second time with a NULL window which just calls Exit(). | |
| 183 ui_task_runner_->PostDelayedTask( | |
| 184 FROM_HERE, | |
| 185 base::Bind(&ChromeAppViewAsh::OnMetroExit, base::Unretained(app_view_), | |
| 186 TERMINATE_USING_PROCESS_EXIT), | |
| 187 base::TimeDelta::FromMilliseconds(100)); | |
| 188 } | |
| 189 | |
| 190 private: | |
| 191 void OnActivateDesktop(const base::FilePath& shortcut, bool ash_exit) { | |
| 192 ui_task_runner_->PostTask( | |
| 193 FROM_HERE, base::Bind(&ChromeAppViewAsh::OnActivateDesktop, | |
| 194 base::Unretained(app_view_), shortcut, ash_exit)); | |
| 195 } | |
| 196 | |
| 197 void OnMetroExit() { | |
| 198 ui_task_runner_->PostTask( | |
| 199 FROM_HERE, | |
| 200 base::Bind(&ChromeAppViewAsh::OnMetroExit, base::Unretained(app_view_), | |
| 201 TERMINATE_USING_KEY_SEQUENCE)); | |
| 202 } | |
| 203 | |
| 204 void OnOpenURLOnDesktop(const base::FilePath& shortcut, | |
| 205 const base::string16& url) { | |
| 206 ui_task_runner_->PostTask( | |
| 207 FROM_HERE, base::Bind(&ChromeAppViewAsh::OnOpenURLOnDesktop, | |
| 208 base::Unretained(app_view_), shortcut, url)); | |
| 209 } | |
| 210 | |
| 211 void OnSetCursor(int64_t cursor) { | |
| 212 ui_task_runner_->PostTask( | |
| 213 FROM_HERE, | |
| 214 base::Bind(&ChromeAppViewAsh::OnSetCursor, base::Unretained(app_view_), | |
| 215 reinterpret_cast<HCURSOR>(cursor))); | |
| 216 } | |
| 217 | |
| 218 void OnDisplayFileOpenDialog(const base::string16& title, | |
| 219 const base::string16& filter, | |
| 220 const base::FilePath& default_path, | |
| 221 bool allow_multiple_files) { | |
| 222 ui_task_runner_->PostTask( | |
| 223 FROM_HERE, base::Bind(&ChromeAppViewAsh::OnDisplayFileOpenDialog, | |
| 224 base::Unretained(app_view_), title, filter, | |
| 225 default_path, allow_multiple_files)); | |
| 226 } | |
| 227 | |
| 228 void OnDisplayFileSaveAsDialog( | |
| 229 const MetroViewerHostMsg_SaveAsDialogParams& params) { | |
| 230 ui_task_runner_->PostTask( | |
| 231 FROM_HERE, base::Bind(&ChromeAppViewAsh::OnDisplayFileSaveAsDialog, | |
| 232 base::Unretained(app_view_), params)); | |
| 233 } | |
| 234 | |
| 235 void OnDisplayFolderPicker(const base::string16& title) { | |
| 236 ui_task_runner_->PostTask( | |
| 237 FROM_HERE, base::Bind(&ChromeAppViewAsh::OnDisplayFolderPicker, | |
| 238 base::Unretained(app_view_), title)); | |
| 239 } | |
| 240 | |
| 241 void OnSetCursorPos(int x, int y) { | |
| 242 VLOG(1) << "In IPC OnSetCursorPos: " << x << ", " << y; | |
| 243 ui_task_runner_->PostTask(FROM_HERE, | |
| 244 base::Bind(&ChromeAppViewAsh::OnSetCursorPos, | |
| 245 base::Unretained(app_view_), x, y)); | |
| 246 } | |
| 247 | |
| 248 void OnImeCancelComposition() { | |
| 249 ui_task_runner_->PostTask( | |
| 250 FROM_HERE, base::Bind(&ChromeAppViewAsh::OnImeCancelComposition, | |
| 251 base::Unretained(app_view_))); | |
| 252 } | |
| 253 | |
| 254 void OnImeTextInputClientChanged( | |
| 255 const std::vector<int32_t>& input_scopes, | |
| 256 const std::vector<metro_viewer::CharacterBounds>& character_bounds) { | |
| 257 ui_task_runner_->PostTask( | |
| 258 FROM_HERE, base::Bind(&ChromeAppViewAsh::OnImeUpdateTextInputClient, | |
| 259 base::Unretained(app_view_), input_scopes, | |
| 260 character_bounds)); | |
| 261 } | |
| 262 | |
| 263 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_; | |
| 264 ChromeAppViewAsh* app_view_; | |
| 265 }; | |
| 266 | |
| 267 void RunMessageLoop(winui::Core::ICoreDispatcher* dispatcher) { | |
| 268 // We're entering a nested message loop, let's allow dispatching | |
| 269 // tasks while we're in there. | |
| 270 base::MessageLoop::current()->SetNestableTasksAllowed(true); | |
| 271 | |
| 272 // Enter main core message loop. There are several ways to exit it | |
| 273 // Nicely: | |
| 274 // 1 - User action like ALT-F4. | |
| 275 // 2 - Calling ICoreApplicationExit::Exit(). | |
| 276 // 3- Posting WM_CLOSE to the core window. | |
| 277 dispatcher->ProcessEvents( | |
| 278 winui::Core::CoreProcessEventsOption | |
| 279 ::CoreProcessEventsOption_ProcessUntilQuit); | |
| 280 | |
| 281 // Wind down the thread's chrome message loop. | |
| 282 base::MessageLoop::current()->QuitWhenIdle(); | |
| 283 } | |
| 284 | |
| 285 // Helper to return the state of the shift/control/alt keys. | |
| 286 uint32_t GetKeyboardEventFlags() { | |
| 287 uint32_t flags = 0; | |
| 288 if (ui::win::IsShiftPressed()) | |
| 289 flags |= ui::EF_SHIFT_DOWN; | |
| 290 if (ui::win::IsCtrlPressed()) | |
| 291 flags |= ui::EF_CONTROL_DOWN; | |
| 292 if (ui::win::IsAltPressed()) | |
| 293 flags |= ui::EF_ALT_DOWN; | |
| 294 return flags; | |
| 295 } | |
| 296 | |
| 297 bool LaunchChromeBrowserProcess(const wchar_t* additional_parameters, | |
| 298 winapp::Activation::IActivatedEventArgs* args) { | |
| 299 if (args) { | |
| 300 DVLOG(1) << __FUNCTION__ << ":" << ::GetCommandLineW(); | |
| 301 winapp::Activation::ActivationKind activation_kind; | |
| 302 CheckHR(args->get_Kind(&activation_kind)); | |
| 303 | |
| 304 DVLOG(1) << __FUNCTION__ << ", activation_kind=" << activation_kind; | |
| 305 | |
| 306 if (activation_kind == winapp::Activation::ActivationKind_Launch) { | |
| 307 mswr::ComPtr<winapp::Activation::ILaunchActivatedEventArgs> launch_args; | |
| 308 if (args->QueryInterface( | |
| 309 winapp::Activation::IID_ILaunchActivatedEventArgs, | |
| 310 &launch_args) == S_OK) { | |
| 311 DVLOG(1) << "Activate: ActivationKind_Launch"; | |
| 312 mswrw::HString launch_args_str; | |
| 313 launch_args->get_Arguments(launch_args_str.GetAddressOf()); | |
| 314 base::string16 actual_launch_args( | |
| 315 MakeStdWString(launch_args_str.Get())); | |
| 316 if (actual_launch_args == win8::kMetroViewerConnectVerb) { | |
| 317 DVLOG(1) << __FUNCTION__ << "Not launching chrome server"; | |
| 318 return true; | |
| 319 } | |
| 320 } | |
| 321 } | |
| 322 } | |
| 323 | |
| 324 DVLOG(1) << "Launching chrome server"; | |
| 325 base::FilePath chrome_exe_path; | |
| 326 | |
| 327 if (!PathService::Get(base::FILE_EXE, &chrome_exe_path)) | |
| 328 return false; | |
| 329 | |
| 330 base::string16 parameters = L"--silent-launch --connect-to-metro-viewer "; | |
| 331 if (additional_parameters) | |
| 332 parameters += additional_parameters; | |
| 333 | |
| 334 SHELLEXECUTEINFO sei = { sizeof(sei) }; | |
| 335 sei.nShow = SW_SHOWNORMAL; | |
| 336 sei.lpFile = chrome_exe_path.value().c_str(); | |
| 337 sei.lpDirectory = L""; | |
| 338 sei.lpParameters = parameters.c_str(); | |
| 339 ::ShellExecuteEx(&sei); | |
| 340 return true; | |
| 341 } | |
| 342 | |
| 343 } // namespace | |
| 344 | |
| 345 // This class helps decoding the pointer properties of an event. | |
| 346 class ChromeAppViewAsh::PointerInfoHandler { | |
| 347 public: | |
| 348 PointerInfoHandler(float metro_dpi_scale, float win32_dpi_scale) | |
| 349 : x_(0), | |
| 350 y_(0), | |
| 351 wheel_delta_(0), | |
| 352 pointer_id_(0), | |
| 353 update_kind_(winui::Input::PointerUpdateKind_Other), | |
| 354 timestamp_(0), | |
| 355 mouse_down_flags_(0), | |
| 356 is_horizontal_wheel_(0), | |
| 357 metro_dpi_scale_(metro_dpi_scale), | |
| 358 win32_dpi_scale_(win32_dpi_scale) {} | |
| 359 | |
| 360 HRESULT Init(winui::Core::IPointerEventArgs* args) { | |
| 361 HRESULT hr = args->get_CurrentPoint(&pointer_point_); | |
| 362 if (FAILED(hr)) | |
| 363 return hr; | |
| 364 | |
| 365 winfoundtn::Point point; | |
| 366 hr = pointer_point_->get_Position(&point); | |
| 367 if (FAILED(hr)) | |
| 368 return hr; | |
| 369 | |
| 370 mswr::ComPtr<winui::Input::IPointerPointProperties> properties; | |
| 371 hr = pointer_point_->get_Properties(&properties); | |
| 372 if (FAILED(hr)) | |
| 373 return hr; | |
| 374 | |
| 375 hr = properties->get_PointerUpdateKind(&update_kind_); | |
| 376 if (FAILED(hr)) | |
| 377 return hr; | |
| 378 | |
| 379 hr = properties->get_MouseWheelDelta(&wheel_delta_); | |
| 380 if (FAILED(hr)) | |
| 381 return hr; | |
| 382 | |
| 383 is_horizontal_wheel_ = 0; | |
| 384 properties->get_IsHorizontalMouseWheel(&is_horizontal_wheel_); | |
| 385 | |
| 386 // The input coordinates are in DIP based on the metro scale factor. | |
| 387 // We want to convert it to DIP based on the win32 scale factor. | |
| 388 // We scale the point by the metro scale factor and then scale down | |
| 389 // via the win32 scale factor which achieves the needful. | |
| 390 gfx::Point dip_point_metro(point.X, point.Y); | |
| 391 gfx::Point scaled_point_metro = | |
| 392 gfx::ScaleToCeiledPoint(dip_point_metro, metro_dpi_scale_); | |
| 393 gfx::Point dip_point_win32 = | |
| 394 gfx::ScaleToCeiledPoint(scaled_point_metro, 1.0 / win32_dpi_scale_); | |
| 395 x_ = dip_point_win32.x(); | |
| 396 y_ = dip_point_win32.y(); | |
| 397 | |
| 398 pointer_point_->get_Timestamp(×tamp_); | |
| 399 pointer_point_->get_PointerId(&pointer_id_); | |
| 400 // Map the OS touch event id to a range allowed by the gesture recognizer. | |
| 401 if (IsTouch()) | |
| 402 pointer_id_ %= ui::MotionEvent::MAX_TOUCH_POINT_COUNT; | |
| 403 | |
| 404 boolean left_button_state; | |
| 405 hr = properties->get_IsLeftButtonPressed(&left_button_state); | |
| 406 if (FAILED(hr)) | |
| 407 return hr; | |
| 408 if (left_button_state) | |
| 409 mouse_down_flags_ |= ui::EF_LEFT_MOUSE_BUTTON; | |
| 410 | |
| 411 boolean right_button_state; | |
| 412 hr = properties->get_IsRightButtonPressed(&right_button_state); | |
| 413 if (FAILED(hr)) | |
| 414 return hr; | |
| 415 if (right_button_state) | |
| 416 mouse_down_flags_ |= ui::EF_RIGHT_MOUSE_BUTTON; | |
| 417 | |
| 418 boolean middle_button_state; | |
| 419 hr = properties->get_IsMiddleButtonPressed(&middle_button_state); | |
| 420 if (FAILED(hr)) | |
| 421 return hr; | |
| 422 if (middle_button_state) | |
| 423 mouse_down_flags_ |= ui::EF_MIDDLE_MOUSE_BUTTON; | |
| 424 | |
| 425 return S_OK; | |
| 426 } | |
| 427 | |
| 428 bool IsType(windevs::Input::PointerDeviceType type) const { | |
| 429 mswr::ComPtr<windevs::Input::IPointerDevice> pointer_device; | |
| 430 CheckHR(pointer_point_->get_PointerDevice(&pointer_device)); | |
| 431 windevs::Input::PointerDeviceType device_type; | |
| 432 CheckHR(pointer_device->get_PointerDeviceType(&device_type)); | |
| 433 return (device_type == type); | |
| 434 } | |
| 435 | |
| 436 bool IsMouse() const { | |
| 437 return IsType(windevs::Input::PointerDeviceType_Mouse); | |
| 438 } | |
| 439 | |
| 440 bool IsTouch() const { | |
| 441 return IsType(windevs::Input::PointerDeviceType_Touch); | |
| 442 } | |
| 443 | |
| 444 int32_t wheel_delta() const { return wheel_delta_; } | |
| 445 | |
| 446 // Identifies the button that changed. | |
| 447 ui::EventFlags changed_button() const { | |
| 448 switch (update_kind_) { | |
| 449 case winui::Input::PointerUpdateKind_LeftButtonPressed: | |
| 450 return ui::EF_LEFT_MOUSE_BUTTON; | |
| 451 case winui::Input::PointerUpdateKind_LeftButtonReleased: | |
| 452 return ui::EF_LEFT_MOUSE_BUTTON; | |
| 453 case winui::Input::PointerUpdateKind_RightButtonPressed: | |
| 454 return ui::EF_RIGHT_MOUSE_BUTTON; | |
| 455 case winui::Input::PointerUpdateKind_RightButtonReleased: | |
| 456 return ui::EF_RIGHT_MOUSE_BUTTON; | |
| 457 case winui::Input::PointerUpdateKind_MiddleButtonPressed: | |
| 458 return ui::EF_MIDDLE_MOUSE_BUTTON; | |
| 459 case winui::Input::PointerUpdateKind_MiddleButtonReleased: | |
| 460 return ui::EF_MIDDLE_MOUSE_BUTTON; | |
| 461 default: | |
| 462 return ui::EF_NONE; | |
| 463 } | |
| 464 } | |
| 465 | |
| 466 uint32_t mouse_down_flags() const { return mouse_down_flags_; } | |
| 467 | |
| 468 int x() const { return x_; } | |
| 469 int y() const { return y_; } | |
| 470 | |
| 471 uint32_t pointer_id() const { return pointer_id_; } | |
| 472 | |
| 473 uint64_t timestamp() const { return timestamp_; } | |
| 474 | |
| 475 winui::Input::PointerUpdateKind update_kind() const { return update_kind_; } | |
| 476 | |
| 477 bool is_horizontal_wheel() const { return !!is_horizontal_wheel_; } | |
| 478 | |
| 479 private: | |
| 480 int x_; | |
| 481 int y_; | |
| 482 int wheel_delta_; | |
| 483 uint32_t pointer_id_; | |
| 484 winui::Input::PointerUpdateKind update_kind_; | |
| 485 mswr::ComPtr<winui::Input::IPointerPoint> pointer_point_; | |
| 486 uint64_t timestamp_; | |
| 487 | |
| 488 // Bitmask of ui::EventFlags corresponding to the buttons that are currently | |
| 489 // down. | |
| 490 uint32_t mouse_down_flags_; | |
| 491 | |
| 492 // Set to true for a horizontal wheel message. | |
| 493 boolean is_horizontal_wheel_; | |
| 494 | |
| 495 // The metro device scale factor as reported by the winrt interfaces. | |
| 496 float metro_dpi_scale_; | |
| 497 // The win32 dpi scale which is queried via GetDeviceCaps. Please refer to | |
| 498 // ui/gfx/win/dpi.cc for more information. | |
| 499 float win32_dpi_scale_; | |
| 500 | |
| 501 DISALLOW_COPY_AND_ASSIGN(PointerInfoHandler); | |
| 502 }; | |
| 503 | |
| 504 ChromeAppViewAsh::ChromeAppViewAsh() | |
| 505 : mouse_down_flags_(ui::EF_NONE), | |
| 506 ui_channel_(nullptr), | |
| 507 core_window_hwnd_(NULL), | |
| 508 metro_dpi_scale_(0), | |
| 509 win32_dpi_scale_(0), | |
| 510 last_cursor_(NULL), | |
| 511 channel_listener_(NULL) { | |
| 512 DVLOG(1) << __FUNCTION__; | |
| 513 globals.previous_state = | |
| 514 winapp::Activation::ApplicationExecutionState_NotRunning; | |
| 515 } | |
| 516 | |
| 517 ChromeAppViewAsh::~ChromeAppViewAsh() { | |
| 518 DVLOG(1) << __FUNCTION__; | |
| 519 } | |
| 520 | |
| 521 IFACEMETHODIMP | |
| 522 ChromeAppViewAsh::Initialize(winapp::Core::ICoreApplicationView* view) { | |
| 523 view_ = view; | |
| 524 DVLOG(1) << __FUNCTION__; | |
| 525 HRESULT hr = view_->add_Activated(mswr::Callback<ActivatedHandler>( | |
| 526 this, &ChromeAppViewAsh::OnActivate).Get(), | |
| 527 &activated_token_); | |
| 528 CheckHR(hr); | |
| 529 return hr; | |
| 530 } | |
| 531 | |
| 532 IFACEMETHODIMP | |
| 533 ChromeAppViewAsh::SetWindow(winui::Core::ICoreWindow* window) { | |
| 534 window_ = window; | |
| 535 DVLOG(1) << __FUNCTION__; | |
| 536 | |
| 537 // Retrieve the native window handle via the interop layer. | |
| 538 mswr::ComPtr<ICoreWindowInterop> interop; | |
| 539 HRESULT hr = window->QueryInterface(interop.GetAddressOf()); | |
| 540 CheckHR(hr); | |
| 541 hr = interop->get_WindowHandle(&core_window_hwnd_); | |
| 542 CheckHR(hr); | |
| 543 | |
| 544 text_service_ = metro_driver::CreateTextService(this, core_window_hwnd_); | |
| 545 | |
| 546 hr = window_->add_SizeChanged(mswr::Callback<SizeChangedHandler>( | |
| 547 this, &ChromeAppViewAsh::OnSizeChanged).Get(), | |
| 548 &sizechange_token_); | |
| 549 CheckHR(hr); | |
| 550 | |
| 551 // Register for pointer and keyboard notifications. We forward | |
| 552 // them to the browser process via IPC. | |
| 553 hr = window_->add_PointerMoved(mswr::Callback<PointerEventHandler>( | |
| 554 this, &ChromeAppViewAsh::OnPointerMoved).Get(), | |
| 555 &pointermoved_token_); | |
| 556 CheckHR(hr); | |
| 557 | |
| 558 hr = window_->add_PointerPressed(mswr::Callback<PointerEventHandler>( | |
| 559 this, &ChromeAppViewAsh::OnPointerPressed).Get(), | |
| 560 &pointerpressed_token_); | |
| 561 CheckHR(hr); | |
| 562 | |
| 563 hr = window_->add_PointerReleased(mswr::Callback<PointerEventHandler>( | |
| 564 this, &ChromeAppViewAsh::OnPointerReleased).Get(), | |
| 565 &pointerreleased_token_); | |
| 566 CheckHR(hr); | |
| 567 | |
| 568 hr = window_->add_KeyDown(mswr::Callback<KeyEventHandler>( | |
| 569 this, &ChromeAppViewAsh::OnKeyDown).Get(), | |
| 570 &keydown_token_); | |
| 571 CheckHR(hr); | |
| 572 | |
| 573 hr = window_->add_KeyUp(mswr::Callback<KeyEventHandler>( | |
| 574 this, &ChromeAppViewAsh::OnKeyUp).Get(), | |
| 575 &keyup_token_); | |
| 576 CheckHR(hr); | |
| 577 | |
| 578 mswr::ComPtr<winui::Core::ICoreDispatcher> dispatcher; | |
| 579 hr = window_->get_Dispatcher(dispatcher.GetAddressOf()); | |
| 580 CheckHR(hr, "Get Dispatcher failed."); | |
| 581 | |
| 582 mswr::ComPtr<winui::Core::ICoreAcceleratorKeys> accelerator_keys; | |
| 583 hr = dispatcher.CopyTo(__uuidof(winui::Core::ICoreAcceleratorKeys), | |
| 584 reinterpret_cast<void**>( | |
| 585 accelerator_keys.GetAddressOf())); | |
| 586 CheckHR(hr, "QI for ICoreAcceleratorKeys failed."); | |
| 587 hr = accelerator_keys->add_AcceleratorKeyActivated( | |
| 588 mswr::Callback<AcceleratorKeyEventHandler>( | |
| 589 this, &ChromeAppViewAsh::OnAcceleratorKeyDown).Get(), | |
| 590 &accel_keydown_token_); | |
| 591 CheckHR(hr); | |
| 592 | |
| 593 hr = window_->add_PointerWheelChanged(mswr::Callback<PointerEventHandler>( | |
| 594 this, &ChromeAppViewAsh::OnWheel).Get(), | |
| 595 &wheel_token_); | |
| 596 CheckHR(hr); | |
| 597 | |
| 598 hr = window_->add_CharacterReceived(mswr::Callback<CharEventHandler>( | |
| 599 this, &ChromeAppViewAsh::OnCharacterReceived).Get(), | |
| 600 &character_received_token_); | |
| 601 CheckHR(hr); | |
| 602 | |
| 603 hr = window_->add_Activated(mswr::Callback<WindowActivatedHandler>( | |
| 604 this, &ChromeAppViewAsh::OnWindowActivated).Get(), | |
| 605 &window_activated_token_); | |
| 606 CheckHR(hr); | |
| 607 | |
| 608 if (base::win::GetVersion() >= base::win::VERSION_WIN8) { | |
| 609 // Register for edge gesture notifications only for Windows 8 and above. | |
| 610 mswr::ComPtr<winui::Input::IEdgeGestureStatics> edge_gesture_statics; | |
| 611 hr = winrt_utils::CreateActivationFactory( | |
| 612 RuntimeClass_Windows_UI_Input_EdgeGesture, | |
| 613 edge_gesture_statics.GetAddressOf()); | |
| 614 CheckHR(hr); | |
| 615 | |
| 616 mswr::ComPtr<winui::Input::IEdgeGesture> edge_gesture; | |
| 617 hr = edge_gesture_statics->GetForCurrentView(&edge_gesture); | |
| 618 CheckHR(hr); | |
| 619 | |
| 620 hr = edge_gesture->add_Completed(mswr::Callback<EdgeEventHandler>( | |
| 621 this, &ChromeAppViewAsh::OnEdgeGestureCompleted).Get(), | |
| 622 &edgeevent_token_); | |
| 623 CheckHR(hr); | |
| 624 } | |
| 625 | |
| 626 // By initializing the direct 3D swap chain with the corewindow | |
| 627 // we can now directly blit to it from the browser process. | |
| 628 direct3d_helper_.Initialize(window); | |
| 629 DVLOG(1) << "Initialized Direct3D."; | |
| 630 | |
| 631 // On Windows 8+ the WinRT interface IDisplayProperties which we use to get | |
| 632 // device scale factor does not return the correct values in metro mode. | |
| 633 // To workaround this we retrieve the device scale factor via the win32 way | |
| 634 // and scale input coordinates accordingly to pass them in DIP to chrome. | |
| 635 // TODO(ananta). Investigate and fix. | |
| 636 metro_dpi_scale_ = GetModernUIScale(); | |
| 637 win32_dpi_scale_ = gfx::GetDPIScale(); | |
| 638 DVLOG(1) << "Metro Scale is " << metro_dpi_scale_; | |
| 639 DVLOG(1) << "Win32 Scale is " << win32_dpi_scale_; | |
| 640 return S_OK; | |
| 641 } | |
| 642 | |
| 643 IFACEMETHODIMP | |
| 644 ChromeAppViewAsh::Load(HSTRING entryPoint) { | |
| 645 // On Win7 |entryPoint| is NULL. | |
| 646 DVLOG(1) << __FUNCTION__; | |
| 647 return S_OK; | |
| 648 } | |
| 649 | |
| 650 IFACEMETHODIMP | |
| 651 ChromeAppViewAsh::Run() { | |
| 652 DVLOG(1) << __FUNCTION__; | |
| 653 mswr::ComPtr<winui::Core::ICoreDispatcher> dispatcher; | |
| 654 HRESULT hr = window_->get_Dispatcher(dispatcher.GetAddressOf()); | |
| 655 CheckHR(hr, "Dispatcher failed."); | |
| 656 | |
| 657 // Create the IPC channel IO thread. It needs to out-live the ChannelProxy. | |
| 658 io_thread_.reset(new base::Thread("metro_IO_thread")); | |
| 659 base::Thread::Options options; | |
| 660 options.message_loop_type = base::MessageLoop::TYPE_IO; | |
| 661 io_thread_->StartWithOptions(options); | |
| 662 | |
| 663 ChromeChannelListener ui_channel_listener(&ui_loop_, this); | |
| 664 channel_listener_ = &ui_channel_listener; | |
| 665 | |
| 666 // We can't do anything until the Chrome browser IPC channel is initialized. | |
| 667 // Lazy initialization in a timer. | |
| 668 ui_loop_.PostDelayedTask(FROM_HERE, | |
| 669 base::Bind(base::IgnoreResult(&ChromeAppViewAsh::StartChromeOSMode), | |
| 670 base::Unretained(this)), | |
| 671 base::TimeDelta::FromMilliseconds(kChromeChannelPollTimerMs)); | |
| 672 | |
| 673 // Post the task that'll do the inner Metro message pumping to it. | |
| 674 ui_loop_.PostTask(FROM_HERE, base::Bind(&RunMessageLoop, dispatcher.Get())); | |
| 675 ui_loop_.Run(); | |
| 676 | |
| 677 io_thread_.reset(NULL); | |
| 678 ui_channel_.reset(NULL); | |
| 679 channel_listener_ = NULL; | |
| 680 | |
| 681 DVLOG(0) << "ProcessEvents done, hr=" << hr; | |
| 682 return hr; | |
| 683 } | |
| 684 | |
| 685 IFACEMETHODIMP | |
| 686 ChromeAppViewAsh::Uninitialize() { | |
| 687 DVLOG(1) << __FUNCTION__; | |
| 688 metro_driver::RemoveImePopupObserver(this); | |
| 689 input_source_.reset(); | |
| 690 text_service_.reset(); | |
| 691 window_ = nullptr; | |
| 692 view_ = nullptr; | |
| 693 core_window_hwnd_ = NULL; | |
| 694 return S_OK; | |
| 695 } | |
| 696 | |
| 697 // static | |
| 698 HRESULT ChromeAppViewAsh::Unsnap() { | |
| 699 mswr::ComPtr<winui::ViewManagement::IApplicationViewStatics> view_statics; | |
| 700 HRESULT hr = winrt_utils::CreateActivationFactory( | |
| 701 RuntimeClass_Windows_UI_ViewManagement_ApplicationView, | |
| 702 view_statics.GetAddressOf()); | |
| 703 CheckHR(hr); | |
| 704 | |
| 705 winui::ViewManagement::ApplicationViewState state = | |
| 706 winui::ViewManagement::ApplicationViewState_FullScreenLandscape; | |
| 707 hr = view_statics->get_Value(&state); | |
| 708 CheckHR(hr); | |
| 709 | |
| 710 if (state == winui::ViewManagement::ApplicationViewState_Snapped) { | |
| 711 boolean success = FALSE; | |
| 712 hr = view_statics->TryUnsnap(&success); | |
| 713 | |
| 714 if (FAILED(hr) || !success) { | |
| 715 LOG(ERROR) << "Failed to unsnap. Error 0x" << hr; | |
| 716 if (SUCCEEDED(hr)) | |
| 717 hr = E_UNEXPECTED; | |
| 718 } | |
| 719 } | |
| 720 return hr; | |
| 721 } | |
| 722 | |
| 723 void ChromeAppViewAsh::OnActivateDesktop(const base::FilePath& file_path, | |
| 724 bool ash_exit) { | |
| 725 DVLOG(1) << "ChannelAppViewAsh::OnActivateDesktop\n"; | |
| 726 | |
| 727 if (ash_exit) { | |
| 728 // As we are the top level window, the exiting is done async so we manage | |
| 729 // to execute the entire function including the final Send(). | |
| 730 OnMetroExit(TERMINATE_USING_KEY_SEQUENCE); | |
| 731 } | |
| 732 | |
| 733 // We are just executing delegate_execute here without parameters. Assumption | |
| 734 // here is that this process will be reused by shell when asking for | |
| 735 // IExecuteCommand interface. | |
| 736 | |
| 737 // TODO(shrikant): Consolidate ShellExecuteEx with SEE_MASK_FLAG_LOG_USAGE | |
| 738 // and place it metro.h or similar accessible file from all code code paths | |
| 739 // using this function. | |
| 740 SHELLEXECUTEINFO sei = { sizeof(sei) }; | |
| 741 sei.fMask = SEE_MASK_FLAG_LOG_USAGE; | |
| 742 sei.nShow = SW_SHOWNORMAL; | |
| 743 sei.lpFile = file_path.value().c_str(); | |
| 744 sei.lpParameters = NULL; | |
| 745 if (!ash_exit) | |
| 746 sei.fMask |= SEE_MASK_NOCLOSEPROCESS; | |
| 747 ::ShellExecuteExW(&sei); | |
| 748 if (!ash_exit) { | |
| 749 ::TerminateProcess(sei.hProcess, 0); | |
| 750 ::CloseHandle(sei.hProcess); | |
| 751 } | |
| 752 } | |
| 753 | |
| 754 void ChromeAppViewAsh::OnOpenURLOnDesktop(const base::FilePath& shortcut, | |
| 755 const base::string16& url) { | |
| 756 base::FilePath::StringType file = shortcut.value(); | |
| 757 SHELLEXECUTEINFO sei = { sizeof(sei) }; | |
| 758 sei.fMask = SEE_MASK_FLAG_LOG_USAGE; | |
| 759 sei.nShow = SW_SHOWNORMAL; | |
| 760 sei.lpFile = file.c_str(); | |
| 761 sei.lpDirectory = L""; | |
| 762 sei.lpParameters = url.c_str(); | |
| 763 ShellExecuteEx(&sei); | |
| 764 } | |
| 765 | |
| 766 void ChromeAppViewAsh::OnSetCursor(HCURSOR cursor) { | |
| 767 ::SetCursor(cursor); | |
| 768 last_cursor_ = cursor; | |
| 769 } | |
| 770 | |
| 771 void ChromeAppViewAsh::OnDisplayFileOpenDialog( | |
| 772 const base::string16& title, | |
| 773 const base::string16& filter, | |
| 774 const base::FilePath& default_path, | |
| 775 bool allow_multiple_files) { | |
| 776 DVLOG(1) << __FUNCTION__; | |
| 777 | |
| 778 // The OpenFilePickerSession instance is deleted when we receive a | |
| 779 // callback from the OpenFilePickerSession class about the completion of the | |
| 780 // operation. | |
| 781 FilePickerSessionBase* file_picker_ = | |
| 782 new OpenFilePickerSession(this, | |
| 783 title, | |
| 784 filter, | |
| 785 default_path, | |
| 786 allow_multiple_files); | |
| 787 file_picker_->Run(); | |
| 788 } | |
| 789 | |
| 790 void ChromeAppViewAsh::OnDisplayFileSaveAsDialog( | |
| 791 const MetroViewerHostMsg_SaveAsDialogParams& params) { | |
| 792 DVLOG(1) << __FUNCTION__; | |
| 793 | |
| 794 // The SaveFilePickerSession instance is deleted when we receive a | |
| 795 // callback from the SaveFilePickerSession class about the completion of the | |
| 796 // operation. | |
| 797 FilePickerSessionBase* file_picker_ = | |
| 798 new SaveFilePickerSession(this, params); | |
| 799 file_picker_->Run(); | |
| 800 } | |
| 801 | |
| 802 void ChromeAppViewAsh::OnDisplayFolderPicker(const base::string16& title) { | |
| 803 DVLOG(1) << __FUNCTION__; | |
| 804 // The FolderPickerSession instance is deleted when we receive a | |
| 805 // callback from the FolderPickerSession class about the completion of the | |
| 806 // operation. | |
| 807 FilePickerSessionBase* file_picker_ = new FolderPickerSession(this, title); | |
| 808 file_picker_->Run(); | |
| 809 } | |
| 810 | |
| 811 void ChromeAppViewAsh::OnSetCursorPos(int x, int y) { | |
| 812 if (ui_channel_) { | |
| 813 ::SetCursorPos(x, y); | |
| 814 DVLOG(1) << "In UI OnSetCursorPos: " << x << ", " << y; | |
| 815 ui_channel_->Send(new MetroViewerHostMsg_SetCursorPosAck()); | |
| 816 // Generate a fake mouse move which matches the SetCursor coordinates as | |
| 817 // the browser expects to receive a mouse move for these coordinates. | |
| 818 // It is not clear why we don't receive a real mouse move in response to | |
| 819 // the SetCursorPos calll above. | |
| 820 ui_channel_->Send(new MetroViewerHostMsg_MouseMoved(x, y, 0)); | |
| 821 } | |
| 822 } | |
| 823 | |
| 824 void ChromeAppViewAsh::OnOpenFileCompleted( | |
| 825 OpenFilePickerSession* open_file_picker, | |
| 826 bool success) { | |
| 827 DVLOG(1) << __FUNCTION__; | |
| 828 DVLOG(1) << "Success: " << success; | |
| 829 if (ui_channel_) { | |
| 830 if (open_file_picker->allow_multi_select()) { | |
| 831 ui_channel_->Send(new MetroViewerHostMsg_MultiFileOpenDone( | |
| 832 success, open_file_picker->filenames())); | |
| 833 } else { | |
| 834 ui_channel_->Send(new MetroViewerHostMsg_FileOpenDone( | |
| 835 success, base::FilePath(open_file_picker->result()))); | |
| 836 } | |
| 837 } | |
| 838 delete open_file_picker; | |
| 839 } | |
| 840 | |
| 841 void ChromeAppViewAsh::OnSaveFileCompleted( | |
| 842 SaveFilePickerSession* save_file_picker, | |
| 843 bool success) { | |
| 844 DVLOG(1) << __FUNCTION__; | |
| 845 DVLOG(1) << "Success: " << success; | |
| 846 if (ui_channel_) { | |
| 847 ui_channel_->Send(new MetroViewerHostMsg_FileSaveAsDone( | |
| 848 success, | |
| 849 base::FilePath(save_file_picker->result()), | |
| 850 save_file_picker->filter_index())); | |
| 851 } | |
| 852 delete save_file_picker; | |
| 853 } | |
| 854 | |
| 855 void ChromeAppViewAsh::OnFolderPickerCompleted( | |
| 856 FolderPickerSession* folder_picker, | |
| 857 bool success) { | |
| 858 DVLOG(1) << __FUNCTION__; | |
| 859 DVLOG(1) << "Success: " << success; | |
| 860 if (ui_channel_) { | |
| 861 ui_channel_->Send(new MetroViewerHostMsg_SelectFolderDone( | |
| 862 success, | |
| 863 base::FilePath(folder_picker->result()))); | |
| 864 } | |
| 865 delete folder_picker; | |
| 866 } | |
| 867 | |
| 868 void ChromeAppViewAsh::OnImeCancelComposition() { | |
| 869 if (!text_service_) | |
| 870 return; | |
| 871 text_service_->CancelComposition(); | |
| 872 } | |
| 873 | |
| 874 void ChromeAppViewAsh::OnImeUpdateTextInputClient( | |
| 875 const std::vector<int32_t>& input_scopes, | |
| 876 const std::vector<metro_viewer::CharacterBounds>& character_bounds) { | |
| 877 if (!text_service_) | |
| 878 return; | |
| 879 text_service_->OnDocumentChanged(input_scopes, character_bounds); | |
| 880 } | |
| 881 | |
| 882 void ChromeAppViewAsh::OnImePopupChanged(ImePopupObserver::EventType event) { | |
| 883 if (!ui_channel_) | |
| 884 return; | |
| 885 switch (event) { | |
| 886 case ImePopupObserver::kPopupShown: | |
| 887 ui_channel_->Send(new MetroViewerHostMsg_ImeCandidatePopupChanged(true)); | |
| 888 return; | |
| 889 case ImePopupObserver::kPopupHidden: | |
| 890 ui_channel_->Send(new MetroViewerHostMsg_ImeCandidatePopupChanged(false)); | |
| 891 return; | |
| 892 case ImePopupObserver::kPopupUpdated: | |
| 893 // TODO(kochi): Support this event for W3C IME API proposal. | |
| 894 // See crbug.com/238585. | |
| 895 return; | |
| 896 default: | |
| 897 NOTREACHED() << "unknown event type: " << event; | |
| 898 return; | |
| 899 } | |
| 900 } | |
| 901 | |
| 902 // Function to Exit metro chrome cleanly. If we are in the foreground | |
| 903 // then we try and exit by sending an Alt+F4 key combination to the core | |
| 904 // window which ensures that the chrome application tile does not show up in | |
| 905 // the running metro apps list on the top left corner. | |
| 906 void ChromeAppViewAsh::OnMetroExit(MetroTerminateMethod method) { | |
| 907 if (base::win::GetVersion() >= base::win::VERSION_WIN8) { | |
| 908 HWND core_window = core_window_hwnd(); | |
| 909 if (method == TERMINATE_USING_KEY_SEQUENCE && core_window != NULL && | |
| 910 core_window == ::GetForegroundWindow()) { | |
| 911 DVLOG(1) << "We are in the foreground. Exiting via Alt F4"; | |
| 912 SendKeySequence(VK_F4, ALT); | |
| 913 if (ui_channel_) | |
| 914 ui_channel_->Close(); | |
| 915 } else { | |
| 916 globals.app_exit->Exit(); | |
| 917 } | |
| 918 } else { | |
| 919 if (ui_channel_) | |
| 920 ui_channel_->Close(); | |
| 921 | |
| 922 HWND core_window = core_window_hwnd(); | |
| 923 ::PostMessage(core_window, WM_CLOSE, 0, 0); | |
| 924 | |
| 925 globals.app_exit->Exit(); | |
| 926 } | |
| 927 } | |
| 928 | |
| 929 void ChromeAppViewAsh::OnInputSourceChanged() { | |
| 930 if (!input_source_) | |
| 931 return; | |
| 932 | |
| 933 DCHECK(ui_channel_); | |
| 934 | |
| 935 LANGID langid = 0; | |
| 936 bool is_ime = false; | |
| 937 if (!input_source_->GetActiveSource(&langid, &is_ime)) { | |
| 938 LOG(ERROR) << "GetActiveSource failed"; | |
| 939 return; | |
| 940 } | |
| 941 ui_channel_->Send(new MetroViewerHostMsg_ImeInputSourceChanged(langid, | |
| 942 is_ime)); | |
| 943 } | |
| 944 | |
| 945 void ChromeAppViewAsh::OnCompositionChanged( | |
| 946 const base::string16& text, | |
| 947 int32_t selection_start, | |
| 948 int32_t selection_end, | |
| 949 const std::vector<metro_viewer::UnderlineInfo>& underlines) { | |
| 950 ui_channel_->Send(new MetroViewerHostMsg_ImeCompositionChanged( | |
| 951 text, selection_start, selection_end, underlines)); | |
| 952 } | |
| 953 | |
| 954 void ChromeAppViewAsh::OnTextCommitted(const base::string16& text) { | |
| 955 ui_channel_->Send(new MetroViewerHostMsg_ImeTextCommitted(text)); | |
| 956 } | |
| 957 | |
| 958 void ChromeAppViewAsh::SendMouseButton(int x, | |
| 959 int y, | |
| 960 int extra, | |
| 961 ui::EventType event_type, | |
| 962 uint32_t flags, | |
| 963 ui::EventFlags changed_button, | |
| 964 bool is_horizontal_wheel) { | |
| 965 if (!ui_channel_) | |
| 966 return; | |
| 967 MetroViewerHostMsg_MouseButtonParams params; | |
| 968 params.x = static_cast<int32_t>(x); | |
| 969 params.y = static_cast<int32_t>(y); | |
| 970 params.extra = static_cast<int32_t>(extra); | |
| 971 params.event_type = event_type; | |
| 972 params.flags = static_cast<int32_t>(flags); | |
| 973 params.changed_button = changed_button; | |
| 974 params.is_horizontal_wheel = is_horizontal_wheel; | |
| 975 ui_channel_->Send(new MetroViewerHostMsg_MouseButton(params)); | |
| 976 } | |
| 977 | |
| 978 void ChromeAppViewAsh::GenerateMouseEventFromMoveIfNecessary( | |
| 979 const PointerInfoHandler& pointer) { | |
| 980 ui::EventType event_type; | |
| 981 // For aura we want the flags to include the button that was released, thus | |
| 982 // we or the old and new. | |
| 983 uint32_t mouse_down_flags = pointer.mouse_down_flags() | mouse_down_flags_; | |
| 984 mouse_down_flags_ = pointer.mouse_down_flags(); | |
| 985 switch (pointer.update_kind()) { | |
| 986 case winui::Input::PointerUpdateKind_LeftButtonPressed: | |
| 987 case winui::Input::PointerUpdateKind_RightButtonPressed: | |
| 988 case winui::Input::PointerUpdateKind_MiddleButtonPressed: | |
| 989 event_type = ui::ET_MOUSE_PRESSED; | |
| 990 break; | |
| 991 case winui::Input::PointerUpdateKind_LeftButtonReleased: | |
| 992 case winui::Input::PointerUpdateKind_RightButtonReleased: | |
| 993 case winui::Input::PointerUpdateKind_MiddleButtonReleased: | |
| 994 event_type = ui::ET_MOUSE_RELEASED; | |
| 995 break; | |
| 996 default: | |
| 997 return; | |
| 998 } | |
| 999 SendMouseButton(pointer.x(), pointer.y(), 0, event_type, | |
| 1000 mouse_down_flags | GetKeyboardEventFlags(), | |
| 1001 pointer.changed_button(), pointer.is_horizontal_wheel()); | |
| 1002 } | |
| 1003 | |
| 1004 HRESULT ChromeAppViewAsh::OnActivate( | |
| 1005 winapp::Core::ICoreApplicationView*, | |
| 1006 winapp::Activation::IActivatedEventArgs* args) { | |
| 1007 DVLOG(1) << __FUNCTION__; | |
| 1008 // Note: If doing more work in this function, you migth need to call | |
| 1009 // get_PreviousExecutionState() and skip the work if the result is | |
| 1010 // ApplicationExecutionState_Running and globals.previous_state is too. | |
| 1011 args->get_PreviousExecutionState(&globals.previous_state); | |
| 1012 DVLOG(1) << "Previous Execution State: " << globals.previous_state; | |
| 1013 | |
| 1014 winapp::Activation::ActivationKind activation_kind; | |
| 1015 CheckHR(args->get_Kind(&activation_kind)); | |
| 1016 DVLOG(1) << "Activation kind: " << activation_kind; | |
| 1017 | |
| 1018 if (activation_kind == winapp::Activation::ActivationKind_Search) | |
| 1019 HandleSearchRequest(args); | |
| 1020 else if (activation_kind == winapp::Activation::ActivationKind_Protocol) | |
| 1021 HandleProtocolRequest(args); | |
| 1022 else | |
| 1023 LaunchChromeBrowserProcess(NULL, args); | |
| 1024 // We call ICoreWindow::Activate after the handling for the search/protocol | |
| 1025 // requests because Chrome can be launched to handle a search request which | |
| 1026 // in turn launches the chrome browser process in desktop mode via | |
| 1027 // ShellExecute. If we call ICoreWindow::Activate before this, then | |
| 1028 // Windows kills the metro chrome process when it calls ShellExecute. Seems | |
| 1029 // to be a bug. | |
| 1030 window_->Activate(); | |
| 1031 return S_OK; | |
| 1032 } | |
| 1033 | |
| 1034 HRESULT ChromeAppViewAsh::OnPointerMoved(winui::Core::ICoreWindow* sender, | |
| 1035 winui::Core::IPointerEventArgs* args) { | |
| 1036 if (!ui_channel_) | |
| 1037 return S_OK; | |
| 1038 | |
| 1039 PointerInfoHandler pointer(metro_dpi_scale_, win32_dpi_scale_); | |
| 1040 HRESULT hr = pointer.Init(args); | |
| 1041 if (FAILED(hr)) | |
| 1042 return hr; | |
| 1043 | |
| 1044 if (pointer.IsMouse()) { | |
| 1045 // If the mouse was moved towards the charms or the OS specific section, | |
| 1046 // the cursor may change from what the browser last set. Restore it here. | |
| 1047 if (::GetCursor() != last_cursor_) | |
| 1048 SetCursor(last_cursor_); | |
| 1049 | |
| 1050 GenerateMouseEventFromMoveIfNecessary(pointer); | |
| 1051 ui_channel_->Send(new MetroViewerHostMsg_MouseMoved( | |
| 1052 pointer.x(), | |
| 1053 pointer.y(), | |
| 1054 mouse_down_flags_ | GetKeyboardEventFlags())); | |
| 1055 } else { | |
| 1056 DCHECK(pointer.IsTouch()); | |
| 1057 ui_channel_->Send(new MetroViewerHostMsg_TouchMoved(pointer.x(), | |
| 1058 pointer.y(), | |
| 1059 pointer.timestamp(), | |
| 1060 pointer.pointer_id())); | |
| 1061 } | |
| 1062 return S_OK; | |
| 1063 } | |
| 1064 | |
| 1065 // NOTE: From experimentation, it seems like Metro only sends a PointerPressed | |
| 1066 // event for the first button pressed and the last button released in a sequence | |
| 1067 // of mouse events. | |
| 1068 // For example, a sequence of LEFT_DOWN, RIGHT_DOWN, LEFT_UP, RIGHT_UP results | |
| 1069 // only in PointerPressed(LEFT)/PointerReleased(RIGHT) events. Intermediary | |
| 1070 // presses and releases are tracked in OnPointMoved(). | |
| 1071 HRESULT ChromeAppViewAsh::OnPointerPressed( | |
| 1072 winui::Core::ICoreWindow* sender, | |
| 1073 winui::Core::IPointerEventArgs* args) { | |
| 1074 if (!ui_channel_) | |
| 1075 return S_OK; | |
| 1076 | |
| 1077 PointerInfoHandler pointer(metro_dpi_scale_, win32_dpi_scale_); | |
| 1078 HRESULT hr = pointer.Init(args); | |
| 1079 if (FAILED(hr)) | |
| 1080 return hr; | |
| 1081 | |
| 1082 if (pointer.IsMouse()) { | |
| 1083 mouse_down_flags_ = pointer.mouse_down_flags(); | |
| 1084 SendMouseButton(pointer.x(), pointer.y(), 0, ui::ET_MOUSE_PRESSED, | |
| 1085 mouse_down_flags_ | GetKeyboardEventFlags(), | |
| 1086 pointer.changed_button(), pointer.is_horizontal_wheel()); | |
| 1087 } else { | |
| 1088 DCHECK(pointer.IsTouch()); | |
| 1089 ui_channel_->Send(new MetroViewerHostMsg_TouchDown(pointer.x(), | |
| 1090 pointer.y(), | |
| 1091 pointer.timestamp(), | |
| 1092 pointer.pointer_id())); | |
| 1093 } | |
| 1094 return S_OK; | |
| 1095 } | |
| 1096 | |
| 1097 HRESULT ChromeAppViewAsh::OnPointerReleased( | |
| 1098 winui::Core::ICoreWindow* sender, | |
| 1099 winui::Core::IPointerEventArgs* args) { | |
| 1100 if (!ui_channel_) | |
| 1101 return S_OK; | |
| 1102 | |
| 1103 PointerInfoHandler pointer(metro_dpi_scale_, win32_dpi_scale_); | |
| 1104 HRESULT hr = pointer.Init(args); | |
| 1105 if (FAILED(hr)) | |
| 1106 return hr; | |
| 1107 | |
| 1108 if (pointer.IsMouse()) { | |
| 1109 mouse_down_flags_ = ui::EF_NONE; | |
| 1110 SendMouseButton(pointer.x(), pointer.y(), 0, ui::ET_MOUSE_RELEASED, | |
| 1111 static_cast<uint32_t>(pointer.changed_button()) | | |
| 1112 GetKeyboardEventFlags(), | |
| 1113 pointer.changed_button(), pointer.is_horizontal_wheel()); | |
| 1114 } else { | |
| 1115 DCHECK(pointer.IsTouch()); | |
| 1116 ui_channel_->Send(new MetroViewerHostMsg_TouchUp(pointer.x(), | |
| 1117 pointer.y(), | |
| 1118 pointer.timestamp(), | |
| 1119 pointer.pointer_id())); | |
| 1120 } | |
| 1121 return S_OK; | |
| 1122 } | |
| 1123 | |
| 1124 HRESULT ChromeAppViewAsh::OnWheel( | |
| 1125 winui::Core::ICoreWindow* sender, | |
| 1126 winui::Core::IPointerEventArgs* args) { | |
| 1127 if (!ui_channel_) | |
| 1128 return S_OK; | |
| 1129 | |
| 1130 PointerInfoHandler pointer(metro_dpi_scale_, win32_dpi_scale_); | |
| 1131 HRESULT hr = pointer.Init(args); | |
| 1132 if (FAILED(hr)) | |
| 1133 return hr; | |
| 1134 DCHECK(pointer.IsMouse()); | |
| 1135 SendMouseButton(pointer.x(), pointer.y(), pointer.wheel_delta(), | |
| 1136 ui::ET_MOUSEWHEEL, GetKeyboardEventFlags(), ui::EF_NONE, | |
| 1137 pointer.is_horizontal_wheel()); | |
| 1138 return S_OK; | |
| 1139 } | |
| 1140 | |
| 1141 HRESULT ChromeAppViewAsh::OnKeyDown( | |
| 1142 winui::Core::ICoreWindow* sender, | |
| 1143 winui::Core::IKeyEventArgs* args) { | |
| 1144 if (!ui_channel_) | |
| 1145 return S_OK; | |
| 1146 | |
| 1147 winsys::VirtualKey virtual_key; | |
| 1148 HRESULT hr = args->get_VirtualKey(&virtual_key); | |
| 1149 if (FAILED(hr)) | |
| 1150 return hr; | |
| 1151 winui::Core::CorePhysicalKeyStatus status; | |
| 1152 hr = args->get_KeyStatus(&status); | |
| 1153 if (FAILED(hr)) | |
| 1154 return hr; | |
| 1155 | |
| 1156 ui_channel_->Send(new MetroViewerHostMsg_KeyDown(virtual_key, | |
| 1157 status.RepeatCount, | |
| 1158 status.ScanCode, | |
| 1159 GetKeyboardEventFlags())); | |
| 1160 return S_OK; | |
| 1161 } | |
| 1162 | |
| 1163 HRESULT ChromeAppViewAsh::OnKeyUp( | |
| 1164 winui::Core::ICoreWindow* sender, | |
| 1165 winui::Core::IKeyEventArgs* args) { | |
| 1166 if (!ui_channel_) | |
| 1167 return S_OK; | |
| 1168 | |
| 1169 winsys::VirtualKey virtual_key; | |
| 1170 HRESULT hr = args->get_VirtualKey(&virtual_key); | |
| 1171 if (FAILED(hr)) | |
| 1172 return hr; | |
| 1173 winui::Core::CorePhysicalKeyStatus status; | |
| 1174 hr = args->get_KeyStatus(&status); | |
| 1175 if (FAILED(hr)) | |
| 1176 return hr; | |
| 1177 | |
| 1178 ui_channel_->Send(new MetroViewerHostMsg_KeyUp(virtual_key, | |
| 1179 status.RepeatCount, | |
| 1180 status.ScanCode, | |
| 1181 GetKeyboardEventFlags())); | |
| 1182 return S_OK; | |
| 1183 } | |
| 1184 | |
| 1185 HRESULT ChromeAppViewAsh::OnAcceleratorKeyDown( | |
| 1186 winui::Core::ICoreDispatcher* sender, | |
| 1187 winui::Core::IAcceleratorKeyEventArgs* args) { | |
| 1188 if (!ui_channel_) | |
| 1189 return S_OK; | |
| 1190 | |
| 1191 winsys::VirtualKey virtual_key; | |
| 1192 HRESULT hr = args->get_VirtualKey(&virtual_key); | |
| 1193 if (FAILED(hr)) | |
| 1194 return hr; | |
| 1195 winui::Core::CorePhysicalKeyStatus status; | |
| 1196 hr = args->get_KeyStatus(&status); | |
| 1197 if (FAILED(hr)) | |
| 1198 return hr; | |
| 1199 | |
| 1200 winui::Core::CoreAcceleratorKeyEventType event_type; | |
| 1201 hr = args->get_EventType(&event_type); | |
| 1202 if (FAILED(hr)) | |
| 1203 return hr; | |
| 1204 | |
| 1205 uint32_t keyboard_flags = GetKeyboardEventFlags(); | |
| 1206 | |
| 1207 switch (event_type) { | |
| 1208 case winui::Core::CoreAcceleratorKeyEventType_SystemCharacter: | |
| 1209 ui_channel_->Send(new MetroViewerHostMsg_Character(virtual_key, | |
| 1210 status.RepeatCount, | |
| 1211 status.ScanCode, | |
| 1212 keyboard_flags)); | |
| 1213 break; | |
| 1214 | |
| 1215 case winui::Core::CoreAcceleratorKeyEventType_SystemKeyDown: | |
| 1216 // Don't send the Alt + F4 combination to Chrome as this is intended to | |
| 1217 // shut the metro environment down. Reason we check for Control here is | |
| 1218 // Windows does not shutdown metro if Ctrl is pressed along with Alt F4. | |
| 1219 // Other key combinations with Alt F4 shutdown metro. | |
| 1220 if ((virtual_key == VK_F4) && ((keyboard_flags & ui::EF_ALT_DOWN) && | |
| 1221 !(keyboard_flags & ui::EF_CONTROL_DOWN))) | |
| 1222 return S_OK; | |
| 1223 // Don't send the EF_ALT_DOWN modifier along with the IPC message for | |
| 1224 // the Alt or F10 key. The accelerator for VKEY_MENU is registered | |
| 1225 // without modifiers in Chrome for historical reasons. Not sending the | |
| 1226 // EF_ALT_DOWN modifier ensures that the accelerator is processed | |
| 1227 // correctly. | |
| 1228 if (virtual_key == winsys::VirtualKey_Menu) | |
| 1229 keyboard_flags &= ~ui::EF_ALT_DOWN; | |
| 1230 ui_channel_->Send(new MetroViewerHostMsg_KeyDown(virtual_key, | |
| 1231 status.RepeatCount, | |
| 1232 status.ScanCode, | |
| 1233 keyboard_flags)); | |
| 1234 break; | |
| 1235 | |
| 1236 case winui::Core::CoreAcceleratorKeyEventType_SystemKeyUp: | |
| 1237 ui_channel_->Send(new MetroViewerHostMsg_KeyUp(virtual_key, | |
| 1238 status.RepeatCount, | |
| 1239 status.ScanCode, | |
| 1240 keyboard_flags)); | |
| 1241 break; | |
| 1242 | |
| 1243 default: | |
| 1244 break; | |
| 1245 } | |
| 1246 return S_OK; | |
| 1247 } | |
| 1248 | |
| 1249 HRESULT ChromeAppViewAsh::OnCharacterReceived( | |
| 1250 winui::Core::ICoreWindow* sender, | |
| 1251 winui::Core::ICharacterReceivedEventArgs* args) { | |
| 1252 if (!ui_channel_) | |
| 1253 return S_OK; | |
| 1254 | |
| 1255 unsigned int char_code = 0; | |
| 1256 HRESULT hr = args->get_KeyCode(&char_code); | |
| 1257 if (FAILED(hr)) | |
| 1258 return hr; | |
| 1259 | |
| 1260 winui::Core::CorePhysicalKeyStatus status; | |
| 1261 hr = args->get_KeyStatus(&status); | |
| 1262 if (FAILED(hr)) | |
| 1263 return hr; | |
| 1264 | |
| 1265 ui_channel_->Send(new MetroViewerHostMsg_Character(char_code, | |
| 1266 status.RepeatCount, | |
| 1267 status.ScanCode, | |
| 1268 GetKeyboardEventFlags())); | |
| 1269 return S_OK; | |
| 1270 } | |
| 1271 | |
| 1272 HRESULT ChromeAppViewAsh::OnWindowActivated( | |
| 1273 winui::Core::ICoreWindow* sender, | |
| 1274 winui::Core::IWindowActivatedEventArgs* args) { | |
| 1275 if (!ui_channel_) | |
| 1276 return S_OK; | |
| 1277 | |
| 1278 if (args) { | |
| 1279 winui::Core::CoreWindowActivationState state; | |
| 1280 HRESULT hr = args->get_WindowActivationState(&state); | |
| 1281 if (FAILED(hr)) | |
| 1282 return hr; | |
| 1283 | |
| 1284 // Treat both full activation (Ash was reopened from the Start Screen or | |
| 1285 // from any other Metro entry point in Windows) and pointer activation | |
| 1286 // (user clicked back in Ash after using another app on another monitor) | |
| 1287 // the same. | |
| 1288 if (state == winui::Core::CoreWindowActivationState_CodeActivated || | |
| 1289 state == winui::Core::CoreWindowActivationState_PointerActivated) { | |
| 1290 ui_channel_->Send(new MetroViewerHostMsg_WindowActivated(false)); | |
| 1291 } | |
| 1292 } else { | |
| 1293 // On Windows 7, we force a repaint when the window is activated. | |
| 1294 ui_channel_->Send(new MetroViewerHostMsg_WindowActivated(true)); | |
| 1295 } | |
| 1296 if (text_service_) | |
| 1297 text_service_->OnWindowActivated(); | |
| 1298 return S_OK; | |
| 1299 } | |
| 1300 | |
| 1301 HRESULT ChromeAppViewAsh::HandleSearchRequest( | |
| 1302 winapp::Activation::IActivatedEventArgs* args) { | |
| 1303 mswr::ComPtr<winapp::Activation::ISearchActivatedEventArgs> search_args; | |
| 1304 CheckHR(args->QueryInterface( | |
| 1305 winapp::Activation::IID_ISearchActivatedEventArgs, &search_args)); | |
| 1306 | |
| 1307 if (!ui_channel_) { | |
| 1308 DVLOG(1) << "Launched to handle search request"; | |
| 1309 LaunchChromeBrowserProcess(L"--windows8-search", args); | |
| 1310 } | |
| 1311 | |
| 1312 mswrw::HString search_string; | |
| 1313 CheckHR(search_args->get_QueryText(search_string.GetAddressOf())); | |
| 1314 base::string16 search_text(MakeStdWString(search_string.Get())); | |
| 1315 | |
| 1316 ui_loop_.PostTask(FROM_HERE, | |
| 1317 base::Bind(&ChromeAppViewAsh::OnSearchRequest, | |
| 1318 base::Unretained(this), | |
| 1319 search_text)); | |
| 1320 return S_OK; | |
| 1321 } | |
| 1322 | |
| 1323 HRESULT ChromeAppViewAsh::HandleProtocolRequest( | |
| 1324 winapp::Activation::IActivatedEventArgs* args) { | |
| 1325 DVLOG(1) << __FUNCTION__; | |
| 1326 if (!ui_channel_) | |
| 1327 DVLOG(1) << "Launched to handle url request"; | |
| 1328 | |
| 1329 mswr::ComPtr<winapp::Activation::IProtocolActivatedEventArgs> | |
| 1330 protocol_args; | |
| 1331 CheckHR(args->QueryInterface( | |
| 1332 winapp::Activation::IID_IProtocolActivatedEventArgs, | |
| 1333 &protocol_args)); | |
| 1334 | |
| 1335 mswr::ComPtr<winfoundtn::IUriRuntimeClass> uri; | |
| 1336 protocol_args->get_Uri(&uri); | |
| 1337 mswrw::HString url; | |
| 1338 uri->get_AbsoluteUri(url.GetAddressOf()); | |
| 1339 base::string16 actual_url(MakeStdWString(url.Get())); | |
| 1340 DVLOG(1) << "Received url request: " << actual_url; | |
| 1341 | |
| 1342 ui_loop_.PostTask(FROM_HERE, | |
| 1343 base::Bind(&ChromeAppViewAsh::OnNavigateToUrl, | |
| 1344 base::Unretained(this), | |
| 1345 actual_url)); | |
| 1346 return S_OK; | |
| 1347 } | |
| 1348 | |
| 1349 HRESULT ChromeAppViewAsh::OnEdgeGestureCompleted( | |
| 1350 winui::Input::IEdgeGesture* gesture, | |
| 1351 winui::Input::IEdgeGestureEventArgs* args) { | |
| 1352 if (ui_channel_) | |
| 1353 ui_channel_->Send(new MetroViewerHostMsg_EdgeGesture()); | |
| 1354 return S_OK; | |
| 1355 } | |
| 1356 | |
| 1357 void ChromeAppViewAsh::OnSearchRequest(const base::string16& search_string) { | |
| 1358 if (ui_channel_) | |
| 1359 ui_channel_->Send(new MetroViewerHostMsg_SearchRequest(search_string)); | |
| 1360 } | |
| 1361 | |
| 1362 void ChromeAppViewAsh::OnNavigateToUrl(const base::string16& url) { | |
| 1363 if (ui_channel_) | |
| 1364 ui_channel_->Send(new MetroViewerHostMsg_OpenURL(url)); | |
| 1365 } | |
| 1366 | |
| 1367 HRESULT ChromeAppViewAsh::OnSizeChanged(winui::Core::ICoreWindow* sender, | |
| 1368 winui::Core::IWindowSizeChangedEventArgs* args) { | |
| 1369 if (!window_ || !ui_channel_) { | |
| 1370 return S_OK; | |
| 1371 } | |
| 1372 | |
| 1373 // winui::Core::IWindowSizeChangedEventArgs args->Size appears to return | |
| 1374 // scaled values under HiDPI. We will instead use GetWindowRect() which | |
| 1375 // should always return values in Pixels. | |
| 1376 RECT rect = {0}; | |
| 1377 ::GetWindowRect(core_window_hwnd_, &rect); | |
| 1378 | |
| 1379 uint32_t cx = static_cast<uint32_t>(rect.right - rect.left); | |
| 1380 uint32_t cy = static_cast<uint32_t>(rect.bottom - rect.top); | |
| 1381 | |
| 1382 DVLOG(1) << "Window size changed: width=" << cx << ", height=" << cy; | |
| 1383 ui_channel_->Send(new MetroViewerHostMsg_WindowSizeChanged(cx, cy)); | |
| 1384 return S_OK; | |
| 1385 } | |
| 1386 | |
| 1387 void ChromeAppViewAsh::StartChromeOSMode() { | |
| 1388 static int ms_elapsed = 0; | |
| 1389 | |
| 1390 if (!IPC::Channel::IsNamedServerInitialized( | |
| 1391 win8::kMetroViewerIPCChannelName) && ms_elapsed < 10000) { | |
| 1392 ms_elapsed += 100; | |
| 1393 ui_loop_.PostDelayedTask(FROM_HERE, | |
| 1394 base::Bind(base::IgnoreResult(&ChromeAppViewAsh::StartChromeOSMode), | |
| 1395 base::Unretained(this)), | |
| 1396 base::TimeDelta::FromMilliseconds(kChromeChannelPollTimerMs)); | |
| 1397 return; | |
| 1398 } | |
| 1399 | |
| 1400 if (!IPC::Channel::IsNamedServerInitialized( | |
| 1401 win8::kMetroViewerIPCChannelName)) { | |
| 1402 DVLOG(1) << "Failed to connect to chrome channel : " | |
| 1403 << win8::kMetroViewerIPCChannelName; | |
| 1404 DVLOG(1) << "Exiting. Elapsed time :" << ms_elapsed; | |
| 1405 PostMessage(core_window_hwnd_, WM_CLOSE, 0, 0); | |
| 1406 return; | |
| 1407 } | |
| 1408 | |
| 1409 DVLOG(1) << "Found channel : " << win8::kMetroViewerIPCChannelName; | |
| 1410 | |
| 1411 DCHECK(channel_listener_); | |
| 1412 | |
| 1413 // In Aura mode we create an IPC channel to the browser, then ask it to | |
| 1414 // connect to us. | |
| 1415 ui_channel_ = | |
| 1416 IPC::ChannelProxy::Create(win8::kMetroViewerIPCChannelName, | |
| 1417 IPC::Channel::MODE_NAMED_CLIENT, | |
| 1418 channel_listener_, | |
| 1419 io_thread_->task_runner()); | |
| 1420 DVLOG(1) << "Created channel proxy"; | |
| 1421 | |
| 1422 // Upon receipt of the MetroViewerHostMsg_SetTargetSurface message the | |
| 1423 // browser will use D3D from the browser process to present to our Window. | |
| 1424 ui_channel_->Send(new MetroViewerHostMsg_SetTargetSurface( | |
| 1425 gfx::NativeViewId(core_window_hwnd_), | |
| 1426 win32_dpi_scale_)); | |
| 1427 DVLOG(1) << "ICoreWindow sent " << core_window_hwnd_; | |
| 1428 | |
| 1429 // Send an initial size message so that the Ash root window host gets sized | |
| 1430 // correctly. | |
| 1431 RECT rect = {0}; | |
| 1432 ::GetWindowRect(core_window_hwnd_, &rect); | |
| 1433 ui_channel_->Send( | |
| 1434 new MetroViewerHostMsg_WindowSizeChanged(rect.right - rect.left, | |
| 1435 rect.bottom - rect.top)); | |
| 1436 | |
| 1437 input_source_ = metro_driver::InputSource::Create(); | |
| 1438 if (input_source_) { | |
| 1439 input_source_->AddObserver(this); | |
| 1440 // Send an initial input source. | |
| 1441 OnInputSourceChanged(); | |
| 1442 } | |
| 1443 | |
| 1444 // Start receiving IME popup window notifications. | |
| 1445 metro_driver::AddImePopupObserver(this); | |
| 1446 | |
| 1447 DVLOG(1) << "Channel setup complete"; | |
| 1448 } | |
| 1449 | |
| 1450 /////////////////////////////////////////////////////////////////////////////// | |
| 1451 | |
| 1452 ChromeAppViewFactory::ChromeAppViewFactory( | |
| 1453 winapp::Core::ICoreApplication* icore_app) { | |
| 1454 mswr::ComPtr<winapp::Core::ICoreApplication> core_app(icore_app); | |
| 1455 mswr::ComPtr<winapp::Core::ICoreApplicationExit> app_exit; | |
| 1456 CheckHR(core_app.As(&app_exit)); | |
| 1457 globals.app_exit = app_exit.Detach(); | |
| 1458 } | |
| 1459 | |
| 1460 IFACEMETHODIMP | |
| 1461 ChromeAppViewFactory::CreateView(winapp::Core::IFrameworkView** view) { | |
| 1462 *view = mswr::Make<ChromeAppViewAsh>().Detach(); | |
| 1463 return (*view) ? S_OK : E_OUTOFMEMORY; | |
| 1464 } | |
| OLD | NEW |