Update C sources

This commit is contained in:
Milan Nikolic 2025-06-09 15:53:56 +02:00
parent e08c4cd054
commit 3327fcaf9f
No known key found for this signature in database
GPG key ID: 9229D0EAA3AA4E75
22 changed files with 14167 additions and 10920 deletions

View file

@ -27,7 +27,7 @@
*
* LICENSE: zlib/libpng
*
* Copyright (c) 2013-2024 Ramon Santamaria (@raysan5) and contributors
* Copyright (c) 2013-2025 Ramon Santamaria (@raysan5) and contributors
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
@ -70,6 +70,16 @@ typedef struct {
EGLConfig config; // Graphic config
} PlatformData;
typedef struct {
// Store data for both Hover and Touch events
// Used to ignore Hover events which are interpreted as Touch events
int32_t pointCount; // Number of touch points active
int32_t pointId[MAX_TOUCH_POINTS]; // Point identifiers
Vector2 position[MAX_TOUCH_POINTS]; // Touch position on screen
int32_t hoverPoints[MAX_TOUCH_POINTS]; // Hover Points
} TouchRaw;
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
@ -246,6 +256,8 @@ static const KeyboardKey mapKeycode[KEYCODE_MAP_SIZE] = {
KEY_KP_EQUAL // AKEYCODE_NUMPAD_EQUALS
};
static TouchRaw touchRaw = { 0 };
//----------------------------------------------------------------------------------
// Module Internal Functions Declaration
//----------------------------------------------------------------------------------
@ -339,7 +351,7 @@ void MinimizeWindow(void)
TRACELOG(LOG_WARNING, "MinimizeWindow() not available on target platform");
}
// Set window state: not minimized/maximized
// Restore window from being minimized/maximized
void RestoreWindow(void)
{
TRACELOG(LOG_WARNING, "RestoreWindow() not available on target platform");
@ -433,7 +445,7 @@ int GetMonitorCount(void)
return 1;
}
// Get number of monitors
// Get current monitor where window is placed
int GetCurrentMonitor(void)
{
TRACELOG(LOG_WARNING, "GetCurrentMonitor() not implemented on target platform");
@ -462,17 +474,21 @@ int GetMonitorHeight(int monitor)
}
// Get selected monitor physical width in millimetres
// NOTE: It seems to return a slightly underestimated value on some devices
int GetMonitorPhysicalWidth(int monitor)
{
TRACELOG(LOG_WARNING, "GetMonitorPhysicalWidth() not implemented on target platform");
return 0;
int widthPixels = ANativeWindow_getWidth(platform.app->window);
float dpi = AConfiguration_getDensity(platform.app->config);
return (widthPixels/dpi)*25.4f;
}
// Get selected monitor physical height in millimetres
// NOTE: It seems to return a slightly underestimated value on some devices
int GetMonitorPhysicalHeight(int monitor)
{
TRACELOG(LOG_WARNING, "GetMonitorPhysicalHeight() not implemented on target platform");
return 0;
int heightPixels = ANativeWindow_getHeight(platform.app->window);
float dpi = AConfiguration_getDensity(platform.app->config);
return (heightPixels/dpi)*25.4f;
}
// Get selected monitor refresh rate
@ -499,8 +515,9 @@ Vector2 GetWindowPosition(void)
// Get window scale DPI factor for current monitor
Vector2 GetWindowScaleDPI(void)
{
TRACELOG(LOG_WARNING, "GetWindowScaleDPI() not implemented on target platform");
return (Vector2){ 1.0f, 1.0f };
int density = AConfiguration_getDensity(platform.app->config);
float scale = (float)density/160;
return (Vector2){ scale, scale };
}
// Set clipboard text content
@ -629,7 +646,7 @@ int SetGamepadMappings(const char *mappings)
// Set gamepad vibration
void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float duration)
{
TRACELOG(LOG_WARNING, "GamepadSetVibration() not implemented on target platform");
TRACELOG(LOG_WARNING, "SetGamepadVibration() not implemented on target platform");
}
// Set mouse position XY
@ -701,7 +718,7 @@ void PollInputEvents(void)
// Poll Events (registered events) until we reach TIMEOUT which indicates there are no events left to poll
// NOTE: Activity is paused if not enabled (platform.appEnabled)
while ((pollResult = ALooper_pollOnce(platform.appEnabled? 0 : -1, NULL, &pollEvents, (void**)&platform.source)) > ALOOPER_POLL_TIMEOUT)
while ((pollResult = ALooper_pollOnce(platform.appEnabled? 0 : -1, NULL, &pollEvents, ((void **)&platform.source)) > ALOOPER_POLL_TIMEOUT))
{
// Process this event
if (platform.source != NULL) platform.source->process(platform.app, platform.source);
@ -788,7 +805,7 @@ int InitPlatform(void)
while (!CORE.Window.ready)
{
// Process events until we reach TIMEOUT, which indicates no more events queued.
while ((pollResult = ALooper_pollOnce(0, NULL, &pollEvents, (void**)&platform.source)) > ALOOPER_POLL_TIMEOUT)
while ((pollResult = ALooper_pollOnce(0, NULL, &pollEvents, ((void **)&platform.source)) > ALOOPER_POLL_TIMEOUT))
{
// Process this event
if (platform.source != NULL) platform.source->process(platform.app, platform.source);
@ -798,6 +815,8 @@ int InitPlatform(void)
}
}
for (int i = 0; i < MAX_TOUCH_POINTS; i++) touchRaw.hoverPoints[i] = -1;
return 0;
}
@ -850,22 +869,20 @@ static int InitGraphicsDevice(void)
TRACELOG(LOG_INFO, "DISPLAY: Trying to enable MSAA x4");
}
const EGLint framebufferAttribs[] =
{
EGL_RENDERABLE_TYPE, (rlGetVersion() == RL_OPENGL_ES_30)? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT, // Type of context support
const EGLint framebufferAttribs[] = {
EGL_RENDERABLE_TYPE, (rlGetVersion() == RL_OPENGL_ES_30)? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT, // Type of context support
EGL_RED_SIZE, 8, // RED color bit depth (alternative: 5)
EGL_GREEN_SIZE, 8, // GREEN color bit depth (alternative: 6)
EGL_BLUE_SIZE, 8, // BLUE color bit depth (alternative: 5)
//EGL_TRANSPARENT_TYPE, EGL_NONE, // Request transparent framebuffer (EGL_TRANSPARENT_RGB does not work on RPI)
EGL_DEPTH_SIZE, 16, // Depth buffer size (Required to use Depth testing!)
EGL_DEPTH_SIZE, 24, // Depth buffer size (Required to use Depth testing!)
//EGL_STENCIL_SIZE, 8, // Stencil buffer size
EGL_SAMPLE_BUFFERS, sampleBuffer, // Activate MSAA
EGL_SAMPLE_BUFFERS, sampleBuffer, // Activate MSAA
EGL_SAMPLES, samples, // 4x Antialiasing if activated (Free on MALI GPUs)
EGL_NONE
};
const EGLint contextAttribs[] =
{
const EGLint contextAttribs[] = {
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE
};
@ -1228,7 +1245,7 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
return 1; // Handled gamepad button
}
KeyboardKey key = (keycode > 0 && keycode < KEYCODE_MAP_SIZE)? mapKeycode[keycode] : KEY_NULL;
KeyboardKey key = ((keycode > 0) && (keycode < KEYCODE_MAP_SIZE))? mapKeycode[keycode] : KEY_NULL;
if (key != KEY_NULL)
{
// Save current key and its state
@ -1268,25 +1285,85 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
}
// Register touch points count
CORE.Input.Touch.pointCount = AMotionEvent_getPointerCount(event);
touchRaw.pointCount = AMotionEvent_getPointerCount(event);
for (int i = 0; (i < CORE.Input.Touch.pointCount) && (i < MAX_TOUCH_POINTS); i++)
for (int i = 0; (i < touchRaw.pointCount) && (i < MAX_TOUCH_POINTS); i++)
{
// Register touch points id
CORE.Input.Touch.pointId[i] = AMotionEvent_getPointerId(event, i);
touchRaw.pointId[i] = AMotionEvent_getPointerId(event, i);
// Register touch points position
CORE.Input.Touch.position[i] = (Vector2){ AMotionEvent_getX(event, i), AMotionEvent_getY(event, i) };
touchRaw.position[i] = (Vector2){ AMotionEvent_getX(event, i), AMotionEvent_getY(event, i) };
// Normalize CORE.Input.Touch.position[i] for CORE.Window.screen.width and CORE.Window.screen.height
float widthRatio = (float)(CORE.Window.screen.width + CORE.Window.renderOffset.x)/(float)CORE.Window.display.width;
float heightRatio = (float)(CORE.Window.screen.height + CORE.Window.renderOffset.y)/(float)CORE.Window.display.height;
CORE.Input.Touch.position[i].x = CORE.Input.Touch.position[i].x*widthRatio - (float)CORE.Window.renderOffset.x/2;
CORE.Input.Touch.position[i].y = CORE.Input.Touch.position[i].y*heightRatio - (float)CORE.Window.renderOffset.y/2;
touchRaw.position[i].x = touchRaw.position[i].x*widthRatio - (float)CORE.Window.renderOffset.x/2;
touchRaw.position[i].y = touchRaw.position[i].y*heightRatio - (float)CORE.Window.renderOffset.y/2;
}
int32_t action = AMotionEvent_getAction(event);
unsigned int flags = action & AMOTION_EVENT_ACTION_MASK;
int32_t pointerIndex = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
if (flags == AMOTION_EVENT_ACTION_HOVER_ENTER)
{
// The new pointer is hover
// So add it to hoverPoints
for (int i = 0; i < MAX_TOUCH_POINTS; i++)
{
if (touchRaw.hoverPoints[i] == -1)
{
touchRaw.hoverPoints[i] = touchRaw.pointId[pointerIndex];
break;
}
}
}
if ((flags == AMOTION_EVENT_ACTION_POINTER_UP) || (flags == AMOTION_EVENT_ACTION_UP) || (flags == AMOTION_EVENT_ACTION_HOVER_EXIT))
{
// One of the touchpoints is released, remove it from touch point arrays
if (flags == AMOTION_EVENT_ACTION_HOVER_EXIT)
{
// If the touchPoint is hover, remove it from hoverPoints
for (int i = 0; i < MAX_TOUCH_POINTS; i++)
{
if (touchRaw.hoverPoints[i] == touchRaw.pointId[pointerIndex])
{
touchRaw.hoverPoints[i] = -1;
break;
}
}
}
for (int i = pointerIndex; (i < touchRaw.pointCount - 1) && (i < MAX_TOUCH_POINTS - 1); i++)
{
touchRaw.pointId[i] = touchRaw.pointId[i+1];
touchRaw.position[i] = touchRaw.position[i+1];
}
touchRaw.pointCount--;
}
int pointCount = 0;
for (int i = 0; (i < touchRaw.pointCount) && (i < MAX_TOUCH_POINTS); i++)
{
// If the touchPoint is hover, Ignore it
bool hover = false;
for (int j = 0; j < MAX_TOUCH_POINTS; j++)
{
// Check if the touchPoint is in hoverPointers
if (touchRaw.hoverPoints[j] == touchRaw.pointId[i])
{
hover = true;
break;
}
}
if (hover) continue;
CORE.Input.Touch.pointId[pointCount] = touchRaw.pointId[i];
CORE.Input.Touch.position[pointCount] = touchRaw.position[i];
pointCount++;
}
CORE.Input.Touch.pointCount = pointCount;
#if defined(SUPPORT_GESTURES_SYSTEM)
GestureEvent gestureEvent = { 0 };
@ -1311,20 +1388,6 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
ProcessGestureEvent(gestureEvent);
#endif
int32_t pointerIndex = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
if (flags == AMOTION_EVENT_ACTION_POINTER_UP || flags == AMOTION_EVENT_ACTION_UP)
{
// One of the touchpoints is released, remove it from touch point arrays
for (int i = pointerIndex; (i < CORE.Input.Touch.pointCount - 1) && (i < MAX_TOUCH_POINTS); i++)
{
CORE.Input.Touch.pointId[i] = CORE.Input.Touch.pointId[i+1];
CORE.Input.Touch.position[i] = CORE.Input.Touch.position[i+1];
}
CORE.Input.Touch.pointCount--;
}
// When all touchpoints are tapped and released really quickly, this event is generated
if (flags == AMOTION_EVENT_ACTION_CANCEL) CORE.Input.Touch.pointCount = 0;

View file

@ -1,6 +1,6 @@
/**********************************************************************************************
*
* rcore_desktop - Functions to manage window, graphics device and inputs
* rcore_desktop_glfw - Functions to manage window, graphics device and inputs
*
* PLATFORM: DESKTOP: GLFW
* - Windows (Win32, Win64)
@ -30,7 +30,7 @@
*
* LICENSE: zlib/libpng
*
* Copyright (c) 2013-2024 Ramon Santamaria (@raysan5) and contributors
* Copyright (c) 2013-2025 Ramon Santamaria (@raysan5) and contributors
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
@ -68,7 +68,7 @@
// NOTE: Those functions require linking with winmm library
//#pragma warning(disable: 4273)
__declspec(dllimport) unsigned int __stdcall timeEndPeriod(unsigned int uPeriod);
//#pragma warning(default: 4273)
//#pragma warning(default: 4273)
#endif
#endif
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__)
@ -86,6 +86,8 @@
#include "GLFW/glfw3native.h" // Required for: glfwGetCocoaWindow()
#endif
#include <stddef.h> // Required for: size_t
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
@ -127,6 +129,11 @@ static void MouseScrollCallback(GLFWwindow *window, double xoffset, double yoffs
static void CursorEnterCallback(GLFWwindow *window, int enter); // GLFW3 Cursor Enter Callback, cursor enters client area
static void JoystickCallback(int jid, int event); // GLFW3 Joystick Connected/Disconnected Callback
// Wrappers used by glfwInitAllocator
static void *AllocateWrapper(size_t size, void *user); // GLFW3 GLFWallocatefun, wrapps around RL_MALLOC macro
static void *ReallocateWrapper(void *block, size_t size, void *user); // GLFW3 GLFWreallocatefun, wrapps around RL_MALLOC macro
static void DeallocateWrapper(void *block, void *user); // GLFW3 GLFWdeallocatefun, wraps around RL_FREE macro
//----------------------------------------------------------------------------------
// Module Functions Declaration
//----------------------------------------------------------------------------------
@ -223,11 +230,9 @@ void ToggleBorderlessWindowed(void)
if (!wasOnFullscreen) CORE.Window.previousPosition = CORE.Window.position;
CORE.Window.previousScreen = CORE.Window.screen;
// Set undecorated and topmost modes and flags
// Set undecorated flag
glfwSetWindowAttrib(platform.handle, GLFW_DECORATED, GLFW_FALSE);
CORE.Window.flags |= FLAG_WINDOW_UNDECORATED;
glfwSetWindowAttrib(platform.handle, GLFW_FLOATING, GLFW_TRUE);
CORE.Window.flags |= FLAG_WINDOW_TOPMOST;
// Get monitor position and size
int monitorPosX = 0;
@ -247,9 +252,7 @@ void ToggleBorderlessWindowed(void)
}
else
{
// Remove topmost and undecorated modes and flags
glfwSetWindowAttrib(platform.handle, GLFW_FLOATING, GLFW_FALSE);
CORE.Window.flags &= ~FLAG_WINDOW_TOPMOST;
// Remove undecorated flag
glfwSetWindowAttrib(platform.handle, GLFW_DECORATED, GLFW_TRUE);
CORE.Window.flags &= ~FLAG_WINDOW_UNDECORATED;
@ -289,7 +292,7 @@ void MinimizeWindow(void)
glfwIconifyWindow(platform.handle);
}
// Set window state: not minimized/maximized
// Restore window from being minimized/maximized
void RestoreWindow(void)
{
if (glfwGetWindowAttrib(platform.handle, GLFW_RESIZABLE) == GLFW_TRUE)
@ -304,6 +307,8 @@ void RestoreWindow(void)
// Set window configuration state using flags
void SetWindowState(unsigned int flags)
{
if (!CORE.Window.ready) TRACELOG(LOG_WARNING, "WINDOW: SetWindowState does nothing before window initialization, Use \"SetConfigFlags\" instead");
// Check previous state and requested state to apply required changes
// NOTE: In most cases the functions already change the flags internally
@ -322,7 +327,7 @@ void SetWindowState(unsigned int flags)
}
// State change: FLAG_FULLSCREEN_MODE
if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) != (flags & FLAG_FULLSCREEN_MODE))
if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) != (flags & FLAG_FULLSCREEN_MODE) && ((flags & FLAG_FULLSCREEN_MODE) > 0))
{
ToggleFullscreen(); // NOTE: Window state flag updated inside function
}
@ -571,7 +576,7 @@ void SetWindowIcons(Image *images, int count)
else
{
int valid = 0;
GLFWimage *icons = RL_CALLOC(count, sizeof(GLFWimage));
GLFWimage *icons = (GLFWimage *)RL_CALLOC(count, sizeof(GLFWimage));
for (int i = 0; i < count; i++)
{
@ -733,7 +738,7 @@ int GetMonitorCount(void)
return monitorCount;
}
// Get number of monitors
// Get current monitor where window is placed
int GetCurrentMonitor(void)
{
int index = 0;
@ -967,32 +972,29 @@ const char *GetClipboardText(void)
return glfwGetClipboardString(platform.handle);
}
#if defined(SUPPORT_CLIPBOARD_IMAGE)
// Get clipboard image
Image GetClipboardImage(void)
{
Image image = {0};
Image image = { 0 };
#if defined(SUPPORT_CLIPBOARD_IMAGE)
#if defined(_WIN32)
unsigned long long int dataSize = 0;
void* fileData = NULL;
void *fileData = NULL;
int width = 0;
int height = 0;
#ifdef _WIN32
int width, height;
fileData = (void*)Win32GetClipboardImageData(&width, &height, &dataSize);
#else
TRACELOG(LOG_WARNING, "Clipboard image: PLATFORM_DESKTOP_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, (int)dataSize);
}
if (fileData == NULL) TRACELOG(LOG_WARNING, "Clipboard image: Couldn't get clipboard data.");
else image = LoadImageFromMemory(".bmp", fileData, (int)dataSize);
#else
TRACELOG(LOG_WARNING, "GetClipboardImage() not implemented on target platform");
#endif
#endif // SUPPORT_CLIPBOARD_IMAGE
return image;
}
#endif // SUPPORT_CLIPBOARD_IMAGE
// Show mouse cursor
void ShowCursor(void)
@ -1024,6 +1026,9 @@ void EnableCursor(void)
// Disables cursor (lock cursor)
void DisableCursor(void)
{
// Reset mouse position within the window area before disabling cursor
SetMousePosition(CORE.Window.screen.width, CORE.Window.screen.height);
glfwSetInputMode(platform.handle, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
// Set cursor position in the middle
@ -1091,7 +1096,7 @@ int SetGamepadMappings(const char *mappings)
// Set gamepad vibration
void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float duration)
{
TRACELOG(LOG_WARNING, "GamepadSetVibration() not available on target platform");
TRACELOG(LOG_WARNING, "SetGamepadVibration() not available on target platform");
}
// Set mouse position XY
@ -1233,7 +1238,7 @@ void PollInputEvents(void)
}
}
// Get current axis state
// Get current state of axes
const float *axes = state.axes;
for (int k = 0; (axes != NULL) && (k < GLFW_GAMEPAD_AXIS_LAST + 1); k++)
@ -1241,9 +1246,19 @@ void PollInputEvents(void)
CORE.Input.Gamepad.axisState[i][k] = axes[k];
}
// Register buttons for 2nd triggers (because GLFW doesn't count these as buttons but rather axis)
CORE.Input.Gamepad.currentButtonState[i][GAMEPAD_BUTTON_LEFT_TRIGGER_2] = (char)(CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_LEFT_TRIGGER] > 0.1f);
CORE.Input.Gamepad.currentButtonState[i][GAMEPAD_BUTTON_RIGHT_TRIGGER_2] = (char)(CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_RIGHT_TRIGGER] > 0.1f);
// Register buttons for 2nd triggers (because GLFW doesn't count these as buttons but rather as axes)
if (CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_LEFT_TRIGGER] > 0.1f)
{
CORE.Input.Gamepad.currentButtonState[i][GAMEPAD_BUTTON_LEFT_TRIGGER_2] = 1;
CORE.Input.Gamepad.lastButtonPressed = GAMEPAD_BUTTON_LEFT_TRIGGER_2;
}
else CORE.Input.Gamepad.currentButtonState[i][GAMEPAD_BUTTON_LEFT_TRIGGER_2] = 0;
if (CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_RIGHT_TRIGGER] > 0.1f)
{
CORE.Input.Gamepad.currentButtonState[i][GAMEPAD_BUTTON_RIGHT_TRIGGER_2] = 1;
CORE.Input.Gamepad.lastButtonPressed = GAMEPAD_BUTTON_RIGHT_TRIGGER_2;
}
else CORE.Input.Gamepad.currentButtonState[i][GAMEPAD_BUTTON_RIGHT_TRIGGER_2] = 0;
CORE.Input.Gamepad.axisCount[i] = GLFW_GAMEPAD_AXIS_LAST + 1;
}
@ -1251,12 +1266,13 @@ void PollInputEvents(void)
CORE.Window.resizedLastFrame = false;
if (CORE.Window.eventWaiting) glfwWaitEvents(); // Wait for in input events before continue (drawing is paused)
if ((CORE.Window.eventWaiting) || (IsWindowState(FLAG_WINDOW_MINIMIZED) && !IsWindowState(FLAG_WINDOW_ALWAYS_RUN)))
{
glfwWaitEvents(); // Wait for in input events before continue (drawing is paused)
CORE.Time.previous = GetTime();
}
else glfwPollEvents(); // Poll input events: keyboard/mouse/window events (callbacks) -> Update keys state
// While window minimized, stop loop execution
while (IsWindowState(FLAG_WINDOW_MINIMIZED) && !IsWindowState(FLAG_WINDOW_ALWAYS_RUN)) glfwWaitEvents();
CORE.Window.shouldClose = glfwWindowShouldClose(platform.handle);
// Reset close status for next frame
@ -1280,21 +1296,39 @@ static void SetDimensionsFromMonitor(GLFWmonitor *monitor)
if (CORE.Window.screen.height == 0) CORE.Window.screen.height = CORE.Window.display.height;
}
// Function wrappers around RL_*alloc macros, used by glfwInitAllocator() inside of InitPlatform()
// We need to provide these because GLFWallocator expects function pointers with specific signatures.
// Similar wrappers exist in utils.c but we cannot reuse them here due to declaration mismatch.
// https://www.glfw.org/docs/latest/intro_guide.html#init_allocator
static void *AllocateWrapper(size_t size, void *user)
{
(void)user;
return RL_MALLOC(size);
}
static void *ReallocateWrapper(void *block, size_t size, void *user)
{
(void)user;
return RL_REALLOC(block, size);
}
static void DeallocateWrapper(void *block, void *user)
{
(void)user;
RL_FREE(block);
}
// Initialize platform: graphics, inputs and more
int InitPlatform(void)
{
glfwSetErrorCallback(ErrorCallback);
/*
// TODO: Setup GLFW custom allocators to match raylib ones
const GLFWallocator allocator = {
.allocate = MemAlloc,
.deallocate = MemFree,
.reallocate = MemRealloc,
.user = NULL
.allocate = AllocateWrapper,
.deallocate = DeallocateWrapper,
.reallocate = ReallocateWrapper,
.user = NULL, // RL_*ALLOC macros are not capable of handling user-provided data
};
glfwInitAllocator(&allocator);
*/
#if defined(__APPLE__)
glfwInitHint(GLFW_COCOA_CHDIR_RESOURCES, GLFW_FALSE);
@ -1348,6 +1382,12 @@ int InitPlatform(void)
if ((CORE.Window.flags & FLAG_WINDOW_TRANSPARENT) > 0) glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE); // Transparent framebuffer
else glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_FALSE); // Opaque framebuffer
// HACK: Most of this was written before GLFW_SCALE_FRAMEBUFFER existed and
// was enabled by default. Disabling it gets back the old behavior. A
// complete fix will require removing a lot of CORE.Window.render
// manipulation code.
glfwWindowHint(GLFW_SCALE_FRAMEBUFFER, GLFW_FALSE);
if ((CORE.Window.flags & FLAG_WINDOW_HIGHDPI) > 0)
{
// Resize window content area based on the monitor content scale.
@ -1355,7 +1395,7 @@ int InitPlatform(void)
// On platforms like macOS the resolution of the framebuffer is changed independently of the window size.
glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE); // Scale content area based on the monitor content scale where window is placed on
#if defined(__APPLE__)
glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_TRUE);
glfwWindowHint(GLFW_SCALE_FRAMEBUFFER, GLFW_TRUE);
#endif
}
else glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_FALSE);
@ -1490,6 +1530,12 @@ int InitPlatform(void)
SetupFramebuffer(CORE.Window.display.width, CORE.Window.display.height);
platform.handle = glfwCreateWindow(CORE.Window.display.width, CORE.Window.display.height, (CORE.Window.title != 0)? CORE.Window.title : " ", monitor, NULL);
if (!platform.handle)
{
glfwTerminate();
TRACELOG(LOG_WARNING, "GLFW: Failed to initialize Window");
return -1;
}
// NOTE: Full-screen change, not working properly...
//glfwSetWindowMonitor(platform.handle, glfwGetPrimaryMonitor(), 0, 0, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);
@ -1504,6 +1550,12 @@ int InitPlatform(void)
int creationHeight = CORE.Window.screen.height != 0 ? CORE.Window.screen.height : 1;
platform.handle = glfwCreateWindow(creationWidth, creationHeight, (CORE.Window.title != 0)? CORE.Window.title : " ", NULL, NULL);
if (!platform.handle)
{
glfwTerminate();
TRACELOG(LOG_WARNING, "GLFW: Failed to initialize Window");
return -1;
}
// After the window was created, determine the monitor that the window manager assigned.
// Derive display sizes, and, if possible, window size in case it was zero at beginning.
@ -1527,18 +1579,8 @@ int InitPlatform(void)
return -1;
}
if (platform.handle)
{
CORE.Window.render.width = CORE.Window.screen.width;
CORE.Window.render.height = CORE.Window.screen.height;
}
}
if (!platform.handle)
{
glfwTerminate();
TRACELOG(LOG_WARNING, "GLFW: Failed to initialize Window");
return -1;
CORE.Window.render.width = CORE.Window.screen.width;
CORE.Window.render.height = CORE.Window.screen.height;
}
glfwMakeContextCurrent(platform.handle);
@ -1567,7 +1609,7 @@ int InitPlatform(void)
if ((CORE.Window.flags & FLAG_WINDOW_HIGHDPI) > 0)
{
// NOTE: On APPLE platforms system should manage window/input scaling and also framebuffer scaling.
// Framebuffer scaling should be activated with: glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_TRUE);
// Framebuffer scaling should be activated with: glfwWindowHint(GLFW_SCALE_FRAMEBUFFER, GLFW_TRUE);
#if !defined(__APPLE__)
glfwGetFramebufferSize(platform.handle, &fbWidth, &fbHeight);
@ -1655,7 +1697,9 @@ int InitPlatform(void)
// Retrieve gamepad names
for (int i = 0; i < MAX_GAMEPADS; i++)
{
if (glfwJoystickPresent(i)) strcpy(CORE.Input.Gamepad.name[i], glfwGetJoystickName(i));
// WARNING: If glfwGetJoystickName() is longer than MAX_GAMEPAD_NAME_LENGTH,
// we can get a not-NULL terminated string, so, we only copy up to (MAX_GAMEPAD_NAME_LENGTH - 1)
if (glfwJoystickPresent(i)) strncpy(CORE.Input.Gamepad.name[i], glfwGetJoystickName(i), MAX_GAMEPAD_NAME_LENGTH - 1);
}
//----------------------------------------------------------------------------
@ -1708,9 +1752,13 @@ static void ErrorCallback(int error, const char *description)
}
// GLFW3 WindowSize Callback, runs when window is resizedLastFrame
// NOTE: Window resizing not allowed by default
// NOTE: Window resizing not enabled by default, use SetConfigFlags()
static void WindowSizeCallback(GLFWwindow *window, int width, int height)
{
// WARNING: On window minimization, callback is called,
// but we don't want to change internal screen values, it breaks things
if ((width == 0) || (height == 0)) return;
// Reset viewport and projection matrix for new size
SetupViewport(width, height);
@ -1720,12 +1768,22 @@ static void WindowSizeCallback(GLFWwindow *window, int width, int height)
if (IsWindowFullscreen()) return;
// Set current screen size
// if we are doing automatic DPI scaling, then the "screen" size is divided by the window scale
if (IsWindowState(FLAG_WINDOW_HIGHDPI))
{
width = (int)(width/GetWindowScaleDPI().x);
height = (int)(height/GetWindowScaleDPI().y);
}
// Set render size
CORE.Window.render.width = width;
CORE.Window.render.height = height;
// Set current screen size
CORE.Window.screen.width = width;
CORE.Window.screen.height = height;
// NOTE: Postprocessing texture is not scaled to new size
// WARNING: If using a render texture, it is not scaled to new size
}
static void WindowPosCallback(GLFWwindow* window, int x, int y)
{
@ -1918,11 +1976,14 @@ static void JoystickCallback(int jid, int event)
{
if (event == GLFW_CONNECTED)
{
strcpy(CORE.Input.Gamepad.name[jid], glfwGetJoystickName(jid));
// WARNING: If glfwGetJoystickName() is longer than MAX_GAMEPAD_NAME_LENGTH,
// we can get a not-NULL terminated string, so, we clean destination and only copy up to -1
memset(CORE.Input.Gamepad.name[jid], 0, MAX_GAMEPAD_NAME_LENGTH);
strncpy(CORE.Input.Gamepad.name[jid], glfwGetJoystickName(jid), MAX_GAMEPAD_NAME_LENGTH - 1);
}
else if (event == GLFW_DISCONNECTED)
{
memset(CORE.Input.Gamepad.name[jid], 0, 64);
memset(CORE.Input.Gamepad.name[jid], 0, MAX_GAMEPAD_NAME_LENGTH);
}
}

File diff suppressed because it is too large Load diff

View file

@ -23,13 +23,13 @@
* Custom flag for rcore on target platform -not used-
*
* DEPENDENCIES:
* - SDL 2 or SLD 3 (main library): Windowing and inputs management
* - SDL 2 or SDL 3 (main library): Windowing and inputs management
* - gestures: Gestures system for touch-ready devices (or simulated from mouse inputs)
*
*
* LICENSE: zlib/libpng
*
* Copyright (c) 2013-2024 Ramon Santamaria (@raysan5) and contributors
* Copyright (c) 2013-2025 Ramon Santamaria (@raysan5) and contributors
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
@ -68,13 +68,12 @@
#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))
#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
//----------------------------------------------------------------------------------
@ -83,6 +82,7 @@ typedef struct {
SDL_GLContext glContext;
SDL_GameController *gamepad[MAX_GAMEPADS];
SDL_JoystickID gamepadId[MAX_GAMEPADS]; // Joystick instance ids
SDL_Cursor *cursor;
bool cursorRelative;
} PlatformData;
@ -240,16 +240,15 @@ static const int CursorsLUT[] = {
// SDL3 Migration Layer made to avoid `ifdefs` inside functions when we can.
#ifdef PLATFORM_DESKTOP_SDL3
#if defined(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
// 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
@ -260,27 +259,29 @@ static const int CursorsLUT[] = {
// 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
//
// 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)
// SDL2 implementation for SDL3 function
const char *SDL_GameControllerNameForIndex(int joystickIndex)
{
// NOTE: SDL3 uses the IDs itself (SDL_JoystickID) instead of SDL2 joystick_index
const char* name = NULL;
const char *name = NULL;
int numJoysticks = 0;
SDL_JoystickID *joysticks = SDL_GetJoysticks(&numJoysticks);
if (joysticks) {
if (joystickIndex < numJoysticks) {
if (joysticks)
{
if (joystickIndex < numJoysticks)
{
SDL_JoystickID instance_id = joysticks[joystickIndex];
name = SDL_GetGamepadNameForID(instance_id);
}
SDL_free(joysticks);
}
return name;
}
@ -288,45 +289,40 @@ int SDL_GetNumVideoDisplays(void)
{
int monitorCount = 0;
SDL_DisplayID *displays = SDL_GetDisplays(&monitorCount);
// Safe because If `mem` is NULL, SDL_free does nothing.
// Safe because If `mem` is NULL, SDL_free does nothing
SDL_free(displays);
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) {
// 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");
}
return stateBefore;
}
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;
}
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));
@ -337,11 +333,14 @@ 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.
// returns 0 on success or a negative error code on failure
int SDL_GetDisplayDPI(int displayIndex, float * ddpi, float * hdpi, float * vdpi) {
float dpi = SDL_GetWindowDisplayScale(platform.window) * 96.0;
int SDL_GetDisplayDPI(int displayIndex, float *ddpi, float *hdpi, float *vdpi)
{
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;
}
@ -368,17 +367,13 @@ int SDL_NumJoysticks(void)
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
@ -398,7 +393,6 @@ bool SDL_GetRelativeMouseMode_Adapter(void)
#define SDL_GetRelativeMouseMode SDL_GetRelativeMouseMode_Adapter
int SDL_GetNumTouchFingers(SDL_TouchID touchID)
{
// SDL_Finger **SDL_GetTouchFingers(SDL_TouchID touchID, int *count)
@ -412,16 +406,16 @@ int SDL_GetNumTouchFingers(SDL_TouchID touchID)
// 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) {
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
//----------------------------------------------------------------------------------
@ -452,7 +446,7 @@ 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 defined(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))
@ -479,7 +473,8 @@ 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 defined(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))
@ -503,25 +498,28 @@ void ToggleBorderlessWindowed(void)
void MaximizeWindow(void)
{
SDL_MaximizeWindow(platform.window);
CORE.Window.flags |= FLAG_WINDOW_MAXIMIZED;
if ((CORE.Window.flags & FLAG_WINDOW_MAXIMIZED) == 0) CORE.Window.flags |= FLAG_WINDOW_MAXIMIZED;
}
// Set window state: minimized
void MinimizeWindow(void)
{
SDL_MinimizeWindow(platform.window);
CORE.Window.flags |= FLAG_WINDOW_MINIMIZED;
if ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) == 0) CORE.Window.flags |= FLAG_WINDOW_MINIMIZED;
}
// Set window state: not minimized/maximized
// Restore window from being minimized/maximized
void RestoreWindow(void)
{
SDL_ShowWindow(platform.window);
SDL_RestoreWindow(platform.window);
// CORE.Window.flags will be removed on PollInputEvents()
}
// Set window configuration state using flags
void SetWindowState(unsigned int flags)
{
if (!CORE.Window.ready) TRACELOG(LOG_WARNING, "WINDOW: SetWindowState does nothing before window initialization, Use \"SetConfigFlags\" instead");
CORE.Window.flags |= flags;
if (flags & FLAG_VSYNC_HINT)
@ -532,7 +530,8 @@ 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 defined(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))
@ -575,7 +574,7 @@ void SetWindowState(unsigned int flags)
}
if (flags & FLAG_WINDOW_ALWAYS_RUN)
{
TRACELOG(LOG_WARNING, "SetWindowState() - FLAG_WINDOW_ALWAYS_RUN is not supported on PLATFORM_DESKTOP_SDL");
CORE.Window.flags |= FLAG_WINDOW_ALWAYS_RUN;
}
if (flags & FLAG_WINDOW_TRANSPARENT)
{
@ -595,7 +594,8 @@ 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 defined(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))
@ -661,7 +661,7 @@ void ClearWindowState(unsigned int flags)
}
if (flags & FLAG_WINDOW_ALWAYS_RUN)
{
TRACELOG(LOG_WARNING, "ClearWindowState() - FLAG_WINDOW_ALWAYS_RUN is not supported on PLATFORM_DESKTOP_SDL");
CORE.Window.flags &= ~FLAG_WINDOW_ALWAYS_RUN;
}
if (flags & FLAG_WINDOW_TRANSPARENT)
{
@ -704,70 +704,84 @@ void SetWindowIcon(Image image)
switch (image.format)
{
case PIXELFORMAT_UNCOMPRESSED_GRAYSCALE:
{
rmask = 0xFF, gmask = 0;
bmask = 0, amask = 0;
depth = 8, pitch = image.width;
break;
} break;
case PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA:
{
rmask = 0xFF, gmask = 0xFF00;
bmask = 0, amask = 0;
depth = 16, pitch = image.width*2;
break;
} break;
case PIXELFORMAT_UNCOMPRESSED_R5G6B5:
{
rmask = 0xF800, gmask = 0x07E0;
bmask = 0x001F, amask = 0;
depth = 16, pitch = image.width*2;
break;
case PIXELFORMAT_UNCOMPRESSED_R8G8B8: // Uses BGR for 24-bit
rmask = 0x0000FF, gmask = 0x00FF00;
bmask = 0xFF0000, amask = 0;
} break;
case PIXELFORMAT_UNCOMPRESSED_R8G8B8:
{
// WARNING: SDL2 could be using BGR but SDL3 RGB
rmask = 0xFF0000, gmask = 0x00FF00;
bmask = 0x0000FF, amask = 0;
depth = 24, pitch = image.width*3;
break;
} break;
case PIXELFORMAT_UNCOMPRESSED_R5G5B5A1:
{
rmask = 0xF800, gmask = 0x07C0;
bmask = 0x003E, amask = 0x0001;
depth = 16, pitch = image.width*2;
break;
} break;
case PIXELFORMAT_UNCOMPRESSED_R4G4B4A4:
{
rmask = 0xF000, gmask = 0x0F00;
bmask = 0x00F0, amask = 0x000F;
depth = 16, pitch = image.width*2;
break;
} break;
case PIXELFORMAT_UNCOMPRESSED_R8G8B8A8:
{
rmask = 0xFF000000, gmask = 0x00FF0000;
bmask = 0x0000FF00, amask = 0x000000FF;
depth = 32, pitch = image.width*4;
break;
} break;
case PIXELFORMAT_UNCOMPRESSED_R32:
{
rmask = 0xFFFFFFFF, gmask = 0;
bmask = 0, amask = 0;
depth = 32, pitch = image.width*4;
break;
} break;
case PIXELFORMAT_UNCOMPRESSED_R32G32B32:
{
rmask = 0xFFFFFFFF, gmask = 0xFFFFFFFF;
bmask = 0xFFFFFFFF, amask = 0;
depth = 96, pitch = image.width*12;
break;
} break;
case PIXELFORMAT_UNCOMPRESSED_R32G32B32A32:
{
rmask = 0xFFFFFFFF, gmask = 0xFFFFFFFF;
bmask = 0xFFFFFFFF, amask = 0xFFFFFFFF;
depth = 128, pitch = image.width*16;
break;
} break;
case PIXELFORMAT_UNCOMPRESSED_R16:
{
rmask = 0xFFFF, gmask = 0;
bmask = 0, amask = 0;
depth = 16, pitch = image.width*2;
break;
} break;
case PIXELFORMAT_UNCOMPRESSED_R16G16B16:
{
rmask = 0xFFFF, gmask = 0xFFFF;
bmask = 0xFFFF, amask = 0;
depth = 48, pitch = image.width*6;
break;
} break;
case PIXELFORMAT_UNCOMPRESSED_R16G16B16A16:
{
rmask = 0xFFFF, gmask = 0xFFFF;
bmask = 0xFFFF, amask = 0xFFFF;
depth = 64, pitch = image.width*8;
break;
} break;
default: return; // Compressed formats are not supported
}
@ -818,7 +832,8 @@ 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 defined(PLATFORM_DESKTOP_SDL3) // Different style for success checking
if (SDL_GetDisplayUsableBounds(monitor, &usableBounds))
#else
if (SDL_GetDisplayUsableBounds(monitor, &usableBounds) == 0)
@ -915,7 +930,7 @@ int GetMonitorCount(void)
return monitorCount;
}
// Get number of monitors
// Get current monitor where window is placed
int GetCurrentMonitor(void)
{
int currentMonitor = 0;
@ -933,7 +948,8 @@ Vector2 GetMonitorPosition(int monitor)
if ((monitor >= 0) && (monitor < monitorCount))
{
SDL_Rect displayBounds;
#ifdef PLATFORM_DESKTOP_SDL3
#if defined(PLATFORM_DESKTOP_SDL3)
if (SDL_GetDisplayUsableBounds(monitor, &displayBounds))
#else
if (SDL_GetDisplayUsableBounds(monitor, &displayBounds) == 0)
@ -1104,53 +1120,55 @@ const char *GetClipboardText(void)
return buffer;
}
#if defined(SUPPORT_CLIPBOARD_IMAGE)
// Get clipboard image
Image GetClipboardImage(void)
{
Image image = { 0 };
#if defined(SUPPORT_CLIPBOARD_IMAGE)
// Let's hope compiler put these arrays in static memory
const char *image_formats[] = {
const char *imageFormats[] = {
"image/bmp",
"image/png",
"image/jpg",
"image/tiff",
};
const char *image_extensions[] = {
const char *imageExtensions[] = {
".bmp",
".png",
".jpg",
".tiff",
};
Image image = {0};
size_t dataSize = 0;
void *fileData = NULL;
for (int i = 0; i < SDL_arraysize(image_formats); ++i)
for (int i = 0; i < SDL_arraysize(imageFormats); ++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);
// NOTE: This pointer should be free with SDL_free() at some point
fileData = SDL_GetClipboardData(imageFormats[i], &dataSize);
if (fileData)
{
image = LoadImageFromMemory(imageExtensions[i], fileData, dataSize);
if (IsImageValid(image))
{
TRACELOG(LOG_INFO, "Clipboard image: Got image from clipboard as a `%s` successfully", image_extensions[i]);
TRACELOG(LOG_INFO, "Clipboard image: Got image from clipboard as a `%s` successfully", imageExtensions[i]);
return image;
}
}
}
TRACELOG(LOG_WARNING, "Clipboard image: Couldn't get clipboard data. %s", SDL_GetError());
return image;
}
if (!IsImageValid(image)) TRACELOG(LOG_WARNING, "Clipboard image: Couldn't get clipboard data. Error: %s", SDL_GetError());
#endif
return image;
}
// Show mouse cursor
void ShowCursor(void)
{
#ifdef PLATFORM_DESKTOP_SDL3
#if defined(PLATFORM_DESKTOP_SDL3)
SDL_ShowCursor();
#else
SDL_ShowCursor(SDL_ENABLE);
@ -1161,7 +1179,7 @@ void ShowCursor(void)
// Hides mouse cursor
void HideCursor(void)
{
#ifdef PLATFORM_DESKTOP_SDL3
#if defined(PLATFORM_DESKTOP_SDL3)
SDL_HideCursor();
#else
SDL_ShowCursor(SDL_DISABLE);
@ -1174,7 +1192,7 @@ void EnableCursor(void)
{
SDL_SetRelativeMouseMode(SDL_FALSE);
#ifdef PLATFORM_DESKTOP_SDL3
#if defined(PLATFORM_DESKTOP_SDL3)
// SDL_ShowCursor() has been split into three functions: SDL_ShowCursor(), SDL_HideCursor(), and SDL_CursorVisible()
SDL_ShowCursor();
#else
@ -1275,7 +1293,7 @@ const char *GetKeyName(int key)
static void UpdateTouchPointsSDL(SDL_TouchFingerEvent event)
{
#ifdef PLATFORM_DESKTOP_SDL3 // SDL3
#if defined(PLATFORM_DESKTOP_SDL3) // SDL3
int count = 0;
SDL_Finger **fingers = SDL_GetTouchFingers(event.touchID, &count);
CORE.Input.Touch.pointCount = count;
@ -1288,7 +1306,9 @@ static void UpdateTouchPointsSDL(SDL_TouchFingerEvent event)
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);
@ -1345,7 +1365,7 @@ void PollInputEvents(void)
for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.previousTouchState[i] = CORE.Input.Touch.currentTouchState[i];
// Map touch position to mouse position for convenience
CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition;
if (CORE.Input.Touch.pointCount == 0) CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition;
int touchAction = -1; // 0-TOUCH_ACTION_UP, 1-TOUCH_ACTION_DOWN, 2-TOUCH_ACTION_MOVE
bool realTouch = false; // Flag to differentiate real touch gestures from mouse ones
@ -1375,6 +1395,12 @@ void PollInputEvents(void)
CORE.Window.resizedLastFrame = false;
if ((CORE.Window.eventWaiting) || (((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) > 0) && ((CORE.Window.flags & FLAG_WINDOW_ALWAYS_RUN) == 0)))
{
SDL_WaitEvent(NULL);
CORE.Time.previous = GetTime();
}
SDL_Event event = { 0 };
while (SDL_PollEvent(&event) != 0)
{
@ -1393,7 +1419,8 @@ 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
#if defined(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);
@ -1407,7 +1434,8 @@ void PollInputEvents(void)
else if (CORE.Window.dropFileCount < 1024)
{
CORE.Window.dropFilepaths[CORE.Window.dropFileCount] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char));
#ifdef PLATFORM_DESKTOP_SDL3
#if defined(PLATFORM_DESKTOP_SDL3)
strcpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event.drop.data);
#else
strcpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event.drop.file);
@ -1422,7 +1450,7 @@ void PollInputEvents(void)
// Window events are also polled (Minimized, maximized, close...)
#ifndef PLATFORM_DESKTOP_SDL3
#ifndef PLATFORM_DESKTOP_SDL3
// SDL3 states:
// The SDL_WINDOWEVENT_* events have been moved to top level events,
// and SDL_WINDOWEVENT has been removed.
@ -1432,19 +1460,45 @@ void PollInputEvents(void)
{
switch (event.window.event)
{
#endif
#endif
case SDL_WINDOWEVENT_RESIZED:
case SDL_WINDOWEVENT_SIZE_CHANGED:
{
const int width = event.window.data1;
const int height = event.window.data2;
SetupViewport(width, height);
CORE.Window.screen.width = width;
CORE.Window.screen.height = height;
// if we are doing automatic DPI scaling, then the "screen" size is divided by the window scale
if (IsWindowState(FLAG_WINDOW_HIGHDPI))
{
CORE.Window.screen.width = (int)(width / GetWindowScaleDPI().x);
CORE.Window.screen.height = (int)(height / GetWindowScaleDPI().y);
}
else
{
CORE.Window.screen.width = width;
CORE.Window.screen.height = height;
}
CORE.Window.currentFbo.width = width;
CORE.Window.currentFbo.height = height;
CORE.Window.resizedLastFrame = true;
#ifndef PLATFORM_DESKTOP_SDL3
// Manually detect if the window was maximized (due to SDL2 restore being unreliable on some platforms) to remove the FLAG_WINDOW_MAXIMIZED accordingly
if ((CORE.Window.flags & FLAG_WINDOW_MAXIMIZED) > 0)
{
int borderTop = 0;
int borderLeft = 0;
int borderBottom = 0;
int borderRight = 0;
SDL_GetWindowBordersSize(platform.window, &borderTop, &borderLeft, &borderBottom, &borderRight);
SDL_Rect usableBounds;
SDL_GetDisplayUsableBounds(SDL_GetWindowDisplayIndex(platform.window), &usableBounds);
if ((width + borderLeft + borderRight != usableBounds.w) && (height + borderTop + borderBottom != usableBounds.h)) CORE.Window.flags &= ~FLAG_WINDOW_MAXIMIZED;
}
#endif
} break;
case SDL_WINDOWEVENT_ENTER:
{
CORE.Input.Mouse.cursorOnScreen = true;
@ -1453,16 +1507,49 @@ void PollInputEvents(void)
{
CORE.Input.Mouse.cursorOnScreen = false;
} break;
case SDL_WINDOWEVENT_HIDDEN:
case SDL_WINDOWEVENT_MINIMIZED:
case SDL_WINDOWEVENT_FOCUS_LOST:
case SDL_WINDOWEVENT_SHOWN:
case SDL_WINDOWEVENT_FOCUS_GAINED:
{
if ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) == 0) CORE.Window.flags |= FLAG_WINDOW_MINIMIZED;
} break;
case SDL_WINDOWEVENT_MAXIMIZED:
{
if ((CORE.Window.flags & FLAG_WINDOW_MAXIMIZED) == 0) CORE.Window.flags |= FLAG_WINDOW_MAXIMIZED;
} break;
case SDL_WINDOWEVENT_RESTORED:
#ifdef PLATFORM_DESKTOP_SDL3
break;
#else
{
if ((SDL_GetWindowFlags(platform.window) & SDL_WINDOW_MINIMIZED) == 0)
{
if ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) > 0) CORE.Window.flags &= ~FLAG_WINDOW_MINIMIZED;
}
#ifdef PLATFORM_DESKTOP_SDL3
if ((SDL_GetWindowFlags(platform.window) & SDL_WINDOW_MAXIMIZED) == 0)
{
if ((CORE.Window.flags & SDL_WINDOW_MAXIMIZED) > 0) CORE.Window.flags &= ~SDL_WINDOW_MAXIMIZED;
}
#endif
} break;
case SDL_WINDOWEVENT_HIDDEN:
{
if ((CORE.Window.flags & FLAG_WINDOW_HIDDEN) == 0) CORE.Window.flags |= FLAG_WINDOW_HIDDEN;
} break;
case SDL_WINDOWEVENT_SHOWN:
{
if ((CORE.Window.flags & FLAG_WINDOW_HIDDEN) > 0) CORE.Window.flags &= ~FLAG_WINDOW_HIDDEN;
} break;
case SDL_WINDOWEVENT_FOCUS_GAINED:
{
if ((CORE.Window.flags & FLAG_WINDOW_UNFOCUSED) > 0) CORE.Window.flags &= ~FLAG_WINDOW_UNFOCUSED;
} break;
case SDL_WINDOWEVENT_FOCUS_LOST:
{
if ((CORE.Window.flags & FLAG_WINDOW_UNFOCUSED) == 0) CORE.Window.flags |= FLAG_WINDOW_UNFOCUSED;
} break;
#ifndef PLATFORM_DESKTOP_SDL3
default: break;
}
} break;
@ -1471,7 +1558,7 @@ void PollInputEvents(void)
// Keyboard events
case SDL_KEYDOWN:
{
#ifdef PLATFORM_DESKTOP_SDL3
#if defined(PLATFORM_DESKTOP_SDL3)
// SDL3 Migration: The following structures have been removed: * SDL_Keysym
KeyboardKey key = ConvertScancodeToKey(event.key.scancode);
#else
@ -1502,7 +1589,7 @@ void PollInputEvents(void)
case SDL_KEYUP:
{
#ifdef PLATFORM_DESKTOP_SDL3
#if defined(PLATFORM_DESKTOP_SDL3)
KeyboardKey key = ConvertScancodeToKey(event.key.scancode);
#else
KeyboardKey key = ConvertScancodeToKey(event.key.keysym.scancode);
@ -1597,11 +1684,12 @@ void PollInputEvents(void)
// Check gamepad events
case SDL_JOYDEVICEADDED:
{
int jid = event.jdevice.which;
int jid = event.jdevice.which; // Joystick device index
if (!CORE.Input.Gamepad.ready[jid] && (jid < MAX_GAMEPADS))
if (CORE.Input.Gamepad.ready[jid] && (jid < MAX_GAMEPADS))
{
platform.gamepad[jid] = SDL_GameControllerOpen(jid);
platform.gamepadId[jid] = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(platform.gamepad[jid]));
if (platform.gamepad[jid])
{
@ -1609,8 +1697,8 @@ void PollInputEvents(void)
CORE.Input.Gamepad.axisCount[jid] = SDL_JoystickNumAxes(SDL_GameControllerGetJoystick(platform.gamepad[jid]));
CORE.Input.Gamepad.axisState[jid][GAMEPAD_AXIS_LEFT_TRIGGER] = -1.0f;
CORE.Input.Gamepad.axisState[jid][GAMEPAD_AXIS_RIGHT_TRIGGER] = -1.0f;
strncpy(CORE.Input.Gamepad.name[jid], SDL_GameControllerNameForIndex(jid), 63);
CORE.Input.Gamepad.name[jid][63] = '\0';
memset(CORE.Input.Gamepad.name[jid], 0, MAX_GAMEPAD_NAME_LENGTH);
strncpy(CORE.Input.Gamepad.name[jid], SDL_GameControllerNameForIndex(jid), MAX_GAMEPAD_NAME_LENGTH - 1);
}
else
{
@ -1620,14 +1708,18 @@ void PollInputEvents(void)
} break;
case SDL_JOYDEVICEREMOVED:
{
int jid = event.jdevice.which;
int jid = event.jdevice.which; // Joystick instance id
if (jid == SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(platform.gamepad[jid])))
for (int i = 0; i < MAX_GAMEPADS; i++)
{
SDL_GameControllerClose(platform.gamepad[jid]);
platform.gamepad[jid] = SDL_GameControllerOpen(0);
CORE.Input.Gamepad.ready[jid] = false;
memset(CORE.Input.Gamepad.name[jid], 0, 64);
if (platform.gamepadId[i] == jid)
{
SDL_GameControllerClose(platform.gamepad[i]);
CORE.Input.Gamepad.ready[i] = false;
memset(CORE.Input.Gamepad.name[i], 0, MAX_GAMEPAD_NAME_LENGTH);
platform.gamepadId[i] = -1;
break;
}
}
} break;
case SDL_CONTROLLERBUTTONDOWN:
@ -1660,8 +1752,15 @@ void PollInputEvents(void)
if (button >= 0)
{
CORE.Input.Gamepad.currentButtonState[event.jbutton.which][button] = 1;
CORE.Input.Gamepad.lastButtonPressed = button;
for (int i = 0; i < MAX_GAMEPADS; i++)
{
if (platform.gamepadId[i] == event.jbutton.which)
{
CORE.Input.Gamepad.currentButtonState[i][button] = 1;
CORE.Input.Gamepad.lastButtonPressed = button;
break;
}
}
}
} break;
case SDL_CONTROLLERBUTTONUP:
@ -1694,8 +1793,15 @@ void PollInputEvents(void)
if (button >= 0)
{
CORE.Input.Gamepad.currentButtonState[event.jbutton.which][button] = 0;
if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0;
for (int i = 0; i < MAX_GAMEPADS; i++)
{
if (platform.gamepadId[i] == event.jbutton.which)
{
CORE.Input.Gamepad.currentButtonState[i][button] = 0;
if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0;
break;
}
}
}
} break;
case SDL_CONTROLLERAXISMOTION:
@ -1715,18 +1821,25 @@ void PollInputEvents(void)
if (axis >= 0)
{
// SDL axis value range is -32768 to 32767, we normalize it to RayLib's -1.0 to 1.0f range
float value = event.jaxis.value/(float)32767;
CORE.Input.Gamepad.axisState[event.jaxis.which][axis] = value;
// Register button state for triggers in addition to their axes
if ((axis == GAMEPAD_AXIS_LEFT_TRIGGER) || (axis == GAMEPAD_AXIS_RIGHT_TRIGGER))
for (int i = 0; i < MAX_GAMEPADS; i++)
{
int button = (axis == GAMEPAD_AXIS_LEFT_TRIGGER)? GAMEPAD_BUTTON_LEFT_TRIGGER_2 : GAMEPAD_BUTTON_RIGHT_TRIGGER_2;
int pressed = (value > 0.1f);
CORE.Input.Gamepad.currentButtonState[event.jaxis.which][button] = pressed;
if (pressed) CORE.Input.Gamepad.lastButtonPressed = button;
else if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0;
if (platform.gamepadId[i] == event.jaxis.which)
{
// SDL axis value range is -32768 to 32767, we normalize it to raylib's -1.0 to 1.0f range
float value = event.jaxis.value/(float)32767;
CORE.Input.Gamepad.axisState[i][axis] = value;
// Register button state for triggers in addition to their axes
if ((axis == GAMEPAD_AXIS_LEFT_TRIGGER) || (axis == GAMEPAD_AXIS_RIGHT_TRIGGER))
{
int button = (axis == GAMEPAD_AXIS_LEFT_TRIGGER)? GAMEPAD_BUTTON_LEFT_TRIGGER_2 : GAMEPAD_BUTTON_RIGHT_TRIGGER_2;
int pressed = (value > 0.1f);
CORE.Input.Gamepad.currentButtonState[i][button] = pressed;
if (pressed) CORE.Input.Gamepad.lastButtonPressed = button;
else if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0;
}
break;
}
}
}
} break;
@ -1858,7 +1971,7 @@ int InitPlatform(void)
}
// Init window
#ifdef PLATFORM_DESKTOP_SDL3
#if defined(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);
@ -1906,9 +2019,15 @@ int InitPlatform(void)
// Initialize input events system
//----------------------------------------------------------------------------
// Initialize gamepads
for (int i = 0; i < MAX_GAMEPADS; i++)
{
platform.gamepadId[i] = -1; // Set all gamepad initial instance ids as invalid to not conflict with instance id zero
}
for (int i = 0; (i < SDL_NumJoysticks()) && (i < MAX_GAMEPADS); i++)
{
platform.gamepad[i] = SDL_GameControllerOpen(i);
platform.gamepadId[i] = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(platform.gamepad[i]));
if (platform.gamepad[i])
{
@ -1916,8 +2035,8 @@ int InitPlatform(void)
CORE.Input.Gamepad.axisCount[i] = SDL_JoystickNumAxes(SDL_GameControllerGetJoystick(platform.gamepad[i]));
CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_LEFT_TRIGGER] = -1.0f;
CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_RIGHT_TRIGGER] = -1.0f;
strncpy(CORE.Input.Gamepad.name[i], SDL_GameControllerNameForIndex(i), 63);
CORE.Input.Gamepad.name[i][63] = '\0';
strncpy(CORE.Input.Gamepad.name[i], SDL_GameControllerNameForIndex(i), MAX_GAMEPAD_NAME_LENGTH - 1);
CORE.Input.Gamepad.name[i][MAX_GAMEPAD_NAME_LENGTH - 1] = '\0';
}
else TRACELOG(LOG_WARNING, "PLATFORM: Unable to open game controller [ERROR: %s]", SDL_GetError());
}
@ -1946,11 +2065,10 @@ int InitPlatform(void)
CORE.Storage.basePath = SDL_GetBasePath(); // Alternative: GetWorkingDirectory();
//----------------------------------------------------------------------------
#ifdef PLATFORM_DESKTOP_SDL3
#if defined(PLATFORM_DESKTOP_SDL3)
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (SDL3): Initialized successfully");
#else
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (SDL): Initialized successfully");
TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (SDL2): Initialized successfully");
#endif
return 0;
@ -1968,7 +2086,7 @@ void ClosePlatform(void)
// Scancode to keycode mapping
static KeyboardKey ConvertScancodeToKey(SDL_Scancode sdlScancode)
{
if (sdlScancode >= 0 && sdlScancode < SCANCODE_MAPPED_NUM)
if ((sdlScancode >= 0) && (sdlScancode < SCANCODE_MAPPED_NUM))
{
return mapScancodeToKey[sdlScancode];
}

View file

@ -29,7 +29,7 @@
*
* LICENSE: zlib/libpng
*
* Copyright (c) 2013-2024 Ramon Santamaria (@raysan5) and contributors
* Copyright (c) 2013-2025 Ramon Santamaria (@raysan5) and contributors
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
@ -125,7 +125,7 @@ typedef struct {
// Gamepad data
int gamepadStreamFd[MAX_GAMEPADS]; // Gamepad device file descriptor
int gamepadAbsAxisRange[MAX_GAMEPADS][MAX_GAMEPAD_AXIS][2]; // [0] = min, [1] = range value of the axis
int gamepadAbsAxisRange[MAX_GAMEPADS][MAX_GAMEPAD_AXES][2]; // [0] = min, [1] = range value of the axes
int gamepadAbsAxisMap[MAX_GAMEPADS][ABS_CNT]; // Maps the axes gamepads from the evdev api to a sequential one
int gamepadCount; // The number of gamepads registered
} PlatformData;
@ -278,7 +278,7 @@ void MinimizeWindow(void)
TRACELOG(LOG_WARNING, "MinimizeWindow() not available on target platform");
}
// Set window state: not minimized/maximized
// Restore window from being minimized/maximized
void RestoreWindow(void)
{
TRACELOG(LOG_WARNING, "RestoreWindow() not available on target platform");
@ -372,7 +372,7 @@ int GetMonitorCount(void)
return 1;
}
// Get number of monitors
// Get current monitor where window is placed
int GetCurrentMonitor(void)
{
TRACELOG(LOG_WARNING, "GetCurrentMonitor() not implemented on target platform");
@ -623,7 +623,7 @@ int SetGamepadMappings(const char *mappings)
// Set gamepad vibration
void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float duration)
{
TRACELOG(LOG_WARNING, "GamepadSetVibration() not implemented on target platform");
TRACELOG(LOG_WARNING, "SetGamepadVibration() not implemented on target platform");
}
// Set mouse position XY
@ -736,20 +736,24 @@ int InitPlatform(void)
#if defined(DEFAULT_GRAPHIC_DEVICE_DRM)
platform.fd = open(DEFAULT_GRAPHIC_DEVICE_DRM, O_RDWR);
if (platform.fd != -1) TRACELOG(LOG_INFO, "DISPLAY: Default graphic device DRM opened successfully");
#else
TRACELOG(LOG_INFO, "DISPLAY: No graphic card set, trying platform-gpu-card");
TRACELOG(LOG_WARNING, "DISPLAY: No graphic card set, trying platform-gpu-card");
platform.fd = open("/dev/dri/by-path/platform-gpu-card", O_RDWR); // VideoCore VI (Raspberry Pi 4)
if (platform.fd != -1) TRACELOG(LOG_INFO, "DISPLAY: platform-gpu-card opened successfully");
if ((platform.fd == -1) || (drmModeGetResources(platform.fd) == NULL))
{
TRACELOG(LOG_INFO, "DISPLAY: Failed to open platform-gpu-card, trying card1");
TRACELOG(LOG_WARNING, "DISPLAY: Failed to open platform-gpu-card, trying card1");
platform.fd = open("/dev/dri/card1", O_RDWR); // Other Embedded
if (platform.fd != -1) TRACELOG(LOG_INFO, "DISPLAY: card1 opened successfully");
}
if ((platform.fd == -1) || (drmModeGetResources(platform.fd) == NULL))
{
TRACELOG(LOG_INFO, "DISPLAY: Failed to open graphic card1, trying card0");
TRACELOG(LOG_WARNING, "DISPLAY: Failed to open graphic card1, trying card0");
platform.fd = open("/dev/dri/card0", O_RDWR); // VideoCore IV (Raspberry Pi 1-3)
if (platform.fd != -1) TRACELOG(LOG_INFO, "DISPLAY: card0 opened successfully");
}
#endif
@ -899,18 +903,17 @@ int InitPlatform(void)
TRACELOG(LOG_INFO, "DISPLAY: Trying to enable MSAA x4");
}
const EGLint framebufferAttribs[] =
{
EGL_RENDERABLE_TYPE, (rlGetVersion() == RL_OPENGL_ES_30)? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT, // Type of context support
EGL_SURFACE_TYPE, EGL_WINDOW_BIT, // Don't use it on Android!
const EGLint framebufferAttribs[] = {
EGL_RENDERABLE_TYPE, (rlGetVersion() == RL_OPENGL_ES_30)? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT, // Type of context support
EGL_SURFACE_TYPE, EGL_WINDOW_BIT, // Don't use it on Android!
EGL_RED_SIZE, 8, // RED color bit depth (alternative: 5)
EGL_GREEN_SIZE, 8, // GREEN color bit depth (alternative: 6)
EGL_BLUE_SIZE, 8, // BLUE color bit depth (alternative: 5)
EGL_ALPHA_SIZE, 8, // ALPHA bit depth (required for transparent framebuffer)
//EGL_TRANSPARENT_TYPE, EGL_NONE, // Request transparent framebuffer (EGL_TRANSPARENT_RGB does not work on RPI)
EGL_DEPTH_SIZE, 16, // Depth buffer size (Required to use Depth testing!)
EGL_DEPTH_SIZE, 24, // Depth buffer size (Required to use Depth testing!)
//EGL_STENCIL_SIZE, 8, // Stencil buffer size
EGL_SAMPLE_BUFFERS, sampleBuffer, // Activate MSAA
EGL_SAMPLE_BUFFERS, sampleBuffer, // Activate MSAA
EGL_SAMPLES, samples, // 4x Antialiasing if activated (Free on MALI GPUs)
EGL_NONE
};
@ -946,7 +949,7 @@ int InitPlatform(void)
TRACELOG(LOG_TRACE, "DISPLAY: EGL configs available: %d", numConfigs);
EGLConfig *configs = RL_CALLOC(numConfigs, sizeof(*configs));
EGLConfig *configs = (EGLConfig *)RL_CALLOC(numConfigs, sizeof(*configs));
if (!configs)
{
TRACELOG(LOG_WARNING, "DISPLAY: Failed to get memory for EGL configs");
@ -1372,7 +1375,7 @@ static void InitEvdevInput(void)
if ((strncmp("event", entity->d_name, strlen("event")) == 0) || // Search for devices named "event*"
(strncmp("mouse", entity->d_name, strlen("mouse")) == 0)) // Search for devices named "mouse*"
{
sprintf(path, "%s%s", DEFAULT_EVDEV_PATH, entity->d_name);
snprintf(path, MAX_FILEPATH_LENGTH, "%s%s", DEFAULT_EVDEV_PATH, entity->d_name);
ConfigureEvdevDevice(path); // Configure the device if appropriate
}
}
@ -1401,7 +1404,7 @@ static void ConfigureEvdevDevice(char *device)
int fd = open(device, O_RDONLY | O_NONBLOCK);
if (fd < 0)
{
TRACELOG(LOG_WARNING, "DRM: Failed to open input device: %s", device);
TRACELOG(LOG_WARNING, "SYSTEM: Failed to open input device: %s", device);
return;
}
@ -1458,7 +1461,7 @@ static void ConfigureEvdevDevice(char *device)
// matter if we support them
else if (hasAbsXY && TEST_BIT(keyBits, BTN_MOUSE)) isMouse = true;
// If any of the common joystick axis is present, we assume it's a gamepad
// If any of the common joystick axes are present, we assume it's a gamepad
else
{
for (int axis = (hasAbsXY? ABS_Z : ABS_X); axis < ABS_PRESSURE; axis++)
@ -1530,7 +1533,7 @@ static void ConfigureEvdevDevice(char *device)
platform.absRange.height = absinfo[ABS_Y].info.maximum - absinfo[ABS_Y].info.minimum;
}
}
else if (isGamepad && !isMouse && !isKeyboard && platform.gamepadCount < MAX_GAMEPADS)
else if (isGamepad && !isMouse && !isKeyboard && (platform.gamepadCount < MAX_GAMEPADS))
{
deviceKindStr = "gamepad";
int index = platform.gamepadCount++;
@ -1544,7 +1547,7 @@ static void ConfigureEvdevDevice(char *device)
if (absAxisCount > 0)
{
// TODO / NOTE
// So gamepad axis (as in the actual linux joydev.c) are just simply enumerated
// So gamepad axes (as in the actual linux joydev.c) are just simply enumerated
// and (at least for some input drivers like xpat) it's convention to use
// ABS_X, ABX_Y for one joystick ABS_RX, ABS_RY for the other and the Z axes for the
// shoulder buttons
@ -1679,7 +1682,7 @@ static void PollGamepadEvents(void)
TRACELOG(LOG_DEBUG, "INPUT: Gamepad %2i: Axis: %2i Value: %i", i, axisRaylib, event.value);
if (axisRaylib < MAX_GAMEPAD_AXIS)
if (axisRaylib < MAX_GAMEPAD_AXES)
{
int min = platform.gamepadAbsAxisRange[i][event.code][0];
int range = platform.gamepadAbsAxisRange[i][event.code][1];
@ -1894,7 +1897,7 @@ static int FindExactConnectorMode(const drmModeConnector *connector, uint width,
TRACELOG(LOG_TRACE, "DISPLAY: DRM Mode %d %ux%u@%u %s", i, mode->hdisplay, mode->vdisplay, mode->vrefresh, (mode->flags & DRM_MODE_FLAG_INTERLACE)? "interlaced" : "progressive");
if ((mode->flags & DRM_MODE_FLAG_INTERLACE) && (!allowInterlaced)) continue;
if ((mode->flags & DRM_MODE_FLAG_INTERLACE) && !allowInterlaced) continue;
if ((mode->hdisplay == width) && (mode->vdisplay == height) && (mode->vrefresh == fps)) return i;
}
@ -1924,7 +1927,7 @@ static int FindNearestConnectorMode(const drmModeConnector *connector, uint widt
continue;
}
if ((mode->flags & DRM_MODE_FLAG_INTERLACE) && (!allowInterlaced))
if ((mode->flags & DRM_MODE_FLAG_INTERLACE) && !allowInterlaced)
{
TRACELOG(LOG_TRACE, "DISPLAY: DRM shouldn't choose an interlaced mode");
continue;