OLD | NEW |
| 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 |
1 // This project demonstrates how to migrate a Windows desktop app to Native | 6 // This project demonstrates how to migrate a Windows desktop app to Native |
2 // Client, running first as a Win32 application (define STEP1), then as a PPAPI | 7 // Client, running first as a Win32 application (define STEP1), then as a PPAPI |
3 // plugin (define STEP2 through STEP6), and finally as a Native Client module. | 8 // plugin (define STEP2 through STEP6), and finally as a Native Client module. |
4 | 9 |
5 // Start with STEP1 defined and the defines for STEP2 through STEP6 commented | 10 // Start with STEP1 defined and the defines for STEP2 through STEP6 commented |
6 // out. For each step in the process, un-comment the next #define, leaving the | 11 // out. For each step in the process, un-comment the next #define, leaving the |
7 // previous ones on. Ready, set, port! | 12 // previous ones on. Ready, set, port! |
8 | 13 |
9 // *** SELECT THE WIN32 PLATFORM AND RUN WITH #define STEP1 ONLY *** | 14 // *** SELECT THE WIN32 PLATFORM AND RUN WITH #define STEP1 ONLY *** |
10 | 15 |
11 #define STEP1 | 16 #define STEP1 |
12 // Launches the original Windows desktop application, Hello World, which runs | 17 // Launches the original Windows desktop application, Hello World, which runs |
13 // as WinMain. STEP1 encloses Windows-specific functions that are used with | 18 // as WinMain. STEP1 encloses Windows-specific functions that are used with |
14 // the WIN32 and PPAPI platforms. These will be removed when the full PPAPI | 19 // the WIN32 and PPAPI platforms. These will be removed when the full PPAPI |
15 // port is finished (STEP6) | 20 // port is finished (STEP6) |
16 | 21 |
17 // *** SELECT THE PPAPI PLATFORM *** | 22 // *** SELECT THE PPAPI PLATFORM *** |
18 | 23 |
19 #define STEP2 | 24 //#define STEP2 |
20 | 25 |
21 // Client Module. STEP2 encloses the Native Client module APIs needed to link | 26 // Client Module. STEP2 encloses the Native Client module APIs needed to link |
22 // any app to the browser. The module does nothing except report | 27 // any app to the browser. The module does nothing except report |
23 // starting/ending the function Instance_DidCreate. The Windows app does not | 28 // starting/ending the function Instance_DidCreate. The Windows app does not |
24 // run because it is not being called. | 29 // run because it is not being called. |
25 | 30 |
26 #define STEP3 | 31 //#define STEP3 |
27 // What changed: Replace WinMain with WndProc, and call it from | 32 // What changed: Replace WinMain with WndProc, and call it from |
28 // Instance_DidCreate, launching hello_nacl_plus in its own window. Since | 33 // Instance_DidCreate, launching hello_nacl_plus in its own window. Since |
29 // WndProc spins in its message loop, the call to Instance_DidCreate never | 34 // WndProc spins in its message loop, the call to Instance_DidCreate never |
30 // returns. Close the hello_nacl_plus window and the module initialization will | 35 // returns. Close the hello_nacl_plus window and the module initialization will |
31 // finish. | 36 // finish. |
32 | 37 |
33 #define STEP4 | 38 //#define STEP4 |
34 // What changed: In WndProc replace the message loop with a callback function. | 39 // What changed: In WndProc replace the message loop with a callback function. |
35 // Now the app window and the Native Client module are running concurrently. | 40 // Now the app window and the Native Client module are running concurrently. |
36 | 41 |
37 #define STEP5 | 42 //#define STEP5 |
38 // What changed: Instance_DidCreate calls initInstanceInBrowserWindow rather | 43 // What changed: Instance_DidCreate calls InitInstanceInBrowserWindow rather |
39 // than initInstanceInPCWindow. The initInstanceInBrowserWindow uses | 44 // than InitInstanceInPCWindow. The InitInstanceInBrowserWindow uses |
40 // postMessage to place text (now "Hello, Native Client") in the web page | 45 // postMessage to place text (now "Hello, Native Client") in the web page |
41 // instead of opening and writing to a window. | 46 // instead of opening and writing to a window. |
42 | 47 |
43 #define STEP6 | 48 //#define STEP6 |
44 // What changed: All the Windows code is def'd out, to prove we are | 49 // What changed: All the Windows code is def'd out, to prove we are |
45 // PPAPI-compliant. The functional code that is running is the same as STEP5. | 50 // PPAPI-compliant. The functional code that is running is the same as STEP5. |
46 | 51 |
47 // *** SELECT THE NACL64 PLATFORM AND RUN *** | 52 // *** SELECT THE NACL64 PLATFORM AND RUN *** |
48 | 53 |
49 // What changed: The code is the same as STEP6, but you are using the SDK | 54 // What changed: The code is the same as STEP6, but you are using the SDK |
50 // toolchain to compile it into a nexe. The module is now running as a real | 55 // toolchain to compile it into a nexe. The module is now running as a real |
51 // Native Client executable in a NaCl sandbox, with nacl-gdb attached. | 56 // Native Client executable in a NaCl sandbox, with nacl-gdb attached. |
52 | 57 |
53 // *** RUN YOUR MODULE IN THE WILD *** | 58 // *** RUN YOUR MODULE IN THE WILD *** |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
85 #include "ppapi/utility/completion_callback_factory.h" | 90 #include "ppapi/utility/completion_callback_factory.h" |
86 | 91 |
87 // This is a known PPAPI platform problem (Issue 81375). | 92 // This is a known PPAPI platform problem (Issue 81375). |
88 // When WinUser.h is included it defines PostMessage, so we undef it here. | 93 // When WinUser.h is included it defines PostMessage, so we undef it here. |
89 // There is a work-around: | 94 // There is a work-around: |
90 #ifdef PostMessage | 95 #ifdef PostMessage |
91 #undef PostMessage | 96 #undef PostMessage |
92 #endif | 97 #endif |
93 | 98 |
94 class NaClProjectInstance *myInstance; | 99 class NaClProjectInstance *myInstance; |
95 int initInstanceInPCWindow(); | 100 int InitInstanceInPCWindow(); |
96 void initInstanceInBrowserWindow(); | 101 void InitInstanceInBrowserWindow(); |
97 | 102 |
98 #endif | 103 #endif |
99 | 104 |
100 #ifdef STEP2 | 105 #ifdef STEP2 |
101 | 106 |
102 // **** Native Client Framework **** | 107 // **** Native Client Framework **** |
103 | 108 |
104 // The Instance class. | 109 // The Instance class. |
105 class NaClProjectInstance : public pp::Instance { | 110 class NaClProjectInstance : public pp::Instance { |
106 public: | 111 public: |
107 pp::CompletionCallbackFactory<NaClProjectInstance> factory_; | |
108 | |
109 explicit NaClProjectInstance(PP_Instance instance) | 112 explicit NaClProjectInstance(PP_Instance instance) |
110 : pp::Instance(instance), | 113 : pp::Instance(instance), |
111 // Use this macro to eliminate compiler warning. | 114 // Use this macro to eliminate compiler warning. |
112 PP_ALLOW_THIS_IN_INITIALIZER_LIST(factory_(this)) { | 115 PP_ALLOW_THIS_IN_INITIALIZER_LIST(factory_(this)) { |
113 myInstance = this; | 116 myInstance = this; |
114 } | 117 } |
115 | |
116 | 118 |
117 virtual ~NaClProjectInstance() { | 119 virtual ~NaClProjectInstance() { |
118 } | 120 } |
119 | 121 |
120 virtual bool Init(uint32_t /*argc*/, const char* /*argn*/[], | 122 virtual bool Init(uint32_t argc, const char* argn[], |
121 const char* /*argv*/[]) { | 123 const char* argv[]) { |
122 PostMessage(pp::Var("Creating Instance Start")); | 124 PostMessage(pp::Var("Creating Instance Start")); |
123 #ifdef STEP5 | 125 #ifdef STEP5 |
124 // Will be included in STEP5 and STEP6 | 126 // Will be included in STEP5 and STEP6 |
125 // Uses messaging to relay text to the module's view on the web page | 127 // Uses messaging to relay text to the module's view on the web page |
126 initInstanceInBrowserWindow(); | 128 InitInstanceInBrowserWindow(); |
127 #else | 129 #else |
128 #ifdef STEP3 | 130 #ifdef STEP3 |
129 // Will be included in STEP3 and STEP4 only | 131 // Will be included in STEP3 and STEP4 only |
130 // Uses WndProc to place text in a window separate from the browser. | 132 // Uses WndProc to place text in a window separate from the browser. |
131 initInstanceInPCWindow(); | 133 InitInstanceInPCWindow(); |
132 #endif | 134 #endif |
133 #endif | 135 #endif |
134 PostMessage(pp::Var("Creating Instance End")); | 136 PostMessage(pp::Var("Creating Instance End")); |
135 return true; | 137 return true; |
136 } | 138 } |
137 | 139 |
138 #ifdef STEP4 | 140 #ifdef STEP4 |
139 // Implements Windows window message loop with a callback function. | 141 // Implements Windows window message loop with a callback function. |
140 void NaClProjectInstance::SendCallback(int result) { | 142 void NaClProjectInstance::SendCallback(int result) { |
141 pp::Core* core = pp::Module::Get()->core(); | 143 pp::Core* core = pp::Module::Get()->core(); |
142 CompletionCallback callback = factory_.NewCallback(&HandleWindowMsg); | 144 core->CallOnMainThread( |
143 core->CallOnMainThread(100, callbacl, result); | 145 100, |
| 146 factory_.NewCallback(&NaClProjectInstance::HandleWindowMsg), |
| 147 result); |
144 } | 148 } |
145 | 149 |
146 void HandleWindowMsg(int32_t result) { | 150 void HandleWindowMsg(int32_t result) { |
147 MSG uMsg; | 151 MSG uMsg; |
148 if (PeekMessage(&uMsg, NULL, 0, 0, PM_REMOVE)) { | 152 if (PeekMessage(&uMsg, NULL, 0, 0, PM_REMOVE)) { |
149 TranslateMessage(&uMsg); | 153 TranslateMessage(&uMsg); |
150 DispatchMessage(&uMsg); | 154 DispatchMessage(&uMsg); |
151 } | 155 } |
152 SendCallback(0); | 156 SendCallback(0); |
153 } | 157 } |
154 | 158 |
155 #endif | 159 #endif |
156 private: | 160 private: |
157 virtual void HandleMessage(const pp::Var& var_message) { | 161 virtual void HandleMessage(const pp::Var& var_message) { |
158 } | 162 } |
| 163 |
| 164 pp::CompletionCallbackFactory<NaClProjectInstance> factory_; |
159 }; | 165 }; |
160 | 166 |
161 // The Module class. | 167 // The Module class. |
162 class NaClProjectModule : public pp::Module { | 168 class NaClProjectModule : public pp::Module { |
163 public: | 169 public: |
164 NaClProjectModule() : pp::Module() {} | 170 NaClProjectModule() : pp::Module() {} |
165 virtual ~NaClProjectModule() {} | 171 virtual ~NaClProjectModule() {} |
166 | 172 |
167 virtual pp::Instance* CreateInstance(PP_Instance instance) { | 173 virtual pp::Instance* CreateInstance(PP_Instance instance) { |
168 return new NaClProjectInstance(instance); | 174 return new NaClProjectInstance(instance); |
169 } | 175 } |
170 }; | 176 }; |
171 | 177 |
172 namespace pp { | 178 namespace pp { |
173 Module* CreateModule() { | 179 |
174 return new NaClProjectModule(); | 180 Module* CreateModule() { |
175 } | 181 return new NaClProjectModule(); |
| 182 } |
| 183 |
176 } | 184 } |
177 | 185 |
178 #endif | 186 #endif |
179 | 187 |
180 // **** Application Code **** | 188 // **** Application Code **** |
181 | 189 |
182 #ifdef STEP1 | 190 #ifdef STEP1 |
183 // Desktop Windows Hello World app. Native Client agnostic. | 191 // Desktop Windows Hello World app. Native Client agnostic. |
184 | 192 |
185 static TCHAR szWindowClass[] = _T("win32app"); | 193 static TCHAR szWindowClass[] = _T("win32app"); |
186 static TCHAR szTitle[] = _T("hello_nacl_plus"); | 194 static TCHAR szTitle[] = _T("hello_nacl_plus"); |
187 HINSTANCE hInst; | 195 HINSTANCE hInst; |
188 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); | 196 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); |
189 | 197 |
190 // WinMain | 198 // WinMain |
191 int WINAPI WinMain(HINSTANCE hInstance, | 199 int WINAPI WinMain( |
192 HINSTANCE hPrevInstance, | 200 HINSTANCE hInstance, |
193 LPSTR lpCmdLine, | 201 HINSTANCE hPrevInstance, |
194 int nCmdShow) | 202 LPSTR lpCmdLine, |
195 { | 203 int nCmdShow) { |
196 WNDCLASSEX wcex; | 204 WNDCLASSEX wcex; |
197 | 205 |
198 wcex.cbSize = sizeof(WNDCLASSEX); | 206 wcex.cbSize = sizeof(WNDCLASSEX); |
199 wcex.style = CS_HREDRAW | CS_VREDRAW; | 207 wcex.style = CS_HREDRAW | CS_VREDRAW; |
200 wcex.lpfnWndProc = WndProc; | 208 wcex.lpfnWndProc = WndProc; |
201 wcex.cbClsExtra = 0; | 209 wcex.cbClsExtra = 0; |
202 wcex.cbWndExtra = 0; | 210 wcex.cbWndExtra = 0; |
203 wcex.hInstance = hInstance; | 211 wcex.hInstance = hInstance; |
204 wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION)); | 212 wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION)); |
205 wcex.hCursor = LoadCursor(NULL, IDC_ARROW); | 213 wcex.hCursor = LoadCursor(NULL, IDC_ARROW); |
206 wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); | 214 wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); |
207 wcex.lpszMenuName = NULL; | 215 wcex.lpszMenuName = NULL; |
208 wcex.lpszClassName = szWindowClass; | 216 wcex.lpszClassName = szWindowClass; |
209 wcex.hIconSm = LoadIcon(wcex.hInstance, | 217 wcex.hIconSm = LoadIcon(wcex.hInstance, |
210 MAKEINTRESOURCE(IDI_APPLICATION)); | 218 MAKEINTRESOURCE(IDI_APPLICATION)); |
211 | 219 |
212 if (!RegisterClassEx(&wcex)) { | 220 if (!RegisterClassEx(&wcex)) { |
213 MessageBox(NULL, | 221 MessageBox(NULL, |
214 _T("Call to RegisterClassEx failed!"), | 222 _T("Call to RegisterClassEx failed!"), |
215 _T("hello_nacl_plus"), | 223 _T("hello_nacl_plus"), |
216 NULL); | 224 NULL); |
217 | 225 |
218 return 1; | 226 return 1; |
219 } | 227 } |
220 | 228 |
221 hInst = hInstance; | 229 hInst = hInstance; |
222 | 230 |
223 HWND hWnd = CreateWindow( | 231 HWND hWnd = CreateWindow( |
224 szWindowClass, | 232 szWindowClass, szTitle, |
225 szTitle, | 233 WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, |
226 WS_OVERLAPPEDWINDOW, | 234 500, 100, NULL, NULL, hInstance, NULL); |
227 CW_USEDEFAULT, CW_USEDEFAULT, | |
228 500, 100, | |
229 NULL, | |
230 NULL, | |
231 hInstance, | |
232 NULL); | |
233 | 235 |
234 if (!hWnd) { | 236 if (!hWnd) { |
235 MessageBox(NULL, | 237 MessageBox(NULL, |
236 _T("Call to CreateWindow failed!"), | 238 _T("Call to CreateWindow failed!"), |
237 _T("hello_nacl_plus"), | 239 _T("hello_nacl_plus"), |
238 NULL); | 240 NULL); |
239 | 241 |
240 return 1; | 242 return 1; |
241 } | 243 } |
242 | 244 |
243 ShowWindow(hWnd, | 245 ShowWindow(hWnd, nCmdShow); |
244 nCmdShow); | |
245 UpdateWindow(hWnd); | 246 UpdateWindow(hWnd); |
246 | 247 |
247 // Main message loop: | 248 // Main message loop: |
248 MSG msg; | 249 MSG msg; |
249 while (GetMessage(&msg, NULL, 0, 0)) { | 250 while (GetMessage(&msg, NULL, 0, 0)) { |
250 TranslateMessage(&msg); | 251 TranslateMessage(&msg); |
251 DispatchMessage(&msg); | 252 DispatchMessage(&msg); |
252 } | 253 } |
253 | 254 |
254 return (int) msg.wParam; | 255 return (int) msg.wParam; |
255 } | 256 } |
256 | 257 |
257 // WndProc | 258 // WndProc |
258 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) | 259 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, |
259 { | 260 WPARAM wParam, LPARAM lParam) { |
260 PAINTSTRUCT ps; | 261 PAINTSTRUCT ps; |
261 HDC hdc; | 262 HDC hdc; |
262 TCHAR greeting[] = _T("Hello, World!"); | 263 TCHAR greeting[] = _T("Hello, World!"); |
263 | 264 |
264 switch (message) | 265 switch (message) |
265 { | 266 { |
266 case WM_PAINT: | 267 case WM_PAINT: |
267 hdc = BeginPaint(hWnd, &ps); | 268 hdc = BeginPaint(hWnd, &ps); |
268 | 269 |
269 // Here your application is laid out. | 270 // Here your application is laid out. |
(...skipping 12 matching lines...) Expand all Loading... |
282 default: | 283 default: |
283 return DefWindowProc(hWnd, message, wParam, lParam); | 284 return DefWindowProc(hWnd, message, wParam, lParam); |
284 break; | 285 break; |
285 } | 286 } |
286 | 287 |
287 return 0; | 288 return 0; |
288 } | 289 } |
289 #endif | 290 #endif |
290 | 291 |
291 #ifdef STEP3 | 292 #ifdef STEP3 |
292 // Replace WinMain with initInstanceInPCWindow so the NativeClient Module can | 293 // Replace WinMain with InitInstanceInPCWindow so the NativeClient Module can |
293 // launch the original application. | 294 // launch the original application. |
294 // Note the inclusion of a message-handling loop. STEP4 will replace the loop | 295 // Note the inclusion of a message-handling loop. STEP4 will replace the loop |
295 // with a callback. | 296 // with a callback. |
296 | 297 |
297 void shutDown(void); | 298 void shutDown(void); |
298 HINSTANCE g_hInstance = NULL; | 299 HINSTANCE g_hInstance = NULL; |
299 HWND g_hWnd = NULL; | 300 HWND g_hWnd = NULL; |
300 | 301 |
301 int initInstanceInPCWindow() | 302 int InitInstanceInPCWindow() |
302 { | 303 { |
303 WNDCLASSEX winClass; | 304 WNDCLASSEX winClass; |
304 MSG uMsg; | 305 MSG uMsg; |
305 | 306 |
306 memset(&uMsg,0,sizeof(uMsg)); | 307 memset(&uMsg,0,sizeof(uMsg)); |
307 | 308 |
308 winClass.lpszClassName = _T("MY_WINDOWS_CLASS"); | 309 winClass.lpszClassName = _T("MY_WINDOWS_CLASS"); |
309 winClass.cbSize = sizeof(WNDCLASSEX); | 310 winClass.cbSize = sizeof(WNDCLASSEX); |
310 winClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; | 311 winClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; |
311 winClass.lpfnWndProc = WndProc; | 312 winClass.lpfnWndProc = WndProc; |
312 winClass.hInstance = g_hInstance; | 313 winClass.hInstance = g_hInstance; |
313 winClass.hIcon = NULL; | 314 winClass.hIcon = NULL; |
314 winClass.hIconSm = NULL; | 315 winClass.hIconSm = NULL; |
315 winClass.hCursor = LoadCursor(NULL, IDC_ARROW); | 316 winClass.hCursor = LoadCursor(NULL, IDC_ARROW); |
316 winClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); | 317 winClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); |
317 winClass.lpszMenuName = NULL; | 318 winClass.lpszMenuName = NULL; |
318 winClass.cbClsExtra = 0; | 319 winClass.cbClsExtra = 0; |
319 winClass.cbWndExtra = 0; | 320 winClass.cbWndExtra = 0; |
320 | 321 |
321 if (!RegisterClassEx(&winClass)) | 322 if (!RegisterClassEx(&winClass)) |
322 return E_FAIL; | 323 return E_FAIL; |
323 | 324 |
324 g_hWnd = CreateWindowEx(NULL,_T("MY_WINDOWS_CLASS"), | 325 g_hWnd = CreateWindowEx( |
325 _T("hello_nacl_plus"), | 326 NULL,_T("MY_WINDOWS_CLASS"), |
326 WS_OVERLAPPEDWINDOW, | 327 _T("hello_nacl_plus"), |
327 0,0, 640, 480, NULL, NULL, g_hInstance, NULL); | 328 WS_OVERLAPPEDWINDOW, |
| 329 0, 0, 640, 480, NULL, NULL, g_hInstance, NULL); |
328 | 330 |
329 if (g_hWnd == NULL) | 331 if (g_hWnd == NULL) |
330 return E_FAIL; | 332 return E_FAIL; |
331 | 333 |
332 ShowWindow(g_hWnd, 1); | 334 ShowWindow(g_hWnd, 1); |
333 | 335 |
334 UpdateWindow(g_hWnd); | 336 UpdateWindow(g_hWnd); |
335 | 337 |
336 #ifdef STEP4 | 338 #ifdef STEP4 |
337 // Skip the message loop, schedule a callback instead to periodically check | 339 // Skip the message loop, schedule a callback instead to periodically check |
(...skipping 11 matching lines...) Expand all Loading... |
349 return uMsg.wParam; | 351 return uMsg.wParam; |
350 #endif | 352 #endif |
351 | 353 |
352 } | 354 } |
353 #endif | 355 #endif |
354 | 356 |
355 #ifdef STEP5 | 357 #ifdef STEP5 |
356 // Pass the text to the browser page, there is no separate app window anymore. | 358 // Pass the text to the browser page, there is no separate app window anymore. |
357 // The text is added as a new element to the page, it does not appear in the | 359 // The text is added as a new element to the page, it does not appear in the |
358 // module's embed view. | 360 // module's embed view. |
359 void initInstanceInBrowserWindow() { | 361 void InitInstanceInBrowserWindow() { |
360 myInstance->PostMessage(pp::Var("Hello, Native Client!")); | 362 myInstance->PostMessage(pp::Var("Hello, Native Client!")); |
361 } | 363 } |
362 #endif | 364 #endif |
OLD | NEW |