diff --git a/src/platforms/rcore_clipboard_win32.c b/src/external/win32_clipboard.h similarity index 94% rename from src/platforms/rcore_clipboard_win32.c rename to src/external/win32_clipboard.h index 2eed8468..083e90a9 100644 --- a/src/platforms/rcore_clipboard_win32.c +++ b/src/external/win32_clipboard.h @@ -1,8 +1,13 @@ #if !defined(_WIN32) # error "This module is only made for Windows OS" -#else -// Needs both `Image` and `LoadImageFromMemory` from `rtexture` >:C +#endif + +#ifndef WIN32_CLIPBOARD_ +#define WIN32_CLIPBOARD_ +unsigned char* Win32GetClipboardImageData(int* width, int* height, unsigned long long int *dataSize); +#endif // WIN32_CLIPBOARD_ +#ifdef WIN32_CLIPBOARD_IMPLEMENTATION #include #include #include @@ -176,21 +181,9 @@ typedef struct tagRGBQUAD { static BOOL OpenClipboardRetrying(HWND handle); // Open clipboard with a number of retries static int GetPixelDataOffset(BITMAPINFOHEADER bih); static unsigned char* GetClipboardImageData(int* width, int* height, unsigned int *dataSize); -//---------------------------------------------------------------------------------- -// Module Functions Definition: Clipboard Image -//---------------------------------------------------------------------------------- -Image GetClipboardImage(void) -{ - int width = 0, height = 0; - unsigned int dataSize = 0; - unsigned char* fileData = GetClipboardImageData(&width, &height, &dataSize); - Image image = LoadImageFromMemory(".bmp", fileData, dataSize); - return image; -} - -static unsigned char* GetClipboardImageData(int* width, int* height, unsigned int *dataSize) +unsigned char* Win32GetClipboardImageData(int* width, int* height, unsigned long long int *dataSize) { HWND win = NULL; // Get from somewhere but is doesnt seem to matter const char* msgString = ""; @@ -340,5 +333,5 @@ static int GetPixelDataOffset(BITMAPINFOHEADER bih) return bih.biSize + offset; } -#endif +#endif // WIN32_CLIPBOARD_IMPLEMENTATION // EOF diff --git a/src/platforms/rcore_desktop_sdl.c b/src/platforms/rcore_desktop_sdl.c index 1a016e8e..33e78b0e 100644 --- a/src/platforms/rcore_desktop_sdl.c +++ b/src/platforms/rcore_desktop_sdl.c @@ -23,7 +23,7 @@ * Custom flag for rcore on target platform -not used- * * DEPENDENCIES: -* - SDL 2 (main library): Windowing and inputs management +* - SDL 2 or SLD 3 (main library): Windowing and inputs management * - gestures: Gestures system for touch-ready devices (or simulated from mouse inputs) * * @@ -48,6 +48,10 @@ * **********************************************************************************************/ + +#ifndef SDL_ENABLE_OLD_NAMES + #define SDL_ENABLE_OLD_NAMES // Just in case we're on SDL3, we need some in-between compatibily +#endif #include "SDL.h" // SDL base library (window/rendered, input, timing... functionality) #if defined(GRAPHICS_API_OPENGL_ES2) @@ -64,6 +68,13 @@ #define MAX_CLIPBOARD_BUFFER_LENGTH 1024 // Size of the clipboard buffer used on GetClipboardText() #endif +#if ((defined(SDL_MAJOR_VERSION) && SDL_MAJOR_VERSION == 3) && (defined(SDL_MINOR_VERSION) && SDL_MINOR_VERSION >= 1)) + #ifndef PLATFORM_DESKTOP_SDL3 + #define PLATFORM_DESKTOP_SDL3 + #endif +#endif + + //---------------------------------------------------------------------------------- // Types and Structures Definition //---------------------------------------------------------------------------------- @@ -227,6 +238,184 @@ static const int CursorsLUT[] = { //SDL_SYSTEM_CURSOR_WAITARROW, // No equivalent implemented on MouseCursor enum on raylib.h }; + +// SDL3 Migration Layer made to avoid `ifdefs` inside functions when we can. +#ifdef PLATFORM_DESKTOP_SDL3 + +// SDL3 Migration: +// SDL_WINDOW_FULLSCREEN_DESKTOP has been removed, +// and you can call SDL_GetWindowFullscreenMode() +// to see whether an exclusive fullscreen mode will be used +// or the borderless fullscreen desktop mode will be used +#define SDL_WINDOW_FULLSCREEN_DESKTOP SDL_WINDOW_FULLSCREEN + + +#define SDL_IGNORE false +#define SDL_DISABLE false +#define SDL_ENABLE true + +// SDL3 Migration: SDL_INIT_TIMER - no longer needed before calling SDL_AddTimer() +#define SDL_INIT_TIMER 0x0 // It's a flag, so no problem in setting it to zero if we use in a bitor (|) + +// SDL3 Migration: The SDL_WINDOW_SHOWN flag has been removed. Windows are shown by default and can be created hidden by using the SDL_WINDOW_HIDDEN flag. +#define SDL_WINDOW_SHOWN 0x0 // It's a flag, so no problem in setting it to zero if we use in a bitor (|) + +// +// SDL3 Migration: Renamed +// IMPORTANT: +// Might need to call SDL_CleanupEvent somewhere see :https://github.com/libsdl-org/SDL/issues/3540#issuecomment-1793449852 +// +#define SDL_DROPFILE SDL_EVENT_DROP_FILE + + +const char* SDL_GameControllerNameForIndex(int joystickIndex) +{ + // NOTE: SDL3 uses the IDs itself (SDL_JoystickID) instead of SDL2 joystick_index + const char* name = NULL; + int i, numJoysticks; + SDL_JoystickID *joysticks = SDL_GetJoysticks(&numJoysticks); + if (joysticks) { + if (joystickIndex < numJoysticks) { + SDL_JoystickID instance_id = joysticks[joystickIndex]; + name = SDL_GetGamepadNameForID(instance_id); + } + SDL_free(joysticks); + } + return name; +} + +int SDL_GetNumVideoDisplays(void) +{ + int monitorCount = 0; + SDL_DisplayID *displays = SDL_GetDisplays(&monitorCount); + // Safe because If `mem` is NULL, SDL_free does nothing. + SDL_free(displays); + + return monitorCount; +} + +Uint8 SDL_EventState(Uint32 type, int state) { + switch (state) + { + case SDL_DISABLE: + SDL_SetEventEnabled(type, false); + break; + case SDL_ENABLE: + SDL_SetEventEnabled(type, true); + break; + default: + TRACELOG(LOG_WARNING, "Event sate: unknow type"); + break; + } +} + +void SDL_GetCurrentDisplayMode_Adapter(SDL_DisplayID displayID, SDL_DisplayMode* mode) +{ + const SDL_DisplayMode* currMode = SDL_GetCurrentDisplayMode(displayID); + if (currMode == NULL) + { + TRACELOG(LOG_WARNING, "No current display mode"); + } + else + { + *mode = *currMode; + } +} + +// SDL3 Migration: Renamed +#define SDL_GetCurrentDisplayMode SDL_GetCurrentDisplayMode_Adapter + + +SDL_Surface *SDL_CreateRGBSurface(Uint32 flags, int width, int height, int depth, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) +{ + return SDL_CreateSurface(width, height, SDL_GetPixelFormatForMasks(depth, Rmask, Gmask, Bmask, Amask)); +} + +// SDL3 Migration: +// SDL_GetDisplayDPI() - +// not reliable across platforms, approximately replaced by multiplying +// SDL_GetWindowDisplayScale() times 160 on iPhone and Android, and 96 on other platforms. +int SDL_GetDisplayDPI(int displayIndex, float * ddpi, float * hdpi, float * vdpi) { + SDL_GetWindowDisplayScale(platform.window) * 96; +} + +SDL_Surface *SDL_CreateRGBSurfaceWithFormat(Uint32 flags, int width, int height, int depth, Uint32 format) +{ + return SDL_CreateSurface(width, height, format); +} + +SDL_Surface *SDL_CreateRGBSurfaceFrom(void *pixels, int width, int height, int depth, int pitch, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) +{ + return SDL_CreateSurfaceFrom(width, height, SDL_GetPixelFormatForMasks(depth, Rmask, Gmask, Bmask, Amask), pixels, pitch); +} + +SDL_Surface *SDL_CreateRGBSurfaceWithFormatFrom(void *pixels, int width, int height, int depth, int pitch, Uint32 format) +{ + return SDL_CreateSurfaceFrom(width, height, format, pixels, pitch); +} + +int SDL_NumJoysticks(void) +{ + int i, numJoysticks; + SDL_JoystickID *joysticks = SDL_GetJoysticks(&numJoysticks); + SDL_free(joysticks); + return numJoysticks; +} + + +// SDL_SetRelativeMouseMode +// returns 0 on success or a negative error code on failure +// If relative mode is not supported, this returns -1. +int SDL_SetRelativeMouseMode_Adapter(SDL_bool enabled) +{ + + // + // SDL_SetWindowRelativeMouseMode(SDL_Window *window, bool enabled) + // \returns true on success or false on failure; call SDL_GetError() for more + // + if (SDL_SetWindowRelativeMouseMode(platform.window, enabled)) + { + return 0; // success + } + else + { + return -1; // failure + } +} + +#define SDL_SetRelativeMouseMode SDL_SetRelativeMouseMode_Adapter + +bool SDL_GetRelativeMouseMode_Adapter(void) +{ + return SDL_GetWindowRelativeMouseMode(platform.window); +} + +#define SDL_GetRelativeMouseMode SDL_GetRelativeMouseMode_Adapter + + +int SDL_GetNumTouchFingers(SDL_TouchID touchID) +{ + // SDL_Finger **SDL_GetTouchFingers(SDL_TouchID touchID, int *count) + int count = 0; + SDL_Finger **fingers = SDL_GetTouchFingers(touchID, &count); + SDL_free(fingers); + return count; +} + +#else // We're on SDL2 + +// Since SDL2 doesn't have this function we leave a stub +// SDL_GetClipboardData function is available since SDL 3.1.3. (e.g. SDL3) +void* SDL_GetClipboardData(const char *mime_type, size_t *size) { + TRACELOG(LOG_WARNING, "Getting clipboard data that is not text is only available in SDL3"); + // We could possibly implement it ourselves in this case for some easier platforms + return NULL; +} + +#endif // PLATFORM_DESKTOP_SDL3 + + + //---------------------------------------------------------------------------------- // Module Internal Functions Declaration //---------------------------------------------------------------------------------- @@ -606,7 +795,11 @@ void SetWindowMonitor(int monitor) const int screenWidth = CORE.Window.screen.width; const int screenHeight = CORE.Window.screen.height; SDL_Rect usableBounds; + #ifdef PLATFORM_DESKTOP_SDL3 // Different style for success checking + if (SDL_GetDisplayUsableBounds(monitor, &usableBounds)) + #else if (SDL_GetDisplayUsableBounds(monitor, &usableBounds) == 0) + #endif { if (wasFullscreen == 1) ToggleFullscreen(); // Leave fullscreen. @@ -716,7 +909,11 @@ Vector2 GetMonitorPosition(int monitor) if ((monitor >= 0) && (monitor < monitorCount)) { SDL_Rect displayBounds; + #ifdef PLATFORM_DESKTOP_SDL3 + if (SDL_GetDisplayUsableBounds(monitor, &displayBounds)) + #else if (SDL_GetDisplayUsableBounds(monitor, &displayBounds) == 0) + #endif { return (Vector2){ (float)displayBounds.x, (float)displayBounds.y }; } @@ -844,10 +1041,16 @@ Vector2 GetWindowScaleDPI(void) { Vector2 scale = { 1.0f, 1.0f }; +#ifndef PLATFORM_DESKTOP_SDL3 // NOTE: SDL_GetWindowDisplayScale was only added on SDL3 // see https://wiki.libsdl.org/SDL3/SDL_GetWindowDisplayScale // TODO: Implement the window scale factor calculation manually. TRACELOG(LOG_WARNING, "GetWindowScaleDPI() not implemented on target platform"); +#else + scale.x = SDL_GetWindowDisplayScale(platform.window); + scale.y = scale.x; + TRACELOG(LOG_INFO, "WindowScaleDPI is %f", scale.x); +#endif return scale; } @@ -877,23 +1080,25 @@ const char *GetClipboardText(void) return buffer; } + #if defined(SUPPORT_CLIPBOARD_IMAGE) // Get clipboard image Image GetClipboardImage(void) { Image image = {0}; -// SDL_GetClipboardData function is available since SDL 3.1.3. (e.g. SDL3) -#if (defined(SDL_MAJOR_VERSION) && SDL_MAJOR_VERSION == 3 && defined(SDL_MAJOR_MINOR) && SDL_MAJOR_VERSION >= 1) - unsigned int dataSize = 0; + size_t dataSize = 0; + // NOTE: This pointer should be free with SDL_free() at some point. + // TODO: In case of failure let's try to cycle in to other mime types (formats) void* fileData = SDL_GetClipboardData("image/bmp", &dataSize); // returns NULL on failure; - if(fileData == NULL) + if (fileData == NULL) { - TRACELOG(LOG_WARNING, "Clipboard image: %s", SDL_GetError()); + TRACELOG(LOG_WARNING, "Clipboard image: Couldn't get clipboard data. %s", SDL_GetError()); + } + else + { + image = LoadImageFromMemory(".bmp", fileData, dataSize); } - - image = LoadImageFromMemory(".bmp", fileData, dataSize); -#endif return image; } #endif @@ -902,16 +1107,22 @@ Image GetClipboardImage(void) // Show mouse cursor void ShowCursor(void) { +#ifdef PLATFORM_DESKTOP_SDL3 + SDL_ShowCursor(); +#else SDL_ShowCursor(SDL_ENABLE); - +#endif CORE.Input.Mouse.cursorHidden = false; } // Hides mouse cursor void HideCursor(void) { +#ifdef PLATFORM_DESKTOP_SDL3 + SDL_HideCursor(); +#else SDL_ShowCursor(SDL_DISABLE); - +#endif CORE.Input.Mouse.cursorHidden = true; } @@ -919,7 +1130,13 @@ void HideCursor(void) void EnableCursor(void) { SDL_SetRelativeMouseMode(SDL_FALSE); + +#ifdef PLATFORM_DESKTOP_SDL3 + // SDL_ShowCursor() has been split into three functions: SDL_ShowCursor(), SDL_HideCursor(), and SDL_CursorVisible() + SDL_ShowCursor(); +#else SDL_ShowCursor(SDL_ENABLE); +#endif platform.cursorRelative = false; CORE.Input.Mouse.cursorHidden = false; @@ -1015,6 +1232,22 @@ const char *GetKeyName(int key) static void UpdateTouchPointsSDL(SDL_TouchFingerEvent event) { +#ifdef PLATFORM_DESKTOP_SDL3 // SDL3 + int count = 0; + SDL_Finger **fingers = SDL_GetTouchFingers(event.touchID, &count); + CORE.Input.Touch.pointCount = count; + + for (int i = 0; i < CORE.Input.Touch.pointCount; i++) + { + SDL_Finger *finger = fingers[i]; + CORE.Input.Touch.pointId[i] = finger->id; + CORE.Input.Touch.position[i].x = finger->x*CORE.Window.screen.width; + CORE.Input.Touch.position[i].y = finger->y*CORE.Window.screen.height; + CORE.Input.Touch.currentTouchState[i] = 1; + } + SDL_free(fingers); +#else // SDL2 + CORE.Input.Touch.pointCount = SDL_GetNumTouchFingers(event.touchId); for (int i = 0; i < CORE.Input.Touch.pointCount; i++) @@ -1025,6 +1258,7 @@ static void UpdateTouchPointsSDL(SDL_TouchFingerEvent event) CORE.Input.Touch.position[i].y = finger->y*CORE.Window.screen.height; CORE.Input.Touch.currentTouchState[i] = 1; } +#endif for (int i = CORE.Input.Touch.pointCount; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.currentTouchState[i] = 0; } @@ -1116,16 +1350,26 @@ void PollInputEvents(void) CORE.Window.dropFilepaths = (char **)RL_CALLOC(1024, sizeof(char *)); CORE.Window.dropFilepaths[CORE.Window.dropFileCount] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char)); + #ifdef PLATFORM_DESKTOP_SDL3 + // const char *data; /**< The text for SDL_EVENT_DROP_TEXT and the file name for SDL_EVENT_DROP_FILE, NULL for other events */ + // Event memory is now managed by SDL, so you should not free the data in SDL_EVENT_DROP_FILE, and if you want to hold onto the text in SDL_EVENT_TEXT_EDITING and SDL_EVENT_TEXT_INPUT events, you should make a copy of it. SDL_TEXTINPUTEVENT_TEXT_SIZE is no longer necessary and has been removed. + strcpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event.drop.data); + #else strcpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event.drop.file); SDL_free(event.drop.file); + #endif CORE.Window.dropFileCount++; } else if (CORE.Window.dropFileCount < 1024) { CORE.Window.dropFilepaths[CORE.Window.dropFileCount] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char)); + #ifdef PLATFORM_DESKTOP_SDL3 + strcpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event.drop.data); + #else strcpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event.drop.file); SDL_free(event.drop.file); + #endif CORE.Window.dropFileCount++; } @@ -1134,10 +1378,18 @@ void PollInputEvents(void) } break; // Window events are also polled (Minimized, maximized, close...) + + #ifndef PLATFORM_DESKTOP_SDL3 + // SDL3 states: + // The SDL_WINDOWEVENT_* events have been moved to top level events, + // and SDL_WINDOWEVENT has been removed. + // In general, handling this change just means checking for the individual events instead of first checking for SDL_WINDOWEVENT + // and then checking for window events. You can compare the event >= SDL_EVENT_WINDOW_FIRST and <= SDL_EVENT_WINDOW_LAST if you need to see whether it's a window event. case SDL_WINDOWEVENT: { switch (event.window.event) { + #endif case SDL_WINDOWEVENT_RESIZED: case SDL_WINDOWEVENT_SIZE_CHANGED: { @@ -1165,14 +1417,23 @@ void PollInputEvents(void) case SDL_WINDOWEVENT_FOCUS_GAINED: case SDL_WINDOWEVENT_MAXIMIZED: case SDL_WINDOWEVENT_RESTORED: + #ifdef PLATFORM_DESKTOP_SDL3 + break; + #else default: break; } } break; + #endif // Keyboard events case SDL_KEYDOWN: { + #ifdef PLATFORM_DESKTOP_SDL3 + // SDL3 Migration: The following structures have been removed: * SDL_Keysym + KeyboardKey key = ConvertScancodeToKey(event.key.scancode); + #else KeyboardKey key = ConvertScancodeToKey(event.key.keysym.scancode); + #endif if (key != KEY_NULL) { @@ -1197,7 +1458,12 @@ void PollInputEvents(void) case SDL_KEYUP: { + + #ifdef PLATFORM_DESKTOP_SDL3 + KeyboardKey key = ConvertScancodeToKey(event.key.scancode); + #else KeyboardKey key = ConvertScancodeToKey(event.key.keysym.scancode); + #endif if (key != KEY_NULL) CORE.Input.Keyboard.currentKeyState[key] = 0; } break; @@ -1549,7 +1815,11 @@ int InitPlatform(void) } // Init window +#ifdef PLATFORM_DESKTOP_SDL3 + platform.window = SDL_CreateWindow(CORE.Window.title, CORE.Window.screen.width, CORE.Window.screen.height, flags); +#else platform.window = SDL_CreateWindow(CORE.Window.title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, CORE.Window.screen.width, CORE.Window.screen.height, flags); +#endif // Init OpenGL context platform.glContext = SDL_GL_CreateContext(platform.window); @@ -1633,7 +1903,12 @@ int InitPlatform(void) CORE.Storage.basePath = SDL_GetBasePath(); // Alternative: GetWorkingDirectory(); //---------------------------------------------------------------------------- + +#ifdef PLATFORM_DESKTOP_SDL3 + TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (SDL3): Initialized successfully"); +#else TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (SDL): Initialized successfully"); +#endif return 0; } diff --git a/src/raylib.h b/src/raylib.h index 89d1fdfd..723f787d 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1012,6 +1012,7 @@ RLAPI const char *GetMonitorName(int monitor); // Get the hum RLAPI void SetClipboardText(const char *text); // Set clipboard text content RLAPI const char *GetClipboardText(void); // Get clipboard text content RLAPI Image GetClipboardImage(void); // Get clipboard image +void SetClipboardImage(Image *image) RLAPI void EnableEventWaiting(void); // Enable waiting for events on EndDrawing(), no automatic event polling RLAPI void DisableEventWaiting(void); // Disable waiting for events on EndDrawing(), automatic events polling diff --git a/src/rcore.c b/src/rcore.c index 13670969..119e4838 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -516,25 +516,15 @@ const char *TextFormat(const char *text, ...); // Formatting of tex #if !defined(SUPPORT_FILEFORMAT_BMP) || !defined(STBI_REQUIRED) || !defined(SUPPORT_MODULE_RTEXTURES) #error "To enabled SUPPORT_CLIPBOARD_IMAGE, it also needs SUPPORT_FILEFORMAT_BMP, SUPPORT_MODULE_RTEXTURES and STBI_REQUIRED to be defined" #endif -#endif - +#endif // SUPPORT_CLIPBOARD_IMAGE // Include platform-specific submodules #if defined(PLATFORM_DESKTOP_GLFW) #include "platforms/rcore_desktop_glfw.c" - #if defined(SUPPORT_CLIPBOARD_IMAGE) && defined(_WIN32) - #include "platforms/rcore_clipboard_win32.c" - #endif #elif defined(PLATFORM_DESKTOP_SDL) #include "platforms/rcore_desktop_sdl.c" #elif defined(PLATFORM_DESKTOP_RGFW) #include "platforms/rcore_desktop_rgfw.c" - #if defined(SUPPORT_CLIPBOARD_IMAGE) && defined(_WIN32) - #define WINUSER_ALREADY_INCLUDED - #define WINBASE_ALREADY_INCLUDED - #define WINGDI_ALREADY_INCLUDED - #include "platforms/rcore_clipboard_win32.c" - #endif #elif defined(PLATFORM_WEB) #include "platforms/rcore_web.c" #elif defined(PLATFORM_DRM)