0/**********************************************************************************************
1*
2* rcore_desktop_rgfw - Functions to manage window, graphics device and inputs
3*
4* PLATFORM: RGFW
5* - Windows (Win32, Win64)
6* - Linux (X11/Wayland desktop mode)
7* - MacOS (Cocoa)
8* - HTML5 (Emscripten)
9* - Others (untested)
10*
11* LIMITATIONS:
12* - TODO
13*
14* POSSIBLE IMPROVEMENTS:
15* - TODO
16*
17* ADDITIONAL NOTES:
18* - TRACELOG() function is located in raylib [utils] module
19*
20* CONFIGURATION:
21* #define RCORE_PLATFORM_RGFW
22* Custom flag for rcore on target platform RGFW
23*
24* DEPENDENCIES:
25* - RGFW.h (main library): Windowing and inputs management
26* - gestures: Gestures system for touch-ready devices (or simulated from mouse inputs)
27*
28*
29* LICENSE: zlib/libpng
30*
31* Copyright (c) 2013-2025 Ramon Santamaria (@raysan5), Colleague Riley and contributors
32*
33* This software is provided "as-is", without any express or implied warranty. In no event
34* will the authors be held liable for any damages arising from the use of this software.
35*
36* Permission is granted to anyone to use this software for any purpose, including commercial
37* applications, and to alter it and redistribute it freely, subject to the following restrictions:
38*
39* 1. The origin of this software must not be misrepresented; you must not claim that you
40* wrote the original software. If you use this software in a product, an acknowledgment
41* in the product documentation would be appreciated but is not required.
42*
43* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
44* as being the original software.
45*
46* 3. This notice may not be removed or altered from any source distribution.
47*
48**********************************************************************************************/
50#if defined(PLATFORM_WEB_RGFW)
51#define RGFW_NO_GL_HEADER
52#endif
54#if defined(GRAPHICS_API_OPENGL_ES2) && !defined(PLATFORM_WEB_RGFW)
55 #define RGFW_OPENGL_ES2
56#endif
58void ShowCursor(void);
59void CloseWindow(void);
61#if defined(__linux__)
62 #define _INPUT_EVENT_CODES_H
63#endif
65#if defined(__unix__) || defined(__linux__)
66 #define _XTYPEDEF_FONT
67#endif
69#define RGFW_IMPLEMENTATION
71#if defined(_WIN32) || defined(_WIN64)
72 #define WIN32_LEAN_AND_MEAN
73 #define Rectangle rectangle_win32
74 #define CloseWindow CloseWindow_win32
75 #define ShowCursor __imp_ShowCursor
76 #define _APISETSTRING_
78 #undef MAX_PATH
80#if defined(__cplusplus)
81extern "C" {
82#endif
83 __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int CodePage, unsigned long dwFlags, const char *lpMultiByteStr, int cbMultiByte, wchar_t *lpWideCharStr, int cchWideChar);
84#if defined(__cplusplus)
85}
86#endif
88#endif
90#if defined(__APPLE__)
91 #define Point NSPOINT
92 #define Size NSSIZE
93#endif
95#define RGFW_ALLOC RL_MALLOC
96#define RGFW_FREE RL_FREE
97#define RGFW_CALLOC RL_CALLOC
99#include "../external/RGFW.h"
101#if defined(_WIN32) || defined(_WIN64)
102 #undef DrawText
103 #undef ShowCursor
104 #undef CloseWindow
105 #undef Rectangle
107 #undef MAX_PATH
108 #define MAX_PATH 1025
109#endif
111#if defined(__APPLE__)
112 #undef Point
113 #undef Size
114#endif
116#include <stdbool.h>
117#include <string.h> // Required for: strcmp()
119//----------------------------------------------------------------------------------
120// Types and Structures Definition
121//----------------------------------------------------------------------------------
122typedef struct {
123 RGFW_window *window; // Native display device (physical screen connection)
124 RGFW_monitor mon;
125} PlatformData;
127//----------------------------------------------------------------------------------
128// Global Variables Definition
129//----------------------------------------------------------------------------------
130extern CoreData CORE; // Global CORE state context
132static PlatformData platform = { 0 }; // Platform specific
134static bool RGFW_disableCursor = false;
136static const unsigned short keyMappingRGFW[] = {
137 [RGFW_keyNULL] = KEY_NULL,
138 [RGFW_return] = KEY_ENTER,
139 [RGFW_apostrophe] = KEY_APOSTROPHE,
140 [RGFW_comma] = KEY_COMMA,
141 [RGFW_minus] = KEY_MINUS,
142 [RGFW_period] = KEY_PERIOD,
143 [RGFW_slash] = KEY_SLASH,
144 [RGFW_escape] = KEY_ESCAPE,
145 [RGFW_F1] = KEY_F1,
146 [RGFW_F2] = KEY_F2,
147 [RGFW_F3] = KEY_F3,
148 [RGFW_F4] = KEY_F4,
149 [RGFW_F5] = KEY_F5,
150 [RGFW_F6] = KEY_F6,
151 [RGFW_F7] = KEY_F7,
152 [RGFW_F8] = KEY_F8,
153 [RGFW_F9] = KEY_F9,
154 [RGFW_F10] = KEY_F10,
155 [RGFW_F11] = KEY_F11,
156 [RGFW_F12] = KEY_F12,
157 [RGFW_backtick] = KEY_GRAVE,
158 [RGFW_0] = KEY_ZERO,
159 [RGFW_1] = KEY_ONE,
160 [RGFW_2] = KEY_TWO,
161 [RGFW_3] = KEY_THREE,
162 [RGFW_4] = KEY_FOUR,
163 [RGFW_5] = KEY_FIVE,
164 [RGFW_6] = KEY_SIX,
165 [RGFW_7] = KEY_SEVEN,
166 [RGFW_8] = KEY_EIGHT,
167 [RGFW_9] = KEY_NINE,
168 [RGFW_equals] = KEY_EQUAL,
169 [RGFW_backSpace] = KEY_BACKSPACE,
170 [RGFW_tab] = KEY_TAB,
171 [RGFW_capsLock] = KEY_CAPS_LOCK,
172 [RGFW_shiftL] = KEY_LEFT_SHIFT,
173 [RGFW_controlL] = KEY_LEFT_CONTROL,
174 [RGFW_altL] = KEY_LEFT_ALT,
175 [RGFW_superL] = KEY_LEFT_SUPER,
176 #ifndef RGFW_MACOS
177 [RGFW_shiftR] = KEY_RIGHT_SHIFT,
178 [RGFW_controlR] = KEY_RIGHT_CONTROL,
179 [RGFW_altR] = KEY_RIGHT_ALT,
180 [RGFW_superR] = KEY_RIGHT_SUPER,
181 #endif
182 [RGFW_space] = KEY_SPACE,
184 [RGFW_a] = KEY_A,
185 [RGFW_b] = KEY_B,
186 [RGFW_c] = KEY_C,
187 [RGFW_d] = KEY_D,
188 [RGFW_e] = KEY_E,
189 [RGFW_f] = KEY_F,
190 [RGFW_g] = KEY_G,
191 [RGFW_h] = KEY_H,
192 [RGFW_i] = KEY_I,
193 [RGFW_j] = KEY_J,
194 [RGFW_k] = KEY_K,
195 [RGFW_l] = KEY_L,
196 [RGFW_m] = KEY_M,
197 [RGFW_n] = KEY_N,
198 [RGFW_o] = KEY_O,
199 [RGFW_p] = KEY_P,
200 [RGFW_q] = KEY_Q,
201 [RGFW_r] = KEY_R,
202 [RGFW_s] = KEY_S,
203 [RGFW_t] = KEY_T,
204 [RGFW_u] = KEY_U,
205 [RGFW_v] = KEY_V,
206 [RGFW_w] = KEY_W,
207 [RGFW_x] = KEY_X,
208 [RGFW_y] = KEY_Y,
209 [RGFW_z] = KEY_Z,
210 [RGFW_bracket] = KEY_LEFT_BRACKET,
211 [RGFW_backSlash] = KEY_BACKSLASH,
212 [RGFW_closeBracket] = KEY_RIGHT_BRACKET,
213 [RGFW_semicolon] = KEY_SEMICOLON,
214 [RGFW_insert] = KEY_INSERT,
215 [RGFW_home] = KEY_HOME,
216 [RGFW_pageUp] = KEY_PAGE_UP,
217 [RGFW_delete] = KEY_DELETE,
218 [RGFW_end] = KEY_END,
219 [RGFW_pageDown] = KEY_PAGE_DOWN,
220 [RGFW_right] = KEY_RIGHT,
221 [RGFW_left] = KEY_LEFT,
222 [RGFW_down] = KEY_DOWN,
223 [RGFW_up] = KEY_UP,
224 [RGFW_numLock] = KEY_NUM_LOCK,
225 [RGFW_KP_Slash] = KEY_KP_DIVIDE,
226 [RGFW_multiply] = KEY_KP_MULTIPLY,
227 [RGFW_KP_Minus] = KEY_KP_SUBTRACT,
228 [RGFW_KP_Return] = KEY_KP_ENTER,
229 [RGFW_KP_1] = KEY_KP_1,
230 [RGFW_KP_2] = KEY_KP_2,
231 [RGFW_KP_3] = KEY_KP_3,
232 [RGFW_KP_4] = KEY_KP_4,
233 [RGFW_KP_5] = KEY_KP_5,
234 [RGFW_KP_6] = KEY_KP_6,
235 [RGFW_KP_7] = KEY_KP_7,
236 [RGFW_KP_8] = KEY_KP_8,
237 [RGFW_KP_9] = KEY_KP_9,
238 [RGFW_KP_0] = KEY_KP_0,
239 [RGFW_KP_Period] = KEY_KP_DECIMAL,
240 [RGFW_scrollLock] = KEY_SCROLL_LOCK,
241};
243static int RGFW_gpConvTable[18] = {
244 [RGFW_gamepadY] = GAMEPAD_BUTTON_RIGHT_FACE_UP,
245 [RGFW_gamepadB] = GAMEPAD_BUTTON_RIGHT_FACE_RIGHT,
246 [RGFW_gamepadA] = GAMEPAD_BUTTON_RIGHT_FACE_DOWN,
247 [RGFW_gamepadX] = GAMEPAD_BUTTON_RIGHT_FACE_LEFT,
248 [RGFW_gamepadL1] = GAMEPAD_BUTTON_LEFT_TRIGGER_1,
249 [RGFW_gamepadR1] = GAMEPAD_BUTTON_RIGHT_TRIGGER_1,
250 [RGFW_gamepadL2] = GAMEPAD_BUTTON_LEFT_TRIGGER_2,
251 [RGFW_gamepadR2] = GAMEPAD_BUTTON_RIGHT_TRIGGER_2,
252 [RGFW_gamepadSelect] = GAMEPAD_BUTTON_MIDDLE_LEFT,
253 [RGFW_gamepadHome] = GAMEPAD_BUTTON_MIDDLE,
254 [RGFW_gamepadStart] = GAMEPAD_BUTTON_MIDDLE_RIGHT,
255 [RGFW_gamepadUp] = GAMEPAD_BUTTON_LEFT_FACE_UP,
256 [RGFW_gamepadRight] = GAMEPAD_BUTTON_LEFT_FACE_RIGHT,
257 [RGFW_gamepadDown] = GAMEPAD_BUTTON_LEFT_FACE_DOWN,
258 [RGFW_gamepadLeft] = GAMEPAD_BUTTON_LEFT_FACE_LEFT,
259 [RGFW_gamepadL3] = GAMEPAD_BUTTON_LEFT_THUMB,
260 [RGFW_gamepadR3] = GAMEPAD_BUTTON_RIGHT_THUMB,
261};
263//----------------------------------------------------------------------------------
264// Module Internal Functions Declaration
265//----------------------------------------------------------------------------------
266int InitPlatform(void); // Initialize platform (graphics, inputs and more)
267bool InitGraphicsDevice(void); // Initialize graphics device
269static KeyboardKey ConvertScancodeToKey(u32 keycode);
271//----------------------------------------------------------------------------------
272// Module Functions Declaration
273//----------------------------------------------------------------------------------
274// NOTE: Functions declaration is provided by raylib.h
276//----------------------------------------------------------------------------------
277// Module Functions Definition: Window and Graphics Device
278//----------------------------------------------------------------------------------
280// Check if application should close
281bool WindowShouldClose(void)
282{
283 if (CORE.Window.shouldClose == false)
284 CORE.Window.shouldClose = RGFW_window_shouldClose(platform.window);
285 if (CORE.Window.ready) return CORE.Window.shouldClose;
286 else return true;
287}
289// Toggle fullscreen mode
290void ToggleFullscreen(void)
291{
292 if (!FLAG_IS_SET(CORE.Window.flags, FLAG_FULLSCREEN_MODE))
293 {
294 // Store previous window position (in case we exit fullscreen)
295 CORE.Window.previousPosition = CORE.Window.position;
296 CORE.Window.previousScreen = CORE.Window.screen;
298 platform.mon = RGFW_window_getMonitor(platform.window);
299 FLAG_SET(CORE.Window.flags, FLAG_FULLSCREEN_MODE);
301 RGFW_monitor_scaleToWindow(platform.mon, platform.window);
302 RGFW_window_setFullscreen(platform.window, 1);
303 }
304 else
305 {
306 FLAG_CLEAR(CORE.Window.flags, FLAG_FULLSCREEN_MODE);
308 if (platform.mon.mode.area.w)
309 {
310 RGFW_monitor monitor = RGFW_window_getMonitor(platform.window);
311 RGFW_monitor_requestMode(monitor, platform.mon.mode, RGFW_monitorScale);
313 platform.mon.mode.area.w = 0;
314 }
316 // we update the window position right away
317 CORE.Window.position = CORE.Window.previousPosition;
318 RGFW_window_setFullscreen(platform.window, 0);
319 RGFW_window_move(platform.window, RGFW_POINT(CORE.Window.position.x, CORE.Window.position.y));
320 RGFW_window_resize(platform.window, RGFW_AREA(CORE.Window.previousScreen.width, CORE.Window.previousScreen.height));
321 }
323 // Try to enable GPU V-Sync, so frames are limited to screen refresh rate (60Hz -> 60 FPS)
324 // NOTE: V-Sync can be enabled by graphic driver configuration
325 if (FLAG_IS_SET(CORE.Window.flags, FLAG_VSYNC_HINT)) RGFW_window_swapInterval(platform.window, 1);
326}
328// Toggle borderless windowed mode
329void ToggleBorderlessWindowed(void)
330{
331 if (FLAG_IS_SET(CORE.Window.flags, FLAG_FULLSCREEN_MODE)) ToggleFullscreen();
333 if (FLAG_IS_SET(CORE.Window.flags, FLAG_BORDERLESS_WINDOWED_MODE))
334 {
335 CORE.Window.previousPosition = CORE.Window.position;
336 CORE.Window.previousScreen = CORE.Window.screen;
338 RGFW_window_setBorder(platform.window, 0);
340 RGFW_monitor mon = RGFW_window_getMonitor(platform.window);
341 RGFW_window_resize(platform.window, mon.mode.area);
342 }
343 else
344 {
345 RGFW_window_setBorder(platform.window, 1);
347 CORE.Window.position = CORE.Window.previousPosition;
348 RGFW_window_resize(platform.window, RGFW_AREA(CORE.Window.previousScreen.width, CORE.Window.previousScreen.height));
349 }
350}
352// Set window state: maximized, if resizable
353void MaximizeWindow(void)
354{
355 RGFW_window_maximize(platform.window);
356}
358// Set window state: minimized
359void MinimizeWindow(void)
360{
361 RGFW_window_minimize(platform.window);
362}
364// Restore window from being minimized/maximized
365void RestoreWindow(void)
366{
367 if (!FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_UNFOCUSED)) RGFW_window_focus(platform.window);
369 RGFW_window_restore(platform.window);
370}
372// Set window configuration state using flags
373void SetWindowState(unsigned int flags)
374{
375 if (!CORE.Window.ready) TRACELOG(LOG_WARNING, "WINDOW: SetWindowState does nothing before window initialization, Use \"SetConfigFlags\" instead");
377 FLAG_SET(CORE.Window.flags, flags);
379 if (FLAG_IS_SET(flags, FLAG_VSYNC_HINT))
380 {
381 RGFW_window_swapInterval(platform.window, 1);
382 }
383 if (FLAG_IS_SET(flags, FLAG_FULLSCREEN_MODE))
384 {
385 ToggleFullscreen();
386 }
387 if (FLAG_IS_SET(flags, FLAG_WINDOW_RESIZABLE))
388 {
389 RGFW_window_setMaxSize(platform.window, RGFW_AREA(0, 0));
390 RGFW_window_setMinSize(platform.window, RGFW_AREA(0, 0));
391 }
392 if (FLAG_IS_SET(flags, FLAG_WINDOW_UNDECORATED))
393 {
394 RGFW_window_setBorder(platform.window, 0);
395 }
396 if (FLAG_IS_SET(flags, FLAG_WINDOW_HIDDEN))
397 {
398 RGFW_window_hide(platform.window);
399 }
400 if (FLAG_IS_SET(flags, FLAG_WINDOW_MINIMIZED))
401 {
402 RGFW_window_minimize(platform.window);
403 }
404 if (FLAG_IS_SET(flags, FLAG_WINDOW_MAXIMIZED))
405 {
406 RGFW_window_maximize(platform.window);
407 }
408 if (FLAG_IS_SET(flags, FLAG_WINDOW_UNFOCUSED))
409 {
410 FLAG_SET(CORE.Window.flags, FLAG_WINDOW_UNFOCUSED);
411 FLAG_CLEAR(platform.window->_flags, RGFW_windowFocusOnShow);
412 RGFW_window_setFlags(platform.window, platform.window->_flags);
413 }
414 if (FLAG_IS_SET(flags, FLAG_WINDOW_TOPMOST))
415 {
416 RGFW_window_setFloating(platform.window, RGFW_TRUE);
417 }
418 if (FLAG_IS_SET(flags, FLAG_WINDOW_ALWAYS_RUN))
419 {
420 FLAG_SET(CORE.Window.flags, FLAG_WINDOW_ALWAYS_RUN);
421 }
422 if (FLAG_IS_SET(flags, FLAG_WINDOW_TRANSPARENT))
423 {
424 TRACELOG(LOG_WARNING, "WINDOW: Framebuffer transparency can only be configured before window initialization");
425 }
426 if (FLAG_IS_SET(flags, FLAG_WINDOW_HIGHDPI))
427 {
428 TRACELOG(LOG_WARNING, "WINDOW: High DPI can only be configured before window initialization");
429 }
430 if (FLAG_IS_SET(flags, FLAG_WINDOW_MOUSE_PASSTHROUGH))
431 {
432 RGFW_window_setMousePassthrough(platform.window, 1);
433 }
434 if (FLAG_IS_SET(flags, FLAG_BORDERLESS_WINDOWED_MODE))
435 {
436 ToggleBorderlessWindowed();
437 }
438 if (FLAG_IS_SET(flags, FLAG_MSAA_4X_HINT))
439 {
440 RGFW_setGLHint(RGFW_glSamples, 4);
441 }
442 if (FLAG_IS_SET(flags, FLAG_INTERLACED_HINT))
443 {
444 TRACELOG(LOG_WARNING, "RPI: Interlaced mode can only be configured before window initialization");
445 }
446}
448// Clear window configuration state flags
449void ClearWindowState(unsigned int flags)
450{
451 FLAG_CLEAR(CORE.Window.flags, flags);
453 if (FLAG_IS_SET(flags, FLAG_VSYNC_HINT))
454 {
455 RGFW_window_swapInterval(platform.window, 0);
456 }
457 if (FLAG_IS_SET(flags, FLAG_FULLSCREEN_MODE))
458 {
459 ToggleFullscreen();
460 }
461 if (FLAG_IS_SET(flags, FLAG_WINDOW_RESIZABLE))
462 {
463 RGFW_window_setMaxSize(platform.window, RGFW_AREA(platform.window->r.w, platform.window->r.h));
464 RGFW_window_setMinSize(platform.window, RGFW_AREA(platform.window->r.w, platform.window->r.h));
465 }
466 if (FLAG_IS_SET(flags, FLAG_WINDOW_UNDECORATED))
467 {
468 RGFW_window_setBorder(platform.window, 1);
469 }
470 if (FLAG_IS_SET(flags, FLAG_WINDOW_HIDDEN))
471 {
472 if (!FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_UNFOCUSED)) RGFW_window_focus(platform.window);
474 RGFW_window_show(platform.window);
475 }
476 if (FLAG_IS_SET(flags, FLAG_WINDOW_MINIMIZED))
477 {
478 if (!FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_UNFOCUSED)) RGFW_window_focus(platform.window);
480 RGFW_window_restore(platform.window);
481 }
482 if (FLAG_IS_SET(flags, FLAG_WINDOW_MAXIMIZED))
483 {
484 if (!FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_UNFOCUSED)) RGFW_window_focus(platform.window);
486 RGFW_window_restore(platform.window);
487 }
488 if (FLAG_IS_SET(flags, FLAG_WINDOW_UNFOCUSED))
489 {
490 RGFW_window_setFlags(platform.window, platform.window->_flags | RGFW_windowFocusOnShow);
491 }
492 if (FLAG_IS_SET(flags, FLAG_WINDOW_TOPMOST))
493 {
494 RGFW_window_setFloating(platform.window, RGFW_FALSE);
495 }
496 if (FLAG_IS_SET(flags, FLAG_WINDOW_TRANSPARENT))
497 {
498 TRACELOG(LOG_WARNING, "WINDOW: Framebuffer transparency can only be configured before window initialization");
499 }
500 if (FLAG_IS_SET(flags, FLAG_WINDOW_HIGHDPI))
501 {
502 TRACELOG(LOG_WARNING, "WINDOW: High DPI can only be configured before window initialization");
503 }
504 if (FLAG_IS_SET(flags, FLAG_WINDOW_MOUSE_PASSTHROUGH))
505 {
506 RGFW_window_setMousePassthrough(platform.window, 0);
507 }
508 if (FLAG_IS_SET(flags, FLAG_BORDERLESS_WINDOWED_MODE))
509 {
510 ToggleBorderlessWindowed();
511 }
512 if (FLAG_IS_SET(flags, FLAG_MSAA_4X_HINT))
513 {
514 RGFW_setGLHint(RGFW_glSamples, 0);
515 }
516 if (FLAG_IS_SET(flags, FLAG_INTERLACED_HINT))
517 {
518 TRACELOG(LOG_WARNING, "RPI: Interlaced mode can only be configured before window initialization");
519 }
520}
522// Set icon for window
523void SetWindowIcon(Image image)
524{
525 if (image.format != PIXELFORMAT_UNCOMPRESSED_R8G8B8A8)
526 {
527 TRACELOG(LOG_WARNING, "RGFW: Window icon image must be in R8G8B8A8 pixel format");
528 return;
529 }
530 RGFW_window_setIcon(platform.window, (u8 *)image.data, RGFW_AREA(image.width, image.height), 4);
531}
533// Set icon for window
534void SetWindowIcons(Image *images, int count)
535{
536 if ((images == NULL) || (count <= 0))
537 {
538 RGFW_window_setIcon(platform.window, NULL, RGFW_AREA(0, 0), 0);
539 }
540 else
541 {
542 Image *bigIcon = NULL;
543 Image *smallIcon = NULL;
545 for (int i = 0; i < count; i++)
546 {
547 if (images[i].format != PIXELFORMAT_UNCOMPRESSED_R8G8B8A8)
548 {
549 TRACELOG(LOG_WARNING, "RGFW: Window icon image must be in R8G8B8A8 pixel format");
550 continue;
551 }
552 if ((bigIcon == NULL) || ((images[i].width > bigIcon->width) && (images[i].height > bigIcon->height))) bigIcon = &images[i];
553 if ((smallIcon == NULL) || ((images[i].width < smallIcon->width) && (images[i].height > smallIcon->height))) smallIcon = &images[i];
554 }
556 if (smallIcon != NULL) RGFW_window_setIconEx(platform.window, (u8 *)smallIcon->data, RGFW_AREA(smallIcon->width, smallIcon->height), 4, RGFW_iconWindow);
557 if (bigIcon != NULL) RGFW_window_setIconEx(platform.window, (u8 *)bigIcon->data, RGFW_AREA(bigIcon->width, bigIcon->height), 4, RGFW_iconTaskbar);
558 }
559}
561// Set title for window
562void SetWindowTitle(const char *title)
563{
564 RGFW_window_setName(platform.window, (char *)title);
565 CORE.Window.title = title;
566}
568// Set window position on screen (windowed mode)
569void SetWindowPosition(int x, int y)
570{
571 RGFW_window_move(platform.window, RGFW_POINT(x, y));
572}
574// Set monitor for the current window
575void SetWindowMonitor(int monitor)
576{
577 RGFW_window_moveToMonitor(platform.window, RGFW_getMonitors(NULL)[monitor]);
578}
580// Set window minimum dimensions (FLAG_WINDOW_RESIZABLE)
581void SetWindowMinSize(int width, int height)
582{
583 RGFW_window_setMinSize(platform.window, RGFW_AREA(width, height));
584 CORE.Window.screenMin.width = width;
585 CORE.Window.screenMin.height = height;
586}
588// Set window maximum dimensions (FLAG_WINDOW_RESIZABLE)
589void SetWindowMaxSize(int width, int height)
590{
591 RGFW_window_setMaxSize(platform.window, RGFW_AREA(width, height));
592 CORE.Window.screenMax.width = width;
593 CORE.Window.screenMax.height = height;
594}
596// Set window dimensions
597void SetWindowSize(int width, int height)
598{
599 CORE.Window.screen.width = width;
600 CORE.Window.screen.height = height;
602 RGFW_window_resize(platform.window, RGFW_AREA(width, height));
603}
605// Set window opacity, value opacity is between 0.0 and 1.0
606void SetWindowOpacity(float opacity)
607{
608 RGFW_window_setOpacity(platform.window, opacity);
609}
611// Set window focused
612void SetWindowFocused(void)
613{
614 RGFW_window_focus(platform.window);
615}
617// Get native window handle
618void *GetWindowHandle(void)
619{
620 if (platform.window == NULL) return NULL;
621#ifdef RGFW_WASM
622 return (void *)platform.window->src.ctx;
623#else
624 return (void *)platform.window->src.window;
625#endif
626}
628// Get number of monitors
629int GetMonitorCount(void)
630{
631 #define MAX_MONITORS_SUPPORTED 6
633 int count = MAX_MONITORS_SUPPORTED;
634 RGFW_monitor *mons = RGFW_getMonitors(NULL);
636 for (int i = 0; i < 6; i++)
637 {
638 if (!mons[i].x && !mons[i].y && !mons[i].mode.area.w && mons[i].mode.area.h)
639 {
640 count = i;
641 break;
642 }
643 }
645 return count;
646}
648// Get current monitor where window is placed
649int GetCurrentMonitor(void)
650{
651 RGFW_monitor *mons = RGFW_getMonitors(NULL);
652 RGFW_monitor mon = { 0 };
654 if (platform.window) mon = RGFW_window_getMonitor(platform.window);
655 else mon = RGFW_getPrimaryMonitor();
657 for (int i = 0; i < 6; i++)
658 {
659 if ((mons[i].x == mon.x) && (mons[i].y == mon.y)) return i;
660 }
662 return 0;
663}
665// Get selected monitor position
666Vector2 GetMonitorPosition(int monitor)
667{
668 RGFW_monitor *mons = RGFW_getMonitors(NULL);
670 return (Vector2){ (float)mons[monitor].x, (float)mons[monitor].y };
671}
673// Get selected monitor width (currently used by monitor)
674int GetMonitorWidth(int monitor)
675{
676 RGFW_monitor *mons = RGFW_getMonitors(NULL);
678 return mons[monitor].mode.area.w;
679}
681// Get selected monitor height (currently used by monitor)
682int GetMonitorHeight(int monitor)
683{
684 RGFW_monitor *mons = RGFW_getMonitors(NULL);
686 return mons[monitor].mode.area.h;
687}
689// Get selected monitor physical width in millimetres
690int GetMonitorPhysicalWidth(int monitor)
691{
692 RGFW_monitor *mons = RGFW_getMonitors(NULL);
694 return mons[monitor].physW;
695}
697// Get selected monitor physical height in millimetres
698int GetMonitorPhysicalHeight(int monitor)
699{
700 RGFW_monitor *mons = RGFW_getMonitors(NULL);
702 return (int)mons[monitor].physH;
703}
705// Get selected monitor refresh rate
706int GetMonitorRefreshRate(int monitor)
707{
708 RGFW_monitor *mons = RGFW_getMonitors(NULL);
710 return (int)mons[monitor].mode.refreshRate;
711}
713// Get the human-readable, UTF-8 encoded name of the selected monitor
714const char *GetMonitorName(int monitor)
715{
716 RGFW_monitor *mons = RGFW_getMonitors(NULL);
718 return mons[monitor].name;
719}
721// Get window position XY on monitor
722Vector2 GetWindowPosition(void)
723{
724 if (platform.window == NULL) return (Vector2){ 0.0f, 0.0f };
725 return (Vector2){ (float)platform.window->r.x, (float)platform.window->r.y };
726}
728// Get window scale DPI factor for current monitor
729Vector2 GetWindowScaleDPI(void)
730{
731 RGFW_monitor monitor = { 0 };
733 if (platform.window) monitor = RGFW_window_getMonitor(platform.window);
734 else monitor = RGFW_getPrimaryMonitor();
736 return (Vector2){ monitor.scaleX, monitor.scaleX };
737}
739// Set clipboard text content
740void SetClipboardText(const char *text)
741{
742 RGFW_writeClipboard(text, strlen(text));
743}
745// Get clipboard text content
746// NOTE: returned string is allocated and freed by RGFW
747const char *GetClipboardText(void)
748{
749 return RGFW_readClipboard(NULL);
750}
752#if defined(SUPPORT_CLIPBOARD_IMAGE)
753#if defined(_WIN32)
754 #define WIN32_CLIPBOARD_IMPLEMENTATION
755 #define WINUSER_ALREADY_INCLUDED
756 #define WINBASE_ALREADY_INCLUDED
757 #define WINGDI_ALREADY_INCLUDED
758 #include "../external/win32_clipboard.h"
759#endif
760#endif
762// Get clipboard image
763Image GetClipboardImage(void)
764{
765 Image image = { 0 };
766 unsigned long long int dataSize = 0;
767 void *fileData = NULL;
769#if defined(SUPPORT_CLIPBOARD_IMAGE)
770#if defined(_WIN32)
771 int width = 0;
772 int height = 0;
773 fileData = (void *)Win32GetClipboardImageData(&width, &height, &dataSize);
775 if (fileData == NULL) TRACELOG(LOG_WARNING, "Clipboard image: Couldn't get clipboard data");
776 else image = LoadImageFromMemory(".bmp", (const unsigned char *)fileData, dataSize);
777#else
778 TRACELOG(LOG_WARNING, "Clipboard image: PLATFORM_DESKTOP_RGFW doesn't implement GetClipboardImage() for this OS");
779#endif
780#endif // SUPPORT_CLIPBOARD_IMAGE
782 return image;
783}
785// Show mouse cursor
786void ShowCursor(void)
787{
788 RGFW_window_showMouse(platform.window, true);
789 CORE.Input.Mouse.cursorHidden = false;
790}
792// Hides mouse cursor
793void HideCursor(void)
794{
795 RGFW_window_showMouse(platform.window, false);
796 CORE.Input.Mouse.cursorHidden = true;
797}
799// Enables cursor (unlock cursor)
800void EnableCursor(void)
801{
802 RGFW_disableCursor = false;
803 RGFW_window_mouseUnhold(platform.window);
805 // Set cursor position in the middle
806 SetMousePosition(CORE.Window.screen.width/2, CORE.Window.screen.height/2);
807 ShowCursor();
809 CORE.Input.Mouse.cursorLocked = true;
810}
812// Disables cursor (lock cursor)
813void DisableCursor(void)
814{
815 RGFW_disableCursor = true;
816 RGFW_window_mouseHold(platform.window, RGFW_AREA(0, 0));
817 HideCursor();
819 CORE.Input.Mouse.cursorLocked = true;
820}
822// Swap back buffer with front buffer (screen drawing)
823void SwapScreenBuffer(void)
824{
825 RGFW_window_swapBuffers(platform.window);
826}
828//----------------------------------------------------------------------------------
829// Module Functions Definition: Misc
830//----------------------------------------------------------------------------------
832// Get elapsed time measure in seconds since InitTimer()
833double GetTime(void)
834{
835 return RGFW_getTime();
836}
838// Open URL with default system browser (if available)
839// NOTE: This function is only safe to use if you control the URL given
840// A user could craft a malicious string performing another action
841void OpenURL(const char *url)
842{
843 // Security check to (partially) avoid malicious code on target platform
844 if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character");
845 else
846 {
847 char *cmd = (char *)RL_CALLOC(strlen(url) + 32, sizeof(char));
848#if defined(_WIN32)
849 sprintf(cmd, "explorer \"%s\"", url);
850#endif
851#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__)
852 sprintf(cmd, "xdg-open '%s'", url); // Alternatives: firefox, x-www-browser
853#endif
854#if defined(__APPLE__)
855 sprintf(cmd, "open '%s'", url);
856#endif
857 int result = system(cmd);
858 if (result == -1) TRACELOG(LOG_WARNING, "OpenURL() child process could not be created");
859 RL_FREE(cmd);
860 }
861}
863//----------------------------------------------------------------------------------
864// Module Functions Definition: Inputs
865//----------------------------------------------------------------------------------
867// Set internal gamepad mappings
868int SetGamepadMappings(const char *mappings)
869{
870 TRACELOG(LOG_WARNING, "SetGamepadMappings() unsupported on target platform");
871 return 0;
872}
874// Set gamepad vibration
875void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float duration)
876{
877 TRACELOG(LOG_WARNING, "SetGamepadVibration() unsupported on target platform");
878}
880// Set mouse position XY
881void SetMousePosition(int x, int y)
882{
883 RGFW_window_moveMouse(platform.window, RGFW_POINT(x, y));
884 CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y };
885 CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
886}
888// Set mouse cursor
889void SetMouseCursor(int cursor)
890{
891 RGFW_window_setMouseStandard(platform.window, cursor);
892}
894// Get physical key name
895const char *GetKeyName(int key)
896{
897 TRACELOG(LOG_WARNING, "GetKeyName() unsupported on target platform");
899 return "";
900}
902// Register all input events
903void PollInputEvents(void)
904{
905#if defined(SUPPORT_GESTURES_SYSTEM)
906 // NOTE: Gestures update must be called every frame to reset gestures correctly
907 // because ProcessGestureEvent() is just called on an event, not every frame
908 UpdateGestures();
909#endif
911 // Reset keys/chars pressed registered
912 CORE.Input.Keyboard.keyPressedQueueCount = 0;
913 CORE.Input.Keyboard.charPressedQueueCount = 0;
915 // Reset mouse wheel
916 CORE.Input.Mouse.currentWheelMove.x = 0;
917 CORE.Input.Mouse.currentWheelMove.y = 0;
919 // Register previous mouse position
921 // Reset last gamepad button/axis registered state
922 for (int i = 0; (i < 4) && (i < MAX_GAMEPADS); i++)
923 {
924 // Check if gamepad is available
925 if (CORE.Input.Gamepad.ready[i])
926 {
927 // Register previous gamepad button states
928 for (int k = 0; k < MAX_GAMEPAD_BUTTONS; k++)
929 {
930 CORE.Input.Gamepad.previousButtonState[i][k] = CORE.Input.Gamepad.currentButtonState[i][k];
931 }
932 }
933 }
935 // Register previous touch states
936 for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.previousTouchState[i] = CORE.Input.Touch.currentTouchState[i];
938 // Map touch position to mouse position for convenience
939 CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition;
941 int touchAction = -1; // 0-TOUCH_ACTION_UP, 1-TOUCH_ACTION_DOWN, 2-TOUCH_ACTION_MOVE
942 bool realTouch = false; // Flag to differentiate real touch gestures from mouse ones
944 // Register previous keys states
945 // NOTE: Android supports up to 260 keys
946 for (int i = 0; i < MAX_KEYBOARD_KEYS; i++)
947 {
948 CORE.Input.Keyboard.previousKeyState[i] = CORE.Input.Keyboard.currentKeyState[i];
949 CORE.Input.Keyboard.keyRepeatInFrame[i] = 0;
950 }
952 // Register previous mouse states
953 for (int i = 0; i < MAX_MOUSE_BUTTONS; i++) CORE.Input.Mouse.previousButtonState[i] = CORE.Input.Mouse.currentButtonState[i];
955 // Poll input events for current platform
956 //-----------------------------------------------------------------------------
957 CORE.Window.resizedLastFrame = false;
959 CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
960 if (FLAG_IS_SET(platform.window->_flags, RGFW_HOLD_MOUSE))
961 {
962 CORE.Input.Mouse.previousPosition = (Vector2){ 0.0f, 0.0f };
963 CORE.Input.Mouse.currentPosition = (Vector2){ 0.0f, 0.0f };
964 }
965 else
966 {
967 CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
968 }
970 if ((CORE.Window.eventWaiting) || (IsWindowState(FLAG_WINDOW_MINIMIZED) && !IsWindowState(FLAG_WINDOW_ALWAYS_RUN)))
971 {
972 RGFW_window_eventWait(platform.window, -1); // Wait for input events: keyboard/mouse/window events (callbacks) -> Update keys state
973 CORE.Time.previous = GetTime();
974 }
976 while (RGFW_window_checkEvent(platform.window))
977 {
978 RGFW_event *event = &platform.window->event;
979 // All input events can be processed after polling
981 switch (event->type)
982 {
983 case RGFW_mouseEnter: CORE.Input.Mouse.cursorOnScreen = true; break;
984 case RGFW_mouseLeave: CORE.Input.Mouse.cursorOnScreen = false; break;
985 case RGFW_quit:
986 event->type = 0;
987 CORE.Window.shouldClose = true;
988 return;
989 case RGFW_DND: // Dropped file
990 {
991 for (int i = 0; i < event->droppedFilesCount; i++)
992 {
993 if (CORE.Window.dropFileCount == 0)
994 {
995 // When a new file is dropped, we reserve a fixed number of slots for all possible dropped files
996 // at the moment we limit the number of drops at once to 1024 files but this behaviour should probably be reviewed
997 // TODO: Pointers should probably be reallocated for any new file added...
998 CORE.Window.dropFilepaths = (char **)RL_CALLOC(1024, sizeof(char *));
1000 CORE.Window.dropFilepaths[CORE.Window.dropFileCount] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char));
1001 strcpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event->droppedFiles[i]);
1003 CORE.Window.dropFileCount++;
1004 }
1005 else if (CORE.Window.dropFileCount < 1024)
1006 {
1007 CORE.Window.dropFilepaths[CORE.Window.dropFileCount] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char));
1008 strcpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event->droppedFiles[i]);
1010 CORE.Window.dropFileCount++;
1011 }
1012 else TRACELOG(LOG_WARNING, "FILE: Maximum drag and drop files at once is limited to 1024 files!");
1013 }
1014 } break;
1016 // Window events are also polled (Minimized, maximized, close...)
1017 case RGFW_windowResized:
1018 {
1019 SetupViewport(platform.window->r.w, platform.window->r.h);
1021 // if we are doing automatic DPI scaling, then the "screen" size is divided by the window scale
1022 if (IsWindowState(FLAG_WINDOW_HIGHDPI))
1023 {
1024 CORE.Window.screen.width = (int)(platform.window->r.w/GetWindowScaleDPI().x);
1025 CORE.Window.screen.height = (int)(platform.window->r.h/GetWindowScaleDPI().y);
1026 }
1027 else
1028 {
1029 CORE.Window.screen.width = platform.window->r.w;
1030 CORE.Window.screen.height = platform.window->r.h;
1031 }
1033 CORE.Window.currentFbo.width = platform.window->r.w;
1034 CORE.Window.currentFbo.height = platform.window->r.h;
1035 CORE.Window.resizedLastFrame = true;
1036 } break;
1037 case RGFW_windowMaximized:
1038 {
1039 FLAG_SET(CORE.Window.flags, FLAG_WINDOW_MAXIMIZED); // The window was maximized
1040 } break;
1041 case RGFW_windowMinimized:
1042 {
1043 FLAG_SET(CORE.Window.flags, FLAG_WINDOW_MINIMIZED); // The window was iconified
1044 } break;
1045 case RGFW_windowRestored:
1046 {
1047 if (RGFW_window_isMaximized(platform.window))
1048 FLAG_CLEAR(CORE.Window.flags, FLAG_WINDOW_MAXIMIZED); // The window was restored
1049 if (RGFW_window_isMinimized(platform.window))
1050 FLAG_CLEAR(CORE.Window.flags, FLAG_WINDOW_MINIMIZED); // The window was restored
1051 } break;
1052 case RGFW_windowMoved:
1053 {
1054 CORE.Window.position.x = platform.window->r.x;
1055 CORE.Window.position.y = platform.window->r.x;
1056 } break;
1058 // Keyboard events
1059 case RGFW_keyPressed:
1060 {
1061 KeyboardKey key = ConvertScancodeToKey(event->key);
1062 if (key != KEY_NULL)
1063 {
1064 // If key was up, add it to the key pressed queue
1065 if ((CORE.Input.Keyboard.currentKeyState[key] == 0) && (CORE.Input.Keyboard.keyPressedQueueCount < MAX_KEY_PRESSED_QUEUE))
1066 {
1067 CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = key;
1068 CORE.Input.Keyboard.keyPressedQueueCount++;
1069 }
1071 CORE.Input.Keyboard.currentKeyState[key] = 1;
1072 }
1074 if (CORE.Input.Keyboard.currentKeyState[CORE.Input.Keyboard.exitKey]) CORE.Window.shouldClose = true;
1076 // NOTE: event.text.text data comes an UTF-8 text sequence but we register codepoints (int)
1077 // Check if there is space available in the queue
1078 if (CORE.Input.Keyboard.charPressedQueueCount < MAX_CHAR_PRESSED_QUEUE)
1079 {
1080 // Add character (codepoint) to the queue
1081 CORE.Input.Keyboard.charPressedQueue[CORE.Input.Keyboard.charPressedQueueCount] = event->keyChar;
1082 CORE.Input.Keyboard.charPressedQueueCount++;
1083 }
1084 } break;
1085 case RGFW_keyReleased:
1086 {
1087 KeyboardKey key = ConvertScancodeToKey(event->key);
1088 if (key != KEY_NULL) CORE.Input.Keyboard.currentKeyState[key] = 0;
1089 } break;
1091 // Check mouse events
1092 case RGFW_mouseButtonPressed:
1093 {
1094 if ((event->button == RGFW_mouseScrollUp) || (event->button == RGFW_mouseScrollDown))
1095 {
1096 CORE.Input.Mouse.currentWheelMove.y = event->scroll;
1097 break;
1098 }
1099 else CORE.Input.Mouse.currentWheelMove.y = 0;
1101 int btn = event->button;
1102 if (btn == RGFW_mouseLeft) btn = 1;
1103 else if (btn == RGFW_mouseRight) btn = 2;
1104 else if (btn == RGFW_mouseMiddle) btn = 3;
1106 CORE.Input.Mouse.currentButtonState[btn - 1] = 1;
1107 CORE.Input.Touch.currentTouchState[btn - 1] = 1;
1109 touchAction = 1;
1110 } break;
1111 case RGFW_mouseButtonReleased:
1112 {
1113 if ((event->button == RGFW_mouseScrollUp) || (event->button == RGFW_mouseScrollDown))
1114 {
1115 CORE.Input.Mouse.currentWheelMove.y = event->scroll;
1116 break;
1117 }
1118 else CORE.Input.Mouse.currentWheelMove.y = 0;
1120 int btn = event->button;
1121 if (btn == RGFW_mouseLeft) btn = 1;
1122 else if (btn == RGFW_mouseRight) btn = 2;
1123 else if (btn == RGFW_mouseMiddle) btn = 3;
1125 CORE.Input.Mouse.currentButtonState[btn - 1] = 0;
1126 CORE.Input.Touch.currentTouchState[btn - 1] = 0;
1128 touchAction = 0;
1129 } break;
1130 case RGFW_mousePosChanged:
1131 {
1132 if (FLAG_IS_SET(platform.window->_flags, RGFW_HOLD_MOUSE))
1133 {
1134 CORE.Input.Mouse.currentPosition.x += (float)event->vector.x;
1135 CORE.Input.Mouse.currentPosition.y += (float)event->vector.y;
1136 }
1137 else
1138 {
1139 CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
1140 CORE.Input.Mouse.currentPosition.x = (float)event->point.x;
1141 CORE.Input.Mouse.currentPosition.y = (float)event->point.y;
1142 }
1144 CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition;
1145 touchAction = 2;
1146 } break;
1147 case RGFW_gamepadConnected:
1148 {
1149 CORE.Input.Gamepad.ready[platform.window->event.gamepad] = true;
1150 CORE.Input.Gamepad.axisCount[platform.window->event.gamepad] = platform.window->event.axisesCount;
1151 CORE.Input.Gamepad.axisState[platform.window->event.gamepad][GAMEPAD_AXIS_LEFT_TRIGGER] = -1.0f;
1152 CORE.Input.Gamepad.axisState[platform.window->event.gamepad][GAMEPAD_AXIS_RIGHT_TRIGGER] = -1.0f;
1154 strcpy(CORE.Input.Gamepad.name[platform.window->event.gamepad], RGFW_getGamepadName(platform.window, platform.window->event.gamepad));
1155 } break;
1156 case RGFW_gamepadDisconnected:
1157 {
1158 CORE.Input.Gamepad.ready[platform.window->event.gamepad] = false;
1159 } break;
1160 case RGFW_gamepadButtonPressed:
1161 {
1162 int button = RGFW_gpConvTable[event->button];
1164 if (button >= 0)
1165 {
1166 CORE.Input.Gamepad.currentButtonState[event->gamepad][button] = 1;
1167 CORE.Input.Gamepad.lastButtonPressed = button;
1168 }
1169 } break;
1170 case RGFW_gamepadButtonReleased:
1171 {
1172 int button = RGFW_gpConvTable[event->button];
1174 CORE.Input.Gamepad.currentButtonState[event->gamepad][button] = 0;
1175 if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0;
1176 } break;
1177 case RGFW_gamepadAxisMove:
1178 {
1179 int axis = -1;
1180 float value = 0;
1182 switch(event->whichAxis)
1183 {
1184 case 0:
1185 {
1186 CORE.Input.Gamepad.axisState[event->gamepad][GAMEPAD_AXIS_LEFT_X] = event->axis[0].x/100.0f;
1187 CORE.Input.Gamepad.axisState[event->gamepad][GAMEPAD_AXIS_LEFT_Y] = event->axis[0].y/100.0f;
1188 } break;
1189 case 1:
1190 {
1191 CORE.Input.Gamepad.axisState[event->gamepad][GAMEPAD_AXIS_RIGHT_X] = event->axis[1].x/100.0f;
1192 CORE.Input.Gamepad.axisState[event->gamepad][GAMEPAD_AXIS_RIGHT_Y] = event->axis[1].y/100.0f;
1193 } break;
1194 case 2: axis = GAMEPAD_AXIS_LEFT_TRIGGER;
1195 case 3:
1196 {
1197 if (axis == -1) axis = GAMEPAD_AXIS_RIGHT_TRIGGER;
1199 int button = (axis == GAMEPAD_AXIS_LEFT_TRIGGER)? GAMEPAD_BUTTON_LEFT_TRIGGER_2 : GAMEPAD_BUTTON_RIGHT_TRIGGER_2;
1200 int pressed = (value > 0.1f);
1201 CORE.Input.Gamepad.currentButtonState[event->gamepad][button] = pressed;
1203 if (pressed) CORE.Input.Gamepad.lastButtonPressed = button;
1204 else if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0;
1205 }
1206 default: break;
1207 }
1208 } break;
1209 default: break;
1210 }
1212#if defined(SUPPORT_GESTURES_SYSTEM)
1213 if (touchAction > -1)
1214 {
1215 // Process mouse events as touches to be able to use mouse-gestures
1216 GestureEvent gestureEvent = { 0 };
1218 // Register touch actions
1219 gestureEvent.touchAction = touchAction;
1221 // Assign a pointer ID
1222 gestureEvent.pointId[0] = 0;
1224 // Register touch points count
1225 gestureEvent.pointCount = 1;
1227 // Register touch points position, only one point registered
1228 if (touchAction == 2 || realTouch) gestureEvent.position[0] = CORE.Input.Touch.position[0];
1229 else gestureEvent.position[0] = GetMousePosition();
1231 // Normalize gestureEvent.position[0] for CORE.Window.screen.width and CORE.Window.screen.height
1232 gestureEvent.position[0].x /= (float)GetScreenWidth();
1233 gestureEvent.position[0].y /= (float)GetScreenHeight();
1235 // Gesture data is sent to gestures-system for processing
1236 ProcessGestureEvent(gestureEvent);
1238 touchAction = -1;
1239 }
1240#endif
1241 }
1242 //-----------------------------------------------------------------------------
1243}
1245//----------------------------------------------------------------------------------
1246// Module Internal Functions Definition
1247//----------------------------------------------------------------------------------
1249// Initialize platform: graphics, inputs and more
1250int InitPlatform(void)
1251{
1252 // Initialize RGFW internal global state, only required systems
1253 unsigned int flags = RGFW_windowCenter | RGFW_windowAllowDND;
1255 // Check window creation flags
1256 if (FLAG_IS_SET(CORE.Window.flags, FLAG_FULLSCREEN_MODE))
1257 {
1258 FLAG_SET(flags, RGFW_windowFullscreen);
1259 }
1261 if (FLAG_IS_SET(CORE.Window.flags, FLAG_BORDERLESS_WINDOWED_MODE))
1262 {
1263 FLAG_SET(flags, RGFW_windowedFullscreen);
1264 }
1266 if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_UNDECORATED)) FLAG_SET(flags, RGFW_windowNoBorder);
1267 if (!FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_RESIZABLE)) FLAG_SET(flags, RGFW_windowNoResize);
1268 if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_TRANSPARENT)) FLAG_SET(flags, RGFW_windowTransparent);
1269 if (FLAG_IS_SET(CORE.Window.flags, FLAG_FULLSCREEN_MODE)) FLAG_SET(flags, RGFW_windowFullscreen);
1270 if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_HIDDEN)) FLAG_SET(flags, RGFW_windowHide);
1271 if (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_MAXIMIZED)) FLAG_SET(flags, RGFW_windowMaximize);
1273 // NOTE: Some OpenGL context attributes must be set before window creation
1274 // Check selection OpenGL version
1275 if (rlGetVersion() == RL_OPENGL_21)
1276 {
1277 RGFW_setGLHint(RGFW_glMajor, 2);
1278 RGFW_setGLHint(RGFW_glMinor, 1);
1279 }
1280 else if (rlGetVersion() == RL_OPENGL_33)
1281 {
1282 RGFW_setGLHint(RGFW_glMajor, 3);
1283 RGFW_setGLHint(RGFW_glMinor, 3);
1284 }
1285 else if (rlGetVersion() == RL_OPENGL_43)
1286 {
1287 RGFW_setGLHint(RGFW_glMajor, 4);
1288 RGFW_setGLHint(RGFW_glMinor, 3);
1289 }
1291 if (FLAG_IS_SET(CORE.Window.flags, FLAG_MSAA_4X_HINT)) RGFW_setGLHint(RGFW_glSamples, 4);
1293 if (!FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_UNFOCUSED)) FLAG_SET(flags, RGFW_windowFocusOnShow | RGFW_windowFocus);
1295 platform.window = RGFW_createWindow(CORE.Window.title, RGFW_RECT(0, 0, CORE.Window.screen.width, CORE.Window.screen.height), flags);
1296 platform.mon.mode.area.w = 0;
1298 if (platform.window != NULL)
1299 {
1300 // NOTE: RGFW's exit key is distinct from raylib's exit key (which can
1301 // be set with SetExitKey()) and defaults to Escape
1302 platform.window->exitKey = RGFW_keyNULL;
1303 }
1305#ifndef PLATFORM_WEB_RGFW
1306 RGFW_area screenSize = RGFW_getScreenSize();
1307 CORE.Window.display.width = screenSize.w;
1308 CORE.Window.display.height = screenSize.h;
1309#else
1310 CORE.Window.display.width = CORE.Window.screen.width;
1311 CORE.Window.display.height = CORE.Window.screen.height;
1312#endif
1313 if (FLAG_IS_SET(CORE.Window.flags, FLAG_VSYNC_HINT)) RGFW_window_swapInterval(platform.window, 1);
1314 RGFW_window_makeCurrent(platform.window);
1316 // Check surface and context activation
1317 if (platform.window != NULL)
1318 {
1319 CORE.Window.ready = true;
1321 CORE.Window.render.width = CORE.Window.screen.width;
1322 CORE.Window.render.height = CORE.Window.screen.height;
1323 CORE.Window.currentFbo.width = CORE.Window.render.width;
1324 CORE.Window.currentFbo.height = CORE.Window.render.height;
1325 }
1326 else
1327 {
1328 TRACELOG(LOG_FATAL, "PLATFORM: Failed to initialize graphics device");
1329 return -1;
1330 }
1331 //----------------------------------------------------------------------------
1333 // If everything work as expected, we can continue
1334 CORE.Window.position.x = platform.window->r.x;
1335 CORE.Window.position.y = platform.window->r.y;
1336 CORE.Window.render.width = CORE.Window.screen.width;
1337 CORE.Window.render.height = CORE.Window.screen.height;
1338 CORE.Window.currentFbo.width = CORE.Window.render.width;
1339 CORE.Window.currentFbo.height = CORE.Window.render.height;
1341 TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully");
1342 TRACELOG(LOG_INFO, " > Display size: %i x %i", CORE.Window.display.width, CORE.Window.display.height);
1343 TRACELOG(LOG_INFO, " > Screen size: %i x %i", CORE.Window.screen.width, CORE.Window.screen.height);
1344 TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height);
1345 TRACELOG(LOG_INFO, " > Viewport offsets: %i, %i", CORE.Window.renderOffset.x, CORE.Window.renderOffset.y);
1347 // Load OpenGL extensions
1348 // NOTE: GL procedures address loader is required to load extensions
1349 //----------------------------------------------------------------------------
1350 rlLoadExtensions((void *)RGFW_getProcAddress);
1351 //----------------------------------------------------------------------------
1353 // Initialize timing system
1354 //----------------------------------------------------------------------------
1355 InitTimer();
1356 //----------------------------------------------------------------------------
1358 // Initialize storage system
1359 //----------------------------------------------------------------------------
1360 CORE.Storage.basePath = GetWorkingDirectory();
1361 //----------------------------------------------------------------------------
1363#if defined(RGFW_WAYLAND)
1364 if (RGFW_useWaylandBool) TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - Wayland): Initialized successfully");
1365 else TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - X11 (fallback)): Initialized successfully");
1366#elif defined(RGFW_X11)
1367 #if defined(__APPLE__)
1368 TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - X11 (MacOS)): Initialized successfully");
1369 #else
1370 TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - X11): Initialized successfully");
1371 #endif
1372#elif defined (RGFW_WINDOWS)
1373 TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - Win32): Initialized successfully");
1374#elif defined(RGFW_WASM)
1375 TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - WASMs): Initialized successfully");
1376#elif defined(RGFW_MACOS)
1377 TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (RGFW - MacOS): Initialized successfully");
1378#endif
1380 return 0;
1381}
1383// Close platform
1384void ClosePlatform(void)
1385{
1386 RGFW_window_close(platform.window);
1387}
1389// Keycode mapping
1390static KeyboardKey ConvertScancodeToKey(u32 keycode)
1391{
1392 if (keycode > sizeof(keyMappingRGFW)/sizeof(unsigned short)) return KEY_NULL;
1394 return (KeyboardKey)keyMappingRGFW[keycode];
1395}
index : raylib-jai
---