entry_windows.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675
  1. /*
  2. * Copyright 2011-2014 Branimir Karadzic. All rights reserved.
  3. * License: http://www.opensource.org/licenses/BSD-2-Clause
  4. */
  5. #include "entry_p.h"
  6. #if ENTRY_CONFIG_USE_NATIVE && BX_PLATFORM_WINDOWS
  7. #include <bgfxplatform.h>
  8. #include <bx/uint32_t.h>
  9. #include <bx/thread.h>
  10. #include <windowsx.h>
  11. #define WM_USER_SET_WINDOW_SIZE (WM_USER+0)
  12. #define WM_USER_TOGGLE_WINDOW_FRAME (WM_USER+1)
  13. #define WM_USER_MOUSE_LOCK (WM_USER+2)
  14. #define WM_USER_SET_WINDOW_TITLE (WM_USER+3)
  15. namespace entry
  16. {
  17. struct TranslateKeyModifiers
  18. {
  19. int m_vk;
  20. Modifier::Enum m_modifier;
  21. };
  22. static const TranslateKeyModifiers s_translateKeyModifiers[8] =
  23. {
  24. { VK_LMENU, Modifier::LeftAlt },
  25. { VK_RMENU, Modifier::RightAlt },
  26. { VK_LCONTROL, Modifier::LeftCtrl },
  27. { VK_RCONTROL, Modifier::RightCtrl },
  28. { VK_LSHIFT, Modifier::LeftShift },
  29. { VK_RSHIFT, Modifier::RightShift },
  30. { VK_LWIN, Modifier::LeftMeta },
  31. { VK_RWIN, Modifier::RightMeta },
  32. };
  33. static uint8_t translateKeyModifiers()
  34. {
  35. uint8_t modifiers = 0;
  36. for (uint32_t ii = 0; ii < BX_COUNTOF(s_translateKeyModifiers); ++ii)
  37. {
  38. const TranslateKeyModifiers& tkm = s_translateKeyModifiers[ii];
  39. modifiers |= 0 > GetKeyState(tkm.m_vk) ? tkm.m_modifier : Modifier::None;
  40. }
  41. return modifiers;
  42. }
  43. static uint8_t s_translateKey[256];
  44. static Key::Enum translateKey(WPARAM _wparam)
  45. {
  46. return (Key::Enum)s_translateKey[_wparam&0xff];
  47. }
  48. struct MainThreadEntry
  49. {
  50. int m_argc;
  51. char** m_argv;
  52. static int32_t threadFunc(void* _userData);
  53. };
  54. struct Context
  55. {
  56. Context()
  57. : m_frame(true)
  58. , m_mouseLock(false)
  59. , m_init(false)
  60. , m_exit(false)
  61. , m_mz(0)
  62. {
  63. memset(s_translateKey, 0, sizeof(s_translateKey) );
  64. s_translateKey[VK_ESCAPE] = Key::Esc;
  65. s_translateKey[VK_RETURN] = Key::Return;
  66. s_translateKey[VK_TAB] = Key::Tab;
  67. s_translateKey[VK_BACK] = Key::Backspace;
  68. s_translateKey[VK_SPACE] = Key::Space;
  69. s_translateKey[VK_UP] = Key::Up;
  70. s_translateKey[VK_DOWN] = Key::Down;
  71. s_translateKey[VK_LEFT] = Key::Left;
  72. s_translateKey[VK_RIGHT] = Key::Right;
  73. s_translateKey[VK_PRIOR] = Key::PageUp;
  74. s_translateKey[VK_NEXT] = Key::PageUp;
  75. s_translateKey[VK_HOME] = Key::Home;
  76. s_translateKey[VK_END] = Key::End;
  77. s_translateKey[VK_SNAPSHOT] = Key::Print;
  78. s_translateKey[VK_OEM_PLUS] = Key::Plus;
  79. s_translateKey[VK_OEM_MINUS] = Key::Minus;
  80. s_translateKey[VK_F1] = Key::F1;
  81. s_translateKey[VK_F2] = Key::F2;
  82. s_translateKey[VK_F3] = Key::F3;
  83. s_translateKey[VK_F4] = Key::F4;
  84. s_translateKey[VK_F5] = Key::F5;
  85. s_translateKey[VK_F6] = Key::F6;
  86. s_translateKey[VK_F7] = Key::F7;
  87. s_translateKey[VK_F8] = Key::F8;
  88. s_translateKey[VK_F9] = Key::F9;
  89. s_translateKey[VK_F10] = Key::F10;
  90. s_translateKey[VK_F11] = Key::F11;
  91. s_translateKey[VK_F12] = Key::F12;
  92. s_translateKey[VK_NUMPAD0] = Key::NumPad0;
  93. s_translateKey[VK_NUMPAD1] = Key::NumPad1;
  94. s_translateKey[VK_NUMPAD2] = Key::NumPad2;
  95. s_translateKey[VK_NUMPAD3] = Key::NumPad3;
  96. s_translateKey[VK_NUMPAD4] = Key::NumPad4;
  97. s_translateKey[VK_NUMPAD5] = Key::NumPad5;
  98. s_translateKey[VK_NUMPAD6] = Key::NumPad6;
  99. s_translateKey[VK_NUMPAD7] = Key::NumPad7;
  100. s_translateKey[VK_NUMPAD8] = Key::NumPad8;
  101. s_translateKey[VK_NUMPAD9] = Key::NumPad9;
  102. s_translateKey['0'] = Key::Key0;
  103. s_translateKey['1'] = Key::Key1;
  104. s_translateKey['2'] = Key::Key2;
  105. s_translateKey['3'] = Key::Key3;
  106. s_translateKey['4'] = Key::Key4;
  107. s_translateKey['5'] = Key::Key5;
  108. s_translateKey['6'] = Key::Key6;
  109. s_translateKey['7'] = Key::Key7;
  110. s_translateKey['8'] = Key::Key8;
  111. s_translateKey['9'] = Key::Key9;
  112. s_translateKey['A'] = Key::KeyA;
  113. s_translateKey['B'] = Key::KeyB;
  114. s_translateKey['C'] = Key::KeyC;
  115. s_translateKey['D'] = Key::KeyD;
  116. s_translateKey['E'] = Key::KeyE;
  117. s_translateKey['F'] = Key::KeyF;
  118. s_translateKey['G'] = Key::KeyG;
  119. s_translateKey['H'] = Key::KeyH;
  120. s_translateKey['I'] = Key::KeyI;
  121. s_translateKey['J'] = Key::KeyJ;
  122. s_translateKey['K'] = Key::KeyK;
  123. s_translateKey['L'] = Key::KeyL;
  124. s_translateKey['M'] = Key::KeyM;
  125. s_translateKey['N'] = Key::KeyN;
  126. s_translateKey['O'] = Key::KeyO;
  127. s_translateKey['P'] = Key::KeyP;
  128. s_translateKey['Q'] = Key::KeyQ;
  129. s_translateKey['R'] = Key::KeyR;
  130. s_translateKey['S'] = Key::KeyS;
  131. s_translateKey['T'] = Key::KeyT;
  132. s_translateKey['U'] = Key::KeyU;
  133. s_translateKey['V'] = Key::KeyV;
  134. s_translateKey['W'] = Key::KeyW;
  135. s_translateKey['X'] = Key::KeyX;
  136. s_translateKey['Y'] = Key::KeyY;
  137. s_translateKey['Z'] = Key::KeyZ;
  138. }
  139. int32_t run(int _argc, char** _argv)
  140. {
  141. SetDllDirectory(".");
  142. HINSTANCE instance = (HINSTANCE)GetModuleHandle(NULL);
  143. WNDCLASSEX wnd;
  144. memset(&wnd, 0, sizeof(wnd) );
  145. wnd.cbSize = sizeof(wnd);
  146. wnd.lpfnWndProc = DefWindowProc;
  147. wnd.hInstance = instance;
  148. wnd.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  149. wnd.hCursor = LoadCursor(NULL, IDC_ARROW);
  150. wnd.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
  151. wnd.lpszClassName = "bgfx_letterbox";
  152. wnd.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
  153. RegisterClassExA(&wnd);
  154. memset(&wnd, 0, sizeof(wnd) );
  155. wnd.cbSize = sizeof(wnd);
  156. wnd.style = CS_HREDRAW | CS_VREDRAW;
  157. wnd.lpfnWndProc = wndProc;
  158. wnd.hInstance = instance;
  159. wnd.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  160. wnd.hCursor = LoadCursor(NULL, IDC_ARROW);
  161. wnd.lpszClassName = "bgfx";
  162. wnd.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
  163. RegisterClassExA(&wnd);
  164. HWND hwnd = CreateWindowA("bgfx_letterbox"
  165. , "BGFX"
  166. , WS_POPUP|WS_SYSMENU
  167. , -32000
  168. , -32000
  169. , 0
  170. , 0
  171. , NULL
  172. , NULL
  173. , instance
  174. , 0
  175. );
  176. m_hwnd = CreateWindowA("bgfx"
  177. , "BGFX"
  178. , WS_OVERLAPPEDWINDOW|WS_VISIBLE
  179. , 0
  180. , 0
  181. , ENTRY_DEFAULT_WIDTH
  182. , ENTRY_DEFAULT_HEIGHT
  183. , hwnd
  184. , NULL
  185. , instance
  186. , 0
  187. );
  188. bgfx::winSetHwnd(m_hwnd);
  189. adjust(ENTRY_DEFAULT_WIDTH, ENTRY_DEFAULT_HEIGHT, true);
  190. m_width = ENTRY_DEFAULT_WIDTH;
  191. m_height = ENTRY_DEFAULT_HEIGHT;
  192. m_oldWidth = ENTRY_DEFAULT_WIDTH;
  193. m_oldHeight = ENTRY_DEFAULT_HEIGHT;
  194. MainThreadEntry mte;
  195. mte.m_argc = _argc;
  196. mte.m_argv = _argv;
  197. bx::Thread thread;
  198. thread.init(mte.threadFunc, &mte);
  199. m_init = true;
  200. m_eventQueue.postSizeEvent(m_width, m_height);
  201. MSG msg;
  202. msg.message = WM_NULL;
  203. while (!m_exit)
  204. {
  205. WaitMessage();
  206. while (0 != PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE) )
  207. {
  208. TranslateMessage(&msg);
  209. DispatchMessage(&msg);
  210. }
  211. }
  212. thread.shutdown();
  213. DestroyWindow(m_hwnd);
  214. DestroyWindow(hwnd);
  215. return 0;
  216. }
  217. LRESULT process(HWND _hwnd, UINT _id, WPARAM _wparam, LPARAM _lparam)
  218. {
  219. if (m_init)
  220. {
  221. switch (_id)
  222. {
  223. case WM_USER_SET_WINDOW_SIZE:
  224. {
  225. uint32_t width = GET_X_LPARAM(_lparam);
  226. uint32_t height = GET_Y_LPARAM(_lparam);
  227. adjust(width, height, true);
  228. }
  229. break;
  230. case WM_USER_SET_WINDOW_TITLE:
  231. {
  232. SetWindowText(_hwnd, (const char*)_lparam);
  233. }
  234. break;
  235. case WM_USER_TOGGLE_WINDOW_FRAME:
  236. {
  237. if (m_frame)
  238. {
  239. m_oldWidth = m_width;
  240. m_oldHeight = m_height;
  241. }
  242. adjust(m_oldWidth, m_oldHeight, !m_frame);
  243. }
  244. break;
  245. case WM_USER_MOUSE_LOCK:
  246. setMouseLock(!!_lparam);
  247. break;
  248. case WM_DESTROY:
  249. break;
  250. case WM_QUIT:
  251. case WM_CLOSE:
  252. m_exit = true;
  253. m_eventQueue.postExitEvent();
  254. break;
  255. case WM_SIZING:
  256. {
  257. RECT& rect = *(RECT*)_lparam;
  258. uint32_t width = rect.right - rect.left - m_frameWidth;
  259. uint32_t height = rect.bottom - rect.top - m_frameHeight;
  260. //Recalculate size according to aspect ratio
  261. switch (_wparam)
  262. {
  263. case WMSZ_LEFT:
  264. case WMSZ_RIGHT:
  265. {
  266. float aspectRatio = 1.0f/m_aspectRatio;
  267. width = bx::uint32_max(ENTRY_DEFAULT_WIDTH/4, width);
  268. height = uint32_t(float(width)*aspectRatio);
  269. }
  270. break;
  271. default:
  272. {
  273. float aspectRatio = m_aspectRatio;
  274. height = bx::uint32_max(ENTRY_DEFAULT_HEIGHT/4, height);
  275. width = uint32_t(float(height)*aspectRatio);
  276. }
  277. break;
  278. }
  279. //Recalculate position using different anchor points
  280. switch(_wparam)
  281. {
  282. case WMSZ_LEFT:
  283. case WMSZ_TOPLEFT:
  284. case WMSZ_BOTTOMLEFT:
  285. rect.left = rect.right - width - m_frameWidth;
  286. rect.bottom = rect.top + height + m_frameHeight;
  287. break;
  288. default:
  289. rect.right = rect.left + width + m_frameWidth;
  290. rect.bottom = rect.top + height + m_frameHeight;
  291. break;
  292. }
  293. m_eventQueue.postSizeEvent(m_width, m_height);
  294. }
  295. return 0;
  296. case WM_SIZE:
  297. {
  298. uint32_t width = GET_X_LPARAM(_lparam);
  299. uint32_t height = GET_Y_LPARAM(_lparam);
  300. m_width = width;
  301. m_height = height;
  302. m_eventQueue.postSizeEvent(m_width, m_height);
  303. }
  304. break;
  305. case WM_SYSCOMMAND:
  306. switch (_wparam)
  307. {
  308. case SC_MINIMIZE:
  309. case SC_RESTORE:
  310. {
  311. HWND parent = GetWindow(_hwnd, GW_OWNER);
  312. if (NULL != parent)
  313. {
  314. PostMessage(parent, _id, _wparam, _lparam);
  315. }
  316. }
  317. }
  318. break;
  319. case WM_MOUSEMOVE:
  320. {
  321. int32_t mx = GET_X_LPARAM(_lparam);
  322. int32_t my = GET_Y_LPARAM(_lparam);
  323. if (m_mouseLock)
  324. {
  325. mx -= m_mx;
  326. my -= m_my;
  327. if (0 == mx
  328. && 0 == my)
  329. {
  330. break;
  331. }
  332. setMousePos(m_mx, m_my);
  333. }
  334. m_eventQueue.postMouseEvent(mx, my, m_mz);
  335. }
  336. break;
  337. case WM_MOUSEWHEEL:
  338. {
  339. POINT pt = { GET_X_LPARAM(_lparam), GET_Y_LPARAM(_lparam) };
  340. ScreenToClient(m_hwnd, &pt);
  341. int32_t mx = pt.x;
  342. int32_t my = pt.y;
  343. m_mz += GET_WHEEL_DELTA_WPARAM(_wparam);
  344. m_eventQueue.postMouseEvent(mx, my, m_mz);
  345. }
  346. break;
  347. case WM_LBUTTONDOWN:
  348. case WM_LBUTTONUP:
  349. case WM_LBUTTONDBLCLK:
  350. {
  351. int32_t mx = GET_X_LPARAM(_lparam);
  352. int32_t my = GET_Y_LPARAM(_lparam);
  353. m_eventQueue.postMouseEvent(mx, my, m_mz, MouseButton::Left, _id == WM_LBUTTONDOWN);
  354. }
  355. break;
  356. case WM_MBUTTONDOWN:
  357. case WM_MBUTTONUP:
  358. case WM_MBUTTONDBLCLK:
  359. {
  360. int32_t mx = GET_X_LPARAM(_lparam);
  361. int32_t my = GET_Y_LPARAM(_lparam);
  362. m_eventQueue.postMouseEvent(mx, my, m_mz, MouseButton::Middle, _id == WM_MBUTTONDOWN);
  363. }
  364. break;
  365. case WM_RBUTTONUP:
  366. case WM_RBUTTONDOWN:
  367. case WM_RBUTTONDBLCLK:
  368. {
  369. int32_t mx = GET_X_LPARAM(_lparam);
  370. int32_t my = GET_Y_LPARAM(_lparam);
  371. m_eventQueue.postMouseEvent(mx, my, m_mz, MouseButton::Right, _id == WM_RBUTTONDOWN);
  372. }
  373. break;
  374. case WM_KEYDOWN:
  375. case WM_SYSKEYDOWN:
  376. case WM_KEYUP:
  377. case WM_SYSKEYUP:
  378. {
  379. uint8_t modifiers = translateKeyModifiers();
  380. Key::Enum key = translateKey(_wparam);
  381. if (Key::Print == key
  382. && 0x3 == ( (uint32_t)(_lparam)>>30) )
  383. {
  384. // VK_SNAPSHOT doesn't generate keydown event. Fire on down event when previous
  385. // key state bit is set to 1 and transition state bit is set to 1.
  386. //
  387. // http://msdn.microsoft.com/en-us/library/windows/desktop/ms646280%28v=vs.85%29.aspx
  388. m_eventQueue.postKeyEvent(key, modifiers, true);
  389. }
  390. m_eventQueue.postKeyEvent(key, modifiers, _id == WM_KEYDOWN || _id == WM_SYSKEYDOWN);
  391. }
  392. break;
  393. default:
  394. break;
  395. }
  396. }
  397. return DefWindowProc(_hwnd, _id, _wparam, _lparam);
  398. }
  399. void adjust(uint32_t _width, uint32_t _height, bool _windowFrame)
  400. {
  401. m_width = _width;
  402. m_height = _height;
  403. m_aspectRatio = float(_width)/float(_height);
  404. ShowWindow(m_hwnd, SW_SHOWNORMAL);
  405. RECT rect;
  406. RECT newrect = {0, 0, (LONG)_width, (LONG)_height};
  407. DWORD style = WS_POPUP|WS_SYSMENU;
  408. if (m_frame)
  409. {
  410. GetWindowRect(m_hwnd, &m_rect);
  411. m_style = GetWindowLong(m_hwnd, GWL_STYLE);
  412. }
  413. if (_windowFrame)
  414. {
  415. rect = m_rect;
  416. style = m_style;
  417. }
  418. else
  419. {
  420. #if defined(__MINGW32__)
  421. rect = m_rect;
  422. style = m_style;
  423. #else
  424. HMONITOR monitor = MonitorFromWindow(m_hwnd, MONITOR_DEFAULTTONEAREST);
  425. MONITORINFO mi;
  426. mi.cbSize = sizeof(mi);
  427. GetMonitorInfo(monitor, &mi);
  428. newrect = mi.rcMonitor;
  429. rect = mi.rcMonitor;
  430. #endif // !defined(__MINGW__)
  431. }
  432. SetWindowLong(m_hwnd, GWL_STYLE, style);
  433. uint32_t prewidth = newrect.right - newrect.left;
  434. uint32_t preheight = newrect.bottom - newrect.top;
  435. AdjustWindowRect(&newrect, style, FALSE);
  436. m_frameWidth = (newrect.right - newrect.left) - prewidth;
  437. m_frameHeight = (newrect.bottom - newrect.top) - preheight;
  438. UpdateWindow(m_hwnd);
  439. if (rect.left == -32000
  440. || rect.top == -32000)
  441. {
  442. rect.left = 0;
  443. rect.top = 0;
  444. }
  445. int32_t left = rect.left;
  446. int32_t top = rect.top;
  447. int32_t width = (newrect.right-newrect.left);
  448. int32_t height = (newrect.bottom-newrect.top);
  449. if (!_windowFrame)
  450. {
  451. float aspectRatio = 1.0f/m_aspectRatio;
  452. width = bx::uint32_max(ENTRY_DEFAULT_WIDTH/4, width);
  453. height = uint32_t(float(width)*aspectRatio);
  454. left = newrect.left+(newrect.right-newrect.left-width)/2;
  455. top = newrect.top+(newrect.bottom-newrect.top-height)/2;
  456. }
  457. HWND parent = GetWindow(m_hwnd, GW_OWNER);
  458. if (NULL != parent)
  459. {
  460. if (_windowFrame)
  461. {
  462. SetWindowPos(parent
  463. , HWND_TOP
  464. , -32000
  465. , -32000
  466. , 0
  467. , 0
  468. , SWP_SHOWWINDOW
  469. );
  470. }
  471. else
  472. {
  473. SetWindowPos(parent
  474. , HWND_TOP
  475. , newrect.left
  476. , newrect.top
  477. , newrect.right-newrect.left
  478. , newrect.bottom-newrect.top
  479. , SWP_SHOWWINDOW
  480. );
  481. }
  482. }
  483. SetWindowPos(m_hwnd
  484. , HWND_TOP
  485. , left
  486. , top
  487. , width
  488. , height
  489. , SWP_SHOWWINDOW
  490. );
  491. ShowWindow(m_hwnd, SW_RESTORE);
  492. m_frame = _windowFrame;
  493. }
  494. void setMousePos(int32_t _mx, int32_t _my)
  495. {
  496. POINT pt = { _mx, _my };
  497. ClientToScreen(m_hwnd, &pt);
  498. SetCursorPos(pt.x, pt.y);
  499. }
  500. void setMouseLock(bool _lock)
  501. {
  502. if (_lock != m_mouseLock)
  503. {
  504. if (_lock)
  505. {
  506. m_mx = m_width/2;
  507. m_my = m_height/2;
  508. ShowCursor(false);
  509. setMousePos(m_mx, m_my);
  510. }
  511. else
  512. {
  513. setMousePos(m_mx, m_my);
  514. ShowCursor(true);
  515. }
  516. m_mouseLock = _lock;
  517. }
  518. }
  519. static LRESULT CALLBACK wndProc(HWND _hwnd, UINT _id, WPARAM _wparam, LPARAM _lparam);
  520. EventQueue m_eventQueue;
  521. HWND m_hwnd;
  522. RECT m_rect;
  523. DWORD m_style;
  524. uint32_t m_width;
  525. uint32_t m_height;
  526. uint32_t m_oldWidth;
  527. uint32_t m_oldHeight;
  528. uint32_t m_frameWidth;
  529. uint32_t m_frameHeight;
  530. float m_aspectRatio;
  531. int32_t m_mx;
  532. int32_t m_my;
  533. int32_t m_mz;
  534. bool m_frame;
  535. bool m_mouseLock;
  536. bool m_init;
  537. bool m_exit;
  538. };
  539. static Context s_ctx;
  540. LRESULT CALLBACK Context::wndProc(HWND _hwnd, UINT _id, WPARAM _wparam, LPARAM _lparam)
  541. {
  542. return s_ctx.process(_hwnd, _id, _wparam, _lparam);
  543. }
  544. const Event* poll()
  545. {
  546. return s_ctx.m_eventQueue.poll();
  547. }
  548. void release(const Event* _event)
  549. {
  550. s_ctx.m_eventQueue.release(_event);
  551. }
  552. void setWindowSize(uint32_t _width, uint32_t _height)
  553. {
  554. PostMessage(s_ctx.m_hwnd, WM_USER_SET_WINDOW_SIZE, 0, (_height<<16) | (_width&0xffff) );
  555. }
  556. void setWindowTitle(const char* _title)
  557. {
  558. PostMessage(s_ctx.m_hwnd, WM_USER_SET_WINDOW_TITLE, 0, (LPARAM)_title);
  559. }
  560. void toggleWindowFrame()
  561. {
  562. PostMessage(s_ctx.m_hwnd, WM_USER_TOGGLE_WINDOW_FRAME, 0, 0);
  563. }
  564. void setMouseLock(bool _lock)
  565. {
  566. PostMessage(s_ctx.m_hwnd, WM_USER_MOUSE_LOCK, 0, _lock);
  567. }
  568. int32_t MainThreadEntry::threadFunc(void* _userData)
  569. {
  570. MainThreadEntry* self = (MainThreadEntry*)_userData;
  571. int32_t result = main(self->m_argc, self->m_argv);
  572. PostMessage(s_ctx.m_hwnd, WM_QUIT, 0, 0);
  573. return result;
  574. }
  575. } // namespace entry
  576. int main(int _argc, char** _argv)
  577. {
  578. using namespace entry;
  579. return s_ctx.run(_argc, _argv);
  580. }
  581. #endif // BX_PLATFORM_WINDOWS