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
7EXTERN_C IMAGE_DOS_HEADER __ImageBase;
8
9struct 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
19void 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
42LRESULT 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
61HWND 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
86DWORD 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
95extern "C" __declspec(dllexport)
96int 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
126extern "C" _declspec(dllexport) HWND GetRootWindow() {
127  ODS("GetRootWindow", ULONG_PTR(globals.core_window));
128  return globals.core_window;
129}
130
131extern "C" _declspec(dllexport) void SetFrameWindow(HWND window) {
132  ODS("SetFrameWindow", ULONG_PTR(window));
133  globals.host_window = window;
134}
135
136extern "C" __declspec(dllexport) const wchar_t* GetInitialUrl() {
137  return L"";
138}
139
140