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 "stdafx.h" 6 #include <corewindow.h> 7 #include <shobjidl.h> 8 9 #include "base/logging.h" 10 #include "ui/gfx/geometry/safe_integer_conversions.h" 11 #include "ui/gfx/win/msg_util.h" 12 13 #pragma comment(lib, "shell32.lib") 14 15 EXTERN_C IMAGE_DOS_HEADER __ImageBase; 16 // Even though we only create a single window, we need to keep this 17 // count because of the hidden window used by the UI message loop of 18 // the metro viewer. 19 int g_window_count = 0; 20 21 const wchar_t kAshWin7AppId[] = L"Google.Chrome.AshWin7.1"; 22 23 extern float GetModernUIScale(); 24 25 LRESULT CALLBACK WndProc(HWND hwnd, UINT message, 26 WPARAM wparam, LPARAM lparam) { 27 PAINTSTRUCT ps; 28 HDC hdc; 29 switch (message) { 30 case WM_CREATE: 31 ++g_window_count; 32 break; 33 case WM_PAINT: 34 hdc = ::BeginPaint(hwnd, &ps); 35 ::EndPaint(hwnd, &ps); 36 break; 37 case WM_CLOSE: 38 ::DestroyWindow(hwnd); 39 break; 40 case WM_DESTROY: 41 --g_window_count; 42 if (!g_window_count) 43 ::PostQuitMessage(0); 44 break; 45 // Always allow Chrome to set the cursor. 46 case WM_SETCURSOR: 47 return 1; 48 default: 49 return ::DefWindowProc(hwnd, message, wparam, lparam); 50 } 51 return 0; 52 } 53 54 HWND CreateMetroTopLevelWindow(const RECT& work_area) { 55 HINSTANCE hInst = reinterpret_cast<HINSTANCE>(&__ImageBase); 56 WNDCLASSEXW wcex; 57 wcex.cbSize = sizeof(wcex); 58 wcex.style = CS_HREDRAW | CS_VREDRAW; 59 wcex.lpfnWndProc = WndProc; 60 wcex.cbClsExtra = 0; 61 wcex.cbWndExtra = 0; 62 wcex.hInstance = hInst; 63 wcex.hIcon = LoadIcon(::GetModuleHandle(NULL), L"IDR_MAINFRAME"); 64 wcex.hCursor = LoadCursor(NULL, IDC_ARROW); 65 wcex.hbrBackground = (HBRUSH)(COLOR_INACTIVECAPTION+1); 66 wcex.lpszMenuName = 0; 67 wcex.lpszClassName = L"Windows.UI.Core.CoreWindow"; 68 wcex.hIconSm = LoadIcon(::GetModuleHandle(NULL), L"IDR_MAINFRAME"); 69 70 71 72 HWND hwnd = ::CreateWindowExW(0, 73 MAKEINTATOM(::RegisterClassExW(&wcex)), 74 L"metro_win7", 75 WS_POPUP | WS_VISIBLE | WS_MINIMIZEBOX, 76 work_area.top, work_area.left, 77 work_area.right, work_area.bottom, 78 NULL, NULL, hInst, NULL); 79 return hwnd; 80 } 81 82 typedef winfoundtn::ITypedEventHandler< 83 winapp::Core::CoreApplicationView*, 84 winapp::Activation::IActivatedEventArgs*> ActivatedHandler; 85 86 typedef winfoundtn::ITypedEventHandler< 87 winui::Core::CoreWindow*, 88 winui::Core::WindowActivatedEventArgs*> WindowActivatedHandler; 89 90 typedef winfoundtn::ITypedEventHandler< 91 winui::Core::CoreWindow*, 92 winui::Core::AutomationProviderRequestedEventArgs*> 93 AutomationProviderHandler; 94 95 typedef winfoundtn::ITypedEventHandler< 96 winui::Core::CoreWindow*, 97 winui::Core::CharacterReceivedEventArgs*> CharEventHandler; 98 99 typedef winfoundtn::ITypedEventHandler< 100 winui::Core::CoreWindow*, 101 winui::Core::CoreWindowEventArgs*> CoreWindowEventHandler; 102 103 typedef winfoundtn::ITypedEventHandler< 104 winui::Core::CoreWindow*, 105 winui::Core::InputEnabledEventArgs*> InputEnabledEventHandler; 106 107 typedef winfoundtn::ITypedEventHandler< 108 winui::Core::CoreWindow*, 109 winui::Core::KeyEventArgs*> KeyEventHandler; 110 111 typedef winfoundtn::ITypedEventHandler< 112 winui::Core::CoreWindow*, 113 winui::Core::PointerEventArgs*> PointerEventHandler; 114 115 typedef winfoundtn::ITypedEventHandler< 116 winui::Core::CoreWindow*, 117 winui::Core::WindowSizeChangedEventArgs*> SizeChangedHandler; 118 119 typedef winfoundtn::ITypedEventHandler< 120 winui::Core::CoreWindow*, 121 winui::Core::TouchHitTestingEventArgs*> TouchHitTestHandler; 122 123 typedef winfoundtn::ITypedEventHandler< 124 winui::Core::CoreWindow*, 125 winui::Core::VisibilityChangedEventArgs*> VisibilityChangedHandler; 126 127 typedef winfoundtn::ITypedEventHandler< 128 winui::Core::CoreDispatcher*, 129 winui::Core::AcceleratorKeyEventArgs*> AcceleratorKeyEventHandler; 130 131 // This interface is implemented by classes which handle mouse and keyboard 132 // input. 133 class InputHandler { 134 public: 135 InputHandler() {} 136 virtual ~InputHandler() {} 137 138 virtual bool HandleKeyboardMessage(const MSG& msg) = 0; 139 virtual bool HandleMouseMessage(const MSG& msg) = 0; 140 141 private: 142 DISALLOW_COPY_AND_ASSIGN(InputHandler); 143 }; 144 145 // This class implements the winrt interfaces corresponding to mouse input. 146 class MouseEvent : public mswr::RuntimeClass< 147 winui::Core::IPointerEventArgs, 148 winui::Input::IPointerPoint, 149 winui::Input::IPointerPointProperties, 150 windevs::Input::IPointerDevice> { 151 public: 152 MouseEvent(const MSG& msg) 153 : msg_(msg) { 154 } 155 156 // IPointerEventArgs implementation. 157 virtual HRESULT STDMETHODCALLTYPE get_CurrentPoint( 158 winui::Input::IPointerPoint** point) { 159 return QueryInterface(winui::Input::IID_IPointerPoint, 160 reinterpret_cast<void**>(point)); 161 } 162 163 virtual HRESULT STDMETHODCALLTYPE get_KeyModifiers( 164 winsys::VirtualKeyModifiers* modifiers) { 165 return E_NOTIMPL; 166 } 167 168 virtual HRESULT STDMETHODCALLTYPE GetIntermediatePoints( 169 winfoundtn::Collections::IVector<winui::Input::PointerPoint*>** points) { 170 return E_NOTIMPL; 171 } 172 173 // IPointerPoint implementation. 174 virtual HRESULT STDMETHODCALLTYPE get_PointerDevice( 175 windevs::Input::IPointerDevice** pointer_device) { 176 return QueryInterface(windevs::Input::IID_IPointerDevice, 177 reinterpret_cast<void**>(pointer_device)); 178 } 179 180 virtual HRESULT STDMETHODCALLTYPE get_Position(winfoundtn::Point* position) { 181 static float scale = GetModernUIScale(); 182 // Scale down the points here as they are scaled up on the other side. 183 position->X = gfx::ToRoundedInt(CR_GET_X_LPARAM(msg_.lParam) / scale); 184 position->Y = gfx::ToRoundedInt(CR_GET_Y_LPARAM(msg_.lParam) / scale); 185 return S_OK; 186 } 187 188 virtual HRESULT STDMETHODCALLTYPE get_PointerId(uint32* pointer_id) { 189 // TODO(ananta) 190 // Implement this properly. 191 *pointer_id = 1; 192 return S_OK; 193 } 194 195 virtual HRESULT STDMETHODCALLTYPE get_Timestamp(uint64* timestamp) { 196 *timestamp = msg_.time; 197 return S_OK; 198 } 199 200 virtual HRESULT STDMETHODCALLTYPE get_Properties( 201 winui::Input::IPointerPointProperties** properties) { 202 return QueryInterface(winui::Input::IID_IPointerPointProperties, 203 reinterpret_cast<void**>(properties)); 204 } 205 206 virtual HRESULT STDMETHODCALLTYPE get_RawPosition( 207 winfoundtn::Point* position) { 208 return E_NOTIMPL; 209 } 210 211 virtual HRESULT STDMETHODCALLTYPE get_FrameId(uint32* frame_id) { 212 return E_NOTIMPL; 213 } 214 215 virtual HRESULT STDMETHODCALLTYPE get_IsInContact(boolean* in_contact) { 216 return E_NOTIMPL; 217 } 218 219 // IPointerPointProperties implementation. 220 virtual HRESULT STDMETHODCALLTYPE get_PointerUpdateKind( 221 winui::Input::PointerUpdateKind* update_kind) { 222 // TODO(ananta) 223 // There is no WM_POINTERUPDATE equivalent on Windows 7. Look into 224 // equivalents. 225 if (msg_.message == WM_LBUTTONDOWN) { 226 *update_kind = winui::Input::PointerUpdateKind_LeftButtonPressed; 227 } else if (msg_.message == WM_RBUTTONDOWN) { 228 *update_kind = winui::Input::PointerUpdateKind_RightButtonPressed; 229 } else if (msg_.message == WM_MBUTTONDOWN) { 230 *update_kind = winui::Input::PointerUpdateKind_MiddleButtonPressed; 231 } else if (msg_.message == WM_LBUTTONUP) { 232 *update_kind = winui::Input::PointerUpdateKind_LeftButtonReleased; 233 } else if (msg_.message == WM_RBUTTONUP) { 234 *update_kind = winui::Input::PointerUpdateKind_RightButtonReleased; 235 } else if (msg_.message == WM_MBUTTONUP) { 236 *update_kind = winui::Input::PointerUpdateKind_MiddleButtonReleased; 237 } 238 return S_OK; 239 } 240 241 virtual HRESULT STDMETHODCALLTYPE get_IsLeftButtonPressed( 242 boolean* left_button_pressed) { 243 *left_button_pressed = msg_.wParam & MK_LBUTTON ? true : false; 244 return S_OK; 245 } 246 247 virtual HRESULT STDMETHODCALLTYPE get_IsRightButtonPressed( 248 boolean* right_button_pressed) { 249 *right_button_pressed = msg_.wParam & MK_RBUTTON ? true : false; 250 return S_OK; 251 } 252 253 virtual HRESULT STDMETHODCALLTYPE get_IsMiddleButtonPressed( 254 boolean* middle_button_pressed) { 255 *middle_button_pressed = msg_.wParam & MK_MBUTTON ? true : false; 256 return S_OK; 257 } 258 259 virtual HRESULT STDMETHODCALLTYPE get_IsHorizontalMouseWheel( 260 boolean* is_horizontal_mouse_wheel) { 261 *is_horizontal_mouse_wheel = 262 (msg_.message == WM_MOUSEHWHEEL) ? true : false; 263 return S_OK; 264 } 265 266 virtual HRESULT STDMETHODCALLTYPE get_MouseWheelDelta(int* delta) { 267 if (msg_.message == WM_MOUSEWHEEL || msg_.message == WM_MOUSEHWHEEL) { 268 *delta = GET_WHEEL_DELTA_WPARAM(msg_.wParam); 269 return S_OK; 270 } else { 271 return S_FALSE; 272 } 273 } 274 275 virtual HRESULT STDMETHODCALLTYPE get_Pressure(float* pressure) { 276 return E_NOTIMPL; 277 } 278 279 virtual HRESULT STDMETHODCALLTYPE get_IsInverted(boolean* inverted) { 280 return E_NOTIMPL; 281 } 282 283 virtual HRESULT STDMETHODCALLTYPE get_IsEraser(boolean* is_eraser) { 284 return E_NOTIMPL; 285 } 286 287 virtual HRESULT STDMETHODCALLTYPE get_Orientation(float* orientation) { 288 return E_NOTIMPL; 289 } 290 291 virtual HRESULT STDMETHODCALLTYPE get_XTilt(float* x_tilt) { 292 return E_NOTIMPL; 293 } 294 295 virtual HRESULT STDMETHODCALLTYPE get_YTilt(float* y_tilt) { 296 return E_NOTIMPL; 297 } 298 299 virtual HRESULT STDMETHODCALLTYPE get_Twist(float* twist) { 300 return E_NOTIMPL; 301 } 302 303 virtual HRESULT STDMETHODCALLTYPE get_ContactRect(winfoundtn::Rect* rect) { 304 return E_NOTIMPL; 305 } 306 307 virtual HRESULT STDMETHODCALLTYPE get_ContactRectRaw(winfoundtn::Rect* rect) { 308 return E_NOTIMPL; 309 } 310 311 virtual HRESULT STDMETHODCALLTYPE get_TouchConfidence(boolean* confidence) { 312 return E_NOTIMPL; 313 } 314 315 virtual HRESULT STDMETHODCALLTYPE get_IsPrimary(boolean* is_primary) { 316 return E_NOTIMPL; 317 } 318 319 virtual HRESULT STDMETHODCALLTYPE get_IsInRange(boolean* is_in_range) { 320 return E_NOTIMPL; 321 } 322 323 virtual HRESULT STDMETHODCALLTYPE get_IsCanceled(boolean* is_canceled) { 324 return E_NOTIMPL; 325 } 326 327 virtual HRESULT STDMETHODCALLTYPE get_IsBarrelButtonPressed( 328 boolean* is_barrel_button_pressed) { 329 return E_NOTIMPL; 330 } 331 332 virtual HRESULT STDMETHODCALLTYPE get_IsXButton1Pressed( 333 boolean* is_xbutton1_pressed) { 334 return E_NOTIMPL; 335 } 336 337 virtual HRESULT STDMETHODCALLTYPE get_IsXButton2Pressed( 338 boolean* is_xbutton2_pressed) { 339 return E_NOTIMPL; 340 } 341 342 virtual HRESULT STDMETHODCALLTYPE HasUsage(uint32 usage_page, 343 uint32 usage_id, 344 boolean* has_usage) { 345 return E_NOTIMPL; 346 } 347 348 virtual HRESULT STDMETHODCALLTYPE GetUsageValue(uint32 usage_page, 349 uint32 usage_id, 350 int32* usage_value) { 351 return E_NOTIMPL; 352 } 353 354 // IPointerDevice implementation. 355 virtual HRESULT STDMETHODCALLTYPE get_PointerDeviceType( 356 windevs::Input::PointerDeviceType* device_type) { 357 if (msg_.message == WM_TOUCH) { 358 *device_type = windevs::Input::PointerDeviceType_Touch; 359 } else { 360 *device_type = windevs::Input::PointerDeviceType_Mouse; 361 } 362 return S_OK; 363 } 364 365 virtual HRESULT STDMETHODCALLTYPE get_IsIntegrated(boolean* is_integrated) { 366 return E_NOTIMPL; 367 } 368 369 virtual HRESULT STDMETHODCALLTYPE get_MaxContacts(uint32* contacts) { 370 return E_NOTIMPL; 371 } 372 373 virtual HRESULT STDMETHODCALLTYPE get_PhysicalDeviceRect( 374 winfoundtn::Rect* rect) { 375 return E_NOTIMPL; 376 } 377 378 virtual HRESULT STDMETHODCALLTYPE get_ScreenRect(winfoundtn::Rect* rect) { 379 return E_NOTIMPL; 380 } 381 382 virtual HRESULT STDMETHODCALLTYPE get_SupportedUsages( 383 winfoundtn::Collections::IVectorView< 384 windevs::Input::PointerDeviceUsage>** usages) { 385 return E_NOTIMPL; 386 } 387 388 private: 389 MSG msg_; 390 391 DISALLOW_COPY_AND_ASSIGN(MouseEvent); 392 }; 393 394 // This class implements the winrt interfaces needed to support keyboard 395 // character and system character messages. 396 class KeyEvent : public mswr::RuntimeClass< 397 winui::Core::IKeyEventArgs, 398 winui::Core::ICharacterReceivedEventArgs, 399 winui::Core::IAcceleratorKeyEventArgs> { 400 public: 401 KeyEvent(const MSG& msg) 402 : msg_(msg) {} 403 404 // IKeyEventArgs implementation. 405 virtual HRESULT STDMETHODCALLTYPE get_VirtualKey( 406 winsys::VirtualKey* virtual_key) { 407 *virtual_key = static_cast<winsys::VirtualKey>(msg_.wParam); 408 return S_OK; 409 } 410 411 virtual HRESULT STDMETHODCALLTYPE get_KeyStatus( 412 winui::Core::CorePhysicalKeyStatus* key_status) { 413 // As per msdn documentation for the keyboard messages. 414 key_status->RepeatCount = msg_.lParam & 0x0000FFFF; 415 key_status->ScanCode = (msg_.lParam >> 16) & 0x00FF; 416 key_status->IsExtendedKey = (msg_.lParam & (1 << 24)); 417 key_status->IsMenuKeyDown = (msg_.lParam & (1 << 29)); 418 key_status->WasKeyDown = (msg_.lParam & (1 << 30)); 419 key_status->IsKeyReleased = (msg_.lParam & (1 << 31)); 420 return S_OK; 421 } 422 423 // ICharacterReceivedEventArgs implementation. 424 virtual HRESULT STDMETHODCALLTYPE get_KeyCode(uint32* key_code) { 425 *key_code = msg_.wParam; 426 return S_OK; 427 } 428 429 // IAcceleratorKeyEventArgs implementation. 430 virtual HRESULT STDMETHODCALLTYPE get_EventType( 431 winui::Core::CoreAcceleratorKeyEventType* event_type) { 432 if (msg_.message == WM_SYSKEYDOWN) { 433 *event_type = winui::Core::CoreAcceleratorKeyEventType_SystemKeyDown; 434 } else if (msg_.message == WM_SYSKEYUP) { 435 *event_type = winui::Core::CoreAcceleratorKeyEventType_SystemKeyUp; 436 } else if (msg_.message == WM_SYSCHAR) { 437 *event_type = winui::Core::CoreAcceleratorKeyEventType_SystemCharacter; 438 } 439 return S_OK; 440 } 441 442 private: 443 MSG msg_; 444 }; 445 446 // The following classes are the emulation of the WinRT system as exposed 447 // to metro applications. There is one application (ICoreApplication) which 448 // contains a series of Views (ICoreApplicationView) each one of them 449 // containing a CoreWindow which represents a surface that can drawn to 450 // and that receives events. 451 // 452 // Here is the general dependency hierachy in terms of interfaces: 453 // 454 // IFrameworkViewSource --> IFrameworkView 455 // ^ | 456 // | | metro app 457 // --------------------------------------------------------------------- 458 // | | winRT system 459 // | v 460 // ICoreApplication ICoreApplicationView 461 // | 462 // v 463 // ICoreWindow -----> ICoreWindowInterop 464 // | | 465 // | | 466 // v V 467 // ICoreDispatcher <==> real HWND 468 // 469 class CoreDispatcherEmulation : 470 public mswr::RuntimeClass< 471 winui::Core::ICoreDispatcher, 472 winui::Core::ICoreAcceleratorKeys> { 473 public: 474 CoreDispatcherEmulation(InputHandler* input_handler) 475 : input_handler_(input_handler), 476 accelerator_key_event_handler_(NULL) {} 477 478 // ICoreDispatcher implementation: 479 virtual HRESULT STDMETHODCALLTYPE get_HasThreadAccess(boolean* value) { 480 return S_OK; 481 } 482 483 virtual HRESULT STDMETHODCALLTYPE ProcessEvents( 484 winui::Core::CoreProcessEventsOption options) { 485 // We don't support the other message pump modes. So we basically enter a 486 // traditional message loop that we only exit a teardown. 487 if (options != winui::Core::CoreProcessEventsOption_ProcessUntilQuit) 488 return E_FAIL; 489 490 MSG msg = {0}; 491 while((::GetMessage(&msg, NULL, 0, 0) != 0) && g_window_count > 0) { 492 ProcessInputMessage(msg); 493 ::TranslateMessage(&msg); 494 ::DispatchMessage(&msg); 495 } 496 // TODO(cpu): figure what to do with msg.WParam which we would normally 497 // return here. 498 return S_OK; 499 } 500 501 virtual HRESULT STDMETHODCALLTYPE RunAsync( 502 winui::Core::CoreDispatcherPriority priority, 503 winui::Core::IDispatchedHandler *agileCallback, 504 ABI::Windows::Foundation::IAsyncAction** asyncAction) { 505 return S_OK; 506 } 507 508 virtual HRESULT STDMETHODCALLTYPE RunIdleAsync( 509 winui::Core::IIdleDispatchedHandler *agileCallback, 510 winfoundtn::IAsyncAction** asyncAction) { 511 return S_OK; 512 } 513 514 // ICoreAcceleratorKeys implementation: 515 virtual HRESULT STDMETHODCALLTYPE add_AcceleratorKeyActivated( 516 AcceleratorKeyEventHandler* handler, 517 EventRegistrationToken *pCookie) { 518 accelerator_key_event_handler_ = handler; 519 accelerator_key_event_handler_->AddRef(); 520 return S_OK; 521 } 522 523 virtual HRESULT STDMETHODCALLTYPE remove_AcceleratorKeyActivated( 524 EventRegistrationToken cookie) { 525 accelerator_key_event_handler_->Release(); 526 accelerator_key_event_handler_ = NULL; 527 return S_OK; 528 } 529 530 private: 531 bool ProcessInputMessage(const MSG& msg) { 532 // Poor man's way of dispatching input events. 533 bool ret = false; 534 if (input_handler_) { 535 if ((msg.message >= WM_KEYFIRST) && (msg.message <= WM_KEYLAST)) { 536 if ((msg.message == WM_SYSKEYDOWN) || (msg.message == WM_SYSKEYUP) || 537 msg.message == WM_SYSCHAR) { 538 ret = HandleSystemKeys(msg); 539 } else { 540 ret = input_handler_->HandleKeyboardMessage(msg); 541 } 542 } else if ((msg.message >= WM_MOUSEFIRST) && 543 (msg.message <= WM_MOUSELAST)) { 544 ret = input_handler_->HandleMouseMessage(msg); 545 } 546 } 547 return ret; 548 } 549 550 bool HandleSystemKeys(const MSG& msg) { 551 mswr::ComPtr<winui::Core::IAcceleratorKeyEventArgs> event_args; 552 event_args = mswr::Make<KeyEvent>(msg); 553 accelerator_key_event_handler_->Invoke(this, event_args.Get()); 554 return true; 555 } 556 557 InputHandler* input_handler_; 558 AcceleratorKeyEventHandler* accelerator_key_event_handler_; 559 }; 560 561 class CoreWindowEmulation 562 : public mswr::RuntimeClass< 563 mswr::RuntimeClassFlags<mswr::WinRtClassicComMix>, 564 winui::Core::ICoreWindow, ICoreWindowInterop>, 565 public InputHandler { 566 public: 567 CoreWindowEmulation() 568 : core_hwnd_(NULL), 569 mouse_moved_handler_(NULL), 570 mouse_capture_lost_handler_(NULL), 571 mouse_pressed_handler_(NULL), 572 mouse_released_handler_(NULL), 573 mouse_entered_handler_(NULL), 574 mouse_exited_handler_(NULL), 575 mouse_wheel_changed_handler_(NULL), 576 key_down_handler_(NULL), 577 key_up_handler_(NULL), 578 character_received_handler_(NULL) { 579 dispatcher_ = mswr::Make<CoreDispatcherEmulation>(this); 580 581 // Unless we select our own AppUserModelID the shell might confuse us 582 // with the app launcher one and we get the wrong taskbar button and icon. 583 ::SetCurrentProcessExplicitAppUserModelID(kAshWin7AppId); 584 585 RECT work_area = {0}; 586 ::SystemParametersInfo(SPI_GETWORKAREA, 0, &work_area, 0); 587 if (::IsDebuggerPresent()) { 588 work_area.top = 0; 589 work_area.left = 0; 590 work_area.right = 1600; 591 work_area.bottom = 900; 592 } 593 594 core_hwnd_ = CreateMetroTopLevelWindow(work_area); 595 } 596 597 ~CoreWindowEmulation() { 598 if (core_hwnd_) 599 ::DestroyWindow(core_hwnd_); 600 } 601 602 // ICoreWindow implementation: 603 virtual HRESULT STDMETHODCALLTYPE get_AutomationHostProvider( 604 IInspectable** value) { 605 return S_OK; 606 } 607 608 virtual HRESULT STDMETHODCALLTYPE get_Bounds( 609 winfoundtn::Rect* value) { 610 RECT rect; 611 if (!::GetClientRect(core_hwnd_, &rect)) 612 return E_FAIL; 613 value->Width = rect.right; 614 value->Height = rect.bottom; 615 return S_OK; 616 } 617 618 virtual HRESULT STDMETHODCALLTYPE get_CustomProperties( 619 winfoundtn::Collections::IPropertySet** value) { 620 return S_OK; 621 } 622 623 virtual HRESULT STDMETHODCALLTYPE get_Dispatcher( 624 winui::Core::ICoreDispatcher** value) { 625 return dispatcher_.CopyTo(value); 626 } 627 628 virtual HRESULT STDMETHODCALLTYPE get_FlowDirection( 629 winui::Core::CoreWindowFlowDirection* value) { 630 return S_OK; 631 } 632 633 virtual HRESULT STDMETHODCALLTYPE put_FlowDirection( 634 winui::Core::CoreWindowFlowDirection value) { 635 return S_OK; 636 } 637 638 virtual HRESULT STDMETHODCALLTYPE get_IsInputEnabled( 639 boolean* value) { 640 return S_OK; 641 } 642 643 virtual HRESULT STDMETHODCALLTYPE put_IsInputEnabled( 644 boolean value) { 645 return S_OK; 646 } 647 648 virtual HRESULT STDMETHODCALLTYPE get_PointerCursor( 649 winui::Core::ICoreCursor** value) { 650 return S_OK; 651 } 652 653 virtual HRESULT STDMETHODCALLTYPE put_PointerCursor( 654 winui::Core::ICoreCursor* value) { 655 return S_OK; 656 } 657 658 virtual HRESULT STDMETHODCALLTYPE get_PointerPosition( 659 winfoundtn::Point* value) { 660 return S_OK; 661 } 662 663 virtual HRESULT STDMETHODCALLTYPE get_Visible( 664 boolean* value) { 665 return S_OK; 666 } 667 668 virtual HRESULT STDMETHODCALLTYPE Activate(void) { 669 // After we fire OnActivate on the View, Chrome calls us back here. 670 return S_OK; 671 } 672 673 virtual HRESULT STDMETHODCALLTYPE Close(void) { 674 ::PostMessage(core_hwnd_, WM_CLOSE, 0, 0); 675 core_hwnd_ = NULL; 676 return S_OK; 677 } 678 679 virtual HRESULT STDMETHODCALLTYPE GetAsyncKeyState( 680 ABI::Windows::System::VirtualKey virtualKey, 681 winui::Core::CoreVirtualKeyStates* KeyState) { 682 return S_OK; 683 } 684 685 virtual HRESULT STDMETHODCALLTYPE GetKeyState( 686 ABI::Windows::System::VirtualKey virtualKey, 687 winui::Core::CoreVirtualKeyStates* KeyState) { 688 return S_OK; 689 } 690 691 virtual HRESULT STDMETHODCALLTYPE ReleasePointerCapture(void) { 692 return S_OK; 693 } 694 695 virtual HRESULT STDMETHODCALLTYPE SetPointerCapture(void) { 696 return S_OK; 697 } 698 699 virtual HRESULT STDMETHODCALLTYPE add_Activated( 700 WindowActivatedHandler* handler, 701 EventRegistrationToken* pCookie) { 702 // TODO(cpu) implement this. 703 return S_OK; 704 } 705 706 virtual HRESULT STDMETHODCALLTYPE remove_Activated( 707 EventRegistrationToken cookie) { 708 return S_OK; 709 } 710 711 virtual HRESULT STDMETHODCALLTYPE add_AutomationProviderRequested( 712 AutomationProviderHandler* handler, 713 EventRegistrationToken* cookie) { 714 return S_OK; 715 } 716 717 virtual HRESULT STDMETHODCALLTYPE remove_AutomationProviderRequested( 718 EventRegistrationToken cookie) { 719 return S_OK; 720 } 721 722 virtual HRESULT STDMETHODCALLTYPE add_CharacterReceived( 723 CharEventHandler* handler, 724 EventRegistrationToken* pCookie) { 725 character_received_handler_ = handler; 726 character_received_handler_->AddRef(); 727 return S_OK; 728 } 729 730 virtual HRESULT STDMETHODCALLTYPE remove_CharacterReceived( 731 EventRegistrationToken cookie) { 732 character_received_handler_->Release(); 733 character_received_handler_ = NULL; 734 return S_OK; 735 } 736 737 virtual HRESULT STDMETHODCALLTYPE add_Closed( 738 CoreWindowEventHandler* handler, 739 EventRegistrationToken* pCookie) { 740 return S_OK; 741 } 742 743 virtual HRESULT STDMETHODCALLTYPE remove_Closed( 744 EventRegistrationToken cookie) { 745 return S_OK; 746 } 747 748 virtual HRESULT STDMETHODCALLTYPE add_InputEnabled( 749 InputEnabledEventHandler* handler, 750 EventRegistrationToken* pCookie) { 751 return S_OK; 752 } 753 754 virtual HRESULT STDMETHODCALLTYPE remove_InputEnabled( 755 EventRegistrationToken cookie) { 756 return S_OK; 757 } 758 759 virtual HRESULT STDMETHODCALLTYPE add_KeyDown( 760 KeyEventHandler* handler, 761 EventRegistrationToken* pCookie) { 762 key_down_handler_ = handler; 763 key_down_handler_->AddRef(); 764 return S_OK; 765 } 766 767 virtual HRESULT STDMETHODCALLTYPE remove_KeyDown( 768 EventRegistrationToken cookie) { 769 key_down_handler_->Release(); 770 key_down_handler_ = NULL; 771 return S_OK; 772 } 773 774 virtual HRESULT STDMETHODCALLTYPE add_KeyUp( 775 KeyEventHandler* handler, 776 EventRegistrationToken* pCookie) { 777 key_up_handler_ = handler; 778 key_up_handler_->AddRef(); 779 return S_OK; 780 } 781 782 virtual HRESULT STDMETHODCALLTYPE remove_KeyUp( 783 EventRegistrationToken cookie) { 784 key_up_handler_->Release(); 785 key_up_handler_ = NULL; 786 return S_OK; 787 } 788 789 virtual HRESULT STDMETHODCALLTYPE add_PointerCaptureLost( 790 PointerEventHandler* handler, 791 EventRegistrationToken* cookie) { 792 mouse_capture_lost_handler_ = handler; 793 return S_OK; 794 } 795 796 virtual HRESULT STDMETHODCALLTYPE remove_PointerCaptureLost( 797 EventRegistrationToken cookie) { 798 mouse_capture_lost_handler_ = NULL; 799 return S_OK; 800 } 801 802 virtual HRESULT STDMETHODCALLTYPE add_PointerEntered( 803 PointerEventHandler* handler, 804 EventRegistrationToken* cookie) { 805 mouse_entered_handler_ = handler; 806 return S_OK; 807 } 808 809 virtual HRESULT STDMETHODCALLTYPE remove_PointerEntered( 810 EventRegistrationToken cookie) { 811 mouse_entered_handler_ = NULL; 812 return S_OK; 813 } 814 815 virtual HRESULT STDMETHODCALLTYPE add_PointerExited( 816 PointerEventHandler* handler, 817 EventRegistrationToken* cookie) { 818 mouse_exited_handler_ = handler; 819 return S_OK; 820 } 821 822 virtual HRESULT STDMETHODCALLTYPE remove_PointerExited( 823 EventRegistrationToken cookie) { 824 mouse_exited_handler_ = NULL; 825 return S_OK; 826 } 827 828 virtual HRESULT STDMETHODCALLTYPE add_PointerMoved( 829 PointerEventHandler* handler, 830 EventRegistrationToken* cookie) { 831 mouse_moved_handler_ = handler; 832 mouse_moved_handler_->AddRef(); 833 return S_OK; 834 } 835 836 virtual HRESULT STDMETHODCALLTYPE remove_PointerMoved( 837 EventRegistrationToken cookie) { 838 mouse_moved_handler_->Release(); 839 mouse_moved_handler_ = NULL; 840 return S_OK; 841 } 842 843 virtual HRESULT STDMETHODCALLTYPE add_PointerPressed( 844 PointerEventHandler* handler, 845 EventRegistrationToken* cookie) { 846 mouse_pressed_handler_ = handler; 847 mouse_pressed_handler_->AddRef(); 848 return S_OK; 849 } 850 851 virtual HRESULT STDMETHODCALLTYPE remove_PointerPressed( 852 EventRegistrationToken cookie) { 853 mouse_pressed_handler_->Release(); 854 mouse_pressed_handler_ = NULL; 855 return S_OK; 856 } 857 858 virtual HRESULT STDMETHODCALLTYPE add_PointerReleased( 859 PointerEventHandler* handler, 860 EventRegistrationToken* cookie) { 861 mouse_released_handler_ = handler; 862 mouse_released_handler_->AddRef(); 863 return S_OK; 864 } 865 866 virtual HRESULT STDMETHODCALLTYPE remove_PointerReleased( 867 EventRegistrationToken cookie) { 868 mouse_released_handler_->Release(); 869 mouse_released_handler_ = NULL; 870 return S_OK; 871 } 872 873 virtual HRESULT STDMETHODCALLTYPE add_TouchHitTesting( 874 TouchHitTestHandler* handler, 875 EventRegistrationToken* pCookie) { 876 return S_OK; 877 } 878 879 virtual HRESULT STDMETHODCALLTYPE remove_TouchHitTesting( 880 EventRegistrationToken cookie) { 881 return S_OK; 882 } 883 884 virtual HRESULT STDMETHODCALLTYPE add_PointerWheelChanged( 885 PointerEventHandler* handler, 886 EventRegistrationToken* cookie) { 887 mouse_wheel_changed_handler_ = handler; 888 mouse_wheel_changed_handler_->AddRef(); 889 return S_OK; 890 } 891 892 virtual HRESULT STDMETHODCALLTYPE remove_PointerWheelChanged( 893 EventRegistrationToken cookie) { 894 mouse_wheel_changed_handler_->Release(); 895 mouse_wheel_changed_handler_ = NULL; 896 return S_OK; 897 } 898 899 virtual HRESULT STDMETHODCALLTYPE add_SizeChanged( 900 SizeChangedHandler* handler, 901 EventRegistrationToken* pCookie) { 902 // TODO(cpu): implement this. 903 return S_OK; 904 } 905 906 virtual HRESULT STDMETHODCALLTYPE remove_SizeChanged( 907 EventRegistrationToken cookie) { 908 return S_OK; 909 } 910 911 virtual HRESULT STDMETHODCALLTYPE add_VisibilityChanged( 912 VisibilityChangedHandler* handler, 913 EventRegistrationToken* pCookie) { 914 return S_OK; 915 } 916 917 virtual HRESULT STDMETHODCALLTYPE remove_VisibilityChanged( 918 EventRegistrationToken cookie) { 919 return S_OK; 920 } 921 922 // ICoreWindowInterop implementation: 923 virtual HRESULT STDMETHODCALLTYPE get_WindowHandle(HWND* hwnd) { 924 if (!core_hwnd_) 925 return E_FAIL; 926 *hwnd = core_hwnd_; 927 return S_OK; 928 } 929 930 virtual HRESULT STDMETHODCALLTYPE put_MessageHandled( 931 boolean value) { 932 return S_OK; 933 } 934 935 // InputHandler 936 virtual bool HandleKeyboardMessage(const MSG& msg) OVERRIDE { 937 switch (msg.message) { 938 case WM_KEYDOWN: 939 case WM_KEYUP: { 940 mswr::ComPtr<winui::Core::IKeyEventArgs> event_args; 941 event_args = mswr::Make<KeyEvent>(msg); 942 KeyEventHandler* handler = NULL; 943 if (msg.message == WM_KEYDOWN) { 944 handler = key_down_handler_; 945 } else { 946 handler = key_up_handler_; 947 } 948 handler->Invoke(this, event_args.Get()); 949 break; 950 } 951 952 case WM_CHAR: 953 case WM_DEADCHAR: 954 case WM_UNICHAR: { 955 mswr::ComPtr<winui::Core::ICharacterReceivedEventArgs> event_args; 956 event_args = mswr::Make<KeyEvent>(msg); 957 character_received_handler_->Invoke(this, event_args.Get()); 958 break; 959 } 960 961 default: 962 return false; 963 } 964 return true; 965 } 966 967 virtual bool HandleMouseMessage(const MSG& msg) OVERRIDE { 968 PointerEventHandler* handler = NULL; 969 mswr::ComPtr<winui::Core::IPointerEventArgs> event_args; 970 event_args = mswr::Make<MouseEvent>(msg); 971 switch (msg.message) { 972 case WM_MOUSEMOVE: { 973 handler = mouse_moved_handler_; 974 break; 975 } 976 case WM_LBUTTONDOWN: { 977 case WM_RBUTTONDOWN: 978 case WM_MBUTTONDOWN: 979 handler = mouse_pressed_handler_; 980 break; 981 } 982 983 case WM_LBUTTONUP: { 984 case WM_RBUTTONUP: 985 case WM_MBUTTONUP: 986 handler = mouse_released_handler_; 987 break; 988 } 989 990 case WM_MOUSEWHEEL: { 991 case WM_MOUSEHWHEEL: 992 handler = mouse_wheel_changed_handler_; 993 break; 994 } 995 996 default: 997 return false; 998 } 999 DCHECK(handler); 1000 handler->Invoke(this, event_args.Get()); 1001 return true; 1002 } 1003 1004 private: 1005 PointerEventHandler* mouse_moved_handler_; 1006 PointerEventHandler* mouse_capture_lost_handler_; 1007 PointerEventHandler* mouse_pressed_handler_; 1008 PointerEventHandler* mouse_released_handler_; 1009 PointerEventHandler* mouse_entered_handler_; 1010 PointerEventHandler* mouse_exited_handler_; 1011 PointerEventHandler* mouse_wheel_changed_handler_; 1012 KeyEventHandler* key_down_handler_; 1013 KeyEventHandler* key_up_handler_; 1014 CharEventHandler* character_received_handler_; 1015 HWND core_hwnd_; 1016 mswr::ComPtr<winui::Core::ICoreDispatcher> dispatcher_; 1017 }; 1018 1019 class ActivatedEvent 1020 : public mswr::RuntimeClass<winapp::Activation::IActivatedEventArgs> { 1021 public: 1022 ActivatedEvent(winapp::Activation::ActivationKind activation_kind) 1023 : activation_kind_(activation_kind) { 1024 } 1025 1026 virtual HRESULT STDMETHODCALLTYPE get_Kind( 1027 winapp::Activation::ActivationKind *value) { 1028 *value = activation_kind_; 1029 return S_OK; 1030 } 1031 1032 virtual HRESULT STDMETHODCALLTYPE get_PreviousExecutionState( 1033 winapp::Activation::ApplicationExecutionState *value) { 1034 *value = winapp::Activation::ApplicationExecutionState_ClosedByUser; 1035 return S_OK; 1036 } 1037 1038 virtual HRESULT STDMETHODCALLTYPE get_SplashScreen( 1039 winapp::Activation::ISplashScreen **value) { 1040 return E_FAIL; 1041 } 1042 1043 private: 1044 winapp::Activation::ActivationKind activation_kind_; 1045 }; 1046 1047 class CoreApplicationViewEmulation 1048 : public mswr::RuntimeClass<winapp::Core::ICoreApplicationView> { 1049 public: 1050 CoreApplicationViewEmulation() { 1051 core_window_ = mswr::Make<CoreWindowEmulation>(); 1052 } 1053 1054 HRESULT Activate() { 1055 if (activated_handler_) { 1056 auto ae = mswr::Make<ActivatedEvent>( 1057 winapp::Activation::ActivationKind_File); 1058 return activated_handler_->Invoke(this, ae.Get()); 1059 } else { 1060 return S_OK; 1061 } 1062 } 1063 1064 HRESULT Close() { 1065 return core_window_->Close(); 1066 } 1067 1068 // ICoreApplicationView implementation: 1069 virtual HRESULT STDMETHODCALLTYPE get_CoreWindow( 1070 winui::Core::ICoreWindow** value) { 1071 if (!core_window_) 1072 return E_FAIL; 1073 return core_window_.CopyTo(value); 1074 } 1075 1076 virtual HRESULT STDMETHODCALLTYPE add_Activated( 1077 ActivatedHandler* handler, 1078 EventRegistrationToken* token) { 1079 // The real component supports multiple handles but we don't yet. 1080 if (activated_handler_) 1081 return E_FAIL; 1082 activated_handler_ = handler; 1083 return S_OK; 1084 } 1085 1086 virtual HRESULT STDMETHODCALLTYPE remove_Activated( 1087 EventRegistrationToken token) { 1088 // Chrome never unregisters handlers, so we don't care about it. 1089 return S_OK; 1090 } 1091 1092 virtual HRESULT STDMETHODCALLTYPE get_IsMain( 1093 boolean* value) { 1094 return S_OK; 1095 } 1096 1097 virtual HRESULT STDMETHODCALLTYPE get_IsHosted( 1098 boolean* value) { 1099 return S_OK; 1100 } 1101 1102 private: 1103 mswr::ComPtr<CoreWindowEmulation> core_window_; 1104 mswr::ComPtr<ActivatedHandler> activated_handler_; 1105 }; 1106 1107 class CoreApplicationWin7Emulation 1108 : public mswr::RuntimeClass<winapp::Core::ICoreApplication, 1109 winapp::Core::ICoreApplicationExit> { 1110 public: 1111 // ICoreApplication implementation: 1112 1113 virtual HRESULT STDMETHODCALLTYPE get_Id( 1114 HSTRING* value) { 1115 return S_OK; 1116 } 1117 1118 virtual HRESULT STDMETHODCALLTYPE add_Suspending( 1119 winfoundtn::IEventHandler<winapp::SuspendingEventArgs*>* handler, 1120 EventRegistrationToken* token) { 1121 return S_OK; 1122 } 1123 1124 virtual HRESULT STDMETHODCALLTYPE remove_Suspending( 1125 EventRegistrationToken token) { 1126 return S_OK; 1127 } 1128 1129 virtual HRESULT STDMETHODCALLTYPE add_Resuming( 1130 winfoundtn::IEventHandler<IInspectable*>* handler, 1131 EventRegistrationToken* token) { 1132 return S_OK; 1133 } 1134 1135 virtual HRESULT STDMETHODCALLTYPE remove_Resuming( 1136 EventRegistrationToken token) { 1137 return S_OK; 1138 } 1139 1140 virtual HRESULT STDMETHODCALLTYPE get_Properties( 1141 winfoundtn::Collections::IPropertySet** value) { 1142 return S_OK; 1143 } 1144 1145 virtual HRESULT STDMETHODCALLTYPE GetCurrentView( 1146 winapp::Core::ICoreApplicationView** value) { 1147 return S_OK; 1148 } 1149 1150 virtual HRESULT STDMETHODCALLTYPE Run( 1151 winapp::Core::IFrameworkViewSource* viewSource) { 1152 HRESULT hr = viewSource->CreateView(app_view_.GetAddressOf()); 1153 if (FAILED(hr)) 1154 return hr; 1155 view_emulation_ = mswr::Make<CoreApplicationViewEmulation>(); 1156 hr = app_view_->Initialize(view_emulation_.Get()); 1157 if (FAILED(hr)) 1158 return hr; 1159 mswr::ComPtr<winui::Core::ICoreWindow> core_window; 1160 hr = view_emulation_->get_CoreWindow(core_window.GetAddressOf()); 1161 if (FAILED(hr)) 1162 return hr; 1163 hr = app_view_->SetWindow(core_window.Get()); 1164 if (FAILED(hr)) 1165 return hr; 1166 hr = app_view_->Load(NULL); 1167 if (FAILED(hr)) 1168 return hr; 1169 hr = view_emulation_->Activate(); 1170 if (FAILED(hr)) 1171 return hr; 1172 return app_view_->Run(); 1173 } 1174 1175 virtual HRESULT STDMETHODCALLTYPE RunWithActivationFactories( 1176 winfoundtn::IGetActivationFactory* activationFactoryCallback) { 1177 return S_OK; 1178 } 1179 1180 // ICoreApplicationExit implementation: 1181 1182 virtual HRESULT STDMETHODCALLTYPE Exit(void) { 1183 return view_emulation_->Close(); 1184 } 1185 1186 virtual HRESULT STDMETHODCALLTYPE add_Exiting( 1187 winfoundtn::IEventHandler<IInspectable*>* handler, 1188 EventRegistrationToken* token) { 1189 return S_OK; 1190 } 1191 1192 virtual HRESULT STDMETHODCALLTYPE remove_Exiting( 1193 EventRegistrationToken token) { 1194 return S_OK; 1195 } 1196 1197 private: 1198 mswr::ComPtr<winapp::Core::IFrameworkView> app_view_; 1199 mswr::ComPtr<CoreApplicationViewEmulation> view_emulation_; 1200 }; 1201 1202 1203 mswr::ComPtr<winapp::Core::ICoreApplication> InitWindows7() { 1204 HRESULT hr = ::CoInitializeEx(NULL, COINIT_MULTITHREADED); 1205 if (FAILED(hr)) 1206 CHECK(false); 1207 return mswr::Make<CoreApplicationWin7Emulation>(); 1208 } 1209 1210