Window.hl.hx 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878
  1. package hxd;
  2. import hxd.Key in K;
  3. import hxd.impl.MouseMode;
  4. #if (hlsdl && hldx)
  5. #error "You shouldn't use both -lib hlsdl and -lib hldx"
  6. #end
  7. #if hlsdl
  8. typedef DisplayMode = sdl.Window.DisplayMode;
  9. #elseif hldx
  10. typedef DisplayMode = dx.Window.DisplayMode;
  11. #else
  12. enum DisplayMode {
  13. Windowed;
  14. Borderless;
  15. Fullscreen;
  16. }
  17. #end
  18. typedef Monitor = {
  19. name : String,
  20. width : Int,
  21. height : Int
  22. }
  23. typedef DisplaySetting = {
  24. width : Int,
  25. height : Int,
  26. framerate : Int
  27. }
  28. private class NativeDroppedFile extends hxd.DropFileEvent.DroppedFile {
  29. public function getBytes( callback : ( data : haxe.io.Bytes ) -> Void ) {
  30. haxe.Timer.delay(() -> callback(sys.io.File.getBytes(file)), 1);
  31. }
  32. }
  33. //@:coreApi
  34. class Window {
  35. static var WINDOWS : Array<Window> = [];
  36. var resizeEvents : List<Void -> Void>;
  37. var eventTargets : List<Event -> Void>;
  38. var dropTargets : List<DropFileEvent -> Void>;
  39. var dropFiles : Array<hxd.DropFileEvent.DroppedFile>;
  40. public var id : Int;
  41. public var width(get, never) : Int;
  42. public var height(get, never) : Int;
  43. public var mouseX(get, never) : Int;
  44. public var mouseY(get, never) : Int;
  45. @:deprecated("Use mouseMode = AbsoluteUnbound(true)")
  46. public var mouseLock(get, set) : Bool;
  47. /**
  48. If set, will restrain the mouse cursor within the window boundaries.
  49. **/
  50. public var mouseClip(get, set) : Bool;
  51. /**
  52. Set the mouse movement input handling mode.
  53. @see `hxd.impl.MouseMode` for more details on each mode.
  54. **/
  55. public var mouseMode(default, set): MouseMode = Absolute;
  56. public var monitor : Null<Int> = null;
  57. public var framerate : Null<Int> = null;
  58. public var vsync(get, set) : Bool;
  59. public var isFocused(get, never) : Bool;
  60. public var title(get, set) : String;
  61. public var displayMode(get, set) : DisplayMode;
  62. #if (hl_ver >= version("1.12.0"))
  63. public var currentMonitorIndex(get,null) : Int;
  64. #end
  65. #if hlsdl
  66. var window : sdl.Window;
  67. #elseif hldx
  68. var window : dx.Window;
  69. var _mouseClip : Bool;
  70. #end
  71. var windowWidth = 800;
  72. var windowHeight = 600;
  73. var curMouseX = 0;
  74. var curMouseY = 0;
  75. var startMouseX = 0;
  76. var startMouseY = 0;
  77. var savedSize : { x : Int, y : Int, width : Int, height : Int };
  78. static var CODEMAP = [for( i in 0...2048 ) i];
  79. static var MIN_HEIGHT = 720;
  80. static var MIN_FRAMERATE = 60; // 30 and 60 are always allowed
  81. #if hlsdl
  82. static inline var TOUCH_SCALE = #if (hl_ver >= version("1.12.0")) 10000 #else 100 #end;
  83. #if heaps_vulkan
  84. public static var USE_VULKAN = false;
  85. #end
  86. #end
  87. function new(title:String, width:Int, height:Int, fixed:Bool = false) {
  88. this.windowWidth = width;
  89. this.windowHeight = height;
  90. eventTargets = new List();
  91. resizeEvents = new List();
  92. dropTargets = new List();
  93. #if hlsdl
  94. var sdlFlags = if (!fixed) sdl.Window.SDL_WINDOW_SHOWN | sdl.Window.SDL_WINDOW_RESIZABLE else sdl.Window.SDL_WINDOW_SHOWN;
  95. #if heaps_vulkan
  96. if( USE_VULKAN ) sdlFlags |= sdl.Window.SDL_WINDOW_VULKAN;
  97. #end
  98. window = new sdl.Window(title, width, height, sdl.Window.SDL_WINDOWPOS_CENTERED, sdl.Window.SDL_WINDOWPOS_CENTERED, sdlFlags);
  99. this.windowWidth = window.width;
  100. this.windowHeight = window.height;
  101. #elseif hldx
  102. final dxFlags = if (!fixed) dx.Window.RESIZABLE else 0;
  103. window = new dx.Window(title, width, height, dx.Window.CW_USEDEFAULT, dx.Window.CW_USEDEFAULT, dxFlags);
  104. #end
  105. WINDOWS.push(this);
  106. #if multidriver
  107. id = window.id;
  108. #end
  109. }
  110. public dynamic function onClose() : Bool {
  111. return true;
  112. }
  113. public dynamic function onMove() : Void {
  114. }
  115. public dynamic function onMouseModeChange( from : MouseMode, to : MouseMode ) : Null<MouseMode> {
  116. return null;
  117. }
  118. public function close() {
  119. if( !WINDOWS.remove(this) )
  120. return;
  121. #if (multidriver && (hlsdl || hldx))
  122. window.destroy();
  123. #end
  124. }
  125. public function event( e : hxd.Event ) : Void {
  126. for( et in eventTargets )
  127. et(e);
  128. }
  129. public function addEventTarget(et : Event -> Void) : Void {
  130. eventTargets.add(et);
  131. }
  132. public function removeEventTarget(et : Event -> Void) : Void {
  133. for( e in eventTargets )
  134. if( Reflect.compareMethods(e,et) ) {
  135. eventTargets.remove(e);
  136. break;
  137. }
  138. }
  139. public function addResizeEvent( f : Void -> Void ) : Void {
  140. resizeEvents.push(f);
  141. }
  142. public function removeResizeEvent( f : Void -> Void ) : Void {
  143. for( e in resizeEvents )
  144. if( Reflect.compareMethods(e,f) ) {
  145. resizeEvents.remove(f);
  146. break;
  147. }
  148. }
  149. function onResize(e:Dynamic) : Void {
  150. for( r in resizeEvents )
  151. r();
  152. }
  153. public function resize( width : Int, height : Int ) : Void {
  154. #if (hldx || hlsdl)
  155. if( window.displayMode == Fullscreen ) {
  156. #if (hlsdl && hl_ver >= version("1.12.0") )
  157. var cds = getCurrentDisplaySetting();
  158. var mode = getBestDisplayMode(width, height, framerate != null ? framerate : cds.framerate);
  159. if(mode != null) {
  160. @:privateAccess sdl.Window.winSetDisplayMode(window.win, mode.mode.width, mode.mode.height, mode.mode.framerate);
  161. width = mode.mode.width;
  162. height = mode.mode.height;
  163. }
  164. #end
  165. }
  166. window.resize(width, height);
  167. #end
  168. windowWidth = width;
  169. windowHeight = height;
  170. for( f in resizeEvents ) f();
  171. }
  172. public function addDragAndDropTarget( f : ( event : DropFileEvent ) -> Void ) : Void {
  173. if (dropTargets.length == 0) {
  174. #if (hlsdl >= version("1.14.0"))
  175. sdl.Sdl.setDragAndDropEnabled(true);
  176. #elseif (hldx >= version("1.14.0"))
  177. window.dragAndDropEnabled = true;
  178. #end
  179. }
  180. dropTargets.push(f);
  181. }
  182. public function removeDragAndDropTarget( f : ( event : DropFileEvent ) -> Void ) : Void {
  183. for( e in dropTargets )
  184. if( Reflect.compareMethods(e, f) ) {
  185. dropTargets.remove(f);
  186. break;
  187. }
  188. if ( dropTargets.length == 0 ) {
  189. #if (hlsdl >= version("1.14.0"))
  190. sdl.Sdl.setDragAndDropEnabled(false);
  191. #elseif (hldx >= version("1.14.0"))
  192. window.dragAndDropEnabled = false;
  193. #end
  194. }
  195. }
  196. public function setCursorPos( x : Int, y : Int, emitEvent : Bool = false ) : Void {
  197. #if hldx
  198. if (mouseMode == Absolute) window.setCursorPosition(x, y);
  199. #elseif hlsdl
  200. if (mouseMode == Absolute) window.warpMouse(x, y);
  201. #else
  202. throw "Not implemented";
  203. #end
  204. curMouseX = x;
  205. curMouseY = y;
  206. if (emitEvent) event(new hxd.Event(EMove, x, y));
  207. }
  208. @:deprecated("Use the displayMode property instead")
  209. public function setFullScreen( v : Bool ) : Void {
  210. #if (hldx || hlsdl)
  211. window.displayMode = v ? Borderless : Windowed;
  212. #end
  213. }
  214. function get_mouseX() : Int {
  215. return curMouseX;
  216. }
  217. function get_mouseY() : Int {
  218. return curMouseY;
  219. }
  220. function get_width() : Int {
  221. return windowWidth;
  222. }
  223. function get_height() : Int {
  224. return windowHeight;
  225. }
  226. function get_mouseLock() : Bool {
  227. return switch (mouseMode) { case AbsoluteUnbound(_): true; default: false; };
  228. }
  229. function set_mouseLock(v:Bool) : Bool {
  230. return set_mouseMode(v ? AbsoluteUnbound(true) : Absolute).equals(AbsoluteUnbound(true));
  231. }
  232. function get_mouseClip() : Bool {
  233. #if hldx
  234. return _mouseClip;
  235. #elseif hlsdl
  236. return window.grab;
  237. #else
  238. return false;
  239. #end
  240. }
  241. function set_mouseClip( v : Bool ) : Bool {
  242. #if hldx
  243. window.clipCursor(v);
  244. return _mouseClip = v;
  245. #elseif hlsdl
  246. return window.grab = v;
  247. #else
  248. if( v ) throw "Not implemented";
  249. return false;
  250. #end
  251. }
  252. function set_mouseMode( v : MouseMode ) : MouseMode {
  253. if ( v.equals(mouseMode) ) return v;
  254. var forced = onMouseModeChange(mouseMode, v);
  255. if (forced != null) v = forced;
  256. #if hldx
  257. window.setRelativeMouseMode(v != Absolute);
  258. return mouseMode = v;
  259. #elseif hlsdl
  260. sdl.Sdl.setRelativeMouseMode(v != Absolute);
  261. #else
  262. if ( v != Absolute ) throw "Not implemented";
  263. #end
  264. if ( v == Absolute ) {
  265. switch ( mouseMode ) {
  266. case Relative(_, restorePos) | AbsoluteUnbound(restorePos):
  267. if ( restorePos ) {
  268. curMouseX = startMouseX;
  269. curMouseY = startMouseY;
  270. } else {
  271. curMouseX = hxd.Math.iclamp(curMouseX, 0, width);
  272. curMouseY = hxd.Math.iclamp(curMouseY, 0, height);
  273. }
  274. #if hldx
  275. window.setCursorPosition(curMouseX, curMouseY);
  276. #elseif hlsdl
  277. window.warpMouse(curMouseX, curMouseY);
  278. #end
  279. default:
  280. }
  281. }
  282. startMouseX = curMouseX;
  283. startMouseY = curMouseY;
  284. return mouseMode = v;
  285. }
  286. #if usesys
  287. function get_vsync() : Bool return haxe.System.vsync;
  288. function set_vsync( b : Bool ) : Bool {
  289. return haxe.System.vsync = b;
  290. }
  291. function get_isFocused() : Bool return true;
  292. function onEvent( e : Event ) : Bool {
  293. event(e);
  294. return true;
  295. }
  296. #elseif (hldx||hlsdl)
  297. function get_vsync() : Bool return window.vsync;
  298. function set_vsync( b : Bool ) : Bool {
  299. window.vsync = b;
  300. return b;
  301. }
  302. function get_isFocused() : Bool return !wasBlurred;
  303. var wasBlurred : Bool;
  304. function onEvent( e : #if hldx dx.Event #else sdl.Event #end ) : Bool {
  305. var eh = null;
  306. switch( e.type ) {
  307. case WindowState:
  308. switch( e.state ) {
  309. case Resize:
  310. windowWidth = window.width;
  311. windowHeight = window.height;
  312. onResize(null);
  313. case Focus:
  314. #if hldx
  315. // return to exclusive mode
  316. if( window.displayMode == Fullscreen && wasBlurred ) {
  317. window.displayMode = Borderless;
  318. window.displayMode = Fullscreen;
  319. }
  320. #end
  321. wasBlurred = false;
  322. event(new Event(EFocus));
  323. case Blur:
  324. wasBlurred = true;
  325. event(new Event(EFocusLost));
  326. #if hldx
  327. // release all keys
  328. var ev = new Event(EKeyUp);
  329. for( i in 0...@:privateAccess hxd.Key.keyPressed.length )
  330. if( hxd.Key.isDown(i) ) {
  331. ev.keyCode = i;
  332. event(ev);
  333. }
  334. #end
  335. case Enter:
  336. #if hldx
  337. // Restore cursor
  338. var cur = @:privateAccess hxd.System.currentNativeCursor;
  339. @:privateAccess hxd.System.currentNativeCursor = null;
  340. hxd.System.setNativeCursor(cur);
  341. #end
  342. event(new Event(EOver));
  343. case Leave:
  344. event(new Event(EOut));
  345. case Close:
  346. return onCloseEvent();
  347. case Move:
  348. if( onMove != null )
  349. onMove();
  350. default:
  351. }
  352. case MouseDown if (!hxd.System.getValue(IsTouch)):
  353. if (mouseMode == Absolute) {
  354. curMouseX = e.mouseX;
  355. curMouseY = e.mouseY;
  356. }
  357. eh = new Event(EPush, curMouseX, curMouseY);
  358. // middle button -> 2 / right button -> 1
  359. eh.button = switch( e.button - 1 ) {
  360. case 0: 0;
  361. case 1: 2;
  362. case 2: 1;
  363. case x: x;
  364. }
  365. case MouseUp if (!hxd.System.getValue(IsTouch)):
  366. if (mouseMode == Absolute) {
  367. curMouseX = e.mouseX;
  368. curMouseY = e.mouseY;
  369. }
  370. eh = new Event(ERelease, curMouseX, curMouseY);
  371. eh.button = switch( e.button - 1 ) {
  372. case 0: 0;
  373. case 1: 2;
  374. case 2: 1;
  375. case x: x;
  376. };
  377. case MouseMove if (!hxd.System.getValue(IsTouch)):
  378. switch (mouseMode) {
  379. case Absolute:
  380. curMouseX = e.mouseX;
  381. curMouseY = e.mouseY;
  382. eh = new Event(EMove, e.mouseX, e.mouseY);
  383. case Relative(callback, _):
  384. #if (hldx || hlsdl)
  385. var ev = new Event(EMove, e.mouseXRel, e.mouseYRel);
  386. #else
  387. var ev = new Event(EMove, e.mouseX - curMouseX, e.mouseY - curMouseY);
  388. #end
  389. callback(ev);
  390. if (!ev.cancel && ev.propagate) {
  391. ev.cancel = false;
  392. ev.propagate = false;
  393. ev.relX = curMouseX;
  394. ev.relY = curMouseY;
  395. eh = ev;
  396. }
  397. case AbsoluteUnbound(_):
  398. #if (hldx || hlsdl)
  399. curMouseX += e.mouseXRel;
  400. curMouseY += e.mouseYRel;
  401. #else
  402. curMouseX += e.mouseX - curMouseX;
  403. curMouseY += e.mouseY - curMouseY;
  404. #end
  405. eh = new Event(EMove, curMouseX, curMouseY);
  406. }
  407. case MouseWheel:
  408. eh = new Event(EWheel, mouseX, mouseY);
  409. eh.wheelDelta = -e.wheelDelta;
  410. #if hlsdl
  411. case GControllerAdded, GControllerRemoved, GControllerUp, GControllerDown, GControllerAxis:
  412. @:privateAccess hxd.Pad.onEvent( e );
  413. case KeyDown:
  414. eh = new Event(EKeyDown, curMouseX, curMouseY);
  415. if( e.keyCode & (1 << 30) != 0 ) e.keyCode = (e.keyCode & ((1 << 30) - 1)) + 1000;
  416. eh.keyCode = CODEMAP[e.keyCode];
  417. if( eh.keyCode & (K.LOC_LEFT | K.LOC_RIGHT) != 0 ) {
  418. e.keyCode = eh.keyCode & 0xFF;
  419. onEvent(e);
  420. }
  421. case KeyUp:
  422. eh = new Event(EKeyUp, curMouseX, curMouseY);
  423. if( e.keyCode & (1 << 30) != 0 ) e.keyCode = (e.keyCode & ((1 << 30) - 1)) + 1000;
  424. eh.keyCode = CODEMAP[e.keyCode];
  425. if( eh.keyCode & (K.LOC_LEFT | K.LOC_RIGHT) != 0 ) {
  426. e.keyCode = eh.keyCode & 0xFF;
  427. onEvent(e);
  428. }
  429. case TextInput:
  430. eh = new Event(ETextInput, mouseX, mouseY);
  431. var c = e.keyCode & 0xFF;
  432. eh.charCode = if( c < 0x7F )
  433. c;
  434. else if( c < 0xE0 )
  435. ((c & 0x3F) << 6) | ((e.keyCode >> 8) & 0x7F);
  436. else if( c < 0xF0 )
  437. ((c & 0x1F) << 12) | (((e.keyCode >> 8) & 0x7F) << 6) | ((e.keyCode >> 16) & 0x7F);
  438. else
  439. ((c & 0x0F) << 18) | (((e.keyCode >> 8) & 0x7F) << 12) | (((e.keyCode >> 16) & 0x7F) << 6) | ((e.keyCode >> 24) & 0x7F);
  440. case TouchDown if (hxd.System.getValue(IsTouch)):
  441. #if hlsdl
  442. e.mouseX = Std.int(windowWidth * e.mouseX / TOUCH_SCALE);
  443. e.mouseY = Std.int(windowHeight * e.mouseY / TOUCH_SCALE);
  444. #end
  445. eh = new Event(EPush, e.mouseX, e.mouseY);
  446. eh.touchId = e.fingerId;
  447. case TouchMove if (hxd.System.getValue(IsTouch)):
  448. #if hlsdl
  449. e.mouseX = Std.int(windowWidth * e.mouseX / TOUCH_SCALE);
  450. e.mouseY = Std.int(windowHeight * e.mouseY / TOUCH_SCALE);
  451. #end
  452. eh = new Event(EMove, e.mouseX, e.mouseY);
  453. eh.touchId = e.fingerId;
  454. case TouchUp if (hxd.System.getValue(IsTouch)):
  455. #if hlsdl
  456. e.mouseX = Std.int(windowWidth * e.mouseX / TOUCH_SCALE);
  457. e.mouseY = Std.int(windowHeight * e.mouseY / TOUCH_SCALE);
  458. #end
  459. eh = new Event(ERelease, e.mouseX, e.mouseY);
  460. eh.touchId = e.fingerId;
  461. #elseif hldx
  462. case KeyDown:
  463. eh = new Event(EKeyDown, curMouseX, curMouseY);
  464. eh.keyCode = e.keyCode;
  465. if( eh.keyCode & (K.LOC_LEFT | K.LOC_RIGHT) != 0 ) {
  466. e.keyCode = eh.keyCode & 0xFF;
  467. onEvent(e);
  468. }
  469. case KeyUp:
  470. eh = new Event(EKeyUp, curMouseX, curMouseY);
  471. eh.keyCode = CODEMAP[e.keyCode];
  472. if( eh.keyCode & (K.LOC_LEFT | K.LOC_RIGHT) != 0 ) {
  473. e.keyCode = eh.keyCode & 0xFF;
  474. onEvent(e);
  475. }
  476. case TextInput:
  477. eh = new Event(ETextInput, mouseX, mouseY);
  478. eh.charCode = e.keyCode;
  479. #end
  480. #if (hlsdl >= version("1.14.0") || hldx >= version("1.14.0"))
  481. case DropStart:
  482. dropFiles = [];
  483. case DropFile:
  484. #if hlsdl
  485. dropFiles.push(new NativeDroppedFile(@:privateAccess String.fromUTF8(e.dropFile)));
  486. #else
  487. dropFiles.push(new NativeDroppedFile(@:privateAccess String.fromUCS2(e.dropFile)));
  488. #end
  489. case DropEnd:
  490. var event = new DropFileEvent(
  491. dropFiles,
  492. #if hldx
  493. e.mouseX, e.mouseY
  494. #else
  495. mouseX, mouseY
  496. #end
  497. );
  498. for ( dt in dropTargets ) dt(event);
  499. dropFiles = null;
  500. #end
  501. #if (hlsdl >= version("1.16.0") || hldx >= version("1.16.0"))
  502. case KeyMapChanged:
  503. hxd.System.onKeyboardLayoutChange();
  504. #end
  505. #if !hlsdl // hlsdl post both Close+Quit
  506. case Quit:
  507. return onCloseEvent();
  508. #end
  509. default:
  510. }
  511. if( eh != null ) event(eh);
  512. return true;
  513. }
  514. function onCloseEvent() {
  515. var ret = onClose();
  516. if( ret )
  517. close();
  518. return ret;
  519. }
  520. static function initChars() : Void {
  521. inline function addKey(sdl, keyCode) {
  522. CODEMAP[sdl] = keyCode;
  523. }
  524. // ASCII
  525. for( i in 0...26 )
  526. addKey(97 + i, K.A + i);
  527. for( i in 0...12 )
  528. addKey(1058 + i, K.F1 + i);
  529. for( i in 0...12 )
  530. addKey(1104 + i, K.F13 + i);
  531. // NUMPAD
  532. addKey(1084, K.NUMPAD_DIV);
  533. addKey(1085, K.NUMPAD_MULT);
  534. addKey(1086, K.NUMPAD_SUB);
  535. addKey(1087, K.NUMPAD_ADD);
  536. addKey(1088, K.NUMPAD_ENTER);
  537. for( i in 0...9 )
  538. addKey(1089 + i, K.NUMPAD_1 + i);
  539. addKey(1098, K.NUMPAD_0);
  540. addKey(1099, K.NUMPAD_DOT);
  541. // EXTRA
  542. var keys = [
  543. //K.BACKSPACE
  544. //K.TAB
  545. //K.ENTER
  546. 1225 => K.LSHIFT,
  547. 1229 => K.RSHIFT,
  548. 1224 => K.LCTRL,
  549. 1228 => K.RCTRL,
  550. 1226 => K.LALT,
  551. 1230 => K.RALT,
  552. 1227 => K.LEFT_WINDOW_KEY,
  553. 1231 => K.RIGHT_WINDOW_KEY,
  554. // K.ESCAPE
  555. // K.SPACE
  556. 1075 => K.PGUP,
  557. 1078 => K.PGDOWN,
  558. 1077 => K.END,
  559. 1074 => K.HOME,
  560. 1080 => K.LEFT,
  561. 1082 => K.UP,
  562. 1079 => K.RIGHT,
  563. 1081 => K.DOWN,
  564. 1073 => K.INSERT,
  565. 127 => K.DELETE,
  566. //K.NUMPAD_0-9
  567. //K.A-Z
  568. //K.F1-F12
  569. 1085 => K.NUMPAD_MULT,
  570. 1087 => K.NUMPAD_ADD,
  571. 1088 => K.NUMPAD_ENTER,
  572. 1086 => K.NUMPAD_SUB,
  573. 1099 => K.NUMPAD_DOT,
  574. 1084 => K.NUMPAD_DIV,
  575. 39 => K.QWERTY_QUOTE,
  576. 44 => K.QWERTY_COMMA,
  577. 45 => K.QWERTY_MINUS,
  578. 46 => K.QWERTY_PERIOD,
  579. 47 => K.QWERTY_SLASH,
  580. 59 => K.QWERTY_SEMICOLON,
  581. 61 => K.QWERTY_EQUALS,
  582. 91 => K.QWERTY_BRACKET_LEFT,
  583. 92 => K.QWERTY_BACKSLASH,
  584. 93 => K.QWERTY_BRACKET_RIGHT,
  585. 96 => K.QWERTY_TILDE,
  586. 167 => K.QWERTY_BACKSLASH,
  587. // AZERTY
  588. 41 => K.QWERTY_BRACKET_LEFT, // degree
  589. 94 => K.QWERTY_BRACKET_RIGHT, // caret
  590. 249 => K.QWERTY_TILDE, // percent
  591. 58 => K.QWERTY_SLASH, // slash
  592. 1101 => K.CONTEXT_MENU,
  593. 1057 => K.CAPS_LOCK,
  594. 1071 => K.SCROLL_LOCK,
  595. 1072 => K.PAUSE_BREAK,
  596. 1083 => K.NUM_LOCK,
  597. // LowerThan on AZERTY, none on QWERTY because hlsdl uses sym code, instead of scancode - INTL_BACKSLASH always reports 0x5C, e.g. regular slash.
  598. 60 => K.INTL_BACKSLASH,
  599. //1070 => K.PRINT_SCREEN
  600. ];
  601. for( sdl in keys.keys() )
  602. addKey(sdl, keys.get(sdl));
  603. }
  604. #else
  605. function get_vsync() : Bool return true;
  606. function set_vsync( b : Bool ) : Bool {
  607. return true;
  608. }
  609. function get_isFocused() : Bool return false;
  610. function onEvent( e : Event ) : Bool {
  611. event(e);
  612. return true;
  613. }
  614. #end
  615. function get_displayMode() : DisplayMode {
  616. #if (hldx || hlsdl)
  617. return window.displayMode;
  618. #end
  619. return Windowed;
  620. }
  621. function set_displayMode( m : DisplayMode ) : DisplayMode {
  622. #if (hldx || hlsdl)
  623. var oldMode = window.displayMode;
  624. #if (hl_ver >= version("1.12.0"))
  625. var oldMode = window.displayMode;
  626. if( window.displayMode != m ) {
  627. if(window.displayMode == Windowed) {
  628. if( savedSize == null ) {
  629. savedSize = { x: window.x, y: window.y, width: window.width, height: window.height };
  630. }
  631. }
  632. }
  633. // No way to choose the screen in SDL, need to fit the window in the right screen before.
  634. if(m != Windowed) {
  635. window.displayMode = Windowed;
  636. var mon = selectedMonitor();
  637. if(mon != null) {
  638. window.setPosition(mon.left, mon.top);
  639. window.resize(mon.right-mon.left, mon.bottom-mon.top);
  640. }
  641. }
  642. if( m == Fullscreen ) {
  643. var cds = getCurrentDisplaySetting();
  644. var dm = getBestDisplayMode(windowWidth, windowHeight, framerate != null ? framerate : cds.framerate);
  645. if(dm == null)
  646. return oldMode;
  647. window.displaySetting = dm.mode;
  648. #if hldx
  649. var mon = selectedMonitor();
  650. window.selectedMonitor = mon != null ? mon.name : null;
  651. #end
  652. window.displayMode = m;
  653. window.resize(dm.mode.width, dm.mode.height);
  654. }
  655. else {
  656. window.displayMode = m;
  657. if( oldMode != m && m == Windowed && savedSize != null) {
  658. window.setPosition(savedSize.x, savedSize.y);
  659. window.resize(savedSize.width, savedSize.height);
  660. savedSize = null;
  661. }
  662. }
  663. #else
  664. window.displayMode = m;
  665. #end
  666. #end
  667. return displayMode;
  668. }
  669. public function applyDisplay() {
  670. displayMode = displayMode;
  671. }
  672. #if (hl_ver >= version("1.12.0"))
  673. public static function getMonitors() : Array<Monitor> {
  674. return [for(m in #if hldx dx.Window.getMonitors() #elseif hlsdl sdl.Sdl.getDisplays() #else [] #end) { name: m.name, width: m.right-m.left, height: m.bottom-m.top}];
  675. }
  676. // If registry is set, return the default DisplaySetting when it's currently modified by the application.
  677. public function getCurrentDisplaySetting(?monitorId : Int, registry : Bool = false) : DisplaySetting {
  678. #if hldx
  679. var mon = monitorId != null ? getMonitors()[monitorId] : null;
  680. return dx.Window.getCurrentDisplaySetting(mon == null ? null : mon.name, registry);
  681. #elseif hlsdl
  682. return sdl.Sdl.getCurrentDisplayMode(monitorId == null ? 0 : monitorId, true);
  683. #else
  684. return null;
  685. #end
  686. }
  687. public function getDisplaySettings(?monitorId : Int) : Array<DisplaySetting> {
  688. var map = new Map<String,DisplaySetting>();
  689. var f = [];
  690. if(monitorId == null)
  691. monitorId = monitor;
  692. #if hldx
  693. var m = dx.Window.getMonitors()[monitorId];
  694. var l = m != null ? dx.Window.getDisplaySettings(m.name) : [];
  695. #elseif hlsdl
  696. var l = sdl.Sdl.getDisplayModes( monitorId == null ? window.currentMonitor : monitorId );
  697. #else
  698. var l = [];
  699. #end
  700. for(d in l) {
  701. if(d.height >= MIN_HEIGHT && (d.framerate >= MIN_FRAMERATE || d.framerate == 30 || d.framerate == 60)) {
  702. f.push(d);
  703. }
  704. }
  705. if(f.length > 0)
  706. return f;
  707. else
  708. return l;
  709. }
  710. function selectedMonitor() : Dynamic {
  711. var m = if(monitor == null) currentMonitorIndex else monitor;
  712. #if hldx
  713. return dx.Window.getMonitors()[m];
  714. #elseif hlsdl
  715. return sdl.Sdl.getDisplays()[m];
  716. #else
  717. return null;
  718. #end
  719. }
  720. function getBestDisplayMode(width, height, framerate) {
  721. var m : {idx: Int, mode: DisplaySetting } = {
  722. idx: -1,
  723. mode: null
  724. }
  725. var defaultId = -1;
  726. var def = getCurrentDisplaySetting(currentMonitorIndex, true);
  727. for( i => s in getDisplaySettings(currentMonitorIndex) ) {
  728. if(s.width == def.width && s.height == def.height && s.framerate == def.framerate)
  729. defaultId = i;
  730. if(s.width == width && s.height == height) {
  731. if(s.framerate == framerate)
  732. return { idx: i, mode: s };
  733. else if(s.framerate == def.framerate)
  734. m = {idx : i, mode : s };
  735. else if(m.idx == -1)
  736. m = {idx: i, mode : s };
  737. }
  738. }
  739. return m.idx == -1 ? { idx: defaultId, mode: def } : m;
  740. }
  741. function get_currentMonitorIndex() : Int {
  742. #if hldx
  743. var current = window.getCurrentMonitor();
  744. for(i => m in getMonitors()) {
  745. if(m.name == current)
  746. return i;
  747. }
  748. return 0;
  749. #elseif hlsdl
  750. return window.currentMonitor;
  751. #else
  752. return 0;
  753. #end
  754. }
  755. #end
  756. function get_title() : String {
  757. #if (hldx || hlsdl)
  758. return window.title;
  759. #end
  760. return "";
  761. }
  762. function set_title( t : String ) : String {
  763. #if (hldx || hlsdl)
  764. return window.title = t;
  765. #end
  766. return "";
  767. }
  768. public function setCurrent() {
  769. inst = this;
  770. #if hlsdl
  771. window.renderTo();
  772. #end
  773. }
  774. static var inst : Window = null;
  775. public static function getInstance() : Window {
  776. return inst;
  777. }
  778. public static function hasWindow() {
  779. return WINDOWS.length > 0;
  780. }
  781. static function dispatchEvent( e ) {
  782. #if multidriver
  783. if( false ) @:privateAccess WINDOWS[0].onEvent(e); // typing
  784. for( w in WINDOWS )
  785. if( e.windowId == w.id )
  786. return w.onEvent(e);
  787. return true;
  788. #else
  789. return inst.onEvent(e);
  790. #end
  791. }
  792. }