summaryrefslogtreecommitdiffstats
path: root/win8/metro_driver/metro_driver_win7.cc
blob: 253e527b8c2a29dd0e26da8e8a0c3f9543e2bbe2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
// 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"";
}