commit 7869c92
uint
·
2026-07-13 19:19:12 +0000 UTC
parent 2627aa1
replace rgfw with libmaus backend
5 files changed,
+74,
-16168
M
Makefile
+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, ®istry_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-