Home | History | Annotate | Download | only in metro_driver
      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