entry_windows.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715
  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 <bx/mutex.h>
  11. #include <bx/handlealloc.h>
  12. #include <windowsx.h>
  13. #define WM_USER_CREATE_WINDOW (WM_USER+0)
  14. #define WM_USER_SET_WINDOW_SIZE (WM_USER+1)
  15. #define WM_USER_TOGGLE_WINDOW_FRAME (WM_USER+2)
  16. #define WM_USER_MOUSE_LOCK (WM_USER+3)
  17. namespace entry
  18. {
  19. struct TranslateKeyModifiers
  20. {
  21. int m_vk;
  22. Modifier::Enum m_modifier;
  23. };
  24. static const TranslateKeyModifiers s_translateKeyModifiers[8] =
  25. {
  26. { VK_LMENU, Modifier::LeftAlt },
  27. { VK_RMENU, Modifier::RightAlt },
  28. { VK_LCONTROL, Modifier::LeftCtrl },
  29. { VK_RCONTROL, Modifier::RightCtrl },
  30. { VK_LSHIFT, Modifier::LeftShift },
  31. { VK_RSHIFT, Modifier::RightShift },
  32. { VK_LWIN, Modifier::LeftMeta },
  33. { VK_RWIN, Modifier::RightMeta },
  34. };
  35. static uint8_t translateKeyModifiers()
  36. {
  37. uint8_t modifiers = 0;
  38. for (uint32_t ii = 0; ii < BX_COUNTOF(s_translateKeyModifiers); ++ii)
  39. {
  40. const TranslateKeyModifiers& tkm = s_translateKeyModifiers[ii];
  41. modifiers |= 0 > GetKeyState(tkm.m_vk) ? tkm.m_modifier : Modifier::None;
  42. }
  43. return modifiers;
  44. }
  45. static uint8_t s_translateKey[256];
  46. static Key::Enum translateKey(WPARAM _wparam)
  47. {
  48. return (Key::Enum)s_translateKey[_wparam&0xff];
  49. }
  50. struct MainThreadEntry
  51. {
  52. int m_argc;
  53. char** m_argv;
  54. static int32_t threadFunc(void* _userData);
  55. };
  56. struct Context
  57. {
  58. Context()
  59. : m_mz(0)
  60. , m_frame(true)
  61. , m_mouseLock(NULL)
  62. , m_init(false)
  63. , m_exit(false)
  64. {
  65. memset(s_translateKey, 0, sizeof(s_translateKey) );
  66. s_translateKey[VK_ESCAPE] = Key::Esc;
  67. s_translateKey[VK_RETURN] = Key::Return;
  68. s_translateKey[VK_TAB] = Key::Tab;
  69. s_translateKey[VK_BACK] = Key::Backspace;
  70. s_translateKey[VK_SPACE] = Key::Space;
  71. s_translateKey[VK_UP] = Key::Up;
  72. s_translateKey[VK_DOWN] = Key::Down;
  73. s_translateKey[VK_LEFT] = Key::Left;
  74. s_translateKey[VK_RIGHT] = Key::Right;
  75. s_translateKey[VK_PRIOR] = Key::PageUp;
  76. s_translateKey[VK_NEXT] = Key::PageUp;
  77. s_translateKey[VK_HOME] = Key::Home;
  78. s_translateKey[VK_END] = Key::End;
  79. s_translateKey[VK_SNAPSHOT] = Key::Print;
  80. s_translateKey[VK_OEM_PLUS] = Key::Plus;
  81. s_translateKey[VK_OEM_MINUS] = Key::Minus;
  82. s_translateKey[VK_F1] = Key::F1;
  83. s_translateKey[VK_F2] = Key::F2;
  84. s_translateKey[VK_F3] = Key::F3;
  85. s_translateKey[VK_F4] = Key::F4;
  86. s_translateKey[VK_F5] = Key::F5;
  87. s_translateKey[VK_F6] = Key::F6;
  88. s_translateKey[VK_F7] = Key::F7;
  89. s_translateKey[VK_F8] = Key::F8;
  90. s_translateKey[VK_F9] = Key::F9;
  91. s_translateKey[VK_F10] = Key::F10;
  92. s_translateKey[VK_F11] = Key::F11;
  93. s_translateKey[VK_F12] = Key::F12;
  94. s_translateKey[VK_NUMPAD0] = Key::NumPad0;
  95. s_translateKey[VK_NUMPAD1] = Key::NumPad1;
  96. s_translateKey[VK_NUMPAD2] = Key::NumPad2;
  97. s_translateKey[VK_NUMPAD3] = Key::NumPad3;
  98. s_translateKey[VK_NUMPAD4] = Key::NumPad4;
  99. s_translateKey[VK_NUMPAD5] = Key::NumPad5;
  100. s_translateKey[VK_NUMPAD6] = Key::NumPad6;
  101. s_translateKey[VK_NUMPAD7] = Key::NumPad7;
  102. s_translateKey[VK_NUMPAD8] = Key::NumPad8;
  103. s_translateKey[VK_NUMPAD9] = Key::NumPad9;
  104. s_translateKey['0'] = Key::Key0;
  105. s_translateKey['1'] = Key::Key1;
  106. s_translateKey['2'] = Key::Key2;
  107. s_translateKey['3'] = Key::Key3;
  108. s_translateKey['4'] = Key::Key4;
  109. s_translateKey['5'] = Key::Key5;
  110. s_translateKey['6'] = Key::Key6;
  111. s_translateKey['7'] = Key::Key7;
  112. s_translateKey['8'] = Key::Key8;
  113. s_translateKey['9'] = Key::Key9;
  114. s_translateKey['A'] = Key::KeyA;
  115. s_translateKey['B'] = Key::KeyB;
  116. s_translateKey['C'] = Key::KeyC;
  117. s_translateKey['D'] = Key::KeyD;
  118. s_translateKey['E'] = Key::KeyE;
  119. s_translateKey['F'] = Key::KeyF;
  120. s_translateKey['G'] = Key::KeyG;
  121. s_translateKey['H'] = Key::KeyH;
  122. s_translateKey['I'] = Key::KeyI;
  123. s_translateKey['J'] = Key::KeyJ;
  124. s_translateKey['K'] = Key::KeyK;
  125. s_translateKey['L'] = Key::KeyL;
  126. s_translateKey['M'] = Key::KeyM;
  127. s_translateKey['N'] = Key::KeyN;
  128. s_translateKey['O'] = Key::KeyO;
  129. s_translateKey['P'] = Key::KeyP;
  130. s_translateKey['Q'] = Key::KeyQ;
  131. s_translateKey['R'] = Key::KeyR;
  132. s_translateKey['S'] = Key::KeyS;
  133. s_translateKey['T'] = Key::KeyT;
  134. s_translateKey['U'] = Key::KeyU;
  135. s_translateKey['V'] = Key::KeyV;
  136. s_translateKey['W'] = Key::KeyW;
  137. s_translateKey['X'] = Key::KeyX;
  138. s_translateKey['Y'] = Key::KeyY;
  139. s_translateKey['Z'] = Key::KeyZ;
  140. }
  141. int32_t run(int _argc, char** _argv)
  142. {
  143. SetDllDirectory(".");
  144. HINSTANCE instance = (HINSTANCE)GetModuleHandle(NULL);
  145. WNDCLASSEX wnd;
  146. memset(&wnd, 0, sizeof(wnd) );
  147. wnd.cbSize = sizeof(wnd);
  148. wnd.style = CS_HREDRAW | CS_VREDRAW;
  149. wnd.lpfnWndProc = wndProc;
  150. wnd.hInstance = instance;
  151. wnd.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  152. wnd.hCursor = LoadCursor(NULL, IDC_ARROW);
  153. wnd.lpszClassName = "bgfx";
  154. wnd.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
  155. RegisterClassExA(&wnd);
  156. m_windowAlloc.alloc();
  157. m_hwnd[0] = CreateWindowA("bgfx"
  158. , "BGFX"
  159. , WS_OVERLAPPEDWINDOW|WS_VISIBLE
  160. , 0
  161. , 0
  162. , ENTRY_DEFAULT_WIDTH
  163. , ENTRY_DEFAULT_HEIGHT
  164. , NULL
  165. , NULL
  166. , instance
  167. , 0
  168. );
  169. bgfx::winSetHwnd(m_hwnd[0]);
  170. adjust(m_hwnd[0], ENTRY_DEFAULT_WIDTH, ENTRY_DEFAULT_HEIGHT, true);
  171. m_width = ENTRY_DEFAULT_WIDTH;
  172. m_height = ENTRY_DEFAULT_HEIGHT;
  173. m_oldWidth = ENTRY_DEFAULT_WIDTH;
  174. m_oldHeight = ENTRY_DEFAULT_HEIGHT;
  175. MainThreadEntry mte;
  176. mte.m_argc = _argc;
  177. mte.m_argv = _argv;
  178. bx::Thread thread;
  179. thread.init(mte.threadFunc, &mte);
  180. m_init = true;
  181. m_eventQueue.postSizeEvent(findHandle(m_hwnd[0]), m_width, m_height);
  182. MSG msg;
  183. msg.message = WM_NULL;
  184. while (!m_exit)
  185. {
  186. WaitMessage();
  187. while (0 != PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE) )
  188. {
  189. TranslateMessage(&msg);
  190. DispatchMessage(&msg);
  191. }
  192. }
  193. thread.shutdown();
  194. DestroyWindow(m_hwnd[0]);
  195. return 0;
  196. }
  197. LRESULT process(HWND _hwnd, UINT _id, WPARAM _wparam, LPARAM _lparam)
  198. {
  199. if (m_init)
  200. {
  201. switch (_id)
  202. {
  203. case WM_USER_CREATE_WINDOW:
  204. {
  205. uint32_t width = GET_X_LPARAM(_lparam);
  206. uint32_t height = GET_Y_LPARAM(_lparam);
  207. HWND hwnd = CreateWindowA("bgfx"
  208. , ""
  209. , WS_OVERLAPPEDWINDOW|WS_VISIBLE
  210. , 0
  211. , 0
  212. , width
  213. , height
  214. , NULL
  215. , NULL
  216. , (HINSTANCE)GetModuleHandle(NULL)
  217. , 0
  218. );
  219. m_hwnd[_wparam] = hwnd;
  220. WindowHandle handle = { (uint16_t)_wparam };
  221. m_eventQueue.postWindowEvent(handle, hwnd);
  222. }
  223. break;
  224. case WM_USER_SET_WINDOW_SIZE:
  225. {
  226. uint32_t width = GET_X_LPARAM(_lparam);
  227. uint32_t height = GET_Y_LPARAM(_lparam);
  228. adjust(m_hwnd[_wparam], width, height, true);
  229. }
  230. break;
  231. case WM_USER_TOGGLE_WINDOW_FRAME:
  232. {
  233. if (m_frame)
  234. {
  235. m_oldWidth = m_width;
  236. m_oldHeight = m_height;
  237. }
  238. adjust(m_hwnd[_wparam], m_oldWidth, m_oldHeight, !m_frame);
  239. }
  240. break;
  241. case WM_USER_MOUSE_LOCK:
  242. setMouseLock(_hwnd, !!_lparam);
  243. break;
  244. case WM_DESTROY:
  245. break;
  246. case WM_QUIT:
  247. case WM_CLOSE:
  248. m_eventQueue.postWindowEvent(findHandle(_hwnd) );
  249. if (_hwnd == m_hwnd[0])
  250. {
  251. m_exit = true;
  252. m_eventQueue.postExitEvent();
  253. }
  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(findHandle(_hwnd), 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(findHandle(_hwnd), 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 (_hwnd == m_mouseLock)
  324. {
  325. mx -= m_mx;
  326. my -= m_my;
  327. if (0 == mx
  328. && 0 == my)
  329. {
  330. break;
  331. }
  332. setMousePos(_hwnd, m_mx, m_my);
  333. }
  334. m_eventQueue.postMouseEvent(findHandle(_hwnd), 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(_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(findHandle(_hwnd), 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(findHandle(_hwnd), 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(findHandle(_hwnd), 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(findHandle(_hwnd), 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. WindowHandle handle = findHandle(_hwnd);
  382. if (Key::Print == key
  383. && 0x3 == ( (uint32_t)(_lparam)>>30) )
  384. {
  385. // VK_SNAPSHOT doesn't generate keydown event. Fire on down event when previous
  386. // key state bit is set to 1 and transition state bit is set to 1.
  387. //
  388. // http://msdn.microsoft.com/en-us/library/windows/desktop/ms646280%28v=vs.85%29.aspx
  389. m_eventQueue.postKeyEvent(handle, key, modifiers, true);
  390. }
  391. m_eventQueue.postKeyEvent(handle, key, modifiers, _id == WM_KEYDOWN || _id == WM_SYSKEYDOWN);
  392. }
  393. break;
  394. default:
  395. break;
  396. }
  397. }
  398. return DefWindowProc(_hwnd, _id, _wparam, _lparam);
  399. }
  400. WindowHandle findHandle(HWND _hwnd)
  401. {
  402. bx::LwMutexScope scope(m_lock);
  403. for (uint32_t ii = 0, num = m_windowAlloc.getNumHandles(); ii < num; ++ii)
  404. {
  405. uint16_t idx = m_windowAlloc.getHandleAt(ii);
  406. if (_hwnd == m_hwnd[idx])
  407. {
  408. WindowHandle handle = { idx };
  409. return handle;
  410. }
  411. }
  412. WindowHandle invalid = { UINT16_MAX };
  413. return invalid;
  414. }
  415. void adjust(HWND _hwnd, uint32_t _width, uint32_t _height, bool _windowFrame)
  416. {
  417. m_width = _width;
  418. m_height = _height;
  419. m_aspectRatio = float(_width)/float(_height);
  420. ShowWindow(_hwnd, SW_SHOWNORMAL);
  421. RECT rect;
  422. RECT newrect = {0, 0, (LONG)_width, (LONG)_height};
  423. DWORD style = WS_POPUP|WS_SYSMENU;
  424. if (m_frame)
  425. {
  426. GetWindowRect(_hwnd, &m_rect);
  427. m_style = GetWindowLong(_hwnd, GWL_STYLE);
  428. }
  429. if (_windowFrame)
  430. {
  431. rect = m_rect;
  432. style = m_style;
  433. }
  434. else
  435. {
  436. #if defined(__MINGW32__)
  437. rect = m_rect;
  438. style = m_style;
  439. #else
  440. HMONITOR monitor = MonitorFromWindow(_hwnd, MONITOR_DEFAULTTONEAREST);
  441. MONITORINFO mi;
  442. mi.cbSize = sizeof(mi);
  443. GetMonitorInfo(monitor, &mi);
  444. newrect = mi.rcMonitor;
  445. rect = mi.rcMonitor;
  446. #endif // !defined(__MINGW__)
  447. }
  448. SetWindowLong(_hwnd, GWL_STYLE, style);
  449. uint32_t prewidth = newrect.right - newrect.left;
  450. uint32_t preheight = newrect.bottom - newrect.top;
  451. AdjustWindowRect(&newrect, style, FALSE);
  452. m_frameWidth = (newrect.right - newrect.left) - prewidth;
  453. m_frameHeight = (newrect.bottom - newrect.top) - preheight;
  454. UpdateWindow(_hwnd);
  455. if (rect.left == -32000
  456. || rect.top == -32000)
  457. {
  458. rect.left = 0;
  459. rect.top = 0;
  460. }
  461. int32_t left = rect.left;
  462. int32_t top = rect.top;
  463. int32_t width = (newrect.right-newrect.left);
  464. int32_t height = (newrect.bottom-newrect.top);
  465. if (!_windowFrame)
  466. {
  467. float aspectRatio = 1.0f/m_aspectRatio;
  468. width = bx::uint32_max(ENTRY_DEFAULT_WIDTH/4, width);
  469. height = uint32_t(float(width)*aspectRatio);
  470. left = newrect.left+(newrect.right-newrect.left-width)/2;
  471. top = newrect.top+(newrect.bottom-newrect.top-height)/2;
  472. }
  473. HWND parent = GetWindow(_hwnd, GW_OWNER);
  474. if (NULL != parent)
  475. {
  476. if (_windowFrame)
  477. {
  478. SetWindowPos(parent
  479. , HWND_TOP
  480. , -32000
  481. , -32000
  482. , 0
  483. , 0
  484. , SWP_SHOWWINDOW
  485. );
  486. }
  487. else
  488. {
  489. SetWindowPos(parent
  490. , HWND_TOP
  491. , newrect.left
  492. , newrect.top
  493. , newrect.right-newrect.left
  494. , newrect.bottom-newrect.top
  495. , SWP_SHOWWINDOW
  496. );
  497. }
  498. }
  499. SetWindowPos(_hwnd
  500. , HWND_TOP
  501. , left
  502. , top
  503. , width
  504. , height
  505. , SWP_SHOWWINDOW
  506. );
  507. ShowWindow(_hwnd, SW_RESTORE);
  508. m_frame = _windowFrame;
  509. }
  510. void setMousePos(HWND _hwnd, int32_t _mx, int32_t _my)
  511. {
  512. POINT pt = { _mx, _my };
  513. ClientToScreen(_hwnd, &pt);
  514. SetCursorPos(pt.x, pt.y);
  515. }
  516. void setMouseLock(HWND _hwnd, bool _lock)
  517. {
  518. if (_hwnd != m_mouseLock)
  519. {
  520. if (_lock)
  521. {
  522. m_mx = m_width/2;
  523. m_my = m_height/2;
  524. ShowCursor(false);
  525. setMousePos(_hwnd, m_mx, m_my);
  526. }
  527. else
  528. {
  529. setMousePos(_hwnd, m_mx, m_my);
  530. ShowCursor(true);
  531. }
  532. m_mouseLock = _hwnd;
  533. }
  534. }
  535. static LRESULT CALLBACK wndProc(HWND _hwnd, UINT _id, WPARAM _wparam, LPARAM _lparam);
  536. EventQueue m_eventQueue;
  537. bx::LwMutex m_lock;
  538. bx::HandleAllocT<ENTRY_CONFIG_MAX_WINDOWS> m_windowAlloc;
  539. HWND m_hwnd[ENTRY_CONFIG_MAX_WINDOWS];
  540. RECT m_rect;
  541. DWORD m_style;
  542. uint32_t m_width;
  543. uint32_t m_height;
  544. uint32_t m_oldWidth;
  545. uint32_t m_oldHeight;
  546. uint32_t m_frameWidth;
  547. uint32_t m_frameHeight;
  548. float m_aspectRatio;
  549. int32_t m_mx;
  550. int32_t m_my;
  551. int32_t m_mz;
  552. bool m_frame;
  553. HWND m_mouseLock;
  554. bool m_init;
  555. bool m_exit;
  556. };
  557. static Context s_ctx;
  558. LRESULT CALLBACK Context::wndProc(HWND _hwnd, UINT _id, WPARAM _wparam, LPARAM _lparam)
  559. {
  560. return s_ctx.process(_hwnd, _id, _wparam, _lparam);
  561. }
  562. const Event* poll()
  563. {
  564. return s_ctx.m_eventQueue.poll();
  565. }
  566. void release(const Event* _event)
  567. {
  568. s_ctx.m_eventQueue.release(_event);
  569. }
  570. WindowHandle createWindow(uint32_t _width, uint32_t _height, const char* /*_title*/)
  571. {
  572. bx::LwMutexScope scope(s_ctx.m_lock);
  573. WindowHandle handle = { s_ctx.m_windowAlloc.alloc() };
  574. if (UINT16_MAX != handle.idx)
  575. {
  576. PostMessage(s_ctx.m_hwnd[0], WM_USER_CREATE_WINDOW, handle.idx, (_height<<16) | (_width&0xffff) );
  577. }
  578. return handle;
  579. }
  580. void destroyWindow(WindowHandle _handle)
  581. {
  582. PostMessage(s_ctx.m_hwnd[_handle.idx], WM_CLOSE, _handle.idx, 0);
  583. }
  584. void setWindowSize(WindowHandle _handle, uint32_t _width, uint32_t _height)
  585. {
  586. PostMessage(s_ctx.m_hwnd[_handle.idx], WM_USER_SET_WINDOW_SIZE, _handle.idx, (_height<<16) | (_width&0xffff) );
  587. }
  588. void setWindowTitle(WindowHandle _handle, const char* _title)
  589. {
  590. SetWindowTextA(s_ctx.m_hwnd[_handle.idx], _title);
  591. // SetWindowTextA(GetWindow(s_ctx.m_hwnd[_handle.idx], GW_HWNDNEXT), _title);
  592. }
  593. void toggleWindowFrame(WindowHandle _handle)
  594. {
  595. PostMessage(s_ctx.m_hwnd[_handle.idx], WM_USER_TOGGLE_WINDOW_FRAME, _handle.idx, 0);
  596. }
  597. void setMouseLock(WindowHandle _handle, bool _lock)
  598. {
  599. PostMessage(s_ctx.m_hwnd[_handle.idx], WM_USER_MOUSE_LOCK, _handle.idx, _lock);
  600. }
  601. int32_t MainThreadEntry::threadFunc(void* _userData)
  602. {
  603. MainThreadEntry* self = (MainThreadEntry*)_userData;
  604. int32_t result = main(self->m_argc, self->m_argv);
  605. PostMessage(s_ctx.m_hwnd[0], WM_QUIT, 0, 0);
  606. return result;
  607. }
  608. } // namespace entry
  609. int main(int _argc, char** _argv)
  610. {
  611. using namespace entry;
  612. return s_ctx.run(_argc, _argv);
  613. }
  614. #endif // BX_PLATFORM_WINDOWS