minesweeper

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

RGFW.h (293229B)


      1 /*
      2 * Copyright (C) 2023-24 ColleagueRiley
      3 *
      4 * libpng license
      5 *
      6 * This software is provided 'as-is', without any express or implied
      7 * warranty.  In no event will the authors be held liable for any damages
      8 * arising from the use of this software.
      9 *
     10 * Permission is granted to anyone to use this software for any purpose,
     11 * including commercial applications, and to alter it and redistribute it
     12 * freely, subject to the following restrictions:
     13 *
     14 * 1. The origin of this software must not be misrepresented; you must not
     15 *    claim that you wrote the original software. If you use this software
     16 *    in a product, an acknowledgment in the product documentation would be
     17 *    appreciated but is not required.
     18 * 2. Altered source versions must be plainly marked as such, and must not be
     19 *    misrepresented as being the original software.
     20 * 3. This notice may not be removed or altered from any source distribution.
     21 *
     22 *
     23 */
     24 
     25 /*
     26 	(MAKE SURE RGFW_IMPLEMENTATION is in exactly one header or you use -D RGFW_IMPLEMENTATION)
     27 	#define RGFW_IMPLEMENTATION - makes it so source code is included with header
     28 */
     29 
     30 /*
     31 	#define RGFW_IMPLEMENTATION - (required) makes it so the source code is included
     32 	#define RGFW_PRINT_ERRORS - (optional) makes it so RGFW prints errors when they're found
     33 	#define RGFW_OSMESA - (optional) use OSmesa as backend (instead of system's opengl api + regular opengl)
     34 	#define RGFW_BUFFER - (optional) just draw directly to (RGFW) window pixel buffer that is drawn to screen (the buffer is in the RGBA format)
     35 	#define RGFW_EGL - (optional) use EGL for loading an OpenGL context (instead of the system's opengl api)
     36 	#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)
     37 									This version doesn't work for desktops (I'm pretty sure)
     38 	#define RGFW_OPENGL_ES2 - (optional) use OpenGL ES (version 2)
     39 	#define RGFW_OPENGL_ES3 - (optional) use OpenGL ES (version 3)
     40 	#define RGFW_DIRECTX - (optional) use directX for the rendering backend (rather than opengl) (windows only, defaults to opengl for unix)
     41 	#define RGFW_WEBGPU - (optional) use webGPU for rendering (Web ONLY)
     42 	#define RGFW_NO_API - (optional) don't use any rendering API (no opengl, no vulkan, no directX)
     43 
     44 	#define RGFW_LINK_EGL (optional) (windows only) if EGL is being used, if EGL functions should be defined dymanically (using GetProcAddress)
     45 	#define RGFW_LINK_OSMESA (optional) (windows only) if EGL is being used, if OS Mesa functions should be defined dymanically  (using GetProcAddress)
     46 
     47 	#define RGFW_X11 (optional) (unix only) if X11 should be used. This option is turned on by default by unix systems except for MacOS
     48 	#define RGFW_WGL_LOAD (optional) (windows only) if WGL should be loaded dynamically during runtime
     49 	#define RGFW_NO_X11_CURSOR (optional) (unix only) don't use XCursor
     50 	#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)
     51 
     52 	#define RGFW_NO_DPI - Do not include calculate DPI (no XRM nor libShcore included)
     53 
     54 	#define RGFW_ALLOC_DROPFILES (optional) if room should be allocating for drop files (by default it's global data)
     55 	#define RGFW_MALLOC x - choose what function to use to allocate, by default the standard malloc is used
     56 	#define RGFW_CALLOC x - choose what function to use to allocate (calloc), by default the standard calloc is used
     57 	#define RGFW_FREE x - choose what function to use to allocated memory, by default the standard free is used
     58 
     59  	#define RGFW_EXPORT - Use when building RGFW 
     60     #define RGFW_IMPORT - Use when linking with RGFW (not as a single-header)
     61 	
     62 	#define RGFW_STD_INT - force the use stdint.h (for systems that might not have stdint.h (msvc)) 
     63 */
     64 
     65 /*
     66 	Credits :
     67 		EimaMei/Sacode : Much of the code for creating windows using winapi, Wrote the Silicon library, helped with MacOS Support, siliapp.h -> referencing 
     68 
     69 		stb - This project is heavily inspired by the stb single header files
     70 
     71 		GLFW:
     72 			certain parts of winapi and X11 are very poorly documented,
     73 			GLFW's source code was referenced and used throughout the project (used code is marked in some way),
     74 			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)
     75 
     76 			GLFW Copyright, https::/github.com/GLFW/GLFW
     77 
     78 			Copyright (c) 2002-2006 Marcus Geelnard
     79 			Copyright (c) 2006-2019 Camilla Löwy
     80 
     81 		contributors : (feel free to put yourself here if you contribute)
     82 		krisvers -> code review
     83 		EimaMei (SaCode) -> code review
     84 		Code-Nycticebus -> bug fixes
     85 		Rob Rohan -> X11 bugs and missing features, MacOS/Cocoa fixing memory issues/bugs 
     86 		AICDG (@THISISAGOODNAME) -> vulkan support (example)
     87 		@Easymode -> support, testing/debugging, bug fixes and reviews
     88 		Joshua Rowe (omnisci3nce) - bug fix, review (macOS)
     89 		@lesleyrs -> bug fix, review (OpenGL)
     90 		Nick Porcino (meshula) - testing, organization, review (MacOS, examples)
     91 */
     92 
     93 #if _MSC_VER
     94 	#pragma comment(lib, "gdi32")
     95 	#pragma comment(lib, "shell32")
     96 	#pragma comment(lib, "opengl32")
     97 	#pragma comment(lib, "winmm")
     98 	#pragma comment(lib, "user32")
     99 #endif
    100 
    101 #ifndef RGFW_MALLOC
    102 	#include <stdlib.h>
    103 
    104 	#ifndef __USE_POSIX199309
    105 	#define __USE_POSIX199309
    106 	#endif
    107 
    108 	#include <time.h>
    109 	#define RGFW_MALLOC malloc
    110 	#define RGFW_CALLOC calloc
    111 	#define RGFW_FREE free
    112 #endif
    113 
    114 #if !_MSC_VER
    115 	#ifndef inline
    116 		#ifndef __APPLE__
    117 			#define inline __inline
    118 		#endif
    119 	#endif
    120 #endif
    121 
    122 #ifdef RGFW_WIN95 /* for windows 95 testing (not that it really works) */
    123 	#define RGFW_NO_MONITOR
    124 	#define RGFW_NO_PASSTHROUGH
    125 #endif
    126 
    127 #if defined(RGFW_EXPORT) ||  defined(RGFW_IMPORT)
    128 	#if defined(_WIN32)
    129 		#if defined(__TINYC__) && (defined(RGFW_EXPORT) ||  defined(RGFW_IMPORT))
    130 			#define __declspec(x) __attribute__((x))
    131 		#endif
    132 
    133 		#if defined(RGFW_EXPORT)
    134 			#define RGFWDEF __declspec(dllexport)
    135 		#else 
    136 			#define RGFWDEF __declspec(dllimport)
    137 		#endif
    138 	#else
    139 		#if defined(RGFW_EXPORT)
    140 			#define RGFWDEF __attribute__((visibility("default")))
    141 		#endif
    142 	#endif
    143 #endif 
    144 
    145 #ifndef RGFWDEF
    146 	#ifdef __clang__
    147 		#define RGFWDEF static inline
    148 	#else
    149 		#define RGFWDEF inline
    150 	#endif
    151 #endif
    152 
    153 #ifndef RGFW_ENUM
    154 	#define RGFW_ENUM(type, name) type name; enum
    155 #endif
    156 
    157 #ifndef RGFW_UNUSED
    158 	#define RGFW_UNUSED(x) (void)(x);
    159 #endif
    160 
    161 #if defined(__cplusplus) && !defined(__EMSCRIPTEN__)
    162 	extern "C" {
    163 #endif
    164 
    165 	/* makes sure the header file part is only defined once by default */
    166 #ifndef RGFW_HEADER
    167 
    168 #define RGFW_HEADER
    169 
    170 #if !defined(u8)
    171 	#if ((defined(_MSC_VER) || defined(__SYMBIAN32__)) && !defined(RGFW_STD_INT)) /* MSVC might not have stdint.h */
    172 		typedef unsigned char 	u8;
    173 		typedef signed char		i8;
    174 		typedef unsigned short  u16;
    175 		typedef signed short 	i16;
    176 		typedef unsigned int 	u32;
    177 		typedef signed int		i32;
    178 		typedef unsigned long	u64;
    179 		typedef signed long		i64;
    180 	#else /* use stdint standard types instead of c ""standard"" types */
    181 		#include <stdint.h>
    182 
    183 		typedef uint8_t     u8;
    184 		typedef int8_t      i8;
    185 		typedef uint16_t   u16;
    186 		typedef int16_t    i16;
    187 		typedef uint32_t   u32;
    188 		typedef int32_t    i32;
    189 		typedef uint64_t   u64;
    190 		typedef int64_t    i64;
    191 	#endif
    192 #endif
    193 
    194 #if !defined(b8) /* RGFW bool type */
    195 	typedef u8 b8;
    196 	typedef u32 b32;
    197 #endif
    198 
    199 #define RGFW_TRUE (!(0))
    200 #define RGFW_FALSE 0
    201 
    202 /* thse OS macros looks better & are standardized */
    203 /* plus it helps with cross-compiling */
    204 
    205 #ifdef __EMSCRIPTEN__
    206 	#define RGFW_WEBASM
    207 
    208 	#if !defined(RGFW_NO_API) && !defined(RGFW_WEBGPU)
    209 		#define RGFW_OPENGL
    210 	#endif
    211 
    212 	#ifdef RGFW_EGL
    213 		#undef RGFW_EGL
    214 	#endif
    215 
    216 	#include <emscripten/html5.h>
    217 	#include <emscripten/key_codes.h>
    218 
    219 	#ifdef RGFW_WEBGPU
    220 		#include <emscripten/html5_webgpu.h>
    221 	#endif
    222 #endif
    223 
    224 #if defined(RGFW_X11) && defined(__APPLE__)
    225 	#define RGFW_MACOS_X11
    226 	#undef __APPLE__
    227 #endif
    228 
    229 #if defined(_WIN32) && !defined(RGFW_X11) && !defined(RGFW_WEBASM) /* (if you're using X11 on windows some how) */
    230 	#define RGFW_WINDOWS
    231 
    232 	/* make sure the correct architecture is defined */
    233 	#if defined(_WIN64)
    234 		#define _AMD64_
    235 		#undef _X86_
    236 	#else
    237 		#undef _AMD64_
    238 		#ifndef _X86_
    239 			#define _X86_
    240 		#endif
    241 	#endif
    242 
    243 	#ifndef RGFW_NO_XINPUT
    244 		#ifdef __MINGW32__ /* try to find the right header */
    245 			#include <xinput.h>
    246 		#else
    247 			#include <XInput.h>
    248 		#endif
    249 	#endif
    250 
    251 	#if defined(RGFW_DIRECTX)
    252 		#include <d3d11.h>
    253 		#include <dxgi.h>
    254 		#include <dxgi.h>
    255 		#include <d3dcompiler.h>
    256 
    257 		#ifndef __cplusplus
    258 			#define __uuidof(T) IID_##T
    259 		#endif
    260 	#endif
    261 
    262 #elif defined(RGFW_WAYLAND)
    263     #if !defined(RGFW_NO_API) && (!defined(RGFW_BUFFER) || defined(RGFW_OPENGL))
    264 		#define RGFW_EGL
    265 		#define RGFW_OPENGL
    266 		#include <wayland-egl.h>
    267 	#endif
    268 
    269 	#include <wayland-client.h>
    270 #elif (defined(__unix__) || defined(RGFW_MACOS_X11) || defined(RGFW_X11))  && !defined(RGFW_WEBASM)
    271 	#define RGFW_MACOS_X11
    272 	#define RGFW_X11
    273 	#include <X11/Xlib.h>
    274 #elif defined(__APPLE__) && !defined(RGFW_MACOS_X11) && !defined(RGFW_X11)  && !defined(RGFW_WEBASM)
    275 	#define RGFW_MACOS
    276 #endif
    277 
    278 #if (defined(RGFW_OPENGL_ES1) || defined(RGFW_OPENGL_ES2) || defined(RGFW_OPENGL_ES3)) && !defined(RGFW_EGL)
    279 	#define RGFW_EGL
    280 #endif
    281 
    282 #if !defined(RGFW_OSMESA) && !defined(RGFW_EGL) && !defined(RGFW_OPENGL) && !defined(RGFW_DIRECTX) && !defined(RGFW_BUFFER) && !defined(RGFW_NO_API)
    283 	#define RGFW_OPENGL
    284 #endif
    285 
    286 #ifdef RGFW_EGL
    287 	#include <EGL/egl.h>
    288 #elif defined(RGFW_OSMESA)
    289 	#ifndef __APPLE__
    290 		#include <GL/osmesa.h>
    291 	#else
    292 		#include <OpenGL/osmesa.h>
    293 	#endif
    294 #endif
    295 
    296 #if defined(RGFW_OPENGL) && defined(RGFW_X11)
    297 	#ifndef GLX_MESA_swap_control
    298 		#define  GLX_MESA_swap_control
    299 	#endif
    300 	#include <GL/glx.h> /* GLX defs, xlib.h, gl.h */
    301 #endif
    302 
    303 #ifndef RGFW_ALPHA
    304 	#define RGFW_ALPHA 128 /* alpha value for RGFW_TRANSPARENT_WINDOW (WINAPI ONLY, macOS + linux don't need this) */
    305 #endif
    306 
    307 /*! Optional arguments for making a windows */
    308 #define RGFW_TRANSPARENT_WINDOW		(1L<<9) /*!< the window is transparent (only properly works on X11 and MacOS, although it's although for windows) */
    309 #define RGFW_NO_BORDER		(1L<<3) /*!< the window doesn't have border */
    310 #define RGFW_NO_RESIZE		(1L<<4) /*!< the window cannot be resized  by the user */
    311 #define RGFW_ALLOW_DND     (1L<<5) /*!< the window supports drag and drop*/
    312 #define RGFW_HIDE_MOUSE (1L<<6) /*! the window should hide the mouse or not (can be toggled later on) using `RGFW_window_mouseShow*/
    313 #define RGFW_FULLSCREEN (1L<<8) /* the window is fullscreen by default or not */
    314 #define RGFW_CENTER (1L<<10) /*! center the window on the screen */
    315 #define RGFW_OPENGL_SOFTWARE (1L<<11) /*! use OpenGL software rendering */
    316 #define RGFW_COCOA_MOVE_TO_RESOURCE_DIR (1L << 12) /* (cocoa only), move to resource folder */
    317 #define RGFW_SCALE_TO_MONITOR (1L << 13) /* scale the window to the screen */
    318 #define RGFW_NO_INIT_API (1L << 2) /* DO not init an API (mostly for bindings, you should use `#define RGFW_NO_API` in C */
    319 
    320 #define RGFW_NO_GPU_RENDER (1L<<14) /* don't render (using the GPU based API)*/
    321 #define RGFW_NO_CPU_RENDER (1L<<15) /* don't render (using the CPU based buffer rendering)*/
    322 #define RGFW_WINDOW_HIDE (1L <<  16)/* the window is hidden */
    323 
    324 typedef RGFW_ENUM(u8, RGFW_event_types) {
    325 	/*! event codes */
    326  	RGFW_keyPressed = 1, /* a key has been pressed */
    327 	RGFW_keyReleased, /*!< a key has been released*/
    328 	/*! key event note
    329 		the code of the key pressed is stored in
    330 		RGFW_Event.keyCode
    331 		!!Keycodes defined at the bottom of the RGFW_HEADER part of this file!!
    332 
    333 		while a string version is stored in
    334 		RGFW_Event.KeyString
    335 
    336 		RGFW_Event.lockState holds the current lockState
    337 		this means if CapsLock, NumLock are active or not
    338 	*/
    339 	RGFW_mouseButtonPressed, /*!< a mouse button has been pressed (left,middle,right)*/
    340 	RGFW_mouseButtonReleased, /*!< a mouse button has been released (left,middle,right)*/
    341 	RGFW_mousePosChanged, /*!< the position of the mouse has been changed*/
    342 	/*! mouse event note
    343 		the x and y of the mouse can be found in the vector, RGFW_Event.point
    344 
    345 		RGFW_Event.button holds which mouse button was pressed
    346 	*/
    347 	RGFW_jsButtonPressed, /*!< a joystick button was pressed */
    348 	RGFW_jsButtonReleased, /*!< a joystick button was released */
    349 	RGFW_jsAxisMove, /*!< an axis of a joystick was moved*/
    350 	/*! joystick event note
    351 		RGFW_Event.joystick holds which joystick was altered, if any
    352 		RGFW_Event.button holds which joystick button was pressed
    353 
    354 		RGFW_Event.axis holds the data of all the axis
    355 		RGFW_Event.axisCount says how many axis there are
    356 	*/
    357 	RGFW_windowMoved, /*!< the window was moved (by the user) */
    358 	RGFW_windowResized, /*!< the window was resized (by the user), [on webASM this means the browser was resized] */
    359 	RGFW_focusIn, /*!< window is in focus now */
    360 	RGFW_focusOut, /*!< window is out of focus now */
    361 	RGFW_mouseEnter, /* mouse entered the window */
    362 	RGFW_mouseLeave, /* mouse left the window */
    363 	RGFW_windowRefresh, /* The window content needs to be refreshed */
    364 
    365 	/* attribs change event note
    366 		The event data is sent straight to the window structure
    367 		with win->r.x, win->r.y, win->r.w and win->r.h
    368 	*/
    369 	RGFW_quit, /*!< the user clicked the quit button*/ 
    370 	RGFW_dnd, /*!< a file has been dropped into the window*/
    371 	RGFW_dnd_init /*!< the start of a dnd event, when the place where the file drop is known */
    372 	/* dnd data note
    373 		The x and y coords of the drop are stored in the vector RGFW_Event.point
    374 
    375 		RGFW_Event.droppedFilesCount holds how many files were dropped
    376 
    377 		This is also the size of the array which stores all the dropped file string,
    378 		RGFW_Event.droppedFiles
    379 	*/
    380 };
    381 
    382 /*! mouse button codes (RGFW_Event.button) */
    383 #define RGFW_mouseLeft  1 /*!< left mouse button is pressed*/
    384 #define RGFW_mouseMiddle  2 /*!< mouse-wheel-button is pressed*/
    385 #define RGFW_mouseRight  3 /*!< right mouse button is pressed*/
    386 #define RGFW_mouseScrollUp  4 /*!< mouse wheel is scrolling up*/
    387 #define RGFW_mouseScrollDown  5 /*!< mouse wheel is scrolling down*/
    388 
    389 #ifndef RGFW_MAX_PATH
    390 #define RGFW_MAX_PATH 260 /* max length of a path (for dnd) */
    391 #endif
    392 #ifndef RGFW_MAX_DROPS
    393 #define RGFW_MAX_DROPS 260 /* max items you can drop at once */
    394 #endif
    395 
    396 
    397 /* for RGFW_Event.lockstate */
    398 #define RGFW_CAPSLOCK (1L << 1)
    399 #define RGFW_NUMLOCK (1L << 2)
    400 
    401 /*! joystick button codes (based on xbox/playstation), you may need to change these values per controller */
    402 #ifndef RGFW_joystick_codes
    403 	typedef RGFW_ENUM(u8, RGFW_joystick_codes) {
    404 		RGFW_JS_A = 0, /*!< or PS X button */
    405 		RGFW_JS_B = 1, /*!< or PS circle button */
    406 		RGFW_JS_Y = 2, /*!< or PS triangle button */
    407 		RGFW_JS_X = 3, /*!< or PS square button */
    408 		RGFW_JS_START = 9, /*!< start button */
    409 		RGFW_JS_SELECT = 8, /*!< select button */
    410 		RGFW_JS_HOME = 10, /*!< home button */
    411 		RGFW_JS_UP = 13, /*!< dpad up */
    412 		RGFW_JS_DOWN = 14, /*!< dpad down*/
    413 		RGFW_JS_LEFT = 15, /*!< dpad left */
    414 		RGFW_JS_RIGHT = 16, /*!< dpad right */
    415 		RGFW_JS_L1 = 4, /*!< left bump */
    416 		RGFW_JS_L2 = 5, /*!< left trigger*/
    417 		RGFW_JS_R1 = 6, /*!< right bumper */
    418 		RGFW_JS_R2 = 7, /*!< right trigger */
    419 	};
    420 #endif
    421 
    422 /*! basic vector type, if there's not already a point/vector type of choice */
    423 #ifndef RGFW_point
    424 	typedef struct { i32 x, y; } RGFW_point;
    425 #endif
    426 
    427 /*! basic rect type, if there's not already a rect type of choice */
    428 #ifndef RGFW_rect
    429 	typedef struct { i32 x, y, w, h; } RGFW_rect;
    430 #endif
    431 
    432 /*! basic area type, if there's not already a area type of choice */
    433 #ifndef RGFW_area
    434 	typedef struct { u32 w, h; } RGFW_area;
    435 #endif
    436 
    437 #ifndef __cplusplus
    438 #define RGFW_POINT(x, y) (RGFW_point){(i32)(x), (i32)(y)}
    439 #define RGFW_RECT(x, y, w, h) (RGFW_rect){(i32)(x), (i32)(y), (i32)(w), (i32)(h)}
    440 #define RGFW_AREA(w, h) (RGFW_area){(u32)(w), (u32)(h)}
    441 #else
    442 #define RGFW_POINT(x, y) {(i32)(x), (i32)(y)}
    443 #define RGFW_RECT(x, y, w, h) {(i32)(x), (i32)(y), (i32)(w), (i32)(h)}
    444 #define RGFW_AREA(w, h) {(u32)(w), (u32)(h)}
    445 #endif
    446 
    447 #ifndef RGFW_NO_MONITOR
    448 	/*! structure for monitor data */
    449 	typedef struct RGFW_monitor {
    450 		char name[128]; /*!< monitor name */
    451 		RGFW_rect rect; /*!< monitor Workarea */
    452 		float scaleX, scaleY; /*!< monitor content scale*/
    453 		float physW, physH; /*!< monitor physical size */
    454 	} RGFW_monitor;
    455 
    456 	/*
    457 		NOTE : Monitor functions should be ran only as many times as needed (not in a loop)
    458 	*/
    459 
    460 	/*! get an array of all the monitors (max 6) */
    461 	RGFWDEF RGFW_monitor* RGFW_getMonitors(void);
    462 	/*! get the primary monitor */
    463 	RGFWDEF RGFW_monitor RGFW_getPrimaryMonitor(void);
    464 #endif
    465 
    466 /* NOTE: some parts of the data can represent different things based on the event (read comments in RGFW_Event struct) */
    467 /*! Event structure for checking/getting events */
    468 typedef struct RGFW_Event {
    469 	char keyName[16]; /*!< key name of event*/
    470 
    471 	/*! drag and drop data */
    472 	/* 260 max paths with a max length of 260 */
    473 #ifdef RGFW_ALLOC_DROPFILES
    474 	char** droppedFiles;
    475 #else
    476 	char droppedFiles[RGFW_MAX_DROPS][RGFW_MAX_PATH]; /*!< dropped files*/
    477 #endif
    478 	u32 droppedFilesCount; /*!< house many files were dropped */
    479 
    480 	u32 type; /*!< which event has been sent?*/
    481 	RGFW_point point; /*!< mouse x, y of event (or drop point) */
    482 	
    483 	u8 keyCode; /*!< keycode of event 	!!Keycodes defined at the bottom of the RGFW_HEADER part of this file!! */	
    484 	
    485 	b8 repeat; /*!< key press event repeated (the key is being held) */
    486 	b8 inFocus;  /*!< if the window is in focus or not (this is always true for MacOS windows due to the api being weird) */
    487 
    488 	u8 lockState;
    489 	
    490 	u8 button; /* !< which mouse button was pressed */
    491 	double scroll; /*!< the raw mouse scroll value */
    492 
    493 	u16 joystick; /*! which joystick this event applies to (if applicable to any) */
    494 	u8 axisesCount; /*!< number of axises */
    495 	RGFW_point axis[2]; /*!< x, y of axises (-100 to 100) */
    496 
    497 	u64 frameTime, frameTime2; /*!< this is used for counting the fps */
    498 } RGFW_Event;
    499 
    500 /*! source data for the window (used by the APIs) */
    501 typedef struct RGFW_window_src {
    502 #ifdef RGFW_WINDOWS
    503 	HWND window; /*!< source window */
    504 	HDC hdc; /*!< source HDC */
    505 	u32 hOffset; /*!< height offset for window */
    506 	#if (defined(RGFW_OPENGL)) && !defined(RGFW_OSMESA) && !defined(RGFW_EGL)
    507 		HGLRC ctx; /*!< source graphics context */
    508 	#elif defined(RGFW_OSMESA)
    509 		OSMesaContext ctx;
    510 	#elif defined(RGFW_DIRECTX)
    511 		IDXGISwapChain* swapchain;
    512 		ID3D11RenderTargetView* renderTargetView;
    513 		ID3D11DepthStencilView* pDepthStencilView;
    514 	#elif defined(RGFW_EGL)
    515 		EGLSurface EGL_surface;
    516 		EGLDisplay EGL_display;
    517 		EGLContext EGL_context;
    518 	#endif
    519 
    520 	#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) 
    521 		HDC hdcMem;
    522 		HBITMAP bitmap;
    523 	#endif
    524 	RGFW_area maxSize, minSize; /*!< for setting max/min resize (RGFW_WINDOWS) */
    525 #elif defined(RGFW_X11)
    526 	Display* display; /*!< source display */
    527 	Window window; /*!< source window */
    528 	#if (defined(RGFW_OPENGL)) && !defined(RGFW_OSMESA) && !defined(RGFW_EGL)
    529 		GLXContext ctx; /*!< source graphics context */
    530 	#elif defined(RGFW_OSMESA)
    531 		OSMesaContext ctx;
    532 	#elif defined(RGFW_EGL)
    533 		EGLSurface EGL_surface;
    534 		EGLDisplay EGL_display;
    535 		EGLContext EGL_context;
    536 	#endif
    537 
    538 #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) 
    539 		XImage* bitmap;
    540 		GC gc;
    541 #endif
    542 #elif defined(RGFW_WAYLAND)
    543 	struct wl_display* display;
    544 	struct wl_surface* surface;
    545 	struct wl_buffer* wl_buffer;
    546 	struct wl_keyboard* keyboard;
    547 
    548 	struct xdg_surface* xdg_surface;
    549 	struct xdg_toplevel* xdg_toplevel;
    550 	struct zxdg_toplevel_decoration_v1* decoration;
    551 	RGFW_Event events[20];
    552 		i32 eventLen;
    553 		size_t eventIndex;
    554 	#if defined(RGFW_EGL)
    555 			struct wl_egl_window* window;
    556 			EGLSurface EGL_surface;
    557 			EGLDisplay EGL_display;
    558 			EGLContext EGL_context;
    559 	#elif defined(RGFW_OSMESA)
    560 		OSMesaContext ctx;
    561 	#endif
    562 #elif defined(RGFW_MACOS)
    563 	u32 display;
    564 	void* displayLink;
    565 	void* window;
    566 	b8 dndPassed;
    567 #if (defined(RGFW_OPENGL)) && !defined(RGFW_OSMESA) && !defined(RGFW_EGL)
    568 		void* ctx; /*!< source graphics context */
    569 #elif defined(RGFW_OSMESA)
    570 		OSMesaContext ctx;
    571 #elif defined(RGFW_EGL)
    572 		EGLSurface EGL_surface;
    573 		EGLDisplay EGL_display;
    574 		EGLContext EGL_context;
    575 #endif
    576 
    577 	void* view; /*apple viewpoint thingy*/
    578 
    579 #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) 
    580 		void* bitmap; /*!< API's bitmap for storing or managing */
    581 		void* image;
    582 #endif
    583 #elif defined(RGFW_WEBASM)
    584 	#ifdef RGFW_WEBGPU
    585 		WGPUInstance ctx;
    586         WGPUDevice device;
    587         WGPUQueue queue;
    588 	#else
    589 		EMSCRIPTEN_WEBGL_CONTEXT_HANDLE ctx;
    590 	#endif
    591 #endif
    592 } RGFW_window_src;
    593 
    594 
    595 
    596 typedef struct RGFW_window {
    597 	RGFW_window_src src; /*!< src window data */
    598 
    599 #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) 
    600 	u8* buffer; /*!< buffer for non-GPU systems (OSMesa, basic software rendering) */
    601 	/* when rendering using RGFW_BUFFER, the buffer is in the RGBA format */
    602 #endif
    603 	void* userPtr; /* ptr for usr data */
    604 	
    605 	RGFW_Event event; /*!< current event */
    606 
    607 	RGFW_rect r; /*!< the x, y, w and h of the struct */
    608 	
    609 	RGFW_point _lastMousePoint; /*!< last cusor point (for raw mouse data) */
    610 	
    611 	u32 _winArgs; /*!< windows args (for RGFW to check) */
    612 } RGFW_window; /*!< Window structure for managing the window */
    613 
    614 #if defined(RGFW_X11) || defined(RGFW_MACOS)
    615 	typedef u64 RGFW_thread; /*!< thread type unix */
    616 #else
    617 	typedef void* RGFW_thread; /*!< thread type for window */
    618 #endif
    619 
    620 /** * @defgroup Window_management
    621 * @{ */ 
    622 
    623 
    624 /*! 
    625  * the class name for X11 and WinAPI. apps with the same class will be grouped by the WM
    626  * by default the class name will == the root window's name
    627 */
    628 RGFWDEF void RGFW_setClassName(char* name);
    629 
    630 /*! this has to be set before createWindow is called, else the fulscreen size is used */
    631 RGFWDEF void RGFW_setBufferSize(RGFW_area size); /*!< the buffer cannot be resized (by RGFW) */
    632 
    633 RGFWDEF RGFW_window* RGFW_createWindow(
    634 	const char* name, /* name of the window */
    635 	RGFW_rect rect, /* rect of window */
    636 	u16 args /* extra arguments (NULL / (u16)0 means no args used)*/
    637 ); /*!< function to create a window struct */
    638 
    639 /*! get the size of the screen to an area struct */
    640 RGFWDEF RGFW_area RGFW_getScreenSize(void);
    641 
    642 /*!
    643 	this function checks an *individual* event (and updates window structure attributes)
    644 	this means, using this function without a while loop may cause event lag
    645 
    646 	ex.
    647 
    648 	while (RGFW_window_checkEvent(win) != NULL) [this keeps checking events until it reaches the last one]
    649 
    650 	this function is optional if you choose to use event callbacks, 
    651 	although you still need some way to tell RGFW to process events eg. `RGFW_window_checkEvents`
    652 */
    653 
    654 RGFWDEF RGFW_Event* RGFW_window_checkEvent(RGFW_window* win); /*!< check current event (returns a pointer to win->event or NULL if there is no event)*/
    655 
    656 /*!
    657 	for RGFW_window_eventWait and RGFW_window_checkEvents
    658 	waitMS -> Allows th	e function to keep checking for events even after `RGFW_window_checkEvent == NULL`
    659 			  if waitMS == 0, the loop will not wait for events
    660 			  if waitMS == a positive integer, the loop will wait that many miliseconds after there are no more events until it returns
    661 			  if waitMS == a negative integer, the loop will not return until it gets another event
    662 */
    663 typedef RGFW_ENUM(i32, RGFW_eventWait) {
    664 	RGFW_NEXT = -1,
    665 	RGFW_NO_WAIT = 0
    666 };
    667 
    668 /*! sleep until RGFW gets an event or the timer ends (defined by OS) */
    669 RGFWDEF void RGFW_window_eventWait(RGFW_window* win, i32 waitMS);
    670 
    671 /*!
    672 	check all the events until there are none left, 
    673 	this should only be used if you're using callbacks only
    674 */
    675 RGFWDEF void RGFW_window_checkEvents(RGFW_window* win, i32 waitMS);
    676 
    677 /*! 
    678 	Tell RGFW_window_eventWait to stop waiting, to be ran from another thread
    679 */
    680 RGFWDEF void RGFW_stopCheckEvents(void);
    681 
    682 /*! window managment functions*/
    683 RGFWDEF void RGFW_window_close(RGFW_window* win); /*!< close the window and free leftover data */
    684 
    685 /*! moves window to a given point */
    686 RGFWDEF void RGFW_window_move(RGFW_window* win,
    687 	RGFW_point v/*!< new pos*/
    688 );
    689 
    690 #ifndef RGFW_NO_MONITOR
    691 	/*! move to a specific monitor */
    692 	RGFWDEF void RGFW_window_moveToMonitor(RGFW_window* win, RGFW_monitor m /* monitor */);
    693 #endif
    694 
    695 /*! resize window to a current size/area */
    696 RGFWDEF void RGFW_window_resize(RGFW_window* win, /*!< source window */
    697 	RGFW_area a/*!< new size*/
    698 );
    699 
    700 /*! set the minimum size a user can shrink a window to a given size/area */
    701 RGFWDEF void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a);
    702 /*! set the minimum size a user can extend a window to a given size/area */
    703 RGFWDEF void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a);
    704 
    705 RGFWDEF void RGFW_window_maximize(RGFW_window* win); /*!< maximize the window size */
    706 RGFWDEF void RGFW_window_minimize(RGFW_window* win); /*!< minimize the window (in taskbar (per OS))*/
    707 RGFWDEF void RGFW_window_restore(RGFW_window* win); /*!< restore the window from minimized (per OS)*/
    708 
    709 /*! if the window should have a border or not (borderless) based on bool value of `border` */
    710 RGFWDEF void RGFW_window_setBorder(RGFW_window* win, b8 border);
    711 
    712 /*! turn on / off dnd (RGFW_ALLOW_DND stil must be passed to the window)*/
    713 RGFWDEF void RGFW_window_setDND(RGFW_window* win, b8 allow);
    714 
    715 #ifndef RGFW_NO_PASSTHROUGH
    716 	/*!! turn on / off mouse passthrough */
    717 	RGFWDEF void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough);
    718 #endif 
    719 
    720 /*! rename window to a given string */
    721 RGFWDEF void RGFW_window_setName(RGFW_window* win,
    722 	char* name
    723 );
    724 
    725 RGFWDEF void RGFW_window_setIcon(RGFW_window* win, /*!< source window */
    726 	u8* icon /*!< icon bitmap */,
    727 	RGFW_area a /*!< width and height of the bitmap*/,
    728 	i32 channels /*!< how many channels the bitmap has (rgb : 3, rgba : 4) */
    729 ); /*!< image resized by default */
    730 
    731 /*!< sets mouse to bitmap (very simular to RGFW_window_setIcon), image NOT resized by default*/
    732 RGFWDEF void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels);
    733 
    734 /*!< sets the mouse to a standard API cursor (based on RGFW_MOUSE, as seen at the end of the RGFW_HEADER part of this file) */
    735 RGFWDEF	void RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse);
    736 
    737 RGFWDEF void RGFW_window_setMouseDefault(RGFW_window* win); /*!< sets the mouse to the default mouse icon */
    738 /*
    739 	Locks cursor at the center of the window
    740 	win->event.point become raw mouse movement data 
    741 
    742 	this is useful for a 3D camera
    743 */
    744 RGFWDEF void RGFW_window_mouseHold(RGFW_window* win, RGFW_area area);
    745 /*! stop holding the mouse and let it move freely */
    746 RGFWDEF void RGFW_window_mouseUnhold(RGFW_window* win);
    747 
    748 /*! hide the window */
    749 RGFWDEF void RGFW_window_hide(RGFW_window* win);
    750 /*! show the window */
    751 RGFWDEF void RGFW_window_show(RGFW_window* win);
    752 
    753 /*
    754 	makes it so `RGFW_window_shouldClose` returns true
    755 	by setting the window event.type to RGFW_quit
    756 */
    757 RGFWDEF void RGFW_window_setShouldClose(RGFW_window* win);
    758 
    759 /*! where the mouse is on the screen */
    760 RGFWDEF RGFW_point RGFW_getGlobalMousePoint(void);
    761 
    762 /*! where the mouse is on the window */
    763 RGFWDEF RGFW_point RGFW_window_getMousePoint(RGFW_window* win);
    764 
    765 /*! show the mouse or hide the mouse*/
    766 RGFWDEF void RGFW_window_showMouse(RGFW_window* win, i8 show);
    767 /*! move the mouse to a set x, y pos*/
    768 RGFWDEF void RGFW_window_moveMouse(RGFW_window* win, RGFW_point v);
    769 
    770 /*! if the window should close (RGFW_close was sent or escape was pressed) */
    771 RGFWDEF b8 RGFW_window_shouldClose(RGFW_window* win);
    772 /*! if window is fullscreen'd */
    773 RGFWDEF b8 RGFW_window_isFullscreen(RGFW_window* win);
    774 /*! if window is hidden */
    775 RGFWDEF b8 RGFW_window_isHidden(RGFW_window* win);
    776 /*! if window is minimized */
    777 RGFWDEF b8 RGFW_window_isMinimized(RGFW_window* win);
    778 /*! if window is maximized */
    779 RGFWDEF b8 RGFW_window_isMaximized(RGFW_window* win);
    780 
    781 /** @} */ 
    782 
    783 /** * @defgroup Monitor
    784 * @{ */ 
    785 
    786 #ifndef RGFW_NO_MONITOR
    787 /*
    788 scale the window to the monitor,
    789 this is run by default if the user uses the arg `RGFW_SCALE_TO_MONITOR` during window creation
    790 */
    791 RGFWDEF void RGFW_window_scaleToMonitor(RGFW_window* win);
    792 /*! get the struct of the window's monitor  */
    793 RGFWDEF RGFW_monitor RGFW_window_getMonitor(RGFW_window* win);
    794 #endif
    795 
    796 /** @} */ 
    797 
    798 /** * @defgroup Input
    799 * @{ */ 
    800 
    801 /*error handling*/
    802 RGFWDEF b8 RGFW_Error(void); /*!< returns true if an error has occurred (doesn't print errors itself) */
    803 
    804 /*! returns true if the key should be shifted */
    805 RGFWDEF b8 RGFW_shouldShift(u32 keycode, u8 lockState);
    806 
    807 /*! get char from RGFW keycode (using a LUT), uses shift'd version if shift = true */
    808 RGFWDEF char RGFW_keyCodeToChar(u32 keycode, b8 shift);
    809 /*! get char from RGFW keycode (using a LUT), uses lockState for shouldShift) */
    810 RGFWDEF char RGFW_keyCodeToCharAuto(u32 keycode, u8 lockState);
    811 
    812 /*! 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.*/
    813 RGFWDEF b8 RGFW_isPressed(RGFW_window* win, u8 key); /*!< if key is pressed (key code)*/
    814 
    815 RGFWDEF b8 RGFW_wasPressed(RGFW_window* win, u8 key); /*!< if key was pressed (checks previous state only) (key code)*/
    816 
    817 RGFWDEF b8 RGFW_isHeld(RGFW_window* win, u8 key); /*!< if key is held (key code)*/
    818 RGFWDEF b8 RGFW_isReleased(RGFW_window* win, u8 key); /*!< if key is released (key code)*/
    819 
    820 /* if a key is pressed and then released, pretty much the same as RGFW_isReleased */
    821 RGFWDEF b8 RGFW_isClicked(RGFW_window* win, u8 key /*!< key code*/);
    822 
    823 /*! if a mouse button is pressed */
    824 RGFWDEF b8 RGFW_isMousePressed(RGFW_window* win, u8 button /*!< mouse button code */ );
    825 /*! if a mouse button is held */
    826 RGFWDEF b8 RGFW_isMouseHeld(RGFW_window* win, u8 button /*!< mouse button code */ );
    827 /*! if a mouse button was released */
    828 RGFWDEF b8 RGFW_isMouseReleased(RGFW_window* win, u8 button /*!< mouse button code */ );
    829 /*! if a mouse button was pressed (checks previous state only) */
    830 RGFWDEF b8 RGFW_wasMousePressed(RGFW_window* win, u8 button /*!< mouse button code */ );
    831 /** @} */ 
    832 
    833 /** * @defgroup Clipboard
    834 * @{ */ 
    835 RGFWDEF char* RGFW_readClipboard(size_t* size); /*!< read clipboard data */
    836 RGFWDEF void RGFW_clipboardFree(char* str); /*!< the string returned from RGFW_readClipboard must be freed */
    837 
    838 RGFWDEF void RGFW_writeClipboard(const char* text, u32 textLen); /*!< write text to the clipboard */
    839 /** @} */ 
    840 
    841 /**
    842 	
    843 	
    844 	Event callbacks, 
    845 	these are completely optional, you can use the normal 
    846 	RGFW_checkEvent() method if you prefer that
    847 
    848 * @defgroup Callbacks
    849 * @{ 
    850 */
    851 
    852 /*! RGFW_windowMoved, the window and its new rect value  */
    853 typedef void (* RGFW_windowmovefunc)(RGFW_window* win, RGFW_rect r);
    854 /*! RGFW_windowResized, the window and its new rect value  */
    855 typedef void (* RGFW_windowresizefunc)(RGFW_window* win, RGFW_rect r);
    856 /*! RGFW_quit, the window that was closed */
    857 typedef void (* RGFW_windowquitfunc)(RGFW_window* win);
    858 /*! RGFW_focusIn / RGFW_focusOut, the window who's focus has changed and if its inFocus */
    859 typedef void (* RGFW_focusfunc)(RGFW_window* win, b8 inFocus);
    860 /*! RGFW_mouseEnter / RGFW_mouseLeave, the window that changed, the point of the mouse (enter only) and if the mouse has entered */
    861 typedef void (* RGFW_mouseNotifyfunc)(RGFW_window* win, RGFW_point point, b8 status);
    862 /*! RGFW_mousePosChanged, the window that the move happened on and the new point of the mouse  */
    863 typedef void (* RGFW_mouseposfunc)(RGFW_window* win, RGFW_point point);
    864 /*! RGFW_dnd_init, the window, the point of the drop on the windows */
    865 typedef void (* RGFW_dndInitfunc)(RGFW_window* win, RGFW_point point);
    866 /*! RGFW_windowRefresh, the window that needs to be refreshed */
    867 typedef void (* RGFW_windowrefreshfunc)(RGFW_window* win);
    868 /*! RGFW_keyPressed / RGFW_keyReleased, the window that got the event, the keycode, the string version, the state of mod keys, if it was a press (else it's a release) */
    869 typedef void (* RGFW_keyfunc)(RGFW_window* win, u32 keycode, char keyName[16], u8 lockState, b8 pressed);
    870 /*! RGFW_mouseButtonPressed / RGFW_mouseButtonReleased, the window that got the event, the button that was pressed, the scroll value, if it was a press (else it's a release)  */
    871 typedef void (* RGFW_mousebuttonfunc)(RGFW_window* win, u8 button, double scroll, b8 pressed);
    872 /*! RGFW_jsButtonPressed / RGFW_jsButtonReleased, the window that got the event, the button that was pressed, the scroll value, if it was a press (else it's a release) */
    873 typedef void (* RGFW_jsButtonfunc)(RGFW_window* win, u16 joystick, u8 button, b8 pressed);
    874 /*! RGFW_jsAxisMove, the window that got the event, the joystick in question, the axis values and the amount of axises */
    875 typedef void (* RGFW_jsAxisfunc)(RGFW_window* win, u16 joystick, RGFW_point axis[2], u8 axisesCount);
    876 
    877 
    878 /*!  RGFW_dnd, the window that had the drop, the drop data and the amount files dropped returns previous callback function (if it was set) */
    879 #ifdef RGFW_ALLOC_DROPFILES
    880 	typedef void (* RGFW_dndfunc)(RGFW_window* win, char** droppedFiles, u32 droppedFilesCount);
    881 #else
    882 	typedef void (* RGFW_dndfunc)(RGFW_window* win, char droppedFiles[RGFW_MAX_DROPS][RGFW_MAX_PATH], u32 droppedFilesCount);
    883 #endif
    884 /*! set callback for a window move event returns previous callback function (if it was set)  */
    885 RGFWDEF RGFW_windowmovefunc RGFW_setWindowMoveCallback(RGFW_windowmovefunc func);
    886 /*! set callback for a window resize event returns previous callback function (if it was set)  */
    887 RGFWDEF RGFW_windowresizefunc RGFW_setWindowResizeCallback(RGFW_windowresizefunc func);
    888 /*! set callback for a window quit event returns previous callback function (if it was set)  */
    889 RGFWDEF RGFW_windowquitfunc RGFW_setWindowQuitCallback(RGFW_windowquitfunc func);
    890 /*! set callback for a mouse move event returns previous callback function (if it was set)  */
    891 RGFWDEF RGFW_mouseposfunc RGFW_setMousePosCallback(RGFW_mouseposfunc func);
    892 /*! set callback for a window refresh event returns previous callback function (if it was set)  */
    893 RGFWDEF RGFW_windowrefreshfunc RGFW_setWindowRefreshCallback(RGFW_windowrefreshfunc func);
    894 /*! set callback for a window focus change event returns previous callback function (if it was set)  */
    895 RGFWDEF RGFW_focusfunc RGFW_setFocusCallback(RGFW_focusfunc func);
    896 /*! set callback for a mouse notify event returns previous callback function (if it was set)  */
    897 RGFWDEF RGFW_mouseNotifyfunc RGFW_setMouseNotifyCallBack(RGFW_mouseNotifyfunc func);
    898 /*! set callback for a drop event event returns previous callback function (if it was set)  */
    899 RGFWDEF RGFW_dndfunc RGFW_setDndCallback(RGFW_dndfunc func);
    900 /*! set callback for a start of a drop event returns previous callback function (if it was set)  */
    901 RGFWDEF RGFW_dndInitfunc RGFW_setDndInitCallback(RGFW_dndInitfunc func);
    902 /*! set callback for a key (press / release ) event returns previous callback function (if it was set)  */
    903 RGFWDEF RGFW_keyfunc RGFW_setKeyCallback(RGFW_keyfunc func);
    904 /*! set callback for a mouse button (press / release ) event returns previous callback function (if it was set)  */
    905 RGFWDEF RGFW_mousebuttonfunc RGFW_setMouseButtonCallback(RGFW_mousebuttonfunc func);
    906 /*! set callback for a controller button (press / release ) event returns previous callback function (if it was set)  */
    907 RGFWDEF RGFW_jsButtonfunc RGFW_setjsButtonCallback(RGFW_jsButtonfunc func);
    908 /*! set callback for a joystick axis mov event returns previous callback function (if it was set)  */
    909 RGFWDEF RGFW_jsAxisfunc RGFW_setjsAxisCallback(RGFW_jsAxisfunc func);
    910 
    911 /** @} */ 
    912 
    913 /** * @defgroup Threads
    914 * @{ */ 
    915 
    916 #ifndef RGFW_NO_THREADS
    917 	/*! threading functions*/
    918 
    919 	/*! 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 */
    920 	/*
    921 		I'd suggest you use sili's threading functions instead
    922 		if you're going to use sili
    923 		which is a good idea generally
    924 	*/
    925 
    926 	#if defined(__unix__) || defined(__APPLE__) || defined(RGFW_WEBASM) 
    927 		typedef void* (* RGFW_threadFunc_ptr)(void*);
    928 	#else
    929 		typedef DWORD (__stdcall *RGFW_threadFunc_ptr) (LPVOID lpThreadParameter);  
    930 	#endif
    931 
    932 	RGFWDEF RGFW_thread RGFW_createThread(RGFW_threadFunc_ptr ptr, void* args); /*!< create a thread*/
    933 	RGFWDEF void RGFW_cancelThread(RGFW_thread thread); /*!< cancels a thread*/
    934 	RGFWDEF void RGFW_joinThread(RGFW_thread thread); /*!< join thread to current thread */
    935 	RGFWDEF void RGFW_setThreadPriority(RGFW_thread thread, u8 priority); /*!< sets the priority priority  */
    936 #endif
    937 
    938 /** @} */ 
    939 
    940 /** * @defgroup joystick
    941 * @{ */ 
    942 
    943 /*! joystick count starts at 0*/
    944 /*!< register joystick to window based on a number (the number is based on when it was connected eg. /dev/js0)*/
    945 RGFWDEF u16 RGFW_registerJoystick(RGFW_window* win, i32 jsNumber);
    946 RGFWDEF u16 RGFW_registerJoystickF(RGFW_window* win, char* file);
    947 
    948 RGFWDEF u32 RGFW_isPressedJS(RGFW_window* win, u16 controller, u8 button);
    949 
    950 /** @} */ 
    951 
    952 /** * @defgroup graphics_API
    953 * @{ */ 
    954 
    955 /*!< make the window the current opengl drawing context
    956 
    957 	NOTE:
    958  	if you want to switch the graphics context's thread, 
    959 	you have to run RGFW_window_makeCurrent(NULL); on the old thread
    960 	then RGFW_window_makeCurrent(valid_window) on the new thread
    961 */
    962 RGFWDEF void RGFW_window_makeCurrent(RGFW_window* win);
    963 
    964 /*< updates fps / sets fps to cap (must by ran manually by the user at the end of a frame), returns current fps */
    965 RGFWDEF u32 RGFW_window_checkFPS(RGFW_window* win, u32 fpsCap);
    966 
    967 /* supports openGL, directX, OSMesa, EGL and software rendering */
    968 RGFWDEF void RGFW_window_swapBuffers(RGFW_window* win); /*!< swap the rendering buffer */
    969 RGFWDEF void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval);
    970 
    971 RGFWDEF void RGFW_window_setGPURender(RGFW_window* win, i8 set);
    972 RGFWDEF void RGFW_window_setCPURender(RGFW_window* win, i8 set);
    973 
    974 /*! native API functions */
    975 #if defined(RGFW_OPENGL) || defined(RGFW_EGL)
    976 	/*! OpenGL init hints */
    977 	RGFWDEF void RGFW_setGLStencil(i32 stencil); /*!< set stencil buffer bit size (8 by default) */
    978 	RGFWDEF void RGFW_setGLSamples(i32 samples); /*!< set number of sampiling buffers (4 by default) */
    979 	RGFWDEF void RGFW_setGLStereo(i32 stereo); /*!< use GL_STEREO (GL_FALSE by default) */
    980 	RGFWDEF void RGFW_setGLAuxBuffers(i32 auxBuffers); /*!< number of aux buffers (0 by default) */
    981 
    982 	/*! which profile to use for the opengl verion */
    983 	typedef RGFW_ENUM(u8, RGFW_GL_profile)  { RGFW_GL_CORE = 0,  RGFW_GL_COMPATIBILITY  };
    984 	/*! Set OpenGL version hint (core or compatibility profile)*/
    985 	RGFWDEF void RGFW_setGLVersion(RGFW_GL_profile profile, i32 major, i32 minor);
    986 	RGFWDEF void RGFW_setDoubleBuffer(b8 useDoubleBuffer); 
    987     RGFWDEF void* RGFW_getProcAddress(const char* procname); /*!< get native opengl proc address */
    988     RGFWDEF void RGFW_window_makeCurrent_OpenGL(RGFW_window* win); /*!< to be called by RGFW_window_makeCurrent */
    989 #elif defined(RGFW_DIRECTX)
    990 	typedef struct {
    991 		IDXGIFactory* pFactory;
    992 		IDXGIAdapter* pAdapter;
    993 		ID3D11Device* pDevice;
    994 		ID3D11DeviceContext* pDeviceContext;
    995 	} RGFW_directXinfo;
    996 
    997 	/*
    998 		RGFW stores a global instance of RGFW_directXinfo,
    999 		you can use this function to get a pointer the instance
   1000 	*/
   1001 	RGFWDEF RGFW_directXinfo* RGFW_getDirectXInfo(void);
   1002 #endif
   1003 
   1004 /** @} */ 
   1005 
   1006 /** * @defgroup Supporting
   1007 * @{ */ 
   1008 RGFWDEF u64 RGFW_getTime(void); /*!< get time in seconds */
   1009 RGFWDEF u64 RGFW_getTimeNS(void); /*!< get time in nanoseconds */
   1010 RGFWDEF void RGFW_sleep(u64 milisecond); /*!< sleep for a set time */
   1011 
   1012 /*!
   1013 	key codes and mouse icon enums
   1014 */
   1015 
   1016 typedef RGFW_ENUM(u8, RGFW_Key) {
   1017 	RGFW_KEY_NULL = 0,
   1018 	RGFW_Escape,
   1019 	RGFW_F1,
   1020 	RGFW_F2,
   1021 	RGFW_F3,
   1022 	RGFW_F4,
   1023 	RGFW_F5,
   1024 	RGFW_F6,
   1025 	RGFW_F7,
   1026 	RGFW_F8,
   1027 	RGFW_F9,
   1028 	RGFW_F10,
   1029 	RGFW_F11,
   1030 	RGFW_F12,
   1031 
   1032 	RGFW_Backtick,
   1033 
   1034 	RGFW_0,
   1035 	RGFW_1,
   1036 	RGFW_2,
   1037 	RGFW_3,
   1038 	RGFW_4,
   1039 	RGFW_5,
   1040 	RGFW_6,
   1041 	RGFW_7,
   1042 	RGFW_8,
   1043 	RGFW_9,
   1044 
   1045 	RGFW_Minus,
   1046 	RGFW_Equals,
   1047 	RGFW_BackSpace,
   1048 	RGFW_Tab,
   1049 	RGFW_CapsLock,
   1050 	RGFW_ShiftL,
   1051 	RGFW_ControlL,
   1052 	RGFW_AltL,
   1053 	RGFW_SuperL,
   1054 	RGFW_ShiftR,
   1055 	RGFW_ControlR,
   1056 	RGFW_AltR,
   1057 	RGFW_SuperR,
   1058 	RGFW_Space,
   1059 
   1060 	RGFW_a,
   1061 	RGFW_b,
   1062 	RGFW_c,
   1063 	RGFW_d,
   1064 	RGFW_e,
   1065 	RGFW_f,
   1066 	RGFW_g,
   1067 	RGFW_h,
   1068 	RGFW_i,
   1069 	RGFW_j,
   1070 	RGFW_k,
   1071 	RGFW_l,
   1072 	RGFW_m,
   1073 	RGFW_n,
   1074 	RGFW_o,
   1075 	RGFW_p,
   1076 	RGFW_q,
   1077 	RGFW_r,
   1078 	RGFW_s,
   1079 	RGFW_t,
   1080 	RGFW_u,
   1081 	RGFW_v,
   1082 	RGFW_w,
   1083 	RGFW_x,
   1084 	RGFW_y,
   1085 	RGFW_z,
   1086 
   1087 	RGFW_Period,
   1088 	RGFW_Comma,
   1089 	RGFW_Slash,
   1090 	RGFW_Bracket,
   1091 	RGFW_CloseBracket,
   1092 	RGFW_Semicolon,
   1093 	RGFW_Return,
   1094 	RGFW_Quote,
   1095 	RGFW_BackSlash,
   1096 
   1097 	RGFW_Up,
   1098 	RGFW_Down,
   1099 	RGFW_Left,
   1100 	RGFW_Right,
   1101 
   1102 	RGFW_Delete,
   1103 	RGFW_Insert,
   1104 	RGFW_End,
   1105 	RGFW_Home,
   1106 	RGFW_PageUp,
   1107 	RGFW_PageDown,
   1108 
   1109 	RGFW_Numlock,
   1110 	RGFW_KP_Slash,
   1111 	RGFW_Multiply,
   1112 	RGFW_KP_Minus,
   1113 	RGFW_KP_1,
   1114 	RGFW_KP_2,
   1115 	RGFW_KP_3,
   1116 	RGFW_KP_4,
   1117 	RGFW_KP_5,
   1118 	RGFW_KP_6,
   1119 	RGFW_KP_7,
   1120 	RGFW_KP_8,
   1121 	RGFW_KP_9,
   1122 	RGFW_KP_0,
   1123 	RGFW_KP_Period,
   1124 	RGFW_KP_Return,
   1125 
   1126 	final_key,
   1127 };
   1128 
   1129 
   1130 typedef RGFW_ENUM(u8, RGFW_mouseIcons) {
   1131 	RGFW_MOUSE_NORMAL = 0,
   1132 	RGFW_MOUSE_ARROW,
   1133 	RGFW_MOUSE_IBEAM,
   1134 	RGFW_MOUSE_CROSSHAIR,
   1135 	RGFW_MOUSE_POINTING_HAND,
   1136 	RGFW_MOUSE_RESIZE_EW,
   1137 	RGFW_MOUSE_RESIZE_NS,
   1138 	RGFW_MOUSE_RESIZE_NWSE,
   1139 	RGFW_MOUSE_RESIZE_NESW,
   1140 	RGFW_MOUSE_RESIZE_ALL,
   1141 	RGFW_MOUSE_NOT_ALLOWED,
   1142 };
   1143 
   1144 /** @} */ 
   1145 
   1146 #endif /* RGFW_HEADER */
   1147 
   1148 /*
   1149 Example to get you started :
   1150 
   1151 linux : gcc main.c -lX11 -lXcursor -lGL
   1152 windows : gcc main.c -lopengl32 -lshell32 -lgdi32
   1153 macos : gcc main.c -framework Foundation -framework AppKit -framework OpenGL -framework CoreVideo
   1154 
   1155 #define RGFW_IMPLEMENTATION
   1156 #include "RGFW.h"
   1157 
   1158 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};
   1159 
   1160 int main() {
   1161 	RGFW_window* win = RGFW_createWindow("name", RGFW_RECT(500, 500, 500, 500), (u64)0);
   1162 
   1163 	RGFW_window_setIcon(win, icon, RGFW_AREA(3, 3), 4);
   1164 
   1165 	for (;;) {
   1166 		RGFW_window_checkEvent(win); // NOTE: checking events outside of a while loop may cause input lag
   1167 		if (win->event.type == RGFW_quit || RGFW_isPressed(win, RGFW_Escape))
   1168 			break;
   1169 
   1170 		RGFW_window_swapBuffers(win);
   1171 
   1172 		glClearColor(0xFF, 0XFF, 0xFF, 0xFF);
   1173 		glClear(GL_COLOR_BUFFER_BIT);
   1174 	}
   1175 
   1176 	RGFW_window_close(win);
   1177 }
   1178 
   1179 	compiling :
   1180 
   1181 	if you wish to compile the library all you have to do is create a new file with this in it
   1182 
   1183 	rgfw.c
   1184 	#define RGFW_IMPLEMENTATION
   1185 	#include "RGFW.h"
   1186 
   1187 	then you can use gcc (or whatever compile you wish to use) to compile the library into object file
   1188 
   1189 	ex. gcc -c RGFW.c -fPIC
   1190 
   1191 	after you compile the library into an object file, you can also turn the object file into an static or shared library
   1192 
   1193 	(commands ar and gcc can be replaced with whatever equivalent your system uses)
   1194 	static : ar rcs RGFW.a RGFW.o
   1195 	shared :
   1196 		windows:
   1197 			gcc -shared RGFW.o -lwinmm -lopengl32 -lshell32 -lgdi32 -o RGFW.dll
   1198 		linux:
   1199 			gcc -shared RGFW.o -lX11 -lXcursor -lGL -lXrandr -o RGFW.so
   1200 		macos:
   1201 			gcc -shared RGFW.o -framework Foundation -framework AppKit -framework OpenGL -framework CoreVideo
   1202 */
   1203 
   1204 #ifdef RGFW_X11
   1205 	#define RGFW_OS_BASED_VALUE(l, w, m, h, ww) l
   1206 #elif defined(RGFW_WINDOWS)
   1207 	#define RGFW_OS_BASED_VALUE(l, w, m, h, ww) w
   1208 #elif defined(RGFW_MACOS)
   1209 	#define RGFW_OS_BASED_VALUE(l, w, m, h, ww) m
   1210 #elif defined(RGFW_WEBASM)
   1211 	#define RGFW_OS_BASED_VALUE(l, w, m, h, ww) h
   1212 #elif defined(RGFW_WAYLAND)
   1213     #define RGFW_OS_BASED_VALUE(l, w, m, h, ww) ww  
   1214 #endif
   1215 
   1216 
   1217 #ifdef RGFW_IMPLEMENTATION
   1218 
   1219 #include <stdio.h>
   1220 #include <string.h>
   1221 #include <math.h>
   1222 #include <assert.h>
   1223 
   1224 /*
   1225 RGFW_IMPLEMENTATION starts with generic RGFW defines
   1226 
   1227 This is the start of keycode data
   1228 
   1229 	Why not use macros instead of the numbers itself?
   1230 	Windows -> Not all virtual keys are macros (VK_0 - VK_1, VK_a - VK_z)
   1231 	Linux -> Only symcodes are values, (XK_0 - XK_1, XK_a - XK_z) are larger than 0xFF00, I can't find any way to work with them without making the array an unreasonable size
   1232 	MacOS -> windows and linux already don't have keycodes as macros, so there's no point
   1233 */
   1234 
   1235 
   1236 
   1237 /* 
   1238 	the c++ compiler doesn't support setting up an array like, 
   1239 	we'll have to do it during runtime using a function & this messy setup
   1240 */
   1241 #ifndef __cplusplus
   1242 #define RGFW_NEXT ,
   1243 #define RGFW_MAP
   1244 #else 
   1245 #define RGFW_NEXT ;
   1246 #define RGFW_MAP RGFW_keycodes
   1247 #endif
   1248 
   1249 #ifdef RGFW_WAYLAND
   1250 #include <linux/input-event-codes.h>
   1251 #endif
   1252 
   1253 u8 RGFW_keycodes [RGFW_OS_BASED_VALUE(136, 337, 128, DOM_VK_WIN_OEM_CLEAR + 1, 130)] = {
   1254 #ifdef __cplusplus
   1255 	0
   1256 };
   1257 void RGFW_init_keys(void) {
   1258 #endif
   1259 	RGFW_MAP [RGFW_OS_BASED_VALUE(49, 192, 50, DOM_VK_BACK_QUOTE, KEY_GRAVE)] = RGFW_Backtick 		RGFW_NEXT
   1260 
   1261 	RGFW_MAP [RGFW_OS_BASED_VALUE(19, 0x30, 29, DOM_VK_0, KEY_0)] = RGFW_0 					RGFW_NEXT
   1262 	RGFW_MAP [RGFW_OS_BASED_VALUE(10, 0x31, 18, DOM_VK_1, KEY_1)] = RGFW_1						RGFW_NEXT
   1263 	RGFW_MAP [RGFW_OS_BASED_VALUE(11, 0x32, 19, DOM_VK_2, KEY_2)] = RGFW_2						RGFW_NEXT
   1264 	RGFW_MAP [RGFW_OS_BASED_VALUE(12, 0x33, 20, DOM_VK_3, KEY_3)] = RGFW_3						RGFW_NEXT
   1265 	RGFW_MAP [RGFW_OS_BASED_VALUE(13, 0x34, 21, DOM_VK_4, KEY_4)] = RGFW_4						RGFW_NEXT
   1266 	RGFW_MAP [RGFW_OS_BASED_VALUE(14, 0x35, 23, DOM_VK_5, KEY_5)] = RGFW_5                		RGFW_NEXT
   1267 	RGFW_MAP [RGFW_OS_BASED_VALUE(15, 0x36, 22, DOM_VK_6, KEY_6)] = RGFW_6                		RGFW_NEXT
   1268 	RGFW_MAP [RGFW_OS_BASED_VALUE(16, 0x37, 26, DOM_VK_7, KEY_7)] = RGFW_7                		RGFW_NEXT
   1269 	RGFW_MAP [RGFW_OS_BASED_VALUE(17, 0x38, 28, DOM_VK_8, KEY_8)] = RGFW_8                		RGFW_NEXT
   1270 	RGFW_MAP [RGFW_OS_BASED_VALUE(18, 0x39, 25, DOM_VK_9, KEY_9)] = RGFW_9,
   1271 
   1272 	RGFW_MAP [RGFW_OS_BASED_VALUE(65, 0x20, 49, DOM_VK_SPACE, KEY_SPACE)] = RGFW_Space,
   1273 
   1274 	RGFW_MAP [RGFW_OS_BASED_VALUE(38, 0x41, 0, DOM_VK_A, KEY_A)] = RGFW_a                 		RGFW_NEXT
   1275 	RGFW_MAP [RGFW_OS_BASED_VALUE(56, 0x42, 11, DOM_VK_B, KEY_B)] = RGFW_b                		RGFW_NEXT
   1276 	RGFW_MAP [RGFW_OS_BASED_VALUE(54, 0x43, 8, DOM_VK_C, KEY_C)] = RGFW_c                		RGFW_NEXT
   1277 	RGFW_MAP [RGFW_OS_BASED_VALUE(40, 0x44, 2, DOM_VK_D, KEY_D)] = RGFW_d                 		RGFW_NEXT
   1278 	RGFW_MAP [RGFW_OS_BASED_VALUE(26, 0x45, 14, DOM_VK_E, KEY_E)] = RGFW_e                		RGFW_NEXT
   1279 	RGFW_MAP [RGFW_OS_BASED_VALUE(41, 0x46, 3, DOM_VK_F, KEY_F)] = RGFW_f                 		RGFW_NEXT
   1280 	RGFW_MAP [RGFW_OS_BASED_VALUE(42, 0x47, 5, DOM_VK_G, KEY_G)] = RGFW_g                 		RGFW_NEXT
   1281 	RGFW_MAP [RGFW_OS_BASED_VALUE(43, 0x48, 4, DOM_VK_H, KEY_H)] = RGFW_h                 		RGFW_NEXT
   1282 	RGFW_MAP [RGFW_OS_BASED_VALUE(31, 0x49, 34, DOM_VK_I, KEY_I)] = RGFW_i                		RGFW_NEXT
   1283 	RGFW_MAP [RGFW_OS_BASED_VALUE(44, 0x4A, 38, DOM_VK_J, KEY_J)] = RGFW_j                		RGFW_NEXT
   1284 	RGFW_MAP [RGFW_OS_BASED_VALUE(45, 0x4B, 40, DOM_VK_K, KEY_K)] = RGFW_k                		RGFW_NEXT
   1285 	RGFW_MAP [RGFW_OS_BASED_VALUE(46, 0x4C, 37, DOM_VK_L, KEY_L)] = RGFW_l                		RGFW_NEXT
   1286 	RGFW_MAP [RGFW_OS_BASED_VALUE(58, 0x4D, 46, DOM_VK_M, KEY_M)] = RGFW_m                		RGFW_NEXT
   1287 	RGFW_MAP [RGFW_OS_BASED_VALUE(57, 0x4E, 45, DOM_VK_N, KEY_N)] = RGFW_n                		RGFW_NEXT
   1288 	RGFW_MAP [RGFW_OS_BASED_VALUE(32, 0x4F, 31, DOM_VK_O, KEY_O)] = RGFW_o                		RGFW_NEXT
   1289 	RGFW_MAP [RGFW_OS_BASED_VALUE(33, 0x50, 35, DOM_VK_P, KEY_P)] = RGFW_p                		RGFW_NEXT
   1290 	RGFW_MAP [RGFW_OS_BASED_VALUE(24, 0x51, 12, DOM_VK_Q, KEY_Q)] = RGFW_q                		RGFW_NEXT
   1291 	RGFW_MAP [RGFW_OS_BASED_VALUE(27, 0x52, 15, DOM_VK_R, KEY_R)] = RGFW_r                		RGFW_NEXT
   1292 	RGFW_MAP [RGFW_OS_BASED_VALUE(39, 0x53, 1, DOM_VK_S, KEY_S)] = RGFW_s                 		RGFW_NEXT
   1293 	RGFW_MAP [RGFW_OS_BASED_VALUE(28, 0x54, 17, DOM_VK_T, KEY_T)] = RGFW_t                		RGFW_NEXT
   1294 	RGFW_MAP [RGFW_OS_BASED_VALUE(30, 0x55, 32, DOM_VK_U, KEY_U)] = RGFW_u                		RGFW_NEXT
   1295 	RGFW_MAP [RGFW_OS_BASED_VALUE(55, 0x56, 9, DOM_VK_V, KEY_V)] = RGFW_v                 		RGFW_NEXT
   1296 	RGFW_MAP [RGFW_OS_BASED_VALUE(25, 0x57, 13, DOM_VK_W, KEY_W)] = RGFW_w                		RGFW_NEXT
   1297 	RGFW_MAP [RGFW_OS_BASED_VALUE(53, 0x58, 7, DOM_VK_X, KEY_X)] = RGFW_x                 		RGFW_NEXT
   1298 	RGFW_MAP [RGFW_OS_BASED_VALUE(29, 0x59, 16, DOM_VK_Y, KEY_Y)] = RGFW_y                		RGFW_NEXT
   1299 	RGFW_MAP [RGFW_OS_BASED_VALUE(52, 0x5A, 6, DOM_VK_Z, KEY_Z)] = RGFW_z,
   1300 
   1301 	RGFW_MAP [RGFW_OS_BASED_VALUE(60, 190, 47, DOM_VK_PERIOD, KEY_DOT)] = RGFW_Period             			RGFW_NEXT
   1302 	RGFW_MAP [RGFW_OS_BASED_VALUE(59, 188, 43, DOM_VK_COMMA, KEY_COMMA)] = RGFW_Comma               			RGFW_NEXT
   1303 	RGFW_MAP [RGFW_OS_BASED_VALUE(61, 191, 44, DOM_VK_SLASH, KEY_SLASH)] = RGFW_Slash               			RGFW_NEXT
   1304 	RGFW_MAP [RGFW_OS_BASED_VALUE(34, 219, 33, DOM_VK_OPEN_BRACKET, KEY_LEFTBRACE)] = RGFW_Bracket      			RGFW_NEXT
   1305 	RGFW_MAP [RGFW_OS_BASED_VALUE(35, 221, 30, DOM_VK_CLOSE_BRACKET, KEY_RIGHTBRACE)] = RGFW_CloseBracket             RGFW_NEXT
   1306 	RGFW_MAP [RGFW_OS_BASED_VALUE(47, 186, 41, DOM_VK_SEMICOLON, KEY_SEMICOLON)] = RGFW_Semicolon                 RGFW_NEXT
   1307 	RGFW_MAP [RGFW_OS_BASED_VALUE(48, 222, 39, DOM_VK_QUOTE, KEY_APOSTROPHE)] = RGFW_Quote                 			RGFW_NEXT
   1308 	RGFW_MAP [RGFW_OS_BASED_VALUE(51, 322, 42, DOM_VK_BACK_SLASH, KEY_BACKSLASH)] = RGFW_BackSlash,
   1309 	
   1310 	RGFW_MAP [RGFW_OS_BASED_VALUE(36, 0x0D, 36, DOM_VK_RETURN, KEY_ENTER)] = RGFW_Return              RGFW_NEXT
   1311 	RGFW_MAP [RGFW_OS_BASED_VALUE(119, 0x2E, 118, DOM_VK_DELETE, KEY_DELETE)] = RGFW_Delete                		RGFW_NEXT
   1312 	RGFW_MAP [RGFW_OS_BASED_VALUE(77, 0x90, 72, DOM_VK_NUM_LOCK, KEY_NUMLOCK)] = RGFW_Numlock               RGFW_NEXT
   1313 	RGFW_MAP [RGFW_OS_BASED_VALUE(106, 0x6F, 82, DOM_VK_DIVIDE, KEY_KPSLASH)] = RGFW_KP_Slash               RGFW_NEXT
   1314 	RGFW_MAP [RGFW_OS_BASED_VALUE(63, 0x6A, 76, DOM_VK_MULTIPLY, KEY_KPASTERISK)] = RGFW_Multiply              RGFW_NEXT
   1315 	RGFW_MAP [RGFW_OS_BASED_VALUE(82, 0x6D, 67, DOM_VK_SUBTRACT, KEY_KPMINUS)] = RGFW_KP_Minus              RGFW_NEXT
   1316 	RGFW_MAP [RGFW_OS_BASED_VALUE(87, 0x61, 84, DOM_VK_NUMPAD1, KEY_KP1)] = RGFW_KP_1               RGFW_NEXT
   1317 	RGFW_MAP [RGFW_OS_BASED_VALUE(88, 0x62, 85, DOM_VK_NUMPAD2, KEY_KP2)] = RGFW_KP_2               RGFW_NEXT
   1318 	RGFW_MAP [RGFW_OS_BASED_VALUE(89, 0x63, 86, DOM_VK_NUMPAD3, KEY_KP3)] = RGFW_KP_3               RGFW_NEXT
   1319 	RGFW_MAP [RGFW_OS_BASED_VALUE(83, 0x64, 87, DOM_VK_NUMPAD4, KEY_KP4)] = RGFW_KP_4               RGFW_NEXT
   1320 	RGFW_MAP [RGFW_OS_BASED_VALUE(84, 0x65, 88, DOM_VK_NUMPAD5, KEY_KP5)] = RGFW_KP_5               RGFW_NEXT
   1321 	RGFW_MAP [RGFW_OS_BASED_VALUE(85, 0x66, 89, DOM_VK_NUMPAD6, KEY_KP6)] = RGFW_KP_6               RGFW_NEXT
   1322 	RGFW_MAP [RGFW_OS_BASED_VALUE(79, 0x67, 90, DOM_VK_NUMPAD7, KEY_KP7)] = RGFW_KP_7               RGFW_NEXT
   1323 	RGFW_MAP [RGFW_OS_BASED_VALUE(80, 0x68, 92, DOM_VK_NUMPAD8, KEY_KP8)] = RGFW_KP_8               RGFW_NEXT
   1324 	RGFW_MAP [RGFW_OS_BASED_VALUE(81, 0x69, 93, DOM_VK_NUMPAD9, KEY_KP9)] = RGFW_KP_9               RGFW_NEXT
   1325 	RGFW_MAP [RGFW_OS_BASED_VALUE(90, 0x60, 83, DOM_VK_NUMPAD0, KEY_KP0)] = RGFW_KP_0               RGFW_NEXT
   1326 	RGFW_MAP [RGFW_OS_BASED_VALUE(91, 0x6E, 65, DOM_VK_DECIMAL, KEY_KPDOT)] = RGFW_KP_Period              RGFW_NEXT
   1327 	RGFW_MAP [RGFW_OS_BASED_VALUE(104, 0x92, 77, 0, KEY_KPENTER)] = RGFW_KP_Return,
   1328 	
   1329 	RGFW_MAP [RGFW_OS_BASED_VALUE(20, 189, 27, DOM_VK_HYPHEN_MINUS, KEY_MINUS)] = RGFW_Minus              RGFW_NEXT
   1330 	RGFW_MAP [RGFW_OS_BASED_VALUE(21, 187, 24, DOM_VK_EQUALS, KEY_EQUAL)] = RGFW_Equals               RGFW_NEXT
   1331 	RGFW_MAP [RGFW_OS_BASED_VALUE(22, 8, 51, DOM_VK_BACK_SPACE, KEY_BACKSPACE)] = RGFW_BackSpace              RGFW_NEXT
   1332 	RGFW_MAP [RGFW_OS_BASED_VALUE(23, 0x09, 48, DOM_VK_TAB, KEY_TAB)] = RGFW_Tab                		RGFW_NEXT
   1333 	RGFW_MAP [RGFW_OS_BASED_VALUE(66, 20, 57, DOM_VK_CAPS_LOCK, KEY_CAPSLOCK)] = RGFW_CapsLock               RGFW_NEXT
   1334 	RGFW_MAP [RGFW_OS_BASED_VALUE(50, 0x10, 56, DOM_VK_SHIFT, KEY_LEFTSHIFT)] = RGFW_ShiftL               RGFW_NEXT
   1335 	RGFW_MAP [RGFW_OS_BASED_VALUE(37, 0x11, 59, DOM_VK_CONTROL, KEY_LEFTCTRL)] = RGFW_ControlL               RGFW_NEXT
   1336 	RGFW_MAP [RGFW_OS_BASED_VALUE(64,0x12, 58, DOM_VK_ALT, KEY_LEFTALT)] = RGFW_AltL                		RGFW_NEXT
   1337 	RGFW_MAP [RGFW_OS_BASED_VALUE(133, 0x5B, 55, DOM_VK_WIN, KEY_LEFTMETA)] = RGFW_SuperL,
   1338 	
   1339 	#if !defined(RGFW_WINDOWS) && !defined(RGFW_MACOS) && !defined(RGFW_WEBASM)
   1340 	RGFW_MAP [RGFW_OS_BASED_VALUE(105, 0x11, 59, 0, KEY_RIGHTCTRL)] = RGFW_ControlR               RGFW_NEXT
   1341 	RGFW_MAP [RGFW_OS_BASED_VALUE(135, 0xA4, 55, 0, KEY_RIGHTMETA)] = RGFW_SuperR,
   1342 	RGFW_MAP [RGFW_OS_BASED_VALUE(62, 0x5C, 56, 0, KEY_RIGHTSHIFT)] = RGFW_ShiftR              RGFW_NEXT
   1343 	RGFW_MAP [RGFW_OS_BASED_VALUE(108, 165, 58, 0, KEY_RIGHTALT)] = RGFW_AltR,
   1344 	#endif
   1345 
   1346 	RGFW_MAP [RGFW_OS_BASED_VALUE(67, 0x70, 127, DOM_VK_F1, KEY_F1)] = RGFW_F1                 		RGFW_NEXT
   1347 	RGFW_MAP [RGFW_OS_BASED_VALUE(68, 0x71, 121, DOM_VK_F2, KEY_F2)] = RGFW_F2                 		RGFW_NEXT
   1348 	RGFW_MAP [RGFW_OS_BASED_VALUE(69, 0x72, 100, DOM_VK_F3, KEY_F3)] = RGFW_F3                 		RGFW_NEXT
   1349 	RGFW_MAP [RGFW_OS_BASED_VALUE(70, 0x73, 119, DOM_VK_F4, KEY_F4)] = RGFW_F4                 		RGFW_NEXT
   1350 	RGFW_MAP [RGFW_OS_BASED_VALUE(71, 0x74, 97, DOM_VK_F5, KEY_F5)] = RGFW_F5              RGFW_NEXT
   1351 	RGFW_MAP [RGFW_OS_BASED_VALUE(72, 0x75, 98, DOM_VK_F6, KEY_F6)] = RGFW_F6              RGFW_NEXT
   1352 	RGFW_MAP [RGFW_OS_BASED_VALUE(73, 0x76, 99, DOM_VK_F7, KEY_F7)] = RGFW_F7              RGFW_NEXT
   1353 	RGFW_MAP [RGFW_OS_BASED_VALUE(74, 0x77, 101, DOM_VK_F8, KEY_F8)] = RGFW_F8                 		RGFW_NEXT
   1354 	RGFW_MAP [RGFW_OS_BASED_VALUE(75, 0x78, 102, DOM_VK_F9, KEY_F9)] = RGFW_F9                 		RGFW_NEXT
   1355 	RGFW_MAP [RGFW_OS_BASED_VALUE(76, 0x79, 110, DOM_VK_F10, KEY_F10)] = RGFW_F10               RGFW_NEXT
   1356 	RGFW_MAP [RGFW_OS_BASED_VALUE(95, 0x7A, 104, DOM_VK_F11, KEY_F11)] = RGFW_F11               RGFW_NEXT
   1357 	RGFW_MAP [RGFW_OS_BASED_VALUE(96, 0x7B, 112, DOM_VK_F12, KEY_F12)] = RGFW_F12               RGFW_NEXT
   1358 	RGFW_MAP [RGFW_OS_BASED_VALUE(111, 0x26, 126, DOM_VK_UP, KEY_UP)] = RGFW_Up                		RGFW_NEXT
   1359 	RGFW_MAP [RGFW_OS_BASED_VALUE(116, 0x28, 125, DOM_VK_DOWN, KEY_DOWN)] = RGFW_Down                		RGFW_NEXT
   1360 	RGFW_MAP [RGFW_OS_BASED_VALUE(113, 0x25, 123, DOM_VK_LEFT, KEY_LEFT)] = RGFW_Left                		RGFW_NEXT
   1361 	RGFW_MAP [RGFW_OS_BASED_VALUE(114, 0x27, 124, DOM_VK_RIGHT, KEY_RIGHT)] = RGFW_Right              RGFW_NEXT
   1362 	RGFW_MAP [RGFW_OS_BASED_VALUE(118, 0x2D, 115, DOM_VK_INSERT, KEY_INSERT)] = RGFW_Insert                		RGFW_NEXT
   1363 	RGFW_MAP [RGFW_OS_BASED_VALUE(115, 0x23, 120, DOM_VK_END, KEY_END)] = RGFW_End                  		RGFW_NEXT
   1364 	RGFW_MAP [RGFW_OS_BASED_VALUE(112, 336, 117, DOM_VK_PAGE_UP, KEY_PAGEUP)] = RGFW_PageUp                		RGFW_NEXT
   1365 	RGFW_MAP [RGFW_OS_BASED_VALUE(117, 325, 122, DOM_VK_PAGE_DOWN, KEY_PAGEDOWN)] = RGFW_PageDown            RGFW_NEXT
   1366 	RGFW_MAP [RGFW_OS_BASED_VALUE(9, 0x1B, 53, DOM_VK_ESCAPE, KEY_ESC)] = RGFW_Escape                   		RGFW_NEXT
   1367 	RGFW_MAP [RGFW_OS_BASED_VALUE(110, 0x24, 116, DOM_VK_HOME, KEY_HOME)] = RGFW_Home                    		RGFW_NEXT
   1368 #ifndef __cplusplus
   1369 };
   1370 #else 
   1371 }
   1372 #endif
   1373 
   1374 #undef RGFW_NEXT
   1375 #undef RGFW_MAP
   1376 
   1377 typedef struct {
   1378 	b8 current  : 1;
   1379 	b8 prev  : 1;
   1380 } RGFW_keyState;
   1381 
   1382 RGFW_keyState RGFW_keyboard[final_key] = { {0, 0} };
   1383 
   1384 RGFWDEF u32 RGFW_apiKeyCodeToRGFW(u32 keycode);
   1385 
   1386 u32 RGFW_apiKeyCodeToRGFW(u32 keycode) {
   1387 	#ifdef __cplusplus
   1388 	if (RGFW_OS_BASED_VALUE(49, 192, 50, DOM_VK_BACK_QUOTE, KEY_GRAVE) != RGFW_Backtick) {
   1389 		RGFW_init_keys();
   1390 	}
   1391 	#endif
   1392 
   1393 	/* make sure the key isn't out of bounds */
   1394 	if (keycode > sizeof(RGFW_keycodes) / sizeof(u8))
   1395 		return 0;
   1396 	
   1397 	return RGFW_keycodes[keycode];
   1398 }
   1399 
   1400 RGFWDEF void RGFW_resetKey(void);
   1401 void RGFW_resetKey(void) {
   1402 	size_t len = final_key; /*!< last_key == length */
   1403 	
   1404 	size_t i; /*!< reset each previous state  */
   1405 	for (i = 0; i < len; i++)
   1406 		RGFW_keyboard[i].prev = 0;
   1407 }
   1408 
   1409 b8 RGFW_shouldShift(u32 keycode, u8 lockState) {
   1410     #define RGFW_xor(x, y) (( (x) && (!(y)) ) ||  ((y) && (!(x)) ))
   1411     b8 caps4caps = (lockState & RGFW_CAPSLOCK) && ((keycode >= RGFW_a) && (keycode <= RGFW_z));
   1412     b8 shouldShift = RGFW_xor((RGFW_isPressed(NULL, RGFW_ShiftL) || RGFW_isPressed(NULL, RGFW_ShiftR)), caps4caps);
   1413     #undef RGFW_xor
   1414 
   1415 	return shouldShift;
   1416 }	
   1417 
   1418 char RGFW_keyCodeToChar(u32 keycode, b8 shift) {
   1419     static const char map[] = {
   1420         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '`', '0', '1', '2', '3', '4', '5', '6', '7', '8', 
   1421         '9', '-', '=', 0, '\t',  0, 0, 0, 0, 0, 0, 0, 0, 0, ' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
   1422         'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '.', ',', '/', '[', ']',  ';', '\n', '\'', '\\', 
   1423         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  '/', '*', '-', '1', '2', '3',  '4', '5', '6', '7', '8',  '9', '0', '\n'
   1424     };
   1425 
   1426     static const char mapCaps[] = {
   1427         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '~', ')', '!', '@', '#', '$', '%', '^', '&', '*', 
   1428         '(', '_', '+', 0, '0',  0, 0, 0, 0, 0, 0, 0, 0, 0, ' ', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
   1429         'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
   1430         'X', 'Y', 'Z', '>', '<', '?', '{', '}',  ':', '\n', '"', '|', 
   1431         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '?', '*', '-', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
   1432     };
   1433 
   1434     if (shift == RGFW_FALSE)
   1435         return map[keycode]; 
   1436     return mapCaps[keycode];
   1437 }
   1438 
   1439 char RGFW_keyCodeToCharAuto(u32 keycode, u8 lockState) { return RGFW_keyCodeToChar(keycode, RGFW_shouldShift(keycode, lockState)); }
   1440 
   1441 /*
   1442 	this is the end of keycode data
   1443 */
   1444 
   1445 /* joystick data */
   1446 u8 RGFW_jsPressed[4][16]; /*!< if a key is currently pressed or not (per joystick) */
   1447 
   1448 i32 RGFW_joysticks[4]; /*!< limit of 4 joysticks at a time */
   1449 u16 RGFW_joystickCount; /*!< the actual amount of joysticks */
   1450 
   1451 /* 
   1452 	event callback defines start here
   1453 */
   1454 
   1455 
   1456 /*
   1457 	These exist to avoid the 
   1458 	if (func == NULL) check 
   1459 	for (allegedly) better performance
   1460 */
   1461 void RGFW_windowmovefuncEMPTY(RGFW_window* win, RGFW_rect r) { RGFW_UNUSED(win); RGFW_UNUSED(r); }
   1462 void RGFW_windowresizefuncEMPTY(RGFW_window* win, RGFW_rect r) { RGFW_UNUSED(win); RGFW_UNUSED(r); }
   1463 void RGFW_windowquitfuncEMPTY(RGFW_window* win) { RGFW_UNUSED(win); }
   1464 void RGFW_focusfuncEMPTY(RGFW_window* win, b8 inFocus) {RGFW_UNUSED(win); RGFW_UNUSED(inFocus);}
   1465 void RGFW_mouseNotifyfuncEMPTY(RGFW_window* win, RGFW_point point, b8 status) {RGFW_UNUSED(win); RGFW_UNUSED(point); RGFW_UNUSED(status);}
   1466 void RGFW_mouseposfuncEMPTY(RGFW_window* win, RGFW_point point) {RGFW_UNUSED(win); RGFW_UNUSED(point);}
   1467 void RGFW_dndInitfuncEMPTY(RGFW_window* win, RGFW_point point) {RGFW_UNUSED(win); RGFW_UNUSED(point);}
   1468 void RGFW_windowrefreshfuncEMPTY(RGFW_window* win) {RGFW_UNUSED(win); }
   1469 void RGFW_keyfuncEMPTY(RGFW_window* win, u32 keycode, char keyName[16], u8 lockState, b8 pressed) {RGFW_UNUSED(win); RGFW_UNUSED(keycode); RGFW_UNUSED(keyName); RGFW_UNUSED(lockState); RGFW_UNUSED(pressed);}
   1470 void RGFW_mousebuttonfuncEMPTY(RGFW_window* win, u8 button, double scroll, b8 pressed) {RGFW_UNUSED(win); RGFW_UNUSED(button); RGFW_UNUSED(scroll); RGFW_UNUSED(pressed);}
   1471 void RGFW_jsButtonfuncEMPTY(RGFW_window* win, u16 joystick, u8 button, b8 pressed){RGFW_UNUSED(win); RGFW_UNUSED(joystick); RGFW_UNUSED(button); RGFW_UNUSED(pressed); }
   1472 void RGFW_jsAxisfuncEMPTY(RGFW_window* win, u16 joystick, RGFW_point axis[2], u8 axisesCount){RGFW_UNUSED(win); RGFW_UNUSED(joystick); RGFW_UNUSED(axis); RGFW_UNUSED(axisesCount); }
   1473 
   1474 #ifdef RGFW_ALLOC_DROPFILES
   1475 void RGFW_dndfuncEMPTY(RGFW_window* win, char** droppedFiles, u32 droppedFilesCount) {RGFW_UNUSED(win); RGFW_UNUSED(droppedFiles); RGFW_UNUSED(droppedFilesCount);}
   1476 #else
   1477 void RGFW_dndfuncEMPTY(RGFW_window* win, char droppedFiles[RGFW_MAX_DROPS][RGFW_MAX_PATH], u32 droppedFilesCount) {RGFW_UNUSED(win); RGFW_UNUSED(droppedFiles); RGFW_UNUSED(droppedFilesCount);}
   1478 #endif
   1479 
   1480 RGFW_windowmovefunc RGFW_windowMoveCallback = RGFW_windowmovefuncEMPTY;
   1481 RGFW_windowresizefunc RGFW_windowResizeCallback = RGFW_windowresizefuncEMPTY;
   1482 RGFW_windowquitfunc RGFW_windowQuitCallback = RGFW_windowquitfuncEMPTY;
   1483 RGFW_mouseposfunc RGFW_mousePosCallback = RGFW_mouseposfuncEMPTY;
   1484 RGFW_windowrefreshfunc RGFW_windowRefreshCallback = RGFW_windowrefreshfuncEMPTY;
   1485 RGFW_focusfunc RGFW_focusCallback = RGFW_focusfuncEMPTY;
   1486 RGFW_mouseNotifyfunc RGFW_mouseNotifyCallBack = RGFW_mouseNotifyfuncEMPTY;
   1487 RGFW_dndfunc RGFW_dndCallback = RGFW_dndfuncEMPTY;
   1488 RGFW_dndInitfunc RGFW_dndInitCallback = RGFW_dndInitfuncEMPTY;
   1489 RGFW_keyfunc RGFW_keyCallback = RGFW_keyfuncEMPTY;
   1490 RGFW_mousebuttonfunc RGFW_mouseButtonCallback = RGFW_mousebuttonfuncEMPTY;
   1491 RGFW_jsButtonfunc RGFW_jsButtonCallback = RGFW_jsButtonfuncEMPTY;
   1492 RGFW_jsAxisfunc RGFW_jsAxisCallback = RGFW_jsAxisfuncEMPTY;
   1493 
   1494 void RGFW_window_checkEvents(RGFW_window* win, i32 waitMS) { 
   1495 	RGFW_window_eventWait(win, waitMS);
   1496 
   1497 	while (RGFW_window_checkEvent(win) != NULL && RGFW_window_shouldClose(win) == 0) { 
   1498 		if (win->event.type == RGFW_quit) return; 
   1499 	}
   1500 	
   1501 	#ifdef RGFW_WEBASM /* webasm needs to run the sleep function for asyncify */
   1502 		RGFW_sleep(0);
   1503 	#endif
   1504 }
   1505 
   1506 RGFW_windowmovefunc RGFW_setWindowMoveCallback(RGFW_windowmovefunc func) { 
   1507 	RGFW_windowmovefunc	prev =  (RGFW_windowMoveCallback == RGFW_windowmovefuncEMPTY) ? NULL : RGFW_windowMoveCallback;
   1508 	RGFW_windowMoveCallback = func;
   1509 	return prev;
   1510 }
   1511 RGFW_windowresizefunc RGFW_setWindowResizeCallback(RGFW_windowresizefunc func) {
   1512     RGFW_windowresizefunc prev = (RGFW_windowResizeCallback == RGFW_windowresizefuncEMPTY) ? NULL : RGFW_windowResizeCallback;
   1513     RGFW_windowResizeCallback = func;
   1514     return prev;
   1515 }
   1516 RGFW_windowquitfunc RGFW_setWindowQuitCallback(RGFW_windowquitfunc func) {
   1517     RGFW_windowquitfunc prev = (RGFW_windowQuitCallback == RGFW_windowquitfuncEMPTY) ? NULL : RGFW_windowQuitCallback;
   1518     RGFW_windowQuitCallback = func;
   1519     return prev;
   1520 }
   1521 
   1522 RGFW_mouseposfunc RGFW_setMousePosCallback(RGFW_mouseposfunc func) {
   1523     RGFW_mouseposfunc prev = (RGFW_mousePosCallback == RGFW_mouseposfuncEMPTY) ? NULL : RGFW_mousePosCallback;
   1524     RGFW_mousePosCallback = func;
   1525     return prev;
   1526 }
   1527 RGFW_windowrefreshfunc RGFW_setWindowRefreshCallback(RGFW_windowrefreshfunc func) {
   1528     RGFW_windowrefreshfunc prev = (RGFW_windowRefreshCallback == RGFW_windowrefreshfuncEMPTY) ? NULL : RGFW_windowRefreshCallback;
   1529     RGFW_windowRefreshCallback = func;
   1530     return prev;
   1531 }
   1532 RGFW_focusfunc RGFW_setFocusCallback(RGFW_focusfunc func) {
   1533     RGFW_focusfunc prev = (RGFW_focusCallback == RGFW_focusfuncEMPTY) ? NULL : RGFW_focusCallback;
   1534     RGFW_focusCallback = func;
   1535     return prev;
   1536 }
   1537 
   1538 RGFW_mouseNotifyfunc RGFW_setMouseNotifyCallBack(RGFW_mouseNotifyfunc func) {
   1539     RGFW_mouseNotifyfunc prev = (RGFW_mouseNotifyCallBack == RGFW_mouseNotifyfuncEMPTY) ? NULL : RGFW_mouseNotifyCallBack;
   1540     RGFW_mouseNotifyCallBack = func;
   1541     return prev;
   1542 }
   1543 RGFW_dndfunc RGFW_setDndCallback(RGFW_dndfunc func) {
   1544     RGFW_dndfunc prev = (RGFW_dndCallback == RGFW_dndfuncEMPTY) ? NULL : RGFW_dndCallback;
   1545     RGFW_dndCallback = func;
   1546     return prev;
   1547 }
   1548 RGFW_dndInitfunc RGFW_setDndInitCallback(RGFW_dndInitfunc func) {
   1549     RGFW_dndInitfunc prev = (RGFW_dndInitCallback == RGFW_dndInitfuncEMPTY) ? NULL : RGFW_dndInitCallback;
   1550     RGFW_dndInitCallback = func;
   1551     return prev;
   1552 }
   1553 RGFW_keyfunc RGFW_setKeyCallback(RGFW_keyfunc func) {
   1554     RGFW_keyfunc prev = (RGFW_keyCallback == RGFW_keyfuncEMPTY) ? NULL : RGFW_keyCallback;
   1555     RGFW_keyCallback = func;
   1556     return prev;
   1557 }
   1558 RGFW_mousebuttonfunc RGFW_setMouseButtonCallback(RGFW_mousebuttonfunc func) {
   1559     RGFW_mousebuttonfunc prev = (RGFW_mouseButtonCallback == RGFW_mousebuttonfuncEMPTY) ? NULL : RGFW_mouseButtonCallback;
   1560     RGFW_mouseButtonCallback = func;
   1561     return prev;
   1562 }
   1563 RGFW_jsButtonfunc RGFW_setjsButtonCallback(RGFW_jsButtonfunc func) {
   1564     RGFW_jsButtonfunc prev = (RGFW_jsButtonCallback == RGFW_jsButtonfuncEMPTY) ? NULL : RGFW_jsButtonCallback;
   1565     RGFW_jsButtonCallback = func;
   1566     return prev;
   1567 }
   1568 RGFW_jsAxisfunc RGFW_setjsAxisCallback(RGFW_jsAxisfunc func) {
   1569     RGFW_jsAxisfunc prev = (RGFW_jsAxisCallback == RGFW_jsAxisfuncEMPTY) ? NULL : RGFW_jsAxisCallback;
   1570     RGFW_jsAxisCallback = func;
   1571     return prev;
   1572 }
   1573 /* 
   1574 no more event call back defines
   1575 */
   1576 
   1577 #define RGFW_ASSERT(check, str) {\
   1578 	if (!(check)) { \
   1579 		printf(str); \
   1580 		assert(check); \
   1581 	} \
   1582 }
   1583 
   1584 b8 RGFW_error = 0;
   1585 b8 RGFW_Error(void) { return RGFW_error; }
   1586 
   1587 #define SET_ATTRIB(a, v) { \
   1588     assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
   1589     attribs[index++] = a; \
   1590     attribs[index++] = v; \
   1591 }
   1592 	
   1593 RGFW_area RGFW_bufferSize = {0, 0};
   1594 void RGFW_setBufferSize(RGFW_area size) {
   1595 	RGFW_bufferSize = size;
   1596 }
   1597 
   1598 
   1599 RGFWDEF RGFW_window* RGFW_window_basic_init(RGFW_rect rect, u16 args);
   1600 
   1601 /* do a basic initialization for RGFW_window, this is to standard it for each OS */
   1602 RGFW_window* RGFW_window_basic_init(RGFW_rect rect, u16 args) {
   1603 	RGFW_window* win = (RGFW_window*) RGFW_MALLOC(sizeof(RGFW_window)); /*!< make a new RGFW struct */
   1604 
   1605 	/* clear out dnd info */
   1606 #ifdef RGFW_ALLOC_DROPFILES
   1607 	win->event.droppedFiles = (char**) RGFW_MALLOC(sizeof(char*) * RGFW_MAX_DROPS);
   1608 	u32 i;
   1609 	for (i = 0; i < RGFW_MAX_DROPS; i++)
   1610 		win->event.droppedFiles[i] = (char*) RGFW_CALLOC(RGFW_MAX_PATH, sizeof(char));
   1611 #endif
   1612 
   1613 	/* X11 requires us to have a display to get the screen size */
   1614 	#ifndef RGFW_X11 
   1615 	RGFW_area screenR = RGFW_getScreenSize();
   1616 	#else
   1617 	win->src.display = XOpenDisplay(NULL);
   1618 	assert(win->src.display != NULL);
   1619 
   1620 	Screen* scrn = DefaultScreenOfDisplay((Display*)win->src.display);
   1621 	RGFW_area screenR = RGFW_AREA((u32)scrn->width, (u32)scrn->height);
   1622 	#endif
   1623 	
   1624 	/* rect based the requested args */
   1625 	if (args & RGFW_FULLSCREEN)
   1626 		rect = RGFW_RECT(0, 0, screenR.w, screenR.h);
   1627 
   1628 	/* set and init the new window's data */
   1629 	win->r = rect;
   1630 	win->event.inFocus = 1;
   1631 	win->event.droppedFilesCount = 0;
   1632 	RGFW_joystickCount = 0;
   1633 	win->_winArgs = 0;
   1634 	win->event.lockState = 0;
   1635 
   1636 	return win;
   1637 }
   1638 
   1639 #ifndef RGFW_NO_MONITOR
   1640 void RGFW_window_scaleToMonitor(RGFW_window* win) {
   1641 	RGFW_monitor monitor = RGFW_window_getMonitor(win);
   1642 	
   1643 	RGFW_window_resize(win, RGFW_AREA((u32)(monitor.scaleX * (float)win->r.w), (u32)(monitor.scaleX * (float)win->r.h)));
   1644 }
   1645 #endif
   1646 
   1647 RGFW_window* RGFW_root = NULL;
   1648 
   1649 
   1650 #define RGFW_HOLD_MOUSE			(1L<<2) /*!< hold the moues still */
   1651 #define RGFW_MOUSE_LEFT 		(1L<<3) /* if mouse left the window */
   1652 
   1653 #ifdef RGFW_MACOS
   1654 RGFWDEF void RGFW_window_cocoaSetLayer(RGFW_window* win, void* layer);
   1655 RGFWDEF void* RGFW_cocoaGetLayer(void);
   1656 #endif
   1657 
   1658 char* RGFW_className = NULL;
   1659 void RGFW_setClassName(char* name) {
   1660 	RGFW_className = name;
   1661 }
   1662 
   1663 void RGFW_clipboardFree(char* str) { RGFW_FREE(str); }
   1664 
   1665 RGFW_keyState RGFW_mouseButtons[5] = { {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0} };
   1666 
   1667 b8 RGFW_isMousePressed(RGFW_window* win, u8 button) {
   1668 	assert(win != NULL);
   1669 	return RGFW_mouseButtons[button].current && (win != NULL) && win->event.inFocus; 
   1670 }
   1671 b8 RGFW_wasMousePressed(RGFW_window* win, u8 button) {
   1672 	assert(win != NULL); 
   1673 	return RGFW_mouseButtons[button].prev && (win != NULL) && win->event.inFocus; 
   1674 }
   1675 b8 RGFW_isMouseHeld(RGFW_window* win, u8 button) {
   1676 	return (RGFW_isMousePressed(win, button) && RGFW_wasMousePressed(win, button));
   1677 }
   1678 b8 RGFW_isMouseReleased(RGFW_window* win, u8 button) {
   1679 	return (!RGFW_isMousePressed(win, button) && RGFW_wasMousePressed(win, button));	
   1680 }
   1681 
   1682 b8 RGFW_isPressed(RGFW_window* win, u8 key) {
   1683 	return RGFW_keyboard[key].current && (win == NULL || win->event.inFocus);
   1684 }
   1685 
   1686 b8 RGFW_wasPressed(RGFW_window* win, u8 key) {
   1687 	return RGFW_keyboard[key].prev && (win == NULL || win->event.inFocus);
   1688 }
   1689 
   1690 b8 RGFW_isHeld(RGFW_window* win, u8 key) {
   1691 	return (RGFW_isPressed(win, key) && RGFW_wasPressed(win, key));
   1692 }
   1693 
   1694 b8 RGFW_isClicked(RGFW_window* win, u8 key) {
   1695 	return (RGFW_wasPressed(win, key) && !RGFW_isPressed(win, key));
   1696 }
   1697 
   1698 b8 RGFW_isReleased(RGFW_window* win, u8 key) {
   1699 	return (!RGFW_isPressed(win, key) && RGFW_wasPressed(win, key));	
   1700 }
   1701 
   1702 #if defined(RGFW_WINDOWS)  && defined(RGFW_DIRECTX) /* defines for directX context*/
   1703 	RGFW_directXinfo RGFW_dxInfo;
   1704 	RGFW_directXinfo* RGFW_getDirectXInfo(void) { return &RGFW_dxInfo; }
   1705 #endif
   1706 
   1707 void RGFW_window_makeCurrent(RGFW_window* win) {
   1708 #if defined(RGFW_WINDOWS) && defined(RGFW_DIRECTX)
   1709 	if (win == NULL)
   1710 		RGFW_dxInfo.pDeviceContext->lpVtbl->OMSetRenderTargets(RGFW_dxInfo.pDeviceContext, 1, NULL, NULL);
   1711 	else
   1712 		RGFW_dxInfo.pDeviceContext->lpVtbl->OMSetRenderTargets(RGFW_dxInfo.pDeviceContext, 1, &win->src.renderTargetView, NULL);
   1713 #elif defined(RGFW_OPENGL)
   1714 	RGFW_window_makeCurrent_OpenGL(win);
   1715 #else
   1716 	RGFW_UNUSED(win)
   1717 #endif
   1718 }
   1719 
   1720 void RGFW_window_setGPURender(RGFW_window* win, i8 set) {
   1721 	if (!set && !(win->_winArgs & RGFW_NO_GPU_RENDER))
   1722 		win->_winArgs |= RGFW_NO_GPU_RENDER;
   1723 		
   1724 	else if (set && win->_winArgs & RGFW_NO_GPU_RENDER)
   1725 		win->_winArgs ^= RGFW_NO_GPU_RENDER;
   1726 }
   1727 
   1728 void RGFW_window_setCPURender(RGFW_window* win, i8 set) {
   1729 	if (!set && !(win->_winArgs & RGFW_NO_CPU_RENDER))
   1730 		win->_winArgs |= RGFW_NO_CPU_RENDER;
   1731 
   1732 	else if (set && win->_winArgs & RGFW_NO_CPU_RENDER)
   1733 		win->_winArgs ^= RGFW_NO_CPU_RENDER;
   1734 }
   1735 
   1736 void RGFW_window_maximize(RGFW_window* win) {
   1737 	assert(win != NULL);
   1738 
   1739 	RGFW_area screen = RGFW_getScreenSize();
   1740 
   1741 	RGFW_window_move(win, RGFW_POINT(0, 0));
   1742 	RGFW_window_resize(win, screen);
   1743 }
   1744 
   1745 b8 RGFW_window_shouldClose(RGFW_window* win) {
   1746 	assert(win != NULL);
   1747 	return (win->event.type == RGFW_quit || RGFW_isPressed(win, RGFW_Escape));
   1748 }
   1749 
   1750 void RGFW_window_setShouldClose(RGFW_window* win) { win->event.type = RGFW_quit; RGFW_windowQuitCallback(win); }
   1751 
   1752 #ifndef RGFW_NO_MONITOR
   1753 	void RGFW_window_moveToMonitor(RGFW_window* win, RGFW_monitor m) {
   1754 		RGFW_window_move(win, RGFW_POINT(m.rect.x + win->r.x, m.rect.y + win->r.y));
   1755 	}
   1756 #endif
   1757 
   1758 RGFWDEF void RGFW_captureCursor(RGFW_window* win, RGFW_rect);
   1759 RGFWDEF void RGFW_releaseCursor(RGFW_window* win);
   1760 
   1761 void RGFW_window_mouseHold(RGFW_window* win, RGFW_area area) {
   1762 	if ((win->_winArgs & RGFW_HOLD_MOUSE))
   1763 		return;
   1764 	
   1765 
   1766 	if (!area.w && !area.h)
   1767 		area = RGFW_AREA(win->r.w / 2, win->r.h / 2);
   1768 		
   1769 	win->_winArgs |= RGFW_HOLD_MOUSE;
   1770 	RGFW_captureCursor(win, win->r);
   1771 	RGFW_window_moveMouse(win, RGFW_POINT(win->r.x + (win->r.w / 2), win->r.y + (win->r.h / 2)));
   1772 }
   1773 
   1774 void RGFW_window_mouseUnhold(RGFW_window* win) {
   1775 	if ((win->_winArgs & RGFW_HOLD_MOUSE)) {
   1776 		win->_winArgs ^= RGFW_HOLD_MOUSE;
   1777 
   1778 		RGFW_releaseCursor(win);
   1779 	}
   1780 }
   1781 
   1782 u32 RGFW_window_checkFPS(RGFW_window* win, u32 fpsCap) {
   1783 	u64 deltaTime = RGFW_getTimeNS() - win->event.frameTime;
   1784 
   1785 	u32 output_fps = 0;
   1786 	u64 fps = round(1e+9 / deltaTime);
   1787 	output_fps= fps;
   1788 
   1789 	if (fpsCap && fps > fpsCap) {
   1790 		u64 frameTimeNS = 1e+9 / fpsCap;
   1791 		u64 sleepTimeMS = (frameTimeNS - deltaTime) / 1e6;
   1792 
   1793 		if (sleepTimeMS > 0) {
   1794 			RGFW_sleep(sleepTimeMS);
   1795 			win->event.frameTime = 0;
   1796 		}
   1797 	}
   1798 
   1799 	win->event.frameTime = RGFW_getTimeNS();
   1800 	
   1801 	if (fpsCap == 0) 
   1802 		return (u32) output_fps;
   1803 	
   1804 	deltaTime = RGFW_getTimeNS() - win->event.frameTime2;
   1805 	output_fps = round(1e+9 / deltaTime);
   1806 	win->event.frameTime2 = RGFW_getTimeNS();
   1807 
   1808 	return output_fps;
   1809 }
   1810 
   1811 u32 RGFW_isPressedJS(RGFW_window* win, u16 c, u8 button) { 
   1812 	RGFW_UNUSED(win);
   1813 	return RGFW_jsPressed[c][button]; 
   1814 }
   1815 
   1816 #if defined(RGFW_X11) || defined(RGFW_WINDOWS)
   1817 	void RGFW_window_showMouse(RGFW_window* win, i8 show) {
   1818 		static u8 RGFW_blk[] = { 0, 0, 0, 0 };
   1819 		if (show == 0)
   1820 			RGFW_window_setMouse(win, RGFW_blk, RGFW_AREA(1, 1), 4);
   1821 		else
   1822 			RGFW_window_setMouseDefault(win);
   1823 	}
   1824 #endif
   1825 
   1826 RGFWDEF void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock);	
   1827 void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) {
   1828 	if (capital && !(win->event.lockState & RGFW_CAPSLOCK))
   1829 		win->event.lockState |= RGFW_CAPSLOCK;
   1830 	else if (!capital && (win->event.lockState & RGFW_CAPSLOCK))			
   1831 		win->event.lockState ^= RGFW_CAPSLOCK;
   1832 	
   1833 	if (numlock && !(win->event.lockState & RGFW_NUMLOCK))
   1834 		win->event.lockState |= RGFW_NUMLOCK;
   1835 	else if (!numlock && (win->event.lockState & RGFW_NUMLOCK))
   1836 		win->event.lockState ^= RGFW_NUMLOCK;
   1837 }
   1838 
   1839 #if defined(RGFW_X11) || defined(RGFW_MACOS) || defined(RGFW_WEBASM) || defined(RGFW_WAYLAND)
   1840 	struct timespec;
   1841 
   1842 	int nanosleep(const struct timespec* duration, struct timespec* rem);
   1843 	int clock_gettime(clockid_t clk_id, struct timespec* tp);
   1844 	int setenv(const char *name, const char *value, int overwrite);
   1845 
   1846 	void RGFW_window_setDND(RGFW_window* win, b8 allow) {
   1847 		if (allow && !(win->_winArgs & RGFW_ALLOW_DND))
   1848 			win->_winArgs |= RGFW_ALLOW_DND;
   1849 
   1850 		else if (!allow && (win->_winArgs & RGFW_ALLOW_DND))
   1851 			win->_winArgs ^= RGFW_ALLOW_DND;
   1852 	}
   1853 #endif
   1854 
   1855 /*
   1856 	graphics API specific code (end of generic code)
   1857 	starts here 
   1858 */
   1859 
   1860 
   1861 /* 
   1862 	OpenGL defines start here   (Normal, EGL, OSMesa)
   1863 */
   1864 
   1865 #if defined(RGFW_OPENGL) || defined(RGFW_EGL) || defined(RGFW_OSMESA)
   1866 	#ifdef RGFW_WINDOWS
   1867 		#define WIN32_LEAN_AND_MEAN
   1868 		#define OEMRESOURCE
   1869 		#include <windows.h>
   1870 	#endif
   1871 
   1872 	#if !defined(__APPLE__) && !defined(RGFW_NO_GL_HEADER)
   1873 		#include <GL/gl.h>
   1874 	#elif defined(__APPLE__)
   1875 		#ifndef GL_SILENCE_DEPRECATION
   1876 			#define GL_SILENCE_DEPRECATION
   1877 		#endif
   1878 		#include <OpenGL/gl.h>
   1879 		#include <OpenGL/OpenGL.h>
   1880 	#endif
   1881 
   1882 /* EGL, normal OpenGL only */
   1883 #if !defined(RGFW_OSMESA) 
   1884 	i32 RGFW_majorVersion = 0, RGFW_minorVersion = 0;
   1885 	b8 RGFW_profile = RGFW_GL_CORE;
   1886 	
   1887 	#ifndef RGFW_EGL
   1888 	i32 RGFW_STENCIL = 8, RGFW_SAMPLES = 4, RGFW_STEREO = 0, RGFW_AUX_BUFFERS = 0, RGFW_DOUBLE_BUFFER = 1;
   1889 	#else
   1890 	i32 RGFW_STENCIL = 0, RGFW_SAMPLES = 0, RGFW_STEREO = 0, RGFW_AUX_BUFFERS = 0, RGFW_DOUBLE_BUFFER = 1;
   1891 	#endif
   1892 
   1893 
   1894 	void RGFW_setGLStencil(i32 stencil) { RGFW_STENCIL = stencil; }
   1895 	void RGFW_setGLSamples(i32 samples) { RGFW_SAMPLES = samples; }
   1896 	void RGFW_setGLStereo(i32 stereo) { RGFW_STEREO = stereo; }
   1897 	void RGFW_setGLAuxBuffers(i32 auxBuffers) { RGFW_AUX_BUFFERS = auxBuffers; }
   1898 	void RGFW_setDoubleBuffer(b8 useDoubleBuffer) { RGFW_DOUBLE_BUFFER = useDoubleBuffer; }
   1899 
   1900 	void RGFW_setGLVersion(b8 profile, i32 major, i32 minor) {
   1901         RGFW_profile = profile;
   1902 		RGFW_majorVersion = major;
   1903 		RGFW_minorVersion = minor;
   1904 	}
   1905 
   1906 /* OPENGL normal only (no EGL / OSMesa) */
   1907 #ifndef RGFW_EGL
   1908 
   1909 #define RGFW_GL_RENDER_TYPE 		RGFW_OS_BASED_VALUE(GLX_X_VISUAL_TYPE,    	0x2003,		73, 0, 0)
   1910 	#define RGFW_GL_ALPHA_SIZE 		RGFW_OS_BASED_VALUE(GLX_ALPHA_SIZE,       	0x201b,		11,     0, 0)
   1911 	#define RGFW_GL_DEPTH_SIZE 		RGFW_OS_BASED_VALUE(GLX_DEPTH_SIZE,       	0x2022,		12,     0, 0)
   1912 	#define RGFW_GL_DOUBLEBUFFER 		RGFW_OS_BASED_VALUE(GLX_DOUBLEBUFFER,     	0x2011, 	5,  0, 0)   
   1913 	#define RGFW_GL_STENCIL_SIZE 		RGFW_OS_BASED_VALUE(GLX_STENCIL_SIZE,	 	0x2023,	13,     0, 0)
   1914 	#define RGFW_GL_SAMPLES			RGFW_OS_BASED_VALUE(GLX_SAMPLES, 		 	0x2042,	    55,     0, 0)
   1915 	#define RGFW_GL_STEREO 			RGFW_OS_BASED_VALUE(GLX_STEREO,	 		 	0x2012,			6,  0, 0)
   1916 	#define RGFW_GL_AUX_BUFFERS		RGFW_OS_BASED_VALUE(GLX_AUX_BUFFERS,	    0x2024,	7, 		    0, 0)
   1917 
   1918 #if defined(RGFW_X11) || defined(RGFW_WINDOWS)
   1919 	#define RGFW_GL_DRAW 			RGFW_OS_BASED_VALUE(GLX_X_RENDERABLE,	 	0x2001,					0, 0, 0)
   1920 	#define RGFW_GL_DRAW_TYPE 		RGFW_OS_BASED_VALUE(GLX_RENDER_TYPE,     	0x2013,						0, 0, 0)
   1921 	#define RGFW_GL_FULL_FORMAT		RGFW_OS_BASED_VALUE(GLX_TRUE_COLOR,   	 	0x2027,						0, 0, 0)
   1922 	#define RGFW_GL_RED_SIZE		RGFW_OS_BASED_VALUE(GLX_RED_SIZE,         	0x2015,						0, 0, 0)
   1923 	#define RGFW_GL_GREEN_SIZE		RGFW_OS_BASED_VALUE(GLX_GREEN_SIZE,       	0x2017,						0, 0, 0)
   1924 	#define RGFW_GL_BLUE_SIZE		RGFW_OS_BASED_VALUE(GLX_BLUE_SIZE, 	 		0x2019,						0, 0, 0)
   1925 	#define RGFW_GL_USE_RGBA		RGFW_OS_BASED_VALUE(GLX_RGBA_BIT,   	 	0x202B,						0, 0, 0)
   1926 #endif
   1927 
   1928 #ifdef RGFW_WINDOWS
   1929 	#define WGL_SUPPORT_OPENGL_ARB                    0x2010
   1930 	#define WGL_COLOR_BITS_ARB                        0x2014
   1931 	#define WGL_NUMBER_PIXEL_FORMATS_ARB 			0x2000
   1932 	#define WGL_CONTEXT_MAJOR_VERSION_ARB             0x2091
   1933 	#define WGL_CONTEXT_MINOR_VERSION_ARB             0x2092
   1934 	#define WGL_CONTEXT_PROFILE_MASK_ARB              0x9126
   1935 	#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
   1936 	#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
   1937 	#define WGL_SAMPLE_BUFFERS_ARB               0x2041
   1938 	#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20a9
   1939 	#define WGL_PIXEL_TYPE_ARB                        0x2013
   1940 	#define WGL_TYPE_RGBA_ARB                         0x202B
   1941 
   1942 	#define WGL_TRANSPARENT_ARB   					  0x200A
   1943 #endif
   1944 	
   1945 /*  The window'ing api needs to know how to render the data we (or opengl) give it 
   1946 	MacOS and Windows do this using a structure called a "pixel format" 
   1947 	X11 calls it a "Visual"
   1948 	This function returns the attributes for the format we want */
   1949 	static u32* RGFW_initFormatAttribs(u32 useSoftware) {
   1950 		RGFW_UNUSED(useSoftware);
   1951 		static u32 attribs[] = {
   1952 								#if defined(RGFW_X11) || defined(RGFW_WINDOWS)
   1953 								RGFW_GL_RENDER_TYPE,
   1954 								RGFW_GL_FULL_FORMAT,
   1955 								#endif
   1956 								RGFW_GL_ALPHA_SIZE      , 8,
   1957 								RGFW_GL_DEPTH_SIZE      , 24,
   1958 								#if defined(RGFW_X11) || defined(RGFW_WINDOWS)
   1959 								RGFW_GL_DRAW, 1,
   1960 								RGFW_GL_RED_SIZE        , 8,
   1961 								RGFW_GL_GREEN_SIZE      , 8,
   1962 								RGFW_GL_BLUE_SIZE       , 8,
   1963 								RGFW_GL_DRAW_TYPE     , RGFW_GL_USE_RGBA,
   1964 								#endif 
   1965 
   1966 								#ifdef RGFW_X11
   1967 								GLX_DRAWABLE_TYPE   , GLX_WINDOW_BIT,
   1968 								#endif	
   1969 
   1970 								#ifdef RGFW_MACOS
   1971 								72,
   1972 								8, 24,
   1973 								#endif
   1974 
   1975 								#ifdef RGFW_WINDOWS
   1976 								WGL_SUPPORT_OPENGL_ARB,		1,
   1977 								WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
   1978 								WGL_COLOR_BITS_ARB,	 32,
   1979 								#endif
   1980 
   1981 								0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
   1982 		};
   1983 
   1984 		size_t index = (sizeof(attribs) / sizeof(attribs[0])) - 13;
   1985 
   1986 	#define RGFW_GL_ADD_ATTRIB(attrib, attVal) \
   1987 		if (attVal) { \
   1988 			attribs[index] = attrib;\
   1989 			attribs[index + 1] = attVal;\
   1990 			index += 2;\
   1991 		}
   1992          
   1993         RGFW_GL_ADD_ATTRIB(RGFW_GL_DOUBLEBUFFER, 1);
   1994         
   1995         RGFW_GL_ADD_ATTRIB(RGFW_GL_STENCIL_SIZE, RGFW_STENCIL);
   1996 		RGFW_GL_ADD_ATTRIB(RGFW_GL_STEREO, RGFW_STEREO);
   1997 		RGFW_GL_ADD_ATTRIB(RGFW_GL_AUX_BUFFERS, RGFW_AUX_BUFFERS);
   1998 
   1999 #ifndef RGFW_X11
   2000 		RGFW_GL_ADD_ATTRIB(RGFW_GL_SAMPLES, RGFW_SAMPLES);
   2001 #endif 
   2002 
   2003 #ifdef RGFW_MACOS
   2004 		if (useSoftware) {
   2005 			RGFW_GL_ADD_ATTRIB(70, kCGLRendererGenericFloatID);
   2006 		} else {
   2007 			attribs[index] = RGFW_GL_RENDER_TYPE;
   2008 			index += 1;
   2009 		}
   2010 #endif
   2011 
   2012 #ifdef RGFW_MACOS
   2013 		/* macOS has the surface attribs and the opengl attribs connected for some reason
   2014 			maybe this is to give macOS more control to limit openGL/the opengl version? */
   2015 
   2016 		attribs[index] = 99;
   2017 		attribs[index + 1] = 0x1000;
   2018 
   2019 		if (RGFW_majorVersion >= 4 || RGFW_majorVersion >= 3) {
   2020 			attribs[index + 1] = (u32) ((RGFW_majorVersion >= 4) ? 0x4100 : 0x3200);
   2021 		}
   2022 #endif
   2023 
   2024 		RGFW_GL_ADD_ATTRIB(0, 0);
   2025 
   2026 		return attribs;
   2027 	}
   2028 
   2029 /* EGL only (no OSMesa nor normal OPENGL) */
   2030 #elif defined(RGFW_EGL)
   2031 
   2032 #include <EGL/egl.h>
   2033 
   2034 #if defined(RGFW_LINK_EGL)
   2035 	typedef EGLBoolean(EGLAPIENTRY* PFN_eglInitialize)(EGLDisplay, EGLint*, EGLint*);
   2036 
   2037 	PFNEGLINITIALIZEPROC eglInitializeSource;
   2038 	PFNEGLGETCONFIGSPROC eglGetConfigsSource;
   2039 	PFNEGLCHOOSECONFIGPROC eglChooseConfigSource;
   2040 	PFNEGLCREATEWINDOWSURFACEPROC eglCreateWindowSurfaceSource;
   2041 	PFNEGLCREATECONTEXTPROC eglCreateContextSource;
   2042 	PFNEGLMAKECURRENTPROC eglMakeCurrentSource;
   2043 	PFNEGLGETDISPLAYPROC eglGetDisplaySource;
   2044 	PFNEGLSWAPBUFFERSPROC eglSwapBuffersSource;
   2045 	PFNEGLSWAPINTERVALPROC eglSwapIntervalSource;
   2046 	PFNEGLBINDAPIPROC eglBindAPISource;
   2047 	PFNEGLDESTROYCONTEXTPROC eglDestroyContextSource;
   2048 	PFNEGLTERMINATEPROC eglTerminateSource;
   2049 	PFNEGLDESTROYSURFACEPROC eglDestroySurfaceSource;
   2050 
   2051 #define eglInitialize eglInitializeSource
   2052 #define eglGetConfigs eglGetConfigsSource
   2053 #define eglChooseConfig eglChooseConfigSource
   2054 #define eglCreateWindowSurface eglCreateWindowSurfaceSource
   2055 #define eglCreateContext eglCreateContextSource
   2056 #define eglMakeCurrent eglMakeCurrentSource
   2057 #define eglGetDisplay eglGetDisplaySource
   2058 #define eglSwapBuffers eglSwapBuffersSource
   2059 #define eglSwapInterval eglSwapIntervalSource
   2060 #define eglBindAPI eglBindAPISource
   2061 #define eglDestroyContext eglDestroyContextSource
   2062 #define eglTerminate eglTerminateSource
   2063 #define eglDestroySurface eglDestroySurfaceSource;
   2064 #endif
   2065 
   2066 
   2067 #define EGL_SURFACE_MAJOR_VERSION_KHR 0x3098
   2068 #define EGL_SURFACE_MINOR_VERSION_KHR 0x30fb
   2069 
   2070 #ifndef RGFW_GL_ADD_ATTRIB
   2071 #define RGFW_GL_ADD_ATTRIB(attrib, attVal) \
   2072 	if (attVal) { \
   2073 		attribs[index] = attrib;\
   2074 		attribs[index + 1] = attVal;\
   2075 		index += 2;\
   2076 	}
   2077 #endif
   2078 
   2079 
   2080 	void RGFW_createOpenGLContext(RGFW_window* win) {
   2081 #if defined(RGFW_LINK_EGL)
   2082 		eglInitializeSource = (PFNEGLINITIALIZEPROC) eglGetProcAddress("eglInitialize");
   2083 		eglGetConfigsSource = (PFNEGLGETCONFIGSPROC) eglGetProcAddress("eglGetConfigs");
   2084 		eglChooseConfigSource = (PFNEGLCHOOSECONFIGPROC) eglGetProcAddress("eglChooseConfig");
   2085 		eglCreateWindowSurfaceSource = (PFNEGLCREATEWINDOWSURFACEPROC) eglGetProcAddress("eglCreateWindowSurface");
   2086 		eglCreateContextSource = (PFNEGLCREATECONTEXTPROC) eglGetProcAddress("eglCreateContext");
   2087 		eglMakeCurrentSource = (PFNEGLMAKECURRENTPROC) eglGetProcAddress("eglMakeCurrent");
   2088 		eglGetDisplaySource = (PFNEGLGETDISPLAYPROC) eglGetProcAddress("eglGetDisplay");
   2089 		eglSwapBuffersSource = (PFNEGLSWAPBUFFERSPROC) eglGetProcAddress("eglSwapBuffers");
   2090 		eglSwapIntervalSource = (PFNEGLSWAPINTERVALPROC) eglGetProcAddress("eglSwapInterval");
   2091 		eglBindAPISource = (PFNEGLBINDAPIPROC) eglGetProcAddress("eglBindAPI");
   2092 		eglDestroyContextSource = (PFNEGLDESTROYCONTEXTPROC) eglGetProcAddress("eglDestroyContext");
   2093 		eglTerminateSource = (PFNEGLTERMINATEPROC) eglGetProcAddress("eglTerminate");
   2094 		eglDestroySurfaceSource = (PFNEGLDESTROYSURFACEPROC) eglGetProcAddress("eglDestroySurface");
   2095 #endif /* RGFW_LINK_EGL */
   2096 
   2097 		#ifdef RGFW_WINDOWS
   2098 		win->src.EGL_display = eglGetDisplay((EGLNativeDisplayType) win->src.hdc);
   2099 		#elif defined(RGFW_MACOS)
   2100 		win->src.EGL_display = eglGetDisplay((EGLNativeDisplayType)0);
   2101 		#else
   2102 		win->src.EGL_display = eglGetDisplay((EGLNativeDisplayType) win->src.display);
   2103 		#endif
   2104 
   2105 		EGLint major, minor;
   2106 
   2107 		eglInitialize(win->src.EGL_display, &major, &minor);
   2108 
   2109 		#ifndef EGL_OPENGL_ES1_BIT
   2110 		#define EGL_OPENGL_ES1_BIT 0x1
   2111 		#endif
   2112 
   2113 		EGLint egl_config[] = {
   2114 			EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
   2115 			EGL_RENDERABLE_TYPE,
   2116 			#ifdef RGFW_OPENGL_ES1
   2117 			EGL_OPENGL_ES1_BIT,
   2118 			#elif defined(RGFW_OPENGL_ES3)
   2119 			EGL_OPENGL_ES3_BIT,
   2120 			#elif defined(RGFW_OPENGL_ES2)
   2121 			EGL_OPENGL_ES2_BIT,
   2122 			#else
   2123 			EGL_OPENGL_BIT,
   2124 			#endif
   2125 			EGL_NONE, EGL_NONE
   2126 		};
   2127 
   2128 		EGLConfig config;
   2129 		EGLint numConfigs;
   2130 		eglChooseConfig(win->src.EGL_display, egl_config, &config, 1, &numConfigs);
   2131 
   2132 		#if defined(RGFW_MACOS)
   2133 		    void* layer = RGFW_cocoaGetLayer(); 
   2134 		
   2135 			RGFW_window_cocoaSetLayer(win, layer);
   2136 			
   2137 			win->src.EGL_surface = eglCreateWindowSurface(win->src.EGL_display, config, (EGLNativeWindowType) layer, NULL);
   2138 		#else
   2139 			win->src.EGL_surface = eglCreateWindowSurface(win->src.EGL_display, config, (EGLNativeWindowType) win->src.window, NULL);
   2140 		#endif
   2141 
   2142 		EGLint attribs[] = {
   2143 			EGL_CONTEXT_CLIENT_VERSION,
   2144 			#ifdef RGFW_OPENGL_ES1
   2145 			1,
   2146 			#else
   2147 			2,
   2148 			#endif
   2149 			EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE
   2150 		};
   2151 
   2152 		size_t index = 4;
   2153 		RGFW_GL_ADD_ATTRIB(EGL_STENCIL_SIZE, RGFW_STENCIL);
   2154 		RGFW_GL_ADD_ATTRIB(EGL_SAMPLES, RGFW_SAMPLES);
   2155 
   2156         if (RGFW_DOUBLE_BUFFER)
   2157             RGFW_GL_ADD_ATTRIB(EGL_RENDER_BUFFER, EGL_BACK_BUFFER);
   2158 
   2159 		if (RGFW_majorVersion) {
   2160 			attribs[1] = RGFW_majorVersion;
   2161 	
   2162 			RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_MAJOR_VERSION, RGFW_majorVersion);
   2163 			RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_MINOR_VERSION, RGFW_minorVersion);
   2164 
   2165 			if (RGFW_profile == RGFW_GL_CORE) {
   2166 				RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT);
   2167 			}
   2168 			else {
   2169 				RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT);
   2170 			}
   2171 
   2172 		}
   2173 
   2174 		#if defined(RGFW_OPENGL_ES1) || defined(RGFW_OPENGL_ES2) || defined(RGFW_OPENGL_ES3)
   2175 		eglBindAPI(EGL_OPENGL_ES_API);
   2176 		#else
   2177 		eglBindAPI(EGL_OPENGL_API);		
   2178 		#endif
   2179       		
   2180 		win->src.EGL_context = eglCreateContext(win->src.EGL_display, config, EGL_NO_CONTEXT, attribs);
   2181 		
   2182 		if (win->src.EGL_context == NULL)
   2183 			fprintf(stderr, "failed to create an EGL opengl context\n");
   2184 
   2185 		eglMakeCurrent(win->src.EGL_display, win->src.EGL_surface, win->src.EGL_surface, win->src.EGL_context);
   2186 		eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface);
   2187 	}
   2188 
   2189 	void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) {
   2190 		eglMakeCurrent(win->src.EGL_display, win->src.EGL_surface, win->src.EGL_surface, win->src.EGL_context);
   2191 	}
   2192 
   2193 	#ifdef RGFW_APPLE
   2194 	void* RGFWnsglFramework = NULL;
   2195 	#elif defined(RGFW_WINDOWS)
   2196 	static HMODULE wglinstance = NULL;
   2197 	#endif
   2198 
   2199 	void* RGFW_getProcAddress(const char* procname) { 
   2200 		#if defined(RGFW_WINDOWS)
   2201 			void* proc = (void*) GetProcAddress(wglinstance, procname); 
   2202 
   2203 			if (proc)
   2204 				return proc;
   2205 		#endif
   2206 
   2207 		return (void*) eglGetProcAddress(procname); 
   2208 	}
   2209 
   2210 	void RGFW_closeEGL(RGFW_window* win) {
   2211 		eglDestroySurface(win->src.EGL_display, win->src.EGL_surface);
   2212 		eglDestroyContext(win->src.EGL_display, win->src.EGL_context);
   2213 
   2214 		eglTerminate(win->src.EGL_display);
   2215 	}
   2216 	
   2217 	void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) {
   2218 		assert(win != NULL);
   2219 		
   2220 		eglSwapInterval(win->src.EGL_display, swapInterval);
   2221 
   2222 	}
   2223 #endif /* RGFW_EGL */
   2224 
   2225 /* 
   2226 	end of RGFW_EGL defines
   2227 */
   2228 
   2229 /* OPENGL Normal / EGL defines only (no OS MESA)  Ends here */
   2230 
   2231 #elif defined(RGFW_OSMESA) /* OSmesa only */
   2232 RGFWDEF void RGFW_OSMesa_reorganize(void);
   2233 
   2234 /* reorganize buffer for osmesa */
   2235 void RGFW_OSMesa_reorganize(void) {
   2236 	u8* row = (u8*) RGFW_MALLOC(win->r.w * 3);
   2237 
   2238 	i32 half_height = win->r.h / 2;
   2239 	i32 stride = win->r.w * 3;
   2240 
   2241 	i32 y;
   2242 	for (y = 0; y < half_height; ++y) {
   2243 		i32 top_offset = y * stride;
   2244 		i32 bottom_offset = (win->r.h - y - 1) * stride;
   2245 		memcpy(row, win->buffer + top_offset, stride);
   2246 		memcpy(win->buffer + top_offset, win->buffer + bottom_offset, stride);
   2247 		memcpy(win->buffer + bottom_offset, row, stride);
   2248 	}
   2249 
   2250 	RGFW_FREE(row);
   2251 }
   2252 #endif /* RGFW_OSMesa */
   2253 
   2254 #endif /* RGFW_GL (OpenGL, EGL, OSMesa )*/
   2255 
   2256 /*
   2257 This is where OS specific stuff starts
   2258 */
   2259 
   2260 
   2261 #if defined(RGFW_WAYLAND) || defined(RGFW_X11)
   2262 	int RGFW_eventWait_forceStop[] = {0, 0, 0}; /* for wait events */
   2263 
   2264 	#ifdef __linux__
   2265 		#include <linux/joystick.h>
   2266 		#include <fcntl.h>
   2267 		#include <unistd.h>
   2268 		
   2269 		RGFW_Event* RGFW_linux_updateJoystick(RGFW_window* win) {
   2270 			static int xAxis = 0, yAxis = 0;
   2271 			u8 i;
   2272 			for (i = 0; i < RGFW_joystickCount; i++) {
   2273 				struct js_event e;
   2274 
   2275 
   2276 				if (RGFW_joysticks[i] == 0)
   2277 					continue;
   2278 
   2279 				i32 flags = fcntl(RGFW_joysticks[i], F_GETFL, 0);
   2280 				fcntl(RGFW_joysticks[i], F_SETFL, flags | O_NONBLOCK);
   2281 
   2282 				ssize_t bytes;
   2283 				while ((bytes = read(RGFW_joysticks[i], &e, sizeof(e))) > 0) {
   2284 					switch (e.type) {
   2285 					case JS_EVENT_BUTTON:
   2286 						win->event.type = e.value ? RGFW_jsButtonPressed : RGFW_jsButtonReleased;
   2287 						win->event.button = e.number;
   2288 						RGFW_jsPressed[i][e.number] = e.value;
   2289 						RGFW_jsButtonCallback(win, i, e.number, e.value);
   2290 						return &win->event;
   2291 					case JS_EVENT_AXIS:
   2292 						ioctl(RGFW_joysticks[i], JSIOCGAXES, &win->event.axisesCount);
   2293 
   2294 						if ((e.number == 0 || e.number % 2) && e.number != 1)
   2295 							xAxis = e.value;
   2296 						else
   2297 							yAxis = e.value;
   2298 
   2299 						win->event.axis[e.number / 2].x = xAxis;
   2300 						win->event.axis[e.number / 2].y = yAxis;
   2301 						win->event.type = RGFW_jsAxisMove;
   2302 						win->event.joystick = i;
   2303 						RGFW_jsAxisCallback(win, i, win->event.axis, win->event.axisesCount);
   2304 						return &win->event;
   2305 
   2306 						default: break;
   2307 					}
   2308 				}
   2309 			}
   2310 
   2311 			return NULL;
   2312 		}
   2313 
   2314 	#endif
   2315 #endif
   2316 
   2317 /*
   2318 
   2319 
   2320 Start of Linux / Unix defines
   2321 
   2322 
   2323 */
   2324 
   2325 #ifdef RGFW_X11
   2326 #ifndef RGFW_NO_X11_CURSOR
   2327 #include <X11/Xcursor/Xcursor.h>
   2328 #endif
   2329 #include <dlfcn.h>
   2330 
   2331 #ifndef RGFW_NO_DPI
   2332 #include <X11/extensions/Xrandr.h>
   2333 #include <X11/Xresource.h>
   2334 #endif
   2335 
   2336 #include <X11/Xutil.h>
   2337 #include <X11/Xatom.h>
   2338 #include <X11/keysymdef.h>
   2339 #include <unistd.h>
   2340 
   2341 #include <X11/XKBlib.h> /* for converting keycode to string */
   2342 #include <X11/cursorfont.h> /* for hiding */
   2343 #include <X11/extensions/shapeconst.h>
   2344 #include <X11/extensions/shape.h>
   2345 #include <X11/extensions/XInput2.h>
   2346 
   2347 #include <limits.h> /* for data limits (mainly used in drag and drop functions) */
   2348 #include <poll.h>
   2349 
   2350 
   2351 #ifdef __linux__
   2352 #include <linux/joystick.h>
   2353 #endif
   2354 
   2355 	u8 RGFW_mouseIconSrc[] = { XC_arrow, XC_left_ptr, XC_xterm, XC_crosshair, XC_hand2, XC_sb_h_double_arrow, XC_sb_v_double_arrow, XC_bottom_left_corner, XC_bottom_right_corner, XC_fleur, XC_X_cursor};  
   2356 	/*atoms needed for drag and drop*/
   2357 	Atom XdndAware, XdndTypeList, XdndSelection, XdndEnter, XdndPosition, XdndStatus, XdndLeave, XdndDrop, XdndFinished, XdndActionCopy, XtextPlain, XtextUriList;
   2358 
   2359 	Atom wm_delete_window = 0;
   2360 
   2361 #if !defined(RGFW_NO_X11_CURSOR) && !defined(RGFW_NO_X11_CURSOR_PRELOAD)
   2362 	typedef XcursorImage* (*PFN_XcursorImageCreate)(int, int);
   2363 	typedef void (*PFN_XcursorImageDestroy)(XcursorImage*);
   2364 	typedef Cursor(*PFN_XcursorImageLoadCursor)(Display*, const XcursorImage*);
   2365 #endif
   2366 #ifdef RGFW_OPENGL
   2367 	typedef GLXContext(*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*);
   2368 #endif
   2369 
   2370 #if !defined(RGFW_NO_X11_XI_PRELOAD)
   2371 	typedef int (* PFN_XISelectEvents)(Display*,Window,XIEventMask*,int);
   2372 	PFN_XISelectEvents XISelectEventsSrc = NULL;
   2373 	#define XISelectEvents XISelectEventsSrc
   2374 
   2375 	void* X11Xihandle = NULL;
   2376 #endif
   2377 
   2378 #if !defined(RGFW_NO_X11_CURSOR) && !defined(RGFW_NO_X11_CURSOR_PRELOAD)
   2379 	PFN_XcursorImageLoadCursor XcursorImageLoadCursorSrc = NULL;
   2380 	PFN_XcursorImageCreate XcursorImageCreateSrc = NULL;
   2381 	PFN_XcursorImageDestroy XcursorImageDestroySrc = NULL;
   2382 
   2383 #define XcursorImageLoadCursor XcursorImageLoadCursorSrc
   2384 #define XcursorImageCreate XcursorImageCreateSrc
   2385 #define XcursorImageDestroy XcursorImageDestroySrc
   2386 
   2387 	void* X11Cursorhandle = NULL;
   2388 #endif
   2389 
   2390 	u32 RGFW_windowsOpen = 0;
   2391 
   2392 #ifdef RGFW_OPENGL
   2393 	void* RGFW_getProcAddress(const char* procname) { return (void*) glXGetProcAddress((GLubyte*) procname); }
   2394 #endif
   2395 
   2396 	RGFWDEF void RGFW_init_buffer(RGFW_window* win, XVisualInfo* vi);
   2397 	void RGFW_init_buffer(RGFW_window* win, XVisualInfo* vi) {
   2398 #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)
   2399 		if (RGFW_bufferSize.w == 0 && RGFW_bufferSize.h == 0)
   2400 			RGFW_bufferSize = RGFW_getScreenSize();
   2401 		
   2402 		win->buffer = (u8*)RGFW_MALLOC(RGFW_bufferSize.w * RGFW_bufferSize.h * 4);
   2403 
   2404 		#ifdef RGFW_OSMESA
   2405 				win->src.ctx = OSMesaCreateContext(OSMESA_RGBA, NULL);
   2406 				OSMesaMakeCurrent(win->src.ctx, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h);
   2407 		#endif
   2408 
   2409 		win->src.bitmap = XCreateImage(
   2410 			win->src.display, XDefaultVisual(win->src.display, vi->screen),
   2411 			vi->depth,
   2412 			ZPixmap, 0, NULL, RGFW_bufferSize.w, RGFW_bufferSize.h,
   2413 			32, 0
   2414 		);
   2415 
   2416 		win->src.gc = XCreateGC(win->src.display, win->src.window, 0, NULL);
   2417 
   2418 		#else
   2419 		RGFW_UNUSED(win); /*!< if buffer rendering is not being used */
   2420 		RGFW_UNUSED(vi)
   2421 		#endif
   2422 	}
   2423 
   2424 
   2425 
   2426 	void RGFW_window_setBorder(RGFW_window* win, u8 border) {
   2427 		static Atom _MOTIF_WM_HINTS = 0;
   2428 		if (_MOTIF_WM_HINTS == 0 )
   2429 			_MOTIF_WM_HINTS = XInternAtom(win->src.display, "_MOTIF_WM_HINTS", False);
   2430 		
   2431 		struct __x11WindowHints {
   2432 			unsigned long flags, functions, decorations, status;
   2433 			long input_mode;
   2434 		} hints;
   2435 		hints.flags = (1L << 1);
   2436 		hints.decorations = border;
   2437 
   2438 		XChangeProperty(
   2439 			win->src.display, win->src.window,
   2440 			_MOTIF_WM_HINTS, _MOTIF_WM_HINTS,
   2441 			32, PropModeReplace, (u8*)&hints, 5
   2442 		);
   2443 	}
   2444 	
   2445 	void RGFW_releaseCursor(RGFW_window* win) {
   2446 		XUngrabPointer(win->src.display, CurrentTime);
   2447 
   2448 		/* disable raw input */
   2449 		unsigned char mask[] = { 0 };
   2450 		XIEventMask em;
   2451 		em.deviceid = XIAllMasterDevices;
   2452 		em.mask_len = sizeof(mask);
   2453 		em.mask = mask;
   2454 
   2455 		XISelectEvents(win->src.display, XDefaultRootWindow(win->src.display), &em, 1);
   2456 	}
   2457 	
   2458 	void RGFW_captureCursor(RGFW_window* win, RGFW_rect r) { 
   2459 		/* enable raw input */
   2460 		unsigned char mask[XIMaskLen(XI_RawMotion)] = { 0 };
   2461 		XISetMask(mask, XI_RawMotion);
   2462 
   2463 		XIEventMask em;
   2464 		em.deviceid = XIAllMasterDevices;
   2465 		em.mask_len = sizeof(mask);
   2466 		em.mask = mask;
   2467 		
   2468 		XISelectEvents(win->src.display, XDefaultRootWindow(win->src.display), &em, 1);
   2469 
   2470 		XGrabPointer(win->src.display, win->src.window, True, PointerMotionMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
   2471 
   2472 		RGFW_window_moveMouse(win, RGFW_POINT(win->r.x + (i32)(r.w / 2), win->r.y + (i32)(r.h / 2)));
   2473 	}
   2474 
   2475 	RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) {
   2476 #if !defined(RGFW_NO_X11_CURSOR) && !defined(RGFW_NO_X11_CURSOR_PRELOAD)
   2477 		if (X11Cursorhandle == NULL) {
   2478 #if defined(__CYGWIN__)
   2479 			X11Cursorhandle = dlopen("libXcursor-1.so", RTLD_LAZY | RTLD_LOCAL);
   2480 #elif defined(__OpenBSD__) || defined(__NetBSD__)
   2481 			X11Cursorhandle = dlopen("libXcursor.so", RTLD_LAZY | RTLD_LOCAL);
   2482 #else
   2483 			X11Cursorhandle = dlopen("libXcursor.so.1", RTLD_LAZY | RTLD_LOCAL);
   2484 #endif
   2485 
   2486 			XcursorImageCreateSrc = (PFN_XcursorImageCreate) dlsym(X11Cursorhandle, "XcursorImageCreate");
   2487 			XcursorImageDestroySrc = (PFN_XcursorImageDestroy) dlsym(X11Cursorhandle, "XcursorImageDestroy");
   2488 			XcursorImageLoadCursorSrc = (PFN_XcursorImageLoadCursor) dlsym(X11Cursorhandle, "XcursorImageLoadCursor");
   2489 		}
   2490 #endif
   2491 
   2492 #if !defined(RGFW_NO_X11_XI_PRELOAD)
   2493 		if (X11Xihandle == NULL) {
   2494 #if defined(__CYGWIN__)
   2495 			X11Xihandle = dlopen("libXi-6.so", RTLD_LAZY | RTLD_LOCAL);
   2496 #elif defined(__OpenBSD__) || defined(__NetBSD__)
   2497 			X11Xihandle = dlopen("libXi.so", RTLD_LAZY | RTLD_LOCAL);
   2498 #else
   2499 			X11Xihandle = dlopen("libXi.so.6", RTLD_LAZY | RTLD_LOCAL);
   2500 #endif
   2501 
   2502 			XISelectEventsSrc = (PFN_XISelectEvents) dlsym(X11Xihandle, "XISelectEvents");
   2503 		}
   2504 #endif
   2505 
   2506 		XInitThreads(); /*!< init X11 threading*/
   2507 
   2508 		if (args & RGFW_OPENGL_SOFTWARE)
   2509 			setenv("LIBGL_ALWAYS_SOFTWARE", "1", 1);
   2510 
   2511 		RGFW_window* win = RGFW_window_basic_init(rect, args);
   2512 
   2513 		u64 event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask | FocusChangeMask | LeaveWindowMask | EnterWindowMask | ExposureMask; /*!< X11 events accepted*/
   2514 
   2515 #ifdef RGFW_OPENGL
   2516 		u32* visual_attribs = RGFW_initFormatAttribs(args & RGFW_OPENGL_SOFTWARE);
   2517 		i32 fbcount;
   2518 		GLXFBConfig* fbc = glXChooseFBConfig((Display*) win->src.display, DefaultScreen(win->src.display), (i32*) visual_attribs, &fbcount);
   2519 
   2520 		i32 best_fbc = -1;
   2521 
   2522 		if (fbcount == 0) {
   2523 			printf("Failed to find any valid GLX visual configs\n");
   2524 			return NULL;
   2525 		}
   2526 
   2527 		u32 i;
   2528 		for (i = 0; i < (u32)fbcount; i++) {
   2529 			XVisualInfo* vi = glXGetVisualFromFBConfig((Display*) win->src.display, fbc[i]);
   2530                         if (vi == NULL)
   2531 				continue;
   2532                         
   2533 			XFree(vi);
   2534 
   2535 			i32 samp_buf, samples;
   2536 			glXGetFBConfigAttrib((Display*) win->src.display, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf);
   2537 			glXGetFBConfigAttrib((Display*) win->src.display, fbc[i], GLX_SAMPLES, &samples);
   2538 			
   2539 			if ((!(args & RGFW_TRANSPARENT_WINDOW) || vi->depth == 32) && 
   2540 				(best_fbc < 0 || samp_buf) && (samples == RGFW_SAMPLES || best_fbc == -1)) {
   2541 				best_fbc = i;
   2542 			}
   2543 		}
   2544 
   2545 		if (best_fbc == -1) {
   2546 			printf("Failed to get a valid GLX visual\n");
   2547 			return NULL;
   2548 		}
   2549 
   2550 		GLXFBConfig bestFbc = fbc[best_fbc];
   2551 
   2552 		/* Get a visual */
   2553 		XVisualInfo* vi = glXGetVisualFromFBConfig((Display*) win->src.display, bestFbc);
   2554 		
   2555 		XFree(fbc);
   2556 #else
   2557 		XVisualInfo viNorm;
   2558 
   2559 		viNorm.visual = DefaultVisual((Display*) win->src.display, DefaultScreen((Display*) win->src.display));
   2560 		
   2561 		viNorm.depth = 0;
   2562 		XVisualInfo* vi = &viNorm;
   2563 		
   2564 		XMatchVisualInfo((Display*) win->src.display, DefaultScreen((Display*) win->src.display), 32, TrueColor, vi); /*!< for RGBA backgrounds*/
   2565 #endif
   2566 		/* make X window attrubutes*/
   2567 		XSetWindowAttributes swa;
   2568 		Colormap cmap;
   2569 
   2570 		swa.colormap = cmap = XCreateColormap((Display*) win->src.display,
   2571 			DefaultRootWindow(win->src.display),
   2572 			vi->visual, AllocNone);
   2573 
   2574 		swa.background_pixmap = None;
   2575 		swa.border_pixel = 0;
   2576 		swa.event_mask = event_mask;
   2577 		
   2578 		swa.background_pixel = 0;
   2579 
   2580 		/* create the window*/
   2581 		win->src.window = XCreateWindow((Display*) win->src.display, DefaultRootWindow((Display*) win->src.display), win->r.x, win->r.y, win->r.w, win->r.h,
   2582 			0, vi->depth, InputOutput, vi->visual,
   2583 			CWColormap | CWBorderPixel | CWBackPixel | CWEventMask, &swa);
   2584 
   2585 		XFreeColors((Display*) win->src.display, cmap, NULL, 0, 0);
   2586 
   2587 		#ifdef RGFW_OPENGL
   2588 		XFree(vi);
   2589 		#endif
   2590 
   2591 		// In your .desktop app, if you set the property
   2592 		// StartupWMClass=RGFW that will assoicate the launcher icon
   2593 		// with your application - robrohan 
   2594 		
   2595 		if (RGFW_className == NULL)
   2596 			RGFW_className = (char*)name;
   2597 
   2598 		XClassHint *hint = XAllocClassHint();
   2599 		assert(hint != NULL);
   2600 		hint->res_class = (char*)RGFW_className;
   2601 		hint->res_name = (char*)name; // just use the window name as the app name
   2602 		XSetClassHint((Display*) win->src.display, win->src.window, hint);
   2603 		XFree(hint);
   2604 
   2605 		if ((args & RGFW_NO_INIT_API) == 0) {
   2606 #ifdef RGFW_OPENGL /* This is the second part of setting up opengl. This is where we ask OpenGL for a specific version. */ 
   2607 		i32 context_attribs[7] = { 0, 0, 0, 0, 0, 0, 0 };
   2608 		context_attribs[0] = GLX_CONTEXT_PROFILE_MASK_ARB;
   2609 		if (RGFW_profile == RGFW_GL_CORE) 
   2610 			context_attribs[1] = GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
   2611 		else 
   2612 			context_attribs[1] = GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
   2613 		
   2614 		if (RGFW_majorVersion || RGFW_minorVersion) {
   2615 			context_attribs[2] = GLX_CONTEXT_MAJOR_VERSION_ARB;
   2616 			context_attribs[3] = RGFW_majorVersion;
   2617 			context_attribs[4] = GLX_CONTEXT_MINOR_VERSION_ARB;
   2618 			context_attribs[5] = RGFW_minorVersion;
   2619 		}
   2620 
   2621 		glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0;
   2622 		glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)
   2623 			glXGetProcAddressARB((GLubyte*) "glXCreateContextAttribsARB");
   2624 
   2625 		GLXContext ctx = NULL;
   2626 
   2627 		if (RGFW_root != NULL)
   2628 			ctx = RGFW_root->src.ctx;
   2629 
   2630 		win->src.ctx = glXCreateContextAttribsARB((Display*) win->src.display, bestFbc, ctx, True, context_attribs);
   2631 #endif
   2632 		if (RGFW_root == NULL)
   2633 			RGFW_root = win;
   2634 
   2635 		RGFW_init_buffer(win, vi);
   2636 		}
   2637 		
   2638 
   2639 		#ifndef RGFW_NO_MONITOR
   2640 		if (args & RGFW_SCALE_TO_MONITOR)
   2641 			RGFW_window_scaleToMonitor(win);
   2642 		#endif
   2643 
   2644 		if (args & RGFW_CENTER) {
   2645 			RGFW_area screenR = RGFW_getScreenSize();
   2646 			RGFW_window_move(win, RGFW_POINT((screenR.w - win->r.w) / 2, (screenR.h - win->r.h) / 2));
   2647 		}
   2648 
   2649 		if (args & RGFW_NO_RESIZE) { /* make it so the user can't resize the window*/
   2650 			XSizeHints* sh = XAllocSizeHints();
   2651 			sh->flags = (1L << 4) | (1L << 5);
   2652 			sh->min_width = sh->max_width = win->r.w;
   2653 			sh->min_height = sh->max_height = win->r.h;
   2654 
   2655 			XSetWMSizeHints((Display*) win->src.display, (Drawable) win->src.window, sh, XA_WM_NORMAL_HINTS);
   2656 			XFree(sh);
   2657 		}
   2658 
   2659 		if (args & RGFW_NO_BORDER) {
   2660 			RGFW_window_setBorder(win, 0);
   2661 		}
   2662 
   2663 		XSelectInput((Display*) win->src.display, (Drawable) win->src.window, event_mask); /*!< tell X11 what events we want*/
   2664 
   2665 		/* make it so the user can't close the window until the program does*/
   2666 		if (wm_delete_window == 0)
   2667 			wm_delete_window = XInternAtom((Display*) win->src.display, "WM_DELETE_WINDOW", False);
   2668 
   2669 		XSetWMProtocols((Display*) win->src.display, (Drawable) win->src.window, &wm_delete_window, 1);
   2670 
   2671 		/* connect the context to the window*/
   2672 #ifdef RGFW_OPENGL
   2673 		if ((args & RGFW_NO_INIT_API) == 0)
   2674 			glXMakeCurrent((Display*) win->src.display, (Drawable) win->src.window, (GLXContext) win->src.ctx);
   2675 #endif
   2676 
   2677 		/* set the background*/
   2678 		XStoreName((Display*) win->src.display, (Drawable) win->src.window, name); /*!< set the name*/
   2679 
   2680 		XMapWindow((Display*) win->src.display, (Drawable) win->src.window);						  /* draw the window*/
   2681 		XMoveWindow((Display*) win->src.display, (Drawable) win->src.window, win->r.x, win->r.y); /*!< move the window to it's proper cords*/
   2682 
   2683 		if (args & RGFW_ALLOW_DND) { /* init drag and drop atoms and turn on drag and drop for this window */
   2684 			win->_winArgs |= RGFW_ALLOW_DND;
   2685 
   2686 			XdndTypeList = XInternAtom((Display*) win->src.display, "XdndTypeList", False);
   2687 			XdndSelection = XInternAtom((Display*) win->src.display, "XdndSelection", False);
   2688 
   2689 			/* client messages */
   2690 			XdndEnter = XInternAtom((Display*) win->src.display, "XdndEnter", False);
   2691 			XdndPosition = XInternAtom((Display*) win->src.display, "XdndPosition", False);
   2692 			XdndStatus = XInternAtom((Display*) win->src.display, "XdndStatus", False);
   2693 			XdndLeave = XInternAtom((Display*) win->src.display, "XdndLeave", False);
   2694 			XdndDrop = XInternAtom((Display*) win->src.display, "XdndDrop", False);
   2695 			XdndFinished = XInternAtom((Display*) win->src.display, "XdndFinished", False);
   2696 
   2697 			/* actions */
   2698 			XdndActionCopy = XInternAtom((Display*) win->src.display, "XdndActionCopy", False);
   2699 
   2700 			XtextUriList = XInternAtom((Display*) win->src.display, "text/uri-list", False); 
   2701 			XtextPlain = XInternAtom((Display*) win->src.display, "text/plain", False);
   2702 
   2703 			XdndAware = XInternAtom((Display*) win->src.display, "XdndAware", False);
   2704 			const u8 version = 5;
   2705 
   2706 			XChangeProperty((Display*) win->src.display, (Window) win->src.window,
   2707 				XdndAware, 4, 32,
   2708 				PropModeReplace, &version, 1); /*!< turns on drag and drop */
   2709 		}
   2710 
   2711 		#ifdef RGFW_EGL
   2712 			if ((args & RGFW_NO_INIT_API) == 0)
   2713 				RGFW_createOpenGLContext(win);
   2714 		#endif
   2715 
   2716 		RGFW_window_setMouseDefault(win);
   2717 
   2718 		RGFW_windowsOpen++;
   2719 
   2720 		return win; /*return newly created window*/
   2721 	}
   2722 
   2723 	RGFW_area RGFW_getScreenSize(void) {
   2724 		assert(RGFW_root != NULL);
   2725 
   2726 		Screen* scrn = DefaultScreenOfDisplay((Display*) RGFW_root->src.display);
   2727 		return RGFW_AREA(scrn->width, scrn->height);
   2728 	}
   2729 
   2730 	RGFW_point RGFW_getGlobalMousePoint(void) {
   2731 		assert(RGFW_root != NULL);
   2732 
   2733 		RGFW_point RGFWMouse;
   2734 
   2735 		i32 x, y;
   2736 		u32 z;
   2737 		Window window1, window2;
   2738 		XQueryPointer((Display*) RGFW_root->src.display, XDefaultRootWindow((Display*) RGFW_root->src.display), &window1, &window2, &RGFWMouse.x, &RGFWMouse.y, &x, &y, &z);
   2739  
   2740 		return RGFWMouse;
   2741 	}
   2742 
   2743 	RGFW_point RGFW_window_getMousePoint(RGFW_window* win) {
   2744 		assert(win != NULL);
   2745 
   2746 		RGFW_point RGFWMouse;
   2747 
   2748 		i32 x, y;
   2749 		u32 z;
   2750 		Window window1, window2;
   2751 		XQueryPointer((Display*) win->src.display, win->src.window, &window1, &window2, &x, &y, &RGFWMouse.x, &RGFWMouse.y, &z);
   2752 
   2753 		return RGFWMouse;
   2754 	}
   2755 
   2756 	int xAxis = 0, yAxis = 0;
   2757 
   2758 	RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) {
   2759 		assert(win != NULL);
   2760 
   2761 		static struct {
   2762 			long source, version;
   2763 			i32 format;
   2764 		} xdnd;
   2765 
   2766 		if (win->event.type == 0) 
   2767 			RGFW_resetKey();
   2768 
   2769 		if (win->event.type == RGFW_quit) {
   2770 			return NULL;
   2771 		}
   2772 
   2773 		win->event.type = 0;
   2774 
   2775 #ifdef __linux__
   2776 	RGFW_Event* event = RGFW_linux_updateJoystick(win);
   2777 	if (event != NULL)
   2778 		return event;
   2779 #endif
   2780 
   2781 		XPending(win->src.display);
   2782 
   2783 		XEvent E; /*!< raw X11 event */
   2784 
   2785 		/* if there is no unread qued events, get a new one */
   2786 		if ((QLength(win->src.display) || XEventsQueued((Display*) win->src.display, QueuedAlready) + XEventsQueued((Display*) win->src.display, QueuedAfterReading)) 
   2787 			&& win->event.type != RGFW_quit
   2788 		)
   2789 			XNextEvent((Display*) win->src.display, &E);
   2790 		else {
   2791 			return NULL;
   2792 		}
   2793 
   2794 		u32 i;
   2795 		win->event.type = 0;
   2796 
   2797 
   2798 		switch (E.type) {
   2799 		case KeyPress:
   2800 		case KeyRelease: {
   2801 			win->event.repeat = RGFW_FALSE;
   2802 			/* check if it's a real key release */
   2803 			if (E.type == KeyRelease && XEventsQueued((Display*) win->src.display, QueuedAfterReading)) { /* get next event if there is one*/
   2804 				XEvent NE;
   2805 				XPeekEvent((Display*) win->src.display, &NE);
   2806 
   2807 				if (E.xkey.time == NE.xkey.time && E.xkey.keycode == NE.xkey.keycode) /* check if the current and next are both the same*/
   2808 					win->event.repeat = RGFW_TRUE;
   2809 			}
   2810 
   2811 			/* set event key data */
   2812 			KeySym sym = (KeySym)XkbKeycodeToKeysym((Display*) win->src.display, E.xkey.keycode, 0, E.xkey.state & ShiftMask ? 1 : 0);
   2813 			win->event.keyCode = RGFW_apiKeyCodeToRGFW(E.xkey.keycode);
   2814 			
   2815 			char* str = (char*)XKeysymToString(sym);
   2816 			if (str != NULL)
   2817 				strncpy(win->event.keyName, str, 16);
   2818 
   2819 			win->event.keyName[15] = '\0';		
   2820 
   2821 			RGFW_keyboard[win->event.keyCode].prev = RGFW_isPressed(win, win->event.keyCode);
   2822 			
   2823 			/* get keystate data */
   2824 			win->event.type = (E.type == KeyPress) ? RGFW_keyPressed : RGFW_keyReleased;
   2825 
   2826 			XKeyboardState keystate;
   2827 			XGetKeyboardControl((Display*) win->src.display, &keystate);
   2828 
   2829 			RGFW_updateLockState(win, (keystate.led_mask & 1), (keystate.led_mask & 2));
   2830 			RGFW_keyboard[win->event.keyCode].current = (E.type == KeyPress);
   2831 			RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, (E.type == KeyPress));
   2832 			break;
   2833 		}
   2834 		case ButtonPress:
   2835 		case ButtonRelease:
   2836 			win->event.type = RGFW_mouseButtonPressed + (E.type == ButtonRelease); // the events match 
   2837 			
   2838 			switch(win->event.button) {
   2839 				case RGFW_mouseScrollUp:
   2840 					win->event.scroll = 1;
   2841 					break;
   2842 				case RGFW_mouseScrollDown:
   2843 					win->event.scroll = -1;
   2844 					break;
   2845 				default: break;
   2846 			}
   2847 
   2848 			win->event.button = E.xbutton.button;
   2849 			RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;
   2850 
   2851 			if (win->event.repeat == RGFW_FALSE)
   2852 				win->event.repeat = RGFW_isPressed(win, win->event.keyCode);
   2853 
   2854 			RGFW_mouseButtons[win->event.button].current = (E.type == ButtonPress);
   2855 			RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, (E.type == ButtonPress));
   2856 			break;
   2857 
   2858 		case MotionNotify:	
   2859 			win->event.point.x = E.xmotion.x;
   2860 			win->event.point.y = E.xmotion.y;
   2861 			
   2862 			if ((win->_winArgs & RGFW_HOLD_MOUSE)) {
   2863 				win->event.point.y = E.xmotion.y;
   2864 
   2865 				win->event.point.x = win->_lastMousePoint.x - abs(win->event.point.x);
   2866 				win->event.point.y = win->_lastMousePoint.y - abs(win->event.point.y);
   2867 			}
   2868 
   2869 			win->_lastMousePoint = RGFW_POINT(E.xmotion.x, E.xmotion.y);
   2870 
   2871 			win->event.type = RGFW_mousePosChanged;
   2872 			RGFW_mousePosCallback(win, win->event.point);
   2873 			break;
   2874 
   2875 		case GenericEvent: {
   2876 			/* MotionNotify is used for mouse events if the mouse isn't held */                
   2877 			if (!(win->_winArgs & RGFW_HOLD_MOUSE)) {
   2878             	XFreeEventData(win->src.display, &E.xcookie);
   2879 				break;
   2880 			}
   2881 			
   2882             XGetEventData(win->src.display, &E.xcookie);
   2883             if (E.xcookie.evtype == XI_RawMotion) {
   2884 				XIRawEvent *raw = (XIRawEvent *)E.xcookie.data;
   2885 				if (raw->valuators.mask_len == 0) {
   2886 					XFreeEventData(win->src.display, &E.xcookie);
   2887 					break;
   2888 				}
   2889 
   2890                 double deltaX = 0.0f; 
   2891 				double deltaY = 0.0f;
   2892 
   2893                 /* check if relative motion data exists where we think it does */
   2894 				if (XIMaskIsSet(raw->valuators.mask, 0) != 0)
   2895 					deltaX += raw->raw_values[0];
   2896 				if (XIMaskIsSet(raw->valuators.mask, 1) != 0)
   2897 					deltaY += raw->raw_values[1];
   2898 
   2899 				win->event.point = RGFW_POINT((i32)deltaX, (i32)deltaY);
   2900 				
   2901 				RGFW_window_moveMouse(win, RGFW_POINT(win->r.x + (win->r.w / 2), win->r.y + (win->r.h / 2)));
   2902 
   2903 				win->event.type = RGFW_mousePosChanged;
   2904 				RGFW_mousePosCallback(win, win->event.point);
   2905             }
   2906 
   2907             XFreeEventData(win->src.display, &E.xcookie);
   2908 			break;
   2909 		}
   2910 		
   2911 		case Expose:
   2912 			win->event.type = RGFW_windowRefresh;
   2913 			RGFW_windowRefreshCallback(win);
   2914 			break;
   2915 
   2916 		case ClientMessage:
   2917 			/* if the client closed the window*/
   2918 			if (E.xclient.data.l[0] == (i64) wm_delete_window) {
   2919 				win->event.type = RGFW_quit;
   2920 				RGFW_windowQuitCallback(win);
   2921 				break;
   2922 			}
   2923 			
   2924 			/* reset DND values */
   2925 			if (win->event.droppedFilesCount) {
   2926 				for (i = 0; i < win->event.droppedFilesCount; i++)
   2927 					win->event.droppedFiles[i][0] = '\0';
   2928 			}
   2929 
   2930 			win->event.droppedFilesCount = 0;
   2931 
   2932 			if ((win->_winArgs & RGFW_ALLOW_DND) == 0)
   2933 				break;
   2934 
   2935 			XEvent reply = { ClientMessage };
   2936 			reply.xclient.window = xdnd.source;
   2937 			reply.xclient.format = 32;
   2938 			reply.xclient.data.l[0] = (long) win->src.window;
   2939 			reply.xclient.data.l[1] = 0;
   2940 			reply.xclient.data.l[2] = None;
   2941 
   2942 			if (E.xclient.message_type == XdndEnter) {
   2943 				unsigned long count;
   2944 				Atom* formats;
   2945 				Atom real_formats[6];
   2946 
   2947 				Bool list = E.xclient.data.l[1] & 1;
   2948 
   2949 				xdnd.source = E.xclient.data.l[0];
   2950 				xdnd.version = E.xclient.data.l[1] >> 24;
   2951 				xdnd.format = None;
   2952 
   2953 				if (xdnd.version > 5)
   2954 					break;
   2955 
   2956 				if (list) {
   2957 					Atom actualType;
   2958 					i32 actualFormat;
   2959 					unsigned long bytesAfter;
   2960 
   2961 					XGetWindowProperty((Display*) win->src.display,
   2962 						xdnd.source,
   2963 						XdndTypeList,
   2964 						0,
   2965 						LONG_MAX,
   2966 						False,
   2967 						4,
   2968 						&actualType,
   2969 						&actualFormat,
   2970 						&count,
   2971 						&bytesAfter,
   2972 						(u8**) &formats);
   2973 				} else {
   2974 					count = 0;
   2975 
   2976 					if (E.xclient.data.l[2] != None)
   2977 						real_formats[count++] = E.xclient.data.l[2];
   2978 					if (E.xclient.data.l[3] != None)
   2979 						real_formats[count++] = E.xclient.data.l[3];
   2980 					if (E.xclient.data.l[4] != None)
   2981 						real_formats[count++] = E.xclient.data.l[4];
   2982 					
   2983 					formats = real_formats;
   2984 				}
   2985 
   2986 				unsigned long i;
   2987 				for (i = 0; i < count; i++) {
   2988 				    if (formats[i] == XtextUriList || formats[i] == XtextPlain) {
   2989 						xdnd.format = formats[i];
   2990 						break;
   2991 					}
   2992 				}
   2993 
   2994 				if (list) {
   2995 					XFree(formats);
   2996 				}
   2997 
   2998 				break;
   2999 			}
   3000 			if (E.xclient.message_type == XdndPosition) {
   3001 				const i32 xabs = (E.xclient.data.l[2] >> 16) & 0xffff;
   3002 				const i32 yabs = (E.xclient.data.l[2]) & 0xffff;
   3003 				Window dummy;
   3004 				i32 xpos, ypos;
   3005 
   3006 				if (xdnd.version > 5)
   3007 					break;
   3008 
   3009 				XTranslateCoordinates((Display*) win->src.display,
   3010 					XDefaultRootWindow((Display*) win->src.display),
   3011 					(Window) win->src.window,
   3012 					xabs, yabs,
   3013 					&xpos, &ypos,
   3014 					&dummy);
   3015 
   3016 				win->event.point.x = xpos;
   3017 				win->event.point.y = ypos;
   3018 
   3019 				reply.xclient.window = xdnd.source;
   3020 				reply.xclient.message_type = XdndStatus;
   3021 
   3022 				if (xdnd.format) {
   3023 					reply.xclient.data.l[1] = 1;
   3024 					if (xdnd.version >= 2)
   3025 						reply.xclient.data.l[4] = XdndActionCopy;
   3026 				}
   3027 
   3028 				XSendEvent((Display*) win->src.display, xdnd.source, False, NoEventMask, &reply);
   3029 				XFlush((Display*) win->src.display);
   3030 				break;
   3031 			}
   3032 
   3033 			if (E.xclient.message_type != XdndDrop)
   3034 				break;
   3035 
   3036 			if (xdnd.version > 5)
   3037 				break;
   3038 
   3039 			win->event.type = RGFW_dnd_init;
   3040 
   3041 			if (xdnd.format) {
   3042 				Time time = CurrentTime;
   3043 
   3044 				if (xdnd.version >= 1)
   3045 					time = E.xclient.data.l[2];
   3046 
   3047 				XConvertSelection((Display*) win->src.display,
   3048 					XdndSelection,
   3049 					xdnd.format,
   3050 					XdndSelection,
   3051 					(Window) win->src.window,
   3052 					time);
   3053 			} else if (xdnd.version >= 2) {
   3054 				XEvent reply = { ClientMessage };
   3055 
   3056 				XSendEvent((Display*) win->src.display, xdnd.source,
   3057 					False, NoEventMask, &reply);
   3058 				XFlush((Display*) win->src.display);
   3059 			}
   3060 
   3061 			RGFW_dndInitCallback(win, win->event.point);
   3062 			break;
   3063 		case SelectionNotify: {
   3064 			/* this is only for checking for xdnd drops */
   3065 			if (E.xselection.property != XdndSelection || !(win->_winArgs | RGFW_ALLOW_DND))
   3066 				break;
   3067 
   3068 			char* data;
   3069 			unsigned long result;
   3070 
   3071 			Atom actualType;
   3072 			i32 actualFormat;
   3073 			unsigned long bytesAfter;
   3074 
   3075 			XGetWindowProperty((Display*) win->src.display, E.xselection.requestor, E.xselection.property, 0, LONG_MAX, False, E.xselection.target, &actualType, &actualFormat, &result, &bytesAfter, (u8**) &data);
   3076 
   3077 			if (result == 0)
   3078 				break;
   3079 
   3080 			/*
   3081 			SOURCED FROM GLFW _glfwParseUriList
   3082 			Copyright (c) 2002-2006 Marcus Geelnard
   3083 			Copyright (c) 2006-2019 Camilla Löwy
   3084 			*/
   3085 
   3086 			const char* prefix = (const char*)"file://";
   3087 
   3088 			char* line;
   3089 
   3090 			win->event.droppedFilesCount = 0;
   3091 
   3092 			win->event.type = RGFW_dnd;
   3093 
   3094 			while ((line = strtok(data, "\r\n"))) {
   3095 				char path[RGFW_MAX_PATH];
   3096 
   3097 				data = NULL;
   3098 
   3099 				if (line[0] == '#')
   3100 					continue;
   3101 
   3102 				char* l;
   3103 				for (l = line; 1; l++) {
   3104 					if ((l - line) > 7)
   3105 						break;
   3106 					else if (*l != prefix[(l - line)])
   3107 						break;
   3108 					else if (*l == '\0' && prefix[(l - line)] == '\0') {
   3109 						line += 7;
   3110 						while (*line != '/')
   3111 							line++;
   3112 						break;
   3113 					} else if (*l == '\0')
   3114 						break;
   3115 				}
   3116 
   3117 				win->event.droppedFilesCount++;
   3118 
   3119 				size_t index = 0;
   3120 				while (*line) {
   3121 					if (line[0] == '%' && line[1] && line[2]) {
   3122 						const char digits[3] = { line[1], line[2], '\0' };
   3123 						path[index] = (char) strtol(digits, NULL, 16);
   3124 						line += 2;
   3125 					} else
   3126 						path[index] = *line;
   3127 
   3128 					index++;
   3129 					line++;
   3130 				}
   3131 				path[index] = '\0';
   3132 				strncpy(win->event.droppedFiles[win->event.droppedFilesCount - 1], path, index + 1);
   3133 			}
   3134 
   3135 			if (data)
   3136 				XFree(data);
   3137 
   3138 			if (xdnd.version >= 2) {
   3139 				reply.xclient.message_type = XdndFinished;
   3140 				reply.xclient.data.l[1] = result;
   3141 				reply.xclient.data.l[2] = XdndActionCopy;
   3142 
   3143 				XSendEvent((Display*) win->src.display, xdnd.source, False, NoEventMask, &reply);
   3144 				XFlush((Display*) win->src.display);
   3145 			}
   3146 
   3147 			RGFW_dndCallback(win, win->event.droppedFiles, win->event.droppedFilesCount);
   3148 			break;
   3149 		}
   3150 		case FocusIn:
   3151 			win->event.inFocus = 1;
   3152 			win->event.type = RGFW_focusIn;
   3153 			RGFW_focusCallback(win, 1);
   3154 			break;
   3155 
   3156 			break;
   3157 		case FocusOut:
   3158 			win->event.inFocus = 0;
   3159 			win->event.type = RGFW_focusOut;
   3160 			RGFW_focusCallback(win, 0);
   3161 			break;
   3162 		
   3163 		case EnterNotify: {
   3164 			win->event.type = RGFW_mouseEnter;
   3165 			win->event.point.x = E.xcrossing.x;
   3166 			win->event.point.y = E.xcrossing.y;
   3167 			RGFW_mouseNotifyCallBack(win, win->event.point, 1);
   3168 			break;
   3169 		}
   3170 
   3171 		case LeaveNotify: {
   3172 			win->event.type = RGFW_mouseLeave;
   3173 			RGFW_mouseNotifyCallBack(win, win->event.point, 0);
   3174 			break;
   3175 		}
   3176 
   3177 		case ConfigureNotify: {
   3178 				/* detect resize */
   3179       			if (E.xconfigure.width != win->r.w || E.xconfigure.height != win->r.h) {
   3180 					win->event.type = RGFW_windowResized;
   3181 					win->r = RGFW_RECT(win->r.x, win->r.y, E.xconfigure.width, E.xconfigure.height);
   3182 					RGFW_windowResizeCallback(win, win->r);
   3183 					break;
   3184       			}  
   3185       
   3186       			/* detect move */
   3187       			if (E.xconfigure.x != win->r.x || E.xconfigure.y != win->r.y) {
   3188 					win->event.type = RGFW_windowMoved;
   3189 					win->r = RGFW_RECT(E.xconfigure.x, E.xconfigure.y, win->r.w, win->r.h);
   3190 					RGFW_windowMoveCallback(win, win->r);
   3191 					break;
   3192 				} 
   3193 
   3194 				break;
   3195 		}
   3196 		default: {
   3197 			break;
   3198 		}
   3199 		}
   3200 
   3201 		XFlush((Display*) win->src.display);
   3202 
   3203 		if (win->event.type)
   3204 			return &win->event;
   3205 		else
   3206 			return NULL;
   3207 	}
   3208 
   3209 	void RGFW_window_move(RGFW_window* win, RGFW_point v) {
   3210 		assert(win != NULL);
   3211 		win->r.x = v.x;
   3212 		win->r.y = v.y;
   3213 
   3214 		XMoveWindow((Display*) win->src.display, (Window) win->src.window, v.x, v.y);
   3215 	}
   3216 
   3217 
   3218 	void RGFW_window_resize(RGFW_window* win, RGFW_area a) {
   3219 		assert(win != NULL);
   3220 		win->r.w = a.w;
   3221 		win->r.h = a.h;
   3222 
   3223 		XResizeWindow((Display*) win->src.display, (Window) win->src.window, a.w, a.h);
   3224 	}
   3225 
   3226 	void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) {
   3227 		assert(win != NULL);
   3228 
   3229 		if (a.w == 0 && a.h == 0)
   3230 			return;
   3231 
   3232 		XSizeHints hints;
   3233 		long flags;
   3234 
   3235 		XGetWMNormalHints(win->src.display, (Window) win->src.window, &hints, &flags);
   3236 
   3237 		hints.flags |= PMinSize;
   3238 		
   3239 		hints.min_width = a.w;
   3240 		hints.min_height = a.h;
   3241 
   3242 		XSetWMNormalHints(win->src.display, (Window) win->src.window, &hints);
   3243 	}
   3244 
   3245 	void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) {
   3246 		assert(win != NULL);
   3247 
   3248 		if (a.w == 0 && a.h == 0)
   3249 			return;
   3250 
   3251 		XSizeHints hints;
   3252 		long flags;
   3253 
   3254 		XGetWMNormalHints(win->src.display, (Window) win->src.window, &hints, &flags);
   3255 
   3256 		hints.flags |= PMaxSize;
   3257 
   3258 		hints.max_width = a.w;
   3259 		hints.max_height = a.h;
   3260 
   3261 		XSetWMNormalHints(win->src.display, (Window) win->src.window, &hints);
   3262 	}
   3263 
   3264 
   3265 	void RGFW_window_minimize(RGFW_window* win) {
   3266 		assert(win != NULL);
   3267 
   3268 		XIconifyWindow(win->src.display, (Window) win->src.window, DefaultScreen(win->src.display));
   3269 		XFlush(win->src.display);
   3270 	}
   3271 
   3272 	void RGFW_window_restore(RGFW_window* win) {
   3273 		assert(win != NULL);
   3274 
   3275 		XMapWindow(win->src.display, (Window) win->src.window);
   3276 		XFlush(win->src.display);
   3277 	}	
   3278 
   3279 	void RGFW_window_setName(RGFW_window* win, char* name) {
   3280 		assert(win != NULL);
   3281 
   3282 		XStoreName((Display*) win->src.display, (Window) win->src.window, name);
   3283 	}
   3284 	
   3285 	void* RGFW_libxshape = NULL;
   3286 
   3287 	#ifndef RGFW_NO_PASSTHROUGH
   3288 	void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) {
   3289 		assert(win != NULL);
   3290 		
   3291 		#if defined(__CYGWIN__)
   3292 			RGFW_libxshape = dlopen("libXext-6.so", RTLD_LAZY | RTLD_LOCAL);
   3293 		#elif defined(__OpenBSD__) || defined(__NetBSD__)
   3294 			RGFW_libxshape = dlopen("libXext.so", RTLD_LAZY | RTLD_LOCAL);
   3295 		#else
   3296     		RGFW_libxshape = dlopen("libXext.so.6", RTLD_LAZY | RTLD_LOCAL);
   3297 		#endif
   3298 		
   3299 		typedef void (* PFN_XShapeCombineMask)(Display*,Window,int,int,int,Pixmap,int);
   3300 		static PFN_XShapeCombineMask XShapeCombineMask;
   3301 		
   3302 		typedef void (* PFN_XShapeCombineRegion)(Display*,Window,int,int,int,Region,int);
   3303 		static PFN_XShapeCombineRegion XShapeCombineRegion;
   3304 		
   3305 		if (XShapeCombineMask != NULL)
   3306 			XShapeCombineMask = (PFN_XShapeCombineMask) dlsym(RGFW_libxshape, "XShapeCombineMask");
   3307 
   3308 		if (XShapeCombineRegion != NULL)
   3309 			XShapeCombineRegion = (PFN_XShapeCombineRegion) dlsym(RGFW_libxshape, "XShapeCombineMask");
   3310 
   3311 		if (passthrough) {
   3312 			Region region = XCreateRegion();
   3313 			XShapeCombineRegion(win->src.display, win->src.window, ShapeInput, 0, 0, region, ShapeSet);
   3314 			XDestroyRegion(region);
   3315 
   3316 			return;
   3317 		}
   3318 
   3319 		XShapeCombineMask(win->src.display, win->src.window, ShapeInput, 0, 0, None, ShapeSet);
   3320 	}
   3321 	#endif
   3322 
   3323 	/*
   3324 		the majority function is sourced from GLFW
   3325 	*/
   3326 
   3327 	void RGFW_window_setIcon(RGFW_window* win, u8* icon, RGFW_area a, i32 channels) {
   3328 		assert(win != NULL);
   3329 
   3330 		i32 longCount = 2 + a.w * a.h;
   3331 
   3332 		u64* X11Icon = (u64*) RGFW_MALLOC(longCount * sizeof(u64));
   3333 		u64* target = X11Icon;
   3334 
   3335 		*target++ = a.w;
   3336 		*target++ = a.h;
   3337 
   3338 		u32 i;
   3339 
   3340 		for (i = 0; i < a.w * a.h; i++) {
   3341 			if (channels == 3)
   3342 				*target++ = ((icon[i * 3 + 0]) << 16) |
   3343 				((icon[i * 3 + 1]) << 8) |
   3344 				((icon[i * 3 + 2]) << 0) |
   3345 				(0xFF << 24);
   3346 
   3347 			else if (channels == 4)
   3348 				*target++ = ((icon[i * 4 + 0]) << 16) |
   3349 				((icon[i * 4 + 1]) << 8) |
   3350 				((icon[i * 4 + 2]) << 0) |
   3351 				((icon[i * 4 + 3]) << 24);
   3352 		}
   3353 
   3354 		static Atom NET_WM_ICON = 0;
   3355 		if (NET_WM_ICON == 0)
   3356 			NET_WM_ICON = XInternAtom((Display*) win->src.display, "_NET_WM_ICON", False);
   3357 
   3358 		XChangeProperty((Display*) win->src.display, (Window) win->src.window,
   3359 			NET_WM_ICON,
   3360 			6, 32,
   3361 			PropModeReplace,
   3362 			(u8*) X11Icon,
   3363 			longCount);
   3364 
   3365 		RGFW_FREE(X11Icon);
   3366 
   3367 		XFlush((Display*) win->src.display);
   3368 	}
   3369 
   3370 	void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels) {
   3371 		assert(win != NULL);
   3372 
   3373 #ifndef RGFW_NO_X11_CURSOR
   3374 		XcursorImage* native = XcursorImageCreate(a.w, a.h);
   3375 		native->xhot = 0;
   3376 		native->yhot = 0;
   3377 
   3378 		u8* source = (u8*) image;
   3379 		XcursorPixel* target = native->pixels;
   3380 
   3381 		u32 i;
   3382 		for (i = 0; i < a.w * a.h; i++, target++, source += 4) {
   3383 			u8 alpha = 0xFF;
   3384 			if (channels == 4)
   3385 				alpha = source[3];
   3386 
   3387 			*target = (alpha << 24) | (((source[0] * alpha) / 255) << 16) | (((source[1] * alpha) / 255) << 8) | (((source[2] * alpha) / 255) << 0);
   3388 		}
   3389 
   3390 		Cursor cursor = XcursorImageLoadCursor((Display*) win->src.display, native);
   3391 		XDefineCursor((Display*) win->src.display, (Window) win->src.window, (Cursor) cursor);
   3392 
   3393 		XFreeCursor((Display*) win->src.display, (Cursor) cursor);
   3394 		XcursorImageDestroy(native);
   3395 #else
   3396 	RGFW_UNUSED(image) RGFW_UNUSED(a.w) RGFW_UNUSED(channels)
   3397 #endif
   3398 	}
   3399 
   3400 	void RGFW_window_moveMouse(RGFW_window* win, RGFW_point v) {
   3401 		assert(win != NULL);
   3402 
   3403 		XEvent event;
   3404 		XQueryPointer(win->src.display, DefaultRootWindow(win->src.display),
   3405 			&event.xbutton.root, &event.xbutton.window,
   3406 			&event.xbutton.x_root, &event.xbutton.y_root,
   3407 			&event.xbutton.x, &event.xbutton.y,
   3408 			&event.xbutton.state);
   3409 
   3410 		if (event.xbutton.x == v.x && event.xbutton.y == v.y)
   3411 			return;
   3412 
   3413 		XWarpPointer(win->src.display, None, win->src.window, 0, 0, 0, 0, (int) v.x - win->r.x, (int) v.y - win->r.y);
   3414 	}
   3415 
   3416 	RGFWDEF void RGFW_window_disableMouse(RGFW_window* win) {
   3417 		RGFW_UNUSED(win);
   3418 	}
   3419 
   3420 	void RGFW_window_setMouseDefault(RGFW_window* win) {
   3421 		RGFW_window_setMouseStandard(win, RGFW_MOUSE_ARROW);
   3422 	}
   3423 
   3424 	void RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse) {
   3425 		assert(win != NULL);
   3426 		 
   3427 		if (mouse > (sizeof(RGFW_mouseIconSrc) / sizeof(u8)))
   3428 			return;
   3429 		
   3430 		mouse = RGFW_mouseIconSrc[mouse];
   3431 
   3432 		Cursor cursor = XCreateFontCursor((Display*) win->src.display, mouse);
   3433 		XDefineCursor((Display*) win->src.display, (Window) win->src.window, (Cursor) cursor);
   3434 
   3435 		XFreeCursor((Display*) win->src.display, (Cursor) cursor);
   3436 	}
   3437 
   3438 	void RGFW_window_hide(RGFW_window* win) {
   3439 		XMapWindow(win->src.display, win->src.window);
   3440 	}
   3441 
   3442 	void RGFW_window_show(RGFW_window* win) {
   3443 		XUnmapWindow(win->src.display, win->src.window);
   3444 	}
   3445 
   3446 	/*
   3447 		the majority function is sourced from GLFW
   3448 	*/
   3449 	char* RGFW_readClipboard(size_t* size) {
   3450 		static Atom UTF8 = 0;
   3451 		if (UTF8 == 0)
   3452 			UTF8 = XInternAtom(RGFW_root->src.display, "UTF8_STRING", True);
   3453 
   3454 		XEvent event;
   3455 		int format;
   3456 		unsigned long N, sizeN;
   3457 		char* data, * s = NULL;
   3458 		Atom target;
   3459 		Atom CLIPBOARD = 0, XSEL_DATA = 0;
   3460 
   3461 		if (CLIPBOARD == 0) {
   3462 			CLIPBOARD = XInternAtom(RGFW_root->src.display, "CLIPBOARD", 0);
   3463 			XSEL_DATA = XInternAtom(RGFW_root->src.display, "XSEL_DATA", 0);
   3464 		}
   3465 
   3466 		XConvertSelection(RGFW_root->src.display, CLIPBOARD, UTF8, XSEL_DATA, RGFW_root->src.window, CurrentTime);
   3467 		XSync(RGFW_root->src.display, 0);
   3468 		XNextEvent(RGFW_root->src.display, &event);
   3469 
   3470 		if (event.type != SelectionNotify || event.xselection.selection != CLIPBOARD || event.xselection.property == 0)
   3471 			return NULL;
   3472 
   3473 		XGetWindowProperty(event.xselection.display, event.xselection.requestor,
   3474 			event.xselection.property, 0L, (~0L), 0, AnyPropertyType, &target,
   3475 			&format, &sizeN, &N, (unsigned char**) &data);
   3476 
   3477 		if (target == UTF8 || target == XA_STRING) {
   3478 			s = (char*)RGFW_MALLOC(sizeof(char) * sizeN);
   3479 			strncpy(s, data, sizeN);
   3480 			s[sizeN] = '\0';
   3481 			XFree(data);
   3482 		}
   3483 
   3484 		XDeleteProperty(event.xselection.display, event.xselection.requestor, event.xselection.property);
   3485 
   3486 		if (s != NULL && size != NULL)
   3487 			*size = sizeN;
   3488 
   3489 		return s;
   3490 	}
   3491 
   3492 	/*
   3493 		almost all of this function is sourced from GLFW
   3494 	*/
   3495 	void RGFW_writeClipboard(const char* text, u32 textLen) {
   3496 		static Atom CLIPBOARD = 0,
   3497 			UTF8_STRING = 0,
   3498 			SAVE_TARGETS = 0,
   3499 			TARGETS = 0,
   3500 			MULTIPLE = 0,
   3501 			ATOM_PAIR = 0,
   3502 			CLIPBOARD_MANAGER = 0;
   3503 
   3504 		if (CLIPBOARD == 0) {
   3505 			CLIPBOARD = XInternAtom((Display*) RGFW_root->src.display, "CLIPBOARD", False);
   3506 			UTF8_STRING = XInternAtom((Display*) RGFW_root->src.display, "UTF8_STRING", False);
   3507 			SAVE_TARGETS = XInternAtom((Display*) RGFW_root->src.display, "SAVE_TARGETS", False);
   3508 			TARGETS = XInternAtom((Display*) RGFW_root->src.display, "TARGETS", False);
   3509 			MULTIPLE = XInternAtom((Display*) RGFW_root->src.display, "MULTIPLE", False);
   3510 			ATOM_PAIR = XInternAtom((Display*) RGFW_root->src.display, "ATOM_PAIR", False);
   3511 			CLIPBOARD_MANAGER = XInternAtom((Display*) RGFW_root->src.display, "CLIPBOARD_MANAGER", False);
   3512 		}
   3513 		
   3514 		XSetSelectionOwner((Display*) RGFW_root->src.display, CLIPBOARD, (Window) RGFW_root->src.window, CurrentTime);
   3515 
   3516 		XConvertSelection((Display*) RGFW_root->src.display, CLIPBOARD_MANAGER, SAVE_TARGETS, None, (Window) RGFW_root->src.window, CurrentTime);
   3517 		for (;;) {
   3518 			XEvent event;
   3519 
   3520 			XNextEvent((Display*) RGFW_root->src.display, &event);
   3521 			if (event.type != SelectionRequest) {
   3522 				break;
   3523 			}
   3524 
   3525 			const XSelectionRequestEvent* request = &event.xselectionrequest;
   3526 
   3527 			XEvent reply = { SelectionNotify };
   3528 			reply.xselection.property = 0;
   3529 
   3530 			if (request->target == TARGETS) {
   3531 				const Atom targets[] = { TARGETS,
   3532 										MULTIPLE,
   3533 										UTF8_STRING,
   3534 										XA_STRING };
   3535 
   3536 				XChangeProperty((Display*) RGFW_root->src.display,
   3537 					request->requestor,
   3538 					request->property,
   3539 					4,
   3540 					32,
   3541 					PropModeReplace,
   3542 					(u8*) targets,
   3543 					sizeof(targets) / sizeof(targets[0]));
   3544 
   3545 				reply.xselection.property = request->property;
   3546 			}
   3547 
   3548 			if (request->target == MULTIPLE) {
   3549 				Atom* targets = NULL;
   3550 
   3551 				Atom actualType = 0;
   3552 				int actualFormat = 0;
   3553 				unsigned long count = 0, bytesAfter = 0;
   3554 
   3555 				XGetWindowProperty((Display*) RGFW_root->src.display, request->requestor, request->property, 0, LONG_MAX, False, ATOM_PAIR, &actualType, &actualFormat, &count, &bytesAfter, (u8**) &targets);
   3556 
   3557 				unsigned long i;
   3558 				for (i = 0; i < (u32)count; i += 2) {
   3559 					if (targets[i] == UTF8_STRING || targets[i] == XA_STRING) {
   3560 						XChangeProperty((Display*) RGFW_root->src.display,
   3561 							request->requestor,
   3562 							targets[i + 1],
   3563 							targets[i],
   3564 							8,
   3565 							PropModeReplace,
   3566 							(u8*) text,
   3567 							textLen);
   3568 						XFlush(RGFW_root->src.display);
   3569 					} else {
   3570 						targets[i + 1] = None;
   3571 					}
   3572 				}
   3573 
   3574 				XChangeProperty((Display*) RGFW_root->src.display,
   3575 					request->requestor,
   3576 					request->property,
   3577 					ATOM_PAIR,
   3578 					32,
   3579 					PropModeReplace,
   3580 					(u8*) targets,
   3581 					count);
   3582 
   3583 				XFlush(RGFW_root->src.display);
   3584 				XFree(targets);
   3585 
   3586 				reply.xselection.property = request->property;
   3587 			}
   3588 
   3589 			reply.xselection.display = request->display;
   3590 			reply.xselection.requestor = request->requestor;
   3591 			reply.xselection.selection = request->selection;
   3592 			reply.xselection.target = request->target;
   3593 			reply.xselection.time = request->time;
   3594 
   3595 			XSendEvent((Display*) RGFW_root->src.display, request->requestor, False, 0, &reply);
   3596 			XFlush(RGFW_root->src.display);
   3597 		}
   3598 	}
   3599 
   3600 	u8 RGFW_window_isFullscreen(RGFW_window* win) {
   3601 		assert(win != NULL);
   3602 
   3603 		XWindowAttributes windowAttributes;
   3604 		XGetWindowAttributes(win->src.display, (Window) win->src.window, &windowAttributes);
   3605 
   3606 		/* check if the window is visable */
   3607 		if (windowAttributes.map_state != IsViewable)
   3608 			return 0;
   3609 
   3610 		/* check if the window covers the full screen */
   3611 		return (windowAttributes.x == 0 && windowAttributes.y == 0 &&
   3612 			windowAttributes.width == XDisplayWidth(win->src.display, DefaultScreen(win->src.display)) &&
   3613 			windowAttributes.height == XDisplayHeight(win->src.display, DefaultScreen(win->src.display)));
   3614 	}
   3615 
   3616 	u8 RGFW_window_isHidden(RGFW_window* win) {
   3617 		assert(win != NULL);
   3618 
   3619 		XWindowAttributes windowAttributes;
   3620 		XGetWindowAttributes(win->src.display, (Window) win->src.window, &windowAttributes);
   3621 
   3622 		return (windowAttributes.map_state == IsUnmapped && !RGFW_window_isMinimized(win));
   3623 	}
   3624 
   3625 	u8 RGFW_window_isMinimized(RGFW_window* win) {
   3626 		assert(win != NULL);
   3627 
   3628 		static Atom prop = 0;
   3629 		if (prop == 0)
   3630 			prop = XInternAtom(win->src.display, "WM_STATE", False);
   3631 
   3632 		Atom actual_type;
   3633 		i32 actual_format;
   3634 		unsigned long nitems, bytes_after;
   3635 		unsigned char* prop_data;
   3636 
   3637 		i16 status = XGetWindowProperty(win->src.display, (Window) win->src.window, prop, 0, 2, False,
   3638 			AnyPropertyType, &actual_type, &actual_format,
   3639 			&nitems, &bytes_after, &prop_data);
   3640 
   3641 		if (status == Success && nitems >= 1 && *((int*) prop_data) == IconicState) {
   3642 			XFree(prop_data);
   3643 			return 1;
   3644 		}
   3645 
   3646 		if (prop_data != NULL)
   3647 			XFree(prop_data);
   3648 
   3649 		return 0;
   3650 	}
   3651 
   3652 	u8 RGFW_window_isMaximized(RGFW_window* win) {
   3653 		assert(win != NULL);
   3654 
   3655 		static Atom net_wm_state = 0;
   3656 		static Atom net_wm_state_maximized_horz = 0;
   3657 		static Atom net_wm_state_maximized_vert = 0;
   3658 
   3659 		if (net_wm_state == 0) {
   3660 			net_wm_state = XInternAtom(win->src.display, "_NET_WM_STATE", False);
   3661 			net_wm_state_maximized_vert = XInternAtom(win->src.display, "_NET_WM_STATE_MAXIMIZED_VERT", False);
   3662 			net_wm_state_maximized_horz = XInternAtom(win->src.display, "_NET_WM_STATE_MAXIMIZED_HORZ", False);
   3663 		}
   3664 
   3665 		Atom actual_type;
   3666 		i32 actual_format;
   3667 		unsigned long nitems, bytes_after;
   3668 		unsigned char* prop_data;
   3669 
   3670 		i16 status = XGetWindowProperty(win->src.display, (Window) win->src.window, net_wm_state, 0, 1024, False,
   3671 			XA_ATOM, &actual_type, &actual_format,
   3672 			&nitems, &bytes_after, &prop_data);
   3673 
   3674 		if (status != Success) {
   3675 			if (prop_data != NULL)
   3676 				XFree(prop_data);
   3677 
   3678 			return 0;
   3679 		}
   3680 
   3681 		Atom* atoms = (Atom*) prop_data;
   3682 		u64 i;
   3683 		for (i = 0; i < nitems; ++i) {
   3684 			if (atoms[i] == net_wm_state_maximized_horz ||
   3685 				atoms[i] == net_wm_state_maximized_vert) {
   3686 				XFree(prop_data);
   3687 				return 1;
   3688 			}
   3689 		}
   3690 
   3691 		return 0;
   3692 	}
   3693 
   3694 	static void XGetSystemContentScale(Display* display, float* xscale, float* yscale) {
   3695 		float xdpi = 96.f, ydpi = 96.f;
   3696 
   3697 #ifndef RGFW_NO_DPI
   3698 		char* rms = XResourceManagerString(display);
   3699 		XrmDatabase db = NULL;
   3700 
   3701 		if (rms && db)
   3702 			db = XrmGetStringDatabase(rms);
   3703 
   3704 		if (db == 0) {
   3705 			*xscale = xdpi / 96.f;
   3706 			*yscale = ydpi / 96.f;
   3707 			return;
   3708 		}
   3709 
   3710 		XrmValue value;
   3711 		char* type = NULL;
   3712 
   3713 		if (XrmGetResource(db, "Xft.dpi", "Xft.Dpi", &type, &value) && type && strncmp(type, "String", 7) == 0)
   3714 			xdpi = ydpi = atof(value.addr);
   3715 		XrmDestroyDatabase(db);
   3716 #endif
   3717 
   3718 		* xscale = xdpi / 96.f;
   3719 		*yscale = ydpi / 96.f;
   3720 	}
   3721 
   3722 	RGFW_monitor RGFW_XCreateMonitor(i32 screen) {
   3723 		RGFW_monitor monitor;
   3724 
   3725 		Display* display = XOpenDisplay(NULL);
   3726 		
   3727 		RGFW_area size = RGFW_getScreenSize();
   3728 
   3729 		monitor.rect = RGFW_RECT(0, 0, size.w, size.h);
   3730 		monitor.physW = DisplayWidthMM(display, screen);
   3731 		monitor.physH = DisplayHeightMM(display, screen);
   3732 		
   3733 		XGetSystemContentScale(display, &monitor.scaleX, &monitor.scaleY);
   3734 		XRRScreenResources* sr = XRRGetScreenResourcesCurrent(display, RootWindow(display, screen));
   3735 
   3736 		XRRCrtcInfo* ci = NULL;
   3737 		int crtc = screen;
   3738 
   3739 		if (sr->ncrtc > crtc) {
   3740 			ci = XRRGetCrtcInfo(display, sr, sr->crtcs[crtc]);
   3741 		}
   3742 		
   3743 		if (ci == NULL) {
   3744 			float dpi_width = round((double)monitor.rect.w/(((double)monitor.physW)/25.4));
   3745 			float dpi_height = round((double)monitor.rect.h/(((double)monitor.physH)/25.4));
   3746 		
   3747 			monitor.scaleX = (float) (dpi_width) / (float) 96;
   3748 			monitor.scaleY = (float) (dpi_height) / (float) 96;
   3749 			XRRFreeScreenResources(sr);
   3750 			XCloseDisplay(display);
   3751 			return monitor;
   3752 		}
   3753 	    
   3754 		XRROutputInfo* info = XRRGetOutputInfo (display, sr, sr->outputs[screen]);
   3755 		monitor.physW = info->mm_width;
   3756 		monitor.physH = info->mm_height;
   3757 
   3758 		monitor.rect.x = ci->x;
   3759 		monitor.rect.y = ci->y;
   3760 		monitor.rect.w = ci->width;
   3761 		monitor.rect.h = ci->height;
   3762 		
   3763 		float dpi_width = round((double)monitor.rect.w/(((double)monitor.physW)/25.4));
   3764 		float dpi_height = round((double)monitor.rect.h/(((double)monitor.physH)/25.4));
   3765 
   3766 		monitor.scaleX = (float) (dpi_width) / (float) 96;
   3767 		monitor.scaleY = (float) (dpi_height) / (float) 96;		
   3768 
   3769 		if (monitor.scaleX > 1 && monitor.scaleX < 1.1)
   3770 			monitor.scaleX = 1;
   3771 
   3772 		if (monitor.scaleY > 1 && monitor.scaleY < 1.1)
   3773 			monitor.scaleY = 1;
   3774 
   3775 		XRRFreeCrtcInfo(ci);
   3776 		XRRFreeScreenResources(sr);
   3777 
   3778 		XCloseDisplay(display);
   3779 
   3780 		return monitor;
   3781 	}
   3782 
   3783 	RGFW_monitor RGFW_monitors[6];
   3784 	RGFW_monitor* RGFW_getMonitors(void) {
   3785 		size_t i;
   3786 		for (i = 0; i < (size_t)ScreenCount(RGFW_root->src.display) && i < 6; i++)
   3787 			RGFW_monitors[i] = RGFW_XCreateMonitor(i);
   3788 
   3789 		return RGFW_monitors;
   3790 	}
   3791 
   3792 	RGFW_monitor RGFW_getPrimaryMonitor(void) {
   3793 		assert(RGFW_root != NULL);
   3794 
   3795 		i32 primary = -1;
   3796 		Window root = DefaultRootWindow(RGFW_root->src.display);
   3797 		XRRScreenResources* res = XRRGetScreenResources(RGFW_root->src.display, root);
   3798 
   3799 		for (int i = 0; i < res->noutput; i++) {
   3800 			XRROutputInfo* output_info = XRRGetOutputInfo(RGFW_root->src.display, res, res->outputs[i]);
   3801 			if (output_info->connection == RR_Connected && output_info->crtc) {
   3802 				XRRCrtcInfo* crtc_info = XRRGetCrtcInfo(RGFW_root->src.display, res, output_info->crtc);
   3803 				if (crtc_info->mode != None && crtc_info->x == 0 && crtc_info->y == 0) {
   3804 					primary = i;
   3805 					XRRFreeCrtcInfo(crtc_info);
   3806 					XRRFreeOutputInfo(output_info);
   3807 					break;
   3808 				}
   3809 				XRRFreeCrtcInfo(crtc_info);
   3810 			}
   3811 			XRRFreeOutputInfo(output_info);
   3812 		}
   3813 
   3814 		XRRFreeScreenResources(res);
   3815 
   3816 		return RGFW_XCreateMonitor(primary);
   3817 	}
   3818 
   3819 	RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) {
   3820 		return RGFW_XCreateMonitor(DefaultScreen(win->src.display));
   3821 	}
   3822 
   3823 	#ifdef RGFW_OPENGL
   3824 	void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) {
   3825 		if (win == NULL)
   3826 			glXMakeCurrent((Display*) NULL, (Drawable)NULL, (GLXContext) NULL);
   3827 		else
   3828 			glXMakeCurrent((Display*) win->src.display, (Drawable) win->src.window, (GLXContext) win->src.ctx);
   3829 	}
   3830 	#endif
   3831 
   3832 
   3833 	void RGFW_window_swapBuffers(RGFW_window* win) {
   3834 		assert(win != NULL);
   3835 
   3836 		/* clear the window*/
   3837 		if (!(win->_winArgs & RGFW_NO_CPU_RENDER)) {
   3838 #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)
   3839 			#ifdef RGFW_OSMESA
   3840 			RGFW_OSMesa_reorganize();
   3841 			#endif
   3842 			RGFW_area area = RGFW_bufferSize;
   3843 
   3844 #ifndef RGFW_X11_DONT_CONVERT_BGR
   3845 			win->src.bitmap->data = (char*) win->buffer;
   3846 			u32 x, y;
   3847 			for (y = 0; y < (u32)win->r.h; y++) {
   3848 				for (x = 0; x < (u32)win->r.w; x++) {
   3849 					u32 index = (y * 4 * area.w) + x * 4;
   3850 
   3851 					u8 red = win->src.bitmap->data[index];
   3852 					win->src.bitmap->data[index] = win->buffer[index + 2];
   3853 					win->src.bitmap->data[index + 2] = red;
   3854 
   3855 				}
   3856 			}
   3857 #endif	
   3858 			XPutImage(win->src.display, (Window) win->src.window, win->src.gc, win->src.bitmap, 0, 0, 0, 0, RGFW_bufferSize.w, RGFW_bufferSize.h);
   3859 #endif
   3860 		}
   3861 
   3862 		if (!(win->_winArgs & RGFW_NO_GPU_RENDER)) {
   3863 			#ifdef RGFW_EGL
   3864 					eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface);
   3865 			#elif defined(RGFW_OPENGL)
   3866 					glXSwapBuffers((Display*) win->src.display, (Window) win->src.window);
   3867 			#endif
   3868 		}
   3869 	}
   3870 
   3871 	#if !defined(RGFW_EGL)	
   3872 	void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) {
   3873 		assert(win != NULL);
   3874 
   3875 		#if defined(RGFW_OPENGL)	
   3876 		((PFNGLXSWAPINTERVALEXTPROC) glXGetProcAddress((GLubyte*) "glXSwapIntervalEXT"))((Display*) win->src.display, (Window) win->src.window, swapInterval);
   3877 		#else
   3878 		RGFW_UNUSED(swapInterval);
   3879 		#endif
   3880 	}
   3881 	#endif
   3882 
   3883 
   3884 	void RGFW_window_close(RGFW_window* win) {
   3885 		/* ungrab pointer if it was grabbed */
   3886 		if (win->_winArgs & RGFW_HOLD_MOUSE) 
   3887 			XUngrabPointer(win->src.display, CurrentTime);
   3888 			
   3889 		assert(win != NULL);
   3890 #ifdef RGFW_EGL
   3891 		RGFW_closeEGL(win);
   3892 #endif
   3893 
   3894 #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)
   3895 		if (win->buffer != NULL) {
   3896 			XDestroyImage((XImage*) win->src.bitmap);
   3897 			XFreeGC(win->src.display, win->src.gc);
   3898 		}
   3899 #endif
   3900 
   3901 		if ((Display*) win->src.display) {
   3902 #ifdef RGFW_OPENGL
   3903 			glXDestroyContext((Display*) win->src.display, win->src.ctx);
   3904 #endif
   3905 
   3906 			if (win == RGFW_root)
   3907 				RGFW_root = NULL;
   3908 
   3909 			if ((Drawable) win->src.window)
   3910 				XDestroyWindow((Display*) win->src.display, (Drawable) win->src.window); /*!< close the window*/
   3911 			
   3912 			XCloseDisplay((Display*) win->src.display); /*!< kill the display*/
   3913 		}
   3914 
   3915 #ifdef RGFW_ALLOC_DROPFILES
   3916 		{
   3917 			u32 i;
   3918 			for (i = 0; i < RGFW_MAX_DROPS; i++)
   3919 				RGFW_FREE(win->event.droppedFiles[i]);
   3920 
   3921 
   3922 			RGFW_FREE(win->event.droppedFiles);
   3923 		}
   3924 #endif
   3925 
   3926 		RGFW_windowsOpen--;
   3927 #if !defined(RGFW_NO_X11_CURSOR_PRELOAD) && !defined(RGFW_NO_X11_CURSOR)
   3928 		if (X11Cursorhandle != NULL && RGFW_windowsOpen <= 0) {
   3929 			dlclose(X11Cursorhandle);
   3930 
   3931 			X11Cursorhandle = NULL;
   3932 		}
   3933 #endif
   3934 #if !defined(RGFW_NO_X11_XI_PRELOAD)
   3935 		if (X11Xihandle != NULL && RGFW_windowsOpen <= 0) {
   3936 			dlclose(X11Xihandle);
   3937 
   3938 			X11Xihandle = NULL;
   3939 		}
   3940 #endif
   3941 
   3942 		if (RGFW_libxshape != NULL && RGFW_windowsOpen <= 0) {
   3943 			dlclose(RGFW_libxshape);
   3944 			RGFW_libxshape = NULL;
   3945 		}
   3946 
   3947 		if (RGFW_windowsOpen <= 0) {
   3948 			if (RGFW_eventWait_forceStop[0] || RGFW_eventWait_forceStop[1]){
   3949 				close(RGFW_eventWait_forceStop[0]);
   3950 				close(RGFW_eventWait_forceStop[1]);
   3951 			}
   3952 
   3953 			u8 i;
   3954 			for (i = 0; i < RGFW_joystickCount; i++)
   3955 				close(RGFW_joysticks[i]);
   3956 		}
   3957 
   3958 		/* set cleared display / window to NULL for error checking */
   3959 		win->src.display = (Display*) 0;
   3960 		win->src.window = (Window) 0;
   3961 
   3962 		RGFW_FREE(win); /*!< free collected window data */
   3963 	}
   3964 	
   3965 
   3966 /* 
   3967 	End of X11 linux / unix defines
   3968 */
   3969 
   3970 #endif /* RGFW_X11 */
   3971 
   3972 
   3973 /* wayland or X11 defines*/
   3974 #if defined(RGFW_WAYLAND) || defined(RGFW_X11)
   3975 #include <fcntl.h>
   3976 #include <poll.h>
   3977 #include <unistd.h>
   3978 	u16 RGFW_registerJoystickF(RGFW_window* win, char* file) {
   3979 		assert(win != NULL);
   3980 
   3981 #ifdef __linux__
   3982 
   3983 		i32 js = open(file, O_RDONLY);
   3984 
   3985 		if (js && RGFW_joystickCount < 4) {
   3986 			RGFW_joystickCount++;
   3987 
   3988 			RGFW_joysticks[RGFW_joystickCount - 1] = open(file, O_RDONLY);
   3989 
   3990 			u8 i;
   3991 			for (i = 0; i < 16; i++)
   3992 				RGFW_jsPressed[RGFW_joystickCount - 1][i] = 0;
   3993 
   3994 		}
   3995 
   3996 		else {
   3997 #ifdef RGFW_PRINT_ERRORS
   3998 			RGFW_error = 1;
   3999 			fprintf(stderr, "Error RGFW_registerJoystickF : Cannot open file %s\n", file);
   4000 #endif
   4001 		}
   4002 
   4003 		return RGFW_joystickCount - 1;
   4004 #endif
   4005 	}
   4006 	
   4007 	u16 RGFW_registerJoystick(RGFW_window* win, i32 jsNumber) {
   4008 		assert(win != NULL);
   4009 
   4010 #ifdef __linux__
   4011 		char file[15];
   4012 		sprintf(file, "/dev/input/js%i", jsNumber);
   4013 
   4014 		return RGFW_registerJoystickF(win, file);
   4015 #endif
   4016 	}
   4017 	
   4018 	void RGFW_stopCheckEvents(void) { 
   4019 		RGFW_eventWait_forceStop[2] = 1;
   4020 		while (1) {
   4021 			const char byte = 0;
   4022 			const ssize_t result = write(RGFW_eventWait_forceStop[1], &byte, 1);
   4023 			if (result == 1 || result == -1)
   4024 				break;
   4025 		}
   4026 	}
   4027 
   4028 	void RGFW_window_eventWait(RGFW_window* win, i32 waitMS) {
   4029 		if (waitMS == 0)
   4030 			return;
   4031 		
   4032 		u8 i;
   4033 
   4034 		if (RGFW_eventWait_forceStop[0] == 0 || RGFW_eventWait_forceStop[1] == 0) {
   4035 			if (pipe(RGFW_eventWait_forceStop) != -1) {
   4036 				fcntl(RGFW_eventWait_forceStop[0], F_GETFL, 0);
   4037 				fcntl(RGFW_eventWait_forceStop[0], F_GETFD, 0);
   4038 				fcntl(RGFW_eventWait_forceStop[1], F_GETFL, 0);
   4039 				fcntl(RGFW_eventWait_forceStop[1], F_GETFD, 0);
   4040 			}
   4041 		}
   4042 
   4043 		struct pollfd fds[] = {
   4044 			#ifdef RGFW_WAYLAND
   4045 			{ wl_display_get_fd(win->src.display), POLLIN, 0 },
   4046 			#else
   4047 			{ ConnectionNumber(win->src.display), POLLIN, 0 },
   4048 			#endif
   4049 			{ RGFW_eventWait_forceStop[0], POLLIN, 0 },
   4050 			#ifdef __linux__ /* blank space for 4 joystick files*/
   4051 			{ -1, POLLIN, 0 }, {-1, POLLIN, 0 }, {-1, POLLIN, 0 },  {-1, POLLIN, 0} 
   4052 			#endif
   4053 		};
   4054 
   4055 		u8 index = 2;
   4056 		
   4057 		#if defined(__linux__)
   4058 			for (i = 0; i < RGFW_joystickCount; i++) {
   4059 				if (RGFW_joysticks[i] == 0)
   4060 					continue;
   4061 
   4062 				fds[index].fd = RGFW_joysticks[i];
   4063 				index++;
   4064 			}
   4065 		#endif
   4066 
   4067 
   4068 		u64 start = RGFW_getTimeNS();
   4069 
   4070 		#ifdef RGFW_WAYLAND
   4071 		while (wl_display_dispatch(win->src.display) <= 0 && waitMS >= -1) {
   4072 		#else
   4073 		while (XPending(win->src.display) == 0 && waitMS >= -1) {
   4074 		#endif
   4075 			if (poll(fds, index, waitMS) <= 0)
   4076 				break;
   4077 
   4078 			if (waitMS > 0) {
   4079 				waitMS -= (RGFW_getTimeNS() - start) / 1e+6;
   4080 			}
   4081 		}
   4082 
   4083 		/* drain any data in the stop request */
   4084 		if (RGFW_eventWait_forceStop[2]) {	
   4085 			char data[64];
   4086 			(void)!read(RGFW_eventWait_forceStop[0], data, sizeof(data));
   4087 			
   4088 			RGFW_eventWait_forceStop[2] = 0;
   4089 		}
   4090 	}
   4091 
   4092 	u64 RGFW_getTimeNS(void) { 
   4093 		struct timespec ts = { 0 };
   4094 		clock_gettime(1, &ts);
   4095 		unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec;
   4096 
   4097 		return nanoSeconds;
   4098 	}
   4099 
   4100 	u64 RGFW_getTime(void) {
   4101 		struct timespec ts = { 0 };
   4102 		clock_gettime(1, &ts);
   4103 		unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec;
   4104 
   4105 		return (double)(nanoSeconds) * 1e-9;
   4106 	}
   4107 #endif /* end of wayland or X11 time defines*/
   4108 
   4109 
   4110 /*
   4111 
   4112 	Start of Wayland defines
   4113 
   4114 
   4115 */
   4116 
   4117 #ifdef RGFW_WAYLAND
   4118 /*
   4119 Wayland TODO:
   4120 - fix RGFW_keyPressed lock state
   4121 
   4122 	RGFW_windowMoved, 		the window was moved (by the user)
   4123 	RGFW_windowResized  	the window was resized (by the user), [on webASM this means the browser was resized]
   4124 	RGFW_windowRefresh	 	The window content needs to be refreshed
   4125 
   4126 	RGFW_dnd 				a file has been dropped into the window
   4127 	RGFW_dnd_init
   4128 
   4129 - window args:
   4130 	#define RGFW_NO_RESIZE	 			the window cannot be resized  by the user
   4131 	#define RGFW_ALLOW_DND     			the window supports drag and drop
   4132 	#define RGFW_SCALE_TO_MONITOR 			scale the window to the screen 
   4133 
   4134 - other missing functions functions ("TODO wayland") (~30 functions)
   4135 - fix buffer rendering weird behavior
   4136 */
   4137 	#include <errno.h>
   4138 	#include <unistd.h>
   4139 	#include <sys/mman.h>
   4140 	#include <xkbcommon/xkbcommon.h>
   4141 	#include <xkbcommon/xkbcommon-keysyms.h>
   4142 	#include <dirent.h>
   4143 	#include <linux/kd.h> 
   4144 	#include <wayland-cursor.h>
   4145 
   4146 RGFW_window* RGFW_key_win = NULL;
   4147 
   4148 void RGFW_eventPipe_push(RGFW_window* win, RGFW_Event event) {
   4149 	if (win == NULL) {
   4150 		win = RGFW_key_win;
   4151 
   4152 		if (win == NULL) return;
   4153 	}
   4154 	
   4155 	if (win->src.eventLen >= (i32)(sizeof(win->src.events) / sizeof(win->src.events[0])))
   4156 		return;
   4157 
   4158 	win->src.events[win->src.eventLen] = event;
   4159 	win->src.eventLen += 1;
   4160 }
   4161 
   4162 RGFW_Event RGFW_eventPipe_pop(RGFW_window* win) {
   4163 	RGFW_Event ev;
   4164 	ev.type = 0;
   4165 	
   4166 	if (win->src.eventLen > -1)
   4167 		win->src.eventLen -= 1;
   4168 	
   4169 	if (win->src.eventLen >= 0)  
   4170 		ev = win->src.events[win->src.eventLen];
   4171 
   4172 	return ev;	
   4173 }
   4174 
   4175 /* wayland global garbage (wayland bad, X11 is fine (ish) (not really)) */
   4176 #include "xdg-shell.h"
   4177 #include "xdg-decoration-unstable-v1.h"
   4178 
   4179 struct xdg_wm_base *xdg_wm_base;
   4180 struct wl_compositor* RGFW_compositor = NULL;
   4181 struct wl_shm* shm = NULL;
   4182 struct wl_shell* RGFW_shell = NULL;
   4183 static struct wl_seat *seat = NULL;
   4184 static struct xkb_context *xkb_context;
   4185 static struct xkb_keymap *keymap = NULL;
   4186 static struct xkb_state *xkb_state = NULL;
   4187 enum zxdg_toplevel_decoration_v1_mode client_preferred_mode, RGFW_current_mode;
   4188 static struct zxdg_decoration_manager_v1 *decoration_manager = NULL;
   4189 
   4190 struct wl_cursor_theme* RGFW_wl_cursor_theme = NULL;
   4191 struct wl_surface* RGFW_cursor_surface = NULL;
   4192 struct wl_cursor_image* RGFW_cursor_image = NULL;
   4193 
   4194 static void xdg_wm_base_ping_handler(void *data,
   4195         struct xdg_wm_base *wm_base, uint32_t serial)
   4196 {
   4197 	RGFW_UNUSED(data);
   4198     xdg_wm_base_pong(wm_base, serial);
   4199 }
   4200 
   4201 static const struct xdg_wm_base_listener xdg_wm_base_listener = {
   4202     .ping = xdg_wm_base_ping_handler,
   4203 };
   4204 
   4205 b8 RGFW_wl_configured = 0;
   4206 
   4207 static void xdg_surface_configure_handler(void *data,
   4208         struct xdg_surface *xdg_surface, uint32_t serial)
   4209 {	
   4210 	RGFW_UNUSED(data);
   4211     xdg_surface_ack_configure(xdg_surface, serial);
   4212 	#ifdef RGFW_DEBUG
   4213 	printf("Surface configured\n");
   4214 	#endif
   4215 	RGFW_wl_configured = 1;
   4216 }
   4217 
   4218 static const struct xdg_surface_listener xdg_surface_listener = {
   4219     .configure = xdg_surface_configure_handler,
   4220 };
   4221 
   4222 static void xdg_toplevel_configure_handler(void *data,
   4223         struct xdg_toplevel *toplevel, int32_t width, int32_t height,
   4224         struct wl_array *states)
   4225 {
   4226 	RGFW_UNUSED(data); RGFW_UNUSED(toplevel); RGFW_UNUSED(states)
   4227     fprintf(stderr, "XDG toplevel configure: %dx%d\n", width, height);
   4228 }
   4229 
   4230 static void xdg_toplevel_close_handler(void *data,
   4231         struct xdg_toplevel *toplevel)
   4232 {
   4233 	RGFW_UNUSED(data);
   4234 	RGFW_window* win = (RGFW_window*)xdg_toplevel_get_user_data(toplevel);
   4235 	if (win == NULL)
   4236 		win = RGFW_key_win;
   4237 	
   4238 	RGFW_Event ev;
   4239 	ev.type = RGFW_quit;
   4240 
   4241 	RGFW_eventPipe_push(win, ev); 	
   4242 
   4243 	RGFW_windowQuitCallback(win);
   4244 }
   4245 
   4246 static void shm_format_handler(void *data,
   4247         struct wl_shm *shm, uint32_t format)
   4248 {
   4249 	RGFW_UNUSED(data); RGFW_UNUSED(shm);
   4250     fprintf(stderr, "Format %d\n", format);
   4251 }
   4252 
   4253 static const struct wl_shm_listener shm_listener = {
   4254     .format = shm_format_handler,
   4255 };
   4256 
   4257 static const struct xdg_toplevel_listener xdg_toplevel_listener = {
   4258     .configure = xdg_toplevel_configure_handler,
   4259     .close = xdg_toplevel_close_handler,
   4260 };
   4261 
   4262 RGFW_window* RGFW_mouse_win = NULL;
   4263 
   4264 static void pointer_enter(void *data, struct wl_pointer *pointer, uint32_t serial, struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y) {
   4265 	RGFW_UNUSED(data); RGFW_UNUSED(pointer); RGFW_UNUSED(serial); RGFW_UNUSED(surface_x); RGFW_UNUSED(surface_y);
   4266 	RGFW_window* win = (RGFW_window*)wl_surface_get_user_data(surface);
   4267 	RGFW_mouse_win = win;
   4268 
   4269 	RGFW_Event ev;
   4270 	ev.type = RGFW_mouseEnter;
   4271 	ev.point = win->event.point;
   4272 
   4273 	RGFW_eventPipe_push(win, ev); 	
   4274 
   4275 	RGFW_mouseNotifyCallBack(win, win->event.point, RGFW_TRUE);
   4276 }
   4277 static void pointer_leave(void *data, struct wl_pointer *pointer, uint32_t serial, struct wl_surface *surface) {
   4278 	RGFW_UNUSED(data); RGFW_UNUSED(pointer); RGFW_UNUSED(serial); RGFW_UNUSED(surface);
   4279 	RGFW_window* win = (RGFW_window*)wl_surface_get_user_data(surface);
   4280 	if (RGFW_mouse_win == win)
   4281 		RGFW_mouse_win = NULL;
   4282 	
   4283 	RGFW_Event ev;
   4284 	ev.type = RGFW_mouseLeave;
   4285 	ev.point = win->event.point;
   4286 	RGFW_eventPipe_push(win, ev);
   4287 
   4288 	RGFW_mouseNotifyCallBack(win,  win->event.point, RGFW_FALSE);
   4289 }
   4290 static void pointer_motion(void *data, struct wl_pointer *pointer, uint32_t time, wl_fixed_t x, wl_fixed_t y) {
   4291 	RGFW_UNUSED(data); RGFW_UNUSED(pointer); RGFW_UNUSED(time); RGFW_UNUSED(x); RGFW_UNUSED(y);
   4292 
   4293 	assert(RGFW_mouse_win != NULL);
   4294 	
   4295 	RGFW_Event ev;
   4296 	ev.type = RGFW_mousePosChanged;
   4297 	ev.point = RGFW_POINT(wl_fixed_to_double(x), wl_fixed_to_double(y));
   4298 	RGFW_eventPipe_push(RGFW_mouse_win, ev);
   4299 	
   4300 	RGFW_mousePosCallback(RGFW_mouse_win, RGFW_POINT(wl_fixed_to_double(x), wl_fixed_to_double(y)));
   4301 }
   4302 static void pointer_button(void *data, struct wl_pointer *pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state) {
   4303 	RGFW_UNUSED(data); RGFW_UNUSED(pointer); RGFW_UNUSED(time); RGFW_UNUSED(serial);
   4304 	assert(RGFW_mouse_win != NULL);
   4305 
   4306 	u32 b = (button - 0x110) + 1;
   4307 
   4308 	/* flip right and middle button codes */
   4309 	if (b == 2) b = 3;
   4310 	else if (b == 3) b = 2;
   4311 	
   4312 	RGFW_mouseButtons[b].prev = RGFW_mouseButtons[b].current;
   4313 	RGFW_mouseButtons[b].current = state;
   4314 
   4315 	RGFW_Event ev;
   4316 	ev.type = RGFW_mouseButtonPressed + state;
   4317 	ev.button = b;
   4318 	RGFW_eventPipe_push(RGFW_mouse_win, ev);
   4319 
   4320 	RGFW_mouseButtonCallback(RGFW_mouse_win, b, 0, state);
   4321 }
   4322 static void pointer_axis(void *data, struct wl_pointer *pointer, uint32_t time, uint32_t axis, wl_fixed_t value) {
   4323 	RGFW_UNUSED(data); RGFW_UNUSED(pointer); RGFW_UNUSED(time);  RGFW_UNUSED(axis);
   4324 	assert(RGFW_mouse_win != NULL); 
   4325 
   4326 	double scroll = wl_fixed_to_double(value);
   4327 
   4328 	RGFW_Event ev;
   4329 	ev.type = RGFW_mouseButtonPressed;
   4330 	ev.button = RGFW_mouseScrollUp + (scroll < 0);
   4331 	RGFW_eventPipe_push(RGFW_mouse_win, ev);
   4332 
   4333 	RGFW_mouseButtonCallback(RGFW_mouse_win, RGFW_mouseScrollUp + (scroll < 0), scroll, 1);
   4334 }
   4335 
   4336 void RGFW_doNothing(void) { }
   4337 static struct wl_pointer_listener pointer_listener = (struct wl_pointer_listener){&pointer_enter, &pointer_leave, &pointer_motion, &pointer_button, &pointer_axis, (void*)&RGFW_doNothing, (void*)&RGFW_doNothing, (void*)&RGFW_doNothing, (void*)&RGFW_doNothing, (void*)&RGFW_doNothing, (void*)&RGFW_doNothing};
   4338 
   4339 static void keyboard_keymap (void *data, struct wl_keyboard *keyboard, uint32_t format, int32_t fd, uint32_t size) {
   4340 	RGFW_UNUSED(data); RGFW_UNUSED(keyboard); RGFW_UNUSED(format);
   4341 
   4342 	char *keymap_string = mmap (NULL, size, PROT_READ, MAP_SHARED, fd, 0);
   4343 	xkb_keymap_unref (keymap);
   4344 	keymap = xkb_keymap_new_from_string (xkb_context, keymap_string, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
   4345 	
   4346 	munmap (keymap_string, size);
   4347 	close (fd);
   4348 	xkb_state_unref (xkb_state);
   4349 	xkb_state = xkb_state_new (keymap);
   4350 }
   4351 static void keyboard_enter (void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface, struct wl_array *keys) { 
   4352 	RGFW_UNUSED(data); RGFW_UNUSED(keyboard); RGFW_UNUSED(serial); RGFW_UNUSED(keys);
   4353 
   4354 	RGFW_key_win = (RGFW_window*)wl_surface_get_user_data(surface);
   4355 
   4356 	RGFW_Event ev;
   4357 	ev.type = RGFW_focusIn;
   4358 	ev.inFocus = RGFW_TRUE;
   4359 	RGFW_key_win->event.inFocus = RGFW_TRUE;
   4360 
   4361 	RGFW_eventPipe_push((RGFW_window*)RGFW_mouse_win, ev);
   4362 
   4363 	RGFW_focusCallback(RGFW_key_win, RGFW_TRUE);
   4364 }
   4365 static void keyboard_leave (void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface) { 
   4366 	RGFW_UNUSED(data); RGFW_UNUSED(keyboard); RGFW_UNUSED(serial);
   4367 
   4368 	RGFW_window* win = (RGFW_window*)wl_surface_get_user_data(surface);
   4369 	if (RGFW_key_win == win)
   4370 		RGFW_key_win = NULL;	
   4371 
   4372 	RGFW_Event ev;
   4373 	ev.type = RGFW_focusOut;
   4374 	ev.inFocus = RGFW_FALSE;
   4375 	win->event.inFocus = RGFW_FALSE;
   4376 	RGFW_eventPipe_push(win, ev);
   4377 
   4378 	RGFW_focusCallback(win, RGFW_FALSE);
   4379 }
   4380 static void keyboard_key (void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state) {
   4381 	RGFW_UNUSED(data); RGFW_UNUSED(keyboard); RGFW_UNUSED(serial); RGFW_UNUSED(time); 
   4382 
   4383 	assert(RGFW_key_win != NULL);
   4384 
   4385 	xkb_keysym_t keysym = xkb_state_key_get_one_sym (xkb_state, key+8);
   4386 	char name[16];
   4387 	xkb_keysym_get_name(keysym, name, 16);
   4388 
   4389 	u32 RGFW_key = RGFW_apiKeyCodeToRGFW(key);
   4390 	RGFW_keyboard[RGFW_key].prev = RGFW_keyboard[RGFW_key].current;
   4391 	RGFW_keyboard[RGFW_key].current = state;
   4392 	RGFW_Event ev;
   4393 	ev.type = RGFW_keyPressed + state;
   4394 	ev.keyCode = RGFW_key;
   4395 	strcpy(ev.keyName, name);
   4396 	ev.repeat = RGFW_isHeld(RGFW_key_win, RGFW_key);
   4397 	RGFW_eventPipe_push(RGFW_key_win, ev);
   4398 	
   4399 	RGFW_updateLockState(RGFW_key_win, xkb_keymap_mod_get_index(keymap, "Lock"), xkb_keymap_mod_get_index(keymap, "Mod2"));
   4400 
   4401 	RGFW_keyCallback(RGFW_key_win, RGFW_key, name, RGFW_key_win->event.lockState, state);
   4402 }
   4403 static void keyboard_modifiers (void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group) {
   4404 	RGFW_UNUSED(data); RGFW_UNUSED(keyboard); RGFW_UNUSED(serial); RGFW_UNUSED(time); 
   4405 	xkb_state_update_mask (xkb_state, mods_depressed, mods_latched, mods_locked, 0, 0, group);
   4406 }
   4407 static struct wl_keyboard_listener keyboard_listener = {&keyboard_keymap, &keyboard_enter, &keyboard_leave, &keyboard_key, &keyboard_modifiers, (void*)&RGFW_doNothing};
   4408 
   4409 static void seat_capabilities (void *data, struct wl_seat *seat, uint32_t capabilities) {
   4410 	RGFW_UNUSED(data);
   4411 
   4412 	if (capabilities & WL_SEAT_CAPABILITY_POINTER) {
   4413 		struct wl_pointer *pointer = wl_seat_get_pointer (seat);
   4414 		wl_pointer_add_listener (pointer, &pointer_listener, NULL);
   4415 	}
   4416 	if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) {
   4417 		struct wl_keyboard *keyboard = wl_seat_get_keyboard (seat);
   4418 		wl_keyboard_add_listener (keyboard, &keyboard_listener, NULL);
   4419 	}
   4420 }
   4421 static struct wl_seat_listener seat_listener = {&seat_capabilities, (void*)&RGFW_doNothing};
   4422 
   4423 static void wl_global_registry_handler(void *data,
   4424 		struct wl_registry *registry, uint32_t id, const char *interface,
   4425 		uint32_t version)
   4426 {
   4427 	RGFW_UNUSED(data); RGFW_UNUSED(version);
   4428 
   4429     if (strcmp(interface, "wl_compositor") == 0) {
   4430 		RGFW_compositor = wl_registry_bind(registry,
   4431 			id, &wl_compositor_interface, 4);
   4432 	} else if (strcmp(interface, "xdg_wm_base") == 0) {
   4433 	xdg_wm_base = wl_registry_bind(registry,
   4434 		id, &xdg_wm_base_interface, 1);
   4435 	} else if (strcmp(interface, zxdg_decoration_manager_v1_interface.name) == 0) {
   4436 		decoration_manager = wl_registry_bind(registry, id, &zxdg_decoration_manager_v1_interface, 1);
   4437     } else if (strcmp(interface, "wl_shm") == 0) {
   4438         shm = wl_registry_bind(registry,
   4439             id, &wl_shm_interface, 1);
   4440         wl_shm_add_listener(shm, &shm_listener, NULL);
   4441 	} else if (strcmp(interface,"wl_seat") == 0) {
   4442 		seat = wl_registry_bind(registry, id, &wl_seat_interface, 1);
   4443 		wl_seat_add_listener(seat, &seat_listener, NULL);
   4444 	}
   4445 
   4446 	else {
   4447 		#ifdef RGFW_DEBUG
   4448 		printf("did not register %s\n", interface);
   4449 		return;
   4450 		#endif
   4451 	}
   4452 
   4453 		#ifdef RGFW_DEBUG
   4454 		printf("registered %s\n", interface);
   4455 		#endif
   4456 }
   4457 
   4458 static void wl_global_registry_remove(void *data, struct wl_registry *registry, uint32_t name) { RGFW_UNUSED(data); RGFW_UNUSED(registry); RGFW_UNUSED(name); }
   4459 static const struct wl_registry_listener registry_listener = {
   4460 	.global = wl_global_registry_handler,
   4461 	.global_remove = wl_global_registry_remove,
   4462 };
   4463 
   4464 static const char *get_mode_name(enum zxdg_toplevel_decoration_v1_mode mode) {
   4465 	switch (mode) {
   4466 	case ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE:
   4467 		return "client-side decorations";
   4468 	case ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE:
   4469 		return "server-side decorations";
   4470 	}
   4471 	abort();
   4472 }
   4473 
   4474 
   4475 static void decoration_handle_configure(void *data,
   4476 		struct zxdg_toplevel_decoration_v1 *decoration,
   4477 		enum zxdg_toplevel_decoration_v1_mode mode) {
   4478 	RGFW_UNUSED(data); RGFW_UNUSED(decoration);
   4479 	printf("Using %s\n", get_mode_name(mode));
   4480 	RGFW_current_mode = mode;
   4481 }
   4482 
   4483 static const struct zxdg_toplevel_decoration_v1_listener decoration_listener = {
   4484 	.configure = decoration_handle_configure,
   4485 };
   4486 
   4487 static void randname(char *buf) {
   4488 	struct timespec ts;
   4489 	clock_gettime(CLOCK_REALTIME, &ts);
   4490 	long r = ts.tv_nsec;
   4491 	for (int i = 0; i < 6; ++i) {
   4492 		buf[i] = 'A'+(r&15)+(r&16)*2;
   4493 		r >>= 5;
   4494 	}
   4495 }
   4496 
   4497 static int anonymous_shm_open(void) {
   4498 	char name[] = "/RGFW-wayland-XXXXXX";
   4499 	int retries = 100;
   4500 
   4501 	do {
   4502 		randname(name + strlen(name) - 6);
   4503 
   4504 		--retries;
   4505 		// shm_open guarantees that O_CLOEXEC is set
   4506 		int fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL, 0600);
   4507 		if (fd >= 0) {
   4508 			shm_unlink(name);
   4509 			return fd;
   4510 		}
   4511 	} while (retries > 0 && errno == EEXIST);
   4512 
   4513 	return -1;
   4514 }
   4515 
   4516 int create_shm_file(off_t size) {
   4517 	int fd = anonymous_shm_open();
   4518 	if (fd < 0) {
   4519 		return fd;
   4520 	}
   4521 
   4522 	if (ftruncate(fd, size) < 0) {
   4523 		close(fd);
   4524 		return -1;
   4525 	}
   4526 
   4527 	return fd;
   4528 }
   4529 
   4530 static void wl_surface_frame_done(void *data, struct wl_callback *cb, uint32_t time) {
   4531 	#ifdef RGFW_BUFFER
   4532 		RGFW_window* win = (RGFW_window*)data;
   4533 		if ((win->_winArgs & RGFW_NO_CPU_RENDER))
   4534 			return;	
   4535 		
   4536 		#ifndef RGFW_X11_DONT_CONVERT_BGR
   4537 			u32 x, y;
   4538 			for (y = 0; y < (u32)win->r.h; y++) {
   4539 				for (x = 0; x < (u32)win->r.w; x++) {
   4540 					u32 index = (y * 4 * win->r.w) + x * 4;
   4541 
   4542 					u8 red = win->buffer[index];
   4543 					win->buffer[index] = win->buffer[index + 2];
   4544 					win->buffer[index + 2] = red;
   4545 
   4546 				}
   4547 			}
   4548 		#endif	
   4549 	
   4550 		wl_surface_attach(win->src.surface, win->src.wl_buffer, 0, 0);
   4551 		wl_surface_damage_buffer(win->src.surface, 0, 0, win->r.w, win->r.h);
   4552 		wl_surface_commit(win->src.surface);
   4553 	#endif
   4554 }
   4555 
   4556 static const struct wl_callback_listener wl_surface_frame_listener = {
   4557 	.done = wl_surface_frame_done,
   4558 };
   4559 
   4560 
   4561 	/* normal wayland RGFW stuff */
   4562 	
   4563 	RGFW_area RGFW_getScreenSize(void) {
   4564 		RGFW_area area = {};
   4565 
   4566 		if (RGFW_root != NULL)
   4567 			/* this isn't right but it's here for buffers */
   4568 			area = RGFW_AREA(RGFW_root->r.w, RGFW_root->r.h);
   4569 		
   4570 		/* TODO wayland */
   4571 		return area;
   4572 	}
   4573 	
   4574 	void RGFW_releaseCursor(RGFW_window* win) {
   4575 		RGFW_UNUSED(win);
   4576 	}
   4577 
   4578 	void RGFW_captureCursor(RGFW_window* win, RGFW_rect r) {
   4579 		RGFW_UNUSED(win); RGFW_UNUSED(r);
   4580 
   4581 		/* TODO wayland */
   4582 	}
   4583 
   4584 
   4585 	RGFWDEF void RGFW_init_buffer(RGFW_window* win);
   4586 	void RGFW_init_buffer(RGFW_window* win) {
   4587 		#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)	
   4588 			size_t size = win->r.w * win->r.h * 4;
   4589 			int fd = create_shm_file(size);
   4590 			if (fd < 0) {
   4591 				fprintf(stderr, "Failed to create a buffer. size: %ld\n", size);
   4592 				exit(1);
   4593 			}
   4594 
   4595 			win->buffer = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
   4596 			if (win->buffer == MAP_FAILED) {
   4597 				fprintf(stderr, "mmap failed!\n");
   4598 				close(fd);
   4599 				exit(1);
   4600 			}
   4601 
   4602 			struct wl_shm_pool* pool = wl_shm_create_pool(shm, fd, size);
   4603 			win->src.wl_buffer = wl_shm_pool_create_buffer(pool, 0, win->r.w, win->r.h, win->r.w * 4,
   4604 				WL_SHM_FORMAT_ARGB8888);
   4605 			wl_shm_pool_destroy(pool);
   4606 
   4607 			close(fd);
   4608 			
   4609 			wl_surface_attach(win->src.surface, win->src.wl_buffer, 0, 0);
   4610 			wl_surface_commit(win->src.surface);
   4611 
   4612 			u8 color[] = {0x00, 0x00, 0x00, 0xFF};
   4613 
   4614 			size_t i;
   4615 			for (i = 0; i < size; i += 4) {
   4616 				memcpy(&win->buffer[i], color, 4);
   4617 			}
   4618 	
   4619 			#if defined(RGFW_OSMESA)
   4620 					win->src.ctx = OSMesaCreateContext(OSMESA_RGBA, NULL);
   4621 					OSMesaMakeCurrent(win->src.ctx, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h);
   4622 			#endif
   4623 		#else
   4624 		RGFW_UNUSED(win);
   4625 		#endif
   4626 	}
   4627    
   4628 
   4629 	RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) {
   4630 		RGFW_window* win = RGFW_window_basic_init(rect, args);
   4631 		
   4632 		fprintf(stderr, "Warning: RGFW Wayland support is experimental\n");
   4633 		
   4634 		win->src.display = wl_display_connect(NULL);
   4635 		if (win->src.display == NULL) {
   4636 			#ifdef RGFW_DEBUG
   4637 				fprintf(stderr, "Failed to load Wayland display\n");
   4638 			#endif
   4639 			return NULL;
   4640 		}
   4641 		
   4642 		struct wl_registry *registry = wl_display_get_registry(win->src.display);
   4643 		wl_registry_add_listener(registry, &registry_listener, NULL);
   4644 			
   4645 		wl_display_dispatch(win->src.display);
   4646 		wl_display_roundtrip(win->src.display);
   4647 
   4648 		if (RGFW_compositor == NULL) {
   4649 			#ifdef RGFW_DEBUG
   4650 				fprintf(stderr, "Can't find compositor.\n");
   4651 			#endif
   4652 			
   4653 			return NULL;
   4654 		}
   4655 		
   4656 		if (RGFW_wl_cursor_theme == NULL) {
   4657 			RGFW_wl_cursor_theme = wl_cursor_theme_load(NULL, 24, shm);
   4658 			RGFW_cursor_surface = wl_compositor_create_surface(RGFW_compositor); 
   4659 			
   4660 			struct wl_cursor* cursor = wl_cursor_theme_get_cursor(RGFW_wl_cursor_theme, "left_ptr");
   4661 			RGFW_cursor_image = cursor->images[0];
   4662 			struct wl_buffer* cursor_buffer	= wl_cursor_image_get_buffer(RGFW_cursor_image);
   4663 
   4664 			wl_surface_attach(RGFW_cursor_surface, cursor_buffer, 0, 0);
   4665 			wl_surface_commit(RGFW_cursor_surface); 
   4666 		}
   4667 
   4668 		if (RGFW_root == NULL)
   4669 			xdg_wm_base_add_listener(xdg_wm_base, &xdg_wm_base_listener, NULL);
   4670 		
   4671 		xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
   4672 
   4673 		win->src.surface = wl_compositor_create_surface(RGFW_compositor);
   4674 		wl_surface_set_user_data(win->src.surface, win);
   4675 
   4676 		win->src.xdg_surface = xdg_wm_base_get_xdg_surface(xdg_wm_base, win->src.surface);
   4677 		xdg_surface_add_listener(win->src.xdg_surface, &xdg_surface_listener, NULL);
   4678 	
   4679 		xdg_wm_base_set_user_data(xdg_wm_base, win);
   4680 
   4681 		win->src.xdg_toplevel = xdg_surface_get_toplevel(win->src.xdg_surface);
   4682 		xdg_toplevel_set_user_data(win->src.xdg_toplevel, win);
   4683 		xdg_toplevel_set_title(win->src.xdg_toplevel, name);
   4684 		xdg_toplevel_add_listener(win->src.xdg_toplevel, &xdg_toplevel_listener, NULL);
   4685 
   4686 		xdg_surface_set_window_geometry(win->src.xdg_surface, 0, 0, win->r.w, win->r.h);
   4687 		
   4688 		if (!(args & RGFW_NO_BORDER)) {
   4689 			win->src.decoration = zxdg_decoration_manager_v1_get_toplevel_decoration(
   4690 						decoration_manager, win->src.xdg_toplevel);
   4691 		}
   4692 
   4693 		if (args & RGFW_CENTER) {
   4694 			RGFW_area screenR = RGFW_getScreenSize();
   4695 			RGFW_window_move(win, RGFW_POINT((screenR.w - win->r.w) / 2, (screenR.h - win->r.h) / 2));
   4696 		}
   4697 
   4698 		if (args & RGFW_OPENGL_SOFTWARE)
   4699 			setenv("LIBGL_ALWAYS_SOFTWARE", "1", 1);
   4700 
   4701 		wl_display_roundtrip(win->src.display);
   4702 
   4703 		wl_surface_commit(win->src.surface);
   4704 		
   4705 		/* wait for the surface to be configured */
   4706 		while (wl_display_dispatch(win->src.display) != -1 && !RGFW_wl_configured) { }
   4707 		
   4708 		
   4709 		#ifdef RGFW_OPENGL
   4710 			if ((args & RGFW_NO_INIT_API) == 0) {
   4711 				win->src.window = wl_egl_window_create(win->src.surface, win->r.w, win->r.h);
   4712 				RGFW_createOpenGLContext(win);
   4713 			}
   4714 		#endif	
   4715 
   4716 		RGFW_init_buffer(win);
   4717 
   4718 		struct wl_callback* callback = wl_surface_frame(win->src.surface);
   4719    		wl_callback_add_listener(callback, &wl_surface_frame_listener, win);	
   4720 		wl_surface_commit(win->src.surface);
   4721 
   4722 		if (args & RGFW_HIDE_MOUSE) {
   4723 			RGFW_window_showMouse(win, 0);
   4724 		}
   4725 		
   4726 		if (RGFW_root == NULL) {
   4727 			RGFW_root = win;
   4728 		}
   4729 		
   4730 		win->src.eventIndex = 0;
   4731 		win->src.eventLen = 0;
   4732 		
   4733 		return win;
   4734 	}
   4735 
   4736 	RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) {
   4737 		if (win->_winArgs & RGFW_WINDOW_HIDE)
   4738 			return NULL;
   4739 
   4740 		if (win->src.eventIndex == 0) {
   4741 			if (wl_display_roundtrip(win->src.display) == -1) {
   4742 				return NULL;
   4743 			}
   4744 			RGFW_resetKey();
   4745 		}
   4746 
   4747 		#ifdef __linux__
   4748 			RGFW_Event* event = RGFW_linux_updateJoystick(win);
   4749 			if (event != NULL)
   4750 				return event;
   4751 		#endif
   4752 		
   4753 		if (win->src.eventLen == 0) {
   4754 				return NULL;
   4755 		}
   4756 
   4757 		RGFW_Event ev = RGFW_eventPipe_pop(win);
   4758 		
   4759 		if (ev.type ==  0 || win->event.type == RGFW_quit) {
   4760 			return NULL;
   4761 		}
   4762         
   4763 		ev.frameTime = win->event.frameTime;
   4764         ev.frameTime2 = win->event.frameTime2;
   4765         ev.inFocus = win->event.inFocus;
   4766         win->event = ev;
   4767 		
   4768 		return &win->event;
   4769 	}
   4770 
   4771 
   4772 	void RGFW_window_resize(RGFW_window* win, RGFW_area a) {
   4773 		RGFW_UNUSED(win); RGFW_UNUSED(a);
   4774 
   4775 		/* TODO wayland */
   4776 	}
   4777 
   4778 	void RGFW_window_move(RGFW_window* win, RGFW_point v) {
   4779 		RGFW_UNUSED(win); RGFW_UNUSED(v);
   4780 
   4781 		/* TODO wayland */
   4782 	}
   4783 
   4784 	void RGFW_window_setIcon(RGFW_window* win, u8* src, RGFW_area a, i32 channels) {
   4785 		RGFW_UNUSED(win); RGFW_UNUSED(src); RGFW_UNUSED(a); RGFW_UNUSED(channels)
   4786 		/* TODO wayland */
   4787 	}
   4788 
   4789 	void RGFW_window_moveMouse(RGFW_window* win, RGFW_point v) {
   4790 		RGFW_UNUSED(win); RGFW_UNUSED(v);
   4791 
   4792 		/* TODO wayland */
   4793 	}
   4794 
   4795 	void RGFW_window_showMouse(RGFW_window* win, i8 show) {
   4796 		RGFW_UNUSED(win);
   4797 
   4798 		if (show) {
   4799 
   4800 		}
   4801 		else {
   4802 			
   4803 		}
   4804 
   4805 		/* TODO wayland */
   4806 	}
   4807 
   4808 	b8 RGFW_window_isMaximized(RGFW_window* win) {
   4809 		RGFW_UNUSED(win);
   4810 		/* TODO wayland */
   4811 		return 0;
   4812 	}
   4813 
   4814 	b8 RGFW_window_isMinimized(RGFW_window* win) {
   4815 		RGFW_UNUSED(win);
   4816 		/* TODO wayland */
   4817 		return 0;
   4818 	}
   4819 
   4820 	b8 RGFW_window_isHidden(RGFW_window* win) {
   4821 		RGFW_UNUSED(win);
   4822 		/* TODO wayland */
   4823 		return 0;
   4824 	}
   4825 
   4826 	b8 RGFW_window_isFullscreen(RGFW_window* win) {
   4827 		RGFW_UNUSED(win);
   4828 		/* TODO wayland */
   4829 		return 0;
   4830 	}
   4831 
   4832 	RGFW_point RGFW_window_getMousePoint(RGFW_window* win) {
   4833 		RGFW_UNUSED(win);
   4834 		/* TODO wayland */
   4835 		return RGFW_POINT(0, 0);
   4836 	}
   4837 			
   4838 	RGFW_point RGFW_getGlobalMousePoint(void) {
   4839 		/* TODO wayland */
   4840 		return RGFW_POINT(0, 0);
   4841 	}
   4842 			
   4843 	void RGFW_window_show(RGFW_window* win) {
   4844 		//wl_surface_attach(win->src.surface, win->rc., 0, 0);
   4845         wl_surface_commit(win->src.surface);
   4846 		
   4847 		if (win->_winArgs & RGFW_WINDOW_HIDE)
   4848 			win->_winArgs ^= RGFW_WINDOW_HIDE;
   4849 	}
   4850 		
   4851 	void RGFW_window_hide(RGFW_window* win) {
   4852 		wl_surface_attach(win->src.surface, NULL, 0, 0);
   4853         wl_surface_commit(win->src.surface);
   4854 		win->_winArgs |= RGFW_WINDOW_HIDE;
   4855 	}
   4856 		
   4857 	void RGFW_window_setMouseDefault(RGFW_window* win) {
   4858 		RGFW_UNUSED(win);
   4859 	
   4860 		RGFW_window_setMouseStandard(win, RGFW_MOUSE_NORMAL);
   4861 	}
   4862 		
   4863 	void RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse) {
   4864 		RGFW_UNUSED(win);
   4865 		
   4866 		static const char* iconStrings[] = { "left_ptr", "left_ptr", "text", "cross", "pointer", "e-resize", "n-resize", "nw-resize", "ne-resize", "all-resize", "not-allowed" };
   4867 
   4868 		struct wl_cursor* cursor = wl_cursor_theme_get_cursor(RGFW_wl_cursor_theme, iconStrings[mouse]);
   4869 		RGFW_cursor_image = cursor->images[0];
   4870 		struct wl_buffer* cursor_buffer	= wl_cursor_image_get_buffer(RGFW_cursor_image);
   4871 
   4872 		wl_surface_attach(RGFW_cursor_surface, cursor_buffer, 0, 0);
   4873 		wl_surface_commit(RGFW_cursor_surface); 
   4874 	}
   4875 		
   4876 	void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels) {
   4877 		RGFW_UNUSED(win); RGFW_UNUSED(image); RGFW_UNUSED(a); RGFW_UNUSED(channels)
   4878 		//struct wl_cursor* cursor = wl_cursor_theme_get_cursor(RGFW_wl_cursor_theme, iconStrings[mouse]);
   4879 		//RGFW_cursor_image = image;
   4880 		struct wl_buffer* cursor_buffer	= wl_cursor_image_get_buffer(RGFW_cursor_image);
   4881 
   4882 		wl_surface_attach(RGFW_cursor_surface, cursor_buffer, 0, 0);
   4883 		wl_surface_commit(RGFW_cursor_surface); 
   4884 	}
   4885 		
   4886 	void RGFW_window_setName(RGFW_window* win, char* name) {
   4887 		xdg_toplevel_set_title(win->src.xdg_toplevel, name);
   4888 	}
   4889 		
   4890 	void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) {
   4891 		RGFW_UNUSED(win); RGFW_UNUSED(passthrough);
   4892 
   4893 	/* TODO wayland */
   4894 	}
   4895 		
   4896 	void RGFW_window_setBorder(RGFW_window* win, b8 border) {
   4897 		RGFW_UNUSED(win); RGFW_UNUSED(border);
   4898 
   4899 	/* TODO wayland */
   4900 	}
   4901 		
   4902 	void RGFW_window_restore(RGFW_window* win) {
   4903 		RGFW_UNUSED(win);
   4904 
   4905 	/* TODO wayland */
   4906 	}
   4907 		
   4908 	void RGFW_window_minimize(RGFW_window* win) {
   4909 		RGFW_UNUSED(win);
   4910 
   4911 	/* TODO wayland */
   4912 	}
   4913 		
   4914 	void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) {
   4915 		RGFW_UNUSED(win); RGFW_UNUSED(a);
   4916 
   4917 	/* TODO wayland */
   4918 	}
   4919 		
   4920 	void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) {
   4921 		RGFW_UNUSED(win); RGFW_UNUSED(a);
   4922 
   4923 	/* TODO wayland */
   4924 	}
   4925 
   4926 	RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) {
   4927 		RGFW_monitor m = {};
   4928 		RGFW_UNUSED(win);
   4929 		RGFW_UNUSED(m);
   4930 		/* TODO wayland */
   4931 
   4932 		return m;
   4933 	}
   4934 
   4935 
   4936 	#ifndef RGFW_EGL
   4937 	void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) { RGFW_UNUSED(win); RGFW_UNUSED(swapInterval); }
   4938 	#endif
   4939 
   4940 	void RGFW_window_swapBuffers(RGFW_window* win) {
   4941 		assert(win != NULL);
   4942 
   4943 		/* clear the window*/
   4944 		#ifdef RGFW_BUFFER	
   4945 			wl_surface_frame_done(win, NULL, 0);
   4946 			if (!(win->_winArgs & RGFW_NO_GPU_RENDER)) 
   4947 		#endif
   4948 		{
   4949 		#ifdef RGFW_OPENGL
   4950 			eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface);
   4951 		#endif
   4952 		}
   4953 		
   4954 		wl_display_flush(win->src.display);
   4955 	}
   4956 
   4957 	void RGFW_window_close(RGFW_window* win) {
   4958 		#ifdef RGFW_EGL
   4959 			RGFW_closeEGL(win);
   4960 		#endif
   4961 
   4962 		if (RGFW_root == win) {
   4963 			RGFW_root = NULL;
   4964 		}
   4965 
   4966 		xdg_toplevel_destroy(win->src.xdg_toplevel);
   4967 		xdg_surface_destroy(win->src.xdg_surface);
   4968 		wl_surface_destroy(win->src.surface);
   4969 
   4970 		#ifdef RGFW_BUFFER
   4971 		wl_buffer_destroy(win->src.wl_buffer);
   4972 		#endif
   4973 		
   4974 		wl_display_disconnect(win->src.display);
   4975 		RGFW_FREE(win);
   4976 	}
   4977 
   4978 	RGFW_monitor RGFW_getPrimaryMonitor(void) {
   4979 		/* TODO wayland */
   4980 
   4981 		return (RGFW_monitor){};
   4982 	}
   4983 						
   4984 	RGFW_monitor* RGFW_getMonitors(void) {
   4985 		/* TODO wayland */
   4986 
   4987 		return NULL;
   4988 	}
   4989 
   4990 	void RGFW_writeClipboard(const char* text, u32 textLen) {
   4991 		RGFW_UNUSED(text); RGFW_UNUSED(textLen);
   4992 
   4993 		/* TODO wayland */
   4994 	}
   4995 
   4996 	char* RGFW_readClipboard(size_t* size) {
   4997 		RGFW_UNUSED(size);
   4998 
   4999 		/* TODO wayland */
   5000 
   5001 		return NULL;
   5002 	}
   5003 #endif /* RGFW_WAYLAND */
   5004 
   5005 /* 
   5006 	End of Wayland defines
   5007 */
   5008 
   5009 
   5010 /*
   5011 
   5012 	Start of Windows defines
   5013 
   5014 
   5015 */
   5016 
   5017 #ifdef RGFW_WINDOWS
   5018 	#define WIN32_LEAN_AND_MEAN
   5019 	#define OEMRESOURCE
   5020 	#include <windows.h>
   5021 	
   5022 	#include <processthreadsapi.h>
   5023 	#include <wchar.h>
   5024 	#include <locale.h>
   5025 	#include <windowsx.h>
   5026 	#include <shellapi.h>
   5027 	#include <shellscalingapi.h>
   5028 
   5029 	#include <winuser.h>
   5030 
   5031 	__declspec(dllimport) int __stdcall WideCharToMultiByte( UINT CodePage, DWORD dwFlags, const WCHAR* lpWideCharStr, int cchWideChar,  LPSTR lpMultiByteStr, int cbMultiByte, LPCCH lpDefaultChar, LPBOOL lpUsedDefaultChar);
   5032 	
   5033 	#ifndef RGFW_NO_XINPUT
   5034 	typedef DWORD (WINAPI * PFN_XInputGetState)(DWORD,XINPUT_STATE*);
   5035 	PFN_XInputGetState XInputGetStateSRC = NULL;
   5036 	#define XInputGetState XInputGetStateSRC
   5037 
   5038 	typedef DWORD (WINAPI * PFN_XInputGetKeystroke)(DWORD, DWORD, PXINPUT_KEYSTROKE);
   5039 	PFN_XInputGetKeystroke XInputGetKeystrokeSRC = NULL;
   5040 	#define XInputGetKeystroke XInputGetKeystrokeSRC
   5041 
   5042 	static HMODULE RGFW_XInput_dll = NULL;
   5043 	#endif
   5044 
   5045 	u32 RGFW_mouseIconSrc[] = {OCR_NORMAL, OCR_NORMAL, OCR_IBEAM, OCR_CROSS, OCR_HAND, OCR_SIZEWE, OCR_SIZENS, OCR_SIZENWSE, OCR_SIZENESW, OCR_SIZEALL, OCR_NO};
   5046 
   5047 	char* createUTF8FromWideStringWin32(const WCHAR* source);
   5048 
   5049 #define GL_FRONT				0x0404
   5050 #define GL_BACK					0x0405
   5051 #define GL_LEFT					0x0406
   5052 #define GL_RIGHT				0x0407
   5053 
   5054 #if defined(RGFW_OSMESA) && defined(RGFW_LINK_OSMESA)
   5055 
   5056 	typedef void (GLAPIENTRY* PFN_OSMesaDestroyContext)(OSMesaContext);
   5057 	typedef i32(GLAPIENTRY* PFN_OSMesaMakeCurrent)(OSMesaContext, void*, int, int, int);
   5058 	typedef OSMesaContext(GLAPIENTRY* PFN_OSMesaCreateContext)(GLenum, OSMesaContext);
   5059 
   5060 	PFN_OSMesaMakeCurrent OSMesaMakeCurrentSource;
   5061 	PFN_OSMesaCreateContext OSMesaCreateContextSource;
   5062 	PFN_OSMesaDestroyContext OSMesaDestroyContextSource;
   5063 
   5064 #define OSMesaCreateContext OSMesaCreateContextSource
   5065 #define OSMesaMakeCurrent OSMesaMakeCurrentSource
   5066 #define OSMesaDestroyContext OSMesaDestroyContextSource
   5067 #endif
   5068 
   5069 	typedef int (*PFN_wglGetSwapIntervalEXT)(void);
   5070 	PFN_wglGetSwapIntervalEXT wglGetSwapIntervalEXTSrc = NULL;
   5071 #define wglGetSwapIntervalEXT wglGetSwapIntervalEXTSrc
   5072 
   5073 
   5074 	void* RGFWjoystickApi = NULL;
   5075 
   5076 	/* these two wgl functions need to be preloaded */
   5077 	typedef HGLRC (WINAPI *PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC hdc, HGLRC hglrc, const int *attribList);
   5078 	PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL;
   5079 
   5080 	/* defines for creating ARB attributes */
   5081 #define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000
   5082 #define WGL_CONTEXT_MAJOR_VERSION_ARB             0x2091
   5083 #define WGL_CONTEXT_MINOR_VERSION_ARB             0x2092
   5084 #define WGL_DRAW_TO_WINDOW_ARB                    0x2001
   5085 #define WGL_ACCELERATION_ARB                      0x2003
   5086 #define WGL_NO_ACCELERATION_ARB 0x2025
   5087 #define WGL_DOUBLE_BUFFER_ARB                     0x2011
   5088 #define WGL_COLOR_BITS_ARB                        0x2014
   5089 #define WGL_RED_BITS_ARB 0x2015
   5090 #define WGL_RED_SHIFT_ARB 0x2016
   5091 #define WGL_GREEN_BITS_ARB 0x2017
   5092 #define WGL_GREEN_SHIFT_ARB 0x2018
   5093 #define WGL_BLUE_BITS_ARB 0x2019
   5094 #define WGL_BLUE_SHIFT_ARB 0x201a
   5095 #define WGL_ALPHA_BITS_ARB 0x201b
   5096 #define WGL_ALPHA_SHIFT_ARB 0x201c
   5097 #define WGL_ACCUM_BITS_ARB 0x201d
   5098 #define WGL_ACCUM_RED_BITS_ARB 0x201e
   5099 #define WGL_ACCUM_GREEN_BITS_ARB 0x201f
   5100 #define WGL_ACCUM_BLUE_BITS_ARB 0x2020
   5101 #define WGL_ACCUM_ALPHA_BITS_ARB 0x2021
   5102 #define WGL_DEPTH_BITS_ARB 0x2022
   5103 #define WGL_AUX_BUFFERS_ARB 0x2024
   5104 #define WGL_STEREO_ARB 0x2012
   5105 #define WGL_DEPTH_BITS_ARB                        0x2022
   5106 #define WGL_STENCIL_BITS_ARB 					  0x2023
   5107 #define WGL_FULL_ACCELERATION_ARB                 0x2027
   5108 #define WGL_CONTEXT_FLAGS_ARB                     0x2094
   5109 #define WGL_CONTEXT_PROFILE_MASK_ARB              0x9126
   5110 #define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
   5111 #define WGL_SAMPLE_BUFFERS_ARB               0x2041
   5112 #define WGL_SAMPLES_ARB 0x2042
   5113 #define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20a9
   5114 
   5115 #ifndef RGFW_EGL
   5116 static HMODULE wglinstance = NULL;
   5117 #endif
   5118 
   5119 #ifdef RGFW_WGL_LOAD
   5120 	typedef HGLRC(WINAPI* PFN_wglCreateContext)(HDC);
   5121 	typedef BOOL(WINAPI* PFN_wglDeleteContext)(HGLRC);
   5122 	typedef PROC(WINAPI* PFN_wglGetProcAddress)(LPCSTR);
   5123 	typedef BOOL(WINAPI* PFN_wglMakeCurrent)(HDC, HGLRC);
   5124 	typedef HDC(WINAPI* PFN_wglGetCurrentDC)();
   5125 	typedef HGLRC(WINAPI* PFN_wglGetCurrentContext)();
   5126 
   5127 	PFN_wglCreateContext wglCreateContextSRC;
   5128 	PFN_wglDeleteContext wglDeleteContextSRC;
   5129 	PFN_wglGetProcAddress wglGetProcAddressSRC;
   5130 	PFN_wglMakeCurrent wglMakeCurrentSRC;
   5131 	PFN_wglGetCurrentDC wglGetCurrentDCSRC;
   5132 	PFN_wglGetCurrentContext wglGetCurrentContextSRC;
   5133 
   5134 	#define wglCreateContext wglCreateContextSRC
   5135 	#define wglDeleteContext wglDeleteContextSRC
   5136 	#define wglGetProcAddress wglGetProcAddressSRC
   5137 	#define wglMakeCurrent wglMakeCurrentSRC
   5138 
   5139 	#define wglGetCurrentDC wglGetCurrentDCSRC
   5140 	#define wglGetCurrentContext wglGetCurrentContextSRC
   5141 #endif
   5142 
   5143 #ifdef RGFW_OPENGL
   5144 	void* RGFW_getProcAddress(const char* procname) { 
   5145 		void* proc = (void*) wglGetProcAddress(procname);
   5146 		if (proc)
   5147 			return proc;
   5148 
   5149 		return (void*) GetProcAddress(wglinstance, procname); 
   5150 	}
   5151 
   5152 	typedef HRESULT (APIENTRY* PFNWGLCHOOSEPIXELFORMATARBPROC)(HDC hdc, const int* piAttribIList, const FLOAT* pfAttribFList, UINT nMaxFormats, int* piFormats, UINT* nNumFormats);
   5153 	static PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = NULL;
   5154 #endif
   5155 
   5156 	RGFW_window RGFW_eventWindow;
   5157 
   5158 	LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
   5159 		switch (message) {
   5160 		case WM_MOVE:
   5161 			RGFW_eventWindow.r.x = LOWORD(lParam);
   5162 			RGFW_eventWindow.r.y = HIWORD(lParam);
   5163 			RGFW_eventWindow.src.window = hWnd;
   5164 			return DefWindowProcA(hWnd, message, wParam, lParam);
   5165 		case WM_SIZE:
   5166 			RGFW_eventWindow.r.w = LOWORD(lParam);
   5167 			RGFW_eventWindow.r.h = HIWORD(lParam);
   5168 			RGFW_eventWindow.src.window = hWnd;
   5169 			return DefWindowProcA(hWnd, message, wParam, lParam); // Call DefWindowProc after handling
   5170 		default:
   5171 			return DefWindowProcA(hWnd, message, wParam, lParam);
   5172 		}
   5173 	}
   5174 	
   5175 	#ifndef RGFW_NO_DPI
   5176 	static HMODULE RGFW_Shcore_dll = NULL;
   5177 	typedef HRESULT (WINAPI * PFN_GetDpiForMonitor)(HMONITOR,MONITOR_DPI_TYPE,UINT*,UINT*);
   5178 	PFN_GetDpiForMonitor GetDpiForMonitorSRC = NULL;
   5179 	#define GetDpiForMonitor GetDpiForMonitorSRC
   5180 	#endif
   5181 
   5182 	__declspec(dllimport) u32 __stdcall timeBeginPeriod(u32 uPeriod);
   5183 	
   5184 	#ifndef RGFW_NO_XINPUT
   5185 	void RGFW_loadXInput(void) {
   5186 		u32 i;
   5187 		static const char* names[] = { 
   5188 			"xinput1_4.dll",
   5189 			"xinput1_3.dll",
   5190 			"xinput9_1_0.dll",
   5191 			"xinput1_2.dll",
   5192 			"xinput1_1.dll"
   5193 		};
   5194 
   5195 		for (i = 0; i < sizeof(names) / sizeof(const char*);  i++) {
   5196 			RGFW_XInput_dll = LoadLibraryA(names[i]);
   5197 
   5198 			if (RGFW_XInput_dll) {
   5199 				XInputGetStateSRC = (PFN_XInputGetState)(void*)GetProcAddress(RGFW_XInput_dll, "XInputGetState");
   5200 			
   5201 				if (XInputGetStateSRC == NULL)
   5202 					printf("Failed to load XInputGetState");
   5203 			}
   5204 		}
   5205 	}
   5206 	#endif
   5207 
   5208 	RGFWDEF void RGFW_init_buffer(RGFW_window* win);
   5209 	void RGFW_init_buffer(RGFW_window* win) {
   5210 #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)
   5211 	if (RGFW_bufferSize.w == 0 && RGFW_bufferSize.h == 0)
   5212 		RGFW_bufferSize = RGFW_getScreenSize();
   5213 	
   5214 	BITMAPV5HEADER bi = { 0 };
   5215 	ZeroMemory(&bi, sizeof(bi));
   5216 	bi.bV5Size = sizeof(bi);
   5217 	bi.bV5Width = RGFW_bufferSize.w;
   5218 	bi.bV5Height = -((LONG) RGFW_bufferSize.h);
   5219 	bi.bV5Planes = 1;
   5220 	bi.bV5BitCount = 32;
   5221 	bi.bV5Compression = BI_BITFIELDS;
   5222 	bi.bV5BlueMask = 0x00ff0000;
   5223 	bi.bV5GreenMask = 0x0000ff00;
   5224 	bi.bV5RedMask = 0x000000ff;
   5225 	bi.bV5AlphaMask = 0xff000000;
   5226 
   5227 	win->src.bitmap = CreateDIBSection(win->src.hdc,
   5228 		(BITMAPINFO*) &bi,
   5229 		DIB_RGB_COLORS,
   5230 		(void**) &win->buffer,
   5231 		NULL,
   5232 		(DWORD) 0);
   5233 	
   5234 	win->src.hdcMem = CreateCompatibleDC(win->src.hdc);
   5235 
   5236 	#if defined(RGFW_OSMESA)
   5237 	win->src.ctx = OSMesaCreateContext(OSMESA_RGBA, NULL);
   5238 	OSMesaMakeCurrent(win->src.ctx, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h);
   5239 	#endif
   5240 #else
   5241 RGFW_UNUSED(win); /*!< if buffer rendering is not being used */
   5242 #endif
   5243 	}
   5244 
   5245 	void RGFW_window_setDND(RGFW_window* win, b8 allow) {
   5246 		DragAcceptFiles(win->src.window, allow);
   5247 	}
   5248 
   5249 	void RGFW_releaseCursor(RGFW_window* win) {
   5250 		RGFW_UNUSED(win);
   5251 		ClipCursor(NULL);
   5252     	const RAWINPUTDEVICE id = { 0x01, 0x02, RIDEV_REMOVE, NULL };
   5253     	RegisterRawInputDevices(&id, 1, sizeof(id));	
   5254 	}
   5255 
   5256 	void RGFW_captureCursor(RGFW_window* win, RGFW_rect rect) {
   5257 		RGFW_UNUSED(win); RGFW_UNUSED(rect);
   5258 
   5259 		RECT clipRect;
   5260 		GetClientRect(win->src.window, &clipRect);
   5261 		ClientToScreen(win->src.window, (POINT*) &clipRect.left);
   5262 		ClientToScreen(win->src.window, (POINT*) &clipRect.right);
   5263 		ClipCursor(&clipRect);
   5264 
   5265 	    const RAWINPUTDEVICE id = { 0x01, 0x02, 0, win->src.window };
   5266 		RegisterRawInputDevices(&id, 1, sizeof(id));
   5267 	}
   5268 
   5269 	RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) {
   5270 		#ifndef RGFW_NO_XINPUT
   5271 		if (RGFW_XInput_dll == NULL)
   5272 			RGFW_loadXInput();
   5273 		#endif
   5274 
   5275 		#ifndef RGFW_NO_DPI
   5276 		if (RGFW_Shcore_dll == NULL) {
   5277 			RGFW_Shcore_dll = LoadLibraryA("shcore.dll");
   5278 			GetDpiForMonitorSRC = (PFN_GetDpiForMonitor)(void*)GetProcAddress(RGFW_Shcore_dll, "GetDpiForMonitor");
   5279 			SetProcessDPIAware();
   5280 		}
   5281 		#endif
   5282 
   5283 		if (wglinstance == NULL) {
   5284 			wglinstance = LoadLibraryA("opengl32.dll");
   5285 #ifdef RGFW_WGL_LOAD
   5286 			wglCreateContextSRC = (PFN_wglCreateContext) GetProcAddress(wglinstance, "wglCreateContext");
   5287 			wglDeleteContextSRC = (PFN_wglDeleteContext) GetProcAddress(wglinstance, "wglDeleteContext");
   5288 			wglGetProcAddressSRC = (PFN_wglGetProcAddress) GetProcAddress(wglinstance, "wglGetProcAddress");
   5289 			wglMakeCurrentSRC = (PFN_wglMakeCurrent) GetProcAddress(wglinstance, "wglMakeCurrent");
   5290 			wglGetCurrentDCSRC = (PFN_wglGetCurrentDC) GetProcAddress(wglinstance, "wglGetCurrentDC");
   5291 			wglGetCurrentContextSRC = (PFN_wglGetCurrentContext) GetProcAddress(wglinstance, "wglGetCurrentContext");
   5292 #endif
   5293 		}
   5294 	
   5295 		if (name[0] == 0) name = (char*) " ";
   5296 
   5297 		RGFW_eventWindow.r = RGFW_RECT(-1, -1, -1, -1);
   5298 		RGFW_eventWindow.src.window = NULL;
   5299 
   5300 		RGFW_window* win = RGFW_window_basic_init(rect, args);
   5301 
   5302 		win->src.maxSize = RGFW_AREA(0, 0);
   5303 		win->src.minSize = RGFW_AREA(0, 0);
   5304 
   5305 
   5306 		HINSTANCE inh = GetModuleHandleA(NULL);
   5307 
   5308 		#ifndef __cplusplus
   5309 		WNDCLASSA Class = { 0 }; /*!< Setup the Window class. */
   5310 		#else
   5311 		WNDCLASSA Class = { };
   5312 		#endif
   5313 
   5314 		if (RGFW_className == NULL)
   5315 			RGFW_className = (char*)name;
   5316 
   5317 		Class.lpszClassName = RGFW_className;
   5318 		Class.hInstance = inh;
   5319 		Class.hCursor = LoadCursor(NULL, IDC_ARROW);
   5320 		Class.lpfnWndProc = WndProc;
   5321 
   5322 		RegisterClassA(&Class);
   5323 
   5324 		DWORD window_style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
   5325 
   5326 		RECT windowRect, clientRect;
   5327 
   5328 		if (!(args & RGFW_NO_BORDER)) {
   5329 			window_style |= WS_CAPTION | WS_SYSMENU | WS_BORDER | WS_MINIMIZEBOX;
   5330 
   5331 			if (!(args & RGFW_NO_RESIZE))
   5332 				window_style |= WS_SIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME;
   5333 		} else
   5334 			window_style |= WS_POPUP | WS_VISIBLE | WS_SYSMENU | WS_MINIMIZEBOX;
   5335 
   5336 		HWND dummyWin = CreateWindowA(Class.lpszClassName, name, window_style, win->r.x, win->r.y, win->r.w, win->r.h, 0, 0, inh, 0);
   5337 
   5338 		GetWindowRect(dummyWin, &windowRect);
   5339 		GetClientRect(dummyWin, &clientRect);
   5340 
   5341 		win->src.hOffset = (windowRect.bottom - windowRect.top) - (clientRect.bottom - clientRect.top);
   5342 		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);
   5343 
   5344 		if (args & RGFW_ALLOW_DND) {
   5345 			win->_winArgs |= RGFW_ALLOW_DND;
   5346 			RGFW_window_setDND(win, 1);
   5347 		}
   5348 		win->src.hdc = GetDC(win->src.window);
   5349 
   5350 		if ((args & RGFW_NO_INIT_API) == 0) {
   5351 #ifdef RGFW_DIRECTX
   5352 		assert(FAILED(CreateDXGIFactory(&__uuidof(IDXGIFactory), (void**) &RGFW_dxInfo.pFactory)) == 0);
   5353 
   5354 		if (FAILED(RGFW_dxInfo.pFactory->lpVtbl->EnumAdapters(RGFW_dxInfo.pFactory, 0, &RGFW_dxInfo.pAdapter))) {
   5355 			fprintf(stderr, "Failed to enumerate DXGI adapters\n");
   5356 			RGFW_dxInfo.pFactory->lpVtbl->Release(RGFW_dxInfo.pFactory);
   5357 			return NULL;
   5358 		}
   5359 
   5360 		D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_0 };
   5361 
   5362 		if (FAILED(D3D11CreateDevice(RGFW_dxInfo.pAdapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, 0, featureLevels, 1, D3D11_SDK_VERSION, &RGFW_dxInfo.pDevice, NULL, &RGFW_dxInfo.pDeviceContext))) {
   5363 			fprintf(stderr, "Failed to create Direct3D device\n");
   5364 			RGFW_dxInfo.pAdapter->lpVtbl->Release(RGFW_dxInfo.pAdapter);
   5365 			RGFW_dxInfo.pFactory->lpVtbl->Release(RGFW_dxInfo.pFactory);
   5366 			return NULL;
   5367 		}
   5368 
   5369 		DXGI_SWAP_CHAIN_DESC swapChainDesc = { 0 };
   5370 		swapChainDesc.BufferCount = 1;
   5371 		swapChainDesc.BufferDesc.Width = win->r.w;
   5372 		swapChainDesc.BufferDesc.Height = win->r.h;
   5373 		swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
   5374 		swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
   5375 		swapChainDesc.OutputWindow = win->src.window;
   5376 		swapChainDesc.SampleDesc.Count = 1;
   5377 		swapChainDesc.SampleDesc.Quality = 0;
   5378 		swapChainDesc.Windowed = TRUE;
   5379 		RGFW_dxInfo.pFactory->lpVtbl->CreateSwapChain(RGFW_dxInfo.pFactory, (IUnknown*) RGFW_dxInfo.pDevice, &swapChainDesc, &win->src.swapchain);
   5380 
   5381 		ID3D11Texture2D* pBackBuffer;
   5382 		win->src.swapchain->lpVtbl->GetBuffer(win->src.swapchain, 0, &__uuidof(ID3D11Texture2D), (LPVOID*) &pBackBuffer);
   5383 		RGFW_dxInfo.pDevice->lpVtbl->CreateRenderTargetView(RGFW_dxInfo.pDevice, (ID3D11Resource*) pBackBuffer, NULL, &win->src.renderTargetView);
   5384 		pBackBuffer->lpVtbl->Release(pBackBuffer);
   5385 
   5386 		D3D11_TEXTURE2D_DESC depthStencilDesc = { 0 };
   5387 		depthStencilDesc.Width = win->r.w;
   5388 		depthStencilDesc.Height = win->r.h;
   5389 		depthStencilDesc.MipLevels = 1;
   5390 		depthStencilDesc.ArraySize = 1;
   5391 		depthStencilDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
   5392 		depthStencilDesc.SampleDesc.Count = 1;
   5393 		depthStencilDesc.SampleDesc.Quality = 0;
   5394 		depthStencilDesc.Usage = D3D11_USAGE_DEFAULT;
   5395 		depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
   5396 
   5397 		ID3D11Texture2D* pDepthStencilTexture = NULL;
   5398 		RGFW_dxInfo.pDevice->lpVtbl->CreateTexture2D(RGFW_dxInfo.pDevice, &depthStencilDesc, NULL, &pDepthStencilTexture);
   5399 
   5400 		D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc = { 0 };
   5401 		depthStencilViewDesc.Format = depthStencilDesc.Format;
   5402 		depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
   5403 		depthStencilViewDesc.Texture2D.MipSlice = 0;
   5404 
   5405 		RGFW_dxInfo.pDevice->lpVtbl->CreateDepthStencilView(RGFW_dxInfo.pDevice, (ID3D11Resource*) pDepthStencilTexture, &depthStencilViewDesc, &win->src.pDepthStencilView);
   5406 
   5407 		pDepthStencilTexture->lpVtbl->Release(pDepthStencilTexture);
   5408 
   5409 		RGFW_dxInfo.pDeviceContext->lpVtbl->OMSetRenderTargets(RGFW_dxInfo.pDeviceContext, 1, &win->src.renderTargetView, win->src.pDepthStencilView);
   5410 #endif
   5411 
   5412 #ifdef RGFW_OPENGL 
   5413 		HDC dummy_dc = GetDC(dummyWin);
   5414         
   5415         u32 pfd_flags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL; 
   5416         
   5417         //if (RGFW_DOUBLE_BUFFER)    
   5418              pfd_flags |= PFD_DOUBLEBUFFER;
   5419 		
   5420         PIXELFORMATDESCRIPTOR pfd = {
   5421 			sizeof(pfd),
   5422 			1, /* version */
   5423 			pfd_flags,
   5424 		    PFD_TYPE_RGBA, /* ipixel type */
   5425 			24, /* color bits */
   5426 			0, 0, 0, 0, 0, 0,
   5427 			8, /* alpha bits */
   5428 			0, 0, 0, 0, 0, 0,
   5429 			32, /* depth bits */
   5430 			8, /* stencil bits */ 
   5431 			0,
   5432 			PFD_MAIN_PLANE, /* Layer type */
   5433 			0, 0, 0, 0
   5434 		};
   5435 
   5436 		int pixel_format = ChoosePixelFormat(dummy_dc, &pfd);
   5437 		SetPixelFormat(dummy_dc, pixel_format, &pfd);
   5438 
   5439 		HGLRC dummy_context = wglCreateContext(dummy_dc);
   5440 		wglMakeCurrent(dummy_dc, dummy_context);
   5441 
   5442 		if (wglChoosePixelFormatARB == NULL) {
   5443 			wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC) (void*) wglGetProcAddress("wglCreateContextAttribsARB");
   5444 			wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC) (void*)wglGetProcAddress("wglChoosePixelFormatARB");
   5445 		}
   5446 
   5447 		wglMakeCurrent(dummy_dc, 0);
   5448 		wglDeleteContext(dummy_context);
   5449 		ReleaseDC(dummyWin, dummy_dc);
   5450 		
   5451 		/* try to create the pixel format we want for opengl and then try to create an opengl context for the specified version */ 
   5452 		if (wglCreateContextAttribsARB != NULL) {
   5453 			PIXELFORMATDESCRIPTOR pfd = {sizeof(pfd), 1, pfd_flags, PFD_TYPE_RGBA, 32, 8, PFD_MAIN_PLANE, 24, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
   5454 
   5455 			if (args & RGFW_OPENGL_SOFTWARE)
   5456 				pfd.dwFlags |= PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED;
   5457 
   5458 			if (wglChoosePixelFormatARB != NULL) {
   5459 				i32* pixel_format_attribs = (i32*)RGFW_initFormatAttribs(args & RGFW_OPENGL_SOFTWARE);
   5460 
   5461 				int pixel_format;
   5462 				UINT num_formats;
   5463 				wglChoosePixelFormatARB(win->src.hdc, pixel_format_attribs, 0, 1, &pixel_format, &num_formats);
   5464 				if (!num_formats) {
   5465 					printf("Failed to create a pixel format for WGL.\n");
   5466 				}
   5467 
   5468 				DescribePixelFormat(win->src.hdc, pixel_format, sizeof(pfd), &pfd);
   5469 				if (!SetPixelFormat(win->src.hdc, pixel_format, &pfd)) {
   5470 					printf("Failed to set the WGL pixel format.\n");
   5471 				}
   5472 			}
   5473 			
   5474 			/* create opengl/WGL context for the specified version */ 
   5475 			u32 index = 0;
   5476 			i32 attribs[40];
   5477 
   5478 			if (RGFW_profile == RGFW_GL_CORE) {
   5479 				SET_ATTRIB(WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB);
   5480 			}
   5481 			else {
   5482 				SET_ATTRIB(WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB);
   5483 			}
   5484 			
   5485 			if (RGFW_majorVersion || RGFW_minorVersion) {
   5486 				SET_ATTRIB(WGL_CONTEXT_MAJOR_VERSION_ARB, RGFW_majorVersion);
   5487 				SET_ATTRIB(WGL_CONTEXT_MINOR_VERSION_ARB, RGFW_minorVersion);
   5488 			}
   5489 
   5490 			SET_ATTRIB(0, 0);
   5491 
   5492 			win->src.ctx = (HGLRC)wglCreateContextAttribsARB(win->src.hdc, NULL, attribs);
   5493 		} else { /* fall back to a default context (probably opengl 2 or something) */
   5494 			fprintf(stderr, "Failed to create an accelerated OpenGL Context\n");
   5495 
   5496 			int pixel_format = ChoosePixelFormat(win->src.hdc, &pfd);
   5497 			SetPixelFormat(win->src.hdc, pixel_format, &pfd);
   5498 
   5499 			win->src.ctx = wglCreateContext(win->src.hdc);
   5500 		}
   5501 		
   5502 		wglMakeCurrent(win->src.hdc, win->src.ctx);
   5503 #endif
   5504 	}
   5505 
   5506 #ifdef RGFW_OSMESA
   5507 #ifdef RGFW_LINK_OSM ESA
   5508 		OSMesaMakeCurrentSource = (PFN_OSMesaMakeCurrent) GetProcAddress(win->src.hdc, "OSMesaMakeCurrent");
   5509 		OSMesaCreateContextSource = (PFN_OSMesaCreateContext) GetProcAddress(win->src.hdc, "OSMesaCreateContext");
   5510 		OSMesaDestroyContextSource = (PFN_OSMesaDestroyContext) GetProcAddress(win->src.hdc, "OSMesaDestroyContext");
   5511 #endif
   5512 #endif
   5513 
   5514 #ifdef RGFW_OPENGL
   5515 		if ((args & RGFW_NO_INIT_API) == 0) {
   5516 			ReleaseDC(win->src.window, win->src.hdc);
   5517 			win->src.hdc = GetDC(win->src.window);
   5518 			wglMakeCurrent(win->src.hdc, win->src.ctx);
   5519 		}
   5520 #endif
   5521 
   5522 		DestroyWindow(dummyWin);
   5523 		RGFW_init_buffer(win);
   5524 
   5525 
   5526 		#ifndef RGFW_NO_MONITOR
   5527 		if (args & RGFW_SCALE_TO_MONITOR)
   5528 			RGFW_window_scaleToMonitor(win);
   5529 		#endif
   5530 	
   5531 		if (args & RGFW_CENTER) {
   5532 			RGFW_area screenR = RGFW_getScreenSize();
   5533 			RGFW_window_move(win, RGFW_POINT((screenR.w - win->r.w) / 2, (screenR.h - win->r.h) / 2));
   5534 		}
   5535 
   5536 #ifdef RGFW_EGL
   5537 		if ((args & RGFW_NO_INIT_API) == 0)
   5538 			RGFW_createOpenGLContext(win);
   5539 #endif
   5540 
   5541 		if (args & RGFW_HIDE_MOUSE)
   5542 			RGFW_window_showMouse(win, 0);
   5543 
   5544 		if (args & RGFW_TRANSPARENT_WINDOW) {
   5545 			SetWindowLong(win->src.window, GWL_EXSTYLE, GetWindowLong(win->src.window, GWL_EXSTYLE) | WS_EX_LAYERED);
   5546 			SetLayeredWindowAttributes(win->src.window, RGB(255, 255, 255), RGFW_ALPHA, LWA_ALPHA);
   5547 		}
   5548 
   5549 		ShowWindow(win->src.window, SW_SHOWNORMAL);
   5550 		
   5551 		if (RGFW_root == NULL)
   5552 			RGFW_root = win;
   5553 		
   5554 		#ifdef RGFW_OPENGL
   5555 		else 
   5556 			wglShareLists(RGFW_root->src.ctx, win->src.ctx);
   5557 		#endif
   5558 
   5559 		return win;
   5560 	}
   5561 
   5562 	void RGFW_window_setBorder(RGFW_window* win, u8 border) {
   5563 		DWORD style = GetWindowLong(win->src.window, GWL_STYLE);
   5564 
   5565 		if (border == 0) {
   5566 			SetWindowLong(win->src.window, GWL_STYLE, style & ~WS_OVERLAPPEDWINDOW);
   5567 			SetWindowPos(
   5568 				win->src.window, HWND_TOP, 0, 0, 0, 0,
   5569 				SWP_NOZORDER | SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE
   5570 			);
   5571 		}
   5572 		else {
   5573 			SetWindowLong(win->src.window, GWL_STYLE, style | WS_OVERLAPPEDWINDOW);
   5574 			SetWindowPos(
   5575 				win->src.window, HWND_TOP, 0, 0, 0, 0,
   5576 				SWP_NOZORDER | SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE
   5577 			);
   5578 		}
   5579 	}
   5580 
   5581 
   5582 	RGFW_area RGFW_getScreenSize(void) {
   5583 		return RGFW_AREA(GetDeviceCaps(GetDC(NULL), HORZRES), GetDeviceCaps(GetDC(NULL), VERTRES));
   5584 	}
   5585 
   5586 	RGFW_point RGFW_getGlobalMousePoint(void) {
   5587 		POINT p;
   5588 		GetCursorPos(&p);
   5589 
   5590 		return RGFW_POINT(p.x, p.y);
   5591 	}
   5592 
   5593 	RGFW_point RGFW_window_getMousePoint(RGFW_window* win) {
   5594 		POINT p;
   5595 		GetCursorPos(&p);
   5596 		ScreenToClient(win->src.window, &p);
   5597 
   5598 		return RGFW_POINT(p.x, p.y);
   5599 	}
   5600 
   5601 	void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) {
   5602 		assert(win != NULL);
   5603 		win->src.minSize = a;
   5604 	}
   5605 
   5606 	void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) {
   5607 		assert(win != NULL);
   5608 		win->src.maxSize = a;
   5609 	}
   5610 
   5611 
   5612 	void RGFW_window_minimize(RGFW_window* win) {
   5613 		assert(win != NULL);
   5614 
   5615 		ShowWindow(win->src.window, SW_MINIMIZE);
   5616 	}
   5617 
   5618 	void RGFW_window_restore(RGFW_window* win) {
   5619 		assert(win != NULL);
   5620 
   5621 		ShowWindow(win->src.window, SW_RESTORE);
   5622 	}
   5623 
   5624 
   5625 	u8 RGFW_xinput2RGFW[] = {
   5626 		RGFW_JS_A, /* or PS X button */
   5627 		RGFW_JS_B, /* or PS circle button */
   5628 		RGFW_JS_X, /* or PS square button */
   5629 		RGFW_JS_Y, /* or PS triangle button */
   5630 		RGFW_JS_R1, /* right bumper */
   5631 		RGFW_JS_L1, /* left bump */
   5632 		RGFW_JS_L2, /* left trigger*/
   5633 		RGFW_JS_R2, /* right trigger */
   5634 		0, 0, 0, 0, 0, 0, 0, 0,
   5635 		RGFW_JS_UP, /* dpad up */
   5636 		RGFW_JS_DOWN, /* dpad down*/
   5637 		RGFW_JS_LEFT, /* dpad left */
   5638 		RGFW_JS_RIGHT, /* dpad right */
   5639 		RGFW_JS_START, /* start button */
   5640 		RGFW_JS_SELECT/* select button */
   5641 	};
   5642 
   5643 	static i32 RGFW_checkXInput(RGFW_window* win, RGFW_Event* e) {
   5644 		RGFW_UNUSED(win)
   5645 		
   5646 		size_t i;
   5647 		for (i = 0; i < 4; i++) {
   5648 			XINPUT_KEYSTROKE keystroke;
   5649 
   5650 			if (XInputGetKeystroke == NULL)
   5651 				return 0;
   5652 
   5653 			DWORD result = XInputGetKeystroke((DWORD)i, 0, &keystroke);
   5654 
   5655 			if ((keystroke.Flags & XINPUT_KEYSTROKE_REPEAT) == 0 && result != ERROR_EMPTY) {
   5656 				if (result != ERROR_SUCCESS)
   5657 					return 0;
   5658 
   5659 				if (keystroke.VirtualKey > VK_PAD_BACK)
   5660 					continue;
   5661 
   5662 				// RGFW_jsButtonPressed + 1 = RGFW_jsButtonReleased
   5663 				e->type = RGFW_jsButtonPressed + !(keystroke.Flags & XINPUT_KEYSTROKE_KEYDOWN);
   5664 				e->button = RGFW_xinput2RGFW[keystroke.VirtualKey - 0x5800];
   5665 				RGFW_jsPressed[i][e->button] = !(keystroke.Flags & XINPUT_KEYSTROKE_KEYDOWN);
   5666 
   5667 				return 1;
   5668 			}
   5669 
   5670 			XINPUT_STATE state;
   5671 			if (XInputGetState == NULL ||
   5672 				XInputGetState((DWORD) i, &state) == ERROR_DEVICE_NOT_CONNECTED
   5673 			)
   5674 				return 0;
   5675 #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.
   5676 
   5677 			if ((state.Gamepad.sThumbLX < INPUT_DEADZONE &&
   5678 				state.Gamepad.sThumbLX > -INPUT_DEADZONE) &&
   5679 				(state.Gamepad.sThumbLY < INPUT_DEADZONE &&
   5680 					state.Gamepad.sThumbLY > -INPUT_DEADZONE))
   5681 			{
   5682 				state.Gamepad.sThumbLX = 0;
   5683 				state.Gamepad.sThumbLY = 0;
   5684 			}
   5685 
   5686 			if ((state.Gamepad.sThumbRX < INPUT_DEADZONE &&
   5687 				state.Gamepad.sThumbRX > -INPUT_DEADZONE) &&
   5688 				(state.Gamepad.sThumbRY < INPUT_DEADZONE &&
   5689 					state.Gamepad.sThumbRY > -INPUT_DEADZONE))
   5690 			{
   5691 				state.Gamepad.sThumbRX = 0;
   5692 				state.Gamepad.sThumbRY = 0;
   5693 			}
   5694 
   5695 			e->axisesCount = 2;
   5696 			RGFW_point axis1 = RGFW_POINT(state.Gamepad.sThumbLX, state.Gamepad.sThumbLY);
   5697 			RGFW_point axis2 = RGFW_POINT(state.Gamepad.sThumbRX, state.Gamepad.sThumbRY);
   5698 
   5699 			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) {
   5700 				e->type = RGFW_jsAxisMove;
   5701 
   5702 				e->axis[0] = axis1;
   5703 				e->axis[1] = axis2;
   5704 
   5705 				return 1;
   5706 			}
   5707 
   5708 			e->axis[0] = axis1;
   5709 			e->axis[1] = axis2;
   5710 		}
   5711 
   5712 		return 0;
   5713 	}
   5714 
   5715 	void RGFW_stopCheckEvents(void) { 
   5716 		PostMessageW(RGFW_root->src.window, WM_NULL, 0, 0);
   5717 	}
   5718 
   5719 	void RGFW_window_eventWait(RGFW_window* win, i32 waitMS) {
   5720 		RGFW_UNUSED(win);
   5721 
   5722 		MsgWaitForMultipleObjects(0, NULL, FALSE, (DWORD) (waitMS * 1e3), QS_ALLINPUT);
   5723 	}
   5724 
   5725 	RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) {
   5726 		assert(win != NULL);
   5727 
   5728 		if (win->event.type == RGFW_quit) {
   5729 			return NULL;
   5730 		}
   5731 
   5732 		MSG msg;
   5733 
   5734 		if (RGFW_eventWindow.src.window == win->src.window) {
   5735 			if (RGFW_eventWindow.r.x != -1) {
   5736 				win->r.x = RGFW_eventWindow.r.x;
   5737 				win->r.y = RGFW_eventWindow.r.y;
   5738 				win->event.type = RGFW_windowMoved;
   5739 				RGFW_windowMoveCallback(win, win->r);
   5740 			}
   5741 
   5742 			if (RGFW_eventWindow.r.w != -1) {
   5743 				win->r.w = RGFW_eventWindow.r.w;
   5744 				win->r.h = RGFW_eventWindow.r.h;
   5745 				win->event.type = RGFW_windowResized;
   5746 				RGFW_windowResizeCallback(win, win->r);
   5747 			}
   5748 
   5749 			RGFW_eventWindow.src.window = NULL;
   5750 			RGFW_eventWindow.r = RGFW_RECT(-1, -1, -1, -1);
   5751 
   5752 			return &win->event;
   5753 		}
   5754 
   5755 
   5756 		static HDROP drop;
   5757 		
   5758 		if (win->event.type == RGFW_dnd_init) {
   5759 			if (win->event.droppedFilesCount) {
   5760 				u32 i;
   5761 				for (i = 0; i < win->event.droppedFilesCount; i++)
   5762 					win->event.droppedFiles[i][0] = '\0';
   5763 			}
   5764 
   5765 			win->event.droppedFilesCount = 0;
   5766 			win->event.droppedFilesCount = DragQueryFileW(drop, 0xffffffff, NULL, 0);
   5767 			//win->event.droppedFiles = (char**)RGFW_CALLOC(win->event.droppedFilesCount, sizeof(char*));
   5768 
   5769 			u32 i;
   5770 			for (i = 0; i < win->event.droppedFilesCount; i++) {
   5771 				const UINT length = DragQueryFileW(drop, i, NULL, 0);
   5772 				WCHAR* buffer = (WCHAR*) RGFW_CALLOC((size_t) length + 1, sizeof(WCHAR));
   5773 
   5774 				DragQueryFileW(drop, i, buffer, length + 1);
   5775 				strncpy(win->event.droppedFiles[i], createUTF8FromWideStringWin32(buffer), RGFW_MAX_PATH);
   5776 				win->event.droppedFiles[i][RGFW_MAX_PATH - 1] = '\0';
   5777 				RGFW_FREE(buffer);
   5778 			}
   5779 
   5780 			DragFinish(drop);
   5781 			RGFW_dndCallback(win, win->event.droppedFiles, win->event.droppedFilesCount);
   5782 			
   5783 			win->event.type = RGFW_dnd;
   5784 			return &win->event;
   5785 		}
   5786 
   5787 		win->event.inFocus = (GetForegroundWindow() == win->src.window);
   5788 
   5789 		if (RGFW_checkXInput(win, &win->event))
   5790 			return &win->event;
   5791 
   5792 		static BYTE keyboardState[256];
   5793 
   5794 		if (PeekMessageA(&msg, win->src.window, 0u, 0u, PM_REMOVE)) {
   5795 			switch (msg.message) {
   5796 			case WM_CLOSE:
   5797 			case WM_QUIT:
   5798 				RGFW_windowQuitCallback(win);
   5799 				win->event.type = RGFW_quit;
   5800 				break;
   5801 
   5802 			case WM_ACTIVATE:
   5803 				win->event.inFocus = (LOWORD(msg.wParam) == WA_INACTIVE);
   5804 
   5805 				if (win->event.inFocus) {
   5806 					win->event.type = RGFW_focusIn;
   5807 					RGFW_focusCallback(win, 1);
   5808 				}
   5809 				else {
   5810 					win->event.type = RGFW_focusOut;
   5811 					RGFW_focusCallback(win, 0);
   5812 				}
   5813 
   5814 				break;
   5815 			
   5816 			case WM_PAINT:
   5817 				win->event.type = RGFW_windowRefresh;
   5818 				RGFW_windowRefreshCallback(win);
   5819 				break;
   5820 			
   5821 			case WM_MOUSELEAVE:
   5822 				win->event.type = RGFW_mouseLeave;
   5823 				win->_winArgs |= RGFW_MOUSE_LEFT;
   5824 				RGFW_mouseNotifyCallBack(win, win->event.point, 0);
   5825 				break;
   5826 			
   5827 			case WM_KEYUP: {
   5828 				win->event.keyCode = RGFW_apiKeyCodeToRGFW((u32) msg.wParam);
   5829 								
   5830 				RGFW_keyboard[win->event.keyCode].prev = RGFW_isPressed(win, win->event.keyCode);
   5831 
   5832 				static char keyName[16];
   5833 				
   5834 				{
   5835 					GetKeyNameTextA((LONG) msg.lParam, keyName, 16);
   5836 
   5837 					if ((!(GetKeyState(VK_CAPITAL) & 0x0001) && !(GetKeyState(VK_SHIFT) & 0x8000)) ||
   5838 						((GetKeyState(VK_CAPITAL) & 0x0001) && (GetKeyState(VK_SHIFT) & 0x8000))) {
   5839 						CharLowerBuffA(keyName, 16);
   5840 					}
   5841 				}
   5842 
   5843 				RGFW_updateLockState(win, (GetKeyState(VK_CAPITAL) & 0x0001), (GetKeyState(VK_NUMLOCK) & 0x0001));
   5844 
   5845 				strncpy(win->event.keyName, keyName, 16);
   5846 
   5847 				if (RGFW_isPressed(win, RGFW_ShiftL)) {
   5848 					ToAscii((UINT) msg.wParam, MapVirtualKey((UINT) msg.wParam, MAPVK_VK_TO_CHAR),
   5849 						keyboardState, (LPWORD) win->event.keyName, 0);
   5850 				}
   5851 
   5852 				win->event.type = RGFW_keyReleased;
   5853 				RGFW_keyboard[win->event.keyCode].current = 0;
   5854 				RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, 0);
   5855 				break;
   5856 			}
   5857 			case WM_KEYDOWN: {
   5858 				win->event.keyCode = RGFW_apiKeyCodeToRGFW((u32) msg.wParam);
   5859 
   5860 				RGFW_keyboard[win->event.keyCode].prev = RGFW_isPressed(win, win->event.keyCode);
   5861 
   5862 				static char keyName[16];
   5863 				
   5864 				{
   5865 					GetKeyNameTextA((LONG) msg.lParam, keyName, 16);
   5866 
   5867 					if ((!(GetKeyState(VK_CAPITAL) & 0x0001) && !(GetKeyState(VK_SHIFT) & 0x8000)) ||
   5868 						((GetKeyState(VK_CAPITAL) & 0x0001) && (GetKeyState(VK_SHIFT) & 0x8000))) {
   5869 						CharLowerBuffA(keyName, 16);
   5870 					}
   5871 				}
   5872 				
   5873 				RGFW_updateLockState(win, (GetKeyState(VK_CAPITAL) & 0x0001), (GetKeyState(VK_NUMLOCK) & 0x0001));
   5874 
   5875 				strncpy(win->event.keyName, keyName, 16);
   5876 
   5877 				if (RGFW_isPressed(win, RGFW_ShiftL) & 0x8000) {
   5878 					ToAscii((UINT) msg.wParam, MapVirtualKey((UINT) msg.wParam, MAPVK_VK_TO_CHAR),
   5879 						keyboardState, (LPWORD) win->event.keyName, 0);
   5880 				}
   5881 
   5882 				win->event.type = RGFW_keyPressed;
   5883 				win->event.repeat = RGFW_isPressed(win, win->event.keyCode);
   5884 				RGFW_keyboard[win->event.keyCode].current = 1;
   5885 				RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, 1);
   5886 				break;
   5887 			}
   5888 
   5889 			case WM_MOUSEMOVE:
   5890 				if ((win->_winArgs & RGFW_HOLD_MOUSE))
   5891 					break;
   5892 
   5893 				win->event.type = RGFW_mousePosChanged;
   5894 
   5895 				win->event.point.x = GET_X_LPARAM(msg.lParam);
   5896 				win->event.point.y = GET_Y_LPARAM(msg.lParam);
   5897 				
   5898 				RGFW_mousePosCallback(win, win->event.point);
   5899 
   5900 				if (win->_winArgs & RGFW_MOUSE_LEFT) {
   5901 					win->_winArgs ^= RGFW_MOUSE_LEFT;
   5902 					win->event.type = RGFW_mouseEnter;
   5903 					RGFW_mouseNotifyCallBack(win, win->event.point, 1);
   5904 				}
   5905 
   5906 				break;
   5907 
   5908 			case WM_INPUT: {
   5909 				if (!(win->_winArgs & RGFW_HOLD_MOUSE))
   5910 					break;
   5911 				
   5912 				unsigned size = sizeof(RAWINPUT);
   5913 				static RAWINPUT raw[sizeof(RAWINPUT)];
   5914 				GetRawInputData((HRAWINPUT)msg.lParam, RID_INPUT, raw, &size, sizeof(RAWINPUTHEADER));
   5915 
   5916 				if (raw->header.dwType != RIM_TYPEMOUSE || (raw->data.mouse.lLastX == 0 && raw->data.mouse.lLastY == 0) )
   5917 					break;
   5918 				
   5919 				win->event.type = RGFW_mousePosChanged;
   5920 				win->event.point.x = raw->data.mouse.lLastX;
   5921 				win->event.point.y = raw->data.mouse.lLastY;
   5922 				break;
   5923 			}
   5924 
   5925 			case WM_LBUTTONDOWN:
   5926 				win->event.button = RGFW_mouseLeft;
   5927 				RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;
   5928 				RGFW_mouseButtons[win->event.button].current = 1;
   5929 				win->event.type = RGFW_mouseButtonPressed;
   5930 				RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1);
   5931 				break;
   5932 			case WM_RBUTTONDOWN:
   5933 				win->event.button = RGFW_mouseRight;
   5934 				win->event.type = RGFW_mouseButtonPressed;
   5935 				RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;
   5936 				RGFW_mouseButtons[win->event.button].current = 1;
   5937 				RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1);
   5938 				break;
   5939 			case WM_MBUTTONDOWN:
   5940 				win->event.button = RGFW_mouseMiddle;
   5941 				win->event.type = RGFW_mouseButtonPressed;
   5942 				RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;
   5943 				RGFW_mouseButtons[win->event.button].current = 1;
   5944 				RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1);
   5945 				break;
   5946 
   5947 			case WM_MOUSEWHEEL:
   5948 				if (msg.wParam > 0)
   5949 					win->event.button = RGFW_mouseScrollUp;
   5950 				else
   5951 					win->event.button = RGFW_mouseScrollDown;
   5952 
   5953 				RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;
   5954 				RGFW_mouseButtons[win->event.button].current = 1;
   5955 
   5956 				win->event.scroll = (SHORT) HIWORD(msg.wParam) / (double) WHEEL_DELTA;
   5957 
   5958 				win->event.type = RGFW_mouseButtonPressed;
   5959 				RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1);
   5960 				break;
   5961 
   5962 			case WM_LBUTTONUP:
   5963 			
   5964 				win->event.button = RGFW_mouseLeft;
   5965 				win->event.type = RGFW_mouseButtonReleased;
   5966 
   5967 				RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;
   5968 				RGFW_mouseButtons[win->event.button].current = 0;
   5969 				RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0);
   5970 				break;
   5971 			case WM_RBUTTONUP:
   5972 				win->event.button = RGFW_mouseRight;
   5973 				win->event.type = RGFW_mouseButtonReleased;
   5974 
   5975 				RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;
   5976 				RGFW_mouseButtons[win->event.button].current = 0;
   5977 				RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0);
   5978 				break;
   5979 			case WM_MBUTTONUP:
   5980 				win->event.button = RGFW_mouseMiddle;
   5981 				win->event.type = RGFW_mouseButtonReleased;
   5982 
   5983 				RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;
   5984 				RGFW_mouseButtons[win->event.button].current = 0;
   5985 				RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0);
   5986 				break;
   5987 
   5988 				/*
   5989 					much of this event is source from glfw
   5990 				*/
   5991 			case WM_DROPFILES: {				
   5992 				win->event.type = RGFW_dnd_init;
   5993 
   5994 				drop = (HDROP) msg.wParam;
   5995 				POINT pt;
   5996 
   5997 				/* Move the mouse to the position of the drop */
   5998 				DragQueryPoint(drop, &pt);
   5999 
   6000 				win->event.point.x = pt.x;
   6001 				win->event.point.y = pt.y;
   6002 
   6003 				RGFW_dndInitCallback(win, win->event.point);
   6004 			}
   6005 				break;
   6006 			case WM_GETMINMAXINFO:
   6007 			{
   6008 				if (win->src.maxSize.w == 0 && win->src.maxSize.h == 0)
   6009 					break;
   6010 
   6011 				MINMAXINFO* mmi = (MINMAXINFO*) msg.lParam;
   6012 				mmi->ptMinTrackSize.x = win->src.minSize.w;
   6013 				mmi->ptMinTrackSize.y = win->src.minSize.h;
   6014 				mmi->ptMaxTrackSize.x = win->src.maxSize.w;
   6015 				mmi->ptMaxTrackSize.y = win->src.maxSize.h;
   6016 				return 0;
   6017 			}
   6018 			default:
   6019 				win->event.type = 0;
   6020 				break;
   6021 			}
   6022 
   6023 			TranslateMessage(&msg);
   6024 			DispatchMessageA(&msg);
   6025 		}
   6026 
   6027 		else
   6028 			win->event.type = 0;
   6029 
   6030 		if (!IsWindow(win->src.window)) {
   6031 			win->event.type = RGFW_quit;
   6032 			RGFW_windowQuitCallback(win);
   6033 		}
   6034 
   6035 		if (win->event.type)
   6036 			return &win->event;
   6037 		else
   6038 			return NULL;
   6039 	}
   6040 
   6041 	u8 RGFW_window_isFullscreen(RGFW_window* win) {
   6042 		assert(win != NULL);
   6043 
   6044 		#ifndef __cplusplus
   6045 		WINDOWPLACEMENT placement = { 0 };
   6046 		#else
   6047 		WINDOWPLACEMENT placement = {  };
   6048 		#endif
   6049 		GetWindowPlacement(win->src.window, &placement);
   6050 		return placement.showCmd == SW_SHOWMAXIMIZED;
   6051 	}
   6052 
   6053 	u8 RGFW_window_isHidden(RGFW_window* win) {
   6054 		assert(win != NULL);
   6055 
   6056 		return IsWindowVisible(win->src.window) == 0 && !RGFW_window_isMinimized(win);
   6057 	}
   6058 
   6059 	u8 RGFW_window_isMinimized(RGFW_window* win) {
   6060 		assert(win != NULL);
   6061 
   6062 		#ifndef __cplusplus
   6063 		WINDOWPLACEMENT placement = { 0 };
   6064 		#else
   6065 		WINDOWPLACEMENT placement = {  };
   6066 		#endif
   6067 		GetWindowPlacement(win->src.window, &placement);
   6068 		return placement.showCmd == SW_SHOWMINIMIZED;
   6069 	}
   6070 
   6071 	u8 RGFW_window_isMaximized(RGFW_window* win) {
   6072 		assert(win != NULL);
   6073 
   6074 		#ifndef __cplusplus
   6075 		WINDOWPLACEMENT placement = { 0 };
   6076 		#else
   6077 		WINDOWPLACEMENT placement = {  };
   6078 		#endif
   6079 		GetWindowPlacement(win->src.window, &placement);
   6080 		return placement.showCmd == SW_SHOWMAXIMIZED;
   6081 	}
   6082 
   6083 	typedef struct { int iIndex; HMONITOR hMonitor; } RGFW_mInfo;
   6084 	BOOL CALLBACK GetMonitorByHandle(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) {
   6085 		RGFW_UNUSED(hdcMonitor)
   6086 		RGFW_UNUSED(lprcMonitor)
   6087 
   6088 		RGFW_mInfo* info = (RGFW_mInfo*) dwData;
   6089 		if (info->hMonitor == hMonitor)
   6090 			return FALSE;
   6091 
   6092 		info->iIndex++;
   6093 		return TRUE;
   6094 	}
   6095 	
   6096 	#ifndef RGFW_NO_MONITOR
   6097 	RGFW_monitor win32CreateMonitor(HMONITOR src) {
   6098 		RGFW_monitor monitor;
   6099 		MONITORINFO monitorInfo;
   6100 
   6101 		monitorInfo.cbSize = sizeof(MONITORINFO);
   6102 		GetMonitorInfoA(src, &monitorInfo);
   6103 
   6104 		RGFW_mInfo info;
   6105 		info.iIndex = 0;
   6106 		info.hMonitor = src;
   6107 
   6108 		/* get the monitor's index */
   6109 		if (EnumDisplayMonitors(NULL, NULL, GetMonitorByHandle, (LPARAM) &info)) {
   6110 			DISPLAY_DEVICEA dd;
   6111 			dd.cb = sizeof(dd);
   6112 
   6113 			/* loop through the devices until you find a device with the monitor's index */
   6114 			size_t deviceIndex;
   6115 			for (deviceIndex = 0; EnumDisplayDevicesA(0, (DWORD) deviceIndex, &dd, 0); deviceIndex++) {
   6116 				char* deviceName = dd.DeviceName;
   6117 				if (EnumDisplayDevicesA(deviceName, info.iIndex, &dd, 0)) {
   6118 					strncpy(monitor.name, dd.DeviceString, 128); /*!< copy the monitor's name */
   6119 					break;
   6120 				}
   6121 			}
   6122 		}
   6123 
   6124 		monitor.rect.x = monitorInfo.rcWork.left;
   6125 		monitor.rect.y = monitorInfo.rcWork.top;
   6126 		monitor.rect.w = monitorInfo.rcWork.right - monitorInfo.rcWork.left;
   6127 		monitor.rect.h = monitorInfo.rcWork.bottom - monitorInfo.rcWork.top;
   6128 
   6129 #ifndef RGFW_NO_DPI
   6130 		#ifndef USER_DEFAULT_SCREEN_DPI
   6131 		#define USER_DEFAULT_SCREEN_DPI 96
   6132 		#endif
   6133 
   6134 		if (GetDpiForMonitor != NULL) {
   6135 			u32 x, y;
   6136 			GetDpiForMonitor(src, MDT_EFFECTIVE_DPI, &x, &y);
   6137 			
   6138 			monitor.scaleX = (float) (x) / (float) USER_DEFAULT_SCREEN_DPI;
   6139 			monitor.scaleY = (float) (y) / (float) USER_DEFAULT_SCREEN_DPI;
   6140 		}
   6141 #endif
   6142 
   6143 		HDC hdc = GetDC(NULL);
   6144 		/* get pixels per inch */
   6145 		i32 ppiX = GetDeviceCaps(hdc, LOGPIXELSX);
   6146 		i32 ppiY = GetDeviceCaps(hdc, LOGPIXELSY);
   6147 		ReleaseDC(NULL, hdc);
   6148 
   6149 		/* Calculate physical height in inches */
   6150 		monitor.physW = GetSystemMetrics(SM_CYSCREEN) / (float) ppiX;
   6151 		monitor.physH = GetSystemMetrics(SM_CXSCREEN) / (float) ppiY;
   6152 		
   6153 		return monitor;
   6154 	}
   6155 	#endif /* RGFW_NO_MONITOR */
   6156 	
   6157 
   6158 	#ifndef RGFW_NO_MONITOR
   6159 	RGFW_monitor RGFW_monitors[6];
   6160 	BOOL CALLBACK GetMonitorHandle(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) {
   6161 		RGFW_UNUSED(hdcMonitor)
   6162 		RGFW_UNUSED(lprcMonitor)
   6163 
   6164 		RGFW_mInfo* info = (RGFW_mInfo*) dwData;
   6165 
   6166 		if (info->iIndex >= 6)
   6167 			return FALSE;
   6168 
   6169 		RGFW_monitors[info->iIndex] = win32CreateMonitor(hMonitor);
   6170 		info->iIndex++;
   6171 
   6172 		return TRUE;
   6173 	}
   6174 
   6175 	RGFW_monitor RGFW_getPrimaryMonitor(void) {
   6176         #ifdef __cplusplus
   6177         return win32CreateMonitor(MonitorFromPoint({ 0, 0 }, MONITOR_DEFAULTTOPRIMARY));
   6178         #else
   6179 		return win32CreateMonitor(MonitorFromPoint((POINT) { 0, 0 }, MONITOR_DEFAULTTOPRIMARY));
   6180 	    #endif
   6181     }
   6182 
   6183 	RGFW_monitor* RGFW_getMonitors(void) {
   6184 		RGFW_mInfo info;
   6185 		info.iIndex = 0;
   6186 		while (EnumDisplayMonitors(NULL, NULL, GetMonitorHandle, (LPARAM) &info));
   6187 			
   6188 		return RGFW_monitors;
   6189 	}
   6190 
   6191 	RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) {
   6192 		HMONITOR src = MonitorFromWindow(win->src.window, MONITOR_DEFAULTTOPRIMARY);
   6193 		return win32CreateMonitor(src);
   6194 	}
   6195 	#endif
   6196 
   6197 	HICON RGFW_loadHandleImage(RGFW_window* win, u8* src, RGFW_area a, BOOL icon) {
   6198 		assert(win != NULL);
   6199 
   6200 		u32 i;
   6201 		HDC dc;
   6202 		HICON handle;
   6203 		HBITMAP color, mask;
   6204 		BITMAPV5HEADER bi;
   6205 		ICONINFO ii;
   6206 		u8* target = NULL;
   6207 		u8* source = src;
   6208 
   6209 		ZeroMemory(&bi, sizeof(bi));
   6210 		bi.bV5Size = sizeof(bi);
   6211 		bi.bV5Width = a.w;
   6212 		bi.bV5Height = -((LONG) a.h);
   6213 		bi.bV5Planes = 1;
   6214 		bi.bV5BitCount = 32;
   6215 		bi.bV5Compression = BI_BITFIELDS;
   6216 		bi.bV5RedMask = 0x00ff0000;
   6217 		bi.bV5GreenMask = 0x0000ff00;
   6218 		bi.bV5BlueMask = 0x000000ff;
   6219 		bi.bV5AlphaMask = 0xff000000;
   6220 
   6221 		dc = GetDC(NULL);
   6222 		color = CreateDIBSection(dc,
   6223 			(BITMAPINFO*) &bi,
   6224 			DIB_RGB_COLORS,
   6225 			(void**) &target,
   6226 			NULL,
   6227 			(DWORD) 0);
   6228 		ReleaseDC(NULL, dc);
   6229 
   6230 		mask = CreateBitmap(a.w, a.h, 1, 1, NULL);
   6231 
   6232 		for (i = 0; i < a.w * a.h; i++) {
   6233 			target[0] = source[2];
   6234 			target[1] = source[1];
   6235 			target[2] = source[0];
   6236 			target[3] = source[3];
   6237 			target += 4;
   6238 			source += 4;
   6239 		}
   6240 
   6241 		ZeroMemory(&ii, sizeof(ii));
   6242 		ii.fIcon = icon;
   6243 		ii.xHotspot = 0;
   6244 		ii.yHotspot = 0;
   6245 		ii.hbmMask = mask;
   6246 		ii.hbmColor = color;
   6247 
   6248 		handle = CreateIconIndirect(&ii);
   6249 
   6250 		DeleteObject(color);
   6251 		DeleteObject(mask);
   6252 
   6253 		return handle;
   6254 	}
   6255 
   6256 	void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels) {
   6257 		assert(win != NULL);
   6258 		RGFW_UNUSED(channels)
   6259 
   6260 		HCURSOR cursor = (HCURSOR) RGFW_loadHandleImage(win, image, a, FALSE);
   6261 		SetClassLongPtrA(win->src.window, GCLP_HCURSOR, (LPARAM) cursor);
   6262 		SetCursor(cursor);
   6263 		DestroyCursor(cursor);
   6264 	}
   6265 
   6266 	void RGFW_window_setMouseDefault(RGFW_window* win) {
   6267 		RGFW_window_setMouseStandard(win, RGFW_MOUSE_ARROW);
   6268 	}
   6269 
   6270 	void RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse) {
   6271 		assert(win != NULL);
   6272 
   6273 		if (mouse > (sizeof(RGFW_mouseIconSrc) / sizeof(u32)))
   6274 			return;
   6275 
   6276 		char* icon = MAKEINTRESOURCEA(RGFW_mouseIconSrc[mouse]);
   6277 
   6278 		SetClassLongPtrA(win->src.window, GCLP_HCURSOR, (LPARAM) LoadCursorA(NULL, icon));
   6279 		SetCursor(LoadCursorA(NULL, icon));
   6280 	}
   6281 
   6282 	void RGFW_window_hide(RGFW_window* win) {
   6283 		ShowWindow(win->src.window, SW_HIDE);
   6284 	}
   6285 
   6286 	void RGFW_window_show(RGFW_window* win) {
   6287 		ShowWindow(win->src.window, SW_RESTORE);
   6288 	}
   6289 
   6290 	void RGFW_window_close(RGFW_window* win) {
   6291 		assert(win != NULL);
   6292 
   6293 #ifdef RGFW_EGL
   6294 		RGFW_closeEGL(win);
   6295 #endif
   6296 
   6297 		if (win == RGFW_root) {
   6298 #ifdef RGFW_DIRECTX
   6299 			RGFW_dxInfo.pDeviceContext->lpVtbl->Release(RGFW_dxInfo.pDeviceContext);
   6300 			RGFW_dxInfo.pDevice->lpVtbl->Release(RGFW_dxInfo.pDevice);
   6301 			RGFW_dxInfo.pAdapter->lpVtbl->Release(RGFW_dxInfo.pAdapter);
   6302 			RGFW_dxInfo.pFactory->lpVtbl->Release(RGFW_dxInfo.pFactory);
   6303 #endif
   6304 		
   6305 			if (RGFW_XInput_dll != NULL) {
   6306 				FreeLibrary(RGFW_XInput_dll);
   6307 				RGFW_XInput_dll = NULL;
   6308 			}
   6309 
   6310 			#ifndef RGFW_NO_DPI
   6311 			if (RGFW_Shcore_dll != NULL) {
   6312 				FreeLibrary(RGFW_Shcore_dll);
   6313 				RGFW_Shcore_dll = NULL;
   6314 			}
   6315 			#endif
   6316 
   6317 			if (wglinstance != NULL) {
   6318 				FreeLibrary(wglinstance);
   6319 				wglinstance = NULL;
   6320 			}
   6321 
   6322 			RGFW_root = NULL;
   6323 		}
   6324 
   6325 #ifdef RGFW_DIRECTX
   6326 		win->src.swapchain->lpVtbl->Release(win->src.swapchain);
   6327 		win->src.renderTargetView->lpVtbl->Release(win->src.renderTargetView);
   6328 		win->src.pDepthStencilView->lpVtbl->Release(win->src.pDepthStencilView);
   6329 #endif
   6330 
   6331 #ifdef RGFW_BUFFER
   6332 		DeleteDC(win->src.hdcMem);
   6333 		DeleteObject(win->src.bitmap);
   6334 #endif
   6335 
   6336 #ifdef RGFW_OPENGL
   6337 		wglDeleteContext((HGLRC) win->src.ctx); /*!< delete opengl context */
   6338 #endif
   6339 		DeleteDC(win->src.hdc); /*!< delete device context */
   6340 		DestroyWindow(win->src.window); /*!< delete window */
   6341 
   6342 #if defined(RGFW_OSMESA)
   6343 		if (win->buffer != NULL)
   6344 			RGFW_FREE(win->buffer);
   6345 #endif
   6346 
   6347 #ifdef RGFW_ALLOC_DROPFILES
   6348 		{
   6349 			u32 i;
   6350 			for (i = 0; i < RGFW_MAX_DROPS; i++)
   6351 				RGFW_FREE(win->event.droppedFiles[i]);
   6352 
   6353 
   6354 			RGFW_FREE(win->event.droppedFiles);
   6355 		}
   6356 #endif
   6357 
   6358 		RGFW_FREE(win);
   6359 	}
   6360 
   6361 	void RGFW_window_move(RGFW_window* win, RGFW_point v) {
   6362 		assert(win != NULL);
   6363 
   6364 		win->r.x = v.x;
   6365 		win->r.y = v.y;
   6366 		SetWindowPos(win->src.window, HWND_TOP, win->r.x, win->r.y, 0, 0, SWP_NOSIZE);
   6367 	}
   6368 
   6369 	void RGFW_window_resize(RGFW_window* win, RGFW_area a) {
   6370 		assert(win != NULL);
   6371 
   6372 		win->r.w = a.w;
   6373 		win->r.h = a.h;
   6374 		SetWindowPos(win->src.window, HWND_TOP, 0, 0, win->r.w, win->r.h + win->src.hOffset, SWP_NOMOVE);
   6375 	}
   6376 
   6377 
   6378 	void RGFW_window_setName(RGFW_window* win, char* name) {
   6379 		assert(win != NULL);
   6380 
   6381 		SetWindowTextA(win->src.window, name);
   6382 	}
   6383 
   6384 	/* sourced from GLFW */
   6385 	#ifndef RGFW_NO_PASSTHROUGH
   6386 	void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) {
   6387 		assert(win != NULL);
   6388 		
   6389 		COLORREF key = 0;
   6390 		BYTE alpha = 0;
   6391 		DWORD flags = 0;
   6392 		DWORD exStyle = GetWindowLongW(win->src.window, GWL_EXSTYLE);
   6393 		
   6394 		if (exStyle & WS_EX_LAYERED)
   6395 			GetLayeredWindowAttributes(win->src.window, &key, &alpha, &flags);
   6396 
   6397 		if (passthrough)
   6398 			exStyle |= (WS_EX_TRANSPARENT | WS_EX_LAYERED);
   6399 		else
   6400 		{
   6401 			exStyle &= ~WS_EX_TRANSPARENT;
   6402 			// NOTE: Window opacity also needs the layered window style so do not
   6403 			//       remove it if the window is alpha blended
   6404 			if (exStyle & WS_EX_LAYERED)
   6405 			{
   6406 				if (!(flags & LWA_ALPHA))
   6407 					exStyle &= ~WS_EX_LAYERED;
   6408 			}
   6409 		}
   6410 
   6411 		SetWindowLongW(win->src.window, GWL_EXSTYLE, exStyle);
   6412 
   6413 		if (passthrough) {
   6414 			SetLayeredWindowAttributes(win->src.window, key, alpha, flags);
   6415 		}
   6416 	}
   6417 	#endif
   6418 
   6419 	/* much of this function is sourced from GLFW */
   6420 	void RGFW_window_setIcon(RGFW_window* win, u8* src, RGFW_area a, i32 channels) {
   6421 		assert(win != NULL);
   6422 		#ifndef RGFW_WIN95
   6423 		RGFW_UNUSED(channels)
   6424 
   6425 		HICON handle = RGFW_loadHandleImage(win, src, a, TRUE);
   6426 
   6427 		SetClassLongPtrA(win->src.window, GCLP_HICON, (LPARAM) handle);
   6428 
   6429 		DestroyIcon(handle);
   6430 		#else
   6431 		RGFW_UNUSED(src)
   6432 		RGFW_UNUSED(a)
   6433 		RGFW_UNUSED(channels)
   6434 		#endif
   6435 	}
   6436 
   6437 	char* RGFW_readClipboard(size_t* size) {
   6438 		/* Open the clipboard */
   6439 		if (OpenClipboard(NULL) == 0)
   6440 			return (char*) "";
   6441 
   6442 		/* Get the clipboard data as a Unicode string */
   6443 		HANDLE hData = GetClipboardData(CF_UNICODETEXT);
   6444 		if (hData == NULL) {
   6445 			CloseClipboard();
   6446 			return (char*) "";
   6447 		}
   6448 
   6449 		wchar_t* wstr = (wchar_t*) GlobalLock(hData);
   6450 
   6451 		char* text;
   6452 
   6453 		{
   6454 			setlocale(LC_ALL, "en_US.UTF-8");
   6455 
   6456 			size_t textLen = wcstombs(NULL, wstr, 0);
   6457 			if (textLen == 0)
   6458 				return (char*) "";
   6459 
   6460 			text = (char*) RGFW_MALLOC((textLen * sizeof(char)) + 1);
   6461 
   6462 			wcstombs(text, wstr, (textLen) +1);
   6463 
   6464 			if (size != NULL)
   6465 				*size = textLen + 1;
   6466 
   6467 			text[textLen] = '\0';
   6468 		}
   6469 
   6470 		/* Release the clipboard data */
   6471 		GlobalUnlock(hData);
   6472 		CloseClipboard();
   6473 
   6474 		return text;
   6475 	}
   6476 
   6477 	void RGFW_writeClipboard(const char* text, u32 textLen) {
   6478 		HANDLE object;
   6479 		WCHAR* buffer;
   6480 
   6481 		object = GlobalAlloc(GMEM_MOVEABLE, (1 + textLen) * sizeof(WCHAR));
   6482 		if (!object)
   6483 			return;
   6484 
   6485 		buffer = (WCHAR*) GlobalLock(object);
   6486 		if (!buffer) {
   6487 			GlobalFree(object);
   6488 			return;
   6489 		}
   6490 
   6491 		MultiByteToWideChar(CP_UTF8, 0, text, -1, buffer, textLen);
   6492 		GlobalUnlock(object);
   6493 
   6494 		if (!OpenClipboard(RGFW_root->src.window)) {
   6495 			GlobalFree(object);
   6496 			return;
   6497 		}
   6498 
   6499 		EmptyClipboard();
   6500 		SetClipboardData(CF_UNICODETEXT, object);
   6501 		CloseClipboard();
   6502 	}
   6503 
   6504 	u16 RGFW_registerJoystick(RGFW_window* win, i32 jsNumber) {
   6505 		assert(win != NULL);
   6506 
   6507 		RGFW_UNUSED(jsNumber)
   6508 
   6509 		return RGFW_registerJoystickF(win, (char*) "");
   6510 	}
   6511 
   6512 	u16 RGFW_registerJoystickF(RGFW_window* win, char* file) {
   6513 		assert(win != NULL);
   6514 		RGFW_UNUSED(file)
   6515 
   6516 		return RGFW_joystickCount - 1;
   6517 	}
   6518 
   6519 	void RGFW_window_moveMouse(RGFW_window* win, RGFW_point p) {
   6520 		assert(win != NULL);
   6521 
   6522 		SetCursorPos(p.x, p.y);
   6523 	}
   6524 
   6525 	#ifdef RGFW_OPENGL
   6526 	void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) {
   6527 		if (win == NULL)
   6528 			wglMakeCurrent(NULL, NULL);
   6529 		else
   6530 			wglMakeCurrent(win->src.hdc, (HGLRC) win->src.ctx);
   6531 	}
   6532 	#endif
   6533 
   6534 	#ifndef RGFW_EGL
   6535 	void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) {
   6536 		assert(win != NULL);
   6537 		
   6538 		#if defined(RGFW_OPENGL)
   6539 		typedef BOOL(APIENTRY* PFNWGLSWAPINTERVALEXTPROC)(int interval);
   6540 		static PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = NULL;
   6541 		static void* loadSwapFunc = (void*) 1;
   6542 
   6543 		if (loadSwapFunc == NULL) {
   6544 			fprintf(stderr, "wglSwapIntervalEXT not supported\n");
   6545 			return;
   6546 		}
   6547 
   6548 		if (wglSwapIntervalEXT == NULL) {
   6549 			loadSwapFunc = (void*) wglGetProcAddress("wglSwapIntervalEXT");
   6550 			wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC) loadSwapFunc;
   6551 		}
   6552 
   6553 		if (wglSwapIntervalEXT(swapInterval) == FALSE)
   6554 			fprintf(stderr, "Failed to set swap interval\n");
   6555 		#else
   6556         RGFW_UNUSED(swapInterval);
   6557         #endif
   6558 
   6559 	}
   6560 	#endif
   6561 
   6562 	void RGFW_window_swapBuffers(RGFW_window* win) {
   6563 		//assert(win != NULL);
   6564 		/* clear the window*/
   6565 
   6566 		if (!(win->_winArgs & RGFW_NO_CPU_RENDER)) {
   6567 #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)
   6568 			#ifdef RGFW_OSMESA
   6569 			RGFW_OSMesa_reorganize();
   6570 			#endif
   6571 
   6572 			HGDIOBJ oldbmp = SelectObject(win->src.hdcMem, win->src.bitmap);
   6573 			BitBlt(win->src.hdc, 0, 0, win->r.w, win->r.h, win->src.hdcMem, 0, 0, SRCCOPY);
   6574 			SelectObject(win->src.hdcMem, oldbmp);
   6575 #endif
   6576 		}
   6577 
   6578 		if (!(win->_winArgs & RGFW_NO_GPU_RENDER)) {
   6579 			#ifdef RGFW_EGL
   6580 					eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface);
   6581 			#elif defined(RGFW_OPENGL)
   6582 					SwapBuffers(win->src.hdc);
   6583 			#endif
   6584 
   6585 			#if defined(RGFW_WINDOWS) && defined(RGFW_DIRECTX)
   6586 					win->src.swapchain->lpVtbl->Present(win->src.swapchain, 0, 0);
   6587 			#endif
   6588 		}
   6589 	}
   6590 
   6591 	char* createUTF8FromWideStringWin32(const WCHAR* source) {
   6592 		char* target;
   6593 		i32 size;
   6594 
   6595 		size = WideCharToMultiByte(CP_UTF8, 0, source, -1, NULL, 0, NULL, NULL);
   6596 		if (!size) {
   6597 			return NULL;
   6598 		}
   6599 
   6600 		target = (char*) RGFW_CALLOC(size, 1);
   6601 
   6602 		if (!WideCharToMultiByte(CP_UTF8, 0, source, -1, target, size, NULL, NULL)) {
   6603 			RGFW_FREE(target);
   6604 			return NULL;
   6605 		}
   6606 
   6607 		return target;
   6608 	}
   6609 	
   6610     static inline LARGE_INTEGER RGFW_win32_initTimer(void) {
   6611 		static LARGE_INTEGER frequency = {{0, 0}};
   6612 		if (frequency.QuadPart == 0) {
   6613 			timeBeginPeriod(1);
   6614 			QueryPerformanceFrequency(&frequency);
   6615 		}
   6616 
   6617 		return frequency;
   6618 	}
   6619 
   6620 	u64 RGFW_getTimeNS(void) {
   6621 		LARGE_INTEGER frequency = RGFW_win32_initTimer();
   6622 
   6623 		LARGE_INTEGER counter;
   6624 		QueryPerformanceCounter(&counter);
   6625 
   6626 		return (u64) ((counter.QuadPart * 1e9) / frequency.QuadPart);
   6627 	}
   6628 
   6629 	u64 RGFW_getTime(void) {
   6630 		LARGE_INTEGER frequency = RGFW_win32_initTimer();
   6631 
   6632 		LARGE_INTEGER counter;
   6633 		QueryPerformanceCounter(&counter);
   6634 		return (u64) (counter.QuadPart / (double) frequency.QuadPart);
   6635 	}
   6636 	
   6637 	void RGFW_sleep(u64 ms) {
   6638 		Sleep(ms);
   6639 	}
   6640 
   6641 #ifndef RGFW_NO_THREADS
   6642 	RGFW_thread RGFW_createThread(RGFW_threadFunc_ptr ptr, void* args) { return CreateThread(NULL, 0, ptr, args, 0, NULL); }
   6643 	void RGFW_cancelThread(RGFW_thread thread) { CloseHandle((HANDLE) thread); }
   6644 	void RGFW_joinThread(RGFW_thread thread) { WaitForSingleObject((HANDLE) thread, INFINITE); }
   6645 	void RGFW_setThreadPriority(RGFW_thread thread, u8 priority) { SetThreadPriority((HANDLE) thread, priority); }
   6646 #endif
   6647 #endif /* RGFW_WINDOWS */
   6648 
   6649 /*
   6650 	End of Windows defines
   6651 */
   6652 
   6653 
   6654 
   6655 /* 
   6656 
   6657 	Start of MacOS defines
   6658 
   6659 
   6660 */
   6661 
   6662 #if defined(RGFW_MACOS)
   6663 	/*
   6664 		based on silicon.h
   6665 		start of cocoa wrapper
   6666 	*/
   6667 
   6668 #include <CoreVideo/CVDisplayLink.h>
   6669 #include <ApplicationServices/ApplicationServices.h>
   6670 #include <objc/runtime.h>
   6671 #include <objc/message.h>
   6672 #include <mach/mach_time.h>
   6673 
   6674 	typedef CGRect NSRect;
   6675 	typedef CGPoint NSPoint;
   6676 	typedef CGSize NSSize;
   6677 
   6678 	typedef void NSBitmapImageRep;
   6679 	typedef void NSCursor;
   6680 	typedef void NSDraggingInfo;
   6681 	typedef void NSWindow;
   6682 	typedef void NSApplication;
   6683 	typedef void NSScreen;
   6684 	typedef void NSEvent;
   6685 	typedef void NSString;
   6686 	typedef void NSOpenGLContext;
   6687 	typedef void NSPasteboard;
   6688 	typedef void NSColor;
   6689 	typedef void NSArray;
   6690 	typedef void NSImageRep;
   6691 	typedef void NSImage;
   6692 	typedef void NSOpenGLView;
   6693 
   6694 
   6695 	typedef const char* NSPasteboardType;
   6696 	typedef unsigned long NSUInteger;
   6697 	typedef long NSInteger;
   6698 	typedef NSInteger NSModalResponse;
   6699 
   6700 #ifdef __arm64__
   6701 	/* ARM just uses objc_msgSend */
   6702 #define abi_objc_msgSend_stret objc_msgSend
   6703 #define abi_objc_msgSend_fpret objc_msgSend
   6704 #else /* __i386__ */ 
   6705 	/* x86 just uses abi_objc_msgSend_fpret and (NSColor *)objc_msgSend_id respectively */
   6706 #define abi_objc_msgSend_stret objc_msgSend_stret
   6707 #define abi_objc_msgSend_fpret objc_msgSend_fpret
   6708 #endif
   6709 
   6710 #define NSAlloc(nsclass) objc_msgSend_id((id)nsclass, sel_registerName("alloc"))
   6711 #define objc_msgSend_bool			((BOOL (*)(id, SEL))objc_msgSend)
   6712 #define objc_msgSend_void			((void (*)(id, SEL))objc_msgSend)
   6713 #define objc_msgSend_void_id		((void (*)(id, SEL, id))objc_msgSend)
   6714 #define objc_msgSend_uint			((NSUInteger (*)(id, SEL))objc_msgSend)
   6715 #define objc_msgSend_void_bool		((void (*)(id, SEL, BOOL))objc_msgSend)
   6716 #define objc_msgSend_bool_void		((BOOL (*)(id, SEL))objc_msgSend)
   6717 #define objc_msgSend_void_SEL		((void (*)(id, SEL, SEL))objc_msgSend)
   6718 #define objc_msgSend_id				((id (*)(id, SEL))objc_msgSend)
   6719 #define objc_msgSend_id_id				((id (*)(id, SEL, id))objc_msgSend)
   6720 #define objc_msgSend_id_bool			((BOOL (*)(id, SEL, id))objc_msgSend)
   6721 #define objc_msgSend_int ((id (*)(id, SEL, int))objc_msgSend)
   6722 #define objc_msgSend_arr ((id (*)(id, SEL, int))objc_msgSend)
   6723 #define objc_msgSend_ptr ((id (*)(id, SEL, void*))objc_msgSend)
   6724 #define objc_msgSend_class ((id (*)(Class, SEL))objc_msgSend)
   6725 #define objc_msgSend_class_char ((id (*)(Class, SEL, char*))objc_msgSend)
   6726 
   6727 	NSApplication* NSApp = NULL;
   6728 
   6729 	void NSRelease(id obj) {
   6730 		objc_msgSend_void(obj, sel_registerName("release"));
   6731 	}
   6732 
   6733 	#define release NSRelease
   6734 
   6735 	NSString* NSString_stringWithUTF8String(const char* str) {	
   6736 		return ((id(*)(id, SEL, const char*))objc_msgSend)
   6737 			((id)objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), str);
   6738 	}
   6739 
   6740 	const char* NSString_to_char(NSString* str) {
   6741 		return ((const char* (*)(id, SEL)) objc_msgSend) (str, sel_registerName("UTF8String"));
   6742 	}
   6743 
   6744 	void si_impl_func_to_SEL_with_name(const char* class_name, const char* register_name, void* function) {
   6745 		Class selected_class;
   6746 
   6747 		if (strcmp(class_name, "NSView") == 0) {
   6748 			selected_class = objc_getClass("ViewClass");
   6749 		} else if (strcmp(class_name, "NSWindow") == 0) {
   6750 			selected_class = objc_getClass("WindowClass");
   6751 		} else {
   6752 			selected_class = objc_getClass(class_name);
   6753 		}
   6754 
   6755 		class_addMethod(selected_class, sel_registerName(register_name), (IMP) function, 0);
   6756 	}
   6757 
   6758 	/* Header for the array. */
   6759 	typedef struct siArrayHeader {
   6760 		size_t count;
   6761 		/* TODO(EimaMei): Add a `type_width` later on. */
   6762 	} siArrayHeader;
   6763 
   6764 	/* Gets the header of the siArray. */
   6765 #define SI_ARRAY_HEADER(s) ((siArrayHeader*)s - 1)
   6766 
   6767 	void* si_array_init_reserve(size_t sizeof_element, size_t count) {
   6768 		siArrayHeader* ptr = malloc(sizeof(siArrayHeader) + (sizeof_element * count));
   6769 		void* array = ptr + sizeof(siArrayHeader);
   6770 
   6771 		siArrayHeader* header = SI_ARRAY_HEADER(array);
   6772 		header->count = count;
   6773 
   6774 		return array;
   6775 	}
   6776 
   6777 #define si_array_len(array) (SI_ARRAY_HEADER(array)->count)
   6778 #define si_func_to_SEL(class_name, function) si_impl_func_to_SEL_with_name(class_name, #function":", function)
   6779 	/* Creates an Objective-C method (SEL) from a regular C function with the option to set the register name.*/
   6780 #define si_func_to_SEL_with_name(class_name, register_name, function) si_impl_func_to_SEL_with_name(class_name, register_name":", function)
   6781 	
   6782 	unsigned char* NSBitmapImageRep_bitmapData(NSBitmapImageRep* imageRep) {
   6783 		return ((unsigned char* (*)(id, SEL))objc_msgSend)
   6784 			(imageRep, sel_registerName("bitmapData"));
   6785 	}
   6786 
   6787 #define NS_ENUM(type, name) type name; enum
   6788 
   6789 	typedef NS_ENUM(NSUInteger, NSBitmapFormat) {
   6790 		NSBitmapFormatAlphaFirst = 1 << 0,       // 0 means is alpha last (RGBA, CMYKA, etc.)
   6791 			NSBitmapFormatAlphaNonpremultiplied = 1 << 1,       // 0 means is premultiplied
   6792 			NSBitmapFormatFloatingPointSamples = 1 << 2,  // 0 is integer
   6793 
   6794 			NSBitmapFormatSixteenBitLittleEndian API_AVAILABLE(macos(10.10)) = (1 << 8),
   6795 			NSBitmapFormatThirtyTwoBitLittleEndian API_AVAILABLE(macos(10.10)) = (1 << 9),
   6796 			NSBitmapFormatSixteenBitBigEndian API_AVAILABLE(macos(10.10)) = (1 << 10),
   6797 			NSBitmapFormatThirtyTwoBitBigEndian API_AVAILABLE(macos(10.10)) = (1 << 11)
   6798 	};
   6799 
   6800 	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) {
   6801 		void* func = sel_registerName("initWithBitmapDataPlanes:pixelsWide:pixelsHigh:bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:colorSpaceName:bitmapFormat:bytesPerRow:bitsPerPixel:");
   6802 
   6803 		return (NSBitmapImageRep*) ((id(*)(id, SEL, unsigned char**, NSInteger, NSInteger, NSInteger, NSInteger, bool, bool, const char*, NSBitmapFormat, NSInteger, NSInteger))objc_msgSend)
   6804 			(NSAlloc((id)objc_getClass("NSBitmapImageRep")), func, planes, width, height, bps, spp, alpha, isPlanar, NSString_stringWithUTF8String(colorSpaceName), bitmapFormat, rowBytes, pixelBits);
   6805 	}
   6806 
   6807 	NSColor* NSColor_colorWithSRGB(CGFloat red, CGFloat green, CGFloat blue, CGFloat alpha) {
   6808 		void* nsclass = objc_getClass("NSColor");
   6809 		void* func = sel_registerName("colorWithSRGBRed:green:blue:alpha:");
   6810 		return ((id(*)(id, SEL, CGFloat, CGFloat, CGFloat, CGFloat))objc_msgSend)
   6811 			(nsclass, func, red, green, blue, alpha);
   6812 	}
   6813 
   6814 	NSCursor* NSCursor_initWithImage(NSImage* newImage, NSPoint aPoint) {
   6815 		void* func = sel_registerName("initWithImage:hotSpot:");
   6816 		void* nsclass = objc_getClass("NSCursor");
   6817 
   6818 		return (NSCursor*) ((id(*)(id, SEL, id, NSPoint))objc_msgSend)
   6819 			(NSAlloc(nsclass), func, newImage, aPoint);
   6820 	}
   6821 
   6822 	void NSImage_addRepresentation(NSImage* image, NSImageRep* imageRep) {
   6823 		void* func = sel_registerName("addRepresentation:");
   6824 		objc_msgSend_void_id(image, func, imageRep);
   6825 	}
   6826 
   6827 	NSImage* NSImage_initWithSize(NSSize size) {
   6828 		void* func = sel_registerName("initWithSize:");
   6829 		return ((id(*)(id, SEL, NSSize))objc_msgSend)
   6830 			(NSAlloc((id)objc_getClass("NSImage")), func, size);
   6831 	}
   6832 #define NS_OPENGL_ENUM_DEPRECATED(minVers, maxVers) API_AVAILABLE(macos(minVers))
   6833 	typedef NS_ENUM(NSInteger, NSOpenGLContextParameter) {
   6834 		NSOpenGLContextParameterSwapInterval           NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 222, /* 1 param.  0 -> Don't sync, 1 -> Sync to vertical retrace     */
   6835 			NSOpenGLContextParametectxaceOrder           NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 235, /* 1 param.  1 -> Above Window (default), -1 -> Below Window    */
   6836 			NSOpenGLContextParametectxaceOpacity         NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 236, /* 1 param.  1-> Surface is opaque (default), 0 -> non-opaque   */
   6837 			NSOpenGLContextParametectxaceBackingSize     NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 304, /* 2 params.  Width/height of surface backing size              */
   6838 			NSOpenGLContextParameterReclaimResources       NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 308, /* 0 params.                                                    */
   6839 			NSOpenGLContextParameterCurrentRendererID      NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 309, /* 1 param.   Retrieves the current renderer ID                 */
   6840 			NSOpenGLContextParameterGPUVertexProcessing    NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 310, /* 1 param.   Currently processing vertices with GPU (get)      */
   6841 			NSOpenGLContextParameterGPUFragmentProcessing  NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 311, /* 1 param.   Currently processing fragments with GPU (get)     */
   6842 			NSOpenGLContextParameterHasDrawable            NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 314, /* 1 param.   Boolean returned if drawable is attached          */
   6843 			NSOpenGLContextParameterMPSwapsInFlight        NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 315, /* 1 param.   Max number of swaps queued by the MP GL engine    */
   6844 
   6845 			NSOpenGLContextParameterSwapRectangle API_DEPRECATED("", macos(10.0, 10.14)) = 200, /* 4 params.  Set or get the swap rectangle {x, y, w, h} */
   6846 			NSOpenGLContextParameterSwapRectangleEnable API_DEPRECATED("", macos(10.0, 10.14)) = 201, /* Enable or disable the swap rectangle */
   6847 			NSOpenGLContextParameterRasterizationEnable API_DEPRECATED("", macos(10.0, 10.14)) = 221, /* Enable or disable all rasterization */
   6848 			NSOpenGLContextParameterStateValidation API_DEPRECATED("", macos(10.0, 10.14)) = 301, /* Validate state for multi-screen functionality */
   6849 			NSOpenGLContextParametectxaceSurfaceVolatile API_DEPRECATED("", macos(10.0, 10.14)) = 306, /* 1 param.   Surface volatile state */
   6850 	};
   6851 
   6852 
   6853 	void NSOpenGLContext_setValues(NSOpenGLContext* context, const int* vals, NSOpenGLContextParameter param) {
   6854 		void* func = sel_registerName("setValues:forParameter:");
   6855 		((void (*)(id, SEL, const int*, NSOpenGLContextParameter))objc_msgSend)
   6856 			(context, func, vals, param);
   6857 	}
   6858 
   6859 	void* NSOpenGLPixelFormat_initWithAttributes(const uint32_t* attribs) {
   6860 		void* func = sel_registerName("initWithAttributes:");
   6861 		return (void*) ((id(*)(id, SEL, const uint32_t*))objc_msgSend)
   6862 			(NSAlloc((id)objc_getClass("NSOpenGLPixelFormat")), func, attribs);
   6863 	}
   6864 
   6865 	NSOpenGLView* NSOpenGLView_initWithFrame(NSRect frameRect, uint32_t* format) {
   6866 		void* func = sel_registerName("initWithFrame:pixelFormat:");
   6867 		return (NSOpenGLView*) ((id(*)(id, SEL, NSRect, uint32_t*))objc_msgSend)
   6868 			(NSAlloc((id)objc_getClass("NSOpenGLView")), func, frameRect, format);
   6869 	}
   6870 
   6871 	void NSCursor_performSelector(NSCursor* cursor, void* selector) {
   6872 		void* func = sel_registerName("performSelector:");
   6873 		objc_msgSend_void_SEL(cursor, func, selector);
   6874 	}
   6875 
   6876 	NSPasteboard* NSPasteboard_generalPasteboard(void) {
   6877 		return (NSPasteboard*) objc_msgSend_id((id)objc_getClass("NSPasteboard"), sel_registerName("generalPasteboard"));
   6878 	}
   6879 
   6880 	NSString** cstrToNSStringArray(char** strs, size_t len) {
   6881 		static NSString* nstrs[6];
   6882 		size_t i;
   6883 		for (i = 0; i < len; i++)
   6884 			nstrs[i] = NSString_stringWithUTF8String(strs[i]);
   6885 
   6886 		return nstrs;
   6887 	}
   6888 
   6889 	const char* NSPasteboard_stringForType(NSPasteboard* pasteboard, NSPasteboardType dataType) {
   6890 		void* func = sel_registerName("stringForType:");
   6891 		return (const char*) NSString_to_char(((id(*)(id, SEL, const char*))objc_msgSend)(pasteboard, func, NSString_stringWithUTF8String(dataType)));
   6892 	}
   6893 
   6894 	NSArray* c_array_to_NSArray(void* array, size_t len) {
   6895 		SEL func = sel_registerName("initWithObjects:count:");
   6896 		void* nsclass = objc_getClass("NSArray");
   6897 		return ((id (*)(id, SEL, void*, NSUInteger))objc_msgSend)
   6898 					(NSAlloc(nsclass), func, array, len);
   6899 	}
   6900  
   6901 	void NSregisterForDraggedTypes(void* view, NSPasteboardType* newTypes, size_t len) {
   6902 		NSString** ntypes = cstrToNSStringArray((char**)newTypes, len);
   6903 
   6904 		NSArray* array = c_array_to_NSArray(ntypes, len);
   6905 		objc_msgSend_void_id(view, sel_registerName("registerForDraggedTypes:"), array);
   6906 		NSRelease(array);
   6907 	}
   6908 
   6909 	NSInteger NSPasteBoard_declareTypes(NSPasteboard* pasteboard, NSPasteboardType* newTypes, size_t len, void* owner) {
   6910 		NSString** ntypes = cstrToNSStringArray((char**)newTypes, len);
   6911 
   6912 		void* func = sel_registerName("declareTypes:owner:");
   6913 
   6914 		NSArray* array = c_array_to_NSArray(ntypes, len);
   6915 
   6916 		NSInteger output = ((NSInteger(*)(id, SEL, id, void*))objc_msgSend)
   6917 			(pasteboard, func, array, owner);
   6918 		NSRelease(array);
   6919 
   6920 		return output;
   6921 	}
   6922 
   6923 	bool NSPasteBoard_setString(NSPasteboard* pasteboard, const char* stringToWrite, NSPasteboardType dataType) {
   6924 		void* func = sel_registerName("setString:forType:");
   6925 		return ((bool (*)(id, SEL, id, NSPasteboardType))objc_msgSend)
   6926 			(pasteboard, func, NSString_stringWithUTF8String(stringToWrite), NSString_stringWithUTF8String(dataType));
   6927 	}
   6928 
   6929 	void NSRetain(id obj) { objc_msgSend_void(obj, sel_registerName("retain")); }
   6930 
   6931 	typedef enum NSApplicationActivationPolicy {
   6932 		NSApplicationActivationPolicyRegular,
   6933 		NSApplicationActivationPolicyAccessory,
   6934 		NSApplicationActivationPolicyProhibited
   6935 	} NSApplicationActivationPolicy;
   6936 
   6937 	typedef NS_ENUM(u32, NSBackingStoreType) {
   6938 		NSBackingStoreRetained = 0,
   6939 			NSBackingStoreNonretained = 1,
   6940 			NSBackingStoreBuffered = 2
   6941 	};
   6942 
   6943 	typedef NS_ENUM(u32, NSWindowStyleMask) {
   6944 		NSWindowStyleMaskBorderless = 0,
   6945 			NSWindowStyleMaskTitled = 1 << 0,
   6946 			NSWindowStyleMaskClosable = 1 << 1,
   6947 			NSWindowStyleMaskMiniaturizable = 1 << 2,
   6948 			NSWindowStyleMaskResizable = 1 << 3,
   6949 			NSWindowStyleMaskTexturedBackground = 1 << 8, /* deprecated */
   6950 			NSWindowStyleMaskUnifiedTitleAndToolbar = 1 << 12,
   6951 			NSWindowStyleMaskFullScreen = 1 << 14,
   6952 			NSWindowStyleMaskFullSizeContentView = 1 << 15,
   6953 			NSWindowStyleMaskUtilityWindow = 1 << 4,
   6954 			NSWindowStyleMaskDocModalWindow = 1 << 6,
   6955 			NSWindowStyleMaskNonactivatingPanel = 1 << 7,
   6956 			NSWindowStyleMaskHUDWindow = 1 << 13
   6957 	};
   6958 
   6959 	NSPasteboardType const NSPasteboardTypeString = "public.utf8-plain-text"; // Replaces NSStringPboardType
   6960 
   6961 
   6962 	typedef NS_ENUM(i32, NSDragOperation) {
   6963 		NSDragOperationNone = 0,
   6964 			NSDragOperationCopy = 1,
   6965 			NSDragOperationLink = 2,
   6966 			NSDragOperationGeneric = 4,
   6967 			NSDragOperationPrivate = 8,
   6968 			NSDragOperationMove = 16,
   6969 			NSDragOperationDelete = 32,
   6970 			NSDragOperationEvery = ULONG_MAX,
   6971 
   6972 			//NSDragOperationAll_Obsolete	API_DEPRECATED("", macos(10.0,10.10)) = 15, // Use NSDragOperationEvery
   6973 			//NSDragOperationAll API_DEPRECATED("", macos(10.0,10.10)) = NSDragOperationAll_Obsolete, // Use NSDragOperationEvery
   6974 	};
   6975 
   6976 	void* NSArray_objectAtIndex(NSArray* array, NSUInteger index) {
   6977 		void* func = sel_registerName("objectAtIndex:");
   6978 		return ((id(*)(id, SEL, NSUInteger))objc_msgSend)(array, func, index);
   6979 	}
   6980 
   6981 	const char** NSPasteboard_readObjectsForClasses(NSPasteboard* pasteboard, Class* classArray, size_t len, void* options) {
   6982 		void* func = sel_registerName("readObjectsForClasses:options:");
   6983 
   6984 		NSArray* array = c_array_to_NSArray(classArray, len);
   6985 
   6986 		NSArray* output = (NSArray*) ((id(*)(id, SEL, id, void*))objc_msgSend)
   6987 			(pasteboard, func, array, options);
   6988 
   6989 		NSRelease(array);
   6990 		NSUInteger count = ((NSUInteger(*)(id, SEL))objc_msgSend)(output, sel_registerName("count"));
   6991 
   6992 		const char** res = si_array_init_reserve(sizeof(const char*), count);
   6993 
   6994 		void* path_func = sel_registerName("path");
   6995 
   6996 		for (NSUInteger i = 0; i < count; i++) {
   6997 			void* url = NSArray_objectAtIndex(output, i);
   6998 			NSString* url_str = ((id(*)(id, SEL))objc_msgSend)(url, path_func);
   6999 			res[i] = NSString_to_char(url_str);
   7000 		}
   7001 
   7002 		return res;
   7003 	}
   7004 
   7005 	void* NSWindow_contentView(NSWindow* window) {
   7006 		void* func = sel_registerName("contentView");
   7007 		return objc_msgSend_id(window, func);
   7008 	}
   7009 
   7010 	/*
   7011 		End of cocoa wrapper
   7012 	*/
   7013 
   7014 	char* RGFW_mouseIconSrc[] = {"arrowCursor", "arrowCursor", "IBeamCursor", "crosshairCursor", "pointingHandCursor", "resizeLeftRightCursor", "resizeUpDownCursor", "_windowResizeNorthWestSouthEastCursor", "_windowResizeNorthEastSouthWestCursor", "closedHandCursor", "operationNotAllowedCursor"};
   7015 
   7016 	void* RGFWnsglFramework = NULL;
   7017 
   7018 #ifdef RGFW_OPENGL
   7019 	void* RGFW_getProcAddress(const char* procname) {
   7020 		if (RGFWnsglFramework == NULL)
   7021 			RGFWnsglFramework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));
   7022 
   7023 		CFStringRef symbolName = CFStringCreateWithCString(kCFAllocatorDefault, procname, kCFStringEncodingASCII);
   7024 
   7025 		void* symbol = CFBundleGetFunctionPointerForName(RGFWnsglFramework, symbolName);
   7026 
   7027 		CFRelease(symbolName);
   7028 
   7029 		return symbol;
   7030 	}
   7031 #endif
   7032 
   7033 	CVReturn displayCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* inNow, const CVTimeStamp* inOutputTime, CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* displayLinkContext) { 
   7034 		RGFW_UNUSED(displayLink) RGFW_UNUSED(inNow) RGFW_UNUSED(inOutputTime) RGFW_UNUSED(flagsIn) RGFW_UNUSED(flagsOut) RGFW_UNUSED(displayLinkContext)
   7035 		return kCVReturnSuccess; 
   7036 	}
   7037 
   7038 	id NSWindow_delegate(RGFW_window* win) {
   7039 		return (id) objc_msgSend_id(win->src.window, sel_registerName("delegate"));
   7040 	}
   7041 
   7042 	u32 RGFW_OnClose(void* self) {
   7043 		RGFW_window* win = NULL;
   7044 		object_getInstanceVariable(self, "RGFW_window", (void*)&win);
   7045 		if (win == NULL)
   7046 			return true;
   7047 
   7048 		win->event.type = RGFW_quit;
   7049 		RGFW_windowQuitCallback(win);
   7050 
   7051 		return true;
   7052 	}
   7053 
   7054 	/* NOTE(EimaMei): Fixes the constant clicking when the app is running under a terminal. */
   7055 	bool acceptsFirstResponder(void) { return true; }
   7056 	bool performKeyEquivalent(NSEvent* event) { RGFW_UNUSED(event); return true; }
   7057 
   7058 	NSDragOperation draggingEntered(id self, SEL sel, id sender) { 
   7059 		RGFW_UNUSED(sender); RGFW_UNUSED(self); RGFW_UNUSED(sel);  
   7060 
   7061 		return NSDragOperationCopy; 
   7062 	}
   7063 	NSDragOperation draggingUpdated(id self, SEL sel, id sender) { 
   7064 		RGFW_UNUSED(sel); 
   7065 
   7066 		RGFW_window* win = NULL;
   7067 		object_getInstanceVariable(self, "RGFW_window", (void*)&win);
   7068 		if (win == NULL)
   7069 			return 0;
   7070 		
   7071 		if (!(win->_winArgs & RGFW_ALLOW_DND)) {
   7072 			return 0;
   7073 		}
   7074 
   7075 		win->event.type = RGFW_dnd_init;
   7076 		win->src.dndPassed = 0;
   7077 
   7078 		NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(sender, sel_registerName("draggingLocation"));
   7079 
   7080 		win->event.point = RGFW_POINT((u32) p.x, (u32) (win->r.h - p.y));
   7081 		RGFW_dndInitCallback(win, win->event.point);
   7082 
   7083 		return NSDragOperationCopy; 
   7084 	}
   7085 	bool prepareForDragOperation(id self) {
   7086 		RGFW_window* win = NULL;
   7087 		object_getInstanceVariable(self, "RGFW_window", (void*)&win);
   7088 		if (win == NULL)
   7089 			return true;
   7090 		
   7091 		if (!(win->_winArgs & RGFW_ALLOW_DND)) {
   7092 			return false;
   7093 		}
   7094 
   7095 		return true;
   7096 	}
   7097 
   7098 	void RGFW__osxDraggingEnded(id self, SEL sel, id sender) { RGFW_UNUSED(sender); RGFW_UNUSED(self); RGFW_UNUSED(sel);  return; }
   7099 
   7100 	/* NOTE(EimaMei): Usually, you never need 'id self, SEL cmd' for C -> Obj-C methods. This isn't the case. */
   7101 	bool performDragOperation(id self, SEL sel, id sender) {
   7102 		RGFW_UNUSED(sender); RGFW_UNUSED(self); RGFW_UNUSED(sel); 
   7103 
   7104 		RGFW_window* win = NULL;
   7105 		object_getInstanceVariable(self, "RGFW_window", (void*)&win);
   7106 
   7107         if (win == NULL)
   7108 			return false;
   7109 
   7110 		// NSPasteboard* pasteBoard = objc_msgSend_id(sender, sel_registerName("draggingPasteboard"));
   7111 
   7112         /////////////////////////////
   7113         id pasteBoard = objc_msgSend_id(sender, sel_registerName("draggingPasteboard"));
   7114 
   7115         // Get the types of data available on the pasteboard
   7116         id types = objc_msgSend_id(pasteBoard, sel_registerName("types"));
   7117 
   7118         // Get the string type for file URLs
   7119         id fileURLsType = objc_msgSend_class_char(objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), "NSFilenamesPboardType");
   7120 
   7121         // Check if the pasteboard contains file URLs
   7122         if (objc_msgSend_id_bool(types, sel_registerName("containsObject:"), fileURLsType) == 0) {
   7123 		    #ifdef RGFW_DEBUG
   7124             printf("No files found on the pasteboard.\n");
   7125 			#endif
   7126 
   7127 			return 0;
   7128 		}
   7129 
   7130 		id fileURLs = objc_msgSend_id_id(pasteBoard, sel_registerName("propertyListForType:"), fileURLsType);
   7131 		int count = ((int (*)(id, SEL))objc_msgSend)(fileURLs, sel_registerName("count"));
   7132 
   7133 		if (count == 0)
   7134 			return 0;
   7135 
   7136 		for (int i = 0; i < count; i++) {
   7137 			id fileURL = objc_msgSend_arr(fileURLs, sel_registerName("objectAtIndex:"), i);
   7138 			const char *filePath = ((const char* (*)(id, SEL))objc_msgSend)(fileURL, sel_registerName("UTF8String"));
   7139 			strncpy(win->event.droppedFiles[i], filePath, RGFW_MAX_PATH);
   7140 			win->event.droppedFiles[i][RGFW_MAX_PATH - 1] = '\0';
   7141 		}
   7142 		win->event.droppedFilesCount = count;
   7143 
   7144 		win->event.type = RGFW_dnd;
   7145 		win->src.dndPassed = 0;
   7146 		
   7147 		NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(sender, sel_registerName("draggingLocation"));
   7148 		win->event.point = RGFW_POINT((u32) p.x, (u32) (win->r.h - p.y));
   7149 		
   7150 		RGFW_dndCallback(win, win->event.droppedFiles, win->event.droppedFilesCount);
   7151 	
   7152     	return false;
   7153 	}
   7154 
   7155 	static void NSMoveToResourceDir(void) {
   7156 		/* sourced from glfw */
   7157 		char resourcesPath[255];
   7158 
   7159 		CFBundleRef bundle = CFBundleGetMainBundle();
   7160 		if (!bundle)
   7161 			return;
   7162 
   7163 		CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(bundle);
   7164 		CFStringRef last = CFURLCopyLastPathComponent(resourcesURL);
   7165 
   7166 		if (
   7167 			CFStringCompare(CFSTR("Resources"), last, 0) != kCFCompareEqualTo ||
   7168 			CFURLGetFileSystemRepresentation(resourcesURL, true, (u8*) resourcesPath, 255) == 0
   7169 			) {
   7170 			CFRelease(last);
   7171 			CFRelease(resourcesURL);
   7172 			return;
   7173 		}
   7174 
   7175 		CFRelease(last);
   7176 		CFRelease(resourcesURL);
   7177 
   7178 		chdir(resourcesPath);
   7179 	}
   7180 
   7181 
   7182 	NSSize RGFW__osxWindowResize(void* self, SEL sel, NSSize frameSize) {
   7183 		RGFW_UNUSED(sel); 
   7184 
   7185 		RGFW_window* win = NULL;
   7186 		object_getInstanceVariable(self, "RGFW_window", (void*)&win);
   7187 		if (win == NULL)
   7188 			return frameSize;
   7189 		
   7190 		win->r.w = frameSize.width;
   7191 		win->r.h = frameSize.height;
   7192 		win->event.type = RGFW_windowResized;
   7193 		RGFW_windowResizeCallback(win, win->r);
   7194 		return frameSize;
   7195 	}
   7196 
   7197 	void RGFW__osxWindowMove(void* self, SEL sel) {
   7198 		RGFW_UNUSED(sel); 
   7199 
   7200 		RGFW_window* win = NULL;
   7201 		object_getInstanceVariable(self, "RGFW_window", (void*)&win);
   7202 		if (win == NULL)
   7203 			return;
   7204 		
   7205 		NSRect frame = ((NSRect(*)(id, SEL))abi_objc_msgSend_stret)(win->src.window, sel_registerName("frame"));
   7206 		win->r.x = (i32) frame.origin.x;
   7207 		win->r.y = (i32) frame.origin.y;
   7208 
   7209 		win->event.type = RGFW_windowMoved;
   7210 		RGFW_windowMoveCallback(win, win->r);
   7211 	}
   7212 
   7213 	void RGFW__osxUpdateLayer(void* self, SEL sel) {
   7214 		RGFW_UNUSED(sel);
   7215 
   7216 		RGFW_window* win = NULL;
   7217 		object_getInstanceVariable(self, "RGFW_window", (void*)&win);
   7218 		if (win == NULL)
   7219 			return;
   7220 		
   7221 		win->event.type = RGFW_windowRefresh;
   7222 		RGFW_windowRefreshCallback(win);
   7223 	}
   7224 
   7225 	RGFWDEF void RGFW_init_buffer(RGFW_window* win);
   7226 	void RGFW_init_buffer(RGFW_window* win) {
   7227 		#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)
   7228 			if (RGFW_bufferSize.w == 0 && RGFW_bufferSize.h == 0)
   7229 				RGFW_bufferSize = RGFW_getScreenSize();
   7230 				
   7231 			win->buffer = RGFW_MALLOC(RGFW_bufferSize.w * RGFW_bufferSize.h * 4);
   7232 
   7233 		#ifdef RGFW_OSMESA
   7234 				win->src.ctx = OSMesaCreateContext(OSMESA_RGBA, NULL);
   7235 				OSMesaMakeCurrent(win->src.ctx, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h);
   7236 		#endif
   7237 		#else
   7238 		RGFW_UNUSED(win); /*!< if buffer rendering is not being used */
   7239 		#endif
   7240 	}
   7241 
   7242 
   7243 	void RGFW_window_cocoaSetLayer(RGFW_window* win, void* layer) {
   7244 		objc_msgSend_void_id(win->src.view, sel_registerName("setLayer"), layer);
   7245 	}
   7246 
   7247 	void* RGFW_cocoaGetLayer(void) {
   7248 		return objc_msgSend_class(objc_getClass("CAMetalLayer"), sel_registerName("layer"));
   7249 	}
   7250 
   7251 
   7252 	NSPasteboardType const NSPasteboardTypeURL = "public.url";
   7253 	NSPasteboardType const NSPasteboardTypeFileURL  = "public.file-url";
   7254 
   7255 	RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) {
   7256 		static u8 RGFW_loaded = 0;
   7257 
   7258 		/* NOTE(EimaMei): Why does Apple hate good code? Like wtf, who thought of methods being a great idea???
   7259 		Imagine a universe, where MacOS had a proper system API (we would probably have like 20% better performance).
   7260 		*/
   7261 		si_func_to_SEL_with_name("NSObject", "windowShouldClose", RGFW_OnClose);
   7262 
   7263 		/* NOTE(EimaMei): Fixes the 'Boop' sfx from constantly playing each time you click a key. Only a problem when running in the terminal. */
   7264 		si_func_to_SEL("NSWindow", acceptsFirstResponder);
   7265 		si_func_to_SEL("NSWindow", performKeyEquivalent);
   7266 
   7267 		// RR Create an autorelease pool
   7268 		id pool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc"));
   7269 		pool = objc_msgSend_id(pool, sel_registerName("init"));
   7270 
   7271 		if (NSApp == NULL) {
   7272 			NSApp = objc_msgSend_id((id)objc_getClass("NSApplication"), sel_registerName("sharedApplication"));
   7273 
   7274 			((void (*)(id, SEL, NSUInteger))objc_msgSend)
   7275 				(NSApp, sel_registerName("setActivationPolicy:"), NSApplicationActivationPolicyRegular);
   7276 		}
   7277 
   7278 		RGFW_window* win = RGFW_window_basic_init(rect, args);
   7279 		
   7280 		RGFW_window_setMouseDefault(win);
   7281 
   7282 		NSRect windowRect;
   7283 		windowRect.origin.x = win->r.x;
   7284 		windowRect.origin.y = win->r.y;
   7285 		windowRect.size.width = win->r.w;
   7286 		windowRect.size.height = win->r.h;
   7287 
   7288 		NSBackingStoreType macArgs = NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSBackingStoreBuffered | NSWindowStyleMaskTitled;
   7289 
   7290 		if (!(args & RGFW_NO_RESIZE))
   7291 			macArgs |= NSWindowStyleMaskResizable;
   7292 		if (!(args & RGFW_NO_BORDER))
   7293 			macArgs |= NSWindowStyleMaskTitled;
   7294 		else
   7295 			macArgs = NSWindowStyleMaskBorderless;
   7296 		{
   7297 			void* nsclass = objc_getClass("NSWindow");
   7298 			void* func = sel_registerName("initWithContentRect:styleMask:backing:defer:");
   7299 
   7300 			win->src.window = ((id(*)(id, SEL, NSRect, NSWindowStyleMask, NSBackingStoreType, bool))objc_msgSend)
   7301 				(NSAlloc(nsclass), func, windowRect, macArgs, macArgs, false);
   7302 		}
   7303 
   7304 		NSString* str = NSString_stringWithUTF8String(name);
   7305 		objc_msgSend_void_id(win->src.window, sel_registerName("setTitle:"), str);
   7306 
   7307 #ifdef RGFW_EGL
   7308 		if ((args & RGFW_NO_INIT_API) == 0)
   7309 			RGFW_createOpenGLContext(win);
   7310 #endif
   7311 
   7312 #ifdef RGFW_OPENGL
   7313 	if ((args & RGFW_NO_INIT_API) == 0) {
   7314 		void* attrs = RGFW_initFormatAttribs(args & RGFW_OPENGL_SOFTWARE);
   7315 		void* format = NSOpenGLPixelFormat_initWithAttributes(attrs);
   7316 
   7317 		if (format == NULL) {
   7318 			printf("Failed to load pixel format for OpenGL\n");
   7319 
   7320 			void* attrs = RGFW_initFormatAttribs(1);
   7321 			format = NSOpenGLPixelFormat_initWithAttributes(attrs);
   7322 			if (format == NULL)
   7323 				printf("and loading software rendering OpenGL failed\n");
   7324 			else
   7325 				printf("Switching to software rendering\n");
   7326 		}
   7327 		
   7328 		/* the pixel format can be passed directly to opengl context creation to create a context 
   7329 			this is because the format also includes information about the opengl version (which may be a bad thing) */
   7330 		win->src.view = NSOpenGLView_initWithFrame((NSRect){{0, 0}, {win->r.w, win->r.h}}, format);
   7331 		objc_msgSend_void(win->src.view, sel_registerName("prepareOpenGL"));
   7332 		win->src.ctx = objc_msgSend_id(win->src.view, sel_registerName("openGLContext"));
   7333 	} else
   7334 #endif
   7335 	{
   7336 		NSRect contentRect = (NSRect){{0, 0}, {win->r.w, win->r.h}};
   7337 		win->src.view = ((id(*)(id, SEL, NSRect))objc_msgSend)
   7338 			(NSAlloc((id)objc_getClass("NSView")), sel_registerName("initWithFrame:"),
   7339 				contentRect);
   7340 	}
   7341 
   7342 		void* contentView = NSWindow_contentView(win->src.window);
   7343 		objc_msgSend_void_bool(contentView, sel_registerName("setWantsLayer:"), true);
   7344 
   7345 		objc_msgSend_void_id(win->src.window, sel_registerName("setContentView:"), win->src.view);
   7346 
   7347 #ifdef RGFW_OPENGL
   7348 		if ((args & RGFW_NO_INIT_API) == 0)
   7349 			objc_msgSend_void(win->src.ctx, sel_registerName("makeCurrentContext"));
   7350 #endif
   7351 		if (args & RGFW_TRANSPARENT_WINDOW) {
   7352 #ifdef RGFW_OPENGL
   7353 		if ((args & RGFW_NO_INIT_API) == 0) {
   7354 			i32 opacity = 0;
   7355 			#define NSOpenGLCPSurfaceOpacity 236
   7356 			NSOpenGLContext_setValues(win->src.ctx, &opacity, NSOpenGLCPSurfaceOpacity);
   7357 		}
   7358 #endif
   7359 
   7360 			objc_msgSend_void_bool(win->src.window, sel_registerName("setOpaque:"), false);
   7361 
   7362 			objc_msgSend_void_id(win->src.window, sel_registerName("setBackgroundColor:"),
   7363 				NSColor_colorWithSRGB(0, 0, 0, 0));
   7364 		}
   7365 
   7366 		win->src.display = CGMainDisplayID();
   7367 		CVDisplayLinkCreateWithCGDisplay(win->src.display, (CVDisplayLinkRef*)&win->src.displayLink);
   7368 		CVDisplayLinkSetOutputCallback(win->src.displayLink, displayCallback, win);
   7369 		CVDisplayLinkStart(win->src.displayLink);
   7370 
   7371 		RGFW_init_buffer(win);
   7372 
   7373 		#ifndef RGFW_NO_MONITOR
   7374 		if (args & RGFW_SCALE_TO_MONITOR)
   7375 			RGFW_window_scaleToMonitor(win);
   7376 		#endif
   7377 
   7378 		if (args & RGFW_CENTER) {
   7379 			RGFW_area screenR = RGFW_getScreenSize();
   7380 			RGFW_window_move(win, RGFW_POINT((screenR.w - win->r.w) / 2, (screenR.h - win->r.h) / 2));
   7381 		}
   7382 
   7383 		if (args & RGFW_HIDE_MOUSE)
   7384 			RGFW_window_showMouse(win, 0);
   7385 
   7386 		if (args & RGFW_COCOA_MOVE_TO_RESOURCE_DIR)
   7387 			NSMoveToResourceDir();
   7388 
   7389 		Class delegateClass = objc_allocateClassPair(objc_getClass("NSObject"), "WindowDelegate", 0);
   7390 
   7391 		class_addIvar(
   7392 			delegateClass, "RGFW_window",
   7393 			sizeof(RGFW_window*), rint(log2(sizeof(RGFW_window*))),
   7394 			"L"
   7395 		);
   7396 
   7397 		class_addMethod(delegateClass, sel_registerName("windowWillResize:toSize:"), (IMP) RGFW__osxWindowResize, "{NSSize=ff}@:{NSSize=ff}");
   7398 		class_addMethod(delegateClass, sel_registerName("updateLayer:"), (IMP) RGFW__osxUpdateLayer, "");
   7399 		class_addMethod(delegateClass, sel_registerName("windowWillMove:"), (IMP) RGFW__osxWindowMove, "");
   7400 		class_addMethod(delegateClass, sel_registerName("windowDidMove:"), (IMP) RGFW__osxWindowMove, "");
   7401 		class_addMethod(delegateClass, sel_registerName("draggingEntered:"), (IMP)draggingEntered, "l@:@");
   7402 		class_addMethod(delegateClass, sel_registerName("draggingUpdated:"), (IMP)draggingUpdated, "l@:@");
   7403 		class_addMethod(delegateClass, sel_registerName("draggingExited:"), (IMP)RGFW__osxDraggingEnded, "v@:@");
   7404 		class_addMethod(delegateClass, sel_registerName("draggingEnded:"), (IMP)RGFW__osxDraggingEnded, "v@:@");
   7405 		class_addMethod(delegateClass, sel_registerName("prepareForDragOperation:"), (IMP)prepareForDragOperation, "B@:@");
   7406 		class_addMethod(delegateClass, sel_registerName("performDragOperation:"), (IMP)performDragOperation, "B@:@");
   7407 
   7408 		id delegate = objc_msgSend_id(NSAlloc(delegateClass), sel_registerName("init"));
   7409 
   7410 		object_setInstanceVariable(delegate, "RGFW_window", win);
   7411 
   7412 		objc_msgSend_void_id(win->src.window, sel_registerName("setDelegate:"), delegate);
   7413 
   7414 		if (args & RGFW_ALLOW_DND) {
   7415 			win->_winArgs |= RGFW_ALLOW_DND;
   7416 
   7417 			NSPasteboardType types[] = {NSPasteboardTypeURL, NSPasteboardTypeFileURL, NSPasteboardTypeString};
   7418 			NSregisterForDraggedTypes(win->src.window, types, 3);
   7419 		}
   7420 
   7421 		// Show the window
   7422 		objc_msgSend_void_bool(NSApp, sel_registerName("activateIgnoringOtherApps:"), true);
   7423 		((id(*)(id, SEL, SEL))objc_msgSend)(win->src.window, sel_registerName("makeKeyAndOrderFront:"), NULL);
   7424 		objc_msgSend_void_bool(win->src.window, sel_registerName("setIsVisible:"), true);
   7425 
   7426 		if (!RGFW_loaded) {
   7427 			objc_msgSend_void(win->src.window, sel_registerName("makeMainWindow"));
   7428 
   7429 			RGFW_loaded = 1;
   7430 		}
   7431 
   7432 		objc_msgSend_void(win->src.window, sel_registerName("makeKeyWindow"));
   7433 
   7434 		objc_msgSend_void(NSApp, sel_registerName("finishLaunching"));
   7435 
   7436 		if (RGFW_root == NULL)
   7437 			RGFW_root = win;
   7438 
   7439 		NSRetain(win->src.window);
   7440 		NSRetain(NSApp);
   7441 
   7442 		return win;
   7443 	}
   7444 
   7445 	void RGFW_window_setBorder(RGFW_window* win, u8 border) {
   7446 		NSBackingStoreType storeType = NSWindowStyleMaskBorderless;
   7447 		if (!border) {
   7448 			storeType = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable;
   7449 		}
   7450 		if (!(win->_winArgs & RGFW_NO_RESIZE)) {
   7451 			storeType |= NSWindowStyleMaskResizable;
   7452 		}
   7453 		
   7454 		((void (*)(id, SEL, NSBackingStoreType))objc_msgSend)(win->src.window, sel_registerName("setStyleMask:"), storeType);
   7455 
   7456 		objc_msgSend_void_bool(win->src.window, sel_registerName("setHasShadow:"), border);
   7457 	}
   7458 
   7459 	RGFW_area RGFW_getScreenSize(void) {
   7460 		static CGDirectDisplayID display = 0;
   7461 
   7462 		if (display == 0)
   7463 			display = CGMainDisplayID();
   7464 
   7465 		return RGFW_AREA(CGDisplayPixelsWide(display), CGDisplayPixelsHigh(display));
   7466 	}
   7467 
   7468 	RGFW_point RGFW_getGlobalMousePoint(void) {
   7469 		assert(RGFW_root != NULL);
   7470 
   7471 		CGEventRef e = CGEventCreate(NULL);
   7472 		CGPoint point = CGEventGetLocation(e);
   7473 		CFRelease(e);
   7474 
   7475 		return RGFW_POINT((u32) point.x, (u32) point.y); /*!< the point is loaded during event checks */
   7476 	}
   7477 
   7478 	RGFW_point RGFW_window_getMousePoint(RGFW_window* win) {
   7479 		NSPoint p =  ((NSPoint(*)(id, SEL)) objc_msgSend)(win->src.window, sel_registerName("mouseLocationOutsideOfEventStream"));
   7480 
   7481 		return RGFW_POINT((u32) p.x, (u32) (win->r.h - p.y));
   7482 	}
   7483 
   7484 	u32 RGFW_keysPressed[10]; /*10 keys at a time*/
   7485 	typedef NS_ENUM(u32, NSEventType) {        /* various types of events */
   7486 		NSEventTypeLeftMouseDown = 1,
   7487 			NSEventTypeLeftMouseUp = 2,
   7488 			NSEventTypeRightMouseDown = 3,
   7489 			NSEventTypeRightMouseUp = 4,
   7490 			NSEventTypeMouseMoved = 5,
   7491 			NSEventTypeLeftMouseDragged = 6,
   7492 			NSEventTypeRightMouseDragged = 7,
   7493 			NSEventTypeMouseEntered = 8,
   7494 			NSEventTypeMouseExited = 9,
   7495 			NSEventTypeKeyDown = 10,
   7496 			NSEventTypeKeyUp = 11,
   7497 			NSEventTypeFlagsChanged = 12,
   7498 			NSEventTypeAppKitDefined = 13,
   7499 			NSEventTypeSystemDefined = 14,
   7500 			NSEventTypeApplicationDefined = 15,
   7501 			NSEventTypePeriodic = 16,
   7502 			NSEventTypeCursorUpdate = 17,
   7503 			NSEventTypeScrollWheel = 22,
   7504 			NSEventTypeTabletPoint = 23,
   7505 			NSEventTypeTabletProximity = 24,
   7506 			NSEventTypeOtherMouseDown = 25,
   7507 			NSEventTypeOtherMouseUp = 26,
   7508 			NSEventTypeOtherMouseDragged = 27,
   7509 			/* The following event types are available on some hardware on 10.5.2 and later */
   7510 			NSEventTypeGesture API_AVAILABLE(macos(10.5)) = 29,
   7511 			NSEventTypeMagnify API_AVAILABLE(macos(10.5)) = 30,
   7512 			NSEventTypeSwipe   API_AVAILABLE(macos(10.5)) = 31,
   7513 			NSEventTypeRotate  API_AVAILABLE(macos(10.5)) = 18,
   7514 			NSEventTypeBeginGesture API_AVAILABLE(macos(10.5)) = 19,
   7515 			NSEventTypeEndGesture API_AVAILABLE(macos(10.5)) = 20,
   7516 
   7517 			NSEventTypeSmartMagnify API_AVAILABLE(macos(10.8)) = 32,
   7518 			NSEventTypeQuickLook API_AVAILABLE(macos(10.8)) = 33,
   7519 
   7520 			NSEventTypePressure API_AVAILABLE(macos(10.10.3)) = 34,
   7521 			NSEventTypeDirectTouch API_AVAILABLE(macos(10.10)) = 37,
   7522 
   7523 			NSEventTypeChangeMode API_AVAILABLE(macos(10.15)) = 38,
   7524 	};
   7525 
   7526 	typedef NS_ENUM(unsigned long long, NSEventMask) { /* masks for the types of events */
   7527 		NSEventMaskLeftMouseDown = 1ULL << NSEventTypeLeftMouseDown,
   7528 			NSEventMaskLeftMouseUp = 1ULL << NSEventTypeLeftMouseUp,
   7529 			NSEventMaskRightMouseDown = 1ULL << NSEventTypeRightMouseDown,
   7530 			NSEventMaskRightMouseUp = 1ULL << NSEventTypeRightMouseUp,
   7531 			NSEventMaskMouseMoved = 1ULL << NSEventTypeMouseMoved,
   7532 			NSEventMaskLeftMouseDragged = 1ULL << NSEventTypeLeftMouseDragged,
   7533 			NSEventMaskRightMouseDragged = 1ULL << NSEventTypeRightMouseDragged,
   7534 			NSEventMaskMouseEntered = 1ULL << NSEventTypeMouseEntered,
   7535 			NSEventMaskMouseExited = 1ULL << NSEventTypeMouseExited,
   7536 			NSEventMaskKeyDown = 1ULL << NSEventTypeKeyDown,
   7537 			NSEventMaskKeyUp = 1ULL << NSEventTypeKeyUp,
   7538 			NSEventMaskFlagsChanged = 1ULL << NSEventTypeFlagsChanged,
   7539 			NSEventMaskAppKitDefined = 1ULL << NSEventTypeAppKitDefined,
   7540 			NSEventMaskSystemDefined = 1ULL << NSEventTypeSystemDefined,
   7541 			NSEventMaskApplicationDefined = 1ULL << NSEventTypeApplicationDefined,
   7542 			NSEventMaskPeriodic = 1ULL << NSEventTypePeriodic,
   7543 			NSEventMaskCursorUpdate = 1ULL << NSEventTypeCursorUpdate,
   7544 			NSEventMaskScrollWheel = 1ULL << NSEventTypeScrollWheel,
   7545 			NSEventMaskTabletPoint = 1ULL << NSEventTypeTabletPoint,
   7546 			NSEventMaskTabletProximity = 1ULL << NSEventTypeTabletProximity,
   7547 			NSEventMaskOtherMouseDown = 1ULL << NSEventTypeOtherMouseDown,
   7548 			NSEventMaskOtherMouseUp = 1ULL << NSEventTypeOtherMouseUp,
   7549 			NSEventMaskOtherMouseDragged = 1ULL << NSEventTypeOtherMouseDragged,
   7550 			/* The following event masks are available on some hardware on 10.5.2 and later */
   7551 			NSEventMaskGesture API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeGesture,
   7552 			NSEventMaskMagnify API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeMagnify,
   7553 			NSEventMaskSwipe API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeSwipe,
   7554 			NSEventMaskRotate API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeRotate,
   7555 			NSEventMaskBeginGesture API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeBeginGesture,
   7556 			NSEventMaskEndGesture API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeEndGesture,
   7557 
   7558 			/* 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.
   7559 			 */
   7560 			NSEventMaskSmartMagnify API_AVAILABLE(macos(10.8)) = 1ULL << NSEventTypeSmartMagnify,
   7561 			NSEventMaskPressure API_AVAILABLE(macos(10.10.3)) = 1ULL << NSEventTypePressure,
   7562 			NSEventMaskDirectTouch API_AVAILABLE(macos(10.12.2)) = 1ULL << NSEventTypeDirectTouch,
   7563 
   7564 			NSEventMaskChangeMode API_AVAILABLE(macos(10.15)) = 1ULL << NSEventTypeChangeMode,
   7565 
   7566 			NSEventMaskAny = ULONG_MAX,
   7567 
   7568 	};
   7569 
   7570 	typedef enum NSEventModifierFlags {
   7571 		NSEventModifierFlagCapsLock = 1 << 16,
   7572 		NSEventModifierFlagShift = 1 << 17,
   7573 		NSEventModifierFlagControl = 1 << 18,
   7574 		NSEventModifierFlagOption = 1 << 19,
   7575 		NSEventModifierFlagCommand = 1 << 20,
   7576 		NSEventModifierFlagNumericPad = 1 << 21
   7577 	} NSEventModifierFlags;
   7578 
   7579 	void RGFW_stopCheckEvents(void) { 
   7580 		id eventPool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc"));
   7581         eventPool = objc_msgSend_id(eventPool, sel_registerName("init"));
   7582 
   7583 		NSEvent* e = (NSEvent*) ((id(*)(id, SEL, NSEventType, NSPoint, NSEventModifierFlags, void*, NSInteger, void**, short, NSInteger, NSInteger))objc_msgSend)
   7584 			(NSApp, sel_registerName("otherEventWithType:location:modifierFlags:timestamp:windowNumber:context:subtype:data1:data2:"), 
   7585 				NSEventTypeApplicationDefined, (NSPoint){0, 0}, 0, 0, 0, NULL, 0, 0, 0);
   7586 
   7587 		((void (*)(id, SEL, id, bool))objc_msgSend)
   7588 			(NSApp, sel_registerName("postEvent:atStart:"), e, 1);
   7589 
   7590 		objc_msgSend_bool_void(eventPool, sel_registerName("drain"));
   7591 	}
   7592 
   7593 	void RGFW_window_eventWait(RGFW_window* win, i32 waitMS) {
   7594 		RGFW_UNUSED(win);
   7595 		
   7596 		id eventPool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc"));
   7597         eventPool = objc_msgSend_id(eventPool, sel_registerName("init"));
   7598 
   7599 		void* date = (void*) ((id(*)(Class, SEL, double))objc_msgSend)
   7600 					(objc_getClass("NSDate"), sel_registerName("dateWithTimeIntervalSinceNow:"), waitMS);
   7601 
   7602 		NSEvent* e = (NSEvent*) ((id(*)(id, SEL, NSEventMask, void*, NSString*, bool))objc_msgSend)
   7603 			(NSApp, sel_registerName("nextEventMatchingMask:untilDate:inMode:dequeue:"), 
   7604 				ULONG_MAX, date, NSString_stringWithUTF8String("kCFRunLoopDefaultMode"), true);
   7605 
   7606 
   7607 		if (e) {
   7608 			objc_msgSend_void_id(NSApp, sel_registerName("sendEvent:"), e);
   7609 		}
   7610 
   7611 		objc_msgSend_bool_void(eventPool, sel_registerName("drain"));
   7612 	}
   7613 
   7614 	RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) {
   7615 		assert(win != NULL);
   7616 		
   7617 		if (win->event.type == RGFW_quit)
   7618 			return NULL;
   7619 		
   7620 		if ((win->event.type == RGFW_dnd || win->event.type == RGFW_dnd_init) && win->src.dndPassed == 0) {
   7621 			win->src.dndPassed = 1;
   7622 			return &win->event;
   7623 		}
   7624 
   7625 		id eventPool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc"));
   7626         eventPool = objc_msgSend_id(eventPool, sel_registerName("init"));
   7627 
   7628 		static void* eventFunc = NULL;
   7629 		if (eventFunc == NULL) 
   7630 			eventFunc = sel_registerName("nextEventMatchingMask:untilDate:inMode:dequeue:");
   7631 
   7632 		if ((win->event.type == RGFW_windowMoved || win->event.type == RGFW_windowResized || win->event.type == RGFW_windowRefresh) && win->event.keyCode != 120) {
   7633 			win->event.keyCode = 120;
   7634 			objc_msgSend_bool_void(eventPool, sel_registerName("drain"));
   7635 			return &win->event;
   7636 		}
   7637 
   7638 		void* date = NULL;
   7639 
   7640 		NSEvent* e = (NSEvent*) ((id(*)(id, SEL, NSEventMask, void*, NSString*, bool))objc_msgSend)
   7641 			(NSApp, eventFunc, ULONG_MAX, date, NSString_stringWithUTF8String("kCFRunLoopDefaultMode"), true);
   7642 
   7643 		if (e == NULL) {
   7644 			objc_msgSend_bool_void(eventPool, sel_registerName("drain"));
   7645 			return NULL;
   7646 		}
   7647 		
   7648 		if (objc_msgSend_id(e, sel_registerName("window")) != win->src.window) {
   7649 			((void (*)(id, SEL, id, bool))objc_msgSend)
   7650 				(NSApp, sel_registerName("postEvent:atStart:"), e, 0);
   7651 						
   7652 			objc_msgSend_bool_void(eventPool, sel_registerName("drain"));
   7653 			return NULL;
   7654 		}
   7655 
   7656 		if (win->event.droppedFilesCount) {
   7657 			u32 i;
   7658 			for (i = 0; i < win->event.droppedFilesCount; i++)
   7659 				win->event.droppedFiles[i][0] = '\0';
   7660 		}
   7661 
   7662 		win->event.droppedFilesCount = 0;
   7663 		win->event.type = 0;
   7664 		
   7665 		switch (objc_msgSend_uint(e, sel_registerName("type"))) {
   7666 			case NSEventTypeMouseEntered: {
   7667 				win->event.type = RGFW_mouseEnter;
   7668 				NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(e, sel_registerName("locationInWindow"));
   7669 
   7670 				win->event.point = RGFW_POINT((i32) p.x, (i32) (win->r.h - p.y));
   7671 				RGFW_mouseNotifyCallBack(win, win->event.point, 1);
   7672 				break;
   7673 			}
   7674 			
   7675 			case NSEventTypeMouseExited:
   7676 				win->event.type = RGFW_mouseLeave;
   7677 				RGFW_mouseNotifyCallBack(win, win->event.point, 0);
   7678 				break;
   7679 
   7680 			case NSEventTypeKeyDown: {
   7681 				u32 key = (u16) objc_msgSend_uint(e, sel_registerName("keyCode"));
   7682 				win->event.keyCode = RGFW_apiKeyCodeToRGFW(key);
   7683 				RGFW_keyboard[win->event.keyCode].prev = RGFW_keyboard[win->event.keyCode].current;
   7684 
   7685 				win->event.type = RGFW_keyPressed;
   7686 				char* str = (char*)(const char*) NSString_to_char(objc_msgSend_id(e, sel_registerName("characters")));
   7687 				strncpy(win->event.keyName, str, 16);
   7688 				win->event.repeat = RGFW_isPressed(win, win->event.keyCode);
   7689 				RGFW_keyboard[win->event.keyCode].current = 1;
   7690 
   7691 				RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, 1);
   7692 				break;
   7693 			}
   7694 
   7695 			case NSEventTypeKeyUp: {
   7696 				u32 key = (u16) objc_msgSend_uint(e, sel_registerName("keyCode"));
   7697 				win->event.keyCode = RGFW_apiKeyCodeToRGFW(key);;
   7698 
   7699 				RGFW_keyboard[win->event.keyCode].prev = RGFW_keyboard[win->event.keyCode].current;
   7700 
   7701 				win->event.type = RGFW_keyReleased;
   7702 				char* str = (char*)(const char*) NSString_to_char(objc_msgSend_id(e, sel_registerName("characters")));
   7703 				strncpy(win->event.keyName, str, 16);
   7704 
   7705 				RGFW_keyboard[win->event.keyCode].current = 0;
   7706 				RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, 0);
   7707 				break;
   7708 			}
   7709 
   7710 			case NSEventTypeFlagsChanged: {
   7711 				u32 flags = objc_msgSend_uint(e, sel_registerName("modifierFlags"));
   7712 				RGFW_updateLockState(win, ((u32)(flags & NSEventModifierFlagCapsLock) % 255), ((flags & NSEventModifierFlagNumericPad) % 255));
   7713 				
   7714 				u8 i;
   7715 				for (i = 0; i < 9; i++)
   7716 					RGFW_keyboard[i + RGFW_CapsLock].prev = 0;
   7717 				
   7718 				for (i = 0; i < 5; i++) {
   7719 					u32 shift = (1 << (i + 16));
   7720 					u32 key = i + RGFW_CapsLock;
   7721 
   7722 					if ((flags & shift) && !RGFW_wasPressed(win, key)) {
   7723 						RGFW_keyboard[key].current = 1;
   7724 
   7725 						if (key != RGFW_CapsLock)
   7726 							RGFW_keyboard[key+ 4].current = 1;
   7727 						
   7728 						win->event.type = RGFW_keyPressed;
   7729 						win->event.keyCode = key;
   7730 						break;
   7731 					} 
   7732 					
   7733 					if (!(flags & shift) && RGFW_wasPressed(win, key)) {
   7734 						RGFW_keyboard[key].current = 0;
   7735 						
   7736 						if (key != RGFW_CapsLock)
   7737 							RGFW_keyboard[key + 4].current = 0;
   7738 
   7739 						win->event.type = RGFW_keyReleased;
   7740 						win->event.keyCode = key;
   7741 						break;
   7742 					}
   7743 				}
   7744 
   7745 				RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, win->event.type == RGFW_keyPressed);
   7746 
   7747 				break;
   7748 			}
   7749 			case NSEventTypeLeftMouseDragged:
   7750 			case NSEventTypeOtherMouseDragged:
   7751 			case NSEventTypeRightMouseDragged:
   7752 			case NSEventTypeMouseMoved:
   7753 				win->event.type = RGFW_mousePosChanged;
   7754 				NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(e, sel_registerName("locationInWindow"));
   7755 				win->event.point = RGFW_POINT((u32) p.x, (u32) (win->r.h - p.y));
   7756 
   7757 				if ((win->_winArgs & RGFW_HOLD_MOUSE)) {
   7758 					p.x = ((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(e, sel_registerName("deltaX"));
   7759 					p.y = ((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(e, sel_registerName("deltaY"));
   7760 					
   7761 					win->event.point = RGFW_POINT((i32)p.x, (i32)p.y);
   7762 				}
   7763 
   7764 				RGFW_mousePosCallback(win, win->event.point);
   7765 				break;
   7766 
   7767 			case NSEventTypeLeftMouseDown:
   7768 				win->event.button = RGFW_mouseLeft;
   7769 				win->event.type = RGFW_mouseButtonPressed;
   7770 				RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;
   7771 				RGFW_mouseButtons[win->event.button].current = 1;
   7772 				RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1);
   7773 				break;
   7774 
   7775 			case NSEventTypeOtherMouseDown:
   7776 				win->event.button = RGFW_mouseMiddle;
   7777 				win->event.type = RGFW_mouseButtonPressed;
   7778 				RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;
   7779 				RGFW_mouseButtons[win->event.button].current = 1;
   7780 				RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1);
   7781 				break;
   7782 
   7783 			case NSEventTypeRightMouseDown:
   7784 				win->event.button = RGFW_mouseRight;
   7785 				win->event.type = RGFW_mouseButtonPressed;
   7786 				RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;
   7787 				RGFW_mouseButtons[win->event.button].current = 1;
   7788 				RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1);
   7789 				break;
   7790 
   7791 			case NSEventTypeLeftMouseUp:
   7792 				win->event.button = RGFW_mouseLeft;
   7793 				win->event.type = RGFW_mouseButtonReleased;
   7794 				RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;
   7795 				RGFW_mouseButtons[win->event.button].current = 0;
   7796 				RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0);
   7797 				break;
   7798 
   7799 			case NSEventTypeOtherMouseUp:
   7800 				win->event.button = RGFW_mouseMiddle;
   7801 				RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;
   7802 				RGFW_mouseButtons[win->event.button].current = 0;
   7803 				win->event.type = RGFW_mouseButtonReleased;
   7804 				RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0);
   7805 				break;
   7806 
   7807 			case NSEventTypeRightMouseUp:
   7808 				win->event.button = RGFW_mouseRight;
   7809 				RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;
   7810 				RGFW_mouseButtons[win->event.button].current = 0;
   7811 				win->event.type = RGFW_mouseButtonReleased;
   7812 				RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0);
   7813 				break;
   7814 
   7815 			case NSEventTypeScrollWheel: {
   7816 				double deltaY = ((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(e, sel_registerName("deltaY"));
   7817 
   7818 				if (deltaY > 0) {
   7819 					win->event.button = RGFW_mouseScrollUp;
   7820 				}
   7821 				else if (deltaY < 0) {
   7822 					win->event.button = RGFW_mouseScrollDown;
   7823 				}
   7824 
   7825 				RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;
   7826 				RGFW_mouseButtons[win->event.button].current = 1;
   7827 
   7828 				win->event.scroll = deltaY;
   7829 
   7830 				win->event.type = RGFW_mouseButtonPressed;
   7831 				RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1);
   7832 				break;
   7833 			}
   7834 
   7835 			default:
   7836 				break;
   7837 		}
   7838 
   7839 		objc_msgSend_void_id(NSApp, sel_registerName("sendEvent:"), e);
   7840 		((void(*)(id, SEL))objc_msgSend)(NSApp, sel_registerName("updateWindows"));
   7841 				
   7842 		objc_msgSend_bool_void(eventPool, sel_registerName("drain"));
   7843 		return &win->event;
   7844 	}
   7845 
   7846 
   7847 	void RGFW_window_move(RGFW_window* win, RGFW_point v) {
   7848 		assert(win != NULL);
   7849 
   7850 		win->r.x = v.x;
   7851 		win->r.y = v.y;
   7852 		((void(*)(id, SEL, NSRect, bool, bool))objc_msgSend)
   7853 			(win->src.window, sel_registerName("setFrame:display:animate:"), (NSRect){{win->r.x, win->r.y}, {win->r.w, win->r.h}}, true, true);
   7854 	}
   7855 
   7856 	void RGFW_window_resize(RGFW_window* win, RGFW_area a) {
   7857 		assert(win != NULL);
   7858 
   7859 		win->r.w = a.w;
   7860 		win->r.h = a.h;
   7861 		((void(*)(id, SEL, NSRect, bool, bool))objc_msgSend)
   7862 			(win->src.window, sel_registerName("setFrame:display:animate:"), (NSRect){{win->r.x, win->r.y}, {win->r.w, win->r.h}}, true, true);
   7863 	}
   7864 
   7865 	void RGFW_window_minimize(RGFW_window* win) {
   7866 		assert(win != NULL);
   7867 
   7868 		objc_msgSend_void_SEL(win->src.window, sel_registerName("performMiniaturize:"), NULL);
   7869 	}
   7870 
   7871 	void RGFW_window_restore(RGFW_window* win) {
   7872 		assert(win != NULL);
   7873 
   7874 		objc_msgSend_void_SEL(win->src.window, sel_registerName("deminiaturize:"), NULL);
   7875 	}
   7876 
   7877 	void RGFW_window_setName(RGFW_window* win, char* name) {
   7878 		assert(win != NULL);
   7879 
   7880 		NSString* str = NSString_stringWithUTF8String(name);
   7881 		objc_msgSend_void_id(win->src.window, sel_registerName("setTitle:"), str);
   7882 	}
   7883 
   7884 	#ifndef RGFW_NO_PASSTHROUGH
   7885 	void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) {
   7886 		objc_msgSend_void_bool(win->src.window, sel_registerName("setIgnoresMouseEvents:"), passthrough);
   7887 	}
   7888 	#endif
   7889 
   7890 	void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) {
   7891 		if (a.w == 0 && a.h == 0)
   7892 			return;
   7893 
   7894 		((void (*)(id, SEL, NSSize))objc_msgSend)
   7895 			(win->src.window, sel_registerName("setMinSize:"), (NSSize){a.w, a.h});
   7896 	}
   7897 
   7898 	void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) {
   7899 		if (a.w == 0 && a.h == 0)
   7900 			return;
   7901 
   7902 		((void (*)(id, SEL, NSSize))objc_msgSend)
   7903 			(win->src.window, sel_registerName("setMaxSize:"), (NSSize){a.w, a.h});
   7904 	}
   7905 
   7906 	void RGFW_window_setIcon(RGFW_window* win, u8* data, RGFW_area area, i32 channels) {
   7907 		assert(win != NULL);
   7908 
   7909 		/* code by EimaMei  */
   7910 		// Make a bitmap representation, then copy the loaded image into it.
   7911 		void* representation = NSBitmapImageRep_initWithBitmapData(NULL, area.w, area.h, 8, channels, (channels == 4), false, "NSCalibratedRGBColorSpace", 1 << 1, area.w * channels, 8 * channels);
   7912 		memcpy(NSBitmapImageRep_bitmapData(representation), data, area.w * area.h * channels);
   7913 
   7914 		// Add ze representation.
   7915 		void* dock_image = NSImage_initWithSize((NSSize){area.w, area.h});
   7916 		NSImage_addRepresentation(dock_image, (void*) representation);
   7917 
   7918 		// Finally, set the dock image to it.
   7919 		objc_msgSend_void_id(NSApp, sel_registerName("setApplicationIconImage:"), dock_image);
   7920 		// Free the garbage.
   7921 		release(dock_image);
   7922 		release(representation);
   7923 	}
   7924 
   7925 	NSCursor* NSCursor_arrowStr(char* str) {
   7926 		void* nclass = objc_getClass("NSCursor");
   7927 		void* func = sel_registerName(str);
   7928 		return (NSCursor*) objc_msgSend_id(nclass, func);
   7929 	}
   7930 
   7931 	void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels) {
   7932 		assert(win != NULL);
   7933 
   7934 		if (image == NULL) {
   7935 			objc_msgSend_void(NSCursor_arrowStr("arrowCursor"), sel_registerName("set"));
   7936 			return;
   7937 		}
   7938 
   7939 		/* NOTE(EimaMei): Code by yours truly. */
   7940 		// Make a bitmap representation, then copy the loaded image into it.
   7941 		void* representation = NSBitmapImageRep_initWithBitmapData(NULL, a.w, a.h, 8, channels, (channels == 4), false, "NSCalibratedRGBColorSpace", 1 << 1, a.w * channels, 8 * channels);
   7942 		memcpy(NSBitmapImageRep_bitmapData(representation), image, a.w * a.h * channels);
   7943 
   7944 		// Add ze representation.
   7945 		void* cursor_image = NSImage_initWithSize((NSSize){a.w, a.h});
   7946 		NSImage_addRepresentation(cursor_image, representation);
   7947 
   7948 		// Finally, set the cursor image.
   7949 		void* cursor = NSCursor_initWithImage(cursor_image, (NSPoint){0.0, 0.0});
   7950 
   7951 		objc_msgSend_void(cursor, sel_registerName("set"));
   7952 
   7953 		// Free the garbage.
   7954 		release(cursor_image);
   7955 		release(representation);
   7956 	}
   7957 
   7958 	void RGFW_window_setMouseDefault(RGFW_window* win) {
   7959 		RGFW_window_setMouseStandard(win, RGFW_MOUSE_ARROW);
   7960 	}
   7961 
   7962 	void RGFW_window_showMouse(RGFW_window* win, i8 show) {
   7963 		RGFW_UNUSED(win);
   7964 
   7965 		if (show) {
   7966 			CGDisplayShowCursor(kCGDirectMainDisplay);
   7967 		}
   7968 		else {
   7969 			CGDisplayHideCursor(kCGDirectMainDisplay);
   7970 		}
   7971 	}
   7972 
   7973 	void RGFW_window_setMouseStandard(RGFW_window* win, u8 stdMouses) {
   7974 		if (stdMouses > ((sizeof(RGFW_mouseIconSrc)) / (sizeof(char*))))
   7975 			return;
   7976 		
   7977 		char* mouseStr = RGFW_mouseIconSrc[stdMouses];
   7978 		void* mouse = NSCursor_arrowStr(mouseStr);
   7979 
   7980 		if (mouse == NULL)
   7981 			return;
   7982 
   7983 		RGFW_UNUSED(win);
   7984 		CGDisplayShowCursor(kCGDirectMainDisplay);
   7985 		objc_msgSend_void(mouse, sel_registerName("set"));
   7986 	}
   7987 	
   7988 	void RGFW_releaseCursor(RGFW_window* win) {
   7989 		RGFW_UNUSED(win);
   7990 		CGAssociateMouseAndMouseCursorPosition(1);	
   7991 	}
   7992 
   7993 	void RGFW_captureCursor(RGFW_window* win, RGFW_rect r) { 
   7994 		RGFW_UNUSED(win)
   7995 
   7996 		CGWarpMouseCursorPosition(CGPointMake(r.x + (r.w / 2), r.y + (r.h / 2)));
   7997 		CGAssociateMouseAndMouseCursorPosition(0);
   7998 	}
   7999 
   8000 	void RGFW_window_moveMouse(RGFW_window* win, RGFW_point v) {
   8001 		RGFW_UNUSED(win);
   8002 		
   8003 		CGWarpMouseCursorPosition(CGPointMake(v.x, v.y));		
   8004 	}
   8005 
   8006 
   8007 	void RGFW_window_hide(RGFW_window* win) {
   8008 		objc_msgSend_void_bool(win->src.window, sel_registerName("setIsVisible:"), false);
   8009 	}
   8010 
   8011 	void RGFW_window_show(RGFW_window* win) {
   8012 		((id(*)(id, SEL, SEL))objc_msgSend)(win->src.window, sel_registerName("makeKeyAndOrderFront:"), NULL);
   8013 		objc_msgSend_void_bool(win->src.window, sel_registerName("setIsVisible:"), true);
   8014 	}
   8015 
   8016 	u8 RGFW_window_isFullscreen(RGFW_window* win) {
   8017 		assert(win != NULL);
   8018 
   8019 		NSWindowStyleMask mask = (NSWindowStyleMask) objc_msgSend_uint(win->src.window, sel_registerName("styleMask"));
   8020 		return (mask & NSWindowStyleMaskFullScreen) == NSWindowStyleMaskFullScreen;
   8021 	}
   8022 
   8023 	u8 RGFW_window_isHidden(RGFW_window* win) {
   8024 		assert(win != NULL);
   8025 
   8026 		bool visible = objc_msgSend_bool(win->src.window, sel_registerName("isVisible"));
   8027 		return visible == NO && !RGFW_window_isMinimized(win);
   8028 	}
   8029 
   8030 	u8 RGFW_window_isMinimized(RGFW_window* win) {
   8031 		assert(win != NULL);
   8032 
   8033 		return objc_msgSend_bool(win->src.window, sel_registerName("isMiniaturized")) == YES;
   8034 	}
   8035 
   8036 	u8 RGFW_window_isMaximized(RGFW_window* win) {
   8037 		assert(win != NULL);
   8038 
   8039 		return objc_msgSend_bool(win->src.window, sel_registerName("isZoomed"));
   8040 	}
   8041 
   8042 	static RGFW_monitor RGFW_NSCreateMonitor(CGDirectDisplayID display) {
   8043 		RGFW_monitor monitor;
   8044 
   8045 		CGRect bounds = CGDisplayBounds(display);
   8046 		monitor.rect = RGFW_RECT((int) bounds.origin.x, (int) bounds.origin.y, (int) bounds.size.width, (int) bounds.size.height);
   8047 
   8048 		CGSize screenSizeMM = CGDisplayScreenSize(display);
   8049 		monitor.physW = screenSizeMM.width;
   8050 		monitor.physH = screenSizeMM.height;
   8051 
   8052 		monitor.scaleX = ((monitor.rect.w / (screenSizeMM.width / 25.4)) / 96) + 0.25;
   8053 		monitor.scaleY = ((monitor.rect.h / (screenSizeMM.height / 25.4)) / 96) + 0.25;
   8054 
   8055 		return monitor;
   8056 	}
   8057 
   8058 
   8059 	static RGFW_monitor RGFW_monitors[7];
   8060 
   8061 	RGFW_monitor* RGFW_getMonitors(void) {
   8062 		static CGDirectDisplayID displays[7];
   8063 		u32 count;
   8064 
   8065 		if (CGGetActiveDisplayList(6, displays, &count) != kCGErrorSuccess)
   8066 			return NULL;
   8067 
   8068 		for (u32 i = 0; i < count; i++)
   8069 			RGFW_monitors[i] = RGFW_NSCreateMonitor(displays[i]);
   8070 
   8071 		return RGFW_monitors;
   8072 	}
   8073 
   8074 	RGFW_monitor RGFW_getPrimaryMonitor(void) {
   8075 		CGDirectDisplayID primary = CGMainDisplayID();
   8076 		return RGFW_NSCreateMonitor(primary);
   8077 	}
   8078 
   8079 	RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) {
   8080 		return RGFW_NSCreateMonitor(win->src.display);
   8081 	}
   8082 
   8083 	char* RGFW_readClipboard(size_t* size) {
   8084 		char* clip = (char*)NSPasteboard_stringForType(NSPasteboard_generalPasteboard(), NSPasteboardTypeString);
   8085 		
   8086 		size_t clip_len = 1;
   8087 
   8088 		if (clip != NULL) {
   8089 			clip_len = strlen(clip) + 1; 
   8090 		}
   8091 
   8092 		char* str = (char*)RGFW_MALLOC(sizeof(char) * clip_len);
   8093 		
   8094 		if (clip != NULL) {
   8095 			strncpy(str, clip, clip_len);
   8096 		}
   8097 
   8098 		str[clip_len] = '\0';
   8099 		
   8100 		if (size != NULL)
   8101 			*size = clip_len;
   8102 		return str;
   8103 	}
   8104 
   8105 	void RGFW_writeClipboard(const char* text, u32 textLen) {
   8106 		RGFW_UNUSED(textLen);
   8107 
   8108 		NSPasteboardType array[] = { NSPasteboardTypeString, NULL };
   8109 		NSPasteBoard_declareTypes(NSPasteboard_generalPasteboard(), array, 1, NULL);
   8110 
   8111 		NSPasteBoard_setString(NSPasteboard_generalPasteboard(), text, NSPasteboardTypeString);
   8112 	}
   8113 
   8114 	u16 RGFW_registerJoystick(RGFW_window* win, i32 jsNumber) {
   8115 		RGFW_UNUSED(jsNumber);
   8116 
   8117 		assert(win != NULL);
   8118 
   8119 		return RGFW_registerJoystickF(win, (char*) "");
   8120 	}
   8121 
   8122 	u16 RGFW_registerJoystickF(RGFW_window* win, char* file) {
   8123 		RGFW_UNUSED(file);
   8124 
   8125 		assert(win != NULL);
   8126 
   8127 		return RGFW_joystickCount - 1;
   8128 	}
   8129 
   8130 	#ifdef RGFW_OPENGL
   8131 	void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) {
   8132 		assert(win != NULL);
   8133 		objc_msgSend_void(win->src.ctx, sel_registerName("makeCurrentContext"));
   8134 	}
   8135 	#endif
   8136 
   8137 	#if !defined(RGFW_EGL)
   8138 	void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) {
   8139 		assert(win != NULL);
   8140 		#if defined(RGFW_OPENGL)
   8141 		
   8142 		NSOpenGLContext_setValues(win->src.ctx, &swapInterval, 222);
   8143 		#else
   8144 		RGFW_UNUSED(swapInterval);
   8145 		#endif
   8146 	}
   8147 	#endif
   8148 	
   8149 	// Function to create a CGImageRef from an array of bytes
   8150 	CGImageRef createImageFromBytes(unsigned char *buffer, int width, int height)
   8151 	{
   8152 		// Define color space
   8153         CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
   8154         // Create bitmap context
   8155         CGContextRef context = CGBitmapContextCreate(
   8156         		buffer, 
   8157         		width, height,
   8158         		8,
   8159         		RGFW_bufferSize.w * 4, 
   8160         		colorSpace,
   8161         		kCGImageAlphaPremultipliedLast);
   8162         // Create image from bitmap context
   8163         CGImageRef image = CGBitmapContextCreateImage(context);
   8164         // Release the color space and context
   8165         CGColorSpaceRelease(colorSpace);
   8166         CGContextRelease(context);
   8167                          
   8168         return image;
   8169     }
   8170 
   8171 	void RGFW_window_swapBuffers(RGFW_window* win) {
   8172 		assert(win != NULL);
   8173 		/* clear the window*/
   8174 
   8175 		if (!(win->_winArgs & RGFW_NO_CPU_RENDER)) {
   8176 #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)
   8177 			#ifdef RGFW_OSMESA
   8178 			RGFW_OSMesa_reorganize();
   8179 			#endif
   8180 
   8181 			void* view = NSWindow_contentView(win->src.window);
   8182 			void* layer = objc_msgSend_id(view, sel_registerName("layer"));
   8183 
   8184 			((void(*)(id, SEL, NSRect))objc_msgSend)(layer,
   8185 				sel_registerName("setFrame:"),
   8186 				(NSRect){{0, 0}, {win->r.w, win->r.h}});
   8187 
   8188             CGImageRef image = createImageFromBytes(win->buffer, win->r.w, win->r.h);
   8189             // Get the current graphics context
   8190             id graphicsContext = objc_msgSend_class(objc_getClass("NSGraphicsContext"), sel_registerName("currentContext"));
   8191             // Get the CGContext from the current NSGraphicsContext
   8192             id cgContext = objc_msgSend_id(graphicsContext, sel_registerName("graphicsPort"));
   8193 			// Draw the image in the context
   8194 			NSRect bounds = (NSRect){{0,0}, {win->r.w, win->r.h}};
   8195 		    CGContextDrawImage((void*)cgContext, *(CGRect*)&bounds, image);
   8196           	// Flush the graphics context to ensure the drawing is displayed
   8197             objc_msgSend_id(graphicsContext, sel_registerName("flushGraphics"));
   8198             
   8199             objc_msgSend_void_id(layer, sel_registerName("setContents:"), (id)image);
   8200             objc_msgSend_id(layer, sel_registerName("setNeedsDisplay"));
   8201             
   8202             CGImageRelease(image);
   8203 #endif
   8204 		}
   8205 
   8206 		if (!(win->_winArgs & RGFW_NO_GPU_RENDER)) {
   8207 			#ifdef RGFW_EGL
   8208 					eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface);
   8209 			#elif defined(RGFW_OPENGL)
   8210 					objc_msgSend_void(win->src.ctx, sel_registerName("flushBuffer"));
   8211 			#endif
   8212 		}
   8213 	}
   8214 
   8215 	void RGFW_window_close(RGFW_window* win) {
   8216 		assert(win != NULL);
   8217 		release(win->src.view);
   8218 
   8219 #ifdef RGFW_ALLOC_DROPFILES
   8220 		{
   8221 			u32 i;
   8222 			for (i = 0; i < RGFW_MAX_DROPS; i++)
   8223 				RGFW_FREE(win->event.droppedFiles[i]);
   8224 
   8225 
   8226 			RGFW_FREE(win->event.droppedFiles);
   8227 		}
   8228 #endif
   8229 	
   8230 #ifdef RGFW_BUFFER
   8231 		release(win->src.bitmap);
   8232 		release(win->src.image);
   8233 #endif
   8234 
   8235 		CVDisplayLinkStop(win->src.displayLink);
   8236 		CVDisplayLinkRelease(win->src.displayLink);
   8237 
   8238 		RGFW_FREE(win);
   8239 	}
   8240 
   8241 	u64 RGFW_getTimeNS(void) {
   8242 		static mach_timebase_info_data_t timebase_info;
   8243 		if (timebase_info.denom == 0) {
   8244 			mach_timebase_info(&timebase_info);
   8245 		}
   8246 		return mach_absolute_time() * timebase_info.numer / timebase_info.denom;
   8247 	}
   8248 
   8249 	u64 RGFW_getTime(void) {
   8250 		static mach_timebase_info_data_t timebase_info;
   8251 		if (timebase_info.denom == 0) {
   8252 			mach_timebase_info(&timebase_info);
   8253 		}
   8254 		return (double) mach_absolute_time() * (double) timebase_info.numer / ((double) timebase_info.denom * 1e9);
   8255 	}
   8256 #endif /* RGFW_MACOS */
   8257 
   8258 /*
   8259 	End of MaOS defines
   8260 */
   8261 
   8262 /*
   8263 	WEBASM defines
   8264 */
   8265 
   8266 #ifdef RGFW_WEBASM
   8267 RGFW_Event RGFW_events[20];
   8268 size_t RGFW_eventLen = 0;
   8269 
   8270 EM_BOOL Emscripten_on_keydown(int eventType, const EmscriptenKeyboardEvent* e, void* userData) {
   8271 	RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
   8272 	
   8273 	RGFW_events[RGFW_eventLen].type = RGFW_keyPressed;
   8274 	memcpy(RGFW_events[RGFW_eventLen].keyName, e->key, 16);
   8275 	RGFW_events[RGFW_eventLen].keyCode = RGFW_apiKeyCodeToRGFW(e->keyCode);
   8276 	RGFW_events[RGFW_eventLen].lockState = 0;
   8277 	RGFW_eventLen++;
   8278 
   8279 	RGFW_keyboard[RGFW_apiKeyCodeToRGFW(e->keyCode)].prev = RGFW_keyboard[RGFW_apiKeyCodeToRGFW(e->keyCode)].current;
   8280 	RGFW_keyboard[RGFW_apiKeyCodeToRGFW(e->keyCode)].current = 1;
   8281 	RGFW_keyCallback(RGFW_root, RGFW_apiKeyCodeToRGFW(e->keyCode), RGFW_events[RGFW_eventLen].keyName, 0, 1);
   8282 	
   8283     return EM_TRUE;
   8284 }
   8285 
   8286 EM_BOOL Emscripten_on_keyup(int eventType, const EmscriptenKeyboardEvent* e, void* userData) {
   8287 	RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
   8288 
   8289 	RGFW_events[RGFW_eventLen].type = RGFW_keyReleased;
   8290 	memcpy(RGFW_events[RGFW_eventLen].keyName, e->key, 16);
   8291 	RGFW_events[RGFW_eventLen].keyCode = RGFW_apiKeyCodeToRGFW(e->keyCode);
   8292 	RGFW_events[RGFW_eventLen].lockState = 0;
   8293 	RGFW_eventLen++;
   8294 
   8295 	RGFW_keyboard[RGFW_apiKeyCodeToRGFW(e->keyCode)].prev = RGFW_keyboard[RGFW_apiKeyCodeToRGFW(e->keyCode)].current;
   8296 	RGFW_keyboard[RGFW_apiKeyCodeToRGFW(e->keyCode)].current = 0;
   8297 
   8298 	RGFW_keyCallback(RGFW_root, RGFW_apiKeyCodeToRGFW(e->keyCode), RGFW_events[RGFW_eventLen].keyName, 0, 0);
   8299 
   8300     return EM_TRUE;
   8301 }
   8302 
   8303 EM_BOOL Emscripten_on_resize(int eventType, const EmscriptenUiEvent* e, void* userData) {
   8304 	RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
   8305 
   8306 	RGFW_events[RGFW_eventLen].type = RGFW_windowResized;
   8307 	RGFW_eventLen++;
   8308 
   8309 	RGFW_windowResizeCallback(RGFW_root, RGFW_RECT(0, 0, e->windowInnerWidth, e->windowInnerHeight));
   8310     return EM_TRUE;
   8311 }
   8312 
   8313 EM_BOOL Emscripten_on_fullscreenchange(int eventType, const EmscriptenFullscreenChangeEvent* e, void* userData) {
   8314 	RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
   8315 
   8316 	RGFW_events[RGFW_eventLen].type = RGFW_windowResized;
   8317 	RGFW_eventLen++;
   8318 
   8319 	RGFW_root->r = RGFW_RECT(0, 0, e->elementWidth, e->elementHeight);
   8320 	RGFW_windowResizeCallback(RGFW_root, RGFW_root->r);
   8321     return EM_TRUE;
   8322 }
   8323 
   8324 EM_BOOL Emscripten_on_focusin(int eventType, const EmscriptenFocusEvent* e, void* userData) {
   8325 	RGFW_UNUSED(eventType); RGFW_UNUSED(userData); RGFW_UNUSED(e);
   8326 
   8327 	RGFW_events[RGFW_eventLen].type = RGFW_focusIn;
   8328 	RGFW_eventLen++;
   8329 
   8330 	RGFW_root->event.inFocus = 1;
   8331 	RGFW_focusCallback(RGFW_root, 1);
   8332     return EM_TRUE;
   8333 }
   8334 
   8335 EM_BOOL Emscripten_on_focusout(int eventType, const EmscriptenFocusEvent* e, void* userData) {
   8336 	RGFW_UNUSED(eventType); RGFW_UNUSED(userData); RGFW_UNUSED(e);
   8337 
   8338 	RGFW_events[RGFW_eventLen].type = RGFW_focusOut;
   8339 	RGFW_eventLen++;
   8340 
   8341 	RGFW_root->event.inFocus = 0;
   8342 	RGFW_focusCallback(RGFW_root, 0);
   8343     return EM_TRUE;
   8344 }
   8345 
   8346 EM_BOOL Emscripten_on_mousemove(int eventType, const EmscriptenMouseEvent* e, void* userData) {
   8347 	RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
   8348 
   8349 	RGFW_events[RGFW_eventLen].type = RGFW_mousePosChanged;
   8350 
   8351 	if ((RGFW_root->_winArgs & RGFW_HOLD_MOUSE)) {
   8352 		RGFW_point p = RGFW_POINT(e->movementX, e->movementY);
   8353 		RGFW_events[RGFW_eventLen].point = p;
   8354 	}
   8355 	else
   8356 		RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->targetX, e->targetY);
   8357 	RGFW_eventLen++;
   8358 	
   8359 	RGFW_mousePosCallback(RGFW_root, RGFW_events[RGFW_eventLen].point);
   8360     return EM_TRUE;
   8361 }
   8362 
   8363 EM_BOOL Emscripten_on_mousedown(int eventType, const EmscriptenMouseEvent* e, void* userData) {
   8364 	RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
   8365 
   8366 	RGFW_events[RGFW_eventLen].type = RGFW_mouseButtonPressed;
   8367 	RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->targetX, e->targetY);
   8368 	RGFW_events[RGFW_eventLen].button = e->button + 1; 
   8369 	RGFW_events[RGFW_eventLen].scroll = 0;
   8370 
   8371 	RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current;	
   8372 	RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current = 1;
   8373 
   8374 	RGFW_mouseButtonCallback(RGFW_root, RGFW_events[RGFW_eventLen].button, RGFW_events[RGFW_eventLen].scroll, 1);
   8375 	RGFW_eventLen++;
   8376 	
   8377     return EM_TRUE;
   8378 }
   8379 
   8380 EM_BOOL Emscripten_on_mouseup(int eventType, const EmscriptenMouseEvent* e, void* userData) {
   8381 	RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
   8382 
   8383 	RGFW_events[RGFW_eventLen].type = RGFW_mouseButtonReleased;
   8384 	RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->targetX, e->targetY);
   8385 	RGFW_events[RGFW_eventLen].button = e->button + 1; 
   8386 	RGFW_events[RGFW_eventLen].scroll = 0;
   8387 
   8388 	RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current;	
   8389 	RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current = 0;
   8390 
   8391 	RGFW_mouseButtonCallback(RGFW_root, RGFW_events[RGFW_eventLen].button, RGFW_events[RGFW_eventLen].scroll, 0);
   8392 	RGFW_eventLen++;
   8393     return EM_TRUE;
   8394 }
   8395 
   8396 EM_BOOL Emscripten_on_wheel(int eventType, const EmscriptenWheelEvent* e, void* userData) {
   8397 	RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
   8398 
   8399 	RGFW_events[RGFW_eventLen].type = RGFW_mouseButtonPressed;
   8400 	RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->mouse.targetX, e->mouse.targetY);
   8401 	RGFW_events[RGFW_eventLen].button = RGFW_mouseScrollUp + (e->deltaY < 0); 
   8402 	RGFW_events[RGFW_eventLen].scroll = e->deltaY;
   8403 
   8404 	RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current;	
   8405 	RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current = 1;
   8406 
   8407 	RGFW_mouseButtonCallback(RGFW_root, RGFW_events[RGFW_eventLen].button, RGFW_events[RGFW_eventLen].scroll, 1);
   8408 	RGFW_eventLen++;
   8409 
   8410     return EM_TRUE;
   8411 }
   8412 
   8413 EM_BOOL Emscripten_on_touchstart(int eventType, const EmscriptenTouchEvent* e, void* userData) { 
   8414 	RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
   8415 
   8416     size_t i; 
   8417     for (i = 0; i < (size_t)e->numTouches; i++) { 
   8418 	    RGFW_events[RGFW_eventLen].type = RGFW_mouseButtonPressed;
   8419 	    RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->touches[i].targetX, e->touches[i].targetY);
   8420 	    RGFW_events[RGFW_eventLen].button = 1; 
   8421 	    RGFW_events[RGFW_eventLen].scroll = 0;
   8422 
   8423 
   8424 	    RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current;	
   8425 	    RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current = 1;
   8426 
   8427         RGFW_mousePosCallback(RGFW_root, RGFW_events[RGFW_eventLen].point);
   8428 
   8429 	    RGFW_mouseButtonCallback(RGFW_root, RGFW_events[RGFW_eventLen].button, RGFW_events[RGFW_eventLen].scroll, 1);
   8430     	RGFW_eventLen++;
   8431     }
   8432 
   8433 	return EM_TRUE;
   8434 }
   8435 EM_BOOL Emscripten_on_touchmove(int eventType, const EmscriptenTouchEvent* e, void* userData) { 
   8436 	RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
   8437     
   8438     size_t i; 
   8439     for (i = 0; i < (size_t)e->numTouches; i++) { 
   8440    	    RGFW_events[RGFW_eventLen].type = RGFW_mousePosChanged;
   8441 	    RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->touches[i].targetX, e->touches[i].targetY);
   8442 
   8443         RGFW_mousePosCallback(RGFW_root, RGFW_events[RGFW_eventLen].point);
   8444 	    RGFW_eventLen++;
   8445     }
   8446     return EM_TRUE;
   8447 }
   8448 
   8449 EM_BOOL Emscripten_on_touchend(int eventType, const EmscriptenTouchEvent* e, void* userData) {
   8450 	RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
   8451 	
   8452     size_t i; 
   8453     for (i = 0; i < (size_t)e->numTouches; i++) { 
   8454 	    RGFW_events[RGFW_eventLen].type = RGFW_mouseButtonReleased;
   8455 	    RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->touches[i].targetX, e->touches[i].targetY);
   8456 	    RGFW_events[RGFW_eventLen].button = 1; 
   8457 	    RGFW_events[RGFW_eventLen].scroll = 0;
   8458 
   8459 	    RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current;	
   8460 	    RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current = 0;
   8461         
   8462 	    RGFW_mouseButtonCallback(RGFW_root, RGFW_events[RGFW_eventLen].button, RGFW_events[RGFW_eventLen].scroll, 0);
   8463 	    RGFW_eventLen++;
   8464     }
   8465 	return EM_TRUE;
   8466 }
   8467 
   8468 EM_BOOL Emscripten_on_touchcancel(int eventType, const EmscriptenTouchEvent* e, void* userData) { RGFW_UNUSED(eventType); RGFW_UNUSED(userData); RGFW_UNUSED(e); return EM_TRUE; }
   8469 
   8470 EM_BOOL Emscripten_on_gamepad(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData) {	
   8471 	RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
   8472 
   8473 	if (gamepadEvent->index >= 4)
   8474 		return 0;
   8475 
   8476 	RGFW_joysticks[gamepadEvent->index] = gamepadEvent->connected;
   8477 
   8478     return 1; // The event was consumed by the callback handler
   8479 }
   8480 
   8481 void EMSCRIPTEN_KEEPALIVE Emscripten_onDrop(size_t count) {
   8482 	if (!(RGFW_root->_winArgs & RGFW_ALLOW_DND))
   8483 		return;
   8484 
   8485 	RGFW_events[RGFW_eventLen].droppedFilesCount = count;	
   8486 	RGFW_dndCallback(RGFW_root, RGFW_events[RGFW_eventLen].droppedFiles, count);
   8487 	RGFW_eventLen++;
   8488 }
   8489 
   8490 b8 RGFW_stopCheckEvents_bool = RGFW_FALSE;
   8491 void RGFW_stopCheckEvents(void) { 
   8492 	RGFW_stopCheckEvents_bool = RGFW_TRUE;
   8493 }
   8494 
   8495 void RGFW_window_eventWait(RGFW_window* win, i32 waitMS) {
   8496 	RGFW_UNUSED(win);
   8497 
   8498 	if (waitMS == 0)
   8499 		return;
   8500 	
   8501 	u32 start = (u32)(((u64)RGFW_getTimeNS()) / 1e+6);
   8502 
   8503 	while ((RGFW_eventLen == 0) && RGFW_stopCheckEvents_bool == RGFW_FALSE && 
   8504 		(waitMS < 0 || (RGFW_getTimeNS() / 1e+6) - start < waitMS)
   8505 	) {
   8506 		emscripten_sleep(0);
   8507 	}
   8508 	
   8509 	RGFW_stopCheckEvents_bool = RGFW_FALSE;
   8510 }
   8511 
   8512 RGFWDEF void RGFW_init_buffer(RGFW_window* win);
   8513 void RGFW_init_buffer(RGFW_window* win) {
   8514 	#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)
   8515 		if (RGFW_bufferSize.w == 0 && RGFW_bufferSize.h == 0)
   8516 			RGFW_bufferSize = RGFW_getScreenSize();
   8517 		
   8518 		win->buffer = RGFW_MALLOC(RGFW_bufferSize.w * RGFW_bufferSize.h * 4);
   8519 	#ifdef RGFW_OSMESA
   8520 			win->src.ctx = OSMesaCreateContext(OSMESA_RGBA, NULL);
   8521 			OSMesaMakeCurrent(win->src.ctx, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h);
   8522 	#endif
   8523 	#else
   8524 	RGFW_UNUSED(win); /*!< if buffer rendering is not being used */
   8525 	#endif
   8526 }
   8527 
   8528 void EMSCRIPTEN_KEEPALIVE RGFW_makeSetValue(size_t index, char* file) { 
   8529 	/* This seems like a terrible idea, don't replicate this unless you hate yourself or the OS */
   8530 	/* TODO: find a better way to do this, 
   8531 		strcpy doesn't seem to work, maybe because of asyncio
   8532 	*/
   8533 
   8534 	RGFW_events[RGFW_eventLen].type = RGFW_dnd;
   8535 	char** arr = (char**)&RGFW_events[RGFW_eventLen].droppedFiles[index];
   8536 	*arr = file;
   8537 }
   8538 
   8539 #include <sys/stat.h>
   8540 #include <sys/types.h>
   8541 #include <errno.h>
   8542 
   8543 void EMSCRIPTEN_KEEPALIVE RGFW_mkdir(char* name) { mkdir(name, 0755); }
   8544 
   8545 void EMSCRIPTEN_KEEPALIVE RGFW_writeFile(const char *path, const char *data, size_t len) {
   8546     FILE* file = fopen(path, "w+");
   8547 	if (file == NULL)
   8548 		return;
   8549 
   8550     fwrite(data, sizeof(char), len, file);
   8551     fclose(file);
   8552 }
   8553 
   8554 RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) {
   8555 	RGFW_UNUSED(name) 
   8556 
   8557 	RGFW_UNUSED(RGFW_initFormatAttribs);
   8558 	
   8559     RGFW_window* win = RGFW_window_basic_init(rect, args);
   8560 	
   8561 #ifndef RGFW_WEBGPU
   8562     EmscriptenWebGLContextAttributes attrs;
   8563     attrs.alpha = EM_TRUE;
   8564     attrs.depth = EM_TRUE;
   8565 	attrs.alpha = EM_TRUE;
   8566     attrs.stencil = RGFW_STENCIL;
   8567     attrs.antialias = RGFW_SAMPLES;
   8568     attrs.premultipliedAlpha = EM_TRUE;
   8569     attrs.preserveDrawingBuffer = EM_FALSE;
   8570 	
   8571     if (RGFW_DOUBLE_BUFFER == 0)
   8572         attrs.renderViaOffscreenBackBuffer = 0;
   8573     else
   8574         attrs.renderViaOffscreenBackBuffer = RGFW_AUX_BUFFERS;
   8575     
   8576     attrs.failIfMajorPerformanceCaveat = EM_FALSE;
   8577 	attrs.majorVersion = (RGFW_majorVersion == 0) ? 1 : RGFW_majorVersion;
   8578 	attrs.minorVersion = RGFW_minorVersion;
   8579 	
   8580     attrs.enableExtensionsByDefault = EM_TRUE;
   8581     attrs.explicitSwapControl = EM_TRUE;
   8582 
   8583     emscripten_webgl_init_context_attributes(&attrs);
   8584     win->src.ctx = emscripten_webgl_create_context("#canvas", &attrs);
   8585     emscripten_webgl_make_context_current(win->src.ctx);
   8586 
   8587 	#ifdef LEGACY_GL_EMULATION
   8588 	EM_ASM("Module.useWebGL = true; GLImmediate.init();");	
   8589 	#endif
   8590 #else
   8591 	win->src.ctx = wgpuCreateInstance(NULL);
   8592     win->src.device = emscripten_webgpu_get_device();
   8593     win->src.queue = wgpuDeviceGetQueue(win->src.device);
   8594 #endif
   8595 
   8596 	emscripten_set_canvas_element_size("#canvas", rect.w, rect.h);
   8597 	emscripten_set_window_title(name);
   8598 
   8599 	/* load callbacks */
   8600     emscripten_set_keydown_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, Emscripten_on_keydown);
   8601     emscripten_set_keyup_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, Emscripten_on_keyup);
   8602     emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, Emscripten_on_resize);
   8603     emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, NULL, EM_FALSE, Emscripten_on_fullscreenchange);
   8604     emscripten_set_mousemove_callback("#canvas", NULL, EM_FALSE, Emscripten_on_mousemove);
   8605     emscripten_set_touchstart_callback("#canvas", NULL, EM_FALSE, Emscripten_on_touchstart);
   8606     emscripten_set_touchend_callback("#canvas", NULL, EM_FALSE, Emscripten_on_touchend);
   8607     emscripten_set_touchmove_callback("#canvas", NULL, EM_FALSE, Emscripten_on_touchmove);
   8608     emscripten_set_touchcancel_callback("#canvas", NULL, EM_FALSE, Emscripten_on_touchcancel);
   8609     emscripten_set_mousedown_callback("#canvas", NULL, EM_FALSE, Emscripten_on_mousedown);
   8610     emscripten_set_mouseup_callback("#canvas", NULL, EM_FALSE, Emscripten_on_mouseup);
   8611     emscripten_set_wheel_callback("#canvas", NULL, EM_FALSE, Emscripten_on_wheel);
   8612     emscripten_set_focusin_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, Emscripten_on_focusin);
   8613     emscripten_set_focusout_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, Emscripten_on_focusout);
   8614 	emscripten_set_gamepadconnected_callback(NULL, 1, Emscripten_on_gamepad);
   8615 	emscripten_set_gamepaddisconnected_callback(NULL, 1, Emscripten_on_gamepad);
   8616 	
   8617 	if (args & RGFW_ALLOW_DND)  {
   8618 		win->_winArgs |= RGFW_ALLOW_DND;
   8619 	}
   8620 
   8621     EM_ASM({
   8622 		var canvas = document.getElementById('canvas');
   8623         canvas.addEventListener('drop', function(e) {
   8624             e.preventDefault();
   8625             if (e.dataTransfer.file < 0)
   8626 				return;
   8627 
   8628 			var filenamesArray = [];
   8629 			var count = e.dataTransfer.files.length;
   8630 
   8631 			/* Read and save the files to emscripten's files */
   8632 			var drop_dir = '.rgfw_dropped_files';
   8633 			Module._RGFW_mkdir(drop_dir);
   8634 
   8635 			for (var i = 0; i < count; i++) {
   8636 				var file = e.dataTransfer.files[i];
   8637 
   8638 				var path = '/' + drop_dir + '/' + file.name.replace("//", '_');
   8639 				var reader = new FileReader();
   8640 				
   8641 				reader.onloadend = (e) => {
   8642 					if (reader.readyState != 2) {
   8643 						out('failed to read dropped file: '+file.name+': '+reader.error);
   8644 					}
   8645 					else {
   8646 						var data = e.target.result;
   8647 						
   8648 						_RGFW_writeFile(path, new Uint8Array(data), file.size);
   8649 					}
   8650 				};
   8651 
   8652 				reader.readAsArrayBuffer(file);		
   8653 				// This works weird on modern opengl
   8654 				var filename = stringToNewUTF8(path);
   8655 
   8656 				filenamesArray.push(filename);
   8657 				
   8658 				Module._RGFW_makeSetValue(i, filename);
   8659 			}
   8660 			
   8661 			Module._Emscripten_onDrop(count);
   8662 			
   8663 			for (var i = 0; i < count; ++i) {
   8664 				_free(filenamesArray[i]);
   8665 			}
   8666         }, true);
   8667 
   8668         canvas.addEventListener('dragover', function(e) { e.preventDefault(); return false; }, true);
   8669     });
   8670 
   8671 	RGFW_init_buffer(win);
   8672 	glViewport(0, 0, rect.w, rect.h);
   8673 	
   8674 	RGFW_root = win; 
   8675 
   8676 	if (args & RGFW_HIDE_MOUSE) {
   8677 		RGFW_window_showMouse(win, 0);
   8678 	}
   8679 
   8680 	if (args & RGFW_FULLSCREEN) {
   8681 		RGFW_window_resize(win, RGFW_getScreenSize());
   8682 	}
   8683 
   8684     return win;
   8685 }
   8686 
   8687 RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) {
   8688 	static u8 index = 0;
   8689 	
   8690 	if (index == 0) 
   8691 		RGFW_resetKey();
   8692 
   8693 	/* check gamepads */
   8694     for (int i = 0; (i < emscripten_get_num_gamepads()) && (i < 4); i++) {
   8695 		if (RGFW_joysticks[i] == 0)
   8696 			continue;;
   8697 		
   8698         EmscriptenGamepadEvent gamepadState;
   8699 
   8700         if (emscripten_get_gamepad_status(i, &gamepadState) != EMSCRIPTEN_RESULT_SUCCESS)
   8701 			break;
   8702 
   8703 		// Register buttons data for every connected gamepad
   8704 		for (int j = 0; (j < gamepadState.numButtons) && (j < 16); j++) {
   8705 			u32 map[] = {
   8706 				RGFW_JS_A, RGFW_JS_X, RGFW_JS_B, RGFW_JS_Y,
   8707 				RGFW_JS_L1, RGFW_JS_R1, RGFW_JS_L2, RGFW_JS_R2,
   8708 				RGFW_JS_SELECT, RGFW_JS_START,
   8709 				0, 0,
   8710 				RGFW_JS_UP, RGFW_JS_DOWN, RGFW_JS_LEFT, RGFW_JS_RIGHT
   8711 			};
   8712 
   8713 			u32 button = map[j]; 
   8714 			if (RGFW_jsPressed[i][button] != gamepadState.digitalButton[j]) {
   8715 				win->event.type = RGFW_jsButtonPressed;
   8716 				win->event.joystick = i;
   8717 				win->event.button = map[j];
   8718 				return &win->event;
   8719 			}
   8720 
   8721 			RGFW_jsPressed[i][button] = gamepadState.digitalButton[j];
   8722 		}
   8723 
   8724 		for (int j = 0; (j < gamepadState.numAxes) && (j < 4); j += 2) {
   8725 			win->event.axisesCount = gamepadState.numAxes;
   8726 			if (win->event.axis[j].x != gamepadState.axis[j] || 
   8727 				win->event.axis[j].y != gamepadState.axis[j + 1]
   8728 			) {
   8729 				win->event.axis[j].x = gamepadState.axis[j];
   8730 				win->event.axis[j].y = gamepadState.axis[j + 1];
   8731 				win->event.type = RGFW_jsAxisMove;
   8732 				win->event.joystick = i;
   8733 				return &win->event;
   8734 			}
   8735 		}
   8736     }
   8737 
   8738 	/* check queued events */
   8739 	if (RGFW_eventLen == 0)
   8740 		return NULL;
   8741 	
   8742 	RGFW_events[index].frameTime = win->event.frameTime;
   8743 	RGFW_events[index].frameTime2 = win->event.frameTime2;
   8744 	RGFW_events[index].inFocus = win->event.inFocus;
   8745 
   8746 	win->event = RGFW_events[index];
   8747 
   8748 	RGFW_eventLen--;
   8749 
   8750 	if (RGFW_eventLen)
   8751 		index++;
   8752 	else
   8753 		index = 0;
   8754 
   8755 	return &win->event;
   8756 }
   8757 
   8758 void RGFW_window_resize(RGFW_window* win, RGFW_area a) {
   8759 	RGFW_UNUSED(win)
   8760 	emscripten_set_canvas_element_size("#canvas", a.w, a.h);
   8761 }
   8762 
   8763 /* NOTE: I don't know if this is possible */
   8764 void RGFW_window_moveMouse(RGFW_window* win, RGFW_point v) { RGFW_UNUSED(win); RGFW_UNUSED(v); }
   8765 /* this one might be possible but it looks iffy */
   8766 void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels) { RGFW_UNUSED(win); RGFW_UNUSED(channels) RGFW_UNUSED(a) RGFW_UNUSED(image) }
   8767 
   8768 const char RGFW_CURSORS[11][12] = {
   8769     "default",
   8770     "default",
   8771     "text",
   8772     "crosshair",
   8773     "pointer",
   8774     "ew-resize",
   8775     "ns-resize",
   8776     "nwse-resize",
   8777     "nesw-resize",
   8778     "move",
   8779     "not-allowed"
   8780 };
   8781 
   8782 void RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse) {
   8783 	RGFW_UNUSED(win)
   8784 	EM_ASM( { document.getElementById("canvas").style.cursor = UTF8ToString($0); }, RGFW_CURSORS[mouse]);
   8785 }
   8786 
   8787 void RGFW_window_setMouseDefault(RGFW_window* win) {
   8788 	RGFW_window_setMouseStandard(win, RGFW_MOUSE_NORMAL);
   8789 }
   8790 
   8791 void RGFW_window_showMouse(RGFW_window* win, i8 show) {
   8792 	if (show)
   8793 		RGFW_window_setMouseDefault(win);
   8794 	else
   8795 		EM_ASM(document.getElementById('canvas').style.cursor = 'none';);
   8796 }
   8797 
   8798 RGFW_point RGFW_getGlobalMousePoint(void) {
   8799     RGFW_point point;
   8800     point.x = EM_ASM_INT({
   8801         return window.mouseX || 0;
   8802     });
   8803     point.y = EM_ASM_INT({
   8804         return window.mouseY || 0;
   8805     });
   8806     return point;
   8807 }
   8808 
   8809 RGFW_point RGFW_window_getMousePoint(RGFW_window* win) {
   8810 	RGFW_UNUSED(win);
   8811 	
   8812 	EmscriptenMouseEvent mouseEvent;
   8813     emscripten_get_mouse_status(&mouseEvent);
   8814 	return RGFW_POINT( mouseEvent.targetX,  mouseEvent.targetY);
   8815 }
   8816 
   8817 void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) {
   8818 	RGFW_UNUSED(win);
   8819 
   8820     EM_ASM_({
   8821         var canvas = document.getElementById('canvas');
   8822         if ($0) {
   8823             canvas.style.pointerEvents = 'none';
   8824         } else {
   8825             canvas.style.pointerEvents = 'auto';
   8826         }
   8827     }, passthrough);
   8828 }
   8829 
   8830 void RGFW_writeClipboard(const char* text, u32 textLen) {
   8831 	RGFW_UNUSED(textLen)
   8832 	EM_ASM({ navigator.clipboard.writeText(UTF8ToString($0)); }, text);
   8833 }
   8834 
   8835 
   8836 char* RGFW_readClipboard(size_t* size) {
   8837 	/*
   8838 		placeholder code for later
   8839 		I'm not sure if this is possible do the the async stuff
   8840 	*/
   8841 	
   8842 	if (size != NULL)
   8843 		*size = 0;
   8844 	
   8845 	char* str = (char*)malloc(1);
   8846 	str[0] = '\0';
   8847 
   8848 	return str;
   8849 }
   8850 
   8851 void RGFW_window_swapBuffers(RGFW_window* win) {
   8852 	RGFW_UNUSED(win);
   8853 	
   8854 	#ifdef RGFW_BUFFER
   8855 	if (!(win->_winArgs & RGFW_NO_CPU_RENDER)) {		
   8856 		glEnable(GL_TEXTURE_2D);
   8857 
   8858 		GLuint texture;
   8859 		glGenTextures(1,&texture);
   8860 
   8861 		glBindTexture(GL_TEXTURE_2D,texture);
   8862 		
   8863 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
   8864 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
   8865 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   8866 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
   8867 
   8868 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, RGFW_bufferSize.w, RGFW_bufferSize.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, win->buffer);
   8869 		
   8870 		float ratioX = ((float)win->r.w / (float)RGFW_bufferSize.w);
   8871 		float ratioY = ((float)win->r.h / (float)RGFW_bufferSize.h);
   8872 
   8873 		// Set up the viewport
   8874 		glClear(GL_COLOR_BUFFER_BIT);
   8875 
   8876 		glBegin(GL_TRIANGLES);
   8877 			glTexCoord2f(0, ratioY); glColor3f(1, 1, 1); glVertex2f(-1, -1);
   8878 			glTexCoord2f(0, 0); glColor3f(1, 1, 1); glVertex2f(-1, 1);
   8879 			glTexCoord2f(ratioX, ratioY); glColor3f(1, 1, 1); glVertex2f(1, -1);
   8880 
   8881 			glTexCoord2f(ratioX, 0); glColor3f(1, 1, 1); glVertex2f(1, 1);
   8882 			glTexCoord2f(ratioX, ratioY); glColor3f(1, 1, 1); glVertex2f(1, -1);
   8883 			glTexCoord2f(0, 0); glColor3f(1, 1, 1); glVertex2f(-1, 1);
   8884 		glEnd();
   8885 
   8886 		glDeleteTextures(1, &texture);
   8887 	}
   8888 	#endif
   8889 
   8890 #ifndef RGFW_WEBGPU
   8891 	emscripten_webgl_commit_frame();
   8892 #endif
   8893 	emscripten_sleep(0);
   8894 }
   8895 
   8896 
   8897 void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) {
   8898 #ifndef RGFW_WEBGPU
   8899 	if (win == NULL)
   8900 	    emscripten_webgl_make_context_current(0);
   8901 	else
   8902 	    emscripten_webgl_make_context_current(win->src.ctx);
   8903 #endif
   8904 }
   8905 
   8906 #ifndef RGFW_EGL
   8907 void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) { RGFW_UNUSED(win); RGFW_UNUSED(swapInterval); }
   8908 #endif
   8909 
   8910 void RGFW_window_close(RGFW_window* win) {
   8911 #ifndef RGFW_WEBGPU
   8912 	emscripten_webgl_destroy_context(win->src.ctx);
   8913 #endif
   8914 
   8915     free(win);
   8916 }
   8917 
   8918 int RGFW_innerWidth(void) {   return EM_ASM_INT({ return window.innerWidth; });  }
   8919 int RGFW_innerHeight(void) {  return EM_ASM_INT({ return window.innerHeight; });  }
   8920 
   8921 RGFW_area RGFW_getScreenSize(void) {
   8922 	return RGFW_AREA(RGFW_innerWidth(), RGFW_innerHeight());
   8923 }
   8924 
   8925 void* RGFW_getProcAddress(const char* procname) { 
   8926 	return emscripten_webgl_get_proc_address(procname);
   8927 }
   8928 
   8929 void RGFW_sleep(u64 milisecond) {
   8930 	emscripten_sleep(milisecond);
   8931 }
   8932 
   8933 u64 RGFW_getTimeNS(void) {
   8934 	return emscripten_get_now() * 1e+6;
   8935 }
   8936 
   8937 u64 RGFW_getTime(void) {
   8938 	return emscripten_get_now() * 1000;
   8939 }
   8940 
   8941 void RGFW_releaseCursor(RGFW_window* win) {
   8942 	RGFW_UNUSED(win);
   8943 	emscripten_exit_pointerlock();
   8944 }
   8945 
   8946 void RGFW_captureCursor(RGFW_window* win, RGFW_rect r) { 
   8947 	RGFW_UNUSED(win); RGFW_UNUSED(r);
   8948 
   8949 	emscripten_request_pointerlock("#canvas", 1);
   8950 }
   8951 
   8952 
   8953 void RGFW_window_setName(RGFW_window* win, char* name) {
   8954 	RGFW_UNUSED(win);
   8955 	emscripten_set_window_title(name);
   8956 }
   8957 
   8958 /* unsupported functions */
   8959 RGFW_monitor* RGFW_getMonitors(void) { return NULL; }
   8960 RGFW_monitor RGFW_getPrimaryMonitor(void) { return (RGFW_monitor){}; }
   8961 void RGFW_window_move(RGFW_window* win, RGFW_point v) { RGFW_UNUSED(win) RGFW_UNUSED(v) }
   8962 void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) { RGFW_UNUSED(win) RGFW_UNUSED(a)  }
   8963 void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) { RGFW_UNUSED(win) RGFW_UNUSED(a)  }
   8964 void RGFW_window_minimize(RGFW_window* win) { RGFW_UNUSED(win)}
   8965 void RGFW_window_restore(RGFW_window* win) { RGFW_UNUSED(win) }
   8966 void RGFW_window_setBorder(RGFW_window* win, b8 border) { RGFW_UNUSED(win) RGFW_UNUSED(border)  }
   8967 void RGFW_window_setIcon(RGFW_window* win, u8* icon, RGFW_area a, i32 channels) { RGFW_UNUSED(win) RGFW_UNUSED(icon) RGFW_UNUSED(a) RGFW_UNUSED(channels)  }
   8968 void RGFW_window_hide(RGFW_window* win) { RGFW_UNUSED(win) }
   8969 void RGFW_window_show(RGFW_window* win) {RGFW_UNUSED(win) }
   8970 b8 RGFW_window_isHidden(RGFW_window* win) { RGFW_UNUSED(win) return 0; }
   8971 b8 RGFW_window_isMinimized(RGFW_window* win) { RGFW_UNUSED(win) return 0; }
   8972 b8 RGFW_window_isMaximized(RGFW_window* win) { RGFW_UNUSED(win) return 0; }
   8973 RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) { RGFW_UNUSED(win) return (RGFW_monitor){}; }
   8974 
   8975 #endif
   8976 
   8977 /* end of web asm defines */
   8978 
   8979 /* unix (macOS, linux, web asm) only stuff */
   8980 #if defined(RGFW_X11) || defined(RGFW_MACOS) || defined(RGFW_WEBASM)  || defined(RGFW_WAYLAND)
   8981 /* unix threading */
   8982 #ifndef RGFW_NO_THREADS
   8983 #include <pthread.h>
   8984 
   8985 	RGFW_thread RGFW_createThread(RGFW_threadFunc_ptr ptr, void* args) {
   8986 		RGFW_UNUSED(args);
   8987 		
   8988 		RGFW_thread t;
   8989 		pthread_create((pthread_t*) &t, NULL, *ptr, NULL);
   8990 		return t;
   8991 	}
   8992 	void RGFW_cancelThread(RGFW_thread thread) { pthread_cancel((pthread_t) thread); }
   8993 	void RGFW_joinThread(RGFW_thread thread) { pthread_join((pthread_t) thread, NULL); }
   8994 #ifdef __linux__
   8995 	void RGFW_setThreadPriority(RGFW_thread thread, u8 priority) { pthread_setschedprio((pthread_t)thread, priority); }
   8996 #endif
   8997 #endif
   8998 
   8999 #ifndef RGFW_WEBASM
   9000 /* unix sleep */
   9001 	void RGFW_sleep(u64 ms) {
   9002 		struct timespec time;
   9003 		time.tv_sec = 0;
   9004 		time.tv_nsec = ms * 1e+6;
   9005 
   9006 		nanosleep(&time, NULL);
   9007 	}
   9008 #endif
   9009 
   9010 #endif /* end of unix / mac stuff*/
   9011 #endif /*RGFW_IMPLEMENTATION*/
   9012 
   9013 #if defined(__cplusplus) && !defined(__EMSCRIPTEN__)
   9014 }
   9015 #endif