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 
      7 EXTERN_C IMAGE_DOS_HEADER __ImageBase;
      8 
      9 struct Globals {
     10   LPTHREAD_START_ROUTINE host_main;
     11   void* host_context;
     12   HWND core_window;
     13   HWND host_window;
     14   HANDLE host_thread;
     15   DWORD main_thread_id;
     16 } globals;
     17 
     18 
     19 void ODS(const char* str, LONG_PTR val = 0) {
     20   char buf[80];
     21   size_t len = strlen(str);
     22   if (len > 50) {
     23     ::OutputDebugStringA("ODS: buffer too long");
     24     return;
     25   }
     26 
     27   if (str[0] == '!') {
     28     // Fatal error.
     29     DWORD gle = ::GetLastError();
     30     if (::IsDebuggerPresent())
     31       __debugbreak();
     32     wsprintfA(buf, "ODS:fatal %s (%p) gle=0x%x", str, val, gle);
     33     ::MessageBoxA(NULL, buf, "!!!", MB_OK);
     34     ::ExitProcess(gle);
     35   } else {
     36     // Just information.
     37     wsprintfA(buf, "ODS:%s (%p)\n", str, val);
     38     ::OutputDebugStringA(buf);
     39   }
     40 }
     41 
     42 LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
     43                          WPARAM wparam, LPARAM lparam) {
     44   PAINTSTRUCT ps;
     45   HDC hdc;
     46   switch (message) {
     47     case WM_PAINT:
     48       hdc = BeginPaint(hwnd, &ps);
     49       EndPaint(hwnd, &ps);
     50       break;
     51     case WM_DESTROY:
     52       PostQuitMessage(0);
     53       ODS("Metro WM_DESTROY received");
     54       break;
     55     default:
     56       return DefWindowProc(hwnd, message, wparam, lparam);
     57   }
     58   return 0;
     59 }
     60 
     61 HWND CreateMetroTopLevelWindow() {
     62   HINSTANCE hInst = reinterpret_cast<HINSTANCE>(&__ImageBase);
     63   WNDCLASSEXW wcex;
     64   wcex.cbSize = sizeof(wcex);
     65   wcex.style                    = CS_HREDRAW | CS_VREDRAW;
     66         wcex.lpfnWndProc        = WndProc;
     67         wcex.cbClsExtra         = 0;
     68         wcex.cbWndExtra         = 0;
     69         wcex.hInstance          = hInst;
     70         wcex.hIcon              = 0;
     71         wcex.hCursor            = LoadCursor(NULL, IDC_ARROW);
     72         wcex.hbrBackground      = (HBRUSH)(COLOR_INACTIVECAPTION+1);
     73         wcex.lpszMenuName       = 0;
     74         wcex.lpszClassName      = L"Windows.UI.Core.CoreWindow";
     75         wcex.hIconSm            = 0;
     76 
     77   HWND hwnd = ::CreateWindowExW(0,
     78                                 MAKEINTATOM(::RegisterClassExW(&wcex)),
     79                                 L"metro_metro",
     80                                 WS_POPUP,
     81                                 0, 0, 0, 0,
     82                                 NULL, NULL, hInst, NULL);
     83   return hwnd;
     84 }
     85 
     86 DWORD WINAPI HostThread(void*) {
     87   // The sleeps simulates the delay we have in the actual metro code
     88   // which takes in account the corewindow being created and some other
     89   // unknown machinations of metro.
     90   ODS("Chrome main thread", ::GetCurrentThreadId());
     91   ::Sleep(30);
     92   return globals.host_main(globals.host_context);
     93 }
     94 
     95 extern "C" __declspec(dllexport)
     96 int InitMetro(LPTHREAD_START_ROUTINE thread_proc, void* context) {
     97   ODS("InitMetro [Win7 emulation]");
     98   HWND window = CreateMetroTopLevelWindow();
     99   if (!window)
    100     return 1;
    101   // This magic incatation tells windows that the window is going fullscreen
    102   // so the taskbar gets out of the wait automatically.
    103   ::SetWindowPos(window,
    104                  HWND_TOP,
    105                  0,0,
    106                  GetSystemMetrics(SM_CXSCREEN),
    107                  GetSystemMetrics(SM_CYSCREEN),
    108                  SWP_SHOWWINDOW);
    109 
    110   // Ready to start our caller.
    111   globals.core_window = window;
    112   globals.host_main = thread_proc;
    113   globals.host_context = context;
    114   HANDLE thread = ::CreateThread(NULL, 0, &HostThread, NULL, 0, NULL);
    115 
    116   // Main message loop.
    117   MSG msg = {0};
    118   while (GetMessage(&msg, NULL, 0, 0)) {
    119     TranslateMessage(&msg);
    120     DispatchMessage(&msg);
    121   }
    122 
    123   return (int) msg.wParam;
    124 }
    125 
    126 extern "C" _declspec(dllexport) HWND GetRootWindow() {
    127   ODS("GetRootWindow", ULONG_PTR(globals.core_window));
    128   return globals.core_window;
    129 }
    130 
    131 extern "C" _declspec(dllexport) void SetFrameWindow(HWND window) {
    132   ODS("SetFrameWindow", ULONG_PTR(window));
    133   globals.host_window = window;
    134 }
    135 
    136 extern "C" __declspec(dllexport) const wchar_t* GetInitialUrl() {
    137   return L"";
    138 }
    139 
    140