diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 754295a05..a2fbb05ad 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -128,11 +128,39 @@ jobs: libmbedtls-dev \ libopenal-dev \ libpng-dev \ - libsdl2-dev \ libturbojpeg-dev \ 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 \ + 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 \ + libpipewire-0.3-dev \ + libwayland-dev \ + libdecor-0-dev \ + liburing-dev ;; darwin*) @@ -143,10 +171,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 ;; @@ -174,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: | @@ -202,7 +242,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 }} + ;; esac cmake --build build --config ${{ matrix.cmake_configuration }} 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/Makefile b/Makefile index 9696f2a12..dc2016f82 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 -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 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..10b8e4624 100644 --- a/libs/sdl/gl.c +++ b/libs/sdl/gl.c @@ -3,18 +3,17 @@ #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 +23,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 98730a50a..381cbb761 100644 --- a/libs/sdl/sdl.c +++ b/libs/sdl/sdl.c @@ -4,11 +4,8 @@ #include "hlsystem.h" #include -#include - -#if defined(HL_WIN) || defined(HL_IOS) || defined(HL_TVOS) -# include -#endif +#include +#include #if defined (HL_IOS) || defined(HL_TVOS) # include @@ -16,7 +13,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 +100,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; } @@ -157,9 +154,14 @@ HL_PRIM void HL_NAME(gl_options)( int major, int minor, int depth, int stencil, SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, samples); } } +static bool hint_window_grab_keyboard = false; HL_PRIM bool HL_NAME(hint_value)( vbyte* name, vbyte* value) { - return SDL_SetHint((char*)name, (char*)value) == SDL_TRUE; + if( strcmp( (char*)name, "SDL_GRAB_KEYBOARD" ) == 0 ) + hint_window_grab_keyboard = value != 0; + + + return SDL_SetHint((char*)name, (char*)value) == true; } HL_PRIM int HL_NAME(event_poll)( SDL_Event *e ) { @@ -169,12 +171,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 +238,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 +293,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; + event->reference = e.gdevice.which; break; - case SDL_CONTROLLERDEVICEREMOVED: + case SDL_EVENT_GAMEPAD_REMOVED: event->type = GControllerRemoved; - event->reference = e.jdevice.which; + event->reference = e.gdevice.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 +404,38 @@ HL_PRIM void HL_NAME(delay)( int time ) { hl_blocking(false); } +// SDL2 compat: Assume display 0. HL_PRIM int HL_NAME(get_screen_width)() { - SDL_DisplayMode e; - SDL_GetCurrentDisplayMode(0, &e); - return e.w; + int count; + SDL_DisplayID *displays = SDL_GetDisplays( &count ); + const SDL_DisplayMode *e = SDL_GetCurrentDisplayMode(displays[0]); + SDL_free( displays ); + return e->w; } +// SDL2 compat: Assume display 0. HL_PRIM int HL_NAME(get_screen_height)() { - SDL_DisplayMode e; - SDL_GetCurrentDisplayMode(0, &e); - return e.h; + int count; + SDL_DisplayID *displays = SDL_GetDisplays( &count ); + + const SDL_DisplayMode *e = SDL_GetCurrentDisplayMode(displays[0]); + SDL_free( displays ); + 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,55 @@ HL_PRIM bool HL_NAME(detect_win32)() { # endif } +// sdl2 compat: start input for all windows HL_PRIM void HL_NAME(text_input)( bool enable ) { - if( enable ) - SDL_StartTextInput(); - else - SDL_StopTextInput(); + + SDL_Window **windows; + + /* First, enable text events */ + SDL_SetEventEnabled(SDL_EVENT_TEXT_INPUT, true ); + SDL_SetEventEnabled(SDL_EVENT_TEXT_EDITING, true); + + 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 int HL_NAME(set_relative_mouse_mode)(bool enable) { - return SDL_SetRelativeMouseMode(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)() { - return SDL_GetRelativeMouseMode(); + return relative_mouse_mode; } HL_PRIM int HL_NAME(warp_mouse_global)(int x, int y) { @@ -470,22 +516,32 @@ HL_PRIM void HL_NAME(warp_mouse_in_window)(SDL_Window* window, int x, int y) { SDL_WarpMouseInWindow(window, x, y); } +// SDl2 compat: Check emulated `SDL_HINT_GRAB_KEYBOARD` hint HL_PRIM void HL_NAME(set_window_grab)(SDL_Window* window, bool grabbed) { - SDL_SetWindowGrab(window, grabbed); + if( hint_window_grab_keyboard ) + SDL_SetWindowKeyboardGrab(window, grabbed); + + SDL_SetWindowMouseGrab(window, grabbed); } +// 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_GetWindowGrab(window); + return SDL_GetWindowMouseGrab(window); } +// sdl2 compat: HL_PRIM int HL_NAME(get_global_mouse_state)(int* x, int* y) { - return SDL_GetGlobalMouseState(x, 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)() { - 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"; @@ -533,11 +589,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 @@ -547,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; } @@ -559,70 +658,38 @@ 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) { @@ -662,13 +729,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) { @@ -720,7 +785,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) @@ -751,33 +816,34 @@ DEFINE_PRIM(_I32, win_get_id, TWIN); // game controller HL_PRIM int HL_NAME(gctrl_count)() { - return SDL_NumJoysticks(); + int count; + SDL_JoystickID *sticks = SDL_GetJoysticks(&count); + SDL_free(sticks); + 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)(SDL_JoystickID id) { + return SDL_OpenGamepad(id); } -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) @@ -789,20 +855,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); @@ -813,35 +879,39 @@ DEFINE_PRIM(_I32, haptic_rumble_play, THAPTIC _F64 _I32); // joystick HL_PRIM int HL_NAME(joy_count)() { - return SDL_NumJoysticks(); + int count; + SDL_JoystickID *sticks = SDL_GetJoysticks(&count); + SDL_free(sticks); + + 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) @@ -854,15 +924,32 @@ 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_JoystickID *sticks; + int count; + sticks = SDL_GetJoysticks( &count ); + varray *result = hl_alloc_array(&hlt_i32, count); + SDL_JoystickID *idx = hl_aptr(result,SDL_JoystickID); + while( *sticks ) + { + *idx++ = *sticks++; + } + return result; +} + +DEFINE_PRIM(_ARR, get_joysticks, _NO_ARG ); + // surface 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) @@ -872,11 +959,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 ) { @@ -888,7 +978,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 ) { @@ -896,7 +986,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)() { @@ -909,66 +999,74 @@ 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) - return NULL; + 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; - 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; } + + SDL_free( displays ); + return arr; } 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; } + + SDL_free(modes); return arr; } HL_PRIM vdynobj* HL_NAME(get_current_display_mode)(int display_id, bool registry) { - SDL_DisplayMode mode; - int r; + const SDL_DisplayMode *mode; if(registry) - r = SDL_GetDesktopDisplayMode(display_id, &mode); + mode = SDL_GetDesktopDisplayMode(display_id); else - r = SDL_GetCurrentDisplayMode(display_id, &mode); - if (r < 0) { - printf("can't find mode for %d : %d\n", display_id, r); + mode = SDL_GetCurrentDisplayMode(display_id); + if (mode == NULL) { + printf("can't find mode for %d\n", display_id); 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; } @@ -987,6 +1085,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); @@ -1002,3 +1104,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/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 ){ diff --git a/libs/sdl/sdl/Sdl.hx b/libs/sdl/sdl/Sdl.hx index 44d4e0db5..1c0f6253a 100644 --- a/libs/sdl/sdl/Sdl.hx +++ b/libs/sdl/sdl/Sdl.hx @@ -166,6 +166,15 @@ 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 { return 0; @@ -251,6 +260,19 @@ class Sdl { public static function getDragAndDropEnabled(): Bool { return false; } + + @:hlNative("?sdl", "get_error") + 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 { @@ -269,7 +291,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"; diff --git a/libs/sdl/sdl/Window.hx b/libs/sdl/sdl/Window.hx index aac77be21..cbf324fad 100644 --- a/libs/sdl/sdl/Window.hx +++ b/libs/sdl/sdl/Window.hx @@ -26,27 +26,33 @@ 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; 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; @@ -68,7 +74,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"; @@ -316,7 +322,7 @@ 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 ): Void { } static function winGetPosition( win : WinPtr, width : hl.Ref, height : hl.Ref ) { @@ -399,5 +405,4 @@ class Window { static function warpMouseInWindow( win : WinPtr, x : Int, y : Int ) : Void { } - }