diff --git a/project/include/system/System.h b/project/include/system/System.h index ec67cdd16e..9e53410e7a 100644 --- a/project/include/system/System.h +++ b/project/include/system/System.h @@ -30,6 +30,7 @@ namespace lime { static void GCExitBlocking (); static void GCTryEnterBlocking (); static void GCTryExitBlocking (); + static long GetTicks (); static bool GetAllowScreenTimeout (); static std::wstring* GetDeviceModel (); static std::wstring* GetDeviceVendor (); diff --git a/project/include/ui/KeyEvent.h b/project/include/ui/KeyEvent.h index 28e6fcc6fd..803a6290a9 100644 --- a/project/include/ui/KeyEvent.h +++ b/project/include/ui/KeyEvent.h @@ -25,6 +25,7 @@ namespace lime { int modifier; KeyEventType type; int windowID; + int timestamp; static ValuePointer* callback; static ValuePointer* eventObject; diff --git a/project/src/ExternalInterface.cpp b/project/src/ExternalInterface.cpp index fc1fdf1b41..a12f68db67 100644 --- a/project/src/ExternalInterface.cpp +++ b/project/src/ExternalInterface.cpp @@ -2649,6 +2649,20 @@ namespace lime { } + int lime_sdl_get_ticks () { + + return System::GetTicks (); + + } + + + HL_PRIM int HL_NAME(hl_sdl_get_ticks) () { + + return System::GetTicks (); + + } + + bool lime_system_get_allow_screen_timeout () { return System::GetAllowScreenTimeout (); @@ -3996,6 +4010,7 @@ namespace lime { DEFINE_PRIME3 (lime_png_decode_bytes); DEFINE_PRIME3 (lime_png_decode_file); DEFINE_PRIME2v (lime_render_event_manager_register); + DEFINE_PRIME0 (lime_sdl_get_ticks); DEFINE_PRIME2v (lime_sensor_event_manager_register); DEFINE_PRIME0 (lime_system_get_allow_screen_timeout); DEFINE_PRIME0 (lime_system_get_device_model); @@ -4184,6 +4199,7 @@ namespace lime { DEFINE_HL_PRIM (_TIMAGEBUFFER, hl_png_decode_bytes, _TBYTES _BOOL _TIMAGEBUFFER); DEFINE_HL_PRIM (_TIMAGEBUFFER, hl_png_decode_file, _STRING _BOOL _TIMAGEBUFFER); DEFINE_HL_PRIM (_VOID, hl_render_event_manager_register, _FUN (_VOID, _NO_ARG) _TRENDER_EVENT); + DEFINE_HL_PRIM (_I64, hl_sdl_get_ticks, _FUN (_VOID, _NO_ARG) _TRENDER_EVENT); DEFINE_HL_PRIM (_VOID, hl_sensor_event_manager_register, _FUN (_VOID, _NO_ARG) _TSENSOR_EVENT); DEFINE_HL_PRIM (_BOOL, hl_system_get_allow_screen_timeout, _NO_ARG); DEFINE_HL_PRIM (_BYTES, hl_system_get_device_model, _NO_ARG); diff --git a/project/src/backend/sdl/SDLApplication.cpp b/project/src/backend/sdl/SDLApplication.cpp index 53674f53a9..c3a8df56cf 100644 --- a/project/src/backend/sdl/SDLApplication.cpp +++ b/project/src/backend/sdl/SDLApplication.cpp @@ -561,6 +561,7 @@ namespace lime { keyEvent.keyCode = event->key.keysym.sym; keyEvent.modifier = event->key.keysym.mod; keyEvent.windowID = event->key.windowID; + keyEvent.timestamp = event->key.timestamp; if (keyEvent.type == KEY_DOWN) { diff --git a/project/src/backend/sdl/SDLSystem.cpp b/project/src/backend/sdl/SDLSystem.cpp index 058f2d3dd8..d3cb474924 100644 --- a/project/src/backend/sdl/SDLSystem.cpp +++ b/project/src/backend/sdl/SDLSystem.cpp @@ -91,6 +91,13 @@ namespace lime { } + long System::GetTicks () { + + return SDL_GetTicks (); + + } + + bool System::GetAllowScreenTimeout () { return SDL_IsScreenSaverEnabled (); diff --git a/project/src/ui/KeyEvent.cpp b/project/src/ui/KeyEvent.cpp index 42acd15560..81ad7551c4 100644 --- a/project/src/ui/KeyEvent.cpp +++ b/project/src/ui/KeyEvent.cpp @@ -12,6 +12,7 @@ namespace lime { static int id_modifier; static int id_type; static int id_windowID; + static int id_timestamp; static bool init = false; @@ -21,6 +22,7 @@ namespace lime { modifier = 0; type = KEY_DOWN; windowID = 0; + timestamp = 0; } @@ -37,6 +39,7 @@ namespace lime { id_modifier = val_id ("modifier"); id_type = val_id ("type"); id_windowID = val_id ("windowID"); + id_timestamp = val_id ("timestamp"); init = true; } @@ -47,6 +50,7 @@ namespace lime { alloc_field (object, id_modifier, alloc_int (event->modifier)); alloc_field (object, id_type, alloc_int (event->type)); alloc_field (object, id_windowID, alloc_int (event->windowID)); + alloc_field (object, id_timestamp, alloc_int (event->timestamp)); } else { diff --git a/src/lime/_internal/backend/html5/HTML5Application.hx b/src/lime/_internal/backend/html5/HTML5Application.hx index 3b137e92b1..e518ece390 100644 --- a/src/lime/_internal/backend/html5/HTML5Application.hx +++ b/src/lime/_internal/backend/html5/HTML5Application.hx @@ -1,5 +1,6 @@ package lime._internal.backend.html5; +import haxe.Int64; import js.html.DeviceMotionEvent; import js.html.KeyboardEvent; import js.Browser; @@ -412,12 +413,14 @@ class HTML5Application var keyCode = cast convertKeyCode(event.keyCode != null ? event.keyCode : event.which); var modifier = (event.shiftKey ? (KeyModifier.SHIFT) : 0) | (event.ctrlKey ? (KeyModifier.CTRL) : 0) | (event.altKey ? (KeyModifier.ALT) : 0) | (event.metaKey ? (KeyModifier.META) : 0); + var timestamp = Int64.fromFloat(event.timeStamp); if (event.type == "keydown") { parent.window.onKeyDown.dispatch(keyCode, modifier); + parent.window.onKeyDownPrecise.dispatch(keyCode, modifier, timestamp); - if (parent.window.onKeyDown.canceled && event.cancelable) + if ((parent.window.onKeyDown.canceled || parent.window.onKeyDownPrecise.canceled) && event.cancelable) { event.preventDefault(); } @@ -425,8 +428,9 @@ class HTML5Application else { parent.window.onKeyUp.dispatch(keyCode, modifier); + parent.window.onKeyUpPrecise.dispatch(keyCode, modifier, timestamp); - if (parent.window.onKeyUp.canceled && event.cancelable) + if ((parent.window.onKeyUp.canceled || parent.window.onKeyUpPrecise.canceled) && event.cancelable) { event.preventDefault(); } diff --git a/src/lime/_internal/backend/native/NativeApplication.hx b/src/lime/_internal/backend/native/NativeApplication.hx index 2208624bfb..2bf796b366 100644 --- a/src/lime/_internal/backend/native/NativeApplication.hx +++ b/src/lime/_internal/backend/native/NativeApplication.hx @@ -1,5 +1,6 @@ package lime._internal.backend.native; +import haxe.Int64; import haxe.Timer; import lime._internal.backend.native.NativeCFFI; import lime.app.Application; @@ -254,14 +255,17 @@ class NativeApplication var int32:Float = keyEventInfo.keyCode; var keyCode:KeyCode = Std.int(int32); var modifier:KeyModifier = keyEventInfo.modifier; + var timestamp:Int64 = keyEventInfo.timestamp; switch (type) { case KEY_DOWN: window.onKeyDown.dispatch(keyCode, modifier); + window.onKeyDownPrecise.dispatch(keyCode, modifier, timestamp); case KEY_UP: window.onKeyUp.dispatch(keyCode, modifier); + window.onKeyUpPrecise.dispatch(keyCode, modifier, timestamp); } #if (windows || linux) @@ -761,18 +765,25 @@ class NativeApplication public var modifier:Int; public var type:KeyEventType; public var windowID:Int; + /** + * The timestamp, in milliseconds, of when the event occurred. + * Relative to `lime_sdl_get_ticks()` + * May be `0` if timestamp could not be determined. + */ + public var timestamp:Int64; - public function new(type:KeyEventType = null, windowID:Int = 0, keyCode: Float = 0, modifier:Int = 0) + public function new(type:KeyEventType = null, windowID:Int = 0, keyCode: Float = 0, modifier:Int = 0, timestamp:Null = null) { this.type = type; this.windowID = windowID; this.keyCode = keyCode; this.modifier = modifier; + this.timestamp = timestamp == null ? Int64.ofInt(0) : timestamp; } public function clone():KeyEventInfo { - return new KeyEventInfo(type, windowID, keyCode, modifier); + return new KeyEventInfo(type, windowID, keyCode, modifier, timestamp); } } diff --git a/src/lime/_internal/backend/native/NativeCFFI.hx b/src/lime/_internal/backend/native/NativeCFFI.hx index 7d3b6e65eb..0a4e26f7f7 100644 --- a/src/lime/_internal/backend/native/NativeCFFI.hx +++ b/src/lime/_internal/backend/native/NativeCFFI.hx @@ -1,5 +1,6 @@ package lime._internal.backend.native; +import haxe.Int64; import haxe.io.Bytes; import lime.graphics.opengl.GLBuffer; import lime.graphics.opengl.GLFramebuffer; @@ -239,6 +240,8 @@ class NativeCFFI @:cffi private static function lime_render_event_manager_register(callback:Dynamic, eventObject:Dynamic):Void; + @:cffi private static function lime_sdl_get_ticks():Int; + @:cffi private static function lime_sensor_event_manager_register(callback:Dynamic, eventObject:Dynamic):Void; @:cffi private static function lime_system_get_allow_screen_timeout():Bool; @@ -518,6 +521,7 @@ class NativeCFFI "sboo", false)); private static var lime_render_event_manager_register = new cpp.Callablecpp.Object->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_render_event_manager_register", "oov", false)); + private static var lime_sdl_get_ticks = new cpp.CallableInt>(cpp.Prime._loadPrime("lime", "lime_sdl_get_ticks", "i", false)); private static var lime_sensor_event_manager_register = new cpp.Callablecpp.Object->cpp.Void>(cpp.Prime._loadPrime("lime", "lime_sensor_event_manager_register", "oov", false)); private static var lime_system_get_allow_screen_timeout = new cpp.CallableBool>(cpp.Prime._loadPrime("lime", @@ -715,6 +719,7 @@ class NativeCFFI private static var lime_png_decode_bytes = CFFI.load("lime", "lime_png_decode_bytes", 3); private static var lime_png_decode_file = CFFI.load("lime", "lime_png_decode_file", 3); private static var lime_render_event_manager_register = CFFI.load("lime", "lime_render_event_manager_register", 2); + private static var lime_sdl_get_ticks = CFFI.load("lime", "lime_sdl_get_ticks", 0); private static var lime_sensor_event_manager_register = CFFI.load("lime", "lime_sensor_event_manager_register", 2); private static var lime_system_get_allow_screen_timeout = CFFI.load("lime", "lime_system_get_allow_screen_timeout", 0); private static var lime_system_set_allow_screen_timeout = CFFI.load("lime", "lime_system_set_allow_screen_timeout", 1); @@ -1161,6 +1166,11 @@ class NativeCFFI @:hlNative("lime", "hl_render_event_manager_register") private static function lime_render_event_manager_register(callback:Void->Void, eventObject:RenderEventInfo):Void {} + @:hlNative("lime", "hl_sdl_get_ticks") private static function lime_sdl_get_ticks():Int + { + return 0; + } + @:hlNative("lime", "hl_sensor_event_manager_register") private static function lime_sensor_event_manager_register(callback:Void->Void, eventObject:SensorEventInfo):Void {} diff --git a/src/lime/app/Application.hx b/src/lime/app/Application.hx index 87cf6ce6d1..9befc41972 100644 --- a/src/lime/app/Application.hx +++ b/src/lime/app/Application.hx @@ -1,5 +1,6 @@ package lime.app; +import haxe.Int64; import lime.graphics.RenderContext; import lime.system.System; import lime.ui.Gamepad; @@ -240,6 +241,22 @@ class Application extends Module **/ public function onKeyUp(keyCode:KeyCode, modifier:KeyModifier):Void {} + /** + Called when a key down event is fired on the primary window + @param keyCode The code of the key that was pressed + @param modifier The modifier of the key that was pressed + @param timestamp The timestamp of the event + **/ + public function onKeyDownPrecise(keyCode:KeyCode, modifier:KeyModifier, timestamp:Int64):Void {} + + /** + Called when a key up event is fired on the primary window + @param keyCode The code of the key that was released + @param modifier The modifier of the key that was released + @param timestamp The timestamp of the event + **/ + public function onKeyUpPrecise(keyCode:KeyCode, modifier:KeyModifier, timestamp:Int64):Void {} + /** Called when the module is exiting **/ diff --git a/src/lime/ui/Window.hx b/src/lime/ui/Window.hx index 64810eba3b..7cf39cf304 100644 --- a/src/lime/ui/Window.hx +++ b/src/lime/ui/Window.hx @@ -1,5 +1,6 @@ package lime.ui; +import haxe.Int64; import lime.app.Application; import lime.app.Event; import lime.graphics.Image; @@ -69,6 +70,9 @@ class Window public var onHide(default, null) = new EventVoid>(); public var onKeyDown(default, null) = new EventKeyModifier->Void>(); public var onKeyUp(default, null) = new EventKeyModifier->Void>(); + // TODO: Deprecate and supercede onKeyDown and onKeyUp to include timestamps. + public var onKeyDownPrecise(default, null) = new EventKeyModifier->Int64->Void>(); + public var onKeyUpPrecise(default, null) = new EventKeyModifier->Int64->Void>(); public var onLeave(default, null) = new EventVoid>(); public var onMaximize(default, null) = new EventVoid>(); public var onMinimize(default, null) = new EventVoid>();