minesweeper

A minewseeper implementation to play around with Hare and Raylib
git clone https://git.tronto.net/minesweeper
Download | Log | Files | Refs | README | LICENSE

rcore_desktop_rgfw.c (49130B)


      1 /**********************************************************************************************
      2 *
      3 *   rcore_desktop_rgfw - Functions to manage window, graphics device and inputs
      4 *
      5 *   PLATFORM: RGFW
      6 *       - Windows (Win32, Win64)
      7 *       - Linux (X11/Wayland desktop mode)
      8 *       - MacOS (Cocoa)
      9 *
     10 *   LIMITATIONS:
     11 *       - TODO
     12 *
     13 *   POSSIBLE IMPROVEMENTS:
     14 *       - TODO
     15 *
     16 *   ADDITIONAL NOTES:
     17 *       - TRACELOG() function is located in raylib [utils] module
     18 *
     19 *   CONFIGURATION:
     20 *       #define RCORE_PLATFORM_RGFW
     21 *           Custom flag for rcore on target platform RGFW
     22 *
     23 *   DEPENDENCIES:
     24 *       - RGFW.h (main library): Windowing and inputs management
     25 *       - gestures: Gestures system for touch-ready devices (or simulated from mouse inputs)
     26 *
     27 *
     28 *   LICENSE: zlib/libpng
     29 *
     30 *   Copyright (c) 2013-2024 Ramon Santamaria (@raysan5), Colleague Riley and contributors
     31 *
     32 *   This software is provided "as-is", without any express or implied warranty. In no event
     33 *   will the authors be held liable for any damages arising from the use of this software.
     34 *
     35 *   Permission is granted to anyone to use this software for any purpose, including commercial
     36 *   applications, and to alter it and redistribute it freely, subject to the following restrictions:
     37 *
     38 *     1. The origin of this software must not be misrepresented; you must not claim that you
     39 *     wrote the original software. If you use this software in a product, an acknowledgment
     40 *     in the product documentation would be appreciated but is not required.
     41 *
     42 *     2. Altered source versions must be plainly marked as such, and must not be misrepresented
     43 *     as being the original software.
     44 *
     45 *     3. This notice may not be removed or altered from any source distribution.
     46 *
     47 **********************************************************************************************/
     48 
     49 #if defined(GRAPHICS_API_OPENGL_ES2)
     50     #define RGFW_OPENGL_ES2
     51 #endif
     52 
     53 void ShowCursor(void);
     54 void CloseWindow(void);
     55 
     56 #if defined(__linux__)
     57     #define _INPUT_EVENT_CODES_H
     58 #endif
     59 
     60 #if defined(__unix__) || defined(__linux__)
     61     #define _XTYPEDEF_FONT
     62 #endif
     63 
     64 #define RGFW_IMPLEMENTATION
     65 
     66 #if defined(_WIN32) || defined(_WIN64)
     67     #define WIN32_LEAN_AND_MEAN
     68 	#define Rectangle rectangle_win32
     69     #define CloseWindow CloseWindow_win32
     70     #define ShowCursor __imp_ShowCursor
     71 	#define _APISETSTRING_
     72 	
     73 	#undef MAX_PATH
     74 
     75 	__declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int CodePage, unsigned long dwFlags, const char *lpMultiByteStr, int cbMultiByte, wchar_t *lpWideCharStr, int cchWideChar);
     76 #endif
     77 
     78 #if defined(__APPLE__)
     79     #define Point NSPOINT
     80     #define Size NSSIZE
     81 #endif
     82 
     83 #include "../external/RGFW.h"
     84 
     85 #if defined(_WIN32) || defined(_WIN64)
     86     #undef DrawText
     87     #undef ShowCursor
     88     #undef CloseWindow
     89     #undef Rectangle
     90 
     91 	#undef MAX_PATH
     92 	#define MAX_PATH 1025
     93 #endif
     94 
     95 #if defined(__APPLE__)
     96     #undef Point
     97     #undef Size
     98 #endif
     99 
    100 #include <stdbool.h>
    101 #include <string.h>     // Required for: strcmp()
    102 
    103 //----------------------------------------------------------------------------------
    104 // Types and Structures Definition
    105 //----------------------------------------------------------------------------------
    106 typedef struct {
    107     RGFW_window *window;                // Native display device (physical screen connection)
    108 } PlatformData;
    109 
    110 //----------------------------------------------------------------------------------
    111 // Global Variables Definition
    112 //----------------------------------------------------------------------------------
    113 extern CoreData CORE;                   // Global CORE state context
    114 
    115 static PlatformData platform = { NULL }; // Platform specific
    116 
    117 static bool RGFW_disableCursor = false;
    118 
    119 static const unsigned short keyMappingRGFW[] = {
    120     [RGFW_KEY_NULL] = KEY_NULL,
    121     [RGFW_Quote] = KEY_APOSTROPHE,
    122     [RGFW_Comma] = KEY_COMMA,
    123     [RGFW_Minus] = KEY_MINUS,
    124     [RGFW_Period] = KEY_PERIOD,
    125     [RGFW_Slash] = KEY_SLASH,
    126     [RGFW_Escape] = KEY_ESCAPE,
    127     [RGFW_F1] = KEY_F1,
    128     [RGFW_F2] = KEY_F2,
    129     [RGFW_F3] = KEY_F3,
    130     [RGFW_F4] = KEY_F4,
    131     [RGFW_F5] = KEY_F5,
    132     [RGFW_F6] = KEY_F6,
    133     [RGFW_F7] = KEY_F7,
    134     [RGFW_F8] = KEY_F8,
    135     [RGFW_F9] = KEY_F9,
    136     [RGFW_F10] = KEY_F10,
    137     [RGFW_F11] = KEY_F11,
    138     [RGFW_F12] = KEY_F12,
    139     [RGFW_Backtick] = KEY_GRAVE,
    140     [RGFW_0] = KEY_ZERO,
    141     [RGFW_1] = KEY_ONE,
    142     [RGFW_2] = KEY_TWO,
    143     [RGFW_3] = KEY_THREE,
    144     [RGFW_4] = KEY_FOUR,
    145     [RGFW_5] = KEY_FIVE,
    146     [RGFW_6] = KEY_SIX,
    147     [RGFW_7] = KEY_SEVEN,
    148     [RGFW_8] = KEY_EIGHT,
    149     [RGFW_9] = KEY_NINE,
    150     [RGFW_Equals] = KEY_EQUAL,
    151     [RGFW_BackSpace] = KEY_BACKSPACE,
    152     [RGFW_Tab] = KEY_TAB,
    153     [RGFW_CapsLock] = KEY_CAPS_LOCK,
    154     [RGFW_ShiftL] = KEY_LEFT_SHIFT,
    155     [RGFW_ControlL] = KEY_LEFT_CONTROL,
    156     [RGFW_AltL] = KEY_LEFT_ALT,
    157     [RGFW_SuperL] = KEY_LEFT_SUPER,
    158     #ifndef RGFW_MACOS
    159     [RGFW_ShiftR] = KEY_RIGHT_SHIFT,
    160 
    161     [RGFW_AltR] = KEY_RIGHT_ALT,
    162     #endif
    163     [RGFW_Space] = KEY_SPACE,
    164 
    165     [RGFW_a] = KEY_A,
    166     [RGFW_b] = KEY_B,
    167     [RGFW_c] = KEY_C,
    168     [RGFW_d] = KEY_D,
    169     [RGFW_e] = KEY_E,
    170     [RGFW_f] = KEY_F,
    171     [RGFW_g] = KEY_G,
    172     [RGFW_h] = KEY_H,
    173     [RGFW_i] = KEY_I,
    174     [RGFW_j] = KEY_J,
    175     [RGFW_k] = KEY_K,
    176     [RGFW_l] = KEY_L,
    177     [RGFW_m] = KEY_M,
    178     [RGFW_n] = KEY_N,
    179     [RGFW_o] = KEY_O,
    180     [RGFW_p] = KEY_P,
    181     [RGFW_q] = KEY_Q,
    182     [RGFW_r] = KEY_R,
    183     [RGFW_s] = KEY_S,
    184     [RGFW_t] = KEY_T,
    185     [RGFW_u] = KEY_U,
    186     [RGFW_v] = KEY_V,
    187     [RGFW_w] = KEY_W,
    188     [RGFW_x] = KEY_X,
    189     [RGFW_y] = KEY_Y,
    190     [RGFW_z] = KEY_Z,
    191     [RGFW_Bracket] = KEY_LEFT_BRACKET,
    192     [RGFW_BackSlash] = KEY_BACKSLASH,
    193     [RGFW_CloseBracket] = KEY_RIGHT_BRACKET,
    194     [RGFW_Semicolon] = KEY_SEMICOLON,
    195     [RGFW_Insert] = KEY_INSERT,
    196     [RGFW_Home] = KEY_HOME,
    197     [RGFW_PageUp] = KEY_PAGE_UP,
    198     [RGFW_Delete] = KEY_DELETE,
    199     [RGFW_End] = KEY_END,
    200     [RGFW_PageDown] = KEY_PAGE_DOWN,
    201     [RGFW_Right] = KEY_RIGHT,
    202     [RGFW_Left] = KEY_LEFT,
    203     [RGFW_Down] = KEY_DOWN,
    204     [RGFW_Up] = KEY_UP,
    205     [RGFW_Numlock] = KEY_NUM_LOCK,
    206     [RGFW_KP_Slash] = KEY_KP_DIVIDE,
    207     [RGFW_Multiply] = KEY_KP_MULTIPLY,
    208     [RGFW_KP_Minus] = KEY_KP_SUBTRACT,
    209     [RGFW_KP_Return] = KEY_KP_ENTER,
    210     [RGFW_KP_1] = KEY_KP_1,
    211     [RGFW_KP_2] = KEY_KP_2,
    212     [RGFW_KP_3] = KEY_KP_3,
    213     [RGFW_KP_4] = KEY_KP_4,
    214     [RGFW_KP_5] = KEY_KP_5,
    215     [RGFW_KP_6] = KEY_KP_6,
    216     [RGFW_KP_7] = KEY_KP_7,
    217     [RGFW_KP_8] = KEY_KP_8,
    218     [RGFW_KP_9] = KEY_KP_9,
    219     [RGFW_KP_0] = KEY_KP_0,
    220     [RGFW_KP_Period] = KEY_KP_DECIMAL
    221 };
    222 
    223 //----------------------------------------------------------------------------------
    224 // Module Internal Functions Declaration
    225 //----------------------------------------------------------------------------------
    226 int InitPlatform(void);          // Initialize platform (graphics, inputs and more)
    227 bool InitGraphicsDevice(void);   // Initialize graphics device
    228 
    229 //----------------------------------------------------------------------------------
    230 // Module Functions Declaration
    231 //----------------------------------------------------------------------------------
    232 // NOTE: Functions declaration is provided by raylib.h
    233 
    234 //----------------------------------------------------------------------------------
    235 // Module Functions Definition: Window and Graphics Device
    236 //----------------------------------------------------------------------------------
    237 
    238 // Check if application should close
    239 bool WindowShouldClose(void)
    240 {
    241     if (CORE.Window.shouldClose == false)
    242         CORE.Window.shouldClose = RGFW_window_shouldClose(platform.window);
    243     if (CORE.Window.ready) return CORE.Window.shouldClose;
    244     else return true;
    245 }
    246 
    247 // Toggle fullscreen mode
    248 void ToggleFullscreen(void)
    249 {   
    250     RGFW_window_maximize(platform.window);
    251     ToggleBorderlessWindowed();
    252 }
    253 
    254 // Toggle borderless windowed mode
    255 void ToggleBorderlessWindowed(void)
    256 {
    257     if (platform.window != NULL)
    258     {
    259         RGFW_window_setBorder(platform.window, CORE.Window.flags & FLAG_WINDOW_UNDECORATED);
    260     }
    261 }
    262 
    263 // Set window state: maximized, if resizable
    264 void MaximizeWindow(void)
    265 {
    266     RGFW_window_maximize(platform.window);
    267 }
    268 
    269 // Set window state: minimized
    270 void MinimizeWindow(void)
    271 {
    272     RGFW_window_minimize(platform.window);
    273 }
    274 
    275 // Set window state: not minimized/maximized
    276 void RestoreWindow(void)
    277 {
    278     RGFW_window_restore(platform.window);
    279 }
    280 
    281 // Set window configuration state using flags
    282 void SetWindowState(unsigned int flags)
    283 {
    284     CORE.Window.flags |= flags;
    285 
    286     if (flags & FLAG_VSYNC_HINT)
    287     {
    288         RGFW_window_swapInterval(platform.window, 1);
    289     }
    290     if (flags & FLAG_FULLSCREEN_MODE)
    291     {
    292         RGFW_window_maximize(platform.window);
    293         ToggleBorderlessWindowed();
    294     }
    295     if (flags & FLAG_WINDOW_RESIZABLE)
    296     {
    297         RGFW_window_setMaxSize(platform.window, RGFW_AREA(platform.window->r.w, platform.window->r.h));
    298         RGFW_window_setMinSize(platform.window, RGFW_AREA(platform.window->r.w, platform.window->r.h));
    299     }
    300     if (flags & FLAG_WINDOW_UNDECORATED)
    301     {
    302         ToggleBorderlessWindowed();
    303     }
    304     if (flags & FLAG_WINDOW_HIDDEN)
    305     {
    306         RGFW_window_hide(platform.window);
    307     }
    308     if (flags & FLAG_WINDOW_MINIMIZED)
    309     {
    310         RGFW_window_minimize(platform.window);
    311     }
    312     if (flags & FLAG_WINDOW_MAXIMIZED)
    313     {
    314         RGFW_window_maximize(platform.window);
    315     }
    316     if (flags & FLAG_WINDOW_UNFOCUSED)
    317     {
    318         TRACELOG(LOG_WARNING, "SetWindowState() - FLAG_WINDOW_UNFOCUSED is not supported on PLATFORM_DESKTOP_RGFW");
    319     }
    320     if (flags & FLAG_WINDOW_TOPMOST)
    321     {
    322         TRACELOG(LOG_WARNING, "SetWindowState() - FLAG_WINDOW_TOPMOST is not supported on PLATFORM_DESKTOP_RGFW");
    323     }
    324     if (flags & FLAG_WINDOW_ALWAYS_RUN)
    325     {
    326         TRACELOG(LOG_WARNING, "SetWindowState() - FLAG_WINDOW_ALWAYS_RUN is not supported on PLATFORM_DESKTOP_RGFW");
    327     }
    328     if (flags & FLAG_WINDOW_TRANSPARENT)
    329     {
    330         TRACELOG(LOG_WARNING, "SetWindowState() - FLAG_WINDOW_TRANSPARENT post window creation post window creation is not supported on PLATFORM_DESKTOP_RGFW");
    331     }
    332     if (flags & FLAG_WINDOW_HIGHDPI)
    333     {
    334         TRACELOG(LOG_WARNING, "SetWindowState() - FLAG_WINDOW_HIGHDPI is not supported on PLATFORM_DESKTOP_RGFW");
    335     }
    336     if (flags & FLAG_WINDOW_MOUSE_PASSTHROUGH)
    337     {
    338         RGFW_window_setMousePassthrough(platform.window, flags & FLAG_WINDOW_MOUSE_PASSTHROUGH);
    339     }
    340     if (flags & FLAG_BORDERLESS_WINDOWED_MODE)
    341     {
    342         ToggleBorderlessWindowed();
    343     }
    344     if (flags & FLAG_MSAA_4X_HINT)
    345     {
    346         RGFW_setGLSamples(4);
    347     }
    348     if (flags & FLAG_INTERLACED_HINT)
    349     {
    350         TRACELOG(LOG_WARNING, "SetWindowState() - FLAG_INTERLACED_HINT is not supported on PLATFORM_DESKTOP_RGFW");
    351     }
    352 }
    353 
    354 // Clear window configuration state flags
    355 void ClearWindowState(unsigned int flags)
    356 {
    357     CORE.Window.flags &= ~flags;
    358 
    359     if (flags & FLAG_VSYNC_HINT)
    360     {
    361         RGFW_window_swapInterval(platform.window, 0);
    362     }
    363     if (flags & FLAG_FULLSCREEN_MODE)
    364     {
    365         ToggleBorderlessWindowed();
    366         RGFW_window_restore(platform.window);
    367         CORE.Window.fullscreen = false;
    368     }
    369     if (flags & FLAG_WINDOW_RESIZABLE)
    370     {
    371         RGFW_window_setMaxSize(platform.window, RGFW_AREA(0, 0));
    372         RGFW_window_setMinSize(platform.window, RGFW_AREA(0, 0));
    373     }
    374     if (flags & FLAG_WINDOW_UNDECORATED)
    375     {
    376         ToggleBorderlessWindowed();
    377     }
    378     if (flags & FLAG_WINDOW_HIDDEN)
    379     {
    380         RGFW_window_show(platform.window);
    381     }
    382     if (flags & FLAG_WINDOW_MINIMIZED)
    383     {
    384         RGFW_window_restore(platform.window);
    385     }
    386     if (flags & FLAG_WINDOW_MAXIMIZED)
    387     {
    388         RGFW_window_restore(platform.window);
    389     }
    390     if (flags & FLAG_WINDOW_UNFOCUSED)
    391     {
    392         TRACELOG(LOG_WARNING, "ClearWindowState() - FLAG_WINDOW_UNFOCUSED is not supported on PLATFORM_DESKTOP_RGFW");
    393     }
    394     if (flags & FLAG_WINDOW_TOPMOST)
    395     {
    396         TRACELOG(LOG_WARNING, "ClearWindowState() - FLAG_WINDOW_TOPMOST is not supported on PLATFORM_DESKTOP_RGFW");
    397     }
    398     if (flags & FLAG_WINDOW_ALWAYS_RUN)
    399     {
    400         TRACELOG(LOG_WARNING, "ClearWindowState() - FLAG_WINDOW_ALWAYS_RUN is not supported on PLATFORM_DESKTOP_RGFW");
    401     }
    402     if (flags & FLAG_WINDOW_TRANSPARENT)
    403     {
    404         TRACELOG(LOG_WARNING, "ClearWindowState() - FLAG_WINDOW_TRANSPARENT is not supported on PLATFORM_DESKTOP_RGFW");
    405     }
    406     if (flags & FLAG_WINDOW_HIGHDPI)
    407     {
    408         // NOTE: There also doesn't seem to be a feature to disable high DPI once enabled
    409         TRACELOG(LOG_WARNING, "ClearWindowState() - FLAG_WINDOW_HIGHDPI is not supported on PLATFORM_DESKTOP_RGFW");
    410     }
    411     if (flags & FLAG_WINDOW_MOUSE_PASSTHROUGH)
    412     {
    413         RGFW_window_setMousePassthrough(platform.window, flags & FLAG_WINDOW_MOUSE_PASSTHROUGH);
    414         TRACELOG(LOG_WARNING, "ClearWindowState() - FLAG_WINDOW_MOUSE_PASSTHROUGH is not supported on PLATFORM_DESKTOP_RGFW");
    415     }
    416     if (flags & FLAG_BORDERLESS_WINDOWED_MODE)
    417     {
    418         ToggleFullscreen();
    419     }
    420     if (flags & FLAG_MSAA_4X_HINT)
    421     {
    422         RGFW_setGLSamples(0);
    423     }
    424     if (flags & FLAG_INTERLACED_HINT)
    425     {
    426         TRACELOG(LOG_WARNING, "ClearWindowState() - FLAG_INTERLACED_HINT is not supported on PLATFORM_DESKTOP_RGFW");
    427     }
    428 }
    429 
    430 // Set icon for window
    431 void SetWindowIcon(Image image)
    432 {
    433     i32 channels = 4;
    434 
    435     switch (image.format)
    436     {
    437         case PIXELFORMAT_UNCOMPRESSED_GRAYSCALE:
    438         case PIXELFORMAT_UNCOMPRESSED_R16:           // 16 bpp (1 channel - half float)
    439         case PIXELFORMAT_UNCOMPRESSED_R32:           // 32 bpp (1 channel - float)
    440         {
    441             channels = 1;
    442         } break;
    443         case PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA:    // 8*2 bpp (2 channels)
    444         case PIXELFORMAT_UNCOMPRESSED_R5G6B5:        // 16 bpp
    445         case PIXELFORMAT_UNCOMPRESSED_R8G8B8:        // 24 bpp
    446         case PIXELFORMAT_UNCOMPRESSED_R5G5B5A1:      // 16 bpp (1 bit alpha)
    447         case PIXELFORMAT_UNCOMPRESSED_R4G4B4A4:      // 16 bpp (4 bit alpha)
    448         case PIXELFORMAT_UNCOMPRESSED_R8G8B8A8:      // 32 bpp
    449         {
    450             channels = 2;
    451         } break;
    452         case PIXELFORMAT_UNCOMPRESSED_R32G32B32:     // 32*3 bpp (3 channels - float)
    453         case PIXELFORMAT_UNCOMPRESSED_R16G16B16:     // 16*3 bpp (3 channels - half float)
    454         case PIXELFORMAT_COMPRESSED_DXT1_RGB:        // 4 bpp (no alpha)
    455         case PIXELFORMAT_COMPRESSED_ETC1_RGB:        // 4 bpp
    456         case PIXELFORMAT_COMPRESSED_ETC2_RGB:        // 4 bpp
    457         case PIXELFORMAT_COMPRESSED_PVRT_RGB:        // 4 bpp
    458         {
    459             channels = 3;
    460         } break;
    461         case PIXELFORMAT_UNCOMPRESSED_R32G32B32A32:  // 32*4 bpp (4 channels - float)
    462         case PIXELFORMAT_UNCOMPRESSED_R16G16B16A16:  // 16*4 bpp (4 channels - half float)
    463         case PIXELFORMAT_COMPRESSED_DXT1_RGBA:       // 4 bpp (1 bit alpha)
    464         case PIXELFORMAT_COMPRESSED_DXT3_RGBA:       // 8 bpp
    465         case PIXELFORMAT_COMPRESSED_DXT5_RGBA:       // 8 bpp
    466         case PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA:   // 8 bpp
    467         case PIXELFORMAT_COMPRESSED_PVRT_RGBA:       // 4 bpp
    468         case PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA:   // 8 bpp
    469         case PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA:   // 2 bpp
    470         {
    471             channels = 4;
    472         } break;
    473         default: break;
    474     }
    475 
    476     RGFW_window_setIcon(platform.window, image.data, RGFW_AREA(image.width, image.height), channels);
    477 }
    478 
    479 // Set icon for window
    480 void SetWindowIcons(Image *images, int count)
    481 {
    482     TRACELOG(LOG_WARNING, "SetWindowIcons() not available on target platform");
    483 }
    484 
    485 // Set title for window
    486 void SetWindowTitle(const char *title)
    487 {
    488     RGFW_window_setName(platform.window, (char*)title);
    489     CORE.Window.title = title;
    490 }
    491 
    492 // Set window position on screen (windowed mode)
    493 void SetWindowPosition(int x, int y)
    494 {
    495     RGFW_window_move(platform.window, RGFW_POINT(x, y));
    496 }
    497 
    498 // Set monitor for the current window
    499 void SetWindowMonitor(int monitor)
    500 {
    501     RGFW_window_moveToMonitor(platform.window, RGFW_getMonitors()[monitor]);
    502 }
    503 
    504 // Set window minimum dimensions (FLAG_WINDOW_RESIZABLE)
    505 void SetWindowMinSize(int width, int height)
    506 {
    507     RGFW_window_setMinSize(platform.window, RGFW_AREA(width, height));
    508     CORE.Window.screenMin.width = width;
    509     CORE.Window.screenMin.height = height;
    510 }
    511 
    512 // Set window maximum dimensions (FLAG_WINDOW_RESIZABLE)
    513 void SetWindowMaxSize(int width, int height)
    514 {
    515     RGFW_window_setMaxSize(platform.window, RGFW_AREA(width, height));
    516     CORE.Window.screenMax.width = width;
    517     CORE.Window.screenMax.height = height;
    518 }
    519 
    520 // Set window dimensions
    521 void SetWindowSize(int width, int height)
    522 {
    523     CORE.Window.screen.width = width;
    524     CORE.Window.screen.height = height;
    525 
    526     RGFW_window_resize(platform.window, RGFW_AREA(width, height));
    527 }
    528 
    529 // Set window opacity, value opacity is between 0.0 and 1.0
    530 void SetWindowOpacity(float opacity)
    531 {
    532     TRACELOG(LOG_WARNING, "SetWindowOpacity() not available on target platform");
    533 }
    534 
    535 // Set window focused
    536 void SetWindowFocused(void)
    537 {
    538     RGFW_window_show(platform.window);
    539 }
    540 
    541 // Get native window handle
    542 void *GetWindowHandle(void)
    543 {
    544 #ifdef RGFW_WEBASM
    545     return (void*)platform.window->src.ctx;
    546 #else
    547     return (void*)platform.window->src.window;
    548 #endif
    549 }
    550 
    551 // Get number of monitors
    552 int GetMonitorCount(void)
    553 {
    554     #define MAX_MONITORS_SUPPORTED 6
    555 
    556     int count = MAX_MONITORS_SUPPORTED;
    557     RGFW_monitor *mons = RGFW_getMonitors();
    558 
    559     for (int i = 0; i < 6; i++)
    560     {
    561         if (!mons[i].rect.x && !mons[i].rect.y && !mons[i].rect.w && mons[i].rect.h)
    562         {
    563             count = i;
    564             break;
    565         }
    566     }
    567 
    568     return count;
    569 }
    570 
    571 // Get number of monitors
    572 int GetCurrentMonitor(void)
    573 {
    574     RGFW_monitor *mons = RGFW_getMonitors();
    575     RGFW_monitor mon = RGFW_window_getMonitor(platform.window);
    576 
    577     for (int i = 0; i < 6; i++)
    578     {
    579         if ((mons[i].rect.x ==  mon.rect.x) && (mons[i].rect.y ==  mon.rect.y)) return i;
    580     }
    581 
    582     return 0;
    583 }
    584 
    585 // Get selected monitor position
    586 Vector2 GetMonitorPosition(int monitor)
    587 {
    588     RGFW_monitor *mons = RGFW_getMonitors();
    589 
    590     return (Vector2){mons[monitor].rect.x, mons[monitor].rect.y};
    591 }
    592 
    593 // Get selected monitor width (currently used by monitor)
    594 int GetMonitorWidth(int monitor)
    595 {
    596     RGFW_monitor *mons = RGFW_getMonitors();
    597 
    598     return mons[monitor].rect.w;
    599 }
    600 
    601 // Get selected monitor height (currently used by monitor)
    602 int GetMonitorHeight(int monitor)
    603 {
    604     RGFW_monitor *mons = RGFW_getMonitors();
    605 
    606     return mons[monitor].rect.h;
    607 }
    608 
    609 // Get selected monitor physical width in millimetres
    610 int GetMonitorPhysicalWidth(int monitor)
    611 {
    612     RGFW_monitor* mons = RGFW_getMonitors();
    613 
    614     return mons[monitor].physW;
    615 }
    616 
    617 // Get selected monitor physical height in millimetres
    618 int GetMonitorPhysicalHeight(int monitor)
    619 {
    620     RGFW_monitor *mons = RGFW_getMonitors();
    621 
    622     return mons[monitor].physH;
    623 }
    624 
    625 // Get selected monitor refresh rate
    626 int GetMonitorRefreshRate(int monitor)
    627 {
    628     TRACELOG(LOG_WARNING, "GetMonitorRefreshRate() not implemented on target platform");
    629     return 0;
    630 }
    631 
    632 // Get the human-readable, UTF-8 encoded name of the selected monitor
    633 const char *GetMonitorName(int monitor)
    634 {
    635     RGFW_monitor *mons = RGFW_getMonitors();
    636 
    637     return mons[monitor].name;
    638 }
    639 
    640 // Get window position XY on monitor
    641 Vector2 GetWindowPosition(void)
    642 {
    643     return (Vector2){ platform.window->r.x, platform.window->r.y };
    644 }
    645 
    646 // Get window scale DPI factor for current monitor
    647 Vector2 GetWindowScaleDPI(void)
    648 {
    649     RGFW_monitor monitor = RGFW_window_getMonitor(platform.window);
    650 
    651     return (Vector2){monitor.scaleX, monitor.scaleX};
    652 }
    653 
    654 // Set clipboard text content
    655 void SetClipboardText(const char *text)
    656 {
    657     RGFW_writeClipboard(text, strlen(text));
    658 }
    659 
    660 // Get clipboard text content
    661 // NOTE: returned string is allocated and freed by GLFW
    662 const char *GetClipboardText(void)
    663 {
    664     return RGFW_readClipboard(NULL);
    665 }
    666 
    667 
    668 #if defined(SUPPORT_CLIPBOARD_IMAGE)
    669 
    670 #ifdef _WIN32
    671 #   define WIN32_CLIPBOARD_IMPLEMENTATION
    672 #   define WINUSER_ALREADY_INCLUDED
    673 #   define WINBASE_ALREADY_INCLUDED
    674 #   define WINGDI_ALREADY_INCLUDED
    675 #   include "../external/win32_clipboard.h"
    676 #endif
    677 
    678 // Get clipboard image
    679 Image GetClipboardImage(void)
    680 {
    681     Image image = {0};
    682     unsigned long long int dataSize = 0;
    683     void* fileData = NULL;
    684 
    685 #ifdef _WIN32
    686     int width, height;
    687     fileData  = (void*)Win32GetClipboardImageData(&width, &height, &dataSize);
    688 #else
    689     TRACELOG(LOG_WARNING, "Clipboard image: PLATFORM_DESKTOP_RGFW doesn't implement `GetClipboardImage` for this OS");
    690 #endif
    691 
    692     if (fileData == NULL)
    693     {
    694         TRACELOG(LOG_WARNING, "Clipboard image: Couldn't get clipboard data.");
    695     }
    696     else
    697     {
    698         image = LoadImageFromMemory(".bmp", fileData, dataSize);
    699     }
    700     return image;
    701 }
    702 #endif // SUPPORT_CLIPBOARD_IMAGE
    703 
    704 // Show mouse cursor
    705 void ShowCursor(void)
    706 {
    707     RGFW_window_showMouse(platform.window, true);
    708     CORE.Input.Mouse.cursorHidden = false;
    709 }
    710 
    711 // Hides mouse cursor
    712 void HideCursor(void)
    713 {
    714     RGFW_window_showMouse(platform.window, false);
    715     CORE.Input.Mouse.cursorHidden = true;
    716 }
    717 
    718 // Enables cursor (unlock cursor)
    719 void EnableCursor(void)
    720 {
    721     RGFW_disableCursor = false;
    722     RGFW_window_mouseUnhold(platform.window);
    723 
    724     // Set cursor position in the middle
    725     SetMousePosition(CORE.Window.screen.width/2, CORE.Window.screen.height/2);
    726     RGFW_window_showMouse(platform.window, true);
    727     CORE.Input.Mouse.cursorHidden = false;
    728 }
    729 
    730 // Disables cursor (lock cursor)
    731 void DisableCursor(void)
    732 {
    733     RGFW_disableCursor = true;
    734 
    735     RGFW_window_mouseHold(platform.window, RGFW_AREA(0, 0));
    736 
    737     HideCursor();
    738 }
    739 
    740 // Swap back buffer with front buffer (screen drawing)
    741 void SwapScreenBuffer(void)
    742 {
    743     RGFW_window_swapBuffers(platform.window);
    744 }
    745 
    746 //----------------------------------------------------------------------------------
    747 // Module Functions Definition: Misc
    748 //----------------------------------------------------------------------------------
    749 
    750 // Get elapsed time measure in seconds since InitTimer()
    751 double GetTime(void)
    752 {
    753     double time = 0.0;
    754     unsigned long long int nanoSeconds = RGFW_getTimeNS();
    755     time = (double)(nanoSeconds - CORE.Time.base)*1e-9;  // Elapsed time since InitTimer()
    756 
    757     return time;
    758 }
    759 
    760 // Open URL with default system browser (if available)
    761 // NOTE: This function is only safe to use if you control the URL given.
    762 // A user could craft a malicious string performing another action.
    763 // Only call this function yourself not with user input or make sure to check the string yourself.
    764 // Ref: https://github.com/raysan5/raylib/issues/686
    765 void OpenURL(const char *url)
    766 {
    767     // Security check to (partially) avoid malicious code on target platform
    768     if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character");
    769     else
    770     {
    771         // TODO: Open URL implementation
    772     }
    773 }
    774 
    775 //----------------------------------------------------------------------------------
    776 // Module Functions Definition: Inputs
    777 //----------------------------------------------------------------------------------
    778 
    779 // Set internal gamepad mappings
    780 int SetGamepadMappings(const char *mappings)
    781 {
    782     TRACELOG(LOG_WARNING, "SetGamepadMappings() not implemented on target platform");
    783     return 0;
    784 }
    785 
    786 // Set mouse position XY
    787 void SetMousePosition(int x, int y)
    788 {
    789     RGFW_window_moveMouse(platform.window, RGFW_POINT(x, y));
    790     CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y };
    791     CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
    792 }
    793 
    794 // Set mouse cursor
    795 void SetMouseCursor(int cursor)
    796 {
    797     RGFW_window_setMouseStandard(platform.window, cursor);
    798 }
    799 
    800 // Get physical key name.
    801 const char *GetKeyName(int key)
    802 {
    803     TRACELOG(LOG_WARNING, "GetKeyName() not implemented on target platform");
    804     return "";
    805 }
    806 
    807 static KeyboardKey ConvertScancodeToKey(u32 keycode);
    808 
    809 // TODO: Review function to avoid duplicate with RSGL
    810 char RSGL_keystrToChar(const char *str)
    811 {
    812     if (str[1] == 0) return str[0];
    813 
    814     static const char *map[] = {
    815         "asciitilde", "`",
    816         "grave", "~",
    817         "exclam", "!",
    818         "at", "@",
    819         "numbersign", "#",
    820         "dollar", "$",
    821         "percent", "%%",
    822         "asciicircum", "^",
    823         "ampersand", "&",
    824         "asterisk", "*",
    825         "parenleft", "(",
    826         "parenright", ")",
    827         "underscore", "_",
    828         "minus", "-",
    829         "plus", "+",
    830         "equal", "=",
    831         "braceleft", "{",
    832         "bracketleft", "[",
    833         "bracketright", "]",
    834         "braceright", "}",
    835         "colon", ":",
    836         "semicolon", ";",
    837         "quotedbl", "\"",
    838         "apostrophe", "'",
    839         "bar", "|",
    840         "backslash", "\'",
    841         "less", "<",
    842         "comma", ",",
    843         "greater", ">",
    844         "period", ".",
    845         "question", "?",
    846         "slash", "/",
    847         "space", " ",
    848         "Return", "\n",
    849         "Enter", "\n",
    850         "enter", "\n",
    851     };
    852 
    853     for (unsigned char i = 0; i < (sizeof(map)/sizeof(char *)); i += 2)
    854     {
    855         if (strcmp(map[i], str) == 0) return *map[i + 1];
    856     }
    857 
    858     return '\0';
    859 }
    860 
    861 // Register all input events
    862 void PollInputEvents(void)
    863 {
    864 #if defined(SUPPORT_GESTURES_SYSTEM)
    865     // NOTE: Gestures update must be called every frame to reset gestures correctly
    866     // because ProcessGestureEvent() is just called on an event, not every frame
    867     UpdateGestures();
    868 #endif
    869 
    870     // Reset keys/chars pressed registered
    871     CORE.Input.Keyboard.keyPressedQueueCount = 0;
    872     CORE.Input.Keyboard.charPressedQueueCount = 0;
    873 
    874     // Reset mouse wheel
    875     CORE.Input.Mouse.currentWheelMove.x = 0;
    876     CORE.Input.Mouse.currentWheelMove.y = 0;
    877 
    878     // Register previous mouse position
    879 
    880     // Reset last gamepad button/axis registered state
    881 
    882     for (int i = 0; (i < 4) && (i < MAX_GAMEPADS); i++)
    883     {
    884         // Check if gamepad is available
    885         if (CORE.Input.Gamepad.ready[i])
    886         {
    887             // Register previous gamepad button states
    888             for (int k = 0; k < MAX_GAMEPAD_BUTTONS; k++)
    889             {
    890                 CORE.Input.Gamepad.previousButtonState[i][k] = CORE.Input.Gamepad.currentButtonState[i][k];
    891             }
    892         }
    893     }
    894 
    895     // Register previous touch states
    896     for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.previousTouchState[i] = CORE.Input.Touch.currentTouchState[i];
    897 
    898     // Map touch position to mouse position for convenience
    899     CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition;
    900 
    901     int touchAction = -1;       // 0-TOUCH_ACTION_UP, 1-TOUCH_ACTION_DOWN, 2-TOUCH_ACTION_MOVE
    902     bool realTouch = false;     // Flag to differentiate real touch gestures from mouse ones
    903 
    904     // Register previous keys states
    905     // NOTE: Android supports up to 260 keys
    906     for (int i = 0; i < MAX_KEYBOARD_KEYS; i++)
    907     {
    908         CORE.Input.Keyboard.previousKeyState[i] = CORE.Input.Keyboard.currentKeyState[i];
    909         CORE.Input.Keyboard.keyRepeatInFrame[i] = 0;
    910     }
    911 
    912     // Register previous mouse states
    913     for (int i = 0; i < MAX_MOUSE_BUTTONS; i++) CORE.Input.Mouse.previousButtonState[i] = CORE.Input.Mouse.currentButtonState[i];
    914 
    915     // Poll input events for current platform
    916     //-----------------------------------------------------------------------------
    917     CORE.Window.resizedLastFrame = false;
    918 
    919     CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
    920     #define RGFW_HOLD_MOUSE     (1L<<2)
    921     if (platform.window->_winArgs & RGFW_HOLD_MOUSE)
    922     {
    923         CORE.Input.Mouse.previousPosition = (Vector2){ 0.0f, 0.0f };
    924         CORE.Input.Mouse.currentPosition = (Vector2){ 0.0f, 0.0f };
    925     }
    926     else
    927     {
    928         CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
    929     }
    930 
    931     while (RGFW_window_checkEvent(platform.window))
    932     {
    933         if ((platform.window->event.type >= RGFW_jsButtonPressed) && (platform.window->event.type <= RGFW_jsAxisMove))
    934         {
    935             if (!CORE.Input.Gamepad.ready[platform.window->event.joystick])
    936             {
    937                 CORE.Input.Gamepad.ready[platform.window->event.joystick] = true;
    938                 CORE.Input.Gamepad.axisCount[platform.window->event.joystick] = platform.window->event.axisesCount;
    939                 CORE.Input.Gamepad.name[platform.window->event.joystick][0] = '\0';
    940                 CORE.Input.Gamepad.axisState[platform.window->event.joystick][GAMEPAD_AXIS_LEFT_TRIGGER] = -1.0f;
    941                 CORE.Input.Gamepad.axisState[platform.window->event.joystick][GAMEPAD_AXIS_RIGHT_TRIGGER] = -1.0f;
    942             }
    943         }
    944 
    945         RGFW_Event *event = &platform.window->event;
    946 
    947         // All input events can be processed after polling
    948         switch (event->type)
    949         {
    950             case RGFW_quit: CORE.Window.shouldClose = true; break;
    951             case RGFW_dnd:      // Dropped file
    952             {
    953                 for (int i = 0; i < event->droppedFilesCount; i++)
    954                 {
    955                     if (CORE.Window.dropFileCount == 0)
    956                     {
    957                         // When a new file is dropped, we reserve a fixed number of slots for all possible dropped files
    958                         // at the moment we limit the number of drops at once to 1024 files but this behaviour should probably be reviewed
    959                         // TODO: Pointers should probably be reallocated for any new file added...
    960                         CORE.Window.dropFilepaths = (char **)RL_CALLOC(1024, sizeof(char *));
    961 
    962                         CORE.Window.dropFilepaths[CORE.Window.dropFileCount] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char));
    963                         strcpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event->droppedFiles[i]);
    964 
    965                         CORE.Window.dropFileCount++;
    966                     }
    967                     else if (CORE.Window.dropFileCount < 1024)
    968                     {
    969                         CORE.Window.dropFilepaths[CORE.Window.dropFileCount] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char));
    970                         strcpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event->droppedFiles[i]);
    971 
    972                         CORE.Window.dropFileCount++;
    973                     }
    974                     else TRACELOG(LOG_WARNING, "FILE: Maximum drag and drop files at once is limited to 1024 files!");
    975                 }
    976             } break;
    977 
    978             // Window events are also polled (Minimized, maximized, close...)
    979             case RGFW_windowResized:
    980             {
    981                 SetupViewport(platform.window->r.w, platform.window->r.h);
    982                 CORE.Window.screen.width = platform.window->r.w;
    983                 CORE.Window.screen.height =  platform.window->r.h;
    984                 CORE.Window.currentFbo.width = platform.window->r.w;
    985                 CORE.Window.currentFbo.height = platform.window->r.h;
    986                 CORE.Window.resizedLastFrame = true;
    987             } break;
    988             case RGFW_windowMoved:
    989             {
    990                 CORE.Window.position.x = platform.window->r.x;
    991                 CORE.Window.position.y = platform.window->r.x;
    992             } break;
    993 
    994             // Keyboard events
    995             case RGFW_keyPressed:
    996             {
    997                 KeyboardKey key = ConvertScancodeToKey(event->keyCode);
    998 
    999                 if (key != KEY_NULL)
   1000                 {
   1001                     // If key was up, add it to the key pressed queue
   1002                     if ((CORE.Input.Keyboard.currentKeyState[key] == 0) && (CORE.Input.Keyboard.keyPressedQueueCount < MAX_KEY_PRESSED_QUEUE))
   1003                     {
   1004                         CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = key;
   1005                         CORE.Input.Keyboard.keyPressedQueueCount++;
   1006                     }
   1007 
   1008                     CORE.Input.Keyboard.currentKeyState[key] = 1;
   1009                 }
   1010 
   1011                 // TODO: Put exitKey verification outside the switch?
   1012                 if (CORE.Input.Keyboard.currentKeyState[CORE.Input.Keyboard.exitKey])
   1013                 {
   1014                     CORE.Window.shouldClose = true;
   1015                 }
   1016 
   1017                 // NOTE: event.text.text data comes an UTF-8 text sequence but we register codepoints (int)
   1018                 // Check if there is space available in the queue
   1019                 if (CORE.Input.Keyboard.charPressedQueueCount < MAX_CHAR_PRESSED_QUEUE)
   1020                 {
   1021                     // Add character (codepoint) to the queue
   1022                     CORE.Input.Keyboard.charPressedQueue[CORE.Input.Keyboard.charPressedQueueCount] = RSGL_keystrToChar(event->keyName);
   1023                     CORE.Input.Keyboard.charPressedQueueCount++;
   1024                 }
   1025             } break;
   1026             case RGFW_keyReleased:
   1027             {
   1028                 KeyboardKey key = ConvertScancodeToKey(event->keyCode);
   1029                 if (key != KEY_NULL) CORE.Input.Keyboard.currentKeyState[key] = 0;
   1030             } break;
   1031 
   1032             // Check mouse events
   1033             case RGFW_mouseButtonPressed:
   1034             {
   1035                 if ((event->button == RGFW_mouseScrollUp) || (event->button == RGFW_mouseScrollDown))
   1036                 {
   1037                     CORE.Input.Mouse.currentWheelMove.y = event->scroll;
   1038                     break;
   1039                 }
   1040 
   1041                 int btn = event->button;
   1042                 if (btn == RGFW_mouseLeft) btn = 1;
   1043                 else if (btn == RGFW_mouseRight) btn = 2;
   1044                 else if (btn == RGFW_mouseMiddle) btn = 3;
   1045 
   1046                 CORE.Input.Mouse.currentButtonState[btn - 1] = 1;
   1047                 CORE.Input.Touch.currentTouchState[btn - 1] = 1;
   1048 
   1049                 touchAction = 1;
   1050             } break;
   1051             case RGFW_mouseButtonReleased:
   1052             {
   1053 
   1054                 if ((event->button == RGFW_mouseScrollUp) || (event->button == RGFW_mouseScrollDown))
   1055                 {
   1056                     CORE.Input.Mouse.currentWheelMove.y = event->scroll;
   1057                     break;
   1058                 }
   1059 
   1060                 int btn = event->button;
   1061                 if (btn == RGFW_mouseLeft) btn = 1;
   1062                 else if (btn == RGFW_mouseRight) btn = 2;
   1063                 else if (btn == RGFW_mouseMiddle) btn = 3;
   1064 
   1065                 CORE.Input.Mouse.currentButtonState[btn - 1] = 0;
   1066                 CORE.Input.Touch.currentTouchState[btn - 1] = 0;
   1067 
   1068                 touchAction = 0;
   1069             } break;
   1070             case RGFW_mousePosChanged:
   1071             {
   1072                 if (platform.window->_winArgs & RGFW_HOLD_MOUSE)
   1073                 {
   1074                     CORE.Input.Mouse.currentPosition.x += (float)event->point.x;
   1075                     CORE.Input.Mouse.currentPosition.y += (float)event->point.y;
   1076                 }
   1077                 else
   1078                 {
   1079                     CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
   1080                     CORE.Input.Mouse.currentPosition.x = (float)event->point.x;
   1081                     CORE.Input.Mouse.currentPosition.y = (float)event->point.y;
   1082                 }
   1083 
   1084                 CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition;
   1085                 touchAction = 2;
   1086             } break;
   1087             case RGFW_jsButtonPressed:
   1088             {
   1089                 int button = -1;
   1090 
   1091                 switch (event->button)
   1092                 {
   1093                     case RGFW_JS_Y: button = GAMEPAD_BUTTON_RIGHT_FACE_UP; break;
   1094                     case RGFW_JS_B: button = GAMEPAD_BUTTON_RIGHT_FACE_RIGHT; break;
   1095                     case RGFW_JS_A: button = GAMEPAD_BUTTON_RIGHT_FACE_DOWN; break;
   1096                     case RGFW_JS_X: button = GAMEPAD_BUTTON_RIGHT_FACE_LEFT; break;
   1097 
   1098                     case RGFW_JS_L1: button = GAMEPAD_BUTTON_LEFT_TRIGGER_1; break;
   1099                     case RGFW_JS_R1: button = GAMEPAD_BUTTON_RIGHT_TRIGGER_1; break;
   1100 
   1101                     case RGFW_JS_L2: button = GAMEPAD_BUTTON_LEFT_TRIGGER_2; break;
   1102                     case RGFW_JS_R2: button = GAMEPAD_BUTTON_RIGHT_TRIGGER_2; break;
   1103 
   1104                     case RGFW_JS_SELECT: button = GAMEPAD_BUTTON_MIDDLE_LEFT; break;
   1105                     case RGFW_JS_HOME: button = GAMEPAD_BUTTON_MIDDLE; break;
   1106                     case RGFW_JS_START: button = GAMEPAD_BUTTON_MIDDLE_RIGHT; break;
   1107 
   1108                     case RGFW_JS_UP: button = GAMEPAD_BUTTON_LEFT_FACE_UP; break;
   1109                     case RGFW_JS_RIGHT: button = GAMEPAD_BUTTON_LEFT_FACE_RIGHT; break;
   1110                     case RGFW_JS_DOWN: button = GAMEPAD_BUTTON_LEFT_FACE_DOWN; break;
   1111                     case RGFW_JS_LEFT: button = GAMEPAD_BUTTON_LEFT_FACE_LEFT; break;
   1112 
   1113                     default: break;
   1114                 }
   1115 
   1116                 if (button >= 0)
   1117                 {
   1118                     CORE.Input.Gamepad.currentButtonState[event->joystick][button] = 1;
   1119                     CORE.Input.Gamepad.lastButtonPressed = button;
   1120                 }
   1121             } break;
   1122             case RGFW_jsButtonReleased:
   1123             {
   1124                 int button = -1;
   1125                 switch (event->button)
   1126                 {
   1127                     case RGFW_JS_Y: button = GAMEPAD_BUTTON_RIGHT_FACE_UP; break;
   1128                     case RGFW_JS_B: button = GAMEPAD_BUTTON_RIGHT_FACE_RIGHT; break;
   1129                     case RGFW_JS_A: button = GAMEPAD_BUTTON_RIGHT_FACE_DOWN; break;
   1130                     case RGFW_JS_X: button = GAMEPAD_BUTTON_RIGHT_FACE_LEFT; break;
   1131 
   1132                     case RGFW_JS_L1: button = GAMEPAD_BUTTON_LEFT_TRIGGER_1; break;
   1133                     case RGFW_JS_R1: button = GAMEPAD_BUTTON_RIGHT_TRIGGER_1; break;
   1134 
   1135                     case RGFW_JS_L2: button = GAMEPAD_BUTTON_LEFT_TRIGGER_2; break;
   1136                     case RGFW_JS_R2: button = GAMEPAD_BUTTON_RIGHT_TRIGGER_2; break;
   1137 
   1138                     case RGFW_JS_SELECT: button = GAMEPAD_BUTTON_MIDDLE_LEFT; break;
   1139                     case RGFW_JS_HOME: button = GAMEPAD_BUTTON_MIDDLE; break;
   1140                     case RGFW_JS_START: button = GAMEPAD_BUTTON_MIDDLE_RIGHT; break;
   1141 
   1142                     case RGFW_JS_UP: button = GAMEPAD_BUTTON_LEFT_FACE_UP; break;
   1143                     case RGFW_JS_RIGHT: button = GAMEPAD_BUTTON_LEFT_FACE_RIGHT; break;
   1144                     case RGFW_JS_DOWN: button = GAMEPAD_BUTTON_LEFT_FACE_DOWN; break;
   1145                     case RGFW_JS_LEFT: button = GAMEPAD_BUTTON_LEFT_FACE_LEFT; break;
   1146                     default: break;
   1147                 }
   1148 
   1149                 if (button >= 0)
   1150                 {
   1151                     CORE.Input.Gamepad.currentButtonState[event->joystick][button] = 0;
   1152                     if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0;
   1153                 }
   1154             } break;
   1155             case RGFW_jsAxisMove:
   1156             {
   1157                 int axis = -1;
   1158                 for (int i = 0; i < event->axisesCount; i++)
   1159                 {
   1160                     switch(i)
   1161                     {
   1162                         case 0:
   1163                         {
   1164                             if (abs(event->axis[i].x) > abs(event->axis[i].y))
   1165                             {
   1166                                 axis = GAMEPAD_AXIS_LEFT_X;
   1167                                 break;
   1168                             }
   1169 
   1170                             axis = GAMEPAD_AXIS_LEFT_Y;
   1171                         } break;
   1172                         case 1:
   1173                         {
   1174                             if (abs(event->axis[i].x) > abs(event->axis[i].y))
   1175                             {
   1176                                 axis = GAMEPAD_AXIS_RIGHT_X;
   1177                                 break;
   1178                             }
   1179 
   1180                             axis = GAMEPAD_AXIS_RIGHT_Y;
   1181                         } break;
   1182                         case 2: axis = GAMEPAD_AXIS_LEFT_TRIGGER; break;
   1183                         case 3: axis = GAMEPAD_AXIS_RIGHT_TRIGGER; break;
   1184                         default: break;
   1185                     }
   1186 
   1187                     #ifdef __linux__
   1188                     float value = (event->axis[i].x + event->axis[i].y)/(float)32767;
   1189                     #else
   1190                     float value = (event->axis[i].x + -event->axis[i].y)/(float)32767;
   1191                     #endif
   1192                     CORE.Input.Gamepad.axisState[event->joystick][axis] = value;
   1193 
   1194                     // Register button state for triggers in addition to their axes
   1195                     if ((axis == GAMEPAD_AXIS_LEFT_TRIGGER) || (axis == GAMEPAD_AXIS_RIGHT_TRIGGER))
   1196                     {
   1197                         int button = (axis == GAMEPAD_AXIS_LEFT_TRIGGER)? GAMEPAD_BUTTON_LEFT_TRIGGER_2 : GAMEPAD_BUTTON_RIGHT_TRIGGER_2;
   1198                         int pressed = (value > 0.1f);
   1199                         CORE.Input.Gamepad.currentButtonState[event->joystick][button] = pressed;
   1200                         
   1201                         if (pressed) CORE.Input.Gamepad.lastButtonPressed = button;
   1202                         else if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0;
   1203                     }
   1204                 }
   1205             } break;
   1206             default: break;
   1207         }
   1208 
   1209 #if defined(SUPPORT_GESTURES_SYSTEM)
   1210         if (touchAction > -1)
   1211         {
   1212             // Process mouse events as touches to be able to use mouse-gestures
   1213             GestureEvent gestureEvent = { 0 };
   1214 
   1215             // Register touch actions
   1216             gestureEvent.touchAction = touchAction;
   1217 
   1218             // Assign a pointer ID
   1219             gestureEvent.pointId[0] = 0;
   1220 
   1221             // Register touch points count
   1222             gestureEvent.pointCount = 1;
   1223 
   1224             // Register touch points position, only one point registered
   1225             if (touchAction == 2 || realTouch) gestureEvent.position[0] = CORE.Input.Touch.position[0];
   1226             else gestureEvent.position[0] = GetMousePosition();
   1227 
   1228             // Normalize gestureEvent.position[0] for CORE.Window.screen.width and CORE.Window.screen.height
   1229             gestureEvent.position[0].x /= (float)GetScreenWidth();
   1230             gestureEvent.position[0].y /= (float)GetScreenHeight();
   1231 
   1232             // Gesture data is sent to gestures-system for processing
   1233             ProcessGestureEvent(gestureEvent);
   1234 
   1235             touchAction = -1;
   1236         }
   1237 #endif
   1238     }
   1239     //-----------------------------------------------------------------------------
   1240 }
   1241 
   1242 //----------------------------------------------------------------------------------
   1243 // Module Internal Functions Definition
   1244 //----------------------------------------------------------------------------------
   1245 
   1246 // Initialize platform: graphics, inputs and more
   1247 int InitPlatform(void)
   1248 {
   1249     // Initialize RGFW internal global state, only required systems
   1250     unsigned int flags = RGFW_CENTER | RGFW_ALLOW_DND;
   1251 
   1252     // Check window creation flags
   1253     if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) > 0)
   1254     {
   1255         CORE.Window.fullscreen = true;
   1256         flags |= RGFW_FULLSCREEN;
   1257     }
   1258 
   1259     if ((CORE.Window.flags & FLAG_WINDOW_UNDECORATED) > 0) flags |= RGFW_NO_BORDER;
   1260     if ((CORE.Window.flags & FLAG_WINDOW_RESIZABLE) == 0) flags |= RGFW_NO_RESIZE;
   1261 
   1262     if ((CORE.Window.flags & FLAG_WINDOW_TRANSPARENT) > 0) flags |= RGFW_TRANSPARENT_WINDOW;
   1263 
   1264     if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) > 0) flags |= RGFW_FULLSCREEN;
   1265 
   1266     // NOTE: Some OpenGL context attributes must be set before window creation
   1267 
   1268     // Check selection OpenGL version
   1269     if (rlGetVersion() == RL_OPENGL_21)
   1270     {
   1271         RGFW_setGLVersion(RGFW_GL_CORE, 2, 1);
   1272     }
   1273     else if (rlGetVersion() == RL_OPENGL_33)
   1274     {
   1275         RGFW_setGLVersion(RGFW_GL_CORE, 3, 3);
   1276     }
   1277     else if (rlGetVersion() == RL_OPENGL_43)
   1278     {
   1279         RGFW_setGLVersion(RGFW_GL_CORE, 4, 1);
   1280     }
   1281 
   1282     if (CORE.Window.flags & FLAG_MSAA_4X_HINT)
   1283     {
   1284         RGFW_setGLSamples(4);
   1285     }
   1286 
   1287     platform.window = RGFW_createWindow(CORE.Window.title, RGFW_RECT(0, 0, CORE.Window.screen.width, CORE.Window.screen.height), flags);
   1288 
   1289     RGFW_area screenSize = RGFW_getScreenSize();
   1290     CORE.Window.display.width = screenSize.w;
   1291     CORE.Window.display.height = screenSize.h;
   1292     /* 
   1293         I think this is needed by Raylib now ? 
   1294         If so, rcore_destkop_sdl should be updated too
   1295     */
   1296     SetupFramebuffer(CORE.Window.display.width, CORE.Window.display.height);
   1297 
   1298     if (CORE.Window.flags & FLAG_VSYNC_HINT) RGFW_window_swapInterval(platform.window, 1);
   1299 
   1300     RGFW_window_makeCurrent(platform.window);
   1301 
   1302     // Check surface and context activation
   1303     if (platform.window != NULL)
   1304     {
   1305         CORE.Window.ready = true;
   1306 
   1307         CORE.Window.render.width = CORE.Window.screen.width;
   1308         CORE.Window.render.height = CORE.Window.screen.height;
   1309         CORE.Window.currentFbo.width = CORE.Window.render.width;
   1310         CORE.Window.currentFbo.height = CORE.Window.render.height;
   1311 
   1312         TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully");
   1313         TRACELOG(LOG_INFO, "    > Display size: %i x %i", CORE.Window.display.width, CORE.Window.display.height);
   1314         TRACELOG(LOG_INFO, "    > Screen size:  %i x %i", CORE.Window.screen.width, CORE.Window.screen.height);
   1315         TRACELOG(LOG_INFO, "    > Render size:  %i x %i", CORE.Window.render.width, CORE.Window.render.height);
   1316         TRACELOG(LOG_INFO, "    > Viewport offsets: %i, %i", CORE.Window.renderOffset.x, CORE.Window.renderOffset.y);
   1317     }
   1318     else
   1319     {
   1320         TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize graphics device");
   1321         return -1;
   1322     }
   1323     //----------------------------------------------------------------------------
   1324 
   1325     // If everything work as expected, we can continue
   1326     CORE.Window.position.x = platform.window->r.x;
   1327     CORE.Window.position.y = platform.window->r.y;
   1328     CORE.Window.render.width = CORE.Window.screen.width;
   1329     CORE.Window.render.height = CORE.Window.screen.height;
   1330     CORE.Window.currentFbo.width = CORE.Window.render.width;
   1331     CORE.Window.currentFbo.height = CORE.Window.render.height;
   1332 
   1333     TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully");
   1334     TRACELOG(LOG_INFO, "    > Display size: %i x %i", CORE.Window.display.width, CORE.Window.display.height);
   1335     TRACELOG(LOG_INFO, "    > Screen size:  %i x %i", CORE.Window.screen.width, CORE.Window.screen.height);
   1336     TRACELOG(LOG_INFO, "    > Render size:  %i x %i", CORE.Window.render.width, CORE.Window.render.height);
   1337     TRACELOG(LOG_INFO, "    > Viewport offsets: %i, %i", CORE.Window.renderOffset.x, CORE.Window.renderOffset.y);
   1338 
   1339     // Load OpenGL extensions
   1340     // NOTE: GL procedures address loader is required to load extensions
   1341     //----------------------------------------------------------------------------
   1342     rlLoadExtensions((void*)RGFW_getProcAddress);
   1343     //----------------------------------------------------------------------------
   1344 
   1345     // TODO: Initialize input events system
   1346     // It could imply keyboard, mouse, gamepad, touch...
   1347     // Depending on the platform libraries/SDK it could use a callback mechanism
   1348     // For system events and inputs evens polling on a per-frame basis, use PollInputEvents()
   1349     //----------------------------------------------------------------------------
   1350     // ...
   1351     //----------------------------------------------------------------------------
   1352 
   1353     // Initialize timing system
   1354     //----------------------------------------------------------------------------
   1355     InitTimer();
   1356     //----------------------------------------------------------------------------
   1357 
   1358     // Initialize storage system
   1359     //----------------------------------------------------------------------------
   1360     CORE.Storage.basePath = GetWorkingDirectory();
   1361     //----------------------------------------------------------------------------
   1362 
   1363 #ifdef RGFW_X11
   1364     for (int i = 0; (i < 4) && (i < MAX_GAMEPADS); i++)
   1365     {
   1366         RGFW_registerJoystick(platform.window, i);
   1367     }
   1368 #endif
   1369 
   1370     TRACELOG(LOG_INFO, "PLATFORM: CUSTOM: Initialized successfully");
   1371 
   1372     return 0;
   1373 }
   1374 
   1375 // Close platform
   1376 void ClosePlatform(void)
   1377 {
   1378     RGFW_window_close(platform.window);
   1379 }
   1380 
   1381 // Keycode mapping
   1382 static KeyboardKey ConvertScancodeToKey(u32 keycode)
   1383 {
   1384     if (keycode > sizeof(keyMappingRGFW)/sizeof(unsigned short)) return 0;
   1385 
   1386     return keyMappingRGFW[keycode];
   1387 }