os_windows.cpp 63 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630
  1. /*************************************************************************/
  2. /* os_windows.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
  9. /* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /*************************************************************************/
  30. #include "drivers/gles2/rasterizer_gles2.h"
  31. #include "drivers/unix/memory_pool_static_malloc.h"
  32. #include "drivers/windows/dir_access_windows.h"
  33. #include "drivers/windows/file_access_windows.h"
  34. #include "drivers/windows/mutex_windows.h"
  35. #include "drivers/windows/semaphore_windows.h"
  36. #include "drivers/windows/thread_windows.h"
  37. #include "main/main.h"
  38. #include "os/memory_pool_dynamic_static.h"
  39. #include "os_windows.h"
  40. #include "scene/resources/texture.h"
  41. #include "servers/audio/audio_server_sw.h"
  42. #include "servers/visual/visual_server_raster.h"
  43. #include "servers/visual/visual_server_wrap_mt.h"
  44. #include "globals.h"
  45. #include "io/marshalls.h"
  46. #include "joystick.h"
  47. #include "lang_table.h"
  48. #include "os/memory_pool_dynamic_prealloc.h"
  49. #include "packet_peer_udp_winsock.h"
  50. #include "stream_peer_winsock.h"
  51. #include "tcp_server_winsock.h"
  52. #include "shlobj.h"
  53. #include <process.h>
  54. #include <regstr.h>
  55. static const WORD MAX_CONSOLE_LINES = 1500;
  56. extern "C" {
  57. #ifdef _MSC_VER
  58. _declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
  59. #else
  60. __attribute__((visibility("default"))) DWORD NvOptimusEnablement = 0x00000001;
  61. #endif
  62. }
  63. // Workaround mingw-w64 < 4.0 bug
  64. #ifndef WM_TOUCH
  65. #define WM_TOUCH 576
  66. #endif
  67. extern HINSTANCE godot_hinstance;
  68. void RedirectIOToConsole() {
  69. int hConHandle;
  70. intptr_t lStdHandle;
  71. CONSOLE_SCREEN_BUFFER_INFO coninfo;
  72. FILE *fp;
  73. // allocate a console for this app
  74. AllocConsole();
  75. // set the screen buffer to be big enough to let us scroll text
  76. GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE),
  77. &coninfo);
  78. coninfo.dwSize.Y = MAX_CONSOLE_LINES;
  79. SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE),
  80. coninfo.dwSize);
  81. // redirect unbuffered STDOUT to the console
  82. lStdHandle = (intptr_t)GetStdHandle(STD_OUTPUT_HANDLE);
  83. hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
  84. fp = _fdopen(hConHandle, "w");
  85. *stdout = *fp;
  86. setvbuf(stdout, NULL, _IONBF, 0);
  87. // redirect unbuffered STDIN to the console
  88. lStdHandle = (intptr_t)GetStdHandle(STD_INPUT_HANDLE);
  89. hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
  90. fp = _fdopen(hConHandle, "r");
  91. *stdin = *fp;
  92. setvbuf(stdin, NULL, _IONBF, 0);
  93. // redirect unbuffered STDERR to the console
  94. lStdHandle = (intptr_t)GetStdHandle(STD_ERROR_HANDLE);
  95. hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
  96. fp = _fdopen(hConHandle, "w");
  97. *stderr = *fp;
  98. setvbuf(stderr, NULL, _IONBF, 0);
  99. // make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog
  100. // point to console as well
  101. }
  102. int OS_Windows::get_video_driver_count() const {
  103. return 1;
  104. }
  105. const char *OS_Windows::get_video_driver_name(int p_driver) const {
  106. return "GLES2";
  107. }
  108. OS::VideoMode OS_Windows::get_default_video_mode() const {
  109. return VideoMode(1024, 600, false);
  110. }
  111. int OS_Windows::get_audio_driver_count() const {
  112. return AudioDriverManagerSW::get_driver_count();
  113. }
  114. const char *OS_Windows::get_audio_driver_name(int p_driver) const {
  115. AudioDriverSW *driver = AudioDriverManagerSW::get_driver(p_driver);
  116. ERR_FAIL_COND_V(!driver, "");
  117. return AudioDriverManagerSW::get_driver(p_driver)->get_name();
  118. }
  119. static MemoryPoolStatic *mempool_static = NULL;
  120. static MemoryPoolDynamic *mempool_dynamic = NULL;
  121. void OS_Windows::initialize_core() {
  122. crash_handler.initialize();
  123. last_button_state = 0;
  124. //RedirectIOToConsole();
  125. maximized = false;
  126. minimized = false;
  127. borderless = false;
  128. ThreadWindows::make_default();
  129. SemaphoreWindows::make_default();
  130. MutexWindows::make_default();
  131. FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_RESOURCES);
  132. FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_USERDATA);
  133. FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_FILESYSTEM);
  134. //FileAccessBufferedFA<FileAccessWindows>::make_default();
  135. DirAccess::make_default<DirAccessWindows>(DirAccess::ACCESS_RESOURCES);
  136. DirAccess::make_default<DirAccessWindows>(DirAccess::ACCESS_USERDATA);
  137. DirAccess::make_default<DirAccessWindows>(DirAccess::ACCESS_FILESYSTEM);
  138. TCPServerWinsock::make_default();
  139. StreamPeerWinsock::make_default();
  140. PacketPeerUDPWinsock::make_default();
  141. mempool_static = new MemoryPoolStaticMalloc;
  142. #if 1
  143. mempool_dynamic = memnew(MemoryPoolDynamicStatic);
  144. #else
  145. #define DYNPOOL_SIZE 4 * 1024 * 1024
  146. void *buffer = malloc(DYNPOOL_SIZE);
  147. mempool_dynamic = memnew(MemoryPoolDynamicPrealloc(buffer, DYNPOOL_SIZE));
  148. #endif
  149. // We need to know how often the clock is updated
  150. if (!QueryPerformanceFrequency((LARGE_INTEGER *)&ticks_per_second))
  151. ticks_per_second = 1000;
  152. // If timeAtGameStart is 0 then we get the time since
  153. // the start of the computer when we call GetGameTime()
  154. ticks_start = 0;
  155. ticks_start = get_ticks_usec();
  156. process_map = memnew((Map<ProcessID, ProcessInfo>));
  157. IP_Unix::make_default();
  158. cursor_shape = CURSOR_ARROW;
  159. }
  160. bool OS_Windows::can_draw() const {
  161. return !minimized;
  162. };
  163. #define MI_WP_SIGNATURE 0xFF515700
  164. #define SIGNATURE_MASK 0xFFFFFF00
  165. #define IsPenEvent(dw) (((dw)&SIGNATURE_MASK) == MI_WP_SIGNATURE)
  166. void OS_Windows::_touch_event(bool p_pressed, int p_x, int p_y, int idx) {
  167. #if WINVER >= 0x0601 // for windows 7
  168. // Defensive
  169. if (touch_state.has(idx) == p_pressed)
  170. return;
  171. if (p_pressed) {
  172. touch_state.insert(idx, Point2i(p_x, p_y));
  173. } else {
  174. touch_state.erase(idx);
  175. }
  176. #endif
  177. InputEvent event;
  178. event.type = InputEvent::SCREEN_TOUCH;
  179. event.ID = ++last_id;
  180. event.screen_touch.index = idx;
  181. event.screen_touch.pressed = p_pressed;
  182. event.screen_touch.x = p_x;
  183. event.screen_touch.y = p_y;
  184. if (main_loop) {
  185. input->parse_input_event(event);
  186. }
  187. };
  188. void OS_Windows::_drag_event(int p_x, int p_y, int idx) {
  189. #if WINVER >= 0x0601 // for windows 7
  190. Map<int, Point2i>::Element *curr = touch_state.find(idx);
  191. // Defensive
  192. if (!curr)
  193. return;
  194. if (curr->get() == Point2i(p_x, p_y))
  195. return;
  196. curr->get() = Point2i(p_x, p_y);
  197. #endif
  198. InputEvent event;
  199. event.type = InputEvent::SCREEN_DRAG;
  200. event.ID = ++last_id;
  201. event.screen_drag.index = idx;
  202. event.screen_drag.x = p_x;
  203. event.screen_drag.y = p_y;
  204. if (main_loop)
  205. input->parse_input_event(event);
  206. };
  207. LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  208. switch (uMsg) // Check For Windows Messages
  209. {
  210. case WM_ACTIVATE: // Watch For Window Activate Message
  211. {
  212. minimized = HIWORD(wParam) != 0;
  213. if (!main_loop) {
  214. return 0;
  215. };
  216. if (LOWORD(wParam) == WA_ACTIVE || LOWORD(wParam) == WA_CLICKACTIVE) {
  217. main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_IN);
  218. alt_mem = false;
  219. control_mem = false;
  220. shift_mem = false;
  221. if (mouse_mode == MOUSE_MODE_CAPTURED) {
  222. RECT clipRect;
  223. GetClientRect(hWnd, &clipRect);
  224. ClientToScreen(hWnd, (POINT *)&clipRect.left);
  225. ClientToScreen(hWnd, (POINT *)&clipRect.right);
  226. ClipCursor(&clipRect);
  227. SetCapture(hWnd);
  228. }
  229. } else {
  230. main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT);
  231. alt_mem = false;
  232. };
  233. return 0; // Return To The Message Loop
  234. }
  235. case WM_KILLFOCUS: {
  236. #if WINVER >= 0x0601 // for windows 7
  237. // Release every touch to avoid sticky points
  238. for (Map<int, Point2i>::Element *E = touch_state.front(); E; E = E->next()) {
  239. _touch_event(false, E->get().x, E->get().y, E->key());
  240. }
  241. touch_state.clear();
  242. #endif
  243. } break;
  244. case WM_PAINT:
  245. Main::force_redraw();
  246. break;
  247. case WM_SYSCOMMAND: // Intercept System Commands
  248. {
  249. switch (wParam) // Check System Calls
  250. {
  251. case SC_SCREENSAVE: // Screensaver Trying To Start?
  252. case SC_MONITORPOWER: // Monitor Trying To Enter Powersave?
  253. return 0; // Prevent From Happening
  254. case SC_KEYMENU:
  255. if ((lParam >> 16) <= 0)
  256. return 0;
  257. }
  258. break; // Exit
  259. }
  260. case WM_CLOSE: // Did We Receive A Close Message?
  261. {
  262. if (main_loop)
  263. main_loop->notification(MainLoop::NOTIFICATION_WM_QUIT_REQUEST);
  264. //force_quit=true;
  265. return 0; // Jump Back
  266. }
  267. case WM_MOUSELEAVE: {
  268. old_invalid = true;
  269. outside = true;
  270. if (main_loop && mouse_mode != MOUSE_MODE_CAPTURED)
  271. main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_EXIT);
  272. } break;
  273. case WM_MOUSEMOVE: {
  274. if (outside) {
  275. //mouse enter
  276. if (main_loop && mouse_mode != MOUSE_MODE_CAPTURED)
  277. main_loop->notification(MainLoop::NOTIFICATION_WM_MOUSE_ENTER);
  278. CursorShape c = cursor_shape;
  279. cursor_shape = CURSOR_MAX;
  280. set_cursor_shape(c);
  281. outside = false;
  282. //Once-Off notification, must call again....
  283. TRACKMOUSEEVENT tme;
  284. tme.cbSize = sizeof(TRACKMOUSEEVENT);
  285. tme.dwFlags = TME_LEAVE;
  286. tme.hwndTrack = hWnd;
  287. tme.dwHoverTime = HOVER_DEFAULT;
  288. TrackMouseEvent(&tme);
  289. }
  290. /*
  291. LPARAM extra = GetMessageExtraInfo();
  292. if (IsPenEvent(extra)) {
  293. int idx = extra & 0x7f;
  294. _drag_event(idx, uMsg, wParam, lParam);
  295. if (idx != 0) {
  296. return 0;
  297. };
  298. // fallthrough for mouse event
  299. };
  300. */
  301. InputEvent event;
  302. event.type = InputEvent::MOUSE_MOTION;
  303. event.ID = ++last_id;
  304. InputEventMouseMotion &mm = event.mouse_motion;
  305. mm.mod.control = (wParam & MK_CONTROL) != 0;
  306. mm.mod.shift = (wParam & MK_SHIFT) != 0;
  307. mm.mod.alt = alt_mem;
  308. mm.button_mask |= (wParam & MK_LBUTTON) ? (1 << 0) : 0;
  309. mm.button_mask |= (wParam & MK_RBUTTON) ? (1 << 1) : 0;
  310. mm.button_mask |= (wParam & MK_MBUTTON) ? (1 << 2) : 0;
  311. last_button_state = mm.button_mask;
  312. /*mm.button_mask|=(wParam&MK_XBUTTON1)?(1<<5):0;
  313. mm.button_mask|=(wParam&MK_XBUTTON2)?(1<<6):0;*/
  314. mm.x = GET_X_LPARAM(lParam);
  315. mm.y = GET_Y_LPARAM(lParam);
  316. if (mouse_mode == MOUSE_MODE_CAPTURED) {
  317. Point2i c(video_mode.width / 2, video_mode.height / 2);
  318. old_x = c.x;
  319. old_y = c.y;
  320. if (Point2i(mm.x, mm.y) == c) {
  321. center = c;
  322. return 0;
  323. }
  324. Point2i ncenter(mm.x, mm.y);
  325. center = ncenter;
  326. POINT pos = { (int)c.x, (int)c.y };
  327. ClientToScreen(hWnd, &pos);
  328. SetCursorPos(pos.x, pos.y);
  329. }
  330. input->set_mouse_pos(Point2(mm.x, mm.y));
  331. mm.global_x = mm.x;
  332. mm.global_y = mm.y;
  333. mm.speed_x = input->get_mouse_speed().x;
  334. mm.speed_y = input->get_mouse_speed().y;
  335. if (old_invalid) {
  336. old_x = mm.x;
  337. old_y = mm.y;
  338. old_invalid = false;
  339. }
  340. mm.relative_x = mm.x - old_x;
  341. mm.relative_y = mm.y - old_y;
  342. old_x = mm.x;
  343. old_y = mm.y;
  344. if (main_loop)
  345. input->parse_input_event(event);
  346. } break;
  347. case WM_LBUTTONDOWN:
  348. case WM_LBUTTONUP:
  349. case WM_MBUTTONDOWN:
  350. case WM_MBUTTONUP:
  351. case WM_RBUTTONDOWN:
  352. case WM_RBUTTONUP:
  353. case WM_MOUSEWHEEL:
  354. case WM_MOUSEHWHEEL:
  355. case WM_LBUTTONDBLCLK:
  356. case WM_MBUTTONDBLCLK:
  357. case WM_RBUTTONDBLCLK:
  358. /*case WM_XBUTTONDOWN:
  359. case WM_XBUTTONUP: */
  360. {
  361. /*
  362. LPARAM extra = GetMessageExtraInfo();
  363. if (IsPenEvent(extra)) {
  364. int idx = extra & 0x7f;
  365. _touch_event(idx, uMsg, wParam, lParam);
  366. if (idx != 0) {
  367. return 0;
  368. };
  369. // fallthrough for mouse event
  370. };
  371. */
  372. InputEvent event;
  373. event.type = InputEvent::MOUSE_BUTTON;
  374. event.ID = ++last_id;
  375. InputEventMouseButton &mb = event.mouse_button;
  376. switch (uMsg) {
  377. case WM_LBUTTONDOWN: {
  378. mb.pressed = true;
  379. mb.button_index = 1;
  380. } break;
  381. case WM_LBUTTONUP: {
  382. mb.pressed = false;
  383. mb.button_index = 1;
  384. } break;
  385. case WM_MBUTTONDOWN: {
  386. mb.pressed = true;
  387. mb.button_index = 3;
  388. } break;
  389. case WM_MBUTTONUP: {
  390. mb.pressed = false;
  391. mb.button_index = 3;
  392. } break;
  393. case WM_RBUTTONDOWN: {
  394. mb.pressed = true;
  395. mb.button_index = 2;
  396. } break;
  397. case WM_RBUTTONUP: {
  398. mb.pressed = false;
  399. mb.button_index = 2;
  400. } break;
  401. case WM_LBUTTONDBLCLK: {
  402. mb.pressed = true;
  403. mb.button_index = 1;
  404. mb.doubleclick = true;
  405. } break;
  406. case WM_RBUTTONDBLCLK: {
  407. mb.pressed = true;
  408. mb.button_index = 2;
  409. mb.doubleclick = true;
  410. } break;
  411. case WM_MBUTTONDBLCLK: {
  412. mb.pressed = true;
  413. mb.button_index = 3;
  414. mb.doubleclick = true;
  415. } break;
  416. case WM_MOUSEWHEEL: {
  417. mb.pressed = true;
  418. int motion = (short)HIWORD(wParam);
  419. if (!motion)
  420. return 0;
  421. if (motion > 0)
  422. mb.button_index = BUTTON_WHEEL_UP;
  423. else
  424. mb.button_index = BUTTON_WHEEL_DOWN;
  425. } break;
  426. case WM_MOUSEHWHEEL: {
  427. mb.pressed = true;
  428. int motion = (short)HIWORD(wParam);
  429. if (!motion)
  430. return 0;
  431. if (motion < 0) {
  432. mb.button_index = BUTTON_WHEEL_LEFT;
  433. mb.factor = fabs((double)motion / (double)WHEEL_DELTA);
  434. } else {
  435. mb.button_index = BUTTON_WHEEL_RIGHT;
  436. mb.factor = fabs((double)motion / (double)WHEEL_DELTA);
  437. }
  438. } break;
  439. /*
  440. case WM_XBUTTONDOWN: {
  441. mb.pressed=true;
  442. mb.button_index=(HIWORD(wParam)==XBUTTON1)?6:7;
  443. } break;
  444. case WM_XBUTTONUP:
  445. mb.pressed=true;
  446. mb.button_index=(HIWORD(wParam)==XBUTTON1)?6:7;
  447. } break;*/
  448. default: { return 0; }
  449. }
  450. mb.mod.control = (wParam & MK_CONTROL) != 0;
  451. mb.mod.shift = (wParam & MK_SHIFT) != 0;
  452. mb.mod.alt = alt_mem;
  453. //mb.mod.alt=(wParam&MK_MENU)!=0;
  454. mb.button_mask |= (wParam & MK_LBUTTON) ? (1 << 0) : 0;
  455. mb.button_mask |= (wParam & MK_RBUTTON) ? (1 << 1) : 0;
  456. mb.button_mask |= (wParam & MK_MBUTTON) ? (1 << 2) : 0;
  457. last_button_state = mb.button_mask;
  458. /*
  459. mb.button_mask|=(wParam&MK_XBUTTON1)?(1<<5):0;
  460. mb.button_mask|=(wParam&MK_XBUTTON2)?(1<<6):0;*/
  461. mb.x = GET_X_LPARAM(lParam);
  462. mb.y = GET_Y_LPARAM(lParam);
  463. if (mouse_mode == MOUSE_MODE_CAPTURED) {
  464. mb.x = old_x;
  465. mb.y = old_y;
  466. }
  467. if (uMsg != WM_MOUSEWHEEL && uMsg != WM_MOUSEHWHEEL) {
  468. if (mb.pressed) {
  469. if (++pressrc > 0)
  470. SetCapture(hWnd);
  471. } else {
  472. if (--pressrc <= 0) {
  473. ReleaseCapture();
  474. pressrc = 0;
  475. }
  476. }
  477. } else if (mouse_mode != MOUSE_MODE_CAPTURED) {
  478. // for reasons unknown to mankind, wheel comes in screen cordinates
  479. POINT coords;
  480. coords.x = mb.x;
  481. coords.y = mb.y;
  482. ScreenToClient(hWnd, &coords);
  483. mb.x = coords.x;
  484. mb.y = coords.y;
  485. }
  486. mb.global_x = mb.x;
  487. mb.global_y = mb.y;
  488. if (main_loop) {
  489. input->parse_input_event(event);
  490. if (mb.pressed && mb.button_index > 3) {
  491. //send release for mouse wheel
  492. mb.pressed = false;
  493. event.ID = ++last_id;
  494. input->parse_input_event(event);
  495. }
  496. }
  497. }
  498. break;
  499. case WM_SIZE: {
  500. int window_w = LOWORD(lParam);
  501. int window_h = HIWORD(lParam);
  502. if (window_w > 0 && window_h > 0) {
  503. video_mode.width = window_w;
  504. video_mode.height = window_h;
  505. }
  506. //return 0; // Jump Back
  507. } break;
  508. case WM_ENTERSIZEMOVE: {
  509. move_timer_id = SetTimer(hWnd, 1, USER_TIMER_MINIMUM, (TIMERPROC)NULL);
  510. } break;
  511. case WM_EXITSIZEMOVE: {
  512. KillTimer(hWnd, move_timer_id);
  513. } break;
  514. case WM_TIMER: {
  515. if (wParam == move_timer_id) {
  516. process_key_events();
  517. Main::iteration();
  518. }
  519. } break;
  520. case WM_SYSKEYDOWN:
  521. case WM_SYSKEYUP:
  522. case WM_KEYUP:
  523. case WM_KEYDOWN: {
  524. if (wParam == VK_SHIFT)
  525. shift_mem = uMsg == WM_KEYDOWN;
  526. if (wParam == VK_CONTROL)
  527. control_mem = uMsg == WM_KEYDOWN;
  528. if (wParam == VK_MENU) {
  529. alt_mem = (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN);
  530. if (lParam & (1 << 24))
  531. gr_mem = alt_mem;
  532. }
  533. //if (wParam==VK_WIN) TODO wtf is this?
  534. // meta_mem=uMsg==WM_KEYDOWN;
  535. } //fallthrough
  536. case WM_CHAR: {
  537. ERR_BREAK(key_event_pos >= KEY_EVENT_BUFFER_SIZE);
  538. // Make sure we don't include modifiers for the modifier key itself.
  539. KeyEvent ke;
  540. ke.mod_state.shift = (wParam != VK_SHIFT) ? shift_mem : false;
  541. ke.mod_state.alt = (!(wParam == VK_MENU && (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN))) ? alt_mem : false;
  542. ke.mod_state.control = (wParam != VK_CONTROL) ? control_mem : false;
  543. ke.mod_state.meta = meta_mem;
  544. ke.uMsg = uMsg;
  545. if (ke.uMsg == WM_SYSKEYDOWN)
  546. ke.uMsg = WM_KEYDOWN;
  547. if (ke.uMsg == WM_SYSKEYUP)
  548. ke.uMsg = WM_KEYUP;
  549. /*if (ke.uMsg==WM_KEYDOWN && alt_mem && uMsg!=WM_SYSKEYDOWN) {
  550. //altgr hack for intl keyboards, not sure how good it is
  551. //windows is weeeeird
  552. ke.mod_state.alt=false;
  553. ke.mod_state.control=false;
  554. print_line("")
  555. }*/
  556. ke.wParam = wParam;
  557. ke.lParam = lParam;
  558. key_event_buffer[key_event_pos++] = ke;
  559. } break;
  560. case WM_INPUTLANGCHANGEREQUEST: {
  561. print_line("input lang change");
  562. } break;
  563. #if WINVER >= 0x0601 // for windows 7
  564. case WM_TOUCH: {
  565. BOOL bHandled = FALSE;
  566. UINT cInputs = LOWORD(wParam);
  567. PTOUCHINPUT pInputs = memnew_arr(TOUCHINPUT, cInputs);
  568. if (pInputs) {
  569. if (GetTouchInputInfo((HTOUCHINPUT)lParam, cInputs, pInputs, sizeof(TOUCHINPUT))) {
  570. for (UINT i = 0; i < cInputs; i++) {
  571. TOUCHINPUT ti = pInputs[i];
  572. //do something with each touch input entry
  573. if (ti.dwFlags & TOUCHEVENTF_MOVE) {
  574. _drag_event(ti.x / 100, ti.y / 100, ti.dwID);
  575. } else if (ti.dwFlags & (TOUCHEVENTF_UP | TOUCHEVENTF_DOWN)) {
  576. _touch_event(ti.dwFlags & TOUCHEVENTF_DOWN, ti.x / 100, ti.y / 100, ti.dwID);
  577. };
  578. }
  579. bHandled = TRUE;
  580. } else {
  581. /* handle the error here */
  582. }
  583. memdelete_arr(pInputs);
  584. } else {
  585. /* handle the error here, probably out of memory */
  586. }
  587. if (bHandled) {
  588. CloseTouchInputHandle((HTOUCHINPUT)lParam);
  589. return 0;
  590. };
  591. } break;
  592. #endif
  593. case WM_DEVICECHANGE: {
  594. joystick->probe_joysticks();
  595. } break;
  596. case WM_SETCURSOR: {
  597. if (LOWORD(lParam) == HTCLIENT) {
  598. if (mouse_mode == MOUSE_MODE_HIDDEN || mouse_mode == MOUSE_MODE_CAPTURED) {
  599. //Hide the cursor
  600. if (hCursor == NULL)
  601. hCursor = SetCursor(NULL);
  602. else
  603. SetCursor(NULL);
  604. } else {
  605. if (hCursor != NULL) {
  606. CursorShape c = cursor_shape;
  607. cursor_shape = CURSOR_MAX;
  608. set_cursor_shape(c);
  609. hCursor = NULL;
  610. }
  611. }
  612. }
  613. } break;
  614. case WM_DROPFILES: {
  615. HDROP hDropInfo = NULL;
  616. hDropInfo = (HDROP)wParam;
  617. const int buffsize = 4096;
  618. wchar_t buf[buffsize];
  619. int fcount = DragQueryFileW(hDropInfo, 0xFFFFFFFF, NULL, 0);
  620. Vector<String> files;
  621. for (int i = 0; i < fcount; i++) {
  622. DragQueryFileW(hDropInfo, i, buf, buffsize);
  623. String file = buf;
  624. files.push_back(file);
  625. }
  626. if (files.size() && main_loop) {
  627. main_loop->drop_files(files, 0);
  628. }
  629. } break;
  630. default: {
  631. if (user_proc) {
  632. return CallWindowProcW(user_proc, hWnd, uMsg, wParam, lParam);
  633. };
  634. };
  635. }
  636. return DefWindowProcW(hWnd, uMsg, wParam, lParam);
  637. }
  638. LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  639. OS_Windows *os_win = static_cast<OS_Windows *>(OS::get_singleton());
  640. if (os_win)
  641. return os_win->WndProc(hWnd, uMsg, wParam, lParam);
  642. else
  643. return DefWindowProcW(hWnd, uMsg, wParam, lParam);
  644. }
  645. void OS_Windows::process_key_events() {
  646. for (int i = 0; i < key_event_pos; i++) {
  647. KeyEvent &ke = key_event_buffer[i];
  648. switch (ke.uMsg) {
  649. case WM_CHAR: {
  650. if ((i == 0 && ke.uMsg == WM_CHAR) || (i > 0 && key_event_buffer[i - 1].uMsg == WM_CHAR)) {
  651. InputEvent event;
  652. event.type = InputEvent::KEY;
  653. event.ID = ++last_id;
  654. InputEventKey &k = event.key;
  655. k.mod = ke.mod_state;
  656. k.pressed = true;
  657. k.scancode = KeyMappingWindows::get_keysym(ke.wParam);
  658. k.unicode = ke.wParam;
  659. if (k.unicode && gr_mem) {
  660. k.mod.alt = false;
  661. k.mod.control = false;
  662. }
  663. if (k.unicode < 32)
  664. k.unicode = 0;
  665. input->parse_input_event(event);
  666. }
  667. //do nothing
  668. } break;
  669. case WM_KEYUP:
  670. case WM_KEYDOWN: {
  671. InputEvent event;
  672. event.type = InputEvent::KEY;
  673. event.ID = ++last_id;
  674. InputEventKey &k = event.key;
  675. k.mod = ke.mod_state;
  676. k.pressed = (ke.uMsg == WM_KEYDOWN);
  677. if ((ke.lParam & (1 << 24)) && (ke.wParam == VK_RETURN)) {
  678. // Special case for Numpad Enter key
  679. k.scancode = KEY_ENTER;
  680. } else {
  681. k.scancode = KeyMappingWindows::get_keysym(ke.wParam);
  682. }
  683. if (i + 1 < key_event_pos && key_event_buffer[i + 1].uMsg == WM_CHAR)
  684. k.unicode = key_event_buffer[i + 1].wParam;
  685. if (k.unicode && gr_mem) {
  686. k.mod.alt = false;
  687. k.mod.control = false;
  688. }
  689. if (k.unicode < 32)
  690. k.unicode = 0;
  691. k.echo = (ke.uMsg == WM_KEYDOWN && (ke.lParam & (1 << 30)));
  692. input->parse_input_event(event);
  693. } break;
  694. }
  695. }
  696. key_event_pos = 0;
  697. }
  698. enum _MonitorDpiType {
  699. MDT_Effective_DPI = 0,
  700. MDT_Angular_DPI = 1,
  701. MDT_Raw_DPI = 2,
  702. MDT_Default = MDT_Effective_DPI
  703. };
  704. static int QueryDpiForMonitor(HMONITOR hmon, _MonitorDpiType dpiType = MDT_Default) {
  705. int dpiX = 96, dpiY = 96;
  706. static HMODULE Shcore = NULL;
  707. typedef HRESULT(WINAPI * GetDPIForMonitor_t)(HMONITOR hmonitor, _MonitorDpiType dpiType, UINT * dpiX, UINT * dpiY);
  708. static GetDPIForMonitor_t getDPIForMonitor = NULL;
  709. if (Shcore == NULL) {
  710. Shcore = LoadLibraryW(L"Shcore.dll");
  711. getDPIForMonitor = Shcore ? (GetDPIForMonitor_t)GetProcAddress(Shcore, "GetDpiForMonitor") : NULL;
  712. if ((Shcore == NULL) || (getDPIForMonitor == NULL)) {
  713. if (Shcore)
  714. FreeLibrary(Shcore);
  715. Shcore = (HMODULE)INVALID_HANDLE_VALUE;
  716. }
  717. }
  718. UINT x = 0, y = 0;
  719. HRESULT hr = E_FAIL;
  720. bool bSet = false;
  721. if (hmon && (Shcore != (HMODULE)INVALID_HANDLE_VALUE)) {
  722. hr = getDPIForMonitor(hmon, dpiType /*MDT_Effective_DPI*/, &x, &y);
  723. if (SUCCEEDED(hr) && (x > 0) && (y > 0)) {
  724. dpiX = (int)x;
  725. dpiY = (int)y;
  726. }
  727. } else {
  728. static int overallX = 0, overallY = 0;
  729. if (overallX <= 0 || overallY <= 0) {
  730. HDC hdc = GetDC(NULL);
  731. if (hdc) {
  732. overallX = GetDeviceCaps(hdc, LOGPIXELSX);
  733. overallY = GetDeviceCaps(hdc, LOGPIXELSY);
  734. ReleaseDC(NULL, hdc);
  735. }
  736. }
  737. if (overallX > 0 && overallY > 0) {
  738. dpiX = overallX;
  739. dpiY = overallY;
  740. }
  741. }
  742. return (dpiX + dpiY) / 2;
  743. }
  744. typedef enum _SHC_PROCESS_DPI_AWARENESS {
  745. SHC_PROCESS_DPI_UNAWARE = 0,
  746. SHC_PROCESS_SYSTEM_DPI_AWARE = 1,
  747. SHC_PROCESS_PER_MONITOR_DPI_AWARE = 2
  748. } SHC_PROCESS_DPI_AWARENESS;
  749. void OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) {
  750. main_loop = NULL;
  751. outside = true;
  752. WNDCLASSEXW wc;
  753. if (is_hidpi_allowed()) {
  754. HMODULE Shcore = LoadLibraryW(L"Shcore.dll");;
  755. if (Shcore != NULL) {
  756. typedef HRESULT (WINAPI *SetProcessDpiAwareness_t)(SHC_PROCESS_DPI_AWARENESS);
  757. SetProcessDpiAwareness_t SetProcessDpiAwareness = (SetProcessDpiAwareness_t)GetProcAddress(Shcore, "SetProcessDpiAwareness");
  758. if (SetProcessDpiAwareness) {
  759. SetProcessDpiAwareness(SHC_PROCESS_SYSTEM_DPI_AWARE);
  760. }
  761. }
  762. }
  763. video_mode = p_desired;
  764. //printf("**************** desired %s, mode %s\n", p_desired.fullscreen?"true":"false", video_mode.fullscreen?"true":"false");
  765. RECT WindowRect;
  766. WindowRect.left = 0;
  767. WindowRect.right = video_mode.width;
  768. WindowRect.top = 0;
  769. WindowRect.bottom = video_mode.height;
  770. memset(&wc, 0, sizeof(WNDCLASSEXW));
  771. wc.cbSize = sizeof(WNDCLASSEXW);
  772. wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS;
  773. wc.lpfnWndProc = (WNDPROC)::WndProc;
  774. wc.cbClsExtra = 0;
  775. wc.cbWndExtra = 0;
  776. //wc.hInstance = hInstance;
  777. wc.hInstance = godot_hinstance ? godot_hinstance : GetModuleHandle(NULL);
  778. wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
  779. wc.hCursor = NULL; //LoadCursor(NULL, IDC_ARROW);
  780. wc.hbrBackground = NULL;
  781. wc.lpszMenuName = NULL;
  782. wc.lpszClassName = L"Engine";
  783. if (!RegisterClassExW(&wc)) {
  784. MessageBox(NULL, "Failed To Register The Window Class.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
  785. return; // Return
  786. }
  787. pre_fs_valid = true;
  788. if (video_mode.fullscreen) {
  789. DEVMODE current;
  790. memset(&current, 0, sizeof(current));
  791. EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &current);
  792. WindowRect.right = current.dmPelsWidth;
  793. WindowRect.bottom = current.dmPelsHeight;
  794. /* DEVMODE dmScreenSettings;
  795. memset(&dmScreenSettings,0,sizeof(dmScreenSettings));
  796. dmScreenSettings.dmSize=sizeof(dmScreenSettings);
  797. dmScreenSettings.dmPelsWidth = video_mode.width;
  798. dmScreenSettings.dmPelsHeight = video_mode.height;
  799. dmScreenSettings.dmBitsPerPel = current.dmBitsPerPel;
  800. dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
  801. LONG err = ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN);
  802. if (err!=DISP_CHANGE_SUCCESSFUL) {
  803. video_mode.fullscreen=false;
  804. }*/
  805. pre_fs_valid = false;
  806. }
  807. DWORD dwExStyle;
  808. DWORD dwStyle;
  809. if (video_mode.fullscreen || video_mode.borderless_window) {
  810. dwExStyle = WS_EX_APPWINDOW;
  811. dwStyle = WS_POPUP;
  812. } else {
  813. dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
  814. dwStyle = WS_OVERLAPPEDWINDOW;
  815. if (!video_mode.resizable) {
  816. dwStyle &= ~WS_THICKFRAME;
  817. dwStyle &= ~WS_MAXIMIZEBOX;
  818. }
  819. }
  820. AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);
  821. char *windowid = getenv("GODOT_WINDOWID");
  822. if (windowid) {
  823. // strtoull on mingw
  824. #ifdef MINGW_ENABLED
  825. hWnd = (HWND)strtoull(windowid, NULL, 0);
  826. #else
  827. hWnd = (HWND)_strtoui64(windowid, NULL, 0);
  828. #endif
  829. SetLastError(0);
  830. user_proc = (WNDPROC)GetWindowLongPtr(hWnd, GWLP_WNDPROC);
  831. SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)(WNDPROC)::WndProc);
  832. DWORD le = GetLastError();
  833. if (user_proc == 0 && le != 0) {
  834. printf("Error setting WNDPROC: %li\n", le);
  835. };
  836. LONG_PTR proc = GetWindowLongPtr(hWnd, GWLP_WNDPROC);
  837. RECT rect;
  838. if (!GetClientRect(hWnd, &rect)) {
  839. MessageBoxW(NULL, L"Window Creation Error.", L"ERROR", MB_OK | MB_ICONEXCLAMATION);
  840. return; // Return FALSE
  841. };
  842. video_mode.width = rect.right;
  843. video_mode.height = rect.bottom;
  844. video_mode.fullscreen = false;
  845. } else {
  846. if (!(hWnd = CreateWindowExW(dwExStyle, L"Engine", L"", dwStyle | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, (GetSystemMetrics(SM_CXSCREEN) - WindowRect.right) / 2, (GetSystemMetrics(SM_CYSCREEN) - WindowRect.bottom) / 2, WindowRect.right - WindowRect.left, WindowRect.bottom - WindowRect.top, NULL, NULL, hInstance, NULL))) {
  847. MessageBoxW(NULL, L"Window Creation Error.", L"ERROR", MB_OK | MB_ICONEXCLAMATION);
  848. return; // Return FALSE
  849. }
  850. };
  851. if (video_mode.always_on_top) {
  852. SetWindowPos(hWnd, video_mode.always_on_top ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
  853. }
  854. #if defined(OPENGL_ENABLED) || defined(GLES2_ENABLED) || defined(LEGACYGL_ENABLED)
  855. gl_context = memnew(ContextGL_Win(hWnd, false));
  856. gl_context->initialize();
  857. rasterizer = memnew(RasterizerGLES2);
  858. #else
  859. #ifdef DX9_ENABLED
  860. rasterizer = memnew(RasterizerDX9(hWnd));
  861. #endif
  862. #endif
  863. visual_server = memnew(VisualServerRaster(rasterizer));
  864. if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) {
  865. visual_server = memnew(VisualServerWrapMT(visual_server, get_render_thread_mode() == RENDER_SEPARATE_THREAD));
  866. }
  867. //
  868. physics_server = memnew(PhysicsServerSW);
  869. physics_server->init();
  870. physics_2d_server = Physics2DServerWrapMT::init_server<Physics2DServerSW>();
  871. physics_2d_server->init();
  872. if (!is_no_window_mode_enabled()) {
  873. ShowWindow(hWnd, SW_SHOW); // Show The Window
  874. SetForegroundWindow(hWnd); // Slightly Higher Priority
  875. SetFocus(hWnd); // Sets Keyboard Focus To
  876. }
  877. /*
  878. DEVMODE dmScreenSettings; // Device Mode
  879. memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); // Makes Sure Memory's Cleared
  880. dmScreenSettings.dmSize=sizeof(dmScreenSettings); // Size Of The Devmode Structure
  881. dmScreenSettings.dmPelsWidth = width; // Selected Screen Width
  882. dmScreenSettings.dmPelsHeight = height; // Selected Screen Height
  883. dmScreenSettings.dmBitsPerPel = bits; // Selected Bits Per Pixel
  884. dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
  885. if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
  886. */
  887. visual_server->init();
  888. input = memnew(InputDefault);
  889. joystick = memnew(joystick_windows(input, &hWnd));
  890. AudioDriverManagerSW::get_driver(p_audio_driver)->set_singleton();
  891. if (AudioDriverManagerSW::get_driver(p_audio_driver)->init() != OK) {
  892. ERR_PRINT("Initializing audio failed.");
  893. }
  894. sample_manager = memnew(SampleManagerMallocSW);
  895. audio_server = memnew(AudioServerSW(sample_manager));
  896. audio_server->init();
  897. spatial_sound_server = memnew(SpatialSoundServerSW);
  898. spatial_sound_server->init();
  899. spatial_sound_2d_server = memnew(SpatialSound2DServerSW);
  900. spatial_sound_2d_server->init();
  901. TRACKMOUSEEVENT tme;
  902. tme.cbSize = sizeof(TRACKMOUSEEVENT);
  903. tme.dwFlags = TME_LEAVE;
  904. tme.hwndTrack = hWnd;
  905. tme.dwHoverTime = HOVER_DEFAULT;
  906. TrackMouseEvent(&tme);
  907. #if WINVER >= 0x0601 // for windows 7
  908. RegisterTouchWindow(hWnd, 0); // Windows 7
  909. #endif
  910. _ensure_data_dir();
  911. DragAcceptFiles(hWnd, true);
  912. move_timer_id = 1;
  913. }
  914. void OS_Windows::set_clipboard(const String &p_text) {
  915. if (!OpenClipboard(hWnd)) {
  916. ERR_EXPLAIN("Unable to open clipboard.");
  917. ERR_FAIL();
  918. };
  919. EmptyClipboard();
  920. HGLOBAL mem = GlobalAlloc(GMEM_MOVEABLE, (p_text.length() + 1) * sizeof(CharType));
  921. if (mem == NULL) {
  922. ERR_EXPLAIN("Unable to allocate memory for clipboard contents.");
  923. ERR_FAIL();
  924. };
  925. LPWSTR lptstrCopy = (LPWSTR)GlobalLock(mem);
  926. memcpy(lptstrCopy, p_text.c_str(), (p_text.length() + 1) * sizeof(CharType));
  927. //memset((lptstrCopy + p_text.length()), 0, sizeof(CharType));
  928. GlobalUnlock(mem);
  929. SetClipboardData(CF_UNICODETEXT, mem);
  930. // set the CF_TEXT version (not needed?)
  931. CharString utf8 = p_text.utf8();
  932. mem = GlobalAlloc(GMEM_MOVEABLE, utf8.length() + 1);
  933. if (mem == NULL) {
  934. ERR_EXPLAIN("Unable to allocate memory for clipboard contents.");
  935. ERR_FAIL();
  936. };
  937. LPTSTR ptr = (LPTSTR)GlobalLock(mem);
  938. memcpy(ptr, utf8.get_data(), utf8.length());
  939. ptr[utf8.length()] = 0;
  940. GlobalUnlock(mem);
  941. SetClipboardData(CF_TEXT, mem);
  942. CloseClipboard();
  943. };
  944. String OS_Windows::get_clipboard() const {
  945. String ret;
  946. if (!OpenClipboard(hWnd)) {
  947. ERR_EXPLAIN("Unable to open clipboard.");
  948. ERR_FAIL_V("");
  949. };
  950. if (IsClipboardFormatAvailable(CF_UNICODETEXT)) {
  951. HGLOBAL mem = GetClipboardData(CF_UNICODETEXT);
  952. if (mem != NULL) {
  953. LPWSTR ptr = (LPWSTR)GlobalLock(mem);
  954. if (ptr != NULL) {
  955. ret = String((CharType *)ptr);
  956. GlobalUnlock(mem);
  957. };
  958. };
  959. } else if (IsClipboardFormatAvailable(CF_TEXT)) {
  960. HGLOBAL mem = GetClipboardData(CF_UNICODETEXT);
  961. if (mem != NULL) {
  962. LPTSTR ptr = (LPTSTR)GlobalLock(mem);
  963. if (ptr != NULL) {
  964. ret.parse_utf8((const char *)ptr);
  965. GlobalUnlock(mem);
  966. };
  967. };
  968. };
  969. CloseClipboard();
  970. return ret;
  971. };
  972. void OS_Windows::delete_main_loop() {
  973. if (main_loop)
  974. memdelete(main_loop);
  975. main_loop = NULL;
  976. }
  977. void OS_Windows::set_main_loop(MainLoop *p_main_loop) {
  978. input->set_main_loop(p_main_loop);
  979. main_loop = p_main_loop;
  980. }
  981. void OS_Windows::finalize() {
  982. if (main_loop)
  983. memdelete(main_loop);
  984. main_loop = NULL;
  985. memdelete(joystick);
  986. memdelete(input);
  987. #if WINVER >= 0x0601 // for windows 7
  988. touch_state.clear();
  989. #endif
  990. visual_server->finish();
  991. memdelete(visual_server);
  992. #ifdef OPENGL_ENABLED
  993. if (gl_context)
  994. memdelete(gl_context);
  995. #endif
  996. if (rasterizer)
  997. memdelete(rasterizer);
  998. if (user_proc) {
  999. SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)user_proc);
  1000. };
  1001. spatial_sound_server->finish();
  1002. memdelete(spatial_sound_server);
  1003. spatial_sound_2d_server->finish();
  1004. memdelete(spatial_sound_2d_server);
  1005. //if (debugger_connection_console) {
  1006. // memdelete(debugger_connection_console);
  1007. //}
  1008. memdelete(sample_manager);
  1009. audio_server->finish();
  1010. memdelete(audio_server);
  1011. physics_server->finish();
  1012. memdelete(physics_server);
  1013. physics_2d_server->finish();
  1014. memdelete(physics_2d_server);
  1015. }
  1016. void OS_Windows::finalize_core() {
  1017. memdelete(process_map);
  1018. if (mempool_dynamic)
  1019. memdelete(mempool_dynamic);
  1020. delete mempool_static;
  1021. TCPServerWinsock::cleanup();
  1022. StreamPeerWinsock::cleanup();
  1023. }
  1024. void OS_Windows::vprint(const char *p_format, va_list p_list, bool p_stderr) {
  1025. const unsigned int BUFFER_SIZE = 16384;
  1026. char buf[BUFFER_SIZE + 1]; // +1 for the terminating character
  1027. int len = vsnprintf(buf, BUFFER_SIZE, p_format, p_list);
  1028. if (len <= 0)
  1029. return;
  1030. if (len >= BUFFER_SIZE)
  1031. len = BUFFER_SIZE; // Output is too big, will be truncated
  1032. buf[len] = 0;
  1033. int wlen = MultiByteToWideChar(CP_UTF8, 0, buf, len, NULL, 0);
  1034. if (wlen < 0)
  1035. return;
  1036. wchar_t *wbuf = (wchar_t *)malloc((len + 1) * sizeof(wchar_t));
  1037. MultiByteToWideChar(CP_UTF8, 0, buf, len, wbuf, wlen);
  1038. wbuf[wlen] = 0;
  1039. if (p_stderr)
  1040. fwprintf(stderr, L"%ls", wbuf);
  1041. else
  1042. wprintf(L"%ls", wbuf);
  1043. #ifdef STDOUT_FILE
  1044. //vwfprintf(stdo,p_format,p_list);
  1045. #endif
  1046. free(wbuf);
  1047. fflush(stdout);
  1048. };
  1049. void OS_Windows::alert(const String &p_alert, const String &p_title) {
  1050. if (!is_no_window_mode_enabled())
  1051. MessageBoxW(NULL, p_alert.c_str(), p_title.c_str(), MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
  1052. else
  1053. print_line("ALERT: " + p_alert);
  1054. }
  1055. void OS_Windows::set_mouse_mode(MouseMode p_mode) {
  1056. if (mouse_mode == p_mode)
  1057. return;
  1058. mouse_mode = p_mode;
  1059. if (p_mode == MOUSE_MODE_CAPTURED) {
  1060. RECT clipRect;
  1061. GetClientRect(hWnd, &clipRect);
  1062. ClientToScreen(hWnd, (POINT *)&clipRect.left);
  1063. ClientToScreen(hWnd, (POINT *)&clipRect.right);
  1064. ClipCursor(&clipRect);
  1065. SetCapture(hWnd);
  1066. center = Point2i(video_mode.width / 2, video_mode.height / 2);
  1067. POINT pos = { (int)center.x, (int)center.y };
  1068. ClientToScreen(hWnd, &pos);
  1069. SetCursorPos(pos.x, pos.y);
  1070. } else {
  1071. ReleaseCapture();
  1072. ClipCursor(NULL);
  1073. }
  1074. if (p_mode == MOUSE_MODE_CAPTURED || p_mode == MOUSE_MODE_HIDDEN) {
  1075. hCursor = SetCursor(NULL);
  1076. } else {
  1077. CursorShape c = cursor_shape;
  1078. cursor_shape = CURSOR_MAX;
  1079. set_cursor_shape(c);
  1080. }
  1081. }
  1082. OS_Windows::MouseMode OS_Windows::get_mouse_mode() const {
  1083. return mouse_mode;
  1084. }
  1085. void OS_Windows::warp_mouse_pos(const Point2 &p_to) {
  1086. if (mouse_mode == MOUSE_MODE_CAPTURED) {
  1087. old_x = p_to.x;
  1088. old_y = p_to.y;
  1089. } else {
  1090. POINT p;
  1091. p.x = p_to.x;
  1092. p.y = p_to.y;
  1093. ClientToScreen(hWnd, &p);
  1094. SetCursorPos(p.x, p.y);
  1095. }
  1096. }
  1097. Point2 OS_Windows::get_mouse_pos() const {
  1098. return Point2(old_x, old_y);
  1099. }
  1100. int OS_Windows::get_mouse_button_state() const {
  1101. return last_button_state;
  1102. }
  1103. void OS_Windows::set_window_title(const String &p_title) {
  1104. SetWindowTextW(hWnd, p_title.c_str());
  1105. }
  1106. void OS_Windows::set_video_mode(const VideoMode &p_video_mode, int p_screen) {
  1107. }
  1108. OS::VideoMode OS_Windows::get_video_mode(int p_screen) const {
  1109. return video_mode;
  1110. }
  1111. void OS_Windows::get_fullscreen_mode_list(List<VideoMode> *p_list, int p_screen) const {
  1112. }
  1113. static BOOL CALLBACK _MonitorEnumProcCount(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) {
  1114. int *data = (int *)dwData;
  1115. (*data)++;
  1116. return TRUE;
  1117. }
  1118. int OS_Windows::get_screen_count() const {
  1119. int data = 0;
  1120. EnumDisplayMonitors(NULL, NULL, _MonitorEnumProcCount, (LPARAM)&data);
  1121. return data;
  1122. }
  1123. typedef struct {
  1124. int count;
  1125. int screen;
  1126. HMONITOR monitor;
  1127. } EnumScreenData;
  1128. static BOOL CALLBACK _MonitorEnumProcScreen(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) {
  1129. EnumScreenData *data = (EnumScreenData *)dwData;
  1130. if (data->monitor == hMonitor) {
  1131. data->screen = data->count;
  1132. }
  1133. data->count++;
  1134. return TRUE;
  1135. }
  1136. int OS_Windows::get_current_screen() const {
  1137. EnumScreenData data = { 0, 0, MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST) };
  1138. EnumDisplayMonitors(NULL, NULL, _MonitorEnumProcScreen, (LPARAM)&data);
  1139. return data.screen;
  1140. }
  1141. void OS_Windows::set_current_screen(int p_screen) {
  1142. Vector2 ofs = get_window_position() - get_screen_position(get_current_screen());
  1143. set_window_position(ofs + get_screen_position(p_screen));
  1144. }
  1145. typedef struct {
  1146. int count;
  1147. int screen;
  1148. Point2 pos;
  1149. } EnumPosData;
  1150. static BOOL CALLBACK _MonitorEnumProcPos(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) {
  1151. EnumPosData *data = (EnumPosData *)dwData;
  1152. if (data->count == data->screen) {
  1153. data->pos.x = lprcMonitor->left;
  1154. data->pos.y = lprcMonitor->top;
  1155. }
  1156. data->count++;
  1157. return TRUE;
  1158. }
  1159. Point2 OS_Windows::get_screen_position(int p_screen) const {
  1160. EnumPosData data = { 0, p_screen, Point2() };
  1161. EnumDisplayMonitors(NULL, NULL, _MonitorEnumProcPos, (LPARAM)&data);
  1162. return data.pos;
  1163. }
  1164. typedef struct {
  1165. int count;
  1166. int screen;
  1167. Size2 size;
  1168. } EnumSizeData;
  1169. static BOOL CALLBACK _MonitorEnumProcSize(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) {
  1170. EnumSizeData *data = (EnumSizeData *)dwData;
  1171. if (data->count == data->screen) {
  1172. data->size.x = lprcMonitor->right - lprcMonitor->left;
  1173. data->size.y = lprcMonitor->bottom - lprcMonitor->top;
  1174. }
  1175. data->count++;
  1176. return TRUE;
  1177. }
  1178. Size2 OS_Windows::get_screen_size(int p_screen) const {
  1179. EnumSizeData data = { 0, p_screen, Size2() };
  1180. EnumDisplayMonitors(NULL, NULL, _MonitorEnumProcSize, (LPARAM)&data);
  1181. return data.size;
  1182. }
  1183. typedef struct {
  1184. int count;
  1185. int screen;
  1186. int dpi;
  1187. } EnumDpiData;
  1188. static BOOL CALLBACK _MonitorEnumProcDpi(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) {
  1189. EnumDpiData *data = (EnumDpiData *)dwData;
  1190. if (data->count == data->screen) {
  1191. data->dpi = QueryDpiForMonitor(hMonitor);
  1192. }
  1193. data->count++;
  1194. return TRUE;
  1195. }
  1196. int OS_Windows::get_screen_dpi(int p_screen) const {
  1197. EnumDpiData data = { 0, p_screen, 72 };
  1198. EnumDisplayMonitors(NULL, NULL, _MonitorEnumProcDpi, (LPARAM)&data);
  1199. return data.dpi;
  1200. }
  1201. Point2 OS_Windows::get_window_position() const {
  1202. RECT r;
  1203. GetWindowRect(hWnd, &r);
  1204. return Point2(r.left, r.top);
  1205. }
  1206. void OS_Windows::set_window_position(const Point2 &p_position) {
  1207. if (video_mode.fullscreen) return;
  1208. RECT r;
  1209. GetWindowRect(hWnd, &r);
  1210. MoveWindow(hWnd, p_position.x, p_position.y, r.right - r.left, r.bottom - r.top, TRUE);
  1211. }
  1212. Size2 OS_Windows::get_window_size() const {
  1213. RECT r;
  1214. GetClientRect(hWnd, &r);
  1215. return Vector2(r.right - r.left, r.bottom - r.top);
  1216. }
  1217. Size2 OS_Windows::get_real_window_size() const {
  1218. RECT r;
  1219. GetWindowRect(hWnd, &r);
  1220. return Vector2(r.right - r.left, r.bottom - r.top);
  1221. }
  1222. void OS_Windows::set_window_size(const Size2 p_size) {
  1223. video_mode.width = p_size.width;
  1224. video_mode.height = p_size.height;
  1225. if (video_mode.fullscreen) {
  1226. return;
  1227. }
  1228. int w = p_size.width;
  1229. int h = p_size.height;
  1230. RECT rect;
  1231. GetWindowRect(hWnd, &rect);
  1232. if (video_mode.borderless_window == false) {
  1233. RECT crect;
  1234. GetClientRect(hWnd, &crect);
  1235. w += (rect.right - rect.left) - (crect.right - crect.left);
  1236. h += (rect.bottom - rect.top) - (crect.bottom - crect.top);
  1237. }
  1238. MoveWindow(hWnd, rect.left, rect.top, w, h, TRUE);
  1239. }
  1240. void OS_Windows::set_window_fullscreen(bool p_enabled) {
  1241. if (video_mode.fullscreen == p_enabled)
  1242. return;
  1243. if (p_enabled) {
  1244. if (pre_fs_valid) {
  1245. GetWindowRect(hWnd, &pre_fs_rect);
  1246. //print_line("A: "+itos(pre_fs_rect.left)+","+itos(pre_fs_rect.top)+","+itos(pre_fs_rect.right-pre_fs_rect.left)+","+itos(pre_fs_rect.bottom-pre_fs_rect.top));
  1247. //MapWindowPoints(hWnd, GetParent(hWnd), (LPPOINT) &pre_fs_rect, 2);
  1248. //print_line("B: "+itos(pre_fs_rect.left)+","+itos(pre_fs_rect.top)+","+itos(pre_fs_rect.right-pre_fs_rect.left)+","+itos(pre_fs_rect.bottom-pre_fs_rect.top));
  1249. }
  1250. int cs = get_current_screen();
  1251. Point2 pos = get_screen_position(cs);
  1252. Size2 size = get_screen_size(cs);
  1253. video_mode.fullscreen = true;
  1254. _update_window_style(false);
  1255. MoveWindow(hWnd, pos.x, pos.y, size.width, size.height, TRUE);
  1256. } else {
  1257. RECT rect;
  1258. video_mode.fullscreen = false;
  1259. if (pre_fs_valid) {
  1260. rect = pre_fs_rect;
  1261. } else {
  1262. rect.left = 0;
  1263. rect.right = video_mode.width;
  1264. rect.top = 0;
  1265. rect.bottom = video_mode.height;
  1266. }
  1267. _update_window_style(false);
  1268. MoveWindow(hWnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, TRUE);
  1269. pre_fs_valid = true;
  1270. }
  1271. }
  1272. bool OS_Windows::is_window_fullscreen() const {
  1273. return video_mode.fullscreen;
  1274. }
  1275. void OS_Windows::set_window_resizable(bool p_enabled) {
  1276. if (video_mode.resizable == p_enabled)
  1277. return;
  1278. video_mode.resizable = p_enabled;
  1279. _update_window_style();
  1280. }
  1281. bool OS_Windows::is_window_resizable() const {
  1282. return video_mode.resizable;
  1283. }
  1284. void OS_Windows::set_window_minimized(bool p_enabled) {
  1285. if (p_enabled) {
  1286. maximized = false;
  1287. minimized = true;
  1288. ShowWindow(hWnd, SW_MINIMIZE);
  1289. } else {
  1290. ShowWindow(hWnd, SW_RESTORE);
  1291. maximized = false;
  1292. minimized = false;
  1293. }
  1294. }
  1295. bool OS_Windows::is_window_minimized() const {
  1296. return minimized;
  1297. }
  1298. void OS_Windows::set_window_maximized(bool p_enabled) {
  1299. if (p_enabled) {
  1300. maximized = true;
  1301. minimized = false;
  1302. ShowWindow(hWnd, SW_MAXIMIZE);
  1303. } else {
  1304. ShowWindow(hWnd, SW_RESTORE);
  1305. maximized = false;
  1306. minimized = false;
  1307. }
  1308. }
  1309. bool OS_Windows::is_window_maximized() const {
  1310. return maximized;
  1311. }
  1312. void OS_Windows::set_window_always_on_top(bool p_enabled) {
  1313. if (video_mode.always_on_top == p_enabled)
  1314. return;
  1315. video_mode.always_on_top = p_enabled;
  1316. _update_window_style();
  1317. }
  1318. bool OS_Windows::is_window_always_on_top() const {
  1319. return video_mode.always_on_top;
  1320. }
  1321. void OS_Windows::set_borderless_window(int p_borderless) {
  1322. if (video_mode.borderless_window == p_borderless)
  1323. return;
  1324. video_mode.borderless_window = p_borderless;
  1325. _update_window_style();
  1326. }
  1327. bool OS_Windows::get_borderless_window() {
  1328. return video_mode.borderless_window;
  1329. }
  1330. void OS_Windows::_update_window_style(bool repaint) {
  1331. if (video_mode.fullscreen || video_mode.borderless_window) {
  1332. SetWindowLongPtr(hWnd, GWL_STYLE, WS_SYSMENU | WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE);
  1333. } else {
  1334. if (video_mode.resizable) {
  1335. SetWindowLongPtr(hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE);
  1336. } else {
  1337. SetWindowLongPtr(hWnd, GWL_STYLE, WS_CAPTION | WS_MINIMIZEBOX | WS_POPUPWINDOW | WS_VISIBLE);
  1338. }
  1339. }
  1340. SetWindowPos(hWnd, video_mode.always_on_top ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
  1341. if (repaint) {
  1342. RECT rect;
  1343. GetWindowRect(hWnd, &rect);
  1344. MoveWindow(hWnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, TRUE);
  1345. }
  1346. }
  1347. void OS_Windows::request_attention() {
  1348. FLASHWINFO info;
  1349. info.cbSize = sizeof(FLASHWINFO);
  1350. info.hwnd = hWnd;
  1351. info.dwFlags = FLASHW_TRAY;
  1352. info.dwTimeout = 0;
  1353. info.uCount = 2;
  1354. FlashWindowEx(&info);
  1355. }
  1356. void OS_Windows::print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
  1357. HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE);
  1358. if (!hCon || hCon == INVALID_HANDLE_VALUE) {
  1359. const char *err_details;
  1360. if (p_rationale && p_rationale[0])
  1361. err_details = p_rationale;
  1362. else
  1363. err_details = p_code;
  1364. switch (p_type) {
  1365. case ERR_ERROR:
  1366. print("ERROR: %s: %s\n", p_function, err_details);
  1367. print(" At: %s:%i\n", p_file, p_line);
  1368. break;
  1369. case ERR_WARNING:
  1370. print("WARNING: %s: %s\n", p_function, err_details);
  1371. print(" At: %s:%i\n", p_file, p_line);
  1372. break;
  1373. case ERR_SCRIPT:
  1374. print("SCRIPT ERROR: %s: %s\n", p_function, err_details);
  1375. print(" At: %s:%i\n", p_file, p_line);
  1376. break;
  1377. }
  1378. } else {
  1379. CONSOLE_SCREEN_BUFFER_INFO sbi; //original
  1380. GetConsoleScreenBufferInfo(hCon, &sbi);
  1381. WORD current_fg = sbi.wAttributes & (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
  1382. WORD current_bg = sbi.wAttributes & (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY);
  1383. uint32_t basecol = 0;
  1384. switch (p_type) {
  1385. case ERR_ERROR: basecol = FOREGROUND_RED; break;
  1386. case ERR_WARNING: basecol = FOREGROUND_RED | FOREGROUND_GREEN; break;
  1387. case ERR_SCRIPT: basecol = FOREGROUND_RED | FOREGROUND_BLUE; break;
  1388. }
  1389. basecol |= current_bg;
  1390. if (p_rationale && p_rationale[0]) {
  1391. SetConsoleTextAttribute(hCon, basecol | FOREGROUND_INTENSITY);
  1392. switch (p_type) {
  1393. case ERR_ERROR: print("ERROR: "); break;
  1394. case ERR_WARNING: print("WARNING: "); break;
  1395. case ERR_SCRIPT: print("SCRIPT ERROR: "); break;
  1396. }
  1397. SetConsoleTextAttribute(hCon, current_fg | current_bg | FOREGROUND_INTENSITY);
  1398. print("%s\n", p_rationale);
  1399. SetConsoleTextAttribute(hCon, basecol);
  1400. switch (p_type) {
  1401. case ERR_ERROR: print(" At: "); break;
  1402. case ERR_WARNING: print(" At: "); break;
  1403. case ERR_SCRIPT: print(" At: "); break;
  1404. }
  1405. SetConsoleTextAttribute(hCon, current_fg | current_bg);
  1406. print("%s:%i\n", p_file, p_line);
  1407. } else {
  1408. SetConsoleTextAttribute(hCon, basecol | FOREGROUND_INTENSITY);
  1409. switch (p_type) {
  1410. case ERR_ERROR: print("ERROR: %s: ", p_function); break;
  1411. case ERR_WARNING: print("WARNING: %s: ", p_function); break;
  1412. case ERR_SCRIPT: print("SCRIPT ERROR: %s: ", p_function); break;
  1413. }
  1414. SetConsoleTextAttribute(hCon, current_fg | current_bg | FOREGROUND_INTENSITY);
  1415. print("%s\n", p_code);
  1416. SetConsoleTextAttribute(hCon, basecol);
  1417. switch (p_type) {
  1418. case ERR_ERROR: print(" At: "); break;
  1419. case ERR_WARNING: print(" At: "); break;
  1420. case ERR_SCRIPT: print(" At: "); break;
  1421. }
  1422. SetConsoleTextAttribute(hCon, current_fg | current_bg);
  1423. print("%s:%i\n", p_file, p_line);
  1424. }
  1425. SetConsoleTextAttribute(hCon, sbi.wAttributes);
  1426. }
  1427. }
  1428. String OS_Windows::get_name() {
  1429. return "Windows";
  1430. }
  1431. OS::Date OS_Windows::get_date(bool utc) const {
  1432. SYSTEMTIME systemtime;
  1433. if (utc)
  1434. GetSystemTime(&systemtime);
  1435. else
  1436. GetLocalTime(&systemtime);
  1437. Date date;
  1438. date.day = systemtime.wDay;
  1439. date.month = Month(systemtime.wMonth);
  1440. date.weekday = Weekday(systemtime.wDayOfWeek);
  1441. date.year = systemtime.wYear;
  1442. date.dst = false;
  1443. return date;
  1444. }
  1445. OS::Time OS_Windows::get_time(bool utc) const {
  1446. SYSTEMTIME systemtime;
  1447. if (utc)
  1448. GetSystemTime(&systemtime);
  1449. else
  1450. GetLocalTime(&systemtime);
  1451. Time time;
  1452. time.hour = systemtime.wHour;
  1453. time.min = systemtime.wMinute;
  1454. time.sec = systemtime.wSecond;
  1455. return time;
  1456. }
  1457. OS::TimeZoneInfo OS_Windows::get_time_zone_info() const {
  1458. TIME_ZONE_INFORMATION info;
  1459. bool daylight = false;
  1460. if (GetTimeZoneInformation(&info) == TIME_ZONE_ID_DAYLIGHT)
  1461. daylight = true;
  1462. TimeZoneInfo ret;
  1463. if (daylight) {
  1464. ret.name = info.DaylightName;
  1465. } else {
  1466. ret.name = info.StandardName;
  1467. }
  1468. ret.bias = info.Bias;
  1469. return ret;
  1470. }
  1471. uint64_t OS_Windows::get_unix_time() const {
  1472. FILETIME ft;
  1473. SYSTEMTIME st;
  1474. GetSystemTime(&st);
  1475. SystemTimeToFileTime(&st, &ft);
  1476. SYSTEMTIME ep;
  1477. ep.wYear = 1970;
  1478. ep.wMonth = 1;
  1479. ep.wDayOfWeek = 4;
  1480. ep.wDay = 1;
  1481. ep.wHour = 0;
  1482. ep.wMinute = 0;
  1483. ep.wSecond = 0;
  1484. ep.wMilliseconds = 0;
  1485. FILETIME fep;
  1486. SystemTimeToFileTime(&ep, &fep);
  1487. return (*(uint64_t *)&ft - *(uint64_t *)&fep) / 10000000;
  1488. };
  1489. uint64_t OS_Windows::get_system_time_secs() const {
  1490. const uint64_t WINDOWS_TICK = 10000000;
  1491. const uint64_t SEC_TO_UNIX_EPOCH = 11644473600LL;
  1492. SYSTEMTIME st;
  1493. GetSystemTime(&st);
  1494. FILETIME ft;
  1495. SystemTimeToFileTime(&st, &ft);
  1496. uint64_t ret;
  1497. ret = ft.dwHighDateTime;
  1498. ret <<= 32;
  1499. ret |= ft.dwLowDateTime;
  1500. return (uint64_t)(ret / WINDOWS_TICK - SEC_TO_UNIX_EPOCH);
  1501. }
  1502. void OS_Windows::delay_usec(uint32_t p_usec) const {
  1503. if (p_usec < 1000)
  1504. Sleep(1);
  1505. else
  1506. Sleep(p_usec / 1000);
  1507. }
  1508. uint64_t OS_Windows::get_ticks_usec() const {
  1509. uint64_t ticks;
  1510. uint64_t time;
  1511. // This is the number of clock ticks since start
  1512. if (!QueryPerformanceCounter((LARGE_INTEGER *)&ticks))
  1513. ticks = (UINT64)timeGetTime();
  1514. // Divide by frequency to get the time in seconds
  1515. time = ticks * 1000000L / ticks_per_second;
  1516. // Subtract the time at game start to get
  1517. // the time since the game started
  1518. time -= ticks_start;
  1519. return time;
  1520. }
  1521. void OS_Windows::process_events() {
  1522. MSG msg;
  1523. last_id = joystick->process_joysticks(last_id);
  1524. while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) {
  1525. TranslateMessage(&msg);
  1526. DispatchMessageW(&msg);
  1527. }
  1528. process_key_events();
  1529. }
  1530. void OS_Windows::set_cursor_shape(CursorShape p_shape) {
  1531. ERR_FAIL_INDEX(p_shape, CURSOR_MAX);
  1532. if (cursor_shape == p_shape)
  1533. return;
  1534. if (mouse_mode != MOUSE_MODE_VISIBLE) {
  1535. cursor_shape = p_shape;
  1536. return;
  1537. }
  1538. static const LPCTSTR win_cursors[CURSOR_MAX] = {
  1539. IDC_ARROW,
  1540. IDC_IBEAM,
  1541. IDC_HAND, //finger
  1542. IDC_CROSS,
  1543. IDC_WAIT,
  1544. IDC_APPSTARTING,
  1545. IDC_ARROW,
  1546. IDC_ARROW,
  1547. IDC_NO,
  1548. IDC_SIZENS,
  1549. IDC_SIZEWE,
  1550. IDC_SIZENESW,
  1551. IDC_SIZENWSE,
  1552. IDC_SIZEALL,
  1553. IDC_SIZENS,
  1554. IDC_SIZEWE,
  1555. IDC_HELP
  1556. };
  1557. if (cursors[p_shape] != NULL) {
  1558. SetCursor(cursors[p_shape]);
  1559. } else {
  1560. SetCursor(LoadCursor(hInstance, win_cursors[p_shape]));
  1561. }
  1562. cursor_shape = p_shape;
  1563. }
  1564. void OS_Windows::set_custom_mouse_cursor(const RES &p_cursor, CursorShape p_shape, const Vector2 &p_hotspot) {
  1565. if (p_cursor.is_valid()) {
  1566. Ref<ImageTexture> texture = p_cursor;
  1567. Ref<AtlasTexture> atlas_texture = p_cursor;
  1568. Size2 texture_size;
  1569. Rect2 atlas_rect;
  1570. if (!texture.is_valid() && atlas_texture.is_valid()) {
  1571. texture = atlas_texture->get_atlas();
  1572. atlas_rect.size.width = texture->get_width();
  1573. atlas_rect.size.height = texture->get_height();
  1574. atlas_rect.pos.x = atlas_texture->get_region().pos.x;
  1575. atlas_rect.pos.y = atlas_texture->get_region().pos.y;
  1576. texture_size.width = atlas_texture->get_region().size.x;
  1577. texture_size.height = atlas_texture->get_region().size.y;
  1578. } else if (texture.is_valid()) {
  1579. texture_size.width = texture->get_width();
  1580. texture_size.height = texture->get_height();
  1581. }
  1582. ERR_FAIL_COND(!texture.is_valid());
  1583. ERR_FAIL_COND(texture_size.width > 256 || texture_size.height > 256);
  1584. Image image = texture->get_data();
  1585. UINT image_size = texture_size.width * texture_size.height;
  1586. UINT size = sizeof(UINT) * image_size;
  1587. // Create the BITMAP with alpha channel
  1588. COLORREF *buffer = (COLORREF *)memalloc(sizeof(COLORREF) * image_size);
  1589. for (UINT index = 0; index < image_size; index++) {
  1590. int row_index = floor(index / texture_size.width) + atlas_rect.pos.y;
  1591. int column_index = (index % int(texture_size.width)) + atlas_rect.pos.x;
  1592. if (atlas_texture.is_valid()) {
  1593. column_index = MIN(column_index, atlas_rect.size.width - 1);
  1594. row_index = MIN(row_index, atlas_rect.size.height - 1);
  1595. }
  1596. *(buffer + index) = image.get_pixel(column_index, row_index).to_ARGB32();
  1597. }
  1598. // Using 4 channels, so 4 * 8 bits
  1599. HBITMAP bitmap = CreateBitmap(texture_size.width, texture_size.height, 1, 4 * 8, buffer);
  1600. COLORREF clrTransparent = -1;
  1601. // Create the AND and XOR masks for the bitmap
  1602. HBITMAP hAndMask = NULL;
  1603. HBITMAP hXorMask = NULL;
  1604. GetMaskBitmaps(bitmap, clrTransparent, hAndMask, hXorMask);
  1605. if (NULL == hAndMask || NULL == hXorMask) {
  1606. memfree(buffer);
  1607. DeleteObject(bitmap);
  1608. return;
  1609. }
  1610. // Finally, create the icon
  1611. ICONINFO iconinfo = { 0 };
  1612. iconinfo.fIcon = FALSE;
  1613. iconinfo.xHotspot = p_hotspot.x;
  1614. iconinfo.yHotspot = p_hotspot.y;
  1615. iconinfo.hbmMask = hAndMask;
  1616. iconinfo.hbmColor = hXorMask;
  1617. cursors[p_shape] = CreateIconIndirect(&iconinfo);
  1618. if (p_shape == CURSOR_ARROW) {
  1619. if (mouse_mode == MOUSE_MODE_VISIBLE) {
  1620. SetCursor(cursors[p_shape]);
  1621. }
  1622. }
  1623. if (hAndMask != NULL) {
  1624. DeleteObject(hAndMask);
  1625. }
  1626. if (hXorMask != NULL) {
  1627. DeleteObject(hXorMask);
  1628. }
  1629. memfree(buffer);
  1630. DeleteObject(bitmap);
  1631. }
  1632. }
  1633. void OS_Windows::GetMaskBitmaps(HBITMAP hSourceBitmap, COLORREF clrTransparent, OUT HBITMAP &hAndMaskBitmap, OUT HBITMAP &hXorMaskBitmap) {
  1634. // Get the system display DC
  1635. HDC hDC = GetDC(NULL);
  1636. // Create helper DC
  1637. HDC hMainDC = CreateCompatibleDC(hDC);
  1638. HDC hAndMaskDC = CreateCompatibleDC(hDC);
  1639. HDC hXorMaskDC = CreateCompatibleDC(hDC);
  1640. // Get the dimensions of the source bitmap
  1641. BITMAP bm;
  1642. GetObject(hSourceBitmap, sizeof(BITMAP), &bm);
  1643. // Create the mask bitmaps
  1644. hAndMaskBitmap = CreateCompatibleBitmap(hDC, bm.bmWidth, bm.bmHeight); // color
  1645. hXorMaskBitmap = CreateCompatibleBitmap(hDC, bm.bmWidth, bm.bmHeight); // color
  1646. // Release the system display DC
  1647. ReleaseDC(NULL, hDC);
  1648. // Select the bitmaps to helper DC
  1649. HBITMAP hOldMainBitmap = (HBITMAP)SelectObject(hMainDC, hSourceBitmap);
  1650. HBITMAP hOldAndMaskBitmap = (HBITMAP)SelectObject(hAndMaskDC, hAndMaskBitmap);
  1651. HBITMAP hOldXorMaskBitmap = (HBITMAP)SelectObject(hXorMaskDC, hXorMaskBitmap);
  1652. // Assign the monochrome AND mask bitmap pixels so that a pixels of the source bitmap
  1653. // with 'clrTransparent' will be white pixels of the monochrome bitmap
  1654. SetBkColor(hMainDC, clrTransparent);
  1655. BitBlt(hAndMaskDC, 0, 0, bm.bmWidth, bm.bmHeight, hMainDC, 0, 0, SRCCOPY);
  1656. // Assign the color XOR mask bitmap pixels so that a pixels of the source bitmap
  1657. // with 'clrTransparent' will be black and rest the pixels same as corresponding
  1658. // pixels of the source bitmap
  1659. SetBkColor(hXorMaskDC, RGB(0, 0, 0));
  1660. SetTextColor(hXorMaskDC, RGB(255, 255, 255));
  1661. BitBlt(hXorMaskDC, 0, 0, bm.bmWidth, bm.bmHeight, hAndMaskDC, 0, 0, SRCCOPY);
  1662. BitBlt(hXorMaskDC, 0, 0, bm.bmWidth, bm.bmHeight, hMainDC, 0, 0, SRCAND);
  1663. // Deselect bitmaps from the helper DC
  1664. SelectObject(hMainDC, hOldMainBitmap);
  1665. SelectObject(hAndMaskDC, hOldAndMaskBitmap);
  1666. SelectObject(hXorMaskDC, hOldXorMaskBitmap);
  1667. // Delete the helper DC
  1668. DeleteDC(hXorMaskDC);
  1669. DeleteDC(hAndMaskDC);
  1670. DeleteDC(hMainDC);
  1671. }
  1672. Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, String *r_pipe, int *r_exitcode, bool read_stderr) {
  1673. if (p_blocking && r_pipe) {
  1674. String argss;
  1675. argss = "\"\"" + p_path + "\"";
  1676. for (const List<String>::Element *E = p_arguments.front(); E; E = E->next()) {
  1677. argss += String(" \"") + E->get() + "\"";
  1678. }
  1679. // print_line("ARGS: "+argss);
  1680. //argss+"\"";
  1681. //argss+=" 2>nul";
  1682. FILE *f = _wpopen(argss.c_str(), L"r");
  1683. ERR_FAIL_COND_V(!f, ERR_CANT_OPEN);
  1684. char buf[65535];
  1685. while (fgets(buf, 65535, f)) {
  1686. (*r_pipe) += buf;
  1687. }
  1688. int rv = _pclose(f);
  1689. if (r_exitcode)
  1690. *r_exitcode = rv;
  1691. return OK;
  1692. }
  1693. String cmdline = "\"" + p_path + "\"";
  1694. const List<String>::Element *I = p_arguments.front();
  1695. while (I) {
  1696. cmdline += " \"" + I->get() + "\"";
  1697. I = I->next();
  1698. };
  1699. //cmdline+="\"";
  1700. ProcessInfo pi;
  1701. ZeroMemory(&pi.si, sizeof(pi.si));
  1702. pi.si.cb = sizeof(pi.si);
  1703. ZeroMemory(&pi.pi, sizeof(pi.pi));
  1704. LPSTARTUPINFOW si_w = (LPSTARTUPINFOW)&pi.si;
  1705. print_line("running cmdline: " + cmdline);
  1706. Vector<CharType> modstr; //windows wants to change this no idea why
  1707. modstr.resize(cmdline.size());
  1708. for (int i = 0; i < cmdline.size(); i++)
  1709. modstr[i] = cmdline[i];
  1710. int ret = CreateProcessW(NULL, modstr.ptr(), NULL, NULL, 0, NORMAL_PRIORITY_CLASS, NULL, NULL, si_w, &pi.pi);
  1711. ERR_FAIL_COND_V(ret == 0, ERR_CANT_FORK);
  1712. if (p_blocking) {
  1713. DWORD ret = WaitForSingleObject(pi.pi.hProcess, INFINITE);
  1714. if (r_exitcode)
  1715. *r_exitcode = ret;
  1716. } else {
  1717. ProcessID pid = pi.pi.dwProcessId;
  1718. if (r_child_id) {
  1719. *r_child_id = pid;
  1720. };
  1721. process_map->insert(pid, pi);
  1722. };
  1723. return OK;
  1724. };
  1725. Error OS_Windows::kill(const ProcessID &p_pid) {
  1726. HANDLE h;
  1727. if (process_map->has(p_pid)) {
  1728. h = (*process_map)[p_pid].pi.hProcess;
  1729. process_map->erase(p_pid);
  1730. } else {
  1731. ERR_FAIL_COND_V(!process_map->has(p_pid), FAILED);
  1732. };
  1733. int ret = TerminateProcess(h, 0);
  1734. return ret != 0 ? OK : FAILED;
  1735. };
  1736. int OS_Windows::get_process_ID() const {
  1737. return _getpid();
  1738. }
  1739. Error OS_Windows::set_cwd(const String &p_cwd) {
  1740. if (_wchdir(p_cwd.c_str()) != 0)
  1741. return ERR_CANT_OPEN;
  1742. return OK;
  1743. }
  1744. String OS_Windows::get_executable_path() const {
  1745. wchar_t bufname[4096];
  1746. GetModuleFileNameW(NULL, bufname, 4096);
  1747. String s = bufname;
  1748. return s;
  1749. }
  1750. void OS_Windows::set_icon(const Image &p_icon) {
  1751. Image icon = p_icon;
  1752. if (icon.get_format() != Image::FORMAT_RGBA)
  1753. icon.convert(Image::FORMAT_RGBA);
  1754. int w = icon.get_width();
  1755. int h = icon.get_height();
  1756. /* Create temporary bitmap buffer */
  1757. int icon_len = 40 + h * w * 4;
  1758. Vector<BYTE> v;
  1759. v.resize(icon_len);
  1760. BYTE *icon_bmp = &v[0];
  1761. encode_uint32(40, &icon_bmp[0]);
  1762. encode_uint32(w, &icon_bmp[4]);
  1763. encode_uint32(h * 2, &icon_bmp[8]);
  1764. encode_uint16(1, &icon_bmp[12]);
  1765. encode_uint16(32, &icon_bmp[14]);
  1766. encode_uint32(BI_RGB, &icon_bmp[16]);
  1767. encode_uint32(w * h * 4, &icon_bmp[20]);
  1768. encode_uint32(0, &icon_bmp[24]);
  1769. encode_uint32(0, &icon_bmp[28]);
  1770. encode_uint32(0, &icon_bmp[32]);
  1771. encode_uint32(0, &icon_bmp[36]);
  1772. uint8_t *wr = &icon_bmp[40];
  1773. DVector<uint8_t>::Read r = icon.get_data().read();
  1774. for (int i = 0; i < h; i++) {
  1775. for (int j = 0; j < w; j++) {
  1776. const uint8_t *rpx = &r[((h - i - 1) * w + j) * 4];
  1777. uint8_t *wpx = &wr[(i * w + j) * 4];
  1778. wpx[0] = rpx[2];
  1779. wpx[1] = rpx[1];
  1780. wpx[2] = rpx[0];
  1781. wpx[3] = rpx[3];
  1782. }
  1783. }
  1784. HICON hicon = CreateIconFromResource(icon_bmp, icon_len, TRUE, 0x00030000);
  1785. /* Set the icon for the window */
  1786. SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM)hicon);
  1787. /* Set the icon in the task manager (should we do this?) */
  1788. SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM)hicon);
  1789. }
  1790. bool OS_Windows::has_environment(const String &p_var) const {
  1791. return getenv(p_var.utf8().get_data()) != NULL;
  1792. };
  1793. String OS_Windows::get_environment(const String &p_var) const {
  1794. wchar_t wval[0x7Fff]; // MSDN says 32767 char is the maximum
  1795. int wlen = GetEnvironmentVariableW(p_var.c_str(), wval, 0x7Fff);
  1796. if (wlen > 0) {
  1797. return wval;
  1798. }
  1799. return "";
  1800. }
  1801. String OS_Windows::get_stdin_string(bool p_block) {
  1802. if (p_block) {
  1803. char buff[1024];
  1804. return fgets(buff, 1024, stdin);
  1805. };
  1806. return String();
  1807. }
  1808. void OS_Windows::enable_for_stealing_focus(ProcessID pid) {
  1809. AllowSetForegroundWindow(pid);
  1810. }
  1811. void OS_Windows::move_window_to_foreground() {
  1812. SetForegroundWindow(hWnd);
  1813. }
  1814. Error OS_Windows::shell_open(String p_uri) {
  1815. ShellExecuteW(NULL, L"open", p_uri.c_str(), NULL, NULL, SW_SHOWNORMAL);
  1816. return OK;
  1817. }
  1818. String OS_Windows::get_locale() const {
  1819. const _WinLocale *wl = &_win_locales[0];
  1820. LANGID langid = GetUserDefaultUILanguage();
  1821. String neutral;
  1822. int lang = langid & ((1 << 9) - 1);
  1823. int sublang = langid & ~((1 << 9) - 1);
  1824. while (wl->locale) {
  1825. if (wl->main_lang == lang && wl->sublang == SUBLANG_NEUTRAL)
  1826. neutral = wl->locale;
  1827. if (lang == wl->main_lang && sublang == wl->sublang)
  1828. return wl->locale;
  1829. wl++;
  1830. }
  1831. if (neutral != "")
  1832. return neutral;
  1833. return "en";
  1834. }
  1835. OS::LatinKeyboardVariant OS_Windows::get_latin_keyboard_variant() const {
  1836. unsigned long azerty[] = {
  1837. 0x00020401, // Arabic (102) AZERTY
  1838. 0x0001080c, // Belgian (Comma)
  1839. 0x0000080c, // Belgian French
  1840. 0x0000040c, // French
  1841. 0 // <--- STOP MARK
  1842. };
  1843. unsigned long qwertz[] = {
  1844. 0x0000041a, // Croation
  1845. 0x00000405, // Czech
  1846. 0x00000407, // German
  1847. 0x00010407, // German (IBM)
  1848. 0x0000040e, // Hungarian
  1849. 0x0000046e, // Luxembourgish
  1850. 0x00010415, // Polish (214)
  1851. 0x00000418, // Romanian (Legacy)
  1852. 0x0000081a, // Serbian (Latin)
  1853. 0x0000041b, // Slovak
  1854. 0x00000424, // Slovenian
  1855. 0x0001042e, // Sorbian Extended
  1856. 0x0002042e, // Sorbian Standard
  1857. 0x0000042e, // Sorbian Standard (Legacy)
  1858. 0x0000100c, // Swiss French
  1859. 0x00000807, // Swiss German
  1860. 0 // <--- STOP MARK
  1861. };
  1862. unsigned long dvorak[] = {
  1863. 0x00010409, // US-Dvorak
  1864. 0x00030409, // US-Dvorak for left hand
  1865. 0x00040409, // US-Dvorak for right hand
  1866. 0 // <--- STOP MARK
  1867. };
  1868. char name[KL_NAMELENGTH + 1];
  1869. name[0] = 0;
  1870. GetKeyboardLayoutNameA(name);
  1871. unsigned long hex = strtoul(name, NULL, 16);
  1872. int i = 0;
  1873. while (azerty[i] != 0) {
  1874. if (azerty[i] == hex) return LATIN_KEYBOARD_AZERTY;
  1875. i++;
  1876. }
  1877. i = 0;
  1878. while (qwertz[i] != 0) {
  1879. if (qwertz[i] == hex) return LATIN_KEYBOARD_QWERTZ;
  1880. i++;
  1881. }
  1882. i = 0;
  1883. while (dvorak[i] != 0) {
  1884. if (dvorak[i] == hex) return LATIN_KEYBOARD_DVORAK;
  1885. i++;
  1886. }
  1887. return LATIN_KEYBOARD_QWERTY;
  1888. }
  1889. void OS_Windows::release_rendering_thread() {
  1890. gl_context->release_current();
  1891. }
  1892. void OS_Windows::make_rendering_thread() {
  1893. gl_context->make_current();
  1894. }
  1895. void OS_Windows::swap_buffers() {
  1896. gl_context->swap_buffers();
  1897. }
  1898. void OS_Windows::run() {
  1899. if (!main_loop)
  1900. return;
  1901. main_loop->init();
  1902. uint64_t last_ticks = get_ticks_usec();
  1903. int frames = 0;
  1904. uint64_t frame = 0;
  1905. while (!force_quit) {
  1906. process_events(); // get rid of pending events
  1907. if (Main::iteration() == true)
  1908. break;
  1909. };
  1910. main_loop->finish();
  1911. }
  1912. MainLoop *OS_Windows::get_main_loop() const {
  1913. return main_loop;
  1914. }
  1915. String OS_Windows::get_system_dir(SystemDir p_dir) const {
  1916. int id;
  1917. switch (p_dir) {
  1918. case SYSTEM_DIR_DESKTOP: {
  1919. id = CSIDL_DESKTOPDIRECTORY;
  1920. } break;
  1921. case SYSTEM_DIR_DCIM: {
  1922. id = CSIDL_MYPICTURES;
  1923. } break;
  1924. case SYSTEM_DIR_DOCUMENTS: {
  1925. id = CSIDL_PERSONAL;
  1926. } break;
  1927. case SYSTEM_DIR_DOWNLOADS: {
  1928. id = 0x000C;
  1929. } break;
  1930. case SYSTEM_DIR_MOVIES: {
  1931. id = CSIDL_MYVIDEO;
  1932. } break;
  1933. case SYSTEM_DIR_MUSIC: {
  1934. id = CSIDL_MYMUSIC;
  1935. } break;
  1936. case SYSTEM_DIR_PICTURES: {
  1937. id = CSIDL_MYPICTURES;
  1938. } break;
  1939. case SYSTEM_DIR_RINGTONES: {
  1940. id = CSIDL_MYMUSIC;
  1941. } break;
  1942. }
  1943. WCHAR szPath[MAX_PATH];
  1944. HRESULT res = SHGetFolderPathW(NULL, id, NULL, 0, szPath);
  1945. ERR_FAIL_COND_V(res != S_OK, String());
  1946. return String(szPath);
  1947. }
  1948. String OS_Windows::get_data_dir() const {
  1949. String an = get_safe_application_name();
  1950. if (an != "") {
  1951. if (has_environment("APPDATA")) {
  1952. bool use_godot = Globals::get_singleton()->get("application/use_shared_user_dir");
  1953. if (!use_godot)
  1954. return (OS::get_singleton()->get_environment("APPDATA") + "/" + an).replace("\\", "/");
  1955. else
  1956. return (OS::get_singleton()->get_environment("APPDATA") + "/Godot/app_userdata/" + an).replace("\\", "/");
  1957. }
  1958. }
  1959. return Globals::get_singleton()->get_resource_path();
  1960. }
  1961. bool OS_Windows::is_joy_known(int p_device) {
  1962. return input->is_joy_mapped(p_device);
  1963. }
  1964. String OS_Windows::get_joy_guid(int p_device) const {
  1965. return input->get_joy_guid_remapped(p_device);
  1966. }
  1967. void OS_Windows::set_use_vsync(bool p_enable) {
  1968. if (gl_context)
  1969. gl_context->set_use_vsync(p_enable);
  1970. }
  1971. bool OS_Windows::is_vsync_enabled() const {
  1972. if (gl_context)
  1973. return gl_context->is_using_vsync();
  1974. return true;
  1975. }
  1976. void OS_Windows::disable_crash_handler() {
  1977. crash_handler.disable();
  1978. }
  1979. bool OS_Windows::is_disable_crash_handler() const {
  1980. return crash_handler.is_disabled();
  1981. }
  1982. Error OS_Windows::move_path_to_trash(String p_dir) {
  1983. SHFILEOPSTRUCTA sf;
  1984. TCHAR *from = new TCHAR[p_dir.length() + 2];
  1985. strcpy(from, p_dir.utf8().get_data());
  1986. from[p_dir.length()] = 0;
  1987. from[p_dir.length() + 1] = 0;
  1988. sf.hwnd = hWnd;
  1989. sf.wFunc = FO_DELETE;
  1990. sf.pFrom = from;
  1991. sf.pTo = NULL;
  1992. sf.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMATION;
  1993. sf.fAnyOperationsAborted = FALSE;
  1994. sf.hNameMappings = NULL;
  1995. sf.lpszProgressTitle = NULL;
  1996. int ret = SHFileOperation(&sf);
  1997. delete[] from;
  1998. if (ret) {
  1999. ERR_PRINTS("SHFileOperation error: " + itos(ret));
  2000. return FAILED;
  2001. }
  2002. return OK;
  2003. }
  2004. OS_Windows::OS_Windows(HINSTANCE _hInstance) {
  2005. key_event_pos = 0;
  2006. force_quit = false;
  2007. alt_mem = false;
  2008. gr_mem = false;
  2009. shift_mem = false;
  2010. control_mem = false;
  2011. meta_mem = false;
  2012. minimized = false;
  2013. hInstance = _hInstance;
  2014. pressrc = 0;
  2015. old_invalid = true;
  2016. last_id = 0;
  2017. mouse_mode = MOUSE_MODE_VISIBLE;
  2018. #ifdef STDOUT_FILE
  2019. stdo = fopen("stdout.txt", "wb");
  2020. #endif
  2021. user_proc = NULL;
  2022. #ifdef WASAPI_ENABLED
  2023. AudioDriverManagerSW::add_driver(&driver_wasapi);
  2024. #endif
  2025. #ifdef RTAUDIO_ENABLED
  2026. AudioDriverManagerSW::add_driver(&driver_rtaudio);
  2027. #endif
  2028. }
  2029. OS_Windows::~OS_Windows() {
  2030. #ifdef STDOUT_FILE
  2031. fclose(stdo);
  2032. #endif
  2033. }