From 02bae94a8c2288fb86a580a62a6e418e19b624d7 Mon Sep 17 00:00:00 2001 From: Spitko Date: Wed, 17 Sep 2025 22:34:05 -0700 Subject: [PATCH 01/26] Port hlsdl to SDL3 First pass. Tested major functionality on linux/wayland, seems good. --- .github/workflows/build.yml | 6 +- Brewfile | 2 +- README.md | 8 +- libs/sdl/CMakeLists.txt | 14 +- libs/sdl/README.md | 4 +- libs/sdl/gl.c | 10 +- libs/sdl/sdl.c | 544 +++++++++++++++++++----------------- libs/sdl/sdl.vcxproj | 12 +- libs/sdl/sdl/Sdl.hx | 36 ++- libs/sdl/sdl/Window.hx | 34 ++- 10 files changed, 367 insertions(+), 303 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 754295a05..4fca7fa11 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -128,7 +128,7 @@ jobs: libmbedtls-dev \ libopenal-dev \ libpng-dev \ - libsdl2-dev \ + libsdl3-dev \ libturbojpeg-dev \ libuv1-dev \ libvorbis-dev \ @@ -143,10 +143,10 @@ jobs: ;; windows*) - curl -fsSL --retry 3 --retry-delay 5 -o /tmp/sdl.zip https://www.libsdl.org/release/SDL2-devel-2.30.2-VC.zip + curl -fsSL --retry 3 --retry-delay 5 -o /tmp/sdl.zip https://github.com/libsdl-org/SDL/releases/download/release-3.2.22/SDL3-devel-3.2.22-VC.zip curl -fsSL --retry 3 --retry-delay 5 -o /tmp/openal.zip https://github.com/kcat/openal-soft/releases/download/1.23.1/openal-soft-1.23.1-bin.zip curl -fsSL --retry 3 --retry-delay 5 -o /tmp/ffmpeg.zip ${{ matrix.ffmpeg_url }} - 7z x /tmp/sdl.zip -oinclude; mv include/SDL2* include/sdl + 7z x /tmp/sdl.zip -oinclude; mv include/SDL3* include/sdl 7z x /tmp/openal.zip -oinclude; mv include/openal* include/openal 7z x /tmp/ffmpeg.zip -oinclude; mv include/ffmpeg* include/ffmpeg ;; diff --git a/Brewfile b/Brewfile index 9fa2ce060..365794aa7 100644 --- a/Brewfile +++ b/Brewfile @@ -3,7 +3,7 @@ brew "cmake" brew "jpeg-turbo" brew "libpng" -brew "sdl2" +brew "sdl3" brew "libogg" brew "libvorbis" brew "openal-soft" diff --git a/README.md b/README.md index a0526860d..c1ef909e2 100644 --- a/README.md +++ b/README.md @@ -14,20 +14,20 @@ Here's the dependencies that you install in order to compile all the libraries: * fmt: libpng-dev libturbojpeg-dev libvorbis-dev * openal: libopenal-dev -* sdl: libsdl2-dev libglu1-mesa-dev +* sdl: libsdl3-dev libglu1-mesa-dev * ssl: libmbedtls-dev * uv: libuv1-dev * sqlite: libsqlite3-dev To install all dependencies on the latest **Ubuntu**, for example: -`sudo apt-get install libpng-dev libturbojpeg-dev libvorbis-dev libopenal-dev libsdl2-dev libglu1-mesa-dev libmbedtls-dev libuv1-dev libsqlite3-dev` +`sudo apt-get install libpng-dev libturbojpeg-dev libvorbis-dev libopenal-dev libsdl3-dev libglu1-mesa-dev libmbedtls-dev libuv1-dev libsqlite3-dev` For 16.04, see [this note](https://github.com/HaxeFoundation/hashlink/issues/147). To install all dependencies on the latest **Fedora**, for example: -`sudo dnf install libpng-devel turbojpeg-devel libvorbis-devel openal-soft-devel SDL2-devel mesa-libGLU-devel mbedtls-devel libuv-devel sqlite-devel` +`sudo dnf install libpng-devel turbojpeg-devel libvorbis-devel openal-soft-devel SDL3-devel mesa-libGLU-devel mbedtls-devel libuv-devel sqlite-devel` **And on OSX:** @@ -53,7 +53,7 @@ To build all of HashLink libraries it is required to download several additional In short you'll probably need: -- [SDL2-devel](https://github.com/libsdl-org/SDL/releases/download/release-2.30.12/SDL2-devel-2.30.12-VC.zip), extract to `/include/sdl` +- [SDL3-devel](https://github.com/libsdl-org/SDL/releases/download/release-3.2.22/SDL3-devel-3.2.22-VC.zip), extract to `/include/sdl` - [openal-soft](https://github.com/kcat/openal-soft/releases/download/1.23.1/openal-soft-1.23.1-bin.zip), extract to `/include/openal` ## Debugging diff --git a/libs/sdl/CMakeLists.txt b/libs/sdl/CMakeLists.txt index c26ca0c77..043d75a19 100644 --- a/libs/sdl/CMakeLists.txt +++ b/libs/sdl/CMakeLists.txt @@ -5,9 +5,9 @@ add_library(sdl.hdll if ((NOT WIN32) AND DOWNLOAD_DEPENDENCIES) FetchContent_Declare( - SDL2 - URL https://github.com/libsdl-org/SDL/releases/download/release-2.32.8/SDL2-2.32.8.tar.gz - URL_HASH SHA256=0ca83e9c9b31e18288c7ec811108e58bac1f1bb5ec6577ad386830eac51c787e + SDL3 + URL https://github.com/libsdl-org/SDL/releases/download/release-3.2.22/SDL3-3.2.22.tar.gz + URL_HASH SHA256=f29d00cbcee273c0a54f3f32f86bf5c595e8823a96b1d92a145aac40571ebfcc DOWNLOAD_EXTRACT_TIMESTAMP true EXCLUDE_FROM_ALL ) @@ -22,13 +22,13 @@ if ((NOT WIN32) AND DOWNLOAD_DEPENDENCIES) set(SDL_STATIC_PIC ON CACHE INTERNAL "") endif() endif() - FetchContent_MakeAvailable(SDL2) + FetchContent_MakeAvailable(SDL3) else() if(WIN32) - set(SDL2_DIR ${INCLUDES_BASE_DIR}/sdl/cmake) + set(SDL3_DIR ${INCLUDES_BASE_DIR}/sdl/cmake) endif() - find_package(SDL2 REQUIRED) + find_package(SDL3 REQUIRED CONFIG REQUIRED COMPONENTS SDL3) endif() set_as_hdll(sdl) @@ -38,7 +38,7 @@ target_include_directories(sdl.hdll ) target_link_libraries(sdl.hdll libhl - SDL2::SDL2 + SDL3::SDL3 ) if(APPLE) target_compile_definitions(sdl.hdll PRIVATE GL_SILENCE_DEPRECATION) diff --git a/libs/sdl/README.md b/libs/sdl/README.md index 4d2fd876f..942757e43 100644 --- a/libs/sdl/README.md +++ b/libs/sdl/README.md @@ -1,9 +1,9 @@ hlsdl ===== -HLSDL is a SDL2 backend for HashLink +HLSDL is a SDL3 backend for HashLink Read https://www.libsdl.org/ for more information on SDL -In order to compile on Windows, download the Development Libraries from SDL2 and unzip them into the hashlink/include/sdl directory, so you have the directories hashlink/include/sdl/include and hashlink/include/sdl/lib available. +In order to compile on Windows, download the Development Libraries from SDL3 and unzip them into the hashlink/include/sdl directory, so you have the directories hashlink/include/sdl/include and hashlink/include/sdl/lib available. diff --git a/libs/sdl/gl.c b/libs/sdl/gl.c index 74efd7717..118be4117 100644 --- a/libs/sdl/gl.c +++ b/libs/sdl/gl.c @@ -3,18 +3,18 @@ #include "hlsystem.h" #if defined(HL_IOS) || defined (HL_TVOS) -# include +# include # include # include # define HL_GLES #elif defined(HL_MAC) -# include +# include # include # define glBindImageTexture(...) hl_error("Not supported on OSX") # define glDispatchCompute(...) hl_error("Not supported on OSX") # define glMemoryBarrier(...) hl_error("Not supported on OSX") #elif defined(_WIN32) -# include +# include # include # include #elif defined(HL_CONSOLE) @@ -24,12 +24,12 @@ # include # define HL_GLES #elif defined(HL_ANDROID) -# include +# include # include # include # define HL_GLES #else -# include +# include # include #endif diff --git a/libs/sdl/sdl.c b/libs/sdl/sdl.c index 9baa75cba..e762acac3 100644 --- a/libs/sdl/sdl.c +++ b/libs/sdl/sdl.c @@ -4,7 +4,8 @@ #include "hlsystem.h" #include -#include +#include +#include #if defined(HL_WIN) || defined(HL_IOS) || defined(HL_TVOS) # include @@ -16,7 +17,7 @@ #endif #ifndef SDL_MAJOR_VERSION -# error "SDL2 SDK not found in hl/include/sdl/" +# error "SDL3 SDK not found in hl/include/sdl/" #endif #define TWIN _ABSTRACT(sdl_window) @@ -103,7 +104,7 @@ static bool isGlOptionsSet = false; HL_PRIM bool HL_NAME(init_once)() { SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1"); - if( SDL_Init(SDL_INIT_EVERYTHING) != 0 ) { + if( !SDL_Init( SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_GAMEPAD ) ) { hl_error("SDL_Init failed: %s", hl_to_utf16(SDL_GetError())); return false; } @@ -159,7 +160,7 @@ HL_PRIM void HL_NAME(gl_options)( int major, int minor, int depth, int stencil, } HL_PRIM bool HL_NAME(hint_value)( vbyte* name, vbyte* value) { - return SDL_SetHint((char*)name, (char*)value) == SDL_TRUE; + return SDL_SetHint((char*)name, (char*)value) == true; } HL_PRIM int HL_NAME(event_poll)( SDL_Event *e ) { @@ -169,12 +170,66 @@ HL_PRIM int HL_NAME(event_poll)( SDL_Event *e ) { HL_PRIM bool HL_NAME(event_loop)( event_data *event ) { while (true) { SDL_Event e; - if (SDL_PollEvent(&e) == 0) break; + if ( !SDL_PollEvent(&e) ) break; + + // Handle window events first to make porting easier + if( e.type >= SDL_EVENT_WINDOW_FIRST && e.type <= SDL_EVENT_WINDOW_LAST) + { + event->type = WindowState; + event->window = e.window.windowID; + switch (e.type) { + case SDL_EVENT_WINDOW_SHOWN: + event->state = Show; + break; + case SDL_EVENT_WINDOW_HIDDEN: + event->state = Hide; + break; + case SDL_EVENT_WINDOW_EXPOSED: + event->state = Expose; + break; + case SDL_EVENT_WINDOW_MOVED: + event->state = Move; + break; + case SDL_EVENT_WINDOW_RESIZED: + event->state = Resize; + break; + case SDL_EVENT_WINDOW_MINIMIZED: + event->state = Minimize; + break; + case SDL_EVENT_WINDOW_MAXIMIZED: + event->state = Maximize; + break; + case SDL_EVENT_WINDOW_RESTORED: + event->state = Restore; + break; + case SDL_EVENT_WINDOW_MOUSE_ENTER: + event->state = Enter; + break; + case SDL_EVENT_WINDOW_MOUSE_LEAVE: + event->state = Leave; + break; + case SDL_EVENT_WINDOW_FOCUS_GAINED: + event->state = Focus; + break; + case SDL_EVENT_WINDOW_FOCUS_LOST: + event->state = Blur; + break; + case SDL_EVENT_WINDOW_CLOSE_REQUESTED: + event->state = Close; + break; + default: + //printf("Unknown window state code %d\\n", e.window.event); + continue; + } + + return true; + } + switch (e.type) { - case SDL_QUIT: + case SDL_EVENT_QUIT: event->type = Quit; break; - case SDL_MOUSEMOTION: + case SDL_EVENT_MOUSE_MOTION: event->type = MouseMove; event->window = e.motion.windowID; event->mouseX = e.motion.x; @@ -182,54 +237,52 @@ HL_PRIM bool HL_NAME(event_loop)( event_data *event ) { event->mouseXRel = e.motion.xrel; event->mouseYRel = e.motion.yrel; break; - case SDL_KEYDOWN: + case SDL_EVENT_KEY_DOWN: event->type = KeyDown; event->window = e.key.windowID; - event->keyCode = e.key.keysym.sym; - event->scanCode = e.key.keysym.scancode; + event->keyCode = e.key.key; + event->scanCode = e.key.scancode; event->keyRepeat = e.key.repeat != 0; break; - case SDL_KEYUP: + case SDL_EVENT_KEY_UP: event->type = KeyUp; event->window = e.key.windowID; - event->keyCode = e.key.keysym.sym; - event->scanCode = e.key.keysym.scancode; + event->keyCode = e.key.key; + event->scanCode = e.key.scancode; break; - case SDL_SYSWMEVENT: - continue; - case SDL_MOUSEBUTTONDOWN: + case SDL_EVENT_MOUSE_BUTTON_DOWN: event->type = MouseDown; event->window = e.button.windowID; event->button = e.button.button; event->mouseX = e.button.x; event->mouseY = e.button.y; break; - case SDL_MOUSEBUTTONUP: + case SDL_EVENT_MOUSE_BUTTON_UP: event->type = MouseUp; event->window = e.button.windowID; event->button = e.button.button; event->mouseX = e.button.x; event->mouseY = e.button.y; break; - case SDL_FINGERDOWN: + case SDL_EVENT_FINGER_DOWN: event->type = TouchDown; event->mouseX = (int)(e.tfinger.x*10000); event->mouseY = (int)(e.tfinger.y*10000); - event->reference = (int)e.tfinger.fingerId; + event->reference = (int)e.tfinger.fingerID; break; - case SDL_FINGERMOTION: + case SDL_EVENT_FINGER_MOTION: event->type = TouchMove; event->mouseX = (int)(e.tfinger.x*10000); event->mouseY = (int)(e.tfinger.y*10000); - event->reference = (int)e.tfinger.fingerId; + event->reference = (int)e.tfinger.fingerID; break; - case SDL_FINGERUP: + case SDL_EVENT_FINGER_UP: event->type = TouchUp; event->mouseX = (int)(e.tfinger.x*10000); event->mouseY = (int)(e.tfinger.y*10000); - event->reference = (int)e.tfinger.fingerId; + event->reference = (int)e.tfinger.fingerID; break; - case SDL_MOUSEWHEEL: + case SDL_EVENT_MOUSE_WHEEL: event->type = MouseWheel; event->window = e.wheel.windowID; event->wheelDelta = e.wheel.y; @@ -239,141 +292,93 @@ HL_PRIM bool HL_NAME(event_loop)( event_data *event ) { event->mouseX = e.wheel.x; event->mouseY = e.wheel.y; break; - case SDL_WINDOWEVENT: - event->type = WindowState; - event->window = e.window.windowID; - switch (e.window.event) { - case SDL_WINDOWEVENT_SHOWN: - event->state = Show; - break; - case SDL_WINDOWEVENT_HIDDEN: - event->state = Hide; - break; - case SDL_WINDOWEVENT_EXPOSED: - event->state = Expose; - break; - case SDL_WINDOWEVENT_MOVED: - event->state = Move; - break; - case SDL_WINDOWEVENT_SIZE_CHANGED: - event->state = Resize; - break; - case SDL_WINDOWEVENT_MINIMIZED: - event->state = Minimize; - break; - case SDL_WINDOWEVENT_MAXIMIZED: - event->state = Maximize; - break; - case SDL_WINDOWEVENT_RESTORED: - event->state = Restore; - break; - case SDL_WINDOWEVENT_ENTER: - event->state = Enter; - break; - case SDL_WINDOWEVENT_LEAVE: - event->state = Leave; - break; - case SDL_WINDOWEVENT_FOCUS_GAINED: - event->state = Focus; - break; - case SDL_WINDOWEVENT_FOCUS_LOST: - event->state = Blur; - break; - case SDL_WINDOWEVENT_CLOSE: - event->state = Close; - break; - default: - //printf("Unknown window state code %d\\n", e.window.event); - continue; - } - break; - case SDL_TEXTEDITING: + + case SDL_EVENT_TEXT_EDITING: // skip continue; - case SDL_TEXTINPUT: + case SDL_EVENT_TEXT_INPUT: event->type = TextInput; event->window = e.text.windowID; event->keyCode = *(int*)e.text.text; event->keyCode &= e.text.text[0] ? e.text.text[1] ? e.text.text[2] ? e.text.text[3] ? 0xFFFFFFFF : 0xFFFFFF : 0xFFFF : 0xFF : 0; break; - case SDL_CONTROLLERDEVICEADDED: + case SDL_EVENT_GAMEPAD_ADDED: event->type = GControllerAdded; event->reference = e.jdevice.which; break; - case SDL_CONTROLLERDEVICEREMOVED: + case SDL_EVENT_GAMEPAD_REMOVED: event->type = GControllerRemoved; event->reference = e.jdevice.which; break; - case SDL_CONTROLLERBUTTONDOWN: + case SDL_EVENT_GAMEPAD_BUTTON_DOWN : event->type = GControllerDown; - event->reference = e.cbutton.which; - event->button = e.cbutton.button; + event->reference = e.gbutton.which; + event->button = e.gbutton.button; break; - case SDL_CONTROLLERBUTTONUP: + case SDL_EVENT_GAMEPAD_BUTTON_UP: event->type = GControllerUp; - event->reference = e.cbutton.which; - event->button = e.cbutton.button; + event->reference = e.gbutton.which; + event->button = e.gbutton.button; break; - case SDL_CONTROLLERAXISMOTION: + case SDL_EVENT_GAMEPAD_AXIS_MOTION : event->type = GControllerAxis; - event->reference = e.caxis.which; - event->button = e.caxis.axis; - event->value = e.caxis.value; + event->reference = e.gaxis.which; + event->button = e.gaxis.axis; + event->value = e.gaxis.value; break; - case SDL_JOYAXISMOTION: + case SDL_EVENT_JOYSTICK_AXIS_MOTION: event->type = JoystickAxisMotion; event->reference = e.jaxis.which; event->button = e.jaxis.axis; event->value = e.jaxis.value; break; - case SDL_JOYBALLMOTION: + case SDL_EVENT_JOYSTICK_BALL_MOTION: event->type = JoystickBallMotion; event->reference = e.jball.which; event->button = e.jball.ball; event->mouseXRel = e.jball.xrel; event->mouseYRel = e.jball.yrel; break; - case SDL_JOYHATMOTION: + case SDL_EVENT_JOYSTICK_HAT_MOTION: event->type = JoystickHatMotion; event->reference = e.jhat.which; event->button = e.jhat.hat; event->value = e.jhat.value; break; - case SDL_JOYBUTTONDOWN: + case SDL_EVENT_JOYSTICK_BUTTON_DOWN: event->type = JoystickButtonDown; event->reference = e.jbutton.which; event->button = e.jbutton.button; break; - case SDL_JOYBUTTONUP: + case SDL_EVENT_JOYSTICK_BUTTON_UP: event->type = JoystickButtonUp; event->reference = e.jbutton.which; event->button = e.jbutton.button; break; - case SDL_JOYDEVICEADDED: + case SDL_EVENT_JOYSTICK_ADDED: event->type = JoystickAdded; event->reference = e.jdevice.which; break; - case SDL_JOYDEVICEREMOVED: + case SDL_EVENT_JOYSTICK_REMOVED: event->type = JoystickRemoved; event->reference = e.jdevice.which; break; - case SDL_DROPBEGIN: + case SDL_EVENT_DROP_BEGIN: event->type = DropStart; event->window = e.drop.windowID; break; - case SDL_DROPFILE: case SDL_DROPTEXT: { - vbyte* bytes = hl_copy_bytes(e.drop.file, (int)strlen(e.drop.file) + 1); - SDL_free(e.drop.file); - event->type = e.type == SDL_DROPFILE ? DropFile : DropText; + case SDL_EVENT_DROP_FILE: case SDL_EVENT_DROP_TEXT: { + vbyte* bytes = hl_copy_bytes(e.drop.data, (int)strlen(e.drop.data) + 1); + event->type = e.type == SDL_EVENT_DROP_FILE ? DropFile : DropText; event->dropFile = bytes; event->window = e.drop.windowID; break; } - case SDL_DROPCOMPLETE: + case SDL_EVENT_DROP_COMPLETE: event->type = DropEnd; event->window = e.drop.windowID; break; - case SDL_KEYMAPCHANGED: + case SDL_EVENT_KEYMAP_CHANGED: event->type = KeyMapChanged; break; default: @@ -398,34 +403,39 @@ HL_PRIM void HL_NAME(delay)( int time ) { hl_blocking(false); } -HL_PRIM int HL_NAME(get_screen_width)() { - SDL_DisplayMode e; - SDL_GetCurrentDisplayMode(0, &e); - return e.w; +HL_PRIM int HL_NAME(get_screen_width)( int index ) { + int count; + SDL_DisplayID *displays = SDL_GetDisplays( &count ); + if ( index < 0 || index > count ) + index = 0; + + const SDL_DisplayMode *e = SDL_GetCurrentDisplayMode(displays[index]); + return e->w; } -HL_PRIM int HL_NAME(get_screen_height)() { - SDL_DisplayMode e; - SDL_GetCurrentDisplayMode(0, &e); - return e.h; +HL_PRIM int HL_NAME(get_screen_height)( int index ) { + int count; + SDL_DisplayID *displays = SDL_GetDisplays( &count ); + if ( index < 0 || index > count ) + index = 0; + + const SDL_DisplayMode *e = SDL_GetCurrentDisplayMode(displays[index]); + return e->h; } HL_PRIM int HL_NAME(get_screen_width_of_window)(SDL_Window* win) { - SDL_DisplayMode e; - SDL_GetCurrentDisplayMode(win != NULL ? SDL_GetWindowDisplayIndex(win) : 0, &e); - return e.w; + const SDL_DisplayMode *e = SDL_GetCurrentDisplayMode(win != NULL ? SDL_GetDisplayForWindow(win) : 0 ); + return e->w; } HL_PRIM int HL_NAME(get_screen_height_of_window)(SDL_Window* win) { - SDL_DisplayMode e; - SDL_GetCurrentDisplayMode(win != NULL ? SDL_GetWindowDisplayIndex(win) : 0, &e); - return e.h; + const SDL_DisplayMode *e = SDL_GetCurrentDisplayMode(win != NULL ? SDL_GetDisplayForWindow(win) : 0 ); + return e->h; } HL_PRIM int HL_NAME(get_framerate)(SDL_Window* win) { - SDL_DisplayMode e; - SDL_GetCurrentDisplayMode(win != NULL ? SDL_GetWindowDisplayIndex(win) : 0, &e); - return e.refresh_rate; + const SDL_DisplayMode *e = SDL_GetCurrentDisplayMode(win != NULL ? SDL_GetDisplayForWindow(win) : 0 ); + return e->refresh_rate; } HL_PRIM void HL_NAME(message_box)(vbyte *title, vbyte *text, bool error) { @@ -447,19 +457,19 @@ HL_PRIM bool HL_NAME(detect_win32)() { # endif } -HL_PRIM void HL_NAME(text_input)( bool enable ) { +HL_PRIM void HL_NAME(text_input)( SDL_Window* window, bool enable ) { if( enable ) - SDL_StartTextInput(); + SDL_StartTextInput(window); else - SDL_StopTextInput(); + SDL_StopTextInput(window); } -HL_PRIM int HL_NAME(set_relative_mouse_mode)(bool enable) { - return SDL_SetRelativeMouseMode(enable); +HL_PRIM bool HL_NAME(set_relative_mouse_mode)(SDL_Window* window, bool enable) { + return SDL_SetWindowRelativeMouseMode(window, enable); } -HL_PRIM bool HL_NAME(get_relative_mouse_mode)() { - return SDL_GetRelativeMouseMode(); +HL_PRIM bool HL_NAME(get_relative_mouse_mode)(SDL_Window* window) { + return SDL_GetWindowRelativeMouseMode(window); } HL_PRIM int HL_NAME(warp_mouse_global)(int x, int y) { @@ -471,21 +481,24 @@ HL_PRIM void HL_NAME(warp_mouse_in_window)(SDL_Window* window, int x, int y) { } HL_PRIM void HL_NAME(set_window_grab)(SDL_Window* window, bool grabbed) { - SDL_SetWindowGrab(window, grabbed); + // Grab both. + SDL_SetWindowKeyboardGrab(window, grabbed); + SDL_SetWindowMouseGrab(window, grabbed); } HL_PRIM bool HL_NAME(get_window_grab)(SDL_Window* window) { - return SDL_GetWindowGrab(window); + // @todo: SDL3 separates keyboard and mouse grab here. Do we care? + return SDL_GetWindowKeyboardGrab(window); } -HL_PRIM int HL_NAME(get_global_mouse_state)(int* x, int* y) { +HL_PRIM int HL_NAME(get_global_mouse_state)(float* x, float* y) { return SDL_GetGlobalMouseState(x, y); } HL_PRIM const char *HL_NAME(detect_keyboard_layout)() { - char q = SDL_GetKeyFromScancode(SDL_SCANCODE_Q); - char w = SDL_GetKeyFromScancode(SDL_SCANCODE_W); - char y = SDL_GetKeyFromScancode(SDL_SCANCODE_Y); + char q = SDL_GetKeyFromScancode(SDL_SCANCODE_Q, SDL_KMOD_NONE, false); + char w = SDL_GetKeyFromScancode(SDL_SCANCODE_W, SDL_KMOD_NONE, false); + char y = SDL_GetKeyFromScancode(SDL_SCANCODE_Y, SDL_KMOD_NONE, false); if (q == 'q' && w == 'w' && y == 'y') return "qwerty"; if (q == 'a' && w == 'z' && y == 'y') return "azerty"; @@ -501,22 +514,22 @@ DEFINE_PRIM(_BOOL, event_loop, _DYN ); DEFINE_PRIM(_I32, event_poll, _STRUCT ); DEFINE_PRIM(_VOID, quit, _NO_ARG); DEFINE_PRIM(_VOID, delay, _I32); -DEFINE_PRIM(_I32, get_screen_width, _NO_ARG); -DEFINE_PRIM(_I32, get_screen_height, _NO_ARG); +DEFINE_PRIM(_I32, get_screen_width, _I32); +DEFINE_PRIM(_I32, get_screen_height, _I32); DEFINE_PRIM(_I32, get_screen_width_of_window, TWIN); DEFINE_PRIM(_I32, get_screen_height_of_window, TWIN); DEFINE_PRIM(_I32, get_framerate, TWIN); DEFINE_PRIM(_VOID, message_box, _BYTES _BYTES _BOOL); DEFINE_PRIM(_VOID, set_vsync, _BOOL); DEFINE_PRIM(_BOOL, detect_win32, _NO_ARG); -DEFINE_PRIM(_VOID, text_input, _BOOL); -DEFINE_PRIM(_I32, set_relative_mouse_mode, _BOOL); -DEFINE_PRIM(_BOOL, get_relative_mouse_mode, _NO_ARG); +DEFINE_PRIM(_VOID, text_input, TWIN _BOOL); +DEFINE_PRIM(_BOOL, set_relative_mouse_mode, TWIN _BOOL); +DEFINE_PRIM(_BOOL, get_relative_mouse_mode, TWIN _NO_ARG); DEFINE_PRIM(_I32, warp_mouse_global, _I32 _I32); DEFINE_PRIM(_VOID, warp_mouse_in_window, TWIN _I32 _I32); DEFINE_PRIM(_VOID, set_window_grab, TWIN _BOOL); DEFINE_PRIM(_BOOL, get_window_grab, TWIN); -DEFINE_PRIM(_I32, get_global_mouse_state, _REF(_I32) _REF(_I32)); +DEFINE_PRIM(_I32, get_global_mouse_state, _REF(_F32) _REF(_F32)); DEFINE_PRIM(_BYTES, detect_keyboard_layout, _NO_ARG); DEFINE_PRIM(_BOOL, hint_value, _BYTES _BYTES); @@ -535,9 +548,50 @@ HL_PRIM SDL_Window *HL_NAME(win_create_ex)(int x, int y, int width, int height, #ifdef HL_MOBILE SDL_DisplayMode displayMode; SDL_GetDesktopDisplayMode(0, &displayMode); - SDL_Window* win = SDL_CreateWindow("", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_BORDERLESS | sdlFlags); + SDL_Window* win = SDL_CreateWindow("", width, height, + SDL_WINDOW_BORDERLESS | sdlFlags); #else - SDL_Window* win = SDL_CreateWindow("", x, y, width, height, sdlFlags); + SDL_PropertiesID props = SDL_CreateProperties(); + SDL_SetStringProperty(props, SDL_PROP_WINDOW_CREATE_TITLE_STRING, ""); + SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER, width); + SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER, height); + SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_X_NUMBER, x); + SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_Y_NUMBER, y); + SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_OPENGL_BOOLEAN, true); + if( sdlFlags & SDL_WINDOW_BORDERLESS ) + SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_BORDERLESS_BOOLEAN, true); + if( sdlFlags & SDL_WINDOW_FULLSCREEN ) + SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_FULLSCREEN_BOOLEAN, true); + if( sdlFlags & SDL_WINDOW_HIDDEN ) + SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_HIDDEN_BOOLEAN, true); + if( sdlFlags & SDL_WINDOW_RESIZABLE ) + SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_RESIZABLE_BOOLEAN, true); + if( sdlFlags & SDL_WINDOW_MINIMIZED ) + SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_MINIMIZED_BOOLEAN, true); + if( sdlFlags & SDL_WINDOW_MAXIMIZED ) + SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_MAXIMIZED_BOOLEAN, true); + if( sdlFlags & SDL_WINDOW_MOUSE_FOCUS ) + SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_MOUSE_GRABBED_BOOLEAN, true); + if( sdlFlags & SDL_WINDOW_HIGH_PIXEL_DENSITY ) + SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_HIGH_PIXEL_DENSITY_BOOLEAN, true); + if( sdlFlags & SDL_WINDOW_ALWAYS_ON_TOP ) + SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_ALWAYS_ON_TOP_BOOLEAN, true); + if( sdlFlags & SDL_WINDOW_UTILITY ) + SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_UTILITY_BOOLEAN, true); + if( sdlFlags & SDL_WINDOW_TOOLTIP ) + SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_TOOLTIP_BOOLEAN, true); + if( sdlFlags & SDL_WINDOW_POPUP_MENU ) + SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_MENU_BOOLEAN, true); + if( sdlFlags & SDL_WINDOW_MODAL ) + SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_MODAL_BOOLEAN, true); + if( sdlFlags & SDL_WINDOW_POPUP_MENU ) + SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_MENU_BOOLEAN, true); + + + + SDL_Window* win = SDL_CreateWindowWithProperties(props); + SDL_DestroyProperties(props); + #endif # ifdef HL_WIN // force window to show even if the debugger force process windows to be hidden @@ -559,78 +613,46 @@ HL_PRIM SDL_GLContext HL_NAME(win_get_glcontext)(SDL_Window *win) { } HL_PRIM bool HL_NAME(win_set_fullscreen)(SDL_Window *win, int mode) { -# ifdef HL_WIN - wsave_pos *save = SDL_GetWindowData(win,"save"); - SDL_SysWMinfo info; - HWND wnd; - SDL_VERSION(&info.version); - SDL_GetWindowWMInfo(win,&info); - wnd = info.info.win.window; - if( save && mode != 2 ) { - // exit borderless - SetWindowLong(wnd,GWL_STYLE,save->style); - SetWindowPos(wnd,NULL,save->x,save->y,save->w,save->h,0); - SDL_SetWindowSize(win, save->w, save->h); - free(save); - SDL_SetWindowData(win,"save",NULL); - save = NULL; - } -# endif switch( mode ) { case 0: // WINDOWED - return SDL_SetWindowFullscreen(win, 0) == 0; + return SDL_SetWindowFullscreen(win, false); + case 1: // FULLSCREEN - return SDL_SetWindowFullscreen(win, SDL_WINDOW_FULLSCREEN) == 0; + // sdl3 non-standard behavior; force mode to get exclusive fullscreen. + const SDL_DisplayMode *mode = SDL_GetWindowFullscreenMode(win); + if( mode != NULL ) + return SDL_SetWindowFullscreenMode(win, mode); + + // Fall back to borderless if we can't find a mode. + return SDL_SetWindowFullscreen(win, true); + case 2: // BORDERLESS -# ifdef _WIN32 - { - HMONITOR hmon = MonitorFromWindow(wnd,MONITOR_DEFAULTTONEAREST); - MONITORINFO mi = { sizeof(mi) }; - RECT r; - if( !GetMonitorInfo(hmon, &mi) ) - return false; - GetWindowRect(wnd,&r); - save = (wsave_pos*)malloc(sizeof(wsave_pos)); - save->x = r.left; - save->y = r.top; - save->w = r.right - r.left; - save->h = r.bottom - r.top; - save->style = GetWindowLong(wnd,GWL_STYLE); - SDL_SetWindowData(win,"save",save); - SetWindowLong(wnd,GWL_STYLE, WS_POPUP | WS_VISIBLE); - SetWindowPos(wnd,NULL,mi.rcMonitor.left,mi.rcMonitor.top,mi.rcMonitor.right - mi.rcMonitor.left,mi.rcMonitor.bottom - mi.rcMonitor.top + 2 /* prevent opengl driver to use exclusive mode !*/,0); - return true; - } -# else - return SDL_SetWindowFullscreen(win, SDL_WINDOW_FULLSCREEN_DESKTOP) == 0; -# endif + return SDL_SetWindowFullscreen(win, true); } return false; } HL_PRIM bool HL_NAME(win_set_display_mode)(SDL_Window *win, int width, int height, int framerate) { SDL_DisplayMode mode; - int display_idx = SDL_GetWindowDisplayIndex(win); - for (int i = 0; i < SDL_GetNumDisplayModes(display_idx); i++) { - if (SDL_GetDisplayMode(display_idx, i, &mode) == 0) { - if (mode.w == width && mode.h == height && mode.refresh_rate == framerate) { - return SDL_SetWindowDisplayMode(win, &mode) >= 0; - } - } + int display_idx = SDL_GetDisplayForWindow(win); + + if( SDL_GetClosestFullscreenDisplayMode( display_idx, width, height, framerate, true, &mode ) ) + { + return SDL_SetWindowFullscreenMode(win, &mode); } return false; } HL_PRIM int HL_NAME(win_display_handle)(SDL_Window *win) { - return SDL_GetWindowDisplayIndex(win); + return SDL_GetDisplayForWindow(win); } HL_PRIM void HL_NAME(win_set_title)(SDL_Window *win, vbyte *title) { SDL_SetWindowTitle(win, (char*)title); } -HL_PRIM void HL_NAME(win_set_position)(SDL_Window *win, int x, int y) { - SDL_SetWindowPosition(win, x, y); +HL_PRIM bool HL_NAME(win_set_position)(SDL_Window *win, int x, int y) { + return SDL_SetWindowPosition(win, x, y); } HL_PRIM void HL_NAME(win_get_position)(SDL_Window *win, int *x, int *y) { @@ -662,13 +684,11 @@ HL_PRIM void HL_NAME(win_get_max_size)(SDL_Window *win, int *width, int *height) } HL_PRIM double HL_NAME(win_get_opacity)(SDL_Window *win) { - float opacity = 1.0f; - SDL_GetWindowOpacity(win, &opacity); - return opacity; + return SDL_GetWindowOpacity(win ); } HL_PRIM bool HL_NAME(win_set_opacity)(SDL_Window *win, double opacity) { - return SDL_SetWindowOpacity(win, (float)opacity) == 0; + return SDL_SetWindowOpacity(win, (float)opacity); } HL_PRIM void HL_NAME(win_resize)(SDL_Window *win, int mode) { @@ -716,7 +736,7 @@ HL_PRIM int HL_NAME(win_get_id)(SDL_Window *window) { HL_PRIM void HL_NAME(win_destroy)(SDL_Window *win, SDL_GLContext gl) { SDL_DestroyWindow(win); - SDL_GL_DeleteContext(gl); + SDL_GL_DestroyContext(gl); } #define TGL _ABSTRACT(sdl_gl) @@ -728,7 +748,7 @@ DEFINE_PRIM(_BOOL, win_set_display_mode, TWIN _I32 _I32 _I32); DEFINE_PRIM(_I32, win_display_handle, TWIN); DEFINE_PRIM(_VOID, win_resize, TWIN _I32); DEFINE_PRIM(_VOID, win_set_title, TWIN _BYTES); -DEFINE_PRIM(_VOID, win_set_position, TWIN _I32 _I32); +DEFINE_PRIM(_BOOL, win_set_position, TWIN _I32 _I32); DEFINE_PRIM(_VOID, win_get_position, TWIN _REF(_I32) _REF(_I32)); DEFINE_PRIM(_VOID, win_set_size, TWIN _I32 _I32); DEFINE_PRIM(_VOID, win_set_min_size, TWIN _I32 _I32); @@ -746,33 +766,38 @@ DEFINE_PRIM(_I32, win_get_id, TWIN); // game controller HL_PRIM int HL_NAME(gctrl_count)() { - return SDL_NumJoysticks(); + int count; + SDL_GetJoysticks(&count); + return count; } -HL_PRIM SDL_GameController *HL_NAME(gctrl_open)(int idx) { - if (SDL_IsGameController(idx)) - return SDL_GameControllerOpen(idx); - return NULL; +HL_PRIM SDL_Gamepad *HL_NAME(gctrl_open)(int idx) { + int count; + SDL_JoystickID *sticks = SDL_GetJoysticks(&count); + if( idx >= count || !SDL_IsGamepad(sticks[idx]) ) + return NULL; + + return SDL_OpenGamepad(sticks[idx]); } -HL_PRIM void HL_NAME(gctrl_close)(SDL_GameController *controller) { - SDL_GameControllerClose(controller); +HL_PRIM void HL_NAME(gctrl_close)(SDL_Gamepad *controller) { + SDL_CloseGamepad(controller); } -HL_PRIM int HL_NAME(gctrl_get_axis)(SDL_GameController *controller, int axisIdx ){ - return SDL_GameControllerGetAxis(controller, axisIdx); +HL_PRIM int HL_NAME(gctrl_get_axis)(SDL_Gamepad *controller, int axisIdx ){ + return SDL_GetGamepadAxis(controller, axisIdx); } -HL_PRIM bool HL_NAME(gctrl_get_button)(SDL_GameController *controller, int btnIdx) { - return SDL_GameControllerGetButton(controller, btnIdx) == 1; +HL_PRIM bool HL_NAME(gctrl_get_button)(SDL_Gamepad *controller, int btnIdx) { + return SDL_GetGamepadButton(controller, btnIdx) == 1; } -HL_PRIM int HL_NAME(gctrl_get_id)(SDL_GameController *controller) { - return SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(controller)); +HL_PRIM int HL_NAME(gctrl_get_id)(SDL_Gamepad *controller) { + return SDL_GetGamepadID( controller ); } -HL_PRIM vbyte *HL_NAME(gctrl_get_name)(SDL_GameController *controller) { - return (vbyte*)SDL_GameControllerName(controller); +HL_PRIM vbyte *HL_NAME(gctrl_get_name)(SDL_Gamepad *controller) { + return (vbyte*) SDL_GetGamepadName(controller); } #define TGCTRL _ABSTRACT(sdl_gamecontroller) @@ -784,20 +809,20 @@ DEFINE_PRIM(_BOOL, gctrl_get_button, TGCTRL _I32); DEFINE_PRIM(_I32, gctrl_get_id, TGCTRL); DEFINE_PRIM(_BYTES, gctrl_get_name, TGCTRL); -HL_PRIM SDL_Haptic *HL_NAME(haptic_open)(SDL_GameController *controller) { - return SDL_HapticOpenFromJoystick(SDL_GameControllerGetJoystick(controller)); +HL_PRIM SDL_Haptic *HL_NAME(haptic_open)(SDL_Gamepad *controller) { + return SDL_OpenHapticFromJoystick(SDL_GetGamepadJoystick(controller)); } HL_PRIM void HL_NAME(haptic_close)(SDL_Haptic *haptic) { - SDL_HapticClose(haptic); + SDL_CloseHaptic(haptic); } HL_PRIM int HL_NAME(haptic_rumble_init)(SDL_Haptic *haptic) { - return SDL_HapticRumbleInit(haptic); + return SDL_InitHapticRumble(haptic); } HL_PRIM int HL_NAME(haptic_rumble_play)(SDL_Haptic *haptic, double strength, int length) { - return SDL_HapticRumblePlay(haptic, (float)strength, length); + return SDL_PlayHapticRumble(haptic, (float)strength, length); } #define THAPTIC _ABSTRACT(sdl_haptic) DEFINE_PRIM(THAPTIC, haptic_open, TGCTRL); @@ -808,35 +833,37 @@ DEFINE_PRIM(_I32, haptic_rumble_play, THAPTIC _F64 _I32); // joystick HL_PRIM int HL_NAME(joy_count)() { - return SDL_NumJoysticks(); + int count; + SDL_GetJoysticks(&count); + return count; } HL_PRIM SDL_Joystick *HL_NAME(joy_open)(int idx) { - return SDL_JoystickOpen(idx); + return SDL_OpenJoystick(idx); } HL_PRIM void HL_NAME(joy_close)(SDL_Joystick *joystick) { - SDL_JoystickClose(joystick); + SDL_CloseJoystick(joystick); } HL_PRIM int HL_NAME(joy_get_axis)(SDL_Joystick *joystick, int axisIdx ){ - return SDL_JoystickGetAxis(joystick, axisIdx); + return SDL_GetJoystickAxis(joystick, axisIdx); } HL_PRIM int HL_NAME(joy_get_hat)(SDL_Joystick *joystick, int hatIdx ){ - return SDL_JoystickGetHat(joystick, hatIdx); + return SDL_GetJoystickHat(joystick, hatIdx); } HL_PRIM bool HL_NAME(joy_get_button)(SDL_Joystick *joystick, int btnIdx) { - return SDL_JoystickGetButton(joystick, btnIdx) == 1; + return SDL_GetJoystickButton(joystick, btnIdx) == 1; } HL_PRIM int HL_NAME(joy_get_id)(SDL_Joystick *joystick) { - return SDL_JoystickInstanceID(joystick); + return SDL_GetJoystickID(joystick); } HL_PRIM vbyte *HL_NAME(joy_get_name)(SDL_Joystick *joystick) { - return (vbyte*)SDL_JoystickName(joystick); + return (vbyte*) SDL_GetJoystickName(joystick); } #define TJOY _ABSTRACT(sdl_joystick) @@ -853,11 +880,11 @@ DEFINE_PRIM(_BYTES, joy_get_name, TJOY); HL_PRIM SDL_Surface *HL_NAME(surface_from)( vbyte *ptr, int width, int height, int depth, int pitch, int rmask, int gmask, int bmask, int amask ) { - return SDL_CreateRGBSurfaceFrom(ptr,width,height,depth,pitch,rmask,gmask,bmask,amask); + return SDL_CreateSurfaceFrom(width, height, SDL_GetPixelFormatForMasks(depth, rmask, gmask, bmask, amask), ptr, pitch); } HL_PRIM void HL_NAME(free_surface)( SDL_Surface *s ) { - SDL_FreeSurface(s); + SDL_DestroySurface(s); } #define _SURF _ABSTRACT(sdl_surface) @@ -867,11 +894,14 @@ DEFINE_PRIM(_VOID, free_surface, _SURF); // cursor HL_PRIM void HL_NAME(show_cursor)( bool b ) { - SDL_ShowCursor(b?SDL_ENABLE:SDL_DISABLE); + if( b ) + SDL_ShowCursor(); + else + SDL_HideCursor(); } HL_PRIM bool HL_NAME(is_cursor_visible)() { - return SDL_ShowCursor(SDL_QUERY) == SDL_ENABLE; + return SDL_CursorVisible(); } HL_PRIM SDL_Cursor *HL_NAME(cursor_create)( SDL_Surface *s, int hotX, int hotY ) { @@ -883,7 +913,7 @@ HL_PRIM SDL_Cursor *HL_NAME(cursor_create_system)( int kind ) { } HL_PRIM void HL_NAME(free_cursor)( SDL_Cursor *c ) { - SDL_FreeCursor(c); + SDL_DestroyCursor(c); } HL_PRIM void HL_NAME(set_cursor)( SDL_Cursor *c ) { @@ -891,7 +921,7 @@ HL_PRIM void HL_NAME(set_cursor)( SDL_Cursor *c ) { } HL_PRIM bool HL_NAME(set_clipboard_text)(char* text) { - return SDL_SetClipboardText(text) == 0; + return SDL_SetClipboardText(text); } HL_PRIM char* HL_NAME(get_clipboard_text)() { @@ -904,28 +934,30 @@ HL_PRIM char* HL_NAME(get_clipboard_text)() { } HL_PRIM void HL_NAME(set_drag_and_drop_enabled)( bool enabled ) { - SDL_EventState(SDL_DROPFILE, enabled ? SDL_ENABLE : SDL_DISABLE); + SDL_SetEventEnabled(SDL_EVENT_DROP_FILE, enabled ); } HL_PRIM bool HL_NAME(get_drag_and_drop_enabled)() { - return SDL_EventState(SDL_DROPFILE, SDL_QUERY); + return SDL_EventEnabled(SDL_EVENT_DROP_FILE); } HL_PRIM varray* HL_NAME(get_displays)() { - int n = SDL_GetNumVideoDisplays(); - if (n < 0) + int n; + SDL_DisplayID *displays = SDL_GetDisplays(&n); + if (n <= 0) return NULL; varray* arr = hl_alloc_array(&hlt_dynobj, n); for (int i = 0; i < n; i++) { vdynamic *obj = (vdynamic*) hl_alloc_dynobj(); SDL_Rect rect; - SDL_GetDisplayBounds(i, &rect); + SDL_DisplayID display = displays[i]; + SDL_GetDisplayBounds(display, &rect); hl_dyn_seti(obj, hl_hash_utf8("right"), &hlt_i32, rect.x+rect.w); hl_dyn_seti(obj, hl_hash_utf8("bottom"), &hlt_i32, rect.y+rect.h); hl_dyn_seti(obj, hl_hash_utf8("left"), &hlt_i32, rect.x); hl_dyn_seti(obj, hl_hash_utf8("top"), &hlt_i32, rect.y); hl_dyn_seti(obj, hl_hash_utf8("handle"), &hlt_i32, i); - const char *name = SDL_GetDisplayName(i); + const char *name = SDL_GetDisplayName(display); hl_dyn_setp(obj, hl_hash_utf8("name"), &hlt_bytes, hl_copy_bytes(name, (int) strlen(name)+1)); hl_aptr(arr, vdynamic*)[i] = obj; } @@ -933,37 +965,40 @@ HL_PRIM varray* HL_NAME(get_displays)() { } HL_PRIM varray* HL_NAME(get_display_modes)(int display_id) { - int n = SDL_GetNumDisplayModes(display_id); - if (n < 0) - return NULL; - varray* arr = hl_alloc_array(&hlt_dynobj, n); - for (int i = 0; i < n; i++) { - SDL_DisplayMode mode; - SDL_GetDisplayMode(display_id, i, &mode); + + + SDL_DisplayMode **modes; + int count; + modes = SDL_GetFullscreenDisplayModes(display_id, &count); + varray* arr = hl_alloc_array(&hlt_dynobj, count); + + for (int i = 0; i < count; i++) { + SDL_DisplayMode *mode = modes[i]; + vdynamic *obj = (vdynamic*)hl_alloc_dynobj(); - hl_dyn_seti(obj, hl_hash_utf8("width"), &hlt_i32, mode.w); - hl_dyn_seti(obj, hl_hash_utf8("height"), &hlt_i32, mode.h); - hl_dyn_seti(obj, hl_hash_utf8("framerate"), &hlt_i32, mode.refresh_rate); + hl_dyn_seti(obj, hl_hash_utf8("width"), &hlt_i32, mode->w); + hl_dyn_seti(obj, hl_hash_utf8("height"), &hlt_i32, mode->h); + hl_dyn_seti(obj, hl_hash_utf8("framerate"), &hlt_i32, mode->refresh_rate); hl_aptr(arr, vdynamic*)[i] = obj; } return arr; } HL_PRIM vdynobj* HL_NAME(get_current_display_mode)(int display_id, bool registry) { - SDL_DisplayMode mode; + const SDL_DisplayMode *mode; int r; if(registry) - r = SDL_GetDesktopDisplayMode(display_id, &mode); + mode = SDL_GetDesktopDisplayMode(display_id); else - r = SDL_GetCurrentDisplayMode(display_id, &mode); - if (r < 0) { + mode = SDL_GetCurrentDisplayMode(display_id); + if (mode == NULL) { printf("can't find mode for %d : %d\n", display_id, r); return NULL; } vdynamic* obj = (vdynamic*)hl_alloc_dynobj(); - hl_dyn_seti(obj, hl_hash_utf8("width"), &hlt_i32, mode.w); - hl_dyn_seti(obj, hl_hash_utf8("height"), &hlt_i32, mode.h); - hl_dyn_seti(obj, hl_hash_utf8("framerate"), &hlt_i32, mode.refresh_rate); + hl_dyn_seti(obj, hl_hash_utf8("width"), &hlt_i32, mode->w); + hl_dyn_seti(obj, hl_hash_utf8("height"), &hlt_i32, mode->h); + hl_dyn_seti(obj, hl_hash_utf8("framerate"), &hlt_i32, mode->refresh_rate); return (vdynobj*) obj; } @@ -982,6 +1017,10 @@ HL_PRIM varray *HL_NAME(get_devices)() { return a; } +HL_PRIM vbyte* HL_NAME(get_error)() { + return (vbyte*) SDL_GetError(); +} + #define _CURSOR _ABSTRACT(sdl_cursor) DEFINE_PRIM(_VOID, show_cursor, _BOOL); DEFINE_PRIM(_BOOL, is_cursor_visible, _NO_ARG); @@ -997,3 +1036,4 @@ DEFINE_PRIM(_ARR, get_displays, _NO_ARG); DEFINE_PRIM(_ARR, get_display_modes, _I32); DEFINE_PRIM(_DYN, get_current_display_mode, _I32 _BOOL); DEFINE_PRIM(_ARR, get_devices, _NO_ARG); +DEFINE_PRIM(_BYTES, get_error, _NO_ARG); diff --git a/libs/sdl/sdl.vcxproj b/libs/sdl/sdl.vcxproj index 88ce0be5b..5cc8b3e5f 100644 --- a/libs/sdl/sdl.vcxproj +++ b/libs/sdl/sdl.vcxproj @@ -145,7 +145,7 @@ Windows true ../../$(Configuration)/$(TargetName).hdll - libhl.lib;winmm.lib;SDL2.lib;opengl32.lib;user32.lib;kernel32.lib + libhl.lib;winmm.lib;SDL3.lib;opengl32.lib;user32.lib;kernel32.lib @@ -160,7 +160,7 @@ Windows true false - libhl.lib;winmm.lib;SDL2.lib;opengl32.lib;user32.lib;kernel32.lib + libhl.lib;winmm.lib;SDL3.lib;opengl32.lib;user32.lib;kernel32.lib @@ -180,7 +180,7 @@ true false ../../$(Configuration)/$(TargetName).hdll - libhl.lib;winmm.lib;SDL2.lib;opengl32.lib;user32.lib;kernel32.lib + libhl.lib;winmm.lib;SDL3.lib;opengl32.lib;user32.lib;kernel32.lib @@ -200,7 +200,7 @@ true false ../../$(Configuration)/$(TargetName).hdll - libhl.lib;winmm.lib;SDL2.lib;opengl32.lib;user32.lib;kernel32.lib + libhl.lib;winmm.lib;SDL3.lib;opengl32.lib;user32.lib;kernel32.lib @@ -218,7 +218,7 @@ true true true - libhl.lib;winmm.lib;SDL2.lib;opengl32.lib;user32.lib;kernel32.lib + libhl.lib;winmm.lib;SDL3.lib;opengl32.lib;user32.lib;kernel32.lib @@ -236,7 +236,7 @@ true true true - libhl.lib;winmm.lib;SDL2.lib;opengl32.lib;user32.lib;kernel32.lib + libhl.lib;winmm.lib;SDL3.lib;opengl32.lib;user32.lib;kernel32.lib diff --git a/libs/sdl/sdl/Sdl.hx b/libs/sdl/sdl/Sdl.hx index 44d4e0db5..d997b2ce0 100644 --- a/libs/sdl/sdl/Sdl.hx +++ b/libs/sdl/sdl/Sdl.hx @@ -90,18 +90,18 @@ class Sdl { public static function delay(time:Int) { } - public static function getScreenWidth(?win : sdl.Window) : Int { + public static function getScreenWidth(?win : sdl.Window, index: Int = 0) : Int { return if(win == null) - get_screen_width(); + get_screen_width( index ); else get_screen_width_of_window(@:privateAccess win.win); } - public static function getScreenHeight(?win : sdl.Window) : Int { + public static function getScreenHeight(?win : sdl.Window, index: Int = 0) : Int { return if(win == null) - get_screen_height(); + get_screen_height( index ); else get_screen_height_of_window(@:privateAccess win.win); } @@ -148,10 +148,6 @@ class Sdl { return a; } - public static function setRelativeMouseMode( enable : Bool ) : Int { - return 0; - } - public static function setClipboardText( text : String ) : Bool { if( text == null ) return false; @@ -166,13 +162,22 @@ class Sdl { return @:privateAccess String.fromUTF8(t); } + + public static function getError() : String { + var t = _getError(); + if( t == null ) + return null; + else + return @:privateAccess String.fromUTF8(t); + } + @:hlNative("?sdl", "get_screen_width") - static function get_screen_width() : Int { + static function get_screen_width( index: Int ) : Int { return 0; } @:hlNative("?sdl", "get_screen_height") - static function get_screen_height() : Int { + static function get_screen_height( index: Int ) : Int { return 0; } @@ -212,16 +217,12 @@ class Sdl { return null; } - public static function getRelativeMouseMode() : Bool { - return false; - } - public static function warpMouseGlobal( x : Int, y : Int ) : Int { return 0; } @:hlNative("?sdl", "get_global_mouse_state") - public static function getGlobalMouseState( x : hl.Ref, y : hl.Ref ) : Int { + public static function getGlobalMouseState( x : hl.Ref, y : hl.Ref ) : Int { return 0; } @@ -251,6 +252,11 @@ class Sdl { public static function getDragAndDropEnabled(): Bool { return false; } + + @:hlNative("?sdl", "get_error") + private static function _getError() : hl.Bytes { + return null; + } } enum abstract SDLHint(String) from String to String { diff --git a/libs/sdl/sdl/Window.hx b/libs/sdl/sdl/Window.hx index d5dd1a133..e39eb87a3 100644 --- a/libs/sdl/sdl/Window.hx +++ b/libs/sdl/sdl/Window.hx @@ -26,21 +26,20 @@ class Window { public static inline var SDL_WINDOW_FULLSCREEN = 0x00000001; public static inline var SDL_WINDOW_OPENGL = 0x00000002; - public static inline var SDL_WINDOW_SHOWN = 0x00000004; + public static inline var SDL_WINDOW_OCCLUDED = 0x00000004; public static inline var SDL_WINDOW_HIDDEN = 0x00000008; public static inline var SDL_WINDOW_BORDERLESS = 0x00000010; public static inline var SDL_WINDOW_RESIZABLE = 0x00000020; public static inline var SDL_WINDOW_MINIMIZED = 0x00000040; public static inline var SDL_WINDOW_MAXIMIZED = 0x00000080; - public static inline var SDL_WINDOW_INPUT_GRABBED = 0x00000100; + public static inline var SDL_WINDOW_MOUSE_GRABBED = 0x00000100; public static inline var SDL_WINDOW_INPUT_FOCUS = 0x00000200; public static inline var SDL_WINDOW_MOUSE_FOCUS = 0x00000400; - public static inline var SDL_WINDOW_FULLSCREEN_DESKTOP = 0x00001001; public static inline var SDL_WINDOW_FOREIGN = 0x00000800; + public static inline var SDL_WINDOW_MODAL = 0x00001000; public static inline var SDL_WINDOW_ALLOW_HIGHDPI = 0x00002000; public static inline var SDL_WINDOW_MOUSE_CAPTURE = 0x00004000; - public static inline var SDL_WINDOW_ALWAYS_ON_TOP = 0x00008000; - public static inline var SDL_WINDOW_SKIP_TASKBAR = 0x00010000; + public static inline var SDL_WINDOW_ALWAYS_ON_TOP = 0x00010000; public static inline var SDL_WINDOW_UTILITY = 0x00020000; public static inline var SDL_WINDOW_TOOLTIP = 0x00040000; public static inline var SDL_WINDOW_POPUP_MENU = 0x00080000; @@ -68,7 +67,7 @@ class Window { public var opacity(get, set) : Float; public var grab(get, set) : Bool; - public function new( title : String, width : Int, height : Int, x : Int = SDL_WINDOWPOS_CENTERED, y : Int = SDL_WINDOWPOS_CENTERED, sdlFlags : Int = SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE ) { + public function new( title : String, width : Int, height : Int, x : Int = SDL_WINDOWPOS_CENTERED, y : Int = SDL_WINDOWPOS_CENTERED, sdlFlags : Int = SDL_WINDOW_RESIZABLE ) { while( true ) { win = winCreateEx(x, y, width, height, sdlFlags); if( win == null ) throw "Failed to create window"; @@ -173,7 +172,7 @@ class Window { } public function setPosition( x : Int, y : Int ) { - winSetPosition(win, x, y); + return winSetPosition(win, x, y); } public function center() { @@ -301,6 +300,15 @@ class Window { winResize(win, 2); } + + public function getRelativeMouseMode() : Bool { + return winGetRelativeMouseMode( win ); + } + + public function setRelativeMouseMode( enabled: Bool ) : Bool { + return winSetRelativeMouseMode( win, enabled ); + } + static function winCreateEx( x : Int, y : Int, width : Int, height : Int, sdlFlags : Int ) : WinPtr { return null; } @@ -312,7 +320,8 @@ class Window { static function winSetTitle( win : WinPtr, title : hl.Bytes ) { } - static function winSetPosition( win : WinPtr, width : Int, height : Int ) { + static function winSetPosition( win : WinPtr, width : Int, height : Int ): Bool { + return false; } static function winGetPosition( win : WinPtr, width : hl.Ref, height : hl.Ref ) { @@ -392,4 +401,13 @@ class Window { static function warpMouseInWindow( win : WinPtr, x : Int, y : Int ) : Void { } + @:hlNative("?sdl", "get_relative_mouse_mode") + static function winGetRelativeMouseMode( win : WinPtr ) : Bool { + return false; + } + @:hlNative("?sdl", "set_relative_mouse_mode") + static function winSetRelativeMouseMode( win : WinPtr, enabled: Bool ) : Bool { + return false; + } + } From 6a710ce52691df664b2467fa08b7ae32098c1fb5 Mon Sep 17 00:00:00 2001 From: Spitko Date: Wed, 17 Sep 2025 22:47:38 -0700 Subject: [PATCH 02/26] Enable -DDOWNLOAD-DEPENDENCIES for linux Ubuntu LTS doesn't have libsdl3-dev yet. --- .github/workflows/build.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4fca7fa11..feeec632e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -128,7 +128,6 @@ jobs: libmbedtls-dev \ libopenal-dev \ libpng-dev \ - libsdl3-dev \ libturbojpeg-dev \ libuv1-dev \ libvorbis-dev \ @@ -202,7 +201,9 @@ jobs: -DFLAT_INSTALL_TREE=ON ;; linux64) - cmake -B build -DCMAKE_BUILD_TYPE=${{ matrix.cmake_configuration }} ;; + cmake -B build -DCMAKE_BUILD_TYPE=${{ matrix.cmake_configuration }} \ + -DDOWNLOAD_DEPENDENCIES=ON \ + ;; esac cmake --build build --config ${{ matrix.cmake_configuration }} From d15aea9ad667f89ef9bf178b1dda8569e4100d89 Mon Sep 17 00:00:00 2001 From: Spitko Date: Wed, 17 Sep 2025 23:02:17 -0700 Subject: [PATCH 03/26] Remove syswm.h include, add linux deps --- .github/workflows/build.yml | 26 ++++++++++++++++++++++++++ libs/sdl/sdl.c | 4 ---- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index feeec632e..f1e12d3ef 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -134,6 +134,32 @@ jobs: libsqlite3-dev ;; + # ref https://github.com/libsdl-org/SDL/blob/main/docs/README-linux.md#build-dependencies + sudo apt-get install --no-install-recommends -y \ + libasound2-dev \ + libpulse-dev \ + libaudio-dev \ + libjack-dev \ + libsndio-dev \ + libx11-dev \ + libxext-dev \ + libxrandr-dev \ + libxcursor-dev \ + libxfixes-dev \ + libxi-dev \ + libxss-dev \ + libxtst-dev \ + libxkbcommon-dev \ + libdrm-dev \ + libgbm-dev \ + libgl1-mesa-dev \ + libgles2-mesa-dev \ + libegl1-mesa-dev \ + libdbus-1-dev \ + libibus-1.0-dev \ + libudev-dev + ;; + darwin*) if [ "${{matrix.build_system}}" != "cmake" ]; then brew update diff --git a/libs/sdl/sdl.c b/libs/sdl/sdl.c index e762acac3..bfdc9af30 100644 --- a/libs/sdl/sdl.c +++ b/libs/sdl/sdl.c @@ -7,10 +7,6 @@ #include #include -#if defined(HL_WIN) || defined(HL_IOS) || defined(HL_TVOS) -# include -#endif - #if defined (HL_IOS) || defined(HL_TVOS) # include # include From 2fa33094d9bd9d20942a60471c4df1eeab208225 Mon Sep 17 00:00:00 2001 From: Spitko Date: Wed, 17 Sep 2025 23:04:58 -0700 Subject: [PATCH 04/26] Remove extra terminator --- .github/workflows/build.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f1e12d3ef..2d921b956 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -132,7 +132,6 @@ jobs: libuv1-dev \ libvorbis-dev \ libsqlite3-dev - ;; # ref https://github.com/libsdl-org/SDL/blob/main/docs/README-linux.md#build-dependencies sudo apt-get install --no-install-recommends -y \ From 0625c8e4613e026084ceadff82d99f05161a73e4 Mon Sep 17 00:00:00 2001 From: Spitko Date: Wed, 17 Sep 2025 23:12:59 -0700 Subject: [PATCH 05/26] Remove syntactically significant whitespace --- .github/workflows/build.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2d921b956..4c2067161 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -138,7 +138,7 @@ jobs: libasound2-dev \ libpulse-dev \ libaudio-dev \ - libjack-dev \ + libjack-dev \ libsndio-dev \ libx11-dev \ libxext-dev \ @@ -156,7 +156,11 @@ jobs: libegl1-mesa-dev \ libdbus-1-dev \ libibus-1.0-dev \ - libudev-dev + libudev-dev \ + libpipewire-0.3-dev \ + libwayland-dev \ + libdecor-0-dev \ + liburing-dev ;; darwin*) From a2feaeef42b547297f425c7988c8a6e5fd06eb6b Mon Sep 17 00:00:00 2001 From: Spitko Date: Wed, 17 Sep 2025 23:29:53 -0700 Subject: [PATCH 06/26] Remove dead code for HL_MOBILE --- libs/sdl/sdl.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/libs/sdl/sdl.c b/libs/sdl/sdl.c index bfdc9af30..35ea6da73 100644 --- a/libs/sdl/sdl.c +++ b/libs/sdl/sdl.c @@ -542,8 +542,6 @@ HL_PRIM SDL_Window *HL_NAME(win_create_ex)(int x, int y, int width, int height, } #ifdef HL_MOBILE - SDL_DisplayMode displayMode; - SDL_GetDesktopDisplayMode(0, &displayMode); SDL_Window* win = SDL_CreateWindow("", width, height, SDL_WINDOW_BORDERLESS | sdlFlags); #else From feeb331c10e0b94297081bc309d826b000a0808f Mon Sep 17 00:00:00 2001 From: Spitko Date: Wed, 17 Sep 2025 23:41:43 -0700 Subject: [PATCH 07/26] Update Makefile --- Makefile | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 9696f2a12..d2ee144cf 100644 --- a/Makefile +++ b/Makefile @@ -136,11 +136,11 @@ ifeq ($(MARCH),32) CFLAGS += -msse2 -mfpmath=sse CC=i686-pc-cygwin-gcc BUILD_DIR = Release -VS_SDL_LIBRARY ?= include/sdl/lib/x86/SDL2.dll +VS_SDL_LIBRARY ?= include/sdl/lib/x86/SDL3.dll VS_OPENAL_LIBRARY ?= include/openal/bin/Win32/soft_oal.dll else BUILD_DIR = x64/Release -VS_SDL_LIBRARY ?= include/sdl/lib/x64/SDL2.dll +VS_SDL_LIBRARY ?= include/sdl/lib/x64/SDL3.dll VS_OPENAL_LIBRARY ?= include/openal/bin/Win64/soft_oal.dll endif @@ -152,9 +152,9 @@ LIBEXT=dylib BREW_PREFIX := $(shell brew --prefix) # prefixes for keg-only packages BREW_OPENAL_PREFIX := $(shell brew --prefix openal-soft) -BREW_SDL_PREFIX := $(shell brew --prefix sdl2) +BREW_SDL_PREFIX := $(shell brew --prefix sdl3) -CFLAGS += -m$(MARCH) -I include -I $(BREW_PREFIX)/include -I $(BREW_OPENAL_PREFIX)/include -I $(BREW_SDL_PREFIX)/include/SDL2 -Dopenal_soft -DGL_SILENCE_DEPRECATION +CFLAGS += -m$(MARCH) -I include -I $(BREW_PREFIX)/include -I $(BREW_OPENAL_PREFIX)/include -I $(BREW_SDL_PREFIX)/include/SDL3 -Dopenal_soft -DGL_SILENCE_DEPRECATION LFLAGS += -Wl,-export_dynamic ifdef OSX_SDK @@ -163,7 +163,7 @@ CFLAGS += -isysroot $(ISYSROOT) LFLAGS += -isysroot $(ISYSROOT) endif -SDL_LINK_FLAGS = -L$(BREW_SDL_PREFIX)/lib -lSDL2 +SDL_LINK_FLAGS = -L$(BREW_SDL_PREFIX)/lib -lSDL3 LIBFLAGS += -L$(BREW_PREFIX)/lib -L$(BREW_OPENAL_PREFIX)/lib LIBOPENGL = -framework OpenGL LIBOPENAL = -lopenal @@ -185,7 +185,7 @@ LHL_LINK_FLAGS += -install_name @rpath/libhl.dylib else # Linux -CFLAGS += -m$(MARCH) -fPIC -pthread -fno-omit-frame-pointer $(shell pkg-config --cflags sdl2) +CFLAGS += -m$(MARCH) -fPIC -pthread -fno-omit-frame-pointer $(shell pkg-config --cflags sdl3) LFLAGS += -lm -Wl,-rpath,.:'$$ORIGIN':$(INSTALL_LIB_DIR) -Wl,--export-dynamic -Wl,--no-undefined ifeq ($(MARCH),32) @@ -195,7 +195,7 @@ else LIBFLAGS += -L/opt/libjpeg-turbo/lib64 endif -SDL_LINK_FLAGS = $(shell pkg-config --libs sdl2) +SDL_LINK_FLAGS = $(shell pkg-config --libs sdl3) LIBOPENAL = -lopenal LIBOPENGL = -lGL RELEASE_NAME = linux From 6aaf85f26966e8258f2ca8bb2f58435276b2a9f9 Mon Sep 17 00:00:00 2001 From: Spitko Date: Thu, 18 Sep 2025 00:33:57 -0700 Subject: [PATCH 08/26] Try building SDL locally on linux runners --- .github/workflows/build.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4c2067161..6d1d94c1a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -116,6 +116,13 @@ jobs: brew unlink python && brew link --overwrite python brew unlink python@3.12 && brew link --overwrite python@3.12 + - name: "Setup SDL3" + if: runner.os == 'Linux' + uses: libsdl-org/setup-sdl@main + with: + version: 3-latest + install-linux-dependencies: true + - name: "Install: Required Dev Packages" run: | set -eux @@ -230,8 +237,7 @@ jobs: -DFLAT_INSTALL_TREE=ON ;; linux64) - cmake -B build -DCMAKE_BUILD_TYPE=${{ matrix.cmake_configuration }} \ - -DDOWNLOAD_DEPENDENCIES=ON \ + cmake -B build -DCMAKE_BUILD_TYPE=${{ matrix.cmake_configuration }} ;; esac From 959fd043bbb6565f13c5baac8a8b2b52eb533f1d Mon Sep 17 00:00:00 2001 From: Spitko Date: Thu, 18 Sep 2025 00:43:47 -0700 Subject: [PATCH 09/26] Remove setup SDL action, it's broken --- .github/workflows/build.yml | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6d1d94c1a..4c2067161 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -116,13 +116,6 @@ jobs: brew unlink python && brew link --overwrite python brew unlink python@3.12 && brew link --overwrite python@3.12 - - name: "Setup SDL3" - if: runner.os == 'Linux' - uses: libsdl-org/setup-sdl@main - with: - version: 3-latest - install-linux-dependencies: true - - name: "Install: Required Dev Packages" run: | set -eux @@ -237,7 +230,8 @@ jobs: -DFLAT_INSTALL_TREE=ON ;; linux64) - cmake -B build -DCMAKE_BUILD_TYPE=${{ matrix.cmake_configuration }} + cmake -B build -DCMAKE_BUILD_TYPE=${{ matrix.cmake_configuration }} \ + -DDOWNLOAD_DEPENDENCIES=ON \ ;; esac From 6d9c5eac6d8e39616021eb227f155221b2ec523b Mon Sep 17 00:00:00 2001 From: Spitko Date: Thu, 18 Sep 2025 21:41:44 -0700 Subject: [PATCH 10/26] Fix memory leaks, manually install SDL on linux --- .github/workflows/build.yml | 15 ++++++++-- libs/sdl/sdl.c | 56 +++++++++++++++++++++++-------------- 2 files changed, 48 insertions(+), 23 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4c2067161..a802f836e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -202,6 +202,18 @@ jobs: haxelib install hashlink haxelib list + - name: "Build and install SDL3" + if: runner.os == 'Linux' + run: | + wget https://github.com/libsdl-org/SDL/releases/download/release-3.2.22/SDL3-3.2.22.tar.gz + tar -xzvf SDL3-3.2.22.tar.gz + cd SDL3-3.2.22/ + mkdir build + cd build + cmake .. + make + sudo make --install + - name: "Build: HashLink" run: | @@ -230,8 +242,7 @@ jobs: -DFLAT_INSTALL_TREE=ON ;; linux64) - cmake -B build -DCMAKE_BUILD_TYPE=${{ matrix.cmake_configuration }} \ - -DDOWNLOAD_DEPENDENCIES=ON \ + cmake -B build -DCMAKE_BUILD_TYPE=${{ matrix.cmake_configuration }} ;; esac diff --git a/libs/sdl/sdl.c b/libs/sdl/sdl.c index 35ea6da73..c2d226fee 100644 --- a/libs/sdl/sdl.c +++ b/libs/sdl/sdl.c @@ -406,6 +406,7 @@ HL_PRIM int HL_NAME(get_screen_width)( int index ) { index = 0; const SDL_DisplayMode *e = SDL_GetCurrentDisplayMode(displays[index]); + SDL_Free( displays ); return e->w; } @@ -416,6 +417,7 @@ HL_PRIM int HL_NAME(get_screen_height)( int index ) { index = 0; const SDL_DisplayMode *e = SDL_GetCurrentDisplayMode(displays[index]); + SDL_Free( displays ); return e->h; } @@ -761,17 +763,22 @@ DEFINE_PRIM(_I32, win_get_id, TWIN); HL_PRIM int HL_NAME(gctrl_count)() { int count; - SDL_GetJoysticks(&count); + SDL_JoystickID *sticks = SDL_GetJoysticks(&count); + SDL_Free(sticks); return count; } HL_PRIM SDL_Gamepad *HL_NAME(gctrl_open)(int idx) { int count; SDL_JoystickID *sticks = SDL_GetJoysticks(&count); - if( idx >= count || !SDL_IsGamepad(sticks[idx]) ) - return NULL; - return SDL_OpenGamepad(sticks[idx]); + SDL_GamePad *pad = NULL; + + if( idx >= 0 && idx < count && SDL_IsGamepad(sticks[idx]) ) + pad = SDL_OpenGamepad( sticks[idx] ); + + SDL_Free(sticks); + return pad; } HL_PRIM void HL_NAME(gctrl_close)(SDL_Gamepad *controller) { @@ -828,7 +835,9 @@ DEFINE_PRIM(_I32, haptic_rumble_play, THAPTIC _F64 _I32); HL_PRIM int HL_NAME(joy_count)() { int count; - SDL_GetJoysticks(&count); + SDL_Joystick *sticks = SDL_GetJoysticks(&count); + SDL_Free(sticks); + return count; } @@ -938,23 +947,26 @@ HL_PRIM bool HL_NAME(get_drag_and_drop_enabled)() { HL_PRIM varray* HL_NAME(get_displays)() { int n; SDL_DisplayID *displays = SDL_GetDisplays(&n); - if (n <= 0) - return NULL; - varray* arr = hl_alloc_array(&hlt_dynobj, n); - for (int i = 0; i < n; i++) { - vdynamic *obj = (vdynamic*) hl_alloc_dynobj(); - SDL_Rect rect; - SDL_DisplayID display = displays[i]; - SDL_GetDisplayBounds(display, &rect); - hl_dyn_seti(obj, hl_hash_utf8("right"), &hlt_i32, rect.x+rect.w); - hl_dyn_seti(obj, hl_hash_utf8("bottom"), &hlt_i32, rect.y+rect.h); - hl_dyn_seti(obj, hl_hash_utf8("left"), &hlt_i32, rect.x); - hl_dyn_seti(obj, hl_hash_utf8("top"), &hlt_i32, rect.y); - hl_dyn_seti(obj, hl_hash_utf8("handle"), &hlt_i32, i); - const char *name = SDL_GetDisplayName(display); - hl_dyn_setp(obj, hl_hash_utf8("name"), &hlt_bytes, hl_copy_bytes(name, (int) strlen(name)+1)); - hl_aptr(arr, vdynamic*)[i] = obj; + if (n > 0) + { + varray* arr = hl_alloc_array(&hlt_dynobj, n); + for (int i = 0; i < n; i++) { + vdynamic *obj = (vdynamic*) hl_alloc_dynobj(); + SDL_Rect rect; + SDL_DisplayID display = displays[i]; + SDL_GetDisplayBounds(display, &rect); + hl_dyn_seti(obj, hl_hash_utf8("right"), &hlt_i32, rect.x+rect.w); + hl_dyn_seti(obj, hl_hash_utf8("bottom"), &hlt_i32, rect.y+rect.h); + hl_dyn_seti(obj, hl_hash_utf8("left"), &hlt_i32, rect.x); + hl_dyn_seti(obj, hl_hash_utf8("top"), &hlt_i32, rect.y); + hl_dyn_seti(obj, hl_hash_utf8("handle"), &hlt_i32, i); + const char *name = SDL_GetDisplayName(display); + hl_dyn_setp(obj, hl_hash_utf8("name"), &hlt_bytes, hl_copy_bytes(name, (int) strlen(name)+1)); + hl_aptr(arr, vdynamic*)[i] = obj; + } } + SDL_Free( displays ); + return arr; } @@ -975,6 +987,8 @@ HL_PRIM varray* HL_NAME(get_display_modes)(int display_id) { hl_dyn_seti(obj, hl_hash_utf8("framerate"), &hlt_i32, mode->refresh_rate); hl_aptr(arr, vdynamic*)[i] = obj; } + + SDL_Free(modes); return arr; } From bf21e883c0e7d4a527ea538be630a581bdc442a7 Mon Sep 17 00:00:00 2001 From: Spitko Date: Thu, 18 Sep 2025 21:48:10 -0700 Subject: [PATCH 11/26] Fix build errors --- libs/sdl/sdl.c | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/libs/sdl/sdl.c b/libs/sdl/sdl.c index c2d226fee..e341751bc 100644 --- a/libs/sdl/sdl.c +++ b/libs/sdl/sdl.c @@ -772,7 +772,7 @@ HL_PRIM SDL_Gamepad *HL_NAME(gctrl_open)(int idx) { int count; SDL_JoystickID *sticks = SDL_GetJoysticks(&count); - SDL_GamePad *pad = NULL; + SDL_Gamepad *pad = NULL; if( idx >= 0 && idx < count && SDL_IsGamepad(sticks[idx]) ) pad = SDL_OpenGamepad( sticks[idx] ); @@ -947,24 +947,23 @@ HL_PRIM bool HL_NAME(get_drag_and_drop_enabled)() { HL_PRIM varray* HL_NAME(get_displays)() { int n; SDL_DisplayID *displays = SDL_GetDisplays(&n); - if (n > 0) - { - varray* arr = hl_alloc_array(&hlt_dynobj, n); - for (int i = 0; i < n; i++) { - vdynamic *obj = (vdynamic*) hl_alloc_dynobj(); - SDL_Rect rect; - SDL_DisplayID display = displays[i]; - SDL_GetDisplayBounds(display, &rect); - hl_dyn_seti(obj, hl_hash_utf8("right"), &hlt_i32, rect.x+rect.w); - hl_dyn_seti(obj, hl_hash_utf8("bottom"), &hlt_i32, rect.y+rect.h); - hl_dyn_seti(obj, hl_hash_utf8("left"), &hlt_i32, rect.x); - hl_dyn_seti(obj, hl_hash_utf8("top"), &hlt_i32, rect.y); - hl_dyn_seti(obj, hl_hash_utf8("handle"), &hlt_i32, i); - const char *name = SDL_GetDisplayName(display); - hl_dyn_setp(obj, hl_hash_utf8("name"), &hlt_bytes, hl_copy_bytes(name, (int) strlen(name)+1)); - hl_aptr(arr, vdynamic*)[i] = obj; - } + varray* arr = hl_alloc_array(&hlt_dynobj, n); + + for (int i = 0; i < n; i++) { + vdynamic *obj = (vdynamic*) hl_alloc_dynobj(); + SDL_Rect rect; + SDL_DisplayID display = displays[i]; + SDL_GetDisplayBounds(display, &rect); + hl_dyn_seti(obj, hl_hash_utf8("right"), &hlt_i32, rect.x+rect.w); + hl_dyn_seti(obj, hl_hash_utf8("bottom"), &hlt_i32, rect.y+rect.h); + hl_dyn_seti(obj, hl_hash_utf8("left"), &hlt_i32, rect.x); + hl_dyn_seti(obj, hl_hash_utf8("top"), &hlt_i32, rect.y); + hl_dyn_seti(obj, hl_hash_utf8("handle"), &hlt_i32, i); + const char *name = SDL_GetDisplayName(display); + hl_dyn_setp(obj, hl_hash_utf8("name"), &hlt_bytes, hl_copy_bytes(name, (int) strlen(name)+1)); + hl_aptr(arr, vdynamic*)[i] = obj; } + SDL_Free( displays ); return arr; From c53a6b0e373d4fdc74acdf92d000c1c8ede5dd3e Mon Sep 17 00:00:00 2001 From: Spitko Date: Thu, 18 Sep 2025 21:53:14 -0700 Subject: [PATCH 12/26] SDL_Free -> SDL_free, fix warning --- libs/sdl/sdl.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/libs/sdl/sdl.c b/libs/sdl/sdl.c index e341751bc..e69140296 100644 --- a/libs/sdl/sdl.c +++ b/libs/sdl/sdl.c @@ -406,7 +406,7 @@ HL_PRIM int HL_NAME(get_screen_width)( int index ) { index = 0; const SDL_DisplayMode *e = SDL_GetCurrentDisplayMode(displays[index]); - SDL_Free( displays ); + SDL_free( displays ); return e->w; } @@ -417,7 +417,7 @@ HL_PRIM int HL_NAME(get_screen_height)( int index ) { index = 0; const SDL_DisplayMode *e = SDL_GetCurrentDisplayMode(displays[index]); - SDL_Free( displays ); + SDL_free( displays ); return e->h; } @@ -764,7 +764,7 @@ DEFINE_PRIM(_I32, win_get_id, TWIN); HL_PRIM int HL_NAME(gctrl_count)() { int count; SDL_JoystickID *sticks = SDL_GetJoysticks(&count); - SDL_Free(sticks); + SDL_free(sticks); return count; } @@ -777,7 +777,7 @@ HL_PRIM SDL_Gamepad *HL_NAME(gctrl_open)(int idx) { if( idx >= 0 && idx < count && SDL_IsGamepad(sticks[idx]) ) pad = SDL_OpenGamepad( sticks[idx] ); - SDL_Free(sticks); + SDL_free(sticks); return pad; } @@ -836,7 +836,7 @@ DEFINE_PRIM(_I32, haptic_rumble_play, THAPTIC _F64 _I32); HL_PRIM int HL_NAME(joy_count)() { int count; SDL_Joystick *sticks = SDL_GetJoysticks(&count); - SDL_Free(sticks); + SDL_free(sticks); return count; } @@ -948,7 +948,7 @@ HL_PRIM varray* HL_NAME(get_displays)() { int n; SDL_DisplayID *displays = SDL_GetDisplays(&n); varray* arr = hl_alloc_array(&hlt_dynobj, n); - + for (int i = 0; i < n; i++) { vdynamic *obj = (vdynamic*) hl_alloc_dynobj(); SDL_Rect rect; @@ -964,7 +964,7 @@ HL_PRIM varray* HL_NAME(get_displays)() { hl_aptr(arr, vdynamic*)[i] = obj; } - SDL_Free( displays ); + SDL_free( displays ); return arr; } @@ -987,19 +987,18 @@ HL_PRIM varray* HL_NAME(get_display_modes)(int display_id) { hl_aptr(arr, vdynamic*)[i] = obj; } - SDL_Free(modes); + SDL_free(modes); return arr; } HL_PRIM vdynobj* HL_NAME(get_current_display_mode)(int display_id, bool registry) { const SDL_DisplayMode *mode; - int r; if(registry) mode = SDL_GetDesktopDisplayMode(display_id); else mode = SDL_GetCurrentDisplayMode(display_id); if (mode == NULL) { - printf("can't find mode for %d : %d\n", display_id, r); + printf("can't find mode for %d\n", display_id); return NULL; } vdynamic* obj = (vdynamic*)hl_alloc_dynobj(); From d077ea3c2e93544195b6db0031363f6b895ede5d Mon Sep 17 00:00:00 2001 From: Spitko Date: Thu, 18 Sep 2025 21:54:11 -0700 Subject: [PATCH 13/26] Workflow fix --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a802f836e..a2fbb05ad 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -212,7 +212,7 @@ jobs: cd build cmake .. make - sudo make --install + sudo make install - name: "Build: HashLink" From 8dd01958642a81737525af9acdfc309d0f85f419 Mon Sep 17 00:00:00 2001 From: Spitko Date: Thu, 18 Sep 2025 22:01:48 -0700 Subject: [PATCH 14/26] SDL_GetJoysticks returns SDL_JoystickID*, not SDL_Joystick* caught by gcc14 build --- libs/sdl/sdl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/sdl/sdl.c b/libs/sdl/sdl.c index e69140296..101f9136b 100644 --- a/libs/sdl/sdl.c +++ b/libs/sdl/sdl.c @@ -835,7 +835,7 @@ DEFINE_PRIM(_I32, haptic_rumble_play, THAPTIC _F64 _I32); HL_PRIM int HL_NAME(joy_count)() { int count; - SDL_Joystick *sticks = SDL_GetJoysticks(&count); + SDL_JoystickID *sticks = SDL_GetJoysticks(&count); SDL_free(sticks); return count; From 1ecc107c1088fc9131253acdf24c080e2da9bf7b Mon Sep 17 00:00:00 2001 From: Spitko Date: Thu, 18 Sep 2025 22:09:19 -0700 Subject: [PATCH 15/26] Remove -I $(BREW_SDL_PREFIX)/include/SDL3, fix IOS SDL_syswm.h was removed, builders didn't catch because we don't hace CI for IOS/TVOS --- Makefile | 2 +- libs/sdl/gl.c | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Makefile b/Makefile index d2ee144cf..dc2016f82 100644 --- a/Makefile +++ b/Makefile @@ -154,7 +154,7 @@ BREW_PREFIX := $(shell brew --prefix) BREW_OPENAL_PREFIX := $(shell brew --prefix openal-soft) BREW_SDL_PREFIX := $(shell brew --prefix sdl3) -CFLAGS += -m$(MARCH) -I include -I $(BREW_PREFIX)/include -I $(BREW_OPENAL_PREFIX)/include -I $(BREW_SDL_PREFIX)/include/SDL3 -Dopenal_soft -DGL_SILENCE_DEPRECATION +CFLAGS += -m$(MARCH) -I include -I $(BREW_PREFIX)/include -I $(BREW_OPENAL_PREFIX)/include -Dopenal_soft -DGL_SILENCE_DEPRECATION LFLAGS += -Wl,-export_dynamic ifdef OSX_SDK diff --git a/libs/sdl/gl.c b/libs/sdl/gl.c index 118be4117..10b8e4624 100644 --- a/libs/sdl/gl.c +++ b/libs/sdl/gl.c @@ -4,7 +4,6 @@ #if defined(HL_IOS) || defined (HL_TVOS) # include -# include # include # define HL_GLES #elif defined(HL_MAC) From 163800e81ef00e942723a521ef24ef9cc20696e9 Mon Sep 17 00:00:00 2001 From: Spitko Date: Fri, 19 Sep 2025 20:52:37 -0700 Subject: [PATCH 16/26] Fix controller hotplug SDL3 no longer uses controller index, but a joystick ID now. These IDs are not necessarily sequential, so controllers would often not work unless they were plugged in at launch, or may not work at all if the ids are higher than the count. This requires a small heaps change as well. --- libs/sdl/sdl.c | 13 ++----------- libs/sdl/sdl/GameController.hx | 4 ++-- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/libs/sdl/sdl.c b/libs/sdl/sdl.c index 101f9136b..03e25dd15 100644 --- a/libs/sdl/sdl.c +++ b/libs/sdl/sdl.c @@ -768,17 +768,8 @@ HL_PRIM int HL_NAME(gctrl_count)() { return count; } -HL_PRIM SDL_Gamepad *HL_NAME(gctrl_open)(int idx) { - int count; - SDL_JoystickID *sticks = SDL_GetJoysticks(&count); - - SDL_Gamepad *pad = NULL; - - if( idx >= 0 && idx < count && SDL_IsGamepad(sticks[idx]) ) - pad = SDL_OpenGamepad( sticks[idx] ); - - SDL_free(sticks); - return pad; +HL_PRIM SDL_Gamepad *HL_NAME(gctrl_open)(SDL_JoystickID id) { + return SDL_OpenGamepad(id); } HL_PRIM void HL_NAME(gctrl_close)(SDL_Gamepad *controller) { diff --git a/libs/sdl/sdl/GameController.hx b/libs/sdl/sdl/GameController.hx index 7ffe2faa3..1147a68df 100644 --- a/libs/sdl/sdl/GameController.hx +++ b/libs/sdl/sdl/GameController.hx @@ -13,8 +13,8 @@ class GameController { public var id(get,never) : Int; public var name(get,never) : String; - public function new( index : Int ){ - ptr = gctrlOpen( index ); + public function new( id : Int ){ + ptr = gctrlOpen( id ); } public inline function getAxis( axisId : Int ){ From 98819745e871190922c5934a1da238f304f9ce8b Mon Sep 17 00:00:00 2001 From: Spitko Date: Sat, 20 Sep 2025 15:04:23 -0700 Subject: [PATCH 17/26] Maintain API compatibility with SDL2 --- libs/sdl/sdl.c | 102 ++++++++++++++++++++++++++++------------- libs/sdl/sdl/Sdl.hx | 22 ++++++--- libs/sdl/sdl/Window.hx | 25 ++-------- 3 files changed, 88 insertions(+), 61 deletions(-) diff --git a/libs/sdl/sdl.c b/libs/sdl/sdl.c index 03e25dd15..42bf48e47 100644 --- a/libs/sdl/sdl.c +++ b/libs/sdl/sdl.c @@ -399,24 +399,21 @@ HL_PRIM void HL_NAME(delay)( int time ) { hl_blocking(false); } -HL_PRIM int HL_NAME(get_screen_width)( int index ) { +// SDL2 compat: Assume display 0. +HL_PRIM int HL_NAME(get_screen_width)() { int count; SDL_DisplayID *displays = SDL_GetDisplays( &count ); - if ( index < 0 || index > count ) - index = 0; - - const SDL_DisplayMode *e = SDL_GetCurrentDisplayMode(displays[index]); + const SDL_DisplayMode *e = SDL_GetCurrentDisplayMode(displays[0]); SDL_free( displays ); return e->w; } -HL_PRIM int HL_NAME(get_screen_height)( int index ) { +// SDL2 compat: Assume display 0. +HL_PRIM int HL_NAME(get_screen_height)() { int count; SDL_DisplayID *displays = SDL_GetDisplays( &count ); - if ( index < 0 || index > count ) - index = 0; - const SDL_DisplayMode *e = SDL_GetCurrentDisplayMode(displays[index]); + const SDL_DisplayMode *e = SDL_GetCurrentDisplayMode(displays[0]); SDL_free( displays ); return e->h; } @@ -455,19 +452,55 @@ HL_PRIM bool HL_NAME(detect_win32)() { # endif } -HL_PRIM void HL_NAME(text_input)( SDL_Window* window, bool enable ) { - if( enable ) - SDL_StartTextInput(window); - else - SDL_StopTextInput(window); +// sdl2 compat: start input for all windows +HL_PRIM void HL_NAME(text_input)( bool enable ) { + + SDL_Window **windows; + + /* First, enable text events */ + (void)SDL_EventState(SDL_EVENT_TEXT_INPUT, 1); + (void)SDL_EventState(SDL_EVENT_TEXT_EDITING, 1); + + windows = SDL_GetWindows(NULL); + if (windows) { + int i; + for (i = 0; windows[i]; ++i) { + if( enable ) + SDL_StartTextInput(windows[i]); + else + SDL_StopTextInput(windows[i]); + + } + SDL_free(windows); + } } -HL_PRIM bool HL_NAME(set_relative_mouse_mode)(SDL_Window* window, bool enable) { - return SDL_SetWindowRelativeMouseMode(window, enable); + +// sdl2 compat: We need to internally store relative mouse mode state +static bool relative_mouse_mode = false; + +HL_PRIM int HL_NAME(set_relative_mouse_mode)( bool enable) { + int retval = 0; + SDL_Window **windows = SDL_GetWindows(NULL); + if (windows) { + int i; + + for (i = 0; windows[i]; ++i) { + if (!SDL_SetWindowRelativeMouseMode(windows[i], enable)) { + retval = -1; + } + } + + SDL_free(windows); + } + if (retval == 0) { + relative_mouse_mode = enable; + } + return retval; } -HL_PRIM bool HL_NAME(get_relative_mouse_mode)(SDL_Window* window) { - return SDL_GetWindowRelativeMouseMode(window); +HL_PRIM bool HL_NAME(get_relative_mouse_mode)() { + return relative_mouse_mode; } HL_PRIM int HL_NAME(warp_mouse_global)(int x, int y) { @@ -478,19 +511,24 @@ HL_PRIM void HL_NAME(warp_mouse_in_window)(SDL_Window* window, int x, int y) { SDL_WarpMouseInWindow(window, x, y); } +// SDl2 compat: Grab both HL_PRIM void HL_NAME(set_window_grab)(SDL_Window* window, bool grabbed) { - // Grab both. SDL_SetWindowKeyboardGrab(window, grabbed); SDL_SetWindowMouseGrab(window, grabbed); } +// SDL2 compat: We only need to check for keyboard grab since we grab both HL_PRIM bool HL_NAME(get_window_grab)(SDL_Window* window) { - // @todo: SDL3 separates keyboard and mouse grab here. Do we care? return SDL_GetWindowKeyboardGrab(window); } -HL_PRIM int HL_NAME(get_global_mouse_state)(float* x, float* y) { - return SDL_GetGlobalMouseState(x, y); +// sdl2 compat: +HL_PRIM int HL_NAME(get_global_mouse_state)(int* x, int* y) { + float fx, fy; + int retval = SDL_GetGlobalMouseState(&fx, &fy); + *x = (int)fx; + *y = (int)fy; + return retval; } HL_PRIM const char *HL_NAME(detect_keyboard_layout)() { @@ -512,22 +550,22 @@ DEFINE_PRIM(_BOOL, event_loop, _DYN ); DEFINE_PRIM(_I32, event_poll, _STRUCT ); DEFINE_PRIM(_VOID, quit, _NO_ARG); DEFINE_PRIM(_VOID, delay, _I32); -DEFINE_PRIM(_I32, get_screen_width, _I32); -DEFINE_PRIM(_I32, get_screen_height, _I32); +DEFINE_PRIM(_I32, get_screen_width, _NO_ARG); +DEFINE_PRIM(_I32, get_screen_height, _NO_ARG); DEFINE_PRIM(_I32, get_screen_width_of_window, TWIN); DEFINE_PRIM(_I32, get_screen_height_of_window, TWIN); DEFINE_PRIM(_I32, get_framerate, TWIN); DEFINE_PRIM(_VOID, message_box, _BYTES _BYTES _BOOL); DEFINE_PRIM(_VOID, set_vsync, _BOOL); DEFINE_PRIM(_BOOL, detect_win32, _NO_ARG); -DEFINE_PRIM(_VOID, text_input, TWIN _BOOL); -DEFINE_PRIM(_BOOL, set_relative_mouse_mode, TWIN _BOOL); -DEFINE_PRIM(_BOOL, get_relative_mouse_mode, TWIN _NO_ARG); +DEFINE_PRIM(_VOID, text_input, _BOOL); +DEFINE_PRIM(_I32, set_relative_mouse_mode, _BOOL); +DEFINE_PRIM(_BOOL, get_relative_mouse_mode, _NO_ARG); DEFINE_PRIM(_I32, warp_mouse_global, _I32 _I32); DEFINE_PRIM(_VOID, warp_mouse_in_window, TWIN _I32 _I32); DEFINE_PRIM(_VOID, set_window_grab, TWIN _BOOL); DEFINE_PRIM(_BOOL, get_window_grab, TWIN); -DEFINE_PRIM(_I32, get_global_mouse_state, _REF(_F32) _REF(_F32)); +DEFINE_PRIM(_I32, get_global_mouse_state, _REF(_I32) _REF(_I32)); DEFINE_PRIM(_BYTES, detect_keyboard_layout, _NO_ARG); DEFINE_PRIM(_BOOL, hint_value, _BYTES _BYTES); @@ -647,8 +685,8 @@ HL_PRIM void HL_NAME(win_set_title)(SDL_Window *win, vbyte *title) { SDL_SetWindowTitle(win, (char*)title); } -HL_PRIM bool HL_NAME(win_set_position)(SDL_Window *win, int x, int y) { - return SDL_SetWindowPosition(win, x, y); +HL_PRIM void HL_NAME(win_set_position)(SDL_Window *win, int x, int y) { + SDL_SetWindowPosition(win, x, y); } HL_PRIM void HL_NAME(win_get_position)(SDL_Window *win, int *x, int *y) { @@ -680,7 +718,7 @@ HL_PRIM void HL_NAME(win_get_max_size)(SDL_Window *win, int *width, int *height) } HL_PRIM double HL_NAME(win_get_opacity)(SDL_Window *win) { - return SDL_GetWindowOpacity(win ); + return SDL_GetWindowOpacity(win); } HL_PRIM bool HL_NAME(win_set_opacity)(SDL_Window *win, double opacity) { @@ -744,7 +782,7 @@ DEFINE_PRIM(_BOOL, win_set_display_mode, TWIN _I32 _I32 _I32); DEFINE_PRIM(_I32, win_display_handle, TWIN); DEFINE_PRIM(_VOID, win_resize, TWIN _I32); DEFINE_PRIM(_VOID, win_set_title, TWIN _BYTES); -DEFINE_PRIM(_BOOL, win_set_position, TWIN _I32 _I32); +DEFINE_PRIM(_VOID, win_set_position, TWIN _I32 _I32); DEFINE_PRIM(_VOID, win_get_position, TWIN _REF(_I32) _REF(_I32)); DEFINE_PRIM(_VOID, win_set_size, TWIN _I32 _I32); DEFINE_PRIM(_VOID, win_set_min_size, TWIN _I32 _I32); diff --git a/libs/sdl/sdl/Sdl.hx b/libs/sdl/sdl/Sdl.hx index d997b2ce0..77d6e40be 100644 --- a/libs/sdl/sdl/Sdl.hx +++ b/libs/sdl/sdl/Sdl.hx @@ -90,18 +90,18 @@ class Sdl { public static function delay(time:Int) { } - public static function getScreenWidth(?win : sdl.Window, index: Int = 0) : Int { + public static function getScreenWidth(?win : sdl.Window) : Int { return if(win == null) - get_screen_width( index ); + get_screen_width(); else get_screen_width_of_window(@:privateAccess win.win); } - public static function getScreenHeight(?win : sdl.Window, index: Int = 0) : Int { + public static function getScreenHeight(?win : sdl.Window) : Int { return if(win == null) - get_screen_height( index ); + get_screen_height(); else get_screen_height_of_window(@:privateAccess win.win); } @@ -148,6 +148,10 @@ class Sdl { return a; } + public static function setRelativeMouseMode( enable : Bool ) : Int { + return 0; + } + public static function setClipboardText( text : String ) : Bool { if( text == null ) return false; @@ -172,12 +176,12 @@ class Sdl { } @:hlNative("?sdl", "get_screen_width") - static function get_screen_width( index: Int ) : Int { + static function get_screen_width() : Int { return 0; } @:hlNative("?sdl", "get_screen_height") - static function get_screen_height( index: Int ) : Int { + static function get_screen_height() : Int { return 0; } @@ -217,12 +221,16 @@ class Sdl { return null; } + public static function getRelativeMouseMode() : Bool { + return false; + } + public static function warpMouseGlobal( x : Int, y : Int ) : Int { return 0; } @:hlNative("?sdl", "get_global_mouse_state") - public static function getGlobalMouseState( x : hl.Ref, y : hl.Ref ) : Int { + public static function getGlobalMouseState( x : hl.Ref, y : hl.Ref ) : Int { return 0; } diff --git a/libs/sdl/sdl/Window.hx b/libs/sdl/sdl/Window.hx index e39eb87a3..2342e0b7d 100644 --- a/libs/sdl/sdl/Window.hx +++ b/libs/sdl/sdl/Window.hx @@ -27,6 +27,7 @@ class Window { public static inline var SDL_WINDOW_FULLSCREEN = 0x00000001; public static inline var SDL_WINDOW_OPENGL = 0x00000002; public static inline var SDL_WINDOW_OCCLUDED = 0x00000004; + public static inline var SDL_WINDOW_SHOWN = 0x00000004; // SDL2 compat public static inline var SDL_WINDOW_HIDDEN = 0x00000008; public static inline var SDL_WINDOW_BORDERLESS = 0x00000010; public static inline var SDL_WINDOW_RESIZABLE = 0x00000020; @@ -172,7 +173,7 @@ class Window { } public function setPosition( x : Int, y : Int ) { - return winSetPosition(win, x, y); + winSetPosition(win, x, y); } public function center() { @@ -300,15 +301,6 @@ class Window { winResize(win, 2); } - - public function getRelativeMouseMode() : Bool { - return winGetRelativeMouseMode( win ); - } - - public function setRelativeMouseMode( enabled: Bool ) : Bool { - return winSetRelativeMouseMode( win, enabled ); - } - static function winCreateEx( x : Int, y : Int, width : Int, height : Int, sdlFlags : Int ) : WinPtr { return null; } @@ -320,8 +312,7 @@ class Window { static function winSetTitle( win : WinPtr, title : hl.Bytes ) { } - static function winSetPosition( win : WinPtr, width : Int, height : Int ): Bool { - return false; + static function winSetPosition( win : WinPtr, width : Int, height : Int ): Void { } static function winGetPosition( win : WinPtr, width : hl.Ref, height : hl.Ref ) { @@ -400,14 +391,4 @@ class Window { static function warpMouseInWindow( win : WinPtr, x : Int, y : Int ) : Void { } - - @:hlNative("?sdl", "get_relative_mouse_mode") - static function winGetRelativeMouseMode( win : WinPtr ) : Bool { - return false; - } - @:hlNative("?sdl", "set_relative_mouse_mode") - static function winSetRelativeMouseMode( win : WinPtr, enabled: Bool ) : Bool { - return false; - } - } From 67c2dfd5187891afbc39614451a92d176dd4e5df Mon Sep 17 00:00:00 2001 From: Spitko Date: Sat, 20 Sep 2025 15:17:55 -0700 Subject: [PATCH 18/26] Add missing window flags, fix SDL_SetEventEnabled --- libs/sdl/sdl.c | 4 ++-- libs/sdl/sdl/Window.hx | 8 +++++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/libs/sdl/sdl.c b/libs/sdl/sdl.c index c20a1f6ed..713aa2139 100644 --- a/libs/sdl/sdl.c +++ b/libs/sdl/sdl.c @@ -458,8 +458,8 @@ HL_PRIM void HL_NAME(text_input)( bool enable ) { SDL_Window **windows; /* First, enable text events */ - (void)SDL_EventState(SDL_EVENT_TEXT_INPUT, 1); - (void)SDL_EventState(SDL_EVENT_TEXT_EDITING, 1); + SDL_SetEventEnabled(SDL_EVENT_TEXT_INPUT, true ); + SDL_SetEventEnabled(SDL_EVENT_TEXT_EDITING, true); windows = SDL_GetWindows(NULL); if (windows) { diff --git a/libs/sdl/sdl/Window.hx b/libs/sdl/sdl/Window.hx index 37382994c..cbf324fad 100644 --- a/libs/sdl/sdl/Window.hx +++ b/libs/sdl/sdl/Window.hx @@ -27,13 +27,13 @@ class Window { public static inline var SDL_WINDOW_FULLSCREEN = 0x00000001; public static inline var SDL_WINDOW_OPENGL = 0x00000002; public static inline var SDL_WINDOW_OCCLUDED = 0x00000004; - public static inline var SDL_WINDOW_SHOWN = 0x00000004; // SDL2 compat public static inline var SDL_WINDOW_HIDDEN = 0x00000008; public static inline var SDL_WINDOW_BORDERLESS = 0x00000010; public static inline var SDL_WINDOW_RESIZABLE = 0x00000020; public static inline var SDL_WINDOW_MINIMIZED = 0x00000040; public static inline var SDL_WINDOW_MAXIMIZED = 0x00000080; public static inline var SDL_WINDOW_MOUSE_GRABBED = 0x00000100; + public static inline var SDL_WINDOW_INPUT_FOCUS = 0x00000200; public static inline var SDL_WINDOW_MOUSE_FOCUS = 0x00000400; public static inline var SDL_WINDOW_FOREIGN = 0x00000800; @@ -42,11 +42,17 @@ class Window { public static inline var SDL_WINDOW_MOUSE_CAPTURE = 0x00004000; public static inline var SDL_WINDOW_ALWAYS_ON_TOP = 0x00010000; public static inline var SDL_WINDOW_UTILITY = 0x00020000; + public static inline var SDL_WINDOW_TOOLTIP = 0x00040000; public static inline var SDL_WINDOW_POPUP_MENU = 0x00080000; public static inline var SDL_WINDOW_VULKAN = 0x10000000; public static inline var SDL_WINDOW_METAL = 0x20000000; + // SDL2 compatibility + public static inline var SDL_WINDOW_SHOWN = 0x00000004; // SDL2 compat + public static inline var SDL_WINDOW_INPUT_GRABBED = 0x00000100; // SDL2 compat + public static inline var SDL_WINDOW_SKIP_TASKBAR = 0x00020000; // SDL2 compat + var win : WinPtr; var glctx : GLContext; var lastFrame : Float; From 2971fec2f4f6d34ffa666456336e92ae4336cc11 Mon Sep 17 00:00:00 2001 From: Spitko Date: Sat, 20 Sep 2025 15:27:35 -0700 Subject: [PATCH 19/26] Emulate SDL_GRAB_KEYBOARD --- libs/sdl/sdl.c | 15 +++++++++++---- libs/sdl/sdl/Sdl.hx | 2 +- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/libs/sdl/sdl.c b/libs/sdl/sdl.c index 713aa2139..9ee40e373 100644 --- a/libs/sdl/sdl.c +++ b/libs/sdl/sdl.c @@ -154,8 +154,13 @@ HL_PRIM void HL_NAME(gl_options)( int major, int minor, int depth, int stencil, SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, samples); } } +static hint_window_grab_keyboard = false; HL_PRIM bool HL_NAME(hint_value)( vbyte* name, vbyte* value) { + if( strcmp( name, "SDL_GRAB_KEYBOARD" ) == 0 ) + hint_window_grab_keyboard = value != 0; + + return SDL_SetHint((char*)name, (char*)value) == true; } @@ -511,15 +516,17 @@ HL_PRIM void HL_NAME(warp_mouse_in_window)(SDL_Window* window, int x, int y) { SDL_WarpMouseInWindow(window, x, y); } -// SDl2 compat: Grab both +// SDl2 compat: Check emulated `SDL_HINT_GRAB_KEYBOARD` hint HL_PRIM void HL_NAME(set_window_grab)(SDL_Window* window, bool grabbed) { - SDL_SetWindowKeyboardGrab(window, grabbed); + if( hint_window_grab_keyboard ) + SDL_SetWindowKeyboardGrab(window, grabbed); + SDL_SetWindowMouseGrab(window, grabbed); } -// SDL2 compat: We only need to check for keyboard grab since we grab both +// SDL2 compat: We only need to check for mouse grab since that's always obtained. HL_PRIM bool HL_NAME(get_window_grab)(SDL_Window* window) { - return SDL_GetWindowKeyboardGrab(window); + return SDL_GetWindowMouseGrab(window); } // sdl2 compat: diff --git a/libs/sdl/sdl/Sdl.hx b/libs/sdl/sdl/Sdl.hx index 77d6e40be..1d2735c95 100644 --- a/libs/sdl/sdl/Sdl.hx +++ b/libs/sdl/sdl/Sdl.hx @@ -283,7 +283,7 @@ enum abstract SDLHint(String) from String to String { var SDL_HINT_VIDEO_X11_NET_WM_PING = "SDL_VIDEO_X11_NET_WM_PING"; var SDL_HINT_WINDOW_FRAME_USABLE_WHILE_CURSOR_HIDDEN = "SDL_WINDOW_FRAME_USABLE_WHILE_CURSOR_HIDDEN"; var SDL_HINT_WINDOWS_ENABLE_MESSAGELOOP = "SDL_WINDOWS_ENABLE_MESSAGELOOP"; - var SDL_HINT_GRAB_KEYBOARD = "SDL_GRAB_KEYBOARD"; + var SDL_HINT_GRAB_KEYBOARD = "SDL_GRAB_KEYBOARD"; // SDL2 compat var SDL_HINT_MOUSE_RELATIVE_MODE_WARP = "SDL_MOUSE_RELATIVE_MODE_WARP"; var SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS = "SDL_VIDEO_MINIMIZE_ON_FOCUS_LOSS"; var SDL_HINT_IDLE_TIMER_DISABLED = "SDL_IOS_IDLE_TIMER_DISABLED"; From 146c81041500b3d6445a301b9ccc1412b7371f00 Mon Sep 17 00:00:00 2001 From: Spitko Date: Sat, 20 Sep 2025 15:31:06 -0700 Subject: [PATCH 20/26] Add missing cast --- libs/sdl/sdl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/sdl/sdl.c b/libs/sdl/sdl.c index 9ee40e373..0b45fdebd 100644 --- a/libs/sdl/sdl.c +++ b/libs/sdl/sdl.c @@ -157,7 +157,7 @@ HL_PRIM void HL_NAME(gl_options)( int major, int minor, int depth, int stencil, static hint_window_grab_keyboard = false; HL_PRIM bool HL_NAME(hint_value)( vbyte* name, vbyte* value) { - if( strcmp( name, "SDL_GRAB_KEYBOARD" ) == 0 ) + if( strcmp( (char*)name, "SDL_GRAB_KEYBOARD" ) == 0 ) hint_window_grab_keyboard = value != 0; From 5b84dea92d1652579435d35f9da715e62998601d Mon Sep 17 00:00:00 2001 From: Spitko Date: Sat, 20 Sep 2025 15:32:06 -0700 Subject: [PATCH 21/26] Fix missing bool --- libs/sdl/sdl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/sdl/sdl.c b/libs/sdl/sdl.c index 0b45fdebd..d8c630d4c 100644 --- a/libs/sdl/sdl.c +++ b/libs/sdl/sdl.c @@ -154,7 +154,7 @@ HL_PRIM void HL_NAME(gl_options)( int major, int minor, int depth, int stencil, SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, samples); } } -static hint_window_grab_keyboard = false; +static bool hint_window_grab_keyboard = false; HL_PRIM bool HL_NAME(hint_value)( vbyte* name, vbyte* value) { if( strcmp( (char*)name, "SDL_GRAB_KEYBOARD" ) == 0 ) From a45b7ceff7c8017079451f7ced254eb4f0754f77 Mon Sep 17 00:00:00 2001 From: Spitko Date: Sun, 21 Sep 2025 14:28:17 -0700 Subject: [PATCH 22/26] jdevice->gdevice This doesn't affect anything as these point to the same field, but will prevent a bug in the future if for some reason these structs become unaligned in future SDL releases. --- libs/sdl/sdl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/sdl/sdl.c b/libs/sdl/sdl.c index d8c630d4c..5ea9e15d6 100644 --- a/libs/sdl/sdl.c +++ b/libs/sdl/sdl.c @@ -305,11 +305,11 @@ HL_PRIM bool HL_NAME(event_loop)( event_data *event ) { break; case SDL_EVENT_GAMEPAD_ADDED: event->type = GControllerAdded; - event->reference = e.jdevice.which; + event->reference = e.gdevice.which; break; case SDL_EVENT_GAMEPAD_REMOVED: event->type = GControllerRemoved; - event->reference = e.jdevice.which; + event->reference = e.gdevice.which; break; case SDL_EVENT_GAMEPAD_BUTTON_DOWN : event->type = GControllerDown; From 1849d6fe7daa807ff6358d80b967763abbd8a29c Mon Sep 17 00:00:00 2001 From: Spitko Date: Mon, 22 Sep 2025 21:50:25 -0700 Subject: [PATCH 23/26] add getJoysticks. Bump version. --- libs/sdl/haxelib.json | 2 +- libs/sdl/sdl.c | 17 +++++++++++++++++ libs/sdl/sdl/Sdl.hx | 8 ++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/libs/sdl/haxelib.json b/libs/sdl/haxelib.json index 5ada45cca..0960556cf 100644 --- a/libs/sdl/haxelib.json +++ b/libs/sdl/haxelib.json @@ -4,7 +4,7 @@ "license" : "BSD", "contributors" : ["ncannasse"], "description" : "SDL/GL support for Haxe/HL.", - "version" : "1.16.0", + "version" : "1.17.0", "releasenote" : "", "dependencies": {} } diff --git a/libs/sdl/sdl.c b/libs/sdl/sdl.c index 5ea9e15d6..040558c6a 100644 --- a/libs/sdl/sdl.c +++ b/libs/sdl/sdl.c @@ -920,6 +920,23 @@ DEFINE_PRIM(_BOOL, joy_get_button, TJOY _I32); DEFINE_PRIM(_I32, joy_get_id, TJOY); DEFINE_PRIM(_BYTES, joy_get_name, TJOY); + +// SDL3 Joystick API +HL_PRIM varray *HL_NAME(get_joysticks)(SDL_Joystick *joystick) { + SDL_JoystickID *sticks; + int count; + sticks = SDL_GetJoysticks( &count ); + varray *result = hl_alloc_array(&hlt_i32, count); + int *idx = hl_aptr(result,SDL_Joystick); + while( *sticks ) + { + *idx++ = *sticks++; + } + return result; +} + +DEFINE_PRIM(_ARR, get_joysticks, _NO_ARG ); + // surface diff --git a/libs/sdl/sdl/Sdl.hx b/libs/sdl/sdl/Sdl.hx index 1d2735c95..1c0f6253a 100644 --- a/libs/sdl/sdl/Sdl.hx +++ b/libs/sdl/sdl/Sdl.hx @@ -265,6 +265,14 @@ class Sdl { private static function _getError() : hl.Bytes { return null; } + + + // + // SDL3 Joystick API + // + public static function getJoysticks() : hl.NativeArray { + return null; + } } enum abstract SDLHint(String) from String to String { From 21bfe52b6ba79a2922e3d748c927f61b1ce94bcd Mon Sep 17 00:00:00 2001 From: Spitko Date: Mon, 22 Sep 2025 21:59:57 -0700 Subject: [PATCH 24/26] SDL_Joystick -> SDL_JoystickID --- libs/sdl/sdl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/sdl/sdl.c b/libs/sdl/sdl.c index 040558c6a..fee9cf17f 100644 --- a/libs/sdl/sdl.c +++ b/libs/sdl/sdl.c @@ -922,12 +922,12 @@ DEFINE_PRIM(_BYTES, joy_get_name, TJOY); // SDL3 Joystick API -HL_PRIM varray *HL_NAME(get_joysticks)(SDL_Joystick *joystick) { +HL_PRIM varray *HL_NAME(get_joysticks)() { SDL_JoystickID *sticks; int count; sticks = SDL_GetJoysticks( &count ); varray *result = hl_alloc_array(&hlt_i32, count); - int *idx = hl_aptr(result,SDL_Joystick); + SDL_JoystickID *idx = hl_aptr(result,SDL_JoystickID); while( *sticks ) { *idx++ = *sticks++; From c03200b71bd44769d3abf955e65c020553c36aca Mon Sep 17 00:00:00 2001 From: Spitko Date: Wed, 24 Sep 2025 20:00:48 -0700 Subject: [PATCH 25/26] Update haxelib.json --- libs/sdl/haxelib.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/sdl/haxelib.json b/libs/sdl/haxelib.json index 0960556cf..5ada45cca 100644 --- a/libs/sdl/haxelib.json +++ b/libs/sdl/haxelib.json @@ -4,7 +4,7 @@ "license" : "BSD", "contributors" : ["ncannasse"], "description" : "SDL/GL support for Haxe/HL.", - "version" : "1.17.0", + "version" : "1.16.0", "releasenote" : "", "dependencies": {} } From 71b8f2d4224dc37101ea731e80c3da5f23c43b4e Mon Sep 17 00:00:00 2001 From: Spitko Date: Wed, 15 Oct 2025 23:10:45 -0700 Subject: [PATCH 26/26] fix text input In SDL2, windows start with text_input enabled. SDL3 toggles this, so we need to enable text input whenever we create a window to avoid breaking existing apps. --- libs/sdl/sdl.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libs/sdl/sdl.c b/libs/sdl/sdl.c index fee9cf17f..381cbb761 100644 --- a/libs/sdl/sdl.c +++ b/libs/sdl/sdl.c @@ -642,6 +642,10 @@ HL_PRIM SDL_Window *HL_NAME(win_create_ex)(int x, int y, int width, int height, } SDL_RaiseWindow(win); // better first focus lost behavior # endif + + // SDL2 compat + SDL_StartTextInput(win); + return win; }