Browse Source

[rcore] PLATFORM_SDL: create a compatility layer for SDL3

pull/4459/head
evertonse 1 month ago
parent
commit
b5bad8e096
4 changed files with 297 additions and 38 deletions
  1. +9
    -16
      src/external/win32_clipboard.h
  2. +286
    -11
      src/platforms/rcore_desktop_sdl.c
  3. +1
    -0
      src/raylib.h
  4. +1
    -11
      src/rcore.c

src/platforms/rcore_clipboard_win32.c → src/external/win32_clipboard.h View File

@ -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 <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
@ -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

+ 286
- 11
src/platforms/rcore_desktop_sdl.c View File

@ -23,7 +23,7 @@
* Custom flag for rcore on target platform -not used-
*
* DEPENDENCIES:
* - SDL 2 (main library): Windowing and inputs management
* - SDL 2 n">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)
kt">unsigned int dataSize = 0;
size_t dataSize = 0;
// NOTE: This pointer should be free with SDL_free() at some point.
o">// 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;
}

+ 1
- 0
src/raylib.h View File

@ -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

+ 1
- 11
src/rcore.c View File

@ -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)

Loading…
Cancel
Save