os_windows.cpp 53 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324
  1. /*************************************************************************/
  2. /* os_windows.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* http://www.godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
  9. /* */
  10. /* Permission is hereby granted, free of charge, to any person obtaining */
  11. /* a copy of this software and associated documentation files (the */
  12. /* "Software"), to deal in the Software without restriction, including */
  13. /* without limitation the rights to use, copy, modify, merge, publish, */
  14. /* distribute, sublicense, and/or sell copies of the Software, and to */
  15. /* permit persons to whom the Software is furnished to do so, subject to */
  16. /* the following conditions: */
  17. /* */
  18. /* The above copyright notice and this permission notice shall be */
  19. /* included in all copies or substantial portions of the Software. */
  20. /* */
  21. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  22. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  23. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
  24. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  25. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  26. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  27. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  28. /*************************************************************************/
  29. #include "drivers/gles2/rasterizer_gles2.h"
  30. #include "os_windows.h"
  31. #include "drivers/nedmalloc/memory_pool_static_nedmalloc.h"
  32. #include "drivers/unix/memory_pool_static_malloc.h"
  33. #include "os/memory_pool_dynamic_static.h"
  34. #include "drivers/windows/thread_windows.h"
  35. #include "drivers/windows/semaphore_windows.h"
  36. #include "drivers/windows/mutex_windows.h"
  37. #include "main/main.h"
  38. #include "drivers/windows/file_access_windows.h"
  39. #include "drivers/windows/dir_access_windows.h"
  40. #include "servers/visual/visual_server_raster.h"
  41. #include "servers/audio/audio_server_sw.h"
  42. #include "servers/visual/visual_server_wrap_mt.h"
  43. #include "tcp_server_winsock.h"
  44. #include "packet_peer_udp_winsock.h"
  45. #include "stream_peer_winsock.h"
  46. #include "os/pc_joystick_map.h"
  47. #include "lang_table.h"
  48. #include "os/memory_pool_dynamic_prealloc.h"
  49. #include "globals.h"
  50. #include "io/marshalls.h"
  51. #include "shlobj.h"
  52. #include <regstr.h>
  53. static const WORD MAX_CONSOLE_LINES = 1500;
  54. extern "C" {
  55. #ifdef _MSC_VER
  56. _declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
  57. #else
  58. __attribute__((visibility("default"))) DWORD NvOptimusEnablement = 0x00000001;
  59. #endif
  60. }
  61. //#define STDOUT_FILE
  62. extern HINSTANCE godot_hinstance;
  63. void RedirectIOToConsole() {
  64. int hConHandle;
  65. intptr_t lStdHandle;
  66. CONSOLE_SCREEN_BUFFER_INFO coninfo;
  67. FILE *fp;
  68. // allocate a console for this app
  69. AllocConsole();
  70. // set the screen buffer to be big enough to let us scroll text
  71. GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE),
  72. &coninfo);
  73. coninfo.dwSize.Y = MAX_CONSOLE_LINES;
  74. SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE),
  75. coninfo.dwSize);
  76. // redirect unbuffered STDOUT to the console
  77. lStdHandle = (intptr_t)GetStdHandle(STD_OUTPUT_HANDLE);
  78. hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
  79. fp = _fdopen( hConHandle, "w" );
  80. *stdout = *fp;
  81. setvbuf( stdout, NULL, _IONBF, 0 );
  82. // redirect unbuffered STDIN to the console
  83. lStdHandle = (intptr_t)GetStdHandle(STD_INPUT_HANDLE);
  84. hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
  85. fp = _fdopen( hConHandle, "r" );
  86. *stdin = *fp;
  87. setvbuf( stdin, NULL, _IONBF, 0 );
  88. // redirect unbuffered STDERR to the console
  89. lStdHandle = (intptr_t)GetStdHandle(STD_ERROR_HANDLE);
  90. hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
  91. fp = _fdopen( hConHandle, "w" );
  92. *stderr = *fp;
  93. setvbuf( stderr, NULL, _IONBF, 0 );
  94. // make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog
  95. // point to console as well
  96. }
  97. int OS_Windows::get_video_driver_count() const {
  98. return 1;
  99. }
  100. const char * OS_Windows::get_video_driver_name(int p_driver) const {
  101. return "GLES2";
  102. }
  103. OS::VideoMode OS_Windows::get_default_video_mode() const {
  104. return VideoMode(800,600,false);
  105. }
  106. int OS_Windows::get_audio_driver_count() const {
  107. return AudioDriverManagerSW::get_driver_count();
  108. }
  109. const char * OS_Windows::get_audio_driver_name(int p_driver) const {
  110. AudioDriverSW* driver = AudioDriverManagerSW::get_driver(p_driver);
  111. ERR_FAIL_COND_V( !driver, "" );
  112. return AudioDriverManagerSW::get_driver(p_driver)->get_name();
  113. }
  114. static MemoryPoolStatic *mempool_static=NULL;
  115. static MemoryPoolDynamic *mempool_dynamic=NULL;
  116. void OS_Windows::initialize_core() {
  117. last_button_state=0;
  118. //RedirectIOToConsole();
  119. maximized=false;
  120. minimized=false;
  121. ThreadWindows::make_default();
  122. SemaphoreWindows::make_default();
  123. MutexWindows::make_default();
  124. FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_RESOURCES);
  125. FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_USERDATA);
  126. FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_FILESYSTEM);
  127. //FileAccessBufferedFA<FileAccessWindows>::make_default();
  128. DirAccess::make_default<DirAccessWindows>(DirAccess::ACCESS_RESOURCES);
  129. DirAccess::make_default<DirAccessWindows>(DirAccess::ACCESS_USERDATA);
  130. DirAccess::make_default<DirAccessWindows>(DirAccess::ACCESS_FILESYSTEM);
  131. TCPServerWinsock::make_default();
  132. StreamPeerWinsock::make_default();
  133. PacketPeerUDPWinsock::make_default();
  134. mempool_static = new MemoryPoolStaticMalloc;
  135. #if 1
  136. mempool_dynamic = memnew( MemoryPoolDynamicStatic );
  137. #else
  138. #define DYNPOOL_SIZE 4*1024*1024
  139. void * buffer = malloc( DYNPOOL_SIZE );
  140. mempool_dynamic = memnew( MemoryPoolDynamicPrealloc(buffer,DYNPOOL_SIZE) );
  141. #endif
  142. // We need to know how often the clock is updated
  143. if( !QueryPerformanceFrequency((LARGE_INTEGER *)&ticks_per_second) )
  144. ticks_per_second = 1000;
  145. // If timeAtGameStart is 0 then we get the time since
  146. // the start of the computer when we call GetGameTime()
  147. ticks_start = 0;
  148. ticks_start = get_ticks_usec();
  149. process_map = memnew((Map<ProcessID, ProcessInfo>));
  150. IP_Unix::make_default();
  151. cursor_shape=CURSOR_ARROW;
  152. }
  153. bool OS_Windows::can_draw() const {
  154. return !minimized;
  155. };
  156. #define MI_WP_SIGNATURE 0xFF515700
  157. #define SIGNATURE_MASK 0xFFFFFF00
  158. #define IsPenEvent(dw) (((dw) & SIGNATURE_MASK) == MI_WP_SIGNATURE)
  159. void OS_Windows::_touch_event(bool p_pressed, int p_x, int p_y, int idx) {
  160. InputEvent event;
  161. event.type = InputEvent::SCREEN_TOUCH;
  162. event.ID=++last_id;
  163. event.screen_touch.index = idx;
  164. event.screen_touch.pressed = p_pressed;
  165. event.screen_touch.x=p_x;
  166. event.screen_touch.y=p_y;
  167. if (main_loop) {
  168. input->parse_input_event(event);
  169. }
  170. };
  171. void OS_Windows::_drag_event(int p_x, int p_y, int idx) {
  172. InputEvent event;
  173. event.type = InputEvent::SCREEN_DRAG;
  174. event.ID=++last_id;
  175. event.screen_drag.index = idx;
  176. event.screen_drag.x=p_x;
  177. event.screen_drag.y=p_y;
  178. if (main_loop)
  179. input->parse_input_event(event);
  180. };
  181. LRESULT OS_Windows::WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) {
  182. switch (uMsg) // Check For Windows Messages
  183. {
  184. case WM_ACTIVATE: // Watch For Window Activate Message
  185. {
  186. minimized = HIWORD(wParam) != 0;
  187. if (!main_loop) {
  188. return 0;
  189. };
  190. if (LOWORD(wParam) == WA_ACTIVE || LOWORD(wParam) == WA_CLICKACTIVE) {
  191. main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_IN);
  192. alt_mem=false;
  193. control_mem=false;
  194. shift_mem=false;
  195. if (mouse_mode==MOUSE_MODE_CAPTURED) {
  196. RECT clipRect;
  197. GetClientRect(hWnd, &clipRect);
  198. ClientToScreen(hWnd, (POINT*) &clipRect.left);
  199. ClientToScreen(hWnd, (POINT*) &clipRect.right);
  200. ClipCursor(&clipRect);
  201. SetCapture(hWnd);
  202. }
  203. } else {
  204. main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT);
  205. alt_mem=false;
  206. };
  207. return 0; // Return To The Message Loop
  208. }
  209. case WM_PAINT:
  210. Main::force_redraw();
  211. break;
  212. case WM_SYSCOMMAND: // Intercept System Commands
  213. {
  214. switch (wParam) // Check System Calls
  215. {
  216. case SC_SCREENSAVE: // Screensaver Trying To Start?
  217. case SC_MONITORPOWER: // Monitor Trying To Enter Powersave?
  218. return 0; // Prevent From Happening
  219. case SC_KEYMENU:
  220. if ((lParam>>16)<=0)
  221. return 0;
  222. }
  223. break; // Exit
  224. }
  225. case WM_CLOSE: // Did We Receive A Close Message?
  226. {
  227. if (main_loop)
  228. main_loop->notification(MainLoop::NOTIFICATION_WM_QUIT_REQUEST);
  229. //force_quit=true;
  230. return 0; // Jump Back
  231. }
  232. case WM_MOUSELEAVE: {
  233. old_invalid=true;
  234. outside=true;
  235. } break;
  236. case WM_MOUSEMOVE: {
  237. if (outside) {
  238. CursorShape c=cursor_shape;
  239. cursor_shape=CURSOR_MAX;
  240. set_cursor_shape(c);
  241. outside=false;
  242. //Once-Off notification, must call again....
  243. TRACKMOUSEEVENT tme;
  244. tme.cbSize=sizeof(TRACKMOUSEEVENT);
  245. tme.dwFlags=TME_LEAVE;
  246. tme.hwndTrack=hWnd;
  247. tme.dwHoverTime=HOVER_DEFAULT;
  248. TrackMouseEvent(&tme);
  249. }
  250. /*
  251. LPARAM extra = GetMessageExtraInfo();
  252. if (IsPenEvent(extra)) {
  253. int idx = extra & 0x7f;
  254. _drag_event(idx, uMsg, wParam, lParam);
  255. if (idx != 0) {
  256. return 0;
  257. };
  258. // fallthrough for mouse event
  259. };
  260. */
  261. InputEvent event;
  262. event.type=InputEvent::MOUSE_MOTION;
  263. event.ID=++last_id;
  264. InputEventMouseMotion &mm=event.mouse_motion;
  265. mm.mod.control=(wParam&MK_CONTROL)!=0;
  266. mm.mod.shift=(wParam&MK_SHIFT)!=0;
  267. mm.mod.alt=alt_mem;
  268. mm.button_mask|=(wParam&MK_LBUTTON)?(1<<0):0;
  269. mm.button_mask|=(wParam&MK_RBUTTON)?(1<<1):0;
  270. mm.button_mask|=(wParam&MK_MBUTTON)?(1<<2):0;
  271. last_button_state=mm.button_mask;
  272. /*mm.button_mask|=(wParam&MK_XBUTTON1)?(1<<5):0;
  273. mm.button_mask|=(wParam&MK_XBUTTON2)?(1<<6):0;*/
  274. mm.x=GET_X_LPARAM(lParam);
  275. mm.y=GET_Y_LPARAM(lParam);
  276. if (mouse_mode==MOUSE_MODE_CAPTURED) {
  277. Point2i c(video_mode.width/2,video_mode.height/2);
  278. if (Point2i(mm.x,mm.y)==c) {
  279. center=c;
  280. return 0;
  281. }
  282. Point2i ncenter(mm.x,mm.y);
  283. mm.x = old_x + (mm.x-center.x);
  284. mm.y = old_y + (mm.y-center.y);
  285. center=ncenter;
  286. POINT pos = { (int) c.x, (int) c.y };
  287. ClientToScreen(hWnd, &pos);
  288. SetCursorPos(pos.x, pos.y);
  289. }
  290. input->set_mouse_pos(Point2(mm.x,mm.y));
  291. mm.speed_x=input->get_mouse_speed().x;
  292. mm.speed_y=input->get_mouse_speed().y;
  293. if (old_invalid) {
  294. old_x=mm.x;
  295. old_y=mm.y;
  296. old_invalid=false;
  297. }
  298. mm.relative_x=mm.x-old_x;
  299. mm.relative_y=mm.y-old_y;
  300. old_x=mm.x;
  301. old_y=mm.y;
  302. if (main_loop)
  303. input->parse_input_event(event);
  304. } break;
  305. case WM_LBUTTONDOWN:
  306. case WM_LBUTTONUP:
  307. case WM_MBUTTONDOWN:
  308. case WM_MBUTTONUP:
  309. case WM_RBUTTONDOWN:
  310. case WM_RBUTTONUP:
  311. case WM_MOUSEWHEEL:
  312. case WM_LBUTTONDBLCLK:
  313. case WM_RBUTTONDBLCLK:
  314. /*case WM_XBUTTONDOWN:
  315. case WM_XBUTTONUP: */{
  316. /*
  317. LPARAM extra = GetMessageExtraInfo();
  318. if (IsPenEvent(extra)) {
  319. int idx = extra & 0x7f;
  320. _touch_event(idx, uMsg, wParam, lParam);
  321. if (idx != 0) {
  322. return 0;
  323. };
  324. // fallthrough for mouse event
  325. };
  326. */
  327. InputEvent event;
  328. event.type=InputEvent::MOUSE_BUTTON;
  329. event.ID=++last_id;
  330. InputEventMouseButton &mb=event.mouse_button;
  331. switch (uMsg) {
  332. case WM_LBUTTONDOWN: {
  333. mb.pressed=true;
  334. mb.button_index=1;
  335. } break;
  336. case WM_LBUTTONUP: {
  337. mb.pressed=false;
  338. mb.button_index=1;
  339. } break;
  340. case WM_MBUTTONDOWN: {
  341. mb.pressed=true;
  342. mb.button_index=3;
  343. } break;
  344. case WM_MBUTTONUP: {
  345. mb.pressed=false;
  346. mb.button_index=3;
  347. } break;
  348. case WM_RBUTTONDOWN: {
  349. mb.pressed=true;
  350. mb.button_index=2;
  351. } break;
  352. case WM_RBUTTONUP: {
  353. mb.pressed=false;
  354. mb.button_index=2;
  355. } break;
  356. case WM_LBUTTONDBLCLK: {
  357. mb.pressed=true;
  358. mb.button_index=1;
  359. mb.doubleclick = true;
  360. } break;
  361. case WM_RBUTTONDBLCLK: {
  362. mb.pressed=true;
  363. mb.button_index=2;
  364. mb.doubleclick = true;
  365. } break;
  366. case WM_MOUSEWHEEL: {
  367. mb.pressed=true;
  368. int motion = (short)HIWORD(wParam);
  369. if (!motion)
  370. return 0;
  371. if (motion>0)
  372. mb.button_index=4;
  373. else
  374. mb.button_index=5;
  375. } break;
  376. /*
  377. case WM_XBUTTONDOWN: {
  378. mb.pressed=true;
  379. mb.button_index=(HIWORD(wParam)==XBUTTON1)?6:7;
  380. } break;
  381. case WM_XBUTTONUP:
  382. mb.pressed=true;
  383. mb.button_index=(HIWORD(wParam)==XBUTTON1)?6:7;
  384. } break;*/
  385. default: { return 0; }
  386. }
  387. mb.mod.control=(wParam&MK_CONTROL)!=0;
  388. mb.mod.shift=(wParam&MK_SHIFT)!=0;
  389. mb.mod.alt=alt_mem;
  390. //mb.mod.alt=(wParam&MK_MENU)!=0;
  391. mb.button_mask|=(wParam&MK_LBUTTON)?(1<<0):0;
  392. mb.button_mask|=(wParam&MK_RBUTTON)?(1<<1):0;
  393. mb.button_mask|=(wParam&MK_MBUTTON)?(1<<2):0;
  394. last_button_state=mb.button_mask;
  395. /*
  396. mb.button_mask|=(wParam&MK_XBUTTON1)?(1<<5):0;
  397. mb.button_mask|=(wParam&MK_XBUTTON2)?(1<<6):0;*/
  398. mb.x=GET_X_LPARAM(lParam);
  399. mb.y=GET_Y_LPARAM(lParam);
  400. if (mouse_mode==MOUSE_MODE_CAPTURED) {
  401. mb.x=old_x;
  402. mb.y=old_y;
  403. }
  404. mb.global_x=mb.x;
  405. mb.global_y=mb.y;
  406. if (uMsg != WM_MOUSEWHEEL) {
  407. if (mb.pressed) {
  408. if (++pressrc>0)
  409. SetCapture(hWnd);
  410. } else {
  411. if (--pressrc<=0) {
  412. ReleaseCapture();
  413. pressrc=0;
  414. }
  415. }
  416. } else if (mouse_mode!=MOUSE_MODE_CAPTURED) {
  417. // for reasons unknown to mankind, wheel comes in screen cordinates
  418. RECT rect;
  419. GetWindowRect(hWnd,&rect);
  420. mb.x-=rect.left;
  421. mb.y-=rect.top;
  422. }
  423. if (main_loop) {
  424. input->parse_input_event(event);
  425. if (mb.pressed && mb.button_index>3) {
  426. //send release for mouse wheel
  427. mb.pressed=false;
  428. event.ID=++last_id;
  429. input->parse_input_event(event);
  430. }
  431. }
  432. } break;
  433. case WM_SIZE: {
  434. video_mode.width=LOWORD(lParam);
  435. video_mode.height=HIWORD(lParam);
  436. //return 0; // Jump Back
  437. } break;
  438. case WM_SYSKEYDOWN:
  439. case WM_SYSKEYUP:
  440. case WM_KEYUP:
  441. case WM_KEYDOWN: {
  442. if (wParam==VK_SHIFT)
  443. shift_mem=uMsg==WM_KEYDOWN;
  444. if (wParam==VK_CONTROL)
  445. control_mem=uMsg==WM_KEYDOWN;
  446. if (wParam==VK_MENU) {
  447. alt_mem=(uMsg==WM_KEYDOWN || uMsg==WM_SYSKEYDOWN);
  448. if (lParam&(1<<24))
  449. gr_mem=alt_mem;
  450. }
  451. //if (wParam==VK_WIN) TODO wtf is this?
  452. // meta_mem=uMsg==WM_KEYDOWN;
  453. } //fallthrough
  454. case WM_CHAR: {
  455. ERR_BREAK(key_event_pos >= KEY_EVENT_BUFFER_SIZE);
  456. // Make sure we don't include modifiers for the modifier key itself.
  457. KeyEvent ke;
  458. ke.mod_state.shift= (wParam != VK_SHIFT) ? shift_mem : false;
  459. ke.mod_state.alt= (! (wParam == VK_MENU && (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN))) ? alt_mem : false;
  460. ke.mod_state.control= (wParam != VK_CONTROL) ? control_mem : false;
  461. ke.mod_state.meta=meta_mem;
  462. ke.uMsg=uMsg;
  463. if (ke.uMsg==WM_SYSKEYDOWN)
  464. ke.uMsg=WM_KEYDOWN;
  465. if (ke.uMsg==WM_SYSKEYUP)
  466. ke.uMsg=WM_KEYUP;
  467. /*if (ke.uMsg==WM_KEYDOWN && alt_mem && uMsg!=WM_SYSKEYDOWN) {
  468. //altgr hack for intl keyboards, not sure how good it is
  469. //windows is weeeeird
  470. ke.mod_state.alt=false;
  471. ke.mod_state.control=false;
  472. print_line("")
  473. }*/
  474. ke.wParam=wParam;
  475. ke.lParam=lParam;
  476. key_event_buffer[key_event_pos++]=ke;
  477. } break;
  478. case WM_INPUTLANGCHANGEREQUEST: {
  479. print_line("input lang change");
  480. } break;
  481. #if WINVER >= 0x0700 // for windows 7
  482. case WM_TOUCH: {
  483. BOOL bHandled = FALSE;
  484. UINT cInputs = LOWORD(wParam);
  485. PTOUCHINPUT pInputs = memnew_arr(TOUCHINPUT, cInputs);
  486. if (pInputs){
  487. if (GetTouchInputInfo((HTOUCHINPUT)lParam, cInputs, pInputs, sizeof(TOUCHINPUT))){
  488. for (UINT i=0; i < cInputs; i++){
  489. TOUCHINPUT ti = pInputs[i];
  490. //do something with each touch input entry
  491. if (ti.dwFlags & TOUCHEVENTF_MOVE) {
  492. _drag_event(ti.x / 100, ti.y / 100, ti.dwID);
  493. } else if (ti.dwFlags & (TOUCHEVENTF_UP | TOUCHEVENTF_DOWN)) {
  494. _touch_event(ti.dwFlags & TOUCHEVENTF_DOWN != 0, ti.x / 100, ti.y / 100, ti.dwID);
  495. };
  496. }
  497. bHandled = TRUE;
  498. }else{
  499. /* handle the error here */
  500. }
  501. memdelete_arr(pInputs);
  502. }else{
  503. /* handle the error here, probably out of memory */
  504. }
  505. if (bHandled) {
  506. CloseTouchInputHandle((HTOUCHINPUT)lParam);
  507. return 0;
  508. };
  509. } break;
  510. #endif
  511. default: {
  512. if (user_proc) {
  513. return CallWindowProcW(user_proc, hWnd, uMsg, wParam, lParam);
  514. };
  515. };
  516. }
  517. return DefWindowProcW(hWnd,uMsg,wParam,lParam);
  518. }
  519. LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) {
  520. OS_Windows *os_win = static_cast<OS_Windows*>(OS::get_singleton());
  521. if (os_win)
  522. return os_win->WndProc(hWnd,uMsg,wParam,lParam);
  523. else
  524. return DefWindowProcW(hWnd,uMsg,wParam,lParam);
  525. }
  526. String OS_Windows::get_joystick_name(int id, JOYCAPS jcaps)
  527. {
  528. char buffer [256];
  529. char OEM [256];
  530. HKEY hKey;
  531. DWORD sz;
  532. int res;
  533. _snprintf(buffer, sizeof(buffer), "%s\\%s\\%s",
  534. REGSTR_PATH_JOYCONFIG, jcaps.szRegKey,
  535. REGSTR_KEY_JOYCURR );
  536. res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, buffer, 0, KEY_QUERY_VALUE, &hKey);
  537. if (res != ERROR_SUCCESS)
  538. {
  539. res = RegOpenKeyEx(HKEY_CURRENT_USER, buffer, 0, KEY_QUERY_VALUE, &hKey);
  540. if (res != ERROR_SUCCESS)
  541. return "";
  542. }
  543. sz = sizeof(OEM);
  544. _snprintf( buffer, sizeof(buffer), "Joystick%d%s", id + 1, REGSTR_VAL_JOYOEMNAME);
  545. res = RegQueryValueEx ( hKey, buffer, 0, 0, (LPBYTE) OEM, &sz);
  546. RegCloseKey ( hKey );
  547. if (res != ERROR_SUCCESS)
  548. return "";
  549. _snprintf( buffer, sizeof(buffer), "%s\\%s", REGSTR_PATH_JOYOEM, OEM);
  550. res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, buffer, 0, KEY_QUERY_VALUE, &hKey);
  551. if (res != ERROR_SUCCESS)
  552. {
  553. res = RegOpenKeyEx(HKEY_CURRENT_USER, buffer, 0, KEY_QUERY_VALUE, &hKey);
  554. if (res != ERROR_SUCCESS)
  555. return "";
  556. }
  557. sz = sizeof(buffer);
  558. res = RegQueryValueEx(hKey, REGSTR_VAL_JOYOEMNAME, 0, 0, (LPBYTE) buffer,
  559. &sz);
  560. RegCloseKey(hKey);
  561. if (res != ERROR_SUCCESS)
  562. return "";
  563. return String(buffer);
  564. }
  565. void OS_Windows::probe_joysticks() {
  566. static uint32_t last_attached = 0;
  567. int device_count = joyGetNumDevs();
  568. JOYINFOEX jinfo;
  569. jinfo.dwSize = sizeof(JOYINFOEX);
  570. jinfo.dwFlags = JOY_RETURNALL;
  571. for (int i=0; i<JOYSTICKS_MAX; i++) {
  572. Joystick joy;
  573. joy.id = i;
  574. joy.attached = (device_count > 0) && (joyGetPosEx(JOYSTICKID1 + i, &jinfo) == JOYERR_NOERROR);
  575. if (joy.attached == (last_attached & (1 << i) != 0)) {
  576. continue;
  577. };
  578. // there's been a change since last call
  579. if (joy.attached)
  580. last_attached = last_attached | (1 << i);
  581. else
  582. last_attached &= ~(1 << i);
  583. if (joy.attached) {
  584. joy.last_buttons = jinfo.dwButtons;
  585. joy.last_axis[0] = jinfo.dwXpos;
  586. joy.last_axis[1] = jinfo.dwYpos;
  587. joy.last_axis[2] = jinfo.dwZpos;
  588. joy.last_axis[3] = jinfo.dwRpos;
  589. joy.last_axis[4] = jinfo.dwUpos;
  590. joy.last_axis[5] = jinfo.dwVpos;
  591. JOYCAPS jcaps;
  592. MMRESULT res = joyGetDevCaps(JOYSTICKID1 + i, &jcaps, sizeof(jcaps));
  593. if (res == JOYERR_NOERROR) {
  594. String name = get_joystick_name(JOYSTICKID1 + i, jcaps);
  595. if ( name == "")
  596. joy.name = jcaps.szPname;
  597. else
  598. joy.name = name;
  599. };
  600. };
  601. joystick_change_queue.push_back(joy);
  602. };
  603. };
  604. void OS_Windows::process_key_events() {
  605. for(int i=0;i<key_event_pos;i++) {
  606. KeyEvent &ke = key_event_buffer[i];
  607. switch(ke.uMsg) {
  608. case WM_CHAR: {
  609. if ((i==0 && ke.uMsg==WM_CHAR) || (i>0 && key_event_buffer[i-1].uMsg==WM_CHAR))
  610. {
  611. InputEvent event;
  612. event.type=InputEvent::KEY;
  613. event.ID=++last_id;
  614. InputEventKey &k=event.key;
  615. k.mod=ke.mod_state;
  616. k.pressed=true;
  617. k.scancode=KeyMappingWindows::get_keysym(ke.wParam);
  618. k.unicode=ke.wParam;
  619. if (k.unicode && gr_mem) {
  620. k.mod.alt=false;
  621. k.mod.control=false;
  622. }
  623. if (k.unicode<32)
  624. k.unicode=0;
  625. input->parse_input_event(event);
  626. }
  627. //do nothing
  628. } break;
  629. case WM_KEYUP:
  630. case WM_KEYDOWN: {
  631. InputEvent event;
  632. event.type=InputEvent::KEY;
  633. event.ID=++last_id;
  634. InputEventKey &k=event.key;
  635. k.mod=ke.mod_state;
  636. k.pressed=(ke.uMsg==WM_KEYDOWN);
  637. k.scancode=KeyMappingWindows::get_keysym(ke.wParam);
  638. if (i+1 < key_event_pos && key_event_buffer[i+1].uMsg==WM_CHAR)
  639. k.unicode=key_event_buffer[i+1].wParam;
  640. if (k.unicode && gr_mem) {
  641. k.mod.alt=false;
  642. k.mod.control=false;
  643. }
  644. if (k.unicode<32)
  645. k.unicode=0;
  646. k.echo=(ke.uMsg==WM_KEYDOWN && (ke.lParam&(1<<30)));
  647. input->parse_input_event(event);
  648. } break;
  649. }
  650. }
  651. key_event_pos=0;
  652. }
  653. void OS_Windows::_post_dpad(DWORD p_dpad, int p_device, bool p_pressed) {
  654. InputEvent ievent;
  655. ievent.device = p_device;
  656. ievent.type = InputEvent::JOYSTICK_BUTTON;
  657. ievent.joy_button.pressed = p_pressed;
  658. ievent.joy_button.pressure = p_pressed ? 1.0 : 0.0;
  659. if (p_dpad == 0) {
  660. ievent.joy_button.button_index = JOY_DPAD_UP;
  661. ievent.ID = ++last_id;
  662. input->parse_input_event(ievent);
  663. } else if (p_dpad == 4500) {
  664. ievent.joy_button.button_index = JOY_DPAD_UP;
  665. ievent.ID = ++last_id;
  666. input->parse_input_event(ievent);
  667. ievent.joy_button.button_index = JOY_DPAD_RIGHT;
  668. ievent.ID = ++last_id;
  669. input->parse_input_event(ievent);
  670. } else if (p_dpad == 9000) {
  671. ievent.joy_button.button_index = JOY_DPAD_RIGHT;
  672. ievent.ID = ++last_id;
  673. input->parse_input_event(ievent);
  674. } else if (p_dpad == 13500) {
  675. ievent.joy_button.button_index = JOY_DPAD_RIGHT;
  676. ievent.ID = ++last_id;
  677. input->parse_input_event(ievent);
  678. ievent.joy_button.button_index = JOY_DPAD_DOWN;
  679. ievent.ID = ++last_id;
  680. input->parse_input_event(ievent);
  681. } else if (p_dpad == 18000) {
  682. ievent.joy_button.button_index = JOY_DPAD_DOWN;
  683. ievent.ID = ++last_id;
  684. input->parse_input_event(ievent);
  685. } else if (p_dpad == 22500) {
  686. ievent.joy_button.button_index = JOY_DPAD_DOWN;
  687. ievent.ID = ++last_id;
  688. input->parse_input_event(ievent);
  689. ievent.joy_button.button_index = JOY_DPAD_LEFT;
  690. ievent.ID = ++last_id;
  691. input->parse_input_event(ievent);
  692. } else if (p_dpad == 27000) {
  693. ievent.joy_button.button_index = JOY_DPAD_LEFT;
  694. ievent.ID = ++last_id;
  695. input->parse_input_event(ievent);
  696. } else if (p_dpad == 31500) {
  697. ievent.joy_button.button_index = JOY_DPAD_LEFT;
  698. ievent.ID = ++last_id;
  699. input->parse_input_event(ievent);
  700. ievent.joy_button.button_index = JOY_DPAD_UP;
  701. ievent.ID = ++last_id;
  702. input->parse_input_event(ievent);
  703. };
  704. };
  705. void OS_Windows::process_joysticks() {
  706. if (!main_loop) {
  707. return;
  708. };
  709. InputEvent ievent;
  710. JOYINFOEX jinfo;
  711. jinfo.dwSize = sizeof(JOYINFOEX);
  712. jinfo.dwFlags = JOY_RETURNALL;
  713. for (int i=0; i<JOYSTICKS_MAX; i++) {
  714. if (!joysticks[i].attached) {
  715. continue;
  716. };
  717. if (joyGetPosEx(JOYSTICKID1 + i, &jinfo) != JOYERR_NOERROR) {
  718. continue;
  719. };
  720. ievent.device = i;
  721. #define CHECK_AXIS(n, var) \
  722. if (joysticks[i].last_axis[n] != var) {\
  723. ievent.type = InputEvent::JOYSTICK_MOTION;\
  724. ievent.ID = ++last_id;\
  725. ievent.joy_motion.axis = n;\
  726. ievent.joy_motion.axis_value = (float)((int)var - MAX_JOY_AXIS) / (float)MAX_JOY_AXIS;\
  727. joysticks[i].last_axis[n] = var;\
  728. input->parse_input_event(ievent);\
  729. };
  730. CHECK_AXIS(0, jinfo.dwXpos);
  731. CHECK_AXIS(1, jinfo.dwYpos);
  732. CHECK_AXIS(2, jinfo.dwZpos);
  733. CHECK_AXIS(3, jinfo.dwRpos);
  734. CHECK_AXIS(4, jinfo.dwUpos);
  735. CHECK_AXIS(5, jinfo.dwVpos);
  736. if (joysticks[i].last_pov != jinfo.dwPOV) {
  737. if (joysticks[i].last_pov != JOY_POVCENTERED)
  738. _post_dpad(joysticks[i].last_pov, i, false);
  739. if (jinfo.dwPOV != JOY_POVCENTERED)
  740. _post_dpad(jinfo.dwPOV, i, true);
  741. joysticks[i].last_pov = jinfo.dwPOV;
  742. };
  743. if (joysticks[i].last_buttons == jinfo.dwButtons) {
  744. continue;
  745. };
  746. ievent.type = InputEvent::JOYSTICK_BUTTON;
  747. for (int j=0; j<32; j++) {
  748. if ( (joysticks[i].last_buttons & (1<<j)) != (jinfo.dwButtons & (1<<j)) ) {
  749. ievent.joy_button.button_index = j; //_pc_joystick_get_native_button(j);
  750. ievent.joy_button.pressed = jinfo.dwButtons & 1<<j;
  751. ievent.ID = ++last_id;
  752. input->parse_input_event(ievent);
  753. };
  754. };
  755. joysticks[i].last_buttons = jinfo.dwButtons;
  756. };
  757. };
  758. BOOL CALLBACK OS_Windows::MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) {
  759. OS_Windows *self=(OS_Windows*)OS::get_singleton();
  760. MonitorInfo minfo;
  761. minfo.hMonitor=hMonitor;
  762. minfo.hdcMonitor=hdcMonitor;
  763. minfo.rect.pos.x=lprcMonitor->left;
  764. minfo.rect.pos.y=lprcMonitor->top;
  765. minfo.rect.size.x=lprcMonitor->right - lprcMonitor->left;
  766. minfo.rect.size.y=lprcMonitor->bottom - lprcMonitor->top;
  767. self->monitor_info.push_back(minfo);
  768. return TRUE;
  769. }
  770. void OS_Windows::initialize(const VideoMode& p_desired,int p_video_driver,int p_audio_driver) {
  771. main_loop=NULL;
  772. outside=true;
  773. WNDCLASSEXW wc;
  774. video_mode=p_desired;
  775. //printf("**************** desired %s, mode %s\n", p_desired.fullscreen?"true":"false", video_mode.fullscreen?"true":"false");
  776. RECT WindowRect;
  777. WindowRect.left=0;
  778. WindowRect.right=video_mode.width;
  779. WindowRect.top=0;
  780. WindowRect.bottom=video_mode.height;
  781. memset(&wc,0,sizeof(WNDCLASSEXW));
  782. wc.cbSize=sizeof(WNDCLASSEXW);
  783. wc.style= CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS;
  784. wc.lpfnWndProc = (WNDPROC)::WndProc;
  785. wc.cbClsExtra = 0;
  786. wc.cbWndExtra= 0;
  787. //wc.hInstance = hInstance;
  788. wc.hInstance = godot_hinstance ? godot_hinstance : GetModuleHandle(NULL);
  789. wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
  790. wc.hCursor = NULL;//LoadCursor(NULL, IDC_ARROW);
  791. wc.hbrBackground = NULL;
  792. wc.lpszMenuName = NULL;
  793. wc.lpszClassName = L"Engine";
  794. if (!RegisterClassExW(&wc)) {
  795. MessageBox(NULL,"Failed To Register The Window Class.","ERROR",MB_OK|MB_ICONEXCLAMATION);
  796. return; // Return
  797. }
  798. EnumDisplayMonitors(NULL,NULL,MonitorEnumProc,0);
  799. print_line("DETECTED MONITORS: "+itos(monitor_info.size()));
  800. pre_fs_valid=true;
  801. if (video_mode.fullscreen) {
  802. DEVMODE current;
  803. memset(&current,0,sizeof(current));
  804. EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &current);
  805. WindowRect.right = current.dmPelsWidth;
  806. WindowRect.bottom = current.dmPelsHeight;
  807. /* DEVMODE dmScreenSettings;
  808. memset(&dmScreenSettings,0,sizeof(dmScreenSettings));
  809. dmScreenSettings.dmSize=sizeof(dmScreenSettings);
  810. dmScreenSettings.dmPelsWidth = video_mode.width;
  811. dmScreenSettings.dmPelsHeight = video_mode.height;
  812. dmScreenSettings.dmBitsPerPel = current.dmBitsPerPel;
  813. dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
  814. LONG err = ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN);
  815. if (err!=DISP_CHANGE_SUCCESSFUL) {
  816. video_mode.fullscreen=false;
  817. }*/
  818. pre_fs_valid=false;
  819. }
  820. DWORD dwExStyle;
  821. DWORD dwStyle;
  822. if (video_mode.fullscreen) {
  823. dwExStyle=WS_EX_APPWINDOW;
  824. dwStyle=WS_POPUP;
  825. } else {
  826. dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
  827. dwStyle=WS_OVERLAPPEDWINDOW;
  828. if (!video_mode.resizable) {
  829. dwStyle &= ~WS_THICKFRAME;
  830. dwStyle &= ~WS_MAXIMIZEBOX;
  831. }
  832. }
  833. AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);
  834. char* windowid = getenv("GODOT_WINDOWID");
  835. if (windowid) {
  836. // strtoull on mingw
  837. #ifdef MINGW_ENABLED
  838. hWnd = (HWND)strtoull(windowid, NULL, 0);
  839. #else
  840. hWnd = (HWND)_strtoui64(windowid, NULL, 0);
  841. #endif
  842. SetLastError(0);
  843. user_proc = (WNDPROC)GetWindowLongPtr(hWnd, GWLP_WNDPROC);
  844. SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)(WNDPROC)::WndProc);
  845. DWORD le = GetLastError();
  846. if (user_proc == 0 && le != 0) {
  847. printf("Error setting WNDPROC: %li\n", le);
  848. };
  849. LONG_PTR proc = GetWindowLongPtr(hWnd, GWLP_WNDPROC);
  850. RECT rect;
  851. if (!GetClientRect(hWnd, &rect)) {
  852. MessageBoxW(NULL,L"Window Creation Error.",L"ERROR",MB_OK|MB_ICONEXCLAMATION);
  853. return; // Return FALSE
  854. };
  855. video_mode.width = rect.right;
  856. video_mode.height = rect.bottom;
  857. video_mode.fullscreen = false;
  858. } else {
  859. if (!(hWnd=CreateWindowExW(dwExStyle,L"Engine",L"", dwStyle|WS_CLIPSIBLINGS|WS_CLIPCHILDREN, 0, 0,WindowRect.right-WindowRect.left,WindowRect.bottom-WindowRect.top, NULL,NULL, hInstance,NULL))) {
  860. MessageBoxW(NULL,L"Window Creation Error.",L"ERROR",MB_OK|MB_ICONEXCLAMATION);
  861. return; // Return FALSE
  862. }
  863. };
  864. #if defined(OPENGL_ENABLED) || defined(GLES2_ENABLED) || defined(LEGACYGL_ENABLED)
  865. gl_context = memnew( ContextGL_Win(hWnd,false) );
  866. gl_context->initialize();
  867. rasterizer = memnew( RasterizerGLES2 );
  868. #else
  869. #ifdef DX9_ENABLED
  870. rasterizer = memnew( RasterizerDX9(hWnd) );
  871. #endif
  872. #endif
  873. visual_server = memnew( VisualServerRaster(rasterizer) );
  874. if (get_render_thread_mode()!=RENDER_THREAD_UNSAFE) {
  875. visual_server =memnew(VisualServerWrapMT(visual_server,get_render_thread_mode()==RENDER_SEPARATE_THREAD));
  876. }
  877. //
  878. physics_server = memnew( PhysicsServerSW );
  879. physics_server->init();
  880. physics_2d_server = memnew( Physics2DServerSW );
  881. physics_2d_server->init();
  882. if (!is_no_window_mode_enabled()) {
  883. ShowWindow(hWnd,SW_SHOW); // Show The Window
  884. SetForegroundWindow(hWnd); // Slightly Higher Priority
  885. SetFocus(hWnd); // Sets Keyboard Focus To
  886. }
  887. /*
  888. DEVMODE dmScreenSettings; // Device Mode
  889. memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); // Makes Sure Memory's Cleared
  890. dmScreenSettings.dmSize=sizeof(dmScreenSettings); // Size Of The Devmode Structure
  891. dmScreenSettings.dmPelsWidth = width; // Selected Screen Width
  892. dmScreenSettings.dmPelsHeight = height; // Selected Screen Height
  893. dmScreenSettings.dmBitsPerPel = bits; // Selected Bits Per Pixel
  894. dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
  895. if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
  896. */
  897. visual_server->init();
  898. input = memnew( InputDefault );
  899. AudioDriverManagerSW::get_driver(p_audio_driver)->set_singleton();
  900. if (AudioDriverManagerSW::get_driver(p_audio_driver)->init()!=OK) {
  901. ERR_PRINT("Initializing audio failed.");
  902. }
  903. sample_manager = memnew( SampleManagerMallocSW );
  904. audio_server = memnew( AudioServerSW(sample_manager) );
  905. audio_server->init();
  906. spatial_sound_server = memnew( SpatialSoundServerSW );
  907. spatial_sound_server->init();
  908. spatial_sound_2d_server = memnew( SpatialSound2DServerSW );
  909. spatial_sound_2d_server->init();
  910. probe_joysticks(); // todo: move this to a thread
  911. while (joystick_change_queue.size() > 0) {
  912. Joystick joy = joystick_change_queue.front()->get();
  913. joystick_change_queue.pop_front();
  914. joysticks[joy.id] = joy;
  915. input->joy_connection_changed(joy.id, joy.attached, joy.name);
  916. };
  917. TRACKMOUSEEVENT tme;
  918. tme.cbSize=sizeof(TRACKMOUSEEVENT);
  919. tme.dwFlags=TME_LEAVE;
  920. tme.hwndTrack=hWnd;
  921. tme.dwHoverTime=HOVER_DEFAULT;
  922. TrackMouseEvent(&tme);
  923. //RegisterTouchWindow(hWnd, 0); // Windows 7
  924. _ensure_data_dir();
  925. }
  926. void OS_Windows::set_clipboard(const String& p_text) {
  927. if (!OpenClipboard(hWnd)) {
  928. ERR_EXPLAIN("Unable to open clipboard.");
  929. ERR_FAIL();
  930. };
  931. EmptyClipboard();
  932. HGLOBAL mem = GlobalAlloc(GMEM_MOVEABLE, (p_text.length() + 1) * sizeof(CharType));
  933. if (mem == NULL) {
  934. ERR_EXPLAIN("Unable to allocate memory for clipboard contents.");
  935. ERR_FAIL();
  936. };
  937. LPWSTR lptstrCopy = (LPWSTR)GlobalLock(mem);
  938. memcpy(lptstrCopy, p_text.c_str(), (p_text.length() + 1) * sizeof(CharType));
  939. //memset((lptstrCopy + p_text.length()), 0, sizeof(CharType));
  940. GlobalUnlock(mem);
  941. SetClipboardData(CF_UNICODETEXT, mem);
  942. // set the CF_TEXT version (not needed?)
  943. CharString utf8 = p_text.utf8();
  944. mem = GlobalAlloc(GMEM_MOVEABLE, utf8.length() + 1);
  945. if (mem == NULL) {
  946. ERR_EXPLAIN("Unable to allocate memory for clipboard contents.");
  947. ERR_FAIL();
  948. };
  949. LPTSTR ptr = (LPTSTR)GlobalLock(mem);
  950. memcpy(ptr, utf8.get_data(), utf8.length());
  951. ptr[utf8.length()] = 0;
  952. GlobalUnlock(mem);
  953. SetClipboardData(CF_TEXT, mem);
  954. CloseClipboard();
  955. };
  956. String OS_Windows::get_clipboard() const {
  957. String ret;
  958. if (!OpenClipboard(hWnd)) {
  959. ERR_EXPLAIN("Unable to open clipboard.");
  960. ERR_FAIL_V("");
  961. };
  962. if (IsClipboardFormatAvailable(CF_UNICODETEXT)) {
  963. HGLOBAL mem = GetClipboardData(CF_UNICODETEXT);
  964. if (mem != NULL) {
  965. LPWSTR ptr = (LPWSTR)GlobalLock(mem);
  966. if (ptr != NULL) {
  967. ret = String((CharType*)ptr);
  968. GlobalUnlock(mem);
  969. };
  970. };
  971. } else if (IsClipboardFormatAvailable(CF_TEXT)) {
  972. HGLOBAL mem = GetClipboardData(CF_UNICODETEXT);
  973. if (mem != NULL) {
  974. LPTSTR ptr = (LPTSTR)GlobalLock(mem);
  975. if (ptr != NULL) {
  976. ret.parse_utf8((const char*)ptr);
  977. GlobalUnlock(mem);
  978. };
  979. };
  980. };
  981. CloseClipboard();
  982. return ret;
  983. };
  984. void OS_Windows::delete_main_loop() {
  985. if (main_loop)
  986. memdelete(main_loop);
  987. main_loop=NULL;
  988. }
  989. void OS_Windows::set_main_loop( MainLoop * p_main_loop ) {
  990. input->set_main_loop(p_main_loop);
  991. main_loop=p_main_loop;
  992. }
  993. void OS_Windows::finalize() {
  994. if(main_loop)
  995. memdelete(main_loop);
  996. main_loop=NULL;
  997. visual_server->finish();
  998. memdelete(visual_server);
  999. #ifdef OPENGL_ENABLED
  1000. if (gl_context)
  1001. memdelete(gl_context);
  1002. #endif
  1003. if (rasterizer)
  1004. memdelete(rasterizer);
  1005. if (user_proc) {
  1006. SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)user_proc);
  1007. };
  1008. spatial_sound_server->finish();
  1009. memdelete(spatial_sound_server);
  1010. spatial_sound_2d_server->finish();
  1011. memdelete(spatial_sound_2d_server);
  1012. //if (debugger_connection_console) {
  1013. // memdelete(debugger_connection_console);
  1014. //}
  1015. audio_server->finish();
  1016. memdelete(audio_server);
  1017. memdelete(sample_manager);
  1018. memdelete(input);
  1019. physics_server->finish();
  1020. memdelete(physics_server);
  1021. physics_2d_server->finish();
  1022. memdelete(physics_2d_server);
  1023. }
  1024. void OS_Windows::finalize_core() {
  1025. memdelete(process_map);
  1026. if (mempool_dynamic)
  1027. memdelete( mempool_dynamic );
  1028. if (mempool_static)
  1029. delete mempool_static;
  1030. TCPServerWinsock::cleanup();
  1031. StreamPeerWinsock::cleanup();
  1032. }
  1033. void OS_Windows::vprint(const char* p_format, va_list p_list, bool p_stderr) {
  1034. char buf[16384+1];
  1035. int len = vsnprintf(buf,16384,p_format,p_list);
  1036. if (len<=0)
  1037. return;
  1038. buf[len]=0;
  1039. int wlen = MultiByteToWideChar(CP_UTF8,0,buf,len,NULL,0);
  1040. if (wlen<0)
  1041. return;
  1042. wchar_t *wbuf = (wchar_t*)malloc((len+1)*sizeof(wchar_t));
  1043. MultiByteToWideChar(CP_UTF8,0,buf,len,wbuf,wlen);
  1044. wbuf[wlen]=0;
  1045. if (p_stderr)
  1046. fwprintf(stderr,L"%s",wbuf);
  1047. else
  1048. wprintf(L"%s",wbuf);
  1049. #ifdef STDOUT_FILE
  1050. //vwfprintf(stdo,p_format,p_list);
  1051. #endif
  1052. free(wbuf);
  1053. fflush(stdout);
  1054. };
  1055. void OS_Windows::alert(const String& p_alert,const String& p_title) {
  1056. if (!is_no_window_mode_enabled())
  1057. MessageBoxW(NULL,p_alert.c_str(),p_title.c_str(),MB_OK|MB_ICONEXCLAMATION);
  1058. else
  1059. print_line("ALERT: "+p_alert);
  1060. }
  1061. void OS_Windows::set_mouse_mode(MouseMode p_mode) {
  1062. if (mouse_mode==p_mode)
  1063. return;
  1064. ShowCursor(p_mode==MOUSE_MODE_VISIBLE);
  1065. mouse_mode=p_mode;
  1066. if (p_mode==MOUSE_MODE_CAPTURED) {
  1067. RECT clipRect;
  1068. GetClientRect(hWnd, &clipRect);
  1069. ClientToScreen(hWnd, (POINT*) &clipRect.left);
  1070. ClientToScreen(hWnd, (POINT*) &clipRect.right);
  1071. ClipCursor(&clipRect);
  1072. SetCapture(hWnd);
  1073. center=Point2i(video_mode.width/2,video_mode.height/2);
  1074. POINT pos = { (int) center.x, (int) center.y };
  1075. ClientToScreen(hWnd, &pos);
  1076. SetCursorPos(pos.x, pos.y);
  1077. } else {
  1078. ReleaseCapture();
  1079. ClipCursor(NULL);
  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. int OS_Windows::get_screen_count() const {
  1114. return monitor_info.size();
  1115. }
  1116. int OS_Windows::get_current_screen() const{
  1117. HMONITOR monitor = MonitorFromWindow(hWnd,MONITOR_DEFAULTTONEAREST);
  1118. for(int i=0;i<monitor_info.size();i++) {
  1119. if (monitor_info[i].hMonitor==monitor)
  1120. return i;
  1121. }
  1122. return 0;
  1123. }
  1124. void OS_Windows::set_current_screen(int p_screen){
  1125. ERR_FAIL_INDEX(p_screen,monitor_info.size());
  1126. Vector2 ofs = get_window_position() - get_screen_position(get_current_screen());
  1127. set_window_position(ofs+get_screen_position(p_screen));
  1128. }
  1129. Point2 OS_Windows::get_screen_position(int p_screen) const{
  1130. ERR_FAIL_INDEX_V(p_screen,monitor_info.size(),Point2());
  1131. return Vector2( monitor_info[p_screen].rect.pos );
  1132. }
  1133. Size2 OS_Windows::get_screen_size(int p_screen) const{
  1134. ERR_FAIL_INDEX_V(p_screen,monitor_info.size(),Point2());
  1135. return Vector2( monitor_info[p_screen].rect.size );
  1136. }
  1137. Point2 OS_Windows::get_window_position() const{
  1138. RECT r;
  1139. GetWindowRect(hWnd,&r);
  1140. return Point2(r.left,r.top);
  1141. }
  1142. void OS_Windows::set_window_position(const Point2& p_position){
  1143. RECT r;
  1144. GetWindowRect(hWnd,&r);
  1145. MoveWindow(hWnd,p_position.x,p_position.y,r.right-r.left,r.bottom-r.top,TRUE);
  1146. }
  1147. Size2 OS_Windows::get_window_size() const{
  1148. RECT r;
  1149. GetClientRect(hWnd,&r);
  1150. return Vector2(r.right-r.left,r.bottom-r.top);
  1151. }
  1152. void OS_Windows::set_window_size(const Size2 p_size){
  1153. video_mode.width=p_size.width;
  1154. video_mode.height=p_size.height;
  1155. if (video_mode.fullscreen) {
  1156. return;
  1157. }
  1158. RECT crect;
  1159. GetClientRect(hWnd,&crect);
  1160. RECT rect;
  1161. GetWindowRect(hWnd,&rect);
  1162. int dx = (rect.right-rect.left)-(crect.right-crect.left);
  1163. int dy = (rect.bottom-rect.top)-(crect.bottom-crect.top);
  1164. rect.right=rect.left+p_size.width+dx;
  1165. rect.bottom=rect.top+p_size.height+dy;
  1166. //print_line("PRE: "+itos(rect.left)+","+itos(rect.top)+","+itos(rect.right-rect.left)+","+itos(rect.bottom-rect.top));
  1167. /*if (video_mode.resizable) {
  1168. AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);
  1169. } else {
  1170. AdjustWindowRect(&rect, WS_CAPTION | WS_POPUPWINDOW, FALSE);
  1171. }*/
  1172. //print_line("POST: "+itos(rect.left)+","+itos(rect.top)+","+itos(rect.right-rect.left)+","+itos(rect.bottom-rect.top));
  1173. MoveWindow(hWnd,rect.left,rect.top,rect.right-rect.left,rect.bottom-rect.top,TRUE);
  1174. }
  1175. void OS_Windows::set_window_fullscreen(bool p_enabled){
  1176. if (video_mode.fullscreen==p_enabled)
  1177. return;
  1178. if (p_enabled) {
  1179. if (pre_fs_valid) {
  1180. GetWindowRect(hWnd,&pre_fs_rect);
  1181. //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));
  1182. //MapWindowPoints(hWnd, GetParent(hWnd), (LPPOINT) &pre_fs_rect, 2);
  1183. //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));
  1184. }
  1185. int cs = get_current_screen();
  1186. Point2 pos = get_screen_position(cs);
  1187. Size2 size = get_screen_size(cs);
  1188. /* r.left = pos.x;
  1189. r.top = pos.y;
  1190. r.bottom = pos.y+size.y;
  1191. r.right = pos.x+size.x;
  1192. */
  1193. SetWindowLongPtr(hWnd, GWL_STYLE,
  1194. WS_SYSMENU | WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE);
  1195. MoveWindow(hWnd, pos.x, pos.y, size.width, size.height, TRUE);
  1196. video_mode.fullscreen=true;
  1197. } else {
  1198. RECT rect;
  1199. if (pre_fs_valid) {
  1200. rect=pre_fs_rect;
  1201. } else {
  1202. rect.left=0;
  1203. rect.right=video_mode.width;
  1204. rect.top=0;
  1205. rect.bottom=video_mode.height;
  1206. }
  1207. if (video_mode.resizable) {
  1208. SetWindowLongPtr(hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE);
  1209. //AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);
  1210. MoveWindow(hWnd, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE);
  1211. } else {
  1212. SetWindowLongPtr(hWnd, GWL_STYLE, WS_CAPTION | WS_POPUPWINDOW | WS_VISIBLE);
  1213. //AdjustWindowRect(&rect, WS_CAPTION | WS_POPUPWINDOW, FALSE);
  1214. MoveWindow(hWnd, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE);
  1215. }
  1216. video_mode.fullscreen=false;
  1217. pre_fs_valid=true;
  1218. /*
  1219. DWORD dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
  1220. DWORD dwStyle=WS_OVERLAPPEDWINDOW;
  1221. if (!video_mode.resizable) {
  1222. dwStyle &= ~WS_THICKFRAME;
  1223. dwStyle &= ~WS_MAXIMIZEBOX;
  1224. }
  1225. AdjustWindowRectEx(&pre_fs_rect, dwStyle, FALSE, dwExStyle);
  1226. video_mode.fullscreen=false;
  1227. video_mode.width=pre_fs_rect.right-pre_fs_rect.left;
  1228. video_mode.height=pre_fs_rect.bottom-pre_fs_rect.top;
  1229. */
  1230. }
  1231. // MoveWindow(hWnd,r.left,r.top,p_size.x,p_size.y,TRUE);
  1232. }
  1233. bool OS_Windows::is_window_fullscreen() const{
  1234. return video_mode.fullscreen;
  1235. }
  1236. void OS_Windows::set_window_resizable(bool p_enabled){
  1237. if (video_mode.resizable==p_enabled)
  1238. return;
  1239. /*
  1240. GetWindowRect(hWnd,&pre_fs_rect);
  1241. DWORD dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
  1242. DWORD dwStyle=WS_OVERLAPPEDWINDOW;
  1243. if (!p_enabled) {
  1244. dwStyle &= ~WS_THICKFRAME;
  1245. dwStyle &= ~WS_MAXIMIZEBOX;
  1246. }
  1247. AdjustWindowRectEx(&pre_fs_rect, dwStyle, FALSE, dwExStyle);
  1248. */
  1249. if (!video_mode.fullscreen) {
  1250. if (p_enabled) {
  1251. SetWindowLongPtr(hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE);
  1252. } else {
  1253. SetWindowLongPtr(hWnd, GWL_STYLE, WS_CAPTION | WS_POPUPWINDOW | WS_VISIBLE);
  1254. }
  1255. RECT rect;
  1256. GetWindowRect(hWnd,&rect);
  1257. MoveWindow(hWnd, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE);
  1258. }
  1259. video_mode.resizable=p_enabled;
  1260. }
  1261. bool OS_Windows::is_window_resizable() const{
  1262. return video_mode.resizable;
  1263. }
  1264. void OS_Windows::set_window_minimized(bool p_enabled){
  1265. if (p_enabled) {
  1266. maximized=false;
  1267. minimized=true;
  1268. ShowWindow(hWnd,SW_MINIMIZE);
  1269. } else {
  1270. ShowWindow(hWnd,SW_RESTORE);
  1271. maximized=false;
  1272. minimized=false;
  1273. }
  1274. }
  1275. bool OS_Windows::is_window_minimized() const{
  1276. return minimized;
  1277. }
  1278. void OS_Windows::set_window_maximized(bool p_enabled){
  1279. if (p_enabled) {
  1280. maximized=true;
  1281. minimized=false;
  1282. ShowWindow(hWnd,SW_MAXIMIZE);
  1283. } else {
  1284. ShowWindow(hWnd,SW_RESTORE);
  1285. maximized=false;
  1286. minimized=false;
  1287. }
  1288. }
  1289. bool OS_Windows::is_window_maximized() const{
  1290. return maximized;
  1291. }
  1292. 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) {
  1293. HANDLE hCon=GetStdHandle(STD_OUTPUT_HANDLE);
  1294. if (!hCon || hCon==INVALID_HANDLE_VALUE) {
  1295. if (p_rationale && p_rationale[0]) {
  1296. print("\E[1;31;40mERROR: %s: \E[1;37;40m%s\n",p_function,p_rationale);
  1297. print("\E[0;31;40m At: %s:%i.\E[0;0;37m\n",p_file,p_line);
  1298. } else {
  1299. print("\E[1;31;40mERROR: %s: \E[1;37;40m%s\n",p_function,p_code);
  1300. print("\E[0;31;40m At: %s:%i.\E[0;0;37m\n",p_file,p_line);
  1301. }
  1302. } else {
  1303. CONSOLE_SCREEN_BUFFER_INFO sbi; //original
  1304. GetConsoleScreenBufferInfo(hCon,&sbi);
  1305. SetConsoleTextAttribute(hCon,sbi.wAttributes);
  1306. uint32_t basecol=0;
  1307. switch(p_type) {
  1308. case ERR_ERROR: basecol = FOREGROUND_RED; break;
  1309. case ERR_WARNING: basecol = FOREGROUND_RED|FOREGROUND_GREEN; break;
  1310. case ERR_SCRIPT: basecol = FOREGROUND_GREEN; break;
  1311. }
  1312. if (p_rationale && p_rationale[0]) {
  1313. SetConsoleTextAttribute(hCon,basecol|FOREGROUND_INTENSITY);
  1314. switch(p_type) {
  1315. case ERR_ERROR: print("ERROR: "); break;
  1316. case ERR_WARNING: print("WARNING: "); break;
  1317. case ERR_SCRIPT: print("SCRIPT ERROR: "); break;
  1318. }
  1319. SetConsoleTextAttribute(hCon,FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_INTENSITY);
  1320. print(" %s\n",p_rationale);
  1321. SetConsoleTextAttribute(hCon,basecol);
  1322. print("At: ");
  1323. SetConsoleTextAttribute(hCon,FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_GREEN);
  1324. print(" %s:%i\n",p_file,p_line);
  1325. } else {
  1326. SetConsoleTextAttribute(hCon,basecol|FOREGROUND_INTENSITY);
  1327. switch(p_type) {
  1328. case ERR_ERROR: print("ERROR: %s: ",p_function); break;
  1329. case ERR_WARNING: print("WARNING: %s: ",p_function); break;
  1330. case ERR_SCRIPT: print("SCRIPT ERROR: %s: ",p_function); break;
  1331. }
  1332. SetConsoleTextAttribute(hCon,FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_INTENSITY);
  1333. print(" %s\n",p_code);
  1334. SetConsoleTextAttribute(hCon,basecol);
  1335. print("At: ");
  1336. SetConsoleTextAttribute(hCon,FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_GREEN);
  1337. print(" %s:%i\n",p_file,p_line);
  1338. }
  1339. SetConsoleTextAttribute(hCon,sbi.wAttributes);
  1340. }
  1341. }
  1342. String OS_Windows::get_name() {
  1343. return "Windows";
  1344. }
  1345. OS::Date OS_Windows::get_date() const {
  1346. SYSTEMTIME systemtime;
  1347. GetSystemTime(&systemtime);
  1348. Date date;
  1349. date.day=systemtime.wDay;
  1350. date.month=Month(systemtime.wMonth);
  1351. date.weekday=Weekday(systemtime.wDayOfWeek);
  1352. date.year=systemtime.wYear;
  1353. date.dst=false;
  1354. return date;
  1355. }
  1356. OS::Time OS_Windows::get_time() const {
  1357. SYSTEMTIME systemtime;
  1358. GetLocalTime(&systemtime);
  1359. Time time;
  1360. time.hour=systemtime.wHour;
  1361. time.min=systemtime.wMinute;
  1362. time.sec=systemtime.wSecond;
  1363. return time;
  1364. }
  1365. uint64_t OS_Windows::get_unix_time() const {
  1366. FILETIME ft;
  1367. SYSTEMTIME st;
  1368. GetSystemTime(&st);
  1369. SystemTimeToFileTime(&st, &ft);
  1370. SYSTEMTIME ep;
  1371. ep.wYear = 1970;
  1372. ep.wMonth = 1;
  1373. ep.wDayOfWeek = 4;
  1374. ep.wDay = 1;
  1375. ep.wHour = 0;
  1376. ep.wMinute = 0;
  1377. ep.wSecond = 0;
  1378. ep.wMilliseconds = 0;
  1379. FILETIME fep;
  1380. SystemTimeToFileTime(&ep, &fep);
  1381. return (*(uint64_t*)&ft - *(uint64_t*)&fep) / 10000000;
  1382. };
  1383. void OS_Windows::delay_usec(uint32_t p_usec) const {
  1384. if (p_usec < 1000)
  1385. Sleep(1);
  1386. else
  1387. Sleep(p_usec / 1000);
  1388. }
  1389. uint64_t OS_Windows::get_ticks_usec() const {
  1390. uint64_t ticks;
  1391. uint64_t time;
  1392. // This is the number of clock ticks since start
  1393. if( !QueryPerformanceCounter((LARGE_INTEGER *)&ticks) )
  1394. ticks = (UINT64)timeGetTime();
  1395. // Divide by frequency to get the time in seconds
  1396. time = ticks * 1000000L / ticks_per_second;
  1397. // Subtract the time at game start to get
  1398. // the time since the game started
  1399. time -= ticks_start;
  1400. return time;
  1401. }
  1402. void OS_Windows::process_events() {
  1403. MSG msg;
  1404. process_joysticks();
  1405. while(PeekMessageW(&msg,NULL,0,0,PM_REMOVE)) {
  1406. TranslateMessage(&msg);
  1407. DispatchMessageW(&msg);
  1408. }
  1409. process_key_events();
  1410. }
  1411. void OS_Windows::set_cursor_shape(CursorShape p_shape) {
  1412. ERR_FAIL_INDEX(p_shape,CURSOR_MAX);
  1413. if (cursor_shape==p_shape)
  1414. return;
  1415. static const LPCTSTR win_cursors[CURSOR_MAX]={
  1416. IDC_ARROW,
  1417. IDC_IBEAM,
  1418. IDC_HAND,//finger
  1419. IDC_CROSS,
  1420. IDC_WAIT,
  1421. IDC_APPSTARTING,
  1422. IDC_ARROW,
  1423. IDC_ARROW,
  1424. IDC_NO,
  1425. IDC_SIZENS,
  1426. IDC_SIZEWE,
  1427. IDC_SIZENESW,
  1428. IDC_SIZENWSE,
  1429. IDC_SIZEALL,
  1430. IDC_SIZENS,
  1431. IDC_SIZEWE,
  1432. IDC_HELP
  1433. };
  1434. SetCursor(LoadCursor(hInstance,win_cursors[p_shape]));
  1435. cursor_shape=p_shape;
  1436. }
  1437. 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) {
  1438. if (p_blocking && r_pipe) {
  1439. String argss;
  1440. argss="\"\""+p_path+"\"";
  1441. for(int i=0;i<p_arguments.size();i++) {
  1442. argss+=String(" \"")+p_arguments[i]+"\"";
  1443. }
  1444. // print_line("ARGS: "+argss);
  1445. //argss+"\"";
  1446. //argss+=" 2>nul";
  1447. FILE* f=_wpopen(argss.c_str(),L"r");
  1448. ERR_FAIL_COND_V(!f,ERR_CANT_OPEN);
  1449. char buf[65535];
  1450. while(fgets(buf,65535,f)) {
  1451. (*r_pipe)+=buf;
  1452. }
  1453. int rv = _pclose(f);
  1454. if (r_exitcode)
  1455. *r_exitcode=rv;
  1456. return OK;
  1457. }
  1458. String cmdline = "\""+p_path+"\"";
  1459. const List<String>::Element* I = p_arguments.front();
  1460. while (I) {
  1461. cmdline += " \""+I->get() + "\"";
  1462. I = I->next();
  1463. };
  1464. //cmdline+="\"";
  1465. ProcessInfo pi;
  1466. ZeroMemory( &pi.si, sizeof(pi.si) );
  1467. pi.si.cb = sizeof(pi.si);
  1468. ZeroMemory( &pi.pi, sizeof(pi.pi) );
  1469. LPSTARTUPINFOW si_w = (LPSTARTUPINFOW) &pi.si;
  1470. print_line("running cmdline: "+cmdline);
  1471. Vector<CharType> modstr; //windows wants to change this no idea why
  1472. modstr.resize(cmdline.size());
  1473. for(int i=0;i<cmdline.size();i++)
  1474. modstr[i]=cmdline[i];
  1475. int ret = CreateProcessW(NULL, modstr.ptr(), NULL, NULL, 0, NORMAL_PRIORITY_CLASS, NULL, NULL, si_w, &pi.pi);
  1476. ERR_FAIL_COND_V(ret == 0, ERR_CANT_FORK);
  1477. if (p_blocking) {
  1478. DWORD ret = WaitForSingleObject(pi.pi.hProcess, INFINITE);
  1479. if (r_exitcode)
  1480. *r_exitcode=ret;
  1481. } else {
  1482. ProcessID pid = pi.pi.dwProcessId;
  1483. if (r_child_id) {
  1484. *r_child_id = pid;
  1485. };
  1486. process_map->insert(pid, pi);
  1487. };
  1488. return OK;
  1489. };
  1490. Error OS_Windows::kill(const ProcessID& p_pid) {
  1491. HANDLE h;
  1492. if (process_map->has(p_pid)) {
  1493. h = (*process_map)[p_pid].pi.hProcess;
  1494. process_map->erase(p_pid);
  1495. } else {
  1496. ERR_FAIL_COND_V(!process_map->has(p_pid), FAILED);
  1497. };
  1498. int ret = TerminateProcess(h, 0);
  1499. return ret != 0?OK:FAILED;
  1500. };
  1501. Error OS_Windows::set_cwd(const String& p_cwd) {
  1502. if (_wchdir(p_cwd.c_str())!=0)
  1503. return ERR_CANT_OPEN;
  1504. return OK;
  1505. }
  1506. String OS_Windows::get_executable_path() const {
  1507. wchar_t bufname[4096];
  1508. GetModuleFileNameW(NULL,bufname,4096);
  1509. String s= bufname;
  1510. print_line("EXEC PATHP¨®: "+s);
  1511. return s;
  1512. }
  1513. void OS_Windows::set_icon(const Image& p_icon) {
  1514. Image icon=p_icon;
  1515. if (icon.get_format()!=Image::FORMAT_RGBA)
  1516. icon.convert(Image::FORMAT_RGBA);
  1517. int w = icon.get_width();
  1518. int h = icon.get_height();
  1519. /* Create temporary bitmap buffer */
  1520. int icon_len = 40 + h * w * 4;
  1521. Vector<BYTE> v;
  1522. v.resize(icon_len);
  1523. BYTE *icon_bmp = &v[0];
  1524. encode_uint32(40,&icon_bmp[0]);
  1525. encode_uint32(w,&icon_bmp[4]);
  1526. encode_uint32(h*2,&icon_bmp[8]);
  1527. encode_uint16(1,&icon_bmp[12]);
  1528. encode_uint16(32,&icon_bmp[14]);
  1529. encode_uint32(BI_RGB,&icon_bmp[16]);
  1530. encode_uint32(w*h*4,&icon_bmp[20]);
  1531. encode_uint32(0,&icon_bmp[24]);
  1532. encode_uint32(0,&icon_bmp[28]);
  1533. encode_uint32(0,&icon_bmp[32]);
  1534. encode_uint32(0,&icon_bmp[36]);
  1535. uint8_t *wr=&icon_bmp[40];
  1536. DVector<uint8_t>::Read r= icon.get_data().read();
  1537. for(int i=0;i<h;i++) {
  1538. for(int j=0;j<w;j++) {
  1539. const uint8_t *rpx = &r[((h-i-1)*w+j)*4];
  1540. uint8_t *wpx = &wr[(i*w+j)*4];
  1541. wpx[0]=rpx[2];
  1542. wpx[1]=rpx[1];
  1543. wpx[2]=rpx[0];
  1544. wpx[3]=rpx[3];
  1545. }
  1546. }
  1547. HICON hicon = CreateIconFromResource(icon_bmp, icon_len, TRUE, 0x00030000);
  1548. /* Set the icon for the window */
  1549. SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM) hicon);
  1550. /* Set the icon in the task manager (should we do this?) */
  1551. SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM) hicon);
  1552. }
  1553. bool OS_Windows::has_environment(const String& p_var) const {
  1554. return getenv(p_var.utf8().get_data()) != NULL;
  1555. };
  1556. String OS_Windows::get_environment(const String& p_var) const {
  1557. wchar_t wval[0x7Fff]; // MSDN says 32767 char is the maximum
  1558. int wlen = GetEnvironmentVariableW(p_var.c_str(),wval,0x7Fff);
  1559. if ( wlen > 0 ) {
  1560. return wval;
  1561. }
  1562. return "";
  1563. }
  1564. String OS_Windows::get_stdin_string(bool p_block) {
  1565. if (p_block) {
  1566. char buff[1024];
  1567. return fgets(buff,1024,stdin);
  1568. };
  1569. return String();
  1570. }
  1571. void OS_Windows::move_window_to_foreground() {
  1572. SetForegroundWindow(hWnd);
  1573. BringWindowToTop(hWnd);
  1574. }
  1575. Error OS_Windows::shell_open(String p_uri) {
  1576. ShellExecuteW(NULL, L"open", p_uri.c_str(), NULL, NULL, SW_SHOWNORMAL);
  1577. return OK;
  1578. }
  1579. String OS_Windows::get_locale() const {
  1580. const _WinLocale *wl = &_win_locales[0];
  1581. LANGID langid = GetUserDefaultUILanguage();
  1582. String neutral;
  1583. int lang = langid&((1<<9)-1);
  1584. int sublang = langid&~((1<<9)-1);
  1585. while(wl->locale) {
  1586. if (wl->main_lang==lang && wl->sublang==SUBLANG_NEUTRAL)
  1587. neutral=wl->locale;
  1588. if (lang==wl->main_lang && sublang==wl->sublang)
  1589. return wl->locale;
  1590. wl++;
  1591. }
  1592. if (neutral!="")
  1593. return neutral;
  1594. return "en";
  1595. }
  1596. void OS_Windows::release_rendering_thread() {
  1597. gl_context->release_current();
  1598. }
  1599. void OS_Windows::make_rendering_thread() {
  1600. gl_context->make_current();
  1601. }
  1602. void OS_Windows::swap_buffers() {
  1603. gl_context->swap_buffers();
  1604. }
  1605. void OS_Windows::run() {
  1606. if (!main_loop)
  1607. return;
  1608. main_loop->init();
  1609. uint64_t last_ticks=get_ticks_usec();
  1610. int frames=0;
  1611. uint64_t frame=0;
  1612. while (!force_quit) {
  1613. process_events(); // get rid of pending events
  1614. if (Main::iteration()==true)
  1615. break;
  1616. };
  1617. main_loop->finish();
  1618. }
  1619. MainLoop *OS_Windows::get_main_loop() const {
  1620. return main_loop;
  1621. }
  1622. String OS_Windows::get_system_dir(SystemDir p_dir) const {
  1623. int id;
  1624. switch(p_dir) {
  1625. case SYSTEM_DIR_DESKTOP: {
  1626. id=CSIDL_DESKTOPDIRECTORY;
  1627. } break;
  1628. case SYSTEM_DIR_DCIM: {
  1629. id=CSIDL_MYPICTURES;
  1630. } break;
  1631. case SYSTEM_DIR_DOCUMENTS: {
  1632. id=0x000C;
  1633. } break;
  1634. case SYSTEM_DIR_DOWNLOADS: {
  1635. id=0x000C ;
  1636. } break;
  1637. case SYSTEM_DIR_MOVIES: {
  1638. id=CSIDL_MYVIDEO;
  1639. } break;
  1640. case SYSTEM_DIR_MUSIC: {
  1641. id=CSIDL_MYMUSIC;
  1642. } break;
  1643. case SYSTEM_DIR_PICTURES: {
  1644. id=CSIDL_MYPICTURES;
  1645. } break;
  1646. case SYSTEM_DIR_RINGTONES: {
  1647. id=CSIDL_MYMUSIC;
  1648. } break;
  1649. }
  1650. WCHAR szPath[MAX_PATH];
  1651. HRESULT res = SHGetFolderPathW(NULL,id,NULL,0,szPath);
  1652. ERR_FAIL_COND_V(res!=S_OK,String());
  1653. return String(szPath);
  1654. }
  1655. String OS_Windows::get_data_dir() const {
  1656. String an = Globals::get_singleton()->get("application/name");
  1657. if (an!="") {
  1658. if (has_environment("APPDATA")) {
  1659. bool use_godot = Globals::get_singleton()->get("application/use_shared_user_dir");
  1660. if (!use_godot)
  1661. return (OS::get_singleton()->get_environment("APPDATA")+"/"+an).replace("\\","/");
  1662. else
  1663. return (OS::get_singleton()->get_environment("APPDATA")+"/Godot/app_userdata/"+an).replace("\\","/");
  1664. }
  1665. }
  1666. return Globals::get_singleton()->get_resource_path();
  1667. }
  1668. OS_Windows::OS_Windows(HINSTANCE _hInstance) {
  1669. key_event_pos=0;
  1670. force_quit=false;
  1671. alt_mem=false;
  1672. gr_mem=false;
  1673. shift_mem=false;
  1674. control_mem=false;
  1675. meta_mem=false;
  1676. minimized = false;
  1677. hInstance=_hInstance;
  1678. pressrc=0;
  1679. old_invalid=true;
  1680. last_id=0;
  1681. mouse_mode=MOUSE_MODE_VISIBLE;
  1682. #ifdef STDOUT_FILE
  1683. stdo=fopen("stdout.txt","wb");
  1684. #endif
  1685. user_proc = NULL;
  1686. #ifdef RTAUDIO_ENABLED
  1687. AudioDriverManagerSW::add_driver(&driver_rtaudio);
  1688. #endif
  1689. }
  1690. OS_Windows::~OS_Windows()
  1691. {
  1692. #ifdef STDOUT_FILE
  1693. fclose(stdo);
  1694. #endif
  1695. }