Forráskód Böngészése

make RGFW a custom platform (#3941)

* fix minor bugs and errors (x86) for the RGFW platform, update RGFW platform license, update makefile info for RGFW platform

* revert

* (RGFW) (winapi) fix mouse hide bug when cursor changes

* ensure PLATFORM_SHELL is defined (PLATFORM_RGFW)

---------

Co-authored-by: ColleagueRiley <[email protected]>
Colleague Riley 1 éve
szülő
commit
9805fe0b1a
5 módosított fájl, 7948 hozzáadás és 7 törlés
  1. 32 2
      examples/Makefile
  2. 42 3
      src/Makefile
  3. 6349 0
      src/external/RGFW.h
  4. 1519 0
      src/platforms/rcore_desktop_rgfw.c
  5. 6 2
      src/rcore.c

+ 32 - 2
examples/Makefile

@@ -13,6 +13,11 @@
 #         - Windows (Win32, Win64)
 #         - Linux (X11/Wayland desktop mode)
 #         - Others (not tested)
+#     > PLATFORM_DESKTOP_RGFW (RGFW backend):
+#         - Windows (Win32, Win64)
+#         - Linux (X11 desktop mode)
+#         - macOS/OSX (x64, arm64 (not tested))
+#         - Others (not tested)
 #     > PLATFORM_WEB:
 #         - HTML5 (WebAssembly)
 #     > PLATFORM_DRM:
@@ -45,7 +50,7 @@
 # Define required environment variables
 #------------------------------------------------------------------------------------------------
 # Define target platform: PLATFORM_DESKTOP, PLATFORM_DESKTOP_SDL, PLATFORM_DRM, PLATFORM_ANDROID, PLATFORM_WEB
-PLATFORM              ?= PLATFORM_DESKTOP
+PLATFORM              ?= PLATFORM_DESKTOP_RGFW
 
 # Define required raylib variables
 PROJECT_NAME          ?= raylib_examples
@@ -86,7 +91,7 @@ BUILD_WEB_RESOURCES   ?= TRUE
 BUILD_WEB_RESOURCES_PATH  ?= $(dir $<)resources@resources
 
 # Determine PLATFORM_OS when required
-ifeq ($(PLATFORM),$(filter $(PLATFORM),PLATFORM_DESKTOP PLATFORM_DESKTOP_SDL PLATFORM_WEB))
+ifeq ($(PLATFORM),$(filter $(PLATFORM),PLATFORM_DESKTOP PLATFORM_DESKTOP_SDL PLATFORM_WEB PLATFORM_DESKTOP_RGFW))
     # No uname.exe on MinGW!, but OS=Windows_NT on Windows!
     # ifeq ($(UNAME),Msys) -> Windows
     ifeq ($(OS),Windows_NT)
@@ -416,6 +421,31 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP_SDL)
         LDLIBS += -latomic
     endif
 endif
+ifeq ($(PLATFORM),PLATFORM_DESKTOP_RGFW)
+    ifeq ($(PLATFORM_OS),WINDOWS)
+        # Libraries for Windows desktop compilation
+        LDLIBS = ..\src\libraylib.a -lgdi32 -lwinmm -lopengl32
+    endif
+    ifeq ($(PLATFORM_OS),LINUX)
+        # Libraries for Debian GNU/Linux desktop compipling
+        # NOTE: Required packages: libegl1-mesa-dev
+        LDLIBS = ../src/libraylib.a -lGL -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor -lm -lpthread -ldl -lrt
+
+        # Explicit link to libc
+        ifeq ($(RAYLIB_LIBTYPE),SHARED)
+            LDLIBS += -lc
+        endif
+
+        # NOTE: On ARM 32bit arch, miniaudio requires atomics library
+        LDLIBS += -latomic
+    endif
+    ifeq ($(PLATFORM_OS),OSX)
+        # Libraries for Debian GNU/Linux desktop compiling
+        # NOTE: Required packages: libegl1-mesa-dev
+        LDLIBS = ../src/libraylib.a -lm 
+        LDLIBS += -framework Foundation -framework AppKit -framework OpenGL -framework CoreVideo
+    endif
+endif
 ifeq ($(PLATFORM),PLATFORM_DRM)
     # Libraries for DRM compiling
     # NOTE: Required packages: libasound2-dev (ALSA)

+ 42 - 3
src/Makefile

@@ -13,6 +13,11 @@
 #         - Windows (Win32, Win64)
 #         - Linux (X11/Wayland desktop mode)
 #         - Others (not tested)
+#     > PLATFORM_DESKTOP_RGFW (RGFW backend):
+#         - Windows (Win32, Win64)
+#         - Linux (X11 desktop mode)
+#         - macOS/OSX (x64, arm64 (not tested))
+#         - Others (not tested)
 #     > PLATFORM_WEB:
 #         - HTML5 (WebAssembly)
 #     > PLATFORM_DRM:
@@ -114,7 +119,7 @@ HOST_PLATFORM_OS ?= WINDOWS
 PLATFORM_OS ?= WINDOWS
 
 # Determine PLATFORM_OS when required
-ifeq ($(PLATFORM),$(filter $(PLATFORM),PLATFORM_DESKTOP PLATFORM_DESKTOP_SDL PLATFORM_WEB PLATFORM_ANDROID))
+ifeq ($(PLATFORM),$(filter $(PLATFORM),PLATFORM_DESKTOP PLATFORM_DESKTOP_SDL PLATFORM_WEB PLATFORM_ANDROID PLATFORM_DESKTOP_RGFW))
     # No uname.exe on MinGW!, but OS=Windows_NT on Windows!
     # ifeq ($(UNAME),Msys) -> Windows
     ifeq ($(OS),Windows_NT)
@@ -224,6 +229,14 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP)
     #GRAPHICS = GRAPHICS_API_OPENGL_43      # Uncomment to use OpenGL 4.3
     #GRAPHICS = GRAPHICS_API_OPENGL_ES2     # Uncomment to use OpenGL ES 2.0 (ANGLE)
 endif
+ifeq ($(PLATFORM),PLATFORM_DESKTOP_RGFW)
+    # By default use OpenGL 3.3 on desktop platforms
+    GRAPHICS ?= GRAPHICS_API_OPENGL_33
+    #GRAPHICS = GRAPHICS_API_OPENGL_11      # Uncomment to use OpenGL 1.1
+    #GRAPHICS = GRAPHICS_API_OPENGL_21      # Uncomment to use OpenGL 2.1
+    #GRAPHICS = GRAPHICS_API_OPENGL_43      # Uncomment to use OpenGL 4.3
+    #GRAPHICS = GRAPHICS_API_OPENGL_ES2     # Uncomment to use OpenGL ES 2.0 (ANGLE)
+endif
 ifeq ($(PLATFORM),PLATFORM_DESKTOP_SDL)
     # By default use OpenGL 3.3 on desktop platform with SDL backend
     GRAPHICS ?= GRAPHICS_API_OPENGL_33
@@ -576,6 +589,31 @@ endif
 ifeq ($(PLATFORM),PLATFORM_ANDROID)
     LDLIBS = -llog -landroid -lEGL -lGLESv2 -lOpenSLES -lc -lm
 endif
+ifeq ($(PLATFORM),PLATFORM_DESKTOP_RGFW)
+    ifeq ($(PLATFORM_OS),WINDOWS)
+        # Libraries for Windows desktop compilation
+        LDLIBS = ..\src\libraylib.a -lgdi32 -lwinmm -lopengl32
+    endif
+    ifeq ($(PLATFORM_OS),LINUX)
+        # Libraries for Debian GNU/Linux desktop compipling
+        # NOTE: Required packages: libegl1-mesa-dev
+        LDLIBS = ../src/libraylib.a -lGL -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor -lm -lpthread -ldl -lrt
+
+        # Explicit link to libc
+        ifeq ($(RAYLIB_LIBTYPE),SHARED)
+            LDLIBS += -lc
+        endif
+
+        # NOTE: On ARM 32bit arch, miniaudio requires atomics library
+        LDLIBS += -latomic
+    endif
+    ifeq ($(PLATFORM_OS),OSX)
+        # Libraries for Debian GNU/Linux desktop compiling
+        # NOTE: Required packages: libegl1-mesa-dev
+        LDLIBS = ../src/libraylib.a -lm 
+        LDLIBS += -framework Foundation -framework AppKit -framework OpenGL -framework CoreVideo
+    endif
+endif
 
 # Define source code object files required
 #------------------------------------------------------------------------------------------------
@@ -583,7 +621,8 @@ OBJS = rcore.o \
        rshapes.o \
        rtextures.o \
        rtext.o \
-       utils.o
+       utils.o 
+
 
 ifeq ($(PLATFORM),PLATFORM_DESKTOP)
     ifeq ($(USE_EXTERNAL_GLFW),FALSE)
@@ -619,7 +658,7 @@ ifeq ($(PLATFORM),PLATFORM_WEB)
 	@echo "raylib library generated (lib$(RAYLIB_LIB_NAME).a)!"
 else
     ifeq ($(RAYLIB_LIBTYPE),SHARED)
-        ifeq ($(PLATFORM),$(filter $(PLATFORM),PLATFORM_DESKTOP PLATFORM_DESKTOP_SDL))
+        ifeq ($(PLATFORM),$(filter $(PLATFORM),PLATFORM_DESKTOP PLATFORM_DESKTOP_SDL PLATFORM_DESKTOP_RGFW))
             ifeq ($(PLATFORM_OS),WINDOWS)
                 # NOTE: Linking with provided resource file
 				$(CC) -shared -o $(RAYLIB_RELEASE_PATH)/$(RAYLIB_LIB_NAME).dll $(OBJS) $(RAYLIB_RES_FILE) $(LDFLAGS) $(LDLIBS)

+ 6349 - 0
src/external/RGFW.h

@@ -0,0 +1,6349 @@
+/*
+* Copyright (C) 2023-24 ColleagueRiley
+*
+* libpng license
+*
+* This software is provided 'as-is', without any express or implied
+* warranty.  In no event will the authors be held liable for any damages
+* arising from the use of this software.
+*
+* Permission is granted to anyone to use this software for any purpose,
+* including commercial applications, and to alter it and redistribute it
+* freely, subject to the following restrictions:
+*
+* 1. The origin of this software must not be misrepresented; you must not
+*    claim that you wrote the original software. If you use this software
+*    in a product, an acknowledgment in the product documentation would be
+*    appreciated but is not required.
+* 2. Altered source versions must be plainly marked as such, and must not be
+*    misrepresented as being the original software.
+* 3. This notice may not be removed or altered from any source distribution.
+*
+*
+*/
+
+/*
+	(MAKE SURE RGFW_IMPLEMENTATION is in exactly one header or you use -D RGFW_IMPLEMENTATION)
+	#define RGFW_IMPLEMENTATION - makes it so source code is included with header
+*/
+
+/*
+	#define RGFW_IMPLEMENTATION - (required) makes it so the source code is included
+	#define RGFW_PRINT_ERRORS - (optional) makes it so RGFW prints errors when they're found
+	#define RGFW_OSMESA - (optional) use OSmesa as backend (instead of system's opengl api + regular opengl)
+	#define RGFW_BUFFER - (optional) just draw directly to (RGFW) window pixel buffer that is drawn to screen (the buffer is in the RGBA format)
+	#define RGFW_EGL - (optional) use EGL for loading an OpenGL context (instead of the system's opengl api)
+	#define RGFW_OPENGL_ES1 - (optional) use EGL to load and use Opengl ES (version 1) for backend rendering (instead of the system's opengl api)
+	#define RGFW_OPENGL_ES2 - (optional) use OpenGL ES (version 2)
+	#define RGFW_VULKAN - (optional) use vulkan for the rendering backend (rather than opengl)
+	#define RGFW_DIRECTX - (optional) use directX for the rendering backend (rather than opengl) (windows only, defaults to opengl for unix)
+	#define RGFW_NO_API - (optional) don't use any rendering API (no opengl, no vulkan, no directX)
+
+	#define RGFW_LINK_EGL (optional) (windows only) if EGL is being used, if EGL functions should be defined dymanically (using GetProcAddress)
+	#define RGFW_LINK_OSMESA (optional) (windows only) if EGL is being used, if OS Mesa functions should be defined dymanically  (using GetProcAddress)
+
+	#define RGFW_X11 (optional) (unix only) if X11 should be used. This option is turned on by default by unix systems except for MacOS
+	#define RGFW_WGL_LOAD (optional) (windows only) if WGL should be loaded dynamically during runtime
+	#define RGFW_NO_X11_CURSOR (optional) (unix only) don't use XCursor
+	#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)
+
+	#define RGFW_NO_DPI - Do not include calculate DPI (no XRM nor libShcore included)
+
+	#define RGFW_ALLOC_DROPFILES (optional) if room should be allocating for drop files (by default it's global data)
+	#define RGFW_MALLOC x - choose what function to use to allocate, by default the standard malloc is used
+	#define RGFW_CALLOC x - choose what function to use to allocate (calloc), by default the standard calloc is used
+	#define RGFW_FREE x - choose what function to use to allocated memory, by default the standard free is used
+*/
+
+/*
+	Credits :
+		EimaMei/Sacode : Much of the code for creating windows using winapi, Wrote the Silicon library, helped with MacOS Support
+
+		stb - This project is heavily inspired by the stb single header files
+
+		GLFW:
+			certain parts of winapi and X11 are very poorly documented,
+			GLFW's source code was referenced and used throughout the project (used code is marked in some way),
+			this mainly includes, code for drag and drops, code for setting the icon to a bitmap and the code for managing the clipboard for X11 (as these parts are not documented very well)
+
+			GLFW Copyright, https::/github.com/GLFW/GLFW
+
+			Copyright (c) 2002-2006 Marcus Geelnard
+			Copyright (c) 2006-2019 Camilla Löwy
+*/
+
+#ifndef RGFW_MALLOC
+#include <stdlib.h>
+#include <time.h>
+#define RGFW_MALLOC malloc
+#define RGFW_CALLOC calloc
+#define RGFW_FREE free
+#endif
+
+#if !_MSC_VER
+#ifndef inline
+#ifndef __APPLE__
+#define inline __inline
+#endif
+#endif
+#endif
+
+#ifndef RGFWDEF
+#ifdef __APPLE__
+#define RGFWDEF extern inline
+#else
+#define RGFWDEF inline
+#endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+	/* makes sure the header file part is only defined once by default */
+#ifndef RGFW_HEADER
+
+#define RGFW_HEADER
+
+#if !defined(u8)
+#include <stdint.h>
+
+	typedef uint8_t     u8;
+	typedef int8_t      i8;
+	typedef uint16_t   u16;
+	typedef int16_t    i16;
+	typedef uint32_t   u32;
+	typedef int32_t    i32;
+	typedef uint64_t   u64;
+	typedef int64_t    i64;
+#endif
+
+#if defined(RGFW_X11) && defined(__APPLE__)
+#define RGFW_MACOS_X11
+#undef __APPLE__
+#endif
+
+#if defined(_WIN32) && !defined(RGFW_X11) /* (if you're using X11 on windows some how) */
+
+	/* this name looks better */
+	/* plus it helps with cross-compiling because RGFW_X11 won't be accidently defined */
+	
+#define RGFW_WINDOWS
+
+#if defined(_WIN32)
+#define WIN32
+#endif
+
+#if defined(_WIN64)
+#define WIN64
+#define _AMD64_
+#undef _X86_
+#else
+#undef _AMD64_
+#define _X86_
+#endif
+
+#include <windef.h>
+
+#ifdef __MINGW32__
+#include <xinput.h>
+#else
+#include <XInput.h>
+#endif
+
+#else 
+#if defined(__unix__) || defined(RGFW_MACOS_X11) || defined(RGFW_X11)
+#define RGFW_MACOS_X11
+#define RGFW_X11
+#include <X11/Xlib.h>
+#endif
+#endif 	
+
+#if defined(__APPLE__) && !defined(RGFW_MACOS_X11) && !defined(RGFW_X11)
+#define RGFW_MACOS
+#endif
+
+#if (defined(RGFW_OPENGL_ES1) || defined(RGFW_OPENGL_ES2)) && !defined(RGFW_EGL)
+#define RGFW_EGL
+#endif
+#if defined(RGFW_EGL) && defined(__APPLE__)
+	#warning  EGL is not supported for Cocoa, switching back to the native opengl api
+#undef RGFW_EGL
+#endif
+
+#if !defined(RGFW_OSMESA) && !defined(RGFW_EGL) && !defined(RGFW_OPENGL) && !defined (RGFW_VULKAN) && !defined(RGFW_DIRECTX) && !defined(RGFW_BUFFER) && !defined(RGFW_NO_API)
+#define RGFW_OPENGL
+#endif
+
+#ifdef RGFW_VULKAN
+#ifndef RGFW_MAX_FRAMES_IN_FLIGHT
+#define RGFW_MAX_FRAMES_IN_FLIGHT 2
+#endif
+
+#ifdef RGFW_X11
+#define VK_USE_PLATFORM_XLIB_KHR
+#endif
+#ifdef RGFW_WINDOWS
+#define VK_USE_PLATFORM_WIN32_KHR
+#endif
+#ifdef RGFW_MACOS
+#define VK_USE_PLATFORM_MACOS_MVK
+#endif
+
+#include <vulkan/vulkan.h>
+#endif
+
+#if defined(RGFW_X11) && defined(RGFW_OPENGL)
+#ifndef GLX_MESA_swap_control
+#define  GLX_MESA_swap_control
+#endif
+#include <GL/glx.h> /* GLX defs, xlib.h, gl.h */
+#endif
+
+#ifdef RGFW_EGL
+#include <EGL/egl.h>
+#endif
+
+#ifdef RGFW_OSMESA
+#ifndef __APPLE__
+#include <GL/osmesa.h>
+#else
+#include <OpenGL/osmesa.h>
+#endif
+#endif
+
+#if defined(RGFW_DIRECTX) && defined(RGFW_WINDOWS)
+#include <d3d11.h>
+#include <dxgi.h>
+#include <dxgi.h>
+#include <d3dcompiler.h>
+
+#ifndef __cplusplus
+#define __uuidof(T) IID_##T
+#endif
+#endif
+
+		/*! Optional arguments for making a windows */
+#define RGFW_TRANSPARENT_WINDOW		(1L<<9) /*!< the window is transparent */
+#define RGFW_NO_BORDER		(1L<<3) /*!< the window doesn't have border */
+#define RGFW_NO_RESIZE		(1L<<4) /*!< the window cannot be resized  by the user */
+#define RGFW_ALLOW_DND     (1L<<5) /*!< the window supports drag and drop*/
+#define RGFW_HIDE_MOUSE (1L<<6) /*! the window should hide the mouse or not (can be toggled later on) using `RGFW_window_mouseShow*/
+#define RGFW_FULLSCREEN (1L<<8) /* the window is fullscreen by default or not */
+#define RGFW_CENTER (1L<<10) /*! center the window on the screen */
+#define RGFW_OPENGL_SOFTWARE (1L<<11) /*! use OpenGL software rendering */
+#define RGFW_COCOA_MOVE_TO_RESOURCE_DIR (1L << 12) /* (cocoa only), move to resource folder */
+#define RGFW_SCALE_TO_MONITOR (1L << 13) /* scale the window to the screen */
+
+#define RGFW_NO_GPU_RENDER (1L<<14) /* don't render (using the GPU based API)*/
+#define RGFW_NO_CPU_RENDER (1L<<15) /* don't render (using the CPU based buffer rendering)*/
+
+
+/*! event codes */
+#define RGFW_keyPressed 2 /* a key has been pressed */
+#define RGFW_keyReleased 3 /*!< a key has been released*/
+/*! key event note
+	the code of the key pressed is stored in
+	RGFW_Event.keyCode
+	!!Keycodes defined at the bottom of the header file!!
+
+	while a string version is stored in
+	RGFW_Event.KeyString
+
+	RGFW_Event.lockState holds the current lockState
+	this means if CapsLock, NumLock are active or not
+*/
+#define RGFW_mouseButtonPressed 4 /*!< a mouse button has been pressed (left,middle,right)*/
+#define RGFW_mouseButtonReleased 5 /*!< a mouse button has been released (left,middle,right)*/
+#define RGFW_mousePosChanged 6 /*!< the position of the mouse has been changed*/
+/*! mouse event note
+	the x and y of the mouse can be found in the vector, RGFW_Event.point
+
+	RGFW_Event.button holds which mouse button was pressed
+*/
+#define RGFW_jsButtonPressed 7 /*!< a joystick button was pressed */
+#define RGFW_jsButtonReleased 8 /*!< a joystick button was released */
+#define RGFW_jsAxisMove 9 /*!< an axis of a joystick was moved*/
+/*! joystick event note
+	RGFW_Event.joystick holds which joystick was altered, if any
+	RGFW_Event.button holds which joystick button was pressed
+
+	RGFW_Event.axis holds the data of all the axis
+	RGFW_Event.axisCount says how many axis there are
+*/
+#define RGFW_windowAttribsChange 10 /*!< the window was moved or resized (by the user) */
+/* attribs change event note
+	The event data is sent straight to the window structure
+	with win->r.x, win->r.y, win->r.w and win->r.h
+*/
+#define RGFW_quit 33 /*!< the user clicked the quit button*/ 
+#define RGFW_dnd 34 /*!< a file has been dropped into the window*/
+#define RGFW_dnd_init 35 /*!< the start of a dnd event, when the place where the file drop is known */
+/* dnd data note
+	The x and y coords of the drop are stored in the vector RGFW_Event.point
+
+	RGFW_Event.droppedFilesCount holds how many files were dropped
+
+	This is also the size of the array which stores all the dropped file string,
+	RGFW_Event.droppedFiles
+*/
+
+/*! mouse button codes (RGFW_Event.button) */
+#define RGFW_mouseLeft  1 /*!< left mouse button is pressed*/
+#define RGFW_mouseMiddle  2 /*!< mouse-wheel-button is pressed*/
+#define RGFW_mouseRight  3 /*!< right mouse button is pressed*/
+#define RGFW_mouseScrollUp  4 /*!< mouse wheel is scrolling up*/
+#define RGFW_mouseScrollDown  5 /*!< mouse wheel is scrolling down*/
+
+#ifndef RGFW_MAX_PATH
+#define RGFW_MAX_PATH 260 /* max length of a path (for dnd) */
+#endif
+#ifndef RGFW_MAX_DROPS
+#define RGFW_MAX_DROPS 260 /* max items you can drop at once */
+#endif
+
+
+/* for RGFW_Event.lockstate */
+#define RGFW_CAPSLOCK (1L << 1)
+#define RGFW_NUMLOCK (1L << 2)
+
+/*! joystick button codes (based on xbox/playstation), you may need to change these values per controller */
+#ifndef RGFW_JS_A
+
+#define RGFW_JS_A 0 /* or PS X button */
+#define RGFW_JS_B 1 /* or PS circle button */
+#define RGFW_JS_Y 2 /* or PS triangle button */
+#define RGFW_JS_X 3 /* or PS square button */
+#define RGFW_JS_START 9 /* start button */
+#define RGFW_JS_SELECT 8 /* select button */
+#define RGFW_JS_HOME 10 /* home button */
+#define RGFW_JS_UP 13 /* dpad up */
+#define RGFW_JS_DOWN 14 /* dpad down*/
+#define RGFW_JS_LEFT 15 /* dpad left */
+#define RGFW_JS_RIGHT 16 /* dpad right */
+#define RGFW_JS_L1 4 /* left bump */
+#define RGFW_JS_L2 5 /* left trigger*/
+#define RGFW_JS_R1 6 /* right bumper */
+#define RGFW_JS_R2 7 /* right trigger */
+
+#endif
+
+/* basic vector type, if there's not already a point/vector type of choice */
+#ifndef RGFW_vector
+typedef struct { i32 x, y; } RGFW_vector;
+#endif
+
+	/* basic rect type, if there's not already a rect type of choice */
+#ifndef RGFW_rect
+	typedef struct { i32 x, y, w, h; } RGFW_rect;
+#endif
+
+	/* basic area type, if there's not already a area type of choice */
+#ifndef RGFW_area
+	typedef struct { u32 w, h; } RGFW_area;
+#endif
+
+#define RGFW_VECTOR(x, y) (RGFW_vector){x, y}
+#define RGFW_RECT(x, y, w, h) (RGFW_rect){x, y, w, h}
+#define RGFW_AREA(w, h) (RGFW_area){w, h}
+
+	typedef struct RGFW_monitor {
+		char name[128];  /* monitor name */
+		RGFW_rect rect; /* monitor Workarea */
+		float scaleX, scaleY; /* monitor content scale*/
+		float physW, physH; /* monitor physical size */
+	} RGFW_monitor;
+
+	/*
+	NOTE : Monitor functions should be ran only as many times as needed (not in a loop)
+	*/
+
+	/* get an array of all the monitors (max 6) */
+	RGFWDEF RGFW_monitor* RGFW_getMonitors(void);
+	/* get the primary monitor */
+	RGFWDEF RGFW_monitor RGFW_getPrimaryMonitor(void);
+
+	/* NOTE: some parts of the data can represent different things based on the event (read comments in RGFW_Event struct) */
+	typedef struct RGFW_Event {
+#ifdef RGFW_WINDOWS
+		char keyName[16]; /* key name of event*/
+#else
+		char* keyName; /*!< key name of event */
+#endif
+
+		/*! drag and drop data */
+		/* 260 max paths with a max length of 260 */
+#ifdef RGFW_ALLOC_DROPFILES
+		char** droppedFiles;
+#else
+		char droppedFiles[RGFW_MAX_DROPS][RGFW_MAX_PATH]; /*!< dropped files*/
+#endif
+		u32 droppedFilesCount; /*!< house many files were dropped */
+
+		u32 type; /*!< which event has been sent?*/
+		RGFW_vector point; /*!< mouse x, y of event (or drop point) */
+		u32 keyCode; /*!< keycode of event 	!!Keycodes defined at the bottom of the header file!! */
+
+		u32 inFocus;  /*if the window is in focus or not*/
+
+		u32 fps; /*the current fps of the window [the fps is checked when events are checked]*/
+		u32 current_ticks, frames; /* this is used for counting the fps */
+
+		u8 lockState;
+
+		u16 joystick; /* which joystick this event applies to (if applicable to any) */
+
+		u8 button; /*!< which mouse button has been clicked (0) left (1) middle (2) right OR which joystick button was pressed*/
+		double scroll; /* the raw mouse scroll value */
+
+		u8 axisesCount; /* number of axises */
+		RGFW_vector axis[2]; /* x, y of axises (-100 to 100) */
+	} RGFW_Event; /*!< Event structure for checking/getting events */
+
+	/* source data for the window (used by the APIs) */
+	typedef struct RGFW_window_src {
+#ifdef RGFW_WINDOWS
+		HWND window; /*!< source window */
+		HDC hdc; /*!< source HDC */
+		u32 hOffset; /*!< height offset for window */
+#endif
+#ifdef RGFW_X11
+		Display* display; /*!< source display */
+		Window window; /*!< source window */
+		Cursor cursor;
+#endif
+#ifdef RGFW_MACOS
+		u32 display;
+		void* displayLink;
+		void* window;
+#endif
+
+#if defined(RGFW_OPENGL) && !defined(RGFW_OSMESA)
+#ifdef RGFW_MACOS
+		void* rSurf; /*!< source graphics context */
+#endif
+#ifdef RGFW_WINDOWS
+		HGLRC rSurf; /*!< source graphics context */
+#endif
+#ifdef RGFW_X11
+		GLXContext rSurf; /*!< source graphics context */
+#endif
+#else
+#ifdef RGFW_VULKAN
+		VkSurfaceKHR rSurf; /*!< source graphics context */
+
+		/* vulkan data */
+		VkSwapchainKHR swapchain;
+		u32 image_count;
+		VkImage* swapchain_images;
+		VkImageView* swapchain_image_views;
+#endif
+
+#ifdef RGFW_OSMESA
+		OSMesaContext rSurf;
+#endif
+#endif
+
+#ifdef RGFW_WINDOWS
+		RGFW_area maxSize, minSize;
+#if defined(RGFW_DIRECTX)
+		IDXGISwapChain* swapchain;
+		ID3D11RenderTargetView* renderTargetView;
+		ID3D11DepthStencilView* pDepthStencilView;
+#endif
+#endif
+
+#if defined(RGFW_MACOS) && !defined(RGFW_MACOS_X11)
+		void* view; /*apple viewpoint thingy*/
+#endif
+
+#ifdef RGFW_EGL
+		EGLSurface EGL_surface;
+		EGLDisplay EGL_display;
+#endif
+
+#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) 
+#ifdef RGFW_WINDOWS
+		HBITMAP bitmap;
+#endif
+#ifdef RGFW_X11
+		XImage* bitmap;
+#endif
+#ifdef RGFW_MACOS
+		void* bitmap; /* API's bitmap for storing or managing */
+		void* image;
+#endif
+#if defined(RGFW_BUFFER) && defined(RGFW_WINDOWS)
+		HDC hdcMem; /* window stored in memory that winapi needs to render buffers */
+#endif
+#endif
+
+		u8 jsPressed[4][16]; /* if a key is currently pressed or not (per joystick) */
+
+		i32 joysticks[4]; /* limit of 4 joysticks at a time */
+		u16 joystickCount; /* the actual amount of joysticks */
+
+		RGFW_area scale; /* window scaling */
+
+#ifdef RGFW_MACOS
+		u8 cursorChanged; /* for steve jobs */
+#endif
+
+		u32 winArgs; /* windows args (for RGFW to check) */
+		/*
+			!< if dnd is enabled or on (based on window creating args)
+			cursorChanged
+		*/
+	} RGFW_window_src;
+
+	typedef struct RGFW_window {
+		RGFW_window_src src;
+
+#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) 
+		u8* buffer; /* buffer for non-GPU systems (OSMesa, basic software rendering) */
+		/* when rendering using RGFW_BUFFER, the buffer is in the RGBA format */
+#endif
+
+		RGFW_Event event; /*!< current event */
+
+		RGFW_rect r; /* the x, y, w and h of the struct */
+
+		u8 fpsCap; /*!< the fps cap of the window should run at (change this var to change the fps cap, 0 = no limit)*/
+		/*[the fps is capped when events are checked]*/
+	} RGFW_window; /*!< Window structure for managing the window */
+
+#if defined(RGFW_X11) || defined(RGFW_MACOS)
+	typedef u64 RGFW_thread; /* thread type unix */
+#else
+	typedef void* RGFW_thread; /* thread type for window */
+#endif
+
+	RGFW_window* RGFW_createWindow(
+		const char* name, /* name of the window */
+		RGFW_rect rect, /* rect of window */
+		u16 args /* extra arguments (NULL / (u16)0 means no args used)*/
+	); /*!< function to create a window struct */
+
+	/* get the size of the screen to an area struct */
+	RGFWDEF RGFW_area RGFW_getScreenSize(void);
+
+	/*
+		this function checks an *individual* event (and updates window structure attributes)
+		this means, using this function without a while loop may cause event lag
+
+		ex.
+
+		while (RGFW_window_checkEvent(win) != NULL) [this keeps checking events until it reaches the last one]
+	*/
+
+	RGFW_Event* RGFW_window_checkEvent(RGFW_window* win); /*!< check events (returns a pointer to win->event or NULL if there is no event)*/
+
+	/*! window managment functions*/
+	RGFWDEF void RGFW_window_close(RGFW_window* win); /*!< close the window and free leftover data */
+
+	RGFWDEF void RGFW_window_move(RGFW_window* win,
+		RGFW_vector v/* new pos*/
+	);
+
+	/* move to a specific monitor */
+	RGFWDEF void RGFW_window_moveToMonitor(RGFW_window* win, RGFW_monitor m);
+
+	RGFWDEF void RGFW_window_resize(RGFW_window* win,
+		RGFW_area a/* new size*/
+	);
+
+	/* set the minimum size a user can shrink a window */
+	RGFWDEF void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a);
+	/* set the minimum size a user can extend a window */
+	RGFWDEF void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a);
+
+	RGFWDEF void RGFW_window_maximize(RGFW_window* win); /* maximize the window size */
+	RGFWDEF void RGFW_window_minimize(RGFW_window* win); /* minimize the window (in taskbar (per OS))*/
+	RGFWDEF void RGFW_window_restore(RGFW_window* win); /* restore the window from minimized (per OS)*/
+
+	RGFWDEF void RGFW_window_setName(RGFW_window* win,
+		char* name
+	);
+
+	void RGFW_window_setIcon(RGFW_window* win, /*!< source window */
+		u8* icon /*!< icon bitmap */,
+		RGFW_area a /*!< width and height of the bitmap*/,
+		i32 channels /*!< how many channels the bitmap has (rgb : 3, rgba : 4) */
+	); /*!< image resized by default */
+
+	/*!< sets mouse to bitmap (very simular to RGFW_window_setIcon), image NOT resized by default*/
+	RGFWDEF void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels);
+
+	/*!< sets the mouse to a standard API cursor (based on RGFW_MOUSE, as seen at the end of the file) */
+#ifdef RGFW_MACOS
+	RGFWDEF void RGFW_window_setMouseStandard(RGFW_window* win, void* mouse);
+#else
+	RGFWDEF	void RGFW_window_setMouseStandard(RGFW_window* win, i32 mouse);
+#endif
+
+	RGFWDEF void RGFW_window_setMouseDefault(RGFW_window* win); /* sets the mouse to1` the default mouse image */
+	/*
+		holds the mouse in place by moving the mouse back each time it moves
+		you can still use win->event.point to see how much it moved before it was put back in place
+
+		this is useful for a 3D camera
+	*/
+	RGFWDEF void RGFW_window_mouseHold(RGFW_window* win);
+	/* undo hold */
+	RGFWDEF void RGFW_window_mouseUnhold(RGFW_window* win);
+
+	/* hide the window */
+	RGFWDEF void RGFW_window_hide(RGFW_window* win);
+	/* show the window */
+	RGFWDEF void RGFW_window_show(RGFW_window* win);
+
+	/*
+		makes it so `RGFW_window_shouldClose` returns true
+		by setting the window event.type to RGFW_quit
+	*/
+	RGFWDEF void RGFW_window_setShouldClose(RGFW_window* win);
+
+	/* where the mouse is on the screen */
+	RGFWDEF RGFW_vector RGFW_getGlobalMousePoint(void);
+
+	/* show the mouse or hide the mouse*/
+	RGFWDEF void RGFW_window_showMouse(RGFW_window* win, i8 show);
+	/* move the mouse to a set x, y pos*/
+	RGFWDEF void RGFW_window_moveMouse(RGFW_window* win, RGFW_vector v);
+
+	/* if the window should close (RGFW_close was sent or escape was pressed) */
+	RGFWDEF u8 RGFW_window_shouldClose(RGFW_window* win);
+	/* if window is fullscreen'd */
+	RGFWDEF u8 RGFW_window_isFullscreen(RGFW_window* win);
+	/* if window is hidden */
+	RGFWDEF u8 RGFW_window_isHidden(RGFW_window* win);
+	/* if window is minimized */
+	RGFWDEF u8 RGFW_window_isMinimized(RGFW_window* win);
+	/* if window is maximized */
+	RGFWDEF u8 RGFW_window_isMaximized(RGFW_window* win);
+
+	/*
+	scale the window to the monitor,
+	this is run by default if the user uses the arg `RGFW_SCALE_TO_MONITOR` during window creation
+	*/
+	RGFWDEF void RGFW_window_scaleToMonitor(RGFW_window* win);
+
+	/* get the struct of the window's monitor  */
+	RGFWDEF RGFW_monitor RGFW_window_getMonitor(RGFW_window* win);
+
+	/*!< make the window the current opengl drawing context */
+	RGFWDEF void RGFW_window_makeCurrent(RGFW_window* win);
+
+	/*error handling*/
+	RGFWDEF u8 RGFW_Error(); /* returns true if an error has occurred (doesn't print errors itself) */
+
+	/*!< if window == NULL, it checks if the key is pressed globally. Otherwise, it checks only if the key is pressed while the window in focus.*/
+	RGFWDEF u8 RGFW_isPressedI(RGFW_window* win, u32 key); /*!< if key is pressed (key code)*/
+
+	/*
+		!!Keycodes defined at the bottom of the header file!!
+	*/
+	/*!< converts a key code to it's key string */
+	RGFWDEF char* RGFW_keyCodeTokeyStr(u64 key);
+	/*!< converts a string of a key to it's key code */
+	RGFWDEF u32 RGFW_keyStrToKeyCode(char* key);
+	/*!< if key is pressed (key string) */
+#define RGFW_isPressedS(win, key) RGFW_isPressedI(win, RGFW_keyStrToKeyCode(key))
+
+/*! clipboard functions*/
+	RGFWDEF char* RGFW_readClipboard(size_t* size); /*!< read clipboard data */
+#define RGFW_clipboardFree free /* the string returned from RGFW_readClipboard must be freed */
+
+	RGFWDEF void RGFW_writeClipboard(const char* text, u32 textLen); /*!< write text to the clipboard */
+
+	/*
+		convert a keyString to a char version
+	*/
+	RGFWDEF char RGFW_keystrToChar(const char*);
+	/*
+		ex.
+		"parenleft" -> '('
+		"A" -> 'A',
+		"Return" -> "\n"
+	*/
+
+#ifndef RGFW_NO_THREADS
+	/*! threading functions*/
+
+	/*! NOTE! (for X11/linux) : if you define a window in a thread, it must be run after the original thread's window is created or else there will be a memory error */
+	/*
+		I'd suggest you use sili's threading functions instead
+		if you're going to use sili
+		which is a good idea generally
+	*/
+	RGFWDEF RGFW_thread RGFW_createThread(void* (*function_ptr)(void*), void* args); /*!< create a thread*/
+	RGFWDEF void RGFW_cancelThread(RGFW_thread thread); /*!< cancels a thread*/
+	RGFWDEF void RGFW_joinThread(RGFW_thread thread); /*!< join thread to current thread */
+	RGFWDEF void RGFW_setThreadPriority(RGFW_thread thread, u8 priority); /*!< sets the priority priority  */
+#endif
+
+	/*! gamepad/joystick functions (linux-only currently) */
+
+	/*! joystick count starts at 0*/
+	/*!< register joystick to window based on a number (the number is based on when it was connected eg. /dev/js0)*/
+	RGFWDEF u16 RGFW_registerJoystick(RGFW_window* win, i32 jsNumber);
+	RGFWDEF u16 RGFW_registerJoystickF(RGFW_window* win, char* file);
+
+	RGFWDEF u32 RGFW_isPressedJS(RGFW_window* win, u16 controller, u8 button);
+
+	/*! native opengl functions */
+#ifdef RGFW_OPENGL
+/*! Get max OpenGL version */
+	RGFWDEF u8* RGFW_getMaxGLVersion();
+	/* OpenGL init hints */
+	RGFWDEF void RGFW_setGLStencil(i32 stencil); /* set stencil buffer bit size (8 by default) */
+	RGFWDEF void RGFW_setGLSamples(i32 samples); /* set number of sampiling buffers (4 by default) */
+	RGFWDEF void RGFW_setGLStereo(i32 stereo); /* use GL_STEREO (GL_FALSE by default) */
+	RGFWDEF void RGFW_setGLAuxBuffers(i32 auxBuffers); /* number of aux buffers (0 by default) */
+
+	/*! Set OpenGL version hint */
+	RGFWDEF void RGFW_setGLVersion(i32 major, i32 minor);
+	RGFWDEF void* RGFW_getProcAddress(const char* procname); /* get native opengl proc address */
+#endif
+	/* supports openGL, directX, OSMesa, EGL and software rendering */
+	RGFWDEF void RGFW_window_swapBuffers(RGFW_window* win); /* swap the rendering buffer */
+	RGFWDEF void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval);
+
+	RGFWDEF void RGFW_window_setGPURender(RGFW_window* win, i8 set);
+
+#ifdef RGFW_VULKAN
+	typedef struct {
+		VkInstance instance;
+		VkPhysicalDevice physical_device;
+		VkDevice device;
+
+		VkDebugUtilsMessengerEXT debugMessenger;
+
+		VkQueue graphics_queue;
+		VkQueue present_queue;
+
+		VkFramebuffer* framebuffers;
+
+		VkRenderPass render_pass;
+		VkPipelineLayout pipeline_layout;
+		VkPipeline graphics_pipeline;
+
+		VkCommandPool command_pool;
+		VkCommandBuffer* command_buffers;
+
+		VkSemaphore* available_semaphores;
+		VkSemaphore* finished_semaphore;
+		VkFence* in_flight_fences;
+		VkFence* image_in_flight;
+		size_t current_frame;
+	} RGFW_vulkanInfo;
+
+	/*! initializes a vulkan rendering context for the RGFW window,
+		this outputs the vulkan surface into wwin->src.rSurf
+		other vulkan data is stored in the global instance of the RGFW_vulkanInfo structure which is returned
+		by the initVulkan() function
+		RGFW_VULKAN must be defined for this function to be defined
+
+	*/
+	RGFWDEF RGFW_vulkanInfo* RGFW_initVulkan(RGFW_window* win);
+	RGFWDEF void RGFW_freeVulkan(void);
+
+	RGFWDEF RGFW_vulkanInfo* RGFW_getVulkanInfo(void);
+
+	RGFWDEF int RGFW_initData(RGFW_window* win);
+	RGFWDEF void RGFW_createSurface(VkInstance instance, RGFW_window* win);
+	int RGFW_deviceInitialization(RGFW_window* win);
+	int RGFW_createSwapchain(RGFW_window* win);
+	RGFWDEF int RGFW_createRenderPass();
+	int RGFW_createCommandPool();
+	int RGFW_createCommandBuffers(RGFW_window* win);
+	int RGFW_createSyncObjects(RGFW_window* win);
+	RGFWDEF int RGFW_createFramebuffers(RGFW_window* win);
+#endif
+
+#ifdef RGFW_DIRECTX
+	typedef struct {
+		IDXGIFactory* pFactory;
+		IDXGIAdapter* pAdapter;
+		ID3D11Device* pDevice;
+		ID3D11DeviceContext* pDeviceContext;
+	} RGFW_directXinfo;
+
+	/*
+		RGFW stores a global instance of RGFW_directXinfo,
+		you can use this function to get a pointer the instance
+	*/
+	RGFWDEF RGFW_directXinfo* RGFW_getDirectXInfo(void);
+#endif
+
+	/*! Supporting functions */
+	RGFWDEF void RGFW_window_checkFPS(RGFW_window* win); /*!< updates fps / sets fps to cap (ran by RGFW_window_checkEvent)*/
+	RGFWDEF u64 RGFW_getTime(void); /* get time in seconds */
+	RGFWDEF u64 RGFW_getTimeNS(void); /* get time in nanoseconds */
+	RGFWDEF u32 RGFW_getFPS(void); /* get current FPS (win->event.fps) */
+	RGFWDEF void RGFW_sleep(u32 microsecond); /* sleep for a set time */
+#endif /* RGFW_HEADER */
+
+	/*
+	Example to get you started :
+
+	linux : gcc main.c -lX11 -lXcursor -lGL
+	windows : gcc main.c -lopengl32 -lshell32 -lgdi32
+	macos : gcc main.c -framework Foundation -framework AppKit -framework OpenGL -framework CoreVideo
+
+	#define RGFW_IMPLEMENTATION
+	#include "RGFW.h"
+
+	u8 icon[4 * 3 * 3] = {0xFF, 0x00, 0x00, 0xFF,    0xFF, 0x00, 0x00, 0xFF,     0xFF, 0x00, 0x00, 0xFF,   0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFF,     0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF};
+
+	int main() {
+		RGFW_window* win = RGFW_createWindow("name", RGFW_RECT(500, 500, 500, 500), (u64)0);
+
+		RGFW_window_setIcon(win, icon, RGFW_AREA(3, 3), 4);
+
+		for (;;) {
+			RGFW_window_checkEvent(win); // NOTE: checking events outside of a while loop may cause input lag
+			if (win->event.type == RGFW_quit || RGFW_isPressedI(win, RGFW_Escape))
+				break;
+
+			RGFW_window_swapBuffers(win);
+
+			glClearColor(0xFF, 0XFF, 0xFF, 0xFF);
+			glClear(GL_COLOR_BUFFER_BIT);
+		}
+
+		RGFW_window_close(win);
+	}
+
+		compiling :
+
+		if you wish to compile the library all you have to do is create a new file with this in it
+
+		rgfw.c
+		#define RGFW_IMPLEMENTATION
+		#include "RGFW.h"
+
+		then you can use gcc (or whatever compile you wish to use) to compile the library into object file
+
+		ex. gcc -c RGFW.c -fPIC
+
+		after you compile the library into an object file, you can also turn the object file into an static or shared library
+
+		(commands ar and gcc can be replaced with whatever equivalent your system uses)
+		static : ar rcs RGFW.a RGFW.o
+		shared :
+			windows:
+				gcc -shared RGFW.o -lopengl32 -lshell32 -lgdi32 -o RGFW.dll
+			linux:
+				gcc -shared RGFW.o -lX11 -lXcursor -lGL -o RGFW.so
+			macos:
+				gcc -shared RGFW.o -framework Foundation -framework AppKit -framework OpenGL -framework CoreVideo
+	*/
+
+#ifdef RGFW_X11
+#define RGFW_OS_BASED_VALUE(l, w, m) l
+#endif
+#ifdef RGFW_WINDOWS
+#define RGFW_OS_BASED_VALUE(l, w, m) w
+#endif
+#ifdef RGFW_MACOS
+#define RGFW_OS_BASED_VALUE(l, w, m) m
+#endif
+
+#ifdef RGFW_IMPLEMENTATION
+
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <assert.h>
+
+#ifdef RGFW_WINDOWS
+
+#define WIN32_LEAN_AND_MEAN
+
+#include <windows.h>
+
+#endif
+
+#ifdef RGFW_MACOS
+#include <CoreVideo/CVDisplayLink.h>
+
+	/*
+		based on silicon.h
+	*/
+
+#define GL_SILENCE_DEPRECATION
+#include <CoreVideo/CVDisplayLink.h>
+#include <ApplicationServices/ApplicationServices.h>
+#include <objc/runtime.h>
+#include <objc/message.h>
+
+	typedef CGRect NSRect;
+	typedef CGPoint NSPoint;
+	typedef CGSize NSSize;
+
+	typedef void NSBitmapImageRep;
+	typedef void NSCursor;
+	typedef void NSDraggingInfo;
+	typedef void NSWindow;
+	typedef void NSApplication;
+	typedef void NSScreen;
+	typedef void NSEvent;
+	typedef void NSString;
+	typedef void NSOpenGLContext;
+	typedef void NSPasteboard;
+	typedef void NSColor;
+	typedef void NSArray;
+	typedef void NSImageRep;
+	typedef void NSImage;
+	typedef void NSOpenGLView;
+
+
+	typedef const char* NSPasteboardType;
+	typedef unsigned long NSUInteger;
+	typedef long NSInteger;
+	typedef NSInteger NSModalResponse;
+
+#ifdef __arm64__
+	/* ARM just uses objc_msgSend */
+#define abi_objc_msgSend_stret objc_msgSend
+#define abi_objc_msgSend_fpret objc_msgSend
+#else /* __i386__ */ 
+	/* x86 just uses abi_objc_msgSend_fpret and (NSColor *)objc_msgSend_id respectively */
+#define abi_objc_msgSend_stret objc_msgSend_stret
+#define abi_objc_msgSend_fpret objc_msgSend_fpret
+#endif
+
+#define NSAlloc(nsclass) objc_msgSend_id(nsclass, sel_registerName("alloc"))
+#define objc_msgSend_bool			((BOOL (*)(id, SEL))objc_msgSend)
+#define objc_msgSend_void			((void (*)(id, SEL))objc_msgSend)
+#define objc_msgSend_void_id		((void (*)(id, SEL, id))objc_msgSend)
+#define objc_msgSend_uint			((NSUInteger (*)(id, SEL))objc_msgSend)
+#define objc_msgSend_void_bool		((void (*)(id, SEL, BOOL))objc_msgSend)
+#define objc_msgSend_void_SEL		((void (*)(id, SEL, SEL))objc_msgSend)
+#define objc_msgSend_id				((id (*)(id, SEL))objc_msgSend)
+
+#define si_declare_single(class, name, func)	\
+	void class##_##name(class* obj) { \
+		return objc_msgSend_void(obj, sel_registerName(func)); \
+	}
+
+
+#define loadFunc(funcName) \
+	static void* func = NULL;\
+	if (func == NULL) \
+		func = sel_registerName(funcName);
+
+	void NSRelease(id obj) {
+		loadFunc("release");
+		objc_msgSend_void(obj, func);
+	}
+
+#define release NSRelease
+
+	si_declare_single(NSApplication, finishLaunching, "finishLaunching")
+		si_declare_single(NSOpenGLContext, flushBuffer, "flushBuffer")
+
+		NSString* NSString_stringWithUTF8String(const char* str) {
+		loadFunc("stringWithUTF8String:");
+
+		return ((id(*)(id, SEL, const char*))objc_msgSend)
+			(objc_getClass("NSString"), func, str);
+	}
+
+	const char* NSString_to_char(NSString* str) {
+		return ((const char* (*)(id, SEL)) objc_msgSend) (str, sel_registerName("UTF8String"));
+	}
+
+	void si_impl_func_to_SEL_with_name(const char* class_name, const char* register_name, void* function) {
+		Class selected_class;
+
+		if (strcmp(class_name, "NSView") == 0) {
+			selected_class = objc_getClass("ViewClass");
+		} else if (strcmp(class_name, "NSWindow") == 0) {
+			selected_class = objc_getClass("WindowClass");
+		} else {
+			selected_class = objc_getClass(class_name);
+		}
+
+		class_addMethod(selected_class, sel_registerName(register_name), (IMP) function, 0);
+	}
+
+	/* Header for the array. */
+	typedef struct siArrayHeader {
+		size_t count;
+		/* TODO(EimaMei): Add a `type_width` later on. */
+	} siArrayHeader;
+
+	/* Gets the header of the siArray. */
+#define SI_ARRAY_HEADER(s) ((siArrayHeader*)s - 1)
+
+	void* si_array_init_reserve(size_t sizeof_element, size_t count) {
+		siArrayHeader* ptr = malloc(sizeof(siArrayHeader) + (sizeof_element * count));
+		void* array = ptr + sizeof(siArrayHeader);
+
+		siArrayHeader* header = SI_ARRAY_HEADER(array);
+		header->count = count;
+
+		return array;
+	}
+
+#define si_array_len(array) (SI_ARRAY_HEADER(array)->count)
+#define si_func_to_SEL(class_name, function) si_impl_func_to_SEL_with_name(class_name, #function":", function)
+	/* Creates an Objective-C method (SEL) from a regular C function with the option to set the register name.*/
+#define si_func_to_SEL_with_name(class_name, register_name, function) si_impl_func_to_SEL_with_name(class_name, register_name":", function)
+
+	NSRect NSMakeRect(double x, double y, double width, double height) {
+		NSRect r;
+		r.origin.x = x;
+		r.origin.y = y;
+		r.size.width = width;
+		r.size.height = height;
+
+		return r;
+	}
+
+	NSPoint NSMakePoint(double x, double y) {
+		NSPoint point;
+		point.x = x;
+		point.y = y;
+		return point;
+	}
+
+	NSSize NSMakeSize(double w, double h) {
+		NSSize size;
+		size.width = w;
+		size.height = h;
+		return size;
+	}
+
+	void* si_array_init(void* allocator, size_t sizeof_element, size_t count) {
+		void* array = si_array_init_reserve(sizeof_element, count);
+		memcpy(array, allocator, sizeof_element * count);
+
+		return array;
+	}
+
+	void si_array_free(void* array) {
+		if (array == NULL)
+			return;
+
+		free(SI_ARRAY_HEADER(array));
+	}
+
+	unsigned char* NSBitmapImageRep_bitmapData(NSBitmapImageRep* imageRep) {
+		return ((unsigned char* (*)(id, SEL))objc_msgSend)
+			(imageRep, sel_registerName("bitmapData"));
+	}
+
+#define NS_ENUM(type, name) type name; enum
+
+	typedef NS_ENUM(NSUInteger, NSBitmapFormat) {
+		NSBitmapFormatAlphaFirst = 1 << 0,       // 0 means is alpha last (RGBA, CMYKA, etc.)
+			NSBitmapFormatAlphaNonpremultiplied = 1 << 1,       // 0 means is premultiplied
+			NSBitmapFormatFloatingPointSamples = 1 << 2,  // 0 is integer
+
+			NSBitmapFormatSixteenBitLittleEndian API_AVAILABLE(macos(10.10)) = (1 << 8),
+			NSBitmapFormatThirtyTwoBitLittleEndian API_AVAILABLE(macos(10.10)) = (1 << 9),
+			NSBitmapFormatSixteenBitBigEndian API_AVAILABLE(macos(10.10)) = (1 << 10),
+			NSBitmapFormatThirtyTwoBitBigEndian API_AVAILABLE(macos(10.10)) = (1 << 11)
+	};
+
+	NSBitmapImageRep* 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) {
+		void* func = sel_registerName("initWithBitmapDataPlanes:pixelsWide:pixelsHigh:bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:colorSpaceName:bitmapFormat:bytesPerRow:bitsPerPixel:");
+
+		return (NSBitmapImageRep*) ((id(*)(id, SEL, unsigned char**, NSInteger, NSInteger, NSInteger, NSInteger, bool, bool, const char*, NSBitmapFormat, NSInteger, NSInteger))objc_msgSend)
+			(NSAlloc(objc_getClass("NSBitmapImageRep")), func, planes, width, height, bps, spp, alpha, isPlanar, NSString_stringWithUTF8String(colorSpaceName), bitmapFormat, rowBytes, pixelBits);
+	}
+
+	NSColor* NSColor_colorWithSRGB(CGFloat red, CGFloat green, CGFloat blue, CGFloat alpha) {
+		void* nsclass = objc_getClass("NSColor");
+		void* func = sel_registerName("colorWithSRGBRed:green:blue:alpha:");
+		return ((id(*)(id, SEL, CGFloat, CGFloat, CGFloat, CGFloat))objc_msgSend)
+			(nsclass, func, red, green, blue, alpha);
+	}
+
+	NSCursor* NSCursor_initWithImage(NSImage* newImage, NSPoint aPoint) {
+		void* func = sel_registerName("initWithImage:hotSpot:");
+		void* nsclass = objc_getClass("NSCursor");
+
+		return (NSCursor*) ((id(*)(id, SEL, id, NSPoint))objc_msgSend)
+			(NSAlloc(nsclass), func, newImage, aPoint);
+	}
+
+	void NSImage_addRepresentation(NSImage* image, NSImageRep* imageRep) {
+		void* func = sel_registerName("addRepresentation:");
+		objc_msgSend_void_id(image, func, imageRep);
+	}
+
+	NSImage* NSImage_initWithSize(NSSize size) {
+		void* func = sel_registerName("initWithSize:");
+		return ((id(*)(id, SEL, NSSize))objc_msgSend)
+			(NSAlloc(objc_getClass("NSImage")), func, size);
+	}
+#define NS_OPENGL_ENUM_DEPRECATED(minVers, maxVers) API_AVAILABLE(macos(minVers))
+	typedef NS_ENUM(NSInteger, NSOpenGLContextParameter) {
+		NSOpenGLContextParameterSwapInterval           NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 222, /* 1 param.  0 -> Don't sync, 1 -> Sync to vertical retrace     */
+			NSOpenGLContextParameterSurfaceOrder           NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 235, /* 1 param.  1 -> Above Window (default), -1 -> Below Window    */
+			NSOpenGLContextParameterSurfaceOpacity         NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 236, /* 1 param.  1-> Surface is opaque (default), 0 -> non-opaque   */
+			NSOpenGLContextParameterSurfaceBackingSize     NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 304, /* 2 params.  Width/height of surface backing size              */
+			NSOpenGLContextParameterReclaimResources       NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 308, /* 0 params.                                                    */
+			NSOpenGLContextParameterCurrentRendererID      NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 309, /* 1 param.   Retrieves the current renderer ID                 */
+			NSOpenGLContextParameterGPUVertexProcessing    NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 310, /* 1 param.   Currently processing vertices with GPU (get)      */
+			NSOpenGLContextParameterGPUFragmentProcessing  NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 311, /* 1 param.   Currently processing fragments with GPU (get)     */
+			NSOpenGLContextParameterHasDrawable            NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 314, /* 1 param.   Boolean returned if drawable is attached          */
+			NSOpenGLContextParameterMPSwapsInFlight        NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 315, /* 1 param.   Max number of swaps queued by the MP GL engine    */
+
+			NSOpenGLContextParameterSwapRectangle API_DEPRECATED("", macos(10.0, 10.14)) = 200, /* 4 params.  Set or get the swap rectangle {x, y, w, h} */
+			NSOpenGLContextParameterSwapRectangleEnable API_DEPRECATED("", macos(10.0, 10.14)) = 201, /* Enable or disable the swap rectangle */
+			NSOpenGLContextParameterRasterizationEnable API_DEPRECATED("", macos(10.0, 10.14)) = 221, /* Enable or disable all rasterization */
+			NSOpenGLContextParameterStateValidation API_DEPRECATED("", macos(10.0, 10.14)) = 301, /* Validate state for multi-screen functionality */
+			NSOpenGLContextParameterSurfaceSurfaceVolatile API_DEPRECATED("", macos(10.0, 10.14)) = 306, /* 1 param.   Surface volatile state */
+	};
+
+
+	void NSOpenGLContext_setValues(NSOpenGLContext* context, const int* vals, NSOpenGLContextParameter param) {
+		void* func = sel_registerName("setValues:forParameter:");
+		((void (*)(id, SEL, const int*, NSOpenGLContextParameter))objc_msgSend)
+			(context, func, vals, param);
+	}
+
+	void* NSOpenGLPixelFormat_initWithAttributes(const uint32_t* attribs) {
+		void* func = sel_registerName("initWithAttributes:");
+		return (void*) ((id(*)(id, SEL, const uint32_t*))objc_msgSend)
+			(NSAlloc(objc_getClass("NSOpenGLPixelFormat")), func, attribs);
+	}
+
+	NSOpenGLView* NSOpenGLView_initWithFrame(NSRect frameRect, uint32_t* format) {
+		void* func = sel_registerName("initWithFrame:pixelFormat:");
+		return (NSOpenGLView*) ((id(*)(id, SEL, NSRect, uint32_t*))objc_msgSend)
+			(NSAlloc(objc_getClass("NSOpenGLView")), func, frameRect, format);
+	}
+
+	void NSCursor_performSelector(NSCursor* cursor, void* selector) {
+		void* func = sel_registerName("performSelector:");
+		objc_msgSend_void_SEL(cursor, func, selector);
+	}
+
+	NSPasteboard* NSPasteboard_generalPasteboard(void) {
+		return (NSPasteboard*) objc_msgSend_id(objc_getClass("NSPasteboard"), sel_registerName("generalPasteboard"));
+	}
+
+	NSString** cstrToNSStringArray(char** strs, size_t len) {
+		static NSString* nstrs[6];
+		size_t i;
+		for (i = 0; i < len; i++)
+			nstrs[i] = NSString_stringWithUTF8String(strs[i]);
+
+		return nstrs;
+	}
+
+	const char* NSPasteboard_stringForType(NSPasteboard* pasteboard, NSPasteboardType dataType) {
+		void* func = sel_registerName("stringForType:");
+		return (const char*) NSString_to_char(((id(*)(id, SEL, const char*))objc_msgSend)(pasteboard, func, NSString_stringWithUTF8String(dataType)));
+	}
+
+	NSArray* c_array_to_NSArray(void* array, size_t len) {
+		void* func = sel_registerName("initWithObjects:count:");
+		void* nsclass = objc_getClass("NSArray");
+
+		return ((id(*)(id, SEL, void*, NSUInteger))objc_msgSend)
+			(NSAlloc(nsclass), func, array, len);
+	}
+
+	void NSregisterForDraggedTypes(void* view, NSPasteboardType* newTypes, size_t len) {
+		NSString** ntypes = cstrToNSStringArray(newTypes, len);
+
+		void* func = sel_registerName("registerForDraggedTypes:");
+
+		NSArray* array = c_array_to_NSArray(ntypes, len);
+
+		objc_msgSend_void_id(view, sel_registerName("registerForDraggedTypes:"), array);
+
+		NSRelease(array);
+	}
+
+	NSInteger NSPasteBoard_declareTypes(NSPasteboard* pasteboard, NSPasteboardType* newTypes, size_t len, void* owner) {
+		NSString** ntypes = cstrToNSStringArray(newTypes, len);
+
+		void* func = sel_registerName("declareTypes:owner:");
+
+		NSArray* array = c_array_to_NSArray(ntypes, len);
+
+		NSInteger output = ((NSInteger(*)(id, SEL, id, void*))objc_msgSend)
+			(pasteboard, func, array, owner);
+		NSRelease(array);
+
+		return output;
+	}
+
+	bool NSPasteBoard_setString(NSPasteboard* pasteboard, const char* stringToWrite, NSPasteboardType dataType) {
+		void* func = sel_registerName("setString:forType:");
+		return ((bool (*)(id, SEL, id, NSPasteboardType))objc_msgSend)
+			(pasteboard, func, NSString_stringWithUTF8String(stringToWrite), NSString_stringWithUTF8String(dataType));
+	}
+
+	void NSRetain(id obj) { objc_msgSend_void(obj, sel_registerName("retain")); }
+
+	typedef enum NSApplicationActivationPolicy {
+		NSApplicationActivationPolicyRegular,
+		NSApplicationActivationPolicyAccessory,
+		NSApplicationActivationPolicyProhibited
+	} NSApplicationActivationPolicy;
+
+	typedef NS_ENUM(u32, NSBackingStoreType) {
+		NSBackingStoreRetained = 0,
+			NSBackingStoreNonretained = 1,
+			NSBackingStoreBuffered = 2
+	};
+
+	typedef NS_ENUM(u32, NSWindowStyleMask) {
+		NSWindowStyleMaskBorderless = 0,
+			NSWindowStyleMaskTitled = 1 << 0,
+			NSWindowStyleMaskClosable = 1 << 1,
+			NSWindowStyleMaskMiniaturizable = 1 << 2,
+			NSWindowStyleMaskResizable = 1 << 3,
+			NSWindowStyleMaskTexturedBackground = 1 << 8, /* deprecated */
+			NSWindowStyleMaskUnifiedTitleAndToolbar = 1 << 12,
+			NSWindowStyleMaskFullScreen = 1 << 14,
+			NSWindowStyleMaskFullSizeContentView = 1 << 15,
+			NSWindowStyleMaskUtilityWindow = 1 << 4,
+			NSWindowStyleMaskDocModalWindow = 1 << 6,
+			NSWindowStyleMaskNonactivatingPanel = 1 << 7,
+			NSWindowStyleMaskHUDWindow = 1 << 13
+	};
+
+	typedef const char* NSPasteboardType;
+	NSPasteboardType const NSPasteboardTypeString = "public.utf8-plain-text"; // Replaces NSStringPboardType
+
+
+
+	typedef NS_ENUM(i32, NSDragOperation) {
+		NSDragOperationNone = 0,
+			NSDragOperationCopy = 1,
+			NSDragOperationLink = 2,
+			NSDragOperationGeneric = 4,
+			NSDragOperationPrivate = 8,
+			NSDragOperationMove = 16,
+			NSDragOperationDelete = 32,
+			NSDragOperationEvery = ULONG_MAX,
+
+			//NSDragOperationAll_Obsolete	API_DEPRECATED("", macos(10.0,10.10)) = 15, // Use NSDragOperationEvery
+			//NSDragOperationAll API_DEPRECATED("", macos(10.0,10.10)) = NSDragOperationAll_Obsolete, // Use NSDragOperationEvery
+	};
+
+
+	NSUInteger NSArray_count(NSArray* array) {
+		void* func = sel_registerName("count");
+		return ((NSUInteger(*)(id, SEL))objc_msgSend)(array, func);
+	}
+
+	void* NSArray_objectAtIndex(NSArray* array, NSUInteger index) {
+		void* func = sel_registerName("objectAtIndex:");
+		return ((id(*)(id, SEL, NSUInteger))objc_msgSend)(array, func, index);
+	}
+
+	const char** NSPasteboard_readObjectsForClasses(NSPasteboard* pasteboard, Class* classArray, size_t len, void* options) {
+		void* func = sel_registerName("readObjectsForClasses:options:");
+
+		NSArray* array = c_array_to_NSArray(classArray, len);
+
+		NSArray* output = (NSArray*) ((id(*)(id, SEL, id, void*))objc_msgSend)
+			(pasteboard, func, array, options);
+
+		NSRelease(array);
+
+		NSUInteger count = NSArray_count(output);
+
+		const char** res = si_array_init_reserve(sizeof(const char*), count);
+
+		for (NSUInteger i = 0; i < count; i++)
+			res[i] = NSString_to_char(NSArray_objectAtIndex(output, i));
+
+		return res;
+	}
+
+	void* NSWindow_contentView(NSWindow* window) {
+		void* func = sel_registerName("contentView");
+		return objc_msgSend_id(window, func);
+	}
+#endif
+
+
+#define RGFW_ASSERT(check, str) {\
+	if (!(check)) { \
+		printf(str); \
+		assert(check); \
+	} \
+}
+
+	u8 RGFW_error = 0;
+	u8 RGFW_Error() { return RGFW_error; }
+
+#define SET_ATTRIB(a, v) { \
+    assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
+    attribs[index++] = a; \
+    attribs[index++] = v; \
+}
+
+#define ADD_ATTRIB(a) { \
+    assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
+    attribs[index++] = a; \
+}
+
+#if defined(RGFW_X11) || defined(RGFW_WINDOWS)
+	void RGFW_window_showMouse(RGFW_window* win, i8 show) {
+		static u8 RGFW_blk[] = { 0, 0, 0, 0 };
+		if (show == 0)
+			RGFW_window_setMouse(win, RGFW_blk, RGFW_AREA(1, 1), 4);
+		else
+			RGFW_window_setMouseDefault(win);
+	}
+#endif
+
+	RGFWDEF RGFW_window* RGFW_window_basic_init(RGFW_rect rect, u16 args);
+	RGFWDEF void RGFW_init_buffer(RGFW_window* win);
+
+	RGFW_window* RGFW_window_basic_init(RGFW_rect rect, u16 args) {
+		RGFW_window* win = (RGFW_window*) RGFW_MALLOC(sizeof(RGFW_window)); /* make a new RGFW struct */
+
+#ifdef RGFW_ALLOC_DROPFILES
+		win->event.droppedFiles = (char**) RGFW_MALLOC(sizeof(char*) * RGFW_MAX_DROPS);
+		u32 i;
+		for (i = 0; i < RGFW_MAX_DROPS; i++)
+			win->event.droppedFiles[i] = (char*) RGFW_CALLOC(RGFW_MAX_PATH, sizeof(char));
+#endif
+
+#ifdef RGFW_X11 
+		/* open X11 display */
+		/* this is done here so the screen size can be accessed */
+		win->src.display = XOpenDisplay(NULL);
+		assert(win->src.display != NULL);
+#endif
+
+		#ifndef RGFW_X11 
+		RGFW_area screenR = RGFW_getScreenSize();
+		#else
+		win->src.display = XOpenDisplay(NULL);
+		assert(win->src.display != NULL);
+
+		Screen* scrn = DefaultScreenOfDisplay((Display*)win->src.display);
+		RGFW_area screenR = RGFW_AREA(scrn->width, scrn->height);
+		#endif
+		
+		if (args & RGFW_FULLSCREEN)
+			rect = RGFW_RECT(0, 0, screenR.w, screenR.h);
+
+		if (args & RGFW_CENTER)
+			rect = RGFW_RECT((screenR.w - rect.w) / 2, (screenR.h - rect.h) / 2, rect.w, rect.h);
+
+		/* set and init the new window's data */
+		win->r = rect;
+		win->fpsCap = 0;
+		win->event.inFocus = 1;
+		win->event.droppedFilesCount = 0;
+		win->src.joystickCount = 0;
+#ifdef RGFW_X11
+		win->src.cursor = 0;
+#endif
+#ifdef RGFW_MACOS
+		RGFW_window_setMouseDefault(win);
+#endif
+#ifdef RGFW_WINDOWS
+		win->src.maxSize = RGFW_AREA(0, 0);
+		win->src.minSize = RGFW_AREA(0, 0);
+#endif
+		win->src.winArgs = 0;
+
+		return win;
+	}
+
+	void RGFW_window_scaleToMonitor(RGFW_window* win) {
+		RGFW_monitor monitor = RGFW_window_getMonitor(win);
+
+		RGFW_window_resize(win, RGFW_AREA(((u32) monitor.scaleX) * win->r.w, ((u32) monitor.scaleX) * win->r.h));
+	}
+
+	void RGFW_init_buffer(RGFW_window* win) {
+#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)
+		RGFW_area area = RGFW_getScreenSize();
+#if !(defined(RGFW_WINDOWS)) || defined(RGFW_OSMESA)
+		win->buffer = RGFW_MALLOC(area.w * area.h * 4);
+#endif
+
+#ifdef RGFW_OSMESA
+		win->src.rSurf = OSMesaCreateContext(OSMESA_RGBA, NULL);
+		OSMesaMakeCurrent(win->src.rSurf, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h);
+#endif
+#ifdef RGFW_X11
+		win->src.bitmap = XCreateImage(
+			win->src.display, DefaultVisual(win->src.display, XDefaultScreen(win->src.display)),
+			DefaultDepth(win->src.display, XDefaultScreen(win->src.display)),
+			ZPixmap, 0, NULL, area.w, area.h,
+			32, 0
+		);
+#endif
+#ifdef RGFW_WINDOWS
+		BITMAPV5HEADER bi = { 0 };
+		ZeroMemory(&bi, sizeof(bi));
+		bi.bV5Size = sizeof(bi);
+		bi.bV5Width = area.w;
+		bi.bV5Height = -((LONG) area.h);
+		bi.bV5Planes = 1;
+		bi.bV5BitCount = 32;
+		bi.bV5Compression = BI_BITFIELDS;
+		bi.bV5BlueMask = 0x00ff0000;
+		bi.bV5GreenMask = 0x0000ff00;
+		bi.bV5RedMask = 0x000000ff;
+		bi.bV5AlphaMask = 0xff000000;
+
+		win->src.bitmap = CreateDIBSection(win->src.hdc,
+			(BITMAPINFO*) &bi,
+			DIB_RGB_COLORS,
+			(void**) &win->buffer,
+			NULL,
+			(DWORD) 0);
+
+		win->src.hdcMem = CreateCompatibleDC(win->src.hdc);
+#endif
+#endif
+	}
+
+#if defined(RGFW_OPENGL) || defined(RGFW_EGL) || defined(RGFW_OSMESA)
+#ifndef __APPLE__
+#include <GL/gl.h>
+#else
+#include <OpenGL/gl.h>
+#endif
+#endif
+
+#ifdef RGFW_VULKAN
+	RGFW_vulkanInfo RGFW_vulkan_info;
+
+	RGFW_vulkanInfo* RGFW_initVulkan(RGFW_window* win) {
+		assert(win != NULL);
+
+		if (
+			RGFW_initData(win) ||
+			RGFW_deviceInitialization(win) ||
+			RGFW_createSwapchain(win)
+			)
+			return NULL;
+
+		u32 graphics_family_index = 0;
+		u32 present_family_index = 0;
+
+		vkGetDeviceQueue(RGFW_vulkan_info.device, graphics_family_index, 0, &RGFW_vulkan_info.graphics_queue);
+		vkGetDeviceQueue(RGFW_vulkan_info.device, present_family_index, 0, &RGFW_vulkan_info.present_queue);
+
+		if (
+			RGFW_createRenderPass() ||
+			RGFW_createFramebuffers(win) ||
+			RGFW_createCommandPool() ||
+			RGFW_createCommandBuffers(win) ||
+			RGFW_createSyncObjects(win)
+			)
+			return NULL;
+
+		return &RGFW_vulkan_info;
+	}
+
+	int RGFW_initData(RGFW_window* win) {
+		assert(win != NULL);
+
+		win->src.swapchain = VK_NULL_HANDLE;
+		win->src.image_count = 0;
+		RGFW_vulkan_info.current_frame = 0;
+
+		return 0;
+	}
+
+	void RGFW_createSurface(VkInstance instance, RGFW_window* win) {
+		assert(win != NULL);
+		assert(instance);
+
+		win->src.rSurf = VK_NULL_HANDLE;
+
+#ifdef RGFW_X11
+		VkXlibSurfaceCreateInfoKHR x11 = { VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, 0, 0, (Display*) win->src.display, (Window) win->src.window };
+
+		vkCreateXlibSurfaceKHR(RGFW_vulkan_info.instance, &x11, NULL, &win->src.rSurf);
+#endif
+#ifdef RGFW_WINDOWS
+		VkWin32SurfaceCreateInfoKHR win32 = { VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR, 0, 0, GetModuleHandle(NULL), win->src.window };
+
+		vkCreateWin32SurfaceKHR(RGFW_vulkan_info.instance, &win32, NULL, &win->src.rSurf);
+#endif
+#if defined(RGFW_MACOS) && !defined(RGFW_MACOS_X11)
+		VkMacOSSurfaceCreateFlagsMVK macos = { VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK, 0, 0, win->src.display, win->src.window };
+
+		vkCreateMacOSSurfaceMVK(RGFW_vulkan_info.instance, &macos, NULL, &win->src.rSurf);
+#endif
+	}
+
+	RGFW_vulkanInfo* RGFW_getVulkanInfo(void) {
+		return &RGFW_vulkan_info;
+	}
+
+	int RGFW_deviceInitialization(RGFW_window* win) {
+		assert(win != NULL);
+
+		VkApplicationInfo appInfo = { 0 };
+		appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
+		appInfo.pApplicationName = "RGFW app";
+		appInfo.apiVersion = VK_MAKE_VERSION(1, 0, 0);
+
+		char* extension =
+#ifdef RGFW_WINDOWS
+			"VK_KHR_win32_surface";
+#elif defined(RGFW_X11)
+			VK_KHR_XLIB_SURFACE_EXTENSION_NAME;
+#elif defined(RGFW_MACOS)
+			"VK_MVK_macos_surface";
+#else
+			NULL;
+#endif
+
+		VkInstanceCreateInfo instance_create_info = { 0 };
+		instance_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
+		instance_create_info.pApplicationInfo = &appInfo;
+		instance_create_info.enabledExtensionCount = extension ? 2 : 0,
+			instance_create_info.ppEnabledExtensionNames = (const char* [2]){
+					VK_KHR_SURFACE_EXTENSION_NAME,
+					extension
+		};
+
+		if (vkCreateInstance(&instance_create_info, NULL, &RGFW_vulkan_info.instance) != VK_SUCCESS) {
+			fprintf(stderr, "failed to create instance!\n");
+			return -1;
+		}
+
+
+		RGFW_createSurface(RGFW_vulkan_info.instance, win);
+
+		u32 deviceCount = 0;
+		vkEnumeratePhysicalDevices(RGFW_vulkan_info.instance, &deviceCount, NULL);
+		VkPhysicalDevice* devices = (VkPhysicalDevice*) malloc(sizeof(VkPhysicalDevice) * deviceCount);
+		vkEnumeratePhysicalDevices(RGFW_vulkan_info.instance, &deviceCount, devices);
+
+		RGFW_vulkan_info.physical_device = devices[0];
+
+		u32 queue_family_count = 0;
+		vkGetPhysicalDeviceQueueFamilyProperties(RGFW_vulkan_info.physical_device, &queue_family_count, NULL);
+		VkQueueFamilyProperties* queueFamilies = (VkQueueFamilyProperties*) malloc(sizeof(VkQueueFamilyProperties) * queue_family_count);
+		vkGetPhysicalDeviceQueueFamilyProperties(RGFW_vulkan_info.physical_device, &queue_family_count, queueFamilies);
+
+		float queuePriority = 1.0f;
+
+		VkPhysicalDeviceFeatures device_features = { 0 };
+
+		VkDeviceCreateInfo device_create_info = { 0 };
+		device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
+		VkDeviceQueueCreateInfo queue_create_infos[2] = {
+			{0},
+			{0},
+		};
+		queue_create_infos[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
+		queue_create_infos[0].queueCount = 1;
+		queue_create_infos[0].pQueuePriorities = &queuePriority;
+		queue_create_infos[1].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
+		queue_create_infos[1].queueCount = 1;
+		queue_create_infos[1].pQueuePriorities = &queuePriority;
+		device_create_info.queueCreateInfoCount = 2;
+		device_create_info.pQueueCreateInfos = queue_create_infos;
+
+		device_create_info.enabledExtensionCount = 1;
+
+		const char* device_extensions[] = {
+			VK_KHR_SWAPCHAIN_EXTENSION_NAME
+		};
+
+		device_create_info.ppEnabledExtensionNames = device_extensions;
+		device_create_info.pEnabledFeatures = &device_features;
+
+		if (vkCreateDevice(RGFW_vulkan_info.physical_device, &device_create_info, NULL, &RGFW_vulkan_info.device) != VK_SUCCESS) {
+			fprintf(stderr, "failed to create logical device!\n");
+			return -1;
+		}
+
+		return 0;
+	}
+
+	int RGFW_createSwapchain(RGFW_window* win) {
+		assert(win != NULL);
+
+		VkSurfaceFormatKHR surfaceFormat = { VK_FORMAT_B8G8R8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
+		VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR;
+
+		VkSurfaceCapabilitiesKHR capabilities = { 0 };
+		vkGetPhysicalDeviceSurfaceCapabilitiesKHR(RGFW_vulkan_info.physical_device, win->src.rSurf, &capabilities);
+
+		win->src.image_count = capabilities.minImageCount + 1;
+		if (capabilities.maxImageCount > 0 && win->src.image_count > capabilities.maxImageCount) {
+			win->src.image_count = capabilities.maxImageCount;
+		}
+
+		VkSwapchainCreateInfoKHR swapchain_create_info = { 0 };
+		swapchain_create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
+		swapchain_create_info.surface = win->src.rSurf;
+		swapchain_create_info.minImageCount = win->src.image_count;
+		swapchain_create_info.imageFormat = surfaceFormat.format;
+		swapchain_create_info.imageColorSpace = surfaceFormat.colorSpace;
+		swapchain_create_info.imageExtent = (VkExtent2D){ win->r.w, win->r.h };
+		swapchain_create_info.imageArrayLayers = 1;
+		swapchain_create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+		swapchain_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
+		swapchain_create_info.queueFamilyIndexCount = 2;
+		swapchain_create_info.preTransform = capabilities.currentTransform;
+		swapchain_create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
+		swapchain_create_info.presentMode = presentMode;
+		swapchain_create_info.clipped = VK_TRUE;
+		swapchain_create_info.oldSwapchain = VK_NULL_HANDLE;
+
+		if (vkCreateSwapchainKHR(RGFW_vulkan_info.device, &swapchain_create_info, NULL, &win->src.swapchain) != VK_SUCCESS) {
+			fprintf(stderr, "failed to create swap chain!\n");
+			return -1;
+		}
+
+		u32 imageCount;
+		vkGetSwapchainImagesKHR(RGFW_vulkan_info.device, win->src.swapchain, &imageCount, NULL);
+		win->src.swapchain_images = (VkImage*) malloc(sizeof(VkImage) * imageCount);
+		vkGetSwapchainImagesKHR(RGFW_vulkan_info.device, win->src.swapchain, &imageCount, win->src.swapchain_images);
+
+		win->src.swapchain_image_views = (VkImageView*) malloc(sizeof(VkImageView) * imageCount);
+		for (u32 i = 0; i < imageCount; i++) {
+			VkImageViewCreateInfo image_view_cre_infos = { 0 };
+			image_view_cre_infos.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+			image_view_cre_infos.image = win->src.swapchain_images[i];
+			image_view_cre_infos.viewType = VK_IMAGE_VIEW_TYPE_2D;
+			image_view_cre_infos.format = VK_FORMAT_B8G8R8A8_SRGB;
+			image_view_cre_infos.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
+			image_view_cre_infos.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
+			image_view_cre_infos.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
+			image_view_cre_infos.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
+			image_view_cre_infos.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+			image_view_cre_infos.subresourceRange.baseMipLevel = 0;
+			image_view_cre_infos.subresourceRange.levelCount = 1;
+			image_view_cre_infos.subresourceRange.baseArrayLayer = 0;
+			image_view_cre_infos.subresourceRange.layerCount = 1;
+			if (vkCreateImageView(RGFW_vulkan_info.device, &image_view_cre_infos, NULL, &win->src.swapchain_image_views[i]) != VK_SUCCESS) {
+				fprintf(stderr, "failed to create image views!");
+				return -1;
+			}
+		}
+
+		return 0;
+	}
+
+	int RGFW_createRenderPass(void) {
+		VkAttachmentDescription color_attachment = { 0 };
+		color_attachment.format = VK_FORMAT_B8G8R8A8_SRGB;
+		color_attachment.samples = VK_SAMPLE_COUNT_1_BIT;
+		color_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+		color_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+		color_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+		color_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+		color_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+		color_attachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
+
+		VkAttachmentReference color_attachment_ref = { 0 };
+		color_attachment_ref.attachment = 0;
+		color_attachment_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+		VkSubpassDescription subpass = { 0 };
+		subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
+		subpass.colorAttachmentCount = 1;
+		subpass.pColorAttachments = &color_attachment_ref;
+
+		VkSubpassDependency dependency = { 0 };
+		dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
+		dependency.dstSubpass = 0;
+		dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+		dependency.srcAccessMask = 0;
+		dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+		dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+
+		VkRenderPassCreateInfo render_pass_info = { 0 };
+		render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
+		render_pass_info.attachmentCount = 1;
+		render_pass_info.pAttachments = &color_attachment;
+		render_pass_info.subpassCount = 1;
+		render_pass_info.pSubpasses = &subpass;
+		render_pass_info.dependencyCount = 1;
+		render_pass_info.pDependencies = &dependency;
+
+		if (vkCreateRenderPass(RGFW_vulkan_info.device, &render_pass_info, NULL, &RGFW_vulkan_info.render_pass) != VK_SUCCESS) {
+			fprintf(stderr, "failed to create render pass\n");
+			return -1; // failed to create render pass!
+		}
+		return 0;
+	}
+
+	int RGFW_createCommandPool(void) {
+		VkCommandPoolCreateInfo pool_info = { 0 };
+		pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
+		pool_info.queueFamilyIndex = 0;
+
+		if (vkCreateCommandPool(RGFW_vulkan_info.device, &pool_info, NULL, &RGFW_vulkan_info.command_pool) != VK_SUCCESS) {
+			fprintf(stderr, "failed to create command pool\n");
+			return -1; // failed to create command pool
+		}
+		return 0;
+	}
+
+	int RGFW_createCommandBuffers(RGFW_window* win) {
+		assert(win != NULL);
+
+		RGFW_vulkan_info.command_buffers = (VkCommandBuffer*) malloc(sizeof(VkCommandBuffer) * win->src.image_count);
+
+		VkCommandBufferAllocateInfo allocInfo = { 0 };
+		allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
+		allocInfo.commandPool = RGFW_vulkan_info.command_pool;
+		allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+		allocInfo.commandBufferCount = (u32) win->src.image_count;
+
+		if (vkAllocateCommandBuffers(RGFW_vulkan_info.device, &allocInfo, RGFW_vulkan_info.command_buffers) != VK_SUCCESS) {
+			return -1; // failed to allocate command buffers;
+		}
+
+		return 0;
+	}
+
+	int RGFW_createSyncObjects(RGFW_window* win) {
+		assert(win != NULL);
+
+		RGFW_vulkan_info.available_semaphores = (VkSemaphore*) malloc(sizeof(VkSemaphore) * RGFW_MAX_FRAMES_IN_FLIGHT);
+		RGFW_vulkan_info.finished_semaphore = (VkSemaphore*) malloc(sizeof(VkSemaphore) * RGFW_MAX_FRAMES_IN_FLIGHT);
+		RGFW_vulkan_info.in_flight_fences = (VkFence*) malloc(sizeof(VkFence) * RGFW_MAX_FRAMES_IN_FLIGHT);
+		RGFW_vulkan_info.image_in_flight = (VkFence*) malloc(sizeof(VkFence) * win->src.image_count);
+
+		VkSemaphoreCreateInfo semaphore_info = { 0 };
+		semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
+
+		VkFenceCreateInfo fence_info = { 0 };
+		fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
+		fence_info.flags = VK_FENCE_CREATE_SIGNALED_BIT;
+
+		for (size_t i = 0; i < RGFW_MAX_FRAMES_IN_FLIGHT; i++) {
+			if (vkCreateSemaphore(RGFW_vulkan_info.device, &semaphore_info, NULL, &RGFW_vulkan_info.available_semaphores[i]) != VK_SUCCESS ||
+				vkCreateSemaphore(RGFW_vulkan_info.device, &semaphore_info, NULL, &RGFW_vulkan_info.finished_semaphore[i]) != VK_SUCCESS ||
+				vkCreateFence(RGFW_vulkan_info.device, &fence_info, NULL, &RGFW_vulkan_info.in_flight_fences[i]) != VK_SUCCESS) {
+				fprintf(stderr, "failed to create sync objects\n");
+				return -1; // failed to create synchronization objects for a frame
+			}
+		}
+
+		for (size_t i = 0; i < win->src.image_count; i++) {
+			RGFW_vulkan_info.image_in_flight[i] = VK_NULL_HANDLE;
+		}
+
+		return 0;
+	}
+
+	int RGFW_createFramebuffers(RGFW_window* win) {
+		assert(win != NULL);
+
+		RGFW_vulkan_info.framebuffers = (VkFramebuffer*) malloc(sizeof(VkFramebuffer) * win->src.image_count);
+
+		for (size_t i = 0; i < win->src.image_count; i++) {
+			VkImageView attachments[] = { win->src.swapchain_image_views[i] };
+
+			VkFramebufferCreateInfo framebuffer_info = { 0 };
+			framebuffer_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
+			framebuffer_info.renderPass = RGFW_vulkan_info.render_pass;
+			framebuffer_info.attachmentCount = 1;
+			framebuffer_info.pAttachments = attachments;
+			framebuffer_info.width = win->r.w;
+			framebuffer_info.height = win->r.h;
+			framebuffer_info.layers = 1;
+
+			if (vkCreateFramebuffer(RGFW_vulkan_info.device, &framebuffer_info, NULL, &RGFW_vulkan_info.framebuffers[i]) != VK_SUCCESS) {
+				return -1; // failed to create framebuffer
+			}
+		}
+		return 0;
+	}
+
+	void RGFW_freeVulkan(void) {
+		vkDeviceWaitIdle(RGFW_vulkan_info.device);
+
+		for (size_t i = 0; i < RGFW_MAX_FRAMES_IN_FLIGHT; i++) {
+			vkDestroySemaphore(RGFW_vulkan_info.device, RGFW_vulkan_info.finished_semaphore[i], NULL);
+			vkDestroySemaphore(RGFW_vulkan_info.device, RGFW_vulkan_info.available_semaphores[i], NULL);
+			vkDestroyFence(RGFW_vulkan_info.device, RGFW_vulkan_info.in_flight_fences[i], NULL);
+		}
+
+		vkDestroyCommandPool(RGFW_vulkan_info.device, RGFW_vulkan_info.command_pool, NULL);
+
+		vkDestroyPipeline(RGFW_vulkan_info.device, RGFW_vulkan_info.graphics_pipeline, NULL);
+		vkDestroyPipelineLayout(RGFW_vulkan_info.device, RGFW_vulkan_info.pipeline_layout, NULL);
+		vkDestroyRenderPass(RGFW_vulkan_info.device, RGFW_vulkan_info.render_pass, NULL);
+
+#ifdef RGFW_DEBUG
+		PFN_vkDestroyDebugUtilsMessengerEXT func = (PFN_vkDestroyDebugUtilsMessengerEXT) vkGetInstanceProcAddr(RGFW_vulkan_info.instance, "vkDestroyDebugUtilsMessengerEXT");
+		if (func != NULL) {
+			func(RGFW_vulkan_info.instance, RGFW_vulkan_info.debugMessenger, NULL);
+		}
+#endif
+
+		vkDestroyDevice(RGFW_vulkan_info.device, NULL);
+		vkDestroyInstance(RGFW_vulkan_info.instance, NULL);
+
+		free(RGFW_vulkan_info.framebuffers);
+		free(RGFW_vulkan_info.command_buffers);
+		free(RGFW_vulkan_info.available_semaphores);
+		free(RGFW_vulkan_info.finished_semaphore);
+		free(RGFW_vulkan_info.in_flight_fences);
+		free(RGFW_vulkan_info.image_in_flight);
+	}
+
+#endif /* RGFW_VULKAN */
+
+	RGFW_window* RGFW_root = NULL;
+
+#ifdef RGFW_X11
+#include <X11/Xlib.h>
+#ifndef RGFW_NO_X11_CURSOR
+#include <X11/Xcursor/Xcursor.h>
+#endif
+#include <dlfcn.h>
+
+#ifndef RGFW_NO_DPI
+#include <X11/extensions/Xrandr.h>
+#include <X11/Xresource.h>
+#endif
+#endif
+
+#define RGFW_MOUSE_CHANGED		(1L<<1) /*!< mouse change (for winargs)*/
+#define RGFW_HOLD_MOUSE			(1L<<2) /*!< hold the moues still */
+
+#ifdef RGFW_WINDOWS
+#include <processthreadsapi.h>
+#include <wchar.h>
+#include <locale.h>
+#include <windowsx.h>
+#include <shellapi.h>
+#include <shellscalingapi.h>
+#endif
+
+#if defined(RGFW_MACOS)
+	u8 RGFW_keyMap[128] = { 0 };
+#endif
+
+	char* RGFW_keyCodeTokeyStr(u64 key) {
+#if defined(RGFW_MACOS)
+		static char* keyStrs[128] = { "a", "s", "d", "f", "h", "g", "z", "x", "c", "v", "0", "b", "q", "w", "e", "r", "y", "t", "1", "2", "3", "4", "6", "5", "Equals", "9", "7", "Minus", "8", "0", "CloseBracket", "o", "u", "Bracket", "i", "p", "Return", "l", "j", "Apostrophe", "k", "Semicolon", "BackSlash", "Comma", "Slash", "n", "m", "Period", "Tab", "Space", "Backtick", "BackSpace", "0", "Escape", "0", "Super", "Shift", "CapsLock", "Alt", "Control", "0", "0", "0", "0", "0", "KP_Period", "0", "KP_Minus", "0", "0", "0", "0", "Numlock", "0", "0", "0", "KP_Multiply", "KP_Return", "0", "0", "0", "0", "KP_Slash", "KP_0", "KP_1", "KP_2", "KP_3", "KP_4", "KP_5", "KP_6", "KP_7", "0", "KP_8", "KP_9", "0", "0", "0", "F5", "F6", "F7", "F3", "F8", "F9", "0", "F11", "0", "F13", "0", "F14", "0", "F10", "0", "F12", "0", "F15", "Insert", "Home", "PageUp", "Delete", "F4", "End", "F2", "PageDown", "Left", "Right", "Down", "Up", "F1" };
+
+		return keyStrs[key];
+#endif
+#ifdef RGFW_X11
+		return XKeysymToString(key);
+#endif
+#ifdef RGFW_WINDOWS
+		static char keyName[16];
+		GetKeyNameTextA((LONG) key, keyName, 16);
+
+		if ((!(GetKeyState(VK_CAPITAL) & 0x0001) && !(GetKeyState(VK_SHIFT) & 0x8000)) ||
+			((GetKeyState(VK_CAPITAL) & 0x0001) && (GetKeyState(VK_SHIFT) & 0x8000))) {
+			CharLowerBuffA(keyName, 16);
+		}
+
+		return keyName;
+#endif
+	}
+
+	u32 RGFW_keyStrToKeyCode(char* key) {
+#if defined(RGFW_MACOS)
+		static char* keyStrs[128] = { "a", "s", "d", "f", "h", "g", "z", "x", "c", "v", "0", "b", "q", "w", "e", "r", "y", "t", "1", "2", "3", "4", "6", "5", "Equals", "9", "7", "Minus", "8", "0", "CloseBracket", "o", "u", "Bracket", "i", "p", "Return", "l", "j", "Apostrophe", "k", "Semicolon", "BackSlash", "Comma", "Slash", "n", "m", "Period", "Tab", "Space", "Backtick", "BackSpace", "0", "Escape", "0", "Super", "Shift", "CapsLock", "Alt", "Control", "0", "0", "0", "0", "0", "KP_Period", "0", "KP_Minus", "0", "0", "0", "0", "Numlock", "0", "0", "0", "KP_Multiply", "KP_Return", "0", "0", "0", "0", "KP_Slash", "KP_0", "KP_1", "KP_2", "KP_3", "KP_4", "KP_5", "KP_6", "KP_7", "0", "KP_8", "KP_9", "0", "0", "0", "F5", "F6", "F7", "F3", "F8", "F9", "0", "F11", "0", "F13", "0", "F14", "0", "F10", "0", "F12", "0", "F15", "Insert", "Home", "PageUp", "Delete", "F4", "End", "F2", "PageDown", "Left", "Right", "Down", "Up", "F1" };
+
+		key--;
+		while (key++) {
+			u32 i;
+			for (i = 0; i < 128; i++) {
+				if (*keyStrs[i] == '\1')
+					continue;
+
+				if (*keyStrs[i] != *key) {
+					keyStrs[i] = "\1";
+					continue;
+				}
+
+				if (*keyStrs[i] == '\0' && *key == '\0')
+					return i;
+
+				else
+					keyStrs[i]++;
+			}
+
+			if (*key == '\0')
+				break;
+		}
+
+#endif
+#ifdef RGFW_X11
+		if (strcmp(key, "Space") == 0) key = (char*) "space";
+
+		return XStringToKeysym(key);
+#endif
+#ifdef RGFW_WINDOWS
+		if (key[1]) {
+			struct { char* key; i32 code; } keyStrs[] = {
+						{"Super_L", VK_LWIN},
+						{"Super_R", VK_RWIN},
+						{"Space", VK_SPACE},
+						{"Return", VK_RETURN},
+						{"Caps_Lock", VK_CAPITAL},
+						{"Tab", VK_TAB},
+						{"Right", VK_RIGHT},
+						{"Left", VK_LEFT},
+						{"Up", VK_UP},
+						{"Down", VK_DOWN},
+						{"ShiftL", VK_LSHIFT},
+						{"ShiftR", VK_RSHIFT},
+						{"ControlL", VK_RCONTROL},
+						{"ControlR", VK_RCONTROL}
+			};
+
+
+			while (key++) {
+				u32 i;
+				for (i = 0; i < 14; i++) {
+					if (*keyStrs[i].key != '\0' && *keyStrs[i].key != '\1')
+						keyStrs[i].key++;
+
+					if (*keyStrs[i].key != *key) {
+						keyStrs[i].key = "\1";
+						continue;
+					}
+
+					if (*keyStrs[i].key == '\0' && *key == '\0')
+						return keyStrs[i].code;
+				}
+
+				if (*key == '\0')
+					break;
+			}
+		}
+
+		i32 vKey = VkKeyScan(key[0]);
+
+		return vKey;
+#endif /* RGFW_WINDOWS */
+
+		return 0;
+	}
+
+
+	char RGFW_keystrToChar(const char* str) {
+		if (str[1] == 0)
+			return str[0];
+
+		static const char* map[] = {
+			"asciitilde", "`",
+			"grave", "~",
+			"exclam", "!",
+			"at", "@",
+			"numbersign", "#",
+			"dollar", "$",
+			"percent", "%%",
+			"asciicircum", "^",
+			"ampersand", "&",
+			"asterisk", "*",
+			"parenleft", "(",
+			"parenright", ")",
+			"underscore", "_",
+			"minus", "-",
+			"plus", "+",
+			"equal", "=",
+			"braceleft", "{",
+			"bracketleft", "[",
+			"bracketright", "]",
+			"braceright", "}",
+			"colon", ":",
+			"semicolon", ";",
+			"quotedbl", "\"",
+			"apostrophe", "'",
+			"bar", "|",
+			"backslash", "\'",
+			"less", "<",
+			"comma", ",",
+			"greater", ">",
+			"period", ".",
+			"question", "?",
+			"slash", "/",
+			"space", " ",
+			"Return", "\n",
+			"Enter", "\n",
+			"enter", "\n",
+		};
+
+		u8 i = 0;
+		for (i = 0; i < (sizeof(map) / sizeof(char*)); i += 2)
+			if (strcmp(map[i], str) == 0)
+				return *map[i + 1];
+
+		return '\0';
+	}
+
+#ifndef M_PI
+#define M_PI		3.14159265358979323846	/* pi */
+#endif
+
+	typedef struct RGFW_Timespec {
+		time_t tv_sec;		/* Seconds.  */
+		u32 tv_nsec;	/* Nanoseconds.  */
+	} RGFW_Timespec; /*time struct for fps functions*/
+
+#ifndef RGFW_WINDOWS
+	u32 RGFW_isPressedJS(RGFW_window* win, u16 c, u8 button) { return win->src.jsPressed[c][button]; }
+#else
+
+	typedef DWORD (WINAPI * PFN_XInputGetState)(DWORD,XINPUT_STATE*);
+	PFN_XInputGetState XInputGetStateSRC = NULL;
+	#define XInputGetState XInputGetStateSRC
+	static HMODULE RGFW_XInput_dll = NULL;
+	
+	u32 RGFW_isPressedJS(RGFW_window* win, u16 c, u8 button) {
+		XINPUT_STATE state;
+		if (XInputGetState == NULL || XInputGetState(c, &state) == ERROR_DEVICE_NOT_CONNECTED)
+			return 0;
+
+		if (button == RGFW_JS_A) return state.Gamepad.wButtons & XINPUT_GAMEPAD_A;
+		else if (button == RGFW_JS_B) return state.Gamepad.wButtons & XINPUT_GAMEPAD_B;
+		else if (button == RGFW_JS_Y) return state.Gamepad.wButtons & XINPUT_GAMEPAD_Y;
+		else if (button == RGFW_JS_X) return state.Gamepad.wButtons & XINPUT_GAMEPAD_X;
+		else if (button == RGFW_JS_START) return state.Gamepad.wButtons & XINPUT_GAMEPAD_START;
+		else if (button == RGFW_JS_SELECT) return state.Gamepad.wButtons & XINPUT_GAMEPAD_BACK;
+		else if (button == RGFW_JS_UP) return state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP;
+		else if (button == RGFW_JS_DOWN) return state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN;
+		else if (button == RGFW_JS_LEFT) return state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT;
+		else if (button == RGFW_JS_RIGHT) return state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT;
+		else if (button == RGFW_JS_L1) return state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER;
+		else if (button == RGFW_JS_R1) return state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER;
+		else if (button == RGFW_JS_L2 && state.Gamepad.bLeftTrigger) return 1;
+		else if (button == RGFW_JS_R2 && state.Gamepad.bRightTrigger) return 1;
+
+		return 0;
+	}
+#endif
+
+#ifdef RGFW_OPENGL
+	i32 RGFW_majorVersion = 0, RGFW_minorVersion = 0;
+	i32 RGFW_STENCIL = 8, RGFW_SAMPLES = 4, RGFW_STEREO = GL_FALSE, RGFW_AUX_BUFFERS = 0;
+
+	void RGFW_setGLStencil(i32 stencil) { RGFW_STENCIL = stencil; }
+	void RGFW_setGLSamples(i32 samples) { RGFW_SAMPLES = samples; }
+	void RGFW_setGLStereo(i32 stereo) { RGFW_STEREO = stereo; }
+	void RGFW_setGLAuxBuffers(i32 auxBuffers) { RGFW_AUX_BUFFERS = auxBuffers; }
+
+	void RGFW_setGLVersion(i32 major, i32 minor) {
+		RGFW_majorVersion = major;
+		RGFW_minorVersion = minor;
+	}
+
+	u8* RGFW_getMaxGLVersion() {
+		RGFW_window* dummy = RGFW_createWindow("dummy", RGFW_RECT(0, 0, 1, 1), 0);
+
+		const char* versionStr = (const char*) glGetString(GL_VERSION);
+
+		static u8 version[2];
+		version[0] = versionStr[0] - '0',
+			version[1] = versionStr[2] - '0';
+
+		RGFW_window_close(dummy);
+
+		return version;
+	}
+
+#define RGFW_GL_RENDER_TYPE 		RGFW_OS_BASED_VALUE(GLX_X_VISUAL_TYPE,    	0x2003,		73)
+#define RGFW_GL_ALPHA_SIZE 		RGFW_OS_BASED_VALUE(GLX_ALPHA_SIZE,       	0x201b,		11)
+#define RGFW_GL_DEPTH_SIZE 		RGFW_OS_BASED_VALUE(GLX_DEPTH_SIZE,       	0x2022,		12)
+#define RGFW_GL_DOUBLEBUFFER 		RGFW_OS_BASED_VALUE(GLX_DOUBLEBUFFER,     	0x2011, 	5)   
+#define RGFW_GL_STENCIL_SIZE 		RGFW_OS_BASED_VALUE(GLX_STENCIL_SIZE,	 	0x2023,	13)
+#define RGFW_GL_SAMPLES			RGFW_OS_BASED_VALUE(GLX_SAMPLES, 		 	0x2042,	    55)
+#define RGFW_GL_STEREO 			RGFW_OS_BASED_VALUE(GLX_STEREO,	 		 	0x2012,			6)
+#define RGFW_GL_AUX_BUFFERS		RGFW_OS_BASED_VALUE(GLX_AUX_BUFFERS,	    0x2024,	7)
+
+#if defined(RGFW_X11) || defined(RGFW_WINDOWS)
+#define RGFW_GL_DRAW 			RGFW_OS_BASED_VALUE(GLX_X_RENDERABLE,	 	0x2001,					0)
+#define RGFW_GL_DRAW_TYPE 		RGFW_OS_BASED_VALUE(GLX_RENDER_TYPE,     	0x2013,						0)
+#define RGFW_GL_USE_OPENGL		RGFW_OS_BASED_VALUE(GLX_USE_GL,				0x2010,						0)
+#define RGFW_GL_FULL_FORMAT		RGFW_OS_BASED_VALUE(GLX_TRUE_COLOR,   	 	0x2027,						0)
+#define RGFW_GL_RED_SIZE		RGFW_OS_BASED_VALUE(GLX_RED_SIZE,         	0x2015,						0)
+#define RGFW_GL_GREEN_SIZE		RGFW_OS_BASED_VALUE(GLX_GREEN_SIZE,       	0x2017,						0)
+#define RGFW_GL_BLUE_SIZE		RGFW_OS_BASED_VALUE(GLX_BLUE_SIZE, 	 		0x2019,						0)
+#define RGFW_GL_USE_RGBA		RGFW_OS_BASED_VALUE(GLX_RGBA_BIT,   	 	0x202B,						0)
+#endif
+
+#ifdef RGFW_WINDOWS
+#define WGL_COLOR_BITS_ARB                        0x2014
+#define WGL_NUMBER_PIXEL_FORMATS_ARB 			0x2000
+#define WGL_CONTEXT_MAJOR_VERSION_ARB             0x2091
+#define WGL_CONTEXT_MINOR_VERSION_ARB             0x2092
+#define WGL_CONTEXT_PROFILE_MASK_ARB              0x9126
+#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
+#define WGL_SAMPLE_BUFFERS_ARB               0x2041
+#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20a9
+#endif
+
+	static u32* RGFW_initAttribs(u32 useSoftware) {
+		static u32 attribs[] = {
+								#ifndef RGFW_MACOS
+								RGFW_GL_RENDER_TYPE,
+								RGFW_GL_FULL_FORMAT,
+								#endif
+								RGFW_GL_ALPHA_SIZE      , 8,
+								RGFW_GL_DEPTH_SIZE      , 24,
+								RGFW_GL_DOUBLEBUFFER    ,
+								#ifndef RGFW_MACOS
+								1,
+								#endif
+
+								#if defined(RGFW_X11) || defined(RGFW_WINDOWS)
+								RGFW_GL_USE_OPENGL,		1,
+								RGFW_GL_DRAW, 1,
+								RGFW_GL_RED_SIZE        , 8,
+								RGFW_GL_GREEN_SIZE      , 8,
+								RGFW_GL_BLUE_SIZE       , 8,
+								RGFW_GL_DRAW_TYPE     , RGFW_GL_USE_RGBA,
+								#endif 
+
+								#ifdef RGFW_X11
+								GLX_DRAWABLE_TYPE   , GLX_WINDOW_BIT,
+								#endif
+
+								#ifdef RGFW_MACOS
+								72,
+								8, 24,
+								#endif
+
+								#ifdef RGFW_WINDOWS
+								WGL_COLOR_BITS_ARB,	 32,
+								#endif
+
+								0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+		};
+
+		size_t index = (sizeof(attribs) / sizeof(attribs[0])) - 13;
+
+#define RGFW_GL_ADD_ATTRIB(attrib, attVal) \
+		if (attVal) { \
+			attribs[index] = attrib;\
+			attribs[index + 1] = attVal;\
+			index += 2;\
+		}
+
+		RGFW_GL_ADD_ATTRIB(RGFW_GL_STENCIL_SIZE, RGFW_STENCIL);
+		RGFW_GL_ADD_ATTRIB(RGFW_GL_STEREO, RGFW_STEREO);
+		RGFW_GL_ADD_ATTRIB(RGFW_GL_AUX_BUFFERS, RGFW_AUX_BUFFERS);
+
+#ifndef RGFW_X11
+		RGFW_GL_ADD_ATTRIB(RGFW_GL_SAMPLES, RGFW_SAMPLES);
+#endif 
+
+#ifdef RGFW_MACOS
+		if (useSoftware) {
+			RGFW_GL_ADD_ATTRIB(70, kCGLRendererGenericFloatID);
+		} else {
+			attribs[index] = RGFW_GL_RENDER_TYPE;
+			index += 1;
+		}
+#endif
+
+#ifdef RGFW_MACOS
+		attribs[index] = 99;
+		attribs[index + 1] = 0x1000;
+
+		if (RGFW_majorVersion >= 4 || RGFW_majorVersion >= 3) {
+			attribs[index + 1] = (u32) ((RGFW_majorVersion >= 4) ? 0x4100 : 0x3200);
+		}
+
+#endif
+
+		RGFW_GL_ADD_ATTRIB(0, 0);
+
+		return attribs;
+	}
+
+#endif
+
+#ifdef RGFW_EGL
+
+#if defined(RGFW_LINK_EGL)
+	typedef EGLBoolean(EGLAPIENTRY* PFN_eglInitialize)(EGLDisplay, EGLint*, EGLint*);
+
+	PFNEGLINITIALIZEPROC eglInitializeSource;
+	PFNEGLGETCONFIGSPROC eglGetConfigsSource;
+	PFNEGLCHOOSECONFIGPROC eglChooseConfigSource;
+	PFNEGLCREATEWINDOWSURFACEPROC eglCreateWindowSurfaceSource;
+	PFNEGLCREATECONTEXTPROC eglCreateContextSource;
+	PFNEGLMAKECURRENTPROC eglMakeCurrentSource;
+	PFNEGLGETDISPLAYPROC eglGetDisplaySource;
+	PFNEGLSWAPBUFFERSPROC eglSwapBuffersSource;
+	PFNEGLSWAPINTERVALPROC eglSwapIntervalSource;
+	PFNEGLBINDAPIPROC eglBindAPISource;
+	PFNEGLDESTROYCONTEXTPROC eglDestroyContextSource;
+	PFNEGLTERMINATEPROC eglTerminateSource;
+	PFNEGLDESTROYSURFACEPROC eglDestroySurfaceSource;
+
+#define eglInitialize eglInitializeSource
+#define eglGetConfigs eglGetConfigsSource
+#define eglChooseConfig eglChooseConfigSource
+#define eglCreateWindowSurface eglCreateWindowSurfaceSource
+#define eglCreateContext eglCreateContextSource
+#define eglMakeCurrent eglMakeCurrentSource
+#define eglGetDisplay eglGetDisplaySource
+#define eglSwapBuffers eglSwapBuffersSource
+#define eglSwapInterval eglSwapIntervalSource
+#define eglBindAPI eglBindAPISource
+#define eglDestroyContext eglDestroyContextSource
+#define eglTerminate eglTerminateSource
+#define eglDestroySurface eglDestroySurfaceSource;
+#endif
+
+
+#define EGL_CONTEXT_MAJOR_VERSION_KHR 0x3098
+#define EGL_CONTEXT_MINOR_VERSION_KHR 0x30fb
+
+#ifndef RGFW_GL_ADD_ATTRIB
+#define RGFW_GL_ADD_ATTRIB(attrib, attVal) \
+	if (attVal) { \
+		attribs[index] = attrib;\
+		attribs[index + 1] = attVal;\
+		index += 2;\
+	}
+#endif
+
+	void RGFW_createOpenGLContext(RGFW_window* win) {
+		static EGLContext globalCtx = EGL_NO_CONTEXT;
+
+#if defined(RGFW_LINK_EGL)
+		eglInitializeSource = (PFNEGLINITIALIZEPROC) eglGetProcAddress("eglInitialize");
+		eglGetConfigsSource = (PFNEGLGETCONFIGSPROC) eglGetProcAddress("eglGetConfigs");
+		eglChooseConfigSource = (PFNEGLCHOOSECONFIGPROC) eglGetProcAddress("eglChooseConfig");
+		eglCreateWindowSurfaceSource = (PFNEGLCREATEWINDOWSURFACEPROC) eglGetProcAddress("eglCreateWindowSurface");
+		eglCreateContextSource = (PFNEGLCREATECONTEXTPROC) eglGetProcAddress("eglCreateContext");
+		eglMakeCurrentSource = (PFNEGLMAKECURRENTPROC) eglGetProcAddress("eglMakeCurrent");
+		eglGetDisplaySource = (PFNEGLGETDISPLAYPROC) eglGetProcAddress("eglGetDisplay");
+		eglSwapBuffersSource = (PFNEGLSWAPBUFFERSPROC) eglGetProcAddress("eglSwapBuffers");
+		eglSwapIntervalSource = (PFNEGLSWAPINTERVALPROC) eglGetProcAddress("eglSwapInterval");
+		eglBindAPISource = (PFNEGLBINDAPIPROC) eglGetProcAddress("eglBindAPI");
+		eglDestroyContextSource = (PFNEGLDESTROYCONTEXTPROC) eglGetProcAddress("eglDestroyContext");
+		eglTerminateSource = (PFNEGLTERMINATEPROC) eglGetProcAddress("eglTerminate");
+		eglDestroySurfaceSource = (PFNEGLDESTROYSURFACEPROC) eglGetProcAddress("eglDestroySurface");
+#endif /* RGFW_LINK_EGL */
+
+		win->src.EGL_display = eglGetDisplay((EGLNativeDisplayType) win->src.display);
+
+		EGLint major, minor;
+
+		eglInitialize(win->src.EGL_display, &major, &minor);
+
+		EGLint config_attribs[] = {
+			EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+			EGL_RENDERABLE_TYPE,
+			#ifdef RGFW_OPENGL_ES1
+			EGL_OPENGL_ES1_BIT,
+			#endif
+			#ifdef RGFW_OPENGL_ES2
+			EGL_OPENGL_ES2_BIT,
+			#else
+			EGL_OPENGL_BIT,
+			#endif
+			EGL_NONE
+		};
+
+		EGLConfig config;
+		EGLint num_configs;
+		eglChooseConfig(win->src.EGL_display, config_attribs, &config, 1, &num_configs);
+
+#if defined(RGFW_OPENGL_ES2) || defined(RGFW_OPENGL_ES1)
+		eglBindAPI(EGL_OPENGL_ES_API);
+#else
+		eglBindAPI(EGL_OPENGL_API);
+#endif
+
+		EGLint attribs[]{
+			EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT,
+			0, 0, 0, 0
+		};
+
+		size_t index = 2;
+		RGFW_GL_ADD_ATTRIB(EGL_STENCIL_SIZE, RGFW_STENCIL);
+		RGFW_GL_ADD_ATTRIB(EGL_SAMPLES, RGFW_SAMPLES);
+		RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_MAJOR_VERSION, RGFW_majorVersion);
+		RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_MINOR_VERSION, RGFW_minorVersion);
+
+		win->src.rSurf = eglCreateContext(win->src.EGL_display, config, globalCtx, attribs);
+		win->src.EGL_surface = eglCreateWindowSurface(win->src.EGL_display, config, (EGLNativeWindowType) win->src.window, NULL);
+
+		if (globalCtx == EGL_NO_CONTEXT)
+			RGFW_EGLglobalContext = win->src.rSurf;
+
+		eglMakeCurrent(win->src.EGL_display, win->src.EGL_surface, win->src.EGL_surface, win->src.rSurf);
+		eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface);
+
+		eglSwapInterval(win->src.EGL_display, 1);
+	}
+
+	void* RGFW_getProcAddress(const char* procname) { return (void*) eglGetProcAddress(procname); }
+
+	void RGFW_closeEGL(RGFW_window* win) {
+		eglDestroySurface(win->src.EGL_display, win->src.EGL_surface);
+		eglDestroyContext(win->src.EGL_display, win->src.rSurf);
+
+		eglTerminate(win->src.EGL_display);
+	}
+
+#endif /* RGFW_EGL */
+
+	/*
+	This is where OS specific stuff starts
+	*/
+
+#ifdef RGFW_X11
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <X11/keysymdef.h>
+#include <unistd.h>
+
+#include <X11/XKBlib.h> /* for converting keycode to string */
+#include <X11/cursorfont.h> /* for hiding */
+
+#include <limits.h> /* for data limits (mainly used in drag and drop functions) */
+#include <fcntl.h>
+
+#ifdef __linux__
+#include <linux/joystick.h>
+#endif
+
+	/*atoms needed for drag and drop*/
+	Atom XdndAware, XdndTypeList, XdndSelection, XdndEnter, XdndPosition, XdndStatus, XdndLeave, XdndDrop, XdndFinished, XdndActionCopy, XdndActionMove, XdndActionLink, XdndActionAsk, XdndActionPrivate;
+
+	Atom wm_delete_window = 0;
+
+#if !defined(RGFW_NO_X11_CURSOR) && !defined(RGFW_NO_X11_CURSOR_PRELOAD)
+	typedef XcursorImage* (*PFN_XcursorImageCreate)(int, int);
+	typedef void (*PFN_XcursorImageDestroy)(XcursorImage*);
+	typedef Cursor(*PFN_XcursorImageLoadCursor)(Display*, const XcursorImage*);
+#endif
+#ifdef RGFW_OPENGL
+	typedef GLXContext(*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*);
+#endif
+
+#if !defined(RGFW_NO_X11_CURSOR) && !defined(RGFW_NO_X11_CURSOR_PRELOAD)
+	PFN_XcursorImageLoadCursor XcursorImageLoadCursorSrc = NULL;
+	PFN_XcursorImageCreate XcursorImageCreateSrc = NULL;
+	PFN_XcursorImageDestroy XcursorImageDestroySrc = NULL;
+
+#define XcursorImageLoadCursor XcursorImageLoadCursorSrc
+#define XcursorImageCreate XcursorImageCreateSrc
+#define XcursorImageDestroy XcursorImageDestroySrc
+
+	void* X11Cursorhandle = NULL;
+#endif
+
+	u32 RGFW_windowsOpen = 0;
+
+#ifdef RGFW_OPENGL
+	void* RGFW_getProcAddress(const char* procname) { return (void*) glXGetProcAddress((GLubyte*) procname); }
+#endif
+
+	RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) {
+#if !defined(RGFW_NO_X11_CURSOR) && !defined(RGFW_NO_X11_CURSOR_PRELOAD)
+		if (X11Cursorhandle == NULL) {
+#if defined(__CYGWIN__)
+			X11Cursorhandle = dlopen("libXcursor-1.so", RTLD_LAZY | RTLD_LOCAL);
+#elif defined(__OpenBSD__) || defined(__NetBSD__)
+			X11Cursorhandle = dlopen("libXcursor.so", RTLD_LAZY | RTLD_LOCAL);
+#else
+			X11Cursorhandle = dlopen("libXcursor.so.1", RTLD_LAZY | RTLD_LOCAL);
+#endif
+
+			XcursorImageCreateSrc = (PFN_XcursorImageCreate) dlsym(X11Cursorhandle, "XcursorImageCreate");
+			XcursorImageDestroySrc = (PFN_XcursorImageDestroy) dlsym(X11Cursorhandle, "XcursorImageDestroy");
+			XcursorImageLoadCursorSrc = (PFN_XcursorImageLoadCursor) dlsym(X11Cursorhandle, "XcursorImageLoadCursor");
+		}
+#endif
+
+		XInitThreads(); /* init X11 threading*/
+
+		if (args & RGFW_OPENGL_SOFTWARE)
+			setenv("LIBGL_ALWAYS_SOFTWARE", "1", 1);
+
+		RGFW_window* win = RGFW_window_basic_init(rect, args);
+
+		u64 event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask | FocusChangeMask; /* X11 events accepted*/
+
+#ifdef RGFW_OPENGL
+		u32* visual_attribs = RGFW_initAttribs(args & RGFW_OPENGL_SOFTWARE);
+		i32 fbcount;
+		GLXFBConfig* fbc = glXChooseFBConfig((Display*) win->src.display, DefaultScreen(win->src.display), (i32*) visual_attribs, &fbcount);
+
+		i32 best_fbc = -1;
+
+		if (fbcount == 0) {
+			printf("Failed to find any valid GLX configs\n");
+			return NULL;
+		}
+
+		u32 i;
+		for (i = 0; i < fbcount; i++) {
+			XVisualInfo* vi = glXGetVisualFromFBConfig((Display*) win->src.display, fbc[i]);
+			if (vi == NULL)
+				continue;
+
+			XFree(vi);
+
+			i32 samp_buf, samples;
+			glXGetFBConfigAttrib((Display*) win->src.display, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf);
+			glXGetFBConfigAttrib((Display*) win->src.display, fbc[i], GLX_SAMPLES, &samples);
+			if ((best_fbc < 0 || samp_buf) && (samples == RGFW_SAMPLES))
+				best_fbc = i;
+		}
+
+		if (best_fbc == -1) {
+			printf("Failed to get a valid GLX visual\n");
+			return NULL;
+		}
+
+		GLXFBConfig bestFbc = fbc[best_fbc];
+
+		/* Get a visual */
+		XVisualInfo* vi = glXGetVisualFromFBConfig((Display*) win->src.display, bestFbc);
+
+		XFree(fbc);
+
+		u32 valuemask = CWBorderPixel | CWColormap;
+#else
+		XVisualInfo* vi = (XVisualInfo*) malloc(sizeof(XVisualInfo));
+		vi->screen = DefaultScreen((Display*) win->src.display);
+		vi->visual = DefaultVisual((Display*) win->src.display, vi->screen);
+
+		vi->depth = 0;
+		u32 valuemask = 0;
+#endif
+
+		/* make X window attrubutes*/
+		XSetWindowAttributes swa;
+		Colormap cmap;
+
+		swa.colormap = cmap = XCreateColormap((Display*) win->src.display,
+			RootWindow(win->src.display, vi->screen),
+			vi->visual, AllocNone);
+
+		swa.background_pixmap = None;
+		swa.border_pixel = 0;
+		swa.event_mask = event_mask;
+
+		/* create the window*/
+		win->src.window = XCreateWindow((Display*) win->src.display, RootWindow((Display*) win->src.display, vi->screen), win->r.x, win->r.y, win->r.w, win->r.h,
+			0, vi->depth, InputOutput, vi->visual,
+			valuemask | CWEventMask, &swa);
+
+
+		XFreeColors((Display*) win->src.display, cmap, NULL, 0, 0);
+		if (args & RGFW_TRANSPARENT_WINDOW)
+			XMatchVisualInfo((Display*) win->src.display, DefaultScreen((Display*) win->src.display), 32, TrueColor, vi); /* for RGBA backgrounds*/
+
+		XFree(vi);
+
+#ifdef RGFW_OPENGL
+		i32 context_attribs[7] = { 0, 0, 0, 0, 0, 0, 0 };
+		context_attribs[0] = GLX_CONTEXT_PROFILE_MASK_ARB;
+		context_attribs[1] = GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
+
+		if (RGFW_majorVersion || RGFW_minorVersion) {
+			context_attribs[2] = GLX_CONTEXT_MAJOR_VERSION_ARB;
+			context_attribs[3] = RGFW_majorVersion;
+			context_attribs[4] = GLX_CONTEXT_MINOR_VERSION_ARB;
+			context_attribs[5] = RGFW_minorVersion;
+		}
+
+		glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0;
+		glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)
+			glXGetProcAddressARB((GLubyte*) "glXCreateContextAttribsARB");
+
+		GLXContext ctx = NULL;
+
+		if (RGFW_root != NULL)
+			ctx = RGFW_root->src.rSurf;
+
+		win->src.rSurf = glXCreateContextAttribsARB((Display*) win->src.display, bestFbc, ctx, True, context_attribs);
+#endif
+
+#ifdef RGFW_EGL
+		RGFW_createOpenGLContext(win);
+#endif
+
+		if (RGFW_root == NULL)
+			RGFW_root = win;
+
+		RGFW_init_buffer(win);
+
+#ifdef RGFW_VULKAN
+		RGFW_initVulkan(win);
+#endif
+
+		if (args & RGFW_SCALE_TO_MONITOR)
+			RGFW_window_scaleToMonitor(win);
+
+		if (args & RGFW_NO_RESIZE) { /* make it so the user can't resize the window*/
+			XSizeHints* sh = XAllocSizeHints();
+			sh->flags = (1L << 4) | (1L << 5);
+			sh->min_width = sh->max_width = win->r.w;
+			sh->min_height = sh->max_height = win->r.h;
+
+			XSetWMSizeHints((Display*) win->src.display, (Drawable) win->src.window, sh, XA_WM_NORMAL_HINTS);
+			XFree(sh);
+		}
+
+		if (args & RGFW_NO_BORDER) {
+			/* Atom vars for no-border*/
+			static Atom window_type = 0;
+			static Atom value = 0;
+
+			if (window_type == 0) {
+				window_type = XInternAtom((Display*) win->src.display, "_NET_WM_WINDOW_TYPE", False);
+				value = XInternAtom((Display*) win->src.display, "_NET_WM_WINDOW_TYPE_DOCK", False);
+			}
+
+			XChangeProperty((Display*) win->src.display, (Drawable) win->src.window, window_type, XA_ATOM, 32, PropModeReplace, (u8*) &value, 1); /* toggle border*/
+		}
+
+		XSelectInput((Display*) win->src.display, (Drawable) win->src.window, event_mask); /* tell X11 what events we want*/
+
+		/* make it so the user can't close the window until the program does*/
+		if (wm_delete_window == 0)
+			wm_delete_window = XInternAtom((Display*) win->src.display, "WM_DELETE_WINDOW", 1);
+
+		XSetWMProtocols((Display*) win->src.display, (Drawable) win->src.window, &wm_delete_window, 1);
+
+		/* connect the context to the window*/
+#ifdef RGFW_OPENGL
+		glXMakeCurrent((Display*) win->src.display, (Drawable) win->src.window, (GLXContext) win->src.rSurf);
+#endif
+
+		/* set the background*/
+		XStoreName((Display*) win->src.display, (Drawable) win->src.window, name); /* set the name*/
+
+		XMapWindow((Display*) win->src.display, (Drawable) win->src.window);						  /* draw the window*/
+		XMoveWindow((Display*) win->src.display, (Drawable) win->src.window, win->r.x, win->r.y); /* move the window to it's proper cords*/
+
+		if (args & RGFW_ALLOW_DND) { /* init drag and drop atoms and turn on drag and drop for this window */
+			win->src.winArgs |= RGFW_ALLOW_DND;
+
+			XdndAware = XInternAtom((Display*) win->src.display, "XdndAware", False);
+			XdndTypeList = XInternAtom((Display*) win->src.display, "XdndTypeList", False);
+			XdndSelection = XInternAtom((Display*) win->src.display, "XdndSelection", False);
+
+			/* client messages */
+			XdndEnter = XInternAtom((Display*) win->src.display, "XdndEnter", False);
+			XdndPosition = XInternAtom((Display*) win->src.display, "XdndPosition", False);
+			XdndStatus = XInternAtom((Display*) win->src.display, "XdndStatus", False);
+			XdndLeave = XInternAtom((Display*) win->src.display, "XdndLeave", False);
+			XdndDrop = XInternAtom((Display*) win->src.display, "XdndDrop", False);
+			XdndFinished = XInternAtom((Display*) win->src.display, "XdndFinished", False);
+
+			/* actions */
+			XdndActionCopy = XInternAtom((Display*) win->src.display, "XdndActionCopy", False);
+			XdndActionMove = XInternAtom((Display*) win->src.display, "XdndActionMove", False);
+			XdndActionLink = XInternAtom((Display*) win->src.display, "XdndActionLink", False);
+			XdndActionAsk = XInternAtom((Display*) win->src.display, "XdndActionAsk", False);
+			XdndActionPrivate = XInternAtom((Display*) win->src.display, "XdndActionPrivate", False);
+			const Atom version = 5;
+
+			XChangeProperty((Display*) win->src.display, (Window) win->src.window,
+				XdndAware, 4, 32,
+				PropModeReplace, (u8*) &version, 1); /* turns on drag and drop */
+		}
+
+		RGFW_window_setMouseDefault(win);
+
+		RGFW_windowsOpen++;
+
+		return win; /*return newly created window*/
+	}
+
+	RGFW_area RGFW_getScreenSize(void) {
+		assert(RGFW_root != NULL);
+
+		Screen* scrn = DefaultScreenOfDisplay((Display*) RGFW_root->src.display);
+		return RGFW_AREA(scrn->width, scrn->height);
+	}
+
+	RGFW_vector RGFW_getGlobalMousePoint(void) {
+		assert(RGFW_root != NULL);
+
+		RGFW_vector RGFWMouse;
+
+		i32 x, y;
+		u32 z;
+		Window window1, window2;
+		XQueryPointer((Display*) RGFW_root->src.display, XDefaultRootWindow((Display*) RGFW_root->src.display), &window1, &window2, &x, &RGFWMouse.x, &RGFWMouse.y, &y, &z);
+
+		return RGFWMouse;
+	}
+
+	typedef struct XDND {
+		long source, version;
+		i32 format;
+	} XDND; /* data structure for xdnd events */
+	XDND xdnd;
+
+	int xAxis = 0, yAxis = 0;
+
+	RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) {
+		assert(win != NULL);
+
+		win->event.type = 0;
+
+#ifdef __linux__
+		{
+			u8 i;
+			for (i = 0; i < win->src.joystickCount; i++) {
+				struct js_event e;
+
+
+				if (!win->src.joysticks[i])
+					continue;
+
+				i32 flags = fcntl(win->src.joysticks[i], F_GETFL, 0);
+				fcntl(win->src.joysticks[i], F_SETFL, flags | O_NONBLOCK);
+
+				ssize_t bytes;
+				while ((bytes = read(win->src.joysticks[i], &e, sizeof(e))) > 0) {
+					switch (e.type) {
+					case JS_EVENT_BUTTON:
+						win->event.type = e.value ? RGFW_jsButtonPressed : RGFW_jsButtonReleased;
+						win->event.button = e.number;
+						win->src.jsPressed[i][e.number] = e.value;
+						return &win->event;
+					case JS_EVENT_AXIS:
+						ioctl(win->src.joysticks[i], JSIOCGAXES, &win->event.axisesCount);
+
+						if ((e.number == 0 || e.number % 2) && e.number != 1)
+							xAxis = e.value;
+						else
+							yAxis = e.value;
+
+						win->event.axis[e.number / 2].x = xAxis;
+						win->event.axis[e.number / 2].y = yAxis;
+						win->event.type = RGFW_jsAxisMove;
+						win->event.joystick = e.number / 2;
+						return &win->event;
+
+					default: break;
+					}
+				}
+			}
+		}
+#endif
+
+		XEvent E; /* raw X11 event */
+
+		/* if there is no unread qued events, get a new one */
+		if (XEventsQueued((Display*) win->src.display, QueuedAlready) + XEventsQueued((Display*) win->src.display, QueuedAfterReading) && win->event.type != RGFW_quit)
+			XNextEvent((Display*) win->src.display, &E);
+		else {
+			return NULL;
+		}
+
+		u32 i;
+
+		if (win->event.droppedFilesCount) {
+			for (i = 0; i < win->event.droppedFilesCount; i++)
+				win->event.droppedFiles[i][0] = '\0';
+		}
+
+		win->event.droppedFilesCount = 0;
+		win->event.type = 0;
+
+
+		switch (E.type) {
+		case KeyPress:
+		case KeyRelease:
+			/* check if it's a real key release */
+			if (E.type == KeyRelease && XEventsQueued((Display*) win->src.display, QueuedAfterReading)) { /* get next event if there is one*/
+				XEvent NE;
+				XPeekEvent((Display*) win->src.display, &NE);
+
+				if (E.xkey.time == NE.xkey.time && E.xkey.keycode == NE.xkey.keycode) /* check if the current and next are both the same*/
+					break;
+			}
+
+			/* set event key data */
+			win->event.keyCode = XkbKeycodeToKeysym((Display*) win->src.display, E.xkey.keycode, 0, E.xkey.state & ShiftMask ? 1 : 0);
+			win->event.keyName = XKeysymToString(win->event.keyCode); /* convert to string */
+
+			/* get keystate data */
+			win->event.type = (E.type == KeyPress) ? RGFW_keyPressed : RGFW_keyReleased;
+
+			if (win->event.type == RGFW_keyReleased) {
+				if (win->event.keyCode == XK_Caps_Lock && win->event.lockState & RGFW_CAPSLOCK)
+					win->event.lockState ^= RGFW_CAPSLOCK;
+				else if (win->event.keyCode == XK_Caps_Lock)
+					win->event.lockState |= RGFW_CAPSLOCK;
+
+				else if (win->event.keyCode == XK_Num_Lock && win->event.lockState & RGFW_NUMLOCK)
+					win->event.lockState ^= RGFW_NUMLOCK;
+				else if (win->event.keyCode == XK_Num_Lock)
+					win->event.lockState |= RGFW_NUMLOCK;
+			}
+			break;
+
+		case ButtonPress:
+		case ButtonRelease:
+			win->event.type = (E.type == ButtonPress) ? RGFW_mouseButtonPressed : RGFW_mouseButtonReleased;
+		
+			if (win->event.button == RGFW_mouseScrollUp) {
+				win->event.scroll = 1;
+			}
+			else if (win->event.button == RGFW_mouseScrollDown) {
+				win->event.scroll = -1;
+			}
+
+			win->event.button = E.xbutton.button;
+			break;
+
+		case MotionNotify:
+			win->event.point.x = E.xmotion.x;
+			win->event.point.y = E.xmotion.y;
+			win->event.type = RGFW_mousePosChanged;
+			break;
+
+		case ClientMessage:
+			/* if the client closed the window*/
+			if (E.xclient.data.l[0] == (i64) wm_delete_window) {
+				win->event.type = RGFW_quit;
+				break;
+			}
+
+			/*
+				much of this event (drag and drop code) is source from glfw
+			*/
+
+			if ((win->src.winArgs & RGFW_ALLOW_DND) == 0)
+				break;
+
+			u8 formFree = 0;
+			if (E.xclient.message_type == XdndEnter) {
+				u64 count;
+				Atom* formats = (Atom*) 0;
+				Bool list = E.xclient.data.l[1] & 1;
+
+				xdnd.source = E.xclient.data.l[0];
+				xdnd.version = E.xclient.data.l[1] >> 24;
+				xdnd.format = None;
+
+				if (xdnd.version > 5)
+					break;
+
+				if (list) {
+					Atom actualType;
+					i32 actualFormat;
+					u64 bytesAfter;
+
+					XGetWindowProperty((Display*) win->src.display,
+						xdnd.source,
+						XdndTypeList,
+						0,
+						LONG_MAX,
+						False,
+						4,
+						&actualType,
+						&actualFormat,
+						&count,
+						&bytesAfter,
+						(u8**) &formats);
+				} else {
+					formats = (Atom*) RGFW_MALLOC(E.xclient.data.l[2] + E.xclient.data.l[3] + E.xclient.data.l[4]);
+					formFree = 1;
+
+					count = 0;
+
+					if (E.xclient.data.l[2] != None)
+						formats[count++] = E.xclient.data.l[2];
+					if (E.xclient.data.l[3] != None)
+						formats[count++] = E.xclient.data.l[3];
+					if (E.xclient.data.l[4] != None)
+						formats[count++] = E.xclient.data.l[4];
+				}
+
+				u32 i;
+				for (i = 0; i < count; i++) {
+					char* name = XGetAtomName((Display*) win->src.display, formats[i]);
+
+					char* links[2] = { (char*) (const char*) "text/uri-list", (char*) (const char*) "text/plain" };
+					for (; 1; name++) {
+						u32 j;
+						for (j = 0; j < 2; j++) {
+							if (*links[j] != *name) {
+								links[j] = (char*) (const char*) "\1";
+								continue;
+							}
+
+							if (*links[j] == '\0' && *name == '\0')
+								xdnd.format = formats[i];
+
+							if (*links[j] != '\0' && *links[j] != '\1')
+								links[j]++;
+						}
+
+						if (*name == '\0')
+							break;
+					}
+				}
+
+				if (list && formats) {
+					XFree(formats);
+					formats = (Atom*) 0;
+				} else if (formFree && formats != (Atom*) 0) {
+					RGFW_FREE(formats);
+
+					formats = (Atom*) 0;
+					formFree = 1;
+				}
+
+				break;
+			}
+			if (E.xclient.message_type == XdndPosition) {
+				const i32 xabs = (E.xclient.data.l[2] >> 16) & 0xffff;
+				const i32 yabs = (E.xclient.data.l[2]) & 0xffff;
+				Window dummy;
+				i32 xpos, ypos;
+
+				if (xdnd.version > 5)
+					break;
+
+				XTranslateCoordinates((Display*) win->src.display,
+					XDefaultRootWindow((Display*) win->src.display),
+					(Window) win->src.window,
+					xabs, yabs,
+					&xpos, &ypos,
+					&dummy);
+
+				win->event.point.x = xpos;
+				win->event.point.y = ypos;
+
+				XEvent reply = { ClientMessage };
+				reply.xclient.window = xdnd.source;
+				reply.xclient.message_type = XdndStatus;
+				reply.xclient.format = 32;
+				reply.xclient.data.l[0] = (long) win->src.window;
+				reply.xclient.data.l[2] = 0;
+				reply.xclient.data.l[3] = 0;
+
+				if (xdnd.format) {
+					reply.xclient.data.l[1] = 1;
+					if (xdnd.version >= 2)
+						reply.xclient.data.l[4] = XdndActionCopy;
+				}
+
+				XSendEvent((Display*) win->src.display, xdnd.source, False, NoEventMask, &reply);
+				XFlush((Display*) win->src.display);
+				break;
+			}
+
+			if (E.xclient.message_type != XdndDrop)
+				break;
+
+			if (xdnd.version > 5)
+				break;
+
+			win->event.type = RGFW_dnd_init;
+
+			if (xdnd.format) {
+				Time time = CurrentTime;
+
+				if (xdnd.version >= 1)
+					time = E.xclient.data.l[2];
+
+				XConvertSelection((Display*) win->src.display,
+					XdndSelection,
+					xdnd.format,
+					XdndSelection,
+					(Window) win->src.window,
+					time);
+			} else if (xdnd.version >= 2) {
+				XEvent reply = { ClientMessage };
+				reply.xclient.window = xdnd.source;
+				reply.xclient.message_type = XdndFinished;
+				reply.xclient.format = 32;
+				reply.xclient.data.l[0] = (long) win->src.window;
+				reply.xclient.data.l[1] = 0;
+				reply.xclient.data.l[2] = None;
+
+				XSendEvent((Display*) win->src.display, xdnd.source,
+					False, NoEventMask, &reply);
+				XFlush((Display*) win->src.display);
+			}
+			break;
+		case SelectionNotify:
+			/* this is only for checking for xdnd drops */
+			if (E.xselection.property != XdndSelection || !(win->src.winArgs | RGFW_ALLOW_DND))
+				break;
+
+			char* data;
+			u64 result;
+
+			Atom actualType;
+			i32 actualFormat;
+			u64 bytesAfter;
+
+			XGetWindowProperty((Display*) win->src.display, E.xselection.requestor, E.xselection.property, 0, LONG_MAX, False, E.xselection.target, &actualType, &actualFormat, &result, &bytesAfter, (u8**) &data);
+
+			if (result == 0)
+				break;
+
+			/*
+			SOURCED FROM GLFW _glfwParseUriList
+			Copyright (c) 2002-2006 Marcus Geelnard
+			Copyright (c) 2006-2019 Camilla Löwy
+			*/
+
+			const char* prefix = "file://";
+
+			char* line;
+
+			win->event.droppedFilesCount = 0;
+
+			win->event.type = RGFW_dnd;
+
+			while ((line = strtok(data, "\r\n"))) {
+				char path[RGFW_MAX_PATH];
+
+				data = NULL;
+
+				if (line[0] == '#')
+					continue;
+
+				char* l;
+				for (l = line; 1; l++) {
+					if ((l - line) > 7)
+						break;
+					else if (*l != prefix[(l - line)])
+						break;
+					else if (*l == '\0' && prefix[(l - line)] == '\0') {
+						line += 7;
+						while (*line != '/')
+							line++;
+						break;
+					} else if (*l == '\0')
+						break;
+				}
+
+				win->event.droppedFilesCount++;
+
+				size_t index = 0;
+				while (*line) {
+					if (line[0] == '%' && line[1] && line[2]) {
+						const char digits[3] = { line[1], line[2], '\0' };
+						path[index] = (char) strtol(digits, NULL, 16);
+						line += 2;
+					} else
+						path[index] = *line;
+
+					index++;
+					line++;
+				}
+
+				strcpy(win->event.droppedFiles[win->event.droppedFilesCount - 1], path);
+			}
+
+			if (data)
+				XFree(data);
+
+			if (xdnd.version >= 2) {
+				XEvent reply = { ClientMessage };
+				reply.xclient.window = xdnd.source;
+				reply.xclient.message_type = XdndFinished;
+				reply.xclient.format = 32;
+				reply.xclient.data.l[0] = (long) win->src.window;
+				reply.xclient.data.l[1] = result;
+				reply.xclient.data.l[2] = XdndActionCopy;
+
+				XSendEvent((Display*) win->src.display, xdnd.source, False, NoEventMask, &reply);
+				XFlush((Display*) win->src.display);
+			}
+
+			break;
+
+		case FocusIn:
+			win->event.inFocus = 1;
+
+			XKeyboardState keystate;
+			XGetKeyboardControl((Display*) win->src.display, &keystate);
+			win->event.lockState = keystate.led_mask;
+
+			break;
+		case FocusOut:
+			win->event.inFocus = 0;
+			RGFW_window_setMouseDefault(win);
+			break;
+		case ConfigureNotify: {
+#ifndef RGFW_NO_X11_WINDOW_ATTRIB
+			XWindowAttributes a;
+			XGetWindowAttributes((Display*) win->src.display, (Window) win->src.window, &a);
+			win->r = RGFW_RECT(E.xconfigure.x, E.xconfigure.y, E.xconfigure.width, E.xconfigure.height);
+#endif
+
+			win->event.type = RGFW_windowAttribsChange;
+			break;
+		}
+		default: {
+			break;
+		}
+		}
+
+		if (win->event.inFocus && (win->src.winArgs & RGFW_MOUSE_CHANGED)) {
+			XDefineCursor((Display*) win->src.display, (Window) win->src.window, (Cursor) win->src.cursor);
+
+			win->src.winArgs &= ~RGFW_MOUSE_CHANGED;
+		}
+
+			RGFW_vector mouse = RGFW_getGlobalMousePoint();
+			if (win->src.winArgs & RGFW_HOLD_MOUSE && win->event.inFocus && win->event.type == RGFW_mousePosChanged) {
+				RGFW_window_moveMouse(win, RGFW_VECTOR(win->r.x + (win->r.w / 2), win->r.y + (win->r.h / 2)));
+				
+				if (XEventsQueued((Display*) win->src.display, QueuedAfterReading) <= 1)
+					XSync(win->src.display, True);
+			}
+			
+
+		XFlush((Display*) win->src.display);
+
+		if (win->event.type)
+			return &win->event;
+		else
+			return NULL;
+	}
+
+	void RGFW_window_close(RGFW_window* win) {
+		assert(win != NULL);
+
+#ifdef RGFW_VULKAN
+		for (int i = 0; i < win->src.image_count; i++) {
+			vkDestroyImageView(RGFW_vulkan_info.device, win->src.swapchain_image_views[i], NULL);
+		}
+
+		vkDestroySwapchainKHR(RGFW_vulkan_info.device, win->src.swapchain, NULL);
+		vkDestroySurfaceKHR(RGFW_vulkan_info.instance, win->src.rSurf, NULL);
+		free(win->src.swapchain_image_views);
+		free(win->src.swapchain_images);
+#endif
+
+#ifdef RGFW_EGL
+		RGFW_closeEGL(win);
+#endif
+
+		XFreeCursor((Display*) win->src.display, (Cursor) win->src.cursor);
+
+#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)
+		if (win->buffer != NULL) {
+			XDestroyImage((XImage*) win->src.bitmap);
+		}
+#endif
+
+		if ((Display*) win->src.display) {
+#ifdef RGFW_OPENGL
+			glXDestroyContext((Display*) win->src.display, win->src.rSurf);
+#endif
+
+			if (win == RGFW_root)
+				RGFW_root = NULL;
+
+			if ((Drawable) win->src.window)
+				XDestroyWindow((Display*) win->src.display, (Drawable) win->src.window); /* close the window*/
+
+			if (win->src.display)
+				XCloseDisplay((Display*) win->src.display); /* kill the display*/
+		}
+
+#ifdef RGFW_ALLOC_DROPFILES
+		{
+			u32 i;
+			for (i = 0; i < RGFW_MAX_DROPS; i++)
+				RGFW_FREE(win->event.droppedFiles[i]);
+
+
+			RGFW_FREE(win->event.droppedFiles);
+		}
+#endif
+
+		RGFW_windowsOpen--;
+#if !defined(RGFW_NO_X11_CURSOR_PRELOAD) && !defined(RGFW_NO_X11_CURSOR)
+		if (X11Cursorhandle != NULL && RGFW_windowsOpen <= 0) {
+			dlclose(X11Cursorhandle);
+
+			X11Cursorhandle = NULL;
+		}
+#endif
+
+		/* set cleared display / window to NULL for error checking */
+		win->src.display = (Display*) 0;
+		win->src.window = (Window) 0;
+
+		u8 i;
+		for (i = 0; i < win->src.joystickCount; i++)
+			close(win->src.joysticks[i]);
+
+		RGFW_FREE(win); /* free collected window data */
+	}
+
+	void RGFW_window_move(RGFW_window* win, RGFW_vector v) {
+		assert(win != NULL);
+		win->r.x = v.x;
+		win->r.y = v.y;
+
+		XMoveWindow((Display*) win->src.display, (Window) win->src.window, v.x, v.y);
+	}
+
+
+	void RGFW_window_resize(RGFW_window* win, RGFW_area a) {
+		assert(win != NULL);
+		win->r.w = a.w;
+		win->r.h = a.h;
+
+		XResizeWindow((Display*) win->src.display, (Window) win->src.window, a.w, a.h);
+	}
+
+	void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) {
+		assert(win != NULL);
+
+		XSizeHints hints;
+		long flags;
+
+		XGetWMNormalHints(win->src.display, (Window) win->src.window, &hints, &flags);
+
+		hints.flags |= PMinSize;
+
+		hints.min_width = a.w;
+		hints.min_height = a.h;
+
+		XSetWMNormalHints(win->src.display, (Window) win->src.window, &hints);
+	}
+
+	void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) {
+		assert(win != NULL);
+
+		XSizeHints hints;
+		long flags;
+
+		XGetWMNormalHints(win->src.display, (Window) win->src.window, &hints, &flags);
+
+		hints.flags |= PMaxSize;
+
+		hints.max_width = a.w;
+		hints.max_height = a.h;
+
+		XSetWMNormalHints(win->src.display, (Window) win->src.window, &hints);
+	}
+
+
+	void RGFW_window_minimize(RGFW_window* win) {
+		assert(win != NULL);
+
+		XIconifyWindow(win->src.display, (Window) win->src.window, DefaultScreen(win->src.display));
+		XFlush(win->src.display);
+	}
+
+	void RGFW_window_restore(RGFW_window* win) {
+		assert(win != NULL);
+
+		XMapWindow(win->src.display, (Window) win->src.window);
+		XFlush(win->src.display);
+	}
+
+	void RGFW_window_setName(RGFW_window* win, char* name) {
+		assert(win != NULL);
+
+		XStoreName((Display*) win->src.display, (Window) win->src.window, name);
+	}
+
+	/*
+		the majority function is sourced from GLFW
+	*/
+
+	void RGFW_window_setIcon(RGFW_window* win, u8* icon, RGFW_area a, i32 channels) {
+		assert(win != NULL);
+
+		i32 longCount = 2 + a.w * a.h;
+
+		u64* X11Icon = (u64*) RGFW_MALLOC(longCount * sizeof(u64));
+		u64* target = X11Icon;
+
+		*target++ = a.w;
+		*target++ = a.h;
+
+		u32 i;
+
+		for (i = 0; i < a.w * a.h; i++) {
+			if (channels == 3)
+				*target++ = ((icon[i * 3 + 0]) << 16) |
+				((icon[i * 3 + 1]) << 8) |
+				((icon[i * 3 + 2]) << 0) |
+				(0xFF << 24);
+
+			else if (channels == 4)
+				*target++ = ((icon[i * 4 + 0]) << 16) |
+				((icon[i * 4 + 1]) << 8) |
+				((icon[i * 4 + 2]) << 0) |
+				((icon[i * 4 + 3]) << 24);
+		}
+
+		static Atom NET_WM_ICON = 0;
+		if (NET_WM_ICON == 0)
+			NET_WM_ICON = XInternAtom((Display*) win->src.display, "_NET_WM_ICON", False);
+
+		XChangeProperty((Display*) win->src.display, (Window) win->src.window,
+			NET_WM_ICON,
+			6, 32,
+			PropModeReplace,
+			(u8*) X11Icon,
+			longCount);
+
+		RGFW_FREE(X11Icon);
+
+		XFlush((Display*) win->src.display);
+	}
+
+	void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels) {
+		assert(win != NULL);
+
+#ifndef RGFW_NO_X11_CURSOR
+		/* free the previous cursor */
+		if (win->src.cursor && win->src.cursor != -1)
+			XFreeCursor((Display*) win->src.display, (Cursor) win->src.cursor);
+
+		XcursorImage* native = XcursorImageCreate(a.w, a.h);
+		native->xhot = 0;
+		native->yhot = 0;
+
+		u8* source = (u8*) image;
+		XcursorPixel* target = native->pixels;
+
+		u32 i;
+		for (i = 0; i < a.w * a.h; i++, target++, source += 4) {
+			u8 alpha = 0xFF;
+			if (channels == 4)
+				alpha = source[3];
+
+			*target = (alpha << 24) | (((source[0] * alpha) / 255) << 16) | (((source[1] * alpha) / 255) << 8) | (((source[2] * alpha) / 255) << 0);
+		}
+
+		win->src.winArgs |= RGFW_MOUSE_CHANGED;
+		win->src.cursor = XcursorImageLoadCursor((Display*) win->src.display, native);
+
+		XcursorImageDestroy(native);
+#endif
+	}
+
+	void RGFW_window_moveMouse(RGFW_window* win, RGFW_vector v) {
+		assert(win != NULL);
+
+		XEvent event;
+		XQueryPointer(win->src.display, DefaultRootWindow(win->src.display),
+			&event.xbutton.root, &event.xbutton.window,
+			&event.xbutton.x_root, &event.xbutton.y_root,
+			&event.xbutton.x, &event.xbutton.y,
+			&event.xbutton.state);
+
+		if (event.xbutton.x == v.x && event.xbutton.y == v.y)
+			return;
+
+		XWarpPointer(win->src.display, None, None, 0, 0, 0, 0, -event.xbutton.x, -event.xbutton.y);
+		XWarpPointer(win->src.display, None, None, 0, 0, 0, 0, v.x, v.y);
+	}
+
+	RGFWDEF void RGFW_window_disableMouse(RGFW_window* win) {
+
+	}
+
+	void RGFW_window_setMouseDefault(RGFW_window* win) {
+		RGFW_window_setMouseStandard(win, XC_left_ptr);
+	}
+
+	void RGFW_window_setMouseStandard(RGFW_window* win, i32 mouse) {
+		assert(win != NULL);
+
+		/* free the previous cursor */
+		if (win->src.cursor && win->src.cursor != -1)
+			XFreeCursor((Display*) win->src.display, (Cursor) win->src.cursor);
+
+		win->src.winArgs |= RGFW_MOUSE_CHANGED;
+		win->src.cursor = XCreateFontCursor((Display*) win->src.display, mouse);
+	}
+
+	void RGFW_window_hide(RGFW_window* win) {
+		XMapWindow(win->src.display, win->src.window);
+	}
+
+	void RGFW_window_show(RGFW_window* win) {
+		XUnmapWindow(win->src.display, win->src.window);
+	}
+
+	/*
+		the majority function is sourced from GLFW
+	*/
+	char* RGFW_readClipboard(size_t* size) {
+		static Atom UTF8 = 0;
+		if (UTF8 == 0)
+			UTF8 = XInternAtom(RGFW_root->src.display, "UTF8_STRING", True);
+
+		XEvent event;
+		int format;
+		unsigned long N, sizeN;
+		char* data, * s = NULL;
+		Atom target;
+		Atom CLIPBOARD = 0, XSEL_DATA = 0;
+
+		if (CLIPBOARD == 0) {
+			CLIPBOARD = XInternAtom(RGFW_root->src.display, "CLIPBOARD", 0);
+			XSEL_DATA = XInternAtom(RGFW_root->src.display, "XSEL_DATA", 0);
+		}
+
+		XConvertSelection(RGFW_root->src.display, CLIPBOARD, UTF8, XSEL_DATA, RGFW_root->src.window, CurrentTime);
+		XSync(RGFW_root->src.display, 0);
+		XNextEvent(RGFW_root->src.display, &event);
+
+		if (event.type != SelectionNotify || event.xselection.selection != CLIPBOARD || event.xselection.property == 0)
+			return NULL;
+
+		XGetWindowProperty(event.xselection.display, event.xselection.requestor,
+			event.xselection.property, 0L, (~0L), 0, AnyPropertyType, &target,
+			&format, &sizeN, &N, (unsigned char**) &data);
+
+		if (target == UTF8 || target == XA_STRING) {
+			s = strndup(data, sizeN);
+			XFree(data);
+		}
+
+		XDeleteProperty(event.xselection.display, event.xselection.requestor, event.xselection.property);
+
+		if (s != NULL && size != NULL)
+			*size = sizeN;
+
+		return s;
+	}
+
+	/*
+		almost all of this function is sourced from GLFW
+	*/
+	void RGFW_writeClipboard(const char* text, u32 textLen) {
+		static Atom CLIPBOARD = 0,
+			UTF8_STRING = 0,
+			SAVE_TARGETS = 0,
+			TARGETS = 0,
+			MULTIPLE = 0,
+			ATOM_PAIR = 0,
+			CLIPBOARD_MANAGER = 0;
+
+		if (CLIPBOARD == 0) {
+			CLIPBOARD = XInternAtom((Display*) RGFW_root->src.display, "CLIPBOARD", False);
+			UTF8_STRING = XInternAtom((Display*) RGFW_root->src.display, "UTF8_STRING", False);
+			SAVE_TARGETS = XInternAtom((Display*) RGFW_root->src.display, "SAVE_TARGETS", False);
+			TARGETS = XInternAtom((Display*) RGFW_root->src.display, "TARGETS", False);
+			MULTIPLE = XInternAtom((Display*) RGFW_root->src.display, "MULTIPLE", False);
+			ATOM_PAIR = XInternAtom((Display*) RGFW_root->src.display, "ATOM_PAIR", False);
+			CLIPBOARD_MANAGER = XInternAtom((Display*) RGFW_root->src.display, "CLIPBOARD_MANAGER", False);
+		}
+
+		XSetSelectionOwner((Display*) RGFW_root->src.display, CLIPBOARD, (Window) RGFW_root->src.window, CurrentTime);
+
+		XConvertSelection((Display*) RGFW_root->src.display, CLIPBOARD_MANAGER, SAVE_TARGETS, None, (Window) RGFW_root->src.window, CurrentTime);
+
+		for (;;) {
+			XEvent event;
+
+			XNextEvent((Display*) RGFW_root->src.display, &event);
+			if (event.type != SelectionRequest)
+				return;
+
+			const XSelectionRequestEvent* request = &event.xselectionrequest;
+
+			XEvent reply = { SelectionNotify };
+
+			char* selectionString = NULL;
+			const Atom formats[] = { UTF8_STRING, XA_STRING };
+			const i32 formatCount = sizeof(formats) / sizeof(formats[0]);
+
+			selectionString = (char*) text;
+
+			if (request->target == TARGETS) {
+				const Atom targets[] = { TARGETS,
+										MULTIPLE,
+										UTF8_STRING,
+										XA_STRING };
+
+				XChangeProperty((Display*) RGFW_root->src.display,
+					request->requestor,
+					request->property,
+					4,
+					32,
+					PropModeReplace,
+					(u8*) targets,
+					sizeof(targets) / sizeof(targets[0]));
+
+				reply.xselection.property = request->property;
+			}
+
+			if (request->target == MULTIPLE) {
+
+				Atom* targets;
+
+				Atom actualType;
+				i32 actualFormat;
+				u64 count, bytesAfter;
+
+				XGetWindowProperty((Display*) RGFW_root->src.display, request->requestor, request->property, 0, LONG_MAX, False, ATOM_PAIR, &actualType, &actualFormat, &count, &bytesAfter, (u8**) &targets);
+
+				u64 i;
+				for (i = 0; i < count; i += 2) {
+					i32 j;
+
+					for (j = 0; j < formatCount; j++) {
+						if (targets[i] == formats[j])
+							break;
+					}
+
+					if (j < formatCount)
+					{
+						XChangeProperty((Display*) RGFW_root->src.display,
+							request->requestor,
+							targets[i + 1],
+							targets[i],
+							8,
+							PropModeReplace,
+							(u8*) selectionString,
+							textLen);
+					} else
+						targets[i + 1] = None;
+				}
+
+				XChangeProperty((Display*) RGFW_root->src.display,
+					request->requestor,
+					request->property,
+					ATOM_PAIR,
+					32,
+					PropModeReplace,
+					(u8*) targets,
+					count);
+
+				XFree(targets);
+
+				reply.xselection.property = request->property;
+			}
+
+			reply.xselection.display = request->display;
+			reply.xselection.requestor = request->requestor;
+			reply.xselection.selection = request->selection;
+			reply.xselection.target = request->target;
+			reply.xselection.time = request->time;
+
+			XSendEvent((Display*) RGFW_root->src.display, request->requestor, False, 0, &reply);
+		}
+	}
+
+	u16 RGFW_registerJoystick(RGFW_window* win, i32 jsNumber) {
+		assert(win != NULL);
+
+#ifdef __linux__
+		char file[15];
+		sprintf(file, "/dev/input/js%i", jsNumber);
+
+		return RGFW_registerJoystickF(win, file);
+#endif
+	}
+
+	u16 RGFW_registerJoystickF(RGFW_window* win, char* file) {
+		assert(win != NULL);
+
+#ifdef __linux__
+
+		i32 js = open(file, O_RDONLY);
+
+		if (js && win->src.joystickCount < 4) {
+			win->src.joystickCount++;
+
+			win->src.joysticks[win->src.joystickCount - 1] = open(file, O_RDONLY);
+
+			u8 i;
+			for (i = 0; i < 16; i++)
+				win->src.jsPressed[win->src.joystickCount - 1][i] = 0;
+
+		}
+
+		else {
+#ifdef RGFW_PRINT_ERRORS
+			RGFW_error = 1;
+			fprintf(stderr, "Error RGFW_registerJoystickF : Cannot open file %s\n", file);
+#endif
+		}
+
+		return win->src.joystickCount - 1;
+#endif
+	}
+
+	u8 RGFW_window_isFullscreen(RGFW_window* win) {
+		assert(win != NULL);
+
+		XWindowAttributes windowAttributes;
+		XGetWindowAttributes(win->src.display, (Window) win->src.window, &windowAttributes);
+
+		/* check if the window is visable */
+		if (windowAttributes.map_state != IsViewable)
+			return 0;
+
+		/* check if the window covers the full screen */
+		return (windowAttributes.x == 0 && windowAttributes.y == 0 &&
+			windowAttributes.width == XDisplayWidth(win->src.display, DefaultScreen(win->src.display)) &&
+			windowAttributes.height == XDisplayHeight(win->src.display, DefaultScreen(win->src.display)));
+	}
+
+	u8 RGFW_window_isHidden(RGFW_window* win) {
+		assert(win != NULL);
+
+		XWindowAttributes windowAttributes;
+		XGetWindowAttributes(win->src.display, (Window) win->src.window, &windowAttributes);
+
+		return (windowAttributes.map_state == IsUnmapped && !RGFW_window_isMinimized(win));
+	}
+
+	u8 RGFW_window_isMinimized(RGFW_window* win) {
+		assert(win != NULL);
+
+		static Atom prop = 0;
+		if (prop == 0)
+			prop = XInternAtom(win->src.display, "WM_STATE", False);
+
+		Atom actual_type;
+		i32 actual_format;
+		u64 nitems, bytes_after;
+		unsigned char* prop_data;
+
+		i16 status = XGetWindowProperty(win->src.display, (Window) win->src.window, prop, 0, 2, False,
+			AnyPropertyType, &actual_type, &actual_format,
+			&nitems, &bytes_after, &prop_data);
+
+		if (status == Success && nitems >= 1 && *((int*) prop_data) == IconicState) {
+			XFree(prop_data);
+			return 1;
+		}
+
+		if (prop_data != NULL)
+			XFree(prop_data);
+
+		return 0;
+	}
+
+	u8 RGFW_window_isMaximized(RGFW_window* win) {
+		assert(win != NULL);
+
+		static Atom net_wm_state = 0;
+		static Atom net_wm_state_maximized_horz = 0;
+		static Atom net_wm_state_maximized_vert = 0;
+
+		if (net_wm_state == 0) {
+			net_wm_state = XInternAtom(win->src.display, "_NET_WM_STATE", False);
+			net_wm_state_maximized_vert = XInternAtom(win->src.display, "_NET_WM_STATE_MAXIMIZED_VERT", False);
+			net_wm_state_maximized_horz = XInternAtom(win->src.display, "_NET_WM_STATE_MAXIMIZED_HORZ", False);
+		}
+
+		Atom actual_type;
+		i32 actual_format;
+		u64 nitems, bytes_after;
+		unsigned char* prop_data;
+
+		i16 status = XGetWindowProperty(win->src.display, (Window) win->src.window, net_wm_state, 0, 1024, False,
+			XA_ATOM, &actual_type, &actual_format,
+			&nitems, &bytes_after, &prop_data);
+
+		if (status != Success) {
+			if (prop_data != NULL)
+				XFree(prop_data);
+
+			return 0;
+		}
+
+		Atom* atoms = (Atom*) prop_data;
+		u64 i;
+		for (i = 0; i < nitems; ++i) {
+			if (atoms[i] == net_wm_state_maximized_horz ||
+				atoms[i] == net_wm_state_maximized_vert) {
+				XFree(prop_data);
+				return 1;
+			}
+		}
+
+		return 0;
+	}
+
+	static void XGetSystemContentScale(Display* display, float* xscale, float* yscale) {
+		float xdpi = 96.f, ydpi = 96.f;
+
+#ifndef RGFW_NO_DPI
+		char* rms = XResourceManagerString(display);
+		XrmDatabase db = NULL;
+
+		if (rms && db)
+			db = XrmGetStringDatabase(rms);
+
+		if (db == 0) {
+			*xscale = xdpi / 96.f;
+			*yscale = ydpi / 96.f;
+			return;
+		}
+
+		XrmValue value;
+		char* type = NULL;
+
+		if (XrmGetResource(db, "Xft.dpi", "Xft.Dpi", &type, &value) && type && strcmp(type, "String") == 0)
+			xdpi = ydpi = atof(value.addr);
+		XrmDestroyDatabase(db);
+#endif
+
+		* xscale = xdpi / 96.f;
+		*yscale = ydpi / 96.f;
+	}
+
+	RGFW_monitor RGFW_XCreateMonitor(i32 screen) {
+		RGFW_monitor monitor;
+
+		Display* display = XOpenDisplay(NULL);
+
+		monitor.rect = RGFW_RECT(0, 0, DisplayWidth(display, screen), DisplayHeight(display, screen));
+		monitor.physW = (monitor.rect.w * 25.4f / 96.f);
+		monitor.physH = (monitor.rect.h * 25.4f / 96.f);
+
+		strncpy(monitor.name, DisplayString(display), 128);
+
+		XGetSystemContentScale(display, &monitor.scaleX, &monitor.scaleY);
+
+		XRRScreenResources* sr = XRRGetScreenResourcesCurrent(display, RootWindow(display, screen));
+
+		XRRCrtcInfo* ci = NULL;
+		int crtc = 0;
+
+		if (sr->ncrtc > crtc) {
+			ci = XRRGetCrtcInfo(display, sr, sr->crtcs[crtc]);
+		}
+
+		if (ci == NULL) {
+			XRRFreeScreenResources(sr);
+			XCloseDisplay(display);
+			return monitor;
+		}
+
+		monitor.rect.x = ci->x;
+		monitor.rect.y = ci->y;
+
+		XRRFreeCrtcInfo(ci);
+		XRRFreeScreenResources(sr);
+
+		XCloseDisplay(display);
+
+		return monitor;
+	}
+
+	RGFW_monitor RGFW_monitors[6];
+	RGFW_monitor* RGFW_getMonitors(void) {
+		size_t i;
+		for (i = 0; i < ScreenCount(RGFW_root->src.display) && i < 6; i++)
+			RGFW_monitors[i] = RGFW_XCreateMonitor(i);
+
+		return RGFW_monitors;
+	}
+
+	RGFW_monitor RGFW_getPrimaryMonitor(void) {
+		assert(RGFW_root != NULL);
+
+		i32 primary = -1;
+		Window root = DefaultRootWindow(RGFW_root->src.display);
+		XRRScreenResources* res = XRRGetScreenResources(RGFW_root->src.display, root);
+
+		for (int i = 0; i < res->noutput; i++) {
+			XRROutputInfo* output_info = XRRGetOutputInfo(RGFW_root->src.display, res, res->outputs[i]);
+			if (output_info->connection == RR_Connected && output_info->crtc) {
+				XRRCrtcInfo* crtc_info = XRRGetCrtcInfo(RGFW_root->src.display, res, output_info->crtc);
+				if (crtc_info->mode != None && crtc_info->x == 0 && crtc_info->y == 0) {
+					primary = i;
+					XRRFreeCrtcInfo(crtc_info);
+					XRRFreeOutputInfo(output_info);
+					break;
+				}
+				XRRFreeCrtcInfo(crtc_info);
+			}
+			XRRFreeOutputInfo(output_info);
+		}
+
+		XRRFreeScreenResources(res);
+
+		return RGFW_XCreateMonitor(primary);
+	}
+
+	RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) {
+		return RGFW_XCreateMonitor(DefaultScreen(win->src.display));
+	}
+
+	char keyboard[32];
+
+	u8 RGFW_isPressedI(RGFW_window* win, u32 key) {
+		Display* d;
+		if (win == (RGFW_window*) 0)
+			d = RGFW_root->src.display;
+		else if (!win->event.inFocus)
+			return 0;
+		else
+			d = (Display*) win->src.display;
+
+		XQueryKeymap(d, keyboard); /* query the keymap */
+
+		KeyCode kc2 = XKeysymToKeycode(d, key); /* convert the key to a keycode */
+		return !!(keyboard[kc2 >> 3] & (1 << (kc2 & 7)));				/* check if the key is pressed */
+	}
+
+#endif
+
+#ifdef RGFW_WINDOWS
+	char* createUTF8FromWideStringWin32(const WCHAR* source);
+
+#define GL_FRONT				0x0404
+#define GL_BACK					0x0405
+#define GL_LEFT					0x0406
+#define GL_RIGHT				0x0407
+
+#if defined(RGFW_OSMESA) && defined(RGFW_LINK_OSMESA)
+
+	typedef void (GLAPIENTRY* PFN_OSMesaDestroyContext)(OSMesaContext);
+	typedef i32(GLAPIENTRY* PFN_OSMesaMakeCurrent)(OSMesaContext, void*, int, int, int);
+	typedef OSMesaContext(GLAPIENTRY* PFN_OSMesaCreateContext)(GLenum, OSMesaContext);
+
+	PFN_OSMesaMakeCurrent OSMesaMakeCurrentSource;
+	PFN_OSMesaCreateContext OSMesaCreateContextSource;
+	PFN_OSMesaDestroyContext OSMesaDestroyContextSource;
+
+#define OSMesaCreateContext OSMesaCreateContextSource
+#define OSMesaMakeCurrent OSMesaMakeCurrentSource
+#define OSMesaDestroyContext OSMesaDestroyContextSource
+#endif
+
+	typedef int (*PFN_wglGetSwapIntervalEXT)(void);
+	PFN_wglGetSwapIntervalEXT wglGetSwapIntervalEXTSrc = NULL;
+#define wglGetSwapIntervalEXT wglGetSwapIntervalEXTSrc
+
+
+
+#if defined(RGFW_DIRECTX)
+	RGFW_directXinfo RGFW_dxInfo;
+
+	RGFW_directXinfo* RGFW_getDirectXInfo(void) { return &RGFW_dxInfo; }
+#endif
+
+	void* RGFWjoystickApi = NULL;
+
+	/* these two wgl functions need to be preloaded */
+	typedef HGLRC(WINAPI* wglCreateContextAttribsARB_type)(HDC hdc, HGLRC hShareContext,
+		const i32* attribList);
+	wglCreateContextAttribsARB_type wglCreateContextAttribsARB = NULL;
+
+	/* defines for creating ARB attributes */
+#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000
+#define WGL_CONTEXT_MAJOR_VERSION_ARB             0x2091
+#define WGL_CONTEXT_MINOR_VERSION_ARB             0x2092
+#define WGL_TRANSPARENT_ARB   					  0x200A
+#define WGL_DRAW_TO_WINDOW_ARB                    0x2001
+#define WGL_ACCELERATION_ARB                      0x2003
+#define WGL_NO_ACCELERATION_ARB 0x2025
+#define WGL_SUPPORT_OPENGL_ARB                    0x2010
+#define WGL_DOUBLE_BUFFER_ARB                     0x2011
+#define WGL_PIXEL_TYPE_ARB                        0x2013
+#define WGL_COLOR_BITS_ARB                        0x2014
+#define WGL_RED_BITS_ARB 0x2015
+#define WGL_RED_SHIFT_ARB 0x2016
+#define WGL_GREEN_BITS_ARB 0x2017
+#define WGL_GREEN_SHIFT_ARB 0x2018
+#define WGL_BLUE_BITS_ARB 0x2019
+#define WGL_BLUE_SHIFT_ARB 0x201a
+#define WGL_ALPHA_BITS_ARB 0x201b
+#define WGL_ALPHA_SHIFT_ARB 0x201c
+#define WGL_ACCUM_BITS_ARB 0x201d
+#define WGL_ACCUM_RED_BITS_ARB 0x201e
+#define WGL_ACCUM_GREEN_BITS_ARB 0x201f
+#define WGL_ACCUM_BLUE_BITS_ARB 0x2020
+#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021
+#define WGL_DEPTH_BITS_ARB 0x2022
+#define WGL_AUX_BUFFERS_ARB 0x2024
+#define WGL_STEREO_ARB 0x2012
+#define WGL_DEPTH_BITS_ARB                        0x2022
+#define WGL_STENCIL_BITS_ARB 					  0x2023
+#define WGL_FULL_ACCELERATION_ARB                 0x2027
+#define WGL_TYPE_RGBA_ARB                         0x202B
+#define WGL_CONTEXT_FLAGS_ARB                     0x2094
+#define WGL_CONTEXT_PROFILE_MASK_ARB              0x9126
+#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
+#define WGL_SAMPLE_BUFFERS_ARB               0x2041
+#define WGL_SAMPLES_ARB 0x2042
+#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20a9
+
+static HMODULE wglinstance = NULL;
+
+#ifdef RGFW_WGL_LOAD
+	typedef HGLRC(WINAPI* PFN_wglCreateContext)(HDC);
+	typedef BOOL(WINAPI* PFN_wglDeleteContext)(HGLRC);
+	typedef PROC(WINAPI* PFN_wglGetProcAddress)(LPCSTR);
+	typedef BOOL(WINAPI* PFN_wglMakeCurrent)(HDC, HGLRC);
+	typedef HDC(WINAPI* PFN_wglGetCurrentDC)();
+	typedef HGLRC(WINAPI* PFN_wglGetCurrentContext)();
+
+	PFN_wglCreateContext wglCreateContextSRC;
+	PFN_wglDeleteContext wglDeleteContextSRC;
+	PFN_wglGetProcAddress wglGetProcAddressSRC;
+	PFN_wglMakeCurrent wglMakeCurrentSRC;
+	PFN_wglGetCurrentDC wglGetCurrentDCSRC;
+	PFN_wglGetCurrentContext wglGetCurrentContextSRC;
+
+#define wglCreateContext wglCreateContextSRC
+#define wglDeleteContext wglDeleteContextSRC
+#define wglGetProcAddress wglGetProcAddressSRC
+#define wglMakeCurrent wglMakeCurrentSRC
+
+#define wglGetCurrentDC wglGetCurrentDCSRC
+#define wglGetCurrentContext wglGetCurrentContextSRC
+#endif
+
+#ifdef RGFW_OPENGL
+	void* RGFW_getProcAddress(const char* procname) { 
+		void* proc = (void*) wglGetProcAddress(procname);
+		if (proc)
+			return proc;
+
+		return (void*) GetProcAddress(wglinstance, procname); 
+	}
+
+	typedef BOOL(APIENTRY* PFNWGLCHOOSEPIXELFORMATARBPROC)(HDC hdc, const int* piAttribIList, const FLOAT* pfAttribFList, UINT nMaxFormats, int* piFormats, UINT* nNumFormats);
+	static PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = NULL;
+#endif
+
+	RGFW_window RGFW_eventWindow = { {NULL} };
+
+	LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
+		switch (message) {
+		case WM_MOVE:
+			RGFW_eventWindow.r.x = LOWORD(lParam);
+			RGFW_eventWindow.r.y = HIWORD(lParam);
+			RGFW_eventWindow.src.window = hWnd;
+			return DefWindowProcA(hWnd, message, wParam, lParam);
+		case WM_SIZE:
+			RGFW_eventWindow.r.w = LOWORD(lParam);
+			RGFW_eventWindow.r.h = HIWORD(lParam);
+			RGFW_eventWindow.src.window = hWnd;
+			return DefWindowProcA(hWnd, message, wParam, lParam); // Call DefWindowProc after handling
+		default:
+			return DefWindowProcA(hWnd, message, wParam, lParam);
+		}
+	}
+	
+	#ifndef RGFW_NO_DPI
+	static HMODULE RGFW_Shcore_dll = NULL;
+	typedef HRESULT (WINAPI * PFN_GetDpiForMonitor)(HMONITOR,MONITOR_DPI_TYPE,UINT*,UINT*);
+	PFN_GetDpiForMonitor GetDpiForMonitorSRC = NULL;
+	#define GetDpiForMonitor GetDpiForMonitorSRC
+	#endif
+
+	void RGFW_loadXInput(void) {
+		u32 i;
+		static const char* names[] = { 
+			"xinput1_4.dll",
+			"xinput1_3.dll",
+			"xinput9_1_0.dll",
+			"xinput1_2.dll",
+			"xinput1_1.dll"
+		};
+
+		for (i = 0; i < sizeof(names) / sizeof(const char*);  i++) {
+			RGFW_XInput_dll = LoadLibraryA(names[i]);
+
+			if (RGFW_XInput_dll) {
+				XInputGetStateSRC = (PFN_XInputGetState)GetProcAddress(RGFW_XInput_dll, "XInputGetState");
+			
+				if (XInputGetStateSRC == NULL)
+					printf("Failed to load XInputGetState");
+			}
+		}
+	}
+
+	RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) {
+		if (RGFW_XInput_dll == NULL)
+			RGFW_loadXInput();
+		
+		#ifndef RGFW_NO_DPI
+		if (RGFW_Shcore_dll == NULL) {
+			RGFW_Shcore_dll = LoadLibraryA("shcore.dll");
+			GetDpiForMonitorSRC = (PFN_GetDpiForMonitor)GetProcAddress(RGFW_Shcore_dll, "GetDpiForMonitor");
+		}
+		#endif
+
+		if (wglinstance == NULL) {
+			wglinstance = LoadLibraryA("opengl32.dll");
+#ifdef RGFW_WGL_LOAD
+			wglCreateContextSRC = (PFN_wglCreateContext) GetProcAddress(wglinstance, "wglCreateContext");
+			wglDeleteContextSRC = (PFN_wglDeleteContext) GetProcAddress(wglinstance, "wglDeleteContext");
+			wglGetProcAddressSRC = (PFN_wglGetProcAddress) GetProcAddress(wglinstance, "wglGetProcAddress");
+			wglMakeCurrentSRC = (PFN_wglMakeCurrent) GetProcAddress(wglinstance, "wglMakeCurrent");
+			wglGetCurrentDCSRC = (PFN_wglGetCurrentDC) GetProcAddress(wglinstance, "wglGetCurrentDC");
+			wglGetCurrentContextSRC = (PFN_wglGetCurrentContext) GetProcAddress(wglinstance, "wglGetCurrentContext");
+#endif
+		}
+
+		if (name[0] == 0) name = (char*) " ";
+
+		RGFW_eventWindow.r = RGFW_RECT(-1, -1, -1, -1);
+
+		RGFW_window* win = RGFW_window_basic_init(rect, args);
+
+		if (RGFW_root == NULL) {
+			RGFW_root = win;
+		}
+		
+		HINSTANCE inh = GetModuleHandleA(NULL);
+
+		WNDCLASSA Class = { 0 }; /* Setup the Window class. */
+		Class.lpszClassName = name;
+		Class.hInstance = inh;
+		Class.hCursor = LoadCursor(NULL, IDC_ARROW);
+		Class.lpfnWndProc = WndProc;
+
+		RegisterClassA(&Class);
+
+		DWORD window_style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
+
+		RECT windowRect, clientRect;
+
+		if (!(args & RGFW_NO_BORDER)) {
+			window_style |= WS_CAPTION | WS_SYSMENU | WS_BORDER | WS_VISIBLE | WS_MINIMIZEBOX;
+
+			if (!(args & RGFW_NO_RESIZE))
+				window_style |= WS_SIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME;
+		} else
+			window_style |= WS_POPUP | WS_VISIBLE | WS_SYSMENU | WS_MINIMIZEBOX;
+
+		HWND dummyWin = CreateWindowA(Class.lpszClassName, name, window_style, win->r.x, win->r.y, win->r.w, win->r.h, 0, 0, inh, 0);
+
+		GetWindowRect(dummyWin, &windowRect);
+		GetClientRect(dummyWin, &clientRect);
+
+		win->src.hOffset = (windowRect.bottom - windowRect.top) - (clientRect.bottom - clientRect.top);
+		win->src.window = CreateWindowA(Class.lpszClassName, name, window_style, win->r.x, win->r.y, win->r.w, win->r.h + win->src.hOffset, 0, 0, inh, 0);
+
+		if (args & RGFW_TRANSPARENT_WINDOW) {
+			SetWindowLongA(win->src.window, GWL_EXSTYLE, GetWindowLongA(win->src.window, GWL_EXSTYLE) | WS_EX_LAYERED);
+		}
+		if (args & RGFW_ALLOW_DND) {
+			win->src.winArgs |= RGFW_ALLOW_DND;
+			DragAcceptFiles(win->src.window, TRUE);
+		}
+		win->src.hdc = GetDC(win->src.window);
+
+#ifdef RGFW_DIRECTX
+		assert(FAILED(CreateDXGIFactory(&__uuidof(IDXGIFactory), (void**) &RGFW_dxInfo.pFactory)) == 0);
+
+		if (FAILED(RGFW_dxInfo.pFactory->lpVtbl->EnumAdapters(RGFW_dxInfo.pFactory, 0, &RGFW_dxInfo.pAdapter))) {
+			fprintf(stderr, "Failed to enumerate DXGI adapters\n");
+			RGFW_dxInfo.pFactory->lpVtbl->Release(RGFW_dxInfo.pFactory);
+			return NULL;
+		}
+
+		D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_0 };
+
+		if (FAILED(D3D11CreateDevice(RGFW_dxInfo.pAdapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, 0, featureLevels, 1, D3D11_SDK_VERSION, &RGFW_dxInfo.pDevice, NULL, &RGFW_dxInfo.pDeviceContext))) {
+			fprintf(stderr, "Failed to create Direct3D device\n");
+			RGFW_dxInfo.pAdapter->lpVtbl->Release(RGFW_dxInfo.pAdapter);
+			RGFW_dxInfo.pFactory->lpVtbl->Release(RGFW_dxInfo.pFactory);
+			return NULL;
+		}
+
+		DXGI_SWAP_CHAIN_DESC swapChainDesc = { 0 };
+		swapChainDesc.BufferCount = 1;
+		swapChainDesc.BufferDesc.Width = win->r.w;
+		swapChainDesc.BufferDesc.Height = win->r.h;
+		swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+		swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+		swapChainDesc.OutputWindow = win->src.window;
+		swapChainDesc.SampleDesc.Count = 1;
+		swapChainDesc.SampleDesc.Quality = 0;
+		swapChainDesc.Windowed = TRUE;
+		RGFW_dxInfo.pFactory->lpVtbl->CreateSwapChain(RGFW_dxInfo.pFactory, (IUnknown*) RGFW_dxInfo.pDevice, &swapChainDesc, &win->src.swapchain);
+
+		ID3D11Texture2D* pBackBuffer;
+		win->src.swapchain->lpVtbl->GetBuffer(win->src.swapchain, 0, &__uuidof(ID3D11Texture2D), (LPVOID*) &pBackBuffer);
+		RGFW_dxInfo.pDevice->lpVtbl->CreateRenderTargetView(RGFW_dxInfo.pDevice, (ID3D11Resource*) pBackBuffer, NULL, &win->src.renderTargetView);
+		pBackBuffer->lpVtbl->Release(pBackBuffer);
+
+		D3D11_TEXTURE2D_DESC depthStencilDesc = { 0 };
+		depthStencilDesc.Width = win->r.w;
+		depthStencilDesc.Height = win->r.h;
+		depthStencilDesc.MipLevels = 1;
+		depthStencilDesc.ArraySize = 1;
+		depthStencilDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
+		depthStencilDesc.SampleDesc.Count = 1;
+		depthStencilDesc.SampleDesc.Quality = 0;
+		depthStencilDesc.Usage = D3D11_USAGE_DEFAULT;
+		depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
+
+		ID3D11Texture2D* pDepthStencilTexture = NULL;
+		RGFW_dxInfo.pDevice->lpVtbl->CreateTexture2D(RGFW_dxInfo.pDevice, &depthStencilDesc, NULL, &pDepthStencilTexture);
+
+		D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc = { 0 };
+		depthStencilViewDesc.Format = depthStencilDesc.Format;
+		depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
+		depthStencilViewDesc.Texture2D.MipSlice = 0;
+
+		RGFW_dxInfo.pDevice->lpVtbl->CreateDepthStencilView(RGFW_dxInfo.pDevice, (ID3D11Resource*) pDepthStencilTexture, &depthStencilViewDesc, &win->src.pDepthStencilView);
+
+		pDepthStencilTexture->lpVtbl->Release(pDepthStencilTexture);
+
+		RGFW_dxInfo.pDeviceContext->lpVtbl->OMSetRenderTargets(RGFW_dxInfo.pDeviceContext, 1, &win->src.renderTargetView, win->src.pDepthStencilView);
+#endif
+
+#ifdef RGFW_OPENGL 
+		HDC dummy_dc = GetDC(dummyWin);
+
+		PIXELFORMATDESCRIPTOR pfd = {
+			.nSize = sizeof(pfd),
+			.nVersion = 1,
+			.iPixelType = PFD_TYPE_RGBA,
+			.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
+			.cColorBits = 32,
+			.cAlphaBits = 8,
+			.iLayerType = PFD_MAIN_PLANE,
+			.cDepthBits = 24,
+			.cStencilBits = 8,
+		};
+
+		int pixel_format = ChoosePixelFormat(dummy_dc, &pfd);
+		SetPixelFormat(dummy_dc, pixel_format, &pfd);
+
+		HGLRC dummy_context = wglCreateContext(dummy_dc);
+		wglMakeCurrent(dummy_dc, dummy_context);
+
+		if (wglChoosePixelFormatARB == NULL) {
+			wglCreateContextAttribsARB = (wglCreateContextAttribsARB_type) wglGetProcAddress("wglCreateContextAttribsARB");
+			wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC) wglGetProcAddress("wglChoosePixelFormatARB");
+		}
+
+		wglMakeCurrent(dummy_dc, 0);
+		wglDeleteContext(dummy_context);
+		ReleaseDC(dummyWin, dummy_dc);
+
+		if (wglCreateContextAttribsARB != NULL) {
+			PIXELFORMATDESCRIPTOR pfd = { sizeof(pfd), 1, PFD_TYPE_RGBA, PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, 32, 8, PFD_MAIN_PLANE, 24, 8 };
+
+			if (args & RGFW_OPENGL_SOFTWARE)
+				pfd.dwFlags |= PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED;
+
+			if (wglChoosePixelFormatARB != NULL) {
+				i32* pixel_format_attribs = (i32*)RGFW_initAttribs(args & RGFW_OPENGL_SOFTWARE);
+
+				int pixel_format;
+				UINT num_formats;
+				wglChoosePixelFormatARB(win->src.hdc, pixel_format_attribs, 0, 1, &pixel_format, &num_formats);
+				if (!num_formats) {
+					printf("Failed to set the OpenGL 3.3 pixel format.\n");
+				}
+
+				DescribePixelFormat(win->src.hdc, pixel_format, sizeof(pfd), &pfd);
+				if (!SetPixelFormat(win->src.hdc, pixel_format, &pfd)) {
+					printf("Failed to set the OpenGL 3.3 pixel format.\n");
+				}
+			}
+
+			u32 index = 0;
+			i32 attribs[40];
+#define  WGL_CONTEXT_CORE_PROFILE_BIT_ARB        0x00000001
+			SET_ATTRIB(WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB);
+
+			if (RGFW_majorVersion || RGFW_minorVersion) {
+				SET_ATTRIB(WGL_CONTEXT_MAJOR_VERSION_ARB, RGFW_majorVersion);
+				SET_ATTRIB(WGL_CONTEXT_MINOR_VERSION_ARB, RGFW_minorVersion);
+			}
+
+			SET_ATTRIB(WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB);
+
+			if (RGFW_majorVersion || RGFW_minorVersion) {
+				SET_ATTRIB(WGL_CONTEXT_MAJOR_VERSION_ARB, RGFW_majorVersion);
+				SET_ATTRIB(WGL_CONTEXT_MINOR_VERSION_ARB, RGFW_minorVersion);
+			}
+
+			SET_ATTRIB(0, 0);
+
+			win->src.rSurf = wglCreateContextAttribsARB(win->src.hdc, NULL, attribs);
+		} else {
+			fprintf(stderr, "Failed to create an accelerated OpenGL Context\n");
+
+			int pixel_format = ChoosePixelFormat(win->src.hdc, &pfd);
+			SetPixelFormat(win->src.hdc, pixel_format, &pfd);
+
+			win->src.rSurf = wglCreateContext(win->src.hdc);
+		}
+		
+		wglMakeCurrent(win->src.hdc, win->src.rSurf);
+		wglShareLists(RGFW_root->src.rSurf, win->src.rSurf);
+#endif
+
+#ifdef RGFW_OSMESA
+#ifdef RGFW_LINK_OSM ESA
+		OSMesaMakeCurrentSource = (PFN_OSMesaMakeCurrent) GetProcAddress(win->src.hdc, "OSMesaMakeCurrent");
+		OSMesaCreateContextSource = (PFN_OSMesaCreateContext) GetProcAddress(win->src.hdc, "OSMesaCreateContext");
+		OSMesaDestroyContextSource = (PFN_OSMesaDestroyContext) GetProcAddress(win->src.hdc, "OSMesaDestroyContext");
+#endif
+#endif
+
+#ifdef RGFW_OPENGL
+		ReleaseDC(win->src.window, win->src.hdc);
+		win->src.hdc = GetDC(win->src.window);
+		wglMakeCurrent(win->src.hdc, win->src.rSurf);
+#endif
+
+		DestroyWindow(dummyWin);
+		RGFW_init_buffer(win);
+
+#ifdef RGFW_VULKAN
+		RGFW_initVulkan(win);
+#endif
+
+		if (args & RGFW_SCALE_TO_MONITOR)
+			RGFW_window_scaleToMonitor(win);
+
+#ifdef RGFW_EGL
+		RGFW_createOpenGLContext(win);
+#endif
+
+		if (args & RGFW_HIDE_MOUSE)
+			RGFW_window_showMouse(win, 0);
+
+		ShowWindow(win->src.window, SW_SHOWNORMAL);
+
+		return win;
+	}
+
+
+	RGFW_area RGFW_getScreenSize(void) {
+		return RGFW_AREA(GetDeviceCaps(GetDC(NULL), HORZRES), GetDeviceCaps(GetDC(NULL), VERTRES));
+	}
+
+	RGFW_vector RGFW_getGlobalMousePoint(void) {
+		POINT p;
+		GetCursorPos(&p);
+
+		return RGFW_VECTOR(p.x, p.y);
+	}
+
+	void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) {
+		assert(win != NULL);
+		win->src.minSize = a;
+	}
+
+	void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) {
+		assert(win != NULL);
+		win->src.maxSize = a;
+	}
+
+
+	void RGFW_window_minimize(RGFW_window* win) {
+		assert(win != NULL);
+
+		ShowWindow(win->src.window, SW_MINIMIZE);
+	}
+
+	void RGFW_window_restore(RGFW_window* win) {
+		assert(win != NULL);
+
+		ShowWindow(win->src.window, SW_RESTORE);
+	}
+
+	static i32 RGFW_checkXInput(RGFW_Event* e) {
+		static WORD buttons[4];
+		static BYTE triggers[4][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
+
+		size_t i;
+		for (i = 0; i < 4; i++) {
+			XINPUT_STATE state;
+			if (XInputGetState == NULL ||
+				XInputGetState((DWORD) i, &state) == ERROR_DEVICE_NOT_CONNECTED
+			)
+				return 0;
+
+			e->button = 0;
+			if (state.Gamepad.wButtons & XINPUT_GAMEPAD_A && !(buttons[i] & XINPUT_GAMEPAD_A)) {
+				e->button = RGFW_JS_A;
+				e->type = RGFW_jsButtonPressed;
+				buttons[i] = state.Gamepad.wButtons;
+				return 1;
+			} else if (state.Gamepad.wButtons & XINPUT_GAMEPAD_B && !(buttons[i] & XINPUT_GAMEPAD_B))
+				e->button = RGFW_JS_B;
+			else if (state.Gamepad.wButtons & XINPUT_GAMEPAD_Y && !(buttons[i] & XINPUT_GAMEPAD_Y))
+				e->button = RGFW_JS_Y;
+			else if (state.Gamepad.wButtons & XINPUT_GAMEPAD_X && !(buttons[i] & XINPUT_GAMEPAD_X))
+				e->button = RGFW_JS_X;
+			else if (state.Gamepad.wButtons & XINPUT_GAMEPAD_START && !(buttons[i] & XINPUT_GAMEPAD_START))
+				e->button = RGFW_JS_START;
+			else if (state.Gamepad.wButtons & XINPUT_GAMEPAD_BACK && !(buttons[i] & XINPUT_GAMEPAD_BACK))
+				e->button = RGFW_JS_SELECT;
+			else if (state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP && !(buttons[i] & XINPUT_GAMEPAD_DPAD_UP))
+				e->button = RGFW_JS_UP;
+			else if (state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN && !(buttons[i] & XINPUT_GAMEPAD_DPAD_DOWN))
+				e->button = RGFW_JS_DOWN;
+			else if (state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT && !(buttons[i] & XINPUT_GAMEPAD_DPAD_LEFT))
+				e->button = RGFW_JS_LEFT;
+			else if (state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT && !(buttons[i] & XINPUT_GAMEPAD_DPAD_RIGHT))
+				e->button = RGFW_JS_RIGHT;
+			else if (state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER && !(buttons[i] & XINPUT_GAMEPAD_LEFT_SHOULDER))
+				e->button = RGFW_JS_L1;
+			else if (state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER && !(buttons[i] & XINPUT_GAMEPAD_RIGHT_SHOULDER))
+				e->button = RGFW_JS_R1;
+			else if (state.Gamepad.bLeftTrigger && triggers[i][0] == 0)
+				e->button = RGFW_JS_L2;
+			else if (state.Gamepad.bRightTrigger && triggers[i][1] == 0)
+				e->button = RGFW_JS_R2;
+
+			triggers[i][0] = state.Gamepad.bLeftTrigger;
+			triggers[i][1] = state.Gamepad.bRightTrigger;
+
+			if (e->button) {
+				buttons[i] = state.Gamepad.wButtons;
+				e->type = RGFW_jsButtonPressed;
+				return 1;
+			}
+
+			if (!(state.Gamepad.wButtons & XINPUT_GAMEPAD_A) && (buttons[i] & XINPUT_GAMEPAD_A)) {
+				e->button = RGFW_JS_A;
+				e->type = RGFW_jsButtonReleased;
+				buttons[i] = state.Gamepad.wButtons;
+				return 1;
+			} else if (!(state.Gamepad.wButtons & XINPUT_GAMEPAD_B) && (buttons[i] & XINPUT_GAMEPAD_B))
+				e->button = RGFW_JS_B;
+			else if (!(state.Gamepad.wButtons & XINPUT_GAMEPAD_Y) && (buttons[i] & XINPUT_GAMEPAD_Y))
+				e->button = RGFW_JS_Y;
+			else if (!(state.Gamepad.wButtons & XINPUT_GAMEPAD_X) && (buttons[i] & XINPUT_GAMEPAD_X))
+				e->button = RGFW_JS_X;
+			else if (!(state.Gamepad.wButtons & XINPUT_GAMEPAD_START) && (buttons[i] & XINPUT_GAMEPAD_START))
+				e->button = RGFW_JS_START;
+			else if (!(state.Gamepad.wButtons & XINPUT_GAMEPAD_BACK) && (buttons[i] & XINPUT_GAMEPAD_BACK))
+				e->button = RGFW_JS_SELECT;
+			else if (!(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP) && (buttons[i] & XINPUT_GAMEPAD_DPAD_UP))
+				e->button = RGFW_JS_UP;
+			else if (!(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN) && (buttons[i] & XINPUT_GAMEPAD_DPAD_DOWN))
+				e->button = RGFW_JS_DOWN;
+			else if (!(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT) && (buttons[i] & XINPUT_GAMEPAD_DPAD_LEFT))
+				e->button = RGFW_JS_LEFT;
+			else if (!(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) && (buttons[i] & XINPUT_GAMEPAD_DPAD_RIGHT))
+				e->button = RGFW_JS_RIGHT;
+			else if (!(state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER) && (buttons[i] & XINPUT_GAMEPAD_LEFT_SHOULDER))
+				e->button = RGFW_JS_L1;
+			else if (!(state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER) && (buttons[i] & XINPUT_GAMEPAD_RIGHT_SHOULDER))
+				e->button = RGFW_JS_R1;
+			else if (state.Gamepad.bLeftTrigger == 0 && triggers[i][0] != 0)
+				e->button = RGFW_JS_L2;
+			else if (state.Gamepad.bRightTrigger == 0 && triggers[i][1] != 0)
+				e->button = RGFW_JS_R2;
+			
+			buttons[i] = state.Gamepad.wButtons;
+
+			if (e->button) {
+				e->type = RGFW_jsButtonReleased;
+				return 1;
+			}
+#define INPUT_DEADZONE  ( 0.24f * (float)(0x7FFF) )  // Default to 24% of the +/- 32767 range.   This is a reasonable default value but can be altered if needed.
+
+			if ((state.Gamepad.sThumbLX < INPUT_DEADZONE &&
+				state.Gamepad.sThumbLX > -INPUT_DEADZONE) &&
+				(state.Gamepad.sThumbLY < INPUT_DEADZONE &&
+					state.Gamepad.sThumbLY > -INPUT_DEADZONE))
+			{
+				state.Gamepad.sThumbLX = 0;
+				state.Gamepad.sThumbLY = 0;
+			}
+
+			if ((state.Gamepad.sThumbRX < INPUT_DEADZONE &&
+				state.Gamepad.sThumbRX > -INPUT_DEADZONE) &&
+				(state.Gamepad.sThumbRY < INPUT_DEADZONE &&
+					state.Gamepad.sThumbRY > -INPUT_DEADZONE))
+			{
+				state.Gamepad.sThumbRX = 0;
+				state.Gamepad.sThumbRY = 0;
+			}
+
+			e->axisesCount = 2;
+			RGFW_vector axis1 = RGFW_VECTOR(state.Gamepad.sThumbLX, state.Gamepad.sThumbLY);
+			RGFW_vector axis2 = RGFW_VECTOR(state.Gamepad.sThumbRX, state.Gamepad.sThumbRY);
+
+			if (axis1.x != e->axis[0].x || axis1.y != e->axis[0].y || axis2.x != e->axis[1].x || axis2.y != e->axis[1].y) {
+				e->type = RGFW_jsAxisMove;
+
+				e->axis[0] = axis1;
+				e->axis[1] = axis2;
+
+				return 1;
+			}
+
+			e->axis[0] = axis1;
+			e->axis[1] = axis2;
+		}
+
+		return 0;
+	}
+
+	RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) {
+		assert(win != NULL);
+
+		MSG msg;
+
+		if (RGFW_eventWindow.src.window == win->src.window) {
+			if (RGFW_eventWindow.r.x != -1) {
+				win->r.x = RGFW_eventWindow.r.x;
+				win->r.y = RGFW_eventWindow.r.y;
+			}
+
+			if (RGFW_eventWindow.r.w != -1) {
+				win->r.w = RGFW_eventWindow.r.w;
+				win->r.h = RGFW_eventWindow.r.h;
+			}
+
+			win->event.type = RGFW_windowAttribsChange;
+
+			RGFW_eventWindow.src.window = NULL;
+			RGFW_eventWindow.r = RGFW_RECT(-1, -1, -1, -1);
+
+			return &win->event;
+		}
+
+		if (win->event.droppedFilesCount) {
+			u32 i;
+			for (i = 0; i < win->event.droppedFilesCount; i++)
+				win->event.droppedFiles[i][0] = '\0';
+		}
+
+		win->event.droppedFilesCount = 0;
+
+		win->event.inFocus = (GetForegroundWindow() == win->src.window);
+
+		if (RGFW_checkXInput(&win->event))
+			return &win->event;
+
+		if (win->event.type == RGFW_quit)
+			return NULL;
+
+		static BYTE keyboardState[256];
+		GetKeyboardState(keyboardState);
+
+		if (PeekMessageA(&msg, win->src.window, 0u, 0u, PM_REMOVE)) {
+			switch (msg.message) {
+			case WM_CLOSE:
+			case WM_QUIT:
+				win->event.type = RGFW_quit;
+				break;
+
+			case WM_KEYUP:
+				win->event.keyCode = (u32) msg.wParam;
+				strncpy(win->event.keyName, RGFW_keyCodeTokeyStr(msg.lParam), 16);
+				if (GetKeyState(VK_SHIFT) & 0x8000) {
+					ToAscii((UINT) msg.wParam, MapVirtualKey((UINT) msg.wParam, MAPVK_VK_TO_CHAR),
+						keyboardState, (LPWORD) win->event.keyName, 0);
+				}
+
+				win->event.type = RGFW_keyReleased;
+				break;
+
+			case WM_KEYDOWN:
+				win->event.keyCode = (u32) msg.wParam;
+				strncpy(win->event.keyName, RGFW_keyCodeTokeyStr(msg.lParam), 16);
+				if (GetKeyState(VK_SHIFT) & 0x8000) {
+					ToAscii((UINT) msg.wParam, MapVirtualKey((UINT) msg.wParam, MAPVK_VK_TO_CHAR),
+						keyboardState, (LPWORD) win->event.keyName, 0);
+				}
+
+				win->event.type = RGFW_keyPressed;
+				break;
+
+			case WM_MOUSEMOVE:
+				win->event.point.x = GET_X_LPARAM(msg.lParam);
+				win->event.point.y = GET_Y_LPARAM(msg.lParam);
+
+				win->event.type = RGFW_mousePosChanged;
+				break;
+
+			case WM_LBUTTONDOWN:
+				win->event.button = RGFW_mouseLeft;
+				win->event.type = RGFW_mouseButtonPressed;
+				break;
+			case WM_RBUTTONDOWN:
+				win->event.button = RGFW_mouseRight;
+				win->event.type = RGFW_mouseButtonPressed;
+				break;
+			case WM_MBUTTONDOWN:
+				win->event.button = RGFW_mouseMiddle;
+				win->event.type = RGFW_mouseButtonPressed;
+				break;
+
+			case WM_MOUSEWHEEL:
+				if (msg.wParam > 0)
+					win->event.button = RGFW_mouseScrollUp;
+				else
+					win->event.button = RGFW_mouseScrollDown;
+
+				win->event.scroll = (SHORT) HIWORD(msg.wParam) / (double) WHEEL_DELTA;
+
+				win->event.type = RGFW_mouseButtonPressed;
+				break;
+
+			case WM_LBUTTONUP:
+				win->event.button = RGFW_mouseLeft;
+				win->event.type = RGFW_mouseButtonReleased;
+				break;
+			case WM_RBUTTONUP:
+				win->event.button = RGFW_mouseRight;
+				win->event.type = RGFW_mouseButtonReleased;
+				break;
+			case WM_MBUTTONUP:
+				win->event.button = RGFW_mouseMiddle;
+				win->event.type = RGFW_mouseButtonReleased;
+				break;
+
+				/*
+					much of this event is source from glfw
+				*/
+			case WM_DROPFILES: {
+				win->event.type = RGFW_dnd;
+
+				HDROP drop = (HDROP) msg.wParam;
+				POINT pt;
+				u32 i;
+
+				win->event.droppedFilesCount = DragQueryFileW(drop, 0xffffffff, NULL, 0);
+				//win->event.droppedFiles = (char**)RGFW_CALLOC(win->event.droppedFilesCount, sizeof(char*));
+
+				/* Move the mouse to the position of the drop */
+				DragQueryPoint(drop, &pt);
+
+				win->event.point.x = pt.x;
+				win->event.point.y = pt.y;
+
+				for (i = 0; i < win->event.droppedFilesCount; i++) {
+					const UINT length = DragQueryFileW(drop, i, NULL, 0);
+					WCHAR* buffer = (WCHAR*) RGFW_CALLOC((size_t) length + 1, sizeof(WCHAR));
+
+					DragQueryFileW(drop, i, buffer, length + 1);
+					strcpy(win->event.droppedFiles[i], createUTF8FromWideStringWin32(buffer));
+
+					RGFW_FREE(buffer);
+				}
+
+				DragFinish(drop);
+			}
+							 break;
+			case WM_GETMINMAXINFO:
+			{
+				if (win->src.maxSize.w == 0 && win->src.maxSize.h == 0)
+					break;
+
+				MINMAXINFO* mmi = (MINMAXINFO*) msg.lParam;
+				mmi->ptMinTrackSize.x = win->src.minSize.w;
+				mmi->ptMinTrackSize.y = win->src.minSize.h;
+				mmi->ptMaxTrackSize.x = win->src.maxSize.w;
+				mmi->ptMaxTrackSize.y = win->src.maxSize.h;
+				return 0;
+			}
+			default:
+				win->event.type = 0;
+				break;
+			}
+
+			TranslateMessage(&msg);
+			DispatchMessageA(&msg);
+		}
+
+		else
+			win->event.type = 0;
+
+		RGFW_vector mouse = RGFW_getGlobalMousePoint();
+		if (win->src.winArgs & RGFW_HOLD_MOUSE && win->event.inFocus &&
+			(mouse.x != win->r.x + (win->r.w / 2) || mouse.y != win->r.y + (win->r.h / 2))) {
+			RGFW_window_moveMouse(win, RGFW_VECTOR(win->r.x + (win->r.w / 2), win->r.y + (win->r.h / 2)));
+		}
+
+		win->event.lockState = 0;
+
+		if ((GetKeyState(VK_CAPITAL) & 0x0001) != 0)
+			win->event.lockState |= RGFW_CAPSLOCK;
+		if ((GetKeyState(VK_NUMLOCK) & 0x0001) != 0)
+			win->event.lockState |= RGFW_NUMLOCK;
+		if ((GetKeyState(VK_SCROLL) & 0x0001) != 0)
+			win->event.lockState |= 3;
+
+
+		if (!IsWindow(win->src.window))
+			win->event.type = RGFW_quit;
+
+		if (win->event.type)
+			return &win->event;
+		else
+			return NULL;
+	}
+
+	u8 RGFW_window_isFullscreen(RGFW_window* win) {
+		assert(win != NULL);
+
+		WINDOWPLACEMENT placement = { 0 };
+		GetWindowPlacement(win->src.window, &placement);
+		return placement.showCmd == SW_SHOWMAXIMIZED;
+	}
+
+	u8 RGFW_window_isHidden(RGFW_window* win) {
+		assert(win != NULL);
+
+		return IsWindowVisible(win->src.window) == 0 && !RGFW_window_isMinimized(win);
+	}
+
+	u8 RGFW_window_isMinimized(RGFW_window* win) {
+		assert(win != NULL);
+
+		WINDOWPLACEMENT placement = { 0 };
+		GetWindowPlacement(win->src.window, &placement);
+		return placement.showCmd == SW_SHOWMINIMIZED;
+	}
+
+	u8 RGFW_window_isMaximized(RGFW_window* win) {
+		assert(win != NULL);
+
+		WINDOWPLACEMENT placement = { 0 };
+		GetWindowPlacement(win->src.window, &placement);
+		return placement.showCmd == SW_SHOWMAXIMIZED;
+	}
+
+	typedef struct { int iIndex; HMONITOR hMonitor; } RGFW_mInfo;
+	BOOL CALLBACK GetMonitorByHandle(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) {
+		RGFW_mInfo* info = (RGFW_mInfo*) dwData;
+		if (info->hMonitor == hMonitor)
+			return FALSE;
+
+		info->iIndex++;
+		return TRUE;
+	}
+
+	RGFW_monitor win32CreateMonitor(HMONITOR src) {
+		RGFW_monitor monitor;
+		MONITORINFO monitorInfo;
+
+		monitorInfo.cbSize = sizeof(MONITORINFO);
+		GetMonitorInfoA(src, &monitorInfo);
+
+		RGFW_mInfo info;
+		info.iIndex = 0;
+		info.hMonitor = src;
+
+		/* get the monitor's index */
+		if (EnumDisplayMonitors(NULL, NULL, GetMonitorByHandle, (LPARAM) &info)) {
+			DISPLAY_DEVICEA dd;
+			dd.cb = sizeof(dd);
+
+			/* loop through the devices until you find a device with the monitor's index */
+			size_t deviceIndex;
+			for (deviceIndex = 0; EnumDisplayDevicesA(0, (DWORD) deviceIndex, &dd, 0); deviceIndex++) {
+				char* deviceName = dd.DeviceName;
+				if (EnumDisplayDevicesA(deviceName, info.iIndex, &dd, 0)) {
+					strcpy(monitor.name, dd.DeviceString); /* copy the monitor's name */
+					break;
+				}
+			}
+		}
+
+		monitor.rect.x = monitorInfo.rcWork.left;
+		monitor.rect.y = monitorInfo.rcWork.top;
+		monitor.rect.w = monitorInfo.rcWork.right - monitorInfo.rcWork.left;
+		monitor.rect.h = monitorInfo.rcWork.bottom - monitorInfo.rcWork.top;
+
+#ifndef RGFW_NO_DPI
+		if (GetDpiForMonitor != NULL) {
+			u32 x, y;
+			GetDpiForMonitor(src, MDT_ANGULAR_DPI, &x, &y);
+			monitor.scaleX = (float) (x) / (float) USER_DEFAULT_SCREEN_DPI;
+			monitor.scaleY = (float) (y) / (float) USER_DEFAULT_SCREEN_DPI;
+		}
+#endif
+
+		HDC hdc = GetDC(NULL);
+		/* get pixels per inch */
+		i32 ppiX = GetDeviceCaps(hdc, LOGPIXELSX);
+		i32 ppiY = GetDeviceCaps(hdc, LOGPIXELSY);
+		ReleaseDC(NULL, hdc);
+
+		/* Calculate physical height in inches */
+		monitor.physW = GetSystemMetrics(SM_CYSCREEN) / (float) ppiX;
+		monitor.physH = GetSystemMetrics(SM_CXSCREEN) / (float) ppiY;
+
+		return monitor;
+	}
+
+	RGFW_monitor RGFW_monitors[6];
+	BOOL CALLBACK GetMonitorHandle(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) {
+		RGFW_mInfo* info = (RGFW_mInfo*) dwData;
+
+		if (info->iIndex >= 6)
+			return FALSE;
+
+		RGFW_monitors[info->iIndex] = win32CreateMonitor(hMonitor);
+		info->iIndex++;
+
+		return TRUE;
+	}
+
+	RGFW_monitor RGFW_getPrimaryMonitor(void) {
+		return win32CreateMonitor(MonitorFromPoint((POINT) { 0, 0 }, MONITOR_DEFAULTTOPRIMARY));
+	}
+
+	RGFW_monitor* RGFW_getMonitors(void) {
+		RGFW_mInfo info;
+		info.iIndex = 0;
+		while (EnumDisplayMonitors(NULL, NULL, GetMonitorHandle, (LPARAM) &info));
+
+		return RGFW_monitors;
+	}
+
+	RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) {
+		HMONITOR src = MonitorFromWindow(win->src.window, MONITOR_DEFAULTTOPRIMARY);
+		return win32CreateMonitor(src);
+	}
+
+	u8 RGFW_isPressedI(RGFW_window* win, u32 key) {
+		if (win != NULL && !win->event.inFocus)
+			return 0;
+
+		if (GetAsyncKeyState(key) & 0x8000)
+			return 1;
+		else return 0;
+	}
+
+	HICON RGFW_loadHandleImage(RGFW_window* win, u8* src, RGFW_area a, BOOL icon) {
+		assert(win != NULL);
+
+		u32 i;
+		HDC dc;
+		HICON handle;
+		HBITMAP color, mask;
+		BITMAPV5HEADER bi;
+		ICONINFO ii;
+		u8* target = NULL;
+		u8* source = src;
+
+		ZeroMemory(&bi, sizeof(bi));
+		bi.bV5Size = sizeof(bi);
+		bi.bV5Width = a.w;
+		bi.bV5Height = -((LONG) a.h);
+		bi.bV5Planes = 1;
+		bi.bV5BitCount = 32;
+		bi.bV5Compression = BI_BITFIELDS;
+		bi.bV5RedMask = 0x00ff0000;
+		bi.bV5GreenMask = 0x0000ff00;
+		bi.bV5BlueMask = 0x000000ff;
+		bi.bV5AlphaMask = 0xff000000;
+
+		dc = GetDC(NULL);
+		color = CreateDIBSection(dc,
+			(BITMAPINFO*) &bi,
+			DIB_RGB_COLORS,
+			(void**) &target,
+			NULL,
+			(DWORD) 0);
+		ReleaseDC(NULL, dc);
+
+		mask = CreateBitmap(a.w, a.h, 1, 1, NULL);
+
+		for (i = 0; i < a.w * a.h; i++) {
+			target[0] = source[2];
+			target[1] = source[1];
+			target[2] = source[0];
+			target[3] = source[3];
+			target += 4;
+			source += 4;
+		}
+
+		ZeroMemory(&ii, sizeof(ii));
+		ii.fIcon = icon;
+		ii.xHotspot = 0;
+		ii.yHotspot = 0;
+		ii.hbmMask = mask;
+		ii.hbmColor = color;
+
+		handle = CreateIconIndirect(&ii);
+
+		DeleteObject(color);
+		DeleteObject(mask);
+
+		return handle;
+	}
+
+	void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels) {
+		assert(win != NULL);
+
+		HCURSOR cursor = (HCURSOR) RGFW_loadHandleImage(win, image, a, FALSE);
+		SetClassLongPtrA(win->src.window, GCLP_HCURSOR, (LPARAM) cursor);
+		SetCursor(cursor);
+		DestroyCursor(cursor);
+	}
+
+	void RGFW_window_setMouseDefault(RGFW_window* win) {
+		RGFW_window_setMouseStandard(win, 32512);
+	}
+
+	void RGFW_window_setMouseStandard(RGFW_window* win, i32 mouse) {
+		assert(win != NULL);
+
+		char* icon = MAKEINTRESOURCEA(mouse);
+
+		SetClassLongPtrA(win->src.window, GCLP_HCURSOR, (LPARAM) LoadCursorA(NULL, icon));
+		SetCursor(LoadCursorA(NULL, icon));
+	}
+
+	void RGFW_window_hide(RGFW_window* win) {
+		ShowWindow(win->src.window, SW_HIDE);
+	}
+
+	void RGFW_window_show(RGFW_window* win) {
+		ShowWindow(win->src.window, SW_RESTORE);
+	}
+
+	void RGFW_window_close(RGFW_window* win) {
+		assert(win != NULL);
+
+#ifdef RGFW_VULKAN
+		for (u32 i = 0; i < win->src.image_count; i++) {
+			vkDestroyFramebuffer(RGFW_vulkan_info.device, RGFW_vulkan_info.framebuffers[i], NULL);
+		}
+
+		for (u32 i = 0; i < win->src.image_count; i++) {
+			vkDestroyImageView(RGFW_vulkan_info.device, win->src.swapchain_image_views[i], NULL);
+		}
+
+		vkDestroySwapchainKHR(RGFW_vulkan_info.device, win->src.swapchain, NULL);
+		vkDestroySurfaceKHR(RGFW_vulkan_info.instance, win->src.rSurf, NULL);
+		free(win->src.swapchain_image_views);
+		free(win->src.swapchain_images);
+#endif
+
+#ifdef RGFW_EGL
+		RGFW_closeEGL(win);
+#endif
+
+		if (win == RGFW_root) {
+#ifdef RGFW_DIRECTX
+			RGFW_dxInfo.pDeviceContext->lpVtbl->Release(RGFW_dxInfo.pDeviceContext);
+			RGFW_dxInfo.pDevice->lpVtbl->Release(RGFW_dxInfo.pDevice);
+			RGFW_dxInfo.pAdapter->lpVtbl->Release(RGFW_dxInfo.pAdapter);
+			RGFW_dxInfo.pFactory->lpVtbl->Release(RGFW_dxInfo.pFactory);
+#endif
+		
+			if (RGFW_XInput_dll != NULL) {
+				FreeLibrary(RGFW_XInput_dll);
+				RGFW_XInput_dll = NULL;
+			}
+
+			#ifndef RGFW_NO_DPI
+			if (RGFW_Shcore_dll != NULL) {
+				FreeLibrary(RGFW_Shcore_dll);
+				RGFW_Shcore_dll = NULL;
+			}
+			#endif
+
+			if (wglinstance != NULL) {
+				FreeLibrary(wglinstance);
+				wglinstance = NULL;
+			}
+
+			RGFW_root = NULL;
+		}
+
+#ifdef RGFW_DIRECTX
+		win->src.swapchain->lpVtbl->Release(win->src.swapchain);
+		win->src.renderTargetView->lpVtbl->Release(win->src.renderTargetView);
+		win->src.pDepthStencilView->lpVtbl->Release(win->src.pDepthStencilView);
+#endif
+
+#ifdef RGFW_BUFFER
+		DeleteDC(win->src.hdcMem);
+		DeleteObject(win->src.bitmap);
+#endif
+
+#ifdef RGFW_OPENGL
+		wglDeleteContext((HGLRC) win->src.rSurf); /* delete opengl context */
+#endif
+		DeleteDC(win->src.hdc); /* delete device context */
+		DestroyWindow(win->src.window); /* delete window */
+
+#if defined(RGFW_OSMESA)
+		if (win->buffer != NULL)
+			RGFW_FREE(win->buffer);
+#endif
+
+#ifdef RGFW_ALLOC_DROPFILES
+		{
+			u32 i;
+			for (i = 0; i < RGFW_MAX_DROPS; i++)
+				RGFW_FREE(win->event.droppedFiles[i]);
+
+
+			RGFW_FREE(win->event.droppedFiles);
+		}
+#endif
+
+		RGFW_FREE(win);
+	}
+
+	void RGFW_window_move(RGFW_window* win, RGFW_vector v) {
+		assert(win != NULL);
+
+		win->r.x = v.x;
+		win->r.y = v.y;
+		SetWindowPos(win->src.window, HWND_TOP, win->r.x, win->r.y, 0, 0, SWP_NOSIZE);
+	}
+
+	void RGFW_window_resize(RGFW_window* win, RGFW_area a) {
+		assert(win != NULL);
+
+		win->r.w = a.w;
+		win->r.h = a.h;
+		SetWindowPos(win->src.window, HWND_TOP, 0, 0, win->r.w, win->r.h + win->src.hOffset, SWP_NOMOVE);
+	}
+
+
+	void RGFW_window_setName(RGFW_window* win, char* name) {
+		assert(win != NULL);
+
+		SetWindowTextA(win->src.window, name);
+	}
+
+	/* much of this function is sourced from GLFW */
+	void RGFW_window_setIcon(RGFW_window* win, u8* src, RGFW_area a, i32 channels) {
+		assert(win != NULL);
+
+		HICON handle = RGFW_loadHandleImage(win, src, a, TRUE);
+
+		SetClassLongPtrA(win->src.window, GCLP_HICON, (LPARAM) handle);
+
+		DestroyIcon(handle);
+	}
+
+	char* RGFW_readClipboard(size_t* size) {
+		/* Open the clipboard */
+		if (OpenClipboard(NULL) == 0)
+			return (char*) "";
+
+		/* Get the clipboard data as a Unicode string */
+		HANDLE hData = GetClipboardData(CF_UNICODETEXT);
+		if (hData == NULL) {
+			CloseClipboard();
+			return (char*) "";
+		}
+
+		wchar_t* wstr = (wchar_t*) GlobalLock(hData);
+
+		char* text;
+
+		{
+			setlocale(LC_ALL, "en_US.UTF-8");
+
+			size_t textLen = wcstombs(NULL, wstr, 0);
+			if (textLen == 0)
+				return (char*) "";
+
+			text = (char*) malloc((textLen * sizeof(char)) + 1);
+
+			wcstombs(text, wstr, (textLen) +1);
+
+			if (size != NULL)
+				*size = textLen + 1;
+		}
+
+		/* Release the clipboard data */
+		GlobalUnlock(hData);
+		CloseClipboard();
+
+		return text;
+	}
+
+	void RGFW_writeClipboard(const char* text, u32 textLen) {
+		HANDLE object;
+		WCHAR* buffer;
+
+		object = GlobalAlloc(GMEM_MOVEABLE, (1 + textLen) * sizeof(WCHAR));
+		if (!object)
+			return;
+
+		buffer = (WCHAR*) GlobalLock(object);
+		if (!buffer) {
+			GlobalFree(object);
+			return;
+		}
+
+		MultiByteToWideChar(CP_UTF8, 0, text, -1, buffer, textLen);
+		GlobalUnlock(object);
+
+		if (!OpenClipboard(RGFW_root->src.window)) {
+			GlobalFree(object);
+			return;
+		}
+
+		EmptyClipboard();
+		SetClipboardData(CF_UNICODETEXT, object);
+		CloseClipboard();
+	}
+
+	u16 RGFW_registerJoystick(RGFW_window* win, i32 jsNumber) {
+		assert(win != NULL);
+
+		return RGFW_registerJoystickF(win, (char*) "");
+	}
+
+	u16 RGFW_registerJoystickF(RGFW_window* win, char* file) {
+		assert(win != NULL);
+
+
+		return win->src.joystickCount - 1;
+	}
+
+	void RGFW_window_moveMouse(RGFW_window* win, RGFW_vector p) {
+		assert(win != NULL);
+
+		SetCursorPos(p.x, p.y);
+	}
+
+	char* createUTF8FromWideStringWin32(const WCHAR* source) {
+		char* target;
+		i32 size;
+
+		size = WideCharToMultiByte(CP_UTF8, 0, source, -1, NULL, 0, NULL, NULL);
+		if (!size) {
+			return NULL;
+		}
+
+		target = (char*) RGFW_CALLOC(size, 1);
+
+		if (!WideCharToMultiByte(CP_UTF8, 0, source, -1, target, size, NULL, NULL)) {
+			RGFW_FREE(target);
+			return NULL;
+		}
+
+		return target;
+	}
+
+#ifndef RGFW_NO_THREADS
+	RGFW_thread RGFW_createThread(void* (*function_ptr)(void*), void* args) { return CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) *function_ptr, args, 0, NULL); }
+	void RGFW_cancelThread(RGFW_thread thread) { CloseHandle((HANDLE) thread); }
+	void RGFW_joinThread(RGFW_thread thread) { WaitForSingleObject((HANDLE) thread, INFINITE); }
+	void RGFW_setThreadPriority(RGFW_thread thread, u8 priority) { SetThreadPriority((HANDLE) thread, priority); }
+#endif
+#endif
+
+#if defined(RGFW_MACOS)
+
+	void* RGFWnsglFramework = NULL;
+
+#ifdef RGFW_OPENGL
+	void* RGFW_getProcAddress(const char* procname) {
+		if (RGFWnsglFramework == NULL)
+			RGFWnsglFramework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));
+
+		CFStringRef symbolName = CFStringCreateWithCString(kCFAllocatorDefault, procname, kCFStringEncodingASCII);
+
+		void* symbol = CFBundleGetFunctionPointerForName(RGFWnsglFramework, symbolName);
+
+		CFRelease(symbolName);
+
+		return symbol;
+	}
+#endif
+
+	CVReturn displayCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* inNow, const CVTimeStamp* inOutputTime, CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* displayLinkContext) { return kCVReturnSuccess; }
+
+	RGFW_window* RGFW_windows[10];
+	u32 RGFW_windows_size = 0;
+
+	id NSWindow_delegate(RGFW_window* win) {
+		return (id) objc_msgSend_id(win->src.window, sel_registerName("delegate"));
+	}
+
+	u32 RGFW_OnClose(void* self) {
+		u32 i;
+		for (i = 0; i < RGFW_windows_size; i++)
+			if (RGFW_windows[i] && NSWindow_delegate(RGFW_windows[i]) == self) {
+				RGFW_windows[i]->event.type = RGFW_quit;
+				return true;
+			}
+
+		return true;
+	}
+
+	/* NOTE(EimaMei): Fixes the constant clicking when the app is running under a terminal. */
+	bool acceptsFirstResponder() { return true; }
+	bool performKeyEquivalent(NSEvent* event) { return true; }
+
+	NSDragOperation draggingEntered(id self, SEL sel, id sender) { return NSDragOperationCopy; }
+	NSDragOperation draggingUpdated(id self, SEL sel, id sender) { return NSDragOperationCopy; }
+	bool prepareForDragOperation(void) { return true; }
+
+	void RGFW__osxDraggingEnded(id self, SEL sel, id sender) { return; }
+
+	/* NOTE(EimaMei): Usually, you never need 'id self, SEL cmd' for C -> Obj-C methods. This isn't the case. */
+	bool performDragOperation(id self, SEL sel, id sender) {
+		NSWindow* window = objc_msgSend_id(sender, sel_registerName("draggingDestinationWindow"));
+		u32 i;
+		bool found = false;
+
+		for (i = 0; i < RGFW_windows_size; i++)
+			if (RGFW_windows[i]->src.window == window) {
+				found = true;
+				break;
+			}
+
+		if (!found)
+			i = 0;
+
+		Class* array[] = { objc_getClass("NSURL"), NULL };
+		char** droppedFiles = (char**) NSPasteboard_readObjectsForClasses(
+			(NSPasteboard*) objc_msgSend_id(sender, sel_registerName("draggingPasteboard")),
+			array, 1, NULL);
+
+		RGFW_windows[i]->event.droppedFilesCount = si_array_len(droppedFiles);
+
+		u32 y;
+
+		for (y = 0; y < RGFW_windows[i]->event.droppedFilesCount; y++)
+			strcpy(RGFW_windows[i]->event.droppedFiles[y], droppedFiles[y]);
+
+		RGFW_windows[i]->event.type = RGFW_dnd;
+
+		NSPoint p = *(NSPoint*) objc_msgSend_id(sender, sel_registerName("draggingLocation"));
+		RGFW_windows[i]->event.point.x = p.x;
+		RGFW_windows[i]->event.point.x = p.y;
+
+		return true;
+	}
+
+
+	NSApplication* NSApp = NULL;
+
+	static void NSMoveToResourceDir(void) {
+		/* sourced from glfw */
+		char resourcesPath[255];
+
+		CFBundleRef bundle = CFBundleGetMainBundle();
+		if (!bundle)
+			return;
+
+		CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(bundle);
+		CFStringRef last = CFURLCopyLastPathComponent(resourcesURL);
+
+		if (
+			CFStringCompare(CFSTR("Resources"), last, 0) != kCFCompareEqualTo ||
+			CFURLGetFileSystemRepresentation(resourcesURL, true, (u8*) resourcesPath, 255) == 0
+			) {
+			CFRelease(last);
+			CFRelease(resourcesURL);
+			return;
+		}
+
+		CFRelease(last);
+		CFRelease(resourcesURL);
+
+		chdir(resourcesPath);
+	}
+
+
+	NSSize RGFW__osxWindowResize(void* self, SEL sel, NSSize frameSize) {
+		u32 i;
+		for (i = 0; i < RGFW_windows_size; i++) {
+			if (RGFW_windows[i] && NSWindow_delegate(RGFW_windows[i]) == self) {
+				RGFW_windows[i]->r.w = frameSize.width;
+				RGFW_windows[i]->r.h = frameSize.height;
+				RGFW_windows[i]->event.type = RGFW_windowAttribsChange;
+
+				return frameSize;
+			}
+		}
+
+		return frameSize;
+	}
+
+	void RGFW__osxWindowMove(void* self, SEL sel) {
+		u32 i;
+		for (i = 0; i < RGFW_windows_size; i++) {
+			if (RGFW_windows[i] && NSWindow_delegate(RGFW_windows[i]) == self) {
+				NSRect frame = ((NSRect(*)(id, SEL))abi_objc_msgSend_stret)(RGFW_windows[i]->src.window, sel_registerName("frame"));
+				RGFW_windows[i]->r.x = (i32) frame.origin.x;
+				RGFW_windows[i]->r.y = (i32) frame.origin.y;
+
+				RGFW_windows[i]->event.type = RGFW_windowAttribsChange;
+				return;
+			}
+		}
+	}
+
+	#ifdef __cplusplus
+	#define APPKIT_EXTERN		extern "C"
+	#else
+	#define APPKIT_EXTERN		extern
+	#endif
+
+	APPKIT_EXTERN NSPasteboardType const NSPasteboardTypeURL = "public.url";                        API_AVAILABLE(macos(10.13)); // Equivalent to kUTTypeURL
+	APPKIT_EXTERN NSPasteboardType const NSPasteboardTypeFileURL  = "public.file-url";                  API_AVAILABLE(macos(10.13)); // Equivalent to kUTTypeFileURL
+
+	RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) {
+		static u8 RGFW_loaded = 0;
+
+		/* NOTE(EimaMei): Why does Apple hate good code? Like wtf, who thought of methods being a great idea???
+		Imagine a universe, where MacOS had a proper system API (we would probably have like 20% better performance).
+		*/
+		si_func_to_SEL_with_name("NSObject", "windowShouldClose", RGFW_OnClose);
+
+		/* NOTE(EimaMei): Fixes the 'Boop' sfx from constantly playing each time you click a key. Only a problem when running in the terminal. */
+		si_func_to_SEL("NSWindow", acceptsFirstResponder);
+		si_func_to_SEL("NSWindow", performKeyEquivalent);
+
+		if (NSApp == NULL) {
+			NSApp = objc_msgSend_id(objc_getClass("NSApplication"), sel_registerName("sharedApplication"));
+
+			((void (*)(id, SEL, NSUInteger))objc_msgSend)
+				(NSApp, sel_registerName("setActivationPolicy:"), NSApplicationActivationPolicyRegular);
+		}
+
+		RGFW_window* win = RGFW_window_basic_init(rect, args);
+
+		NSRect windowRect;
+		windowRect.origin.x = win->r.x;
+		windowRect.origin.y = win->r.y;
+		windowRect.size.width = win->r.w;
+		windowRect.size.height = win->r.h;
+
+		NSBackingStoreType macArgs = NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSBackingStoreBuffered | NSWindowStyleMaskTitled;
+
+		if (!(args & RGFW_NO_RESIZE))
+			macArgs |= NSWindowStyleMaskResizable;
+		if (!(args & RGFW_NO_BORDER))
+			macArgs |= NSWindowStyleMaskTitled;
+		else
+			macArgs = NSWindowStyleMaskBorderless;
+		{
+			void* nsclass = objc_getClass("NSWindow");
+			void* func = sel_registerName("initWithContentRect:styleMask:backing:defer:");
+
+			win->src.window = ((id(*)(id, SEL, NSRect, NSWindowStyleMask, NSBackingStoreType, bool))objc_msgSend)
+				(NSAlloc(nsclass), func, windowRect, macArgs, macArgs, false);
+		}
+
+		NSString* str = NSString_stringWithUTF8String(name);
+		objc_msgSend_void_id(win->src.window, sel_registerName("setTitle:"), str);
+
+#ifdef RGFW_OPENGL
+		void* attrs = RGFW_initAttribs(args & RGFW_OPENGL_SOFTWARE);
+		void* format = NSOpenGLPixelFormat_initWithAttributes(attrs);
+
+		if (format == NULL) {
+			printf("Failed to load pixel format ");
+
+			void* attrs = RGFW_initAttribs(1);
+			format = NSOpenGLPixelFormat_initWithAttributes(attrs);
+			if (format == NULL)
+				printf("and loading software rendering OpenGL failed\n");
+			else
+				printf("Switching to software rendering\n");
+		}
+
+		win->src.view = NSOpenGLView_initWithFrame(NSMakeRect(0, 0, win->r.w, win->r.h), format);
+		objc_msgSend_void(win->src.view, sel_registerName("prepareOpenGL"));
+		win->src.rSurf = objc_msgSend_id(win->src.view, sel_registerName("openGLContext"));
+
+#else
+		NSRect contentRect = NSMakeRect(0, 0, win->r.w, win->r.h);
+		win->src.view = ((id(*)(id, SEL, NSRect))objc_msgSend)
+			(NSAlloc(objc_getClass("NSView")), sel_registerName("initWithFrame:"),
+				contentRect);
+#endif
+
+
+		void* contentView = NSWindow_contentView(win->src.window);
+		objc_msgSend_void_bool(contentView, sel_registerName("setWantsLayer:"), true);
+
+		objc_msgSend_void_id(win->src.window, sel_registerName("setContentView:"), win->src.view);
+
+#ifdef RGFW_OPENGL
+		objc_msgSend_void(win->src.rSurf, sel_registerName("makeCurrentContext"));
+#endif
+		if (args & RGFW_TRANSPARENT_WINDOW) {
+#ifdef RGFW_OPENGL
+			i32 opacity = 0;
+			NSOpenGLContext_setValues(win->src.rSurf, &opacity, 304);
+#endif
+
+			objc_msgSend_void_bool(win->src.window, sel_registerName("setOpaque:"), false);
+
+			objc_msgSend_void_id(win->src.window, sel_registerName("setBackgroundColor:"),
+				NSColor_colorWithSRGB(0, 0, 0, 0));
+
+			((void (*)(id, SEL, CGFloat))objc_msgSend)
+				(win->src.window, sel_registerName("setAlphaValue:"), 0x00);
+		}
+
+		win->src.display = CGMainDisplayID();
+		CVDisplayLinkCreateWithCGDisplay(win->src.display, &win->src.displayLink);
+		CVDisplayLinkSetOutputCallback(win->src.displayLink, displayCallback, win);
+		CVDisplayLinkStart(win->src.displayLink);
+
+		RGFW_init_buffer(win);
+
+#ifdef RGFW_VULKAN
+		RGFW_initVulkan(win);
+#endif
+
+		if (args & RGFW_SCALE_TO_MONITOR)
+			RGFW_window_scaleToMonitor(win);
+
+		if (args & RGFW_HIDE_MOUSE)
+			RGFW_window_showMouse(win, 0);
+
+		if (args & RGFW_COCOA_MOVE_TO_RESOURCE_DIR)
+			NSMoveToResourceDir();
+
+		Class delegateClass = objc_allocateClassPair(objc_getClass("NSObject"), "WindowDelegate", 0);
+		class_addMethod(delegateClass, sel_registerName("windowWillResize:toSize:"), (IMP) RGFW__osxWindowResize, "{NSSize=ff}@:{NSSize=ff}");
+		class_addMethod(delegateClass, sel_registerName("windowWillMove:"), (IMP) RGFW__osxWindowMove, "");
+		class_addMethod(delegateClass, sel_registerName("windowDidMove:"), (IMP) RGFW__osxWindowMove, "");
+
+
+		if (args & RGFW_ALLOW_DND) {
+			win->src.winArgs |= RGFW_ALLOW_DND;
+
+/*
+		NSPasteboardType types[] = {NSPasteboardTypeURL, NSPasteboardTypeFileURL, NSPasteboardTypeString};
+
+		siArray(NSPasteboardType) array = sic_arrayInit(types, sizeof(id), countof(types));
+		NSWindow_registerForDraggedTypes(win->hwnd, array);
+
+		win->dndHead = win->dndPrev = out;
+*/
+
+			NSPasteboardType array[] = {NSPasteboardTypeURL, NSPasteboardTypeFileURL, NSPasteboardTypeString};
+			NSregisterForDraggedTypes(win->src.window, array, 3);
+
+			/* NOTE(EimaMei): Drag 'n Drop requires too many damn functions for just a Drag 'n Drop event. */
+			class_addMethod(delegateClass, "draggingEntered:", draggingEntered, "l@:@");
+			class_addMethod(delegateClass, "draggingUpdated:", draggingUpdated, "l@:@");
+			class_addMethod(delegateClass, "draggingExited:", RGFW__osxDraggingEnded, "v@:@");
+			class_addMethod(delegateClass, "draggingEnded:", RGFW__osxDraggingEnded, "v@:@");
+			class_addMethod(delegateClass, "prepareForDragOperation:", prepareForDragOperation, "B@:@");
+			class_addMethod(delegateClass, "performDragOperation:", performDragOperation, "B@:@");
+
+		}
+
+		id delegate = objc_msgSend_id(NSAlloc(delegateClass), sel_registerName("init"));
+
+		object_setInstanceVariable(delegate, "RGFW_window", win);
+
+		objc_msgSend_void_id(win->src.window, sel_registerName("setDelegate:"), delegate);
+
+		// Show the window
+		((id(*)(id, SEL, SEL))objc_msgSend)(win->src.window, sel_registerName("makeKeyAndOrderFront:"), NULL);
+		objc_msgSend_void_bool(win->src.window, sel_registerName("setIsVisible:"), true);
+
+		if (!RGFW_loaded) {
+			objc_msgSend_void(win->src.window, sel_registerName("makeMainWindow"));
+
+			RGFW_loaded = 1;
+		}
+
+		NSApplication_finishLaunching(NSApp);
+
+		RGFW_windows_size++;
+
+		size_t i;
+		for (i = 0; i < RGFW_windows_size; i++)
+			if (!RGFW_windows[i]) {
+				RGFW_windows[i] = win;
+				break;
+			}
+
+		if (RGFW_root == NULL)
+			RGFW_root = win;
+
+		NSRetain(win->src.window);
+		NSRetain(NSApp);
+
+		return win;
+	}
+
+
+	RGFW_area RGFW_getScreenSize(void) {
+		static CGDirectDisplayID display = 0;
+
+		if (display == 0)
+			display = CGMainDisplayID();
+
+		return RGFW_AREA(CGDisplayPixelsWide(display), CGDisplayPixelsHigh(display));
+	}
+
+	RGFW_vector RGFW_getGlobalMousePoint(void) {
+		assert(RGFW_root != NULL);
+
+		CGEventRef e = CGEventCreate(NULL);
+		CGPoint point = CGEventGetLocation(e);
+		CFRelease(e);
+
+		return RGFW_VECTOR((u32) point.x, (u32) point.y); /* the point is loaded during event checks */
+	}
+
+	u32 RGFW_keysPressed[10]; /*10 keys at a time*/
+	typedef NS_ENUM(u32, NSEventType) {        /* various types of events */
+		NSEventTypeLeftMouseDown = 1,
+			NSEventTypeLeftMouseUp = 2,
+			NSEventTypeRightMouseDown = 3,
+			NSEventTypeRightMouseUp = 4,
+			NSEventTypeMouseMoved = 5,
+			NSEventTypeLeftMouseDragged = 6,
+			NSEventTypeRightMouseDragged = 7,
+			NSEventTypeMouseEntered = 8,
+			NSEventTypeMouseExited = 9,
+			NSEventTypeKeyDown = 10,
+			NSEventTypeKeyUp = 11,
+			NSEventTypeFlagsChanged = 12,
+			NSEventTypeAppKitDefined = 13,
+			NSEventTypeSystemDefined = 14,
+			NSEventTypeApplicationDefined = 15,
+			NSEventTypePeriodic = 16,
+			NSEventTypeCursorUpdate = 17,
+			NSEventTypeScrollWheel = 22,
+			NSEventTypeTabletPoint = 23,
+			NSEventTypeTabletProximity = 24,
+			NSEventTypeOtherMouseDown = 25,
+			NSEventTypeOtherMouseUp = 26,
+			NSEventTypeOtherMouseDragged = 27,
+			/* The following event types are available on some hardware on 10.5.2 and later */
+			NSEventTypeGesture API_AVAILABLE(macos(10.5)) = 29,
+			NSEventTypeMagnify API_AVAILABLE(macos(10.5)) = 30,
+			NSEventTypeSwipe   API_AVAILABLE(macos(10.5)) = 31,
+			NSEventTypeRotate  API_AVAILABLE(macos(10.5)) = 18,
+			NSEventTypeBeginGesture API_AVAILABLE(macos(10.5)) = 19,
+			NSEventTypeEndGesture API_AVAILABLE(macos(10.5)) = 20,
+
+			NSEventTypeSmartMagnify API_AVAILABLE(macos(10.8)) = 32,
+			NSEventTypeQuickLook API_AVAILABLE(macos(10.8)) = 33,
+
+			NSEventTypePressure API_AVAILABLE(macos(10.10.3)) = 34,
+			NSEventTypeDirectTouch API_AVAILABLE(macos(10.10)) = 37,
+
+			NSEventTypeChangeMode API_AVAILABLE(macos(10.15)) = 38,
+	};
+
+	typedef NS_ENUM(unsigned long long, NSEventMask) { /* masks for the types of events */
+		NSEventMaskLeftMouseDown = 1ULL << NSEventTypeLeftMouseDown,
+			NSEventMaskLeftMouseUp = 1ULL << NSEventTypeLeftMouseUp,
+			NSEventMaskRightMouseDown = 1ULL << NSEventTypeRightMouseDown,
+			NSEventMaskRightMouseUp = 1ULL << NSEventTypeRightMouseUp,
+			NSEventMaskMouseMoved = 1ULL << NSEventTypeMouseMoved,
+			NSEventMaskLeftMouseDragged = 1ULL << NSEventTypeLeftMouseDragged,
+			NSEventMaskRightMouseDragged = 1ULL << NSEventTypeRightMouseDragged,
+			NSEventMaskMouseEntered = 1ULL << NSEventTypeMouseEntered,
+			NSEventMaskMouseExited = 1ULL << NSEventTypeMouseExited,
+			NSEventMaskKeyDown = 1ULL << NSEventTypeKeyDown,
+			NSEventMaskKeyUp = 1ULL << NSEventTypeKeyUp,
+			NSEventMaskFlagsChanged = 1ULL << NSEventTypeFlagsChanged,
+			NSEventMaskAppKitDefined = 1ULL << NSEventTypeAppKitDefined,
+			NSEventMaskSystemDefined = 1ULL << NSEventTypeSystemDefined,
+			NSEventMaskApplicationDefined = 1ULL << NSEventTypeApplicationDefined,
+			NSEventMaskPeriodic = 1ULL << NSEventTypePeriodic,
+			NSEventMaskCursorUpdate = 1ULL << NSEventTypeCursorUpdate,
+			NSEventMaskScrollWheel = 1ULL << NSEventTypeScrollWheel,
+			NSEventMaskTabletPoint = 1ULL << NSEventTypeTabletPoint,
+			NSEventMaskTabletProximity = 1ULL << NSEventTypeTabletProximity,
+			NSEventMaskOtherMouseDown = 1ULL << NSEventTypeOtherMouseDown,
+			NSEventMaskOtherMouseUp = 1ULL << NSEventTypeOtherMouseUp,
+			NSEventMaskOtherMouseDragged = 1ULL << NSEventTypeOtherMouseDragged,
+			/* The following event masks are available on some hardware on 10.5.2 and later */
+			NSEventMaskGesture API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeGesture,
+			NSEventMaskMagnify API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeMagnify,
+			NSEventMaskSwipe API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeSwipe,
+			NSEventMaskRotate API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeRotate,
+			NSEventMaskBeginGesture API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeBeginGesture,
+			NSEventMaskEndGesture API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeEndGesture,
+
+			/* Note: You can only use these event masks on 64 bit. In other words, you cannot setup a local, nor global, event monitor for these event types on 32 bit. Also, you cannot search the event queue for them (nextEventMatchingMask:...) on 32 bit.
+			 */
+			NSEventMaskSmartMagnify API_AVAILABLE(macos(10.8)) = 1ULL << NSEventTypeSmartMagnify,
+			NSEventMaskPressure API_AVAILABLE(macos(10.10.3)) = 1ULL << NSEventTypePressure,
+			NSEventMaskDirectTouch API_AVAILABLE(macos(10.12.2)) = 1ULL << NSEventTypeDirectTouch,
+
+			NSEventMaskChangeMode API_AVAILABLE(macos(10.15)) = 1ULL << NSEventTypeChangeMode,
+
+			NSEventMaskAny = ULONG_MAX,
+
+	};
+
+	RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) {
+		assert(win != NULL);
+
+		if (win->event.type == RGFW_quit)
+			return &win->event;
+
+		static void* eventFunc = NULL;
+		if (eventFunc == NULL)
+			eventFunc = sel_registerName("nextEventMatchingMask:untilDate:inMode:dequeue:");
+		
+		if (win->event.type == RGFW_windowAttribsChange && win->event.keyCode != 120) {
+			win->event.keyCode = 120;
+			return &win->event;
+		}
+
+		NSEvent* e = (NSEvent*) ((id(*)(id, SEL, NSEventMask, void*, NSString*, bool))objc_msgSend)
+			(NSApp, eventFunc, ULONG_MAX, NULL, NSString_stringWithUTF8String("kCFRunLoopDefaultMode"), true);
+
+
+		if (e == NULL)
+			return NULL;
+
+		if (objc_msgSend_id(e, sel_registerName("window")) != win->src.window) {
+			((void (*)(id, SEL, id, bool))objc_msgSend)
+				(NSApp, sel_registerName("postEvent:atStart:"), e, 0);
+
+			return NULL;
+		}
+
+		if (win->event.droppedFilesCount) {
+			u32 i;
+			for (i = 0; i < win->event.droppedFilesCount; i++)
+				win->event.droppedFiles[i][0] = '\0';
+		}
+
+		win->event.droppedFilesCount = 0;
+		win->event.type = 0;
+
+		win->event.inFocus = (bool) objc_msgSend_bool(win->src.window, sel_registerName("isKeyWindow"));
+
+		switch (objc_msgSend_uint(e, sel_registerName("type"))) {
+		case NSEventTypeKeyDown:
+			win->event.type = RGFW_keyPressed;
+			win->event.keyCode = (u16) objc_msgSend_uint(e, sel_registerName("keyCode"));
+			win->event.keyName = (const char*) NSString_to_char(objc_msgSend_id(e, sel_registerName("characters")));
+
+			RGFW_keyMap[win->event.keyCode] = 1;
+			break;
+
+		case NSEventTypeKeyUp:
+			win->event.type = RGFW_keyReleased;
+			win->event.keyCode = (u16) objc_msgSend_uint(e, sel_registerName("keyCode"));
+			win->event.keyName = (const char*) NSString_to_char(objc_msgSend_id(e, sel_registerName("characters")));
+
+			RGFW_keyMap[win->event.keyCode] = 0;
+			break;
+
+		case NSEventTypeLeftMouseDragged:
+		case NSEventTypeOtherMouseDragged:
+		case NSEventTypeRightMouseDragged:
+		case NSEventTypeMouseMoved:
+			win->event.type = RGFW_mousePosChanged;
+			NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(e, sel_registerName("locationInWindow"));
+
+			win->event.point = RGFW_VECTOR((u32) p.x, (u32) (win->r.h - p.y));
+
+			if (win->src.winArgs & RGFW_HOLD_MOUSE) {
+				RGFW_vector mouse = RGFW_getGlobalMousePoint();
+				if ((mouse.x != win->r.x + (win->r.w / 2) || mouse.y != win->r.y + (win->r.h / 2))) {
+					RGFW_window_moveMouse(win, RGFW_VECTOR(win->r.x + (win->r.w / 2), win->r.y + (win->r.h / 2)));
+				}
+			}
+			break;
+
+		case NSEventTypeLeftMouseDown:
+			win->event.button = RGFW_mouseLeft;
+			win->event.type = RGFW_mouseButtonPressed;
+			break;
+
+		case NSEventTypeOtherMouseDown:
+			win->event.button = RGFW_mouseMiddle;
+			win->event.type = RGFW_mouseButtonPressed;
+			break;
+
+		case NSEventTypeRightMouseDown:
+			win->event.button = RGFW_mouseRight;
+			win->event.type = RGFW_mouseButtonPressed;
+			break;
+
+		case NSEventTypeLeftMouseUp:
+			win->event.button = RGFW_mouseLeft;
+			win->event.type = RGFW_mouseButtonReleased;
+			break;
+
+		case NSEventTypeOtherMouseUp:
+			win->event.button = RGFW_mouseMiddle;
+			win->event.type = RGFW_mouseButtonReleased;
+			break;
+
+		case NSEventTypeScrollWheel: {
+			double deltaY = ((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(e, sel_registerName("deltaY"));
+
+			if (deltaY > 0)
+				win->event.button = RGFW_mouseScrollUp;
+
+			else if (deltaY < 0)
+				win->event.button = RGFW_mouseScrollDown;
+
+			win->event.scroll = deltaY;
+
+			win->event.type = RGFW_mouseButtonReleased;
+			break;
+		}
+		case NSEventTypeRightMouseUp:
+			win->event.button = RGFW_mouseRight;
+			win->event.type = RGFW_mouseButtonReleased;
+			break;
+
+		default:
+			break;
+		}
+
+		objc_msgSend_void_id(NSApp, sel_registerName("sendEvent:"), e);
+
+		return &win->event;
+	}
+
+
+	void RGFW_window_move(RGFW_window* win, RGFW_vector v) {
+		assert(win != NULL);
+
+		win->r.x = v.x;
+		win->r.y = v.y;
+		((void(*)(id, SEL, NSRect, bool, bool))objc_msgSend)
+			(win->src.window, sel_registerName("setFrame:display:animate:"), NSMakeRect(win->r.x, win->r.y, win->r.w, win->r.h), true, true);
+	}
+
+	void RGFW_window_resize(RGFW_window* win, RGFW_area a) {
+		assert(win != NULL);
+
+		win->r.w = a.w;
+		win->r.h = a.h;
+		((void(*)(id, SEL, NSRect, bool, bool))objc_msgSend)
+			(win->src.window, sel_registerName("setFrame:display:animate:"), NSMakeRect(win->r.x, win->r.y, win->r.w, win->r.h), true, true);
+	}
+
+	void RGFW_window_minimize(RGFW_window* win) {
+		assert(win != NULL);
+
+		objc_msgSend_void_SEL(win->src.window, sel_registerName("performMiniaturize:"), NULL);
+	}
+
+	void RGFW_window_restore(RGFW_window* win) {
+		assert(win != NULL);
+
+		objc_msgSend_void_SEL(win->src.window, sel_registerName("deminiaturize:"), NULL);
+	}
+
+	void RGFW_window_setName(RGFW_window* win, char* name) {
+		assert(win != NULL);
+
+		NSString* str = NSString_stringWithUTF8String(name);
+		objc_msgSend_void_id(win->src.window, sel_registerName("setTitle:"), str);
+	}
+
+	void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) {
+		((void (*)(id, SEL, NSSize))objc_msgSend)
+			(win->src.window, sel_registerName("setMinSize:"), NSMakeSize(a.w, a.h));
+	}
+
+	void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) {
+		((void (*)(id, SEL, NSSize))objc_msgSend)
+			(win->src.window, sel_registerName("setMaxSize:"), NSMakeSize(a.w, a.h));
+	}
+
+	void RGFW_window_setIcon(RGFW_window* win, u8* data, RGFW_area area, i32 channels) {
+		assert(win != NULL);
+
+		/* code by EimaMei  */
+		// Make a bitmap representation, then copy the loaded image into it.
+		void* representation = NSBitmapImageRep_initWithBitmapData(NULL, area.w, area.h, 8, channels, (channels == 4), false, "NSCalibratedRGBColorSpace", 1 << 1, area.w * channels, 8 * channels);
+		memcpy(NSBitmapImageRep_bitmapData(representation), data, area.w * area.h * channels);
+
+		// Add ze representation.
+		void* dock_image = NSImage_initWithSize(NSMakeSize(area.w, area.h));
+		NSImage_addRepresentation(dock_image, (void*) representation);
+
+		// Finally, set the dock image to it.
+		objc_msgSend_void_id(NSApp, sel_registerName("setApplicationIconImage:"), dock_image);
+		// Free the garbage.
+		release(dock_image);
+		release(representation);
+	}
+
+	NSCursor* NSCursor_arrowStr(char* str) {
+		void* nclass = objc_getClass("NSCursor");
+		void* func = sel_registerName(str);
+		return (NSCursor*) objc_msgSend_id(nclass, func);
+	}
+
+	void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels) {
+		assert(win != NULL);
+
+		if (image == NULL) {
+			objc_msgSend_void(NSCursor_arrowStr("arrowCursor"), sel_registerName("set"));
+			return;
+		}
+
+		/* NOTE(EimaMei): Code by yours truly. */
+		// Make a bitmap representation, then copy the loaded image into it.
+		void* representation = NSBitmapImageRep_initWithBitmapData(NULL, a.w, a.h, 8, channels, (channels == 4), false, "NSCalibratedRGBColorSpace", 1 << 1, a.w * channels, 8 * channels);
+		memcpy(NSBitmapImageRep_bitmapData(representation), image, a.w * a.h * channels);
+
+		// Add ze representation.
+		void* cursor_image = NSImage_initWithSize(NSMakeSize(a.w, a.h));
+		NSImage_addRepresentation(cursor_image, representation);
+
+		// Finally, set the cursor image.
+		void* cursor = NSCursor_initWithImage(cursor_image, NSMakePoint(0, 0));
+
+		objc_msgSend_void(cursor, sel_registerName("set"));
+
+		// Free the garbage.
+		release(cursor_image);
+		release(representation);
+	}
+
+	void RGFW_window_setMouseDefault(RGFW_window* win) {
+		RGFW_window_setMouseStandard(win, NSCursor_arrowStr("arrowCursor"));
+	}
+
+	void RGFW_window_showMouse(RGFW_window* win, i8 show) {
+		if (show) {
+			CGDisplayShowCursor(kCGDirectMainDisplay);
+		}
+		else {
+			CGDisplayHideCursor(kCGDirectMainDisplay);
+		}
+	}
+
+	void RGFW_window_setMouseStandard(RGFW_window* win, void* mouse) {
+		CGDisplayShowCursor(kCGDirectMainDisplay);
+		objc_msgSend_void(mouse, sel_registerName("set"));
+	}
+
+	void RGFW_window_moveMouse(RGFW_window* win, RGFW_vector v) {
+		assert(win != NULL);
+
+		CGWarpMouseCursorPosition(CGPointMake(v.x, v.y));
+	}
+
+
+	void RGFW_window_hide(RGFW_window* win) {
+		objc_msgSend_void_bool(win->src.window, sel_registerName("setIsVisible:"), false);
+	}
+
+	void RGFW_window_show(RGFW_window* win) {
+		((id(*)(id, SEL, SEL))objc_msgSend)(win->src.window, sel_registerName("makeKeyAndOrderFront:"), NULL);
+		objc_msgSend_void_bool(win->src.window, sel_registerName("setIsVisible:"), true);
+	}
+
+	u8 RGFW_window_isFullscreen(RGFW_window* win) {
+		assert(win != NULL);
+
+		NSWindowStyleMask mask = (NSWindowStyleMask) objc_msgSend_uint(win->src.window, sel_registerName("styleMask"));
+		return (mask & NSWindowStyleMaskFullScreen) == NSWindowStyleMaskFullScreen;
+	}
+
+	u8 RGFW_window_isHidden(RGFW_window* win) {
+		assert(win != NULL);
+
+		bool visible = objc_msgSend_bool(win->src.window, sel_registerName("isVisible"));
+		return visible == NO && !RGFW_window_isMinimized(win);
+	}
+
+	u8 RGFW_window_isMinimized(RGFW_window* win) {
+		assert(win != NULL);
+
+		return objc_msgSend_bool(win->src.window, sel_registerName("isMiniaturized")) == YES;
+	}
+
+	u8 RGFW_window_isMaximized(RGFW_window* win) {
+		assert(win != NULL);
+
+		return objc_msgSend_bool(win->src.window, sel_registerName("isZoomed"));
+	}
+
+	static RGFW_monitor RGFW_NSCreateMonitor(CGDirectDisplayID display) {
+		RGFW_monitor monitor;
+
+		CGRect bounds = CGDisplayBounds(display);
+		monitor.rect = RGFW_RECT((int) bounds.origin.x, (int) bounds.origin.y, (int) bounds.size.width, (int) bounds.size.height);
+
+		CGSize screenSizeMM = CGDisplayScreenSize(display);
+		monitor.physW = screenSizeMM.width / 25.4;
+		monitor.physH = screenSizeMM.height / 25.4;
+
+		monitor.scaleX = (monitor.rect.w / (screenSizeMM.width)) / 2.6;
+		monitor.scaleY = (monitor.rect.h / (screenSizeMM.height)) / 2.6;
+
+		snprintf(monitor.name, 128, "%i %i %i", CGDisplayModelNumber(display), CGDisplayVendorNumber(display), CGDisplaySerialNumber(display));
+
+		return monitor;
+	}
+
+
+	static RGFW_monitor RGFW_monitors[7];
+
+	RGFW_monitor* RGFW_getMonitors(void) {
+		static CGDirectDisplayID displays[7];
+		u32 count;
+
+		if (CGGetActiveDisplayList(6, displays, &count) != kCGErrorSuccess)
+			return NULL;
+
+		for (u32 i = 0; i < count; i++)
+			RGFW_monitors[i] = RGFW_NSCreateMonitor(displays[i]);
+
+		return RGFW_monitors;
+	}
+
+	RGFW_monitor RGFW_getPrimaryMonitor(void) {
+		CGDirectDisplayID primary = CGMainDisplayID();
+		return RGFW_NSCreateMonitor(primary);
+	}
+
+	RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) {
+		return RGFW_NSCreateMonitor(win->src.display);
+	}
+
+	u8 RGFW_isPressedI(RGFW_window* win, u32 key) {
+		if (key >= 128) {
+#ifdef RGFW_PRINT_ERRORS
+			fprintf(stderr, "RGFW_isPressedI : invalid keycode\n");
+#endif
+			RGFW_error = 1;
+		}
+
+		return RGFW_keyMap[key];
+	}
+
+#ifdef __cplusplus
+#define APPKIT_EXTERN		extern "C"
+#else
+#define APPKIT_EXTERN		extern
+#endif
+
+	char* RGFW_readClipboard(size_t* size) {
+		char* str = strdup((char*) NSPasteboard_stringForType(NSPasteboard_generalPasteboard(), NSPasteboardTypeString));
+		if (size != NULL)
+			*size = strlen(str);
+		return str;
+	}
+
+	void RGFW_writeClipboard(const char* text, u32 textLen) {
+		NSPasteboardType array[] = { NSPasteboardTypeString, NULL };
+		NSPasteBoard_declareTypes(NSPasteboard_generalPasteboard(), array, 1, NULL);
+
+		NSPasteBoard_setString(NSPasteboard_generalPasteboard(), text, NSPasteboardTypeString);
+	}
+
+	u16 RGFW_registerJoystick(RGFW_window* win, i32 jsNumber) {
+		assert(win != NULL);
+
+		return RGFW_registerJoystickF(win, (char*) "");
+	}
+
+	u16 RGFW_registerJoystickF(RGFW_window* win, char* file) {
+		assert(win != NULL);
+
+		return win->src.joystickCount - 1;
+	}
+
+	void RGFW_window_close(RGFW_window* win) {
+		assert(win != NULL);
+
+#ifdef RGFW_VULKAN
+		for (int i = 0; i < win->src.image_count; i++) {
+			vkDestroyFramebuffer(RGFW_vulkan_info.device, RGFW_vulkan_info.framebuffers[i], NULL);
+		}
+
+		for (int i = 0; i < win->src.image_count; i++) {
+			vkDestroyImageView(RGFW_vulkan_info.device, win->src.swapchain_image_views[i], NULL);
+		}
+
+		vkDestroySwapchainKHR(RGFW_vulkan_info.device, win->src.swapchain, NULL);
+		vkDestroySurfaceKHR(RGFW_vulkan_info.instance, win->src.rSurf, NULL);
+		free(win->src.swapchain_image_views);
+		free(win->src.swapchain_images);
+#endif
+
+		release(win->src.view);
+
+#ifdef RGFW_ALLOC_DROPFILES
+		{
+			u32 i;
+			for (i = 0; i < RGFW_MAX_DROPS; i++)
+				RGFW_FREE(win->event.droppedFiles[i]);
+
+
+			RGFW_FREE(win->event.droppedFiles);
+		}
+#endif
+
+		u32 i;
+		for (i = 0; i < RGFW_windows_size; i++)
+			if (RGFW_windows[i]->src.window == win->src.window) {
+				RGFW_windows[i] = NULL;
+				break;
+			}
+
+		if (!i) {
+			RGFW_windows_size = 0;
+
+			objc_msgSend_void_id(NSApp, sel_registerName("terminate:"), (id) win->src.window);
+			NSApp = NULL;
+		}
+
+#ifdef RGFW_BUFFER
+		release(win->src.bitmap);
+		release(win->src.image);
+#endif
+
+		CVDisplayLinkStop(win->src.displayLink);
+		CVDisplayLinkRelease(win->src.displayLink);
+
+		free(win);
+	}
+#endif
+
+#if defined(RGFW_X11) || defined(RGFW_MACOS)
+
+#ifndef RGFW_NO_THREADS
+#include <pthread.h>
+
+	RGFW_thread RGFW_createThread(void* (*function_ptr)(void*), void* args) {
+		RGFW_thread t;
+		pthread_create((pthread_t*) &t, NULL, *function_ptr, NULL);
+		return t;
+	}
+	void RGFW_cancelThread(RGFW_thread thread) { pthread_cancel((pthread_t) thread); }
+	void RGFW_joinThread(RGFW_thread thread) { pthread_join((pthread_t) thread, NULL); }
+#ifdef __linux__
+	void RGFW_setThreadPriority(RGFW_thread thread, u8 priority) { pthread_setschedprio(thread, priority); }
+#endif
+#endif
+#endif
+
+	void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) {
+		assert(win != NULL);
+
+#ifdef RGFW_OPENGL
+#ifdef RGFW_X11
+		glXMakeCurrent((Display*) win->src.display, (Drawable) win->src.window, (GLXContext) win->src.rSurf);
+#endif
+#ifdef RGFW_WINDOWS
+		wglMakeCurrent(win->src.hdc, (HGLRC) win->src.rSurf);
+#endif
+#if defined(RGFW_MACOS)
+		objc_msgSend_void(win->src.rSurf, sel_registerName("makeCurrentContext"));
+#endif
+#else
+#ifdef RGFW_EGL
+		eglMakeCurrent(win->src.EGL_display, win->src.EGL_surface, win->src.EGL_surface, win->src.rSurf);
+#endif
+#endif
+
+	}
+
+	void RGFW_window_makeCurrent(RGFW_window* win) {
+		assert(win != NULL);
+
+#if defined(RGFW_WINDOWS) && defined(RGFW_DIRECTX)
+		RGFW_dxInfo.pDeviceContext->lpVtbl->OMSetRenderTargets(RGFW_dxInfo.pDeviceContext, 1, &win->src.renderTargetView, NULL);
+#endif
+
+#ifdef RGFW_OPENGL
+		RGFW_window_makeCurrent_OpenGL(win);
+#endif
+	}
+
+	void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) {
+		assert(win != NULL);
+
+#ifdef RGFW_OPENGL
+#ifdef RGFW_X11
+		((PFNGLXSWAPINTERVALEXTPROC) glXGetProcAddress((GLubyte*) "glXSwapIntervalEXT"))((Display*) win->src.display, (Window) win->src.window, swapInterval);
+#endif
+#ifdef RGFW_WINDOWS
+
+		typedef BOOL(APIENTRY* PFNWGLSWAPINTERVALEXTPROC)(int interval);
+		static PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = NULL;
+		static void* loadSwapFunc = (void*) 1;
+
+		if (loadSwapFunc == NULL) {
+			fprintf(stderr, "wglSwapIntervalEXT not supported\n");
+			win->fpsCap = (swapInterval == 1) ? 0 : swapInterval;
+			return;
+		}
+
+		if (wglSwapIntervalEXT == NULL) {
+			loadSwapFunc = (void*) wglGetProcAddress("wglSwapIntervalEXT");
+			wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC) loadSwapFunc;
+		}
+
+		if (wglSwapIntervalEXT(swapInterval) == FALSE)
+			fprintf(stderr, "Failed to set swap interval\n");
+
+#endif
+#if defined(RGFW_MACOS)
+		NSOpenGLContext_setValues(win->src.rSurf, &swapInterval, 222);
+#endif
+#endif
+
+#ifdef RGFW_EGL
+		eglSwapInterval(win->src.EGL_display, swapInterval);
+#endif
+
+		win->fpsCap = (swapInterval == 1) ? 0 : swapInterval;
+
+	}
+
+	void RGFW_window_setGPURender(RGFW_window* win, i8 set) {
+		if (!set && !(win->src.winArgs & RGFW_NO_GPU_RENDER))
+			win->src.winArgs |= RGFW_NO_GPU_RENDER;
+
+		else if (set && win->src.winArgs & RGFW_NO_GPU_RENDER)
+			win->src.winArgs ^= RGFW_NO_GPU_RENDER;
+	}
+
+	void RGFW_window_setCPURender(RGFW_window* win, i8 set) {
+		if (!set && !(win->src.winArgs & RGFW_NO_CPU_RENDER))
+			win->src.winArgs |= RGFW_NO_CPU_RENDER;
+
+		else if (set && win->src.winArgs & RGFW_NO_CPU_RENDER)
+			win->src.winArgs ^= RGFW_NO_CPU_RENDER;
+	}
+
+
+	void RGFW_window_swapBuffers(RGFW_window* win) {
+		assert(win != NULL);
+
+		win->event.frames++;
+		RGFW_window_checkFPS(win);
+
+		RGFW_window_makeCurrent(win);
+
+		/* clear the window*/
+
+		if (!(win->src.winArgs & RGFW_NO_CPU_RENDER)) {
+#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)
+#ifdef RGFW_OSMESA
+			u8* row = (u8*) RGFW_MALLOC(win->r.w * 3);
+
+			i32 half_height = win->r.h / 2;
+			i32 stride = win->r.w * 3;
+
+			i32 y;
+			for (y = 0; y < half_height; ++y) {
+				i32 top_offset = y * stride;
+				i32 bottom_offset = (win->r.h - y - 1) * stride;
+				memcpy(row, win->buffer + top_offset, stride);
+				memcpy(win->buffer + top_offset, win->buffer + bottom_offset, stride);
+				memcpy(win->buffer + bottom_offset, row, stride);
+			}
+
+			RGFW_FREE(row);
+#endif
+
+#ifdef RGFW_X11
+			RGFW_area area = RGFW_getScreenSize();
+
+#ifndef RGFW_X11_DONT_CONVERT_BGR
+			win->src.bitmap->data = (const char*) win->buffer;
+			u32 x, y;
+			for (y = 0; y < win->r.h; y++) {
+				for (x = 0; x < win->r.w; x++) {
+					u32 index = (y * 4 * area.w) + x * 4;
+
+					u8 red = win->src.bitmap->data[index];
+					win->src.bitmap->data[index] = win->buffer[index + 2];
+					win->src.bitmap->data[index + 2] = red;
+				}
+			}
+#endif
+
+			XPutImage(win->src.display, (Window) win->src.window, XDefaultGC(win->src.display, XDefaultScreen(win->src.display)), win->src.bitmap, 0, 0, 0, 0, win->r.w, win->r.h);
+#endif
+#ifdef RGFW_WINDOWS
+			HGDIOBJ oldbmp = SelectObject(win->src.hdcMem, win->src.bitmap);
+			BitBlt(win->src.hdc, 0, 0, win->r.w, win->r.h, win->src.hdcMem, 0, 0, SRCCOPY);
+			SelectObject(win->src.hdcMem, oldbmp);
+#endif	
+#if defined(RGFW_MACOS)
+			RGFW_area area = RGFW_getScreenSize();
+			void* view = NSWindow_contentView(win->src.window);
+			void* layer = objc_msgSend_id(view, sel_registerName("layer"));
+
+			((void(*)(id, SEL, NSRect))objc_msgSend)(layer,
+				sel_registerName("setFrame:"),
+				NSMakeRect(0, 0, win->r.w, win->r.h));
+
+			NSBitmapImageRep* rep = NSBitmapImageRep_initWithBitmapData(
+				&win->buffer, win->r.w, win->r.h, 8, 4, true, false,
+				"NSDeviceRGBColorSpace", 0,
+				area.w * 4, 32
+			);
+			id image = NSAlloc(objc_getClass("NSImage"));
+			NSImage_addRepresentation(image, rep);
+			objc_msgSend_void_id(layer, sel_registerName("setContents:"), (id) image);
+
+			release(image);
+			release(rep);
+#endif
+#endif
+
+#ifdef RGFW_VULKAN
+#ifdef RGFW_PRINT_ERRORS
+			fprintf(stderr, "RGFW_window_swapBuffers %s\n", "RGFW_window_swapBuffers is not yet supported for Vulkan");
+			RGFW_error = 1;
+#endif
+#endif
+		}
+
+		if (win->src.winArgs & RGFW_NO_GPU_RENDER)
+			return;
+
+#ifdef RGFW_OPENGL
+#ifdef RGFW_EGL
+		eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface);
+#else
+#if defined(RGFW_X11) && defined(RGFW_OPENGL)
+		glXSwapBuffers((Display*) win->src.display, (Window) win->src.window);
+#endif
+#ifdef RGFW_WINDOWS
+		SwapBuffers(win->src.hdc);
+#endif
+#if defined(RGFW_MACOS)
+		NSOpenGLContext_flushBuffer(win->src.rSurf);
+#endif
+#endif
+#endif
+
+#if defined(RGFW_WINDOWS) && defined(RGFW_DIRECTX)
+		win->src.swapchain->lpVtbl->Present(win->src.swapchain, 0, 0);
+#endif
+	}
+
+	void RGFW_window_maximize(RGFW_window* win) {
+		assert(win != NULL);
+
+		RGFW_area screen = RGFW_getScreenSize();
+
+		RGFW_window_move(win, RGFW_VECTOR(0, 0));
+		RGFW_window_resize(win, screen);
+	}
+
+	u8 RGFW_window_shouldClose(RGFW_window* win) {
+		assert(win != NULL);
+
+		/* || RGFW_isPressedI(win, RGFW_Escape) */
+		return (win->event.type == RGFW_quit || RGFW_isPressedI(win, RGFW_OS_BASED_VALUE(0xff1b, 0x1B, 53)));
+	}
+
+	void RGFW_window_setShouldClose(RGFW_window* win) { win->event.type = RGFW_quit; }
+
+	void RGFW_window_moveToMonitor(RGFW_window* win, RGFW_monitor m) {
+		RGFW_window_move(win, RGFW_VECTOR(m.rect.x + win->r.x, m.rect.y + win->r.y));
+	}
+
+	void RGFW_window_mouseHold(RGFW_window* win) {
+		win->src.winArgs |= RGFW_HOLD_MOUSE;
+
+		#ifdef RGFW_WINDOWS
+		RECT rect = {win->r.x, win->r.y, win->r.x + win->r.w, win->r.y + win->r.h};
+		ClipCursor(&rect);
+		#endif
+	}
+
+	void RGFW_window_mouseUnhold(RGFW_window* win) {
+		win->src.winArgs ^= RGFW_HOLD_MOUSE;
+
+		#ifdef RGFW_WINDOWS
+		ClipCursor(NULL);
+		#endif
+	}
+
+	void RGFW_sleep(u32 ms) {
+#ifndef _MSC_VER
+		struct timespec time;
+		time.tv_sec = 0;
+		time.tv_nsec = ms * 1000;
+
+		nanosleep(&time, NULL);
+#else
+		Sleep(ms);
+#endif
+	}
+
+	static float currentFrameTime = 0;
+
+	void RGFW_window_checkFPS(RGFW_window* win) {
+		assert(win != NULL);
+
+		win->event.fps = RGFW_getFPS();
+
+		if (win->fpsCap == 0)
+			return;
+
+		double targetFrameTime = 1.0 / win->fpsCap;
+		double elapsedTime = RGFW_getTime() - currentFrameTime;
+
+		if (elapsedTime < targetFrameTime) {
+			u32 sleepTime = (u32) ((targetFrameTime - elapsedTime) * 1e3);
+			RGFW_sleep(sleepTime);
+		}
+
+		currentFrameTime = (float) RGFW_getTime();
+
+		if (elapsedTime < targetFrameTime) {
+			u32 sleepTime = (u32) ((targetFrameTime - elapsedTime) * 1e3);
+			RGFW_sleep(sleepTime);
+		}
+
+		currentFrameTime = (float) RGFW_getTime();
+	}
+
+#ifdef __APPLE__
+#include <mach/mach_time.h>
+#endif
+
+	u64 RGFW_getTimeNS(void) {
+#ifdef RGFW_WINDOWS
+		LARGE_INTEGER frequency;
+		QueryPerformanceFrequency(&frequency);
+
+		LARGE_INTEGER counter;
+		QueryPerformanceCounter(&counter);
+
+		return (u64) (counter.QuadPart * 1e9 / frequency.QuadPart);
+#elif defined(__unix__)
+		struct timespec ts = { 0 };
+		clock_gettime(CLOCK_MONOTONIC, &ts);
+		unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec;
+
+		return nanoSeconds;
+#elif defined(__APPLE__)
+		static mach_timebase_info_data_t timebase_info;
+		if (timebase_info.denom == 0) {
+			mach_timebase_info(&timebase_info);
+		}
+		return mach_absolute_time() * timebase_info.numer / timebase_info.denom;
+#endif
+		return 0;
+	}
+
+	u64 RGFW_getTime(void) {
+#ifdef RGFW_WINDOWS
+		LARGE_INTEGER frequency;
+		QueryPerformanceFrequency(&frequency);
+
+		LARGE_INTEGER counter;
+		QueryPerformanceCounter(&counter);
+		return (u64) (counter.QuadPart / (double) frequency.QuadPart);
+#elif defined(__unix__)
+		struct timespec ts = { 0 };
+		clock_gettime(CLOCK_MONOTONIC, &ts);
+		unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec;
+
+		return (double)(nanoSeconds) * 1e-9;
+#elif defined(__APPLE__)
+		static mach_timebase_info_data_t timebase_info;
+		if (timebase_info.denom == 0) {
+			mach_timebase_info(&timebase_info);
+		}
+		return (double) mach_absolute_time() * (double) timebase_info.numer / ((double) timebase_info.denom * 1e9);
+#endif
+		return 0;
+	}
+
+	u32 RGFW_getFPS(void) {
+		static double previousSeconds = 0.0;
+		if (previousSeconds == 0.0)
+			previousSeconds = (double) RGFW_getTime();//glfwGetTime();
+
+		static i16 frameCount;
+		double currentSeconds = (double) RGFW_getTime();//glfwGetTime();
+		double elapsedSeconds = currentSeconds - previousSeconds;
+		static double fps = 0;
+
+		if (elapsedSeconds > 0.25) {
+			previousSeconds = currentSeconds;
+			fps = (double) frameCount / elapsedSeconds;
+			frameCount = 0;
+		}
+
+		frameCount++;
+
+		return (u32) fps;
+	}
+
+#endif /*RGFW_IMPLEMENTATION*/
+
+#define RGFW_Escape RGFW_OS_BASED_VALUE(0xff1b, 0x1B, 53)
+#define RGFW_F1 RGFW_OS_BASED_VALUE(0xffbe, 0x70, 127)
+#define RGFW_F2 RGFW_OS_BASED_VALUE(0xffbf, 0x71, 121)
+#define RGFW_F3 RGFW_OS_BASED_VALUE(0xffc0, 0x72, 100)
+#define RGFW_F4 RGFW_OS_BASED_VALUE(0xffc1, 0x73, 119)
+#define RGFW_F5 RGFW_OS_BASED_VALUE(0xffc2, 0x74, 97)
+#define RGFW_F6 RGFW_OS_BASED_VALUE(0xffc3, 0x75, 98)
+#define RGFW_F7 RGFW_OS_BASED_VALUE(0xffc4, 0x76, 99)
+#define RGFW_F8 RGFW_OS_BASED_VALUE(0xffc5, 0x77, 101)
+#define RGFW_F9 RGFW_OS_BASED_VALUE(0xffc6, 0x78, 102)
+#define RGFW_F10 RGFW_OS_BASED_VALUE(0xffc7, 0x79, 110)
+#define RGFW_F11 RGFW_OS_BASED_VALUE(0xffc8, 0x7A, 104)
+#define RGFW_F12 RGFW_OS_BASED_VALUE(0xffc9, 0x7B, 112)
+#define RGFW_F13 RGFW_OS_BASED_VALUE(0xffca, 0x7C, 106)
+#define RGFW_F14 RGFW_OS_BASED_VALUE(0xffcb, 0x7D, 108)
+#define RGFW_F15 RGFW_OS_BASED_VALUE(0xffcc, 0x7E, 114)
+
+#define RGFW_Backtick RGFW_OS_BASED_VALUE(96 , 192, 50)
+
+#define RGFW_0 RGFW_OS_BASED_VALUE(0x0030, 0x30, 29)
+#define RGFW_1 RGFW_OS_BASED_VALUE(0x0031, 0x31, 18)
+#define RGFW_2 RGFW_OS_BASED_VALUE(0x0032, 0x32, 19)
+#define RGFW_3 RGFW_OS_BASED_VALUE(0x0033, 0x33, 20)
+#define RGFW_4 RGFW_OS_BASED_VALUE(0x0034, 0x34, 21)
+#define RGFW_5 RGFW_OS_BASED_VALUE(0x0035, 0x35, 23)
+#define RGFW_6 RGFW_OS_BASED_VALUE(0x0036, 0x36, 22)
+#define RGFW_7 RGFW_OS_BASED_VALUE(0x0037, 0x37, 26)
+#define RGFW_8 RGFW_OS_BASED_VALUE(0x0038, 0x38, 28)
+#define RGFW_9 RGFW_OS_BASED_VALUE(0x0039, 0x39, 25)
+
+#define RGFW_Minus RGFW_OS_BASED_VALUE(0x002d, 189, 27)
+#define RGFW_Equals RGFW_OS_BASED_VALUE(0x003d, 187, 24)
+#define RGFW_BackSpace RGFW_OS_BASED_VALUE(0xff08, 8, 51)
+#define RGFW_Tab RGFW_OS_BASED_VALUE(0xff89, 0x09, 48)
+#define RGFW_CapsLock RGFW_OS_BASED_VALUE(0xffe5, 20, 57)
+#define RGFW_ShiftL RGFW_OS_BASED_VALUE(0xffe1, 0xA0, 56)
+#define RGFW_ControlL RGFW_OS_BASED_VALUE(0xffe3, 0x11, 59)
+#define RGFW_AltL RGFW_OS_BASED_VALUE(0xffe9, 164, 58)
+#define RGFW_SuperL RGFW_OS_BASED_VALUE(0xffeb, 0x5B, 55) 
+#define RGFW_ShiftR RGFW_OS_BASED_VALUE(0xffe2, 0x5C, 56)
+#define RGFW_ControlR RGFW_OS_BASED_VALUE(0xffe4, 0x11, 59)
+#define RGFW_AltR RGFW_OS_BASED_VALUE(0xffea, 165, 58)
+#define RGFW_SuperR RGFW_OS_BASED_VALUE(0xffec, 0xA4, 55)
+#define RGFW_Space RGFW_OS_BASED_VALUE(0x0020,  0x20, 49)
+
+#define RGFW_A RGFW_OS_BASED_VALUE(0x0041, 0x41, 0)
+#define RGFW_B RGFW_OS_BASED_VALUE(0x0042, 0x42, 11)
+#define RGFW_C RGFW_OS_BASED_VALUE(0x0043, 0x43, 8)
+#define RGFW_D RGFW_OS_BASED_VALUE(0x0044, 0x44, 2)
+#define RGFW_E RGFW_OS_BASED_VALUE(0x0045, 0x45, 14)
+#define RGFW_F RGFW_OS_BASED_VALUE(0x0046, 0x46, 3)
+#define RGFW_G RGFW_OS_BASED_VALUE(0x0047, 0x47, 5)
+#define RGFW_H RGFW_OS_BASED_VALUE(0x0048, 0x48, 4) 
+#define RGFW_I RGFW_OS_BASED_VALUE(0x0049, 0x49, 34)
+#define RGFW_J RGFW_OS_BASED_VALUE(0x004a, 0x4A, 38)
+#define RGFW_K RGFW_OS_BASED_VALUE(0x004b, 0x4B, 40)
+#define RGFW_L RGFW_OS_BASED_VALUE(0x004c, 0x4C, 37)
+#define RGFW_M RGFW_OS_BASED_VALUE(0x004d, 0x4D, 46)
+#define RGFW_N RGFW_OS_BASED_VALUE(0x004e, 0x4E, 45)
+#define RGFW_O RGFW_OS_BASED_VALUE(0x004f, 0x4F, 31)
+#define RGFW_P RGFW_OS_BASED_VALUE(0x0050, 0x50, 35)
+#define RGFW_Q RGFW_OS_BASED_VALUE(0x0051, 0x51, 12)
+#define RGFW_R RGFW_OS_BASED_VALUE(0x0052, 0x52, 15)
+#define RGFW_S RGFW_OS_BASED_VALUE(0x0053, 0x53, 1)
+#define RGFW_T RGFW_OS_BASED_VALUE(0x0054, 0x54, 17)
+#define RGFW_U RGFW_OS_BASED_VALUE(0x0055, 0x55, 32)
+#define RGFW_V RGFW_OS_BASED_VALUE(0x0056, 0x56, 9)
+#define RGFW_W RGFW_OS_BASED_VALUE(0x0057, 0x57, 13)
+#define RGFW_X RGFW_OS_BASED_VALUE(0x0058, 0x58, 7)
+#define RGFW_Y RGFW_OS_BASED_VALUE(0x0059, 0x59, 16)
+#define RGFW_Z RGFW_OS_BASED_VALUE(0x005a, 0x5A, 6)
+
+#define RGFW_a RGFW_OS_BASED_VALUE(0x0061, 0x41, 0)
+#define RGFW_b RGFW_OS_BASED_VALUE(0x0062, 0x42, 11)
+#define RGFW_c RGFW_OS_BASED_VALUE(0x0063, 0x43, 8)
+#define RGFW_d RGFW_OS_BASED_VALUE(0x0064, 0x44, 2)
+#define RGFW_e RGFW_OS_BASED_VALUE(0x0065, 0x45, 14)
+#define RGFW_f RGFW_OS_BASED_VALUE(0x0066, 0x46, 3)
+#define RGFW_g RGFW_OS_BASED_VALUE(0x0067, 0x47, 5)
+#define RGFW_h RGFW_OS_BASED_VALUE(0x0068, 0x48, 4)
+#define RGFW_i RGFW_OS_BASED_VALUE(0x0069, 0x49, 34)
+#define RGFW_j RGFW_OS_BASED_VALUE(0x006a, 0x4a, 38)
+#define RGFW_k RGFW_OS_BASED_VALUE(0x006b, 0x4b, 40)
+#define RGFW_l RGFW_OS_BASED_VALUE(0x006c, 0x4c, 37)
+#define RGFW_m RGFW_OS_BASED_VALUE(0x006d, 0x4d, 46)
+#define RGFW_n RGFW_OS_BASED_VALUE(0x006e, 0x4e, 45)
+#define RGFW_o RGFW_OS_BASED_VALUE(0x006f, 0x4f, 31)
+#define RGFW_p RGFW_OS_BASED_VALUE(0x0070, 0x50, 35)
+#define RGFW_q RGFW_OS_BASED_VALUE(0x0071, 0x51, 12)
+#define RGFW_r RGFW_OS_BASED_VALUE(0x0072, 0x52, 15)
+#define RGFW_s RGFW_OS_BASED_VALUE(0x0073, 0x53, 1)
+#define RGFW_t RGFW_OS_BASED_VALUE(0x0074, 0x54, 17)
+#define RGFW_u RGFW_OS_BASED_VALUE(0x0075, 0x55, 32)
+#define RGFW_v RGFW_OS_BASED_VALUE(0x0076, 0x56, 9)
+#define RGFW_w RGFW_OS_BASED_VALUE(0x0077, 0x57, 13)
+#define RGFW_x RGFW_OS_BASED_VALUE(0x0078, 0x58, 7) 
+#define RGFW_y RGFW_OS_BASED_VALUE(0x0079, 0x59, 16)
+#define RGFW_z RGFW_OS_BASED_VALUE(0x007a, 0x5A, 6)
+
+#define RGFW_Period RGFW_OS_BASED_VALUE(0x002e, 190, 47)
+#define RGFW_Comma RGFW_OS_BASED_VALUE(0x002c, 188, 43)
+#define RGFW_Slash RGFW_OS_BASED_VALUE(0x002f, 191, 44)
+#define RGFW_Bracket RGFW_OS_BASED_VALUE(0x005b, 219, 33)
+#define RGFW_CloseBracket RGFW_OS_BASED_VALUE(0x005d, 221, 30) 
+#define RGFW_Semicolon RGFW_OS_BASED_VALUE(0x003b, 186, 41)
+#define RGFW_Return RGFW_OS_BASED_VALUE(0xff0d, 0x0D, 36) 
+#define RGFW_Quote RGFW_OS_BASED_VALUE(0x0022, 222, 39)
+#define RGFW_BackSlash RGFW_OS_BASED_VALUE(0x005c, 322, 42)
+
+#define RGFW_Up RGFW_OS_BASED_VALUE(0xff52, 0x26, 126)
+#define RGFW_Down RGFW_OS_BASED_VALUE(0xff54, 0x28, 125)
+#define RGFW_Left RGFW_OS_BASED_VALUE(0xff51, 0x25, 123)
+#define RGFW_Right RGFW_OS_BASED_VALUE(0xff53, 0x27, 124)
+
+#define RGFW_Delete RGFW_OS_BASED_VALUE(0xffff, 0x2E, 118)
+#define RGFW_Insert RGFW_OS_BASED_VALUE(0xff63, 0x2D, 115)
+#define RGFW_End RGFW_OS_BASED_VALUE(0xff57, 0x23, 120)
+#define RGFW_Home RGFW_OS_BASED_VALUE(0xff50, 0x24, 116) 
+#define RGFW_PageUp RGFW_OS_BASED_VALUE(0xff55, 336, 117)
+#define RGFW_PageDown RGFW_OS_BASED_VALUE(0xff56, 325, 122)
+
+#define RGFW_Numlock RGFW_OS_BASED_VALUE(0xff7f, 0x90, 72)
+#define RGFW_KP_Slash RGFW_OS_BASED_VALUE(0xffaf, 0x6F, 82)
+#define RGFW_Multiply RGFW_OS_BASED_VALUE(0xffaa, 0x6A, 76)
+#define RGFW_KP_Minus RGFW_OS_BASED_VALUE(0xffad, 0x6D, 67)
+#define RGFW_KP_1 RGFW_OS_BASED_VALUE(0xffb1, 0x61, 84)
+#define RGFW_KP_2 RGFW_OS_BASED_VALUE(0xffb2, 0x62, 85)
+#define RGFW_KP_3 RGFW_OS_BASED_VALUE(0xffb3, 0x63, 86)
+#define RGFW_KP_4 RGFW_OS_BASED_VALUE(0xffb4, 0x64, 87)
+#define RGFW_KP_5 RGFW_OS_BASED_VALUE(0xffb5, 0x65, 88)
+#define RGFW_KP_6 RGFW_OS_BASED_VALUE(0xffb6, 0x66, 89)
+#define RGFW_KP_7 RGFW_OS_BASED_VALUE(0xffb7, 0x67, 90)
+#define RGFW_KP_8 RGFW_OS_BASED_VALUE(0xffb8, 0x68, 92)
+#define RGFW_KP_9 RGFW_OS_BASED_VALUE(0xffb9, 0x619, 93)
+#define RGFW_KP_0 RGFW_OS_BASED_VALUE(0xffb0, 0x60, 83)
+#define RGFW_KP_Period RGFW_OS_BASED_VALUE(0xffae, 0x6E, 65)
+#define RGFW_KP_Return RGFW_OS_BASED_VALUE(0xff8d, 0x92, 77)
+
+#ifdef __APPLE__
+	void* NSCursor_arrowStr(char* str);
+	void NSCursor_performSelector(void* cursor, void* selector);
+#endif
+
+	/* mouse icons */
+#define RGFW_MOUSE_ARROW 				RGFW_OS_BASED_VALUE(68,   32512, NSCursor_arrowStr("arrowCursor"))
+#define RGFW_MOUSE_IBEAM 				RGFW_OS_BASED_VALUE(152,  32513, NSCursor_arrowStr("IBeamCursor"))
+#define RGFW_MOUSE_CROSSHAIR		 	RGFW_OS_BASED_VALUE(34,   32515, NSCursor_arrowStr("crosshairCursor"))
+#define RGFW_MOUSE_POINTING_HAND 		RGFW_OS_BASED_VALUE(60,   32649, NSCursor_arrowStr("pointingHandCursor"))
+#define RGFW_MOUSE_RESIZE_EW 			RGFW_OS_BASED_VALUE(108,  32644, NSCursor_arrowStr("resizeLeftRightCursor"))
+#define RGFW_MOUSE_RESIZE_NS  			RGFW_OS_BASED_VALUE(116,  32645, NSCursor_arrowStr("resizeUpDownCursor"))
+#define RGFW_MOUSE_RESIZE_ALL 			RGFW_OS_BASED_VALUE(52,   32646, NSCursor_arrowStr("closedHandCursor"))
+#define RGFW_MOUSE_RESIZE_NWSE 			RGFW_OS_BASED_VALUE(12,   32642, NSCursor_performSelector(selector("_windowResizeNorthWestSouthEastCursor")))
+#define RGFW_MOUSE_RESIZE_NESW 			RGFW_OS_BASED_VALUE(14,   32643, NSCursor_performSelector(selector("_windowResizeNorthEastSouthWestCursor")))
+#define RGFW_MOUSE_NOT_ALLOWED 			RGFW_OS_BASED_VALUE(0,    32648, NSCursor_arrowStr("operationNotAllowedCursor"))
+
+#ifdef __cplusplus
+}
+#endif

+ 1519 - 0
src/platforms/rcore_desktop_rgfw.c

@@ -0,0 +1,1519 @@
+/**********************************************************************************************
+*
+*   rcore_desktop_rgfw template - Functions to manage window, graphics device and inputs
+*
+*   PLATFORM: RGFW
+*       - Windows (Win32, Win64)
+*       - Linux (X11/Wayland desktop mode)
+*       - MacOS (Cocoa)
+*
+*   LIMITATIONS:
+*       - Limitation 01
+*       - Limitation 02
+*
+*   POSSIBLE IMPROVEMENTS:
+*       - Improvement 01
+*       - Improvement 02
+*
+*   ADDITIONAL NOTES:
+*       - TRACELOG() function is located in raylib [utils] module
+*
+*   CONFIGURATION:
+*       #define RCORE_PLATFORM_CUSTOM_FLAG
+*           Custom flag for rcore on target platform -not used-
+*
+*   DEPENDENCIES:
+*       - RGFW.h (main library): Windowing and inputs management
+*       - gestures: Gestures system for touch-ready devices (or simulated from mouse inputs)
+*
+*
+*   LICENSE: zlib/libpng
+*
+*   Copyright (c) 2013-2024 Ramon Santamaria (@raysan5), Colleague Riley and contributors
+*
+*   This software is provided "as-is", without any express or implied warranty. In no event
+*   will the authors be held liable for any damages arising from the use of this software.
+*
+*   Permission is granted to anyone to use this software for any purpose, including commercial
+*   applications, and to alter it and redistribute it freely, subject to the following restrictions:
+*
+*     1. The origin of this software must not be misrepresented; you must not claim that you
+*     wrote the original software. If you use this software in a product, an acknowledgment
+*     in the product documentation would be appreciated but is not required.
+*
+*     2. Altered source versions must be plainly marked as such, and must not be misrepresented
+*     as being the original software.
+*
+*     3. This notice may not be removed or altered from any source distribution.
+*
+**********************************************************************************************/
+
+#ifdef GRAPHICS_API_OPENGL_ES2
+#define RGFW_OPENGL_ES2
+#endif
+
+void ShowCursor(void);
+void CloseWindow(void);
+
+#define _INPUT_EVENT_CODES_H
+#define _APISETSTRING_
+#define RGFWDEF
+#define _XTYPEDEF_FONT
+#define RGFW_IMPLEMENTATION
+
+#define WIN32_LEAN_AND_MEAN
+#define Rectangle rectangle_win32
+#define CloseWindow CloseWindow_win32
+#define ShowCursor __imp_ShowCursor
+
+#define Point NSPOINT
+#define Size NSSIZE
+
+#ifdef _MSC_VER
+__declspec(dllimport) int __stdcall  MultiByteToWideChar(unsigned int CodePage, unsigned long dwFlags, const char* lpMultiByteStr, int cbMultiByte, wchar_t* lpWideCharStr, int cchWideChar);
+#endif
+
+#include "../external/RGFW.h"
+#undef DrawText
+#undef ShowCursor
+#undef CloseWindow
+#undef Point
+#undef Size
+
+#define Rectangle struct Rectangle
+void CloseWindow(void);
+void ShowCursor(void);
+
+
+#include <stdbool.h>
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//----------------------------------------------------------------------------------
+typedef struct {
+    // TODO: Define the platform specific variables required
+
+    RGFW_window* window;                  // Native display device (physical screen connection)
+} PlatformData;
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition
+//----------------------------------------------------------------------------------
+extern CoreData CORE;                   // Global CORE state context
+
+static PlatformData platform = { NULL };   // Platform specific 
+
+//----------------------------------------------------------------------------------
+// Module Internal Functions Declaration
+//----------------------------------------------------------------------------------
+int InitPlatform(void);          // Initialize platform (graphics, inputs and more)
+bool InitGraphicsDevice(void);   // Initialize graphics device
+
+//----------------------------------------------------------------------------------
+// Module Functions Declaration
+//----------------------------------------------------------------------------------
+// NOTE: Functions declaration is provided by raylib.h
+
+//----------------------------------------------------------------------------------
+// Module Functions Definition: Window and Graphics Device
+//----------------------------------------------------------------------------------
+
+// Check if application should close
+bool WindowShouldClose(void)
+{   
+    if (CORE.Window.shouldClose == false)
+        CORE.Window.shouldClose = RGFW_window_shouldClose(platform.window);
+    if (CORE.Window.ready) return CORE.Window.shouldClose;
+    else return true;
+}
+
+// Toggle fullscreen mode
+void ToggleFullscreen(void)
+{   
+    RGFW_window_maximize(platform.window);
+    ToggleBorderlessWindowed();
+}
+
+// Toggle borderless windowed mode
+void ToggleBorderlessWindowed(void)
+{
+    CORE.Window.flags & FLAG_WINDOW_UNDECORATED;
+    
+    if (platform.window != NULL)
+        TRACELOG(LOG_WARNING, "ToggleBorderlessWindowed() after window creation not available on target platform");
+}
+
+// Set window state: maximized, if resizable
+void MaximizeWindow(void)
+{
+    RGFW_window_maximize(platform.window);
+}
+
+// Set window state: minimized
+void MinimizeWindow(void)
+{
+    RGFW_window_minimize(platform.window);
+}
+
+// Set window state: not minimized/maximized
+void RestoreWindow(void)
+{
+    RGFW_window_restore(platform.window);
+}
+
+// Set window configuration state using flags
+void SetWindowState(unsigned int flags)
+{
+    CORE.Window.flags |= flags;
+
+    if (flags & FLAG_VSYNC_HINT)
+    {
+        RGFW_window_swapInterval(platform.window, 1);
+    }
+    if (flags & FLAG_FULLSCREEN_MODE)
+    {
+        RGFW_window_maximize(platform.window);
+        ToggleBorderlessWindowed();
+    }
+    if (flags & FLAG_WINDOW_RESIZABLE)
+    {
+        RGFW_window_setMaxSize(platform.window, RGFW_AREA(platform.window->r.w, platform.window->r.h));
+        RGFW_window_setMinSize(platform.window, RGFW_AREA(platform.window->r.w, platform.window->r.h));
+    }
+    if (flags & FLAG_WINDOW_UNDECORATED)
+    {
+        ToggleBorderlessWindowed();
+    }
+    if (flags & FLAG_WINDOW_HIDDEN)
+    {
+        RGFW_window_hide(platform.window);
+    }
+    if (flags & FLAG_WINDOW_MINIMIZED)
+    {
+        RGFW_window_minimize(platform.window);
+    }
+    if (flags & FLAG_WINDOW_MAXIMIZED)
+    {
+        RGFW_window_maximize(platform.window);
+    }
+    if (flags & FLAG_WINDOW_UNFOCUSED)
+    {
+        TRACELOG(LOG_WARNING, "SetWindowState() - FLAG_WINDOW_UNFOCUSED is not supported on PLATFORM_DESKTOP_SDL");
+    }
+    if (flags & FLAG_WINDOW_TOPMOST)
+    {
+        TRACELOG(LOG_WARNING, "SetWindowState() - FLAG_WINDOW_TOPMOST is not supported on PLATFORM_DESKTOP_RGFW");
+    }
+    if (flags & FLAG_WINDOW_ALWAYS_RUN)
+    {
+        TRACELOG(LOG_WARNING, "SetWindowState() - FLAG_WINDOW_ALWAYS_RUN is not supported on PLATFORM_DESKTOP_RGFW");
+    }
+    if (flags & FLAG_WINDOW_TRANSPARENT)
+    {
+        TRACELOG(LOG_WARNING, "SetWindowState() - FLAG_WINDOW_TRANSPARENT is not supported on PLATFORM_DESKTOP_RGFW");
+    }
+    if (flags & FLAG_WINDOW_HIGHDPI)
+    {
+        TRACELOG(LOG_WARNING, "SetWindowState() - FLAG_WINDOW_HIGHDPI is not supported on PLATFORM_DESKTOP_RGFW");
+    }
+    if (flags & FLAG_WINDOW_MOUSE_PASSTHROUGH)
+    {
+        TRACELOG(LOG_WARNING, "SetWindowState() - FLAG_WINDOW_MOUSE_PASSTHROUGH is not supported on PLATFORM_DESKTOP_RGFW");
+    }
+    if (flags & FLAG_BORDERLESS_WINDOWED_MODE)
+    {
+        ToggleBorderlessWindowed();
+    }
+    if (flags & FLAG_MSAA_4X_HINT)
+    {
+        RGFW_setGLSamples(4);
+    }
+    if (flags & FLAG_INTERLACED_HINT)
+    {
+        TRACELOG(LOG_WARNING, "SetWindowState() - FLAG_INTERLACED_HINT is not supported on PLATFORM_DESKTOP_RGFW");
+    }
+}
+
+// Clear window configuration state flags
+void ClearWindowState(unsigned int flags)
+{
+    CORE.Window.flags &= ~flags;
+
+    if (flags & FLAG_VSYNC_HINT)
+    {
+        RGFW_window_swapInterval(platform.window, 0);
+    }
+    if (flags & FLAG_FULLSCREEN_MODE)
+    {
+        ToggleBorderlessWindowed();
+        RGFW_window_restore(platform.window);
+        CORE.Window.fullscreen = false;
+    }
+    if (flags & FLAG_WINDOW_RESIZABLE)
+    {
+        RGFW_window_setMaxSize(platform.window, RGFW_AREA(0, 0));
+        RGFW_window_setMinSize(platform.window, RGFW_AREA(0, 0));
+    }
+    if (flags & FLAG_WINDOW_UNDECORATED)
+    {
+        ToggleBorderlessWindowed();
+    }
+    if (flags & FLAG_WINDOW_HIDDEN)
+    {
+        RGFW_window_show(platform.window);
+    }
+    if (flags & FLAG_WINDOW_MINIMIZED)
+    {
+        RGFW_window_restore(platform.window);
+    }
+    if (flags & FLAG_WINDOW_MAXIMIZED)
+    {
+        RGFW_window_restore(platform.window);
+    }
+    if (flags & FLAG_WINDOW_UNFOCUSED)
+    {
+        TRACELOG(LOG_WARNING, "ClearWindowState() - FLAG_WINDOW_UNFOCUSED is not supported on PLATFORM_DESKTOP_RGFW");
+    }
+    if (flags & FLAG_WINDOW_TOPMOST)
+    {
+        TRACELOG(LOG_WARNING, "ClearWindowState() - FLAG_WINDOW_TOPMOST is not supported on PLATFORM_DESKTOP_RGFW");
+    }
+    if (flags & FLAG_WINDOW_ALWAYS_RUN)
+    {
+        TRACELOG(LOG_WARNING, "ClearWindowState() - FLAG_WINDOW_ALWAYS_RUN is not supported on PLATFORM_DESKTOP_RGFW");
+    }
+    if (flags & FLAG_WINDOW_TRANSPARENT)
+    {
+        TRACELOG(LOG_WARNING, "ClearWindowState() - FLAG_WINDOW_TRANSPARENT is not supported on PLATFORM_DESKTOP_RGFW");
+    }
+    if (flags & FLAG_WINDOW_HIGHDPI)
+    {
+        // NOTE: There also doesn't seem to be a feature to disable high DPI once enabled
+        TRACELOG(LOG_WARNING, "ClearWindowState() - FLAG_WINDOW_HIGHDPI is not supported on PLATFORM_DESKTOP_RGFW");
+    }
+    if (flags & FLAG_WINDOW_MOUSE_PASSTHROUGH)
+    {
+        //SDL_SetWindowGrab(platform.window, SDL_TRUE);
+        TRACELOG(LOG_WARNING, "ClearWindowState() - FLAG_WINDOW_MOUSE_PASSTHROUGH is not supported on PLATFORM_DESKTOP_RGFW");
+    }
+    if (flags & FLAG_BORDERLESS_WINDOWED_MODE)
+    {
+        ToggleFullscreen();
+    }
+    if (flags & FLAG_MSAA_4X_HINT)
+    {
+        RGFW_setGLSamples(0);
+    }
+    if (flags & FLAG_INTERLACED_HINT)
+    {
+        TRACELOG(LOG_WARNING, "ClearWindowState() - FLAG_INTERLACED_HINT is not supported on PLATFORM_DESKTOP_RGFW");
+    }
+}
+
+// Set icon for window
+void SetWindowIcon(Image image)
+{
+    i32 channels = 4; 
+
+    switch (image.format) {
+        case PIXELFORMAT_UNCOMPRESSED_GRAYSCALE:
+        case PIXELFORMAT_UNCOMPRESSED_R16:           // 16 bpp (1 channel - half float)
+        case PIXELFORMAT_UNCOMPRESSED_R32:           // 32 bpp (1 channel - float)
+            channels = 1;
+            break;
+        
+        case PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA:    // 8*2 bpp (2 channels)
+        case PIXELFORMAT_UNCOMPRESSED_R5G6B5:        // 16 bpp
+        case PIXELFORMAT_UNCOMPRESSED_R8G8B8:        // 24 bpp
+        case PIXELFORMAT_UNCOMPRESSED_R5G5B5A1:      // 16 bpp (1 bit alpha)
+        case PIXELFORMAT_UNCOMPRESSED_R4G4B4A4:      // 16 bpp (4 bit alpha)
+        case PIXELFORMAT_UNCOMPRESSED_R8G8B8A8:      // 32 bpp
+            channels = 2;
+            break;
+        
+        case PIXELFORMAT_UNCOMPRESSED_R32G32B32:     // 32*3 bpp (3 channels - float)
+        case PIXELFORMAT_UNCOMPRESSED_R16G16B16:     // 16*3 bpp (3 channels - half float)
+        case PIXELFORMAT_COMPRESSED_DXT1_RGB:        // 4 bpp (no alpha)
+        case PIXELFORMAT_COMPRESSED_ETC1_RGB:        // 4 bpp
+        case PIXELFORMAT_COMPRESSED_ETC2_RGB:        // 4 bpp
+        case PIXELFORMAT_COMPRESSED_PVRT_RGB:        // 4 bpp
+            channels = 3;
+            break;
+
+        case PIXELFORMAT_UNCOMPRESSED_R32G32B32A32:  // 32*4 bpp (4 channels - float)
+        case PIXELFORMAT_UNCOMPRESSED_R16G16B16A16:  // 16*4 bpp (4 channels - half float)
+        case PIXELFORMAT_COMPRESSED_DXT1_RGBA:       // 4 bpp (1 bit alpha)
+        case PIXELFORMAT_COMPRESSED_DXT3_RGBA:       // 8 bpp
+        case PIXELFORMAT_COMPRESSED_DXT5_RGBA:       // 8 bpp
+        case PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA:   // 8 bpp
+        case PIXELFORMAT_COMPRESSED_PVRT_RGBA:       // 4 bpp
+        case PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA:   // 8 bpp
+        case PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA:    // 2 bpp
+            channels = 4;
+            break;
+
+        default: break;
+    }
+
+    RGFW_window_setIcon(platform.window, image.data, RGFW_AREA(image.width, image.height), channels);
+}
+
+// Set icon for window
+void SetWindowIcons(Image *images, int count)
+{
+    TRACELOG(LOG_WARNING, "SetWindowIcons() not available on target platform");
+}
+
+// Set title for window
+void SetWindowTitle(const char *title)
+{
+    RGFW_window_setName(platform.window, title);
+    CORE.Window.title = title;
+}
+
+// Set window position on screen (windowed mode)
+void SetWindowPosition(int x, int y)
+{
+    RGFW_window_move(platform.window, RGFW_VECTOR(x, y));
+}
+
+// Set monitor for the current window
+void SetWindowMonitor(int monitor)
+{
+    RGFW_window_moveToMonitor(platform.window, RGFW_getMonitors()[monitor]);
+}
+
+// Set window minimum dimensions (FLAG_WINDOW_RESIZABLE)
+void SetWindowMinSize(int width, int height)
+{
+    RGFW_window_setMinSize(platform.window, RGFW_AREA(width, height));
+    CORE.Window.screenMin.width = width;
+    CORE.Window.screenMin.height = height;
+}
+
+// Set window maximum dimensions (FLAG_WINDOW_RESIZABLE)
+void SetWindowMaxSize(int width, int height)
+{
+    RGFW_window_setMaxSize(platform.window, RGFW_AREA(width, height));
+    CORE.Window.screenMax.width = width;
+    CORE.Window.screenMax.height = height;
+}
+
+// Set window dimensions
+void SetWindowSize(int width, int height)
+{
+    RGFW_window_resize(platform.window, RGFW_AREA(width, height));
+}
+
+// Set window opacity, value opacity is between 0.0 and 1.0
+void SetWindowOpacity(float opacity)
+{
+    TRACELOG(LOG_WARNING, "SetWindowOpacity() not available on target platform");
+}
+
+// Set window focused
+void SetWindowFocused(void)
+{
+    RGFW_window_show(platform.window);
+}
+
+// Get native window handle
+void *GetWindowHandle(void)
+{
+    return platform.window->src.window;
+}
+
+// Get number of monitors
+int GetMonitorCount(void)
+{
+    RGFW_monitor* mons = RGFW_getMonitors();
+    u32 i;
+    for (i = 0; i < 6; i++) {
+        if (!mons[i].rect.x && !mons[i].rect.y && !mons[i].rect.w && mons[i].rect.h)
+            return i;
+    }
+
+    return 6;
+}
+
+// Get number of monitors
+int GetCurrentMonitor(void)
+{
+    RGFW_monitor* mons = RGFW_getMonitors();
+    RGFW_monitor mon = RGFW_window_getMonitor(platform.window);
+
+    u32 i;
+    for (i = 0; i < 6; i++) {
+        if (mons[i].rect.x ==  mon.rect.x && 
+            mons[i].rect.y ==  mon.rect.y)
+            return i;
+    }
+
+    return 0;
+}
+
+// Get selected monitor position
+Vector2 GetMonitorPosition(int monitor)
+{
+    RGFW_monitor* mons = RGFW_getMonitors();
+
+    return (Vector2){mons[monitor].rect.x, mons[monitor].rect.y}; 
+}
+
+// Get selected monitor width (currently used by monitor)
+int GetMonitorWidth(int monitor)
+{
+    RGFW_monitor* mons = RGFW_getMonitors();
+
+    return mons[monitor].rect.w; 
+}
+
+// Get selected monitor height (currently used by monitor)
+int GetMonitorHeight(int monitor)
+{
+    RGFW_monitor* mons = RGFW_getMonitors();
+
+    return mons[monitor].rect.h; 
+    return 0;
+}
+
+// Get selected monitor physical width in millimetres
+int GetMonitorPhysicalWidth(int monitor)
+{
+    RGFW_monitor* mons = RGFW_getMonitors();
+
+    return mons[monitor].physW; 
+}
+
+// Get selected monitor physical height in millimetres
+int GetMonitorPhysicalHeight(int monitor)
+{
+    RGFW_monitor* mons = RGFW_getMonitors();
+
+    return mons[monitor].physH; 
+}
+
+// Get selected monitor refresh rate
+int GetMonitorRefreshRate(int monitor)
+{
+    TRACELOG(LOG_WARNING, "GetMonitorRefreshRate() not implemented on target platform");
+    return 0;
+}
+
+// Get the human-readable, UTF-8 encoded name of the selected monitor
+const char *GetMonitorName(int monitor)
+{
+    RGFW_monitor* mons = RGFW_getMonitors();
+
+    return mons[monitor].name;
+}
+
+// Get window position XY on monitor
+Vector2 GetWindowPosition(void)
+{
+    return (Vector2){ platform.window->r.x, platform.window->r.y };
+}
+
+// Get window scale DPI factor for current monitor
+Vector2 GetWindowScaleDPI(void)
+{
+    RGFW_monitor monitor = RGFW_window_getMonitor(platform.window);
+
+    return (Vector2){((u32)monitor.scaleX) * platform.window->r.w, ((u32) monitor.scaleX) * platform.window->r.h};
+}
+
+// Set clipboard text content
+void SetClipboardText(const char *text)
+{
+    RGFW_writeClipboard(text, strlen(text));
+}
+
+// Get clipboard text content
+// NOTE: returned string is allocated and freed by GLFW
+const char *GetClipboardText(void)
+{
+    return RGFW_readClipboard(NULL);
+}
+
+// Show mouse cursor
+void ShowCursor(void)
+{
+    RGFW_window_showMouse(platform.window, true);
+    CORE.Input.Mouse.cursorHidden = false;
+}
+
+// Hides mouse cursor
+void HideCursor(void)
+{
+    RGFW_window_showMouse(platform.window, false);
+    CORE.Input.Mouse.cursorHidden = true;
+}
+
+// Enables cursor (unlock cursor)
+void EnableCursor(void)
+{
+    RGFW_window_mouseUnhold(platform.window);
+
+    // Set cursor position in the middle
+    SetMousePosition(CORE.Window.screen.width/2, CORE.Window.screen.height/2);
+    RGFW_window_showMouse(platform.window, true);
+    CORE.Input.Mouse.cursorHidden = false;
+}
+
+// Disables cursor (lock cursor)
+void DisableCursor(void)
+{
+    RGFW_window_mouseHold(platform.window);
+    // Set cursor position in the middle
+    SetMousePosition(CORE.Window.screen.width/2, CORE.Window.screen.height/2);
+
+    HideCursor();
+}
+
+// Swap back buffer with front buffer (screen drawing)
+void SwapScreenBuffer(void)
+{
+    RGFW_window_swapBuffers(platform.window);
+}
+
+//----------------------------------------------------------------------------------
+// Module Functions Definition: Misc
+//----------------------------------------------------------------------------------
+
+// Get elapsed time measure in seconds since InitTimer()
+double GetTime(void)
+{
+    double time = 0.0;
+    unsigned long long int nanoSeconds = RGFW_getTimeNS();
+    time = (double)(nanoSeconds - CORE.Time.base)*1e-9;  // Elapsed time since InitTimer()
+
+    return time;
+}
+
+// Open URL with default system browser (if available)
+// NOTE: This function is only safe to use if you control the URL given.
+// A user could craft a malicious string performing another action.
+// Only call this function yourself not with user input or make sure to check the string yourself.
+// Ref: https://github.com/raysan5/raylib/issues/686
+void OpenURL(const char *url)
+{
+    // Security check to (partially) avoid malicious code on target platform
+    if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character");
+    else
+    {
+        // TODO:
+    }
+}
+
+//----------------------------------------------------------------------------------
+// Module Functions Definition: Inputs
+//----------------------------------------------------------------------------------
+
+// Set internal gamepad mappings
+int SetGamepadMappings(const char *mappings)
+{
+    TRACELOG(LOG_WARNING, "SetGamepadMappings() not implemented on target platform");
+    return 0;
+}
+
+// Set mouse position XY
+void SetMousePosition(int x, int y)
+{
+    RGFW_window_moveMouse(platform.window, RGFW_VECTOR(x, y));
+    CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y };
+    CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
+}
+
+// Set mouse cursor
+void SetMouseCursor(int cursor)
+{
+    switch (cursor) {
+        case MOUSE_CURSOR_DEFAULT:
+            return RGFW_window_setMouseDefault(platform.window);
+        case MOUSE_CURSOR_ARROW:
+            return RGFW_window_setMouseStandard(platform.window, RGFW_MOUSE_ARROW);
+        case MOUSE_CURSOR_IBEAM:
+            return RGFW_window_setMouseStandard(platform.window, RGFW_MOUSE_IBEAM);
+        case MOUSE_CURSOR_CROSSHAIR:
+            return RGFW_window_setMouseStandard(platform.window, RGFW_MOUSE_CROSSHAIR);
+        case MOUSE_CURSOR_POINTING_HAND:
+            return RGFW_window_setMouseStandard(platform.window, RGFW_MOUSE_POINTING_HAND);
+        case MOUSE_CURSOR_RESIZE_EW:
+            return RGFW_window_setMouseStandard(platform.window, RGFW_MOUSE_RESIZE_EW);
+        case MOUSE_CURSOR_RESIZE_NS:
+            return RGFW_window_setMouseStandard(platform.window, RGFW_MOUSE_RESIZE_NS);
+        #ifndef RGFW_MACOS
+        case MOUSE_CURSOR_RESIZE_NWSE:
+            return RGFW_window_setMouseStandard(platform.window, RGFW_MOUSE_RESIZE_NWSE);
+        case MOUSE_CURSOR_RESIZE_NESW:
+            return RGFW_window_setMouseStandard(platform.window, RGFW_MOUSE_RESIZE_NESW);
+        #endif
+        case MOUSE_CURSOR_RESIZE_ALL:
+            return RGFW_window_setMouseStandard(platform.window, RGFW_MOUSE_RESIZE_ALL);
+        case MOUSE_CURSOR_NOT_ALLOWED:
+            return RGFW_window_setMouseStandard(platform.window, RGFW_MOUSE_NOT_ALLOWED);
+        default:
+            break;
+    }
+}
+
+static KeyboardKey ConvertScancodeToKey(u32 keycode);
+
+// Register all input events
+void PollInputEvents(void) 
+{
+#if defined(SUPPORT_GESTURES_SYSTEM)
+    // NOTE: Gestures update must be called every frame to reset gestures correctly
+    // because ProcessGestureEvent() is just called on an event, not every frame
+    UpdateGestures();
+#endif
+
+    // Reset keys/chars pressed registered
+    CORE.Input.Keyboard.keyPressedQueueCount = 0;
+    CORE.Input.Keyboard.charPressedQueueCount = 0;
+
+    // Reset mouse wheel
+    CORE.Input.Mouse.currentWheelMove.x = 0;
+    CORE.Input.Mouse.currentWheelMove.y = 0;
+
+    // Register previous mouse position
+    
+    // Reset last gamepad button/axis registered state
+
+    for (int i = 0; (i < 4) && (i < MAX_GAMEPADS); i++)
+    {
+        // Check if gamepad is available
+        if (CORE.Input.Gamepad.ready[i])
+        {
+            // Register previous gamepad button states
+            for (int k = 0; k < MAX_GAMEPAD_BUTTONS; k++)
+            {
+                CORE.Input.Gamepad.previousButtonState[i][k] = CORE.Input.Gamepad.currentButtonState[i][k];
+            }
+        }
+    }
+
+    // Register previous touch states
+    for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.previousTouchState[i] = CORE.Input.Touch.currentTouchState[i];
+
+    // Map touch position to mouse position for convenience
+    CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition;
+
+    int touchAction = -1;       // 0-TOUCH_ACTION_UP, 1-TOUCH_ACTION_DOWN, 2-TOUCH_ACTION_MOVE
+    bool realTouch = false;     // Flag to differentiate real touch gestures from mouse ones
+
+    // Register previous keys states
+    // NOTE: Android supports up to 260 keys
+    for (int i = 0; i < MAX_KEYBOARD_KEYS; i++)
+    {
+        CORE.Input.Keyboard.previousKeyState[i] = CORE.Input.Keyboard.currentKeyState[i];
+        CORE.Input.Keyboard.keyRepeatInFrame[i] = 0;
+    }
+
+    // Register previous mouse states
+    for (int i = 0; i < MAX_MOUSE_BUTTONS; i++) 
+        CORE.Input.Mouse.previousButtonState[i] = CORE.Input.Mouse.currentButtonState[i];
+
+    // Poll input events for current platform
+    //-----------------------------------------------------------------------------
+    CORE.Window.resizedLastFrame = false;
+
+
+    #define RGFW_HOLD_MOUSE			(1L<<2)
+    #if defined(RGFW_X11) //|| defined(RGFW_MACOS)
+    if (platform.window->src.winArgs & RGFW_HOLD_MOUSE) 
+    {
+        CORE.Input.Mouse.previousPosition = (Vector2){ 0.0f, 0.0f };
+        CORE.Input.Mouse.currentPosition = (Vector2){ 0.0f, 0.0f };
+    }
+    else {
+        CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
+    }
+    #endif
+
+    while (RGFW_window_checkEvent(platform.window))
+    {
+
+        if (platform.window->event.type >= RGFW_jsButtonPressed && platform.window->event.type <= RGFW_jsAxisMove) {
+            if (!CORE.Input.Gamepad.ready[platform.window->event.joystick])
+            {
+                CORE.Input.Gamepad.ready[platform.window->event.joystick] = true;
+                CORE.Input.Gamepad.axisCount[platform.window->event.joystick] = platform.window->event.axisesCount;
+                CORE.Input.Gamepad.name[platform.window->event.joystick][0] = '\0';
+                CORE.Input.Gamepad.axisState[platform.window->event.joystick][GAMEPAD_AXIS_LEFT_TRIGGER] = -1.0f;
+                CORE.Input.Gamepad.axisState[platform.window->event.joystick][GAMEPAD_AXIS_RIGHT_TRIGGER] = -1.0f;
+            }
+        }
+
+        RGFW_Event* event = &platform.window->event;
+
+        // All input events can be processed after polling
+        switch (event->type)
+        {
+            case RGFW_quit: CORE.Window.shouldClose = true; break;
+
+            case RGFW_dnd:      // Dropped file
+            {
+                size_t i; 
+                for (i = 0; i < event->droppedFilesCount; i++) {
+                    if (CORE.Window.dropFileCount == 0)
+                    {
+                        // When a new file is dropped, we reserve a fixed number of slots for all possible dropped files
+                        // at the moment we limit the number of drops at once to 1024 files but this behaviour should probably be reviewed
+                        // TODO: Pointers should probably be reallocated for any new file added...
+                        CORE.Window.dropFilepaths = (char **)RL_CALLOC(1024, sizeof(char *));
+
+                        CORE.Window.dropFilepaths[CORE.Window.dropFileCount] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char));
+                        strcpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event->droppedFiles[i]);
+    
+                        CORE.Window.dropFileCount++;
+                    }
+                    else if (CORE.Window.dropFileCount < 1024)
+                    {
+                        CORE.Window.dropFilepaths[CORE.Window.dropFileCount] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char));
+                        strcpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event->droppedFiles[i]);
+
+                        CORE.Window.dropFileCount++;
+                    }
+                    else TRACELOG(LOG_WARNING, "FILE: Maximum drag and drop files at once is limited to 1024 files!");
+                }
+            } break;
+
+            // Window events are also polled (Minimized, maximized, close...)
+            case RGFW_windowAttribsChange:
+            {
+                SetupViewport(platform.window->r.w, platform.window->r.h);
+                CORE.Window.position.x = platform.window->r.x;
+                CORE.Window.position.y = platform.window->r.x;
+                CORE.Window.screen.width = platform.window->r.w;
+                CORE.Window.screen.height =  platform.window->r.h;
+                CORE.Window.currentFbo.width = platform.window->r.w;;
+                CORE.Window.currentFbo.height = platform.window->r.h;
+                CORE.Window.resizedLastFrame = true;
+            } break;
+
+            // Keyboard events
+            case RGFW_keyPressed:
+            {
+                KeyboardKey key = ConvertScancodeToKey(event->keyCode);
+                
+                if (key != KEY_NULL) {
+                    // If key was up, add it to the key pressed queue
+                    if ((CORE.Input.Keyboard.currentKeyState[key] == 0) && (CORE.Input.Keyboard.keyPressedQueueCount < MAX_KEY_PRESSED_QUEUE))
+                    {
+                        CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = key;
+                        CORE.Input.Keyboard.keyPressedQueueCount++;
+                    }
+
+                    CORE.Input.Keyboard.currentKeyState[key] = 1;
+                }
+
+                // TODO: Put exitKey verification outside the switch?
+                if (CORE.Input.Keyboard.currentKeyState[CORE.Input.Keyboard.exitKey])
+                {
+                    CORE.Window.shouldClose = true;
+                }
+
+                // NOTE: event.text.text data comes an UTF-8 text sequence but we register codepoints (int)
+                // Check if there is space available in the queue
+                if (CORE.Input.Keyboard.charPressedQueueCount < MAX_CHAR_PRESSED_QUEUE)
+                {
+                    // Add character (codepoint) to the queue
+                    CORE.Input.Keyboard.charPressedQueue[CORE.Input.Keyboard.charPressedQueueCount] = RGFW_keystrToChar(event->keyName);
+                    CORE.Input.Keyboard.charPressedQueueCount++;
+                }
+            } break;
+
+            case RGFW_keyReleased:
+            {
+                KeyboardKey key = ConvertScancodeToKey(event->keyCode);
+                if (key != KEY_NULL) CORE.Input.Keyboard.currentKeyState[key] = 0;
+            } break;
+
+            // Check mouse events
+            case RGFW_mouseButtonPressed:
+            {
+                if (event->button == RGFW_mouseScrollUp || event->button == RGFW_mouseScrollDown) {
+                    CORE.Input.Mouse.currentWheelMove.y = event->scroll;
+                    break;
+                }
+
+                int btn = event->button;
+                if (btn == RGFW_mouseLeft) btn = 1;
+                else if (btn == RGFW_mouseRight) btn = 2;
+                else if (btn == RGFW_mouseMiddle) btn = 3;
+
+                CORE.Input.Mouse.currentButtonState[btn - 1] = 1;
+                CORE.Input.Touch.currentTouchState[btn - 1] = 1;
+
+                touchAction = 1;
+            } break;
+            case RGFW_mouseButtonReleased:
+            {
+
+                if (event->button == RGFW_mouseScrollUp || event->button == RGFW_mouseScrollDown) {
+                    CORE.Input.Mouse.currentWheelMove.y = event->scroll;
+                    break;
+                }
+                
+                int btn = event->button;
+                if (btn == RGFW_mouseLeft) btn = 1;
+                else if (btn == RGFW_mouseRight) btn = 2;
+                else if (btn == RGFW_mouseMiddle) btn = 3;
+
+                CORE.Input.Mouse.currentButtonState[btn - 1] = 0;
+                CORE.Input.Touch.currentTouchState[btn - 1] = 0;
+
+                touchAction = 0;
+            } break;
+            case RGFW_mousePosChanged:
+            {
+                if (platform.window->src.winArgs & RGFW_HOLD_MOUSE) {
+                                        
+                    CORE.Input.Mouse.previousPosition = (Vector2){ 0.0f, 0.0f };
+                    
+                    if ((event->point.x - (platform.window->r.w / 2)) * 2)
+                        CORE.Input.Mouse.previousPosition.x = CORE.Input.Mouse.currentPosition.x;    
+                    if ((event->point.y - (platform.window->r.h / 2)) * 2)
+                        CORE.Input.Mouse.previousPosition.y = CORE.Input.Mouse.currentPosition.y;
+
+                    CORE.Input.Mouse.currentPosition.x = (event->point.x - (platform.window->r.w / 2)) * 2;
+                    CORE.Input.Mouse.currentPosition.y = (event->point.y - (platform.window->r.h / 2)) * 2;
+
+                    RGFW_window_showMouse(platform.window, 1);
+                }
+                else {
+                    CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;    
+                    CORE.Input.Mouse.currentPosition.x = (float)event->point.x;
+                    CORE.Input.Mouse.currentPosition.y = (float)event->point.y;
+                }
+
+                CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition;
+                touchAction = 2;
+            } break;
+
+            case RGFW_jsButtonPressed:
+            {
+                int button = -1;
+
+                switch (event->button)
+                {
+                    case RGFW_JS_Y: button = GAMEPAD_BUTTON_RIGHT_FACE_UP; break;
+                    case RGFW_JS_B: button = GAMEPAD_BUTTON_RIGHT_FACE_RIGHT; break;
+                    case RGFW_JS_A: button = GAMEPAD_BUTTON_RIGHT_FACE_DOWN; break;
+                    case RGFW_JS_X: button = GAMEPAD_BUTTON_RIGHT_FACE_LEFT; break;
+
+                    case RGFW_JS_L1: button = GAMEPAD_BUTTON_LEFT_TRIGGER_1; break;
+                    case RGFW_JS_R1: button = GAMEPAD_BUTTON_RIGHT_TRIGGER_1; break;
+
+                    case RGFW_JS_L2: button = GAMEPAD_BUTTON_LEFT_TRIGGER_2; break;
+                    case RGFW_JS_R2: button = GAMEPAD_BUTTON_RIGHT_TRIGGER_2; break;
+
+                    case RGFW_JS_SELECT: button = GAMEPAD_BUTTON_MIDDLE_LEFT; break;
+                    case RGFW_JS_HOME: button = GAMEPAD_BUTTON_MIDDLE; break;
+                    case RGFW_JS_START: button = GAMEPAD_BUTTON_MIDDLE_RIGHT; break;
+
+                    case RGFW_JS_UP: button = GAMEPAD_BUTTON_LEFT_FACE_UP; break;
+                    case RGFW_JS_RIGHT: button = GAMEPAD_BUTTON_LEFT_FACE_RIGHT; break;
+                    case RGFW_JS_DOWN: button = GAMEPAD_BUTTON_LEFT_FACE_DOWN; break;
+                    case RGFW_JS_LEFT: button = GAMEPAD_BUTTON_LEFT_FACE_LEFT; break;
+
+                    default: break;
+                }
+
+                if (button >= 0)
+                {
+                    CORE.Input.Gamepad.currentButtonState[event->joystick][button] = 1;
+                    CORE.Input.Gamepad.lastButtonPressed = button;
+                }
+            } break;
+            case RGFW_jsButtonReleased:
+            {
+                int button = -1;
+                switch (event->button)
+                {
+                    case RGFW_JS_Y: button = GAMEPAD_BUTTON_RIGHT_FACE_UP; break;
+                    case RGFW_JS_B: button = GAMEPAD_BUTTON_RIGHT_FACE_RIGHT; break;
+                    case RGFW_JS_A: button = GAMEPAD_BUTTON_RIGHT_FACE_DOWN; break;
+                    case RGFW_JS_X: button = GAMEPAD_BUTTON_RIGHT_FACE_LEFT; break;
+
+                    case RGFW_JS_L1: button = GAMEPAD_BUTTON_LEFT_TRIGGER_1; break;
+                    case RGFW_JS_R1: button = GAMEPAD_BUTTON_RIGHT_TRIGGER_1; break;
+
+                    case RGFW_JS_L2: button = GAMEPAD_BUTTON_LEFT_TRIGGER_2; break;
+                    case RGFW_JS_R2: button = GAMEPAD_BUTTON_RIGHT_TRIGGER_2; break;
+
+                    case RGFW_JS_SELECT: button = GAMEPAD_BUTTON_MIDDLE_LEFT; break;
+                    case RGFW_JS_HOME: button = GAMEPAD_BUTTON_MIDDLE; break;
+                    case RGFW_JS_START: button = GAMEPAD_BUTTON_MIDDLE_RIGHT; break;
+
+                    case RGFW_JS_UP: button = GAMEPAD_BUTTON_LEFT_FACE_UP; break;
+                    case RGFW_JS_RIGHT: button = GAMEPAD_BUTTON_LEFT_FACE_RIGHT; break;
+                    case RGFW_JS_DOWN: button = GAMEPAD_BUTTON_LEFT_FACE_DOWN; break;
+                    case RGFW_JS_LEFT: button = GAMEPAD_BUTTON_LEFT_FACE_LEFT; break;
+                    default: break;
+                }
+
+                if (button >= 0)
+                {
+                    CORE.Input.Gamepad.currentButtonState[event->joystick][button] = 0;
+                    if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0;
+                }
+            } break;
+            case RGFW_jsAxisMove:
+            {
+                int axis = -1;
+
+                size_t i;
+                for (i = 0; i < event->axisesCount; i++)
+                {
+                    switch(i) {
+                        case 0: 
+                            if (abs(event->axis[i].x) > abs(event->axis[i].y)) {
+                                axis = GAMEPAD_AXIS_LEFT_X; 
+                                break;
+                            }
+                            
+                            axis = GAMEPAD_AXIS_LEFT_Y;
+                            break;
+                        case 1: 
+                            if (abs(event->axis[i].x) > abs(event->axis[i].y)) {
+                                axis = GAMEPAD_AXIS_RIGHT_X; break;
+                            }
+
+                            axis = GAMEPAD_AXIS_RIGHT_Y; break;
+                        case 2: axis = GAMEPAD_AXIS_LEFT_TRIGGER; break;
+                        case 3: axis = GAMEPAD_AXIS_RIGHT_TRIGGER; break;
+                        default: break;
+                    }
+
+                    #ifdef __linux__
+                    float value = (event->axis[i].x + event->axis[i].y) / (float) 32767;
+                    #else
+                    float value = (event->axis[i].x + -event->axis[i].y) / (float) 32767;
+                    #endif
+                    CORE.Input.Gamepad.axisState[event->joystick][axis] = value;
+
+                    // Register button state for triggers in addition to their axes
+                    if ((axis == GAMEPAD_AXIS_LEFT_TRIGGER) || (axis == GAMEPAD_AXIS_RIGHT_TRIGGER))
+                    {
+                        int button = (axis == GAMEPAD_AXIS_LEFT_TRIGGER) ? GAMEPAD_BUTTON_LEFT_TRIGGER_2 : GAMEPAD_BUTTON_RIGHT_TRIGGER_2;
+                        int pressed = (value > 0.1f);
+                        CORE.Input.Gamepad.currentButtonState[event->joystick][button] = pressed;
+                        if (pressed) CORE.Input.Gamepad.lastButtonPressed = button;
+                        else if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0;
+                    }
+                }
+            } break;
+            default: break;
+        }
+
+#if defined(SUPPORT_GESTURES_SYSTEM)
+        if (touchAction > -1)
+        {
+            // Process mouse events as touches to be able to use mouse-gestures
+            GestureEvent gestureEvent = { 0 };
+
+            // Register touch actions
+            gestureEvent.touchAction = touchAction;
+
+            // Assign a pointer ID
+            gestureEvent.pointId[0] = 0;
+
+            // Register touch points count
+            gestureEvent.pointCount = 1;
+
+            // Register touch points position, only one point registered
+            if (touchAction == 2 || realTouch) gestureEvent.position[0] = CORE.Input.Touch.position[0];
+            else gestureEvent.position[0] = GetMousePosition();
+
+            // Normalize gestureEvent.position[0] for CORE.Window.screen.width and CORE.Window.screen.height
+            gestureEvent.position[0].x /= (float)GetScreenWidth();
+            gestureEvent.position[0].y /= (float)GetScreenHeight();
+
+            // Gesture data is sent to gestures-system for processing
+            ProcessGestureEvent(gestureEvent);
+
+            touchAction = -1;
+        }
+#endif
+    }
+    //-----------------------------------------------------------------------------
+}
+
+
+//----------------------------------------------------------------------------------
+// Module Internal Functions Definition
+//----------------------------------------------------------------------------------
+
+// Initialize platform: graphics, inputs and more
+int InitPlatform(void)
+{
+    // TODO: Initialize graphic device: display/window
+    // It usually requires setting up the platform display system configuration
+    // and connexion with the GPU through some system graphic API
+    // raylib uses OpenGL so, platform should create that kind of connection
+    // Below example illustrates that process using EGL library
+    //----------------------------------------------------------------------------
+    // Initialize RGFW internal global state, only required systems
+    // Initialize graphic device: display/window and graphic context
+    //----------------------------------------------------------------------------
+    unsigned int flags = RGFW_CENTER | RGFW_ALLOW_DND;
+
+    // Check window creation flags
+    if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) > 0)
+    {
+        CORE.Window.fullscreen = true;
+        flags |= RGFW_FULLSCREEN;
+    }
+
+    if ((CORE.Window.flags & FLAG_WINDOW_UNDECORATED) > 0) flags |= RGFW_NO_BORDER;
+    if ((CORE.Window.flags & FLAG_WINDOW_RESIZABLE) == 0) flags |= RGFW_NO_RESIZE;
+
+    if ((CORE.Window.flags & FLAG_WINDOW_TRANSPARENT) > 0) flags |= RGFW_TRANSPARENT_WINDOW;
+
+    if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) > 0) flags |= RGFW_FULLSCREEN;
+
+    // NOTE: Some OpenGL context attributes must be set before window creation
+
+    // Check selection OpenGL version
+    if (rlGetVersion() == RL_OPENGL_21)
+    {
+        RGFW_setGLVersion(2, 1);
+    }
+    else if (rlGetVersion() == RL_OPENGL_33)
+    {
+        RGFW_setGLVersion(3, 3);
+    }
+    else if (rlGetVersion() == RL_OPENGL_43)
+    {
+        RGFW_setGLVersion(4, 1);
+    }
+
+    if (CORE.Window.flags & FLAG_MSAA_4X_HINT)
+    {
+        RGFW_setGLSamples(4);
+    }
+
+    platform.window = RGFW_createWindow(CORE.Window.title, RGFW_RECT(0, 0, CORE.Window.screen.width, CORE.Window.screen.height), flags);
+
+    if (CORE.Window.flags & FLAG_VSYNC_HINT)
+        RGFW_window_swapInterval(platform.window, 1);
+    
+    RGFW_window_makeCurrent(platform.window);
+
+    // Check surface and context activation
+    if (platform.window != NULL)
+    {
+        CORE.Window.ready = true;
+        
+        CORE.Window.render.width = CORE.Window.screen.width;
+        CORE.Window.render.height = CORE.Window.screen.height;
+        CORE.Window.currentFbo.width = CORE.Window.render.width;
+        CORE.Window.currentFbo.height = CORE.Window.render.height;
+
+        TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully");
+        TRACELOG(LOG_INFO, "    > Display size: %i x %i", CORE.Window.display.width, CORE.Window.display.height);
+        TRACELOG(LOG_INFO, "    > Screen size:  %i x %i", CORE.Window.screen.width, CORE.Window.screen.height);
+        TRACELOG(LOG_INFO, "    > Render size:  %i x %i", CORE.Window.render.width, CORE.Window.render.height);
+        TRACELOG(LOG_INFO, "    > Viewport offsets: %i, %i", CORE.Window.renderOffset.x, CORE.Window.renderOffset.y);
+    }
+    else
+    {
+        TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize graphics device");
+        return -1;
+    }
+    //----------------------------------------------------------------------------
+
+    // If everything work as expected, we can continue
+    CORE.Window.position.x = platform.window->r.x;
+    CORE.Window.position.y = platform.window->r.y;
+    CORE.Window.render.width = CORE.Window.screen.width;
+    CORE.Window.render.height = CORE.Window.screen.height;
+    CORE.Window.currentFbo.width = CORE.Window.render.width;
+    CORE.Window.currentFbo.height = CORE.Window.render.height;
+
+    TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully");
+    TRACELOG(LOG_INFO, "    > Display size: %i x %i", CORE.Window.display.width, CORE.Window.display.height);
+    TRACELOG(LOG_INFO, "    > Screen size:  %i x %i", CORE.Window.screen.width, CORE.Window.screen.height);
+    TRACELOG(LOG_INFO, "    > Render size:  %i x %i", CORE.Window.render.width, CORE.Window.render.height);
+    TRACELOG(LOG_INFO, "    > Viewport offsets: %i, %i", CORE.Window.renderOffset.x, CORE.Window.renderOffset.y);
+
+    // TODO: Load OpenGL extensions
+    // NOTE: GL procedures address loader is required to load extensions
+    //----------------------------------------------------------------------------
+    rlLoadExtensions((void*)RGFW_getProcAddress);
+    //----------------------------------------------------------------------------
+
+    // TODO: Initialize input events system
+    // It could imply keyboard, mouse, gamepad, touch...
+    // Depending on the platform libraries/SDK it could use a callback mechanism
+    // For system events and inputs evens polling on a per-frame basis, use PollInputEvents()
+    //----------------------------------------------------------------------------
+    // ...
+    //----------------------------------------------------------------------------
+
+    // TODO: Initialize timing system
+    //----------------------------------------------------------------------------
+    InitTimer();
+    //----------------------------------------------------------------------------
+
+    // TODO: Initialize storage system
+    //----------------------------------------------------------------------------
+    CORE.Storage.basePath = GetWorkingDirectory();
+    //----------------------------------------------------------------------------
+
+    #ifdef RGFW_X11
+    for (int i = 0; (i < 4) && (i < MAX_GAMEPADS); i++)
+    {
+        RGFW_registerJoystick(platform.window, i);
+    }
+    #endif
+
+    TRACELOG(LOG_INFO, "PLATFORM: CUSTOM: Initialized successfully");
+
+    return 0;
+}
+
+// Close platform
+void ClosePlatform(void)
+{
+    RGFW_window_close(platform.window);
+    // TODO: De-initialize graphics, inputs and more
+}
+
+
+static KeyboardKey ConvertScancodeToKey(u32 keycode) {
+    switch (keycode) {
+        case RGFW_Quote:
+            return KEY_APOSTROPHE;
+        case RGFW_Comma:
+            return KEY_COMMA;
+        case RGFW_Minus:
+            return KEY_MINUS;
+        case RGFW_Period:
+            return KEY_PERIOD;
+        case RGFW_Slash:
+            return KEY_SLASH;
+        case RGFW_Escape:
+            return KEY_ESCAPE;
+        case RGFW_F1:
+            return KEY_F1;
+        case RGFW_F2:
+            return KEY_F2;
+        case RGFW_F3:
+            return KEY_F3;
+        case RGFW_F4:
+            return KEY_F4;
+        case RGFW_F5:
+            return KEY_F5;
+        case RGFW_F6:
+            return KEY_F6;
+        case RGFW_F7:
+            return KEY_F7;
+        case RGFW_F8:
+            return KEY_F8;
+        case RGFW_F9:
+            return KEY_F9;
+        case RGFW_F10:
+            return KEY_F10;
+        case RGFW_F11:
+            return KEY_F11;
+        case RGFW_F12:
+            return KEY_F12;
+        case RGFW_Backtick:
+            return KEY_GRAVE;
+        case RGFW_0:
+            return KEY_ZERO;
+        case RGFW_1:
+            return KEY_ONE;
+        case RGFW_2:
+            return KEY_TWO;
+        case RGFW_3:
+            return KEY_THREE;
+        case RGFW_4:
+            return KEY_FOUR;
+        case RGFW_5:
+            return KEY_FIVE;
+        case RGFW_6:
+            return KEY_SIX;
+        case RGFW_7:
+            return KEY_SEVEN;
+        case RGFW_8:
+            return KEY_EIGHT;
+        case RGFW_9:
+            return KEY_NINE;
+        case RGFW_Equals:
+            return KEY_EQUAL;
+        case RGFW_BackSpace:
+            return KEY_BACKSPACE;
+        case RGFW_Tab:
+            return KEY_TAB;
+        case RGFW_CapsLock:
+            return KEY_CAPS_LOCK;
+        case RGFW_ShiftL:
+            return KEY_LEFT_SHIFT;
+        case RGFW_ControlL:
+            return KEY_LEFT_CONTROL;
+        case RGFW_AltL:
+            return KEY_LEFT_ALT;
+        case RGFW_SuperL:
+            return KEY_LEFT_SUPER;
+        #ifndef RGFW_MACOS
+        case RGFW_ShiftR:
+            return KEY_RIGHT_SHIFT;
+        
+        case RGFW_AltR:
+            return KEY_RIGHT_ALT;
+        #endif
+        case RGFW_Space:
+            return KEY_SPACE;
+
+        #ifdef RGFW_X11
+        case RGFW_a:
+        #endif
+
+        case RGFW_A:
+            return KEY_A;
+
+        #ifdef RGFW_X11
+        case RGFW_b:
+        #endif
+
+        case RGFW_B:
+            return KEY_B;
+
+        #ifdef RGFW_X11
+        case RGFW_c:
+        #endif
+
+        case RGFW_C:
+            return KEY_C;
+
+        #ifdef RGFW_X11
+        case RGFW_d:
+        #endif
+
+        case RGFW_D:
+            return KEY_D;
+
+        #ifdef RGFW_X11
+        case RGFW_e:
+        #endif
+
+        case RGFW_E:
+            return KEY_E;
+
+        #ifdef RGFW_X11
+        case RGFW_f:
+        #endif
+
+        case RGFW_F:
+            return KEY_F;
+
+        #ifdef RGFW_X11
+        case RGFW_g:
+        #endif
+
+        case RGFW_G:
+            return KEY_G;
+        
+        #ifdef RGFW_X11
+        case RGFW_h:
+        #endif
+
+        case RGFW_H:
+            return KEY_H;
+
+        #ifdef RGFW_X11
+        case RGFW_i:
+        #endif
+
+        case RGFW_I:
+            return KEY_I;
+
+        #ifdef RGFW_X11
+        case RGFW_j:
+        #endif
+
+        case RGFW_J:
+            return KEY_J;
+
+        #ifdef RGFW_X11
+        case RGFW_k:
+        #endif
+
+        case RGFW_K:
+            return KEY_K;
+
+        #ifdef RGFW_X11
+        case RGFW_l:
+        #endif
+
+        case RGFW_L:
+            return KEY_L;
+        
+        #ifdef RGFW_X11
+        case RGFW_m:
+        #endif
+
+        case RGFW_M:
+            return KEY_M;
+        
+        #ifdef RGFW_X11
+        case RGFW_n:
+        #endif
+
+        case RGFW_N:
+            return KEY_N;
+
+        #ifdef RGFW_X11
+        case RGFW_o:
+        #endif
+
+        case RGFW_O:
+            return KEY_O;
+
+        #ifdef RGFW_X11
+        case RGFW_p:
+        #endif
+
+        case RGFW_P:
+            return KEY_P;
+
+        #ifdef RGFW_X11
+        case RGFW_q:
+        #endif
+
+        case RGFW_Q:
+            return KEY_Q;
+
+        #ifdef RGFW_X11
+        case RGFW_r:
+        #endif
+
+        case RGFW_R:
+            return KEY_R;
+
+        #ifdef RGFW_X11
+        case RGFW_s:
+        #endif
+
+        case RGFW_S:
+            return KEY_S;
+
+        #ifdef RGFW_X11
+        case RGFW_t:
+        #endif
+
+        case RGFW_T:
+            return KEY_T;
+
+        #ifdef RGFW_X11
+        case RGFW_u:
+        #endif
+
+        case RGFW_U:
+            return KEY_U;
+
+        #ifdef RGFW_X11
+        case RGFW_v:
+        #endif
+
+        case RGFW_V:
+            return KEY_V;
+
+        #ifdef RGFW_X11
+        case RGFW_w:
+        #endif
+
+        case RGFW_W:
+            return KEY_W;
+
+        #ifdef RGFW_X11
+        case RGFW_x:
+        #endif
+
+        case RGFW_X:
+            return KEY_X;
+
+        #ifdef RGFW_X11
+        case RGFW_y:
+        #endif
+
+        case RGFW_Y:
+            return KEY_Y;
+
+        #ifdef RGFW_X11
+        case RGFW_z:
+        #endif
+
+        case RGFW_Z:
+            return KEY_Z;
+        case RGFW_Bracket:
+            return KEY_LEFT_BRACKET;
+        case RGFW_BackSlash:
+            return KEY_BACKSLASH;
+        case RGFW_CloseBracket:
+            return KEY_RIGHT_BRACKET;
+        case RGFW_Semicolon:
+            return KEY_SEMICOLON;
+        case RGFW_Insert:
+            return KEY_INSERT;
+        case RGFW_Home:
+            return KEY_HOME;
+        case RGFW_PageUp:
+            return KEY_PAGE_UP;
+        case RGFW_Delete:
+            return KEY_DELETE;
+        case RGFW_End:
+            return KEY_END;
+        case RGFW_PageDown:
+            return KEY_PAGE_DOWN;
+        case RGFW_Right:
+            return KEY_RIGHT;
+        case RGFW_Left:
+            return KEY_LEFT;
+        case RGFW_Down:
+            return KEY_DOWN;
+        case RGFW_Up:
+            return KEY_UP;
+        case RGFW_Numlock:
+            return KEY_NUM_LOCK;
+        case RGFW_KP_Slash:
+            return KEY_KP_DIVIDE;
+        case RGFW_Multiply:
+            return KEY_KP_MULTIPLY;
+        case RGFW_KP_Minus:
+            return KEY_KP_SUBTRACT;
+        case RGFW_KP_Return:
+            return KEY_KP_ENTER;
+        case RGFW_KP_1:
+            return KEY_KP_1;
+        case RGFW_KP_2:
+            return KEY_KP_2;
+        case RGFW_KP_3:
+            return KEY_KP_3;
+        case RGFW_KP_4:
+            return KEY_KP_4;
+        case RGFW_KP_5:
+            return KEY_KP_5;
+        case RGFW_KP_6:
+            return KEY_KP_6;
+        case RGFW_KP_7:
+            return KEY_KP_7;
+        case RGFW_KP_8:
+            return KEY_KP_8;
+        case RGFW_KP_9:
+            return KEY_KP_9;
+        case RGFW_KP_0:
+            return KEY_KP_0;
+        case RGFW_KP_Period:
+            return KEY_KP_DECIMAL;
+        default:
+            return 0;
+    }
+
+    return 0;
+}
+// EOF

+ 6 - 2
src/rcore.c

@@ -154,13 +154,15 @@
 #endif
 
 // Platform specific defines to handle GetApplicationDirectory()
-#if defined(_WIN32)
+#if (defined(_WIN32) && !defined(PLATFORM_DESKTOP_RGFW)) || (defined(_MSC_VER) && defined(PLATFORM_DESKTOP_RGFW))
     #ifndef MAX_PATH
         #define MAX_PATH 1025
     #endif
 __declspec(dllimport) unsigned long __stdcall GetModuleFileNameA(void *hModule, void *lpFilename, unsigned long nSize);
 __declspec(dllimport) unsigned long __stdcall GetModuleFileNameW(void *hModule, void *lpFilename, unsigned long nSize);
 __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigned long flags, void *widestr, int cchwide, void *str, int cbmb, void *defchar, int *used_default);
+unsigned int __stdcall timeBeginPeriod(unsigned int uPeriod);
+unsigned int __stdcall timeEndPeriod(unsigned int uPeriod);
 #elif defined(__linux__)
     #include <unistd.h>
 #elif defined(__APPLE__)
@@ -482,7 +484,7 @@ static void ScanDirectoryFilesRecursively(const char *basePath, FilePathList *li
 static void RecordAutomationEvent(void); // Record frame events (to internal events array)
 #endif
 
-#if defined(_WIN32)
+#if defined(_WIN32) && !defined(PLATFORM_DESKTOP_RGFW)
 // NOTE: We declare Sleep() function symbol to avoid including windows.h (kernel32.lib linkage required)
 void __stdcall Sleep(unsigned long msTimeout);              // Required for: WaitTime()
 #endif
@@ -496,6 +498,8 @@ const char *TextFormat(const char *text, ...);              // Formatting of tex
     #include "platforms/rcore_desktop.c"
 #elif defined(PLATFORM_DESKTOP_SDL)
     #include "platforms/rcore_desktop_sdl.c"
+#elif defined(PLATFORM_DESKTOP_RGFW)
+    #include "platforms/rcore_desktop_rgfw.c"
 #elif defined(PLATFORM_WEB)
     #include "platforms/rcore_web.c"
 #elif defined(PLATFORM_DRM)