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