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