commit 7869c92

uint  ·  2026-07-13 19:19:12 +0000 UTC
parent 2627aa1
replace rgfw with libmaus backend
5 files changed,  +74, -16168
+5, -2
 1@@ -1,6 +1,6 @@
 2 CC = cc
 3 CFLAGS = -std=c99 -Wall -Wextra
 4-CPPFLAGS = -Isource/external -Isource/include
 5+CPPFLAGS = -Isource/include -Ilibmaus/include
 6 
 7 LDFLAGS = -lschrift -lgrapheme -lm
 8 
 9@@ -10,7 +10,10 @@ SRCS = source/cterm.c \
10        source/utils.c  \
11        source/font.c  \
12        source/term.c  \
13-       source/draw.c
14+       source/draw.c  \
15+       libmaus/source/maus.c     \
16+       libmaus/source/maus_x11.c \
17+       libmaus/source/utils.c
18 OUT = cterm
19 
20 all:
+2, -1
 1@@ -5,13 +5,14 @@
 2 #include <stdint.h>
 3 #include <stdlib.h>
 4 
 5-static const char* font_path = "./Xanh.bdf";
 6+static const char* font_path = "/home/seiko/programming/c/cterm/Xanh.bdf";
 7 static const float font_size = 24.0f; /* Bitmap fonts ignore font_size */
 8 static const int   antialias = true;  /* Bitmap fonts are not affected */
 9 
10 static const int   win_width = 80;  /* in columns */
11 static const int   win_height = 24; /* in rows */
12 static const char* win_title = "cterm";
13+static const int   win_fps = 60;
14 
15 static const int   pad_x = 8;
16 static const int   pad_y = 8;
+67, -111
  1@@ -1,5 +1,3 @@
  2-#include <sys/wait.h>
  3-#define RGFW_IMPLEMENTATION
  4 #include <errno.h>
  5 #include <fcntl.h>
  6 #include <locale.h>
  7@@ -16,7 +14,7 @@
  8 #endif
  9 #include <unistd.h>
 10 
 11-#include <RGFW.h>
 12+#include <maus.h>
 13 #include <schrift.h>
 14 
 15 #include "config.h"
 16@@ -26,21 +24,19 @@
 17 #include "utils.h"
 18 
 19 static void cleanup(void);
 20-static void handle_key(RGFW_event ev);
 21+static void handle_key(const MausEvent* ev);
 22 static void init(void);
 23 static bool ptyread(void);
 24 static void ptywrite(const char* s, size_t n);
 25 static void resize_pty(void);
 26-static int resize_surface(int w, int h);
 27+static int resize_window(int w, int h);
 28 static void resize_terminal(int w, int h);
 29 static void run(void);
 30 static void wait_events(void);
 31 
 32 static Fontface font;
 33 static Caret car;
 34-static RGFW_window* win = NULL;
 35-static RGFW_surface* surf = NULL;
 36-static uint32_t* pixels = NULL;
 37+static Maus* win = NULL;
 38 static int winw;
 39 static int winh;
 40 
 41@@ -64,12 +60,10 @@ static void cleanup(void)
 42 	free(term.alt);
 43 	font_free(&font);
 44 
 45-	if (surf)
 46-		RGFW_surface_free(surf);
 47-	if (pixels)
 48-		free(pixels);
 49-	if (win)
 50-		RGFW_window_close(win);
 51+	if (win) {
 52+		maus_close(win);
 53+		free(win);
 54+	}
 55 }
 56 
 57 /**
 58@@ -77,56 +71,34 @@ static void cleanup(void)
 59  *
 60  * @param c character check dispatch
 61  */
 62-static void handle_key(RGFW_event ev)
 63+static void handle_key(const MausEvent* ev)
 64 {
 65-	int skip_keypress = 0;
 66-
 67-	/* regular character-
 68-	   dont have to handle e.g. shift cases:
 69-	   SHIFT+1 or `!`
 70-	 */
 71-	if (ev.type == RGFW_keyChar) {
 72-		uint32_t cp = ev.keyChar.value;
 73-
 74-		skip_keypress = 1; /* key handled */
 75+	char text;
 76 
 77-		if (cp <= 0x7F) {
 78-			char cpch = (char)cp;
 79-			ptywrite(&cpch, 1);
 80-			return;
 81-		}
 82-
 83-		/* TODO? encode non ascii->UTF-8 */
 84+	if (ev->type != MAUS_EV_KEY || !ev->key.pressed)
 85 		return;
 86-	}
 87 
 88-	/* special character */
 89-	if (ev.type == RGFW_keyPressed) {
 90-		RGFW_key key = ev.key.value;
 91-
 92-		if (skip_keypress) {
 93-			skip_keypress = 0;
 94-			return;
 95-		}
 96-
 97-		switch(key) {
 98-		case RGFW_keyReturn:
 99-		case RGFW_keyPadReturn: ptywrite("\r", 1); break;
100-		case RGFW_keyBackSpace: ptywrite("\x7F", 1); break;
101-		case RGFW_keyTab:       ptywrite("\t",  1); break;
102-		case RGFW_keyEscape:    ptywrite("\x1B", 1); break;
103-		case RGFW_keyUp:        ptywrite("\x1B[A", 3); break;
104-		case RGFW_keyDown:      ptywrite("\x1B[B", 3); break;
105-		case RGFW_keyRight:     ptywrite("\x1B[C", 3); break;
106-		case RGFW_keyLeft:      ptywrite("\x1B[D", 3); break;
107-		case RGFW_keyHome:      ptywrite("\x1B[H", 3); break;
108-		case RGFW_keyEnd:       ptywrite("\x1B[F", 3); break;
109-		case RGFW_keyInsert:    ptywrite("\x1B[2~", 4); break;
110-		case RGFW_keyDelete:    ptywrite("\x1B[3~", 4); break;
111-		case RGFW_keyPageUp:    ptywrite("\x1B[5~", 4); break;
112-		case RGFW_keyPageDown:  ptywrite("\x1B[6~", 4); break;
113-		default: break;
114-		}
115+	switch(ev->key.key) {
116+	case MAUS_KEY_ENTER:
117+	case MAUS_KEY_KP_ENTER: ptywrite("\r", 1); break;
118+	case MAUS_KEY_BACKSPACE: ptywrite("\x7F", 1); break;
119+	case MAUS_KEY_TAB:       ptywrite("\t",  1); break;
120+	case MAUS_KEY_ESCAPE:    ptywrite("\x1B", 1); break;
121+	case MAUS_KEY_UP:        ptywrite("\x1B[A", 3); break;
122+	case MAUS_KEY_DOWN:      ptywrite("\x1B[B", 3); break;
123+	case MAUS_KEY_RIGHT:     ptywrite("\x1B[C", 3); break;
124+	case MAUS_KEY_LEFT:      ptywrite("\x1B[D", 3); break;
125+	case MAUS_KEY_HOME:      ptywrite("\x1B[H", 3); break;
126+	case MAUS_KEY_END:       ptywrite("\x1B[F", 3); break;
127+	case MAUS_KEY_INSERT:    ptywrite("\x1B[2~", 4); break;
128+	case MAUS_KEY_DELETE:    ptywrite("\x1B[3~", 4); break;
129+	case MAUS_KEY_PAGE_UP:   ptywrite("\x1B[5~", 4); break;
130+	case MAUS_KEY_PAGE_DOWN: ptywrite("\x1B[6~", 4); break;
131+	default:
132+		text = ev->key.text;
133+		if (text != '\0')
134+			ptywrite(&text, 1);
135+		break;
136 	}
137 }
138 
139@@ -149,19 +121,12 @@ static void init(void)
140 		die(1, "failed to resize terminal");
141 
142 	/* window */
143-	if (!(win = RGFW_createWindow(win_title, 0, 0, winw, winh, 0)))
144+	win = maus_init(win_title, 0, 0, winw, winh);
145+	if (!win)
146+		die(1, "failed to init window");
147+	if (!maus_create_window(win))
148 		die(1, "failed to create window");
149 
150-	pixels = calloc(winw*winh, sizeof(*pixels));
151-	if (!pixels)
152-		die(1, "failed to alloc pixel buffer");
153-
154-	surf = RGFW_window_createSurface(
155-		win, (u8*)pixels, winw, winh, RGFW_formatRGBA8
156-	);
157-	if (!surf)
158-		die(1, "failed to create window surface");
159-
160 	/* pty */
161 	struct winsize ws = {
162 		.ws_col = term.cols,
163@@ -258,36 +223,20 @@ static void resize_pty(void)
164 }
165 
166 /** 
167- * @brief resize window surface to reflect resized size
168+ * @brief resize window framebuffer to reflect resized size
169  */
170-static int resize_surface(int w, int h)
171+static int resize_window(int w, int h)
172 {
173-	uint32_t* npixels;
174-	RGFW_surface* nsurf;
175-
176 	if (w < 1)
177 		w = 1;
178 	if (h < 1)
179 		h = 1;
180 
181-	npixels = calloc(w*h, sizeof(*npixels));
182-	if (!npixels)
183-		return -1;
184+	if (w == winw && h == winh)
185+		return 0;
186 
187-	nsurf = RGFW_window_createSurface(
188-		win, (u8*)npixels, w, h, RGFW_formatRGBA8
189-	);
190-	if (!nsurf) {
191-		free(npixels);
192+	if (!maus_resize(win, w, h))
193 		return -1;
194-	}
195-
196-	if (surf)
197-		RGFW_surface_free(surf);
198-	free(pixels);
199-
200-	pixels = npixels;
201-	surf = nsurf;
202 	winw = w;
203 	winh = h;
204 
205@@ -320,34 +269,36 @@ static void resize_terminal(int w, int h)
206  */
207 static void run(void)
208 {
209-	RGFW_event ev;
210+	MausEvent ev;
211 	Caret ocar = { -1, -1 };
212+	bool running = true;
213 	bool dirty = true;
214 	bool redraw_all = true;
215 
216-	while (!RGFW_window_shouldClose(win)) {
217-		while (RGFW_window_checkEvent(win, &ev)) {
218-			if (ev.type == RGFW_windowResized) {
219-				if (resize_surface(ev.update.w, ev.update.h) < 0)
220-					die(EXIT_FAILURE, "failed to resize surface");
221-				resize_terminal(ev.update.w, ev.update.h);
222-				term_damage_all(&term);
223-				dirty = true;
224-				continue;
225+	while (running) {
226+		while (maus_event_poll(win, &ev)) {
227+			if (ev.type == MAUS_EV_CLOSE) {
228+				running = false;
229+				break;
230 			}
231 
232-			if (ev.type == RGFW_windowRefresh ||
233-			    ev.type == RGFW_windowFocusIn ||
234-			    ev.type == RGFW_windowRestored) {
235+			if (ev.type == MAUS_EV_RESIZE) {
236+				if (resize_window(ev.resize.width, ev.resize.height) < 0)
237+					die(EXIT_FAILURE, "failed to resize window");
238+				resize_terminal(ev.resize.width, ev.resize.height);
239 				term_damage_all(&term);
240 				dirty = true;
241 				redraw_all = true;
242 				continue;
243 			}
244 
245-			handle_key(ev);
246+
247+			handle_key(&ev);
248 		}
249 
250+		if (!running)
251+			break;
252+
253 		if (ptyread())
254 			dirty = true;
255 
256@@ -363,7 +314,7 @@ static void run(void)
257 		}
258 
259 		if (redraw_all) {
260-			draw_clear(pixels, winw, winh, rgba(0, 0, 0, 255));
261+			draw_clear(win->bfb, win->stride, winh, rgba(0, 0, 0, 255));
262 		}
263 
264 		for (int y = 0; y < term.rows; y++) {
265@@ -379,13 +330,13 @@ static void run(void)
266 					continue;
267 
268 				draw_rune(
269-					pixels, winw, winh, x, y,
270+					win->bfb, win->stride, winh, x, y,
271 					font.cellw, font.cellh, bg
272 				);
273 
274 				if (r->cp != ' ') {
275 					draw_codepoint(
276-						&font, pixels, winw, winh,
277+						&font, win->bfb, win->stride, winh,
278 						x * font.cellw,
279 						y * font.cellh + (int)font.asc,
280 						r->cp,
281@@ -397,7 +348,8 @@ static void run(void)
282 			}
283 		}
284 
285-		RGFW_window_blitSurface(win, surf);
286+		maus_target_fps(win, win_fps);
287+		maus_present(win);
288 
289 		ocar = car;
290 		dirty = false;
291@@ -416,7 +368,11 @@ static void wait_events(void)
292 	};
293 
294 	if (term.ptyfd < 0) {
295-		RGFW_waitForEvent(16);
296+		struct timespec ts = {
297+			.tv_sec = 0,
298+			.tv_nsec = 16 * 1000 * 1000, /* TODO? libmaus */
299+		};
300+		nanosleep(&ts, NULL);
301 		return;
302 	}
303 
+0, -20
 1@@ -1,20 +0,0 @@
 2-zlib License
 3-
 4-Copyright (C) 2022-2025 Riley Mabb (@ColleagueRiley)
 5-
 6-This software is provided 'as-is', without any express or implied
 7-warranty.  In no event will the authors be held liable for any damages
 8-arising from the use of this software.
 9-
10-Permission is granted to anyone to use this software for any purpose,
11-including commercial applications, and to alter it and redistribute it
12-freely, subject to the following restrictions:
13-  
14-1. The origin of this software must not be misrepresented; you must not
15-   claim that you wrote the original software. If you use this software
16-   in a product, an acknowledgment in the product documentation would be
17-   appreciated but is not required. 
18-2. Altered source versions must be plainly marked as such, and must not be
19-   misrepresented as being the original software.
20-3. This notice may not be removed or altered from any source distribution.
21-
+0, -16034
    1@@ -1,16034 +0,0 @@
    2-/*
    3-*
    4-*	RGFW 2.0.0-dev
    5-
    6-* Copyright (C) 2022-26 Riley Mabb (@ColleagueRiley)
    7-*
    8-* libpng license
    9-*
   10-* This software is provided 'as-is', without any express or implied
   11-* warranty.  In no event will the authors be held liable for any damages
   12-* arising from the use of this software.
   13-
   14-* Permission is granted to anyone to use this software for any purpose,
   15-* including commercial applications, and to alter it and redistribute it
   16-* freely, subject to the following restrictions:
   17-*
   18-* 1. The origin of this software must not be misrepresented; you must not
   19-*    claim that you wrote the original software. If you use this software
   20-*    in a product, an acknowledgment in the product documentation would be
   21-*    appreciated but is not required.
   22-* 2. Altered source versions must be plainly marked as such, and must not be
   23-*    misrepresented as being the original software.
   24-* 3. This notice may not be removed or altered from any source distribution.
   25-*
   26-*
   27-*/
   28-
   29-/*
   30-	(MAKE SURE RGFW_IMPLEMENTATION is in exactly one header or you use -D RGFW_IMPLEMENTATION)
   31-	#define RGFW_IMPLEMENTATION - makes it so source code is included with header
   32-*/
   33-
   34-/*
   35-	#define RGFW_IMPLEMENTATION - (required) makes it so the source code is included
   36-	#define RGFW_DEBUG - (optional) makes it so RGFW prints debug messages and errors when they're found
   37-	#define RGFW_EGL - (optional) compile with OpenGL functions, allowing you to use to use EGL instead of the native OpenGL functions
   38-	#define RGFW_DIRECTX - (optional) include integration directX functions (windows only)
   39-	#define RGFW_VULKAN - (optional) include helpful vulkan integration functions and macros
   40-	#define RGFW_WEBGPU - (optional) use WebGPU for rendering
   41-	#define RGFW_NATIVE - (optional) define native RGFW types that use native API structures
   42-
   43-	#define RGFW_X11 (optional) (unix only) if X11 should be used. This option is turned on by default by unix systems except for MacOS
   44-	#define RGFW_WAYLAND (optional) (unix only) use Wayland. (This can be used with X11)
   45-	#define RGFW_NO_STATIC_CONTEXT - do not initalizize with a static variable, use the heap if RGFW is not manually initalized
   46-	#define RGFW_NO_X11 (optional) (unix only) don't fallback to X11 when using Wayland
   47-	#define RGFW_NO_LOAD_WGL (optional) (windows only) if WGL should be loaded dynamically during runtime
   48-	#define RGFW_NO_X11_CURSOR (optional) (unix only) don't use XCursor
   49-	#define RGFW_NO_X11_CURSOR_PRELOAD (optional) (unix only) use XCursor, but don't link it in code, (you'll have to link it with -lXcursor)
   50-	#define RGFW_NO_X11_EXT_PRELOAD (optional) (unix only) use Xext, but don't link it in code, (you'll have to link it with -lXext)
   51-	#define RGFW_NO_LOAD_WINMM (optional) (windows only) use winmm (timeBeginPeriod), but don't link it in code, (you'll have to link it with -lwinmm)
   52-	#define RGFW_NO_WINMM (optional) (windows only) don't use winmm
   53-	#define RGFW_NO_IOKIT (optional) (macOS) don't use IOKit
   54-	#define RGFW_NO_UNIX_CLOCK (optional) (unix) don't link unix clock functions
   55-	#define RGFW_NO_DWM (windows only) - do not use or link dwmapi
   56-	#define RGFW_USE_XDL (optional) (X11) if XDL (XLib Dynamic Loader) should be used to load X11 dynamically during runtime (must include XDL.h along with RGFW)
   57-	#define RGFW_COCOA_GRAPHICS_SWITCHING - (optional) (cocoa) use automatic graphics switching (allow the system to choose to use GPU or iGPU)
   58-	#define RGFW_COCOA_FRAME_NAME (optional) (cocoa) set frame name
   59-	#define RGFW_NO_DPI - do not calculate DPI and don't use libShcore (win32)
   60-	#define RGFW_ADVANCED_SMOOTH_RESIZE - use advanced methods for smooth resizing (may result in a spike in memory usage or worse performance) (eg. WM_TIMER and XSyncValue)
   61-	#define RGFW_NO_INFO - do not define the RGFW_info struct (without RGFW_IMPLEMENTATION)
   62-	#define RGFW_NO_GLXWINDOW - do not use GLXWindow
   63-	#define RGFW_NO_ALLOCATE_MONITORS - do not allocate monitors on the heap at all (when there's no pre-allocated space left)
   64-	#define RGFW_PREALLOCATED_MONITORS x - choose the default amount of pre-allocated monitors (can be zero)
   65-
   66-	#define RGFW_ALLOC x  - choose the default allocation function (defaults to standard malloc)
   67-	#define RGFW_FREE x  - choose the default deallocation function (defaults to standard free)
   68-	#define RGFW_USERPTR x - choose the default userptr sent to the malloc call, (NULL by default)
   69-
   70-	#define RGFW_EXPORT - use when building RGFW
   71-	#define RGFW_IMPORT - use when linking with RGFW (not as a single-header)
   72-
   73-	#define RGFW_USE_INT - force the use c-types rather than stdint.h (for systems that might not have stdint.h (msvc))
   74-	#define RGFW_bool x - choose what type to use for bool, by default u32 is used
   75-*/
   76-
   77-/*
   78-Example to get you started :
   79-
   80-linux : gcc main.c -lX11 -lXrandr -lm
   81-windows : gcc main.c -lgdi32
   82-macos : gcc main.c -framework Cocoa -framework CoreVideo -framework IOKit
   83-
   84-#define RGFW_IMPLEMENTATION
   85-#include "RGFW.h"
   86-
   87-int main() {
   88-	RGFW_window* win = RGFW_createWindow("name", 100, 100, 500, 500, 0);
   89-
   90-	while (RGFW_window_shouldClose(win) == RGFW_FALSE) {
   91-		RGFW_pollEvents();
   92-	}
   93-
   94-	RGFW_window_close(win);
   95-}
   96-
   97-	compiling :
   98-
   99-	if you wish to compile the library all you have to do is create a new file with this in it
  100-
  101-	rgfw.c
  102-	#define RGFW_IMPLEMENTATION
  103-	#include "RGFW.h"
  104-
  105-	You may also want to add
  106-	`#define RGFW_EXPORT` when compiling and
  107-	`#define RGFW_IMPORT`when linking RGFW on it's own:
  108-	this reduces inline functions and prevents bloat in the object file
  109-
  110-	then you can use gcc (or whatever compile you wish to use) to compile the library into object file
  111-
  112-	ex. gcc -c RGFW.c -fPIC
  113-
  114-	after you compile the library into an object file, you can also turn the object file into an static or shared library
  115-
  116-	(commands ar and gcc can be replaced with whatever equivalent your system uses)
  117-
  118-	static : ar rcs RGFW.a RGFW.o
  119-	shared :
  120-		windows:
  121-			gcc -shared RGFW.o -lopengl32 -lgdi32 -o RGFW.dll
  122-		linux:
  123-			gcc -shared RGFW.o -lX11 -lGL -lXrandr -o RGFW.so
  124-		macos:
  125-			gcc -shared RGFW.o -framework CoreVideo -framework Cocoa -framework OpenGL -framework IOKit
  126-*/
  127-
  128-
  129-
  130-/*
  131-	Credits :
  132-		EimaMei/Sacode : Code review, helped with X11, MacOS and Windows support, Silicon, siliapp.h -> referencing
  133-
  134-		contributors : (feel free to put yourself here if you contribute)
  135-		krisvers (@krisvers) -> code review
  136-		EimaMei (@SaCode) -> code review
  137-		Nycticebus (@Code-Nycticebus) -> bug fixes
  138-		Rob Rohan (@robrohan) -> X11 bugs and missing features, MacOS/Cocoa fixing memory issues/bugs
  139-		AICDG (@THISISAGOODNAME) -> vulkan support (example)
  140-		@Easymode -> support, testing/debugging, bug fixes and reviews
  141-		Joshua Rowe (omnisci3nce) - bug fix, review (macOS)
  142-		@lesleyrs -> bug fix, review (OpenGL)
  143-		Nick Porcino (@meshula) - testing, organization, review (MacOS, examples)
  144-		@therealmarrakesh -> documentation
  145-		@DarekParodia -> code review (X11) (C++)
  146-		@NishiOwO -> fix BSD support, fix OSMesa example
  147-		@BaynariKattu -> code review and documentation
  148-		Miguel Pinto (@konopimi) -> code review, fix vulkan example
  149-		@m-doescode -> code review (wayland)
  150-		Robert Gonzalez (@uni-dos) -> code review (wayland)
  151-		@TheLastVoyager -> code review
  152-		@yehoravramenko -> code review (winapi)
  153-		@halocupcake -> code review (OpenGL)
  154-		@GideonSerf -> documentation
  155-		Alexandre Almeida (@M374LX) -> code review (keycodes)
  156-		Vũ Xuân Trường (@wanwanvxt) -> code review (winapi)
  157-		Lucas (@lightspeedlucas) -> code review (msvc++)
  158-		Jeffery Myers (@JeffM2501) -> code review (msvc)
  159-		Zeni (@zenitsuyo) -> documentation
  160-		TheYahton (@TheYahton) -> documentation
  161-		nonexistant_object (@DiarrheaMcgee)
  162-		AC Gaudette (@acgaudette)
  163-*/
  164-
  165-#if _MSC_VER
  166-	#pragma comment(lib, "gdi32")
  167-	#pragma comment(lib, "shell32")
  168-	#pragma comment(lib, "User32")
  169-	#pragma comment(lib, "Advapi32")
  170-    #pragma warning( push )
  171-	#pragma warning( disable : 4996 4191 4127)
  172-    #if _MSC_VER < 600
  173-        #define RGFW_C89
  174-    #endif
  175-#else
  176-    #if defined(__STDC__) && !defined(__STDC_VERSION__)
  177-        #define RGFW_C89
  178-    #endif
  179-#endif
  180-
  181-#if defined(RGFW_EGL) && !defined(RGFW_OPENGL)
  182-	#define RGFW_OPENGL
  183-#endif
  184-
  185-/* these OS macros look better & are standardized */
  186-/* plus it helps with cross-compiling */
  187-
  188-#ifdef __EMSCRIPTEN__
  189-	#define RGFW_WASM
  190-#endif
  191-
  192-#if defined(RGFW_X11) && defined(__APPLE__) && !defined(RGFW_CUSTOM_BACKEND)
  193-	#define RGFW_MACOS_X11
  194-	#define RGFW_UNIX
  195-#endif
  196-
  197-#if defined(_WIN32) && !defined(RGFW_X11) && !defined(RGFW_UNIX) && !defined(RGFW_WASM) && !defined(RGFW_CUSTOM_BACKEND) /* (if you're using X11 on windows some how) */
  198-	#define RGFW_WINDOWS
  199-#endif
  200-#if defined(RGFW_WAYLAND)
  201-	#define RGFW_DEBUG /* wayland will be in debug mode by default for now */
  202-	#define RGFW_UNIX
  203-	#ifdef RGFW_OPENGL
  204-		#define RGFW_EGL
  205-	#endif
  206-	#ifdef RGFW_X11
  207-		#define RGFW_DYNAMIC
  208-	#endif
  209-#endif
  210-#if (!defined(RGFW_WAYLAND) && !defined(RGFW_X11)) && (defined(__unix__) || defined(RGFW_MACOS_X11) || defined(RGFW_X11))  && !defined(RGFW_WASM)  && !defined(RGFW_CUSTOM_BACKEND)
  211-		#define RGFW_MACOS_X11
  212-		#define RGFW_X11
  213-		#define RGFW_UNIX
  214-#elif defined(__APPLE__) && !defined(RGFW_MACOS_X11) && !defined(RGFW_X11)  && !defined(RGFW_WASM)  && !defined(RGFW_CUSTOM_BACKEND)
  215-	#define RGFW_MACOS
  216-#endif
  217-
  218-#ifndef RGFW_ASSERT
  219-	#include <assert.h>
  220-	#define RGFW_ASSERT assert
  221-#endif
  222-
  223-#if !defined(__STDC_VERSION__)
  224-    #define RGFW_C89
  225-#endif
  226-
  227-#if !defined(RGFW_SNPRINTF) && (defined(RGFW_X11) || defined(RGFW_WAYLAND))
  228-	/* required for X11 errors */
  229-	#include <stdio.h>
  230-	#define RGFW_SNPRINTF snprintf
  231-#endif
  232-
  233-#ifndef RGFW_USERPTR
  234-	#define RGFW_USERPTR NULL
  235-#endif
  236-
  237-#ifndef RGFW_UNUSED
  238-	#define RGFW_UNUSED(x) (void)(x)
  239-#endif
  240-
  241-#ifndef RGFW_ROUND
  242-	#define RGFW_ROUND(x) (i32)((x) >= 0 ? (x) + 0.5f : (x) - 0.5f)
  243-#endif
  244-
  245-#ifndef RGFW_ROUNDF
  246-	#define RGFW_ROUNDF(x) (float)((i32)((x) + ((x) < 0.0f ? -0.5f : 0.5f)))
  247-#endif
  248-
  249-#ifndef RGFW_MIN
  250-	#define RGFW_MIN(x, y) ((x < y) ? x : y)
  251-#endif
  252-
  253-#ifndef RGFW_ALLOC
  254-	#include <stdlib.h>
  255-	#define RGFW_ALLOC malloc
  256-	#define RGFW_FREE free
  257-#endif
  258-
  259-#if !defined(RGFW_MEMCPY) || !defined(RGFW_STRNCMP) || !defined(RGFW_STRNCPY) || !defined(RGFW_MEMZERO)
  260-	#include <string.h>
  261-#endif
  262-
  263-#ifndef RGFW_MEMZERO
  264-	#define RGFW_MEMZERO(ptr, num) memset(ptr, 0, num)
  265-#endif
  266-
  267-#ifndef RGFW_MEMCPY
  268-	#define RGFW_MEMCPY(dist, src, len) memcpy(dist, src, len)
  269-#endif
  270-
  271-#ifndef RGFW_STRNCMP
  272-	#define RGFW_STRNCMP(s1, s2, max) strncmp(s1, s2, max)
  273-#endif
  274-
  275-#ifndef RGFW_STRNCPY
  276-	#define RGFW_STRNCPY(dist, src, len) strncpy(dist, src, len)
  277-#endif
  278-
  279-#ifndef RGFW_STRSTR
  280-	#define RGFW_STRSTR(str, substr) strstr(str, substr)
  281-#endif
  282-
  283-#ifndef RGFW_STRTOL
  284-	/* required for X11 XDnD and X11 Monitor DPI */
  285-	#include <stdlib.h>
  286-	#define RGFW_STRTOL(str, endptr, base) strtol(str, endptr, base)
  287-	#define RGFW_ATOF(num) atof(num)
  288-#endif
  289-
  290-#if !defined(RGFW_PRINTF) && ( defined(RGFW_DEBUG) || defined(RGFW_WAYLAND) )
  291-    /* required when using RGFW_DEBUG */
  292-    #include <stdio.h>
  293-    #define RGFW_PRINTF printf
  294-#endif
  295-
  296-#ifndef RGFW_MAX_EVENTS
  297-	#define RGFW_MAX_EVENTS 32
  298-#endif
  299-#ifndef RGFW_PREALLOCATED_MONITORS
  300-	#define RGFW_PREALLOCATED_MONITORS 6 /* the number of preallocated monitors */
  301-#elif defined(RGFW_NO_ALLOCATE_MONITORS) && (RGFW_PREALLOCATED_MONITORS == 0)
  302-	#warning RGFW monitors have no place to be allocated
  303-#endif
  304-
  305-#ifndef RGFW_COCOA_FRAME_NAME
  306-	#define RGFW_COCOA_FRAME_NAME NULL
  307-#endif
  308-
  309-#ifdef RGFW_WIN95 /* for windows 95 testing (not that it really works) */
  310-	#define RGFW_NO_PASSTHROUGH
  311-#endif
  312-
  313-#if defined(RGFW_EXPORT) ||  defined(RGFW_IMPORT)
  314-	#if defined(_WIN32)
  315-		#if defined(__TINYC__) && (defined(RGFW_EXPORT) ||  defined(RGFW_IMPORT))
  316-			#define __declspec(x) __attribute__((x))
  317-		#endif
  318-
  319-		#if defined(RGFW_EXPORT)
  320-			#define RGFWDEF __declspec(dllexport)
  321-		#else
  322-			#define RGFWDEF __declspec(dllimport)
  323-		#endif
  324-	#else
  325-		#if defined(RGFW_EXPORT)
  326-			#define RGFWDEF __attribute__((visibility("default")))
  327-		#endif
  328-	#endif
  329-    #ifndef RGFWDEF
  330-        #define RGFWDEF
  331-    #endif
  332-#endif
  333-
  334-#ifndef RGFWDEF
  335-	#ifdef RGFW_C89
  336-		#define RGFWDEF __inline
  337-	#else
  338-		#define RGFWDEF inline
  339-	#endif
  340-#endif
  341-
  342-#if defined(__cplusplus) && !defined(__EMSCRIPTEN__)
  343-	extern "C" {
  344-#endif
  345-
  346-/* makes sure the header file part is only defined once by default */
  347-#ifndef RGFW_HEADER
  348-
  349-#define RGFW_HEADER
  350-
  351-#include <stddef.h>
  352-#ifndef RGFW_INT_DEFINED
  353-	#ifdef RGFW_USE_INT /* optional for any system that might not have stdint.h */
  354-		typedef unsigned char       u8;
  355-		typedef signed char         i8;
  356-		typedef unsigned short     u16;
  357-		typedef signed short 	   i16;
  358-		typedef unsigned long int  u32;
  359-		typedef signed long int    i32;
  360-		typedef unsigned long long u64;
  361-		typedef signed long long   i64;
  362-	#else /* use stdint standard types instead of c "standard" types */
  363-		#include <stdint.h>
  364-
  365-		typedef uint8_t     u8;
  366-		typedef int8_t      i8;
  367-		typedef uint16_t   u16;
  368-		typedef int16_t    i16;
  369-		typedef uint32_t   u32;
  370-		typedef int32_t    i32;
  371-		typedef uint64_t   u64;
  372-		typedef int64_t    i64;
  373-	#endif
  374-	#define RGFW_INT_DEFINED
  375-#endif
  376-
  377-typedef ptrdiff_t RGFW_ssize_t;
  378-
  379-#ifndef RGFW_BOOL_DEFINED
  380-    #define RGFW_BOOL_DEFINED
  381-    typedef u8 RGFW_bool;
  382-#endif
  383-
  384-#define RGFW_BOOL(x) (RGFW_bool)((x) != 0) /* force a value to be 0 or 1 */
  385-#define RGFW_TRUE (RGFW_bool)1
  386-#define RGFW_FALSE (RGFW_bool)0
  387-
  388-#define RGFW_ENUM(type, name) type name; enum
  389-#define RGFW_BIT(x) (1 << (x))
  390-
  391-#ifdef RGFW_VULKAN
  392-
  393-	#if defined(RGFW_WAYLAND) && defined(RGFW_X11)
  394-		#define VK_USE_PLATFORM_WAYLAND_KHR
  395-		#define VK_USE_PLATFORM_XLIB_KHR
  396-		#define RGFW_VK_SURFACE ((RGFW_usingWayland()) ? ("VK_KHR_wayland_surface") : ("VK_KHR_xlib_surface"))
  397-	#elif defined(RGFW_WAYLAND)
  398-		#define VK_USE_PLATFORM_WAYLAND_KHR
  399-		#define VK_USE_PLATFORM_XLIB_KHR
  400-		#define RGFW_VK_SURFACE "VK_KHR_wayland_surface"
  401-	#elif defined(RGFW_X11)
  402-		#define VK_USE_PLATFORM_XLIB_KHR
  403-		#define RGFW_VK_SURFACE "VK_KHR_xlib_surface"
  404-	#elif defined(RGFW_WINDOWS)
  405-		#define VK_USE_PLATFORM_WIN32_KHR
  406-		#define OEMRESOURCE
  407-		#define RGFW_VK_SURFACE "VK_KHR_win32_surface"
  408-	#elif defined(RGFW_MACOS) && !defined(RGFW_MACOS_X11)
  409-		#define VK_USE_PLATFORM_MACOS_MVK
  410-		#define RGFW_VK_SURFACE "VK_MVK_macos_surface"
  411-	#else
  412-		#define RGFW_VK_SURFACE NULL
  413-	#endif
  414-
  415-#endif
  416-
  417-
  418-/*! @brief The stucture that contains information about the current RGFW instance */
  419-typedef struct RGFW_info RGFW_info;
  420-
  421-/*! @brief The window stucture for interfacing with the window */
  422-typedef struct RGFW_window RGFW_window;
  423-
  424-/*! @brief The source window stucture for interfacing with the underlying windowing API (e.g. winapi, wayland, cocoa, etc) */
  425-typedef struct RGFW_window_src RGFW_window_src;
  426-
  427-/*! @brief The color format for pixel data */
  428-typedef RGFW_ENUM(u8, RGFW_format) {
  429-	RGFW_formatRGB8 = 0,    /*!< 8-bit RGB (3 channels) */
  430-	RGFW_formatBGR8,    /*!< 8-bit BGR (3 channels) */
  431-	RGFW_formatRGBA8,   /*!< 8-bit RGBA (4 channels) */
  432-	RGFW_formatARGB8,   /*!< 8-bit RGBA (4 channels) */
  433-	RGFW_formatBGRA8,   /*!< 8-bit BGRA (4 channels) */
  434-	RGFW_formatABGR8,   /*!< 8-bit BGRA (4 channels) */
  435-	RGFW_formatCount
  436-};
  437-
  438-/*! @brief layout struct for mapping out format types */
  439-typedef struct RGFW_colorLayout {  i32 r, g, b, a; u32 channels;  } RGFW_colorLayout;
  440-
  441-/*! @brief function type converting raw image data between formats */
  442-typedef void (* RGFW_convertImageDataFunc)(u8* dest_data, u8* src_data, const RGFW_colorLayout* srcLayout, const RGFW_colorLayout* destLayout, size_t count);
  443-
  444-/*! @brief a stucture for interfacing with the underlying native image (e.g. XImage, HBITMAP, etc) */
  445-typedef struct RGFW_nativeImage RGFW_nativeImage;
  446-
  447-/*! @brief a stucture for interfacing with pixel data as a renderable surface */
  448-typedef struct RGFW_surface RGFW_surface;
  449-
  450-/*! @brief gamma struct for monitors */
  451-typedef struct RGFW_gammaRamp {
  452-	u16* red; /*!< array for the red channel */
  453-	u16* green; /*!< array for the green channel */
  454-	u16* blue; /*!< array for the blue channel */
  455-	size_t count; /*! count of elements in each channel */
  456-} RGFW_gammaRamp;
  457-
  458-/*! @brief monitor mode data | can be changed by the user (with functions)*/
  459-typedef struct RGFW_monitorMode {
  460-	i32 w, h; /*!< monitor workarea size */
  461-	float refreshRate; /*!< monitor refresh rate */
  462-	u8 red, blue, green; /*!< sizeof rgb values */
  463-	void* src; /*!< source API mode */
  464-} RGFW_monitorMode;
  465-
  466-/*! @brief structure for monitor node and source monitor data */
  467-typedef struct RGFW_monitorNode RGFW_monitorNode;
  468-
  469-/*! @brief structure for monitor data */
  470-typedef struct RGFW_monitor {
  471-	i32 x, y; /*!< x - y of the monitor workarea */
  472-	char name[128]; /*!< monitor name */
  473-	float scaleX, scaleY; /*!< monitor content scale */
  474-	float pixelRatio; /*!< pixel ratio for monitor (1.0 for regular, 2.0 for hiDPI)  */
  475-	float physW, physH; /*!< monitor physical size in inches */
  476-	RGFW_monitorMode mode; /*!< current mode of the monitor */
  477-	void* userPtr; /*!< pointer for user data */
  478-	RGFW_monitorNode* node; /*!< source node data of the monitor */
  479-} RGFW_monitor;
  480-
  481-/*! @brief what type of request you are making for the monitor */
  482-typedef RGFW_ENUM(u8, RGFW_modeRequest) {
  483-	RGFW_monitorScale = RGFW_BIT(0), /*!< scale the monitor size */
  484-	RGFW_monitorRefresh = RGFW_BIT(1), /*!< change the refresh rate */
  485-	RGFW_monitorRGB = RGFW_BIT(2), /*!< change the monitor RGB bits size */
  486-	RGFW_monitorAll = RGFW_monitorScale | RGFW_monitorRefresh | RGFW_monitorRGB
  487-};
  488-
  489-/*! a raw pointer to the underlying mouse handle for setting and creating custom mouse icons */
  490-typedef void RGFW_mouse;
  491-
  492-/*! @brief RGFW's abstract keycodes */
  493-typedef RGFW_ENUM(u8, RGFW_key) {
  494-	RGFW_keyNULL = 0,
  495-	RGFW_keyEscape = '\033',
  496-	RGFW_keyBacktick = '`',
  497-	RGFW_key0 = '0',
  498-	RGFW_key1 = '1',
  499-	RGFW_key2 = '2',
  500-	RGFW_key3 = '3',
  501-	RGFW_key4 = '4',
  502-	RGFW_key5 = '5',
  503-	RGFW_key6 = '6',
  504-	RGFW_key7 = '7',
  505-	RGFW_key8 = '8',
  506-	RGFW_key9 = '9',
  507-	RGFW_keyMinus = '-',
  508-	RGFW_keyEqual = '=',
  509-	RGFW_keyEquals = RGFW_keyEqual,
  510-	RGFW_keyBackSpace = '\b',
  511-	RGFW_keyTab = '\t',
  512-	RGFW_keySpace = ' ',
  513-	RGFW_keyA = 'a',
  514-	RGFW_keyB = 'b',
  515-	RGFW_keyC = 'c',
  516-	RGFW_keyD = 'd',
  517-	RGFW_keyE = 'e',
  518-	RGFW_keyF = 'f',
  519-	RGFW_keyG = 'g',
  520-	RGFW_keyH = 'h',
  521-	RGFW_keyI = 'i',
  522-	RGFW_keyJ = 'j',
  523-	RGFW_keyK = 'k',
  524-	RGFW_keyL = 'l',
  525-	RGFW_keyM = 'm',
  526-	RGFW_keyN = 'n',
  527-	RGFW_keyO = 'o',
  528-	RGFW_keyP = 'p',
  529-	RGFW_keyQ = 'q',
  530-	RGFW_keyR = 'r',
  531-	RGFW_keyS = 's',
  532-	RGFW_keyT = 't',
  533-	RGFW_keyU = 'u',
  534-	RGFW_keyV = 'v',
  535-	RGFW_keyW = 'w',
  536-	RGFW_keyX = 'x',
  537-	RGFW_keyY = 'y',
  538-	RGFW_keyZ = 'z',
  539-	RGFW_keyPeriod = '.',
  540-	RGFW_keyComma = ',',
  541-	RGFW_keySlash = '/',
  542-	RGFW_keyBracket = '[',
  543-    RGFW_keyCloseBracket = ']',
  544-    RGFW_keySemicolon = ';',
  545-	RGFW_keyApostrophe = '\'',
  546-	RGFW_keyBackSlash = '\\',
  547-	RGFW_keyReturn = '\n',
  548-	RGFW_keyEnter = RGFW_keyReturn,
  549-	RGFW_keyDelete = '\177', /* 127 */
  550-	RGFW_keyF1,
  551-	RGFW_keyF2,
  552-	RGFW_keyF3,
  553-	RGFW_keyF4,
  554-	RGFW_keyF5,
  555-	RGFW_keyF6,
  556-	RGFW_keyF7,
  557-	RGFW_keyF8,
  558-	RGFW_keyF9,
  559-	RGFW_keyF10,
  560-	RGFW_keyF11,
  561-	RGFW_keyF12,
  562-    RGFW_keyF13,
  563-    RGFW_keyF14,
  564-    RGFW_keyF15,
  565-    RGFW_keyF16,
  566-    RGFW_keyF17,
  567-    RGFW_keyF18,
  568-    RGFW_keyF19,
  569-    RGFW_keyF20,
  570-    RGFW_keyF21,
  571-    RGFW_keyF22,
  572-    RGFW_keyF23,
  573-    RGFW_keyF24,
  574-    RGFW_keyF25,
  575-	RGFW_keyCapsLock,
  576-	RGFW_keyShiftL,
  577-	RGFW_keyControlL,
  578-	RGFW_keyAltL,
  579-	RGFW_keySuperL,
  580-	RGFW_keyShiftR,
  581-	RGFW_keyControlR,
  582-	RGFW_keyAltR,
  583-	RGFW_keySuperR,
  584-	RGFW_keyUp,
  585-	RGFW_keyDown,
  586-	RGFW_keyLeft,
  587-	RGFW_keyRight,
  588-	RGFW_keyInsert,
  589-	RGFW_keyMenu,
  590-	RGFW_keyEnd,
  591-	RGFW_keyHome,
  592-	RGFW_keyPageUp,
  593-	RGFW_keyPageDown,
  594-	RGFW_keyNumLock,
  595-	RGFW_keyPadSlash,
  596-	RGFW_keyPadMultiply,
  597-	RGFW_keyPadPlus,
  598-	RGFW_keyPadMinus,
  599-	RGFW_keyPadEqual,
  600-	RGFW_keyPadEquals = RGFW_keyPadEqual,
  601-	RGFW_keyPad1,
  602-	RGFW_keyPad2,
  603-	RGFW_keyPad3,
  604-	RGFW_keyPad4,
  605-	RGFW_keyPad5,
  606-	RGFW_keyPad6,
  607-	RGFW_keyPad7,
  608-	RGFW_keyPad8,
  609-	RGFW_keyPad9,
  610-	RGFW_keyPad0,
  611-	RGFW_keyPadPeriod,
  612-	RGFW_keyPadReturn,
  613-	RGFW_keyScrollLock,
  614-    RGFW_keyPrintScreen,
  615-    RGFW_keyPause,
  616-	RGFW_keyWorld1,
  617-    RGFW_keyWorld2,
  618-    RGFW_keyLast = 256 /* padding for alignment ~(175 by default) */
  619-};
  620-
  621-/*! @brief abstract mouse button codes */
  622-typedef RGFW_ENUM(u8, RGFW_mouseButton) {
  623-	RGFW_mouseLeft = 0, /*!< left mouse button is pressed */
  624-	RGFW_mouseMiddle, /*!< mouse-wheel-button is pressed */
  625-	RGFW_mouseRight, /*!< right mouse button is pressed */
  626-	RGFW_mouseMisc1, RGFW_mouseMisc2, RGFW_mouseMisc3, RGFW_mouseMisc4, RGFW_mouseMisc5,
  627-	RGFW_mouseFinal
  628-};
  629-
  630-/*! abstract key modifier codes */
  631-typedef RGFW_ENUM(u8, RGFW_keymod) {
  632-	RGFW_modCapsLock = RGFW_BIT(0),
  633-	RGFW_modNumLock  = RGFW_BIT(1),
  634-	RGFW_modControl  = RGFW_BIT(2),
  635-	RGFW_modAlt = RGFW_BIT(3),
  636-	RGFW_modShift  = RGFW_BIT(4),
  637-	RGFW_modSuper = RGFW_BIT(5),
  638-	RGFW_modScrollLock = RGFW_BIT(6)
  639-};
  640-
  641-/*! types of dnd drag actions */
  642-typedef RGFW_ENUM(u8, RGFW_dndActionType) {
  643-	RGFW_dndActionNone = 0,
  644-	RGFW_dndActionEnter, /*!< data has been dragged into the window area */
  645-	RGFW_dndActionMove, /*!< the data that was dragged into the window area has moved inside the window */
  646-	RGFW_dndActionExit, /*!< the data that was dragged into the window area has left the window */
  647-};
  648-
  649-/*! types of transfered data (clipboard, dnd) */
  650-typedef RGFW_ENUM(u8, RGFW_dataTransferType) {
  651-	RGFW_dataNone = 0,
  652-	RGFW_dataText, /*!< plain text string */
  653-	RGFW_dataFile, /*!< file string */
  654-	RGFW_dataURL, /*!< URL string */
  655-	RGFW_dataImage, /*!< raw image data */
  656-	RGFW_dataUnknown /*!< unknown raw data */
  657-};
  658-
  659-/*! internal node for a individual data drop */
  660-typedef struct RGFW_dataDropNode {
  661-	const char* data; /*!< dropped data */
  662-	size_t size; /*!< the size of the data in bytes */
  663-	RGFW_dataTransferType type; /*!< the type of data being dropped */
  664-	struct RGFW_dataDropNode* next; /*!< the next drop data node if any [when handling callbacks, this will always be NULL because the linked list is built as events are processed] */
  665-} RGFW_dataDropNode;
  666-
  667-/*! @brief codes for the event types that can be sent */
  668-typedef RGFW_ENUM(u8, RGFW_eventType) {
  669-	RGFW_eventNone = 0, /*!< no event has been sent */
  670- 	RGFW_keyPressed, /*!< a key has been pressed */
  671-	RGFW_keyReleased, /*!< a key has been released */
  672-	RGFW_keyChar, /*!< keyboard character input event specifically for utf8 input */
  673-	RGFW_mouseButtonPressed, /*!< a mouse button has been pressed (left,middle,right) */
  674-	RGFW_mouseButtonReleased, /*!< a mouse button has been released (left,middle,right) */
  675-	RGFW_mouseScroll, /*!< a mouse scroll event */
  676-	RGFW_mousePosChanged, /*!< the position of the mouse has been changed */
  677-	RGFW_mouseRawMotion, /*!< raw mouse motion */
  678-	RGFW_mouseEnter, /*!< mouse entered the window */
  679-	RGFW_mouseLeave, /*!< mouse left the window */
  680-	RGFW_windowMoved, /*!< the window was moved (by the user) */
  681-	RGFW_windowResized, /*!< the window was resized (by the user), [on WASM this means the browser was resized] */
  682-	RGFW_windowFocusIn, /*!< window is in focus now */
  683-	RGFW_windowFocusOut, /*!< window is out of focus now */
  684-	RGFW_windowRefresh, /*!< The window content needs to be refreshed */
  685-	RGFW_windowClose, /*!< the user attempts to close the window */
  686-	RGFW_windowMaximized, /*!< the window was maximized */
  687-	RGFW_windowMinimized, /*!< the window was minimized */
  688-	RGFW_windowRestored, /*!< the window was restored */
  689-	RGFW_dataDrop, /*!< data has been dropped into the window */
  690-	RGFW_dataDrag, /*!< the start of a drag and drop event, when data is being dragged */
  691-	RGFW_scaleUpdated, /*!< content scale factor changed */
  692-	RGFW_monitorConnected, /*!< a monitor has been connected */
  693-	RGFW_monitorDisconnected, /*!< a monitor has been disconnected */
  694-	RGFW_eventCount /*!< the number of event types there are */
  695-};
  696-
  697-/*! @brief flags for toggling whether or not an event should be processed */
  698-typedef RGFW_ENUM(u32, RGFW_eventFlag) {
  699-    RGFW_keyPressedFlag = RGFW_BIT(RGFW_keyPressed),
  700-    RGFW_keyReleasedFlag = RGFW_BIT(RGFW_keyReleased),
  701-    RGFW_keyCharFlag = RGFW_BIT(RGFW_keyChar),
  702-    RGFW_mouseScrollFlag = RGFW_BIT(RGFW_mouseScroll),
  703-    RGFW_mouseButtonPressedFlag = RGFW_BIT(RGFW_mouseButtonPressed),
  704-    RGFW_mouseButtonReleasedFlag = RGFW_BIT(RGFW_mouseButtonReleased),
  705-    RGFW_mousePosChangedFlag = RGFW_BIT(RGFW_mousePosChanged),
  706-    RGFW_mouseRawMotionFlag = RGFW_BIT(RGFW_mouseRawMotion),
  707-    RGFW_mouseEnterFlag = RGFW_BIT(RGFW_mouseEnter),
  708-    RGFW_mouseLeaveFlag = RGFW_BIT(RGFW_mouseLeave),
  709-    RGFW_windowMovedFlag = RGFW_BIT(RGFW_windowMoved),
  710-    RGFW_windowResizedFlag = RGFW_BIT(RGFW_windowResized),
  711-    RGFW_windowFocusInFlag = RGFW_BIT(RGFW_windowFocusIn),
  712-    RGFW_windowFocusOutFlag = RGFW_BIT(RGFW_windowFocusOut),
  713-    RGFW_windowRefreshFlag = RGFW_BIT(RGFW_windowRefresh),
  714-    RGFW_windowMaximizedFlag = RGFW_BIT(RGFW_windowMaximized),
  715-    RGFW_windowMinimizedFlag = RGFW_BIT(RGFW_windowMinimized),
  716-    RGFW_windowRestoredFlag = RGFW_BIT(RGFW_windowRestored),
  717-    RGFW_scaleUpdatedFlag = RGFW_BIT(RGFW_scaleUpdated),
  718-    RGFW_windowCloseFlag = RGFW_BIT(RGFW_windowClose),
  719-    RGFW_dataDropFlag = RGFW_BIT(RGFW_dataDrop),
  720-    RGFW_dataDragFlag = RGFW_BIT(RGFW_dataDrag),
  721-	RGFW_monitorConnectedFlag = RGFW_BIT(RGFW_monitorConnected),
  722-	RGFW_monitorDisconnectedFlag = RGFW_BIT(RGFW_monitorDisconnected),
  723-
  724-    RGFW_keyEventsFlag = RGFW_keyPressedFlag | RGFW_keyReleasedFlag | RGFW_keyCharFlag,
  725-    RGFW_mouseEventsFlag = RGFW_mouseButtonPressedFlag | RGFW_mouseButtonReleasedFlag | RGFW_mousePosChangedFlag | RGFW_mouseEnterFlag | RGFW_mouseLeaveFlag | RGFW_mouseScrollFlag | RGFW_mouseRawMotionFlag,
  726-    RGFW_windowEventsFlag = RGFW_windowMovedFlag | RGFW_windowResizedFlag | RGFW_windowRefreshFlag | RGFW_windowMaximizedFlag | RGFW_windowMinimizedFlag | RGFW_windowRestoredFlag | RGFW_scaleUpdatedFlag,
  727-    RGFW_windowFocusEventsFlag = RGFW_windowFocusInFlag | RGFW_windowFocusOutFlag,
  728-    RGFW_dataDragDropEventsFlag = RGFW_dataDropFlag | RGFW_dataDragFlag,
  729-	RGFW_monitorEventsFlag = RGFW_monitorConnectedFlag | RGFW_monitorDisconnectedFlag,
  730-    RGFW_allEventFlags = RGFW_keyEventsFlag | RGFW_mouseEventsFlag | RGFW_windowEventsFlag | RGFW_windowFocusEventsFlag | RGFW_dataDragDropEventsFlag | RGFW_windowCloseFlag | RGFW_monitorEventsFlag
  731-};
  732-
  733-/*! Event structure(s) and union for checking/getting events */
  734-
  735-/*! @brief common event data across all events */
  736-typedef struct RGFW_commonEvent {
  737-	RGFW_eventType type; /*!< which event has been sent?*/
  738-	RGFW_window* win; /*!< the window this event applies to (for event queue events) */
  739-} RGFW_commonEvent;
  740-
  741-/*! @brief event data for all focus events */
  742-typedef struct RGFW_windowFocusEvent {
  743-	RGFW_eventType type; /*!< which event has been sent?*/
  744-	RGFW_window* win; /*!< the window this event applies to (for event queue events) */
  745-	RGFW_bool state; /*!< wether or not the window is in focus or not */
  746-} RGFW_windowFocusEvent;
  747-
  748-/*! @brief event data for any mouse button event (press/release) */
  749-typedef struct RGFW_mouseButtonEvent {
  750-	RGFW_eventType type; /*!< which event has been sent?*/
  751-	RGFW_window* win; /*!< the window this event applies to (for event queue events) */
  752-	RGFW_mouseButton value; /* !< which mouse button was pressed */
  753-	RGFW_bool state; /*!< if the button was pressed or released */
  754-} RGFW_mouseButtonEvent;
  755-
  756-/*! @brief event data for any mouse scroll or raw motion event */
  757-typedef struct RGFW_mouseDeltaEvent {
  758-	RGFW_eventType type; /*!< which event has been sent?*/
  759-	RGFW_window* win; /*!< the window this event applies to (for event queue events) */
  760-	float x, y; /*!< the raw mouse scroll or motion delta value */
  761-} RGFW_mouseDeltaEvent;
  762-
  763-/*! @brief event data for a mouse position event (RGFW_mousePosChanged) */
  764-typedef struct RGFW_mousePosEvent {
  765-	RGFW_eventType type; /*!< which event has been sent?*/
  766-	RGFW_window* win; /*!< the window this event applies to (for event queue events) */
  767-	i32 x, y; /*!< mouse x, y of event (or drop point) */
  768-	RGFW_bool inWindow; /*!< if the mouse is in the window or not */
  769-} RGFW_mousePosEvent;
  770-
  771-/*! @brief event data for a key press/release event */
  772-typedef struct RGFW_keyEvent {
  773-	RGFW_eventType type; /*!< which event has been sent?*/
  774-	RGFW_window* win; /*!< the window this event applies to (for event queue events) */
  775-	RGFW_key value; /*!< the physical key of the event, refers to where key is physically */
  776-	RGFW_bool repeat; /*!< key press event repeated (the key is being held) */
  777-	RGFW_keymod mod; /*!< state of the key modifier state */
  778-	RGFW_bool state; /*!< if the key was pressed or released */
  779-} RGFW_keyEvent;
  780-
  781-/*! @brief event data for a key character event */
  782-typedef struct RGFW_keyCharEvent {
  783-	RGFW_eventType type; /*!< which event has been sent?*/
  784-	RGFW_window* win; /*!< the window this event applies to (for event queue events) */
  785-	u32 value; /*!< the unicode value of the key */
  786-} RGFW_keyCharEvent;
  787-
  788-/*! @brief event data for any data drop event */
  789-typedef struct RGFW_dataDropEvent {
  790-	RGFW_eventType type; /*!< which event has been sent?*/
  791-	RGFW_window* win; /*!< the window this event applies to (for event queue events) */
  792-	const RGFW_dataDropNode* value;
  793-} RGFW_dataDropEvent;
  794-
  795-/*! @brief event data for any data drag event */
  796-typedef struct RGFW_dataDragEvent {
  797-	RGFW_eventType type; /*!< which event has been sent?*/
  798-	RGFW_window* win; /*!< the window this event applies to (for event queue events) */
  799-	i32 x, y; /*!< mouse x, y of event (or drop point) */
  800-	RGFW_dndActionType action; /*!< the type of drag action, e.g. enter, leave, move */
  801-	RGFW_dataTransferType dataType; /*!< the type of data being dragged*/
  802-} RGFW_dataDragEvent;
  803-
  804-/*! @brief event data for when the window scale (DPI) is updated */
  805-typedef struct RGFW_scaleUpdatedEvent {
  806-	RGFW_eventType type; /*!< which event has been sent?*/
  807-	RGFW_window* win; /*!< the window this event applies to (for event queue events) */
  808-	float x, y; /*!< DPI scaling */
  809-} RGFW_scaleUpdatedEvent;
  810-
  811-/*! @brief event data for when a monitor is connected, disconnected or updated */
  812-typedef struct RGFW_monitorEvent {
  813-	RGFW_eventType type; /*!< which event has been sent?*/
  814-	RGFW_window* win; /*!< the window this event applies to (for event queue events) */
  815-	const RGFW_monitor* monitor; /*!< the monitor that this event applies to */
  816-	RGFW_bool state; /*!< if the monitor is connected or disconnected */
  817-} RGFW_monitorEvent;
  818-
  819-/*! @breif event data for when the window is updated, moved, resized or refreshed */
  820-typedef struct RGFW_windowUpdateEvent {
  821-	RGFW_eventType type; /*!< the specific event type */
  822-	RGFW_window* win; /*!< the window that was updated */
  823-	i32 x; /*!< the new window x OR the x of the rectanglular refresh area */
  824-	i32 y; /*!< the new window y OR the y of the rectanglular refresh area */
  825-	i32 w; /*!< the new window width OR the width of the rectanglular refresh area */
  826-	i32 h; /*!< the new window height OR the height of the rectanglular refresh area */
  827-} RGFW_windowUpdateEvent;
  828-
  829-/*! @brief union for all of the event stucture types */
  830-typedef union RGFW_event {
  831-	RGFW_eventType type; /*!< which event has been sent?*/
  832-	RGFW_commonEvent common; /*!< common event data (e.g.) type and win */
  833-	RGFW_windowFocusEvent focus; /*!< event data  for focus in/out events */
  834-	RGFW_windowUpdateEvent update; /*!< data for window update/move/resize/refresh events */
  835-	RGFW_mouseButtonEvent button; /*!< data for a button press/release */
  836-	RGFW_mouseDeltaEvent delta; /*!< data for a mouse scroll or raw motion */
  837-	RGFW_mousePosEvent mouse; /*!< data for mouse motion events */
  838-	RGFW_keyEvent key; /*!< data for key press/release/hold events */
  839-	RGFW_keyCharEvent keyChar; /*!< data for key character events */
  840-	RGFW_dataDropEvent drop; /*!< data dropping events */
  841-	RGFW_dataDragEvent drag; /*!< data for data dragging events */
  842-	RGFW_scaleUpdatedEvent scale; /*!< data for dpi scaling update events */
  843-	RGFW_monitorEvent monitor; /*!< data for monitor events */
  844-} RGFW_event;
  845-
  846-/*!
  847-	@!brief codes for for RGFW_the code is stupid and C++ waitForEvent
  848-	waitMS -> Allows the function to keep checking for events even after there are no more events
  849-			  if waitMS == 0, the loop will not wait for events
  850-			  if waitMS > 0, the loop will wait that many miliseconds after there are no more events until it returns
  851-			  if waitMS == -1 or waitMS == the max size of an unsigned 32-bit int, the loop will not return until it gets another event
  852-*/
  853-typedef RGFW_ENUM(i32, RGFW_eventWait) {
  854-	RGFW_eventNoWait = 0,
  855-	RGFW_eventWaitNext = -1
  856-};
  857-
  858-/*! @brief generic event callback function type */
  859-typedef void (*RGFW_genericFunc)(const RGFW_event* e);
  860-
  861-/*! brief structure that holds an array to callback data*/
  862-typedef struct RGFW_callbacks {
  863-	RGFW_genericFunc arr[RGFW_eventCount]; /*!< an array of all the callbacks */
  864-} RGFW_callbacks;
  865-
  866-/*! @brief optional bitwise arguments for making a windows, these can be OR'd together */
  867-typedef RGFW_ENUM(u32, RGFW_windowFlags) {
  868-	RGFW_windowNoBorder = RGFW_BIT(0), /*!< the window doesn't have a border / frame / decor */
  869-	RGFW_windowNoResize = RGFW_BIT(1), /*!< the window cannot be resized by the user */
  870-	RGFW_windowAllowDND = RGFW_BIT(2), /*!< the window supports drag and drop */
  871-	RGFW_windowHideMouse = RGFW_BIT(3), /*! the window should hide the mouse (can be toggled later on using `RGFW_window_showMouse`) */
  872-	RGFW_windowFullscreen = RGFW_BIT(4), /*!< the window is fullscreen by default */
  873-	RGFW_windowTranslucent = RGFW_BIT(5), /*!< the window is translucent (only properly works on X11 and MacOS, although it's meant for for windows) */
  874-	RGFW_windowTransparent = RGFW_windowTranslucent,  /*!< the window is translucent (only properly works on X11 and MacOS, although it's meant for for windows) */
  875-	RGFW_windowCenter = RGFW_BIT(6), /*! center the window on the screen */
  876-	RGFW_windowRawMouse = RGFW_BIT(7), /*!< use raw mouse mouse on window creation */
  877-	RGFW_windowScaleToMonitor = RGFW_BIT(8), /*! scale the window to the screen */
  878-	RGFW_windowHide = RGFW_BIT(9), /*! the window is hidden */
  879-	RGFW_windowMaximize = RGFW_BIT(10), /*!< maximize the window on creation */
  880-	RGFW_windowCenterCursor = RGFW_BIT(11), /*!< center the cursor to the window on creation */
  881-	RGFW_windowFloating = RGFW_BIT(12), /*!< create a floating window */
  882-	RGFW_windowFocusOnShow = RGFW_BIT(13), /*!< focus the window when it's shown */
  883-	RGFW_windowMinimize = RGFW_BIT(14), /*!< focus the window when it's shown */
  884-	RGFW_windowFocus = RGFW_BIT(15), /*!< if the window is in focus */
  885-	RGFW_windowCaptureMouse = RGFW_BIT(16), /*!< capture the mouse mouse mouse on window creation */
  886-	RGFW_windowOpenGL = RGFW_BIT(17), /*!< create an OpenGL context (you can also do this manually with RGFW_window_createContext_OpenGL) */
  887-	RGFW_windowEGL = RGFW_BIT(18), /*!< create an EGL context (you can also do this manually with RGFW_window_createContext_EGL) */
  888-	RGFW_noDeinitOnClose = RGFW_BIT(19), /*!< do not auto deinit RGFW if the window closes and this is the last window open */
  889-	RGFW_windowedFullscreen = RGFW_windowNoBorder | RGFW_windowMaximize,
  890-	RGFW_windowCaptureRawMouse = RGFW_windowCaptureMouse | RGFW_windowRawMouse
  891-};
  892-
  893-/*! @brief the types of icon to set */
  894-typedef RGFW_ENUM(u8, RGFW_icon) {
  895-	RGFW_iconTaskbar = RGFW_BIT(0),
  896-	RGFW_iconWindow = RGFW_BIT(1),
  897-	RGFW_iconBoth = RGFW_iconTaskbar | RGFW_iconWindow
  898-};
  899-
  900-/*! @brief standard mouse icons */
  901-typedef RGFW_ENUM(u8, RGFW_mouseIcon) {
  902-	RGFW_mouseNormal = 0,
  903-	RGFW_mouseArrow,
  904-	RGFW_mouseIbeam,
  905-	RGFW_mouseText = RGFW_mouseIbeam,
  906-	RGFW_mouseCrosshair,
  907-	RGFW_mousePointingHand,
  908-	RGFW_mouseResizeEW,
  909-	RGFW_mouseResizeNS,
  910-	RGFW_mouseResizeNWSE,
  911-	RGFW_mouseResizeNESW,
  912-	RGFW_mouseResizeNW,
  913-	RGFW_mouseResizeN,
  914-	RGFW_mouseResizeNE,
  915-	RGFW_mouseResizeE,
  916-	RGFW_mouseResizeSE,
  917-	RGFW_mouseResizeS,
  918-	RGFW_mouseResizeSW,
  919-	RGFW_mouseResizeW,
  920-	RGFW_mouseResizeAll,
  921-	RGFW_mouseNotAllowed,
  922-	RGFW_mouseWait,
  923-	RGFW_mouseProgress,
  924-	RGFW_mouseIconCount,
  925-    RGFW_mouseIconFinal = 16 /* padding for alignment */
  926-};
  927-
  928-/*! @breif flash request type */
  929-typedef RGFW_ENUM(u8, RGFW_flashRequest) {
  930-	RGFW_flashCancel = 0,
  931-	RGFW_flashBriefly,
  932-	RGFW_flashUntilFocused
  933-};
  934-
  935-/*! @brief the type of debug message */
  936-typedef RGFW_ENUM(u8, RGFW_debugType) {
  937-	RGFW_typeError = 0, RGFW_typeWarning, RGFW_typeInfo
  938-};
  939-
  940-/*! @brief error codes for known failure types */
  941-typedef RGFW_ENUM(u8, RGFW_errorCode) {
  942-	RGFW_noError = 0, /*!< no error */
  943-	RGFW_errOutOfMemory,
  944-	RGFW_errOpenGLContext, RGFW_errEGLContext, /*!< error with the OpenGL context */
  945-	RGFW_errWayland, RGFW_errX11,
  946-	RGFW_errDirectXContext,
  947-	RGFW_errIOKit,
  948-	RGFW_errClipboard,
  949-	RGFW_errFailedFuncLoad,
  950-	RGFW_errBuffer,
  951-	RGFW_errMetal,
  952-	RGFW_errPlatform,
  953-	RGFW_errEventQueue,
  954-	RGFW_infoWindow, RGFW_infoBuffer, RGFW_infoGlobal, RGFW_infoOpenGL,
  955-	RGFW_warningWayland, RGFW_warningOpenGL
  956-};
  957-
  958-/*! @brief data for debug messages */
  959-typedef struct RGFW_debugInfo {
  960-	RGFW_debugType type; /*!< the type of message */
  961-	RGFW_errorCode code; /*!< the code for the specific type of debug message */
  962-	const char* msg; /*!< string message */
  963-} RGFW_debugInfo;
  964-
  965-/*! @brief callback function type for debug messags */
  966-typedef void (* RGFW_debugFunc)(const RGFW_debugInfo* info);
  967-
  968-/*! @brief function pointer equivalent of void* */
  969-typedef void (*RGFW_proc)(void);
  970-
  971-#if defined(RGFW_OPENGL)
  972-
  973-/*! @brief abstract structure for interfacing with the underlying OpenGL API */
  974-typedef struct RGFW_glContext RGFW_glContext;
  975-
  976-/*! @brief abstract structure for interfacing with the underlying EGL API */
  977-typedef struct RGFW_eglContext RGFW_eglContext;
  978-
  979-/*! values for the releaseBehavior hint */
  980-typedef RGFW_ENUM(i32, RGFW_glReleaseBehavior)   {
  981-	RGFW_glReleaseFlush = 0, /*!< flush the pipeline will be flushed when the context is release */
  982-	RGFW_glReleaseNone /*!< do nothing on release */
  983-};
  984-
  985-/*! values for the profile hint */
  986-typedef RGFW_ENUM(i32, RGFW_glProfile)  {
  987-	RGFW_glCore = 0, /*!< the core OpenGL version, e.g. just support for that version */
  988-	RGFW_glForwardCompatibility, /*!< only compatibility for newer versions of OpenGL as well as the requested version */
  989-	RGFW_glCompatibility, /*!< allow compatibility for older versions of OpenGL as well as the requested version */
  990-	RGFW_glES, /*!< use OpenGL ES */
  991-	RGFW_glWeb /*!< use WebGL version (otherwise the version is changed to match it's GLES equivalent) */
  992-};
  993-
  994-/*! values for the renderer hint */
  995-typedef RGFW_ENUM(i32, RGFW_glRenderer)  {
  996-	RGFW_glAccelerated = 0, /*!< hardware accelerated (GPU) */
  997-	RGFW_glSoftware /*!< software rendered (CPU) */
  998-};
  999-
 1000-/*! OpenGL initalization hints */
 1001-typedef struct RGFW_glHints {
 1002-	i32 stencil;  /*!< set stencil buffer bit size (0 by default) */
 1003-	i32 samples; /*!< set number of sample buffers (0 by default) */
 1004-	i32 stereo; /*!< hint the context to use stereoscopic frame buffers for 3D (false by default) */
 1005-	i32 auxBuffers; /*!< number of aux buffers (0 by default) */
 1006-	i32 doubleBuffer; /*!< request double buffering (true by default) */
 1007-	i32 red, green, blue, alpha; /*!< set color bit sizes (all 8 by default) */
 1008-	i32 depth; /*!< set depth buffer bit size (24 by default) */
 1009-	i32 accumRed, accumGreen, accumBlue, accumAlpha; /*!< set accumulated RGBA bit sizes (all 0 by default) */
 1010-	RGFW_bool sRGB; /*!< request sRGA format (false by default) */
 1011-	RGFW_bool robustness; /*!< request a "robust" (as in memory-safe) context (false by default). For more information check the overview section: https://registry.khronos.org/OpenGL/extensions/EXT/EXT_robustness.txt */
 1012-	RGFW_bool debug; /*!< request OpenGL debugging (false by default). */
 1013-	RGFW_bool noError; /*!< request no OpenGL errors (false by default). This causes OpenGL errors to be undefined behavior. For more information check the overview section: https://registry.khronos.org/OpenGL/extensions/KHR/KHR_no_error.txt */
 1014-	RGFW_glReleaseBehavior releaseBehavior; /*!< hint how the OpenGL driver should behave when changing contexts (RGFW_glReleaseNone by default). For more information check the overview section: https://registry.khronos.org/OpenGL/extensions/KHR/KHR_context_flush_control.txt */
 1015-	RGFW_glProfile profile; /*!< set OpenGL API profile (RGFW_glCore by default) */
 1016-	i32 major, minor;  /*!< set the OpenGL API profile version (by default RGFW_glMajor is 1, RGFW_glMinor is 0) */
 1017-	RGFW_glContext* share; /*!< Share this OpenGL context with newly created OpenGL contexts; defaults to NULL. */
 1018-	RGFW_eglContext* shareEGL; /*!< Share this EGL context with newly created OpenGL contexts; defaults to NULL. */
 1019-	RGFW_glRenderer renderer; /*!< renderer to use e.g. accelerated or software defaults to accelerated */
 1020-} RGFW_glHints;
 1021-
 1022-#endif
 1023-
 1024-/**!
 1025- * @brief Allocates memory using the allocator defined by RGFW_ALLOC at compile time.
 1026- * @param size The size (in bytes) of the memory block to allocate.
 1027- * @return A pointer to the allocated memory block.
 1028-*/
 1029-RGFWDEF void* RGFW_alloc(size_t size);
 1030-
 1031-/**!
 1032- * @brief Frees memory using the deallocator defined by RGFW_FREE at compile time.
 1033- * @param ptr A pointer to the memory block to free.
 1034-*/
 1035-RGFWDEF void RGFW_free(void* ptr);
 1036-
 1037-/**!
 1038- * @brief Returns the size (in bytes) of the RGFW_window structure.
 1039- * @return The size of the RGFW_window structure.
 1040-*/
 1041-RGFWDEF size_t RGFW_sizeofWindow(void);
 1042-
 1043-/**!
 1044- * @brief Returns the size (in bytes) of the RGFW_window_src structure.
 1045- * @return The size of the RGFW_window_src structure.
 1046-*/
 1047-RGFWDEF size_t RGFW_sizeofWindowSrc(void);
 1048-
 1049-/**!
 1050- * @brief (Unix) Toggles the use of Wayland.
 1051- * This is enabled by default when compiled with `RGFW_WAYLAND`.
 1052- * If not using `RGFW_WAYLAND`, Wayland functions are not exposed.
 1053- * This function can be used to force the use of XWayland.
 1054- * @param wayland A boolean value indicating whether to use Wayland (true) or not (false).
 1055-*/
 1056-RGFWDEF void RGFW_useWayland(RGFW_bool wayland);
 1057-
 1058-/**!
 1059- * @brief Checks if Wayland is currently being used.
 1060- * @return RGFW_TRUE if using Wayland, RGFW_FALSE otherwise.
 1061-*/
 1062-RGFWDEF RGFW_bool RGFW_usingWayland(void);
 1063-
 1064-/**!
 1065- * @brief Retrieves the current Cocoa layer (macOS only).
 1066- * @return A pointer to the Cocoa layer, or NULL if the platform is not in use.
 1067-*/
 1068-RGFWDEF void* RGFW_getLayer_OSX(void);
 1069-
 1070-/**!
 1071- * @brief Retrieves the current X11 display connection.
 1072- * @return A pointer to the X11 display, or NULL if the platform is not in use.
 1073-*/
 1074-RGFWDEF void* RGFW_getDisplay_X11(void);
 1075-
 1076-/**!
 1077- * @brief Retrieves the current Wayland display connection.
 1078- * @return A pointer to the Wayland display (`struct wl_display*`), or NULL if the platform is not in use.
 1079-*/
 1080-RGFWDEF struct wl_display* RGFW_getDisplay_Wayland(void);
 1081-
 1082-/**!
 1083- * @brief Sets the class name for X11 and WinAPI windows.
 1084- * Windows with the same class name will be grouped by the window manager.
 1085- * By default, the class name matches the root window’s name.
 1086- * @param name The class name to assign.
 1087-*/
 1088-RGFWDEF void RGFW_setClassName(const char* name);
 1089-
 1090-/**!
 1091- * @brief Sets the X11 instance name.
 1092- * By default, the window name will be used as the instance name.
 1093- * @param name The X11 instance name to set.
 1094-*/
 1095-RGFWDEF void RGFW_setXInstName(const char* name);
 1096-
 1097-/**!
 1098- * @brief (macOS only) Changes the current working directory to the application’s resource folder.
 1099-*/
 1100-RGFWDEF void RGFW_moveToMacOSResourceDir(void);
 1101-
 1102-/*! copy image to another image, respecting each image's format */
 1103-RGFWDEF void RGFW_copyImageData(u8* dest_data, i32 w, i32 h, RGFW_format dest_format, u8* src_data, RGFW_format src_format, RGFW_convertImageDataFunc func);
 1104-
 1105-/**!
 1106- * @brief Returns the size (in bytes) of the RGFW_nativeImage structure.
 1107- * @return The size of the RGFW_nativeImage structure.
 1108-*/
 1109-RGFWDEF size_t RGFW_sizeofNativeImage(void);
 1110-
 1111-/**!
 1112- * @brief Returns the size (in bytes) of the RGFW_surface structure.
 1113- * @return The size of the RGFW_surface structure.
 1114-*/
 1115-RGFWDEF size_t RGFW_sizeofSurface(void);
 1116-
 1117-/**!
 1118- * @brief Returns the native format type for the system
 1119- * @return the native format type for the system as a RGFW_format enum value
 1120-*/
 1121-RGFWDEF RGFW_format RGFW_nativeFormat(void);
 1122-
 1123-/**!
 1124- * @brief Creates a new surface from raw pixel data.
 1125- * @param data A pointer to the pixel data buffer.
 1126- * @param w The width of the surface in pixels.
 1127- * @param h The height of the surface in pixels.
 1128- * @param format The pixel format of the data.
 1129- * @return A pointer to the newly created RGFW_surface.
 1130- *
 1131- * NOTE: when you create a surface using RGFW_createSurface / ptr, on X11 it uses the root window's visual
 1132- * this means it may fail to render on any other window if the visual does not match
 1133- * RGFW_window_createSurface and RGFW_window_createSurfacePtr exist only for X11 to address this issues
 1134- * Of course, you can also manually set the root window with RGFW_setRootWindow
 1135-*/
 1136-RGFWDEF RGFW_surface* RGFW_createSurface(u8* data, i32 w, i32 h, RGFW_format format);
 1137-
 1138-/**!
 1139- * @brief Creates a surface using a pre-allocated RGFW_surface structure.
 1140- * @param data A pointer to the pixel data buffer.
 1141- * @param w The width of the surface in pixels.
 1142- * @param h The height of the surface in pixels.
 1143- * @param format The pixel format of the data.
 1144- * @param surface A pointer to a pre-allocated RGFW_surface structure.
 1145- * @return RGFW_TRUE if successful, RGFW_FALSE otherwise.
 1146-*/
 1147-RGFWDEF RGFW_bool RGFW_createSurfacePtr(u8* data, i32 w, i32 h, RGFW_format format, RGFW_surface* surface);
 1148-
 1149-/**!
 1150- * @brief Retrieves the native image associated with a surface.
 1151- * @param surface A pointer to the RGFW_surface.
 1152- * @return A pointer to the native RGFW_nativeImage associated with the surface.
 1153-*/
 1154-RGFWDEF RGFW_nativeImage* RGFW_surface_getNativeImage(RGFW_surface* surface);
 1155-
 1156-/**!
 1157- * @brief Frees the surface pointer and any buffers used for software rendering.
 1158- * @param surface A pointer to the RGFW_surface to free.
 1159-*/
 1160-RGFWDEF void RGFW_surface_free(RGFW_surface* surface);
 1161-
 1162-/**!
 1163- * @brief Frees only the internal buffers used for software rendering, leaving the surface struct intact.
 1164- * @param surface A pointer to the RGFW_surface whose buffers should be freed.
 1165-*/
 1166-RGFWDEF void RGFW_surface_freePtr(RGFW_surface* surface);
 1167-
 1168-
 1169-/**!
 1170- * @brief create a mouse icon from bitmap data (similar to RGFW_window_setIcon).
 1171- * @param data A pointer to the bitmap pixel data.
 1172- * @param w The width of the mouse icon in pixels.
 1173- * @param h The height of the mouse icon in pixels.
 1174- * @param format The pixel format of the data.
 1175- * @return A pointer to the newly loaded RGFW_mouse structure.
 1176- *
 1177- * @note The icon is not resized by default.
 1178-*/
 1179-RGFWDEF RGFW_mouse* RGFW_createMouse(u8* data, i32 w, i32 h, RGFW_format format);
 1180-
 1181-/**!
 1182- * @brief create a standard mouse icon
 1183- * @param mouse The standard cursor type (see RGFW_MOUSE enum).
 1184- * @return A pointer to the newly loaded RGFW_mouse structure.
 1185-*/
 1186-RGFWDEF RGFW_mouse* RGFW_createMouseStandard(RGFW_mouseIcon mouse);
 1187-
 1188-/**!
 1189- * @brief Frees the data associated with an RGFW_mouse structure.
 1190- * @param mouse A pointer to the RGFW_mouse to free.
 1191-*/
 1192-RGFWDEF void RGFW_freeMouse(RGFW_mouse* mouse);
 1193-
 1194-/**!
 1195- * @brief Get an allocated array of the supported modes of a monitor
 1196- * @param monitor the source monitor object
 1197- * @param count [OUTPUT] the count of the array
 1198- * @return the allocated array of supported modes
 1199-*/
 1200-RGFWDEF RGFW_monitorMode* RGFW_monitor_getModes(RGFW_monitor* monitor, size_t* count);
 1201-
 1202-/**!
 1203- * @brief Free RGFW allocated modes array
 1204- * @param monitor the source monitor object
 1205- * @param modes a pointer to an allocated array of modes
 1206-*/
 1207-RGFWDEF void RGFW_freeModes(RGFW_monitorMode* modes);
 1208-
 1209-/**!
 1210- * @brief Get the supported modes of a monitor using a pre-allocated array
 1211- * @param monitor the source monitor object
 1212- * @param modes [OUTPUT] a pointer to an allocated array of modes
 1213- * @return the number of (possible) modes, if [modes == NULL] the possible nodes *may* be less than the actual modes
 1214-*/
 1215-RGFWDEF size_t RGFW_monitor_getModesPtr(RGFW_monitor* monitor, RGFW_monitorMode** modes);
 1216-
 1217-/**!
 1218- * @brief find the closest monitor mode based on the give mode with size being the highest priority, format being the second and refreshrate being the third.
 1219- * @param monitor the source monitor object
 1220- * @param mode user filled mode to use for comparison
 1221- * @param modes [OUTPUT] a pointer to be filled with the output closest monitor
 1222- * @return returns true if a suitable monitor was found and false if no suitable monitor was found at all
 1223-*/
 1224-
 1225-RGFWDEF RGFW_bool RGFW_monitor_findClosestMode(RGFW_monitor* monitor, RGFW_monitorMode* mode, RGFW_monitorMode* closest);
 1226-
 1227-/**!
 1228- * @brief Get the allocated gamma ramp
 1229- * @param monitor the source monitor object
 1230-*/
 1231-RGFWDEF RGFW_gammaRamp* RGFW_monitor_getGammaRamp(RGFW_monitor* monitor);
 1232-
 1233-/**!
 1234- * @brief Free the gamma ramp allocated by RGFW
 1235- * @param allocated gamma ramp
 1236-*/
 1237-RGFWDEF void RGFW_freeGammaRamp(RGFW_gammaRamp* ramp);
 1238-
 1239-/**!
 1240- * @brief Get the monitor's gamma ramp using a pre-allocated struct with allocated data
 1241- * @param monitor the source monitor object
 1242- * @param ramp [OUTPUT] a pointer to an allocated gamma ramp (can be NULL to just get the count)
 1243- * @return the count of the gamma ramp
 1244-*/
 1245-RGFWDEF size_t RGFW_monitor_getGammaRampPtr(RGFW_monitor* monitor, RGFW_gammaRamp* ramp);
 1246-
 1247-/**!
 1248- * @brief Set the monitor's gamma ramp using a pre-allocated struct with allocated data
 1249- * @param monitor the source monitor object
 1250- * @param ramp a pointer to an allocated gamma ramp
 1251- * @return a bool if the function was successful
 1252-*/
 1253-RGFWDEF RGFW_bool RGFW_monitor_setGammaRamp(RGFW_monitor* monitor, RGFW_gammaRamp* ramp);
 1254-
 1255-/**!
 1256- * @brief Create and set the monitor's gamma ramp with a base gamma exponent
 1257- * @param monitor the source monitor object
 1258- * @param the gamma exponent
 1259- * @return a bool if the function was successful
 1260-*/
 1261-RGFWDEF RGFW_bool RGFW_monitor_setGamma(RGFW_monitor* monitor, float gamma);
 1262-
 1263-/**!
 1264- * @brief Create and set the monitor's gamma ramp with a base gamma exponent using a pre-allocated array
 1265- * @param monitor the source monitor object
 1266- * @param gamma the gamma exponent
 1267- * @param pre-allocated gammaramp channel
 1268- * @param count the length of the allocated channel array
 1269- * @return a bool if the function was successful
 1270-*/
 1271-RGFWDEF RGFW_bool RGFW_monitor_setGammaPtr(RGFW_monitor* monitor, float gamma, u16* ptr, size_t count);
 1272-
 1273-/**!
 1274- * @brief Get the workarea of a monitor, meaning the parts not occupied by OS graphics (i.e. the taskbar)
 1275- * @param monitor the source monitor object
 1276- * @param x [OUTPUT] the x pos of the workarea
 1277- * @param y [OUTPUT] the y pos of the workarea
 1278- * @param w [OUTPUT] the width of the workarea
 1279- * @param h [OUTPUT] the height of the workarea
 1280- * @return a bool if the function was successful
 1281-*/
 1282-RGFWDEF RGFW_bool RGFW_monitor_getWorkarea(RGFW_monitor* monitor, i32* x, i32* y, i32* width, i32* height);
 1283-
 1284-/**!
 1285- * @brief Get the position of a monitor (the same as monitor.x / monitor.y)
 1286- * @param x [OUTPUT] the x position of the monitor
 1287- * @param y [OUTPUT] the y position of the monitor
 1288- * @return a bool if the function was successful
 1289-*/
 1290-RGFWDEF RGFW_bool RGFW_monitor_getPosition(RGFW_monitor* monitor, i32* x, i32* y);
 1291-
 1292-/**!
 1293- * @brief Get the name of a monitor (the same as monitor.name)
 1294- * @return the cstring of the monitor's name
 1295-*/
 1296-RGFWDEF const char* RGFW_monitor_getName(RGFW_monitor* monitor);
 1297-
 1298-/**!
 1299- * @brief Get the scale of a monitor (the same as monitor.scaleX / monitor.scaleY)
 1300- * @param monitor the source monitor object
 1301- * @param x [OUTPUT] the x scale of the monitor
 1302- * @param y [OUTPUT] the y scale of the monitor
 1303- * @return a bool if the function was successful
 1304-*/
 1305-RGFWDEF RGFW_bool RGFW_monitor_getScale(RGFW_monitor* monitor, float* x, float* y);
 1306-
 1307-/**!
 1308- * @brief Get the physical size of a monitor (the same as monitor.physW / monitor.physH)
 1309- * @param monitor the source monitor object
 1310- * @param w [OUTPUT] the physical width of the monitor
 1311- * @param h [OUTPUT] the physical height of the monitor
 1312- * @return a bool if the function was successful
 1313-*/
 1314-RGFWDEF RGFW_bool RGFW_monitor_getPhysicalSize(RGFW_monitor* monitor, float* w, float* h);
 1315-
 1316-/**!
 1317- * @brief Set the user pointer of a monitor (the same as monitor.userPtr = userPtr)
 1318- * @param monitor the source monitor object
 1319- * @param userPtr the new user pointer for the monitor
 1320-*/
 1321-RGFWDEF void RGFW_monitor_setUserPtr(RGFW_monitor* monitor, void* userPtr);
 1322-
 1323-/**!
 1324- * @brief Get the user pointer of a monitor (the same as monitor.userPtr)
 1325- * @param monitor the source monitor object
 1326- * @return the user pointer of the monitor
 1327-*/
 1328-RGFWDEF void* RGFW_monitor_getUserPtr(RGFW_monitor* monitor);
 1329-
 1330-/**!
 1331- * @brief Get the mode of a monitor (the same as monitor.mode)
 1332- * @param monitor the source monitor object
 1333- * @param mode [OUTPUT] current mode the monitor
 1334- * @return a bool if the function was successful
 1335-*/
 1336-RGFWDEF RGFW_bool RGFW_monitor_getMode(RGFW_monitor* monitor, RGFW_monitorMode* mode);
 1337-
 1338-/**!
 1339- * @brief Poll and check for monitor updates (this is called internally on monitor update events and RGFW_init)
 1340-*/
 1341-RGFWDEF void RGFW_pollMonitors(void);
 1342-
 1343-/**!
 1344- * @brief Allocates and returns an array of all available monitors.
 1345- * @param len [OUTPUT] A pointer to store the number of monitors found.
 1346- * @return An allocated array of pointers to RGFW_monitor structures that must be freed.
 1347-*/
 1348-RGFWDEF RGFW_monitor** RGFW_getMonitors(size_t* len);
 1349-
 1350-/**!
 1351- * @brief fills a pre-allocated array with available monitors.
 1352- * @param maximum number of monitors that the passed [monitors] buffer supports, can be zero to get the length alone
 1353- * @param pre-allocated buffer of monitors, can be NULL to get the length alone
 1354- * @param len [OUTPUT] A pointer to store the number of monitors found, if max is not zero and monitors is not NULL, length will be set to max.
 1355- * @return An array of pointers to RGFW_monitor structures or NULL if the function failed.
 1356-*/
 1357-RGFWDEF RGFW_bool RGFW_getMonitorsPtr(size_t max, RGFW_monitor** monitors, size_t* len);
 1358-
 1359-/**!
 1360- * @brief Retrieves the primary monitor.
 1361- * @return A pointer to the RGFW_monitor structure representing the primary monitor.
 1362-*/
 1363-RGFWDEF RGFW_monitor* RGFW_getPrimaryMonitor(void);
 1364-
 1365-/**!
 1366- * @brief Requests the display mode for a monitor (based on what attributes are directly requested).
 1367- * @param mon The monitor to apply the mode change to.
 1368- * @param mode The desired RGFW_monitorMode.
 1369- * @param request The RGFW_modeRequest describing how to handle the mode change.
 1370- * @return RGFW_TRUE if the mode was successfully applied, otherwise RGFW_FALSE.
 1371-*/
 1372-RGFWDEF RGFW_bool RGFW_monitor_requestMode(RGFW_monitor* mon, RGFW_monitorMode* mode, RGFW_modeRequest request);
 1373-
 1374-/**!
 1375- * @brief Sets a specific display mode for a monitor directly.
 1376- * @param mon The monitor to apply the mode change to.
 1377- * @param mode The desired RGFW_monitorMode.
 1378- * @param request The RGFW_modeRequest describing how to handle the mode change.
 1379- * @return RGFW_TRUE if the mode was successfully applied, otherwise RGFW_FALSE.
 1380-*/
 1381-RGFWDEF RGFW_bool RGFW_monitor_setMode(RGFW_monitor* mon, RGFW_monitorMode* mode);
 1382-
 1383-/**!
 1384- * @brief Compares two monitor modes to check if they are equivalent.
 1385- * @param mon The first monitor mode.
 1386- * @param mon2 The second monitor mode.
 1387- * @param request The RGFW_modeRequest that defines the comparison parameters.
 1388- * @return RGFW_TRUE if both modes are equivalent, otherwise RGFW_FALSE.
 1389-*/
 1390-RGFWDEF RGFW_bool RGFW_monitorModeCompare(RGFW_monitorMode* mon, RGFW_monitorMode* mon2, RGFW_modeRequest request);
 1391-
 1392-/**!
 1393- * @brief Scales a monitor’s mode to match a window’s size.
 1394- * @param mon The monitor to be scaled.
 1395- * @param win The window whose size should be used as a reference.
 1396- * @return RGFW_TRUE if the scaling was successful, otherwise RGFW_FALSE.
 1397-*/
 1398-RGFWDEF RGFW_bool RGFW_monitor_scaleToWindow(RGFW_monitor* mon, struct RGFW_window* win);
 1399-
 1400- /**!
 1401- * @brief set (enable or disable) raw mouse mode globally
 1402- * @param the boolean state of raw mouse mode
 1403- *
 1404-*/
 1405-RGFWDEF void RGFW_setRawMouseMode(RGFW_bool state);
 1406-
 1407-/**!
 1408- * @brief toggles building the drag-and-drop (DND) linked list
 1409- * @param allow RGFW_TRUE to allow DND building, RGFW_FALSE to disable
 1410- * @note this is for state checking, the list is created by default if you are using the event queue
 1411-*/
 1412-RGFWDEF void RGFW_setBuildDND(RGFW_bool allow);
 1413-
 1414-/**!
 1415-* @brief sleep until RGFW gets an event or the timer ends (defined by OS)
 1416-* @param waitMS how long to wait for the next event (in miliseconds)
 1417-*/
 1418-RGFWDEF void RGFW_waitForEvent(i32 waitMS);
 1419-
 1420-/**!
 1421-* @brief Set if events should be queued or not (enabled by default if the event queue is checked)
 1422-* @param queue boolean value if RGFW should queue events or not
 1423-*/
 1424-RGFWDEF void RGFW_setQueueEvents(RGFW_bool queue);
 1425-
 1426-/**!
 1427- * @brief Sets the callback function for the event.
 1428- * @param the event type for the callback
 1429- * @param func The function to be called when the event is triggered.
 1430- * @return The previously set callback function, if any.
 1431-*/
 1432-RGFWDEF RGFW_genericFunc RGFW_setEventCallback(RGFW_eventType type, RGFW_genericFunc func);
 1433-
 1434-/**!
 1435- * @brief Sets the callback function for two continuous events.
 1436- * @param func The function to be called when the event is triggered.
 1437- * @param [OUTPUT] The previously set callback function for the first event, if any.
 1438- * @param [OUTPUT] The previously set callback function for the second event, if any.
 1439-*/
 1440-RGFWDEF void RGFW_setDualEventCallback(RGFW_eventType type, RGFW_genericFunc func, RGFW_genericFunc* first, RGFW_genericFunc* second);
 1441-
 1442-/**!
 1443- * @brief Sets the callback function for all events.
 1444- * @param func The function to be called when the event is triggered.
 1445- * @param [OUTPUT] a structure that holds an array of all the event callbacks
 1446-*/
 1447-RGFWDEF void RGFW_setAllEventCallbacks(RGFW_genericFunc func, RGFW_callbacks* callbacks);
 1448-
 1449-/**!
 1450-* @brief check all the events until there are none left and updates window structure attributes
 1451-*/
 1452-RGFWDEF void RGFW_pollEvents(void);
 1453-
 1454-/**!
 1455-* @brief check all the events until there are none left and updates window structure attributes
 1456-* queues events if the queue is checked and/or requested
 1457-*/
 1458-RGFWDEF void RGFW_stopCheckEvents(void);
 1459-
 1460-/**!
 1461- * @brief polls and pops the next event
 1462- * @param event [OUTPUT] a pointer to store the retrieved event
 1463- * @return RGFW_TRUE if an event was found, RGFW_FALSE otherwise
 1464- *
 1465- * NOTE: Using this function without a loop may cause event lag.
 1466- * For multi-threaded systems, use RGFW_pollEvents combined with RGFW_checkQueuedEvent.
 1467- *
 1468- * Example:
 1469- * RGFW_event event;
 1470- * while (RGFW_checkEvent(win, &event)) {
 1471- *     // handle event
 1472- * }
 1473-*/
 1474-RGFWDEF RGFW_bool RGFW_checkEvent(RGFW_event* event);
 1475-
 1476-/**!
 1477- * @brief pops the first queued event
 1478- * @param event [OUTPUT] a pointer to store the retrieved event
 1479- * @return RGFW_TRUE if an event was found, RGFW_FALSE otherwise
 1480-*/
 1481-RGFWDEF RGFW_bool RGFW_checkQueuedEvent(RGFW_event* event);
 1482-
 1483-/** * @defgroup Input
 1484-* @{ */
 1485-
 1486-/**!
 1487- * @brief returns true if the key is pressed during the current frame
 1488- * @param key the key code of the key you want to check
 1489- * @return The boolean value if the key is pressed or not
 1490-*/
 1491-RGFWDEF RGFW_bool RGFW_isKeyPressed(RGFW_key key);
 1492-
 1493-/**!
 1494- * @brief returns true if the key was released during the current frame
 1495- * @param key the key code of the key you want to check
 1496- * @return The boolean value if the key is released or not
 1497-*/
 1498-RGFWDEF RGFW_bool RGFW_isKeyReleased(RGFW_key key);
 1499-
 1500-/**!
 1501- * @brief returns true if the key is down
 1502- * @param key the key code of the key you want to check
 1503- * @return The boolean value if the key is down or not
 1504-*/
 1505-RGFWDEF RGFW_bool RGFW_isKeyDown(RGFW_key key);
 1506-
 1507-/**!
 1508- * @brief returns true if the mouse button is pressed during the current frame
 1509- * @param button the mouse button code of the button you want to check
 1510- * @return The boolean value if the button is pressed or not
 1511-*/
 1512-RGFWDEF RGFW_bool RGFW_isMousePressed(RGFW_mouseButton button);
 1513-
 1514-/**!
 1515- * @brief returns true if the mouse button is released during the current frame
 1516- * @param button the mouse button code of the button you want to check
 1517- * @return The boolean value if the button is released or not
 1518-*/
 1519-RGFWDEF RGFW_bool RGFW_isMouseReleased(RGFW_mouseButton button);
 1520-
 1521-/**!
 1522- * @brief returns true if the mouse button is down
 1523- * @param button the mouse button code of the button you want to check
 1524- * @return The boolean value if the button is down or not
 1525-*/
 1526-RGFWDEF RGFW_bool RGFW_isMouseDown(RGFW_mouseButton button);
 1527-
 1528-/**!
 1529- * @brief outputs the current x, y position of the mouse
 1530- * @param X [OUTPUT] a pointer for the output X value
 1531- * @param Y [OUTPUT] a pointer for the output Y value
 1532-*/
 1533-RGFWDEF void RGFW_getMouseScroll(float* x, float* y);
 1534-
 1535-/**!
 1536- * @brief outputs the current x, y movement vector of the mouse
 1537- * @param X [OUTPUT] a pointer for the output X vector value
 1538- * @param Y [OUTPUT] a pointer for the output Y vector value
 1539-*/
 1540-RGFWDEF void RGFW_getMouseVector(float* x, float* y);
 1541-/** @} */
 1542-
 1543-/**!
 1544- * @brief creates a new window
 1545- * @param name the requested title of the window
 1546- * @param x the requested x position of the window
 1547- * @param y the requested y position of the window
 1548- * @param w the requested width of the window
 1549- * @param h the requested height of the window
 1550- * @param flags extra arguments ((u32)0 means no flags used)
 1551- * @return A pointer to the newly created window structure
 1552- *
 1553- * NOTE: (windows) if the executable has an icon resource named RGFW_ICON, it will be set as the initial icon for the window
 1554-*/
 1555-RGFWDEF RGFW_window* RGFW_createWindow(const char* name, i32 x, i32 y, i32 w, i32 h,  RGFW_windowFlags flags);
 1556-
 1557-/**!
 1558- * @brief creates a new window using a pre-allocated window structure
 1559- * @param name the requested title of the window
 1560- * @param x the requested x position of the window
 1561- * @param y the requested y position of the window
 1562- * @param w the requested width of the window
 1563- * @param h the requested height of the window
 1564- * @param flags extra arguments ((u32)0 means no flags used)
 1565- * @param win a pointer the pre-allocated window structure
 1566- * @return A pointer to the newly created window structure
 1567-*/
 1568-RGFWDEF RGFW_window* RGFW_createWindowPtr(const char* name, i32 x, i32 y, i32 w, i32 h, RGFW_windowFlags flags, RGFW_window* win);
 1569-
 1570-/**!
 1571- * @brief creates a new surface structure
 1572- * @param win the source window of the surface
 1573- * @param data a pointer to the raw data of the structure (you allocate this)
 1574- * @param w the width the data
 1575- * @param h the height of the data
 1576- * @return A pointer to the newly created surface structure
 1577- *
 1578- * NOTE: when you create a surface using RGFW_createSurface / ptr, on X11 it uses the root window's visual
 1579- * this means it may fail to render on any other window if the visual does not match
 1580- * RGFW_window_createSurface and RGFW_window_createSurfacePtr exist only for X11 to address this issues
 1581- * Of course, you can also manually set the root window with RGFW_setRootWindow
 1582- */
 1583-RGFWDEF RGFW_surface* RGFW_window_createSurface(RGFW_window* win, u8* data, i32 w, i32 h, RGFW_format format);
 1584-
 1585-/**!
 1586- * @brief creates a new surface structure using a pre-allocated surface structure
 1587- * @param win the source window of the surface
 1588- * @param data a pointer to the raw data of the structure (you allocate this)
 1589- * @param w the width the data
 1590- * @param h the height of the data
 1591- * @param a pointer to the pre-allocated surface structure
 1592- * @return a bool if the creation was successful or not
 1593-*/
 1594-RGFWDEF RGFW_bool RGFW_window_createSurfacePtr(RGFW_window* win, u8* data, i32 w, i32 h, RGFW_format format, RGFW_surface* surface);
 1595-
 1596-/**!
 1597- * @brief set the function/callback used for converting surface data between formats
 1598- * @param surface a pointer to the surface
 1599- * @param a function pointer for the function to use [if NULL the default function is used]
 1600-*/
 1601-RGFWDEF void RGFW_surface_setConvertFunc(RGFW_surface* surface, RGFW_convertImageDataFunc func);
 1602-
 1603-/**!
 1604- * @brief blits a surface stucture to the window
 1605- * @param win a pointer the window to blit to
 1606- * @param surface a pointer to the surface
 1607-*/
 1608-RGFWDEF void RGFW_window_blitSurface(RGFW_window* win, RGFW_surface* surface);
 1609-
 1610-/**!
 1611- * @brief gets the position of the window | with RGFW_window.x and window.y
 1612- * @param x [OUTPUT] the x position of the window
 1613- * @param y [OUTPUT] the y position of the window
 1614- * @return a bool if the function was successful
 1615-*/
 1616-RGFWDEF RGFW_bool RGFW_window_getPosition(RGFW_window* win, i32* x, i32* y); /*!<  */
 1617-
 1618-/**!
 1619- * @brief gets the size of the window | with RGFW_window.w and window.h
 1620- * @param win a pointer to the window
 1621- * @param w [OUTPUT] the width of the window
 1622- * @param h [OUTPUT] the height of the window
 1623- * @return a bool if the function was successful
 1624-*/
 1625-RGFWDEF RGFW_bool RGFW_window_getSize(RGFW_window* win, i32* w, i32* h);
 1626-
 1627-/**!
 1628- * @brief gets the size of the window in exact pixels
 1629- * @param win a pointer to the window
 1630- * @param w [OUTPUT] the width of the window
 1631- * @param h [OUTPUT] the height of the window
 1632- * @return a bool if the function was successful
 1633-*/
 1634-RGFWDEF RGFW_bool RGFW_window_getSizeInPixels(RGFW_window* win, i32* w, i32* h);
 1635-
 1636-/**!
 1637- * @brief gets the flags of the window | returns RGFW_window._flags
 1638- * @param win a pointer to the window
 1639- * @return the window flags
 1640-*/
 1641-RGFWDEF u32 RGFW_window_getFlags(RGFW_window* win);
 1642-
 1643-/**!
 1644- * @brief returns the exit key assigned to the window
 1645- * @param win a pointer to the target window
 1646- * @return The key code assigned as the exit key
 1647-*/
 1648-RGFWDEF RGFW_key RGFW_window_getExitKey(RGFW_window* win);
 1649-
 1650-/**!
 1651- * @brief sets the exit key for the window
 1652- * @param win a pointer to the target window
 1653- * @param key the key code to assign as the exit key
 1654-*/
 1655-RGFWDEF void RGFW_window_setExitKey(RGFW_window* win, RGFW_key key);
 1656-
 1657-/**!
 1658- * @brief sets the types of events you want the window to receive
 1659- * @param win a pointer to the target window
 1660- * @param events the event flags to enable (use RGFW_allEventFlags for all)
 1661-*/
 1662-RGFWDEF void RGFW_window_setEnabledEvents(RGFW_window* win, RGFW_eventFlag events);
 1663-
 1664-/**!
 1665- * @brief gets the currently enabled events for the window
 1666- * @param win a pointer to the target window
 1667- * @return The enabled event flags for the window
 1668-*/
 1669-RGFWDEF RGFW_eventFlag RGFW_window_getEnabledEvents(RGFW_window* win);
 1670-
 1671-/**!
 1672- * @brief enables all events and disables selected ones
 1673- * @param win a pointer to the target window
 1674- * @param events the event flags to disable
 1675-*/
 1676-RGFWDEF void RGFW_window_setDisabledEvents(RGFW_window* win, RGFW_eventFlag events);
 1677-
 1678-/**!
 1679- * @brief directly enables or disables a specific event or group of events
 1680- * @param win a pointer to the target window
 1681- * @param event the event flag or group of flags to modify
 1682- * @param state RGFW_TRUE to enable, RGFW_FALSE to disable
 1683-*/
 1684-RGFWDEF void RGFW_window_setEventState(RGFW_window* win, RGFW_eventFlag event, RGFW_bool state);
 1685-
 1686-/**!
 1687- * @brief gets the user pointer associated with the window
 1688- * @param win a pointer to the target window
 1689- * @return The user-defined pointer stored in the window
 1690-*/
 1691-RGFWDEF void* RGFW_window_getUserPtr(RGFW_window* win);
 1692-
 1693-/**!
 1694- * @brief sets a user pointer for the window
 1695- * @param win a pointer to the target window
 1696- * @param ptr a pointer to associate with the window
 1697-*/
 1698-RGFWDEF void RGFW_window_setUserPtr(RGFW_window* win, void* ptr);
 1699-
 1700-/**!
 1701- * @brief retrieves the platform-specific window source pointer
 1702- * @param win a pointer to the target window
 1703- * @return A pointer to the internal RGFW_window_src structure
 1704-*/
 1705-RGFWDEF RGFW_window_src* RGFW_window_getSrc(RGFW_window* win);
 1706-
 1707-/**!
 1708- * @brief sets the macOS layer object associated with the window
 1709- * @param win a pointer to the target window
 1710- * @param layer a pointer to the macOS layer object
 1711- * @note Only available on macOS platforms
 1712-*/
 1713-RGFWDEF void RGFW_window_setLayer_OSX(RGFW_window* win, void* layer);
 1714-
 1715-/**!
 1716- * @brief retrieves the macOS view object associated with the window
 1717- * @param win a pointer to the target window
 1718- * @return A pointer to the macOS view object, or NULL if not on macOS
 1719-*/
 1720-RGFWDEF void* RGFW_window_getView_OSX(RGFW_window* win);
 1721-
 1722-/**!
 1723- * @brief retrieves the macOS window object
 1724- * @param win a pointer to the target window
 1725- * @return A pointer to the macOS window object, or NULL if not on macOS
 1726-*/
 1727-RGFWDEF void* RGFW_window_getWindow_OSX(RGFW_window* win);
 1728-
 1729-/**!
 1730- * @brief retrieves the HWND handle for the window
 1731- * @param win a pointer to the target window
 1732- * @return A pointer to the Windows HWND handle, or NULL if not on Windows
 1733-*/
 1734-RGFWDEF void* RGFW_window_getHWND(RGFW_window* win);
 1735-
 1736-/**!
 1737- * @brief retrieves the HDC handle for the window
 1738- * @param win a pointer to the target window
 1739- * @return A pointer to the Windows HDC handle, or NULL if not on Windows
 1740-*/
 1741-RGFWDEF void* RGFW_window_getHDC(RGFW_window* win);
 1742-
 1743-/**!
 1744- * @brief retrieves the X11 Window handle for the window
 1745- * @param win a pointer to the target window
 1746- * @return The X11 Window handle, or 0 if not on X11
 1747-*/
 1748-RGFWDEF u64 RGFW_window_getWindow_X11(RGFW_window* win);
 1749-
 1750-/**!
 1751- * @brief retrieves the Wayland surface handle for the window
 1752- * @param win a pointer to the target window
 1753- * @return A pointer to the Wayland wl_surface, or NULL if not on Wayland
 1754-*/
 1755-RGFWDEF struct wl_surface* RGFW_window_getWindow_Wayland(RGFW_window* win);
 1756-
 1757-/** * @defgroup Window_management
 1758-* @{ */
 1759-
 1760-/*! set the window flags (will undo flags if they don't match the old ones) */
 1761-RGFWDEF void RGFW_window_setFlags(RGFW_window* win, RGFW_windowFlags);
 1762-
 1763-/**!
 1764- * @brief polls and pops the next event with the matching target window in event queue, pushes back events that don't match
 1765- * @param win a pointer to the target window
 1766- * @param event [OUTPUT] a pointer to store the retrieved event
 1767- * @return RGFW_TRUE if an event was found, RGFW_FALSE otherwise
 1768- *
 1769- * NOTE: Using this function without a loop may cause event lag.
 1770- * For multi-threaded systems, use RGFW_pollEvents combined with RGFW_window_checkQueuedEvent.
 1771- *
 1772- * Example:
 1773- * RGFW_event event;
 1774- * while (RGFW_window_checkEvent(win, &event)) {
 1775- *     // handle event
 1776- * }
 1777-*/
 1778-RGFWDEF RGFW_bool RGFW_window_checkEvent(RGFW_window* win, RGFW_event* event);
 1779-
 1780-/**!
 1781- * @brief pops the first queued event with the matching target window, pushes back events that don't match
 1782- * @param win a pointer to the target window
 1783- * @param event [OUTPUT] a pointer to store the retrieved event
 1784- * @return RGFW_TRUE if an event was found, RGFW_FALSE otherwise
 1785-*/
 1786-RGFWDEF RGFW_bool RGFW_window_checkQueuedEvent(RGFW_window* win, RGFW_event* event);
 1787-
 1788-/**!
 1789- * @brief checks if a key was pressed while the window is in focus
 1790- * @param win a pointer to the target window
 1791- * @param key the key code to check
 1792- * @return RGFW_TRUE if the key was pressed, RGFW_FALSE otherwise
 1793-*/
 1794-RGFWDEF RGFW_bool RGFW_window_isKeyPressed(RGFW_window* win, RGFW_key key);
 1795-
 1796-/**!
 1797- * @brief checks if a key is currently being held down
 1798- * @param win a pointer to the target window
 1799- * @param key the key code to check
 1800- * @return RGFW_TRUE if the key is held down, RGFW_FALSE otherwise
 1801-*/
 1802-RGFWDEF RGFW_bool RGFW_window_isKeyDown(RGFW_window* win, RGFW_key key);
 1803-
 1804-/**!
 1805- * @brief checks if a key was released
 1806- * @param win a pointer to the target window
 1807- * @param key the key code to check
 1808- * @return RGFW_TRUE if the key was released, RGFW_FALSE otherwise
 1809-*/
 1810-RGFWDEF RGFW_bool RGFW_window_isKeyReleased(RGFW_window* win, RGFW_key key);
 1811-
 1812-/**!
 1813- * @brief checks if a mouse button was pressed
 1814- * @param win a pointer to the target window
 1815- * @param button the mouse button code to check
 1816- * @return RGFW_TRUE if the mouse button was pressed, RGFW_FALSE otherwise
 1817-*/
 1818-RGFWDEF RGFW_bool RGFW_window_isMousePressed(RGFW_window* win, RGFW_mouseButton button);
 1819-
 1820-/**!
 1821- * @brief checks if a mouse button is currently held down
 1822- * @param win a pointer to the target window
 1823- * @param button the mouse button code to check
 1824- * @return RGFW_TRUE if the mouse button is down, RGFW_FALSE otherwise
 1825-*/
 1826-RGFWDEF RGFW_bool RGFW_window_isMouseDown(RGFW_window* win, RGFW_mouseButton button);
 1827-
 1828-/**!
 1829- * @brief checks if a mouse button was released
 1830- * @param win a pointer to the target window
 1831- * @param button the mouse button code to check
 1832- * @return RGFW_TRUE if the mouse button was released, RGFW_FALSE otherwise
 1833-*/
 1834-RGFWDEF RGFW_bool RGFW_window_isMouseReleased(RGFW_window* win, RGFW_mouseButton button);
 1835-
 1836-/**!
 1837- * @brief checks if the mouse left the window (true only for the first frame)
 1838- * @param win a pointer to the target window
 1839- * @return RGFW_TRUE if the mouse left, RGFW_FALSE otherwise
 1840-*/
 1841-RGFWDEF RGFW_bool RGFW_window_didMouseLeave(RGFW_window* win);
 1842-
 1843-/**!
 1844- * @brief checks if the mouse entered the window (true only for the first frame)
 1845- * @param win a pointer to the target window
 1846- * @return RGFW_TRUE if the mouse entered, RGFW_FALSE otherwise
 1847-*/
 1848-RGFWDEF RGFW_bool RGFW_window_didMouseEnter(RGFW_window* win);
 1849-
 1850-/**!
 1851- * @brief checks if the mouse is currently inside the window bounds
 1852- * @param win a pointer to the target window
 1853- * @return RGFW_TRUE if the mouse is inside, RGFW_FALSE otherwise
 1854-*/
 1855-RGFWDEF RGFW_bool RGFW_window_isMouseInside(RGFW_window* win);
 1856-
 1857-/**!
 1858- * @brief checks if there is data being dragged into or within the window
 1859- * @param win a pointer to the target window
 1860- * @return RGFW_TRUE if data is being dragged, RGFW_FALSE otherwise
 1861-*/
 1862-RGFWDEF RGFW_bool RGFW_window_isDataDragging(RGFW_window* win);
 1863-
 1864-/**!
 1865- * @brief gets the position of a data drag
 1866- * @param win a pointer to the target window
 1867- * @param x [OUTPUT] pointer to store the x position
 1868- * @param y [OUTPUT] pointer to store the y position
 1869- * @return RGFW_TRUE if there is an active drag, RGFW_FALSE otherwise
 1870-*/
 1871-RGFWDEF RGFW_bool RGFW_window_getDataDrag(RGFW_window* win, i32* x, i32* y);
 1872-
 1873-/**!
 1874- * @brief checks if a data drop occurred in the window (first frame only)
 1875- * @param win a pointer to the target window
 1876- * @return RGFW_TRUE if data was dropped, RGFW_FALSE otherwise
 1877-*/
 1878-RGFWDEF RGFW_bool RGFW_window_didDataDrop(RGFW_window* win);
 1879-
 1880-/**!
 1881- * @brief retrieves data from a data drop (drag and drop)
 1882- * @param win a pointer to the target window
 1883- * @return a valid pointer to the root drag node if a data drop occurred, NULL otherwise
 1884-*/
 1885-RGFWDEF RGFW_dataDropNode* RGFW_window_getDataDrop(RGFW_window* win);
 1886-
 1887-/**!
 1888- * @brief closes the window and frees its associated structure
 1889- * @param win a pointer to the target window
 1890-*/
 1891-RGFWDEF void RGFW_window_close(RGFW_window* win);
 1892-
 1893-/**!
 1894- * @brief closes the window without freeing its structure
 1895- * @param win a pointer to the target window
 1896-*/
 1897-RGFWDEF void RGFW_window_closePtr(RGFW_window* win);
 1898-
 1899-/**!
 1900- * @brief fetches the size of the window through the OS (and updates the internal values)
 1901- * @param win a pointer to the window
 1902- * @param w [OUTPUT] the width of the window
 1903- * @param h [OUTPUT] the height of the window
 1904- * @return a bool if the function was successful
 1905-*/
 1906-RGFWDEF RGFW_bool RGFW_window_fetchSize(RGFW_window* win, i32* w, i32* h);
 1907-
 1908-/**!
 1909- * @brief moves the window to a new position on the screen
 1910- * @param win a pointer to the target window
 1911- * @param x the new x position
 1912- * @param y the new y position
 1913-*/
 1914-RGFWDEF void RGFW_window_move(RGFW_window* win, i32 x, i32 y);
 1915-
 1916-/**!
 1917- * @brief moves the window to a specific monitor
 1918- * @param win a pointer to the target window
 1919- * @param m the target monitor
 1920-*/
 1921-RGFWDEF void RGFW_window_moveToMonitor(RGFW_window* win, RGFW_monitor* m);
 1922-
 1923-/**!
 1924- * @brief resizes the window to the given dimensions
 1925- * @param win a pointer to the target window
 1926- * @param w the new width
 1927- * @param h the new height
 1928-*/
 1929-RGFWDEF void RGFW_window_resize(RGFW_window* win, i32 w, i32 h);
 1930-
 1931-/**!
 1932- * @brief sets the aspect ratio of the window
 1933- * @param win a pointer to the target window
 1934- * @param w the width ratio
 1935- * @param h the height ratio
 1936-*/
 1937-RGFWDEF void RGFW_window_setAspectRatio(RGFW_window* win, i32 w, i32 h);
 1938-
 1939-/**!
 1940- * @brief sets the minimum size of the window
 1941- * @param win a pointer to the target window
 1942- * @param w the minimum width
 1943- * @param h the minimum height
 1944-*/
 1945-RGFWDEF void RGFW_window_setMinSize(RGFW_window* win, i32 w, i32 h);
 1946-
 1947-/**!
 1948- * @brief sets the maximum size of the window
 1949- * @param win a pointer to the target window
 1950- * @param w the maximum width
 1951- * @param h the maximum height
 1952-*/
 1953-RGFWDEF void RGFW_window_setMaxSize(RGFW_window* win, i32 w, i32 h);
 1954-
 1955-/**!
 1956- * @brief sets focus to the window
 1957- * @param win a pointer to the target window
 1958-*/
 1959-RGFWDEF void RGFW_window_focus(RGFW_window* win);
 1960-
 1961-/**!
 1962- * @brief checks if the window is currently in focus
 1963- * @param win a pointer to the target window
 1964- * @return RGFW_TRUE if the window is in focus, RGFW_FALSE otherwise
 1965-*/
 1966-RGFWDEF RGFW_bool RGFW_window_isInFocus(RGFW_window* win);
 1967-
 1968-/**!
 1969- * @brief raises the window to the top of the stack
 1970- * @param win a pointer to the target window
 1971-*/
 1972-RGFWDEF void RGFW_window_raise(RGFW_window* win);
 1973-
 1974-/**!
 1975- * @brief maximizes the window
 1976- * @param win a pointer to the target window
 1977-*/
 1978-RGFWDEF void RGFW_window_maximize(RGFW_window* win);
 1979-
 1980-/**!
 1981- * @brief toggles fullscreen mode for the window
 1982- * @param win a pointer to the target window
 1983- * @param fullscreen RGFW_TRUE to enable fullscreen, RGFW_FALSE to disable
 1984-*/
 1985-RGFWDEF void RGFW_window_setFullscreen(RGFW_window* win, RGFW_bool fullscreen);
 1986-
 1987-/**!
 1988- * @brief centers the window on the screen
 1989- * @param win a pointer to the target window
 1990-*/
 1991-RGFWDEF void RGFW_window_center(RGFW_window* win);
 1992-
 1993-/**!
 1994- * @brief minimizes the window
 1995- * @param win a pointer to the target window
 1996-*/
 1997-RGFWDEF void RGFW_window_minimize(RGFW_window* win);
 1998-
 1999-/**!
 2000- * @brief restores the window from minimized state
 2001- * @param win a pointer to the target window
 2002-*/
 2003-RGFWDEF void RGFW_window_restore(RGFW_window* win);
 2004-
 2005-/**!
 2006- * @brief makes the window a floating window
 2007- * @param win a pointer to the target window
 2008- * @param floating RGFW_TRUE to float, RGFW_FALSE to disable
 2009-*/
 2010-RGFWDEF void RGFW_window_setFloating(RGFW_window* win, RGFW_bool floating);
 2011-
 2012-/**!
 2013- * @brief sets the opacity level of the window
 2014- * @param win a pointer to the target window
 2015- * @param opacity the opacity level (0–255)
 2016-*/
 2017-RGFWDEF void RGFW_window_setOpacity(RGFW_window* win, u8 opacity);
 2018-
 2019-/**!
 2020- * @brief toggles window borders / frame / decor
 2021- * @param win a pointer to the target window
 2022- * @param border RGFW_TRUE for bordered, RGFW_FALSE for borderless
 2023-*/
 2024-RGFWDEF void RGFW_window_setBorder(RGFW_window* win, RGFW_bool border);
 2025-
 2026-/**!
 2027- * @brief checks if the window is borderless (has a border, frame or decor)
 2028- * @param win a pointer to the target window
 2029- * @return RGFW_TRUE if borderless, RGFW_FALSE otherwise
 2030-*/
 2031-RGFWDEF RGFW_bool RGFW_window_borderless(RGFW_window* win);
 2032-
 2033-/**!
 2034- * @brief toggles drag-and-drop (DND) support for the window
 2035- * @param win a pointer to the target window
 2036- * @param allow RGFW_TRUE to allow DND, RGFW_FALSE to disable
 2037- * @note RGFW_windowAllowDND must still be passed when creating the window
 2038-*/
 2039-RGFWDEF void RGFW_window_setDND(RGFW_window* win, RGFW_bool allow);
 2040-
 2041-/**!
 2042- * @brief checks if drag-and-drop (DND) is allowed
 2043- * @param win a pointer to the target window
 2044- * @return RGFW_TRUE if DND is enabled, RGFW_FALSE otherwise
 2045-*/
 2046-RGFWDEF RGFW_bool RGFW_window_allowsDND(RGFW_window* win);
 2047-
 2048-#ifndef RGFW_NO_PASSTHROUGH
 2049-/**!
 2050- * @brief toggles mouse passthrough for the window
 2051- * @param win a pointer to the target window
 2052- * @param passthrough RGFW_TRUE to enable passthrough, RGFW_FALSE to disable
 2053-*/
 2054-RGFWDEF void RGFW_window_setMousePassthrough(RGFW_window* win, RGFW_bool passthrough);
 2055-#endif
 2056-
 2057-/**!
 2058- * @brief renames the window
 2059- * @param win a pointer to the target window
 2060- * @param name the new title string for the window
 2061-*/
 2062-RGFWDEF void RGFW_window_setName(RGFW_window* win, const char* name);
 2063-
 2064-/**!
 2065- * @brief sets the icon for the window and taskbar
 2066- * @param win a pointer to the target window
 2067- * @param data the image data
 2068- * @param w the width of the icon
 2069- * @param h the height of the icon
 2070- * @param format the image format
 2071- * @return RGFW_TRUE if successful, RGFW_FALSE otherwise
 2072- *
 2073- * NOTE: The image may be resized by default.
 2074-*/
 2075-RGFWDEF RGFW_bool RGFW_window_setIcon(RGFW_window* win, u8* data, i32 w, i32 h, RGFW_format format);
 2076-
 2077-/**!
 2078- * @brief sets the icon for the window and/or taskbar
 2079- * @param win a pointer to the target window
 2080- * @param data the image data
 2081- * @param w the width of the icon
 2082- * @param h the height of the icon
 2083- * @param format the image format
 2084- * @param type the target icon type (taskbar, window, or both)
 2085- * @return RGFW_TRUE if successful, RGFW_FALSE otherwise
 2086-*/
 2087-RGFWDEF RGFW_bool RGFW_window_setIconEx(RGFW_window* win, u8* data, i32 w, i32 h, RGFW_format format, RGFW_icon type);
 2088-
 2089-/**!
 2090- * @brief sets the mouse icon for the window using a loaded mouse icon
 2091- * @param win a pointer to the target window
 2092- * @param mouse a pointer to the RGFW_mouse struct containing the icon
 2093-*/
 2094-RGFWDEF RGFW_bool RGFW_window_setMouse(RGFW_window* win, RGFW_mouse* mouse);
 2095-
 2096-/**!
 2097- * @brief Sets the mouse to a preloaded [by RGFW] standard system cursor.
 2098- * @param win The target window.
 2099- * @param mouse The standardmouse icon (see RGFW_mouseIcon enum).
 2100- * @return True if the standard cursor was successfully applied.
 2101-*/
 2102-RGFWDEF RGFW_bool RGFW_window_setMouseStandard(RGFW_window* win, RGFW_mouseIcon icon);
 2103-
 2104-/**!
 2105- * @brief Sets the mouse to the default cursor icon.
 2106- * @param win The target window.
 2107- * @return True if the default cursor was successfully set.
 2108-*/
 2109-RGFWDEF RGFW_bool RGFW_window_setMouseDefault(RGFW_window* win);
 2110-
 2111-/**!
 2112- * @brief set (enable or disable) raw mouse mode only for the select window
 2113- * @param win The target window.
 2114- * @param the boolean state of raw mouse mode
 2115- *
 2116-*/
 2117-RGFWDEF void RGFW_window_setRawMouseMode(RGFW_window* win, RGFW_bool state);
 2118-
 2119-/**!
 2120- * @brief lock/unlock the cursor.
 2121- * @param win The target window.
 2122- * @param the boolean state of the mouse's capture state
 2123- *
 2124-*/
 2125-RGFWDEF void RGFW_window_captureMouse(RGFW_window* win, RGFW_bool state);
 2126-
 2127-/**!
 2128- * @brief lock/unlock the cursor and enable raw mpuise mode.
 2129- * @param win The target window.
 2130- * @param the boolean state of raw mouse mode
 2131- *
 2132-*/
 2133-RGFWDEF void RGFW_window_captureRawMouse(RGFW_window* win, RGFW_bool state);
 2134-
 2135-/**!
 2136- * @brief Returns true if the mouse is using raw mouse mode
 2137- * @param win The target window.
 2138- * @return True if the mouse is using raw mouse input mode.
 2139-*/
 2140-RGFWDEF RGFW_bool RGFW_window_isRawMouseMode(RGFW_window* win);
 2141-
 2142-
 2143-/**!
 2144- * @brief Returns true if the mouse is captured
 2145- * @param win The target window.
 2146- * @return True if the mouse is being captured.
 2147-*/
 2148-RGFWDEF RGFW_bool RGFW_window_isCaptured(RGFW_window* win);
 2149-
 2150-/**!
 2151- * @brief Hides the window from view.
 2152- * @param win The target window.
 2153-*/
 2154-RGFWDEF void RGFW_window_hide(RGFW_window* win);
 2155-
 2156-/**!
 2157- * @brief Shows the window if it was hidden.
 2158- * @param win The target window.
 2159-*/
 2160-RGFWDEF void RGFW_window_show(RGFW_window* win);
 2161-
 2162-/**!
 2163- * @breif request a window flash to get attention from the user
 2164- * @param win the target window
 2165- * @param request the flash operation requested
 2166-*/
 2167-RGFWDEF void RGFW_window_flash(RGFW_window* win, RGFW_flashRequest request);
 2168-
 2169-/**!
 2170- * @brief Sets whether the window should close.
 2171- * @param win The target window.
 2172- * @param shouldClose True to signal the window should close, false to keep it open.
 2173- *
 2174- * This can override or trigger the `RGFW_window_shouldClose` state by modifying window flags.
 2175-*/
 2176-RGFWDEF void RGFW_window_setShouldClose(RGFW_window* win, RGFW_bool shouldClose);
 2177-
 2178-/**!
 2179- * @brief Retrieves the current global mouse position.
 2180- * @param x [OUTPUT] Pointer to store the X position of the mouse on the screen.
 2181- * @param y [OUTPUT] Pointer to store the Y position of the mouse on the screen.
 2182- * @return True if the position was successfully retrieved.
 2183-*/
 2184-RGFWDEF RGFW_bool RGFW_getGlobalMouse(i32* x, i32* y);
 2185-
 2186-/**!
 2187- * @brief Retrieves the mouse position relative to the window.
 2188- * @param win The target window.
 2189- * @param x [OUTPUT] Pointer to store the X position within the window.
 2190- * @param y [OUTPUT] Pointer to store the Y position within the window.
 2191- * @return True if the position was successfully retrieved.
 2192-*/
 2193-RGFWDEF RGFW_bool RGFW_window_getMouse(RGFW_window* win, i32* x, i32* y);
 2194-
 2195-/**!
 2196- * @brief Shows or hides the mouse cursor for the window.
 2197- * @param win The target window.
 2198- * @param show True to show the mouse, false to hide it.
 2199-*/
 2200-RGFWDEF void RGFW_window_showMouse(RGFW_window* win, RGFW_bool show);
 2201-
 2202-/**!
 2203- * @brief Checks if the mouse is currently hidden in the window.
 2204- * @param win The target window.
 2205- * @return True if the mouse is hidden.
 2206-*/
 2207-RGFWDEF RGFW_bool RGFW_window_isMouseHidden(RGFW_window* win);
 2208-
 2209-/**!
 2210- * @brief Moves the mouse to the specified position within the window.
 2211- * @param win The target window.
 2212- * @param x The new X position.
 2213- * @param y The new Y position.
 2214-*/
 2215-RGFWDEF void RGFW_window_moveMouse(RGFW_window* win, i32 x, i32 y);
 2216-
 2217-/**!
 2218- * @brief Checks if the window should close.
 2219- * @param win The target window.
 2220- * @return True if the window should close (for example, if ESC was pressed or a close event occurred).
 2221-*/
 2222-RGFWDEF RGFW_bool RGFW_window_shouldClose(RGFW_window* win);
 2223-
 2224-/**!
 2225- * @brief Checks if the window is currently fullscreen.
 2226- * @param win The target window.
 2227- * @return True if the window is fullscreen.
 2228-*/
 2229-RGFWDEF RGFW_bool RGFW_window_isFullscreen(RGFW_window* win);
 2230-
 2231-/**!
 2232- * @brief Checks if the window is currently hidden.
 2233- * @param win The target window.
 2234- * @return True if the window is hidden.
 2235-*/
 2236-RGFWDEF RGFW_bool RGFW_window_isHidden(RGFW_window* win);
 2237-
 2238-/**!
 2239- * @brief Checks if the window is minimized.
 2240- * @param win The target window.
 2241- * @return True if the window is minimized.
 2242-*/
 2243-RGFWDEF RGFW_bool RGFW_window_isMinimized(RGFW_window* win);
 2244-
 2245-/**!
 2246- * @brief Checks if the window is maximized.
 2247- * @param win The target window.
 2248- * @return True if the window is maximized.
 2249-*/
 2250-RGFWDEF RGFW_bool RGFW_window_isMaximized(RGFW_window* win);
 2251-
 2252-/**!
 2253- * @brief Checks if the window is floating.
 2254- * @param win The target window.
 2255- * @return True if the window is floating.
 2256-*/
 2257-RGFWDEF RGFW_bool RGFW_window_isFloating(RGFW_window* win);
 2258-/** @} */
 2259-
 2260-/** * @defgroup Monitor
 2261-* @{ */
 2262-
 2263-/**!
 2264- * @brief Scales the window to match its monitor’s resolution.
 2265- * @param win The target window.
 2266- *
 2267- * This function is automatically called when the flag `RGFW_scaleToMonitor`
 2268- * is used during window creation.
 2269-*/
 2270-RGFWDEF void RGFW_window_scaleToMonitor(RGFW_window* win);
 2271-
 2272-/**!
 2273- * @brief Retrieves the monitor structure associated with the window.
 2274- * @param win The target window.
 2275- * @return The monitor structure of the window.
 2276-*/
 2277-RGFWDEF RGFW_monitor* RGFW_window_getMonitor(RGFW_window* win);
 2278-
 2279-/** @} */
 2280-
 2281-/** * @defgroup Clipboard
 2282-* @{ */
 2283-
 2284-/**!
 2285- * @brief Reads clipboard data.
 2286- * @param size [OUTPUT] A pointer that will be filled with the size of the clipboard data.
 2287- * @return A pointer to the clipboard data as a string.
 2288-*/
 2289-RGFWDEF const char* RGFW_readClipboard(size_t* size);
 2290-
 2291-/**!
 2292- * @brief Reads clipboard data into a provided buffer, or returns the required length if str is NULL.
 2293- * @param str [OUTPUT] A pointer to the buffer that will receive the clipboard data (or NULL to get required size).
 2294- * @param strCapacity The capacity of the provided buffer.
 2295- * @return The number of bytes read or required length of clipboard data.
 2296-*/
 2297-RGFWDEF RGFW_ssize_t RGFW_readClipboardPtr(char* str, size_t strCapacity);
 2298-
 2299-/**!
 2300- * @brief Writes text to the clipboard.
 2301- * @param text The text to be written to the clipboard.
 2302- * @param textLen The length of the text being written.
 2303-*/
 2304-RGFWDEF void RGFW_writeClipboard(const char* text, u32 textLen);
 2305-/** @} */
 2306-
 2307-
 2308-
 2309-/** * @defgroup error handling
 2310-* @{ */
 2311-/**!
 2312- * @brief Sets the callback function to handle debug messages from RGFW.
 2313- * @param func The function pointer to be used as the debug callback.
 2314- * @return The previously set debug callback function.
 2315-*/
 2316-RGFWDEF RGFW_debugFunc RGFW_setDebugCallback(RGFW_debugFunc func);
 2317-
 2318-/**!
 2319- * @brief Sends a debug message manually through the currently set debug callback.
 2320- * @param type The type of debug message being sent.
 2321- * @param err The associated error code.
 2322- * @param msg The debug message text.
 2323-*/
 2324-RGFWDEF void RGFW_debugCallback(RGFW_debugType type, RGFW_errorCode code, const char* msg);
 2325-/** @} */
 2326-
 2327-/** * @defgroup graphics_API
 2328-* @{ */
 2329-
 2330-/*! native rendering API functions */
 2331-#if defined(RGFW_OPENGL)
 2332-/* these are native opengl specific functions and will NOT work with EGL */
 2333-
 2334-/*!< make the window the current OpenGL drawing context
 2335-
 2336-	NOTE:
 2337- 	if you want to switch the graphics context's thread,
 2338-	you have to run RGFW_window_makeCurrentContext_OpenGL(NULL); on the old thread
 2339-	then RGFW_window_makeCurrentContext_OpenGL(valid_window) on the new thread
 2340-*/
 2341-
 2342-/**!
 2343- * @brief Sets the global OpenGL hints to the specified pointer.
 2344- * @param hints A pointer to the RGFW_glHints structure containing the desired OpenGL settings.
 2345-*/
 2346-RGFWDEF void RGFW_setGlobalHints_OpenGL(RGFW_glHints* hints);
 2347-
 2348-/**!
 2349- * @brief Resets the global OpenGL hints to their default values.
 2350-*/
 2351-RGFWDEF void RGFW_resetGlobalHints_OpenGL(void);
 2352-
 2353-/**!
 2354- * @brief Gets the current global OpenGL hints pointer.
 2355- * @return A pointer to the currently active RGFW_glHints structure.
 2356-*/
 2357-RGFWDEF RGFW_glHints* RGFW_getGlobalHints_OpenGL(void);
 2358-
 2359-/**!
 2360- * @brief Creates and allocates an OpenGL context for the specified window.
 2361- * @param win A pointer to the target RGFW_window.
 2362- * @param hints A pointer to an RGFW_glHints structure defining context creation parameters.
 2363- * @return A pointer to the newly created RGFW_glContext.
 2364-*/
 2365-RGFWDEF RGFW_glContext* RGFW_window_createContext_OpenGL(RGFW_window* win, RGFW_glHints* hints);
 2366-
 2367-/**!
 2368- * @brief Creates an OpenGL context for the specified window using a preallocated context structure.
 2369- * @param win A pointer to the target RGFW_window.
 2370- * @param ctx A pointer to an already allocated RGFW_glContext structure.
 2371- * @param hints A pointer to an RGFW_glHints structure defining context creation parameters.
 2372- * @return RGFW_TRUE on success, RGFW_FALSE on failure.
 2373-*/
 2374-RGFWDEF RGFW_bool RGFW_window_createContextPtr_OpenGL(RGFW_window* win, RGFW_glContext* ctx, RGFW_glHints* hints);
 2375-
 2376-/**!
 2377- * @brief Retrieves the OpenGL context associated with a window.
 2378- * @param win A pointer to the RGFW_window.
 2379- * @return A pointer to the associated RGFW_glContext, or NULL if none exists or if the context is EGL-based.
 2380-*/
 2381-RGFWDEF RGFW_glContext* RGFW_window_getContext_OpenGL(RGFW_window* win);
 2382-
 2383-/**!
 2384- * @brief Deletes and frees the OpenGL context.
 2385- * @param win A pointer to the RGFW_window.
 2386- * @param ctx A pointer to the RGFW_glContext to delete.
 2387- *
 2388- * @note This is automatically called by RGFW_window_close if the window’s context is not NULL.
 2389-*/
 2390-RGFWDEF void RGFW_window_deleteContext_OpenGL(RGFW_window* win, RGFW_glContext* ctx);
 2391-
 2392-/**!
 2393- * @brief Deletes the OpenGL context without freeing its memory.
 2394- * @param win A pointer to the RGFW_window.
 2395- * @param ctx A pointer to the RGFW_glContext to delete.
 2396- *
 2397- * @note This is automatically called by RGFW_window_close if the window’s context is not NULL.
 2398-*/
 2399-RGFWDEF void RGFW_window_deleteContextPtr_OpenGL(RGFW_window* win, RGFW_glContext* ctx);
 2400-
 2401-/**!
 2402- * @brief Retrieves the native source context from an RGFW_glContext.
 2403- * @param ctx A pointer to the RGFW_glContext.
 2404- * @return A pointer to the native OpenGL context handle.
 2405-*/
 2406-RGFWDEF void* RGFW_glContext_getSourceContext(RGFW_glContext* ctx);
 2407-
 2408-/**!
 2409- * @brief Makes the specified window the current OpenGL rendering target.
 2410- * @param win A pointer to the RGFW_window to make current.
 2411- *
 2412- * @note This is typically called internally by RGFW_window_makeCurrent.
 2413-*/
 2414-RGFWDEF void RGFW_window_makeCurrentWindow_OpenGL(RGFW_window* win);
 2415-
 2416-/**!
 2417- * @brief Makes the OpenGL context of the specified window current.
 2418- * @param win A pointer to the RGFW_window whose context should be made current.
 2419- *
 2420- * @note To move a context between threads, call RGFW_window_makeCurrentContext_OpenGL(NULL)
 2421- *       on the old thread before making it current on the new one.
 2422-*/
 2423-RGFWDEF void RGFW_window_makeCurrentContext_OpenGL(RGFW_window* win);
 2424-
 2425-/**!
 2426- * @brief Swaps the OpenGL buffers for the specified window.
 2427- * @param win A pointer to the RGFW_window whose buffers should be swapped.
 2428-*/
 2429-RGFWDEF void RGFW_window_swapBuffers_OpenGL(RGFW_window* win);
 2430-
 2431-/**!
 2432- * @brief Retrieves the current OpenGL context.
 2433- * @return A pointer to the currently active OpenGL context (GLX, WGL, Cocoa, or WebGL backend).
 2434-*/
 2435-RGFWDEF void* RGFW_getCurrentContext_OpenGL(void);
 2436-
 2437-/**!
 2438- * @brief Retrieves the current OpenGL window.
 2439- * @return A pointer to the RGFW_window currently bound as the OpenGL context target.
 2440-*/
 2441-RGFWDEF RGFW_window* RGFW_getCurrentWindow_OpenGL(void);
 2442-
 2443-/**!
 2444- * @brief Sets the OpenGL swap interval (vsync).
 2445- * @param win A pointer to the RGFW_window.
 2446- * @param swapInterval The desired swap interval value (0 to disable vsync, 1 to enable).
 2447-*/
 2448-RGFWDEF void RGFW_window_swapInterval_OpenGL(RGFW_window* win, i32 swapInterval);
 2449-
 2450-/**!
 2451- * @brief Retrieves the address of a native OpenGL procedure.
 2452- * @param procname The name of the OpenGL function to look up.
 2453- * @return A pointer to the function, or NULL if not found.
 2454-*/
 2455-RGFWDEF RGFW_proc RGFW_getProcAddress_OpenGL(const char* procname);
 2456-
 2457-/**!
 2458- * @brief Checks whether a specific OpenGL or OpenGL ES API extension is supported.
 2459- * @param extension The name of the extension to check.
 2460- * @param len The length of the extension string.
 2461- * @return RGFW_TRUE if supported, RGFW_FALSE otherwise.
 2462-*/
 2463-RGFWDEF RGFW_bool RGFW_extensionSupported_OpenGL(const char* extension, size_t len);
 2464-
 2465-/**!
 2466- * @brief Checks whether a specific platform-dependent OpenGL extension is supported.
 2467- * @param extension The name of the extension to check.
 2468- * @param len The length of the extension string.
 2469- * @return RGFW_TRUE if supported, RGFW_FALSE otherwise.
 2470-*/
 2471-RGFWDEF RGFW_bool RGFW_extensionSupportedPlatform_OpenGL(const char* extension, size_t len);
 2472-
 2473-/* these are EGL specific functions, they may fallback to OpenGL */
 2474-#ifdef RGFW_EGL
 2475-/**!
 2476- * @brief Creates and allocates an OpenGL/EGL context for the specified window.
 2477- * @param win A pointer to the target RGFW_window.
 2478- * @param hints A pointer to an RGFW_glHints structure defining context creation parameters.
 2479- * @return A pointer to the newly created RGFW_eglContext.
 2480-*/
 2481-RGFWDEF RGFW_eglContext* RGFW_window_createContext_EGL(RGFW_window* win, RGFW_glHints* hints);
 2482-
 2483-/**!
 2484- * @brief Creates an OpenGL/EGL context for the specified window using a preallocated context structure.
 2485- * @param win A pointer to the target RGFW_window.
 2486- * @param ctx A pointer to an already allocated RGFW_eglContext structure.
 2487- * @param hints A pointer to an RGFW_glHints structure defining context creation parameters.
 2488- * @return RGFW_TRUE on success, RGFW_FALSE on failure.
 2489-*/
 2490-RGFWDEF RGFW_bool RGFW_window_createContextPtr_EGL(RGFW_window* win, RGFW_eglContext* ctx, RGFW_glHints* hints);
 2491-
 2492-/**!
 2493- * @brief Frees and deletes an OpenGL/EGL context.
 2494- * @param win A pointer to the RGFW_window.
 2495- * @param ctx A pointer to the RGFW_eglContext to delete.
 2496- *
 2497- * @note Automatically called by RGFW_window_close if RGFW owns the context.
 2498-*/
 2499-RGFWDEF void RGFW_window_deleteContext_EGL(RGFW_window* win, RGFW_eglContext* ctx);
 2500-
 2501-/**!
 2502- * @brief Deletes an OpenGL/EGL context without freeing its memory.
 2503- * @param win A pointer to the RGFW_window.
 2504- * @param ctx A pointer to the RGFW_eglContext to delete.
 2505- *
 2506- * @note Automatically called by RGFW_window_close if RGFW owns the context.
 2507-*/
 2508-RGFWDEF void RGFW_window_deleteContextPtr_EGL(RGFW_window* win, RGFW_eglContext* ctx);
 2509-
 2510-/**!
 2511- * @brief Retrieves the OpenGL/EGL context associated with a window.
 2512- * @param win A pointer to the RGFW_window.
 2513- * @return A pointer to the associated RGFW_eglContext, or NULL if none exists or if the context is a native OpenGL context.
 2514-*/
 2515-RGFWDEF RGFW_eglContext* RGFW_window_getContext_EGL(RGFW_window* win);
 2516-
 2517-/**!
 2518- * @brief Retrieves the EGL display handle.
 2519- * @return A pointer to the native EGLDisplay.
 2520-*/
 2521-RGFWDEF void* RGFW_getDisplay_EGL(void);
 2522-
 2523-/**!
 2524- * @brief Retrieves the native source context from an RGFW_eglContext.
 2525- * @param ctx A pointer to the RGFW_eglContext.
 2526- * @return A pointer to the native EGLContext handle.
 2527-*/
 2528-RGFWDEF void* RGFW_eglContext_getSourceContext(RGFW_eglContext* ctx);
 2529-
 2530-/**!
 2531- * @brief Retrieves the EGL surface handle from an RGFW_eglContext.
 2532- * @param ctx A pointer to the RGFW_eglContext.
 2533- * @return A pointer to the EGLSurface associated with the context.
 2534-*/
 2535-RGFWDEF void* RGFW_eglContext_getSurface(RGFW_eglContext* ctx);
 2536-
 2537-/**!
 2538- * @brief Retrieves the Wayland EGL window handle from an RGFW_eglContext.
 2539- * @param ctx A pointer to the RGFW_eglContext.
 2540- * @return A pointer to the wl_egl_window associated with the EGL context.
 2541-*/
 2542-RGFWDEF struct wl_egl_window* RGFW_eglContext_wlEGLWindow(RGFW_eglContext* ctx);
 2543-
 2544-/**!
 2545- * @brief Swaps the EGL buffers for the specified window.
 2546- * @param win A pointer to the RGFW_window whose buffers should be swapped.
 2547- *
 2548- * @note Typically called by RGFW_window_swapInterval.
 2549-*/
 2550-RGFWDEF void RGFW_window_swapBuffers_EGL(RGFW_window* win);
 2551-
 2552-/**!
 2553- * @brief Makes the specified window the current EGL rendering target.
 2554- * @param win A pointer to the RGFW_window to make current.
 2555- *
 2556- * @note This is typically called internally by RGFW_window_makeCurrent.
 2557-*/
 2558-RGFWDEF void RGFW_window_makeCurrentWindow_EGL(RGFW_window* win);
 2559-
 2560-/**!
 2561- * @brief Makes the EGL context of the specified window current.
 2562- * @param win A pointer to the RGFW_window whose context should be made current.
 2563- *
 2564- * @note To move a context between threads, call RGFW_window_makeCurrentContext_EGL(NULL)
 2565- *       on the old thread before making it current on the new one.
 2566-*/
 2567-RGFWDEF void RGFW_window_makeCurrentContext_EGL(RGFW_window* win);
 2568-
 2569-/**!
 2570- * @brief Retrieves the current EGL context.
 2571- * @return A pointer to the currently active EGLContext.
 2572-*/
 2573-RGFWDEF void* RGFW_getCurrentContext_EGL(void);
 2574-
 2575-/**!
 2576- * @brief Retrieves the current EGL window.
 2577- * @return A pointer to the RGFW_window currently bound as the EGL context target.
 2578-*/
 2579-RGFWDEF RGFW_window* RGFW_getCurrentWindow_EGL(void);
 2580-
 2581-/**!
 2582- * @brief Sets the EGL swap interval (vsync).
 2583- * @param win A pointer to the RGFW_window.
 2584- * @param swapInterval The desired swap interval value (0 to disable vsync, 1 to enable).
 2585-*/
 2586-RGFWDEF void RGFW_window_swapInterval_EGL(RGFW_window* win, i32 swapInterval);
 2587-
 2588-/**!
 2589- * @brief Retrieves the address of a native OpenGL or OpenGL ES procedure in an EGL context.
 2590- * @param procname The name of the OpenGL function to look up.
 2591- * @return A pointer to the function, or NULL if not found.
 2592-*/
 2593-RGFWDEF RGFW_proc RGFW_getProcAddress_EGL(const char* procname);
 2594-
 2595-/**!
 2596- * @brief Checks whether a specific OpenGL or OpenGL ES API extension is supported in the current EGL context.
 2597- * @param extension The name of the extension to check.
 2598- * @param len The length of the extension string.
 2599- * @return RGFW_TRUE if supported, RGFW_FALSE otherwise.
 2600-*/
 2601-RGFWDEF RGFW_bool RGFW_extensionSupported_EGL(const char* extension, size_t len);
 2602-
 2603-/**!
 2604- * @brief Checks whether a specific platform-dependent EGL extension is supported in the current context.
 2605- * @param extension The name of the extension to check.
 2606- * @param len The length of the extension string.
 2607- * @return RGFW_TRUE if supported, RGFW_FALSE otherwise.
 2608-*/
 2609-RGFWDEF RGFW_bool RGFW_extensionSupportedPlatform_EGL(const char* extension, size_t len);
 2610-#endif
 2611-#endif
 2612-
 2613-#ifdef RGFW_VULKAN
 2614-#include <vulkan/vulkan.h>
 2615-
 2616-/* if you don't want to use the above macros */
 2617-
 2618-/**!
 2619- * @brief Retrieves the Vulkan instance extensions required by RGFW.
 2620- * @param count [OUTPUT] A pointer that will receive the number of required extensions (typically 2).
 2621- * @return A pointer to a static array of required Vulkan instance extension names.
 2622-*/
 2623-RGFWDEF const char** RGFW_getRequiredInstanceExtensions_Vulkan(size_t* count);
 2624-
 2625-/**!
 2626- * @brief Creates a Vulkan surface for the specified window.
 2627- * @param win A pointer to the RGFW_window for which to create the Vulkan surface.
 2628- * @param instance The Vulkan instance used to create the surface.
 2629- * @param surface [OUTPUT] A pointer to a VkSurfaceKHR handle that will receive the created surface.
 2630- * @return A VkResult indicating success or failure.
 2631-*/
 2632-RGFWDEF VkResult RGFW_window_createSurface_Vulkan(RGFW_window* win, VkInstance instance, VkSurfaceKHR* surface);
 2633-
 2634-/**!
 2635- * @brief Checks whether the specified Vulkan physical device and queue family support presentation for RGFW.
 2636- * @param instance The Vulkan instance.
 2637- * @param physicalDevice The Vulkan physical device to check.
 2638- * @param queueFamilyIndex The index of the queue family to query for presentation support.
 2639- * @return RGFW_TRUE if presentation is supported, RGFW_FALSE otherwise.
 2640-*/
 2641-RGFWDEF RGFW_bool RGFW_getPresentationSupport_Vulkan(VkPhysicalDevice physicalDevice, u32 queueFamilyIndex);
 2642-#endif
 2643-
 2644-#ifdef RGFW_DIRECTX
 2645-#ifndef RGFW_WINDOWS
 2646-	#undef RGFW_DIRECTX
 2647-#else
 2648-	#define OEMRESOURCE
 2649-	#include <dxgi.h>
 2650-
 2651-	#ifndef __cplusplus
 2652-		#define __uuidof(T) IID_##T
 2653-	#endif
 2654-/**!
 2655- * @brief Creates a DirectX swap chain for the specified RGFW window.
 2656- * @param win A pointer to the RGFW_window for which to create the swap chain.
 2657- * @param pFactory A pointer to the IDXGIFactory used to create the swap chain.
 2658- * @param pDevice A pointer to the DirectX device (e.g., ID3D11Device or ID3D12Device).
 2659- * @param swapchain [OUTPUT] A pointer to an IDXGISwapChain pointer that will receive the created swap chain.
 2660- * @return An integer result code (0 on success, or a DirectX error code on failure).
 2661-*/
 2662-RGFWDEF int RGFW_window_createSwapChain_DirectX(RGFW_window* win, IDXGIFactory* pFactory, IUnknown* pDevice, IDXGISwapChain** swapchain);
 2663-#endif
 2664-#endif
 2665-
 2666-#ifdef RGFW_WEBGPU
 2667-	#include <webgpu/webgpu.h>
 2668-	/**!
 2669-	 * @brief Creates a WebGPU surface for the specified RGFW window.
 2670-	 * @param window A pointer to the RGFW_window for which to create the surface.
 2671-	 * @param instance The WebGPU instance used to create the surface.
 2672-	 * @return The created WGPUSurface handle.
 2673-	*/
 2674-	RGFWDEF WGPUSurface RGFW_window_createSurface_WebGPU(RGFW_window* window, WGPUInstance instance);
 2675-#endif
 2676-
 2677-/** @} */
 2678-
 2679-/** * @defgroup Supporting
 2680-* @{ */
 2681-
 2682-/**!
 2683- * @brief Sets the root (main) RGFW window.
 2684- * @param win A pointer to the RGFW_window to set as the root window.
 2685-*/
 2686-RGFWDEF void RGFW_setRootWindow(RGFW_window* win);
 2687-
 2688-/**!
 2689- * @brief Retrieves the current root RGFW window.
 2690- * @return A pointer to the current root RGFW_window.
 2691-*/
 2692-RGFWDEF RGFW_window* RGFW_getRootWindow(void);
 2693-
 2694-/**!
 2695- * @brief Pushes an event into the standard RGFW event queue.
 2696- * @param event A pointer to the RGFW_event to be added to the queue.
 2697-*/
 2698-RGFWDEF void RGFW_eventQueuePush(const RGFW_event* event);
 2699-
 2700-/**!
 2701- * @brief Pushes an event into the standard RGFW event queue and call the callback.
 2702- * @param event A pointer to the RGFW_event to be added to the queue.
 2703-*/
 2704-RGFWDEF void RGFW_eventQueuePushAndCall(const RGFW_event* event);
 2705-
 2706-/**!
 2707- * @brief Clears all events from the RGFW event queue without processing them.
 2708-*/
 2709-RGFWDEF void RGFW_eventQueueFlush(void);
 2710-
 2711-/**!
 2712- * @brief Pops the next event from the RGFW event queue.
 2713- * @return A pointer to the popped RGFW_event, or NULL if the queue is empty.
 2714-*/
 2715-RGFWDEF RGFW_event* RGFW_eventQueuePop(void);
 2716-
 2717-/**!
 2718- * @brief Pops the next event from the RGFW event queue that matches the target window, pushes back events that don't matchj.
 2719- * @param win A pointer to the target RGFW_window.
 2720- * @return A pointer to the popped RGFW_event, or NULL if the queue is empty.
 2721-*/
 2722-RGFWDEF RGFW_event* RGFW_window_eventQueuePop(RGFW_window* win);
 2723-
 2724-/**!
 2725- * @brief Converts an API keycode to the RGFW unmapped (physical) key.
 2726- * @param keycode The platform-specific keycode.
 2727- * @return The corresponding RGFW keycode.
 2728-*/
 2729-RGFWDEF RGFW_key RGFW_apiKeyToRGFW(u32 keycode);
 2730-
 2731-/**!
 2732- * @brief Converts an RGFW keycode to the unmapped (physical) API key.
 2733- * @param keycode The RGFW keycode.
 2734- * @return The corresponding platform-specific keycode.
 2735-*/
 2736-RGFWDEF u32 RGFW_rgfwToApiKey(RGFW_key keycode);
 2737-
 2738-/**!
 2739- * @brief Converts an physical RGFW keycode to a mapped RGFW keycode.
 2740- * @param keycode the physical RGFW keycode.
 2741- * @return The corresponding mapped RGFW keycode.
 2742-*/
 2743-RGFWDEF RGFW_key RGFW_physicalToMappedKey(RGFW_key keycode);
 2744-
 2745-/**!
 2746- * @brief Retrieves the size of the RGFW_info structure.
 2747- * @return The size (in bytes) of RGFW_info.
 2748-*/
 2749-RGFWDEF size_t RGFW_sizeofInfo(void);
 2750-
 2751-/**!
 2752- * @brief Initializes the RGFW library internally.
 2753- * @return 0 on success, or a negative error code on failure.
 2754- * @note This is automatically called when the first window is created.
 2755-*/
 2756-RGFWDEF i32 RGFW_init(void);
 2757-
 2758-/**!
 2759- * @brief Deinitializes the current instance of the RGFW library.
 2760- * @note This is automatically called when the last open window is closed.
 2761-*/
 2762-RGFWDEF void RGFW_deinit(void);
 2763-
 2764-/**!
 2765- * @brief Initializes RGFW using a user-provided RGFW_info structure.
 2766- * @param info A pointer to an RGFW_info structure to be used for initialization.
 2767- * @return 0 on success, or a negative error code on failure.
 2768-*/
 2769-RGFWDEF i32 RGFW_init_ptr(RGFW_info* info);
 2770-
 2771-/**!
 2772- * @brief Deinitializes a specific RGFW instance stored in the provided RGFW_info pointer.
 2773- * @param info A pointer to the RGFW_info structure representing the instance to deinitialize.
 2774-*/
 2775-RGFWDEF void RGFW_deinit_ptr(RGFW_info* info);
 2776-
 2777-/**!
 2778- * @brief Sets the global RGFW_info structure pointer.
 2779- * @param info A pointer to the RGFW_info structure to set.
 2780-*/
 2781-RGFWDEF void RGFW_setInfo(RGFW_info* info);
 2782-
 2783-/**!
 2784- * @brief Retrieves the global RGFW_info structure pointer.
 2785- * @return A pointer to the current RGFW_info structure.
 2786-*/
 2787-RGFWDEF RGFW_info* RGFW_getInfo(void);
 2788-
 2789-/** @} */
 2790-#endif /* RGFW_HEADER */
 2791-
 2792-#if !defined(RGFW_NATIVE_HEADER) && (defined(RGFW_NATIVE) || defined(RGFW_IMPLEMENTATION))
 2793-#define RGFW_NATIVE_HEADER
 2794-	#if (defined(RGFW_OPENGL) || defined(RGFW_WEGL)) && defined(_MSC_VER)
 2795-		#pragma comment(lib, "opengl32")
 2796-	#endif
 2797-
 2798-	#ifdef RGFW_OPENGL
 2799-		struct RGFW_eglContext {
 2800-			void* ctx;
 2801-			void* surface;
 2802-			struct wl_egl_window* eglWindow;
 2803-		};
 2804-
 2805-		typedef union RGFW_gfxContext {
 2806-			RGFW_glContext* native;
 2807-			RGFW_eglContext* egl;
 2808-		} RGFW_gfxContext;
 2809-
 2810-		typedef RGFW_ENUM(u32, RGFW_gfxContextType) {
 2811-			RGFW_gfxNativeOpenGL = RGFW_BIT(0),
 2812-			RGFW_gfxEGL = RGFW_BIT(1),
 2813-			RGFW_gfxOwnedByRGFW = RGFW_BIT(2)
 2814-		};
 2815-	#endif
 2816-
 2817-	/*! source data for the window (used by the APIs) */
 2818-	#ifdef RGFW_WINDOWS
 2819-
 2820-	#ifndef WIN32_LEAN_AND_MEAN
 2821-		#define WIN32_LEAN_AND_MEAN
 2822-	#endif
 2823-	#ifndef OEMRESOURCE
 2824-		#define OEMRESOURCE
 2825-	#endif
 2826-
 2827-	#include <windows.h>
 2828-
 2829-	struct RGFW_nativeImage {
 2830-		HBITMAP bitmap;
 2831-		u8* bitmapBits;
 2832-		RGFW_format format;
 2833-		HDC hdcMem;
 2834-	};
 2835-
 2836-	#ifdef RGFW_OPENGL
 2837-		struct RGFW_glContext {    HGLRC ctx;	};
 2838-	#endif
 2839-
 2840-	struct RGFW_window_src {
 2841-		HWND window; /*!< source window */
 2842-		HDC hdc; /*!< source HDC */
 2843-		HICON hIconSmall, hIconBig; /*!< source window icons */
 2844-		i32 maxSizeW, maxSizeH, minSizeW, minSizeH, aspectRatioW, aspectRatioH; /*!< for setting max/min resize (RGFW_WINDOWS) */
 2845-		RGFW_bool actionFrame; /* frame after a caption button was toggled (e.g. minimize, maximize or close) */
 2846-		WCHAR highSurrogate;
 2847-		#ifdef RGFW_OPENGL
 2848-			RGFW_gfxContext ctx;
 2849-			RGFW_gfxContextType gfxType;
 2850-		#endif
 2851-	};
 2852-
 2853-#elif defined(RGFW_UNIX)
 2854-	#ifdef RGFW_X11
 2855-		#include <X11/Xlib.h>
 2856-		#include <X11/Xutil.h>
 2857-
 2858-		#include <X11/extensions/Xrandr.h>
 2859-		#include <X11/Xresource.h>
 2860-
 2861-		#ifndef RGFW_XDND_VERSION
 2862-			#define RGFW_XDND_VERSION 5
 2863-		#endif
 2864-	#endif
 2865-
 2866-	#ifdef RGFW_WAYLAND
 2867-		#ifdef RGFW_LIBDECOR
 2868-			#include <libdecor-0/libdecor.h>
 2869-		#endif
 2870-
 2871-		#include <wayland-client.h>
 2872-		#include <errno.h>
 2873-	#endif
 2874-
 2875-	struct RGFW_nativeImage {
 2876-		#ifdef RGFW_X11
 2877-			XImage* bitmap;
 2878-		#endif
 2879-		#ifdef RGFW_WAYLAND
 2880-			struct wl_buffer* wl_buffer;
 2881-			i32 fd;
 2882-			struct wl_shm_pool* pool;
 2883-		#endif
 2884-		u8* buffer;
 2885-		RGFW_format format;
 2886-	};
 2887-
 2888-	#ifdef RGFW_OPENGL
 2889-		struct RGFW_glContext {
 2890-			#ifdef RGFW_X11
 2891-				struct __GLXcontextRec* ctx; /*!< source graphics context */
 2892-				Window window;
 2893-			#endif
 2894-			#ifdef RGFW_WAYLAND
 2895-				RGFW_eglContext egl;
 2896-			#endif
 2897-		};
 2898-	#endif
 2899-
 2900-	struct RGFW_window_src {
 2901-		i32 x, y, w, h;
 2902-	#ifdef RGFW_OPENGL
 2903-		RGFW_gfxContext ctx;
 2904-		RGFW_gfxContextType gfxType;
 2905-	#endif
 2906-#ifdef RGFW_X11
 2907-		Window window; /*!< source window */
 2908-		Window parent; /*!< parent window */
 2909-		GC gc;
 2910-		XIC ic;
 2911-		u64 flashEnd;
 2912-		#ifdef RGFW_ADVANCED_SMOOTH_RESIZE
 2913-			i64 counter_value;
 2914-			XID counter;
 2915-		#endif
 2916-#endif /* RGFW_X11 */
 2917-
 2918-#if defined(RGFW_WAYLAND)
 2919-		struct wl_surface* surface;
 2920-		struct xdg_surface* xdg_surface;
 2921-		struct xdg_toplevel* xdg_toplevel;
 2922-		struct zxdg_toplevel_decoration_v1* decoration;
 2923-		struct zwp_locked_pointer_v1 *locked_pointer;
 2924-		struct xdg_toplevel_icon_v1 *icon;
 2925-		u32 decoration_mode;
 2926-		/* State flags to configure the window */
 2927-		RGFW_bool pending_activated;
 2928-		RGFW_bool activated;
 2929-		RGFW_bool resizing;
 2930-		RGFW_bool pending_maximized;
 2931-		RGFW_bool maximized;
 2932-		RGFW_bool minimized;
 2933-		RGFW_bool configured;
 2934-
 2935-		RGFW_bool using_custom_cursor;
 2936-		struct wl_surface* custom_cursor_surface;
 2937-
 2938-		RGFW_monitorNode* active_monitor;
 2939-
 2940-		struct wl_data_source *data_source; // offer data to other clients
 2941-
 2942-		#ifdef RGFW_LIBDECOR
 2943-			struct libdecor* decorContext;
 2944-		#endif
 2945-#endif /* RGFW_WAYLAND */
 2946-	};
 2947-
 2948-#elif defined(RGFW_MACOS)
 2949-	#include <CoreVideo/CoreVideo.h>
 2950-
 2951-	struct RGFW_nativeImage {
 2952-		RGFW_format format;
 2953-		u8* buffer;
 2954-		void* rep;
 2955-	};
 2956-
 2957-	#ifdef RGFW_OPENGL
 2958-		struct RGFW_glContext {
 2959-			void* ctx;
 2960-			void* format;
 2961-		};
 2962-	#endif
 2963-
 2964-	struct RGFW_window_src {
 2965-		void* window;
 2966-		void* view; /* apple viewpoint thingy */
 2967-		void* mouse;
 2968-		void* delegate;
 2969-		#ifdef RGFW_OPENGL
 2970-			RGFW_gfxContext ctx;
 2971-			RGFW_gfxContextType gfxType;
 2972-		#endif
 2973-	};
 2974-
 2975-#elif defined(RGFW_WASM)
 2976-
 2977-	#include <emscripten/html5.h>
 2978-	#include <emscripten/key_codes.h>
 2979-
 2980-	struct RGFW_nativeImage  {
 2981-		RGFW_format format;
 2982-	};
 2983-
 2984-	#ifdef RGFW_OPENGL
 2985-		struct RGFW_glContext {
 2986-			EMSCRIPTEN_WEBGL_CONTEXT_HANDLE ctx;
 2987-		};
 2988-	#endif
 2989-
 2990-	struct RGFW_window_src {
 2991-		#ifdef RGFW_OPENGL
 2992-			RGFW_gfxContext ctx;
 2993-			RGFW_gfxContextType gfxType;
 2994-		#endif
 2995-	};
 2996-
 2997-#endif
 2998-
 2999-struct RGFW_surface {
 3000-	u8* data;
 3001-	i32 w, h;
 3002-	RGFW_format format;
 3003-	RGFW_convertImageDataFunc convertFunc;
 3004-	RGFW_nativeImage native;
 3005-};
 3006-
 3007-/*! internal window data that is not specific to the OS */
 3008-typedef struct RGFW_windowInternal {
 3009-	/*! which key RGFW_window_shouldClose checks. Settting this to RGFW_keyNULL disables the feature. */
 3010-	RGFW_key exitKey;
 3011-	i32 lastMouseX, lastMouseY; /*!< last cusor point (for raw mouse data) */
 3012-
 3013-	RGFW_bool shouldClose;
 3014-	RGFW_bool rawMouse;
 3015-	RGFW_bool captureMouse;
 3016-	RGFW_bool inFocus;
 3017-	RGFW_bool mouseInside;
 3018-	RGFW_keymod mod;
 3019-	RGFW_eventFlag enabledEvents;
 3020-	u32 flags; /*!< windows flags (for RGFW to check and modify) */
 3021-	i32 oldX, oldY, oldW, oldH;
 3022-	RGFW_monitorMode oldMode;
 3023-	RGFW_mouse* mouse;
 3024-} RGFW_windowInternal;
 3025-
 3026-struct RGFW_window {
 3027-	RGFW_window_src src; /*!< src window data */
 3028-	RGFW_windowInternal internal; /*!< internal window data that is not specific to the OS */
 3029-	void* userPtr; /* ptr for user data */
 3030-	i32 x, y, w, h; /*!< position and size of the window */
 3031-}; /*!< window structure for the window */
 3032-
 3033-typedef struct RGFW_windowState {
 3034-	RGFW_bool mouseEnter;
 3035-	RGFW_bool dataDragging;
 3036-	RGFW_bool dataDrop;
 3037-	size_t dataSize;
 3038-	i32 dropX, dropY;
 3039-	RGFW_window* win; /*!< it's not possible for one of these events to happen in the frame that the other event happened */
 3040-
 3041-	RGFW_bool mouseLeave;
 3042-	RGFW_window* winLeave; /*!< if a mouse leaves one window and enters the next */
 3043-} RGFW_windowState;
 3044-
 3045-typedef struct {
 3046-	RGFW_bool current;
 3047-	RGFW_bool prev;
 3048-} RGFW_keyState;
 3049-
 3050-struct RGFW_monitorNode {
 3051-	RGFW_monitor mon;
 3052-	RGFW_bool disconnected;
 3053-	RGFW_monitorNode* next;
 3054-#ifdef RGFW_WAYLAND
 3055-	u32 id; /* Add id so wl_outputs can be removed */
 3056-	struct wl_output *output;
 3057-	struct zxdg_output_v1 *xdg_output;
 3058-	RGFW_monitorMode* modes;
 3059-	size_t modeCount;
 3060-#endif
 3061-#if defined(RGFW_X11)
 3062-	i32 screen;
 3063-	RROutput rrOutput;
 3064-	RRCrtc crtc;
 3065-#endif
 3066-#ifdef RGFW_WINDOWS
 3067-	HMONITOR hMonitor;
 3068-	WCHAR adapterName[32];
 3069-	WCHAR deviceName[32];
 3070-#endif
 3071-#ifdef RGFW_MACOS
 3072-	void* screen;
 3073-	CGDirectDisplayID display;
 3074-	u32 uintNum;
 3075-#endif
 3076-};
 3077-
 3078-typedef struct RGFW_monitorList {
 3079-	RGFW_monitorNode* head;
 3080-	RGFW_monitorNode* cur;
 3081-} RGFW_monitorList;
 3082-
 3083-typedef struct RGFW_monitors {
 3084-	RGFW_monitorList list;
 3085-	size_t count;
 3086-
 3087-	RGFW_monitorNode* primary;
 3088-	#if (RGFW_PREALLOCATED_MONITORS)
 3089-		RGFW_monitorList freeList;
 3090-		RGFW_monitorNode data[RGFW_PREALLOCATED_MONITORS];
 3091-	#endif
 3092-} RGFW_monitors;
 3093-
 3094-RGFWDEF RGFW_monitorNode* RGFW_monitors_add(const RGFW_monitor* mon);
 3095-RGFWDEF void RGFW_monitors_remove(RGFW_monitorNode* node, RGFW_monitorNode* prev);
 3096-
 3097-struct RGFW_info {
 3098-    RGFW_window* root;
 3099-    i32 windowCount;
 3100-
 3101-	RGFW_mouse* hiddenMouse;
 3102-	RGFW_mouse* standardMice[RGFW_mouseIconCount];
 3103-
 3104-	RGFW_debugFunc debugCallbackSrc;
 3105-	RGFW_genericFunc callbacks[RGFW_eventCount];
 3106-    RGFW_event events[RGFW_MAX_EVENTS]; /* A circular buffer (FIFO), using eventBottom/Len  */
 3107-
 3108-	i32 eventBottom;
 3109-    i32 eventLen;
 3110-	RGFW_bool queueEvents;
 3111-	RGFW_bool polledEvents;
 3112-
 3113-    u32 apiKeycodes[RGFW_keyLast];
 3114-	#if defined(RGFW_X11) || defined(RGFW_WAYLAND)
 3115-		RGFW_key keycodes[256];
 3116-	#elif defined(RGFW_WINDOWS)
 3117-		RGFW_key keycodes[512];
 3118-	#elif defined(RGFW_MACOS)
 3119-		RGFW_key keycodes[128];
 3120-	#elif defined(RGFW_WASM)
 3121-		RGFW_key keycodes[256];
 3122-	#endif
 3123-
 3124-    const char* className;
 3125-    RGFW_bool useWaylandBool;
 3126-    RGFW_bool stopCheckEvents_bool ;
 3127-    u64 timerOffset;
 3128-
 3129-    char* clipboard_data;
 3130-    char* clipboard; /* for writing to the clipboard selection */
 3131-    size_t clipboard_len;
 3132-
 3133-	RGFW_bool dndBuild;
 3134-	RGFW_dataDropNode* dndRoot;
 3135-	RGFW_dataDropNode* dndCur;
 3136-
 3137-	#ifdef RGFW_X11
 3138-        Display* display;
 3139-		XContext context;
 3140-        Window helperWindow;
 3141-        const char* instName;
 3142-        XErrorEvent* x11Error;
 3143-		i32 xrandrEventBase;
 3144-		XIM im;
 3145-		Window x11Source;
 3146-		long x11Version;
 3147-		i32 x11Format;
 3148-		RGFW_dataTransferType x11TransferType;
 3149-    #endif
 3150-    #ifdef RGFW_WAYLAND
 3151-        struct wl_display* wl_display;
 3152-        struct xkb_context *xkb_context;
 3153-        struct xkb_keymap *keymap;
 3154-        struct xkb_state *xkb_state;
 3155-        struct zxdg_decoration_manager_v1 *decoration_manager;
 3156-        struct zwp_relative_pointer_manager_v1 *relative_pointer_manager;
 3157-        struct zwp_relative_pointer_v1 *relative_pointer;
 3158-        struct zwp_pointer_constraints_v1 *constraint_manager;
 3159-        struct xdg_toplevel_icon_manager_v1 *icon_manager;
 3160-
 3161-        struct zxdg_output_manager_v1 *xdg_output_manager;
 3162-
 3163-        struct wl_data_device_manager *data_device_manager;
 3164-        struct wl_data_device *data_device; // supports clipboard and DND
 3165-		struct wp_pointer_warp_v1* wp_pointer_warp;
 3166-
 3167-        struct wl_keyboard* wl_keyboard;
 3168-        struct wl_pointer* wl_pointer;
 3169-        struct wl_compositor* compositor;
 3170-        struct xdg_wm_base* xdg_wm_base;
 3171-        struct wl_shm* shm;
 3172-        struct wl_seat *seat;
 3173-        struct wl_registry *registry;
 3174-        u32 mouse_enter_serial;
 3175-        struct wl_cursor_theme* wl_cursor_theme;
 3176-        struct wl_surface* cursor_surface;
 3177-		struct xkb_compose_state* composeState;
 3178-
 3179-        RGFW_window* kbOwner;
 3180-		RGFW_window* mouseOwner; /* what window has access to the mouse */
 3181-
 3182-		u32 last_key;  /* wayland key repeat data */
 3183-		i32 wl_repeat_info_rate, wl_repeat_info_delay;
 3184-		u32 last_key_time;
 3185-    #endif
 3186-
 3187-    RGFW_monitors monitors;
 3188-
 3189-    #ifdef RGFW_UNIX
 3190-	    int eventWait_forceStop[3];
 3191-		i32 clock;
 3192-    #endif
 3193-
 3194-    #ifdef RGFW_MACOS
 3195-    void* NSApp;
 3196-	i64 flash;
 3197-	void* customViewClasses[2]; /* NSView and NSOpenGLView  */
 3198-	void* customNSAppDelegateClass;
 3199-	void* customWindowDelegateClass;
 3200-	void* customNSAppDelegate;
 3201-	void* tisBundle;
 3202-    #endif
 3203-
 3204-	#ifdef RGFW_OPENGL
 3205-		RGFW_window* current;
 3206-	#endif
 3207-	#ifdef RGFW_EGL
 3208-		void* EGL_display;
 3209-	#endif
 3210-
 3211-	RGFW_bool rawMouse; /* global raw mouse toggle */
 3212-
 3213-	RGFW_windowState windowState; /*! for checking window state events */
 3214-
 3215-	RGFW_keyState mouseButtons[RGFW_mouseFinal];
 3216-	RGFW_keyState keyboard[RGFW_keyLast];
 3217-	float scrollX, scrollY;
 3218-	float vectorX, vectorY;
 3219-};
 3220-#endif /* RGFW_NATIVE_HEADER */
 3221-
 3222-#ifdef RGFW_IMPLEMENTATION
 3223-
 3224-#ifndef RGFW_NO_MATH
 3225-#include <math.h>
 3226-#endif
 3227-
 3228-/* global private API */
 3229-
 3230-/* for C++ / C89 */
 3231-RGFWDEF RGFW_window* RGFW_createWindowPlatform(const char* name, RGFW_windowFlags flags, RGFW_window* win);
 3232-RGFWDEF void RGFW_window_closePlatform(RGFW_window* win);
 3233-RGFWDEF RGFW_bool RGFW_window_setMousePlatform(RGFW_window* win, RGFW_mouse* mouse);
 3234-
 3235-RGFWDEF void RGFW_window_setFlagsInternal(RGFW_window* win, RGFW_windowFlags flags, RGFW_windowFlags cmpFlags);
 3236-
 3237-RGFWDEF void RGFW_initKeycodes(void);
 3238-RGFWDEF void RGFW_initKeycodesPlatform(void);
 3239-RGFWDEF void RGFW_resetPrevState(void);
 3240-RGFWDEF void RGFW_resetKey(void);
 3241-RGFWDEF void RGFW_unloadEGL(void);
 3242-RGFWDEF void RGFW_keyUpdateKeyModsEx(RGFW_window* win, RGFW_bool capital, RGFW_bool numlock, RGFW_bool control, RGFW_bool alt, RGFW_bool shift, RGFW_bool super, RGFW_bool scroll);
 3243-RGFWDEF void RGFW_keyUpdateKeyMods(RGFW_window* win, RGFW_bool capital, RGFW_bool numlock, RGFW_bool scroll);
 3244-RGFWDEF void RGFW_window_showMouseFlags(RGFW_window* win, RGFW_bool show);
 3245-RGFWDEF void RGFW_keyUpdateKeyMod(RGFW_window* win, RGFW_keymod mod, RGFW_bool value);
 3246-RGFWDEF void RGFW_monitors_refresh(void);
 3247-
 3248-RGFWDEF void RGFW_windowMaximizedCallback(RGFW_window* win, i32 x, i32 y, i32 w, i32 h);
 3249-RGFWDEF void RGFW_windowMinimizedCallback(RGFW_window* win);
 3250-RGFWDEF void RGFW_windowRestoredCallback(RGFW_window* win, i32 x, i32 y, i32 w, i32 h);
 3251-RGFWDEF void RGFW_windowMovedCallback(RGFW_window* win, i32 x, i32 y);
 3252-RGFWDEF void RGFW_windowResizedCallback(RGFW_window* win, i32 w, i32 h);
 3253-RGFWDEF void RGFW_windowCloseCallback(RGFW_window* win);
 3254-RGFWDEF void RGFW_mousePosCallback(RGFW_window* win, i32 x, i32 y);
 3255-RGFWDEF void RGFW_rawMotionCallback(RGFW_window* win, float x, float y);
 3256-RGFWDEF void RGFW_windowRefreshCallback(RGFW_window* win, i32 x, i32 y, i32 w, i32 h);
 3257-RGFWDEF void RGFW_windowFocusCallback(RGFW_window* win, RGFW_bool inFocus);
 3258-RGFWDEF void RGFW_mouseNotifyCallback(RGFW_window* win, i32 x, i32 y, RGFW_bool status);
 3259-RGFWDEF void RGFW_dataDropCallback(RGFW_window* win, const char* data, size_t count, RGFW_dataTransferType dataType);
 3260-RGFWDEF void RGFW_dataDragCallback(RGFW_window* win, RGFW_dataTransferType dataType, RGFW_dndActionType action, i32 x, i32 y);
 3261-RGFWDEF void RGFW_keyCharCallback(RGFW_window* win, u32 codepoint);
 3262-RGFWDEF void RGFW_keyCallback(RGFW_window* win, RGFW_key key, RGFW_keymod mod, RGFW_bool repeat, RGFW_bool press);
 3263-RGFWDEF void RGFW_mouseButtonCallback(RGFW_window* win, RGFW_mouseButton button, RGFW_bool press);
 3264-RGFWDEF void RGFW_mouseScrollCallback(RGFW_window* win, float x, float y);
 3265-RGFWDEF void RGFW_scaleUpdatedCallback(RGFW_window* win, float scaleX, float scaleY);
 3266-RGFWDEF void RGFW_monitorCallback(RGFW_window* win, const RGFW_monitor* monitor, RGFW_bool connected);
 3267-
 3268-RGFWDEF void RGFW_setBit(u32* var, u32 mask, RGFW_bool set);
 3269-RGFWDEF void RGFW_splitBPP(u32 bpp, RGFW_monitorMode* mode);
 3270-
 3271-RGFWDEF void RGFW_window_captureMousePlatform(RGFW_window* win, RGFW_bool state);
 3272-RGFWDEF void RGFW_window_setRawMouseModePlatform(RGFW_window *win, RGFW_bool state);
 3273-
 3274-RGFWDEF void RGFW_copyImageData64(u8* dest_data, i32 w, i32 h, RGFW_format dest_format,
 3275-							u8* src_data, RGFW_format src_format, RGFW_bool is64bit, RGFW_convertImageDataFunc func);
 3276-
 3277-RGFWDEF RGFW_bool RGFW_loadEGL(void);
 3278-
 3279-#ifdef RGFW_OPENGL
 3280-typedef struct RGFW_attribStack {
 3281-	i32* attribs;
 3282-	size_t count;
 3283-	size_t max;
 3284-} RGFW_attribStack;
 3285-RGFWDEF void RGFW_attribStack_init(RGFW_attribStack* stack, i32* attribs, size_t max);
 3286-RGFWDEF void RGFW_attribStack_pushAttrib(RGFW_attribStack* stack, i32 attrib);
 3287-RGFWDEF void RGFW_attribStack_pushAttribs(RGFW_attribStack* stack, i32 attrib1, i32 attrib2);
 3288-
 3289-RGFWDEF RGFW_bool RGFW_extensionSupportedStr(const char* extensions, const char* ext, size_t len);
 3290-#endif
 3291-
 3292-#ifdef RGFW_X11
 3293-RGFWDEF void RGFW_XCreateWindow (XVisualInfo visual, const char* name, RGFW_windowFlags flags, RGFW_window* win);
 3294-#endif
 3295-#ifdef RGFW_MACOS
 3296-RGFWDEF void RGFW_osx_initView(RGFW_window* win);
 3297-#endif
 3298-/* end of global private API defs */
 3299-
 3300-RGFW_info* _RGFW = NULL;
 3301-void RGFW_setInfo(RGFW_info* info) { _RGFW = info; }
 3302-RGFW_info* RGFW_getInfo(void) { return _RGFW; }
 3303-
 3304-
 3305-void* RGFW_alloc(size_t size) { return RGFW_ALLOC(size); }
 3306-void RGFW_free(void* ptr) { RGFW_FREE(ptr); }
 3307-
 3308-void RGFW_useWayland(RGFW_bool wayland) { RGFW_init(); _RGFW->useWaylandBool = RGFW_BOOL(wayland);  }
 3309-RGFW_bool RGFW_usingWayland(void) { return _RGFW->useWaylandBool; }
 3310-
 3311-void RGFW_setRawMouseMode(RGFW_bool state) {
 3312-	_RGFW->rawMouse = state;
 3313-	RGFW_window_setRawMouseModePlatform(_RGFW->root, state);
 3314-}
 3315-
 3316-void RGFW_clipboard_switch(char* newstr);
 3317-void RGFW_clipboard_switch(char* newstr) {
 3318-	if (_RGFW->clipboard_data != NULL)
 3319-		RGFW_FREE(_RGFW->clipboard_data);
 3320-	_RGFW->clipboard_data =  newstr;
 3321-}
 3322-
 3323-#define RGFW_CHECK_CLIPBOARD() \
 3324-	if (size <= 0 && _RGFW->clipboard_data != NULL) \
 3325-		return (const char*)_RGFW->clipboard_data; \
 3326-	else if (size <= 0) \
 3327-		return "\0";
 3328-
 3329-const char* RGFW_readClipboard(size_t* len) {
 3330-	RGFW_ssize_t size = RGFW_readClipboardPtr(NULL, 0);
 3331-    RGFW_CHECK_CLIPBOARD();
 3332-    char* str = (char*)RGFW_ALLOC((size_t)size);
 3333-    RGFW_ASSERT(str != NULL);
 3334-    str[0] = '\0';
 3335-
 3336-    size = RGFW_readClipboardPtr(str, (size_t)size);
 3337-
 3338-    RGFW_CHECK_CLIPBOARD();
 3339-
 3340-	if (len != NULL) *len = (size_t)size;
 3341-
 3342-	RGFW_clipboard_switch(str);
 3343-	return (const char*)str;
 3344-}
 3345-
 3346-/* generic RGFW defines */
 3347-
 3348-void RGFW_initKeycodes(void) {
 3349-	RGFW_MEMZERO(_RGFW->keycodes, sizeof(_RGFW->keycodes));
 3350-	RGFW_initKeycodesPlatform();
 3351-	size_t i, y;
 3352-    for (i = 0; i < RGFW_keyLast; i++) {
 3353-        for (y = 0; y < (sizeof(_RGFW->keycodes) / sizeof(RGFW_key)); y++) {
 3354-            if (_RGFW->keycodes[y] == i) {
 3355-                _RGFW->apiKeycodes[i] = (RGFW_key)y;
 3356-                break;
 3357-            }
 3358-        }
 3359-    }
 3360-
 3361-
 3362-    RGFW_resetKey();
 3363-}
 3364-
 3365-RGFW_key RGFW_apiKeyToRGFW(u32 keycode) {
 3366-    /* make sure the key isn't out of bounds */
 3367-	if (keycode > (sizeof(_RGFW->keycodes) / sizeof(RGFW_key)))
 3368-		return 0;
 3369-
 3370-	return _RGFW->keycodes[keycode];
 3371-}
 3372-
 3373-u32 RGFW_rgfwToApiKey(RGFW_key keycode) {
 3374-	/* make sure the key isn't out of bounds */
 3375-	return _RGFW->apiKeycodes[keycode];
 3376-}
 3377-
 3378-void RGFW_resetKey(void) { RGFW_MEMZERO(_RGFW->keyboard, sizeof(_RGFW->keyboard)); }
 3379-/*
 3380-	this is the end of keycode data
 3381-*/
 3382-
 3383-RGFW_genericFunc RGFW_setEventCallback(RGFW_eventType type, RGFW_genericFunc func) {
 3384-	RGFW_ASSERT(type > RGFW_eventNone && type < RGFW_eventCount);
 3385-	RGFW_init();
 3386-
 3387-	RGFW_genericFunc old = _RGFW->callbacks[type];
 3388-	_RGFW->callbacks[type] = func;
 3389-
 3390-	return old;
 3391-}
 3392-
 3393-void RGFW_setDualEventCallback(RGFW_eventType type, RGFW_genericFunc func, RGFW_genericFunc* first, RGFW_genericFunc* second) {
 3394-	RGFW_genericFunc func1 = RGFW_setEventCallback(type, func);
 3395-	RGFW_genericFunc func2 = RGFW_setEventCallback(type + 1, func);
 3396-
 3397-	if (first) *first = func1;
 3398-	if (second) *second = func2;
 3399-}
 3400-
 3401-void RGFW_setAllEventCallbacks(RGFW_genericFunc func, RGFW_callbacks* callbacks) {
 3402-	for (RGFW_eventType i = RGFW_eventNone + 1; i < RGFW_eventCount; i++) {
 3403-		if (callbacks) callbacks->arr[i] = _RGFW->callbacks[i];
 3404-		RGFW_setEventCallback(i, func);
 3405-	}
 3406-}
 3407-
 3408-RGFW_debugFunc RGFW_setDebugCallback(RGFW_debugFunc func) {
 3409-	RGFW_init();
 3410-	RGFW_debugFunc prev = _RGFW->debugCallbackSrc;
 3411-	_RGFW->debugCallbackSrc = func;
 3412-	return prev;
 3413-}
 3414-
 3415-void RGFW_eventQueuePushAndCall(const RGFW_event* event) {
 3416-	RGFW_ASSERT(event->type > RGFW_eventNone && event->type < RGFW_eventCount);
 3417-	if (_RGFW->callbacks[event->type]) (_RGFW->callbacks[event->type])(event);
 3418-	RGFW_eventQueuePush(event);
 3419-}
 3420-
 3421-void RGFW_windowMaximizedCallback(RGFW_window* win, i32 x, i32 y, i32 w, i32 h) {
 3422-	win->internal.flags |= RGFW_windowMaximize;
 3423-	win->x = x;
 3424-	win->y = y;
 3425-	win->w = w;
 3426-	win->h = h;
 3427-
 3428-	if (!(win->internal.enabledEvents & RGFW_windowMaximizedFlag)) return;
 3429-
 3430-	RGFW_event event;
 3431-	event.type = RGFW_windowMaximized;
 3432-	event.update.x = x;
 3433-	event.update.y = y;
 3434-	event.update.w = w;
 3435-	event.update.h = h;
 3436-	event.common.win = win;
 3437-	RGFW_eventQueuePushAndCall(&event);
 3438-}
 3439-
 3440-void RGFW_windowMinimizedCallback(RGFW_window* win) {
 3441-	win->internal.flags |= RGFW_windowMinimize;
 3442-
 3443-	if (!(win->internal.enabledEvents & RGFW_windowMinimizedFlag)) return;
 3444-
 3445-	RGFW_event event;
 3446-	event.type = RGFW_windowMinimized;
 3447-	event.update.x = win->x;
 3448-	event.update.y = win->y;
 3449-	event.update.w = win->w;
 3450-	event.update.h = win->h;
 3451-	event.common.win = win;
 3452-	RGFW_eventQueuePushAndCall(&event);
 3453-}
 3454-
 3455-void RGFW_windowRestoredCallback(RGFW_window* win, i32 x, i32 y, i32 w, i32 h) {
 3456-	win->internal.flags &= ~(u32)RGFW_windowMinimize;
 3457-	win->x = x;
 3458-	win->y = y;
 3459-	win->w = w;
 3460-	win->h = h;
 3461-
 3462-	if (RGFW_window_isMaximized(win) == RGFW_FALSE) win->internal.flags &= ~(u32)RGFW_windowMaximize;
 3463-
 3464-	if (!(win->internal.enabledEvents & RGFW_windowRestoredFlag)) return;
 3465-
 3466-	RGFW_event event;
 3467-	event.type = RGFW_windowRestored;
 3468-	event.update.x = x;
 3469-	event.update.y = y;
 3470-	event.update.w = w;
 3471-	event.update.h = h;
 3472-	event.common.win = win;
 3473-	RGFW_eventQueuePushAndCall(&event);
 3474-}
 3475-
 3476-void RGFW_windowMovedCallback(RGFW_window* win, i32 x, i32 y) {
 3477-	win->x = x;
 3478-	win->y = y;
 3479-	if (!(win->internal.enabledEvents & RGFW_windowMovedFlag)) return;
 3480-
 3481-	RGFW_event event;
 3482-	event.type = RGFW_windowMoved;
 3483-	event.update.x = x;
 3484-	event.update.x = y;
 3485-	event.update.w = win->w;
 3486-	event.update.h = win->h;
 3487-	event.common.win = win;
 3488-	RGFW_eventQueuePushAndCall(&event);
 3489-}
 3490-
 3491-void RGFW_windowResizedCallback(RGFW_window* win, i32 w, i32 h) {
 3492-	win->w = w;
 3493-	win->h = h;
 3494-
 3495-	if (!(win->internal.enabledEvents & RGFW_windowResizedFlag)) return;
 3496-	RGFW_event event;
 3497-	event.type = RGFW_windowResized;
 3498-	event.update.x = win->x;
 3499-	event.update.y = win->y;
 3500-	event.update.w = w;
 3501-	event.update.h = h;
 3502-	event.common.win = win;
 3503-	RGFW_eventQueuePushAndCall(&event);
 3504-}
 3505-
 3506-void RGFW_windowCloseCallback(RGFW_window* win) {
 3507-	win->internal.shouldClose = RGFW_TRUE;
 3508-
 3509-	RGFW_event event;
 3510-	event.type = RGFW_windowClose;
 3511-	event.common.win = win;
 3512-	RGFW_eventQueuePushAndCall(&event);
 3513-}
 3514-
 3515-void RGFW_mousePosCallback(RGFW_window* win, i32 x, i32 y) {
 3516-	win->internal.lastMouseX = x;
 3517-	win->internal.lastMouseY = y;
 3518-
 3519-	if (!(win->internal.enabledEvents & RGFW_mousePosChangedFlag)) return;
 3520-
 3521-	RGFW_event event;
 3522-	event.type = RGFW_mousePosChanged;
 3523-	event.mouse.x = x;
 3524-	event.mouse.y = y;
 3525-	event.mouse.inWindow = win->internal.mouseInside;
 3526-	event.common.win = win;
 3527-	RGFW_eventQueuePushAndCall(&event);
 3528-}
 3529-
 3530-void RGFW_rawMotionCallback(RGFW_window* win, float x, float y) {
 3531-	_RGFW->vectorX = x;
 3532-	_RGFW->vectorY = y;
 3533-	if (!(win->internal.enabledEvents & RGFW_mouseRawMotionFlag)) return;
 3534-
 3535-	RGFW_event event;
 3536-	event.type = RGFW_mouseRawMotion;
 3537-	event.delta.x = x;
 3538-	event.delta.y = y;
 3539-	event.common.win = win;
 3540-	RGFW_eventQueuePushAndCall(&event);
 3541-}
 3542-
 3543-void RGFW_windowRefreshCallback(RGFW_window* win, i32 x, i32 y, i32 w, i32 h) {
 3544-	if (!(win->internal.enabledEvents & RGFW_windowRefreshFlag)) return;
 3545-	RGFW_event event;
 3546-	event.type = RGFW_windowRefresh;
 3547-	event.update.x = x;
 3548-	event.update.y = y;
 3549-	event.update.w = w;
 3550-	event.update.h = h;
 3551-	event.common.win = win;
 3552-	RGFW_eventQueuePushAndCall(&event);
 3553-}
 3554-
 3555-void RGFW_windowFocusCallback(RGFW_window* win, RGFW_bool inFocus) {
 3556-	win->internal.inFocus = inFocus;
 3557-
 3558-	if (win->internal.captureMouse) {
 3559-		RGFW_window_captureMousePlatform(win, inFocus);
 3560-	}
 3561-
 3562-	RGFW_event event;
 3563-	event.common.win = win;
 3564-	event.focus.state = inFocus;
 3565-
 3566-	if (inFocus == RGFW_TRUE) {
 3567-		if ((win->internal.flags & RGFW_windowFullscreen))
 3568-			RGFW_window_raise(win);
 3569-
 3570-		event.type = RGFW_windowFocusIn;
 3571-	} else if (inFocus == RGFW_FALSE) {
 3572-		if ((win->internal.flags & RGFW_windowFullscreen))
 3573-			RGFW_window_minimize(win);
 3574-
 3575-		size_t key;
 3576-		for (key = 0; key < RGFW_keyLast; key++) {
 3577-			if (RGFW_isKeyDown((u8)key) == RGFW_FALSE) continue;
 3578-
 3579-			_RGFW->keyboard[key].current = RGFW_FALSE;
 3580-			if ((win->internal.enabledEvents & RGFW_BIT(RGFW_keyReleased))) {
 3581-				RGFW_keyCallback(win, (u8)key, win->internal.mod, RGFW_FALSE, RGFW_FALSE);
 3582-			}
 3583-		}
 3584-
 3585-		RGFW_resetKey();
 3586-		event.type = RGFW_windowFocusOut;
 3587-	}
 3588-
 3589-	event.common.win = win;
 3590-
 3591-	RGFW_eventQueuePushAndCall(&event);
 3592-}
 3593-
 3594-void RGFW_mouseNotifyCallback(RGFW_window* win, i32 x, i32 y, RGFW_bool status) {
 3595-	win->internal.mouseInside = status;
 3596-	_RGFW->windowState.win = win;
 3597-
 3598-	win->internal.lastMouseX = x;
 3599-	win->internal.lastMouseY = y;
 3600-
 3601-	RGFW_event event;
 3602-	event.common.win = win;
 3603-	event.mouse.x = x;
 3604-	event.mouse.y = y;
 3605-	event.mouse.inWindow = win->internal.mouseInside;
 3606-
 3607-	if (status) {
 3608-		if (!(win->internal.enabledEvents & RGFW_mouseEnterFlag)) return;
 3609-		_RGFW->windowState.mouseEnter =  RGFW_TRUE;
 3610-		_RGFW->windowState.win = win;
 3611-		event.type = RGFW_mouseEnter;
 3612-	} else {
 3613-		if (!(win->internal.enabledEvents & RGFW_mouseLeaveFlag)) return;
 3614-		_RGFW->windowState.winLeave = win;
 3615-		_RGFW->windowState.mouseLeave =  RGFW_TRUE;
 3616-		event.type = RGFW_mouseLeave;
 3617-	}
 3618-
 3619-	RGFW_eventQueuePushAndCall(&event);
 3620-}
 3621-
 3622-void RGFW_dataDropCallback(RGFW_window* win, const char* data, size_t size, RGFW_dataTransferType dataType) {
 3623-	if (!(win->internal.enabledEvents & RGFW_dataDropFlag) || !(win->internal.flags & RGFW_windowAllowDND))
 3624-		return;
 3625-
 3626-	_RGFW->windowState.win = win;
 3627-	_RGFW->windowState.dataDrop = RGFW_TRUE;
 3628-	_RGFW->windowState.dataSize = size;
 3629-
 3630-	RGFW_dataDropNode node;
 3631-	RGFW_MEMZERO(&node, sizeof(node));
 3632-	node.data = data;
 3633-	node.size = size;
 3634-	node.type = dataType;
 3635-	node.next = NULL;
 3636-
 3637-	RGFW_event event;
 3638-	event.type = RGFW_dataDrop;
 3639-	event.drop.value = &node;
 3640-	event.drop.win = win;
 3641-
 3642-	if (_RGFW->callbacks[event.type]) (_RGFW->callbacks[event.type])(&event);
 3643-
 3644-	if (_RGFW->queueEvents == RGFW_TRUE || _RGFW->dndBuild) {
 3645-		if (_RGFW->dndRoot == NULL) {
 3646-			_RGFW->dndRoot = (RGFW_dataDropNode*)RGFW_ALLOC(sizeof(RGFW_dataDropNode));
 3647-			_RGFW->dndCur =	_RGFW->dndRoot;
 3648-		} else if (_RGFW->dndCur) {
 3649-			_RGFW->dndCur->next = (RGFW_dataDropNode*)RGFW_ALLOC(sizeof(RGFW_dataDropNode));
 3650-			_RGFW->dndCur = _RGFW->dndCur->next;
 3651-		} else { RGFW_ASSERT(0); }
 3652-
 3653-		char* dataCopy = (char*)RGFW_ALLOC(size);
 3654-		RGFW_MEMCPY(dataCopy, data, size);
 3655-		node.data = dataCopy;
 3656-
 3657-		RGFW_MEMCPY(_RGFW->dndCur, &node, sizeof(node));
 3658-
 3659-		event.drop.value = _RGFW->dndCur;
 3660-		RGFW_eventQueuePush(&event);
 3661-	}
 3662-}
 3663-
 3664-void RGFW_dataDragCallback(RGFW_window* win, RGFW_dataTransferType dataType, RGFW_dndActionType action, i32 x, i32 y) {
 3665-	if (!(win->internal.enabledEvents & RGFW_dataDragFlag) || !(win->internal.flags & RGFW_windowAllowDND)) return;
 3666-
 3667-	_RGFW->windowState.win = win;
 3668-	_RGFW->windowState.dataDragging = RGFW_TRUE;
 3669-	_RGFW->windowState.dropX = x;
 3670-	_RGFW->windowState.dropY = y;
 3671-
 3672-	RGFW_event event;
 3673-	event.type = RGFW_dataDrag;
 3674-	event.drag.x = x;
 3675-	event.drag.y = y;
 3676-	event.drag.action = action;
 3677-	event.drag.dataType = dataType;
 3678-	event.common.win = win;
 3679-
 3680-	RGFW_eventQueuePushAndCall(&event);
 3681-}
 3682-
 3683-void RGFW_keyCharCallback(RGFW_window* win, u32 codepoint) {
 3684-	if (!(win->internal.enabledEvents & RGFW_keyCharFlag)) return;
 3685-
 3686-	RGFW_event event;
 3687-	event.type = RGFW_keyChar;
 3688-	event.keyChar.value = codepoint;
 3689-	event.common.win = win;
 3690-	RGFW_eventQueuePushAndCall(&event);
 3691-}
 3692-
 3693-void RGFW_keyCallback(RGFW_window* win, RGFW_key key, RGFW_keymod mod, RGFW_bool repeat, RGFW_bool press) {
 3694-	RGFW_event event;
 3695-
 3696-	if (press) {
 3697-		if (!(win->internal.enabledEvents & RGFW_keyPressedFlag)) return;
 3698-		event.type = RGFW_keyPressed;
 3699-	} else {
 3700-		if (!(win->internal.enabledEvents & RGFW_keyReleasedFlag)) return;
 3701-		event.type = RGFW_keyReleased;
 3702-	}
 3703-
 3704-	_RGFW->keyboard[key].prev = _RGFW->keyboard[key].current;
 3705-	_RGFW->keyboard[key].current = press;
 3706-
 3707-	event.key.value = key;
 3708-	event.key.repeat = repeat;
 3709-	event.key.mod = mod;
 3710-	event.key.state = press;
 3711-	event.common.win = win;
 3712-	RGFW_eventQueuePushAndCall(&event);
 3713-}
 3714-
 3715-void RGFW_mouseButtonCallback(RGFW_window* win, RGFW_mouseButton button, RGFW_bool press) {
 3716-	RGFW_event event;
 3717-
 3718-	if (press) {
 3719-		if (!(win->internal.enabledEvents & RGFW_mouseButtonPressedFlag)) return;
 3720-		event.type = RGFW_mouseButtonPressed;
 3721-	} else {
 3722-		if (!(win->internal.enabledEvents & RGFW_mouseButtonReleasedFlag)) return;
 3723-		event.type = RGFW_mouseButtonReleased;
 3724-	}
 3725-
 3726-	_RGFW->mouseButtons[button].prev = _RGFW->mouseButtons[button].current;
 3727-	_RGFW->mouseButtons[button].current = press;
 3728-
 3729-	event.button.value = button;
 3730-	event.button.state = press;
 3731-	event.common.win = win;
 3732-	RGFW_eventQueuePushAndCall(&event);
 3733-}
 3734-
 3735-void RGFW_mouseScrollCallback(RGFW_window* win, float x, float y) {
 3736-	if (!(win->internal.enabledEvents & RGFW_mouseScrollFlag)) return;
 3737-	_RGFW->scrollX = x;
 3738-	_RGFW->scrollY = y;
 3739-
 3740-	RGFW_event event;
 3741-	event.type = RGFW_mouseScroll;
 3742-	event.delta.x = x;
 3743-	event.delta.y = y;
 3744-	event.common.win = win;
 3745-	RGFW_eventQueuePushAndCall(&event);
 3746-}
 3747-
 3748-void RGFW_scaleUpdatedCallback(RGFW_window* win, float scaleX, float scaleY) {
 3749-	if (!(win->internal.enabledEvents & RGFW_scaleUpdatedFlag)) return;
 3750-
 3751-	RGFW_event event;
 3752-	event.type = RGFW_scaleUpdated;
 3753-	event.scale.x = scaleX;
 3754-	event.scale.y = scaleY;
 3755-	event.common.win = win;
 3756-	RGFW_eventQueuePushAndCall(&event);
 3757-}
 3758-
 3759-void RGFW_monitorCallback(RGFW_window* win, const RGFW_monitor* monitor, RGFW_bool connected) {
 3760-	if (win) {
 3761-		if (connected && !(win->internal.enabledEvents & RGFW_monitorConnectedFlag)) return;
 3762-		if (!connected && !(win->internal.enabledEvents & RGFW_monitorDisconnectedFlag)) return;
 3763-	}
 3764-
 3765-	RGFW_event event;
 3766-	event.type = (connected) ? (RGFW_eventType)(RGFW_monitorConnected) : (RGFW_eventType)(RGFW_monitorDisconnected);
 3767-	event.monitor.monitor = monitor;
 3768-	event.monitor.state = connected;
 3769-	event.common.win = win;
 3770-	RGFW_eventQueuePushAndCall(&event);
 3771-}
 3772-
 3773-#ifdef RGFW_DEBUG
 3774-#include <stdio.h>
 3775-#endif
 3776-
 3777-void RGFW_debugCallback(RGFW_debugType type, RGFW_errorCode code, const char* msg) {
 3778-	RGFW_debugInfo info;
 3779-	info.type = type;
 3780-	info.code = code;
 3781-	info.msg = msg;
 3782-
 3783-	if (_RGFW && _RGFW->debugCallbackSrc) _RGFW->debugCallbackSrc(&info);
 3784-
 3785-    #ifdef RGFW_DEBUG
 3786-	switch (type) {
 3787-		case RGFW_typeInfo: RGFW_PRINTF("RGFW INFO (%i %i): %s", type, code, msg); break;
 3788-		case RGFW_typeError: RGFW_PRINTF("RGFW DEBUG (%i %i): %s", type, code, msg); break;
 3789-		case RGFW_typeWarning: RGFW_PRINTF("RGFW WARNING (%i %i): %s", type, code, msg); break;
 3790-		default: break;
 3791-	}
 3792-
 3793-	RGFW_PRINTF("\n");
 3794-	#endif
 3795-}
 3796-
 3797-void RGFW_window_checkMode(RGFW_window* win);
 3798-void RGFW_window_checkMode(RGFW_window* win) {
 3799-	if (RGFW_window_isMinimized(win) && (win->internal.enabledEvents & RGFW_windowMinimizedFlag)) {
 3800-		RGFW_windowMinimizedCallback(win);
 3801-	} else if (RGFW_window_isMaximized(win) && (win->internal.enabledEvents & RGFW_windowMaximizedFlag)) {
 3802-		RGFW_windowMaximizedCallback(win, win->x, win->y, win->w, win->h);
 3803-	} else if ((((win->internal.flags & RGFW_windowMinimize) && !RGFW_window_isMaximized(win)) ||
 3804-				(win->internal.flags & RGFW_windowMaximize && !RGFW_window_isMaximized(win))) && (win->internal.enabledEvents & RGFW_windowRestoredFlag)) {
 3805-		RGFW_windowRestoredCallback(win, win->x, win->y, win->w, win->h);
 3806-	}
 3807-}
 3808-
 3809-/*
 3810-no more event call back defines
 3811-*/
 3812-
 3813-size_t RGFW_sizeofInfo(void) { return sizeof(RGFW_info); }
 3814-size_t RGFW_sizeofNativeImage(void) { return sizeof(RGFW_nativeImage); }
 3815-size_t RGFW_sizeofSurface(void) { return sizeof(RGFW_surface); }
 3816-size_t RGFW_sizeofWindow(void) { return sizeof(RGFW_window); }
 3817-size_t RGFW_sizeofWindowSrc(void) { return sizeof(RGFW_window_src); }
 3818-
 3819-RGFW_window_src* RGFW_window_getSrc(RGFW_window* win) { return &win->src; }
 3820-RGFW_bool RGFW_window_getPosition(RGFW_window* win, i32* x, i32* y) { if (x) *x = win->x; if (y) *y = win->y; return RGFW_TRUE; }
 3821-RGFW_bool RGFW_window_getSize(RGFW_window* win, i32* w, i32* h) { if (w) *w = win->w; if (h) *h = win->h; return RGFW_TRUE; }
 3822-u32 RGFW_window_getFlags(RGFW_window* win) { return win->internal.flags; }
 3823-RGFW_key RGFW_window_getExitKey(RGFW_window* win) { return win->internal.exitKey; }
 3824-void RGFW_window_setExitKey(RGFW_window* win, RGFW_key key) { win->internal.exitKey = key; }
 3825-void RGFW_window_setEnabledEvents(RGFW_window* win, RGFW_eventFlag events) { win->internal.enabledEvents = events; }
 3826-RGFW_eventFlag RGFW_window_getEnabledEvents(RGFW_window* win) { return win->internal.enabledEvents; }
 3827-void RGFW_window_setDisabledEvents(RGFW_window* win, RGFW_eventFlag events) {   RGFW_window_setEnabledEvents(win, (RGFW_allEventFlags) & ~(u32)events);  }
 3828-void RGFW_window_setEventState(RGFW_window* win, RGFW_eventFlag event, RGFW_bool state) { RGFW_setBit(&win->internal.enabledEvents, event, state); }
 3829-void* RGFW_window_getUserPtr(RGFW_window* win) { return win->userPtr; }
 3830-void RGFW_window_setUserPtr(RGFW_window* win, void* ptr) { win->userPtr = ptr; }
 3831-
 3832-RGFW_bool RGFW_window_getSizeInPixels(RGFW_window* win, i32* w, i32* h) {
 3833-	RGFW_monitor* mon = RGFW_window_getMonitor(win);
 3834-	if (mon == NULL) return RGFW_FALSE;
 3835-
 3836-	if (w) *w = (i32)((float)win->w * mon->pixelRatio);
 3837-	if (h) *h = (i32)((float)win->h * mon->pixelRatio);
 3838-
 3839-	return RGFW_TRUE;
 3840-}
 3841-
 3842-
 3843-#if defined(RGFW_USE_XDL) && defined(RGFW_X11)
 3844-	#define XDL_IMPLEMENTATION
 3845-	#include "XDL.h"
 3846-#endif
 3847-
 3848-#ifndef RGFW_NO_STATIC_CONTEXT
 3849-
 3850-i32 RGFW_init(void) {
 3851-	static RGFW_info _rgfwGlobal;
 3852-	return RGFW_init_ptr(&_rgfwGlobal);
 3853-}
 3854-
 3855-
 3856-void RGFW_deinit(void) { RGFW_deinit_ptr(_RGFW); }
 3857-
 3858-#else
 3859-
 3860-RGFW_info* _rgfwGlobal;
 3861-
 3862-i32 RGFW_init(void) {
 3863-	if (_rgfwGlobal != NULL) {
 3864-		RGFW_FREE(_rgfwGlobal);
 3865-	}
 3866-
 3867-	_rgfwGlobal = (RGFW_info*)RGFW_ALLOC(sizeof(RGFW_info));
 3868-
 3869-	return RGFW_init_ptr(&_rgfwGlobal);
 3870-}
 3871-
 3872-void RGFW_deinit(void) {
 3873-	if (_RGFW == _rgfwGlobal) {
 3874-		RGFW_FREE(_rgfwGlobal);
 3875-		_rgfwGlobal = NULL;
 3876-	}
 3877-	RGFW_deinit_ptr(_RGFW);
 3878-}
 3879-
 3880-#endif
 3881-
 3882-i32 RGFW_initPlatform(void);
 3883-void RGFW_deinitPlatform(void);
 3884-
 3885-i32 RGFW_init_ptr(RGFW_info* info) {
 3886-    if (info == _RGFW || info == NULL) return 1;
 3887-
 3888-    RGFW_setInfo(info);
 3889-    RGFW_MEMZERO(_RGFW, sizeof(RGFW_info));
 3890-	_RGFW->queueEvents = RGFW_FALSE;
 3891-	_RGFW->polledEvents = RGFW_FALSE;
 3892-#ifdef RGFW_WAYLAND
 3893-	_RGFW->useWaylandBool = RGFW_TRUE;
 3894-#endif
 3895-
 3896-	#if (RGFW_PREALLOCATED_MONITORS)
 3897-		_RGFW->monitors.freeList.head = &_RGFW->monitors.data[0];
 3898-		_RGFW->monitors.freeList.cur = _RGFW->monitors.freeList.head;
 3899-
 3900-		for (size_t i = 1; i < RGFW_PREALLOCATED_MONITORS; i++) {
 3901-			RGFW_monitorNode* newNode = &_RGFW->monitors.data[i];
 3902-			_RGFW->monitors.freeList.cur->next = newNode;
 3903-			_RGFW->monitors.freeList.cur = _RGFW->monitors.freeList.cur->next;
 3904-		}
 3905-	#endif
 3906-
 3907-	_RGFW->monitors.list.head = NULL;
 3908-	_RGFW->monitors.list.head = NULL;
 3909-    RGFW_initKeycodes();
 3910-    i32 out = RGFW_initPlatform();
 3911-
 3912-	for (size_t i = 0; i < RGFW_mouseIconCount; i++) {
 3913-        _RGFW->standardMice[i] = RGFW_createMouseStandard((RGFW_mouseIcon)i);
 3914-	}
 3915-
 3916-	RGFW_pollMonitors();
 3917-
 3918-    RGFW_debugCallback(RGFW_typeInfo, RGFW_infoGlobal, "global context initialized");
 3919-
 3920-	return out;
 3921-}
 3922-
 3923-#ifndef RGFW_EGL
 3924-void RGFW_unloadEGL(void) { }
 3925-#endif
 3926-
 3927-void RGFW_deinit_ptr(RGFW_info* info) {
 3928-    if (info == NULL) return;
 3929-
 3930-    RGFW_setInfo(info);
 3931-	RGFW_unloadEGL();
 3932-
 3933-	for (RGFW_mouseIcon i = 0; i < RGFW_mouseIconCount; i++) {
 3934-		if (_RGFW->standardMice[i]) RGFW_freeMouse(_RGFW->standardMice[i]);
 3935-	}
 3936-
 3937-	RGFW_debugCallback(RGFW_typeInfo, RGFW_infoGlobal, "global context deinitialized");
 3938-	RGFW_deinitPlatform();
 3939-
 3940-    _RGFW->root = NULL;
 3941-    _RGFW->windowCount = 0;
 3942-    RGFW_setInfo(NULL);
 3943-}
 3944-
 3945-RGFW_window* RGFW_createWindow(const char* name, i32 x, i32 y, i32 w, i32 h, RGFW_windowFlags flags) {
 3946-	RGFW_window* win = (RGFW_window*)RGFW_ALLOC(sizeof(RGFW_window));
 3947-	RGFW_ASSERT(win != NULL);
 3948-    return RGFW_createWindowPtr(name, x, y, w, h, flags, win);
 3949-}
 3950-
 3951-void RGFW_window_close(RGFW_window* win) {
 3952-	RGFW_ASSERT(win != NULL);
 3953-	RGFW_window_closePtr(win);
 3954-	RGFW_FREE(win);
 3955-}
 3956-
 3957-RGFW_window* RGFW_createWindowPtr(const char* name, i32 x, i32 y, i32 w, i32 h, RGFW_windowFlags flags, RGFW_window* win) {
 3958-	RGFW_ASSERT(win != NULL);
 3959-	if (name == NULL) name = "\0";
 3960-
 3961-	RGFW_MEMZERO(win, sizeof(RGFW_window));
 3962-
 3963-	if (_RGFW == NULL) RGFW_init();
 3964-	_RGFW->windowCount++;
 3965-
 3966-	/* rect based the requested flags */
 3967-	if (_RGFW->root == NULL) {
 3968-		RGFW_setRootWindow(win);
 3969-	}
 3970-
 3971-	/* set and init the new window's data */
 3972-	win->x = x;
 3973-	win->y = y;
 3974-	win->w = w;
 3975-	win->h = h;
 3976-	win->internal.mouse = _RGFW->standardMice[RGFW_mouseNormal];
 3977-	win->internal.flags = flags;
 3978-	win->internal.enabledEvents = RGFW_allEventFlags;
 3979-
 3980-	RGFW_windowFlags reservedFlags = flags & (RGFW_windowScaleToMonitor);
 3981-	flags &= ~reservedFlags;
 3982-
 3983-	RGFW_window* ret = RGFW_createWindowPlatform(name, flags, win);
 3984-
 3985-	flags |= reservedFlags;
 3986-
 3987-#ifndef RGFW_X11
 3988-	RGFW_window_setFlagsInternal(win, flags, 0);
 3989-#endif
 3990-
 3991-#ifdef RGFW_OPENGL
 3992-	win->src.gfxType = 0;
 3993-	if (flags & RGFW_windowOpenGL)
 3994-		RGFW_window_createContext_OpenGL(win, RGFW_getGlobalHints_OpenGL());
 3995-#endif
 3996-
 3997-#ifdef RGFW_EGL
 3998-	if (flags & RGFW_windowEGL)
 3999-		RGFW_window_createContext_EGL(win, RGFW_getGlobalHints_OpenGL());
 4000-#endif
 4001-
 4002-	/* X11 creates the window after the OpenGL context is created (because of visual garbage),
 4003-		 * so we have to wait to set the flags
 4004-		 * This is required so that way the user can create their own OpenGL context after RGFW_createWindow is used
 4005-		 * if a window is created, CreateContext will delete the window and create a new one
 4006-		 * */
 4007-#ifdef RGFW_X11
 4008-	RGFW_window_setFlagsInternal(win, flags, 0);
 4009-#endif
 4010-
 4011-#ifdef RGFW_MACOS
 4012-	/*NOTE: another OpenGL/setFlags related hack, this because OSX the 'view' class must be setup after the NSOpenGL view is made AND after setFlags happens */
 4013-	RGFW_osx_initView(win);
 4014-#endif
 4015-
 4016-#ifdef RGFW_WAYLAND
 4017-	/* recieve all events needed to configure the surface */
 4018-	/* also gets the wl_outputs */
 4019-	if (RGFW_usingWayland()) {
 4020-		wl_display_roundtrip(_RGFW->wl_display);
 4021-		/* NOTE: this is a hack so that way wayland spawns a window, even if nothing is drawn */
 4022-		if (!(flags & RGFW_windowOpenGL) && !(flags & RGFW_windowEGL)) {
 4023-			u8* data = (u8*)RGFW_ALLOC((u32)(win->w * win->h * 3));
 4024-			RGFW_MEMZERO(data, (u32)(win->w * win->h * 3) * sizeof(u8));
 4025-			RGFW_surface* surface = RGFW_createSurface(data, win->w, win->h, RGFW_formatBGR8);
 4026-			RGFW_window_blitSurface(win, surface);
 4027-			RGFW_FREE(data);
 4028-			RGFW_surface_free(surface);
 4029-		}
 4030-	}
 4031-#endif
 4032-
 4033-	if (!(flags & RGFW_windowHideMouse)) {
 4034-		RGFW_window_setMouseDefault(win);
 4035-	}
 4036-
 4037-	RGFW_window_setName(win, name);
 4038-	if (!(flags & RGFW_windowHide)) {
 4039-		flags |= RGFW_windowHide;
 4040-		RGFW_window_show(win);
 4041-	}
 4042-
 4043-	RGFW_debugCallback(RGFW_typeInfo, RGFW_infoWindow, "a new window was created");
 4044-
 4045-	return ret;
 4046-}
 4047-
 4048-void RGFW_window_closePtr(RGFW_window* win) {
 4049-	RGFW_ASSERT(win != NULL);
 4050-
 4051-	if (win->internal.captureMouse) {
 4052-		RGFW_window_captureMouse(win, RGFW_FALSE);
 4053-	}
 4054-
 4055-	#ifdef RGFW_EGL
 4056-	if ((win->src.gfxType & RGFW_gfxEGL) && win->src.ctx.egl) {
 4057-		RGFW_window_deleteContext_EGL(win, win->src.ctx.egl);
 4058-		win->src.ctx.egl = NULL;
 4059-	}
 4060-	#endif
 4061-
 4062-	#ifdef RGFW_OPENGL
 4063-	if ((win->src.gfxType & RGFW_gfxNativeOpenGL) && win->src.ctx.native) {
 4064-		RGFW_window_deleteContext_OpenGL(win, win->src.ctx.native);
 4065-		win->src.ctx.native = NULL;
 4066-	}
 4067-	#endif
 4068-
 4069-	RGFW_window_closePlatform(win);
 4070-
 4071-	RGFW_clipboard_switch(NULL);
 4072-
 4073-	_RGFW->windowCount--;
 4074-	RGFW_debugCallback(RGFW_typeInfo, RGFW_infoWindow, "a window was freed");
 4075-
 4076-	if (_RGFW->windowCount == 0 && !(win->internal.flags & RGFW_noDeinitOnClose)) RGFW_deinit();
 4077-}
 4078-
 4079-void RGFW_setQueueEvents(RGFW_bool queue) {  _RGFW->queueEvents = RGFW_BOOL(queue); }
 4080-
 4081-void RGFW_eventQueueFlush(void) { _RGFW->eventLen = 0; }
 4082-
 4083-void RGFW_eventQueuePush(const RGFW_event* event) {
 4084-	if (_RGFW->queueEvents == RGFW_FALSE) return;
 4085-	RGFW_ASSERT(_RGFW->eventLen >= 0);
 4086-
 4087-	if (_RGFW->eventLen >= RGFW_MAX_EVENTS) {
 4088-		RGFW_debugCallback(RGFW_typeError, RGFW_errEventQueue, "Event queue limit 'RGFW_MAX_EVENTS' has been reached automatically flushing queue.");
 4089-		RGFW_eventQueueFlush();
 4090-		return;
 4091-	}
 4092-
 4093-	i32 eventTop = (_RGFW->eventBottom + _RGFW->eventLen) % RGFW_MAX_EVENTS;
 4094-	_RGFW->eventLen += 1;
 4095-	_RGFW->events[eventTop] = *event;
 4096-}
 4097-
 4098-RGFW_event* RGFW_eventQueuePop(void) {
 4099-	RGFW_ASSERT(_RGFW->eventLen >= 0 && _RGFW->eventLen <= RGFW_MAX_EVENTS);
 4100-	RGFW_event* ev;
 4101-
 4102-	if (_RGFW->eventLen == 0) {
 4103-		return NULL;
 4104-	}
 4105-
 4106-	ev = &_RGFW->events[_RGFW->eventBottom];
 4107-	_RGFW->eventLen -= 1;
 4108-    _RGFW->eventBottom = (_RGFW->eventBottom + 1) % RGFW_MAX_EVENTS;
 4109-
 4110-	return ev;
 4111-}
 4112-
 4113-RGFW_bool RGFW_checkEvent(RGFW_event* event) {
 4114-	if (_RGFW->eventLen == 0 && _RGFW->polledEvents == RGFW_FALSE) {
 4115-		_RGFW->queueEvents = RGFW_TRUE;
 4116-		RGFW_pollEvents();
 4117-		_RGFW->polledEvents = RGFW_TRUE;
 4118-	}
 4119-
 4120-	if (RGFW_checkQueuedEvent(event) == RGFW_FALSE) {
 4121-		_RGFW->polledEvents = RGFW_FALSE;
 4122-		return RGFW_FALSE;
 4123-	}
 4124-
 4125-	return RGFW_TRUE;
 4126-}
 4127-
 4128-RGFW_bool RGFW_checkQueuedEvent(RGFW_event* event) {
 4129-	RGFW_event* ev;
 4130-	_RGFW->queueEvents = RGFW_TRUE;
 4131-	/* check queued events */
 4132-	ev = RGFW_eventQueuePop();
 4133-	if (ev != NULL) {
 4134-		*event = *ev;
 4135-		return RGFW_TRUE;
 4136-    }
 4137-
 4138-	return RGFW_FALSE;
 4139-}
 4140-
 4141-void RGFW_resetPrevState(void) {
 4142-	size_t i; /*!< reset each previous state  */
 4143-    for (i = 0; i < RGFW_keyLast; i++) _RGFW->keyboard[i].prev = _RGFW->keyboard[i].current;
 4144-    for (i = 0; i < RGFW_mouseFinal; i++) _RGFW->mouseButtons[i].prev = _RGFW->mouseButtons[i].current;
 4145-	_RGFW->scrollX = 0.0f;
 4146-	_RGFW->scrollY = 0.0f;
 4147-	_RGFW->vectorX = (float)0.0f;
 4148-	_RGFW->vectorY = (float)0.0f;
 4149-	RGFW_MEMZERO(&_RGFW->windowState, sizeof(_RGFW->windowState));
 4150-
 4151-	for (RGFW_dataDropNode* node = _RGFW->dndRoot; node; ) {
 4152-		RGFW_dataDropNode* next = node->next;
 4153-		RGFW_FREE(node);
 4154-		node = next;
 4155-	}
 4156-
 4157-	_RGFW->dndRoot = NULL;
 4158-	_RGFW->dndCur = NULL;
 4159-}
 4160-
 4161-RGFW_bool RGFW_isKeyPressed(RGFW_key key) {
 4162-	RGFW_ASSERT(_RGFW != NULL);
 4163-    return _RGFW->keyboard[key].current && !_RGFW->keyboard[key].prev;
 4164-}
 4165-RGFW_bool RGFW_isKeyDown(RGFW_key key) {
 4166-	RGFW_ASSERT(_RGFW != NULL);
 4167-	return _RGFW->keyboard[key].current;
 4168-}
 4169-RGFW_bool RGFW_isKeyReleased(RGFW_key key) {
 4170-	RGFW_ASSERT(_RGFW != NULL);
 4171-	return !_RGFW->keyboard[key].current && _RGFW->keyboard[key].prev;
 4172-}
 4173-
 4174-
 4175-RGFW_bool RGFW_isMousePressed(RGFW_mouseButton button) {
 4176-	RGFW_ASSERT(_RGFW != NULL);
 4177-	return _RGFW->mouseButtons[button].current && !_RGFW->mouseButtons[button].prev;
 4178-}
 4179-RGFW_bool RGFW_isMouseDown(RGFW_mouseButton button) {
 4180-	RGFW_ASSERT(_RGFW != NULL);
 4181-	return _RGFW->mouseButtons[button].current;
 4182-}
 4183-RGFW_bool RGFW_isMouseReleased(RGFW_mouseButton button) {
 4184-	RGFW_ASSERT(_RGFW != NULL);
 4185-	return !_RGFW->mouseButtons[button].current && _RGFW->mouseButtons[button].prev;
 4186-}
 4187-
 4188-void RGFW_getMouseScroll(float* x, float* y) {
 4189-	RGFW_ASSERT(_RGFW != NULL);
 4190-	if (x) *x = _RGFW->scrollX;
 4191-	if (y) *y = _RGFW->scrollY;
 4192-}
 4193-
 4194-void RGFW_getMouseVector(float* x, float* y) {
 4195-	RGFW_ASSERT(_RGFW != NULL);
 4196-	if (x) *x = _RGFW->vectorX;
 4197-	if (y) *y = _RGFW->vectorY;
 4198-}
 4199-
 4200-RGFW_bool RGFW_window_didMouseLeave(RGFW_window* win) { return _RGFW->windowState.winLeave == win && _RGFW->windowState.mouseLeave; }
 4201-RGFW_bool RGFW_window_didMouseEnter(RGFW_window* win) { return _RGFW->windowState.win == win && _RGFW->windowState.mouseEnter; }
 4202-RGFW_bool RGFW_window_isMouseInside(RGFW_window* win) { return win->internal.mouseInside;  }
 4203-
 4204-RGFW_bool RGFW_window_isDataDragging(RGFW_window* win) { return RGFW_window_getDataDrag(win, (i32*)NULL, (i32*)NULL); }
 4205-RGFW_bool RGFW_window_didDataDrop(RGFW_window* win) { return RGFW_window_getDataDrop(win) != NULL;}
 4206-
 4207-
 4208-RGFW_bool RGFW_window_getDataDrag(RGFW_window* win, i32* x, i32* y) {
 4209-	if (_RGFW->windowState.win != win || _RGFW->windowState.dataDragging == RGFW_FALSE) return RGFW_FALSE;
 4210-	if (x) *x = _RGFW->windowState.dropX;
 4211-	if (y) *y =  _RGFW->windowState.dropY;
 4212-	return RGFW_TRUE;
 4213-}
 4214-RGFW_dataDropNode* RGFW_window_getDataDrop(RGFW_window* win) {
 4215-	if (_RGFW->windowState.win != win || _RGFW->windowState.dataDrop == RGFW_FALSE) return NULL;
 4216-	return _RGFW->dndRoot;
 4217-}
 4218-
 4219-RGFW_bool RGFW_window_checkEvent(RGFW_window* win, RGFW_event* event) {
 4220-	if (_RGFW->eventLen == 0 && _RGFW->polledEvents == RGFW_FALSE) {
 4221-		_RGFW->queueEvents = RGFW_TRUE;
 4222-		RGFW_pollEvents();
 4223-		_RGFW->polledEvents = RGFW_TRUE;
 4224-	}
 4225-
 4226-	if (RGFW_window_checkQueuedEvent(win, event) == RGFW_FALSE) {
 4227-		_RGFW->polledEvents = RGFW_FALSE;
 4228-		return RGFW_FALSE;
 4229-	}
 4230-
 4231-	return RGFW_TRUE;
 4232-}
 4233-
 4234-RGFW_bool RGFW_window_checkQueuedEvent(RGFW_window* win, RGFW_event* event) {
 4235-	RGFW_event* ev;
 4236-	RGFW_ASSERT(win != NULL);
 4237-	_RGFW->queueEvents = RGFW_TRUE;
 4238-	/* check queued events */
 4239-	ev = RGFW_window_eventQueuePop(win);
 4240-	if (ev == NULL) return RGFW_FALSE;
 4241-
 4242-	*event = *ev;
 4243-	return RGFW_TRUE;
 4244-}
 4245-
 4246-RGFW_event* RGFW_window_eventQueuePop(RGFW_window* win) {
 4247-	RGFW_event* ev = RGFW_eventQueuePop();
 4248-	if (ev == NULL) return ev;
 4249-
 4250-	for (i32 i = 1; i < _RGFW->eventLen && ev->common.win != win && ev->common.win != NULL; i++) {
 4251-		RGFW_eventQueuePush(ev);
 4252-		ev = RGFW_eventQueuePop();
 4253-	}
 4254-
 4255-	if (ev->common.win != win && ev->common.win != NULL) {
 4256-		return NULL;
 4257-	}
 4258-
 4259-	return ev;
 4260-}
 4261-
 4262-void RGFW_setRootWindow(RGFW_window* win) { _RGFW->root = win; }
 4263-RGFW_window* RGFW_getRootWindow(void) { return _RGFW->root; }
 4264-
 4265-#ifndef RGFW_EGL
 4266-RGFW_bool RGFW_loadEGL(void) { return RGFW_FALSE; }
 4267-#endif
 4268-
 4269-void RGFW_window_setFlagsInternal(RGFW_window* win, RGFW_windowFlags flags, RGFW_windowFlags cmpFlags) {
 4270-	if (flags & RGFW_windowNoBorder)            RGFW_window_setBorder(win, 0);
 4271-	else if (cmpFlags & RGFW_windowNoBorder)    RGFW_window_setBorder(win, 1);
 4272-	if (flags & RGFW_windowMaximize)            RGFW_window_maximize(win);
 4273-	else if (cmpFlags & RGFW_windowMaximize)    RGFW_window_restore(win);
 4274-	if (flags & RGFW_windowMinimize)            RGFW_window_minimize(win);
 4275-	else if (cmpFlags & RGFW_windowMinimize)    RGFW_window_restore(win);
 4276-	if (flags & RGFW_windowCenter)              RGFW_window_center(win);
 4277-	if (flags & RGFW_windowCenterCursor)        RGFW_window_moveMouse(win, win->x + (win->w / 2), win->y + (win->h / 2));
 4278-	if (flags & RGFW_windowFullscreen)          RGFW_window_setFullscreen(win, RGFW_TRUE);
 4279-	else if (cmpFlags & RGFW_windowFullscreen)  RGFW_window_setFullscreen(win, 0);
 4280-	if (flags & RGFW_windowHideMouse)           RGFW_window_showMouse(win, 0);
 4281-	else if (cmpFlags & RGFW_windowHideMouse)   RGFW_window_showMouse(win, 1);
 4282-	if (flags & RGFW_windowHide)                RGFW_window_hide(win);
 4283-	else if (cmpFlags & RGFW_windowHide)        RGFW_window_show(win);
 4284-	if (flags & RGFW_windowFloating)            RGFW_window_setFloating(win, 1);
 4285-	else if (cmpFlags & RGFW_windowFloating)    RGFW_window_setFloating(win, 0);
 4286-	if (flags & RGFW_windowRawMouse)			RGFW_window_setRawMouseMode(win, RGFW_TRUE);
 4287-	else if (cmpFlags & RGFW_windowRawMouse)	RGFW_window_setRawMouseMode(win, RGFW_FALSE);
 4288-	if (flags & RGFW_windowCaptureMouse)			RGFW_window_captureRawMouse(win, RGFW_TRUE);
 4289-	else if (cmpFlags & RGFW_windowCaptureMouse)	RGFW_window_captureMouse(win, RGFW_FALSE);
 4290-	if (flags & RGFW_windowFocus)               RGFW_window_focus(win);
 4291-	if (flags & RGFW_windowScaleToMonitor)      RGFW_window_scaleToMonitor(win);
 4292-
 4293-	if (flags & RGFW_windowNoResize) {
 4294-	    RGFW_window_setMaxSize(win, win->w, win->h);
 4295-	    RGFW_window_setMinSize(win, win->w, win->h);
 4296-	} else if (cmpFlags & RGFW_windowNoResize) {
 4297-		RGFW_window_setMaxSize(win, 0, 0);
 4298-		RGFW_window_setMinSize(win, 0, 0);
 4299-	}
 4300-
 4301-	win->internal.flags = flags;
 4302-}
 4303-
 4304-
 4305-void RGFW_window_setFlags(RGFW_window* win, RGFW_windowFlags flags) { RGFW_window_setFlagsInternal(win, flags, win->internal.flags); }
 4306-
 4307-RGFW_bool RGFW_window_isInFocus(RGFW_window* win) {
 4308-#ifdef RGFW_WASM
 4309-    return RGFW_TRUE;
 4310-#else
 4311-    return RGFW_BOOL(win->internal.inFocus);
 4312-#endif
 4313-}
 4314-
 4315-void RGFW_setClassName(const char* name) { RGFW_init(); _RGFW->className = name; }
 4316-void RGFW_setBuildDND(RGFW_bool state) { _RGFW->dndBuild = state; }
 4317-
 4318-#ifndef RGFW_X11
 4319-void RGFW_setXInstName(const char* name) { RGFW_UNUSED(name); }
 4320-#endif
 4321-
 4322-RGFW_bool RGFW_window_getMouse(RGFW_window* win, i32* x, i32* y) {
 4323-	RGFW_ASSERT(win != NULL);
 4324-	if (x) *x = win->internal.lastMouseX;
 4325-	if (y) *y = win->internal.lastMouseY;
 4326-	return RGFW_TRUE;
 4327-}
 4328-
 4329-RGFW_bool RGFW_window_isKeyPressed(RGFW_window* win, RGFW_key key) { return RGFW_isKeyPressed(key)  && RGFW_window_isInFocus(win); }
 4330-RGFW_bool RGFW_window_isKeyDown(RGFW_window* win, RGFW_key key) { return RGFW_isKeyDown(key) && RGFW_window_isInFocus(win); }
 4331-RGFW_bool RGFW_window_isKeyReleased(RGFW_window* win, RGFW_key key) { return RGFW_isKeyReleased(key) && RGFW_window_isInFocus(win); }
 4332-
 4333-RGFW_bool RGFW_window_isMousePressed(RGFW_window* win, RGFW_mouseButton button) { return RGFW_isMousePressed(button) && RGFW_window_isInFocus(win); }
 4334-RGFW_bool RGFW_window_isMouseDown(RGFW_window* win, RGFW_mouseButton button) { return RGFW_isMouseDown(button) && RGFW_window_isInFocus(win); }
 4335-RGFW_bool RGFW_window_isMouseReleased(RGFW_window* win, RGFW_mouseButton button) { return RGFW_isMouseReleased(button) && RGFW_window_isInFocus(win); }
 4336-
 4337-
 4338-
 4339-#ifndef RGFW_X11
 4340-void* RGFW_getDisplay_X11(void) { return NULL; }
 4341-u64 RGFW_window_getWindow_X11(RGFW_window* win) { RGFW_UNUSED(win); return 0; }
 4342-#endif
 4343-
 4344-#ifndef RGFW_WAYLAND
 4345-struct wl_display* RGFW_getDisplay_Wayland(void) { return NULL; }
 4346-struct wl_surface* RGFW_window_getWindow_Wayland(RGFW_window* win) { RGFW_UNUSED(win); return NULL; }
 4347-#endif
 4348-
 4349-#ifndef RGFW_WINDOWS
 4350-void* RGFW_window_getHWND(RGFW_window* win) { RGFW_UNUSED(win); return NULL; }
 4351-void* RGFW_window_getHDC(RGFW_window* win) { RGFW_UNUSED(win); return NULL; }
 4352-#endif
 4353-
 4354-#ifndef RGFW_MACOS
 4355-void* RGFW_window_getView_OSX(RGFW_window* win) { RGFW_UNUSED(win); return NULL; }
 4356-void RGFW_window_setLayer_OSX(RGFW_window* win, void* layer) { RGFW_UNUSED(win); RGFW_UNUSED(layer); }
 4357-void* RGFW_getLayer_OSX(void) { return NULL; }
 4358-void* RGFW_window_getWindow_OSX(RGFW_window* win) { RGFW_UNUSED(win); return NULL; }
 4359-#endif
 4360-
 4361-void RGFW_setBit(u32* var, u32 mask, RGFW_bool set) {
 4362-	if (set) *var |=  mask;
 4363-	else     *var &= ~mask;
 4364-}
 4365-
 4366-void RGFW_window_center(RGFW_window* win) {
 4367-	RGFW_ASSERT(win != NULL);
 4368-	RGFW_monitor* mon = RGFW_window_getMonitor(win);
 4369-	if (mon == NULL) return;
 4370-
 4371-	RGFW_window_move(win, mon->x + ((i32)(mon->mode.w - win->w) / 2), mon->y + ((mon->mode.h - win->h) / 2));
 4372-}
 4373-
 4374-RGFW_bool RGFW_monitor_scaleToWindow(RGFW_monitor* mon, RGFW_window* win) {
 4375-	RGFW_monitorMode mode;
 4376-    RGFW_ASSERT(win != NULL);
 4377-
 4378-	mode.w = win->w;
 4379-	mode.h = win->h;
 4380-	RGFW_bool ret = RGFW_monitor_requestMode(mon, &mode, RGFW_monitorScale);
 4381-
 4382-	/* move window to monitor origin so it doesn't move to the next monitor */
 4383-	RGFW_window_move(win, mon->x, mon->y);
 4384-
 4385-	return ret;
 4386-}
 4387-
 4388-void RGFW_splitBPP(u32 bpp, RGFW_monitorMode* mode) {
 4389-    if (bpp == 32) bpp = 24;
 4390-    mode->red = mode->green = mode->blue = (u8)(bpp / 3);
 4391-
 4392-    u32 delta = bpp - (mode->red * 3); /* handle leftovers */
 4393-    if (delta >= 1) mode->green = mode->green + 1;
 4394-    if (delta == 2) mode->red = mode->red + 1;
 4395-}
 4396-
 4397-RGFW_bool RGFW_monitorModeCompare(RGFW_monitorMode* mon, RGFW_monitorMode* mon2, RGFW_modeRequest request) {
 4398-	RGFW_ASSERT(mon);
 4399-	RGFW_ASSERT(mon2);
 4400-
 4401-	return (((mon->w == mon2->w && mon->h == mon2->h) || !(request & RGFW_monitorScale)) &&
 4402-			((mon->refreshRate == mon2->refreshRate) || !(request & RGFW_monitorRefresh)) &&
 4403-			((mon->red == mon2->red && mon->green == mon2->green && mon->blue == mon2->blue) || !(request & RGFW_monitorRGB)));
 4404-}
 4405-
 4406-RGFW_bool RGFW_window_shouldClose(RGFW_window* win) {
 4407-	return (win == NULL || win->internal.shouldClose || (win->internal.exitKey && RGFW_isKeyDown(win->internal.exitKey)));
 4408-}
 4409-
 4410-void RGFW_window_setShouldClose(RGFW_window* win, RGFW_bool shouldClose) {
 4411-	if (shouldClose)  {
 4412-		RGFW_windowCloseCallback(win);
 4413-	} else {
 4414-		win->internal.shouldClose = RGFW_FALSE;
 4415-	}
 4416-}
 4417-
 4418-void RGFW_window_scaleToMonitor(RGFW_window* win) {
 4419-	RGFW_monitor* monitor = RGFW_window_getMonitor(win);
 4420-	if (monitor->scaleX == 0 && monitor->scaleY == 0)
 4421-		return;
 4422-
 4423-	RGFW_window_resize(win, (i32)(monitor->scaleX * (float)win->w), (i32)(monitor->scaleY * (float)win->h));
 4424-}
 4425-
 4426-void RGFW_window_moveToMonitor(RGFW_window* win, RGFW_monitor* m) {
 4427-	RGFW_window_move(win, m->x + win->x, m->y + win->y);
 4428-}
 4429-
 4430-RGFW_surface* RGFW_createSurface(u8* data, i32 w, i32 h, RGFW_format format) {
 4431-	RGFW_surface* surface = (RGFW_surface*)RGFW_ALLOC(sizeof(RGFW_surface));
 4432-	RGFW_MEMZERO(surface, sizeof(RGFW_surface));
 4433-	RGFW_createSurfacePtr(data, w, h, format, surface);
 4434-	return surface;
 4435-}
 4436-
 4437-void RGFW_surface_setConvertFunc(RGFW_surface* surface, RGFW_convertImageDataFunc func) {
 4438-	surface->convertFunc = func;
 4439-}
 4440-
 4441-void RGFW_surface_free(RGFW_surface* surface) {
 4442-	RGFW_surface_freePtr(surface);
 4443-	RGFW_FREE(surface);
 4444-}
 4445-
 4446-RGFW_nativeImage* RGFW_surface_getNativeImage(RGFW_surface* surface) {
 4447-	return &surface->native;
 4448-}
 4449-
 4450-RGFW_surface* RGFW_window_createSurface(RGFW_window* win, u8* data, i32 w, i32 h, RGFW_format format) {
 4451-	RGFW_surface* surface = (RGFW_surface*)RGFW_ALLOC(sizeof(RGFW_surface));
 4452-	RGFW_MEMZERO(surface, sizeof(RGFW_surface));
 4453-	RGFW_window_createSurfacePtr(win, data, w, h, format, surface);
 4454-	return surface;
 4455-}
 4456-
 4457-#ifndef RGFW_X11
 4458-RGFW_bool RGFW_window_createSurfacePtr(RGFW_window* win, u8* data, i32 w, i32 h, RGFW_format format, RGFW_surface* surface) {
 4459-	RGFW_UNUSED(win);
 4460-	return RGFW_createSurfacePtr(data, w, h, format, surface);
 4461-}
 4462-#endif
 4463-
 4464-const RGFW_colorLayout RGFW_layouts[RGFW_formatCount] = {
 4465-	{ 0, 1, 2, 3, 3 }, /* RGFW_formatRGB8 */
 4466-	{ 2, 1, 0, 3, 3 }, /* RGFW_formatBGR8 */
 4467-	{ 0, 1, 2, 3, 4 }, /* RGFW_formatRGBA8 */
 4468-	{ 1, 2, 3, 0, 4 }, /* RGFW_formatARGB8 */
 4469-	{ 2, 1, 0, 3, 4 }, /* RGFW_formatBGRA8 */
 4470-	{ 3, 2, 1, 0, 4 }, /* RGFW_formatABGR8 */
 4471-};
 4472-
 4473-
 4474-void RGFW_copyImageData(u8* dest_data, i32 w, i32 h, RGFW_format dest_format, u8* src_data, RGFW_format src_format, RGFW_convertImageDataFunc func) {
 4475-	RGFW_copyImageData64(dest_data, w, h, dest_format, src_data, src_format, RGFW_FALSE, func);
 4476-}
 4477-
 4478-RGFWDEF void RGFW_convertImageData64(u8* dest_data, u8* src_data, const RGFW_colorLayout* srcLayout, const RGFW_colorLayout* destLayout, size_t count, RGFW_bool is64bit);
 4479-void RGFW_convertImageData64(u8* dest_data, u8* src_data, const RGFW_colorLayout* srcLayout, const RGFW_colorLayout* destLayout, size_t count, RGFW_bool is64bit) {
 4480-	u32 i, i2 = 0;
 4481-	u8 rgba[4] = {0};
 4482-
 4483-	for (i = 0; i < count; i++) {
 4484-		const u8* src_px = &src_data[i * srcLayout->channels];
 4485-		u8* dst_px = &dest_data[i2 * destLayout->channels];
 4486-        rgba[0] = src_px[srcLayout->r];
 4487-        rgba[1] = src_px[srcLayout->g];
 4488-        rgba[2] = src_px[srcLayout->b];
 4489-        rgba[3] = (srcLayout->channels == 4) ? src_px[srcLayout->a] : 255;
 4490-
 4491-        dst_px[destLayout->r] = rgba[0];
 4492-        dst_px[destLayout->g] = rgba[1];
 4493-        dst_px[destLayout->b] = rgba[2];
 4494-		if (destLayout->channels == 4)
 4495-			dst_px[destLayout->a] = rgba[3];
 4496-
 4497-		i2 += 1 + is64bit;
 4498-	}
 4499-}
 4500-
 4501-void RGFW_copyImageData64(u8* dest_data, i32 dest_w, i32 dest_h, RGFW_format dest_format, u8* src_data, RGFW_format src_format, RGFW_bool is64bit, RGFW_convertImageDataFunc func) {
 4502-	RGFW_ASSERT(dest_data && src_data);
 4503-
 4504-    u32 count = (u32)(dest_w * dest_h);
 4505-
 4506-	if (src_format == dest_format) {
 4507-		u32 channels = (dest_format >= RGFW_formatRGBA8) ? 4 : 3;
 4508-        RGFW_MEMCPY(dest_data, src_data, count * channels);
 4509-        return;
 4510-    }
 4511-
 4512-    const RGFW_colorLayout* srcLayout  = &RGFW_layouts[src_format];
 4513-    const RGFW_colorLayout* destLayout = &RGFW_layouts[dest_format];
 4514-
 4515-	if (is64bit || func == NULL) {
 4516-		RGFW_convertImageData64(dest_data, src_data, srcLayout, destLayout, count, is64bit);
 4517-	} else {
 4518-		func(dest_data, src_data, srcLayout, destLayout, count);
 4519-	}
 4520-}
 4521-
 4522-RGFW_monitorNode* RGFW_monitors_add(const RGFW_monitor* mon) {
 4523-	RGFW_monitorNode* node = NULL;
 4524-
 4525-	#if (RGFW_PREALLOCATED_MONITORS)
 4526-		node = _RGFW->monitors.freeList.head;
 4527-		if (node) {
 4528-			_RGFW->monitors.freeList.head = node->next;
 4529-			if (_RGFW->monitors.freeList.head == NULL) {
 4530-				_RGFW->monitors.freeList.cur = NULL;
 4531-			}
 4532-		} else
 4533-	#elif !defined(RGFW_NO_ALLOCATE_MONITORS)
 4534-	{
 4535-		node = (RGFW_monitorNode*)RGFW_ALLOC(sizeof(RGFW_monitorNode));
 4536-	}
 4537-	#endif
 4538-
 4539-	if (node == NULL) return NULL;
 4540-
 4541-	node->next = NULL;
 4542-
 4543-	if (_RGFW->monitors.list.head == NULL) {
 4544-		_RGFW->monitors.list.head = node;
 4545-	} else {
 4546-		_RGFW->monitors.list.cur->next = node;
 4547-	}
 4548-
 4549-	_RGFW->monitors.list.cur = node;
 4550-
 4551-	if (mon) node->mon = *mon;
 4552-	node->mon.node = node;
 4553-	node->disconnected = RGFW_FALSE;
 4554-
 4555-	_RGFW->monitors.count += 1;
 4556-	return node;
 4557-}
 4558-
 4559-void RGFW_monitors_remove(RGFW_monitorNode* node, RGFW_monitorNode* prev) {
 4560-	_RGFW->monitors.count -= 1;
 4561-
 4562-	/* remove node from the list */
 4563-	if (prev != node) {
 4564-		prev->next = node->next;
 4565-	} else { /* node is the head */
 4566-		_RGFW->monitors.list.head = NULL;
 4567-	}
 4568-
 4569-	node->next = NULL;
 4570-
 4571-	#if (RGFW_PREALLOCATED_MONITORS)
 4572-	/* check if the monitor was allocated in the heap or not */
 4573-	if (node >= _RGFW->monitors.data && node <= &_RGFW->monitors.data[RGFW_PREALLOCATED_MONITORS - 1]) {
 4574-		/* move node to the free list */
 4575-		if (_RGFW->monitors.freeList.head == NULL) {
 4576-			_RGFW->monitors.freeList.head = node;
 4577-		} else {
 4578-			_RGFW->monitors.freeList.cur->next = node;
 4579-		}
 4580-
 4581-		_RGFW->monitors.freeList.cur = node;
 4582-	} else
 4583-	{
 4584-	#elif !defined(RGFW_NO_ALLOCATE_MONITORS)
 4585-		RGFW_FREE(node);
 4586-	#endif
 4587-	}
 4588-}
 4589-
 4590-void RGFW_monitors_refresh(void) {
 4591-	RGFW_monitorNode* prev = _RGFW->monitors.list.head;
 4592-	for (RGFW_monitorNode* node = _RGFW->monitors.list.head; node; node = node->next) {
 4593-		if (node->disconnected == RGFW_FALSE) continue;
 4594-
 4595-		RGFW_monitorCallback(_RGFW->root, &node->mon, RGFW_FALSE);
 4596-		RGFW_monitors_remove(node, prev);
 4597-		prev = node;
 4598-	}
 4599-}
 4600-
 4601-RGFW_monitorMode* RGFW_monitor_getModes(RGFW_monitor* monitor, size_t* count) {
 4602-	size_t num = RGFW_monitor_getModesPtr(monitor, NULL);
 4603-	RGFW_monitorMode* modes = (RGFW_monitorMode*)RGFW_ALLOC(num * sizeof(RGFW_monitorNode));
 4604-	num = RGFW_monitor_getModesPtr(monitor, &modes);
 4605-
 4606-	if (count) *count = num;
 4607-	return modes;
 4608-}
 4609-
 4610-void RGFW_freeModes(RGFW_monitorMode* modes) {
 4611-	RGFW_FREE(modes);
 4612-}
 4613-
 4614-RGFW_bool RGFW_monitor_findClosestMode(RGFW_monitor* monitor, RGFW_monitorMode* mode, RGFW_monitorMode* closest) {
 4615-	size_t count = RGFW_monitor_getModesPtr(monitor, NULL);
 4616-	RGFW_monitorMode* modes = (RGFW_monitorMode*)RGFW_ALLOC(count * sizeof(RGFW_monitorNode));
 4617-	count = RGFW_monitor_getModesPtr(monitor, &modes);
 4618-
 4619-	RGFW_monitorMode* chosen = NULL;
 4620-
 4621-	u32 topScore = 1;
 4622-	for (size_t i = 0; i < count; i++) {
 4623-		RGFW_monitorMode* mode2 = &modes[i];
 4624-
 4625-		u32 score = 0;
 4626-		if (mode->w == mode2->w && mode->h == mode2->h) score += 1000;
 4627-		if (mode->red == mode2->red && mode->green == mode2->green && mode->blue == mode2->blue) score += 100;
 4628-		if (mode->refreshRate == mode->refreshRate) score += 10;
 4629-
 4630-		if (score > topScore) {
 4631-			topScore = score;
 4632-			chosen = mode2;
 4633-		}
 4634-	}
 4635-
 4636-	if (chosen && closest) *closest = *chosen;
 4637-
 4638-
 4639-	RGFW_FREE(modes);
 4640-
 4641-	return (chosen == NULL) ? RGFW_FALSE : RGFW_TRUE;
 4642-}
 4643-
 4644-RGFW_bool RGFW_monitor_getPosition(RGFW_monitor* monitor, i32* x, i32* y) {
 4645-	if (x) *x = monitor->x;
 4646-	if (y) *y = monitor->y;
 4647-	return RGFW_TRUE;
 4648-}
 4649-
 4650-const char* RGFW_monitor_getName(RGFW_monitor* monitor) {
 4651-	return monitor->name;
 4652-}
 4653-
 4654-RGFW_bool RGFW_monitor_getScale(RGFW_monitor* monitor, float* x, float* y) {
 4655-	if (x) *x = monitor->scaleX;
 4656-	if (y) *y = monitor->scaleY;
 4657-	return RGFW_TRUE;
 4658-}
 4659-
 4660-RGFW_bool RGFW_monitor_getPhysicalSize(RGFW_monitor* monitor, float* w, float* h) {
 4661-	if (w) *w = monitor->physW;
 4662-	if (h) *h = monitor->physH;
 4663-	return RGFW_TRUE;
 4664-}
 4665-
 4666-void RGFW_monitor_setUserPtr(RGFW_monitor* monitor, void* userPtr) {
 4667-	monitor->userPtr = userPtr;
 4668-}
 4669-
 4670-void* RGFW_monitor_getUserPtr(RGFW_monitor* monitor) {
 4671-	return monitor->userPtr;
 4672-}
 4673-
 4674-RGFW_bool RGFW_monitor_getMode(RGFW_monitor* monitor, RGFW_monitorMode* mode) {
 4675-	if (mode) *mode = monitor->mode;
 4676-	return RGFW_TRUE;
 4677-}
 4678-
 4679-RGFW_gammaRamp* RGFW_monitor_getGammaRamp(RGFW_monitor* monitor) {
 4680-	RGFW_gammaRamp* ramp = (RGFW_gammaRamp*)RGFW_ALLOC(sizeof(RGFW_gammaRamp));
 4681-	ramp->count = RGFW_monitor_getGammaRampPtr(monitor, NULL);
 4682-	ramp->red = (u16*)RGFW_ALLOC(sizeof(u16) * ramp->count);
 4683-	ramp->green = (u16*)RGFW_ALLOC(sizeof(u16) * ramp->count);
 4684-	ramp->blue = (u16*)RGFW_ALLOC(sizeof(u16) * ramp->count);
 4685-	ramp->count = RGFW_monitor_getGammaRampPtr(monitor, ramp);
 4686-
 4687-	return ramp;
 4688-}
 4689-
 4690-void RGFW_freeGammaRamp(RGFW_gammaRamp* ramp) {
 4691-	RGFW_FREE(ramp->red);
 4692-	RGFW_FREE(ramp->green);
 4693-	RGFW_FREE(ramp->blue);
 4694-	RGFW_FREE(ramp);
 4695-}
 4696-
 4697-RGFW_bool RGFW_monitor_setGammaPtr(RGFW_monitor* monitor, float gamma, u16* ptr, size_t count) {
 4698-	RGFW_ASSERT(monitor);
 4699-    RGFW_ASSERT(gamma > 0.0f);
 4700-
 4701-	size_t i;
 4702-    for (i = 0;  i < count;  i++) {
 4703-        float value = (float)i / (float) (count - 1);
 4704-		#ifndef RGFW_NO_MATH
 4705-			value = powf(value, 1.f / gamma) * 65535.f + 0.5f;
 4706-		#endif
 4707-        value = RGFW_MIN(value, 65535.f);
 4708-
 4709-        ptr[i] = (u16)value;
 4710-    }
 4711-
 4712-    RGFW_gammaRamp ramp;
 4713-    ramp.red = ptr;
 4714-    ramp.green = ptr;
 4715-    ramp.blue = ptr;
 4716-    ramp.count = count;
 4717-
 4718-    return RGFW_monitor_setGammaRamp(monitor, &ramp);
 4719-}
 4720-
 4721-RGFW_bool RGFW_monitor_setGamma(RGFW_monitor* monitor, float gamma) {
 4722-	size_t count = RGFW_monitor_getGammaRampPtr(monitor, NULL);
 4723-	u16* ptr = (u16*)RGFW_ALLOC(count * sizeof(u16));
 4724-
 4725-	RGFW_bool ret = RGFW_monitor_setGammaPtr(monitor, gamma, ptr, count);
 4726-	RGFW_FREE(ptr);
 4727-
 4728-	return ret;
 4729-}
 4730-
 4731-RGFW_monitor** RGFW_getMonitors(size_t* len) {
 4732-	if (len != NULL) *len = 0;
 4733-
 4734-	size_t count = 0;
 4735-	if (RGFW_getMonitorsPtr(0, NULL, &count) == RGFW_FALSE || count == 0) return NULL;
 4736-
 4737-	RGFW_monitor** monitors = (RGFW_monitor**)RGFW_ALLOC(sizeof(RGFW_monitor*) * count);
 4738-
 4739-	if (RGFW_getMonitorsPtr(count, monitors, &count) == RGFW_FALSE) {
 4740-		RGFW_FREE(monitors);
 4741-		return NULL;
 4742-	}
 4743-
 4744-	if (len != NULL) *len = count;
 4745-
 4746-	return monitors;
 4747-}
 4748-
 4749-RGFW_bool RGFW_getMonitorsPtr(size_t max, RGFW_monitor** monitors, size_t* len) {
 4750-	RGFW_init();
 4751-	if (len != NULL) {
 4752-		*len = _RGFW->monitors.count;
 4753-	}
 4754-
 4755-	if (monitors == NULL || max == 0) return RGFW_TRUE;
 4756-
 4757-
 4758-	if (len != NULL) {
 4759-		*len = max;
 4760-	}
 4761-
 4762-	size_t i = 0;
 4763-	RGFW_monitorNode* cur_node = _RGFW->monitors.list.head;
 4764-	while (cur_node != NULL && i < max) {
 4765-		monitors[i] = &cur_node->mon;
 4766-		i++;
 4767-		cur_node = cur_node->next;
 4768-	}
 4769-
 4770-	return RGFW_TRUE;
 4771-}
 4772-
 4773-RGFW_monitor* RGFW_getPrimaryMonitor(void) {
 4774-	if (_RGFW->monitors.primary == NULL) {
 4775-		_RGFW->monitors.primary = _RGFW->monitors.list.head;
 4776-	}
 4777-
 4778-	return &_RGFW->monitors.primary->mon;
 4779-}
 4780-
 4781-RGFW_bool RGFW_window_setIcon(RGFW_window* win, u8* data, i32 w, i32 h, RGFW_format format) {
 4782-	return RGFW_window_setIconEx(win, data, w, h, format, RGFW_iconBoth);
 4783-}
 4784-
 4785-void RGFW_window_captureMouse(RGFW_window* win, RGFW_bool state) {
 4786-	win->internal.captureMouse = state;
 4787-	RGFW_window_captureMousePlatform(win, state);
 4788-}
 4789-
 4790-void RGFW_window_setRawMouseMode(RGFW_window* win, RGFW_bool state) {
 4791-	win->internal.rawMouse = state;
 4792-	RGFW_window_setRawMouseModePlatform(win, state);
 4793-}
 4794-
 4795-void RGFW_window_captureRawMouse(RGFW_window* win, RGFW_bool state) {
 4796-	RGFW_window_captureMouse(win, state);
 4797-	RGFW_window_setRawMouseMode(win, state);
 4798-}
 4799-
 4800-RGFW_bool RGFW_window_isRawMouseMode(RGFW_window* win) { return RGFW_BOOL(win->internal.rawMouse); }
 4801-RGFW_bool RGFW_window_isCaptured(RGFW_window* win) { return RGFW_BOOL(win->internal.captureMouse);  }
 4802-
 4803-void RGFW_keyUpdateKeyMod(RGFW_window* win, RGFW_keymod mod, RGFW_bool value) {
 4804-	if (value) win->internal.mod |= mod;
 4805-	else win->internal.mod &= ~mod;
 4806-}
 4807-
 4808-void RGFW_keyUpdateKeyModsEx(RGFW_window* win, RGFW_bool capital, RGFW_bool numlock, RGFW_bool control, RGFW_bool alt, RGFW_bool shift, RGFW_bool super, RGFW_bool scroll) {
 4809-	RGFW_keyUpdateKeyMod(win, RGFW_modCapsLock, capital);
 4810-	RGFW_keyUpdateKeyMod(win, RGFW_modNumLock, numlock);
 4811-	RGFW_keyUpdateKeyMod(win, RGFW_modControl, control);
 4812-	RGFW_keyUpdateKeyMod(win, RGFW_modAlt, alt);
 4813-	RGFW_keyUpdateKeyMod(win, RGFW_modShift, shift);
 4814-	RGFW_keyUpdateKeyMod(win, RGFW_modSuper, super);
 4815-	RGFW_keyUpdateKeyMod(win, RGFW_modScrollLock, scroll);
 4816-}
 4817-
 4818-void RGFW_keyUpdateKeyMods(RGFW_window* win, RGFW_bool capital, RGFW_bool numlock, RGFW_bool scroll) {
 4819-	RGFW_keyUpdateKeyModsEx(win, capital, numlock,
 4820-					RGFW_isKeyDown(RGFW_keyControlL) || RGFW_isKeyDown(RGFW_keyControlR),
 4821-					RGFW_isKeyDown(RGFW_keyAltL) || RGFW_isKeyDown(RGFW_keyAltR),
 4822-					RGFW_isKeyDown(RGFW_keyShiftL) || RGFW_isKeyDown(RGFW_keyShiftR),
 4823-					RGFW_isKeyDown(RGFW_keySuperL) || RGFW_isKeyDown(RGFW_keySuperR),
 4824-					scroll);
 4825-}
 4826-
 4827-void RGFW_window_showMouseFlags(RGFW_window* win, RGFW_bool show) {
 4828-	if (show && (win->internal.flags & RGFW_windowHideMouse))
 4829-		win->internal.flags ^= RGFW_windowHideMouse;
 4830-	else if (!show && !(win->internal.flags & RGFW_windowHideMouse))
 4831-		win->internal.flags |= RGFW_windowHideMouse;
 4832-}
 4833-
 4834-RGFW_bool RGFW_window_isMouseHidden(RGFW_window* win) {
 4835-	return (RGFW_bool)RGFW_BOOL(((RGFW_window*)win)->internal.flags & RGFW_windowHideMouse);
 4836-}
 4837-
 4838-RGFW_bool RGFW_window_borderless(RGFW_window* win) {
 4839-	return (RGFW_bool)RGFW_BOOL(win->internal.flags & RGFW_windowNoBorder);
 4840-}
 4841-
 4842-RGFW_bool RGFW_window_isFullscreen(RGFW_window* win){ return RGFW_BOOL(win->internal.flags & RGFW_windowFullscreen); }
 4843-RGFW_bool RGFW_window_allowsDND(RGFW_window* win) { return RGFW_BOOL(win->internal.flags & RGFW_windowAllowDND); }
 4844-
 4845-RGFW_bool RGFW_window_setMouseDefault(RGFW_window* win) {
 4846-	return RGFW_window_setMouseStandard(win, RGFW_mouseNormal);
 4847-}
 4848-
 4849-RGFW_bool RGFW_window_setMouseStandard(RGFW_window* win, RGFW_mouseIcon icon) {
 4850-	RGFW_ASSERT(win);
 4851-	RGFW_ASSERT(icon < RGFW_mouseIconCount);
 4852-	return RGFW_window_setMouse(win, _RGFW->standardMice[icon]);
 4853-}
 4854-
 4855-RGFW_bool RGFW_window_setMouse(RGFW_window* win, RGFW_mouse* mouse) {
 4856-	RGFW_ASSERT(win && mouse);
 4857-	if (mouse != _RGFW->hiddenMouse) {
 4858-		win->internal.mouse = mouse;
 4859-	}
 4860-
 4861-	return RGFW_window_setMousePlatform(win, mouse);
 4862-}
 4863-
 4864-#ifndef RGFW_WINDOWS
 4865-void RGFW_window_setDND(RGFW_window* win, RGFW_bool allow) {
 4866-	RGFW_setBit(&win->internal.flags, RGFW_windowAllowDND, allow);
 4867-}
 4868-#endif
 4869-
 4870-#if defined(RGFW_X11) || defined(RGFW_MACOS) || defined(RGFW_WASM) || defined(RGFW_WAYLAND)
 4871-#ifndef __USE_POSIX199309
 4872-	#define __USE_POSIX199309
 4873-#endif
 4874-#include <time.h>
 4875-struct timespec;
 4876-#endif
 4877-
 4878-#if defined(RGFW_WAYLAND) || defined(RGFW_X11) || defined(RGFW_WINDOWS)
 4879-void RGFW_window_showMouse(RGFW_window* win, RGFW_bool show) {
 4880-	RGFW_window_showMouseFlags(win, show);
 4881-	if (show == RGFW_FALSE) {
 4882-		RGFW_window_setMouse(win, _RGFW->hiddenMouse);
 4883-	} else {
 4884-		RGFW_window_setMouse(win, win->internal.mouse);
 4885-	}
 4886-}
 4887-#endif
 4888-
 4889-#ifndef RGFW_MACOS
 4890-void RGFW_moveToMacOSResourceDir(void) { }
 4891-#endif
 4892-
 4893-RGFWDEF RGFW_bool RGFW_isLatin(const char *string, size_t length);
 4894-RGFW_bool RGFW_isLatin(const char *string, size_t length) {
 4895-	for (size_t i = 0; i < length; i++) {
 4896-        if ((u8)string[i] >= 0x80) {
 4897-            return RGFW_TRUE;
 4898-        }
 4899-    }
 4900-    return RGFW_FALSE;
 4901-}
 4902-
 4903-RGFWDEF u32 RGFW_decodeUTF8(const char* string, size_t* starting_index);
 4904-u32 RGFW_decodeUTF8(const char* string, size_t* starting_index) {
 4905-    static const u32 offsets[] = {
 4906-        0x00000000u, 0x00003080u, 0x000e2080u,
 4907-        0x03c82080u, 0xfa082080u, 0x82082080u
 4908-    };
 4909-
 4910-    u32 codepoint = (u8)string[(*starting_index)];
 4911-	size_t count;
 4912-	for (count = 1; (string[count + (*starting_index)] & 0xc0) == 0x80; count++) {
 4913-        codepoint = (codepoint << 6) + (u8)string[count + (*starting_index)];
 4914-	}
 4915-
 4916-	*starting_index += count;
 4917-
 4918-    RGFW_ASSERT(count <= 6);
 4919-    return codepoint - offsets[count - 1];
 4920-}
 4921-
 4922-/*
 4923-	graphics API specific code (end of generic code)
 4924-	starts here
 4925-*/
 4926-
 4927-
 4928-/*
 4929-	OpenGL defines start here   (Normal, EGL, OSMesa)
 4930-*/
 4931-
 4932-#if defined(RGFW_OPENGL)
 4933-/* EGL, OpenGL */
 4934-#define RGFW_DEFAULT_GL_HINTS { \
 4935-	/* Stencil         */ 0, \
 4936-	/* Samples         */ 0, \
 4937-	/* Stereo          */ RGFW_FALSE, \
 4938-	/* AuxBuffers      */ 0, \
 4939-	/* DoubleBuffer    */ RGFW_TRUE, \
 4940-	/* Red             */ 8, \
 4941-	/* Green           */ 8, \
 4942-	/* Blue            */ 8, \
 4943-	/* Alpha           */ 8, \
 4944-	/* Depth           */ 24, \
 4945-	/* AccumRed        */ 0, \
 4946-	/* AccumGreen      */ 0, \
 4947-	/* AccumBlue       */ 0, \
 4948-	/* AccumAlpha      */ 0, \
 4949-	/* SRGB            */ RGFW_FALSE, \
 4950-	/* Robustness      */ RGFW_FALSE, \
 4951-	/* Debug           */ RGFW_FALSE, \
 4952-	/* NoError         */ RGFW_FALSE, \
 4953-	/* ReleaseBehavior */ RGFW_glReleaseNone, \
 4954-	/* Profile         */ RGFW_glCore, \
 4955-	/* Major           */ 1, \
 4956-	/* Minor           */ 0, \
 4957-	/* Share */ NULL, \
 4958-	/* Share_EGL */ NULL, \
 4959-	/* renderer */ RGFW_glAccelerated \
 4960-}
 4961-
 4962-RGFW_glHints RGFW_globalHints_OpenGL_SRC = RGFW_DEFAULT_GL_HINTS;
 4963-RGFW_glHints* RGFW_globalHints_OpenGL = &RGFW_globalHints_OpenGL_SRC;
 4964-
 4965-void RGFW_resetGlobalHints_OpenGL(void) {
 4966-#if !defined(__cplusplus) || defined(RGFW_MACOS)
 4967-	RGFW_globalHints_OpenGL_SRC = (RGFW_glHints)RGFW_DEFAULT_GL_HINTS;
 4968-#else
 4969-	RGFW_globalHints_OpenGL_SRC = RGFW_DEFAULT_GL_HINTS;
 4970-#endif
 4971-}
 4972-void RGFW_setGlobalHints_OpenGL(RGFW_glHints* hints) { RGFW_globalHints_OpenGL = hints;  }
 4973-RGFW_glHints* RGFW_getGlobalHints_OpenGL(void) { RGFW_init(); return RGFW_globalHints_OpenGL; }
 4974-
 4975-
 4976-void* RGFW_glContext_getSourceContext(RGFW_glContext* ctx) {
 4977-	RGFW_UNUSED(ctx);
 4978-
 4979-#ifdef RGFW_WAYLAND
 4980-	if (RGFW_usingWayland()) return (void*)ctx->egl.ctx;
 4981-#endif
 4982-
 4983-#if defined(RGFW_X11)
 4984-	return (void*)ctx->ctx;
 4985-#else
 4986-	return NULL;
 4987-#endif
 4988-}
 4989-
 4990-RGFW_glContext* RGFW_window_createContext_OpenGL(RGFW_window* win, RGFW_glHints* hints) {
 4991-	#ifdef RGFW_WAYLAND
 4992-	if (RGFW_usingWayland()) {
 4993-		return (RGFW_glContext*)RGFW_window_createContext_EGL(win, hints);
 4994-	}
 4995-	#endif
 4996-	RGFW_glContext* ctx = (RGFW_glContext*)RGFW_ALLOC(sizeof(RGFW_glContext));
 4997-	if (RGFW_window_createContextPtr_OpenGL(win, ctx, hints) == RGFW_FALSE) {
 4998-		RGFW_FREE(ctx);
 4999-		win->src.ctx.native = NULL;
 5000-		return NULL;
 5001-	}
 5002-	win->src.gfxType |= RGFW_gfxOwnedByRGFW;
 5003-	return ctx;
 5004-}
 5005-
 5006-RGFW_glContext* RGFW_window_getContext_OpenGL(RGFW_window* win) {
 5007-	if (win->src.gfxType & RGFW_windowEGL) return NULL;
 5008-	return win->src.ctx.native;
 5009-}
 5010-
 5011-void RGFW_window_deleteContext_OpenGL(RGFW_window* win, RGFW_glContext* ctx) {
 5012-	RGFW_window_deleteContextPtr_OpenGL(win, ctx);
 5013-	if (win->src.gfxType & RGFW_gfxOwnedByRGFW) RGFW_FREE(ctx);
 5014-}
 5015-
 5016-RGFW_bool RGFW_extensionSupportedStr(const char* extensions, const char* ext, size_t len) {
 5017-    const char *start = extensions;
 5018-    const char *where;
 5019-    const char* terminator;
 5020-
 5021-    if (extensions == NULL || ext == NULL) {
 5022-        return RGFW_FALSE;
 5023-	}
 5024-
 5025-	while (ext[len - 1] == '\0' && len > 3) {
 5026-		len--;
 5027-	}
 5028-
 5029-    where = RGFW_STRSTR(extensions, ext);
 5030-    while (where) {
 5031-		terminator = where + len;
 5032-        if ((where == start || *(where - 1) == ' ') &&
 5033-            (*terminator == ' ' || *terminator == '\0')) {
 5034-			return RGFW_TRUE;
 5035-        }
 5036-        where = RGFW_STRSTR(terminator, ext);
 5037-    }
 5038-
 5039-    return RGFW_FALSE;
 5040-}
 5041-
 5042-RGFWDEF RGFW_bool RGFW_extensionSupported_base(const char* extension, size_t len);
 5043-RGFW_bool RGFW_extensionSupported_base(const char* extension, size_t len) {
 5044-    #ifdef GL_NUM_EXTENSIONS
 5045-    if (RGFW_globalHints_OpenGL->major >= 3) {
 5046-        i32 i;
 5047-
 5048-        GLint count = 0;
 5049-
 5050-        RGFW_proc RGFW_glGetStringi = RGFW_getProcAddress_OpenGL("glGetStringi");
 5051-        RGFW_proc RGFW_glGetIntegerv = RGFW_getProcAddress_OpenGL("glGetIntegerv");
 5052-		if (RGFW_glGetIntegerv)
 5053-            ((void(*)(GLenum, GLint*))RGFW_glGetIntegerv)(GL_NUM_EXTENSIONS, &count);
 5054-
 5055-        for (i = 0; RGFW_glGetStringi && i < count;  i++) {
 5056-            const char* en = ((const char* (*)(u32, u32))RGFW_glGetStringi)(GL_EXTENSIONS, (u32)i);
 5057-            if (en && RGFW_STRNCMP(en, extension, len) == 0) {
 5058-				return RGFW_TRUE;
 5059-			}
 5060-        }
 5061-    } else
 5062-#endif
 5063-    {
 5064-        RGFW_proc RGFW_glGetString = RGFW_getProcAddress_OpenGL("glGetString");
 5065-		#define RGFW_GL_EXTENSIONS 0x1F03
 5066-        if (RGFW_glGetString) {
 5067-            const char* extensions = ((const char*(*)(u32))RGFW_glGetString)(RGFW_GL_EXTENSIONS);
 5068-
 5069-            if ((extensions != NULL) && RGFW_extensionSupportedStr(extensions, extension, len)) {
 5070-				return RGFW_TRUE;
 5071-			}
 5072-        }
 5073-    }
 5074-	return RGFW_FALSE;
 5075-}
 5076-
 5077-RGFW_bool RGFW_extensionSupported_OpenGL(const char* extension, size_t len) {
 5078-	if (RGFW_extensionSupported_base(extension, len))  return RGFW_TRUE;
 5079-    return RGFW_extensionSupportedPlatform_OpenGL(extension, len);
 5080-}
 5081-
 5082-void RGFW_window_makeCurrentWindow_OpenGL(RGFW_window* win) {
 5083-	if (win) {
 5084-		_RGFW->current = win;
 5085-	}
 5086-
 5087-    RGFW_window_makeCurrentContext_OpenGL(win);
 5088-}
 5089-
 5090-RGFW_window* RGFW_getCurrentWindow_OpenGL(void) { return _RGFW->current; }
 5091-void RGFW_attribStack_init(RGFW_attribStack* stack, i32* attribs, size_t max) { stack->attribs = attribs; stack->count = 0; stack->max = max; }
 5092-void RGFW_attribStack_pushAttrib(RGFW_attribStack* stack, i32 attrib) {
 5093-	RGFW_ASSERT(stack->count < stack->max);
 5094-	stack->attribs[stack->count] = attrib;
 5095-	stack->count += 1;
 5096-}
 5097-void RGFW_attribStack_pushAttribs(RGFW_attribStack* stack, i32 attrib1, i32 attrib2) {
 5098-	RGFW_attribStack_pushAttrib(stack, attrib1);
 5099-	RGFW_attribStack_pushAttrib(stack, attrib2);
 5100-}
 5101-
 5102-/* EGL */
 5103-#ifdef RGFW_EGL
 5104-#include <EGL/egl.h>
 5105-
 5106-PFNEGLINITIALIZEPROC RGFW_eglInitialize;
 5107-PFNEGLGETCONFIGSPROC RGFW_eglGetConfigs;
 5108-PFNEGLCHOOSECONFIGPROC RGFW_eglChooseConfig;
 5109-PFNEGLCREATEWINDOWSURFACEPROC RGFW_eglCreateWindowSurface;
 5110-PFNEGLCREATECONTEXTPROC RGFW_eglCreateContext;
 5111-PFNEGLMAKECURRENTPROC RGFW_eglMakeCurrent;
 5112-PFNEGLGETDISPLAYPROC RGFW_eglGetDisplay;
 5113-PFNEGLSWAPBUFFERSPROC RGFW_eglSwapBuffers;
 5114-PFNEGLSWAPINTERVALPROC RGFW_eglSwapInterval;
 5115-PFNEGLBINDAPIPROC RGFW_eglBindAPI;
 5116-PFNEGLDESTROYCONTEXTPROC RGFW_eglDestroyContext;
 5117-PFNEGLTERMINATEPROC RGFW_eglTerminate;
 5118-PFNEGLDESTROYSURFACEPROC RGFW_eglDestroySurface;
 5119-PFNEGLGETCURRENTCONTEXTPROC RGFW_eglGetCurrentContext;
 5120-PFNEGLGETPROCADDRESSPROC RGFW_eglGetProcAddress = NULL;
 5121-PFNEGLQUERYSTRINGPROC RGFW_eglQueryString;
 5122-PFNEGLGETCONFIGATTRIBPROC RGFW_eglGetConfigAttrib;
 5123-
 5124-#define EGL_SURFACE_MAJOR_VERSION_KHR 0x3098
 5125-#define EGL_SURFACE_MINOR_VERSION_KHR 0x30fb
 5126-
 5127-#ifdef RGFW_WINDOWS
 5128-    #include <windows.h>
 5129-#elif defined(RGFW_MACOS) || defined(RGFW_UNIX)
 5130-    #include <dlfcn.h>
 5131-#endif
 5132-
 5133-#ifdef RGFW_WAYLAND
 5134-#include <wayland-egl.h>
 5135-#endif
 5136-
 5137-void* RGFW_eglLibHandle = NULL;
 5138-
 5139-void* RGFW_getDisplay_EGL(void) { return _RGFW->EGL_display; }
 5140-void* RGFW_eglContext_getSourceContext(RGFW_eglContext* ctx) { return ctx->ctx; }
 5141-void* RGFW_eglContext_getSurface(RGFW_eglContext* ctx) { return ctx->surface; }
 5142-struct wl_egl_window* RGFW_eglContext_wlEGLWindow(RGFW_eglContext* ctx) { return ctx->eglWindow; }
 5143-
 5144-RGFW_bool RGFW_loadEGL(void) {
 5145-	RGFW_init();
 5146-	if (RGFW_eglGetProcAddress != NULL) {
 5147-		return RGFW_TRUE;
 5148-	}
 5149-
 5150-#ifndef RGFW_WASM
 5151-	#ifdef RGFW_WINDOWS
 5152-		const char* libNames[] = { "libEGL.dll", "EGL.dll" };
 5153-	#elif defined(RGFW_MACOS) || defined(RGFW_UNIX)
 5154-		/* Linux and macOS */
 5155-		const char* libNames[] = {
 5156-			"libEGL.so.1",  /* most common */
 5157-			"libEGL.so",    /* fallback */
 5158-			"/System/Library/Frameworks/OpenGL.framework/OpenGL"  /* fallback for older macOS EGL-like systems */
 5159-		};
 5160-	#endif
 5161-
 5162-	for (size_t i = 0; i < sizeof(libNames) / sizeof(libNames[0]); i++) {
 5163-		#ifdef RGFW_WINDOWS
 5164-			RGFW_eglLibHandle = (void*)LoadLibraryA(libNames[i]);
 5165-			if (RGFW_eglLibHandle) {
 5166-				RGFW_eglGetProcAddress = (PFNEGLGETPROCADDRESSPROC)(RGFW_proc)GetProcAddress((HMODULE)RGFW_eglLibHandle, "eglGetProcAddress");
 5167-				break;
 5168-			}
 5169-		#elif defined(RGFW_MACOS) || defined(RGFW_UNIX)
 5170-			RGFW_eglLibHandle = dlopen(libNames[i], RTLD_LAZY | RTLD_GLOBAL);
 5171-			if (RGFW_eglLibHandle) {
 5172-				void* lib = dlsym(RGFW_eglLibHandle, "eglGetProcAddress");
 5173-				if (lib != NULL) RGFW_MEMCPY(&RGFW_eglGetProcAddress, &lib, sizeof(PFNEGLGETPROCADDRESSPROC));
 5174-				break;
 5175-			}
 5176-		#endif
 5177-	}
 5178-
 5179-	if (!RGFW_eglLibHandle || !RGFW_eglGetProcAddress) {
 5180-		return RGFW_FALSE;
 5181-	}
 5182-
 5183-	RGFW_eglInitialize = (PFNEGLINITIALIZEPROC) RGFW_eglGetProcAddress("eglInitialize");
 5184-	RGFW_eglGetConfigs = (PFNEGLGETCONFIGSPROC) RGFW_eglGetProcAddress("eglGetConfigs");
 5185-	RGFW_eglChooseConfig = (PFNEGLCHOOSECONFIGPROC) RGFW_eglGetProcAddress("eglChooseConfig");
 5186-	RGFW_eglCreateWindowSurface = (PFNEGLCREATEWINDOWSURFACEPROC) RGFW_eglGetProcAddress("eglCreateWindowSurface");
 5187-	RGFW_eglCreateContext = (PFNEGLCREATECONTEXTPROC) RGFW_eglGetProcAddress("eglCreateContext");
 5188-	RGFW_eglMakeCurrent = (PFNEGLMAKECURRENTPROC) RGFW_eglGetProcAddress("eglMakeCurrent");
 5189-	RGFW_eglGetDisplay = (PFNEGLGETDISPLAYPROC) RGFW_eglGetProcAddress("eglGetDisplay");
 5190-	RGFW_eglSwapBuffers = (PFNEGLSWAPBUFFERSPROC) RGFW_eglGetProcAddress("eglSwapBuffers");
 5191-	RGFW_eglSwapInterval = (PFNEGLSWAPINTERVALPROC) RGFW_eglGetProcAddress("eglSwapInterval");
 5192-	RGFW_eglBindAPI = (PFNEGLBINDAPIPROC) RGFW_eglGetProcAddress("eglBindAPI");
 5193-	RGFW_eglDestroyContext = (PFNEGLDESTROYCONTEXTPROC) RGFW_eglGetProcAddress("eglDestroyContext");
 5194-	RGFW_eglTerminate = (PFNEGLTERMINATEPROC) RGFW_eglGetProcAddress("eglTerminate");
 5195-	RGFW_eglDestroySurface = (PFNEGLDESTROYSURFACEPROC) RGFW_eglGetProcAddress("eglDestroySurface");
 5196-	RGFW_eglQueryString = (PFNEGLQUERYSTRINGPROC) RGFW_eglGetProcAddress("eglQueryString");
 5197-	RGFW_eglGetCurrentContext = (PFNEGLGETCURRENTCONTEXTPROC) RGFW_eglGetProcAddress("eglGetCurrentContext");
 5198-	RGFW_eglGetConfigAttrib = (PFNEGLGETCONFIGATTRIBPROC) RGFW_eglGetProcAddress("eglGetConfigAttrib");
 5199-
 5200-#else
 5201-	RGFW_eglGetProcAddress = eglGetProcAddress;
 5202-	RGFW_eglInitialize = (PFNEGLINITIALIZEPROC) eglInitialize;
 5203-	RGFW_eglGetConfigs = (PFNEGLGETCONFIGSPROC) eglGetConfigs;
 5204-	RGFW_eglChooseConfig = (PFNEGLCHOOSECONFIGPROC) eglChooseConfig;
 5205-	RGFW_eglCreateWindowSurface = (PFNEGLCREATEWINDOWSURFACEPROC) eglCreateWindowSurface;
 5206-	RGFW_eglCreateContext = (PFNEGLCREATECONTEXTPROC) eglCreateContext;
 5207-	RGFW_eglMakeCurrent = (PFNEGLMAKECURRENTPROC) eglMakeCurrent;
 5208-	RGFW_eglGetDisplay = (PFNEGLGETDISPLAYPROC) eglGetDisplay;
 5209-	RGFW_eglSwapBuffers = (PFNEGLSWAPBUFFERSPROC) eglSwapBuffers;
 5210-	RGFW_eglSwapInterval = (PFNEGLSWAPINTERVALPROC) eglSwapInterval;
 5211-	RGFW_eglBindAPI = (PFNEGLBINDAPIPROC) eglBindAPI;
 5212-	RGFW_eglDestroyContext = (PFNEGLDESTROYCONTEXTPROC) eglDestroyContext;
 5213-	RGFW_eglTerminate = (PFNEGLTERMINATEPROC) eglTerminate;
 5214-	RGFW_eglDestroySurface = (PFNEGLDESTROYSURFACEPROC) eglDestroySurface;
 5215-	RGFW_eglQueryString = (PFNEGLQUERYSTRINGPROC) eglQueryString;
 5216-	RGFW_eglGetCurrentContext = (PFNEGLGETCURRENTCONTEXTPROC) eglGetCurrentContext;
 5217-	RGFW_eglGetConfigAttrib = (PFNEGLGETCONFIGATTRIBPROC)eglGetConfigAttrib;
 5218-#endif
 5219-
 5220-	RGFW_bool out = RGFW_BOOL(RGFW_eglInitialize!= NULL &&
 5221-	            RGFW_eglGetConfigs!= NULL &&
 5222-	            RGFW_eglChooseConfig!= NULL &&
 5223-	            RGFW_eglCreateWindowSurface!= NULL &&
 5224-	            RGFW_eglCreateContext!= NULL &&
 5225-	            RGFW_eglMakeCurrent!= NULL &&
 5226-	            RGFW_eglGetDisplay!= NULL &&
 5227-	            RGFW_eglSwapBuffers!= NULL &&
 5228-	            RGFW_eglSwapInterval != NULL &&
 5229-	            RGFW_eglBindAPI!= NULL &&
 5230-	            RGFW_eglDestroyContext!= NULL &&
 5231-	            RGFW_eglTerminate!= NULL &&
 5232-	            RGFW_eglDestroySurface!= NULL &&
 5233-				RGFW_eglQueryString != NULL &&
 5234-				RGFW_eglGetCurrentContext != NULL &&
 5235-				RGFW_eglGetConfigAttrib != NULL);
 5236-
 5237-	if (out) {
 5238-		#ifdef RGFW_WINDOWS
 5239-		HDC dc = GetDC(NULL);
 5240-		_RGFW->EGL_display = RGFW_eglGetDisplay((EGLNativeDisplayType) dc);
 5241-		ReleaseDC(NULL, dc);
 5242-		#elif defined(RGFW_WAYLAND)
 5243-		if (_RGFW->useWaylandBool)
 5244-			_RGFW->EGL_display = RGFW_eglGetDisplay((EGLNativeDisplayType) _RGFW->wl_display);
 5245-		else
 5246-		#endif
 5247-		#ifdef RGFW_X11
 5248-			_RGFW->EGL_display = RGFW_eglGetDisplay((EGLNativeDisplayType) _RGFW->display);
 5249-		#else
 5250-		{}
 5251-		#endif
 5252-		#if !defined(RGFW_WAYLAND) && !defined(RGFW_WINDOWS) && !defined(RGFW_X11)
 5253-		_RGFW->EGL_display = RGFW_eglGetDisplay(EGL_DEFAULT_DISPLAY);
 5254-		#endif
 5255-	}
 5256-
 5257-	RGFW_eglInitialize(_RGFW->EGL_display, NULL, NULL);
 5258-	return out;
 5259-}
 5260-
 5261-
 5262-void RGFW_unloadEGL(void) {
 5263-	if (!RGFW_eglLibHandle) return;
 5264-	RGFW_eglTerminate(_RGFW->EGL_display);
 5265-	#ifdef RGFW_WINDOWS
 5266-	    FreeLibrary((HMODULE)RGFW_eglLibHandle);
 5267-	#elif defined(RGFW_MACOS) || defined(RGFW_UNIX)
 5268-	    dlclose(RGFW_eglLibHandle);
 5269-	#endif
 5270-
 5271-    RGFW_eglLibHandle = NULL;
 5272-    RGFW_eglGetProcAddress = NULL;
 5273-}
 5274-
 5275-RGFW_bool RGFW_window_createContextPtr_EGL(RGFW_window* win, RGFW_eglContext* ctx, RGFW_glHints* hints) {
 5276-	if (RGFW_loadEGL() == RGFW_FALSE) return RGFW_FALSE;
 5277-	win->src.ctx.egl = ctx;
 5278-	win->src.gfxType = RGFW_gfxEGL;
 5279-
 5280-#ifdef RGFW_WAYLAND
 5281-    if (_RGFW->useWaylandBool)
 5282-        win->src.ctx.egl->eglWindow = wl_egl_window_create(win->src.surface, win->w, win->h);
 5283-#endif
 5284-
 5285-	#ifndef EGL_OPENGL_ES1_BIT
 5286-	#define EGL_OPENGL_ES1_BIT 0x1
 5287-	#endif
 5288-
 5289-	EGLint egl_config[24];
 5290-
 5291-	{
 5292-		RGFW_attribStack stack;
 5293-		RGFW_attribStack_init(&stack, egl_config, 24);
 5294-
 5295-		RGFW_attribStack_pushAttribs(&stack, EGL_SURFACE_TYPE, EGL_WINDOW_BIT);
 5296-		RGFW_attribStack_pushAttrib(&stack, EGL_RENDERABLE_TYPE);
 5297-
 5298-		if (hints->profile == RGFW_glES) {
 5299-			switch (hints->major) {
 5300-				case 1: RGFW_attribStack_pushAttrib(&stack, EGL_OPENGL_ES1_BIT); break;
 5301-				case 2: RGFW_attribStack_pushAttrib(&stack, EGL_OPENGL_ES2_BIT); break;
 5302-				case 3: RGFW_attribStack_pushAttrib(&stack, EGL_OPENGL_ES3_BIT); break;
 5303-				default: break;
 5304-			}
 5305-		} else {
 5306-			RGFW_attribStack_pushAttrib(&stack, EGL_OPENGL_BIT);
 5307-		}
 5308-
 5309-		RGFW_attribStack_pushAttribs(&stack, EGL_RED_SIZE, hints->red);
 5310-		RGFW_attribStack_pushAttribs(&stack, EGL_GREEN_SIZE, hints->green);
 5311-		RGFW_attribStack_pushAttribs(&stack, EGL_BLUE_SIZE, hints->blue);
 5312-		RGFW_attribStack_pushAttribs(&stack, EGL_ALPHA_SIZE, hints->alpha);
 5313-		RGFW_attribStack_pushAttribs(&stack, EGL_DEPTH_SIZE, hints->depth);
 5314-
 5315-		RGFW_attribStack_pushAttribs(&stack, EGL_STENCIL_SIZE, hints->stencil);
 5316-		if (hints->samples) {
 5317-			RGFW_attribStack_pushAttribs(&stack, EGL_SAMPLE_BUFFERS, 1);
 5318-			RGFW_attribStack_pushAttribs(&stack, EGL_SAMPLES, hints->samples);
 5319-		}
 5320-
 5321-		RGFW_attribStack_pushAttribs(&stack, EGL_NONE, EGL_NONE);
 5322-	}
 5323-
 5324-	EGLint numConfigs, best_config = -1, best_samples = 0;
 5325-
 5326-	RGFW_eglChooseConfig(_RGFW->EGL_display, egl_config, NULL, 0, &numConfigs);
 5327-	EGLConfig* configs = (EGLConfig*)RGFW_ALLOC(sizeof(EGLConfig) * (u32)numConfigs);
 5328-
 5329-	RGFW_eglChooseConfig(_RGFW->EGL_display, egl_config, configs, numConfigs, &numConfigs);
 5330-
 5331-#ifdef RGFW_X11
 5332-	RGFW_bool transparent = (win->internal.flags & RGFW_windowTransparent);
 5333-	EGLint best_depth = 0;
 5334-#endif
 5335-
 5336-	for (EGLint i = 0; i < numConfigs; i++) {
 5337-		EGLint visual_id = 0;
 5338-		EGLint samples = 0;
 5339-
 5340-		RGFW_eglGetConfigAttrib(_RGFW->EGL_display, configs[i], EGL_NATIVE_VISUAL_ID, &visual_id);
 5341-		RGFW_eglGetConfigAttrib(_RGFW->EGL_display, configs[i], EGL_SAMPLES, &samples);
 5342-
 5343-		if (best_config  == -1) best_config = i;
 5344-
 5345-#ifdef RGFW_X11
 5346-		if (_RGFW->useWaylandBool == RGFW_FALSE) {
 5347-			XVisualInfo vinfo_template;
 5348-			vinfo_template.visualid = (VisualID)visual_id;
 5349-
 5350-			int num_visuals = 0;
 5351-			XVisualInfo* vi = XGetVisualInfo(_RGFW->display, VisualIDMask, &vinfo_template, &num_visuals);
 5352-			if (!vi) continue;
 5353-			if ((!transparent || vi->depth == 32) && best_depth == 0) {
 5354-				best_config = i;
 5355-				best_depth = vi->depth;
 5356-			}
 5357-
 5358-			if ((!(transparent) || vi->depth == 32) && (samples <= hints->samples && samples > best_samples)) {
 5359-				best_depth = vi->depth;
 5360-				best_config = i;
 5361-				best_samples = samples;
 5362-				XFree(vi);
 5363-				continue;
 5364-			}
 5365-		}
 5366-#endif
 5367-
 5368-		if (samples <= hints->samples && samples > best_samples) {
 5369-			best_config = i;
 5370-			best_samples = samples;
 5371-		}
 5372-	}
 5373-
 5374-	EGLConfig config = configs[best_config];
 5375-	RGFW_FREE(configs);
 5376-#ifdef RGFW_X11
 5377-    if (_RGFW->useWaylandBool == RGFW_FALSE) {
 5378-		/*  This is required so that way the user can create their own OpenGL context after RGFW_createWindow is used */
 5379-		XVisualInfo* result;
 5380-		XVisualInfo desired;
 5381-		EGLint visualID = 0, count = 0;
 5382-
 5383-		RGFW_eglGetConfigAttrib(_RGFW->EGL_display, config, EGL_NATIVE_VISUAL_ID, &visualID);
 5384-		if (visualID) {
 5385-			desired.visualid = (VisualID)visualID;
 5386-			result = XGetVisualInfo(_RGFW->display, VisualIDMask, &desired, &count);
 5387-		} else  RGFW_debugCallback(RGFW_typeError, RGFW_errEGLContext,  "Failed to fetch a valid EGL VisualID");
 5388-
 5389-		if (result == NULL || count == 0) {
 5390-			if (win->src.window == 0) {
 5391-				/* try to create a EGL context anyway (this will work if you're not using a NVidia driver) */
 5392-				win->internal.flags &= ~(u32)RGFW_windowEGL;
 5393-				RGFW_createWindowPlatform("", win->internal.flags, win);
 5394-			}
 5395-			RGFW_debugCallback(RGFW_typeError, RGFW_errEGLContext,  "Failed to find a valid visual for the EGL config");
 5396-		} else {
 5397-			RGFW_bool showWindow = RGFW_FALSE;
 5398-			if (win->src.window) {
 5399-				showWindow = (RGFW_window_isMinimized(win) == RGFW_FALSE);
 5400-				RGFW_window_closePlatform(win);
 5401-			}
 5402-
 5403-			RGFW_XCreateWindow(*result, "", win->internal.flags, win);
 5404-
 5405-			if (showWindow) {
 5406-				RGFW_window_show(win);
 5407-			}
 5408-			XFree(result);
 5409-		}
 5410-	}
 5411-#endif
 5412-
 5413-	EGLint surf_attribs[9];
 5414-
 5415-	{
 5416-		RGFW_attribStack stack;
 5417-		RGFW_attribStack_init(&stack, surf_attribs, 9);
 5418-
 5419-		const char present_opaque_str[] = "EGL_EXT_present_opaque";
 5420-		RGFW_bool opaque_extension_Found = RGFW_extensionSupportedPlatform_EGL(present_opaque_str, sizeof(present_opaque_str));
 5421-
 5422-		#ifndef EGL_PRESENT_OPAQUE_EXT
 5423-		#define EGL_PRESENT_OPAQUE_EXT 0x31df
 5424-		#endif
 5425-
 5426-		#ifndef EGL_GL_COLORSPACE_KHR
 5427-		#define EGL_GL_COLORSPACE_KHR 0x309D
 5428-		#ifndef EGL_GL_COLORSPACE_SRGB_KHR
 5429-		#define EGL_GL_COLORSPACE_SRGB_KHR 0x3089
 5430-		#endif
 5431-		#endif
 5432-
 5433-		const char gl_colorspace_str[] = "EGL_KHR_gl_colorspace";
 5434-		RGFW_bool gl_colorspace_Found = RGFW_extensionSupportedPlatform_EGL(gl_colorspace_str, sizeof(gl_colorspace_str));
 5435-
 5436-		if (hints->sRGB && gl_colorspace_Found) {
 5437-			RGFW_attribStack_pushAttribs(&stack, EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR);
 5438-		}
 5439-
 5440-		if (!(win->internal.flags & RGFW_windowTransparent) && opaque_extension_Found)
 5441-			RGFW_attribStack_pushAttribs(&stack, EGL_PRESENT_OPAQUE_EXT, EGL_TRUE);
 5442-
 5443-		if (hints->doubleBuffer == 0) {
 5444-			RGFW_attribStack_pushAttribs(&stack, EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER);
 5445-		}
 5446-
 5447-		RGFW_attribStack_pushAttribs(&stack, EGL_NONE, EGL_NONE);
 5448-	}
 5449-	#if defined(RGFW_MACOS)
 5450-		void* layer = RGFW_getLayer_OSX();
 5451-
 5452-		RGFW_window_setLayer_OSX(win, layer);
 5453-
 5454-		win->src.ctx.egl->surface = RGFW_eglCreateWindowSurface(_RGFW->EGL_display, config, (EGLNativeWindowType) layer, surf_attribs);
 5455-	#elif defined(RGFW_WINDOWS)
 5456-		win->src.ctx.egl->surface = RGFW_eglCreateWindowSurface(_RGFW->EGL_display, config, (EGLNativeWindowType) win->src.window, surf_attribs);
 5457-	#elif defined(RGFW_WAYLAND)
 5458-		if (_RGFW->useWaylandBool)
 5459-			win->src.ctx.egl->surface = RGFW_eglCreateWindowSurface(_RGFW->EGL_display, config, (EGLNativeWindowType) win->src.ctx.egl->eglWindow, surf_attribs);
 5460-		else
 5461-    #endif
 5462-    #ifdef RGFW_X11
 5463-        win->src.ctx.egl->surface = RGFW_eglCreateWindowSurface(_RGFW->EGL_display, config, (EGLNativeWindowType) win->src.window, surf_attribs);
 5464-    #else
 5465-    {}
 5466-    #endif
 5467-	#ifdef RGFW_WASM
 5468-		win->src.ctx.egl->surface = eglCreateWindowSurface(_RGFW->EGL_display, config, 0, 0);
 5469-	#endif
 5470-
 5471-	if (win->src.ctx.egl->surface == NULL) {
 5472-		RGFW_debugCallback(RGFW_typeError, RGFW_errEGLContext, "Failed to create an EGL surface.");
 5473-		return RGFW_FALSE;
 5474-	}
 5475-
 5476-	EGLint attribs[20];
 5477-	{
 5478-		RGFW_attribStack stack;
 5479-		RGFW_attribStack_init(&stack, attribs, 20);
 5480-
 5481-		if (hints->major || hints->minor) {
 5482-			RGFW_attribStack_pushAttribs(&stack, EGL_CONTEXT_MAJOR_VERSION, hints->major);
 5483-			RGFW_attribStack_pushAttribs(&stack, EGL_CONTEXT_MINOR_VERSION, hints->minor);
 5484-		}
 5485-
 5486-		if (hints->profile == RGFW_glCore) {
 5487-			RGFW_attribStack_pushAttribs(&stack, EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT);
 5488-		} else if (hints->profile == RGFW_glCompatibility) {
 5489-			RGFW_attribStack_pushAttribs(&stack, EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT);
 5490-		} else if (hints->profile == RGFW_glForwardCompatibility) {
 5491-			RGFW_attribStack_pushAttribs(&stack, EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE, EGL_TRUE);
 5492-		}
 5493-
 5494-
 5495-		RGFW_attribStack_pushAttribs(&stack, EGL_CONTEXT_OPENGL_ROBUST_ACCESS, hints->robustness);
 5496-		RGFW_attribStack_pushAttribs(&stack, EGL_CONTEXT_OPENGL_DEBUG, hints->debug);
 5497-
 5498-		#ifndef EGL_CONTEXT_RELEASE_BEHAVIOR_KHR
 5499-			#define EGL_CONTEXT_RELEASE_BEHAVIOR_KHR 0x2097
 5500-		#endif
 5501-
 5502-		#ifndef EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR
 5503-			#define EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x2098
 5504-		#endif
 5505-
 5506-		if (hints->releaseBehavior == RGFW_glReleaseFlush) {
 5507-			RGFW_attribStack_pushAttribs(&stack, EGL_CONTEXT_RELEASE_BEHAVIOR_KHR, EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR);
 5508-		} else {
 5509-			RGFW_attribStack_pushAttribs(&stack, EGL_CONTEXT_RELEASE_BEHAVIOR_KHR, 0x0000);
 5510-		}
 5511-
 5512-		RGFW_attribStack_pushAttribs(&stack, EGL_NONE, EGL_NONE);
 5513-	}
 5514-
 5515-	if (hints->profile == RGFW_glES)
 5516-		RGFW_eglBindAPI(EGL_OPENGL_ES_API);
 5517-	else
 5518-		RGFW_eglBindAPI(EGL_OPENGL_API);
 5519-
 5520-	win->src.ctx.egl->ctx = RGFW_eglCreateContext(_RGFW->EGL_display, config, hints->shareEGL, attribs);
 5521-
 5522-	if (win->src.ctx.egl->ctx == NULL) {
 5523-		RGFW_debugCallback(RGFW_typeError, RGFW_errEGLContext,  "Failed to create an EGL context.");
 5524-		return RGFW_FALSE;
 5525-	}
 5526-
 5527-	RGFW_eglMakeCurrent(_RGFW->EGL_display, win->src.ctx.egl->surface, win->src.ctx.egl->surface, win->src.ctx.egl->ctx);
 5528-	RGFW_eglSwapBuffers(_RGFW->EGL_display, win->src.ctx.egl->surface);
 5529-	RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "EGL context initalized.");
 5530-	return RGFW_TRUE;
 5531-}
 5532-
 5533-RGFW_eglContext* RGFW_window_getContext_EGL(RGFW_window* win) {
 5534-	if (win->src.gfxType == RGFW_windowOpenGL) return NULL;
 5535-	return win->src.ctx.egl;
 5536-}
 5537-
 5538-void RGFW_window_deleteContextPtr_EGL(RGFW_window* win, RGFW_eglContext* ctx) {
 5539-	if (_RGFW->EGL_display == NULL) return;
 5540-
 5541-	RGFW_eglDestroySurface(_RGFW->EGL_display, ctx->surface);
 5542-	RGFW_eglDestroyContext(_RGFW->EGL_display, ctx->ctx);
 5543-	RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "EGL context freed");
 5544-	#ifdef RGFW_WAYLAND
 5545-		if (_RGFW->useWaylandBool == RGFW_FALSE) return;
 5546-		wl_egl_window_destroy(win->src.ctx.egl->eglWindow);
 5547-		RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "EGL window context freed");
 5548-	#endif
 5549-	win->src.ctx.egl = NULL;
 5550-}
 5551-
 5552-void RGFW_window_makeCurrentContext_EGL(RGFW_window* win) { if (win) RGFW_ASSERT(win->src.ctx.egl);
 5553-	if (win == NULL)
 5554-        RGFW_eglMakeCurrent(_RGFW->EGL_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
 5555-    else {
 5556-        RGFW_eglMakeCurrent(_RGFW->EGL_display, win->src.ctx.egl->surface, win->src.ctx.egl->surface, win->src.ctx.egl->ctx);
 5557-    }
 5558-}
 5559-
 5560-void RGFW_window_swapBuffers_EGL(RGFW_window* win) {
 5561-	if (RGFW_eglSwapBuffers)
 5562-		RGFW_eglSwapBuffers(_RGFW->EGL_display, win->src.ctx.egl->surface);
 5563-	else RGFW_window_swapBuffers_OpenGL(win);
 5564-}
 5565-
 5566-void* RGFW_getCurrentContext_EGL(void) {
 5567-	return RGFW_eglGetCurrentContext();
 5568-}
 5569-
 5570-RGFW_proc RGFW_getProcAddress_EGL(const char* procname) {
 5571-	#if defined(RGFW_WINDOWS)
 5572-	RGFW_proc proc = (RGFW_proc) GetProcAddress(RGFW_wgl_dll, procname);
 5573-
 5574-		if (proc)
 5575-			return proc;
 5576-	#endif
 5577-
 5578-	return (RGFW_proc) RGFW_eglGetProcAddress(procname);
 5579-}
 5580-
 5581-RGFW_bool RGFW_extensionSupportedPlatform_EGL(const char* extension, size_t len) {
 5582-	if (RGFW_loadEGL() == RGFW_FALSE) return RGFW_FALSE;
 5583-	const char* extensions = RGFW_eglQueryString(_RGFW->EGL_display, EGL_EXTENSIONS);
 5584-	return extensions != NULL && RGFW_extensionSupportedStr(extensions, extension, len);
 5585-}
 5586-
 5587-void RGFW_window_swapInterval_EGL(RGFW_window* win, i32 swapInterval) {
 5588-	RGFW_ASSERT(win != NULL);
 5589-	RGFW_eglSwapInterval(_RGFW->EGL_display, swapInterval);
 5590-}
 5591-
 5592-RGFW_bool RGFW_extensionSupported_EGL(const char* extension, size_t len) {
 5593-	if (RGFW_extensionSupported_base(extension, len))  return RGFW_TRUE;
 5594-    return RGFW_extensionSupportedPlatform_EGL(extension, len);
 5595-}
 5596-
 5597-void RGFW_window_makeCurrentWindow_EGL(RGFW_window* win) {
 5598-    _RGFW->current = win;
 5599-    RGFW_window_makeCurrentContext_EGL(win);
 5600-}
 5601-
 5602-RGFW_window* RGFW_getCurrentWindow_EGL(void) { return _RGFW->current; }
 5603-
 5604-RGFW_eglContext* RGFW_window_createContext_EGL(RGFW_window* win, RGFW_glHints* hints) {
 5605-	RGFW_eglContext* ctx = (RGFW_eglContext*)RGFW_ALLOC(sizeof(RGFW_eglContext));
 5606-	if (RGFW_window_createContextPtr_EGL(win, ctx, hints) == RGFW_FALSE) {
 5607-		RGFW_FREE(ctx);
 5608-		win->src.ctx.egl = NULL;
 5609-		return NULL;
 5610-	}
 5611-	win->src.gfxType |= RGFW_gfxOwnedByRGFW;
 5612-	return ctx;
 5613-}
 5614-
 5615-void RGFW_window_deleteContext_EGL(RGFW_window* win, RGFW_eglContext* ctx) {
 5616-	RGFW_window_deleteContextPtr_EGL(win, ctx);
 5617-	if (win->src.gfxType & RGFW_gfxOwnedByRGFW) RGFW_FREE(ctx);
 5618-}
 5619-
 5620-#endif /* RGFW_EGL */
 5621-
 5622-/*
 5623-	end of RGFW_EGL defines
 5624-*/
 5625-#endif /* end of RGFW_GL (OpenGL, EGL, OSMesa )*/
 5626-
 5627-/*
 5628-	RGFW_VULKAN defines
 5629-*/
 5630-#ifdef RGFW_VULKAN
 5631-#ifdef RGFW_MACOS
 5632-#include <objc/message.h>
 5633-#endif
 5634-
 5635-const char** RGFW_getRequiredInstanceExtensions_Vulkan(size_t* count) {
 5636-    static const char* arr[2] = {VK_KHR_SURFACE_EXTENSION_NAME};
 5637-    arr[1] = RGFW_VK_SURFACE;
 5638-    if (count != NULL) *count = 2;
 5639-
 5640-    return (const char**)arr;
 5641-}
 5642-
 5643-#ifndef RGFW_MACOS
 5644-VkResult RGFW_window_createSurface_Vulkan(RGFW_window* win, VkInstance instance, VkSurfaceKHR* surface) {
 5645-    RGFW_ASSERT(win != NULL); RGFW_ASSERT(instance);
 5646-	RGFW_ASSERT(surface != NULL);
 5647-
 5648-    *surface = VK_NULL_HANDLE;
 5649-
 5650-#ifdef RGFW_X11
 5651-
 5652-    VkXlibSurfaceCreateInfoKHR x11 = { VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, 0, 0, (Display*) _RGFW->display, (Window) win->src.window };
 5653-    return vkCreateXlibSurfaceKHR(instance, &x11, NULL, surface);
 5654-#endif
 5655-#if defined(RGFW_WAYLAND)
 5656-
 5657-    VkWaylandSurfaceCreateInfoKHR wayland = { VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR, 0, 0, (struct wl_display*) _RGFW->wl_display, (struct wl_surface*) win->src.surface };
 5658-    return vkCreateWaylandSurfaceKHR(instance, &wayland, NULL, surface);
 5659-#elif defined(RGFW_WINDOWS)
 5660-    VkWin32SurfaceCreateInfoKHR win32 = { VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR, 0, 0, GetModuleHandle(NULL), (HWND)win->src.window };
 5661-
 5662-    return vkCreateWin32SurfaceKHR(instance, &win32, NULL, surface);
 5663-#endif
 5664-}
 5665-#endif
 5666-
 5667-RGFW_bool RGFW_getPresentationSupport_Vulkan(VkPhysicalDevice physicalDevice, u32 queueFamilyIndex) {
 5668-	if (_RGFW == NULL) RGFW_init();
 5669-#ifdef RGFW_X11
 5670-
 5671-	Visual* visual = DefaultVisual(_RGFW->display, DefaultScreen(_RGFW->display));
 5672-    RGFW_bool out = vkGetPhysicalDeviceXlibPresentationSupportKHR(physicalDevice, queueFamilyIndex, _RGFW->display, XVisualIDFromVisual(visual));
 5673-    return out;
 5674-#endif
 5675-#if defined(RGFW_WAYLAND)
 5676-
 5677-    RGFW_bool wlout = vkGetPhysicalDeviceWaylandPresentationSupportKHR(physicalDevice, queueFamilyIndex, _RGFW->wl_display);
 5678-    return wlout;
 5679-#elif defined(RGFW_WINDOWS)
 5680-	RGFW_bool out = vkGetPhysicalDeviceWin32PresentationSupportKHR(physicalDevice, queueFamilyIndex);
 5681-	return out;
 5682-#elif defined(RGFW_MACOS) && !defined(RGFW_MACOS_X11)
 5683-	RGFW_UNUSED(physicalDevice);
 5684-	RGFW_UNUSED(queueFamilyIndex);
 5685-    return RGFW_FALSE; /* TODO */
 5686-#endif
 5687-}
 5688-#endif /* end of RGFW_vulkan */
 5689-
 5690-/*
 5691-This is where OS specific stuff starts
 5692-*/
 5693-
 5694-/* start of unix (wayland or X11 (unix) ) defines */
 5695-
 5696-#ifdef RGFW_UNIX
 5697-#include <fcntl.h>
 5698-#include <poll.h>
 5699-#include <unistd.h>
 5700-
 5701-void RGFW_stopCheckEvents(void) {
 5702-
 5703-	_RGFW->eventWait_forceStop[2] = 1;
 5704-	while (1) {
 5705-		const char byte = 0;
 5706-		const ssize_t result = write(_RGFW->eventWait_forceStop[1], &byte, 1);
 5707-		if (result == 1 || result == -1)
 5708-			break;
 5709-	}
 5710-}
 5711-
 5712-RGFWDEF u64 RGFW_linux_getTimeNS(void);
 5713-u64 RGFW_linux_getTimeNS(void) {
 5714-    struct timespec ts;
 5715-    const u64 scale_factor = 1000000000;
 5716-    clock_gettime(_RGFW->clock, &ts);
 5717-    return (u64)ts.tv_sec * scale_factor + (u64)ts.tv_nsec;
 5718-}
 5719-
 5720-void RGFW_waitForEvent(i32 waitMS) {
 5721-	if (waitMS == 0) return;
 5722-
 5723-	if (_RGFW->eventWait_forceStop[0] == 0 || _RGFW->eventWait_forceStop[1] == 0) {
 5724-		if (pipe(_RGFW->eventWait_forceStop) != -1) {
 5725-			fcntl(_RGFW->eventWait_forceStop[0], F_GETFL, 0);
 5726-			fcntl(_RGFW->eventWait_forceStop[0], F_GETFD, 0);
 5727-			fcntl(_RGFW->eventWait_forceStop[1], F_GETFL, 0);
 5728-			fcntl(_RGFW->eventWait_forceStop[1], F_GETFD, 0);
 5729-		}
 5730-	}
 5731-
 5732-	struct pollfd fds[2];
 5733-    fds[0].fd = 0;
 5734-    fds[0].events = POLLIN;
 5735-    fds[0].revents = 0;
 5736-    fds[1].fd = _RGFW->eventWait_forceStop[0];
 5737-    fds[1].events = POLLIN;
 5738-    fds[1].revents = 0;
 5739-
 5740-
 5741-	if (RGFW_usingWayland()) {
 5742-		#ifdef RGFW_WAYLAND
 5743-		fds[0].fd = wl_display_get_fd(_RGFW->wl_display);
 5744-
 5745-		/* empty the queue */
 5746-		while (wl_display_prepare_read(_RGFW->wl_display) != 0) {
 5747-			/* error occured when dispatching the queue */
 5748-			if (wl_display_dispatch_pending(_RGFW->wl_display) == -1) {
 5749-				return;
 5750-			}
 5751-		}
 5752-
 5753-		/* send any pending requests to the compositor */
 5754-		while (wl_display_flush(_RGFW->wl_display) == -1) {
 5755-
 5756-			/* queue is full dispatch them */
 5757-			if (errno == EAGAIN) {
 5758-				if (wl_display_dispatch_pending(_RGFW->wl_display) == -1) {
 5759-					return;
 5760-				}
 5761-			} else {
 5762-				return;
 5763-			}
 5764-		}
 5765-		#endif
 5766-	} else {
 5767-		#ifdef RGFW_X11
 5768-		fds[0].fd = ConnectionNumber(_RGFW->display);
 5769-		#endif
 5770-	}
 5771-
 5772-
 5773-	u64 start = RGFW_linux_getTimeNS();
 5774-	if (RGFW_usingWayland()) {
 5775-		#ifdef RGFW_WAYLAND
 5776-		while (wl_display_dispatch_pending(_RGFW->wl_display) == 0) {
 5777-			if (poll(fds, 1, waitMS) <= 0) {
 5778-				wl_display_cancel_read(_RGFW->wl_display);
 5779-				break;
 5780-			} else {
 5781-				if (wl_display_read_events(_RGFW->wl_display) == -1)
 5782-					return;
 5783-			}
 5784-
 5785-			if (waitMS != RGFW_eventWaitNext) {
 5786-				waitMS -= (i32)(RGFW_linux_getTimeNS() - start) / (i32)1e+6;
 5787-			}
 5788-		}
 5789-
 5790-		/* queue contains events from read, dispatch them */
 5791-		if (wl_display_dispatch_pending(_RGFW->wl_display) == -1) {
 5792-			return;
 5793-		}
 5794-		#endif
 5795-	} else {
 5796-		#ifdef RGFW_X11
 5797-		while (XPending(_RGFW->display) == 0) {
 5798-			if (poll(fds, 1, waitMS) <= 0)
 5799-				break;
 5800-
 5801-			if (waitMS != RGFW_eventWaitNext) {
 5802-				waitMS -= (i32)(RGFW_linux_getTimeNS() - start) / (i32)1e+6;
 5803-			}
 5804-		}
 5805-		#endif
 5806-	}
 5807-
 5808-	/* drain any data in the stop request */
 5809-	if (_RGFW->eventWait_forceStop[2]) {
 5810-		char data[64];
 5811-        RGFW_MEMZERO(data, sizeof(data));
 5812-        (void)!read(_RGFW->eventWait_forceStop[0], data, sizeof(data));
 5813-
 5814-		_RGFW->eventWait_forceStop[2] = 0;
 5815-	}
 5816-}
 5817-
 5818-char* RGFW_strtok(char* str, const char* delimStr);
 5819-char* RGFW_strtok(char* str, const char* delimStr) {
 5820-    static char* static_str = NULL;
 5821-
 5822-    if (str != NULL)
 5823-        static_str = str;
 5824-
 5825-    if (static_str == NULL) {
 5826-        return NULL;
 5827-    }
 5828-
 5829-    while (*static_str != '\0') {
 5830-        RGFW_bool delim = 0;
 5831-        const char* d;
 5832-        for (d = delimStr; *d != '\0'; d++) {
 5833-            if (*static_str == *d) {
 5834-                delim = 1;
 5835-                break;
 5836-            }
 5837-        }
 5838-        if (!delim)
 5839-            break;
 5840-        static_str++;
 5841-    }
 5842-
 5843-    if (*static_str == '\0')
 5844-        return NULL;
 5845-
 5846-    char* token_start = static_str;
 5847-    while (*static_str != '\0') {
 5848-        int delim = 0;
 5849-        const char* d;
 5850-        for (d = delimStr; *d != '\0'; d++) {
 5851-            if (*static_str == *d) {
 5852-                delim = 1;
 5853-                break;
 5854-            }
 5855-        }
 5856-
 5857-        if (delim) {
 5858-            *static_str = '\0';
 5859-            static_str++;
 5860-            break;
 5861-        }
 5862-        static_str++;
 5863-    }
 5864-
 5865-    return token_start;
 5866-}
 5867-
 5868-#ifdef RGFW_X11
 5869-RGFWDEF i32 RGFW_initPlatform_X11(void);
 5870-RGFWDEF void RGFW_deinitPlatform_X11(void);
 5871-#endif
 5872-#ifdef RGFW_WAYLAND
 5873-RGFWDEF i32 RGFW_initPlatform_Wayland(void);
 5874-RGFWDEF void RGFW_deinitPlatform_Wayland(void);
 5875-#endif
 5876-
 5877-RGFWDEF void RGFW_load_X11(void);
 5878-RGFWDEF void RGFW_load_Wayland(void);
 5879-
 5880-#if !defined(RGFW_X11) || !defined(RGFW_WAYLAND)
 5881-void RGFW_load_X11(void) { }
 5882-void RGFW_load_Wayland(void) { }
 5883-#endif
 5884-
 5885-/*
 5886- * Sadly we have to use magic linux keycodes
 5887- * We can't use X11 functions, because that breaks Wayland, but they use the same keycodes so there's no use redeffing them
 5888- * We can't use linux enums, because the headers don't exist on BSD
 5889- */
 5890-void RGFW_initKeycodesPlatform(void) {
 5891-	_RGFW->keycodes[49] = RGFW_keyBacktick;
 5892-	_RGFW->keycodes[19] = RGFW_key0;
 5893-	_RGFW->keycodes[10] = RGFW_key1;
 5894-	_RGFW->keycodes[11] = RGFW_key2;
 5895-	_RGFW->keycodes[12] = RGFW_key3;
 5896-	_RGFW->keycodes[13] = RGFW_key4;
 5897-	_RGFW->keycodes[14] = RGFW_key5;
 5898-	_RGFW->keycodes[15] = RGFW_key6;
 5899-	_RGFW->keycodes[16] = RGFW_key7;
 5900-	_RGFW->keycodes[17] = RGFW_key8;
 5901-	_RGFW->keycodes[18] = RGFW_key9;
 5902-	_RGFW->keycodes[65] = RGFW_keySpace;
 5903-	_RGFW->keycodes[38] = RGFW_keyA;
 5904-	_RGFW->keycodes[56] = RGFW_keyB;
 5905-	_RGFW->keycodes[54] = RGFW_keyC;
 5906-	_RGFW->keycodes[40] = RGFW_keyD;
 5907-	_RGFW->keycodes[26] = RGFW_keyE;
 5908-	_RGFW->keycodes[41] = RGFW_keyF;
 5909-	_RGFW->keycodes[42] = RGFW_keyG;
 5910-	_RGFW->keycodes[43] = RGFW_keyH;
 5911-	_RGFW->keycodes[31] = RGFW_keyI;
 5912-	_RGFW->keycodes[44] = RGFW_keyJ;
 5913-	_RGFW->keycodes[45] = RGFW_keyK;
 5914-	_RGFW->keycodes[46] = RGFW_keyL;
 5915-	_RGFW->keycodes[58] = RGFW_keyM;
 5916-	_RGFW->keycodes[57] = RGFW_keyN;
 5917-	_RGFW->keycodes[32] = RGFW_keyO;
 5918-	_RGFW->keycodes[33] = RGFW_keyP;
 5919-	_RGFW->keycodes[24] = RGFW_keyQ;
 5920-	_RGFW->keycodes[27] = RGFW_keyR;
 5921-	_RGFW->keycodes[39] = RGFW_keyS;
 5922-	_RGFW->keycodes[28] = RGFW_keyT;
 5923-	_RGFW->keycodes[30] = RGFW_keyU;
 5924-	_RGFW->keycodes[55] = RGFW_keyV;
 5925-	_RGFW->keycodes[25] = RGFW_keyW;
 5926-	_RGFW->keycodes[53] = RGFW_keyX;
 5927-	_RGFW->keycodes[29] = RGFW_keyY;
 5928-	_RGFW->keycodes[52] = RGFW_keyZ;
 5929-	_RGFW->keycodes[60] = RGFW_keyPeriod;
 5930-	_RGFW->keycodes[59] = RGFW_keyComma;
 5931-	_RGFW->keycodes[61] = RGFW_keySlash;
 5932-	_RGFW->keycodes[34] = RGFW_keyBracket;
 5933-	_RGFW->keycodes[35] = RGFW_keyCloseBracket;
 5934-	_RGFW->keycodes[47] = RGFW_keySemicolon;
 5935-	_RGFW->keycodes[48] = RGFW_keyApostrophe;
 5936-	_RGFW->keycodes[51] = RGFW_keyBackSlash;
 5937-	_RGFW->keycodes[36] = RGFW_keyReturn;
 5938-	_RGFW->keycodes[119] = RGFW_keyDelete;
 5939-	_RGFW->keycodes[77] = RGFW_keyNumLock;
 5940-	_RGFW->keycodes[106] = RGFW_keyPadSlash;
 5941-	_RGFW->keycodes[63] = RGFW_keyPadMultiply;
 5942-	_RGFW->keycodes[86] = RGFW_keyPadPlus;
 5943-	_RGFW->keycodes[82] = RGFW_keyPadMinus;
 5944-	_RGFW->keycodes[87] = RGFW_keyPad1;
 5945-	_RGFW->keycodes[88] = RGFW_keyPad2;
 5946-	_RGFW->keycodes[89] = RGFW_keyPad3;
 5947-	_RGFW->keycodes[83] = RGFW_keyPad4;
 5948-	_RGFW->keycodes[84] = RGFW_keyPad5;
 5949-	_RGFW->keycodes[85] = RGFW_keyPad6;
 5950-	_RGFW->keycodes[81] = RGFW_keyPad9;
 5951-	_RGFW->keycodes[90] = RGFW_keyPad0;
 5952-	_RGFW->keycodes[91] = RGFW_keyPadPeriod;
 5953-	_RGFW->keycodes[104] = RGFW_keyPadReturn;
 5954-	_RGFW->keycodes[20] = RGFW_keyMinus;
 5955-	_RGFW->keycodes[21] = RGFW_keyEquals;
 5956-	_RGFW->keycodes[22] = RGFW_keyBackSpace;
 5957-	_RGFW->keycodes[23] = RGFW_keyTab;
 5958-	_RGFW->keycodes[66] = RGFW_keyCapsLock;
 5959-	_RGFW->keycodes[50] = RGFW_keyShiftL;
 5960-	_RGFW->keycodes[37] = RGFW_keyControlL;
 5961-	_RGFW->keycodes[64] = RGFW_keyAltL;
 5962-	_RGFW->keycodes[133] = RGFW_keySuperL;
 5963-	_RGFW->keycodes[105] = RGFW_keyControlR;
 5964-	_RGFW->keycodes[134] = RGFW_keySuperR;
 5965-	_RGFW->keycodes[62] = RGFW_keyShiftR;
 5966-	_RGFW->keycodes[108] = RGFW_keyAltR;
 5967-	_RGFW->keycodes[67] = RGFW_keyF1;
 5968-	_RGFW->keycodes[68] = RGFW_keyF2;
 5969-	_RGFW->keycodes[69] = RGFW_keyF3;
 5970-	_RGFW->keycodes[70] = RGFW_keyF4;
 5971-	_RGFW->keycodes[71] = RGFW_keyF5;
 5972-	_RGFW->keycodes[72] = RGFW_keyF6;
 5973-	_RGFW->keycodes[73] = RGFW_keyF7;
 5974-	_RGFW->keycodes[74] = RGFW_keyF8;
 5975-	_RGFW->keycodes[75] = RGFW_keyF9;
 5976-	_RGFW->keycodes[76] = RGFW_keyF10;
 5977-	_RGFW->keycodes[95] = RGFW_keyF11;
 5978-	_RGFW->keycodes[96] = RGFW_keyF12;
 5979-	_RGFW->keycodes[111] = RGFW_keyUp;
 5980-	_RGFW->keycodes[116] = RGFW_keyDown;
 5981-	_RGFW->keycodes[113] = RGFW_keyLeft;
 5982-	_RGFW->keycodes[114] = RGFW_keyRight;
 5983-	_RGFW->keycodes[118] = RGFW_keyInsert;
 5984-	_RGFW->keycodes[115] = RGFW_keyEnd;
 5985-	_RGFW->keycodes[112] = RGFW_keyPageUp;
 5986-	_RGFW->keycodes[117] = RGFW_keyPageDown;
 5987-	_RGFW->keycodes[9] = RGFW_keyEscape;
 5988-	_RGFW->keycodes[110] = RGFW_keyHome;
 5989-	_RGFW->keycodes[78] = RGFW_keyScrollLock;
 5990-	_RGFW->keycodes[107] = RGFW_keyPrintScreen;
 5991-	_RGFW->keycodes[128] = RGFW_keyPause;
 5992-    _RGFW->keycodes[191] = RGFW_keyF13;
 5993-    _RGFW->keycodes[192] = RGFW_keyF14;
 5994-    _RGFW->keycodes[193] = RGFW_keyF15;
 5995-    _RGFW->keycodes[194] = RGFW_keyF16;
 5996-    _RGFW->keycodes[195] = RGFW_keyF17;
 5997-    _RGFW->keycodes[196] = RGFW_keyF18;
 5998-    _RGFW->keycodes[197] = RGFW_keyF19;
 5999-    _RGFW->keycodes[198] = RGFW_keyF20;
 6000-    _RGFW->keycodes[199] = RGFW_keyF21;
 6001-    _RGFW->keycodes[200] = RGFW_keyF22;
 6002-    _RGFW->keycodes[201] = RGFW_keyF23;
 6003-    _RGFW->keycodes[202] = RGFW_keyF24;
 6004-    _RGFW->keycodes[203] = RGFW_keyF25;
 6005-	_RGFW->keycodes[142] = RGFW_keyPadEqual;
 6006-	_RGFW->keycodes[161] = RGFW_keyWorld1; /* non-US key #1 */
 6007-    _RGFW->keycodes[162] = RGFW_keyWorld2; /* non-US key #2 */
 6008-}
 6009-
 6010-i32 RGFW_initPlatform(void) {
 6011-	#if defined(_POSIX_MONOTONIC_CLOCK)
 6012-	struct timespec ts;
 6013-	RGFW_MEMZERO(&ts, sizeof(struct timespec));
 6014-
 6015-	if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
 6016-		_RGFW->clock = CLOCK_MONOTONIC;
 6017-	#else
 6018-		_RGFW->clock = CLOCK_REALTIME;
 6019-	#endif
 6020-
 6021-#ifdef RGFW_WAYLAND
 6022-	RGFW_load_Wayland();
 6023-	i32 ret = RGFW_initPlatform_Wayland();
 6024-	if (ret == 0) {
 6025-		return 0;
 6026-	} else {
 6027-		#ifdef RGFW_X11
 6028-			RGFW_debugCallback(RGFW_typeWarning, RGFW_warningWayland,  "Falling back to X11");
 6029-			RGFW_useWayland(0);
 6030-		#else
 6031-			return ret;
 6032-		#endif
 6033-	}
 6034-#endif
 6035-#ifdef RGFW_X11
 6036-	RGFW_load_X11();
 6037-	return RGFW_initPlatform_X11();
 6038-#else
 6039-	return 0;
 6040-#endif
 6041-}
 6042-
 6043-
 6044-void RGFW_deinitPlatform(void) {
 6045-    if (_RGFW->eventWait_forceStop[0] || _RGFW->eventWait_forceStop[1]){
 6046-        close(_RGFW->eventWait_forceStop[0]);
 6047-        close(_RGFW->eventWait_forceStop[1]);
 6048-    }
 6049-#ifdef RGFW_WAYLAND
 6050-	if (_RGFW->useWaylandBool) {
 6051-		RGFW_deinitPlatform_Wayland();
 6052-		return;
 6053-	}
 6054-#endif
 6055-#ifdef RGFW_X11
 6056-	RGFW_deinitPlatform_X11();
 6057-#endif
 6058-}
 6059-
 6060-RGFWDEF size_t RGFW_unix_stringlen(const char* name);
 6061-size_t RGFW_unix_stringlen(const char* name) {
 6062-	size_t i = 0;
 6063-    while (name[i]) { i++; }
 6064-	return i;
 6065-}
 6066-
 6067-RGFWDEF void RGFW_unix_parseURI(RGFW_window* win, char* data);
 6068-void RGFW_unix_parseURI(RGFW_window* win, char* data) {
 6069-	const char* prefix = (const char*)"file://";
 6070-	char* line;
 6071-	while ((line = (char*)RGFW_strtok(data, "\r\n"))) {
 6072-		data = NULL;
 6073-
 6074-		if (line[0] == '#')
 6075-			continue;
 6076-
 6077-		char* l;
 6078-		for (l = line; 1; l++) {
 6079-			if ((l - line) > 7)
 6080-				break;
 6081-			else if (*l != prefix[(l - line)])
 6082-				break;
 6083-			else if (*l == '\0' && prefix[(l - line)] == '\0') {
 6084-				line += 7;
 6085-				while (*line != '/')
 6086-					line++;
 6087-				break;
 6088-			} else if (*l == '\0')
 6089-				break;
 6090-		}
 6091-
 6092-		size_t len = RGFW_unix_stringlen(line);
 6093-		char* path = (char*)RGFW_ALLOC(len + 1);
 6094-
 6095-		size_t index = 0;
 6096-		while (*line) {
 6097-			if (line[0] == '%' && line[1] && line[2]) {
 6098-				char digits[3] = {0};
 6099-				digits[0] = line[1];
 6100-				digits[1] = line[2];
 6101-				digits[2] = '\0';
 6102-				path[index] = (char) RGFW_STRTOL(digits, NULL, 16);
 6103-				line += 2;
 6104-			} else {
 6105-				if (index >= len) {
 6106-					break;
 6107-				}
 6108-
 6109-				path[index] = *line;
 6110-			}
 6111-
 6112-			index++;
 6113-			line++;
 6114-		}
 6115-
 6116-		path[len] = '\0';
 6117-		RGFW_dataDropCallback(win, (const char*)path, len + 1, RGFW_dataFile);
 6118-		RGFW_FREE(path);
 6119-	}
 6120-}
 6121-
 6122-
 6123-#endif /* end of wayland or X11 defines */
 6124-
 6125-
 6126-/*
 6127-
 6128-
 6129-Start of Linux / Unix defines
 6130-
 6131-
 6132-*/
 6133-
 6134-#ifdef RGFW_X11
 6135-#ifdef RGFW_WAYLAND
 6136-#define RGFW_FUNC(func) func##_X11
 6137-#else
 6138-#define RGFW_FUNC(func) func
 6139-#endif
 6140-
 6141-#include <dlfcn.h>
 6142-#include <unistd.h>
 6143-
 6144-#include <limits.h> /* for data limits (mainly used in drag and drop functions) */
 6145-#include <poll.h>
 6146-
 6147-void RGFW_setXInstName(const char* name) { _RGFW->instName = name; }
 6148-#if !defined(RGFW_NO_X11_CURSOR) && defined(RGFW_X11)
 6149-	#include <X11/Xcursor/Xcursor.h>
 6150-#endif
 6151-
 6152-#include <X11/Xatom.h>
 6153-#include <X11/keysymdef.h>
 6154-#include <X11/extensions/sync.h>
 6155-
 6156-#include <X11/XKBlib.h> /* for converting keycode to string */
 6157-#include <X11/cursorfont.h> /* for hiding */
 6158-#include <X11/extensions/shapeconst.h>
 6159-#include <X11/extensions/shape.h>
 6160-#include <X11/extensions/XInput2.h>
 6161-
 6162-#ifdef RGFW_OPENGL
 6163-	#ifndef __gl_h_
 6164-		#define __gl_h_
 6165-		#define RGFW_gl_ndef
 6166-		#define GLubyte     unsigned char
 6167-		#define GLenum      unsigned int
 6168-		#define GLint       int
 6169-		#define GLuint      unsigned int
 6170-		#define GLsizei     int
 6171-		#define GLfloat     float
 6172-		#define GLvoid      void
 6173-		#define GLbitfield  unsigned int
 6174-		#define GLintptr    ptrdiff_t
 6175-		#define GLsizeiptr  ptrdiff_t
 6176-		#define GLboolean   unsigned char
 6177-	#endif
 6178-
 6179-	#include <GL/glx.h> /* GLX defs, xlib.h, gl.h */
 6180-	#ifndef GLX_MESA_swap_control
 6181-		#define  GLX_MESA_swap_control
 6182-	#endif
 6183-
 6184-	#ifdef RGFW_gl_ndef
 6185-		#undef __gl_h_
 6186-		#undef GLubyte
 6187-		#undef GLenum
 6188-		#undef GLint
 6189-		#undef GLuint
 6190-		#undef GLsizei
 6191-		#undef GLfloat
 6192-		#undef GLvoid
 6193-		#undef GLbitfield
 6194-		#undef GLintptr
 6195-		#undef GLsizeiptr
 6196-		#undef GLboolean
 6197-	#endif
 6198-	typedef GLXContext(*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*);
 6199-#endif
 6200-
 6201-/* atoms needed for drag and drop */
 6202-#if !defined(RGFW_NO_X11_CURSOR) && !defined(RGFW_NO_X11_CURSOR_PRELOAD)
 6203-		typedef XcursorImage* (*PFN_XcursorImageCreate)(int, int);
 6204-		typedef void (*PFN_XcursorImageDestroy)(XcursorImage*);
 6205-		typedef Cursor(*PFN_XcursorImageLoadCursor)(Display*, const XcursorImage*);
 6206-#endif
 6207-
 6208-#if !defined(RGFW_NO_X11_XI_PRELOAD)
 6209-		typedef int (* PFN_XISelectEvents)(Display*,Window,XIEventMask*,int);
 6210-		PFN_XISelectEvents XISelectEventsSRC = NULL;
 6211-		#define XISelectEvents XISelectEventsSRC
 6212-
 6213-		void* X11Xihandle = NULL;
 6214-#endif
 6215-
 6216-#if !defined(RGFW_NO_X11_EXT_PRELOAD)
 6217-		typedef void (* PFN_XSyncIntToValue)(XSyncValue*, int);
 6218-		PFN_XSyncIntToValue XSyncIntToValueSRC = NULL;
 6219-		#define XSyncIntToValue XSyncIntToValueSRC
 6220-
 6221-		typedef Status (* PFN_XSyncSetCounter)(Display*, XSyncCounter, XSyncValue);
 6222-		PFN_XSyncSetCounter XSyncSetCounterSRC = NULL;
 6223-		#define XSyncSetCounter XSyncSetCounterSRC
 6224-
 6225-		typedef XSyncCounter (* PFN_XSyncCreateCounter)(Display*, XSyncValue);
 6226-		PFN_XSyncCreateCounter XSyncCreateCounterSRC = NULL;
 6227-		#define XSyncCreateCounter XSyncCreateCounterSRC
 6228-
 6229-		typedef void (* PFN_XShapeCombineMask)(Display*,Window,int,int,int,Pixmap,int);
 6230-		PFN_XShapeCombineMask XShapeCombineMaskSRC;
 6231-		#define XShapeCombineMask XShapeCombineMaskSRC
 6232-
 6233-		typedef void (* PFN_XShapeCombineRegion)(Display*,Window,int,int,int,Region,int);
 6234-		PFN_XShapeCombineRegion XShapeCombineRegionSRC;
 6235-		#define XShapeCombineRegion XShapeCombineRegionSRC
 6236-		void* X11XEXThandle = NULL;
 6237-#endif
 6238-
 6239-#if !defined(RGFW_NO_X11_CURSOR) && !defined(RGFW_NO_X11_CURSOR_PRELOAD)
 6240-		PFN_XcursorImageLoadCursor XcursorImageLoadCursorSRC = NULL;
 6241-		PFN_XcursorImageCreate XcursorImageCreateSRC = NULL;
 6242-		PFN_XcursorImageDestroy XcursorImageDestroySRC = NULL;
 6243-
 6244-		#define XcursorImageLoadCursor XcursorImageLoadCursorSRC
 6245-		#define XcursorImageCreate XcursorImageCreateSRC
 6246-		#define XcursorImageDestroy XcursorImageDestroySRC
 6247-
 6248-		void* X11Cursorhandle = NULL;
 6249-#endif
 6250-
 6251-RGFWDEF RGFW_bool RGFW_waitForShowEvent_X11(RGFW_window* win);
 6252-RGFW_bool RGFW_waitForShowEvent_X11(RGFW_window* win) {
 6253-    XEvent dummy;
 6254-    while (!XCheckTypedWindowEvent(_RGFW->display, win->src.window, VisibilityNotify, &dummy)) {
 6255-		RGFW_waitForEvent(100);
 6256-    }
 6257-
 6258-	return RGFW_TRUE;
 6259-}
 6260-
 6261-RGFWDEF void RGFW_x11_icCallback(XIC ic, char* clientData, char* callData);
 6262-void RGFW_x11_icCallback(XIC ic, char* clientData, char* callData) {
 6263-	RGFW_UNUSED(ic); RGFW_UNUSED(callData);
 6264-    RGFW_window* win = (RGFW_window*)(void*)clientData;
 6265-    win->src.ic = NULL;
 6266-}
 6267-
 6268-RGFWDEF void RGFW_x11_imCallback(XIM im, char* clientData, char* callData);
 6269-void RGFW_x11_imCallback(XIM im, char* clientData, char* callData) {
 6270-	RGFW_UNUSED(im); RGFW_UNUSED(clientData); RGFW_UNUSED(callData);
 6271-	_RGFW->im = NULL;
 6272-}
 6273-
 6274-RGFWDEF void RGFW_x11_imInitCallback(Display* display, XPointer clientData, XPointer callData);
 6275-void RGFW_x11_imInitCallback(Display* display, XPointer clientData, XPointer callData) {
 6276-	RGFW_UNUSED(display); RGFW_UNUSED(clientData); RGFW_UNUSED(callData);
 6277-
 6278-	if (_RGFW->im) {
 6279-		return;
 6280-	}
 6281-
 6282-	_RGFW->im = XOpenIM(_RGFW->display, 0, NULL, NULL);
 6283-	if (_RGFW->im == NULL) {
 6284-		return;
 6285-	}
 6286-
 6287-    RGFW_bool found = RGFW_FALSE;
 6288-    XIMStyles* styles = NULL;
 6289-
 6290-    if (XGetIMValues(_RGFW->im, XNQueryInputStyle, &styles, NULL) != NULL) {
 6291-        found = RGFW_FALSE;
 6292-	} else {
 6293-		for (unsigned int i = 0;  i < styles->count_styles;  i++) {
 6294-			if (styles->supported_styles[i] == (XIMPreeditNothing | XIMStatusNothing)) {
 6295-				found = RGFW_TRUE;
 6296-				break;
 6297-			}
 6298-		}
 6299-
 6300-	    XFree(styles);
 6301-	}
 6302-
 6303-	if (found == RGFW_FALSE) {
 6304-		XCloseIM(_RGFW->im);
 6305-		_RGFW->im = NULL;
 6306-	}
 6307-
 6308-	XIMCallback callback;
 6309-	callback.callback = (XIMProc) RGFW_x11_imCallback;
 6310-	callback.client_data = NULL;
 6311-	XSetIMValues(_RGFW->im, XNDestroyCallback, &callback, NULL);
 6312-}
 6313-
 6314-void* RGFW_getDisplay_X11(void) { return _RGFW->display; }
 6315-u64 RGFW_window_getWindow_X11(RGFW_window* win) { return (u64)win->src.window; }
 6316-
 6317-RGFWDEF RGFW_format RGFW_XImage_getFormat(XImage* image);
 6318-RGFW_format RGFW_XImage_getFormat(XImage* image) {
 6319-    switch (image->bits_per_pixel) {
 6320-        case 24:
 6321-            if (image->red_mask == 0xFF0000 && image->green_mask == 0x00FF00 && image->blue_mask == 0x0000FF)
 6322-                return RGFW_formatRGB8;
 6323-            if (image->red_mask == 0x0000FF && image->green_mask == 0x00FF00 && image->blue_mask == 0xFF0000)
 6324-                return RGFW_formatBGR8;
 6325-            break;
 6326-        case 32:
 6327-            if (image->red_mask == 0x00FF0000 && image->green_mask == 0x0000FF00 && image->blue_mask == 0x000000FF)
 6328-                return RGFW_formatBGRA8;
 6329-            if (image->red_mask == 0x000000FF && image->green_mask == 0x0000FF00 && image->blue_mask == 0x00FF0000)
 6330-                return RGFW_formatRGBA8;
 6331-            if (image->red_mask == 0x0000FF00 && image->green_mask == 0x00FF0000 && image->blue_mask == 0xFF000000)
 6332-                return RGFW_formatABGR8;
 6333-            if (image->red_mask == 0x00FF0000 && image->green_mask == 0x0000FF00 && image->blue_mask == 0x000000FF)
 6334-                return RGFW_formatARGB8;  /* ambiguous without alpha */
 6335-            break;
 6336-    }
 6337-	return RGFW_formatARGB8;
 6338-}
 6339-
 6340-
 6341-RGFW_bool RGFW_window_createSurfacePtr(RGFW_window* win, u8* data, i32 w, i32 h, RGFW_format format, RGFW_surface* surface) {
 6342-	RGFW_ASSERT(surface != NULL);
 6343-	surface->data = data;
 6344-	surface->w = w;
 6345-	surface->h = h;
 6346-	surface->format = format;
 6347-
 6348-	XWindowAttributes attrs;
 6349-	if (XGetWindowAttributes(_RGFW->display, win->src.window, &attrs) == 0) {
 6350-		RGFW_debugCallback(RGFW_typeError, RGFW_errBuffer, "Failed to get window attributes.");
 6351-		return RGFW_FALSE;
 6352-	}
 6353-
 6354-	surface->native.bitmap = XCreateImage(_RGFW->display,  attrs.visual,  (u32)attrs.depth,
 6355-										ZPixmap, 0, NULL, (u32)surface->w, (u32)surface->h, 32, 0);
 6356-
 6357-	surface->native.buffer = (u8*)RGFW_ALLOC((size_t)(w * h * 4));
 6358-	surface->native.format = RGFW_XImage_getFormat(surface->native.bitmap);
 6359-
 6360-	if (surface->native.bitmap == NULL) {
 6361-		RGFW_debugCallback(RGFW_typeError, RGFW_errBuffer,  "Failed to create XImage.");
 6362-		return RGFW_FALSE;
 6363-	}
 6364-
 6365-	surface->native.format = RGFW_formatBGRA8;
 6366-	return RGFW_TRUE;
 6367-}
 6368-
 6369-RGFW_format RGFW_FUNC(RGFW_nativeFormat)(void) { return RGFW_formatBGRA8; }
 6370-
 6371-RGFW_bool RGFW_FUNC(RGFW_createSurfacePtr) (u8* data, i32 w, i32 h, RGFW_format format, RGFW_surface* surface) {
 6372-	return RGFW_window_createSurfacePtr(_RGFW->root, data, w, h, format, surface);
 6373-}
 6374-
 6375-void RGFW_FUNC(RGFW_window_blitSurface) (RGFW_window* win, RGFW_surface* surface) {
 6376-	RGFW_ASSERT(surface != NULL);
 6377-	surface->native.bitmap->data = (char*)surface->native.buffer;
 6378-	RGFW_copyImageData((u8*)surface->native.buffer, surface->w, RGFW_MIN(win->h, surface->h), surface->native.format, surface->data, surface->format, surface->convertFunc);
 6379-
 6380-	XPutImage(_RGFW->display, win->src.window, win->src.gc, surface->native.bitmap, 0, 0, 0, 0, (u32)RGFW_MIN(win->w, surface->w), (u32)RGFW_MIN(win->h, surface->h));
 6381-	surface->native.bitmap->data = NULL;
 6382-	return;
 6383-}
 6384-
 6385-void RGFW_FUNC(RGFW_surface_freePtr) (RGFW_surface* surface) {
 6386-	RGFW_ASSERT(surface != NULL);
 6387-	RGFW_FREE(surface->native.buffer);
 6388-	XDestroyImage(surface->native.bitmap);
 6389-	return;
 6390-}
 6391-
 6392-#define RGFW_LOAD_ATOM(name) \
 6393-	static Atom name = 0; \
 6394-	if (name == 0) name = XInternAtom(_RGFW->display, #name, False);
 6395-
 6396-void RGFW_FUNC(RGFW_window_setBorder) (RGFW_window* win, RGFW_bool border) {
 6397-	RGFW_setBit(&win->internal.flags, RGFW_windowNoBorder, !border);
 6398-	RGFW_LOAD_ATOM(_MOTIF_WM_HINTS);
 6399-
 6400-	struct __x11WindowHints {
 6401-		unsigned long flags, functions, decorations, status;
 6402-		long input_mode;
 6403-	} hints;
 6404-	hints.flags = 2;
 6405-	hints.decorations = border;
 6406-
 6407-	XChangeProperty(_RGFW->display, win->src.window, _MOTIF_WM_HINTS, _MOTIF_WM_HINTS, 32, PropModeReplace, (u8*)&hints, 5);
 6408-
 6409-	if (RGFW_window_isHidden(win) == 0) {
 6410-		RGFW_window_hide(win);
 6411-		RGFW_window_show(win);
 6412-	}
 6413-}
 6414-
 6415-void RGFW_FUNC(RGFW_window_setRawMouseModePlatform) (RGFW_window* win, RGFW_bool state) {
 6416-	RGFW_UNUSED(win); RGFW_UNUSED(state);
 6417-}
 6418-
 6419-void RGFW_FUNC(RGFW_window_captureMousePlatform) (RGFW_window* win, RGFW_bool state) {
 6420-	if (state) {
 6421-		unsigned int event_mask = ButtonPressMask | ButtonReleaseMask | PointerMotionMask;
 6422-		XGrabPointer(_RGFW->display, win->src.window, True, event_mask, GrabModeAsync, GrabModeAsync, win->src.window, None, CurrentTime);
 6423-	} else {
 6424-		XUngrabPointer(_RGFW->display, CurrentTime);
 6425-	}
 6426-}
 6427-
 6428-#define RGFW_LOAD_LIBRARY(x, lib) if (x == NULL) x = dlopen(lib, RTLD_LAZY | RTLD_LOCAL)
 6429-#define RGFW_PROC_DEF(proc, name) if (name##SRC == NULL && proc != NULL) { \
 6430-	void* ptr = dlsym(proc, #name); \
 6431-	if (ptr != NULL) RGFW_MEMCPY(&name##SRC, &ptr, sizeof(PFN_##name)); \
 6432-}
 6433-
 6434-RGFWDEF void RGFW_window_getVisual(XVisualInfo* visual, RGFW_bool transparent);
 6435-void RGFW_window_getVisual(XVisualInfo* visual, RGFW_bool transparent) {
 6436-	visual->visual = DefaultVisual(_RGFW->display, DefaultScreen(_RGFW->display));
 6437-	visual->depth = DefaultDepth(_RGFW->display, DefaultScreen(_RGFW->display));
 6438-	if (transparent) {
 6439-		XMatchVisualInfo(_RGFW->display, DefaultScreen(_RGFW->display), 32, TrueColor, visual); /*!< for RGBA backgrounds */
 6440-		if (visual->depth != 32)
 6441-			RGFW_debugCallback(RGFW_typeWarning, RGFW_warningOpenGL, "Failed to load a 32-bit depth.");
 6442-	}
 6443-}
 6444-
 6445-RGFWDEF int RGFW_XErrorHandler(Display* display, XErrorEvent* ev);
 6446-int RGFW_XErrorHandler(Display* display, XErrorEvent* ev) {
 6447-    char errorText[512];
 6448-    XGetErrorText(display, ev->error_code, errorText, sizeof(errorText));
 6449-
 6450-    char buf[1024];
 6451-    RGFW_SNPRINTF(buf, sizeof(buf),  "[X Error] %s\n  Error code: %d\n  Request code: %d\n  Minor code: %d\n  Serial: %lu\n",
 6452-             errorText,
 6453-             ev->error_code, ev->request_code, ev->minor_code, ev->serial);
 6454-
 6455-    RGFW_debugCallback(RGFW_typeError, RGFW_errX11, buf);
 6456-    _RGFW->x11Error = ev;
 6457-    return 0;
 6458-}
 6459-
 6460-void RGFW_XCreateWindow (XVisualInfo visual, const char* name, RGFW_windowFlags flags, RGFW_window* win) {
 6461-	i64 event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask | FocusChangeMask |
 6462-						LeaveWindowMask | EnterWindowMask | ExposureMask | VisibilityChangeMask | PropertyChangeMask;
 6463-
 6464-	/* make X window attrubutes */
 6465-	XSetWindowAttributes swa;
 6466-    RGFW_MEMZERO(&swa, sizeof(swa));
 6467-
 6468-	win->src.parent = DefaultRootWindow(_RGFW->display);
 6469-
 6470-	Colormap cmap;
 6471-	swa.colormap = cmap = XCreateColormap(_RGFW->display,
 6472-		win->src.parent,
 6473-		visual.visual, AllocNone);
 6474-	swa.event_mask = event_mask;
 6475-    swa.background_pixmap = None;
 6476-
 6477-	/* create the window */
 6478-	win->src.window = XCreateWindow(_RGFW->display, win->src.parent, win->x, win->y, (u32)win->w, (u32)win->h,
 6479-		0, visual.depth, InputOutput, visual.visual,
 6480-		CWBorderPixel | CWColormap | CWEventMask, &swa);
 6481-
 6482-	win->src.flashEnd = 0;
 6483-
 6484-	XFreeColors(_RGFW->display, cmap, NULL, 0, 0);
 6485-
 6486-	XSaveContext(_RGFW->display, win->src.window, _RGFW->context, (XPointer)win);
 6487-
 6488-	win->src.gc = XCreateGC(_RGFW->display, win->src.window, 0, NULL);
 6489-
 6490-	if (_RGFW->im) {
 6491-		XIMCallback callback;
 6492-		callback.callback = (XIMProc) RGFW_x11_icCallback;
 6493-		callback.client_data = (XPointer) win;
 6494-
 6495-		win->src.ic = XCreateIC(_RGFW->im, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, XNClientWindow, win->src.window, XNFocusWindow, win->src.window, XNDestroyCallback, &callback, NULL);
 6496-	}
 6497-
 6498-
 6499-	/* In your .desktop app, if you set the property
 6500-	    StartupWMClass=RGFW that will assoicate the launcher icon
 6501-	     with your application - robrohan */
 6502-	if (_RGFW->className == NULL)
 6503-		_RGFW->className = (char*)name;
 6504-
 6505-	XClassHint hint;
 6506-	hint.res_class = (char*)_RGFW->className;
 6507-
 6508-	if (_RGFW->instName == NULL)	hint.res_name = (char*)name;
 6509-	else 						hint.res_name = (char*)_RGFW->instName;
 6510-
 6511-	XSetClassHint(_RGFW->display, win->src.window, &hint);
 6512-
 6513-	XWMHints hints;
 6514-	hints.flags = StateHint;
 6515-	hints.initial_state = NormalState;
 6516-
 6517-	XSetWMHints(_RGFW->display, win->src.window, &hints);
 6518-
 6519-	XSelectInput(_RGFW->display, (Drawable) win->src.window, event_mask); /*!< tell X11 what events we want */
 6520-
 6521-	/* make it so the user can't close the window until the program does */
 6522-    RGFW_LOAD_ATOM(WM_DELETE_WINDOW);
 6523-	XSetWMProtocols(_RGFW->display, (Drawable) win->src.window, &WM_DELETE_WINDOW, 1);
 6524-	/* set the background */
 6525-	RGFW_window_setName(win, name);
 6526-
 6527-	XMoveWindow(_RGFW->display, (Drawable) win->src.window, win->x, win->y); /*!< move the window to it's proper cords */
 6528-
 6529-	if (flags & RGFW_windowAllowDND) { /* init drag and drop atoms and turn on drag and drop for this window */
 6530-		win->internal.flags |= RGFW_windowAllowDND;
 6531-
 6532-		/* actions */
 6533-		Atom XdndAware = XInternAtom(_RGFW->display, "XdndAware", False);
 6534-		const u8 version = 5;
 6535-
 6536-		XChangeProperty(_RGFW->display, win->src.window,
 6537-			XdndAware, 4, 32,
 6538-			PropModeReplace, &version, 1); /*!< turns on drag and drop */
 6539-	}
 6540-
 6541-#ifdef RGFW_ADVANCED_SMOOTH_RESIZE
 6542-    RGFW_LOAD_ATOM(_NET_WM_SYNC_REQUEST_COUNTER)
 6543-    RGFW_LOAD_ATOM(_NET_WM_SYNC_REQUEST)
 6544-
 6545-    Atom protcols[2] = {_NET_WM_SYNC_REQUEST, WM_DELETE_WINDOW};
 6546-    XSetWMProtocols(_RGFW->display, win->src.window, protcols, 2);
 6547-
 6548-    XSyncValue initial_value;
 6549-    XSyncIntToValue(&initial_value, 0);
 6550-    win->src.counter = XSyncCreateCounter(_RGFW->display, initial_value);
 6551-
 6552-    XChangeProperty(_RGFW->display, win->src.window, _NET_WM_SYNC_REQUEST_COUNTER, XA_CARDINAL, 32, PropModeReplace, (u8*)&win->src.counter, 1);
 6553-#endif
 6554-
 6555-	win->src.x = win->x;
 6556-	win->src.y = win->y;
 6557-	win->src.w = win->w;
 6558-	win->src.h = win->h;
 6559-
 6560-	XSetWindowBackground(_RGFW->display, win->src.window, None);
 6561-    XClearWindow(_RGFW->display, win->src.window);
 6562-
 6563-	/* stupid hack to make resizing the window less bad */
 6564-	XSetWindowBackgroundPixmap(_RGFW->display, win->src.window, None);
 6565-}
 6566-
 6567-RGFW_window* RGFW_FUNC(RGFW_createWindowPlatform) (const char* name, RGFW_windowFlags flags, RGFW_window* win) {
 6568-	if ((flags & RGFW_windowOpenGL) || (flags & RGFW_windowEGL)) {
 6569-		win->src.window = 0;
 6570-		return win;
 6571-	}
 6572-
 6573-	XVisualInfo visual;
 6574-	RGFW_window_getVisual(&visual, RGFW_BOOL(win->internal.flags & RGFW_windowTransparent));
 6575-	RGFW_XCreateWindow(visual, name, flags, win);
 6576-	return win; /*return newly created window */
 6577-}
 6578-
 6579-RGFW_bool RGFW_FUNC(RGFW_getGlobalMouse) (i32* fX, i32* fY) {
 6580-	RGFW_init();
 6581-	i32 x, y;
 6582-	u32 z;
 6583-	Window window1, window2;
 6584-	XQueryPointer(_RGFW->display, XDefaultRootWindow(_RGFW->display), &window1, &window2, fX, fY, &x, &y, &z);
 6585-	return RGFW_TRUE;
 6586-}
 6587-
 6588-RGFWDEF void RGFW_XHandleClipboardSelection(XEvent* event);
 6589-void RGFW_XHandleClipboardSelection(XEvent* event) { RGFW_UNUSED(event);
 6590-    RGFW_LOAD_ATOM(ATOM_PAIR);
 6591-	RGFW_LOAD_ATOM(MULTIPLE);
 6592-	RGFW_LOAD_ATOM(TARGETS);
 6593-	RGFW_LOAD_ATOM(SAVE_TARGETS);
 6594-	RGFW_LOAD_ATOM(UTF8_STRING);
 6595-
 6596-    const XSelectionRequestEvent* request = &event->xselectionrequest;
 6597-    Atom formats[2] = {0};
 6598-    formats[0] = UTF8_STRING;
 6599-    formats[1] = XA_STRING;
 6600-    const int formatCount = sizeof(formats) / sizeof(formats[0]);
 6601-
 6602-    if (request->target == TARGETS) {
 6603-        Atom targets[4] = {0};
 6604-        targets[0] = TARGETS;
 6605-        targets[1] = MULTIPLE;
 6606-        targets[2] = UTF8_STRING;
 6607-        targets[3] = XA_STRING;
 6608-
 6609-        XChangeProperty(_RGFW->display, request->requestor, request->property,
 6610-                        XA_ATOM, 32, PropModeReplace, (u8*) targets, sizeof(targets) / sizeof(Atom));
 6611-    }  else if (request->target == MULTIPLE) {
 6612-		Atom* targets = NULL;
 6613-
 6614-		Atom actualType = 0;
 6615-		int actualFormat = 0;
 6616-		unsigned long count = 0, bytesAfter = 0;
 6617-
 6618-		XGetWindowProperty(_RGFW->display, request->requestor, request->property, 0, LONG_MAX,
 6619-							False, ATOM_PAIR, &actualType, &actualFormat, &count, &bytesAfter, (u8**) &targets);
 6620-
 6621-		unsigned long i;
 6622-		for (i = 0; i < (u32)count; i += 2) {
 6623-			if (targets[i] == UTF8_STRING || targets[i] == XA_STRING)
 6624-				XChangeProperty(_RGFW->display, request->requestor, targets[i + 1], targets[i],
 6625-					8, PropModeReplace, (const unsigned char *)_RGFW->clipboard, (i32)_RGFW->clipboard_len);
 6626-			else
 6627-				targets[i + 1] = None;
 6628-		}
 6629-
 6630-		XChangeProperty(_RGFW->display,
 6631-			request->requestor, request->property, ATOM_PAIR, 32,
 6632-			PropModeReplace, (u8*) targets, (i32)count);
 6633-
 6634-		XFlush(_RGFW->display);
 6635-		XFree(targets);
 6636-	} else if (request->target == SAVE_TARGETS)
 6637-        XChangeProperty(_RGFW->display, request->requestor, request->property, 0, 32, PropModeReplace, NULL, 0);
 6638-    else {
 6639-        int i;
 6640-        for (i = 0;  i < formatCount;  i++) {
 6641-			if (request->target != formats[i])
 6642-				continue;
 6643-			XChangeProperty(_RGFW->display, request->requestor, request->property, request->target,
 6644-								8, PropModeReplace, (u8*) _RGFW->clipboard, (i32)_RGFW->clipboard_len);
 6645-		}
 6646-	}
 6647-
 6648-    XEvent reply = { SelectionNotify };
 6649-    reply.xselection.property = request->property;
 6650-    reply.xselection.display = request->display;
 6651-    reply.xselection.requestor = request->requestor;
 6652-    reply.xselection.selection = request->selection;
 6653-    reply.xselection.target = request->target;
 6654-    reply.xselection.time = request->time;
 6655-
 6656-    XSendEvent(_RGFW->display, request->requestor, False, 0, &reply);
 6657-	XFlush(_RGFW->display);
 6658-}
 6659-
 6660-i32 RGFW_XHandleClipboardSelectionHelper(void);
 6661-
 6662-RGFW_key RGFW_FUNC(RGFW_physicalToMappedKey) (RGFW_key key) {
 6663-    KeyCode keycode = (KeyCode)RGFW_rgfwToApiKey(key);
 6664-    KeySym sym = XkbKeycodeToKeysym(_RGFW->display, keycode, 0, 0);
 6665-
 6666-    if (sym < 256) {
 6667-        return (RGFW_key)sym;
 6668-    }
 6669-
 6670-    switch (sym) {
 6671-        case XK_F1:  return RGFW_keyF1;
 6672-        case XK_F2:  return RGFW_keyF2;
 6673-        case XK_F3:  return RGFW_keyF3;
 6674-        case XK_F4:  return RGFW_keyF4;
 6675-        case XK_F5:  return RGFW_keyF5;
 6676-        case XK_F6:  return RGFW_keyF6;
 6677-        case XK_F7:  return RGFW_keyF7;
 6678-        case XK_F8:  return RGFW_keyF8;
 6679-        case XK_F9:  return RGFW_keyF9;
 6680-        case XK_F10: return RGFW_keyF10;
 6681-        case XK_F11: return RGFW_keyF11;
 6682-        case XK_F12: return RGFW_keyF12;
 6683-        case XK_F13: return RGFW_keyF13;
 6684-        case XK_F14: return RGFW_keyF14;
 6685-        case XK_F15: return RGFW_keyF15;
 6686-        case XK_F16: return RGFW_keyF16;
 6687-        case XK_F17: return RGFW_keyF17;
 6688-        case XK_F18: return RGFW_keyF18;
 6689-        case XK_F19: return RGFW_keyF19;
 6690-        case XK_F20: return RGFW_keyF20;
 6691-        case XK_F21: return RGFW_keyF21;
 6692-        case XK_F22: return RGFW_keyF22;
 6693-        case XK_F23: return RGFW_keyF23;
 6694-        case XK_F24: return RGFW_keyF24;
 6695-        case XK_F25: return RGFW_keyF25;
 6696-        case XK_Shift_L:   return RGFW_keyShiftL;
 6697-        case XK_Shift_R:   return RGFW_keyShiftR;
 6698-        case XK_Control_L: return RGFW_keyControlL;
 6699-        case XK_Control_R: return RGFW_keyControlR;
 6700-        case XK_Alt_L:     return RGFW_keyAltL;
 6701-        case XK_Alt_R:     return RGFW_keyAltR;
 6702-        case XK_Super_L:   return RGFW_keySuperL;
 6703-        case XK_Super_R:   return RGFW_keySuperR;
 6704-        case XK_Caps_Lock: return RGFW_keyCapsLock;
 6705-        case XK_Num_Lock:  return RGFW_keyNumLock;
 6706-        case XK_Scroll_Lock:return RGFW_keyScrollLock;
 6707-        case XK_Up:        return RGFW_keyUp;
 6708-        case XK_Down:      return RGFW_keyDown;
 6709-        case XK_Left:      return RGFW_keyLeft;
 6710-        case XK_Right:     return RGFW_keyRight;
 6711-        case XK_Home:      return RGFW_keyHome;
 6712-        case XK_End:       return RGFW_keyEnd;
 6713-        case XK_Page_Up:   return RGFW_keyPageUp;
 6714-        case XK_Page_Down: return RGFW_keyPageDown;
 6715-        case XK_Insert:    return RGFW_keyInsert;
 6716-        case XK_Menu:      return RGFW_keyMenu;
 6717-        case XK_KP_Add:      return RGFW_keyPadPlus;
 6718-        case XK_KP_Subtract: return RGFW_keyPadMinus;
 6719-        case XK_KP_Multiply: return RGFW_keyPadMultiply;
 6720-        case XK_KP_Divide:   return RGFW_keyPadSlash;
 6721-        case XK_KP_Equal:    return RGFW_keyPadEqual;
 6722-        case XK_KP_Enter:    return RGFW_keyPadReturn;
 6723-        case XK_KP_Decimal:  return RGFW_keyPadPeriod;
 6724-        case XK_KP_0: return RGFW_keyPad0;
 6725-        case XK_KP_1: return RGFW_keyPad1;
 6726-        case XK_KP_2: return RGFW_keyPad2;
 6727-        case XK_KP_3: return RGFW_keyPad3;
 6728-        case XK_KP_4: return RGFW_keyPad4;
 6729-        case XK_KP_5: return RGFW_keyPad5;
 6730-        case XK_KP_6: return RGFW_keyPad6;
 6731-        case XK_KP_7: return RGFW_keyPad7;
 6732-        case XK_KP_8: return RGFW_keyPad8;
 6733-        case XK_KP_9: return RGFW_keyPad9;
 6734-        case XK_Print: return RGFW_keyPrintScreen;
 6735-        case XK_Pause: return RGFW_keyPause;
 6736-        default: break;
 6737-    }
 6738-
 6739-    return RGFW_keyNULL;
 6740-}
 6741-
 6742-RGFWDEF void RGFW_XHandleEvent(void);
 6743-void RGFW_XHandleEvent(void) {
 6744-	RGFW_LOAD_ATOM(XdndTypeList);
 6745-	RGFW_LOAD_ATOM(XdndSelection);
 6746-	RGFW_LOAD_ATOM(XdndEnter);
 6747-	RGFW_LOAD_ATOM(XdndPosition);
 6748-	RGFW_LOAD_ATOM(XdndStatus);
 6749-	RGFW_LOAD_ATOM(XdndLeave);
 6750-	RGFW_LOAD_ATOM(XdndDrop);
 6751-	RGFW_LOAD_ATOM(XdndFinished);
 6752-	RGFW_LOAD_ATOM(XdndActionCopy);
 6753-	RGFW_LOAD_ATOM(_NET_WM_SYNC_REQUEST);
 6754-	RGFW_LOAD_ATOM(WM_PROTOCOLS);
 6755-	RGFW_LOAD_ATOM(WM_STATE);
 6756-	RGFW_LOAD_ATOM(_NET_WM_STATE);
 6757-
 6758-	static float deltaX = 0.0f;
 6759-	static float deltaY = 0.0f;
 6760-
 6761-	XEvent E;
 6762-
 6763-	XNextEvent(_RGFW->display, &E);
 6764-
 6765-	if (E.type != GenericEvent) {
 6766-		deltaX = 0.0f;
 6767-		deltaY = 0.0f;
 6768-	}
 6769-
 6770-	if (E.type == _RGFW->xrandrEventBase + RRNotify) {
 6771-		RGFW_pollMonitors();
 6772-		return;
 6773-	}
 6774-
 6775-	switch (E.type) {
 6776-		case SelectionRequest:
 6777-			RGFW_XHandleClipboardSelection(&E);
 6778-			return;
 6779-		case GenericEvent: {
 6780-			XGetEventData(_RGFW->display, &E.xcookie);
 6781-			switch (E.xcookie.evtype) {
 6782-				case XI_RawMotion: {
 6783-					XIRawEvent* raw = (XIRawEvent *)E.xcookie.data;
 6784-					if (raw->valuators.mask_len == 0) {
 6785-						XFreeEventData(_RGFW->display, &E.xcookie);
 6786-						return;
 6787-					}
 6788-
 6789-					i32 index = 0;
 6790-					if (XIMaskIsSet(raw->valuators.mask, 0) != 0) {
 6791-						deltaX += (float)raw->raw_values[index];
 6792-						index += 1;
 6793-					}
 6794-
 6795-					if (XIMaskIsSet(raw->valuators.mask, 1) != 0)
 6796-						deltaY += (float)raw->raw_values[index];
 6797-
 6798-					_RGFW->vectorX = (float)deltaX;
 6799-					_RGFW->vectorY = (float)deltaY;
 6800-					RGFW_rawMotionCallback(_RGFW->root, _RGFW->vectorX, _RGFW->vectorY);
 6801-				}
 6802-				default: break;
 6803-			}
 6804-
 6805-			XFreeEventData(_RGFW->display, &E.xcookie);
 6806-			return;
 6807-		}
 6808-	}
 6809-
 6810-	RGFW_window* win = NULL;
 6811-	if (XFindContext(_RGFW->display, E.xany.window, _RGFW->context, (XPointer*) &win) != 0) {
 6812-		return;
 6813-	}
 6814-
 6815-	if (win->src.flashEnd) {
 6816-		if ((win->src.flashEnd <= RGFW_linux_getTimeNS()) || RGFW_window_isInFocus(win)) {
 6817-			RGFW_window_flash(win, RGFW_flashCancel);
 6818-		}
 6819-	}
 6820-
 6821-
 6822-	/*
 6823-		Repeated key presses are sent as a release followed by another press at the same time.
 6824-		We want to convert that into a single key press event with the repeat flag set
 6825-	*/
 6826-
 6827-	RGFW_bool keyRepeat = RGFW_FALSE;
 6828-
 6829-	if (E.type == KeyRelease && XEventsQueued(_RGFW->display, QueuedAfterReading)) {
 6830-		XEvent NE;
 6831-		XPeekEvent(_RGFW->display, &NE);
 6832-		if (NE.type == KeyPress && E.xkey.time == NE.xkey.time && E.xkey.keycode == NE.xkey.keycode) {
 6833-			/* Use the next KeyPress event */
 6834-			XNextEvent(_RGFW->display, &E);
 6835-			keyRepeat = RGFW_TRUE;
 6836-		}
 6837-	}
 6838-
 6839-	switch (E.type) {
 6840-		case KeyPress: {
 6841-			if (!(win->internal.enabledEvents & RGFW_keyPressedFlag)) return;
 6842-			RGFW_key value = (u8)RGFW_apiKeyToRGFW(E.xkey.keycode);
 6843-
 6844-			XkbStateRec state;
 6845-			XkbGetState(_RGFW->display, XkbUseCoreKbd, &state);
 6846-			RGFW_keyUpdateKeyMods(win, (state.locked_mods & LockMask), (state.locked_mods & Mod2Mask), (state.locked_mods & Mod3Mask));
 6847-
 6848-			if (win->src.ic && XFilterEvent(&E, None) == False) {
 6849-				char buffer[100];
 6850-				char* chars = buffer;
 6851-
 6852-				Status status;
 6853-				size_t count = (size_t)Xutf8LookupString(win->src.ic, &E.xkey, buffer, sizeof(buffer) - 1, NULL, &status);
 6854-
 6855-				if (status == XBufferOverflow) {
 6856-					chars = (char*)RGFW_ALLOC(count + 1);
 6857-					count = (size_t)Xutf8LookupString(win->src.ic, &E.xkey, chars, (int)count, NULL, &status);
 6858-				}
 6859-
 6860-				if (status == XLookupChars || status == XLookupBoth) {
 6861-					chars[count] = '\0';
 6862-					for (size_t index = 0; index < count;
 6863-						RGFW_keyCharCallback(win, RGFW_decodeUTF8(&chars[index], &index))
 6864-					);
 6865-				}
 6866-
 6867-				if (chars != buffer)
 6868-					RGFW_FREE(chars);
 6869-			} else {
 6870-				Window root = DefaultRootWindow(_RGFW->display);
 6871-				Window ret_root, ret_child;
 6872-				int root_x, root_y, win_x, win_y;
 6873-				unsigned int mask;
 6874-				XQueryPointer(_RGFW->display, root, &ret_root, &ret_child, &root_x, &root_y, &win_x, &win_y, &mask);
 6875-				KeySym sym = (KeySym)XkbKeycodeToKeysym(_RGFW->display, (KeyCode)E.xkey.keycode, 0, (KeyCode)mask & ShiftMask ? 1 : 0);
 6876-
 6877-				if ((mask & LockMask) && sym >= XK_a && sym <= XK_z)
 6878-					sym = (mask & ShiftMask) ? sym + 32 : sym - 32;
 6879-				if ((u8)sym != (u32)sym)
 6880-					sym = 0;
 6881-
 6882-				RGFW_keyCharCallback(win, (u8)sym);
 6883-			}
 6884-
 6885-			RGFW_keyCallback(win, value, win->internal.mod, keyRepeat, RGFW_TRUE);
 6886-			break;
 6887-		}
 6888-		case KeyRelease: {
 6889-			if (!(win->internal.enabledEvents & RGFW_keyReleasedFlag)) return;
 6890-
 6891-			RGFW_key value = (u8)RGFW_apiKeyToRGFW(E.xkey.keycode);
 6892-
 6893-			XkbStateRec state;
 6894-			XkbGetState(_RGFW->display, XkbUseCoreKbd, &state);
 6895-			RGFW_keyUpdateKeyMods(win, (state.locked_mods & LockMask), (state.locked_mods & Mod2Mask), (state.locked_mods & Mod3Mask));
 6896-
 6897-			RGFW_keyCallback(win, value, win->internal.mod, RGFW_FALSE, RGFW_FALSE);
 6898-			break;
 6899-		}
 6900-		case ButtonPress: {
 6901-			RGFW_bool scroll = RGFW_FALSE;
 6902-			if (E.xbutton.button >= Button4 && E.xbutton.button <= 7) {
 6903-				scroll = RGFW_TRUE;
 6904-			}
 6905-
 6906-			float scrollX = 0.0f;
 6907-			float scrollY = 0.0f;
 6908-			RGFW_mouseButton value = 0;
 6909-
 6910-			switch (E.xbutton.button) {
 6911-				case Button1: value = RGFW_mouseLeft; break;
 6912-				case Button2: value = RGFW_mouseMiddle; break;
 6913-				case Button3: value = RGFW_mouseRight; break;
 6914-				case Button4: scrollY = 1.0; break;
 6915-				case Button5: scrollY = -1.0; break;
 6916-				case 6: scrollX = 1.0f; break;
 6917-				case 7: scrollX = -1.0f; break;
 6918-				default:
 6919-					value = (u8)E.xbutton.button - Button1 - 4;
 6920-					break;
 6921-			}
 6922-
 6923-			if (scroll) {
 6924-				RGFW_mouseScrollCallback(win, scrollX, scrollY);
 6925-				break;
 6926-			}
 6927-
 6928-			RGFW_mouseButtonCallback(win, value, RGFW_TRUE);
 6929-			break;
 6930-		}
 6931-		case ButtonRelease: {
 6932-			if (E.xbutton.button >= Button4 && E.xbutton.button <= 7) break;
 6933-
 6934-			RGFW_mouseButton value = 0;
 6935-			switch(E.xbutton.button) {
 6936-				case Button1: value = RGFW_mouseLeft; break;
 6937-				case Button2: value = RGFW_mouseMiddle; break;
 6938-				case Button3: value = RGFW_mouseRight; break;
 6939-				default:
 6940-					value = (u8)E.xbutton.button - Button1 - 4;
 6941-					break;
 6942-			}
 6943-
 6944-			RGFW_mouseButtonCallback(win, value, RGFW_FALSE);
 6945-			break;
 6946-		}
 6947-		case MotionNotify:
 6948-			RGFW_mousePosCallback(win, E.xmotion.x, E.xmotion.y);
 6949-			break;
 6950-
 6951-		case Expose: {
 6952-			RGFW_windowRefreshCallback(win, 0, 0, win->w, win->h);
 6953-
 6954-#ifdef RGFW_ADVANCED_SMOOTH_RESIZE
 6955-			XSyncValue value;
 6956-			XSyncIntToValue(&value, (i32)win->src.counter_value);
 6957-			XSyncSetCounter(_RGFW->display, win->src.counter, value);
 6958-#endif
 6959-			break;
 6960-		}
 6961-
 6962-		case PropertyNotify:
 6963-			if (E.xproperty.state != PropertyNewValue) break;
 6964-
 6965-			if (E.xproperty.atom == WM_STATE) {
 6966-				if (RGFW_window_isMinimized(win) && !(win->internal.flags & RGFW_windowMinimized)) {
 6967-					RGFW_windowMinimizedCallback(win);
 6968-					break;
 6969-				}
 6970-			} else if (E.xproperty.atom == _NET_WM_STATE) {
 6971-				if (RGFW_window_isMaximized(win) && !(win->internal.flags & RGFW_windowMaximize)) {
 6972-					RGFW_windowMaximizedCallback(win, win->x, win->y, win->w, win->h);
 6973-					break;
 6974-				}
 6975-			}
 6976-
 6977-			RGFW_window_checkMode(win);
 6978-			break;
 6979-		case MapNotify: case UnmapNotify: 		RGFW_window_checkMode(win); break;
 6980-		case ClientMessage: {
 6981-			RGFW_LOAD_ATOM(WM_DELETE_WINDOW);
 6982-			/* if the client closed the window */
 6983-			if (E.xclient.data.l[0] == (long)WM_DELETE_WINDOW) {
 6984-				RGFW_windowCloseCallback(win);
 6985-				break;
 6986-			}
 6987-#ifdef RGFW_ADVANCED_SMOOTH_RESIZE
 6988-			if (E.xclient.message_type == WM_PROTOCOLS && (Atom)E.xclient.data.l[0] == _NET_WM_SYNC_REQUEST) {
 6989-				RGFW_windowRefreshCallback(win, 0, 0, win->w, win->h);
 6990-				win->src.counter_value = 0;
 6991-				win->src.counter_value |= E.xclient.data.l[2];
 6992-				win->src.counter_value |= (E.xclient.data.l[3] << 32);
 6993-
 6994-				XSyncValue value;
 6995-				XSyncIntToValue(&value, (i32)win->src.counter_value);
 6996-				XSyncSetCounter(_RGFW->display, win->src.counter, value);
 6997-				break;
 6998-			}
 6999-#endif
 7000-			if ((win->internal.flags & RGFW_windowAllowDND) == 0 || _RGFW->x11Version > RGFW_XDND_VERSION) {
 7001-				return;
 7002-			}
 7003-
 7004-			i32 dragX = 0;
 7005-			i32 dragY = 0;
 7006-
 7007-			if (E.xclient.message_type == XdndEnter) {
 7008-				unsigned long count;
 7009-				Atom* formats;
 7010-				Atom real_formats[3];
 7011-				Bool list = E.xclient.data.l[1] & 1;
 7012-
 7013-				_RGFW->x11Source = (Window)E.xclient.data.l[0];
 7014-				_RGFW->x11Version = E.xclient.data.l[1] >> 24;
 7015-				_RGFW->x11Format = None;
 7016-				if (list) {
 7017-					Atom actualType;
 7018-					i32 actualFormat;
 7019-					unsigned long bytesAfter;
 7020-
 7021-					XGetWindowProperty(
 7022-						_RGFW->display, _RGFW->x11Source, XdndTypeList,
 7023-						0, LONG_MAX, False, 4,
 7024-						&actualType, &actualFormat, &count, &bytesAfter, (u8**)&formats
 7025-					);
 7026-				} else {
 7027-					count = 0;
 7028-
 7029-					size_t i;
 7030-					for (i = 2; i < (2 + 3); i++) {
 7031-						if (E.xclient.data.l[i] != None) {
 7032-							real_formats[count] = (unsigned long int)E.xclient.data.l[i];
 7033-							count += 1;
 7034-						}
 7035-					}
 7036-
 7037-					formats = real_formats;
 7038-				}
 7039-
 7040-				Atom XtextPlain = XInternAtom(_RGFW->display, "text/plain", False);
 7041-				Atom XtextUriList = XInternAtom(_RGFW->display, "text/uri-list", False);
 7042-
 7043-				size_t i;
 7044-				for (i = 0; i < count; i++) {
 7045-					if (formats[i] == XtextUriList)  _RGFW->x11TransferType  = RGFW_dataFile;
 7046-					else if (formats[i] == XtextPlain) _RGFW->x11TransferType  = RGFW_dataText;
 7047-					else continue;
 7048-
 7049-					_RGFW->x11Format = (int)formats[i];
 7050-					break;
 7051-				}
 7052-
 7053-				if (list && formats) {
 7054-					XFree(formats);
 7055-				}
 7056-
 7057-
 7058-				RGFW_dataDragCallback(win, _RGFW->x11TransferType , RGFW_dndActionEnter, dragX, dragY);
 7059-			} else if (E.xclient.message_type == XdndPosition) {
 7060-				const i32 xabs = (E.xclient.data.l[2] >> 16) & 0xffff;
 7061-				const i32 yabs = (E.xclient.data.l[2]) & 0xffff;
 7062-				Window dummy;
 7063-				i32 xpos, ypos;
 7064-
 7065-				XTranslateCoordinates(
 7066-					_RGFW->display, XDefaultRootWindow(_RGFW->display), win->src.window,
 7067-					xabs, yabs, &xpos, &ypos, &dummy
 7068-				);
 7069-
 7070-				dragX = xpos;
 7071-				dragY = ypos;
 7072-
 7073-				RGFW_mousePosCallback(win, xpos, ypos);
 7074-                XEvent reply = { ClientMessage };
 7075-				reply.xclient.window = _RGFW->x11Source;
 7076-                reply.xclient.message_type = XdndStatus;
 7077-                reply.xclient.format = 32;
 7078-				reply.xclient.data.l[0] = (long)win->src.window;
 7079-                reply.xclient.data.l[2] = 0;
 7080-                reply.xclient.data.l[3] = 0;
 7081-
 7082-				if (_RGFW->x11Format) {
 7083-					reply.xclient.data.l[1] = 1;
 7084-					if (_RGFW->x11Version >= 2)
 7085-						reply.xclient.data.l[4] = (long)XdndActionCopy;
 7086-				}
 7087-
 7088-				XSendEvent(_RGFW->display, _RGFW->x11Source, False, NoEventMask, &reply);
 7089-				XFlush(_RGFW->display);
 7090-
 7091-
 7092-				RGFW_dataDragCallback(win, _RGFW->x11TransferType, RGFW_dndActionMove, dragX, dragY);
 7093-			} else if (E.xclient.message_type == XdndLeave) {
 7094-				RGFW_dataDragCallback(win, _RGFW->x11TransferType, RGFW_dndActionExit, dragX, dragY);
 7095-			} else if (E.xclient.message_type == XdndDrop) {
 7096-				if (_RGFW->x11Format) {
 7097-					Time time = (_RGFW->x11Version >= 1)
 7098-						? (Time)E.xclient.data.l[2]
 7099-						: CurrentTime;
 7100-					XConvertSelection(
 7101-						_RGFW->display, XdndSelection, (Atom)_RGFW->x11Format,
 7102-						XdndSelection, win->src.window, time
 7103-					);
 7104-				} else if (_RGFW->x11Version >= 2) {
 7105-                    XEvent reply = { ClientMessage };
 7106-                    reply.xclient.window = _RGFW->x11Source;
 7107-                    reply.xclient.message_type = XdndFinished;
 7108-                    reply.xclient.format = 32;
 7109-                    reply.xclient.data.l[0] = (long)win->src.window;
 7110-                    reply.xclient.data.l[1] = 0;
 7111-                    reply.xclient.data.l[2] = None;
 7112-
 7113-					XSendEvent(_RGFW->display, _RGFW->x11Source, False, NoEventMask, &reply);
 7114-					XFlush(_RGFW->display);
 7115-				}
 7116-			}
 7117-		} break;
 7118-		case SelectionNotify: {
 7119-			/* this is only for checking for xdnd drops */
 7120-			if (!(win->internal.enabledEvents & RGFW_dataDropFlag) || E.xselection.property != XdndSelection || !(win->internal.flags & RGFW_windowAllowDND))
 7121-				return;
 7122-			char* data;
 7123-			unsigned long result;
 7124-
 7125-			Atom actualType;
 7126-			i32 actualFormat;
 7127-			unsigned long bytesAfter;
 7128-
 7129-			XGetWindowProperty(_RGFW->display, E.xselection.requestor, E.xselection.property, 0, LONG_MAX, False, E.xselection.target, &actualType, &actualFormat, &result, &bytesAfter, (u8**) &data);
 7130-
 7131-			if (result != 0) {
 7132-				RGFW_unix_parseURI(win, data);
 7133-
 7134-				if (data)
 7135-					XFree(data);
 7136-			}
 7137-
 7138-			if (_RGFW->x11Version >= 2) {
 7139-				XEvent reply = { ClientMessage };
 7140-				reply.xclient.window = _RGFW->x11Source;
 7141-				reply.xclient.message_type = XdndFinished;
 7142-				reply.xclient.format = 32;
 7143-				reply.xclient.data.l[0] = (long)win->src.window;
 7144-				reply.xclient.data.l[1] = (long int)result;
 7145-				reply.xclient.data.l[2] = (long int)XdndActionCopy;
 7146-				XSendEvent(_RGFW->display, _RGFW->x11Source, False, NoEventMask, &reply);
 7147-				XFlush(_RGFW->display);
 7148-			}
 7149-			break;
 7150-		}
 7151-		case FocusIn:
 7152-            if (win->src.ic) XSetICFocus(win->src.ic);
 7153-			RGFW_windowFocusCallback(win, 1);
 7154-			break;
 7155-		case FocusOut:
 7156-            if (win->src.ic) XUnsetICFocus(win->src.ic);
 7157-			RGFW_windowFocusCallback(win, 0);
 7158-			break;
 7159-		case EnterNotify: {
 7160-			RGFW_mouseNotifyCallback(win, E.xcrossing.x, E.xcrossing.y, RGFW_TRUE);
 7161-			break;
 7162-		}
 7163-
 7164-		case LeaveNotify: {
 7165-			RGFW_mouseNotifyCallback(win, win->internal.lastMouseX, win->internal.lastMouseY, RGFW_FALSE);
 7166-			break;
 7167-		}
 7168-        case ReparentNotify:
 7169-            win->src.parent = E.xreparent.parent;
 7170-			break;
 7171-		case ConfigureNotify: {
 7172-			/* detect resize */
 7173-			if (E.xconfigure.width != win->src.w || E.xconfigure.height != win->src.h) {
 7174-				RGFW_window_checkMode(win);
 7175-				win->src.w = E.xconfigure.width;
 7176-				win->src.h = E.xconfigure.height;
 7177-				RGFW_windowResizedCallback(win, E.xconfigure.width, E.xconfigure.height);
 7178-			}
 7179-
 7180-			i32 x = E.xconfigure.x;
 7181-			i32 y = E.xconfigure.y;
 7182-
 7183-			/*
 7184-			 if the event came from the server and we're not a direct child of the root window then
 7185-			 we're using local coords which need to be translated into screen coords
 7186-			*/
 7187-			Window root = DefaultRootWindow(_RGFW->display);
 7188-			if (E.xany.send_event == 0 && win->src.parent != root) {
 7189-				Window dummy = 0;
 7190-				XTranslateCoordinates(_RGFW->display, win->src.parent, root, x, y, &x, &y, &dummy);
 7191-			}
 7192-
 7193-			/* detect move */
 7194-			if (E.xconfigure.x != win->src.x || E.xconfigure.y != win->src.y) {
 7195-				win->src.x = E.xconfigure.x;
 7196-				win->src.y = E.xconfigure.y;
 7197-				RGFW_windowMovedCallback(win, E.xconfigure.x, E.xconfigure.y);
 7198-			}
 7199-			return;
 7200-		}
 7201-		default:
 7202-			break;
 7203-	}
 7204-
 7205-	XFlush(_RGFW->display);
 7206-}
 7207-
 7208-RGFW_bool RGFW_FUNC(RGFW_window_fetchSize) (RGFW_window* win, i32* w, i32* h) {
 7209-    XWindowAttributes attribs;
 7210-    XGetWindowAttributes(_RGFW->display, win->src.window, &attribs);
 7211-
 7212-    win->w = attribs.width;
 7213-    win->h = attribs.height;
 7214-
 7215-	return RGFW_window_getSize(win, w, h);
 7216-}
 7217-
 7218-void RGFW_FUNC(RGFW_pollEvents) (void) {
 7219-	RGFW_resetPrevState();
 7220-
 7221-	XPending(_RGFW->display);
 7222-    /* if there is no unread queued events, get a new one */
 7223-	while (QLength(_RGFW->display)) {
 7224-		RGFW_XHandleEvent();
 7225-	}
 7226-}
 7227-
 7228-void RGFW_FUNC(RGFW_window_move) (RGFW_window* win, i32 x, i32 y) {
 7229-	RGFW_ASSERT(win != NULL);
 7230-	win->x = x;
 7231-	win->y = y;
 7232-
 7233-	XMoveWindow(_RGFW->display, win->src.window, x, y);
 7234-	return;
 7235-}
 7236-
 7237-
 7238-void RGFW_FUNC(RGFW_window_resize) (RGFW_window* win, i32 w, i32 h) {
 7239-	RGFW_ASSERT(win != NULL);
 7240-	win->w = (i32)w;
 7241-	win->h = (i32)h;
 7242-
 7243-	XResizeWindow(_RGFW->display, win->src.window, (u32)w, (u32)h);
 7244-
 7245-	if ((win->internal.flags & RGFW_windowNoResize)) {
 7246-		XSizeHints sh;
 7247-		sh.flags = (1L << 4) | (1L << 5);
 7248-		sh.min_width = sh.max_width = (i32)w;
 7249-		sh.min_height = sh.max_height = (i32)h;
 7250-
 7251-		XSetWMSizeHints(_RGFW->display, (Drawable) win->src.window, &sh, XA_WM_NORMAL_HINTS);
 7252-	}
 7253-	return;
 7254-}
 7255-
 7256-void RGFW_FUNC(RGFW_window_setAspectRatio) (RGFW_window* win, i32 w, i32 h) {
 7257-	RGFW_ASSERT(win != NULL);
 7258-
 7259-
 7260-	if (w == 0 && h == 0)
 7261-		return;
 7262-	XSizeHints hints;
 7263-	long flags;
 7264-
 7265-	XGetWMNormalHints(_RGFW->display, win->src.window, &hints, &flags);
 7266-
 7267-	hints.flags |= PAspect;
 7268-
 7269-	hints.min_aspect.x = hints.max_aspect.x = (i32)w;
 7270-	hints.min_aspect.y = hints.max_aspect.y = (i32)h;
 7271-
 7272-	XSetWMNormalHints(_RGFW->display, win->src.window, &hints);
 7273-    return;
 7274-}
 7275-
 7276-void RGFW_FUNC(RGFW_window_setMinSize) (RGFW_window* win, i32 w, i32 h) {
 7277-	RGFW_ASSERT(win != NULL);
 7278-
 7279-    long flags;
 7280-	XSizeHints hints;
 7281-    RGFW_MEMZERO(&hints, sizeof(XSizeHints));
 7282-
 7283-	XGetWMNormalHints(_RGFW->display, win->src.window, &hints, &flags);
 7284-
 7285-	hints.flags |= PMinSize;
 7286-
 7287-	hints.min_width = (i32)w;
 7288-	hints.min_height = (i32)h;
 7289-
 7290-	XSetWMNormalHints(_RGFW->display, win->src.window, &hints);
 7291-    return;
 7292-}
 7293-
 7294-void RGFW_FUNC(RGFW_window_setMaxSize) (RGFW_window* win, i32 w, i32 h) {
 7295-	RGFW_ASSERT(win != NULL);
 7296-
 7297-    long flags;
 7298-	XSizeHints hints;
 7299-    RGFW_MEMZERO(&hints, sizeof(XSizeHints));
 7300-
 7301-	XGetWMNormalHints(_RGFW->display, win->src.window, &hints, &flags);
 7302-
 7303-	hints.flags |= PMaxSize;
 7304-
 7305-	hints.max_width = (i32)w;
 7306-	hints.max_height = (i32)h;
 7307-
 7308-	XSetWMNormalHints(_RGFW->display, win->src.window, &hints);
 7309-	return;
 7310-}
 7311-
 7312-void RGFW_toggleXMaximized(RGFW_window* win, RGFW_bool maximized);
 7313-void RGFW_toggleXMaximized(RGFW_window* win, RGFW_bool maximized) {
 7314-	RGFW_ASSERT(win != NULL);
 7315-	RGFW_LOAD_ATOM(_NET_WM_STATE);
 7316-	RGFW_LOAD_ATOM(_NET_WM_STATE_MAXIMIZED_VERT);
 7317-	RGFW_LOAD_ATOM(_NET_WM_STATE_MAXIMIZED_HORZ);
 7318-
 7319-	XEvent xev = {0};
 7320-	xev.type = ClientMessage;
 7321-	xev.xclient.window = win->src.window;
 7322-	xev.xclient.message_type = _NET_WM_STATE;
 7323-	xev.xclient.format = 32;
 7324-	xev.xclient.data.l[0] = maximized;
 7325-	xev.xclient.data.l[1] = (long int)_NET_WM_STATE_MAXIMIZED_HORZ;
 7326-	xev.xclient.data.l[2] = (long int)_NET_WM_STATE_MAXIMIZED_VERT;
 7327-	xev.xclient.data.l[3] = 0;
 7328-	xev.xclient.data.l[4] = 0;
 7329-
 7330-	XSendEvent(_RGFW->display, DefaultRootWindow(_RGFW->display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
 7331-}
 7332-
 7333-void RGFW_FUNC(RGFW_window_maximize) (RGFW_window* win) {
 7334-	win->internal.oldX = win->x;
 7335-	win->internal.oldY = win->y;
 7336-	win->internal.oldW = win->w;
 7337-	win->internal.oldH = win->h;
 7338-
 7339-    RGFW_toggleXMaximized(win, 1);
 7340-	RGFW_window_fetchSize(win, NULL, NULL);
 7341-    return;
 7342-}
 7343-
 7344-void RGFW_FUNC(RGFW_window_focus) (RGFW_window* win) {
 7345-	RGFW_ASSERT(win);
 7346-
 7347-	XWindowAttributes attr;
 7348-	XGetWindowAttributes(_RGFW->display, win->src.window, &attr);
 7349-	if (attr.map_state != IsViewable) return;
 7350-
 7351-	XSetInputFocus(_RGFW->display, win->src.window, RevertToPointerRoot, CurrentTime);
 7352-	XFlush(_RGFW->display);
 7353-}
 7354-
 7355-void RGFW_FUNC(RGFW_window_raise) (RGFW_window* win) {
 7356-	RGFW_ASSERT(win);
 7357-	XMapRaised(_RGFW->display, win->src.window);
 7358-	RGFW_window_setFullscreen(win, RGFW_window_isFullscreen(win));
 7359-}
 7360-
 7361-void RGFW_window_setXAtom(RGFW_window* win, Atom netAtom, RGFW_bool fullscreen);
 7362-void RGFW_window_setXAtom(RGFW_window* win, Atom netAtom, RGFW_bool fullscreen) {
 7363-	RGFW_ASSERT(win != NULL);
 7364-	RGFW_LOAD_ATOM(_NET_WM_STATE);
 7365-
 7366-	XEvent xev = {0};
 7367-	xev.xclient.type = ClientMessage;
 7368-	xev.xclient.serial = 0;
 7369-	xev.xclient.send_event = True;
 7370-	xev.xclient.message_type = _NET_WM_STATE;
 7371-	xev.xclient.window = win->src.window;
 7372-	xev.xclient.format = 32;
 7373-	xev.xclient.data.l[0] = fullscreen;
 7374-	xev.xclient.data.l[1] = (long int)netAtom;
 7375-	xev.xclient.data.l[2] = 0;
 7376-
 7377-	XSendEvent(_RGFW->display, DefaultRootWindow(_RGFW->display), False, SubstructureNotifyMask | SubstructureRedirectMask, &xev);
 7378-}
 7379-
 7380-void RGFW_FUNC(RGFW_window_setFullscreen)(RGFW_window* win, RGFW_bool fullscreen) {
 7381-	RGFW_ASSERT(win != NULL);
 7382-
 7383-	if (fullscreen) {
 7384-		win->internal.flags |= RGFW_windowFullscreen;
 7385-		win->internal.oldX = win->x;
 7386-		win->internal.oldY = win->y;
 7387-		win->internal.oldW = win->w;
 7388-		win->internal.oldH = win->h;
 7389-	}
 7390-	else win->internal.flags &= ~(u32)RGFW_windowFullscreen;
 7391-
 7392-	XRaiseWindow(_RGFW->display, win->src.window);
 7393-
 7394-	RGFW_LOAD_ATOM(_NET_WM_STATE_FULLSCREEN);
 7395-	RGFW_window_setXAtom(win, _NET_WM_STATE_FULLSCREEN, fullscreen);
 7396-
 7397-	if (!(win->internal.flags & RGFW_windowTransparent)) {
 7398-		const unsigned char value = fullscreen;
 7399-		RGFW_LOAD_ATOM(_NET_WM_BYPASS_COMPOSITOR);
 7400-		XChangeProperty(
 7401-			_RGFW->display, win->src.window,
 7402-			_NET_WM_BYPASS_COMPOSITOR, XA_CARDINAL, 32,
 7403-			PropModeReplace, &value, 1);
 7404-	}
 7405-}
 7406-
 7407-void RGFW_FUNC(RGFW_window_setFloating)(RGFW_window* win, RGFW_bool floating) {
 7408-    RGFW_ASSERT(win != NULL);
 7409-	RGFW_LOAD_ATOM(_NET_WM_STATE_ABOVE);
 7410-	RGFW_window_setXAtom(win, _NET_WM_STATE_ABOVE, floating);
 7411-}
 7412-
 7413-void RGFW_FUNC(RGFW_window_setOpacity)(RGFW_window* win, u8 opacity) {
 7414-	RGFW_ASSERT(win != NULL);
 7415-    const u32 value = (u32) (0xffffffffu * (double) opacity);
 7416-	RGFW_LOAD_ATOM(NET_WM_WINDOW_OPACITY);
 7417-    XChangeProperty(_RGFW->display, win->src.window,
 7418-					NET_WM_WINDOW_OPACITY, XA_CARDINAL, 32, PropModeReplace, (unsigned char*) &value, 1);
 7419-}
 7420-
 7421-void RGFW_FUNC(RGFW_window_minimize)(RGFW_window* win) {
 7422-	RGFW_ASSERT(win != NULL);
 7423-
 7424-	if (RGFW_window_isMaximized(win)) return;
 7425-
 7426-	win->internal.oldX = win->x;
 7427-	win->internal.oldY = win->y;
 7428-	win->internal.oldW = win->w;
 7429-	win->internal.oldH = win->h;
 7430-    XIconifyWindow(_RGFW->display, win->src.window, DefaultScreen(_RGFW->display));
 7431-	XFlush(_RGFW->display);
 7432-}
 7433-
 7434-void RGFW_FUNC(RGFW_window_restore)(RGFW_window* win) {
 7435-	RGFW_ASSERT(win != NULL);
 7436-	RGFW_toggleXMaximized(win, RGFW_FALSE);
 7437-	RGFW_window_move(win, win->internal.oldX, win->internal.oldY);
 7438-	RGFW_window_resize(win, win->internal.oldW, win->internal.oldH);
 7439-
 7440-    RGFW_window_show(win);
 7441-    XFlush(_RGFW->display);
 7442-}
 7443-
 7444-RGFW_bool RGFW_FUNC(RGFW_window_isFloating)(RGFW_window* win) {
 7445-    RGFW_LOAD_ATOM(_NET_WM_STATE);
 7446-	RGFW_LOAD_ATOM(_NET_WM_STATE_ABOVE);
 7447-
 7448-	Atom actual_type;
 7449-	int actual_format;
 7450-	unsigned long nitems, bytes_after;
 7451-	Atom* prop_return = NULL;
 7452-
 7453-	int status = XGetWindowProperty(_RGFW->display, win->src.window, _NET_WM_STATE, 0, (~0L), False, XA_ATOM,
 7454-									&actual_type, &actual_format, &nitems, &bytes_after,
 7455-									(unsigned char **)&prop_return);
 7456-
 7457-	if (status != Success || actual_type != XA_ATOM)
 7458-		return RGFW_FALSE;
 7459-
 7460-    unsigned long i;
 7461-	for (i = 0; i < nitems; i++)
 7462-		if (prop_return[i] == _NET_WM_STATE_ABOVE) return RGFW_TRUE;
 7463-
 7464-	if (prop_return)
 7465-		XFree(prop_return);
 7466-	return RGFW_FALSE;
 7467-}
 7468-
 7469-void RGFW_FUNC(RGFW_window_setName)(RGFW_window* win, const char* name) {
 7470-	RGFW_ASSERT(win != NULL);
 7471-	if (name == NULL) name = "\0";
 7472-
 7473-	Xutf8SetWMProperties(_RGFW->display, win->src.window, name, name, NULL, 0, NULL, NULL, NULL);
 7474-	XStoreName(_RGFW->display, win->src.window, name);
 7475-
 7476-	RGFW_LOAD_ATOM(_NET_WM_NAME); RGFW_LOAD_ATOM(UTF8_STRING);
 7477-
 7478-    XChangeProperty(
 7479-		_RGFW->display, win->src.window, _NET_WM_NAME, UTF8_STRING,
 7480-		8, PropModeReplace, (u8*)name, (int)RGFW_unix_stringlen(name)
 7481-	);
 7482-}
 7483-
 7484-#ifndef RGFW_NO_PASSTHROUGH
 7485-void RGFW_FUNC(RGFW_window_setMousePassthrough) (RGFW_window* win, RGFW_bool passthrough) {
 7486-	RGFW_ASSERT(win != NULL);
 7487-    if (passthrough) {
 7488-		Region region = XCreateRegion();
 7489-		XShapeCombineRegion(_RGFW->display, win->src.window, ShapeInput, 0, 0, region, ShapeSet);
 7490-		XDestroyRegion(region);
 7491-
 7492-		return;
 7493-	}
 7494-
 7495-	XShapeCombineMask(_RGFW->display, win->src.window, ShapeInput, 0, 0, None, ShapeSet);
 7496-}
 7497-#endif /* RGFW_NO_PASSTHROUGH */
 7498-
 7499-RGFW_bool RGFW_FUNC(RGFW_window_setIconEx) (RGFW_window* win, u8* data_src, i32 w, i32 h, RGFW_format format, RGFW_icon type) {
 7500-	Atom _NET_WM_ICON = XInternAtom(_RGFW->display, "_NET_WM_ICON", False);
 7501-	RGFW_ASSERT(win != NULL);
 7502-	if (data_src == NULL) {
 7503-		RGFW_bool res = (RGFW_bool)XChangeProperty(
 7504-			_RGFW->display, win->src.window, _NET_WM_ICON, XA_CARDINAL, 32,
 7505-			PropModeReplace, (u8*)NULL, 0
 7506-		);
 7507-		return res;
 7508-	}
 7509-
 7510-	i32 count = (i32)(2 + (w * h));
 7511-
 7512-	unsigned long* data = (unsigned long*) RGFW_ALLOC((u32)count * sizeof(unsigned long));
 7513-    RGFW_ASSERT(data != NULL);
 7514-
 7515-	RGFW_MEMZERO(data, (u32)count * sizeof(unsigned long));
 7516-    data[0] = (unsigned long)w;
 7517-	data[1] = (unsigned long)h;
 7518-
 7519-	RGFW_copyImageData64((u8*)&data[2], w, h, RGFW_formatBGRA8, data_src, format, RGFW_TRUE, NULL);
 7520-	RGFW_bool res = RGFW_TRUE;
 7521-	if (type & RGFW_iconTaskbar) {
 7522-		res = (RGFW_bool)XChangeProperty(
 7523-			_RGFW->display, win->src.window, _NET_WM_ICON, XA_CARDINAL, 32,
 7524-			PropModeReplace, (u8*)data, count
 7525-		);
 7526-	}
 7527-
 7528-	RGFW_copyImageData64((u8*)&data[2], w, h, RGFW_formatBGRA8, data_src, format, RGFW_FALSE, NULL);
 7529-
 7530-	if (type & RGFW_iconWindow) {
 7531-		XWMHints wm_hints;
 7532-		wm_hints.flags = IconPixmapHint;
 7533-
 7534-		i32 depth = DefaultDepth(_RGFW->display, DefaultScreen(_RGFW->display));
 7535-		XImage *image = XCreateImage(_RGFW->display, DefaultVisual(_RGFW->display, DefaultScreen(_RGFW->display)),
 7536-									(u32)depth, ZPixmap, 0, (char *)&data[2], (u32)w, (u32)h, 32, 0);
 7537-
 7538-		wm_hints.icon_pixmap = XCreatePixmap(_RGFW->display, win->src.window, (u32)w, (u32)h, (u32)depth);
 7539-		XPutImage(_RGFW->display, wm_hints.icon_pixmap, DefaultGC(_RGFW->display, DefaultScreen(_RGFW->display)), image, 0, 0, 0, 0, (u32)w, (u32)h);
 7540-		image->data = NULL;
 7541-		XDestroyImage(image);
 7542-
 7543-		XSetWMHints(_RGFW->display, win->src.window, &wm_hints);
 7544-	}
 7545-
 7546-	RGFW_FREE(data);
 7547-	XFlush(_RGFW->display);
 7548-	return RGFW_BOOL(res);
 7549-}
 7550-
 7551-RGFW_mouse* RGFW_FUNC(RGFW_createMouseStandard) (RGFW_mouseIcon mouse) {
 7552-	u32 mouseIcon = 0;
 7553-
 7554-    switch (mouse) {
 7555-        case RGFW_mouseNormal: mouseIcon = XC_left_ptr; break;
 7556-        case RGFW_mouseArrow: mouseIcon = XC_left_ptr; break;
 7557-        case RGFW_mouseIbeam: mouseIcon = XC_xterm; break;
 7558-        case RGFW_mouseWait: mouseIcon = XC_watch; break;
 7559-        case RGFW_mouseCrosshair: mouseIcon = XC_tcross; break;
 7560-        case RGFW_mouseProgress: mouseIcon = XC_watch; break;
 7561-        case RGFW_mouseResizeNWSE: mouseIcon = XC_top_left_corner; break;
 7562-        case RGFW_mouseResizeNESW: mouseIcon = XC_top_right_corner; break;
 7563-        case RGFW_mouseResizeEW: mouseIcon = XC_sb_h_double_arrow; break;
 7564-        case RGFW_mouseResizeNS: mouseIcon = XC_sb_v_double_arrow; break;
 7565-        case RGFW_mouseResizeNW: mouseIcon = XC_top_left_corner; break;
 7566-        case RGFW_mouseResizeN: mouseIcon = XC_top_side; break;
 7567-        case RGFW_mouseResizeNE: mouseIcon = XC_top_right_corner; break;
 7568-        case RGFW_mouseResizeE: mouseIcon = XC_right_side; break;
 7569-        case RGFW_mouseResizeSE: mouseIcon = XC_bottom_right_corner; break;
 7570-        case RGFW_mouseResizeS: mouseIcon = XC_bottom_side; break;
 7571-        case RGFW_mouseResizeSW: mouseIcon = XC_bottom_left_corner; break;
 7572-        case RGFW_mouseResizeW: mouseIcon = XC_left_side; break;
 7573-		case RGFW_mouseResizeAll: mouseIcon = XC_fleur; break;
 7574-        case RGFW_mouseNotAllowed: mouseIcon = XC_pirate; break;
 7575-        case RGFW_mousePointingHand: mouseIcon = XC_hand2; break;
 7576-		default: return NULL;
 7577-	}
 7578-
 7579-	Cursor cursor = XCreateFontCursor(_RGFW->display, mouseIcon);
 7580-	return (RGFW_mouse*)cursor;
 7581-}
 7582-
 7583-RGFW_mouse* RGFW_FUNC(RGFW_createMouse) (u8* data, i32 w, i32 h, RGFW_format format) {
 7584-    RGFW_ASSERT(data);
 7585-#ifndef RGFW_NO_X11_CURSOR
 7586-	RGFW_init();
 7587-    XcursorImage* native = XcursorImageCreate((i32)w, (i32)h);
 7588-	native->xhot = 0;
 7589-	native->yhot = 0;
 7590-	RGFW_MEMZERO(native->pixels, (u32)(w * h * 4));
 7591-	RGFW_copyImageData((u8*)native->pixels, w, h, RGFW_formatBGRA8, data, format, NULL);
 7592-
 7593-	Cursor cursor = XcursorImageLoadCursor(_RGFW->display, native);
 7594-	XcursorImageDestroy(native);
 7595-
 7596-	return (void*)cursor;
 7597-#else
 7598-	RGFW_UNUSED(data); RGFW_UNUSED(w); RGFW_UNUSED(h); RGFW_UNUSED(format);
 7599-	return NULL;
 7600-#endif
 7601-}
 7602-
 7603-RGFW_bool RGFW_FUNC(RGFW_window_setMousePlatform)(RGFW_window* win, RGFW_mouse* mouse) {
 7604-	RGFW_ASSERT(win && mouse);
 7605-	XDefineCursor(_RGFW->display, win->src.window, (Cursor)mouse);
 7606-	return RGFW_TRUE;
 7607-}
 7608-
 7609-void RGFW_FUNC(RGFW_freeMouse)(RGFW_mouse* mouse) {
 7610-	RGFW_ASSERT(mouse);
 7611-	XFreeCursor(_RGFW->display, (Cursor)mouse);
 7612-}
 7613-
 7614-void RGFW_FUNC(RGFW_window_moveMouse)(RGFW_window* win, i32 x, i32 y) {
 7615-	RGFW_ASSERT(win != NULL);
 7616-
 7617-	XEvent event;
 7618-	XQueryPointer(_RGFW->display, DefaultRootWindow(_RGFW->display),
 7619-		&event.xbutton.root, &event.xbutton.window,
 7620-		&event.xbutton.x_root, &event.xbutton.y_root,
 7621-		&event.xbutton.x, &event.xbutton.y,
 7622-		&event.xbutton.state);
 7623-
 7624-	win->internal.lastMouseX = x - win->x;
 7625-	win->internal.lastMouseY = y - win->y;
 7626-	if (event.xbutton.x == x && event.xbutton.y == y)
 7627-		return;
 7628-
 7629-	XWarpPointer(_RGFW->display, None, win->src.window, 0, 0, 0, 0, (int) x - win->x, (int) y - win->y);
 7630-}
 7631-
 7632-void RGFW_FUNC(RGFW_window_hide)(RGFW_window* win) {
 7633-	win->internal.flags |= (u32)RGFW_windowHide;
 7634-	XUnmapWindow(_RGFW->display, win->src.window);
 7635-
 7636-	XFlush(_RGFW->display);
 7637-}
 7638-
 7639-void RGFW_FUNC(RGFW_window_show) (RGFW_window* win) {
 7640-	win->internal.flags &= ~(u32)RGFW_windowHide;
 7641-	if (win->internal.flags & RGFW_windowFocusOnShow) RGFW_window_focus(win);
 7642-
 7643-	if (RGFW_window_isHidden(win) == RGFW_FALSE) {
 7644-		return;
 7645-	}
 7646-
 7647-	XMapWindow(_RGFW->display, win->src.window);
 7648-	RGFW_window_move(win, win->x, win->y);
 7649-
 7650-	RGFW_waitForShowEvent_X11(win);
 7651-	RGFW_window_setFullscreen(win, RGFW_window_isFullscreen(win));
 7652-	return;
 7653-}
 7654-
 7655-void RGFW_FUNC(RGFW_window_flash) (RGFW_window* win, RGFW_flashRequest request) {
 7656-	if (RGFW_window_isInFocus(win) && request) {
 7657-		return;
 7658-	}
 7659-
 7660-	XWMHints* wmhints = XGetWMHints(_RGFW->display, win->src.window);
 7661-	if (wmhints == NULL) return;
 7662-
 7663-	if (request) {
 7664-		wmhints->flags |= XUrgencyHint;
 7665-		if (request == RGFW_flashBriefly)
 7666-			win->src.flashEnd = RGFW_linux_getTimeNS() + (u64)1e+9;
 7667-		if (request == RGFW_flashUntilFocused)
 7668-			win->src.flashEnd = (u64)-1;
 7669-	} else {
 7670-		win->src.flashEnd = 0;
 7671-		wmhints->flags &= ~XUrgencyHint;
 7672-	}
 7673-
 7674-    XSetWMHints(_RGFW->display, win->src.window, wmhints);
 7675-    XFree(wmhints);
 7676-}
 7677-
 7678-RGFW_ssize_t RGFW_FUNC(RGFW_readClipboardPtr)(char* str, size_t strCapacity) {
 7679-	RGFW_init();
 7680-	RGFW_LOAD_ATOM(XSEL_DATA); RGFW_LOAD_ATOM(UTF8_STRING); RGFW_LOAD_ATOM(CLIPBOARD);
 7681-	if (XGetSelectionOwner(_RGFW->display, CLIPBOARD) == _RGFW->helperWindow) {
 7682-		if (str != NULL)
 7683-			RGFW_STRNCPY(str, _RGFW->clipboard, _RGFW->clipboard_len - 1);
 7684-		_RGFW->clipboard[_RGFW->clipboard_len - 1] = '\0';
 7685-		return (RGFW_ssize_t)_RGFW->clipboard_len - 1;
 7686-	}
 7687-
 7688-	XEvent event;
 7689-	int format;
 7690-	unsigned long N, sizeN;
 7691-	char* data;
 7692-	Atom target;
 7693-
 7694-	XConvertSelection(_RGFW->display, CLIPBOARD, UTF8_STRING, XSEL_DATA, _RGFW->helperWindow, CurrentTime);
 7695-	XSync(_RGFW->display, 0);
 7696-	while (1) {
 7697-		XNextEvent(_RGFW->display, &event);
 7698-		if (event.type != SelectionNotify) continue;
 7699-
 7700-		if (event.xselection.selection != CLIPBOARD || event.xselection.property == 0)
 7701-			return -1;
 7702-		break;
 7703-	}
 7704-
 7705-	XGetWindowProperty(event.xselection.display, event.xselection.requestor,
 7706-			event.xselection.property, 0L, (~0L), 0, AnyPropertyType, &target,
 7707-			&format, &sizeN, &N, (u8**) &data);
 7708-
 7709-	RGFW_ssize_t size;
 7710-	if (sizeN > strCapacity && str != NULL)
 7711-		size = -1;
 7712-
 7713-	if ((target == UTF8_STRING || target == XA_STRING) && str != NULL) {
 7714-		RGFW_MEMCPY(str, data, sizeN);
 7715-		str[sizeN] = '\0';
 7716-		XFree(data);
 7717-	} else if (str != NULL) size = -1;
 7718-
 7719-	XDeleteProperty(event.xselection.display, event.xselection.requestor, event.xselection.property);
 7720-	size = (RGFW_ssize_t)sizeN;
 7721-
 7722-    return size;
 7723-}
 7724-
 7725-i32 RGFW_XHandleClipboardSelectionHelper(void) {
 7726-    RGFW_LOAD_ATOM(SAVE_TARGETS);
 7727-
 7728-    XEvent event;
 7729-    XPending(_RGFW->display);
 7730-
 7731-    if (QLength(_RGFW->display) || XEventsQueued(_RGFW->display, QueuedAlready) + XEventsQueued(_RGFW->display, QueuedAfterReading))
 7732-        XNextEvent(_RGFW->display, &event);
 7733-    else
 7734-        return 0;
 7735-
 7736-    switch (event.type) {
 7737-        case SelectionRequest:
 7738-            RGFW_XHandleClipboardSelection(&event);
 7739-            return 0;
 7740-        case SelectionNotify:
 7741-            if (event.xselection.target == SAVE_TARGETS)
 7742-                return 0;
 7743-            break;
 7744-        default: break;
 7745-    }
 7746-
 7747-    return 0;
 7748-}
 7749-
 7750-void RGFW_FUNC(RGFW_writeClipboard)(const char* text, u32 textLen) {
 7751-	RGFW_LOAD_ATOM(SAVE_TARGETS); RGFW_LOAD_ATOM(CLIPBOARD);
 7752-    RGFW_init();
 7753-
 7754-    /* request ownership of the clipboard section and request to convert it, this means its our job to convert it */
 7755-	XSetSelectionOwner(_RGFW->display, CLIPBOARD, _RGFW->helperWindow, CurrentTime);
 7756-	if (XGetSelectionOwner(_RGFW->display, CLIPBOARD) != _RGFW->helperWindow) {
 7757-    	RGFW_debugCallback(RGFW_typeError, RGFW_errClipboard,  "X11 failed to become owner of clipboard selection");
 7758-		return;
 7759-	}
 7760-
 7761-	if (_RGFW->clipboard)
 7762-		RGFW_FREE(_RGFW->clipboard);
 7763-
 7764-	_RGFW->clipboard = (char*)RGFW_ALLOC(textLen);
 7765-	RGFW_ASSERT(_RGFW->clipboard != NULL);
 7766-
 7767-	RGFW_STRNCPY(_RGFW->clipboard, text, textLen - 1);
 7768-	_RGFW->clipboard[textLen - 1] = '\0';
 7769-	_RGFW->clipboard_len = textLen;
 7770-	return;
 7771-}
 7772-
 7773-RGFW_bool RGFW_FUNC(RGFW_window_isHidden)(RGFW_window* win) {
 7774-	RGFW_ASSERT(win != NULL);
 7775-	XWindowAttributes windowAttributes;
 7776-	XGetWindowAttributes(_RGFW->display, win->src.window, &windowAttributes);
 7777-
 7778-	return (windowAttributes.map_state != IsViewable);
 7779-}
 7780-
 7781-RGFW_bool RGFW_FUNC(RGFW_window_isMinimized)(RGFW_window* win) {
 7782-	RGFW_ASSERT(win != NULL);
 7783-    RGFW_LOAD_ATOM(WM_STATE);
 7784-
 7785-	Atom actual_type;
 7786-	i32 actual_format;
 7787-	unsigned long nitems, bytes_after;
 7788-	unsigned char* prop_data;
 7789-
 7790-	i32 status = XGetWindowProperty(_RGFW->display, win->src.window, WM_STATE, 0, 2, False,
 7791-		AnyPropertyType, &actual_type, &actual_format,
 7792-		&nitems, &bytes_after, &prop_data);
 7793-
 7794-	if (status == Success && nitems >= 1 && prop_data == (unsigned char*)IconicState) {
 7795-		XFree(prop_data);
 7796-		return RGFW_TRUE;
 7797-	}
 7798-
 7799-	if (prop_data != NULL)
 7800-		XFree(prop_data);
 7801-
 7802-	XWindowAttributes windowAttributes;
 7803-	XGetWindowAttributes(_RGFW->display, win->src.window, &windowAttributes);
 7804-    return windowAttributes.map_state != IsViewable;
 7805-}
 7806-
 7807-RGFW_bool RGFW_FUNC(RGFW_window_isMaximized)(RGFW_window* win) {
 7808-	RGFW_ASSERT(win != NULL);
 7809-    RGFW_LOAD_ATOM(_NET_WM_STATE);
 7810-	RGFW_LOAD_ATOM(_NET_WM_STATE_MAXIMIZED_VERT);
 7811-	RGFW_LOAD_ATOM(_NET_WM_STATE_MAXIMIZED_HORZ);
 7812-
 7813-	Atom actual_type;
 7814-	i32 actual_format;
 7815-	unsigned long nitems, bytes_after;
 7816-	unsigned char* prop_data;
 7817-
 7818-	i32 status = XGetWindowProperty(_RGFW->display, win->src.window, _NET_WM_STATE, 0, 1024, False,
 7819-		XA_ATOM, &actual_type, &actual_format,
 7820-		&nitems, &bytes_after, &prop_data);
 7821-
 7822-	if (status != Success) {
 7823-		if (prop_data != NULL)
 7824-			XFree(prop_data);
 7825-
 7826-		return RGFW_FALSE;
 7827-	}
 7828-
 7829-	u64 i;
 7830-	for (i = 0; i < nitems; i++) {
 7831-		if (prop_data[i] == _NET_WM_STATE_MAXIMIZED_VERT ||
 7832-			prop_data[i] == _NET_WM_STATE_MAXIMIZED_HORZ) {
 7833-			XFree(prop_data);
 7834-			return RGFW_TRUE;
 7835-		}
 7836-	}
 7837-
 7838-	if (prop_data != NULL)
 7839-		XFree(prop_data);
 7840-
 7841-	return RGFW_FALSE;
 7842-}
 7843-
 7844-RGFWDEF void RGFW_XGetSystemContentDPI(float* dpi);
 7845-void RGFW_XGetSystemContentDPI(float* dpi) {
 7846-	if (dpi == NULL) return;
 7847-	float dpiOutput = 96.0f;
 7848-
 7849-	char* rms = XResourceManagerString(_RGFW->display);
 7850-	if (rms == NULL) return;
 7851-
 7852-	XrmDatabase db = XrmGetStringDatabase(rms);
 7853-	if (db == NULL) return;
 7854-
 7855-	XrmValue value;
 7856-	char* type = NULL;
 7857-
 7858-	if (XrmGetResource(db, "Xft.dpi", "Xft.Dpi", &type, &value) && type && RGFW_STRNCMP(type, "String", 7) == 0)
 7859-		dpiOutput = (float)RGFW_ATOF(value.addr);
 7860-	XrmDestroyDatabase(db);
 7861-
 7862-	if (dpi) *dpi = dpiOutput;
 7863-}
 7864-
 7865-RGFWDEF XRRModeInfo* RGFW_XGetMode(XRRCrtcInfo* ci, XRRScreenResources* res, RRMode mode, RGFW_monitorMode* foundMode);
 7866-XRRModeInfo* RGFW_XGetMode(XRRCrtcInfo* ci, XRRScreenResources* res, RRMode mode, RGFW_monitorMode* foundMode) {
 7867-	XRRModeInfo* mi = None;
 7868-	for (i32 j = 0; j < res->nmode; j++) {
 7869-		if (res->modes[j].id ==  mode)
 7870-			mi = &res->modes[j];
 7871-	}
 7872-
 7873-	if (mi == None) return NULL;
 7874-
 7875-	if ((mi->modeFlags & RR_Interlace) != 0) return NULL;
 7876-
 7877-	foundMode->w = (i32)mi->width;
 7878-	foundMode->h = (i32)mi->height;
 7879-	if (ci->rotation == RR_Rotate_90 || ci->rotation == RR_Rotate_270) {
 7880-		foundMode->w = (i32)mi->height;
 7881-		foundMode->h = (i32)mi->width;
 7882-	} else {
 7883-		foundMode->w = (i32)mi->width;
 7884-		foundMode->h = (i32)mi->height;
 7885-	}
 7886-
 7887-	RGFW_splitBPP((u32)DefaultDepth(_RGFW->display, DefaultScreen(_RGFW->display)), foundMode);
 7888-
 7889-	foundMode->src = (void*)mode;
 7890-
 7891-	foundMode->refreshRate = 0;
 7892-	if (mi->hTotal == 0 || mi->vTotal == 0)
 7893-		return mi;
 7894-
 7895-    u32 vTotal = mi->vTotal;
 7896-
 7897-    if (mi->modeFlags & RR_DoubleScan) {
 7898-        vTotal *= 2;
 7899-    }
 7900-
 7901-    if (mi->modeFlags & RR_Interlace) {
 7902-        vTotal /= 2;
 7903-    }
 7904-
 7905-	i32 numerator = (i32)mi->dotClock;
 7906-	i32 denominator = (i32)(mi->hTotal * vTotal);
 7907-	float refreshRate = 0;
 7908-
 7909-	if (denominator <= 0) {
 7910-		denominator = 1;
 7911-	}
 7912-
 7913-	refreshRate = ((float)numerator / (float)denominator);
 7914-
 7915-	foundMode->refreshRate = RGFW_ROUNDF((refreshRate * 100)) / 100.0f;
 7916-	return mi;
 7917-}
 7918-
 7919-void RGFW_FUNC(RGFW_pollMonitors) (void) {
 7920-    RGFW_init();
 7921-
 7922-	Window root = XDefaultRootWindow(_RGFW->display);
 7923-	XRRScreenResources* res = XRRGetScreenResourcesCurrent(_RGFW->display, root);
 7924-	if (res == 0) {
 7925-		return;
 7926-	}
 7927-
 7928-	RROutput primary = XRRGetOutputPrimary(_RGFW->display, root);
 7929-
 7930-	for (RGFW_monitorNode* node = _RGFW->monitors.list.head; node; node = node->next) {
 7931-		node->disconnected = RGFW_TRUE;
 7932-	}
 7933-
 7934-	for (i32 i = 0; i < res->noutput; i++) {
 7935-		RGFW_monitorNode* node = NULL;
 7936-		for (node = _RGFW->monitors.list.head; node; node = node->next) {
 7937-			if (node->rrOutput == res->outputs[i]) {
 7938-				break;
 7939-			}
 7940-		}
 7941-
 7942-		if (node) {
 7943-			node->disconnected = RGFW_FALSE;
 7944-			if (node->rrOutput == primary) {
 7945-				_RGFW->monitors.primary = node;
 7946-			}
 7947-			continue;
 7948-		}
 7949-
 7950-		RGFW_monitor monitor;
 7951-
 7952-		XRROutputInfo* info = XRRGetOutputInfo(_RGFW->display, res, res->outputs[i]);
 7953-		if (info == NULL) continue;
 7954-		if (info->connection != RR_Connected || info->crtc == None) {
 7955-			XRRFreeOutputInfo(info);
 7956-			continue;
 7957-		}
 7958-
 7959-		XRRCrtcInfo* ci = XRRGetCrtcInfo(_RGFW->display, res, info->crtc);
 7960-
 7961-		if (ci == NULL) {
 7962-			continue;
 7963-		}
 7964-
 7965-		float physW = (float)info->mm_width / 25.4f;
 7966-		float physH = (float)info->mm_height / 25.4f;
 7967-
 7968-		RGFW_STRNCPY(monitor.name, info->name, sizeof(monitor.name) - 1);
 7969-		monitor.name[sizeof(monitor.name) - 1] = '\0';
 7970-
 7971-		if (physW > 0.0f && physH > 0.0f) {
 7972-			monitor.physW = physW;
 7973-			monitor.physH = physH;
 7974-		} else {
 7975-			monitor.physW = (float) ((float)ci->width / 96.f);
 7976-			monitor.physH = (float) ((float)ci->height / 96.f);
 7977-		}
 7978-
 7979-		monitor.x = ci->x;
 7980-		monitor.y = ci->y;
 7981-
 7982-		float dpi = 96.0f;
 7983-		RGFW_XGetSystemContentDPI(&dpi);
 7984-
 7985-		monitor.scaleX = dpi / 96.0f;
 7986-		monitor.scaleY = dpi / 96.0f;
 7987-
 7988-		monitor.pixelRatio = dpi >= 192.0f ? 2.0f : 1.0f;
 7989-
 7990-		XRRModeInfo* mi = RGFW_XGetMode(ci, res, ci->mode, &monitor.mode);
 7991-
 7992-		if (mi == NULL) {
 7993-			break;
 7994-		}
 7995-
 7996-		XRRFreeCrtcInfo(ci);
 7997-
 7998-		node = RGFW_monitors_add(&monitor);
 7999-		if (node == NULL) break;
 8000-
 8001-		node->rrOutput = res->outputs[i];
 8002-		node->crtc = info->crtc;
 8003-
 8004-		if (node->rrOutput == primary) {
 8005-			_RGFW->monitors.primary = node;
 8006-		}
 8007-
 8008-		XRRFreeOutputInfo(info);
 8009-		info = NULL;
 8010-
 8011-		RGFW_monitorCallback(_RGFW->root, &node->mon, RGFW_TRUE);
 8012-	}
 8013-
 8014-	XRRFreeScreenResources(res);
 8015-
 8016-	RGFW_monitors_refresh();
 8017-}
 8018-
 8019-RGFW_bool RGFW_FUNC(RGFW_monitor_getWorkarea) (RGFW_monitor* monitor, i32* x, i32* y, i32* width, i32* height) {
 8020-    RGFW_LOAD_ATOM(_NET_WORKAREA);
 8021-    RGFW_LOAD_ATOM(_NET_CURRENT_DESKTOP);
 8022-
 8023-	Window root = DefaultRootWindow(_RGFW->display);
 8024-
 8025-	i32 areaX = monitor->x;
 8026-	i32 areaY = monitor->y;
 8027-	i32 areaW = monitor->mode.w;
 8028-	i32 areaH  = monitor->mode.h;
 8029-
 8030-    if (_NET_WORKAREA && _NET_CURRENT_DESKTOP) {
 8031-        Atom* extents = NULL;
 8032-        Atom* desktop = NULL;
 8033-
 8034-		Atom actualType = 0;
 8035-		int actualFormat = 0;
 8036-		unsigned long extentCount = 0, bytesAfter = 0;
 8037-		XGetWindowProperty(_RGFW->display, root, _NET_WORKAREA, 0, LONG_MAX, False, XA_CARDINAL, &actualType, &actualFormat, &extentCount, &bytesAfter, (u8**) &extents);
 8038-
 8039-		unsigned long count;
 8040-		XGetWindowProperty(_RGFW->display, root, _NET_CURRENT_DESKTOP, 0, LONG_MAX, False, XA_CARDINAL, &actualType, &actualFormat, &count, &bytesAfter, (u8**) &desktop);
 8041-
 8042-        if (count) {
 8043-			if (extentCount >= 4 && *desktop < extentCount / 4) {
 8044-                i32 globalX = (i32)extents[*desktop * 4 + 0];
 8045-                i32 globalY = (i32)extents[*desktop * 4 + 1];
 8046-                i32 globalW = (i32)extents[*desktop * 4 + 2];
 8047-                i32 globalH = (i32)extents[*desktop * 4 + 3];
 8048-
 8049-                if (areaX < globalX) {
 8050-                    areaW -= globalX - areaX;
 8051-                    areaX = globalX;
 8052-                }
 8053-
 8054-                if (areaY < globalY) {
 8055-                    areaH -= globalY - areaY;
 8056-                    areaY = globalY;
 8057-                }
 8058-
 8059-                if (areaX + areaW > globalX + globalW)
 8060-                    areaW = globalX - areaX + globalW;
 8061-                if (areaY + areaH > globalY + globalH)
 8062-                    areaH = globalY - areaY + globalH;
 8063-            }
 8064-        }
 8065-
 8066-        if (extents)
 8067-            XFree(extents);
 8068-        if (desktop)
 8069-            XFree(desktop);
 8070-    }
 8071-
 8072-    if (x) *x = areaX;
 8073-    if (y) *y = areaY;
 8074-    if (width) *width = areaW;
 8075-    if (height) *height = areaH;
 8076-
 8077-	return RGFW_TRUE;
 8078-}
 8079-
 8080-size_t RGFW_FUNC(RGFW_monitor_getModesPtr) (RGFW_monitor* monitor, RGFW_monitorMode** modes) {
 8081-	size_t count = 0;
 8082-
 8083-	XRRScreenResources* res = XRRGetScreenResourcesCurrent(_RGFW->display, DefaultRootWindow(_RGFW->display));
 8084-	if (res == NULL) return 0;
 8085-
 8086-	XRRCrtcInfo* ci = XRRGetCrtcInfo(_RGFW->display, res, monitor->node->crtc);
 8087-	XRROutputInfo* oi = XRRGetOutputInfo(_RGFW->display, res, monitor->node->rrOutput);
 8088-	count = (size_t)oi->nmode;
 8089-
 8090-	int i;
 8091-	for (i = 0; modes && i < oi->nmode; i++) {
 8092-		XRRModeInfo* mi = RGFW_XGetMode(ci, res, oi->modes[i], &((*modes)[i]));
 8093-		RGFW_UNUSED(mi);
 8094-	}
 8095-
 8096-    XRRFreeOutputInfo(oi);
 8097-	XRRFreeCrtcInfo(ci);
 8098-    XRRFreeScreenResources(res);
 8099-
 8100-	return count;
 8101-}
 8102-
 8103-size_t RGFW_FUNC(RGFW_monitor_getGammaRampPtr) (RGFW_monitor* monitor, RGFW_gammaRamp* ramp) {
 8104-	RGFW_UNUSED(monitor); RGFW_UNUSED(ramp);
 8105-	size_t size = (size_t)XRRGetCrtcGammaSize(_RGFW->display, monitor->node->crtc);
 8106-	XRRCrtcGamma* gamma = XRRGetCrtcGamma(_RGFW->display, monitor->node->crtc);
 8107-
 8108-	if (ramp) {
 8109-		RGFW_MEMCPY(ramp->red,   gamma->red,   size * sizeof(unsigned short));
 8110-		RGFW_MEMCPY(ramp->green, gamma->green, size * sizeof(unsigned short));
 8111-		RGFW_MEMCPY(ramp->blue,  gamma->blue,  size * sizeof(unsigned short));
 8112-	}
 8113-
 8114-	XRRFreeGamma(gamma);
 8115-	return size;
 8116-}
 8117-
 8118-RGFW_bool RGFW_FUNC(RGFW_monitor_setGammaRamp) (RGFW_monitor* monitor, RGFW_gammaRamp* ramp) {
 8119-	RGFW_UNUSED(monitor); RGFW_UNUSED(ramp);
 8120-
 8121-	size_t size = (size_t)XRRGetCrtcGammaSize(_RGFW->display, monitor->node->crtc);
 8122-	if (size != ramp->count) {
 8123-		RGFW_debugCallback(RGFW_typeError, RGFW_errX11, "X11: Gamma ramp size must match current ramp size");
 8124-		return RGFW_FALSE;
 8125-	}
 8126-
 8127-	XRRCrtcGamma* gamma = XRRAllocGamma((int)ramp->count);
 8128-
 8129-	memcpy(gamma->red,   ramp->red,   ramp->count * sizeof(unsigned short));
 8130-	memcpy(gamma->green, ramp->green, ramp->count * sizeof(unsigned short));
 8131-	memcpy(gamma->blue,  ramp->blue,  ramp->count * sizeof(unsigned short));
 8132-
 8133-	XRRSetCrtcGamma(_RGFW->display, monitor->node->crtc, gamma);
 8134-	XRRFreeGamma(gamma);
 8135-
 8136-	return RGFW_TRUE;
 8137-}
 8138-
 8139-RGFW_bool RGFW_FUNC(RGFW_monitor_setMode)(RGFW_monitor* mon, RGFW_monitorMode* mode) {
 8140-	RGFW_bool out = RGFW_FALSE;
 8141-
 8142-	XRRScreenResources* res = XRRGetScreenResourcesCurrent(_RGFW->display, DefaultRootWindow(_RGFW->display));
 8143-	XRRCrtcInfo* ci = XRRGetCrtcInfo(_RGFW->display, res, mon->node->crtc);
 8144-
 8145-	if (XRRSetCrtcConfig(_RGFW->display, res, mon->node->crtc, CurrentTime, ci->x, ci->y, (RRMode)mode->src, ci->rotation, ci->outputs, ci->noutput) == True) {
 8146-		out = RGFW_TRUE;
 8147-	}
 8148-
 8149-	XRRFreeCrtcInfo(ci);
 8150-    XRRFreeScreenResources(res);
 8151-	return out;
 8152-}
 8153-
 8154-RGFW_bool RGFW_FUNC(RGFW_monitor_requestMode)(RGFW_monitor* mon, RGFW_monitorMode* mode, RGFW_modeRequest request) {
 8155-    RGFW_init();
 8156-
 8157-	RGFW_bool output = RGFW_FALSE;
 8158-
 8159-	XRRScreenResources* res = XRRGetScreenResourcesCurrent(_RGFW->display, DefaultRootWindow(_RGFW->display));
 8160-	if (res == NULL) return RGFW_FALSE;
 8161-
 8162-	XRRCrtcInfo* ci = XRRGetCrtcInfo(_RGFW->display, res, mon->node->crtc);
 8163-	XRROutputInfo* oi = XRRGetOutputInfo(_RGFW->display, res, mon->node->rrOutput);
 8164-
 8165-	RRMode native = None;
 8166-
 8167-    int i;
 8168-    for (i = 0; i < oi->nmode; i++) {
 8169-		RGFW_monitorMode foundMode;
 8170-		XRRModeInfo* mi = RGFW_XGetMode(ci, res, oi->modes[i], &foundMode);
 8171-		if (mi == NULL) {
 8172-			continue;
 8173-		}
 8174-
 8175-		if (RGFW_monitorModeCompare(mode, &foundMode, request)) {
 8176-			native = mi->id;
 8177-			output = RGFW_TRUE;
 8178-			mon->mode = foundMode;
 8179-			break;
 8180-		}
 8181-	}
 8182-
 8183-	if (native) {
 8184-		XRRSetCrtcConfig(_RGFW->display, res, mon->node->crtc, CurrentTime, ci->x, ci->y, native, ci->rotation, ci->outputs, ci->noutput);
 8185-	}
 8186-
 8187-    XRRFreeOutputInfo(oi);
 8188-	XRRFreeCrtcInfo(ci);
 8189-    XRRFreeScreenResources(res);
 8190-	return output;
 8191-}
 8192-
 8193-RGFW_monitor* RGFW_FUNC(RGFW_window_getMonitor) (RGFW_window* win) {
 8194-    RGFW_ASSERT(win != NULL);
 8195-
 8196-	XWindowAttributes attrs;
 8197-    if (!XGetWindowAttributes(_RGFW->display, win->src.window, &attrs)) {
 8198-		return NULL;
 8199-	}
 8200-
 8201-	for (RGFW_monitorNode* node = _RGFW->monitors.list.head; node; node = node->next) {
 8202-		if ((attrs.x < node->mon.x + node->mon.mode.w) && (attrs.x + attrs.width > node->mon.x) && (attrs.y < node->mon.y + node->mon.mode.h) && (attrs.y + attrs.height > node->mon.y))
 8203-			return &node->mon;
 8204-	}
 8205-
 8206-
 8207-	return &_RGFW->monitors.list.head->mon;
 8208-}
 8209-
 8210-#ifdef RGFW_OPENGL
 8211-RGFW_bool RGFW_FUNC(RGFW_window_createContextPtr_OpenGL) (RGFW_window* win, RGFW_glContext* context, RGFW_glHints* hints) {
 8212-	/* for checking extensions later */
 8213-	const char sRGBARBstr[] = "GLX_ARB_framebuffer_sRGB";
 8214-	const char sRGBEXTstr[] = "GLX_EXT_framebuffer_sRGB";
 8215-	const char noErorrStr[]  = "GLX_ARB_create_context_no_error";
 8216-	const char flushStr[] = "GLX_ARB_context_flush_control";
 8217-	const char robustStr[]	= "GLX_ARB_create_context_robustness";
 8218-
 8219-	/* basic RGFW int */
 8220-	win->src.ctx.native = context;
 8221-	win->src.gfxType = RGFW_gfxNativeOpenGL;
 8222-
 8223-	/*  This is required so that way the user can create their own OpenGL context after RGFW_createWindow is used */
 8224-	RGFW_bool showWindow = RGFW_FALSE;
 8225-	if (win->src.window) {
 8226-		showWindow = (RGFW_window_isMinimized(win) == RGFW_FALSE);
 8227-		RGFW_window_closePlatform(win);
 8228-	}
 8229-
 8230-	RGFW_bool transparent = (win->internal.flags & RGFW_windowTransparent);
 8231-
 8232-	/* start by creating a GLX config / X11 Viusal */
 8233-	XVisualInfo visual;
 8234-	GLXFBConfig bestFbc;
 8235-
 8236-	i32 visual_attribs[40];
 8237-	RGFW_attribStack stack;
 8238-	RGFW_attribStack_init(&stack, visual_attribs, 40);
 8239-	RGFW_attribStack_pushAttribs(&stack, GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR);
 8240-	RGFW_attribStack_pushAttribs(&stack, GLX_X_RENDERABLE, 1);
 8241-	RGFW_attribStack_pushAttribs(&stack, GLX_RENDER_TYPE, GLX_RGBA_BIT);
 8242-	RGFW_attribStack_pushAttribs(&stack, GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT);
 8243-	RGFW_attribStack_pushAttribs(&stack, GLX_DOUBLEBUFFER, 1);
 8244-	RGFW_attribStack_pushAttribs(&stack, GLX_ALPHA_SIZE, hints->alpha);
 8245-	RGFW_attribStack_pushAttribs(&stack, GLX_DEPTH_SIZE, hints->depth);
 8246-	RGFW_attribStack_pushAttribs(&stack, GLX_STENCIL_SIZE, hints->stencil);
 8247-	RGFW_attribStack_pushAttribs(&stack, GLX_STEREO, hints->stereo);
 8248-	RGFW_attribStack_pushAttribs(&stack, GLX_AUX_BUFFERS, hints->auxBuffers);
 8249-	RGFW_attribStack_pushAttribs(&stack, GLX_RED_SIZE, hints->red);
 8250-	RGFW_attribStack_pushAttribs(&stack, GLX_GREEN_SIZE, hints->green);
 8251-	RGFW_attribStack_pushAttribs(&stack, GLX_BLUE_SIZE, hints->blue);
 8252-	RGFW_attribStack_pushAttribs(&stack, GLX_ACCUM_RED_SIZE, hints->accumRed);
 8253-	RGFW_attribStack_pushAttribs(&stack, GLX_ACCUM_GREEN_SIZE, hints->accumGreen);
 8254-	RGFW_attribStack_pushAttribs(&stack, GLX_ACCUM_BLUE_SIZE, hints->accumBlue);
 8255-	RGFW_attribStack_pushAttribs(&stack, GLX_ACCUM_ALPHA_SIZE, hints->accumAlpha);
 8256-
 8257-	if (hints->sRGB) {
 8258-		if (RGFW_extensionSupportedPlatform_OpenGL(sRGBARBstr, sizeof(sRGBARBstr)))
 8259-			RGFW_attribStack_pushAttribs(&stack, GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB, hints->sRGB);
 8260-		if (RGFW_extensionSupportedPlatform_OpenGL(sRGBEXTstr, sizeof(sRGBEXTstr)))
 8261-			RGFW_attribStack_pushAttribs(&stack, GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT, hints->sRGB);
 8262-	}
 8263-
 8264-	RGFW_attribStack_pushAttribs(&stack, 0, 0);
 8265-
 8266-	/* find the configs */
 8267-	i32 fbcount;
 8268-	GLXFBConfig* fbc = glXChooseFBConfig(_RGFW->display, DefaultScreen(_RGFW->display), visual_attribs, &fbcount);
 8269-
 8270-	i32 best_fbc = -1;
 8271-	i32 best_depth = 0;
 8272-	i32 best_samples = 0;
 8273-
 8274-	if (fbcount == 0) {
 8275-		RGFW_debugCallback(RGFW_typeError, RGFW_errOpenGLContext, "Failed to find any valid GLX visual configs.");
 8276-		return 0;
 8277-	}
 8278-
 8279-	/* search through all found configs to find the best match */
 8280-	i32 i;
 8281-	for (i = 0; i < fbcount; i++) {
 8282-		XVisualInfo* vi = glXGetVisualFromFBConfig(_RGFW->display, fbc[i]);
 8283-		if (vi == NULL)
 8284-			continue;
 8285-
 8286-		i32 samp_buf, samples;
 8287-		glXGetFBConfigAttrib(_RGFW->display, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf);
 8288-		glXGetFBConfigAttrib(_RGFW->display, fbc[i], GLX_SAMPLES, &samples);
 8289-
 8290-		if (best_fbc == -1) best_fbc = i;
 8291-		if ((!(transparent) || vi->depth == 32)  && best_depth == 0) {
 8292-			best_fbc = i;
 8293-			best_depth = vi->depth;
 8294-		}
 8295-		if ((!(transparent) || vi->depth == 32) && samples <= hints->samples && samples > best_samples) {
 8296-			best_fbc = i;
 8297-			best_depth = vi->depth;
 8298-			best_samples = samples;
 8299-		}
 8300-		XFree(vi);
 8301-	}
 8302-
 8303-	if (best_fbc == -1) {
 8304-		RGFW_debugCallback(RGFW_typeError, RGFW_errOpenGLContext, "Failed to get a valid GLX visual.");
 8305-		return 0;
 8306-	}
 8307-
 8308-	/* we found a config */
 8309-	bestFbc = fbc[best_fbc];
 8310-	XVisualInfo* vi = glXGetVisualFromFBConfig(_RGFW->display, bestFbc);
 8311-	if (vi->depth != 32 && transparent)
 8312-		RGFW_debugCallback(RGFW_typeWarning, RGFW_warningOpenGL,  "Failed to to find a matching visual with a 32-bit depth.");
 8313-
 8314-	if (best_samples < hints->samples)
 8315-		RGFW_debugCallback(RGFW_typeWarning, RGFW_warningOpenGL, "Failed to load a matching sample count.");
 8316-
 8317-	XFree(fbc);
 8318-	visual = *vi;
 8319-	XFree(vi);
 8320-
 8321-	/* use the visual to create a new window */
 8322-	RGFW_XCreateWindow(visual, "", win->internal.flags, win);
 8323-
 8324-	if (showWindow) {
 8325-		RGFW_window_show(win);
 8326-	}
 8327-
 8328-	/* create the actual OpenGL context  */
 8329-	i32 context_attribs[40];
 8330-	RGFW_attribStack_init(&stack, context_attribs, 40);
 8331-
 8332-	i32 mask = 0;
 8333-	switch (hints->profile) {
 8334-		case RGFW_glES: mask |= GLX_CONTEXT_ES_PROFILE_BIT_EXT; break;
 8335-		case RGFW_glForwardCompatibility: mask |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; break;
 8336-		case RGFW_glCompatibility: mask |= GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; break;
 8337-		case RGFW_glCore: mask |= GLX_CONTEXT_CORE_PROFILE_BIT_ARB; break;
 8338-		default: mask |= GLX_CONTEXT_CORE_PROFILE_BIT_ARB; break;
 8339-	}
 8340-
 8341-	RGFW_attribStack_pushAttribs(&stack, GLX_CONTEXT_PROFILE_MASK_ARB, mask);
 8342-
 8343-	if (hints->minor || hints->major) {
 8344-		RGFW_attribStack_pushAttribs(&stack, GLX_CONTEXT_MAJOR_VERSION_ARB, hints->major);
 8345-		RGFW_attribStack_pushAttribs(&stack, GLX_CONTEXT_MINOR_VERSION_ARB, hints->minor);
 8346-	}
 8347-
 8348-
 8349-	if (RGFW_extensionSupportedPlatform_OpenGL(flushStr, sizeof(flushStr))) {
 8350-		if (hints->releaseBehavior == RGFW_glReleaseFlush) {
 8351-			RGFW_attribStack_pushAttribs(&stack, GLX_CONTEXT_RELEASE_BEHAVIOR_ARB, GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
 8352-		} else if (hints->releaseBehavior == RGFW_glReleaseNone) {
 8353-			RGFW_attribStack_pushAttribs(&stack, GLX_CONTEXT_RELEASE_BEHAVIOR_ARB, GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
 8354-		}
 8355-	}
 8356-
 8357-	i32 flags = 0;
 8358-	if (hints->debug) flags |= GLX_CONTEXT_DEBUG_BIT_ARB;
 8359-	if (hints->robustness && RGFW_extensionSupportedPlatform_OpenGL(robustStr, sizeof(robustStr))) flags |= GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB;
 8360-	if (flags) {
 8361-		RGFW_attribStack_pushAttribs(&stack, GLX_CONTEXT_FLAGS_ARB, flags);
 8362-	}
 8363-
 8364-	if (RGFW_extensionSupportedPlatform_OpenGL(noErorrStr, sizeof(noErorrStr))) {
 8365-		RGFW_attribStack_pushAttribs(&stack, GLX_CONTEXT_OPENGL_NO_ERROR_ARB, hints->noError);
 8366-	}
 8367-
 8368-	RGFW_attribStack_pushAttribs(&stack, 0, 0);
 8369-
 8370-	/*  create the context */
 8371-	glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0;
 8372-	char str[] = "glXCreateContextAttribsARB";
 8373-	glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)glXGetProcAddressARB((u8*) str);
 8374-
 8375-	GLXContext ctx = NULL;
 8376-	if (hints->share) {
 8377-		ctx = hints->share->ctx;
 8378-	}
 8379-
 8380-	if (glXCreateContextAttribsARB == NULL) {
 8381-		RGFW_debugCallback(RGFW_typeError, RGFW_errOpenGLContext, "Failed to load proc address 'glXCreateContextAttribsARB', loading a generic OpenGL context.");
 8382-			win->src.ctx.native->ctx = glXCreateContext(_RGFW->display, &visual, ctx, True);
 8383-	} else {
 8384-		_RGFW->x11Error = NULL;
 8385-		win->src.ctx.native->ctx = glXCreateContextAttribsARB(_RGFW->display, bestFbc, ctx, True, context_attribs);
 8386-		if (_RGFW->x11Error || win->src.ctx.native->ctx == NULL) {
 8387-			RGFW_debugCallback(RGFW_typeError, RGFW_errOpenGLContext, "Failed to create an OpenGL context with AttribsARB, loading a generic OpenGL context.");
 8388-			win->src.ctx.native->ctx = glXCreateContext(_RGFW->display, &visual, ctx, True);
 8389-		}
 8390-	}
 8391-
 8392-	#ifndef RGFW_NO_GLXWINDOW
 8393-		win->src.ctx.native->window = glXCreateWindow(_RGFW->display, bestFbc, win->src.window, NULL);
 8394-	#else
 8395-		win->src.ctx.native->window = win->src.window;
 8396-	#endif
 8397-
 8398-	glXMakeCurrent(_RGFW->display, (Drawable)win->src.ctx.native->window, (GLXContext)win->src.ctx.native->ctx);
 8399-	RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "OpenGL context initalized.");
 8400-
 8401-	RGFW_window_swapInterval_OpenGL(win, 0);
 8402-
 8403-	return RGFW_TRUE;
 8404-}
 8405-
 8406-void RGFW_FUNC(RGFW_window_deleteContextPtr_OpenGL) (RGFW_window* win, RGFW_glContext* ctx) {
 8407-	#ifndef RGFW_NO_GLXWINDOW
 8408-	if (win->src.ctx.native->window != win->src.window) {
 8409-		glXDestroyWindow(_RGFW->display, win->src.ctx.native->window);
 8410-	}
 8411-	#endif
 8412-
 8413-	glXDestroyContext(_RGFW->display, ctx->ctx);
 8414-	win->src.ctx.native = NULL;
 8415-	RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL,  "OpenGL context freed.");
 8416-}
 8417-
 8418-RGFW_bool RGFW_FUNC(RGFW_extensionSupportedPlatform_OpenGL)(const char * extension, size_t len) {
 8419-	RGFW_init();
 8420-	const char* extensions = glXQueryExtensionsString(_RGFW->display, XDefaultScreen(_RGFW->display));
 8421-	return (extensions != NULL) && RGFW_extensionSupportedStr(extensions, extension, len);
 8422-}
 8423-
 8424-RGFW_proc RGFW_FUNC(RGFW_getProcAddress_OpenGL)(const char* procname) { return glXGetProcAddress((u8*) procname); }
 8425-
 8426-void RGFW_FUNC(RGFW_window_makeCurrentContext_OpenGL) (RGFW_window* win) { if (win) RGFW_ASSERT(win->src.ctx.native);
 8427-	if (win == NULL)
 8428-		glXMakeCurrent(NULL, (Drawable)NULL, (GLXContext) NULL);
 8429-	else
 8430-		glXMakeCurrent(_RGFW->display, (Drawable)win->src.ctx.native->window, (GLXContext) win->src.ctx.native->ctx);
 8431-	return;
 8432-}
 8433-void* RGFW_FUNC(RGFW_getCurrentContext_OpenGL) (void) { return glXGetCurrentContext(); }
 8434-void RGFW_FUNC(RGFW_window_swapBuffers_OpenGL) (RGFW_window* win) { RGFW_ASSERT(win->src.ctx.native); glXSwapBuffers(_RGFW->display, win->src.ctx.native->window); }
 8435-
 8436-void RGFW_FUNC(RGFW_window_swapInterval_OpenGL) (RGFW_window* win, i32 swapInterval) {
 8437-	RGFW_ASSERT(win != NULL);
 8438-	/* cached pfn to avoid calling glXGetProcAddress more than once */
 8439-	static PFNGLXSWAPINTERVALEXTPROC pfn = NULL;
 8440-	static int (*pfn2)(int) = NULL;
 8441-
 8442-	if (pfn == NULL) {
 8443-		u8 str[] = "glXSwapIntervalEXT";
 8444-		pfn = (PFNGLXSWAPINTERVALEXTPROC)glXGetProcAddress(str);
 8445-		if (pfn == NULL)  {
 8446-			pfn = (PFNGLXSWAPINTERVALEXTPROC)1;
 8447-			const char* array[] = {"GLX_MESA_swap_control", "GLX_SGI_swap_control"};
 8448-
 8449-			size_t i;
 8450-			for (i = 0; i < sizeof(array) / sizeof(char*) && pfn2 == NULL; i++) {
 8451-				pfn2 = (int(*)(int))glXGetProcAddress((u8*)array[i]);
 8452-			}
 8453-
 8454-			if (pfn2 != NULL) {
 8455-				RGFW_debugCallback(RGFW_typeError, RGFW_errOpenGLContext,  "Failed to load swap interval function, fallingback to the native swapinterval function");
 8456-			} else {
 8457-				RGFW_debugCallback(RGFW_typeError, RGFW_errOpenGLContext,  "Failed to load swap interval function");
 8458-			}
 8459-		}
 8460-	}
 8461-
 8462-	if (pfn != (PFNGLXSWAPINTERVALEXTPROC)1) {
 8463-		pfn(_RGFW->display, win->src.ctx.native->window, swapInterval);
 8464-	}
 8465-	else if (pfn2 != NULL) {
 8466-		pfn2(swapInterval);
 8467-	}
 8468-}
 8469-#endif /* RGFW_OPENGL */
 8470-
 8471-i32 RGFW_initPlatform_X11(void) {
 8472-    #ifdef RGFW_USE_XDL
 8473-		XDL_init();
 8474-	#endif
 8475-
 8476-	#if !defined(RGFW_NO_X11_CURSOR) && !defined(RGFW_NO_X11_CURSOR_PRELOAD)
 8477-	#if defined(__CYGWIN__)
 8478-				RGFW_LOAD_LIBRARY(X11Cursorhandle, "libXcursor-1.so");
 8479-	#elif defined(__OpenBSD__) || defined(__NetBSD__)
 8480-				RGFW_LOAD_LIBRARY(X11Cursorhandle, "libXcursor.so");
 8481-	#else
 8482-				RGFW_LOAD_LIBRARY(X11Cursorhandle, "libXcursor.so.1");
 8483-	#endif
 8484-		RGFW_PROC_DEF(X11Cursorhandle, XcursorImageCreate);
 8485-		RGFW_PROC_DEF(X11Cursorhandle, XcursorImageDestroy);
 8486-		RGFW_PROC_DEF(X11Cursorhandle, XcursorImageLoadCursor);
 8487-	#endif
 8488-
 8489-	#if !defined(RGFW_NO_X11_XI_PRELOAD)
 8490-	#if defined(__CYGWIN__)
 8491-			RGFW_LOAD_LIBRARY(X11Xihandle, "libXi-6.so");
 8492-	#elif defined(__OpenBSD__) || defined(__NetBSD__)
 8493-			RGFW_LOAD_LIBRARY(X11Xihandle, "libXi.so");
 8494-	#else
 8495-			RGFW_LOAD_LIBRARY(X11Xihandle, "libXi.so.6");
 8496-	#endif
 8497-			RGFW_PROC_DEF(X11Xihandle, XISelectEvents);
 8498-	#endif
 8499-
 8500-	#if !defined(RGFW_NO_X11_EXT_PRELOAD)
 8501-	#if defined(__CYGWIN__)
 8502-			RGFW_LOAD_LIBRARY(X11XEXThandle, "libXext-6.so");
 8503-	#elif defined(__OpenBSD__) || defined(__NetBSD__)
 8504-	        RGFW_LOAD_LIBRARY(X11XEXThandle, "libXext.so");
 8505-	#else
 8506-			RGFW_LOAD_LIBRARY(X11XEXThandle, "libXext.so.6");
 8507-	#endif
 8508-			RGFW_PROC_DEF(X11XEXThandle, XSyncCreateCounter);
 8509-			RGFW_PROC_DEF(X11XEXThandle, XSyncIntToValue);
 8510-			RGFW_PROC_DEF(X11XEXThandle, XSyncSetCounter);
 8511-    	    RGFW_PROC_DEF(X11XEXThandle, XShapeCombineRegion);
 8512-	        RGFW_PROC_DEF(X11XEXThandle, XShapeCombineMask);
 8513-    #endif
 8514-
 8515-    XInitThreads(); /*!< init X11 threading */
 8516-    _RGFW->display = XOpenDisplay(0);
 8517-	_RGFW->context = XUniqueContext();
 8518-
 8519-	XSetWindowAttributes wa;
 8520-    RGFW_MEMZERO(&wa, sizeof(wa));
 8521-    wa.event_mask = PropertyChangeMask;
 8522-    _RGFW->helperWindow = XCreateWindow(_RGFW->display, XDefaultRootWindow(_RGFW->display), 0, 0, 1, 1, 0, 0,
 8523-                                        InputOnly, DefaultVisual(_RGFW->display, DefaultScreen(_RGFW->display)), CWEventMask, &wa);
 8524-
 8525-    u8 RGFW_blk[] = { 0, 0, 0, 0 };
 8526-	_RGFW->hiddenMouse = RGFW_createMouse(RGFW_blk, 1, 1, RGFW_formatRGBA8);
 8527-
 8528-	_RGFW->clipboard = NULL;
 8529-
 8530-    XkbComponentNamesRec rec;
 8531-    XkbDescPtr desc = XkbGetMap(_RGFW->display, 0, XkbUseCoreKbd);
 8532-    XkbDescPtr evdesc;
 8533-    XSetErrorHandler(RGFW_XErrorHandler);
 8534-	u8 old[256];
 8535-
 8536-    XkbGetNames(_RGFW->display, XkbKeyNamesMask, desc);
 8537-
 8538-    RGFW_MEMZERO(&rec, sizeof(rec));
 8539-    char evdev[] = "evdev";
 8540-    rec.keycodes = evdev;
 8541-    evdesc = XkbGetKeyboardByName(_RGFW->display, XkbUseCoreKbd, &rec, XkbGBN_KeyNamesMask, XkbGBN_KeyNamesMask, False);
 8542-    /* memo: RGFW_keycodes[x11 keycode] = rgfw keycode */
 8543-    if(evdesc != NULL && desc != NULL) {
 8544-        int i, j;
 8545-        for(i = 0; i < (int)sizeof(old); i++){
 8546-    	    old[i] = _RGFW->keycodes[i];
 8547-    	    _RGFW->keycodes[i] = 0;
 8548-        }
 8549-        for(i = evdesc->min_key_code; i <= evdesc->max_key_code; i++){
 8550-    	    for(j = desc->min_key_code; j <= desc->max_key_code; j++){
 8551-                if(RGFW_STRNCMP(evdesc->names->keys[i].name, desc->names->keys[j].name, XkbKeyNameLength) == 0){
 8552-                    _RGFW->keycodes[j] = old[i];
 8553-                    break;
 8554-                }
 8555-    	    }
 8556-        }
 8557-		XkbFreeKeyboard(desc, 0, True);
 8558-		XkbFreeKeyboard(evdesc, 0, True);
 8559-    }
 8560-
 8561-	XSetLocaleModifiers("");
 8562-	XRegisterIMInstantiateCallback(_RGFW->display, NULL, NULL, NULL, RGFW_x11_imInitCallback, NULL);
 8563-
 8564-	unsigned char mask[XIMaskLen(XI_RawMotion)];
 8565-	RGFW_MEMZERO(mask, sizeof(mask));
 8566-	XISetMask(mask, XI_RawMotion);
 8567-
 8568-	XIEventMask em;
 8569-	em.deviceid = XIAllMasterDevices;
 8570-	em.mask_len = sizeof(mask);
 8571-	em.mask = mask;
 8572-
 8573-	XISelectEvents(_RGFW->display, XDefaultRootWindow(_RGFW->display), &em, 1);
 8574-
 8575-	i32 errorBase;
 8576-	if (XRRQueryExtension(_RGFW->display, &_RGFW->xrandrEventBase, &errorBase)) {
 8577-        XRRSelectInput(_RGFW->display, RootWindow(_RGFW->display, DefaultScreen(_RGFW->display)), RROutputChangeNotifyMask);
 8578-	}
 8579-
 8580-	return 0;
 8581-}
 8582-
 8583-void RGFW_deinitPlatform_X11(void) {
 8584-    #define RGFW_FREE_LIBRARY(x) if (x != NULL) dlclose(x); x = NULL;
 8585-	/* to save the clipboard on the x server after the window is closed */
 8586-	RGFW_LOAD_ATOM(CLIPBOARD_MANAGER);  RGFW_LOAD_ATOM(CLIPBOARD);
 8587-	RGFW_LOAD_ATOM(SAVE_TARGETS);
 8588-	if (XGetSelectionOwner(_RGFW->display, CLIPBOARD) == _RGFW->helperWindow) {
 8589-		XConvertSelection(_RGFW->display, CLIPBOARD_MANAGER, SAVE_TARGETS, None, _RGFW->helperWindow, CurrentTime);
 8590-        while (RGFW_XHandleClipboardSelectionHelper());
 8591-	}
 8592-
 8593-	XUnregisterIMInstantiateCallback(_RGFW->display, NULL, NULL, NULL, RGFW_x11_imInitCallback, NULL);
 8594-
 8595-    if (_RGFW->im) {
 8596-        XCloseIM(_RGFW->im);
 8597-        _RGFW->im = NULL;
 8598-    }
 8599-
 8600-	if (_RGFW->clipboard) {
 8601-		RGFW_FREE(_RGFW->clipboard);
 8602-		_RGFW->clipboard = NULL;
 8603-	}
 8604-
 8605-	if (_RGFW->hiddenMouse) {
 8606-		RGFW_freeMouse(_RGFW->hiddenMouse);
 8607-		_RGFW->hiddenMouse = NULL;
 8608-	}
 8609-
 8610-    XDestroyWindow(_RGFW->display, (Drawable) _RGFW->helperWindow); /*!< close the window */
 8611-    XCloseDisplay(_RGFW->display); /*!< kill connection to the x server */
 8612-
 8613-    #if !defined(RGFW_NO_X11_CURSOR_PRELOAD) && !defined(RGFW_NO_X11_CURSOR)
 8614-        RGFW_FREE_LIBRARY(X11Cursorhandle);
 8615-    #endif
 8616-    #if !defined(RGFW_NO_X11_XI_PRELOAD)
 8617-        RGFW_FREE_LIBRARY(X11Xihandle);
 8618-    #endif
 8619-
 8620-    #ifdef RGFW_USE_XDL
 8621-        XDL_close();
 8622-    #endif
 8623-
 8624-    #if !defined(RGFW_NO_X11_EXT_PRELOAD)
 8625-        RGFW_FREE_LIBRARY(X11XEXThandle);
 8626-    #endif
 8627-}
 8628-
 8629-void RGFW_FUNC(RGFW_window_closePlatform)(RGFW_window* win) {
 8630-    if (win->src.ic) {
 8631-        XDestroyIC(win->src.ic);
 8632-        win->src.ic = NULL;
 8633-    }
 8634-
 8635-	XFreeGC(_RGFW->display, win->src.gc);
 8636-	XDeleteContext(_RGFW->display, win->src.window, _RGFW->context);
 8637-	XDestroyWindow(_RGFW->display, (Drawable) win->src.window); /*!< close the window */
 8638-	return;
 8639-}
 8640-
 8641-#ifdef RGFW_WEBGPU
 8642-WGPUSurface RGFW_FUNC(RGFW_window_createSurface_WebGPU) (RGFW_window* window, WGPUInstance instance) {
 8643-	WGPUSurfaceDescriptor surfaceDesc = {0};
 8644-	WGPUSurfaceSourceXlibWindow fromXlib = {0};
 8645-	fromXlib.chain.sType = WGPUSType_SurfaceSourceXlibWindow;
 8646-	fromXlib.display = _RGFW->display;
 8647-	fromXlib.window = window->src.window;
 8648-
 8649-	surfaceDesc.nextInChain = (WGPUChainedStruct*)&fromXlib.chain;
 8650-	return wgpuInstanceCreateSurface(instance, &surfaceDesc);
 8651-}
 8652-#endif
 8653-
 8654-#endif
 8655-/*
 8656-	End of X11 linux / wayland / unix defines
 8657-*/
 8658-
 8659-/*
 8660-
 8661-	Start of Wayland defayland
 8662-*/
 8663-
 8664-#ifdef RGFW_WAYLAND
 8665-#ifdef RGFW_X11
 8666-#undef RGFW_FUNC /* remove previous define */
 8667-#define RGFW_FUNC(func) func##_Wayland
 8668-#else
 8669-#define RGFW_FUNC(func) func
 8670-#endif
 8671-
 8672-/*
 8673-Wayland TODO: (out of date)
 8674-- fix RGFW_keyPressed lock state
 8675-
 8676-	RGFW_windowMoved, 		the window was moved (by the user)
 8677-	RGFW_windowRefresh	 	The window content needs to be refreshed
 8678-
 8679-	RGFW_dataDrop 				a file has been dropped into the window
 8680-	RGFW_dataDrag
 8681-
 8682-- window args:
 8683-	#define RGFW_windowNoResize	 			the window cannot be resized  by the user
 8684-	#define RGFW_windowAllowDND     			the window supports drag and drop
 8685-	#define RGFW_scaleToMonitor 			scale the window to the screen
 8686-
 8687-- other missing functions functions ("TODO wayland") (~30 functions)
 8688-- fix buffer rendering weird behavior
 8689-*/
 8690-#include <errno.h>
 8691-#include <unistd.h>
 8692-#include <sys/mman.h>
 8693-#include <xkbcommon/xkbcommon.h>
 8694-#include <xkbcommon/xkbcommon-keysyms.h>
 8695-#include <xkbcommon/xkbcommon-compose.h>
 8696-#include <dirent.h>
 8697-#include <linux/kd.h>
 8698-#include <wayland-cursor.h>
 8699-#include <fcntl.h>
 8700-
 8701-struct wl_display* RGFW_getDisplay_Wayland(void) { return _RGFW->wl_display; }
 8702-struct wl_surface* RGFW_window_getWindow_Wayland(RGFW_window* win) { return win->src.surface; }
 8703-
 8704-
 8705-/* wayland global garbage (wayland bad, X11 is fine (ish) (not really)) */
 8706-#include "xdg-shell.h"
 8707-#include "xdg-toplevel-icon-v1.h"
 8708-#include "xdg-decoration-unstable-v1.h"
 8709-#include "relative-pointer-unstable-v1.h"
 8710-#include "pointer-constraints-unstable-v1.h"
 8711-#include "xdg-output-unstable-v1.h"
 8712-#include "pointer-warp-v1.h"
 8713-
 8714-void RGFW_toggleWaylandMaximized(RGFW_window* win, RGFW_bool maximized);
 8715-
 8716-static void RGFW_wl_setOpaque(RGFW_window* win) {
 8717-	struct wl_region* wl_region = wl_compositor_create_region(_RGFW->compositor);
 8718-
 8719-	if (!wl_region) return; /* return if no region was created */
 8720-
 8721-	wl_region_add(wl_region, 0, 0, win->w, win->h);
 8722-	wl_surface_set_opaque_region(win->src.surface, wl_region);
 8723-	wl_region_destroy(wl_region);
 8724-
 8725-}
 8726-
 8727-static void RGFW_wl_xdg_wm_base_ping_handler(void* data, struct xdg_wm_base* wm_base,
 8728-		u32 serial) {
 8729-	RGFW_UNUSED(data);
 8730-    xdg_wm_base_pong(wm_base, serial);
 8731-}
 8732-static void RGFW_wl_xdg_surface_configure_handler(void* data, struct xdg_surface* xdg_surface,
 8733-		u32 serial) {
 8734-
 8735-    xdg_surface_ack_configure(xdg_surface, serial);
 8736-
 8737-    RGFW_window* win = (RGFW_window*)data;
 8738-
 8739-    if (win == NULL) {
 8740-		win = _RGFW->kbOwner;
 8741-		if (win == NULL)
 8742-			return;
 8743-	}
 8744-
 8745-	/* useful for libdecor */
 8746-	if (win->src.activated != win->src.pending_activated) {
 8747-		win->src.activated = win->src.pending_activated;
 8748-	}
 8749-
 8750-	if (win->src.maximized != win->src.pending_maximized) {
 8751-		RGFW_toggleWaylandMaximized(win, win->src.pending_maximized);
 8752-
 8753-		RGFW_window_checkMode(win);
 8754-	}
 8755-
 8756-
 8757-	if (win->src.resizing) {
 8758-
 8759-		RGFW_windowResizedCallback(win, win->w, win->h);
 8760-		RGFW_window_resize(win, win->w, win->h);
 8761-		if (!(win->internal.flags & RGFW_windowTransparent)) {
 8762-			RGFW_wl_setOpaque(win);
 8763-		}
 8764-	}
 8765-
 8766-	win->src.configured = RGFW_TRUE;
 8767-}
 8768-
 8769-static void RGFW_wl_xdg_toplevel_configure_handler(void* data, struct xdg_toplevel* toplevel,
 8770-		i32 width, i32 height, struct wl_array* states) {
 8771-
 8772-    RGFW_UNUSED(toplevel);
 8773-    RGFW_window* win = (RGFW_window*)data;
 8774-
 8775-
 8776-    win->src.pending_activated = RGFW_FALSE;
 8777-    win->src.pending_maximized = RGFW_FALSE;
 8778-    win->src.resizing = RGFW_FALSE;
 8779-
 8780-
 8781-	enum xdg_toplevel_state* state;
 8782-	wl_array_for_each(state, states) {
 8783-		switch (*state) {
 8784-			case XDG_TOPLEVEL_STATE_ACTIVATED:
 8785-				 win->src.pending_activated = RGFW_TRUE;
 8786-				break;
 8787-			case XDG_TOPLEVEL_STATE_MAXIMIZED:
 8788-				win->src.pending_maximized = RGFW_TRUE;
 8789-				break;
 8790-			default:
 8791-				break;
 8792-		}
 8793-
 8794-	}
 8795-	/* if width and height are not zero and are not the same as the window */
 8796-    /* the window is resizing so update the values */
 8797-	if ((width && height) && (win->w != width ||  win->h != height)) {
 8798-		win->src.resizing = RGFW_TRUE;
 8799-		win->src.w = win->w = width;
 8800-		win->src.h = win->h = height;
 8801-	}
 8802-}
 8803-
 8804-static void RGFW_wl_xdg_toplevel_close_handler(void* data, struct xdg_toplevel *toplevel) {
 8805-	RGFW_UNUSED(toplevel);
 8806-	RGFW_window* win = (RGFW_window*)data;
 8807-
 8808-	if (!win->internal.shouldClose) {
 8809-		RGFW_windowCloseCallback(win);
 8810-	}
 8811-}
 8812-
 8813-static void RGFW_wl_xdg_decoration_configure_handler(void* data,
 8814-		struct zxdg_toplevel_decoration_v1* zxdg_toplevel_decoration_v1, u32 mode) {
 8815-	RGFW_window* win = (RGFW_window*)data; RGFW_UNUSED(zxdg_toplevel_decoration_v1);
 8816-
 8817-	/* this is expected to run once */
 8818-    /* set the decoration mode set by earlier request */
 8819-	if (mode != win->src.decoration_mode) {
 8820-		win->src.decoration_mode = mode;
 8821-	}
 8822-}
 8823-
 8824-static void RGFW_wl_shm_format_handler(void* data, struct wl_shm *shm, u32 format) {
 8825-	RGFW_UNUSED(data); RGFW_UNUSED(shm); RGFW_UNUSED(format);
 8826-}
 8827-
 8828-static void RGFW_wl_relative_pointer_motion(void *data, struct zwp_relative_pointer_v1 *zwp_relative_pointer_v1,
 8829-	u32 time_hi, u32 time_lo, wl_fixed_t dx, wl_fixed_t dy, wl_fixed_t dx_unaccel, wl_fixed_t dy_unaccel) {
 8830-
 8831-	RGFW_UNUSED(zwp_relative_pointer_v1); RGFW_UNUSED(time_hi); RGFW_UNUSED(time_lo);
 8832-	RGFW_UNUSED(dx_unaccel); RGFW_UNUSED(dy_unaccel);
 8833-
 8834-	RGFW_info* RGFW = (RGFW_info*)data;
 8835-
 8836-	RGFW_ASSERT(RGFW->mouseOwner != NULL);
 8837-	RGFW_window* win = RGFW->mouseOwner;
 8838-
 8839-	RGFW_ASSERT(win);
 8840-
 8841-	float vecX =  (float)wl_fixed_to_double(dx);
 8842-	float vecY = (float)wl_fixed_to_double(dy);
 8843-	RGFW_rawMotionCallback(win, vecX, vecY);
 8844-}
 8845-
 8846-static void RGFW_wl_pointer_locked(void *data, struct zwp_locked_pointer_v1 *zwp_locked_pointer_v1) {
 8847-	RGFW_UNUSED(zwp_locked_pointer_v1);
 8848-	RGFW_info* RGFW = (RGFW_info*)data;
 8849-	wl_pointer_set_cursor(RGFW->wl_pointer, RGFW->mouse_enter_serial, NULL, 0, 0); /* draw no cursor */
 8850-}
 8851-
 8852-static void RGFW_wl_pointer_enter(void* data, struct wl_pointer* pointer, u32 serial,
 8853-		struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y) {
 8854-	RGFW_info* RGFW = (RGFW_info*)data;
 8855-	RGFW_window* win = (RGFW_window*)wl_surface_get_user_data(surface);
 8856-
 8857-	/* save when the pointer is locked or using default cursor */
 8858-	RGFW->mouse_enter_serial = serial;
 8859-	win->internal.mouseInside = RGFW_TRUE;
 8860-	RGFW->windowState.mouseEnter = RGFW_TRUE;
 8861-
 8862-	RGFW->mouseOwner = win;
 8863-
 8864-	/* set the cursor */
 8865-	if (win->src.using_custom_cursor) {
 8866-		wl_pointer_set_cursor(pointer, serial, win->src.custom_cursor_surface, 0, 0);
 8867-	}
 8868-	else {
 8869-		RGFW_window_setMouseDefault(win);
 8870-	}
 8871-
 8872-	i32 x = (i32)wl_fixed_to_double(surface_x);
 8873-	i32 y = (i32)wl_fixed_to_double(surface_y);
 8874-	RGFW_mouseNotifyCallback(win, x, y, RGFW_TRUE);
 8875-}
 8876-
 8877-static void RGFW_wl_pointer_leave(void* data, struct wl_pointer *pointer, u32 serial, struct wl_surface *surface) {
 8878-	RGFW_UNUSED(pointer); RGFW_UNUSED(serial);
 8879-	RGFW_window* win = (RGFW_window*)wl_surface_get_user_data(surface);
 8880-	RGFW_info* RGFW = (RGFW_info*)data;
 8881-	if (RGFW->mouseOwner == win)
 8882-		RGFW->mouseOwner = NULL;
 8883-
 8884-	RGFW_mouseNotifyCallback(win, win->internal.lastMouseX, win->internal.lastMouseY, RGFW_FALSE);
 8885-}
 8886-
 8887-static void RGFW_wl_pointer_motion(void* data, struct wl_pointer *pointer, u32 time, wl_fixed_t x, wl_fixed_t y) {
 8888-	RGFW_UNUSED(pointer); RGFW_UNUSED(time);
 8889-	RGFW_info* RGFW = (RGFW_info*)data;
 8890-	RGFW_ASSERT(RGFW->mouseOwner != NULL);
 8891-
 8892-	RGFW_window* win = RGFW->mouseOwner;
 8893-
 8894-	i32 convertedX = (i32)wl_fixed_to_double(x);
 8895-	i32 convertedY = (i32)wl_fixed_to_double(y);
 8896-
 8897-	RGFW_mousePosCallback(win, convertedX, convertedY);
 8898-}
 8899-
 8900-static void RGFW_wl_pointer_button(void* data, struct wl_pointer *pointer, u32 serial, u32 time, u32 button, u32 state) {
 8901-	RGFW_UNUSED(pointer); RGFW_UNUSED(time); RGFW_UNUSED(serial);
 8902-	RGFW_info* RGFW = (RGFW_info*)data;
 8903-
 8904-	RGFW_ASSERT(RGFW->mouseOwner != NULL);
 8905-	RGFW_window* win = RGFW->mouseOwner;
 8906-
 8907-	u32 b = (button - 0x110);
 8908-
 8909-	/* flip right and middle button codes */
 8910-	if (b == 1) b = 2;
 8911-	else if (b == 2) b = 1;
 8912-
 8913-	RGFW_mouseButtonCallback(win, (u8)b, RGFW_BOOL(state));
 8914-}
 8915-
 8916-static void RGFW_wl_pointer_axis(void* data, struct wl_pointer *pointer, u32 time, u32 axis, wl_fixed_t value) {
 8917-	RGFW_UNUSED(pointer); RGFW_UNUSED(time);  RGFW_UNUSED(axis);
 8918-
 8919-	RGFW_info* RGFW = (RGFW_info*)data;
 8920-	RGFW_ASSERT(RGFW->mouseOwner != NULL);
 8921-	RGFW_window* win = RGFW->mouseOwner;
 8922-
 8923-	float scrollX = 0.0;
 8924-	float scrollY = 0.0;
 8925-
 8926-	if (!(win->internal.enabledEvents  & (RGFW_BIT(RGFW_mouseScroll)))) return;
 8927-
 8928-	if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL)
 8929-		scrollX = (float)(-wl_fixed_to_double(value) / 10.0);
 8930-	else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
 8931-		scrollY = (float)(-wl_fixed_to_double(value) / 10.0);
 8932-
 8933-	RGFW_mouseScrollCallback(win, scrollX, scrollY);
 8934-}
 8935-
 8936-
 8937-static void RGFW_doNothing(void) { }
 8938-
 8939-static void RGFW_wl_keyboard_keymap(void* data, struct wl_keyboard *keyboard, u32 format, i32 fd, u32 size) {
 8940-	RGFW_UNUSED(keyboard); RGFW_UNUSED(format);
 8941-	RGFW_info* RGFW = (RGFW_info*)data;
 8942-
 8943-	char *keymap_string = mmap (NULL, size, PROT_READ, MAP_SHARED, fd, 0);
 8944-	xkb_keymap_unref(RGFW->keymap);
 8945-	RGFW->keymap = xkb_keymap_new_from_string(RGFW->xkb_context, keymap_string, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
 8946-
 8947-	munmap(keymap_string, size);
 8948-	close(fd);
 8949-	xkb_state_unref(RGFW->xkb_state);
 8950-	RGFW->xkb_state = xkb_state_new(RGFW->keymap);
 8951-
 8952-	const char* locale = getenv("LC_ALL");
 8953-	if (!locale)
 8954-		locale = getenv("LC_CTYPE");
 8955-	if (!locale)
 8956-		locale = getenv("LANG");
 8957-	if (!locale)
 8958-		locale = "C";
 8959-
 8960-	struct xkb_compose_table* composeTable = xkb_compose_table_new_from_locale(RGFW->xkb_context, locale, XKB_COMPOSE_COMPILE_NO_FLAGS);
 8961-	if (composeTable) {
 8962-		RGFW->composeState = xkb_compose_state_new(composeTable, XKB_COMPOSE_STATE_NO_FLAGS);
 8963-		xkb_compose_table_unref(composeTable);
 8964-	}
 8965-}
 8966-
 8967-static void RGFW_wl_keyboard_enter(void* data, struct wl_keyboard *keyboard, u32 serial, struct wl_surface *surface, struct wl_array *keys) {
 8968-	RGFW_UNUSED(keyboard); RGFW_UNUSED(keys);
 8969-
 8970-	RGFW_info* RGFW = (RGFW_info*)data;
 8971-	RGFW_window* win = (RGFW_window*)wl_surface_get_user_data(surface);
 8972-	RGFW->kbOwner = win;
 8973-
 8974-
 8975-	// this is to prevent race conditions
 8976-	if (RGFW->data_device != NULL && win->src.data_source != NULL) {
 8977-		wl_data_device_set_selection(RGFW->data_device, win->src.data_source, serial);
 8978-	}
 8979-	/* is set when RGFW_window_minimize is called; if the minimize button is */
 8980-	/* pressed this flag is not set since there is no event to listen for */
 8981-	if (win->src.minimized == RGFW_TRUE) win->src.minimized = RGFW_FALSE;
 8982-
 8983-	RGFW_windowFocusCallback(win, RGFW_TRUE);
 8984-}
 8985-
 8986-static void RGFW_wl_keyboard_leave(void* data, struct wl_keyboard *keyboard, u32 serial, struct wl_surface *surface) {
 8987-	RGFW_UNUSED(keyboard); RGFW_UNUSED(serial);
 8988-
 8989-	RGFW_info* RGFW = (RGFW_info*)data;
 8990-	RGFW_window* win = (RGFW_window*)wl_surface_get_user_data(surface);
 8991-	if (RGFW->kbOwner == win)
 8992-		RGFW->kbOwner = NULL;
 8993-
 8994-	RGFW_windowFocusCallback(win, RGFW_FALSE);
 8995-}
 8996-
 8997-static xkb_keysym_t RGFW_wl_composeSymbol(RGFW_info* RGFW, xkb_keysym_t sym) {
 8998-    if (sym == XKB_KEY_NoSymbol || !RGFW->composeState)
 8999-        return sym;
 9000-    if (xkb_compose_state_feed(RGFW->composeState, sym) != XKB_COMPOSE_FEED_ACCEPTED)
 9001-        return sym;
 9002-    switch (xkb_compose_state_get_status(RGFW->composeState)) {
 9003-        case XKB_COMPOSE_COMPOSED:
 9004-            return xkb_compose_state_get_one_sym(RGFW->composeState);
 9005-        case XKB_COMPOSE_COMPOSING:
 9006-        case XKB_COMPOSE_CANCELLED:
 9007-            return XKB_KEY_NoSymbol;
 9008-        case XKB_COMPOSE_NOTHING:
 9009-        default:
 9010-            return sym;
 9011-    }
 9012-}
 9013-
 9014-static void RGFW_wl_send_key_event(u32 key) {
 9015-	const xkb_keysym_t* keysyms;
 9016-	if (xkb_state_key_get_syms(_RGFW->xkb_state, key + 8, &keysyms) == 1) {
 9017-		xkb_keysym_t keysym = RGFW_wl_composeSymbol(_RGFW, keysyms[0]);
 9018-		u32 codepoint = xkb_keysym_to_utf32(keysym);
 9019-		if (codepoint != 0) {
 9020-			RGFW_keyCharCallback(_RGFW->kbOwner, codepoint);
 9021-		}
 9022-	}
 9023-}
 9024-
 9025-static void RGFW_wl_keyboard_key(void* data, struct wl_keyboard *keyboard, u32 serial, u32 time, u32 key, u32 state) {
 9026-	RGFW_UNUSED(keyboard); RGFW_UNUSED(serial);
 9027-
 9028-	RGFW_info* RGFW = (RGFW_info*)data;
 9029-	if (RGFW->kbOwner == NULL) return;
 9030-
 9031-	RGFW_window *RGFW_key_win = RGFW->kbOwner;
 9032-	RGFW_key RGFWkey = RGFW_apiKeyToRGFW(key + 8);
 9033-
 9034-	RGFW_keyUpdateKeyMods(RGFW_key_win, RGFW_BOOL(xkb_keymap_mod_get_index(RGFW->keymap, "Lock")), RGFW_BOOL(xkb_keymap_mod_get_index(RGFW->keymap, "Mod2")), RGFW_BOOL(xkb_keymap_mod_get_index(RGFW->keymap, "ScrollLock")));
 9035-	RGFW_keyCallback(RGFW_key_win, (u8)RGFWkey, RGFW_key_win->internal.mod, RGFW_isKeyDown((u8)RGFWkey) && RGFW_BOOL(state), RGFW_BOOL(state));
 9036-
 9037-	/* [comment by Kala Telo (@kala-telo) and edited by Riley Mabb (@ColleagueRiley)]
 9038-		we send the event at the moment we receive it, and
 9039-		repeated key presses will be handled by RGFW_pollEvents
 9040-		if the compositor doesn't support proxy (seat?) version
 9041-		of at least 4, it won't initialize wl_repeat_info_rate,
 9042-		and by spec, rate of 0 means disabled, thus repeating
 9043-		keys are disabled by being zero-initialized
 9044-	*/
 9045-	RGFW->last_key = state ? key : 0;
 9046-	RGFW->last_key_time = time + (u32)_RGFW->wl_repeat_info_delay;
 9047-	if (state) {
 9048-		RGFW_wl_send_key_event(_RGFW->last_key);
 9049-	}
 9050-}
 9051-
 9052-static void RGFW_wl_keyboard_modifiers(void* data, struct wl_keyboard *keyboard, u32 serial, u32 mods_depressed, u32 mods_latched, u32 mods_locked, u32 group) {
 9053-	RGFW_UNUSED(keyboard); RGFW_UNUSED(serial); RGFW_UNUSED(time);
 9054-	RGFW_info* RGFW = (RGFW_info*)data;
 9055-	xkb_state_update_mask(RGFW->xkb_state, mods_depressed, mods_latched, mods_locked, 0, 0, group);
 9056-}
 9057-
 9058-static void RGFW_wl_keyboard_repeat_info(void* data, struct wl_keyboard *keyboard, i32 rate, i32 delay) {
 9059-	RGFW_UNUSED(data);
 9060-	RGFW_UNUSED(keyboard);
 9061-	_RGFW->wl_repeat_info_rate = rate;
 9062-	_RGFW->wl_repeat_info_delay = delay;
 9063-}
 9064-
 9065-static void RGFW_wl_seat_capabilities(void* data, struct wl_seat *seat, u32 capabilities) {
 9066-	RGFW_info* RGFW = (RGFW_info*)data;
 9067-    static struct wl_pointer_listener pointer_listener;
 9068-	RGFW_MEMZERO(&pointer_listener, sizeof(pointer_listener));
 9069-	pointer_listener.enter = &RGFW_wl_pointer_enter;
 9070-	pointer_listener.leave = &RGFW_wl_pointer_leave;
 9071-	pointer_listener.motion = &RGFW_wl_pointer_motion;
 9072-	pointer_listener.button = &RGFW_wl_pointer_button;
 9073-	pointer_listener.axis = &RGFW_wl_pointer_axis;
 9074-
 9075-	static struct wl_keyboard_listener keyboard_listener;
 9076-	RGFW_MEMZERO(&keyboard_listener, sizeof(keyboard_listener));
 9077-	keyboard_listener.keymap = &RGFW_wl_keyboard_keymap;
 9078-	keyboard_listener.enter = &RGFW_wl_keyboard_enter;
 9079-	keyboard_listener.leave = &RGFW_wl_keyboard_leave;
 9080-	keyboard_listener.key = &RGFW_wl_keyboard_key;
 9081-	keyboard_listener.modifiers = &RGFW_wl_keyboard_modifiers;
 9082-	keyboard_listener.repeat_info = &RGFW_wl_keyboard_repeat_info;
 9083-
 9084-    if ((capabilities & WL_SEAT_CAPABILITY_POINTER) && !RGFW->wl_pointer) {
 9085-		RGFW->wl_pointer = wl_seat_get_pointer(seat);
 9086-		wl_pointer_add_listener(RGFW->wl_pointer, &pointer_listener, RGFW);
 9087-	}
 9088-	if ((capabilities & WL_SEAT_CAPABILITY_KEYBOARD) && !RGFW->wl_keyboard) {
 9089-		RGFW->wl_keyboard = wl_seat_get_keyboard(seat);
 9090-		wl_keyboard_add_listener(RGFW->wl_keyboard, &keyboard_listener, RGFW);
 9091-	}
 9092-
 9093-    if (!(capabilities & WL_SEAT_CAPABILITY_POINTER) && RGFW->wl_pointer) {
 9094-		wl_pointer_destroy(RGFW->wl_pointer);
 9095-	}
 9096-	if (!(capabilities & WL_SEAT_CAPABILITY_KEYBOARD) && RGFW->wl_keyboard) {
 9097-		wl_keyboard_destroy(RGFW->wl_keyboard);
 9098-	}
 9099-}
 9100-
 9101-static void RGFW_wl_output_set_geometry(void *data, struct wl_output *wl_output,
 9102-			 i32 x, i32 y, i32 physical_width, i32 physical_height,
 9103-			 i32 subpixel, const char *make, const char *model, i32 transform) {
 9104-
 9105-	RGFW_monitor* monitor = &((RGFW_monitorNode*)data)->mon;
 9106-	monitor->x = x;
 9107-	monitor->y = y;
 9108-
 9109-	monitor->physW = (float)physical_width / 25.4f;
 9110-	monitor->physH = (float)physical_height / 25.4f;
 9111-
 9112-	RGFW_UNUSED(wl_output);
 9113-	RGFW_UNUSED(subpixel);
 9114-	RGFW_UNUSED(make);
 9115-	RGFW_UNUSED(model);
 9116-	RGFW_UNUSED(transform);
 9117-}
 9118-
 9119-static void RGFW_wl_output_handle_mode(void *data, struct wl_output *wl_output, u32 flags,
 9120-		     i32 width, i32 height, i32 refresh) {
 9121-
 9122-	RGFW_monitor* monitor = &((RGFW_monitorNode*)data)->mon;
 9123-
 9124-	RGFW_monitorMode mode;
 9125-	mode.w = width;
 9126-	mode.h = height;
 9127-	mode.refreshRate = (float)refresh / 1000.0f;
 9128-	mode.src = wl_output;
 9129-
 9130-	monitor->node->modeCount += 1;
 9131-
 9132-	RGFW_monitorMode* modes = (RGFW_monitorMode*)RGFW_ALLOC(monitor->node->modeCount * sizeof(RGFW_monitorMode));
 9133-
 9134-	if (monitor->node->modeCount > 1) {
 9135-		RGFW_monitor_getModesPtr(monitor, &modes);
 9136-		RGFW_FREE(monitor->node->modes);
 9137-	}
 9138-
 9139-	modes[monitor->node->modeCount - 1] = mode;
 9140-	monitor->node->modes = modes;
 9141-
 9142-	if (flags & WL_OUTPUT_MODE_CURRENT) {
 9143-		monitor->mode = mode;
 9144-	} else {
 9145-	}
 9146-}
 9147-
 9148-static void RGFW_wl_output_set_scale(void *data, struct wl_output *wl_output, i32 factor) {
 9149-	RGFW_UNUSED(wl_output);
 9150-	RGFW_monitor* mon = &((RGFW_monitorNode*)data)->mon;
 9151-
 9152-	mon->scaleX = (float)factor;
 9153-	mon->scaleY = (float)factor;
 9154-}
 9155-
 9156-static void RGFW_wl_output_set_name(void *data, struct wl_output *wl_output, const char *name) {
 9157-	RGFW_monitor* monitor = &((RGFW_monitorNode*)data)->mon;
 9158-
 9159-	RGFW_STRNCPY(monitor->name, name, sizeof(monitor->name) - 1);
 9160-	monitor->name[sizeof(monitor->name) - 1] = '\0';
 9161-
 9162-	RGFW_UNUSED(wl_output);
 9163-
 9164-}
 9165-
 9166-static void RGFW_xdg_output_logical_pos(void *data, struct zxdg_output_v1 *zxdg_output_v1, i32 x, i32 y) {
 9167-	RGFW_monitor* monitor = &((RGFW_monitorNode*)data)->mon;
 9168-	monitor->x = x;
 9169-	monitor->y = y;
 9170-	RGFW_UNUSED(zxdg_output_v1);
 9171-}
 9172-
 9173-static void RGFW_xdg_output_logical_size(void *data, struct zxdg_output_v1 *zxdg_output_v1, i32 width, i32 height) {
 9174-	RGFW_monitor* monitor = &((RGFW_monitorNode*)data)->mon;
 9175-
 9176-	float mon_float_width = (float) monitor->mode.w;
 9177-	float mon_float_height = (float) monitor->mode.h;
 9178-
 9179-	float scaleX = (mon_float_width / (float) width);
 9180-	float scaleY = (mon_float_height / (float) height);
 9181-	RGFW_UNUSED(scaleY);
 9182-
 9183-	float dpi = scaleX * 96.0f;
 9184-
 9185-	monitor->pixelRatio = dpi >= 192.0f ? 2.0f : 1.0f;
 9186-
 9187-	/* under xwayland the monitor changes w & h when compositor scales it */
 9188-	monitor->mode.w = width;
 9189-	monitor->mode.h = height;
 9190-	RGFW_UNUSED(zxdg_output_v1);
 9191-}
 9192-
 9193-
 9194-static void RGFW_wl_output_handle_done(void* data, struct wl_output* output) {
 9195-	RGFW_UNUSED(output);
 9196-
 9197-	RGFW_monitor* monitor = &((RGFW_monitorNode*)data)->mon;
 9198-
 9199-    if (monitor->physW <= 0 || monitor->physH <= 0) {
 9200-		monitor->physW = (i32) ((float)monitor->mode.w / 96.0f);
 9201-		monitor->physH = (i32) ((float)monitor->mode.h / 96.0f);
 9202-    }
 9203-
 9204-	if (((RGFW_monitorNode*)data)->disconnected == RGFW_FALSE) {
 9205-		return;
 9206-	}
 9207-
 9208-	((RGFW_monitorNode*)data)->disconnected = RGFW_TRUE;
 9209-
 9210-	RGFW_monitorCallback(_RGFW->root, monitor, RGFW_TRUE);
 9211-}
 9212-
 9213-static void RGFW_wl_create_outputs(struct wl_registry *const registry, u32 id) {
 9214-	struct wl_output *output = wl_registry_bind(registry, id, &wl_output_interface, wl_proxy_get_version((struct wl_proxy*)_RGFW->seat));
 9215-	RGFW_monitorNode* node;
 9216-	RGFW_monitor mon;
 9217-
 9218-	if (!output) return;
 9219-
 9220-	char RGFW_mon_default_name[10];
 9221-
 9222-	RGFW_SNPRINTF(RGFW_mon_default_name, sizeof(RGFW_mon_default_name), "monitor-%li", _RGFW->monitors.count);
 9223-	RGFW_STRNCPY(mon.name, RGFW_mon_default_name, sizeof(mon.name) - 1);
 9224-	mon.name[sizeof(mon.name) - 1] = '\0';
 9225-
 9226-	/* set in case compositor does not send one */
 9227-    /* or no xdg_output support */
 9228-	mon.scaleY = mon.scaleX = mon.pixelRatio = 1.0f;
 9229-
 9230-	node = RGFW_monitors_add(&mon);
 9231-	if (node == NULL) return;
 9232-
 9233-	node->modeCount = 0;
 9234-	node->disconnected = RGFW_TRUE;
 9235-	node->id = id;
 9236-	node->output = output;
 9237-
 9238-	static const struct wl_output_listener wl_output_listener = {
 9239-			.geometry = RGFW_wl_output_set_geometry,
 9240-			.mode = RGFW_wl_output_handle_mode,
 9241-			.done = RGFW_wl_output_handle_done,
 9242-			.scale = RGFW_wl_output_set_scale,
 9243-			.name = RGFW_wl_output_set_name,
 9244-			.description = (void (*)(void *, struct wl_output *, const char *))&RGFW_doNothing
 9245-	};
 9246-
 9247-	/* the wl_output will have a reference to the node */
 9248-	wl_output_set_user_data(output, node);
 9249-
 9250-	/* pass the monitor so we can access it in the callback functions */
 9251-	wl_output_add_listener(output, &wl_output_listener, node);
 9252-
 9253-	if (!_RGFW->xdg_output_manager)
 9254-		return; /* compositor does not support it */
 9255-
 9256-	static const struct zxdg_output_v1_listener xdg_output_listener = {
 9257-		.name = (void (*)(void *,struct zxdg_output_v1 *, const char *))&RGFW_doNothing,
 9258-		.done = (void (*)(void *,struct zxdg_output_v1 *))&RGFW_doNothing,
 9259-		.description = (void (*)(void *,struct zxdg_output_v1 *, const char *))&RGFW_doNothing,
 9260-		.logical_position = RGFW_xdg_output_logical_pos,
 9261-		.logical_size = RGFW_xdg_output_logical_size
 9262-	};
 9263-
 9264-	node->xdg_output = zxdg_output_manager_v1_get_xdg_output(_RGFW->xdg_output_manager, node->output);
 9265-	zxdg_output_v1_add_listener(node->xdg_output, &xdg_output_listener, node);
 9266-}
 9267-
 9268-static void RGFW_wl_surface_enter(void *data, struct wl_surface *wl_surface, struct wl_output *output) {
 9269-	RGFW_UNUSED(wl_surface);
 9270-
 9271-	RGFW_window* win = (RGFW_window*)data;
 9272-	RGFW_monitorNode* node = wl_output_get_user_data(output);
 9273-	if (node == NULL) return;
 9274-
 9275-	win->src.active_monitor = node;
 9276-}
 9277-
 9278-static void RGFW_wl_data_source_send(void *data, struct wl_data_source *wl_data_source, const char *mime_type, i32 fd) {
 9279-	RGFW_UNUSED(data); RGFW_UNUSED(wl_data_source);
 9280-
 9281-	// a client can accept our clipboard
 9282-	if (RGFW_STRNCMP(mime_type, "text/plain;charset=utf-8", 25) == 0) {
 9283-		// do not write \0
 9284-		write(fd, _RGFW->clipboard, _RGFW->clipboard_len - 1);
 9285-	}
 9286-
 9287-	close(fd);
 9288-}
 9289-
 9290-static void RGFW_wl_data_source_cancelled(void *data, struct wl_data_source *wl_data_source) {
 9291-
 9292-	RGFW_info* RGFW = (RGFW_info*)data;
 9293-
 9294-	if (RGFW->kbOwner->src.data_source == wl_data_source) {
 9295-		RGFW->kbOwner->src.data_source = NULL;
 9296-	}
 9297-
 9298-	wl_data_source_destroy(wl_data_source);
 9299-
 9300-}
 9301-
 9302-static void RGFW_wl_data_device_data_offer(void *data, struct wl_data_device *wl_data_device, struct wl_data_offer *wl_data_offer) {
 9303-
 9304-	RGFW_UNUSED(data); RGFW_UNUSED(wl_data_device);
 9305-	static const struct wl_data_offer_listener wl_data_offer_listener = {
 9306-		.offer = (void (*)(void *data, struct wl_data_offer *wl_data_offer, const char *))RGFW_doNothing,
 9307-		.source_actions = (void (*)(void *data, struct wl_data_offer *wl_data_offer, u32 dnd_action))RGFW_doNothing,
 9308-		.action = (void (*)(void *data, struct wl_data_offer *wl_data_offer, u32 dnd_action))RGFW_doNothing
 9309-	};
 9310-	wl_data_offer_add_listener(wl_data_offer, &wl_data_offer_listener, NULL);
 9311-}
 9312-
 9313-static void RGFW_wl_data_device_selection(void *data, struct wl_data_device *wl_data_device, struct wl_data_offer *wl_data_offer) {
 9314-	RGFW_UNUSED(data); RGFW_UNUSED(wl_data_device);
 9315-	/* Clipboard is empty */
 9316-	if (wl_data_offer == NULL) {
 9317-		return;
 9318-	}
 9319-
 9320-	int pfds[2];
 9321-	pipe(pfds);
 9322-
 9323-	wl_data_offer_receive(wl_data_offer, "text/plain;charset=utf-8", pfds[1]);
 9324-	close(pfds[1]);
 9325-
 9326-	wl_display_roundtrip(_RGFW->wl_display);
 9327-
 9328-	char buf[1024];
 9329-
 9330-	ssize_t n = read(pfds[0], buf, sizeof(buf));
 9331-
 9332-	_RGFW->clipboard = (char*)RGFW_ALLOC((size_t)n);
 9333-	RGFW_ASSERT(_RGFW->clipboard != NULL);
 9334-	RGFW_STRNCPY(_RGFW->clipboard, buf, (size_t)n);
 9335-
 9336-	_RGFW->clipboard_len = (size_t)n + 1;
 9337-
 9338-	close(pfds[0]);
 9339-
 9340-	wl_data_offer_destroy(wl_data_offer);
 9341-
 9342-}
 9343-
 9344-static void RGFW_wl_global_registry_handler(void* data, struct wl_registry *registry, u32 id, const char *interface, u32 version) {
 9345-
 9346-    static struct wl_seat_listener seat_listener = {&RGFW_wl_seat_capabilities, (void (*)(void *, struct wl_seat *, const char *))&RGFW_doNothing};
 9347-    static const struct wl_shm_listener shm_listener = { .format = RGFW_wl_shm_format_handler };
 9348-
 9349-    RGFW_info* RGFW = (RGFW_info*)data;
 9350-    RGFW_UNUSED(version);
 9351-
 9352-    if (RGFW_STRNCMP(interface, "wl_compositor", 16) == 0) {
 9353-		RGFW->compositor = wl_registry_bind(registry, id, &wl_compositor_interface, 4);
 9354-	} else if (RGFW_STRNCMP(interface, "xdg_wm_base", 12) == 0) {
 9355-		RGFW->xdg_wm_base = wl_registry_bind(registry, id, &xdg_wm_base_interface, 1);
 9356-	} else if (RGFW_STRNCMP(interface, zxdg_decoration_manager_v1_interface.name, 255) == 0) {
 9357-		RGFW->decoration_manager = wl_registry_bind(registry, id, &zxdg_decoration_manager_v1_interface, 1);
 9358-    } else if (RGFW_STRNCMP(interface, zwp_pointer_constraints_v1_interface.name, 255) == 0) {
 9359-		RGFW->constraint_manager = wl_registry_bind(registry, id, &zwp_pointer_constraints_v1_interface, 1);
 9360-    } else if (RGFW_STRNCMP(interface, zwp_relative_pointer_manager_v1_interface.name, 255) == 0) {
 9361-		RGFW->relative_pointer_manager = wl_registry_bind(registry, id, &zwp_relative_pointer_manager_v1_interface, 1);
 9362-	} else if (RGFW_STRNCMP(interface, xdg_toplevel_icon_manager_v1_interface.name, 255) == 0) {
 9363-		RGFW->icon_manager = wl_registry_bind(registry, id, &xdg_toplevel_icon_manager_v1_interface, 1);
 9364-    } else if (RGFW_STRNCMP(interface, "wl_shm", 7) == 0) {
 9365-        RGFW->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
 9366-        wl_shm_add_listener(RGFW->shm, &shm_listener, RGFW);
 9367-	} else if (RGFW_STRNCMP(interface,"wl_seat", 8) == 0) {
 9368-		RGFW->seat = wl_registry_bind(registry, id, &wl_seat_interface, version < 4 ? 3 : 4);
 9369-		wl_seat_add_listener(RGFW->seat, &seat_listener, RGFW);
 9370-	} else if (RGFW_STRNCMP(interface, zxdg_output_manager_v1_interface.name, 255) == 0) {
 9371-		RGFW->xdg_output_manager = wl_registry_bind(registry, id, &zxdg_output_manager_v1_interface, 1);
 9372-	} else if (RGFW_STRNCMP(interface,"wl_output", 10) == 0) {
 9373-		RGFW_wl_create_outputs(registry, id);
 9374-	} else if (RGFW_STRNCMP(interface, wp_pointer_warp_v1_interface.name, 255) == 0) {
 9375-		RGFW->wp_pointer_warp = wl_registry_bind(registry, id, &wp_pointer_warp_v1_interface, 1);
 9376-	} else if (RGFW_STRNCMP(interface,"wl_data_device_manager", 23) == 0) {
 9377-		RGFW->data_device_manager = wl_registry_bind(registry, id, &wl_data_device_manager_interface, 1);
 9378-	}
 9379-}
 9380-
 9381-static void RGFW_wl_global_registry_remove(void* data, struct wl_registry *registry, u32 id) {
 9382-	RGFW_UNUSED(data); RGFW_UNUSED(registry);
 9383-	RGFW_info* RGFW = (RGFW_info*)data;
 9384-	RGFW_monitorNode* prev = RGFW->monitors.list.head;
 9385-	RGFW_monitorNode* node = NULL;
 9386-	if (prev == NULL) return;
 9387-
 9388-	if (prev->id != id) {
 9389-		/* find the first node that has a matching id */
 9390-		while(prev->next != NULL && prev->next->id != id) {
 9391-			prev = prev->next;
 9392-		}
 9393-
 9394-		if (prev->next == NULL) return;
 9395-		node = prev->next;
 9396-	} else {
 9397-		node = prev;
 9398-	}
 9399-
 9400-	if (node->output) {
 9401-		wl_output_destroy(node->output);
 9402-	}
 9403-
 9404-	if (node->xdg_output) {
 9405-		zxdg_output_v1_destroy(node->xdg_output);
 9406-	}
 9407-
 9408-	if (node->modeCount) {
 9409-		RGFW_FREE(node->modes);
 9410-		node->modeCount = 0;
 9411-	}
 9412-
 9413-	RGFW_monitorCallback(_RGFW->root, &node->mon, RGFW_FALSE);
 9414-	RGFW_monitors_remove(node, prev);
 9415-}
 9416-
 9417-static void RGFW_wl_randname(char *buf) {
 9418-	struct timespec ts;
 9419-	clock_gettime(CLOCK_REALTIME, &ts);
 9420-	long r = ts.tv_nsec;
 9421-
 9422-    int i;
 9423-    for (i = 0; i < 6; i++) {
 9424-		buf[i] = (char)('A'+(r&15)+(r&16)*2);
 9425-		r >>= 5;
 9426-	}
 9427-}
 9428-
 9429-static int RGFW_wl_anonymous_shm_open(void) {
 9430-	char name[] = "/RGFW-wayland-XXXXXX";
 9431-	int retries = 100;
 9432-
 9433-	do {
 9434-		RGFW_wl_randname(name + RGFW_unix_stringlen(name) - 6);
 9435-
 9436-		--retries;
 9437-		/* shm_open guarantees that O_CLOEXEC is set */
 9438-		int fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL, 0600);
 9439-		if (fd >= 0) {
 9440-			shm_unlink(name);
 9441-			return fd;
 9442-		}
 9443-	} while (retries > 0 && errno == EEXIST);
 9444-
 9445-	return -1;
 9446-}
 9447-
 9448-static int RGFW_wl_create_shm_file(off_t size) {
 9449-	int fd = RGFW_wl_anonymous_shm_open();
 9450-	if (fd < 0) {
 9451-		return fd;
 9452-	}
 9453-
 9454-	if (ftruncate(fd, size) < 0) {
 9455-		close(fd);
 9456-		return -1;
 9457-	}
 9458-
 9459-	return fd;
 9460-}
 9461-
 9462-i32 RGFW_initPlatform_Wayland(void) {
 9463-	_RGFW->wl_display = wl_display_connect(NULL);
 9464-	if (_RGFW->wl_display == NULL) {
 9465-		RGFW_debugCallback(RGFW_typeError, RGFW_errWayland,  "Failed to load Wayland display");
 9466-		return -1;
 9467-	}
 9468-
 9469-	_RGFW->compositor = NULL;
 9470-	static const struct wl_registry_listener registry_listener = {
 9471-		.global = RGFW_wl_global_registry_handler,
 9472-		.global_remove = RGFW_wl_global_registry_remove,
 9473-	};
 9474-
 9475-	_RGFW->registry = wl_display_get_registry(_RGFW->wl_display);
 9476-	wl_registry_add_listener(_RGFW->registry, &registry_listener, _RGFW);
 9477-
 9478-	wl_display_roundtrip(_RGFW->wl_display); /* bind to globals */
 9479-
 9480-	if (_RGFW->compositor == NULL) {
 9481-		RGFW_debugCallback(RGFW_typeError, RGFW_errWayland, "Can't find compositor.");
 9482-		return 1;
 9483-	}
 9484-
 9485-	if (_RGFW->wl_cursor_theme == NULL) {
 9486-		_RGFW->wl_cursor_theme = wl_cursor_theme_load(NULL, 24, _RGFW->shm);
 9487-		_RGFW->cursor_surface = wl_compositor_create_surface(_RGFW->compositor);
 9488-	}
 9489-
 9490-	 u8 RGFW_blk[] = { 0, 0, 0, 0 };
 9491-	_RGFW->hiddenMouse = RGFW_createMouse(RGFW_blk, 1, 1, RGFW_formatRGBA8);
 9492-
 9493-	static const struct xdg_wm_base_listener xdg_wm_base_listener = {
 9494-		.ping = RGFW_wl_xdg_wm_base_ping_handler,
 9495-	};
 9496-
 9497-	xdg_wm_base_add_listener(_RGFW->xdg_wm_base, &xdg_wm_base_listener, NULL);
 9498-
 9499-	_RGFW->xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
 9500-
 9501-	static const struct wl_data_device_listener wl_data_device_listener = {
 9502-		.data_offer = RGFW_wl_data_device_data_offer,
 9503-		.enter = (void (*)(void *, struct wl_data_device *, u32, struct wl_surface*, wl_fixed_t, wl_fixed_t, struct wl_data_offer *))&RGFW_doNothing,
 9504-		.leave = (void (*)(void *, struct wl_data_device *))&RGFW_doNothing,
 9505-		.motion = (void (*)(void *, struct wl_data_device *, u32, wl_fixed_t, wl_fixed_t))&RGFW_doNothing,
 9506-		.drop = (void (*)(void *, struct wl_data_device *))&RGFW_doNothing,
 9507-		.selection = RGFW_wl_data_device_selection
 9508-	};
 9509-
 9510-	if (_RGFW->seat && _RGFW->data_device_manager) {
 9511-		_RGFW->data_device = wl_data_device_manager_get_data_device(_RGFW->data_device_manager, _RGFW->seat);
 9512-		wl_data_device_add_listener(_RGFW->data_device, &wl_data_device_listener, NULL);
 9513-	}
 9514-
 9515-	return 0;
 9516-}
 9517-
 9518-void RGFW_deinitPlatform_Wayland(void) {
 9519-	if (_RGFW->clipboard) {
 9520-		RGFW_FREE(_RGFW->clipboard);
 9521-		_RGFW->clipboard = NULL;
 9522-	}
 9523-
 9524-    if (_RGFW->wl_pointer) {
 9525-		wl_pointer_destroy(_RGFW->wl_pointer);
 9526-	}
 9527-	if (_RGFW->wl_keyboard) {
 9528-		wl_keyboard_destroy(_RGFW->wl_keyboard);
 9529-	}
 9530-
 9531-	wl_registry_destroy(_RGFW->registry);
 9532-	if (_RGFW->decoration_manager != NULL)
 9533-		zxdg_decoration_manager_v1_destroy(_RGFW->decoration_manager);
 9534-	if (_RGFW->relative_pointer_manager != NULL) {
 9535-		zwp_relative_pointer_manager_v1_destroy(_RGFW->relative_pointer_manager);
 9536-	}
 9537-
 9538-	if (_RGFW->relative_pointer) {
 9539-		zwp_relative_pointer_v1_destroy(_RGFW->relative_pointer);
 9540-	}
 9541-
 9542-	if (_RGFW->constraint_manager != NULL) {
 9543-		zwp_pointer_constraints_v1_destroy(_RGFW->constraint_manager);
 9544-	}
 9545-
 9546-	if (_RGFW->xdg_output_manager != NULL)
 9547-	if (_RGFW->icon_manager != NULL) {
 9548-		xdg_toplevel_icon_manager_v1_destroy(_RGFW->icon_manager);
 9549-	}
 9550-
 9551-	if (_RGFW->xdg_output_manager) {
 9552-		zxdg_output_manager_v1_destroy(_RGFW->xdg_output_manager);
 9553-	}
 9554-
 9555-	if (_RGFW->data_device_manager) {
 9556-		wl_data_device_manager_destroy(_RGFW->data_device_manager);
 9557-	}
 9558-
 9559-	if (_RGFW->data_device) {
 9560-		wl_data_device_destroy(_RGFW->data_device);
 9561-	}
 9562-
 9563-	if (_RGFW->wl_cursor_theme != NULL) {
 9564-		wl_cursor_theme_destroy(_RGFW->wl_cursor_theme);
 9565-	}
 9566-
 9567-	if (_RGFW->wp_pointer_warp != NULL) {
 9568-		wp_pointer_warp_v1_destroy(_RGFW->wp_pointer_warp);
 9569-	}
 9570-
 9571-	RGFW_freeMouse(_RGFW->hiddenMouse);
 9572-
 9573-	RGFW_monitorNode* node = _RGFW->monitors.list.head;
 9574-
 9575-	while (node != NULL) {
 9576-		if (node->output) {
 9577-			wl_output_destroy(node->output);
 9578-		}
 9579-
 9580-		if (node->xdg_output) {
 9581-			zxdg_output_v1_destroy(node->xdg_output);
 9582-		}
 9583-
 9584-		_RGFW->monitors.count -= 1;
 9585-		node = node->next;
 9586-
 9587-	}
 9588-
 9589-	wl_surface_destroy(_RGFW->cursor_surface);
 9590-	wl_shm_destroy(_RGFW->shm);
 9591-	wl_seat_release(_RGFW->seat);
 9592-	xdg_wm_base_destroy(_RGFW->xdg_wm_base);
 9593-	wl_compositor_destroy(_RGFW->compositor);
 9594-	wl_display_disconnect(_RGFW->wl_display);
 9595-}
 9596-
 9597-RGFW_format RGFW_FUNC(RGFW_nativeFormat)(void) { return RGFW_formatBGRA8; }
 9598-
 9599-RGFW_bool RGFW_FUNC(RGFW_createSurfacePtr) (u8* data, i32 w, i32 h, RGFW_format format, RGFW_surface* surface) {
 9600-	RGFW_ASSERT(surface != NULL);
 9601-	surface->data = data;
 9602-	surface->w = w;
 9603-	surface->h = h;
 9604-	surface->format = format;
 9605-	RGFW_debugCallback(RGFW_typeInfo, RGFW_infoBuffer,  "Creating a 4 channel buffer");
 9606-
 9607-	u32 size = (u32)(surface->w * surface->h * 4);
 9608-	int fd = RGFW_wl_create_shm_file(size);
 9609-	if (fd < 0) {
 9610-		RGFW_debugCallback(RGFW_typeError, RGFW_errBuffer, "Failed to create a buffer.");
 9611-		return RGFW_FALSE;
 9612-	}
 9613-
 9614-	surface->native.pool = wl_shm_create_pool(_RGFW->shm, fd, (i32)size);
 9615-
 9616-	surface->native.buffer = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
 9617-	if (surface->native.buffer == MAP_FAILED) {
 9618-		RGFW_debugCallback(RGFW_typeError, RGFW_errBuffer, "mmap failed.");
 9619-		return RGFW_FALSE;
 9620-	}
 9621-
 9622-	surface->native.fd = fd;
 9623-	surface->native.format = RGFW_formatBGRA8;
 9624-	return RGFW_TRUE;
 9625-}
 9626-
 9627-void RGFW_FUNC(RGFW_window_blitSurface) (RGFW_window* win, RGFW_surface* surface) {
 9628-	RGFW_ASSERT(surface != NULL);
 9629-
 9630-	surface->native.wl_buffer = wl_shm_pool_create_buffer(surface->native.pool, 0, RGFW_MIN(win->w, surface->w), RGFW_MIN(win->h, surface->h), (i32)surface->w * 4, WL_SHM_FORMAT_ARGB8888);
 9631-	RGFW_copyImageData(surface->native.buffer, surface->w, RGFW_MIN(win->h, surface->h), surface->native.format, surface->data, surface->format, surface->convertFunc);
 9632-
 9633-	wl_surface_attach(win->src.surface, surface->native.wl_buffer, 0, 0);
 9634-	wl_surface_damage(win->src.surface, 0, 0, RGFW_MIN(win->w, surface->w), RGFW_MIN(win->h, surface->h));
 9635-	wl_surface_commit(win->src.surface);
 9636-
 9637-	wl_buffer_destroy(surface->native.wl_buffer);
 9638-
 9639-	surface->native.wl_buffer = NULL;
 9640-}
 9641-
 9642-void RGFW_FUNC(RGFW_surface_freePtr) (RGFW_surface* surface) {
 9643-	RGFW_ASSERT(surface != NULL);
 9644-
 9645-	if (surface->native.pool) wl_shm_pool_destroy(surface->native.pool);
 9646-	if (surface->native.fd) close(surface->native.fd);
 9647-	if (surface->native.buffer) munmap(surface->native.buffer, (size_t)(surface->w * surface->h * 4));
 9648-}
 9649-
 9650-void RGFW_FUNC(RGFW_window_setBorder) (RGFW_window* win, RGFW_bool border) {
 9651-	RGFW_setBit(&win->internal.flags, RGFW_windowNoBorder, !border);
 9652-
 9653-	/* for now just toggle between SSD & CSD depending on the bool */
 9654-	if (_RGFW->decoration_manager != NULL) {
 9655-		zxdg_toplevel_decoration_v1_set_mode(win->src.decoration, (border ? ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE : ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE));
 9656-	}
 9657-}
 9658-
 9659-void RGFW_FUNC(RGFW_window_setRawMouseModePlatform) (RGFW_window* win, RGFW_bool state) {
 9660-	RGFW_ASSERT(win);
 9661-	if (_RGFW->relative_pointer_manager == NULL) return;
 9662-
 9663-	if (state == RGFW_FALSE) {
 9664-		if (_RGFW->relative_pointer != NULL)
 9665-			zwp_relative_pointer_v1_destroy(_RGFW->relative_pointer);
 9666-		_RGFW->relative_pointer = NULL;
 9667-		return;
 9668-	}
 9669-
 9670-	if (_RGFW->relative_pointer != NULL) return;
 9671-
 9672-	_RGFW->relative_pointer = zwp_relative_pointer_manager_v1_get_relative_pointer(_RGFW->relative_pointer_manager, _RGFW->wl_pointer);
 9673-
 9674-	static const struct zwp_relative_pointer_v1_listener relative_motion_listener = {
 9675-		.relative_motion = RGFW_wl_relative_pointer_motion
 9676-	};
 9677-
 9678-	zwp_relative_pointer_v1_add_listener(_RGFW->relative_pointer, &relative_motion_listener, _RGFW);
 9679-}
 9680-
 9681-void RGFW_FUNC(RGFW_window_captureMousePlatform) (RGFW_window* win, RGFW_bool state) {
 9682-	RGFW_ASSERT(win);
 9683-
 9684-	/* compositor has no support or window already is locked do nothing */
 9685-	if (_RGFW->constraint_manager == NULL) return;
 9686-
 9687-	if (state == RGFW_FALSE) {
 9688-		if (win->src.locked_pointer != NULL)
 9689-			zwp_locked_pointer_v1_destroy(win->src.locked_pointer);
 9690-		win->src.locked_pointer = NULL;
 9691-		return;
 9692-	}
 9693-
 9694-
 9695-	if (win->src.locked_pointer != NULL) return;
 9696-	win->src.locked_pointer = zwp_pointer_constraints_v1_lock_pointer(_RGFW->constraint_manager, win->src.surface, _RGFW->wl_pointer, NULL, ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
 9697-
 9698-	static const struct zwp_locked_pointer_v1_listener locked_listener = {
 9699-		.locked = RGFW_wl_pointer_locked,
 9700-		.unlocked = (void (*)(void *, struct zwp_locked_pointer_v1 *))RGFW_doNothing
 9701-	};
 9702-
 9703-	zwp_locked_pointer_v1_add_listener(win->src.locked_pointer, &locked_listener, _RGFW);
 9704-}
 9705-
 9706-RGFW_window* RGFW_FUNC(RGFW_createWindowPlatform) (const char* name, RGFW_windowFlags flags, RGFW_window* win) {
 9707-	RGFW_debugCallback(RGFW_typeWarning, RGFW_warningWayland, "RGFW Wayland support is experimental");
 9708-
 9709-	static const struct xdg_surface_listener xdg_surface_listener = {
 9710-		.configure = RGFW_wl_xdg_surface_configure_handler,
 9711-	};
 9712-
 9713-	static const struct wl_surface_listener wl_surface_listener = {
 9714-		.enter = RGFW_wl_surface_enter,
 9715-		.leave = (void (*)(void *, struct wl_surface *, struct wl_output *))&RGFW_doNothing,
 9716-		.preferred_buffer_scale = (void (*)(void *, struct wl_surface *, i32))&RGFW_doNothing,
 9717-		.preferred_buffer_transform = (void (*)(void *, struct wl_surface *, u32))&RGFW_doNothing
 9718-	};
 9719-
 9720-	win->src.surface = wl_compositor_create_surface(_RGFW->compositor);
 9721-	wl_surface_add_listener(win->src.surface, &wl_surface_listener, win);
 9722-
 9723-	/* create a surface for a custom cursor */
 9724-	win->src.custom_cursor_surface = wl_compositor_create_surface(_RGFW->compositor);
 9725-
 9726-	win->src.xdg_surface = xdg_wm_base_get_xdg_surface(_RGFW->xdg_wm_base, win->src.surface);
 9727-	xdg_surface_add_listener(win->src.xdg_surface, &xdg_surface_listener, win);
 9728-
 9729-	xdg_wm_base_set_user_data(_RGFW->xdg_wm_base, win);
 9730-
 9731-	win->src.xdg_toplevel = xdg_surface_get_toplevel(win->src.xdg_surface);
 9732-
 9733-	if (_RGFW->className == NULL)
 9734-		_RGFW->className = (char*)name;
 9735-
 9736-	xdg_toplevel_set_app_id(win->src.xdg_toplevel, name);
 9737-
 9738-	xdg_surface_set_window_geometry(win->src.xdg_surface, 0, 0, win->w, win->h);
 9739-
 9740-	if (!(win->internal.flags & RGFW_windowTransparent)) { /* no transparency */
 9741-		RGFW_wl_setOpaque(win);
 9742-	}
 9743-
 9744-	static const struct xdg_toplevel_listener xdg_toplevel_listener = {
 9745-		.configure = RGFW_wl_xdg_toplevel_configure_handler,
 9746-		.close = RGFW_wl_xdg_toplevel_close_handler,
 9747-	};
 9748-
 9749-	xdg_toplevel_add_listener(win->src.xdg_toplevel, &xdg_toplevel_listener, win);
 9750-
 9751-	/* compositor supports both SSD & CSD
 9752-	   So choose accordingly
 9753-	 */
 9754-	if (_RGFW->decoration_manager) {
 9755-		u32 decoration_mode = ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE;
 9756-		win->src.decoration = zxdg_decoration_manager_v1_get_toplevel_decoration(
 9757-			_RGFW->decoration_manager, win->src.xdg_toplevel);
 9758-
 9759-		static const struct zxdg_toplevel_decoration_v1_listener xdg_decoration_listener = {
 9760-			.configure = RGFW_wl_xdg_decoration_configure_handler
 9761-		};
 9762-
 9763-		zxdg_toplevel_decoration_v1_add_listener(win->src.decoration, &xdg_decoration_listener, win);
 9764-
 9765-		/* we want no decorations */
 9766-		if ((flags & RGFW_windowNoBorder)) {
 9767-			decoration_mode = ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE;
 9768-		}
 9769-
 9770-		zxdg_toplevel_decoration_v1_set_mode(win->src.decoration, decoration_mode);
 9771-
 9772-        /* no xdg_decoration support */
 9773-	} else if (!(flags & RGFW_windowNoBorder)) {
 9774-		/* TODO, some fallback */
 9775-		#ifdef RGFW_LIBDECOR
 9776-			static struct libdecor_interface interface = {
 9777-				.error = NULL,
 9778-			};
 9779-
 9780-			static struct libdecor_frame_interface frameInterface = {0}; /*= {
 9781-				RGFW_wl_handle_configure,
 9782-				RGFW_wl_handle_close,
 9783-				RGFW_wl_handle_commit,
 9784-				RGFW_wl_handle_dismiss_popup,
 9785-			};*/
 9786-
 9787-			win->src.decorContext = libdecor_new(_RGFW->wl_display, &interface);
 9788-			if (win->src.decorContext) {
 9789-				struct libdecor_frame *frame = libdecor_decorate(win->src.decorContext, win->src.surface, &frameInterface, win);
 9790-				if (!frame) {
 9791-					libdecor_unref(win->src.decorContext);
 9792-					win->src.decorContext = NULL;
 9793-				} else {
 9794-					libdecor_frame_set_app_id(frame, "my-libdecor-app");
 9795-					libdecor_frame_set_title(frame, "My Libdecor Window");
 9796-				}
 9797-			}
 9798-		#endif
 9799-	}
 9800-
 9801-	if (_RGFW->icon_manager != NULL) {
 9802-		/* set the default wayland icon */
 9803-		xdg_toplevel_icon_manager_v1_set_icon(_RGFW->icon_manager, win->src.xdg_toplevel, NULL);
 9804-	}
 9805-
 9806-	wl_surface_commit(win->src.surface);
 9807-
 9808-	while (win->src.configured == RGFW_FALSE) {
 9809-		wl_display_dispatch(_RGFW->wl_display);
 9810-	}
 9811-
 9812-	RGFW_UNUSED(name);
 9813-
 9814-	return win;
 9815-}
 9816-
 9817-RGFW_bool RGFW_FUNC(RGFW_getGlobalMouse) (i32* x, i32* y) {
 9818-	RGFW_init();
 9819-	if (x) *x = 0;
 9820-	if (y) *y = 0;
 9821-	return RGFW_FALSE;
 9822-}
 9823-
 9824-RGFW_key RGFW_FUNC(RGFW_physicalToMappedKey)(RGFW_key key) {
 9825-    u32 keycode = RGFW_rgfwToApiKey(key);
 9826-	xkb_keycode_t kc = keycode + 8;
 9827-    xkb_keysym_t sym = xkb_state_key_get_one_sym(_RGFW->xkb_state, kc);
 9828-    if (sym < 256) {
 9829-        return (RGFW_key)sym;
 9830-    }
 9831-
 9832-    switch (sym) {
 9833-        case XKB_KEY_F1:  return RGFW_keyF1;
 9834-        case XKB_KEY_F2:  return RGFW_keyF2;
 9835-        case XKB_KEY_F3:  return RGFW_keyF3;
 9836-        case XKB_KEY_F4:  return RGFW_keyF4;
 9837-        case XKB_KEY_F5:  return RGFW_keyF5;
 9838-        case XKB_KEY_F6:  return RGFW_keyF6;
 9839-        case XKB_KEY_F7:  return RGFW_keyF7;
 9840-        case XKB_KEY_F8:  return RGFW_keyF8;
 9841-        case XKB_KEY_F9:  return RGFW_keyF9;
 9842-        case XKB_KEY_F10: return RGFW_keyF10;
 9843-        case XKB_KEY_F11: return RGFW_keyF11;
 9844-        case XKB_KEY_F12: return RGFW_keyF12;
 9845-        case XKB_KEY_F13: return RGFW_keyF13;
 9846-        case XKB_KEY_F14: return RGFW_keyF14;
 9847-        case XKB_KEY_F15: return RGFW_keyF15;
 9848-        case XKB_KEY_F16: return RGFW_keyF16;
 9849-        case XKB_KEY_F17: return RGFW_keyF17;
 9850-        case XKB_KEY_F18: return RGFW_keyF18;
 9851-        case XKB_KEY_F19: return RGFW_keyF19;
 9852-        case XKB_KEY_F20: return RGFW_keyF20;
 9853-        case XKB_KEY_F21: return RGFW_keyF21;
 9854-        case XKB_KEY_F22: return RGFW_keyF22;
 9855-        case XKB_KEY_F23: return RGFW_keyF23;
 9856-        case XKB_KEY_F24: return RGFW_keyF24;
 9857-        case XKB_KEY_F25: return RGFW_keyF25;
 9858-        case XKB_KEY_Shift_L:   return RGFW_keyShiftL;
 9859-        case XKB_KEY_Shift_R:   return RGFW_keyShiftR;
 9860-        case XKB_KEY_Control_L: return RGFW_keyControlL;
 9861-        case XKB_KEY_Control_R: return RGFW_keyControlR;
 9862-        case XKB_KEY_Alt_L:     return RGFW_keyAltL;
 9863-        case XKB_KEY_Alt_R:     return RGFW_keyAltR;
 9864-        case XKB_KEY_Super_L:   return RGFW_keySuperL;
 9865-        case XKB_KEY_Super_R:   return RGFW_keySuperR;
 9866-        case XKB_KEY_Caps_Lock: return RGFW_keyCapsLock;
 9867-        case XKB_KEY_Num_Lock:  return RGFW_keyNumLock;
 9868-        case XKB_KEY_Scroll_Lock:return RGFW_keyScrollLock;
 9869-        case XKB_KEY_Up:        return RGFW_keyUp;
 9870-        case XKB_KEY_Down:      return RGFW_keyDown;
 9871-        case XKB_KEY_Left:      return RGFW_keyLeft;
 9872-        case XKB_KEY_Right:     return RGFW_keyRight;
 9873-        case XKB_KEY_Home:      return RGFW_keyHome;
 9874-        case XKB_KEY_End:       return RGFW_keyEnd;
 9875-        case XKB_KEY_Page_Up:   return RGFW_keyPageUp;
 9876-        case XKB_KEY_Page_Down: return RGFW_keyPageDown;
 9877-        case XKB_KEY_Insert:    return RGFW_keyInsert;
 9878-        case XKB_KEY_Menu:      return RGFW_keyMenu;
 9879-        case XKB_KEY_KP_Add:      return RGFW_keyPadPlus;
 9880-        case XKB_KEY_KP_Subtract: return RGFW_keyPadMinus;
 9881-        case XKB_KEY_KP_Multiply: return RGFW_keyPadMultiply;
 9882-        case XKB_KEY_KP_Divide:   return RGFW_keyPadSlash;
 9883-        case XKB_KEY_KP_Equal:    return RGFW_keyPadEqual;
 9884-        case XKB_KEY_KP_Enter:    return RGFW_keyPadReturn;
 9885-        case XKB_KEY_KP_Decimal:  return RGFW_keyPadPeriod;
 9886-        case XKB_KEY_KP_0: return RGFW_keyPad0;
 9887-        case XKB_KEY_KP_1: return RGFW_keyPad1;
 9888-        case XKB_KEY_KP_2: return RGFW_keyPad2;
 9889-        case XKB_KEY_KP_3: return RGFW_keyPad3;
 9890-        case XKB_KEY_KP_4: return RGFW_keyPad4;
 9891-        case XKB_KEY_KP_5: return RGFW_keyPad5;
 9892-        case XKB_KEY_KP_6: return RGFW_keyPad6;
 9893-        case XKB_KEY_KP_7: return RGFW_keyPad7;
 9894-        case XKB_KEY_KP_8: return RGFW_keyPad8;
 9895-        case XKB_KEY_KP_9: return RGFW_keyPad9;
 9896-        case XKB_KEY_Print: return RGFW_keyPrintScreen;
 9897-        case XKB_KEY_Pause: return RGFW_keyPause;
 9898-        default: break;
 9899-    }
 9900-
 9901-    return RGFW_keyNULL;
 9902-}
 9903-
 9904-RGFW_bool RGFW_FUNC(RGFW_window_fetchSize) (RGFW_window* win, i32* w, i32* h) {
 9905-	return RGFW_window_getSize(win, w, h);
 9906-}
 9907-
 9908-void RGFW_FUNC(RGFW_pollEvents) (void) {
 9909-	RGFW_resetPrevState();
 9910-
 9911-	/* send buffered requests to compositor */
 9912-	while (wl_display_flush(_RGFW->wl_display) == -1) {
 9913-		/* compositor not responding to new requests */
 9914-		/* so let's dispatch some events so the compositor responds */
 9915-		if (errno == EAGAIN) {
 9916-			if (wl_display_dispatch_pending(_RGFW->wl_display) == -1) {
 9917-				return;
 9918-			}
 9919-		} else {
 9920-			return;
 9921-		}
 9922-	}
 9923-	if (_RGFW->wl_repeat_info_rate != 0 && _RGFW->last_key) {
 9924-		u32 now = (u32)(RGFW_linux_getTimeNS() / 1000000);
 9925-		if (now > _RGFW->last_key_time) {
 9926-			RGFW_wl_send_key_event(_RGFW->last_key);
 9927-			_RGFW->last_key_time = now + 1000 / (u32)_RGFW->wl_repeat_info_rate;
 9928-		}
 9929-	}
 9930-
 9931-	/* read the events; if empty this reads from the */
 9932-	/* wayland file descriptor */
 9933-	if (wl_display_dispatch(_RGFW->wl_display) == -1) {
 9934-		return;
 9935-	}
 9936-
 9937-}
 9938-
 9939-void RGFW_FUNC(RGFW_window_move) (RGFW_window* win, i32 x, i32 y) {
 9940-	RGFW_ASSERT(win != NULL);
 9941-	win->x = x;
 9942-	win->y = y;
 9943-}
 9944-
 9945-
 9946-void RGFW_FUNC(RGFW_window_resize) (RGFW_window* win, i32 w, i32 h) {
 9947-	RGFW_ASSERT(win != NULL);
 9948-	win->w = w;
 9949-	win->h = h;
 9950-	if (_RGFW->compositor) {
 9951-		xdg_surface_set_window_geometry(win->src.xdg_surface, 0, 0, win->w, win->h);
 9952-		#ifdef RGFW_OPENGL
 9953-		if (win->src.ctx.egl)
 9954-			wl_egl_window_resize(win->src.ctx.egl->eglWindow, (i32)w, (i32)h, 0, 0);
 9955-		#endif
 9956-	}
 9957-}
 9958-
 9959-void RGFW_FUNC(RGFW_window_setAspectRatio) (RGFW_window* win, i32 w, i32 h) {
 9960-	RGFW_ASSERT(win != NULL);
 9961-
 9962-	if (w == 0 && h == 0)
 9963-		return;
 9964-    xdg_toplevel_set_max_size(win->src.xdg_toplevel, (i32)w, (i32)h);
 9965-}
 9966-
 9967-void RGFW_FUNC(RGFW_window_setMinSize) (RGFW_window* win, i32 w, i32 h) {
 9968-	RGFW_ASSERT(win != NULL);
 9969-    xdg_toplevel_set_min_size(win->src.xdg_toplevel, w, h);
 9970-}
 9971-
 9972-void RGFW_FUNC(RGFW_window_setMaxSize) (RGFW_window* win, i32 w, i32 h) {
 9973-	RGFW_ASSERT(win != NULL);
 9974-    xdg_toplevel_set_max_size(win->src.xdg_toplevel, w, h);
 9975-}
 9976-
 9977-void RGFW_toggleWaylandMaximized(RGFW_window* win, RGFW_bool maximized) {
 9978-    win->src.maximized = maximized;
 9979-    if (maximized) {
 9980-		xdg_toplevel_set_maximized(win->src.xdg_toplevel);
 9981-    } else {
 9982-		xdg_toplevel_unset_maximized(win->src.xdg_toplevel);
 9983-    }
 9984-}
 9985-
 9986-void RGFW_FUNC(RGFW_window_maximize) (RGFW_window* win) {
 9987-	win->internal.oldX = win->x;
 9988-	win->internal.oldY = win->y;
 9989-	win->internal.oldW = win->w;
 9990-	win->internal.oldH = win->h;
 9991-    RGFW_toggleWaylandMaximized(win, 1);
 9992-	RGFW_window_fetchSize(win, NULL, NULL);
 9993-    return;
 9994-}
 9995-
 9996-void RGFW_FUNC(RGFW_window_focus)(RGFW_window* win) {
 9997-	RGFW_ASSERT(win);
 9998-}
 9999-
10000-void RGFW_FUNC(RGFW_window_raise)(RGFW_window* win) {
10001-	RGFW_ASSERT(win);
10002-}
10003-
10004-void RGFW_FUNC(RGFW_window_setFullscreen)(RGFW_window* win, RGFW_bool fullscreen) {
10005-	RGFW_ASSERT(win != NULL);
10006-    if (fullscreen) {
10007-
10008-		win->internal.flags |= RGFW_windowFullscreen;
10009-		win->internal.oldX = win->x;
10010-		win->internal.oldY = win->y;
10011-		win->internal.oldW = win->w;
10012-		win->internal.oldH = win->h;
10013-		xdg_toplevel_set_fullscreen(win->src.xdg_toplevel, NULL); /* let the compositor decide */
10014-	} else {
10015-		win->internal.flags &= ~(u32)RGFW_windowFullscreen;
10016-		xdg_toplevel_unset_fullscreen(win->src.xdg_toplevel);
10017-	}
10018-
10019-}
10020-
10021-void RGFW_FUNC(RGFW_window_setFloating) (RGFW_window* win, RGFW_bool floating) {
10022-    RGFW_ASSERT(win != NULL);
10023-	RGFW_UNUSED(floating);
10024-}
10025-
10026-void RGFW_FUNC(RGFW_window_setOpacity) (RGFW_window* win, u8 opacity) {
10027-	RGFW_ASSERT(win != NULL);
10028-	RGFW_UNUSED(opacity);
10029-}
10030-
10031-void RGFW_FUNC(RGFW_window_minimize)(RGFW_window* win) {
10032-	RGFW_ASSERT(win != NULL);
10033-	if (RGFW_window_isMaximized(win)) return;
10034-	win->internal.oldX = win->x;
10035-	win->internal.oldY = win->y;
10036-	win->internal.oldW = win->w;
10037-	win->internal.oldH = win->h;
10038-	win->src.minimized = RGFW_TRUE;
10039-	xdg_toplevel_set_minimized(win->src.xdg_toplevel);
10040-}
10041-
10042-void RGFW_FUNC(RGFW_window_restore)(RGFW_window* win) {
10043-	RGFW_ASSERT(win != NULL);
10044-	RGFW_toggleWaylandMaximized(win, RGFW_FALSE);
10045-
10046-	RGFW_window_move(win, win->internal.oldX, win->internal.oldY);
10047-	RGFW_window_resize(win, win->internal.oldW, win->internal.oldH);
10048-
10049-	RGFW_window_show(win);
10050-	RGFW_window_move(win, win->internal.oldX, win->internal.oldY);
10051-	RGFW_window_resize(win, win->internal.oldW, win->internal.oldH);
10052-
10053-    RGFW_window_show(win);
10054-}
10055-
10056-RGFW_bool RGFW_FUNC(RGFW_window_isFloating)(RGFW_window* win) {
10057-	return (!RGFW_window_isFullscreen(win) && !RGFW_window_isMaximized(win));
10058-}
10059-
10060-void RGFW_FUNC(RGFW_window_setName) (RGFW_window* win, const char* name) {
10061-	RGFW_ASSERT(win != NULL);
10062-	if (name == NULL) name = "\0";
10063-
10064-	if (_RGFW->compositor)
10065-		xdg_toplevel_set_title(win->src.xdg_toplevel, name);
10066-}
10067-
10068-#ifndef RGFW_NO_PASSTHROUGH
10069-void RGFW_FUNC(RGFW_window_setMousePassthrough) (RGFW_window* win, RGFW_bool passthrough) {
10070-	RGFW_ASSERT(win != NULL);
10071-    RGFW_UNUSED(passthrough);
10072-}
10073-#endif /* RGFW_NO_PASSTHROUGH */
10074-
10075-RGFW_bool RGFW_FUNC(RGFW_window_setIconEx) (RGFW_window* win, u8* data, i32 w, i32 h, RGFW_format format, RGFW_icon type) {
10076-	RGFW_ASSERT(win != NULL);
10077-	RGFW_UNUSED(type);
10078-
10079-	if (_RGFW->icon_manager == NULL || w != h) return RGFW_FALSE;
10080-
10081-	if (win->src.icon) {
10082-		xdg_toplevel_icon_v1_destroy(win->src.icon);
10083-		win->src.icon= NULL;
10084-	}
10085-
10086-	RGFW_surface* surface = RGFW_createSurface(data, w, h, format);
10087-
10088-	if (surface == NULL) return RGFW_FALSE;
10089-
10090-	RGFW_copyImageData(surface->native.buffer, RGFW_MIN(w, surface->w), RGFW_MIN(h, surface->h), surface->native.format, surface->data, surface->format, NULL);
10091-
10092-	win->src.icon = xdg_toplevel_icon_manager_v1_create_icon(_RGFW->icon_manager);
10093-	xdg_toplevel_icon_v1_add_buffer(win->src.icon, surface->native.wl_buffer, 1);
10094-	xdg_toplevel_icon_manager_v1_set_icon(_RGFW->icon_manager, win->src.xdg_toplevel, win->src.icon);
10095-
10096-	RGFW_surface_free(surface);
10097-	return RGFW_TRUE;
10098-}
10099-
10100-RGFW_mouse* RGFW_FUNC(RGFW_createMouseStandard) (RGFW_mouseIcon mouse) {
10101-	char* cursorName = NULL;
10102-	switch (mouse) {
10103-		case RGFW_mouseNormal:       cursorName = (char*)"left_ptr"; break;
10104-		case RGFW_mouseArrow:       cursorName = (char*)"left_ptr"; break;
10105-		case RGFW_mouseIbeam:       cursorName = (char*)"xterm"; break;
10106-		case RGFW_mouseCrosshair:    cursorName = (char*)"crosshair"; break;
10107-		case RGFW_mousePointingHand: cursorName = (char*)"hand2"; break;
10108-		case RGFW_mouseResizeEW:     cursorName = (char*)"sb_h_double_arrow"; break;
10109-		case RGFW_mouseResizeNS:     cursorName = (char*)"sb_v_double_arrow"; break;
10110-		case RGFW_mouseResizeNWSE:   cursorName = (char*)"top_left_corner"; break;   /* or fd_double_arrow */
10111-		case RGFW_mouseResizeNESW:   cursorName = (char*)"top_right_corner"; break;  /* or bd_double_arrow */
10112-		case RGFW_mouseResizeNW:     cursorName = (char*)"top_left_corner"; break;
10113-		case RGFW_mouseResizeN:      cursorName = (char*)"top_side"; break;
10114-		case RGFW_mouseResizeNE:     cursorName = (char*)"top_right_corner"; break;
10115-		case RGFW_mouseResizeE:      cursorName = (char*)"right_side"; break;
10116-		case RGFW_mouseResizeSE:     cursorName = (char*)"bottom_right_corner"; break;
10117-		case RGFW_mouseResizeS:      cursorName = (char*)"bottom_side"; break;
10118-		case RGFW_mouseResizeSW:     cursorName = (char*)"bottom_left_corner"; break;
10119-		case RGFW_mouseResizeW:      cursorName = (char*)"left_side"; break;
10120-		case RGFW_mouseResizeAll:    cursorName = (char*)"fleur"; break;
10121-		case RGFW_mouseNotAllowed:   cursorName = (char*)"not-allowed"; break;
10122-		case RGFW_mouseWait:         cursorName = (char*)"watch"; break;
10123-		case RGFW_mouseProgress:     cursorName = (char*)"watch"; break;
10124-		default:                     return NULL;
10125-	}
10126-
10127-	struct wl_cursor* wlcursor = wl_cursor_theme_get_cursor(_RGFW->wl_cursor_theme, cursorName);
10128-	if (wlcursor == NULL)
10129-		return NULL;
10130-	struct wl_cursor_image* cursor_image = wlcursor->images[0];
10131-	struct wl_buffer* cursor_buffer = wl_cursor_image_get_buffer(cursor_image);
10132-
10133-	RGFW_surface* surface = RGFW_ALLOC(sizeof(RGFW_surface));
10134-	RGFW_MEMZERO(surface, sizeof(RGFW_surface));
10135-	surface->w = (i32)cursor_image->width;
10136-	surface->h = (i32)cursor_image->height;
10137-	surface->native.wl_buffer = cursor_buffer;
10138-
10139-	return (RGFW_mouse*)surface;
10140-}
10141-
10142-RGFW_mouse* RGFW_FUNC(RGFW_createMouse)(u8* data, i32 w, i32 h, RGFW_format format) {
10143-    RGFW_surface* surface = RGFW_createSurface(data, w, h, format);
10144-	if (surface == NULL) return NULL;
10145-
10146-	surface->native.wl_buffer = wl_shm_pool_create_buffer(surface->native.pool, 0, surface->w, surface->h, (i32)surface->w * 4, WL_SHM_FORMAT_ARGB8888);
10147-
10148-	RGFW_copyImageData(surface->native.buffer, RGFW_MIN(w, surface->w), RGFW_MIN(h, surface->h), surface->native.format, surface->data, surface->format, NULL);
10149-
10150-	return (RGFW_mouse*)surface;
10151-}
10152-
10153-RGFW_bool RGFW_FUNC(RGFW_window_setMousePlatform)(RGFW_window* win, RGFW_mouse* mouse) {
10154-	RGFW_ASSERT(win); RGFW_ASSERT(mouse);
10155-	RGFW_surface* surface = (RGFW_surface*)mouse;
10156-
10157-	win->src.using_custom_cursor = RGFW_TRUE;
10158-
10159-	wl_surface_attach(win->src.custom_cursor_surface, surface->native.wl_buffer, 0, 0);
10160-	wl_surface_damage(win->src.custom_cursor_surface, 0, 0, surface->w, surface->h);
10161-	wl_surface_commit(win->src.custom_cursor_surface);
10162-
10163-	return RGFW_TRUE;
10164-}
10165-
10166-void RGFW_FUNC(RGFW_freeMouse)(RGFW_mouse* mouse) {
10167-	if (mouse != NULL) {
10168-		RGFW_surface* surface = (RGFW_surface*)mouse;
10169-
10170-		if (surface->native.buffer && surface->native.wl_buffer) {
10171-			wl_buffer_destroy(surface->native.wl_buffer);
10172-		}
10173-
10174-		RGFW_surface_free(surface);
10175-	}
10176-}
10177-
10178-void RGFW_FUNC(RGFW_window_moveMouse)(RGFW_window* win, i32 x, i32 y) {
10179-	if (_RGFW->wp_pointer_warp != NULL) {
10180-		wp_pointer_warp_v1_warp_pointer(_RGFW->wp_pointer_warp, win->src.surface, _RGFW->wl_pointer, wl_fixed_from_int(x), wl_fixed_from_int(y), _RGFW->mouse_enter_serial);
10181-	}
10182-}
10183-
10184-void RGFW_FUNC(RGFW_window_hide) (RGFW_window* win) {
10185-	wl_surface_attach(win->src.surface, NULL, 0, 0);
10186-	wl_surface_commit(win->src.surface);
10187-	win->internal.flags |= RGFW_windowHide;
10188-}
10189-
10190-void RGFW_FUNC(RGFW_window_show) (RGFW_window* win) {
10191-	win->internal.flags &= ~(u32)RGFW_windowHide;
10192-	if (win->internal.flags & RGFW_windowFocusOnShow) RGFW_window_focus(win);
10193-	/* wl_surface_attach(win->src.surface, win->x, win->y, win->w, win->h, 0, 0); */
10194-	wl_surface_commit(win->src.surface);
10195-}
10196-
10197-void RGFW_FUNC(RGFW_window_flash) (RGFW_window* win, RGFW_flashRequest request) {
10198-	if (RGFW_window_isInFocus(win) && request) {
10199-		return;
10200-	}
10201-}
10202-
10203-RGFW_ssize_t RGFW_FUNC(RGFW_readClipboardPtr) (char* str, size_t strCapacity) {
10204-
10205-	RGFW_UNUSED(strCapacity);
10206-
10207-	if (str != NULL)
10208-		RGFW_STRNCPY(str, _RGFW->clipboard, _RGFW->clipboard_len - 1);
10209-	_RGFW->clipboard[_RGFW->clipboard_len - 1] = '\0';
10210-	return (RGFW_ssize_t)_RGFW->clipboard_len - 1;
10211-}
10212-
10213-void RGFW_FUNC(RGFW_writeClipboard) (const char* text, u32 textLen) {
10214-
10215-	// compositor does not support wl_data_device_manager
10216-	// clients cannot read rgfw's clipboard
10217-	if (_RGFW->data_device_manager == NULL) return;
10218-	// clear the clipboard
10219-	if (_RGFW->clipboard)
10220-		RGFW_FREE(_RGFW->clipboard);
10221-
10222-	// set the contents
10223-	_RGFW->clipboard = (char*)RGFW_ALLOC(textLen);
10224-	RGFW_ASSERT(_RGFW->clipboard != NULL);
10225-	RGFW_STRNCPY(_RGFW->clipboard, text, textLen - 1);
10226-	_RGFW->clipboard[textLen - 1] = '\0';
10227-	_RGFW->clipboard_len = textLen;
10228-
10229-	// means we already wrote to the clipboard
10230-	// so destroy it to create a new one
10231-	RGFW_window* win = _RGFW->kbOwner;
10232-
10233-	if (win->src.data_source != NULL) {
10234-		wl_data_source_destroy(win->src.data_source);
10235-		win->src.data_source = NULL;
10236-	}
10237-
10238-	// advertise to other clients that we offer text
10239-	win->src.data_source = wl_data_device_manager_create_data_source(_RGFW->data_device_manager);
10240-
10241-	// basic error checking
10242-	if (win->src.data_source == NULL) {
10243-		RGFW_debugCallback(RGFW_typeError, RGFW_errClipboard, "Could not create clipboard data source");
10244-		return;
10245-	}
10246-	wl_data_source_offer(win->src.data_source , "text/plain;charset=utf-8");
10247-
10248-	// needed RGFW_doNothing because wayland will call the functions
10249-	// if not set they are random data that lead to a crash
10250-	static const struct wl_data_source_listener data_source_listener = {
10251-		.target = (void (*)(void *, struct wl_data_source *, const char *))&RGFW_doNothing,
10252-		.action = (void (*)(void *, struct wl_data_source *, u32))&RGFW_doNothing,
10253-		.dnd_drop_performed = (void (*)(void *, struct wl_data_source *))&RGFW_doNothing,
10254-		.dnd_finished = (void (*)(void *, struct wl_data_source *))&RGFW_doNothing,
10255-		.send = RGFW_wl_data_source_send,
10256-		.cancelled = RGFW_wl_data_source_cancelled
10257-	};
10258-
10259-	wl_data_source_add_listener(win->src.data_source, &data_source_listener, _RGFW);
10260-
10261-}
10262-
10263-RGFW_bool RGFW_FUNC(RGFW_window_isHidden) (RGFW_window* win) {
10264-	RGFW_ASSERT(win != NULL);
10265-    return RGFW_FALSE;
10266-}
10267-
10268-RGFW_bool RGFW_FUNC(RGFW_window_isMinimized) (RGFW_window* win) {
10269-	RGFW_ASSERT(win != NULL);
10270-    return win->src.minimized;
10271-}
10272-
10273-RGFW_bool RGFW_FUNC(RGFW_window_isMaximized) (RGFW_window* win) {
10274-	RGFW_ASSERT(win != NULL);
10275-	return win->src.maximized;
10276-}
10277-
10278-void RGFW_FUNC(RGFW_pollMonitors) (void) {
10279-	_RGFW->monitors.primary = _RGFW->monitors.list.head;
10280-}
10281-
10282-
10283-RGFW_bool RGFW_FUNC(RGFW_monitor_getWorkarea) (RGFW_monitor* monitor, i32* x, i32* y, i32* width, i32* height) {
10284-	/* NOTE: Wayland has no way to get the actual workarea as far as I'm aware :( */
10285-	if (x) *x = monitor->x;
10286-	if (y) *y = monitor->y;
10287-	if (width) *width = monitor->mode.w;
10288-	if (height) *height = monitor->mode.h;
10289-	return RGFW_TRUE;
10290-}
10291-
10292-size_t RGFW_FUNC(RGFW_monitor_getModesPtr) (RGFW_monitor* monitor, RGFW_monitorMode** modes) {
10293-	if (modes) {
10294-		RGFW_MEMCPY((*modes), monitor->node->modes, monitor->node->modeCount * sizeof(RGFW_monitorMode));
10295-	}
10296-
10297-	return monitor->node->modeCount;
10298-}
10299-
10300-size_t RGFW_FUNC(RGFW_monitor_getGammaRampPtr) (RGFW_monitor* monitor, RGFW_gammaRamp* ramp) {
10301-	RGFW_UNUSED(monitor); RGFW_UNUSED(ramp);
10302-	return 0;
10303-}
10304-
10305-RGFW_bool RGFW_FUNC(RGFW_monitor_setGammaRamp) (RGFW_monitor* monitor, RGFW_gammaRamp* ramp) {
10306-	RGFW_UNUSED(monitor); RGFW_UNUSED(ramp);
10307-	return RGFW_FALSE;
10308-}
10309-
10310-RGFW_bool RGFW_FUNC(RGFW_monitor_requestMode) (RGFW_monitor* mon, RGFW_monitorMode* mode, RGFW_modeRequest request) {
10311-	for (size_t i = 0; i < mon->node->modeCount; i++) {
10312-		if (RGFW_monitorModeCompare(mode, &mon->node->modes[i], request) == RGFW_FALSE) {
10313-			continue;
10314-		}
10315-
10316-		RGFW_monitor_setMode(mon, &mon->node->modes[i]);
10317-		return RGFW_TRUE;
10318-	}
10319-
10320-	return RGFW_FALSE;
10321-}
10322-
10323-RGFW_bool RGFW_FUNC(RGFW_monitor_setMode) (RGFW_monitor* mon, RGFW_monitorMode* mode) {
10324-	RGFW_UNUSED(mon); RGFW_UNUSED(mode);
10325-	return RGFW_FALSE;
10326-}
10327-
10328-RGFW_monitor* RGFW_FUNC(RGFW_window_getMonitor) (RGFW_window* win) {
10329-	RGFW_ASSERT(win);
10330-	if (win->src.active_monitor == NULL) {
10331-		/* TODO: fix race condition [probably a problem with wayland] */
10332-		return RGFW_getPrimaryMonitor();
10333-	}
10334-
10335-	return &win->src.active_monitor->mon;
10336-}
10337-
10338-#ifdef RGFW_OPENGL
10339-RGFW_bool RGFW_FUNC(RGFW_extensionSupportedPlatform_OpenGL) (const char * extension, size_t len) { return RGFW_extensionSupportedPlatform_EGL(extension, len); }
10340-RGFW_proc RGFW_FUNC(RGFW_getProcAddress_OpenGL) (const char* procname) { return RGFW_getProcAddress_EGL(procname); }
10341-
10342-
10343-RGFW_bool RGFW_FUNC(RGFW_window_createContextPtr_OpenGL)(RGFW_window* win, RGFW_glContext* ctx, RGFW_glHints* hints) {
10344-	RGFW_bool out = RGFW_window_createContextPtr_EGL(win, &ctx->egl, hints);
10345-	win->src.gfxType = RGFW_gfxNativeOpenGL;
10346-
10347-	RGFW_window_swapInterval_OpenGL(win, 0);
10348-	return out;
10349-}
10350-void RGFW_FUNC(RGFW_window_deleteContextPtr_OpenGL) (RGFW_window* win, RGFW_glContext* ctx) { RGFW_window_deleteContextPtr_EGL(win, &ctx->egl); win->src.ctx.native = NULL; }
10351-
10352-void RGFW_FUNC(RGFW_window_makeCurrentContext_OpenGL) (RGFW_window* win) { RGFW_window_makeCurrentContext_EGL(win); }
10353-void* RGFW_FUNC(RGFW_getCurrentContext_OpenGL) (void) { return RGFW_getCurrentContext_EGL(); }
10354-void RGFW_FUNC(RGFW_window_swapBuffers_OpenGL) (RGFW_window* win) { RGFW_window_swapBuffers_EGL(win); }
10355-void RGFW_FUNC(RGFW_window_swapInterval_OpenGL) (RGFW_window* win, i32 swapInterval) { RGFW_window_swapInterval_EGL(win, swapInterval); }
10356-#endif /* RGFW_OPENGL */
10357-
10358-void RGFW_FUNC(RGFW_window_closePlatform)(RGFW_window* win) {
10359-	RGFW_ASSERT(win != NULL);
10360-	RGFW_debugCallback(RGFW_typeInfo, RGFW_infoWindow, "a window was freed");
10361-	#ifdef RGFW_LIBDECOR
10362-		if (win->src.decorContext)
10363-			libdecor_unref(win->src.decorContext);
10364-	#endif
10365-
10366-	if (win->src.decoration) {
10367-		zxdg_toplevel_decoration_v1_destroy(win->src.decoration);
10368-	}
10369-
10370-	if (win->src.xdg_toplevel) {
10371-		xdg_toplevel_destroy(win->src.xdg_toplevel);
10372-	}
10373-
10374-	wl_surface_destroy(win->src.custom_cursor_surface);
10375-
10376-	if (win->src.locked_pointer) {
10377-		zwp_locked_pointer_v1_destroy(win->src.locked_pointer);
10378-	}
10379-
10380-	if (win->src.icon) {
10381-		xdg_toplevel_icon_v1_destroy(win->src.icon);
10382-	}
10383-
10384-	xdg_surface_destroy(win->src.xdg_surface);
10385-	wl_surface_destroy(win->src.surface);
10386-}
10387-
10388-#ifdef RGFW_WEBGPU
10389-WGPUSurface RGFW_FUNC(RGFW_window_createSurface_WebGPU) (RGFW_window* window, WGPUInstance instance) {
10390-	WGPUSurfaceDescriptor surfaceDesc = {0};
10391-	WGPUSurfaceSourceWaylandSurface fromWl = {0};
10392-	fromWl.chain.sType = WGPUSType_SurfaceSourceWaylandSurface;
10393-	fromWl.display = _RGFW->wl_display;
10394-	fromWl.surface = window->src.surface;
10395-
10396-	surfaceDesc.nextInChain = (WGPUChainedStruct*)&fromWl.chain;
10397-	return wgpuInstanceCreateSurface(instance, &surfaceDesc);
10398-}
10399-#endif
10400-
10401-
10402-
10403-#endif /* RGFW_WAYLAND */
10404-/*
10405-	End of Wayland defines
10406-*/
10407-
10408-/*
10409-
10410-	Start of Windows defines
10411-
10412-
10413-*/
10414-
10415-#ifdef RGFW_WINDOWS
10416-#ifndef WIN32_LEAN_AND_MEAN
10417-	#define WIN32_LEAN_AND_MEAN
10418-#endif
10419-
10420-#ifndef OEMRESOURCE
10421-	#define OEMRESOURCE
10422-#endif
10423-
10424-#include <windows.h>
10425-
10426-#ifndef OCR_NORMAL
10427-#define OCR_NORMAL 32512
10428-#define OCR_IBEAM 32513
10429-#define OCR_WAIT 32514
10430-#define OCR_CROSS 32515
10431-#define OCR_UP 32516
10432-#define OCR_SIZENWSE 32642
10433-#define OCR_SIZENESW 32643
10434-#define OCR_SIZEWE 32644
10435-#define OCR_SIZENS 32645
10436-#define OCR_SIZEALL 32646
10437-#define OCR_NO 32648
10438-#define OCR_HAND 32649
10439-#define OCR_APPSTARTING 32650
10440-#endif
10441-
10442-#include <windowsx.h>
10443-#include <shellapi.h>
10444-#include <shellscalingapi.h>
10445-#include <wchar.h>
10446-#include <locale.h>
10447-#include <winuser.h>
10448-
10449-#ifndef WM_DPICHANGED
10450-#define WM_DPICHANGED       0x02E0
10451-#endif
10452-
10453-RGFWDEF DWORD RGFW_winapi_window_getStyle(RGFW_window* win, RGFW_windowFlags flags);
10454-DWORD RGFW_winapi_window_getStyle(RGFW_window* win, RGFW_windowFlags flags) {
10455-	RGFW_UNUSED(win);
10456-    DWORD style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
10457-
10458-    if ((flags & RGFW_windowFullscreen)) {
10459-        style |= WS_POPUP;
10460-    } else {
10461-        style |= WS_SYSMENU | WS_MINIMIZEBOX;
10462-
10463-        if (!(flags & RGFW_windowNoBorder)) {
10464-            style |= WS_CAPTION;
10465-
10466-            if (!(flags & RGFW_windowNoResize))
10467-                style |= WS_MAXIMIZEBOX | WS_THICKFRAME;
10468-        }
10469-        else
10470-            style |= WS_POPUP;
10471-    }
10472-
10473-    return style;
10474-}
10475-
10476-RGFWDEF DWORD RGFW_winapi_window_getExStyle(RGFW_window* win, RGFW_windowFlags flags);
10477-DWORD RGFW_winapi_window_getExStyle(RGFW_window* win, RGFW_windowFlags flags) {
10478-    DWORD style = WS_EX_APPWINDOW;
10479-    if (flags & RGFW_windowFullscreen || (flags & RGFW_windowFloating || RGFW_window_isFloating(win))) {
10480-        style |= WS_EX_TOPMOST;
10481-	}
10482-
10483-    return style;
10484-}
10485-
10486-RGFW_bool RGFW_createUTF8FromWideStringWin32(const WCHAR* source, char* out, size_t max);
10487-
10488-#define GL_FRONT				0x0404
10489-#define GL_BACK					0x0405
10490-#define GL_LEFT					0x0406
10491-#define GL_RIGHT				0x0407
10492-
10493-typedef int (*PFN_wglGetSwapIntervalEXT)(void);
10494-PFN_wglGetSwapIntervalEXT wglGetSwapIntervalEXTSrc = NULL;
10495-#define wglGetSwapIntervalEXT wglGetSwapIntervalEXTSrc
10496-
10497-/* these two wgl functions need to be preloaded */
10498-typedef HGLRC (WINAPI *PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC hdc, HGLRC hglrc, const int *attribList);
10499-PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL;
10500-
10501-HMODULE RGFW_wgl_dll = NULL;
10502-
10503-#ifndef RGFW_NO_LOAD_WGL
10504-	typedef HGLRC(WINAPI* PFN_wglCreateContext)(HDC);
10505-	typedef BOOL(WINAPI* PFN_wglDeleteContext)(HGLRC);
10506-	typedef PROC(WINAPI* PFN_wglGetProcAddress)(LPCSTR);
10507-	typedef BOOL(WINAPI* PFN_wglMakeCurrent)(HDC, HGLRC);
10508-	typedef HDC(WINAPI* PFN_wglGetCurrentDC)(void);
10509-	typedef HGLRC(WINAPI* PFN_wglGetCurrentContext)(void);
10510-	typedef BOOL(WINAPI* PFN_wglShareLists)(HGLRC, HGLRC);
10511-
10512-	PFN_wglCreateContext wglCreateContextSRC;
10513-	PFN_wglDeleteContext wglDeleteContextSRC;
10514-	PFN_wglGetProcAddress wglGetProcAddressSRC;
10515-	PFN_wglMakeCurrent wglMakeCurrentSRC;
10516-	PFN_wglGetCurrentDC wglGetCurrentDCSRC;
10517-	PFN_wglGetCurrentContext wglGetCurrentContextSRC;
10518-	PFN_wglShareLists wglShareListsSRC;
10519-
10520-	#define wglCreateContext wglCreateContextSRC
10521-	#define wglDeleteContext wglDeleteContextSRC
10522-	#define wglGetProcAddress wglGetProcAddressSRC
10523-	#define wglMakeCurrent wglMakeCurrentSRC
10524-	#define wglGetCurrentDC wglGetCurrentDCSRC
10525-	#define wglGetCurrentContext wglGetCurrentContextSRC
10526-	#define wglShareLists wglShareListsSRC
10527-#endif
10528-
10529-void* RGFW_window_getHWND(RGFW_window* win) { return win->src.window; }
10530-void* RGFW_window_getHDC(RGFW_window* win) { return win->src.hdc; }
10531-
10532-#ifdef RGFW_OPENGL
10533-RGFWDEF void RGFW_win32_loadOpenGLFuncs(HWND dummyWin);
10534-
10535-typedef HRESULT (APIENTRY* PFNWGLCHOOSEPIXELFORMATARBPROC)(HDC hdc, const int* piAttribIList, const FLOAT* pfAttribFList, UINT nMaxFormats, int* piFormats, UINT* nNumFormats);
10536-PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = NULL;
10537-
10538-typedef BOOL(APIENTRY* PFNWGLSWAPINTERVALEXTPROC)(int interval);
10539-PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = NULL;
10540-#endif
10541-
10542-#ifndef RGFW_NO_DWM
10543-HMODULE RGFW_dwm_dll = NULL;
10544-#ifndef _DWMAPI_H_
10545-typedef struct { DWORD dwFlags; int fEnable; HRGN hRgnBlur; int fTransitionOnMaximized;} DWM_BLURBEHIND;
10546-#endif
10547-typedef HRESULT (WINAPI * PFN_DwmEnableBlurBehindWindow)(HWND, const DWM_BLURBEHIND*);
10548-PFN_DwmEnableBlurBehindWindow DwmEnableBlurBehindWindowSRC = NULL;
10549-
10550-typedef HRESULT (WINAPI * PFN_DwmSetWindowAttribute)(HWND, DWORD, LPCVOID, DWORD);
10551-PFN_DwmSetWindowAttribute DwmSetWindowAttributeSRC = NULL;
10552-#endif
10553-void RGFW_win32_makeWindowTransparent(RGFW_window* win);
10554-void RGFW_win32_makeWindowTransparent(RGFW_window* win) {
10555-	if (!(win->internal.flags & RGFW_windowTransparent)) return;
10556-
10557-	#ifndef RGFW_NO_DWM
10558-	if (DwmEnableBlurBehindWindowSRC != NULL) {
10559-			DWM_BLURBEHIND bb = {0, 0, 0, 0};
10560-			bb.dwFlags = 0x1;
10561-			bb.fEnable = TRUE;
10562-			bb.hRgnBlur = NULL;
10563-			DwmEnableBlurBehindWindowSRC(win->src.window, &bb);
10564-
10565-	} else
10566-	#endif
10567-	{
10568-		SetWindowLong(win->src.window, GWL_EXSTYLE, WS_EX_LAYERED);
10569-		SetLayeredWindowAttributes(win->src.window, 0, 128,  LWA_ALPHA);
10570-	}
10571-}
10572-
10573-RGFWDEF RGFW_bool RGFW_win32_getDarkModeState(void);
10574-RGFW_bool RGFW_win32_getDarkModeState(void) {
10575-	u32 lightMode = 1;
10576-#if (_WIN32_WINNT >= 0x0600)
10577-	DWORD len = sizeof(lightMode);
10578-
10579-	RegGetValueW(
10580-		HKEY_CURRENT_USER,
10581-		L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize",
10582-		L"AppsUseLightTheme", RRF_RT_REG_DWORD, NULL, &lightMode, &len
10583-	);
10584-#endif
10585-
10586-	return (lightMode == 0);
10587-}
10588-
10589-RGFWDEF void RGFW_win32_makeWindowDarkMode(RGFW_window* win, RGFW_bool state);
10590-void RGFW_win32_makeWindowDarkMode(RGFW_window* win, RGFW_bool state) {
10591-	BOOL value = (state == RGFW_TRUE) ? TRUE : FALSE;
10592-	DwmSetWindowAttributeSRC(win->src.window, 20 /* DWMWA_USE_IMMERSIVE_DARK_MODE */, &value, sizeof(value));
10593-}
10594-
10595-LRESULT CALLBACK WndProcW(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
10596-LRESULT CALLBACK WndProcW(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
10597-    RGFW_window* win = (RGFW_window*)GetPropW(hWnd, L"RGFW");
10598-	if (win == NULL) return DefWindowProcW(hWnd, message, wParam, lParam);
10599-
10600-	static BYTE keyboardState[256];
10601-	GetKeyboardState(keyboardState);
10602-
10603-	RECT frame;
10604-	ZeroMemory(&frame, sizeof(frame));
10605-	DWORD style = RGFW_winapi_window_getStyle(win, win->internal.flags);
10606-	DWORD exStyle = RGFW_winapi_window_getExStyle(win, win->internal.flags);
10607-	AdjustWindowRectEx(&frame, style, FALSE, exStyle);
10608-
10609-	switch (message) {
10610-        case WM_DISPLAYCHANGE:
10611-            RGFW_pollMonitors();
10612-            break;
10613-		case WM_CLOSE:
10614-		case WM_QUIT:
10615-			RGFW_windowCloseCallback(win);
10616-			return 0;
10617-		case WM_ACTIVATE: {
10618-			RGFW_bool inFocus = RGFW_BOOL(LOWORD(wParam) != WA_INACTIVE);
10619-			RGFW_windowFocusCallback(win, inFocus);
10620-
10621-			return DefWindowProcW(hWnd, message, wParam, lParam);
10622-		}
10623-		case WM_MOVE:
10624-			if (win->internal.captureMouse) {
10625-				RGFW_window_captureMousePlatform(win, RGFW_TRUE);
10626-			}
10627-
10628-			RGFW_windowMovedCallback(win, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
10629-			return DefWindowProcW(hWnd, message, wParam, lParam);
10630-		case WM_SIZE: {
10631-			if (win->internal.captureMouse) {
10632-				RGFW_window_captureMousePlatform(win, RGFW_TRUE);
10633-			}
10634-
10635-			RGFW_windowResizedCallback(win, LOWORD(lParam), HIWORD(lParam));
10636-			RGFW_window_checkMode(win);
10637-			return DefWindowProcW(hWnd, message, wParam, lParam);
10638-		}
10639-        case WM_MOUSEACTIVATE:         {
10640-            if (HIWORD(lParam) == WM_LBUTTONDOWN) {
10641-                if (LOWORD(lParam) != HTCLIENT)
10642-                    win->src.actionFrame = RGFW_TRUE;
10643-            }
10644-
10645-            break;
10646-        }
10647-		case WM_CAPTURECHANGED:         {
10648-            if (lParam == 0 && win->src.actionFrame) {
10649-				RGFW_window_captureMousePlatform(win, win->internal.captureMouse);
10650-                win->src.actionFrame = RGFW_FALSE;
10651-            }
10652-
10653-            break;
10654-        }
10655-		#ifndef RGFW_NO_DPI
10656-		case WM_DPICHANGED: {
10657-			const float scaleX = HIWORD(wParam) / (float) 96;
10658-            const float scaleY = LOWORD(wParam) / (float) 96;
10659-
10660-			RGFW_scaleUpdatedCallback(win, scaleX, scaleY);
10661-			return DefWindowProcW(hWnd, message, wParam, lParam);
10662-		}
10663-		#endif
10664-		case WM_SIZING: {
10665-			if (win->src.aspectRatioW == 0 && win->src.aspectRatioH == 0) {
10666-				break;
10667-			}
10668-
10669-			RECT* area = (RECT*)lParam;
10670-			i32 edge = (i32)wParam;
10671-
10672-			double ratio = (double)win->src.aspectRatioW / (double) win->src.aspectRatioH;
10673-
10674-			if (edge == WMSZ_LEFT  || edge == WMSZ_BOTTOMLEFT || edge == WMSZ_RIGHT || edge == WMSZ_BOTTOMRIGHT) {
10675-				area->bottom = area->top + (frame.bottom - frame.top) + (i32) (((area->right - area->left) - (frame.right - frame.left)) / ratio);
10676-			} else if (edge == WMSZ_TOPLEFT || edge == WMSZ_TOPRIGHT) {
10677-				area->top = area->bottom - (frame.bottom - frame.top) - (i32) (((area->right - area->left) - (frame.right - frame.left)) / ratio);
10678-			} else if (edge == WMSZ_TOP || edge == WMSZ_BOTTOM) {
10679-				area->right = area->left + (frame.right - frame.left) + (i32) (((area->bottom - area->top) - (frame.bottom - frame.top)) * ratio);
10680-			}
10681-
10682-			return TRUE;
10683-		}
10684-		case WM_GETMINMAXINFO: {
10685-			MINMAXINFO* mmi = (MINMAXINFO*) lParam;
10686-			RGFW_bool resize = ((win->src.minSizeW == win->src.maxSizeW) && (win->src.minSizeH == win->src.maxSizeH));
10687-			RGFW_setBit(&win->internal.flags, RGFW_windowNoResize, resize);
10688-
10689-			mmi->ptMinTrackSize.x = (LONG)(win->src.minSizeW + (frame.right - frame.left));
10690-			mmi->ptMinTrackSize.y = (LONG)(win->src.minSizeH + (frame.bottom - frame.top));
10691-			if (win->src.maxSizeW == 0 && win->src.maxSizeH == 0)
10692-				return DefWindowProcW(hWnd, message, wParam, lParam);
10693-
10694-			mmi->ptMaxTrackSize.x = (LONG)(win->src.maxSizeW + (frame.right - frame.left));
10695-			mmi->ptMaxTrackSize.y = (LONG)(win->src.maxSizeH + (frame.bottom - frame.top));
10696-			return DefWindowProcW(hWnd, message, wParam, lParam);
10697-		}
10698-		case WM_PAINT: {
10699-            PAINTSTRUCT ps;
10700-            BeginPaint(hWnd, &ps);
10701-            RGFW_windowRefreshCallback(win, 0, 0, win->w, win->h);
10702-            EndPaint(hWnd, &ps);
10703-
10704-            return DefWindowProcW(hWnd, message, wParam, lParam);
10705-		}
10706-		#if(_WIN32_WINNT >= 0x0600)
10707-		case WM_DWMCOMPOSITIONCHANGED:
10708-		case WM_DWMCOLORIZATIONCOLORCHANGED:
10709-			RGFW_win32_makeWindowTransparent(win);
10710-			break;
10711-		#endif
10712-
10713-		case WM_ENTERSIZEMOVE: {
10714-			if (win->src.actionFrame)
10715-				RGFW_window_captureMousePlatform(win, win->internal.captureMouse);
10716-
10717-			#ifdef RGFW_ADVANCED_SMOOTH_RESIZE
10718-				SetTimer(win->src.window, 1, USER_TIMER_MINIMUM, NULL); break;
10719-			#endif
10720-			break;
10721-		}
10722-        case WM_EXITSIZEMOVE: {
10723-			if (win->src.actionFrame)
10724-				RGFW_window_captureMousePlatform(win, win->internal.captureMouse);
10725-
10726-			#ifdef RGFW_ADVANCED_SMOOTH_RESIZE
10727-				KillTimer(win->src.window, 1); break;
10728-			#endif
10729-			break;
10730-		}
10731-        case WM_TIMER:
10732-			RGFW_windowRefreshCallback(win, 0, 0, win->w, win->h);
10733-			break;
10734-
10735-		case WM_NCLBUTTONDOWN: {
10736-            /* workaround for half-second pause when starting to move window
10737-                see: https://gamedev.net/forums/topic/672094-keeping-things-moving-during-win32-moveresize-events/5254386/
10738-            */
10739-            POINT point = { 0, 0 };
10740-            if (SendMessage(win->src.window, WM_NCHITTEST, wParam, lParam) != HTCAPTION || GetCursorPos(&point) == FALSE)
10741-                break;
10742-
10743-            ScreenToClient(win->src.window, &point);
10744-            PostMessage(win->src.window, WM_MOUSEMOVE, 0, (u32)(point.x)|((u32)(point.y) << 16));
10745-            break;
10746-        }
10747-		case WM_MOUSELEAVE:
10748-			RGFW_mouseNotifyCallback(win, win->internal.lastMouseX, win->internal.lastMouseY, RGFW_FALSE);
10749-			break;
10750-
10751-        case WM_CHAR:
10752-        case WM_SYSCHAR: {
10753-            if (wParam >= 0xd800 && wParam <= 0xdbff)
10754-                win->src.highSurrogate = (WCHAR) wParam;
10755-            else {
10756-                u32 codepoint = 0;
10757-
10758-                if (wParam >= 0xdc00 && wParam <= 0xdfff) {
10759-                    if (win->src.highSurrogate) {
10760-                        codepoint += (u32)((win->src.highSurrogate - 0xd800) << 10);
10761-                        codepoint += (u32)((WCHAR) wParam - 0xdc00);
10762-                        codepoint += 0x10000;
10763-                    }
10764-                }
10765-                else
10766-                    codepoint = (WCHAR) wParam;
10767-
10768-                win->src.highSurrogate = 0;
10769-				RGFW_keyCharCallback(win, (u32)codepoint);
10770-            }
10771-
10772-            return 0;
10773-        }
10774-
10775-        case WM_UNICHAR: {
10776-            if (wParam == UNICODE_NOCHAR) {
10777-                return TRUE;
10778-            }
10779-
10780-			RGFW_keyCharCallback(win, (u32)wParam);
10781-            return 0;
10782-        }
10783-		case WM_SYSKEYUP: case WM_KEYUP: {
10784-			if (!(win->internal.enabledEvents & RGFW_keyReleasedFlag)) return DefWindowProcW(hWnd, message, wParam, lParam);
10785-			i32 scancode = (HIWORD(lParam) & (KF_EXTENDED | 0xff));
10786-			if (scancode == 0)
10787-				scancode = (i32)MapVirtualKeyW((UINT)wParam, MAPVK_VK_TO_VSC);
10788-
10789-			switch (scancode) {
10790-				case 0x54: scancode = 0x137; break; /*  Alt+PrtS */
10791-				case 0x146: scancode = 0x45; break; /* Ctrl+Pause */
10792-				case 0x136: scancode = 0x36; break; /*  CJK IME sets the extended bit for right Shift */
10793-				default: break;
10794-			}
10795-
10796-			RGFW_key value = (u8)RGFW_apiKeyToRGFW((u32) scancode);
10797-
10798-			if (wParam == VK_CONTROL) {
10799-				if (HIWORD(lParam) & KF_EXTENDED)
10800-					value = RGFW_keyControlR;
10801-				else value = RGFW_keyControlL;
10802-			}
10803-
10804-			RGFW_keyUpdateKeyMods(win, (GetKeyState(VK_CAPITAL) & 0x0001), (GetKeyState(VK_NUMLOCK) & 0x0001), (GetKeyState(VK_SCROLL) & 0x0001));
10805-			RGFW_keyCallback(win, value, win->internal.mod, RGFW_FALSE, RGFW_FALSE);
10806-			break;
10807-		}
10808-		case WM_SYSKEYDOWN: case WM_KEYDOWN: {
10809-			if (!(win->internal.enabledEvents & RGFW_keyPressedFlag)) return DefWindowProcW(hWnd, message, wParam, lParam);
10810-            i32 scancode = (HIWORD(lParam) & (KF_EXTENDED | 0xff));
10811-			if (scancode == 0)
10812-				scancode = (i32)MapVirtualKeyW((u32)wParam, MAPVK_VK_TO_VSC);
10813-
10814-			switch (scancode) {
10815-				case 0x54: scancode = 0x137; break; /*  Alt+PrtS */
10816-				case 0x146: scancode = 0x45; break; /* Ctrl+Pause */
10817-				case 0x136: scancode = 0x36; break; /*  CJK IME sets the extended bit for right Shift */
10818-				default: break;
10819-			}
10820-
10821-			RGFW_key value = (u8)RGFW_apiKeyToRGFW((u32) scancode);
10822-			if (wParam == VK_CONTROL) {
10823-				if (HIWORD(lParam) & KF_EXTENDED)
10824-					value = RGFW_keyControlR;
10825-				else value = RGFW_keyControlL;
10826-			}
10827-
10828-			RGFW_bool repeat = RGFW_isKeyDown(value);
10829-
10830-			RGFW_keyUpdateKeyMods(win, (GetKeyState(VK_CAPITAL) & 0x0001), (GetKeyState(VK_NUMLOCK) & 0x0001), (GetKeyState(VK_SCROLL) & 0x0001));
10831-			RGFW_keyCallback(win, value, win->internal.mod, repeat, 1);
10832-			break;
10833-		}
10834-		case WM_MOUSEMOVE: {
10835-			if (win->internal.mouseInside == RGFW_FALSE) {
10836-				RGFW_mouseNotifyCallback(win, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), RGFW_TRUE);
10837-			}
10838-
10839-			RGFW_mousePosCallback(win, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
10840-			break;
10841-		}
10842-		case WM_INPUT: {
10843-			if (!(win->internal.rawMouse || _RGFW->rawMouse)) return DefWindowProcW(hWnd, message, wParam, lParam);
10844-			unsigned size = sizeof(RAWINPUT);
10845-			static RAWINPUT raw;
10846-
10847-			GetRawInputData((HRAWINPUT)lParam, RID_INPUT, &raw, &size, sizeof(RAWINPUTHEADER));
10848-
10849-			if (raw.header.dwType != RIM_TYPEMOUSE || (raw.data.mouse.lLastX == 0 && raw.data.mouse.lLastY == 0) )
10850-				break;
10851-
10852-			float vecX = 0.0f;
10853-			float vecY = 0.0f;
10854-
10855-			if (raw.data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE) {
10856-				POINT pos = {0, 0};
10857-				int width, height;
10858-
10859-				if (raw.data.mouse.usFlags & MOUSE_VIRTUAL_DESKTOP) {
10860-					pos.x += GetSystemMetrics(SM_XVIRTUALSCREEN);
10861-					pos.y += GetSystemMetrics(SM_YVIRTUALSCREEN);
10862-					width = GetSystemMetrics(SM_CXVIRTUALSCREEN);
10863-					height = GetSystemMetrics(SM_CYVIRTUALSCREEN);
10864-				}
10865-				else {
10866-					width = GetSystemMetrics(SM_CXSCREEN);
10867-					height = GetSystemMetrics(SM_CYSCREEN);
10868-				}
10869-
10870-				pos.x += (int) (((float)raw.data.mouse.lLastX / 65535.f) * (float)width);
10871-				pos.y += (int) (((float)raw.data.mouse.lLastY / 65535.f) * (float)height);
10872-				ScreenToClient(win->src.window, &pos);
10873-
10874-				vecX = (float)(pos.x - win->internal.lastMouseX);
10875-				vecY = (float)(pos.y - win->internal.lastMouseY);
10876-			} else {
10877-				vecX = (float)(raw.data.mouse.lLastX);
10878-				vecY = (float)(raw.data.mouse.lLastY);
10879-			}
10880-
10881-			RGFW_rawMotionCallback(win, vecX, vecY);
10882-			break;
10883-		}
10884-		case WM_LBUTTONDOWN: case WM_RBUTTONDOWN: case WM_MBUTTONDOWN: case WM_XBUTTONDOWN: {
10885-			RGFW_mouseButton value = 0;
10886-			if (message == WM_XBUTTONDOWN)
10887-				value = RGFW_mouseMisc1 + (GET_XBUTTON_WPARAM(wParam) == XBUTTON2);
10888-			else value = (message == WM_LBUTTONDOWN) ? (u8)RGFW_mouseLeft :
10889-									 (message == WM_RBUTTONDOWN) ? (u8)RGFW_mouseRight : (u8)RGFW_mouseMiddle;
10890-
10891-			RGFW_mouseButtonCallback(win, value, 1);
10892-			break;
10893-		}
10894-		case WM_LBUTTONUP: case WM_RBUTTONUP: case WM_MBUTTONUP: case WM_XBUTTONUP: {
10895-			RGFW_mouseButton value = 0;
10896-			if (message == WM_XBUTTONUP)
10897-				value = RGFW_mouseMisc1 + (GET_XBUTTON_WPARAM(wParam) == XBUTTON2);
10898-			else value = (message == WM_LBUTTONUP) ? (u8)RGFW_mouseLeft :
10899-									 (message == WM_RBUTTONUP) ? (u8)RGFW_mouseRight : (u8)RGFW_mouseMiddle;
10900-
10901-			RGFW_mouseButtonCallback(win, value, 0);
10902-			break;
10903-		}
10904-		case WM_MOUSEWHEEL: {
10905-			float scrollY = (float)((i16) HIWORD(wParam) / (double) WHEEL_DELTA);
10906-			RGFW_mouseScrollCallback(win, 0.0f, scrollY);
10907-			break;
10908-		}
10909-		case 0x020E: {/* WM_MOUSEHWHEEL */
10910-			float scrollX = -(float)((i16) HIWORD(wParam) / (double) WHEEL_DELTA);
10911-			RGFW_mouseScrollCallback(win, scrollX, 0.0f);
10912-			break;
10913-		}
10914-		case WM_DROPFILES: {
10915-			HDROP drop = (HDROP) wParam;
10916-			POINT pt;
10917-
10918-			/* Move the mouse to the position of the drop */
10919-			DragQueryPoint(drop, &pt);
10920-			RGFW_dataDragCallback(win, RGFW_dataFile, RGFW_dndActionMove, pt.x, pt.y);
10921-
10922-			if (!(win->internal.enabledEvents & RGFW_dataDrop)) return DefWindowProcW(hWnd, message, wParam, lParam);
10923-			size_t count = DragQueryFileW(drop, 0xffffffff, NULL, 0);
10924-
10925-			u32 i;
10926-			for (i = 0; i < count; i++) {
10927-				UINT length = DragQueryFileW(drop, i, NULL, 0);
10928-				if (length == 0)
10929-					continue;
10930-
10931-				WCHAR* buffer = (WCHAR*)RGFW_ALLOC(sizeof(WCHAR) * (length + 1));
10932-				char* cbuffer = (char*)RGFW_ALLOC(length + 1);
10933-
10934-				DragQueryFileW(drop, i, buffer, length + 1);
10935-
10936-				RGFW_createUTF8FromWideStringWin32(buffer, cbuffer, length);
10937-
10938-				RGFW_dataDropCallback(win, cbuffer, length + 1, RGFW_dataFile);
10939-				RGFW_FREE(buffer);
10940-				RGFW_FREE(cbuffer);
10941-			}
10942-
10943-			DragFinish(drop);
10944-
10945-			break;
10946-		}
10947-		default: break;
10948-	}
10949-
10950-	return DefWindowProcW(hWnd, message, wParam, lParam);
10951-}
10952-
10953-#ifndef RGFW_NO_DPI
10954-	HMODULE RGFW_Shcore_dll = NULL;
10955-	typedef HRESULT (WINAPI *PFN_GetDpiForMonitor)(HMONITOR,MONITOR_DPI_TYPE,UINT*,UINT*);
10956-	PFN_GetDpiForMonitor GetDpiForMonitorSRC = NULL;
10957-	#define GetDpiForMonitor GetDpiForMonitorSRC
10958-#endif
10959-
10960-#if !defined(RGFW_NO_LOAD_WINMM) && !defined(RGFW_NO_WINMM)
10961-	HMODULE RGFW_winmm_dll = NULL;
10962-	typedef u32 (WINAPI * PFN_timeBeginPeriod)(u32);
10963-	typedef PFN_timeBeginPeriod PFN_timeEndPeriod;
10964-	PFN_timeBeginPeriod timeBeginPeriodSRC, timeEndPeriodSRC;
10965-	#define timeBeginPeriod timeBeginPeriodSRC
10966-	#define timeEndPeriod timeEndPeriodSRC
10967-#elif !defined(RGFW_NO_WINMM)
10968-	__declspec(dllimport) u32 __stdcall timeBeginPeriod(u32 uPeriod);
10969-	__declspec(dllimport) u32 __stdcall timeEndPeriod(u32 uPeriod);
10970-#endif
10971-#define RGFW_PROC_DEF(proc, name) if (name##SRC == NULL && proc != NULL) { \
10972-                                        name##SRC = (PFN_##name)(RGFW_proc)GetProcAddress((proc), (#name)); \
10973-                                        RGFW_ASSERT(name##SRC != NULL); \
10974-                                    }
10975-
10976-RGFW_format RGFW_nativeFormat(void) { return RGFW_formatBGRA8; }
10977-
10978-RGFW_bool RGFW_createSurfacePtr(u8* data, i32 w, i32 h, RGFW_format format, RGFW_surface* surface) {
10979-	RGFW_ASSERT(surface != NULL);
10980-	surface->data = data;
10981-	surface->w = w;
10982-	surface->h = h;
10983-	surface->format = format;
10984-
10985-	BITMAPV5HEADER bi;
10986-	ZeroMemory(&bi, sizeof(bi));
10987-	bi.bV5Size = sizeof(bi);
10988-	bi.bV5Width = (i32)w;
10989-	bi.bV5Height = -((LONG) h);
10990-	bi.bV5Planes = 1;
10991-	bi.bV5BitCount = (format >= RGFW_formatRGBA8) ? 32 : 24;
10992-	bi.bV5Compression = BI_RGB;
10993-
10994-	surface->native.bitmap = CreateDIBSection(_RGFW->root->src.hdc,
10995-		(BITMAPINFO*) &bi, DIB_RGB_COLORS,
10996-		(void**) &surface->native.bitmapBits,
10997-		NULL, (DWORD) 0);
10998-
10999-	surface->native.format = (format >= RGFW_formatRGBA8) ? (RGFW_format) RGFW_formatBGRA8 : (RGFW_format) RGFW_formatBGR8;
11000-
11001-	if (surface->native.bitmap == NULL) {
11002-		RGFW_debugCallback(RGFW_typeError, RGFW_errBuffer,  "Failed to create DIB section.");
11003-		return RGFW_FALSE;
11004-	}
11005-
11006-	surface->native.hdcMem = CreateCompatibleDC(_RGFW->root->src.hdc);
11007-	SelectObject(surface->native.hdcMem, surface->native.bitmap);
11008-
11009-	return RGFW_TRUE;
11010-}
11011-
11012-void RGFW_surface_freePtr(RGFW_surface* surface) {
11013-	RGFW_ASSERT(surface != NULL);
11014-
11015-	DeleteDC(surface->native.hdcMem);
11016-	DeleteObject(surface->native.bitmap);
11017-}
11018-
11019-void RGFW_window_blitSurface(RGFW_window* win, RGFW_surface* surface) {
11020-	RGFW_copyImageData(surface->native.bitmapBits, surface->w, RGFW_MIN(win->h, surface->h), surface->native.format, surface->data, surface->format, surface->convertFunc);
11021-	BitBlt(win->src.hdc, 0, 0, RGFW_MIN(win->w, surface->w), RGFW_MIN(win->h, surface->h), surface->native.hdcMem, 0, 0, SRCCOPY);
11022-}
11023-
11024-void RGFW_window_setRawMouseModePlatform(RGFW_window* win, RGFW_bool state) {
11025-	RGFW_UNUSED(win);
11026-	RAWINPUTDEVICE id = { 0x01, 0x02, 0, win->src.window };
11027-	id.dwFlags = (state == RGFW_TRUE) ? 0 : RIDEV_REMOVE;
11028-
11029-	RegisterRawInputDevices(&id, 1, sizeof(id));
11030-}
11031-
11032-void RGFW_window_captureMousePlatform(RGFW_window* win, RGFW_bool state) {
11033-	if (state == RGFW_FALSE) {
11034-		ClipCursor(NULL);
11035-		return;
11036-	}
11037-
11038-	RECT clipRect;
11039-	GetClientRect(win->src.window, &clipRect);
11040-	ClientToScreen(win->src.window, (POINT*) &clipRect.left);
11041-	ClientToScreen(win->src.window, (POINT*) &clipRect.right);
11042-	ClipCursor(&clipRect);
11043-}
11044-
11045-#define RGFW_LOAD_LIBRARY(x, lib) if (x == NULL) { x = LoadLibraryA(lib); RGFW_ASSERT(x != NULL); }
11046-
11047-#ifdef RGFW_DIRECTX
11048-int RGFW_window_createSwapChain_DirectX(RGFW_window* win, IDXGIFactory* pFactory, IUnknown* pDevice, IDXGISwapChain** swapchain) {
11049-    RGFW_ASSERT(win && pFactory && pDevice && swapchain);
11050-
11051-    static DXGI_SWAP_CHAIN_DESC swapChainDesc;
11052-	RGFW_MEMZERO(&swapChainDesc, sizeof(swapChainDesc));
11053-    swapChainDesc.BufferCount = 2;
11054-    swapChainDesc.BufferDesc.Width = win->w;
11055-    swapChainDesc.BufferDesc.Height = win->h;
11056-    swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
11057-    swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
11058-    swapChainDesc.OutputWindow = (HWND)win->src.window;
11059-    swapChainDesc.SampleDesc.Count = 1;
11060-    swapChainDesc.SampleDesc.Quality = 0;
11061-    swapChainDesc.Windowed = TRUE;
11062-    swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
11063-
11064-    HRESULT hr = pFactory->lpVtbl->CreateSwapChain(pFactory, (IUnknown*)pDevice, &swapChainDesc, swapchain);
11065-    if (FAILED(hr)) {
11066-        RGFW_debugCallback(RGFW_typeError, RGFW_errDirectXContext,  "Failed to create DirectX swap chain!");
11067-        return -2;
11068-    }
11069-
11070-    return 0;
11071-}
11072-#endif
11073-
11074-/* we're doing it with magic numbers because some keys are missing  */
11075-void RGFW_initKeycodesPlatform(void) {
11076-	_RGFW->keycodes[0x00B] = RGFW_key0;
11077-	_RGFW->keycodes[0x002] = RGFW_key1;
11078-	_RGFW->keycodes[0x003] = RGFW_key2;
11079-	_RGFW->keycodes[0x004] = RGFW_key3;
11080-	_RGFW->keycodes[0x005] = RGFW_key4;
11081-	_RGFW->keycodes[0x006] = RGFW_key5;
11082-	_RGFW->keycodes[0x007] = RGFW_key6;
11083-	_RGFW->keycodes[0x008] = RGFW_key7;
11084-	_RGFW->keycodes[0x009] = RGFW_key8;
11085-	_RGFW->keycodes[0x00A] = RGFW_key9;
11086-	_RGFW->keycodes[0x01E] = RGFW_keyA;
11087-	_RGFW->keycodes[0x030] = RGFW_keyB;
11088-	_RGFW->keycodes[0x02E] = RGFW_keyC;
11089-	_RGFW->keycodes[0x020] = RGFW_keyD;
11090-	_RGFW->keycodes[0x012] = RGFW_keyE;
11091-	_RGFW->keycodes[0x021] = RGFW_keyF;
11092-	_RGFW->keycodes[0x022] = RGFW_keyG;
11093-	_RGFW->keycodes[0x023] = RGFW_keyH;
11094-	_RGFW->keycodes[0x017] = RGFW_keyI;
11095-	_RGFW->keycodes[0x024] = RGFW_keyJ;
11096-	_RGFW->keycodes[0x025] = RGFW_keyK;
11097-	_RGFW->keycodes[0x026] = RGFW_keyL;
11098-	_RGFW->keycodes[0x032] = RGFW_keyM;
11099-	_RGFW->keycodes[0x031] = RGFW_keyN;
11100-	_RGFW->keycodes[0x018] = RGFW_keyO;
11101-	_RGFW->keycodes[0x019] = RGFW_keyP;
11102-	_RGFW->keycodes[0x010] = RGFW_keyQ;
11103-	_RGFW->keycodes[0x013] = RGFW_keyR;
11104-	_RGFW->keycodes[0x01F] = RGFW_keyS;
11105-	_RGFW->keycodes[0x014] = RGFW_keyT;
11106-	_RGFW->keycodes[0x016] = RGFW_keyU;
11107-	_RGFW->keycodes[0x02F] = RGFW_keyV;
11108-	_RGFW->keycodes[0x011] = RGFW_keyW;
11109-	_RGFW->keycodes[0x02D] = RGFW_keyX;
11110-	_RGFW->keycodes[0x015] = RGFW_keyY;
11111-	_RGFW->keycodes[0x02C] = RGFW_keyZ;
11112-	_RGFW->keycodes[0x028] = RGFW_keyApostrophe;
11113-	_RGFW->keycodes[0x02B] = RGFW_keyBackSlash;
11114-	_RGFW->keycodes[0x033] = RGFW_keyComma;
11115-	_RGFW->keycodes[0x00D] = RGFW_keyEquals;
11116-	_RGFW->keycodes[0x029] = RGFW_keyBacktick;
11117-	_RGFW->keycodes[0x01A] = RGFW_keyBracket;
11118-	_RGFW->keycodes[0x00C] = RGFW_keyMinus;
11119-	_RGFW->keycodes[0x034] = RGFW_keyPeriod;
11120-	_RGFW->keycodes[0x01B] = RGFW_keyCloseBracket;
11121-	_RGFW->keycodes[0x027] = RGFW_keySemicolon;
11122-	_RGFW->keycodes[0x035] = RGFW_keySlash;
11123-	_RGFW->keycodes[0x056] = RGFW_keyWorld2;
11124-	_RGFW->keycodes[0x00E] = RGFW_keyBackSpace;
11125-	_RGFW->keycodes[0x153] = RGFW_keyDelete;
11126-	_RGFW->keycodes[0x14F] = RGFW_keyEnd;
11127-	_RGFW->keycodes[0x01C] = RGFW_keyEnter;
11128-	_RGFW->keycodes[0x001] = RGFW_keyEscape;
11129-	_RGFW->keycodes[0x147] = RGFW_keyHome;
11130-	_RGFW->keycodes[0x152] = RGFW_keyInsert;
11131-	_RGFW->keycodes[0x15D] = RGFW_keyMenu;
11132-	_RGFW->keycodes[0x151] = RGFW_keyPageDown;
11133-	_RGFW->keycodes[0x149] = RGFW_keyPageUp;
11134-	_RGFW->keycodes[0x045] = RGFW_keyPause;
11135-	_RGFW->keycodes[0x039] = RGFW_keySpace;
11136-	_RGFW->keycodes[0x00F] = RGFW_keyTab;
11137-	_RGFW->keycodes[0x03A] = RGFW_keyCapsLock;
11138-	_RGFW->keycodes[0x145] = RGFW_keyNumLock;
11139-	_RGFW->keycodes[0x046] = RGFW_keyScrollLock;
11140-	_RGFW->keycodes[0x03B] = RGFW_keyF1;
11141-	_RGFW->keycodes[0x03C] = RGFW_keyF2;
11142-	_RGFW->keycodes[0x03D] = RGFW_keyF3;
11143-	_RGFW->keycodes[0x03E] = RGFW_keyF4;
11144-	_RGFW->keycodes[0x03F] = RGFW_keyF5;
11145-	_RGFW->keycodes[0x040] = RGFW_keyF6;
11146-	_RGFW->keycodes[0x041] = RGFW_keyF7;
11147-	_RGFW->keycodes[0x042] = RGFW_keyF8;
11148-	_RGFW->keycodes[0x043] = RGFW_keyF9;
11149-	_RGFW->keycodes[0x044] = RGFW_keyF10;
11150-	_RGFW->keycodes[0x057] = RGFW_keyF11;
11151-	_RGFW->keycodes[0x058] = RGFW_keyF12;
11152-	_RGFW->keycodes[0x064] = RGFW_keyF13;
11153-	_RGFW->keycodes[0x065] = RGFW_keyF14;
11154-	_RGFW->keycodes[0x066] = RGFW_keyF15;
11155-	_RGFW->keycodes[0x067] = RGFW_keyF16;
11156-	_RGFW->keycodes[0x068] = RGFW_keyF17;
11157-	_RGFW->keycodes[0x069] = RGFW_keyF18;
11158-	_RGFW->keycodes[0x06A] = RGFW_keyF19;
11159-	_RGFW->keycodes[0x06B] = RGFW_keyF20;
11160-	_RGFW->keycodes[0x06C] = RGFW_keyF21;
11161-	_RGFW->keycodes[0x06D] = RGFW_keyF22;
11162-	_RGFW->keycodes[0x06E] = RGFW_keyF23;
11163-	_RGFW->keycodes[0x076] = RGFW_keyF24;
11164-	_RGFW->keycodes[0x038] = RGFW_keyAltL;
11165-	_RGFW->keycodes[0x01D] = RGFW_keyControlL;
11166-	_RGFW->keycodes[0x02A] = RGFW_keyShiftL;
11167-	_RGFW->keycodes[0x15B] = RGFW_keySuperL;
11168-	_RGFW->keycodes[0x137] = RGFW_keyPrintScreen;
11169-	_RGFW->keycodes[0x138] = RGFW_keyAltR;
11170-	_RGFW->keycodes[0x11D] = RGFW_keyControlR;
11171-	_RGFW->keycodes[0x036] = RGFW_keyShiftR;
11172-	_RGFW->keycodes[0x15C] = RGFW_keySuperR;
11173-	_RGFW->keycodes[0x150] = RGFW_keyDown;
11174-	_RGFW->keycodes[0x14B] = RGFW_keyLeft;
11175-	_RGFW->keycodes[0x14D] = RGFW_keyRight;
11176-	_RGFW->keycodes[0x148] = RGFW_keyUp;
11177-	_RGFW->keycodes[0x052] = RGFW_keyPad0;
11178-	_RGFW->keycodes[0x04F] = RGFW_keyPad1;
11179-	_RGFW->keycodes[0x050] = RGFW_keyPad2;
11180-	_RGFW->keycodes[0x051] = RGFW_keyPad3;
11181-	_RGFW->keycodes[0x04B] = RGFW_keyPad4;
11182-	_RGFW->keycodes[0x04C] = RGFW_keyPad5;
11183-	_RGFW->keycodes[0x04D] = RGFW_keyPad6;
11184-	_RGFW->keycodes[0x047] = RGFW_keyPad7;
11185-	_RGFW->keycodes[0x048] = RGFW_keyPad8;
11186-	_RGFW->keycodes[0x049] = RGFW_keyPad9;
11187-	_RGFW->keycodes[0x04E] = RGFW_keyPadPlus;
11188-	_RGFW->keycodes[0x053] = RGFW_keyPadPeriod;
11189-	_RGFW->keycodes[0x135] = RGFW_keyPadSlash;
11190-	_RGFW->keycodes[0x11C] = RGFW_keyPadReturn;
11191-	_RGFW->keycodes[0x059] = RGFW_keyPadEqual;
11192-	_RGFW->keycodes[0x037] = RGFW_keyPadMultiply;
11193-	_RGFW->keycodes[0x04A] = RGFW_keyPadMinus;
11194-}
11195-
11196-
11197-i32 RGFW_initPlatform(void) {
11198-#ifndef RGFW_NO_DPI
11199-	#if (_WIN32_WINNT >= 0x0600)
11200-		SetProcessDPIAware();
11201-	#endif
11202-#endif
11203-
11204-	#ifndef RGFW_NO_WINMM
11205-		#ifndef RGFW_NO_LOAD_WINMM
11206-			RGFW_LOAD_LIBRARY(RGFW_winmm_dll, "winmm.dll");
11207-			RGFW_PROC_DEF(RGFW_winmm_dll, timeBeginPeriod);
11208-			RGFW_PROC_DEF(RGFW_winmm_dll, timeEndPeriod);
11209-		#endif
11210-		timeBeginPeriod(1);
11211-	#endif
11212-
11213-	#ifndef RGFW_NO_DWM
11214-	RGFW_LOAD_LIBRARY(RGFW_dwm_dll, "dwmapi.dll");
11215-	RGFW_PROC_DEF(RGFW_dwm_dll, DwmEnableBlurBehindWindow);
11216-	RGFW_PROC_DEF(RGFW_dwm_dll, DwmSetWindowAttribute);
11217-	#endif
11218-
11219-	RGFW_LOAD_LIBRARY(RGFW_wgl_dll, "opengl32.dll");
11220-	#ifndef RGFW_NO_LOAD_WGL
11221-		RGFW_PROC_DEF(RGFW_wgl_dll, wglCreateContext);
11222-		RGFW_PROC_DEF(RGFW_wgl_dll, wglDeleteContext);
11223-		RGFW_PROC_DEF(RGFW_wgl_dll, wglGetProcAddress);
11224-		RGFW_PROC_DEF(RGFW_wgl_dll, wglMakeCurrent);
11225-		RGFW_PROC_DEF(RGFW_wgl_dll, wglGetCurrentDC);
11226-		RGFW_PROC_DEF(RGFW_wgl_dll, wglGetCurrentContext);
11227-		RGFW_PROC_DEF(RGFW_wgl_dll, wglShareLists);
11228-	#endif
11229-
11230-	u8 RGFW_blk[] = { 0, 0, 0, 0 };
11231-	_RGFW->hiddenMouse = RGFW_createMouse(RGFW_blk, 1, 1, RGFW_formatRGBA8);
11232-    return 1;
11233-}
11234-
11235-RGFW_window* RGFW_createWindowPlatform(const char* name, RGFW_windowFlags flags, RGFW_window* win) {
11236-	if (name[0] == 0) name = (char*) " ";
11237-	win->src.hIconSmall = win->src.hIconBig = NULL;
11238-	win->src.maxSizeW = 0;
11239-	win->src.maxSizeH = 0;
11240-	win->src.minSizeW = 0;
11241-	win->src.minSizeH = 0;
11242-	win->src.aspectRatioW = 0;
11243-	win->src.aspectRatioH = 0;
11244-
11245-	HINSTANCE inh = GetModuleHandleA(NULL);
11246-
11247-	#ifndef __cplusplus
11248-	WNDCLASSW Class = {0}; /*!< Setup the Window class. */
11249-	#else
11250-	WNDCLASSW Class = {};
11251-	#endif
11252-
11253-	if (_RGFW->className == NULL)
11254-		_RGFW->className = (char*)name;
11255-
11256-	wchar_t wide_class[256];
11257-	MultiByteToWideChar(CP_UTF8, 0, _RGFW->className, -1, wide_class, 255);
11258-
11259-	Class.lpszClassName = wide_class;
11260-	Class.hInstance = inh;
11261-	Class.hCursor = LoadCursor(NULL, IDC_ARROW);
11262-	Class.lpfnWndProc = WndProcW;
11263-	Class.cbClsExtra = sizeof(RGFW_window*);
11264-
11265-	Class.hIcon = (HICON)LoadImageA(GetModuleHandleW(NULL), "RGFW_ICON", IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED);
11266-	if (Class.hIcon == NULL)
11267-		Class.hIcon = (HICON)LoadImageA(NULL, (LPCSTR)IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED);
11268-
11269-	RegisterClassW(&Class);
11270-
11271-	DWORD window_style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
11272-
11273-	if (!(flags & RGFW_windowNoBorder)) {
11274-		window_style |= WS_CAPTION | WS_SYSMENU | WS_BORDER | WS_MINIMIZEBOX;
11275-
11276-		if (!(flags & RGFW_windowNoResize))
11277-			window_style |= WS_SIZEBOX | WS_MAXIMIZEBOX;
11278-	} else
11279-		window_style |= WS_POPUP | WS_VISIBLE | WS_SYSMENU;
11280-
11281-	wchar_t wide_name[256];
11282-	MultiByteToWideChar(CP_UTF8, 0, name, -1, wide_name, 255);
11283-	HWND dummyWin = CreateWindowW(Class.lpszClassName, (wchar_t*)wide_name, window_style, win->x, win->y, win->w, win->h, 0, 0, inh, 0);
11284-
11285-#ifdef RGFW_OPENGL
11286-	RGFW_win32_loadOpenGLFuncs(dummyWin);
11287-#endif
11288-
11289-	DestroyWindow(dummyWin);
11290-
11291-	RECT rect = { 0, 0, win->w, win->h};
11292-	DWORD style = RGFW_winapi_window_getStyle(win, flags);
11293-	DWORD exStyle = RGFW_winapi_window_getExStyle(win, flags);
11294-	AdjustWindowRectEx(&rect, style, FALSE, exStyle);
11295-
11296-	win->src.window = CreateWindowW(Class.lpszClassName, (wchar_t*)wide_name, window_style, win->x + rect.left, win->y + rect.top, rect.right - rect.left, rect.bottom - rect.top, 0, 0, inh, 0);
11297-	SetPropW(win->src.window, L"RGFW", win);
11298-	RGFW_window_resize(win, win->w, win->h); /* so WM_GETMINMAXINFO gets called again */
11299-
11300-	if (flags & RGFW_windowAllowDND) {
11301-		win->internal.flags |= RGFW_windowAllowDND;
11302-		RGFW_window_setDND(win, 1);
11303-	}
11304-	win->src.hdc = GetDC(win->src.window);
11305-
11306-	RGFW_win32_makeWindowDarkMode(win, RGFW_win32_getDarkModeState());
11307-	RGFW_win32_makeWindowTransparent(win);
11308-	return win;
11309-}
11310-
11311-void RGFW_window_setBorder(RGFW_window* win, RGFW_bool border) {
11312-	RGFW_setBit(&win->internal.flags, RGFW_windowNoBorder, !border);
11313-
11314-	RECT rect;
11315-    GetClientRect(win->src.window, &rect);
11316-
11317-	LONG style = GetWindowLong(win->src.window, GWL_STYLE);
11318-	style |= (LONG)RGFW_winapi_window_getStyle(win, win->internal.flags);
11319-
11320-	if (border == 0) {
11321-		style &= ~WS_OVERLAPPEDWINDOW;
11322-	} else {
11323-		if (win->internal.flags & RGFW_windowNoResize) style &= ~WS_MAXIMIZEBOX;
11324-		style |= WS_OVERLAPPEDWINDOW;
11325-	}
11326-
11327-	DWORD exStyle = RGFW_winapi_window_getExStyle(win, win->internal.flags);
11328-	ClientToScreen(win->src.window, (POINT*) &rect.left);
11329-    ClientToScreen(win->src.window, (POINT*) &rect.right);
11330-
11331-	AdjustWindowRectEx(&rect, (DWORD)style, FALSE, exStyle);
11332-	SetWindowLong(win->src.window, GWL_STYLE, style);
11333-
11334-    SetWindowLongW(win->src.window, GWL_STYLE, style);
11335-    SetWindowPos(win->src.window, HWND_TOP, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOZORDER);
11336-}
11337-
11338-void RGFW_window_setDND(RGFW_window* win, RGFW_bool allow) {
11339-	RGFW_setBit(&win->internal.flags, RGFW_windowAllowDND, allow);
11340-	DragAcceptFiles(win->src.window, allow);
11341-}
11342-
11343-RGFW_bool RGFW_getGlobalMouse(i32* x, i32* y) {
11344-	POINT p;
11345-	GetCursorPos(&p);
11346-	if (x) *x = p.x;
11347-	if (y) *y = p.y;
11348-	return RGFW_TRUE;
11349-}
11350-
11351-void RGFW_window_setAspectRatio(RGFW_window* win, i32 w, i32 h) {
11352-	RGFW_ASSERT(win != NULL);
11353-	win->src.aspectRatioW = w;
11354-	win->src.aspectRatioH = h;
11355-}
11356-
11357-void RGFW_window_setMinSize(RGFW_window* win, i32 w, i32 h) {
11358-	RGFW_ASSERT(win != NULL);
11359-	win->src.minSizeW = w;
11360-	win->src.minSizeH = h;
11361-}
11362-
11363-void RGFW_window_setMaxSize(RGFW_window* win, i32 w, i32 h) {
11364-	RGFW_ASSERT(win != NULL);
11365-	win->src.maxSizeW = w;
11366-	win->src.maxSizeH = h;
11367-}
11368-
11369-void RGFW_window_focus(RGFW_window* win) {
11370-	RGFW_ASSERT(win);
11371-	SetForegroundWindow(win->src.window);
11372-	SetFocus(win->src.window);
11373-}
11374-
11375-void RGFW_window_raise(RGFW_window* win) {
11376-	RGFW_ASSERT(win);
11377-	BringWindowToTop(win->src.window);
11378-	SetWindowPos(win->src.window, HWND_TOP, win->x, win->y, win->w, win->h, SWP_NOSIZE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_FRAMECHANGED);
11379-}
11380-
11381-void RGFW_window_setFullscreen(RGFW_window* win, RGFW_bool fullscreen) {
11382-	RGFW_ASSERT(win != NULL);
11383-
11384-	RGFW_monitor* mon  = RGFW_window_getMonitor(win);
11385-
11386-	if (fullscreen == RGFW_FALSE) {
11387-		RGFW_monitor_setMode(mon, &win->internal.oldMode);
11388-
11389-		RGFW_window_setBorder(win, 1);
11390-
11391-		RECT rect = { 0, 0, win->internal.oldW, win->internal.oldH};
11392-		DWORD style = RGFW_winapi_window_getStyle(win, win->internal.flags);
11393-		DWORD exStyle = RGFW_winapi_window_getExStyle(win, win->internal.flags);
11394-		AdjustWindowRectEx(&rect, style, FALSE, exStyle);
11395-		SetWindowPos(win->src.window, HWND_TOP, win->internal.oldX, win->internal.oldY, rect.right - rect.left, rect.bottom - rect.top, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER);
11396-
11397-		win->internal.flags &= ~(u32)RGFW_windowFullscreen;
11398-		win->x  = win->internal.oldX;
11399-		win->y = win->internal.oldY;
11400-		win->w = win->internal.oldW;
11401-		win->h = win->internal.oldH;
11402-		return;
11403-	}
11404-
11405-	win->internal.oldX = win->x;
11406-	win->internal.oldY = win->y;
11407-	win->internal.oldW = win->w;
11408-	win->internal.oldH = win->h;
11409-	win->internal.oldMode = mon->mode;
11410-	win->internal.flags |= RGFW_windowFullscreen;
11411-
11412-	RGFW_window_setBorder(win, 0);
11413-
11414-    SetWindowPos(win->src.window, HWND_TOPMOST, (i32)mon->x, (i32)mon->y, 0, 0, SWP_NOOWNERZORDER | SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOSIZE);
11415-	win->x = mon->x;
11416-	win->y = mon->y;
11417-
11418-	RGFW_monitor_scaleToWindow(mon, win);
11419-    SetWindowPos(win->src.window, HWND_TOPMOST, 0, 0, (i32)mon->mode.w, (i32)mon->mode.h, SWP_NOOWNERZORDER | SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOMOVE);
11420-	win->w = mon->mode.w;
11421-	win->h = mon->mode.h;
11422-}
11423-
11424-void RGFW_window_maximize(RGFW_window* win) {
11425-	RGFW_ASSERT(win != NULL);
11426-	RGFW_window_hide(win);
11427-	ShowWindow(win->src.window, SW_MAXIMIZE);
11428-	RGFW_window_fetchSize(win, NULL, NULL);
11429-}
11430-
11431-void RGFW_window_minimize(RGFW_window* win) {
11432-	RGFW_ASSERT(win != NULL);
11433-	ShowWindow(win->src.window, SW_MINIMIZE);
11434-}
11435-
11436-void RGFW_window_setFloating(RGFW_window* win, RGFW_bool floating) {
11437-    RGFW_ASSERT(win != NULL);
11438-    if (floating) SetWindowPos(win->src.window, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
11439-    else SetWindowPos(win->src.window, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
11440-}
11441-
11442-void RGFW_window_setOpacity(RGFW_window* win, u8 opacity) {
11443-	SetWindowLong(win->src.window, GWL_EXSTYLE, WS_EX_LAYERED);
11444-	SetLayeredWindowAttributes(win->src.window, 0, opacity, LWA_ALPHA);
11445-}
11446-
11447-void RGFW_window_restore(RGFW_window* win) { RGFW_window_show(win); }
11448-
11449-RGFW_bool RGFW_window_isFloating(RGFW_window* win) {
11450-	return (GetWindowLongPtr(win->src.window, GWL_EXSTYLE) & WS_EX_TOPMOST) != 0;
11451-}
11452-
11453-void RGFW_stopCheckEvents(void) {
11454-	PostMessageW(_RGFW->root->src.window, WM_NULL, 0, 0);
11455-}
11456-
11457-void RGFW_waitForEvent(i32 waitMS) {
11458-	MsgWaitForMultipleObjects(0, NULL, FALSE, (DWORD)waitMS, QS_ALLINPUT);
11459-}
11460-
11461-RGFW_key RGFW_physicalToMappedKey(RGFW_key key) {
11462-    UINT vsc = RGFW_rgfwToApiKey(key);
11463-    BYTE keyboardState[256] = {0};
11464-
11465-    if (!GetKeyboardState(keyboardState))
11466-        return key;
11467-
11468-    UINT vk = MapVirtualKeyW(vsc, MAPVK_VSC_TO_VK);
11469-    HKL layout = GetKeyboardLayout(0);
11470-
11471-    wchar_t charBuffer[4] = {0};
11472-    int result = ToUnicodeEx(vk, vsc, keyboardState, charBuffer, 1, 0, layout);
11473-
11474-    if (result == 1 && charBuffer[0] < 256) {
11475-        return (RGFW_key)charBuffer[0];
11476-	}
11477-
11478-    switch (vk) {
11479-        case VK_F1:  return RGFW_keyF1;
11480-        case VK_F2:  return RGFW_keyF2;
11481-        case VK_F3:  return RGFW_keyF3;
11482-        case VK_F4:  return RGFW_keyF4;
11483-        case VK_F5:  return RGFW_keyF5;
11484-        case VK_F6:  return RGFW_keyF6;
11485-        case VK_F7:  return RGFW_keyF7;
11486-        case VK_F8:  return RGFW_keyF8;
11487-        case VK_F9:  return RGFW_keyF9;
11488-        case VK_F10: return RGFW_keyF10;
11489-        case VK_F11: return RGFW_keyF11;
11490-        case VK_F12: return RGFW_keyF12;
11491-        case VK_F13: return RGFW_keyF13;
11492-        case VK_F14: return RGFW_keyF14;
11493-        case VK_F15: return RGFW_keyF15;
11494-        case VK_F16: return RGFW_keyF16;
11495-        case VK_F17: return RGFW_keyF17;
11496-        case VK_F18: return RGFW_keyF18;
11497-        case VK_F19: return RGFW_keyF19;
11498-        case VK_F20: return RGFW_keyF20;
11499-        case VK_F21: return RGFW_keyF21;
11500-        case VK_F22: return RGFW_keyF22;
11501-        case VK_F23: return RGFW_keyF23;
11502-        case VK_F24: return RGFW_keyF24;
11503-        case VK_LSHIFT:   return RGFW_keyShiftL;
11504-        case VK_RSHIFT:   return RGFW_keyShiftR;
11505-        case VK_LCONTROL: return RGFW_keyControlL;
11506-        case VK_RCONTROL: return RGFW_keyControlR;
11507-        case VK_LMENU:    return RGFW_keyAltL;
11508-        case VK_RMENU:    return RGFW_keyAltR;
11509-        case VK_LWIN:     return RGFW_keySuperL;
11510-        case VK_RWIN:     return RGFW_keySuperR;
11511-        case VK_CAPITAL:  return RGFW_keyCapsLock;
11512-        case VK_NUMLOCK:  return RGFW_keyNumLock;
11513-        case VK_SCROLL:   return RGFW_keyScrollLock;
11514-        case VK_UP:       return RGFW_keyUp;
11515-        case VK_DOWN:     return RGFW_keyDown;
11516-        case VK_LEFT:     return RGFW_keyLeft;
11517-        case VK_RIGHT:    return RGFW_keyRight;
11518-        case VK_HOME:     return RGFW_keyHome;
11519-        case VK_END:      return RGFW_keyEnd;
11520-        case VK_PRIOR:    return RGFW_keyPageUp;
11521-        case VK_NEXT:     return RGFW_keyPageDown;
11522-        case VK_INSERT:   return RGFW_keyInsert;
11523-        case VK_APPS:     return RGFW_keyMenu;
11524-        case VK_ADD:      return RGFW_keyPadPlus;
11525-        case VK_SUBTRACT: return RGFW_keyPadMinus;
11526-        case VK_MULTIPLY: return RGFW_keyPadMultiply;
11527-        case VK_DIVIDE:   return RGFW_keyPadSlash;
11528-        case VK_RETURN:   return RGFW_keyPadReturn;
11529-        case VK_DECIMAL:  return RGFW_keyPadPeriod;
11530-        case VK_NUMPAD0: return RGFW_keyPad0;
11531-        case VK_NUMPAD1: return RGFW_keyPad1;
11532-        case VK_NUMPAD2: return RGFW_keyPad2;
11533-        case VK_NUMPAD3: return RGFW_keyPad3;
11534-        case VK_NUMPAD4: return RGFW_keyPad4;
11535-        case VK_NUMPAD5: return RGFW_keyPad5;
11536-        case VK_NUMPAD6: return RGFW_keyPad6;
11537-        case VK_NUMPAD7: return RGFW_keyPad7;
11538-        case VK_NUMPAD8: return RGFW_keyPad8;
11539-        case VK_NUMPAD9: return RGFW_keyPad9;
11540-        case VK_SNAPSHOT: return RGFW_keyPrintScreen;
11541-        case VK_PAUSE:    return RGFW_keyPause;
11542-        default: return RGFW_keyNULL;
11543-    }
11544-
11545-    return RGFW_keyNULL;
11546-}
11547-
11548-RGFW_bool RGFW_window_fetchSize(RGFW_window* win, i32* w, i32* h) {
11549-    RECT area;
11550-    GetClientRect(win->src.window, &area);
11551-
11552-    win->w = area.right;
11553-    win->h = area.bottom;
11554-
11555-	return RGFW_window_getSize(win, w, h);
11556-}
11557-
11558-void RGFW_pollEvents(void) {
11559-	RGFW_resetPrevState();
11560-    MSG msg;
11561-    while (PeekMessageA(&msg, NULL, 0u, 0u, PM_REMOVE)) {
11562-		TranslateMessage(&msg);
11563-		DispatchMessageA(&msg);
11564-	}
11565-}
11566-
11567-RGFW_bool RGFW_window_isHidden(RGFW_window* win) {
11568-	RGFW_ASSERT(win != NULL);
11569-	return IsWindowVisible(win->src.window) == 0 && !RGFW_window_isMinimized(win);
11570-}
11571-
11572-RGFW_bool RGFW_window_isMinimized(RGFW_window* win) {
11573-	RGFW_ASSERT(win != NULL);
11574-
11575-	#ifndef __cplusplus
11576-	WINDOWPLACEMENT placement = {0};
11577-	#else
11578-	WINDOWPLACEMENT placement = {};
11579-	#endif
11580-	GetWindowPlacement(win->src.window, &placement);
11581-	return placement.showCmd == SW_SHOWMINIMIZED;
11582-}
11583-
11584-RGFW_bool RGFW_window_isMaximized(RGFW_window* win) {
11585-	RGFW_ASSERT(win != NULL);
11586-
11587-	#ifndef __cplusplus
11588-	WINDOWPLACEMENT placement = {0};
11589-	#else
11590-	WINDOWPLACEMENT placement = {};
11591-	#endif
11592-	GetWindowPlacement(win->src.window, &placement);
11593-	return placement.showCmd == SW_SHOWMAXIMIZED || IsZoomed(win->src.window);
11594-}
11595-
11596-RGFW_bool RGFW_monitor_getWorkarea(RGFW_monitor* monitor, i32* x, i32* y, i32* width, i32* height) {
11597-    MONITORINFOEX mi;
11598-	mi.cbSize = sizeof(MONITORINFOEX);
11599-	GetMonitorInfoA(monitor->node->hMonitor, (LPMONITORINFO)&mi);
11600-
11601-    if (x) *x = mi.rcWork.left;
11602-    if (y) *y = mi.rcWork.top;
11603-    if (width) *width = mi.rcWork.right - mi.rcWork.left;
11604-    if (height) *height = mi.rcWork.bottom - mi.rcWork.top;
11605-
11606-	return RGFW_TRUE;
11607-}
11608-
11609-size_t RGFW_monitor_getGammaRampPtr(RGFW_monitor* monitor, RGFW_gammaRamp* ramp) {
11610-    WORD values[3][256];
11611-
11612-    HDC dc = CreateDCW(L"DISPLAY", monitor->node->adapterName, NULL, NULL);
11613-    GetDeviceGammaRamp(dc, values);
11614-    DeleteDC(dc);
11615-
11616-	if (ramp) {
11617-	    memcpy(ramp->red,   values[0], sizeof(values[0]));
11618-		memcpy(ramp->green, values[1], sizeof(values[1]));
11619-	    memcpy(ramp->blue,  values[2], sizeof(values[2]));
11620-	}
11621-
11622-    return sizeof(values[0]) / sizeof(WORD);
11623-}
11624-
11625-RGFW_bool RGFW_monitor_setGammaRamp(RGFW_monitor* monitor, RGFW_gammaRamp* ramp) {
11626-    WORD values[3][256];
11627-    if (ramp->count != 256) {
11628-		RGFW_debugCallback(RGFW_typeError, RGFW_errX11, "Win32: Gamma ramp size must be 256");
11629-        return RGFW_FALSE;
11630-    }
11631-
11632-    memcpy(values[0], ramp->red,   sizeof(values[0]));
11633-    memcpy(values[1], ramp->green, sizeof(values[1]));
11634-    memcpy(values[2], ramp->blue,  sizeof(values[2]));
11635-
11636-    HDC dc = CreateDCW(L"DISPLAY", monitor->node->adapterName, NULL, NULL);
11637-    SetDeviceGammaRamp(dc, values);
11638-    DeleteDC(dc);
11639-	return RGFW_TRUE;
11640-}
11641-
11642-BOOL CALLBACK RGFW_win32_getMonitorHandle(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData);
11643-BOOL CALLBACK RGFW_win32_getMonitorHandle(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) {
11644-	RGFW_UNUSED(hMonitor);
11645-	RGFW_UNUSED(hdcMonitor);
11646-	RGFW_UNUSED(lprcMonitor);
11647-	RGFW_UNUSED(dwData);
11648-
11649-    MONITORINFOEXW mi;
11650-    ZeroMemory(&mi, sizeof(mi));
11651-    mi.cbSize = sizeof(mi);
11652-
11653-    if (GetMonitorInfoW(hMonitor, (MONITORINFO*) &mi)) {
11654-		RGFW_monitorNode* node = (RGFW_monitorNode*)dwData;
11655-        if (wcscmp(mi.szDevice, node->adapterName) == 0) {
11656-            node->hMonitor = hMonitor;
11657-		}
11658-    }
11659-
11660-	return TRUE;
11661-}
11662-
11663-RGFWDEF void RGFW_win32_getMode(DEVMODEW* dm, RGFW_monitorMode* mode);
11664-void RGFW_win32_getMode(DEVMODEW* dm, RGFW_monitorMode* mode) {
11665-	mode->w = (i32)dm->dmPelsWidth;
11666-	mode->h = (i32)dm->dmPelsHeight;
11667-	RGFW_splitBPP(dm->dmBitsPerPel, mode);
11668-
11669-    switch (dm->dmDisplayFrequency) {
11670-		case 119:
11671-		case 59:
11672-		case 29:
11673-			mode->refreshRate = ((float)(dm->dmDisplayFrequency + 1) * 1000.0f) / 1001.f;
11674-			break;
11675-		default:
11676-			mode->refreshRate = (float)dm->dmDisplayFrequency;
11677-			break;
11678-    }
11679-}
11680-
11681-size_t RGFW_monitor_getModesPtr(RGFW_monitor* monitor, RGFW_monitorMode** modes){
11682-	size_t count = 0;
11683-	DWORD modeIndex = 0;
11684-
11685-	for (;;) {
11686-		DEVMODEW dm;
11687-		ZeroMemory(&dm, sizeof(dm));
11688-		dm.dmSize = sizeof(dm);
11689-
11690-		if (!EnumDisplaySettingsW(monitor->node->adapterName, modeIndex, &dm))
11691-			break;
11692-
11693-		if (ChangeDisplaySettingsExW(monitor->node->adapterName, &dm, NULL, CDS_TEST, NULL) != DISP_CHANGE_SUCCESSFUL) {
11694-			continue;
11695-		}
11696-
11697-		modeIndex++;
11698-
11699-		if (dm.dmBitsPerPel < 15)
11700-			continue;
11701-
11702-		if (modes) {
11703-			RGFW_monitorMode mode;
11704-			RGFW_win32_getMode(&dm, &mode);
11705-
11706-			size_t i;
11707-			for (i = 0; i < count;  i++) {
11708-				if (RGFW_monitorModeCompare(&(*modes)[i], &mode, RGFW_monitorAll) == RGFW_TRUE) {
11709-					break;
11710-				}
11711-			}
11712-
11713-			if (i < count) {
11714-				continue;
11715-			}
11716-
11717-			(*modes)[count] = mode;
11718-		}
11719-
11720-		count += 1;
11721-	}
11722-
11723-	return count;
11724-}
11725-
11726-RGFWDEF void RGFW_win32_createMonitor(DISPLAY_DEVICEW* adapter, DISPLAY_DEVICEW* dd);
11727-void RGFW_win32_createMonitor(DISPLAY_DEVICEW* adapter, DISPLAY_DEVICEW* dd) {
11728-	DEVMODEW dm;
11729-	ZeroMemory(&dm, sizeof(dm));
11730-	dm.dmSize = sizeof(dm);
11731-
11732-	if (!EnumDisplaySettingsW(adapter->DeviceName, ENUM_CURRENT_SETTINGS, &dm)) {
11733-		return;
11734-	}
11735-
11736-	RGFW_monitorNode* node = RGFW_monitors_add(NULL);
11737-
11738-	wcscpy(node->adapterName, adapter->DeviceName);
11739-	wcscpy(node->deviceName, dd->DeviceName);
11740-
11741-	RGFW_createUTF8FromWideStringWin32(dd->DeviceString, node->mon.name, sizeof(node->mon.name));
11742-	node->mon.name[sizeof(node->mon.name) - 1] = '\0';
11743-
11744-	RECT rect;
11745-	rect.left = (LONG)dm.dmPosition.x;
11746-	rect.top = (LONG)dm.dmPosition.y;
11747-	rect.right = (LONG)((LONG)dm.dmPosition.x + (LONG)dm.dmPelsWidth);
11748-	rect.bottom = (LONG)((long)dm.dmPosition.y + (LONG)dm.dmPelsHeight);
11749-	EnumDisplayMonitors(NULL, &rect, RGFW_win32_getMonitorHandle, (LPARAM)node);
11750-
11751-	RGFW_win32_getMode(&dm, &node->mon.mode);
11752-
11753-	MONITORINFOEXW monitorInfo;
11754-	monitorInfo.cbSize = sizeof(MONITORINFOEXW);
11755-	GetMonitorInfoW(node->hMonitor, (LPMONITORINFO)&monitorInfo);
11756-
11757-	node->mon.x = monitorInfo.rcMonitor.left;
11758-	node->mon.y = monitorInfo.rcMonitor.top;
11759-
11760-	HDC hdc = CreateDCW(monitorInfo.szDevice, NULL, NULL, NULL);
11761-	/* get pixels per inch */
11762-	float dpiX = (float)GetDeviceCaps(hdc, LOGPIXELSX);
11763-	float dpiY = (float)GetDeviceCaps(hdc, LOGPIXELSX);
11764-
11765-	node->mon.scaleX = dpiX / 96.0f;
11766-	node->mon.scaleY = dpiY / 96.0f;
11767-	node->mon.pixelRatio = dpiX >= 192.0f ? 2.0f : 1.0f;
11768-
11769-	node->mon.physW = (float)GetDeviceCaps(hdc, HORZSIZE) / 25.4f;
11770-	node->mon.physH = (float)GetDeviceCaps(hdc, VERTSIZE) / 25.4f;
11771-	DeleteDC(hdc);
11772-
11773-#ifndef RGFW_NO_DPI
11774-	RGFW_LOAD_LIBRARY(RGFW_Shcore_dll, "shcore.dll");
11775-	RGFW_PROC_DEF(RGFW_Shcore_dll, GetDpiForMonitor);
11776-
11777-	if (GetDpiForMonitor != NULL) {
11778-		u32 x, y;
11779-		GetDpiForMonitor(node->hMonitor, MDT_EFFECTIVE_DPI, &x, &y);
11780-		node->mon.scaleX = (float) (x) / (float) 96.0f;
11781-		node->mon.scaleY = (float) (y) / (float) 96.0f;
11782-		node->mon.pixelRatio = dpiX >= 192.0f ? 2.0f : 1.0f;
11783-	}
11784-#endif
11785-
11786-	if (monitorInfo.dwFlags & MONITORINFOF_PRIMARY) {
11787-		_RGFW->monitors.primary = node;
11788-	}
11789-
11790-	RGFW_monitorCallback(_RGFW->root, &node->mon, RGFW_TRUE);
11791-}
11792-
11793-void RGFW_pollMonitors(void) {
11794-	for (RGFW_monitorNode* node = _RGFW->monitors.list.head; node; node = node->next) {
11795-		node->disconnected = RGFW_TRUE;
11796-	}
11797-
11798-	/* loop through display adapters (GPU) */
11799-	DISPLAY_DEVICEW adapter;
11800-	DWORD adapterNum;
11801-	for (adapterNum = 0; ; adapterNum++) {
11802-        ZeroMemory(&adapter, sizeof(adapter));
11803-		adapter.cb = sizeof(adapter);
11804-
11805-		if (!EnumDisplayDevicesW(NULL, adapterNum, &adapter, 0))
11806-			break;
11807-
11808-		if (!(adapter.StateFlags & DISPLAY_DEVICE_ACTIVE))
11809-			continue;
11810-
11811-		DISPLAY_DEVICEW dd;
11812-		dd.cb = sizeof(dd);
11813-
11814-		/* loop through display devices (monitors) */
11815-		DWORD deviceNum;
11816-		for (deviceNum = 0; ; deviceNum++) {
11817-            ZeroMemory(&dd, sizeof(dd));
11818-            dd.cb = sizeof(dd);
11819-
11820-			if (!EnumDisplayDevicesW(adapter.DeviceName, deviceNum, &dd, 0))
11821-				break;
11822-
11823-			if (!(dd.StateFlags & DISPLAY_DEVICE_ACTIVE))
11824-				continue;
11825-
11826-			RGFW_monitorNode* node;
11827-			for (node = _RGFW->monitors.list.head; node; node = node->next) {
11828-				if (node->disconnected == RGFW_TRUE && wcscmp(node->deviceName, dd.DeviceName) == 0) {
11829-					node->disconnected = RGFW_FALSE;
11830-					EnumDisplayMonitors(NULL, NULL, RGFW_win32_getMonitorHandle, (LPARAM) &node->mon);
11831-					break;
11832-				}
11833-			}
11834-
11835-			if (node) {
11836-				continue;
11837-			}
11838-
11839-			RGFW_win32_createMonitor(&adapter, &dd);
11840-		}
11841-
11842-		/* if there are no display devices, just use the monitor directly (hack borrowed from GLFW (I'm not giving it back)) */
11843-        if (deviceNum == 0) {
11844-   			RGFW_monitorNode* node;
11845-			for (node = _RGFW->monitors.list.head; node; node = node->next) {
11846-				if (node->disconnected == RGFW_TRUE && wcscmp(node->adapterName, adapter.DeviceName) == 0) {
11847-					node->disconnected = RGFW_FALSE;
11848-					break;
11849-				}
11850-			}
11851-
11852-			if (node) {
11853-				continue;
11854-			}
11855-
11856-			RGFW_win32_createMonitor(&adapter, NULL);
11857-        }
11858-	}
11859-
11860-	RGFW_monitors_refresh();
11861-}
11862-
11863-RGFW_monitor* RGFW_window_getMonitor(RGFW_window* win) {
11864-	HMONITOR src = MonitorFromWindow(win->src.window, MONITOR_DEFAULTTOPRIMARY);
11865-	RGFW_monitorNode* node = _RGFW->monitors.list.head;
11866-
11867-	for (node = _RGFW->monitors.list.head; node; node = node->next) {
11868-		if (node->hMonitor == src) {
11869-			return &node->mon;
11870-		}
11871-	}
11872-
11873-	return RGFW_getPrimaryMonitor();
11874-}
11875-
11876-RGFW_bool RGFW_monitor_setMode(RGFW_monitor* mon, RGFW_monitorMode* mode) {
11877-	DEVMODEW dm;
11878-	ZeroMemory(&dm, sizeof(dm));
11879-	dm.dmSize = sizeof(dm);
11880-
11881-	dm.dmFields |= DM_PELSWIDTH | DM_PELSHEIGHT;
11882-	dm.dmPelsWidth = (u32)mode->w;
11883-	dm.dmPelsHeight = (u32)mode->h;
11884-
11885-	dm.dmFields |= DM_DISPLAYFREQUENCY;
11886-	dm.dmDisplayFrequency = (DWORD)mode->refreshRate;
11887-
11888-	dm.dmFields |= DM_BITSPERPEL;
11889-	dm.dmBitsPerPel = (DWORD)(mode->red + mode->green + mode->blue);
11890-
11891-	if (ChangeDisplaySettingsExW(mon->node->adapterName, &dm, NULL, CDS_TEST, NULL) == DISP_CHANGE_SUCCESSFUL) {
11892-		if (ChangeDisplaySettingsExW(mon->node->adapterName, &dm, NULL, CDS_UPDATEREGISTRY, NULL) == DISP_CHANGE_SUCCESSFUL) {
11893-			RGFW_win32_getMode(&dm, &mon->mode);
11894-			return RGFW_TRUE;
11895-		}
11896-		return RGFW_FALSE;
11897-	} else return RGFW_FALSE;
11898-}
11899-
11900-RGFW_bool RGFW_monitor_requestMode(RGFW_monitor* mon, RGFW_monitorMode* mode, RGFW_modeRequest request) {
11901-HMONITOR src = mon->node->hMonitor;
11902-
11903-	MONITORINFOEX  monitorInfo;
11904-	monitorInfo.cbSize = sizeof(MONITORINFOEX);
11905-	GetMonitorInfoA(src, (LPMONITORINFO)&monitorInfo);
11906-
11907-	DEVMODEW dm;
11908-	ZeroMemory(&dm, sizeof(dm));
11909-	dm.dmSize = sizeof(dm);
11910-
11911-	DWORD index = 0;
11912-
11913-	for (;;) {
11914-		if (EnumDisplaySettingsW(mon->node->adapterName, index, &dm) == 0) {
11915-			break;
11916-		}
11917-
11918-		index += 1;
11919-
11920-		if (request & RGFW_monitorScale) {
11921-			dm.dmFields |= DM_PELSWIDTH | DM_PELSHEIGHT;
11922-			dm.dmPelsWidth = (u32)mode->w;
11923-			dm.dmPelsHeight = (u32)mode->h;
11924-		}
11925-
11926-		if (request & RGFW_monitorRefresh) {
11927-			dm.dmFields |= DM_DISPLAYFREQUENCY;
11928-			dm.dmDisplayFrequency = (DWORD)mode->refreshRate;
11929-		}
11930-
11931-		if (request & RGFW_monitorRGB) {
11932-			dm.dmFields |= DM_BITSPERPEL;
11933-			dm.dmBitsPerPel = (DWORD)(mode->red + mode->green + mode->blue);
11934-		}
11935-
11936-		if (ChangeDisplaySettingsExW(mon->node->adapterName, &dm, NULL, CDS_TEST, NULL) == DISP_CHANGE_SUCCESSFUL) {
11937-			if (ChangeDisplaySettingsExW(mon->node->adapterName, &dm, NULL, CDS_UPDATEREGISTRY, NULL) == DISP_CHANGE_SUCCESSFUL) {
11938-				RGFW_win32_getMode(&dm, &mon->mode);
11939-				return RGFW_TRUE;
11940-			}
11941-			return RGFW_FALSE;
11942-		}
11943-	}
11944-
11945-	return RGFW_FALSE;
11946-}
11947-
11948-HICON RGFW_loadHandleImage(u8* data, i32 w, i32 h, RGFW_format format, BOOL icon);
11949-HICON RGFW_loadHandleImage(u8* data, i32 w, i32 h, RGFW_format format, BOOL icon) {
11950-	BITMAPV5HEADER bi;
11951-	ZeroMemory(&bi, sizeof(bi));
11952-	bi.bV5Size = sizeof(bi);
11953-	bi.bV5Width = (i32)w;
11954-	bi.bV5Height = -((LONG) h);
11955-	bi.bV5Planes = 1;
11956-	bi.bV5BitCount = (WORD)32;
11957-	bi.bV5Compression = BI_RGB;
11958-	HDC dc = GetDC(NULL);
11959-	u8* target = NULL;
11960-
11961-	HBITMAP color = CreateDIBSection(dc,
11962-		(BITMAPINFO*) &bi, DIB_RGB_COLORS, (void**) &target,
11963-		NULL, (DWORD) 0);
11964-
11965-	RGFW_copyImageData(target, w, h, RGFW_formatBGRA8, data, format, NULL);
11966-    ReleaseDC(NULL, dc);
11967-
11968-	HBITMAP mask = CreateBitmap((i32)w, (i32)h, 1, 1, NULL);
11969-
11970-	ICONINFO ii;
11971-	ZeroMemory(&ii, sizeof(ii));
11972-	ii.fIcon = icon;
11973-	ii.xHotspot = (u32)w / 2;
11974-	ii.yHotspot = (u32)h / 2;
11975-	ii.hbmMask = mask;
11976-	ii.hbmColor = color;
11977-
11978-	HICON handle = CreateIconIndirect(&ii);
11979-
11980-	DeleteObject(color);
11981-	DeleteObject(mask);
11982-
11983-	return handle;
11984-}
11985-
11986-RGFW_mouse* RGFW_createMouseStandard(RGFW_mouseIcon mouse) {
11987-	u32 mouseIcon = 0;
11988-
11989-    switch (mouse) {
11990-		case RGFW_mouseNormal: mouseIcon = OCR_NORMAL; break;
11991-		case RGFW_mouseArrow: mouseIcon = OCR_NORMAL; break;
11992-		case RGFW_mouseIbeam: mouseIcon = OCR_IBEAM; break;
11993-		case RGFW_mouseWait: mouseIcon = OCR_WAIT; break;
11994-		case RGFW_mouseCrosshair: mouseIcon = OCR_CROSS; break;
11995-		case RGFW_mouseProgress: mouseIcon = OCR_APPSTARTING; break;
11996-		case RGFW_mouseResizeNWSE: mouseIcon = OCR_SIZENWSE; break;
11997-		case RGFW_mouseResizeNESW: mouseIcon = OCR_SIZENESW; break;
11998-		case RGFW_mouseResizeEW: mouseIcon = OCR_SIZEWE; break;
11999-		case RGFW_mouseResizeNS: mouseIcon = OCR_SIZENS; break;
12000-		case RGFW_mouseResizeAll: mouseIcon = OCR_SIZEALL; break;
12001-		case RGFW_mouseNotAllowed: mouseIcon = OCR_NO; break;
12002-		case RGFW_mousePointingHand: mouseIcon = OCR_HAND; break;
12003-		case RGFW_mouseResizeNW: mouseIcon = OCR_SIZENWSE; break;
12004-		case RGFW_mouseResizeN: mouseIcon = OCR_SIZENS; break;
12005-		case RGFW_mouseResizeNE: mouseIcon = OCR_SIZENESW; break;
12006-		case RGFW_mouseResizeE: mouseIcon = OCR_SIZEWE; break;
12007-		case RGFW_mouseResizeSE: mouseIcon = OCR_SIZENWSE; break;
12008-		case RGFW_mouseResizeS: mouseIcon = OCR_SIZENS; break;
12009-		case RGFW_mouseResizeSW: mouseIcon = OCR_SIZENESW; break;
12010-		case RGFW_mouseResizeW: mouseIcon = OCR_SIZEWE; break;
12011-		default: return NULL;
12012-    }
12013-
12014-	char* icon = MAKEINTRESOURCEA(mouseIcon);
12015-	return LoadCursorA(NULL, icon);
12016-}
12017-
12018-RGFW_mouse* RGFW_createMouse(u8* data, i32 w, i32 h, RGFW_format format) {
12019-	HCURSOR cursor = (HCURSOR) RGFW_loadHandleImage(data, w, h, format, FALSE);
12020-	return cursor;
12021-}
12022-
12023-RGFW_bool RGFW_window_setMousePlatform(RGFW_window* win, RGFW_mouse* mouse) {
12024-	RGFW_ASSERT(win && mouse);
12025-	SetClassLongPtrA(win->src.window, GCLP_HCURSOR, (LPARAM) mouse);
12026-	SetCursor((HCURSOR)mouse);
12027-
12028-	return RGFW_FALSE;
12029-}
12030-
12031-void RGFW_freeMouse(RGFW_mouse* mouse) {
12032-	RGFW_ASSERT(mouse);
12033-	DestroyCursor((HCURSOR)mouse);
12034-}
12035-
12036-void RGFW_window_hide(RGFW_window* win) {
12037-	ShowWindow(win->src.window, SW_HIDE);
12038-}
12039-
12040-void RGFW_window_show(RGFW_window* win) {
12041-	if (win->internal.flags & RGFW_windowFocusOnShow) RGFW_window_focus(win);
12042-	ShowWindow(win->src.window, SW_RESTORE);
12043-}
12044-
12045-void RGFW_window_flash(RGFW_window* win, RGFW_flashRequest request) {
12046-	if (RGFW_window_isInFocus(win) && request) {
12047-		return;
12048-	}
12049-
12050-	FLASHWINFO desc;
12051-	RGFW_MEMZERO(&desc, sizeof(desc));
12052-
12053-    desc.cbSize = sizeof(desc);
12054-    desc.hwnd = win->src.window;
12055-
12056-    switch (request) {
12057-		case RGFW_flashCancel:
12058-			desc.dwFlags = FLASHW_STOP;
12059-			break;
12060-		case RGFW_flashBriefly:
12061-			desc.dwFlags = FLASHW_TRAY;
12062-			desc.uCount = 1;
12063-			break;
12064-		case RGFW_flashUntilFocused:
12065-			desc.dwFlags = (FLASHW_TRAY | FLASHW_TIMERNOFG);
12066-			break;
12067-		default: break;
12068-    }
12069-
12070-    FlashWindowEx(&desc);
12071-}
12072-
12073-#define RGFW_FREE_LIBRARY(x) if (x != NULL) FreeLibrary(x); x = NULL;
12074-void RGFW_deinitPlatform(void) {
12075-    #ifndef RGFW_NO_DPI
12076-        RGFW_FREE_LIBRARY(RGFW_Shcore_dll);
12077-    #endif
12078-
12079-    #ifndef RGFW_NO_WINMM
12080-        timeEndPeriod(1);
12081-        #ifndef RGFW_NO_LOAD_WINMM
12082-            RGFW_FREE_LIBRARY(RGFW_winmm_dll);
12083-        #endif
12084-    #endif
12085-
12086-    RGFW_FREE_LIBRARY(RGFW_wgl_dll);
12087-
12088-    RGFW_freeMouse(_RGFW->hiddenMouse);
12089-}
12090-
12091-
12092-void RGFW_window_closePlatform(RGFW_window* win) {
12093-	RemovePropW(win->src.window, L"RGFW");
12094-	ReleaseDC(win->src.window, win->src.hdc); /*!< delete device context */
12095-	DestroyWindow(win->src.window); /*!< delete window */
12096-
12097-	if (win->src.hIconSmall) DestroyIcon(win->src.hIconSmall);
12098-	if (win->src.hIconBig) DestroyIcon(win->src.hIconBig);
12099-}
12100-
12101-void RGFW_window_move(RGFW_window* win, i32 x, i32 y) {
12102-	RGFW_ASSERT(win != NULL);
12103-
12104-	win->x = x;
12105-	win->y = y;
12106-	SetWindowPos(win->src.window, HWND_TOP, win->x, win->y, 0, 0, SWP_NOSIZE);
12107-}
12108-
12109-void RGFW_window_resize(RGFW_window* win, i32 w, i32 h) {
12110-	RGFW_ASSERT(win != NULL);
12111-
12112-	win->w = w;
12113-	win->h = h;
12114-	RECT rect = { 0, 0, w, h};
12115-	DWORD style = RGFW_winapi_window_getStyle(win, win->internal.flags);
12116-	DWORD exStyle = RGFW_winapi_window_getExStyle(win, win->internal.flags);
12117-	AdjustWindowRectEx(&rect, style, FALSE, exStyle);
12118-	SetWindowPos(win->src.window, HWND_TOP, 0, 0, rect.right - rect.left, rect.bottom - rect.top, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOZORDER);
12119-}
12120-
12121-void RGFW_window_setName(RGFW_window* win, const char* name) {
12122-	RGFW_ASSERT(win != NULL);
12123-	if (name == NULL) name = "\0";
12124-
12125-	wchar_t wide_name[256];
12126-	MultiByteToWideChar(CP_UTF8, 0, name, -1, wide_name, 256);
12127-	SetWindowTextW(win->src.window, wide_name);
12128-}
12129-
12130-#ifndef RGFW_NO_PASSTHROUGH
12131-void RGFW_window_setMousePassthrough(RGFW_window* win, RGFW_bool passthrough) {
12132-	RGFW_ASSERT(win != NULL);
12133-	COLORREF key = 0;
12134-	BYTE alpha = 0;
12135-	DWORD flags = 0;
12136-	i32 exStyle = GetWindowLongW(win->src.window, GWL_EXSTYLE);
12137-
12138-	if (exStyle & WS_EX_LAYERED)
12139-		GetLayeredWindowAttributes(win->src.window, &key, &alpha, &flags);
12140-
12141-	if (passthrough)
12142-		exStyle |= (WS_EX_TRANSPARENT | WS_EX_LAYERED);
12143-	else {
12144-		exStyle &= ~WS_EX_TRANSPARENT;
12145-		if (exStyle & WS_EX_LAYERED && !(flags & LWA_ALPHA))
12146-			exStyle &= ~WS_EX_LAYERED;
12147-	}
12148-
12149-	SetWindowLongW(win->src.window, GWL_EXSTYLE, exStyle);
12150-
12151-	if (passthrough)
12152-		SetLayeredWindowAttributes(win->src.window, key, alpha, flags);
12153-}
12154-#endif
12155-
12156-RGFW_bool RGFW_window_setIconEx(RGFW_window* win, u8* data, i32 w, i32 h, RGFW_format format, RGFW_icon type) {
12157-	RGFW_ASSERT(win != NULL);
12158-	#ifndef RGFW_WIN95
12159-		if (win->src.hIconSmall && (type & RGFW_iconWindow)) DestroyIcon(win->src.hIconSmall);
12160-		if (win->src.hIconBig && (type & RGFW_iconTaskbar)) DestroyIcon(win->src.hIconBig);
12161-
12162-		if (data == NULL) {
12163-			HICON defaultIcon = LoadIcon(NULL, IDI_APPLICATION);
12164-			if (type & RGFW_iconWindow)
12165-				SendMessage(win->src.window, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM)defaultIcon);
12166-			if (type & RGFW_iconTaskbar)
12167-				SendMessage(win->src.window, WM_SETICON, (WPARAM)ICON_BIG, (LPARAM)defaultIcon);
12168-			return RGFW_TRUE;
12169-		}
12170-
12171-		if (type & RGFW_iconWindow) {
12172-			win->src.hIconSmall = RGFW_loadHandleImage(data, w, h, format, TRUE);
12173-			SendMessage(win->src.window, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM)win->src.hIconSmall);
12174-		}
12175-		if (type & RGFW_iconTaskbar) {
12176-			win->src.hIconBig = RGFW_loadHandleImage(data, w, h, format, TRUE);
12177-			SendMessage(win->src.window, WM_SETICON, (WPARAM)ICON_BIG, (LPARAM)win->src.hIconBig);
12178-		}
12179-		return RGFW_TRUE;
12180-	#else
12181-		RGFW_UNUSED(img);
12182-		RGFW_UNUSED(type);
12183-		return RGFW_FALSE;
12184-	#endif
12185-}
12186-
12187-RGFW_ssize_t RGFW_readClipboardPtr(char* str, size_t strCapacity) {
12188-	/* Open the clipboard */
12189-	if (OpenClipboard(NULL) == 0)
12190-		return -1;
12191-
12192-	/* Get the clipboard data as a Unicode string */
12193-	HANDLE hData = GetClipboardData(CF_UNICODETEXT);
12194-	if (hData == NULL) {
12195-		CloseClipboard();
12196-		return -1;
12197-	}
12198-
12199-	wchar_t* wstr = (wchar_t*) GlobalLock(hData);
12200-
12201-	RGFW_ssize_t textLen = 0;
12202-
12203-	{
12204-		setlocale(LC_ALL, "en_US.UTF-8");
12205-
12206-		textLen = (RGFW_ssize_t)wcstombs(NULL, wstr, 0) + 1;
12207-		if (str != NULL && (RGFW_ssize_t)strCapacity <= textLen - 1)
12208-			textLen = 0;
12209-
12210-		if (str != NULL && textLen) {
12211-			if (textLen > 1)
12212-				wcstombs(str, wstr, (size_t)(textLen));
12213-
12214-			str[textLen - 1] = '\0';
12215-		}
12216-	}
12217-
12218-	/* Release the clipboard data */
12219-	GlobalUnlock(hData);
12220-	CloseClipboard();
12221-
12222-	return textLen;
12223-}
12224-
12225-void RGFW_writeClipboard(const char* text, u32 textLen) {
12226-	HANDLE object;
12227-	WCHAR* buffer;
12228-
12229-	object = GlobalAlloc(GMEM_MOVEABLE, (1 + textLen) * sizeof(WCHAR));
12230-	if (!object)
12231-		return;
12232-
12233-	buffer = (WCHAR*) GlobalLock(object);
12234-	if (!buffer) {
12235-		GlobalFree(object);
12236-		return;
12237-	}
12238-
12239-	MultiByteToWideChar(CP_UTF8, 0, text, -1, buffer, (i32)textLen);
12240-	GlobalUnlock(object);
12241-
12242-	if (!OpenClipboard(_RGFW->root->src.window)) {
12243-		GlobalFree(object);
12244-		return;
12245-	}
12246-
12247-	EmptyClipboard();
12248-	SetClipboardData(CF_UNICODETEXT, object);
12249-	CloseClipboard();
12250-}
12251-
12252-void RGFW_window_moveMouse(RGFW_window* win, i32 x, i32 y) {
12253-	RGFW_ASSERT(win != NULL);
12254-	win->internal.lastMouseX = x - win->x;
12255-	win->internal.lastMouseY = y - win->y;
12256-	SetCursorPos(x, y);
12257-}
12258-
12259-#ifdef RGFW_OPENGL
12260-RGFW_bool RGFW_extensionSupportedPlatform_OpenGL(const char * extension, size_t len) {
12261-	const char* extensions = NULL;
12262-
12263-    RGFW_proc proc = RGFW_getProcAddress_OpenGL("wglGetExtensionsStringARB");
12264-    RGFW_proc proc2 = RGFW_getProcAddress_OpenGL("wglGetExtensionsStringEXT");
12265-
12266-    if (proc)
12267-        extensions = ((const char* (*)(HDC))proc)(wglGetCurrentDC());
12268-    else if (proc2)
12269-        extensions = ((const char*(*)(void))proc2)();
12270-    return extensions != NULL && RGFW_extensionSupportedStr(extensions, extension, len);
12271-}
12272-
12273-RGFW_proc RGFW_getProcAddress_OpenGL(const char* procname) {
12274-    RGFW_proc proc = (RGFW_proc)wglGetProcAddress(procname);
12275-    if (proc)
12276-        return proc;
12277-
12278-    return (RGFW_proc) GetProcAddress(RGFW_wgl_dll, procname);
12279-}
12280-
12281-void RGFW_win32_loadOpenGLFuncs(HWND dummyWin) {
12282-     if (wglSwapIntervalEXT != NULL && wglChoosePixelFormatARB != NULL && wglChoosePixelFormatARB != NULL)
12283-		return;
12284-
12285-	HDC dummy_dc = GetDC(dummyWin);
12286-	u32 pfd_flags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
12287-
12288-	PIXELFORMATDESCRIPTOR pfd = {sizeof(pfd), 1, pfd_flags, PFD_TYPE_RGBA, 32, 8, PFD_MAIN_PLANE, 32, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 32, 8, 0, PFD_MAIN_PLANE, 0, 0, 0, 0};
12289-
12290-	int dummy_pixel_format = ChoosePixelFormat(dummy_dc, &pfd);
12291-	SetPixelFormat(dummy_dc, dummy_pixel_format, &pfd);
12292-
12293-	HGLRC dummy_context = wglCreateContext(dummy_dc);
12294-
12295-	HGLRC cur = wglGetCurrentContext();
12296-	wglMakeCurrent(dummy_dc, dummy_context);
12297-
12298-	wglCreateContextAttribsARB = ((PFNWGLCREATECONTEXTATTRIBSARBPROC(WINAPI *)(const char*)) wglGetProcAddress)("wglCreateContextAttribsARB");
12299-	wglChoosePixelFormatARB = ((PFNWGLCHOOSEPIXELFORMATARBPROC(WINAPI *)(const char*)) wglGetProcAddress)("wglChoosePixelFormatARB");
12300-
12301-    wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)(RGFW_proc)wglGetProcAddress("wglSwapIntervalEXT");
12302-    if (wglSwapIntervalEXT == NULL) {
12303-        RGFW_debugCallback(RGFW_typeError, RGFW_errOpenGLContext,  "Failed to load swap interval function");
12304-    }
12305-
12306-	wglMakeCurrent(dummy_dc, cur);
12307-	wglDeleteContext(dummy_context);
12308-	ReleaseDC(dummyWin, dummy_dc);
12309-}
12310-
12311-#define WGL_ACCELERATION_ARB             0x2003
12312-#define WGL_FULL_ACCELERATION_ARB        0x2027
12313-#define WGL_DRAW_TO_WINDOW_ARB           0x2001
12314-#define WGL_PIXEL_TYPE_ARB               0x2013
12315-#define WGL_TYPE_RGBA_ARB                0x202b
12316-#define WGL_SUPPORT_OPENGL_ARB           0x2010
12317-#define WGL_COLOR_BITS_ARB               0x2014
12318-#define WGL_DOUBLE_BUFFER_ARB            0x2011
12319-#define WGL_ALPHA_BITS_ARB               0x201b
12320-#define WGL_DEPTH_BITS_ARB               0x2022
12321-#define WGL_STENCIL_BITS_ARB             0x2023
12322-#define WGL_STEREO_ARB                  0x2012
12323-#define WGL_AUX_BUFFERS_ARB              0x2024
12324-#define WGL_RED_BITS_ARB                 0x2015
12325-#define WGL_GREEN_BITS_ARB               0x2017
12326-#define WGL_BLUE_BITS_ARB                0x2019
12327-#define WGL_ACCUM_RED_BITS_ARB           0x201e
12328-#define WGL_ACCUM_GREEN_BITS_ARB         0x201f
12329-#define WGL_ACCUM_BLUE_BITS_ARB          0x2020
12330-#define WGL_ACCUM_ALPHA_BITS_ARB         0x2021
12331-#define WGL_COLORSPACE_SRGB_EXT          0x3089
12332-#define WGL_CONTEXT_OPENGL_NO_ERROR_ARB  0x31b3
12333-#define WGL_CONTEXT_RELEASE_BEHAVIOR_ARB         0x2097
12334-#define WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB    0x0000
12335-#define WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB   0x2098
12336-#define WGL_CONTEXT_FLAGS_ARB            0x2094
12337-#define WGL_ACCESS_READ_WRITE_NV         0x00000001
12338-#define WGL_COVERAGE_SAMPLES_NV          0x2042
12339-#define WGL_CONTEXT_ES_PROFILE_BIT_EXT   0x00000004
12340-#define WGL_CONTEXT_PROFILE_MASK_ARB               0x9126
12341-#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB            0x00000001
12342-#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB   0x00000002
12343-#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
12344-#define WGL_CONTEXT_MAJOR_VERSION_ARB               0x2091
12345-#define WGL_CONTEXT_MINOR_VERSION_ARB               0x2092
12346-#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB             0x20A9
12347-#define WGL_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097
12348-#define WGL_CONTEXT_DEBUG_BIT_ARB 0x00000001
12349-#define WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004
12350-
12351-RGFW_bool RGFW_window_createContextPtr_OpenGL(RGFW_window* win, RGFW_glContext* ctx, RGFW_glHints* hints) {
12352-	const char flushControl[] = "WGL_ARB_context_flush_control";
12353-	const char noError[] = "WGL_ARB_create_context_no_error";
12354-	const char robustness[] = "WGL_ARB_create_context_robustness";
12355-
12356-	win->src.ctx.native = ctx;
12357-	win->src.gfxType = RGFW_gfxNativeOpenGL;
12358-
12359-	PIXELFORMATDESCRIPTOR pfd;
12360-	pfd.nSize        = sizeof(PIXELFORMATDESCRIPTOR);
12361-	pfd.nVersion     = 1;
12362-	pfd.dwFlags      = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
12363-	pfd.iPixelType   = PFD_TYPE_RGBA;
12364-	pfd.iLayerType   = PFD_MAIN_PLANE;
12365-	pfd.cColorBits   = 32;
12366-	pfd.cAlphaBits   = 8;
12367-	pfd.cDepthBits   = 24;
12368-	pfd.cStencilBits = (BYTE)hints->stencil;
12369-	pfd.cAuxBuffers  = (BYTE)hints->auxBuffers;
12370-	if (hints->stereo) pfd.dwFlags |= PFD_STEREO;
12371-
12372-	/* try to create the pixel format we want for OpenGL and then try to create an OpenGL context for the specified version */
12373-	if (hints->renderer == RGFW_glSoftware)
12374-		pfd.dwFlags |= PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED;
12375-
12376-	/* get pixel format, default to a basic pixel format */
12377-	int pixel_format = ChoosePixelFormat(win->src.hdc, &pfd);
12378-	if (wglChoosePixelFormatARB != NULL) {
12379-		i32 pixel_format_attribs[50];
12380-		RGFW_attribStack stack;
12381-		RGFW_attribStack_init(&stack, pixel_format_attribs, 50);
12382-
12383-		RGFW_attribStack_pushAttribs(&stack, WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB);
12384-		RGFW_attribStack_pushAttribs(&stack, WGL_DRAW_TO_WINDOW_ARB, 1);
12385-		RGFW_attribStack_pushAttribs(&stack, WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB);
12386-		RGFW_attribStack_pushAttribs(&stack, WGL_SUPPORT_OPENGL_ARB, 1);
12387-		RGFW_attribStack_pushAttribs(&stack, WGL_COLOR_BITS_ARB, 32);
12388-		RGFW_attribStack_pushAttribs(&stack, WGL_DOUBLE_BUFFER_ARB, 1);
12389-		RGFW_attribStack_pushAttribs(&stack, WGL_ALPHA_BITS_ARB, hints->alpha);
12390-		RGFW_attribStack_pushAttribs(&stack, WGL_DEPTH_BITS_ARB, hints->depth);
12391-		RGFW_attribStack_pushAttribs(&stack, WGL_STENCIL_BITS_ARB, hints->stencil);
12392-		RGFW_attribStack_pushAttribs(&stack, WGL_STEREO_ARB, hints->stereo);
12393-		RGFW_attribStack_pushAttribs(&stack, WGL_AUX_BUFFERS_ARB, hints->auxBuffers);
12394-		RGFW_attribStack_pushAttribs(&stack, WGL_RED_BITS_ARB, hints->red);
12395-		RGFW_attribStack_pushAttribs(&stack, WGL_GREEN_BITS_ARB, hints->blue);
12396-		RGFW_attribStack_pushAttribs(&stack, WGL_BLUE_BITS_ARB, hints->green);
12397-		RGFW_attribStack_pushAttribs(&stack, WGL_ACCUM_RED_BITS_ARB, hints->accumRed);
12398-		RGFW_attribStack_pushAttribs(&stack, WGL_ACCUM_GREEN_BITS_ARB, hints->accumGreen);
12399-		RGFW_attribStack_pushAttribs(&stack, WGL_ACCUM_BLUE_BITS_ARB, hints->accumBlue);
12400-		RGFW_attribStack_pushAttribs(&stack, WGL_ACCUM_ALPHA_BITS_ARB, hints->accumAlpha);
12401-
12402-		if(hints->sRGB) {
12403-			if (hints->profile != RGFW_glES)
12404-				RGFW_attribStack_pushAttribs(&stack, WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB, 1);
12405-			else
12406-				RGFW_attribStack_pushAttribs(&stack, WGL_COLORSPACE_SRGB_EXT, hints->sRGB);
12407-		}
12408-
12409-		RGFW_attribStack_pushAttribs(&stack, WGL_COVERAGE_SAMPLES_NV, hints->samples);
12410-
12411-		RGFW_attribStack_pushAttribs(&stack, 0, 0);
12412-
12413-		int new_pixel_format;
12414-		UINT num_formats;
12415-		wglChoosePixelFormatARB(win->src.hdc, pixel_format_attribs, 0, 1, &new_pixel_format, &num_formats);
12416-		if (!num_formats)
12417-			RGFW_debugCallback(RGFW_typeError, RGFW_errOpenGLContext, "Failed to create a pixel format for WGL");
12418-		else pixel_format = new_pixel_format;
12419-	}
12420-
12421-	PIXELFORMATDESCRIPTOR suggested;
12422-	if (!DescribePixelFormat(win->src.hdc, pixel_format, sizeof(suggested), &suggested) ||
12423-		!SetPixelFormat(win->src.hdc, pixel_format, &pfd))
12424-			RGFW_debugCallback(RGFW_typeError, RGFW_errOpenGLContext, "Failed to set the WGL pixel format");
12425-
12426-	if (wglCreateContextAttribsARB != NULL) {
12427-		/* create OpenGL/WGL context for the specified version */
12428-		i32 attribs[40];
12429-		RGFW_attribStack stack;
12430-		RGFW_attribStack_init(&stack, attribs, 50);
12431-
12432-
12433-		i32 mask = 0;
12434-		switch (hints->profile) {
12435-			case RGFW_glES: mask |= WGL_CONTEXT_ES_PROFILE_BIT_EXT; break;
12436-			case RGFW_glCompatibility: mask |= WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; break;
12437-			case RGFW_glForwardCompatibility: mask |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; break;
12438-			case RGFW_glCore: mask |= WGL_CONTEXT_CORE_PROFILE_BIT_ARB; break;
12439-			default: mask |= WGL_CONTEXT_CORE_PROFILE_BIT_ARB; break;
12440-		}
12441-
12442-		RGFW_attribStack_pushAttribs(&stack, WGL_CONTEXT_PROFILE_MASK_ARB, mask);
12443-
12444-		if (hints->minor || hints->major) {
12445-			RGFW_attribStack_pushAttribs(&stack, WGL_CONTEXT_MAJOR_VERSION_ARB, hints->major);
12446-			RGFW_attribStack_pushAttribs(&stack, WGL_CONTEXT_MINOR_VERSION_ARB, hints->minor);
12447-		}
12448-
12449-		if (RGFW_extensionSupportedPlatform_OpenGL(noError, sizeof(noError)))
12450-			RGFW_attribStack_pushAttribs(&stack, WGL_CONTEXT_OPENGL_NO_ERROR_ARB, hints->noError);
12451-
12452-		if (RGFW_extensionSupportedPlatform_OpenGL(flushControl, sizeof(flushControl))) {
12453-			if (hints->releaseBehavior == RGFW_glReleaseFlush) {
12454-				RGFW_attribStack_pushAttribs(&stack, WGL_CONTEXT_RELEASE_BEHAVIOR_ARB, WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB); /* WGL_CONTEXT_RELEASE_BEHAVIOR_ARB */
12455-			} else if (hints->releaseBehavior == RGFW_glReleaseNone) {
12456-				RGFW_attribStack_pushAttribs(&stack, WGL_CONTEXT_RELEASE_BEHAVIOR_ARB, WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
12457-			}
12458-		}
12459-
12460-		i32 flags = 0;
12461-		if (hints->debug) flags |= WGL_CONTEXT_DEBUG_BIT_ARB;
12462-		if (hints->robustness && RGFW_extensionSupportedPlatform_OpenGL(robustness, sizeof(robustness))) flags |= WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB;
12463-		if (flags) {
12464-			RGFW_attribStack_pushAttribs(&stack, WGL_CONTEXT_FLAGS_ARB, flags);
12465-		}
12466-
12467-
12468-		RGFW_attribStack_pushAttribs(&stack, 0, 0);
12469-
12470-		win->src.ctx.native->ctx = (HGLRC)wglCreateContextAttribsARB(win->src.hdc, NULL, attribs);
12471-	}
12472-
12473-	if (wglCreateContextAttribsARB == NULL || win->src.ctx.native->ctx == NULL) { /* fall back to a default context (probably OpenGL 2 or something) */
12474-		RGFW_debugCallback(RGFW_typeError, RGFW_errOpenGLContext, "Failed to create an accelerated OpenGL Context.");
12475-		win->src.ctx.native->ctx = wglCreateContext(win->src.hdc);
12476-	}
12477-
12478-	ReleaseDC(win->src.window, win->src.hdc);
12479-	win->src.hdc = GetDC(win->src.window);
12480-
12481-	if (hints->share) {
12482-		wglShareLists((HGLRC)RGFW_getCurrentContext_OpenGL(), hints->share->ctx);
12483-	}
12484-
12485-	wglMakeCurrent(win->src.hdc, win->src.ctx.native->ctx);
12486-	RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "OpenGL context initalized.");
12487-	return RGFW_TRUE;
12488-}
12489-
12490-void RGFW_window_deleteContextPtr_OpenGL(RGFW_window* win, RGFW_glContext* ctx) {
12491-	wglDeleteContext((HGLRC) ctx->ctx); /*!< delete OpenGL context */
12492-	win->src.ctx.native->ctx = NULL;
12493-	RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "OpenGL context freed.");
12494-}
12495-
12496-void RGFW_window_makeCurrentContext_OpenGL(RGFW_window* win) {
12497-	if (win == NULL)
12498-		wglMakeCurrent(NULL, NULL);
12499-	else
12500-		wglMakeCurrent(win->src.hdc, (HGLRC) win->src.ctx.native->ctx);
12501-}
12502-void* RGFW_getCurrentContext_OpenGL(void) {
12503-	return wglGetCurrentContext();
12504-}
12505-void RGFW_window_swapBuffers_OpenGL(RGFW_window* win) {
12506-	RGFW_ASSERT(win->src.ctx.native);
12507-	SwapBuffers(win->src.hdc);
12508-}
12509-
12510-void RGFW_window_swapInterval_OpenGL(RGFW_window* win, i32 swapInterval) {
12511-	RGFW_ASSERT(win != NULL);
12512-    if (wglSwapIntervalEXT == NULL || wglSwapIntervalEXT(swapInterval) == FALSE)
12513-		RGFW_debugCallback(RGFW_typeError, RGFW_errOpenGLContext, "Failed to set swap interval");
12514-}
12515-#endif
12516-
12517-RGFW_bool RGFW_createUTF8FromWideStringWin32(const WCHAR* source, char* output, size_t max) {
12518-    i32 size = 0;
12519-    if (source == NULL) {
12520-        return RGFW_FALSE;
12521-	}
12522-	size = WideCharToMultiByte(CP_UTF8, 0, source, -1, NULL, 0, NULL, NULL);
12523-	if (!size) {
12524-		return RGFW_FALSE;
12525-	}
12526-
12527-	if (size > (i32)max)
12528-		size = (i32)max;
12529-
12530-	if (!WideCharToMultiByte(CP_UTF8, 0, source, -1, output, size, NULL, NULL)) {
12531-		return RGFW_FALSE;
12532-	}
12533-
12534-	output[size] = 0;
12535-	return RGFW_TRUE;
12536-}
12537-
12538-#ifdef RGFW_WEBGPU
12539-WGPUSurface RGFW_window_createSurface_WebGPU(RGFW_window* window, WGPUInstance instance) {
12540-	WGPUSurfaceDescriptor surfaceDesc = {0};
12541-	WGPUSurfaceSourceWindowsHWND fromHwnd = {0};
12542-    fromHwnd.chain.sType = WGPUSType_SurfaceSourceWindowsHWND;
12543-    fromHwnd.hwnd = window->src.window;
12544-
12545-	fromHwnd.hinstance = GetModuleHandle(NULL);
12546-
12547-    surfaceDesc.nextInChain = (WGPUChainedStruct*)&fromHwnd.chain;
12548-    return wgpuInstanceCreateSurface(instance, &surfaceDesc);
12549-}
12550-#endif
12551-
12552-#endif /* RGFW_WINDOWS */
12553-
12554-/*
12555-	End of Windows defines
12556-*/
12557-
12558-
12559-
12560-/*
12561-
12562-	Start of MacOS defines
12563-
12564-
12565-*/
12566-
12567-#if defined(RGFW_MACOS)
12568-/*
12569-	based on silicon.h
12570-	start of cocoa wrapper
12571-*/
12572-
12573-#include <CoreGraphics/CoreGraphics.h>
12574-#include <ApplicationServices/ApplicationServices.h>
12575-#include <objc/runtime.h>
12576-#include <objc/message.h>
12577-#include <mach/mach_time.h>
12578-
12579-#include <Carbon/Carbon.h>
12580-
12581-typedef TISInputSourceRef (*PFN_TISCopyCurrentKeyboardLayoutInputSource)(void);
12582-PFN_TISCopyCurrentKeyboardLayoutInputSource TISCopyCurrentKeyboardLayoutInputSourceSrc;
12583-#define TISCopyCurrentKeyboardLayoutInputSource TISCopyCurrentKeyboardLayoutInputSourceSrc
12584-
12585-typedef CFDataRef (*PFN_TISGetInputSourceProperty)(TISInputSourceRef, CFStringRef);
12586-PFN_TISGetInputSourceProperty TISGetInputSourcePropertySrc;
12587-#define TISGetInputSourceProperty TISGetInputSourcePropertySrc
12588-
12589-typedef u8 (*PFN_LMGetKbdType)(void);
12590-PFN_LMGetKbdType LMGetKbdTypeSrc;
12591-#define LMGetKbdType LMGetKbdTypeSrc
12592-
12593-CFStringRef kTISPropertyUnicodeKeyLayoutDataSrc;
12594-
12595-#ifndef  __OBJC__
12596-typedef CGRect NSRect;
12597-typedef CGPoint NSPoint;
12598-typedef CGSize NSSize;
12599-
12600-typedef const char* NSPasteboardType;
12601-typedef unsigned long NSUInteger;
12602-typedef long NSInteger;
12603-typedef NSInteger NSModalResponse;
12604-
12605-typedef enum NSRequestUserAttentionType {
12606-	NSCriticalRequest = 0,
12607-    NSInformationalRequest = 10
12608-} NSRequestUserAttentionType;
12609-
12610-typedef enum NSApplicationActivationPolicy {
12611-	NSApplicationActivationPolicyRegular,
12612-	NSApplicationActivationPolicyAccessory,
12613-	NSApplicationActivationPolicyProhibited
12614-} NSApplicationActivationPolicy;
12615-
12616-typedef RGFW_ENUM(u32, NSBackingStoreType) {
12617-	NSBackingStoreRetained = 0,
12618-		NSBackingStoreNonretained = 1,
12619-		NSBackingStoreBuffered = 2
12620-};
12621-
12622-typedef RGFW_ENUM(u32, NSWindowStyleMask) {
12623-	NSWindowStyleMaskBorderless = 0,
12624-		NSWindowStyleMaskTitled = 1 << 0,
12625-		NSWindowStyleMaskClosable = 1 << 1,
12626-		NSWindowStyleMaskMiniaturizable = 1 << 2,
12627-		NSWindowStyleMaskResizable = 1 << 3,
12628-		NSWindowStyleMaskTexturedBackground = 1 << 8, /* deprecated */
12629-		NSWindowStyleMaskUnifiedTitleAndToolbar = 1 << 12,
12630-		NSWindowStyleMaskFullScreen = 1 << 14,
12631-		NSWindowStyleMaskFullSizeContentView = 1 << 15,
12632-		NSWindowStyleMaskUtilityWindow = 1 << 4,
12633-		NSWindowStyleMaskDocModalWindow = 1 << 6,
12634-		NSWindowStyleMaskNonactivatingpanel = 1 << 7,
12635-		NSWindowStyleMaskHUDWindow = 1 << 13
12636-};
12637-
12638-#define NSPasteboardTypeString "public.utf8-plain-text"
12639-
12640-typedef RGFW_ENUM(i32, NSDragOperation) {
12641-	NSDragOperationNone = 0,
12642-		NSDragOperationCopy = 1,
12643-		NSDragOperationLink = 2,
12644-		NSDragOperationGeneric = 4,
12645-		NSDragOperationPrivate = 8,
12646-		NSDragOperationMove = 16,
12647-		NSDragOperationDelete = 32,
12648-		NSDragOperationEvery = (int)ULONG_MAX
12649-};
12650-
12651-typedef RGFW_ENUM(NSInteger, NSOpenGLContextParameter) {
12652-	NSOpenGLContextParameterSwapInterval            = 222, /* 1 param.  0 -> Don't sync, 1 -> Sync to vertical retrace     */
12653-		NSOpenGLContextParametectxaceOrder            = 235, /* 1 param.  1 -> Above Window (default), -1 -> Below Window    */
12654-		NSOpenGLContextParametectxaceOpacity          = 236, /* 1 param.  1-> Surface is opaque (default), 0 -> non-opaque   */
12655-		NSOpenGLContextParametectxaceBackingSize      = 304, /* 2 params.  Width/height of surface backing size              */
12656-		NSOpenGLContextParameterReclaimResources        = 308, /* 0 params.                                                    */
12657-		NSOpenGLContextParameterCurrentRendererID       = 309, /* 1 param.   Retrieves the current renderer ID                 */
12658-		NSOpenGLContextParameterGPUVertexProcessing     = 310, /* 1 param.   Currently processing vertices with GPU (get)      */
12659-		NSOpenGLContextParameterGPUFragmentProcessing   = 311, /* 1 param.   Currently processing fragments with GPU (get)     */
12660-		NSOpenGLContextParameterHasDrawable             = 314, /* 1 param.   Boolean returned if drawable is attached          */
12661-		NSOpenGLContextParameterMPSwapsInFlight         = 315, /* 1 param.   Max number of swaps queued by the MP GL engine    */
12662-
12663-		NSOpenGLContextParameterSwapRectangle API_DEPRECATED("", macos(10.0, 10.14)) = 200, /* 4 params.  Set or get the swap rectangle {x, y, w, h} */
12664-		NSOpenGLContextParameterSwapRectangleEnable API_DEPRECATED("", macos(10.0, 10.14)) = 201, /* Enable or disable the swap rectangle */
12665-		NSOpenGLContextParameterRasterizationEnable API_DEPRECATED("", macos(10.0, 10.14)) = 221, /* Enable or disable all rasterization */
12666-		NSOpenGLContextParameterStateValidation API_DEPRECATED("", macos(10.0, 10.14)) = 301, /* Validate state for multi-screen functionality */
12667-		NSOpenGLContextParametectxaceSurfaceVolatile API_DEPRECATED("", macos(10.0, 10.14)) = 306, /* 1 param.   Surface volatile state */
12668-};
12669-
12670-typedef RGFW_ENUM(NSInteger, NSWindowButton) {
12671-    NSWindowCloseButton            = 0,
12672-    NSWindowMiniaturizeButton      = 1,
12673-    NSWindowZoomButton             = 2,
12674-    NSWindowToolbarButton          = 3,
12675-    NSWindowDocumentIconButton     = 4,
12676-    NSWindowDocumentVersionsButton = 6,
12677-    NSWindowFullScreenButton       = 7,
12678-};
12679-
12680-#define NSPasteboardTypeURL "public.url"
12681-#define NSPasteboardTypeFileURL "public.file-url"
12682-#define NSTrackingMouseEnteredAndExited   0x01
12683-#define NSTrackingMouseMoved              0x02
12684-#define NSTrackingCursorUpdate            0x04
12685-#define NSTrackingActiveWhenFirstResponder 0x10
12686-#define NSTrackingActiveInKeyWindow       0x20
12687-#define NSTrackingActiveInActiveApp       0x40
12688-#define NSTrackingActiveAlways            0x80
12689-#define NSTrackingAssumeInside            0x100
12690-#define NSTrackingInVisibleRect           0x200
12691-#define NSTrackingEnabledDuringMouseDrag  0x400
12692-enum {
12693-	NSOpenGLPFAAllRenderers =   1,	/* choose from all available renderers          */
12694-	NSOpenGLPFATripleBuffer =   3,	/* choose a triple buffered pixel format        */
12695-	NSOpenGLPFADoubleBuffer      =   5,	/* choose a double buffered pixel format        */
12696-	NSOpenGLPFAAuxBuffers   =   7,	/* number of aux buffers                        */
12697-	NSOpenGLPFAColorSize       =   8,	/* number of color buffer bits                  */
12698-	NSOpenGLPFAAlphaSize  =  11,	/* number of alpha component bits               */
12699-	NSOpenGLPFADepthSize   =  12,	/* number of depth buffer bits                  */
12700-	NSOpenGLPFAStencilSize   =  13,	/* number of stencil buffer bits                */
12701-	NSOpenGLPFAAccumSize       =  14,	/* number of accum buffer bits                  */
12702-	NSOpenGLPFAMinimumPolicy   =  51,	/* never choose smaller buffers than requested  */
12703-	NSOpenGLPFAMaximumPolicy =  52,	/* choose largest buffers of type requested     */
12704-	NSOpenGLPFASampleBuffers     =  55,	/* number of multi sample buffers               */
12705-	NSOpenGLPFASamples            =  56,	/* number of samples per multi sample buffer    */
12706-	NSOpenGLPFAAuxDepthStencil     =  57,	/* each aux buffer has its own depth stencil    */
12707-	NSOpenGLPFAColorFloat   =  58,	/* color buffers store floating point pixels    */
12708-	NSOpenGLPFAMultisample   =  59,    /* choose multisampling                         */
12709-	NSOpenGLPFASupersample    =  60,    /* choose supersampling                         */
12710-	NSOpenGLPFASampleAlpha     =  61,    /* request alpha filtering                      */
12711-	NSOpenGLPFARendererID       =  70,	/* request renderer by ID                       */
12712-	NSOpenGLPFANoRecovery   =  72,	/* disable all failure recovery systems         */
12713-	NSOpenGLPFAAccelerated      =  73,	/* choose a hardware accelerated renderer       */
12714-	NSOpenGLPFAClosestPolicy   =  74,	/* choose the closest color buffer to request   */
12715-	NSOpenGLPFABackingStore     =  76,	/* back buffer contents are valid after swap    */
12716-	NSOpenGLPFAScreenMask     =  84,	/* bit mask of supported physical screens       */
12717-	NSOpenGLPFAAllowOfflineRenderers  =  96,  /* allow use of offline renderers               */
12718-	NSOpenGLPFAAcceleratedCompute   =  97,	/* choose a hardware accelerated compute device */
12719-	NSOpenGLPFAOpenGLProfile      =  99,    /* specify an OpenGL Profile to use             */
12720-	NSOpenGLProfileVersionLegacy     = 0x1000, /* The requested profile is a legacy (pre-OpenGL 3.0) profile. */
12721-	NSOpenGLProfileVersion3_2Core    = 0x3200, /* The 3.2 Profile of OpenGL */
12722-	NSOpenGLProfileVersion4_1Core  = 0x3200, /* The 4.1 profile of OpenGL */
12723-	NSOpenGLPFAVirtualScreenCount      = 128,	/* number of virtual screens in this format     */
12724-	NSOpenGLPFAStereo                 =   6,
12725-	NSOpenGLPFAOffScreen             =  53,
12726-	NSOpenGLPFAFullScreen           =  54,
12727-	NSOpenGLPFASingleRenderer      =  71,
12728-	NSOpenGLPFARobust                 =  75,
12729-	NSOpenGLPFAMPSafe           =  78,
12730-	NSOpenGLPFAWindow                 =  80,
12731-	NSOpenGLPFAMultiScreen =    81,
12732-	NSOpenGLPFACompliant   =   83,
12733-	NSOpenGLPFAPixelBuffer            =  90,
12734-	NSOpenGLPFARemotePixelBuffer =  91,
12735-};
12736-
12737-typedef RGFW_ENUM(u32, NSEventType) {        /* various types of events */
12738-	NSEventTypeApplicationDefined = 15,
12739-};
12740-typedef unsigned long long NSEventMask;
12741-
12742-typedef enum NSEventModifierFlags {
12743-	NSEventModifierFlagCapsLock = 1 << 16,
12744-	NSEventModifierFlagShift = 1 << 17,
12745-	NSEventModifierFlagControl = 1 << 18,
12746-	NSEventModifierFlagOption = 1 << 19,
12747-	NSEventModifierFlagCommand = 1 << 20,
12748-	NSEventModifierFlagNumericPad = 1 << 21
12749-} NSEventModifierFlags;
12750-
12751-typedef RGFW_ENUM(NSUInteger, NSBitmapFormat) {
12752-	NSBitmapFormatAlphaFirst = 1 << 0,       /* 0 means is alpha last (RGBA, CMYKA, etc.) */
12753-		NSBitmapFormatAlphaNonpremultiplied = 1 << 1,       /* 0 means is premultiplied */
12754-		NSBitmapFormatFloatingpointSamples = 1 << 2,  /* 0 is integer */
12755-
12756-		NSBitmapFormatSixteenBitLittleEndian = (1 << 8),
12757-		NSBitmapFormatThirtyTwoBitLittleEndian = (1 << 9),
12758-		NSBitmapFormatSixteenBitBigEndian = (1 << 10),
12759-		NSBitmapFormatThirtyTwoBitBigEndian = (1 << 11)
12760-};
12761-
12762-#else
12763-#import <AppKit/AppKit.h>
12764-#include <Foundation/Foundation.h>
12765-#endif /* notdef __OBJC__ */
12766-
12767-#ifdef __arm64__
12768-	/* ARM just uses objc_msgSend */
12769-#define abi_objc_msgSend_stret objc_msgSend
12770-#define abi_objc_msgSend_fpret objc_msgSend
12771-#else /* __i386__ */
12772-	/* x86 just uses abi_objc_msgSend_fpret and (NSColor *)objc_msgSend_id respectively */
12773-#define abi_objc_msgSend_stret objc_msgSend_stret
12774-#define abi_objc_msgSend_fpret objc_msgSend_fpret
12775-#endif
12776-
12777-#define NSAlloc(nsclass) objc_msgSend_id((id)nsclass, sel_registerName("alloc"))
12778-#define objc_msgSend_bool(x, y)			((BOOL (*)(id, SEL))objc_msgSend) ((id)(x), (SEL)y)
12779-#define objc_msgSend_void(x, y)			((void (*)(id, SEL))objc_msgSend) ((id)(x), (SEL)y)
12780-#define objc_msgSend_void_id(x, y, z)		((void (*)(id, SEL, id))objc_msgSend) ((id)x, (SEL)y, (id)z)
12781-#define objc_msgSend_uint(x, y)			((NSUInteger (*)(id, SEL))objc_msgSend)  ((id)(x), (SEL)y)
12782-#define objc_msgSend_void_bool(x, y, z)		((void (*)(id, SEL, BOOL))objc_msgSend)  ((id)(x), (SEL)y, (BOOL)z)
12783-#define objc_msgSend_bool_void(x, y)		((BOOL (*)(id, SEL))objc_msgSend)  ((id)(x), (SEL)y)
12784-#define objc_msgSend_void_SEL(x, y, z)		((void (*)(id, SEL, SEL))objc_msgSend)  ((id)(x), (SEL)y, (SEL)z)
12785-#define objc_msgSend_id(x, y)				((id (*)(id, SEL))objc_msgSend)  ((id)(x), (SEL)y)
12786-#define objc_msgSend_id_id(x, y, z)			((id (*)(id, SEL, id))objc_msgSend)  ((id)(x), (SEL)y, (id)z)
12787-#define objc_msgSend_id_bool(x, y, z)			((BOOL (*)(id, SEL, id))objc_msgSend)  ((id)(x), (SEL)y, (id)z)
12788-#define objc_msgSend_int(x, y, z) 				((id (*)(id, SEL, int))objc_msgSend)  ((id)(x), (SEL)y, (int)z)
12789-#define objc_msgSend_arr(x, y, z)				 	((id (*)(id, SEL, int))objc_msgSend)  ((id)(x), (SEL)y, (int)z)
12790-#define objc_msgSend_ptr(x, y, z) 					((id (*)(id, SEL, void*))objc_msgSend)  ((id)(x), (SEL)y, (void*)z)
12791-#define objc_msgSend_class(x, y) 					((id (*)(Class, SEL))objc_msgSend)  ((Class)(x), (SEL)y)
12792-#define objc_msgSend_class_char(x, y, z) 			((id (*)(Class, SEL, char*))objc_msgSend)  ((Class)(x), (SEL)y, (char*)z)
12793-
12794-#define NSRelease(obj) objc_msgSend_void((id)obj, sel_registerName("release"))
12795-RGFWDEF id NSString_stringWithUTF8String(const char* str);
12796-id NSString_stringWithUTF8String(const char* str) {
12797-	return ((id(*)(id, SEL, const char*))objc_msgSend) ((id)objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), str);
12798-}
12799-
12800-RGFWDEF float RGFW_cocoaYTransform(float y);
12801-float RGFW_cocoaYTransform(float y) { return (float)(CGDisplayBounds(CGMainDisplayID()).size.height - (double)y - (double)1.0f); }
12802-
12803-const char* NSString_to_char(id str);
12804-const char* NSString_to_char(id str) {
12805-	return ((const char* (*)(id, SEL)) objc_msgSend) ((id)(id)str, sel_registerName("UTF8String"));
12806-}
12807-
12808-unsigned char* NSBitmapImageRep_bitmapData(id imageRep);
12809-unsigned char* NSBitmapImageRep_bitmapData(id imageRep) {
12810-	return ((unsigned char* (*)(id, SEL))objc_msgSend) ((id)imageRep, sel_registerName("bitmapData"));
12811-}
12812-
12813-id NSBitmapImageRep_initWithBitmapData(unsigned char** planes, NSInteger width, NSInteger height, NSInteger bps, NSInteger spp, bool alpha, bool isPlanar, const char* colorSpaceName, NSBitmapFormat bitmapFormat, NSInteger rowBytes, NSInteger pixelBits);
12814-id NSBitmapImageRep_initWithBitmapData(unsigned char** planes, NSInteger width, NSInteger height, NSInteger bps, NSInteger spp, bool alpha, bool isPlanar, const char* colorSpaceName, NSBitmapFormat bitmapFormat, NSInteger rowBytes, NSInteger pixelBits) {
12815-	SEL func = sel_registerName("initWithBitmapDataPlanes:pixelsWide:pixelsHigh:bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:colorSpaceName:bitmapFormat:bytesPerRow:bitsPerPixel:");
12816-
12817-	return (id) ((id(*)(id, SEL, unsigned char**, NSInteger, NSInteger, NSInteger, NSInteger, bool, bool, id, NSBitmapFormat, NSInteger, NSInteger))objc_msgSend)
12818-		(NSAlloc((id)objc_getClass("NSBitmapImageRep")), func, planes, width, height, bps, spp, alpha, isPlanar, NSString_stringWithUTF8String(colorSpaceName), bitmapFormat, rowBytes, pixelBits);
12819-}
12820-
12821-id NSColor_colorWithSRGB(CGFloat red, CGFloat green, CGFloat blue, CGFloat alpha);
12822-id NSColor_colorWithSRGB(CGFloat red, CGFloat green, CGFloat blue, CGFloat alpha) {
12823-	Class nsclass = objc_getClass("NSColor");
12824-	SEL func = sel_registerName("colorWithSRGBRed:green:blue:alpha:");
12825-	return ((id(*)(id, SEL, CGFloat, CGFloat, CGFloat, CGFloat))objc_msgSend)
12826-		((id)nsclass, func, red, green, blue, alpha);
12827-}
12828-
12829-id NSPasteboard_generalPasteboard(void);
12830-id NSPasteboard_generalPasteboard(void) {
12831-	return (id) objc_msgSend_id((id)objc_getClass("NSPasteboard"), sel_registerName("generalPasteboard"));
12832-}
12833-
12834-id* cstrToNSStringArray(char** strs, size_t len);
12835-id* cstrToNSStringArray(char** strs, size_t len) {
12836-	static id nstrs[6];
12837-	size_t i;
12838-	for (i = 0; i < len; i++)
12839-		nstrs[i] = NSString_stringWithUTF8String(strs[i]);
12840-
12841-	return nstrs;
12842-}
12843-
12844-const char* NSPasteboard_stringForType(id pasteboard, NSPasteboardType dataType, size_t* len);
12845-const char* NSPasteboard_stringForType(id pasteboard, NSPasteboardType dataType, size_t* len) {
12846-	SEL func = sel_registerName("stringForType:");
12847-	id nsstr = NSString_stringWithUTF8String((const char*)dataType);
12848-	id nsString = ((id(*)(id, SEL, id))objc_msgSend)(pasteboard, func, nsstr);
12849-	const char* str = NSString_to_char(nsString);
12850-	if (len != NULL)
12851-		*len = (size_t)((NSUInteger(*)(id, SEL, int))objc_msgSend)(nsString, sel_registerName("maximumLengthOfBytesUsingEncoding:"), 4);
12852-	return str;
12853-}
12854-
12855-id c_array_to_NSArray(void* array, size_t len);
12856-id c_array_to_NSArray(void* array, size_t len) {
12857-	return ((id (*)(id, SEL, void*, NSUInteger))objc_msgSend) (NSAlloc(objc_getClass("NSArray")), sel_registerName("initWithObjects:count:"), array, len);
12858-}
12859-
12860-
12861-void NSregisterForDraggedTypes(id view, NSPasteboardType* newTypes, size_t len);
12862-void NSregisterForDraggedTypes(id view, NSPasteboardType* newTypes, size_t len) {
12863-	id* ntypes = cstrToNSStringArray((char**)newTypes, len);
12864-
12865-	id array = c_array_to_NSArray(ntypes, len);
12866-	objc_msgSend_void_id(view, sel_registerName("registerForDraggedTypes:"), array);
12867-	NSRelease(array);
12868-}
12869-
12870-NSInteger NSPasteBoard_declareTypes(id pasteboard, NSPasteboardType* newTypes, size_t len, void* owner);
12871-NSInteger NSPasteBoard_declareTypes(id pasteboard, NSPasteboardType* newTypes, size_t len, void* owner) {
12872-	id* ntypes = cstrToNSStringArray((char**)newTypes, len);
12873-
12874-	SEL func = sel_registerName("declareTypes:owner:");
12875-
12876-	id array = c_array_to_NSArray(ntypes, len);
12877-
12878-	NSInteger output = ((NSInteger(*)(id, SEL, id, void*))objc_msgSend)
12879-		(pasteboard, func, array, owner);
12880-	NSRelease(array);
12881-
12882-	return output;
12883-}
12884-
12885-#define NSRetain(obj) objc_msgSend_void((id)obj, sel_registerName("retain"))
12886-
12887-/*
12888-	End of cocoa wrapper
12889-*/
12890-
12891-static id RGFW__osxCustomInitWithRGFWWindow(id self, SEL _cmd, RGFW_window* win) {
12892-	RGFW_UNUSED(_cmd);
12893-    struct objc_super s = { self, class_getSuperclass(object_getClass(self)) };
12894-
12895-    CGRect rect;
12896-    rect.origin.x = 0;
12897-    rect.origin.y = 0;
12898-    rect.size.width = (double)win->w;
12899-    rect.size.height = (double)win->h;
12900-
12901-    self = ((id (*)(struct objc_super*, SEL, CGRect))objc_msgSendSuper)(
12902-        &s, sel_registerName("initWithFrame:"), rect
12903-    );
12904-
12905-    if (self != nil) {
12906-        object_setInstanceVariable(self, "RGFW_window", win);
12907-        object_setInstanceVariable(self, "trackingArea", nil);
12908-
12909-        object_setInstanceVariable(
12910-            self, "markedText",
12911-            ((id (*)(id, SEL))objc_msgSend)(
12912-                ((id (*)(Class, SEL))objc_msgSend)(objc_getClass("NSMutableAttributedString"), sel_registerName("alloc")),
12913-                sel_registerName("init")
12914-            )
12915-        );
12916-
12917-        ((void (*)(id, SEL))objc_msgSend)(self, sel_registerName("updateTrackingAreas"));
12918-
12919-        ((void (*)(id, SEL, id))objc_msgSend)(
12920-            self, sel_registerName("registerForDraggedTypes:"),
12921-            ((id (*)(Class, SEL, id))objc_msgSend)(
12922-                objc_getClass("NSArray"),
12923-                sel_registerName("arrayWithObject:"),
12924-                ((id (*)(Class, SEL, const char*))objc_msgSend)(
12925-                    objc_getClass("NSString"),
12926-                    sel_registerName("stringWithUTF8String:"),
12927-                    "public.url"
12928-                )
12929-            )
12930-        );
12931-    }
12932-
12933-    return self;
12934-}
12935-
12936-static u32 RGFW_OnClose(id self) {
12937-	RGFW_window* win = NULL;
12938-	object_getInstanceVariable(self, (const char*)"RGFW_window", (void**)&win);
12939-	if (win == NULL) return true;
12940-
12941-	RGFW_windowCloseCallback(win);
12942-	return false;
12943-}
12944-
12945-/* NOTE(EimaMei): Fixes the constant clicking when the app is running under a terminal. */
12946-static bool RGFW__osxAcceptsFirstResponder(void) { return true; }
12947-static bool RGFW__osxPerformKeyEquivalent(id event) { RGFW_UNUSED(event); return true; }
12948-
12949-static NSDragOperation RGFW__osxDraggingEntered(id self, SEL sel, id sender) {
12950-	RGFW_UNUSED(sel);
12951-
12952-	RGFW_window* win = NULL;
12953-	object_getInstanceVariable(self, "RGFW_window", (void**)&win);
12954-	if (win == NULL)
12955-		return 0;
12956-
12957-	NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(sender, sel_registerName("draggingLocation"));
12958-	RGFW_dataDragCallback(win, RGFW_dataFile, RGFW_dndActionEnter, (i32) p.x, (i32) (win->h - p.y));
12959-	return NSDragOperationCopy;
12960-}
12961-static NSDragOperation RGFW__osxDraggingUpdated(id self, SEL sel, id sender) {
12962-	RGFW_UNUSED(sel);
12963-
12964-	RGFW_window* win = NULL;
12965-	object_getInstanceVariable(self, "RGFW_window", (void**)&win);
12966-	if (win == NULL)
12967-		return 0;
12968-	if (!(win->internal.enabledEvents & RGFW_dataDragFlag)) return NSDragOperationCopy;
12969-
12970-	NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(sender, sel_registerName("draggingLocation"));
12971-	RGFW_dataDragCallback(win, RGFW_dataFile, RGFW_dndActionMove, (i32) p.x, (i32) (win->h - p.y));
12972-	return NSDragOperationCopy;
12973-}
12974-static bool RGFW__osxPrepareForDragOperation(id self) {
12975-	RGFW_window* win = NULL;
12976-	object_getInstanceVariable(self, "RGFW_window", (void**)&win);
12977-	if (win == NULL || (!(win->internal.enabledEvents & RGFW_dataDropFlag)))
12978-		return true;
12979-
12980-	if (!(win->internal.flags & RGFW_windowAllowDND)) {
12981-		return false;
12982-	}
12983-
12984-	return true;
12985-}
12986-
12987-static void RGFW__osxDraggingEnded(id self, SEL sel, id sender) {
12988-	RGFW_UNUSED(sel);
12989-
12990-	RGFW_window* win = NULL;
12991-	object_getInstanceVariable(self, "RGFW_window", (void**)&win);
12992-	if (win == NULL)
12993-		return;
12994-	if (!(win->internal.enabledEvents & RGFW_dataDragFlag)) return;
12995-
12996-	NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(sender, sel_registerName("draggingLocation"));
12997-	RGFW_dataDragCallback(win, RGFW_dataFile, RGFW_dndActionExit, (i32) p.x, (i32) (win->h - p.y));
12998-	return;
12999-}
13000-
13001-static bool RGFW__osxPerformDragOperation(id self, SEL sel, id sender) {
13002-	RGFW_UNUSED(sender); RGFW_UNUSED(self); RGFW_UNUSED(sel);
13003-	RGFW_window* win = NULL;
13004-	object_getInstanceVariable(self, "RGFW_window", (void**)&win);
13005-	if (win == NULL || (!(win->internal.enabledEvents & RGFW_dataDropFlag)))
13006-		return false;
13007-
13008-	/* id pasteBoard = objc_msgSend_id(sender, sel_registerName("draggingPasteboard")); */
13009-
13010-	id pasteBoard = objc_msgSend_id(sender, sel_registerName("draggingPasteboard"));
13011-
13012-	/* Get the types of data available on the pasteboard */
13013-	id types = objc_msgSend_id(pasteBoard, sel_registerName("types"));
13014-
13015-	/* Get the string type for file URLs */
13016-	id fileURLsType = objc_msgSend_class_char(objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), "NSFilenamesPboardType");
13017-
13018-	/* Check if the pasteboard contains file URLs */
13019-	if (objc_msgSend_id_bool(types, sel_registerName("containsObject:"), fileURLsType) == 0) {
13020-		RGFW_debugCallback(RGFW_typeError, RGFW_errClipboard, "No files found on the pasteboard.");
13021-		return 0;
13022-	}
13023-
13024-	id fileURLs = objc_msgSend_id_id(pasteBoard, sel_registerName("propertyListForType:"), fileURLsType);
13025-	int count = ((int (*)(id, SEL))objc_msgSend)(fileURLs, sel_registerName("count"));
13026-
13027-	if (count == 0)
13028-		return 0;
13029-
13030-	u32 i;
13031-    for (i = 0; i < (u32)count; i++) {
13032-		id fileURL = objc_msgSend_arr(fileURLs, sel_registerName("objectAtIndex:"), i);
13033-		const char *filePath = ((const char* (*)(id, SEL))objc_msgSend)(fileURL, sel_registerName("UTF8String"));
13034-		int string_count = ((int (*)(id, SEL))objc_msgSend)(fileURL, sel_registerName("count"));
13035-
13036-		RGFW_dataDropCallback(win, filePath, (size_t)string_count + 1, RGFW_dataFile);
13037-	}
13038-
13039-	return false;
13040-}
13041-
13042-#ifndef RGFW_NO_IOKIT
13043-#include <IOKit/IOKitLib.h>
13044-
13045-float RGFW_osx_getFallbackRefreshRate(CGDirectDisplayID displayID);
13046-float RGFW_osx_getFallbackRefreshRate(CGDirectDisplayID displayID) {
13047-    float refreshRate = 0;
13048-    io_iterator_t it;
13049-    io_service_t service;
13050-    CFNumberRef indexRef, clockRef, countRef;
13051-    u32 clock, count;
13052-
13053-#ifdef kIOMainPortDefault
13054-    if (IOServiceGetMatchingServices(kIOMainPortDefault, IOServiceMatching("IOFramebuffer"), &it) != 0)
13055-#elif defined(kIOMasterPortDefault)
13056-    if (IOServiceGetMatchingServices(kIOMainPortDefault, IOServiceMatching("IOFramebuffer"), &it) != 0)
13057-#endif
13058-        return RGFW_FALSE;
13059-
13060-    while ((service = IOIteratorNext(it)) != 0) {
13061-        u32 index;
13062-        indexRef = (CFNumberRef)IORegistryEntryCreateCFProperty(service, CFSTR("IOFramebufferOpenGLIndex"), kCFAllocatorDefault, kNilOptions);
13063-        if (indexRef == 0) continue;
13064-
13065-        if (CFNumberGetValue(indexRef, kCFNumberIntType, &index) && CGOpenGLDisplayMaskToDisplayID(1 << index) == displayID) {
13066-            CFRelease(indexRef);
13067-            break;
13068-        }
13069-
13070-        CFRelease(indexRef);
13071-    }
13072-
13073-    if (service) {
13074-        clockRef = (CFNumberRef)IORegistryEntryCreateCFProperty(service, CFSTR("IOFBCurrentPixelClock"), kCFAllocatorDefault, kNilOptions);
13075-        if (clockRef) {
13076-            if (CFNumberGetValue(clockRef, kCFNumberIntType, &clock) && clock) {
13077-                countRef = (CFNumberRef)IORegistryEntryCreateCFProperty(service, CFSTR("IOFBCurrentPixelCount"), kCFAllocatorDefault, kNilOptions);
13078-                if (countRef && CFNumberGetValue(countRef, kCFNumberIntType, &count) && count) {
13079-					refreshRate = (float)((double)clock / (double) count);
13080-                    CFRelease(countRef);
13081-                }
13082-            }
13083-            CFRelease(clockRef);
13084-        }
13085-    }
13086-
13087-    IOObjectRelease(it);
13088-    return refreshRate;
13089-}
13090-#endif
13091-
13092-void RGFW_moveToMacOSResourceDir(void) {
13093-	char resourcesPath[256];
13094-
13095-	CFBundleRef bundle = CFBundleGetMainBundle();
13096-	if (!bundle)
13097-		return;
13098-
13099-	CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(bundle);
13100-	CFStringRef last = CFURLCopyLastPathComponent(resourcesURL);
13101-
13102-	if (
13103-		CFStringCompare(CFSTR("Resources"), last, 0) != kCFCompareEqualTo ||
13104-		CFURLGetFileSystemRepresentation(resourcesURL, true, (u8*) resourcesPath, 255) == 0
13105-		) {
13106-		CFRelease(last);
13107-		CFRelease(resourcesURL);
13108-		return;
13109-	}
13110-
13111-	CFRelease(last);
13112-	CFRelease(resourcesURL);
13113-
13114-	chdir(resourcesPath);
13115-}
13116-
13117-static void RGFW__osxDidChangeScreenParameters(id self, SEL _cmd, id notification) {
13118-	RGFW_UNUSED(self); RGFW_UNUSED(_cmd); RGFW_UNUSED(notification);
13119-	RGFW_pollMonitors();
13120-}
13121-
13122-static void RGFW__osxWindowDeminiaturize(id self, SEL sel) {
13123-	RGFW_UNUSED(sel);
13124-	RGFW_window* win = NULL;
13125-	object_getInstanceVariable(self, "RGFW_window", (void**)&win);
13126-	if (win == NULL) return;
13127-
13128-	RGFW_windowRestoredCallback(win, win->x, win->y, win->w, win->h);
13129-
13130-}
13131-static void RGFW__osxWindowMiniaturize(id self, SEL sel) {
13132-	RGFW_UNUSED(sel);
13133-	RGFW_window* win = NULL;
13134-	object_getInstanceVariable(self, "RGFW_window", (void**)&win);
13135-	if (win == NULL) return;
13136-
13137-	RGFW_windowMinimizedCallback(win);
13138-
13139-}
13140-
13141-static void RGFW__osxWindowBecameKey(id self, SEL sel) {
13142-	RGFW_UNUSED(sel);
13143-	RGFW_window* win = NULL;
13144-	object_getInstanceVariable(self, "RGFW_window", (void**)&win);
13145-	if (win == NULL) return;
13146-
13147-	RGFW_windowFocusCallback(win, RGFW_TRUE);
13148-}
13149-
13150-static void RGFW__osxWindowResignKey(id self, SEL sel) {
13151-	RGFW_UNUSED(sel);
13152-	RGFW_window* win = NULL;
13153-	object_getInstanceVariable(self, "RGFW_window", (void**)&win);
13154-	if (win == NULL) return;
13155-
13156-	RGFW_windowFocusCallback(win, RGFW_FALSE);
13157-}
13158-
13159-static void RGFW__osxDidWindowResize(id self, SEL _cmd, id notification) {
13160-	RGFW_UNUSED(_cmd); RGFW_UNUSED(notification);
13161-	RGFW_window* win = NULL;
13162-	object_getInstanceVariable(self, "RGFW_window", (void**)&win);
13163-	if (win == NULL) return;
13164-
13165-	NSRect frame;
13166-	if (win->src.view) frame = ((NSRect(*)(id, SEL))abi_objc_msgSend_stret)((id)win->src.view, sel_registerName("frame"));
13167-	else return;
13168-
13169-	if (frame.size.width == 0 || frame.size.height == 0) return;
13170-	win->w = (i32)frame.size.width;
13171-	win->h = (i32)frame.size.height;
13172-
13173-	RGFW_monitor* mon = RGFW_window_getMonitor(win);
13174-	if (mon == NULL) return;
13175-
13176-	if ((i32)mon->mode.w == win->w && (i32)mon->mode.h - 102 <= win->h) {
13177-		RGFW_windowMaximizedCallback(win, 0, 0, win->w, win->h);
13178-	} else if (win->internal.flags & RGFW_windowMaximize) {
13179-		RGFW_windowRestoredCallback(win, win->x, win->y, win->w, win->h);
13180-	}
13181-
13182-	RGFW_windowResizedCallback(win, win->w, win->h);
13183-}
13184-
13185-static void RGFW__osxWindowMove(id self, SEL sel) {
13186-	RGFW_UNUSED(sel);
13187-	RGFW_window* win = NULL;
13188-	object_getInstanceVariable(self, "RGFW_window", (void**)&win);
13189-	if (win == NULL) return;
13190-
13191-	NSRect frame = ((NSRect(*)(id, SEL))abi_objc_msgSend_stret)((id)win->src.window, sel_registerName("frame"));
13192-	NSRect content = ((NSRect(*)(id, SEL, NSRect))abi_objc_msgSend_stret)((id)win->src.window, sel_registerName("contentRectForFrameRect:"), frame);
13193-
13194-	float y = RGFW_cocoaYTransform((float)(content.origin.y + content.size.height - 1));
13195-
13196-	RGFW_windowMovedCallback(win, (i32)content.origin.x, (i32)y);
13197-}
13198-
13199-static void RGFW__osxViewDidChangeBackingProperties(id self, SEL _cmd) {
13200-	RGFW_UNUSED(_cmd);
13201-	RGFW_window* win = NULL;
13202-	object_getInstanceVariable(self, "RGFW_window", (void**)&win);
13203-	if (win == NULL) return;
13204-
13205-	RGFW_monitor* mon = RGFW_window_getMonitor(win);
13206-	if (mon == NULL) return;
13207-
13208-	RGFW_scaleUpdatedCallback(win, mon->scaleX, mon->scaleY);
13209-}
13210-
13211-static BOOL RGFW__osxWantsUpdateLayer(id self, SEL _cmd) { RGFW_UNUSED(self); RGFW_UNUSED(_cmd); return YES; }
13212-
13213-static void RGFW__osxUpdateLayer(id self, SEL _cmd) {
13214-	RGFW_UNUSED(self); RGFW_UNUSED(_cmd);
13215-	RGFW_window* win = NULL;
13216-	object_getInstanceVariable(self, "RGFW_window", (void**)&win);
13217-	if (win == NULL) return;
13218-	RGFW_windowRefreshCallback(win, 0, 0, win->w, win->h);
13219-}
13220-
13221-static void RGFW__osxDrawRect(id self, SEL _cmd, CGRect rect) {
13222-	RGFW_UNUSED(rect); RGFW_UNUSED(_cmd);
13223-	RGFW_window* win = NULL;
13224-	object_getInstanceVariable(self, "RGFW_window", (void**)&win);
13225-	if (win == NULL) return;
13226-
13227-	RGFW_windowRefreshCallback(win, 0, 0, win->w, win->h);
13228-}
13229-
13230-static void RGFW__osxMouseEntered(id self, SEL _cmd, id event) {
13231-	RGFW_UNUSED(_cmd);
13232-	RGFW_window* win = NULL;
13233-    object_getInstanceVariable(self, "RGFW_window", (void**)&win);
13234-    if (win == NULL) return;
13235-
13236-    NSPoint p = ((NSPoint(*)(id, SEL))objc_msgSend)(event, sel_registerName("locationInWindow"));
13237-    RGFW_mouseNotifyCallback(win, (i32)p.x, (i32)(win->h - p.y), 1);
13238-}
13239-
13240-static void RGFW__osxMouseExited(id self, SEL _cmd, id event) {
13241-	RGFW_UNUSED(_cmd); RGFW_UNUSED(event);
13242-	RGFW_window* win = NULL;
13243-    object_getInstanceVariable(self, "RGFW_window", (void**)&win);
13244-    if (win == NULL) return;
13245-
13246-	RGFW_mouseNotifyCallback(win, win->internal.lastMouseX, win->internal.lastMouseY, RGFW_FALSE);
13247-}
13248-
13249-static void RGFW__osxKeyDown(id self, SEL _cmd, id event) {
13250-	RGFW_UNUSED(_cmd);
13251-	RGFW_window* win = NULL;
13252-    object_getInstanceVariable(self, "RGFW_window", (void**)&win);
13253-	if (win == NULL || !(win->internal.enabledEvents & RGFW_keyPressedFlag)) return;
13254-
13255-    u32 key = (u16)((u32(*)(id, SEL))objc_msgSend)(event, sel_registerName("keyCode"));
13256-
13257-	RGFW_key value = (u8)RGFW_apiKeyToRGFW(key);
13258-	RGFW_bool repeat = RGFW_isKeyDown(value);
13259-
13260-    RGFW_keyCallback(win, value, win->internal.mod, repeat, 1);
13261-
13262-	id nsstring = ((id(*)(id, SEL))objc_msgSend)(event, sel_registerName("charactersIgnoringModifiers"));
13263-    const char* string = NSString_to_char(nsstring);
13264-	size_t count = (size_t)((int (*)(id, SEL))objc_msgSend)(nsstring, sel_registerName("length"));
13265-
13266-	for (size_t index = 0; index < count;
13267-			RGFW_keyCharCallback(win, RGFW_decodeUTF8(&string[index], &index))
13268-		);
13269-}
13270-
13271-static void RGFW__osxKeyUp(id self, SEL _cmd, id event) {
13272-	RGFW_UNUSED(_cmd);
13273-	RGFW_window* win = NULL;
13274-    object_getInstanceVariable(self, "RGFW_window", (void**)&win);
13275-    if (win == NULL || !(win->internal.enabledEvents & RGFW_keyReleasedFlag)) return;
13276-
13277-    u32 key = (u16)((u32(*)(id, SEL))objc_msgSend)(event, sel_registerName("keyCode"));
13278-
13279-    RGFW_key value = (u8)RGFW_apiKeyToRGFW(key);
13280-
13281-    RGFW_keyCallback(win, value, win->internal.mod, RGFW_FALSE, 0);
13282-}
13283-
13284-static void RGFW__osxFlagsChanged(id self, SEL _cmd, id event) {
13285-	RGFW_UNUSED(_cmd);
13286-    RGFW_window* win = NULL;
13287-    object_getInstanceVariable(self, "RGFW_window", (void**)&win);
13288-    if (win == NULL) return;
13289-
13290-	RGFW_key value = 0;
13291-	RGFW_bool pressed = RGFW_FALSE;
13292-
13293-    u32 flags = (u32)((u32(*)(id, SEL))objc_msgSend)(event, sel_registerName("modifierFlags"));
13294-    RGFW_keyUpdateKeyModsEx(win,
13295-                          ((u32)(flags & NSEventModifierFlagCapsLock) % 255),
13296-                          ((flags & NSEventModifierFlagNumericPad) % 255),
13297-                          ((flags & NSEventModifierFlagControl) % 255),
13298-                          ((flags & NSEventModifierFlagOption) % 255),
13299-                          ((flags & NSEventModifierFlagShift) % 255),
13300-                          ((flags & NSEventModifierFlagCommand) % 255), 0);
13301-    u8 i;
13302-    for (i = 0; i < 9; i++)
13303-        _RGFW->keyboard[i + RGFW_keyCapsLock].prev = _RGFW->keyboard[i + RGFW_keyCapsLock].current;
13304-
13305-    for (i = 0; i < 5; i++) {
13306-        u32 shift = (1 << (i + 16));
13307-        RGFW_key key = i + RGFW_keyCapsLock;
13308-        if ((flags & shift) && !RGFW_isKeyDown((u8)key)) {
13309-			pressed = RGFW_TRUE;
13310-            value = (u8)key;
13311-            break;
13312-        }
13313-        if (!(flags & shift) && RGFW_isKeyDown((u8)key)) {
13314-			pressed = RGFW_FALSE;
13315-            value = (u8)key;
13316-            break;
13317-        }
13318-    }
13319-
13320-	RGFW_keyCallback(win, value, win->internal.mod, RGFW_isKeyDown(value) && pressed, pressed);
13321-
13322-	if (value != RGFW_keyCapsLock) {
13323-		RGFW_keyCallback(win, value + 4, win->internal.mod, RGFW_isKeyDown(value + 4) && pressed, pressed);
13324-	}
13325-
13326-}
13327-
13328-static void RGFW__osxMouseMoved(id self, SEL _cmd, id event) {
13329-	RGFW_UNUSED(_cmd);
13330-    RGFW_window* win = NULL;
13331-    object_getInstanceVariable(self, "RGFW_window", (void**)&win);
13332-	if (win == NULL) return;
13333-
13334-    NSPoint p = ((NSPoint(*)(id, SEL))objc_msgSend)(event, sel_registerName("locationInWindow"));
13335-
13336-	CGFloat vecX = ((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(event, sel_registerName("deltaX"));
13337-    CGFloat vecY = ((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(event, sel_registerName("deltaY"));
13338-
13339-    RGFW_mousePosCallback(win, (i32)p.x, (i32)(win->h - p.y));
13340-	RGFW_rawMotionCallback(win, (float)vecX, (float)vecY);
13341-}
13342-
13343-static void RGFW__osxMouseDown(id self, SEL _cmd, id event) {
13344-	RGFW_UNUSED(_cmd);
13345-    RGFW_window* win = NULL;
13346-    object_getInstanceVariable(self, "RGFW_window", (void**)&win);
13347-    if (win == NULL) return;
13348-
13349-    u32 buttonNumber = (u32)((u32(*)(id, SEL))objc_msgSend)(event, sel_registerName("buttonNumber"));
13350-
13351-	RGFW_mouseButton value = 0;
13352-    switch (buttonNumber) {
13353-        case 0: value = RGFW_mouseLeft; break;
13354-        case 1: value = RGFW_mouseRight; break;
13355-        case 2: value = RGFW_mouseMiddle; break;
13356-        default: value = (u8)buttonNumber;
13357-    }
13358-
13359-    RGFW_mouseButtonCallback(win, value, 1);
13360-}
13361-
13362-static void RGFW__osxMouseUp(id self, SEL _cmd, id event) {
13363-	RGFW_UNUSED(_cmd);
13364-    RGFW_window* win = NULL;
13365-    object_getInstanceVariable(self, "RGFW_window", (void**)&win);
13366-    if (win == NULL) return;
13367-
13368-    u32 buttonNumber = (u32)((u32(*)(id, SEL))objc_msgSend)(event, sel_registerName("buttonNumber"));
13369-
13370-	RGFW_mouseButton value = 0;
13371-	switch (buttonNumber) {
13372-        case 0: value = RGFW_mouseLeft; break;
13373-        case 1: value = RGFW_mouseRight; break;
13374-        case 2: value = RGFW_mouseMiddle; break;
13375-        default: value = (u8)buttonNumber;
13376-    }
13377-
13378-    RGFW_mouseButtonCallback(win, value, 0);
13379-}
13380-
13381-static void RGFW__osxScrollWheel(id self, SEL _cmd, id event) {
13382-	RGFW_UNUSED(_cmd);
13383-    RGFW_window* win = NULL;
13384-    object_getInstanceVariable(self, "RGFW_window", (void**)&win);
13385-    if (win == NULL) return;
13386-
13387-    float deltaX = (float)((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(event, sel_registerName("deltaX"));
13388-	float deltaY = (float)((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(event, sel_registerName("deltaY"));
13389-
13390-    RGFW_mouseScrollCallback(win, deltaX, deltaY);
13391-}
13392-
13393-RGFW_format RGFW_nativeFormat(void) { return RGFW_formatRGBA8; }
13394-
13395-RGFW_bool RGFW_createSurfacePtr(u8* data, i32 w, i32 h, RGFW_format format, RGFW_surface* surface) {
13396-	surface->data = data;
13397-	surface->w = w;
13398-	surface->h = h;
13399-	surface->format = format;
13400-	surface->native.format = RGFW_formatRGBA8;
13401-
13402-	surface->native.buffer = (u8*)RGFW_ALLOC((size_t)(w * h * 4));
13403-	return RGFW_TRUE;
13404-}
13405-
13406-void RGFW_surface_freePtr(RGFW_surface* surface) {
13407-	RGFW_FREE(surface->native.buffer);
13408-}
13409-
13410-void RGFW_window_blitSurface(RGFW_window* win, RGFW_surface* surface) {
13411-	id pool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc"));
13412-	pool = objc_msgSend_id(pool, sel_registerName("init"));
13413-
13414-	int minW = RGFW_MIN(win->w, surface->w);
13415-	int minH = RGFW_MIN(win->h, surface->h);
13416-
13417-	RGFW_monitor* mon = RGFW_window_getMonitor(win);
13418-	if (mon == NULL) return;
13419-
13420-	minW =  (i32)((float)minW * mon->pixelRatio);
13421-	minH = (i32)((float)minH * mon->pixelRatio);
13422-
13423-	surface->native.rep = (void*)NSBitmapImageRep_initWithBitmapData(&surface->native.buffer, minW, minH, 8, 4, true, false, "NSDeviceRGBColorSpace", 1 << 1, (u32)surface->w * 4, 32);
13424-
13425-	id image = ((id (*)(Class, SEL))objc_msgSend)(objc_getClass("NSImage"), sel_getUid("alloc"));
13426-	NSSize size = (NSSize){(double)minW, (double)minH};
13427-	image = ((id (*)(id, SEL, NSSize))objc_msgSend)((id)image, sel_getUid("initWithSize:"), size);
13428-
13429-	RGFW_copyImageData(NSBitmapImageRep_bitmapData((id)surface->native.rep), surface->w, minH, RGFW_formatRGBA8, surface->data, surface->native.format, surface->convertFunc);
13430-	((void (*)(id, SEL, id))objc_msgSend)((id)image, sel_getUid("addRepresentation:"), (id)surface->native.rep);
13431-
13432-	id layer = ((id (*)(id, SEL))objc_msgSend)((id)win->src.view, sel_getUid("layer"));
13433-	((void (*)(id, SEL, id))objc_msgSend)(layer, sel_getUid("setContents:"), (id)image);
13434-
13435-	NSRelease(image);
13436-	NSRelease(surface->native.rep);
13437-
13438-	objc_msgSend_bool_void(pool, sel_registerName("drain"));
13439-}
13440-
13441-void* RGFW_window_getView_OSX(RGFW_window* win) { return win->src.view; }
13442-
13443-void RGFW_window_setLayer_OSX(RGFW_window* win, void* layer) {
13444-	objc_msgSend_void_id((id)win->src.view, sel_registerName("setLayer:"), (id)layer);
13445-}
13446-
13447-void* RGFW_getLayer_OSX(void) {
13448-	return objc_msgSend_class((id)objc_getClass("CAMetalLayer"), (SEL)sel_registerName("layer"));
13449-}
13450-void* RGFW_window_getWindow_OSX(RGFW_window* win) { return win->src.window; }
13451-
13452-void RGFW_initKeycodesPlatform(void) {
13453-	_RGFW->keycodes[0x1D] = RGFW_key0;
13454-	_RGFW->keycodes[0x12] = RGFW_key1;
13455-	_RGFW->keycodes[0x13] = RGFW_key2;
13456-	_RGFW->keycodes[0x14] = RGFW_key3;
13457-	_RGFW->keycodes[0x15] = RGFW_key4;
13458-	_RGFW->keycodes[0x17] = RGFW_key5;
13459-	_RGFW->keycodes[0x16] = RGFW_key6;
13460-	_RGFW->keycodes[0x1A] = RGFW_key7;
13461-	_RGFW->keycodes[0x1C] = RGFW_key8;
13462-	_RGFW->keycodes[0x19] = RGFW_key9;
13463-	_RGFW->keycodes[0x00] = RGFW_keyA;
13464-	_RGFW->keycodes[0x0B] = RGFW_keyB;
13465-	_RGFW->keycodes[0x08] = RGFW_keyC;
13466-	_RGFW->keycodes[0x02] = RGFW_keyD;
13467-	_RGFW->keycodes[0x0E] = RGFW_keyE;
13468-	_RGFW->keycodes[0x03] = RGFW_keyF;
13469-	_RGFW->keycodes[0x05] = RGFW_keyG;
13470-	_RGFW->keycodes[0x04] = RGFW_keyH;
13471-	_RGFW->keycodes[0x22] = RGFW_keyI;
13472-	_RGFW->keycodes[0x26] = RGFW_keyJ;
13473-	_RGFW->keycodes[0x28] = RGFW_keyK;
13474-	_RGFW->keycodes[0x25] = RGFW_keyL;
13475-	_RGFW->keycodes[0x2E] = RGFW_keyM;
13476-	_RGFW->keycodes[0x2D] = RGFW_keyN;
13477-	_RGFW->keycodes[0x1F] = RGFW_keyO;
13478-	_RGFW->keycodes[0x23] = RGFW_keyP;
13479-	_RGFW->keycodes[0x0C] = RGFW_keyQ;
13480-	_RGFW->keycodes[0x0F] = RGFW_keyR;
13481-	_RGFW->keycodes[0x01] = RGFW_keyS;
13482-	_RGFW->keycodes[0x11] = RGFW_keyT;
13483-	_RGFW->keycodes[0x20] = RGFW_keyU;
13484-	_RGFW->keycodes[0x09] = RGFW_keyV;
13485-	_RGFW->keycodes[0x0D] = RGFW_keyW;
13486-	_RGFW->keycodes[0x07] = RGFW_keyX;
13487-	_RGFW->keycodes[0x10] = RGFW_keyY;
13488-	_RGFW->keycodes[0x06] = RGFW_keyZ;
13489-	_RGFW->keycodes[0x27] = RGFW_keyApostrophe;
13490-	_RGFW->keycodes[0x2A] = RGFW_keyBackSlash;
13491-	_RGFW->keycodes[0x2B] = RGFW_keyComma;
13492-	_RGFW->keycodes[0x18] = RGFW_keyEquals;
13493-	_RGFW->keycodes[0x32] = RGFW_keyBacktick;
13494-	_RGFW->keycodes[0x21] = RGFW_keyBracket;
13495-	_RGFW->keycodes[0x1B] = RGFW_keyMinus;
13496-	_RGFW->keycodes[0x2F] = RGFW_keyPeriod;
13497-	_RGFW->keycodes[0x1E] = RGFW_keyCloseBracket;
13498-	_RGFW->keycodes[0x29] = RGFW_keySemicolon;
13499-	_RGFW->keycodes[0x2C] = RGFW_keySlash;
13500-	_RGFW->keycodes[0x0A] = RGFW_keyWorld1;
13501-	_RGFW->keycodes[0x33] = RGFW_keyBackSpace;
13502-	_RGFW->keycodes[0x39] = RGFW_keyCapsLock;
13503-	_RGFW->keycodes[0x75] = RGFW_keyDelete;
13504-	_RGFW->keycodes[0x7D] = RGFW_keyDown;
13505-	_RGFW->keycodes[0x77] = RGFW_keyEnd;
13506-	_RGFW->keycodes[0x24] = RGFW_keyEnter;
13507-	_RGFW->keycodes[0x35] = RGFW_keyEscape;
13508-	_RGFW->keycodes[0x7A] = RGFW_keyF1;
13509-	_RGFW->keycodes[0x78] = RGFW_keyF2;
13510-	_RGFW->keycodes[0x63] = RGFW_keyF3;
13511-	_RGFW->keycodes[0x76] = RGFW_keyF4;
13512-	_RGFW->keycodes[0x60] = RGFW_keyF5;
13513-	_RGFW->keycodes[0x61] = RGFW_keyF6;
13514-	_RGFW->keycodes[0x62] = RGFW_keyF7;
13515-	_RGFW->keycodes[0x64] = RGFW_keyF8;
13516-	_RGFW->keycodes[0x65] = RGFW_keyF9;
13517-	_RGFW->keycodes[0x6D] = RGFW_keyF10;
13518-	_RGFW->keycodes[0x67] = RGFW_keyF11;
13519-	_RGFW->keycodes[0x6F] = RGFW_keyF12;
13520-	_RGFW->keycodes[0x69] = RGFW_keyPrintScreen;
13521-	_RGFW->keycodes[0x6B] = RGFW_keyF14;
13522-	_RGFW->keycodes[0x71] = RGFW_keyF15;
13523-	_RGFW->keycodes[0x6A] = RGFW_keyF16;
13524-	_RGFW->keycodes[0x40] = RGFW_keyF17;
13525-	_RGFW->keycodes[0x4F] = RGFW_keyF18;
13526-	_RGFW->keycodes[0x50] = RGFW_keyF19;
13527-	_RGFW->keycodes[0x5A] = RGFW_keyF20;
13528-	_RGFW->keycodes[0x73] = RGFW_keyHome;
13529-	_RGFW->keycodes[0x72] = RGFW_keyInsert;
13530-	_RGFW->keycodes[0x7B] = RGFW_keyLeft;
13531-	_RGFW->keycodes[0x3A] = RGFW_keyAltL;
13532-	_RGFW->keycodes[0x3B] = RGFW_keyControlL;
13533-	_RGFW->keycodes[0x38] = RGFW_keyShiftL;
13534-	_RGFW->keycodes[0x37] = RGFW_keySuperL;
13535-	_RGFW->keycodes[0x6E] = RGFW_keyMenu;
13536-	_RGFW->keycodes[0x47] = RGFW_keyNumLock;
13537-	_RGFW->keycodes[0x79] = RGFW_keyPageDown;
13538-	_RGFW->keycodes[0x74] = RGFW_keyPageUp;
13539-	_RGFW->keycodes[0x7C] = RGFW_keyRight;
13540-	_RGFW->keycodes[0x3D] = RGFW_keyAltR;
13541-	_RGFW->keycodes[0x3E] = RGFW_keyControlR;
13542-	_RGFW->keycodes[0x3C] = RGFW_keyShiftR;
13543-	_RGFW->keycodes[0x36] = RGFW_keySuperR;
13544-	_RGFW->keycodes[0x31] = RGFW_keySpace;
13545-	_RGFW->keycodes[0x30] = RGFW_keyTab;
13546-	_RGFW->keycodes[0x7E] = RGFW_keyUp;
13547-	_RGFW->keycodes[0x52] = RGFW_keyPad0;
13548-	_RGFW->keycodes[0x53] = RGFW_keyPad1;
13549-	_RGFW->keycodes[0x54] = RGFW_keyPad2;
13550-	_RGFW->keycodes[0x55] = RGFW_keyPad3;
13551-	_RGFW->keycodes[0x56] = RGFW_keyPad4;
13552-	_RGFW->keycodes[0x57] = RGFW_keyPad5;
13553-	_RGFW->keycodes[0x58] = RGFW_keyPad6;
13554-	_RGFW->keycodes[0x59] = RGFW_keyPad7;
13555-	_RGFW->keycodes[0x5B] = RGFW_keyPad8;
13556-	_RGFW->keycodes[0x5C] = RGFW_keyPad9;
13557-	_RGFW->keycodes[0x45] = RGFW_keyPadSlash;
13558-	_RGFW->keycodes[0x41] = RGFW_keyPadPeriod;
13559-	_RGFW->keycodes[0x4B] = RGFW_keyPadSlash;
13560-	_RGFW->keycodes[0x4C] = RGFW_keyPadReturn;
13561-	_RGFW->keycodes[0x51] = RGFW_keyPadEqual;
13562-	_RGFW->keycodes[0x43] = RGFW_keyPadMultiply;
13563-	_RGFW->keycodes[0x4E] = RGFW_keyPadMinus;
13564-}
13565-
13566-i32 RGFW_initPlatform(void) {
13567-	_RGFW->tisBundle = (void*)CFBundleGetBundleWithIdentifier(CFSTR("com.apple.HIToolbox"));
13568-
13569-	TISGetInputSourcePropertySrc = (PFN_TISGetInputSourceProperty)CFBundleGetFunctionPointerForName((CFBundleRef)_RGFW->tisBundle, CFSTR("TISGetInputSourceProperty"));
13570-	TISCopyCurrentKeyboardLayoutInputSourceSrc = (PFN_TISCopyCurrentKeyboardLayoutInputSource)CFBundleGetFunctionPointerForName((CFBundleRef)_RGFW->tisBundle, CFSTR("TISCopyCurrentKeyboardLayoutInputSource"));
13571-	LMGetKbdTypeSrc = (PFN_LMGetKbdType)CFBundleGetFunctionPointerForName((CFBundleRef)_RGFW->tisBundle, CFSTR("LMGetKbdType"));
13572-
13573-	CFStringRef* cfStr = (CFStringRef*)CFBundleGetDataPointerForName((CFBundleRef)_RGFW->tisBundle, CFSTR("kTISPropertyUnicodeKeyLayoutData"));;
13574-	if (cfStr) kTISPropertyUnicodeKeyLayoutDataSrc = *cfStr;
13575-
13576-	class_addMethod(objc_getClass("NSObject"), sel_registerName("windowShouldClose:"), (IMP)(void*)RGFW_OnClose, 0);
13577-
13578-	/* NOTE(EimaMei): Fixes the 'Boop' sfx from constantly playing each time you click a key. Only a problem when running in the terminal. */
13579-	class_addMethod(objc_getClass("NSWindowClass"), sel_registerName("acceptsFirstResponder:"), (IMP)(void*)RGFW__osxAcceptsFirstResponder, 0);
13580-	class_addMethod(objc_getClass("NSWindowClass"), sel_registerName("performKeyEquivalent:"), (IMP)(void*)RGFW__osxPerformKeyEquivalent, 0);
13581-
13582-	_RGFW->NSApp = objc_msgSend_id(objc_getClass("NSApplication"), sel_registerName("sharedApplication"));
13583-
13584-	NSRetain(_RGFW->NSApp);
13585-
13586-	_RGFW->customNSAppDelegateClass = objc_allocateClassPair(objc_getClass("NSObject"), "RGFWNSAppDelegate", 0);
13587-	class_addMethod((Class)_RGFW->customNSAppDelegateClass, sel_registerName("applicationDidChangeScreenParameters:"), (IMP)RGFW__osxDidChangeScreenParameters, "v@:@");
13588-	objc_registerClassPair((Class)_RGFW->customNSAppDelegateClass);
13589-	_RGFW->customNSAppDelegate = objc_msgSend_id(NSAlloc(_RGFW->customNSAppDelegateClass), sel_registerName("init"));
13590-
13591-	objc_msgSend_void_id(_RGFW->NSApp, sel_registerName("setDelegate:"), _RGFW->customNSAppDelegate);
13592-
13593-	((void (*)(id, SEL, NSUInteger))objc_msgSend) ((id)_RGFW->NSApp, sel_registerName("setActivationPolicy:"), NSApplicationActivationPolicyRegular);
13594-
13595-	_RGFW->customViewClasses[0] = objc_allocateClassPair(objc_getClass("NSView"), "RGFWCustomView", 0);
13596-	_RGFW->customViewClasses[1] = objc_allocateClassPair(objc_getClass("NSOpenGLView"), "RGFWOpenGLCustomView", 0);
13597-	for (size_t i = 0; i < 2; i++) {
13598-		class_addIvar((Class)_RGFW->customViewClasses[i], "RGFW_window", sizeof(RGFW_window*), sizeof(RGFW_window*), "L");
13599-		class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("drawRect:"), (IMP)RGFW__osxDrawRect, "v@:{CGRect=ffff}");
13600-		class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("viewDidChangeBackingProperties"), (IMP)RGFW__osxViewDidChangeBackingProperties, "v@:");
13601-		class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("mouseDown:"), (IMP)RGFW__osxMouseDown, "v@:@");
13602-		class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("rightMouseDown:"), (IMP)RGFW__osxMouseDown, "v@:@");
13603-		class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("otherMouseDown:"), (IMP)RGFW__osxMouseDown, "v@:@");
13604-		class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("mouseUp:"), (IMP)RGFW__osxMouseUp, "v@:@");
13605-		class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("rightMouseUp:"), (IMP)RGFW__osxMouseUp, "v@:@");
13606-		class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("otherMouseUp:"), (IMP)RGFW__osxMouseUp, "v@:@");
13607-		class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("scrollWheel:"), (IMP)RGFW__osxScrollWheel, "v@:@");
13608-		class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("mouseDragged:"), (IMP)RGFW__osxMouseMoved, "v@:@");
13609-		class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("rightMouseDragged:"), (IMP)RGFW__osxMouseMoved, "v@:@");
13610-		class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("otherMouseDragged:"), (IMP)RGFW__osxMouseMoved, "v@:@");
13611-		class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("keyDown:"), (IMP)RGFW__osxKeyDown, "v@:@");
13612-		class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("keyUp:"), (IMP)RGFW__osxKeyUp, "v@:@");
13613-		class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("mouseMoved:"), (IMP)RGFW__osxMouseMoved, "v@:@");
13614-		class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("mouseEntered:"), (IMP)RGFW__osxMouseEntered, "v@:@");
13615-		class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("mouseExited:"), (IMP)RGFW__osxMouseExited, "v@:@");
13616-		class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("flagsChanged:"), (IMP)RGFW__osxFlagsChanged, "v@:@");
13617-		class_addMethod((Class)_RGFW->customViewClasses[i], sel_getUid("acceptsFirstResponder"), (IMP)RGFW__osxAcceptsFirstResponder, "B@:");
13618-		class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("initWithRGFWWindow:"), (IMP)RGFW__osxCustomInitWithRGFWWindow, "@@:{CGRect={CGPoint=dd}{CGSize=dd}}");
13619-		class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("wantsUpdateLayer"), (IMP)RGFW__osxWantsUpdateLayer, "B@:");
13620-		class_addMethod((Class)_RGFW->customViewClasses[i], sel_registerName("updateLayer"), (IMP)RGFW__osxUpdateLayer, "v@:");
13621-		objc_registerClassPair((Class)_RGFW->customViewClasses[i]);
13622-	}
13623-
13624-	_RGFW->customWindowDelegateClass = objc_allocateClassPair(objc_getClass("NSObject"), "RGFWWindowDelegate", 0);
13625-	class_addIvar((Class)_RGFW->customWindowDelegateClass, "RGFW_window", sizeof(RGFW_window*), sizeof(RGFW_window*), "L");
13626-	class_addMethod((Class)_RGFW->customWindowDelegateClass, sel_registerName("windowDidResize:"), (IMP)RGFW__osxDidWindowResize, "v@:@");
13627-	class_addMethod((Class)_RGFW->customWindowDelegateClass, sel_registerName("windowDidMove:"), (IMP) RGFW__osxWindowMove, "");
13628-	class_addMethod((Class)_RGFW->customWindowDelegateClass, sel_registerName("windowDidMiniaturize:"), (IMP) RGFW__osxWindowMiniaturize, "");
13629-	class_addMethod((Class)_RGFW->customWindowDelegateClass, sel_registerName("windowDidDeminiaturize:"), (IMP) RGFW__osxWindowDeminiaturize, "");
13630-	class_addMethod((Class)_RGFW->customWindowDelegateClass, sel_registerName("windowDidBecomeKey:"), (IMP) RGFW__osxWindowBecameKey, "");
13631-	class_addMethod((Class)_RGFW->customWindowDelegateClass, sel_registerName("windowDidResignKey:"), (IMP) RGFW__osxWindowResignKey, "");
13632-	class_addMethod((Class)_RGFW->customWindowDelegateClass, sel_registerName("draggingEntered:"), (IMP)RGFW__osxDraggingEntered, "l@:@");
13633-	class_addMethod((Class)_RGFW->customWindowDelegateClass, sel_registerName("draggingUpdated:"), (IMP)RGFW__osxDraggingUpdated, "l@:@");
13634-	class_addMethod((Class)_RGFW->customWindowDelegateClass, sel_registerName("draggingExited:"), (IMP)RGFW__osxDraggingEnded, "v@:@");
13635-	class_addMethod((Class)_RGFW->customWindowDelegateClass, sel_registerName("draggingEnded:"), (IMP)RGFW__osxDraggingEnded, "v@:@");
13636-	class_addMethod((Class)_RGFW->customWindowDelegateClass, sel_registerName("prepareForDragOperation:"), (IMP)RGFW__osxPrepareForDragOperation, "B@:@");
13637-	class_addMethod((Class)_RGFW->customWindowDelegateClass, sel_registerName("performDragOperation:"), (IMP)RGFW__osxPerformDragOperation, "B@:@");
13638-	objc_registerClassPair((Class)_RGFW->customWindowDelegateClass);
13639-	return 0;
13640-}
13641-
13642-void RGFW_osx_initView(RGFW_window* win) {
13643-	NSRect contentRect;
13644-	contentRect.origin.x = 0;
13645-	contentRect.origin.y = 0;
13646-	contentRect.size.width = (double)win->w;
13647-	contentRect.size.height = (double)win->h;
13648-	((void(*)(id, SEL, CGRect))objc_msgSend)((id)win->src.view, sel_registerName("setFrame:"), contentRect);
13649-
13650-
13651-	if (RGFW_COCOA_FRAME_NAME)
13652-		objc_msgSend_ptr(win->src.view, sel_registerName("setFrameAutosaveName:"), RGFW_COCOA_FRAME_NAME);
13653-
13654-	object_setInstanceVariable((id)win->src.view, "RGFW_window", win);
13655-	objc_msgSend_void_id((id)win->src.window, sel_registerName("setContentView:"), win->src.view);
13656-	objc_msgSend_void_bool(win->src.view, sel_registerName("setWantsLayer:"), true);
13657-	objc_msgSend_int((id)win->src.view, sel_registerName("setLayerContentsPlacement:"),  4);
13658-
13659-	id trackingArea = objc_msgSend_id(objc_getClass("NSTrackingArea"), sel_registerName("alloc"));
13660-	trackingArea = ((id (*)(id, SEL, NSRect, NSUInteger, id, id))objc_msgSend)(
13661-		trackingArea,
13662-		sel_registerName("initWithRect:options:owner:userInfo:"),
13663-		contentRect,
13664-		NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways | NSTrackingInVisibleRect,
13665-		(id)win->src.view,
13666-		nil
13667-	);
13668-
13669-	((void (*)(id, SEL, id))objc_msgSend)((id)win->src.view, sel_registerName("addTrackingArea:"), trackingArea);
13670-	((void (*)(id, SEL))objc_msgSend)(trackingArea, sel_registerName("release"));
13671-}
13672-
13673-RGFW_window* RGFW_createWindowPlatform(const char* name, RGFW_windowFlags flags, RGFW_window* win) {
13674-	/* RR Create an autorelease pool */
13675-	id pool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc"));
13676-	pool = objc_msgSend_id(pool, sel_registerName("init"));
13677-
13678-	RGFW_window_setMouseDefault(win);
13679-
13680-	NSRect windowRect;
13681-	windowRect.origin.x = (double)win->x;
13682-	windowRect.origin.y = (double)RGFW_cocoaYTransform((float)(win->y + win->h - 1));
13683-	windowRect.size.width = (double)win->w;
13684-	windowRect.size.height = (double)win->h;
13685-	NSBackingStoreType macArgs = (NSBackingStoreType)(NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSBackingStoreBuffered | NSWindowStyleMaskTitled);
13686-
13687-	if (!(flags & RGFW_windowNoResize))
13688-		macArgs = (NSBackingStoreType)(macArgs | (NSBackingStoreType)NSWindowStyleMaskResizable);
13689-	if (!(flags & RGFW_windowNoBorder))
13690-		macArgs = (NSBackingStoreType)(macArgs | (NSBackingStoreType)NSWindowStyleMaskTitled);
13691-	{
13692-		void* nsclass = objc_getClass("NSWindow");
13693-		SEL func = sel_registerName("initWithContentRect:styleMask:backing:defer:");
13694-
13695-		win->src.window = ((id(*)(id, SEL, NSRect, NSWindowStyleMask, NSBackingStoreType, bool))objc_msgSend)
13696-			(NSAlloc(nsclass), func, windowRect, (NSWindowStyleMask)macArgs, macArgs, false);
13697-	}
13698-
13699-	id str = NSString_stringWithUTF8String(name);
13700-	objc_msgSend_void_id((id)win->src.window, sel_registerName("setTitle:"), str);
13701-
13702-	win->src.delegate = (void*)objc_msgSend_id(NSAlloc((Class)_RGFW->customWindowDelegateClass), sel_registerName("init"));
13703-	object_setInstanceVariable((id)win->src.delegate, "RGFW_window", win);
13704-
13705-	objc_msgSend_void_id((id)win->src.window, sel_registerName("setDelegate:"), (id)win->src.delegate);
13706-
13707-	if (flags & RGFW_windowAllowDND) {
13708-		win->internal.flags |= RGFW_windowAllowDND;
13709-
13710-		NSPasteboardType types[] = {NSPasteboardTypeURL, NSPasteboardTypeFileURL, NSPasteboardTypeString};
13711-		NSregisterForDraggedTypes((id)win->src.window, types, 3);
13712-	}
13713-
13714-	objc_msgSend_void_bool((id)win->src.window, sel_registerName("setAcceptsMouseMovedEvents:"), true);
13715-
13716-	if (flags & RGFW_windowTransparent) {
13717-		objc_msgSend_void_bool(win->src.window, sel_registerName("setOpaque:"), false);
13718-
13719-		objc_msgSend_void_id((id)win->src.window, sel_registerName("setBackgroundColor:"),
13720-		NSColor_colorWithSRGB(0, 0, 0, 0));
13721-	}
13722-
13723-	/* Show the window */
13724-	objc_msgSend_void_bool((id)_RGFW->NSApp, sel_registerName("activateIgnoringOtherApps:"), true);
13725-
13726-	if (_RGFW->root == NULL) {
13727-		objc_msgSend_void(win->src.window, sel_registerName("makeMainWindow"));
13728-	}
13729-
13730-	objc_msgSend_void(win->src.window, sel_registerName("makeKeyWindow"));
13731-
13732-	NSRetain(win->src.window);
13733-
13734-	win->src.view = ((id(*)(id, SEL, RGFW_window*))objc_msgSend) (NSAlloc((Class)_RGFW->customViewClasses[0]), sel_registerName("initWithRGFWWindow:"), win);
13735-	return win;
13736-}
13737-
13738-void RGFW_window_setBorder(RGFW_window* win, RGFW_bool border) {
13739-	NSRect frame = ((NSRect(*)(id, SEL))abi_objc_msgSend_stret)((id)win->src.window, sel_registerName("frame"));
13740-	NSRect content = ((NSRect(*)(id, SEL))abi_objc_msgSend_stret)((id)win->src.view, sel_registerName("frame"));
13741-	double offset = 0;
13742-
13743-	RGFW_setBit(&win->internal.flags, RGFW_windowNoBorder, !border);
13744-	NSBackingStoreType storeType = (NSBackingStoreType)(NSWindowStyleMaskBorderless | NSWindowStyleMaskFullSizeContentView);
13745-	if (border)
13746-		storeType = (NSBackingStoreType)(NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable);
13747-	if (!(win->internal.flags & RGFW_windowNoResize)) {
13748-		storeType = (NSBackingStoreType)(storeType | (NSBackingStoreType)NSWindowStyleMaskResizable);
13749-	}
13750-
13751-	((void (*)(id, SEL, NSBackingStoreType))objc_msgSend)((id)win->src.window, sel_registerName("setStyleMask:"), storeType);
13752-
13753-	if (!border) {
13754-		id miniaturizeButton = objc_msgSend_int((id)win->src.window, sel_registerName("standardWindowButton:"),  NSWindowMiniaturizeButton);
13755-		id titleBarView = objc_msgSend_id(miniaturizeButton, sel_registerName("superview"));
13756-		objc_msgSend_void_bool(titleBarView, sel_registerName("setHidden:"), true);
13757-
13758-		offset = (double)(frame.size.height - content.size.height);
13759-	}
13760-
13761-	RGFW_window_resize(win, win->w, win->h + (i32)offset);
13762-	win->h -= (i32)offset;
13763-}
13764-
13765-RGFW_bool RGFW_getGlobalMouse(i32* x, i32* y) {
13766-	RGFW_ASSERT(_RGFW->root != NULL);
13767-
13768-	CGEventRef e = CGEventCreate(NULL);
13769-	CGPoint point = CGEventGetLocation(e);
13770-	CFRelease(e);
13771-
13772-	if (x) *x = (i32)point.x;
13773-	if (y) *y = (i32)point.y;
13774-	return RGFW_TRUE;
13775-}
13776-
13777-void RGFW_stopCheckEvents(void) {
13778-	id eventPool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc"));
13779-	eventPool = objc_msgSend_id(eventPool, sel_registerName("init"));
13780-
13781-	id e = (id) ((id(*)(Class, SEL, NSEventType, NSPoint, NSEventModifierFlags, void*, NSInteger, void**, short, NSInteger, NSInteger))objc_msgSend)
13782-		(objc_getClass("NSEvent"), sel_registerName("otherEventWithType:location:modifierFlags:timestamp:windowNumber:context:subtype:data1:data2:"),
13783-			NSEventTypeApplicationDefined, (NSPoint){0, 0}, (NSEventModifierFlags)0, NULL, (NSInteger)0, NULL, 0, 0, 0);
13784-
13785-	((void (*)(id, SEL, id, bool))objc_msgSend)
13786-		((id)_RGFW->NSApp, sel_registerName("postEvent:atStart:"), e, 1);
13787-
13788-	objc_msgSend_bool_void(eventPool, sel_registerName("drain"));
13789-}
13790-
13791-void RGFW_waitForEvent(i32 waitMS) {
13792-	id eventPool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc"));
13793-	eventPool = objc_msgSend_id(eventPool, sel_registerName("init"));
13794-
13795-	void* date = (void*) ((id(*)(Class, SEL, double))objc_msgSend)
13796-				(objc_getClass("NSDate"), sel_registerName("dateWithTimeIntervalSinceNow:"), waitMS);
13797-
13798-	SEL eventFunc = sel_registerName("nextEventMatchingMask:untilDate:inMode:dequeue:");
13799-	id e = (id) ((id(*)(id, SEL, NSEventMask, void*, id, bool))objc_msgSend)
13800-		((id)_RGFW->NSApp, eventFunc,
13801-			ULONG_MAX, date, NSString_stringWithUTF8String("kCFRunLoopDefaultMode"), true);
13802-
13803-	if (e) {
13804-		((void (*)(id, SEL, id, bool))objc_msgSend)
13805-			((id)_RGFW->NSApp, sel_registerName("postEvent:atStart:"), e, 1);
13806-	}
13807-
13808-	objc_msgSend_bool_void(eventPool, sel_registerName("drain"));
13809-}
13810-
13811-RGFW_key RGFW_physicalToMappedKey(RGFW_key key) {
13812-    u16 keycode = (u16)RGFW_rgfwToApiKey(key);
13813-    TISInputSourceRef source = TISCopyCurrentKeyboardLayoutInputSource();
13814-    if (source == NULL)
13815-        return key;
13816-
13817-    CFDataRef layoutData = TISGetInputSourceProperty(source, kTISPropertyUnicodeKeyLayoutDataSrc);
13818-
13819-    if (layoutData == NULL) {
13820-        CFRelease(source);
13821-        return key;
13822-    }
13823-
13824-    UCKeyboardLayout *layout = (UCKeyboardLayout*)(void*)CFDataGetBytePtr(layoutData);
13825-
13826-    UInt32 deadKeyState = 0;
13827-    UniChar chars[4];
13828-    UniCharCount len = 0;
13829-	u32 type =  LMGetKbdType();
13830-	OSStatus status = UCKeyTranslate(layout, keycode, kUCKeyActionDown, 0, type, kUCKeyTranslateNoDeadKeysBit, &deadKeyState, 4, &len, chars );
13831-
13832-    CFRelease(source);
13833-
13834-    if (status == noErr && len == 1 && chars[0] < 256) {
13835-        return (RGFW_key)chars[0];
13836-    }
13837-
13838-	return key;
13839-}
13840-
13841-RGFW_bool RGFW_window_fetchSize(RGFW_window* win, i32* w, i32* h) {
13842-	NSRect content = ((NSRect(*)(id, SEL))abi_objc_msgSend_stret)((id)win->src.view, sel_registerName("frame"));
13843-
13844-	win->w = (i32)content.size.width;
13845-	win->h = (i32)content.size.height;
13846-
13847-	return RGFW_window_getSize(win, w, h);
13848-}
13849-
13850-void RGFW_pollEvents(void) {
13851-	RGFW_resetPrevState();
13852-
13853-	id eventPool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc"));
13854-	eventPool = objc_msgSend_id(eventPool, sel_registerName("init"));
13855-	SEL eventFunc = sel_registerName("nextEventMatchingMask:untilDate:inMode:dequeue:");
13856-
13857-	while (1) {
13858-		void* date = NULL;
13859-		id e = (id) ((id(*)(id, SEL, NSEventMask, void*, id, bool))objc_msgSend)
13860-			((id)_RGFW->NSApp, eventFunc, ULONG_MAX, date, NSString_stringWithUTF8String("kCFRunLoopDefaultMode"), true);
13861-
13862-		if (e == NULL) {
13863-			break;
13864-		}
13865-
13866-		objc_msgSend_void_id((id)_RGFW->NSApp, sel_registerName("sendEvent:"), e);
13867-	}
13868-
13869-	objc_msgSend_bool_void(eventPool, sel_registerName("drain"));
13870-}
13871-
13872-
13873-void RGFW_window_move(RGFW_window* win, i32 x, i32 y) {
13874-	RGFW_ASSERT(win != NULL);
13875-
13876-	NSRect content = ((NSRect(*)(id, SEL))abi_objc_msgSend_stret)((id)win->src.view, sel_registerName("frame"));
13877-
13878-	win->x = x;
13879-	win->y = (i32)RGFW_cocoaYTransform((float)y + (float)content.size.height - 1.0f);
13880-
13881-	((void(*)(id,SEL,NSPoint))objc_msgSend)((id)win->src.window, sel_registerName("setFrameOrigin:"), (NSPoint){(double)x, (double)y});
13882-}
13883-
13884-void RGFW_window_resize(RGFW_window* win, i32 w, i32 h) {
13885-	RGFW_ASSERT(win != NULL);
13886-
13887-	NSRect frame = ((NSRect(*)(id, SEL))abi_objc_msgSend_stret)((id)win->src.window, sel_registerName("frame"));
13888-	NSRect content = ((NSRect(*)(id, SEL))abi_objc_msgSend_stret)((id)win->src.view, sel_registerName("frame"));
13889-	float offset = (float)(frame.size.height - content.size.height);
13890-
13891-	win->w = w;
13892-	win->h = h;
13893-
13894-
13895-	((void(*)(id, SEL, CGRect))objc_msgSend)((id)win->src.view, sel_registerName("setFrame:"),  (NSRect){{0, 0}, {(double)win->w, (double)win->h}});
13896-	((void(*)(id, SEL, NSRect, bool, bool))objc_msgSend)
13897-		((id)win->src.window, sel_registerName("setFrame:display:animate:"), (NSRect){{(double)win->x, (double)win->y}, {(double)win->w, (double)win->h + (double)offset}}, true, true);
13898-}
13899-
13900-void RGFW_window_focus(RGFW_window* win) {
13901-	RGFW_ASSERT(win);
13902-	objc_msgSend_void_bool((id)_RGFW->NSApp, sel_registerName("activateIgnoringOtherApps:"), true);
13903-	((void (*)(id, SEL))objc_msgSend)((id)win->src.window, sel_registerName("makeKeyWindow"));
13904-}
13905-
13906-void RGFW_window_raise(RGFW_window* win) {
13907-	RGFW_ASSERT(win != NULL);
13908-	((id(*)(id, SEL, SEL))objc_msgSend)((id)win->src.window, sel_registerName("orderFront:"), (SEL)NULL);
13909-    	objc_msgSend_void_id(win->src.window, sel_registerName("setLevel:"), kCGNormalWindowLevelKey);
13910-}
13911-
13912-void RGFW_window_setFullscreen(RGFW_window* win, RGFW_bool fullscreen) {
13913-	RGFW_ASSERT(win != NULL);
13914-	if (fullscreen && (win->internal.flags & RGFW_windowFullscreen)) return;
13915-	if (!fullscreen && !(win->internal.flags & RGFW_windowFullscreen)) return;
13916-
13917-	if (fullscreen) {
13918-		win->internal.oldX = win->x;
13919-		win->internal.oldY = win->y;
13920-		win->internal.oldW = win->w;
13921-		win->internal.oldH = win->h;
13922-
13923-		win->internal.flags |= RGFW_windowFullscreen;
13924-
13925-		RGFW_monitor* mon = RGFW_window_getMonitor(win);
13926-		RGFW_monitor_scaleToWindow(mon, win);
13927-
13928-		RGFW_window_setBorder(win, RGFW_FALSE);
13929-
13930-		if (mon != NULL) {
13931-			win->x = mon->x;
13932-			win->y = mon->y;
13933-			win->w = mon->mode.w;
13934-			win->h = mon->mode.h;
13935-			RGFW_window_resize(win, mon->mode.w, mon->mode.h);
13936-			RGFW_window_move(win, mon->x, mon->y);
13937-		}
13938-
13939-		((id(*)(id, SEL, SEL))objc_msgSend)((id)win->src.window, sel_registerName("orderFront:"), (SEL)NULL);
13940-		objc_msgSend_void_id(win->src.window, sel_registerName("setLevel:"), 25);
13941-	}
13942-
13943-	objc_msgSend_void_SEL(win->src.window, sel_registerName("toggleFullScreen:"), NULL);
13944-
13945-	if (!fullscreen) {
13946-		win->x  = win->internal.oldX;
13947-		win->y  = win->internal.oldY;
13948-		win->w  = win->internal.oldW;
13949-		win->h = win->internal.oldH;
13950-		win->internal.flags &= ~(u32)RGFW_windowFullscreen;
13951-
13952-		RGFW_window_resize(win, win->w, win->h);
13953-		RGFW_window_move(win, win->x, win->y);
13954-	}
13955-}
13956-
13957-void RGFW_window_maximize(RGFW_window* win) {
13958-	RGFW_ASSERT(win != NULL);
13959-	if (RGFW_window_isMaximized(win)) return;
13960-
13961-	win->internal.flags |= RGFW_windowMaximize;
13962-	objc_msgSend_void_SEL(win->src.window, sel_registerName("zoom:"), NULL);
13963-	RGFW_window_fetchSize(win, NULL, NULL);
13964-}
13965-
13966-void RGFW_window_minimize(RGFW_window* win) {
13967-	RGFW_ASSERT(win != NULL);
13968-	objc_msgSend_void_SEL(win->src.window, sel_registerName("performMiniaturize:"), NULL);
13969-}
13970-
13971-void RGFW_window_setFloating(RGFW_window* win, RGFW_bool floating) {
13972-    RGFW_ASSERT(win != NULL);
13973-    if (floating) objc_msgSend_void_id(win->src.window, sel_registerName("setLevel:"), kCGFloatingWindowLevelKey);
13974-    else 		  objc_msgSend_void_id(win->src.window, sel_registerName("setLevel:"), kCGNormalWindowLevelKey);
13975-}
13976-
13977-void RGFW_window_setOpacity(RGFW_window* win, u8 opacity) {
13978-	objc_msgSend_int(win->src.window, sel_registerName("setAlphaValue:"), opacity);
13979-	objc_msgSend_void_bool(win->src.window, sel_registerName("setOpaque:"), (opacity < (u8)255));
13980-
13981-	if (opacity)
13982-		objc_msgSend_void_id((id)win->src.window, sel_registerName("setBackgroundColor:"), NSColor_colorWithSRGB(0, 0, 0, opacity));
13983-
13984-}
13985-
13986-void RGFW_window_restore(RGFW_window* win) {
13987-	RGFW_ASSERT(win != NULL);
13988-
13989-	if (RGFW_window_isMaximized(win))
13990-		objc_msgSend_void_SEL(win->src.window, sel_registerName("zoom:"), NULL);
13991-
13992-	objc_msgSend_void_SEL(win->src.window, sel_registerName("deminiaturize:"), NULL);
13993-	RGFW_window_show(win);
13994-}
13995-
13996-RGFW_bool RGFW_window_isFloating(RGFW_window* win) {
13997-	RGFW_ASSERT(win != NULL);
13998-	int level = ((int (*)(id, SEL))objc_msgSend) ((id)(win->src.window), (SEL)sel_registerName("level"));
13999-	return level > kCGNormalWindowLevelKey;
14000-}
14001-
14002-void RGFW_window_setName(RGFW_window* win, const char* name) {
14003-	RGFW_ASSERT(win != NULL);
14004-	if (name == NULL) name = "\0";
14005-
14006-	id str = NSString_stringWithUTF8String(name);
14007-	objc_msgSend_void_id((id)win->src.window, sel_registerName("setTitle:"), str);
14008-}
14009-
14010-#ifndef RGFW_NO_PASSTHROUGH
14011-void RGFW_window_setMousePassthrough(RGFW_window* win, RGFW_bool passthrough) {
14012-	objc_msgSend_void_bool(win->src.window, sel_registerName("setIgnoresMouseEvents:"), passthrough);
14013-}
14014-#endif
14015-
14016-void RGFW_window_setAspectRatio(RGFW_window* win, i32 w, i32 h) {
14017-	if (w == 0 && h == 0) {  w = 1; h = 1; };
14018-
14019-	((void (*)(id, SEL, NSSize))objc_msgSend)
14020-		((id)win->src.window, sel_registerName("setContentAspectRatio:"), (NSSize){(CGFloat)w, (CGFloat)h});
14021-}
14022-
14023-void RGFW_window_setMinSize(RGFW_window* win, i32 w, i32 h) {
14024-	((void (*)(id, SEL, NSSize))objc_msgSend) ((id)win->src.window, sel_registerName("setMinSize:"), (NSSize){(CGFloat)w, (CGFloat)h});
14025-}
14026-
14027-void RGFW_window_setMaxSize(RGFW_window* win, i32 w, i32 h) {
14028-	if (w == 0 && h == 0) {
14029-		RGFW_monitor* mon = RGFW_window_getMonitor(win);
14030-		if (mon != NULL) {
14031-			w = mon->mode.w;
14032-			h = mon->mode.h;
14033-		}
14034-	}
14035-
14036-	((void (*)(id, SEL, NSSize))objc_msgSend)
14037-		((id)win->src.window, sel_registerName("setMaxSize:"), (NSSize){(CGFloat)w, (CGFloat)h});
14038-}
14039-
14040-RGFW_bool RGFW_window_setIconEx(RGFW_window* win, u8* data, i32 w, i32 h, RGFW_format format, RGFW_icon type) {
14041-	RGFW_ASSERT(win != NULL);
14042-	RGFW_UNUSED(type);
14043-
14044-	id pool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc"));
14045-	pool = objc_msgSend_id(pool, sel_registerName("init"));
14046-
14047-	if (data == NULL) {
14048-		objc_msgSend_void_id((id)_RGFW->NSApp, sel_registerName("setApplicationIconImage:"), NULL);
14049-		objc_msgSend_bool_void(pool, sel_registerName("drain"));
14050-		return RGFW_TRUE;
14051-	}
14052-
14053-	id representation = NSBitmapImageRep_initWithBitmapData(NULL, w, h, 8, (NSInteger)4, true, false, "NSCalibratedRGBColorSpace", 1 << 1, w * 4, 32);
14054-	RGFW_copyImageData(NSBitmapImageRep_bitmapData(representation), w, h, RGFW_formatRGBA8, data, format, NULL);
14055-
14056-	id dock_image = ((id(*)(id, SEL, NSSize))objc_msgSend) (NSAlloc((id)objc_getClass("NSImage")), sel_registerName("initWithSize:"), ((NSSize){(CGFloat)w, (CGFloat)h}));
14057-
14058-	objc_msgSend_void_id(dock_image, sel_registerName("addRepresentation:"), representation);
14059-
14060-	objc_msgSend_void_id((id)_RGFW->NSApp, sel_registerName("setApplicationIconImage:"), dock_image);
14061-
14062-	NSRelease(dock_image);
14063-	NSRelease(representation);
14064-
14065-	objc_msgSend_bool_void(pool, sel_registerName("drain"));
14066-
14067-	return RGFW_TRUE;
14068-}
14069-
14070-id NSCursor_arrowStr(const char* str);
14071-id NSCursor_arrowStr(const char* str) {
14072-	void* nclass = objc_getClass("NSCursor");
14073-	SEL func = sel_registerName(str);
14074-	id mouse = (id) objc_msgSend_id(nclass, func);
14075-	NSRetain(mouse);
14076-	return mouse;
14077-}
14078-
14079-RGFW_mouse* RGFW_createMouseStandard(RGFW_mouseIcon mouse) {
14080-	switch (mouse) {
14081-        case RGFW_mouseNormal: return NSCursor_arrowStr("arrowCursor");
14082-        case RGFW_mouseArrow: return NSCursor_arrowStr("arrowCursor");
14083-        case RGFW_mouseIbeam: return NSCursor_arrowStr("IBeamCursor");
14084-        case RGFW_mouseCrosshair: return NSCursor_arrowStr("crosshairCursor");
14085-        case RGFW_mousePointingHand: return NSCursor_arrowStr("pointingHandCursor");
14086-        case RGFW_mouseResizeEW: return NSCursor_arrowStr("resizeLeftRightCursor");
14087-        case RGFW_mouseResizeE: return NSCursor_arrowStr("resizeLeftRightCursor");
14088-        case RGFW_mouseResizeW: return NSCursor_arrowStr("resizeLeftRightCursor");
14089-        case RGFW_mouseResizeNS: return NSCursor_arrowStr("resizeUpDownCursor");
14090-        case RGFW_mouseResizeN: return NSCursor_arrowStr("resizeUpDownCursor");
14091-        case RGFW_mouseResizeS: return NSCursor_arrowStr("resizeUpDownCursor");
14092-        case RGFW_mouseResizeNWSE: return NSCursor_arrowStr("_windowResizeNorthWestSouthEastCursor");
14093-        case RGFW_mouseResizeNW: return NSCursor_arrowStr("_windowResizeNorthWestSouthEastCursor");
14094-        case RGFW_mouseResizeSE: return NSCursor_arrowStr("_windowResizeNorthWestSouthEastCursor");
14095-        case RGFW_mouseResizeNESW: return NSCursor_arrowStr("_windowResizeNorthEastSouthWestCursor");
14096-        case RGFW_mouseResizeNE: return NSCursor_arrowStr("_windowResizeNorthEastSouthWestCursor");
14097-        case RGFW_mouseResizeSW: return NSCursor_arrowStr("_windowResizeNorthEastSouthWestCursor");
14098-        case RGFW_mouseResizeAll: return NSCursor_arrowStr("openHandCursor");
14099-        case RGFW_mouseNotAllowed: return NSCursor_arrowStr("operationNotAllowedCursor");
14100-        case RGFW_mouseWait: return NSCursor_arrowStr("arrowCursor");
14101-        case RGFW_mouseProgress: return NSCursor_arrowStr("arrowCursor");
14102-        default: return NULL;
14103-    }
14104-	return NULL;
14105-}
14106-
14107-RGFW_mouse* RGFW_createMouse(u8* data, i32 w, i32 h, RGFW_format format) {
14108-	id pool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc"));
14109-	pool = objc_msgSend_id(pool, sel_registerName("init"));
14110-
14111-	if (data == NULL) {
14112-		objc_msgSend_void(NSCursor_arrowStr("arrowCursor"), sel_registerName("set"));
14113-
14114-		objc_msgSend_bool_void(pool, sel_registerName("drain"));
14115-		return NULL;
14116-	}
14117-
14118-	id representation = (id)NSBitmapImageRep_initWithBitmapData(NULL, w, h, 8, (NSInteger)4, true, false, "NSCalibratedRGBColorSpace", 1 << 1, w * 4, 32);
14119-	RGFW_copyImageData(NSBitmapImageRep_bitmapData(representation), w, h, RGFW_formatRGBA8, data, format, NULL);
14120-
14121-	id cursor_image = ((id(*)(id, SEL, NSSize))objc_msgSend) (NSAlloc((id)objc_getClass("NSImage")), sel_registerName("initWithSize:"), ((NSSize){(CGFloat)w, (CGFloat)h}));
14122-
14123-	objc_msgSend_void_id(cursor_image, sel_registerName("addRepresentation:"), representation);
14124-
14125-	id cursor = (id) ((id(*)(id, SEL, id, NSPoint))objc_msgSend)
14126-		(NSAlloc(objc_getClass("NSCursor")),  sel_registerName("initWithImage:hotSpot:"), cursor_image, (NSPoint){0.0, 0.0});
14127-
14128-	NSRelease(cursor_image);
14129-	NSRelease(representation);
14130-
14131-	objc_msgSend_bool_void(pool, sel_registerName("drain"));
14132-
14133-	return (void*)cursor;
14134-}
14135-
14136-RGFW_bool RGFW_window_setMousePlatform(RGFW_window* win, RGFW_mouse* mouse) {
14137-	RGFW_ASSERT(win != NULL); RGFW_ASSERT(mouse);
14138-	CGDisplayShowCursor(kCGDirectMainDisplay);
14139-	objc_msgSend_void((id)mouse, sel_registerName("set"));
14140-	win->src.mouse = mouse;
14141-	return RGFW_TRUE;
14142-}
14143-
14144-void RGFW_freeMouse(RGFW_mouse* mouse) {
14145-	RGFW_ASSERT(mouse);
14146-	NSRelease((id)mouse);
14147-}
14148-
14149-void RGFW_window_showMouse(RGFW_window* win, RGFW_bool show) {
14150-	RGFW_window_showMouseFlags(win, show);
14151-	if (show)   CGDisplayShowCursor(kCGDirectMainDisplay);
14152-	else        CGDisplayHideCursor(kCGDirectMainDisplay);
14153-}
14154-
14155-void RGFW_window_setRawMouseModePlatform(RGFW_window* win, RGFW_bool state) {
14156-	RGFW_UNUSED(win); RGFW_UNUSED(state);
14157-}
14158-
14159-void RGFW_window_captureMousePlatform(RGFW_window* win, RGFW_bool state) {
14160-	RGFW_UNUSED(win);
14161-	CGAssociateMouseAndMouseCursorPosition(!(state == RGFW_TRUE));
14162-}
14163-
14164-void RGFW_window_moveMouse(RGFW_window* win, i32 x, i32 y) {
14165-	RGFW_UNUSED(win);
14166-
14167-	win->internal.lastMouseX = x - win->x;
14168-	win->internal.lastMouseY = y - win->y;
14169-	CGWarpMouseCursorPosition((CGPoint){(CGFloat)x, (CGFloat)y});
14170-}
14171-
14172-
14173-void RGFW_window_hide(RGFW_window* win) {
14174-	objc_msgSend_void_bool(win->src.window, sel_registerName("setIsVisible:"), false);
14175-}
14176-
14177-void RGFW_window_show(RGFW_window* win) {
14178-	if (win->internal.flags & RGFW_windowFocusOnShow)
14179-		((id(*)(id, SEL, SEL))objc_msgSend)((id)win->src.window, sel_registerName("makeKeyAndOrderFront:"), NULL);
14180-
14181-	((id(*)(id, SEL, SEL))objc_msgSend)((id)win->src.window, sel_registerName("orderFront:"), NULL);
14182-	objc_msgSend_void_bool(win->src.window, sel_registerName("setIsVisible:"), true);
14183-}
14184-
14185-void RGFW_window_flash(RGFW_window* win, RGFW_flashRequest request) {
14186-	if (RGFW_window_isInFocus(win) && request) {
14187-		return;
14188-	}
14189-
14190-	id pool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc"));
14191-	pool = objc_msgSend_id(pool, sel_registerName("init"));
14192-
14193-	if (_RGFW->flash) {
14194-		((void (*)(id, SEL, NSInteger))objc_msgSend) ((id)_RGFW->NSApp, sel_registerName("cancelUserAttentionRequest:"), _RGFW->flash);
14195-	}
14196-
14197-	switch (request) {
14198-		case RGFW_flashBriefly:
14199-			_RGFW->flash = ((NSInteger (*)(id, SEL, NSInteger))objc_msgSend) ((id)_RGFW->NSApp, sel_registerName("requestUserAttention:"), NSInformationalRequest);
14200-			break;
14201-		case RGFW_flashUntilFocused:
14202-			_RGFW->flash = ((NSInteger (*)(id, SEL, NSInteger))objc_msgSend) ((id)_RGFW->NSApp, sel_registerName("requestUserAttention:"), NSCriticalRequest);
14203-			break;
14204-		default: break;
14205-	}
14206-
14207-	objc_msgSend_bool_void(pool, sel_registerName("drain"));
14208-}
14209-
14210-RGFW_bool RGFW_window_isHidden(RGFW_window* win) {
14211-	RGFW_ASSERT(win != NULL);
14212-
14213-	bool visible = objc_msgSend_bool(win->src.window, sel_registerName("isVisible"));
14214-	return visible == NO && !RGFW_window_isMinimized(win);
14215-}
14216-
14217-RGFW_bool RGFW_window_isMinimized(RGFW_window* win) {
14218-	RGFW_ASSERT(win != NULL);
14219-
14220-	return objc_msgSend_bool(win->src.window, sel_registerName("isMiniaturized")) == YES;
14221-}
14222-
14223-RGFW_bool RGFW_window_isMaximized(RGFW_window* win) {
14224-	RGFW_ASSERT(win != NULL);
14225-	RGFW_bool b = (RGFW_bool)objc_msgSend_bool(win->src.window, sel_registerName("isZoomed"));
14226-	return b;
14227-}
14228-
14229-RGFWDEF id RGFW_getNSScreenForDisplayUInt(u32 uintNum);
14230-id RGFW_getNSScreenForDisplayUInt(u32 uintNum) {
14231-	Class NSScreenClass = objc_getClass("NSScreen");
14232-
14233-	id screens = objc_msgSend_id(NSScreenClass, sel_registerName("screens"));
14234-
14235-	NSUInteger count = (NSUInteger)objc_msgSend_uint(screens, sel_registerName("count"));
14236-    NSUInteger i;
14237-	for (i = 0; i < count; i++) {
14238-		id screen = ((id (*)(id, SEL, int))objc_msgSend) (screens, sel_registerName("objectAtIndex:"), (int)i);
14239-		id description = objc_msgSend_id(screen, sel_registerName("deviceDescription"));
14240-		id screenNumberKey = NSString_stringWithUTF8String("NSScreenNumber");
14241-		id screenNumber = objc_msgSend_id_id(description, sel_registerName("objectForKey:"), screenNumberKey);
14242-
14243-		if (CGDisplayUnitNumber((CGDirectDisplayID)objc_msgSend_uint(screenNumber, sel_registerName("unsignedIntValue"))) == uintNum) {
14244-			return screen;
14245-		}
14246-	}
14247-
14248-	return NULL;
14249-}
14250-
14251-float RGFW_osx_getRefreshRate(CGDirectDisplayID display, CGDisplayModeRef mode);
14252-float RGFW_osx_getRefreshRate(CGDirectDisplayID display, CGDisplayModeRef mode) {
14253-	if (mode) {
14254-		float refreshRate = (float)CGDisplayModeGetRefreshRate(mode);
14255-		if (refreshRate != 0)  return refreshRate;
14256-	}
14257-
14258-#ifndef RGFW_NO_IOKIT
14259-    float res = RGFW_osx_getFallbackRefreshRate(display);
14260-    if (res != 0) return res;
14261-#else
14262-    RGFW_UNUSED(display);
14263-#endif
14264-    return 60;
14265-}
14266-
14267-void RGFW_pollMonitors(void) {
14268-	u32 count;
14269-
14270-	if (CGGetActiveDisplayList(0, NULL, &count) != kCGErrorSuccess) {
14271-		return;
14272-	}
14273-
14274-	CGDirectDisplayID* displays = (CGDirectDisplayID*)RGFW_ALLOC(sizeof(CGDirectDisplayID) * count);
14275-	if (CGGetActiveDisplayList(count, displays, &count) != kCGErrorSuccess) {
14276-		return;
14277-	}
14278-
14279-
14280-	for (RGFW_monitorNode* node = _RGFW->monitors.list.head; node; node = node->next) {
14281-		node->disconnected = RGFW_TRUE;
14282-	}
14283-
14284-	CGDirectDisplayID primary = CGMainDisplayID();
14285-
14286-	u32 i;
14287-	for (i = 0; i < count; i++) {
14288-		RGFW_monitor monitor;
14289-
14290-		u32 uintNum = CGDisplayUnitNumber(displays[i]);
14291-		id screen = RGFW_getNSScreenForDisplayUInt(uintNum);
14292-
14293-		RGFW_monitorNode* node;
14294-		for (node = _RGFW->monitors.list.head; node; node = node->next) {
14295-			if (node->uintNum == uintNum) break;
14296-		}
14297-
14298-		if (node) {
14299-			node->screen = (void*)screen;
14300-			node->display = displays[i];
14301-			node->disconnected = RGFW_FALSE;
14302-			if (displays[i] == primary) {
14303-				_RGFW->monitors.primary = node;
14304-			}
14305-			continue;
14306-		}
14307-
14308-		const char name[] = "MacOS\0";
14309-		RGFW_MEMCPY(monitor.name, name, 6);
14310-
14311-		CGRect bounds = CGDisplayBounds(displays[i]);
14312-		monitor.x = (i32)bounds.origin.x;
14313-		monitor.y = (i32)RGFW_cocoaYTransform((float)(bounds.origin.y + bounds.size.height - 1));
14314-
14315-		CGDisplayModeRef mode = CGDisplayCopyDisplayMode(displays[i]);
14316-		monitor.mode.w = (i32)CGDisplayModeGetWidth(mode);
14317-		monitor.mode.h = (i32)CGDisplayModeGetHeight(mode);
14318-		monitor.mode.src = (void*)mode;
14319-		monitor.mode.red = 8; monitor.mode.green = 8; monitor.mode.blue = 8;
14320-
14321-		monitor.mode.refreshRate = RGFW_osx_getRefreshRate(displays[i], mode);
14322-		CFRelease(mode);
14323-
14324-		CGSize screenSizeMM = CGDisplayScreenSize(displays[i]);
14325-		monitor.physW = (float)screenSizeMM.width / 25.4f;
14326-		monitor.physH = (float)screenSizeMM.height / 25.4f;
14327-
14328-		float ppi_width = ((float)monitor.mode.w / monitor.physW);
14329-		float ppi_height = ((float)monitor.mode.h / monitor.physH);
14330-
14331-		monitor.pixelRatio = (float)((CGFloat (*)(id, SEL))abi_objc_msgSend_fpret) (screen, sel_registerName("backingScaleFactor"));
14332-		float dpi = 96.0f * monitor.pixelRatio;
14333-
14334-		monitor.scaleX = ((((float) (ppi_width) / dpi) * 10.0f)) / 10.0f;
14335-		monitor.scaleY = ((((float) (ppi_height) / dpi) * 10.0f)) / 10.0f;
14336-
14337-		node = RGFW_monitors_add(&monitor);
14338-
14339-		node->screen = (void*)screen;
14340-		node->uintNum = uintNum;
14341-		node->display = displays[i];
14342-
14343-		if (displays[i] == primary) {
14344-			_RGFW->monitors.primary = node;
14345-		}
14346-
14347-		RGFW_monitorCallback(_RGFW->root, &node->mon, RGFW_TRUE);
14348-	}
14349-
14350-	RGFW_FREE(displays);
14351-
14352-	RGFW_monitors_refresh();
14353-}
14354-
14355-RGFW_bool RGFW_monitor_getWorkarea(RGFW_monitor* monitor, i32* x, i32* y, i32* width, i32* height) {
14356-	NSRect frameRect = ((NSRect(*)(id, SEL))abi_objc_msgSend_stret)((id)monitor->node->screen, sel_registerName("visibleFrame"));
14357-
14358-    if (x) *x = (i32)frameRect.origin.x;
14359-    if (y) *y = (i32)RGFW_cocoaYTransform((float)(frameRect.origin.y + frameRect.size.height - (double)1.0f));
14360-    if (width) *width = (i32)frameRect.size.width;
14361-    if (height) *height = (i32)frameRect.size.height;
14362-
14363-	return RGFW_TRUE;
14364-}
14365-
14366-size_t RGFW_monitor_getGammaRampPtr(RGFW_monitor* monitor, RGFW_gammaRamp* ramp) {
14367-	id pool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc"));
14368-	pool = objc_msgSend_id(pool, sel_registerName("init"));
14369-
14370-    u32 size = CGDisplayGammaTableCapacity(monitor->node->display);
14371-    CGGammaValue* values = (CGGammaValue*)RGFW_ALLOC(size * 3 * sizeof(CGGammaValue));
14372-
14373-    CGGetDisplayTransferByTable(monitor->node->display, size, values, values + size, values + size * 2, &size);
14374-
14375-    for (u32 i = 0;  ramp && i < size; i++) {
14376-        ramp->red[i] = (u16) (values[i] * 65535);
14377-        ramp->green[i] = (u16) (values[i + size] * 65535);
14378-        ramp->blue[i] = (u16) (values[i + size * 2] * 65535);
14379-    }
14380-
14381-    RGFW_FREE(values);
14382-
14383-	objc_msgSend_bool_void(pool, sel_registerName("drain"));
14384-	return size;
14385-}
14386-
14387-RGFW_bool RGFW_monitor_setGammaRamp(RGFW_monitor* monitor, RGFW_gammaRamp* ramp) {
14388-	id pool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc"));
14389-	pool = objc_msgSend_id(pool, sel_registerName("init"));
14390-
14391-    CGGammaValue* values = (CGGammaValue*)RGFW_ALLOC(ramp->count * 3 * sizeof(CGGammaValue));
14392-
14393-    for (u32 i = 0;  i < ramp->count;  i++) {
14394-        values[i] = ramp->red[i] / 65535.f;
14395-        values[i + ramp->count] = ramp->green[i] / 65535.f;
14396-        values[i + ramp->count * 2] = ramp->blue[i] / 65535.f;
14397-    }
14398-
14399-    CGSetDisplayTransferByTable(monitor->node->display, (u32)ramp->count, values, values + ramp->count, values + ramp->count * 2);
14400-
14401-    RGFW_FREE(values);
14402-
14403-	objc_msgSend_bool_void(pool, sel_registerName("drain"));
14404-
14405-	return RGFW_TRUE;
14406-}
14407-
14408-size_t RGFW_monitor_getModesPtr(RGFW_monitor* mon, RGFW_monitorMode** modes) {
14409-    CGDirectDisplayID display = mon->node->display;
14410-    CFArrayRef allModes = CGDisplayCopyAllDisplayModes(display, NULL);
14411-
14412-    if (allModes == NULL) {
14413-        return RGFW_FALSE;
14414-	}
14415-
14416-	size_t count = (size_t)CFArrayGetCount(allModes);
14417-
14418-    CFIndex i;
14419-    for (i = 0; i < (CFIndex)count && modes; i++) {
14420-        CGDisplayModeRef cmode = (CGDisplayModeRef)CFArrayGetValueAtIndex(allModes, i);
14421-
14422-		RGFW_monitorMode foundMode;
14423-		foundMode.w = (i32)CGDisplayModeGetWidth(cmode);
14424-		foundMode.h = (i32)CGDisplayModeGetHeight(cmode);
14425-		foundMode.refreshRate =  RGFW_osx_getRefreshRate(display, cmode);
14426-		foundMode.red = 8; foundMode.green = 8; foundMode.blue = 8;
14427-		foundMode.src = (void*)cmode;
14428-		(*modes)[i] = foundMode;
14429-    }
14430-
14431-    CFRelease(allModes);
14432-	return count;
14433-}
14434-
14435-RGFW_bool RGFW_monitor_setMode(RGFW_monitor* mon, RGFW_monitorMode* mode) {
14436-	if (CGDisplaySetDisplayMode(mon->node->display, (CGDisplayModeRef)mode->src, NULL) == kCGErrorSuccess) {
14437-		return RGFW_TRUE;
14438-	}
14439-
14440-	return RGFW_FALSE;
14441-}
14442-
14443-RGFW_bool RGFW_monitor_requestMode(RGFW_monitor* mon, RGFW_monitorMode* mode, RGFW_modeRequest request) {
14444-    CGDirectDisplayID display = mon->node->display;
14445-    CFArrayRef allModes = CGDisplayCopyAllDisplayModes(display, NULL);
14446-
14447-    if (allModes == NULL) {
14448-        return RGFW_FALSE;
14449-	}
14450-
14451-	CGDisplayModeRef native = NULL;
14452-
14453-    CFIndex i;
14454-    for (i = 0; i < CFArrayGetCount(allModes); i++) {
14455-        CGDisplayModeRef cmode = (CGDisplayModeRef)CFArrayGetValueAtIndex(allModes, i);
14456-
14457-		RGFW_monitorMode foundMode;
14458-		foundMode.w = (i32)CGDisplayModeGetWidth(cmode);
14459-		foundMode.h = (i32)CGDisplayModeGetHeight(cmode);
14460-		foundMode.refreshRate =  RGFW_osx_getRefreshRate(display, cmode);
14461-		foundMode.red = 8; foundMode.green = 8; foundMode.blue = 8;
14462-		foundMode.src = (void*)cmode;
14463-
14464-		if (RGFW_monitorModeCompare(mode, &foundMode, request)) {
14465-			native = cmode;
14466-			mon->mode = foundMode;
14467-			break;
14468-        }
14469-    }
14470-
14471-    CFRelease(allModes);
14472-
14473-	if (native) {
14474-		if (CGDisplaySetDisplayMode(display, native, NULL) == kCGErrorSuccess) {
14475-			return RGFW_TRUE;
14476-		}
14477-	}
14478-
14479-	return RGFW_FALSE;
14480-}
14481-
14482-RGFW_monitor* RGFW_window_getMonitor(RGFW_window* win) {
14483-	id screen = objc_msgSend_id(win->src.window, sel_registerName("screen"));
14484-	id description = objc_msgSend_id(screen, sel_registerName("deviceDescription"));
14485-	id screenNumberKey = NSString_stringWithUTF8String("NSScreenNumber");
14486-	id screenNumber = objc_msgSend_id_id(description, sel_registerName("objectForKey:"), screenNumberKey);
14487-
14488-	CGDirectDisplayID display = (CGDirectDisplayID)objc_msgSend_uint(screenNumber, sel_registerName("unsignedIntValue"));
14489-
14490-	RGFW_monitorNode* node = _RGFW->monitors.list.head;
14491-	for (node = _RGFW->monitors.list.head; node; node = node->next) {
14492-		if (node->display == display && (id)node->screen == screen) {
14493-			break;
14494-		}
14495-	}
14496-
14497-    if (node == NULL) {
14498-		node = _RGFW->monitors.primary ? _RGFW->monitors.primary : _RGFW->monitors.list.head;
14499-	}
14500-
14501-	if (node == NULL) return NULL;
14502-	return &node->mon;
14503-}
14504-
14505-RGFW_ssize_t RGFW_readClipboardPtr(char* str, size_t strCapacity) {
14506-	size_t clip_len;
14507-	char* clip = (char*)NSPasteboard_stringForType(NSPasteboard_generalPasteboard(), NSPasteboardTypeString, &clip_len);
14508-	if (clip == NULL) return -1;
14509-
14510-	if (str != NULL) {
14511-		if (strCapacity < clip_len)
14512-			return 0;
14513-
14514-		RGFW_MEMCPY(str, clip, clip_len);
14515-
14516-		str[clip_len] = '\0';
14517-	}
14518-
14519-	return (RGFW_ssize_t)clip_len;
14520-}
14521-
14522-void RGFW_writeClipboard(const char* text, u32 textLen) {
14523-	RGFW_UNUSED(textLen);
14524-
14525-	NSPasteboardType array[] = { NSPasteboardTypeString, NULL };
14526-	NSPasteBoard_declareTypes(NSPasteboard_generalPasteboard(), array, 1, NULL);
14527-
14528-	SEL func = sel_registerName("setString:forType:");
14529-	((bool (*)(id, SEL, id, id))objc_msgSend)
14530-		(NSPasteboard_generalPasteboard(), func, NSString_stringWithUTF8String(text), NSString_stringWithUTF8String((const char*)NSPasteboardTypeString));
14531-}
14532-
14533-#ifdef RGFW_OPENGL
14534-void NSOpenGLContext_setValues(id context, const int* vals, NSOpenGLContextParameter param);
14535-void NSOpenGLContext_setValues(id context, const int* vals, NSOpenGLContextParameter param) {
14536-	((void (*)(id, SEL, const int*, NSOpenGLContextParameter))objc_msgSend)
14537-		(context, sel_registerName("setValues:forParameter:"), vals, param);
14538-}
14539-
14540-
14541-/* MacOS OpenGL API spares us yet again (there are no extensions) */
14542-RGFW_bool RGFW_extensionSupportedPlatform_OpenGL(const char * extension, size_t len) { RGFW_UNUSED(extension); RGFW_UNUSED(len); return RGFW_FALSE; }
14543-
14544-RGFW_proc RGFW_getProcAddress_OpenGL(const char* procname) {
14545-    static CFBundleRef RGFWnsglFramework = NULL;
14546-    if (RGFWnsglFramework == NULL)
14547-		RGFWnsglFramework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));
14548-
14549-	CFStringRef symbolName = CFStringCreateWithCString(kCFAllocatorDefault, procname, kCFStringEncodingASCII);
14550-
14551-	RGFW_proc symbol = (RGFW_proc)CFBundleGetFunctionPointerForName(RGFWnsglFramework, symbolName);
14552-
14553-	CFRelease(symbolName);
14554-
14555-	return symbol;
14556-}
14557-
14558-RGFW_bool RGFW_window_createContextPtr_OpenGL(RGFW_window* win, RGFW_glContext* ctx, RGFW_glHints* hints) {
14559-	win->src.ctx.native = ctx;
14560-	win->src.gfxType = RGFW_gfxNativeOpenGL;
14561-
14562-	i32 attribs[40];
14563-	size_t render_type_index = 0;
14564-	{
14565-		RGFW_attribStack stack;
14566-		RGFW_attribStack_init(&stack, attribs, 40);
14567-
14568-		i32 colorBits = (i32)(hints->red + hints->green +  hints->blue + hints->alpha) / 4;
14569-		RGFW_attribStack_pushAttribs(&stack, NSOpenGLPFAColorSize, colorBits);
14570-
14571-		RGFW_attribStack_pushAttribs(&stack, NSOpenGLPFAAlphaSize, hints->alpha);
14572-		RGFW_attribStack_pushAttribs(&stack, NSOpenGLPFADepthSize, hints->depth);
14573-		RGFW_attribStack_pushAttribs(&stack, NSOpenGLPFAStencilSize, hints->stencil);
14574-		RGFW_attribStack_pushAttribs(&stack, NSOpenGLPFAAuxBuffers, hints->auxBuffers);
14575-		RGFW_attribStack_pushAttrib(&stack, NSOpenGLPFAClosestPolicy);
14576-		if (hints->samples) {
14577-			RGFW_attribStack_pushAttribs(&stack, NSOpenGLPFASampleBuffers, 1);
14578-			RGFW_attribStack_pushAttribs(&stack, NSOpenGLPFASamples, hints->samples);
14579-		} else RGFW_attribStack_pushAttribs(&stack, NSOpenGLPFASampleBuffers, 0);
14580-
14581-		if (hints->doubleBuffer)
14582-			RGFW_attribStack_pushAttrib(&stack, NSOpenGLPFADoubleBuffer);
14583-
14584-		#ifdef RGFW_COCOA_GRAPHICS_SWITCHING
14585-		RGFW_attribStack_pushAttribs(&stack, NSOpenGLPFAAllowOfflineRenderers, kCGLPFASupportsAutomaticGraphicsSwitching);
14586-		#endif
14587-		#if MAC_OS_X_VERSION_MAX_ALLOWED < 101200
14588-		if (hints->stereo) RGFW_attribStack_pushAttrib(&stack, NSOpenGLPFAStereo);
14589-		#endif
14590-
14591-		/* macOS has the surface attribs and the OpenGL attribs connected for some reason maybe this is to give macOS more control to limit openGL/the OpenGL version? */
14592-		RGFW_attribStack_pushAttribs(&stack, NSOpenGLPFAOpenGLProfile,
14593-						(hints->major >= 4) ? NSOpenGLProfileVersion4_1Core  : (hints->major >= 3) ?
14594-															NSOpenGLProfileVersion3_2Core : NSOpenGLProfileVersionLegacy);
14595-
14596-		if (hints->major <= 2) {
14597-			i32 accumSize = (i32)(hints->accumRed + hints->accumGreen +  hints->accumBlue + hints->accumAlpha) / 4;
14598-			RGFW_attribStack_pushAttribs(&stack, NSOpenGLPFAAccumSize, accumSize);
14599-		}
14600-
14601-		if (hints->renderer == RGFW_glSoftware) {
14602-			RGFW_attribStack_pushAttribs(&stack, NSOpenGLPFARendererID, kCGLRendererGenericFloatID);
14603-		} else {
14604-			RGFW_attribStack_pushAttrib(&stack, NSOpenGLPFAAccelerated);
14605-		}
14606-		render_type_index = stack.count - 1;
14607-
14608-		RGFW_attribStack_pushAttribs(&stack, 0, 0);
14609-	}
14610-
14611-	void* format = (void*) ((id(*)(id, SEL, const u32*))objc_msgSend) (NSAlloc((id)objc_getClass("NSOpenGLPixelFormat")), sel_registerName("initWithAttributes:"), (u32*)attribs);
14612-	if (format == NULL) {
14613-		RGFW_debugCallback(RGFW_typeError, RGFW_errOpenGLContext, "Failed to load pixel format for OpenGL");
14614-
14615-		assert(render_type_index + 3 < (sizeof(attribs) / sizeof(attribs[0])));
14616-		attribs[render_type_index] = NSOpenGLPFARendererID;
14617-		attribs[render_type_index + 1] = kCGLRendererGenericFloatID;
14618-		attribs[render_type_index + 3] = 0;
14619-
14620-		format = (void*) ((id(*)(id, SEL, const u32*))objc_msgSend) (NSAlloc((id)objc_getClass("NSOpenGLPixelFormat")), sel_registerName("initWithAttributes:"), (u32*)attribs);
14621-		if (format == NULL)
14622-			RGFW_debugCallback(RGFW_typeError, RGFW_errOpenGLContext, "and loading software rendering OpenGL failed");
14623-		else
14624-			RGFW_debugCallback(RGFW_typeWarning, RGFW_warningOpenGL, "Switching to software rendering");
14625-	}
14626-
14627-	/* the pixel format can be passed directly to OpenGL context creation to create a context
14628-		this is because the format also includes information about the OpenGL version (which may be a bad thing) */
14629-
14630-	if (win->src.view)
14631-		NSRelease(win->src.view);
14632-	win->src.view = (id) ((id(*)(id, SEL, NSRect, u32*))objc_msgSend) (NSAlloc(_RGFW->customViewClasses[1]),
14633-							sel_registerName("initWithFrame:pixelFormat:"), (NSRect){{0, 0}, {(double)win->w, (double)win->h}}, (u32*)format);
14634-
14635-	id share = NULL;
14636-	if (hints->share) {
14637-		share = (id)hints->share->ctx;
14638-	}
14639-
14640-	win->src.ctx.native->ctx = ((id (*)(id, SEL, id, id))objc_msgSend)(NSAlloc(objc_getClass("NSOpenGLContext")),
14641-												 sel_registerName("initWithFormat:shareContext:"),
14642-												 (id)format, share);
14643-
14644-	win->src.ctx.native->format = format;
14645-
14646-	objc_msgSend_void_id(win->src.view, sel_registerName("setOpenGLContext:"), win->src.ctx.native->ctx);
14647-	if (win->internal.flags & RGFW_windowTransparent) {
14648-		i32 opacity = 0;
14649-		#define NSOpenGLCPSurfaceOpacity 236
14650-		NSOpenGLContext_setValues((id)win->src.ctx.native->ctx, &opacity, (NSOpenGLContextParameter)NSOpenGLCPSurfaceOpacity);
14651-
14652-	}
14653-
14654-	objc_msgSend_void(win->src.ctx.native->ctx, sel_registerName("makeCurrentContext"));
14655-
14656-	objc_msgSend_void_id((id)win->src.window, sel_registerName("setContentView:"), win->src.view);
14657-	objc_msgSend_void_bool(win->src.view, sel_registerName("setWantsLayer:"), true);
14658-	objc_msgSend_int((id)win->src.view, sel_registerName("setLayerContentsPlacement:"),  4);
14659-
14660-	RGFW_window_swapInterval_OpenGL(win, 0);
14661-
14662-	RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "OpenGL context initalized.");
14663-	return RGFW_TRUE;
14664-}
14665-
14666-void RGFW_window_deleteContextPtr_OpenGL(RGFW_window* win, RGFW_glContext* ctx) {
14667-	objc_msgSend_void(ctx->format, sel_registerName("release"));
14668-	win->src.ctx.native->format = NULL;
14669-
14670-	objc_msgSend_void(ctx->ctx, sel_registerName("release"));
14671-	win->src.ctx.native->ctx = NULL;
14672-	RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "OpenGL context freed.");
14673-}
14674-
14675-void RGFW_window_makeCurrentContext_OpenGL(RGFW_window* win) {
14676-	if (win) RGFW_ASSERT(win->src.ctx.native);
14677-	if (win != NULL)
14678-		objc_msgSend_void(win->src.ctx.native->ctx, sel_registerName("makeCurrentContext"));
14679-	else
14680-		objc_msgSend_id(objc_getClass("NSOpenGLContext"), sel_registerName("clearCurrentContext"));
14681-}
14682-void* RGFW_getCurrentContext_OpenGL(void) {
14683-	return objc_msgSend_id(objc_getClass("NSOpenGLContext"), sel_registerName("currentContext"));
14684-}
14685-
14686-void RGFW_window_swapBuffers_OpenGL(RGFW_window* win) {
14687-	RGFW_ASSERT(win && win->src.ctx.native);
14688-	objc_msgSend_void(win->src.ctx.native->ctx, sel_registerName("flushBuffer"));
14689-}
14690-void RGFW_window_swapInterval_OpenGL(RGFW_window* win, i32 swapInterval) {
14691-	RGFW_ASSERT(win != NULL && win->src.ctx.native != NULL);
14692-	NSOpenGLContext_setValues((id)win->src.ctx.native->ctx, &swapInterval, (NSOpenGLContextParameter)222);
14693-}
14694-#endif
14695-
14696-void RGFW_deinitPlatform(void) {
14697-	objc_msgSend_void_id(_RGFW->NSApp, sel_registerName("setDelegate:"), NULL);
14698-
14699-	objc_msgSend_void_id(_RGFW->NSApp, sel_registerName("stop:"), NULL);
14700-	NSRelease(_RGFW->NSApp);
14701-	_RGFW->NSApp = NULL;
14702-
14703-	NSRelease(_RGFW->customNSAppDelegate);
14704-
14705-	_RGFW->customNSAppDelegate = NULL;
14706-
14707-	objc_disposeClassPair((Class)_RGFW->customViewClasses[0]);
14708-	objc_disposeClassPair((Class)_RGFW->customViewClasses[1]);
14709-	objc_disposeClassPair((Class)_RGFW->customWindowDelegateClass);
14710-	objc_disposeClassPair((Class)_RGFW->customNSAppDelegateClass);
14711-}
14712-
14713-void RGFW_window_closePlatform(RGFW_window* win) {
14714-	objc_msgSend_void_id((id)win->src.window, sel_registerName("setDelegate:"), NULL);
14715-	NSRelease((id)win->src.delegate);
14716-	NSRelease(win->src.view);
14717-
14718-	objc_msgSend_id(win->src.window, sel_registerName("close"));
14719-	NSRelease(win->src.window);
14720-}
14721-
14722-#ifdef RGFW_VULKAN
14723-VkResult RGFW_window_createSurface_Vulkan(RGFW_window* win, VkInstance instance, VkSurfaceKHR* surface) {
14724-    RGFW_ASSERT(win != NULL); RGFW_ASSERT(instance);
14725-	RGFW_ASSERT(surface != NULL);
14726-
14727-    *surface = VK_NULL_HANDLE;
14728-	id pool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc"));
14729-	pool = objc_msgSend_id(pool, sel_registerName("init"));
14730-
14731-    id nsView = (id)win->src.view;
14732-    if (!nsView) {
14733-		RGFW_debugCallback(RGFW_typeError, RGFW_errMetal, "NSView is NULL for macOS window");
14734-        return -1;
14735-    }
14736-
14737-
14738-    id layer = ((id (*)(id, SEL))objc_msgSend)(nsView, sel_registerName("layer"));
14739-
14740-	void* metalLayer = RGFW_getLayer_OSX();
14741-	if (metalLayer == NULL) {
14742-		 return -1;
14743-	}
14744-	((void (*)(id, SEL, id))objc_msgSend)((id)nsView, sel_registerName("setLayer:"), metalLayer);
14745-    ((void (*)(id, SEL, BOOL))objc_msgSend)(nsView, sel_registerName("setWantsLayer:"), YES);
14746-
14747-	VkResult result;
14748-/*
14749-	VkMetalSurfaceCreateInfoEXT macos;
14750-	macos.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK;
14751-	macos.slayer = metalLayer;
14752-	RGFW_MEMZERO(&macos, sizeof(macos));
14753-    result = vkCreateMacOSSurfaceMVK(instance, &macos, NULL, surface);
14754-*/
14755-
14756-	VkMacOSSurfaceCreateInfoMVK macos;
14757-	RGFW_MEMZERO(&macos, sizeof(macos));
14758-	macos.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK;
14759-	macos.pView = nsView;
14760-
14761-    result = vkCreateMacOSSurfaceMVK(instance, &macos, NULL, surface);
14762-
14763-	objc_msgSend_bool_void(pool, sel_registerName("drain"));
14764-
14765-	return result;
14766-}
14767-#endif
14768-
14769-#ifdef RGFW_WEBGPU
14770-WGPUSurface RGFW_window_createSurface_WebGPU(RGFW_window* window, WGPUInstance instance) {
14771-	WGPUSurfaceDescriptor surfaceDesc = {0};
14772-    id* nsView = (id*)window->src.view;
14773-    if (!nsView) {
14774-		RGFW_debugCallback(RGFW_typeError, RGFW_errMetal, "NSView is NULL for macOS window");
14775-        return NULL;
14776-    }
14777-
14778-    ((void (*)(id, SEL, BOOL))objc_msgSend)(nsView, sel_registerName("setWantsLayer:"), YES);
14779-    id layer = ((id (*)(id, SEL))objc_msgSend)(nsView, sel_registerName("layer"));
14780-
14781-	void* metalLayer = RGFW_getLayer_OSX();
14782-	if (metalLayer == NULL) {
14783-		 return NULL;
14784-	}
14785-	((void (*)(id, SEL, id))objc_msgSend)((id)nsView, sel_registerName("setLayer:"), metalLayer);
14786-	layer = metalLayer;
14787-
14788-    WGPUSurfaceSourceMetalLayer fromMetal = {0};
14789-    fromMetal.chain.sType = WGPUSType_SurfaceSourceMetalLayer;
14790-#ifdef  __OBJC__
14791-	fromMetal.layer = (__bridge CAMetalLayer*)layer; /* Use __bridge for ARC compatibility if mixing C/Obj-C */
14792-#else
14793-	fromMetal.layer = layer;
14794-#endif
14795-
14796-    surfaceDesc.nextInChain = (WGPUChainedStruct*)&fromMetal.chain;
14797-    return wgpuInstanceCreateSurface(instance, &surfaceDesc);
14798-}
14799-#endif
14800-
14801-#endif /* RGFW_MACOS */
14802-
14803-/*
14804-	End of MaOS defines
14805-*/
14806-
14807-/*
14808-	WASM defines
14809-*/
14810-
14811-#ifdef RGFW_WASM
14812-EM_BOOL Emscripten_on_resize(int eventType, const EmscriptenUiEvent* E, void* userData) {
14813-	RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
14814-	RGFW_windowResizedCallback(_RGFW->root, E->windowInnerWidth, E->windowInnerHeight);
14815-    return EM_TRUE;
14816-}
14817-
14818-EM_BOOL Emscripten_on_fullscreenchange(int eventType, const EmscriptenFullscreenChangeEvent* E, void* userData) {
14819-	RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
14820-
14821-	if (!(_RGFW->root->internal.enabledEvents & RGFW_windowResizedFlag)) return EM_TRUE;
14822-
14823-	static u8 fullscreen = RGFW_FALSE;
14824-	static i32 originalW, originalH;
14825-
14826-	if (fullscreen == RGFW_FALSE) {
14827-		originalW = _RGFW->root->w;
14828-		originalH = _RGFW->root->h;
14829-	}
14830-
14831-	fullscreen = !fullscreen;
14832-	_RGFW->root->w = E->screenWidth;
14833-	_RGFW->root->h =  E->screenHeight;
14834-
14835-	EM_ASM("Module.canvas.focus();");
14836-
14837-	if (fullscreen == RGFW_FALSE) {
14838-		_RGFW->root->w = originalW;
14839-		_RGFW->root->h = originalH;
14840-	} else {
14841-		#if __EMSCRIPTEN_major__  >= 1 && __EMSCRIPTEN_minor__  >= 29 && __EMSCRIPTEN_tiny__  >= 0
14842-			EmscriptenFullscreenStrategy FSStrat = {0};
14843-			FSStrat.scaleMode = EMSCRIPTEN_FULLSCREEN_SCALE_STRETCH;
14844-			FSStrat.canvasResolutionScaleMode = EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_HIDEF;
14845-			FSStrat.filteringMode = EMSCRIPTEN_FULLSCREEN_FILTERING_DEFAULT;
14846-			emscripten_request_fullscreen_strategy("#canvas", 1, &FSStrat);
14847-		#else
14848-			emscripten_request_fullscreen("#canvas", 1);
14849-		#endif
14850-	}
14851-
14852-	emscripten_set_canvas_element_size("#canvas", _RGFW->root->w, _RGFW->root->h);
14853-	RGFW_windowResizedCallback(_RGFW->root, _RGFW->root->w, _RGFW->root->h);
14854-	return EM_TRUE;
14855-}
14856-
14857-EM_BOOL Emscripten_on_focusin(int eventType, const EmscriptenFocusEvent* E, void* userData) {
14858-	RGFW_UNUSED(eventType); RGFW_UNUSED(userData); RGFW_UNUSED(E);
14859-
14860-	RGFW_windowFocusCallback(_RGFW->root, 1);
14861-    return EM_TRUE;
14862-}
14863-
14864-EM_BOOL Emscripten_on_focusout(int eventType, const EmscriptenFocusEvent* E, void* userData) {
14865-	RGFW_UNUSED(eventType); RGFW_UNUSED(userData); RGFW_UNUSED(E);
14866-
14867-	RGFW_windowFocusCallback(_RGFW->root, 0);
14868-    return EM_TRUE;
14869-}
14870-
14871-EM_BOOL Emscripten_on_mousemove(int eventType, const EmscriptenMouseEvent* E, void* userData) {
14872-	RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
14873-	RGFW_mousePosCallback(_RGFW->root, E->targetX, E->targetY);
14874-	RGFW_rawMotionCallback(_RGFW->root, E->movementX, E->movementY);
14875-    return EM_TRUE;
14876-}
14877-
14878-EM_BOOL Emscripten_on_mousedown(int eventType, const EmscriptenMouseEvent* E, void* userData) {
14879-	RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
14880-
14881-	int button = E->button;
14882-	if (button > 2)
14883-		button += 2;
14884-
14885-	RGFW_mouseButtonCallback(_RGFW->root, button, 1);
14886-    return EM_TRUE;
14887-}
14888-
14889-EM_BOOL Emscripten_on_mouseup(int eventType, const EmscriptenMouseEvent* E, void* userData) {
14890-	RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
14891-
14892-	int button = E->button;
14893-	if (button > 2)
14894-		button += 2;
14895-
14896-	RGFW_mouseButtonCallback(_RGFW->root, button, 0);
14897-    return EM_TRUE;
14898-}
14899-
14900-EM_BOOL Emscripten_on_wheel(int eventType, const EmscriptenWheelEvent* E, void* userData) {
14901-	RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
14902-
14903-	RGFW_mouseScrollCallback(_RGFW->root, E->deltaX, E->deltaY);
14904-
14905-    return EM_TRUE;
14906-}
14907-
14908-EM_BOOL Emscripten_on_touchstart(int eventType, const EmscriptenTouchEvent* E, void* userData) {
14909-	RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
14910-
14911-	if (!(_RGFW->root->internal.enabledEvents & RGFW_mouseButtonPressedFlag)) return EM_TRUE;
14912-
14913-    size_t i;
14914-    for (i = 0; i < (size_t)E->numTouches; i++) {
14915-        RGFW_mousePosCallback(_RGFW->root, E->touches[i].targetX, E->touches[i].targetY);
14916-		RGFW_rawMotionCallback(_RGFW->root, 0, 0);
14917-	    RGFW_mouseButtonCallback(_RGFW->root, RGFW_mouseLeft, 1);
14918-    }
14919-
14920-	return EM_TRUE;
14921-}
14922-
14923-EM_BOOL Emscripten_on_touchmove(int eventType, const EmscriptenTouchEvent* E, void* userData) {
14924-	RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
14925-
14926-	if (!(_RGFW->root->internal.enabledEvents & RGFW_mousePosChangedFlag)) return EM_TRUE;
14927-
14928-    size_t i;
14929-    for (i = 0; i < (size_t)E->numTouches; i++) {
14930-        RGFW_mousePosCallback(_RGFW->root, E->touches[i].targetX, E->touches[i].targetY);
14931-		RGFW_rawMotionCallback(_RGFW->root, 0, 0);
14932-    }
14933-    return EM_TRUE;
14934-}
14935-
14936-EM_BOOL Emscripten_on_touchend(int eventType, const EmscriptenTouchEvent* E, void* userData) {
14937-	RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
14938-
14939-	if (!(_RGFW->root->internal.enabledEvents & RGFW_mouseButtonReleasedFlag)) return EM_TRUE;
14940-
14941-    size_t i;
14942-    for (i = 0; i < (size_t)E->numTouches; i++) {
14943-		RGFW_mousePosCallback(_RGFW->root, E->touches[i].targetX, E->touches[i].targetY);
14944-		RGFW_rawMotionCallback(_RGFW->root, 0, 0);
14945-		RGFW_mouseButtonCallback(_RGFW->root, RGFW_mouseLeft, 0);
14946-    }
14947-	return EM_TRUE;
14948-}
14949-
14950-EM_BOOL Emscripten_on_touchcancel(int eventType, const EmscriptenTouchEvent* E, void* userData) { RGFW_UNUSED(eventType); RGFW_UNUSED(userData); return EM_TRUE; }
14951-
14952-RGFW_key RGFW_WASMPhysicalToRGFW(u32 hash);
14953-
14954-void EMSCRIPTEN_KEEPALIVE RGFW_handleKeyEvent(char* code, u32 codepoint, RGFW_bool press) {
14955-	const char* iCode = code;
14956-
14957-	u32 hash = 0;
14958-	while(*iCode) hash = ((hash ^ 0x7E057D79U) << 3) ^ (unsigned int)*iCode++;
14959-
14960-	u32 physicalKey = RGFW_WASMPhysicalToRGFW(hash);
14961-
14962-	RGFW_keyCallback(_RGFW->root, physicalKey, _RGFW->root->internal.mod,  RGFW_isKeyDown((u8)physicalKey) && press, press);
14963-	if (press) {
14964-;		RGFW_keyCharCallback(_RGFW->root, codepoint);
14965-	}
14966-}
14967-
14968-void EMSCRIPTEN_KEEPALIVE RGFW_handleKeyMods(RGFW_bool capital, RGFW_bool numlock, RGFW_bool control, RGFW_bool alt, RGFW_bool shift, RGFW_bool super, RGFW_bool scroll) {
14969-	RGFW_keyUpdateKeyModsEx(_RGFW->root, capital, numlock, control, alt, shift, super, scroll);
14970-}
14971-
14972-void EMSCRIPTEN_KEEPALIVE Emscripten_onDrop(char* file, size_t size) {
14973-	RGFW_dataDropCallback(_RGFW->root, file, size, RGFW_dataFile);
14974-}
14975-
14976-void RGFW_stopCheckEvents(void) {
14977-	_RGFW->stopCheckEvents_bool = RGFW_TRUE;
14978-}
14979-
14980-RGFW_bool RGFW_createSurfacePtr(u8* data, i32 w, i32 h, RGFW_format format, RGFW_surface* surface) {
14981-	surface->data = data;
14982-	surface->w = w;
14983-	surface->h = h;
14984-	surface->format = format;
14985-	return RGFW_TRUE;
14986-}
14987-
14988-void RGFW_window_blitSurface(RGFW_window* win, RGFW_surface* surface) {
14989-	/* TODO: Needs fixing. */
14990-	RGFW_copyImageData(surface->data, surface->w, RGFW_MIN(win->h, surface->h), RGFW_formatRGBA8, surface->data, surface->format, surface->convertFunc);
14991-	EM_ASM_({
14992-		var data = Module.HEAPU8.slice($0, $0 + $1 * $2 * 4);
14993-		let context = document.getElementById("canvas").getContext("2d");
14994-		let image = context.getImageData(0, 0, $1, $2);
14995-		image.data.set(data);
14996-		context.putImageData(image, 0, $4 - $2);
14997-	}, surface->data, surface->w, surface->h, RGFW_MIN(win->h, surface->w), RGFW_MIN(win->h, surface->h));
14998-}
14999-
15000-void RGFW_surface_freePtr(RGFW_surface* surface) { }
15001-
15002-#include <sys/stat.h>
15003-#include <sys/types.h>
15004-#include <errno.h>
15005-#include <stdio.h>
15006-
15007-void EMSCRIPTEN_KEEPALIVE RGFW_mkdir(char* name) { mkdir(name, 0755); }
15008-
15009-void EMSCRIPTEN_KEEPALIVE RGFW_writeFile(const char *path, const char *data, size_t len) {
15010-    FILE* file = fopen(path, "w+");
15011-	if (file == NULL)
15012-		return;
15013-
15014-    fwrite(data, sizeof(char), len, file);
15015-    fclose(file);
15016-}
15017-
15018-void RGFW_initKeycodesPlatform(void) {
15019-	_RGFW->keycodes[DOM_VK_BACK_QUOTE] = RGFW_keyBacktick;
15020-	_RGFW->keycodes[DOM_VK_0] = RGFW_key0;
15021-	_RGFW->keycodes[DOM_VK_1] = RGFW_key1;
15022-	_RGFW->keycodes[DOM_VK_2] = RGFW_key2;
15023-	_RGFW->keycodes[DOM_VK_3] = RGFW_key3;
15024-	_RGFW->keycodes[DOM_VK_4] = RGFW_key4;
15025-	_RGFW->keycodes[DOM_VK_5] = RGFW_key5;
15026-	_RGFW->keycodes[DOM_VK_6] = RGFW_key6;
15027-	_RGFW->keycodes[DOM_VK_7] = RGFW_key7;
15028-	_RGFW->keycodes[DOM_VK_8] = RGFW_key8;
15029-	_RGFW->keycodes[DOM_VK_9] = RGFW_key9;
15030-	_RGFW->keycodes[DOM_VK_SPACE] = RGFW_keySpace;
15031-	_RGFW->keycodes[DOM_VK_A] = RGFW_keyA;
15032-	_RGFW->keycodes[DOM_VK_B] = RGFW_keyB;
15033-	_RGFW->keycodes[DOM_VK_C] = RGFW_keyC;
15034-	_RGFW->keycodes[DOM_VK_D] = RGFW_keyD;
15035-	_RGFW->keycodes[DOM_VK_E] = RGFW_keyE;
15036-	_RGFW->keycodes[DOM_VK_F] = RGFW_keyF;
15037-	_RGFW->keycodes[DOM_VK_G] = RGFW_keyG;
15038-	_RGFW->keycodes[DOM_VK_H] = RGFW_keyH;
15039-	_RGFW->keycodes[DOM_VK_I] = RGFW_keyI;
15040-	_RGFW->keycodes[DOM_VK_J] = RGFW_keyJ;
15041-	_RGFW->keycodes[DOM_VK_K] = RGFW_keyK;
15042-	_RGFW->keycodes[DOM_VK_L] = RGFW_keyL;
15043-	_RGFW->keycodes[DOM_VK_M] = RGFW_keyM;
15044-	_RGFW->keycodes[DOM_VK_N] = RGFW_keyN;
15045-	_RGFW->keycodes[DOM_VK_O] = RGFW_keyO;
15046-	_RGFW->keycodes[DOM_VK_P] = RGFW_keyP;
15047-	_RGFW->keycodes[DOM_VK_Q] = RGFW_keyQ;
15048-	_RGFW->keycodes[DOM_VK_R] = RGFW_keyR;
15049-	_RGFW->keycodes[DOM_VK_S] = RGFW_keyS;
15050-	_RGFW->keycodes[DOM_VK_T] = RGFW_keyT;
15051-	_RGFW->keycodes[DOM_VK_U] = RGFW_keyU;
15052-	_RGFW->keycodes[DOM_VK_V] = RGFW_keyV;
15053-	_RGFW->keycodes[DOM_VK_W] = RGFW_keyW;
15054-	_RGFW->keycodes[DOM_VK_X] = RGFW_keyX;
15055-	_RGFW->keycodes[DOM_VK_Y] = RGFW_keyY;
15056-	_RGFW->keycodes[DOM_VK_Z] = RGFW_keyZ;
15057-	_RGFW->keycodes[DOM_VK_PERIOD] = RGFW_keyPeriod;
15058-	_RGFW->keycodes[DOM_VK_COMMA] = RGFW_keyComma;
15059-	_RGFW->keycodes[DOM_VK_SLASH] = RGFW_keySlash;
15060-	_RGFW->keycodes[DOM_VK_OPEN_BRACKET] = RGFW_keyBracket;
15061-	_RGFW->keycodes[DOM_VK_CLOSE_BRACKET] = RGFW_keyCloseBracket;
15062-	_RGFW->keycodes[DOM_VK_SEMICOLON] = RGFW_keySemicolon;
15063-	_RGFW->keycodes[DOM_VK_QUOTE] = RGFW_keyApostrophe;
15064-	_RGFW->keycodes[DOM_VK_BACK_SLASH] = RGFW_keyBackSlash;
15065-	_RGFW->keycodes[DOM_VK_RETURN] = RGFW_keyReturn;
15066-	_RGFW->keycodes[DOM_VK_DELETE] = RGFW_keyDelete;
15067-	_RGFW->keycodes[DOM_VK_NUM_LOCK] = RGFW_keyNumLock;
15068-	_RGFW->keycodes[DOM_VK_DIVIDE] = RGFW_keyPadSlash;
15069-	_RGFW->keycodes[DOM_VK_MULTIPLY] = RGFW_keyPadMultiply;
15070-	_RGFW->keycodes[DOM_VK_SUBTRACT] = RGFW_keyPadMinus;
15071-	_RGFW->keycodes[DOM_VK_NUMPAD1] = RGFW_keyPad1;
15072-	_RGFW->keycodes[DOM_VK_NUMPAD2] = RGFW_keyPad2;
15073-	_RGFW->keycodes[DOM_VK_NUMPAD3] = RGFW_keyPad3;
15074-	_RGFW->keycodes[DOM_VK_NUMPAD4] = RGFW_keyPad4;
15075-	_RGFW->keycodes[DOM_VK_NUMPAD5] = RGFW_keyPad5;
15076-	_RGFW->keycodes[DOM_VK_NUMPAD6] = RGFW_keyPad6;
15077-	_RGFW->keycodes[DOM_VK_NUMPAD9] = RGFW_keyPad9;
15078-	_RGFW->keycodes[DOM_VK_NUMPAD0] = RGFW_keyPad0;
15079-	_RGFW->keycodes[DOM_VK_DECIMAL] = RGFW_keyPadPeriod;
15080-	_RGFW->keycodes[DOM_VK_RETURN] = RGFW_keyPadReturn;
15081-	_RGFW->keycodes[DOM_VK_HYPHEN_MINUS] = RGFW_keyMinus;
15082-	_RGFW->keycodes[DOM_VK_EQUALS] = RGFW_keyEquals;
15083-	_RGFW->keycodes[DOM_VK_BACK_SPACE] = RGFW_keyBackSpace;
15084-	_RGFW->keycodes[DOM_VK_TAB] = RGFW_keyTab;
15085-	_RGFW->keycodes[DOM_VK_CAPS_LOCK] = RGFW_keyCapsLock;
15086-	_RGFW->keycodes[DOM_VK_SHIFT] = RGFW_keyShiftL;
15087-	_RGFW->keycodes[DOM_VK_CONTROL] = RGFW_keyControlL;
15088-	_RGFW->keycodes[DOM_VK_ALT] = RGFW_keyAltL;
15089-	_RGFW->keycodes[DOM_VK_META] = RGFW_keySuperL;
15090-	_RGFW->keycodes[DOM_VK_F1] = RGFW_keyF1;
15091-	_RGFW->keycodes[DOM_VK_F2] = RGFW_keyF2;
15092-	_RGFW->keycodes[DOM_VK_F3] = RGFW_keyF3;
15093-	_RGFW->keycodes[DOM_VK_F4] = RGFW_keyF4;
15094-	_RGFW->keycodes[DOM_VK_F5] = RGFW_keyF5;
15095-	_RGFW->keycodes[DOM_VK_F6] = RGFW_keyF6;
15096-	_RGFW->keycodes[DOM_VK_F7] = RGFW_keyF7;
15097-	_RGFW->keycodes[DOM_VK_F8] = RGFW_keyF8;
15098-	_RGFW->keycodes[DOM_VK_F9] = RGFW_keyF9;
15099-	_RGFW->keycodes[DOM_VK_F10] = RGFW_keyF10;
15100-	_RGFW->keycodes[DOM_VK_F11] = RGFW_keyF11;
15101-	_RGFW->keycodes[DOM_VK_F12] = RGFW_keyF12;
15102-	_RGFW->keycodes[DOM_VK_UP] = RGFW_keyUp;
15103-	_RGFW->keycodes[DOM_VK_DOWN] = RGFW_keyDown;
15104-	_RGFW->keycodes[DOM_VK_LEFT] = RGFW_keyLeft;
15105-	_RGFW->keycodes[DOM_VK_RIGHT] = RGFW_keyRight;
15106-	_RGFW->keycodes[DOM_VK_INSERT] = RGFW_keyInsert;
15107-	_RGFW->keycodes[DOM_VK_END] = RGFW_keyEnd;
15108-	_RGFW->keycodes[DOM_VK_PAGE_UP] = RGFW_keyPageUp;
15109-	_RGFW->keycodes[DOM_VK_PAGE_DOWN] = RGFW_keyPageDown;
15110-	_RGFW->keycodes[DOM_VK_ESCAPE] = RGFW_keyEscape;
15111-	_RGFW->keycodes[DOM_VK_HOME] = RGFW_keyHome;
15112-	_RGFW->keycodes[DOM_VK_SCROLL_LOCK] = RGFW_keyScrollLock;
15113-	_RGFW->keycodes[DOM_VK_PRINTSCREEN] = RGFW_keyPrintScreen;
15114-	_RGFW->keycodes[DOM_VK_PAUSE] = RGFW_keyPause;
15115-	_RGFW->keycodes[DOM_VK_F13]  = RGFW_keyF13;
15116-	_RGFW->keycodes[DOM_VK_F14]  = RGFW_keyF14;
15117-	_RGFW->keycodes[DOM_VK_F15]  = RGFW_keyF15;
15118-	_RGFW->keycodes[DOM_VK_F16]  = RGFW_keyF16;
15119-	_RGFW->keycodes[DOM_VK_F17]  = RGFW_keyF17;
15120-	_RGFW->keycodes[DOM_VK_F18]  = RGFW_keyF18;
15121-	_RGFW->keycodes[DOM_VK_F19]  = RGFW_keyF19;
15122-	_RGFW->keycodes[DOM_VK_F20]  = RGFW_keyF20;
15123-	_RGFW->keycodes[DOM_VK_F21]  = RGFW_keyF21;
15124-	_RGFW->keycodes[DOM_VK_F22]  = RGFW_keyF22;
15125-	_RGFW->keycodes[DOM_VK_F23]  = RGFW_keyF23;
15126-	_RGFW->keycodes[DOM_VK_F24]  = RGFW_keyF24;
15127-}
15128-
15129-i32 RGFW_initPlatform(void) {
15130-	RGFW_monitorNode* node = NULL;
15131-	RGFW_monitor monitor;
15132-
15133-	monitor.name[0] = '\0';
15134-
15135-	monitor.x = 0;
15136-	monitor.y = 0;
15137-
15138-	monitor.pixelRatio = EM_ASM_DOUBLE({return window.devicePixelRatio || 1;});
15139-	monitor.mode.w = EM_ASM_INT({return window.innerWidth || 0;});
15140-	monitor.mode.h = EM_ASM_INT({return window.innerHeight || 0;});
15141-
15142-	monitor.physW = (float)RGFW_ROUND((float)monitor.mode.w * monitor.pixelRatio);
15143-	monitor.physH = (float)RGFW_ROUND((float)monitor.mode.h * monitor.pixelRatio);
15144-
15145-	float dpi = 96.0f * monitor.pixelRatio;
15146-	monitor.scaleX = dpi / 96.0f;
15147-	monitor.scaleY = dpi / 96.0f;
15148-
15149-	RGFW_splitBPP(32, &monitor.mode);
15150-
15151-	monitor.mode.refreshRate = 0;
15152-
15153-	node = RGFW_monitors_add(&monitor);
15154-	if (node != NULL) {
15155-		_RGFW->monitors.primary = node;
15156-		RGFW_monitorCallback(_RGFW->root, &node->mon, RGFW_TRUE);
15157-	}
15158-
15159-	return 0;
15160-}
15161-
15162-RGFW_window* RGFW_createWindowPlatform(const char* name, RGFW_windowFlags flags, RGFW_window* win) {
15163-	emscripten_set_canvas_element_size("#canvas", win->w, win->h);
15164-	emscripten_set_window_title(name);
15165-
15166-	/* load callbacks */
15167-    emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, Emscripten_on_resize);
15168-    emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, NULL, EM_FALSE, Emscripten_on_fullscreenchange);
15169-    emscripten_set_mousemove_callback("#canvas", NULL, EM_FALSE, Emscripten_on_mousemove);
15170-    emscripten_set_touchstart_callback("#canvas", NULL, EM_FALSE, Emscripten_on_touchstart);
15171-    emscripten_set_touchend_callback("#canvas", NULL, EM_FALSE, Emscripten_on_touchend);
15172-    emscripten_set_touchmove_callback("#canvas", NULL, EM_FALSE, Emscripten_on_touchmove);
15173-    emscripten_set_touchcancel_callback("#canvas", NULL, EM_FALSE, Emscripten_on_touchcancel);
15174-    emscripten_set_mousedown_callback("#canvas", NULL, EM_FALSE, Emscripten_on_mousedown);
15175-    emscripten_set_mouseup_callback("#canvas", NULL, EM_FALSE, Emscripten_on_mouseup);
15176-    emscripten_set_wheel_callback("#canvas", NULL, EM_FALSE, Emscripten_on_wheel);
15177-    emscripten_set_focusin_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, Emscripten_on_focusin);
15178-    emscripten_set_focusout_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, Emscripten_on_focusout);
15179-
15180-	if (flags & RGFW_windowAllowDND)  {
15181-		win->internal.flags |= RGFW_windowAllowDND;
15182-	}
15183-
15184-	EM_ASM({
15185-		window.addEventListener("keydown",
15186-			(event) => {
15187-				var code = stringToNewUTF8(event.code);
15188-				Module._RGFW_handleKeyMods(event.getModifierState("CapsLock"), event.getModifierState("NumLock"), event.getModifierState("Control"), event.getModifierState("Alt"), event.getModifierState("Shift"), event.getModifierState("Meta"), event.getModifierState("ScrollLock"));
15189-
15190-				var codepoint = event.key.charCodeAt(0);
15191-				if(codepoint < 0x7f && event.key.length > 1) {
15192-					codepoint = 0;
15193-				}
15194-
15195-				Module._RGFW_handleKeyEvent(code, codepoint, 1);
15196-				_free(code);
15197-			},
15198-		true);
15199-		window.addEventListener("keyup",
15200-			(event) => {
15201-				var code = stringToNewUTF8(event.code);
15202-				Module._RGFW_handleKeyMods(event.getModifierState("CapsLock"), event.getModifierState("NumLock"), event.getModifierState("Control"), event.getModifierState("Alt"), event.getModifierState("Shift"), event.getModifierState("Meta"), event.getModifierState("ScrollLock"));
15203-				Module._RGFW_handleKeyEvent(code, 0, 0);
15204-				_free(code);
15205-			},
15206-		true);
15207-	});
15208-
15209-    EM_ASM({
15210-		var canvas = document.getElementById('canvas');
15211-        canvas.addEventListener('drop', function(e) {
15212-            e.preventDefault();
15213-            if (e.dataTransfer.file < 0)
15214-				return;
15215-
15216-			var count = e.dataTransfer.files.length;
15217-
15218-			/* Read and save the files to emscripten's files */
15219-			var drop_dir = '.rgfw_dropped_files';
15220-			Module._RGFW_mkdir(drop_dir);
15221-
15222-			for (var i = 0; i < count; i++) {
15223-				var file = e.dataTransfer.files[i];
15224-
15225-				var path = '/' + drop_dir + '/' + file.name.replace("//", '_');
15226-				var reader = new FileReader();
15227-
15228-				reader.onloadend = (e) => {
15229-					if (reader.readyState != 2) {
15230-						out('failed to read dropped file: '+file.name+': '+reader.error);
15231-					}
15232-					else {
15233-						var data = e.target.result;
15234-
15235-						Module._RGFW_writeFile(path, new Uint8Array(data), file.size);
15236-					}
15237-				};
15238-
15239-				reader.readAsArrayBuffer(file);
15240-				var filename = stringToNewUTF8(path);
15241-
15242-				Module._Emscripten_onDrop(filename, path.length + 1);
15243-				free(filename);
15244-			}
15245-
15246-        }, true);
15247-
15248-        canvas.addEventListener('dragover', function(e) { e.preventDefault(); return false; }, true);
15249-    });
15250-
15251-	return win;
15252-}
15253-
15254-RGFW_key RGFW_physicalToMappedKey(RGFW_key key) {
15255-	return key;
15256-}
15257-
15258-RGFW_bool RGFW_window_fetchSize(RGFW_window* win, i32* w, i32* h) {
15259-	return RGFW_window_getSize(win, w, h);
15260-}
15261-
15262-void RGFW_pollEvents(void) {
15263-	RGFW_resetPrevState();
15264-	emscripten_sleep(0);
15265-}
15266-
15267-void RGFW_window_resize(RGFW_window* win, i32 w, i32 h) {
15268-	RGFW_UNUSED(win);
15269-	emscripten_set_canvas_element_size("#canvas", w, h);
15270-}
15271-
15272-RGFW_mouse* RGFW_createMouseStandard(RGFW_mouseIcon mouse) {
15273-	char* cursorName = NULL;
15274-
15275-	switch (mouse) {
15276-		case RGFW_mouseNormal:       cursorName = (char*)"default"; break;
15277-		case RGFW_mouseArrow:        cursorName = (char*)"default"; break;
15278-		case RGFW_mouseIbeam:        cursorName = (char*)"text"; break;
15279-		case RGFW_mouseCrosshair:    cursorName = (char*)"crosshair"; break;
15280-		case RGFW_mousePointingHand: cursorName = (char*)"pointer"; break;
15281-		case RGFW_mouseResizeEW:     cursorName = (char*)"ew-resize"; break;
15282-		case RGFW_mouseResizeNS:     cursorName = (char*)"ns-resize"; break;
15283-		case RGFW_mouseResizeNWSE:   cursorName = (char*)"nwse-resize"; break;
15284-		case RGFW_mouseResizeNESW:   cursorName = (char*)"nesw-resize"; break;
15285-		case RGFW_mouseResizeNW:     cursorName = (char*)"nw-resize"; break;
15286-		case RGFW_mouseResizeN:      cursorName = (char*)"n-resize"; break;
15287-		case RGFW_mouseResizeNE:     cursorName = (char*)"ne-resize"; break;
15288-		case RGFW_mouseResizeE:      cursorName = (char*)"e-resize"; break;
15289-		case RGFW_mouseResizeSE:     cursorName = (char*)"se-resize"; break;
15290-		case RGFW_mouseResizeS:      cursorName = (char*)"s-resize"; break;
15291-		case RGFW_mouseResizeSW:     cursorName = (char*)"sw-resize"; break;
15292-		case RGFW_mouseResizeW:      cursorName = (char*)"w-resize"; break;
15293-		case RGFW_mouseResizeAll:    cursorName = (char*)"move"; break;
15294-		case RGFW_mouseNotAllowed:   cursorName = (char*)"not-allowed"; break;
15295-		case RGFW_mouseWait:         cursorName = (char*)"wait"; break;
15296-		case RGFW_mouseProgress:     cursorName = (char*)"progress"; break;
15297-		default:                     return NULL;
15298-	}
15299-
15300-	return (RGFW_mouse*)cursorName;
15301-}
15302-
15303-/* NOTE: I don't know if this is possible */
15304-void RGFW_window_moveMouse(RGFW_window* win, i32 x, i32 y) { RGFW_UNUSED(win); RGFW_UNUSED(x); RGFW_UNUSED(y); }
15305-/* this one might be possible but it looks iffy */
15306-RGFW_mouse* RGFW_createMouse(u8* data, i32 w, i32 h, RGFW_format format) { RGFW_UNUSED(data); RGFW_UNUSED(w); RGFW_UNUSED(h); RGFW_UNUSED(format); return NULL; }
15307-
15308-RGFW_bool RGFW_window_setMousePlatform(RGFW_window* win, RGFW_mouse* mouse) {
15309-	RGFW_ASSERT(win != NULL);
15310-	RGFW_ASSERT(mouse != NULL);
15311-
15312-	EM_ASM( { document.getElementById("canvas").style.cursor = UTF8ToString($0); }, (char*)mouse);
15313-	return RGFW_TRUE;
15314-}
15315-void RGFW_freeMouse(RGFW_mouse* mouse) { RGFW_UNUSED(mouse); }
15316-
15317-void RGFW_window_showMouse(RGFW_window* win, RGFW_bool show) {
15318-	RGFW_window_showMouseFlags(win, show);
15319-	if (show)
15320-		RGFW_window_setMouseDefault(win);
15321-	else
15322-		EM_ASM(document.getElementById('canvas').style.cursor = 'none';);
15323-}
15324-
15325-RGFW_bool RGFW_getGlobalMouse(i32* x, i32* y) {
15326-    if(x) *x = EM_ASM_INT({
15327-        return window.mouseX || 0;
15328-    });
15329-    if (y) *y = EM_ASM_INT({
15330-        return window.mouseY || 0;
15331-    });
15332-    return RGFW_TRUE;
15333-}
15334-
15335-void RGFW_window_setMousePassthrough(RGFW_window* win, RGFW_bool passthrough) {
15336-	RGFW_UNUSED(win);
15337-
15338-    EM_ASM_({
15339-        var canvas = document.getElementById('canvas');
15340-        if ($0) {
15341-            canvas.style.pointerEvents = 'none';
15342-        } else {
15343-            canvas.style.pointerEvents = 'auto';
15344-        }
15345-    }, passthrough);
15346-}
15347-
15348-void RGFW_writeClipboard(const char* text, u32 textLen) {
15349-	RGFW_UNUSED(textLen);
15350-	EM_ASM({ navigator.clipboard.writeText(UTF8ToString($0)); }, text);
15351-}
15352-
15353-
15354-RGFW_ssize_t RGFW_readClipboardPtr(char* str, size_t strCapacity) {
15355-	RGFW_UNUSED(str); RGFW_UNUSED(strCapacity);
15356-	/*
15357-		placeholder code for later
15358-		I'm not sure if this is possible do the the async stuff
15359-	*/
15360-	return 0;
15361-}
15362-
15363-#ifdef RGFW_OPENGL
15364-RGFW_bool RGFW_window_createContextPtr_OpenGL(RGFW_window* win, RGFW_glContext* ctx, RGFW_glHints* hints) {
15365-	win->src.ctx.native = ctx;
15366-	win->src.gfxType = RGFW_gfxNativeOpenGL;
15367-
15368-	EmscriptenWebGLContextAttributes attrs;
15369-	emscripten_webgl_init_context_attributes(&attrs);
15370-	attrs.alpha = hints->alpha;
15371-	attrs.depth = hints->depth;
15372-	attrs.stencil = hints->stencil;
15373-	attrs.antialias = hints->samples;
15374-	attrs.premultipliedAlpha = EM_TRUE;
15375-	attrs.preserveDrawingBuffer = EM_FALSE;
15376-
15377-	if (hints->doubleBuffer == 0)
15378-		attrs.renderViaOffscreenBackBuffer = 0;
15379-	else
15380-		attrs.renderViaOffscreenBackBuffer = hints->auxBuffers;
15381-
15382-	attrs.failIfMajorPerformanceCaveat = EM_FALSE;
15383-
15384-	attrs.enableExtensionsByDefault = EM_TRUE;
15385-	attrs.explicitSwapControl = EM_TRUE;
15386-
15387-	if (hints->profile == RGFW_glWeb) {
15388-		attrs.majorVersion = (hints->major == 0) ? 1 : hints->major;
15389-		attrs.minorVersion = hints->minor;
15390-	} else {
15391-		attrs.majorVersion = (hints->major == 0) ? 1 : hints->major - 1;
15392-		attrs.minorVersion = hints->minor;
15393-	}
15394-
15395-	win->src.ctx.native->ctx = emscripten_webgl_create_context("#canvas", &attrs);
15396-	emscripten_webgl_make_context_current(win->src.ctx.native->ctx);
15397-
15398-	#ifdef LEGACY_GL_EMULATION
15399-	EM_ASM("Module.useWebGL = true; GLImmediate.init();");
15400-	RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "OpenGL context initalized.");
15401-    #endif
15402-
15403-	RGFW_window_swapInterval_OpenGL(win, 0);
15404-
15405-	return RGFW_TRUE;
15406-}
15407-
15408-void RGFW_window_deleteContextPtr_OpenGL(RGFW_window* win, RGFW_glContext* ctx) {
15409-	emscripten_webgl_destroy_context(ctx->ctx);
15410-	win->src.ctx.native->ctx = 0;
15411-	RGFW_debugCallback(RGFW_typeInfo, RGFW_infoOpenGL, "OpenGL context freed.");
15412-}
15413-
15414-void RGFW_window_makeCurrentContext_OpenGL(RGFW_window* win) {
15415-	if (win) RGFW_ASSERT(win->src.ctx.native);
15416-	if (win == NULL)
15417-	    emscripten_webgl_make_context_current(0);
15418-	else
15419-	    emscripten_webgl_make_context_current(win->src.ctx.native->ctx);
15420-}
15421-
15422-void RGFW_window_swapBuffers_OpenGL(RGFW_window* win) {
15423-	RGFW_ASSERT(win && win->src.ctx.native);
15424-	emscripten_webgl_commit_frame();
15425-}
15426-void* RGFW_getCurrentContext_OpenGL(void) { return (void*)emscripten_webgl_get_current_context(); }
15427-
15428-RGFW_bool RGFW_extensionSupportedPlatform_OpenGL(const char* extension, size_t len) {
15429-    return EM_ASM_INT({
15430-        var ext = UTF8ToString($0, $1);
15431-        var canvas = document.querySelector('canvas');
15432-        var gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
15433-        if (!gl) return 0;
15434-
15435-        var supported = gl.getSupportedExtensions();
15436-        return supported && supported.includes(ext) ? 1 : 0;
15437-    }, extension, len);
15438-    return RGFW_FALSE;
15439-}
15440-
15441-RGFW_proc RGFW_getProcAddress_OpenGL(const char* procname) {
15442-    return (RGFW_proc)emscripten_webgl_get_proc_address(procname);
15443-    return NULL;
15444-}
15445-
15446-#endif
15447-
15448-void RGFW_window_swapInterval_OpenGL(RGFW_window* win, i32 swapInterval) { RGFW_UNUSED(win); RGFW_UNUSED(swapInterval); }
15449-
15450-void RGFW_deinitPlatform(void) { }
15451-
15452-void RGFW_window_closePlatform(RGFW_window* win) { }
15453-
15454-int RGFW_innerWidth(void) {   return EM_ASM_INT({ return window.innerWidth; });  }
15455-int RGFW_innerHeight(void) {  return EM_ASM_INT({ return window.innerHeight; });  }
15456-
15457-void RGFW_window_setRawMouseModePlatform(RGFW_window* win, RGFW_bool state) {
15458-	RGFW_UNUSED(win); RGFW_UNUSED(state);
15459-}
15460-
15461-void RGFW_window_captureMousePlatform(RGFW_window* win, RGFW_bool state) {
15462-	RGFW_UNUSED(win);
15463-	if (state) {
15464-		emscripten_request_pointerlock("#canvas", 1);
15465-	} else {
15466-		emscripten_exit_pointerlock();
15467-	}
15468-}
15469-
15470-void RGFW_window_setName(RGFW_window* win, const char* name) {
15471-	RGFW_UNUSED(win);
15472-	if (name == NULL) name = "\0";
15473-
15474-	emscripten_set_window_title(name);
15475-}
15476-
15477-void RGFW_window_maximize(RGFW_window* win) {
15478-	RGFW_ASSERT(win != NULL);
15479-
15480-	RGFW_monitor* mon = RGFW_window_getMonitor(win);
15481-	if (mon != NULL) {
15482-		RGFW_window_resize(win, mon->mode.w, mon->mode.h);
15483-	}
15484-
15485-	RGFW_window_move(win, 0, 0);
15486-	RGFW_window_fetchSize(win, NULL, NULL);
15487-}
15488-
15489-void RGFW_window_setFullscreen(RGFW_window* win, RGFW_bool fullscreen) {
15490-	RGFW_ASSERT(win != NULL);
15491-	if (fullscreen) {
15492-		win->internal.flags |= RGFW_windowFullscreen;
15493-		EM_ASM( Module.requestFullscreen(false, true); );
15494-		return;
15495-	}
15496-	win->internal.flags &= ~(u32)RGFW_windowFullscreen;
15497-	EM_ASM( Module.exitFullscreen(false, true); );
15498-}
15499-
15500-void RGFW_window_setOpacity(RGFW_window* win, u8 opacity) {
15501-	RGFW_UNUSED(win);
15502-	EM_ASM({
15503-		var element = document.getElementById("canvas");
15504-		if (element)
15505-		  element.style.opacity = $1;
15506-	  }, "elementId", opacity);
15507-}
15508-
15509-#ifdef RGFW_WEBGPU
15510-WGPUSurface RGFW_window_createSurface_WebGPU(RGFW_window* window, WGPUInstance instance) {
15511-	WGPUSurfaceDescriptor surfaceDesc = {0};
15512-	WGPUEmscriptenSurfaceSourceCanvasHTMLSelector canvasDesc = {0};
15513-    canvasDesc.chain.sType = WGPUSType_EmscriptenSurfaceSourceCanvasHTMLSelector;
15514-    canvasDesc.selector = (WGPUStringView){.data = "#canvas", .length = 7};
15515-
15516-    surfaceDesc.nextInChain = &canvasDesc.chain;
15517-    return wgpuInstanceCreateSurface(instance, &surfaceDesc);
15518-}
15519-#endif
15520-
15521-RGFW_key RGFW_WASMPhysicalToRGFW(u32 hash) {
15522-	switch(hash) {             /* 0x0000 */
15523-		case 0x67243A2DU /* Escape             */: return RGFW_keyEscape;               /* 0x0001 */
15524-		case 0x67251058U /* Digit0             */: return RGFW_key0;                    /* 0x0002 */
15525-		case 0x67251059U /* Digit1             */: return RGFW_key1;                    /* 0x0003 */
15526-		case 0x6725105AU /* Digit2             */: return RGFW_key2;                    /* 0x0004 */
15527-		case 0x6725105BU /* Digit3             */: return RGFW_key3;                    /* 0x0005 */
15528-		case 0x6725105CU /* Digit4             */: return RGFW_key4;                    /* 0x0006 */
15529-		case 0x6725105DU /* Digit5             */: return RGFW_key5;                    /* 0x0007 */
15530-		case 0x6725105EU /* Digit6             */: return RGFW_key6;                    /* 0x0008 */
15531-		case 0x6725105FU /* Digit7             */: return RGFW_key7;                    /* 0x0009 */
15532-		case 0x67251050U /* Digit8             */: return RGFW_key8;                    /* 0x000A */
15533-		case 0x67251051U /* Digit9             */: return RGFW_key9;                    /* 0x000B */
15534-		case 0x92E14DD3U /* Minus              */: return RGFW_keyMinus;                /* 0x000C */
15535-		case 0x92E1FBACU /* Equal              */: return RGFW_keyEquals;                /* 0x000D */
15536-		case 0x36BF1CB5U /* Backspace          */: return RGFW_keyBackSpace;            /* 0x000E */
15537-		case 0x7B8E51E2U  /* Tab                */: return RGFW_keyTab;                  /* 0x000F */
15538-		case 0x2C595B51U /* KeyQ               */: return RGFW_keyQ;                    /* 0x0010 */
15539-		case 0x2C595B57U /* KeyW               */: return RGFW_keyW;                    /* 0x0011 */
15540-		case 0x2C595B45U /* KeyE               */: return RGFW_keyE;                    /* 0x0012 */
15541-		case 0x2C595B52U /* KeyR               */: return RGFW_keyR;                    /* 0x0013 */
15542-		case 0x2C595B54U /* KeyT               */: return RGFW_keyT;                    /* 0x0014 */
15543-		case 0x2C595B59U /* KeyY               */: return RGFW_keyY;                    /* 0x0015 */
15544-		case 0x2C595B55U /* KeyU               */: return RGFW_keyU;                    /* 0x0016 */
15545-		case 0x2C595B4FU /* KeyO               */: return RGFW_keyO;                    /* 0x0018 */
15546-		case 0x2C595B50U /* KeyP               */: return RGFW_keyP;                    /* 0x0019 */
15547-		case 0x45D8158CU /* BracketLeft        */: return RGFW_keyCloseBracket;         /* 0x001A */
15548-		case 0xDEEABF7CU /* BracketRight       */: return RGFW_keyBracket;        /* 0x001B */
15549-		case 0x92E1C5D2U /* Enter              */: return RGFW_keyReturn;                /* 0x001C */
15550-		case 0xE058958CU /* ControlLeft        */: return RGFW_keyControlL;         /* 0x001D */
15551-		case 0x2C595B41U /* KeyA               */: return RGFW_keyA;                    /* 0x001E */
15552-		case 0x2C595B53U /* KeyS               */: return RGFW_keyS;                    /* 0x001F */
15553-		case 0x2C595B44U /* KeyD               */: return RGFW_keyD;                    /* 0x0020 */
15554-		case 0x2C595B46U /* KeyF               */: return RGFW_keyF;                    /* 0x0021 */
15555-		case 0x2C595B47U /* KeyG               */: return RGFW_keyG;                    /* 0x0022 */
15556-		case 0x2C595B48U /* KeyH               */: return RGFW_keyH;                    /* 0x0023 */
15557-		case 0x2C595B4AU /* KeyJ               */: return RGFW_keyJ;                    /* 0x0024 */
15558-		case 0x2C595B4BU /* KeyK               */: return RGFW_keyK;                    /* 0x0025 */
15559-		case 0x2C595B4CU /* KeyL               */: return RGFW_keyL;                    /* 0x0026 */
15560-		case 0x2707219EU /* Semicolon          */: return RGFW_keySemicolon;            /* 0x0027 */
15561-		case 0x92E0B58DU /* Quote              */: return RGFW_keyApostrophe;                /* 0x0028 */
15562-		case 0x36BF358DU /* Backquote          */: return RGFW_keyBacktick;            /* 0x0029 */
15563-		case 0x26B1958CU /* ShiftLeft          */: return RGFW_keyShiftL;           /* 0x002A */
15564-		case 0x36BF2438U /* Backslash          */: return RGFW_keyBackSlash;            /* 0x002B */
15565-		case 0x2C595B5AU /* KeyZ               */: return RGFW_keyZ;                    /* 0x002C */
15566-		case 0x2C595B58U /* KeyX               */: return RGFW_keyX;                    /* 0x002D */
15567-		case 0x2C595B43U /* KeyC               */: return RGFW_keyC;                    /* 0x002E */
15568-		case 0x2C595B56U /* KeyV               */: return RGFW_keyV;                    /* 0x002F */
15569-		case 0x2C595B42U /* KeyB               */: return RGFW_keyB;                    /* 0x0030 */
15570-		case 0x2C595B4EU /* KeyN               */: return RGFW_keyN;                    /* 0x0031 */
15571-		case 0x2C595B4DU /* KeyM               */: return RGFW_keyM;                    /* 0x0032 */
15572-		case 0x92E1A1C1U /* Comma              */: return RGFW_keyComma;                /* 0x0033 */
15573-		case 0x672FFAD4U /* Period             */: return RGFW_keyPeriod;               /* 0x0034 */
15574-		case 0x92E0A438U /* Slash              */: return RGFW_keySlash;                /* 0x0035 */
15575-		case 0xC5A6BF7CU /* ShiftRight         */: return RGFW_keyShiftR;
15576-		case 0x5D64DA91U /* NumpadMultiply     */: return RGFW_keyPadMultiply;
15577-		case 0xC914958CU /* AltLeft            */: return RGFW_keyAltL;             /* 0x0038 */
15578-		case 0x92E09CB5U /* Space              */: return RGFW_keySpace;                /* 0x0039 */
15579-		case 0xB8FAE73BU  /* CapsLock           */: return RGFW_keyCapsLock;            /* 0x003A */
15580-		case 0x7174B789U /* F1                 */: return RGFW_keyF1;                   /* 0x003B */
15581-		case 0x7174B78AU /* F2                 */: return RGFW_keyF2;                   /* 0x003C */
15582-		case 0x7174B78BU /* F3                 */: return RGFW_keyF3;                   /* 0x003D */
15583-		case 0x7174B78CU /* F4                 */: return RGFW_keyF4;                   /* 0x003E */
15584-		case 0x7174B78DU /* F5                 */: return RGFW_keyF5;                   /* 0x003F */
15585-		case 0x7174B78EU /* F6                 */: return RGFW_keyF6;                   /* 0x0040 */
15586-		case 0x7174B78FU /* F7                 */: return RGFW_keyF7;                   /* 0x0041 */
15587-		case 0x7174B780U /* F8                 */: return RGFW_keyF8;                   /* 0x0042 */
15588-		case 0x7174B781U /* F9                 */: return RGFW_keyF9;                   /* 0x0043 */
15589-		case 0x7B8E57B0U  /* F10                */: return RGFW_keyF10;                  /* 0x0044 */
15590-		case 0xC925FCDFU /* Numpad7            */: return RGFW_keyPadMultiply;             /* 0x0047 */
15591-		case 0xC925FCD0U /* Numpad8            */: return RGFW_keyPad8;             /* 0x0048 */
15592-		case 0xC925FCD1U /* Numpad9            */: return RGFW_keyPad9;             /* 0x0049 */
15593-		case 0x5EA3E8A4U /* NumpadSubtract     */: return RGFW_keyMinus;      /* 0x004A */
15594-		case 0xC925FCDCU /* Numpad4            */: return RGFW_keyPad4;             /* 0x004B */
15595-		case 0xC925FCDDU /* Numpad5            */: return RGFW_keyPad5;             /* 0x004C */
15596-		case 0xC925FCDEU /* Numpad6            */: return RGFW_keyPad6;             /* 0x004D */
15597-		case 0xC925FCD9U /* Numpad1            */: return RGFW_keyPad1;             /* 0x004F */
15598-		case 0xC925FCDAU /* Numpad2            */: return RGFW_keyPad2;             /* 0x0050 */
15599-		case 0xC925FCDBU /* Numpad3            */: return RGFW_keyPad3;             /* 0x0051 */
15600-		case 0xC925FCD8U /* Numpad0            */: return RGFW_keyPad0;             /* 0x0052 */
15601-		case 0x95852DACU /* NumpadDecimal      */: return RGFW_keyPeriod;       /* 0x0053 */
15602-		case 0x7B8E57B1U  /* F11                */: return RGFW_keyF11;                  /* 0x0057 */
15603-		case 0x7B8E57B2U  /* F12                */: return RGFW_keyF12;                  /* 0x0058 */
15604-		case 0x7B8E57B3U /* F13                */: return DOM_PK_F13;                  /* 0x0064 */
15605-		case 0x7B8E57B4U /* F14                */: return DOM_PK_F14;                  /* 0x0065 */
15606-		case 0x7B8E57B5U /* F15                */: return DOM_PK_F15;                  /* 0x0066 */
15607-		case 0x7B8E57B6U /* F16                */: return DOM_PK_F16;                  /* 0x0067 */
15608-		case 0x7B8E57B7U /* F17                */: return DOM_PK_F17;                  /* 0x0068 */
15609-		case 0x7B8E57B8U /* F18                */: return DOM_PK_F18;                  /* 0x0069 */
15610-		case 0x7B8E57B9U /* F19                */: return DOM_PK_F19;                  /* 0x006A */
15611-		case 0x7B8E57A8U /* F20                */: return DOM_PK_F20;                  /* 0x006B */
15612-		case 0x7B8E57A9U /* F21                */: return DOM_PK_F21;                  /* 0x006C */
15613-		case 0x7B8E57AAU /* F22                */: return DOM_PK_F22;                  /* 0x006D */
15614-		case 0x7B8E57ABU /* F23                */: return DOM_PK_F23;                  /* 0x006E */
15615-		case 0x7393FBACU /* NumpadEqual        */: return RGFW_keyPadReturn;
15616-		case 0xB88EBF7CU  /* AltRight           */: return RGFW_keyAltR;            /* 0xE038 */
15617-		case 0xC925873BU /* NumLock            */: return RGFW_keyNumLock;             /* 0xE045 */
15618-		case 0x2C595F45U /* Home               */: return RGFW_keyHome;                 /* 0xE047 */
15619-		case 0xC91BB690U /* ArrowUp            */: return RGFW_keyUp;             /* 0xE048 */
15620-		case 0x672F9210U /* PageUp             */: return RGFW_keyPageUp;              /* 0xE049 */
15621-		case 0x3799258CU /* ArrowLeft          */: return RGFW_keyLeft;           /* 0xE04B */
15622-		case 0x4CE33F7CU /* ArrowRight         */: return RGFW_keyRight;          /* 0xE04D */
15623-		case 0x7B8E55DCU  /* End                */: return RGFW_keyEnd;                  /* 0xE04F */
15624-		case 0x3799379EU /* ArrowDown          */: return RGFW_keyDown;           /* 0xE050 */
15625-		case 0xBA90179EU /* PageDown           */: return RGFW_keyPageDown;            /* 0xE051 */
15626-		case 0x6723CB2CU /* Insert             */: return RGFW_keyInsert;               /* 0xE052 */
15627-		case 0x6725C50DU /* Delete             */: return RGFW_keyDelete;               /* 0xE053 */
15628-		case 0x6723658CU /* OSLeft             */: return RGFW_keySuperL;              /* 0xE05B */
15629-		case 0x39643F7CU /* MetaRight          */: return RGFW_keySuperR;           /* 0xE05C */
15630-		case 0x380B9C8CU /* NumpadAdd          */: return DOM_PK_NUMPAD_ADD;           /* 0x004E */
15631-		default: return DOM_PK_UNKNOWN;
15632-	}
15633-
15634-	return 0;
15635-}
15636-
15637-RGFW_monitor* RGFW_window_getMonitor(RGFW_window* win) {
15638-	RGFW_UNUSED(win);
15639-	return RGFW_getPrimaryMonitor();
15640-}
15641-
15642-/* unsupported functions */
15643-void RGFW_pollMonitors(void) { }
15644-void RGFW_window_focus(RGFW_window* win) { RGFW_UNUSED(win); }
15645-void RGFW_window_raise(RGFW_window* win) { RGFW_UNUSED(win); }
15646-RGFW_bool RGFW_monitor_requestMode(RGFW_monitor* mon, RGFW_monitorMode* mode, RGFW_modeRequest request) { RGFW_UNUSED(mon); RGFW_UNUSED(mode); RGFW_UNUSED(request); return RGFW_FALSE; }
15647-RGFW_bool RGFW_monitor_getWorkarea(RGFW_monitor* monitor, i32* x, i32* y, i32* width, i32* height) { RGFW_UNUSED(monitor); RGFW_UNUSED(x); RGFW_UNUSED(width); RGFW_UNUSED(height); return RGFW_FALSE; }
15648-size_t RGFW_monitor_getGammaRampPtr(RGFW_monitor* monitor, RGFW_gammaRamp* ramp) { RGFW_UNUSED(monitor); RGFW_UNUSED(ramp); return 0; }
15649-RGFW_bool RGFW_monitor_setGammaRamp(RGFW_monitor* monitor, RGFW_gammaRamp* ramp) { RGFW_UNUSED(monitor); RGFW_UNUSED(ramp); return RGFW_FALSE; }
15650-size_t RGFW_monitor_getModesPtr(RGFW_monitor* mon, RGFW_monitorMode** modes) { RGFW_UNUSED(mon); RGFW_UNUSED(modes); return 0; }
15651-RGFW_bool RGFW_monitor_setMode(RGFW_monitor* mon, RGFW_monitorMode* mode) { RGFW_UNUSED(mon); RGFW_UNUSED(mode); return RGFW_FALSE; }
15652-void RGFW_window_move(RGFW_window* win, i32 x, i32 y) { RGFW_UNUSED(win);  RGFW_UNUSED(x); RGFW_UNUSED(y);  }
15653-void RGFW_window_setAspectRatio(RGFW_window* win, i32 w, i32 h) { RGFW_UNUSED(win);  RGFW_UNUSED(w); RGFW_UNUSED(h);  }
15654-void RGFW_window_setMinSize(RGFW_window* win, i32 w, i32 h) { RGFW_UNUSED(win); RGFW_UNUSED(w); RGFW_UNUSED(h);  }
15655-void RGFW_window_setMaxSize(RGFW_window* win, i32 w, i32 h) { RGFW_UNUSED(win);  RGFW_UNUSED(w); RGFW_UNUSED(h);  }
15656-void RGFW_window_minimize(RGFW_window* win) { RGFW_UNUSED(win); }
15657-void RGFW_window_restore(RGFW_window* win) { RGFW_UNUSED(win); }
15658-void RGFW_window_setFloating(RGFW_window* win, RGFW_bool floating) { RGFW_UNUSED(win); RGFW_UNUSED(floating); }
15659-void RGFW_window_setBorder(RGFW_window* win, RGFW_bool border) { RGFW_UNUSED(win); RGFW_UNUSED(border);  }
15660-RGFW_bool RGFW_window_setIconEx(RGFW_window* win, u8* data, i32 w, i32 h, RGFW_format format, RGFW_icon type) { RGFW_UNUSED(win); RGFW_UNUSED(data); RGFW_UNUSED(w); RGFW_UNUSED(h); RGFW_UNUSED(format);  RGFW_UNUSED(type); return RGFW_FALSE;  }
15661-void RGFW_window_hide(RGFW_window* win) { RGFW_UNUSED(win); }
15662-void RGFW_window_show(RGFW_window* win) {RGFW_UNUSED(win); }
15663-void RGFW_window_flash(RGFW_window* win, RGFW_flashRequest request) { RGFW_UNUSED(win); RGFW_UNUSED(request); }
15664-RGFW_bool RGFW_window_isHidden(RGFW_window* win) { RGFW_UNUSED(win); return RGFW_FALSE; }
15665-RGFW_bool RGFW_window_isMinimized(RGFW_window* win) { RGFW_UNUSED(win); return RGFW_FALSE; }
15666-RGFW_bool RGFW_window_isMaximized(RGFW_window* win) { RGFW_UNUSED(win); return RGFW_FALSE; }
15667-RGFW_bool RGFW_window_isFloating(RGFW_window* win) { RGFW_UNUSED(win); return RGFW_FALSE; }
15668-void RGFW_waitForEvent(i32 waitMS) { RGFW_UNUSED(waitMS); }
15669-#endif
15670-
15671-/* end of web asm defines */
15672-
15673-/*
15674-	* RGFW function pointer backend, made to allow you to compile for Wayland but fallback to X11
15675-*/
15676-#ifdef RGFW_DYNAMIC
15677-typedef RGFW_window* (*RGFW_createWindowPlatform_ptr)(const char* name, RGFW_windowFlags flags, RGFW_window* win);
15678-typedef RGFW_bool (*RGFW_getMouse_ptr)(i32* x, i32* y);
15679-typedef RGFW_key (*RGFW_physicalToMappedKey_ptr)(RGFW_key key);
15680-typedef void (*RGFW_pollEvents_ptr)(void);
15681-typedef RGFW_bool (*RGFW_window_fetchSize_ptr)(RGFW_window* win, i32* w, i32* h);
15682-typedef void (*RGFW_pollMonitors_ptr)(void);
15683-typedef void (*RGFW_window_move_ptr)(RGFW_window* win, i32 x, i32 y);
15684-typedef void (*RGFW_window_resize_ptr)(RGFW_window* win, i32 w, i32 h);
15685-typedef void (*RGFW_window_setAspectRatio_ptr)(RGFW_window* win, i32 w, i32 h);
15686-typedef void (*RGFW_window_setMinSize_ptr)(RGFW_window* win, i32 w, i32 h);
15687-typedef void (*RGFW_window_setMaxSize_ptr)(RGFW_window* win, i32 w, i32 h);
15688-typedef void (*RGFW_window_maximize_ptr)(RGFW_window* win);
15689-typedef void (*RGFW_window_focus_ptr)(RGFW_window* win);
15690-typedef void (*RGFW_window_raise_ptr)(RGFW_window* win);
15691-typedef void (*RGFW_window_setFullscreen_ptr)(RGFW_window* win, RGFW_bool fullscreen);
15692-typedef void (*RGFW_window_setFloating_ptr)(RGFW_window* win, RGFW_bool floating);
15693-typedef void (*RGFW_window_setOpacity_ptr)(RGFW_window* win, u8 opacity);
15694-typedef void (*RGFW_window_minimize_ptr)(RGFW_window* win);
15695-typedef void (*RGFW_window_restore_ptr)(RGFW_window* win);
15696-typedef RGFW_bool (*RGFW_window_isFloating_ptr)(RGFW_window* win);
15697-typedef void (*RGFW_window_setName_ptr)(RGFW_window* win, const char* name);
15698-typedef void (*RGFW_window_setMousePassthrough_ptr)(RGFW_window* win, RGFW_bool passthrough);
15699-typedef RGFW_bool (*RGFW_window_setIconEx_ptr)(RGFW_window* win, u8* data, i32 w, i32 h, RGFW_format format, u8 type);
15700-typedef RGFW_mouse* (*RGFW_createMouse_ptr)(u8* data, i32 w, i32 h, RGFW_format format);
15701-typedef RGFW_mouse* (*RGFW_createMouseStandard_ptr)(RGFW_mouseIcon icons);
15702-typedef RGFW_bool (*RGFW_window_setMousePlatform_ptr)(RGFW_window* win, RGFW_mouse* mouse);
15703-typedef void (*RGFW_window_moveMouse_ptr)(RGFW_window* win, i32 x, i32 y);
15704-typedef void (*RGFW_window_hide_ptr)(RGFW_window* win);
15705-typedef void (*RGFW_window_show_ptr)(RGFW_window* win);
15706-typedef void (*RGFW_window_flash_ptr)(RGFW_window* win, RGFW_flashRequest request);
15707-typedef RGFW_ssize_t (*RGFW_readClipboardPtr_ptr)(char* str, size_t strCapacity);
15708-typedef void (*RGFW_writeClipboard_ptr)(const char* text, u32 textLen);
15709-typedef RGFW_bool (*RGFW_window_isHidden_ptr)(RGFW_window* win);
15710-typedef RGFW_bool (*RGFW_window_isMinimized_ptr)(RGFW_window* win);
15711-typedef RGFW_bool (*RGFW_window_isMaximized_ptr)(RGFW_window* win);
15712-typedef RGFW_bool (*RGFW_monitor_requestMode_ptr)(RGFW_monitor* mon, RGFW_monitorMode* mode, RGFW_modeRequest request);
15713-typedef RGFW_bool (*RGFW_monitor_getWorkarea_ptr)(RGFW_monitor* mon, i32* x, i32* y, i32* w, i32* h);
15714-typedef size_t (*RGFW_monitor_getModesPtr_ptr)(RGFW_monitor* mon, RGFW_monitorMode** modes);
15715-typedef size_t (*RGFW_monitor_getGammaRampPtr_ptr) (RGFW_monitor* monitor, RGFW_gammaRamp* ramp);
15716-typedef RGFW_bool (*RGFW_monitor_setGammaRamp_ptr) (RGFW_monitor* monitor, RGFW_gammaRamp* ramp);
15717-typedef RGFW_bool (*RGFW_monitor_setMode_ptr)(RGFW_monitor* mon, RGFW_monitorMode* mode);
15718-typedef RGFW_monitor* (*RGFW_window_getMonitor_ptr)(RGFW_window* win);
15719-typedef void (*RGFW_window_closePlatform_ptr)(RGFW_window* win);
15720-typedef RGFW_format (*RGFW_nativeFormat_ptr)(void);
15721-typedef RGFW_bool (*RGFW_createSurfacePtr_ptr)(u8* data, i32 w, i32 h, RGFW_format format, RGFW_surface* surface);
15722-typedef void (*RGFW_window_blitSurface_ptr)(RGFW_window* win, RGFW_surface* surface);
15723-typedef void (*RGFW_surface_freePtr_ptr)(RGFW_surface* surface);
15724-typedef void (*RGFW_freeMouse_ptr)(RGFW_mouse* mouse);
15725-typedef void (*RGFW_window_setBorder_ptr)(RGFW_window* win, RGFW_bool border);
15726-typedef void (*RGFW_window_captureMousePlatform_ptr)(RGFW_window* win, RGFW_bool state);
15727-typedef void (*RGFW_window_setRawMouseModePlatform_ptr)(RGFW_window* win, RGFW_bool state);
15728-#ifdef RGFW_OPENGL
15729-typedef void (*RGFW_window_makeCurrentContext_OpenGL_ptr)(RGFW_window* win);
15730-typedef void* (*RGFW_getCurrentContext_OpenGL_ptr)(void);
15731-typedef void (*RGFW_window_swapBuffers_OpenGL_ptr)(RGFW_window* win);
15732-typedef void (*RGFW_window_swapInterval_OpenGL_ptr)(RGFW_window* win, i32 swapInterval);
15733-typedef RGFW_bool (*RGFW_extensionSupportedPlatform_OpenGL_ptr)(const char* extension, size_t len);
15734-typedef RGFW_proc (*RGFW_getProcAddress_OpenGL_ptr)(const char* procname);
15735-typedef RGFW_bool (*RGFW_window_createContextPtr_OpenGL_ptr)(RGFW_window* win, RGFW_glContext* ctx, RGFW_glHints* hints);
15736-typedef void (*RGFW_window_deleteContextPtr_OpenGL_ptr)(RGFW_window* win, RGFW_glContext* ctx);
15737-#endif
15738-#ifdef RGFW_WEBGPU
15739-typedef WGPUSurface (*RGFW_window_createSurface_WebGPU_ptr)(RGFW_window* window, WGPUInstance instance);
15740-#endif
15741-
15742-/* Structure to hold all function pointers */
15743-typedef struct RGFW_FunctionPointers {
15744-	RGFW_nativeFormat_ptr nativeFormat;
15745-	RGFW_createSurfacePtr_ptr createSurfacePtr;
15746-    RGFW_window_blitSurface_ptr window_blitSurface;
15747-	RGFW_surface_freePtr_ptr surface_freePtr;
15748-	RGFW_freeMouse_ptr freeMouse;
15749-    RGFW_window_setBorder_ptr window_setBorder;
15750-    RGFW_window_captureMousePlatform_ptr window_captureMousePlatform;
15751-	RGFW_window_setRawMouseModePlatform_ptr window_setRawMouseModePlatform;
15752-    RGFW_createWindowPlatform_ptr createWindowPlatform;
15753-    RGFW_getMouse_ptr getGlobalMouse;
15754-	RGFW_physicalToMappedKey_ptr physicalToMappedKey;
15755-    RGFW_window_fetchSize_ptr window_fetchSize;
15756-	RGFW_pollEvents_ptr pollEvents;
15757-    RGFW_pollMonitors_ptr pollMonitors;
15758-    RGFW_window_move_ptr window_move;
15759-    RGFW_window_resize_ptr window_resize;
15760-    RGFW_window_setAspectRatio_ptr window_setAspectRatio;
15761-    RGFW_window_setMinSize_ptr window_setMinSize;
15762-    RGFW_window_setMaxSize_ptr window_setMaxSize;
15763-    RGFW_window_maximize_ptr window_maximize;
15764-    RGFW_window_focus_ptr window_focus;
15765-    RGFW_window_raise_ptr window_raise;
15766-    RGFW_window_setFullscreen_ptr window_setFullscreen;
15767-    RGFW_window_setFloating_ptr window_setFloating;
15768-    RGFW_window_setOpacity_ptr window_setOpacity;
15769-    RGFW_window_minimize_ptr window_minimize;
15770-    RGFW_window_restore_ptr window_restore;
15771-    RGFW_window_isFloating_ptr window_isFloating;
15772-    RGFW_window_setName_ptr window_setName;
15773-    RGFW_window_setMousePassthrough_ptr window_setMousePassthrough;
15774-    RGFW_window_setIconEx_ptr window_setIconEx;
15775-    RGFW_createMouse_ptr loadMouse;
15776-    RGFW_createMouseStandard_ptr loadMouseStandard;
15777-    RGFW_window_setMousePlatform_ptr window_setMousePlatform;
15778-    RGFW_window_moveMouse_ptr window_moveMouse;
15779-    RGFW_window_hide_ptr window_hide;
15780-    RGFW_window_show_ptr window_show;
15781-    RGFW_window_flash_ptr window_flash;
15782-    RGFW_readClipboardPtr_ptr readClipboardPtr;
15783-    RGFW_writeClipboard_ptr writeClipboard;
15784-    RGFW_window_isHidden_ptr window_isHidden;
15785-    RGFW_window_isMinimized_ptr window_isMinimized;
15786-    RGFW_window_isMaximized_ptr window_isMaximized;
15787-    RGFW_monitor_requestMode_ptr monitor_requestMode;
15788-    RGFW_monitor_getWorkarea_ptr monitor_getWorkarea;
15789-	RGFW_monitor_getModesPtr_ptr monitor_getModesPtr;
15790-	RGFW_monitor_getGammaRampPtr_ptr monitor_getGammaRampPtr;
15791-	RGFW_monitor_setGammaRamp_ptr monitor_setGammaRamp;
15792-	RGFW_monitor_setMode_ptr monitor_setMode;
15793-    RGFW_window_getMonitor_ptr window_getMonitor;
15794-    RGFW_window_closePlatform_ptr window_closePlatform;
15795-#ifdef RGFW_OPENGL
15796-    RGFW_extensionSupportedPlatform_OpenGL_ptr extensionSupportedPlatform_OpenGL;
15797-    RGFW_getProcAddress_OpenGL_ptr getProcAddress_OpenGL;
15798-    RGFW_window_createContextPtr_OpenGL_ptr window_createContextPtr_OpenGL;
15799-    RGFW_window_deleteContextPtr_OpenGL_ptr window_deleteContextPtr_OpenGL;
15800-    RGFW_window_makeCurrentContext_OpenGL_ptr window_makeCurrentContext_OpenGL;
15801-    RGFW_getCurrentContext_OpenGL_ptr getCurrentContext_OpenGL;
15802-    RGFW_window_swapBuffers_OpenGL_ptr window_swapBuffers_OpenGL;
15803-    RGFW_window_swapInterval_OpenGL_ptr window_swapInterval_OpenGL;
15804-#endif
15805-#ifdef RGFW_WEBGPU
15806-    RGFW_window_createSurface_WebGPU_ptr window_createSurface_WebGPU;
15807-#endif
15808-} RGFW_functionPointers;
15809-
15810-RGFW_functionPointers RGFW_api;
15811-
15812-RGFW_format RGFW_nativeFormat(void) { return RGFW_api.nativeFormat(); }
15813-RGFW_bool RGFW_createSurfacePtr(u8* data, i32 w, i32 h, RGFW_format format, RGFW_surface* surface) { return RGFW_api.createSurfacePtr(data, w, h, format, surface); }
15814-void RGFW_surface_freePtr(RGFW_surface* surface) { RGFW_api.surface_freePtr(surface); }
15815-void RGFW_freeMouse(RGFW_mouse* mouse) { RGFW_api.freeMouse(mouse); }
15816-void RGFW_window_blitSurface(RGFW_window* win, RGFW_surface* surface) { RGFW_api.window_blitSurface(win, surface); }
15817-void RGFW_window_setBorder(RGFW_window* win, RGFW_bool border) { RGFW_api.window_setBorder(win, border); }
15818-void RGFW_window_captureMousePlatform(RGFW_window* win, RGFW_bool state) { RGFW_api.window_captureMousePlatform(win, state); }
15819-void RGFW_window_setRawMouseModePlatform(RGFW_window* win, RGFW_bool state) { RGFW_api.window_setRawMouseModePlatform(win, state); }
15820-RGFW_window* RGFW_createWindowPlatform(const char* name, RGFW_windowFlags flags, RGFW_window* win) { RGFW_init(); return RGFW_api.createWindowPlatform(name, flags, win); }
15821-RGFW_bool RGFW_getGlobalMouse(i32* x, i32* y) { return RGFW_api.getGlobalMouse(x, y); }
15822-RGFW_key RGFW_physicalToMappedKey(RGFW_key key) { return RGFW_api.physicalToMappedKey(key); }
15823-void RGFW_pollEvents(void) { RGFW_api.pollEvents(); }
15824-RGFW_bool RGFW_window_fetchSize(RGFW_window* win, i32* w, i32* h) { return RGFW_api.window_fetchSize(win, w, h); }
15825-void RGFW_pollMonitors(void) { RGFW_api.pollMonitors(); }
15826-void RGFW_window_move(RGFW_window* win, i32 x, i32 y) { RGFW_api.window_move(win, x, y); }
15827-void RGFW_window_resize(RGFW_window* win, i32 w, i32 h) { RGFW_api.window_resize(win, w, h); }
15828-void RGFW_window_setAspectRatio(RGFW_window* win, i32 w, i32 h) { RGFW_api.window_setAspectRatio(win, w, h); }
15829-void RGFW_window_setMinSize(RGFW_window* win, i32 w, i32 h) { RGFW_api.window_setMinSize(win, w, h); }
15830-void RGFW_window_setMaxSize(RGFW_window* win, i32 w, i32 h) { RGFW_api.window_setMaxSize(win, w, h); }
15831-void RGFW_window_maximize(RGFW_window* win) { RGFW_api.window_maximize(win); }
15832-void RGFW_window_focus(RGFW_window* win) { RGFW_api.window_focus(win); }
15833-void RGFW_window_raise(RGFW_window* win) { RGFW_api.window_raise(win); }
15834-void RGFW_window_setFullscreen(RGFW_window* win, RGFW_bool fullscreen) { RGFW_api.window_setFullscreen(win, fullscreen); }
15835-void RGFW_window_setFloating(RGFW_window* win, RGFW_bool floating) { RGFW_api.window_setFloating(win, floating); }
15836-void RGFW_window_setOpacity(RGFW_window* win, u8 opacity) { RGFW_api.window_setOpacity(win, opacity); }
15837-void RGFW_window_minimize(RGFW_window* win) { RGFW_api.window_minimize(win); }
15838-void RGFW_window_restore(RGFW_window* win) { RGFW_api.window_restore(win); }
15839-RGFW_bool RGFW_window_isFloating(RGFW_window* win) { return RGFW_api.window_isFloating(win); }
15840-void RGFW_window_setName(RGFW_window* win, const char* name) { RGFW_api.window_setName(win, name); }
15841-
15842-#ifndef RGFW_NO_PASSTHROUGH
15843-void RGFW_window_setMousePassthrough(RGFW_window* win, RGFW_bool passthrough) { RGFW_api.window_setMousePassthrough(win, passthrough); }
15844-#endif
15845-
15846-RGFW_bool RGFW_window_setIconEx(RGFW_window* win, u8* data, i32 w, i32 h, RGFW_format format, u8 type) { return RGFW_api.window_setIconEx(win, data, w, h, format, type); }
15847-RGFW_mouse* RGFW_createMouse(u8* data, i32 w, i32 h, RGFW_format format) { return RGFW_api.loadMouse(data, w, h, format); }
15848-RGFW_mouse* RGFW_createMouseStandard(RGFW_mouseIcon icon) { return RGFW_api.loadMouseStandard(icon); }
15849-RGFW_bool RGFW_window_setMousePlatform(RGFW_window* win, RGFW_mouse* mouse) { return RGFW_api.window_setMousePlatform(win, mouse); }
15850-void RGFW_window_moveMouse(RGFW_window* win, i32 x, i32 y) { RGFW_api.window_moveMouse(win, x, y); }
15851-void RGFW_window_hide(RGFW_window* win) { RGFW_api.window_hide(win); }
15852-void RGFW_window_show(RGFW_window* win) { RGFW_api.window_show(win); }
15853-void RGFW_window_flash(RGFW_window* win, RGFW_flashRequest request) { RGFW_api.window_flash(win, request); }
15854-RGFW_ssize_t RGFW_readClipboardPtr(char* str, size_t strCapacity) { return RGFW_api.readClipboardPtr(str, strCapacity); }
15855-void RGFW_writeClipboard(const char* text, u32 textLen) { RGFW_api.writeClipboard(text, textLen); }
15856-RGFW_bool RGFW_window_isHidden(RGFW_window* win) { return RGFW_api.window_isHidden(win); }
15857-RGFW_bool RGFW_window_isMinimized(RGFW_window* win) { return RGFW_api.window_isMinimized(win); }
15858-RGFW_bool RGFW_window_isMaximized(RGFW_window* win) { return RGFW_api.window_isMaximized(win); }
15859-RGFW_bool RGFW_monitor_requestMode(RGFW_monitor* mon, RGFW_monitorMode* mode, RGFW_modeRequest request) { return RGFW_api.monitor_requestMode(mon, mode, request); }
15860-RGFW_bool RGFW_monitor_getWorkarea(RGFW_monitor* monitor, i32* x, i32* y, i32* width, i32* height) { return  RGFW_api.monitor_getWorkarea(monitor, x, y, width, height); }
15861-size_t RGFW_monitor_getGammaRampPtr(RGFW_monitor* monitor, RGFW_gammaRamp* ramp) { return RGFW_api.monitor_getGammaRampPtr(monitor, ramp); }
15862-RGFW_bool RGFW_monitor_setGammaRamp(RGFW_monitor* monitor, RGFW_gammaRamp* ramp) { return RGFW_api.monitor_setGammaRamp(monitor, ramp); }
15863-size_t RGFW_monitor_getModesPtr(RGFW_monitor* mon, RGFW_monitorMode** modes) { return RGFW_api.monitor_getModesPtr(mon, modes); }
15864-RGFW_bool RGFW_monitor_setMode(RGFW_monitor* mon, RGFW_monitorMode* mode) { return RGFW_api.monitor_setMode(mon, mode); }
15865-RGFW_monitor* RGFW_window_getMonitor(RGFW_window* win) { return RGFW_api.window_getMonitor(win); }
15866-void RGFW_window_closePlatform(RGFW_window* win) { RGFW_api.window_closePlatform(win); }
15867-
15868-#ifdef RGFW_OPENGL
15869-RGFW_bool RGFW_extensionSupportedPlatform_OpenGL(const char* extension, size_t len) { return RGFW_api.extensionSupportedPlatform_OpenGL(extension, len); }
15870-RGFW_proc RGFW_getProcAddress_OpenGL(const char* procname) { return RGFW_api.getProcAddress_OpenGL(procname); }
15871-RGFW_bool RGFW_window_createContextPtr_OpenGL(RGFW_window* win, RGFW_glContext* ctx, RGFW_glHints* hints) { return RGFW_api.window_createContextPtr_OpenGL(win, ctx, hints); }
15872-void RGFW_window_deleteContextPtr_OpenGL(RGFW_window* win, RGFW_glContext* ctx) { RGFW_api.window_deleteContextPtr_OpenGL(win, ctx); }
15873-void RGFW_window_makeCurrentContext_OpenGL(RGFW_window* win) { RGFW_api.window_makeCurrentContext_OpenGL(win); }
15874-void* RGFW_getCurrentContext_OpenGL(void) { return RGFW_api.getCurrentContext_OpenGL(); }
15875-void RGFW_window_swapBuffers_OpenGL(RGFW_window* win) { RGFW_api.window_swapBuffers_OpenGL(win); }
15876-void RGFW_window_swapInterval_OpenGL(RGFW_window* win, i32 swapInterval) { RGFW_api.window_swapInterval_OpenGL(win, swapInterval); }
15877-#endif
15878-
15879-#ifdef RGFW_WEBGPU
15880-WGPUSurface RGFW_window_createSurface_WebGPU(RGFW_window* window, WGPUInstance instance) { return RGFW_api.window_createSurface_WebGPU(window, instance); }
15881-#endif
15882-#endif  /* RGFW_DYNAMIC */
15883-
15884-/*
15885- * start of X11 AND wayland defines
15886- * this allows a single executable to support x11 AND wayland
15887- * falling back to x11 if wayland fails to initalize
15888-*/
15889-#if defined(RGFW_WAYLAND) && defined(RGFW_X11)
15890-void RGFW_load_X11(void) {
15891-	RGFW_api.nativeFormat = RGFW_nativeFormat_X11;
15892-	RGFW_api.createSurfacePtr = RGFW_createSurfacePtr_X11;
15893-    RGFW_api.window_blitSurface = RGFW_window_blitSurface_X11;
15894-	RGFW_api.surface_freePtr = RGFW_surface_freePtr_X11;
15895-	RGFW_api.freeMouse = RGFW_freeMouse_X11;
15896-    RGFW_api.window_setBorder = RGFW_window_setBorder_X11;
15897-    RGFW_api.window_captureMousePlatform = RGFW_window_captureMousePlatform_X11;
15898-	RGFW_api.window_setRawMouseModePlatform = RGFW_window_setRawMouseModePlatform_X11;
15899-	RGFW_api.createWindowPlatform = RGFW_createWindowPlatform_X11;
15900-    RGFW_api.getGlobalMouse = RGFW_getGlobalMouse_X11;
15901-    RGFW_api.physicalToMappedKey = RGFW_physicalToMappedKey_X11;
15902-    RGFW_api.pollEvents = RGFW_pollEvents_X11;
15903-    RGFW_api.window_fetchSize = RGFW_window_fetchSize_X11;
15904-    RGFW_api.pollMonitors = RGFW_pollMonitors_X11;
15905-    RGFW_api.window_move = RGFW_window_move_X11;
15906-    RGFW_api.window_resize = RGFW_window_resize_X11;
15907-    RGFW_api.window_setAspectRatio = RGFW_window_setAspectRatio_X11;
15908-    RGFW_api.window_setMinSize = RGFW_window_setMinSize_X11;
15909-    RGFW_api.window_setMaxSize = RGFW_window_setMaxSize_X11;
15910-    RGFW_api.window_maximize = RGFW_window_maximize_X11;
15911-    RGFW_api.window_focus = RGFW_window_focus_X11;
15912-    RGFW_api.window_raise = RGFW_window_raise_X11;
15913-    RGFW_api.window_setFullscreen = RGFW_window_setFullscreen_X11;
15914-    RGFW_api.window_setFloating = RGFW_window_setFloating_X11;
15915-    RGFW_api.window_setOpacity = RGFW_window_setOpacity_X11;
15916-    RGFW_api.window_minimize = RGFW_window_minimize_X11;
15917-    RGFW_api.window_restore = RGFW_window_restore_X11;
15918-    RGFW_api.window_isFloating = RGFW_window_isFloating_X11;
15919-    RGFW_api.window_setName = RGFW_window_setName_X11;
15920-#ifndef RGFW_NO_PASSTHROUGH
15921-    RGFW_api.window_setMousePassthrough = RGFW_window_setMousePassthrough_X11;
15922-#endif
15923-    RGFW_api.window_setIconEx = RGFW_window_setIconEx_X11;
15924-    RGFW_api.loadMouse = RGFW_createMouse_X11;
15925-    RGFW_api.window_setMousePlatform = RGFW_window_setMousePlatform_X11;
15926-    RGFW_api.window_moveMouse = RGFW_window_moveMouse_X11;
15927-    RGFW_api.window_hide = RGFW_window_hide_X11;
15928-    RGFW_api.window_show = RGFW_window_show_X11;
15929-    RGFW_api.window_flash = RGFW_window_flash_X11;
15930-    RGFW_api.readClipboardPtr = RGFW_readClipboardPtr_X11;
15931-    RGFW_api.writeClipboard = RGFW_writeClipboard_X11;
15932-    RGFW_api.window_isHidden = RGFW_window_isHidden_X11;
15933-    RGFW_api.window_isMinimized = RGFW_window_isMinimized_X11;
15934-    RGFW_api.window_isMaximized = RGFW_window_isMaximized_X11;
15935-    RGFW_api.monitor_requestMode = RGFW_monitor_requestMode_X11;
15936-    RGFW_api.monitor_getModesPtr = RGFW_monitor_getModesPtr_X11;
15937-    RGFW_api.monitor_setGammaRamp = RGFW_monitor_setGammaRamp_X11;
15938-    RGFW_api.monitor_getGammaRampPtr = RGFW_monitor_getGammaRampPtr_X11;
15939-	RGFW_api.monitor_setMode = RGFW_monitor_setMode_X11;
15940-    RGFW_api.window_getMonitor = RGFW_window_getMonitor_X11;
15941-    RGFW_api.window_closePlatform = RGFW_window_closePlatform_X11;
15942-#ifdef RGFW_OPENGL
15943-    RGFW_api.extensionSupportedPlatform_OpenGL = RGFW_extensionSupportedPlatform_OpenGL_X11;
15944-    RGFW_api.getProcAddress_OpenGL = RGFW_getProcAddress_OpenGL_X11;
15945-	RGFW_api.window_createContextPtr_OpenGL = RGFW_window_createContextPtr_OpenGL_X11;
15946-    RGFW_api.window_deleteContextPtr_OpenGL = RGFW_window_deleteContextPtr_OpenGL_X11;
15947-	RGFW_api.window_makeCurrentContext_OpenGL = RGFW_window_makeCurrentContext_OpenGL_X11;
15948-    RGFW_api.getCurrentContext_OpenGL = RGFW_getCurrentContext_OpenGL_X11;
15949-    RGFW_api.window_swapBuffers_OpenGL = RGFW_window_swapBuffers_OpenGL_X11;
15950-    RGFW_api.window_swapInterval_OpenGL = RGFW_window_swapInterval_OpenGL_X11;
15951-#endif
15952-#ifdef RGFW_WEBGPU
15953-    RGFW_api.window_createSurface_WebGPU = RGFW_window_createSurface_WebGPU_X11;
15954-#endif
15955-}
15956-
15957-void RGFW_load_Wayland(void) {
15958-	RGFW_api.nativeFormat = RGFW_nativeFormat_Wayland;
15959-	RGFW_api.createSurfacePtr = RGFW_createSurfacePtr_Wayland;
15960-	RGFW_api.window_blitSurface = RGFW_window_blitSurface_Wayland;
15961-    RGFW_api.surface_freePtr = RGFW_surface_freePtr_Wayland;
15962-	RGFW_api.freeMouse = RGFW_freeMouse_Wayland;
15963-	RGFW_api.window_setBorder = RGFW_window_setBorder_Wayland;
15964-    RGFW_api.window_captureMousePlatform = RGFW_window_captureMousePlatform_Wayland;
15965-	RGFW_api.window_setRawMouseModePlatform = RGFW_window_setRawMouseModePlatform_Wayland;
15966-    RGFW_api.createWindowPlatform = RGFW_createWindowPlatform_Wayland;
15967-    RGFW_api.getGlobalMouse = RGFW_getGlobalMouse_Wayland;
15968-    RGFW_api.physicalToMappedKey = RGFW_physicalToMappedKey_Wayland;
15969-    RGFW_api.pollEvents = RGFW_pollEvents_Wayland;
15970-    RGFW_api.window_fetchSize = RGFW_window_fetchSize_Wayland;
15971-    RGFW_api.pollMonitors = RGFW_pollMonitors_Wayland;
15972-    RGFW_api.window_move = RGFW_window_move_Wayland;
15973-    RGFW_api.window_resize = RGFW_window_resize_Wayland;
15974-    RGFW_api.window_setAspectRatio = RGFW_window_setAspectRatio_Wayland;
15975-    RGFW_api.window_setMinSize = RGFW_window_setMinSize_Wayland;
15976-    RGFW_api.window_setMaxSize = RGFW_window_setMaxSize_Wayland;
15977-    RGFW_api.window_maximize = RGFW_window_maximize_Wayland;
15978-    RGFW_api.window_focus = RGFW_window_focus_Wayland;
15979-    RGFW_api.window_raise = RGFW_window_raise_Wayland;
15980-    RGFW_api.window_setFullscreen = RGFW_window_setFullscreen_Wayland;
15981-    RGFW_api.window_setFloating = RGFW_window_setFloating_Wayland;
15982-    RGFW_api.window_setOpacity = RGFW_window_setOpacity_Wayland;
15983-    RGFW_api.window_minimize = RGFW_window_minimize_Wayland;
15984-    RGFW_api.window_restore = RGFW_window_restore_Wayland;
15985-    RGFW_api.window_isFloating = RGFW_window_isFloating_Wayland;
15986-    RGFW_api.window_setName = RGFW_window_setName_Wayland;
15987-#ifndef RGFW_NO_PASSTHROUGH
15988-    RGFW_api.window_setMousePassthrough = RGFW_window_setMousePassthrough_Wayland;
15989-#endif
15990-    RGFW_api.window_setIconEx = RGFW_window_setIconEx_Wayland;
15991-	RGFW_api.loadMouse = RGFW_createMouse_Wayland;
15992-    RGFW_api.window_setMousePlatform = RGFW_window_setMousePlatform_Wayland;
15993-    RGFW_api.window_moveMouse = RGFW_window_moveMouse_Wayland;
15994-    RGFW_api.window_hide = RGFW_window_hide_Wayland;
15995-    RGFW_api.window_show = RGFW_window_show_Wayland;
15996-    RGFW_api.window_flash = RGFW_window_flash_X11;
15997-    RGFW_api.readClipboardPtr = RGFW_readClipboardPtr_Wayland;
15998-    RGFW_api.writeClipboard = RGFW_writeClipboard_Wayland;
15999-    RGFW_api.window_isHidden = RGFW_window_isHidden_Wayland;
16000-    RGFW_api.window_isMinimized = RGFW_window_isMinimized_Wayland;
16001-    RGFW_api.window_isMaximized = RGFW_window_isMaximized_Wayland;
16002-    RGFW_api.monitor_requestMode = RGFW_monitor_requestMode_Wayland;
16003-    RGFW_api.monitor_getModesPtr = RGFW_monitor_getModesPtr_Wayland;
16004-    RGFW_api.monitor_setGammaRamp = RGFW_monitor_setGammaRamp_Wayland;
16005-    RGFW_api.monitor_getGammaRampPtr = RGFW_monitor_getGammaRampPtr_Wayland;
16006-	RGFW_api.monitor_setMode = RGFW_monitor_setMode_Wayland;
16007-    RGFW_api.window_getMonitor = RGFW_window_getMonitor_Wayland;
16008-    RGFW_api.window_closePlatform = RGFW_window_closePlatform_Wayland;
16009-#ifdef RGFW_OPENGL
16010-    RGFW_api.extensionSupportedPlatform_OpenGL = RGFW_extensionSupportedPlatform_OpenGL_Wayland;
16011-    RGFW_api.getProcAddress_OpenGL = RGFW_getProcAddress_OpenGL_Wayland;
16012-	RGFW_api.window_createContextPtr_OpenGL = RGFW_window_createContextPtr_OpenGL_Wayland;
16013-    RGFW_api.window_deleteContextPtr_OpenGL = RGFW_window_deleteContextPtr_OpenGL_Wayland;
16014-	RGFW_api.window_makeCurrentContext_OpenGL = RGFW_window_makeCurrentContext_OpenGL_Wayland;
16015-    RGFW_api.getCurrentContext_OpenGL = RGFW_getCurrentContext_OpenGL_Wayland;
16016-    RGFW_api.window_swapBuffers_OpenGL = RGFW_window_swapBuffers_OpenGL_Wayland;
16017-    RGFW_api.window_swapInterval_OpenGL = RGFW_window_swapInterval_OpenGL_Wayland;
16018-#endif
16019-#ifdef RGFW_WEBGPU
16020-    RGFW_api.window_createSurface_WebGPU = RGFW_window_createSurface_WebGPU_Wayland;
16021-#endif
16022-}
16023-#endif /* wayland AND x11 */
16024-/* end of X11 AND wayland defines */
16025-
16026-#endif /* RGFW_IMPLEMENTATION */
16027-
16028-#if defined(__cplusplus) && !defined(__EMSCRIPTEN__)
16029-}
16030-#endif
16031-
16032-#if _MSC_VER
16033-	#pragma warning( pop )
16034-#endif
16035-