From c78e61faa86a445cadaed8949b1172e9c9a22da2 Mon Sep 17 00:00:00 2001 From: M374LX Date: Wed, 28 May 2025 19:35:08 -0300 Subject: [PATCH] Fix rcore_desktop_rgfw.c line terminators --- src/platforms/rcore_desktop_rgfw.c | 2832 ++++++++++++++-------------- 1 file changed, 1416 insertions(+), 1416 deletions(-) diff --git a/src/platforms/rcore_desktop_rgfw.c b/src/platforms/rcore_desktop_rgfw.c index 92e3def05..b51a4ffff 100644 --- a/src/platforms/rcore_desktop_rgfw.c +++ b/src/platforms/rcore_desktop_rgfw.c @@ -1,1416 +1,1416 @@ -/********************************************************************************************** -* -* rcore_desktop_rgfw - Functions to manage window, graphics device and inputs -* -* PLATFORM: RGFW -* - Windows (Win32, Win64) -* - Linux (X11/Wayland desktop mode) -* - MacOS (Cocoa) -* - HTML5 (Emscripten) -* - Others (untested) -* -* LIMITATIONS: -* - TODO -* -* POSSIBLE IMPROVEMENTS: -* - TODO -* -* ADDITIONAL NOTES: -* - TRACELOG() function is located in raylib [utils] module -* -* CONFIGURATION: -* #define RCORE_PLATFORM_RGFW -* Custom flag for rcore on target platform RGFW -* -* DEPENDENCIES: -* - RGFW.h (main library): Windowing and inputs management -* - gestures: Gestures system for touch-ready devices (or simulated from mouse inputs) -* -* -* LICENSE: zlib/libpng -* -* Copyright (c) 2013-2025 Ramon Santamaria (@raysan5), Colleague Riley 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. -* -* Permission is granted to anyone to use this software for any purpose, including commercial -* applications, and to alter it and redistribute it freely, subject to the following restrictions: -* -* 1. The origin of this software must not be misrepresented; you must not claim that you -* wrote the original software. If you use this software in a product, an acknowledgment -* in the product documentation would be appreciated but is not required. -* -* 2. Altered source versions must be plainly marked as such, and must not be misrepresented -* as being the original software. -* -* 3. This notice may not be removed or altered from any source distribution. -* -**********************************************************************************************/ - -#ifndef RAYLIB_H /* this should never actually happen, it's only here for IDEs */ -#include "raylib.h" -#include "../rcore.c" -#endif - -#if defined(PLATFORM_WEB_RGFW) -#define RGFW_NO_GL_HEADER -#endif - -#if defined(GRAPHICS_API_OPENGL_ES2) && !defined(PLATFORM_WEB_RGFW) - #define RGFW_OPENGL_ES2 -#endif - -void ShowCursor(void); -void CloseWindow(void); - -#if defined(__linux__) - #define _INPUT_EVENT_CODES_H -#endif - -#if defined(__unix__) || defined(__linux__) - #define _XTYPEDEF_FONT -#endif - -#define RGFW_IMPLEMENTATION - -#if defined(_WIN32) || defined(_WIN64) - #define WIN32_LEAN_AND_MEAN - #define Rectangle rectangle_win32 - #define CloseWindow CloseWindow_win32 - #define ShowCursor __imp_ShowCursor - #define _APISETSTRING_ - - #undef MAX_PATH - - __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int CodePage, unsigned long dwFlags, const char *lpMultiByteStr, int cbMultiByte, wchar_t *lpWideCharStr, int cchWideChar); -#endif - -#if defined(__APPLE__) - #define Point NSPOINT - #define Size NSSIZE -#endif - -#define RGFW_ALLOC RL_MALLOC -#define RGFW_FREE RL_FREE -#define RGFW_CALLOC RL_CALLOC - -#include "../external/RGFW.h" - -#if defined(_WIN32) || defined(_WIN64) - #undef DrawText - #undef ShowCursor - #undef CloseWindow - #undef Rectangle - - #undef MAX_PATH - #define MAX_PATH 1025 -#endif - -#if defined(__APPLE__) - #undef Point - #undef Size -#endif - -#include -#include // Required for: strcmp() - -//---------------------------------------------------------------------------------- -// Types and Structures Definition -//---------------------------------------------------------------------------------- -typedef struct { - RGFW_window *window; // Native display device (physical screen connection) - RGFW_monitor mon; -} PlatformData; - -//---------------------------------------------------------------------------------- -// Global Variables Definition -//---------------------------------------------------------------------------------- -extern CoreData CORE; // Global CORE state context - -static PlatformData platform = { 0 }; // Platform specific - -static bool RGFW_disableCursor = false; - -static const unsigned short keyMappingRGFW[] = { - [RGFW_keyNULL] = KEY_NULL, - [RGFW_return] = KEY_ENTER, - [RGFW_return] = KEY_ENTER, - [RGFW_apostrophe] = KEY_APOSTROPHE, - [RGFW_comma] = KEY_COMMA, - [RGFW_minus] = KEY_MINUS, - [RGFW_period] = KEY_PERIOD, - [RGFW_slash] = KEY_SLASH, - [RGFW_escape] = KEY_ESCAPE, - [RGFW_F1] = KEY_F1, - [RGFW_F2] = KEY_F2, - [RGFW_F3] = KEY_F3, - [RGFW_F4] = KEY_F4, - [RGFW_F5] = KEY_F5, - [RGFW_F6] = KEY_F6, - [RGFW_F7] = KEY_F7, - [RGFW_F8] = KEY_F8, - [RGFW_F9] = KEY_F9, - [RGFW_F10] = KEY_F10, - [RGFW_F11] = KEY_F11, - [RGFW_F12] = KEY_F12, - [RGFW_backtick] = KEY_GRAVE, - [RGFW_0] = KEY_ZERO, - [RGFW_1] = KEY_ONE, - [RGFW_2] = KEY_TWO, - [RGFW_3] = KEY_THREE, - [RGFW_4] = KEY_FOUR, - [RGFW_5] = KEY_FIVE, - [RGFW_6] = KEY_SIX, - [RGFW_7] = KEY_SEVEN, - [RGFW_8] = KEY_EIGHT, - [RGFW_9] = KEY_NINE, - [RGFW_equals] = KEY_EQUAL, - [RGFW_backSpace] = KEY_BACKSPACE, - [RGFW_tab] = KEY_TAB, - [RGFW_capsLock] = KEY_CAPS_LOCK, - [RGFW_shiftL] = KEY_LEFT_SHIFT, - [RGFW_controlL] = KEY_LEFT_CONTROL, - [RGFW_altL] = KEY_LEFT_ALT, - [RGFW_superL] = KEY_LEFT_SUPER, - #ifndef RGFW_MACOS - [RGFW_shiftR] = KEY_RIGHT_SHIFT, - [RGFW_altR] = KEY_RIGHT_ALT, - #endif - [RGFW_space] = KEY_SPACE, - - [RGFW_a] = KEY_A, - [RGFW_b] = KEY_B, - [RGFW_c] = KEY_C, - [RGFW_d] = KEY_D, - [RGFW_e] = KEY_E, - [RGFW_f] = KEY_F, - [RGFW_g] = KEY_G, - [RGFW_h] = KEY_H, - [RGFW_i] = KEY_I, - [RGFW_j] = KEY_J, - [RGFW_k] = KEY_K, - [RGFW_l] = KEY_L, - [RGFW_m] = KEY_M, - [RGFW_n] = KEY_N, - [RGFW_o] = KEY_O, - [RGFW_p] = KEY_P, - [RGFW_q] = KEY_Q, - [RGFW_r] = KEY_R, - [RGFW_s] = KEY_S, - [RGFW_t] = KEY_T, - [RGFW_u] = KEY_U, - [RGFW_v] = KEY_V, - [RGFW_w] = KEY_W, - [RGFW_x] = KEY_X, - [RGFW_y] = KEY_Y, - [RGFW_z] = KEY_Z, - [RGFW_bracket] = KEY_LEFT_BRACKET, - [RGFW_backSlash] = KEY_BACKSLASH, - [RGFW_closeBracket] = KEY_RIGHT_BRACKET, - [RGFW_semicolon] = KEY_SEMICOLON, - [RGFW_insert] = KEY_INSERT, - [RGFW_home] = KEY_HOME, - [RGFW_pageUp] = KEY_PAGE_UP, - [RGFW_delete] = KEY_DELETE, - [RGFW_end] = KEY_END, - [RGFW_pageDown] = KEY_PAGE_DOWN, - [RGFW_right] = KEY_RIGHT, - [RGFW_left] = KEY_LEFT, - [RGFW_down] = KEY_DOWN, - [RGFW_up] = KEY_UP, - [RGFW_numLock] = KEY_NUM_LOCK, - [RGFW_KP_Slash] = KEY_KP_DIVIDE, - [RGFW_multiply] = KEY_KP_MULTIPLY, - [RGFW_KP_Minus] = KEY_KP_SUBTRACT, - [RGFW_KP_Return] = KEY_KP_ENTER, - [RGFW_KP_1] = KEY_KP_1, - [RGFW_KP_2] = KEY_KP_2, - [RGFW_KP_3] = KEY_KP_3, - [RGFW_KP_4] = KEY_KP_4, - [RGFW_KP_5] = KEY_KP_5, - [RGFW_KP_6] = KEY_KP_6, - [RGFW_KP_7] = KEY_KP_7, - [RGFW_KP_8] = KEY_KP_8, - [RGFW_KP_9] = KEY_KP_9, - [RGFW_KP_0] = KEY_KP_0, - [RGFW_KP_Period] = KEY_KP_DECIMAL, - [RGFW_scrollLock] = KEY_SCROLL_LOCK, -}; - -//---------------------------------------------------------------------------------- -// Module Internal Functions Declaration -//---------------------------------------------------------------------------------- -int InitPlatform(void); // Initialize platform (graphics, inputs and more) -bool InitGraphicsDevice(void); // Initialize graphics device - -//---------------------------------------------------------------------------------- -// Module Functions Declaration -//---------------------------------------------------------------------------------- -// NOTE: Functions declaration is provided by raylib.h - -//---------------------------------------------------------------------------------- -// Module Functions Definition: Window and Graphics Device -//---------------------------------------------------------------------------------- - -// Check if application should close -bool WindowShouldClose(void) -{ - if (CORE.Window.shouldClose == false) - CORE.Window.shouldClose = RGFW_window_shouldClose(platform.window); - if (CORE.Window.ready) return CORE.Window.shouldClose; - else return true; -} - -// Toggle fullscreen mode -void ToggleFullscreen(void) -{ - if (!CORE.Window.fullscreen) - { - // Store previous window position (in case we exit fullscreen) - CORE.Window.previousPosition = CORE.Window.position; - CORE.Window.previousScreen = CORE.Window.screen; - - platform.mon = RGFW_window_getMonitor(platform.window); - CORE.Window.fullscreen = true; - CORE.Window.flags |= FLAG_FULLSCREEN_MODE; - - RGFW_monitor_scaleToWindow(platform.mon, platform.window); - RGFW_window_setFullscreen(platform.window, 1); - } - else - { - CORE.Window.fullscreen = false; - CORE.Window.flags &= ~FLAG_FULLSCREEN_MODE; - - if (platform.mon.mode.area.w) - { - RGFW_monitor monitor = RGFW_window_getMonitor(platform.window); - RGFW_monitor_requestMode(monitor, platform.mon.mode, RGFW_monitorScale); - - platform.mon.mode.area.w = 0; - } - - // we update the window position right away - CORE.Window.position = CORE.Window.previousPosition; - RGFW_window_setFullscreen(platform.window, 0); - RGFW_window_move(platform.window, RGFW_POINT(CORE.Window.position.x, CORE.Window.position.y)); - RGFW_window_resize(platform.window, RGFW_AREA(CORE.Window.previousScreen.width, CORE.Window.previousScreen.height)); - } - - // Try to enable GPU V-Sync, so frames are limited to screen refresh rate (60Hz -> 60 FPS) - // NOTE: V-Sync can be enabled by graphic driver configuration - if (CORE.Window.flags & FLAG_VSYNC_HINT) RGFW_window_swapInterval(platform.window, 1); -} - -// Toggle borderless windowed mode -void ToggleBorderlessWindowed(void) -{ - if (CORE.Window.fullscreen) - { - CORE.Window.previousPosition = CORE.Window.position; - CORE.Window.previousScreen = CORE.Window.screen; - - RGFW_window_setBorder(platform.window, 0); - - RGFW_monitor mon = RGFW_window_getMonitor(platform.window); - RGFW_window_resize(platform.window, mon.mode.area); - } - else - { - RGFW_window_setBorder(platform.window, 1); - - CORE.Window.position = CORE.Window.previousPosition; - RGFW_window_resize(platform.window, RGFW_AREA(CORE.Window.previousScreen.width, CORE.Window.previousScreen.height)); - } - - CORE.Window.fullscreen = !CORE.Window.fullscreen; -} - -// Set window state: maximized, if resizable -void MaximizeWindow(void) -{ - RGFW_window_maximize(platform.window); -} - -// Set window state: minimized -void MinimizeWindow(void) -{ - RGFW_window_minimize(platform.window); -} - -// Restore window from being minimized/maximized -void RestoreWindow(void) -{ - if (!(CORE.Window.flags & FLAG_WINDOW_UNFOCUSED)) RGFW_window_focus(platform.window); - - RGFW_window_restore(platform.window); -} - -// 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) - { - RGFW_window_swapInterval(platform.window, 1); - } - if (flags & FLAG_FULLSCREEN_MODE) - { - if (!CORE.Window.fullscreen) ToggleFullscreen(); - } - if (flags & FLAG_WINDOW_RESIZABLE) - { - RGFW_window_setMaxSize(platform.window, RGFW_AREA(0, 0)); - RGFW_window_setMinSize(platform.window, RGFW_AREA(0, 0)); - } - if (flags & FLAG_WINDOW_UNDECORATED) - { - RGFW_window_setBorder(platform.window, 0); - } - if (flags & FLAG_WINDOW_HIDDEN) - { - RGFW_window_hide(platform.window); - } - if (flags & FLAG_WINDOW_MINIMIZED) - { - RGFW_window_minimize(platform.window); - } - if (flags & FLAG_WINDOW_MAXIMIZED) - { - RGFW_window_maximize(platform.window); - } - if (flags & FLAG_WINDOW_UNFOCUSED) - { - CORE.Window.flags |= FLAG_WINDOW_UNFOCUSED; - platform.window->_flags &= ~RGFW_windowFocusOnShow; - RGFW_window_setFlags(platform.window, platform.window->_flags); - } - if (flags & FLAG_WINDOW_TOPMOST) - { - RGFW_window_setFloating(platform.window, RGFW_TRUE); - } - if (flags & FLAG_WINDOW_ALWAYS_RUN) - { - CORE.Window.flags |= FLAG_WINDOW_ALWAYS_RUN; - } - if (flags & FLAG_WINDOW_TRANSPARENT) - { - TRACELOG(LOG_WARNING, "WINDOW: Framebuffer transparency can only be configured before window initialization"); - } - if (flags & FLAG_WINDOW_HIGHDPI) - { - TRACELOG(LOG_WARNING, "WINDOW: High DPI can only be configured before window initialization"); - } - if (flags & FLAG_WINDOW_MOUSE_PASSTHROUGH) - { - RGFW_window_setMousePassthrough(platform.window, 1); - } - if (flags & FLAG_BORDERLESS_WINDOWED_MODE) - { - ToggleBorderlessWindowed(); - } - if (flags & FLAG_MSAA_4X_HINT) - { - RGFW_setGLHint(RGFW_glSamples, 4); - } - if (flags & FLAG_INTERLACED_HINT) - { - TRACELOG(LOG_WARNING, "RPI: Interlaced mode can only be configured before window initialization"); - } -} - -// Clear window configuration state flags -void ClearWindowState(unsigned int flags) -{ - CORE.Window.flags &= ~flags; - - if (flags & FLAG_VSYNC_HINT) - { - RGFW_window_swapInterval(platform.window, 0); - } - if (flags & FLAG_FULLSCREEN_MODE) - { - if (CORE.Window.fullscreen) ToggleFullscreen(); - } - if (flags & FLAG_WINDOW_RESIZABLE) - { - RGFW_window_setMaxSize(platform.window, RGFW_AREA(platform.window->r.w, platform.window->r.h)); - RGFW_window_setMinSize(platform.window, RGFW_AREA(platform.window->r.w, platform.window->r.h)); - } - if (flags & FLAG_WINDOW_UNDECORATED) - { - RGFW_window_setBorder(platform.window, 1); - } - if (flags & FLAG_WINDOW_HIDDEN) - { - if (!(CORE.Window.flags & FLAG_WINDOW_UNFOCUSED)) RGFW_window_focus(platform.window); - - RGFW_window_show(platform.window); - } - if (flags & FLAG_WINDOW_MINIMIZED) - { - if (!(CORE.Window.flags & FLAG_WINDOW_UNFOCUSED)) RGFW_window_focus(platform.window); - - RGFW_window_restore(platform.window); - } - if (flags & FLAG_WINDOW_MAXIMIZED) - { - if (!(CORE.Window.flags & FLAG_WINDOW_UNFOCUSED)) RGFW_window_focus(platform.window); - - RGFW_window_restore(platform.window); - } - if (flags & FLAG_WINDOW_UNFOCUSED) - { - RGFW_window_setFlags(platform.window, platform.window->_flags | RGFW_windowFocusOnShow); - CORE.Window.flags &= ~FLAG_WINDOW_UNFOCUSED; - } - if (flags & FLAG_WINDOW_TOPMOST) - { - RGFW_window_setFloating(platform.window, RGFW_FALSE); - } - if (flags & FLAG_WINDOW_ALWAYS_RUN) - { - CORE.Window.flags &= ~FLAG_WINDOW_ALWAYS_RUN; - } - if (flags & FLAG_WINDOW_TRANSPARENT) - { - TRACELOG(LOG_WARNING, "WINDOW: Framebuffer transparency can only be configured before window initialization"); - } - if (flags & FLAG_WINDOW_HIGHDPI) - { - TRACELOG(LOG_WARNING, "WINDOW: High DPI can only be configured before window initialization"); - } - if (flags & FLAG_WINDOW_MOUSE_PASSTHROUGH) - { - RGFW_window_setMousePassthrough(platform.window, 0); - } - if (flags & FLAG_BORDERLESS_WINDOWED_MODE) - { - if (CORE.Window.fullscreen) ToggleBorderlessWindowed(); - } - if (flags & FLAG_MSAA_4X_HINT) - { - RGFW_setGLHint(RGFW_glSamples, 0); - } - if (flags & FLAG_INTERLACED_HINT) - { - TRACELOG(LOG_WARNING, "RPI: Interlaced mode can only be configured before window initialization"); - } -} - -int RGFW_formatToChannels(int format) -{ - switch (format) - { - case PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: - case PIXELFORMAT_UNCOMPRESSED_R16: // 16 bpp (1 channel - half float) - case PIXELFORMAT_UNCOMPRESSED_R32: // 32 bpp (1 channel - float) - return 1; - case PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: // 8*2 bpp (2 channels) - case PIXELFORMAT_UNCOMPRESSED_R5G6B5: // 16 bpp - case PIXELFORMAT_UNCOMPRESSED_R8G8B8: // 24 bpp - case PIXELFORMAT_UNCOMPRESSED_R5G5B5A1: // 16 bpp (1 bit alpha) - case PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: // 16 bpp (4 bit alpha) - case PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: // 32 bpp - return 2; - case PIXELFORMAT_UNCOMPRESSED_R32G32B32: // 32*3 bpp (3 channels - float) - case PIXELFORMAT_UNCOMPRESSED_R16G16B16: // 16*3 bpp (3 channels - half float) - case PIXELFORMAT_COMPRESSED_DXT1_RGB: // 4 bpp (no alpha) - case PIXELFORMAT_COMPRESSED_ETC1_RGB: // 4 bpp - case PIXELFORMAT_COMPRESSED_ETC2_RGB: // 4 bpp - case PIXELFORMAT_COMPRESSED_PVRT_RGB: // 4 bpp - return 3; - case PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: // 32*4 bpp (4 channels - float) - case PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: // 16*4 bpp (4 channels - half float) - case PIXELFORMAT_COMPRESSED_DXT1_RGBA: // 4 bpp (1 bit alpha) - case PIXELFORMAT_COMPRESSED_DXT3_RGBA: // 8 bpp - case PIXELFORMAT_COMPRESSED_DXT5_RGBA: // 8 bpp - case PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA: // 8 bpp - case PIXELFORMAT_COMPRESSED_PVRT_RGBA: // 4 bpp - case PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA: // 8 bpp - case PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA: // 2 bpp - return 4; - default: return 4; - } -} - -// Set icon for window -void SetWindowIcon(Image image) -{ - RGFW_window_setIcon(platform.window, image.data, RGFW_AREA(image.width, image.height), RGFW_formatToChannels(image.format)); -} - -// Set icon for window -void SetWindowIcons(Image *images, int count) -{ - if ((images == NULL) || (count <= 0)) - { - RGFW_window_setIcon(platform.window, NULL, RGFW_AREA(0, 0), 0); - } - else - { - Image *bigIcon = NULL; - Image *smallIcon = NULL; - - for (int i = 0; i < count; i++) - { - if ((bigIcon == NULL) || ((images[i].width > bigIcon->width) && (images[i].height > bigIcon->height))) bigIcon = &images[i]; - if ((smallIcon == NULL) || ((images[i].width < smallIcon->width) && (images[i].height > smallIcon->height))) smallIcon = &images[i]; - } - - if (smallIcon != NULL) RGFW_window_setIconEx(platform.window, smallIcon->data, RGFW_AREA(smallIcon->width, smallIcon->height), RGFW_formatToChannels(smallIcon->format), RGFW_iconWindow); - if (bigIcon != NULL) RGFW_window_setIconEx(platform.window, bigIcon->data, RGFW_AREA(bigIcon->width, bigIcon->height), RGFW_formatToChannels(bigIcon->format), RGFW_iconTaskbar); - } -} - -// Set title for window -void SetWindowTitle(const char *title) -{ - RGFW_window_setName(platform.window, (char *)title); - CORE.Window.title = title; -} - -// Set window position on screen (windowed mode) -void SetWindowPosition(int x, int y) -{ - RGFW_window_move(platform.window, RGFW_POINT(x, y)); -} - -// Set monitor for the current window -void SetWindowMonitor(int monitor) -{ - RGFW_window_moveToMonitor(platform.window, RGFW_getMonitors()[monitor]); -} - -// Set window minimum dimensions (FLAG_WINDOW_RESIZABLE) -void SetWindowMinSize(int width, int height) -{ - RGFW_window_setMinSize(platform.window, RGFW_AREA(width, height)); - CORE.Window.screenMin.width = width; - CORE.Window.screenMin.height = height; -} - -// Set window maximum dimensions (FLAG_WINDOW_RESIZABLE) -void SetWindowMaxSize(int width, int height) -{ - RGFW_window_setMaxSize(platform.window, RGFW_AREA(width, height)); - CORE.Window.screenMax.width = width; - CORE.Window.screenMax.height = height; -} - -// Set window dimensions -void SetWindowSize(int width, int height) -{ - CORE.Window.screen.width = width; - CORE.Window.screen.height = height; - - RGFW_window_resize(platform.window, RGFW_AREA(width, height)); -} - -// Set window opacity, value opacity is between 0.0 and 1.0 -void SetWindowOpacity(float opacity) -{ - RGFW_window_setOpacity(platform.window, opacity); -} - -// Set window focused -void SetWindowFocused(void) -{ - RGFW_window_focus(platform.window); -} - -// Get native window handle -void *GetWindowHandle(void) -{ - if (platform.window == NULL) return NULL; -#ifdef RGFW_WASM - return (void *)platform.window->src.ctx; -#else - return (void *)platform.window->src.window; -#endif -} - -// Get number of monitors -int GetMonitorCount(void) -{ - #define MAX_MONITORS_SUPPORTED 6 - - int count = MAX_MONITORS_SUPPORTED; - RGFW_monitor *mons = RGFW_getMonitors(); - - for (int i = 0; i < 6; i++) - { - if (!mons[i].x && !mons[i].y && !mons[i].mode.area.w && mons[i].mode.area.h) - { - count = i; - break; - } - } - - return count; -} - -// Get current monitor where window is placed -int GetCurrentMonitor(void) -{ - RGFW_monitor *mons = RGFW_getMonitors(); - RGFW_monitor mon = { 0 }; - - if (platform.window) mon = RGFW_window_getMonitor(platform.window); - else mon = RGFW_getPrimaryMonitor(); - - for (int i = 0; i < 6; i++) - { - if ((mons[i].x == mon.x) && (mons[i].y == mon.y)) return i; - } - - return 0; -} - -// Get selected monitor position -Vector2 GetMonitorPosition(int monitor) -{ - RGFW_monitor *mons = RGFW_getMonitors(); - - return (Vector2){ (float)mons[monitor].x, (float)mons[monitor].y }; -} - -// Get selected monitor width (currently used by monitor) -int GetMonitorWidth(int monitor) -{ - RGFW_monitor *mons = RGFW_getMonitors(); - - return mons[monitor].mode.area.w; -} - -// Get selected monitor height (currently used by monitor) -int GetMonitorHeight(int monitor) -{ - RGFW_monitor *mons = RGFW_getMonitors(); - - return mons[monitor].mode.area.h; -} - -// Get selected monitor physical width in millimetres -int GetMonitorPhysicalWidth(int monitor) -{ - RGFW_monitor *mons = RGFW_getMonitors(); - - return mons[monitor].physW; -} - -// Get selected monitor physical height in millimetres -int GetMonitorPhysicalHeight(int monitor) -{ - RGFW_monitor *mons = RGFW_getMonitors(); - - return (int)mons[monitor].physH; -} - -// Get selected monitor refresh rate -int GetMonitorRefreshRate(int monitor) -{ - RGFW_monitor *mons = RGFW_getMonitors(); - - return (int)mons[monitor].mode.refreshRate; -} - -// Get the human-readable, UTF-8 encoded name of the selected monitor -const char *GetMonitorName(int monitor) -{ - RGFW_monitor *mons = RGFW_getMonitors(); - - return mons[monitor].name; -} - -// Get window position XY on monitor -Vector2 GetWindowPosition(void) -{ - if (platform.window == NULL) return (Vector2){ 0.0f, 0.0f }; - return (Vector2){ (float)platform.window->r.x, (float)platform.window->r.y }; -} - -// Get window scale DPI factor for current monitor -Vector2 GetWindowScaleDPI(void) -{ - RGFW_monitor monitor = { 0 }; - - if (platform.window) monitor = RGFW_window_getMonitor(platform.window); - else monitor = RGFW_getPrimaryMonitor(); - - return (Vector2){ monitor.scaleX, monitor.scaleX }; -} - -// Set clipboard text content -void SetClipboardText(const char *text) -{ - RGFW_writeClipboard(text, strlen(text)); -} - -// Get clipboard text content -// NOTE: returned string is allocated and freed by RGFW -const char *GetClipboardText(void) -{ - return RGFW_readClipboard(NULL); -} - -#if defined(SUPPORT_CLIPBOARD_IMAGE) -#if defined(_WIN32) - #define WIN32_CLIPBOARD_IMPLEMENTATION - #define WINUSER_ALREADY_INCLUDED - #define WINBASE_ALREADY_INCLUDED - #define WINGDI_ALREADY_INCLUDED - #include "../external/win32_clipboard.h" -#endif -#endif - -// Get clipboard image -Image GetClipboardImage(void) -{ - Image image = { 0 }; - unsigned long long int dataSize = 0; - void *fileData = NULL; - -#if defined(SUPPORT_CLIPBOARD_IMAGE) -#if defined(_WIN32) - int width = 0; - int height = 0; - fileData = (void *)Win32GetClipboardImageData(&width, &height, &dataSize); - - if (fileData == NULL) TRACELOG(LOG_WARNING, "Clipboard image: Couldn't get clipboard data"); - else image = LoadImageFromMemory(".bmp", fileData, dataSize); -#else - TRACELOG(LOG_WARNING, "Clipboard image: PLATFORM_DESKTOP_RGFW doesn't implement GetClipboardImage() for this OS"); -#endif -#endif // SUPPORT_CLIPBOARD_IMAGE - - return image; -} - -// Show mouse cursor -void ShowCursor(void) -{ - RGFW_window_showMouse(platform.window, true); - CORE.Input.Mouse.cursorHidden = false; -} - -// Hides mouse cursor -void HideCursor(void) -{ - RGFW_window_showMouse(platform.window, false); - CORE.Input.Mouse.cursorHidden = true; -} - -// Enables cursor (unlock cursor) -void EnableCursor(void) -{ - RGFW_disableCursor = false; - RGFW_window_mouseUnhold(platform.window); - - // Set cursor position in the middle - SetMousePosition(CORE.Window.screen.width/2, CORE.Window.screen.height/2); - RGFW_window_showMouse(platform.window, true); - CORE.Input.Mouse.cursorHidden = false; -} - -// Disables cursor (lock cursor) -void DisableCursor(void) -{ - RGFW_disableCursor = true; - RGFW_window_mouseHold(platform.window, RGFW_AREA(0, 0)); - HideCursor(); -} - -// Swap back buffer with front buffer (screen drawing) -void SwapScreenBuffer(void) -{ - RGFW_window_swapBuffers(platform.window); -} - -//---------------------------------------------------------------------------------- -// Module Functions Definition: Misc -//---------------------------------------------------------------------------------- - -// Get elapsed time measure in seconds since InitTimer() -double GetTime(void) -{ - return RGFW_getTime(); -} - -// Open URL with default system browser (if available) -// NOTE: This function is only safe to use if you control the URL given. -// A user could craft a malicious string performing another action. -// Only call this function yourself not with user input or make sure to check the string yourself. -// Ref: https://github.com/raysan5/raylib/issues/686 -void OpenURL(const char *url) -{ - // Security check to (partially) avoid malicious code on target platform - if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character"); - else - { - // TODO: Open URL implementation - } -} - -//---------------------------------------------------------------------------------- -// Module Functions Definition: Inputs -//---------------------------------------------------------------------------------- - -// Set internal gamepad mappings -int SetGamepadMappings(const char *mappings) -{ - TRACELOG(LOG_WARNING, "SetGamepadMappings() unsupported on target platform"); - return 0; -} - -// Set gamepad vibration -void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float duration) -{ - TRACELOG(LOG_WARNING, "SetGamepadVibration() unsupported on target platform"); -} - -// Set mouse position XY -void SetMousePosition(int x, int y) -{ - RGFW_window_moveMouse(platform.window, RGFW_POINT(x, y)); - CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y }; - CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition; -} - -// Set mouse cursor -void SetMouseCursor(int cursor) -{ - RGFW_window_setMouseStandard(platform.window, cursor); -} - -// Get physical key name. -const char *GetKeyName(int key) -{ - TRACELOG(LOG_WARNING, "GetKeyName() unsupported on target platform"); - - return ""; -} - -static KeyboardKey ConvertScancodeToKey(u32 keycode); - -int RGFW_gpConvTable[18] = { - [RGFW_gamepadY] = GAMEPAD_BUTTON_RIGHT_FACE_UP, - [RGFW_gamepadB] = GAMEPAD_BUTTON_RIGHT_FACE_RIGHT, - [RGFW_gamepadA] = GAMEPAD_BUTTON_RIGHT_FACE_DOWN, - [RGFW_gamepadX] = GAMEPAD_BUTTON_RIGHT_FACE_LEFT, - [RGFW_gamepadL1] = GAMEPAD_BUTTON_LEFT_TRIGGER_1, - [RGFW_gamepadR1] = GAMEPAD_BUTTON_RIGHT_TRIGGER_1, - [RGFW_gamepadL2] = GAMEPAD_BUTTON_LEFT_TRIGGER_2, - [RGFW_gamepadR2] = GAMEPAD_BUTTON_RIGHT_TRIGGER_2, - [RGFW_gamepadSelect] = GAMEPAD_BUTTON_MIDDLE_LEFT, - [RGFW_gamepadHome] = GAMEPAD_BUTTON_MIDDLE, - [RGFW_gamepadStart] = GAMEPAD_BUTTON_MIDDLE_RIGHT, - [RGFW_gamepadUp] = GAMEPAD_BUTTON_LEFT_FACE_UP, - [RGFW_gamepadRight] = GAMEPAD_BUTTON_LEFT_FACE_RIGHT, - [RGFW_gamepadDown] = GAMEPAD_BUTTON_LEFT_FACE_DOWN, - [RGFW_gamepadLeft] = GAMEPAD_BUTTON_LEFT_FACE_LEFT, - [RGFW_gamepadL3] = GAMEPAD_BUTTON_LEFT_THUMB, - [RGFW_gamepadR3] = GAMEPAD_BUTTON_RIGHT_THUMB, -}; - -// Register all input events -void PollInputEvents(void) -{ -#if defined(SUPPORT_GESTURES_SYSTEM) - // NOTE: Gestures update must be called every frame to reset gestures correctly - // because ProcessGestureEvent() is just called on an event, not every frame - UpdateGestures(); -#endif - - // Reset keys/chars pressed registered - CORE.Input.Keyboard.keyPressedQueueCount = 0; - CORE.Input.Keyboard.charPressedQueueCount = 0; - - // Reset mouse wheel - CORE.Input.Mouse.currentWheelMove.x = 0; - CORE.Input.Mouse.currentWheelMove.y = 0; - - // Register previous mouse position - - // Reset last gamepad button/axis registered state - for (int i = 0; (i < 4) && (i < MAX_GAMEPADS); i++) - { - // Check if gamepad is available - if (CORE.Input.Gamepad.ready[i]) - { - // Register previous gamepad button states - for (int k = 0; k < MAX_GAMEPAD_BUTTONS; k++) - { - CORE.Input.Gamepad.previousButtonState[i][k] = CORE.Input.Gamepad.currentButtonState[i][k]; - } - } - } - - // Register previous touch states - 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; - - 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 - - // Register previous keys states - // NOTE: Android supports up to 260 keys - for (int i = 0; i < MAX_KEYBOARD_KEYS; i++) - { - CORE.Input.Keyboard.previousKeyState[i] = CORE.Input.Keyboard.currentKeyState[i]; - CORE.Input.Keyboard.keyRepeatInFrame[i] = 0; - } - - // Register previous mouse states - for (int i = 0; i < MAX_MOUSE_BUTTONS; i++) CORE.Input.Mouse.previousButtonState[i] = CORE.Input.Mouse.currentButtonState[i]; - - // Poll input events for current platform - //----------------------------------------------------------------------------- - CORE.Window.resizedLastFrame = false; - - CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition; - if (platform.window->_flags & RGFW_HOLD_MOUSE) - { - CORE.Input.Mouse.previousPosition = (Vector2){ 0.0f, 0.0f }; - CORE.Input.Mouse.currentPosition = (Vector2){ 0.0f, 0.0f }; - } - else - { - CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition; - } - - if ((CORE.Window.eventWaiting) || (IsWindowState(FLAG_WINDOW_MINIMIZED) && !IsWindowState(FLAG_WINDOW_ALWAYS_RUN))) - { - RGFW_window_eventWait(platform.window, 0); // Wait for input events: keyboard/mouse/window events (callbacks) -> Update keys state - CORE.Time.previous = GetTime(); - } - - while (RGFW_window_checkEvent(platform.window)) - { - RGFW_event *event = &platform.window->event; - // All input events can be processed after polling - - switch (event->type) - { - case RGFW_mouseEnter: CORE.Input.Mouse.cursorOnScreen = true; break; - case RGFW_mouseLeave: CORE.Input.Mouse.cursorOnScreen = false; break; - case RGFW_quit: - event->type = 0; - CORE.Window.shouldClose = true; - return; - case RGFW_DND: // Dropped file - { - for (int i = 0; i < event->droppedFilesCount; i++) - { - if (CORE.Window.dropFileCount == 0) - { - // When a new file is dropped, we reserve a fixed number of slots for all possible dropped files - // at the moment we limit the number of drops at once to 1024 files but this behaviour should probably be reviewed - // TODO: Pointers should probably be reallocated for any new file added... - CORE.Window.dropFilepaths = (char **)RL_CALLOC(1024, sizeof(char *)); - - CORE.Window.dropFilepaths[CORE.Window.dropFileCount] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char)); - strcpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event->droppedFiles[i]); - - CORE.Window.dropFileCount++; - } - else if (CORE.Window.dropFileCount < 1024) - { - CORE.Window.dropFilepaths[CORE.Window.dropFileCount] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char)); - strcpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event->droppedFiles[i]); - - CORE.Window.dropFileCount++; - } - else TRACELOG(LOG_WARNING, "FILE: Maximum drag and drop files at once is limited to 1024 files!"); - } - } break; - - // Window events are also polled (Minimized, maximized, close...) - case RGFW_windowResized: - { - SetupViewport(platform.window->r.w, platform.window->r.h); - - // 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)(platform.window->r.w / GetWindowScaleDPI().x); - CORE.Window.screen.height = (int)(platform.window->r.h / GetWindowScaleDPI().y); - } - else - { - CORE.Window.screen.width = platform.window->r.w; - CORE.Window.screen.height = platform.window->r.h; - } - - CORE.Window.currentFbo.width = platform.window->r.w; - CORE.Window.currentFbo.height = platform.window->r.h; - CORE.Window.resizedLastFrame = true; - } break; - case RGFW_windowMaximized: - { - CORE.Window.flags |= FLAG_WINDOW_MAXIMIZED; // The window was maximized - } break; - case RGFW_windowMinimized: - { - CORE.Window.flags |= FLAG_WINDOW_MINIMIZED; // The window was iconified - } break; - case RGFW_windowRestored: - { - if (RGFW_window_isMaximized(platform.window)) - CORE.Window.flags &= ~FLAG_WINDOW_MAXIMIZED; // The window was restored - if (RGFW_window_isMinimized(platform.window)) - CORE.Window.flags &= ~FLAG_WINDOW_MINIMIZED; // The window was restored - } break; - case RGFW_windowMoved: - { - CORE.Window.position.x = platform.window->r.x; - CORE.Window.position.y = platform.window->r.x; - } break; - - // Keyboard events - case RGFW_keyPressed: - { - KeyboardKey key = ConvertScancodeToKey(event->key); - if (key != KEY_NULL) - { - // If key was up, add it to the key pressed queue - if ((CORE.Input.Keyboard.currentKeyState[key] == 0) && (CORE.Input.Keyboard.keyPressedQueueCount < MAX_KEY_PRESSED_QUEUE)) - { - CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = key; - CORE.Input.Keyboard.keyPressedQueueCount++; - } - - CORE.Input.Keyboard.currentKeyState[key] = 1; - } - - // TODO: Put exitKey verification outside the switch? - if (CORE.Input.Keyboard.currentKeyState[CORE.Input.Keyboard.exitKey]) - { - CORE.Window.shouldClose = true; - } - - // NOTE: event.text.text data comes an UTF-8 text sequence but we register codepoints (int) - // Check if there is space available in the queue - if (CORE.Input.Keyboard.charPressedQueueCount < MAX_CHAR_PRESSED_QUEUE) - { - // Add character (codepoint) to the queue - CORE.Input.Keyboard.charPressedQueue[CORE.Input.Keyboard.charPressedQueueCount] = event->keyChar; - CORE.Input.Keyboard.charPressedQueueCount++; - } - } break; - case RGFW_keyReleased: - { - KeyboardKey key = ConvertScancodeToKey(event->key); - if (key != KEY_NULL) CORE.Input.Keyboard.currentKeyState[key] = 0; - } break; - - // Check mouse events - case RGFW_mouseButtonPressed: - { - if ((event->button == RGFW_mouseScrollUp) || (event->button == RGFW_mouseScrollDown)) - { - CORE.Input.Mouse.currentWheelMove.y = event->scroll; - break; - } - else CORE.Input.Mouse.currentWheelMove.y = 0; - - int btn = event->button; - if (btn == RGFW_mouseLeft) btn = 1; - else if (btn == RGFW_mouseRight) btn = 2; - else if (btn == RGFW_mouseMiddle) btn = 3; - - CORE.Input.Mouse.currentButtonState[btn - 1] = 1; - CORE.Input.Touch.currentTouchState[btn - 1] = 1; - - touchAction = 1; - } break; - case RGFW_mouseButtonReleased: - { - if ((event->button == RGFW_mouseScrollUp) || (event->button == RGFW_mouseScrollDown)) - { - CORE.Input.Mouse.currentWheelMove.y = event->scroll; - break; - } - else CORE.Input.Mouse.currentWheelMove.y = 0; - - int btn = event->button; - if (btn == RGFW_mouseLeft) btn = 1; - else if (btn == RGFW_mouseRight) btn = 2; - else if (btn == RGFW_mouseMiddle) btn = 3; - - CORE.Input.Mouse.currentButtonState[btn - 1] = 0; - CORE.Input.Touch.currentTouchState[btn - 1] = 0; - - touchAction = 0; - } break; - case RGFW_mousePosChanged: - { - if (platform.window->_flags & RGFW_HOLD_MOUSE) - { - CORE.Input.Mouse.currentPosition.x += (float)event->vector.x; - CORE.Input.Mouse.currentPosition.y += (float)event->vector.y; - } - else - { - CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition; - CORE.Input.Mouse.currentPosition.x = (float)event->point.x; - CORE.Input.Mouse.currentPosition.y = (float)event->point.y; - } - - CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition; - touchAction = 2; - } break; - case RGFW_gamepadConnected: - { - CORE.Input.Gamepad.ready[platform.window->event.gamepad] = true; - CORE.Input.Gamepad.axisCount[platform.window->event.gamepad] = platform.window->event.axisesCount; - CORE.Input.Gamepad.axisState[platform.window->event.gamepad][GAMEPAD_AXIS_LEFT_TRIGGER] = -1.0f; - CORE.Input.Gamepad.axisState[platform.window->event.gamepad][GAMEPAD_AXIS_RIGHT_TRIGGER] = -1.0f; - - strcpy(CORE.Input.Gamepad.name[platform.window->event.gamepad], RGFW_getGamepadName(platform.window, platform.window->event.gamepad)); - } break; - case RGFW_gamepadDisconnected: - { - CORE.Input.Gamepad.ready[platform.window->event.gamepad] = false; - } break; - case RGFW_gamepadButtonPressed: - { - int button = RGFW_gpConvTable[event->button]; - - if (button >= 0) - { - CORE.Input.Gamepad.currentButtonState[event->gamepad][button] = 1; - CORE.Input.Gamepad.lastButtonPressed = button; - } - } break; - case RGFW_gamepadButtonReleased: - { - int button = RGFW_gpConvTable[event->button]; - - CORE.Input.Gamepad.currentButtonState[event->gamepad][button] = 0; - if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0; - } break; - case RGFW_gamepadAxisMove: - { - int axis = -1; - float value = 0; - - switch(event->whichAxis) - { - case 0: - { - CORE.Input.Gamepad.axisState[event->gamepad][GAMEPAD_AXIS_LEFT_X] = event->axis[0].x / 100.0f; - CORE.Input.Gamepad.axisState[event->gamepad][GAMEPAD_AXIS_LEFT_Y] = event->axis[0].y / 100.0f; - } break; - case 1: - { - CORE.Input.Gamepad.axisState[event->gamepad][GAMEPAD_AXIS_RIGHT_X] = event->axis[1].x / 100.0f; - CORE.Input.Gamepad.axisState[event->gamepad][GAMEPAD_AXIS_RIGHT_Y] = event->axis[1].y / 100.0f; - } break; - case 2: axis = GAMEPAD_AXIS_LEFT_TRIGGER; - case 3: - { - if (axis == -1) 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[event->gamepad][button] = pressed; - - if (pressed) CORE.Input.Gamepad.lastButtonPressed = button; - else if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0; - } - default: break; - } - } break; - default: break; - } - -#if defined(SUPPORT_GESTURES_SYSTEM) - if (touchAction > -1) - { - // Process mouse events as touches to be able to use mouse-gestures - GestureEvent gestureEvent = { 0 }; - - // Register touch actions - gestureEvent.touchAction = touchAction; - - // Assign a pointer ID - gestureEvent.pointId[0] = 0; - - // Register touch points count - gestureEvent.pointCount = 1; - - // Register touch points position, only one point registered - if (touchAction == 2 || realTouch) gestureEvent.position[0] = CORE.Input.Touch.position[0]; - else gestureEvent.position[0] = GetMousePosition(); - - // Normalize gestureEvent.position[0] for CORE.Window.screen.width and CORE.Window.screen.height - gestureEvent.position[0].x /= (float)GetScreenWidth(); - gestureEvent.position[0].y /= (float)GetScreenHeight(); - - // Gesture data is sent to gestures-system for processing - ProcessGestureEvent(gestureEvent); - - touchAction = -1; - } -#endif - } - //----------------------------------------------------------------------------- -} - -//---------------------------------------------------------------------------------- -// Module Internal Functions Definition -//---------------------------------------------------------------------------------- - -// Initialize platform: graphics, inputs and more -int InitPlatform(void) -{ - // Initialize RGFW internal global state, only required systems - unsigned int flags = RGFW_windowCenter | RGFW_windowAllowDND; - - // Check window creation flags - if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) > 0) - { - CORE.Window.fullscreen = true; - flags |= RGFW_windowFullscreen; - } - - if ((CORE.Window.flags & FLAG_BORDERLESS_WINDOWED_MODE) > 0) - { - CORE.Window.fullscreen = true; - flags |= RGFW_windowedFullscreen; - } - - if ((CORE.Window.flags & FLAG_WINDOW_UNDECORATED) > 0) flags |= RGFW_windowNoBorder; - if ((CORE.Window.flags & FLAG_WINDOW_RESIZABLE) == 0) flags |= RGFW_windowNoResize; - if ((CORE.Window.flags & FLAG_WINDOW_TRANSPARENT) > 0) flags |= RGFW_windowTransparent; - if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) > 0) flags |= RGFW_windowFullscreen; - if ((CORE.Window.flags & FLAG_WINDOW_HIDDEN) > 0) flags |= RGFW_windowHide; - if ((CORE.Window.flags & FLAG_WINDOW_MAXIMIZED) > 0) flags |= RGFW_windowMaximize; - - // NOTE: Some OpenGL context attributes must be set before window creation - // Check selection OpenGL version - if (rlGetVersion() == RL_OPENGL_21) - { - RGFW_setGLHint(RGFW_glMajor, 2); - RGFW_setGLHint(RGFW_glMinor, 1); - } - else if (rlGetVersion() == RL_OPENGL_33) - { - RGFW_setGLHint(RGFW_glMajor, 3); - RGFW_setGLHint(RGFW_glMinor, 3); - } - else if (rlGetVersion() == RL_OPENGL_43) - { - RGFW_setGLHint(RGFW_glMajor, 4); - RGFW_setGLHint(RGFW_glMinor, 3); - } - - if (CORE.Window.flags & FLAG_MSAA_4X_HINT) RGFW_setGLHint(RGFW_glSamples, 4); - - if (!(CORE.Window.flags & FLAG_WINDOW_UNFOCUSED)) flags |= RGFW_windowFocusOnShow | RGFW_windowFocus; - - platform.window = RGFW_createWindow(CORE.Window.title, RGFW_RECT(0, 0, CORE.Window.screen.width, CORE.Window.screen.height), flags); - platform.mon.mode.area.w = 0; - -#ifndef PLATFORM_WEB_RGFW - RGFW_area screenSize = RGFW_getScreenSize(); - CORE.Window.display.width = screenSize.w; - CORE.Window.display.height = screenSize.h; -#else - CORE.Window.display.width = CORE.Window.screen.width; - CORE.Window.display.height = CORE.Window.screen.height; -#endif - // TODO: Is this needed by raylib now? - // If so, rcore_desktop_sdl should be updated too - //SetupFramebuffer(CORE.Window.display.width, CORE.Window.display.height); - - if (CORE.Window.flags & FLAG_VSYNC_HINT) RGFW_window_swapInterval(platform.window, 1); - RGFW_window_makeCurrent(platform.window); - - // Check surface and context activation - if (platform.window != NULL) - { - CORE.Window.ready = true; - - CORE.Window.render.width = CORE.Window.screen.width; - CORE.Window.render.height = CORE.Window.screen.height; - CORE.Window.currentFbo.width = CORE.Window.render.width; - CORE.Window.currentFbo.height = CORE.Window.render.height; - } - else - { - TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize graphics device"); - return -1; - } - //---------------------------------------------------------------------------- - - // If everything work as expected, we can continue - CORE.Window.position.x = platform.window->r.x; - CORE.Window.position.y = platform.window->r.y; - CORE.Window.render.width = CORE.Window.screen.width; - CORE.Window.render.height = CORE.Window.screen.height; - CORE.Window.currentFbo.width = CORE.Window.render.width; - CORE.Window.currentFbo.height = CORE.Window.render.height; - - TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully"); - TRACELOG(LOG_INFO, " > Display size: %i x %i", CORE.Window.display.width, CORE.Window.display.height); - TRACELOG(LOG_INFO, " > Screen size: %i x %i", CORE.Window.screen.width, CORE.Window.screen.height); - TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height); - TRACELOG(LOG_INFO, " > Viewport offsets: %i, %i", CORE.Window.renderOffset.x, CORE.Window.renderOffset.y); - - // Load OpenGL extensions - // NOTE: GL procedures address loader is required to load extensions - //---------------------------------------------------------------------------- - rlLoadExtensions((void *)RGFW_getProcAddress); - //---------------------------------------------------------------------------- - - // Initialize timing system - //---------------------------------------------------------------------------- - InitTimer(); - //---------------------------------------------------------------------------- - - // Initialize storage system - //---------------------------------------------------------------------------- - CORE.Storage.basePath = GetWorkingDirectory(); - //---------------------------------------------------------------------------- - -#if defined(RGFW_WAYLAND) - if (RGFW_useWaylandBool) TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - Wayland): Initialized successfully"); - else TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - X11 (fallback)): Initialized successfully"); -#elif defined(RGFW_X11) - #if defined(__APPLE__) - TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - X11 (MacOS)): Initialized successfully"); - #else - TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - X11): Initialized successfully"); - #endif -#elif defined (RGFW_WINDOWS) - TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - Win32): Initialized successfully"); -#elif defined(RGFW_WASM) - TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - WASMs): Initialized successfully"); -#elif defined(RGFW_MACOS) - TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - MacOS): Initialized successfully"); -#endif - - return 0; -} - -// Close platform -void ClosePlatform(void) -{ - RGFW_window_close(platform.window); -} - -// Keycode mapping -static KeyboardKey ConvertScancodeToKey(u32 keycode) -{ - if (keycode > sizeof(keyMappingRGFW)/sizeof(unsigned short)) return 0; - - return keyMappingRGFW[keycode]; -} +/********************************************************************************************** +* +* rcore_desktop_rgfw - Functions to manage window, graphics device and inputs +* +* PLATFORM: RGFW +* - Windows (Win32, Win64) +* - Linux (X11/Wayland desktop mode) +* - MacOS (Cocoa) +* - HTML5 (Emscripten) +* - Others (untested) +* +* LIMITATIONS: +* - TODO +* +* POSSIBLE IMPROVEMENTS: +* - TODO +* +* ADDITIONAL NOTES: +* - TRACELOG() function is located in raylib [utils] module +* +* CONFIGURATION: +* #define RCORE_PLATFORM_RGFW +* Custom flag for rcore on target platform RGFW +* +* DEPENDENCIES: +* - RGFW.h (main library): Windowing and inputs management +* - gestures: Gestures system for touch-ready devices (or simulated from mouse inputs) +* +* +* LICENSE: zlib/libpng +* +* Copyright (c) 2013-2025 Ramon Santamaria (@raysan5), Colleague Riley 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. +* +* Permission is granted to anyone to use this software for any purpose, including commercial +* applications, and to alter it and redistribute it freely, subject to the following restrictions: +* +* 1. The origin of this software must not be misrepresented; you must not claim that you +* wrote the original software. If you use this software in a product, an acknowledgment +* in the product documentation would be appreciated but is not required. +* +* 2. Altered source versions must be plainly marked as such, and must not be misrepresented +* as being the original software. +* +* 3. This notice may not be removed or altered from any source distribution. +* +**********************************************************************************************/ + +#ifndef RAYLIB_H /* this should never actually happen, it's only here for IDEs */ +#include "raylib.h" +#include "../rcore.c" +#endif + +#if defined(PLATFORM_WEB_RGFW) +#define RGFW_NO_GL_HEADER +#endif + +#if defined(GRAPHICS_API_OPENGL_ES2) && !defined(PLATFORM_WEB_RGFW) + #define RGFW_OPENGL_ES2 +#endif + +void ShowCursor(void); +void CloseWindow(void); + +#if defined(__linux__) + #define _INPUT_EVENT_CODES_H +#endif + +#if defined(__unix__) || defined(__linux__) + #define _XTYPEDEF_FONT +#endif + +#define RGFW_IMPLEMENTATION + +#if defined(_WIN32) || defined(_WIN64) + #define WIN32_LEAN_AND_MEAN + #define Rectangle rectangle_win32 + #define CloseWindow CloseWindow_win32 + #define ShowCursor __imp_ShowCursor + #define _APISETSTRING_ + + #undef MAX_PATH + + __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int CodePage, unsigned long dwFlags, const char *lpMultiByteStr, int cbMultiByte, wchar_t *lpWideCharStr, int cchWideChar); +#endif + +#if defined(__APPLE__) + #define Point NSPOINT + #define Size NSSIZE +#endif + +#define RGFW_ALLOC RL_MALLOC +#define RGFW_FREE RL_FREE +#define RGFW_CALLOC RL_CALLOC + +#include "../external/RGFW.h" + +#if defined(_WIN32) || defined(_WIN64) + #undef DrawText + #undef ShowCursor + #undef CloseWindow + #undef Rectangle + + #undef MAX_PATH + #define MAX_PATH 1025 +#endif + +#if defined(__APPLE__) + #undef Point + #undef Size +#endif + +#include +#include // Required for: strcmp() + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +typedef struct { + RGFW_window *window; // Native display device (physical screen connection) + RGFW_monitor mon; +} PlatformData; + +//---------------------------------------------------------------------------------- +// Global Variables Definition +//---------------------------------------------------------------------------------- +extern CoreData CORE; // Global CORE state context + +static PlatformData platform = { 0 }; // Platform specific + +static bool RGFW_disableCursor = false; + +static const unsigned short keyMappingRGFW[] = { + [RGFW_keyNULL] = KEY_NULL, + [RGFW_return] = KEY_ENTER, + [RGFW_return] = KEY_ENTER, + [RGFW_apostrophe] = KEY_APOSTROPHE, + [RGFW_comma] = KEY_COMMA, + [RGFW_minus] = KEY_MINUS, + [RGFW_period] = KEY_PERIOD, + [RGFW_slash] = KEY_SLASH, + [RGFW_escape] = KEY_ESCAPE, + [RGFW_F1] = KEY_F1, + [RGFW_F2] = KEY_F2, + [RGFW_F3] = KEY_F3, + [RGFW_F4] = KEY_F4, + [RGFW_F5] = KEY_F5, + [RGFW_F6] = KEY_F6, + [RGFW_F7] = KEY_F7, + [RGFW_F8] = KEY_F8, + [RGFW_F9] = KEY_F9, + [RGFW_F10] = KEY_F10, + [RGFW_F11] = KEY_F11, + [RGFW_F12] = KEY_F12, + [RGFW_backtick] = KEY_GRAVE, + [RGFW_0] = KEY_ZERO, + [RGFW_1] = KEY_ONE, + [RGFW_2] = KEY_TWO, + [RGFW_3] = KEY_THREE, + [RGFW_4] = KEY_FOUR, + [RGFW_5] = KEY_FIVE, + [RGFW_6] = KEY_SIX, + [RGFW_7] = KEY_SEVEN, + [RGFW_8] = KEY_EIGHT, + [RGFW_9] = KEY_NINE, + [RGFW_equals] = KEY_EQUAL, + [RGFW_backSpace] = KEY_BACKSPACE, + [RGFW_tab] = KEY_TAB, + [RGFW_capsLock] = KEY_CAPS_LOCK, + [RGFW_shiftL] = KEY_LEFT_SHIFT, + [RGFW_controlL] = KEY_LEFT_CONTROL, + [RGFW_altL] = KEY_LEFT_ALT, + [RGFW_superL] = KEY_LEFT_SUPER, + #ifndef RGFW_MACOS + [RGFW_shiftR] = KEY_RIGHT_SHIFT, + [RGFW_altR] = KEY_RIGHT_ALT, + #endif + [RGFW_space] = KEY_SPACE, + + [RGFW_a] = KEY_A, + [RGFW_b] = KEY_B, + [RGFW_c] = KEY_C, + [RGFW_d] = KEY_D, + [RGFW_e] = KEY_E, + [RGFW_f] = KEY_F, + [RGFW_g] = KEY_G, + [RGFW_h] = KEY_H, + [RGFW_i] = KEY_I, + [RGFW_j] = KEY_J, + [RGFW_k] = KEY_K, + [RGFW_l] = KEY_L, + [RGFW_m] = KEY_M, + [RGFW_n] = KEY_N, + [RGFW_o] = KEY_O, + [RGFW_p] = KEY_P, + [RGFW_q] = KEY_Q, + [RGFW_r] = KEY_R, + [RGFW_s] = KEY_S, + [RGFW_t] = KEY_T, + [RGFW_u] = KEY_U, + [RGFW_v] = KEY_V, + [RGFW_w] = KEY_W, + [RGFW_x] = KEY_X, + [RGFW_y] = KEY_Y, + [RGFW_z] = KEY_Z, + [RGFW_bracket] = KEY_LEFT_BRACKET, + [RGFW_backSlash] = KEY_BACKSLASH, + [RGFW_closeBracket] = KEY_RIGHT_BRACKET, + [RGFW_semicolon] = KEY_SEMICOLON, + [RGFW_insert] = KEY_INSERT, + [RGFW_home] = KEY_HOME, + [RGFW_pageUp] = KEY_PAGE_UP, + [RGFW_delete] = KEY_DELETE, + [RGFW_end] = KEY_END, + [RGFW_pageDown] = KEY_PAGE_DOWN, + [RGFW_right] = KEY_RIGHT, + [RGFW_left] = KEY_LEFT, + [RGFW_down] = KEY_DOWN, + [RGFW_up] = KEY_UP, + [RGFW_numLock] = KEY_NUM_LOCK, + [RGFW_KP_Slash] = KEY_KP_DIVIDE, + [RGFW_multiply] = KEY_KP_MULTIPLY, + [RGFW_KP_Minus] = KEY_KP_SUBTRACT, + [RGFW_KP_Return] = KEY_KP_ENTER, + [RGFW_KP_1] = KEY_KP_1, + [RGFW_KP_2] = KEY_KP_2, + [RGFW_KP_3] = KEY_KP_3, + [RGFW_KP_4] = KEY_KP_4, + [RGFW_KP_5] = KEY_KP_5, + [RGFW_KP_6] = KEY_KP_6, + [RGFW_KP_7] = KEY_KP_7, + [RGFW_KP_8] = KEY_KP_8, + [RGFW_KP_9] = KEY_KP_9, + [RGFW_KP_0] = KEY_KP_0, + [RGFW_KP_Period] = KEY_KP_DECIMAL, + [RGFW_scrollLock] = KEY_SCROLL_LOCK, +}; + +//---------------------------------------------------------------------------------- +// Module Internal Functions Declaration +//---------------------------------------------------------------------------------- +int InitPlatform(void); // Initialize platform (graphics, inputs and more) +bool InitGraphicsDevice(void); // Initialize graphics device + +//---------------------------------------------------------------------------------- +// Module Functions Declaration +//---------------------------------------------------------------------------------- +// NOTE: Functions declaration is provided by raylib.h + +//---------------------------------------------------------------------------------- +// Module Functions Definition: Window and Graphics Device +//---------------------------------------------------------------------------------- + +// Check if application should close +bool WindowShouldClose(void) +{ + if (CORE.Window.shouldClose == false) + CORE.Window.shouldClose = RGFW_window_shouldClose(platform.window); + if (CORE.Window.ready) return CORE.Window.shouldClose; + else return true; +} + +// Toggle fullscreen mode +void ToggleFullscreen(void) +{ + if (!CORE.Window.fullscreen) + { + // Store previous window position (in case we exit fullscreen) + CORE.Window.previousPosition = CORE.Window.position; + CORE.Window.previousScreen = CORE.Window.screen; + + platform.mon = RGFW_window_getMonitor(platform.window); + CORE.Window.fullscreen = true; + CORE.Window.flags |= FLAG_FULLSCREEN_MODE; + + RGFW_monitor_scaleToWindow(platform.mon, platform.window); + RGFW_window_setFullscreen(platform.window, 1); + } + else + { + CORE.Window.fullscreen = false; + CORE.Window.flags &= ~FLAG_FULLSCREEN_MODE; + + if (platform.mon.mode.area.w) + { + RGFW_monitor monitor = RGFW_window_getMonitor(platform.window); + RGFW_monitor_requestMode(monitor, platform.mon.mode, RGFW_monitorScale); + + platform.mon.mode.area.w = 0; + } + + // we update the window position right away + CORE.Window.position = CORE.Window.previousPosition; + RGFW_window_setFullscreen(platform.window, 0); + RGFW_window_move(platform.window, RGFW_POINT(CORE.Window.position.x, CORE.Window.position.y)); + RGFW_window_resize(platform.window, RGFW_AREA(CORE.Window.previousScreen.width, CORE.Window.previousScreen.height)); + } + + // Try to enable GPU V-Sync, so frames are limited to screen refresh rate (60Hz -> 60 FPS) + // NOTE: V-Sync can be enabled by graphic driver configuration + if (CORE.Window.flags & FLAG_VSYNC_HINT) RGFW_window_swapInterval(platform.window, 1); +} + +// Toggle borderless windowed mode +void ToggleBorderlessWindowed(void) +{ + if (CORE.Window.fullscreen) + { + CORE.Window.previousPosition = CORE.Window.position; + CORE.Window.previousScreen = CORE.Window.screen; + + RGFW_window_setBorder(platform.window, 0); + + RGFW_monitor mon = RGFW_window_getMonitor(platform.window); + RGFW_window_resize(platform.window, mon.mode.area); + } + else + { + RGFW_window_setBorder(platform.window, 1); + + CORE.Window.position = CORE.Window.previousPosition; + RGFW_window_resize(platform.window, RGFW_AREA(CORE.Window.previousScreen.width, CORE.Window.previousScreen.height)); + } + + CORE.Window.fullscreen = !CORE.Window.fullscreen; +} + +// Set window state: maximized, if resizable +void MaximizeWindow(void) +{ + RGFW_window_maximize(platform.window); +} + +// Set window state: minimized +void MinimizeWindow(void) +{ + RGFW_window_minimize(platform.window); +} + +// Restore window from being minimized/maximized +void RestoreWindow(void) +{ + if (!(CORE.Window.flags & FLAG_WINDOW_UNFOCUSED)) RGFW_window_focus(platform.window); + + RGFW_window_restore(platform.window); +} + +// 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) + { + RGFW_window_swapInterval(platform.window, 1); + } + if (flags & FLAG_FULLSCREEN_MODE) + { + if (!CORE.Window.fullscreen) ToggleFullscreen(); + } + if (flags & FLAG_WINDOW_RESIZABLE) + { + RGFW_window_setMaxSize(platform.window, RGFW_AREA(0, 0)); + RGFW_window_setMinSize(platform.window, RGFW_AREA(0, 0)); + } + if (flags & FLAG_WINDOW_UNDECORATED) + { + RGFW_window_setBorder(platform.window, 0); + } + if (flags & FLAG_WINDOW_HIDDEN) + { + RGFW_window_hide(platform.window); + } + if (flags & FLAG_WINDOW_MINIMIZED) + { + RGFW_window_minimize(platform.window); + } + if (flags & FLAG_WINDOW_MAXIMIZED) + { + RGFW_window_maximize(platform.window); + } + if (flags & FLAG_WINDOW_UNFOCUSED) + { + CORE.Window.flags |= FLAG_WINDOW_UNFOCUSED; + platform.window->_flags &= ~RGFW_windowFocusOnShow; + RGFW_window_setFlags(platform.window, platform.window->_flags); + } + if (flags & FLAG_WINDOW_TOPMOST) + { + RGFW_window_setFloating(platform.window, RGFW_TRUE); + } + if (flags & FLAG_WINDOW_ALWAYS_RUN) + { + CORE.Window.flags |= FLAG_WINDOW_ALWAYS_RUN; + } + if (flags & FLAG_WINDOW_TRANSPARENT) + { + TRACELOG(LOG_WARNING, "WINDOW: Framebuffer transparency can only be configured before window initialization"); + } + if (flags & FLAG_WINDOW_HIGHDPI) + { + TRACELOG(LOG_WARNING, "WINDOW: High DPI can only be configured before window initialization"); + } + if (flags & FLAG_WINDOW_MOUSE_PASSTHROUGH) + { + RGFW_window_setMousePassthrough(platform.window, 1); + } + if (flags & FLAG_BORDERLESS_WINDOWED_MODE) + { + ToggleBorderlessWindowed(); + } + if (flags & FLAG_MSAA_4X_HINT) + { + RGFW_setGLHint(RGFW_glSamples, 4); + } + if (flags & FLAG_INTERLACED_HINT) + { + TRACELOG(LOG_WARNING, "RPI: Interlaced mode can only be configured before window initialization"); + } +} + +// Clear window configuration state flags +void ClearWindowState(unsigned int flags) +{ + CORE.Window.flags &= ~flags; + + if (flags & FLAG_VSYNC_HINT) + { + RGFW_window_swapInterval(platform.window, 0); + } + if (flags & FLAG_FULLSCREEN_MODE) + { + if (CORE.Window.fullscreen) ToggleFullscreen(); + } + if (flags & FLAG_WINDOW_RESIZABLE) + { + RGFW_window_setMaxSize(platform.window, RGFW_AREA(platform.window->r.w, platform.window->r.h)); + RGFW_window_setMinSize(platform.window, RGFW_AREA(platform.window->r.w, platform.window->r.h)); + } + if (flags & FLAG_WINDOW_UNDECORATED) + { + RGFW_window_setBorder(platform.window, 1); + } + if (flags & FLAG_WINDOW_HIDDEN) + { + if (!(CORE.Window.flags & FLAG_WINDOW_UNFOCUSED)) RGFW_window_focus(platform.window); + + RGFW_window_show(platform.window); + } + if (flags & FLAG_WINDOW_MINIMIZED) + { + if (!(CORE.Window.flags & FLAG_WINDOW_UNFOCUSED)) RGFW_window_focus(platform.window); + + RGFW_window_restore(platform.window); + } + if (flags & FLAG_WINDOW_MAXIMIZED) + { + if (!(CORE.Window.flags & FLAG_WINDOW_UNFOCUSED)) RGFW_window_focus(platform.window); + + RGFW_window_restore(platform.window); + } + if (flags & FLAG_WINDOW_UNFOCUSED) + { + RGFW_window_setFlags(platform.window, platform.window->_flags | RGFW_windowFocusOnShow); + CORE.Window.flags &= ~FLAG_WINDOW_UNFOCUSED; + } + if (flags & FLAG_WINDOW_TOPMOST) + { + RGFW_window_setFloating(platform.window, RGFW_FALSE); + } + if (flags & FLAG_WINDOW_ALWAYS_RUN) + { + CORE.Window.flags &= ~FLAG_WINDOW_ALWAYS_RUN; + } + if (flags & FLAG_WINDOW_TRANSPARENT) + { + TRACELOG(LOG_WARNING, "WINDOW: Framebuffer transparency can only be configured before window initialization"); + } + if (flags & FLAG_WINDOW_HIGHDPI) + { + TRACELOG(LOG_WARNING, "WINDOW: High DPI can only be configured before window initialization"); + } + if (flags & FLAG_WINDOW_MOUSE_PASSTHROUGH) + { + RGFW_window_setMousePassthrough(platform.window, 0); + } + if (flags & FLAG_BORDERLESS_WINDOWED_MODE) + { + if (CORE.Window.fullscreen) ToggleBorderlessWindowed(); + } + if (flags & FLAG_MSAA_4X_HINT) + { + RGFW_setGLHint(RGFW_glSamples, 0); + } + if (flags & FLAG_INTERLACED_HINT) + { + TRACELOG(LOG_WARNING, "RPI: Interlaced mode can only be configured before window initialization"); + } +} + +int RGFW_formatToChannels(int format) +{ + switch (format) + { + case PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: + case PIXELFORMAT_UNCOMPRESSED_R16: // 16 bpp (1 channel - half float) + case PIXELFORMAT_UNCOMPRESSED_R32: // 32 bpp (1 channel - float) + return 1; + case PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: // 8*2 bpp (2 channels) + case PIXELFORMAT_UNCOMPRESSED_R5G6B5: // 16 bpp + case PIXELFORMAT_UNCOMPRESSED_R8G8B8: // 24 bpp + case PIXELFORMAT_UNCOMPRESSED_R5G5B5A1: // 16 bpp (1 bit alpha) + case PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: // 16 bpp (4 bit alpha) + case PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: // 32 bpp + return 2; + case PIXELFORMAT_UNCOMPRESSED_R32G32B32: // 32*3 bpp (3 channels - float) + case PIXELFORMAT_UNCOMPRESSED_R16G16B16: // 16*3 bpp (3 channels - half float) + case PIXELFORMAT_COMPRESSED_DXT1_RGB: // 4 bpp (no alpha) + case PIXELFORMAT_COMPRESSED_ETC1_RGB: // 4 bpp + case PIXELFORMAT_COMPRESSED_ETC2_RGB: // 4 bpp + case PIXELFORMAT_COMPRESSED_PVRT_RGB: // 4 bpp + return 3; + case PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: // 32*4 bpp (4 channels - float) + case PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: // 16*4 bpp (4 channels - half float) + case PIXELFORMAT_COMPRESSED_DXT1_RGBA: // 4 bpp (1 bit alpha) + case PIXELFORMAT_COMPRESSED_DXT3_RGBA: // 8 bpp + case PIXELFORMAT_COMPRESSED_DXT5_RGBA: // 8 bpp + case PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA: // 8 bpp + case PIXELFORMAT_COMPRESSED_PVRT_RGBA: // 4 bpp + case PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA: // 8 bpp + case PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA: // 2 bpp + return 4; + default: return 4; + } +} + +// Set icon for window +void SetWindowIcon(Image image) +{ + RGFW_window_setIcon(platform.window, image.data, RGFW_AREA(image.width, image.height), RGFW_formatToChannels(image.format)); +} + +// Set icon for window +void SetWindowIcons(Image *images, int count) +{ + if ((images == NULL) || (count <= 0)) + { + RGFW_window_setIcon(platform.window, NULL, RGFW_AREA(0, 0), 0); + } + else + { + Image *bigIcon = NULL; + Image *smallIcon = NULL; + + for (int i = 0; i < count; i++) + { + if ((bigIcon == NULL) || ((images[i].width > bigIcon->width) && (images[i].height > bigIcon->height))) bigIcon = &images[i]; + if ((smallIcon == NULL) || ((images[i].width < smallIcon->width) && (images[i].height > smallIcon->height))) smallIcon = &images[i]; + } + + if (smallIcon != NULL) RGFW_window_setIconEx(platform.window, smallIcon->data, RGFW_AREA(smallIcon->width, smallIcon->height), RGFW_formatToChannels(smallIcon->format), RGFW_iconWindow); + if (bigIcon != NULL) RGFW_window_setIconEx(platform.window, bigIcon->data, RGFW_AREA(bigIcon->width, bigIcon->height), RGFW_formatToChannels(bigIcon->format), RGFW_iconTaskbar); + } +} + +// Set title for window +void SetWindowTitle(const char *title) +{ + RGFW_window_setName(platform.window, (char *)title); + CORE.Window.title = title; +} + +// Set window position on screen (windowed mode) +void SetWindowPosition(int x, int y) +{ + RGFW_window_move(platform.window, RGFW_POINT(x, y)); +} + +// Set monitor for the current window +void SetWindowMonitor(int monitor) +{ + RGFW_window_moveToMonitor(platform.window, RGFW_getMonitors()[monitor]); +} + +// Set window minimum dimensions (FLAG_WINDOW_RESIZABLE) +void SetWindowMinSize(int width, int height) +{ + RGFW_window_setMinSize(platform.window, RGFW_AREA(width, height)); + CORE.Window.screenMin.width = width; + CORE.Window.screenMin.height = height; +} + +// Set window maximum dimensions (FLAG_WINDOW_RESIZABLE) +void SetWindowMaxSize(int width, int height) +{ + RGFW_window_setMaxSize(platform.window, RGFW_AREA(width, height)); + CORE.Window.screenMax.width = width; + CORE.Window.screenMax.height = height; +} + +// Set window dimensions +void SetWindowSize(int width, int height) +{ + CORE.Window.screen.width = width; + CORE.Window.screen.height = height; + + RGFW_window_resize(platform.window, RGFW_AREA(width, height)); +} + +// Set window opacity, value opacity is between 0.0 and 1.0 +void SetWindowOpacity(float opacity) +{ + RGFW_window_setOpacity(platform.window, opacity); +} + +// Set window focused +void SetWindowFocused(void) +{ + RGFW_window_focus(platform.window); +} + +// Get native window handle +void *GetWindowHandle(void) +{ + if (platform.window == NULL) return NULL; +#ifdef RGFW_WASM + return (void *)platform.window->src.ctx; +#else + return (void *)platform.window->src.window; +#endif +} + +// Get number of monitors +int GetMonitorCount(void) +{ + #define MAX_MONITORS_SUPPORTED 6 + + int count = MAX_MONITORS_SUPPORTED; + RGFW_monitor *mons = RGFW_getMonitors(); + + for (int i = 0; i < 6; i++) + { + if (!mons[i].x && !mons[i].y && !mons[i].mode.area.w && mons[i].mode.area.h) + { + count = i; + break; + } + } + + return count; +} + +// Get current monitor where window is placed +int GetCurrentMonitor(void) +{ + RGFW_monitor *mons = RGFW_getMonitors(); + RGFW_monitor mon = { 0 }; + + if (platform.window) mon = RGFW_window_getMonitor(platform.window); + else mon = RGFW_getPrimaryMonitor(); + + for (int i = 0; i < 6; i++) + { + if ((mons[i].x == mon.x) && (mons[i].y == mon.y)) return i; + } + + return 0; +} + +// Get selected monitor position +Vector2 GetMonitorPosition(int monitor) +{ + RGFW_monitor *mons = RGFW_getMonitors(); + + return (Vector2){ (float)mons[monitor].x, (float)mons[monitor].y }; +} + +// Get selected monitor width (currently used by monitor) +int GetMonitorWidth(int monitor) +{ + RGFW_monitor *mons = RGFW_getMonitors(); + + return mons[monitor].mode.area.w; +} + +// Get selected monitor height (currently used by monitor) +int GetMonitorHeight(int monitor) +{ + RGFW_monitor *mons = RGFW_getMonitors(); + + return mons[monitor].mode.area.h; +} + +// Get selected monitor physical width in millimetres +int GetMonitorPhysicalWidth(int monitor) +{ + RGFW_monitor *mons = RGFW_getMonitors(); + + return mons[monitor].physW; +} + +// Get selected monitor physical height in millimetres +int GetMonitorPhysicalHeight(int monitor) +{ + RGFW_monitor *mons = RGFW_getMonitors(); + + return (int)mons[monitor].physH; +} + +// Get selected monitor refresh rate +int GetMonitorRefreshRate(int monitor) +{ + RGFW_monitor *mons = RGFW_getMonitors(); + + return (int)mons[monitor].mode.refreshRate; +} + +// Get the human-readable, UTF-8 encoded name of the selected monitor +const char *GetMonitorName(int monitor) +{ + RGFW_monitor *mons = RGFW_getMonitors(); + + return mons[monitor].name; +} + +// Get window position XY on monitor +Vector2 GetWindowPosition(void) +{ + if (platform.window == NULL) return (Vector2){ 0.0f, 0.0f }; + return (Vector2){ (float)platform.window->r.x, (float)platform.window->r.y }; +} + +// Get window scale DPI factor for current monitor +Vector2 GetWindowScaleDPI(void) +{ + RGFW_monitor monitor = { 0 }; + + if (platform.window) monitor = RGFW_window_getMonitor(platform.window); + else monitor = RGFW_getPrimaryMonitor(); + + return (Vector2){ monitor.scaleX, monitor.scaleX }; +} + +// Set clipboard text content +void SetClipboardText(const char *text) +{ + RGFW_writeClipboard(text, strlen(text)); +} + +// Get clipboard text content +// NOTE: returned string is allocated and freed by RGFW +const char *GetClipboardText(void) +{ + return RGFW_readClipboard(NULL); +} + +#if defined(SUPPORT_CLIPBOARD_IMAGE) +#if defined(_WIN32) + #define WIN32_CLIPBOARD_IMPLEMENTATION + #define WINUSER_ALREADY_INCLUDED + #define WINBASE_ALREADY_INCLUDED + #define WINGDI_ALREADY_INCLUDED + #include "../external/win32_clipboard.h" +#endif +#endif + +// Get clipboard image +Image GetClipboardImage(void) +{ + Image image = { 0 }; + unsigned long long int dataSize = 0; + void *fileData = NULL; + +#if defined(SUPPORT_CLIPBOARD_IMAGE) +#if defined(_WIN32) + int width = 0; + int height = 0; + fileData = (void *)Win32GetClipboardImageData(&width, &height, &dataSize); + + if (fileData == NULL) TRACELOG(LOG_WARNING, "Clipboard image: Couldn't get clipboard data"); + else image = LoadImageFromMemory(".bmp", fileData, dataSize); +#else + TRACELOG(LOG_WARNING, "Clipboard image: PLATFORM_DESKTOP_RGFW doesn't implement GetClipboardImage() for this OS"); +#endif +#endif // SUPPORT_CLIPBOARD_IMAGE + + return image; +} + +// Show mouse cursor +void ShowCursor(void) +{ + RGFW_window_showMouse(platform.window, true); + CORE.Input.Mouse.cursorHidden = false; +} + +// Hides mouse cursor +void HideCursor(void) +{ + RGFW_window_showMouse(platform.window, false); + CORE.Input.Mouse.cursorHidden = true; +} + +// Enables cursor (unlock cursor) +void EnableCursor(void) +{ + RGFW_disableCursor = false; + RGFW_window_mouseUnhold(platform.window); + + // Set cursor position in the middle + SetMousePosition(CORE.Window.screen.width/2, CORE.Window.screen.height/2); + RGFW_window_showMouse(platform.window, true); + CORE.Input.Mouse.cursorHidden = false; +} + +// Disables cursor (lock cursor) +void DisableCursor(void) +{ + RGFW_disableCursor = true; + RGFW_window_mouseHold(platform.window, RGFW_AREA(0, 0)); + HideCursor(); +} + +// Swap back buffer with front buffer (screen drawing) +void SwapScreenBuffer(void) +{ + RGFW_window_swapBuffers(platform.window); +} + +//---------------------------------------------------------------------------------- +// Module Functions Definition: Misc +//---------------------------------------------------------------------------------- + +// Get elapsed time measure in seconds since InitTimer() +double GetTime(void) +{ + return RGFW_getTime(); +} + +// Open URL with default system browser (if available) +// NOTE: This function is only safe to use if you control the URL given. +// A user could craft a malicious string performing another action. +// Only call this function yourself not with user input or make sure to check the string yourself. +// Ref: https://github.com/raysan5/raylib/issues/686 +void OpenURL(const char *url) +{ + // Security check to (partially) avoid malicious code on target platform + if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character"); + else + { + // TODO: Open URL implementation + } +} + +//---------------------------------------------------------------------------------- +// Module Functions Definition: Inputs +//---------------------------------------------------------------------------------- + +// Set internal gamepad mappings +int SetGamepadMappings(const char *mappings) +{ + TRACELOG(LOG_WARNING, "SetGamepadMappings() unsupported on target platform"); + return 0; +} + +// Set gamepad vibration +void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float duration) +{ + TRACELOG(LOG_WARNING, "SetGamepadVibration() unsupported on target platform"); +} + +// Set mouse position XY +void SetMousePosition(int x, int y) +{ + RGFW_window_moveMouse(platform.window, RGFW_POINT(x, y)); + CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y }; + CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition; +} + +// Set mouse cursor +void SetMouseCursor(int cursor) +{ + RGFW_window_setMouseStandard(platform.window, cursor); +} + +// Get physical key name. +const char *GetKeyName(int key) +{ + TRACELOG(LOG_WARNING, "GetKeyName() unsupported on target platform"); + + return ""; +} + +static KeyboardKey ConvertScancodeToKey(u32 keycode); + +int RGFW_gpConvTable[18] = { + [RGFW_gamepadY] = GAMEPAD_BUTTON_RIGHT_FACE_UP, + [RGFW_gamepadB] = GAMEPAD_BUTTON_RIGHT_FACE_RIGHT, + [RGFW_gamepadA] = GAMEPAD_BUTTON_RIGHT_FACE_DOWN, + [RGFW_gamepadX] = GAMEPAD_BUTTON_RIGHT_FACE_LEFT, + [RGFW_gamepadL1] = GAMEPAD_BUTTON_LEFT_TRIGGER_1, + [RGFW_gamepadR1] = GAMEPAD_BUTTON_RIGHT_TRIGGER_1, + [RGFW_gamepadL2] = GAMEPAD_BUTTON_LEFT_TRIGGER_2, + [RGFW_gamepadR2] = GAMEPAD_BUTTON_RIGHT_TRIGGER_2, + [RGFW_gamepadSelect] = GAMEPAD_BUTTON_MIDDLE_LEFT, + [RGFW_gamepadHome] = GAMEPAD_BUTTON_MIDDLE, + [RGFW_gamepadStart] = GAMEPAD_BUTTON_MIDDLE_RIGHT, + [RGFW_gamepadUp] = GAMEPAD_BUTTON_LEFT_FACE_UP, + [RGFW_gamepadRight] = GAMEPAD_BUTTON_LEFT_FACE_RIGHT, + [RGFW_gamepadDown] = GAMEPAD_BUTTON_LEFT_FACE_DOWN, + [RGFW_gamepadLeft] = GAMEPAD_BUTTON_LEFT_FACE_LEFT, + [RGFW_gamepadL3] = GAMEPAD_BUTTON_LEFT_THUMB, + [RGFW_gamepadR3] = GAMEPAD_BUTTON_RIGHT_THUMB, +}; + +// Register all input events +void PollInputEvents(void) +{ +#if defined(SUPPORT_GESTURES_SYSTEM) + // NOTE: Gestures update must be called every frame to reset gestures correctly + // because ProcessGestureEvent() is just called on an event, not every frame + UpdateGestures(); +#endif + + // Reset keys/chars pressed registered + CORE.Input.Keyboard.keyPressedQueueCount = 0; + CORE.Input.Keyboard.charPressedQueueCount = 0; + + // Reset mouse wheel + CORE.Input.Mouse.currentWheelMove.x = 0; + CORE.Input.Mouse.currentWheelMove.y = 0; + + // Register previous mouse position + + // Reset last gamepad button/axis registered state + for (int i = 0; (i < 4) && (i < MAX_GAMEPADS); i++) + { + // Check if gamepad is available + if (CORE.Input.Gamepad.ready[i]) + { + // Register previous gamepad button states + for (int k = 0; k < MAX_GAMEPAD_BUTTONS; k++) + { + CORE.Input.Gamepad.previousButtonState[i][k] = CORE.Input.Gamepad.currentButtonState[i][k]; + } + } + } + + // Register previous touch states + 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; + + 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 + + // Register previous keys states + // NOTE: Android supports up to 260 keys + for (int i = 0; i < MAX_KEYBOARD_KEYS; i++) + { + CORE.Input.Keyboard.previousKeyState[i] = CORE.Input.Keyboard.currentKeyState[i]; + CORE.Input.Keyboard.keyRepeatInFrame[i] = 0; + } + + // Register previous mouse states + for (int i = 0; i < MAX_MOUSE_BUTTONS; i++) CORE.Input.Mouse.previousButtonState[i] = CORE.Input.Mouse.currentButtonState[i]; + + // Poll input events for current platform + //----------------------------------------------------------------------------- + CORE.Window.resizedLastFrame = false; + + CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition; + if (platform.window->_flags & RGFW_HOLD_MOUSE) + { + CORE.Input.Mouse.previousPosition = (Vector2){ 0.0f, 0.0f }; + CORE.Input.Mouse.currentPosition = (Vector2){ 0.0f, 0.0f }; + } + else + { + CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition; + } + + if ((CORE.Window.eventWaiting) || (IsWindowState(FLAG_WINDOW_MINIMIZED) && !IsWindowState(FLAG_WINDOW_ALWAYS_RUN))) + { + RGFW_window_eventWait(platform.window, 0); // Wait for input events: keyboard/mouse/window events (callbacks) -> Update keys state + CORE.Time.previous = GetTime(); + } + + while (RGFW_window_checkEvent(platform.window)) + { + RGFW_event *event = &platform.window->event; + // All input events can be processed after polling + + switch (event->type) + { + case RGFW_mouseEnter: CORE.Input.Mouse.cursorOnScreen = true; break; + case RGFW_mouseLeave: CORE.Input.Mouse.cursorOnScreen = false; break; + case RGFW_quit: + event->type = 0; + CORE.Window.shouldClose = true; + return; + case RGFW_DND: // Dropped file + { + for (int i = 0; i < event->droppedFilesCount; i++) + { + if (CORE.Window.dropFileCount == 0) + { + // When a new file is dropped, we reserve a fixed number of slots for all possible dropped files + // at the moment we limit the number of drops at once to 1024 files but this behaviour should probably be reviewed + // TODO: Pointers should probably be reallocated for any new file added... + CORE.Window.dropFilepaths = (char **)RL_CALLOC(1024, sizeof(char *)); + + CORE.Window.dropFilepaths[CORE.Window.dropFileCount] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char)); + strcpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event->droppedFiles[i]); + + CORE.Window.dropFileCount++; + } + else if (CORE.Window.dropFileCount < 1024) + { + CORE.Window.dropFilepaths[CORE.Window.dropFileCount] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char)); + strcpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event->droppedFiles[i]); + + CORE.Window.dropFileCount++; + } + else TRACELOG(LOG_WARNING, "FILE: Maximum drag and drop files at once is limited to 1024 files!"); + } + } break; + + // Window events are also polled (Minimized, maximized, close...) + case RGFW_windowResized: + { + SetupViewport(platform.window->r.w, platform.window->r.h); + + // 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)(platform.window->r.w / GetWindowScaleDPI().x); + CORE.Window.screen.height = (int)(platform.window->r.h / GetWindowScaleDPI().y); + } + else + { + CORE.Window.screen.width = platform.window->r.w; + CORE.Window.screen.height = platform.window->r.h; + } + + CORE.Window.currentFbo.width = platform.window->r.w; + CORE.Window.currentFbo.height = platform.window->r.h; + CORE.Window.resizedLastFrame = true; + } break; + case RGFW_windowMaximized: + { + CORE.Window.flags |= FLAG_WINDOW_MAXIMIZED; // The window was maximized + } break; + case RGFW_windowMinimized: + { + CORE.Window.flags |= FLAG_WINDOW_MINIMIZED; // The window was iconified + } break; + case RGFW_windowRestored: + { + if (RGFW_window_isMaximized(platform.window)) + CORE.Window.flags &= ~FLAG_WINDOW_MAXIMIZED; // The window was restored + if (RGFW_window_isMinimized(platform.window)) + CORE.Window.flags &= ~FLAG_WINDOW_MINIMIZED; // The window was restored + } break; + case RGFW_windowMoved: + { + CORE.Window.position.x = platform.window->r.x; + CORE.Window.position.y = platform.window->r.x; + } break; + + // Keyboard events + case RGFW_keyPressed: + { + KeyboardKey key = ConvertScancodeToKey(event->key); + if (key != KEY_NULL) + { + // If key was up, add it to the key pressed queue + if ((CORE.Input.Keyboard.currentKeyState[key] == 0) && (CORE.Input.Keyboard.keyPressedQueueCount < MAX_KEY_PRESSED_QUEUE)) + { + CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = key; + CORE.Input.Keyboard.keyPressedQueueCount++; + } + + CORE.Input.Keyboard.currentKeyState[key] = 1; + } + + // TODO: Put exitKey verification outside the switch? + if (CORE.Input.Keyboard.currentKeyState[CORE.Input.Keyboard.exitKey]) + { + CORE.Window.shouldClose = true; + } + + // NOTE: event.text.text data comes an UTF-8 text sequence but we register codepoints (int) + // Check if there is space available in the queue + if (CORE.Input.Keyboard.charPressedQueueCount < MAX_CHAR_PRESSED_QUEUE) + { + // Add character (codepoint) to the queue + CORE.Input.Keyboard.charPressedQueue[CORE.Input.Keyboard.charPressedQueueCount] = event->keyChar; + CORE.Input.Keyboard.charPressedQueueCount++; + } + } break; + case RGFW_keyReleased: + { + KeyboardKey key = ConvertScancodeToKey(event->key); + if (key != KEY_NULL) CORE.Input.Keyboard.currentKeyState[key] = 0; + } break; + + // Check mouse events + case RGFW_mouseButtonPressed: + { + if ((event->button == RGFW_mouseScrollUp) || (event->button == RGFW_mouseScrollDown)) + { + CORE.Input.Mouse.currentWheelMove.y = event->scroll; + break; + } + else CORE.Input.Mouse.currentWheelMove.y = 0; + + int btn = event->button; + if (btn == RGFW_mouseLeft) btn = 1; + else if (btn == RGFW_mouseRight) btn = 2; + else if (btn == RGFW_mouseMiddle) btn = 3; + + CORE.Input.Mouse.currentButtonState[btn - 1] = 1; + CORE.Input.Touch.currentTouchState[btn - 1] = 1; + + touchAction = 1; + } break; + case RGFW_mouseButtonReleased: + { + if ((event->button == RGFW_mouseScrollUp) || (event->button == RGFW_mouseScrollDown)) + { + CORE.Input.Mouse.currentWheelMove.y = event->scroll; + break; + } + else CORE.Input.Mouse.currentWheelMove.y = 0; + + int btn = event->button; + if (btn == RGFW_mouseLeft) btn = 1; + else if (btn == RGFW_mouseRight) btn = 2; + else if (btn == RGFW_mouseMiddle) btn = 3; + + CORE.Input.Mouse.currentButtonState[btn - 1] = 0; + CORE.Input.Touch.currentTouchState[btn - 1] = 0; + + touchAction = 0; + } break; + case RGFW_mousePosChanged: + { + if (platform.window->_flags & RGFW_HOLD_MOUSE) + { + CORE.Input.Mouse.currentPosition.x += (float)event->vector.x; + CORE.Input.Mouse.currentPosition.y += (float)event->vector.y; + } + else + { + CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition; + CORE.Input.Mouse.currentPosition.x = (float)event->point.x; + CORE.Input.Mouse.currentPosition.y = (float)event->point.y; + } + + CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition; + touchAction = 2; + } break; + case RGFW_gamepadConnected: + { + CORE.Input.Gamepad.ready[platform.window->event.gamepad] = true; + CORE.Input.Gamepad.axisCount[platform.window->event.gamepad] = platform.window->event.axisesCount; + CORE.Input.Gamepad.axisState[platform.window->event.gamepad][GAMEPAD_AXIS_LEFT_TRIGGER] = -1.0f; + CORE.Input.Gamepad.axisState[platform.window->event.gamepad][GAMEPAD_AXIS_RIGHT_TRIGGER] = -1.0f; + + strcpy(CORE.Input.Gamepad.name[platform.window->event.gamepad], RGFW_getGamepadName(platform.window, platform.window->event.gamepad)); + } break; + case RGFW_gamepadDisconnected: + { + CORE.Input.Gamepad.ready[platform.window->event.gamepad] = false; + } break; + case RGFW_gamepadButtonPressed: + { + int button = RGFW_gpConvTable[event->button]; + + if (button >= 0) + { + CORE.Input.Gamepad.currentButtonState[event->gamepad][button] = 1; + CORE.Input.Gamepad.lastButtonPressed = button; + } + } break; + case RGFW_gamepadButtonReleased: + { + int button = RGFW_gpConvTable[event->button]; + + CORE.Input.Gamepad.currentButtonState[event->gamepad][button] = 0; + if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0; + } break; + case RGFW_gamepadAxisMove: + { + int axis = -1; + float value = 0; + + switch(event->whichAxis) + { + case 0: + { + CORE.Input.Gamepad.axisState[event->gamepad][GAMEPAD_AXIS_LEFT_X] = event->axis[0].x / 100.0f; + CORE.Input.Gamepad.axisState[event->gamepad][GAMEPAD_AXIS_LEFT_Y] = event->axis[0].y / 100.0f; + } break; + case 1: + { + CORE.Input.Gamepad.axisState[event->gamepad][GAMEPAD_AXIS_RIGHT_X] = event->axis[1].x / 100.0f; + CORE.Input.Gamepad.axisState[event->gamepad][GAMEPAD_AXIS_RIGHT_Y] = event->axis[1].y / 100.0f; + } break; + case 2: axis = GAMEPAD_AXIS_LEFT_TRIGGER; + case 3: + { + if (axis == -1) 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[event->gamepad][button] = pressed; + + if (pressed) CORE.Input.Gamepad.lastButtonPressed = button; + else if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0; + } + default: break; + } + } break; + default: break; + } + +#if defined(SUPPORT_GESTURES_SYSTEM) + if (touchAction > -1) + { + // Process mouse events as touches to be able to use mouse-gestures + GestureEvent gestureEvent = { 0 }; + + // Register touch actions + gestureEvent.touchAction = touchAction; + + // Assign a pointer ID + gestureEvent.pointId[0] = 0; + + // Register touch points count + gestureEvent.pointCount = 1; + + // Register touch points position, only one point registered + if (touchAction == 2 || realTouch) gestureEvent.position[0] = CORE.Input.Touch.position[0]; + else gestureEvent.position[0] = GetMousePosition(); + + // Normalize gestureEvent.position[0] for CORE.Window.screen.width and CORE.Window.screen.height + gestureEvent.position[0].x /= (float)GetScreenWidth(); + gestureEvent.position[0].y /= (float)GetScreenHeight(); + + // Gesture data is sent to gestures-system for processing + ProcessGestureEvent(gestureEvent); + + touchAction = -1; + } +#endif + } + //----------------------------------------------------------------------------- +} + +//---------------------------------------------------------------------------------- +// Module Internal Functions Definition +//---------------------------------------------------------------------------------- + +// Initialize platform: graphics, inputs and more +int InitPlatform(void) +{ + // Initialize RGFW internal global state, only required systems + unsigned int flags = RGFW_windowCenter | RGFW_windowAllowDND; + + // Check window creation flags + if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) > 0) + { + CORE.Window.fullscreen = true; + flags |= RGFW_windowFullscreen; + } + + if ((CORE.Window.flags & FLAG_BORDERLESS_WINDOWED_MODE) > 0) + { + CORE.Window.fullscreen = true; + flags |= RGFW_windowedFullscreen; + } + + if ((CORE.Window.flags & FLAG_WINDOW_UNDECORATED) > 0) flags |= RGFW_windowNoBorder; + if ((CORE.Window.flags & FLAG_WINDOW_RESIZABLE) == 0) flags |= RGFW_windowNoResize; + if ((CORE.Window.flags & FLAG_WINDOW_TRANSPARENT) > 0) flags |= RGFW_windowTransparent; + if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) > 0) flags |= RGFW_windowFullscreen; + if ((CORE.Window.flags & FLAG_WINDOW_HIDDEN) > 0) flags |= RGFW_windowHide; + if ((CORE.Window.flags & FLAG_WINDOW_MAXIMIZED) > 0) flags |= RGFW_windowMaximize; + + // NOTE: Some OpenGL context attributes must be set before window creation + // Check selection OpenGL version + if (rlGetVersion() == RL_OPENGL_21) + { + RGFW_setGLHint(RGFW_glMajor, 2); + RGFW_setGLHint(RGFW_glMinor, 1); + } + else if (rlGetVersion() == RL_OPENGL_33) + { + RGFW_setGLHint(RGFW_glMajor, 3); + RGFW_setGLHint(RGFW_glMinor, 3); + } + else if (rlGetVersion() == RL_OPENGL_43) + { + RGFW_setGLHint(RGFW_glMajor, 4); + RGFW_setGLHint(RGFW_glMinor, 3); + } + + if (CORE.Window.flags & FLAG_MSAA_4X_HINT) RGFW_setGLHint(RGFW_glSamples, 4); + + if (!(CORE.Window.flags & FLAG_WINDOW_UNFOCUSED)) flags |= RGFW_windowFocusOnShow | RGFW_windowFocus; + + platform.window = RGFW_createWindow(CORE.Window.title, RGFW_RECT(0, 0, CORE.Window.screen.width, CORE.Window.screen.height), flags); + platform.mon.mode.area.w = 0; + +#ifndef PLATFORM_WEB_RGFW + RGFW_area screenSize = RGFW_getScreenSize(); + CORE.Window.display.width = screenSize.w; + CORE.Window.display.height = screenSize.h; +#else + CORE.Window.display.width = CORE.Window.screen.width; + CORE.Window.display.height = CORE.Window.screen.height; +#endif + // TODO: Is this needed by raylib now? + // If so, rcore_desktop_sdl should be updated too + //SetupFramebuffer(CORE.Window.display.width, CORE.Window.display.height); + + if (CORE.Window.flags & FLAG_VSYNC_HINT) RGFW_window_swapInterval(platform.window, 1); + RGFW_window_makeCurrent(platform.window); + + // Check surface and context activation + if (platform.window != NULL) + { + CORE.Window.ready = true; + + CORE.Window.render.width = CORE.Window.screen.width; + CORE.Window.render.height = CORE.Window.screen.height; + CORE.Window.currentFbo.width = CORE.Window.render.width; + CORE.Window.currentFbo.height = CORE.Window.render.height; + } + else + { + TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize graphics device"); + return -1; + } + //---------------------------------------------------------------------------- + + // If everything work as expected, we can continue + CORE.Window.position.x = platform.window->r.x; + CORE.Window.position.y = platform.window->r.y; + CORE.Window.render.width = CORE.Window.screen.width; + CORE.Window.render.height = CORE.Window.screen.height; + CORE.Window.currentFbo.width = CORE.Window.render.width; + CORE.Window.currentFbo.height = CORE.Window.render.height; + + TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully"); + TRACELOG(LOG_INFO, " > Display size: %i x %i", CORE.Window.display.width, CORE.Window.display.height); + TRACELOG(LOG_INFO, " > Screen size: %i x %i", CORE.Window.screen.width, CORE.Window.screen.height); + TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height); + TRACELOG(LOG_INFO, " > Viewport offsets: %i, %i", CORE.Window.renderOffset.x, CORE.Window.renderOffset.y); + + // Load OpenGL extensions + // NOTE: GL procedures address loader is required to load extensions + //---------------------------------------------------------------------------- + rlLoadExtensions((void *)RGFW_getProcAddress); + //---------------------------------------------------------------------------- + + // Initialize timing system + //---------------------------------------------------------------------------- + InitTimer(); + //---------------------------------------------------------------------------- + + // Initialize storage system + //---------------------------------------------------------------------------- + CORE.Storage.basePath = GetWorkingDirectory(); + //---------------------------------------------------------------------------- + +#if defined(RGFW_WAYLAND) + if (RGFW_useWaylandBool) TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - Wayland): Initialized successfully"); + else TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - X11 (fallback)): Initialized successfully"); +#elif defined(RGFW_X11) + #if defined(__APPLE__) + TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - X11 (MacOS)): Initialized successfully"); + #else + TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - X11): Initialized successfully"); + #endif +#elif defined (RGFW_WINDOWS) + TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - Win32): Initialized successfully"); +#elif defined(RGFW_WASM) + TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - WASMs): Initialized successfully"); +#elif defined(RGFW_MACOS) + TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - MacOS): Initialized successfully"); +#endif + + return 0; +} + +// Close platform +void ClosePlatform(void) +{ + RGFW_window_close(platform.window); +} + +// Keycode mapping +static KeyboardKey ConvertScancodeToKey(u32 keycode) +{ + if (keycode > sizeof(keyMappingRGFW)/sizeof(unsigned short)) return 0; + + return keyMappingRGFW[keycode]; +}