From 78806705979b0e9c4e0717888371fdcd6aaeb15b Mon Sep 17 00:00:00 2001 From: evertonse Date: Fri, 1 Nov 2024 16:20:44 -0300 Subject: [PATCH 01/17] [rcore] add 'GetClipboardImage' for windows --- examples/Makefile | 3 +- examples/core/core_clipboard_image.c | 34 ++ src/config.h | 21 ++ src/platforms/rcore_clipboard_win32.c | 443 ++++++++++++++++++++++++++ src/platforms/rcore_desktop_sdl.c | 22 ++ src/raylib.h | 1 + src/rcore.c | 16 + 7 files changed, 539 insertions(+), 1 deletion(-) create mode 100644 examples/core/core_clipboard_image.c create mode 100644 src/platforms/rcore_clipboard_win32.c diff --git a/examples/Makefile b/examples/Makefile index 304599cf8183..02d83931a615 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -516,7 +516,8 @@ CORE = \ core/core_window_flags \ core/core_window_letterbox \ core/core_window_should_close \ - core/core_world_screen + core/core_world_screen \ + core/core_clipboard_image SHAPES = \ shapes/shapes_basic_shapes \ diff --git a/examples/core/core_clipboard_image.c b/examples/core/core_clipboard_image.c new file mode 100644 index 000000000000..607d31bd57bb --- /dev/null +++ b/examples/core/core_clipboard_image.c @@ -0,0 +1,34 @@ +#include "raylib.h" +#include +#include + +static Image img = {0}; +int main(int argc, char *argv[]) { + + InitWindow(800, 450, "[core] raylib clipboard image"); + SetTraceLogLevel(LOG_TRACE); + SetTargetFPS(60); + + Texture tex = {0}; + while(!WindowShouldClose()) { + if (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_V)) { + #ifdef _WIN32 + img = GetClipboardImage(); + tex = LoadTextureFromImage(img); + if(!IsTextureValid(tex)) { + exit(98); + } else { + ExportImage(img, "Debug.bmp"); + } + #endif + } + + BeginDrawing(); + ClearBackground(RAYWHITE); + if (IsTextureValid(tex)) { + DrawTexture(tex, 0, 0, WHITE); + } + DrawText("Print Screen and Crtl+V", 10, 10, 21, BLACK); + EndDrawing(); + } +} diff --git a/src/config.h b/src/config.h index f37a9de3e948..703b0f23e063 100644 --- a/src/config.h +++ b/src/config.h @@ -71,6 +71,7 @@ // Enabling this flag allows manual control of the frame processes, use at your own risk //#define SUPPORT_CUSTOM_FRAME_CONTROL 1 + // rcore: Configuration values //------------------------------------------------------------------------------------ #define MAX_FILEPATH_CAPACITY 8192 // Maximum file paths capacity @@ -272,4 +273,24 @@ //------------------------------------------------------------------------------------ #define MAX_TRACELOG_MSG_LENGTH 256 // Max length of one trace-log message + +// Enable partial support for clipboard image, only working on SDL3 or +// being on both Windows OS + GLFW or Windows OS + RGFW +#define SUPPORT_CLIPBOARD_IMAGE 1 + +#if defined(SUPPORT_CLIPBOARD_IMAGE) + #ifndef STBI_REQUIRED + #define STBI_REQUIRED + #endif + + #ifndef SUPPORT_FILEFORMAT_BMP + #define SUPPORT_FILEFORMAT_BMP 1 + #endif + + #ifndef SUPPORT_MODULE_RTEXTURES + #define SUPPORT_MODULE_RTEXTURES 1 + #endif + +#endif + #endif // CONFIG_H diff --git a/src/platforms/rcore_clipboard_win32.c b/src/platforms/rcore_clipboard_win32.c new file mode 100644 index 000000000000..e7cba10ed1f8 --- /dev/null +++ b/src/platforms/rcore_clipboard_win32.c @@ -0,0 +1,443 @@ +#if !defined(_WIN32) +# error "This module is only made for Windows OS" +#else +// Needs both `Image` and `LoadImageFromMemory` from `rtexture` >:C + +#include +#include +#include +#include + +#define DrawText DrawText_win32 +#define Rectangle rectangle_win32 +#define CloseWindow CloseWindow_win32 +#define ShowCursor __imp_ShowCursor + +// To avoid conflicting windows.h symbols with raylib, some flags are defined +// WARNING: Those flags avoid inclusion of some Win32 headers that could be required +// by user at some point and won't be included... +//------------------------------------------------------------------------------------- + +#define NOGDICAPMASKS // CC_*, LC_*, PC_*, CP_*, TC_*, RC_ +#define NOVIRTUALKEYCODES // VK_* +#define NOWINMESSAGES // WM_*, EM_*, LB_*, CB_* +#define NOWINSTYLES // WS_*, CS_*, ES_*, LBS_*, SBS_*, CBS_* +#define NOSYSMETRICS // SM_* +#define NOMENUS // MF_* +#define NOICONS // IDI_* +#define NOKEYSTATES // MK_* +#define NOSYSCOMMANDS // SC_* +#define NORASTEROPS // Binary and Tertiary raster ops +#define NOSHOWWINDOW // SW_* +#define OEMRESOURCE // OEM Resource values +#define NOATOM // Atom Manager routines +#define NOCLIPBOARD // Clipboard routines +#define NOCOLOR // Screen colors +#define NOCTLMGR // Control and Dialog routines +#define NODRAWTEXT // DrawText() and DT_* +// #define NOGDI // All GDI defines and routines +#define NOKERNEL // All KERNEL defines and routines +#define NOUSER // All USER defines and routines +#define NONLS // All NLS defines and routines +#define NOMB // MB_* and MessageBox() +#define NOMEMMGR // GMEM_*, LMEM_*, GHND, LHND, associated routines +#define NOMETAFILE // typedef METAFILEPICT +#define NOMINMAX // Macros min(a,b) and max(a,b) +#define NOMSG // typedef MSG and associated routines +#define NOOPENFILE // OpenFile(), OemToAnsi, AnsiToOem, and OF_* +#define NOSCROLL // SB_* and scrolling routines +#define NOSERVICE // All Service Controller routines, SERVICE_ equates, etc. +#define NOSOUND // Sound driver routines +#define NOTEXTMETRIC // typedef TEXTMETRIC and associated routines +#define NOWH // SetWindowsHook and WH_* +#define NOWINOFFSETS // GWL_*, GCL_*, associated routines +#define NOCOMM // COMM driver routines +#define NOKANJI // Kanji support stuff. +#define NOHELP // Help engine interface. +#define NOPROFILER // Profiler interface. +#define NODEFERWINDOWPOS // DeferWindowPos routines +#define NOMCX // Modem Configuration Extensions + +// Type required before windows.h inclusion +typedef struct tagMSG *LPMSG; + +#define WIN32_LEAN_AND_MEAN +// #include +// #include +// #include +#include +// #include + +#ifndef WINAPI +#if defined(_ARM_) +#define WINAPI +#else +#define WINAPI __stdcall +#endif +#endif + +#ifndef WINAPI +#if defined(_ARM_) +#define WINAPI +#else +#define WINAPI __stdcall +#endif +#endif + +#ifndef WINBASEAPI +#ifndef _KERNEL32_ +#define WINBASEAPI DECLSPEC_IMPORT +#else +#define WINBASEAPI +#endif +#endif + +#ifndef WINUSERAPI +#ifndef _USER32_ +#define WINUSERAPI __declspec (dllimport) +#else +#define WINUSERAPI +#endif +#endif + +typedef int WINBOOL; + + + +// typedef HANDLE HGLOBAL; + +#ifndef HWND +#define HWND void* +#endif + + +#if !defined(_WINUSER_) || !defined(WINUSER_ALREADY_INCLUDED) +WINUSERAPI WINBOOL WINAPI OpenClipboard(HWND hWndNewOwner); +WINUSERAPI WINBOOL WINAPI CloseClipboard(VOID); +WINUSERAPI DWORD WINAPI GetClipboardSequenceNumber(VOID); +WINUSERAPI HWND WINAPI GetClipboardOwner(VOID); +WINUSERAPI HWND WINAPI SetClipboardViewer(HWND hWndNewViewer); +WINUSERAPI HWND WINAPI GetClipboardViewer(VOID); +WINUSERAPI WINBOOL WINAPI ChangeClipboardChain(HWND hWndRemove, HWND hWndNewNext); +WINUSERAPI HANDLE WINAPI SetClipboardData(UINT uFormat, HANDLE hMem); +WINUSERAPI HANDLE WINAPI GetClipboardData(UINT uFormat); +WINUSERAPI UINT WINAPI RegisterClipboardFormatA(LPCSTR lpszFormat); +WINUSERAPI UINT WINAPI RegisterClipboardFormatW(LPCWSTR lpszFormat); +WINUSERAPI int WINAPI CountClipboardFormats(VOID); +WINUSERAPI UINT WINAPI EnumClipboardFormats(UINT format); +WINUSERAPI int WINAPI GetClipboardFormatNameA(UINT format, LPSTR lpszFormatName, int cchMaxCount); +WINUSERAPI int WINAPI GetClipboardFormatNameW(UINT format, LPWSTR lpszFormatName, int cchMaxCount); +WINUSERAPI WINBOOL WINAPI EmptyClipboard(VOID); +WINUSERAPI WINBOOL WINAPI IsClipboardFormatAvailable(UINT format); +WINUSERAPI int WINAPI GetPriorityClipboardFormat(UINT *paFormatPriorityList, int cFormats); +WINUSERAPI HWND WINAPI GetOpenClipboardWindow(VOID); +#endif + +#ifndef HGLOBAL +#define HGLOBAL void* +#endif + +#if !defined(_WINBASE_) || !defined(WINBASE_ALREADY_INCLUDED) +WINBASEAPI SIZE_T WINAPI GlobalSize (HGLOBAL hMem); +WINBASEAPI LPVOID WINAPI GlobalLock (HGLOBAL hMem); +WINBASEAPI WINBOOL WINAPI GlobalUnlock (HGLOBAL hMem); +#endif + + +#if !defined(_WINGDI_) || !defined(WINGDI_ALREADY_INCLUDED) +#ifndef BITMAPINFOHEADER_ALREADY_DEFINED +#define BITMAPINFOHEADER_ALREADY_DEFINED +// Does this header need to be packed ? by the windowps header it doesnt seem to be +#pragma pack(push, 1) +typedef struct tagBITMAPINFOHEADER { + DWORD biSize; + LONG biWidth; + LONG biHeight; + WORD biPlanes; + WORD biBitCount; + DWORD biCompression; + DWORD biSizeImage; + LONG biXPelsPerMeter; + LONG biYPelsPerMeter; + DWORD biClrUsed; + DWORD biClrImportant; +} BITMAPINFOHEADER,*LPBITMAPINFOHEADER,*PBITMAPINFOHEADER; +#pragma pack(pop) +#endif + +#ifndef BITMAPFILEHEADER_ALREADY_DEFINED +#define BITMAPFILEHEADER_ALREADY_DEFINED +#pragma pack(push, 1) +typedef struct tagBITMAPFILEHEADER { + WORD bfType; + DWORD bfSize; + WORD bfReserved1; + WORD bfReserved2; + DWORD bfOffBits; +} BITMAPFILEHEADER,*LPBITMAPFILEHEADER,*PBITMAPFILEHEADER; +#pragma pack(pop) +#endif + +#ifndef RGBQUAD_ALREADY_DEFINED +#define RGBQUAD_ALREADY_DEFINED +typedef struct tagRGBQUAD { + BYTE rgbBlue; + BYTE rgbGreen; + BYTE rgbRed; + BYTE rgbReserved; +} RGBQUAD, *LPRGBQUAD; +#endif + + +// https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-wmf/4e588f70-bd92-4a6f-b77f-35d0feaf7a57 +#define BI_RGB 0x0000 +#define BI_RLE8 0x0001 +#define BI_RLE4 0x0002 +#define BI_BITFIELDS 0x0003 +#define BI_JPEG 0x0004 +#define BI_PNG 0x0005 +#define BI_CMYK 0x000B +#define BI_CMYKRLE8 0x000C +#define BI_CMYKRLE4 0x000D + +#endif + +// https://learn.microsoft.com/en-us/windows/win32/dataxchg/standard-clipboard-formats +#define CF_DIB 8 + +// https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setsystemcursor +// #define OCR_NORMAL 32512 // Normal select +// #define OCR_IBEAM 32513 // Text select +// #define OCR_WAIT 32514 // Busy +// #define OCR_CROSS 32515 // Precision select +// #define OCR_UP 32516 // Alternate select +// #define OCR_SIZENWSE 32642 // Diagonal resize 1 +// #define OCR_SIZENESW 32643 // Diagonal resize 2 +// #define OCR_SIZEWE 32644 // Horizontal resize +// #define OCR_SIZENS 32645 // Vertical resize +// #define OCR_SIZEALL 32646 // Move +// #define OCR_NO 32648 // Unavailable +// #define OCR_HAND 32649 // Link select +// #define OCR_APPSTARTING 32650 // + + +//---------------------------------------------------------------------------------- +// Module Internal Functions Declaration +//---------------------------------------------------------------------------------- + + +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) +{ + HWND win = NULL; // Get from somewhere but is doesnt seem to matter + const char* msgString = ""; + int severity = LOG_INFO; + BYTE* bmpData = NULL; + if (!OpenClipboardRetrying(win)) { + severity = LOG_ERROR; + msgString = "Couldn't open clipboard"; + goto end; + } + + HGLOBAL clipHandle = (HGLOBAL)GetClipboardData(CF_DIB); + if (!clipHandle) { + severity = LOG_ERROR; + msgString = "Clipboard data is not an Image"; + goto close; + } + + BITMAPINFOHEADER *bmpInfoHeader = (BITMAPINFOHEADER *)GlobalLock(clipHandle); + if (!bmpInfoHeader) { + // Mapping from HGLOBAL to our local *address space* failed + severity = LOG_ERROR; + msgString = "Clipboard data failed to be locked"; + goto unlock; + } + + *width = bmpInfoHeader->biWidth; + *height = bmpInfoHeader->biHeight; + + SIZE_T clipDataSize = GlobalSize(clipHandle); + if (clipDataSize < sizeof(BITMAPINFOHEADER)) { + // Format CF_DIB needs space for BITMAPINFOHEADER struct. + msgString = "Clipboard has Malformed data"; + severity = LOG_ERROR; + goto unlock; + } + + // Denotes where the pixel data starts from the bmpInfoHeader pointer + int pixelOffset = GetPixelDataOffset(*bmpInfoHeader); + + //--------------------------------------------------------------------------------// + // + // The rest of the section is about create the bytes for a correct BMP file + // Then we copy the data and to a pointer + // + //--------------------------------------------------------------------------------// + + BITMAPFILEHEADER bmpFileHeader = {0}; + SIZE_T bmpFileSize = sizeof(bmpFileHeader) + clipDataSize; + *dataSize = bmpFileSize; + + bmpFileHeader.bfType = 0x4D42; //https://stackoverflow.com/questions/601430/multibyte-character-constants-and-bitmap-file-header-type-constants#601536 + + bmpFileHeader.bfSize = (DWORD)bmpFileSize; // Up to 4GB works fine + bmpFileHeader.bfOffBits = sizeof(bmpFileHeader) + pixelOffset; + + // + // Each process has a default heap provided by the system + // Memory objects allocated by GlobalAlloc and LocalAlloc are in private, + // committed pages with read/write access that cannot be accessed by other processes. + // + // This may be wrong since we might be allocating in a DLL and freeing from another module, the main application + // that may cause heap corruption. We could create a FreeImage function + // + bmpData = malloc(sizeof(bmpFileHeader) + clipDataSize); + // First we add the header for a bmp file + memcpy(bmpData, &bmpFileHeader, sizeof(bmpFileHeader)); + // Then we add the header for the bmp itself + the pixel data + memcpy(bmpData + sizeof(bmpFileHeader), bmpInfoHeader, clipDataSize); + msgString = "Clipboad image acquired successfully"; + + +unlock: + GlobalUnlock(clipHandle); +close: + CloseClipboard(); +end: + + TRACELOG(severity, msgString); + return bmpData; +} + +static BOOL OpenClipboardRetrying(HWND hWnd) +{ + static const int maxTries = 20; + static const int sleepTimeMS = 60; + for (int _ = 0; _ < maxTries; ++_) + { + // Might be being hold by another process + // Or yourself forgot to CloseClipboard + if (OpenClipboard(hWnd)) { + return true; + } + Sleep(sleepTimeMS); + } + return false; +} + +// Based off of researching microsoft docs and reponses from this question https://stackoverflow.com/questions/30552255/how-to-read-a-bitmap-from-the-windows-clipboard#30552856 +// https://learn.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-bitmapinfoheader +// Get the byte offset where does the pixels data start (from a packed DIB) +static int GetPixelDataOffset(BITMAPINFOHEADER bih) +{ + int offset = 0; + const unsigned int rgbaSize = sizeof(RGBQUAD); + + // biSize Specifies the number of bytes required by the structure + // We expect to always be 40 because it should be packed + if (40 == bih.biSize && 40 == sizeof(BITMAPINFOHEADER)) + { + // + // biBitCount Specifies the number of bits per pixel. + // Might exist some bit masks *after* the header and *before* the pixel offset + // we're looking, but only if we have more than + // 8 bits per pixel, so we need to ajust for that + // + if (bih.biBitCount > 8) + { + // if bih.biCompression is RBG we should NOT offset more + + if (bih.biCompression == BI_BITFIELDS) + { + offset += 3 * rgbaSize; + } else if (bih.biCompression == 6 /* BI_ALPHABITFIELDS */) + { + // Not widely supported, but valid. + offset += 4 * rgbaSize; + } + } + } + + // + // biClrUsed Specifies the number of color indices in the color table that are actually used by the bitmap. + // If this value is zero, the bitmap uses the maximum number of colors + // corresponding to the value of the biBitCount member for the compression mode specified by biCompression. + // If biClrUsed is nonzero and the biBitCount member is less than 16 + // the biClrUsed member specifies the actual number of colors + // + if (bih.biClrUsed > 0) { + offset += bih.biClrUsed * rgbaSize; + } else { + if (bih.biBitCount < 16) + { + offset = offset + (rgbaSize << bih.biBitCount); + } + } + + return bih.biSize + offset; +} + +#undef NOGDICAPMASKS // CC_*, LC_*, PC_*, CP_*, TC_*, RC_ +#undef NOVIRTUALKEYCODES // VK_* +#undef NOWINMESSAGES // WM_*, EM_*, LB_*, CB_* +#undef NOWINSTYLES // WS_*, CS_*, ES_*, LBS_*, SBS_*, CBS_* +#undef NOSYSMETRICS // SM_* +#undef NOMENUS // MF_* +#undef NOICONS // IDI_* +#undef NOKEYSTATES // MK_* +#undef NOSYSCOMMANDS // SC_* +#undef NORASTEROPS // Binary and Tertiary raster ops +#undef NOSHOWWINDOW // SW_* +#undef OEMRESOURCE // OEM Resource values +#undef NOATOM // Atom Manager routines +#undef NOCLIPBOARD // Clipboard routines +#undef NOCOLOR // Screen colors +#undef NOCTLMGR // Control and Dialog routines +#undef NODRAWTEXT // DrawText() and DT_* +#undef NOGDI // All GDI defines and routines +#undef NOKERNEL // All KERNEL defines and routines +#undef NOUSER // All USER defines and routines +#undef NONLS // All NLS defines and routines +#undef NOMB // MB_* and MessageBox() +#undef NOMEMMGR // GMEM_*, LMEM_*, GHND, LHND, associated routines +#undef NOMETAFILE // typedef METAFILEPICT +#undef NOMINMAX // Macros min(a,b) and max(a,b) +#undef NOMSG // typedef MSG and associated routines +#undef NOOPENFILE // OpenFile(), OemToAnsi, AnsiToOem, and OF_* +#undef NOSCROLL // SB_* and scrolling routines +#undef NOSERVICE // All Service Controller routines, SERVICE_ equates, etc. +#undef NOSOUND // Sound driver routines +#undef NOTEXTMETRIC // typedef TEXTMETRIC and associated routines +#undef NOWH // SetWindowsHook and WH_* +#undef NOWINOFFSETS // GWL_*, GCL_*, associated routines +#undef NOCOMM // COMM driver routines +#undef NOKANJI // Kanji support stuff. +#undef NOHELP // Help engine interface. +#undef NOPROFILER // Profiler interface. +#undef NODEFERWINDOWPOS // DeferWindowPos routines +#undef NOMCX // Modem Configuration Extensions + +#undef DrawText +#undef ShowCursor +#undef CloseWindow +#undef Rectangle +#undef HWND +#endif +// EOF diff --git a/src/platforms/rcore_desktop_sdl.c b/src/platforms/rcore_desktop_sdl.c index 7cbe0354efc7..1a016e8ecc66 100644 --- a/src/platforms/rcore_desktop_sdl.c +++ b/src/platforms/rcore_desktop_sdl.c @@ -877,6 +877,28 @@ 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; + void* fileData = SDL_GetClipboardData("image/bmp", &dataSize); // returns NULL on failure; + if(fileData == NULL) + { + TRACELOG(LOG_WARNING, "Clipboard image: %s", SDL_GetError()); + } + + image = LoadImageFromMemory(".bmp", fileData, dataSize); +#endif + return image; +} +#endif + + // Show mouse cursor void ShowCursor(void) { diff --git a/src/raylib.h b/src/raylib.h index c9d9f6e54717..89d1fdfde02c 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1011,6 +1011,7 @@ RLAPI Vector2 GetWindowScaleDPI(void); // Get window RLAPI const char *GetMonitorName(int monitor); // Get the human-readable, UTF-8 encoded name of the specified monitor 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 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 75b9bf4514cb..13670969d4c6 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -512,13 +512,29 @@ const char *TextFormat(const char *text, ...); // Formatting of tex #define PLATFORM_DESKTOP_GLFW #endif +#if defined(SUPPORT_CLIPBOARD_IMAGE) + #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 + + // 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) From b53c116536dbce3994be2d485e499f5e38fa4bd6 Mon Sep 17 00:00:00 2001 From: evertonse Date: Fri, 1 Nov 2024 22:15:32 -0300 Subject: [PATCH 02/17] [rcore] GetClipboardImage removed some unneeded defines --- examples/core/core_clipboard_image.c | 2 +- src/platforms/rcore_clipboard_win32.c | 99 --------------------------- 2 files changed, 1 insertion(+), 100 deletions(-) diff --git a/examples/core/core_clipboard_image.c b/examples/core/core_clipboard_image.c index 607d31bd57bb..685d1a5fb684 100644 --- a/examples/core/core_clipboard_image.c +++ b/examples/core/core_clipboard_image.c @@ -26,7 +26,7 @@ int main(int argc, char *argv[]) { BeginDrawing(); ClearBackground(RAYWHITE); if (IsTextureValid(tex)) { - DrawTexture(tex, 0, 0, WHITE); + DrawTexture(tex, 0, 10 + 21, WHITE); } DrawText("Print Screen and Crtl+V", 10, 10, 21, BLACK); EndDrawing(); diff --git a/src/platforms/rcore_clipboard_win32.c b/src/platforms/rcore_clipboard_win32.c index e7cba10ed1f8..2eed8468e9da 100644 --- a/src/platforms/rcore_clipboard_win32.c +++ b/src/platforms/rcore_clipboard_win32.c @@ -8,59 +8,6 @@ #include #include -#define DrawText DrawText_win32 -#define Rectangle rectangle_win32 -#define CloseWindow CloseWindow_win32 -#define ShowCursor __imp_ShowCursor - -// To avoid conflicting windows.h symbols with raylib, some flags are defined -// WARNING: Those flags avoid inclusion of some Win32 headers that could be required -// by user at some point and won't be included... -//------------------------------------------------------------------------------------- - -#define NOGDICAPMASKS // CC_*, LC_*, PC_*, CP_*, TC_*, RC_ -#define NOVIRTUALKEYCODES // VK_* -#define NOWINMESSAGES // WM_*, EM_*, LB_*, CB_* -#define NOWINSTYLES // WS_*, CS_*, ES_*, LBS_*, SBS_*, CBS_* -#define NOSYSMETRICS // SM_* -#define NOMENUS // MF_* -#define NOICONS // IDI_* -#define NOKEYSTATES // MK_* -#define NOSYSCOMMANDS // SC_* -#define NORASTEROPS // Binary and Tertiary raster ops -#define NOSHOWWINDOW // SW_* -#define OEMRESOURCE // OEM Resource values -#define NOATOM // Atom Manager routines -#define NOCLIPBOARD // Clipboard routines -#define NOCOLOR // Screen colors -#define NOCTLMGR // Control and Dialog routines -#define NODRAWTEXT // DrawText() and DT_* -// #define NOGDI // All GDI defines and routines -#define NOKERNEL // All KERNEL defines and routines -#define NOUSER // All USER defines and routines -#define NONLS // All NLS defines and routines -#define NOMB // MB_* and MessageBox() -#define NOMEMMGR // GMEM_*, LMEM_*, GHND, LHND, associated routines -#define NOMETAFILE // typedef METAFILEPICT -#define NOMINMAX // Macros min(a,b) and max(a,b) -#define NOMSG // typedef MSG and associated routines -#define NOOPENFILE // OpenFile(), OemToAnsi, AnsiToOem, and OF_* -#define NOSCROLL // SB_* and scrolling routines -#define NOSERVICE // All Service Controller routines, SERVICE_ equates, etc. -#define NOSOUND // Sound driver routines -#define NOTEXTMETRIC // typedef TEXTMETRIC and associated routines -#define NOWH // SetWindowsHook and WH_* -#define NOWINOFFSETS // GWL_*, GCL_*, associated routines -#define NOCOMM // COMM driver routines -#define NOKANJI // Kanji support stuff. -#define NOHELP // Help engine interface. -#define NOPROFILER // Profiler interface. -#define NODEFERWINDOWPOS // DeferWindowPos routines -#define NOMCX // Modem Configuration Extensions - -// Type required before windows.h inclusion -typedef struct tagMSG *LPMSG; - #define WIN32_LEAN_AND_MEAN // #include // #include @@ -393,51 +340,5 @@ static int GetPixelDataOffset(BITMAPINFOHEADER bih) return bih.biSize + offset; } - -#undef NOGDICAPMASKS // CC_*, LC_*, PC_*, CP_*, TC_*, RC_ -#undef NOVIRTUALKEYCODES // VK_* -#undef NOWINMESSAGES // WM_*, EM_*, LB_*, CB_* -#undef NOWINSTYLES // WS_*, CS_*, ES_*, LBS_*, SBS_*, CBS_* -#undef NOSYSMETRICS // SM_* -#undef NOMENUS // MF_* -#undef NOICONS // IDI_* -#undef NOKEYSTATES // MK_* -#undef NOSYSCOMMANDS // SC_* -#undef NORASTEROPS // Binary and Tertiary raster ops -#undef NOSHOWWINDOW // SW_* -#undef OEMRESOURCE // OEM Resource values -#undef NOATOM // Atom Manager routines -#undef NOCLIPBOARD // Clipboard routines -#undef NOCOLOR // Screen colors -#undef NOCTLMGR // Control and Dialog routines -#undef NODRAWTEXT // DrawText() and DT_* -#undef NOGDI // All GDI defines and routines -#undef NOKERNEL // All KERNEL defines and routines -#undef NOUSER // All USER defines and routines -#undef NONLS // All NLS defines and routines -#undef NOMB // MB_* and MessageBox() -#undef NOMEMMGR // GMEM_*, LMEM_*, GHND, LHND, associated routines -#undef NOMETAFILE // typedef METAFILEPICT -#undef NOMINMAX // Macros min(a,b) and max(a,b) -#undef NOMSG // typedef MSG and associated routines -#undef NOOPENFILE // OpenFile(), OemToAnsi, AnsiToOem, and OF_* -#undef NOSCROLL // SB_* and scrolling routines -#undef NOSERVICE // All Service Controller routines, SERVICE_ equates, etc. -#undef NOSOUND // Sound driver routines -#undef NOTEXTMETRIC // typedef TEXTMETRIC and associated routines -#undef NOWH // SetWindowsHook and WH_* -#undef NOWINOFFSETS // GWL_*, GCL_*, associated routines -#undef NOCOMM // COMM driver routines -#undef NOKANJI // Kanji support stuff. -#undef NOHELP // Help engine interface. -#undef NOPROFILER // Profiler interface. -#undef NODEFERWINDOWPOS // DeferWindowPos routines -#undef NOMCX // Modem Configuration Extensions - -#undef DrawText -#undef ShowCursor -#undef CloseWindow -#undef Rectangle -#undef HWND #endif // EOF From b5bad8e096a2f952e0f66edef2b68c176e8c500e Mon Sep 17 00:00:00 2001 From: evertonse Date: Wed, 6 Nov 2024 16:50:29 -0300 Subject: [PATCH 03/17] [rcore] PLATFORM_SDL: create a compatility layer for SDL3 --- .../win32_clipboard.h} | 25 +- src/platforms/rcore_desktop_sdl.c | 297 +++++++++++++++++- src/raylib.h | 1 + src/rcore.c | 12 +- 4 files changed, 297 insertions(+), 38 deletions(-) rename src/{platforms/rcore_clipboard_win32.c => external/win32_clipboard.h} (94%) 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 2eed8468e9da..083e90a96e78 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 1a016e8ecc66..33e78b0effde 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 89d1fdfde02c..723f787d9f84 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 13670969d4c6..119e48382762 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) From ba5045963e249f635502e60019bf942e87d1a397 Mon Sep 17 00:00:00 2001 From: evertonse Date: Wed, 6 Nov 2024 16:52:04 -0300 Subject: [PATCH 04/17] external: add win32_clipboard.h header only lib --- src/external/win32_clipboard.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/external/win32_clipboard.h b/src/external/win32_clipboard.h index 083e90a96e78..ce986578a8bb 100644 --- a/src/external/win32_clipboard.h +++ b/src/external/win32_clipboard.h @@ -335,3 +335,4 @@ static int GetPixelDataOffset(BITMAPINFOHEADER bih) } #endif // WIN32_CLIPBOARD_IMPLEMENTATION // EOF + From 057f7dc98f20963fc6c1d0c30f6b5ba0359d0bd1 Mon Sep 17 00:00:00 2001 From: evertonse Date: Wed, 6 Nov 2024 17:02:16 -0300 Subject: [PATCH 05/17] [rcore] using win32_clipboard on platforms rlfw and rgfw --- examples/core/core_clipboard_image.c | 34 ------------------------- src/platforms/rcore_desktop_glfw.c | 32 ++++++++++++++++++++++++ src/platforms/rcore_desktop_rgfw.c | 37 ++++++++++++++++++++++++++++ src/rcore.c | 2 +- 4 files changed, 70 insertions(+), 35 deletions(-) delete mode 100644 examples/core/core_clipboard_image.c diff --git a/examples/core/core_clipboard_image.c b/examples/core/core_clipboard_image.c deleted file mode 100644 index 685d1a5fb684..000000000000 --- a/examples/core/core_clipboard_image.c +++ /dev/null @@ -1,34 +0,0 @@ -#include "raylib.h" -#include -#include - -static Image img = {0}; -int main(int argc, char *argv[]) { - - InitWindow(800, 450, "[core] raylib clipboard image"); - SetTraceLogLevel(LOG_TRACE); - SetTargetFPS(60); - - Texture tex = {0}; - while(!WindowShouldClose()) { - if (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_V)) { - #ifdef _WIN32 - img = GetClipboardImage(); - tex = LoadTextureFromImage(img); - if(!IsTextureValid(tex)) { - exit(98); - } else { - ExportImage(img, "Debug.bmp"); - } - #endif - } - - BeginDrawing(); - ClearBackground(RAYWHITE); - if (IsTextureValid(tex)) { - DrawTexture(tex, 0, 10 + 21, WHITE); - } - DrawText("Print Screen and Crtl+V", 10, 10, 21, BLACK); - EndDrawing(); - } -} diff --git a/src/platforms/rcore_desktop_glfw.c b/src/platforms/rcore_desktop_glfw.c index 45811e766ac1..ecbc92aaa75b 100644 --- a/src/platforms/rcore_desktop_glfw.c +++ b/src/platforms/rcore_desktop_glfw.c @@ -58,6 +58,7 @@ #if defined(_WIN32) typedef void *PVOID; typedef PVOID HANDLE; + #include "../external/win32_clipboard.h" typedef HANDLE HWND; #define GLFW_EXPOSE_NATIVE_WIN32 #define GLFW_NATIVE_INCLUDE_NONE // To avoid some symbols re-definition in windows.h @@ -966,6 +967,33 @@ const char *GetClipboardText(void) return glfwGetClipboardString(platform.handle); } +#if defined(SUPPORT_CLIPBOARD_IMAGE) +// Get clipboard image +Image GetClipboardImage(void) +{ + Image image = {0}; + unsigned long long int dataSize = 0; + void* fileData = NULL; + +#ifdef _WIN32 + int width, height; + fileData = (void*)Win32GetClipboardImageData(&width, &height, &dataSize); +#else + TRACELOG(LOG_WARNING, "Clipboard image: PLATFORM_GLFW doesn't implement `GetClipboardImage` for this OS"); +#endif + + if (fileData == NULL) + { + TRACELOG(LOG_WARNING, "Clipboard image: Couldn't get clipboard data."); + } + else + { + image = LoadImageFromMemory(".bmp", fileData, dataSize); + } + return image; +} +#endif // SUPPORT_CLIPBOARD_IMAGE + // Show mouse cursor void ShowCursor(void) { @@ -1898,4 +1926,8 @@ static void JoystickCallback(int jid, int event) } } +#ifdef _WIN32 +# define WIN32_CLIPBOARD_IMPLEMENTATION +# include "../external/win32_clipboard.h" +#endif // EOF diff --git a/src/platforms/rcore_desktop_rgfw.c b/src/platforms/rcore_desktop_rgfw.c index 68885ce3faa1..a8618e98ee72 100644 --- a/src/platforms/rcore_desktop_rgfw.c +++ b/src/platforms/rcore_desktop_rgfw.c @@ -664,6 +664,43 @@ const char *GetClipboardText(void) return RGFW_readClipboard(NULL); } + +#if defined(SUPPORT_CLIPBOARD_IMAGE) + +#ifdef _WIN32 +# define WIN32_CLIPBOARD_IMPLEMENTATION +# define WINUSER_ALREADY_INCLUDED +# define WINBASE_ALREADY_INCLUDED +# define WINGDI_ALREADY_INCLUDED +# include "../external/win32_clipboard.h" +#endif + +// Get clipboard image +Image GetClipboardImage(void) +{ + Image image = {0}; + unsigned long long int dataSize = 0; + void* fileData = NULL; + +#ifdef _WIN32 + int width, height; + fileData = (void*)Win32GetClipboardImageData(&width, &height, &dataSize); +#else + TRACELOG(LOG_WARNING, "Clipboard image: PLATFORM_GLFW doesn't implement `GetClipboardImage` for this OS"); +#endif + + if (fileData == NULL) + { + TRACELOG(LOG_WARNING, "Clipboard image: Couldn't get clipboard data."); + } + else + { + image = LoadImageFromMemory(".bmp", fileData, dataSize); + } + return image; +} +#endif // SUPPORT_CLIPBOARD_IMAGE + // Show mouse cursor void ShowCursor(void) { diff --git a/src/rcore.c b/src/rcore.c index 119e48382762..2d1808c142e5 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -514,7 +514,7 @@ const char *TextFormat(const char *text, ...); // Formatting of tex #if defined(SUPPORT_CLIPBOARD_IMAGE) #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" + #error "To enabled SUPPORT_CLIPBOARD_IMAGE, it also needs SUPPORT_FILEFORMAT_BMP, SUPPORT_MODULE_RTEXTURES and STBI_REQUIRED to be defined. It should have been defined earlier" #endif #endif // SUPPORT_CLIPBOARD_IMAGE From 505d5fcf1bf1ca3dd9a6c056dda3feec9f755a5b Mon Sep 17 00:00:00 2001 From: evertonse Date: Wed, 6 Nov 2024 18:22:48 -0300 Subject: [PATCH 06/17] [rcore] fix warnings in SDL3 compatibility layer --- src/platforms/rcore_desktop_sdl.c | 25 +++++++++++++------------ src/raylib.h | 1 - 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/platforms/rcore_desktop_sdl.c b/src/platforms/rcore_desktop_sdl.c index 33e78b0effde..5e1a4f0fc59e 100644 --- a/src/platforms/rcore_desktop_sdl.c +++ b/src/platforms/rcore_desktop_sdl.c @@ -272,7 +272,7 @@ 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; + int numJoysticks = 0; SDL_JoystickID *joysticks = SDL_GetJoysticks(&numJoysticks); if (joysticks) { if (joystickIndex < numJoysticks) { @@ -294,19 +294,20 @@ int SDL_GetNumVideoDisplays(void) return monitorCount; } + +// SLD3 Migration: +// To emulate SDL2 this function should return `SDL_DISABLE` or `SDL_ENABLE` +// representing the *processing state* of the event before this function makes any changes to it. Uint8 SDL_EventState(Uint32 type, int state) { + + Uint8 stateBefore = SDL_EventEnabled(type); 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; + case SDL_DISABLE: SDL_SetEventEnabled(type, false); break; + case SDL_ENABLE: SDL_SetEventEnabled(type, true); break; + default: TRACELOG(LOG_WARNING, "Event sate: unknow type"); } + return stateBefore; } void SDL_GetCurrentDisplayMode_Adapter(SDL_DisplayID displayID, SDL_DisplayMode* mode) @@ -336,7 +337,7 @@ SDL_Surface *SDL_CreateRGBSurface(Uint32 flags, int width, int height, int depth // 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; + return SDL_GetWindowDisplayScale(platform.window) * 96; } SDL_Surface *SDL_CreateRGBSurfaceWithFormat(Uint32 flags, int width, int height, int depth, Uint32 format) @@ -356,7 +357,7 @@ SDL_Surface *SDL_CreateRGBSurfaceWithFormatFrom(void *pixels, int width, int hei int SDL_NumJoysticks(void) { - int i, numJoysticks; + int numJoysticks; SDL_JoystickID *joysticks = SDL_GetJoysticks(&numJoysticks); SDL_free(joysticks); return numJoysticks; diff --git a/src/raylib.h b/src/raylib.h index 723f787d9f84..89d1fdfde02c 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1012,7 +1012,6 @@ 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 From 98ad55fec2cf96feb84ed9c0781170751d4a3ae4 Mon Sep 17 00:00:00 2001 From: evertonse Date: Wed, 6 Nov 2024 19:06:02 -0300 Subject: [PATCH 07/17] Makefile: Allow specifying SDL_LIBRARIES to link, this helps with SDL3 --- examples/Makefile | 6 ++++-- src/Makefile | 4 +++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/examples/Makefile b/examples/Makefile index 02d83931a615..980f6831528a 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -87,6 +87,8 @@ USE_EXTERNAL_GLFW ?= FALSE # WARNING: Library is not included in raylib, it MUST be configured by users SDL_INCLUDE_PATH ?= $(RAYLIB_SRC_PATH)/external/SDL2/include SDL_LIBRARY_PATH ?= $(RAYLIB_SRC_PATH)/external/SDL2/lib +SDL_LIBRARIES ?= -lSDL2 -lSDL2main + # Use Wayland display server protocol on Linux desktop (by default it uses X11 windowing system) # NOTE: This variable is only used for PLATFORM_OS: LINUX @@ -415,12 +417,12 @@ endif ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_SDL) ifeq ($(PLATFORM_OS),WINDOWS) # Libraries for Windows desktop compilation - LDLIBS = -lraylib -lSDL2 -lSDL2main -lopengl32 -lgdi32 + LDLIBS = -lraylib $(SDL_LIBRARIES) -lopengl32 -lgdi32 endif ifeq ($(PLATFORM_OS),LINUX) # Libraries for Debian GNU/Linux desktop compiling # NOTE: Required packages: libegl1-mesa-dev - LDLIBS = -lraylib -lSDL2 -lSDL2main -lGL -lm -lpthread -ldl -lrt + LDLIBS = -lraylib $(SDL_LIBRARIES) -lGL -lm -lpthread -ldl -lrt # On X11 requires also below libraries LDLIBS += -lX11 diff --git a/src/Makefile b/src/Makefile index 1f0b730c6083..9316f8874f8f 100644 --- a/src/Makefile +++ b/src/Makefile @@ -118,6 +118,8 @@ GLFW_LINUX_ENABLE_X11 ?= TRUE # WARNING: Library is not included in raylib, it MUST be configured by users SDL_INCLUDE_PATH ?= $(RAYLIB_SRC_PATH)/external/SDL2/include SDL_LIBRARY_PATH ?= $(RAYLIB_SRC_PATH)/external/SDL2/lib +SDL_LIBRARIES ?= -lSDL2 -lSDL2main + # Determine if the file has root access (only required to install raylib) # "whoami" prints the name of the user that calls him (so, if it is the root user, "whoami" prints "root") @@ -586,7 +588,7 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_SDL) LDLIBS += -lX11 endif endif - LDLIBS += -lSDL2 -lSDL2main + LDLIBS += $(SDL_LIBRARIES) endif ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_RGFW) ifeq ($(PLATFORM_OS),WINDOWS) From 3e723e73d2ff9af8c176540d1c832a3869cb1fa0 Mon Sep 17 00:00:00 2001 From: evertonse Date: Wed, 6 Nov 2024 19:23:18 -0300 Subject: [PATCH 08/17] Makefile: examples makefile now compile others/rlgl_standalone only when TARGET_PLATFORM is PLATFORM_DESKTOP_GFLW --- examples/Makefile | 8 ++++++-- src/Makefile | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/examples/Makefile b/examples/Makefile index 980f6831528a..f4a265a7a084 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -649,8 +649,12 @@ OTHERS = \ others/embedded_files_loading \ others/raylib_opengl_interop \ others/raymath_vector_angle \ - others/rlgl_compute_shader \ - others/rlgl_standalone + others/rlgl_compute_shader + +ifeq ($(TARGET_PLATFORM), PLATFORM_DESKTOP_GFLW) + OTHERS += others/rlgl_standalone +endif + CURRENT_MAKEFILE = $(lastword $(MAKEFILE_LIST)) diff --git a/src/Makefile b/src/Makefile index 9316f8874f8f..45984d7400b9 100644 --- a/src/Makefile +++ b/src/Makefile @@ -462,7 +462,7 @@ CFLAGS += $(CUSTOM_CFLAGS) # Define include paths for required headers: INCLUDE_PATHS # NOTE: Several external required libraries (stb and others) #------------------------------------------------------------------------------------------------ -INCLUDE_PATHS = -I. +INCLUDE_PATHS = -I. # Define additional directories containing required header files ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW) From 729de10b1ea572d5c8f88a9cdaf877c76dc04865 Mon Sep 17 00:00:00 2001 From: evertonse Date: Wed, 6 Nov 2024 19:41:48 -0300 Subject: [PATCH 09/17] Makefile: examples makefile now compile others/rlgl_standalone only when TARGET_PLATFORM is PLATFORM_DESKTOP_GFLW --- examples/Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/Makefile b/examples/Makefile index f4a265a7a084..fc95654dbce0 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -518,8 +518,7 @@ CORE = \ core/core_window_flags \ core/core_window_letterbox \ core/core_window_should_close \ - core/core_world_screen \ - core/core_clipboard_image + core/core_world_screen SHAPES = \ shapes/shapes_basic_shapes \ From 4d5dfb150c9faab5e9ff570bde47a2524ed68c50 Mon Sep 17 00:00:00 2001 From: evertonse Date: Wed, 6 Nov 2024 20:47:38 -0300 Subject: [PATCH 10/17] [rcore]: PLATFORM_SDL: improve clipboard data retrieval --- src/config.h | 11 +++++++-- src/platforms/rcore_desktop_sdl.c | 41 ++++++++++++++++++++++--------- 2 files changed, 39 insertions(+), 13 deletions(-) diff --git a/src/config.h b/src/config.h index 703b0f23e063..e3749c5602cc 100644 --- a/src/config.h +++ b/src/config.h @@ -283,14 +283,21 @@ #define STBI_REQUIRED #endif - #ifndef SUPPORT_FILEFORMAT_BMP + #ifndef SUPPORT_FILEFORMAT_BMP // For clipboard image on Windows #define SUPPORT_FILEFORMAT_BMP 1 #endif + #ifndef SUPPORT_FILEFORMAT_PNG // Wayland uses png for prints, at least it was on 22 LTS ubuntu + #define SUPPORT_FILEFORMAT_PNG 1 + #endif + + #ifndef SUPPORT_FILEFORMAT_JPG + #define SUPPORT_FILEFORMAT_JPG 1 + #endif + #ifndef SUPPORT_MODULE_RTEXTURES #define SUPPORT_MODULE_RTEXTURES 1 #endif - #endif #endif // CONFIG_H diff --git a/src/platforms/rcore_desktop_sdl.c b/src/platforms/rcore_desktop_sdl.c index 5e1a4f0fc59e..7d931b4b8d8c 100644 --- a/src/platforms/rcore_desktop_sdl.c +++ b/src/platforms/rcore_desktop_sdl.c @@ -1086,20 +1086,39 @@ const char *GetClipboardText(void) // Get clipboard image Image GetClipboardImage(void) { - Image image = {0}; + // Let's hope compiler put these arrays in static memory + const char *image_formats[] = { + "image/bmp", + "image/png", + "image/jpg", + "image/tiff", + }; + const char *image_extensions[] = { + ".bmp", + ".png", + ".jpg", + ".tiff", + }; + + Image image = {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) - { - TRACELOG(LOG_WARNING, "Clipboard image: Couldn't get clipboard data. %s", SDL_GetError()); - } - else - { - image = LoadImageFromMemory(".bmp", fileData, dataSize); + void *fileData = NULL; + for (int i = 0; i < SDL_arraysize(image_formats); ++i) + { + // NOTE: This pointer should be free with SDL_free() at some point. + fileData = SDL_GetClipboardData(image_formats[i], &dataSize); + if (fileData) { + image = LoadImageFromMemory(image_extensions[i], fileData, dataSize); + if (IsImageValid(image)) + { + TRACELOG(LOG_INFO, "Clipboard image: Got image from clipboard as a `%s` successfully", image_extensions[i]); + return image; + } + } } + + TRACELOG(LOG_WARNING, "Clipboard image: Couldn't get clipboard data. %s", SDL_GetError()); return image; } #endif From e1a698a334618efe18744a70200602d805fcd1d7 Mon Sep 17 00:00:00 2001 From: evertonse Date: Wed, 6 Nov 2024 21:18:59 -0300 Subject: [PATCH 11/17] external: remove unused function from win32_clipboard.h --- src/external/win32_clipboard.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/external/win32_clipboard.h b/src/external/win32_clipboard.h index ce986578a8bb..08ee5f759df8 100644 --- a/src/external/win32_clipboard.h +++ b/src/external/win32_clipboard.h @@ -180,8 +180,6 @@ 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); - unsigned char* Win32GetClipboardImageData(int* width, int* height, unsigned long long int *dataSize) { From 207fabd75905427ff29e913cb0824876be86e946 Mon Sep 17 00:00:00 2001 From: evertonse Date: Wed, 6 Nov 2024 23:09:49 -0300 Subject: [PATCH 12/17] Makefile: allow for extra flags necessary when compiling for SDL3 --- examples/Makefile | 4 ++-- src/Makefile | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/Makefile b/examples/Makefile index fc95654dbce0..a47911b5e146 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -265,9 +265,9 @@ endif # Define include paths for required headers: INCLUDE_PATHS # NOTE: Some external/extras libraries could be required (stb, easings...) #------------------------------------------------------------------------------------------------ -INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external - +INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external $(EXTRA_INCLUDE_PATHS) # Define additional directories containing required header files + ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW) ifeq ($(PLATFORM_OS),BSD) INCLUDE_PATHS += -I$(RAYLIB_INCLUDE_PATH) -I/usr/pkg/include -I/usr/X11R7/include diff --git a/src/Makefile b/src/Makefile index 45984d7400b9..265f95ca0ddb 100644 --- a/src/Makefile +++ b/src/Makefile @@ -462,7 +462,7 @@ CFLAGS += $(CUSTOM_CFLAGS) # Define include paths for required headers: INCLUDE_PATHS # NOTE: Several external required libraries (stb and others) #------------------------------------------------------------------------------------------------ -INCLUDE_PATHS = -I. +INCLUDE_PATHS = -I. $(EXTRA_INCLUDE_PATHS) # Define additional directories containing required header files ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW) From 01a999cebe4dd07821653bc74b5a6a30e98193fa Mon Sep 17 00:00:00 2001 From: evertonse Date: Wed, 6 Nov 2024 23:54:05 -0300 Subject: [PATCH 13/17] [rcore]: fix string typo --- src/platforms/rcore_desktop_glfw.c | 2 +- src/platforms/rcore_desktop_rgfw.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/platforms/rcore_desktop_glfw.c b/src/platforms/rcore_desktop_glfw.c index ecbc92aaa75b..e765debc1cbf 100644 --- a/src/platforms/rcore_desktop_glfw.c +++ b/src/platforms/rcore_desktop_glfw.c @@ -979,7 +979,7 @@ Image GetClipboardImage(void) int width, height; fileData = (void*)Win32GetClipboardImageData(&width, &height, &dataSize); #else - TRACELOG(LOG_WARNING, "Clipboard image: PLATFORM_GLFW doesn't implement `GetClipboardImage` for this OS"); + TRACELOG(LOG_WARNING, "Clipboard image: PLATFORM_DESKTOP_GLFW doesn't implement `GetClipboardImage` for this OS"); #endif if (fileData == NULL) diff --git a/src/platforms/rcore_desktop_rgfw.c b/src/platforms/rcore_desktop_rgfw.c index a8618e98ee72..f3f26e3e8bad 100644 --- a/src/platforms/rcore_desktop_rgfw.c +++ b/src/platforms/rcore_desktop_rgfw.c @@ -686,7 +686,7 @@ Image GetClipboardImage(void) int width, height; fileData = (void*)Win32GetClipboardImageData(&width, &height, &dataSize); #else - TRACELOG(LOG_WARNING, "Clipboard image: PLATFORM_GLFW doesn't implement `GetClipboardImage` for this OS"); + TRACELOG(LOG_WARNING, "Clipboard image: PLATFORM_DESKTOP_RGFW doesn't implement `GetClipboardImage` for this OS"); #endif if (fileData == NULL) From c3008017c9ee8e3661cba45dc826b255e8d7794e Mon Sep 17 00:00:00 2001 From: evertonse Date: Thu, 7 Nov 2024 00:10:10 -0300 Subject: [PATCH 14/17] [rcore]: Properly handle NULL dpi passing. As is allowed in SDL2 --- src/platforms/rcore_desktop_sdl.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/platforms/rcore_desktop_sdl.c b/src/platforms/rcore_desktop_sdl.c index 7d931b4b8d8c..2ab216595451 100644 --- a/src/platforms/rcore_desktop_sdl.c +++ b/src/platforms/rcore_desktop_sdl.c @@ -336,8 +336,13 @@ SDL_Surface *SDL_CreateRGBSurface(Uint32 flags, int width, int height, int depth // SDL_GetDisplayDPI() - // not reliable across platforms, approximately replaced by multiplying // SDL_GetWindowDisplayScale() times 160 on iPhone and Android, and 96 on other platforms. +// returns 0 on success or a negative error code on failure int SDL_GetDisplayDPI(int displayIndex, float * ddpi, float * hdpi, float * vdpi) { - return SDL_GetWindowDisplayScale(platform.window) * 96; + float dpi = SDL_GetWindowDisplayScale(platform.window) * 96.0; + if (ddpi != NULL) *ddpi = dpi; + if (hdpi != NULL) *hdpi = dpi; + if (vdpi != NULL) *vdpi = dpi; + return 0; } SDL_Surface *SDL_CreateRGBSurfaceWithFormat(Uint32 flags, int width, int height, int depth, Uint32 format) From cf00b4aa97f7b5d841d934fe8402fc892aa1c61a Mon Sep 17 00:00:00 2001 From: evertonse Date: Fri, 8 Nov 2024 00:57:40 -0300 Subject: [PATCH 15/17] external: fix arch finding on win32_clipboard.h to allow compilation on msvc cmake CI --- src/external/win32_clipboard.h | 38 ++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/external/win32_clipboard.h b/src/external/win32_clipboard.h index 08ee5f759df8..83285643269c 100644 --- a/src/external/win32_clipboard.h +++ b/src/external/win32_clipboard.h @@ -13,6 +13,44 @@ unsigned char* Win32GetClipboardImageData(int* width, int* height, unsigned long #include #include +// NOTE: These search for architecture is taken from "Windows.h", and it's necessary if we really don't wanna import windows.h +// and still make it compile on msvc, because import indirectly importing "winnt.h" (e.g. ) can cause problems is these are not defined. +#if !defined(_X86_) && !defined(_68K_) && !defined(_MPPC_) && !defined(_IA64_) && !defined(_AMD64_) && !defined(_ARM_) && !defined(_ARM64_) && !defined(_ARM64EC_) && defined(_M_IX86) +#define _X86_ +#if !defined(_CHPE_X86_ARM64_) && defined(_M_HYBRID) +#define _CHPE_X86_ARM64_ +#endif +#endif + +#if !defined(_AMD64_) && !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && !defined(_ARM_) && !defined(_ARM64_) && (defined(_M_AMD64) || defined(_M_ARM64EC)) +#define _AMD64_ +#endif + +#if !defined(_ARM_) && !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && !defined(_ARM64_) && !defined(_ARM64EC_) && defined(_M_ARM) +#define _ARM_ +#endif + +#if !defined(_ARM64_) && !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && !defined(_ARM_) && !defined(_ARM64EC_) && defined(_M_ARM64) +#define _ARM64_ +#endif + +#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_ARM_) && !defined(_ARM64_) && !defined(_ARM64EC_) && defined(_M_ARM64EC) +#define _ARM64EC_ +#endif + +#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && !defined(_ARM_) && !defined(_ARM64_) && !defined(_ARM64EC_) && defined(_M_M68K) +#define _68K_ +#endif + +#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && !defined(_ARM_) && !defined(_ARM64_) && !defined(_ARM64EC_) && defined(_M_MPPC) +#define _MPPC_ +#endif + +#if !defined(_IA64_) && !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_M_IX86) && !defined(_AMD64_) && !defined(_ARM_) && !defined(_ARM64_) && !defined(_ARM64EC_) && defined(_M_IA64) +#define _IA64_ +#endif + + #define WIN32_LEAN_AND_MEAN // #include // #include From d7ca8dc11b2bbabcf3a5dde10cba45d5ac0d4c31 Mon Sep 17 00:00:00 2001 From: evertonse Date: Fri, 8 Nov 2024 18:09:13 -0300 Subject: [PATCH 16/17] [rcore]: PLATFORM_SDL: Treat monitor as an ID in SDL3 as opposed to an index as in SDL2 --- src/platforms/rcore_desktop_sdl.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/platforms/rcore_desktop_sdl.c b/src/platforms/rcore_desktop_sdl.c index 2ab216595451..1385917671fd 100644 --- a/src/platforms/rcore_desktop_sdl.c +++ b/src/platforms/rcore_desktop_sdl.c @@ -451,7 +451,12 @@ void ToggleFullscreen(void) { const int monitor = SDL_GetWindowDisplayIndex(platform.window); const int monitorCount = SDL_GetNumVideoDisplays(); + +#ifdef PLATFORM_DESKTOP_SDL3 // SDL3 Migration: Monitor is an id instead of index now, returns 0 on failure + if ((monitor > 0) && (monitor <= monitorCount)) +#else if ((monitor >= 0) && (monitor < monitorCount)) +#endif { if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) > 0) { @@ -474,7 +479,11 @@ void ToggleBorderlessWindowed(void) { const int monitor = SDL_GetWindowDisplayIndex(platform.window); const int monitorCount = SDL_GetNumVideoDisplays(); +#ifdef PLATFORM_DESKTOP_SDL3 // SDL3 Migration: Monitor is an id instead of index now, returns 0 on failure + if ((monitor > 0) && (monitor <= monitorCount)) +#else if ((monitor >= 0) && (monitor < monitorCount)) +#endif { if ((CORE.Window.flags & FLAG_BORDERLESS_WINDOWED_MODE) > 0) { @@ -523,7 +532,11 @@ void SetWindowState(unsigned int flags) { const int monitor = SDL_GetWindowDisplayIndex(platform.window); const int monitorCount = SDL_GetNumVideoDisplays(); + #ifdef PLATFORM_DESKTOP_SDL3 // SDL3 Migration: Monitor is an id instead of index now, returns 0 on failure + if ((monitor > 0) && (monitor <= monitorCount)) + #else if ((monitor >= 0) && (monitor < monitorCount)) + #endif { SDL_SetWindowFullscreen(platform.window, SDL_WINDOW_FULLSCREEN); CORE.Window.fullscreen = true; @@ -582,7 +595,11 @@ void SetWindowState(unsigned int flags) { const int monitor = SDL_GetWindowDisplayIndex(platform.window); const int monitorCount = SDL_GetNumVideoDisplays(); + #ifdef PLATFORM_DESKTOP_SDL3 // SDL3 Migration: Monitor is an id instead of index now, returns 0 on failure + if ((monitor > 0) && (monitor <= monitorCount)) + #else if ((monitor >= 0) && (monitor < monitorCount)) + #endif { SDL_SetWindowFullscreen(platform.window, SDL_WINDOW_FULLSCREEN_DESKTOP); } @@ -903,6 +920,7 @@ int GetCurrentMonitor(void) { int currentMonitor = 0; + // Be away that this returns an ID in SDL3 and a Index in SDL2 currentMonitor = SDL_GetWindowDisplayIndex(platform.window); return currentMonitor; From 08e84a6549df3a84dc23c947af740a5d466da74a Mon Sep 17 00:00:00 2001 From: evertonse Date: Fri, 8 Nov 2024 18:13:41 -0300 Subject: [PATCH 17/17] [rcore]: typo --- src/platforms/rcore_desktop_sdl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platforms/rcore_desktop_sdl.c b/src/platforms/rcore_desktop_sdl.c index 1385917671fd..a201f2cde485 100644 --- a/src/platforms/rcore_desktop_sdl.c +++ b/src/platforms/rcore_desktop_sdl.c @@ -920,7 +920,7 @@ int GetCurrentMonitor(void) { int currentMonitor = 0; - // Be away that this returns an ID in SDL3 and a Index in SDL2 + // Be aware that this returns an ID in SDL3 and a Index in SDL2 currentMonitor = SDL_GetWindowDisplayIndex(platform.window); return currentMonitor;