| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "stdafx.h" |
| |
| EXTERN_C IMAGE_DOS_HEADER __ImageBase; |
| |
| struct Globals { |
| LPTHREAD_START_ROUTINE host_main; |
| void* host_context; |
| HWND core_window; |
| HWND host_window; |
| HANDLE host_thread; |
| DWORD main_thread_id; |
| } globals; |
| |
| |
| void ODS(const char* str, LONG_PTR val = 0) { |
| char buf[80]; |
| size_t len = strlen(str); |
| if (len > 50) { |
| ::OutputDebugStringA("ODS: buffer too long"); |
| return; |
| } |
| |
| if (str[0] == '!') { |
| // Fatal error. |
| DWORD gle = ::GetLastError(); |
| if (::IsDebuggerPresent()) |
| __debugbreak(); |
| wsprintfA(buf, "ODS:fatal %s (%p) gle=0x%x", str, val, gle); |
| ::MessageBoxA(NULL, buf, "!!!", MB_OK); |
| ::ExitProcess(gle); |
| } else { |
| // Just information. |
| wsprintfA(buf, "ODS:%s (%p)\n", str, val); |
| ::OutputDebugStringA(buf); |
| } |
| } |
| |
| LRESULT CALLBACK WndProc(HWND hwnd, UINT message, |
| WPARAM wparam, LPARAM lparam) { |
| PAINTSTRUCT ps; |
| HDC hdc; |
| switch (message) { |
| case WM_PAINT: |
| hdc = BeginPaint(hwnd, &ps); |
| EndPaint(hwnd, &ps); |
| break; |
| case WM_DESTROY: |
| PostQuitMessage(0); |
| ODS("Metro WM_DESTROY received"); |
| break; |
| default: |
| return DefWindowProc(hwnd, message, wparam, lparam); |
| } |
| return 0; |
| } |
| |
| HWND CreateMetroTopLevelWindow() { |
| HINSTANCE hInst = reinterpret_cast<HINSTANCE>(&__ImageBase); |
| WNDCLASSEXW wcex; |
| wcex.cbSize = sizeof(wcex); |
| wcex.style = CS_HREDRAW | CS_VREDRAW; |
| wcex.lpfnWndProc = WndProc; |
| wcex.cbClsExtra = 0; |
| wcex.cbWndExtra = 0; |
| wcex.hInstance = hInst; |
| wcex.hIcon = 0; |
| wcex.hCursor = LoadCursor(NULL, IDC_ARROW); |
| wcex.hbrBackground = (HBRUSH)(COLOR_INACTIVECAPTION+1); |
| wcex.lpszMenuName = 0; |
| wcex.lpszClassName = L"Windows.UI.Core.CoreWindow"; |
| wcex.hIconSm = 0; |
| |
| HWND hwnd = ::CreateWindowExW(0, |
| MAKEINTATOM(::RegisterClassExW(&wcex)), |
| L"metro_metro", |
| WS_POPUP, |
| 0, 0, 0, 0, |
| NULL, NULL, hInst, NULL); |
| return hwnd; |
| } |
| |
| DWORD WINAPI HostThread(void*) { |
| // The sleeps simulates the delay we have in the actual metro code |
| // which takes in account the corewindow being created and some other |
| // unknown machinations of metro. |
| ODS("Chrome main thread", ::GetCurrentThreadId()); |
| ::Sleep(30); |
| return globals.host_main(globals.host_context); |
| } |
| |
| extern "C" __declspec(dllexport) |
| int InitMetro(LPTHREAD_START_ROUTINE thread_proc, void* context) { |
| ODS("InitMetro [Win7 emulation]"); |
| HWND window = CreateMetroTopLevelWindow(); |
| if (!window) |
| return 1; |
| // This magic incatation tells windows that the window is going fullscreen |
| // so the taskbar gets out of the wait automatically. |
| ::SetWindowPos(window, |
| HWND_TOP, |
| 0,0, |
| GetSystemMetrics(SM_CXSCREEN), |
| GetSystemMetrics(SM_CYSCREEN), |
| SWP_SHOWWINDOW); |
| |
| // Ready to start our caller. |
| globals.core_window = window; |
| globals.host_main = thread_proc; |
| globals.host_context = context; |
| HANDLE thread = ::CreateThread(NULL, 0, &HostThread, NULL, 0, NULL); |
| |
| // Main message loop. |
| MSG msg = {0}; |
| while (GetMessage(&msg, NULL, 0, 0)) { |
| TranslateMessage(&msg); |
| DispatchMessage(&msg); |
| } |
| |
| return (int) msg.wParam; |
| } |
| |
| extern "C" _declspec(dllexport) HWND GetRootWindow() { |
| ODS("GetRootWindow", ULONG_PTR(globals.core_window)); |
| return globals.core_window; |
| } |
| |
| extern "C" _declspec(dllexport) void SetFrameWindow(HWND window) { |
| ODS("SetFrameWindow", ULONG_PTR(window)); |
| globals.host_window = window; |
| } |
| |
| extern "C" __declspec(dllexport) const wchar_t* GetInitialUrl() { |
| return L""; |
| } |
| |