commit 4a6b9e0

uint  ·  2026-05-03 23:03:41 +0000 UTC
parent e78c546
add RGFW
4 files changed,  +16059, -2
M README
+1, -1
1@@ -1,7 +1,7 @@
2 CC = cc
3 
4 CFLAGS = -std=c99 -Wall -Wextra
5-CPPFLAGS =
6+CPPFLAGS = -Isource/external -Isource/include
7 
8 SRCS = source/cterm.c
9 OUT = cterm
M README
+4, -1
1@@ -1,3 +1,6 @@
2 cterm
3 
4-minimal cross-platform terminal emulator written in c
5+A minimal cross-platform terminal emulator written in C.
6+
7+Thank you ST for source code :)
8+
+20, -0
 1@@ -0,0 +1,20 @@
 2+zlib License
 3+
 4+Copyright (C) 2022-2025 Riley Mabb (@ColleagueRiley)
 5+
 6+This software is provided 'as-is', without any express or implied
 7+warranty.  In no event will the authors be held liable for any damages
 8+arising from the use of this software.
 9+
10+Permission is granted to anyone to use this software for any purpose,
11+including commercial applications, and to alter it and redistribute it
12+freely, subject to the following restrictions:
13+  
14+1. The origin of this software must not be misrepresented; you must not
15+   claim that you wrote the original software. If you use this software
16+   in a product, an acknowledgment in the product documentation would be
17+   appreciated but is not required. 
18+2. Altered source versions must be plainly marked as such, and must not be
19+   misrepresented as being the original software.
20+3. This notice may not be removed or altered from any source distribution.
21+
+16034, -0
    1@@ -0,0 +1,16034 @@
    2+/*
    3+*
    4+*	RGFW 2.0.0-dev
    5+
    6+* Copyright (C) 2022-26 Riley Mabb (@ColleagueRiley)
    7+*
    8+* libpng license
    9+*
   10+* This software is provided 'as-is', without any express or implied
   11+* warranty.  In no event will the authors be held liable for any damages
   12+* arising from the use of this software.
   13+
   14+* Permission is granted to anyone to use this software for any purpose,
   15+* including commercial applications, and to alter it and redistribute it
   16+* freely, subject to the following restrictions:
   17+*
   18+* 1. The origin of this software must not be misrepresented; you must not
   19+*    claim that you wrote the original software. If you use this software
   20+*    in a product, an acknowledgment in the product documentation would be
   21+*    appreciated but is not required.
   22+* 2. Altered source versions must be plainly marked as such, and must not be
   23+*    misrepresented as being the original software.
   24+* 3. This notice may not be removed or altered from any source distribution.
   25+*
   26+*
   27+*/
   28+
   29+/*
   30+	(MAKE SURE RGFW_IMPLEMENTATION is in exactly one header or you use -D RGFW_IMPLEMENTATION)
   31+	#define RGFW_IMPLEMENTATION - makes it so source code is included with header
   32+*/
   33+
   34+/*
   35+	#define RGFW_IMPLEMENTATION - (required) makes it so the source code is included
   36+	#define RGFW_DEBUG - (optional) makes it so RGFW prints debug messages and errors when they're found
   37+	#define RGFW_EGL - (optional) compile with OpenGL functions, allowing you to use to use EGL instead of the native OpenGL functions
   38+	#define RGFW_DIRECTX - (optional) include integration directX functions (windows only)
   39+	#define RGFW_VULKAN - (optional) include helpful vulkan integration functions and macros
   40+	#define RGFW_WEBGPU - (optional) use WebGPU for rendering
   41+	#define RGFW_NATIVE - (optional) define native RGFW types that use native API structures
   42+
   43+	#define RGFW_X11 (optional) (unix only) if X11 should be used. This option is turned on by default by unix systems except for MacOS
   44+	#define RGFW_WAYLAND (optional) (unix only) use Wayland. (This can be used with X11)
   45+	#define RGFW_NO_STATIC_CONTEXT - do not initalizize with a static variable, use the heap if RGFW is not manually initalized
   46+	#define RGFW_NO_X11 (optional) (unix only) don't fallback to X11 when using Wayland
   47+	#define RGFW_NO_LOAD_WGL (optional) (windows only) if WGL should be loaded dynamically during runtime
   48+	#define RGFW_NO_X11_CURSOR (optional) (unix only) don't use XCursor
   49+	#define RGFW_NO_X11_CURSOR_PRELOAD (optional) (unix only) use XCursor, but don't link it in code, (you'll have to link it with -lXcursor)
   50+	#define RGFW_NO_X11_EXT_PRELOAD (optional) (unix only) use Xext, but don't link it in code, (you'll have to link it with -lXext)
   51+	#define RGFW_NO_LOAD_WINMM (optional) (windows only) use winmm (timeBeginPeriod), but don't link it in code, (you'll have to link it with -lwinmm)
   52+	#define RGFW_NO_WINMM (optional) (windows only) don't use winmm
   53+	#define RGFW_NO_IOKIT (optional) (macOS) don't use IOKit
   54+	#define RGFW_NO_UNIX_CLOCK (optional) (unix) don't link unix clock functions
   55+	#define RGFW_NO_DWM (windows only) - do not use or link dwmapi
   56+	#define RGFW_USE_XDL (optional) (X11) if XDL (XLib Dynamic Loader) should be used to load X11 dynamically during runtime (must include XDL.h along with RGFW)
   57+	#define RGFW_COCOA_GRAPHICS_SWITCHING - (optional) (cocoa) use automatic graphics switching (allow the system to choose to use GPU or iGPU)
   58+	#define RGFW_COCOA_FRAME_NAME (optional) (cocoa) set frame name
   59+	#define RGFW_NO_DPI - do not calculate DPI and don't use libShcore (win32)
   60+	#define RGFW_ADVANCED_SMOOTH_RESIZE - use advanced methods for smooth resizing (may result in a spike in memory usage or worse performance) (eg. WM_TIMER and XSyncValue)
   61+	#define RGFW_NO_INFO - do not define the RGFW_info struct (without RGFW_IMPLEMENTATION)
   62+	#define RGFW_NO_GLXWINDOW - do not use GLXWindow
   63+	#define RGFW_NO_ALLOCATE_MONITORS - do not allocate monitors on the heap at all (when there's no pre-allocated space left)
   64+	#define RGFW_PREALLOCATED_MONITORS x - choose the default amount of pre-allocated monitors (can be zero)
   65+
   66+	#define RGFW_ALLOC x  - choose the default allocation function (defaults to standard malloc)
   67+	#define RGFW_FREE x  - choose the default deallocation function (defaults to standard free)
   68+	#define RGFW_USERPTR x - choose the default userptr sent to the malloc call, (NULL by default)
   69+
   70+	#define RGFW_EXPORT - use when building RGFW
   71+	#define RGFW_IMPORT - use when linking with RGFW (not as a single-header)
   72+
   73+	#define RGFW_USE_INT - force the use c-types rather than stdint.h (for systems that might not have stdint.h (msvc))
   74+	#define RGFW_bool x - choose what type to use for bool, by default u32 is used
   75+*/
   76+
   77+/*
   78+Example to get you started :
   79+
   80+linux : gcc main.c -lX11 -lXrandr -lm
   81+windows : gcc main.c -lgdi32
   82+macos : gcc main.c -framework Cocoa -framework CoreVideo -framework IOKit
   83+
   84+#define RGFW_IMPLEMENTATION
   85+#include "RGFW.h"
   86+
   87+int main() {
   88+	RGFW_window* win = RGFW_createWindow("name", 100, 100, 500, 500, 0);
   89+
   90+	while (RGFW_window_shouldClose(win) == RGFW_FALSE) {
   91+		RGFW_pollEvents();
   92+	}
   93+
   94+	RGFW_window_close(win);
   95+}
   96+
   97+	compiling :
   98+
   99+	if you wish to compile the library all you have to do is create a new file with this in it
  100+
  101+	rgfw.c
  102+	#define RGFW_IMPLEMENTATION
  103+	#include "RGFW.h"
  104+
  105+	You may also want to add
  106+	`#define RGFW_EXPORT` when compiling and
  107+	`#define RGFW_IMPORT`when linking RGFW on it's own:
  108+	this reduces inline functions and prevents bloat in the object file
  109+
  110+	then you can use gcc (or whatever compile you wish to use) to compile the library into object file
  111+
  112+	ex. gcc -c RGFW.c -fPIC
  113+
  114+	after you compile the library into an object file, you can also turn the object file into an static or shared library
  115+
  116+	(commands ar and gcc can be replaced with whatever equivalent your system uses)
  117+
  118+	static : ar rcs RGFW.a RGFW.o
  119+	shared :
  120+		windows:
  121+			gcc -shared RGFW.o -lopengl32 -lgdi32 -o RGFW.dll
  122+		linux:
  123+			gcc -shared RGFW.o -lX11 -lGL -lXrandr -o RGFW.so
  124+		macos:
  125+			gcc -shared RGFW.o -framework CoreVideo -framework Cocoa -framework OpenGL -framework IOKit
  126+*/
  127+
  128+
  129+
  130+/*
  131+	Credits :
  132+		EimaMei/Sacode : Code review, helped with X11, MacOS and Windows support, Silicon, siliapp.h -> referencing
  133+
  134+		contributors : (feel free to put yourself here if you contribute)
  135+		krisvers (@krisvers) -> code review
  136+		EimaMei (@SaCode) -> code review
  137+		Nycticebus (@Code-Nycticebus) -> bug fixes
  138+		Rob Rohan (@robrohan) -> X11 bugs and missing features, MacOS/Cocoa fixing memory issues/bugs
  139+		AICDG (@THISISAGOODNAME) -> vulkan support (example)
  140+		@Easymode -> support, testing/debugging, bug fixes and reviews
  141+		Joshua Rowe (omnisci3nce) - bug fix, review (macOS)
  142+		@lesleyrs -> bug fix, review (OpenGL)
  143+		Nick Porcino (@meshula) - testing, organization, review (MacOS, examples)
  144+		@therealmarrakesh -> documentation
  145+		@DarekParodia -> code review (X11) (C++)
  146+		@NishiOwO -> fix BSD support, fix OSMesa example
  147+		@BaynariKattu -> code review and documentation
  148+		Miguel Pinto (@konopimi) -> code review, fix vulkan example
  149+		@m-doescode -> code review (wayland)
  150+		Robert Gonzalez (@uni-dos) -> code review (wayland)
  151+		@TheLastVoyager -> code review
  152+		@yehoravramenko -> code review (winapi)
  153+		@halocupcake -> code review (OpenGL)
  154+		@GideonSerf -> documentation
  155+		Alexandre Almeida (@M374LX) -> code review (keycodes)
  156+		Vũ Xuân Trường (@wanwanvxt) -> code review (winapi)
  157+		Lucas (@lightspeedlucas) -> code review (msvc++)
  158+		Jeffery Myers (@JeffM2501) -> code review (msvc)
  159+		Zeni (@zenitsuyo) -> documentation
  160+		TheYahton (@TheYahton) -> documentation
  161+		nonexistant_object (@DiarrheaMcgee)
  162+		AC Gaudette (@acgaudette)
  163+*/
  164+
  165+#if _MSC_VER
  166+	#pragma comment(lib, "gdi32")
  167+	#pragma comment(lib, "shell32")
  168+	#pragma comment(lib, "User32")
  169+	#pragma comment(lib, "Advapi32")
  170+    #pragma warning( push )
  171+	#pragma warning( disable : 4996 4191 4127)
  172+    #if _MSC_VER < 600
  173+        #define RGFW_C89
  174+    #endif
  175+#else
  176+    #if defined(__STDC__) && !defined(__STDC_VERSION__)
  177+        #define RGFW_C89
  178+    #endif
  179+#endif
  180+
  181+#if defined(RGFW_EGL) && !defined(RGFW_OPENGL)
  182+	#define RGFW_OPENGL
  183+#endif
  184+
  185+/* these OS macros look better & are standardized */
  186+/* plus it helps with cross-compiling */
  187+
  188+#ifdef __EMSCRIPTEN__
  189+	#define RGFW_WASM
  190+#endif
  191+
  192+#if defined(RGFW_X11) && defined(__APPLE__) && !defined(RGFW_CUSTOM_BACKEND)
  193+	#define RGFW_MACOS_X11
  194+	#define RGFW_UNIX
  195+#endif
  196+
  197+#if defined(_WIN32) && !defined(RGFW_X11) && !defined(RGFW_UNIX) && !defined(RGFW_WASM) && !defined(RGFW_CUSTOM_BACKEND) /* (if you're using X11 on windows some how) */
  198+	#define RGFW_WINDOWS
  199+#endif
  200+#if defined(RGFW_WAYLAND)
  201+	#define RGFW_DEBUG /* wayland will be in debug mode by default for now */
  202+	#define RGFW_UNIX
  203+	#ifdef RGFW_OPENGL
  204+		#define RGFW_EGL
  205+	#endif
  206+	#ifdef RGFW_X11
  207+		#define RGFW_DYNAMIC
  208+	#endif
  209+#endif
  210+#if (!defined(RGFW_WAYLAND) && !defined(RGFW_X11)) && (defined(__unix__) || defined(RGFW_MACOS_X11) || defined(RGFW_X11))  && !defined(RGFW_WASM)  && !defined(RGFW_CUSTOM_BACKEND)
  211+		#define RGFW_MACOS_X11
  212+		#define RGFW_X11
  213+		#define RGFW_UNIX
  214+#elif defined(__APPLE__) && !defined(RGFW_MACOS_X11) && !defined(RGFW_X11)  && !defined(RGFW_WASM)  && !defined(RGFW_CUSTOM_BACKEND)
  215+	#define RGFW_MACOS
  216+#endif
  217+
  218+#ifndef RGFW_ASSERT
  219+	#include <assert.h>
  220+	#define RGFW_ASSERT assert
  221+#endif
  222+
  223+#if !defined(__STDC_VERSION__)
  224+    #define RGFW_C89
  225+#endif
  226+
  227+#if !defined(RGFW_SNPRINTF) && (defined(RGFW_X11) || defined(RGFW_WAYLAND))
  228+	/* required for X11 errors */
  229+	#include <stdio.h>
  230+	#define RGFW_SNPRINTF snprintf
  231+#endif
  232+
  233+#ifndef RGFW_USERPTR
  234+	#define RGFW_USERPTR NULL
  235+#endif
  236+
  237+#ifndef RGFW_UNUSED
  238+	#define RGFW_UNUSED(x) (void)(x)
  239+#endif
  240+
  241+#ifndef RGFW_ROUND
  242+	#define RGFW_ROUND(x) (i32)((x) >= 0 ? (x) + 0.5f : (x) - 0.5f)
  243+#endif
  244+
  245+#ifndef RGFW_ROUNDF
  246+	#define RGFW_ROUNDF(x) (float)((i32)((x) + ((x) < 0.0f ? -0.5f : 0.5f)))
  247+#endif
  248+
  249+#ifndef RGFW_MIN
  250+	#define RGFW_MIN(x, y) ((x < y) ? x : y)
  251+#endif
  252+
  253+#ifndef RGFW_ALLOC
  254+	#include <stdlib.h>
  255+	#define RGFW_ALLOC malloc
  256+	#define RGFW_FREE free
  257+#endif
  258+
  259+#if !defined(RGFW_MEMCPY) || !defined(RGFW_STRNCMP) || !defined(RGFW_STRNCPY) || !defined(RGFW_MEMZERO)
  260+	#include <string.h>
  261+#endif
  262+
  263+#ifndef RGFW_MEMZERO
  264+	#define RGFW_MEMZERO(ptr, num) memset(ptr, 0, num)
  265+#endif
  266+
  267+#ifndef RGFW_MEMCPY
  268+	#define RGFW_MEMCPY(dist, src, len) memcpy(dist, src, len)
  269+#endif
  270+
  271+#ifndef RGFW_STRNCMP
  272+	#define RGFW_STRNCMP(s1, s2, max) strncmp(s1, s2, max)
  273+#endif
  274+
  275+#ifndef RGFW_STRNCPY
  276+	#define RGFW_STRNCPY(dist, src, len) strncpy(dist, src, len)
  277+#endif
  278+
  279+#ifndef RGFW_STRSTR
  280+	#define RGFW_STRSTR(str, substr) strstr(str, substr)
  281+#endif
  282+
  283+#ifndef RGFW_STRTOL
  284+	/* required for X11 XDnD and X11 Monitor DPI */
  285+	#include <stdlib.h>
  286+	#define RGFW_STRTOL(str, endptr, base) strtol(str, endptr, base)
  287+	#define RGFW_ATOF(num) atof(num)
  288+#endif
  289+
  290+#if !defined(RGFW_PRINTF) && ( defined(RGFW_DEBUG) || defined(RGFW_WAYLAND) )
  291+    /* required when using RGFW_DEBUG */
  292+    #include <stdio.h>
  293+    #define RGFW_PRINTF printf
  294+#endif
  295+
  296+#ifndef RGFW_MAX_EVENTS
  297+	#define RGFW_MAX_EVENTS 32
  298+#endif
  299+#ifndef RGFW_PREALLOCATED_MONITORS
  300+	#define RGFW_PREALLOCATED_MONITORS 6 /* the number of preallocated monitors */
  301+#elif defined(RGFW_NO_ALLOCATE_MONITORS) && (RGFW_PREALLOCATED_MONITORS == 0)
  302+	#warning RGFW monitors have no place to be allocated
  303+#endif
  304+
  305+#ifndef RGFW_COCOA_FRAME_NAME
  306+	#define RGFW_COCOA_FRAME_NAME NULL
  307+#endif
  308+
  309+#ifdef RGFW_WIN95 /* for windows 95 testing (not that it really works) */
  310+	#define RGFW_NO_PASSTHROUGH
  311+#endif
  312+
  313+#if defined(RGFW_EXPORT) ||  defined(RGFW_IMPORT)
  314+	#if defined(_WIN32)
  315+		#if defined(__TINYC__) && (defined(RGFW_EXPORT) ||  defined(RGFW_IMPORT))
  316+			#define __declspec(x) __attribute__((x))
  317+		#endif
  318+
  319+		#if defined(RGFW_EXPORT)
  320+			#define RGFWDEF __declspec(dllexport)
  321+		#else
  322+			#define RGFWDEF __declspec(dllimport)
  323+		#endif
  324+	#else
  325+		#if defined(RGFW_EXPORT)
  326+			#define RGFWDEF __attribute__((visibility("default")))
  327+		#endif
  328+	#endif
  329+    #ifndef RGFWDEF
  330+        #define RGFWDEF
  331+    #endif
  332+#endif
  333+
  334+#ifndef RGFWDEF
  335+	#ifdef RGFW_C89
  336+		#define RGFWDEF __inline
  337+	#else
  338+		#define RGFWDEF inline
  339+	#endif
  340+#endif
  341+
  342+#if defined(__cplusplus) && !defined(__EMSCRIPTEN__)
  343+	extern "C" {
  344+#endif
  345+
  346+/* makes sure the header file part is only defined once by default */
  347+#ifndef RGFW_HEADER
  348+
  349+#define RGFW_HEADER
  350+
  351+#include <stddef.h>
  352+#ifndef RGFW_INT_DEFINED
  353+	#ifdef RGFW_USE_INT /* optional for any system that might not have stdint.h */
  354+		typedef unsigned char       u8;
  355+		typedef signed char         i8;
  356+		typedef unsigned short     u16;
  357+		typedef signed short 	   i16;
  358+		typedef unsigned long int  u32;
  359+		typedef signed long int    i32;
  360+		typedef unsigned long long u64;
  361+		typedef signed long long   i64;
  362+	#else /* use stdint standard types instead of c "standard" types */
  363+		#include <stdint.h>
  364+
  365+		typedef uint8_t     u8;
  366+		typedef int8_t      i8;
  367+		typedef uint16_t   u16;
  368+		typedef int16_t    i16;
  369+		typedef uint32_t   u32;
  370+		typedef int32_t    i32;
  371+		typedef uint64_t   u64;
  372+		typedef int64_t    i64;
  373+	#endif
  374+	#define RGFW_INT_DEFINED
  375+#endif
  376+
  377+typedef ptrdiff_t RGFW_ssize_t;
  378+
  379+#ifndef RGFW_BOOL_DEFINED
  380+    #define RGFW_BOOL_DEFINED
  381+    typedef u8 RGFW_bool;
  382+#endif
  383+
  384+#define RGFW_BOOL(x) (RGFW_bool)((x) != 0) /* force a value to be 0 or 1 */
  385+#define RGFW_TRUE (RGFW_bool)1
  386+#define RGFW_FALSE (RGFW_bool)0
  387+
  388+#define RGFW_ENUM(type, name) type name; enum
  389+#define RGFW_BIT(x) (1 << (x))
  390+
  391+#ifdef RGFW_VULKAN
  392+
  393+	#if defined(RGFW_WAYLAND) && defined(RGFW_X11)
  394+		#define VK_USE_PLATFORM_WAYLAND_KHR
  395+		#define VK_USE_PLATFORM_XLIB_KHR
  396+		#define RGFW_VK_SURFACE ((RGFW_usingWayland()) ? ("VK_KHR_wayland_surface") : ("VK_KHR_xlib_surface"))
  397+	#elif defined(RGFW_WAYLAND)
  398+		#define VK_USE_PLATFORM_WAYLAND_KHR
  399+		#define VK_USE_PLATFORM_XLIB_KHR
  400+		#define RGFW_VK_SURFACE "VK_KHR_wayland_surface"
  401+	#elif defined(RGFW_X11)
  402+		#define VK_USE_PLATFORM_XLIB_KHR
  403+		#define RGFW_VK_SURFACE "VK_KHR_xlib_surface"
  404+	#elif defined(RGFW_WINDOWS)
  405+		#define VK_USE_PLATFORM_WIN32_KHR
  406+		#define OEMRESOURCE
  407+		#define RGFW_VK_SURFACE "VK_KHR_win32_surface"
  408+	#elif defined(RGFW_MACOS) && !defined(RGFW_MACOS_X11)
  409+		#define VK_USE_PLATFORM_MACOS_MVK
  410+		#define RGFW_VK_SURFACE "VK_MVK_macos_surface"
  411+	#else
  412+		#define RGFW_VK_SURFACE NULL
  413+	#endif
  414+
  415+#endif
  416+
  417+
  418+/*! @brief The stucture that contains information about the current RGFW instance */
  419+typedef struct RGFW_info RGFW_info;
  420+
  421+/*! @brief The window stucture for interfacing with the window */
  422+typedef struct RGFW_window RGFW_window;
  423+
  424+/*! @brief The source window stucture for interfacing with the underlying windowing API (e.g. winapi, wayland, cocoa, etc) */
  425+typedef struct RGFW_window_src RGFW_window_src;
  426+
  427+/*! @brief The color format for pixel data */
  428+typedef RGFW_ENUM(u8, RGFW_format) {
  429+	RGFW_formatRGB8 = 0,    /*!< 8-bit RGB (3 channels) */
  430+	RGFW_formatBGR8,    /*!< 8-bit BGR (3 channels) */
  431+	RGFW_formatRGBA8,   /*!< 8-bit RGBA (4 channels) */
  432+	RGFW_formatARGB8,   /*!< 8-bit RGBA (4 channels) */
  433+	RGFW_formatBGRA8,   /*!< 8-bit BGRA (4 channels) */
  434+	RGFW_formatABGR8,   /*!< 8-bit BGRA (4 channels) */
  435+	RGFW_formatCount
  436+};
  437+
  438+/*! @brief layout struct for mapping out format types */
  439+typedef struct RGFW_colorLayout {  i32 r, g, b, a; u32 channels;  } RGFW_colorLayout;
  440+
  441+/*! @brief function type converting raw image data between formats */
  442+typedef void (* RGFW_convertImageDataFunc)(u8* dest_data, u8* src_data, const RGFW_colorLayout* srcLayout, const RGFW_colorLayout* destLayout, size_t count);
  443+
  444+/*! @brief a stucture for interfacing with the underlying native image (e.g. XImage, HBITMAP, etc) */
  445+typedef struct RGFW_nativeImage RGFW_nativeImage;
  446+
  447+/*! @brief a stucture for interfacing with pixel data as a renderable surface */
  448+typedef struct RGFW_surface RGFW_surface;
  449+
  450+/*! @brief gamma struct for monitors */
  451+typedef struct RGFW_gammaRamp {
  452+	u16* red; /*!< array for the red channel */
  453+	u16* green; /*!< array for the green channel */
  454+	u16* blue; /*!< array for the blue channel */
  455+	size_t count; /*! count of elements in each channel */
  456+} RGFW_gammaRamp;
  457+
  458+/*! @brief monitor mode data | can be changed by the user (with functions)*/
  459+typedef struct RGFW_monitorMode {
  460+	i32 w, h; /*!< monitor workarea size */
  461+	float refreshRate; /*!< monitor refresh rate */
  462+	u8 red, blue, green; /*!< sizeof rgb values */
  463+	void* src; /*!< source API mode */
  464+} RGFW_monitorMode;
  465+
  466+/*! @brief structure for monitor node and source monitor data */
  467+typedef struct RGFW_monitorNode RGFW_monitorNode;
  468+
  469+/*! @brief structure for monitor data */
  470+typedef struct RGFW_monitor {
  471+	i32 x, y; /*!< x - y of the monitor workarea */
  472+	char name[128]; /*!< monitor name */
  473+	float scaleX, scaleY; /*!< monitor content scale */
  474+	float pixelRatio; /*!< pixel ratio for monitor (1.0 for regular, 2.0 for hiDPI)  */
  475+	float physW, physH; /*!< monitor physical size in inches */
  476+	RGFW_monitorMode mode; /*!< current mode of the monitor */
  477+	void* userPtr; /*!< pointer for user data */
  478+	RGFW_monitorNode* node; /*!< source node data of the monitor */
  479+} RGFW_monitor;
  480+
  481+/*! @brief what type of request you are making for the monitor */
  482+typedef RGFW_ENUM(u8, RGFW_modeRequest) {
  483+	RGFW_monitorScale = RGFW_BIT(0), /*!< scale the monitor size */
  484+	RGFW_monitorRefresh = RGFW_BIT(1), /*!< change the refresh rate */
  485+	RGFW_monitorRGB = RGFW_BIT(2), /*!< change the monitor RGB bits size */
  486+	RGFW_monitorAll = RGFW_monitorScale | RGFW_monitorRefresh | RGFW_monitorRGB
  487+};
  488+
  489+/*! a raw pointer to the underlying mouse handle for setting and creating custom mouse icons */
  490+typedef void RGFW_mouse;
  491+
  492+/*! @brief RGFW's abstract keycodes */
  493+typedef RGFW_ENUM(u8, RGFW_key) {
  494+	RGFW_keyNULL = 0,
  495+	RGFW_keyEscape = '\033',
  496+	RGFW_keyBacktick = '`',
  497+	RGFW_key0 = '0',
  498+	RGFW_key1 = '1',
  499+	RGFW_key2 = '2',
  500+	RGFW_key3 = '3',
  501+	RGFW_key4 = '4',
  502+	RGFW_key5 = '5',
  503+	RGFW_key6 = '6',
  504+	RGFW_key7 = '7',
  505+	RGFW_key8 = '8',
  506+	RGFW_key9 = '9',
  507+	RGFW_keyMinus = '-',
  508+	RGFW_keyEqual = '=',
  509+	RGFW_keyEquals = RGFW_keyEqual,
  510+	RGFW_keyBackSpace = '\b',
  511+	RGFW_keyTab = '\t',
  512+	RGFW_keySpace = ' ',
  513+	RGFW_keyA = 'a',
  514+	RGFW_keyB = 'b',
  515+	RGFW_keyC = 'c',
  516+	RGFW_keyD = 'd',
  517+	RGFW_keyE = 'e',
  518+	RGFW_keyF = 'f',
  519+	RGFW_keyG = 'g',
  520+	RGFW_keyH = 'h',
  521+	RGFW_keyI = 'i',
  522+	RGFW_keyJ = 'j',
  523+	RGFW_keyK = 'k',
  524+	RGFW_keyL = 'l',
  525+	RGFW_keyM = 'm',
  526+	RGFW_keyN = 'n',
  527+	RGFW_keyO = 'o',
  528+	RGFW_keyP = 'p',
  529+	RGFW_keyQ = 'q',
  530+	RGFW_keyR = 'r',
  531+	RGFW_keyS = 's',
  532+	RGFW_keyT = 't',
  533+	RGFW_keyU = 'u',
  534+	RGFW_keyV = 'v',
  535+	RGFW_keyW = 'w',
  536+	RGFW_keyX = 'x',
  537+	RGFW_keyY = 'y',
  538+	RGFW_keyZ = 'z',
  539+	RGFW_keyPeriod = '.',
  540+	RGFW_keyComma = ',',
  541+	RGFW_keySlash = '/',
  542+	RGFW_keyBracket = '[',
  543+    RGFW_keyCloseBracket = ']',
  544+    RGFW_keySemicolon = ';',
  545+	RGFW_keyApostrophe = '\'',
  546+	RGFW_keyBackSlash = '\\',
  547+	RGFW_keyReturn = '\n',
  548+	RGFW_keyEnter = RGFW_keyReturn,
  549+	RGFW_keyDelete = '\177', /* 127 */
  550+	RGFW_keyF1,
  551+	RGFW_keyF2,
  552+	RGFW_keyF3,
  553+	RGFW_keyF4,
  554+	RGFW_keyF5,
  555+	RGFW_keyF6,
  556+	RGFW_keyF7,
  557+	RGFW_keyF8,
  558+	RGFW_keyF9,
  559+	RGFW_keyF10,
  560+	RGFW_keyF11,
  561+	RGFW_keyF12,
  562+    RGFW_keyF13,
  563+    RGFW_keyF14,
  564+    RGFW_keyF15,
  565+    RGFW_keyF16,
  566+    RGFW_keyF17,
  567+    RGFW_keyF18,
  568+    RGFW_keyF19,
  569+    RGFW_keyF20,
  570+    RGFW_keyF21,
  571+    RGFW_keyF22,
  572+    RGFW_keyF23,
  573+    RGFW_keyF24,
  574+    RGFW_keyF25,
  575+	RGFW_keyCapsLock,
  576+	RGFW_keyShiftL,
  577+	RGFW_keyControlL,
  578+	RGFW_keyAltL,
  579+	RGFW_keySuperL,
  580+	RGFW_keyShiftR,
  581+	RGFW_keyControlR,
  582+	RGFW_keyAltR,
  583+	RGFW_keySuperR,
  584+	RGFW_keyUp,
  585+	RGFW_keyDown,
  586+	RGFW_keyLeft,
  587+	RGFW_keyRight,
  588+	RGFW_keyInsert,
  589+	RGFW_keyMenu,
  590+	RGFW_keyEnd,
  591+	RGFW_keyHome,
  592+	RGFW_keyPageUp,
  593+	RGFW_keyPageDown,
  594+	RGFW_keyNumLock,
  595+	RGFW_keyPadSlash,
  596+	RGFW_keyPadMultiply,
  597+	RGFW_keyPadPlus,
  598+	RGFW_keyPadMinus,
  599+	RGFW_keyPadEqual,
  600+	RGFW_keyPadEquals = RGFW_keyPadEqual,
  601+	RGFW_keyPad1,
  602+	RGFW_keyPad2,
  603+	RGFW_keyPad3,
  604+	RGFW_keyPad4,
  605+	RGFW_keyPad5,
  606+	RGFW_keyPad6,
  607+	RGFW_keyPad7,
  608+	RGFW_keyPad8,
  609+	RGFW_keyPad9,
  610+	RGFW_keyPad0,
  611+	RGFW_keyPadPeriod,
  612+	RGFW_keyPadReturn,
  613+	RGFW_keyScrollLock,
  614+    RGFW_keyPrintScreen,
  615+    RGFW_keyPause,
  616+	RGFW_keyWorld1,
  617+    RGFW_keyWorld2,
  618+    RGFW_keyLast = 256 /* padding for alignment ~(175 by default) */
  619+};
  620+
  621+/*! @brief abstract mouse button codes */
  622+typedef RGFW_ENUM(u8, RGFW_mouseButton) {
  623+	RGFW_mouseLeft = 0, /*!< left mouse button is pressed */
  624+	RGFW_mouseMiddle, /*!< mouse-wheel-button is pressed */
  625+	RGFW_mouseRight, /*!< right mouse button is pressed */
  626+	RGFW_mouseMisc1, RGFW_mouseMisc2, RGFW_mouseMisc3, RGFW_mouseMisc4, RGFW_mouseMisc5,
  627+	RGFW_mouseFinal
  628+};
  629+
  630+/*! abstract key modifier codes */
  631+typedef RGFW_ENUM(u8, RGFW_keymod) {
  632+	RGFW_modCapsLock = RGFW_BIT(0),
  633+	RGFW_modNumLock  = RGFW_BIT(1),
  634+	RGFW_modControl  = RGFW_BIT(2),
  635+	RGFW_modAlt = RGFW_BIT(3),
  636+	RGFW_modShift  = RGFW_BIT(4),
  637+	RGFW_modSuper = RGFW_BIT(5),
  638+	RGFW_modScrollLock = RGFW_BIT(6)
  639+};
  640+
  641+/*! types of dnd drag actions */
  642+typedef RGFW_ENUM(u8, RGFW_dndActionType) {
  643+	RGFW_dndActionNone = 0,
  644+	RGFW_dndActionEnter, /*!< data has been dragged into the window area */
  645+	RGFW_dndActionMove, /*!< the data that was dragged into the window area has moved inside the window */
  646+	RGFW_dndActionExit, /*!< the data that was dragged into the window area has left the window */
  647+};
  648+
  649+/*! types of transfered data (clipboard, dnd) */
  650+typedef RGFW_ENUM(u8, RGFW_dataTransferType) {
  651+	RGFW_dataNone = 0,
  652+	RGFW_dataText, /*!< plain text string */
  653+	RGFW_dataFile, /*!< file string */
  654+	RGFW_dataURL, /*!< URL string */
  655+	RGFW_dataImage, /*!< raw image data */
  656+	RGFW_dataUnknown /*!< unknown raw data */
  657+};
  658+
  659+/*! internal node for a individual data drop */
  660+typedef struct RGFW_dataDropNode {
  661+	const char* data; /*!< dropped data */
  662+	size_t size; /*!< the size of the data in bytes */
  663+	RGFW_dataTransferType type; /*!< the type of data being dropped */
  664+	struct RGFW_dataDropNode* next; /*!< the next drop data node if any [when handling callbacks, this will always be NULL because the linked list is built as events are processed] */
  665+} RGFW_dataDropNode;
  666+
  667+/*! @brief codes for the event types that can be sent */
  668+typedef RGFW_ENUM(u8, RGFW_eventType) {
  669+	RGFW_eventNone = 0, /*!< no event has been sent */
  670+ 	RGFW_keyPressed, /*!< a key has been pressed */
  671+	RGFW_keyReleased, /*!< a key has been released */
  672+	RGFW_keyChar, /*!< keyboard character input event specifically for utf8 input */
  673+	RGFW_mouseButtonPressed, /*!< a mouse button has been pressed (left,middle,right) */
  674+	RGFW_mouseButtonReleased, /*!< a mouse button has been released (left,middle,right) */
  675+	RGFW_mouseScroll, /*!< a mouse scroll event */
  676+	RGFW_mousePosChanged, /*!< the position of the mouse has been changed */
  677+	RGFW_mouseRawMotion, /*!< raw mouse motion */
  678+	RGFW_mouseEnter, /*!< mouse entered the window */
  679+	RGFW_mouseLeave, /*!< mouse left the window */
  680+	RGFW_windowMoved, /*!< the window was moved (by the user) */
  681+	RGFW_windowResized, /*!< the window was resized (by the user), [on WASM this means the browser was resized] */
  682+	RGFW_windowFocusIn, /*!< window is in focus now */
  683+	RGFW_windowFocusOut, /*!< window is out of focus now */
  684+	RGFW_windowRefresh, /*!< The window content needs to be refreshed */
  685+	RGFW_windowClose, /*!< the user attempts to close the window */
  686+	RGFW_windowMaximized, /*!< the window was maximized */
  687+	RGFW_windowMinimized, /*!< the window was minimized */
  688+	RGFW_windowRestored, /*!< the window was restored */
  689+	RGFW_dataDrop, /*!< data has been dropped into the window */
  690+	RGFW_dataDrag, /*!< the start of a drag and drop event, when data is being dragged */
  691+	RGFW_scaleUpdated, /*!< content scale factor changed */
  692+	RGFW_monitorConnected, /*!< a monitor has been connected */
  693+	RGFW_monitorDisconnected, /*!< a monitor has been disconnected */
  694+	RGFW_eventCount /*!< the number of event types there are */
  695+};
  696+
  697+/*! @brief flags for toggling whether or not an event should be processed */
  698+typedef RGFW_ENUM(u32, RGFW_eventFlag) {
  699+    RGFW_keyPressedFlag = RGFW_BIT(RGFW_keyPressed),
  700+    RGFW_keyReleasedFlag = RGFW_BIT(RGFW_keyReleased),
  701+    RGFW_keyCharFlag = RGFW_BIT(RGFW_keyChar),
  702+    RGFW_mouseScrollFlag = RGFW_BIT(RGFW_mouseScroll),
  703+    RGFW_mouseButtonPressedFlag = RGFW_BIT(RGFW_mouseButtonPressed),
  704+    RGFW_mouseButtonReleasedFlag = RGFW_BIT(RGFW_mouseButtonReleased),
  705+    RGFW_mousePosChangedFlag = RGFW_BIT(RGFW_mousePosChanged),
  706+    RGFW_mouseRawMotionFlag = RGFW_BIT(RGFW_mouseRawMotion),
  707+    RGFW_mouseEnterFlag = RGFW_BIT(RGFW_mouseEnter),
  708+    RGFW_mouseLeaveFlag = RGFW_BIT(RGFW_mouseLeave),
  709+    RGFW_windowMovedFlag = RGFW_BIT(RGFW_windowMoved),
  710+    RGFW_windowResizedFlag = RGFW_BIT(RGFW_windowResized),
  711+    RGFW_windowFocusInFlag = RGFW_BIT(RGFW_windowFocusIn),
  712+    RGFW_windowFocusOutFlag = RGFW_BIT(RGFW_windowFocusOut),
  713+    RGFW_windowRefreshFlag = RGFW_BIT(RGFW_windowRefresh),
  714+    RGFW_windowMaximizedFlag = RGFW_BIT(RGFW_windowMaximized),
  715+    RGFW_windowMinimizedFlag = RGFW_BIT(RGFW_windowMinimized),
  716+    RGFW_windowRestoredFlag = RGFW_BIT(RGFW_windowRestored),
  717+    RGFW_scaleUpdatedFlag = RGFW_BIT(RGFW_scaleUpdated),
  718+    RGFW_windowCloseFlag = RGFW_BIT(RGFW_windowClose),
  719+    RGFW_dataDropFlag = RGFW_BIT(RGFW_dataDrop),
  720+    RGFW_dataDragFlag = RGFW_BIT(RGFW_dataDrag),
  721+	RGFW_monitorConnectedFlag = RGFW_BIT(RGFW_monitorConnected),
  722+	RGFW_monitorDisconnectedFlag = RGFW_BIT(RGFW_monitorDisconnected),
  723+
  724+    RGFW_keyEventsFlag = RGFW_keyPressedFlag | RGFW_keyReleasedFlag | RGFW_keyCharFlag,
  725+    RGFW_mouseEventsFlag = RGFW_mouseButtonPressedFlag | RGFW_mouseButtonReleasedFlag | RGFW_mousePosChangedFlag | RGFW_mouseEnterFlag | RGFW_mouseLeaveFlag | RGFW_mouseScrollFlag | RGFW_mouseRawMotionFlag,
  726+    RGFW_windowEventsFlag = RGFW_windowMovedFlag | RGFW_windowResizedFlag | RGFW_windowRefreshFlag | RGFW_windowMaximizedFlag | RGFW_windowMinimizedFlag | RGFW_windowRestoredFlag | RGFW_scaleUpdatedFlag,
  727+    RGFW_windowFocusEventsFlag = RGFW_windowFocusInFlag | RGFW_windowFocusOutFlag,
  728+    RGFW_dataDragDropEventsFlag = RGFW_dataDropFlag | RGFW_dataDragFlag,
  729+	RGFW_monitorEventsFlag = RGFW_monitorConnectedFlag | RGFW_monitorDisconnectedFlag,
  730+    RGFW_allEventFlags = RGFW_keyEventsFlag | RGFW_mouseEventsFlag | RGFW_windowEventsFlag | RGFW_windowFocusEventsFlag | RGFW_dataDragDropEventsFlag | RGFW_windowCloseFlag | RGFW_monitorEventsFlag
  731+};
  732+
  733+/*! Event structure(s) and union for checking/getting events */
  734+
  735+/*! @brief common event data across all events */
  736+typedef struct RGFW_commonEvent {
  737+	RGFW_eventType type; /*!< which event has been sent?*/
  738+	RGFW_window* win; /*!< the window this event applies to (for event queue events) */
  739+} RGFW_commonEvent;
  740+
  741+/*! @brief event data for all focus events */
  742+typedef struct RGFW_windowFocusEvent {
  743+	RGFW_eventType type; /*!< which event has been sent?*/
  744+	RGFW_window* win; /*!< the window this event applies to (for event queue events) */
  745+	RGFW_bool state; /*!< wether or not the window is in focus or not */
  746+} RGFW_windowFocusEvent;
  747+
  748+/*! @brief event data for any mouse button event (press/release) */
  749+typedef struct RGFW_mouseButtonEvent {
  750+	RGFW_eventType type; /*!< which event has been sent?*/
  751+	RGFW_window* win; /*!< the window this event applies to (for event queue events) */
  752+	RGFW_mouseButton value; /* !< which mouse button was pressed */
  753+	RGFW_bool state; /*!< if the button was pressed or released */
  754+} RGFW_mouseButtonEvent;
  755+
  756+/*! @brief event data for any mouse scroll or raw motion event */
  757+typedef struct RGFW_mouseDeltaEvent {
  758+	RGFW_eventType type; /*!< which event has been sent?*/
  759+	RGFW_window* win; /*!< the window this event applies to (for event queue events) */
  760+	float x, y; /*!< the raw mouse scroll or motion delta value */
  761+} RGFW_mouseDeltaEvent;
  762+
  763+/*! @brief event data for a mouse position event (RGFW_mousePosChanged) */
  764+typedef struct RGFW_mousePosEvent {
  765+	RGFW_eventType type; /*!< which event has been sent?*/
  766+	RGFW_window* win; /*!< the window this event applies to (for event queue events) */
  767+	i32 x, y; /*!< mouse x, y of event (or drop point) */
  768+	RGFW_bool inWindow; /*!< if the mouse is in the window or not */
  769+} RGFW_mousePosEvent;
  770+
  771+/*! @brief event data for a key press/release event */
  772+typedef struct RGFW_keyEvent {
  773+	RGFW_eventType type; /*!< which event has been sent?*/
  774+	RGFW_window* win; /*!< the window this event applies to (for event queue events) */
  775+	RGFW_key value; /*!< the physical key of the event, refers to where key is physically */
  776+	RGFW_bool repeat; /*!< key press event repeated (the key is being held) */
  777+	RGFW_keymod mod; /*!< state of the key modifier state */
  778+	RGFW_bool state; /*!< if the key was pressed or released */
  779+} RGFW_keyEvent;
  780+
  781+/*! @brief event data for a key character event */
  782+typedef struct RGFW_keyCharEvent {
  783+	RGFW_eventType type; /*!< which event has been sent?*/
  784+	RGFW_window* win; /*!< the window this event applies to (for event queue events) */
  785+	u32 value; /*!< the unicode value of the key */
  786+} RGFW_keyCharEvent;
  787+
  788+/*! @brief event data for any data drop event */
  789+typedef struct RGFW_dataDropEvent {
  790+	RGFW_eventType type; /*!< which event has been sent?*/
  791+	RGFW_window* win; /*!< the window this event applies to (for event queue events) */
  792+	const RGFW_dataDropNode* value;
  793+} RGFW_dataDropEvent;
  794+
  795+/*! @brief event data for any data drag event */
  796+typedef struct RGFW_dataDragEvent {
  797+	RGFW_eventType type; /*!< which event has been sent?*/
  798+	RGFW_window* win; /*!< the window this event applies to (for event queue events) */
  799+	i32 x, y; /*!< mouse x, y of event (or drop point) */
  800+	RGFW_dndActionType action; /*!< the type of drag action, e.g. enter, leave, move */
  801+	RGFW_dataTransferType dataType; /*!< the type of data being dragged*/
  802+} RGFW_dataDragEvent;
  803+
  804+/*! @brief event data for when the window scale (DPI) is updated */
  805+typedef struct RGFW_scaleUpdatedEvent {
  806+	RGFW_eventType type; /*!< which event has been sent?*/
  807+	RGFW_window* win; /*!< the window this event applies to (for event queue events) */
  808+	float x, y; /*!< DPI scaling */
  809+} RGFW_scaleUpdatedEvent;
  810+
  811+/*! @brief event data for when a monitor is connected, disconnected or updated */
  812+typedef struct RGFW_monitorEvent {
  813+	RGFW_eventType type; /*!< which event has been sent?*/
  814+	RGFW_window* win; /*!< the window this event applies to (for event queue events) */
  815+	const RGFW_monitor* monitor; /*!< the monitor that this event applies to */
  816+	RGFW_bool state; /*!< if the monitor is connected or disconnected */
  817+} RGFW_monitorEvent;
  818+
  819+/*! @breif event data for when the window is updated, moved, resized or refreshed */
  820+typedef struct RGFW_windowUpdateEvent {
  821+	RGFW_eventType type; /*!< the specific event type */
  822+	RGFW_window* win; /*!< the window that was updated */
  823+	i32 x; /*!< the new window x OR the x of the rectanglular refresh area */
  824+	i32 y; /*!< the new window y OR the y of the rectanglular refresh area */
  825+	i32 w; /*!< the new window width OR the width of the rectanglular refresh area */
  826+	i32 h; /*!< the new window height OR the height of the rectanglular refresh area */
  827+} RGFW_windowUpdateEvent;
  828+
  829+/*! @brief union for all of the event stucture types */
  830+typedef union RGFW_event {
  831+	RGFW_eventType type; /*!< which event has been sent?*/
  832+	RGFW_commonEvent common; /*!< common event data (e.g.) type and win */
  833+	RGFW_windowFocusEvent focus; /*!< event data  for focus in/out events */
  834+	RGFW_windowUpdateEvent update; /*!< data for window update/move/resize/refresh events */
  835+	RGFW_mouseButtonEvent button; /*!< data for a button press/release */
  836+	RGFW_mouseDeltaEvent delta; /*!< data for a mouse scroll or raw motion */
  837+	RGFW_mousePosEvent mouse; /*!< data for mouse motion events */
  838+	RGFW_keyEvent key; /*!< data for key press/release/hold events */
  839+	RGFW_keyCharEvent keyChar; /*!< data for key character events */
  840+	RGFW_dataDropEvent drop; /*!< data dropping events */
  841+	RGFW_dataDragEvent drag; /*!< data for data dragging events */
  842+	RGFW_scaleUpdatedEvent scale; /*!< data for dpi scaling update events */
  843+	RGFW_monitorEvent monitor; /*!< data for monitor events */
  844+} RGFW_event;
  845+
  846+/*!
  847+	@!brief codes for for RGFW_the code is stupid and C++ waitForEvent
  848+	waitMS -> Allows the function to keep checking for events even after there are no more events
  849+			  if waitMS == 0, the loop will not wait for events
  850+			  if waitMS > 0, the loop will wait that many miliseconds after there are no more events until it returns
  851+			  if waitMS == -1 or waitMS == the max size of an unsigned 32-bit int, the loop will not return until it gets another event
  852+*/
  853+typedef RGFW_ENUM(i32, RGFW_eventWait) {
  854+	RGFW_eventNoWait = 0,
  855+	RGFW_eventWaitNext = -1
  856+};
  857+
  858+/*! @brief generic event callback function type */
  859+typedef void (*RGFW_genericFunc)(const RGFW_event* e);
  860+
  861+/*! brief structure that holds an array to callback data*/
  862+typedef struct RGFW_callbacks {
  863+	RGFW_genericFunc arr[RGFW_eventCount]; /*!< an array of all the callbacks */
  864+} RGFW_callbacks;
  865+
  866+/*! @brief optional bitwise arguments for making a windows, these can be OR'd together */
  867+typedef RGFW_ENUM(u32, RGFW_windowFlags) {
  868+	RGFW_windowNoBorder = RGFW_BIT(0), /*!< the window doesn't have a border / frame / decor */
  869+	RGFW_windowNoResize = RGFW_BIT(1), /*!< the window cannot be resized by the user */
  870+	RGFW_windowAllowDND = RGFW_BIT(2), /*!< the window supports drag and drop */
  871+	RGFW_windowHideMouse = RGFW_BIT(3), /*! the window should hide the mouse (can be toggled later on using `RGFW_window_showMouse`) */
  872+	RGFW_windowFullscreen = RGFW_BIT(4), /*!< the window is fullscreen by default */
  873+	RGFW_windowTranslucent = RGFW_BIT(5), /*!< the window is translucent (only properly works on X11 and MacOS, although it's meant for for windows) */
  874+	RGFW_windowTransparent = RGFW_windowTranslucent,  /*!< the window is translucent (only properly works on X11 and MacOS, although it's meant for for windows) */
  875+	RGFW_windowCenter = RGFW_BIT(6), /*! center the window on the screen */
  876+	RGFW_windowRawMouse = RGFW_BIT(7), /*!< use raw mouse mouse on window creation */
  877+	RGFW_windowScaleToMonitor = RGFW_BIT(8), /*! scale the window to the screen */
  878+	RGFW_windowHide = RGFW_BIT(9), /*! the window is hidden */
  879+	RGFW_windowMaximize = RGFW_BIT(10), /*!< maximize the window on creation */
  880+	RGFW_windowCenterCursor = RGFW_BIT(11), /*!< center the cursor to the window on creation */
  881+	RGFW_windowFloating = RGFW_BIT(12), /*!< create a floating window */
  882+	RGFW_windowFocusOnShow = RGFW_BIT(13), /*!< focus the window when it's shown */
  883+	RGFW_windowMinimize = RGFW_BIT(14), /*!< focus the window when it's shown */
  884+	RGFW_windowFocus = RGFW_BIT(15), /*!< if the window is in focus */
  885+	RGFW_windowCaptureMouse = RGFW_BIT(16), /*!< capture the mouse mouse mouse on window creation */
  886+	RGFW_windowOpenGL = RGFW_BIT(17), /*!< create an OpenGL context (you can also do this manually with RGFW_window_createContext_OpenGL) */
  887+	RGFW_windowEGL = RGFW_BIT(18), /*!< create an EGL context (you can also do this manually with RGFW_window_createContext_EGL) */
  888+	RGFW_noDeinitOnClose = RGFW_BIT(19), /*!< do not auto deinit RGFW if the window closes and this is the last window open */
  889+	RGFW_windowedFullscreen = RGFW_windowNoBorder | RGFW_windowMaximize,
  890+	RGFW_windowCaptureRawMouse = RGFW_windowCaptureMouse | RGFW_windowRawMouse
  891+};
  892+
  893+/*! @brief the types of icon to set */
  894+typedef RGFW_ENUM(u8, RGFW_icon) {
  895+	RGFW_iconTaskbar = RGFW_BIT(0),
  896+	RGFW_iconWindow = RGFW_BIT(1),
  897+	RGFW_iconBoth = RGFW_iconTaskbar | RGFW_iconWindow
  898+};
  899+
  900+/*! @brief standard mouse icons */
  901+typedef RGFW_ENUM(u8, RGFW_mouseIcon) {
  902+	RGFW_mouseNormal = 0,
  903+	RGFW_mouseArrow,
  904+	RGFW_mouseIbeam,
  905+	RGFW_mouseText = RGFW_mouseIbeam,
  906+	RGFW_mouseCrosshair,
  907+	RGFW_mousePointingHand,
  908+	RGFW_mouseResizeEW,
  909+	RGFW_mouseResizeNS,
  910+	RGFW_mouseResizeNWSE,
  911+	RGFW_mouseResizeNESW,
  912+	RGFW_mouseResizeNW,
  913+	RGFW_mouseResizeN,
  914+	RGFW_mouseResizeNE,
  915+	RGFW_mouseResizeE,
  916+	RGFW_mouseResizeSE,
  917+	RGFW_mouseResizeS,
  918+	RGFW_mouseResizeSW,
  919+	RGFW_mouseResizeW,
  920+	RGFW_mouseResizeAll,
  921+	RGFW_mouseNotAllowed,
  922+	RGFW_mouseWait,
  923+	RGFW_mouseProgress,
  924+	RGFW_mouseIconCount,
  925+    RGFW_mouseIconFinal = 16 /* padding for alignment */
  926+};
  927+
  928+/*! @breif flash request type */
  929+typedef RGFW_ENUM(u8, RGFW_flashRequest) {
  930+	RGFW_flashCancel = 0,
  931+	RGFW_flashBriefly,
  932+	RGFW_flashUntilFocused
  933+};
  934+
  935+/*! @brief the type of debug message */
  936+typedef RGFW_ENUM(u8, RGFW_debugType) {
  937+	RGFW_typeError = 0, RGFW_typeWarning, RGFW_typeInfo
  938+};
  939+
  940+/*! @brief error codes for known failure types */
  941+typedef RGFW_ENUM(u8, RGFW_errorCode) {
  942+	RGFW_noError = 0, /*!< no error */
  943+	RGFW_errOutOfMemory,
  944+	RGFW_errOpenGLContext, RGFW_errEGLContext, /*!< error with the OpenGL context */
  945+	RGFW_errWayland, RGFW_errX11,
  946+	RGFW_errDirectXContext,
  947+	RGFW_errIOKit,
  948+	RGFW_errClipboard,
  949+	RGFW_errFailedFuncLoad,
  950+	RGFW_errBuffer,
  951+	RGFW_errMetal,
  952+	RGFW_errPlatform,
  953+	RGFW_errEventQueue,
  954+	RGFW_infoWindow, RGFW_infoBuffer, RGFW_infoGlobal, RGFW_infoOpenGL,
  955+	RGFW_warningWayland, RGFW_warningOpenGL
  956+};
  957+
  958+/*! @brief data for debug messages */
  959+typedef struct RGFW_debugInfo {
  960+	RGFW_debugType type; /*!< the type of message */
  961+	RGFW_errorCode code; /*!< the code for the specific type of debug message */
  962+	const char* msg; /*!< string message */
  963+} RGFW_debugInfo;
  964+
  965+/*! @brief callback function type for debug messags */
  966+typedef void (* RGFW_debugFunc)(const RGFW_debugInfo* info);
  967+
  968+/*! @brief function pointer equivalent of void* */
  969+typedef void (*RGFW_proc)(void);
  970+
  971+#if defined(RGFW_OPENGL)
  972+
  973+/*! @brief abstract structure for interfacing with the underlying OpenGL API */
  974+typedef struct RGFW_glContext RGFW_glContext;
  975+
  976+/*! @brief abstract structure for interfacing with the underlying EGL API */
  977+typedef struct RGFW_eglContext RGFW_eglContext;
  978+
  979+/*! values for the releaseBehavior hint */
  980+typedef RGFW_ENUM(i32, RGFW_glReleaseBehavior)   {
  981+	RGFW_glReleaseFlush = 0, /*!< flush the pipeline will be flushed when the context is release */
  982+	RGFW_glReleaseNone /*!< do nothing on release */
  983+};
  984+
  985+/*! values for the profile hint */
  986+typedef RGFW_ENUM(i32, RGFW_glProfile)  {
  987+	RGFW_glCore = 0, /*!< the core OpenGL version, e.g. just support for that version */
  988+	RGFW_glForwardCompatibility, /*!< only compatibility for newer versions of OpenGL as well as the requested version */
  989+	RGFW_glCompatibility, /*!< allow compatibility for older versions of OpenGL as well as the requested version */
  990+	RGFW_glES, /*!< use OpenGL ES */
  991+	RGFW_glWeb /*!< use WebGL version (otherwise the version is changed to match it's GLES equivalent) */
  992+};
  993+
  994+/*! values for the renderer hint */
  995+typedef RGFW_ENUM(i32, RGFW_glRenderer)  {
  996+	RGFW_glAccelerated = 0, /*!< hardware accelerated (GPU) */
  997+	RGFW_glSoftware /*!< software rendered (CPU) */
  998+};
  999+
 1000+/*! OpenGL initalization hints */
 1001+typedef struct RGFW_glHints {
 1002+	i32 stencil;  /*!< set stencil buffer bit size (0 by default) */
 1003+	i32 samples; /*!< set number of sample buffers (0 by default) */
 1004+	i32 stereo; /*!< hint the context to use stereoscopic frame buffers for 3D (false by default) */
 1005+	i32 auxBuffers; /*!< number of aux buffers (0 by default) */
 1006+	i32 doubleBuffer; /*!< request double buffering (true by default) */
 1007+	i32 red, green, blue, alpha; /*!< set color bit sizes (all 8 by default) */
 1008+	i32 depth; /*!< set depth buffer bit size (24 by default) */
 1009+	i32 accumRed, accumGreen, accumBlue, accumAlpha; /*!< set accumulated RGBA bit sizes (all 0 by default) */
 1010+	RGFW_bool sRGB; /*!< request sRGA format (false by default) */
 1011+	RGFW_bool robustness; /*!< request a "robust" (as in memory-safe) context (false by default). For more information check the overview section: https://registry.khronos.org/OpenGL/extensions/EXT/EXT_robustness.txt */
 1012+	RGFW_bool debug; /*!< request OpenGL debugging (false by default). */
 1013+	RGFW_bool noError; /*!< request no OpenGL errors (false by default). This causes OpenGL errors to be undefined behavior. For more information check the overview section: https://registry.khronos.org/OpenGL/extensions/KHR/KHR_no_error.txt */
 1014+	RGFW_glReleaseBehavior releaseBehavior; /*!< hint how the OpenGL driver should behave when changing contexts (RGFW_glReleaseNone by default). For more information check the overview section: https://registry.khronos.org/OpenGL/extensions/KHR/KHR_context_flush_control.txt */
 1015+	RGFW_glProfile profile; /*!< set OpenGL API profile (RGFW_glCore by default) */
 1016+	i32 major, minor;  /*!< set the OpenGL API profile version (by default RGFW_glMajor is 1, RGFW_glMinor is 0) */
 1017+	RGFW_glContext* share; /*!< Share this OpenGL context with newly created OpenGL contexts; defaults to NULL. */
 1018+	RGFW_eglContext* shareEGL; /*!< Share this EGL context with newly created OpenGL contexts; defaults to NULL. */
 1019+	RGFW_glRenderer renderer; /*!< renderer to use e.g. accelerated or software defaults to accelerated */
 1020+} RGFW_glHints;
 1021+
 1022+#endif
 1023+
 1024+/**!
 1025+ * @brief Allocates memory using the allocator defined by RGFW_ALLOC at compile time.
 1026+ * @param size The size (in bytes) of the memory block to allocate.
 1027+ * @return A pointer to the allocated memory block.
 1028+*/
 1029+RGFWDEF void* RGFW_alloc(size_t size);
 1030+
 1031+/**!
 1032+ * @brief Frees memory using the deallocator defined by RGFW_FREE at compile time.
 1033+ * @param ptr A pointer to the memory block to free.
 1034+*/
 1035+RGFWDEF void RGFW_free(void* ptr);
 1036+
 1037+/**!
 1038+ * @brief Returns the size (in bytes) of the RGFW_window structure.
 1039+ * @return The size of the RGFW_window structure.
 1040+*/
 1041+RGFWDEF size_t RGFW_sizeofWindow(void);
 1042+
 1043+/**!
 1044+ * @brief Returns the size (in bytes) of the RGFW_window_src structure.
 1045+ * @return The size of the RGFW_window_src structure.
 1046+*/
 1047+RGFWDEF size_t RGFW_sizeofWindowSrc(void);
 1048+
 1049+/**!
 1050+ * @brief (Unix) Toggles the use of Wayland.
 1051+ * This is enabled by default when compiled with `RGFW_WAYLAND`.
 1052+ * If not using `RGFW_WAYLAND`, Wayland functions are not exposed.
 1053+ * This function can be used to force the use of XWayland.
 1054+ * @param wayland A boolean value indicating whether to use Wayland (true) or not (false).
 1055+*/
 1056+RGFWDEF void RGFW_useWayland(RGFW_bool wayland);
 1057+
 1058+/**!
 1059+ * @brief Checks if Wayland is currently being used.
 1060+ * @return RGFW_TRUE if using Wayland, RGFW_FALSE otherwise.
 1061+*/
 1062+RGFWDEF RGFW_bool RGFW_usingWayland(void);
 1063+
 1064+/**!
 1065+ * @brief Retrieves the current Cocoa layer (macOS only).
 1066+ * @return A pointer to the Cocoa layer, or NULL if the platform is not in use.
 1067+*/
 1068+RGFWDEF void* RGFW_getLayer_OSX(void);
 1069+
 1070+/**!
 1071+ * @brief Retrieves the current X11 display connection.
 1072+ * @return A pointer to the X11 display, or NULL if the platform is not in use.
 1073+*/
 1074+RGFWDEF void* RGFW_getDisplay_X11(void);
 1075+
 1076+/**!
 1077+ * @brief Retrieves the current Wayland display connection.
 1078+ * @return A pointer to the Wayland display (`struct wl_display*`), or NULL if the platform is not in use.
 1079+*/
 1080+RGFWDEF struct wl_display* RGFW_getDisplay_Wayland(void);
 1081+
 1082+/**!
 1083+ * @brief Sets the class name for X11 and WinAPI windows.
 1084+ * Windows with the same class name will be grouped by the window manager.
 1085+ * By default, the class name matches the root window’s name.
 1086+ * @param name The class name to assign.
 1087+*/
 1088+RGFWDEF void RGFW_setClassName(const char* name);
 1089+
 1090+/**!
 1091+ * @brief Sets the X11 instance name.
 1092+ * By default, the window name will be used as the instance name.
 1093+ * @param name The X11 instance name to set.
 1094+*/
 1095+RGFWDEF void RGFW_setXInstName(const char* name);
 1096+
 1097+/**!
 1098+ * @brief (macOS only) Changes the current working directory to the application’s resource folder.
 1099+*/
 1100+RGFWDEF void RGFW_moveToMacOSResourceDir(void);
 1101+
 1102+/*! copy image to another image, respecting each image's format */
 1103+RGFWDEF void RGFW_copyImageData(u8* dest_data, i32 w, i32 h, RGFW_format dest_format, u8* src_data, RGFW_format src_format, RGFW_convertImageDataFunc func);
 1104+
 1105+/**!
 1106+ * @brief Returns the size (in bytes) of the RGFW_nativeImage structure.
 1107+ * @return The size of the RGFW_nativeImage structure.
 1108+*/
 1109+RGFWDEF size_t RGFW_sizeofNativeImage(void);
 1110+
 1111+/**!
 1112+ * @brief Returns the size (in bytes) of the RGFW_surface structure.
 1113+ * @return The size of the RGFW_surface structure.
 1114+*/
 1115+RGFWDEF size_t RGFW_sizeofSurface(void);
 1116+
 1117+/**!
 1118+ * @brief Returns the native format type for the system
 1119+ * @return the native format type for the system as a RGFW_format enum value
 1120+*/
 1121+RGFWDEF RGFW_format RGFW_nativeFormat(void);
 1122+
 1123+/**!
 1124+ * @brief Creates a new surface from raw pixel data.
 1125+ * @param data A pointer to the pixel data buffer.
 1126+ * @param w The width of the surface in pixels.
 1127+ * @param h The height of the surface in pixels.
 1128+ * @param format The pixel format of the data.
 1129+ * @return A pointer to the newly created RGFW_surface.
 1130+ *
 1131+ * NOTE: when you create a surface using RGFW_createSurface / ptr, on X11 it uses the root window's visual
 1132+ * this means it may fail to render on any other window if the visual does not match
 1133+ * RGFW_window_createSurface and RGFW_window_createSurfacePtr exist only for X11 to address this issues
 1134+ * Of course, you can also manually set the root window with RGFW_setRootWindow
 1135+*/
 1136+RGFWDEF RGFW_surface* RGFW_createSurface(u8* data, i32 w, i32 h, RGFW_format format);
 1137+
 1138+/**!
 1139+ * @brief Creates a surface using a pre-allocated RGFW_surface structure.
 1140+ * @param data A pointer to the pixel data buffer.
 1141+ * @param w The width of the surface in pixels.
 1142+ * @param h The height of the surface in pixels.
 1143+ * @param format The pixel format of the data.
 1144+ * @param surface A pointer to a pre-allocated RGFW_surface structure.
 1145+ * @return RGFW_TRUE if successful, RGFW_FALSE otherwise.
 1146+*/
 1147+RGFWDEF RGFW_bool RGFW_createSurfacePtr(u8* data, i32 w, i32 h, RGFW_format format, RGFW_surface* surface);
 1148+
 1149+/**!
 1150+ * @brief Retrieves the native image associated with a surface.
 1151+ * @param surface A pointer to the RGFW_surface.
 1152+ * @return A pointer to the native RGFW_nativeImage associated with the surface.
 1153+*/
 1154+RGFWDEF RGFW_nativeImage* RGFW_surface_getNativeImage(RGFW_surface* surface);
 1155+
 1156+/**!
 1157+ * @brief Frees the surface pointer and any buffers used for software rendering.
 1158+ * @param surface A pointer to the RGFW_surface to free.
 1159+*/
 1160+RGFWDEF void RGFW_surface_free(RGFW_surface* surface);
 1161+
 1162+/**!
 1163+ * @brief Frees only the internal buffers used for software rendering, leaving the surface struct intact.
 1164+ * @param surface A pointer to the RGFW_surface whose buffers should be freed.
 1165+*/
 1166+RGFWDEF void RGFW_surface_freePtr(RGFW_surface* surface);
 1167+
 1168+
 1169+/**!
 1170+ * @brief create a mouse icon from bitmap data (similar to RGFW_window_setIcon).
 1171+ * @param data A pointer to the bitmap pixel data.
 1172+ * @param w The width of the mouse icon in pixels.
 1173+ * @param h The height of the mouse icon in pixels.
 1174+ * @param format The pixel format of the data.
 1175+ * @return A pointer to the newly loaded RGFW_mouse structure.
 1176+ *
 1177+ * @note The icon is not resized by default.
 1178+*/
 1179+RGFWDEF RGFW_mouse* RGFW_createMouse(u8* data, i32 w, i32 h, RGFW_format format);
 1180+
 1181+/**!
 1182+ * @brief create a standard mouse icon
 1183+ * @param mouse The standard cursor type (see RGFW_MOUSE enum).
 1184+ * @return A pointer to the newly loaded RGFW_mouse structure.
 1185+*/
 1186+RGFWDEF RGFW_mouse* RGFW_createMouseStandard(RGFW_mouseIcon mouse);
 1187+
 1188+/**!
 1189+ * @brief Frees the data associated with an RGFW_mouse structure.
 1190+ * @param mouse A pointer to the RGFW_mouse to free.
 1191+*/
 1192+RGFWDEF void RGFW_freeMouse(RGFW_mouse* mouse);
 1193+
 1194+/**!
 1195+ * @brief Get an allocated array of the supported modes of a monitor
 1196+ * @param monitor the source monitor object
 1197+ * @param count [OUTPUT] the count of the array
 1198+ * @return the allocated array of supported modes
 1199+*/
 1200+RGFWDEF RGFW_monitorMode* RGFW_monitor_getModes(RGFW_monitor* monitor, size_t* count);
 1201+
 1202+/**!
 1203+ * @brief Free RGFW allocated modes array
 1204+ * @param monitor the source monitor object
 1205+ * @param modes a pointer to an allocated array of modes
 1206+*/
 1207+RGFWDEF void RGFW_freeModes(RGFW_monitorMode* modes);
 1208+
 1209+/**!
 1210+ * @brief Get the supported modes of a monitor using a pre-allocated array
 1211+ * @param monitor the source monitor object
 1212+ * @param modes [OUTPUT] a pointer to an allocated array of modes
 1213+ * @return the number of (possible) modes, if [modes == NULL] the possible nodes *may* be less than the actual modes
 1214+*/
 1215+RGFWDEF size_t RGFW_monitor_getModesPtr(RGFW_monitor* monitor, RGFW_monitorMode** modes);
 1216+
 1217+/**!
 1218+ * @brief find the closest monitor mode based on the give mode with size being the highest priority, format being the second and refreshrate being the third.
 1219+ * @param monitor the source monitor object
 1220+ * @param mode user filled mode to use for comparison
 1221+ * @param modes [OUTPUT] a pointer to be filled with the output closest monitor
 1222+ * @return returns true if a suitable monitor was found and false if no suitable monitor was found at all
 1223+*/
 1224+
 1225+RGFWDEF RGFW_bool RGFW_monitor_findClosestMode(RGFW_monitor* monitor, RGFW_monitorMode* mode, RGFW_monitorMode* closest);
 1226+
 1227+/**!
 1228+ * @brief Get the allocated gamma ramp
 1229+ * @param monitor the source monitor object
 1230+*/
 1231+RGFWDEF RGFW_gammaRamp* RGFW_monitor_getGammaRamp(RGFW_monitor* monitor);
 1232+
 1233+/**!
 1234+ * @brief Free the gamma ramp allocated by RGFW
 1235+ * @param allocated gamma ramp
 1236+*/
 1237+RGFWDEF void RGFW_freeGammaRamp(RGFW_gammaRamp* ramp);
 1238+
 1239+/**!
 1240+ * @brief Get the monitor's gamma ramp using a pre-allocated struct with allocated data
 1241+ * @param monitor the source monitor object
 1242+ * @param ramp [OUTPUT] a pointer to an allocated gamma ramp (can be NULL to just get the count)
 1243+ * @return the count of the gamma ramp
 1244+*/
 1245+RGFWDEF size_t RGFW_monitor_getGammaRampPtr(RGFW_monitor* monitor, RGFW_gammaRamp* ramp);
 1246+
 1247+/**!
 1248+ * @brief Set the monitor's gamma ramp using a pre-allocated struct with allocated data
 1249+ * @param monitor the source monitor object
 1250+ * @param ramp a pointer to an allocated gamma ramp
 1251+ * @return a bool if the function was successful
 1252+*/
 1253+RGFWDEF RGFW_bool RGFW_monitor_setGammaRamp(RGFW_monitor* monitor, RGFW_gammaRamp* ramp);
 1254+
 1255+/**!
 1256+ * @brief Create and set the monitor's gamma ramp with a base gamma exponent
 1257+ * @param monitor the source monitor object
 1258+ * @param the gamma exponent
 1259+ * @return a bool if the function was successful
 1260+*/
 1261+RGFWDEF RGFW_bool RGFW_monitor_setGamma(RGFW_monitor* monitor, float gamma);
 1262+
 1263+/**!
 1264+ * @brief Create and set the monitor's gamma ramp with a base gamma exponent using a pre-allocated array
 1265+ * @param monitor the source monitor object
 1266+ * @param gamma the gamma exponent
 1267+ * @param pre-allocated gammaramp channel
 1268+ * @param count the length of the allocated channel array
 1269+ * @return a bool if the function was successful
 1270+*/
 1271+RGFWDEF RGFW_bool RGFW_monitor_setGammaPtr(RGFW_monitor* monitor, float gamma, u16* ptr, size_t count);
 1272+
 1273+/**!
 1274+ * @brief Get the workarea of a monitor, meaning the parts not occupied by OS graphics (i.e. the taskbar)
 1275+ * @param monitor the source monitor object
 1276+ * @param x [OUTPUT] the x pos of the workarea
 1277+ * @param y [OUTPUT] the y pos of the workarea
 1278+ * @param w [OUTPUT] the width of the workarea
 1279+ * @param h [OUTPUT] the height of the workarea
 1280+ * @return a bool if the function was successful
 1281+*/
 1282+RGFWDEF RGFW_bool RGFW_monitor_getWorkarea(RGFW_monitor* monitor, i32* x, i32* y, i32* width, i32* height);
 1283+
 1284+/**!
 1285+ * @brief Get the position of a monitor (the same as monitor.x / monitor.y)
 1286+ * @param x [OUTPUT] the x position of the monitor
 1287+ * @param y [OUTPUT] the y position of the monitor
 1288+ * @return a bool if the function was successful
 1289+*/
 1290+RGFWDEF RGFW_bool RGFW_monitor_getPosition(RGFW_monitor* monitor, i32* x, i32* y);
 1291+
 1292+/**!
 1293+ * @brief Get the name of a monitor (the same as monitor.name)
 1294+ * @return the cstring of the monitor's name
 1295+*/
 1296+RGFWDEF const char* RGFW_monitor_getName(RGFW_monitor* monitor);
 1297+
 1298+/**!
 1299+ * @brief Get the scale of a monitor (the same as monitor.scaleX / monitor.scaleY)
 1300+ * @param monitor the source monitor object
 1301+ * @param x [OUTPUT] the x scale of the monitor
 1302+ * @param y [OUTPUT] the y scale of the monitor
 1303+ * @return a bool if the function was successful
 1304+*/
 1305+RGFWDEF RGFW_bool RGFW_monitor_getScale(RGFW_monitor* monitor, float* x, float* y);
 1306+
 1307+/**!
 1308+ * @brief Get the physical size of a monitor (the same as monitor.physW / monitor.physH)
 1309+ * @param monitor the source monitor object
 1310+ * @param w [OUTPUT] the physical width of the monitor
 1311+ * @param h [OUTPUT] the physical height of the monitor
 1312+ * @return a bool if the function was successful
 1313+*/
 1314+RGFWDEF RGFW_bool RGFW_monitor_getPhysicalSize(RGFW_monitor* monitor, float* w, float* h);
 1315+
 1316+/**!
 1317+ * @brief Set the user pointer of a monitor (the same as monitor.userPtr = userPtr)
 1318+ * @param monitor the source monitor object
 1319+ * @param userPtr the new user pointer for the monitor
 1320+*/
 1321+RGFWDEF void RGFW_monitor_setUserPtr(RGFW_monitor* monitor, void* userPtr);
 1322+
 1323+/**!
 1324+ * @brief Get the user pointer of a monitor (the same as monitor.userPtr)
 1325+ * @param monitor the source monitor object
 1326+ * @return the user pointer of the monitor
 1327+*/
 1328+RGFWDEF void* RGFW_monitor_getUserPtr(RGFW_monitor* monitor);
 1329+
 1330+/**!
 1331+ * @brief Get the mode of a monitor (the same as monitor.mode)
 1332+ * @param monitor the source monitor object
 1333+ * @param mode [OUTPUT] current mode the monitor
 1334+ * @return a bool if the function was successful
 1335+*/
 1336+RGFWDEF RGFW_bool RGFW_monitor_getMode(RGFW_monitor* monitor, RGFW_monitorMode* mode);
 1337+
 1338+/**!
 1339+ * @brief Poll and check for monitor updates (this is called internally on monitor update events and RGFW_init)
 1340+*/
 1341+RGFWDEF void RGFW_pollMonitors(void);
 1342+
 1343+/**!
 1344+ * @brief Allocates and returns an array of all available monitors.
 1345+ * @param len [OUTPUT] A pointer to store the number of monitors found.
 1346+ * @return An allocated array of pointers to RGFW_monitor structures that must be freed.
 1347+*/
 1348+RGFWDEF RGFW_monitor** RGFW_getMonitors(size_t* len);
 1349+
 1350+/**!
 1351+ * @brief fills a pre-allocated array with available monitors.
 1352+ * @param maximum number of monitors that the passed [monitors] buffer supports, can be zero to get the length alone
 1353+ * @param pre-allocated buffer of monitors, can be NULL to get the length alone
 1354+ * @param len [OUTPUT] A pointer to store the number of monitors found, if max is not zero and monitors is not NULL, length will be set to max.
 1355+ * @return An array of pointers to RGFW_monitor structures or NULL if the function failed.
 1356+*/
 1357+RGFWDEF RGFW_bool RGFW_getMonitorsPtr(size_t max, RGFW_monitor** monitors, size_t* len);
 1358+
 1359+/**!
 1360+ * @brief Retrieves the primary monitor.
 1361+ * @return A pointer to the RGFW_monitor structure representing the primary monitor.
 1362+*/
 1363+RGFWDEF RGFW_monitor* RGFW_getPrimaryMonitor(void);
 1364+
 1365+/**!
 1366+ * @brief Requests the display mode for a monitor (based on what attributes are directly requested).
 1367+ * @param mon The monitor to apply the mode change to.
 1368+ * @param mode The desired RGFW_monitorMode.
 1369+ * @param request The RGFW_modeRequest describing how to handle the mode change.
 1370+ * @return RGFW_TRUE if the mode was successfully applied, otherwise RGFW_FALSE.
 1371+*/
 1372+RGFWDEF RGFW_bool RGFW_monitor_requestMode(RGFW_monitor* mon, RGFW_monitorMode* mode, RGFW_modeRequest request);
 1373+
 1374+/**!
 1375+ * @brief Sets a specific display mode for a monitor directly.
 1376+ * @param mon The monitor to apply the mode change to.
 1377+ * @param mode The desired RGFW_monitorMode.
 1378+ * @param request The RGFW_modeRequest describing how to handle the mode change.
 1379+ * @return RGFW_TRUE if the mode was successfully applied, otherwise RGFW_FALSE.
 1380+*/
 1381+RGFWDEF RGFW_bool RGFW_monitor_setMode(RGFW_monitor* mon, RGFW_monitorMode* mode);
 1382+
 1383+/**!
 1384+ * @brief Compares two monitor modes to check if they are equivalent.
 1385+ * @param mon The first monitor mode.
 1386+ * @param mon2 The second monitor mode.
 1387+ * @param request The RGFW_modeRequest that defines the comparison parameters.
 1388+ * @return RGFW_TRUE if both modes are equivalent, otherwise RGFW_FALSE.
 1389+*/
 1390+RGFWDEF RGFW_bool RGFW_monitorModeCompare(RGFW_monitorMode* mon, RGFW_monitorMode* mon2, RGFW_modeRequest request);
 1391+
 1392+/**!
 1393+ * @brief Scales a monitor’s mode to match a window’s size.
 1394+ * @param mon The monitor to be scaled.
 1395+ * @param win The window whose size should be used as a reference.
 1396+ * @return RGFW_TRUE if the scaling was successful, otherwise RGFW_FALSE.
 1397+*/
 1398+RGFWDEF RGFW_bool RGFW_monitor_scaleToWindow(RGFW_monitor* mon, struct RGFW_window* win);
 1399+
 1400+ /**!
 1401+ * @brief set (enable or disable) raw mouse mode globally
 1402+ * @param the boolean state of raw mouse mode
 1403+ *
 1404+*/
 1405+RGFWDEF void RGFW_setRawMouseMode(RGFW_bool state);
 1406+
 1407+/**!
 1408+ * @brief toggles building the drag-and-drop (DND) linked list
 1409+ * @param allow RGFW_TRUE to allow DND building, RGFW_FALSE to disable
 1410+ * @note this is for state checking, the list is created by default if you are using the event queue
 1411+*/
 1412+RGFWDEF void RGFW_setBuildDND(RGFW_bool allow);
 1413+
 1414+/**!
 1415+* @brief sleep until RGFW gets an event or the timer ends (defined by OS)
 1416+* @param waitMS how long to wait for the next event (in miliseconds)
 1417+*/
 1418+RGFWDEF void RGFW_waitForEvent(i32 waitMS);
 1419+
 1420+/**!
 1421+* @brief Set if events should be queued or not (enabled by default if the event queue is checked)
 1422+* @param queue boolean value if RGFW should queue events or not
 1423+*/
 1424+RGFWDEF void RGFW_setQueueEvents(RGFW_bool queue);
 1425+
 1426+/**!
 1427+ * @brief Sets the callback function for the event.
 1428+ * @param the event type for the callback
 1429+ * @param func The function to be called when the event is triggered.
 1430+ * @return The previously set callback function, if any.
 1431+*/
 1432+RGFWDEF RGFW_genericFunc RGFW_setEventCallback(RGFW_eventType type, RGFW_genericFunc func);
 1433+
 1434+/**!
 1435+ * @brief Sets the callback function for two continuous events.
 1436+ * @param func The function to be called when the event is triggered.
 1437+ * @param [OUTPUT] The previously set callback function for the first event, if any.
 1438+ * @param [OUTPUT] The previously set callback function for the second event, if any.
 1439+*/
 1440+RGFWDEF void RGFW_setDualEventCallback(RGFW_eventType type, RGFW_genericFunc func, RGFW_genericFunc* first, RGFW_genericFunc* second);
 1441+
 1442+/**!
 1443+ * @brief Sets the callback function for all events.
 1444+ * @param func The function to be called when the event is triggered.
 1445+ * @param [OUTPUT] a structure that holds an array of all the event callbacks
 1446+*/
 1447+RGFWDEF void RGFW_setAllEventCallbacks(RGFW_genericFunc func, RGFW_callbacks* callbacks);
 1448+
 1449+/**!
 1450+* @brief check all the events until there are none left and updates window structure attributes
 1451+*/
 1452+RGFWDEF void RGFW_pollEvents(void);
 1453+
 1454+/**!
 1455+* @brief check all the events until there are none left and updates window structure attributes
 1456+* queues events if the queue is checked and/or requested
 1457+*/
 1458+RGFWDEF void RGFW_stopCheckEvents(void);
 1459+
 1460+/**!
 1461+ * @brief polls and pops the next event
 1462+ * @param event [OUTPUT] a pointer to store the retrieved event
 1463+ * @return RGFW_TRUE if an event was found, RGFW_FALSE otherwise
 1464+ *
 1465+ * NOTE: Using this function without a loop may cause event lag.
 1466+ * For multi-threaded systems, use RGFW_pollEvents combined with RGFW_checkQueuedEvent.
 1467+ *
 1468+ * Example:
 1469+ * RGFW_event event;
 1470+ * while (RGFW_checkEvent(win, &event)) {
 1471+ *     // handle event
 1472+ * }
 1473+*/
 1474+RGFWDEF RGFW_bool RGFW_checkEvent(RGFW_event* event);
 1475+
 1476+/**!
 1477+ * @brief pops the first queued event
 1478+ * @param event [OUTPUT] a pointer to store the retrieved event
 1479+ * @return RGFW_TRUE if an event was found, RGFW_FALSE otherwise
 1480+*/
 1481+RGFWDEF RGFW_bool RGFW_checkQueuedEvent(RGFW_event* event);
 1482+
 1483+/** * @defgroup Input
 1484+* @{ */
 1485+
 1486+/**!
 1487+ * @brief returns true if the key is pressed during the current frame
 1488+ * @param key the key code of the key you want to check
 1489+ * @return The boolean value if the key is pressed or not
 1490+*/
 1491+RGFWDEF RGFW_bool RGFW_isKeyPressed(RGFW_key key);
 1492+
 1493+/**!
 1494+ * @brief returns true if the key was released during the current frame
 1495+ * @param key the key code of the key you want to check
 1496+ * @return The boolean value if the key is released or not
 1497+*/
 1498+RGFWDEF RGFW_bool RGFW_isKeyReleased(RGFW_key key);
 1499+
 1500+/**!
 1501+ * @brief returns true if the key is down
 1502+ * @param key the key code of the key you want to check
 1503+ * @return The boolean value if the key is down or not
 1504+*/
 1505+RGFWDEF RGFW_bool RGFW_isKeyDown(RGFW_key key);
 1506+
 1507+/**!
 1508+ * @brief returns true if the mouse button is pressed during the current frame
 1509+ * @param button the mouse button code of the button you want to check
 1510+ * @return The boolean value if the button is pressed or not
 1511+*/
 1512+RGFWDEF RGFW_bool RGFW_isMousePressed(RGFW_mouseButton button);
 1513+
 1514+/**!
 1515+ * @brief returns true if the mouse button is released during the current frame
 1516+ * @param button the mouse button code of the button you want to check
 1517+ * @return The boolean value if the button is released or not
 1518+*/
 1519+RGFWDEF RGFW_bool RGFW_isMouseReleased(RGFW_mouseButton button);
 1520+
 1521+/**!
 1522+ * @brief returns true if the mouse button is down
 1523+ * @param button the mouse button code of the button you want to check
 1524+ * @return The boolean value if the button is down or not
 1525+*/
 1526+RGFWDEF RGFW_bool RGFW_isMouseDown(RGFW_mouseButton button);
 1527+
 1528+/**!
 1529+ * @brief outputs the current x, y position of the mouse
 1530+ * @param X [OUTPUT] a pointer for the output X value
 1531+ * @param Y [OUTPUT] a pointer for the output Y value
 1532+*/
 1533+RGFWDEF void RGFW_getMouseScroll(float* x, float* y);
 1534+
 1535+/**!
 1536+ * @brief outputs the current x, y movement vector of the mouse
 1537+ * @param X [OUTPUT] a pointer for the output X vector value
 1538+ * @param Y [OUTPUT] a pointer for the output Y vector value
 1539+*/
 1540+RGFWDEF void RGFW_getMouseVector(float* x, float* y);
 1541+/** @} */
 1542+
 1543+/**!
 1544+ * @brief creates a new window
 1545+ * @param name the requested title of the window
 1546+ * @param x the requested x position of the window
 1547+ * @param y the requested y position of the window
 1548+ * @param w the requested width of the window
 1549+ * @param h the requested height of the window
 1550+ * @param flags extra arguments ((u32)0 means no flags used)
 1551+ * @return A pointer to the newly created window structure
 1552+ *
 1553+ * NOTE: (windows) if the executable has an icon resource named RGFW_ICON, it will be set as the initial icon for the window
 1554+*/
 1555+RGFWDEF RGFW_window* RGFW_createWindow(const char* name, i32 x, i32 y, i32 w, i32 h,  RGFW_windowFlags flags);
 1556+
 1557+/**!
 1558+ * @brief creates a new window using a pre-allocated window structure
 1559+ * @param name the requested title of the window
 1560+ * @param x the requested x position of the window
 1561+ * @param y the requested y position of the window
 1562+ * @param w the requested width of the window
 1563+ * @param h the requested height of the window
 1564+ * @param flags extra arguments ((u32)0 means no flags used)
 1565+ * @param win a pointer the pre-allocated window structure
 1566+ * @return A pointer to the newly created window structure
 1567+*/
 1568+RGFWDEF RGFW_window* RGFW_createWindowPtr(const char* name, i32 x, i32 y, i32 w, i32 h, RGFW_windowFlags flags, RGFW_window* win);
 1569+
 1570+/**!
 1571+ * @brief creates a new surface structure
 1572+ * @param win the source window of the surface
 1573+ * @param data a pointer to the raw data of the structure (you allocate this)
 1574+ * @param w the width the data
 1575+ * @param h the height of the data
 1576+ * @return A pointer to the newly created surface structure
 1577+ *
 1578+ * NOTE: when you create a surface using RGFW_createSurface / ptr, on X11 it uses the root window's visual
 1579+ * this means it may fail to render on any other window if the visual does not match
 1580+ * RGFW_window_createSurface and RGFW_window_createSurfacePtr exist only for X11 to address this issues
 1581+ * Of course, you can also manually set the root window with RGFW_setRootWindow
 1582+ */
 1583+RGFWDEF RGFW_surface* RGFW_window_createSurface(RGFW_window* win, u8* data, i32 w, i32 h, RGFW_format format);
 1584+
 1585+/**!
 1586+ * @brief creates a new surface structure using a pre-allocated surface structure
 1587+ * @param win the source window of the surface
 1588+ * @param data a pointer to the raw data of the structure (you allocate this)
 1589+ * @param w the width the data
 1590+ * @param h the height of the data
 1591+ * @param a pointer to the pre-allocated surface structure
 1592+ * @return a bool if the creation was successful or not
 1593+*/
 1594+RGFWDEF RGFW_bool RGFW_window_createSurfacePtr(RGFW_window* win, u8* data, i32 w, i32 h, RGFW_format format, RGFW_surface* surface);
 1595+
 1596+/**!
 1597+ * @brief set the function/callback used for converting surface data between formats
 1598+ * @param surface a pointer to the surface
 1599+ * @param a function pointer for the function to use [if NULL the default function is used]
 1600+*/
 1601+RGFWDEF void RGFW_surface_setConvertFunc(RGFW_surface* surface, RGFW_convertImageDataFunc func);
 1602+
 1603+/**!
 1604+ * @brief blits a surface stucture to the window
 1605+ * @param win a pointer the window to blit to
 1606+ * @param surface a pointer to the surface
 1607+*/
 1608+RGFWDEF void RGFW_window_blitSurface(RGFW_window* win, RGFW_surface* surface);
 1609+
 1610+/**!
 1611+ * @brief gets the position of the window | with RGFW_window.x and window.y
 1612+ * @param x [OUTPUT] the x position of the window
 1613+ * @param y [OUTPUT] the y position of the window
 1614+ * @return a bool if the function was successful
 1615+*/
 1616+RGFWDEF RGFW_bool RGFW_window_getPosition(RGFW_window* win, i32* x, i32* y); /*!<  */
 1617+
 1618+/**!
 1619+ * @brief gets the size of the window | with RGFW_window.w and window.h
 1620+ * @param win a pointer to the window
 1621+ * @param w [OUTPUT] the width of the window
 1622+ * @param h [OUTPUT] the height of the window
 1623+ * @return a bool if the function was successful
 1624+*/
 1625+RGFWDEF RGFW_bool RGFW_window_getSize(RGFW_window* win, i32* w, i32* h);
 1626+
 1627+/**!
 1628+ * @brief gets the size of the window in exact pixels
 1629+ * @param win a pointer to the window
 1630+ * @param w [OUTPUT] the width of the window
 1631+ * @param h [OUTPUT] the height of the window
 1632+ * @return a bool if the function was successful
 1633+*/
 1634+RGFWDEF RGFW_bool RGFW_window_getSizeInPixels(RGFW_window* win, i32* w, i32* h);
 1635+
 1636+/**!
 1637+ * @brief gets the flags of the window | returns RGFW_window._flags
 1638+ * @param win a pointer to the window
 1639+ * @return the window flags
 1640+*/
 1641+RGFWDEF u32 RGFW_window_getFlags(RGFW_window* win);
 1642+
 1643+/**!
 1644+ * @brief returns the exit key assigned to the window
 1645+ * @param win a pointer to the target window
 1646+ * @return The key code assigned as the exit key
 1647+*/
 1648+RGFWDEF RGFW_key RGFW_window_getExitKey(RGFW_window* win);
 1649+
 1650+/**!
 1651+ * @brief sets the exit key for the window
 1652+ * @param win a pointer to the target window
 1653+ * @param key the key code to assign as the exit key
 1654+*/
 1655+RGFWDEF void RGFW_window_setExitKey(RGFW_window* win, RGFW_key key);
 1656+
 1657+/**!
 1658+ * @brief sets the types of events you want the window to receive
 1659+ * @param win a pointer to the target window
 1660+ * @param events the event flags to enable (use RGFW_allEventFlags for all)
 1661+*/
 1662+RGFWDEF void RGFW_window_setEnabledEvents(RGFW_window* win, RGFW_eventFlag events);
 1663+
 1664+/**!
 1665+ * @brief gets the currently enabled events for the window
 1666+ * @param win a pointer to the target window
 1667+ * @return The enabled event flags for the window
 1668+*/
 1669+RGFWDEF RGFW_eventFlag RGFW_window_getEnabledEvents(RGFW_window* win);
 1670+
 1671+/**!
 1672+ * @brief enables all events and disables selected ones
 1673+ * @param win a pointer to the target window
 1674+ * @param events the event flags to disable
 1675+*/
 1676+RGFWDEF void RGFW_window_setDisabledEvents(RGFW_window* win, RGFW_eventFlag events);
 1677+
 1678+/**!
 1679+ * @brief directly enables or disables a specific event or group of events
 1680+ * @param win a pointer to the target window
 1681+ * @param event the event flag or group of flags to modify
 1682+ * @param state RGFW_TRUE to enable, RGFW_FALSE to disable
 1683+*/
 1684+RGFWDEF void RGFW_window_setEventState(RGFW_window* win, RGFW_eventFlag event, RGFW_bool state);
 1685+
 1686+/**!
 1687+ * @brief gets the user pointer associated with the window
 1688+ * @param win a pointer to the target window
 1689+ * @return The user-defined pointer stored in the window
 1690+*/
 1691+RGFWDEF void* RGFW_window_getUserPtr(RGFW_window* win);
 1692+
 1693+/**!
 1694+ * @brief sets a user pointer for the window
 1695+ * @param win a pointer to the target window
 1696+ * @param ptr a pointer to associate with the window
 1697+*/
 1698+RGFWDEF void RGFW_window_setUserPtr(RGFW_window* win, void* ptr);
 1699+
 1700+/**!
 1701+ * @brief retrieves the platform-specific window source pointer
 1702+ * @param win a pointer to the target window
 1703+ * @return A pointer to the internal RGFW_window_src structure
 1704+*/
 1705+RGFWDEF RGFW_window_src* RGFW_window_getSrc(RGFW_window* win);
 1706+
 1707+/**!
 1708+ * @brief sets the macOS layer object associated with the window
 1709+ * @param win a pointer to the target window
 1710+ * @param layer a pointer to the macOS layer object
 1711+ * @note Only available on macOS platforms
 1712+*/
 1713+RGFWDEF void RGFW_window_setLayer_OSX(RGFW_window* win, void* layer);
 1714+
 1715+/**!
 1716+ * @brief retrieves the macOS view object associated with the window
 1717+ * @param win a pointer to the target window
 1718+ * @return A pointer to the macOS view object, or NULL if not on macOS
 1719+*/
 1720+RGFWDEF void* RGFW_window_getView_OSX(RGFW_window* win);
 1721+
 1722+/**!
 1723+ * @brief retrieves the macOS window object
 1724+ * @param win a pointer to the target window
 1725+ * @return A pointer to the macOS window object, or NULL if not on macOS
 1726+*/
 1727+RGFWDEF void* RGFW_window_getWindow_OSX(RGFW_window* win);
 1728+
 1729+/**!
 1730+ * @brief retrieves the HWND handle for the window
 1731+ * @param win a pointer to the target window
 1732+ * @return A pointer to the Windows HWND handle, or NULL if not on Windows
 1733+*/
 1734+RGFWDEF void* RGFW_window_getHWND(RGFW_window* win);
 1735+
 1736+/**!
 1737+ * @brief retrieves the HDC handle for the window
 1738+ * @param win a pointer to the target window
 1739+ * @return A pointer to the Windows HDC handle, or NULL if not on Windows
 1740+*/
 1741+RGFWDEF void* RGFW_window_getHDC(RGFW_window* win);
 1742+
 1743+/**!
 1744+ * @brief retrieves the X11 Window handle for the window
 1745+ * @param win a pointer to the target window
 1746+ * @return The X11 Window handle, or 0 if not on X11
 1747+*/
 1748+RGFWDEF u64 RGFW_window_getWindow_X11(RGFW_window* win);
 1749+
 1750+/**!
 1751+ * @brief retrieves the Wayland surface handle for the window
 1752+ * @param win a pointer to the target window
 1753+ * @return A pointer to the Wayland wl_surface, or NULL if not on Wayland
 1754+*/
 1755+RGFWDEF struct wl_surface* RGFW_window_getWindow_Wayland(RGFW_window* win);
 1756+
 1757+/** * @defgroup Window_management
 1758+* @{ */
 1759+
 1760+/*! set the window flags (will undo flags if they don't match the old ones) */
 1761+RGFWDEF void RGFW_window_setFlags(RGFW_window* win, RGFW_windowFlags);
 1762+
 1763+/**!
 1764+ * @brief polls and pops the next event with the matching target window in event queue, pushes back events that don't match
 1765+ * @param win a pointer to the target window
 1766+ * @param event [OUTPUT] a pointer to store the retrieved event
 1767+ * @return RGFW_TRUE if an event was found, RGFW_FALSE otherwise
 1768+ *
 1769+ * NOTE: Using this function without a loop may cause event lag.
 1770+ * For multi-threaded systems, use RGFW_pollEvents combined with RGFW_window_checkQueuedEvent.
 1771+ *
 1772+ * Example:
 1773+ * RGFW_event event;
 1774+ * while (RGFW_window_checkEvent(win, &event)) {
 1775+ *     // handle event
 1776+ * }
 1777+*/
 1778+RGFWDEF RGFW_bool RGFW_window_checkEvent(RGFW_window* win, RGFW_event* event);
 1779+
 1780+/**!
 1781+ * @brief pops the first queued event with the matching target window, pushes back events that don't match
 1782+ * @param win a pointer to the target window
 1783+ * @param event [OUTPUT] a pointer to store the retrieved event
 1784+ * @return RGFW_TRUE if an event was found, RGFW_FALSE otherwise
 1785+*/
 1786+RGFWDEF RGFW_bool RGFW_window_checkQueuedEvent(RGFW_window* win, RGFW_event* event);
 1787+
 1788+/**!
 1789+ * @brief checks if a key was pressed while the window is in focus
 1790+ * @param win a pointer to the target window
 1791+ * @param key the key code to check
 1792+ * @return RGFW_TRUE if the key was pressed, RGFW_FALSE otherwise
 1793+*/
 1794+RGFWDEF RGFW_bool RGFW_window_isKeyPressed(RGFW_window* win, RGFW_key key);
 1795+
 1796+/**!
 1797+ * @brief checks if a key is currently being held down
 1798+ * @param win a pointer to the target window
 1799+ * @param key the key code to check
 1800+ * @return RGFW_TRUE if the key is held down, RGFW_FALSE otherwise
 1801+*/
 1802+RGFWDEF RGFW_bool RGFW_window_isKeyDown(RGFW_window* win, RGFW_key key);
 1803+
 1804+/**!
 1805+ * @brief checks if a key was released
 1806+ * @param win a pointer to the target window
 1807+ * @param key the key code to check
 1808+ * @return RGFW_TRUE if the key was released, RGFW_FALSE otherwise
 1809+*/
 1810+RGFWDEF RGFW_bool RGFW_window_isKeyReleased(RGFW_window* win, RGFW_key key);
 1811+
 1812+/**!
 1813+ * @brief checks if a mouse button was pressed
 1814+ * @param win a pointer to the target window
 1815+ * @param button the mouse button code to check
 1816+ * @return RGFW_TRUE if the mouse button was pressed, RGFW_FALSE otherwise
 1817+*/
 1818+RGFWDEF RGFW_bool RGFW_window_isMousePressed(RGFW_window* win, RGFW_mouseButton button);
 1819+
 1820+/**!
 1821+ * @brief checks if a mouse button is currently held down
 1822+ * @param win a pointer to the target window
 1823+ * @param button the mouse button code to check
 1824+ * @return RGFW_TRUE if the mouse button is down, RGFW_FALSE otherwise
 1825+*/
 1826+RGFWDEF RGFW_bool RGFW_window_isMouseDown(RGFW_window* win, RGFW_mouseButton button);
 1827+
 1828+/**!
 1829+ * @brief checks if a mouse button was released
 1830+ * @param win a pointer to the target window
 1831+ * @param button the mouse button code to check
 1832+ * @return RGFW_TRUE if the mouse button was released, RGFW_FALSE otherwise
 1833+*/
 1834+RGFWDEF RGFW_bool RGFW_window_isMouseReleased(RGFW_window* win, RGFW_mouseButton button);
 1835+
 1836+/**!
 1837+ * @brief checks if the mouse left the window (true only for the first frame)
 1838+ * @param win a pointer to the target window
 1839+ * @return RGFW_TRUE if the mouse left, RGFW_FALSE otherwise
 1840+*/
 1841+RGFWDEF RGFW_bool RGFW_window_didMouseLeave(RGFW_window* win);
 1842+
 1843+/**!
 1844+ * @brief checks if the mouse entered the window (true only for the first frame)
 1845+ * @param win a pointer to the target window
 1846+ * @return RGFW_TRUE if the mouse entered, RGFW_FALSE otherwise
 1847+*/
 1848+RGFWDEF RGFW_bool RGFW_window_didMouseEnter(RGFW_window* win);
 1849+
 1850+/**!
 1851+ * @brief checks if the mouse is currently inside the window bounds
 1852+ * @param win a pointer to the target window
 1853+ * @return RGFW_TRUE if the mouse is inside, RGFW_FALSE otherwise
 1854+*/
 1855+RGFWDEF RGFW_bool RGFW_window_isMouseInside(RGFW_window* win);
 1856+
 1857+/**!
 1858+ * @brief checks if there is data being dragged into or within the window
 1859+ * @param win a pointer to the target window
 1860+ * @return RGFW_TRUE if data is being dragged, RGFW_FALSE otherwise
 1861+*/
 1862+RGFWDEF RGFW_bool RGFW_window_isDataDragging(RGFW_window* win);
 1863+
 1864+/**!
 1865+ * @brief gets the position of a data drag
 1866+ * @param win a pointer to the target window
 1867+ * @param x [OUTPUT] pointer to store the x position
 1868+ * @param y [OUTPUT] pointer to store the y position
 1869+ * @return RGFW_TRUE if there is an active drag, RGFW_FALSE otherwise
 1870+*/
 1871+RGFWDEF RGFW_bool RGFW_window_getDataDrag(RGFW_window* win, i32* x, i32* y);
 1872+
 1873+/**!
 1874+ * @brief checks if a data drop occurred in the window (first frame only)
 1875+ * @param win a pointer to the target window
 1876+ * @return RGFW_TRUE if data was dropped, RGFW_FALSE otherwise
 1877+*/
 1878+RGFWDEF RGFW_bool RGFW_window_didDataDrop(RGFW_window* win);
 1879+
 1880+/**!
 1881+ * @brief retrieves data from a data drop (drag and drop)
 1882+ * @param win a pointer to the target window
 1883+ * @return a valid pointer to the root drag node if a data drop occurred, NULL otherwise
 1884+*/
 1885+RGFWDEF RGFW_dataDropNode* RGFW_window_getDataDrop(RGFW_window* win);
 1886+
 1887+/**!
 1888+ * @brief closes the window and frees its associated structure
 1889+ * @param win a pointer to the target window
 1890+*/
 1891+RGFWDEF void RGFW_window_close(RGFW_window* win);
 1892+
 1893+/**!
 1894+ * @brief closes the window without freeing its structure
 1895+ * @param win a pointer to the target window
 1896+*/
 1897+RGFWDEF void RGFW_window_closePtr(RGFW_window* win);
 1898+
 1899+/**!
 1900+ * @brief fetches the size of the window through the OS (and updates the internal values)
 1901+ * @param win a pointer to the window
 1902+ * @param w [OUTPUT] the width of the window
 1903+ * @param h [OUTPUT] the height of the window
 1904+ * @return a bool if the function was successful
 1905+*/
 1906+RGFWDEF RGFW_bool RGFW_window_fetchSize(RGFW_window* win, i32* w, i32* h);
 1907+
 1908+/**!
 1909+ * @brief moves the window to a new position on the screen
 1910+ * @param win a pointer to the target window
 1911+ * @param x the new x position
 1912+ * @param y the new y position
 1913+*/
 1914+RGFWDEF void RGFW_window_move(RGFW_window* win, i32 x, i32 y);
 1915+
 1916+/**!
 1917+ * @brief moves the window to a specific monitor
 1918+ * @param win a pointer to the target window
 1919+ * @param m the target monitor
 1920+*/
 1921+RGFWDEF void RGFW_window_moveToMonitor(RGFW_window* win, RGFW_monitor* m);
 1922+
 1923+/**!
 1924+ * @brief resizes the window to the given dimensions
 1925+ * @param win a pointer to the target window
 1926+ * @param w the new width
 1927+ * @param h the new height
 1928+*/
 1929+RGFWDEF void RGFW_window_resize(RGFW_window* win, i32 w, i32 h);
 1930+
 1931+/**!
 1932+ * @brief sets the aspect ratio of the window
 1933+ * @param win a pointer to the target window
 1934+ * @param w the width ratio
 1935+ * @param h the height ratio
 1936+*/
 1937+RGFWDEF void RGFW_window_setAspectRatio(RGFW_window* win, i32 w, i32 h);
 1938+
 1939+/**!
 1940+ * @brief sets the minimum size of the window
 1941+ * @param win a pointer to the target window
 1942+ * @param w the minimum width
 1943+ * @param h the minimum height
 1944+*/
 1945+RGFWDEF void RGFW_window_setMinSize(RGFW_window* win, i32 w, i32 h);
 1946+
 1947+/**!
 1948+ * @brief sets the maximum size of the window
 1949+ * @param win a pointer to the target window
 1950+ * @param w the maximum width
 1951+ * @param h the maximum height
 1952+*/
 1953+RGFWDEF void RGFW_window_setMaxSize(RGFW_window* win, i32 w, i32 h);
 1954+
 1955+/**!
 1956+ * @brief sets focus to the window
 1957+ * @param win a pointer to the target window
 1958+*/
 1959+RGFWDEF void RGFW_window_focus(RGFW_window* win);
 1960+
 1961+/**!
 1962+ * @brief checks if the window is currently in focus
 1963+ * @param win a pointer to the target window
 1964+ * @return RGFW_TRUE if the window is in focus, RGFW_FALSE otherwise
 1965+*/
 1966+RGFWDEF RGFW_bool RGFW_window_isInFocus(RGFW_window* win);
 1967+
 1968+/**!
 1969+ * @brief raises the window to the top of the stack
 1970+ * @param win a pointer to the target window
 1971+*/
 1972+RGFWDEF void RGFW_window_raise(RGFW_window* win);
 1973+
 1974+/**!
 1975+ * @brief maximizes the window
 1976+ * @param win a pointer to the target window
 1977+*/
 1978+RGFWDEF void RGFW_window_maximize(RGFW_window* win);
 1979+
 1980+/**!
 1981+ * @brief toggles fullscreen mode for the window
 1982+ * @param win a pointer to the target window
 1983+ * @param fullscreen RGFW_TRUE to enable fullscreen, RGFW_FALSE to disable
 1984+*/
 1985+RGFWDEF void RGFW_window_setFullscreen(RGFW_window* win, RGFW_bool fullscreen);
 1986+
 1987+/**!
 1988+ * @brief centers the window on the screen
 1989+ * @param win a pointer to the target window
 1990+*/
 1991+RGFWDEF void RGFW_window_center(RGFW_window* win);
 1992+
 1993+/**!
 1994+ * @brief minimizes the window
 1995+ * @param win a pointer to the target window
 1996+*/
 1997+RGFWDEF void RGFW_window_minimize(RGFW_window* win);
 1998+
 1999+/**!
 2000+ * @brief restores the window from minimized state
 2001+ * @param win a pointer to the target window
 2002+*/
 2003+RGFWDEF void RGFW_window_restore(RGFW_window* win);
 2004+
 2005+/**!
 2006+ * @brief makes the window a floating window
 2007+ * @param win a pointer to the target window
 2008+ * @param floating RGFW_TRUE to float, RGFW_FALSE to disable
 2009+*/
 2010+RGFWDEF void RGFW_window_setFloating(RGFW_window* win, RGFW_bool floating);
 2011+
 2012+/**!
 2013+ * @brief sets the opacity level of the window
 2014+ * @param win a pointer to the target window
 2015+ * @param opacity the opacity level (0–255)
 2016+*/
 2017+RGFWDEF void RGFW_window_setOpacity(RGFW_window* win, u8 opacity);
 2018+
 2019+/**!
 2020+ * @brief toggles window borders / frame / decor
 2021+ * @param win a pointer to the target window
 2022+ * @param border RGFW_TRUE for bordered, RGFW_FALSE for borderless
 2023+*/
 2024+RGFWDEF void RGFW_window_setBorder(RGFW_window* win, RGFW_bool border);
 2025+
 2026+/**!
 2027+ * @brief checks if the window is borderless (has a border, frame or decor)
 2028+ * @param win a pointer to the target window
 2029+ * @return RGFW_TRUE if borderless, RGFW_FALSE otherwise
 2030+*/
 2031+RGFWDEF RGFW_bool RGFW_window_borderless(RGFW_window* win);
 2032+
 2033+/**!
 2034+ * @brief toggles drag-and-drop (DND) support for the window
 2035+ * @param win a pointer to the target window
 2036+ * @param allow RGFW_TRUE to allow DND, RGFW_FALSE to disable
 2037+ * @note RGFW_windowAllowDND must still be passed when creating the window
 2038+*/
 2039+RGFWDEF void RGFW_window_setDND(RGFW_window* win, RGFW_bool allow);
 2040+
 2041+/**!
 2042+ * @brief checks if drag-and-drop (DND) is allowed
 2043+ * @param win a pointer to the target window
 2044+ * @return RGFW_TRUE if DND is enabled, RGFW_FALSE otherwise
 2045+*/
 2046+RGFWDEF RGFW_bool RGFW_window_allowsDND(RGFW_window* win);
 2047+
 2048+#ifndef RGFW_NO_PASSTHROUGH
 2049+/**!
 2050+ * @brief toggles mouse passthrough for the window
 2051+ * @param win a pointer to the target window
 2052+ * @param passthrough RGFW_TRUE to enable passthrough, RGFW_FALSE to disable
 2053+*/
 2054+RGFWDEF void RGFW_window_setMousePassthrough(RGFW_window* win, RGFW_bool passthrough);
 2055+#endif
 2056+
 2057+/**!
 2058+ * @brief renames the window
 2059+ * @param win a pointer to the target window
 2060+ * @param name the new title string for the window
 2061+*/
 2062+RGFWDEF void RGFW_window_setName(RGFW_window* win, const char* name);
 2063+
 2064+/**!
 2065+ * @brief sets the icon for the window and taskbar
 2066+ * @param win a pointer to the target window
 2067+ * @param data the image data
 2068+ * @param w the width of the icon
 2069+ * @param h the height of the icon
 2070+ * @param format the image format
 2071+ * @return RGFW_TRUE if successful, RGFW_FALSE otherwise
 2072+ *
 2073+ * NOTE: The image may be resized by default.
 2074+*/
 2075+RGFWDEF RGFW_bool RGFW_window_setIcon(RGFW_window* win, u8* data, i32 w, i32 h, RGFW_format format);
 2076+
 2077+/**!
 2078+ * @brief sets the icon for the window and/or taskbar
 2079+ * @param win a pointer to the target window
 2080+ * @param data the image data
 2081+ * @param w the width of the icon
 2082+ * @param h the height of the icon
 2083+ * @param format the image format
 2084+ * @param type the target icon type (taskbar, window, or both)
 2085+ * @return RGFW_TRUE if successful, RGFW_FALSE otherwise
 2086+*/
 2087+RGFWDEF RGFW_bool RGFW_window_setIconEx(RGFW_window* win, u8* data, i32 w, i32 h, RGFW_format format, RGFW_icon type);
 2088+
 2089+/**!
 2090+ * @brief sets the mouse icon for the window using a loaded mouse icon
 2091+ * @param win a pointer to the target window
 2092+ * @param mouse a pointer to the RGFW_mouse struct containing the icon
 2093+*/
 2094+RGFWDEF RGFW_bool RGFW_window_setMouse(RGFW_window* win, RGFW_mouse* mouse);
 2095+
 2096+/**!
 2097+ * @brief Sets the mouse to a preloaded [by RGFW] standard system cursor.
 2098+ * @param win The target window.
 2099+ * @param mouse The standardmouse icon (see RGFW_mouseIcon enum).
 2100+ * @return True if the standard cursor was successfully applied.
 2101+*/
 2102+RGFWDEF RGFW_bool RGFW_window_setMouseStandard(RGFW_window* win, RGFW_mouseIcon icon);
 2103+
 2104+/**!
 2105+ * @brief Sets the mouse to the default cursor icon.
 2106+ * @param win The target window.
 2107+ * @return True if the default cursor was successfully set.
 2108+*/
 2109+RGFWDEF RGFW_bool RGFW_window_setMouseDefault(RGFW_window* win);
 2110+
 2111+/**!
 2112+ * @brief set (enable or disable) raw mouse mode only for the select window
 2113+ * @param win The target window.
 2114+ * @param the boolean state of raw mouse mode
 2115+ *
 2116+*/
 2117+RGFWDEF void RGFW_window_setRawMouseMode(RGFW_window* win, RGFW_bool state);
 2118+
 2119+/**!
 2120+ * @brief lock/unlock the cursor.
 2121+ * @param win The target window.
 2122+ * @param the boolean state of the mouse's capture state
 2123+ *
 2124+*/
 2125+RGFWDEF void RGFW_window_captureMouse(RGFW_window* win, RGFW_bool state);
 2126+
 2127+/**!
 2128+ * @brief lock/unlock the cursor and enable raw mpuise mode.
 2129+ * @param win The target window.
 2130+ * @param the boolean state of raw mouse mode
 2131+ *
 2132+*/
 2133+RGFWDEF void RGFW_window_captureRawMouse(RGFW_window* win, RGFW_bool state);
 2134+
 2135+/**!
 2136+ * @brief Returns true if the mouse is using raw mouse mode
 2137+ * @param win The target window.
 2138+ * @return True if the mouse is using raw mouse input mode.
 2139+*/
 2140+RGFWDEF RGFW_bool RGFW_window_isRawMouseMode(RGFW_window* win);
 2141+
 2142+
 2143+/**!
 2144+ * @brief Returns true if the mouse is captured
 2145+ * @param win The target window.
 2146+ * @return True if the mouse is being captured.
 2147+*/
 2148+RGFWDEF RGFW_bool RGFW_window_isCaptured(RGFW_window* win);
 2149+
 2150+/**!
 2151+ * @brief Hides the window from view.
 2152+ * @param win The target window.
 2153+*/
 2154+RGFWDEF void RGFW_window_hide(RGFW_window* win);
 2155+
 2156+/**!
 2157+ * @brief Shows the window if it was hidden.
 2158+ * @param win The target window.
 2159+*/
 2160+RGFWDEF void RGFW_window_show(RGFW_window* win);
 2161+
 2162+/**!
 2163+ * @breif request a window flash to get attention from the user
 2164+ * @param win the target window
 2165+ * @param request the flash operation requested
 2166+*/
 2167+RGFWDEF void RGFW_window_flash(RGFW_window* win, RGFW_flashRequest request);
 2168+
 2169+/**!
 2170+ * @brief Sets whether the window should close.
 2171+ * @param win The target window.
 2172+ * @param shouldClose True to signal the window should close, false to keep it open.
 2173+ *
 2174+ * This can override or trigger the `RGFW_window_shouldClose` state by modifying window flags.
 2175+*/
 2176+RGFWDEF void RGFW_window_setShouldClose(RGFW_window* win, RGFW_bool shouldClose);
 2177+
 2178+/**!
 2179+ * @brief Retrieves the current global mouse position.
 2180+ * @param x [OUTPUT] Pointer to store the X position of the mouse on the screen.
 2181+ * @param y [OUTPUT] Pointer to store the Y position of the mouse on the screen.
 2182+ * @return True if the position was successfully retrieved.
 2183+*/
 2184+RGFWDEF RGFW_bool RGFW_getGlobalMouse(i32* x, i32* y);
 2185+
 2186+/**!
 2187+ * @brief Retrieves the mouse position relative to the window.
 2188+ * @param win The target window.
 2189+ * @param x [OUTPUT] Pointer to store the X position within the window.
 2190+ * @param y [OUTPUT] Pointer to store the Y position within the window.
 2191+ * @return True if the position was successfully retrieved.
 2192+*/
 2193+RGFWDEF RGFW_bool RGFW_window_getMouse(RGFW_window* win, i32* x, i32* y);
 2194+
 2195+/**!
 2196+ * @brief Shows or hides the mouse cursor for the window.
 2197+ * @param win The target window.
 2198+ * @param show True to show the mouse, false to hide it.
 2199+*/
 2200+RGFWDEF void RGFW_window_showMouse(RGFW_window* win, RGFW_bool show);
 2201+
 2202+/**!
 2203+ * @brief Checks if the mouse is currently hidden in the window.
 2204+ * @param win The target window.
 2205+ * @return True if the mouse is hidden.
 2206+*/
 2207+RGFWDEF RGFW_bool RGFW_window_isMouseHidden(RGFW_window* win);
 2208+
 2209+/**!
 2210+ * @brief Moves the mouse to the specified position within the window.
 2211+ * @param win The target window.
 2212+ * @param x The new X position.
 2213+ * @param y The new Y position.
 2214+*/
 2215+RGFWDEF void RGFW_window_moveMouse(RGFW_window* win, i32 x, i32 y);
 2216+
 2217+/**!
 2218+ * @brief Checks if the window should close.
 2219+ * @param win The target window.
 2220+ * @return True if the window should close (for example, if ESC was pressed or a close event occurred).
 2221+*/
 2222+RGFWDEF RGFW_bool RGFW_window_shouldClose(RGFW_window* win);
 2223+
 2224+/**!
 2225+ * @brief Checks if the window is currently fullscreen.
 2226+ * @param win The target window.
 2227+ * @return True if the window is fullscreen.
 2228+*/
 2229+RGFWDEF RGFW_bool RGFW_window_isFullscreen(RGFW_window* win);
 2230+
 2231+/**!
 2232+ * @brief Checks if the window is currently hidden.
 2233+ * @param win The target window.
 2234+ * @return True if the window is hidden.
 2235+*/
 2236+RGFWDEF RGFW_bool RGFW_window_isHidden(RGFW_window* win);
 2237+
 2238+/**!
 2239+ * @brief Checks if the window is minimized.
 2240+ * @param win The target window.
 2241+ * @return True if the window is minimized.
 2242+*/
 2243+RGFWDEF RGFW_bool RGFW_window_isMinimized(RGFW_window* win);
 2244+
 2245+/**!
 2246+ * @brief Checks if the window is maximized.
 2247+ * @param win The target window.
 2248+ * @return True if the window is maximized.
 2249+*/
 2250+RGFWDEF RGFW_bool RGFW_window_isMaximized(RGFW_window* win);
 2251+
 2252+/**!
 2253+ * @brief Checks if the window is floating.
 2254+ * @param win The target window.
 2255+ * @return True if the window is floating.
 2256+*/
 2257+RGFWDEF RGFW_bool RGFW_window_isFloating(RGFW_window* win);
 2258+/** @} */
 2259+
 2260+/** * @defgroup Monitor
 2261+* @{ */
 2262+
 2263+/**!
 2264+ * @brief Scales the window to match its monitor’s resolution.
 2265+ * @param win The target window.
 2266+ *
 2267+ * This function is automatically called when the flag `RGFW_scaleToMonitor`
 2268+ * is used during window creation.
 2269+*/
 2270+RGFWDEF void RGFW_window_scaleToMonitor(RGFW_window* win);
 2271+
 2272+/**!
 2273+ * @brief Retrieves the monitor structure associated with the window.
 2274+ * @param win The target window.
 2275+ * @return The monitor structure of the window.
 2276+*/
 2277+RGFWDEF RGFW_monitor* RGFW_window_getMonitor(RGFW_window* win);
 2278+
 2279+/** @} */
 2280+
 2281+/** * @defgroup Clipboard
 2282+* @{ */
 2283+
 2284+/**!
 2285+ * @brief Reads clipboard data.
 2286+ * @param size [OUTPUT] A pointer that will be filled with the size of the clipboard data.
 2287+ * @return A pointer to the clipboard data as a string.
 2288+*/
 2289+RGFWDEF const char* RGFW_readClipboard(size_t* size);
 2290+
 2291+/**!
 2292+ * @brief Reads clipboard data into a provided buffer, or returns the required length if str is NULL.
 2293+ * @param str [OUTPUT] A pointer to the buffer that will receive the clipboard data (or NULL to get required size).
 2294+ * @param strCapacity The capacity of the provided buffer.
 2295+ * @return The number of bytes read or required length of clipboard data.
 2296+*/
 2297+RGFWDEF RGFW_ssize_t RGFW_readClipboardPtr(char* str, size_t strCapacity);
 2298+
 2299+/**!
 2300+ * @brief Writes text to the clipboard.
 2301+ * @param text The text to be written to the clipboard.
 2302+ * @param textLen The length of the text being written.
 2303+*/
 2304+RGFWDEF void RGFW_writeClipboard(const char* text, u32 textLen);
 2305+/** @} */
 2306+
 2307+
 2308+
 2309+/** * @defgroup error handling
 2310+* @{ */
 2311+/**!
 2312+ * @brief Sets the callback function to handle debug messages from RGFW.
 2313+ * @param func The function pointer to be used as the debug callback.
 2314+ * @return The previously set debug callback function.
 2315+*/
 2316+RGFWDEF RGFW_debugFunc RGFW_setDebugCallback(RGFW_debugFunc func);
 2317+
 2318+/**!
 2319+ * @brief Sends a debug message manually through the currently set debug callback.
 2320+ * @param type The type of debug message being sent.
 2321+ * @param err The associated error code.
 2322+ * @param msg The debug message text.
 2323+*/
 2324+RGFWDEF void RGFW_debugCallback(RGFW_debugType type, RGFW_errorCode code, const char* msg);
 2325+/** @} */
 2326+
 2327+/** * @defgroup graphics_API
 2328+* @{ */
 2329+
 2330+/*! native rendering API functions */
 2331+#if defined(RGFW_OPENGL)
 2332+/* these are native opengl specific functions and will NOT work with EGL */
 2333+
 2334+/*!< make the window the current OpenGL drawing context
 2335+
 2336+	NOTE:
 2337+ 	if you want to switch the graphics context's thread,
 2338+	you have to run RGFW_window_makeCurrentContext_OpenGL(NULL); on the old thread
 2339+	then RGFW_window_makeCurrentContext_OpenGL(valid_window) on the new thread
 2340+*/
 2341+
 2342+/**!
 2343+ * @brief Sets the global OpenGL hints to the specified pointer.
 2344+ * @param hints A pointer to the RGFW_glHints structure containing the desired OpenGL settings.
 2345+*/
 2346+RGFWDEF void RGFW_setGlobalHints_OpenGL(RGFW_glHints* hints);
 2347+
 2348+/**!
 2349+ * @brief Resets the global OpenGL hints to their default values.
 2350+*/
 2351+RGFWDEF void RGFW_resetGlobalHints_OpenGL(void);
 2352+
 2353+/**!
 2354+ * @brief Gets the current global OpenGL hints pointer.
 2355+ * @return A pointer to the currently active RGFW_glHints structure.
 2356+*/
 2357+RGFWDEF RGFW_glHints* RGFW_getGlobalHints_OpenGL(void);
 2358+
 2359+/**!
 2360+ * @brief Creates and allocates an OpenGL context for the specified window.
 2361+ * @param win A pointer to the target RGFW_window.
 2362+ * @param hints A pointer to an RGFW_glHints structure defining context creation parameters.
 2363+ * @return A pointer to the newly created RGFW_glContext.
 2364+*/
 2365+RGFWDEF RGFW_glContext* RGFW_window_createContext_OpenGL(RGFW_window* win, RGFW_glHints* hints);
 2366+
 2367+/**!
 2368+ * @brief Creates an OpenGL context for the specified window using a preallocated context structure.
 2369+ * @param win A pointer to the target RGFW_window.
 2370+ * @param ctx A pointer to an already allocated RGFW_glContext structure.
 2371+ * @param hints A pointer to an RGFW_glHints structure defining context creation parameters.
 2372+ * @return RGFW_TRUE on success, RGFW_FALSE on failure.
 2373+*/
 2374+RGFWDEF RGFW_bool RGFW_window_createContextPtr_OpenGL(RGFW_window* win, RGFW_glContext* ctx, RGFW_glHints* hints);
 2375+
 2376+/**!
 2377+ * @brief Retrieves the OpenGL context associated with a window.
 2378+ * @param win A pointer to the RGFW_window.
 2379+ * @return A pointer to the associated RGFW_glContext, or NULL if none exists or if the context is EGL-based.
 2380+*/
 2381+RGFWDEF RGFW_glContext* RGFW_window_getContext_OpenGL(RGFW_window* win);
 2382+
 2383+/**!
 2384+ * @brief Deletes and frees the OpenGL context.
 2385+ * @param win A pointer to the RGFW_window.
 2386+ * @param ctx A pointer to the RGFW_glContext to delete.
 2387+ *
 2388+ * @note This is automatically called by RGFW_window_close if the window’s context is not NULL.
 2389+*/
 2390+RGFWDEF void RGFW_window_deleteContext_OpenGL(RGFW_window* win, RGFW_glContext* ctx);
 2391+
 2392+/**!
 2393+ * @brief Deletes the OpenGL context without freeing its memory.
 2394+ * @param win A pointer to the RGFW_window.
 2395+ * @param ctx A pointer to the RGFW_glContext to delete.
 2396+ *
 2397+ * @note This is automatically called by RGFW_window_close if the window’s context is not NULL.
 2398+*/
 2399+RGFWDEF void RGFW_window_deleteContextPtr_OpenGL(RGFW_window* win, RGFW_glContext* ctx);
 2400+
 2401+/**!
 2402+ * @brief Retrieves the native source context from an RGFW_glContext.
 2403+ * @param ctx A pointer to the RGFW_glContext.
 2404+ * @return A pointer to the native OpenGL context handle.
 2405+*/
 2406+RGFWDEF void* RGFW_glContext_getSourceContext(RGFW_glContext* ctx);
 2407+
 2408+/**!
 2409+ * @brief Makes the specified window the current OpenGL rendering target.
 2410+ * @param win A pointer to the RGFW_window to make current.
 2411+ *
 2412+ * @note This is typically called internally by RGFW_window_makeCurrent.
 2413+*/
 2414+RGFWDEF void RGFW_window_makeCurrentWindow_OpenGL(RGFW_window* win);
 2415+
 2416+/**!
 2417+ * @brief Makes the OpenGL context of the specified window current.
 2418+ * @param win A pointer to the RGFW_window whose context should be made current.
 2419+ *
 2420+ * @note To move a context between threads, call RGFW_window_makeCurrentContext_OpenGL(NULL)
 2421+ *       on the old thread before making it current on the new one.
 2422+*/
 2423+RGFWDEF void RGFW_window_makeCurrentContext_OpenGL(RGFW_window* win);
 2424+
 2425+/**!
 2426+ * @brief Swaps the OpenGL buffers for the specified window.
 2427+ * @param win A pointer to the RGFW_window whose buffers should be swapped.
 2428+*/
 2429+RGFWDEF void RGFW_window_swapBuffers_OpenGL(RGFW_window* win);
 2430+
 2431+/**!
 2432+ * @brief Retrieves the current OpenGL context.
 2433+ * @return A pointer to the currently active OpenGL context (GLX, WGL, Cocoa, or WebGL backend).
 2434+*/
 2435+RGFWDEF void* RGFW_getCurrentContext_OpenGL(void);
 2436+
 2437+/**!
 2438+ * @brief Retrieves the current OpenGL window.
 2439+ * @return A pointer to the RGFW_window currently bound as the OpenGL context target.
 2440+*/
 2441+RGFWDEF RGFW_window* RGFW_getCurrentWindow_OpenGL(void);
 2442+
 2443+/**!
 2444+ * @brief Sets the OpenGL swap interval (vsync).
 2445+ * @param win A pointer to the RGFW_window.
 2446+ * @param swapInterval The desired swap interval value (0 to disable vsync, 1 to enable).
 2447+*/
 2448+RGFWDEF void RGFW_window_swapInterval_OpenGL(RGFW_window* win, i32 swapInterval);
 2449+
 2450+/**!
 2451+ * @brief Retrieves the address of a native OpenGL procedure.
 2452+ * @param procname The name of the OpenGL function to look up.
 2453+ * @return A pointer to the function, or NULL if not found.
 2454+*/
 2455+RGFWDEF RGFW_proc RGFW_getProcAddress_OpenGL(const char* procname);
 2456+
 2457+/**!
 2458+ * @brief Checks whether a specific OpenGL or OpenGL ES API extension is supported.
 2459+ * @param extension The name of the extension to check.
 2460+ * @param len The length of the extension string.
 2461+ * @return RGFW_TRUE if supported, RGFW_FALSE otherwise.
 2462+*/
 2463+RGFWDEF RGFW_bool RGFW_extensionSupported_OpenGL(const char* extension, size_t len);
 2464+
 2465+/**!
 2466+ * @brief Checks whether a specific platform-dependent OpenGL extension is supported.
 2467+ * @param extension The name of the extension to check.
 2468+ * @param len The length of the extension string.
 2469+ * @return RGFW_TRUE if supported, RGFW_FALSE otherwise.
 2470+*/
 2471+RGFWDEF RGFW_bool RGFW_extensionSupportedPlatform_OpenGL(const char* extension, size_t len);
 2472+
 2473+/* these are EGL specific functions, they may fallback to OpenGL */
 2474+#ifdef RGFW_EGL
 2475+/**!
 2476+ * @brief Creates and allocates an OpenGL/EGL context for the specified window.
 2477+ * @param win A pointer to the target RGFW_window.
 2478+ * @param hints A pointer to an RGFW_glHints structure defining context creation parameters.
 2479+ * @return A pointer to the newly created RGFW_eglContext.
 2480+*/
 2481+RGFWDEF RGFW_eglContext* RGFW_window_createContext_EGL(RGFW_window* win, RGFW_glHints* hints);
 2482+
 2483+/**!
 2484+ * @brief Creates an OpenGL/EGL context for the specified window using a preallocated context structure.
 2485+ * @param win A pointer to the target RGFW_window.
 2486+ * @param ctx A pointer to an already allocated RGFW_eglContext structure.
 2487+ * @param hints A pointer to an RGFW_glHints structure defining context creation parameters.
 2488+ * @return RGFW_TRUE on success, RGFW_FALSE on failure.
 2489+*/
 2490+RGFWDEF RGFW_bool RGFW_window_createContextPtr_EGL(RGFW_window* win, RGFW_eglContext* ctx, RGFW_glHints* hints);
 2491+
 2492+/**!
 2493+ * @brief Frees and deletes an OpenGL/EGL context.
 2494+ * @param win A pointer to the RGFW_window.
 2495+ * @param ctx A pointer to the RGFW_eglContext to delete.
 2496+ *
 2497+ * @note Automatically called by RGFW_window_close if RGFW owns the context.
 2498+*/
 2499+RGFWDEF void RGFW_window_deleteContext_EGL(RGFW_window* win, RGFW_eglContext* ctx);
 2500+
 2501+/**!
 2502+ * @brief Deletes an OpenGL/EGL context without freeing its memory.
 2503+ * @param win A pointer to the RGFW_window.
 2504+ * @param ctx A pointer to the RGFW_eglContext to delete.
 2505+ *
 2506+ * @note Automatically called by RGFW_window_close if RGFW owns the context.
 2507+*/
 2508+RGFWDEF void RGFW_window_deleteContextPtr_EGL(RGFW_window* win, RGFW_eglContext* ctx);
 2509+
 2510+/**!
 2511+ * @brief Retrieves the OpenGL/EGL context associated with a window.
 2512+ * @param win A pointer to the RGFW_window.
 2513+ * @return A pointer to the associated RGFW_eglContext, or NULL if none exists or if the context is a native OpenGL context.
 2514+*/
 2515+RGFWDEF RGFW_eglContext* RGFW_window_getContext_EGL(RGFW_window* win);
 2516+
 2517+/**!
 2518+ * @brief Retrieves the EGL display handle.
 2519+ * @return A pointer to the native EGLDisplay.
 2520+*/
 2521+RGFWDEF void* RGFW_getDisplay_EGL(void);
 2522+
 2523+/**!
 2524+ * @brief Retrieves the native source context from an RGFW_eglContext.
 2525+ * @param ctx A pointer to the RGFW_eglContext.
 2526+ * @return A pointer to the native EGLContext handle.
 2527+*/
 2528+RGFWDEF void* RGFW_eglContext_getSourceContext(RGFW_eglContext* ctx);
 2529+
 2530+/**!
 2531+ * @brief Retrieves the EGL surface handle from an RGFW_eglContext.
 2532+ * @param ctx A pointer to the RGFW_eglContext.
 2533+ * @return A pointer to the EGLSurface associated with the context.
 2534+*/
 2535+RGFWDEF void* RGFW_eglContext_getSurface(RGFW_eglContext* ctx);
 2536+
 2537+/**!
 2538+ * @brief Retrieves the Wayland EGL window handle from an RGFW_eglContext.
 2539+ * @param ctx A pointer to the RGFW_eglContext.
 2540+ * @return A pointer to the wl_egl_window associated with the EGL context.
 2541+*/
 2542+RGFWDEF struct wl_egl_window* RGFW_eglContext_wlEGLWindow(RGFW_eglContext* ctx);
 2543+
 2544+/**!
 2545+ * @brief Swaps the EGL buffers for the specified window.
 2546+ * @param win A pointer to the RGFW_window whose buffers should be swapped.
 2547+ *
 2548+ * @note Typically called by RGFW_window_swapInterval.
 2549+*/
 2550+RGFWDEF void RGFW_window_swapBuffers_EGL(RGFW_window* win);
 2551+
 2552+/**!
 2553+ * @brief Makes the specified window the current EGL rendering target.
 2554+ * @param win A pointer to the RGFW_window to make current.
 2555+ *
 2556+ * @note This is typically called internally by RGFW_window_makeCurrent.
 2557+*/
 2558+RGFWDEF void RGFW_window_makeCurrentWindow_EGL(RGFW_window* win);
 2559+
 2560+/**!
 2561+ * @brief Makes the EGL context of the specified window current.
 2562+ * @param win A pointer to the RGFW_window whose context should be made current.
 2563+ *
 2564+ * @note To move a context between threads, call RGFW_window_makeCurrentContext_EGL(NULL)
 2565+ *       on the old thread before making it current on the new one.
 2566+*/
 2567+RGFWDEF void RGFW_window_makeCurrentContext_EGL(RGFW_window* win);
 2568+
 2569+/**!
 2570+ * @brief Retrieves the current EGL context.
 2571+ * @return A pointer to the currently active EGLContext.
 2572+*/
 2573+RGFWDEF void* RGFW_getCurrentContext_EGL(void);
 2574+
 2575+/**!
 2576+ * @brief Retrieves the current EGL window.
 2577+ * @return A pointer to the RGFW_window currently bound as the EGL context target.
 2578+*/
 2579+RGFWDEF RGFW_window* RGFW_getCurrentWindow_EGL(void);
 2580+
 2581+/**!
 2582+ * @brief Sets the EGL swap interval (vsync).
 2583+ * @param win A pointer to the RGFW_window.
 2584+ * @param swapInterval The desired swap interval value (0 to disable vsync, 1 to enable).
 2585+*/
 2586+RGFWDEF void RGFW_window_swapInterval_EGL(RGFW_window* win, i32 swapInterval);
 2587+
 2588+/**!
 2589+ * @brief Retrieves the address of a native OpenGL or OpenGL ES procedure in an EGL context.
 2590+ * @param procname The name of the OpenGL function to look up.
 2591+ * @return A pointer to the function, or NULL if not found.
 2592+*/
 2593+RGFWDEF RGFW_proc RGFW_getProcAddress_EGL(const char* procname);
 2594+
 2595+/**!
 2596+ * @brief Checks whether a specific OpenGL or OpenGL ES API extension is supported in the current EGL context.
 2597+ * @param extension The name of the extension to check.
 2598+ * @param len The length of the extension string.
 2599+ * @return RGFW_TRUE if supported, RGFW_FALSE otherwise.
 2600+*/
 2601+RGFWDEF RGFW_bool RGFW_extensionSupported_EGL(const char* extension, size_t len);
 2602+
 2603+/**!
 2604+ * @brief Checks whether a specific platform-dependent EGL extension is supported in the current context.
 2605+ * @param extension The name of the extension to check.
 2606+ * @param len The length of the extension string.
 2607+ * @return RGFW_TRUE if supported, RGFW_FALSE otherwise.
 2608+*/
 2609+RGFWDEF RGFW_bool RGFW_extensionSupportedPlatform_EGL(const char* extension, size_t len);
 2610+#endif
 2611+#endif
 2612+
 2613+#ifdef RGFW_VULKAN
 2614+#include <vulkan/vulkan.h>
 2615+
 2616+/* if you don't want to use the above macros */
 2617+
 2618+/**!
 2619+ * @brief Retrieves the Vulkan instance extensions required by RGFW.
 2620+ * @param count [OUTPUT] A pointer that will receive the number of required extensions (typically 2).
 2621+ * @return A pointer to a static array of required Vulkan instance extension names.
 2622+*/
 2623+RGFWDEF const char** RGFW_getRequiredInstanceExtensions_Vulkan(size_t* count);
 2624+
 2625+/**!
 2626+ * @brief Creates a Vulkan surface for the specified window.
 2627+ * @param win A pointer to the RGFW_window for which to create the Vulkan surface.
 2628+ * @param instance The Vulkan instance used to create the surface.
 2629+ * @param surface [OUTPUT] A pointer to a VkSurfaceKHR handle that will receive the created surface.
 2630+ * @return A VkResult indicating success or failure.
 2631+*/
 2632+RGFWDEF VkResult RGFW_window_createSurface_Vulkan(RGFW_window* win, VkInstance instance, VkSurfaceKHR* surface);
 2633+
 2634+/**!
 2635+ * @brief Checks whether the specified Vulkan physical device and queue family support presentation for RGFW.
 2636+ * @param instance The Vulkan instance.
 2637+ * @param physicalDevice The Vulkan physical device to check.
 2638+ * @param queueFamilyIndex The index of the queue family to query for presentation support.
 2639+ * @return RGFW_TRUE if presentation is supported, RGFW_FALSE otherwise.
 2640+*/
 2641+RGFWDEF RGFW_bool RGFW_getPresentationSupport_Vulkan(VkPhysicalDevice physicalDevice, u32 queueFamilyIndex);
 2642+#endif
 2643+
 2644+#ifdef RGFW_DIRECTX
 2645+#ifndef RGFW_WINDOWS
 2646+	#undef RGFW_DIRECTX
 2647+#else
 2648+	#define OEMRESOURCE
 2649+	#include <dxgi.h>
 2650+
 2651+	#ifndef __cplusplus
 2652+		#define __uuidof(T) IID_##T
 2653+	#endif
 2654+/**!
 2655+ * @brief Creates a DirectX swap chain for the specified RGFW window.
 2656+ * @param win A pointer to the RGFW_window for which to create the swap chain.
 2657+ * @param pFactory A pointer to the IDXGIFactory used to create the swap chain.
 2658+ * @param pDevice A pointer to the DirectX device (e.g., ID3D11Device or ID3D12Device).
 2659+ * @param swapchain [OUTPUT] A pointer to an IDXGISwapChain pointer that will receive the created swap chain.
 2660+ * @return An integer result code (0 on success, or a DirectX error code on failure).
 2661+*/
 2662+RGFWDEF int RGFW_window_createSwapChain_DirectX(RGFW_window* win, IDXGIFactory* pFactory, IUnknown* pDevice, IDXGISwapChain** swapchain);
 2663+#endif
 2664+#endif
 2665+
 2666+#ifdef RGFW_WEBGPU
 2667+	#include <webgpu/webgpu.h>
 2668+	/**!
 2669+	 * @brief Creates a WebGPU surface for the specified RGFW window.
 2670+	 * @param window A pointer to the RGFW_window for which to create the surface.
 2671+	 * @param instance The WebGPU instance used to create the surface.
 2672+	 * @return The created WGPUSurface handle.
 2673+	*/
 2674+	RGFWDEF WGPUSurface RGFW_window_createSurface_WebGPU(RGFW_window* window, WGPUInstance instance);
 2675+#endif
 2676+
 2677+/** @} */
 2678+
 2679+/** * @defgroup Supporting
 2680+* @{ */
 2681+
 2682+/**!
 2683+ * @brief Sets the root (main) RGFW window.
 2684+ * @param win A pointer to the RGFW_window to set as the root window.
 2685+*/
 2686+RGFWDEF void RGFW_setRootWindow(RGFW_window* win);
 2687+
 2688+/**!
 2689+ * @brief Retrieves the current root RGFW window.
 2690+ * @return A pointer to the current root RGFW_window.
 2691+*/
 2692+RGFWDEF RGFW_window* RGFW_getRootWindow(void);
 2693+
 2694+/**!
 2695+ * @brief Pushes an event into the standard RGFW event queue.
 2696+ * @param event A pointer to the RGFW_event to be added to the queue.
 2697+*/
 2698+RGFWDEF void RGFW_eventQueuePush(const RGFW_event* event);
 2699+
 2700+/**!
 2701+ * @brief Pushes an event into the standard RGFW event queue and call the callback.
 2702+ * @param event A pointer to the RGFW_event to be added to the queue.
 2703+*/
 2704+RGFWDEF void RGFW_eventQueuePushAndCall(const RGFW_event* event);
 2705+
 2706+/**!
 2707+ * @brief Clears all events from the RGFW event queue without processing them.
 2708+*/
 2709+RGFWDEF void RGFW_eventQueueFlush(void);
 2710+
 2711+/**!
 2712+ * @brief Pops the next event from the RGFW event queue.
 2713+ * @return A pointer to the popped RGFW_event, or NULL if the queue is empty.
 2714+*/
 2715+RGFWDEF RGFW_event* RGFW_eventQueuePop(void);
 2716+
 2717+/**!
 2718+ * @brief Pops the next event from the RGFW event queue that matches the target window, pushes back events that don't matchj.
 2719+ * @param win A pointer to the target RGFW_window.
 2720+ * @return A pointer to the popped RGFW_event, or NULL if the queue is empty.
 2721+*/
 2722+RGFWDEF RGFW_event* RGFW_window_eventQueuePop(RGFW_window* win);
 2723+
 2724+/**!
 2725+ * @brief Converts an API keycode to the RGFW unmapped (physical) key.
 2726+ * @param keycode The platform-specific keycode.
 2727+ * @return The corresponding RGFW keycode.
 2728+*/
 2729+RGFWDEF RGFW_key RGFW_apiKeyToRGFW(u32 keycode);
 2730+
 2731+/**!
 2732+ * @brief Converts an RGFW keycode to the unmapped (physical) API key.
 2733+ * @param keycode The RGFW keycode.
 2734+ * @return The corresponding platform-specific keycode.
 2735+*/
 2736+RGFWDEF u32 RGFW_rgfwToApiKey(RGFW_key keycode);
 2737+
 2738+/**!
 2739+ * @brief Converts an physical RGFW keycode to a mapped RGFW keycode.
 2740+ * @param keycode the physical RGFW keycode.
 2741+ * @return The corresponding mapped RGFW keycode.
 2742+*/
 2743+RGFWDEF RGFW_key RGFW_physicalToMappedKey(RGFW_key keycode);
 2744+
 2745+/**!
 2746+ * @brief Retrieves the size of the RGFW_info structure.
 2747+ * @return The size (in bytes) of RGFW_info.
 2748+*/
 2749+RGFWDEF size_t RGFW_sizeofInfo(void);
 2750+
 2751+/**!
 2752+ * @brief Initializes the RGFW library internally.
 2753+ * @return 0 on success, or a negative error code on failure.
 2754+ * @note This is automatically called when the first window is created.
 2755+*/
 2756+RGFWDEF i32 RGFW_init(void);
 2757+
 2758+/**!
 2759+ * @brief Deinitializes the current instance of the RGFW library.
 2760+ * @note This is automatically called when the last open window is closed.
 2761+*/
 2762+RGFWDEF void RGFW_deinit(void);
 2763+
 2764+/**!
 2765+ * @brief Initializes RGFW using a user-provided RGFW_info structure.
 2766+ * @param info A pointer to an RGFW_info structure to be used for initialization.
 2767+ * @return 0 on success, or a negative error code on failure.
 2768+*/
 2769+RGFWDEF i32 RGFW_init_ptr(RGFW_info* info);
 2770+
 2771+/**!
 2772+ * @brief Deinitializes a specific RGFW instance stored in the provided RGFW_info pointer.
 2773+ * @param info A pointer to the RGFW_info structure representing the instance to deinitialize.
 2774+*/
 2775+RGFWDEF void RGFW_deinit_ptr(RGFW_info* info);
 2776+
 2777+/**!
 2778+ * @brief Sets the global RGFW_info structure pointer.
 2779+ * @param info A pointer to the RGFW_info structure to set.
 2780+*/
 2781+RGFWDEF void RGFW_setInfo(RGFW_info* info);
 2782+
 2783+/**!
 2784+ * @brief Retrieves the global RGFW_info structure pointer.
 2785+ * @return A pointer to the current RGFW_info structure.
 2786+*/
 2787+RGFWDEF RGFW_info* RGFW_getInfo(void);
 2788+
 2789+/** @} */
 2790+#endif /* RGFW_HEADER */
 2791+
 2792+#if !defined(RGFW_NATIVE_HEADER) && (defined(RGFW_NATIVE) || defined(RGFW_IMPLEMENTATION))
 2793+#define RGFW_NATIVE_HEADER
 2794+	#if (defined(RGFW_OPENGL) || defined(RGFW_WEGL)) && defined(_MSC_VER)
 2795+		#pragma comment(lib, "opengl32")
 2796+	#endif
 2797+
 2798+	#ifdef RGFW_OPENGL
 2799+		struct RGFW_eglContext {
 2800+			void* ctx;
 2801+			void* surface;
 2802+			struct wl_egl_window* eglWindow;
 2803+		};
 2804+
 2805+		typedef union RGFW_gfxContext {
 2806+			RGFW_glContext* native;
 2807+			RGFW_eglContext* egl;
 2808+		} RGFW_gfxContext;
 2809+
 2810+		typedef RGFW_ENUM(u32, RGFW_gfxContextType) {
 2811+			RGFW_gfxNativeOpenGL = RGFW_BIT(0),
 2812+			RGFW_gfxEGL = RGFW_BIT(1),
 2813+			RGFW_gfxOwnedByRGFW = RGFW_BIT(2)
 2814+		};
 2815+	#endif
 2816+
 2817+	/*! source data for the window (used by the APIs) */
 2818+	#ifdef RGFW_WINDOWS
 2819+
 2820+	#ifndef WIN32_LEAN_AND_MEAN
 2821+		#define WIN32_LEAN_AND_MEAN
 2822+	#endif
 2823+	#ifndef OEMRESOURCE
 2824+		#define OEMRESOURCE
 2825+	#endif
 2826+
 2827+	#include <windows.h>
 2828+
 2829+	struct RGFW_nativeImage {
 2830+		HBITMAP bitmap;
 2831+		u8* bitmapBits;
 2832+		RGFW_format format;
 2833+		HDC hdcMem;
 2834+	};
 2835+
 2836+	#ifdef RGFW_OPENGL
 2837+		struct RGFW_glContext {    HGLRC ctx;	};
 2838+	#endif
 2839+
 2840+	struct RGFW_window_src {
 2841+		HWND window; /*!< source window */
 2842+		HDC hdc; /*!< source HDC */
 2843+		HICON hIconSmall, hIconBig; /*!< source window icons */
 2844+		i32 maxSizeW, maxSizeH, minSizeW, minSizeH, aspectRatioW, aspectRatioH; /*!< for setting max/min resize (RGFW_WINDOWS) */
 2845+		RGFW_bool actionFrame; /* frame after a caption button was toggled (e.g. minimize, maximize or close) */
 2846+		WCHAR highSurrogate;
 2847+		#ifdef RGFW_OPENGL
 2848+			RGFW_gfxContext ctx;
 2849+			RGFW_gfxContextType gfxType;
 2850+		#endif
 2851+	};
 2852+
 2853+#elif defined(RGFW_UNIX)
 2854+	#ifdef RGFW_X11
 2855+		#include <X11/Xlib.h>
 2856+		#include <X11/Xutil.h>
 2857+
 2858+		#include <X11/extensions/Xrandr.h>
 2859+		#include <X11/Xresource.h>
 2860+
 2861+		#ifndef RGFW_XDND_VERSION
 2862+			#define RGFW_XDND_VERSION 5
 2863+		#endif
 2864+	#endif
 2865+
 2866+	#ifdef RGFW_WAYLAND
 2867+		#ifdef RGFW_LIBDECOR
 2868+			#include <libdecor-0/libdecor.h>
 2869+		#endif
 2870+
 2871+		#include <wayland-client.h>
 2872+		#include <errno.h>
 2873+	#endif
 2874+
 2875+	struct RGFW_nativeImage {
 2876+		#ifdef RGFW_X11
 2877+			XImage* bitmap;
 2878+		#endif
 2879+		#ifdef RGFW_WAYLAND
 2880+			struct wl_buffer* wl_buffer;
 2881+			i32 fd;
 2882+			struct wl_shm_pool* pool;
 2883+		#endif
 2884+		u8* buffer;
 2885+		RGFW_format format;
 2886+	};
 2887+
 2888+	#ifdef RGFW_OPENGL
 2889+		struct RGFW_glContext {
 2890+			#ifdef RGFW_X11
 2891+				struct __GLXcontextRec* ctx; /*!< source graphics context */
 2892+				Window window;
 2893+			#endif
 2894+			#ifdef RGFW_WAYLAND
 2895+				RGFW_eglContext egl;
 2896+			#endif
 2897+		};
 2898+	#endif
 2899+
 2900+	struct RGFW_window_src {
 2901+		i32 x, y, w, h;
 2902+	#ifdef RGFW_OPENGL
 2903+		RGFW_gfxContext ctx;
 2904+		RGFW_gfxContextType gfxType;
 2905+	#endif
 2906+#ifdef RGFW_X11
 2907+		Window window; /*!< source window */
 2908+		Window parent; /*!< parent window */
 2909+		GC gc;
 2910+		XIC ic;
 2911+		u64 flashEnd;
 2912+		#ifdef RGFW_ADVANCED_SMOOTH_RESIZE
 2913+			i64 counter_value;
 2914+			XID counter;
 2915+		#endif
 2916+#endif /* RGFW_X11 */
 2917+
 2918+#if defined(RGFW_WAYLAND)
 2919+		struct wl_surface* surface;
 2920+		struct xdg_surface* xdg_surface;
 2921+		struct xdg_toplevel* xdg_toplevel;
 2922+		struct zxdg_toplevel_decoration_v1* decoration;
 2923+		struct zwp_locked_pointer_v1 *locked_pointer;
 2924+		struct xdg_toplevel_icon_v1 *icon;
 2925+		u32 decoration_mode;
 2926+		/* State flags to configure the window */
 2927+		RGFW_bool pending_activated;
 2928+		RGFW_bool activated;
 2929+		RGFW_bool resizing;
 2930+		RGFW_bool pending_maximized;
 2931+		RGFW_bool maximized;
 2932+		RGFW_bool minimized;
 2933+		RGFW_bool configured;
 2934+
 2935+		RGFW_bool using_custom_cursor;
 2936+		struct wl_surface* custom_cursor_surface;
 2937+
 2938+		RGFW_monitorNode* active_monitor;
 2939+
 2940+		struct wl_data_source *data_source; // offer data to other clients
 2941+
 2942+		#ifdef RGFW_LIBDECOR
 2943+			struct libdecor* decorContext;
 2944+		#endif
 2945+#endif /* RGFW_WAYLAND */
 2946+	};
 2947+
 2948+#elif defined(RGFW_MACOS)
 2949+	#include <CoreVideo/CoreVideo.h>
 2950+
 2951+	struct RGFW_nativeImage {
 2952+		RGFW_format format;
 2953+		u8* buffer;
 2954+		void* rep;
 2955+	};
 2956+
 2957+	#ifdef RGFW_OPENGL
 2958+		struct RGFW_glContext {
 2959+			void* ctx;
 2960+			void* format;
 2961+		};
 2962+	#endif
 2963+
 2964+	struct RGFW_window_src {
 2965+		void* window;
 2966+		void* view; /* apple viewpoint thingy */
 2967+		void* mouse;
 2968+		void* delegate;
 2969+		#ifdef RGFW_OPENGL
 2970+			RGFW_gfxContext ctx;
 2971+			RGFW_gfxContextType gfxType;
 2972+		#endif
 2973+	};
 2974+
 2975+#elif defined(RGFW_WASM)
 2976+
 2977+	#include <emscripten/html5.h>
 2978+	#include <emscripten/key_codes.h>
 2979+
 2980+	struct RGFW_nativeImage  {
 2981+		RGFW_format format;
 2982+	};
 2983+
 2984+	#ifdef RGFW_OPENGL
 2985+		struct RGFW_glContext {
 2986+			EMSCRIPTEN_WEBGL_CONTEXT_HANDLE ctx;
 2987+		};
 2988+	#endif
 2989+
 2990+	struct RGFW_window_src {
 2991+		#ifdef RGFW_OPENGL
 2992+			RGFW_gfxContext ctx;
 2993+			RGFW_gfxContextType gfxType;
 2994+		#endif
 2995+	};
 2996+
 2997+#endif
 2998+
 2999+struct RGFW_surface {
 3000+	u8* data;
 3001+	i32 w, h;
 3002+	RGFW_format format;
 3003+	RGFW_convertImageDataFunc convertFunc;
 3004+	RGFW_nativeImage native;
 3005+};
 3006+
 3007+/*! internal window data that is not specific to the OS */
 3008+typedef struct RGFW_windowInternal {
 3009+	/*! which key RGFW_window_shouldClose checks. Settting this to RGFW_keyNULL disables the feature. */
 3010+	RGFW_key exitKey;
 3011+	i32 lastMouseX, lastMouseY; /*!< last cusor point (for raw mouse data) */
 3012+
 3013+	RGFW_bool shouldClose;
 3014+	RGFW_bool rawMouse;
 3015+	RGFW_bool captureMouse;
 3016+	RGFW_bool inFocus;
 3017+	RGFW_bool mouseInside;
 3018+	RGFW_keymod mod;
 3019+	RGFW_eventFlag enabledEvents;
 3020+	u32 flags; /*!< windows flags (for RGFW to check and modify) */
 3021+	i32 oldX, oldY, oldW, oldH;
 3022+	RGFW_monitorMode oldMode;
 3023+	RGFW_mouse* mouse;
 3024+} RGFW_windowInternal;
 3025+
 3026+struct RGFW_window {
 3027+	RGFW_window_src src; /*!< src window data */
 3028+	RGFW_windowInternal internal; /*!< internal window data that is not specific to the OS */
 3029+	void* userPtr; /* ptr for user data */
 3030+	i32 x, y, w, h; /*!< position and size of the window */
 3031+}; /*!< window structure for the window */
 3032+
 3033+typedef struct RGFW_windowState {
 3034+	RGFW_bool mouseEnter;
 3035+	RGFW_bool dataDragging;
 3036+	RGFW_bool dataDrop;
 3037+	size_t dataSize;
 3038+	i32 dropX, dropY;
 3039+	RGFW_window* win; /*!< it's not possible for one of these events to happen in the frame that the other event happened */
 3040+
 3041+	RGFW_bool mouseLeave;
 3042+	RGFW_window* winLeave; /*!< if a mouse leaves one window and enters the next */
 3043+} RGFW_windowState;
 3044+
 3045+typedef struct {
 3046+	RGFW_bool current;
 3047+	RGFW_bool prev;
 3048+} RGFW_keyState;
 3049+
 3050+struct RGFW_monitorNode {
 3051+	RGFW_monitor mon;
 3052+	RGFW_bool disconnected;
 3053+	RGFW_monitorNode* next;
 3054+#ifdef RGFW_WAYLAND
 3055+	u32 id; /* Add id so wl_outputs can be removed */
 3056+	struct wl_output *output;
 3057+	struct zxdg_output_v1 *xdg_output;
 3058+	RGFW_monitorMode* modes;
 3059+	size_t modeCount;
 3060+#endif
 3061+#if defined(RGFW_X11)
 3062+	i32 screen;
 3063+	RROutput rrOutput;
 3064+	RRCrtc crtc;
 3065+#endif
 3066+#ifdef RGFW_WINDOWS
 3067+	HMONITOR hMonitor;
 3068+	WCHAR adapterName[32];
 3069+	WCHAR deviceName[32];
 3070+#endif
 3071+#ifdef RGFW_MACOS
 3072+	void* screen;
 3073+	CGDirectDisplayID display;
 3074+	u32 uintNum;
 3075+#endif
 3076+};
 3077+
 3078+typedef struct RGFW_monitorList {
 3079+	RGFW_monitorNode* head;
 3080+	RGFW_monitorNode* cur;
 3081+} RGFW_monitorList;
 3082+
 3083+typedef struct RGFW_monitors {
 3084+	RGFW_monitorList list;
 3085+	size_t count;
 3086+
 3087+	RGFW_monitorNode* primary;
 3088+	#if (RGFW_PREALLOCATED_MONITORS)
 3089+		RGFW_monitorList freeList;
 3090+		RGFW_monitorNode data[RGFW_PREALLOCATED_MONITORS];
 3091+	#endif
 3092+} RGFW_monitors;
 3093+
 3094+RGFWDEF RGFW_monitorNode* RGFW_monitors_add(const RGFW_monitor* mon);
 3095+RGFWDEF void RGFW_monitors_remove(RGFW_monitorNode* node, RGFW_monitorNode* prev);
 3096+
 3097+struct RGFW_info {
 3098+    RGFW_window* root;
 3099+    i32 windowCount;
 3100+
 3101+	RGFW_mouse* hiddenMouse;
 3102+	RGFW_mouse* standardMice[RGFW_mouseIconCount];
 3103+
 3104+	RGFW_debugFunc debugCallbackSrc;
 3105+	RGFW_genericFunc callbacks[RGFW_eventCount];
 3106+    RGFW_event events[RGFW_MAX_EVENTS]; /* A circular buffer (FIFO), using eventBottom/Len  */
 3107+
 3108+	i32 eventBottom;
 3109+    i32 eventLen;
 3110+	RGFW_bool queueEvents;
 3111+	RGFW_bool polledEvents;
 3112+
 3113+    u32 apiKeycodes[RGFW_keyLast];
 3114+	#if defined(RGFW_X11) || defined(RGFW_WAYLAND)
 3115+		RGFW_key keycodes[256];
 3116+	#elif defined(RGFW_WINDOWS)
 3117+		RGFW_key keycodes[512];
 3118+	#elif defined(RGFW_MACOS)
 3119+		RGFW_key keycodes[128];
 3120+	#elif defined(RGFW_WASM)
 3121+		RGFW_key keycodes[256];
 3122+	#endif
 3123+
 3124+    const char* className;
 3125+    RGFW_bool useWaylandBool;
 3126+    RGFW_bool stopCheckEvents_bool ;
 3127+    u64 timerOffset;
 3128+
 3129+    char* clipboard_data;
 3130+    char* clipboard; /* for writing to the clipboard selection */
 3131+    size_t clipboard_len;
 3132+
 3133+	RGFW_bool dndBuild;
 3134+	RGFW_dataDropNode* dndRoot;
 3135+	RGFW_dataDropNode* dndCur;
 3136+
 3137+	#ifdef RGFW_X11
 3138+        Display* display;
 3139+		XContext context;
 3140+        Window helperWindow;
 3141+        const char* instName;
 3142+        XErrorEvent* x11Error;
 3143+		i32 xrandrEventBase;
 3144+		XIM im;
 3145+		Window x11Source;
 3146+		long x11Version;
 3147+		i32 x11Format;
 3148+		RGFW_dataTransferType x11TransferType;
 3149+    #endif
 3150+    #ifdef RGFW_WAYLAND
 3151+        struct wl_display* wl_display;
 3152+        struct xkb_context *xkb_context;
 3153+        struct xkb_keymap *keymap;
 3154+        struct xkb_state *xkb_state;
 3155+        struct zxdg_decoration_manager_v1 *decoration_manager;
 3156+        struct zwp_relative_pointer_manager_v1 *relative_pointer_manager;
 3157+        struct zwp_relative_pointer_v1 *relative_pointer;
 3158+        struct zwp_pointer_constraints_v1 *constraint_manager;
 3159+        struct xdg_toplevel_icon_manager_v1 *icon_manager;
 3160+
 3161+        struct zxdg_output_manager_v1 *xdg_output_manager;
 3162+
 3163+        struct wl_data_device_manager *data_device_manager;
 3164+        struct wl_data_device *data_device; // supports clipboard and DND
 3165+		struct wp_pointer_warp_v1* wp_pointer_warp;
 3166+
 3167+        struct wl_keyboard* wl_keyboard;
 3168+        struct wl_pointer* wl_pointer;
 3169+        struct wl_compositor* compositor;
 3170+        struct xdg_wm_base* xdg_wm_base;
 3171+        struct wl_shm* shm;
 3172+        struct wl_seat *seat;
 3173+        struct wl_registry *registry;
 3174+        u32 mouse_enter_serial;
 3175+        struct wl_cursor_theme* wl_cursor_theme;
 3176+        struct wl_surface* cursor_surface;
 3177+		struct xkb_compose_state* composeState;
 3178+
 3179+        RGFW_window* kbOwner;
 3180+		RGFW_window* mouseOwner; /* what window has access to the mouse */
 3181+
 3182+		u32 last_key;  /* wayland key repeat data */
 3183+		i32 wl_repeat_info_rate, wl_repeat_info_delay;
 3184+		u32 last_key_time;
 3185+    #endif
 3186+
 3187+    RGFW_monitors monitors;
 3188+
 3189+    #ifdef RGFW_UNIX
 3190+	    int eventWait_forceStop[3];
 3191+		i32 clock;
 3192+    #endif
 3193+
 3194+    #ifdef RGFW_MACOS
 3195+    void* NSApp;
 3196+	i64 flash;
 3197+	void* customViewClasses[2]; /* NSView and NSOpenGLView  */
 3198+	void* customNSAppDelegateClass;
 3199+	void* customWindowDelegateClass;
 3200+	void* customNSAppDelegate;
 3201+	void* tisBundle;
 3202+    #endif
 3203+
 3204+	#ifdef RGFW_OPENGL
 3205+		RGFW_window* current;
 3206+	#endif
 3207+	#ifdef RGFW_EGL
 3208+		void* EGL_display;
 3209+	#endif
 3210+
 3211+	RGFW_bool rawMouse; /* global raw mouse toggle */
 3212+
 3213+	RGFW_windowState windowState; /*! for checking window state events */
 3214+
 3215+	RGFW_keyState mouseButtons[RGFW_mouseFinal];
 3216+	RGFW_keyState keyboard[RGFW_keyLast];
 3217+	float scrollX, scrollY;
 3218+	float vectorX, vectorY;
 3219+};
 3220+#endif /* RGFW_NATIVE_HEADER */
 3221+
 3222+#ifdef RGFW_IMPLEMENTATION
 3223+
 3224+#ifndef RGFW_NO_MATH
 3225+#include <math.h>
 3226+#endif
 3227+
 3228+/* global private API */
 3229+
 3230+/* for C++ / C89 */
 3231+RGFWDEF RGFW_window* RGFW_createWindowPlatform(const char* name, RGFW_windowFlags flags, RGFW_window* win);
 3232+RGFWDEF void RGFW_window_closePlatform(RGFW_window* win);
 3233+RGFWDEF RGFW_bool RGFW_window_setMousePlatform(RGFW_window* win, RGFW_mouse* mouse);
 3234+
 3235+RGFWDEF void RGFW_window_setFlagsInternal(RGFW_window* win, RGFW_windowFlags flags, RGFW_windowFlags cmpFlags);
 3236+
 3237+RGFWDEF void RGFW_initKeycodes(void);
 3238+RGFWDEF void RGFW_initKeycodesPlatform(void);
 3239+RGFWDEF void RGFW_resetPrevState(void);
 3240+RGFWDEF void RGFW_resetKey(void);
 3241+RGFWDEF void RGFW_unloadEGL(void);
 3242+RGFWDEF void RGFW_keyUpdateKeyModsEx(RGFW_window* win, RGFW_bool capital, RGFW_bool numlock, RGFW_bool control, RGFW_bool alt, RGFW_bool shift, RGFW_bool super, RGFW_bool scroll);
 3243+RGFWDEF void RGFW_keyUpdateKeyMods(RGFW_window* win, RGFW_bool capital, RGFW_bool numlock, RGFW_bool scroll);
 3244+RGFWDEF void RGFW_window_showMouseFlags(RGFW_window* win, RGFW_bool show);
 3245+RGFWDEF void RGFW_keyUpdateKeyMod(RGFW_window* win, RGFW_keymod mod, RGFW_bool value);
 3246+RGFWDEF void RGFW_monitors_refresh(void);
 3247+
 3248+RGFWDEF void RGFW_windowMaximizedCallback(RGFW_window* win, i32 x, i32 y, i32 w, i32 h);
 3249+RGFWDEF void RGFW_windowMinimizedCallback(RGFW_window* win);
 3250+RGFWDEF void RGFW_windowRestoredCallback(RGFW_window* win, i32 x, i32 y, i32 w, i32 h);
 3251+RGFWDEF void RGFW_windowMovedCallback(RGFW_window* win, i32 x, i32 y);
 3252+RGFWDEF void RGFW_windowResizedCallback(RGFW_window* win, i32 w, i32 h);
 3253+RGFWDEF void RGFW_windowCloseCallback(RGFW_window* win);
 3254+RGFWDEF void RGFW_mousePosCallback(RGFW_window* win, i32 x, i32 y);
 3255+RGFWDEF void RGFW_rawMotionCallback(RGFW_window* win, float x, float y);
 3256+RGFWDEF void RGFW_windowRefreshCallback(RGFW_window* win, i32 x, i32 y, i32 w, i32 h);
 3257+RGFWDEF void RGFW_windowFocusCallback(RGFW_window* win, RGFW_bool inFocus);
 3258+RGFWDEF void RGFW_mouseNotifyCallback(RGFW_window* win, i32 x, i32 y, RGFW_bool status);
 3259+RGFWDEF void RGFW_dataDropCallback(RGFW_window* win, const char* data, size_t count, RGFW_dataTransferType dataType);
 3260+RGFWDEF void RGFW_dataDragCallback(RGFW_window* win, RGFW_dataTransferType dataType, RGFW_dndActionType action, i32 x, i32 y);
 3261+RGFWDEF void RGFW_keyCharCallback(RGFW_window* win, u32 codepoint);
 3262+RGFWDEF void RGFW_keyCallback(RGFW_window* win, RGFW_key key, RGFW_keymod mod, RGFW_bool repeat, RGFW_bool press);
 3263+RGFWDEF void RGFW_mouseButtonCallback(RGFW_window* win, RGFW_mouseButton button, RGFW_bool press);
 3264+RGFWDEF void RGFW_mouseScrollCallback(RGFW_window* win, float x, float y);
 3265+RGFWDEF void RGFW_scaleUpdatedCallback(RGFW_window* win, float scaleX, float scaleY);
 3266+RGFWDEF void RGFW_monitorCallback(RGFW_window* win, const RGFW_monitor* monitor, RGFW_bool connected);
 3267+
 3268+RGFWDEF void RGFW_setBit(u32* var, u32 mask, RGFW_bool set);
 3269+RGFWDEF void RGFW_splitBPP(u32 bpp, RGFW_monitorMode* mode);
 3270+
 3271+RGFWDEF void RGFW_window_captureMousePlatform(RGFW_window* win, RGFW_bool state);
 3272+RGFWDEF void RGFW_window_setRawMouseModePlatform(RGFW_window *win, RGFW_bool state);
 3273+
 3274+RGFWDEF void RGFW_copyImageData64(u8* dest_data, i32 w, i32 h, RGFW_format dest_format,
 3275+							u8* src_data, RGFW_format src_format, RGFW_bool is64bit, RGFW_convertImageDataFunc func);
 3276+
 3277+RGFWDEF RGFW_bool RGFW_loadEGL(void);
 3278+
 3279+#ifdef RGFW_OPENGL
 3280+typedef struct RGFW_attribStack {
 3281+	i32* attribs;
 3282+	size_t count;
 3283+	size_t max;
 3284+} RGFW_attribStack;
 3285+RGFWDEF void RGFW_attribStack_init(RGFW_attribStack* stack, i32* attribs, size_t max);
 3286+RGFWDEF void RGFW_attribStack_pushAttrib(RGFW_attribStack* stack, i32 attrib);
 3287+RGFWDEF void RGFW_attribStack_pushAttribs(RGFW_attribStack* stack, i32 attrib1, i32 attrib2);
 3288+
 3289+RGFWDEF RGFW_bool RGFW_extensionSupportedStr(const char* extensions, const char* ext, size_t len);
 3290+#endif
 3291+
 3292+#ifdef RGFW_X11
 3293+RGFWDEF void RGFW_XCreateWindow (XVisualInfo visual, const char* name, RGFW_windowFlags flags, RGFW_window* win);
 3294+#endif
 3295+#ifdef RGFW_MACOS
 3296+RGFWDEF void RGFW_osx_initView(RGFW_window* win);
 3297+#endif
 3298+/* end of global private API defs */
 3299+
 3300+RGFW_info* _RGFW = NULL;
 3301+void RGFW_setInfo(RGFW_info* info) { _RGFW = info; }
 3302+RGFW_info* RGFW_getInfo(void) { return _RGFW; }
 3303+
 3304+
 3305+void* RGFW_alloc(size_t size) { return RGFW_ALLOC(size); }
 3306+void RGFW_free(void* ptr) { RGFW_FREE(ptr); }
 3307+
 3308+void RGFW_useWayland(RGFW_bool wayland) { RGFW_init(); _RGFW->useWaylandBool = RGFW_BOOL(wayland);  }
 3309+RGFW_bool RGFW_usingWayland(void) { return _RGFW->useWaylandBool; }
 3310+
 3311+void RGFW_setRawMouseMode(RGFW_bool state) {
 3312+	_RGFW->rawMouse = state;
 3313+	RGFW_window_setRawMouseModePlatform(_RGFW->root, state);
 3314+}
 3315+
 3316+void RGFW_clipboard_switch(char* newstr);
 3317+void RGFW_clipboard_switch(char* newstr) {
 3318+	if (_RGFW->clipboard_data != NULL)
 3319+		RGFW_FREE(_RGFW->clipboard_data);
 3320+	_RGFW->clipboard_data =  newstr;
 3321+}
 3322+
 3323+#define RGFW_CHECK_CLIPBOARD() \
 3324+	if (size <= 0 && _RGFW->clipboard_data != NULL) \
 3325+		return (const char*)_RGFW->clipboard_data; \
 3326+	else if (size <= 0) \
 3327+		return "\0";
 3328+
 3329+const char* RGFW_readClipboard(size_t* len) {
 3330+	RGFW_ssize_t size = RGFW_readClipboardPtr(NULL, 0);
 3331+    RGFW_CHECK_CLIPBOARD();
 3332+    char* str = (char*)RGFW_ALLOC((size_t)size);
 3333+    RGFW_ASSERT(str != NULL);
 3334+    str[0] = '\0';
 3335+
 3336+    size = RGFW_readClipboardPtr(str, (size_t)size);
 3337+
 3338+    RGFW_CHECK_CLIPBOARD();
 3339+
 3340+	if (len != NULL) *len = (size_t)size;
 3341+
 3342+	RGFW_clipboard_switch(str);
 3343+	return (const char*)str;
 3344+}
 3345+
 3346+/* generic RGFW defines */
 3347+
 3348+void RGFW_initKeycodes(void) {
 3349+	RGFW_MEMZERO(_RGFW->keycodes, sizeof(_RGFW->keycodes));
 3350+	RGFW_initKeycodesPlatform();
 3351+	size_t i, y;
 3352+    for (i = 0; i < RGFW_keyLast; i++) {
 3353+        for (y = 0; y < (sizeof(_RGFW->keycodes) / sizeof(RGFW_key)); y++) {
 3354+            if (_RGFW->keycodes[y] == i) {
 3355+                _RGFW->apiKeycodes[i] = (RGFW_key)y;
 3356+                break;
 3357+            }
 3358+        }
 3359+    }
 3360+
 3361+
 3362+    RGFW_resetKey();
 3363+}
 3364+
 3365+RGFW_key RGFW_apiKeyToRGFW(u32 keycode) {
 3366+    /* make sure the key isn't out of bounds */
 3367+	if (keycode > (sizeof(_RGFW->keycodes) / sizeof(RGFW_key)))
 3368+		return 0;
 3369+
 3370+	return _RGFW->keycodes[keycode];
 3371+}
 3372+
 3373+u32 RGFW_rgfwToApiKey(RGFW_key keycode) {
 3374+	/* make sure the key isn't out of bounds */
 3375+	return _RGFW->apiKeycodes[keycode];
 3376+}
 3377+
 3378+void RGFW_resetKey(void) { RGFW_MEMZERO(_RGFW->keyboard, sizeof(_RGFW->keyboard)); }
 3379+/*
 3380+	this is the end of keycode data
 3381+*/
 3382+
 3383+RGFW_genericFunc RGFW_setEventCallback(RGFW_eventType type, RGFW_genericFunc func) {
 3384+	RGFW_ASSERT(type > RGFW_eventNone && type < RGFW_eventCount);
 3385+	RGFW_init();
 3386+
 3387+	RGFW_genericFunc old = _RGFW->callbacks[type];
 3388+	_RGFW->callbacks[type] = func;
 3389+
 3390+	return old;
 3391+}
 3392+
 3393+void RGFW_setDualEventCallback(RGFW_eventType type, RGFW_genericFunc func, RGFW_genericFunc* first, RGFW_genericFunc* second) {
 3394+	RGFW_genericFunc func1 = RGFW_setEventCallback(type, func);
 3395+	RGFW_genericFunc func2 = RGFW_setEventCallback(type + 1, func);
 3396+
 3397+	if (first) *first = func1;
 3398+	if (second) *second = func2;
 3399+}
 3400+
 3401+void RGFW_setAllEventCallbacks(RGFW_genericFunc func, RGFW_callbacks* callbacks) {
 3402+	for (RGFW_eventType i = RGFW_eventNone + 1; i < RGFW_eventCount; i++) {
 3403+		if (callbacks) callbacks->arr[i] = _RGFW->callbacks[i];
 3404+		RGFW_setEventCallback(i, func);
 3405+	}
 3406+}
 3407+
 3408+RGFW_debugFunc RGFW_setDebugCallback(RGFW_debugFunc func) {
 3409+	RGFW_init();
 3410+	RGFW_debugFunc prev = _RGFW->debugCallbackSrc;
 3411+	_RGFW->debugCallbackSrc = func;
 3412+	return prev;
 3413+}
 3414+
 3415+void RGFW_eventQueuePushAndCall(const RGFW_event* event) {
 3416+	RGFW_ASSERT(event->type > RGFW_eventNone && event->type < RGFW_eventCount);
 3417+	if (_RGFW->callbacks[event->type]) (_RGFW->callbacks[event->type])(event);
 3418+	RGFW_eventQueuePush(event);
 3419+}
 3420+
 3421+void RGFW_windowMaximizedCallback(RGFW_window* win, i32 x, i32 y, i32 w, i32 h) {
 3422+	win->internal.flags |= RGFW_windowMaximize;
 3423+	win->x = x;
 3424+	win->y = y;
 3425+	win->w = w;
 3426+	win->h = h;
 3427+
 3428+	if (!(win->internal.enabledEvents & RGFW_windowMaximizedFlag)) return;
 3429+
 3430+	RGFW_event event;
 3431+	event.type = RGFW_windowMaximized;
 3432+	event.update.x = x;
 3433+	event.update.y = y;
 3434+	event.update.w = w;
 3435+	event.update.h = h;
 3436+	event.common.win = win;
 3437+	RGFW_eventQueuePushAndCall(&event);
 3438+}
 3439+
 3440+void RGFW_windowMinimizedCallback(RGFW_window* win) {
 3441+	win->internal.flags |= RGFW_windowMinimize;
 3442+
 3443+	if (!(win->internal.enabledEvents & RGFW_windowMinimizedFlag)) return;
 3444+
 3445+	RGFW_event event;
 3446+	event.type = RGFW_windowMinimized;
 3447+	event.update.x = win->x;
 3448+	event.update.y = win->y;
 3449+	event.update.w = win->w;
 3450+	event.update.h = win->h;
 3451+	event.common.win = win;
 3452+	RGFW_eventQueuePushAndCall(&event);
 3453+}
 3454+
 3455+void RGFW_windowRestoredCallback(RGFW_window* win, i32 x, i32 y, i32 w, i32 h) {
 3456+	win->internal.flags &= ~(u32)RGFW_windowMinimize;
 3457+	win->x = x;
 3458+	win->y = y;
 3459+	win->w = w;
 3460+	win->h = h;
 3461+
 3462+	if (RGFW_window_isMaximized(win) == RGFW_FALSE) win->internal.flags &= ~(u32)RGFW_windowMaximize;
 3463+
 3464+	if (!(win->internal.enabledEvents & RGFW_windowRestoredFlag)) return;
 3465+
 3466+	RGFW_event event;
 3467+	event.type = RGFW_windowRestored;
 3468+	event.update.x = x;
 3469+	event.update.y = y;
 3470+	event.update.w = w;
 3471+	event.update.h = h;
 3472+	event.common.win = win;
 3473+	RGFW_eventQueuePushAndCall(&event);
 3474+}
 3475+
 3476+void RGFW_windowMovedCallback(RGFW_window* win, i32 x, i32 y) {
 3477+	win->x = x;
 3478+	win->y = y;
 3479+	if (!(win->internal.enabledEvents & RGFW_windowMovedFlag)) return;
 3480+
 3481+	RGFW_event event;
 3482+	event.type = RGFW_windowMoved;
 3483+	event.update.x = x;
 3484+	event.update.x = y;
 3485+	event.update.w = win->w;
 3486+	event.update.h = win->h;
 3487+	event.common.win = win;
 3488+	RGFW_eventQueuePushAndCall(&event);
 3489+}
 3490+
 3491+void RGFW_windowResizedCallback(RGFW_window* win, i32 w, i32 h) {
 3492+	win->w = w;
 3493+	win->h = h;
 3494+
 3495+	if (!(win->internal.enabledEvents & RGFW_windowResizedFlag)) return;
 3496+	RGFW_event event;
 3497+	event.type = RGFW_windowResized;
 3498+	event.update.x = win->x;
 3499+	event.update.y = win->y;
 3500+	event.update.w = w;
 3501+	event.update.h = h;
 3502+	event.common.win = win;
 3503+	RGFW_eventQueuePushAndCall(&event);
 3504+}
 3505+
 3506+void RGFW_windowCloseCallback(RGFW_window* win) {
 3507+	win->internal.shouldClose = RGFW_TRUE;
 3508+
 3509+	RGFW_event event;
 3510+	event.type = RGFW_windowClose;
 3511+	event.common.win = win;
 3512+	RGFW_eventQueuePushAndCall(&event);
 3513+}
 3514+
 3515+void RGFW_mousePosCallback(RGFW_window* win, i32 x, i32 y) {
 3516+	win->internal.lastMouseX = x;
 3517+	win->internal.lastMouseY = y;
 3518+
 3519+	if (!(win->internal.enabledEvents & RGFW_mousePosChangedFlag)) return;
 3520+
 3521+	RGFW_event event;
 3522+	event.type = RGFW_mousePosChanged;
 3523+	event.mouse.x = x;
 3524+	event.mouse.y = y;
 3525+	event.mouse.inWindow = win->internal.mouseInside;
 3526+	event.common.win = win;
 3527+	RGFW_eventQueuePushAndCall(&event);
 3528+}
 3529+
 3530+void RGFW_rawMotionCallback(RGFW_window* win, float x, float y) {
 3531+	_RGFW->vectorX = x;
 3532+	_RGFW->vectorY = y;
 3533+	if (!(win->internal.enabledEvents & RGFW_mouseRawMotionFlag)) return;
 3534+
 3535+	RGFW_event event;
 3536+	event.type = RGFW_mouseRawMotion;
 3537+	event.delta.x = x;
 3538+	event.delta.y = y;
 3539+	event.common.win = win;
 3540+	RGFW_eventQueuePushAndCall(&event);
 3541+}
 3542+
 3543+void RGFW_windowRefreshCallback(RGFW_window* win, i32 x, i32 y, i32 w, i32 h) {
 3544+	if (!(win->internal.enabledEvents & RGFW_windowRefreshFlag)) return;
 3545+	RGFW_event event;
 3546+	event.type = RGFW_windowRefresh;
 3547+	event.update.x = x;
 3548+	event.update.y = y;
 3549+	event.update.w = w;
 3550+	event.update.h = h;
 3551+	event.common.win = win;
 3552+	RGFW_eventQueuePushAndCall(&event);
 3553+}
 3554+
 3555+void RGFW_windowFocusCallback(RGFW_window* win, RGFW_bool inFocus) {
 3556+	win->internal.inFocus = inFocus;
 3557+
 3558+	if (win->internal.captureMouse) {
 3559+		RGFW_window_captureMousePlatform(win, inFocus);
 3560+	}
 3561+
 3562+	RGFW_event event;
 3563+	event.common.win = win;
 3564+	event.focus.state = inFocus;
 3565+
 3566+	if (inFocus == RGFW_TRUE) {
 3567+		if ((win->internal.flags & RGFW_windowFullscreen))
 3568+			RGFW_window_raise(win);
 3569+
 3570+		event.type = RGFW_windowFocusIn;
 3571+	} else if (inFocus == RGFW_FALSE) {
 3572+		if ((win->internal.flags & RGFW_windowFullscreen))
 3573+			RGFW_window_minimize(win);
 3574+
 3575+		size_t key;
 3576+		for (key = 0; key < RGFW_keyLast; key++) {
 3577+			if (RGFW_isKeyDown((u8)key) == RGFW_FALSE) continue;
 3578+
 3579+			_RGFW->keyboard[key].current = RGFW_FALSE;
 3580+			if ((win->internal.enabledEvents & RGFW_BIT(RGFW_keyReleased))) {
 3581+				RGFW_keyCallback(win, (u8)key, win->internal.mod, RGFW_FALSE, RGFW_FALSE);
 3582+			}
 3583+		}
 3584+
 3585+		RGFW_resetKey();
 3586+		event.type = RGFW_windowFocusOut;
 3587+	}
 3588+
 3589+	event.common.win = win;
 3590+
 3591+	RGFW_eventQueuePushAndCall(&event);
 3592+}
 3593+
 3594+void RGFW_mouseNotifyCallback(RGFW_window* win, i32 x, i32 y, RGFW_bool status) {
 3595+	win->internal.mouseInside = status;
 3596+	_RGFW->windowState.win = win;
 3597+
 3598+	win->internal.lastMouseX = x;
 3599+	win->internal.lastMouseY = y;
 3600+
 3601+	RGFW_event event;
 3602+	event.common.win = win;
 3603+	event.mouse.x = x;
 3604+	event.mouse.y = y;
 3605+	event.mouse.inWindow = win->internal.mouseInside;
 3606+
 3607+	if (status) {
 3608+		if (!(win->internal.enabledEvents & RGFW_mouseEnterFlag)) return;
 3609+		_RGFW->windowState.mouseEnter =  RGFW_TRUE;
 3610+		_RGFW->windowState.win = win;
 3611+		event.type = RGFW_mouseEnter;
 3612+	} else {
 3613+		if (!(win->internal.enabledEvents & RGFW_mouseLeaveFlag)) return;
 3614+		_RGFW->windowState.winLeave = win;
 3615+		_RGFW->windowState.mouseLeave =  RGFW_TRUE;
 3616+		event.type = RGFW_mouseLeave;
 3617+	}
 3618+
 3619+	RGFW_eventQueuePushAndCall(&event);
 3620+}
 3621+
 3622+void RGFW_dataDropCallback(RGFW_window* win, const char* data, size_t size, RGFW_dataTransferType dataType) {
 3623+	if (!(win->internal.enabledEvents & RGFW_dataDropFlag) || !(win->internal.flags & RGFW_windowAllowDND))
 3624+		return;
 3625+
 3626+	_RGFW->windowState.win = win;
 3627+	_RGFW->windowState.dataDrop = RGFW_TRUE;
 3628+	_RGFW->windowState.dataSize = size;
 3629+
 3630+	RGFW_dataDropNode node;
 3631+	RGFW_MEMZERO(&node, sizeof(node));
 3632+	node.data = data;
 3633+	node.size = size;
 3634+	node.type = dataType;
 3635+	node.next = NULL;
 3636+
 3637+	RGFW_event event;
 3638+	event.type = RGFW_dataDrop;
 3639+	event.drop.value = &node;
 3640+	event.drop.win = win;
 3641+
 3642+	if (_RGFW->callbacks[event.type]) (_RGFW->callbacks[event.type])(&event);
 3643+
 3644+	if (_RGFW->queueEvents == RGFW_TRUE || _RGFW->dndBuild) {
 3645+		if (_RGFW->dndRoot == NULL) {
 3646+			_RGFW->dndRoot = (RGFW_dataDropNode*)RGFW_ALLOC(sizeof(RGFW_dataDropNode));
 3647+			_RGFW->dndCur =	_RGFW->dndRoot;
 3648+		} else if (_RGFW->dndCur) {
 3649+			_RGFW->dndCur->next = (RGFW_dataDropNode*)RGFW_ALLOC(sizeof(RGFW_dataDropNode));
 3650+			_RGFW->dndCur = _RGFW->dndCur->next;
 3651+		} else { RGFW_ASSERT(0); }
 3652+
 3653+		char* dataCopy = (char*)RGFW_ALLOC(size);
 3654+		RGFW_MEMCPY(dataCopy, data, size);
 3655+		node.data = dataCopy;
 3656+
 3657+		RGFW_MEMCPY(_RGFW->dndCur, &node, sizeof(node));
 3658+
 3659+		event.drop.value = _RGFW->dndCur;
 3660+		RGFW_eventQueuePush(&event);
 3661+	}
 3662+}
 3663+
 3664+void RGFW_dataDragCallback(RGFW_window* win, RGFW_dataTransferType dataType, RGFW_dndActionType action, i32 x, i32 y) {
 3665+	if (!(win->internal.enabledEvents & RGFW_dataDragFlag) || !(win->internal.flags & RGFW_windowAllowDND)) return;
 3666+
 3667+	_RGFW->windowState.win = win;
 3668+	_RGFW->windowState.dataDragging = RGFW_TRUE;
 3669+	_RGFW->windowState.dropX = x;
 3670+	_RGFW->windowState.dropY = y;
 3671+
 3672+	RGFW_event event;
 3673+	event.type = RGFW_dataDrag;
 3674+	event.drag.x = x;
 3675+	event.drag.y = y;
 3676+	event.drag.action = action;
 3677+	event.drag.dataType = dataType;
 3678+	event.common.win = win;
 3679+
 3680+	RGFW_eventQueuePushAndCall(&event);
 3681+}
 3682+
 3683+void RGFW_keyCharCallback(RGFW_window* win, u32 codepoint) {
 3684+	if (!(win->internal.enabledEvents & RGFW_keyCharFlag)) return;
 3685+
 3686+	RGFW_event event;
 3687+	event.type = RGFW_keyChar;
 3688+	event.keyChar.value = codepoint;
 3689+	event.common.win = win;
 3690+	RGFW_eventQueuePushAndCall(&event);
 3691+}
 3692+
 3693+void RGFW_keyCallback(RGFW_window* win, RGFW_key key, RGFW_keymod mod, RGFW_bool repeat, RGFW_bool press) {
 3694+	RGFW_event event;
 3695+
 3696+	if (press) {
 3697+		if (!(win->internal.enabledEvents & RGFW_keyPressedFlag)) return;
 3698+		event.type = RGFW_keyPressed;
 3699+	} else {
 3700+		if (!(win->internal.enabledEvents & RGFW_keyReleasedFlag)) return;
 3701+		event.type = RGFW_keyReleased;
 3702+	}
 3703+
 3704+	_RGFW->keyboard[key].prev = _RGFW->keyboard[key].current;
 3705+	_RGFW->keyboard[key].current = press;
 3706+
 3707+	event.key.value = key;
 3708+	event.key.repeat = repeat;
 3709+	event.key.mod = mod;
 3710+	event.key.state = press;
 3711+	event.common.win = win;
 3712+	RGFW_eventQueuePushAndCall(&event);
 3713+}
 3714+
 3715+void RGFW_mouseButtonCallback(RGFW_window* win, RGFW_mouseButton button, RGFW_bool press) {
 3716+	RGFW_event event;
 3717+
 3718+	if (press) {
 3719+		if (!(win->internal.enabledEvents & RGFW_mouseButtonPressedFlag)) return;
 3720+		event.type = RGFW_mouseButtonPressed;
 3721+	} else {
 3722+		if (!(win->internal.enabledEvents & RGFW_mouseButtonReleasedFlag)) return;
 3723+		event.type = RGFW_mouseButtonReleased;
 3724+	}
 3725+
 3726+	_RGFW->mouseButtons[button].prev = _RGFW->mouseButtons[button].current;
 3727+	_RGFW->mouseButtons[button].current = press;
 3728+
 3729+	event.button.value = button;
 3730+	event.button.state = press;
 3731+	event.common.win = win;
 3732+	RGFW_eventQueuePushAndCall(&event);
 3733+}
 3734+
 3735+void RGFW_mouseScrollCallback(RGFW_window* win, float x, float y) {
 3736+	if (!(win->internal.enabledEvents & RGFW_mouseScrollFlag)) return;
 3737+	_RGFW->scrollX = x;
 3738+	_RGFW->scrollY = y;
 3739+
 3740+	RGFW_event event;
 3741+	event.type = RGFW_mouseScroll;
 3742+	event.delta.x = x;
 3743+	event.delta.y = y;
 3744+	event.common.win = win;
 3745+	RGFW_eventQueuePushAndCall(&event);
 3746+}
 3747+
 3748+void RGFW_scaleUpdatedCallback(RGFW_window* win, float scaleX, float scaleY) {
 3749+	if (!(win->internal.enabledEvents & RGFW_scaleUpdatedFlag)) return;
 3750+
 3751+	RGFW_event event;
 3752+	event.type = RGFW_scaleUpdated;
 3753+	event.scale.x = scaleX;
 3754+	event.scale.y = scaleY;
 3755+	event.common.win = win;
 3756+	RGFW_eventQueuePushAndCall(&event);
 3757+}
 3758+
 3759+void RGFW_monitorCallback(RGFW_window* win, const RGFW_monitor* monitor, RGFW_bool connected) {
 3760+	if (win) {
 3761+		if (connected && !(win->internal.enabledEvents & RGFW_monitorConnectedFlag)) return;
 3762+		if (!connected && !(win->internal.enabledEvents & RGFW_monitorDisconnectedFlag)) return;
 3763+	}
 3764+
 3765+	RGFW_event event;
 3766+	event.type = (connected) ? (RGFW_eventType)(RGFW_monitorConnected) : (RGFW_eventType)(RGFW_monitorDisconnected);
 3767+	event.monitor.monitor = monitor;
 3768+	event.monitor.state = connected;
 3769+	event.common.win = win;
 3770+	RGFW_eventQueuePushAndCall(&event);
 3771+}
 3772+
 3773+#ifdef RGFW_DEBUG
 3774+#include <stdio.h>
 3775+#endif
 3776+
 3777+void RGFW_debugCallback(RGFW_debugType type, RGFW_errorCode code, const char* msg) {
 3778+	RGFW_debugInfo info;
 3779+	info.type = type;
 3780+	info.code = code;
 3781+	info.msg = msg;
 3782+
 3783+	if (_RGFW && _RGFW->debugCallbackSrc) _RGFW->debugCallbackSrc(&info);
 3784+
 3785+    #ifdef RGFW_DEBUG
 3786+	switch (type) {
 3787+		case RGFW_typeInfo: RGFW_PRINTF("RGFW INFO (%i %i): %s", type, code, msg); break;
 3788+		case RGFW_typeError: RGFW_PRINTF("RGFW DEBUG (%i %i): %s", type, code, msg); break;
 3789+		case RGFW_typeWarning: RGFW_PRINTF("RGFW WARNING (%i %i): %s", type, code, msg); break;
 3790+		default: break;
 3791+	}
 3792+
 3793+	RGFW_PRINTF("\n");
 3794+	#endif
 3795+}
 3796+
 3797+void RGFW_window_checkMode(RGFW_window* win);
 3798+void RGFW_window_checkMode(RGFW_window* win) {
 3799+	if (RGFW_window_isMinimized(win) && (win->internal.enabledEvents & RGFW_windowMinimizedFlag)) {
 3800+		RGFW_windowMinimizedCallback(win);
 3801+	} else if (RGFW_window_isMaximized(win) && (win->internal.enabledEvents & RGFW_windowMaximizedFlag)) {
 3802+		RGFW_windowMaximizedCallback(win, win->x, win->y, win->w, win->h);
 3803+	} else if ((((win->internal.flags & RGFW_windowMinimize) && !RGFW_window_isMaximized(win)) ||
 3804+				(win->internal.flags & RGFW_windowMaximize && !RGFW_window_isMaximized(win))) && (win->internal.enabledEvents & RGFW_windowRestoredFlag)) {
 3805+		RGFW_windowRestoredCallback(win, win->x, win->y, win->w, win->h);
 3806+	}
 3807+}
 3808+
 3809+/*
 3810+no more event call back defines
 3811+*/
 3812+
 3813+size_t RGFW_sizeofInfo(void) { return sizeof(RGFW_info); }
 3814+size_t RGFW_sizeofNativeImage(void) { return sizeof(RGFW_nativeImage); }
 3815+size_t RGFW_sizeofSurface(void) { return sizeof(RGFW_surface); }
 3816+size_t RGFW_sizeofWindow(void) { return sizeof(RGFW_window); }
 3817+size_t RGFW_sizeofWindowSrc(void) { return sizeof(RGFW_window_src); }
 3818+
 3819+RGFW_window_src* RGFW_window_getSrc(RGFW_window* win) { return &win->src; }
 3820+RGFW_bool RGFW_window_getPosition(RGFW_window* win, i32* x, i32* y) { if (x) *x = win->x; if (y) *y = win->y; return RGFW_TRUE; }
 3821+RGFW_bool RGFW_window_getSize(RGFW_window* win, i32* w, i32* h) { if (w) *w = win->w; if (h) *h = win->h; return RGFW_TRUE; }
 3822+u32 RGFW_window_getFlags(RGFW_window* win) { return win->internal.flags; }
 3823+RGFW_key RGFW_window_getExitKey(RGFW_window* win) { return win->internal.exitKey; }
 3824+void RGFW_window_setExitKey(RGFW_window* win, RGFW_key key) { win->internal.exitKey = key; }
 3825+void RGFW_window_setEnabledEvents(RGFW_window* win, RGFW_eventFlag events) { win->internal.enabledEvents = events; }
 3826+RGFW_eventFlag RGFW_window_getEnabledEvents(RGFW_window* win) { return win->internal.enabledEvents; }
 3827+void RGFW_window_setDisabledEvents(RGFW_window* win, RGFW_eventFlag events) {   RGFW_window_setEnabledEvents(win, (RGFW_allEventFlags) & ~(u32)events);  }
 3828+void RGFW_window_setEventState(RGFW_window* win, RGFW_eventFlag event, RGFW_bool state) { RGFW_setBit(&win->internal.enabledEvents, event, state); }
 3829+void* RGFW_window_getUserPtr(RGFW_window* win) { return win->userPtr; }
 3830+void RGFW_window_setUserPtr(RGFW_window* win, void* ptr) { win->userPtr = ptr; }
 3831+
 3832+RGFW_bool RGFW_window_getSizeInPixels(RGFW_window* win, i32* w, i32* h) {
 3833+	RGFW_monitor* mon = RGFW_window_getMonitor(win);
 3834+	if (mon == NULL) return RGFW_FALSE;
 3835+
 3836+	if (w) *w = (i32)((float)win->w * mon->pixelRatio);
 3837+	if (h) *h = (i32)((float)win->h * mon->pixelRatio);
 3838+
 3839+	return RGFW_TRUE;
 3840+}
 3841+
 3842+
 3843+#if defined(RGFW_USE_XDL) && defined(RGFW_X11)
 3844+	#define XDL_IMPLEMENTATION
 3845+	#include "XDL.h"
 3846+#endif
 3847+
 3848+#ifndef RGFW_NO_STATIC_CONTEXT
 3849+
 3850+i32 RGFW_init(void) {
 3851+	static RGFW_info _rgfwGlobal;
 3852+	return RGFW_init_ptr(&_rgfwGlobal);
 3853+}
 3854+
 3855+
 3856+void RGFW_deinit(void) { RGFW_deinit_ptr(_RGFW); }
 3857+
 3858+#else
 3859+
 3860+RGFW_info* _rgfwGlobal;
 3861+
 3862+i32 RGFW_init(void) {
 3863+	if (_rgfwGlobal != NULL) {
 3864+		RGFW_FREE(_rgfwGlobal);
 3865+	}
 3866+
 3867+	_rgfwGlobal = (RGFW_info*)RGFW_ALLOC(sizeof(RGFW_info));
 3868+
 3869+	return RGFW_init_ptr(&_rgfwGlobal);
 3870+}
 3871+
 3872+void RGFW_deinit(void) {
 3873+	if (_RGFW == _rgfwGlobal) {
 3874+		RGFW_FREE(_rgfwGlobal);
 3875+		_rgfwGlobal = NULL;
 3876+	}
 3877+	RGFW_deinit_ptr(_RGFW);
 3878+}
 3879+
 3880+#endif
 3881+
 3882+i32 RGFW_initPlatform(void);
 3883+void RGFW_deinitPlatform(void);
 3884+
 3885+i32 RGFW_init_ptr(RGFW_info* info) {
 3886+    if (info == _RGFW || info == NULL) return 1;
 3887+
 3888+    RGFW_setInfo(info);
 3889+    RGFW_MEMZERO(_RGFW, sizeof(RGFW_info));
 3890+	_RGFW->queueEvents = RGFW_FALSE;
 3891+	_RGFW->polledEvents = RGFW_FALSE;
 3892+#ifdef RGFW_WAYLAND
 3893+	_RGFW->useWaylandBool = RGFW_TRUE;
 3894+#endif
 3895+
 3896+	#if (RGFW_PREALLOCATED_MONITORS)
 3897+		_RGFW->monitors.freeList.head = &_RGFW->monitors.data[0];
 3898+		_RGFW->monitors.freeList.cur = _RGFW->monitors.freeList.head;
 3899+
 3900+		for (size_t i = 1; i < RGFW_PREALLOCATED_MONITORS; i++) {
 3901+			RGFW_monitorNode* newNode = &_RGFW->monitors.data[i];
 3902+			_RGFW->monitors.freeList.cur->next = newNode;
 3903+			_RGFW->monitors.freeList.cur = _RGFW->monitors.freeList.cur->next;
 3904+		}
 3905+	#endif
 3906+
 3907+	_RGFW->monitors.list.head = NULL;
 3908+	_RGFW->monitors.list.head = NULL;
 3909+    RGFW_initKeycodes();
 3910+    i32 out = RGFW_initPlatform();
 3911+
 3912+	for (size_t i = 0; i < RGFW_mouseIconCount; i++) {
 3913+        _RGFW->standardMice[i] = RGFW_createMouseStandard((RGFW_mouseIcon)i);
 3914+	}
 3915+
 3916+	RGFW_pollMonitors();
 3917+
 3918+    RGFW_debugCallback(RGFW_typeInfo, RGFW_infoGlobal, "global context initialized");
 3919+
 3920+	return out;
 3921+}
 3922+
 3923+#ifndef RGFW_EGL
 3924+void RGFW_unloadEGL(void) { }
 3925+#endif
 3926+
 3927+void RGFW_deinit_ptr(RGFW_info* info) {
 3928+    if (info == NULL) return;
 3929+
 3930+    RGFW_setInfo(info);
 3931+	RGFW_unloadEGL();
 3932+
 3933+	for (RGFW_mouseIcon i = 0; i < RGFW_mouseIconCount; i++) {
 3934+		if (_RGFW->standardMice[i]) RGFW_freeMouse(_RGFW->standardMice[i]);
 3935+	}
 3936+
 3937+	RGFW_debugCallback(RGFW_typeInfo, RGFW_infoGlobal, "global context deinitialized");
 3938+	RGFW_deinitPlatform();
 3939+
 3940+    _RGFW->root = NULL;
 3941+    _RGFW->windowCount = 0;
 3942+    RGFW_setInfo(NULL);
 3943+}
 3944+
 3945+RGFW_window* RGFW_createWindow(const char* name, i32 x, i32 y, i32 w, i32 h, RGFW_windowFlags flags) {
 3946+	RGFW_window* win = (RGFW_window*)RGFW_ALLOC(sizeof(RGFW_window));
 3947+	RGFW_ASSERT(win != NULL);
 3948+    return RGFW_createWindowPtr(name, x, y, w, h, flags, win);
 3949+}
 3950+
 3951+void RGFW_window_close(RGFW_window* win) {
 3952+	RGFW_ASSERT(win != NULL);
 3953+	RGFW_window_closePtr(win);
 3954+	RGFW_FREE(win);
 3955+}
 3956+
 3957+RGFW_window* RGFW_createWindowPtr(const char* name, i32 x, i32 y, i32 w, i32 h, RGFW_windowFlags flags, RGFW_window* win) {
 3958+	RGFW_ASSERT(win != NULL);
 3959+	if (name == NULL) name = "\0";
 3960+
 3961+	RGFW_MEMZERO(win, sizeof(RGFW_window));
 3962+
 3963+	if (_RGFW == NULL) RGFW_init();
 3964+	_RGFW->windowCount++;
 3965+
 3966+	/* rect based the requested flags */
 3967+	if (_RGFW->root == NULL) {
 3968+		RGFW_setRootWindow(win);
 3969+	}
 3970+
 3971+	/* set and init the new window's data */
 3972+	win->x = x;
 3973+	win->y = y;
 3974+	win->w = w;
 3975+	win->h = h;
 3976+	win->internal.mouse = _RGFW->standardMice[RGFW_mouseNormal];
 3977+	win->internal.flags = flags;
 3978+	win->internal.enabledEvents = RGFW_allEventFlags;
 3979+
 3980+	RGFW_windowFlags reservedFlags = flags & (RGFW_windowScaleToMonitor);
 3981+	flags &= ~reservedFlags;
 3982+
 3983+	RGFW_window* ret = RGFW_createWindowPlatform(name, flags, win);
 3984+
 3985+	flags |= reservedFlags;
 3986+
 3987+#ifndef RGFW_X11
 3988+	RGFW_window_setFlagsInternal(win, flags, 0);
 3989+#endif
 3990+
 3991+#ifdef RGFW_OPENGL
 3992+	win->src.gfxType = 0;
 3993+	if (flags & RGFW_windowOpenGL)
 3994+		RGFW_window_createContext_OpenGL(win, RGFW_getGlobalHints_OpenGL());
 3995+#endif
 3996+
 3997+#ifdef RGFW_EGL
 3998+	if (flags & RGFW_windowEGL)
 3999+		RGFW_window_createContext_EGL(win, RGFW_getGlobalHints_OpenGL());
 4000+#endif
 4001+
 4002+	/* X11 creates the window after the OpenGL context is created (because of visual garbage),
 4003+		 * so we have to wait to set the flags
 4004+		 * This is required so that way the user can create their own OpenGL context after RGFW_createWindow is used
 4005+		 * if a window is created, CreateContext will delete the window and create a new one
 4006+		 * */
 4007+#ifdef RGFW_X11
 4008+	RGFW_window_setFlagsInternal(win, flags, 0);
 4009+#endif
 4010+
 4011+#ifdef RGFW_MACOS
 4012+	/*NOTE: another OpenGL/setFlags related hack, this because OSX the 'view' class must be setup after the NSOpenGL view is made AND after setFlags happens */
 4013+	RGFW_osx_initView(win);
 4014+#endif
 4015+
 4016+#ifdef RGFW_WAYLAND
 4017+	/* recieve all events needed to configure the surface */
 4018+	/* also gets the wl_outputs */
 4019+	if (RGFW_usingWayland()) {
 4020+		wl_display_roundtrip(_RGFW->wl_display);
 4021+		/* NOTE: this is a hack so that way wayland spawns a window, even if nothing is drawn */
 4022+		if (!(flags & RGFW_windowOpenGL) && !(flags & RGFW_windowEGL)) {
 4023+			u8* data = (u8*)RGFW_ALLOC((u32)(win->w * win->h * 3));
 4024+			RGFW_MEMZERO(data, (u32)(win->w * win->h * 3) * sizeof(u8));
 4025+			RGFW_surface* surface = RGFW_createSurface(data, win->w, win->h, RGFW_formatBGR8);
 4026+			RGFW_window_blitSurface(win, surface);
 4027+			RGFW_FREE(data);
 4028+			RGFW_surface_free(surface);
 4029+		}
 4030+	}
 4031+#endif
 4032+
 4033+	if (!(flags & RGFW_windowHideMouse)) {
 4034+		RGFW_window_setMouseDefault(win);
 4035+	}
 4036+
 4037+	RGFW_window_setName(win, name);
 4038+	if (!(flags & RGFW_windowHide)) {
 4039+		flags |= RGFW_windowHide;
 4040+		RGFW_window_show(win);
 4041+	}
 4042+
 4043+	RGFW_debugCallback(RGFW_typeInfo, RGFW_infoWindow, "a new window was created");
 4044+
 4045+	return ret;
 4046+}
 4047+
 4048+void RGFW_window_closePtr(RGFW_window* win) {
 4049+	RGFW_ASSERT(win != NULL);
 4050+
 4051+	if (win->internal.captureMouse) {
 4052+		RGFW_window_captureMouse(win, RGFW_FALSE);
 4053+	}
 4054+
 4055+	#ifdef RGFW_EGL
 4056+	if ((win->src.gfxType & RGFW_gfxEGL) && win->src.ctx.egl) {
 4057+		RGFW_window_deleteContext_EGL(win, win->src.ctx.egl);
 4058+		win->src.ctx.egl = NULL;
 4059+	}
 4060+	#endif
 4061+
 4062+	#ifdef RGFW_OPENGL
 4063+	if ((win->src.gfxType & RGFW_gfxNativeOpenGL) && win->src.ctx.native) {
 4064+		RGFW_window_deleteContext_OpenGL(win, win->src.ctx.native);
 4065+		win->src.ctx.native = NULL;
 4066+	}
 4067+	#endif
 4068+
 4069+	RGFW_window_closePlatform(win);
 4070+
 4071+	RGFW_clipboard_switch(NULL);
 4072+
 4073+	_RGFW->windowCount--;
 4074+	RGFW_debugCallback(RGFW_typeInfo, RGFW_infoWindow, "a window was freed");
 4075+
 4076+	if (_RGFW->windowCount == 0 && !(win->internal.flags & RGFW_noDeinitOnClose)) RGFW_deinit();
 4077+}
 4078+
 4079+void RGFW_setQueueEvents(RGFW_bool queue) {  _RGFW->queueEvents = RGFW_BOOL(queue); }
 4080+
 4081+void RGFW_eventQueueFlush(void) { _RGFW->eventLen = 0; }
 4082+
 4083+void RGFW_eventQueuePush(const RGFW_event* event) {
 4084+	if (_RGFW->queueEvents == RGFW_FALSE) return;
 4085+	RGFW_ASSERT(_RGFW->eventLen >= 0);
 4086+
 4087+	if (_RGFW->eventLen >= RGFW_MAX_EVENTS) {
 4088+		RGFW_debugCallback(RGFW_typeError, RGFW_errEventQueue, "Event queue limit 'RGFW_MAX_EVENTS' has been reached automatically flushing queue.");
 4089+		RGFW_eventQueueFlush();
 4090+		return;
 4091+	}
 4092+
 4093+	i32 eventTop = (_RGFW->eventBottom + _RGFW->eventLen) % RGFW_MAX_EVENTS;
 4094+	_RGFW->eventLen += 1;
 4095+	_RGFW->events[eventTop] = *event;
 4096+}
 4097+
 4098+RGFW_event* RGFW_eventQueuePop(void) {
 4099+	RGFW_ASSERT(_RGFW->eventLen >= 0 && _RGFW->eventLen <= RGFW_MAX_EVENTS);
 4100+	RGFW_event* ev;
 4101+
 4102+	if (_RGFW->eventLen == 0) {
 4103+		return NULL;
 4104+	}
 4105+
 4106+	ev = &_RGFW->events[_RGFW->eventBottom];
 4107+	_RGFW->eventLen -= 1;
 4108+    _RGFW->eventBottom = (_RGFW->eventBottom + 1) % RGFW_MAX_EVENTS;
 4109+
 4110+	return ev;
 4111+}
 4112+
 4113+RGFW_bool RGFW_checkEvent(RGFW_event* event) {
 4114+	if (_RGFW->eventLen == 0 && _RGFW->polledEvents == RGFW_FALSE) {
 4115+		_RGFW->queueEvents = RGFW_TRUE;
 4116+		RGFW_pollEvents();
 4117+		_RGFW->polledEvents = RGFW_TRUE;
 4118+	}
 4119+
 4120+	if (RGFW_checkQueuedEvent(event) == RGFW_FALSE) {
 4121+		_RGFW->polledEvents = RGFW_FALSE;
 4122+		return RGFW_FALSE;
 4123+	}
 4124+
 4125+	return RGFW_TRUE;
 4126+}
 4127+
 4128+RGFW_bool RGFW_checkQueuedEvent(RGFW_event* event) {
 4129+	RGFW_event* ev;
 4130+	_RGFW->queueEvents = RGFW_TRUE;
 4131+	/* check queued events */
 4132+	ev = RGFW_eventQueuePop();
 4133+	if (ev != NULL) {
 4134+		*event = *ev;
 4135+		return RGFW_TRUE;
 4136+    }
 4137+
 4138+	return RGFW_FALSE;
 4139+}
 4140+
 4141+void RGFW_resetPrevState(void) {
 4142+	size_t i; /*!< reset each previous state  */
 4143+    for (i = 0; i < RGFW_keyLast; i++) _RGFW->keyboard[i].prev = _RGFW->keyboard[i].current;
 4144+    for (i = 0; i < RGFW_mouseFinal; i++) _RGFW->mouseButtons[i].prev = _RGFW->mouseButtons[i].current;
 4145+	_RGFW->scrollX = 0.0f;
 4146+	_RGFW->scrollY = 0.0f;
 4147+	_RGFW->vectorX = (float)0.0f;
 4148+	_RGFW->vectorY = (float)0.0f;
 4149+	RGFW_MEMZERO(&_RGFW->windowState, sizeof(_RGFW->windowState));
 4150+
 4151+	for (RGFW_dataDropNode* node = _RGFW->dndRoot; node; ) {
 4152+		RGFW_dataDropNode* next = node->next;
 4153+		RGFW_FREE(node);
 4154+		node = next;
 4155+	}
 4156+
 4157+	_RGFW->dndRoot = NULL;
 4158+	_RGFW->dndCur = NULL;
 4159+}
 4160+
 4161+RGFW_bool RGFW_isKeyPressed(RGFW_key key) {
 4162+	RGFW_ASSERT(_RGFW != NULL);
 4163+    return _RGFW->keyboard[key].current && !_RGFW->keyboard[key].prev;
 4164+}
 4165+RGFW_bool RGFW_isKeyDown(RGFW_key key) {
 4166+	RGFW_ASSERT(_RGFW != NULL);
 4167+	return _RGFW->keyboard[key].current;
 4168+}
 4169+RGFW_bool RGFW_isKeyReleased(RGFW_key key) {
 4170+	RGFW_ASSERT(_RGFW != NULL);
 4171+	return !_RGFW->keyboard[key].current && _RGFW->keyboard[key].prev;
 4172+}
 4173+
 4174+
 4175+RGFW_bool RGFW_isMousePressed(RGFW_mouseButton button) {
 4176+	RGFW_ASSERT(_RGFW != NULL);
 4177+	return _RGFW->mouseButtons[button].current && !_RGFW->mouseButtons[button].prev;
 4178+}
 4179+RGFW_bool RGFW_isMouseDown(RGFW_mouseButton button) {
 4180+	RGFW_ASSERT(_RGFW != NULL);
 4181+	return _RGFW->mouseButtons[button].current;
 4182+}
 4183+RGFW_bool RGFW_isMouseReleased(RGFW_mouseButton button) {
 4184+	RGFW_ASSERT(_RGFW != NULL);
 4185+	return !_RGFW->mouseButtons[button].current && _RGFW->mouseButtons[button].prev;
 4186+}
 4187+
 4188+void RGFW_getMouseScroll(float* x, float* y) {
 4189+	RGFW_ASSERT(_RGFW != NULL);
 4190+	if (x) *x = _RGFW->scrollX;
 4191+	if (y) *y = _RGFW->scrollY;
 4192+}
 4193+
 4194+void RGFW_getMouseVector(float* x, float* y) {
 4195+	RGFW_ASSERT(_RGFW != NULL);
 4196+	if (x) *x = _RGFW->vectorX;
 4197+	if (y) *y = _RGFW->vectorY;
 4198+}
 4199+
 4200+RGFW_bool RGFW_window_didMouseLeave(RGFW_window* win) { return _RGFW->windowState.winLeave == win && _RGFW->windowState.mouseLeave; }
 4201+RGFW_bool RGFW_window_didMouseEnter(RGFW_window* win) { return _RGFW->windowState.win == win && _RGFW->windowState.mouseEnter; }
 4202+RGFW_bool RGFW_window_isMouseInside(RGFW_window* win) { return win->internal.mouseInside;  }
 4203+
 4204+RGFW_bool RGFW_window_isDataDragging(RGFW_window* win) { return RGFW_window_getDataDrag(win, (i32*)NULL, (i32*)NULL); }
 4205+RGFW_bool RGFW_window_didDataDrop(RGFW_window* win) { return RGFW_window_getDataDrop(win) != NULL;}
 4206+
 4207+
 4208+RGFW_bool RGFW_window_getDataDrag(RGFW_window* win, i32* x, i32* y) {
 4209+	if (_RGFW->windowState.win != win || _RGFW->windowState.dataDragging == RGFW_FALSE) return RGFW_FALSE;
 4210+	if (x) *x = _RGFW->windowState.dropX;
 4211+	if (y) *y =  _RGFW->windowState.dropY;
 4212+	return RGFW_TRUE;
 4213+}
 4214+RGFW_dataDropNode* RGFW_window_getDataDrop(RGFW_window* win) {
 4215+	if (_RGFW->windowState.win != win || _RGFW->windowState.dataDrop == RGFW_FALSE) return NULL;
 4216+	return _RGFW->dndRoot;
 4217+}
 4218+
 4219+RGFW_bool RGFW_window_checkEvent(RGFW_window* win, RGFW_event* event) {
 4220+	if (_RGFW->eventLen == 0 && _RGFW->polledEvents == RGFW_FALSE) {
 4221+		_RGFW->queueEvents = RGFW_TRUE;
 4222+		RGFW_pollEvents();
 4223+		_RGFW->polledEvents = RGFW_TRUE;
 4224+	}
 4225+
 4226+	if (RGFW_window_checkQueuedEvent(win, event) == RGFW_FALSE) {
 4227+		_RGFW->polledEvents = RGFW_FALSE;
 4228+		return RGFW_FALSE;
 4229+	}
 4230+
 4231+	return RGFW_TRUE;
 4232+}
 4233+
 4234+RGFW_bool RGFW_window_checkQueuedEvent(RGFW_window* win, RGFW_event* event) {
 4235+	RGFW_event* ev;
 4236+	RGFW_ASSERT(win != NULL);
 4237+	_RGFW->queueEvents = RGFW_TRUE;
 4238+	/* check queued events */
 4239+	ev = RGFW_window_eventQueuePop(win);
 4240+	if (ev == NULL) return RGFW_FALSE;
 4241+
 4242+	*event = *ev;
 4243+	return RGFW_TRUE;
 4244+}
 4245+
 4246+RGFW_event* RGFW_window_eventQueuePop(RGFW_window* win) {
 4247+	RGFW_event* ev = RGFW_eventQueuePop();
 4248+	if (ev == NULL) return ev;
 4249+
 4250+	for (i32 i = 1; i < _RGFW->eventLen && ev->common.win != win && ev->common.win != NULL; i++) {
 4251+		RGFW_eventQueuePush(ev);
 4252+		ev = RGFW_eventQueuePop();
 4253+	}
 4254+
 4255+	if (ev->common.win != win && ev->common.win != NULL) {
 4256+		return NULL;
 4257+	}
 4258+
 4259+	return ev;
 4260+}
 4261+
 4262+void RGFW_setRootWindow(RGFW_window* win) { _RGFW->root = win; }
 4263+RGFW_window* RGFW_getRootWindow(void) { return _RGFW->root; }
 4264+
 4265+#ifndef RGFW_EGL
 4266+RGFW_bool RGFW_loadEGL(void) { return RGFW_FALSE; }
 4267+#endif
 4268+
 4269+void RGFW_window_setFlagsInternal(RGFW_window* win, RGFW_windowFlags flags, RGFW_windowFlags cmpFlags) {
 4270+	if (flags & RGFW_windowNoBorder)            RGFW_window_setBorder(win, 0);
 4271+	else if (cmpFlags & RGFW_windowNoBorder)    RGFW_window_setBorder(win, 1);
 4272+	if (flags & RGFW_windowMaximize)            RGFW_window_maximize(win);
 4273+	else if (cmpFlags & RGFW_windowMaximize)    RGFW_window_restore(win);
 4274+	if (flags & RGFW_windowMinimize)            RGFW_window_minimize(win);
 4275+	else if (cmpFlags & RGFW_windowMinimize)    RGFW_window_restore(win);
 4276+	if (flags & RGFW_windowCenter)              RGFW_window_center(win);
 4277+	if (flags & RGFW_windowCenterCursor)        RGFW_window_moveMouse(win, win->x + (win->w / 2), win->y + (win->h / 2));
 4278+	if (flags & RGFW_windowFullscreen)          RGFW_window_setFullscreen(win, RGFW_TRUE);
 4279+	else if (cmpFlags & RGFW_windowFullscreen)  RGFW_window_setFullscreen(win, 0);
 4280+	if (flags & RGFW_windowHideMouse)           RGFW_window_showMouse(win, 0);
 4281+	else if (cmpFlags & RGFW_windowHideMouse)   RGFW_window_showMouse(win, 1);
 4282+	if (flags & RGFW_windowHide)                RGFW_window_hide(win);
 4283+	else if (cmpFlags & RGFW_windowHide)        RGFW_window_show(win);
 4284+	if (flags & RGFW_windowFloating)            RGFW_window_setFloating(win, 1);
 4285+	else if (cmpFlags & RGFW_windowFloating)    RGFW_window_setFloating(win, 0);
 4286+	if (flags & RGFW_windowRawMouse)			RGFW_window_setRawMouseMode(win, RGFW_TRUE);
 4287+	else if (cmpFlags & RGFW_windowRawMouse)	RGFW_window_setRawMouseMode(win, RGFW_FALSE);
 4288+	if (flags & RGFW_windowCaptureMouse)			RGFW_window_captureRawMouse(win, RGFW_TRUE);
 4289+	else if (cmpFlags & RGFW_windowCaptureMouse)	RGFW_window_captureMouse(win, RGFW_FALSE);
 4290+	if (flags & RGFW_windowFocus)               RGFW_window_focus(win);
 4291+	if (flags & RGFW_windowScaleToMonitor)      RGFW_window_scaleToMonitor(win);
 4292+
 4293+	if (flags & RGFW_windowNoResize) {
 4294+	    RGFW_window_setMaxSize(win, win->w, win->h);
 4295+	    RGFW_window_setMinSize(win, win->w, win->h);
 4296+	} else if (cmpFlags & RGFW_windowNoResize) {
 4297+		RGFW_window_setMaxSize(win, 0, 0);
 4298+		RGFW_window_setMinSize(win, 0, 0);
 4299+	}
 4300+
 4301+	win->internal.flags = flags;
 4302+}
 4303+
 4304+
 4305+void RGFW_window_setFlags(RGFW_window* win, RGFW_windowFlags flags) { RGFW_window_setFlagsInternal(win, flags, win->internal.flags); }
 4306+
 4307+RGFW_bool RGFW_window_isInFocus(RGFW_window* win) {
 4308+#ifdef RGFW_WASM
 4309+    return RGFW_TRUE;
 4310+#else
 4311+    return RGFW_BOOL(win->internal.inFocus);
 4312+#endif
 4313+}
 4314+
 4315+void RGFW_setClassName(const char* name) { RGFW_init(); _RGFW->className = name; }
 4316+void RGFW_setBuildDND(RGFW_bool state) { _RGFW->dndBuild = state; }
 4317+
 4318+#ifndef RGFW_X11
 4319+void RGFW_setXInstName(const char* name) { RGFW_UNUSED(name); }
 4320+#endif
 4321+
 4322+RGFW_bool RGFW_window_getMouse(RGFW_window* win, i32* x, i32* y) {
 4323+	RGFW_ASSERT(win != NULL);
 4324+	if (x) *x = win->internal.lastMouseX;
 4325+	if (y) *y = win->internal.lastMouseY;
 4326+	return RGFW_TRUE;
 4327+}
 4328+
 4329+RGFW_bool RGFW_window_isKeyPressed(RGFW_window* win, RGFW_key key) { return RGFW_isKeyPressed(key)  && RGFW_window_isInFocus(win); }
 4330+RGFW_bool RGFW_window_isKeyDown(RGFW_window* win, RGFW_key key) { return RGFW_isKeyDown(key) && RGFW_window_isInFocus(win); }
 4331+RGFW_bool RGFW_window_isKeyReleased(RGFW_window* win, RGFW_key key) { return RGFW_isKeyReleased(key) && RGFW_window_isInFocus(win); }
 4332+
 4333+RGFW_bool RGFW_window_isMousePressed(RGFW_window* win, RGFW_mouseButton button) { return RGFW_isMousePressed(button) && RGFW_window_isInFocus(win); }
 4334+RGFW_bool RGFW_window_isMouseDown(RGFW_window* win, RGFW_mouseButton button) { return RGFW_isMouseDown(button) && RGFW_window_isInFocus(win); }
 4335+RGFW_bool RGFW_window_isMouseReleased(RGFW_window* win, RGFW_mouseButton button) { return RGFW_isMouseReleased(button) && RGFW_window_isInFocus(win); }
 4336+
 4337+
 4338+
 4339+#ifndef RGFW_X11
 4340+void* RGFW_getDisplay_X11(void) { return NULL; }
 4341+u64 RGFW_window_getWindow_X11(RGFW_window* win) { RGFW_UNUSED(win); return 0; }
 4342+#endif
 4343+
 4344+#ifndef RGFW_WAYLAND
 4345+struct wl_display* RGFW_getDisplay_Wayland(void) { return NULL; }
 4346+struct wl_surface* RGFW_window_getWindow_Wayland(RGFW_window* win) { RGFW_UNUSED(win); return NULL; }
 4347+#endif
 4348+
 4349+#ifndef RGFW_WINDOWS
 4350+void* RGFW_window_getHWND(RGFW_window* win) { RGFW_UNUSED(win); return NULL; }
 4351+void* RGFW_window_getHDC(RGFW_window* win) { RGFW_UNUSED(win); return NULL; }
 4352+#endif
 4353+
 4354+#ifndef RGFW_MACOS
 4355+void* RGFW_window_getView_OSX(RGFW_window* win) { RGFW_UNUSED(win); return NULL; }
 4356+void RGFW_window_setLayer_OSX(RGFW_window* win, void* layer) { RGFW_UNUSED(win); RGFW_UNUSED(layer); }
 4357+void* RGFW_getLayer_OSX(void) { return NULL; }
 4358+void* RGFW_window_getWindow_OSX(RGFW_window* win) { RGFW_UNUSED(win); return NULL; }
 4359+#endif
 4360+
 4361+void RGFW_setBit(u32* var, u32 mask, RGFW_bool set) {
 4362+	if (set) *var |=  mask;
 4363+	else     *var &= ~mask;
 4364+}
 4365+
 4366+void RGFW_window_center(RGFW_window* win) {
 4367+	RGFW_ASSERT(win != NULL);
 4368+	RGFW_monitor* mon = RGFW_window_getMonitor(win);
 4369+	if (mon == NULL) return;
 4370+
 4371+	RGFW_window_move(win, mon->x + ((i32)(mon->mode.w - win->w) / 2), mon->y + ((mon->mode.h - win->h) / 2));
 4372+}
 4373+
 4374+RGFW_bool RGFW_monitor_scaleToWindow(RGFW_monitor* mon, RGFW_window* win) {
 4375+	RGFW_monitorMode mode;
 4376+    RGFW_ASSERT(win != NULL);
 4377+
 4378+	mode.w = win->w;
 4379+	mode.h = win->h;
 4380+	RGFW_bool ret = RGFW_monitor_requestMode(mon, &mode, RGFW_monitorScale);
 4381+
 4382+	/* move window to monitor origin so it doesn't move to the next monitor */
 4383+	RGFW_window_move(win, mon->x, mon->y);
 4384+
 4385+	return ret;
 4386+}
 4387+
 4388+void RGFW_splitBPP(u32 bpp, RGFW_monitorMode* mode) {
 4389+    if (bpp == 32) bpp = 24;
 4390+    mode->red = mode->green = mode->blue = (u8)(bpp / 3);
 4391+
 4392+    u32 delta = bpp - (mode->red * 3); /* handle leftovers */
 4393+    if (delta >= 1) mode->green = mode->green + 1;
 4394+    if (delta == 2) mode->red = mode->red + 1;
 4395+}
 4396+
 4397+RGFW_bool RGFW_monitorModeCompare(RGFW_monitorMode* mon, RGFW_monitorMode* mon2, RGFW_modeRequest request) {
 4398+	RGFW_ASSERT(mon);
 4399+	RGFW_ASSERT(mon2);
 4400+
 4401+	return (((mon->w == mon2->w && mon->h == mon2->h) || !(request & RGFW_monitorScale)) &&
 4402+			((mon->refreshRate == mon2->refreshRate) || !(request & RGFW_monitorRefresh)) &&
 4403+			((mon->red == mon2->red && mon->green == mon2->green && mon->blue == mon2->blue) || !(request & RGFW_monitorRGB)));
 4404+}
 4405+
 4406+RGFW_bool RGFW_window_shouldClose(RGFW_window* win) {
 4407+	return (win == NULL || win->internal.shouldClose || (win->internal.exitKey && RGFW_isKeyDown(win->internal.exitKey)));
 4408+}
 4409+
 4410+void RGFW_window_setShouldClose(RGFW_window* win, RGFW_bool shouldClose) {
 4411+	if (shouldClose)  {
 4412+		RGFW_windowCloseCallback(win);
 4413+	} else {
 4414+		win->internal.shouldClose = RGFW_FALSE;
 4415+	}
 4416+}
 4417+
 4418+void RGFW_window_scaleToMonitor(RGFW_window* win) {
 4419+	RGFW_monitor* monitor = RGFW_window_getMonitor(win);
 4420+	if (monitor->scaleX == 0 && monitor->scaleY == 0)
 4421+		return;
 4422+
 4423+	RGFW_window_resize(win, (i32)(monitor->scaleX * (float)win->w), (i32)(monitor->scaleY * (float)win->h));
 4424+}
 4425+
 4426+void RGFW_window_moveToMonitor(RGFW_window* win, RGFW_monitor* m) {
 4427+	RGFW_window_move(win, m->x + win->x, m->y + win->y);
 4428+}
 4429+
 4430+RGFW_surface* RGFW_createSurface(u8* data, i32 w, i32 h, RGFW_format format) {
 4431+	RGFW_surface* surface = (RGFW_surface*)RGFW_ALLOC(sizeof(RGFW_surface));
 4432+	RGFW_MEMZERO(surface, sizeof(RGFW_surface));
 4433+	RGFW_createSurfacePtr(data, w, h, format, surface);
 4434+	return surface;
 4435+}
 4436+
 4437+void RGFW_surface_setConvertFunc(RGFW_surface* surface, RGFW_convertImageDataFunc func) {
 4438+	surface->convertFunc = func;
 4439+}
 4440+
 4441+void RGFW_surface_free(RGFW_surface* surface) {
 4442+	RGFW_surface_freePtr(surface);
 4443+	RGFW_FREE(surface);
 4444+}
 4445+
 4446+RGFW_nativeImage* RGFW_surface_getNativeImage(RGFW_surface* surface) {
 4447+	return &surface->native;
 4448+}
 4449+
 4450+RGFW_surface* RGFW_window_createSurface(RGFW_window* win, u8* data, i32 w, i32 h, RGFW_format format) {
 4451+	RGFW_surface* surface = (RGFW_surface*)RGFW_ALLOC(sizeof(RGFW_surface));
 4452+	RGFW_MEMZERO(surface, sizeof(RGFW_surface));
 4453+	RGFW_window_createSurfacePtr(win, data, w, h, format, surface);
 4454+	return surface;
 4455+}
 4456+
 4457+#ifndef RGFW_X11
 4458+RGFW_bool RGFW_window_createSurfacePtr(RGFW_window* win, u8* data, i32 w, i32 h, RGFW_format format, RGFW_surface* surface) {
 4459+	RGFW_UNUSED(win);
 4460+	return RGFW_createSurfacePtr(data, w, h, format, surface);
 4461+}
 4462+#endif
 4463+
 4464+const RGFW_colorLayout RGFW_layouts[RGFW_formatCount] = {
 4465+	{ 0, 1, 2, 3, 3 }, /* RGFW_formatRGB8 */
 4466+	{ 2, 1, 0, 3, 3 }, /* RGFW_formatBGR8 */
 4467+	{ 0, 1, 2, 3, 4 }, /* RGFW_formatRGBA8 */
 4468+	{ 1, 2, 3, 0, 4 }, /* RGFW_formatARGB8 */
 4469+	{ 2, 1, 0, 3, 4 }, /* RGFW_formatBGRA8 */
 4470+	{ 3, 2, 1, 0, 4 }, /* RGFW_formatABGR8 */
 4471+};
 4472+
 4473+
 4474+void RGFW_copyImageData(u8* dest_data, i32 w, i32 h, RGFW_format dest_format, u8* src_data, RGFW_format src_format, RGFW_convertImageDataFunc func) {
 4475+	RGFW_copyImageData64(dest_data, w, h, dest_format, src_data, src_format, RGFW_FALSE, func);
 4476+}
 4477+
 4478+RGFWDEF void RGFW_convertImageData64(u8* dest_data, u8* src_data, const RGFW_colorLayout* srcLayout, const RGFW_colorLayout* destLayout, size_t count, RGFW_bool is64bit);
 4479+void RGFW_convertImageData64(u8* dest_data, u8* src_data, const RGFW_colorLayout* srcLayout, const RGFW_colorLayout* destLayout, size_t count, RGFW_bool is64bit) {
 4480+	u32 i, i2 = 0;
 4481+	u8 rgba[4] = {0};
 4482+
 4483+	for (i = 0; i < count; i++) {
 4484+		const u8* src_px = &src_data[i * srcLayout->channels];
 4485+		u8* dst_px = &dest_data[i2 * destLayout->channels];
 4486+        rgba[0] = src_px[srcLayout->r];
 4487+        rgba[1] = src_px[srcLayout->g];
 4488+        rgba[2] = src_px[srcLayout->b];
 4489+        rgba[3] = (srcLayout->channels == 4) ? src_px[srcLayout->a] : 255;
 4490+
 4491+        dst_px[destLayout->r] = rgba[0];
 4492+        dst_px[destLayout->g] = rgba[1];
 4493+        dst_px[destLayout->b] = rgba[2];
 4494+		if (destLayout->channels == 4)
 4495+			dst_px[destLayout->a] = rgba[3];
 4496+
 4497+		i2 += 1 + is64bit;
 4498+	}
 4499+}
 4500+
 4501+void RGFW_copyImageData64(u8* dest_data, i32 dest_w, i32 dest_h, RGFW_format dest_format, u8* src_data, RGFW_format src_format, RGFW_bool is64bit, RGFW_convertImageDataFunc func) {
 4502+	RGFW_ASSERT(dest_data && src_data);
 4503+
 4504+    u32 count = (u32)(dest_w * dest_h);
 4505+
 4506+	if (src_format == dest_format) {
 4507+		u32 channels = (dest_format >= RGFW_formatRGBA8) ? 4 : 3;
 4508+        RGFW_MEMCPY(dest_data, src_data, count * channels);
 4509+        return;
 4510+    }
 4511+
 4512+    const RGFW_colorLayout* srcLayout  = &RGFW_layouts[src_format];
 4513+    const RGFW_colorLayout* destLayout = &RGFW_layouts[dest_format];
 4514+
 4515+	if (is64bit || func == NULL) {
 4516+		RGFW_convertImageData64(dest_data, src_data, srcLayout, destLayout, count, is64bit);
 4517+	} else {
 4518+		func(dest_data, src_data, srcLayout, destLayout, count);
 4519+	}
 4520+}
 4521+
 4522+RGFW_monitorNode* RGFW_monitors_add(const RGFW_monitor* mon) {
 4523+	RGFW_monitorNode* node = NULL;
 4524+
 4525+	#if (RGFW_PREALLOCATED_MONITORS)
 4526+		node = _RGFW->monitors.freeList.head;
 4527+		if (node) {
 4528+			_RGFW->monitors.freeList.head = node->next;
 4529+			if (_RGFW->monitors.freeList.head == NULL) {
 4530+				_RGFW->monitors.freeList.cur = NULL;
 4531+			}
 4532+		} else
 4533+	#elif !defined(RGFW_NO_ALLOCATE_MONITORS)
 4534+	{
 4535+		node = (RGFW_monitorNode*)RGFW_ALLOC(sizeof(RGFW_monitorNode));
 4536+	}
 4537+	#endif
 4538+
 4539+	if (node == NULL) return NULL;
 4540+
 4541+	node->next = NULL;
 4542+
 4543+	if (_RGFW->monitors.list.head == NULL) {
 4544+		_RGFW->monitors.list.head = node;
 4545+	} else {
 4546+		_RGFW->monitors.list.cur->next = node;
 4547+	}
 4548+
 4549+	_RGFW->monitors.list.cur = node;
 4550+
 4551+	if (mon) node->mon = *mon;
 4552+	node->mon.node = node;
 4553+	node->disconnected = RGFW_FALSE;
 4554+
 4555+	_RGFW->monitors.count += 1;
 4556+	return node;
 4557+}
 4558+
 4559+void RGFW_monitors_remove(RGFW_monitorNode* node, RGFW_monitorNode* prev) {
 4560+	_RGFW->monitors.count -= 1;
 4561+
 4562+	/* remove node from the list */
 4563+	if (prev != node) {
 4564+		prev->next = node->next;
 4565+	} else { /* node is the head */
 4566+		_RGFW->monitors.list.head = NULL;
 4567+	}
 4568+
 4569+	node->next = NULL;
 4570+
 4571+	#if (RGFW_PREALLOCATED_MONITORS)
 4572+	/* check if the monitor was allocated in the heap or not */
 4573+	if (node >= _RGFW->monitors.data && node <= &_RGFW->monitors.data[RGFW_PREALLOCATED_MONITORS - 1]) {
 4574+		/* move node to the free list */
 4575+		if (_RGFW->monitors.freeList.head == NULL) {
 4576+			_RGFW->monitors.freeList.head = node;
 4577+		} else {
 4578+			_RGFW->monitors.freeList.cur->next = node;
 4579+		}
 4580+
 4581+		_RGFW->monitors.freeList.cur = node;
 4582+	} else
 4583+	{
 4584+	#elif !defined(RGFW_NO_ALLOCATE_MONITORS)
 4585+		RGFW_FREE(node);
 4586+	#endif
 4587+	}
 4588+}
 4589+
 4590+void RGFW_monitors_refresh(void) {
 4591+	RGFW_monitorNode* prev = _RGFW->monitors.list.head;
 4592+	for (RGFW_monitorNode* node = _RGFW->monitors.list.head; node; node = node->next) {
 4593+		if (node->disconnected == RGFW_FALSE) continue;
 4594+
 4595+		RGFW_monitorCallback(_RGFW->root, &node->mon, RGFW_FALSE);
 4596+		RGFW_monitors_remove(node, prev);
 4597+		prev = node;
 4598+	}
 4599+}
 4600+
 4601+RGFW_monitorMode* RGFW_monitor_getModes(RGFW_monitor* monitor, size_t* count) {
 4602+	size_t num = RGFW_monitor_getModesPtr(monitor, NULL);
 4603+	RGFW_monitorMode* modes = (RGFW_monitorMode*)RGFW_ALLOC(num * sizeof(RGFW_monitorNode));
 4604+	num = RGFW_monitor_getModesPtr(monitor, &modes);
 4605+
 4606+	if (count) *count = num;
 4607+	return modes;
 4608+}
 4609+
 4610+void RGFW_freeModes(RGFW_monitorMode* modes) {
 4611+	RGFW_FREE(modes);
 4612+}
 4613+
 4614+RGFW_bool RGFW_monitor_findClosestMode(RGFW_monitor* monitor, RGFW_monitorMode* mode, RGFW_monitorMode* closest) {
 4615+	size_t count = RGFW_monitor_getModesPtr(monitor, NULL);
 4616+	RGFW_monitorMode* modes = (RGFW_monitorMode*)RGFW_ALLOC(count * sizeof(RGFW_monitorNode));
 4617+	count = RGFW_monitor_getModesPtr(monitor, &modes);
 4618+
 4619+	RGFW_monitorMode* chosen = NULL;
 4620+
 4621+	u32 topScore = 1;
 4622+	for (size_t i = 0; i < count; i++) {
 4623+		RGFW_monitorMode* mode2 = &modes[i];
 4624+
 4625+		u32 score = 0;
 4626+		if (mode->w == mode2->w && mode->h == mode2->h) score += 1000;
 4627+		if (mode->red == mode2->red && mode->green == mode2->green && mode->blue == mode2->blue) score += 100;
 4628+		if (mode->refreshRate == mode->refreshRate) score += 10;
 4629+
 4630+		if (score > topScore) {
 4631+			topScore = score;
 4632+			chosen = mode2;
 4633+		}
 4634+	}
 4635+
 4636+	if (chosen && closest) *closest = *chosen;
 4637+
 4638+
 4639+	RGFW_FREE(modes);
 4640+
 4641+	return (chosen == NULL) ? RGFW_FALSE : RGFW_TRUE;
 4642+}
 4643+
 4644+RGFW_bool RGFW_monitor_getPosition(RGFW_monitor* monitor, i32* x, i32* y) {
 4645+	if (x) *x = monitor->x;
 4646+	if (y) *y = monitor->y;
 4647+	return RGFW_TRUE;
 4648+}
 4649+
 4650+const char* RGFW_monitor_getName(RGFW_monitor* monitor) {
 4651+	return monitor->name;
 4652+}
 4653+
 4654+RGFW_bool RGFW_monitor_getScale(RGFW_monitor* monitor, float* x, float* y) {
 4655+	if (x) *x = monitor->scaleX;
 4656+	if (y) *y = monitor->scaleY;
 4657+	return RGFW_TRUE;
 4658+}
 4659+
 4660+RGFW_bool RGFW_monitor_getPhysicalSize(RGFW_monitor* monitor, float* w, float* h) {
 4661+	if (w) *w = monitor->physW;
 4662+	if (h) *h = monitor->physH;
 4663+	return RGFW_TRUE;
 4664+}
 4665+
 4666+void RGFW_monitor_setUserPtr(RGFW_monitor* monitor, void* userPtr) {
 4667+	monitor->userPtr = userPtr;
 4668+}
 4669+
 4670+void* RGFW_monitor_getUserPtr(RGFW_monitor* monitor) {
 4671+	return monitor->userPtr;
 4672+}
 4673+
 4674+RGFW_bool RGFW_monitor_getMode(RGFW_monitor* monitor, RGFW_monitorMode* mode) {
 4675+	if (mode) *mode = monitor->mode;
 4676+	return RGFW_TRUE;
 4677+}
 4678+
 4679+RGFW_gammaRamp* RGFW_monitor_getGammaRamp(RGFW_monitor* monitor) {
 4680+	RGFW_gammaRamp* ramp = (RGFW_gammaRamp*)RGFW_ALLOC(sizeof(RGFW_gammaRamp));
 4681+	ramp->count = RGFW_monitor_getGammaRampPtr(monitor, NULL);
 4682+	ramp->red = (u16*)RGFW_ALLOC(sizeof(u16) * ramp->count);
 4683+	ramp->green = (u16*)RGFW_ALLOC(sizeof(u16) * ramp->count);
 4684+	ramp->blue = (u16*)RGFW_ALLOC(sizeof(u16) * ramp->count);
 4685+	ramp->count = RGFW_monitor_getGammaRampPtr(monitor, ramp);
 4686+
 4687+	return ramp;
 4688+}
 4689+
 4690+void RGFW_freeGammaRamp(RGFW_gammaRamp* ramp) {
 4691+	RGFW_FREE(ramp->red);
 4692+	RGFW_FREE(ramp->green);
 4693+	RGFW_FREE(ramp->blue);
 4694+	RGFW_FREE(ramp);
 4695+}
 4696+
 4697+RGFW_bool RGFW_monitor_setGammaPtr(RGFW_monitor* monitor, float gamma, u16* ptr, size_t count) {
 4698+	RGFW_ASSERT(monitor);
 4699+    RGFW_ASSERT(gamma > 0.0f);
 4700+
 4701+	size_t i;
 4702+    for (i = 0;  i < count;  i++) {
 4703+        float value = (float)i / (float) (count - 1);
 4704+		#ifndef RGFW_NO_MATH
 4705+			value = powf(value, 1.f / gamma) * 65535.f + 0.5f;
 4706+		#endif
 4707+        value = RGFW_MIN(value, 65535.f);
 4708+
 4709+        ptr[i] = (u16)value;
 4710+    }
 4711+
 4712+    RGFW_gammaRamp ramp;
 4713+    ramp.red = ptr;
 4714+    ramp.green = ptr;
 4715+    ramp.blue = ptr;
 4716+    ramp.count = count;
 4717+
 4718+    return RGFW_monitor_setGammaRamp(monitor, &ramp);
 4719+}
 4720+
 4721+RGFW_bool RGFW_monitor_setGamma(RGFW_monitor* monitor, float gamma) {
 4722+	size_t count = RGFW_monitor_getGammaRampPtr(monitor, NULL);
 4723+	u16* ptr = (u16*)RGFW_ALLOC(count * sizeof(u16));
 4724+
 4725+	RGFW_bool ret = RGFW_monitor_setGammaPtr(monitor, gamma, ptr, count);
 4726+	RGFW_FREE(ptr);
 4727+
 4728+	return ret;
 4729+}
 4730+
 4731+RGFW_monitor** RGFW_getMonitors(size_t* len) {
 4732+	if (len != NULL) *len = 0;
 4733+
 4734+	size_t count = 0;
 4735+	if (RGFW_getMonitorsPtr(0, NULL, &count) == RGFW_FALSE || count == 0) return NULL;
 4736+
 4737+	RGFW_monitor** monitors = (RGFW_monitor**)RGFW_ALLOC(sizeof(RGFW_monitor*) * count);
 4738+
 4739+	if (RGFW_getMonitorsPtr(count, monitors, &count) == RGFW_FALSE) {
 4740+		RGFW_FREE(monitors);
 4741+		return NULL;
 4742+	}
 4743+
 4744+	if (len != NULL) *len = count;
 4745+
 4746+	return monitors;
 4747+}
 4748+
 4749+RGFW_bool RGFW_getMonitorsPtr(size_t max, RGFW_monitor** monitors, size_t* len) {
 4750+	RGFW_init();
 4751+	if (len != NULL) {
 4752+		*len = _RGFW->monitors.count;
 4753+	}
 4754+
 4755+	if (monitors == NULL || max == 0) return RGFW_TRUE;
 4756+
 4757+
 4758+	if (len != NULL) {
 4759+		*len = max;
 4760+	}
 4761+
 4762+	size_t i = 0;
 4763+	RGFW_monitorNode* cur_node = _RGFW->monitors.list.head;
 4764+	while (cur_node != NULL && i < max) {
 4765+		monitors[i] = &cur_node->mon;
 4766+		i++;
 4767+		cur_node = cur_node->next;
 4768+	}
 4769+
 4770+	return RGFW_TRUE;
 4771+}
 4772+
 4773+RGFW_monitor* RGFW_getPrimaryMonitor(void) {
 4774+	if (_RGFW->monitors.primary == NULL) {
 4775+		_RGFW->monitors.primary = _RGFW->monitors.list.head;
 4776+	}
 4777+
 4778+	return &_RGFW->monitors.primary->mon;
 4779+}
 4780+
 4781+RGFW_bool RGFW_window_setIcon(RGFW_window* win, u8* data, i32 w, i32 h, RGFW_format format) {
 4782+	return RGFW_window_setIconEx(win, data, w, h, format, RGFW_iconBoth);
 4783+}
 4784+
 4785+void RGFW_window_captureMouse(RGFW_window* win, RGFW_bool state) {
 4786+	win->internal.captureMouse = state;
 4787+	RGFW_window_captureMousePlatform(win, state);
 4788+}
 4789+
 4790+void RGFW_window_setRawMouseMode(RGFW_window* win, RGFW_bool state) {
 4791+	win->internal.rawMouse = state;
 4792+	RGFW_window_setRawMouseModePlatform(win, state);
 4793+}
 4794+
 4795+void RGFW_window_captureRawMouse(RGFW_window* win, RGFW_bool state) {
 4796+	RGFW_window_captureMouse(win, state);
 4797+	RGFW_window_setRawMouseMode(win, state);
 4798+}
 4799+
 4800+RGFW_bool RGFW_window_isRawMouseMode(RGFW_window* win) { return RGFW_BOOL(win->internal.rawMouse); }
 4801+RGFW_bool RGFW_window_isCaptured(RGFW_window* win) { return RGFW_BOOL(win->internal.captureMouse);  }
 4802+
 4803+void RGFW_keyUpdateKeyMod(RGFW_window* win, RGFW_keymod mod, RGFW_bool value) {
 4804+	if (value) win->internal.mod |= mod;
 4805+	else win->internal.mod &= ~mod;
 4806+}
 4807+
 4808+void RGFW_keyUpdateKeyModsEx(RGFW_window* win, RGFW_bool capital, RGFW_bool numlock, RGFW_bool control, RGFW_bool alt, RGFW_bool shift, RGFW_bool super, RGFW_bool scroll) {
 4809+	RGFW_keyUpdateKeyMod(win, RGFW_modCapsLock, capital);
 4810+	RGFW_keyUpdateKeyMod(win, RGFW_modNumLock, numlock);
 4811+	RGFW_keyUpdateKeyMod(win, RGFW_modControl, control);
 4812+	RGFW_keyUpdateKeyMod(win, RGFW_modAlt, alt);
 4813+	RGFW_keyUpdateKeyMod(win, RGFW_modShift, shift);
 4814+	RGFW_keyUpdateKeyMod(win, RGFW_modSuper, super);
 4815+	RGFW_keyUpdateKeyMod(win, RGFW_modScrollLock, scroll);
 4816+}
 4817+
 4818+void RGFW_keyUpdateKeyMods(RGFW_window* win, RGFW_bool capital, RGFW_bool numlock, RGFW_bool scroll) {
 4819+	RGFW_keyUpdateKeyModsEx(win, capital, numlock,
 4820+					RGFW_isKeyDown(RGFW_keyControlL) || RGFW_isKeyDown(RGFW_keyControlR),
 4821+					RGFW_isKeyDown(RGFW_keyAltL) || RGFW_isKeyDown(RGFW_keyAltR),
 4822+					RGFW_isKeyDown(RGFW_keyShiftL) || RGFW_isKeyDown(RGFW_keyShiftR),
 4823+					RGFW_isKeyDown(RGFW_keySuperL) || RGFW_isKeyDown(RGFW_keySuperR),
 4824+					scroll);
 4825+}
 4826+
 4827+void RGFW_window_showMouseFlags(RGFW_window* win, RGFW_bool show) {
 4828+	if (show && (win->internal.flags & RGFW_windowHideMouse))
 4829+		win->internal.flags ^= RGFW_windowHideMouse;
 4830+	else if (!show && !(win->internal.flags & RGFW_windowHideMouse))
 4831+		win->internal.flags |= RGFW_windowHideMouse;
 4832+}
 4833+
 4834+RGFW_bool RGFW_window_isMouseHidden(RGFW_window* win) {
 4835+	return (RGFW_bool)RGFW_BOOL(((RGFW_window*)win)->internal.flags & RGFW_windowHideMouse);
 4836+}
 4837+
 4838+RGFW_bool RGFW_window_borderless(RGFW_window* win) {
 4839+	return (RGFW_bool)RGFW_BOOL(win->internal.flags & RGFW_windowNoBorder);
 4840+}
 4841+
 4842+RGFW_bool RGFW_window_isFullscreen(RGFW_window* win){ return RGFW_BOOL(win->internal.flags & RGFW_windowFullscreen); }
 4843+RGFW_bool RGFW_window_allowsDND(RGFW_window* win) { return RGFW_BOOL(win->internal.flags & RGFW_windowAllowDND); }
 4844+
 4845+RGFW_bool RGFW_window_setMouseDefault(RGFW_window* win) {
 4846+	return RGFW_window_setMouseStandard(win, RGFW_mouseNormal);
 4847+}
 4848+
 4849+RGFW_bool RGFW_window_setMouseStandard(RGFW_window* win, RGFW_mouseIcon icon) {
 4850+	RGFW_ASSERT(win);
 4851+	RGFW_ASSERT(icon < RGFW_mouseIconCount);
 4852+	return RGFW_window_setMouse(win, _RGFW->standardMice[icon]);
 4853+}
 4854+
 4855+RGFW_bool RGFW_window_setMouse(RGFW_window* win, RGFW_mouse* mouse) {
 4856+	RGFW_ASSERT(win && mouse);
 4857+	if (mouse != _RGFW->hiddenMouse) {
 4858+		win->internal.mouse = mouse;
 4859+	}
 4860+
 4861+	return RGFW_window_setMousePlatform(win, mouse);
 4862+}
 4863+
 4864+#ifndef RGFW_WINDOWS
 4865+void RGFW_window_setDND(RGFW_window* win, RGFW_bool allow) {
 4866+	RGFW_setBit(&win->internal.flags, RGFW_windowAllowDND, allow);
 4867+}
 4868+#endif
 4869+
 4870+#if defined(RGFW_X11) || defined(RGFW_MACOS) || defined(RGFW_WASM) || defined(RGFW_WAYLAND)
 4871+#ifndef __USE_POSIX199309
 4872+	#define __USE_POSIX199309
 4873+#endif
 4874+#include <time.h>
 4875+struct timespec;
 4876+#endif
 4877+
 4878+#if defined(RGFW_WAYLAND) || defined(RGFW_X11) || defined(RGFW_WINDOWS)
 4879+void RGFW_window_showMouse(RGFW_window* win, RGFW_bool show) {
 4880+	RGFW_window_showMouseFlags(win, show);
 4881+	if (show == RGFW_FALSE) {
 4882+		RGFW_window_setMouse(win, _RGFW->hiddenMouse);
 4883+	} else {
 4884+		RGFW_window_setMouse(win, win->internal.mouse);
 4885+	}
 4886+}
 4887+#endif
 4888+
 4889+#ifndef RGFW_MACOS
 4890+void RGFW_moveToMacOSResourceDir(void) { }
 4891+#endif
 4892+
 4893+RGFWDEF RGFW_bool RGFW_isLatin(const char *string, size_t length);
 4894+RGFW_bool RGFW_isLatin(const char *string, size_t length) {
 4895+	for (size_t i = 0; i < length; i++) {
 4896+        if ((u8)string[i] >= 0x80) {
 4897+            return RGFW_TRUE;
 4898+        }
 4899+    }
 4900+    return RGFW_FALSE;
 4901+}
 4902+
 4903+RGFWDEF u32 RGFW_decodeUTF8(const char* string, size_t* starting_index);
 4904+u32 RGFW_decodeUTF8(const char* string, size_t* starting_index) {
 4905+    static const u32 offsets[] = {
 4906+        0x00000000u, 0x00003080u, 0x000e2080u,
 4907+        0x03c82080u, 0xfa082080u, 0x82082080u
 4908+    };
 4909+
 4910+    u32 codepoint = (u8)string[(*starting_index)];
 4911+	size_t count;
 4912+	for (count = 1; (string[count + (*starting_index)] & 0xc0) == 0x80; count++) {
 4913+        codepoint = (codepoint << 6) + (u8)string[count + (*starting_index)];
 4914+	}
 4915+
 4916+	*starting_index += count;
 4917+
 4918+    RGFW_ASSERT(count <= 6);
 4919+    return codepoint - offsets[count - 1];
 4920+}
 4921+
 4922+/*
 4923+	graphics API specific code (end of generic code)
 4924+	starts here
 4925+*/
 4926+
 4927+
 4928+/*
 4929+	OpenGL defines start here   (Normal, EGL, OSMesa)
 4930+*/
 4931+
 4932+#if defined(RGFW_OPENGL)
 4933+/* EGL, OpenGL */
 4934+#define RGFW_DEFAULT_GL_HINTS { \
 4935+	/* Stencil         */ 0, \
 4936+	/* Samples         */ 0, \
 4937+	/* Stereo          */ RGFW_FALSE, \
 4938+	/* AuxBuffers      */ 0, \
 4939+	/* DoubleBuffer    */ RGFW_TRUE, \
 4940+	/* Red             */ 8, \
 4941+	/* Green           */ 8, \
 4942+	/* Blue            */ 8, \
 4943+	/* Alpha           */ 8, \
 4944+	/* Depth           */ 24, \
 4945+	/* AccumRed        */ 0, \
 4946+	/* AccumGreen      */ 0, \
 4947+	/* AccumBlue       */ 0, \
 4948+	/* AccumAlpha      */ 0, \
 4949+	/* SRGB            */ RGFW_FALSE, \
 4950+	/* Robustness      */ RGFW_FALSE, \
 4951+	/* Debug           */ RGFW_FALSE, \
 4952+	/* NoError         */ RGFW_FALSE, \
 4953+	/* ReleaseBehavior */ RGFW_glReleaseNone, \
 4954+	/* Profile         */ RGFW_glCore, \
 4955+	/* Major           */ 1, \
 4956+	/* Minor           */ 0, \
 4957+	/* Share */ NULL, \
 4958+	/* Share_EGL */ NULL, \
 4959+	/* renderer */ RGFW_glAccelerated \
 4960+}
 4961+
 4962+RGFW_glHints RGFW_globalHints_OpenGL_SRC = RGFW_DEFAULT_GL_HINTS;
 4963+RGFW_glHints* RGFW_globalHints_OpenGL = &RGFW_globalHints_OpenGL_SRC;
 4964+
 4965+void RGFW_resetGlobalHints_OpenGL(void) {
 4966+#if !defined(__cplusplus) || defined(RGFW_MACOS)
 4967+	RGFW_globalHints_OpenGL_SRC = (RGFW_glHints)RGFW_DEFAULT_GL_HINTS;
 4968+#else
 4969+	RGFW_globalHints_OpenGL_SRC = RGFW_DEFAULT_GL_HINTS;
 4970+#endif
 4971+}
 4972+void RGFW_setGlobalHints_OpenGL(RGFW_glHints* hints) { RGFW_globalHints_OpenGL = hints;  }
 4973+RGFW_glHints* RGFW_getGlobalHints_OpenGL(void) { RGFW_init(); return RGFW_globalHints_OpenGL; }
 4974+
 4975+
 4976+void* RGFW_glContext_getSourceContext(RGFW_glContext* ctx) {
 4977+	RGFW_UNUSED(ctx);
 4978+
 4979+#ifdef RGFW_WAYLAND
 4980+	if (RGFW_usingWayland()) return (void*)ctx->egl.ctx;
 4981+#endif
 4982+
 4983+#if defined(RGFW_X11)
 4984+	return (void*)ctx->ctx;
 4985+#else
 4986+	return NULL;
 4987+#endif
 4988+}
 4989+
 4990+RGFW_glContext* RGFW_window_createContext_OpenGL(RGFW_window* win, RGFW_glHints* hints) {
 4991+	#ifdef RGFW_WAYLAND
 4992+	if (RGFW_usingWayland()) {
 4993+		return (RGFW_glContext*)RGFW_window_createContext_EGL(win, hints);
 4994+	}
 4995+	#endif
 4996+	RGFW_glContext* ctx = (RGFW_glContext*)RGFW_ALLOC(sizeof(RGFW_glContext));
 4997+	if (RGFW_window_createContextPtr_OpenGL(win, ctx, hints) == RGFW_FALSE) {
 4998+		RGFW_FREE(ctx);
 4999+		win->src.ctx.native = NULL;
 5000+		return NULL;
 5001+	}
 5002+	win->src.gfxType |= RGFW_gfxOwnedByRGFW;
 5003+	return ctx;
 5004+}
 5005+
 5006+RGFW_glContext* RGFW_window_getContext_OpenGL(RGFW_window* win) {
 5007+	if (win->src.gfxType & RGFW_windowEGL) return NULL;
 5008+	return win->src.ctx.native;
 5009+}
 5010+
 5011+void RGFW_window_deleteContext_OpenGL(RGFW_window* win, RGFW_glContext* ctx) {
 5012+	RGFW_window_deleteContextPtr_OpenGL(win, ctx);
 5013+	if (win->src.gfxType & RGFW_gfxOwnedByRGFW) RGFW_FREE(ctx);
 5014+}
 5015+
 5016+RGFW_bool RGFW_extensionSupportedStr(const char* extensions, const char* ext, size_t len) {
 5017+    const char *start = extensions;
 5018+    const char *where;
 5019+    const char* terminator;
 5020+
 5021+    if (extensions == NULL || ext == NULL) {
 5022+        return RGFW_FALSE;
 5023+	}
 5024+
 5025+	while (ext[len - 1] == '\0' && len > 3) {
 5026+		len--;
 5027+	}
 5028+
 5029+    where = RGFW_STRSTR(extensions, ext);
 5030+    while (where) {
 5031+		terminator = where + len;
 5032+        if ((where == start || *(where - 1) == ' ') &&
 5033+            (*terminator == ' ' || *terminator == '\0')) {
 5034+			return RGFW_TRUE;
 5035+        }
 5036+        where = RGFW_STRSTR(terminator, ext);
 5037+    }
 5038+
 5039+    return RGFW_FALSE;
 5040+}
 5041+
 5042+RGFWDEF RGFW_bool RGFW_extensionSupported_base(const char* extension, size_t len);
 5043+RGFW_bool RGFW_extensionSupported_base(const char* extension, size_t len) {
 5044+    #ifdef GL_NUM_EXTENSIONS
 5045+    if (RGFW_globalHints_OpenGL->major >= 3) {
 5046+        i32 i;
 5047+
 5048+        GLint count = 0;
 5049+
 5050+        RGFW_proc RGFW_glGetStringi = RGFW_getProcAddress_OpenGL("glGetStringi");
 5051+        RGFW_proc RGFW_glGetIntegerv = RGFW_getProcAddress_OpenGL("glGetIntegerv");
 5052+		if (RGFW_glGetIntegerv)
 5053+            ((void(*)(GLenum, GLint*))RGFW_glGetIntegerv)(GL_NUM_EXTENSIONS, &count);
 5054+
 5055+        for (i = 0; RGFW_glGetStringi && i < count;  i++) {
 5056+            const char* en = ((const char* (*)(u32, u32))RGFW_glGetStringi)(GL_EXTENSIONS, (u32)i);
 5057+            if (en && RGFW_STRNCMP(en, extension, len) == 0) {
 5058+				return RGFW_TRUE;
 5059+			}
 5060+        }
 5061+    } else
 5062+#endif
 5063+    {
 5064+        RGFW_proc RGFW_glGetString = RGFW_getProcAddress_OpenGL("glGetString");
 5065+		#define RGFW_GL_EXTENSIONS 0x1F03
 5066+        if (RGFW_glGetString) {
 5067+            const char* extensions = ((const char*(*)(u32))RGFW_glGetString)(RGFW_GL_EXTENSIONS);
 5068+
 5069+            if ((extensions != NULL) && RGFW_extensionSupportedStr(extensions, extension, len)) {
 5070+				return RGFW_TRUE;
 5071+			}
 5072+        }
 5073+    }
 5074+	return RGFW_FALSE;
 5075+}
 5076+
 5077+RGFW_bool RGFW_extensionSupported_OpenGL(const char* extension, size_t len) {
 5078+	if (RGFW_extensionSupported_base(extension, len))  return RGFW_TRUE;
 5079+    return RGFW_extensionSupportedPlatform_OpenGL(extension, len);
 5080+}
 5081+
 5082+void RGFW_window_makeCurrentWindow_OpenGL(RGFW_window* win) {
 5083+	if (win) {
 5084+		_RGFW->current = win;
 5085+	}
 5086+
 5087+    RGFW_window_makeCurrentContext_OpenGL(win);
 5088+}
 5089+
 5090+RGFW_window* RGFW_getCurrentWindow_OpenGL(void) { return _RGFW->current; }
 5091+void RGFW_attribStack_init(RGFW_attribStack* stack, i32* attribs, size_t max) { stack->attribs = attribs; stack->count = 0; stack->max = max; }
 5092+void RGFW_attribStack_pushAttrib(RGFW_attribStack* stack, i32 attrib) {
 5093+	RGFW_ASSERT(stack->count < stack->max);
 5094+	stack->attribs[stack->count] = attrib;
 5095+	stack->count += 1;
 5096+}
 5097+void RGFW_attribStack_pushAttribs(RGFW_attribStack* stack, i32 attrib1, i32 attrib2) {
 5098+	RGFW_attribStack_pushAttrib(stack, attrib1);
 5099+	RGFW_attribStack_pushAttrib(stack, attrib2);
 5100+}
 5101+
 5102+/* EGL */
 5103+#ifdef RGFW_EGL
 5104+#include <EGL/egl.h>
 5105+
 5106+PFNEGLINITIALIZEPROC RGFW_eglInitialize;
 5107+PFNEGLGETCONFIGSPROC RGFW_eglGetConfigs;
 5108+PFNEGLCHOOSECONFIGPROC RGFW_eglChooseConfig;
 5109+PFNEGLCREATEWINDOWSURFACEPROC RGFW_eglCreateWindowSurface;
 5110+PFNEGLCREATECONTEXTPROC RGFW_eglCreateContext;
 5111+PFNEGLMAKECURRENTPROC RGFW_eglMakeCurrent;
 5112+PFNEGLGETDISPLAYPROC RGFW_eglGetDisplay;
 5113+PFNEGLSWAPBUFFERSPROC RGFW_eglSwapBuffers;
 5114+PFNEGLSWAPINTERVALPROC RGFW_eglSwapInterval;
 5115+PFNEGLBINDAPIPROC RGFW_eglBindAPI;
 5116+PFNEGLDESTROYCONTEXTPROC RGFW_eglDestroyContext;
 5117+PFNEGLTERMINATEPROC RGFW_eglTerminate;
 5118+PFNEGLDESTROYSURFACEPROC RGFW_eglDestroySurface;
 5119+PFNEGLGETCURRENTCONTEXTPROC RGFW_eglGetCurrentContext;
 5120+PFNEGLGETPROCADDRESSPROC RGFW_eglGetProcAddress = NULL;
 5121+PFNEGLQUERYSTRINGPROC RGFW_eglQueryString;
 5122+PFNEGLGETCONFIGATTRIBPROC RGFW_eglGetConfigAttrib;
 5123+
 5124+#define EGL_SURFACE_MAJOR_VERSION_KHR 0x3098
 5125+#define EGL_SURFACE_MINOR_VERSION_KHR 0x30fb
 5126+
 5127+#ifdef RGFW_WINDOWS
 5128+    #include <windows.h>
 5129+#elif defined(RGFW_MACOS) || defined(RGFW_UNIX)
 5130+    #include <dlfcn.h>
 5131+#endif
 5132+
 5133+#ifdef RGFW_WAYLAND
 5134+#include <wayland-egl.h>
 5135+#endif
 5136+
 5137+void* RGFW_eglLibHandle = NULL;
 5138+
 5139+void* RGFW_getDisplay_EGL(void) { return _RGFW->EGL_display; }
 5140+void* RGFW_eglContext_getSourceContext(RGFW_eglContext* ctx) { return ctx->ctx; }
 5141+void* RGFW_eglContext_getSurface(RGFW_eglContext* ctx) { return ctx->surface; }
 5142+struct wl_egl_window* RGFW_eglContext_wlEGLWindow(RGFW_eglContext* ctx) { return ctx->eglWindow; }
 5143+
 5144+RGFW_bool RGFW_loadEGL(void) {
 5145+	RGFW_init();
 5146+	if (RGFW_eglGetProcAddress != NULL) {
 5147+		return RGFW_TRUE;
 5148+	}
 5149+
 5150+#ifndef RGFW_WASM
 5151+	#ifdef RGFW_WINDOWS
 5152+		const char* libNames[] = { "libEGL.dll", "EGL.dll" };
 5153+	#elif defined(RGFW_MACOS) || defined(RGFW_UNIX)
 5154+		/* Linux and macOS */
 5155+		const char* libNames[] = {
 5156+			"libEGL.so.1",  /* most common */
 5157+			"libEGL.so",    /* fallback */
 5158+			"/System/Library/Frameworks/OpenGL.framework/OpenGL"  /* fallback for older macOS EGL-like systems */
 5159+		};
 5160+	#endif
 5161+
 5162+	for (size_t i = 0; i < sizeof(libNames) / sizeof(libNames[0]); i++) {
 5163+		#ifdef RGFW_WINDOWS
 5164+			RGFW_eglLibHandle = (void*)LoadLibraryA(libNames[i]);
 5165+			if (RGFW_eglLibHandle) {
 5166+				RGFW_eglGetProcAddress = (PFNEGLGETPROCADDRESSPROC)(RGFW_proc)GetProcAddress((HMODULE)RGFW_eglLibHandle, "eglGetProcAddress");
 5167+				break;
 5168+			}
 5169+		#elif defined(RGFW_MACOS) || defined(RGFW_UNIX)
 5170+			RGFW_eglLibHandle = dlopen(libNames[i], RTLD_LAZY | RTLD_GLOBAL);
 5171+			if (RGFW_eglLibHandle) {
 5172+				void* lib = dlsym(RGFW_eglLibHandle, "eglGetProcAddress");
 5173+				if (lib != NULL) RGFW_MEMCPY(&RGFW_eglGetProcAddress, &lib, sizeof(PFNEGLGETPROCADDRESSPROC));
 5174+				break;
 5175+			}
 5176+		#endif
 5177+	}
 5178+
 5179+	if (!RGFW_eglLibHandle || !RGFW_eglGetProcAddress) {
 5180+		return RGFW_FALSE;
 5181+	}
 5182+
 5183+	RGFW_eglInitialize = (PFNEGLINITIALIZEPROC) RGFW_eglGetProcAddress("eglInitialize");
 5184+	RGFW_eglGetConfigs = (PFNEGLGETCONFIGSPROC) RGFW_eglGetProcAddress("eglGetConfigs");
 5185+	RGFW_eglChooseConfig = (PFNEGLCHOOSECONFIGPROC) RGFW_eglGetProcAddress("eglChooseConfig");
 5186+	RGFW_eglCreateWindowSurface = (PFNEGLCREATEWINDOWSURFACEPROC) RGFW_eglGetProcAddress("eglCreateWindowSurface");
 5187+	RGFW_eglCreateContext = (PFNEGLCREATECONTEXTPROC) RGFW_eglGetProcAddress("eglCreateContext");
 5188+	RGFW_eglMakeCurrent = (PFNEGLMAKECURRENTPROC) RGFW_eglGetProcAddress("eglMakeCurrent");
 5189+	RGFW_eglGetDisplay = (PFNEGLGETDISPLAYPROC) RGFW_eglGetProcAddress("eglGetDisplay");
 5190+	RGFW_eglSwapBuffers = (PFNEGLSWAPBUFFERSPROC) RGFW_eglGetProcAddress("eglSwapBuffers");
 5191+	RGFW_eglSwapInterval = (PFNEGLSWAPINTERVALPROC) RGFW_eglGetProcAddress("eglSwapInterval");
 5192+	RGFW_eglBindAPI = (PFNEGLBINDAPIPROC) RGFW_eglGetProcAddress("eglBindAPI");
 5193+	RGFW_eglDestroyContext = (PFNEGLDESTROYCONTEXTPROC) RGFW_eglGetProcAddress("eglDestroyContext");
 5194+	RGFW_eglTerminate = (PFNEGLTERMINATEPROC) RGFW_eglGetProcAddress("eglTerminate");
 5195+	RGFW_eglDestroySurface = (PFNEGLDESTROYSURFACEPROC) RGFW_eglGetProcAddress("eglDestroySurface");
 5196+	RGFW_eglQueryString = (PFNEGLQUERYSTRINGPROC) RGFW_eglGetProcAddress("eglQueryString");
 5197+	RGFW_eglGetCurrentContext = (PFNEGLGETCURRENTCONTEXTPROC) RGFW_eglGetProcAddress("eglGetCurrentContext");
 5198+	RGFW_eglGetConfigAttrib = (PFNEGLGETCONFIGATTRIBPROC) RGFW_eglGetProcAddress("eglGetConfigAttrib");
 5199+
 5200+#else
 5201+	RGFW_eglGetProcAddress = eglGetProcAddress;
 5202+	RGFW_eglInitialize = (PFNEGLINITIALIZEPROC) eglInitialize;
 5203+	RGFW_eglGetConfigs = (PFNEGLGETCONFIGSPROC) eglGetConfigs;
 5204+	RGFW_eglChooseConfig = (PFNEGLCHOOSECONFIGPROC) eglChooseConfig;
 5205+	RGFW_eglCreateWindowSurface = (PFNEGLCREATEWINDOWSURFACEPROC) eglCreateWindowSurface;
 5206+	RGFW_eglCreateContext = (PFNEGLCREATECONTEXTPROC) eglCreateContext;
 5207+	RGFW_eglMakeCurrent = (PFNEGLMAKECURRENTPROC) eglMakeCurrent;
 5208+	RGFW_eglGetDisplay = (PFNEGLGETDISPLAYPROC) eglGetDisplay;
 5209+	RGFW_eglSwapBuffers = (PFNEGLSWAPBUFFERSPROC) eglSwapBuffers;
 5210+	RGFW_eglSwapInterval = (PFNEGLSWAPINTERVALPROC) eglSwapInterval;
 5211+	RGFW_eglBindAPI = (PFNEGLBINDAPIPROC) eglBindAPI;
 5212+	RGFW_eglDestroyContext = (PFNEGLDESTROYCONTEXTPROC) eglDestroyContext;
 5213+	RGFW_eglTerminate = (PFNEGLTERMINATEPROC) eglTerminate;
 5214+	RGFW_eglDestroySurface = (PFNEGLDESTROYSURFACEPROC) eglDestroySurface;
 5215+	RGFW_eglQueryString = (PFNEGLQUERYSTRINGPROC) eglQueryString;
 5216+	RGFW_eglGetCurrentContext = (PFNEGLGETCURRENTCONTEXTPROC) eglGetCurrentContext;
 5217+	RGFW_eglGetConfigAttrib = (PFNEGLGETCONFIGATTRIBPROC)eglGetConfigAttrib;
 5218+#endif
 5219+
 5220+	RGFW_bool out = RGFW_BOOL(RGFW_eglInitialize!= NULL &&
 5221+	            RGFW_eglGetConfigs!= NULL &&
 5222+	            RGFW_eglChooseConfig!= NULL &&
 5223+	            RGFW_eglCreateWindowSurface!= NULL &&
 5224+	            RGFW_eglCreateContext!= NULL &&
 5225+	            RGFW_eglMakeCurrent!= NULL &&
 5226+	            RGFW_eglGetDisplay!= NULL &&
 5227+	            RGFW_eglSwapBuffers!= NULL &&
 5228+	            RGFW_eglSwapInterval != NULL &&
 5229+	            RGFW_eglBindAPI!= NULL &&
 5230+	            RGFW_eglDestroyContext!= NULL &&
 5231+	            RGFW_eglTerminate!= NULL &&
 5232+	            RGFW_eglDestroySurface!= NULL &&
 5233+				RGFW_eglQueryString != NULL &&
 5234+				RGFW_eglGetCurrentContext != NULL &&
 5235+				RGFW_eglGetConfigAttrib != NULL);
 5236+
 5237+	if (out) {
 5238+		#ifdef RGFW_WINDOWS
 5239+		HDC dc = GetDC(NULL);
 5240+		_RGFW->EGL_display = RGFW_eglGetDisplay((EGLNativeDisplayType) dc);
 5241+		ReleaseDC(NULL, dc);
 5242+		#elif defined(RGFW_WAYLAND)
 5243+		if (_RGFW->useWaylandBool)
 5244+			_RGFW->EGL_display = RGFW_eglGetDisplay((EGLNativeDisplayType) _RGFW->wl_display);
 5245+		else
 5246+		#endif
 5247+		#ifdef RGFW_X11
 5248+			_RGFW->EGL_display = RGFW_eglGetDisplay((EGLNativeDisplayType) _RGFW->display);
 5249+		#else
 5250+		{}
 5251+		#endif
 5252+		#if !defined(RGFW_WAYLAND) && !defined(RGFW_WINDOWS) && !defined(RGFW_X11)
 5253+		_RGFW->EGL_display = RGFW_eglGetDisplay(EGL_DEFAULT_DISPLAY);
 5254+		#endif
 5255+	}
 5256+
 5257+	RGFW_eglInitialize(_RGFW->EGL_display, NULL, NULL);
 5258+	return out;
 5259+}
 5260+
 5261+
 5262+void RGFW_unloadEGL(void) {
 5263+	if (!RGFW_eglLibHandle) return;
 5264+	RGFW_eglTerminate(_RGFW->EGL_display);
 5265+	#ifdef RGFW_WINDOWS
 5266+	    FreeLibrary((HMODULE)RGFW_eglLibHandle);
 5267+	#elif defined(RGFW_MACOS) || defined(RGFW_UNIX)
 5268+	    dlclose(RGFW_eglLibHandle);
 5269+	#endif
 5270+
 5271+    RGFW_eglLibHandle = NULL;
 5272+    RGFW_eglGetProcAddress = NULL;
 5273+}
 5274+
 5275+RGFW_bool RGFW_window_createContextPtr_EGL(RGFW_window* win, RGFW_eglContext* ctx, RGFW_glHints* hints) {
 5276+	if (RGFW_loadEGL() == RGFW_FALSE) return RGFW_FALSE;
 5277+	win->src.ctx.egl = ctx;
 5278+	win->src.gfxType = RGFW_gfxEGL;
 5279+
 5280+#ifdef RGFW_WAYLAND
 5281+    if (_RGFW->useWaylandBool)
 5282+        win->src.ctx.egl->eglWindow = wl_egl_window_create(win->src.surface, win->w, win->h);
 5283+#endif
 5284+
 5285+	#ifndef EGL_OPENGL_ES1_BIT
 5286+	#define EGL_OPENGL_ES1_BIT 0x1
 5287+	#endif
 5288+
 5289+	EGLint egl_config[24];
 5290+
 5291+	{
 5292+		RGFW_attribStack stack;
 5293+		RGFW_attribStack_init(&stack, egl_config, 24);
 5294+
 5295+		RGFW_attribStack_pushAttribs(&stack, EGL_SURFACE_TYPE, EGL_WINDOW_BIT);
 5296+		RGFW_attribStack_pushAttrib(&stack, EGL_RENDERABLE_TYPE);
 5297+
 5298+		if (hints->profile == RGFW_glES) {
 5299+			switch (hints->major) {
 5300+				case 1: RGFW_attribStack_pushAttrib(&stack, EGL_OPENGL_ES1_BIT); break;
 5301+				case 2: RGFW_attribStack_pushAttrib(&stack, EGL_OPENGL_ES2_BIT); break;
 5302+				case 3: RGFW_attribStack_pushAttrib(&stack, EGL_OPENGL_ES3_BIT); break;
 5303+				default: break;
 5304+			}
 5305+		} else {
 5306+			RGFW_attribStack_pushAttrib(&stack, EGL_OPENGL_BIT);
 5307+		}
 5308+
 5309+		RGFW_attribStack_pushAttribs(&stack, EGL_RED_SIZE, hints->red);
 5310+		RGFW_attribStack_pushAttribs(&stack, EGL_GREEN_SIZE, hints->green);
 5311+		RGFW_attribStack_pushAttribs(&stack, EGL_BLUE_SIZE, hints->blue);
 5312+		RGFW_attribStack_pushAttribs(&stack, EGL_ALPHA_SIZE, hints->alpha);
 5313+		RGFW_attribStack_pushAttribs(&stack, EGL_DEPTH_SIZE, hints->depth);
 5314+
 5315+		RGFW_attribStack_pushAttribs(&stack, EGL_STENCIL_SIZE, hints->stencil);
 5316+		if (hints->samples) {
 5317+			RGFW_attribStack_pushAttribs(&stack, EGL_SAMPLE_BUFFERS, 1);
 5318+			RGFW_attribStack_pushAttribs(&stack, EGL_SAMPLES, hints->samples);
 5319+		}
 5320+
 5321+		RGFW_attribStack_pushAttribs(&stack, EGL_NONE, EGL_NONE);
 5322+	}
 5323+
 5324+	EGLint numConfigs, best_config = -1, best_samples = 0;
 5325+
 5326+	RGFW_eglChooseConfig(_RGFW->EGL_display, egl_config, NULL, 0, &numConfigs);
 5327+	EGLConfig* configs = (EGLConfig*)RGFW_ALLOC(sizeof(EGLConfig) * (u32)numConfigs);
 5328+
 5329+	RGFW_eglChooseConfig(_RGFW->EGL_display, egl_config, configs, numConfigs, &numConfigs);
 5330+
 5331+#ifdef RGFW_X11
 5332+	RGFW_bool transparent = (win->internal.flags & RGFW_windowTransparent);
 5333+	EGLint best_depth = 0;
 5334+#endif
 5335+
 5336+	for (EGLint i = 0; i < numConfigs; i++) {
 5337+		EGLint visual_id = 0;
 5338+		EGLint samples = 0;
 5339+
 5340+		RGFW_eglGetConfigAttrib(_RGFW->EGL_display, configs[i], EGL_NATIVE_VISUAL_ID, &visual_id);
 5341+		RGFW_eglGetConfigAttrib(_RGFW->EGL_display, configs[i], EGL_SAMPLES, &samples);
 5342+
 5343+		if (best_config  == -1) best_config = i;
 5344+
 5345+#ifdef RGFW_X11
 5346+		if (_RGFW->useWaylandBool == RGFW_FALSE) {
 5347+			XVisualInfo vinfo_template;
 5348+			vinfo_template.visualid = (VisualID)visual_id;
 5349+
 5350+			int num_visuals = 0;
 5351+			XVisualInfo* vi = XGetVisualInfo(_RGFW->display, VisualIDMask, &vinfo_template, &num_visuals);
 5352+			if (!vi) continue;
 5353+			if ((!transparent || vi->depth == 32) && best_depth == 0) {
 5354+				best_config = i;
 5355+				best_depth = vi->depth;
 5356+			}
 5357+
 5358+			if ((!(transparent) || vi->depth == 32) && (samples <= hints->samples && samples > best_samples)) {
 5359+				best_depth = vi->depth;
 5360+				best_config = i;
 5361+				best_samples = samples;
 5362+				XFree(vi);
 5363+				continue;
 5364+			}
 5365+		}
 5366+#endif
 5367+
 5368+		if (samples <= hints->samples && samples > best_samples) {
 5369+			best_config = i;
 5370+			best_samples = samples;
 5371+		}
 5372+	}
 5373+
 5374+	EGLConfig config = configs[best_config];
 5375+	RGFW_FREE(configs);
 5376+#ifdef RGFW_X11
 5377+    if (_RGFW->useWaylandBool == RGFW_FALSE) {
 5378+		/*  This is required so that way the user can create their own OpenGL context after RGFW_createWindow is used */
 5379+		XVisualInfo* result;
 5380+		XVisualInfo desired;
 5381+		EGLint visualID = 0, count = 0;
 5382+
 5383+		RGFW_eglGetConfigAttrib(_RGFW->EGL_display, config, EGL_NATIVE_VISUAL_ID, &visualID);
 5384+		if (visualID) {
 5385+			desired.visualid = (VisualID)visualID;
 5386+			result = XGetVisualInfo(_RGFW->display, VisualIDMask, &desired, &count);
 5387+		} else  RGFW_debugCallback(RGFW_typeError, RGFW_errEGLContext,  "Failed to fetch a valid EGL VisualID");
 5388+
 5389+		if (result == NULL || count == 0) {
 5390+			if (win->src.window == 0) {
 5391+				/* try to create a EGL context anyway (this will work if you're not using a NVidia driver) */
 5392+				win->internal.flags &= ~(u32)RGFW_windowEGL;
 5393+				RGFW_createWindowPlatform("", win->internal.flags, win);
 5394+			}
 5395+			RGFW_debugCallback(RGFW_typeError, RGFW_errEGLContext,  "Failed to find a valid visual for the EGL config");
 5396+		} else {
 5397+			RGFW_bool showWindow = RGFW_FALSE;
 5398+			if (win->src.window) {
 5399+				showWindow = (RGFW_window_isMinimized(win) == RGFW_FALSE);
 5400+				RGFW_window_closePlatform(win);
 5401+			}
 5402+
 5403+			RGFW_XCreateWindow(*result, "", win->internal.flags, win);
 5404+
 5405+			if (showWindow) {
 5406+				RGFW_window_show(win);
 5407+			}
 5408+			XFree(result);
 5409+		}
 5410+	}
 5411+#endif
 5412+
 5413+	EGLint surf_attribs[9];
 5414+
 5415+	{
 5416+		RGFW_attribStack stack;
 5417+		RGFW_attribStack_init(&stack, surf_attribs, 9);
 5418+
 5419+		const char present_opaque_str[] = "EGL_EXT_present_opaque";
 5420+		RGFW_bool opaque_extension_Found = RGFW_extensionSupportedPlatform_EGL(present_opaque_str, sizeof(present_opaque_str));
 5421+
 5422+		#ifndef EGL_PRESENT_OPAQUE_EXT
 5423+		#define EGL_PRESENT_OPAQUE_EXT 0x31df
 5424+		#endif
 5425+
 5426+		#ifndef EGL_GL_COLORSPACE_KHR
 5427+		#define EGL_GL_COLORSPACE_KHR 0x309D
 5428+		#ifndef EGL_GL_COLORSPACE_SRGB_KHR
 5429+		#define EGL_GL_COLORSPACE_SRGB_KHR 0x3089
 5430+		#endif
 5431+		#endif
 5432+
 5433+		const char gl_colorspace_str[] = "EGL_KHR_gl_colorspace";
 5434+		RGFW_bool gl_colorspace_Found = RGFW_extensionSupportedPlatform_EGL(gl_colorspace_str, sizeof(gl_colorspace_str));
 5435+
 5436+		if (hints->sRGB && gl_colorspace_Found) {
 5437+			RGFW_attribStack_pushAttribs(&stack, EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR);
 5438+		}
 5439+
 5440+		if (!(win->internal.flags & RGFW_windowTransparent) && opaque_extension_Found)
 5441+			RGFW_attribStack_pushAttribs(&stack, EGL_PRESENT_OPAQUE_EXT, EGL_TRUE);
 5442+
 5443+		if (hints->doubleBuffer == 0) {
 5444+			RGFW_attribStack_pushAttribs(&stack, EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER);
 5445+		}
 5446+
 5447+		RGFW_attribStack_pushAttribs(&stack, EGL_NONE, EGL_NONE);
 5448+	}
 5449+	#if defined(RGFW_MACOS)
 5450+		void* layer = RGFW_getLayer_OSX();
 5451+
 5452+		RGFW_window_setLayer_OSX(win, layer);
 5453+
 5454+		win->src.ctx.egl->surface = RGFW_eglCreateWindowSurface(_RGFW->EGL_display, config, (EGLNativeWindowType) layer, surf_attribs);
 5455+	#elif defined(RGFW_WINDOWS)
 5456+		win->src.ctx.egl->surface = RGFW_eglCreateWindowSurface(_RGFW->EGL_display, config, (EGLNativeWindowType) win->src.window, surf_attribs);
 5457+	#elif defined(RGFW_WAYLAND)
 5458+		if (_RGFW->useWaylandBool)
 5459+			win->src.ctx.egl->surface = RGFW_eglCreateWindowSurface(_RGFW->EGL_display, config, (EGLNativeWindowType) win->src.ctx.egl->eglWindow, surf_attribs);
 5460+		else
 5461+    #endif
 5462+    #ifdef RGFW_X11
 5463+        win->src.ctx.egl->surface = RGFW_eglCreateWindowSurface(_RGFW->EGL_display, config, (EGLNativeWindowType) win->src.window, surf_attribs);
 5464+    #else
 5465+    {}
 5466+    #endif
 5467+	#ifdef RGFW_WASM
 5468+		win->src.ctx.egl->surface = eglCreateWindowSurface(_RGFW->EGL_display, config, 0, 0);
 5469+	#endif
 5470+
 5471+	if (win->src.ctx.egl->surface == NULL) {
 5472+		RGFW_debugCallback(RGFW_typeError, RGFW_errEGLContext, "Failed to create an EGL surface.");
 5473+		return RGFW_FALSE;
 5474+	}
 5475+
 5476+	EGLint attribs[20];
 5477+	{
 5478+		RGFW_attribStack stack;
 5479+		RGFW_attribStack_init(&stack, attribs, 20);
 5480+
 5481+		if (hints->major || hints->minor) {
 5482+			RGFW_attribStack_pushAttribs(&stack, EGL_CONTEXT_MAJOR_VERSION, hints->major);
 5483+			RGFW_attribStack_pushAttribs(&stack, EGL_CONTEXT_MINOR_VERSION, hints->minor);
 5484+		}
 5485+
 5486+		if (hints->profile == RGFW_glCore) {
 5487+			RGFW_attribStack_pushAttribs(&stack, EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT);
 5488+		} else if (hints->profile == RGFW_glCompatibility) {
 5489+			RGFW_attribStack_pushAttribs(&stack, EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT);
 5490+		} else if (hints->profile == RGFW_glForwardCompatibility) {
 5491+			RGFW_attribStack_pushAttribs(&stack, EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE, EGL_TRUE);
 5492+		}
 5493+
 5494+
 5495+		RGFW_attribStack_pushAttribs(&stack, EGL_CONTEXT_OPENGL_ROBUST_ACCESS, hints->robustness);
 5496+		RGFW_attribStack_pushAttribs(&stack, EGL_CONTEXT_OPENGL_DEBUG, hints->debug);
 5497+
 5498+		#ifndef EGL_CONTEXT_RELEASE_BEHAVIOR_KHR
 5499+			#define EGL_CONTEXT_RELEASE_BEHAVIOR_KHR 0x2097
 5500+		#endif
 5501+
 5502+		#ifndef EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR
 5503+			#define EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x2098
 5504+		#endif
 5505+
 5506+		if (hints->releaseBehavior == RGFW_glReleaseFlush) {
 5507+			RGFW_attribStack_pushAttribs(&stack, EGL_CONTEXT_RELEASE_BEHAVIOR_KHR, EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR);
 5508+		} else {
 5509+			RGFW_attribStack_pushAttribs(&stack, EGL_CONTEXT_RELEASE_BEHAVIOR_KHR, 0x0000);
 5510+		}
 5511+
 5512+		RGFW_attribStack_pushAttribs(&stack, EGL_NONE, EGL_NONE);
 5513+	}
 5514+
 5515+	if (hints->profile == RGFW_glES)
 5516+		RGFW_eglBindAPI(EGL_OPENGL_ES_API);
 5517+	else
 5518+		RGFW_eglBindAPI(EGL_OPENGL_API);
 5519+
 5520+	win->src.ctx.egl->ctx = RGFW_eglCreateContext(_RGFW->EGL_display, config, hints->shareEGL, attribs);
 5521+
 5522+	if (win->src.ctx.egl->ctx == NULL) {
 5523+		RGFW_debugCallback(RGFW_typeError, RGFW_errEGLContext,  "Failed to create an EGL context.");
 5524+		return RGFW_FALSE;
 5525+	}
 5526+
 5527+	RGFW_eglMakeCurrent(_RGFW->EGL_display, win->src.ctx.egl->surface, win->src.ctx.egl->surface, win->src.ctx.egl->ctx);
 5528+	RGFW_eglSwapBuffers(_RGFW->EGL_display, win->src.ctx.egl->surface);
 5529+	RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "EGL context initalized.");
 5530+	return RGFW_TRUE;
 5531+}
 5532+
 5533+RGFW_eglContext* RGFW_window_getContext_EGL(RGFW_window* win) {
 5534+	if (win->src.gfxType == RGFW_windowOpenGL) return NULL;
 5535+	return win->src.ctx.egl;
 5536+}
 5537+
 5538+void RGFW_window_deleteContextPtr_EGL(RGFW_window* win, RGFW_eglContext* ctx) {
 5539+	if (_RGFW->EGL_display == NULL) return;
 5540+
 5541+	RGFW_eglDestroySurface(_RGFW->EGL_display, ctx->surface);
 5542+	RGFW_eglDestroyContext(_RGFW->EGL_display, ctx->ctx);
 5543+	RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "EGL context freed");
 5544+	#ifdef RGFW_WAYLAND
 5545+		if (_RGFW->useWaylandBool == RGFW_FALSE) return;
 5546+		wl_egl_window_destroy(win->src.ctx.egl->eglWindow);
 5547+		RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "EGL window context freed");
 5548+	#endif
 5549+	win->src.ctx.egl = NULL;
 5550+}
 5551+
 5552+void RGFW_window_makeCurrentContext_EGL(RGFW_window* win) { if (win) RGFW_ASSERT(win->src.ctx.egl);
 5553+	if (win == NULL)
 5554+        RGFW_eglMakeCurrent(_RGFW->EGL_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
 5555+    else {
 5556+        RGFW_eglMakeCurrent(_RGFW->EGL_display, win->src.ctx.egl->surface, win->src.ctx.egl->surface, win->src.ctx.egl->ctx);
 5557+    }
 5558+}
 5559+
 5560+void RGFW_window_swapBuffers_EGL(RGFW_window* win) {
 5561+	if (RGFW_eglSwapBuffers)
 5562+		RGFW_eglSwapBuffers(_RGFW->EGL_display, win->src.ctx.egl->surface);
 5563+	else RGFW_window_swapBuffers_OpenGL(win);
 5564+}
 5565+
 5566+void* RGFW_getCurrentContext_EGL(void) {
 5567+	return RGFW_eglGetCurrentContext();
 5568+}
 5569+
 5570+RGFW_proc RGFW_getProcAddress_EGL(const char* procname) {
 5571+	#if defined(RGFW_WINDOWS)
 5572+	RGFW_proc proc = (RGFW_proc) GetProcAddress(RGFW_wgl_dll, procname);
 5573+
 5574+		if (proc)
 5575+			return proc;
 5576+	#endif
 5577+
 5578+	return (RGFW_proc) RGFW_eglGetProcAddress(procname);
 5579+}
 5580+
 5581+RGFW_bool RGFW_extensionSupportedPlatform_EGL(const char* extension, size_t len) {
 5582+	if (RGFW_loadEGL() == RGFW_FALSE) return RGFW_FALSE;
 5583+	const char* extensions = RGFW_eglQueryString(_RGFW->EGL_display, EGL_EXTENSIONS);
 5584+	return extensions != NULL && RGFW_extensionSupportedStr(extensions, extension, len);
 5585+}
 5586+
 5587+void RGFW_window_swapInterval_EGL(RGFW_window* win, i32 swapInterval) {
 5588+	RGFW_ASSERT(win != NULL);
 5589+	RGFW_eglSwapInterval(_RGFW->EGL_display, swapInterval);
 5590+}
 5591+
 5592+RGFW_bool RGFW_extensionSupported_EGL(const char* extension, size_t len) {
 5593+	if (RGFW_extensionSupported_base(extension, len))  return RGFW_TRUE;
 5594+    return RGFW_extensionSupportedPlatform_EGL(extension, len);
 5595+}
 5596+
 5597+void RGFW_window_makeCurrentWindow_EGL(RGFW_window* win) {
 5598+    _RGFW->current = win;
 5599+    RGFW_window_makeCurrentContext_EGL(win);
 5600+}
 5601+
 5602+RGFW_window* RGFW_getCurrentWindow_EGL(void) { return _RGFW->current; }
 5603+
 5604+RGFW_eglContext* RGFW_window_createContext_EGL(RGFW_window* win, RGFW_glHints* hints) {
 5605+	RGFW_eglContext* ctx = (RGFW_eglContext*)RGFW_ALLOC(sizeof(RGFW_eglContext));
 5606+	if (RGFW_window_createContextPtr_EGL(win, ctx, hints) == RGFW_FALSE) {
 5607+		RGFW_FREE(ctx);
 5608+		win->src.ctx.egl = NULL;
 5609+		return NULL;
 5610+	}
 5611+	win->src.gfxType |= RGFW_gfxOwnedByRGFW;
 5612+	return ctx;
 5613+}
 5614+
 5615+void RGFW_window_deleteContext_EGL(RGFW_window* win, RGFW_eglContext* ctx) {
 5616+	RGFW_window_deleteContextPtr_EGL(win, ctx);
 5617+	if (win->src.gfxType & RGFW_gfxOwnedByRGFW) RGFW_FREE(ctx);
 5618+}
 5619+
 5620+#endif /* RGFW_EGL */
 5621+
 5622+/*
 5623+	end of RGFW_EGL defines
 5624+*/
 5625+#endif /* end of RGFW_GL (OpenGL, EGL, OSMesa )*/
 5626+
 5627+/*
 5628+	RGFW_VULKAN defines
 5629+*/
 5630+#ifdef RGFW_VULKAN
 5631+#ifdef RGFW_MACOS
 5632+#include <objc/message.h>
 5633+#endif
 5634+
 5635+const char** RGFW_getRequiredInstanceExtensions_Vulkan(size_t* count) {
 5636+    static const char* arr[2] = {VK_KHR_SURFACE_EXTENSION_NAME};
 5637+    arr[1] = RGFW_VK_SURFACE;
 5638+    if (count != NULL) *count = 2;
 5639+
 5640+    return (const char**)arr;
 5641+}
 5642+
 5643+#ifndef RGFW_MACOS
 5644+VkResult RGFW_window_createSurface_Vulkan(RGFW_window* win, VkInstance instance, VkSurfaceKHR* surface) {
 5645+    RGFW_ASSERT(win != NULL); RGFW_ASSERT(instance);
 5646+	RGFW_ASSERT(surface != NULL);
 5647+
 5648+    *surface = VK_NULL_HANDLE;
 5649+
 5650+#ifdef RGFW_X11
 5651+
 5652+    VkXlibSurfaceCreateInfoKHR x11 = { VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, 0, 0, (Display*) _RGFW->display, (Window) win->src.window };
 5653+    return vkCreateXlibSurfaceKHR(instance, &x11, NULL, surface);
 5654+#endif
 5655+#if defined(RGFW_WAYLAND)
 5656+
 5657+    VkWaylandSurfaceCreateInfoKHR wayland = { VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR, 0, 0, (struct wl_display*) _RGFW->wl_display, (struct wl_surface*) win->src.surface };
 5658+    return vkCreateWaylandSurfaceKHR(instance, &wayland, NULL, surface);
 5659+#elif defined(RGFW_WINDOWS)
 5660+    VkWin32SurfaceCreateInfoKHR win32 = { VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR, 0, 0, GetModuleHandle(NULL), (HWND)win->src.window };
 5661+
 5662+    return vkCreateWin32SurfaceKHR(instance, &win32, NULL, surface);
 5663+#endif
 5664+}
 5665+#endif
 5666+
 5667+RGFW_bool RGFW_getPresentationSupport_Vulkan(VkPhysicalDevice physicalDevice, u32 queueFamilyIndex) {
 5668+	if (_RGFW == NULL) RGFW_init();
 5669+#ifdef RGFW_X11
 5670+
 5671+	Visual* visual = DefaultVisual(_RGFW->display, DefaultScreen(_RGFW->display));
 5672+    RGFW_bool out = vkGetPhysicalDeviceXlibPresentationSupportKHR(physicalDevice, queueFamilyIndex, _RGFW->display, XVisualIDFromVisual(visual));
 5673+    return out;
 5674+#endif
 5675+#if defined(RGFW_WAYLAND)
 5676+
 5677+    RGFW_bool wlout = vkGetPhysicalDeviceWaylandPresentationSupportKHR(physicalDevice, queueFamilyIndex, _RGFW->wl_display);
 5678+    return wlout;
 5679+#elif defined(RGFW_WINDOWS)
 5680+	RGFW_bool out = vkGetPhysicalDeviceWin32PresentationSupportKHR(physicalDevice, queueFamilyIndex);
 5681+	return out;
 5682+#elif defined(RGFW_MACOS) && !defined(RGFW_MACOS_X11)
 5683+	RGFW_UNUSED(physicalDevice);
 5684+	RGFW_UNUSED(queueFamilyIndex);
 5685+    return RGFW_FALSE; /* TODO */
 5686+#endif
 5687+}
 5688+#endif /* end of RGFW_vulkan */
 5689+
 5690+/*
 5691+This is where OS specific stuff starts
 5692+*/
 5693+
 5694+/* start of unix (wayland or X11 (unix) ) defines */
 5695+
 5696+#ifdef RGFW_UNIX
 5697+#include <fcntl.h>
 5698+#include <poll.h>
 5699+#include <unistd.h>
 5700+
 5701+void RGFW_stopCheckEvents(void) {
 5702+
 5703+	_RGFW->eventWait_forceStop[2] = 1;
 5704+	while (1) {
 5705+		const char byte = 0;
 5706+		const ssize_t result = write(_RGFW->eventWait_forceStop[1], &byte, 1);
 5707+		if (result == 1 || result == -1)
 5708+			break;
 5709+	}
 5710+}
 5711+
 5712+RGFWDEF u64 RGFW_linux_getTimeNS(void);
 5713+u64 RGFW_linux_getTimeNS(void) {
 5714+    struct timespec ts;
 5715+    const u64 scale_factor = 1000000000;
 5716+    clock_gettime(_RGFW->clock, &ts);
 5717+    return (u64)ts.tv_sec * scale_factor + (u64)ts.tv_nsec;
 5718+}
 5719+
 5720+void RGFW_waitForEvent(i32 waitMS) {
 5721+	if (waitMS == 0) return;
 5722+
 5723+	if (_RGFW->eventWait_forceStop[0] == 0 || _RGFW->eventWait_forceStop[1] == 0) {
 5724+		if (pipe(_RGFW->eventWait_forceStop) != -1) {
 5725+			fcntl(_RGFW->eventWait_forceStop[0], F_GETFL, 0);
 5726+			fcntl(_RGFW->eventWait_forceStop[0], F_GETFD, 0);
 5727+			fcntl(_RGFW->eventWait_forceStop[1], F_GETFL, 0);
 5728+			fcntl(_RGFW->eventWait_forceStop[1], F_GETFD, 0);
 5729+		}
 5730+	}
 5731+
 5732+	struct pollfd fds[2];
 5733+    fds[0].fd = 0;
 5734+    fds[0].events = POLLIN;
 5735+    fds[0].revents = 0;
 5736+    fds[1].fd = _RGFW->eventWait_forceStop[0];
 5737+    fds[1].events = POLLIN;
 5738+    fds[1].revents = 0;
 5739+
 5740+
 5741+	if (RGFW_usingWayland()) {
 5742+		#ifdef RGFW_WAYLAND
 5743+		fds[0].fd = wl_display_get_fd(_RGFW->wl_display);
 5744+
 5745+		/* empty the queue */
 5746+		while (wl_display_prepare_read(_RGFW->wl_display) != 0) {
 5747+			/* error occured when dispatching the queue */
 5748+			if (wl_display_dispatch_pending(_RGFW->wl_display) == -1) {
 5749+				return;
 5750+			}
 5751+		}
 5752+
 5753+		/* send any pending requests to the compositor */
 5754+		while (wl_display_flush(_RGFW->wl_display) == -1) {
 5755+
 5756+			/* queue is full dispatch them */
 5757+			if (errno == EAGAIN) {
 5758+				if (wl_display_dispatch_pending(_RGFW->wl_display) == -1) {
 5759+					return;
 5760+				}
 5761+			} else {
 5762+				return;
 5763+			}
 5764+		}
 5765+		#endif
 5766+	} else {
 5767+		#ifdef RGFW_X11
 5768+		fds[0].fd = ConnectionNumber(_RGFW->display);
 5769+		#endif
 5770+	}
 5771+
 5772+
 5773+	u64 start = RGFW_linux_getTimeNS();
 5774+	if (RGFW_usingWayland()) {
 5775+		#ifdef RGFW_WAYLAND
 5776+		while (wl_display_dispatch_pending(_RGFW->wl_display) == 0) {
 5777+			if (poll(fds, 1, waitMS) <= 0) {
 5778+				wl_display_cancel_read(_RGFW->wl_display);
 5779+				break;
 5780+			} else {
 5781+				if (wl_display_read_events(_RGFW->wl_display) == -1)
 5782+					return;
 5783+			}
 5784+
 5785+			if (waitMS != RGFW_eventWaitNext) {
 5786+				waitMS -= (i32)(RGFW_linux_getTimeNS() - start) / (i32)1e+6;
 5787+			}
 5788+		}
 5789+
 5790+		/* queue contains events from read, dispatch them */
 5791+		if (wl_display_dispatch_pending(_RGFW->wl_display) == -1) {
 5792+			return;
 5793+		}
 5794+		#endif
 5795+	} else {
 5796+		#ifdef RGFW_X11
 5797+		while (XPending(_RGFW->display) == 0) {
 5798+			if (poll(fds, 1, waitMS) <= 0)
 5799+				break;
 5800+
 5801+			if (waitMS != RGFW_eventWaitNext) {
 5802+				waitMS -= (i32)(RGFW_linux_getTimeNS() - start) / (i32)1e+6;
 5803+			}
 5804+		}
 5805+		#endif
 5806+	}
 5807+
 5808+	/* drain any data in the stop request */
 5809+	if (_RGFW->eventWait_forceStop[2]) {
 5810+		char data[64];
 5811+        RGFW_MEMZERO(data, sizeof(data));
 5812+        (void)!read(_RGFW->eventWait_forceStop[0], data, sizeof(data));
 5813+
 5814+		_RGFW->eventWait_forceStop[2] = 0;
 5815+	}
 5816+}
 5817+
 5818+char* RGFW_strtok(char* str, const char* delimStr);
 5819+char* RGFW_strtok(char* str, const char* delimStr) {
 5820+    static char* static_str = NULL;
 5821+
 5822+    if (str != NULL)
 5823+        static_str = str;
 5824+
 5825+    if (static_str == NULL) {
 5826+        return NULL;
 5827+    }
 5828+
 5829+    while (*static_str != '\0') {
 5830+        RGFW_bool delim = 0;
 5831+        const char* d;
 5832+        for (d = delimStr; *d != '\0'; d++) {
 5833+            if (*static_str == *d) {
 5834+                delim = 1;
 5835+                break;
 5836+            }
 5837+        }
 5838+        if (!delim)
 5839+            break;
 5840+        static_str++;
 5841+    }
 5842+
 5843+    if (*static_str == '\0')
 5844+        return NULL;
 5845+
 5846+    char* token_start = static_str;
 5847+    while (*static_str != '\0') {
 5848+        int delim = 0;
 5849+        const char* d;
 5850+        for (d = delimStr; *d != '\0'; d++) {
 5851+            if (*static_str == *d) {
 5852+                delim = 1;
 5853+                break;
 5854+            }
 5855+        }
 5856+
 5857+        if (delim) {
 5858+            *static_str = '\0';
 5859+            static_str++;
 5860+            break;
 5861+        }
 5862+        static_str++;
 5863+    }
 5864+
 5865+    return token_start;
 5866+}
 5867+
 5868+#ifdef RGFW_X11
 5869+RGFWDEF i32 RGFW_initPlatform_X11(void);
 5870+RGFWDEF void RGFW_deinitPlatform_X11(void);
 5871+#endif
 5872+#ifdef RGFW_WAYLAND
 5873+RGFWDEF i32 RGFW_initPlatform_Wayland(void);
 5874+RGFWDEF void RGFW_deinitPlatform_Wayland(void);
 5875+#endif
 5876+
 5877+RGFWDEF void RGFW_load_X11(void);
 5878+RGFWDEF void RGFW_load_Wayland(void);
 5879+
 5880+#if !defined(RGFW_X11) || !defined(RGFW_WAYLAND)
 5881+void RGFW_load_X11(void) { }
 5882+void RGFW_load_Wayland(void) { }
 5883+#endif
 5884+
 5885+/*
 5886+ * Sadly we have to use magic linux keycodes
 5887+ * We can't use X11 functions, because that breaks Wayland, but they use the same keycodes so there's no use redeffing them
 5888+ * We can't use linux enums, because the headers don't exist on BSD
 5889+ */
 5890+void RGFW_initKeycodesPlatform(void) {
 5891+	_RGFW->keycodes[49] = RGFW_keyBacktick;
 5892+	_RGFW->keycodes[19] = RGFW_key0;
 5893+	_RGFW->keycodes[10] = RGFW_key1;
 5894+	_RGFW->keycodes[11] = RGFW_key2;
 5895+	_RGFW->keycodes[12] = RGFW_key3;
 5896+	_RGFW->keycodes[13] = RGFW_key4;
 5897+	_RGFW->keycodes[14] = RGFW_key5;
 5898+	_RGFW->keycodes[15] = RGFW_key6;
 5899+	_RGFW->keycodes[16] = RGFW_key7;
 5900+	_RGFW->keycodes[17] = RGFW_key8;
 5901+	_RGFW->keycodes[18] = RGFW_key9;
 5902+	_RGFW->keycodes[65] = RGFW_keySpace;
 5903+	_RGFW->keycodes[38] = RGFW_keyA;
 5904+	_RGFW->keycodes[56] = RGFW_keyB;
 5905+	_RGFW->keycodes[54] = RGFW_keyC;
 5906+	_RGFW->keycodes[40] = RGFW_keyD;
 5907+	_RGFW->keycodes[26] = RGFW_keyE;
 5908+	_RGFW->keycodes[41] = RGFW_keyF;
 5909+	_RGFW->keycodes[42] = RGFW_keyG;
 5910+	_RGFW->keycodes[43] = RGFW_keyH;
 5911+	_RGFW->keycodes[31] = RGFW_keyI;
 5912+	_RGFW->keycodes[44] = RGFW_keyJ;
 5913+	_RGFW->keycodes[45] = RGFW_keyK;
 5914+	_RGFW->keycodes[46] = RGFW_keyL;
 5915+	_RGFW->keycodes[58] = RGFW_keyM;
 5916+	_RGFW->keycodes[57] = RGFW_keyN;
 5917+	_RGFW->keycodes[32] = RGFW_keyO;
 5918+	_RGFW->keycodes[33] = RGFW_keyP;
 5919+	_RGFW->keycodes[24] = RGFW_keyQ;
 5920+	_RGFW->keycodes[27] = RGFW_keyR;
 5921+	_RGFW->keycodes[39] = RGFW_keyS;
 5922+	_RGFW->keycodes[28] = RGFW_keyT;
 5923+	_RGFW->keycodes[30] = RGFW_keyU;
 5924+	_RGFW->keycodes[55] = RGFW_keyV;
 5925+	_RGFW->keycodes[25] = RGFW_keyW;
 5926+	_RGFW->keycodes[53] = RGFW_keyX;
 5927+	_RGFW->keycodes[29] = RGFW_keyY;
 5928+	_RGFW->keycodes[52] = RGFW_keyZ;
 5929+	_RGFW->keycodes[60] = RGFW_keyPeriod;
 5930+	_RGFW->keycodes[59] = RGFW_keyComma;
 5931+	_RGFW->keycodes[61] = RGFW_keySlash;
 5932+	_RGFW->keycodes[34] = RGFW_keyBracket;
 5933+	_RGFW->keycodes[35] = RGFW_keyCloseBracket;
 5934+	_RGFW->keycodes[47] = RGFW_keySemicolon;
 5935+	_RGFW->keycodes[48] = RGFW_keyApostrophe;
 5936+	_RGFW->keycodes[51] = RGFW_keyBackSlash;
 5937+	_RGFW->keycodes[36] = RGFW_keyReturn;
 5938+	_RGFW->keycodes[119] = RGFW_keyDelete;
 5939+	_RGFW->keycodes[77] = RGFW_keyNumLock;
 5940+	_RGFW->keycodes[106] = RGFW_keyPadSlash;
 5941+	_RGFW->keycodes[63] = RGFW_keyPadMultiply;
 5942+	_RGFW->keycodes[86] = RGFW_keyPadPlus;
 5943+	_RGFW->keycodes[82] = RGFW_keyPadMinus;
 5944+	_RGFW->keycodes[87] = RGFW_keyPad1;
 5945+	_RGFW->keycodes[88] = RGFW_keyPad2;
 5946+	_RGFW->keycodes[89] = RGFW_keyPad3;
 5947+	_RGFW->keycodes[83] = RGFW_keyPad4;
 5948+	_RGFW->keycodes[84] = RGFW_keyPad5;
 5949+	_RGFW->keycodes[85] = RGFW_keyPad6;
 5950+	_RGFW->keycodes[81] = RGFW_keyPad9;
 5951+	_RGFW->keycodes[90] = RGFW_keyPad0;
 5952+	_RGFW->keycodes[91] = RGFW_keyPadPeriod;
 5953+	_RGFW->keycodes[104] = RGFW_keyPadReturn;
 5954+	_RGFW->keycodes[20] = RGFW_keyMinus;
 5955+	_RGFW->keycodes[21] = RGFW_keyEquals;
 5956+	_RGFW->keycodes[22] = RGFW_keyBackSpace;
 5957+	_RGFW->keycodes[23] = RGFW_keyTab;
 5958+	_RGFW->keycodes[66] = RGFW_keyCapsLock;
 5959+	_RGFW->keycodes[50] = RGFW_keyShiftL;
 5960+	_RGFW->keycodes[37] = RGFW_keyControlL;
 5961+	_RGFW->keycodes[64] = RGFW_keyAltL;
 5962+	_RGFW->keycodes[133] = RGFW_keySuperL;
 5963+	_RGFW->keycodes[105] = RGFW_keyControlR;
 5964+	_RGFW->keycodes[134] = RGFW_keySuperR;
 5965+	_RGFW->keycodes[62] = RGFW_keyShiftR;
 5966+	_RGFW->keycodes[108] = RGFW_keyAltR;
 5967+	_RGFW->keycodes[67] = RGFW_keyF1;
 5968+	_RGFW->keycodes[68] = RGFW_keyF2;
 5969+	_RGFW->keycodes[69] = RGFW_keyF3;
 5970+	_RGFW->keycodes[70] = RGFW_keyF4;
 5971+	_RGFW->keycodes[71] = RGFW_keyF5;
 5972+	_RGFW->keycodes[72] = RGFW_keyF6;
 5973+	_RGFW->keycodes[73] = RGFW_keyF7;
 5974+	_RGFW->keycodes[74] = RGFW_keyF8;
 5975+	_RGFW->keycodes[75] = RGFW_keyF9;
 5976+	_RGFW->keycodes[76] = RGFW_keyF10;
 5977+	_RGFW->keycodes[95] = RGFW_keyF11;
 5978+	_RGFW->keycodes[96] = RGFW_keyF12;
 5979+	_RGFW->keycodes[111] = RGFW_keyUp;
 5980+	_RGFW->keycodes[116] = RGFW_keyDown;
 5981+	_RGFW->keycodes[113] = RGFW_keyLeft;
 5982+	_RGFW->keycodes[114] = RGFW_keyRight;
 5983+	_RGFW->keycodes[118] = RGFW_keyInsert;
 5984+	_RGFW->keycodes[115] = RGFW_keyEnd;
 5985+	_RGFW->keycodes[112] = RGFW_keyPageUp;
 5986+	_RGFW->keycodes[117] = RGFW_keyPageDown;
 5987+	_RGFW->keycodes[9] = RGFW_keyEscape;
 5988+	_RGFW->keycodes[110] = RGFW_keyHome;
 5989+	_RGFW->keycodes[78] = RGFW_keyScrollLock;
 5990+	_RGFW->keycodes[107] = RGFW_keyPrintScreen;
 5991+	_RGFW->keycodes[128] = RGFW_keyPause;
 5992+    _RGFW->keycodes[191] = RGFW_keyF13;
 5993+    _RGFW->keycodes[192] = RGFW_keyF14;
 5994+    _RGFW->keycodes[193] = RGFW_keyF15;
 5995+    _RGFW->keycodes[194] = RGFW_keyF16;
 5996+    _RGFW->keycodes[195] = RGFW_keyF17;
 5997+    _RGFW->keycodes[196] = RGFW_keyF18;
 5998+    _RGFW->keycodes[197] = RGFW_keyF19;
 5999+    _RGFW->keycodes[198] = RGFW_keyF20;
 6000+    _RGFW->keycodes[199] = RGFW_keyF21;
 6001+    _RGFW->keycodes[200] = RGFW_keyF22;
 6002+    _RGFW->keycodes[201] = RGFW_keyF23;
 6003+    _RGFW->keycodes[202] = RGFW_keyF24;
 6004+    _RGFW->keycodes[203] = RGFW_keyF25;
 6005+	_RGFW->keycodes[142] = RGFW_keyPadEqual;
 6006+	_RGFW->keycodes[161] = RGFW_keyWorld1; /* non-US key #1 */
 6007+    _RGFW->keycodes[162] = RGFW_keyWorld2; /* non-US key #2 */
 6008+}
 6009+
 6010+i32 RGFW_initPlatform(void) {
 6011+	#if defined(_POSIX_MONOTONIC_CLOCK)
 6012+	struct timespec ts;
 6013+	RGFW_MEMZERO(&ts, sizeof(struct timespec));
 6014+
 6015+	if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
 6016+		_RGFW->clock = CLOCK_MONOTONIC;
 6017+	#else
 6018+		_RGFW->clock = CLOCK_REALTIME;
 6019+	#endif
 6020+
 6021+#ifdef RGFW_WAYLAND
 6022+	RGFW_load_Wayland();
 6023+	i32 ret = RGFW_initPlatform_Wayland();
 6024+	if (ret == 0) {
 6025+		return 0;
 6026+	} else {
 6027+		#ifdef RGFW_X11
 6028+			RGFW_debugCallback(RGFW_typeWarning, RGFW_warningWayland,  "Falling back to X11");
 6029+			RGFW_useWayland(0);
 6030+		#else
 6031+			return ret;
 6032+		#endif
 6033+	}
 6034+#endif
 6035+#ifdef RGFW_X11
 6036+	RGFW_load_X11();
 6037+	return RGFW_initPlatform_X11();
 6038+#else
 6039+	return 0;
 6040+#endif
 6041+}
 6042+
 6043+
 6044+void RGFW_deinitPlatform(void) {
 6045+    if (_RGFW->eventWait_forceStop[0] || _RGFW->eventWait_forceStop[1]){
 6046+        close(_RGFW->eventWait_forceStop[0]);
 6047+        close(_RGFW->eventWait_forceStop[1]);
 6048+    }
 6049+#ifdef RGFW_WAYLAND
 6050+	if (_RGFW->useWaylandBool) {
 6051+		RGFW_deinitPlatform_Wayland();
 6052+		return;
 6053+	}
 6054+#endif
 6055+#ifdef RGFW_X11
 6056+	RGFW_deinitPlatform_X11();
 6057+#endif
 6058+}
 6059+
 6060+RGFWDEF size_t RGFW_unix_stringlen(const char* name);
 6061+size_t RGFW_unix_stringlen(const char* name) {
 6062+	size_t i = 0;
 6063+    while (name[i]) { i++; }
 6064+	return i;
 6065+}
 6066+
 6067+RGFWDEF void RGFW_unix_parseURI(RGFW_window* win, char* data);
 6068+void RGFW_unix_parseURI(RGFW_window* win, char* data) {
 6069+	const char* prefix = (const char*)"file://";
 6070+	char* line;
 6071+	while ((line = (char*)RGFW_strtok(data, "\r\n"))) {
 6072+		data = NULL;
 6073+
 6074+		if (line[0] == '#')
 6075+			continue;
 6076+
 6077+		char* l;
 6078+		for (l = line; 1; l++) {
 6079+			if ((l - line) > 7)
 6080+				break;
 6081+			else if (*l != prefix[(l - line)])
 6082+				break;
 6083+			else if (*l == '\0' && prefix[(l - line)] == '\0') {
 6084+				line += 7;
 6085+				while (*line != '/')
 6086+					line++;
 6087+				break;
 6088+			} else if (*l == '\0')
 6089+				break;
 6090+		}
 6091+
 6092+		size_t len = RGFW_unix_stringlen(line);
 6093+		char* path = (char*)RGFW_ALLOC(len + 1);
 6094+
 6095+		size_t index = 0;
 6096+		while (*line) {
 6097+			if (line[0] == '%' && line[1] && line[2]) {
 6098+				char digits[3] = {0};
 6099+				digits[0] = line[1];
 6100+				digits[1] = line[2];
 6101+				digits[2] = '\0';
 6102+				path[index] = (char) RGFW_STRTOL(digits, NULL, 16);
 6103+				line += 2;
 6104+			} else {
 6105+				if (index >= len) {
 6106+					break;
 6107+				}
 6108+
 6109+				path[index] = *line;
 6110+			}
 6111+
 6112+			index++;
 6113+			line++;
 6114+		}
 6115+
 6116+		path[len] = '\0';
 6117+		RGFW_dataDropCallback(win, (const char*)path, len + 1, RGFW_dataFile);
 6118+		RGFW_FREE(path);
 6119+	}
 6120+}
 6121+
 6122+
 6123+#endif /* end of wayland or X11 defines */
 6124+
 6125+
 6126+/*
 6127+
 6128+
 6129+Start of Linux / Unix defines
 6130+
 6131+
 6132+*/
 6133+
 6134+#ifdef RGFW_X11
 6135+#ifdef RGFW_WAYLAND
 6136+#define RGFW_FUNC(func) func##_X11
 6137+#else
 6138+#define RGFW_FUNC(func) func
 6139+#endif
 6140+
 6141+#include <dlfcn.h>
 6142+#include <unistd.h>
 6143+
 6144+#include <limits.h> /* for data limits (mainly used in drag and drop functions) */
 6145+#include <poll.h>
 6146+
 6147+void RGFW_setXInstName(const char* name) { _RGFW->instName = name; }
 6148+#if !defined(RGFW_NO_X11_CURSOR) && defined(RGFW_X11)
 6149+	#include <X11/Xcursor/Xcursor.h>
 6150+#endif
 6151+
 6152+#include <X11/Xatom.h>
 6153+#include <X11/keysymdef.h>
 6154+#include <X11/extensions/sync.h>
 6155+
 6156+#include <X11/XKBlib.h> /* for converting keycode to string */
 6157+#include <X11/cursorfont.h> /* for hiding */
 6158+#include <X11/extensions/shapeconst.h>
 6159+#include <X11/extensions/shape.h>
 6160+#include <X11/extensions/XInput2.h>
 6161+
 6162+#ifdef RGFW_OPENGL
 6163+	#ifndef __gl_h_
 6164+		#define __gl_h_
 6165+		#define RGFW_gl_ndef
 6166+		#define GLubyte     unsigned char
 6167+		#define GLenum      unsigned int
 6168+		#define GLint       int
 6169+		#define GLuint      unsigned int
 6170+		#define GLsizei     int
 6171+		#define GLfloat     float
 6172+		#define GLvoid      void
 6173+		#define GLbitfield  unsigned int
 6174+		#define GLintptr    ptrdiff_t
 6175+		#define GLsizeiptr  ptrdiff_t
 6176+		#define GLboolean   unsigned char
 6177+	#endif
 6178+
 6179+	#include <GL/glx.h> /* GLX defs, xlib.h, gl.h */
 6180+	#ifndef GLX_MESA_swap_control
 6181+		#define  GLX_MESA_swap_control
 6182+	#endif
 6183+
 6184+	#ifdef RGFW_gl_ndef
 6185+		#undef __gl_h_
 6186+		#undef GLubyte
 6187+		#undef GLenum
 6188+		#undef GLint
 6189+		#undef GLuint
 6190+		#undef GLsizei
 6191+		#undef GLfloat
 6192+		#undef GLvoid
 6193+		#undef GLbitfield
 6194+		#undef GLintptr
 6195+		#undef GLsizeiptr
 6196+		#undef GLboolean
 6197+	#endif
 6198+	typedef GLXContext(*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*);
 6199+#endif
 6200+
 6201+/* atoms needed for drag and drop */
 6202+#if !defined(RGFW_NO_X11_CURSOR) && !defined(RGFW_NO_X11_CURSOR_PRELOAD)
 6203+		typedef XcursorImage* (*PFN_XcursorImageCreate)(int, int);
 6204+		typedef void (*PFN_XcursorImageDestroy)(XcursorImage*);
 6205+		typedef Cursor(*PFN_XcursorImageLoadCursor)(Display*, const XcursorImage*);
 6206+#endif
 6207+
 6208+#if !defined(RGFW_NO_X11_XI_PRELOAD)
 6209+		typedef int (* PFN_XISelectEvents)(Display*,Window,XIEventMask*,int);
 6210+		PFN_XISelectEvents XISelectEventsSRC = NULL;
 6211+		#define XISelectEvents XISelectEventsSRC
 6212+
 6213+		void* X11Xihandle = NULL;
 6214+#endif
 6215+
 6216+#if !defined(RGFW_NO_X11_EXT_PRELOAD)
 6217+		typedef void (* PFN_XSyncIntToValue)(XSyncValue*, int);
 6218+		PFN_XSyncIntToValue XSyncIntToValueSRC = NULL;
 6219+		#define XSyncIntToValue XSyncIntToValueSRC
 6220+
 6221+		typedef Status (* PFN_XSyncSetCounter)(Display*, XSyncCounter, XSyncValue);
 6222+		PFN_XSyncSetCounter XSyncSetCounterSRC = NULL;
 6223+		#define XSyncSetCounter XSyncSetCounterSRC
 6224+
 6225+		typedef XSyncCounter (* PFN_XSyncCreateCounter)(Display*, XSyncValue);
 6226+		PFN_XSyncCreateCounter XSyncCreateCounterSRC = NULL;
 6227+		#define XSyncCreateCounter XSyncCreateCounterSRC
 6228+
 6229+		typedef void (* PFN_XShapeCombineMask)(Display*,Window,int,int,int,Pixmap,int);
 6230+		PFN_XShapeCombineMask XShapeCombineMaskSRC;
 6231+		#define XShapeCombineMask XShapeCombineMaskSRC
 6232+
 6233+		typedef void (* PFN_XShapeCombineRegion)(Display*,Window,int,int,int,Region,int);
 6234+		PFN_XShapeCombineRegion XShapeCombineRegionSRC;
 6235+		#define XShapeCombineRegion XShapeCombineRegionSRC
 6236+		void* X11XEXThandle = NULL;
 6237+#endif
 6238+
 6239+#if !defined(RGFW_NO_X11_CURSOR) && !defined(RGFW_NO_X11_CURSOR_PRELOAD)
 6240+		PFN_XcursorImageLoadCursor XcursorImageLoadCursorSRC = NULL;
 6241+		PFN_XcursorImageCreate XcursorImageCreateSRC = NULL;
 6242+		PFN_XcursorImageDestroy XcursorImageDestroySRC = NULL;
 6243+
 6244+		#define XcursorImageLoadCursor XcursorImageLoadCursorSRC
 6245+		#define XcursorImageCreate XcursorImageCreateSRC
 6246+		#define XcursorImageDestroy XcursorImageDestroySRC
 6247+
 6248+		void* X11Cursorhandle = NULL;
 6249+#endif
 6250+
 6251+RGFWDEF RGFW_bool RGFW_waitForShowEvent_X11(RGFW_window* win);
 6252+RGFW_bool RGFW_waitForShowEvent_X11(RGFW_window* win) {
 6253+    XEvent dummy;
 6254+    while (!XCheckTypedWindowEvent(_RGFW->display, win->src.window, VisibilityNotify, &dummy)) {
 6255+		RGFW_waitForEvent(100);
 6256+    }
 6257+
 6258+	return RGFW_TRUE;
 6259+}
 6260+
 6261+RGFWDEF void RGFW_x11_icCallback(XIC ic, char* clientData, char* callData);
 6262+void RGFW_x11_icCallback(XIC ic, char* clientData, char* callData) {
 6263+	RGFW_UNUSED(ic); RGFW_UNUSED(callData);
 6264+    RGFW_window* win = (RGFW_window*)(void*)clientData;
 6265+    win->src.ic = NULL;
 6266+}
 6267+
 6268+RGFWDEF void RGFW_x11_imCallback(XIM im, char* clientData, char* callData);
 6269+void RGFW_x11_imCallback(XIM im, char* clientData, char* callData) {
 6270+	RGFW_UNUSED(im); RGFW_UNUSED(clientData); RGFW_UNUSED(callData);
 6271+	_RGFW->im = NULL;
 6272+}
 6273+
 6274+RGFWDEF void RGFW_x11_imInitCallback(Display* display, XPointer clientData, XPointer callData);
 6275+void RGFW_x11_imInitCallback(Display* display, XPointer clientData, XPointer callData) {
 6276+	RGFW_UNUSED(display); RGFW_UNUSED(clientData); RGFW_UNUSED(callData);
 6277+
 6278+	if (_RGFW->im) {
 6279+		return;
 6280+	}
 6281+
 6282+	_RGFW->im = XOpenIM(_RGFW->display, 0, NULL, NULL);
 6283+	if (_RGFW->im == NULL) {
 6284+		return;
 6285+	}
 6286+
 6287+    RGFW_bool found = RGFW_FALSE;
 6288+    XIMStyles* styles = NULL;
 6289+
 6290+    if (XGetIMValues(_RGFW->im, XNQueryInputStyle, &styles, NULL) != NULL) {
 6291+        found = RGFW_FALSE;
 6292+	} else {
 6293+		for (unsigned int i = 0;  i < styles->count_styles;  i++) {
 6294+			if (styles->supported_styles[i] == (XIMPreeditNothing | XIMStatusNothing)) {
 6295+				found = RGFW_TRUE;
 6296+				break;
 6297+			}
 6298+		}
 6299+
 6300+	    XFree(styles);
 6301+	}
 6302+
 6303+	if (found == RGFW_FALSE) {
 6304+		XCloseIM(_RGFW->im);
 6305+		_RGFW->im = NULL;
 6306+	}
 6307+
 6308+	XIMCallback callback;
 6309+	callback.callback = (XIMProc) RGFW_x11_imCallback;
 6310+	callback.client_data = NULL;
 6311+	XSetIMValues(_RGFW->im, XNDestroyCallback, &callback, NULL);
 6312+}
 6313+
 6314+void* RGFW_getDisplay_X11(void) { return _RGFW->display; }
 6315+u64 RGFW_window_getWindow_X11(RGFW_window* win) { return (u64)win->src.window; }
 6316+
 6317+RGFWDEF RGFW_format RGFW_XImage_getFormat(XImage* image);
 6318+RGFW_format RGFW_XImage_getFormat(XImage* image) {
 6319+    switch (image->bits_per_pixel) {
 6320+        case 24:
 6321+            if (image->red_mask == 0xFF0000 && image->green_mask == 0x00FF00 && image->blue_mask == 0x0000FF)
 6322+                return RGFW_formatRGB8;
 6323+            if (image->red_mask == 0x0000FF && image->green_mask == 0x00FF00 && image->blue_mask == 0xFF0000)
 6324+                return RGFW_formatBGR8;
 6325+            break;
 6326+        case 32:
 6327+            if (image->red_mask == 0x00FF0000 && image->green_mask == 0x0000FF00 && image->blue_mask == 0x000000FF)
 6328+                return RGFW_formatBGRA8;
 6329+            if (image->red_mask == 0x000000FF && image->green_mask == 0x0000FF00 && image->blue_mask == 0x00FF0000)
 6330+                return RGFW_formatRGBA8;
 6331+            if (image->red_mask == 0x0000FF00 && image->green_mask == 0x00FF0000 && image->blue_mask == 0xFF000000)
 6332+                return RGFW_formatABGR8;
 6333+            if (image->red_mask == 0x00FF0000 && image->green_mask == 0x0000FF00 && image->blue_mask == 0x000000FF)
 6334+                return RGFW_formatARGB8;  /* ambiguous without alpha */
 6335+            break;
 6336+    }
 6337+	return RGFW_formatARGB8;
 6338+}
 6339+
 6340+
 6341+RGFW_bool RGFW_window_createSurfacePtr(RGFW_window* win, u8* data, i32 w, i32 h, RGFW_format format, RGFW_surface* surface) {
 6342+	RGFW_ASSERT(surface != NULL);
 6343+	surface->data = data;
 6344+	surface->w = w;
 6345+	surface->h = h;
 6346+	surface->format = format;
 6347+
 6348+	XWindowAttributes attrs;
 6349+	if (XGetWindowAttributes(_RGFW->display, win->src.window, &attrs) == 0) {
 6350+		RGFW_debugCallback(RGFW_typeError, RGFW_errBuffer, "Failed to get window attributes.");
 6351+		return RGFW_FALSE;
 6352+	}
 6353+
 6354+	surface->native.bitmap = XCreateImage(_RGFW->display,  attrs.visual,  (u32)attrs.depth,
 6355+										ZPixmap, 0, NULL, (u32)surface->w, (u32)surface->h, 32, 0);
 6356+
 6357+	surface->native.buffer = (u8*)RGFW_ALLOC((size_t)(w * h * 4));
 6358+	surface->native.format = RGFW_XImage_getFormat(surface->native.bitmap);
 6359+
 6360+	if (surface->native.bitmap == NULL) {
 6361+		RGFW_debugCallback(RGFW_typeError, RGFW_errBuffer,  "Failed to create XImage.");
 6362+		return RGFW_FALSE;
 6363+	}
 6364+
 6365+	surface->native.format = RGFW_formatBGRA8;
 6366+	return RGFW_TRUE;
 6367+}
 6368+
 6369+RGFW_format RGFW_FUNC(RGFW_nativeFormat)(void) { return RGFW_formatBGRA8; }
 6370+
 6371+RGFW_bool RGFW_FUNC(RGFW_createSurfacePtr) (u8* data, i32 w, i32 h, RGFW_format format, RGFW_surface* surface) {
 6372+	return RGFW_window_createSurfacePtr(_RGFW->root, data, w, h, format, surface);
 6373+}
 6374+
 6375+void RGFW_FUNC(RGFW_window_blitSurface) (RGFW_window* win, RGFW_surface* surface) {
 6376+	RGFW_ASSERT(surface != NULL);
 6377+	surface->native.bitmap->data = (char*)surface->native.buffer;
 6378+	RGFW_copyImageData((u8*)surface->native.buffer, surface->w, RGFW_MIN(win->h, surface->h), surface->native.format, surface->data, surface->format, surface->convertFunc);
 6379+
 6380+	XPutImage(_RGFW->display, win->src.window, win->src.gc, surface->native.bitmap, 0, 0, 0, 0, (u32)RGFW_MIN(win->w, surface->w), (u32)RGFW_MIN(win->h, surface->h));
 6381+	surface->native.bitmap->data = NULL;
 6382+	return;
 6383+}
 6384+
 6385+void RGFW_FUNC(RGFW_surface_freePtr) (RGFW_surface* surface) {
 6386+	RGFW_ASSERT(surface != NULL);
 6387+	RGFW_FREE(surface->native.buffer);
 6388+	XDestroyImage(surface->native.bitmap);
 6389+	return;
 6390+}
 6391+
 6392+#define RGFW_LOAD_ATOM(name) \
 6393+	static Atom name = 0; \
 6394+	if (name == 0) name = XInternAtom(_RGFW->display, #name, False);
 6395+
 6396+void RGFW_FUNC(RGFW_window_setBorder) (RGFW_window* win, RGFW_bool border) {
 6397+	RGFW_setBit(&win->internal.flags, RGFW_windowNoBorder, !border);
 6398+	RGFW_LOAD_ATOM(_MOTIF_WM_HINTS);
 6399+
 6400+	struct __x11WindowHints {
 6401+		unsigned long flags, functions, decorations, status;
 6402+		long input_mode;
 6403+	} hints;
 6404+	hints.flags = 2;
 6405+	hints.decorations = border;
 6406+
 6407+	XChangeProperty(_RGFW->display, win->src.window, _MOTIF_WM_HINTS, _MOTIF_WM_HINTS, 32, PropModeReplace, (u8*)&hints, 5);
 6408+
 6409+	if (RGFW_window_isHidden(win) == 0) {
 6410+		RGFW_window_hide(win);
 6411+		RGFW_window_show(win);
 6412+	}
 6413+}
 6414+
 6415+void RGFW_FUNC(RGFW_window_setRawMouseModePlatform) (RGFW_window* win, RGFW_bool state) {
 6416+	RGFW_UNUSED(win); RGFW_UNUSED(state);
 6417+}
 6418+
 6419+void RGFW_FUNC(RGFW_window_captureMousePlatform) (RGFW_window* win, RGFW_bool state) {
 6420+	if (state) {
 6421+		unsigned int event_mask = ButtonPressMask | ButtonReleaseMask | PointerMotionMask;
 6422+		XGrabPointer(_RGFW->display, win->src.window, True, event_mask, GrabModeAsync, GrabModeAsync, win->src.window, None, CurrentTime);
 6423+	} else {
 6424+		XUngrabPointer(_RGFW->display, CurrentTime);
 6425+	}
 6426+}
 6427+
 6428+#define RGFW_LOAD_LIBRARY(x, lib) if (x == NULL) x = dlopen(lib, RTLD_LAZY | RTLD_LOCAL)
 6429+#define RGFW_PROC_DEF(proc, name) if (name##SRC == NULL && proc != NULL) { \
 6430+	void* ptr = dlsym(proc, #name); \
 6431+	if (ptr != NULL) RGFW_MEMCPY(&name##SRC, &ptr, sizeof(PFN_##name)); \
 6432+}
 6433+
 6434+RGFWDEF void RGFW_window_getVisual(XVisualInfo* visual, RGFW_bool transparent);
 6435+void RGFW_window_getVisual(XVisualInfo* visual, RGFW_bool transparent) {
 6436+	visual->visual = DefaultVisual(_RGFW->display, DefaultScreen(_RGFW->display));
 6437+	visual->depth = DefaultDepth(_RGFW->display, DefaultScreen(_RGFW->display));
 6438+	if (transparent) {
 6439+		XMatchVisualInfo(_RGFW->display, DefaultScreen(_RGFW->display), 32, TrueColor, visual); /*!< for RGBA backgrounds */
 6440+		if (visual->depth != 32)
 6441+			RGFW_debugCallback(RGFW_typeWarning, RGFW_warningOpenGL, "Failed to load a 32-bit depth.");
 6442+	}
 6443+}
 6444+
 6445+RGFWDEF int RGFW_XErrorHandler(Display* display, XErrorEvent* ev);
 6446+int RGFW_XErrorHandler(Display* display, XErrorEvent* ev) {
 6447+    char errorText[512];
 6448+    XGetErrorText(display, ev->error_code, errorText, sizeof(errorText));
 6449+
 6450+    char buf[1024];
 6451+    RGFW_SNPRINTF(buf, sizeof(buf),  "[X Error] %s\n  Error code: %d\n  Request code: %d\n  Minor code: %d\n  Serial: %lu\n",
 6452+             errorText,
 6453+             ev->error_code, ev->request_code, ev->minor_code, ev->serial);
 6454+
 6455+    RGFW_debugCallback(RGFW_typeError, RGFW_errX11, buf);
 6456+    _RGFW->x11Error = ev;
 6457+    return 0;
 6458+}
 6459+
 6460+void RGFW_XCreateWindow (XVisualInfo visual, const char* name, RGFW_windowFlags flags, RGFW_window* win) {
 6461+	i64 event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask | FocusChangeMask |
 6462+						LeaveWindowMask | EnterWindowMask | ExposureMask | VisibilityChangeMask | PropertyChangeMask;
 6463+
 6464+	/* make X window attrubutes */
 6465+	XSetWindowAttributes swa;
 6466+    RGFW_MEMZERO(&swa, sizeof(swa));
 6467+
 6468+	win->src.parent = DefaultRootWindow(_RGFW->display);
 6469+
 6470+	Colormap cmap;
 6471+	swa.colormap = cmap = XCreateColormap(_RGFW->display,
 6472+		win->src.parent,
 6473+		visual.visual, AllocNone);
 6474+	swa.event_mask = event_mask;
 6475+    swa.background_pixmap = None;
 6476+
 6477+	/* create the window */
 6478+	win->src.window = XCreateWindow(_RGFW->display, win->src.parent, win->x, win->y, (u32)win->w, (u32)win->h,
 6479+		0, visual.depth, InputOutput, visual.visual,
 6480+		CWBorderPixel | CWColormap | CWEventMask, &swa);
 6481+
 6482+	win->src.flashEnd = 0;
 6483+
 6484+	XFreeColors(_RGFW->display, cmap, NULL, 0, 0);
 6485+
 6486+	XSaveContext(_RGFW->display, win->src.window, _RGFW->context, (XPointer)win);
 6487+
 6488+	win->src.gc = XCreateGC(_RGFW->display, win->src.window, 0, NULL);
 6489+
 6490+	if (_RGFW->im) {
 6491+		XIMCallback callback;
 6492+		callback.callback = (XIMProc) RGFW_x11_icCallback;
 6493+		callback.client_data = (XPointer) win;
 6494+
 6495+		win->src.ic = XCreateIC(_RGFW->im, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, XNClientWindow, win->src.window, XNFocusWindow, win->src.window, XNDestroyCallback, &callback, NULL);
 6496+	}
 6497+
 6498+
 6499+	/* In your .desktop app, if you set the property
 6500+	    StartupWMClass=RGFW that will assoicate the launcher icon
 6501+	     with your application - robrohan */
 6502+	if (_RGFW->className == NULL)
 6503+		_RGFW->className = (char*)name;
 6504+
 6505+	XClassHint hint;
 6506+	hint.res_class = (char*)_RGFW->className;
 6507+
 6508+	if (_RGFW->instName == NULL)	hint.res_name = (char*)name;
 6509+	else 						hint.res_name = (char*)_RGFW->instName;
 6510+
 6511+	XSetClassHint(_RGFW->display, win->src.window, &hint);
 6512+
 6513+	XWMHints hints;
 6514+	hints.flags = StateHint;
 6515+	hints.initial_state = NormalState;
 6516+
 6517+	XSetWMHints(_RGFW->display, win->src.window, &hints);
 6518+
 6519+	XSelectInput(_RGFW->display, (Drawable) win->src.window, event_mask); /*!< tell X11 what events we want */
 6520+
 6521+	/* make it so the user can't close the window until the program does */
 6522+    RGFW_LOAD_ATOM(WM_DELETE_WINDOW);
 6523+	XSetWMProtocols(_RGFW->display, (Drawable) win->src.window, &WM_DELETE_WINDOW, 1);
 6524+	/* set the background */
 6525+	RGFW_window_setName(win, name);
 6526+
 6527+	XMoveWindow(_RGFW->display, (Drawable) win->src.window, win->x, win->y); /*!< move the window to it's proper cords */
 6528+
 6529+	if (flags & RGFW_windowAllowDND) { /* init drag and drop atoms and turn on drag and drop for this window */
 6530+		win->internal.flags |= RGFW_windowAllowDND;
 6531+
 6532+		/* actions */
 6533+		Atom XdndAware = XInternAtom(_RGFW->display, "XdndAware", False);
 6534+		const u8 version = 5;
 6535+
 6536+		XChangeProperty(_RGFW->display, win->src.window,
 6537+			XdndAware, 4, 32,
 6538+			PropModeReplace, &version, 1); /*!< turns on drag and drop */
 6539+	}
 6540+
 6541+#ifdef RGFW_ADVANCED_SMOOTH_RESIZE
 6542+    RGFW_LOAD_ATOM(_NET_WM_SYNC_REQUEST_COUNTER)
 6543+    RGFW_LOAD_ATOM(_NET_WM_SYNC_REQUEST)
 6544+
 6545+    Atom protcols[2] = {_NET_WM_SYNC_REQUEST, WM_DELETE_WINDOW};
 6546+    XSetWMProtocols(_RGFW->display, win->src.window, protcols, 2);
 6547+
 6548+    XSyncValue initial_value;
 6549+    XSyncIntToValue(&initial_value, 0);
 6550+    win->src.counter = XSyncCreateCounter(_RGFW->display, initial_value);
 6551+
 6552+    XChangeProperty(_RGFW->display, win->src.window, _NET_WM_SYNC_REQUEST_COUNTER, XA_CARDINAL, 32, PropModeReplace, (u8*)&win->src.counter, 1);
 6553+#endif
 6554+
 6555+	win->src.x = win->x;
 6556+	win->src.y = win->y;
 6557+	win->src.w = win->w;
 6558+	win->src.h = win->h;
 6559+
 6560+	XSetWindowBackground(_RGFW->display, win->src.window, None);
 6561+    XClearWindow(_RGFW->display, win->src.window);
 6562+
 6563+	/* stupid hack to make resizing the window less bad */
 6564+	XSetWindowBackgroundPixmap(_RGFW->display, win->src.window, None);
 6565+}
 6566+
 6567+RGFW_window* RGFW_FUNC(RGFW_createWindowPlatform) (const char* name, RGFW_windowFlags flags, RGFW_window* win) {
 6568+	if ((flags & RGFW_windowOpenGL) || (flags & RGFW_windowEGL)) {
 6569+		win->src.window = 0;
 6570+		return win;
 6571+	}
 6572+
 6573+	XVisualInfo visual;
 6574+	RGFW_window_getVisual(&visual, RGFW_BOOL(win->internal.flags & RGFW_windowTransparent));
 6575+	RGFW_XCreateWindow(visual, name, flags, win);
 6576+	return win; /*return newly created window */
 6577+}
 6578+
 6579+RGFW_bool RGFW_FUNC(RGFW_getGlobalMouse) (i32* fX, i32* fY) {
 6580+	RGFW_init();
 6581+	i32 x, y;
 6582+	u32 z;
 6583+	Window window1, window2;
 6584+	XQueryPointer(_RGFW->display, XDefaultRootWindow(_RGFW->display), &window1, &window2, fX, fY, &x, &y, &z);
 6585+	return RGFW_TRUE;
 6586+}
 6587+
 6588+RGFWDEF void RGFW_XHandleClipboardSelection(XEvent* event);
 6589+void RGFW_XHandleClipboardSelection(XEvent* event) { RGFW_UNUSED(event);
 6590+    RGFW_LOAD_ATOM(ATOM_PAIR);
 6591+	RGFW_LOAD_ATOM(MULTIPLE);
 6592+	RGFW_LOAD_ATOM(TARGETS);
 6593+	RGFW_LOAD_ATOM(SAVE_TARGETS);
 6594+	RGFW_LOAD_ATOM(UTF8_STRING);
 6595+
 6596+    const XSelectionRequestEvent* request = &event->xselectionrequest;
 6597+    Atom formats[2] = {0};
 6598+    formats[0] = UTF8_STRING;
 6599+    formats[1] = XA_STRING;
 6600+    const int formatCount = sizeof(formats) / sizeof(formats[0]);
 6601+
 6602+    if (request->target == TARGETS) {
 6603+        Atom targets[4] = {0};
 6604+        targets[0] = TARGETS;
 6605+        targets[1] = MULTIPLE;
 6606+        targets[2] = UTF8_STRING;
 6607+        targets[3] = XA_STRING;
 6608+
 6609+        XChangeProperty(_RGFW->display, request->requestor, request->property,
 6610+                        XA_ATOM, 32, PropModeReplace, (u8*) targets, sizeof(targets) / sizeof(Atom));
 6611+    }  else if (request->target == MULTIPLE) {
 6612+		Atom* targets = NULL;
 6613+
 6614+		Atom actualType = 0;
 6615+		int actualFormat = 0;
 6616+		unsigned long count = 0, bytesAfter = 0;
 6617+
 6618+		XGetWindowProperty(_RGFW->display, request->requestor, request->property, 0, LONG_MAX,
 6619+							False, ATOM_PAIR, &actualType, &actualFormat, &count, &bytesAfter, (u8**) &targets);
 6620+
 6621+		unsigned long i;
 6622+		for (i = 0; i < (u32)count; i += 2) {
 6623+			if (targets[i] == UTF8_STRING || targets[i] == XA_STRING)
 6624+				XChangeProperty(_RGFW->display, request->requestor, targets[i + 1], targets[i],
 6625+					8, PropModeReplace, (const unsigned char *)_RGFW->clipboard, (i32)_RGFW->clipboard_len);
 6626+			else
 6627+				targets[i + 1] = None;
 6628+		}
 6629+
 6630+		XChangeProperty(_RGFW->display,
 6631+			request->requestor, request->property, ATOM_PAIR, 32,
 6632+			PropModeReplace, (u8*) targets, (i32)count);
 6633+
 6634+		XFlush(_RGFW->display);
 6635+		XFree(targets);
 6636+	} else if (request->target == SAVE_TARGETS)
 6637+        XChangeProperty(_RGFW->display, request->requestor, request->property, 0, 32, PropModeReplace, NULL, 0);
 6638+    else {
 6639+        int i;
 6640+        for (i = 0;  i < formatCount;  i++) {
 6641+			if (request->target != formats[i])
 6642+				continue;
 6643+			XChangeProperty(_RGFW->display, request->requestor, request->property, request->target,
 6644+								8, PropModeReplace, (u8*) _RGFW->clipboard, (i32)_RGFW->clipboard_len);
 6645+		}
 6646+	}
 6647+
 6648+    XEvent reply = { SelectionNotify };
 6649+    reply.xselection.property = request->property;
 6650+    reply.xselection.display = request->display;
 6651+    reply.xselection.requestor = request->requestor;
 6652+    reply.xselection.selection = request->selection;
 6653+    reply.xselection.target = request->target;
 6654+    reply.xselection.time = request->time;
 6655+
 6656+    XSendEvent(_RGFW->display, request->requestor, False, 0, &reply);
 6657+	XFlush(_RGFW->display);
 6658+}
 6659+
 6660+i32 RGFW_XHandleClipboardSelectionHelper(void);
 6661+
 6662+RGFW_key RGFW_FUNC(RGFW_physicalToMappedKey) (RGFW_key key) {
 6663+    KeyCode keycode = (KeyCode)RGFW_rgfwToApiKey(key);
 6664+    KeySym sym = XkbKeycodeToKeysym(_RGFW->display, keycode, 0, 0);
 6665+
 6666+    if (sym < 256) {
 6667+        return (RGFW_key)sym;
 6668+    }
 6669+
 6670+    switch (sym) {
 6671+        case XK_F1:  return RGFW_keyF1;
 6672+        case XK_F2:  return RGFW_keyF2;
 6673+        case XK_F3:  return RGFW_keyF3;
 6674+        case XK_F4:  return RGFW_keyF4;
 6675+        case XK_F5:  return RGFW_keyF5;
 6676+        case XK_F6:  return RGFW_keyF6;
 6677+        case XK_F7:  return RGFW_keyF7;
 6678+        case XK_F8:  return RGFW_keyF8;
 6679+        case XK_F9:  return RGFW_keyF9;
 6680+        case XK_F10: return RGFW_keyF10;
 6681+        case XK_F11: return RGFW_keyF11;
 6682+        case XK_F12: return RGFW_keyF12;
 6683+        case XK_F13: return RGFW_keyF13;
 6684+        case XK_F14: return RGFW_keyF14;
 6685+        case XK_F15: return RGFW_keyF15;
 6686+        case XK_F16: return RGFW_keyF16;
 6687+        case XK_F17: return RGFW_keyF17;
 6688+        case XK_F18: return RGFW_keyF18;
 6689+        case XK_F19: return RGFW_keyF19;
 6690+        case XK_F20: return RGFW_keyF20;
 6691+        case XK_F21: return RGFW_keyF21;
 6692+        case XK_F22: return RGFW_keyF22;
 6693+        case XK_F23: return RGFW_keyF23;
 6694+        case XK_F24: return RGFW_keyF24;
 6695+        case XK_F25: return RGFW_keyF25;
 6696+        case XK_Shift_L:   return RGFW_keyShiftL;
 6697+        case XK_Shift_R:   return RGFW_keyShiftR;
 6698+        case XK_Control_L: return RGFW_keyControlL;
 6699+        case XK_Control_R: return RGFW_keyControlR;
 6700+        case XK_Alt_L:     return RGFW_keyAltL;
 6701+        case XK_Alt_R:     return RGFW_keyAltR;
 6702+        case XK_Super_L:   return RGFW_keySuperL;
 6703+        case XK_Super_R:   return RGFW_keySuperR;
 6704+        case XK_Caps_Lock: return RGFW_keyCapsLock;
 6705+        case XK_Num_Lock:  return RGFW_keyNumLock;
 6706+        case XK_Scroll_Lock:return RGFW_keyScrollLock;
 6707+        case XK_Up:        return RGFW_keyUp;
 6708+        case XK_Down:      return RGFW_keyDown;
 6709+        case XK_Left:      return RGFW_keyLeft;
 6710+        case XK_Right:     return RGFW_keyRight;
 6711+        case XK_Home:      return RGFW_keyHome;
 6712+        case XK_End:       return RGFW_keyEnd;
 6713+        case XK_Page_Up:   return RGFW_keyPageUp;
 6714+        case XK_Page_Down: return RGFW_keyPageDown;
 6715+        case XK_Insert:    return RGFW_keyInsert;
 6716+        case XK_Menu:      return RGFW_keyMenu;
 6717+        case XK_KP_Add:      return RGFW_keyPadPlus;
 6718+        case XK_KP_Subtract: return RGFW_keyPadMinus;
 6719+        case XK_KP_Multiply: return RGFW_keyPadMultiply;
 6720+        case XK_KP_Divide:   return RGFW_keyPadSlash;
 6721+        case XK_KP_Equal:    return RGFW_keyPadEqual;
 6722+        case XK_KP_Enter:    return RGFW_keyPadReturn;
 6723+        case XK_KP_Decimal:  return RGFW_keyPadPeriod;
 6724+        case XK_KP_0: return RGFW_keyPad0;
 6725+        case XK_KP_1: return RGFW_keyPad1;
 6726+        case XK_KP_2: return RGFW_keyPad2;
 6727+        case XK_KP_3: return RGFW_keyPad3;
 6728+        case XK_KP_4: return RGFW_keyPad4;
 6729+        case XK_KP_5: return RGFW_keyPad5;
 6730+        case XK_KP_6: return RGFW_keyPad6;
 6731+        case XK_KP_7: return RGFW_keyPad7;
 6732+        case XK_KP_8: return RGFW_keyPad8;
 6733+        case XK_KP_9: return RGFW_keyPad9;
 6734+        case XK_Print: return RGFW_keyPrintScreen;
 6735+        case XK_Pause: return RGFW_keyPause;
 6736+        default: break;
 6737+    }
 6738+
 6739+    return RGFW_keyNULL;
 6740+}
 6741+
 6742+RGFWDEF void RGFW_XHandleEvent(void);
 6743+void RGFW_XHandleEvent(void) {
 6744+	RGFW_LOAD_ATOM(XdndTypeList);
 6745+	RGFW_LOAD_ATOM(XdndSelection);
 6746+	RGFW_LOAD_ATOM(XdndEnter);
 6747+	RGFW_LOAD_ATOM(XdndPosition);
 6748+	RGFW_LOAD_ATOM(XdndStatus);
 6749+	RGFW_LOAD_ATOM(XdndLeave);
 6750+	RGFW_LOAD_ATOM(XdndDrop);
 6751+	RGFW_LOAD_ATOM(XdndFinished);
 6752+	RGFW_LOAD_ATOM(XdndActionCopy);
 6753+	RGFW_LOAD_ATOM(_NET_WM_SYNC_REQUEST);
 6754+	RGFW_LOAD_ATOM(WM_PROTOCOLS);
 6755+	RGFW_LOAD_ATOM(WM_STATE);
 6756+	RGFW_LOAD_ATOM(_NET_WM_STATE);
 6757+
 6758+	static float deltaX = 0.0f;
 6759+	static float deltaY = 0.0f;
 6760+
 6761+	XEvent E;
 6762+
 6763+	XNextEvent(_RGFW->display, &E);
 6764+
 6765+	if (E.type != GenericEvent) {
 6766+		deltaX = 0.0f;
 6767+		deltaY = 0.0f;
 6768+	}
 6769+
 6770+	if (E.type == _RGFW->xrandrEventBase + RRNotify) {
 6771+		RGFW_pollMonitors();
 6772+		return;
 6773+	}
 6774+
 6775+	switch (E.type) {
 6776+		case SelectionRequest:
 6777+			RGFW_XHandleClipboardSelection(&E);
 6778+			return;
 6779+		case GenericEvent: {
 6780+			XGetEventData(_RGFW->display, &E.xcookie);
 6781+			switch (E.xcookie.evtype) {
 6782+				case XI_RawMotion: {
 6783+					XIRawEvent* raw = (XIRawEvent *)E.xcookie.data;
 6784+					if (raw->valuators.mask_len == 0) {
 6785+						XFreeEventData(_RGFW->display, &E.xcookie);
 6786+						return;
 6787+					}
 6788+
 6789+					i32 index = 0;
 6790+					if (XIMaskIsSet(raw->valuators.mask, 0) != 0) {
 6791+						deltaX += (float)raw->raw_values[index];
 6792+						index += 1;
 6793+					}
 6794+
 6795+					if (XIMaskIsSet(raw->valuators.mask, 1) != 0)
 6796+						deltaY += (float)raw->raw_values[index];
 6797+
 6798+					_RGFW->vectorX = (float)deltaX;
 6799+					_RGFW->vectorY = (float)deltaY;
 6800+					RGFW_rawMotionCallback(_RGFW->root, _RGFW->vectorX, _RGFW->vectorY);
 6801+				}
 6802+				default: break;
 6803+			}
 6804+
 6805+			XFreeEventData(_RGFW->display, &E.xcookie);
 6806+			return;
 6807+		}
 6808+	}
 6809+
 6810+	RGFW_window* win = NULL;
 6811+	if (XFindContext(_RGFW->display, E.xany.window, _RGFW->context, (XPointer*) &win) != 0) {
 6812+		return;
 6813+	}
 6814+
 6815+	if (win->src.flashEnd) {
 6816+		if ((win->src.flashEnd <= RGFW_linux_getTimeNS()) || RGFW_window_isInFocus(win)) {
 6817+			RGFW_window_flash(win, RGFW_flashCancel);
 6818+		}
 6819+	}
 6820+
 6821+
 6822+	/*
 6823+		Repeated key presses are sent as a release followed by another press at the same time.
 6824+		We want to convert that into a single key press event with the repeat flag set
 6825+	*/
 6826+
 6827+	RGFW_bool keyRepeat = RGFW_FALSE;
 6828+
 6829+	if (E.type == KeyRelease && XEventsQueued(_RGFW->display, QueuedAfterReading)) {
 6830+		XEvent NE;
 6831+		XPeekEvent(_RGFW->display, &NE);
 6832+		if (NE.type == KeyPress && E.xkey.time == NE.xkey.time && E.xkey.keycode == NE.xkey.keycode) {
 6833+			/* Use the next KeyPress event */
 6834+			XNextEvent(_RGFW->display, &E);
 6835+			keyRepeat = RGFW_TRUE;
 6836+		}
 6837+	}
 6838+
 6839+	switch (E.type) {
 6840+		case KeyPress: {
 6841+			if (!(win->internal.enabledEvents & RGFW_keyPressedFlag)) return;
 6842+			RGFW_key value = (u8)RGFW_apiKeyToRGFW(E.xkey.keycode);
 6843+
 6844+			XkbStateRec state;
 6845+			XkbGetState(_RGFW->display, XkbUseCoreKbd, &state);
 6846+			RGFW_keyUpdateKeyMods(win, (state.locked_mods & LockMask), (state.locked_mods & Mod2Mask), (state.locked_mods & Mod3Mask));
 6847+
 6848+			if (win->src.ic && XFilterEvent(&E, None) == False) {
 6849+				char buffer[100];
 6850+				char* chars = buffer;
 6851+
 6852+				Status status;
 6853+				size_t count = (size_t)Xutf8LookupString(win->src.ic, &E.xkey, buffer, sizeof(buffer) - 1, NULL, &status);
 6854+
 6855+				if (status == XBufferOverflow) {
 6856+					chars = (char*)RGFW_ALLOC(count + 1);
 6857+					count = (size_t)Xutf8LookupString(win->src.ic, &E.xkey, chars, (int)count, NULL, &status);
 6858+				}
 6859+
 6860+				if (status == XLookupChars || status == XLookupBoth) {
 6861+					chars[count] = '\0';
 6862+					for (size_t index = 0; index < count;
 6863+						RGFW_keyCharCallback(win, RGFW_decodeUTF8(&chars[index], &index))
 6864+					);
 6865+				}
 6866+
 6867+				if (chars != buffer)
 6868+					RGFW_FREE(chars);
 6869+			} else {
 6870+				Window root = DefaultRootWindow(_RGFW->display);
 6871+				Window ret_root, ret_child;
 6872+				int root_x, root_y, win_x, win_y;
 6873+				unsigned int mask;
 6874+				XQueryPointer(_RGFW->display, root, &ret_root, &ret_child, &root_x, &root_y, &win_x, &win_y, &mask);
 6875+				KeySym sym = (KeySym)XkbKeycodeToKeysym(_RGFW->display, (KeyCode)E.xkey.keycode, 0, (KeyCode)mask & ShiftMask ? 1 : 0);
 6876+
 6877+				if ((mask & LockMask) && sym >= XK_a && sym <= XK_z)
 6878+					sym = (mask & ShiftMask) ? sym + 32 : sym - 32;
 6879+				if ((u8)sym != (u32)sym)
 6880+					sym = 0;
 6881+
 6882+				RGFW_keyCharCallback(win, (u8)sym);
 6883+			}
 6884+
 6885+			RGFW_keyCallback(win, value, win->internal.mod, keyRepeat, RGFW_TRUE);
 6886+			break;
 6887+		}
 6888+		case KeyRelease: {
 6889+			if (!(win->internal.enabledEvents & RGFW_keyReleasedFlag)) return;
 6890+
 6891+			RGFW_key value = (u8)RGFW_apiKeyToRGFW(E.xkey.keycode);
 6892+
 6893+			XkbStateRec state;
 6894+			XkbGetState(_RGFW->display, XkbUseCoreKbd, &state);
 6895+			RGFW_keyUpdateKeyMods(win, (state.locked_mods & LockMask), (state.locked_mods & Mod2Mask), (state.locked_mods & Mod3Mask));
 6896+
 6897+			RGFW_keyCallback(win, value, win->internal.mod, RGFW_FALSE, RGFW_FALSE);
 6898+			break;
 6899+		}
 6900+		case ButtonPress: {
 6901+			RGFW_bool scroll = RGFW_FALSE;
 6902+			if (E.xbutton.button >= Button4 && E.xbutton.button <= 7) {
 6903+				scroll = RGFW_TRUE;
 6904+			}
 6905+
 6906+			float scrollX = 0.0f;
 6907+			float scrollY = 0.0f;
 6908+			RGFW_mouseButton value = 0;
 6909+
 6910+			switch (E.xbutton.button) {
 6911+				case Button1: value = RGFW_mouseLeft; break;
 6912+				case Button2: value = RGFW_mouseMiddle; break;
 6913+				case Button3: value = RGFW_mouseRight; break;
 6914+				case Button4: scrollY = 1.0; break;
 6915+				case Button5: scrollY = -1.0; break;
 6916+				case 6: scrollX = 1.0f; break;
 6917+				case 7: scrollX = -1.0f; break;
 6918+				default:
 6919+					value = (u8)E.xbutton.button - Button1 - 4;
 6920+					break;
 6921+			}
 6922+
 6923+			if (scroll) {
 6924+				RGFW_mouseScrollCallback(win, scrollX, scrollY);
 6925+				break;
 6926+			}
 6927+
 6928+			RGFW_mouseButtonCallback(win, value, RGFW_TRUE);
 6929+			break;
 6930+		}
 6931+		case ButtonRelease: {
 6932+			if (E.xbutton.button >= Button4 && E.xbutton.button <= 7) break;
 6933+
 6934+			RGFW_mouseButton value = 0;
 6935+			switch(E.xbutton.button) {
 6936+				case Button1: value = RGFW_mouseLeft; break;
 6937+				case Button2: value = RGFW_mouseMiddle; break;
 6938+				case Button3: value = RGFW_mouseRight; break;
 6939+				default:
 6940+					value = (u8)E.xbutton.button - Button1 - 4;
 6941+					break;
 6942+			}
 6943+
 6944+			RGFW_mouseButtonCallback(win, value, RGFW_FALSE);
 6945+			break;
 6946+		}
 6947+		case MotionNotify:
 6948+			RGFW_mousePosCallback(win, E.xmotion.x, E.xmotion.y);
 6949+			break;
 6950+
 6951+		case Expose: {
 6952+			RGFW_windowRefreshCallback(win, 0, 0, win->w, win->h);
 6953+
 6954+#ifdef RGFW_ADVANCED_SMOOTH_RESIZE
 6955+			XSyncValue value;
 6956+			XSyncIntToValue(&value, (i32)win->src.counter_value);
 6957+			XSyncSetCounter(_RGFW->display, win->src.counter, value);
 6958+#endif
 6959+			break;
 6960+		}
 6961+
 6962+		case PropertyNotify:
 6963+			if (E.xproperty.state != PropertyNewValue) break;
 6964+
 6965+			if (E.xproperty.atom == WM_STATE) {
 6966+				if (RGFW_window_isMinimized(win) && !(win->internal.flags & RGFW_windowMinimized)) {
 6967+					RGFW_windowMinimizedCallback(win);
 6968+					break;
 6969+				}
 6970+			} else if (E.xproperty.atom == _NET_WM_STATE) {
 6971+				if (RGFW_window_isMaximized(win) && !(win->internal.flags & RGFW_windowMaximize)) {
 6972+					RGFW_windowMaximizedCallback(win, win->x, win->y, win->w, win->h);
 6973+					break;
 6974+				}
 6975+			}
 6976+
 6977+			RGFW_window_checkMode(win);
 6978+			break;
 6979+		case MapNotify: case UnmapNotify: 		RGFW_window_checkMode(win); break;
 6980+		case ClientMessage: {
 6981+			RGFW_LOAD_ATOM(WM_DELETE_WINDOW);
 6982+			/* if the client closed the window */
 6983+			if (E.xclient.data.l[0] == (long)WM_DELETE_WINDOW) {
 6984+				RGFW_windowCloseCallback(win);
 6985+				break;
 6986+			}
 6987+#ifdef RGFW_ADVANCED_SMOOTH_RESIZE
 6988+			if (E.xclient.message_type == WM_PROTOCOLS && (Atom)E.xclient.data.l[0] == _NET_WM_SYNC_REQUEST) {
 6989+				RGFW_windowRefreshCallback(win, 0, 0, win->w, win->h);
 6990+				win->src.counter_value = 0;
 6991+				win->src.counter_value |= E.xclient.data.l[2];
 6992+				win->src.counter_value |= (E.xclient.data.l[3] << 32);
 6993+
 6994+				XSyncValue value;
 6995+				XSyncIntToValue(&value, (i32)win->src.counter_value);
 6996+				XSyncSetCounter(_RGFW->display, win->src.counter, value);
 6997+				break;
 6998+			}
 6999+#endif
 7000+			if ((win->internal.flags & RGFW_windowAllowDND) == 0 || _RGFW->x11Version > RGFW_XDND_VERSION) {
 7001+				return;
 7002+			}
 7003+
 7004+			i32 dragX = 0;
 7005+			i32 dragY = 0;
 7006+
 7007+			if (E.xclient.message_type == XdndEnter) {
 7008+				unsigned long count;
 7009+				Atom* formats;
 7010+				Atom real_formats[3];
 7011+				Bool list = E.xclient.data.l[1] & 1;
 7012+
 7013+				_RGFW->x11Source = (Window)E.xclient.data.l[0];
 7014+				_RGFW->x11Version = E.xclient.data.l[1] >> 24;
 7015+				_RGFW->x11Format = None;
 7016+				if (list) {
 7017+					Atom actualType;
 7018+					i32 actualFormat;
 7019+					unsigned long bytesAfter;
 7020+
 7021+					XGetWindowProperty(
 7022+						_RGFW->display, _RGFW->x11Source, XdndTypeList,
 7023+						0, LONG_MAX, False, 4,
 7024+						&actualType, &actualFormat, &count, &bytesAfter, (u8**)&formats
 7025+					);
 7026+				} else {
 7027+					count = 0;
 7028+
 7029+					size_t i;
 7030+					for (i = 2; i < (2 + 3); i++) {
 7031+						if (E.xclient.data.l[i] != None) {
 7032+							real_formats[count] = (unsigned long int)E.xclient.data.l[i];
 7033+							count += 1;
 7034+						}
 7035+					}
 7036+
 7037+					formats = real_formats;
 7038+				}
 7039+
 7040+				Atom XtextPlain = XInternAtom(_RGFW->display, "text/plain", False);
 7041+				Atom XtextUriList = XInternAtom(_RGFW->display, "text/uri-list", False);
 7042+
 7043+				size_t i;
 7044+				for (i = 0; i < count; i++) {
 7045+					if (formats[i] == XtextUriList)  _RGFW->x11TransferType  = RGFW_dataFile;
 7046+					else if (formats[i] == XtextPlain) _RGFW->x11TransferType  = RGFW_dataText;
 7047+					else continue;
 7048+
 7049+					_RGFW->x11Format = (int)formats[i];
 7050+					break;
 7051+				}
 7052+
 7053+				if (list && formats) {
 7054+					XFree(formats);
 7055+				}
 7056+
 7057+
 7058+				RGFW_dataDragCallback(win, _RGFW->x11TransferType , RGFW_dndActionEnter, dragX, dragY);
 7059+			} else if (E.xclient.message_type == XdndPosition) {
 7060+				const i32 xabs = (E.xclient.data.l[2] >> 16) & 0xffff;
 7061+				const i32 yabs = (E.xclient.data.l[2]) & 0xffff;
 7062+				Window dummy;
 7063+				i32 xpos, ypos;
 7064+
 7065+				XTranslateCoordinates(
 7066+					_RGFW->display, XDefaultRootWindow(_RGFW->display), win->src.window,
 7067+					xabs, yabs, &xpos, &ypos, &dummy
 7068+				);
 7069+
 7070+				dragX = xpos;
 7071+				dragY = ypos;
 7072+
 7073+				RGFW_mousePosCallback(win, xpos, ypos);
 7074+                XEvent reply = { ClientMessage };
 7075+				reply.xclient.window = _RGFW->x11Source;
 7076+                reply.xclient.message_type = XdndStatus;
 7077+                reply.xclient.format = 32;
 7078+				reply.xclient.data.l[0] = (long)win->src.window;
 7079+                reply.xclient.data.l[2] = 0;
 7080+                reply.xclient.data.l[3] = 0;
 7081+
 7082+				if (_RGFW->x11Format) {
 7083+					reply.xclient.data.l[1] = 1;
 7084+					if (_RGFW->x11Version >= 2)
 7085+						reply.xclient.data.l[4] = (long)XdndActionCopy;
 7086+				}
 7087+
 7088+				XSendEvent(_RGFW->display, _RGFW->x11Source, False, NoEventMask, &reply);
 7089+				XFlush(_RGFW->display);
 7090+
 7091+
 7092+				RGFW_dataDragCallback(win, _RGFW->x11TransferType, RGFW_dndActionMove, dragX, dragY);
 7093+			} else if (E.xclient.message_type == XdndLeave) {
 7094+				RGFW_dataDragCallback(win, _RGFW->x11TransferType, RGFW_dndActionExit, dragX, dragY);
 7095+			} else if (E.xclient.message_type == XdndDrop) {
 7096+				if (_RGFW->x11Format) {
 7097+					Time time = (_RGFW->x11Version >= 1)
 7098+						? (Time)E.xclient.data.l[2]
 7099+						: CurrentTime;
 7100+					XConvertSelection(
 7101+						_RGFW->display, XdndSelection, (Atom)_RGFW->x11Format,
 7102+						XdndSelection, win->src.window, time
 7103+					);
 7104+				} else if (_RGFW->x11Version >= 2) {
 7105+                    XEvent reply = { ClientMessage };
 7106+                    reply.xclient.window = _RGFW->x11Source;
 7107+                    reply.xclient.message_type = XdndFinished;
 7108+                    reply.xclient.format = 32;
 7109+                    reply.xclient.data.l[0] = (long)win->src.window;
 7110+                    reply.xclient.data.l[1] = 0;
 7111+                    reply.xclient.data.l[2] = None;
 7112+
 7113+					XSendEvent(_RGFW->display, _RGFW->x11Source, False, NoEventMask, &reply);
 7114+					XFlush(_RGFW->display);
 7115+				}
 7116+			}
 7117+		} break;
 7118+		case SelectionNotify: {
 7119+			/* this is only for checking for xdnd drops */
 7120+			if (!(win->internal.enabledEvents & RGFW_dataDropFlag) || E.xselection.property != XdndSelection || !(win->internal.flags & RGFW_windowAllowDND))
 7121+				return;
 7122+			char* data;
 7123+			unsigned long result;
 7124+
 7125+			Atom actualType;
 7126+			i32 actualFormat;
 7127+			unsigned long bytesAfter;
 7128+
 7129+			XGetWindowProperty(_RGFW->display, E.xselection.requestor, E.xselection.property, 0, LONG_MAX, False, E.xselection.target, &actualType, &actualFormat, &result, &bytesAfter, (u8**) &data);
 7130+
 7131+			if (result != 0) {
 7132+				RGFW_unix_parseURI(win, data);
 7133+
 7134+				if (data)
 7135+					XFree(data);
 7136+			}
 7137+
 7138+			if (_RGFW->x11Version >= 2) {
 7139+				XEvent reply = { ClientMessage };
 7140+				reply.xclient.window = _RGFW->x11Source;
 7141+				reply.xclient.message_type = XdndFinished;
 7142+				reply.xclient.format = 32;
 7143+				reply.xclient.data.l[0] = (long)win->src.window;
 7144+				reply.xclient.data.l[1] = (long int)result;
 7145+				reply.xclient.data.l[2] = (long int)XdndActionCopy;
 7146+				XSendEvent(_RGFW->display, _RGFW->x11Source, False, NoEventMask, &reply);
 7147+				XFlush(_RGFW->display);
 7148+			}
 7149+			break;
 7150+		}
 7151+		case FocusIn:
 7152+            if (win->src.ic) XSetICFocus(win->src.ic);
 7153+			RGFW_windowFocusCallback(win, 1);
 7154+			break;
 7155+		case FocusOut:
 7156+            if (win->src.ic) XUnsetICFocus(win->src.ic);
 7157+			RGFW_windowFocusCallback(win, 0);
 7158+			break;
 7159+		case EnterNotify: {
 7160+			RGFW_mouseNotifyCallback(win, E.xcrossing.x, E.xcrossing.y, RGFW_TRUE);
 7161+			break;
 7162+		}
 7163+
 7164+		case LeaveNotify: {
 7165+			RGFW_mouseNotifyCallback(win, win->internal.lastMouseX, win->internal.lastMouseY, RGFW_FALSE);
 7166+			break;
 7167+		}
 7168+        case ReparentNotify:
 7169+            win->src.parent = E.xreparent.parent;
 7170+			break;
 7171+		case ConfigureNotify: {
 7172+			/* detect resize */
 7173+			if (E.xconfigure.width != win->src.w || E.xconfigure.height != win->src.h) {
 7174+				RGFW_window_checkMode(win);
 7175+				win->src.w = E.xconfigure.width;
 7176+				win->src.h = E.xconfigure.height;
 7177+				RGFW_windowResizedCallback(win, E.xconfigure.width, E.xconfigure.height);
 7178+			}
 7179+
 7180+			i32 x = E.xconfigure.x;
 7181+			i32 y = E.xconfigure.y;
 7182+
 7183+			/*
 7184+			 if the event came from the server and we're not a direct child of the root window then
 7185+			 we're using local coords which need to be translated into screen coords
 7186+			*/
 7187+			Window root = DefaultRootWindow(_RGFW->display);
 7188+			if (E.xany.send_event == 0 && win->src.parent != root) {
 7189+				Window dummy = 0;
 7190+				XTranslateCoordinates(_RGFW->display, win->src.parent, root, x, y, &x, &y, &dummy);
 7191+			}
 7192+
 7193+			/* detect move */
 7194+			if (E.xconfigure.x != win->src.x || E.xconfigure.y != win->src.y) {
 7195+				win->src.x = E.xconfigure.x;
 7196+				win->src.y = E.xconfigure.y;
 7197+				RGFW_windowMovedCallback(win, E.xconfigure.x, E.xconfigure.y);
 7198+			}
 7199+			return;
 7200+		}
 7201+		default:
 7202+			break;
 7203+	}
 7204+
 7205+	XFlush(_RGFW->display);
 7206+}
 7207+
 7208+RGFW_bool RGFW_FUNC(RGFW_window_fetchSize) (RGFW_window* win, i32* w, i32* h) {
 7209+    XWindowAttributes attribs;
 7210+    XGetWindowAttributes(_RGFW->display, win->src.window, &attribs);
 7211+
 7212+    win->w = attribs.width;
 7213+    win->h = attribs.height;
 7214+
 7215+	return RGFW_window_getSize(win, w, h);
 7216+}
 7217+
 7218+void RGFW_FUNC(RGFW_pollEvents) (void) {
 7219+	RGFW_resetPrevState();
 7220+
 7221+	XPending(_RGFW->display);
 7222+    /* if there is no unread queued events, get a new one */
 7223+	while (QLength(_RGFW->display)) {
 7224+		RGFW_XHandleEvent();
 7225+	}
 7226+}
 7227+
 7228+void RGFW_FUNC(RGFW_window_move) (RGFW_window* win, i32 x, i32 y) {
 7229+	RGFW_ASSERT(win != NULL);
 7230+	win->x = x;
 7231+	win->y = y;
 7232+
 7233+	XMoveWindow(_RGFW->display, win->src.window, x, y);
 7234+	return;
 7235+}
 7236+
 7237+
 7238+void RGFW_FUNC(RGFW_window_resize) (RGFW_window* win, i32 w, i32 h) {
 7239+	RGFW_ASSERT(win != NULL);
 7240+	win->w = (i32)w;
 7241+	win->h = (i32)h;
 7242+
 7243+	XResizeWindow(_RGFW->display, win->src.window, (u32)w, (u32)h);
 7244+
 7245+	if ((win->internal.flags & RGFW_windowNoResize)) {
 7246+		XSizeHints sh;
 7247+		sh.flags = (1L << 4) | (1L << 5);
 7248+		sh.min_width = sh.max_width = (i32)w;
 7249+		sh.min_height = sh.max_height = (i32)h;
 7250+
 7251+		XSetWMSizeHints(_RGFW->display, (Drawable) win->src.window, &sh, XA_WM_NORMAL_HINTS);
 7252+	}
 7253+	return;
 7254+}
 7255+
 7256+void RGFW_FUNC(RGFW_window_setAspectRatio) (RGFW_window* win, i32 w, i32 h) {
 7257+	RGFW_ASSERT(win != NULL);
 7258+
 7259+
 7260+	if (w == 0 && h == 0)
 7261+		return;
 7262+	XSizeHints hints;
 7263+	long flags;
 7264+
 7265+	XGetWMNormalHints(_RGFW->display, win->src.window, &hints, &flags);
 7266+
 7267+	hints.flags |= PAspect;
 7268+
 7269+	hints.min_aspect.x = hints.max_aspect.x = (i32)w;
 7270+	hints.min_aspect.y = hints.max_aspect.y = (i32)h;
 7271+
 7272+	XSetWMNormalHints(_RGFW->display, win->src.window, &hints);
 7273+    return;
 7274+}
 7275+
 7276+void RGFW_FUNC(RGFW_window_setMinSize) (RGFW_window* win, i32 w, i32 h) {
 7277+	RGFW_ASSERT(win != NULL);
 7278+
 7279+    long flags;
 7280+	XSizeHints hints;
 7281+    RGFW_MEMZERO(&hints, sizeof(XSizeHints));
 7282+
 7283+	XGetWMNormalHints(_RGFW->display, win->src.window, &hints, &flags);
 7284+
 7285+	hints.flags |= PMinSize;
 7286+
 7287+	hints.min_width = (i32)w;
 7288+	hints.min_height = (i32)h;
 7289+
 7290+	XSetWMNormalHints(_RGFW->display, win->src.window, &hints);
 7291+    return;
 7292+}
 7293+
 7294+void RGFW_FUNC(RGFW_window_setMaxSize) (RGFW_window* win, i32 w, i32 h) {
 7295+	RGFW_ASSERT(win != NULL);
 7296+
 7297+    long flags;
 7298+	XSizeHints hints;
 7299+    RGFW_MEMZERO(&hints, sizeof(XSizeHints));
 7300+
 7301+	XGetWMNormalHints(_RGFW->display, win->src.window, &hints, &flags);
 7302+
 7303+	hints.flags |= PMaxSize;
 7304+
 7305+	hints.max_width = (i32)w;
 7306+	hints.max_height = (i32)h;
 7307+
 7308+	XSetWMNormalHints(_RGFW->display, win->src.window, &hints);
 7309+	return;
 7310+}
 7311+
 7312+void RGFW_toggleXMaximized(RGFW_window* win, RGFW_bool maximized);
 7313+void RGFW_toggleXMaximized(RGFW_window* win, RGFW_bool maximized) {
 7314+	RGFW_ASSERT(win != NULL);
 7315+	RGFW_LOAD_ATOM(_NET_WM_STATE);
 7316+	RGFW_LOAD_ATOM(_NET_WM_STATE_MAXIMIZED_VERT);
 7317+	RGFW_LOAD_ATOM(_NET_WM_STATE_MAXIMIZED_HORZ);
 7318+
 7319+	XEvent xev = {0};
 7320+	xev.type = ClientMessage;
 7321+	xev.xclient.window = win->src.window;
 7322+	xev.xclient.message_type = _NET_WM_STATE;
 7323+	xev.xclient.format = 32;
 7324+	xev.xclient.data.l[0] = maximized;
 7325+	xev.xclient.data.l[1] = (long int)_NET_WM_STATE_MAXIMIZED_HORZ;
 7326+	xev.xclient.data.l[2] = (long int)_NET_WM_STATE_MAXIMIZED_VERT;
 7327+	xev.xclient.data.l[3] = 0;
 7328+	xev.xclient.data.l[4] = 0;
 7329+
 7330+	XSendEvent(_RGFW->display, DefaultRootWindow(_RGFW->display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
 7331+}
 7332+
 7333+void RGFW_FUNC(RGFW_window_maximize) (RGFW_window* win) {
 7334+	win->internal.oldX = win->x;
 7335+	win->internal.oldY = win->y;
 7336+	win->internal.oldW = win->w;
 7337+	win->internal.oldH = win->h;
 7338+
 7339+    RGFW_toggleXMaximized(win, 1);
 7340+	RGFW_window_fetchSize(win, NULL, NULL);
 7341+    return;
 7342+}
 7343+
 7344+void RGFW_FUNC(RGFW_window_focus) (RGFW_window* win) {
 7345+	RGFW_ASSERT(win);
 7346+
 7347+	XWindowAttributes attr;
 7348+	XGetWindowAttributes(_RGFW->display, win->src.window, &attr);
 7349+	if (attr.map_state != IsViewable) return;
 7350+
 7351+	XSetInputFocus(_RGFW->display, win->src.window, RevertToPointerRoot, CurrentTime);
 7352+	XFlush(_RGFW->display);
 7353+}
 7354+
 7355+void RGFW_FUNC(RGFW_window_raise) (RGFW_window* win) {
 7356+	RGFW_ASSERT(win);
 7357+	XMapRaised(_RGFW->display, win->src.window);
 7358+	RGFW_window_setFullscreen(win, RGFW_window_isFullscreen(win));
 7359+}
 7360+
 7361+void RGFW_window_setXAtom(RGFW_window* win, Atom netAtom, RGFW_bool fullscreen);
 7362+void RGFW_window_setXAtom(RGFW_window* win, Atom netAtom, RGFW_bool fullscreen) {
 7363+	RGFW_ASSERT(win != NULL);
 7364+	RGFW_LOAD_ATOM(_NET_WM_STATE);
 7365+
 7366+	XEvent xev = {0};
 7367+	xev.xclient.type = ClientMessage;
 7368+	xev.xclient.serial = 0;
 7369+	xev.xclient.send_event = True;
 7370+	xev.xclient.message_type = _NET_WM_STATE;
 7371+	xev.xclient.window = win->src.window;
 7372+	xev.xclient.format = 32;
 7373+	xev.xclient.data.l[0] = fullscreen;
 7374+	xev.xclient.data.l[1] = (long int)netAtom;
 7375+	xev.xclient.data.l[2] = 0;
 7376+
 7377+	XSendEvent(_RGFW->display, DefaultRootWindow(_RGFW->display), False, SubstructureNotifyMask | SubstructureRedirectMask, &xev);
 7378+}
 7379+
 7380+void RGFW_FUNC(RGFW_window_setFullscreen)(RGFW_window* win, RGFW_bool fullscreen) {
 7381+	RGFW_ASSERT(win != NULL);
 7382+
 7383+	if (fullscreen) {
 7384+		win->internal.flags |= RGFW_windowFullscreen;
 7385+		win->internal.oldX = win->x;
 7386+		win->internal.oldY = win->y;
 7387+		win->internal.oldW = win->w;
 7388+		win->internal.oldH = win->h;
 7389+	}
 7390+	else win->internal.flags &= ~(u32)RGFW_windowFullscreen;
 7391+
 7392+	XRaiseWindow(_RGFW->display, win->src.window);
 7393+
 7394+	RGFW_LOAD_ATOM(_NET_WM_STATE_FULLSCREEN);
 7395+	RGFW_window_setXAtom(win, _NET_WM_STATE_FULLSCREEN, fullscreen);
 7396+
 7397+	if (!(win->internal.flags & RGFW_windowTransparent)) {
 7398+		const unsigned char value = fullscreen;
 7399+		RGFW_LOAD_ATOM(_NET_WM_BYPASS_COMPOSITOR);
 7400+		XChangeProperty(
 7401+			_RGFW->display, win->src.window,
 7402+			_NET_WM_BYPASS_COMPOSITOR, XA_CARDINAL, 32,
 7403+			PropModeReplace, &value, 1);
 7404+	}
 7405+}
 7406+
 7407+void RGFW_FUNC(RGFW_window_setFloating)(RGFW_window* win, RGFW_bool floating) {
 7408+    RGFW_ASSERT(win != NULL);
 7409+	RGFW_LOAD_ATOM(_NET_WM_STATE_ABOVE);
 7410+	RGFW_window_setXAtom(win, _NET_WM_STATE_ABOVE, floating);
 7411+}
 7412+
 7413+void RGFW_FUNC(RGFW_window_setOpacity)(RGFW_window* win, u8 opacity) {
 7414+	RGFW_ASSERT(win != NULL);
 7415+    const u32 value = (u32) (0xffffffffu * (double) opacity);
 7416+	RGFW_LOAD_ATOM(NET_WM_WINDOW_OPACITY);
 7417+    XChangeProperty(_RGFW->display, win->src.window,
 7418+					NET_WM_WINDOW_OPACITY, XA_CARDINAL, 32, PropModeReplace, (unsigned char*) &value, 1);
 7419+}
 7420+
 7421+void RGFW_FUNC(RGFW_window_minimize)(RGFW_window* win) {
 7422+	RGFW_ASSERT(win != NULL);
 7423+
 7424+	if (RGFW_window_isMaximized(win)) return;
 7425+
 7426+	win->internal.oldX = win->x;
 7427+	win->internal.oldY = win->y;
 7428+	win->internal.oldW = win->w;
 7429+	win->internal.oldH = win->h;
 7430+    XIconifyWindow(_RGFW->display, win->src.window, DefaultScreen(_RGFW->display));
 7431+	XFlush(_RGFW->display);
 7432+}
 7433+
 7434+void RGFW_FUNC(RGFW_window_restore)(RGFW_window* win) {
 7435+	RGFW_ASSERT(win != NULL);
 7436+	RGFW_toggleXMaximized(win, RGFW_FALSE);
 7437+	RGFW_window_move(win, win->internal.oldX, win->internal.oldY);
 7438+	RGFW_window_resize(win, win->internal.oldW, win->internal.oldH);
 7439+
 7440+    RGFW_window_show(win);
 7441+    XFlush(_RGFW->display);
 7442+}
 7443+
 7444+RGFW_bool RGFW_FUNC(RGFW_window_isFloating)(RGFW_window* win) {
 7445+    RGFW_LOAD_ATOM(_NET_WM_STATE);
 7446+	RGFW_LOAD_ATOM(_NET_WM_STATE_ABOVE);
 7447+
 7448+	Atom actual_type;
 7449+	int actual_format;
 7450+	unsigned long nitems, bytes_after;
 7451+	Atom* prop_return = NULL;
 7452+
 7453+	int status = XGetWindowProperty(_RGFW->display, win->src.window, _NET_WM_STATE, 0, (~0L), False, XA_ATOM,
 7454+									&actual_type, &actual_format, &nitems, &bytes_after,
 7455+									(unsigned char **)&prop_return);
 7456+
 7457+	if (status != Success || actual_type != XA_ATOM)
 7458+		return RGFW_FALSE;
 7459+
 7460+    unsigned long i;
 7461+	for (i = 0; i < nitems; i++)
 7462+		if (prop_return[i] == _NET_WM_STATE_ABOVE) return RGFW_TRUE;
 7463+
 7464+	if (prop_return)
 7465+		XFree(prop_return);
 7466+	return RGFW_FALSE;
 7467+}
 7468+
 7469+void RGFW_FUNC(RGFW_window_setName)(RGFW_window* win, const char* name) {
 7470+	RGFW_ASSERT(win != NULL);
 7471+	if (name == NULL) name = "\0";
 7472+
 7473+	Xutf8SetWMProperties(_RGFW->display, win->src.window, name, name, NULL, 0, NULL, NULL, NULL);
 7474+	XStoreName(_RGFW->display, win->src.window, name);
 7475+
 7476+	RGFW_LOAD_ATOM(_NET_WM_NAME); RGFW_LOAD_ATOM(UTF8_STRING);
 7477+
 7478+    XChangeProperty(
 7479+		_RGFW->display, win->src.window, _NET_WM_NAME, UTF8_STRING,
 7480+		8, PropModeReplace, (u8*)name, (int)RGFW_unix_stringlen(name)
 7481+	);
 7482+}
 7483+
 7484+#ifndef RGFW_NO_PASSTHROUGH
 7485+void RGFW_FUNC(RGFW_window_setMousePassthrough) (RGFW_window* win, RGFW_bool passthrough) {
 7486+	RGFW_ASSERT(win != NULL);
 7487+    if (passthrough) {
 7488+		Region region = XCreateRegion();
 7489+		XShapeCombineRegion(_RGFW->display, win->src.window, ShapeInput, 0, 0, region, ShapeSet);
 7490+		XDestroyRegion(region);
 7491+
 7492+		return;
 7493+	}
 7494+
 7495+	XShapeCombineMask(_RGFW->display, win->src.window, ShapeInput, 0, 0, None, ShapeSet);
 7496+}
 7497+#endif /* RGFW_NO_PASSTHROUGH */
 7498+
 7499+RGFW_bool RGFW_FUNC(RGFW_window_setIconEx) (RGFW_window* win, u8* data_src, i32 w, i32 h, RGFW_format format, RGFW_icon type) {
 7500+	Atom _NET_WM_ICON = XInternAtom(_RGFW->display, "_NET_WM_ICON", False);
 7501+	RGFW_ASSERT(win != NULL);
 7502+	if (data_src == NULL) {
 7503+		RGFW_bool res = (RGFW_bool)XChangeProperty(
 7504+			_RGFW->display, win->src.window, _NET_WM_ICON, XA_CARDINAL, 32,
 7505+			PropModeReplace, (u8*)NULL, 0
 7506+		);
 7507+		return res;
 7508+	}
 7509+
 7510+	i32 count = (i32)(2 + (w * h));
 7511+
 7512+	unsigned long* data = (unsigned long*) RGFW_ALLOC((u32)count * sizeof(unsigned long));
 7513+    RGFW_ASSERT(data != NULL);
 7514+
 7515+	RGFW_MEMZERO(data, (u32)count * sizeof(unsigned long));
 7516+    data[0] = (unsigned long)w;
 7517+	data[1] = (unsigned long)h;
 7518+
 7519+	RGFW_copyImageData64((u8*)&data[2], w, h, RGFW_formatBGRA8, data_src, format, RGFW_TRUE, NULL);
 7520+	RGFW_bool res = RGFW_TRUE;
 7521+	if (type & RGFW_iconTaskbar) {
 7522+		res = (RGFW_bool)XChangeProperty(
 7523+			_RGFW->display, win->src.window, _NET_WM_ICON, XA_CARDINAL, 32,
 7524+			PropModeReplace, (u8*)data, count
 7525+		);
 7526+	}
 7527+
 7528+	RGFW_copyImageData64((u8*)&data[2], w, h, RGFW_formatBGRA8, data_src, format, RGFW_FALSE, NULL);
 7529+
 7530+	if (type & RGFW_iconWindow) {
 7531+		XWMHints wm_hints;
 7532+		wm_hints.flags = IconPixmapHint;
 7533+
 7534+		i32 depth = DefaultDepth(_RGFW->display, DefaultScreen(_RGFW->display));
 7535+		XImage *image = XCreateImage(_RGFW->display, DefaultVisual(_RGFW->display, DefaultScreen(_RGFW->display)),
 7536+									(u32)depth, ZPixmap, 0, (char *)&data[2], (u32)w, (u32)h, 32, 0);
 7537+
 7538+		wm_hints.icon_pixmap = XCreatePixmap(_RGFW->display, win->src.window, (u32)w, (u32)h, (u32)depth);
 7539+		XPutImage(_RGFW->display, wm_hints.icon_pixmap, DefaultGC(_RGFW->display, DefaultScreen(_RGFW->display)), image, 0, 0, 0, 0, (u32)w, (u32)h);
 7540+		image->data = NULL;
 7541+		XDestroyImage(image);
 7542+
 7543+		XSetWMHints(_RGFW->display, win->src.window, &wm_hints);
 7544+	}
 7545+
 7546+	RGFW_FREE(data);
 7547+	XFlush(_RGFW->display);
 7548+	return RGFW_BOOL(res);
 7549+}
 7550+
 7551+RGFW_mouse* RGFW_FUNC(RGFW_createMouseStandard) (RGFW_mouseIcon mouse) {
 7552+	u32 mouseIcon = 0;
 7553+
 7554+    switch (mouse) {
 7555+        case RGFW_mouseNormal: mouseIcon = XC_left_ptr; break;
 7556+        case RGFW_mouseArrow: mouseIcon = XC_left_ptr; break;
 7557+        case RGFW_mouseIbeam: mouseIcon = XC_xterm; break;
 7558+        case RGFW_mouseWait: mouseIcon = XC_watch; break;
 7559+        case RGFW_mouseCrosshair: mouseIcon = XC_tcross; break;
 7560+        case RGFW_mouseProgress: mouseIcon = XC_watch; break;
 7561+        case RGFW_mouseResizeNWSE: mouseIcon = XC_top_left_corner; break;
 7562+        case RGFW_mouseResizeNESW: mouseIcon = XC_top_right_corner; break;
 7563+        case RGFW_mouseResizeEW: mouseIcon = XC_sb_h_double_arrow; break;
 7564+        case RGFW_mouseResizeNS: mouseIcon = XC_sb_v_double_arrow; break;
 7565+        case RGFW_mouseResizeNW: mouseIcon = XC_top_left_corner; break;
 7566+        case RGFW_mouseResizeN: mouseIcon = XC_top_side; break;
 7567+        case RGFW_mouseResizeNE: mouseIcon = XC_top_right_corner; break;
 7568+        case RGFW_mouseResizeE: mouseIcon = XC_right_side; break;
 7569+        case RGFW_mouseResizeSE: mouseIcon = XC_bottom_right_corner; break;
 7570+        case RGFW_mouseResizeS: mouseIcon = XC_bottom_side; break;
 7571+        case RGFW_mouseResizeSW: mouseIcon = XC_bottom_left_corner; break;
 7572+        case RGFW_mouseResizeW: mouseIcon = XC_left_side; break;
 7573+		case RGFW_mouseResizeAll: mouseIcon = XC_fleur; break;
 7574+        case RGFW_mouseNotAllowed: mouseIcon = XC_pirate; break;
 7575+        case RGFW_mousePointingHand: mouseIcon = XC_hand2; break;
 7576+		default: return NULL;
 7577+	}
 7578+
 7579+	Cursor cursor = XCreateFontCursor(_RGFW->display, mouseIcon);
 7580+	return (RGFW_mouse*)cursor;
 7581+}
 7582+
 7583+RGFW_mouse* RGFW_FUNC(RGFW_createMouse) (u8* data, i32 w, i32 h, RGFW_format format) {
 7584+    RGFW_ASSERT(data);
 7585+#ifndef RGFW_NO_X11_CURSOR
 7586+	RGFW_init();
 7587+    XcursorImage* native = XcursorImageCreate((i32)w, (i32)h);
 7588+	native->xhot = 0;
 7589+	native->yhot = 0;
 7590+	RGFW_MEMZERO(native->pixels, (u32)(w * h * 4));
 7591+	RGFW_copyImageData((u8*)native->pixels, w, h, RGFW_formatBGRA8, data, format, NULL);
 7592+
 7593+	Cursor cursor = XcursorImageLoadCursor(_RGFW->display, native);
 7594+	XcursorImageDestroy(native);
 7595+
 7596+	return (void*)cursor;
 7597+#else
 7598+	RGFW_UNUSED(data); RGFW_UNUSED(w); RGFW_UNUSED(h); RGFW_UNUSED(format);
 7599+	return NULL;
 7600+#endif
 7601+}
 7602+
 7603+RGFW_bool RGFW_FUNC(RGFW_window_setMousePlatform)(RGFW_window* win, RGFW_mouse* mouse) {
 7604+	RGFW_ASSERT(win && mouse);
 7605+	XDefineCursor(_RGFW->display, win->src.window, (Cursor)mouse);
 7606+	return RGFW_TRUE;
 7607+}
 7608+
 7609+void RGFW_FUNC(RGFW_freeMouse)(RGFW_mouse* mouse) {
 7610+	RGFW_ASSERT(mouse);
 7611+	XFreeCursor(_RGFW->display, (Cursor)mouse);
 7612+}
 7613+
 7614+void RGFW_FUNC(RGFW_window_moveMouse)(RGFW_window* win, i32 x, i32 y) {
 7615+	RGFW_ASSERT(win != NULL);
 7616+
 7617+	XEvent event;
 7618+	XQueryPointer(_RGFW->display, DefaultRootWindow(_RGFW->display),
 7619+		&event.xbutton.root, &event.xbutton.window,
 7620+		&event.xbutton.x_root, &event.xbutton.y_root,
 7621+		&event.xbutton.x, &event.xbutton.y,
 7622+		&event.xbutton.state);
 7623+
 7624+	win->internal.lastMouseX = x - win->x;
 7625+	win->internal.lastMouseY = y - win->y;
 7626+	if (event.xbutton.x == x && event.xbutton.y == y)
 7627+		return;
 7628+
 7629+	XWarpPointer(_RGFW->display, None, win->src.window, 0, 0, 0, 0, (int) x - win->x, (int) y - win->y);
 7630+}
 7631+
 7632+void RGFW_FUNC(RGFW_window_hide)(RGFW_window* win) {
 7633+	win->internal.flags |= (u32)RGFW_windowHide;
 7634+	XUnmapWindow(_RGFW->display, win->src.window);
 7635+
 7636+	XFlush(_RGFW->display);
 7637+}
 7638+
 7639+void RGFW_FUNC(RGFW_window_show) (RGFW_window* win) {
 7640+	win->internal.flags &= ~(u32)RGFW_windowHide;
 7641+	if (win->internal.flags & RGFW_windowFocusOnShow) RGFW_window_focus(win);
 7642+
 7643+	if (RGFW_window_isHidden(win) == RGFW_FALSE) {
 7644+		return;
 7645+	}
 7646+
 7647+	XMapWindow(_RGFW->display, win->src.window);
 7648+	RGFW_window_move(win, win->x, win->y);
 7649+
 7650+	RGFW_waitForShowEvent_X11(win);
 7651+	RGFW_window_setFullscreen(win, RGFW_window_isFullscreen(win));
 7652+	return;
 7653+}
 7654+
 7655+void RGFW_FUNC(RGFW_window_flash) (RGFW_window* win, RGFW_flashRequest request) {
 7656+	if (RGFW_window_isInFocus(win) && request) {
 7657+		return;
 7658+	}
 7659+
 7660+	XWMHints* wmhints = XGetWMHints(_RGFW->display, win->src.window);
 7661+	if (wmhints == NULL) return;
 7662+
 7663+	if (request) {
 7664+		wmhints->flags |= XUrgencyHint;
 7665+		if (request == RGFW_flashBriefly)
 7666+			win->src.flashEnd = RGFW_linux_getTimeNS() + (u64)1e+9;
 7667+		if (request == RGFW_flashUntilFocused)
 7668+			win->src.flashEnd = (u64)-1;
 7669+	} else {
 7670+		win->src.flashEnd = 0;
 7671+		wmhints->flags &= ~XUrgencyHint;
 7672+	}
 7673+
 7674+    XSetWMHints(_RGFW->display, win->src.window, wmhints);
 7675+    XFree(wmhints);
 7676+}
 7677+
 7678+RGFW_ssize_t RGFW_FUNC(RGFW_readClipboardPtr)(char* str, size_t strCapacity) {
 7679+	RGFW_init();
 7680+	RGFW_LOAD_ATOM(XSEL_DATA); RGFW_LOAD_ATOM(UTF8_STRING); RGFW_LOAD_ATOM(CLIPBOARD);
 7681+	if (XGetSelectionOwner(_RGFW->display, CLIPBOARD) == _RGFW->helperWindow) {
 7682+		if (str != NULL)
 7683+			RGFW_STRNCPY(str, _RGFW->clipboard, _RGFW->clipboard_len - 1);
 7684+		_RGFW->clipboard[_RGFW->clipboard_len - 1] = '\0';
 7685+		return (RGFW_ssize_t)_RGFW->clipboard_len - 1;
 7686+	}
 7687+
 7688+	XEvent event;
 7689+	int format;
 7690+	unsigned long N, sizeN;
 7691+	char* data;
 7692+	Atom target;
 7693+
 7694+	XConvertSelection(_RGFW->display, CLIPBOARD, UTF8_STRING, XSEL_DATA, _RGFW->helperWindow, CurrentTime);
 7695+	XSync(_RGFW->display, 0);
 7696+	while (1) {
 7697+		XNextEvent(_RGFW->display, &event);
 7698+		if (event.type != SelectionNotify) continue;
 7699+
 7700+		if (event.xselection.selection != CLIPBOARD || event.xselection.property == 0)
 7701+			return -1;
 7702+		break;
 7703+	}
 7704+
 7705+	XGetWindowProperty(event.xselection.display, event.xselection.requestor,
 7706+			event.xselection.property, 0L, (~0L), 0, AnyPropertyType, &target,
 7707+			&format, &sizeN, &N, (u8**) &data);
 7708+
 7709+	RGFW_ssize_t size;
 7710+	if (sizeN > strCapacity && str != NULL)
 7711+		size = -1;
 7712+
 7713+	if ((target == UTF8_STRING || target == XA_STRING) && str != NULL) {
 7714+		RGFW_MEMCPY(str, data, sizeN);
 7715+		str[sizeN] = '\0';
 7716+		XFree(data);
 7717+	} else if (str != NULL) size = -1;
 7718+
 7719+	XDeleteProperty(event.xselection.display, event.xselection.requestor, event.xselection.property);
 7720+	size = (RGFW_ssize_t)sizeN;
 7721+
 7722+    return size;
 7723+}
 7724+
 7725+i32 RGFW_XHandleClipboardSelectionHelper(void) {
 7726+    RGFW_LOAD_ATOM(SAVE_TARGETS);
 7727+
 7728+    XEvent event;
 7729+    XPending(_RGFW->display);
 7730+
 7731+    if (QLength(_RGFW->display) || XEventsQueued(_RGFW->display, QueuedAlready) + XEventsQueued(_RGFW->display, QueuedAfterReading))
 7732+        XNextEvent(_RGFW->display, &event);
 7733+    else
 7734+        return 0;
 7735+
 7736+    switch (event.type) {
 7737+        case SelectionRequest:
 7738+            RGFW_XHandleClipboardSelection(&event);
 7739+            return 0;
 7740+        case SelectionNotify:
 7741+            if (event.xselection.target == SAVE_TARGETS)
 7742+                return 0;
 7743+            break;
 7744+        default: break;
 7745+    }
 7746+
 7747+    return 0;
 7748+}
 7749+
 7750+void RGFW_FUNC(RGFW_writeClipboard)(const char* text, u32 textLen) {
 7751+	RGFW_LOAD_ATOM(SAVE_TARGETS); RGFW_LOAD_ATOM(CLIPBOARD);
 7752+    RGFW_init();
 7753+
 7754+    /* request ownership of the clipboard section and request to convert it, this means its our job to convert it */
 7755+	XSetSelectionOwner(_RGFW->display, CLIPBOARD, _RGFW->helperWindow, CurrentTime);
 7756+	if (XGetSelectionOwner(_RGFW->display, CLIPBOARD) != _RGFW->helperWindow) {
 7757+    	RGFW_debugCallback(RGFW_typeError, RGFW_errClipboard,  "X11 failed to become owner of clipboard selection");
 7758+		return;
 7759+	}
 7760+
 7761+	if (_RGFW->clipboard)
 7762+		RGFW_FREE(_RGFW->clipboard);
 7763+
 7764+	_RGFW->clipboard = (char*)RGFW_ALLOC(textLen);
 7765+	RGFW_ASSERT(_RGFW->clipboard != NULL);
 7766+
 7767+	RGFW_STRNCPY(_RGFW->clipboard, text, textLen - 1);
 7768+	_RGFW->clipboard[textLen - 1] = '\0';
 7769+	_RGFW->clipboard_len = textLen;
 7770+	return;
 7771+}
 7772+
 7773+RGFW_bool RGFW_FUNC(RGFW_window_isHidden)(RGFW_window* win) {
 7774+	RGFW_ASSERT(win != NULL);
 7775+	XWindowAttributes windowAttributes;
 7776+	XGetWindowAttributes(_RGFW->display, win->src.window, &windowAttributes);
 7777+
 7778+	return (windowAttributes.map_state != IsViewable);
 7779+}
 7780+
 7781+RGFW_bool RGFW_FUNC(RGFW_window_isMinimized)(RGFW_window* win) {
 7782+	RGFW_ASSERT(win != NULL);
 7783+    RGFW_LOAD_ATOM(WM_STATE);
 7784+
 7785+	Atom actual_type;
 7786+	i32 actual_format;
 7787+	unsigned long nitems, bytes_after;
 7788+	unsigned char* prop_data;
 7789+
 7790+	i32 status = XGetWindowProperty(_RGFW->display, win->src.window, WM_STATE, 0, 2, False,
 7791+		AnyPropertyType, &actual_type, &actual_format,
 7792+		&nitems, &bytes_after, &prop_data);
 7793+
 7794+	if (status == Success && nitems >= 1 && prop_data == (unsigned char*)IconicState) {
 7795+		XFree(prop_data);
 7796+		return RGFW_TRUE;
 7797+	}
 7798+
 7799+	if (prop_data != NULL)
 7800+		XFree(prop_data);
 7801+
 7802+	XWindowAttributes windowAttributes;
 7803+	XGetWindowAttributes(_RGFW->display, win->src.window, &windowAttributes);
 7804+    return windowAttributes.map_state != IsViewable;
 7805+}
 7806+
 7807+RGFW_bool RGFW_FUNC(RGFW_window_isMaximized)(RGFW_window* win) {
 7808+	RGFW_ASSERT(win != NULL);
 7809+    RGFW_LOAD_ATOM(_NET_WM_STATE);
 7810+	RGFW_LOAD_ATOM(_NET_WM_STATE_MAXIMIZED_VERT);
 7811+	RGFW_LOAD_ATOM(_NET_WM_STATE_MAXIMIZED_HORZ);
 7812+
 7813+	Atom actual_type;
 7814+	i32 actual_format;
 7815+	unsigned long nitems, bytes_after;
 7816+	unsigned char* prop_data;
 7817+
 7818+	i32 status = XGetWindowProperty(_RGFW->display, win->src.window, _NET_WM_STATE, 0, 1024, False,
 7819+		XA_ATOM, &actual_type, &actual_format,
 7820+		&nitems, &bytes_after, &prop_data);
 7821+
 7822+	if (status != Success) {
 7823+		if (prop_data != NULL)
 7824+			XFree(prop_data);
 7825+
 7826+		return RGFW_FALSE;
 7827+	}
 7828+
 7829+	u64 i;
 7830+	for (i = 0; i < nitems; i++) {
 7831+		if (prop_data[i] == _NET_WM_STATE_MAXIMIZED_VERT ||
 7832+			prop_data[i] == _NET_WM_STATE_MAXIMIZED_HORZ) {
 7833+			XFree(prop_data);
 7834+			return RGFW_TRUE;
 7835+		}
 7836+	}
 7837+
 7838+	if (prop_data != NULL)
 7839+		XFree(prop_data);
 7840+
 7841+	return RGFW_FALSE;
 7842+}
 7843+
 7844+RGFWDEF void RGFW_XGetSystemContentDPI(float* dpi);
 7845+void RGFW_XGetSystemContentDPI(float* dpi) {
 7846+	if (dpi == NULL) return;
 7847+	float dpiOutput = 96.0f;
 7848+
 7849+	char* rms = XResourceManagerString(_RGFW->display);
 7850+	if (rms == NULL) return;
 7851+
 7852+	XrmDatabase db = XrmGetStringDatabase(rms);
 7853+	if (db == NULL) return;
 7854+
 7855+	XrmValue value;
 7856+	char* type = NULL;
 7857+
 7858+	if (XrmGetResource(db, "Xft.dpi", "Xft.Dpi", &type, &value) && type && RGFW_STRNCMP(type, "String", 7) == 0)
 7859+		dpiOutput = (float)RGFW_ATOF(value.addr);
 7860+	XrmDestroyDatabase(db);
 7861+
 7862+	if (dpi) *dpi = dpiOutput;
 7863+}
 7864+
 7865+RGFWDEF XRRModeInfo* RGFW_XGetMode(XRRCrtcInfo* ci, XRRScreenResources* res, RRMode mode, RGFW_monitorMode* foundMode);
 7866+XRRModeInfo* RGFW_XGetMode(XRRCrtcInfo* ci, XRRScreenResources* res, RRMode mode, RGFW_monitorMode* foundMode) {
 7867+	XRRModeInfo* mi = None;
 7868+	for (i32 j = 0; j < res->nmode; j++) {
 7869+		if (res->modes[j].id ==  mode)
 7870+			mi = &res->modes[j];
 7871+	}
 7872+
 7873+	if (mi == None) return NULL;
 7874+
 7875+	if ((mi->modeFlags & RR_Interlace) != 0) return NULL;
 7876+
 7877+	foundMode->w = (i32)mi->width;
 7878+	foundMode->h = (i32)mi->height;
 7879+	if (ci->rotation == RR_Rotate_90 || ci->rotation == RR_Rotate_270) {
 7880+		foundMode->w = (i32)mi->height;
 7881+		foundMode->h = (i32)mi->width;
 7882+	} else {
 7883+		foundMode->w = (i32)mi->width;
 7884+		foundMode->h = (i32)mi->height;
 7885+	}
 7886+
 7887+	RGFW_splitBPP((u32)DefaultDepth(_RGFW->display, DefaultScreen(_RGFW->display)), foundMode);
 7888+
 7889+	foundMode->src = (void*)mode;
 7890+
 7891+	foundMode->refreshRate = 0;
 7892+	if (mi->hTotal == 0 || mi->vTotal == 0)
 7893+		return mi;
 7894+
 7895+    u32 vTotal = mi->vTotal;
 7896+
 7897+    if (mi->modeFlags & RR_DoubleScan) {
 7898+        vTotal *= 2;
 7899+    }
 7900+
 7901+    if (mi->modeFlags & RR_Interlace) {
 7902+        vTotal /= 2;
 7903+    }
 7904+
 7905+	i32 numerator = (i32)mi->dotClock;
 7906+	i32 denominator = (i32)(mi->hTotal * vTotal);
 7907+	float refreshRate = 0;
 7908+
 7909+	if (denominator <= 0) {
 7910+		denominator = 1;
 7911+	}
 7912+
 7913+	refreshRate = ((float)numerator / (float)denominator);
 7914+
 7915+	foundMode->refreshRate = RGFW_ROUNDF((refreshRate * 100)) / 100.0f;
 7916+	return mi;
 7917+}
 7918+
 7919+void RGFW_FUNC(RGFW_pollMonitors) (void) {
 7920+    RGFW_init();
 7921+
 7922+	Window root = XDefaultRootWindow(_RGFW->display);
 7923+	XRRScreenResources* res = XRRGetScreenResourcesCurrent(_RGFW->display, root);
 7924+	if (res == 0) {
 7925+		return;
 7926+	}
 7927+
 7928+	RROutput primary = XRRGetOutputPrimary(_RGFW->display, root);
 7929+
 7930+	for (RGFW_monitorNode* node = _RGFW->monitors.list.head; node; node = node->next) {
 7931+		node->disconnected = RGFW_TRUE;
 7932+	}
 7933+
 7934+	for (i32 i = 0; i < res->noutput; i++) {
 7935+		RGFW_monitorNode* node = NULL;
 7936+		for (node = _RGFW->monitors.list.head; node; node = node->next) {
 7937+			if (node->rrOutput == res->outputs[i]) {
 7938+				break;
 7939+			}
 7940+		}
 7941+
 7942+		if (node) {
 7943+			node->disconnected = RGFW_FALSE;
 7944+			if (node->rrOutput == primary) {
 7945+				_RGFW->monitors.primary = node;
 7946+			}
 7947+			continue;
 7948+		}
 7949+
 7950+		RGFW_monitor monitor;
 7951+
 7952+		XRROutputInfo* info = XRRGetOutputInfo(_RGFW->display, res, res->outputs[i]);
 7953+		if (info == NULL) continue;
 7954+		if (info->connection != RR_Connected || info->crtc == None) {
 7955+			XRRFreeOutputInfo(info);
 7956+			continue;
 7957+		}
 7958+
 7959+		XRRCrtcInfo* ci = XRRGetCrtcInfo(_RGFW->display, res, info->crtc);
 7960+
 7961+		if (ci == NULL) {
 7962+			continue;
 7963+		}
 7964+
 7965+		float physW = (float)info->mm_width / 25.4f;
 7966+		float physH = (float)info->mm_height / 25.4f;
 7967+
 7968+		RGFW_STRNCPY(monitor.name, info->name, sizeof(monitor.name) - 1);
 7969+		monitor.name[sizeof(monitor.name) - 1] = '\0';
 7970+
 7971+		if (physW > 0.0f && physH > 0.0f) {
 7972+			monitor.physW = physW;
 7973+			monitor.physH = physH;
 7974+		} else {
 7975+			monitor.physW = (float) ((float)ci->width / 96.f);
 7976+			monitor.physH = (float) ((float)ci->height / 96.f);
 7977+		}
 7978+
 7979+		monitor.x = ci->x;
 7980+		monitor.y = ci->y;
 7981+
 7982+		float dpi = 96.0f;
 7983+		RGFW_XGetSystemContentDPI(&dpi);
 7984+
 7985+		monitor.scaleX = dpi / 96.0f;
 7986+		monitor.scaleY = dpi / 96.0f;
 7987+
 7988+		monitor.pixelRatio = dpi >= 192.0f ? 2.0f : 1.0f;
 7989+
 7990+		XRRModeInfo* mi = RGFW_XGetMode(ci, res, ci->mode, &monitor.mode);
 7991+
 7992+		if (mi == NULL) {
 7993+			break;
 7994+		}
 7995+
 7996+		XRRFreeCrtcInfo(ci);
 7997+
 7998+		node = RGFW_monitors_add(&monitor);
 7999+		if (node == NULL) break;
 8000+
 8001+		node->rrOutput = res->outputs[i];
 8002+		node->crtc = info->crtc;
 8003+
 8004+		if (node->rrOutput == primary) {
 8005+			_RGFW->monitors.primary = node;
 8006+		}
 8007+
 8008+		XRRFreeOutputInfo(info);
 8009+		info = NULL;
 8010+
 8011+		RGFW_monitorCallback(_RGFW->root, &node->mon, RGFW_TRUE);
 8012+	}
 8013+
 8014+	XRRFreeScreenResources(res);
 8015+
 8016+	RGFW_monitors_refresh();
 8017+}
 8018+
 8019+RGFW_bool RGFW_FUNC(RGFW_monitor_getWorkarea) (RGFW_monitor* monitor, i32* x, i32* y, i32* width, i32* height) {
 8020+    RGFW_LOAD_ATOM(_NET_WORKAREA);
 8021+    RGFW_LOAD_ATOM(_NET_CURRENT_DESKTOP);
 8022+
 8023+	Window root = DefaultRootWindow(_RGFW->display);
 8024+
 8025+	i32 areaX = monitor->x;
 8026+	i32 areaY = monitor->y;
 8027+	i32 areaW = monitor->mode.w;
 8028+	i32 areaH  = monitor->mode.h;
 8029+
 8030+    if (_NET_WORKAREA && _NET_CURRENT_DESKTOP) {
 8031+        Atom* extents = NULL;
 8032+        Atom* desktop = NULL;
 8033+
 8034+		Atom actualType = 0;
 8035+		int actualFormat = 0;
 8036+		unsigned long extentCount = 0, bytesAfter = 0;
 8037+		XGetWindowProperty(_RGFW->display, root, _NET_WORKAREA, 0, LONG_MAX, False, XA_CARDINAL, &actualType, &actualFormat, &extentCount, &bytesAfter, (u8**) &extents);
 8038+
 8039+		unsigned long count;
 8040+		XGetWindowProperty(_RGFW->display, root, _NET_CURRENT_DESKTOP, 0, LONG_MAX, False, XA_CARDINAL, &actualType, &actualFormat, &count, &bytesAfter, (u8**) &desktop);
 8041+
 8042+        if (count) {
 8043+			if (extentCount >= 4 && *desktop < extentCount / 4) {
 8044+                i32 globalX = (i32)extents[*desktop * 4 + 0];
 8045+                i32 globalY = (i32)extents[*desktop * 4 + 1];
 8046+                i32 globalW = (i32)extents[*desktop * 4 + 2];
 8047+                i32 globalH = (i32)extents[*desktop * 4 + 3];
 8048+
 8049+                if (areaX < globalX) {
 8050+                    areaW -= globalX - areaX;
 8051+                    areaX = globalX;
 8052+                }
 8053+
 8054+                if (areaY < globalY) {
 8055+                    areaH -= globalY - areaY;
 8056+                    areaY = globalY;
 8057+                }
 8058+
 8059+                if (areaX + areaW > globalX + globalW)
 8060+                    areaW = globalX - areaX + globalW;
 8061+                if (areaY + areaH > globalY + globalH)
 8062+                    areaH = globalY - areaY + globalH;
 8063+            }
 8064+        }
 8065+
 8066+        if (extents)
 8067+            XFree(extents);
 8068+        if (desktop)
 8069+            XFree(desktop);
 8070+    }
 8071+
 8072+    if (x) *x = areaX;
 8073+    if (y) *y = areaY;
 8074+    if (width) *width = areaW;
 8075+    if (height) *height = areaH;
 8076+
 8077+	return RGFW_TRUE;
 8078+}
 8079+
 8080+size_t RGFW_FUNC(RGFW_monitor_getModesPtr) (RGFW_monitor* monitor, RGFW_monitorMode** modes) {
 8081+	size_t count = 0;
 8082+
 8083+	XRRScreenResources* res = XRRGetScreenResourcesCurrent(_RGFW->display, DefaultRootWindow(_RGFW->display));
 8084+	if (res == NULL) return 0;
 8085+
 8086+	XRRCrtcInfo* ci = XRRGetCrtcInfo(_RGFW->display, res, monitor->node->crtc);
 8087+	XRROutputInfo* oi = XRRGetOutputInfo(_RGFW->display, res, monitor->node->rrOutput);
 8088+	count = (size_t)oi->nmode;
 8089+
 8090+	int i;
 8091+	for (i = 0; modes && i < oi->nmode; i++) {
 8092+		XRRModeInfo* mi = RGFW_XGetMode(ci, res, oi->modes[i], &((*modes)[i]));
 8093+		RGFW_UNUSED(mi);
 8094+	}
 8095+
 8096+    XRRFreeOutputInfo(oi);
 8097+	XRRFreeCrtcInfo(ci);
 8098+    XRRFreeScreenResources(res);
 8099+
 8100+	return count;
 8101+}
 8102+
 8103+size_t RGFW_FUNC(RGFW_monitor_getGammaRampPtr) (RGFW_monitor* monitor, RGFW_gammaRamp* ramp) {
 8104+	RGFW_UNUSED(monitor); RGFW_UNUSED(ramp);
 8105+	size_t size = (size_t)XRRGetCrtcGammaSize(_RGFW->display, monitor->node->crtc);
 8106+	XRRCrtcGamma* gamma = XRRGetCrtcGamma(_RGFW->display, monitor->node->crtc);
 8107+
 8108+	if (ramp) {
 8109+		RGFW_MEMCPY(ramp->red,   gamma->red,   size * sizeof(unsigned short));
 8110+		RGFW_MEMCPY(ramp->green, gamma->green, size * sizeof(unsigned short));
 8111+		RGFW_MEMCPY(ramp->blue,  gamma->blue,  size * sizeof(unsigned short));
 8112+	}
 8113+
 8114+	XRRFreeGamma(gamma);
 8115+	return size;
 8116+}
 8117+
 8118+RGFW_bool RGFW_FUNC(RGFW_monitor_setGammaRamp) (RGFW_monitor* monitor, RGFW_gammaRamp* ramp) {
 8119+	RGFW_UNUSED(monitor); RGFW_UNUSED(ramp);
 8120+
 8121+	size_t size = (size_t)XRRGetCrtcGammaSize(_RGFW->display, monitor->node->crtc);
 8122+	if (size != ramp->count) {
 8123+		RGFW_debugCallback(RGFW_typeError, RGFW_errX11, "X11: Gamma ramp size must match current ramp size");
 8124+		return RGFW_FALSE;
 8125+	}
 8126+
 8127+	XRRCrtcGamma* gamma = XRRAllocGamma((int)ramp->count);
 8128+
 8129+	memcpy(gamma->red,   ramp->red,   ramp->count * sizeof(unsigned short));
 8130+	memcpy(gamma->green, ramp->green, ramp->count * sizeof(unsigned short));
 8131+	memcpy(gamma->blue,  ramp->blue,  ramp->count * sizeof(unsigned short));
 8132+
 8133+	XRRSetCrtcGamma(_RGFW->display, monitor->node->crtc, gamma);
 8134+	XRRFreeGamma(gamma);
 8135+
 8136+	return RGFW_TRUE;
 8137+}
 8138+
 8139+RGFW_bool RGFW_FUNC(RGFW_monitor_setMode)(RGFW_monitor* mon, RGFW_monitorMode* mode) {
 8140+	RGFW_bool out = RGFW_FALSE;
 8141+
 8142+	XRRScreenResources* res = XRRGetScreenResourcesCurrent(_RGFW->display, DefaultRootWindow(_RGFW->display));
 8143+	XRRCrtcInfo* ci = XRRGetCrtcInfo(_RGFW->display, res, mon->node->crtc);
 8144+
 8145+	if (XRRSetCrtcConfig(_RGFW->display, res, mon->node->crtc, CurrentTime, ci->x, ci->y, (RRMode)mode->src, ci->rotation, ci->outputs, ci->noutput) == True) {
 8146+		out = RGFW_TRUE;
 8147+	}
 8148+
 8149+	XRRFreeCrtcInfo(ci);
 8150+    XRRFreeScreenResources(res);
 8151+	return out;
 8152+}
 8153+
 8154+RGFW_bool RGFW_FUNC(RGFW_monitor_requestMode)(RGFW_monitor* mon, RGFW_monitorMode* mode, RGFW_modeRequest request) {
 8155+    RGFW_init();
 8156+
 8157+	RGFW_bool output = RGFW_FALSE;
 8158+
 8159+	XRRScreenResources* res = XRRGetScreenResourcesCurrent(_RGFW->display, DefaultRootWindow(_RGFW->display));
 8160+	if (res == NULL) return RGFW_FALSE;
 8161+
 8162+	XRRCrtcInfo* ci = XRRGetCrtcInfo(_RGFW->display, res, mon->node->crtc);
 8163+	XRROutputInfo* oi = XRRGetOutputInfo(_RGFW->display, res, mon->node->rrOutput);
 8164+
 8165+	RRMode native = None;
 8166+
 8167+    int i;
 8168+    for (i = 0; i < oi->nmode; i++) {
 8169+		RGFW_monitorMode foundMode;
 8170+		XRRModeInfo* mi = RGFW_XGetMode(ci, res, oi->modes[i], &foundMode);
 8171+		if (mi == NULL) {
 8172+			continue;
 8173+		}
 8174+
 8175+		if (RGFW_monitorModeCompare(mode, &foundMode, request)) {
 8176+			native = mi->id;
 8177+			output = RGFW_TRUE;
 8178+			mon->mode = foundMode;
 8179+			break;
 8180+		}
 8181+	}
 8182+
 8183+	if (native) {
 8184+		XRRSetCrtcConfig(_RGFW->display, res, mon->node->crtc, CurrentTime, ci->x, ci->y, native, ci->rotation, ci->outputs, ci->noutput);
 8185+	}
 8186+
 8187+    XRRFreeOutputInfo(oi);
 8188+	XRRFreeCrtcInfo(ci);
 8189+    XRRFreeScreenResources(res);
 8190+	return output;
 8191+}
 8192+
 8193+RGFW_monitor* RGFW_FUNC(RGFW_window_getMonitor) (RGFW_window* win) {
 8194+    RGFW_ASSERT(win != NULL);
 8195+
 8196+	XWindowAttributes attrs;
 8197+    if (!XGetWindowAttributes(_RGFW->display, win->src.window, &attrs)) {
 8198+		return NULL;
 8199+	}
 8200+
 8201+	for (RGFW_monitorNode* node = _RGFW->monitors.list.head; node; node = node->next) {
 8202+		if ((attrs.x < node->mon.x + node->mon.mode.w) && (attrs.x + attrs.width > node->mon.x) && (attrs.y < node->mon.y + node->mon.mode.h) && (attrs.y + attrs.height > node->mon.y))
 8203+			return &node->mon;
 8204+	}
 8205+
 8206+
 8207+	return &_RGFW->monitors.list.head->mon;
 8208+}
 8209+
 8210+#ifdef RGFW_OPENGL
 8211+RGFW_bool RGFW_FUNC(RGFW_window_createContextPtr_OpenGL) (RGFW_window* win, RGFW_glContext* context, RGFW_glHints* hints) {
 8212+	/* for checking extensions later */
 8213+	const char sRGBARBstr[] = "GLX_ARB_framebuffer_sRGB";
 8214+	const char sRGBEXTstr[] = "GLX_EXT_framebuffer_sRGB";
 8215+	const char noErorrStr[]  = "GLX_ARB_create_context_no_error";
 8216+	const char flushStr[] = "GLX_ARB_context_flush_control";
 8217+	const char robustStr[]	= "GLX_ARB_create_context_robustness";
 8218+
 8219+	/* basic RGFW int */
 8220+	win->src.ctx.native = context;
 8221+	win->src.gfxType = RGFW_gfxNativeOpenGL;
 8222+
 8223+	/*  This is required so that way the user can create their own OpenGL context after RGFW_createWindow is used */
 8224+	RGFW_bool showWindow = RGFW_FALSE;
 8225+	if (win->src.window) {
 8226+		showWindow = (RGFW_window_isMinimized(win) == RGFW_FALSE);
 8227+		RGFW_window_closePlatform(win);
 8228+	}
 8229+
 8230+	RGFW_bool transparent = (win->internal.flags & RGFW_windowTransparent);
 8231+
 8232+	/* start by creating a GLX config / X11 Viusal */
 8233+	XVisualInfo visual;
 8234+	GLXFBConfig bestFbc;
 8235+
 8236+	i32 visual_attribs[40];
 8237+	RGFW_attribStack stack;
 8238+	RGFW_attribStack_init(&stack, visual_attribs, 40);
 8239+	RGFW_attribStack_pushAttribs(&stack, GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR);
 8240+	RGFW_attribStack_pushAttribs(&stack, GLX_X_RENDERABLE, 1);
 8241+	RGFW_attribStack_pushAttribs(&stack, GLX_RENDER_TYPE, GLX_RGBA_BIT);
 8242+	RGFW_attribStack_pushAttribs(&stack, GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT);
 8243+	RGFW_attribStack_pushAttribs(&stack, GLX_DOUBLEBUFFER, 1);
 8244+	RGFW_attribStack_pushAttribs(&stack, GLX_ALPHA_SIZE, hints->alpha);
 8245+	RGFW_attribStack_pushAttribs(&stack, GLX_DEPTH_SIZE, hints->depth);
 8246+	RGFW_attribStack_pushAttribs(&stack, GLX_STENCIL_SIZE, hints->stencil);
 8247+	RGFW_attribStack_pushAttribs(&stack, GLX_STEREO, hints->stereo);
 8248+	RGFW_attribStack_pushAttribs(&stack, GLX_AUX_BUFFERS, hints->auxBuffers);
 8249+	RGFW_attribStack_pushAttribs(&stack, GLX_RED_SIZE, hints->red);
 8250+	RGFW_attribStack_pushAttribs(&stack, GLX_GREEN_SIZE, hints->green);
 8251+	RGFW_attribStack_pushAttribs(&stack, GLX_BLUE_SIZE, hints->blue);
 8252+	RGFW_attribStack_pushAttribs(&stack, GLX_ACCUM_RED_SIZE, hints->accumRed);
 8253+	RGFW_attribStack_pushAttribs(&stack, GLX_ACCUM_GREEN_SIZE, hints->accumGreen);
 8254+	RGFW_attribStack_pushAttribs(&stack, GLX_ACCUM_BLUE_SIZE, hints->accumBlue);
 8255+	RGFW_attribStack_pushAttribs(&stack, GLX_ACCUM_ALPHA_SIZE, hints->accumAlpha);
 8256+
 8257+	if (hints->sRGB) {
 8258+		if (RGFW_extensionSupportedPlatform_OpenGL(sRGBARBstr, sizeof(sRGBARBstr)))
 8259+			RGFW_attribStack_pushAttribs(&stack, GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB, hints->sRGB);
 8260+		if (RGFW_extensionSupportedPlatform_OpenGL(sRGBEXTstr, sizeof(sRGBEXTstr)))
 8261+			RGFW_attribStack_pushAttribs(&stack, GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT, hints->sRGB);
 8262+	}
 8263+
 8264+	RGFW_attribStack_pushAttribs(&stack, 0, 0);
 8265+
 8266+	/* find the configs */
 8267+	i32 fbcount;
 8268+	GLXFBConfig* fbc = glXChooseFBConfig(_RGFW->display, DefaultScreen(_RGFW->display), visual_attribs, &fbcount);
 8269+
 8270+	i32 best_fbc = -1;
 8271+	i32 best_depth = 0;
 8272+	i32 best_samples = 0;
 8273+
 8274+	if (fbcount == 0) {
 8275+		RGFW_debugCallback(RGFW_typeError, RGFW_errOpenGLContext, "Failed to find any valid GLX visual configs.");
 8276+		return 0;
 8277+	}
 8278+
 8279+	/* search through all found configs to find the best match */
 8280+	i32 i;
 8281+	for (i = 0; i < fbcount; i++) {
 8282+		XVisualInfo* vi = glXGetVisualFromFBConfig(_RGFW->display, fbc[i]);
 8283+		if (vi == NULL)
 8284+			continue;
 8285+
 8286+		i32 samp_buf, samples;
 8287+		glXGetFBConfigAttrib(_RGFW->display, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf);
 8288+		glXGetFBConfigAttrib(_RGFW->display, fbc[i], GLX_SAMPLES, &samples);
 8289+
 8290+		if (best_fbc == -1) best_fbc = i;
 8291+		if ((!(transparent) || vi->depth == 32)  && best_depth == 0) {
 8292+			best_fbc = i;
 8293+			best_depth = vi->depth;
 8294+		}
 8295+		if ((!(transparent) || vi->depth == 32) && samples <= hints->samples && samples > best_samples) {
 8296+			best_fbc = i;
 8297+			best_depth = vi->depth;
 8298+			best_samples = samples;
 8299+		}
 8300+		XFree(vi);
 8301+	}
 8302+
 8303+	if (best_fbc == -1) {
 8304+		RGFW_debugCallback(RGFW_typeError, RGFW_errOpenGLContext, "Failed to get a valid GLX visual.");
 8305+		return 0;
 8306+	}
 8307+
 8308+	/* we found a config */
 8309+	bestFbc = fbc[best_fbc];
 8310+	XVisualInfo* vi = glXGetVisualFromFBConfig(_RGFW->display, bestFbc);
 8311+	if (vi->depth != 32 && transparent)
 8312+		RGFW_debugCallback(RGFW_typeWarning, RGFW_warningOpenGL,  "Failed to to find a matching visual with a 32-bit depth.");
 8313+
 8314+	if (best_samples < hints->samples)
 8315+		RGFW_debugCallback(RGFW_typeWarning, RGFW_warningOpenGL, "Failed to load a matching sample count.");
 8316+
 8317+	XFree(fbc);
 8318+	visual = *vi;
 8319+	XFree(vi);
 8320+
 8321+	/* use the visual to create a new window */
 8322+	RGFW_XCreateWindow(visual, "", win->internal.flags, win);
 8323+
 8324+	if (showWindow) {
 8325+		RGFW_window_show(win);
 8326+	}
 8327+
 8328+	/* create the actual OpenGL context  */
 8329+	i32 context_attribs[40];
 8330+	RGFW_attribStack_init(&stack, context_attribs, 40);
 8331+
 8332+	i32 mask = 0;
 8333+	switch (hints->profile) {
 8334+		case RGFW_glES: mask |= GLX_CONTEXT_ES_PROFILE_BIT_EXT; break;
 8335+		case RGFW_glForwardCompatibility: mask |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; break;
 8336+		case RGFW_glCompatibility: mask |= GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; break;
 8337+		case RGFW_glCore: mask |= GLX_CONTEXT_CORE_PROFILE_BIT_ARB; break;
 8338+		default: mask |= GLX_CONTEXT_CORE_PROFILE_BIT_ARB; break;
 8339+	}
 8340+
 8341+	RGFW_attribStack_pushAttribs(&stack, GLX_CONTEXT_PROFILE_MASK_ARB, mask);
 8342+
 8343+	if (hints->minor || hints->major) {
 8344+		RGFW_attribStack_pushAttribs(&stack, GLX_CONTEXT_MAJOR_VERSION_ARB, hints->major);
 8345+		RGFW_attribStack_pushAttribs(&stack, GLX_CONTEXT_MINOR_VERSION_ARB, hints->minor);
 8346+	}
 8347+
 8348+
 8349+	if (RGFW_extensionSupportedPlatform_OpenGL(flushStr, sizeof(flushStr))) {
 8350+		if (hints->releaseBehavior == RGFW_glReleaseFlush) {
 8351+			RGFW_attribStack_pushAttribs(&stack, GLX_CONTEXT_RELEASE_BEHAVIOR_ARB, GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
 8352+		} else if (hints->releaseBehavior == RGFW_glReleaseNone) {
 8353+			RGFW_attribStack_pushAttribs(&stack, GLX_CONTEXT_RELEASE_BEHAVIOR_ARB, GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
 8354+		}
 8355+	}
 8356+
 8357+	i32 flags = 0;
 8358+	if (hints->debug) flags |= GLX_CONTEXT_DEBUG_BIT_ARB;
 8359+	if (hints->robustness && RGFW_extensionSupportedPlatform_OpenGL(robustStr, sizeof(robustStr))) flags |= GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB;
 8360+	if (flags) {
 8361+		RGFW_attribStack_pushAttribs(&stack, GLX_CONTEXT_FLAGS_ARB, flags);
 8362+	}
 8363+
 8364+	if (RGFW_extensionSupportedPlatform_OpenGL(noErorrStr, sizeof(noErorrStr))) {
 8365+		RGFW_attribStack_pushAttribs(&stack, GLX_CONTEXT_OPENGL_NO_ERROR_ARB, hints->noError);
 8366+	}
 8367+
 8368+	RGFW_attribStack_pushAttribs(&stack, 0, 0);
 8369+
 8370+	/*  create the context */
 8371+	glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0;
 8372+	char str[] = "glXCreateContextAttribsARB";
 8373+	glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)glXGetProcAddressARB((u8*) str);
 8374+
 8375+	GLXContext ctx = NULL;
 8376+	if (hints->share) {
 8377+		ctx = hints->share->ctx;
 8378+	}
 8379+
 8380+	if (glXCreateContextAttribsARB == NULL) {
 8381+		RGFW_debugCallback(RGFW_typeError, RGFW_errOpenGLContext, "Failed to load proc address 'glXCreateContextAttribsARB', loading a generic OpenGL context.");
 8382+			win->src.ctx.native->ctx = glXCreateContext(_RGFW->display, &visual, ctx, True);
 8383+	} else {
 8384+		_RGFW->x11Error = NULL;
 8385+		win->src.ctx.native->ctx = glXCreateContextAttribsARB(_RGFW->display, bestFbc, ctx, True, context_attribs);
 8386+		if (_RGFW->x11Error || win->src.ctx.native->ctx == NULL) {
 8387+			RGFW_debugCallback(RGFW_typeError, RGFW_errOpenGLContext, "Failed to create an OpenGL context with AttribsARB, loading a generic OpenGL context.");
 8388+			win->src.ctx.native->ctx = glXCreateContext(_RGFW->display, &visual, ctx, True);
 8389+		}
 8390+	}
 8391+
 8392+	#ifndef RGFW_NO_GLXWINDOW
 8393+		win->src.ctx.native->window = glXCreateWindow(_RGFW->display, bestFbc, win->src.window, NULL);
 8394+	#else
 8395+		win->src.ctx.native->window = win->src.window;
 8396+	#endif
 8397+
 8398+	glXMakeCurrent(_RGFW->display, (Drawable)win->src.ctx.native->window, (GLXContext)win->src.ctx.native->ctx);
 8399+	RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "OpenGL context initalized.");
 8400+
 8401+	RGFW_window_swapInterval_OpenGL(win, 0);
 8402+
 8403+	return RGFW_TRUE;
 8404+}
 8405+
 8406+void RGFW_FUNC(RGFW_window_deleteContextPtr_OpenGL) (RGFW_window* win, RGFW_glContext* ctx) {
 8407+	#ifndef RGFW_NO_GLXWINDOW
 8408+	if (win->src.ctx.native->window != win->src.window) {
 8409+		glXDestroyWindow(_RGFW->display, win->src.ctx.native->window);
 8410+	}
 8411+	#endif
 8412+
 8413+	glXDestroyContext(_RGFW->display, ctx->ctx);
 8414+	win->src.ctx.native = NULL;
 8415+	RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL,  "OpenGL context freed.");
 8416+}
 8417+
 8418+RGFW_bool RGFW_FUNC(RGFW_extensionSupportedPlatform_OpenGL)(const char * extension, size_t len) {
 8419+	RGFW_init();
 8420+	const char* extensions = glXQueryExtensionsString(_RGFW->display, XDefaultScreen(_RGFW->display));
 8421+	return (extensions != NULL) && RGFW_extensionSupportedStr(extensions, extension, len);
 8422+}
 8423+
 8424+RGFW_proc RGFW_FUNC(RGFW_getProcAddress_OpenGL)(const char* procname) { return glXGetProcAddress((u8*) procname); }
 8425+
 8426+void RGFW_FUNC(RGFW_window_makeCurrentContext_OpenGL) (RGFW_window* win) { if (win) RGFW_ASSERT(win->src.ctx.native);
 8427+	if (win == NULL)
 8428+		glXMakeCurrent(NULL, (Drawable)NULL, (GLXContext) NULL);
 8429+	else
 8430+		glXMakeCurrent(_RGFW->display, (Drawable)win->src.ctx.native->window, (GLXContext) win->src.ctx.native->ctx);
 8431+	return;
 8432+}
 8433+void* RGFW_FUNC(RGFW_getCurrentContext_OpenGL) (void) { return glXGetCurrentContext(); }
 8434+void RGFW_FUNC(RGFW_window_swapBuffers_OpenGL) (RGFW_window* win) { RGFW_ASSERT(win->src.ctx.native); glXSwapBuffers(_RGFW->display, win->src.ctx.native->window); }
 8435+
 8436+void RGFW_FUNC(RGFW_window_swapInterval_OpenGL) (RGFW_window* win, i32 swapInterval) {
 8437+	RGFW_ASSERT(win != NULL);
 8438+	/* cached pfn to avoid calling glXGetProcAddress more than once */
 8439+	static PFNGLXSWAPINTERVALEXTPROC pfn = NULL;
 8440+	static int (*pfn2)(int) = NULL;
 8441+
 8442+	if (pfn == NULL) {
 8443+		u8 str[] = "glXSwapIntervalEXT";
 8444+		pfn = (PFNGLXSWAPINTERVALEXTPROC)glXGetProcAddress(str);
 8445+		if (pfn == NULL)  {
 8446+			pfn = (PFNGLXSWAPINTERVALEXTPROC)1;
 8447+			const char* array[] = {"GLX_MESA_swap_control", "GLX_SGI_swap_control"};
 8448+
 8449+			size_t i;
 8450+			for (i = 0; i < sizeof(array) / sizeof(char*) && pfn2 == NULL; i++) {
 8451+				pfn2 = (int(*)(int))glXGetProcAddress((u8*)array[i]);
 8452+			}
 8453+
 8454+			if (pfn2 != NULL) {
 8455+				RGFW_debugCallback(RGFW_typeError, RGFW_errOpenGLContext,  "Failed to load swap interval function, fallingback to the native swapinterval function");
 8456+			} else {
 8457+				RGFW_debugCallback(RGFW_typeError, RGFW_errOpenGLContext,  "Failed to load swap interval function");
 8458+			}
 8459+		}
 8460+	}
 8461+
 8462+	if (pfn != (PFNGLXSWAPINTERVALEXTPROC)1) {
 8463+		pfn(_RGFW->display, win->src.ctx.native->window, swapInterval);
 8464+	}
 8465+	else if (pfn2 != NULL) {
 8466+		pfn2(swapInterval);
 8467+	}
 8468+}
 8469+#endif /* RGFW_OPENGL */
 8470+
 8471+i32 RGFW_initPlatform_X11(void) {
 8472+    #ifdef RGFW_USE_XDL
 8473+		XDL_init();
 8474+	#endif
 8475+
 8476+	#if !defined(RGFW_NO_X11_CURSOR) && !defined(RGFW_NO_X11_CURSOR_PRELOAD)
 8477+	#if defined(__CYGWIN__)
 8478+				RGFW_LOAD_LIBRARY(X11Cursorhandle, "libXcursor-1.so");
 8479+	#elif defined(__OpenBSD__) || defined(__NetBSD__)
 8480+				RGFW_LOAD_LIBRARY(X11Cursorhandle, "libXcursor.so");
 8481+	#else
 8482+				RGFW_LOAD_LIBRARY(X11Cursorhandle, "libXcursor.so.1");
 8483+	#endif
 8484+		RGFW_PROC_DEF(X11Cursorhandle, XcursorImageCreate);
 8485+		RGFW_PROC_DEF(X11Cursorhandle, XcursorImageDestroy);
 8486+		RGFW_PROC_DEF(X11Cursorhandle, XcursorImageLoadCursor);
 8487+	#endif
 8488+
 8489+	#if !defined(RGFW_NO_X11_XI_PRELOAD)
 8490+	#if defined(__CYGWIN__)
 8491+			RGFW_LOAD_LIBRARY(X11Xihandle, "libXi-6.so");
 8492+	#elif defined(__OpenBSD__) || defined(__NetBSD__)
 8493+			RGFW_LOAD_LIBRARY(X11Xihandle, "libXi.so");
 8494+	#else
 8495+			RGFW_LOAD_LIBRARY(X11Xihandle, "libXi.so.6");
 8496+	#endif
 8497+			RGFW_PROC_DEF(X11Xihandle, XISelectEvents);
 8498+	#endif
 8499+
 8500+	#if !defined(RGFW_NO_X11_EXT_PRELOAD)
 8501+	#if defined(__CYGWIN__)
 8502+			RGFW_LOAD_LIBRARY(X11XEXThandle, "libXext-6.so");
 8503+	#elif defined(__OpenBSD__) || defined(__NetBSD__)
 8504+	        RGFW_LOAD_LIBRARY(X11XEXThandle, "libXext.so");
 8505+	#else
 8506+			RGFW_LOAD_LIBRARY(X11XEXThandle, "libXext.so.6");
 8507+	#endif
 8508+			RGFW_PROC_DEF(X11XEXThandle, XSyncCreateCounter);
 8509+			RGFW_PROC_DEF(X11XEXThandle, XSyncIntToValue);
 8510+			RGFW_PROC_DEF(X11XEXThandle, XSyncSetCounter);
 8511+    	    RGFW_PROC_DEF(X11XEXThandle, XShapeCombineRegion);
 8512+	        RGFW_PROC_DEF(X11XEXThandle, XShapeCombineMask);
 8513+    #endif
 8514+
 8515+    XInitThreads(); /*!< init X11 threading */
 8516+    _RGFW->display = XOpenDisplay(0);
 8517+	_RGFW->context = XUniqueContext();
 8518+
 8519+	XSetWindowAttributes wa;
 8520+    RGFW_MEMZERO(&wa, sizeof(wa));
 8521+    wa.event_mask = PropertyChangeMask;
 8522+    _RGFW->helperWindow = XCreateWindow(_RGFW->display, XDefaultRootWindow(_RGFW->display), 0, 0, 1, 1, 0, 0,
 8523+                                        InputOnly, DefaultVisual(_RGFW->display, DefaultScreen(_RGFW->display)), CWEventMask, &wa);
 8524+
 8525+    u8 RGFW_blk[] = { 0, 0, 0, 0 };
 8526+	_RGFW->hiddenMouse = RGFW_createMouse(RGFW_blk, 1, 1, RGFW_formatRGBA8);
 8527+
 8528+	_RGFW->clipboard = NULL;
 8529+
 8530+    XkbComponentNamesRec rec;
 8531+    XkbDescPtr desc = XkbGetMap(_RGFW->display, 0, XkbUseCoreKbd);
 8532+    XkbDescPtr evdesc;
 8533+    XSetErrorHandler(RGFW_XErrorHandler);
 8534+	u8 old[256];
 8535+
 8536+    XkbGetNames(_RGFW->display, XkbKeyNamesMask, desc);
 8537+
 8538+    RGFW_MEMZERO(&rec, sizeof(rec));
 8539+    char evdev[] = "evdev";
 8540+    rec.keycodes = evdev;
 8541+    evdesc = XkbGetKeyboardByName(_RGFW->display, XkbUseCoreKbd, &rec, XkbGBN_KeyNamesMask, XkbGBN_KeyNamesMask, False);
 8542+    /* memo: RGFW_keycodes[x11 keycode] = rgfw keycode */
 8543+    if(evdesc != NULL && desc != NULL) {
 8544+        int i, j;
 8545+        for(i = 0; i < (int)sizeof(old); i++){
 8546+    	    old[i] = _RGFW->keycodes[i];
 8547+    	    _RGFW->keycodes[i] = 0;
 8548+        }
 8549+        for(i = evdesc->min_key_code; i <= evdesc->max_key_code; i++){
 8550+    	    for(j = desc->min_key_code; j <= desc->max_key_code; j++){
 8551+                if(RGFW_STRNCMP(evdesc->names->keys[i].name, desc->names->keys[j].name, XkbKeyNameLength) == 0){
 8552+                    _RGFW->keycodes[j] = old[i];
 8553+                    break;
 8554+                }
 8555+    	    }
 8556+        }
 8557+		XkbFreeKeyboard(desc, 0, True);
 8558+		XkbFreeKeyboard(evdesc, 0, True);
 8559+    }
 8560+
 8561+	XSetLocaleModifiers("");
 8562+	XRegisterIMInstantiateCallback(_RGFW->display, NULL, NULL, NULL, RGFW_x11_imInitCallback, NULL);
 8563+
 8564+	unsigned char mask[XIMaskLen(XI_RawMotion)];
 8565+	RGFW_MEMZERO(mask, sizeof(mask));
 8566+	XISetMask(mask, XI_RawMotion);
 8567+
 8568+	XIEventMask em;
 8569+	em.deviceid = XIAllMasterDevices;
 8570+	em.mask_len = sizeof(mask);
 8571+	em.mask = mask;
 8572+
 8573+	XISelectEvents(_RGFW->display, XDefaultRootWindow(_RGFW->display), &em, 1);
 8574+
 8575+	i32 errorBase;
 8576+	if (XRRQueryExtension(_RGFW->display, &_RGFW->xrandrEventBase, &errorBase)) {
 8577+        XRRSelectInput(_RGFW->display, RootWindow(_RGFW->display, DefaultScreen(_RGFW->display)), RROutputChangeNotifyMask);
 8578+	}
 8579+
 8580+	return 0;
 8581+}
 8582+
 8583+void RGFW_deinitPlatform_X11(void) {
 8584+    #define RGFW_FREE_LIBRARY(x) if (x != NULL) dlclose(x); x = NULL;
 8585+	/* to save the clipboard on the x server after the window is closed */
 8586+	RGFW_LOAD_ATOM(CLIPBOARD_MANAGER);  RGFW_LOAD_ATOM(CLIPBOARD);
 8587+	RGFW_LOAD_ATOM(SAVE_TARGETS);
 8588+	if (XGetSelectionOwner(_RGFW->display, CLIPBOARD) == _RGFW->helperWindow) {
 8589+		XConvertSelection(_RGFW->display, CLIPBOARD_MANAGER, SAVE_TARGETS, None, _RGFW->helperWindow, CurrentTime);
 8590+        while (RGFW_XHandleClipboardSelectionHelper());
 8591+	}
 8592+
 8593+	XUnregisterIMInstantiateCallback(_RGFW->display, NULL, NULL, NULL, RGFW_x11_imInitCallback, NULL);
 8594+
 8595+    if (_RGFW->im) {
 8596+        XCloseIM(_RGFW->im);
 8597+        _RGFW->im = NULL;
 8598+    }
 8599+
 8600+	if (_RGFW->clipboard) {
 8601+		RGFW_FREE(_RGFW->clipboard);
 8602+		_RGFW->clipboard = NULL;
 8603+	}
 8604+
 8605+	if (_RGFW->hiddenMouse) {
 8606+		RGFW_freeMouse(_RGFW->hiddenMouse);
 8607+		_RGFW->hiddenMouse = NULL;
 8608+	}
 8609+
 8610+    XDestroyWindow(_RGFW->display, (Drawable) _RGFW->helperWindow); /*!< close the window */
 8611+    XCloseDisplay(_RGFW->display); /*!< kill connection to the x server */
 8612+
 8613+    #if !defined(RGFW_NO_X11_CURSOR_PRELOAD) && !defined(RGFW_NO_X11_CURSOR)
 8614+        RGFW_FREE_LIBRARY(X11Cursorhandle);
 8615+    #endif
 8616+    #if !defined(RGFW_NO_X11_XI_PRELOAD)
 8617+        RGFW_FREE_LIBRARY(X11Xihandle);
 8618+    #endif
 8619+
 8620+    #ifdef RGFW_USE_XDL
 8621+        XDL_close();
 8622+    #endif
 8623+
 8624+    #if !defined(RGFW_NO_X11_EXT_PRELOAD)
 8625+        RGFW_FREE_LIBRARY(X11XEXThandle);
 8626+    #endif
 8627+}
 8628+
 8629+void RGFW_FUNC(RGFW_window_closePlatform)(RGFW_window* win) {
 8630+    if (win->src.ic) {
 8631+        XDestroyIC(win->src.ic);
 8632+        win->src.ic = NULL;
 8633+    }
 8634+
 8635+	XFreeGC(_RGFW->display, win->src.gc);
 8636+	XDeleteContext(_RGFW->display, win->src.window, _RGFW->context);
 8637+	XDestroyWindow(_RGFW->display, (Drawable) win->src.window); /*!< close the window */
 8638+	return;
 8639+}
 8640+
 8641+#ifdef RGFW_WEBGPU
 8642+WGPUSurface RGFW_FUNC(RGFW_window_createSurface_WebGPU) (RGFW_window* window, WGPUInstance instance) {
 8643+	WGPUSurfaceDescriptor surfaceDesc = {0};
 8644+	WGPUSurfaceSourceXlibWindow fromXlib = {0};
 8645+	fromXlib.chain.sType = WGPUSType_SurfaceSourceXlibWindow;
 8646+	fromXlib.display = _RGFW->display;
 8647+	fromXlib.window = window->src.window;
 8648+
 8649+	surfaceDesc.nextInChain = (WGPUChainedStruct*)&fromXlib.chain;
 8650+	return wgpuInstanceCreateSurface(instance, &surfaceDesc);
 8651+}
 8652+#endif
 8653+
 8654+#endif
 8655+/*
 8656+	End of X11 linux / wayland / unix defines
 8657+*/
 8658+
 8659+/*
 8660+
 8661+	Start of Wayland defayland
 8662+*/
 8663+
 8664+#ifdef RGFW_WAYLAND
 8665+#ifdef RGFW_X11
 8666+#undef RGFW_FUNC /* remove previous define */
 8667+#define RGFW_FUNC(func) func##_Wayland
 8668+#else
 8669+#define RGFW_FUNC(func) func
 8670+#endif
 8671+
 8672+/*
 8673+Wayland TODO: (out of date)
 8674+- fix RGFW_keyPressed lock state
 8675+
 8676+	RGFW_windowMoved, 		the window was moved (by the user)
 8677+	RGFW_windowRefresh	 	The window content needs to be refreshed
 8678+
 8679+	RGFW_dataDrop 				a file has been dropped into the window
 8680+	RGFW_dataDrag
 8681+
 8682+- window args:
 8683+	#define RGFW_windowNoResize	 			the window cannot be resized  by the user
 8684+	#define RGFW_windowAllowDND     			the window supports drag and drop
 8685+	#define RGFW_scaleToMonitor 			scale the window to the screen
 8686+
 8687+- other missing functions functions ("TODO wayland") (~30 functions)
 8688+- fix buffer rendering weird behavior
 8689+*/
 8690+#include <errno.h>
 8691+#include <unistd.h>
 8692+#include <sys/mman.h>
 8693+#include <xkbcommon/xkbcommon.h>
 8694+#include <xkbcommon/xkbcommon-keysyms.h>
 8695+#include <xkbcommon/xkbcommon-compose.h>
 8696+#include <dirent.h>
 8697+#include <linux/kd.h>
 8698+#include <wayland-cursor.h>
 8699+#include <fcntl.h>
 8700+
 8701+struct wl_display* RGFW_getDisplay_Wayland(void) { return _RGFW->wl_display; }
 8702+struct wl_surface* RGFW_window_getWindow_Wayland(RGFW_window* win) { return win->src.surface; }
 8703+
 8704+
 8705+/* wayland global garbage (wayland bad, X11 is fine (ish) (not really)) */
 8706+#include "xdg-shell.h"
 8707+#include "xdg-toplevel-icon-v1.h"
 8708+#include "xdg-decoration-unstable-v1.h"
 8709+#include "relative-pointer-unstable-v1.h"
 8710+#include "pointer-constraints-unstable-v1.h"
 8711+#include "xdg-output-unstable-v1.h"
 8712+#include "pointer-warp-v1.h"
 8713+
 8714+void RGFW_toggleWaylandMaximized(RGFW_window* win, RGFW_bool maximized);
 8715+
 8716+static void RGFW_wl_setOpaque(RGFW_window* win) {
 8717+	struct wl_region* wl_region = wl_compositor_create_region(_RGFW->compositor);
 8718+
 8719+	if (!wl_region) return; /* return if no region was created */
 8720+
 8721+	wl_region_add(wl_region, 0, 0, win->w, win->h);
 8722+	wl_surface_set_opaque_region(win->src.surface, wl_region);
 8723+	wl_region_destroy(wl_region);
 8724+
 8725+}
 8726+
 8727+static void RGFW_wl_xdg_wm_base_ping_handler(void* data, struct xdg_wm_base* wm_base,
 8728+		u32 serial) {
 8729+	RGFW_UNUSED(data);
 8730+    xdg_wm_base_pong(wm_base, serial);
 8731+}
 8732+static void RGFW_wl_xdg_surface_configure_handler(void* data, struct xdg_surface* xdg_surface,
 8733+		u32 serial) {
 8734+
 8735+    xdg_surface_ack_configure(xdg_surface, serial);
 8736+
 8737+    RGFW_window* win = (RGFW_window*)data;
 8738+
 8739+    if (win == NULL) {
 8740+		win = _RGFW->kbOwner;
 8741+		if (win == NULL)
 8742+			return;
 8743+	}
 8744+
 8745+	/* useful for libdecor */
 8746+	if (win->src.activated != win->src.pending_activated) {
 8747+		win->src.activated = win->src.pending_activated;
 8748+	}
 8749+
 8750+	if (win->src.maximized != win->src.pending_maximized) {
 8751+		RGFW_toggleWaylandMaximized(win, win->src.pending_maximized);
 8752+
 8753+		RGFW_window_checkMode(win);
 8754+	}
 8755+
 8756+
 8757+	if (win->src.resizing) {
 8758+
 8759+		RGFW_windowResizedCallback(win, win->w, win->h);
 8760+		RGFW_window_resize(win, win->w, win->h);
 8761+		if (!(win->internal.flags & RGFW_windowTransparent)) {
 8762+			RGFW_wl_setOpaque(win);
 8763+		}
 8764+	}
 8765+
 8766+	win->src.configured = RGFW_TRUE;
 8767+}
 8768+
 8769+static void RGFW_wl_xdg_toplevel_configure_handler(void* data, struct xdg_toplevel* toplevel,
 8770+		i32 width, i32 height, struct wl_array* states) {
 8771+
 8772+    RGFW_UNUSED(toplevel);
 8773+    RGFW_window* win = (RGFW_window*)data;
 8774+
 8775+
 8776+    win->src.pending_activated = RGFW_FALSE;
 8777+    win->src.pending_maximized = RGFW_FALSE;
 8778+    win->src.resizing = RGFW_FALSE;
 8779+
 8780+
 8781+	enum xdg_toplevel_state* state;
 8782+	wl_array_for_each(state, states) {
 8783+		switch (*state) {
 8784+			case XDG_TOPLEVEL_STATE_ACTIVATED:
 8785+				 win->src.pending_activated = RGFW_TRUE;
 8786+				break;
 8787+			case XDG_TOPLEVEL_STATE_MAXIMIZED:
 8788+				win->src.pending_maximized = RGFW_TRUE;
 8789+				break;
 8790+			default:
 8791+				break;
 8792+		}
 8793+
 8794+	}
 8795+	/* if width and height are not zero and are not the same as the window */
 8796+    /* the window is resizing so update the values */
 8797+	if ((width && height) && (win->w != width ||  win->h != height)) {
 8798+		win->src.resizing = RGFW_TRUE;
 8799+		win->src.w = win->w = width;
 8800+		win->src.h = win->h = height;
 8801+	}
 8802+}
 8803+
 8804+static void RGFW_wl_xdg_toplevel_close_handler(void* data, struct xdg_toplevel *toplevel) {
 8805+	RGFW_UNUSED(toplevel);
 8806+	RGFW_window* win = (RGFW_window*)data;
 8807+
 8808+	if (!win->internal.shouldClose) {
 8809+		RGFW_windowCloseCallback(win);
 8810+	}
 8811+}
 8812+
 8813+static void RGFW_wl_xdg_decoration_configure_handler(void* data,
 8814+		struct zxdg_toplevel_decoration_v1* zxdg_toplevel_decoration_v1, u32 mode) {
 8815+	RGFW_window* win = (RGFW_window*)data; RGFW_UNUSED(zxdg_toplevel_decoration_v1);
 8816+
 8817+	/* this is expected to run once */
 8818+    /* set the decoration mode set by earlier request */
 8819+	if (mode != win->src.decoration_mode) {
 8820+		win->src.decoration_mode = mode;
 8821+	}
 8822+}
 8823+
 8824+static void RGFW_wl_shm_format_handler(void* data, struct wl_shm *shm, u32 format) {
 8825+	RGFW_UNUSED(data); RGFW_UNUSED(shm); RGFW_UNUSED(format);
 8826+}
 8827+
 8828+static void RGFW_wl_relative_pointer_motion(void *data, struct zwp_relative_pointer_v1 *zwp_relative_pointer_v1,
 8829+	u32 time_hi, u32 time_lo, wl_fixed_t dx, wl_fixed_t dy, wl_fixed_t dx_unaccel, wl_fixed_t dy_unaccel) {
 8830+
 8831+	RGFW_UNUSED(zwp_relative_pointer_v1); RGFW_UNUSED(time_hi); RGFW_UNUSED(time_lo);
 8832+	RGFW_UNUSED(dx_unaccel); RGFW_UNUSED(dy_unaccel);
 8833+
 8834+	RGFW_info* RGFW = (RGFW_info*)data;
 8835+
 8836+	RGFW_ASSERT(RGFW->mouseOwner != NULL);
 8837+	RGFW_window* win = RGFW->mouseOwner;
 8838+
 8839+	RGFW_ASSERT(win);
 8840+
 8841+	float vecX =  (float)wl_fixed_to_double(dx);
 8842+	float vecY = (float)wl_fixed_to_double(dy);
 8843+	RGFW_rawMotionCallback(win, vecX, vecY);
 8844+}
 8845+
 8846+static void RGFW_wl_pointer_locked(void *data, struct zwp_locked_pointer_v1 *zwp_locked_pointer_v1) {
 8847+	RGFW_UNUSED(zwp_locked_pointer_v1);
 8848+	RGFW_info* RGFW = (RGFW_info*)data;
 8849+	wl_pointer_set_cursor(RGFW->wl_pointer, RGFW->mouse_enter_serial, NULL, 0, 0); /* draw no cursor */
 8850+}
 8851+
 8852+static void RGFW_wl_pointer_enter(void* data, struct wl_pointer* pointer, u32 serial,
 8853+		struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y) {
 8854+	RGFW_info* RGFW = (RGFW_info*)data;
 8855+	RGFW_window* win = (RGFW_window*)wl_surface_get_user_data(surface);
 8856+
 8857+	/* save when the pointer is locked or using default cursor */
 8858+	RGFW->mouse_enter_serial = serial;
 8859+	win->internal.mouseInside = RGFW_TRUE;
 8860+	RGFW->windowState.mouseEnter = RGFW_TRUE;
 8861+
 8862+	RGFW->mouseOwner = win;
 8863+
 8864+	/* set the cursor */
 8865+	if (win->src.using_custom_cursor) {
 8866+		wl_pointer_set_cursor(pointer, serial, win->src.custom_cursor_surface, 0, 0);
 8867+	}
 8868+	else {
 8869+		RGFW_window_setMouseDefault(win);
 8870+	}
 8871+
 8872+	i32 x = (i32)wl_fixed_to_double(surface_x);
 8873+	i32 y = (i32)wl_fixed_to_double(surface_y);
 8874+	RGFW_mouseNotifyCallback(win, x, y, RGFW_TRUE);
 8875+}
 8876+
 8877+static void RGFW_wl_pointer_leave(void* data, struct wl_pointer *pointer, u32 serial, struct wl_surface *surface) {
 8878+	RGFW_UNUSED(pointer); RGFW_UNUSED(serial);
 8879+	RGFW_window* win = (RGFW_window*)wl_surface_get_user_data(surface);
 8880+	RGFW_info* RGFW = (RGFW_info*)data;
 8881+	if (RGFW->mouseOwner == win)
 8882+		RGFW->mouseOwner = NULL;
 8883+
 8884+	RGFW_mouseNotifyCallback(win, win->internal.lastMouseX, win->internal.lastMouseY, RGFW_FALSE);
 8885+}
 8886+
 8887+static void RGFW_wl_pointer_motion(void* data, struct wl_pointer *pointer, u32 time, wl_fixed_t x, wl_fixed_t y) {
 8888+	RGFW_UNUSED(pointer); RGFW_UNUSED(time);
 8889+	RGFW_info* RGFW = (RGFW_info*)data;
 8890+	RGFW_ASSERT(RGFW->mouseOwner != NULL);
 8891+
 8892+	RGFW_window* win = RGFW->mouseOwner;
 8893+
 8894+	i32 convertedX = (i32)wl_fixed_to_double(x);
 8895+	i32 convertedY = (i32)wl_fixed_to_double(y);
 8896+
 8897+	RGFW_mousePosCallback(win, convertedX, convertedY);
 8898+}
 8899+
 8900+static void RGFW_wl_pointer_button(void* data, struct wl_pointer *pointer, u32 serial, u32 time, u32 button, u32 state) {
 8901+	RGFW_UNUSED(pointer); RGFW_UNUSED(time); RGFW_UNUSED(serial);
 8902+	RGFW_info* RGFW = (RGFW_info*)data;
 8903+
 8904+	RGFW_ASSERT(RGFW->mouseOwner != NULL);
 8905+	RGFW_window* win = RGFW->mouseOwner;
 8906+
 8907+	u32 b = (button - 0x110);
 8908+
 8909+	/* flip right and middle button codes */
 8910+	if (b == 1) b = 2;
 8911+	else if (b == 2) b = 1;
 8912+
 8913+	RGFW_mouseButtonCallback(win, (u8)b, RGFW_BOOL(state));
 8914+}
 8915+
 8916+static void RGFW_wl_pointer_axis(void* data, struct wl_pointer *pointer, u32 time, u32 axis, wl_fixed_t value) {
 8917+	RGFW_UNUSED(pointer); RGFW_UNUSED(time);  RGFW_UNUSED(axis);
 8918+
 8919+	RGFW_info* RGFW = (RGFW_info*)data;
 8920+	RGFW_ASSERT(RGFW->mouseOwner != NULL);
 8921+	RGFW_window* win = RGFW->mouseOwner;
 8922+
 8923+	float scrollX = 0.0;
 8924+	float scrollY = 0.0;
 8925+
 8926+	if (!(win->internal.enabledEvents  & (RGFW_BIT(RGFW_mouseScroll)))) return;
 8927+
 8928+	if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL)
 8929+		scrollX = (float)(-wl_fixed_to_double(value) / 10.0);
 8930+	else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
 8931+		scrollY = (float)(-wl_fixed_to_double(value) / 10.0);
 8932+
 8933+	RGFW_mouseScrollCallback(win, scrollX, scrollY);
 8934+}
 8935+
 8936+
 8937+static void RGFW_doNothing(void) { }
 8938+
 8939+static void RGFW_wl_keyboard_keymap(void* data, struct wl_keyboard *keyboard, u32 format, i32 fd, u32 size) {
 8940+	RGFW_UNUSED(keyboard); RGFW_UNUSED(format);
 8941+	RGFW_info* RGFW = (RGFW_info*)data;
 8942+
 8943+	char *keymap_string = mmap (NULL, size, PROT_READ, MAP_SHARED, fd, 0);
 8944+	xkb_keymap_unref(RGFW->keymap);
 8945+	RGFW->keymap = xkb_keymap_new_from_string(RGFW->xkb_context, keymap_string, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
 8946+
 8947+	munmap(keymap_string, size);
 8948+	close(fd);
 8949+	xkb_state_unref(RGFW->xkb_state);
 8950+	RGFW->xkb_state = xkb_state_new(RGFW->keymap);
 8951+
 8952+	const char* locale = getenv("LC_ALL");
 8953+	if (!locale)
 8954+		locale = getenv("LC_CTYPE");
 8955+	if (!locale)
 8956+		locale = getenv("LANG");
 8957+	if (!locale)
 8958+		locale = "C";
 8959+
 8960+	struct xkb_compose_table* composeTable = xkb_compose_table_new_from_locale(RGFW->xkb_context, locale, XKB_COMPOSE_COMPILE_NO_FLAGS);
 8961+	if (composeTable) {
 8962+		RGFW->composeState = xkb_compose_state_new(composeTable, XKB_COMPOSE_STATE_NO_FLAGS);
 8963+		xkb_compose_table_unref(composeTable);
 8964+	}
 8965+}
 8966+
 8967+static void RGFW_wl_keyboard_enter(void* data, struct wl_keyboard *keyboard, u32 serial, struct wl_surface *surface, struct wl_array *keys) {
 8968+	RGFW_UNUSED(keyboard); RGFW_UNUSED(keys);
 8969+
 8970+	RGFW_info* RGFW = (RGFW_info*)data;
 8971+	RGFW_window* win = (RGFW_window*)wl_surface_get_user_data(surface);
 8972+	RGFW->kbOwner = win;
 8973+
 8974+
 8975+	// this is to prevent race conditions
 8976+	if (RGFW->data_device != NULL && win->src.data_source != NULL) {
 8977+		wl_data_device_set_selection(RGFW->data_device, win->src.data_source, serial);
 8978+	}
 8979+	/* is set when RGFW_window_minimize is called; if the minimize button is */
 8980+	/* pressed this flag is not set since there is no event to listen for */
 8981+	if (win->src.minimized == RGFW_TRUE) win->src.minimized = RGFW_FALSE;
 8982+
 8983+	RGFW_windowFocusCallback(win, RGFW_TRUE);
 8984+}
 8985+
 8986+static void RGFW_wl_keyboard_leave(void* data, struct wl_keyboard *keyboard, u32 serial, struct wl_surface *surface) {
 8987+	RGFW_UNUSED(keyboard); RGFW_UNUSED(serial);
 8988+
 8989+	RGFW_info* RGFW = (RGFW_info*)data;
 8990+	RGFW_window* win = (RGFW_window*)wl_surface_get_user_data(surface);
 8991+	if (RGFW->kbOwner == win)
 8992+		RGFW->kbOwner = NULL;
 8993+
 8994+	RGFW_windowFocusCallback(win, RGFW_FALSE);
 8995+}
 8996+
 8997+static xkb_keysym_t RGFW_wl_composeSymbol(RGFW_info* RGFW, xkb_keysym_t sym) {
 8998+    if (sym == XKB_KEY_NoSymbol || !RGFW->composeState)
 8999+        return sym;
 9000+    if (xkb_compose_state_feed(RGFW->composeState, sym) != XKB_COMPOSE_FEED_ACCEPTED)
 9001+        return sym;
 9002+    switch (xkb_compose_state_get_status(RGFW->composeState)) {
 9003+        case XKB_COMPOSE_COMPOSED:
 9004+            return xkb_compose_state_get_one_sym(RGFW->composeState);
 9005+        case XKB_COMPOSE_COMPOSING:
 9006+        case XKB_COMPOSE_CANCELLED:
 9007+            return XKB_KEY_NoSymbol;
 9008+        case XKB_COMPOSE_NOTHING:
 9009+        default:
 9010+            return sym;
 9011+    }
 9012+}
 9013+
 9014+static void RGFW_wl_send_key_event(u32 key) {
 9015+	const xkb_keysym_t* keysyms;
 9016+	if (xkb_state_key_get_syms(_RGFW->xkb_state, key + 8, &keysyms) == 1) {
 9017+		xkb_keysym_t keysym = RGFW_wl_composeSymbol(_RGFW, keysyms[0]);
 9018+		u32 codepoint = xkb_keysym_to_utf32(keysym);
 9019+		if (codepoint != 0) {
 9020+			RGFW_keyCharCallback(_RGFW->kbOwner, codepoint);
 9021+		}
 9022+	}
 9023+}
 9024+
 9025+static void RGFW_wl_keyboard_key(void* data, struct wl_keyboard *keyboard, u32 serial, u32 time, u32 key, u32 state) {
 9026+	RGFW_UNUSED(keyboard); RGFW_UNUSED(serial);
 9027+
 9028+	RGFW_info* RGFW = (RGFW_info*)data;
 9029+	if (RGFW->kbOwner == NULL) return;
 9030+
 9031+	RGFW_window *RGFW_key_win = RGFW->kbOwner;
 9032+	RGFW_key RGFWkey = RGFW_apiKeyToRGFW(key + 8);
 9033+
 9034+	RGFW_keyUpdateKeyMods(RGFW_key_win, RGFW_BOOL(xkb_keymap_mod_get_index(RGFW->keymap, "Lock")), RGFW_BOOL(xkb_keymap_mod_get_index(RGFW->keymap, "Mod2")), RGFW_BOOL(xkb_keymap_mod_get_index(RGFW->keymap, "ScrollLock")));
 9035+	RGFW_keyCallback(RGFW_key_win, (u8)RGFWkey, RGFW_key_win->internal.mod, RGFW_isKeyDown((u8)RGFWkey) && RGFW_BOOL(state), RGFW_BOOL(state));
 9036+
 9037+	/* [comment by Kala Telo (@kala-telo) and edited by Riley Mabb (@ColleagueRiley)]
 9038+		we send the event at the moment we receive it, and
 9039+		repeated key presses will be handled by RGFW_pollEvents
 9040+		if the compositor doesn't support proxy (seat?) version
 9041+		of at least 4, it won't initialize wl_repeat_info_rate,
 9042+		and by spec, rate of 0 means disabled, thus repeating
 9043+		keys are disabled by being zero-initialized
 9044+	*/
 9045+	RGFW->last_key = state ? key : 0;
 9046+	RGFW->last_key_time = time + (u32)_RGFW->wl_repeat_info_delay;
 9047+	if (state) {
 9048+		RGFW_wl_send_key_event(_RGFW->last_key);
 9049+	}
 9050+}
 9051+
 9052+static void RGFW_wl_keyboard_modifiers(void* data, struct wl_keyboard *keyboard, u32 serial, u32 mods_depressed, u32 mods_latched, u32 mods_locked, u32 group) {
 9053+	RGFW_UNUSED(keyboard); RGFW_UNUSED(serial); RGFW_UNUSED(time);
 9054+	RGFW_info* RGFW = (RGFW_info*)data;
 9055+	xkb_state_update_mask(RGFW->xkb_state, mods_depressed, mods_latched, mods_locked, 0, 0, group);
 9056+}
 9057+
 9058+static void RGFW_wl_keyboard_repeat_info(void* data, struct wl_keyboard *keyboard, i32 rate, i32 delay) {
 9059+	RGFW_UNUSED(data);
 9060+	RGFW_UNUSED(keyboard);
 9061+	_RGFW->wl_repeat_info_rate = rate;
 9062+	_RGFW->wl_repeat_info_delay = delay;
 9063+}
 9064+
 9065+static void RGFW_wl_seat_capabilities(void* data, struct wl_seat *seat, u32 capabilities) {
 9066+	RGFW_info* RGFW = (RGFW_info*)data;
 9067+    static struct wl_pointer_listener pointer_listener;
 9068+	RGFW_MEMZERO(&pointer_listener, sizeof(pointer_listener));
 9069+	pointer_listener.enter = &RGFW_wl_pointer_enter;
 9070+	pointer_listener.leave = &RGFW_wl_pointer_leave;
 9071+	pointer_listener.motion = &RGFW_wl_pointer_motion;
 9072+	pointer_listener.button = &RGFW_wl_pointer_button;
 9073+	pointer_listener.axis = &RGFW_wl_pointer_axis;
 9074+
 9075+	static struct wl_keyboard_listener keyboard_listener;
 9076+	RGFW_MEMZERO(&keyboard_listener, sizeof(keyboard_listener));
 9077+	keyboard_listener.keymap = &RGFW_wl_keyboard_keymap;
 9078+	keyboard_listener.enter = &RGFW_wl_keyboard_enter;
 9079+	keyboard_listener.leave = &RGFW_wl_keyboard_leave;
 9080+	keyboard_listener.key = &RGFW_wl_keyboard_key;
 9081+	keyboard_listener.modifiers = &RGFW_wl_keyboard_modifiers;
 9082+	keyboard_listener.repeat_info = &RGFW_wl_keyboard_repeat_info;
 9083+
 9084+    if ((capabilities & WL_SEAT_CAPABILITY_POINTER) && !RGFW->wl_pointer) {
 9085+		RGFW->wl_pointer = wl_seat_get_pointer(seat);
 9086+		wl_pointer_add_listener(RGFW->wl_pointer, &pointer_listener, RGFW);
 9087+	}
 9088+	if ((capabilities & WL_SEAT_CAPABILITY_KEYBOARD) && !RGFW->wl_keyboard) {
 9089+		RGFW->wl_keyboard = wl_seat_get_keyboard(seat);
 9090+		wl_keyboard_add_listener(RGFW->wl_keyboard, &keyboard_listener, RGFW);
 9091+	}
 9092+
 9093+    if (!(capabilities & WL_SEAT_CAPABILITY_POINTER) && RGFW->wl_pointer) {
 9094+		wl_pointer_destroy(RGFW->wl_pointer);
 9095+	}
 9096+	if (!(capabilities & WL_SEAT_CAPABILITY_KEYBOARD) && RGFW->wl_keyboard) {
 9097+		wl_keyboard_destroy(RGFW->wl_keyboard);
 9098+	}
 9099+}
 9100+
 9101+static void RGFW_wl_output_set_geometry(void *data, struct wl_output *wl_output,
 9102+			 i32 x, i32 y, i32 physical_width, i32 physical_height,
 9103+			 i32 subpixel, const char *make, const char *model, i32 transform) {
 9104+
 9105+	RGFW_monitor* monitor = &((RGFW_monitorNode*)data)->mon;
 9106+	monitor->x = x;
 9107+	monitor->y = y;
 9108+
 9109+	monitor->physW = (float)physical_width / 25.4f;
 9110+	monitor->physH = (float)physical_height / 25.4f;
 9111+
 9112+	RGFW_UNUSED(wl_output);
 9113+	RGFW_UNUSED(subpixel);
 9114+	RGFW_UNUSED(make);
 9115+	RGFW_UNUSED(model);
 9116+	RGFW_UNUSED(transform);
 9117+}
 9118+
 9119+static void RGFW_wl_output_handle_mode(void *data, struct wl_output *wl_output, u32 flags,
 9120+		     i32 width, i32 height, i32 refresh) {
 9121+
 9122+	RGFW_monitor* monitor = &((RGFW_monitorNode*)data)->mon;
 9123+
 9124+	RGFW_monitorMode mode;
 9125+	mode.w = width;
 9126+	mode.h = height;
 9127+	mode.refreshRate = (float)refresh / 1000.0f;
 9128+	mode.src = wl_output;
 9129+
 9130+	monitor->node->modeCount += 1;
 9131+
 9132+	RGFW_monitorMode* modes = (RGFW_monitorMode*)RGFW_ALLOC(monitor->node->modeCount * sizeof(RGFW_monitorMode));
 9133+
 9134+	if (monitor->node->modeCount > 1) {
 9135+		RGFW_monitor_getModesPtr(monitor, &modes);
 9136+		RGFW_FREE(monitor->node->modes);
 9137+	}
 9138+
 9139+	modes[monitor->node->modeCount - 1] = mode;
 9140+	monitor->node->modes = modes;
 9141+
 9142+	if (flags & WL_OUTPUT_MODE_CURRENT) {
 9143+		monitor->mode = mode;
 9144+	} else {
 9145+	}
 9146+}
 9147+
 9148+static void RGFW_wl_output_set_scale(void *data, struct wl_output *wl_output, i32 factor) {
 9149+	RGFW_UNUSED(wl_output);
 9150+	RGFW_monitor* mon = &((RGFW_monitorNode*)data)->mon;
 9151+
 9152+	mon->scaleX = (float)factor;
 9153+	mon->scaleY = (float)factor;
 9154+}
 9155+
 9156+static void RGFW_wl_output_set_name(void *data, struct wl_output *wl_output, const char *name) {
 9157+	RGFW_monitor* monitor = &((RGFW_monitorNode*)data)->mon;
 9158+
 9159+	RGFW_STRNCPY(monitor->name, name, sizeof(monitor->name) - 1);
 9160+	monitor->name[sizeof(monitor->name) - 1] = '\0';
 9161+
 9162+	RGFW_UNUSED(wl_output);
 9163+
 9164+}
 9165+
 9166+static void RGFW_xdg_output_logical_pos(void *data, struct zxdg_output_v1 *zxdg_output_v1, i32 x, i32 y) {
 9167+	RGFW_monitor* monitor = &((RGFW_monitorNode*)data)->mon;
 9168+	monitor->x = x;
 9169+	monitor->y = y;
 9170+	RGFW_UNUSED(zxdg_output_v1);
 9171+}
 9172+
 9173+static void RGFW_xdg_output_logical_size(void *data, struct zxdg_output_v1 *zxdg_output_v1, i32 width, i32 height) {
 9174+	RGFW_monitor* monitor = &((RGFW_monitorNode*)data)->mon;
 9175+
 9176+	float mon_float_width = (float) monitor->mode.w;
 9177+	float mon_float_height = (float) monitor->mode.h;
 9178+
 9179+	float scaleX = (mon_float_width / (float) width);
 9180+	float scaleY = (mon_float_height / (float) height);
 9181+	RGFW_UNUSED(scaleY);
 9182+
 9183+	float dpi = scaleX * 96.0f;
 9184+
 9185+	monitor->pixelRatio = dpi >= 192.0f ? 2.0f : 1.0f;
 9186+
 9187+	/* under xwayland the monitor changes w & h when compositor scales it */
 9188+	monitor->mode.w = width;
 9189+	monitor->mode.h = height;
 9190+	RGFW_UNUSED(zxdg_output_v1);
 9191+}
 9192+
 9193+
 9194+static void RGFW_wl_output_handle_done(void* data, struct wl_output* output) {
 9195+	RGFW_UNUSED(output);
 9196+
 9197+	RGFW_monitor* monitor = &((RGFW_monitorNode*)data)->mon;
 9198+
 9199+    if (monitor->physW <= 0 || monitor->physH <= 0) {
 9200+		monitor->physW = (i32) ((float)monitor->mode.w / 96.0f);
 9201+		monitor->physH = (i32) ((float)monitor->mode.h / 96.0f);
 9202+    }
 9203+
 9204+	if (((RGFW_monitorNode*)data)->disconnected == RGFW_FALSE) {
 9205+		return;
 9206+	}
 9207+
 9208+	((RGFW_monitorNode*)data)->disconnected = RGFW_TRUE;
 9209+
 9210+	RGFW_monitorCallback(_RGFW->root, monitor, RGFW_TRUE);
 9211+}
 9212+
 9213+static void RGFW_wl_create_outputs(struct wl_registry *const registry, u32 id) {
 9214+	struct wl_output *output = wl_registry_bind(registry, id, &wl_output_interface, wl_proxy_get_version((struct wl_proxy*)_RGFW->seat));
 9215+	RGFW_monitorNode* node;
 9216+	RGFW_monitor mon;
 9217+
 9218+	if (!output) return;
 9219+
 9220+	char RGFW_mon_default_name[10];
 9221+
 9222+	RGFW_SNPRINTF(RGFW_mon_default_name, sizeof(RGFW_mon_default_name), "monitor-%li", _RGFW->monitors.count);
 9223+	RGFW_STRNCPY(mon.name, RGFW_mon_default_name, sizeof(mon.name) - 1);
 9224+	mon.name[sizeof(mon.name) - 1] = '\0';
 9225+
 9226+	/* set in case compositor does not send one */
 9227+    /* or no xdg_output support */
 9228+	mon.scaleY = mon.scaleX = mon.pixelRatio = 1.0f;
 9229+
 9230+	node = RGFW_monitors_add(&mon);
 9231+	if (node == NULL) return;
 9232+
 9233+	node->modeCount = 0;
 9234+	node->disconnected = RGFW_TRUE;
 9235+	node->id = id;
 9236+	node->output = output;
 9237+
 9238+	static const struct wl_output_listener wl_output_listener = {
 9239+			.geometry = RGFW_wl_output_set_geometry,
 9240+			.mode = RGFW_wl_output_handle_mode,
 9241+			.done = RGFW_wl_output_handle_done,
 9242+			.scale = RGFW_wl_output_set_scale,
 9243+			.name = RGFW_wl_output_set_name,
 9244+			.description = (void (*)(void *, struct wl_output *, const char *))&RGFW_doNothing
 9245+	};
 9246+
 9247+	/* the wl_output will have a reference to the node */
 9248+	wl_output_set_user_data(output, node);
 9249+
 9250+	/* pass the monitor so we can access it in the callback functions */
 9251+	wl_output_add_listener(output, &wl_output_listener, node);
 9252+
 9253+	if (!_RGFW->xdg_output_manager)
 9254+		return; /* compositor does not support it */
 9255+
 9256+	static const struct zxdg_output_v1_listener xdg_output_listener = {
 9257+		.name = (void (*)(void *,struct zxdg_output_v1 *, const char *))&RGFW_doNothing,
 9258+		.done = (void (*)(void *,struct zxdg_output_v1 *))&RGFW_doNothing,
 9259+		.description = (void (*)(void *,struct zxdg_output_v1 *, const char *))&RGFW_doNothing,
 9260+		.logical_position = RGFW_xdg_output_logical_pos,
 9261+		.logical_size = RGFW_xdg_output_logical_size
 9262+	};
 9263+
 9264+	node->xdg_output = zxdg_output_manager_v1_get_xdg_output(_RGFW->xdg_output_manager, node->output);
 9265+	zxdg_output_v1_add_listener(node->xdg_output, &xdg_output_listener, node);
 9266+}
 9267+
 9268+static void RGFW_wl_surface_enter(void *data, struct wl_surface *wl_surface, struct wl_output *output) {
 9269+	RGFW_UNUSED(wl_surface);
 9270+
 9271+	RGFW_window* win = (RGFW_window*)data;
 9272+	RGFW_monitorNode* node = wl_output_get_user_data(output);
 9273+	if (node == NULL) return;
 9274+
 9275+	win->src.active_monitor = node;
 9276+}
 9277+
 9278+static void RGFW_wl_data_source_send(void *data, struct wl_data_source *wl_data_source, const char *mime_type, i32 fd) {
 9279+	RGFW_UNUSED(data); RGFW_UNUSED(wl_data_source);
 9280+
 9281+	// a client can accept our clipboard
 9282+	if (RGFW_STRNCMP(mime_type, "text/plain;charset=utf-8", 25) == 0) {
 9283+		// do not write \0
 9284+		write(fd, _RGFW->clipboard, _RGFW->clipboard_len - 1);
 9285+	}
 9286+
 9287+	close(fd);
 9288+}
 9289+
 9290+static void RGFW_wl_data_source_cancelled(void *data, struct wl_data_source *wl_data_source) {
 9291+
 9292+	RGFW_info* RGFW = (RGFW_info*)data;
 9293+
 9294+	if (RGFW->kbOwner->src.data_source == wl_data_source) {
 9295+		RGFW->kbOwner->src.data_source = NULL;
 9296+	}
 9297+
 9298+	wl_data_source_destroy(wl_data_source);
 9299+
 9300+}
 9301+
 9302+static void RGFW_wl_data_device_data_offer(void *data, struct wl_data_device *wl_data_device, struct wl_data_offer *wl_data_offer) {
 9303+
 9304+	RGFW_UNUSED(data); RGFW_UNUSED(wl_data_device);
 9305+	static const struct wl_data_offer_listener wl_data_offer_listener = {
 9306+		.offer = (void (*)(void *data, struct wl_data_offer *wl_data_offer, const char *))RGFW_doNothing,
 9307+		.source_actions = (void (*)(void *data, struct wl_data_offer *wl_data_offer, u32 dnd_action))RGFW_doNothing,
 9308+		.action = (void (*)(void *data, struct wl_data_offer *wl_data_offer, u32 dnd_action))RGFW_doNothing
 9309+	};
 9310+	wl_data_offer_add_listener(wl_data_offer, &wl_data_offer_listener, NULL);
 9311+}
 9312+
 9313+static void RGFW_wl_data_device_selection(void *data, struct wl_data_device *wl_data_device, struct wl_data_offer *wl_data_offer) {
 9314+	RGFW_UNUSED(data); RGFW_UNUSED(wl_data_device);
 9315+	/* Clipboard is empty */
 9316+	if (wl_data_offer == NULL) {
 9317+		return;
 9318+	}
 9319+
 9320+	int pfds[2];
 9321+	pipe(pfds);
 9322+
 9323+	wl_data_offer_receive(wl_data_offer, "text/plain;charset=utf-8", pfds[1]);
 9324+	close(pfds[1]);
 9325+
 9326+	wl_display_roundtrip(_RGFW->wl_display);
 9327+
 9328+	char buf[1024];
 9329+
 9330+	ssize_t n = read(pfds[0], buf, sizeof(buf));
 9331+
 9332+	_RGFW->clipboard = (char*)RGFW_ALLOC((size_t)n);
 9333+	RGFW_ASSERT(_RGFW->clipboard != NULL);
 9334+	RGFW_STRNCPY(_RGFW->clipboard, buf, (size_t)n);
 9335+
 9336+	_RGFW->clipboard_len = (size_t)n + 1;
 9337+
 9338+	close(pfds[0]);
 9339+
 9340+	wl_data_offer_destroy(wl_data_offer);
 9341+
 9342+}
 9343+
 9344+static void RGFW_wl_global_registry_handler(void* data, struct wl_registry *registry, u32 id, const char *interface, u32 version) {
 9345+
 9346+    static struct wl_seat_listener seat_listener = {&RGFW_wl_seat_capabilities, (void (*)(void *, struct wl_seat *, const char *))&RGFW_doNothing};
 9347+    static const struct wl_shm_listener shm_listener = { .format = RGFW_wl_shm_format_handler };
 9348+
 9349+    RGFW_info* RGFW = (RGFW_info*)data;
 9350+    RGFW_UNUSED(version);
 9351+
 9352+    if (RGFW_STRNCMP(interface, "wl_compositor", 16) == 0) {
 9353+		RGFW->compositor = wl_registry_bind(registry, id, &wl_compositor_interface, 4);
 9354+	} else if (RGFW_STRNCMP(interface, "xdg_wm_base", 12) == 0) {
 9355+		RGFW->xdg_wm_base = wl_registry_bind(registry, id, &xdg_wm_base_interface, 1);
 9356+	} else if (RGFW_STRNCMP(interface, zxdg_decoration_manager_v1_interface.name, 255) == 0) {
 9357+		RGFW->decoration_manager = wl_registry_bind(registry, id, &zxdg_decoration_manager_v1_interface, 1);
 9358+    } else if (RGFW_STRNCMP(interface, zwp_pointer_constraints_v1_interface.name, 255) == 0) {
 9359+		RGFW->constraint_manager = wl_registry_bind(registry, id, &zwp_pointer_constraints_v1_interface, 1);
 9360+    } else if (RGFW_STRNCMP(interface, zwp_relative_pointer_manager_v1_interface.name, 255) == 0) {
 9361+		RGFW->relative_pointer_manager = wl_registry_bind(registry, id, &zwp_relative_pointer_manager_v1_interface, 1);
 9362+	} else if (RGFW_STRNCMP(interface, xdg_toplevel_icon_manager_v1_interface.name, 255) == 0) {
 9363+		RGFW->icon_manager = wl_registry_bind(registry, id, &xdg_toplevel_icon_manager_v1_interface, 1);
 9364+    } else if (RGFW_STRNCMP(interface, "wl_shm", 7) == 0) {
 9365+        RGFW->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
 9366+        wl_shm_add_listener(RGFW->shm, &shm_listener, RGFW);
 9367+	} else if (RGFW_STRNCMP(interface,"wl_seat", 8) == 0) {
 9368+		RGFW->seat = wl_registry_bind(registry, id, &wl_seat_interface, version < 4 ? 3 : 4);
 9369+		wl_seat_add_listener(RGFW->seat, &seat_listener, RGFW);
 9370+	} else if (RGFW_STRNCMP(interface, zxdg_output_manager_v1_interface.name, 255) == 0) {
 9371+		RGFW->xdg_output_manager = wl_registry_bind(registry, id, &zxdg_output_manager_v1_interface, 1);
 9372+	} else if (RGFW_STRNCMP(interface,"wl_output", 10) == 0) {
 9373+		RGFW_wl_create_outputs(registry, id);
 9374+	} else if (RGFW_STRNCMP(interface, wp_pointer_warp_v1_interface.name, 255) == 0) {
 9375+		RGFW->wp_pointer_warp = wl_registry_bind(registry, id, &wp_pointer_warp_v1_interface, 1);
 9376+	} else if (RGFW_STRNCMP(interface,"wl_data_device_manager", 23) == 0) {
 9377+		RGFW->data_device_manager = wl_registry_bind(registry, id, &wl_data_device_manager_interface, 1);
 9378+	}
 9379+}
 9380+
 9381+static void RGFW_wl_global_registry_remove(void* data, struct wl_registry *registry, u32 id) {
 9382+	RGFW_UNUSED(data); RGFW_UNUSED(registry);
 9383+	RGFW_info* RGFW = (RGFW_info*)data;
 9384+	RGFW_monitorNode* prev = RGFW->monitors.list.head;
 9385+	RGFW_monitorNode* node = NULL;
 9386+	if (prev == NULL) return;
 9387+
 9388+	if (prev->id != id) {
 9389+		/* find the first node that has a matching id */
 9390+		while(prev->next != NULL && prev->next->id != id) {
 9391+			prev = prev->next;
 9392+		}
 9393+
 9394+		if (prev->next == NULL) return;
 9395+		node = prev->next;
 9396+	} else {
 9397+		node = prev;
 9398+	}
 9399+
 9400+	if (node->output) {
 9401+		wl_output_destroy(node->output);
 9402+	}
 9403+
 9404+	if (node->xdg_output) {
 9405+		zxdg_output_v1_destroy(node->xdg_output);
 9406+	}
 9407+
 9408+	if (node->modeCount) {
 9409+		RGFW_FREE(node->modes);
 9410+		node->modeCount = 0;
 9411+	}
 9412+
 9413+	RGFW_monitorCallback(_RGFW->root, &node->mon, RGFW_FALSE);
 9414+	RGFW_monitors_remove(node, prev);
 9415+}
 9416+
 9417+static void RGFW_wl_randname(char *buf) {
 9418+	struct timespec ts;
 9419+	clock_gettime(CLOCK_REALTIME, &ts);
 9420+	long r = ts.tv_nsec;
 9421+
 9422+    int i;
 9423+    for (i = 0; i < 6; i++) {
 9424+		buf[i] = (char)('A'+(r&15)+(r&16)*2);
 9425+		r >>= 5;
 9426+	}
 9427+}
 9428+
 9429+static int RGFW_wl_anonymous_shm_open(void) {
 9430+	char name[] = "/RGFW-wayland-XXXXXX";
 9431+	int retries = 100;
 9432+
 9433+	do {
 9434+		RGFW_wl_randname(name + RGFW_unix_stringlen(name) - 6);
 9435+
 9436+		--retries;
 9437+		/* shm_open guarantees that O_CLOEXEC is set */
 9438+		int fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL, 0600);
 9439+		if (fd >= 0) {
 9440+			shm_unlink(name);
 9441+			return fd;
 9442+		}
 9443+	} while (retries > 0 && errno == EEXIST);
 9444+
 9445+	return -1;
 9446+}
 9447+
 9448+static int RGFW_wl_create_shm_file(off_t size) {
 9449+	int fd = RGFW_wl_anonymous_shm_open();
 9450+	if (fd < 0) {
 9451+		return fd;
 9452+	}
 9453+
 9454+	if (ftruncate(fd, size) < 0) {
 9455+		close(fd);
 9456+		return -1;
 9457+	}
 9458+
 9459+	return fd;
 9460+}
 9461+
 9462+i32 RGFW_initPlatform_Wayland(void) {
 9463+	_RGFW->wl_display = wl_display_connect(NULL);
 9464+	if (_RGFW->wl_display == NULL) {
 9465+		RGFW_debugCallback(RGFW_typeError, RGFW_errWayland,  "Failed to load Wayland display");
 9466+		return -1;
 9467+	}
 9468+
 9469+	_RGFW->compositor = NULL;
 9470+	static const struct wl_registry_listener registry_listener = {
 9471+		.global = RGFW_wl_global_registry_handler,
 9472+		.global_remove = RGFW_wl_global_registry_remove,
 9473+	};
 9474+
 9475+	_RGFW->registry = wl_display_get_registry(_RGFW->wl_display);
 9476+	wl_registry_add_listener(_RGFW->registry, &registry_listener, _RGFW);
 9477+
 9478+	wl_display_roundtrip(_RGFW->wl_display); /* bind to globals */
 9479+
 9480+	if (_RGFW->compositor == NULL) {
 9481+		RGFW_debugCallback(RGFW_typeError, RGFW_errWayland, "Can't find compositor.");
 9482+		return 1;
 9483+	}
 9484+
 9485+	if (_RGFW->wl_cursor_theme == NULL) {
 9486+		_RGFW->wl_cursor_theme = wl_cursor_theme_load(NULL, 24, _RGFW->shm);
 9487+		_RGFW->cursor_surface = wl_compositor_create_surface(_RGFW->compositor);
 9488+	}
 9489+
 9490+	 u8 RGFW_blk[] = { 0, 0, 0, 0 };
 9491+	_RGFW->hiddenMouse = RGFW_createMouse(RGFW_blk, 1, 1, RGFW_formatRGBA8);
 9492+
 9493+	static const struct xdg_wm_base_listener xdg_wm_base_listener = {
 9494+		.ping = RGFW_wl_xdg_wm_base_ping_handler,
 9495+	};
 9496+
 9497+	xdg_wm_base_add_listener(_RGFW->xdg_wm_base, &xdg_wm_base_listener, NULL);
 9498+
 9499+	_RGFW->xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
 9500+
 9501+	static const struct wl_data_device_listener wl_data_device_listener = {
 9502+		.data_offer = RGFW_wl_data_device_data_offer,
 9503+		.enter = (void (*)(void *, struct wl_data_device *, u32, struct wl_surface*, wl_fixed_t, wl_fixed_t, struct wl_data_offer *))&RGFW_doNothing,
 9504+		.leave = (void (*)(void *, struct wl_data_device *))&RGFW_doNothing,
 9505+		.motion = (void (*)(void *, struct wl_data_device *, u32, wl_fixed_t, wl_fixed_t))&RGFW_doNothing,
 9506+		.drop = (void (*)(void *, struct wl_data_device *))&RGFW_doNothing,
 9507+		.selection = RGFW_wl_data_device_selection
 9508+	};
 9509+
 9510+	if (_RGFW->seat && _RGFW->data_device_manager) {
 9511+		_RGFW->data_device = wl_data_device_manager_get_data_device(_RGFW->data_device_manager, _RGFW->seat);
 9512+		wl_data_device_add_listener(_RGFW->data_device, &wl_data_device_listener, NULL);
 9513+	}
 9514+
 9515+	return 0;
 9516+}
 9517+
 9518+void RGFW_deinitPlatform_Wayland(void) {
 9519+	if (_RGFW->clipboard) {
 9520+		RGFW_FREE(_RGFW->clipboard);
 9521+		_RGFW->clipboard = NULL;
 9522+	}
 9523+
 9524+    if (_RGFW->wl_pointer) {
 9525+		wl_pointer_destroy(_RGFW->wl_pointer);
 9526+	}
 9527+	if (_RGFW->wl_keyboard) {
 9528+		wl_keyboard_destroy(_RGFW->wl_keyboard);
 9529+	}
 9530+
 9531+	wl_registry_destroy(_RGFW->registry);
 9532+	if (_RGFW->decoration_manager != NULL)
 9533+		zxdg_decoration_manager_v1_destroy(_RGFW->decoration_manager);
 9534+	if (_RGFW->relative_pointer_manager != NULL) {
 9535+		zwp_relative_pointer_manager_v1_destroy(_RGFW->relative_pointer_manager);
 9536+	}
 9537+
 9538+	if (_RGFW->relative_pointer) {
 9539+		zwp_relative_pointer_v1_destroy(_RGFW->relative_pointer);
 9540+	}
 9541+
 9542+	if (_RGFW->constraint_manager != NULL) {
 9543+		zwp_pointer_constraints_v1_destroy(_RGFW->constraint_manager);
 9544+	}
 9545+
 9546+	if (_RGFW->xdg_output_manager != NULL)
 9547+	if (_RGFW->icon_manager != NULL) {
 9548+		xdg_toplevel_icon_manager_v1_destroy(_RGFW->icon_manager);
 9549+	}
 9550+
 9551+	if (_RGFW->xdg_output_manager) {
 9552+		zxdg_output_manager_v1_destroy(_RGFW->xdg_output_manager);
 9553+	}
 9554+
 9555+	if (_RGFW->data_device_manager) {
 9556+		wl_data_device_manager_destroy(_RGFW->data_device_manager);
 9557+	}
 9558+
 9559+	if (_RGFW->data_device) {
 9560+		wl_data_device_destroy(_RGFW->data_device);
 9561+	}
 9562+
 9563+	if (_RGFW->wl_cursor_theme != NULL) {
 9564+		wl_cursor_theme_destroy(_RGFW->wl_cursor_theme);
 9565+	}
 9566+
 9567+	if (_RGFW->wp_pointer_warp != NULL) {
 9568+		wp_pointer_warp_v1_destroy(_RGFW->wp_pointer_warp);
 9569+	}
 9570+
 9571+	RGFW_freeMouse(_RGFW->hiddenMouse);
 9572+
 9573+	RGFW_monitorNode* node = _RGFW->monitors.list.head;
 9574+
 9575+	while (node != NULL) {
 9576+		if (node->output) {
 9577+			wl_output_destroy(node->output);
 9578+		}
 9579+
 9580+		if (node->xdg_output) {
 9581+			zxdg_output_v1_destroy(node->xdg_output);
 9582+		}
 9583+
 9584+		_RGFW->monitors.count -= 1;
 9585+		node = node->next;
 9586+
 9587+	}
 9588+
 9589+	wl_surface_destroy(_RGFW->cursor_surface);
 9590+	wl_shm_destroy(_RGFW->shm);
 9591+	wl_seat_release(_RGFW->seat);
 9592+	xdg_wm_base_destroy(_RGFW->xdg_wm_base);
 9593+	wl_compositor_destroy(_RGFW->compositor);
 9594+	wl_display_disconnect(_RGFW->wl_display);
 9595+}
 9596+
 9597+RGFW_format RGFW_FUNC(RGFW_nativeFormat)(void) { return RGFW_formatBGRA8; }
 9598+
 9599+RGFW_bool RGFW_FUNC(RGFW_createSurfacePtr) (u8* data, i32 w, i32 h, RGFW_format format, RGFW_surface* surface) {
 9600+	RGFW_ASSERT(surface != NULL);
 9601+	surface->data = data;
 9602+	surface->w = w;
 9603+	surface->h = h;
 9604+	surface->format = format;
 9605+	RGFW_debugCallback(RGFW_typeInfo, RGFW_infoBuffer,  "Creating a 4 channel buffer");
 9606+
 9607+	u32 size = (u32)(surface->w * surface->h * 4);
 9608+	int fd = RGFW_wl_create_shm_file(size);
 9609+	if (fd < 0) {
 9610+		RGFW_debugCallback(RGFW_typeError, RGFW_errBuffer, "Failed to create a buffer.");
 9611+		return RGFW_FALSE;
 9612+	}
 9613+
 9614+	surface->native.pool = wl_shm_create_pool(_RGFW->shm, fd, (i32)size);
 9615+
 9616+	surface->native.buffer = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
 9617+	if (surface->native.buffer == MAP_FAILED) {
 9618+		RGFW_debugCallback(RGFW_typeError, RGFW_errBuffer, "mmap failed.");
 9619+		return RGFW_FALSE;
 9620+	}
 9621+
 9622+	surface->native.fd = fd;
 9623+	surface->native.format = RGFW_formatBGRA8;
 9624+	return RGFW_TRUE;
 9625+}
 9626+
 9627+void RGFW_FUNC(RGFW_window_blitSurface) (RGFW_window* win, RGFW_surface* surface) {
 9628+	RGFW_ASSERT(surface != NULL);
 9629+
 9630+	surface->native.wl_buffer = wl_shm_pool_create_buffer(surface->native.pool, 0, RGFW_MIN(win->w, surface->w), RGFW_MIN(win->h, surface->h), (i32)surface->w * 4, WL_SHM_FORMAT_ARGB8888);
 9631+	RGFW_copyImageData(surface->native.buffer, surface->w, RGFW_MIN(win->h, surface->h), surface->native.format, surface->data, surface->format, surface->convertFunc);
 9632+
 9633+	wl_surface_attach(win->src.surface, surface->native.wl_buffer, 0, 0);
 9634+	wl_surface_damage(win->src.surface, 0, 0, RGFW_MIN(win->w, surface->w), RGFW_MIN(win->h, surface->h));
 9635+	wl_surface_commit(win->src.surface);
 9636+
 9637+	wl_buffer_destroy(surface->native.wl_buffer);
 9638+
 9639+	surface->native.wl_buffer = NULL;
 9640+}
 9641+
 9642+void RGFW_FUNC(RGFW_surface_freePtr) (RGFW_surface* surface) {
 9643+	RGFW_ASSERT(surface != NULL);
 9644+
 9645+	if (surface->native.pool) wl_shm_pool_destroy(surface->native.pool);
 9646+	if (surface->native.fd) close(surface->native.fd);
 9647+	if (surface->native.buffer) munmap(surface->native.buffer, (size_t)(surface->w * surface->h * 4));
 9648+}
 9649+
 9650+void RGFW_FUNC(RGFW_window_setBorder) (RGFW_window* win, RGFW_bool border) {
 9651+	RGFW_setBit(&win->internal.flags, RGFW_windowNoBorder, !border);
 9652+
 9653+	/* for now just toggle between SSD & CSD depending on the bool */
 9654+	if (_RGFW->decoration_manager != NULL) {
 9655+		zxdg_toplevel_decoration_v1_set_mode(win->src.decoration, (border ? ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE : ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE));
 9656+	}
 9657+}
 9658+
 9659+void RGFW_FUNC(RGFW_window_setRawMouseModePlatform) (RGFW_window* win, RGFW_bool state) {
 9660+	RGFW_ASSERT(win);
 9661+	if (_RGFW->relative_pointer_manager == NULL) return;
 9662+
 9663+	if (state == RGFW_FALSE) {
 9664+		if (_RGFW->relative_pointer != NULL)
 9665+			zwp_relative_pointer_v1_destroy(_RGFW->relative_pointer);
 9666+		_RGFW->relative_pointer = NULL;
 9667+		return;
 9668+	}
 9669+
 9670+	if (_RGFW->relative_pointer != NULL) return;
 9671+
 9672+	_RGFW->relative_pointer = zwp_relative_pointer_manager_v1_get_relative_pointer(_RGFW->relative_pointer_manager, _RGFW->wl_pointer);
 9673+
 9674+	static const struct zwp_relative_pointer_v1_listener relative_motion_listener = {
 9675+		.relative_motion = RGFW_wl_relative_pointer_motion
 9676+	};
 9677+
 9678+	zwp_relative_pointer_v1_add_listener(_RGFW->relative_pointer, &relative_motion_listener, _RGFW);
 9679+}
 9680+
 9681+void RGFW_FUNC(RGFW_window_captureMousePlatform) (RGFW_window* win, RGFW_bool state) {
 9682+	RGFW_ASSERT(win);
 9683+
 9684+	/* compositor has no support or window already is locked do nothing */
 9685+	if (_RGFW->constraint_manager == NULL) return;
 9686+
 9687+	if (state == RGFW_FALSE) {
 9688+		if (win->src.locked_pointer != NULL)
 9689+			zwp_locked_pointer_v1_destroy(win->src.locked_pointer);
 9690+		win->src.locked_pointer = NULL;
 9691+		return;
 9692+	}
 9693+
 9694+
 9695+	if (win->src.locked_pointer != NULL) return;
 9696+	win->src.locked_pointer = zwp_pointer_constraints_v1_lock_pointer(_RGFW->constraint_manager, win->src.surface, _RGFW->wl_pointer, NULL, ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
 9697+
 9698+	static const struct zwp_locked_pointer_v1_listener locked_listener = {
 9699+		.locked = RGFW_wl_pointer_locked,
 9700+		.unlocked = (void (*)(void *, struct zwp_locked_pointer_v1 *))RGFW_doNothing
 9701+	};
 9702+
 9703+	zwp_locked_pointer_v1_add_listener(win->src.locked_pointer, &locked_listener, _RGFW);
 9704+}
 9705+
 9706+RGFW_window* RGFW_FUNC(RGFW_createWindowPlatform) (const char* name, RGFW_windowFlags flags, RGFW_window* win) {
 9707+	RGFW_debugCallback(RGFW_typeWarning, RGFW_warningWayland, "RGFW Wayland support is experimental");
 9708+
 9709+	static const struct xdg_surface_listener xdg_surface_listener = {
 9710+		.configure = RGFW_wl_xdg_surface_configure_handler,
 9711+	};
 9712+
 9713+	static const struct wl_surface_listener wl_surface_listener = {
 9714+		.enter = RGFW_wl_surface_enter,
 9715+		.leave = (void (*)(void *, struct wl_surface *, struct wl_output *))&RGFW_doNothing,
 9716+		.preferred_buffer_scale = (void (*)(void *, struct wl_surface *, i32))&RGFW_doNothing,
 9717+		.preferred_buffer_transform = (void (*)(void *, struct wl_surface *, u32))&RGFW_doNothing
 9718+	};
 9719+
 9720+	win->src.surface = wl_compositor_create_surface(_RGFW->compositor);
 9721+	wl_surface_add_listener(win->src.surface, &wl_surface_listener, win);
 9722+
 9723+	/* create a surface for a custom cursor */
 9724+	win->src.custom_cursor_surface = wl_compositor_create_surface(_RGFW->compositor);
 9725+
 9726+	win->src.xdg_surface = xdg_wm_base_get_xdg_surface(_RGFW->xdg_wm_base, win->src.surface);
 9727+	xdg_surface_add_listener(win->src.xdg_surface, &xdg_surface_listener, win);
 9728+
 9729+	xdg_wm_base_set_user_data(_RGFW->xdg_wm_base, win);
 9730+
 9731+	win->src.xdg_toplevel = xdg_surface_get_toplevel(win->src.xdg_surface);
 9732+
 9733+	if (_RGFW->className == NULL)
 9734+		_RGFW->className = (char*)name;
 9735+
 9736+	xdg_toplevel_set_app_id(win->src.xdg_toplevel, name);
 9737+
 9738+	xdg_surface_set_window_geometry(win->src.xdg_surface, 0, 0, win->w, win->h);
 9739+
 9740+	if (!(win->internal.flags & RGFW_windowTransparent)) { /* no transparency */
 9741+		RGFW_wl_setOpaque(win);
 9742+	}
 9743+
 9744+	static const struct xdg_toplevel_listener xdg_toplevel_listener = {
 9745+		.configure = RGFW_wl_xdg_toplevel_configure_handler,
 9746+		.close = RGFW_wl_xdg_toplevel_close_handler,
 9747+	};
 9748+
 9749+	xdg_toplevel_add_listener(win->src.xdg_toplevel, &xdg_toplevel_listener, win);
 9750+
 9751+	/* compositor supports both SSD & CSD
 9752+	   So choose accordingly
 9753+	 */
 9754+	if (_RGFW->decoration_manager) {
 9755+		u32 decoration_mode = ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE;
 9756+		win->src.decoration = zxdg_decoration_manager_v1_get_toplevel_decoration(
 9757+			_RGFW->decoration_manager, win->src.xdg_toplevel);
 9758+
 9759+		static const struct zxdg_toplevel_decoration_v1_listener xdg_decoration_listener = {
 9760+			.configure = RGFW_wl_xdg_decoration_configure_handler
 9761+		};
 9762+
 9763+		zxdg_toplevel_decoration_v1_add_listener(win->src.decoration, &xdg_decoration_listener, win);
 9764+
 9765+		/* we want no decorations */
 9766+		if ((flags & RGFW_windowNoBorder)) {
 9767+			decoration_mode = ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE;
 9768+		}
 9769+
 9770+		zxdg_toplevel_decoration_v1_set_mode(win->src.decoration, decoration_mode);
 9771+
 9772+        /* no xdg_decoration support */
 9773+	} else if (!(flags & RGFW_windowNoBorder)) {
 9774+		/* TODO, some fallback */
 9775+		#ifdef RGFW_LIBDECOR
 9776+			static struct libdecor_interface interface = {
 9777+				.error = NULL,
 9778+			};
 9779+
 9780+			static struct libdecor_frame_interface frameInterface = {0}; /*= {
 9781+				RGFW_wl_handle_configure,
 9782+				RGFW_wl_handle_close,
 9783+				RGFW_wl_handle_commit,
 9784+				RGFW_wl_handle_dismiss_popup,
 9785+			};*/
 9786+
 9787+			win->src.decorContext = libdecor_new(_RGFW->wl_display, &interface);
 9788+			if (win->src.decorContext) {
 9789+				struct libdecor_frame *frame = libdecor_decorate(win->src.decorContext, win->src.surface, &frameInterface, win);
 9790+				if (!frame) {
 9791+					libdecor_unref(win->src.decorContext);
 9792+					win->src.decorContext = NULL;
 9793+				} else {
 9794+					libdecor_frame_set_app_id(frame, "my-libdecor-app");
 9795+					libdecor_frame_set_title(frame, "My Libdecor Window");
 9796+				}
 9797+			}
 9798+		#endif
 9799+	}
 9800+
 9801+	if (_RGFW->icon_manager != NULL) {
 9802+		/* set the default wayland icon */
 9803+		xdg_toplevel_icon_manager_v1_set_icon(_RGFW->icon_manager, win->src.xdg_toplevel, NULL);
 9804+	}
 9805+
 9806+	wl_surface_commit(win->src.surface);
 9807+
 9808+	while (win->src.configured == RGFW_FALSE) {
 9809+		wl_display_dispatch(_RGFW->wl_display);
 9810+	}
 9811+
 9812+	RGFW_UNUSED(name);
 9813+
 9814+	return win;
 9815+}
 9816+
 9817+RGFW_bool RGFW_FUNC(RGFW_getGlobalMouse) (i32* x, i32* y) {
 9818+	RGFW_init();
 9819+	if (x) *x = 0;
 9820+	if (y) *y = 0;
 9821+	return RGFW_FALSE;
 9822+}
 9823+
 9824+RGFW_key RGFW_FUNC(RGFW_physicalToMappedKey)(RGFW_key key) {
 9825+    u32 keycode = RGFW_rgfwToApiKey(key);
 9826+	xkb_keycode_t kc = keycode + 8;
 9827+    xkb_keysym_t sym = xkb_state_key_get_one_sym(_RGFW->xkb_state, kc);
 9828+    if (sym < 256) {
 9829+        return (RGFW_key)sym;
 9830+    }
 9831+
 9832+    switch (sym) {
 9833+        case XKB_KEY_F1:  return RGFW_keyF1;
 9834+        case XKB_KEY_F2:  return RGFW_keyF2;
 9835+        case XKB_KEY_F3:  return RGFW_keyF3;
 9836+        case XKB_KEY_F4:  return RGFW_keyF4;
 9837+        case XKB_KEY_F5:  return RGFW_keyF5;
 9838+        case XKB_KEY_F6:  return RGFW_keyF6;
 9839+        case XKB_KEY_F7:  return RGFW_keyF7;
 9840+        case XKB_KEY_F8:  return RGFW_keyF8;
 9841+        case XKB_KEY_F9:  return RGFW_keyF9;
 9842+        case XKB_KEY_F10: return RGFW_keyF10;
 9843+        case XKB_KEY_F11: return RGFW_keyF11;
 9844+        case XKB_KEY_F12: return RGFW_keyF12;
 9845+        case XKB_KEY_F13: return RGFW_keyF13;
 9846+        case XKB_KEY_F14: return RGFW_keyF14;
 9847+        case XKB_KEY_F15: return RGFW_keyF15;
 9848+        case XKB_KEY_F16: return RGFW_keyF16;
 9849+        case XKB_KEY_F17: return RGFW_keyF17;
 9850+        case XKB_KEY_F18: return RGFW_keyF18;
 9851+        case XKB_KEY_F19: return RGFW_keyF19;
 9852+        case XKB_KEY_F20: return RGFW_keyF20;
 9853+        case XKB_KEY_F21: return RGFW_keyF21;
 9854+        case XKB_KEY_F22: return RGFW_keyF22;
 9855+        case XKB_KEY_F23: return RGFW_keyF23;
 9856+        case XKB_KEY_F24: return RGFW_keyF24;
 9857+        case XKB_KEY_F25: return RGFW_keyF25;
 9858+        case XKB_KEY_Shift_L:   return RGFW_keyShiftL;
 9859+        case XKB_KEY_Shift_R:   return RGFW_keyShiftR;
 9860+        case XKB_KEY_Control_L: return RGFW_keyControlL;
 9861+        case XKB_KEY_Control_R: return RGFW_keyControlR;
 9862+        case XKB_KEY_Alt_L:     return RGFW_keyAltL;
 9863+        case XKB_KEY_Alt_R:     return RGFW_keyAltR;
 9864+        case XKB_KEY_Super_L:   return RGFW_keySuperL;
 9865+        case XKB_KEY_Super_R:   return RGFW_keySuperR;
 9866+        case XKB_KEY_Caps_Lock: return RGFW_keyCapsLock;
 9867+        case XKB_KEY_Num_Lock:  return RGFW_keyNumLock;
 9868+        case XKB_KEY_Scroll_Lock:return RGFW_keyScrollLock;
 9869+        case XKB_KEY_Up:        return RGFW_keyUp;
 9870+        case XKB_KEY_Down:      return RGFW_keyDown;
 9871+        case XKB_KEY_Left:      return RGFW_keyLeft;
 9872+        case XKB_KEY_Right:     return RGFW_keyRight;
 9873+        case XKB_KEY_Home:      return RGFW_keyHome;
 9874+        case XKB_KEY_End:       return RGFW_keyEnd;
 9875+        case XKB_KEY_Page_Up:   return RGFW_keyPageUp;
 9876+        case XKB_KEY_Page_Down: return RGFW_keyPageDown;
 9877+        case XKB_KEY_Insert:    return RGFW_keyInsert;
 9878+        case XKB_KEY_Menu:      return RGFW_keyMenu;
 9879+        case XKB_KEY_KP_Add:      return RGFW_keyPadPlus;
 9880+        case XKB_KEY_KP_Subtract: return RGFW_keyPadMinus;
 9881+        case XKB_KEY_KP_Multiply: return RGFW_keyPadMultiply;
 9882+        case XKB_KEY_KP_Divide:   return RGFW_keyPadSlash;
 9883+        case XKB_KEY_KP_Equal:    return RGFW_keyPadEqual;
 9884+        case XKB_KEY_KP_Enter:    return RGFW_keyPadReturn;
 9885+        case XKB_KEY_KP_Decimal:  return RGFW_keyPadPeriod;
 9886+        case XKB_KEY_KP_0: return RGFW_keyPad0;
 9887+        case XKB_KEY_KP_1: return RGFW_keyPad1;
 9888+        case XKB_KEY_KP_2: return RGFW_keyPad2;
 9889+        case XKB_KEY_KP_3: return RGFW_keyPad3;
 9890+        case XKB_KEY_KP_4: return RGFW_keyPad4;
 9891+        case XKB_KEY_KP_5: return RGFW_keyPad5;
 9892+        case XKB_KEY_KP_6: return RGFW_keyPad6;
 9893+        case XKB_KEY_KP_7: return RGFW_keyPad7;
 9894+        case XKB_KEY_KP_8: return RGFW_keyPad8;
 9895+        case XKB_KEY_KP_9: return RGFW_keyPad9;
 9896+        case XKB_KEY_Print: return RGFW_keyPrintScreen;
 9897+        case XKB_KEY_Pause: return RGFW_keyPause;
 9898+        default: break;
 9899+    }
 9900+
 9901+    return RGFW_keyNULL;
 9902+}
 9903+
 9904+RGFW_bool RGFW_FUNC(RGFW_window_fetchSize) (RGFW_window* win, i32* w, i32* h) {
 9905+	return RGFW_window_getSize(win, w, h);
 9906+}
 9907+
 9908+void RGFW_FUNC(RGFW_pollEvents) (void) {
 9909+	RGFW_resetPrevState();
 9910+
 9911+	/* send buffered requests to compositor */
 9912+	while (wl_display_flush(_RGFW->wl_display) == -1) {
 9913+		/* compositor not responding to new requests */
 9914+		/* so let's dispatch some events so the compositor responds */
 9915+		if (errno == EAGAIN) {
 9916+			if (wl_display_dispatch_pending(_RGFW->wl_display) == -1) {
 9917+				return;
 9918+			}
 9919+		} else {
 9920+			return;
 9921+		}
 9922+	}
 9923+	if (_RGFW->wl_repeat_info_rate != 0 && _RGFW->last_key) {
 9924+		u32 now = (u32)(RGFW_linux_getTimeNS() / 1000000);
 9925+		if (now > _RGFW->last_key_time) {
 9926+			RGFW_wl_send_key_event(_RGFW->last_key);
 9927+			_RGFW->last_key_time = now + 1000 / (u32)_RGFW->wl_repeat_info_rate;
 9928+		}
 9929+	}
 9930+
 9931+	/* read the events; if empty this reads from the */
 9932+	/* wayland file descriptor */
 9933+	if (wl_display_dispatch(_RGFW->wl_display) == -1) {
 9934+		return;
 9935+	}
 9936+
 9937+}
 9938+
 9939+void RGFW_FUNC(RGFW_window_move) (RGFW_window* win, i32 x, i32 y) {
 9940+	RGFW_ASSERT(win != NULL);
 9941+	win->x = x;
 9942+	win->y = y;
 9943+}
 9944+
 9945+
 9946+void RGFW_FUNC(RGFW_window_resize) (RGFW_window* win, i32 w, i32 h) {
 9947+	RGFW_ASSERT(win != NULL);
 9948+	win->w = w;
 9949+	win->h = h;
 9950+	if (_RGFW->compositor) {
 9951+		xdg_surface_set_window_geometry(win->src.xdg_surface, 0, 0, win->w, win->h);
 9952+		#ifdef RGFW_OPENGL
 9953+		if (win->src.ctx.egl)
 9954+			wl_egl_window_resize(win->src.ctx.egl->eglWindow, (i32)w, (i32)h, 0, 0);
 9955+		#endif
 9956+	}
 9957+}
 9958+
 9959+void RGFW_FUNC(RGFW_window_setAspectRatio) (RGFW_window* win, i32 w, i32 h) {
 9960+	RGFW_ASSERT(win != NULL);
 9961+
 9962+	if (w == 0 && h == 0)
 9963+		return;
 9964+    xdg_toplevel_set_max_size(win->src.xdg_toplevel, (i32)w, (i32)h);
 9965+}
 9966+
 9967+void RGFW_FUNC(RGFW_window_setMinSize) (RGFW_window* win, i32 w, i32 h) {
 9968+	RGFW_ASSERT(win != NULL);
 9969+    xdg_toplevel_set_min_size(win->src.xdg_toplevel, w, h);
 9970+}
 9971+
 9972+void RGFW_FUNC(RGFW_window_setMaxSize) (RGFW_window* win, i32 w, i32 h) {
 9973+	RGFW_ASSERT(win != NULL);
 9974+    xdg_toplevel_set_max_size(win->src.xdg_toplevel, w, h);
 9975+}
 9976+
 9977+void RGFW_toggleWaylandMaximized(RGFW_window* win, RGFW_bool maximized) {
 9978+    win->src.maximized = maximized;
 9979+    if (maximized) {
 9980+		xdg_toplevel_set_maximized(win->src.xdg_toplevel);
 9981+    } else {
 9982+		xdg_toplevel_unset_maximized(win->src.xdg_toplevel);
 9983+    }
 9984+}
 9985+
 9986+void RGFW_FUNC(RGFW_window_maximize) (RGFW_window* win) {
 9987+	win->internal.oldX = win->x;
 9988+	win->internal.oldY = win->y;
 9989+	win->internal.oldW = win->w;
 9990+	win->internal.oldH = win->h;
 9991+    RGFW_toggleWaylandMaximized(win, 1);
 9992+	RGFW_window_fetchSize(win, NULL, NULL);
 9993+    return;
 9994+}
 9995+
 9996+void RGFW_FUNC(RGFW_window_focus)(RGFW_window* win) {
 9997+	RGFW_ASSERT(win);
 9998+}
 9999+
10000+void RGFW_FUNC(RGFW_window_raise)(RGFW_window* win) {
10001+	RGFW_ASSERT(win);
10002+}
10003+
10004+void RGFW_FUNC(RGFW_window_setFullscreen)(RGFW_window* win, RGFW_bool fullscreen) {
10005+	RGFW_ASSERT(win != NULL);
10006+    if (fullscreen) {
10007+
10008+		win->internal.flags |= RGFW_windowFullscreen;
10009+		win->internal.oldX = win->x;
10010+		win->internal.oldY = win->y;
10011+		win->internal.oldW = win->w;
10012+		win->internal.oldH = win->h;
10013+		xdg_toplevel_set_fullscreen(win->src.xdg_toplevel, NULL); /* let the compositor decide */
10014+	} else {
10015+		win->internal.flags &= ~(u32)RGFW_windowFullscreen;
10016+		xdg_toplevel_unset_fullscreen(win->src.xdg_toplevel);
10017+	}
10018+
10019+}
10020+
10021+void RGFW_FUNC(RGFW_window_setFloating) (RGFW_window* win, RGFW_bool floating) {
10022+    RGFW_ASSERT(win != NULL);
10023+	RGFW_UNUSED(floating);
10024+}
10025+
10026+void RGFW_FUNC(RGFW_window_setOpacity) (RGFW_window* win, u8 opacity) {
10027+	RGFW_ASSERT(win != NULL);
10028+	RGFW_UNUSED(opacity);
10029+}
10030+
10031+void RGFW_FUNC(RGFW_window_minimize)(RGFW_window* win) {
10032+	RGFW_ASSERT(win != NULL);
10033+	if (RGFW_window_isMaximized(win)) return;
10034+	win->internal.oldX = win->x;
10035+	win->internal.oldY = win->y;
10036+	win->internal.oldW = win->w;
10037+	win->internal.oldH = win->h;
10038+	win->src.minimized = RGFW_TRUE;
10039+	xdg_toplevel_set_minimized(win->src.xdg_toplevel);
10040+}
10041+
10042+void RGFW_FUNC(RGFW_window_restore)(RGFW_window* win) {
10043+	RGFW_ASSERT(win != NULL);
10044+	RGFW_toggleWaylandMaximized(win, RGFW_FALSE);
10045+
10046+	RGFW_window_move(win, win->internal.oldX, win->internal.oldY);
10047+	RGFW_window_resize(win, win->internal.oldW, win->internal.oldH);
10048+
10049+	RGFW_window_show(win);
10050+	RGFW_window_move(win, win->internal.oldX, win->internal.oldY);
10051+	RGFW_window_resize(win, win->internal.oldW, win->internal.oldH);
10052+
10053+    RGFW_window_show(win);
10054+}
10055+
10056+RGFW_bool RGFW_FUNC(RGFW_window_isFloating)(RGFW_window* win) {
10057+	return (!RGFW_window_isFullscreen(win) && !RGFW_window_isMaximized(win));
10058+}
10059+
10060+void RGFW_FUNC(RGFW_window_setName) (RGFW_window* win, const char* name) {
10061+	RGFW_ASSERT(win != NULL);
10062+	if (name == NULL) name = "\0";
10063+
10064+	if (_RGFW->compositor)
10065+		xdg_toplevel_set_title(win->src.xdg_toplevel, name);
10066+}
10067+
10068+#ifndef RGFW_NO_PASSTHROUGH
10069+void RGFW_FUNC(RGFW_window_setMousePassthrough) (RGFW_window* win, RGFW_bool passthrough) {
10070+	RGFW_ASSERT(win != NULL);
10071+    RGFW_UNUSED(passthrough);
10072+}
10073+#endif /* RGFW_NO_PASSTHROUGH */
10074+
10075+RGFW_bool RGFW_FUNC(RGFW_window_setIconEx) (RGFW_window* win, u8* data, i32 w, i32 h, RGFW_format format, RGFW_icon type) {
10076+	RGFW_ASSERT(win != NULL);
10077+	RGFW_UNUSED(type);
10078+
10079+	if (_RGFW->icon_manager == NULL || w != h) return RGFW_FALSE;
10080+
10081+	if (win->src.icon) {
10082+		xdg_toplevel_icon_v1_destroy(win->src.icon);
10083+		win->src.icon= NULL;
10084+	}
10085+
10086+	RGFW_surface* surface = RGFW_createSurface(data, w, h, format);
10087+
10088+	if (surface == NULL) return RGFW_FALSE;
10089+
10090+	RGFW_copyImageData(surface->native.buffer, RGFW_MIN(w, surface->w), RGFW_MIN(h, surface->h), surface->native.format, surface->data, surface->format, NULL);
10091+
10092+	win->src.icon = xdg_toplevel_icon_manager_v1_create_icon(_RGFW->icon_manager);
10093+	xdg_toplevel_icon_v1_add_buffer(win->src.icon, surface->native.wl_buffer, 1);
10094+	xdg_toplevel_icon_manager_v1_set_icon(_RGFW->icon_manager, win->src.xdg_toplevel, win->src.icon);
10095+
10096+	RGFW_surface_free(surface);
10097+	return RGFW_TRUE;
10098+}
10099+
10100+RGFW_mouse* RGFW_FUNC(RGFW_createMouseStandard) (RGFW_mouseIcon mouse) {
10101+	char* cursorName = NULL;
10102+	switch (mouse) {
10103+		case RGFW_mouseNormal:       cursorName = (char*)"left_ptr"; break;
10104+		case RGFW_mouseArrow:       cursorName = (char*)"left_ptr"; break;
10105+		case RGFW_mouseIbeam:       cursorName = (char*)"xterm"; break;
10106+		case RGFW_mouseCrosshair:    cursorName = (char*)"crosshair"; break;
10107+		case RGFW_mousePointingHand: cursorName = (char*)"hand2"; break;
10108+		case RGFW_mouseResizeEW:     cursorName = (char*)"sb_h_double_arrow"; break;
10109+		case RGFW_mouseResizeNS:     cursorName = (char*)"sb_v_double_arrow"; break;
10110+		case RGFW_mouseResizeNWSE:   cursorName = (char*)"top_left_corner"; break;   /* or fd_double_arrow */
10111+		case RGFW_mouseResizeNESW:   cursorName = (char*)"top_right_corner"; break;  /* or bd_double_arrow */
10112+		case RGFW_mouseResizeNW:     cursorName = (char*)"top_left_corner"; break;
10113+		case RGFW_mouseResizeN:      cursorName = (char*)"top_side"; break;
10114+		case RGFW_mouseResizeNE:     cursorName = (char*)"top_right_corner"; break;
10115+		case RGFW_mouseResizeE:      cursorName = (char*)"right_side"; break;
10116+		case RGFW_mouseResizeSE:     cursorName = (char*)"bottom_right_corner"; break;
10117+		case RGFW_mouseResizeS:      cursorName = (char*)"bottom_side"; break;
10118+		case RGFW_mouseResizeSW:     cursorName = (char*)"bottom_left_corner"; break;
10119+		case RGFW_mouseResizeW:      cursorName = (char*)"left_side"; break;
10120+		case RGFW_mouseResizeAll:    cursorName = (char*)"fleur"; break;
10121+		case RGFW_mouseNotAllowed:   cursorName = (char*)"not-allowed"; break;
10122+		case RGFW_mouseWait:         cursorName = (char*)"watch"; break;
10123+		case RGFW_mouseProgress:     cursorName = (char*)"watch"; break;
10124+		default:                     return NULL;
10125+	}
10126+
10127+	struct wl_cursor* wlcursor = wl_cursor_theme_get_cursor(_RGFW->wl_cursor_theme, cursorName);
10128+	if (wlcursor == NULL)
10129+		return NULL;
10130+	struct wl_cursor_image* cursor_image = wlcursor->images[0];
10131+	struct wl_buffer* cursor_buffer = wl_cursor_image_get_buffer(cursor_image);
10132+
10133+	RGFW_surface* surface = RGFW_ALLOC(sizeof(RGFW_surface));
10134+	RGFW_MEMZERO(surface, sizeof(RGFW_surface));
10135+	surface->w = (i32)cursor_image->width;
10136+	surface->h = (i32)cursor_image->height;
10137+	surface->native.wl_buffer = cursor_buffer;
10138+
10139+	return (RGFW_mouse*)surface;
10140+}
10141+
10142+RGFW_mouse* RGFW_FUNC(RGFW_createMouse)(u8* data, i32 w, i32 h, RGFW_format format) {
10143+    RGFW_surface* surface = RGFW_createSurface(data, w, h, format);
10144+	if (surface == NULL) return NULL;
10145+
10146+	surface->native.wl_buffer = wl_shm_pool_create_buffer(surface->native.pool, 0, surface->w, surface->h, (i32)surface->w * 4, WL_SHM_FORMAT_ARGB8888);
10147+
10148+	RGFW_copyImageData(surface->native.buffer, RGFW_MIN(w, surface->w), RGFW_MIN(h, surface->h), surface->native.format, surface->data, surface->format, NULL);
10149+
10150+	return (RGFW_mouse*)surface;
10151+}
10152+
10153+RGFW_bool RGFW_FUNC(RGFW_window_setMousePlatform)(RGFW_window* win, RGFW_mouse* mouse) {
10154+	RGFW_ASSERT(win); RGFW_ASSERT(mouse);
10155+	RGFW_surface* surface = (RGFW_surface*)mouse;
10156+
10157+	win->src.using_custom_cursor = RGFW_TRUE;
10158+
10159+	wl_surface_attach(win->src.custom_cursor_surface, surface->native.wl_buffer, 0, 0);
10160+	wl_surface_damage(win->src.custom_cursor_surface, 0, 0, surface->w, surface->h);
10161+	wl_surface_commit(win->src.custom_cursor_surface);
10162+
10163+	return RGFW_TRUE;
10164+}
10165+
10166+void RGFW_FUNC(RGFW_freeMouse)(RGFW_mouse* mouse) {
10167+	if (mouse != NULL) {
10168+		RGFW_surface* surface = (RGFW_surface*)mouse;
10169+
10170+		if (surface->native.buffer && surface->native.wl_buffer) {
10171+			wl_buffer_destroy(surface->native.wl_buffer);
10172+		}
10173+
10174+		RGFW_surface_free(surface);
10175+	}
10176+}
10177+
10178+void RGFW_FUNC(RGFW_window_moveMouse)(RGFW_window* win, i32 x, i32 y) {
10179+	if (_RGFW->wp_pointer_warp != NULL) {
10180+		wp_pointer_warp_v1_warp_pointer(_RGFW->wp_pointer_warp, win->src.surface, _RGFW->wl_pointer, wl_fixed_from_int(x), wl_fixed_from_int(y), _RGFW->mouse_enter_serial);
10181+	}
10182+}
10183+
10184+void RGFW_FUNC(RGFW_window_hide) (RGFW_window* win) {
10185+	wl_surface_attach(win->src.surface, NULL, 0, 0);
10186+	wl_surface_commit(win->src.surface);
10187+	win->internal.flags |= RGFW_windowHide;
10188+}
10189+
10190+void RGFW_FUNC(RGFW_window_show) (RGFW_window* win) {
10191+	win->internal.flags &= ~(u32)RGFW_windowHide;
10192+	if (win->internal.flags & RGFW_windowFocusOnShow) RGFW_window_focus(win);
10193+	/* wl_surface_attach(win->src.surface, win->x, win->y, win->w, win->h, 0, 0); */
10194+	wl_surface_commit(win->src.surface);
10195+}
10196+
10197+void RGFW_FUNC(RGFW_window_flash) (RGFW_window* win, RGFW_flashRequest request) {
10198+	if (RGFW_window_isInFocus(win) && request) {
10199+		return;
10200+	}
10201+}
10202+
10203+RGFW_ssize_t RGFW_FUNC(RGFW_readClipboardPtr) (char* str, size_t strCapacity) {
10204+
10205+	RGFW_UNUSED(strCapacity);
10206+
10207+	if (str != NULL)
10208+		RGFW_STRNCPY(str, _RGFW->clipboard, _RGFW->clipboard_len - 1);
10209+	_RGFW->clipboard[_RGFW->clipboard_len - 1] = '\0';
10210+	return (RGFW_ssize_t)_RGFW->clipboard_len - 1;
10211+}
10212+
10213+void RGFW_FUNC(RGFW_writeClipboard) (const char* text, u32 textLen) {
10214+
10215+	// compositor does not support wl_data_device_manager
10216+	// clients cannot read rgfw's clipboard
10217+	if (_RGFW->data_device_manager == NULL) return;
10218+	// clear the clipboard
10219+	if (_RGFW->clipboard)
10220+		RGFW_FREE(_RGFW->clipboard);
10221+
10222+	// set the contents
10223+	_RGFW->clipboard = (char*)RGFW_ALLOC(textLen);
10224+	RGFW_ASSERT(_RGFW->clipboard != NULL);
10225+	RGFW_STRNCPY(_RGFW->clipboard, text, textLen - 1);
10226+	_RGFW->clipboard[textLen - 1] = '\0';
10227+	_RGFW->clipboard_len = textLen;
10228+
10229+	// means we already wrote to the clipboard
10230+	// so destroy it to create a new one
10231+	RGFW_window* win = _RGFW->kbOwner;
10232+
10233+	if (win->src.data_source != NULL) {
10234+		wl_data_source_destroy(win->src.data_source);
10235+		win->src.data_source = NULL;
10236+	}
10237+
10238+	// advertise to other clients that we offer text
10239+	win->src.data_source = wl_data_device_manager_create_data_source(_RGFW->data_device_manager);
10240+
10241+	// basic error checking
10242+	if (win->src.data_source == NULL) {
10243+		RGFW_debugCallback(RGFW_typeError, RGFW_errClipboard, "Could not create clipboard data source");
10244+		return;
10245+	}
10246+	wl_data_source_offer(win->src.data_source , "text/plain;charset=utf-8");
10247+
10248+	// needed RGFW_doNothing because wayland will call the functions
10249+	// if not set they are random data that lead to a crash
10250+	static const struct wl_data_source_listener data_source_listener = {
10251+		.target = (void (*)(void *, struct wl_data_source *, const char *))&RGFW_doNothing,
10252+		.action = (void (*)(void *, struct wl_data_source *, u32))&RGFW_doNothing,
10253+		.dnd_drop_performed = (void (*)(void *, struct wl_data_source *))&RGFW_doNothing,
10254+		.dnd_finished = (void (*)(void *, struct wl_data_source *))&RGFW_doNothing,
10255+		.send = RGFW_wl_data_source_send,
10256+		.cancelled = RGFW_wl_data_source_cancelled
10257+	};
10258+
10259+	wl_data_source_add_listener(win->src.data_source, &data_source_listener, _RGFW);
10260+
10261+}
10262+
10263+RGFW_bool RGFW_FUNC(RGFW_window_isHidden) (RGFW_window* win) {
10264+	RGFW_ASSERT(win != NULL);
10265+    return RGFW_FALSE;
10266+}
10267+
10268+RGFW_bool RGFW_FUNC(RGFW_window_isMinimized) (RGFW_window* win) {
10269+	RGFW_ASSERT(win != NULL);
10270+    return win->src.minimized;
10271+}
10272+
10273+RGFW_bool RGFW_FUNC(RGFW_window_isMaximized) (RGFW_window* win) {
10274+	RGFW_ASSERT(win != NULL);
10275+	return win->src.maximized;
10276+}
10277+
10278+void RGFW_FUNC(RGFW_pollMonitors) (void) {
10279+	_RGFW->monitors.primary = _RGFW->monitors.list.head;
10280+}
10281+
10282+
10283+RGFW_bool RGFW_FUNC(RGFW_monitor_getWorkarea) (RGFW_monitor* monitor, i32* x, i32* y, i32* width, i32* height) {
10284+	/* NOTE: Wayland has no way to get the actual workarea as far as I'm aware :( */
10285+	if (x) *x = monitor->x;
10286+	if (y) *y = monitor->y;
10287+	if (width) *width = monitor->mode.w;
10288+	if (height) *height = monitor->mode.h;
10289+	return RGFW_TRUE;
10290+}
10291+
10292+size_t RGFW_FUNC(RGFW_monitor_getModesPtr) (RGFW_monitor* monitor, RGFW_monitorMode** modes) {
10293+	if (modes) {
10294+		RGFW_MEMCPY((*modes), monitor->node->modes, monitor->node->modeCount * sizeof(RGFW_monitorMode));
10295+	}
10296+
10297+	return monitor->node->modeCount;
10298+}
10299+
10300+size_t RGFW_FUNC(RGFW_monitor_getGammaRampPtr) (RGFW_monitor* monitor, RGFW_gammaRamp* ramp) {
10301+	RGFW_UNUSED(monitor); RGFW_UNUSED(ramp);
10302+	return 0;
10303+}
10304+
10305+RGFW_bool RGFW_FUNC(RGFW_monitor_setGammaRamp) (RGFW_monitor* monitor, RGFW_gammaRamp* ramp) {
10306+	RGFW_UNUSED(monitor); RGFW_UNUSED(ramp);
10307+	return RGFW_FALSE;
10308+}
10309+
10310+RGFW_bool RGFW_FUNC(RGFW_monitor_requestMode) (RGFW_monitor* mon, RGFW_monitorMode* mode, RGFW_modeRequest request) {
10311+	for (size_t i = 0; i < mon->node->modeCount; i++) {
10312+		if (RGFW_monitorModeCompare(mode, &mon->node->modes[i], request) == RGFW_FALSE) {
10313+			continue;
10314+		}
10315+
10316+		RGFW_monitor_setMode(mon, &mon->node->modes[i]);
10317+		return RGFW_TRUE;
10318+	}
10319+
10320+	return RGFW_FALSE;
10321+}
10322+
10323+RGFW_bool RGFW_FUNC(RGFW_monitor_setMode) (RGFW_monitor* mon, RGFW_monitorMode* mode) {
10324+	RGFW_UNUSED(mon); RGFW_UNUSED(mode);
10325+	return RGFW_FALSE;
10326+}
10327+
10328+RGFW_monitor* RGFW_FUNC(RGFW_window_getMonitor) (RGFW_window* win) {
10329+	RGFW_ASSERT(win);
10330+	if (win->src.active_monitor == NULL) {
10331+		/* TODO: fix race condition [probably a problem with wayland] */
10332+		return RGFW_getPrimaryMonitor();
10333+	}
10334+
10335+	return &win->src.active_monitor->mon;
10336+}
10337+
10338+#ifdef RGFW_OPENGL
10339+RGFW_bool RGFW_FUNC(RGFW_extensionSupportedPlatform_OpenGL) (const char * extension, size_t len) { return RGFW_extensionSupportedPlatform_EGL(extension, len); }
10340+RGFW_proc RGFW_FUNC(RGFW_getProcAddress_OpenGL) (const char* procname) { return RGFW_getProcAddress_EGL(procname); }
10341+
10342+
10343+RGFW_bool RGFW_FUNC(RGFW_window_createContextPtr_OpenGL)(RGFW_window* win, RGFW_glContext* ctx, RGFW_glHints* hints) {
10344+	RGFW_bool out = RGFW_window_createContextPtr_EGL(win, &ctx->egl, hints);
10345+	win->src.gfxType = RGFW_gfxNativeOpenGL;
10346+
10347+	RGFW_window_swapInterval_OpenGL(win, 0);
10348+	return out;
10349+}
10350+void RGFW_FUNC(RGFW_window_deleteContextPtr_OpenGL) (RGFW_window* win, RGFW_glContext* ctx) { RGFW_window_deleteContextPtr_EGL(win, &ctx->egl); win->src.ctx.native = NULL; }
10351+
10352+void RGFW_FUNC(RGFW_window_makeCurrentContext_OpenGL) (RGFW_window* win) { RGFW_window_makeCurrentContext_EGL(win); }
10353+void* RGFW_FUNC(RGFW_getCurrentContext_OpenGL) (void) { return RGFW_getCurrentContext_EGL(); }
10354+void RGFW_FUNC(RGFW_window_swapBuffers_OpenGL) (RGFW_window* win) { RGFW_window_swapBuffers_EGL(win); }
10355+void RGFW_FUNC(RGFW_window_swapInterval_OpenGL) (RGFW_window* win, i32 swapInterval) { RGFW_window_swapInterval_EGL(win, swapInterval); }
10356+#endif /* RGFW_OPENGL */
10357+
10358+void RGFW_FUNC(RGFW_window_closePlatform)(RGFW_window* win) {
10359+	RGFW_ASSERT(win != NULL);
10360+	RGFW_debugCallback(RGFW_typeInfo, RGFW_infoWindow, "a window was freed");
10361+	#ifdef RGFW_LIBDECOR
10362+		if (win->src.decorContext)
10363+			libdecor_unref(win->src.decorContext);
10364+	#endif
10365+
10366+	if (win->src.decoration) {
10367+		zxdg_toplevel_decoration_v1_destroy(win->src.decoration);
10368+	}
10369+
10370+	if (win->src.xdg_toplevel) {
10371+		xdg_toplevel_destroy(win->src.xdg_toplevel);
10372+	}
10373+
10374+	wl_surface_destroy(win->src.custom_cursor_surface);
10375+
10376+	if (win->src.locked_pointer) {
10377+		zwp_locked_pointer_v1_destroy(win->src.locked_pointer);
10378+	}
10379+
10380+	if (win->src.icon) {
10381+		xdg_toplevel_icon_v1_destroy(win->src.icon);
10382+	}
10383+
10384+	xdg_surface_destroy(win->src.xdg_surface);
10385+	wl_surface_destroy(win->src.surface);
10386+}
10387+
10388+#ifdef RGFW_WEBGPU
10389+WGPUSurface RGFW_FUNC(RGFW_window_createSurface_WebGPU) (RGFW_window* window, WGPUInstance instance) {
10390+	WGPUSurfaceDescriptor surfaceDesc = {0};
10391+	WGPUSurfaceSourceWaylandSurface fromWl = {0};
10392+	fromWl.chain.sType = WGPUSType_SurfaceSourceWaylandSurface;
10393+	fromWl.display = _RGFW->wl_display;
10394+	fromWl.surface = window->src.surface;
10395+
10396+	surfaceDesc.nextInChain = (WGPUChainedStruct*)&fromWl.chain;
10397+	return wgpuInstanceCreateSurface(instance, &surfaceDesc);
10398+}
10399+#endif
10400+
10401+
10402+
10403+#endif /* RGFW_WAYLAND */
10404+/*
10405+	End of Wayland defines
10406+*/
10407+
10408+/*
10409+
10410+	Start of Windows defines
10411+
10412+
10413+*/
10414+
10415+#ifdef RGFW_WINDOWS
10416+#ifndef WIN32_LEAN_AND_MEAN
10417+	#define WIN32_LEAN_AND_MEAN
10418+#endif
10419+
10420+#ifndef OEMRESOURCE
10421+	#define OEMRESOURCE
10422+#endif
10423+
10424+#include <windows.h>
10425+
10426+#ifndef OCR_NORMAL
10427+#define OCR_NORMAL 32512
10428+#define OCR_IBEAM 32513
10429+#define OCR_WAIT 32514
10430+#define OCR_CROSS 32515
10431+#define OCR_UP 32516
10432+#define OCR_SIZENWSE 32642
10433+#define OCR_SIZENESW 32643
10434+#define OCR_SIZEWE 32644
10435+#define OCR_SIZENS 32645
10436+#define OCR_SIZEALL 32646
10437+#define OCR_NO 32648
10438+#define OCR_HAND 32649
10439+#define OCR_APPSTARTING 32650
10440+#endif
10441+
10442+#include <windowsx.h>
10443+#include <shellapi.h>
10444+#include <shellscalingapi.h>
10445+#include <wchar.h>
10446+#include <locale.h>
10447+#include <winuser.h>
10448+
10449+#ifndef WM_DPICHANGED
10450+#define WM_DPICHANGED       0x02E0
10451+#endif
10452+
10453+RGFWDEF DWORD RGFW_winapi_window_getStyle(RGFW_window* win, RGFW_windowFlags flags);
10454+DWORD RGFW_winapi_window_getStyle(RGFW_window* win, RGFW_windowFlags flags) {
10455+	RGFW_UNUSED(win);
10456+    DWORD style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
10457+
10458+    if ((flags & RGFW_windowFullscreen)) {
10459+        style |= WS_POPUP;
10460+    } else {
10461+        style |= WS_SYSMENU | WS_MINIMIZEBOX;
10462+
10463+        if (!(flags & RGFW_windowNoBorder)) {
10464+            style |= WS_CAPTION;
10465+
10466+            if (!(flags & RGFW_windowNoResize))
10467+                style |= WS_MAXIMIZEBOX | WS_THICKFRAME;
10468+        }
10469+        else
10470+            style |= WS_POPUP;
10471+    }
10472+
10473+    return style;
10474+}
10475+
10476+RGFWDEF DWORD RGFW_winapi_window_getExStyle(RGFW_window* win, RGFW_windowFlags flags);
10477+DWORD RGFW_winapi_window_getExStyle(RGFW_window* win, RGFW_windowFlags flags) {
10478+    DWORD style = WS_EX_APPWINDOW;
10479+    if (flags & RGFW_windowFullscreen || (flags & RGFW_windowFloating || RGFW_window_isFloating(win))) {
10480+        style |= WS_EX_TOPMOST;
10481+	}
10482+
10483+    return style;
10484+}
10485+
10486+RGFW_bool RGFW_createUTF8FromWideStringWin32(const WCHAR* source, char* out, size_t max);
10487+
10488+#define GL_FRONT				0x0404
10489+#define GL_BACK					0x0405
10490+#define GL_LEFT					0x0406
10491+#define GL_RIGHT				0x0407
10492+
10493+typedef int (*PFN_wglGetSwapIntervalEXT)(void);
10494+PFN_wglGetSwapIntervalEXT wglGetSwapIntervalEXTSrc = NULL;
10495+#define wglGetSwapIntervalEXT wglGetSwapIntervalEXTSrc
10496+
10497+/* these two wgl functions need to be preloaded */
10498+typedef HGLRC (WINAPI *PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC hdc, HGLRC hglrc, const int *attribList);
10499+PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL;
10500+
10501+HMODULE RGFW_wgl_dll = NULL;
10502+
10503+#ifndef RGFW_NO_LOAD_WGL
10504+	typedef HGLRC(WINAPI* PFN_wglCreateContext)(HDC);
10505+	typedef BOOL(WINAPI* PFN_wglDeleteContext)(HGLRC);
10506+	typedef PROC(WINAPI* PFN_wglGetProcAddress)(LPCSTR);
10507+	typedef BOOL(WINAPI* PFN_wglMakeCurrent)(HDC, HGLRC);
10508+	typedef HDC(WINAPI* PFN_wglGetCurrentDC)(void);
10509+	typedef HGLRC(WINAPI* PFN_wglGetCurrentContext)(void);
10510+	typedef BOOL(WINAPI* PFN_wglShareLists)(HGLRC, HGLRC);
10511+
10512+	PFN_wglCreateContext wglCreateContextSRC;
10513+	PFN_wglDeleteContext wglDeleteContextSRC;
10514+	PFN_wglGetProcAddress wglGetProcAddressSRC;
10515+	PFN_wglMakeCurrent wglMakeCurrentSRC;
10516+	PFN_wglGetCurrentDC wglGetCurrentDCSRC;
10517+	PFN_wglGetCurrentContext wglGetCurrentContextSRC;
10518+	PFN_wglShareLists wglShareListsSRC;
10519+
10520+	#define wglCreateContext wglCreateContextSRC
10521+	#define wglDeleteContext wglDeleteContextSRC
10522+	#define wglGetProcAddress wglGetProcAddressSRC
10523+	#define wglMakeCurrent wglMakeCurrentSRC
10524+	#define wglGetCurrentDC wglGetCurrentDCSRC
10525+	#define wglGetCurrentContext wglGetCurrentContextSRC
10526+	#define wglShareLists wglShareListsSRC
10527+#endif
10528+
10529+void* RGFW_window_getHWND(RGFW_window* win) { return win->src.window; }
10530+void* RGFW_window_getHDC(RGFW_window* win) { return win->src.hdc; }
10531+
10532+#ifdef RGFW_OPENGL
10533+RGFWDEF void RGFW_win32_loadOpenGLFuncs(HWND dummyWin);
10534+
10535+typedef HRESULT (APIENTRY* PFNWGLCHOOSEPIXELFORMATARBPROC)(HDC hdc, const int* piAttribIList, const FLOAT* pfAttribFList, UINT nMaxFormats, int* piFormats, UINT* nNumFormats);
10536+PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = NULL;
10537+
10538+typedef BOOL(APIENTRY* PFNWGLSWAPINTERVALEXTPROC)(int interval);
10539+PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = NULL;
10540+#endif
10541+
10542+#ifndef RGFW_NO_DWM
10543+HMODULE RGFW_dwm_dll = NULL;
10544+#ifndef _DWMAPI_H_
10545+typedef struct { DWORD dwFlags; int fEnable; HRGN hRgnBlur; int fTransitionOnMaximized;} DWM_BLURBEHIND;
10546+#endif
10547+typedef HRESULT (WINAPI * PFN_DwmEnableBlurBehindWindow)(HWND, const DWM_BLURBEHIND*);
10548+PFN_DwmEnableBlurBehindWindow DwmEnableBlurBehindWindowSRC = NULL;
10549+
10550+typedef HRESULT (WINAPI * PFN_DwmSetWindowAttribute)(HWND, DWORD, LPCVOID, DWORD);
10551+PFN_DwmSetWindowAttribute DwmSetWindowAttributeSRC = NULL;
10552+#endif
10553+void RGFW_win32_makeWindowTransparent(RGFW_window* win);
10554+void RGFW_win32_makeWindowTransparent(RGFW_window* win) {
10555+	if (!(win->internal.flags & RGFW_windowTransparent)) return;
10556+
10557+	#ifndef RGFW_NO_DWM
10558+	if (DwmEnableBlurBehindWindowSRC != NULL) {
10559+			DWM_BLURBEHIND bb = {0, 0, 0, 0};
10560+			bb.dwFlags = 0x1;
10561+			bb.fEnable = TRUE;
10562+			bb.hRgnBlur = NULL;
10563+			DwmEnableBlurBehindWindowSRC(win->src.window, &bb);
10564+
10565+	} else
10566+	#endif
10567+	{
10568+		SetWindowLong(win->src.window, GWL_EXSTYLE, WS_EX_LAYERED);
10569+		SetLayeredWindowAttributes(win->src.window, 0, 128,  LWA_ALPHA);
10570+	}
10571+}
10572+
10573+RGFWDEF RGFW_bool RGFW_win32_getDarkModeState(void);
10574+RGFW_bool RGFW_win32_getDarkModeState(void) {
10575+	u32 lightMode = 1;
10576+#if (_WIN32_WINNT >= 0x0600)
10577+	DWORD len = sizeof(lightMode);
10578+
10579+	RegGetValueW(
10580+		HKEY_CURRENT_USER,
10581+		L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize",
10582+		L"AppsUseLightTheme", RRF_RT_REG_DWORD, NULL, &lightMode, &len
10583+	);
10584+#endif
10585+
10586+	return (lightMode == 0);
10587+}
10588+
10589+RGFWDEF void RGFW_win32_makeWindowDarkMode(RGFW_window* win, RGFW_bool state);
10590+void RGFW_win32_makeWindowDarkMode(RGFW_window* win, RGFW_bool state) {
10591+	BOOL value = (state == RGFW_TRUE) ? TRUE : FALSE;
10592+	DwmSetWindowAttributeSRC(win->src.window, 20 /* DWMWA_USE_IMMERSIVE_DARK_MODE */, &value, sizeof(value));
10593+}
10594+
10595+LRESULT CALLBACK WndProcW(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
10596+LRESULT CALLBACK WndProcW(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
10597+    RGFW_window* win = (RGFW_window*)GetPropW(hWnd, L"RGFW");
10598+	if (win == NULL) return DefWindowProcW(hWnd, message, wParam, lParam);
10599+
10600+	static BYTE keyboardState[256];
10601+	GetKeyboardState(keyboardState);
10602+
10603+	RECT frame;
10604+	ZeroMemory(&frame, sizeof(frame));
10605+	DWORD style = RGFW_winapi_window_getStyle(win, win->internal.flags);
10606+	DWORD exStyle = RGFW_winapi_window_getExStyle(win, win->internal.flags);
10607+	AdjustWindowRectEx(&frame, style, FALSE, exStyle);
10608+
10609+	switch (message) {
10610+        case WM_DISPLAYCHANGE:
10611+            RGFW_pollMonitors();
10612+            break;
10613+		case WM_CLOSE:
10614+		case WM_QUIT:
10615+			RGFW_windowCloseCallback(win);
10616+			return 0;
10617+		case WM_ACTIVATE: {
10618+			RGFW_bool inFocus = RGFW_BOOL(LOWORD(wParam) != WA_INACTIVE);
10619+			RGFW_windowFocusCallback(win, inFocus);
10620+
10621+			return DefWindowProcW(hWnd, message, wParam, lParam);
10622+		}
10623+		case WM_MOVE:
10624+			if (win->internal.captureMouse) {
10625+				RGFW_window_captureMousePlatform(win, RGFW_TRUE);
10626+			}
10627+
10628+			RGFW_windowMovedCallback(win, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
10629+			return DefWindowProcW(hWnd, message, wParam, lParam);
10630+		case WM_SIZE: {
10631+			if (win->internal.captureMouse) {
10632+				RGFW_window_captureMousePlatform(win, RGFW_TRUE);
10633+			}
10634+
10635+			RGFW_windowResizedCallback(win, LOWORD(lParam), HIWORD(lParam));
10636+			RGFW_window_checkMode(win);
10637+			return DefWindowProcW(hWnd, message, wParam, lParam);
10638+		}
10639+        case WM_MOUSEACTIVATE:         {
10640+            if (HIWORD(lParam) == WM_LBUTTONDOWN) {
10641+                if (LOWORD(lParam) != HTCLIENT)
10642+                    win->src.actionFrame = RGFW_TRUE;
10643+            }
10644+
10645+            break;
10646+        }
10647+		case WM_CAPTURECHANGED:         {
10648+            if (lParam == 0 && win->src.actionFrame) {
10649+				RGFW_window_captureMousePlatform(win, win->internal.captureMouse);
10650+                win->src.actionFrame = RGFW_FALSE;
10651+            }
10652+
10653+            break;
10654+        }
10655+		#ifndef RGFW_NO_DPI
10656+		case WM_DPICHANGED: {
10657+			const float scaleX = HIWORD(wParam) / (float) 96;
10658+            const float scaleY = LOWORD(wParam) / (float) 96;
10659+
10660+			RGFW_scaleUpdatedCallback(win, scaleX, scaleY);
10661+			return DefWindowProcW(hWnd, message, wParam, lParam);
10662+		}
10663+		#endif
10664+		case WM_SIZING: {
10665+			if (win->src.aspectRatioW == 0 && win->src.aspectRatioH == 0) {
10666+				break;
10667+			}
10668+
10669+			RECT* area = (RECT*)lParam;
10670+			i32 edge = (i32)wParam;
10671+
10672+			double ratio = (double)win->src.aspectRatioW / (double) win->src.aspectRatioH;
10673+
10674+			if (edge == WMSZ_LEFT  || edge == WMSZ_BOTTOMLEFT || edge == WMSZ_RIGHT || edge == WMSZ_BOTTOMRIGHT) {
10675+				area->bottom = area->top + (frame.bottom - frame.top) + (i32) (((area->right - area->left) - (frame.right - frame.left)) / ratio);
10676+			} else if (edge == WMSZ_TOPLEFT || edge == WMSZ_TOPRIGHT) {
10677+				area->top = area->bottom - (frame.bottom - frame.top) - (i32) (((area->right - area->left) - (frame.right - frame.left)) / ratio);
10678+			} else if (edge == WMSZ_TOP || edge == WMSZ_BOTTOM) {
10679+				area->right = area->left + (frame.right - frame.left) + (i32) (((area->bottom - area->top) - (frame.bottom - frame.top)) * ratio);
10680+			}
10681+
10682+			return TRUE;
10683+		}
10684+		case WM_GETMINMAXINFO: {
10685+			MINMAXINFO* mmi = (MINMAXINFO*) lParam;
10686+			RGFW_bool resize = ((win->src.minSizeW == win->src.maxSizeW) && (win->src.minSizeH == win->src.maxSizeH));
10687+			RGFW_setBit(&win->internal.flags, RGFW_windowNoResize, resize);
10688+
10689+			mmi->ptMinTrackSize.x = (LONG)(win->src.minSizeW + (frame.right - frame.left));
10690+			mmi->ptMinTrackSize.y = (LONG)(win->src.minSizeH + (frame.bottom - frame.top));
10691+			if (win->src.maxSizeW == 0 && win->src.maxSizeH == 0)
10692+				return DefWindowProcW(hWnd, message, wParam, lParam);
10693+
10694+			mmi->ptMaxTrackSize.x = (LONG)(win->src.maxSizeW + (frame.right - frame.left));
10695+			mmi->ptMaxTrackSize.y = (LONG)(win->src.maxSizeH + (frame.bottom - frame.top));
10696+			return DefWindowProcW(hWnd, message, wParam, lParam);
10697+		}
10698+		case WM_PAINT: {
10699+            PAINTSTRUCT ps;
10700+            BeginPaint(hWnd, &ps);
10701+            RGFW_windowRefreshCallback(win, 0, 0, win->w, win->h);
10702+            EndPaint(hWnd, &ps);
10703+
10704+            return DefWindowProcW(hWnd, message, wParam, lParam);
10705+		}
10706+		#if(_WIN32_WINNT >= 0x0600)
10707+		case WM_DWMCOMPOSITIONCHANGED:
10708+		case WM_DWMCOLORIZATIONCOLORCHANGED:
10709+			RGFW_win32_makeWindowTransparent(win);
10710+			break;
10711+		#endif
10712+
10713+		case WM_ENTERSIZEMOVE: {
10714+			if (win->src.actionFrame)
10715+				RGFW_window_captureMousePlatform(win, win->internal.captureMouse);
10716+
10717+			#ifdef RGFW_ADVANCED_SMOOTH_RESIZE
10718+				SetTimer(win->src.window, 1, USER_TIMER_MINIMUM, NULL); break;
10719+			#endif
10720+			break;
10721+		}
10722+        case WM_EXITSIZEMOVE: {
10723+			if (win->src.actionFrame)
10724+				RGFW_window_captureMousePlatform(win, win->internal.captureMouse);
10725+
10726+			#ifdef RGFW_ADVANCED_SMOOTH_RESIZE
10727+				KillTimer(win->src.window, 1); break;
10728+			#endif
10729+			break;
10730+		}
10731+        case WM_TIMER:
10732+			RGFW_windowRefreshCallback(win, 0, 0, win->w, win->h);
10733+			break;
10734+
10735+		case WM_NCLBUTTONDOWN: {
10736+            /* workaround for half-second pause when starting to move window
10737+                see: https://gamedev.net/forums/topic/672094-keeping-things-moving-during-win32-moveresize-events/5254386/
10738+            */
10739+            POINT point = { 0, 0 };
10740+            if (SendMessage(win->src.window, WM_NCHITTEST, wParam, lParam) != HTCAPTION || GetCursorPos(&point) == FALSE)
10741+                break;
10742+
10743+            ScreenToClient(win->src.window, &point);
10744+            PostMessage(win->src.window, WM_MOUSEMOVE, 0, (u32)(point.x)|((u32)(point.y) << 16));
10745+            break;
10746+        }
10747+		case WM_MOUSELEAVE:
10748+			RGFW_mouseNotifyCallback(win, win->internal.lastMouseX, win->internal.lastMouseY, RGFW_FALSE);
10749+			break;
10750+
10751+        case WM_CHAR:
10752+        case WM_SYSCHAR: {
10753+            if (wParam >= 0xd800 && wParam <= 0xdbff)
10754+                win->src.highSurrogate = (WCHAR) wParam;
10755+            else {
10756+                u32 codepoint = 0;
10757+
10758+                if (wParam >= 0xdc00 && wParam <= 0xdfff) {
10759+                    if (win->src.highSurrogate) {
10760+                        codepoint += (u32)((win->src.highSurrogate - 0xd800) << 10);
10761+                        codepoint += (u32)((WCHAR) wParam - 0xdc00);
10762+                        codepoint += 0x10000;
10763+                    }
10764+                }
10765+                else
10766+                    codepoint = (WCHAR) wParam;
10767+
10768+                win->src.highSurrogate = 0;
10769+				RGFW_keyCharCallback(win, (u32)codepoint);
10770+            }
10771+
10772+            return 0;
10773+        }
10774+
10775+        case WM_UNICHAR: {
10776+            if (wParam == UNICODE_NOCHAR) {
10777+                return TRUE;
10778+            }
10779+
10780+			RGFW_keyCharCallback(win, (u32)wParam);
10781+            return 0;
10782+        }
10783+		case WM_SYSKEYUP: case WM_KEYUP: {
10784+			if (!(win->internal.enabledEvents & RGFW_keyReleasedFlag)) return DefWindowProcW(hWnd, message, wParam, lParam);
10785+			i32 scancode = (HIWORD(lParam) & (KF_EXTENDED | 0xff));
10786+			if (scancode == 0)
10787+				scancode = (i32)MapVirtualKeyW((UINT)wParam, MAPVK_VK_TO_VSC);
10788+
10789+			switch (scancode) {
10790+				case 0x54: scancode = 0x137; break; /*  Alt+PrtS */
10791+				case 0x146: scancode = 0x45; break; /* Ctrl+Pause */
10792+				case 0x136: scancode = 0x36; break; /*  CJK IME sets the extended bit for right Shift */
10793+				default: break;
10794+			}
10795+
10796+			RGFW_key value = (u8)RGFW_apiKeyToRGFW((u32) scancode);
10797+
10798+			if (wParam == VK_CONTROL) {
10799+				if (HIWORD(lParam) & KF_EXTENDED)
10800+					value = RGFW_keyControlR;
10801+				else value = RGFW_keyControlL;
10802+			}
10803+
10804+			RGFW_keyUpdateKeyMods(win, (GetKeyState(VK_CAPITAL) & 0x0001), (GetKeyState(VK_NUMLOCK) & 0x0001), (GetKeyState(VK_SCROLL) & 0x0001));
10805+			RGFW_keyCallback(win, value, win->internal.mod, RGFW_FALSE, RGFW_FALSE);
10806+			break;
10807+		}
10808+		case WM_SYSKEYDOWN: case WM_KEYDOWN: {
10809+			if (!(win->internal.enabledEvents & RGFW_keyPressedFlag)) return DefWindowProcW(hWnd, message, wParam, lParam);
10810+            i32 scancode = (HIWORD(lParam) & (KF_EXTENDED | 0xff));
10811+			if (scancode == 0)
10812+				scancode = (i32)MapVirtualKeyW((u32)wParam, MAPVK_VK_TO_VSC);
10813+
10814+			switch (scancode) {
10815+				case 0x54: scancode = 0x137; break; /*  Alt+PrtS */
10816+				case 0x146: scancode = 0x45; break; /* Ctrl+Pause */
10817+				case 0x136: scancode = 0x36; break; /*  CJK IME sets the extended bit for right Shift */
10818+				default: break;
10819+			}
10820+
10821+			RGFW_key value = (u8)RGFW_apiKeyToRGFW((u32) scancode);
10822+			if (wParam == VK_CONTROL) {
10823+				if (HIWORD(lParam) & KF_EXTENDED)
10824+					value = RGFW_keyControlR;
10825+				else value = RGFW_keyControlL;
10826+			}
10827+
10828+			RGFW_bool repeat = RGFW_isKeyDown(value);
10829+
10830+			RGFW_keyUpdateKeyMods(win, (GetKeyState(VK_CAPITAL) & 0x0001), (GetKeyState(VK_NUMLOCK) & 0x0001), (GetKeyState(VK_SCROLL) & 0x0001));
10831+			RGFW_keyCallback(win, value, win->internal.mod, repeat, 1);
10832+			break;
10833+		}
10834+		case WM_MOUSEMOVE: {
10835+			if (win->internal.mouseInside == RGFW_FALSE) {
10836+				RGFW_mouseNotifyCallback(win, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), RGFW_TRUE);
10837+			}
10838+
10839+			RGFW_mousePosCallback(win, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
10840+			break;
10841+		}
10842+		case WM_INPUT: {
10843+			if (!(win->internal.rawMouse || _RGFW->rawMouse)) return DefWindowProcW(hWnd, message, wParam, lParam);
10844+			unsigned size = sizeof(RAWINPUT);
10845+			static RAWINPUT raw;
10846+
10847+			GetRawInputData((HRAWINPUT)lParam, RID_INPUT, &raw, &size, sizeof(RAWINPUTHEADER));
10848+
10849+			if (raw.header.dwType != RIM_TYPEMOUSE || (raw.data.mouse.lLastX == 0 && raw.data.mouse.lLastY == 0) )
10850+				break;
10851+
10852+			float vecX = 0.0f;
10853+			float vecY = 0.0f;
10854+
10855+			if (raw.data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE) {
10856+				POINT pos = {0, 0};
10857+				int width, height;
10858+
10859+				if (raw.data.mouse.usFlags & MOUSE_VIRTUAL_DESKTOP) {
10860+					pos.x += GetSystemMetrics(SM_XVIRTUALSCREEN);
10861+					pos.y += GetSystemMetrics(SM_YVIRTUALSCREEN);
10862+					width = GetSystemMetrics(SM_CXVIRTUALSCREEN);
10863+					height = GetSystemMetrics(SM_CYVIRTUALSCREEN);
10864+				}
10865+				else {
10866+					width = GetSystemMetrics(SM_CXSCREEN);
10867+					height = GetSystemMetrics(SM_CYSCREEN);
10868+				}
10869+
10870+				pos.x += (int) (((float)raw.data.mouse.lLastX / 65535.f) * (float)width);
10871+				pos.y += (int) (((float)raw.data.mouse.lLastY / 65535.f) * (float)height);
10872+				ScreenToClient(win->src.window, &pos);
10873+
10874+				vecX = (float)(pos.x - win->internal.lastMouseX);
10875+				vecY = (float)(pos.y - win->internal.lastMouseY);
10876+			} else {
10877+				vecX = (float)(raw.data.mouse.lLastX);
10878+				vecY = (float)(raw.data.mouse.lLastY);
10879+			}
10880+
10881+			RGFW_rawMotionCallback(win, vecX, vecY);
10882+			break;
10883+		}
10884+		case WM_LBUTTONDOWN: case WM_RBUTTONDOWN: case WM_MBUTTONDOWN: case WM_XBUTTONDOWN: {
10885+			RGFW_mouseButton value = 0;
10886+			if (message == WM_XBUTTONDOWN)
10887+				value = RGFW_mouseMisc1 + (GET_XBUTTON_WPARAM(wParam) == XBUTTON2);
10888+			else value = (message == WM_LBUTTONDOWN) ? (u8)RGFW_mouseLeft :
10889+									 (message == WM_RBUTTONDOWN) ? (u8)RGFW_mouseRight : (u8)RGFW_mouseMiddle;
10890+
10891+			RGFW_mouseButtonCallback(win, value, 1);
10892+			break;
10893+		}
10894+		case WM_LBUTTONUP: case WM_RBUTTONUP: case WM_MBUTTONUP: case WM_XBUTTONUP: {
10895+			RGFW_mouseButton value = 0;
10896+			if (message == WM_XBUTTONUP)
10897+				value = RGFW_mouseMisc1 + (GET_XBUTTON_WPARAM(wParam) == XBUTTON2);
10898+			else value = (message == WM_LBUTTONUP) ? (u8)RGFW_mouseLeft :
10899+									 (message == WM_RBUTTONUP) ? (u8)RGFW_mouseRight : (u8)RGFW_mouseMiddle;
10900+
10901+			RGFW_mouseButtonCallback(win, value, 0);
10902+			break;
10903+		}
10904+		case WM_MOUSEWHEEL: {
10905+			float scrollY = (float)((i16) HIWORD(wParam) / (double) WHEEL_DELTA);
10906+			RGFW_mouseScrollCallback(win, 0.0f, scrollY);
10907+			break;
10908+		}
10909+		case 0x020E: {/* WM_MOUSEHWHEEL */
10910+			float scrollX = -(float)((i16) HIWORD(wParam) / (double) WHEEL_DELTA);
10911+			RGFW_mouseScrollCallback(win, scrollX, 0.0f);
10912+			break;
10913+		}
10914+		case WM_DROPFILES: {
10915+			HDROP drop = (HDROP) wParam;
10916+			POINT pt;
10917+
10918+			/* Move the mouse to the position of the drop */
10919+			DragQueryPoint(drop, &pt);
10920+			RGFW_dataDragCallback(win, RGFW_dataFile, RGFW_dndActionMove, pt.x, pt.y);
10921+
10922+			if (!(win->internal.enabledEvents & RGFW_dataDrop)) return DefWindowProcW(hWnd, message, wParam, lParam);
10923+			size_t count = DragQueryFileW(drop, 0xffffffff, NULL, 0);
10924+
10925+			u32 i;
10926+			for (i = 0; i < count; i++) {
10927+				UINT length = DragQueryFileW(drop, i, NULL, 0);
10928+				if (length == 0)
10929+					continue;
10930+
10931+				WCHAR* buffer = (WCHAR*)RGFW_ALLOC(sizeof(WCHAR) * (length + 1));
10932+				char* cbuffer = (char*)RGFW_ALLOC(length + 1);
10933+
10934+				DragQueryFileW(drop, i, buffer, length + 1);
10935+
10936+				RGFW_createUTF8FromWideStringWin32(buffer, cbuffer, length);
10937+
10938+				RGFW_dataDropCallback(win, cbuffer, length + 1, RGFW_dataFile);
10939+				RGFW_FREE(buffer);
10940+				RGFW_FREE(cbuffer);
10941+			}
10942+
10943+			DragFinish(drop);
10944+
10945+			break;
10946+		}
10947+		default: break;
10948+	}
10949+
10950+	return DefWindowProcW(hWnd, message, wParam, lParam);
10951+}
10952+
10953+#ifndef RGFW_NO_DPI
10954+	HMODULE RGFW_Shcore_dll = NULL;
10955+	typedef HRESULT (WINAPI *PFN_GetDpiForMonitor)(HMONITOR,MONITOR_DPI_TYPE,UINT*,UINT*);
10956+	PFN_GetDpiForMonitor GetDpiForMonitorSRC = NULL;
10957+	#define GetDpiForMonitor GetDpiForMonitorSRC
10958+#endif
10959+
10960+#if !defined(RGFW_NO_LOAD_WINMM) && !defined(RGFW_NO_WINMM)
10961+	HMODULE RGFW_winmm_dll = NULL;
10962+	typedef u32 (WINAPI * PFN_timeBeginPeriod)(u32);
10963+	typedef PFN_timeBeginPeriod PFN_timeEndPeriod;
10964+	PFN_timeBeginPeriod timeBeginPeriodSRC, timeEndPeriodSRC;
10965+	#define timeBeginPeriod timeBeginPeriodSRC
10966+	#define timeEndPeriod timeEndPeriodSRC
10967+#elif !defined(RGFW_NO_WINMM)
10968+	__declspec(dllimport) u32 __stdcall timeBeginPeriod(u32 uPeriod);
10969+	__declspec(dllimport) u32 __stdcall timeEndPeriod(u32 uPeriod);
10970+#endif
10971+#define RGFW_PROC_DEF(proc, name) if (name##SRC == NULL && proc != NULL) { \
10972+                                        name##SRC = (PFN_##name)(RGFW_proc)GetProcAddress((proc), (#name)); \
10973+                                        RGFW_ASSERT(name##SRC != NULL); \
10974+                                    }
10975+
10976+RGFW_format RGFW_nativeFormat(void) { return RGFW_formatBGRA8; }
10977+
10978+RGFW_bool RGFW_createSurfacePtr(u8* data, i32 w, i32 h, RGFW_format format, RGFW_surface* surface) {
10979+	RGFW_ASSERT(surface != NULL);
10980+	surface->data = data;
10981+	surface->w = w;
10982+	surface->h = h;
10983+	surface->format = format;
10984+
10985+	BITMAPV5HEADER bi;
10986+	ZeroMemory(&bi, sizeof(bi));
10987+	bi.bV5Size = sizeof(bi);
10988+	bi.bV5Width = (i32)w;
10989+	bi.bV5Height = -((LONG) h);
10990+	bi.bV5Planes = 1;
10991+	bi.bV5BitCount = (format >= RGFW_formatRGBA8) ? 32 : 24;
10992+	bi.bV5Compression = BI_RGB;
10993+
10994+	surface->native.bitmap = CreateDIBSection(_RGFW->root->src.hdc,
10995+		(BITMAPINFO*) &bi, DIB_RGB_COLORS,
10996+		(void**) &surface->native.bitmapBits,
10997+		NULL, (DWORD) 0);
10998+
10999+	surface->native.format = (format >= RGFW_formatRGBA8) ? (RGFW_format) RGFW_formatBGRA8 : (RGFW_format) RGFW_formatBGR8;
11000+
11001+	if (surface->native.bitmap == NULL) {
11002+		RGFW_debugCallback(RGFW_typeError, RGFW_errBuffer,  "Failed to create DIB section.");
11003+		return RGFW_FALSE;
11004+	}
11005+
11006+	surface->native.hdcMem = CreateCompatibleDC(_RGFW->root->src.hdc);
11007+	SelectObject(surface->native.hdcMem, surface->native.bitmap);
11008+
11009+	return RGFW_TRUE;
11010+}
11011+
11012+void RGFW_surface_freePtr(RGFW_surface* surface) {
11013+	RGFW_ASSERT(surface != NULL);
11014+
11015+	DeleteDC(surface->native.hdcMem);
11016+	DeleteObject(surface->native.bitmap);
11017+}
11018+
11019+void RGFW_window_blitSurface(RGFW_window* win, RGFW_surface* surface) {
11020+	RGFW_copyImageData(surface->native.bitmapBits, surface->w, RGFW_MIN(win->h, surface->h), surface->native.format, surface->data, surface->format, surface->convertFunc);
11021+	BitBlt(win->src.hdc, 0, 0, RGFW_MIN(win->w, surface->w), RGFW_MIN(win->h, surface->h), surface->native.hdcMem, 0, 0, SRCCOPY);
11022+}
11023+
11024+void RGFW_window_setRawMouseModePlatform(RGFW_window* win, RGFW_bool state) {
11025+	RGFW_UNUSED(win);
11026+	RAWINPUTDEVICE id = { 0x01, 0x02, 0, win->src.window };
11027+	id.dwFlags = (state == RGFW_TRUE) ? 0 : RIDEV_REMOVE;
11028+
11029+	RegisterRawInputDevices(&id, 1, sizeof(id));
11030+}
11031+
11032+void RGFW_window_captureMousePlatform(RGFW_window* win, RGFW_bool state) {
11033+	if (state == RGFW_FALSE) {
11034+		ClipCursor(NULL);
11035+		return;
11036+	}
11037+
11038+	RECT clipRect;
11039+	GetClientRect(win->src.window, &clipRect);
11040+	ClientToScreen(win->src.window, (POINT*) &clipRect.left);
11041+	ClientToScreen(win->src.window, (POINT*) &clipRect.right);
11042+	ClipCursor(&clipRect);
11043+}
11044+
11045+#define RGFW_LOAD_LIBRARY(x, lib) if (x == NULL) { x = LoadLibraryA(lib); RGFW_ASSERT(x != NULL); }
11046+
11047+#ifdef RGFW_DIRECTX
11048+int RGFW_window_createSwapChain_DirectX(RGFW_window* win, IDXGIFactory* pFactory, IUnknown* pDevice, IDXGISwapChain** swapchain) {
11049+    RGFW_ASSERT(win && pFactory && pDevice && swapchain);
11050+
11051+    static DXGI_SWAP_CHAIN_DESC swapChainDesc;
11052+	RGFW_MEMZERO(&swapChainDesc, sizeof(swapChainDesc));
11053+    swapChainDesc.BufferCount = 2;
11054+    swapChainDesc.BufferDesc.Width = win->w;
11055+    swapChainDesc.BufferDesc.Height = win->h;
11056+    swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
11057+    swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
11058+    swapChainDesc.OutputWindow = (HWND)win->src.window;
11059+    swapChainDesc.SampleDesc.Count = 1;
11060+    swapChainDesc.SampleDesc.Quality = 0;
11061+    swapChainDesc.Windowed = TRUE;
11062+    swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
11063+
11064+    HRESULT hr = pFactory->lpVtbl->CreateSwapChain(pFactory, (IUnknown*)pDevice, &swapChainDesc, swapchain);
11065+    if (FAILED(hr)) {
11066+        RGFW_debugCallback(RGFW_typeError, RGFW_errDirectXContext,  "Failed to create DirectX swap chain!");
11067+        return -2;
11068+    }
11069+
11070+    return 0;
11071+}
11072+#endif
11073+
11074+/* we're doing it with magic numbers because some keys are missing  */
11075+void RGFW_initKeycodesPlatform(void) {
11076+	_RGFW->keycodes[0x00B] = RGFW_key0;
11077+	_RGFW->keycodes[0x002] = RGFW_key1;
11078+	_RGFW->keycodes[0x003] = RGFW_key2;
11079+	_RGFW->keycodes[0x004] = RGFW_key3;
11080+	_RGFW->keycodes[0x005] = RGFW_key4;
11081+	_RGFW->keycodes[0x006] = RGFW_key5;
11082+	_RGFW->keycodes[0x007] = RGFW_key6;
11083+	_RGFW->keycodes[0x008] = RGFW_key7;
11084+	_RGFW->keycodes[0x009] = RGFW_key8;
11085+	_RGFW->keycodes[0x00A] = RGFW_key9;
11086+	_RGFW->keycodes[0x01E] = RGFW_keyA;
11087+	_RGFW->keycodes[0x030] = RGFW_keyB;
11088+	_RGFW->keycodes[0x02E] = RGFW_keyC;
11089+	_RGFW->keycodes[0x020] = RGFW_keyD;
11090+	_RGFW->keycodes[0x012] = RGFW_keyE;
11091+	_RGFW->keycodes[0x021] = RGFW_keyF;
11092+	_RGFW->keycodes[0x022] = RGFW_keyG;
11093+	_RGFW->keycodes[0x023] = RGFW_keyH;
11094+	_RGFW->keycodes[0x017] = RGFW_keyI;
11095+	_RGFW->keycodes[0x024] = RGFW_keyJ;
11096+	_RGFW->keycodes[0x025] = RGFW_keyK;
11097+	_RGFW->keycodes[0x026] = RGFW_keyL;
11098+	_RGFW->keycodes[0x032] = RGFW_keyM;
11099+	_RGFW->keycodes[0x031] = RGFW_keyN;
11100+	_RGFW->keycodes[0x018] = RGFW_keyO;
11101+	_RGFW->keycodes[0x019] = RGFW_keyP;
11102+	_RGFW->keycodes[0x010] = RGFW_keyQ;
11103+	_RGFW->keycodes[0x013] = RGFW_keyR;
11104+	_RGFW->keycodes[0x01F] = RGFW_keyS;
11105+	_RGFW->keycodes[0x014] = RGFW_keyT;
11106+	_RGFW->keycodes[0x016] = RGFW_keyU;
11107+	_RGFW->keycodes[0x02F] = RGFW_keyV;
11108+	_RGFW->keycodes[0x011] = RGFW_keyW;
11109+	_RGFW->keycodes[0x02D] = RGFW_keyX;
11110+	_RGFW->keycodes[0x015] = RGFW_keyY;
11111+	_RGFW->keycodes[0x02C] = RGFW_keyZ;
11112+	_RGFW->keycodes[0x028] = RGFW_keyApostrophe;
11113+	_RGFW->keycodes[0x02B] = RGFW_keyBackSlash;
11114+	_RGFW->keycodes[0x033] = RGFW_keyComma;
11115+	_RGFW->keycodes[0x00D] = RGFW_keyEquals;
11116+	_RGFW->keycodes[0x029] = RGFW_keyBacktick;
11117+	_RGFW->keycodes[0x01A] = RGFW_keyBracket;
11118+	_RGFW->keycodes[0x00C] = RGFW_keyMinus;
11119+	_RGFW->keycodes[0x034] = RGFW_keyPeriod;
11120+	_RGFW->keycodes[0x01B] = RGFW_keyCloseBracket;
11121+	_RGFW->keycodes[0x027] = RGFW_keySemicolon;
11122+	_RGFW->keycodes[0x035] = RGFW_keySlash;
11123+	_RGFW->keycodes[0x056] = RGFW_keyWorld2;
11124+	_RGFW->keycodes[0x00E] = RGFW_keyBackSpace;
11125+	_RGFW->keycodes[0x153] = RGFW_keyDelete;
11126+	_RGFW->keycodes[0x14F] = RGFW_keyEnd;
11127+	_RGFW->keycodes[0x01C] = RGFW_keyEnter;
11128+	_RGFW->keycodes[0x001] = RGFW_keyEscape;
11129+	_RGFW->keycodes[0x147] = RGFW_keyHome;
11130+	_RGFW->keycodes[0x152] = RGFW_keyInsert;
11131+	_RGFW->keycodes[0x15D] = RGFW_keyMenu;
11132+	_RGFW->keycodes[0x151] = RGFW_keyPageDown;
11133+	_RGFW->keycodes[0x149] = RGFW_keyPageUp;
11134+	_RGFW->keycodes[0x045] = RGFW_keyPause;
11135+	_RGFW->keycodes[0x039] = RGFW_keySpace;
11136+	_RGFW->keycodes[0x00F] = RGFW_keyTab;
11137+	_RGFW->keycodes[0x03A] = RGFW_keyCapsLock;
11138+	_RGFW->keycodes[0x145] = RGFW_keyNumLock;
11139+	_RGFW->keycodes[0x046] = RGFW_keyScrollLock;
11140+	_RGFW->keycodes[0x03B] = RGFW_keyF1;
11141+	_RGFW->keycodes[0x03C] = RGFW_keyF2;
11142+	_RGFW->keycodes[0x03D] = RGFW_keyF3;
11143+	_RGFW->keycodes[0x03E] = RGFW_keyF4;
11144+	_RGFW->keycodes[0x03F] = RGFW_keyF5;
11145+	_RGFW->keycodes[0x040] = RGFW_keyF6;
11146+	_RGFW->keycodes[0x041] = RGFW_keyF7;
11147+	_RGFW->keycodes[0x042] = RGFW_keyF8;
11148+	_RGFW->keycodes[0x043] = RGFW_keyF9;
11149+	_RGFW->keycodes[0x044] = RGFW_keyF10;
11150+	_RGFW->keycodes[0x057] = RGFW_keyF11;
11151+	_RGFW->keycodes[0x058] = RGFW_keyF12;
11152+	_RGFW->keycodes[0x064] = RGFW_keyF13;
11153+	_RGFW->keycodes[0x065] = RGFW_keyF14;
11154+	_RGFW->keycodes[0x066] = RGFW_keyF15;
11155+	_RGFW->keycodes[0x067] = RGFW_keyF16;
11156+	_RGFW->keycodes[0x068] = RGFW_keyF17;
11157+	_RGFW->keycodes[0x069] = RGFW_keyF18;
11158+	_RGFW->keycodes[0x06A] = RGFW_keyF19;
11159+	_RGFW->keycodes[0x06B] = RGFW_keyF20;
11160+	_RGFW->keycodes[0x06C] = RGFW_keyF21;
11161+	_RGFW->keycodes[0x06D] = RGFW_keyF22;
11162+	_RGFW->keycodes[0x06E] = RGFW_keyF23;
11163+	_RGFW->keycodes[0x076] = RGFW_keyF24;
11164+	_RGFW->keycodes[0x038] = RGFW_keyAltL;
11165+	_RGFW->keycodes[0x01D] = RGFW_keyControlL;
11166+	_RGFW->keycodes[0x02A] = RGFW_keyShiftL;
11167+	_RGFW->keycodes[0x15B] = RGFW_keySuperL;
11168+	_RGFW->keycodes[0x137] = RGFW_keyPrintScreen;
11169+	_RGFW->keycodes[0x138] = RGFW_keyAltR;
11170+	_RGFW->keycodes[0x11D] = RGFW_keyControlR;
11171+	_RGFW->keycodes[0x036] = RGFW_keyShiftR;
11172+	_RGFW->keycodes[0x15C] = RGFW_keySuperR;
11173+	_RGFW->keycodes[0x150] = RGFW_keyDown;
11174+	_RGFW->keycodes[0x14B] = RGFW_keyLeft;
11175+	_RGFW->keycodes[0x14D] = RGFW_keyRight;
11176+	_RGFW->keycodes[0x148] = RGFW_keyUp;
11177+	_RGFW->keycodes[0x052] = RGFW_keyPad0;
11178+	_RGFW->keycodes[0x04F] = RGFW_keyPad1;
11179+	_RGFW->keycodes[0x050] = RGFW_keyPad2;
11180+	_RGFW->keycodes[0x051] = RGFW_keyPad3;
11181+	_RGFW->keycodes[0x04B] = RGFW_keyPad4;
11182+	_RGFW->keycodes[0x04C] = RGFW_keyPad5;
11183+	_RGFW->keycodes[0x04D] = RGFW_keyPad6;
11184+	_RGFW->keycodes[0x047] = RGFW_keyPad7;
11185+	_RGFW->keycodes[0x048] = RGFW_keyPad8;
11186+	_RGFW->keycodes[0x049] = RGFW_keyPad9;
11187+	_RGFW->keycodes[0x04E] = RGFW_keyPadPlus;
11188+	_RGFW->keycodes[0x053] = RGFW_keyPadPeriod;
11189+	_RGFW->keycodes[0x135] = RGFW_keyPadSlash;
11190+	_RGFW->keycodes[0x11C] = RGFW_keyPadReturn;
11191+	_RGFW->keycodes[0x059] = RGFW_keyPadEqual;
11192+	_RGFW->keycodes[0x037] = RGFW_keyPadMultiply;
11193+	_RGFW->keycodes[0x04A] = RGFW_keyPadMinus;
11194+}
11195+
11196+
11197+i32 RGFW_initPlatform(void) {
11198+#ifndef RGFW_NO_DPI
11199+	#if (_WIN32_WINNT >= 0x0600)
11200+		SetProcessDPIAware();
11201+	#endif
11202+#endif
11203+
11204+	#ifndef RGFW_NO_WINMM
11205+		#ifndef RGFW_NO_LOAD_WINMM
11206+			RGFW_LOAD_LIBRARY(RGFW_winmm_dll, "winmm.dll");
11207+			RGFW_PROC_DEF(RGFW_winmm_dll, timeBeginPeriod);
11208+			RGFW_PROC_DEF(RGFW_winmm_dll, timeEndPeriod);
11209+		#endif
11210+		timeBeginPeriod(1);
11211+	#endif
11212+
11213+	#ifndef RGFW_NO_DWM
11214+	RGFW_LOAD_LIBRARY(RGFW_dwm_dll, "dwmapi.dll");
11215+	RGFW_PROC_DEF(RGFW_dwm_dll, DwmEnableBlurBehindWindow);
11216+	RGFW_PROC_DEF(RGFW_dwm_dll, DwmSetWindowAttribute);
11217+	#endif
11218+
11219+	RGFW_LOAD_LIBRARY(RGFW_wgl_dll, "opengl32.dll");
11220+	#ifndef RGFW_NO_LOAD_WGL
11221+		RGFW_PROC_DEF(RGFW_wgl_dll, wglCreateContext);
11222+		RGFW_PROC_DEF(RGFW_wgl_dll, wglDeleteContext);
11223+		RGFW_PROC_DEF(RGFW_wgl_dll, wglGetProcAddress);
11224+		RGFW_PROC_DEF(RGFW_wgl_dll, wglMakeCurrent);
11225+		RGFW_PROC_DEF(RGFW_wgl_dll, wglGetCurrentDC);
11226+		RGFW_PROC_DEF(RGFW_wgl_dll, wglGetCurrentContext);
11227+		RGFW_PROC_DEF(RGFW_wgl_dll, wglShareLists);
11228+	#endif
11229+
11230+	u8 RGFW_blk[] = { 0, 0, 0, 0 };
11231+	_RGFW->hiddenMouse = RGFW_createMouse(RGFW_blk, 1, 1, RGFW_formatRGBA8);
11232+    return 1;
11233+}
11234+
11235+RGFW_window* RGFW_createWindowPlatform(const char* name, RGFW_windowFlags flags, RGFW_window* win) {
11236+	if (name[0] == 0) name = (char*) " ";
11237+	win->src.hIconSmall = win->src.hIconBig = NULL;
11238+	win->src.maxSizeW = 0;
11239+	win->src.maxSizeH = 0;
11240+	win->src.minSizeW = 0;
11241+	win->src.minSizeH = 0;
11242+	win->src.aspectRatioW = 0;
11243+	win->src.aspectRatioH = 0;
11244+
11245+	HINSTANCE inh = GetModuleHandleA(NULL);
11246+
11247+	#ifndef __cplusplus
11248+	WNDCLASSW Class = {0}; /*!< Setup the Window class. */
11249+	#else
11250+	WNDCLASSW Class = {};
11251+	#endif
11252+
11253+	if (_RGFW->className == NULL)
11254+		_RGFW->className = (char*)name;
11255+
11256+	wchar_t wide_class[256];
11257+	MultiByteToWideChar(CP_UTF8, 0, _RGFW->className, -1, wide_class, 255);
11258+
11259+	Class.lpszClassName = wide_class;
11260+	Class.hInstance = inh;
11261+	Class.hCursor = LoadCursor(NULL, IDC_ARROW);
11262+	Class.lpfnWndProc = WndProcW;
11263+	Class.cbClsExtra = sizeof(RGFW_window*);
11264+
11265+	Class.hIcon = (HICON)LoadImageA(GetModuleHandleW(NULL), "RGFW_ICON", IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED);
11266+	if (Class.hIcon == NULL)
11267+		Class.hIcon = (HICON)LoadImageA(NULL, (LPCSTR)IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED);
11268+
11269+	RegisterClassW(&Class);
11270+
11271+	DWORD window_style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
11272+
11273+	if (!(flags & RGFW_windowNoBorder)) {
11274+		window_style |= WS_CAPTION | WS_SYSMENU | WS_BORDER | WS_MINIMIZEBOX;
11275+
11276+		if (!(flags & RGFW_windowNoResize))
11277+			window_style |= WS_SIZEBOX | WS_MAXIMIZEBOX;
11278+	} else
11279+		window_style |= WS_POPUP | WS_VISIBLE | WS_SYSMENU;
11280+
11281+	wchar_t wide_name[256];
11282+	MultiByteToWideChar(CP_UTF8, 0, name, -1, wide_name, 255);
11283+	HWND dummyWin = CreateWindowW(Class.lpszClassName, (wchar_t*)wide_name, window_style, win->x, win->y, win->w, win->h, 0, 0, inh, 0);
11284+
11285+#ifdef RGFW_OPENGL
11286+	RGFW_win32_loadOpenGLFuncs(dummyWin);
11287+#endif
11288+
11289+	DestroyWindow(dummyWin);
11290+
11291+	RECT rect = { 0, 0, win->w, win->h};
11292+	DWORD style = RGFW_winapi_window_getStyle(win, flags);
11293+	DWORD exStyle = RGFW_winapi_window_getExStyle(win, flags);
11294+	AdjustWindowRectEx(&rect, style, FALSE, exStyle);
11295+
11296+	win->src.window = CreateWindowW(Class.lpszClassName, (wchar_t*)wide_name, window_style, win->x + rect.left, win->y + rect.top, rect.right - rect.left, rect.bottom - rect.top, 0, 0, inh, 0);
11297+	SetPropW(win->src.window, L"RGFW", win);
11298+	RGFW_window_resize(win, win->w, win->h); /* so WM_GETMINMAXINFO gets called again */
11299+
11300+	if (flags & RGFW_windowAllowDND) {
11301+		win->internal.flags |= RGFW_windowAllowDND;
11302+		RGFW_window_setDND(win, 1);
11303+	}
11304+	win->src.hdc = GetDC(win->src.window);
11305+
11306+	RGFW_win32_makeWindowDarkMode(win, RGFW_win32_getDarkModeState());
11307+	RGFW_win32_makeWindowTransparent(win);
11308+	return win;
11309+}
11310+
11311+void RGFW_window_setBorder(RGFW_window* win, RGFW_bool border) {
11312+	RGFW_setBit(&win->internal.flags, RGFW_windowNoBorder, !border);
11313+
11314+	RECT rect;
11315+    GetClientRect(win->src.window, &rect);
11316+
11317+	LONG style = GetWindowLong(win->src.window, GWL_STYLE);
11318+	style |= (LONG)RGFW_winapi_window_getStyle(win, win->internal.flags);
11319+
11320+	if (border == 0) {
11321+		style &= ~WS_OVERLAPPEDWINDOW;
11322+	} else {
11323+		if (win->internal.flags & RGFW_windowNoResize) style &= ~WS_MAXIMIZEBOX;
11324+		style |= WS_OVERLAPPEDWINDOW;
11325+	}
11326+
11327+	DWORD exStyle = RGFW_winapi_window_getExStyle(win, win->internal.flags);
11328+	ClientToScreen(win->src.window, (POINT*) &rect.left);
11329+    ClientToScreen(win->src.window, (POINT*) &rect.right);
11330+
11331+	AdjustWindowRectEx(&rect, (DWORD)style, FALSE, exStyle);
11332+	SetWindowLong(win->src.window, GWL_STYLE, style);
11333+
11334+    SetWindowLongW(win->src.window, GWL_STYLE, style);
11335+    SetWindowPos(win->src.window, HWND_TOP, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOZORDER);
11336+}
11337+
11338+void RGFW_window_setDND(RGFW_window* win, RGFW_bool allow) {
11339+	RGFW_setBit(&win->internal.flags, RGFW_windowAllowDND, allow);
11340+	DragAcceptFiles(win->src.window, allow);
11341+}
11342+
11343+RGFW_bool RGFW_getGlobalMouse(i32* x, i32* y) {
11344+	POINT p;
11345+	GetCursorPos(&p);
11346+	if (x) *x = p.x;
11347+	if (y) *y = p.y;
11348+	return RGFW_TRUE;
11349+}
11350+
11351+void RGFW_window_setAspectRatio(RGFW_window* win, i32 w, i32 h) {
11352+	RGFW_ASSERT(win != NULL);
11353+	win->src.aspectRatioW = w;
11354+	win->src.aspectRatioH = h;
11355+}
11356+
11357+void RGFW_window_setMinSize(RGFW_window* win, i32 w, i32 h) {
11358+	RGFW_ASSERT(win != NULL);
11359+	win->src.minSizeW = w;
11360+	win->src.minSizeH = h;
11361+}
11362+
11363+void RGFW_window_setMaxSize(RGFW_window* win, i32 w, i32 h) {
11364+	RGFW_ASSERT(win != NULL);
11365+	win->src.maxSizeW = w;
11366+	win->src.maxSizeH = h;
11367+}
11368+
11369+void RGFW_window_focus(RGFW_window* win) {
11370+	RGFW_ASSERT(win);
11371+	SetForegroundWindow(win->src.window);
11372+	SetFocus(win->src.window);
11373+}
11374+
11375+void RGFW_window_raise(RGFW_window* win) {
11376+	RGFW_ASSERT(win);
11377+	BringWindowToTop(win->src.window);
11378+	SetWindowPos(win->src.window, HWND_TOP, win->x, win->y, win->w, win->h, SWP_NOSIZE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_FRAMECHANGED);
11379+}
11380+
11381+void RGFW_window_setFullscreen(RGFW_window* win, RGFW_bool fullscreen) {
11382+	RGFW_ASSERT(win != NULL);
11383+
11384+	RGFW_monitor* mon  = RGFW_window_getMonitor(win);
11385+
11386+	if (fullscreen == RGFW_FALSE) {
11387+		RGFW_monitor_setMode(mon, &win->internal.oldMode);
11388+
11389+		RGFW_window_setBorder(win, 1);
11390+
11391+		RECT rect = { 0, 0, win->internal.oldW, win->internal.oldH};
11392+		DWORD style = RGFW_winapi_window_getStyle(win, win->internal.flags);
11393+		DWORD exStyle = RGFW_winapi_window_getExStyle(win, win->internal.flags);
11394+		AdjustWindowRectEx(&rect, style, FALSE, exStyle);
11395+		SetWindowPos(win->src.window, HWND_TOP, win->internal.oldX, win->internal.oldY, rect.right - rect.left, rect.bottom - rect.top, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER);
11396+
11397+		win->internal.flags &= ~(u32)RGFW_windowFullscreen;
11398+		win->x  = win->internal.oldX;
11399+		win->y = win->internal.oldY;
11400+		win->w = win->internal.oldW;
11401+		win->h = win->internal.oldH;
11402+		return;
11403+	}
11404+
11405+	win->internal.oldX = win->x;
11406+	win->internal.oldY = win->y;
11407+	win->internal.oldW = win->w;
11408+	win->internal.oldH = win->h;
11409+	win->internal.oldMode = mon->mode;
11410+	win->internal.flags |= RGFW_windowFullscreen;
11411+
11412+	RGFW_window_setBorder(win, 0);
11413+
11414+    SetWindowPos(win->src.window, HWND_TOPMOST, (i32)mon->x, (i32)mon->y, 0, 0, SWP_NOOWNERZORDER | SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOSIZE);
11415+	win->x = mon->x;
11416+	win->y = mon->y;
11417+
11418+	RGFW_monitor_scaleToWindow(mon, win);
11419+    SetWindowPos(win->src.window, HWND_TOPMOST, 0, 0, (i32)mon->mode.w, (i32)mon->mode.h, SWP_NOOWNERZORDER | SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOMOVE);
11420+	win->w = mon->mode.w;
11421+	win->h = mon->mode.h;
11422+}
11423+
11424+void RGFW_window_maximize(RGFW_window* win) {
11425+	RGFW_ASSERT(win != NULL);
11426+	RGFW_window_hide(win);
11427+	ShowWindow(win->src.window, SW_MAXIMIZE);
11428+	RGFW_window_fetchSize(win, NULL, NULL);
11429+}
11430+
11431+void RGFW_window_minimize(RGFW_window* win) {
11432+	RGFW_ASSERT(win != NULL);
11433+	ShowWindow(win->src.window, SW_MINIMIZE);
11434+}
11435+
11436+void RGFW_window_setFloating(RGFW_window* win, RGFW_bool floating) {
11437+    RGFW_ASSERT(win != NULL);
11438+    if (floating) SetWindowPos(win->src.window, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
11439+    else SetWindowPos(win->src.window, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
11440+}
11441+
11442+void RGFW_window_setOpacity(RGFW_window* win, u8 opacity) {
11443+	SetWindowLong(win->src.window, GWL_EXSTYLE, WS_EX_LAYERED);
11444+	SetLayeredWindowAttributes(win->src.window, 0, opacity, LWA_ALPHA);
11445+}
11446+
11447+void RGFW_window_restore(RGFW_window* win) { RGFW_window_show(win); }
11448+
11449+RGFW_bool RGFW_window_isFloating(RGFW_window* win) {
11450+	return (GetWindowLongPtr(win->src.window, GWL_EXSTYLE) & WS_EX_TOPMOST) != 0;
11451+}
11452+
11453+void RGFW_stopCheckEvents(void) {
11454+	PostMessageW(_RGFW->root->src.window, WM_NULL, 0, 0);
11455+}
11456+
11457+void RGFW_waitForEvent(i32 waitMS) {
11458+	MsgWaitForMultipleObjects(0, NULL, FALSE, (DWORD)waitMS, QS_ALLINPUT);
11459+}
11460+
11461+RGFW_key RGFW_physicalToMappedKey(RGFW_key key) {
11462+    UINT vsc = RGFW_rgfwToApiKey(key);
11463+    BYTE keyboardState[256] = {0};
11464+
11465+    if (!GetKeyboardState(keyboardState))
11466+        return key;
11467+
11468+    UINT vk = MapVirtualKeyW(vsc, MAPVK_VSC_TO_VK);
11469+    HKL layout = GetKeyboardLayout(0);
11470+
11471+    wchar_t charBuffer[4] = {0};
11472+    int result = ToUnicodeEx(vk, vsc, keyboardState, charBuffer, 1, 0, layout);
11473+
11474+    if (result == 1 && charBuffer[0] < 256) {
11475+        return (RGFW_key)charBuffer[0];
11476+	}
11477+
11478+    switch (vk) {
11479+        case VK_F1:  return RGFW_keyF1;
11480+        case VK_F2:  return RGFW_keyF2;
11481+        case VK_F3:  return RGFW_keyF3;
11482+        case VK_F4:  return RGFW_keyF4;
11483+        case VK_F5:  return RGFW_keyF5;
11484+        case VK_F6:  return RGFW_keyF6;
11485+        case VK_F7:  return RGFW_keyF7;
11486+        case VK_F8:  return RGFW_keyF8;
11487+        case VK_F9:  return RGFW_keyF9;
11488+        case VK_F10: return RGFW_keyF10;
11489+        case VK_F11: return RGFW_keyF11;
11490+        case VK_F12: return RGFW_keyF12;
11491+        case VK_F13: return RGFW_keyF13;
11492+        case VK_F14: return RGFW_keyF14;
11493+        case VK_F15: return RGFW_keyF15;
11494+        case VK_F16: return RGFW_keyF16;
11495+        case VK_F17: return RGFW_keyF17;
11496+        case VK_F18: return RGFW_keyF18;
11497+        case VK_F19: return RGFW_keyF19;
11498+        case VK_F20: return RGFW_keyF20;
11499+        case VK_F21: return RGFW_keyF21;
11500+        case VK_F22: return RGFW_keyF22;
11501+        case VK_F23: return RGFW_keyF23;
11502+        case VK_F24: return RGFW_keyF24;
11503+        case VK_LSHIFT:   return RGFW_keyShiftL;
11504+        case VK_RSHIFT:   return RGFW_keyShiftR;
11505+        case VK_LCONTROL: return RGFW_keyControlL;
11506+        case VK_RCONTROL: return RGFW_keyControlR;
11507+        case VK_LMENU:    return RGFW_keyAltL;
11508+        case VK_RMENU:    return RGFW_keyAltR;
11509+        case VK_LWIN:     return RGFW_keySuperL;
11510+        case VK_RWIN:     return RGFW_keySuperR;
11511+        case VK_CAPITAL:  return RGFW_keyCapsLock;
11512+        case VK_NUMLOCK:  return RGFW_keyNumLock;
11513+        case VK_SCROLL:   return RGFW_keyScrollLock;
11514+        case VK_UP:       return RGFW_keyUp;
11515+        case VK_DOWN:     return RGFW_keyDown;
11516+        case VK_LEFT:     return RGFW_keyLeft;
11517+        case VK_RIGHT:    return RGFW_keyRight;
11518+        case VK_HOME:     return RGFW_keyHome;
11519+        case VK_END:      return RGFW_keyEnd;
11520+        case VK_PRIOR:    return RGFW_keyPageUp;
11521+        case VK_NEXT:     return RGFW_keyPageDown;
11522+        case VK_INSERT:   return RGFW_keyInsert;
11523+        case VK_APPS:     return RGFW_keyMenu;
11524+        case VK_ADD:      return RGFW_keyPadPlus;
11525+        case VK_SUBTRACT: return RGFW_keyPadMinus;
11526+        case VK_MULTIPLY: return RGFW_keyPadMultiply;
11527+        case VK_DIVIDE:   return RGFW_keyPadSlash;
11528+        case VK_RETURN:   return RGFW_keyPadReturn;
11529+        case VK_DECIMAL:  return RGFW_keyPadPeriod;
11530+        case VK_NUMPAD0: return RGFW_keyPad0;
11531+        case VK_NUMPAD1: return RGFW_keyPad1;
11532+        case VK_NUMPAD2: return RGFW_keyPad2;
11533+        case VK_NUMPAD3: return RGFW_keyPad3;
11534+        case VK_NUMPAD4: return RGFW_keyPad4;
11535+        case VK_NUMPAD5: return RGFW_keyPad5;
11536+        case VK_NUMPAD6: return RGFW_keyPad6;
11537+        case VK_NUMPAD7: return RGFW_keyPad7;
11538+        case VK_NUMPAD8: return RGFW_keyPad8;
11539+        case VK_NUMPAD9: return RGFW_keyPad9;
11540+        case VK_SNAPSHOT: return RGFW_keyPrintScreen;
11541+        case VK_PAUSE:    return RGFW_keyPause;
11542+        default: return RGFW_keyNULL;
11543+    }
11544+
11545+    return RGFW_keyNULL;
11546+}
11547+
11548+RGFW_bool RGFW_window_fetchSize(RGFW_window* win, i32* w, i32* h) {
11549+    RECT area;
11550+    GetClientRect(win->src.window, &area);
11551+
11552+    win->w = area.right;
11553+    win->h = area.bottom;
11554+
11555+	return RGFW_window_getSize(win, w, h);
11556+}
11557+
11558+void RGFW_pollEvents(void) {
11559+	RGFW_resetPrevState();
11560+    MSG msg;
11561+    while (PeekMessageA(&msg, NULL, 0u, 0u, PM_REMOVE)) {
11562+		TranslateMessage(&msg);
11563+		DispatchMessageA(&msg);
11564+	}
11565+}
11566+
11567+RGFW_bool RGFW_window_isHidden(RGFW_window* win) {
11568+	RGFW_ASSERT(win != NULL);
11569+	return IsWindowVisible(win->src.window) == 0 && !RGFW_window_isMinimized(win);
11570+}
11571+
11572+RGFW_bool RGFW_window_isMinimized(RGFW_window* win) {
11573+	RGFW_ASSERT(win != NULL);
11574+
11575+	#ifndef __cplusplus
11576+	WINDOWPLACEMENT placement = {0};
11577+	#else
11578+	WINDOWPLACEMENT placement = {};
11579+	#endif
11580+	GetWindowPlacement(win->src.window, &placement);
11581+	return placement.showCmd == SW_SHOWMINIMIZED;
11582+}
11583+
11584+RGFW_bool RGFW_window_isMaximized(RGFW_window* win) {
11585+	RGFW_ASSERT(win != NULL);
11586+
11587+	#ifndef __cplusplus
11588+	WINDOWPLACEMENT placement = {0};
11589+	#else
11590+	WINDOWPLACEMENT placement = {};
11591+	#endif
11592+	GetWindowPlacement(win->src.window, &placement);
11593+	return placement.showCmd == SW_SHOWMAXIMIZED || IsZoomed(win->src.window);
11594+}
11595+
11596+RGFW_bool RGFW_monitor_getWorkarea(RGFW_monitor* monitor, i32* x, i32* y, i32* width, i32* height) {
11597+    MONITORINFOEX mi;
11598+	mi.cbSize = sizeof(MONITORINFOEX);
11599+	GetMonitorInfoA(monitor->node->hMonitor, (LPMONITORINFO)&mi);
11600+
11601+    if (x) *x = mi.rcWork.left;
11602+    if (y) *y = mi.rcWork.top;
11603+    if (width) *width = mi.rcWork.right - mi.rcWork.left;
11604+    if (height) *height = mi.rcWork.bottom - mi.rcWork.top;
11605+
11606+	return RGFW_TRUE;
11607+}
11608+
11609+size_t RGFW_monitor_getGammaRampPtr(RGFW_monitor* monitor, RGFW_gammaRamp* ramp) {
11610+    WORD values[3][256];
11611+
11612+    HDC dc = CreateDCW(L"DISPLAY", monitor->node->adapterName, NULL, NULL);
11613+    GetDeviceGammaRamp(dc, values);
11614+    DeleteDC(dc);
11615+
11616+	if (ramp) {
11617+	    memcpy(ramp->red,   values[0], sizeof(values[0]));
11618+		memcpy(ramp->green, values[1], sizeof(values[1]));
11619+	    memcpy(ramp->blue,  values[2], sizeof(values[2]));
11620+	}
11621+
11622+    return sizeof(values[0]) / sizeof(WORD);
11623+}
11624+
11625+RGFW_bool RGFW_monitor_setGammaRamp(RGFW_monitor* monitor, RGFW_gammaRamp* ramp) {
11626+    WORD values[3][256];
11627+    if (ramp->count != 256) {
11628+		RGFW_debugCallback(RGFW_typeError, RGFW_errX11, "Win32: Gamma ramp size must be 256");
11629+        return RGFW_FALSE;
11630+    }
11631+
11632+    memcpy(values[0], ramp->red,   sizeof(values[0]));
11633+    memcpy(values[1], ramp->green, sizeof(values[1]));
11634+    memcpy(values[2], ramp->blue,  sizeof(values[2]));
11635+
11636+    HDC dc = CreateDCW(L"DISPLAY", monitor->node->adapterName, NULL, NULL);
11637+    SetDeviceGammaRamp(dc, values);
11638+    DeleteDC(dc);
11639+	return RGFW_TRUE;
11640+}
11641+
11642+BOOL CALLBACK RGFW_win32_getMonitorHandle(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData);
11643+BOOL CALLBACK RGFW_win32_getMonitorHandle(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) {
11644+	RGFW_UNUSED(hMonitor);
11645+	RGFW_UNUSED(hdcMonitor);
11646+	RGFW_UNUSED(lprcMonitor);
11647+	RGFW_UNUSED(dwData);
11648+
11649+    MONITORINFOEXW mi;
11650+    ZeroMemory(&mi, sizeof(mi));
11651+    mi.cbSize = sizeof(mi);
11652+
11653+    if (GetMonitorInfoW(hMonitor, (MONITORINFO*) &mi)) {
11654+		RGFW_monitorNode* node = (RGFW_monitorNode*)dwData;
11655+        if (wcscmp(mi.szDevice, node->adapterName) == 0) {
11656+            node->hMonitor = hMonitor;
11657+		}
11658+    }
11659+
11660+	return TRUE;
11661+}
11662+
11663+RGFWDEF void RGFW_win32_getMode(DEVMODEW* dm, RGFW_monitorMode* mode);
11664+void RGFW_win32_getMode(DEVMODEW* dm, RGFW_monitorMode* mode) {
11665+	mode->w = (i32)dm->dmPelsWidth;
11666+	mode->h = (i32)dm->dmPelsHeight;
11667+	RGFW_splitBPP(dm->dmBitsPerPel, mode);
11668+
11669+    switch (dm->dmDisplayFrequency) {
11670+		case 119:
11671+		case 59:
11672+		case 29:
11673+			mode->refreshRate = ((float)(dm->dmDisplayFrequency + 1) * 1000.0f) / 1001.f;
11674+			break;
11675+		default:
11676+			mode->refreshRate = (float)dm->dmDisplayFrequency;
11677+			break;
11678+    }
11679+}
11680+
11681+size_t RGFW_monitor_getModesPtr(RGFW_monitor* monitor, RGFW_monitorMode** modes){
11682+	size_t count = 0;
11683+	DWORD modeIndex = 0;
11684+
11685+	for (;;) {
11686+		DEVMODEW dm;
11687+		ZeroMemory(&dm, sizeof(dm));
11688+		dm.dmSize = sizeof(dm);
11689+
11690+		if (!EnumDisplaySettingsW(monitor->node->adapterName, modeIndex, &dm))
11691+			break;
11692+
11693+		if (ChangeDisplaySettingsExW(monitor->node->adapterName, &dm, NULL, CDS_TEST, NULL) != DISP_CHANGE_SUCCESSFUL) {
11694+			continue;
11695+		}
11696+
11697+		modeIndex++;
11698+
11699+		if (dm.dmBitsPerPel < 15)
11700+			continue;
11701+
11702+		if (modes) {
11703+			RGFW_monitorMode mode;
11704+			RGFW_win32_getMode(&dm, &mode);
11705+
11706+			size_t i;
11707+			for (i = 0; i < count;  i++) {
11708+				if (RGFW_monitorModeCompare(&(*modes)[i], &mode, RGFW_monitorAll) == RGFW_TRUE) {
11709+					break;
11710+				}
11711+			}
11712+
11713+			if (i < count) {
11714+				continue;
11715+			}
11716+
11717+			(*modes)[count] = mode;
11718+		}
11719+
11720+		count += 1;
11721+	}
11722+
11723+	return count;
11724+}
11725+
11726+RGFWDEF void RGFW_win32_createMonitor(DISPLAY_DEVICEW* adapter, DISPLAY_DEVICEW* dd);
11727+void RGFW_win32_createMonitor(DISPLAY_DEVICEW* adapter, DISPLAY_DEVICEW* dd) {
11728+	DEVMODEW dm;
11729+	ZeroMemory(&dm, sizeof(dm));
11730+	dm.dmSize = sizeof(dm);
11731+
11732+	if (!EnumDisplaySettingsW(adapter->DeviceName, ENUM_CURRENT_SETTINGS, &dm)) {
11733+		return;
11734+	}
11735+
11736+	RGFW_monitorNode* node = RGFW_monitors_add(NULL);
11737+
11738+	wcscpy(node->adapterName, adapter->DeviceName);
11739+	wcscpy(node->deviceName, dd->DeviceName);
11740+
11741+	RGFW_createUTF8FromWideStringWin32(dd->DeviceString, node->mon.name, sizeof(node->mon.name));
11742+	node->mon.name[sizeof(node->mon.name) - 1] = '\0';
11743+
11744+	RECT rect;
11745+	rect.left = (LONG)dm.dmPosition.x;
11746+	rect.top = (LONG)dm.dmPosition.y;
11747+	rect.right = (LONG)((LONG)dm.dmPosition.x + (LONG)dm.dmPelsWidth);
11748+	rect.bottom = (LONG)((long)dm.dmPosition.y + (LONG)dm.dmPelsHeight);
11749+	EnumDisplayMonitors(NULL, &rect, RGFW_win32_getMonitorHandle, (LPARAM)node);
11750+
11751+	RGFW_win32_getMode(&dm, &node->mon.mode);
11752+
11753+	MONITORINFOEXW monitorInfo;
11754+	monitorInfo.cbSize = sizeof(MONITORINFOEXW);
11755+	GetMonitorInfoW(node->hMonitor, (LPMONITORINFO)&monitorInfo);
11756+
11757+	node->mon.x = monitorInfo.rcMonitor.left;
11758+	node->mon.y = monitorInfo.rcMonitor.top;
11759+
11760+	HDC hdc = CreateDCW(monitorInfo.szDevice, NULL, NULL, NULL);
11761+	/* get pixels per inch */
11762+	float dpiX = (float)GetDeviceCaps(hdc, LOGPIXELSX);
11763+	float dpiY = (float)GetDeviceCaps(hdc, LOGPIXELSX);
11764+
11765+	node->mon.scaleX = dpiX / 96.0f;
11766+	node->mon.scaleY = dpiY / 96.0f;
11767+	node->mon.pixelRatio = dpiX >= 192.0f ? 2.0f : 1.0f;
11768+
11769+	node->mon.physW = (float)GetDeviceCaps(hdc, HORZSIZE) / 25.4f;
11770+	node->mon.physH = (float)GetDeviceCaps(hdc, VERTSIZE) / 25.4f;
11771+	DeleteDC(hdc);
11772+
11773+#ifndef RGFW_NO_DPI
11774+	RGFW_LOAD_LIBRARY(RGFW_Shcore_dll, "shcore.dll");
11775+	RGFW_PROC_DEF(RGFW_Shcore_dll, GetDpiForMonitor);
11776+
11777+	if (GetDpiForMonitor != NULL) {
11778+		u32 x, y;
11779+		GetDpiForMonitor(node->hMonitor, MDT_EFFECTIVE_DPI, &x, &y);
11780+		node->mon.scaleX = (float) (x) / (float) 96.0f;
11781+		node->mon.scaleY = (float) (y) / (float) 96.0f;
11782+		node->mon.pixelRatio = dpiX >= 192.0f ? 2.0f : 1.0f;
11783+	}
11784+#endif
11785+
11786+	if (monitorInfo.dwFlags & MONITORINFOF_PRIMARY) {
11787+		_RGFW->monitors.primary = node;
11788+	}
11789+
11790+	RGFW_monitorCallback(_RGFW->root, &node->mon, RGFW_TRUE);
11791+}
11792+
11793+void RGFW_pollMonitors(void) {
11794+	for (RGFW_monitorNode* node = _RGFW->monitors.list.head; node; node = node->next) {
11795+		node->disconnected = RGFW_TRUE;
11796+	}
11797+
11798+	/* loop through display adapters (GPU) */
11799+	DISPLAY_DEVICEW adapter;
11800+	DWORD adapterNum;
11801+	for (adapterNum = 0; ; adapterNum++) {
11802+        ZeroMemory(&adapter, sizeof(adapter));
11803+		adapter.cb = sizeof(adapter);
11804+
11805+		if (!EnumDisplayDevicesW(NULL, adapterNum, &adapter, 0))
11806+			break;
11807+
11808+		if (!(adapter.StateFlags & DISPLAY_DEVICE_ACTIVE))
11809+			continue;
11810+
11811+		DISPLAY_DEVICEW dd;
11812+		dd.cb = sizeof(dd);
11813+
11814+		/* loop through display devices (monitors) */
11815+		DWORD deviceNum;
11816+		for (deviceNum = 0; ; deviceNum++) {
11817+            ZeroMemory(&dd, sizeof(dd));
11818+            dd.cb = sizeof(dd);
11819+
11820+			if (!EnumDisplayDevicesW(adapter.DeviceName, deviceNum, &dd, 0))
11821+				break;
11822+
11823+			if (!(dd.StateFlags & DISPLAY_DEVICE_ACTIVE))
11824+				continue;
11825+
11826+			RGFW_monitorNode* node;
11827+			for (node = _RGFW->monitors.list.head; node; node = node->next) {
11828+				if (node->disconnected == RGFW_TRUE && wcscmp(node->deviceName, dd.DeviceName) == 0) {
11829+					node->disconnected = RGFW_FALSE;
11830+					EnumDisplayMonitors(NULL, NULL, RGFW_win32_getMonitorHandle, (LPARAM) &node->mon);
11831+					break;
11832+				}
11833+			}
11834+
11835+			if (node) {
11836+				continue;
11837+			}
11838+
11839+			RGFW_win32_createMonitor(&adapter, &dd);
11840+		}
11841+
11842+		/* if there are no display devices, just use the monitor directly (hack borrowed from GLFW (I'm not giving it back)) */
11843+        if (deviceNum == 0) {
11844+   			RGFW_monitorNode* node;
11845+			for (node = _RGFW->monitors.list.head; node; node = node->next) {
11846+				if (node->disconnected == RGFW_TRUE && wcscmp(node->adapterName, adapter.DeviceName) == 0) {
11847+					node->disconnected = RGFW_FALSE;
11848+					break;
11849+				}
11850+			}
11851+
11852+			if (node) {
11853+				continue;
11854+			}
11855+
11856+			RGFW_win32_createMonitor(&adapter, NULL);
11857+        }
11858+	}
11859+
11860+	RGFW_monitors_refresh();
11861+}
11862+
11863+RGFW_monitor* RGFW_window_getMonitor(RGFW_window* win) {
11864+	HMONITOR src = MonitorFromWindow(win->src.window, MONITOR_DEFAULTTOPRIMARY);
11865+	RGFW_monitorNode* node = _RGFW->monitors.list.head;
11866+
11867+	for (node = _RGFW->monitors.list.head; node; node = node->next) {
11868+		if (node->hMonitor == src) {
11869+			return &node->mon;
11870+		}
11871+	}
11872+
11873+	return RGFW_getPrimaryMonitor();
11874+}
11875+
11876+RGFW_bool RGFW_monitor_setMode(RGFW_monitor* mon, RGFW_monitorMode* mode) {
11877+	DEVMODEW dm;
11878+	ZeroMemory(&dm, sizeof(dm));
11879+	dm.dmSize = sizeof(dm);
11880+
11881+	dm.dmFields |= DM_PELSWIDTH | DM_PELSHEIGHT;
11882+	dm.dmPelsWidth = (u32)mode->w;
11883+	dm.dmPelsHeight = (u32)mode->h;
11884+
11885+	dm.dmFields |= DM_DISPLAYFREQUENCY;
11886+	dm.dmDisplayFrequency = (DWORD)mode->refreshRate;
11887+
11888+	dm.dmFields |= DM_BITSPERPEL;
11889+	dm.dmBitsPerPel = (DWORD)(mode->red + mode->green + mode->blue);
11890+
11891+	if (ChangeDisplaySettingsExW(mon->node->adapterName, &dm, NULL, CDS_TEST, NULL) == DISP_CHANGE_SUCCESSFUL) {
11892+		if (ChangeDisplaySettingsExW(mon->node->adapterName, &dm, NULL, CDS_UPDATEREGISTRY, NULL) == DISP_CHANGE_SUCCESSFUL) {
11893+			RGFW_win32_getMode(&dm, &mon->mode);
11894+			return RGFW_TRUE;
11895+		}
11896+		return RGFW_FALSE;
11897+	} else return RGFW_FALSE;
11898+}
11899+
11900+RGFW_bool RGFW_monitor_requestMode(RGFW_monitor* mon, RGFW_monitorMode* mode, RGFW_modeRequest request) {
11901+HMONITOR src = mon->node->hMonitor;
11902+
11903+	MONITORINFOEX  monitorInfo;
11904+	monitorInfo.cbSize = sizeof(MONITORINFOEX);
11905+	GetMonitorInfoA(src, (LPMONITORINFO)&monitorInfo);
11906+
11907+	DEVMODEW dm;
11908+	ZeroMemory(&dm, sizeof(dm));
11909+	dm.dmSize = sizeof(dm);
11910+
11911+	DWORD index = 0;
11912+
11913+	for (;;) {
11914+		if (EnumDisplaySettingsW(mon->node->adapterName, index, &dm) == 0) {
11915+			break;
11916+		}
11917+
11918+		index += 1;
11919+
11920+		if (request & RGFW_monitorScale) {
11921+			dm.dmFields |= DM_PELSWIDTH | DM_PELSHEIGHT;
11922+			dm.dmPelsWidth = (u32)mode->w;
11923+			dm.dmPelsHeight = (u32)mode->h;
11924+		}
11925+
11926+		if (request & RGFW_monitorRefresh) {
11927+			dm.dmFields |= DM_DISPLAYFREQUENCY;
11928+			dm.dmDisplayFrequency = (DWORD)mode->refreshRate;
11929+		}
11930+
11931+		if (request & RGFW_monitorRGB) {
11932+			dm.dmFields |= DM_BITSPERPEL;
11933+			dm.dmBitsPerPel = (DWORD)(mode->red + mode->green + mode->blue);
11934+		}
11935+
11936+		if (ChangeDisplaySettingsExW(mon->node->adapterName, &dm, NULL, CDS_TEST, NULL) == DISP_CHANGE_SUCCESSFUL) {
11937+			if (ChangeDisplaySettingsExW(mon->node->adapterName, &dm, NULL, CDS_UPDATEREGISTRY, NULL) == DISP_CHANGE_SUCCESSFUL) {
11938+				RGFW_win32_getMode(&dm, &mon->mode);
11939+				return RGFW_TRUE;
11940+			}
11941+			return RGFW_FALSE;
11942+		}
11943+	}
11944+
11945+	return RGFW_FALSE;
11946+}
11947+
11948+HICON RGFW_loadHandleImage(u8* data, i32 w, i32 h, RGFW_format format, BOOL icon);
11949+HICON RGFW_loadHandleImage(u8* data, i32 w, i32 h, RGFW_format format, BOOL icon) {
11950+	BITMAPV5HEADER bi;
11951+	ZeroMemory(&bi, sizeof(bi));
11952+	bi.bV5Size = sizeof(bi);
11953+	bi.bV5Width = (i32)w;
11954+	bi.bV5Height = -((LONG) h);
11955+	bi.bV5Planes = 1;
11956+	bi.bV5BitCount = (WORD)32;
11957+	bi.bV5Compression = BI_RGB;
11958+	HDC dc = GetDC(NULL);
11959+	u8* target = NULL;
11960+
11961+	HBITMAP color = CreateDIBSection(dc,
11962+		(BITMAPINFO*) &bi, DIB_RGB_COLORS, (void**) &target,
11963+		NULL, (DWORD) 0);
11964+
11965+	RGFW_copyImageData(target, w, h, RGFW_formatBGRA8, data, format, NULL);
11966+    ReleaseDC(NULL, dc);
11967+
11968+	HBITMAP mask = CreateBitmap((i32)w, (i32)h, 1, 1, NULL);
11969+
11970+	ICONINFO ii;
11971+	ZeroMemory(&ii, sizeof(ii));
11972+	ii.fIcon = icon;
11973+	ii.xHotspot = (u32)w / 2;
11974+	ii.yHotspot = (u32)h / 2;
11975+	ii.hbmMask = mask;
11976+	ii.hbmColor = color;
11977+
11978+	HICON handle = CreateIconIndirect(&ii);
11979+
11980+	DeleteObject(color);
11981+	DeleteObject(mask);
11982+
11983+	return handle;
11984+}
11985+
11986+RGFW_mouse* RGFW_createMouseStandard(RGFW_mouseIcon mouse) {
11987+	u32 mouseIcon = 0;
11988+
11989+    switch (mouse) {
11990+		case RGFW_mouseNormal: mouseIcon = OCR_NORMAL; break;
11991+		case RGFW_mouseArrow: mouseIcon = OCR_NORMAL; break;
11992+		case RGFW_mouseIbeam: mouseIcon = OCR_IBEAM; break;
11993+		case RGFW_mouseWait: mouseIcon = OCR_WAIT; break;
11994+		case RGFW_mouseCrosshair: mouseIcon = OCR_CROSS; break;
11995+		case RGFW_mouseProgress: mouseIcon = OCR_APPSTARTING; break;
11996+		case RGFW_mouseResizeNWSE: mouseIcon = OCR_SIZENWSE; break;
11997+		case RGFW_mouseResizeNESW: mouseIcon = OCR_SIZENESW; break;
11998+		case RGFW_mouseResizeEW: mouseIcon = OCR_SIZEWE; break;
11999+		case RGFW_mouseResizeNS: mouseIcon = OCR_SIZENS; break;
12000+		case RGFW_mouseResizeAll: mouseIcon = OCR_SIZEALL; break;
12001+		case RGFW_mouseNotAllowed: mouseIcon = OCR_NO; break;
12002+		case RGFW_mousePointingHand: mouseIcon = OCR_HAND; break;
12003+		case RGFW_mouseResizeNW: mouseIcon = OCR_SIZENWSE; break;
12004+		case RGFW_mouseResizeN: mouseIcon = OCR_SIZENS; break;
12005+		case RGFW_mouseResizeNE: mouseIcon = OCR_SIZENESW; break;
12006+		case RGFW_mouseResizeE: mouseIcon = OCR_SIZEWE; break;
12007+		case RGFW_mouseResizeSE: mouseIcon = OCR_SIZENWSE; break;
12008+		case RGFW_mouseResizeS: mouseIcon = OCR_SIZENS; break;
12009+		case RGFW_mouseResizeSW: mouseIcon = OCR_SIZENESW; break;
12010+		case RGFW_mouseResizeW: mouseIcon = OCR_SIZEWE; break;
12011+		default: return NULL;
12012+    }
12013+
12014+	char* icon = MAKEINTRESOURCEA(mouseIcon);
12015+	return LoadCursorA(NULL, icon);
12016+}
12017+
12018+RGFW_mouse* RGFW_createMouse(u8* data, i32 w, i32 h, RGFW_format format) {
12019+	HCURSOR cursor = (HCURSOR) RGFW_loadHandleImage(data, w, h, format, FALSE);
12020+	return cursor;
12021+}
12022+
12023+RGFW_bool RGFW_window_setMousePlatform(RGFW_window* win, RGFW_mouse* mouse) {
12024+	RGFW_ASSERT(win && mouse);
12025+	SetClassLongPtrA(win->src.window, GCLP_HCURSOR, (LPARAM) mouse);
12026+	SetCursor((HCURSOR)mouse);
12027+
12028+	return RGFW_FALSE;
12029+}
12030+
12031+void RGFW_freeMouse(RGFW_mouse* mouse) {
12032+	RGFW_ASSERT(mouse);
12033+	DestroyCursor((HCURSOR)mouse);
12034+}
12035+
12036+void RGFW_window_hide(RGFW_window* win) {
12037+	ShowWindow(win->src.window, SW_HIDE);
12038+}
12039+
12040+void RGFW_window_show(RGFW_window* win) {
12041+	if (win->internal.flags & RGFW_windowFocusOnShow) RGFW_window_focus(win);
12042+	ShowWindow(win->src.window, SW_RESTORE);
12043+}
12044+
12045+void RGFW_window_flash(RGFW_window* win, RGFW_flashRequest request) {
12046+	if (RGFW_window_isInFocus(win) && request) {
12047+		return;
12048+	}
12049+
12050+	FLASHWINFO desc;
12051+	RGFW_MEMZERO(&desc, sizeof(desc));
12052+
12053+    desc.cbSize = sizeof(desc);
12054+    desc.hwnd = win->src.window;
12055+
12056+    switch (request) {
12057+		case RGFW_flashCancel:
12058+			desc.dwFlags = FLASHW_STOP;
12059+			break;
12060+		case RGFW_flashBriefly:
12061+			desc.dwFlags = FLASHW_TRAY;
12062+			desc.uCount = 1;
12063+			break;
12064+		case RGFW_flashUntilFocused:
12065+			desc.dwFlags = (FLASHW_TRAY | FLASHW_TIMERNOFG);
12066+			break;
12067+		default: break;
12068+    }
12069+
12070+    FlashWindowEx(&desc);
12071+}
12072+
12073+#define RGFW_FREE_LIBRARY(x) if (x != NULL) FreeLibrary(x); x = NULL;
12074+void RGFW_deinitPlatform(void) {
12075+    #ifndef RGFW_NO_DPI
12076+        RGFW_FREE_LIBRARY(RGFW_Shcore_dll);
12077+    #endif
12078+
12079+    #ifndef RGFW_NO_WINMM
12080+        timeEndPeriod(1);
12081+        #ifndef RGFW_NO_LOAD_WINMM
12082+            RGFW_FREE_LIBRARY(RGFW_winmm_dll);
12083+        #endif
12084+    #endif
12085+
12086+    RGFW_FREE_LIBRARY(RGFW_wgl_dll);
12087+
12088+    RGFW_freeMouse(_RGFW->hiddenMouse);
12089+}
12090+
12091+
12092+void RGFW_window_closePlatform(RGFW_window* win) {
12093+	RemovePropW(win->src.window, L"RGFW");
12094+	ReleaseDC(win->src.window, win->src.hdc); /*!< delete device context */
12095+	DestroyWindow(win->src.window); /*!< delete window */
12096+
12097+	if (win->src.hIconSmall) DestroyIcon(win->src.hIconSmall);
12098+	if (win->src.hIconBig) DestroyIcon(win->src.hIconBig);
12099+}
12100+
12101+void RGFW_window_move(RGFW_window* win, i32 x, i32 y) {
12102+	RGFW_ASSERT(win != NULL);
12103+
12104+	win->x = x;
12105+	win->y = y;
12106+	SetWindowPos(win->src.window, HWND_TOP, win->x, win->y, 0, 0, SWP_NOSIZE);
12107+}
12108+
12109+void RGFW_window_resize(RGFW_window* win, i32 w, i32 h) {
12110+	RGFW_ASSERT(win != NULL);
12111+
12112+	win->w = w;
12113+	win->h = h;
12114+	RECT rect = { 0, 0, w, h};
12115+	DWORD style = RGFW_winapi_window_getStyle(win, win->internal.flags);
12116+	DWORD exStyle = RGFW_winapi_window_getExStyle(win, win->internal.flags);
12117+	AdjustWindowRectEx(&rect, style, FALSE, exStyle);
12118+	SetWindowPos(win->src.window, HWND_TOP, 0, 0, rect.right - rect.left, rect.bottom - rect.top, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOZORDER);
12119+}
12120+
12121+void RGFW_window_setName(RGFW_window* win, const char* name) {
12122+	RGFW_ASSERT(win != NULL);
12123+	if (name == NULL) name = "\0";
12124+
12125+	wchar_t wide_name[256];
12126+	MultiByteToWideChar(CP_UTF8, 0, name, -1, wide_name, 256);
12127+	SetWindowTextW(win->src.window, wide_name);
12128+}
12129+
12130+#ifndef RGFW_NO_PASSTHROUGH
12131+void RGFW_window_setMousePassthrough(RGFW_window* win, RGFW_bool passthrough) {
12132+	RGFW_ASSERT(win != NULL);
12133+	COLORREF key = 0;
12134+	BYTE alpha = 0;
12135+	DWORD flags = 0;
12136+	i32 exStyle = GetWindowLongW(win->src.window, GWL_EXSTYLE);
12137+
12138+	if (exStyle & WS_EX_LAYERED)
12139+		GetLayeredWindowAttributes(win->src.window, &key, &alpha, &flags);
12140+
12141+	if (passthrough)
12142+		exStyle |= (WS_EX_TRANSPARENT | WS_EX_LAYERED);
12143+	else {
12144+		exStyle &= ~WS_EX_TRANSPARENT;
12145+		if (exStyle & WS_EX_LAYERED && !(flags & LWA_ALPHA))
12146+			exStyle &= ~WS_EX_LAYERED;
12147+	}
12148+
12149+	SetWindowLongW(win->src.window, GWL_EXSTYLE, exStyle);
12150+
12151+	if (passthrough)
12152+		SetLayeredWindowAttributes(win->src.window, key, alpha, flags);
12153+}
12154+#endif
12155+
12156+RGFW_bool RGFW_window_setIconEx(RGFW_window* win, u8* data, i32 w, i32 h, RGFW_format format, RGFW_icon type) {
12157+	RGFW_ASSERT(win != NULL);
12158+	#ifndef RGFW_WIN95
12159+		if (win->src.hIconSmall && (type & RGFW_iconWindow)) DestroyIcon(win->src.hIconSmall);
12160+		if (win->src.hIconBig && (type & RGFW_iconTaskbar)) DestroyIcon(win->src.hIconBig);
12161+
12162+		if (data == NULL) {
12163+			HICON defaultIcon = LoadIcon(NULL, IDI_APPLICATION);
12164+			if (type & RGFW_iconWindow)
12165+				SendMessage(win->src.window, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM)defaultIcon);
12166+			if (type & RGFW_iconTaskbar)
12167+				SendMessage(win->src.window, WM_SETICON, (WPARAM)ICON_BIG, (LPARAM)defaultIcon);
12168+			return RGFW_TRUE;
12169+		}
12170+
12171+		if (type & RGFW_iconWindow) {
12172+			win->src.hIconSmall = RGFW_loadHandleImage(data, w, h, format, TRUE);
12173+			SendMessage(win->src.window, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM)win->src.hIconSmall);
12174+		}
12175+		if (type & RGFW_iconTaskbar) {
12176+			win->src.hIconBig = RGFW_loadHandleImage(data, w, h, format, TRUE);
12177+			SendMessage(win->src.window, WM_SETICON, (WPARAM)ICON_BIG, (LPARAM)win->src.hIconBig);
12178+		}
12179+		return RGFW_TRUE;
12180+	#else
12181+		RGFW_UNUSED(img);
12182+		RGFW_UNUSED(type);
12183+		return RGFW_FALSE;
12184+	#endif
12185+}
12186+
12187+RGFW_ssize_t RGFW_readClipboardPtr(char* str, size_t strCapacity) {
12188+	/* Open the clipboard */
12189+	if (OpenClipboard(NULL) == 0)
12190+		return -1;
12191+
12192+	/* Get the clipboard data as a Unicode string */
12193+	HANDLE hData = GetClipboardData(CF_UNICODETEXT);
12194+	if (hData == NULL) {
12195+		CloseClipboard();
12196+		return -1;
12197+	}
12198+
12199+	wchar_t* wstr = (wchar_t*) GlobalLock(hData);
12200+
12201+	RGFW_ssize_t textLen = 0;
12202+
12203+	{
12204+		setlocale(LC_ALL, "en_US.UTF-8");
12205+
12206+		textLen = (RGFW_ssize_t)wcstombs(NULL, wstr, 0) + 1;
12207+		if (str != NULL && (RGFW_ssize_t)strCapacity <= textLen - 1)
12208+			textLen = 0;
12209+
12210+		if (str != NULL && textLen) {
12211+			if (textLen > 1)
12212+				wcstombs(str, wstr, (size_t)(textLen));
12213+
12214+			str[textLen - 1] = '\0';
12215+		}
12216+	}
12217+
12218+	/* Release the clipboard data */
12219+	GlobalUnlock(hData);
12220+	CloseClipboard();
12221+
12222+	return textLen;
12223+}
12224+
12225+void RGFW_writeClipboard(const char* text, u32 textLen) {
12226+	HANDLE object;
12227+	WCHAR* buffer;
12228+
12229+	object = GlobalAlloc(GMEM_MOVEABLE, (1 + textLen) * sizeof(WCHAR));
12230+	if (!object)
12231+		return;
12232+
12233+	buffer = (WCHAR*) GlobalLock(object);
12234+	if (!buffer) {
12235+		GlobalFree(object);
12236+		return;
12237+	}
12238+
12239+	MultiByteToWideChar(CP_UTF8, 0, text, -1, buffer, (i32)textLen);
12240+	GlobalUnlock(object);
12241+
12242+	if (!OpenClipboard(_RGFW->root->src.window)) {
12243+		GlobalFree(object);
12244+		return;
12245+	}
12246+
12247+	EmptyClipboard();
12248+	SetClipboardData(CF_UNICODETEXT, object);
12249+	CloseClipboard();
12250+}
12251+
12252+void RGFW_window_moveMouse(RGFW_window* win, i32 x, i32 y) {
12253+	RGFW_ASSERT(win != NULL);
12254+	win->internal.lastMouseX = x - win->x;
12255+	win->internal.lastMouseY = y - win->y;
12256+	SetCursorPos(x, y);
12257+}
12258+
12259+#ifdef RGFW_OPENGL
12260+RGFW_bool RGFW_extensionSupportedPlatform_OpenGL(const char * extension, size_t len) {
12261+	const char* extensions = NULL;
12262+
12263+    RGFW_proc proc = RGFW_getProcAddress_OpenGL("wglGetExtensionsStringARB");
12264+    RGFW_proc proc2 = RGFW_getProcAddress_OpenGL("wglGetExtensionsStringEXT");
12265+
12266+    if (proc)
12267+        extensions = ((const char* (*)(HDC))proc)(wglGetCurrentDC());
12268+    else if (proc2)
12269+        extensions = ((const char*(*)(void))proc2)();
12270+    return extensions != NULL && RGFW_extensionSupportedStr(extensions, extension, len);
12271+}
12272+
12273+RGFW_proc RGFW_getProcAddress_OpenGL(const char* procname) {
12274+    RGFW_proc proc = (RGFW_proc)wglGetProcAddress(procname);
12275+    if (proc)
12276+        return proc;
12277+
12278+    return (RGFW_proc) GetProcAddress(RGFW_wgl_dll, procname);
12279+}
12280+
12281+void RGFW_win32_loadOpenGLFuncs(HWND dummyWin) {
12282+     if (wglSwapIntervalEXT != NULL && wglChoosePixelFormatARB != NULL && wglChoosePixelFormatARB != NULL)
12283+		return;
12284+
12285+	HDC dummy_dc = GetDC(dummyWin);
12286+	u32 pfd_flags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
12287+
12288+	PIXELFORMATDESCRIPTOR pfd = {sizeof(pfd), 1, pfd_flags, PFD_TYPE_RGBA, 32, 8, PFD_MAIN_PLANE, 32, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 32, 8, 0, PFD_MAIN_PLANE, 0, 0, 0, 0};
12289+
12290+	int dummy_pixel_format = ChoosePixelFormat(dummy_dc, &pfd);
12291+	SetPixelFormat(dummy_dc, dummy_pixel_format, &pfd);
12292+
12293+	HGLRC dummy_context = wglCreateContext(dummy_dc);
12294+
12295+	HGLRC cur = wglGetCurrentContext();
12296+	wglMakeCurrent(dummy_dc, dummy_context);
12297+
12298+	wglCreateContextAttribsARB = ((PFNWGLCREATECONTEXTATTRIBSARBPROC(WINAPI *)(const char*)) wglGetProcAddress)("wglCreateContextAttribsARB");
12299+	wglChoosePixelFormatARB = ((PFNWGLCHOOSEPIXELFORMATARBPROC(WINAPI *)(const char*)) wglGetProcAddress)("wglChoosePixelFormatARB");
12300+
12301+    wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)(RGFW_proc)wglGetProcAddress("wglSwapIntervalEXT");
12302+    if (wglSwapIntervalEXT == NULL) {
12303+        RGFW_debugCallback(RGFW_typeError, RGFW_errOpenGLContext,  "Failed to load swap interval function");
12304+    }
12305+
12306+	wglMakeCurrent(dummy_dc, cur);
12307+	wglDeleteContext(dummy_context);
12308+	ReleaseDC(dummyWin, dummy_dc);
12309+}
12310+
12311+#define WGL_ACCELERATION_ARB             0x2003
12312+#define WGL_FULL_ACCELERATION_ARB        0x2027
12313+#define WGL_DRAW_TO_WINDOW_ARB           0x2001
12314+#define WGL_PIXEL_TYPE_ARB               0x2013
12315+#define WGL_TYPE_RGBA_ARB                0x202b
12316+#define WGL_SUPPORT_OPENGL_ARB           0x2010
12317+#define WGL_COLOR_BITS_ARB               0x2014
12318+#define WGL_DOUBLE_BUFFER_ARB            0x2011
12319+#define WGL_ALPHA_BITS_ARB               0x201b
12320+#define WGL_DEPTH_BITS_ARB               0x2022
12321+#define WGL_STENCIL_BITS_ARB             0x2023
12322+#define WGL_STEREO_ARB                  0x2012
12323+#define WGL_AUX_BUFFERS_ARB              0x2024
12324+#define WGL_RED_BITS_ARB                 0x2015
12325+#define WGL_GREEN_BITS_ARB               0x2017
12326+#define WGL_BLUE_BITS_ARB                0x2019
12327+#define WGL_ACCUM_RED_BITS_ARB           0x201e
12328+#define WGL_ACCUM_GREEN_BITS_ARB         0x201f
12329+#define WGL_ACCUM_BLUE_BITS_ARB          0x2020
12330+#define WGL_ACCUM_ALPHA_BITS_ARB         0x2021
12331+#define WGL_COLORSPACE_SRGB_EXT          0x3089
12332+#define WGL_CONTEXT_OPENGL_NO_ERROR_ARB  0x31b3
12333+#define WGL_CONTEXT_RELEASE_BEHAVIOR_ARB         0x2097
12334+#define WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB    0x0000
12335+#define WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB   0x2098
12336+#define WGL_CONTEXT_FLAGS_ARB            0x2094
12337+#define WGL_ACCESS_READ_WRITE_NV         0x00000001
12338+#define WGL_COVERAGE_SAMPLES_NV          0x2042
12339+#define WGL_CONTEXT_ES_PROFILE_BIT_EXT   0x00000004
12340+#define WGL_CONTEXT_PROFILE_MASK_ARB               0x9126
12341+#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB            0x00000001
12342+#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB   0x00000002
12343+#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
12344+#define WGL_CONTEXT_MAJOR_VERSION_ARB               0x2091
12345+#define WGL_CONTEXT_MINOR_VERSION_ARB               0x2092
12346+#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB             0x20A9
12347+#define WGL_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097
12348+#define WGL_CONTEXT_DEBUG_BIT_ARB 0x00000001
12349+#define WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004
12350+
12351+RGFW_bool RGFW_window_createContextPtr_OpenGL(RGFW_window* win, RGFW_glContext* ctx, RGFW_glHints* hints) {
12352+	const char flushControl[] = "WGL_ARB_context_flush_control";
12353+	const char noError[] = "WGL_ARB_create_context_no_error";
12354+	const char robustness[] = "WGL_ARB_create_context_robustness";
12355+
12356+	win->src.ctx.native = ctx;
12357+	win->src.gfxType = RGFW_gfxNativeOpenGL;
12358+
12359+	PIXELFORMATDESCRIPTOR pfd;
12360+	pfd.nSize        = sizeof(PIXELFORMATDESCRIPTOR);
12361+	pfd.nVersion     = 1;
12362+	pfd.dwFlags      = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
12363+	pfd.iPixelType   = PFD_TYPE_RGBA;
12364+	pfd.iLayerType   = PFD_MAIN_PLANE;
12365+	pfd.cColorBits   = 32;
12366+	pfd.cAlphaBits   = 8;
12367+	pfd.cDepthBits   = 24;
12368+	pfd.cStencilBits = (BYTE)hints->stencil;
12369+	pfd.cAuxBuffers  = (BYTE)hints->auxBuffers;
12370+	if (hints->stereo) pfd.dwFlags |= PFD_STEREO;
12371+
12372+	/* try to create the pixel format we want for OpenGL and then try to create an OpenGL context for the specified version */
12373+	if (hints->renderer == RGFW_glSoftware)
12374+		pfd.dwFlags |= PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED;
12375+
12376+	/* get pixel format, default to a basic pixel format */
12377+	int pixel_format = ChoosePixelFormat(win->src.hdc, &pfd);
12378+	if (wglChoosePixelFormatARB != NULL) {
12379+		i32 pixel_format_attribs[50];
12380+		RGFW_attribStack stack;
12381+		RGFW_attribStack_init(&stack, pixel_format_attribs, 50);
12382+
12383+		RGFW_attribStack_pushAttribs(&stack, WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB);
12384+		RGFW_attribStack_pushAttribs(&stack, WGL_DRAW_TO_WINDOW_ARB, 1);
12385+		RGFW_attribStack_pushAttribs(&stack, WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB);
12386+		RGFW_attribStack_pushAttribs(&stack, WGL_SUPPORT_OPENGL_ARB, 1);
12387+		RGFW_attribStack_pushAttribs(&stack, WGL_COLOR_BITS_ARB, 32);
12388+		RGFW_attribStack_pushAttribs(&stack, WGL_DOUBLE_BUFFER_ARB, 1);
12389+		RGFW_attribStack_pushAttribs(&stack, WGL_ALPHA_BITS_ARB, hints->alpha);
12390+		RGFW_attribStack_pushAttribs(&stack, WGL_DEPTH_BITS_ARB, hints->depth);
12391+		RGFW_attribStack_pushAttribs(&stack, WGL_STENCIL_BITS_ARB, hints->stencil);
12392+		RGFW_attribStack_pushAttribs(&stack, WGL_STEREO_ARB, hints->stereo);
12393+		RGFW_attribStack_pushAttribs(&stack, WGL_AUX_BUFFERS_ARB, hints->auxBuffers);
12394+		RGFW_attribStack_pushAttribs(&stack, WGL_RED_BITS_ARB, hints->red);
12395+		RGFW_attribStack_pushAttribs(&stack, WGL_GREEN_BITS_ARB, hints->blue);
12396+		RGFW_attribStack_pushAttribs(&stack, WGL_BLUE_BITS_ARB, hints->green);
12397+		RGFW_attribStack_pushAttribs(&stack, WGL_ACCUM_RED_BITS_ARB, hints->accumRed);
12398+		RGFW_attribStack_pushAttribs(&stack, WGL_ACCUM_GREEN_BITS_ARB, hints->accumGreen);
12399+		RGFW_attribStack_pushAttribs(&stack, WGL_ACCUM_BLUE_BITS_ARB, hints->accumBlue);
12400+		RGFW_attribStack_pushAttribs(&stack, WGL_ACCUM_ALPHA_BITS_ARB, hints->accumAlpha);
12401+
12402+		if(hints->sRGB) {
12403+			if (hints->profile != RGFW_glES)
12404+				RGFW_attribStack_pushAttribs(&stack, WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB, 1);
12405+			else
12406+				RGFW_attribStack_pushAttribs(&stack, WGL_COLORSPACE_SRGB_EXT, hints->sRGB);
12407+		}
12408+
12409+		RGFW_attribStack_pushAttribs(&stack, WGL_COVERAGE_SAMPLES_NV, hints->samples);
12410+
12411+		RGFW_attribStack_pushAttribs(&stack, 0, 0);
12412+
12413+		int new_pixel_format;
12414+		UINT num_formats;
12415+		wglChoosePixelFormatARB(win->src.hdc, pixel_format_attribs, 0, 1, &new_pixel_format, &num_formats);
12416+		if (!num_formats)
12417+			RGFW_debugCallback(RGFW_typeError, RGFW_errOpenGLContext, "Failed to create a pixel format for WGL");
12418+		else pixel_format = new_pixel_format;
12419+	}
12420+
12421+	PIXELFORMATDESCRIPTOR suggested;
12422+	if (!DescribePixelFormat(win->src.hdc, pixel_format, sizeof(suggested), &suggested) ||
12423+		!SetPixelFormat(win->src.hdc, pixel_format, &pfd))
12424+			RGFW_debugCallback(RGFW_typeError, RGFW_errOpenGLContext, "Failed to set the WGL pixel format");
12425+
12426+	if (wglCreateContextAttribsARB != NULL) {
12427+		/* create OpenGL/WGL context for the specified version */
12428+		i32 attribs[40];
12429+		RGFW_attribStack stack;
12430+		RGFW_attribStack_init(&stack, attribs, 50);
12431+
12432+
12433+		i32 mask = 0;
12434+		switch (hints->profile) {
12435+			case RGFW_glES: mask |= WGL_CONTEXT_ES_PROFILE_BIT_EXT; break;
12436+			case RGFW_glCompatibility: mask |= WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; break;
12437+			case RGFW_glForwardCompatibility: mask |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; break;
12438+			case RGFW_glCore: mask |= WGL_CONTEXT_CORE_PROFILE_BIT_ARB; break;
12439+			default: mask |= WGL_CONTEXT_CORE_PROFILE_BIT_ARB; break;
12440+		}
12441+
12442+		RGFW_attribStack_pushAttribs(&stack, WGL_CONTEXT_PROFILE_MASK_ARB, mask);
12443+
12444+		if (hints->minor || hints->major) {
12445+			RGFW_attribStack_pushAttribs(&stack, WGL_CONTEXT_MAJOR_VERSION_ARB, hints->major);
12446+			RGFW_attribStack_pushAttribs(&stack, WGL_CONTEXT_MINOR_VERSION_ARB, hints->minor);
12447+		}
12448+
12449+		if (RGFW_extensionSupportedPlatform_OpenGL(noError, sizeof(noError)))
12450+			RGFW_attribStack_pushAttribs(&stack, WGL_CONTEXT_OPENGL_NO_ERROR_ARB, hints->noError);
12451+
12452+		if (RGFW_extensionSupportedPlatform_OpenGL(flushControl, sizeof(flushControl))) {
12453+			if (hints->releaseBehavior == RGFW_glReleaseFlush) {
12454+				RGFW_attribStack_pushAttribs(&stack, WGL_CONTEXT_RELEASE_BEHAVIOR_ARB, WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB); /* WGL_CONTEXT_RELEASE_BEHAVIOR_ARB */
12455+			} else if (hints->releaseBehavior == RGFW_glReleaseNone) {
12456+				RGFW_attribStack_pushAttribs(&stack, WGL_CONTEXT_RELEASE_BEHAVIOR_ARB, WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
12457+			}
12458+		}
12459+
12460+		i32 flags = 0;
12461+		if (hints->debug) flags |= WGL_CONTEXT_DEBUG_BIT_ARB;
12462+		if (hints->robustness && RGFW_extensionSupportedPlatform_OpenGL(robustness, sizeof(robustness))) flags |= WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB;
12463+		if (flags) {
12464+			RGFW_attribStack_pushAttribs(&stack, WGL_CONTEXT_FLAGS_ARB, flags);
12465+		}
12466+
12467+
12468+		RGFW_attribStack_pushAttribs(&stack, 0, 0);
12469+
12470+		win->src.ctx.native->ctx = (HGLRC)wglCreateContextAttribsARB(win->src.hdc, NULL, attribs);
12471+	}
12472+
12473+	if (wglCreateContextAttribsARB == NULL || win->src.ctx.native->ctx == NULL) { /* fall back to a default context (probably OpenGL 2 or something) */
12474+		RGFW_debugCallback(RGFW_typeError, RGFW_errOpenGLContext, "Failed to create an accelerated OpenGL Context.");
12475+		win->src.ctx.native->ctx = wglCreateContext(win->src.hdc);
12476+	}
12477+
12478+	ReleaseDC(win->src.window, win->src.hdc);
12479+	win->src.hdc = GetDC(win->src.window);
12480+
12481+	if (hints->share) {
12482+		wglShareLists((HGLRC)RGFW_getCurrentContext_OpenGL(), hints->share->ctx);
12483+	}
12484+
12485+	wglMakeCurrent(win->src.hdc, win->src.ctx.native->ctx);
12486+	RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "OpenGL context initalized.");
12487+	return RGFW_TRUE;
12488+}
12489+
12490+void RGFW_window_deleteContextPtr_OpenGL(RGFW_window* win, RGFW_glContext* ctx) {
12491+	wglDeleteContext((HGLRC) ctx->ctx); /*!< delete OpenGL context */
12492+	win->src.ctx.native->ctx = NULL;
12493+	RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "OpenGL context freed.");
12494+}
12495+
12496+void RGFW_window_makeCurrentContext_OpenGL(RGFW_window* win) {
12497+	if (win == NULL)
12498+		wglMakeCurrent(NULL, NULL);
12499+	else
12500+		wglMakeCurrent(win->src.hdc, (HGLRC) win->src.ctx.native->ctx);
12501+}
12502+void* RGFW_getCurrentContext_OpenGL(void) {
12503+	return wglGetCurrentContext();
12504+}
12505+void RGFW_window_swapBuffers_OpenGL(RGFW_window* win) {
12506+	RGFW_ASSERT(win->src.ctx.native);
12507+	SwapBuffers(win->src.hdc);
12508+}
12509+
12510+void RGFW_window_swapInterval_OpenGL(RGFW_window* win, i32 swapInterval) {
12511+	RGFW_ASSERT(win != NULL);
12512+    if (wglSwapIntervalEXT == NULL || wglSwapIntervalEXT(swapInterval) == FALSE)
12513+		RGFW_debugCallback(RGFW_typeError, RGFW_errOpenGLContext, "Failed to set swap interval");
12514+}
12515+#endif
12516+
12517+RGFW_bool RGFW_createUTF8FromWideStringWin32(const WCHAR* source, char* output, size_t max) {
12518+    i32 size = 0;
12519+    if (source == NULL) {
12520+        return RGFW_FALSE;
12521+	}
12522+	size = WideCharToMultiByte(CP_UTF8, 0, source, -1, NULL, 0, NULL, NULL);
12523+	if (!size) {
12524+		return RGFW_FALSE;
12525+	}
12526+
12527+	if (size > (i32)max)
12528+		size = (i32)max;
12529+
12530+	if (!WideCharToMultiByte(CP_UTF8, 0, source, -1, output, size, NULL, NULL)) {
12531+		return RGFW_FALSE;
12532+	}
12533+
12534+	output[size] = 0;
12535+	return RGFW_TRUE;
12536+}
12537+
12538+#ifdef RGFW_WEBGPU
12539+WGPUSurface RGFW_window_createSurface_WebGPU(RGFW_window* window, WGPUInstance instance) {
12540+	WGPUSurfaceDescriptor surfaceDesc = {0};
12541+	WGPUSurfaceSourceWindowsHWND fromHwnd = {0};
12542+    fromHwnd.chain.sType = WGPUSType_SurfaceSourceWindowsHWND;
12543+    fromHwnd.hwnd = window->src.window;
12544+
12545+	fromHwnd.hinstance = GetModuleHandle(NULL);
12546+
12547+    surfaceDesc.nextInChain = (WGPUChainedStruct*)&fromHwnd.chain;
12548+    return wgpuInstanceCreateSurface(instance, &surfaceDesc);
12549+}
12550+#endif
12551+
12552+#endif /* RGFW_WINDOWS */
12553+
12554+/*
12555+	End of Windows defines
12556+*/
12557+
12558+
12559+
12560+/*
12561+
12562+	Start of MacOS defines
12563+
12564+
12565+*/
12566+
12567+#if defined(RGFW_MACOS)
12568+/*
12569+	based on silicon.h
12570+	start of cocoa wrapper
12571+*/
12572+
12573+#include <CoreGraphics/CoreGraphics.h>
12574+#include <ApplicationServices/ApplicationServices.h>
12575+#include <objc/runtime.h>
12576+#include <objc/message.h>
12577+#include <mach/mach_time.h>
12578+
12579+#include <Carbon/Carbon.h>
12580+
12581+typedef TISInputSourceRef (*PFN_TISCopyCurrentKeyboardLayoutInputSource)(void);
12582+PFN_TISCopyCurrentKeyboardLayoutInputSource TISCopyCurrentKeyboardLayoutInputSourceSrc;
12583+#define TISCopyCurrentKeyboardLayoutInputSource TISCopyCurrentKeyboardLayoutInputSourceSrc
12584+
12585+typedef CFDataRef (*PFN_TISGetInputSourceProperty)(TISInputSourceRef, CFStringRef);
12586+PFN_TISGetInputSourceProperty TISGetInputSourcePropertySrc;
12587+#define TISGetInputSourceProperty TISGetInputSourcePropertySrc
12588+
12589+typedef u8 (*PFN_LMGetKbdType)(void);
12590+PFN_LMGetKbdType LMGetKbdTypeSrc;
12591+#define LMGetKbdType LMGetKbdTypeSrc
12592+
12593+CFStringRef kTISPropertyUnicodeKeyLayoutDataSrc;
12594+
12595+#ifndef  __OBJC__
12596+typedef CGRect NSRect;
12597+typedef CGPoint NSPoint;
12598+typedef CGSize NSSize;
12599+
12600+typedef const char* NSPasteboardType;
12601+typedef unsigned long NSUInteger;
12602+typedef long NSInteger;
12603+typedef NSInteger NSModalResponse;
12604+
12605+typedef enum NSRequestUserAttentionType {
12606+	NSCriticalRequest = 0,
12607+    NSInformationalRequest = 10
12608+} NSRequestUserAttentionType;
12609+
12610+typedef enum NSApplicationActivationPolicy {
12611+	NSApplicationActivationPolicyRegular,
12612+	NSApplicationActivationPolicyAccessory,
12613+	NSApplicationActivationPolicyProhibited
12614+} NSApplicationActivationPolicy;
12615+
12616+typedef RGFW_ENUM(u32, NSBackingStoreType) {
12617+	NSBackingStoreRetained = 0,
12618+		NSBackingStoreNonretained = 1,
12619+		NSBackingStoreBuffered = 2
12620+};
12621+
12622+typedef RGFW_ENUM(u32, NSWindowStyleMask) {
12623+	NSWindowStyleMaskBorderless = 0,
12624+		NSWindowStyleMaskTitled = 1 << 0,
12625+		NSWindowStyleMaskClosable = 1 << 1,
12626+		NSWindowStyleMaskMiniaturizable = 1 << 2,
12627+		NSWindowStyleMaskResizable = 1 << 3,
12628+		NSWindowStyleMaskTexturedBackground = 1 << 8, /* deprecated */
12629+		NSWindowStyleMaskUnifiedTitleAndToolbar = 1 << 12,
12630+		NSWindowStyleMaskFullScreen = 1 << 14,
12631+		NSWindowStyleMaskFullSizeContentView = 1 << 15,
12632+		NSWindowStyleMaskUtilityWindow = 1 << 4,
12633+		NSWindowStyleMaskDocModalWindow = 1 << 6,
12634+		NSWindowStyleMaskNonactivatingpanel = 1 << 7,
12635+		NSWindowStyleMaskHUDWindow = 1 << 13
12636+};
12637+
12638+#define NSPasteboardTypeString "public.utf8-plain-text"
12639+
12640+typedef RGFW_ENUM(i32, NSDragOperation) {
12641+	NSDragOperationNone = 0,
12642+		NSDragOperationCopy = 1,
12643+		NSDragOperationLink = 2,
12644+		NSDragOperationGeneric = 4,
12645+		NSDragOperationPrivate = 8,
12646+		NSDragOperationMove = 16,
12647+		NSDragOperationDelete = 32,
12648+		NSDragOperationEvery = (int)ULONG_MAX
12649+};
12650+
12651+typedef RGFW_ENUM(NSInteger, NSOpenGLContextParameter) {
12652+	NSOpenGLContextParameterSwapInterval            = 222, /* 1 param.  0 -> Don't sync, 1 -> Sync to vertical retrace     */
12653+		NSOpenGLContextParametectxaceOrder            = 235, /* 1 param.  1 -> Above Window (default), -1 -> Below Window    */
12654+		NSOpenGLContextParametectxaceOpacity          = 236, /* 1 param.  1-> Surface is opaque (default), 0 -> non-opaque   */
12655+		NSOpenGLContextParametectxaceBackingSize      = 304, /* 2 params.  Width/height of surface backing size              */
12656+		NSOpenGLContextParameterReclaimResources        = 308, /* 0 params.                                                    */
12657+		NSOpenGLContextParameterCurrentRendererID       = 309, /* 1 param.   Retrieves the current renderer ID                 */
12658+		NSOpenGLContextParameterGPUVertexProcessing     = 310, /* 1 param.   Currently processing vertices with GPU (get)      */
12659+		NSOpenGLContextParameterGPUFragmentProcessing   = 311, /* 1 param.   Currently processing fragments with GPU (get)     */
12660+		NSOpenGLContextParameterHasDrawable             = 314, /* 1 param.   Boolean returned if drawable is attached          */
12661+		NSOpenGLContextParameterMPSwapsInFlight         = 315, /* 1 param.   Max number of swaps queued by the MP GL engine    */
12662+
12663+		NSOpenGLContextParameterSwapRectangle API_DEPRECATED("", macos(10.0, 10.14)) = 200, /* 4 params.  Set or get the swap rectangle {x, y, w, h} */
12664+		NSOpenGLContextParameterSwapRectangleEnable API_DEPRECATED("", macos(10.0, 10.14)) = 201, /* Enable or disable the swap rectangle */
12665+		NSOpenGLContextParameterRasterizationEnable API_DEPRECATED("", macos(10.0, 10.14)) = 221, /* Enable or disable all rasterization */
12666+		NSOpenGLContextParameterStateValidation API_DEPRECATED("", macos(10.0, 10.14)) = 301, /* Validate state for multi-screen functionality */
12667+		NSOpenGLContextParametectxaceSurfaceVolatile API_DEPRECATED("", macos(10.0, 10.14)) = 306, /* 1 param.   Surface volatile state */
12668+};
12669+
12670+typedef RGFW_ENUM(NSInteger, NSWindowButton) {
12671+    NSWindowCloseButton            = 0,
12672+    NSWindowMiniaturizeButton      = 1,
12673+    NSWindowZoomButton             = 2,
12674+    NSWindowToolbarButton          = 3,
12675+    NSWindowDocumentIconButton     = 4,
12676+    NSWindowDocumentVersionsButton = 6,
12677+    NSWindowFullScreenButton       = 7,
12678+};
12679+
12680+#define NSPasteboardTypeURL "public.url"
12681+#define NSPasteboardTypeFileURL "public.file-url"
12682+#define NSTrackingMouseEnteredAndExited   0x01
12683+#define NSTrackingMouseMoved              0x02
12684+#define NSTrackingCursorUpdate            0x04
12685+#define NSTrackingActiveWhenFirstResponder 0x10
12686+#define NSTrackingActiveInKeyWindow       0x20
12687+#define NSTrackingActiveInActiveApp       0x40
12688+#define NSTrackingActiveAlways            0x80
12689+#define NSTrackingAssumeInside            0x100
12690+#define NSTrackingInVisibleRect           0x200
12691+#define NSTrackingEnabledDuringMouseDrag  0x400
12692+enum {
12693+	NSOpenGLPFAAllRenderers =   1,	/* choose from all available renderers          */
12694+	NSOpenGLPFATripleBuffer =   3,	/* choose a triple buffered pixel format        */
12695+	NSOpenGLPFADoubleBuffer      =   5,	/* choose a double buffered pixel format        */
12696+	NSOpenGLPFAAuxBuffers   =   7,	/* number of aux buffers                        */
12697+	NSOpenGLPFAColorSize       =   8,	/* number of color buffer bits                  */
12698+	NSOpenGLPFAAlphaSize  =  11,	/* number of alpha component bits               */
12699+	NSOpenGLPFADepthSize   =  12,	/* number of depth buffer bits                  */
12700+	NSOpenGLPFAStencilSize   =  13,	/* number of stencil buffer bits                */
12701+	NSOpenGLPFAAccumSize       =  14,	/* number of accum buffer bits                  */
12702+	NSOpenGLPFAMinimumPolicy   =  51,	/* never choose smaller buffers than requested  */
12703+	NSOpenGLPFAMaximumPolicy =  52,	/* choose largest buffers of type requested     */
12704+	NSOpenGLPFASampleBuffers     =  55,	/* number of multi sample buffers               */
12705+	NSOpenGLPFASamples            =  56,	/* number of samples per multi sample buffer    */
12706+	NSOpenGLPFAAuxDepthStencil     =  57,	/* each aux buffer has its own depth stencil    */
12707+	NSOpenGLPFAColorFloat   =  58,	/* color buffers store floating point pixels    */
12708+	NSOpenGLPFAMultisample   =  59,    /* choose multisampling                         */
12709+	NSOpenGLPFASupersample    =  60,    /* choose supersampling                         */
12710+	NSOpenGLPFASampleAlpha     =  61,    /* request alpha filtering                      */
12711+	NSOpenGLPFARendererID       =  70,	/* request renderer by ID                       */
12712+	NSOpenGLPFANoRecovery   =  72,	/* disable all failure recovery systems         */
12713+	NSOpenGLPFAAccelerated      =  73,	/* choose a hardware accelerated renderer       */
12714+	NSOpenGLPFAClosestPolicy   =  74,	/* choose the closest color buffer to request   */
12715+	NSOpenGLPFABackingStore     =  76,	/* back buffer contents are valid after swap    */
12716+	NSOpenGLPFAScreenMask     =  84,	/* bit mask of supported physical screens       */
12717+	NSOpenGLPFAAllowOfflineRenderers  =  96,  /* allow use of offline renderers               */
12718+	NSOpenGLPFAAcceleratedCompute   =  97,	/* choose a hardware accelerated compute device */
12719+	NSOpenGLPFAOpenGLProfile      =  99,    /* specify an OpenGL Profile to use             */
12720+	NSOpenGLProfileVersionLegacy     = 0x1000, /* The requested profile is a legacy (pre-OpenGL 3.0) profile. */
12721+	NSOpenGLProfileVersion3_2Core    = 0x3200, /* The 3.2 Profile of OpenGL */
12722+	NSOpenGLProfileVersion4_1Core  = 0x3200, /* The 4.1 profile of OpenGL */
12723+	NSOpenGLPFAVirtualScreenCount      = 128,	/* number of virtual screens in this format     */
12724+	NSOpenGLPFAStereo                 =   6,
12725+	NSOpenGLPFAOffScreen             =  53,
12726+	NSOpenGLPFAFullScreen           =  54,
12727+	NSOpenGLPFASingleRenderer      =  71,
12728+	NSOpenGLPFARobust                 =  75,
12729+	NSOpenGLPFAMPSafe           =  78,
12730+	NSOpenGLPFAWindow                 =  80,
12731+	NSOpenGLPFAMultiScreen =    81,
12732+	NSOpenGLPFACompliant   =   83,
12733+	NSOpenGLPFAPixelBuffer            =  90,
12734+	NSOpenGLPFARemotePixelBuffer =  91,
12735+};
12736+
12737+typedef RGFW_ENUM(u32, NSEventType) {        /* various types of events */
12738+	NSEventTypeApplicationDefined = 15,
12739+};
12740+typedef unsigned long long NSEventMask;
12741+
12742+typedef enum NSEventModifierFlags {
12743+	NSEventModifierFlagCapsLock = 1 << 16,
12744+	NSEventModifierFlagShift = 1 << 17,
12745+	NSEventModifierFlagControl = 1 << 18,
12746+	NSEventModifierFlagOption = 1 << 19,
12747+	NSEventModifierFlagCommand = 1 << 20,
12748+	NSEventModifierFlagNumericPad = 1 << 21
12749+} NSEventModifierFlags;
12750+
12751+typedef RGFW_ENUM(NSUInteger, NSBitmapFormat) {
12752+	NSBitmapFormatAlphaFirst = 1 << 0,       /* 0 means is alpha last (RGBA, CMYKA, etc.) */
12753+		NSBitmapFormatAlphaNonpremultiplied = 1 << 1,       /* 0 means is premultiplied */
12754+		NSBitmapFormatFloatingpointSamples = 1 << 2,  /* 0 is integer */
12755+
12756+		NSBitmapFormatSixteenBitLittleEndian = (1 << 8),
12757+		NSBitmapFormatThirtyTwoBitLittleEndian = (1 << 9),
12758+		NSBitmapFormatSixteenBitBigEndian = (1 << 10),
12759+		NSBitmapFormatThirtyTwoBitBigEndian = (1 << 11)
12760+};
12761+
12762+#else
12763+#import <AppKit/AppKit.h>
12764+#include <Foundation/Foundation.h>
12765+#endif /* notdef __OBJC__ */
12766+
12767+#ifdef __arm64__
12768+	/* ARM just uses objc_msgSend */
12769+#define abi_objc_msgSend_stret objc_msgSend
12770+#define abi_objc_msgSend_fpret objc_msgSend
12771+#else /* __i386__ */
12772+	/* x86 just uses abi_objc_msgSend_fpret and (NSColor *)objc_msgSend_id respectively */
12773+#define abi_objc_msgSend_stret objc_msgSend_stret
12774+#define abi_objc_msgSend_fpret objc_msgSend_fpret
12775+#endif
12776+
12777+#define NSAlloc(nsclass) objc_msgSend_id((id)nsclass, sel_registerName("alloc"))
12778+#define objc_msgSend_bool(x, y)			((BOOL (*)(id, SEL))objc_msgSend) ((id)(x), (SEL)y)
12779+#define objc_msgSend_void(x, y)			((void (*)(id, SEL))objc_msgSend) ((id)(x), (SEL)y)
12780+#define objc_msgSend_void_id(x, y, z)		((void (*)(id, SEL, id))objc_msgSend) ((id)x, (SEL)y, (id)z)
12781+#define objc_msgSend_uint(x, y)			((NSUInteger (*)(id, SEL))objc_msgSend)  ((id)(x), (SEL)y)
12782+#define objc_msgSend_void_bool(x, y, z)		((void (*)(id, SEL, BOOL))objc_msgSend)  ((id)(x), (SEL)y, (BOOL)z)
12783+#define objc_msgSend_bool_void(x, y)		((BOOL (*)(id, SEL))objc_msgSend)  ((id)(x), (SEL)y)
12784+#define objc_msgSend_void_SEL(x, y, z)		((void (*)(id, SEL, SEL))objc_msgSend)  ((id)(x), (SEL)y, (SEL)z)
12785+#define objc_msgSend_id(x, y)				((id (*)(id, SEL))objc_msgSend)  ((id)(x), (SEL)y)
12786+#define objc_msgSend_id_id(x, y, z)			((id (*)(id, SEL, id))objc_msgSend)  ((id)(x), (SEL)y, (id)z)
12787+#define objc_msgSend_id_bool(x, y, z)			((BOOL (*)(id, SEL, id))objc_msgSend)  ((id)(x), (SEL)y, (id)z)
12788+#define objc_msgSend_int(x, y, z) 				((id (*)(id, SEL, int))objc_msgSend)  ((id)(x), (SEL)y, (int)z)
12789+#define objc_msgSend_arr(x, y, z)				 	((id (*)(id, SEL, int))objc_msgSend)  ((id)(x), (SEL)y, (int)z)
12790+#define objc_msgSend_ptr(x, y, z) 					((id (*)(id, SEL, void*))objc_msgSend)  ((id)(x), (SEL)y, (void*)z)
12791+#define objc_msgSend_class(x, y) 					((id (*)(Class, SEL))objc_msgSend)  ((Class)(x), (SEL)y)
12792+#define objc_msgSend_class_char(x, y, z) 			((id (*)(Class, SEL, char*))objc_msgSend)  ((Class)(x), (SEL)y, (char*)z)
12793+
12794+#define NSRelease(obj) objc_msgSend_void((id)obj, sel_registerName("release"))
12795+RGFWDEF id NSString_stringWithUTF8String(const char* str);
12796+id NSString_stringWithUTF8String(const char* str) {
12797+	return ((id(*)(id, SEL, const char*))objc_msgSend) ((id)objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), str);
12798+}
12799+
12800+RGFWDEF float RGFW_cocoaYTransform(float y);
12801+float RGFW_cocoaYTransform(float y) { return (float)(CGDisplayBounds(CGMainDisplayID()).size.height - (double)y - (double)1.0f); }
12802+
12803+const char* NSString_to_char(id str);
12804+const char* NSString_to_char(id str) {
12805+	return ((const char* (*)(id, SEL)) objc_msgSend) ((id)(id)str, sel_registerName("UTF8String"));
12806+}
12807+
12808+unsigned char* NSBitmapImageRep_bitmapData(id imageRep);
12809+unsigned char* NSBitmapImageRep_bitmapData(id imageRep) {
12810+	return ((unsigned char* (*)(id, SEL))objc_msgSend) ((id)imageRep, sel_registerName("bitmapData"));
12811+}
12812+
12813+id NSBitmapImageRep_initWithBitmapData(unsigned char** planes, NSInteger width, NSInteger height, NSInteger bps, NSInteger spp, bool alpha, bool isPlanar, const char* colorSpaceName, NSBitmapFormat bitmapFormat, NSInteger rowBytes, NSInteger pixelBits);
12814+id NSBitmapImageRep_initWithBitmapData(unsigned char** planes, NSInteger width, NSInteger height, NSInteger bps, NSInteger spp, bool alpha, bool isPlanar, const char* colorSpaceName, NSBitmapFormat bitmapFormat, NSInteger rowBytes, NSInteger pixelBits) {
12815+	SEL func = sel_registerName("initWithBitmapDataPlanes:pixelsWide:pixelsHigh:bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:colorSpaceName:bitmapFormat:bytesPerRow:bitsPerPixel:");
12816+
12817+	return (id) ((id(*)(id, SEL, unsigned char**, NSInteger, NSInteger, NSInteger, NSInteger, bool, bool, id, NSBitmapFormat, NSInteger, NSInteger))objc_msgSend)
12818+		(NSAlloc((id)objc_getClass("NSBitmapImageRep")), func, planes, width, height, bps, spp, alpha, isPlanar, NSString_stringWithUTF8String(colorSpaceName), bitmapFormat, rowBytes, pixelBits);
12819+}
12820+
12821+id NSColor_colorWithSRGB(CGFloat red, CGFloat green, CGFloat blue, CGFloat alpha);
12822+id NSColor_colorWithSRGB(CGFloat red, CGFloat green, CGFloat blue, CGFloat alpha) {
12823+	Class nsclass = objc_getClass("NSColor");
12824+	SEL func = sel_registerName("colorWithSRGBRed:green:blue:alpha:");
12825+	return ((id(*)(id, SEL, CGFloat, CGFloat, CGFloat, CGFloat))objc_msgSend)
12826+		((id)nsclass, func, red, green, blue, alpha);
12827+}
12828+
12829+id NSPasteboard_generalPasteboard(void);
12830+id NSPasteboard_generalPasteboard(void) {
12831+	return (id) objc_msgSend_id((id)objc_getClass("NSPasteboard"), sel_registerName("generalPasteboard"));
12832+}
12833+
12834+id* cstrToNSStringArray(char** strs, size_t len);
12835+id* cstrToNSStringArray(char** strs, size_t len) {
12836+	static id nstrs[6];
12837+	size_t i;
12838+	for (i = 0; i < len; i++)
12839+		nstrs[i] = NSString_stringWithUTF8String(strs[i]);
12840+
12841+	return nstrs;
12842+}
12843+
12844+const char* NSPasteboard_stringForType(id pasteboard, NSPasteboardType dataType, size_t* len);
12845+const char* NSPasteboard_stringForType(id pasteboard, NSPasteboardType dataType, size_t* len) {
12846+	SEL func = sel_registerName("stringForType:");
12847+	id nsstr = NSString_stringWithUTF8String((const char*)dataType);
12848+	id nsString = ((id(*)(id, SEL, id))objc_msgSend)(pasteboard, func, nsstr);
12849+	const char* str = NSString_to_char(nsString);
12850+	if (len != NULL)
12851+		*len = (size_t)((NSUInteger(*)(id, SEL, int))objc_msgSend)(nsString, sel_registerName("maximumLengthOfBytesUsingEncoding:"), 4);
12852+	return str;
12853+}
12854+
12855+id c_array_to_NSArray(void* array, size_t len);
12856+id c_array_to_NSArray(void* array, size_t len) {
12857+	return ((id (*)(id, SEL, void*, NSUInteger))objc_msgSend) (NSAlloc(objc_getClass("NSArray")), sel_registerName("initWithObjects:count:"), array, len);
12858+}
12859+
12860+
12861+void NSregisterForDraggedTypes(id view, NSPasteboardType* newTypes, size_t len);
12862+void NSregisterForDraggedTypes(id view, NSPasteboardType* newTypes, size_t len) {
12863+	id* ntypes = cstrToNSStringArray((char**)newTypes, len);
12864+
12865+	id array = c_array_to_NSArray(ntypes, len);
12866+	objc_msgSend_void_id(view, sel_registerName("registerForDraggedTypes:"), array);
12867+	NSRelease(array);
12868+}
12869+
12870+NSInteger NSPasteBoard_declareTypes(id pasteboard, NSPasteboardType* newTypes, size_t len, void* owner);
12871+NSInteger NSPasteBoard_declareTypes(id pasteboard, NSPasteboardType* newTypes, size_t len, void* owner) {
12872+	id* ntypes = cstrToNSStringArray((char**)newTypes, len);
12873+
12874+	SEL func = sel_registerName("declareTypes:owner:");
12875+
12876+	id array = c_array_to_NSArray(ntypes, len);
12877+
12878+	NSInteger output = ((NSInteger(*)(id, SEL, id, void*))objc_msgSend)
12879+		(pasteboard, func, array, owner);
12880+	NSRelease(array);
12881+
12882+	return output;
12883+}
12884+
12885+#define NSRetain(obj) objc_msgSend_void((id)obj, sel_registerName("retain"))
12886+
12887+/*
12888+	End of cocoa wrapper
12889+*/
12890+
12891+static id RGFW__osxCustomInitWithRGFWWindow(id self, SEL _cmd, RGFW_window* win) {
12892+	RGFW_UNUSED(_cmd);
12893+    struct objc_super s = { self, class_getSuperclass(object_getClass(self)) };
12894+
12895+    CGRect rect;
12896+    rect.origin.x = 0;
12897+    rect.origin.y = 0;
12898+    rect.size.width = (double)win->w;
12899+    rect.size.height = (double)win->h;
12900+
12901+    self = ((id (*)(struct objc_super*, SEL, CGRect))objc_msgSendSuper)(
12902+        &s, sel_registerName("initWithFrame:"), rect
12903+    );
12904+
12905+    if (self != nil) {
12906+        object_setInstanceVariable(self, "RGFW_window", win);
12907+        object_setInstanceVariable(self, "trackingArea", nil);
12908+
12909+        object_setInstanceVariable(
12910+            self, "markedText",
12911+            ((id (*)(id, SEL))objc_msgSend)(
12912+                ((id (*)(Class, SEL))objc_msgSend)(objc_getClass("NSMutableAttributedString"), sel_registerName("alloc")),
12913+                sel_registerName("init")
12914+            )
12915+        );
12916+
12917+        ((void (*)(id, SEL))objc_msgSend)(self, sel_registerName("updateTrackingAreas"));
12918+
12919+        ((void (*)(id, SEL, id))objc_msgSend)(
12920+            self, sel_registerName("registerForDraggedTypes:"),
12921+            ((id (*)(Class, SEL, id))objc_msgSend)(
12922+                objc_getClass("NSArray"),
12923+                sel_registerName("arrayWithObject:"),
12924+                ((id (*)(Class, SEL, const char*))objc_msgSend)(
12925+                    objc_getClass("NSString"),
12926+                    sel_registerName("stringWithUTF8String:"),
12927+                    "public.url"
12928+                )
12929+            )
12930+        );
12931+    }
12932+
12933+    return self;
12934+}
12935+
12936+static u32 RGFW_OnClose(id self) {
12937+	RGFW_window* win = NULL;
12938+	object_getInstanceVariable(self, (const char*)"RGFW_window", (void**)&win);
12939+	if (win == NULL) return true;
12940+
12941+	RGFW_windowCloseCallback(win);
12942+	return false;
12943+}
12944+
12945+/* NOTE(EimaMei): Fixes the constant clicking when the app is running under a terminal. */
12946+static bool RGFW__osxAcceptsFirstResponder(void) { return true; }
12947+static bool RGFW__osxPerformKeyEquivalent(id event) { RGFW_UNUSED(event); return true; }
12948+
12949+static NSDragOperation RGFW__osxDraggingEntered(id self, SEL sel, id sender) {
12950+	RGFW_UNUSED(sel);
12951+
12952+	RGFW_window* win = NULL;
12953+	object_getInstanceVariable(self, "RGFW_window", (void**)&win);
12954+	if (win == NULL)
12955+		return 0;
12956+
12957+	NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(sender, sel_registerName("draggingLocation"));
12958+	RGFW_dataDragCallback(win, RGFW_dataFile, RGFW_dndActionEnter, (i32) p.x, (i32) (win->h - p.y));
12959+	return NSDragOperationCopy;
12960+}
12961+static NSDragOperation RGFW__osxDraggingUpdated(id self, SEL sel, id sender) {
12962+	RGFW_UNUSED(sel);
12963+
12964+	RGFW_window* win = NULL;
12965+	object_getInstanceVariable(self, "RGFW_window", (void**)&win);
12966+	if (win == NULL)
12967+		return 0;
12968+	if (!(win->internal.enabledEvents & RGFW_dataDragFlag)) return NSDragOperationCopy;
12969+
12970+	NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(sender, sel_registerName("draggingLocation"));
12971+	RGFW_dataDragCallback(win, RGFW_dataFile, RGFW_dndActionMove, (i32) p.x, (i32) (win->h - p.y));
12972+	return NSDragOperationCopy;
12973+}
12974+static bool RGFW__osxPrepareForDragOperation(id self) {
12975+	RGFW_window* win = NULL;
12976+	object_getInstanceVariable(self, "RGFW_window", (void**)&win);
12977+	if (win == NULL || (!(win->internal.enabledEvents & RGFW_dataDropFlag)))
12978+		return true;
12979+
12980+	if (!(win->internal.flags & RGFW_windowAllowDND)) {
12981+		return false;
12982+	}
12983+
12984+	return true;
12985+}
12986+
12987+static void RGFW__osxDraggingEnded(id self, SEL sel, id sender) {
12988+	RGFW_UNUSED(sel);
12989+
12990+	RGFW_window* win = NULL;
12991+	object_getInstanceVariable(self, "RGFW_window", (void**)&win);
12992+	if (win == NULL)
12993+		return;
12994+	if (!(win->internal.enabledEvents & RGFW_dataDragFlag)) return;
12995+
12996+	NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(sender, sel_registerName("draggingLocation"));
12997+	RGFW_dataDragCallback(win, RGFW_dataFile, RGFW_dndActionExit, (i32) p.x, (i32) (win->h - p.y));
12998+	return;
12999+}
13000+
13001+static bool RGFW__osxPerformDragOperation(id self, SEL sel, id sender) {
13002+	RGFW_UNUSED(sender); RGFW_UNUSED(self); RGFW_UNUSED(sel);
13003+	RGFW_window* win = NULL;
13004+	object_getInstanceVariable(self, "RGFW_window", (void**)&win);
13005+	if (win == NULL || (!(win->internal.enabledEvents & RGFW_dataDropFlag)))
13006+		return false;
13007+
13008+	/* id pasteBoard = objc_msgSend_id(sender, sel_registerName("draggingPasteboard")); */
13009+
13010+	id pasteBoard = objc_msgSend_id(sender, sel_registerName("draggingPasteboard"));
13011+
13012+	/* Get the types of data available on the pasteboard */
13013+	id types = objc_msgSend_id(pasteBoard, sel_registerName("types"));
13014+
13015+	/* Get the string type for file URLs */
13016+	id fileURLsType = objc_msgSend_class_char(objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), "NSFilenamesPboardType");
13017+
13018+	/* Check if the pasteboard contains file URLs */
13019+	if (objc_msgSend_id_bool(types, sel_registerName("containsObject:"), fileURLsType) == 0) {
13020+		RGFW_debugCallback(RGFW_typeError, RGFW_errClipboard, "No files found on the pasteboard.");
13021+		return 0;
13022+	}
13023+
13024+	id fileURLs = objc_msgSend_id_id(pasteBoard, sel_registerName("propertyListForType:"), fileURLsType);
13025+	int count = ((int (*)(id, SEL))objc_msgSend)(fileURLs, sel_registerName("count"));
13026+
13027+	if (count == 0)
13028+		return 0;
13029+
13030+	u32 i;
13031+    for (i = 0; i < (u32)count; i++) {
13032+		id fileURL = objc_msgSend_arr(fileURLs, sel_registerName("objectAtIndex:"), i);
13033+		const char *filePath = ((const char* (*)(id, SEL))objc_msgSend)(fileURL, sel_registerName("UTF8String"));
13034+		int string_count = ((int (*)(id, SEL))objc_msgSend)(fileURL, sel_registerName("count"));
13035+
13036+		RGFW_dataDropCallback(win, filePath, (size_t)string_count + 1, RGFW_dataFile);
13037+	}
13038+
13039+	return false;
13040+}
13041+
13042+#ifndef RGFW_NO_IOKIT
13043+#include <IOKit/IOKitLib.h>
13044+
13045+float RGFW_osx_getFallbackRefreshRate(CGDirectDisplayID displayID);
13046+float RGFW_osx_getFallbackRefreshRate(CGDirectDisplayID displayID) {
13047+    float refreshRate = 0;
13048+    io_iterator_t it;
13049+    io_service_t service;
13050+    CFNumberRef indexRef, clockRef, countRef;
13051+    u32 clock, count;
13052+
13053+#ifdef kIOMainPortDefault
13054+    if (IOServiceGetMatchingServices(kIOMainPortDefault, IOServiceMatching("IOFramebuffer"), &it) != 0)
13055+#elif defined(kIOMasterPortDefault)
13056+    if (IOServiceGetMatchingServices(kIOMainPortDefault, IOServiceMatching("IOFramebuffer"), &it) != 0)
13057+#endif
13058+        return RGFW_FALSE;
13059+
13060+    while ((service = IOIteratorNext(it)) != 0) {
13061+        u32 index;
13062+        indexRef = (CFNumberRef)IORegistryEntryCreateCFProperty(service, CFSTR("IOFramebufferOpenGLIndex"), kCFAllocatorDefault, kNilOptions);
13063+        if (indexRef == 0) continue;
13064+
13065+        if (CFNumberGetValue(indexRef, kCFNumberIntType, &index) && CGOpenGLDisplayMaskToDisplayID(1 << index) == displayID) {
13066+            CFRelease(indexRef);
13067+            break;
13068+        }
13069+
13070+        CFRelease(indexRef);
13071+    }
13072+
13073+    if (service) {
13074+        clockRef = (CFNumberRef)IORegistryEntryCreateCFProperty(service, CFSTR("IOFBCurrentPixelClock"), kCFAllocatorDefault, kNilOptions);
13075+        if (clockRef) {
13076+            if (CFNumberGetValue(clockRef, kCFNumberIntType, &clock) && clock) {
13077+                countRef = (CFNumberRef)IORegistryEntryCreateCFProperty(service, CFSTR("IOFBCurrentPixelCount"), kCFAllocatorDefault, kNilOptions);
13078+                if (countRef && CFNumberGetValue(countRef, kCFNumberIntType, &count) && count) {
13079+					refreshRate = (float)((double)clock / (double) count);
13080+                    CFRelease(countRef);
13081+                }
13082+            }
13083+            CFRelease(clockRef);
13084+        }
13085+    }
13086+
13087+    IOObjectRelease(it);
13088+    return refreshRate;
13089+}
13090+#endif
13091+
13092+void RGFW_moveToMacOSResourceDir(void) {
13093+	char resourcesPath[256];
13094+
13095+	CFBundleRef bundle = CFBundleGetMainBundle();
13096+	if (!bundle)
13097+		return;
13098+
13099+	CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(bundle);
13100+	CFStringRef last = CFURLCopyLastPathComponent(resourcesURL);
13101+
13102+	if (
13103+		CFStringCompare(CFSTR("Resources"), last, 0) != kCFCompareEqualTo ||
13104+		CFURLGetFileSystemRepresentation(resourcesURL, true, (u8*) resourcesPath, 255) == 0
13105+		) {
13106+		CFRelease(last);
13107+		CFRelease(resourcesURL);
13108+		return;
13109+	}
13110+
13111+	CFRelease(last);
13112+	CFRelease(resourcesURL);
13113+
13114+	chdir(resourcesPath);
13115+}
13116+
13117+static void RGFW__osxDidChangeScreenParameters(id self, SEL _cmd, id notification) {
13118+	RGFW_UNUSED(self); RGFW_UNUSED(_cmd); RGFW_UNUSED(notification);
13119+	RGFW_pollMonitors();
13120+}
13121+
13122+static void RGFW__osxWindowDeminiaturize(id self, SEL sel) {
13123+	RGFW_UNUSED(sel);
13124+	RGFW_window* win = NULL;
13125+	object_getInstanceVariable(self, "RGFW_window", (void**)&win);
13126+	if (win == NULL) return;
13127+
13128+	RGFW_windowRestoredCallback(win, win->x, win->y, win->w, win->h);
13129+
13130+}
13131+static void RGFW__osxWindowMiniaturize(id self, SEL sel) {
13132+	RGFW_UNUSED(sel);
13133+	RGFW_window* win = NULL;
13134+	object_getInstanceVariable(self, "RGFW_window", (void**)&win);
13135+	if (win == NULL) return;
13136+
13137+	RGFW_windowMinimizedCallback(win);
13138+
13139+}
13140+
13141+static void RGFW__osxWindowBecameKey(id self, SEL sel) {
13142+	RGFW_UNUSED(sel);
13143+	RGFW_window* win = NULL;
13144+	object_getInstanceVariable(self, "RGFW_window", (void**)&win);
13145+	if (win == NULL) return;
13146+
13147+	RGFW_windowFocusCallback(win, RGFW_TRUE);
13148+}
13149+
13150+static void RGFW__osxWindowResignKey(id self, SEL sel) {
13151+	RGFW_UNUSED(sel);
13152+	RGFW_window* win = NULL;
13153+	object_getInstanceVariable(self, "RGFW_window", (void**)&win);
13154+	if (win == NULL) return;
13155+
13156+	RGFW_windowFocusCallback(win, RGFW_FALSE);
13157+}
13158+
13159+static void RGFW__osxDidWindowResize(id self, SEL _cmd, id notification) {
13160+	RGFW_UNUSED(_cmd); RGFW_UNUSED(notification);
13161+	RGFW_window* win = NULL;
13162+	object_getInstanceVariable(self, "RGFW_window", (void**)&win);
13163+	if (win == NULL) return;
13164+
13165+	NSRect frame;
13166+	if (win->src.view) frame = ((NSRect(*)(id, SEL))abi_objc_msgSend_stret)((id)win->src.view, sel_registerName("frame"));
13167+	else return;
13168+
13169+	if (frame.size.width == 0 || frame.size.height == 0) return;
13170+	win->w = (i32)frame.size.width;
13171+	win->h = (i32)frame.size.height;
13172+
13173+	RGFW_monitor* mon = RGFW_window_getMonitor(win);
13174+	if (mon == NULL) return;
13175+
13176+	if ((i32)mon->mode.w == win->w && (i32)mon->mode.h - 102 <= win->h) {
13177+		RGFW_windowMaximizedCallback(win, 0, 0, win->w, win->h);
13178+	} else if (win->internal.flags & RGFW_windowMaximize) {
13179+		RGFW_windowRestoredCallback(win, win->x, win->y, win->w, win->h);
13180+	}
13181+
13182+	RGFW_windowResizedCallback(win, win->w, win->h);
13183+}
13184+
13185+static void RGFW__osxWindowMove(id self, SEL sel) {
13186+	RGFW_UNUSED(sel);
13187+	RGFW_window* win = NULL;
13188+	object_getInstanceVariable(self, "RGFW_window", (void**)&win);
13189+	if (win == NULL) return;
13190+
13191+	NSRect frame = ((NSRect(*)(id, SEL))abi_objc_msgSend_stret)((id)win->src.window, sel_registerName("frame"));
13192+	NSRect content = ((NSRect(*)(id, SEL, NSRect))abi_objc_msgSend_stret)((id)win->src.window, sel_registerName("contentRectForFrameRect:"), frame);
13193+
13194+	float y = RGFW_cocoaYTransform((float)(content.origin.y + content.size.height - 1));
13195+
13196+	RGFW_windowMovedCallback(win, (i32)content.origin.x, (i32)y);
13197+}
13198+
13199+static void RGFW__osxViewDidChangeBackingProperties(id self, SEL _cmd) {
13200+	RGFW_UNUSED(_cmd);
13201+	RGFW_window* win = NULL;
13202+	object_getInstanceVariable(self, "RGFW_window", (void**)&win);
13203+	if (win == NULL) return;
13204+
13205+	RGFW_monitor* mon = RGFW_window_getMonitor(win);
13206+	if (mon == NULL) return;
13207+
13208+	RGFW_scaleUpdatedCallback(win, mon->scaleX, mon->scaleY);
13209+}
13210+
13211+static BOOL RGFW__osxWantsUpdateLayer(id self, SEL _cmd) { RGFW_UNUSED(self); RGFW_UNUSED(_cmd); return YES; }
13212+
13213+static void RGFW__osxUpdateLayer(id self, SEL _cmd) {
13214+	RGFW_UNUSED(self); RGFW_UNUSED(_cmd);
13215+	RGFW_window* win = NULL;
13216+	object_getInstanceVariable(self, "RGFW_window", (void**)&win);
13217+	if (win == NULL) return;
13218+	RGFW_windowRefreshCallback(win, 0, 0, win->w, win->h);
13219+}
13220+
13221+static void RGFW__osxDrawRect(id self, SEL _cmd, CGRect rect) {
13222+	RGFW_UNUSED(rect); RGFW_UNUSED(_cmd);
13223+	RGFW_window* win = NULL;
13224+	object_getInstanceVariable(self, "RGFW_window", (void**)&win);
13225+	if (win == NULL) return;
13226+
13227+	RGFW_windowRefreshCallback(win, 0, 0, win->w, win->h);
13228+}
13229+
13230+static void RGFW__osxMouseEntered(id self, SEL _cmd, id event) {
13231+	RGFW_UNUSED(_cmd);
13232+	RGFW_window* win = NULL;
13233+    object_getInstanceVariable(self, "RGFW_window", (void**)&win);
13234+    if (win == NULL) return;
13235+
13236+    NSPoint p = ((NSPoint(*)(id, SEL))objc_msgSend)(event, sel_registerName("locationInWindow"));
13237+    RGFW_mouseNotifyCallback(win, (i32)p.x, (i32)(win->h - p.y), 1);
13238+}
13239+
13240+static void RGFW__osxMouseExited(id self, SEL _cmd, id event) {
13241+	RGFW_UNUSED(_cmd); RGFW_UNUSED(event);
13242+	RGFW_window* win = NULL;
13243+    object_getInstanceVariable(self, "RGFW_window", (void**)&win);
13244+    if (win == NULL) return;
13245+
13246+	RGFW_mouseNotifyCallback(win, win->internal.lastMouseX, win->internal.lastMouseY, RGFW_FALSE);
13247+}
13248+
13249+static void RGFW__osxKeyDown(id self, SEL _cmd, id event) {
13250+	RGFW_UNUSED(_cmd);
13251+	RGFW_window* win = NULL;
13252+    object_getInstanceVariable(self, "RGFW_window", (void**)&win);
13253+	if (win == NULL || !(win->internal.enabledEvents & RGFW_keyPressedFlag)) return;
13254+
13255+    u32 key = (u16)((u32(*)(id, SEL))objc_msgSend)(event, sel_registerName("keyCode"));
13256+
13257+	RGFW_key value = (u8)RGFW_apiKeyToRGFW(key);
13258+	RGFW_bool repeat = RGFW_isKeyDown(value);
13259+
13260+    RGFW_keyCallback(win, value, win->internal.mod, repeat, 1);
13261+
13262+	id nsstring = ((id(*)(id, SEL))objc_msgSend)(event, sel_registerName("charactersIgnoringModifiers"));
13263+    const char* string = NSString_to_char(nsstring);
13264+	size_t count = (size_t)((int (*)(id, SEL))objc_msgSend)(nsstring, sel_registerName("length"));
13265+
13266+	for (size_t index = 0; index < count;
13267+			RGFW_keyCharCallback(win, RGFW_decodeUTF8(&string[index], &index))
13268+		);
13269+}
13270+
13271+static void RGFW__osxKeyUp(id self, SEL _cmd, id event) {
13272+	RGFW_UNUSED(_cmd);
13273+	RGFW_window* win = NULL;
13274+    object_getInstanceVariable(self, "RGFW_window", (void**)&win);
13275+    if (win == NULL || !(win->internal.enabledEvents & RGFW_keyReleasedFlag)) return;
13276+
13277+    u32 key = (u16)((u32(*)(id, SEL))objc_msgSend)(event, sel_registerName("keyCode"));
13278+
13279+    RGFW_key value = (u8)RGFW_apiKeyToRGFW(key);
13280+
13281+    RGFW_keyCallback(win, value, win->internal.mod, RGFW_FALSE, 0);
13282+}
13283+
13284+static void RGFW__osxFlagsChanged(id self, SEL _cmd, id event) {
13285+	RGFW_UNUSED(_cmd);
13286+    RGFW_window* win = NULL;
13287+    object_getInstanceVariable(self, "RGFW_window", (void**)&win);
13288+    if (win == NULL) return;
13289+
13290+	RGFW_key value = 0;
13291+	RGFW_bool pressed = RGFW_FALSE;
13292+
13293+    u32 flags = (u32)((u32(*)(id, SEL))objc_msgSend)(event, sel_registerName("modifierFlags"));
13294+    RGFW_keyUpdateKeyModsEx(win,
13295+                          ((u32)(flags & NSEventModifierFlagCapsLock) % 255),
13296+                          ((flags & NSEventModifierFlagNumericPad) % 255),
13297+                          ((flags & NSEventModifierFlagControl) % 255),
13298+                          ((flags & NSEventModifierFlagOption) % 255),
13299+                          ((flags & NSEventModifierFlagShift) % 255),
13300+                          ((flags & NSEventModifierFlagCommand) % 255), 0);
13301+    u8 i;
13302+    for (i = 0; i < 9; i++)
13303+        _RGFW->keyboard[i + RGFW_keyCapsLock].prev = _RGFW->keyboard[i + RGFW_keyCapsLock].current;
13304+
13305+    for (i = 0; i < 5; i++) {
13306+        u32 shift = (1 << (i + 16));
13307+        RGFW_key key = i + RGFW_keyCapsLock;
13308+        if ((flags & shift) && !RGFW_isKeyDown((u8)key)) {
13309+			pressed = RGFW_TRUE;
13310+            value = (u8)key;
13311+            break;
13312+        }
13313+        if (!(flags & shift) && RGFW_isKeyDown((u8)key)) {
13314+			pressed = RGFW_FALSE;
13315+            value = (u8)key;
13316+            break;
13317+        }
13318+    }
13319+
13320+	RGFW_keyCallback(win, value, win->internal.mod, RGFW_isKeyDown(value) && pressed, pressed);
13321+
13322+	if (value != RGFW_keyCapsLock) {
13323+		RGFW_keyCallback(win, value + 4, win->internal.mod, RGFW_isKeyDown(value + 4) && pressed, pressed);
13324+	}
13325+
13326+}
13327+
13328+static void RGFW__osxMouseMoved(id self, SEL _cmd, id event) {
13329+	RGFW_UNUSED(_cmd);
13330+    RGFW_window* win = NULL;
13331+    object_getInstanceVariable(self, "RGFW_window", (void**)&win);
13332+	if (win == NULL) return;
13333+
13334+    NSPoint p = ((NSPoint(*)(id, SEL))objc_msgSend)(event, sel_registerName("locationInWindow"));
13335+
13336+	CGFloat vecX = ((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(event, sel_registerName("deltaX"));
13337+    CGFloat vecY = ((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(event, sel_registerName("deltaY"));
13338+
13339+    RGFW_mousePosCallback(win, (i32)p.x, (i32)(win->h - p.y));
13340+	RGFW_rawMotionCallback(win, (float)vecX, (float)vecY);
13341+}
13342+
13343+static void RGFW__osxMouseDown(id self, SEL _cmd, id event) {
13344+	RGFW_UNUSED(_cmd);
13345+    RGFW_window* win = NULL;
13346+    object_getInstanceVariable(self, "RGFW_window", (void**)&win);
13347+    if (win == NULL) return;
13348+
13349+    u32 buttonNumber = (u32)((u32(*)(id, SEL))objc_msgSend)(event, sel_registerName("buttonNumber"));
13350+
13351+	RGFW_mouseButton value = 0;
13352+    switch (buttonNumber) {
13353+        case 0: value = RGFW_mouseLeft; break;
13354+        case 1: value = RGFW_mouseRight; break;
13355+        case 2: value = RGFW_mouseMiddle; break;
13356+        default: value = (u8)buttonNumber;
13357+    }
13358+
13359+    RGFW_mouseButtonCallback(win, value, 1);
13360+}
13361+
13362+static void RGFW__osxMouseUp(id self, SEL _cmd, id event) {
13363+	RGFW_UNUSED(_cmd);
13364+    RGFW_window* win = NULL;
13365+    object_getInstanceVariable(self, "RGFW_window", (void**)&win);
13366+    if (win == NULL) return;
13367+
13368+    u32 buttonNumber = (u32)((u32(*)(id, SEL))objc_msgSend)(event, sel_registerName("buttonNumber"));
13369+
13370+	RGFW_mouseButton value = 0;
13371+	switch (buttonNumber) {
13372+        case 0: value = RGFW_mouseLeft; break;
13373+        case 1: value = RGFW_mouseRight; break;
13374+        case 2: value = RGFW_mouseMiddle; break;
13375+        default: value = (u8)buttonNumber;
13376+    }
13377+
13378+    RGFW_mouseButtonCallback(win, value, 0);
13379+}
13380+
13381+static void RGFW__osxScrollWheel(id self, SEL _cmd, id event) {
13382+	RGFW_UNUSED(_cmd);
13383+    RGFW_window* win = NULL;
13384+    object_getInstanceVariable(self, "RGFW_window", (void**)&win);
13385+    if (win == NULL) return;
13386+
13387+    float deltaX = (float)((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(event, sel_registerName("deltaX"));
13388+	float deltaY = (float)((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(event, sel_registerName("deltaY"));
13389+
13390+    RGFW_mouseScrollCallback(win, deltaX, deltaY);
13391+}
13392+
13393+RGFW_format RGFW_nativeFormat(void) { return RGFW_formatRGBA8; }
13394+
13395+RGFW_bool RGFW_createSurfacePtr(u8* data, i32 w, i32 h, RGFW_format format, RGFW_surface* surface) {
13396+	surface->data = data;
13397+	surface->w = w;
13398+	surface->h = h;
13399+	surface->format = format;
13400+	surface->native.format = RGFW_formatRGBA8;
13401+
13402+	surface->native.buffer = (u8*)RGFW_ALLOC((size_t)(w * h * 4));
13403+	return RGFW_TRUE;
13404+}
13405+
13406+void RGFW_surface_freePtr(RGFW_surface* surface) {
13407+	RGFW_FREE(surface->native.buffer);
13408+}
13409+
13410+void RGFW_window_blitSurface(RGFW_window* win, RGFW_surface* surface) {
13411+	id pool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc"));
13412+	pool = objc_msgSend_id(pool, sel_registerName("init"));
13413+
13414+	int minW = RGFW_MIN(win->w, surface->w);
13415+	int minH = RGFW_MIN(win->h, surface->h);
13416+
13417+	RGFW_monitor* mon = RGFW_window_getMonitor(win);
13418+	if (mon == NULL) return;
13419+
13420+	minW =  (i32)((float)minW * mon->pixelRatio);
13421+	minH = (i32)((float)minH * mon->pixelRatio);
13422+
13423+	surface->native.rep = (void*)NSBitmapImageRep_initWithBitmapData(&surface->native.buffer, minW, minH, 8, 4, true, false, "NSDeviceRGBColorSpace", 1 << 1, (u32)surface->w * 4, 32);
13424+
13425+	id image = ((id (*)(Class, SEL))objc_msgSend)(objc_getClass("NSImage"), sel_getUid("alloc"));
13426+	NSSize size = (NSSize){(double)minW, (double)minH};
13427+	image = ((id (*)(id, SEL, NSSize))objc_msgSend)((id)image, sel_getUid("initWithSize:"), size);
13428+
13429+	RGFW_copyImageData(NSBitmapImageRep_bitmapData((id)surface->native.rep), surface->w, minH, RGFW_formatRGBA8, surface->data, surface->native.format, surface->convertFunc);
13430+	((void (*)(id, SEL, id))objc_msgSend)((id)image, sel_getUid("addRepresentation:"), (id)surface->native.rep);
13431+
13432+	id layer = ((id (*)(id, SEL))objc_msgSend)((id)win->src.view, sel_getUid("layer"));
13433+	((void (*)(id, SEL, id))objc_msgSend)(layer, sel_getUid("setContents:"), (id)image);
13434+
13435+	NSRelease(image);
13436+	NSRelease(surface->native.rep);
13437+
13438+	objc_msgSend_bool_void(pool, sel_registerName("drain"));
13439+}
13440+
13441+void* RGFW_window_getView_OSX(RGFW_window* win) { return win->src.view; }
13442+
13443+void RGFW_window_setLayer_OSX(RGFW_window* win, void* layer) {
13444+	objc_msgSend_void_id((id)win->src.view, sel_registerName("setLayer:"), (id)layer);
13445+}
13446+
13447+void* RGFW_getLayer_OSX(void) {
13448+	return objc_msgSend_class((id)objc_getClass("CAMetalLayer"), (SEL)sel_registerName("layer"));
13449+}
13450+void* RGFW_window_getWindow_OSX(RGFW_window* win) { return win->src.window; }
13451+
13452+void RGFW_initKeycodesPlatform(void) {
13453+	_RGFW->keycodes[0x1D] = RGFW_key0;
13454+	_RGFW->keycodes[0x12] = RGFW_key1;
13455+	_RGFW->keycodes[0x13] = RGFW_key2;
13456+	_RGFW->keycodes[0x14] = RGFW_key3;
13457+	_RGFW->keycodes[0x15] = RGFW_key4;
13458+	_RGFW->keycodes[0x17] = RGFW_key5;
13459+	_RGFW->keycodes[0x16] = RGFW_key6;
13460+	_RGFW->keycodes[0x1A] = RGFW_key7;
13461+	_RGFW->keycodes[0x1C] = RGFW_key8;
13462+	_RGFW->keycodes[0x19] = RGFW_key9;
13463+	_RGFW->keycodes[0x00] = RGFW_keyA;
13464+	_RGFW->keycodes[0x0B] = RGFW_keyB;
13465+	_RGFW->keycodes[0x08] = RGFW_keyC;
13466+	_RGFW->keycodes[0x02] = RGFW_keyD;
13467+	_RGFW->keycodes[0x0E] = RGFW_keyE;
13468+	_RGFW->keycodes[0x03] = RGFW_keyF;
13469+	_RGFW->keycodes[0x05] = RGFW_keyG;
13470+	_RGFW->keycodes[0x04] = RGFW_keyH;
13471+	_RGFW->keycodes[0x22] = RGFW_keyI;
13472+	_RGFW->keycodes[0x26] = RGFW_keyJ;
13473+	_RGFW->keycodes[0x28] = RGFW_keyK;
13474+	_RGFW->keycodes[0x25] = RGFW_keyL;
13475+	_RGFW->keycodes[0x2E] = RGFW_keyM;
13476+	_RGFW->keycodes[0x2D] = RGFW_keyN;
13477+	_RGFW->keycodes[0x1F] = RGFW_keyO;
13478+	_RGFW->keycodes[0x23] = RGFW_keyP;
13479+	_RGFW->keycodes[0x0C] = RGFW_keyQ;
13480+	_RGFW->keycodes[0x0F] = RGFW_keyR;
13481+	_RGFW->keycodes[0x01] = RGFW_keyS;
13482+	_RGFW->keycodes[0x11] = RGFW_keyT;
13483+	_RGFW->keycodes[0x20] = RGFW_keyU;
13484+	_RGFW->keycodes[0x09] = RGFW_keyV;
13485+	_RGFW->keycodes[0x0D] = RGFW_keyW;
13486+	_RGFW->keycodes[0x07] = RGFW_keyX;
13487+	_RGFW->keycodes[0x10] = RGFW_keyY;
13488+	_RGFW->keycodes[0x06] = RGFW_keyZ;
13489+	_RGFW->keycodes[0x27] = RGFW_keyApostrophe;
13490+	_RGFW->keycodes[0x2A] = RGFW_keyBackSlash;
13491+	_RGFW->keycodes[0x2B] = RGFW_keyComma;
13492+	_RGFW->keycodes[0x18] = RGFW_keyEquals;
13493+	_RGFW->keycodes[0x32] = RGFW_keyBacktick;
13494+	_RGFW->keycodes[0x21] = RGFW_keyBracket;
13495+	_RGFW->keycodes[0x1B] = RGFW_keyMinus;
13496+	_RGFW->keycodes[0x2F] = RGFW_keyPeriod;
13497+	_RGFW->keycodes[0x1E] = RGFW_keyCloseBracket;
13498+	_RGFW->keycodes[0x29] = RGFW_keySemicolon;
13499+	_RGFW->keycodes[0x2C] = RGFW_keySlash;
13500+	_RGFW->keycodes[0x0A] = RGFW_keyWorld1;
13501+	_RGFW->keycodes[0x33] = RGFW_keyBackSpace;
13502+	_RGFW->keycodes[0x39] = RGFW_keyCapsLock;
13503+	_RGFW->keycodes[0x75] = RGFW_keyDelete;
13504+	_RGFW->keycodes[0x7D] = RGFW_keyDown;
13505+	_RGFW->keycodes[0x77] = RGFW_keyEnd;
13506+	_RGFW->keycodes[0x24] = RGFW_keyEnter;
13507+	_RGFW->keycodes[0x35] = RGFW_keyEscape;
13508+	_RGFW->keycodes[0x7A] = RGFW_keyF1;
13509+	_RGFW->keycodes[0x78] = RGFW_keyF2;
13510+	_RGFW->keycodes[0x63] = RGFW_keyF3;
13511+	_RGFW->keycodes[0x76] = RGFW_keyF4;
13512+	_RGFW->keycodes[0x60] = RGFW_keyF5;
13513+	_RGFW->keycodes[0x61] = RGFW_keyF6;
13514+	_RGFW->keycodes[0x62] = RGFW_keyF7;
13515+	_RGFW->keycodes[0x64] = RGFW_keyF8;
13516+	_RGFW->keycodes[0x65] = RGFW_keyF9;
13517+	_RGFW->keycodes[0x6D] = RGFW_keyF10;
13518+	_RGFW->keycodes[0x67] = RGFW_keyF11;
13519+	_RGFW->keycodes[0x6F] = RGFW_keyF12;
13520+	_RGFW->keycodes[0x69] = RGFW_keyPrintScreen;
13521+	_RGFW->keycodes[0x6B] = RGFW_keyF14;
13522+	_RGFW->keycodes[0x71] = RGFW_keyF15;
13523+	_RGFW->keycodes[0x6A] = RGFW_keyF16;
13524+	_RGFW->keycodes[0x40] = RGFW_keyF17;
13525+	_RGFW->keycodes[0x4F] = RGFW_keyF18;
13526+	_RGFW->keycodes[0x50] = RGFW_keyF19;
13527+	_RGFW->keycodes[0x5A] = RGFW_keyF20;
13528+	_RGFW->keycodes[0x73] = RGFW_keyHome;
13529+	_RGFW->keycodes[0x72] = RGFW_keyInsert;
13530+	_RGFW->keycodes[0x7B] = RGFW_keyLeft;
13531+	_RGFW->keycodes[0x3A] = RGFW_keyAltL;
13532+	_RGFW->keycodes[0x3B] = RGFW_keyControlL;
13533+	_RGFW->keycodes[0x38] = RGFW_keyShiftL;
13534+	_RGFW->keycodes[0x37] = RGFW_keySuperL;
13535+	_RGFW->keycodes[0x6E] = RGFW_keyMenu;
13536+	_RGFW->keycodes[0x47] = RGFW_keyNumLock;
13537+	_RGFW->keycodes[0x79] = RGFW_keyPageDown;
13538+	_RGFW->keycodes[0x74] = RGFW_keyPageUp;
13539+	_RGFW->keycodes[0x7C] = RGFW_keyRight;
13540+	_RGFW->keycodes[0x3D] = RGFW_keyAltR;
13541+	_RGFW->keycodes[0x3E] = RGFW_keyControlR;
13542+	_RGFW->keycodes[0x3C] = RGFW_keyShiftR;
13543+	_RGFW->keycodes[0x36] = RGFW_keySuperR;
13544+	_RGFW->keycodes[0x31] = RGFW_keySpace;
13545+	_RGFW->keycodes[0x30] = RGFW_keyTab;
13546+	_RGFW->keycodes[0x7E] = RGFW_keyUp;
13547+	_RGFW->keycodes[0x52] = RGFW_keyPad0;
13548+	_RGFW->keycodes[0x53] = RGFW_keyPad1;
13549+	_RGFW->keycodes[0x54] = RGFW_keyPad2;
13550+	_RGFW->keycodes[0x55] = RGFW_keyPad3;
13551+	_RGFW->keycodes[0x56] = RGFW_keyPad4;
13552+	_RGFW->keycodes[0x57] = RGFW_keyPad5;
13553+	_RGFW->keycodes[0x58] = RGFW_keyPad6;
13554+	_RGFW->keycodes[0x59] = RGFW_keyPad7;
13555+	_RGFW->keycodes[0x5B] = RGFW_keyPad8;
13556+	_RGFW->keycodes[0x5C] = RGFW_keyPad9;
13557+	_RGFW->keycodes[0x45] = RGFW_keyPadSlash;
13558+	_RGFW->keycodes[0x41] = RGFW_keyPadPeriod;
13559+	_RGFW->keycodes[0x4B] = RGFW_keyPadSlash;
13560+	_RGFW->keycodes[0x4C] = RGFW_keyPadReturn;
13561+	_RGFW->keycodes[0x51] = RGFW_keyPadEqual;
13562+	_RGFW->keycodes[0x43] = RGFW_keyPadMultiply;
13563+	_RGFW->keycodes[0x4E] = RGFW_keyPadMinus;
13564+}
13565+
13566+i32 RGFW_initPlatform(void) {
13567+	_RGFW->tisBundle = (void*)CFBundleGetBundleWithIdentifier(CFSTR("com.apple.HIToolbox"));
13568+
13569+	TISGetInputSourcePropertySrc = (PFN_TISGetInputSourceProperty)CFBundleGetFunctionPointerForName((CFBundleRef)_RGFW->tisBundle, CFSTR("TISGetInputSourceProperty"));
13570+	TISCopyCurrentKeyboardLayoutInputSourceSrc = (PFN_TISCopyCurrentKeyboardLayoutInputSource)CFBundleGetFunctionPointerForName((CFBundleRef)_RGFW->tisBundle, CFSTR("TISCopyCurrentKeyboardLayoutInputSource"));
13571+	LMGetKbdTypeSrc = (PFN_LMGetKbdType)CFBundleGetFunctionPointerForName((CFBundleRef)_RGFW->tisBundle, CFSTR("LMGetKbdType"));
13572+
13573+	CFStringRef* cfStr = (CFStringRef*)CFBundleGetDataPointerForName((CFBundleRef)_RGFW->tisBundle, CFSTR("kTISPropertyUnicodeKeyLayoutData"));;
13574+	if (cfStr) kTISPropertyUnicodeKeyLayoutDataSrc = *cfStr;
13575+
13576+	class_addMethod(objc_getClass("NSObject"), sel_registerName("windowShouldClose:"), (IMP)(void*)RGFW_OnClose, 0);
13577+
13578+	/* NOTE(EimaMei): Fixes the 'Boop' sfx from constantly playing each time you click a key. Only a problem when running in the terminal. */
13579+	class_addMethod(objc_getClass("NSWindowClass"), sel_registerName("acceptsFirstResponder:"), (IMP)(void*)RGFW__osxAcceptsFirstResponder, 0);
13580+	class_addMethod(objc_getClass("NSWindowClass"), sel_registerName("performKeyEquivalent:"), (IMP)(void*)RGFW__osxPerformKeyEquivalent, 0);
13581+
13582+	_RGFW->NSApp = objc_msgSend_id(objc_getClass("NSApplication"), sel_registerName("sharedApplication"));
13583+
13584+	NSRetain(_RGFW->NSApp);
13585+
13586+	_RGFW->customNSAppDelegateClass = objc_allocateClassPair(objc_getClass("NSObject"), "RGFWNSAppDelegate", 0);
13587+	class_addMethod((Class)_RGFW->customNSAppDelegateClass, sel_registerName("applicationDidChangeScreenParameters:"), (IMP)RGFW__osxDidChangeScreenParameters, "v@:@");
13588+	objc_registerClassPair((Class)_RGFW->customNSAppDelegateClass);
13589+	_RGFW->customNSAppDelegate = objc_msgSend_id(NSAlloc(_RGFW->customNSAppDelegateClass), sel_registerName("init"));
13590+
13591+	objc_msgSend_void_id(_RGFW->NSApp, sel_registerName("setDelegate:"), _RGFW->customNSAppDelegate);
13592+
13593+	((void (*)(id, SEL, NSUInteger))objc_msgSend) ((id)_RGFW->NSApp, sel_registerName("setActivationPolicy:"), NSApplicationActivationPolicyRegular);
13594+
13595+	_RGFW->customViewClasses[0] = objc_allocateClassPair(objc_getClass("NSView"), "RGFWCustomView", 0);
13596+	_RGFW->customViewClasses[1] = objc_allocateClassPair(objc_getClass("NSOpenGLView"), "RGFWOpenGLCustomView", 0);
13597+	for (size_t i = 0; i < 2; i++) {
13598+		class_addIvar((Class)_RGFW->customViewClasses[i], "RGFW_window", sizeof(RGFW_window*), sizeof(RGFW_window*), "L");
13599+		class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("drawRect:"), (IMP)RGFW__osxDrawRect, "v@:{CGRect=ffff}");
13600+		class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("viewDidChangeBackingProperties"), (IMP)RGFW__osxViewDidChangeBackingProperties, "v@:");
13601+		class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("mouseDown:"), (IMP)RGFW__osxMouseDown, "v@:@");
13602+		class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("rightMouseDown:"), (IMP)RGFW__osxMouseDown, "v@:@");
13603+		class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("otherMouseDown:"), (IMP)RGFW__osxMouseDown, "v@:@");
13604+		class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("mouseUp:"), (IMP)RGFW__osxMouseUp, "v@:@");
13605+		class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("rightMouseUp:"), (IMP)RGFW__osxMouseUp, "v@:@");
13606+		class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("otherMouseUp:"), (IMP)RGFW__osxMouseUp, "v@:@");
13607+		class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("scrollWheel:"), (IMP)RGFW__osxScrollWheel, "v@:@");
13608+		class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("mouseDragged:"), (IMP)RGFW__osxMouseMoved, "v@:@");
13609+		class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("rightMouseDragged:"), (IMP)RGFW__osxMouseMoved, "v@:@");
13610+		class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("otherMouseDragged:"), (IMP)RGFW__osxMouseMoved, "v@:@");
13611+		class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("keyDown:"), (IMP)RGFW__osxKeyDown, "v@:@");
13612+		class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("keyUp:"), (IMP)RGFW__osxKeyUp, "v@:@");
13613+		class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("mouseMoved:"), (IMP)RGFW__osxMouseMoved, "v@:@");
13614+		class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("mouseEntered:"), (IMP)RGFW__osxMouseEntered, "v@:@");
13615+		class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("mouseExited:"), (IMP)RGFW__osxMouseExited, "v@:@");
13616+		class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("flagsChanged:"), (IMP)RGFW__osxFlagsChanged, "v@:@");
13617+		class_addMethod((Class)_RGFW->customViewClasses[i], sel_getUid("acceptsFirstResponder"), (IMP)RGFW__osxAcceptsFirstResponder, "B@:");
13618+		class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("initWithRGFWWindow:"), (IMP)RGFW__osxCustomInitWithRGFWWindow, "@@:{CGRect={CGPoint=dd}{CGSize=dd}}");
13619+		class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("wantsUpdateLayer"), (IMP)RGFW__osxWantsUpdateLayer, "B@:");
13620+		class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("updateLayer"), (IMP)RGFW__osxUpdateLayer, "v@:");
13621+		objc_registerClassPair((Class)_RGFW->customViewClasses[i]);
13622+	}
13623+
13624+	_RGFW->customWindowDelegateClass = objc_allocateClassPair(objc_getClass("NSObject"), "RGFWWindowDelegate", 0);
13625+	class_addIvar((Class)_RGFW->customWindowDelegateClass, "RGFW_window", sizeof(RGFW_window*), sizeof(RGFW_window*), "L");
13626+	class_addMethod((Class)_RGFW->customWindowDelegateClass, sel_registerName("windowDidResize:"), (IMP)RGFW__osxDidWindowResize, "v@:@");
13627+	class_addMethod((Class)_RGFW->customWindowDelegateClass, sel_registerName("windowDidMove:"), (IMP) RGFW__osxWindowMove, "");
13628+	class_addMethod((Class)_RGFW->customWindowDelegateClass, sel_registerName("windowDidMiniaturize:"), (IMP) RGFW__osxWindowMiniaturize, "");
13629+	class_addMethod((Class)_RGFW->customWindowDelegateClass, sel_registerName("windowDidDeminiaturize:"), (IMP) RGFW__osxWindowDeminiaturize, "");
13630+	class_addMethod((Class)_RGFW->customWindowDelegateClass, sel_registerName("windowDidBecomeKey:"), (IMP) RGFW__osxWindowBecameKey, "");
13631+	class_addMethod((Class)_RGFW->customWindowDelegateClass, sel_registerName("windowDidResignKey:"), (IMP) RGFW__osxWindowResignKey, "");
13632+	class_addMethod((Class)_RGFW->customWindowDelegateClass, sel_registerName("draggingEntered:"), (IMP)RGFW__osxDraggingEntered, "l@:@");
13633+	class_addMethod((Class)_RGFW->customWindowDelegateClass, sel_registerName("draggingUpdated:"), (IMP)RGFW__osxDraggingUpdated, "l@:@");
13634+	class_addMethod((Class)_RGFW->customWindowDelegateClass, sel_registerName("draggingExited:"), (IMP)RGFW__osxDraggingEnded, "v@:@");
13635+	class_addMethod((Class)_RGFW->customWindowDelegateClass, sel_registerName("draggingEnded:"), (IMP)RGFW__osxDraggingEnded, "v@:@");
13636+	class_addMethod((Class)_RGFW->customWindowDelegateClass, sel_registerName("prepareForDragOperation:"), (IMP)RGFW__osxPrepareForDragOperation, "B@:@");
13637+	class_addMethod((Class)_RGFW->customWindowDelegateClass, sel_registerName("performDragOperation:"), (IMP)RGFW__osxPerformDragOperation, "B@:@");
13638+	objc_registerClassPair((Class)_RGFW->customWindowDelegateClass);
13639+	return 0;
13640+}
13641+
13642+void RGFW_osx_initView(RGFW_window* win) {
13643+	NSRect contentRect;
13644+	contentRect.origin.x = 0;
13645+	contentRect.origin.y = 0;
13646+	contentRect.size.width = (double)win->w;
13647+	contentRect.size.height = (double)win->h;
13648+	((void(*)(id, SEL, CGRect))objc_msgSend)((id)win->src.view, sel_registerName("setFrame:"), contentRect);
13649+
13650+
13651+	if (RGFW_COCOA_FRAME_NAME)
13652+		objc_msgSend_ptr(win->src.view, sel_registerName("setFrameAutosaveName:"), RGFW_COCOA_FRAME_NAME);
13653+
13654+	object_setInstanceVariable((id)win->src.view, "RGFW_window", win);
13655+	objc_msgSend_void_id((id)win->src.window, sel_registerName("setContentView:"), win->src.view);
13656+	objc_msgSend_void_bool(win->src.view, sel_registerName("setWantsLayer:"), true);
13657+	objc_msgSend_int((id)win->src.view, sel_registerName("setLayerContentsPlacement:"),  4);
13658+
13659+	id trackingArea = objc_msgSend_id(objc_getClass("NSTrackingArea"), sel_registerName("alloc"));
13660+	trackingArea = ((id (*)(id, SEL, NSRect, NSUInteger, id, id))objc_msgSend)(
13661+		trackingArea,
13662+		sel_registerName("initWithRect:options:owner:userInfo:"),
13663+		contentRect,
13664+		NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways | NSTrackingInVisibleRect,
13665+		(id)win->src.view,
13666+		nil
13667+	);
13668+
13669+	((void (*)(id, SEL, id))objc_msgSend)((id)win->src.view, sel_registerName("addTrackingArea:"), trackingArea);
13670+	((void (*)(id, SEL))objc_msgSend)(trackingArea, sel_registerName("release"));
13671+}
13672+
13673+RGFW_window* RGFW_createWindowPlatform(const char* name, RGFW_windowFlags flags, RGFW_window* win) {
13674+	/* RR Create an autorelease pool */
13675+	id pool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc"));
13676+	pool = objc_msgSend_id(pool, sel_registerName("init"));
13677+
13678+	RGFW_window_setMouseDefault(win);
13679+
13680+	NSRect windowRect;
13681+	windowRect.origin.x = (double)win->x;
13682+	windowRect.origin.y = (double)RGFW_cocoaYTransform((float)(win->y + win->h - 1));
13683+	windowRect.size.width = (double)win->w;
13684+	windowRect.size.height = (double)win->h;
13685+	NSBackingStoreType macArgs = (NSBackingStoreType)(NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSBackingStoreBuffered | NSWindowStyleMaskTitled);
13686+
13687+	if (!(flags & RGFW_windowNoResize))
13688+		macArgs = (NSBackingStoreType)(macArgs | (NSBackingStoreType)NSWindowStyleMaskResizable);
13689+	if (!(flags & RGFW_windowNoBorder))
13690+		macArgs = (NSBackingStoreType)(macArgs | (NSBackingStoreType)NSWindowStyleMaskTitled);
13691+	{
13692+		void* nsclass = objc_getClass("NSWindow");
13693+		SEL func = sel_registerName("initWithContentRect:styleMask:backing:defer:");
13694+
13695+		win->src.window = ((id(*)(id, SEL, NSRect, NSWindowStyleMask, NSBackingStoreType, bool))objc_msgSend)
13696+			(NSAlloc(nsclass), func, windowRect, (NSWindowStyleMask)macArgs, macArgs, false);
13697+	}
13698+
13699+	id str = NSString_stringWithUTF8String(name);
13700+	objc_msgSend_void_id((id)win->src.window, sel_registerName("setTitle:"), str);
13701+
13702+	win->src.delegate = (void*)objc_msgSend_id(NSAlloc((Class)_RGFW->customWindowDelegateClass), sel_registerName("init"));
13703+	object_setInstanceVariable((id)win->src.delegate, "RGFW_window", win);
13704+
13705+	objc_msgSend_void_id((id)win->src.window, sel_registerName("setDelegate:"), (id)win->src.delegate);
13706+
13707+	if (flags & RGFW_windowAllowDND) {
13708+		win->internal.flags |= RGFW_windowAllowDND;
13709+
13710+		NSPasteboardType types[] = {NSPasteboardTypeURL, NSPasteboardTypeFileURL, NSPasteboardTypeString};
13711+		NSregisterForDraggedTypes((id)win->src.window, types, 3);
13712+	}
13713+
13714+	objc_msgSend_void_bool((id)win->src.window, sel_registerName("setAcceptsMouseMovedEvents:"), true);
13715+
13716+	if (flags & RGFW_windowTransparent) {
13717+		objc_msgSend_void_bool(win->src.window, sel_registerName("setOpaque:"), false);
13718+
13719+		objc_msgSend_void_id((id)win->src.window, sel_registerName("setBackgroundColor:"),
13720+		NSColor_colorWithSRGB(0, 0, 0, 0));
13721+	}
13722+
13723+	/* Show the window */
13724+	objc_msgSend_void_bool((id)_RGFW->NSApp, sel_registerName("activateIgnoringOtherApps:"), true);
13725+
13726+	if (_RGFW->root == NULL) {
13727+		objc_msgSend_void(win->src.window, sel_registerName("makeMainWindow"));
13728+	}
13729+
13730+	objc_msgSend_void(win->src.window, sel_registerName("makeKeyWindow"));
13731+
13732+	NSRetain(win->src.window);
13733+
13734+	win->src.view = ((id(*)(id, SEL, RGFW_window*))objc_msgSend) (NSAlloc((Class)_RGFW->customViewClasses[0]), sel_registerName("initWithRGFWWindow:"), win);
13735+	return win;
13736+}
13737+
13738+void RGFW_window_setBorder(RGFW_window* win, RGFW_bool border) {
13739+	NSRect frame = ((NSRect(*)(id, SEL))abi_objc_msgSend_stret)((id)win->src.window, sel_registerName("frame"));
13740+	NSRect content = ((NSRect(*)(id, SEL))abi_objc_msgSend_stret)((id)win->src.view, sel_registerName("frame"));
13741+	double offset = 0;
13742+
13743+	RGFW_setBit(&win->internal.flags, RGFW_windowNoBorder, !border);
13744+	NSBackingStoreType storeType = (NSBackingStoreType)(NSWindowStyleMaskBorderless | NSWindowStyleMaskFullSizeContentView);
13745+	if (border)
13746+		storeType = (NSBackingStoreType)(NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable);
13747+	if (!(win->internal.flags & RGFW_windowNoResize)) {
13748+		storeType = (NSBackingStoreType)(storeType | (NSBackingStoreType)NSWindowStyleMaskResizable);
13749+	}
13750+
13751+	((void (*)(id, SEL, NSBackingStoreType))objc_msgSend)((id)win->src.window, sel_registerName("setStyleMask:"), storeType);
13752+
13753+	if (!border) {
13754+		id miniaturizeButton = objc_msgSend_int((id)win->src.window, sel_registerName("standardWindowButton:"),  NSWindowMiniaturizeButton);
13755+		id titleBarView = objc_msgSend_id(miniaturizeButton, sel_registerName("superview"));
13756+		objc_msgSend_void_bool(titleBarView, sel_registerName("setHidden:"), true);
13757+
13758+		offset = (double)(frame.size.height - content.size.height);
13759+	}
13760+
13761+	RGFW_window_resize(win, win->w, win->h + (i32)offset);
13762+	win->h -= (i32)offset;
13763+}
13764+
13765+RGFW_bool RGFW_getGlobalMouse(i32* x, i32* y) {
13766+	RGFW_ASSERT(_RGFW->root != NULL);
13767+
13768+	CGEventRef e = CGEventCreate(NULL);
13769+	CGPoint point = CGEventGetLocation(e);
13770+	CFRelease(e);
13771+
13772+	if (x) *x = (i32)point.x;
13773+	if (y) *y = (i32)point.y;
13774+	return RGFW_TRUE;
13775+}
13776+
13777+void RGFW_stopCheckEvents(void) {
13778+	id eventPool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc"));
13779+	eventPool = objc_msgSend_id(eventPool, sel_registerName("init"));
13780+
13781+	id e = (id) ((id(*)(Class, SEL, NSEventType, NSPoint, NSEventModifierFlags, void*, NSInteger, void**, short, NSInteger, NSInteger))objc_msgSend)
13782+		(objc_getClass("NSEvent"), sel_registerName("otherEventWithType:location:modifierFlags:timestamp:windowNumber:context:subtype:data1:data2:"),
13783+			NSEventTypeApplicationDefined, (NSPoint){0, 0}, (NSEventModifierFlags)0, NULL, (NSInteger)0, NULL, 0, 0, 0);
13784+
13785+	((void (*)(id, SEL, id, bool))objc_msgSend)
13786+		((id)_RGFW->NSApp, sel_registerName("postEvent:atStart:"), e, 1);
13787+
13788+	objc_msgSend_bool_void(eventPool, sel_registerName("drain"));
13789+}
13790+
13791+void RGFW_waitForEvent(i32 waitMS) {
13792+	id eventPool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc"));
13793+	eventPool = objc_msgSend_id(eventPool, sel_registerName("init"));
13794+
13795+	void* date = (void*) ((id(*)(Class, SEL, double))objc_msgSend)
13796+				(objc_getClass("NSDate"), sel_registerName("dateWithTimeIntervalSinceNow:"), waitMS);
13797+
13798+	SEL eventFunc = sel_registerName("nextEventMatchingMask:untilDate:inMode:dequeue:");
13799+	id e = (id) ((id(*)(id, SEL, NSEventMask, void*, id, bool))objc_msgSend)
13800+		((id)_RGFW->NSApp, eventFunc,
13801+			ULONG_MAX, date, NSString_stringWithUTF8String("kCFRunLoopDefaultMode"), true);
13802+
13803+	if (e) {
13804+		((void (*)(id, SEL, id, bool))objc_msgSend)
13805+			((id)_RGFW->NSApp, sel_registerName("postEvent:atStart:"), e, 1);
13806+	}
13807+
13808+	objc_msgSend_bool_void(eventPool, sel_registerName("drain"));
13809+}
13810+
13811+RGFW_key RGFW_physicalToMappedKey(RGFW_key key) {
13812+    u16 keycode = (u16)RGFW_rgfwToApiKey(key);
13813+    TISInputSourceRef source = TISCopyCurrentKeyboardLayoutInputSource();
13814+    if (source == NULL)
13815+        return key;
13816+
13817+    CFDataRef layoutData = TISGetInputSourceProperty(source, kTISPropertyUnicodeKeyLayoutDataSrc);
13818+
13819+    if (layoutData == NULL) {
13820+        CFRelease(source);
13821+        return key;
13822+    }
13823+
13824+    UCKeyboardLayout *layout = (UCKeyboardLayout*)(void*)CFDataGetBytePtr(layoutData);
13825+
13826+    UInt32 deadKeyState = 0;
13827+    UniChar chars[4];
13828+    UniCharCount len = 0;
13829+	u32 type =  LMGetKbdType();
13830+	OSStatus status = UCKeyTranslate(layout, keycode, kUCKeyActionDown, 0, type, kUCKeyTranslateNoDeadKeysBit, &deadKeyState, 4, &len, chars );
13831+
13832+    CFRelease(source);
13833+
13834+    if (status == noErr && len == 1 && chars[0] < 256) {
13835+        return (RGFW_key)chars[0];
13836+    }
13837+
13838+	return key;
13839+}
13840+
13841+RGFW_bool RGFW_window_fetchSize(RGFW_window* win, i32* w, i32* h) {
13842+	NSRect content = ((NSRect(*)(id, SEL))abi_objc_msgSend_stret)((id)win->src.view, sel_registerName("frame"));
13843+
13844+	win->w = (i32)content.size.width;
13845+	win->h = (i32)content.size.height;
13846+
13847+	return RGFW_window_getSize(win, w, h);
13848+}
13849+
13850+void RGFW_pollEvents(void) {
13851+	RGFW_resetPrevState();
13852+
13853+	id eventPool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc"));
13854+	eventPool = objc_msgSend_id(eventPool, sel_registerName("init"));
13855+	SEL eventFunc = sel_registerName("nextEventMatchingMask:untilDate:inMode:dequeue:");
13856+
13857+	while (1) {
13858+		void* date = NULL;
13859+		id e = (id) ((id(*)(id, SEL, NSEventMask, void*, id, bool))objc_msgSend)
13860+			((id)_RGFW->NSApp, eventFunc, ULONG_MAX, date, NSString_stringWithUTF8String("kCFRunLoopDefaultMode"), true);
13861+
13862+		if (e == NULL) {
13863+			break;
13864+		}
13865+
13866+		objc_msgSend_void_id((id)_RGFW->NSApp, sel_registerName("sendEvent:"), e);
13867+	}
13868+
13869+	objc_msgSend_bool_void(eventPool, sel_registerName("drain"));
13870+}
13871+
13872+
13873+void RGFW_window_move(RGFW_window* win, i32 x, i32 y) {
13874+	RGFW_ASSERT(win != NULL);
13875+
13876+	NSRect content = ((NSRect(*)(id, SEL))abi_objc_msgSend_stret)((id)win->src.view, sel_registerName("frame"));
13877+
13878+	win->x = x;
13879+	win->y = (i32)RGFW_cocoaYTransform((float)y + (float)content.size.height - 1.0f);
13880+
13881+	((void(*)(id,SEL,NSPoint))objc_msgSend)((id)win->src.window, sel_registerName("setFrameOrigin:"), (NSPoint){(double)x, (double)y});
13882+}
13883+
13884+void RGFW_window_resize(RGFW_window* win, i32 w, i32 h) {
13885+	RGFW_ASSERT(win != NULL);
13886+
13887+	NSRect frame = ((NSRect(*)(id, SEL))abi_objc_msgSend_stret)((id)win->src.window, sel_registerName("frame"));
13888+	NSRect content = ((NSRect(*)(id, SEL))abi_objc_msgSend_stret)((id)win->src.view, sel_registerName("frame"));
13889+	float offset = (float)(frame.size.height - content.size.height);
13890+
13891+	win->w = w;
13892+	win->h = h;
13893+
13894+
13895+	((void(*)(id, SEL, CGRect))objc_msgSend)((id)win->src.view, sel_registerName("setFrame:"),  (NSRect){{0, 0}, {(double)win->w, (double)win->h}});
13896+	((void(*)(id, SEL, NSRect, bool, bool))objc_msgSend)
13897+		((id)win->src.window, sel_registerName("setFrame:display:animate:"), (NSRect){{(double)win->x, (double)win->y}, {(double)win->w, (double)win->h + (double)offset}}, true, true);
13898+}
13899+
13900+void RGFW_window_focus(RGFW_window* win) {
13901+	RGFW_ASSERT(win);
13902+	objc_msgSend_void_bool((id)_RGFW->NSApp, sel_registerName("activateIgnoringOtherApps:"), true);
13903+	((void (*)(id, SEL))objc_msgSend)((id)win->src.window, sel_registerName("makeKeyWindow"));
13904+}
13905+
13906+void RGFW_window_raise(RGFW_window* win) {
13907+	RGFW_ASSERT(win != NULL);
13908+	((id(*)(id, SEL, SEL))objc_msgSend)((id)win->src.window, sel_registerName("orderFront:"), (SEL)NULL);
13909+    	objc_msgSend_void_id(win->src.window, sel_registerName("setLevel:"), kCGNormalWindowLevelKey);
13910+}
13911+
13912+void RGFW_window_setFullscreen(RGFW_window* win, RGFW_bool fullscreen) {
13913+	RGFW_ASSERT(win != NULL);
13914+	if (fullscreen && (win->internal.flags & RGFW_windowFullscreen)) return;
13915+	if (!fullscreen && !(win->internal.flags & RGFW_windowFullscreen)) return;
13916+
13917+	if (fullscreen) {
13918+		win->internal.oldX = win->x;
13919+		win->internal.oldY = win->y;
13920+		win->internal.oldW = win->w;
13921+		win->internal.oldH = win->h;
13922+
13923+		win->internal.flags |= RGFW_windowFullscreen;
13924+
13925+		RGFW_monitor* mon = RGFW_window_getMonitor(win);
13926+		RGFW_monitor_scaleToWindow(mon, win);
13927+
13928+		RGFW_window_setBorder(win, RGFW_FALSE);
13929+
13930+		if (mon != NULL) {
13931+			win->x = mon->x;
13932+			win->y = mon->y;
13933+			win->w = mon->mode.w;
13934+			win->h = mon->mode.h;
13935+			RGFW_window_resize(win, mon->mode.w, mon->mode.h);
13936+			RGFW_window_move(win, mon->x, mon->y);
13937+		}
13938+
13939+		((id(*)(id, SEL, SEL))objc_msgSend)((id)win->src.window, sel_registerName("orderFront:"), (SEL)NULL);
13940+		objc_msgSend_void_id(win->src.window, sel_registerName("setLevel:"), 25);
13941+	}
13942+
13943+	objc_msgSend_void_SEL(win->src.window, sel_registerName("toggleFullScreen:"), NULL);
13944+
13945+	if (!fullscreen) {
13946+		win->x  = win->internal.oldX;
13947+		win->y  = win->internal.oldY;
13948+		win->w  = win->internal.oldW;
13949+		win->h = win->internal.oldH;
13950+		win->internal.flags &= ~(u32)RGFW_windowFullscreen;
13951+
13952+		RGFW_window_resize(win, win->w, win->h);
13953+		RGFW_window_move(win, win->x, win->y);
13954+	}
13955+}
13956+
13957+void RGFW_window_maximize(RGFW_window* win) {
13958+	RGFW_ASSERT(win != NULL);
13959+	if (RGFW_window_isMaximized(win)) return;
13960+
13961+	win->internal.flags |= RGFW_windowMaximize;
13962+	objc_msgSend_void_SEL(win->src.window, sel_registerName("zoom:"), NULL);
13963+	RGFW_window_fetchSize(win, NULL, NULL);
13964+}
13965+
13966+void RGFW_window_minimize(RGFW_window* win) {
13967+	RGFW_ASSERT(win != NULL);
13968+	objc_msgSend_void_SEL(win->src.window, sel_registerName("performMiniaturize:"), NULL);
13969+}
13970+
13971+void RGFW_window_setFloating(RGFW_window* win, RGFW_bool floating) {
13972+    RGFW_ASSERT(win != NULL);
13973+    if (floating) objc_msgSend_void_id(win->src.window, sel_registerName("setLevel:"), kCGFloatingWindowLevelKey);
13974+    else 		  objc_msgSend_void_id(win->src.window, sel_registerName("setLevel:"), kCGNormalWindowLevelKey);
13975+}
13976+
13977+void RGFW_window_setOpacity(RGFW_window* win, u8 opacity) {
13978+	objc_msgSend_int(win->src.window, sel_registerName("setAlphaValue:"), opacity);
13979+	objc_msgSend_void_bool(win->src.window, sel_registerName("setOpaque:"), (opacity < (u8)255));
13980+
13981+	if (opacity)
13982+		objc_msgSend_void_id((id)win->src.window, sel_registerName("setBackgroundColor:"), NSColor_colorWithSRGB(0, 0, 0, opacity));
13983+
13984+}
13985+
13986+void RGFW_window_restore(RGFW_window* win) {
13987+	RGFW_ASSERT(win != NULL);
13988+
13989+	if (RGFW_window_isMaximized(win))
13990+		objc_msgSend_void_SEL(win->src.window, sel_registerName("zoom:"), NULL);
13991+
13992+	objc_msgSend_void_SEL(win->src.window, sel_registerName("deminiaturize:"), NULL);
13993+	RGFW_window_show(win);
13994+}
13995+
13996+RGFW_bool RGFW_window_isFloating(RGFW_window* win) {
13997+	RGFW_ASSERT(win != NULL);
13998+	int level = ((int (*)(id, SEL))objc_msgSend) ((id)(win->src.window), (SEL)sel_registerName("level"));
13999+	return level > kCGNormalWindowLevelKey;
14000+}
14001+
14002+void RGFW_window_setName(RGFW_window* win, const char* name) {
14003+	RGFW_ASSERT(win != NULL);
14004+	if (name == NULL) name = "\0";
14005+
14006+	id str = NSString_stringWithUTF8String(name);
14007+	objc_msgSend_void_id((id)win->src.window, sel_registerName("setTitle:"), str);
14008+}
14009+
14010+#ifndef RGFW_NO_PASSTHROUGH
14011+void RGFW_window_setMousePassthrough(RGFW_window* win, RGFW_bool passthrough) {
14012+	objc_msgSend_void_bool(win->src.window, sel_registerName("setIgnoresMouseEvents:"), passthrough);
14013+}
14014+#endif
14015+
14016+void RGFW_window_setAspectRatio(RGFW_window* win, i32 w, i32 h) {
14017+	if (w == 0 && h == 0) {  w = 1; h = 1; };
14018+
14019+	((void (*)(id, SEL, NSSize))objc_msgSend)
14020+		((id)win->src.window, sel_registerName("setContentAspectRatio:"), (NSSize){(CGFloat)w, (CGFloat)h});
14021+}
14022+
14023+void RGFW_window_setMinSize(RGFW_window* win, i32 w, i32 h) {
14024+	((void (*)(id, SEL, NSSize))objc_msgSend) ((id)win->src.window, sel_registerName("setMinSize:"), (NSSize){(CGFloat)w, (CGFloat)h});
14025+}
14026+
14027+void RGFW_window_setMaxSize(RGFW_window* win, i32 w, i32 h) {
14028+	if (w == 0 && h == 0) {
14029+		RGFW_monitor* mon = RGFW_window_getMonitor(win);
14030+		if (mon != NULL) {
14031+			w = mon->mode.w;
14032+			h = mon->mode.h;
14033+		}
14034+	}
14035+
14036+	((void (*)(id, SEL, NSSize))objc_msgSend)
14037+		((id)win->src.window, sel_registerName("setMaxSize:"), (NSSize){(CGFloat)w, (CGFloat)h});
14038+}
14039+
14040+RGFW_bool RGFW_window_setIconEx(RGFW_window* win, u8* data, i32 w, i32 h, RGFW_format format, RGFW_icon type) {
14041+	RGFW_ASSERT(win != NULL);
14042+	RGFW_UNUSED(type);
14043+
14044+	id pool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc"));
14045+	pool = objc_msgSend_id(pool, sel_registerName("init"));
14046+
14047+	if (data == NULL) {
14048+		objc_msgSend_void_id((id)_RGFW->NSApp, sel_registerName("setApplicationIconImage:"), NULL);
14049+		objc_msgSend_bool_void(pool, sel_registerName("drain"));
14050+		return RGFW_TRUE;
14051+	}
14052+
14053+	id representation = NSBitmapImageRep_initWithBitmapData(NULL, w, h, 8, (NSInteger)4, true, false, "NSCalibratedRGBColorSpace", 1 << 1, w * 4, 32);
14054+	RGFW_copyImageData(NSBitmapImageRep_bitmapData(representation), w, h, RGFW_formatRGBA8, data, format, NULL);
14055+
14056+	id dock_image = ((id(*)(id, SEL, NSSize))objc_msgSend) (NSAlloc((id)objc_getClass("NSImage")), sel_registerName("initWithSize:"), ((NSSize){(CGFloat)w, (CGFloat)h}));
14057+
14058+	objc_msgSend_void_id(dock_image, sel_registerName("addRepresentation:"), representation);
14059+
14060+	objc_msgSend_void_id((id)_RGFW->NSApp, sel_registerName("setApplicationIconImage:"), dock_image);
14061+
14062+	NSRelease(dock_image);
14063+	NSRelease(representation);
14064+
14065+	objc_msgSend_bool_void(pool, sel_registerName("drain"));
14066+
14067+	return RGFW_TRUE;
14068+}
14069+
14070+id NSCursor_arrowStr(const char* str);
14071+id NSCursor_arrowStr(const char* str) {
14072+	void* nclass = objc_getClass("NSCursor");
14073+	SEL func = sel_registerName(str);
14074+	id mouse = (id) objc_msgSend_id(nclass, func);
14075+	NSRetain(mouse);
14076+	return mouse;
14077+}
14078+
14079+RGFW_mouse* RGFW_createMouseStandard(RGFW_mouseIcon mouse) {
14080+	switch (mouse) {
14081+        case RGFW_mouseNormal: return NSCursor_arrowStr("arrowCursor");
14082+        case RGFW_mouseArrow: return NSCursor_arrowStr("arrowCursor");
14083+        case RGFW_mouseIbeam: return NSCursor_arrowStr("IBeamCursor");
14084+        case RGFW_mouseCrosshair: return NSCursor_arrowStr("crosshairCursor");
14085+        case RGFW_mousePointingHand: return NSCursor_arrowStr("pointingHandCursor");
14086+        case RGFW_mouseResizeEW: return NSCursor_arrowStr("resizeLeftRightCursor");
14087+        case RGFW_mouseResizeE: return NSCursor_arrowStr("resizeLeftRightCursor");
14088+        case RGFW_mouseResizeW: return NSCursor_arrowStr("resizeLeftRightCursor");
14089+        case RGFW_mouseResizeNS: return NSCursor_arrowStr("resizeUpDownCursor");
14090+        case RGFW_mouseResizeN: return NSCursor_arrowStr("resizeUpDownCursor");
14091+        case RGFW_mouseResizeS: return NSCursor_arrowStr("resizeUpDownCursor");
14092+        case RGFW_mouseResizeNWSE: return NSCursor_arrowStr("_windowResizeNorthWestSouthEastCursor");
14093+        case RGFW_mouseResizeNW: return NSCursor_arrowStr("_windowResizeNorthWestSouthEastCursor");
14094+        case RGFW_mouseResizeSE: return NSCursor_arrowStr("_windowResizeNorthWestSouthEastCursor");
14095+        case RGFW_mouseResizeNESW: return NSCursor_arrowStr("_windowResizeNorthEastSouthWestCursor");
14096+        case RGFW_mouseResizeNE: return NSCursor_arrowStr("_windowResizeNorthEastSouthWestCursor");
14097+        case RGFW_mouseResizeSW: return NSCursor_arrowStr("_windowResizeNorthEastSouthWestCursor");
14098+        case RGFW_mouseResizeAll: return NSCursor_arrowStr("openHandCursor");
14099+        case RGFW_mouseNotAllowed: return NSCursor_arrowStr("operationNotAllowedCursor");
14100+        case RGFW_mouseWait: return NSCursor_arrowStr("arrowCursor");
14101+        case RGFW_mouseProgress: return NSCursor_arrowStr("arrowCursor");
14102+        default: return NULL;
14103+    }
14104+	return NULL;
14105+}
14106+
14107+RGFW_mouse* RGFW_createMouse(u8* data, i32 w, i32 h, RGFW_format format) {
14108+	id pool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc"));
14109+	pool = objc_msgSend_id(pool, sel_registerName("init"));
14110+
14111+	if (data == NULL) {
14112+		objc_msgSend_void(NSCursor_arrowStr("arrowCursor"), sel_registerName("set"));
14113+
14114+		objc_msgSend_bool_void(pool, sel_registerName("drain"));
14115+		return NULL;
14116+	}
14117+
14118+	id representation = (id)NSBitmapImageRep_initWithBitmapData(NULL, w, h, 8, (NSInteger)4, true, false, "NSCalibratedRGBColorSpace", 1 << 1, w * 4, 32);
14119+	RGFW_copyImageData(NSBitmapImageRep_bitmapData(representation), w, h, RGFW_formatRGBA8, data, format, NULL);
14120+
14121+	id cursor_image = ((id(*)(id, SEL, NSSize))objc_msgSend) (NSAlloc((id)objc_getClass("NSImage")), sel_registerName("initWithSize:"), ((NSSize){(CGFloat)w, (CGFloat)h}));
14122+
14123+	objc_msgSend_void_id(cursor_image, sel_registerName("addRepresentation:"), representation);
14124+
14125+	id cursor = (id) ((id(*)(id, SEL, id, NSPoint))objc_msgSend)
14126+		(NSAlloc(objc_getClass("NSCursor")),  sel_registerName("initWithImage:hotSpot:"), cursor_image, (NSPoint){0.0, 0.0});
14127+
14128+	NSRelease(cursor_image);
14129+	NSRelease(representation);
14130+
14131+	objc_msgSend_bool_void(pool, sel_registerName("drain"));
14132+
14133+	return (void*)cursor;
14134+}
14135+
14136+RGFW_bool RGFW_window_setMousePlatform(RGFW_window* win, RGFW_mouse* mouse) {
14137+	RGFW_ASSERT(win != NULL); RGFW_ASSERT(mouse);
14138+	CGDisplayShowCursor(kCGDirectMainDisplay);
14139+	objc_msgSend_void((id)mouse, sel_registerName("set"));
14140+	win->src.mouse = mouse;
14141+	return RGFW_TRUE;
14142+}
14143+
14144+void RGFW_freeMouse(RGFW_mouse* mouse) {
14145+	RGFW_ASSERT(mouse);
14146+	NSRelease((id)mouse);
14147+}
14148+
14149+void RGFW_window_showMouse(RGFW_window* win, RGFW_bool show) {
14150+	RGFW_window_showMouseFlags(win, show);
14151+	if (show)   CGDisplayShowCursor(kCGDirectMainDisplay);
14152+	else        CGDisplayHideCursor(kCGDirectMainDisplay);
14153+}
14154+
14155+void RGFW_window_setRawMouseModePlatform(RGFW_window* win, RGFW_bool state) {
14156+	RGFW_UNUSED(win); RGFW_UNUSED(state);
14157+}
14158+
14159+void RGFW_window_captureMousePlatform(RGFW_window* win, RGFW_bool state) {
14160+	RGFW_UNUSED(win);
14161+	CGAssociateMouseAndMouseCursorPosition(!(state == RGFW_TRUE));
14162+}
14163+
14164+void RGFW_window_moveMouse(RGFW_window* win, i32 x, i32 y) {
14165+	RGFW_UNUSED(win);
14166+
14167+	win->internal.lastMouseX = x - win->x;
14168+	win->internal.lastMouseY = y - win->y;
14169+	CGWarpMouseCursorPosition((CGPoint){(CGFloat)x, (CGFloat)y});
14170+}
14171+
14172+
14173+void RGFW_window_hide(RGFW_window* win) {
14174+	objc_msgSend_void_bool(win->src.window, sel_registerName("setIsVisible:"), false);
14175+}
14176+
14177+void RGFW_window_show(RGFW_window* win) {
14178+	if (win->internal.flags & RGFW_windowFocusOnShow)
14179+		((id(*)(id, SEL, SEL))objc_msgSend)((id)win->src.window, sel_registerName("makeKeyAndOrderFront:"), NULL);
14180+
14181+	((id(*)(id, SEL, SEL))objc_msgSend)((id)win->src.window, sel_registerName("orderFront:"), NULL);
14182+	objc_msgSend_void_bool(win->src.window, sel_registerName("setIsVisible:"), true);
14183+}
14184+
14185+void RGFW_window_flash(RGFW_window* win, RGFW_flashRequest request) {
14186+	if (RGFW_window_isInFocus(win) && request) {
14187+		return;
14188+	}
14189+
14190+	id pool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc"));
14191+	pool = objc_msgSend_id(pool, sel_registerName("init"));
14192+
14193+	if (_RGFW->flash) {
14194+		((void (*)(id, SEL, NSInteger))objc_msgSend) ((id)_RGFW->NSApp, sel_registerName("cancelUserAttentionRequest:"), _RGFW->flash);
14195+	}
14196+
14197+	switch (request) {
14198+		case RGFW_flashBriefly:
14199+			_RGFW->flash = ((NSInteger (*)(id, SEL, NSInteger))objc_msgSend) ((id)_RGFW->NSApp, sel_registerName("requestUserAttention:"), NSInformationalRequest);
14200+			break;
14201+		case RGFW_flashUntilFocused:
14202+			_RGFW->flash = ((NSInteger (*)(id, SEL, NSInteger))objc_msgSend) ((id)_RGFW->NSApp, sel_registerName("requestUserAttention:"), NSCriticalRequest);
14203+			break;
14204+		default: break;
14205+	}
14206+
14207+	objc_msgSend_bool_void(pool, sel_registerName("drain"));
14208+}
14209+
14210+RGFW_bool RGFW_window_isHidden(RGFW_window* win) {
14211+	RGFW_ASSERT(win != NULL);
14212+
14213+	bool visible = objc_msgSend_bool(win->src.window, sel_registerName("isVisible"));
14214+	return visible == NO && !RGFW_window_isMinimized(win);
14215+}
14216+
14217+RGFW_bool RGFW_window_isMinimized(RGFW_window* win) {
14218+	RGFW_ASSERT(win != NULL);
14219+
14220+	return objc_msgSend_bool(win->src.window, sel_registerName("isMiniaturized")) == YES;
14221+}
14222+
14223+RGFW_bool RGFW_window_isMaximized(RGFW_window* win) {
14224+	RGFW_ASSERT(win != NULL);
14225+	RGFW_bool b = (RGFW_bool)objc_msgSend_bool(win->src.window, sel_registerName("isZoomed"));
14226+	return b;
14227+}
14228+
14229+RGFWDEF id RGFW_getNSScreenForDisplayUInt(u32 uintNum);
14230+id RGFW_getNSScreenForDisplayUInt(u32 uintNum) {
14231+	Class NSScreenClass = objc_getClass("NSScreen");
14232+
14233+	id screens = objc_msgSend_id(NSScreenClass, sel_registerName("screens"));
14234+
14235+	NSUInteger count = (NSUInteger)objc_msgSend_uint(screens, sel_registerName("count"));
14236+    NSUInteger i;
14237+	for (i = 0; i < count; i++) {
14238+		id screen = ((id (*)(id, SEL, int))objc_msgSend) (screens, sel_registerName("objectAtIndex:"), (int)i);
14239+		id description = objc_msgSend_id(screen, sel_registerName("deviceDescription"));
14240+		id screenNumberKey = NSString_stringWithUTF8String("NSScreenNumber");
14241+		id screenNumber = objc_msgSend_id_id(description, sel_registerName("objectForKey:"), screenNumberKey);
14242+
14243+		if (CGDisplayUnitNumber((CGDirectDisplayID)objc_msgSend_uint(screenNumber, sel_registerName("unsignedIntValue"))) == uintNum) {
14244+			return screen;
14245+		}
14246+	}
14247+
14248+	return NULL;
14249+}
14250+
14251+float RGFW_osx_getRefreshRate(CGDirectDisplayID display, CGDisplayModeRef mode);
14252+float RGFW_osx_getRefreshRate(CGDirectDisplayID display, CGDisplayModeRef mode) {
14253+	if (mode) {
14254+		float refreshRate = (float)CGDisplayModeGetRefreshRate(mode);
14255+		if (refreshRate != 0)  return refreshRate;
14256+	}
14257+
14258+#ifndef RGFW_NO_IOKIT
14259+    float res = RGFW_osx_getFallbackRefreshRate(display);
14260+    if (res != 0) return res;
14261+#else
14262+    RGFW_UNUSED(display);
14263+#endif
14264+    return 60;
14265+}
14266+
14267+void RGFW_pollMonitors(void) {
14268+	u32 count;
14269+
14270+	if (CGGetActiveDisplayList(0, NULL, &count) != kCGErrorSuccess) {
14271+		return;
14272+	}
14273+
14274+	CGDirectDisplayID* displays = (CGDirectDisplayID*)RGFW_ALLOC(sizeof(CGDirectDisplayID) * count);
14275+	if (CGGetActiveDisplayList(count, displays, &count) != kCGErrorSuccess) {
14276+		return;
14277+	}
14278+
14279+
14280+	for (RGFW_monitorNode* node = _RGFW->monitors.list.head; node; node = node->next) {
14281+		node->disconnected = RGFW_TRUE;
14282+	}
14283+
14284+	CGDirectDisplayID primary = CGMainDisplayID();
14285+
14286+	u32 i;
14287+	for (i = 0; i < count; i++) {
14288+		RGFW_monitor monitor;
14289+
14290+		u32 uintNum = CGDisplayUnitNumber(displays[i]);
14291+		id screen = RGFW_getNSScreenForDisplayUInt(uintNum);
14292+
14293+		RGFW_monitorNode* node;
14294+		for (node = _RGFW->monitors.list.head; node; node = node->next) {
14295+			if (node->uintNum == uintNum) break;
14296+		}
14297+
14298+		if (node) {
14299+			node->screen = (void*)screen;
14300+			node->display = displays[i];
14301+			node->disconnected = RGFW_FALSE;
14302+			if (displays[i] == primary) {
14303+				_RGFW->monitors.primary = node;
14304+			}
14305+			continue;
14306+		}
14307+
14308+		const char name[] = "MacOS\0";
14309+		RGFW_MEMCPY(monitor.name, name, 6);
14310+
14311+		CGRect bounds = CGDisplayBounds(displays[i]);
14312+		monitor.x = (i32)bounds.origin.x;
14313+		monitor.y = (i32)RGFW_cocoaYTransform((float)(bounds.origin.y + bounds.size.height - 1));
14314+
14315+		CGDisplayModeRef mode = CGDisplayCopyDisplayMode(displays[i]);
14316+		monitor.mode.w = (i32)CGDisplayModeGetWidth(mode);
14317+		monitor.mode.h = (i32)CGDisplayModeGetHeight(mode);
14318+		monitor.mode.src = (void*)mode;
14319+		monitor.mode.red = 8; monitor.mode.green = 8; monitor.mode.blue = 8;
14320+
14321+		monitor.mode.refreshRate = RGFW_osx_getRefreshRate(displays[i], mode);
14322+		CFRelease(mode);
14323+
14324+		CGSize screenSizeMM = CGDisplayScreenSize(displays[i]);
14325+		monitor.physW = (float)screenSizeMM.width / 25.4f;
14326+		monitor.physH = (float)screenSizeMM.height / 25.4f;
14327+
14328+		float ppi_width = ((float)monitor.mode.w / monitor.physW);
14329+		float ppi_height = ((float)monitor.mode.h / monitor.physH);
14330+
14331+		monitor.pixelRatio = (float)((CGFloat (*)(id, SEL))abi_objc_msgSend_fpret) (screen, sel_registerName("backingScaleFactor"));
14332+		float dpi = 96.0f * monitor.pixelRatio;
14333+
14334+		monitor.scaleX = ((((float) (ppi_width) / dpi) * 10.0f)) / 10.0f;
14335+		monitor.scaleY = ((((float) (ppi_height) / dpi) * 10.0f)) / 10.0f;
14336+
14337+		node = RGFW_monitors_add(&monitor);
14338+
14339+		node->screen = (void*)screen;
14340+		node->uintNum = uintNum;
14341+		node->display = displays[i];
14342+
14343+		if (displays[i] == primary) {
14344+			_RGFW->monitors.primary = node;
14345+		}
14346+
14347+		RGFW_monitorCallback(_RGFW->root, &node->mon, RGFW_TRUE);
14348+	}
14349+
14350+	RGFW_FREE(displays);
14351+
14352+	RGFW_monitors_refresh();
14353+}
14354+
14355+RGFW_bool RGFW_monitor_getWorkarea(RGFW_monitor* monitor, i32* x, i32* y, i32* width, i32* height) {
14356+	NSRect frameRect = ((NSRect(*)(id, SEL))abi_objc_msgSend_stret)((id)monitor->node->screen, sel_registerName("visibleFrame"));
14357+
14358+    if (x) *x = (i32)frameRect.origin.x;
14359+    if (y) *y = (i32)RGFW_cocoaYTransform((float)(frameRect.origin.y + frameRect.size.height - (double)1.0f));
14360+    if (width) *width = (i32)frameRect.size.width;
14361+    if (height) *height = (i32)frameRect.size.height;
14362+
14363+	return RGFW_TRUE;
14364+}
14365+
14366+size_t RGFW_monitor_getGammaRampPtr(RGFW_monitor* monitor, RGFW_gammaRamp* ramp) {
14367+	id pool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc"));
14368+	pool = objc_msgSend_id(pool, sel_registerName("init"));
14369+
14370+    u32 size = CGDisplayGammaTableCapacity(monitor->node->display);
14371+    CGGammaValue* values = (CGGammaValue*)RGFW_ALLOC(size * 3 * sizeof(CGGammaValue));
14372+
14373+    CGGetDisplayTransferByTable(monitor->node->display, size, values, values + size, values + size * 2, &size);
14374+
14375+    for (u32 i = 0;  ramp && i < size; i++) {
14376+        ramp->red[i] = (u16) (values[i] * 65535);
14377+        ramp->green[i] = (u16) (values[i + size] * 65535);
14378+        ramp->blue[i] = (u16) (values[i + size * 2] * 65535);
14379+    }
14380+
14381+    RGFW_FREE(values);
14382+
14383+	objc_msgSend_bool_void(pool, sel_registerName("drain"));
14384+	return size;
14385+}
14386+
14387+RGFW_bool RGFW_monitor_setGammaRamp(RGFW_monitor* monitor, RGFW_gammaRamp* ramp) {
14388+	id pool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc"));
14389+	pool = objc_msgSend_id(pool, sel_registerName("init"));
14390+
14391+    CGGammaValue* values = (CGGammaValue*)RGFW_ALLOC(ramp->count * 3 * sizeof(CGGammaValue));
14392+
14393+    for (u32 i = 0;  i < ramp->count;  i++) {
14394+        values[i] = ramp->red[i] / 65535.f;
14395+        values[i + ramp->count] = ramp->green[i] / 65535.f;
14396+        values[i + ramp->count * 2] = ramp->blue[i] / 65535.f;
14397+    }
14398+
14399+    CGSetDisplayTransferByTable(monitor->node->display, (u32)ramp->count, values, values + ramp->count, values + ramp->count * 2);
14400+
14401+    RGFW_FREE(values);
14402+
14403+	objc_msgSend_bool_void(pool, sel_registerName("drain"));
14404+
14405+	return RGFW_TRUE;
14406+}
14407+
14408+size_t RGFW_monitor_getModesPtr(RGFW_monitor* mon, RGFW_monitorMode** modes) {
14409+    CGDirectDisplayID display = mon->node->display;
14410+    CFArrayRef allModes = CGDisplayCopyAllDisplayModes(display, NULL);
14411+
14412+    if (allModes == NULL) {
14413+        return RGFW_FALSE;
14414+	}
14415+
14416+	size_t count = (size_t)CFArrayGetCount(allModes);
14417+
14418+    CFIndex i;
14419+    for (i = 0; i < (CFIndex)count && modes; i++) {
14420+        CGDisplayModeRef cmode = (CGDisplayModeRef)CFArrayGetValueAtIndex(allModes, i);
14421+
14422+		RGFW_monitorMode foundMode;
14423+		foundMode.w = (i32)CGDisplayModeGetWidth(cmode);
14424+		foundMode.h = (i32)CGDisplayModeGetHeight(cmode);
14425+		foundMode.refreshRate =  RGFW_osx_getRefreshRate(display, cmode);
14426+		foundMode.red = 8; foundMode.green = 8; foundMode.blue = 8;
14427+		foundMode.src = (void*)cmode;
14428+		(*modes)[i] = foundMode;
14429+    }
14430+
14431+    CFRelease(allModes);
14432+	return count;
14433+}
14434+
14435+RGFW_bool RGFW_monitor_setMode(RGFW_monitor* mon, RGFW_monitorMode* mode) {
14436+	if (CGDisplaySetDisplayMode(mon->node->display, (CGDisplayModeRef)mode->src, NULL) == kCGErrorSuccess) {
14437+		return RGFW_TRUE;
14438+	}
14439+
14440+	return RGFW_FALSE;
14441+}
14442+
14443+RGFW_bool RGFW_monitor_requestMode(RGFW_monitor* mon, RGFW_monitorMode* mode, RGFW_modeRequest request) {
14444+    CGDirectDisplayID display = mon->node->display;
14445+    CFArrayRef allModes = CGDisplayCopyAllDisplayModes(display, NULL);
14446+
14447+    if (allModes == NULL) {
14448+        return RGFW_FALSE;
14449+	}
14450+
14451+	CGDisplayModeRef native = NULL;
14452+
14453+    CFIndex i;
14454+    for (i = 0; i < CFArrayGetCount(allModes); i++) {
14455+        CGDisplayModeRef cmode = (CGDisplayModeRef)CFArrayGetValueAtIndex(allModes, i);
14456+
14457+		RGFW_monitorMode foundMode;
14458+		foundMode.w = (i32)CGDisplayModeGetWidth(cmode);
14459+		foundMode.h = (i32)CGDisplayModeGetHeight(cmode);
14460+		foundMode.refreshRate =  RGFW_osx_getRefreshRate(display, cmode);
14461+		foundMode.red = 8; foundMode.green = 8; foundMode.blue = 8;
14462+		foundMode.src = (void*)cmode;
14463+
14464+		if (RGFW_monitorModeCompare(mode, &foundMode, request)) {
14465+			native = cmode;
14466+			mon->mode = foundMode;
14467+			break;
14468+        }
14469+    }
14470+
14471+    CFRelease(allModes);
14472+
14473+	if (native) {
14474+		if (CGDisplaySetDisplayMode(display, native, NULL) == kCGErrorSuccess) {
14475+			return RGFW_TRUE;
14476+		}
14477+	}
14478+
14479+	return RGFW_FALSE;
14480+}
14481+
14482+RGFW_monitor* RGFW_window_getMonitor(RGFW_window* win) {
14483+	id screen = objc_msgSend_id(win->src.window, sel_registerName("screen"));
14484+	id description = objc_msgSend_id(screen, sel_registerName("deviceDescription"));
14485+	id screenNumberKey = NSString_stringWithUTF8String("NSScreenNumber");
14486+	id screenNumber = objc_msgSend_id_id(description, sel_registerName("objectForKey:"), screenNumberKey);
14487+
14488+	CGDirectDisplayID display = (CGDirectDisplayID)objc_msgSend_uint(screenNumber, sel_registerName("unsignedIntValue"));
14489+
14490+	RGFW_monitorNode* node = _RGFW->monitors.list.head;
14491+	for (node = _RGFW->monitors.list.head; node; node = node->next) {
14492+		if (node->display == display && (id)node->screen == screen) {
14493+			break;
14494+		}
14495+	}
14496+
14497+    if (node == NULL) {
14498+		node = _RGFW->monitors.primary ? _RGFW->monitors.primary : _RGFW->monitors.list.head;
14499+	}
14500+
14501+	if (node == NULL) return NULL;
14502+	return &node->mon;
14503+}
14504+
14505+RGFW_ssize_t RGFW_readClipboardPtr(char* str, size_t strCapacity) {
14506+	size_t clip_len;
14507+	char* clip = (char*)NSPasteboard_stringForType(NSPasteboard_generalPasteboard(), NSPasteboardTypeString, &clip_len);
14508+	if (clip == NULL) return -1;
14509+
14510+	if (str != NULL) {
14511+		if (strCapacity < clip_len)
14512+			return 0;
14513+
14514+		RGFW_MEMCPY(str, clip, clip_len);
14515+
14516+		str[clip_len] = '\0';
14517+	}
14518+
14519+	return (RGFW_ssize_t)clip_len;
14520+}
14521+
14522+void RGFW_writeClipboard(const char* text, u32 textLen) {
14523+	RGFW_UNUSED(textLen);
14524+
14525+	NSPasteboardType array[] = { NSPasteboardTypeString, NULL };
14526+	NSPasteBoard_declareTypes(NSPasteboard_generalPasteboard(), array, 1, NULL);
14527+
14528+	SEL func = sel_registerName("setString:forType:");
14529+	((bool (*)(id, SEL, id, id))objc_msgSend)
14530+		(NSPasteboard_generalPasteboard(), func, NSString_stringWithUTF8String(text), NSString_stringWithUTF8String((const char*)NSPasteboardTypeString));
14531+}
14532+
14533+#ifdef RGFW_OPENGL
14534+void NSOpenGLContext_setValues(id context, const int* vals, NSOpenGLContextParameter param);
14535+void NSOpenGLContext_setValues(id context, const int* vals, NSOpenGLContextParameter param) {
14536+	((void (*)(id, SEL, const int*, NSOpenGLContextParameter))objc_msgSend)
14537+		(context, sel_registerName("setValues:forParameter:"), vals, param);
14538+}
14539+
14540+
14541+/* MacOS OpenGL API spares us yet again (there are no extensions) */
14542+RGFW_bool RGFW_extensionSupportedPlatform_OpenGL(const char * extension, size_t len) { RGFW_UNUSED(extension); RGFW_UNUSED(len); return RGFW_FALSE; }
14543+
14544+RGFW_proc RGFW_getProcAddress_OpenGL(const char* procname) {
14545+    static CFBundleRef RGFWnsglFramework = NULL;
14546+    if (RGFWnsglFramework == NULL)
14547+		RGFWnsglFramework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));
14548+
14549+	CFStringRef symbolName = CFStringCreateWithCString(kCFAllocatorDefault, procname, kCFStringEncodingASCII);
14550+
14551+	RGFW_proc symbol = (RGFW_proc)CFBundleGetFunctionPointerForName(RGFWnsglFramework, symbolName);
14552+
14553+	CFRelease(symbolName);
14554+
14555+	return symbol;
14556+}
14557+
14558+RGFW_bool RGFW_window_createContextPtr_OpenGL(RGFW_window* win, RGFW_glContext* ctx, RGFW_glHints* hints) {
14559+	win->src.ctx.native = ctx;
14560+	win->src.gfxType = RGFW_gfxNativeOpenGL;
14561+
14562+	i32 attribs[40];
14563+	size_t render_type_index = 0;
14564+	{
14565+		RGFW_attribStack stack;
14566+		RGFW_attribStack_init(&stack, attribs, 40);
14567+
14568+		i32 colorBits = (i32)(hints->red + hints->green +  hints->blue + hints->alpha) / 4;
14569+		RGFW_attribStack_pushAttribs(&stack, NSOpenGLPFAColorSize, colorBits);
14570+
14571+		RGFW_attribStack_pushAttribs(&stack, NSOpenGLPFAAlphaSize, hints->alpha);
14572+		RGFW_attribStack_pushAttribs(&stack, NSOpenGLPFADepthSize, hints->depth);
14573+		RGFW_attribStack_pushAttribs(&stack, NSOpenGLPFAStencilSize, hints->stencil);
14574+		RGFW_attribStack_pushAttribs(&stack, NSOpenGLPFAAuxBuffers, hints->auxBuffers);
14575+		RGFW_attribStack_pushAttrib(&stack, NSOpenGLPFAClosestPolicy);
14576+		if (hints->samples) {
14577+			RGFW_attribStack_pushAttribs(&stack, NSOpenGLPFASampleBuffers, 1);
14578+			RGFW_attribStack_pushAttribs(&stack, NSOpenGLPFASamples, hints->samples);
14579+		} else RGFW_attribStack_pushAttribs(&stack, NSOpenGLPFASampleBuffers, 0);
14580+
14581+		if (hints->doubleBuffer)
14582+			RGFW_attribStack_pushAttrib(&stack, NSOpenGLPFADoubleBuffer);
14583+
14584+		#ifdef RGFW_COCOA_GRAPHICS_SWITCHING
14585+		RGFW_attribStack_pushAttribs(&stack, NSOpenGLPFAAllowOfflineRenderers, kCGLPFASupportsAutomaticGraphicsSwitching);
14586+		#endif
14587+		#if MAC_OS_X_VERSION_MAX_ALLOWED < 101200
14588+		if (hints->stereo) RGFW_attribStack_pushAttrib(&stack, NSOpenGLPFAStereo);
14589+		#endif
14590+
14591+		/* macOS has the surface attribs and the OpenGL attribs connected for some reason maybe this is to give macOS more control to limit openGL/the OpenGL version? */
14592+		RGFW_attribStack_pushAttribs(&stack, NSOpenGLPFAOpenGLProfile,
14593+						(hints->major >= 4) ? NSOpenGLProfileVersion4_1Core  : (hints->major >= 3) ?
14594+															NSOpenGLProfileVersion3_2Core : NSOpenGLProfileVersionLegacy);
14595+
14596+		if (hints->major <= 2) {
14597+			i32 accumSize = (i32)(hints->accumRed + hints->accumGreen +  hints->accumBlue + hints->accumAlpha) / 4;
14598+			RGFW_attribStack_pushAttribs(&stack, NSOpenGLPFAAccumSize, accumSize);
14599+		}
14600+
14601+		if (hints->renderer == RGFW_glSoftware) {
14602+			RGFW_attribStack_pushAttribs(&stack, NSOpenGLPFARendererID, kCGLRendererGenericFloatID);
14603+		} else {
14604+			RGFW_attribStack_pushAttrib(&stack, NSOpenGLPFAAccelerated);
14605+		}
14606+		render_type_index = stack.count - 1;
14607+
14608+		RGFW_attribStack_pushAttribs(&stack, 0, 0);
14609+	}
14610+
14611+	void* format = (void*) ((id(*)(id, SEL, const u32*))objc_msgSend) (NSAlloc((id)objc_getClass("NSOpenGLPixelFormat")), sel_registerName("initWithAttributes:"), (u32*)attribs);
14612+	if (format == NULL) {
14613+		RGFW_debugCallback(RGFW_typeError, RGFW_errOpenGLContext, "Failed to load pixel format for OpenGL");
14614+
14615+		assert(render_type_index + 3 < (sizeof(attribs) / sizeof(attribs[0])));
14616+		attribs[render_type_index] = NSOpenGLPFARendererID;
14617+		attribs[render_type_index + 1] = kCGLRendererGenericFloatID;
14618+		attribs[render_type_index + 3] = 0;
14619+
14620+		format = (void*) ((id(*)(id, SEL, const u32*))objc_msgSend) (NSAlloc((id)objc_getClass("NSOpenGLPixelFormat")), sel_registerName("initWithAttributes:"), (u32*)attribs);
14621+		if (format == NULL)
14622+			RGFW_debugCallback(RGFW_typeError, RGFW_errOpenGLContext, "and loading software rendering OpenGL failed");
14623+		else
14624+			RGFW_debugCallback(RGFW_typeWarning, RGFW_warningOpenGL, "Switching to software rendering");
14625+	}
14626+
14627+	/* the pixel format can be passed directly to OpenGL context creation to create a context
14628+		this is because the format also includes information about the OpenGL version (which may be a bad thing) */
14629+
14630+	if (win->src.view)
14631+		NSRelease(win->src.view);
14632+	win->src.view = (id) ((id(*)(id, SEL, NSRect, u32*))objc_msgSend) (NSAlloc(_RGFW->customViewClasses[1]),
14633+							sel_registerName("initWithFrame:pixelFormat:"), (NSRect){{0, 0}, {(double)win->w, (double)win->h}}, (u32*)format);
14634+
14635+	id share = NULL;
14636+	if (hints->share) {
14637+		share = (id)hints->share->ctx;
14638+	}
14639+
14640+	win->src.ctx.native->ctx = ((id (*)(id, SEL, id, id))objc_msgSend)(NSAlloc(objc_getClass("NSOpenGLContext")),
14641+												 sel_registerName("initWithFormat:shareContext:"),
14642+												 (id)format, share);
14643+
14644+	win->src.ctx.native->format = format;
14645+
14646+	objc_msgSend_void_id(win->src.view, sel_registerName("setOpenGLContext:"), win->src.ctx.native->ctx);
14647+	if (win->internal.flags & RGFW_windowTransparent) {
14648+		i32 opacity = 0;
14649+		#define NSOpenGLCPSurfaceOpacity 236
14650+		NSOpenGLContext_setValues((id)win->src.ctx.native->ctx, &opacity, (NSOpenGLContextParameter)NSOpenGLCPSurfaceOpacity);
14651+
14652+	}
14653+
14654+	objc_msgSend_void(win->src.ctx.native->ctx, sel_registerName("makeCurrentContext"));
14655+
14656+	objc_msgSend_void_id((id)win->src.window, sel_registerName("setContentView:"), win->src.view);
14657+	objc_msgSend_void_bool(win->src.view, sel_registerName("setWantsLayer:"), true);
14658+	objc_msgSend_int((id)win->src.view, sel_registerName("setLayerContentsPlacement:"),  4);
14659+
14660+	RGFW_window_swapInterval_OpenGL(win, 0);
14661+
14662+	RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "OpenGL context initalized.");
14663+	return RGFW_TRUE;
14664+}
14665+
14666+void RGFW_window_deleteContextPtr_OpenGL(RGFW_window* win, RGFW_glContext* ctx) {
14667+	objc_msgSend_void(ctx->format, sel_registerName("release"));
14668+	win->src.ctx.native->format = NULL;
14669+
14670+	objc_msgSend_void(ctx->ctx, sel_registerName("release"));
14671+	win->src.ctx.native->ctx = NULL;
14672+	RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "OpenGL context freed.");
14673+}
14674+
14675+void RGFW_window_makeCurrentContext_OpenGL(RGFW_window* win) {
14676+	if (win) RGFW_ASSERT(win->src.ctx.native);
14677+	if (win != NULL)
14678+		objc_msgSend_void(win->src.ctx.native->ctx, sel_registerName("makeCurrentContext"));
14679+	else
14680+		objc_msgSend_id(objc_getClass("NSOpenGLContext"), sel_registerName("clearCurrentContext"));
14681+}
14682+void* RGFW_getCurrentContext_OpenGL(void) {
14683+	return objc_msgSend_id(objc_getClass("NSOpenGLContext"), sel_registerName("currentContext"));
14684+}
14685+
14686+void RGFW_window_swapBuffers_OpenGL(RGFW_window* win) {
14687+	RGFW_ASSERT(win && win->src.ctx.native);
14688+	objc_msgSend_void(win->src.ctx.native->ctx, sel_registerName("flushBuffer"));
14689+}
14690+void RGFW_window_swapInterval_OpenGL(RGFW_window* win, i32 swapInterval) {
14691+	RGFW_ASSERT(win != NULL && win->src.ctx.native != NULL);
14692+	NSOpenGLContext_setValues((id)win->src.ctx.native->ctx, &swapInterval, (NSOpenGLContextParameter)222);
14693+}
14694+#endif
14695+
14696+void RGFW_deinitPlatform(void) {
14697+	objc_msgSend_void_id(_RGFW->NSApp, sel_registerName("setDelegate:"), NULL);
14698+
14699+	objc_msgSend_void_id(_RGFW->NSApp, sel_registerName("stop:"), NULL);
14700+	NSRelease(_RGFW->NSApp);
14701+	_RGFW->NSApp = NULL;
14702+
14703+	NSRelease(_RGFW->customNSAppDelegate);
14704+
14705+	_RGFW->customNSAppDelegate = NULL;
14706+
14707+	objc_disposeClassPair((Class)_RGFW->customViewClasses[0]);
14708+	objc_disposeClassPair((Class)_RGFW->customViewClasses[1]);
14709+	objc_disposeClassPair((Class)_RGFW->customWindowDelegateClass);
14710+	objc_disposeClassPair((Class)_RGFW->customNSAppDelegateClass);
14711+}
14712+
14713+void RGFW_window_closePlatform(RGFW_window* win) {
14714+	objc_msgSend_void_id((id)win->src.window, sel_registerName("setDelegate:"), NULL);
14715+	NSRelease((id)win->src.delegate);
14716+	NSRelease(win->src.view);
14717+
14718+	objc_msgSend_id(win->src.window, sel_registerName("close"));
14719+	NSRelease(win->src.window);
14720+}
14721+
14722+#ifdef RGFW_VULKAN
14723+VkResult RGFW_window_createSurface_Vulkan(RGFW_window* win, VkInstance instance, VkSurfaceKHR* surface) {
14724+    RGFW_ASSERT(win != NULL); RGFW_ASSERT(instance);
14725+	RGFW_ASSERT(surface != NULL);
14726+
14727+    *surface = VK_NULL_HANDLE;
14728+	id pool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc"));
14729+	pool = objc_msgSend_id(pool, sel_registerName("init"));
14730+
14731+    id nsView = (id)win->src.view;
14732+    if (!nsView) {
14733+		RGFW_debugCallback(RGFW_typeError, RGFW_errMetal, "NSView is NULL for macOS window");
14734+        return -1;
14735+    }
14736+
14737+
14738+    id layer = ((id (*)(id, SEL))objc_msgSend)(nsView, sel_registerName("layer"));
14739+
14740+	void* metalLayer = RGFW_getLayer_OSX();
14741+	if (metalLayer == NULL) {
14742+		 return -1;
14743+	}
14744+	((void (*)(id, SEL, id))objc_msgSend)((id)nsView, sel_registerName("setLayer:"), metalLayer);
14745+    ((void (*)(id, SEL, BOOL))objc_msgSend)(nsView, sel_registerName("setWantsLayer:"), YES);
14746+
14747+	VkResult result;
14748+/*
14749+	VkMetalSurfaceCreateInfoEXT macos;
14750+	macos.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK;
14751+	macos.slayer = metalLayer;
14752+	RGFW_MEMZERO(&macos, sizeof(macos));
14753+    result = vkCreateMacOSSurfaceMVK(instance, &macos, NULL, surface);
14754+*/
14755+
14756+	VkMacOSSurfaceCreateInfoMVK macos;
14757+	RGFW_MEMZERO(&macos, sizeof(macos));
14758+	macos.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK;
14759+	macos.pView = nsView;
14760+
14761+    result = vkCreateMacOSSurfaceMVK(instance, &macos, NULL, surface);
14762+
14763+	objc_msgSend_bool_void(pool, sel_registerName("drain"));
14764+
14765+	return result;
14766+}
14767+#endif
14768+
14769+#ifdef RGFW_WEBGPU
14770+WGPUSurface RGFW_window_createSurface_WebGPU(RGFW_window* window, WGPUInstance instance) {
14771+	WGPUSurfaceDescriptor surfaceDesc = {0};
14772+    id* nsView = (id*)window->src.view;
14773+    if (!nsView) {
14774+		RGFW_debugCallback(RGFW_typeError, RGFW_errMetal, "NSView is NULL for macOS window");
14775+        return NULL;
14776+    }
14777+
14778+    ((void (*)(id, SEL, BOOL))objc_msgSend)(nsView, sel_registerName("setWantsLayer:"), YES);
14779+    id layer = ((id (*)(id, SEL))objc_msgSend)(nsView, sel_registerName("layer"));
14780+
14781+	void* metalLayer = RGFW_getLayer_OSX();
14782+	if (metalLayer == NULL) {
14783+		 return NULL;
14784+	}
14785+	((void (*)(id, SEL, id))objc_msgSend)((id)nsView, sel_registerName("setLayer:"), metalLayer);
14786+	layer = metalLayer;
14787+
14788+    WGPUSurfaceSourceMetalLayer fromMetal = {0};
14789+    fromMetal.chain.sType = WGPUSType_SurfaceSourceMetalLayer;
14790+#ifdef  __OBJC__
14791+	fromMetal.layer = (__bridge CAMetalLayer*)layer; /* Use __bridge for ARC compatibility if mixing C/Obj-C */
14792+#else
14793+	fromMetal.layer = layer;
14794+#endif
14795+
14796+    surfaceDesc.nextInChain = (WGPUChainedStruct*)&fromMetal.chain;
14797+    return wgpuInstanceCreateSurface(instance, &surfaceDesc);
14798+}
14799+#endif
14800+
14801+#endif /* RGFW_MACOS */
14802+
14803+/*
14804+	End of MaOS defines
14805+*/
14806+
14807+/*
14808+	WASM defines
14809+*/
14810+
14811+#ifdef RGFW_WASM
14812+EM_BOOL Emscripten_on_resize(int eventType, const EmscriptenUiEvent* E, void* userData) {
14813+	RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
14814+	RGFW_windowResizedCallback(_RGFW->root, E->windowInnerWidth, E->windowInnerHeight);
14815+    return EM_TRUE;
14816+}
14817+
14818+EM_BOOL Emscripten_on_fullscreenchange(int eventType, const EmscriptenFullscreenChangeEvent* E, void* userData) {
14819+	RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
14820+
14821+	if (!(_RGFW->root->internal.enabledEvents & RGFW_windowResizedFlag)) return EM_TRUE;
14822+
14823+	static u8 fullscreen = RGFW_FALSE;
14824+	static i32 originalW, originalH;
14825+
14826+	if (fullscreen == RGFW_FALSE) {
14827+		originalW = _RGFW->root->w;
14828+		originalH = _RGFW->root->h;
14829+	}
14830+
14831+	fullscreen = !fullscreen;
14832+	_RGFW->root->w = E->screenWidth;
14833+	_RGFW->root->h =  E->screenHeight;
14834+
14835+	EM_ASM("Module.canvas.focus();");
14836+
14837+	if (fullscreen == RGFW_FALSE) {
14838+		_RGFW->root->w = originalW;
14839+		_RGFW->root->h = originalH;
14840+	} else {
14841+		#if __EMSCRIPTEN_major__  >= 1 && __EMSCRIPTEN_minor__  >= 29 && __EMSCRIPTEN_tiny__  >= 0
14842+			EmscriptenFullscreenStrategy FSStrat = {0};
14843+			FSStrat.scaleMode = EMSCRIPTEN_FULLSCREEN_SCALE_STRETCH;
14844+			FSStrat.canvasResolutionScaleMode = EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_HIDEF;
14845+			FSStrat.filteringMode = EMSCRIPTEN_FULLSCREEN_FILTERING_DEFAULT;
14846+			emscripten_request_fullscreen_strategy("#canvas", 1, &FSStrat);
14847+		#else
14848+			emscripten_request_fullscreen("#canvas", 1);
14849+		#endif
14850+	}
14851+
14852+	emscripten_set_canvas_element_size("#canvas", _RGFW->root->w, _RGFW->root->h);
14853+	RGFW_windowResizedCallback(_RGFW->root, _RGFW->root->w, _RGFW->root->h);
14854+	return EM_TRUE;
14855+}
14856+
14857+EM_BOOL Emscripten_on_focusin(int eventType, const EmscriptenFocusEvent* E, void* userData) {
14858+	RGFW_UNUSED(eventType); RGFW_UNUSED(userData); RGFW_UNUSED(E);
14859+
14860+	RGFW_windowFocusCallback(_RGFW->root, 1);
14861+    return EM_TRUE;
14862+}
14863+
14864+EM_BOOL Emscripten_on_focusout(int eventType, const EmscriptenFocusEvent* E, void* userData) {
14865+	RGFW_UNUSED(eventType); RGFW_UNUSED(userData); RGFW_UNUSED(E);
14866+
14867+	RGFW_windowFocusCallback(_RGFW->root, 0);
14868+    return EM_TRUE;
14869+}
14870+
14871+EM_BOOL Emscripten_on_mousemove(int eventType, const EmscriptenMouseEvent* E, void* userData) {
14872+	RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
14873+	RGFW_mousePosCallback(_RGFW->root, E->targetX, E->targetY);
14874+	RGFW_rawMotionCallback(_RGFW->root, E->movementX, E->movementY);
14875+    return EM_TRUE;
14876+}
14877+
14878+EM_BOOL Emscripten_on_mousedown(int eventType, const EmscriptenMouseEvent* E, void* userData) {
14879+	RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
14880+
14881+	int button = E->button;
14882+	if (button > 2)
14883+		button += 2;
14884+
14885+	RGFW_mouseButtonCallback(_RGFW->root, button, 1);
14886+    return EM_TRUE;
14887+}
14888+
14889+EM_BOOL Emscripten_on_mouseup(int eventType, const EmscriptenMouseEvent* E, void* userData) {
14890+	RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
14891+
14892+	int button = E->button;
14893+	if (button > 2)
14894+		button += 2;
14895+
14896+	RGFW_mouseButtonCallback(_RGFW->root, button, 0);
14897+    return EM_TRUE;
14898+}
14899+
14900+EM_BOOL Emscripten_on_wheel(int eventType, const EmscriptenWheelEvent* E, void* userData) {
14901+	RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
14902+
14903+	RGFW_mouseScrollCallback(_RGFW->root, E->deltaX, E->deltaY);
14904+
14905+    return EM_TRUE;
14906+}
14907+
14908+EM_BOOL Emscripten_on_touchstart(int eventType, const EmscriptenTouchEvent* E, void* userData) {
14909+	RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
14910+
14911+	if (!(_RGFW->root->internal.enabledEvents & RGFW_mouseButtonPressedFlag)) return EM_TRUE;
14912+
14913+    size_t i;
14914+    for (i = 0; i < (size_t)E->numTouches; i++) {
14915+        RGFW_mousePosCallback(_RGFW->root, E->touches[i].targetX, E->touches[i].targetY);
14916+		RGFW_rawMotionCallback(_RGFW->root, 0, 0);
14917+	    RGFW_mouseButtonCallback(_RGFW->root, RGFW_mouseLeft, 1);
14918+    }
14919+
14920+	return EM_TRUE;
14921+}
14922+
14923+EM_BOOL Emscripten_on_touchmove(int eventType, const EmscriptenTouchEvent* E, void* userData) {
14924+	RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
14925+
14926+	if (!(_RGFW->root->internal.enabledEvents & RGFW_mousePosChangedFlag)) return EM_TRUE;
14927+
14928+    size_t i;
14929+    for (i = 0; i < (size_t)E->numTouches; i++) {
14930+        RGFW_mousePosCallback(_RGFW->root, E->touches[i].targetX, E->touches[i].targetY);
14931+		RGFW_rawMotionCallback(_RGFW->root, 0, 0);
14932+    }
14933+    return EM_TRUE;
14934+}
14935+
14936+EM_BOOL Emscripten_on_touchend(int eventType, const EmscriptenTouchEvent* E, void* userData) {
14937+	RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
14938+
14939+	if (!(_RGFW->root->internal.enabledEvents & RGFW_mouseButtonReleasedFlag)) return EM_TRUE;
14940+
14941+    size_t i;
14942+    for (i = 0; i < (size_t)E->numTouches; i++) {
14943+		RGFW_mousePosCallback(_RGFW->root, E->touches[i].targetX, E->touches[i].targetY);
14944+		RGFW_rawMotionCallback(_RGFW->root, 0, 0);
14945+		RGFW_mouseButtonCallback(_RGFW->root, RGFW_mouseLeft, 0);
14946+    }
14947+	return EM_TRUE;
14948+}
14949+
14950+EM_BOOL Emscripten_on_touchcancel(int eventType, const EmscriptenTouchEvent* E, void* userData) { RGFW_UNUSED(eventType); RGFW_UNUSED(userData); return EM_TRUE; }
14951+
14952+RGFW_key RGFW_WASMPhysicalToRGFW(u32 hash);
14953+
14954+void EMSCRIPTEN_KEEPALIVE RGFW_handleKeyEvent(char* code, u32 codepoint, RGFW_bool press) {
14955+	const char* iCode = code;
14956+
14957+	u32 hash = 0;
14958+	while(*iCode) hash = ((hash ^ 0x7E057D79U) << 3) ^ (unsigned int)*iCode++;
14959+
14960+	u32 physicalKey = RGFW_WASMPhysicalToRGFW(hash);
14961+
14962+	RGFW_keyCallback(_RGFW->root, physicalKey, _RGFW->root->internal.mod,  RGFW_isKeyDown((u8)physicalKey) && press, press);
14963+	if (press) {
14964+;		RGFW_keyCharCallback(_RGFW->root, codepoint);
14965+	}
14966+}
14967+
14968+void EMSCRIPTEN_KEEPALIVE RGFW_handleKeyMods(RGFW_bool capital, RGFW_bool numlock, RGFW_bool control, RGFW_bool alt, RGFW_bool shift, RGFW_bool super, RGFW_bool scroll) {
14969+	RGFW_keyUpdateKeyModsEx(_RGFW->root, capital, numlock, control, alt, shift, super, scroll);
14970+}
14971+
14972+void EMSCRIPTEN_KEEPALIVE Emscripten_onDrop(char* file, size_t size) {
14973+	RGFW_dataDropCallback(_RGFW->root, file, size, RGFW_dataFile);
14974+}
14975+
14976+void RGFW_stopCheckEvents(void) {
14977+	_RGFW->stopCheckEvents_bool = RGFW_TRUE;
14978+}
14979+
14980+RGFW_bool RGFW_createSurfacePtr(u8* data, i32 w, i32 h, RGFW_format format, RGFW_surface* surface) {
14981+	surface->data = data;
14982+	surface->w = w;
14983+	surface->h = h;
14984+	surface->format = format;
14985+	return RGFW_TRUE;
14986+}
14987+
14988+void RGFW_window_blitSurface(RGFW_window* win, RGFW_surface* surface) {
14989+	/* TODO: Needs fixing. */
14990+	RGFW_copyImageData(surface->data, surface->w, RGFW_MIN(win->h, surface->h), RGFW_formatRGBA8, surface->data, surface->format, surface->convertFunc);
14991+	EM_ASM_({
14992+		var data = Module.HEAPU8.slice($0, $0 + $1 * $2 * 4);
14993+		let context = document.getElementById("canvas").getContext("2d");
14994+		let image = context.getImageData(0, 0, $1, $2);
14995+		image.data.set(data);
14996+		context.putImageData(image, 0, $4 - $2);
14997+	}, surface->data, surface->w, surface->h, RGFW_MIN(win->h, surface->w), RGFW_MIN(win->h, surface->h));
14998+}
14999+
15000+void RGFW_surface_freePtr(RGFW_surface* surface) { }
15001+
15002+#include <sys/stat.h>
15003+#include <sys/types.h>
15004+#include <errno.h>
15005+#include <stdio.h>
15006+
15007+void EMSCRIPTEN_KEEPALIVE RGFW_mkdir(char* name) { mkdir(name, 0755); }
15008+
15009+void EMSCRIPTEN_KEEPALIVE RGFW_writeFile(const char *path, const char *data, size_t len) {
15010+    FILE* file = fopen(path, "w+");
15011+	if (file == NULL)
15012+		return;
15013+
15014+    fwrite(data, sizeof(char), len, file);
15015+    fclose(file);
15016+}
15017+
15018+void RGFW_initKeycodesPlatform(void) {
15019+	_RGFW->keycodes[DOM_VK_BACK_QUOTE] = RGFW_keyBacktick;
15020+	_RGFW->keycodes[DOM_VK_0] = RGFW_key0;
15021+	_RGFW->keycodes[DOM_VK_1] = RGFW_key1;
15022+	_RGFW->keycodes[DOM_VK_2] = RGFW_key2;
15023+	_RGFW->keycodes[DOM_VK_3] = RGFW_key3;
15024+	_RGFW->keycodes[DOM_VK_4] = RGFW_key4;
15025+	_RGFW->keycodes[DOM_VK_5] = RGFW_key5;
15026+	_RGFW->keycodes[DOM_VK_6] = RGFW_key6;
15027+	_RGFW->keycodes[DOM_VK_7] = RGFW_key7;
15028+	_RGFW->keycodes[DOM_VK_8] = RGFW_key8;
15029+	_RGFW->keycodes[DOM_VK_9] = RGFW_key9;
15030+	_RGFW->keycodes[DOM_VK_SPACE] = RGFW_keySpace;
15031+	_RGFW->keycodes[DOM_VK_A] = RGFW_keyA;
15032+	_RGFW->keycodes[DOM_VK_B] = RGFW_keyB;
15033+	_RGFW->keycodes[DOM_VK_C] = RGFW_keyC;
15034+	_RGFW->keycodes[DOM_VK_D] = RGFW_keyD;
15035+	_RGFW->keycodes[DOM_VK_E] = RGFW_keyE;
15036+	_RGFW->keycodes[DOM_VK_F] = RGFW_keyF;
15037+	_RGFW->keycodes[DOM_VK_G] = RGFW_keyG;
15038+	_RGFW->keycodes[DOM_VK_H] = RGFW_keyH;
15039+	_RGFW->keycodes[DOM_VK_I] = RGFW_keyI;
15040+	_RGFW->keycodes[DOM_VK_J] = RGFW_keyJ;
15041+	_RGFW->keycodes[DOM_VK_K] = RGFW_keyK;
15042+	_RGFW->keycodes[DOM_VK_L] = RGFW_keyL;
15043+	_RGFW->keycodes[DOM_VK_M] = RGFW_keyM;
15044+	_RGFW->keycodes[DOM_VK_N] = RGFW_keyN;
15045+	_RGFW->keycodes[DOM_VK_O] = RGFW_keyO;
15046+	_RGFW->keycodes[DOM_VK_P] = RGFW_keyP;
15047+	_RGFW->keycodes[DOM_VK_Q] = RGFW_keyQ;
15048+	_RGFW->keycodes[DOM_VK_R] = RGFW_keyR;
15049+	_RGFW->keycodes[DOM_VK_S] = RGFW_keyS;
15050+	_RGFW->keycodes[DOM_VK_T] = RGFW_keyT;
15051+	_RGFW->keycodes[DOM_VK_U] = RGFW_keyU;
15052+	_RGFW->keycodes[DOM_VK_V] = RGFW_keyV;
15053+	_RGFW->keycodes[DOM_VK_W] = RGFW_keyW;
15054+	_RGFW->keycodes[DOM_VK_X] = RGFW_keyX;
15055+	_RGFW->keycodes[DOM_VK_Y] = RGFW_keyY;
15056+	_RGFW->keycodes[DOM_VK_Z] = RGFW_keyZ;
15057+	_RGFW->keycodes[DOM_VK_PERIOD] = RGFW_keyPeriod;
15058+	_RGFW->keycodes[DOM_VK_COMMA] = RGFW_keyComma;
15059+	_RGFW->keycodes[DOM_VK_SLASH] = RGFW_keySlash;
15060+	_RGFW->keycodes[DOM_VK_OPEN_BRACKET] = RGFW_keyBracket;
15061+	_RGFW->keycodes[DOM_VK_CLOSE_BRACKET] = RGFW_keyCloseBracket;
15062+	_RGFW->keycodes[DOM_VK_SEMICOLON] = RGFW_keySemicolon;
15063+	_RGFW->keycodes[DOM_VK_QUOTE] = RGFW_keyApostrophe;
15064+	_RGFW->keycodes[DOM_VK_BACK_SLASH] = RGFW_keyBackSlash;
15065+	_RGFW->keycodes[DOM_VK_RETURN] = RGFW_keyReturn;
15066+	_RGFW->keycodes[DOM_VK_DELETE] = RGFW_keyDelete;
15067+	_RGFW->keycodes[DOM_VK_NUM_LOCK] = RGFW_keyNumLock;
15068+	_RGFW->keycodes[DOM_VK_DIVIDE] = RGFW_keyPadSlash;
15069+	_RGFW->keycodes[DOM_VK_MULTIPLY] = RGFW_keyPadMultiply;
15070+	_RGFW->keycodes[DOM_VK_SUBTRACT] = RGFW_keyPadMinus;
15071+	_RGFW->keycodes[DOM_VK_NUMPAD1] = RGFW_keyPad1;
15072+	_RGFW->keycodes[DOM_VK_NUMPAD2] = RGFW_keyPad2;
15073+	_RGFW->keycodes[DOM_VK_NUMPAD3] = RGFW_keyPad3;
15074+	_RGFW->keycodes[DOM_VK_NUMPAD4] = RGFW_keyPad4;
15075+	_RGFW->keycodes[DOM_VK_NUMPAD5] = RGFW_keyPad5;
15076+	_RGFW->keycodes[DOM_VK_NUMPAD6] = RGFW_keyPad6;
15077+	_RGFW->keycodes[DOM_VK_NUMPAD9] = RGFW_keyPad9;
15078+	_RGFW->keycodes[DOM_VK_NUMPAD0] = RGFW_keyPad0;
15079+	_RGFW->keycodes[DOM_VK_DECIMAL] = RGFW_keyPadPeriod;
15080+	_RGFW->keycodes[DOM_VK_RETURN] = RGFW_keyPadReturn;
15081+	_RGFW->keycodes[DOM_VK_HYPHEN_MINUS] = RGFW_keyMinus;
15082+	_RGFW->keycodes[DOM_VK_EQUALS] = RGFW_keyEquals;
15083+	_RGFW->keycodes[DOM_VK_BACK_SPACE] = RGFW_keyBackSpace;
15084+	_RGFW->keycodes[DOM_VK_TAB] = RGFW_keyTab;
15085+	_RGFW->keycodes[DOM_VK_CAPS_LOCK] = RGFW_keyCapsLock;
15086+	_RGFW->keycodes[DOM_VK_SHIFT] = RGFW_keyShiftL;
15087+	_RGFW->keycodes[DOM_VK_CONTROL] = RGFW_keyControlL;
15088+	_RGFW->keycodes[DOM_VK_ALT] = RGFW_keyAltL;
15089+	_RGFW->keycodes[DOM_VK_META] = RGFW_keySuperL;
15090+	_RGFW->keycodes[DOM_VK_F1] = RGFW_keyF1;
15091+	_RGFW->keycodes[DOM_VK_F2] = RGFW_keyF2;
15092+	_RGFW->keycodes[DOM_VK_F3] = RGFW_keyF3;
15093+	_RGFW->keycodes[DOM_VK_F4] = RGFW_keyF4;
15094+	_RGFW->keycodes[DOM_VK_F5] = RGFW_keyF5;
15095+	_RGFW->keycodes[DOM_VK_F6] = RGFW_keyF6;
15096+	_RGFW->keycodes[DOM_VK_F7] = RGFW_keyF7;
15097+	_RGFW->keycodes[DOM_VK_F8] = RGFW_keyF8;
15098+	_RGFW->keycodes[DOM_VK_F9] = RGFW_keyF9;
15099+	_RGFW->keycodes[DOM_VK_F10] = RGFW_keyF10;
15100+	_RGFW->keycodes[DOM_VK_F11] = RGFW_keyF11;
15101+	_RGFW->keycodes[DOM_VK_F12] = RGFW_keyF12;
15102+	_RGFW->keycodes[DOM_VK_UP] = RGFW_keyUp;
15103+	_RGFW->keycodes[DOM_VK_DOWN] = RGFW_keyDown;
15104+	_RGFW->keycodes[DOM_VK_LEFT] = RGFW_keyLeft;
15105+	_RGFW->keycodes[DOM_VK_RIGHT] = RGFW_keyRight;
15106+	_RGFW->keycodes[DOM_VK_INSERT] = RGFW_keyInsert;
15107+	_RGFW->keycodes[DOM_VK_END] = RGFW_keyEnd;
15108+	_RGFW->keycodes[DOM_VK_PAGE_UP] = RGFW_keyPageUp;
15109+	_RGFW->keycodes[DOM_VK_PAGE_DOWN] = RGFW_keyPageDown;
15110+	_RGFW->keycodes[DOM_VK_ESCAPE] = RGFW_keyEscape;
15111+	_RGFW->keycodes[DOM_VK_HOME] = RGFW_keyHome;
15112+	_RGFW->keycodes[DOM_VK_SCROLL_LOCK] = RGFW_keyScrollLock;
15113+	_RGFW->keycodes[DOM_VK_PRINTSCREEN] = RGFW_keyPrintScreen;
15114+	_RGFW->keycodes[DOM_VK_PAUSE] = RGFW_keyPause;
15115+	_RGFW->keycodes[DOM_VK_F13]  = RGFW_keyF13;
15116+	_RGFW->keycodes[DOM_VK_F14]  = RGFW_keyF14;
15117+	_RGFW->keycodes[DOM_VK_F15]  = RGFW_keyF15;
15118+	_RGFW->keycodes[DOM_VK_F16]  = RGFW_keyF16;
15119+	_RGFW->keycodes[DOM_VK_F17]  = RGFW_keyF17;
15120+	_RGFW->keycodes[DOM_VK_F18]  = RGFW_keyF18;
15121+	_RGFW->keycodes[DOM_VK_F19]  = RGFW_keyF19;
15122+	_RGFW->keycodes[DOM_VK_F20]  = RGFW_keyF20;
15123+	_RGFW->keycodes[DOM_VK_F21]  = RGFW_keyF21;
15124+	_RGFW->keycodes[DOM_VK_F22]  = RGFW_keyF22;
15125+	_RGFW->keycodes[DOM_VK_F23]  = RGFW_keyF23;
15126+	_RGFW->keycodes[DOM_VK_F24]  = RGFW_keyF24;
15127+}
15128+
15129+i32 RGFW_initPlatform(void) {
15130+	RGFW_monitorNode* node = NULL;
15131+	RGFW_monitor monitor;
15132+
15133+	monitor.name[0] = '\0';
15134+
15135+	monitor.x = 0;
15136+	monitor.y = 0;
15137+
15138+	monitor.pixelRatio = EM_ASM_DOUBLE({return window.devicePixelRatio || 1;});
15139+	monitor.mode.w = EM_ASM_INT({return window.innerWidth || 0;});
15140+	monitor.mode.h = EM_ASM_INT({return window.innerHeight || 0;});
15141+
15142+	monitor.physW = (float)RGFW_ROUND((float)monitor.mode.w * monitor.pixelRatio);
15143+	monitor.physH = (float)RGFW_ROUND((float)monitor.mode.h * monitor.pixelRatio);
15144+
15145+	float dpi = 96.0f * monitor.pixelRatio;
15146+	monitor.scaleX = dpi / 96.0f;
15147+	monitor.scaleY = dpi / 96.0f;
15148+
15149+	RGFW_splitBPP(32, &monitor.mode);
15150+
15151+	monitor.mode.refreshRate = 0;
15152+
15153+	node = RGFW_monitors_add(&monitor);
15154+	if (node != NULL) {
15155+		_RGFW->monitors.primary = node;
15156+		RGFW_monitorCallback(_RGFW->root, &node->mon, RGFW_TRUE);
15157+	}
15158+
15159+	return 0;
15160+}
15161+
15162+RGFW_window* RGFW_createWindowPlatform(const char* name, RGFW_windowFlags flags, RGFW_window* win) {
15163+	emscripten_set_canvas_element_size("#canvas", win->w, win->h);
15164+	emscripten_set_window_title(name);
15165+
15166+	/* load callbacks */
15167+    emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, Emscripten_on_resize);
15168+    emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, NULL, EM_FALSE, Emscripten_on_fullscreenchange);
15169+    emscripten_set_mousemove_callback("#canvas", NULL, EM_FALSE, Emscripten_on_mousemove);
15170+    emscripten_set_touchstart_callback("#canvas", NULL, EM_FALSE, Emscripten_on_touchstart);
15171+    emscripten_set_touchend_callback("#canvas", NULL, EM_FALSE, Emscripten_on_touchend);
15172+    emscripten_set_touchmove_callback("#canvas", NULL, EM_FALSE, Emscripten_on_touchmove);
15173+    emscripten_set_touchcancel_callback("#canvas", NULL, EM_FALSE, Emscripten_on_touchcancel);
15174+    emscripten_set_mousedown_callback("#canvas", NULL, EM_FALSE, Emscripten_on_mousedown);
15175+    emscripten_set_mouseup_callback("#canvas", NULL, EM_FALSE, Emscripten_on_mouseup);
15176+    emscripten_set_wheel_callback("#canvas", NULL, EM_FALSE, Emscripten_on_wheel);
15177+    emscripten_set_focusin_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, Emscripten_on_focusin);
15178+    emscripten_set_focusout_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, Emscripten_on_focusout);
15179+
15180+	if (flags & RGFW_windowAllowDND)  {
15181+		win->internal.flags |= RGFW_windowAllowDND;
15182+	}
15183+
15184+	EM_ASM({
15185+		window.addEventListener("keydown",
15186+			(event) => {
15187+				var code = stringToNewUTF8(event.code);
15188+				Module._RGFW_handleKeyMods(event.getModifierState("CapsLock"), event.getModifierState("NumLock"), event.getModifierState("Control"), event.getModifierState("Alt"), event.getModifierState("Shift"), event.getModifierState("Meta"), event.getModifierState("ScrollLock"));
15189+
15190+				var codepoint = event.key.charCodeAt(0);
15191+				if(codepoint < 0x7f && event.key.length > 1) {
15192+					codepoint = 0;
15193+				}
15194+
15195+				Module._RGFW_handleKeyEvent(code, codepoint, 1);
15196+				_free(code);
15197+			},
15198+		true);
15199+		window.addEventListener("keyup",
15200+			(event) => {
15201+				var code = stringToNewUTF8(event.code);
15202+				Module._RGFW_handleKeyMods(event.getModifierState("CapsLock"), event.getModifierState("NumLock"), event.getModifierState("Control"), event.getModifierState("Alt"), event.getModifierState("Shift"), event.getModifierState("Meta"), event.getModifierState("ScrollLock"));
15203+				Module._RGFW_handleKeyEvent(code, 0, 0);
15204+				_free(code);
15205+			},
15206+		true);
15207+	});
15208+
15209+    EM_ASM({
15210+		var canvas = document.getElementById('canvas');
15211+        canvas.addEventListener('drop', function(e) {
15212+            e.preventDefault();
15213+            if (e.dataTransfer.file < 0)
15214+				return;
15215+
15216+			var count = e.dataTransfer.files.length;
15217+
15218+			/* Read and save the files to emscripten's files */
15219+			var drop_dir = '.rgfw_dropped_files';
15220+			Module._RGFW_mkdir(drop_dir);
15221+
15222+			for (var i = 0; i < count; i++) {
15223+				var file = e.dataTransfer.files[i];
15224+
15225+				var path = '/' + drop_dir + '/' + file.name.replace("//", '_');
15226+				var reader = new FileReader();
15227+
15228+				reader.onloadend = (e) => {
15229+					if (reader.readyState != 2) {
15230+						out('failed to read dropped file: '+file.name+': '+reader.error);
15231+					}
15232+					else {
15233+						var data = e.target.result;
15234+
15235+						Module._RGFW_writeFile(path, new Uint8Array(data), file.size);
15236+					}
15237+				};
15238+
15239+				reader.readAsArrayBuffer(file);
15240+				var filename = stringToNewUTF8(path);
15241+
15242+				Module._Emscripten_onDrop(filename, path.length + 1);
15243+				free(filename);
15244+			}
15245+
15246+        }, true);
15247+
15248+        canvas.addEventListener('dragover', function(e) { e.preventDefault(); return false; }, true);
15249+    });
15250+
15251+	return win;
15252+}
15253+
15254+RGFW_key RGFW_physicalToMappedKey(RGFW_key key) {
15255+	return key;
15256+}
15257+
15258+RGFW_bool RGFW_window_fetchSize(RGFW_window* win, i32* w, i32* h) {
15259+	return RGFW_window_getSize(win, w, h);
15260+}
15261+
15262+void RGFW_pollEvents(void) {
15263+	RGFW_resetPrevState();
15264+	emscripten_sleep(0);
15265+}
15266+
15267+void RGFW_window_resize(RGFW_window* win, i32 w, i32 h) {
15268+	RGFW_UNUSED(win);
15269+	emscripten_set_canvas_element_size("#canvas", w, h);
15270+}
15271+
15272+RGFW_mouse* RGFW_createMouseStandard(RGFW_mouseIcon mouse) {
15273+	char* cursorName = NULL;
15274+
15275+	switch (mouse) {
15276+		case RGFW_mouseNormal:       cursorName = (char*)"default"; break;
15277+		case RGFW_mouseArrow:        cursorName = (char*)"default"; break;
15278+		case RGFW_mouseIbeam:        cursorName = (char*)"text"; break;
15279+		case RGFW_mouseCrosshair:    cursorName = (char*)"crosshair"; break;
15280+		case RGFW_mousePointingHand: cursorName = (char*)"pointer"; break;
15281+		case RGFW_mouseResizeEW:     cursorName = (char*)"ew-resize"; break;
15282+		case RGFW_mouseResizeNS:     cursorName = (char*)"ns-resize"; break;
15283+		case RGFW_mouseResizeNWSE:   cursorName = (char*)"nwse-resize"; break;
15284+		case RGFW_mouseResizeNESW:   cursorName = (char*)"nesw-resize"; break;
15285+		case RGFW_mouseResizeNW:     cursorName = (char*)"nw-resize"; break;
15286+		case RGFW_mouseResizeN:      cursorName = (char*)"n-resize"; break;
15287+		case RGFW_mouseResizeNE:     cursorName = (char*)"ne-resize"; break;
15288+		case RGFW_mouseResizeE:      cursorName = (char*)"e-resize"; break;
15289+		case RGFW_mouseResizeSE:     cursorName = (char*)"se-resize"; break;
15290+		case RGFW_mouseResizeS:      cursorName = (char*)"s-resize"; break;
15291+		case RGFW_mouseResizeSW:     cursorName = (char*)"sw-resize"; break;
15292+		case RGFW_mouseResizeW:      cursorName = (char*)"w-resize"; break;
15293+		case RGFW_mouseResizeAll:    cursorName = (char*)"move"; break;
15294+		case RGFW_mouseNotAllowed:   cursorName = (char*)"not-allowed"; break;
15295+		case RGFW_mouseWait:         cursorName = (char*)"wait"; break;
15296+		case RGFW_mouseProgress:     cursorName = (char*)"progress"; break;
15297+		default:                     return NULL;
15298+	}
15299+
15300+	return (RGFW_mouse*)cursorName;
15301+}
15302+
15303+/* NOTE: I don't know if this is possible */
15304+void RGFW_window_moveMouse(RGFW_window* win, i32 x, i32 y) { RGFW_UNUSED(win); RGFW_UNUSED(x); RGFW_UNUSED(y); }
15305+/* this one might be possible but it looks iffy */
15306+RGFW_mouse* RGFW_createMouse(u8* data, i32 w, i32 h, RGFW_format format) { RGFW_UNUSED(data); RGFW_UNUSED(w); RGFW_UNUSED(h); RGFW_UNUSED(format); return NULL; }
15307+
15308+RGFW_bool RGFW_window_setMousePlatform(RGFW_window* win, RGFW_mouse* mouse) {
15309+	RGFW_ASSERT(win != NULL);
15310+	RGFW_ASSERT(mouse != NULL);
15311+
15312+	EM_ASM( { document.getElementById("canvas").style.cursor = UTF8ToString($0); }, (char*)mouse);
15313+	return RGFW_TRUE;
15314+}
15315+void RGFW_freeMouse(RGFW_mouse* mouse) { RGFW_UNUSED(mouse); }
15316+
15317+void RGFW_window_showMouse(RGFW_window* win, RGFW_bool show) {
15318+	RGFW_window_showMouseFlags(win, show);
15319+	if (show)
15320+		RGFW_window_setMouseDefault(win);
15321+	else
15322+		EM_ASM(document.getElementById('canvas').style.cursor = 'none';);
15323+}
15324+
15325+RGFW_bool RGFW_getGlobalMouse(i32* x, i32* y) {
15326+    if(x) *x = EM_ASM_INT({
15327+        return window.mouseX || 0;
15328+    });
15329+    if (y) *y = EM_ASM_INT({
15330+        return window.mouseY || 0;
15331+    });
15332+    return RGFW_TRUE;
15333+}
15334+
15335+void RGFW_window_setMousePassthrough(RGFW_window* win, RGFW_bool passthrough) {
15336+	RGFW_UNUSED(win);
15337+
15338+    EM_ASM_({
15339+        var canvas = document.getElementById('canvas');
15340+        if ($0) {
15341+            canvas.style.pointerEvents = 'none';
15342+        } else {
15343+            canvas.style.pointerEvents = 'auto';
15344+        }
15345+    }, passthrough);
15346+}
15347+
15348+void RGFW_writeClipboard(const char* text, u32 textLen) {
15349+	RGFW_UNUSED(textLen);
15350+	EM_ASM({ navigator.clipboard.writeText(UTF8ToString($0)); }, text);
15351+}
15352+
15353+
15354+RGFW_ssize_t RGFW_readClipboardPtr(char* str, size_t strCapacity) {
15355+	RGFW_UNUSED(str); RGFW_UNUSED(strCapacity);
15356+	/*
15357+		placeholder code for later
15358+		I'm not sure if this is possible do the the async stuff
15359+	*/
15360+	return 0;
15361+}
15362+
15363+#ifdef RGFW_OPENGL
15364+RGFW_bool RGFW_window_createContextPtr_OpenGL(RGFW_window* win, RGFW_glContext* ctx, RGFW_glHints* hints) {
15365+	win->src.ctx.native = ctx;
15366+	win->src.gfxType = RGFW_gfxNativeOpenGL;
15367+
15368+	EmscriptenWebGLContextAttributes attrs;
15369+	emscripten_webgl_init_context_attributes(&attrs);
15370+	attrs.alpha = hints->alpha;
15371+	attrs.depth = hints->depth;
15372+	attrs.stencil = hints->stencil;
15373+	attrs.antialias = hints->samples;
15374+	attrs.premultipliedAlpha = EM_TRUE;
15375+	attrs.preserveDrawingBuffer = EM_FALSE;
15376+
15377+	if (hints->doubleBuffer == 0)
15378+		attrs.renderViaOffscreenBackBuffer = 0;
15379+	else
15380+		attrs.renderViaOffscreenBackBuffer = hints->auxBuffers;
15381+
15382+	attrs.failIfMajorPerformanceCaveat = EM_FALSE;
15383+
15384+	attrs.enableExtensionsByDefault = EM_TRUE;
15385+	attrs.explicitSwapControl = EM_TRUE;
15386+
15387+	if (hints->profile == RGFW_glWeb) {
15388+		attrs.majorVersion = (hints->major == 0) ? 1 : hints->major;
15389+		attrs.minorVersion = hints->minor;
15390+	} else {
15391+		attrs.majorVersion = (hints->major == 0) ? 1 : hints->major - 1;
15392+		attrs.minorVersion = hints->minor;
15393+	}
15394+
15395+	win->src.ctx.native->ctx = emscripten_webgl_create_context("#canvas", &attrs);
15396+	emscripten_webgl_make_context_current(win->src.ctx.native->ctx);
15397+
15398+	#ifdef LEGACY_GL_EMULATION
15399+	EM_ASM("Module.useWebGL = true; GLImmediate.init();");
15400+	RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "OpenGL context initalized.");
15401+    #endif
15402+
15403+	RGFW_window_swapInterval_OpenGL(win, 0);
15404+
15405+	return RGFW_TRUE;
15406+}
15407+
15408+void RGFW_window_deleteContextPtr_OpenGL(RGFW_window* win, RGFW_glContext* ctx) {
15409+	emscripten_webgl_destroy_context(ctx->ctx);
15410+	win->src.ctx.native->ctx = 0;
15411+	RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "OpenGL context freed.");
15412+}
15413+
15414+void RGFW_window_makeCurrentContext_OpenGL(RGFW_window* win) {
15415+	if (win) RGFW_ASSERT(win->src.ctx.native);
15416+	if (win == NULL)
15417+	    emscripten_webgl_make_context_current(0);
15418+	else
15419+	    emscripten_webgl_make_context_current(win->src.ctx.native->ctx);
15420+}
15421+
15422+void RGFW_window_swapBuffers_OpenGL(RGFW_window* win) {
15423+	RGFW_ASSERT(win && win->src.ctx.native);
15424+	emscripten_webgl_commit_frame();
15425+}
15426+void* RGFW_getCurrentContext_OpenGL(void) { return (void*)emscripten_webgl_get_current_context(); }
15427+
15428+RGFW_bool RGFW_extensionSupportedPlatform_OpenGL(const char* extension, size_t len) {
15429+    return EM_ASM_INT({
15430+        var ext = UTF8ToString($0, $1);
15431+        var canvas = document.querySelector('canvas');
15432+        var gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
15433+        if (!gl) return 0;
15434+
15435+        var supported = gl.getSupportedExtensions();
15436+        return supported && supported.includes(ext) ? 1 : 0;
15437+    }, extension, len);
15438+    return RGFW_FALSE;
15439+}
15440+
15441+RGFW_proc RGFW_getProcAddress_OpenGL(const char* procname) {
15442+    return (RGFW_proc)emscripten_webgl_get_proc_address(procname);
15443+    return NULL;
15444+}
15445+
15446+#endif
15447+
15448+void RGFW_window_swapInterval_OpenGL(RGFW_window* win, i32 swapInterval) { RGFW_UNUSED(win); RGFW_UNUSED(swapInterval); }
15449+
15450+void RGFW_deinitPlatform(void) { }
15451+
15452+void RGFW_window_closePlatform(RGFW_window* win) { }
15453+
15454+int RGFW_innerWidth(void) {   return EM_ASM_INT({ return window.innerWidth; });  }
15455+int RGFW_innerHeight(void) {  return EM_ASM_INT({ return window.innerHeight; });  }
15456+
15457+void RGFW_window_setRawMouseModePlatform(RGFW_window* win, RGFW_bool state) {
15458+	RGFW_UNUSED(win); RGFW_UNUSED(state);
15459+}
15460+
15461+void RGFW_window_captureMousePlatform(RGFW_window* win, RGFW_bool state) {
15462+	RGFW_UNUSED(win);
15463+	if (state) {
15464+		emscripten_request_pointerlock("#canvas", 1);
15465+	} else {
15466+		emscripten_exit_pointerlock();
15467+	}
15468+}
15469+
15470+void RGFW_window_setName(RGFW_window* win, const char* name) {
15471+	RGFW_UNUSED(win);
15472+	if (name == NULL) name = "\0";
15473+
15474+	emscripten_set_window_title(name);
15475+}
15476+
15477+void RGFW_window_maximize(RGFW_window* win) {
15478+	RGFW_ASSERT(win != NULL);
15479+
15480+	RGFW_monitor* mon = RGFW_window_getMonitor(win);
15481+	if (mon != NULL) {
15482+		RGFW_window_resize(win, mon->mode.w, mon->mode.h);
15483+	}
15484+
15485+	RGFW_window_move(win, 0, 0);
15486+	RGFW_window_fetchSize(win, NULL, NULL);
15487+}
15488+
15489+void RGFW_window_setFullscreen(RGFW_window* win, RGFW_bool fullscreen) {
15490+	RGFW_ASSERT(win != NULL);
15491+	if (fullscreen) {
15492+		win->internal.flags |= RGFW_windowFullscreen;
15493+		EM_ASM( Module.requestFullscreen(false, true); );
15494+		return;
15495+	}
15496+	win->internal.flags &= ~(u32)RGFW_windowFullscreen;
15497+	EM_ASM( Module.exitFullscreen(false, true); );
15498+}
15499+
15500+void RGFW_window_setOpacity(RGFW_window* win, u8 opacity) {
15501+	RGFW_UNUSED(win);
15502+	EM_ASM({
15503+		var element = document.getElementById("canvas");
15504+		if (element)
15505+		  element.style.opacity = $1;
15506+	  }, "elementId", opacity);
15507+}
15508+
15509+#ifdef RGFW_WEBGPU
15510+WGPUSurface RGFW_window_createSurface_WebGPU(RGFW_window* window, WGPUInstance instance) {
15511+	WGPUSurfaceDescriptor surfaceDesc = {0};
15512+	WGPUEmscriptenSurfaceSourceCanvasHTMLSelector canvasDesc = {0};
15513+    canvasDesc.chain.sType = WGPUSType_EmscriptenSurfaceSourceCanvasHTMLSelector;
15514+    canvasDesc.selector = (WGPUStringView){.data = "#canvas", .length = 7};
15515+
15516+    surfaceDesc.nextInChain = &canvasDesc.chain;
15517+    return wgpuInstanceCreateSurface(instance, &surfaceDesc);
15518+}
15519+#endif
15520+
15521+RGFW_key RGFW_WASMPhysicalToRGFW(u32 hash) {
15522+	switch(hash) {             /* 0x0000 */
15523+		case 0x67243A2DU /* Escape             */: return RGFW_keyEscape;               /* 0x0001 */
15524+		case 0x67251058U /* Digit0             */: return RGFW_key0;                    /* 0x0002 */
15525+		case 0x67251059U /* Digit1             */: return RGFW_key1;                    /* 0x0003 */
15526+		case 0x6725105AU /* Digit2             */: return RGFW_key2;                    /* 0x0004 */
15527+		case 0x6725105BU /* Digit3             */: return RGFW_key3;                    /* 0x0005 */
15528+		case 0x6725105CU /* Digit4             */: return RGFW_key4;                    /* 0x0006 */
15529+		case 0x6725105DU /* Digit5             */: return RGFW_key5;                    /* 0x0007 */
15530+		case 0x6725105EU /* Digit6             */: return RGFW_key6;                    /* 0x0008 */
15531+		case 0x6725105FU /* Digit7             */: return RGFW_key7;                    /* 0x0009 */
15532+		case 0x67251050U /* Digit8             */: return RGFW_key8;                    /* 0x000A */
15533+		case 0x67251051U /* Digit9             */: return RGFW_key9;                    /* 0x000B */
15534+		case 0x92E14DD3U /* Minus              */: return RGFW_keyMinus;                /* 0x000C */
15535+		case 0x92E1FBACU /* Equal              */: return RGFW_keyEquals;                /* 0x000D */
15536+		case 0x36BF1CB5U /* Backspace          */: return RGFW_keyBackSpace;            /* 0x000E */
15537+		case 0x7B8E51E2U  /* Tab                */: return RGFW_keyTab;                  /* 0x000F */
15538+		case 0x2C595B51U /* KeyQ               */: return RGFW_keyQ;                    /* 0x0010 */
15539+		case 0x2C595B57U /* KeyW               */: return RGFW_keyW;                    /* 0x0011 */
15540+		case 0x2C595B45U /* KeyE               */: return RGFW_keyE;                    /* 0x0012 */
15541+		case 0x2C595B52U /* KeyR               */: return RGFW_keyR;                    /* 0x0013 */
15542+		case 0x2C595B54U /* KeyT               */: return RGFW_keyT;                    /* 0x0014 */
15543+		case 0x2C595B59U /* KeyY               */: return RGFW_keyY;                    /* 0x0015 */
15544+		case 0x2C595B55U /* KeyU               */: return RGFW_keyU;                    /* 0x0016 */
15545+		case 0x2C595B4FU /* KeyO               */: return RGFW_keyO;                    /* 0x0018 */
15546+		case 0x2C595B50U /* KeyP               */: return RGFW_keyP;                    /* 0x0019 */
15547+		case 0x45D8158CU /* BracketLeft        */: return RGFW_keyCloseBracket;         /* 0x001A */
15548+		case 0xDEEABF7CU /* BracketRight       */: return RGFW_keyBracket;        /* 0x001B */
15549+		case 0x92E1C5D2U /* Enter              */: return RGFW_keyReturn;                /* 0x001C */
15550+		case 0xE058958CU /* ControlLeft        */: return RGFW_keyControlL;         /* 0x001D */
15551+		case 0x2C595B41U /* KeyA               */: return RGFW_keyA;                    /* 0x001E */
15552+		case 0x2C595B53U /* KeyS               */: return RGFW_keyS;                    /* 0x001F */
15553+		case 0x2C595B44U /* KeyD               */: return RGFW_keyD;                    /* 0x0020 */
15554+		case 0x2C595B46U /* KeyF               */: return RGFW_keyF;                    /* 0x0021 */
15555+		case 0x2C595B47U /* KeyG               */: return RGFW_keyG;                    /* 0x0022 */
15556+		case 0x2C595B48U /* KeyH               */: return RGFW_keyH;                    /* 0x0023 */
15557+		case 0x2C595B4AU /* KeyJ               */: return RGFW_keyJ;                    /* 0x0024 */
15558+		case 0x2C595B4BU /* KeyK               */: return RGFW_keyK;                    /* 0x0025 */
15559+		case 0x2C595B4CU /* KeyL               */: return RGFW_keyL;                    /* 0x0026 */
15560+		case 0x2707219EU /* Semicolon          */: return RGFW_keySemicolon;            /* 0x0027 */
15561+		case 0x92E0B58DU /* Quote              */: return RGFW_keyApostrophe;                /* 0x0028 */
15562+		case 0x36BF358DU /* Backquote          */: return RGFW_keyBacktick;            /* 0x0029 */
15563+		case 0x26B1958CU /* ShiftLeft          */: return RGFW_keyShiftL;           /* 0x002A */
15564+		case 0x36BF2438U /* Backslash          */: return RGFW_keyBackSlash;            /* 0x002B */
15565+		case 0x2C595B5AU /* KeyZ               */: return RGFW_keyZ;                    /* 0x002C */
15566+		case 0x2C595B58U /* KeyX               */: return RGFW_keyX;                    /* 0x002D */
15567+		case 0x2C595B43U /* KeyC               */: return RGFW_keyC;                    /* 0x002E */
15568+		case 0x2C595B56U /* KeyV               */: return RGFW_keyV;                    /* 0x002F */
15569+		case 0x2C595B42U /* KeyB               */: return RGFW_keyB;                    /* 0x0030 */
15570+		case 0x2C595B4EU /* KeyN               */: return RGFW_keyN;                    /* 0x0031 */
15571+		case 0x2C595B4DU /* KeyM               */: return RGFW_keyM;                    /* 0x0032 */
15572+		case 0x92E1A1C1U /* Comma              */: return RGFW_keyComma;                /* 0x0033 */
15573+		case 0x672FFAD4U /* Period             */: return RGFW_keyPeriod;               /* 0x0034 */
15574+		case 0x92E0A438U /* Slash              */: return RGFW_keySlash;                /* 0x0035 */
15575+		case 0xC5A6BF7CU /* ShiftRight         */: return RGFW_keyShiftR;
15576+		case 0x5D64DA91U /* NumpadMultiply     */: return RGFW_keyPadMultiply;
15577+		case 0xC914958CU /* AltLeft            */: return RGFW_keyAltL;             /* 0x0038 */
15578+		case 0x92E09CB5U /* Space              */: return RGFW_keySpace;                /* 0x0039 */
15579+		case 0xB8FAE73BU  /* CapsLock           */: return RGFW_keyCapsLock;            /* 0x003A */
15580+		case 0x7174B789U /* F1                 */: return RGFW_keyF1;                   /* 0x003B */
15581+		case 0x7174B78AU /* F2                 */: return RGFW_keyF2;                   /* 0x003C */
15582+		case 0x7174B78BU /* F3                 */: return RGFW_keyF3;                   /* 0x003D */
15583+		case 0x7174B78CU /* F4                 */: return RGFW_keyF4;                   /* 0x003E */
15584+		case 0x7174B78DU /* F5                 */: return RGFW_keyF5;                   /* 0x003F */
15585+		case 0x7174B78EU /* F6                 */: return RGFW_keyF6;                   /* 0x0040 */
15586+		case 0x7174B78FU /* F7                 */: return RGFW_keyF7;                   /* 0x0041 */
15587+		case 0x7174B780U /* F8                 */: return RGFW_keyF8;                   /* 0x0042 */
15588+		case 0x7174B781U /* F9                 */: return RGFW_keyF9;                   /* 0x0043 */
15589+		case 0x7B8E57B0U  /* F10                */: return RGFW_keyF10;                  /* 0x0044 */
15590+		case 0xC925FCDFU /* Numpad7            */: return RGFW_keyPadMultiply;             /* 0x0047 */
15591+		case 0xC925FCD0U /* Numpad8            */: return RGFW_keyPad8;             /* 0x0048 */
15592+		case 0xC925FCD1U /* Numpad9            */: return RGFW_keyPad9;             /* 0x0049 */
15593+		case 0x5EA3E8A4U /* NumpadSubtract     */: return RGFW_keyMinus;      /* 0x004A */
15594+		case 0xC925FCDCU /* Numpad4            */: return RGFW_keyPad4;             /* 0x004B */
15595+		case 0xC925FCDDU /* Numpad5            */: return RGFW_keyPad5;             /* 0x004C */
15596+		case 0xC925FCDEU /* Numpad6            */: return RGFW_keyPad6;             /* 0x004D */
15597+		case 0xC925FCD9U /* Numpad1            */: return RGFW_keyPad1;             /* 0x004F */
15598+		case 0xC925FCDAU /* Numpad2            */: return RGFW_keyPad2;             /* 0x0050 */
15599+		case 0xC925FCDBU /* Numpad3            */: return RGFW_keyPad3;             /* 0x0051 */
15600+		case 0xC925FCD8U /* Numpad0            */: return RGFW_keyPad0;             /* 0x0052 */
15601+		case 0x95852DACU /* NumpadDecimal      */: return RGFW_keyPeriod;       /* 0x0053 */
15602+		case 0x7B8E57B1U  /* F11                */: return RGFW_keyF11;                  /* 0x0057 */
15603+		case 0x7B8E57B2U  /* F12                */: return RGFW_keyF12;                  /* 0x0058 */
15604+		case 0x7B8E57B3U /* F13                */: return DOM_PK_F13;                  /* 0x0064 */
15605+		case 0x7B8E57B4U /* F14                */: return DOM_PK_F14;                  /* 0x0065 */
15606+		case 0x7B8E57B5U /* F15                */: return DOM_PK_F15;                  /* 0x0066 */
15607+		case 0x7B8E57B6U /* F16                */: return DOM_PK_F16;                  /* 0x0067 */
15608+		case 0x7B8E57B7U /* F17                */: return DOM_PK_F17;                  /* 0x0068 */
15609+		case 0x7B8E57B8U /* F18                */: return DOM_PK_F18;                  /* 0x0069 */
15610+		case 0x7B8E57B9U /* F19                */: return DOM_PK_F19;                  /* 0x006A */
15611+		case 0x7B8E57A8U /* F20                */: return DOM_PK_F20;                  /* 0x006B */
15612+		case 0x7B8E57A9U /* F21                */: return DOM_PK_F21;                  /* 0x006C */
15613+		case 0x7B8E57AAU /* F22                */: return DOM_PK_F22;                  /* 0x006D */
15614+		case 0x7B8E57ABU /* F23                */: return DOM_PK_F23;                  /* 0x006E */
15615+		case 0x7393FBACU /* NumpadEqual        */: return RGFW_keyPadReturn;
15616+		case 0xB88EBF7CU  /* AltRight           */: return RGFW_keyAltR;            /* 0xE038 */
15617+		case 0xC925873BU /* NumLock            */: return RGFW_keyNumLock;             /* 0xE045 */
15618+		case 0x2C595F45U /* Home               */: return RGFW_keyHome;                 /* 0xE047 */
15619+		case 0xC91BB690U /* ArrowUp            */: return RGFW_keyUp;             /* 0xE048 */
15620+		case 0x672F9210U /* PageUp             */: return RGFW_keyPageUp;              /* 0xE049 */
15621+		case 0x3799258CU /* ArrowLeft          */: return RGFW_keyLeft;           /* 0xE04B */
15622+		case 0x4CE33F7CU /* ArrowRight         */: return RGFW_keyRight;          /* 0xE04D */
15623+		case 0x7B8E55DCU  /* End                */: return RGFW_keyEnd;                  /* 0xE04F */
15624+		case 0x3799379EU /* ArrowDown          */: return RGFW_keyDown;           /* 0xE050 */
15625+		case 0xBA90179EU /* PageDown           */: return RGFW_keyPageDown;            /* 0xE051 */
15626+		case 0x6723CB2CU /* Insert             */: return RGFW_keyInsert;               /* 0xE052 */
15627+		case 0x6725C50DU /* Delete             */: return RGFW_keyDelete;               /* 0xE053 */
15628+		case 0x6723658CU /* OSLeft             */: return RGFW_keySuperL;              /* 0xE05B */
15629+		case 0x39643F7CU /* MetaRight          */: return RGFW_keySuperR;           /* 0xE05C */
15630+		case 0x380B9C8CU /* NumpadAdd          */: return DOM_PK_NUMPAD_ADD;           /* 0x004E */
15631+		default: return DOM_PK_UNKNOWN;
15632+	}
15633+
15634+	return 0;
15635+}
15636+
15637+RGFW_monitor* RGFW_window_getMonitor(RGFW_window* win) {
15638+	RGFW_UNUSED(win);
15639+	return RGFW_getPrimaryMonitor();
15640+}
15641+
15642+/* unsupported functions */
15643+void RGFW_pollMonitors(void) { }
15644+void RGFW_window_focus(RGFW_window* win) { RGFW_UNUSED(win); }
15645+void RGFW_window_raise(RGFW_window* win) { RGFW_UNUSED(win); }
15646+RGFW_bool RGFW_monitor_requestMode(RGFW_monitor* mon, RGFW_monitorMode* mode, RGFW_modeRequest request) { RGFW_UNUSED(mon); RGFW_UNUSED(mode); RGFW_UNUSED(request); return RGFW_FALSE; }
15647+RGFW_bool RGFW_monitor_getWorkarea(RGFW_monitor* monitor, i32* x, i32* y, i32* width, i32* height) { RGFW_UNUSED(monitor); RGFW_UNUSED(x); RGFW_UNUSED(width); RGFW_UNUSED(height); return RGFW_FALSE; }
15648+size_t RGFW_monitor_getGammaRampPtr(RGFW_monitor* monitor, RGFW_gammaRamp* ramp) { RGFW_UNUSED(monitor); RGFW_UNUSED(ramp); return 0; }
15649+RGFW_bool RGFW_monitor_setGammaRamp(RGFW_monitor* monitor, RGFW_gammaRamp* ramp) { RGFW_UNUSED(monitor); RGFW_UNUSED(ramp); return RGFW_FALSE; }
15650+size_t RGFW_monitor_getModesPtr(RGFW_monitor* mon, RGFW_monitorMode** modes) { RGFW_UNUSED(mon); RGFW_UNUSED(modes); return 0; }
15651+RGFW_bool RGFW_monitor_setMode(RGFW_monitor* mon, RGFW_monitorMode* mode) { RGFW_UNUSED(mon); RGFW_UNUSED(mode); return RGFW_FALSE; }
15652+void RGFW_window_move(RGFW_window* win, i32 x, i32 y) { RGFW_UNUSED(win);  RGFW_UNUSED(x); RGFW_UNUSED(y);  }
15653+void RGFW_window_setAspectRatio(RGFW_window* win, i32 w, i32 h) { RGFW_UNUSED(win);  RGFW_UNUSED(w); RGFW_UNUSED(h);  }
15654+void RGFW_window_setMinSize(RGFW_window* win, i32 w, i32 h) { RGFW_UNUSED(win); RGFW_UNUSED(w); RGFW_UNUSED(h);  }
15655+void RGFW_window_setMaxSize(RGFW_window* win, i32 w, i32 h) { RGFW_UNUSED(win);  RGFW_UNUSED(w); RGFW_UNUSED(h);  }
15656+void RGFW_window_minimize(RGFW_window* win) { RGFW_UNUSED(win); }
15657+void RGFW_window_restore(RGFW_window* win) { RGFW_UNUSED(win); }
15658+void RGFW_window_setFloating(RGFW_window* win, RGFW_bool floating) { RGFW_UNUSED(win); RGFW_UNUSED(floating); }
15659+void RGFW_window_setBorder(RGFW_window* win, RGFW_bool border) { RGFW_UNUSED(win); RGFW_UNUSED(border);  }
15660+RGFW_bool RGFW_window_setIconEx(RGFW_window* win, u8* data, i32 w, i32 h, RGFW_format format, RGFW_icon type) { RGFW_UNUSED(win); RGFW_UNUSED(data); RGFW_UNUSED(w); RGFW_UNUSED(h); RGFW_UNUSED(format);  RGFW_UNUSED(type); return RGFW_FALSE;  }
15661+void RGFW_window_hide(RGFW_window* win) { RGFW_UNUSED(win); }
15662+void RGFW_window_show(RGFW_window* win) {RGFW_UNUSED(win); }
15663+void RGFW_window_flash(RGFW_window* win, RGFW_flashRequest request) { RGFW_UNUSED(win); RGFW_UNUSED(request); }
15664+RGFW_bool RGFW_window_isHidden(RGFW_window* win) { RGFW_UNUSED(win); return RGFW_FALSE; }
15665+RGFW_bool RGFW_window_isMinimized(RGFW_window* win) { RGFW_UNUSED(win); return RGFW_FALSE; }
15666+RGFW_bool RGFW_window_isMaximized(RGFW_window* win) { RGFW_UNUSED(win); return RGFW_FALSE; }
15667+RGFW_bool RGFW_window_isFloating(RGFW_window* win) { RGFW_UNUSED(win); return RGFW_FALSE; }
15668+void RGFW_waitForEvent(i32 waitMS) { RGFW_UNUSED(waitMS); }
15669+#endif
15670+
15671+/* end of web asm defines */
15672+
15673+/*
15674+	* RGFW function pointer backend, made to allow you to compile for Wayland but fallback to X11
15675+*/
15676+#ifdef RGFW_DYNAMIC
15677+typedef RGFW_window* (*RGFW_createWindowPlatform_ptr)(const char* name, RGFW_windowFlags flags, RGFW_window* win);
15678+typedef RGFW_bool (*RGFW_getMouse_ptr)(i32* x, i32* y);
15679+typedef RGFW_key (*RGFW_physicalToMappedKey_ptr)(RGFW_key key);
15680+typedef void (*RGFW_pollEvents_ptr)(void);
15681+typedef RGFW_bool (*RGFW_window_fetchSize_ptr)(RGFW_window* win, i32* w, i32* h);
15682+typedef void (*RGFW_pollMonitors_ptr)(void);
15683+typedef void (*RGFW_window_move_ptr)(RGFW_window* win, i32 x, i32 y);
15684+typedef void (*RGFW_window_resize_ptr)(RGFW_window* win, i32 w, i32 h);
15685+typedef void (*RGFW_window_setAspectRatio_ptr)(RGFW_window* win, i32 w, i32 h);
15686+typedef void (*RGFW_window_setMinSize_ptr)(RGFW_window* win, i32 w, i32 h);
15687+typedef void (*RGFW_window_setMaxSize_ptr)(RGFW_window* win, i32 w, i32 h);
15688+typedef void (*RGFW_window_maximize_ptr)(RGFW_window* win);
15689+typedef void (*RGFW_window_focus_ptr)(RGFW_window* win);
15690+typedef void (*RGFW_window_raise_ptr)(RGFW_window* win);
15691+typedef void (*RGFW_window_setFullscreen_ptr)(RGFW_window* win, RGFW_bool fullscreen);
15692+typedef void (*RGFW_window_setFloating_ptr)(RGFW_window* win, RGFW_bool floating);
15693+typedef void (*RGFW_window_setOpacity_ptr)(RGFW_window* win, u8 opacity);
15694+typedef void (*RGFW_window_minimize_ptr)(RGFW_window* win);
15695+typedef void (*RGFW_window_restore_ptr)(RGFW_window* win);
15696+typedef RGFW_bool (*RGFW_window_isFloating_ptr)(RGFW_window* win);
15697+typedef void (*RGFW_window_setName_ptr)(RGFW_window* win, const char* name);
15698+typedef void (*RGFW_window_setMousePassthrough_ptr)(RGFW_window* win, RGFW_bool passthrough);
15699+typedef RGFW_bool (*RGFW_window_setIconEx_ptr)(RGFW_window* win, u8* data, i32 w, i32 h, RGFW_format format, u8 type);
15700+typedef RGFW_mouse* (*RGFW_createMouse_ptr)(u8* data, i32 w, i32 h, RGFW_format format);
15701+typedef RGFW_mouse* (*RGFW_createMouseStandard_ptr)(RGFW_mouseIcon icons);
15702+typedef RGFW_bool (*RGFW_window_setMousePlatform_ptr)(RGFW_window* win, RGFW_mouse* mouse);
15703+typedef void (*RGFW_window_moveMouse_ptr)(RGFW_window* win, i32 x, i32 y);
15704+typedef void (*RGFW_window_hide_ptr)(RGFW_window* win);
15705+typedef void (*RGFW_window_show_ptr)(RGFW_window* win);
15706+typedef void (*RGFW_window_flash_ptr)(RGFW_window* win, RGFW_flashRequest request);
15707+typedef RGFW_ssize_t (*RGFW_readClipboardPtr_ptr)(char* str, size_t strCapacity);
15708+typedef void (*RGFW_writeClipboard_ptr)(const char* text, u32 textLen);
15709+typedef RGFW_bool (*RGFW_window_isHidden_ptr)(RGFW_window* win);
15710+typedef RGFW_bool (*RGFW_window_isMinimized_ptr)(RGFW_window* win);
15711+typedef RGFW_bool (*RGFW_window_isMaximized_ptr)(RGFW_window* win);
15712+typedef RGFW_bool (*RGFW_monitor_requestMode_ptr)(RGFW_monitor* mon, RGFW_monitorMode* mode, RGFW_modeRequest request);
15713+typedef RGFW_bool (*RGFW_monitor_getWorkarea_ptr)(RGFW_monitor* mon, i32* x, i32* y, i32* w, i32* h);
15714+typedef size_t (*RGFW_monitor_getModesPtr_ptr)(RGFW_monitor* mon, RGFW_monitorMode** modes);
15715+typedef size_t (*RGFW_monitor_getGammaRampPtr_ptr) (RGFW_monitor* monitor, RGFW_gammaRamp* ramp);
15716+typedef RGFW_bool (*RGFW_monitor_setGammaRamp_ptr) (RGFW_monitor* monitor, RGFW_gammaRamp* ramp);
15717+typedef RGFW_bool (*RGFW_monitor_setMode_ptr)(RGFW_monitor* mon, RGFW_monitorMode* mode);
15718+typedef RGFW_monitor* (*RGFW_window_getMonitor_ptr)(RGFW_window* win);
15719+typedef void (*RGFW_window_closePlatform_ptr)(RGFW_window* win);
15720+typedef RGFW_format (*RGFW_nativeFormat_ptr)(void);
15721+typedef RGFW_bool (*RGFW_createSurfacePtr_ptr)(u8* data, i32 w, i32 h, RGFW_format format, RGFW_surface* surface);
15722+typedef void (*RGFW_window_blitSurface_ptr)(RGFW_window* win, RGFW_surface* surface);
15723+typedef void (*RGFW_surface_freePtr_ptr)(RGFW_surface* surface);
15724+typedef void (*RGFW_freeMouse_ptr)(RGFW_mouse* mouse);
15725+typedef void (*RGFW_window_setBorder_ptr)(RGFW_window* win, RGFW_bool border);
15726+typedef void (*RGFW_window_captureMousePlatform_ptr)(RGFW_window* win, RGFW_bool state);
15727+typedef void (*RGFW_window_setRawMouseModePlatform_ptr)(RGFW_window* win, RGFW_bool state);
15728+#ifdef RGFW_OPENGL
15729+typedef void (*RGFW_window_makeCurrentContext_OpenGL_ptr)(RGFW_window* win);
15730+typedef void* (*RGFW_getCurrentContext_OpenGL_ptr)(void);
15731+typedef void (*RGFW_window_swapBuffers_OpenGL_ptr)(RGFW_window* win);
15732+typedef void (*RGFW_window_swapInterval_OpenGL_ptr)(RGFW_window* win, i32 swapInterval);
15733+typedef RGFW_bool (*RGFW_extensionSupportedPlatform_OpenGL_ptr)(const char* extension, size_t len);
15734+typedef RGFW_proc (*RGFW_getProcAddress_OpenGL_ptr)(const char* procname);
15735+typedef RGFW_bool (*RGFW_window_createContextPtr_OpenGL_ptr)(RGFW_window* win, RGFW_glContext* ctx, RGFW_glHints* hints);
15736+typedef void (*RGFW_window_deleteContextPtr_OpenGL_ptr)(RGFW_window* win, RGFW_glContext* ctx);
15737+#endif
15738+#ifdef RGFW_WEBGPU
15739+typedef WGPUSurface (*RGFW_window_createSurface_WebGPU_ptr)(RGFW_window* window, WGPUInstance instance);
15740+#endif
15741+
15742+/* Structure to hold all function pointers */
15743+typedef struct RGFW_FunctionPointers {
15744+	RGFW_nativeFormat_ptr nativeFormat;
15745+	RGFW_createSurfacePtr_ptr createSurfacePtr;
15746+    RGFW_window_blitSurface_ptr window_blitSurface;
15747+	RGFW_surface_freePtr_ptr surface_freePtr;
15748+	RGFW_freeMouse_ptr freeMouse;
15749+    RGFW_window_setBorder_ptr window_setBorder;
15750+    RGFW_window_captureMousePlatform_ptr window_captureMousePlatform;
15751+	RGFW_window_setRawMouseModePlatform_ptr window_setRawMouseModePlatform;
15752+    RGFW_createWindowPlatform_ptr createWindowPlatform;
15753+    RGFW_getMouse_ptr getGlobalMouse;
15754+	RGFW_physicalToMappedKey_ptr physicalToMappedKey;
15755+    RGFW_window_fetchSize_ptr window_fetchSize;
15756+	RGFW_pollEvents_ptr pollEvents;
15757+    RGFW_pollMonitors_ptr pollMonitors;
15758+    RGFW_window_move_ptr window_move;
15759+    RGFW_window_resize_ptr window_resize;
15760+    RGFW_window_setAspectRatio_ptr window_setAspectRatio;
15761+    RGFW_window_setMinSize_ptr window_setMinSize;
15762+    RGFW_window_setMaxSize_ptr window_setMaxSize;
15763+    RGFW_window_maximize_ptr window_maximize;
15764+    RGFW_window_focus_ptr window_focus;
15765+    RGFW_window_raise_ptr window_raise;
15766+    RGFW_window_setFullscreen_ptr window_setFullscreen;
15767+    RGFW_window_setFloating_ptr window_setFloating;
15768+    RGFW_window_setOpacity_ptr window_setOpacity;
15769+    RGFW_window_minimize_ptr window_minimize;
15770+    RGFW_window_restore_ptr window_restore;
15771+    RGFW_window_isFloating_ptr window_isFloating;
15772+    RGFW_window_setName_ptr window_setName;
15773+    RGFW_window_setMousePassthrough_ptr window_setMousePassthrough;
15774+    RGFW_window_setIconEx_ptr window_setIconEx;
15775+    RGFW_createMouse_ptr loadMouse;
15776+    RGFW_createMouseStandard_ptr loadMouseStandard;
15777+    RGFW_window_setMousePlatform_ptr window_setMousePlatform;
15778+    RGFW_window_moveMouse_ptr window_moveMouse;
15779+    RGFW_window_hide_ptr window_hide;
15780+    RGFW_window_show_ptr window_show;
15781+    RGFW_window_flash_ptr window_flash;
15782+    RGFW_readClipboardPtr_ptr readClipboardPtr;
15783+    RGFW_writeClipboard_ptr writeClipboard;
15784+    RGFW_window_isHidden_ptr window_isHidden;
15785+    RGFW_window_isMinimized_ptr window_isMinimized;
15786+    RGFW_window_isMaximized_ptr window_isMaximized;
15787+    RGFW_monitor_requestMode_ptr monitor_requestMode;
15788+    RGFW_monitor_getWorkarea_ptr monitor_getWorkarea;
15789+	RGFW_monitor_getModesPtr_ptr monitor_getModesPtr;
15790+	RGFW_monitor_getGammaRampPtr_ptr monitor_getGammaRampPtr;
15791+	RGFW_monitor_setGammaRamp_ptr monitor_setGammaRamp;
15792+	RGFW_monitor_setMode_ptr monitor_setMode;
15793+    RGFW_window_getMonitor_ptr window_getMonitor;
15794+    RGFW_window_closePlatform_ptr window_closePlatform;
15795+#ifdef RGFW_OPENGL
15796+    RGFW_extensionSupportedPlatform_OpenGL_ptr extensionSupportedPlatform_OpenGL;
15797+    RGFW_getProcAddress_OpenGL_ptr getProcAddress_OpenGL;
15798+    RGFW_window_createContextPtr_OpenGL_ptr window_createContextPtr_OpenGL;
15799+    RGFW_window_deleteContextPtr_OpenGL_ptr window_deleteContextPtr_OpenGL;
15800+    RGFW_window_makeCurrentContext_OpenGL_ptr window_makeCurrentContext_OpenGL;
15801+    RGFW_getCurrentContext_OpenGL_ptr getCurrentContext_OpenGL;
15802+    RGFW_window_swapBuffers_OpenGL_ptr window_swapBuffers_OpenGL;
15803+    RGFW_window_swapInterval_OpenGL_ptr window_swapInterval_OpenGL;
15804+#endif
15805+#ifdef RGFW_WEBGPU
15806+    RGFW_window_createSurface_WebGPU_ptr window_createSurface_WebGPU;
15807+#endif
15808+} RGFW_functionPointers;
15809+
15810+RGFW_functionPointers RGFW_api;
15811+
15812+RGFW_format RGFW_nativeFormat(void) { return RGFW_api.nativeFormat(); }
15813+RGFW_bool RGFW_createSurfacePtr(u8* data, i32 w, i32 h, RGFW_format format, RGFW_surface* surface) { return RGFW_api.createSurfacePtr(data, w, h, format, surface); }
15814+void RGFW_surface_freePtr(RGFW_surface* surface) { RGFW_api.surface_freePtr(surface); }
15815+void RGFW_freeMouse(RGFW_mouse* mouse) { RGFW_api.freeMouse(mouse); }
15816+void RGFW_window_blitSurface(RGFW_window* win, RGFW_surface* surface) { RGFW_api.window_blitSurface(win, surface); }
15817+void RGFW_window_setBorder(RGFW_window* win, RGFW_bool border) { RGFW_api.window_setBorder(win, border); }
15818+void RGFW_window_captureMousePlatform(RGFW_window* win, RGFW_bool state) { RGFW_api.window_captureMousePlatform(win, state); }
15819+void RGFW_window_setRawMouseModePlatform(RGFW_window* win, RGFW_bool state) { RGFW_api.window_setRawMouseModePlatform(win, state); }
15820+RGFW_window* RGFW_createWindowPlatform(const char* name, RGFW_windowFlags flags, RGFW_window* win) { RGFW_init(); return RGFW_api.createWindowPlatform(name, flags, win); }
15821+RGFW_bool RGFW_getGlobalMouse(i32* x, i32* y) { return RGFW_api.getGlobalMouse(x, y); }
15822+RGFW_key RGFW_physicalToMappedKey(RGFW_key key) { return RGFW_api.physicalToMappedKey(key); }
15823+void RGFW_pollEvents(void) { RGFW_api.pollEvents(); }
15824+RGFW_bool RGFW_window_fetchSize(RGFW_window* win, i32* w, i32* h) { return RGFW_api.window_fetchSize(win, w, h); }
15825+void RGFW_pollMonitors(void) { RGFW_api.pollMonitors(); }
15826+void RGFW_window_move(RGFW_window* win, i32 x, i32 y) { RGFW_api.window_move(win, x, y); }
15827+void RGFW_window_resize(RGFW_window* win, i32 w, i32 h) { RGFW_api.window_resize(win, w, h); }
15828+void RGFW_window_setAspectRatio(RGFW_window* win, i32 w, i32 h) { RGFW_api.window_setAspectRatio(win, w, h); }
15829+void RGFW_window_setMinSize(RGFW_window* win, i32 w, i32 h) { RGFW_api.window_setMinSize(win, w, h); }
15830+void RGFW_window_setMaxSize(RGFW_window* win, i32 w, i32 h) { RGFW_api.window_setMaxSize(win, w, h); }
15831+void RGFW_window_maximize(RGFW_window* win) { RGFW_api.window_maximize(win); }
15832+void RGFW_window_focus(RGFW_window* win) { RGFW_api.window_focus(win); }
15833+void RGFW_window_raise(RGFW_window* win) { RGFW_api.window_raise(win); }
15834+void RGFW_window_setFullscreen(RGFW_window* win, RGFW_bool fullscreen) { RGFW_api.window_setFullscreen(win, fullscreen); }
15835+void RGFW_window_setFloating(RGFW_window* win, RGFW_bool floating) { RGFW_api.window_setFloating(win, floating); }
15836+void RGFW_window_setOpacity(RGFW_window* win, u8 opacity) { RGFW_api.window_setOpacity(win, opacity); }
15837+void RGFW_window_minimize(RGFW_window* win) { RGFW_api.window_minimize(win); }
15838+void RGFW_window_restore(RGFW_window* win) { RGFW_api.window_restore(win); }
15839+RGFW_bool RGFW_window_isFloating(RGFW_window* win) { return RGFW_api.window_isFloating(win); }
15840+void RGFW_window_setName(RGFW_window* win, const char* name) { RGFW_api.window_setName(win, name); }
15841+
15842+#ifndef RGFW_NO_PASSTHROUGH
15843+void RGFW_window_setMousePassthrough(RGFW_window* win, RGFW_bool passthrough) { RGFW_api.window_setMousePassthrough(win, passthrough); }
15844+#endif
15845+
15846+RGFW_bool RGFW_window_setIconEx(RGFW_window* win, u8* data, i32 w, i32 h, RGFW_format format, u8 type) { return RGFW_api.window_setIconEx(win, data, w, h, format, type); }
15847+RGFW_mouse* RGFW_createMouse(u8* data, i32 w, i32 h, RGFW_format format) { return RGFW_api.loadMouse(data, w, h, format); }
15848+RGFW_mouse* RGFW_createMouseStandard(RGFW_mouseIcon icon) { return RGFW_api.loadMouseStandard(icon); }
15849+RGFW_bool RGFW_window_setMousePlatform(RGFW_window* win, RGFW_mouse* mouse) { return RGFW_api.window_setMousePlatform(win, mouse); }
15850+void RGFW_window_moveMouse(RGFW_window* win, i32 x, i32 y) { RGFW_api.window_moveMouse(win, x, y); }
15851+void RGFW_window_hide(RGFW_window* win) { RGFW_api.window_hide(win); }
15852+void RGFW_window_show(RGFW_window* win) { RGFW_api.window_show(win); }
15853+void RGFW_window_flash(RGFW_window* win, RGFW_flashRequest request) { RGFW_api.window_flash(win, request); }
15854+RGFW_ssize_t RGFW_readClipboardPtr(char* str, size_t strCapacity) { return RGFW_api.readClipboardPtr(str, strCapacity); }
15855+void RGFW_writeClipboard(const char* text, u32 textLen) { RGFW_api.writeClipboard(text, textLen); }
15856+RGFW_bool RGFW_window_isHidden(RGFW_window* win) { return RGFW_api.window_isHidden(win); }
15857+RGFW_bool RGFW_window_isMinimized(RGFW_window* win) { return RGFW_api.window_isMinimized(win); }
15858+RGFW_bool RGFW_window_isMaximized(RGFW_window* win) { return RGFW_api.window_isMaximized(win); }
15859+RGFW_bool RGFW_monitor_requestMode(RGFW_monitor* mon, RGFW_monitorMode* mode, RGFW_modeRequest request) { return RGFW_api.monitor_requestMode(mon, mode, request); }
15860+RGFW_bool RGFW_monitor_getWorkarea(RGFW_monitor* monitor, i32* x, i32* y, i32* width, i32* height) { return  RGFW_api.monitor_getWorkarea(monitor, x, y, width, height); }
15861+size_t RGFW_monitor_getGammaRampPtr(RGFW_monitor* monitor, RGFW_gammaRamp* ramp) { return RGFW_api.monitor_getGammaRampPtr(monitor, ramp); }
15862+RGFW_bool RGFW_monitor_setGammaRamp(RGFW_monitor* monitor, RGFW_gammaRamp* ramp) { return RGFW_api.monitor_setGammaRamp(monitor, ramp); }
15863+size_t RGFW_monitor_getModesPtr(RGFW_monitor* mon, RGFW_monitorMode** modes) { return RGFW_api.monitor_getModesPtr(mon, modes); }
15864+RGFW_bool RGFW_monitor_setMode(RGFW_monitor* mon, RGFW_monitorMode* mode) { return RGFW_api.monitor_setMode(mon, mode); }
15865+RGFW_monitor* RGFW_window_getMonitor(RGFW_window* win) { return RGFW_api.window_getMonitor(win); }
15866+void RGFW_window_closePlatform(RGFW_window* win) { RGFW_api.window_closePlatform(win); }
15867+
15868+#ifdef RGFW_OPENGL
15869+RGFW_bool RGFW_extensionSupportedPlatform_OpenGL(const char* extension, size_t len) { return RGFW_api.extensionSupportedPlatform_OpenGL(extension, len); }
15870+RGFW_proc RGFW_getProcAddress_OpenGL(const char* procname) { return RGFW_api.getProcAddress_OpenGL(procname); }
15871+RGFW_bool RGFW_window_createContextPtr_OpenGL(RGFW_window* win, RGFW_glContext* ctx, RGFW_glHints* hints) { return RGFW_api.window_createContextPtr_OpenGL(win, ctx, hints); }
15872+void RGFW_window_deleteContextPtr_OpenGL(RGFW_window* win, RGFW_glContext* ctx) { RGFW_api.window_deleteContextPtr_OpenGL(win, ctx); }
15873+void RGFW_window_makeCurrentContext_OpenGL(RGFW_window* win) { RGFW_api.window_makeCurrentContext_OpenGL(win); }
15874+void* RGFW_getCurrentContext_OpenGL(void) { return RGFW_api.getCurrentContext_OpenGL(); }
15875+void RGFW_window_swapBuffers_OpenGL(RGFW_window* win) { RGFW_api.window_swapBuffers_OpenGL(win); }
15876+void RGFW_window_swapInterval_OpenGL(RGFW_window* win, i32 swapInterval) { RGFW_api.window_swapInterval_OpenGL(win, swapInterval); }
15877+#endif
15878+
15879+#ifdef RGFW_WEBGPU
15880+WGPUSurface RGFW_window_createSurface_WebGPU(RGFW_window* window, WGPUInstance instance) { return RGFW_api.window_createSurface_WebGPU(window, instance); }
15881+#endif
15882+#endif  /* RGFW_DYNAMIC */
15883+
15884+/*
15885+ * start of X11 AND wayland defines
15886+ * this allows a single executable to support x11 AND wayland
15887+ * falling back to x11 if wayland fails to initalize
15888+*/
15889+#if defined(RGFW_WAYLAND) && defined(RGFW_X11)
15890+void RGFW_load_X11(void) {
15891+	RGFW_api.nativeFormat = RGFW_nativeFormat_X11;
15892+	RGFW_api.createSurfacePtr = RGFW_createSurfacePtr_X11;
15893+    RGFW_api.window_blitSurface = RGFW_window_blitSurface_X11;
15894+	RGFW_api.surface_freePtr = RGFW_surface_freePtr_X11;
15895+	RGFW_api.freeMouse = RGFW_freeMouse_X11;
15896+    RGFW_api.window_setBorder = RGFW_window_setBorder_X11;
15897+    RGFW_api.window_captureMousePlatform = RGFW_window_captureMousePlatform_X11;
15898+	RGFW_api.window_setRawMouseModePlatform = RGFW_window_setRawMouseModePlatform_X11;
15899+	RGFW_api.createWindowPlatform = RGFW_createWindowPlatform_X11;
15900+    RGFW_api.getGlobalMouse = RGFW_getGlobalMouse_X11;
15901+    RGFW_api.physicalToMappedKey = RGFW_physicalToMappedKey_X11;
15902+    RGFW_api.pollEvents = RGFW_pollEvents_X11;
15903+    RGFW_api.window_fetchSize = RGFW_window_fetchSize_X11;
15904+    RGFW_api.pollMonitors = RGFW_pollMonitors_X11;
15905+    RGFW_api.window_move = RGFW_window_move_X11;
15906+    RGFW_api.window_resize = RGFW_window_resize_X11;
15907+    RGFW_api.window_setAspectRatio = RGFW_window_setAspectRatio_X11;
15908+    RGFW_api.window_setMinSize = RGFW_window_setMinSize_X11;
15909+    RGFW_api.window_setMaxSize = RGFW_window_setMaxSize_X11;
15910+    RGFW_api.window_maximize = RGFW_window_maximize_X11;
15911+    RGFW_api.window_focus = RGFW_window_focus_X11;
15912+    RGFW_api.window_raise = RGFW_window_raise_X11;
15913+    RGFW_api.window_setFullscreen = RGFW_window_setFullscreen_X11;
15914+    RGFW_api.window_setFloating = RGFW_window_setFloating_X11;
15915+    RGFW_api.window_setOpacity = RGFW_window_setOpacity_X11;
15916+    RGFW_api.window_minimize = RGFW_window_minimize_X11;
15917+    RGFW_api.window_restore = RGFW_window_restore_X11;
15918+    RGFW_api.window_isFloating = RGFW_window_isFloating_X11;
15919+    RGFW_api.window_setName = RGFW_window_setName_X11;
15920+#ifndef RGFW_NO_PASSTHROUGH
15921+    RGFW_api.window_setMousePassthrough = RGFW_window_setMousePassthrough_X11;
15922+#endif
15923+    RGFW_api.window_setIconEx = RGFW_window_setIconEx_X11;
15924+    RGFW_api.loadMouse = RGFW_createMouse_X11;
15925+    RGFW_api.window_setMousePlatform = RGFW_window_setMousePlatform_X11;
15926+    RGFW_api.window_moveMouse = RGFW_window_moveMouse_X11;
15927+    RGFW_api.window_hide = RGFW_window_hide_X11;
15928+    RGFW_api.window_show = RGFW_window_show_X11;
15929+    RGFW_api.window_flash = RGFW_window_flash_X11;
15930+    RGFW_api.readClipboardPtr = RGFW_readClipboardPtr_X11;
15931+    RGFW_api.writeClipboard = RGFW_writeClipboard_X11;
15932+    RGFW_api.window_isHidden = RGFW_window_isHidden_X11;
15933+    RGFW_api.window_isMinimized = RGFW_window_isMinimized_X11;
15934+    RGFW_api.window_isMaximized = RGFW_window_isMaximized_X11;
15935+    RGFW_api.monitor_requestMode = RGFW_monitor_requestMode_X11;
15936+    RGFW_api.monitor_getModesPtr = RGFW_monitor_getModesPtr_X11;
15937+    RGFW_api.monitor_setGammaRamp = RGFW_monitor_setGammaRamp_X11;
15938+    RGFW_api.monitor_getGammaRampPtr = RGFW_monitor_getGammaRampPtr_X11;
15939+	RGFW_api.monitor_setMode = RGFW_monitor_setMode_X11;
15940+    RGFW_api.window_getMonitor = RGFW_window_getMonitor_X11;
15941+    RGFW_api.window_closePlatform = RGFW_window_closePlatform_X11;
15942+#ifdef RGFW_OPENGL
15943+    RGFW_api.extensionSupportedPlatform_OpenGL = RGFW_extensionSupportedPlatform_OpenGL_X11;
15944+    RGFW_api.getProcAddress_OpenGL = RGFW_getProcAddress_OpenGL_X11;
15945+	RGFW_api.window_createContextPtr_OpenGL = RGFW_window_createContextPtr_OpenGL_X11;
15946+    RGFW_api.window_deleteContextPtr_OpenGL = RGFW_window_deleteContextPtr_OpenGL_X11;
15947+	RGFW_api.window_makeCurrentContext_OpenGL = RGFW_window_makeCurrentContext_OpenGL_X11;
15948+    RGFW_api.getCurrentContext_OpenGL = RGFW_getCurrentContext_OpenGL_X11;
15949+    RGFW_api.window_swapBuffers_OpenGL = RGFW_window_swapBuffers_OpenGL_X11;
15950+    RGFW_api.window_swapInterval_OpenGL = RGFW_window_swapInterval_OpenGL_X11;
15951+#endif
15952+#ifdef RGFW_WEBGPU
15953+    RGFW_api.window_createSurface_WebGPU = RGFW_window_createSurface_WebGPU_X11;
15954+#endif
15955+}
15956+
15957+void RGFW_load_Wayland(void) {
15958+	RGFW_api.nativeFormat = RGFW_nativeFormat_Wayland;
15959+	RGFW_api.createSurfacePtr = RGFW_createSurfacePtr_Wayland;
15960+	RGFW_api.window_blitSurface = RGFW_window_blitSurface_Wayland;
15961+    RGFW_api.surface_freePtr = RGFW_surface_freePtr_Wayland;
15962+	RGFW_api.freeMouse = RGFW_freeMouse_Wayland;
15963+	RGFW_api.window_setBorder = RGFW_window_setBorder_Wayland;
15964+    RGFW_api.window_captureMousePlatform = RGFW_window_captureMousePlatform_Wayland;
15965+	RGFW_api.window_setRawMouseModePlatform = RGFW_window_setRawMouseModePlatform_Wayland;
15966+    RGFW_api.createWindowPlatform = RGFW_createWindowPlatform_Wayland;
15967+    RGFW_api.getGlobalMouse = RGFW_getGlobalMouse_Wayland;
15968+    RGFW_api.physicalToMappedKey = RGFW_physicalToMappedKey_Wayland;
15969+    RGFW_api.pollEvents = RGFW_pollEvents_Wayland;
15970+    RGFW_api.window_fetchSize = RGFW_window_fetchSize_Wayland;
15971+    RGFW_api.pollMonitors = RGFW_pollMonitors_Wayland;
15972+    RGFW_api.window_move = RGFW_window_move_Wayland;
15973+    RGFW_api.window_resize = RGFW_window_resize_Wayland;
15974+    RGFW_api.window_setAspectRatio = RGFW_window_setAspectRatio_Wayland;
15975+    RGFW_api.window_setMinSize = RGFW_window_setMinSize_Wayland;
15976+    RGFW_api.window_setMaxSize = RGFW_window_setMaxSize_Wayland;
15977+    RGFW_api.window_maximize = RGFW_window_maximize_Wayland;
15978+    RGFW_api.window_focus = RGFW_window_focus_Wayland;
15979+    RGFW_api.window_raise = RGFW_window_raise_Wayland;
15980+    RGFW_api.window_setFullscreen = RGFW_window_setFullscreen_Wayland;
15981+    RGFW_api.window_setFloating = RGFW_window_setFloating_Wayland;
15982+    RGFW_api.window_setOpacity = RGFW_window_setOpacity_Wayland;
15983+    RGFW_api.window_minimize = RGFW_window_minimize_Wayland;
15984+    RGFW_api.window_restore = RGFW_window_restore_Wayland;
15985+    RGFW_api.window_isFloating = RGFW_window_isFloating_Wayland;
15986+    RGFW_api.window_setName = RGFW_window_setName_Wayland;
15987+#ifndef RGFW_NO_PASSTHROUGH
15988+    RGFW_api.window_setMousePassthrough = RGFW_window_setMousePassthrough_Wayland;
15989+#endif
15990+    RGFW_api.window_setIconEx = RGFW_window_setIconEx_Wayland;
15991+	RGFW_api.loadMouse = RGFW_createMouse_Wayland;
15992+    RGFW_api.window_setMousePlatform = RGFW_window_setMousePlatform_Wayland;
15993+    RGFW_api.window_moveMouse = RGFW_window_moveMouse_Wayland;
15994+    RGFW_api.window_hide = RGFW_window_hide_Wayland;
15995+    RGFW_api.window_show = RGFW_window_show_Wayland;
15996+    RGFW_api.window_flash = RGFW_window_flash_X11;
15997+    RGFW_api.readClipboardPtr = RGFW_readClipboardPtr_Wayland;
15998+    RGFW_api.writeClipboard = RGFW_writeClipboard_Wayland;
15999+    RGFW_api.window_isHidden = RGFW_window_isHidden_Wayland;
16000+    RGFW_api.window_isMinimized = RGFW_window_isMinimized_Wayland;
16001+    RGFW_api.window_isMaximized = RGFW_window_isMaximized_Wayland;
16002+    RGFW_api.monitor_requestMode = RGFW_monitor_requestMode_Wayland;
16003+    RGFW_api.monitor_getModesPtr = RGFW_monitor_getModesPtr_Wayland;
16004+    RGFW_api.monitor_setGammaRamp = RGFW_monitor_setGammaRamp_Wayland;
16005+    RGFW_api.monitor_getGammaRampPtr = RGFW_monitor_getGammaRampPtr_Wayland;
16006+	RGFW_api.monitor_setMode = RGFW_monitor_setMode_Wayland;
16007+    RGFW_api.window_getMonitor = RGFW_window_getMonitor_Wayland;
16008+    RGFW_api.window_closePlatform = RGFW_window_closePlatform_Wayland;
16009+#ifdef RGFW_OPENGL
16010+    RGFW_api.extensionSupportedPlatform_OpenGL = RGFW_extensionSupportedPlatform_OpenGL_Wayland;
16011+    RGFW_api.getProcAddress_OpenGL = RGFW_getProcAddress_OpenGL_Wayland;
16012+	RGFW_api.window_createContextPtr_OpenGL = RGFW_window_createContextPtr_OpenGL_Wayland;
16013+    RGFW_api.window_deleteContextPtr_OpenGL = RGFW_window_deleteContextPtr_OpenGL_Wayland;
16014+	RGFW_api.window_makeCurrentContext_OpenGL = RGFW_window_makeCurrentContext_OpenGL_Wayland;
16015+    RGFW_api.getCurrentContext_OpenGL = RGFW_getCurrentContext_OpenGL_Wayland;
16016+    RGFW_api.window_swapBuffers_OpenGL = RGFW_window_swapBuffers_OpenGL_Wayland;
16017+    RGFW_api.window_swapInterval_OpenGL = RGFW_window_swapInterval_OpenGL_Wayland;
16018+#endif
16019+#ifdef RGFW_WEBGPU
16020+    RGFW_api.window_createSurface_WebGPU = RGFW_window_createSurface_WebGPU_Wayland;
16021+#endif
16022+}
16023+#endif /* wayland AND x11 */
16024+/* end of X11 AND wayland defines */
16025+
16026+#endif /* RGFW_IMPLEMENTATION */
16027+
16028+#if defined(__cplusplus) && !defined(__EMSCRIPTEN__)
16029+}
16030+#endif
16031+
16032+#if _MSC_VER
16033+	#pragma warning( pop )
16034+#endif
16035+