From f1f08861a1dd86cdd054603522a70a4828663a3e Mon Sep 17 00:00:00 2001 From: Colleague Riley Date: Mon, 22 Jul 2024 16:19:09 -0400 Subject: [PATCH 1/4] Update RGFW (#4176) * update RGFW * fix bug with GetCurrentMonitor * update RGFW * update RGFW * clean up merge --- src/external/RGFW.h | 3369 ++++++++++++++++++---------- src/platforms/rcore_desktop_rgfw.c | 49 +- 2 files changed, 2189 insertions(+), 1229 deletions(-) diff --git a/src/external/RGFW.h b/src/external/RGFW.h index 646ecc9a00a0..5420ccab1eab 100644 --- a/src/external/RGFW.h +++ b/src/external/RGFW.h @@ -54,6 +54,9 @@ #define RGFW_MALLOC x - choose what function to use to allocate, by default the standard malloc is used #define RGFW_CALLOC x - choose what function to use to allocate (calloc), by default the standard calloc is used #define RGFW_FREE x - choose what function to use to allocated memory, by default the standard free is used + + #define RGFW_EXPORT - Use when building RGFW + #define RGFW_IMPORT - Use when linking with RGFW (not as a single-header) */ /* @@ -76,50 +79,75 @@ krisvers -> code review EimaMei (SaCode) -> code review Code-Nycticebus -> bug fixes - Rob Rohan -> X11 bugs and missing features + Rob Rohan -> X11 bugs and missing features, MacOS/Cocoa fixing memory issues/bugs AICDG (@THISISAGOODNAME) -> vulkan support (example) */ +#if _MSC_VER + #pragma comment(lib, "gdi32") + #pragma comment(lib, "shell32") + #pragma comment(lib, "opengl32") + #pragma comment(lib, "winmm") + #pragma comment(lib, "user32") +#endif + #ifndef RGFW_MALLOC -#include -#include -#define RGFW_MALLOC malloc -#define RGFW_CALLOC calloc -#define RGFW_FREE free + #include + #include + #define RGFW_MALLOC malloc + #define RGFW_CALLOC calloc + #define RGFW_FREE free #endif #if !_MSC_VER -#ifndef inline -#ifndef __APPLE__ -#define inline __inline -#endif -#endif + #ifndef inline + #ifndef __APPLE__ + #define inline __inline + #endif + #endif #endif -/* for windows 95 testing (not that it works well) */ -#ifdef RGFW_WIN95 -#define RGFW_NO_MONITOR -#define RGFW_NO_PASSTHROUGH +#ifdef RGFW_WIN95 /* for windows 95 testing (not that it really works) */ + #define RGFW_NO_MONITOR + #define RGFW_NO_PASSTHROUGH #endif +#if defined(RGFW_EXPORT) || defined(RGFW_IMPORT) + #if defined(_WIN32) + #if defined(__TINYC__) && (defined(RGFW_EXPORT) || defined(RGFW_IMPORT)) + #define __declspec(x) __attribute__((x)) + #endif + + #if defined(RGFW_EXPORT) + #define RGFWDEF __declspec(dllexport) + #else + #define RGFWDEF __declspec(dllimport) + #endif + #else + #if defined(RGFW_EXPORT) + #define RGFWDEF __attribute__((visibility("default"))) + #endif + #endif +#endif + #ifndef RGFWDEF -#ifdef __APPLE__ -#define RGFWDEF static inline -#else -#define RGFWDEF inline -#endif + #ifdef __APPLE__ + #define RGFWDEF static inline + #else + #define RGFWDEF inline + #endif #endif #ifndef RGFW_ENUM -#define RGFW_ENUM(type, name) type name; enum + #define RGFW_ENUM(type, name) type name; enum #endif #ifndef RGFW_UNUSED -#define RGFW_UNUSED(x) (void)(x); + #define RGFW_UNUSED(x) (void)(x); #endif #ifdef __cplusplus -extern "C" { + extern "C" { #endif /* makes sure the header file part is only defined once by default */ @@ -128,7 +156,7 @@ extern "C" { #define RGFW_HEADER #if !defined(u8) - #if defined(_MSC_VER) || defined(__SYMBIAN32__) + #if defined(_MSC_VER) || defined(__SYMBIAN32__) /* MSVC might not have stdint.h */ typedef unsigned char u8; typedef signed char i8; typedef unsigned short u16; @@ -137,7 +165,7 @@ extern "C" { typedef signed int i32; typedef unsigned long u64; typedef signed long i64; - #else + #else /* use stdint standard types instead of c ""standard"" types */ #include typedef uint8_t u8; @@ -151,105 +179,109 @@ extern "C" { #endif #endif -#if !defined(b8) +#if !defined(b8) /* RGFW bool type */ typedef u8 b8; + typedef u32 b32; + #define RGFW_TRUE 1 + #define RGFW_FALSE 0 #endif -#if defined(RGFW_X11) && defined(__APPLE__) -#define RGFW_MACOS_X11 -#undef __APPLE__ -#endif +/* thse OS macros looks better & are standardized */ +/* plus it helps with cross-compiling */ -#if defined(_WIN32) && !defined(RGFW_X11) /* (if you're using X11 on windows some how) */ - - /* this name looks better */ - /* plus it helps with cross-compiling because RGFW_X11 won't be accidently defined */ - -#define RGFW_WINDOWS +#ifdef __EMSCRIPTEN__ + #define RGFW_WEBASM -#if defined(_WIN32) && !defined(WIN32) -#define WIN32 -#endif + #ifndef RGFW_NO_API + #define RGFW_OPENGL + #endif -#if defined(_WIN64) + #ifdef RGFW_EGL + #undef RGFW_EGL + #endif -#ifndef WIN64 -#define WIN64 + #include + #include #endif -#define _AMD64_ -#undef _X86_ -#else -#undef _AMD64_ -#ifndef _X86_ -#define _X86_ -#endif +#if defined(RGFW_X11) && defined(__APPLE__) + #define RGFW_MACOS_X11 + #undef __APPLE__ #endif -#ifndef RGFW_NO_XINPUT -#ifdef __MINGW32__ -#include -#else -#include -#endif -#endif +#if defined(_WIN32) && !defined(RGFW_X11) && !defined(RGFW_WEBASM) /* (if you're using X11 on windows some how) */ + #define RGFW_WINDOWS -#else -#if defined(__unix__) || defined(RGFW_MACOS_X11) || defined(RGFW_X11) -#define RGFW_MACOS_X11 -#define RGFW_X11 -#include -#endif -#endif + /* make sure the correct architecture is defined */ + #if defined(_WIN64) + #define _AMD64_ + #undef _X86_ + #else + #undef _AMD64_ + #ifndef _X86_ + #define _X86_ + #endif + #endif + + #ifndef RGFW_NO_XINPUT + #ifdef __MINGW32__ /* try to find the right header */ + #include + #else + #include + #endif + #endif + + #if defined(RGFW_DIRECTX) + #include + #include + #include + #include + + #ifndef __cplusplus + #define __uuidof(T) IID_##T + #endif + #endif -#if defined(__APPLE__) && !defined(RGFW_MACOS_X11) && !defined(RGFW_X11) -#define RGFW_MACOS +#elif (defined(__unix__) || defined(RGFW_MACOS_X11) || defined(RGFW_X11)) && !defined(RGFW_WEBASM) + #define RGFW_MACOS_X11 + #define RGFW_X11 + #include +#elif defined(__APPLE__) && !defined(RGFW_MACOS_X11) && !defined(RGFW_X11) && !defined(RGFW_WEBASM) + #define RGFW_MACOS #endif #if (defined(RGFW_OPENGL_ES1) || defined(RGFW_OPENGL_ES2) || defined(RGFW_OPENGL_ES3)) && !defined(RGFW_EGL) -#define RGFW_EGL -#endif -#if defined(RGFW_EGL) && defined(__APPLE__) - #warning EGL is not supported for Cocoa, switching back to the native opengl api -#undef RGFW_EGL + #define RGFW_EGL #endif #if !defined(RGFW_OSMESA) && !defined(RGFW_EGL) && !defined(RGFW_OPENGL) && !defined(RGFW_DIRECTX) && !defined(RGFW_BUFFER) && !defined(RGFW_NO_API) -#define RGFW_OPENGL -#endif - -#if defined(RGFW_X11) && (defined(RGFW_OPENGL)) -#ifndef GLX_MESA_swap_control -#define GLX_MESA_swap_control -#endif -#include /* GLX defs, xlib.h, gl.h */ + #define RGFW_OPENGL #endif #ifdef RGFW_EGL -#include -#endif + #if defined(__APPLE__) + #warning EGL is not supported for Cocoa, switching back to the native opengl api + #undef RGFW_EGL + #endif -#ifdef RGFW_OSMESA -#ifndef __APPLE__ -#include -#else -#include -#endif + #include +#elif defined(RGFW_OSMESA) + #ifndef __APPLE__ + #include + #else + #include + #endif #endif -#if defined(RGFW_DIRECTX) && defined(RGFW_WINDOWS) -#include -#include -#include -#include - -#ifndef __cplusplus -#define __uuidof(T) IID_##T -#endif +#if defined(RGFW_OPENGL) && defined(RGFW_X11) + #ifndef GLX_MESA_swap_control + #define GLX_MESA_swap_control + #endif + #include /* GLX defs, xlib.h, gl.h */ #endif #ifndef RGFW_ALPHA -#define RGFW_ALPHA 128 /* alpha value for RGFW_TRANSPARENT_WINDOW (WINAPI ONLY, macOS + linux don't need this) */ + #define RGFW_ALPHA 128 /* alpha value for RGFW_TRANSPARENT_WINDOW (WINAPI ONLY, macOS + linux don't need this) */ #endif /*! Optional arguments for making a windows */ @@ -268,7 +300,6 @@ extern "C" { #define RGFW_NO_GPU_RENDER (1L<<14) /* don't render (using the GPU based API)*/ #define RGFW_NO_CPU_RENDER (1L<<15) /* don't render (using the CPU based buffer rendering)*/ - /*! event codes */ #define RGFW_keyPressed 2 /* a key has been pressed */ #define RGFW_keyReleased 3 /*!< a key has been released*/ @@ -302,7 +333,7 @@ extern "C" { RGFW_Event.axisCount says how many axis there are */ #define RGFW_windowMoved 10 /*!< the window was moved (by the user) */ -#define RGFW_windowResized 11 /*!< the window was resized (by the user) */ +#define RGFW_windowResized 11 /*!< the window was resized (by the user), [on webASM this means the browser was resized] */ #define RGFW_focusIn 12 /*!< window is in focus now */ #define RGFW_focusOut 13 /*!< window is out of focus now */ @@ -349,30 +380,28 @@ extern "C" { /*! joystick button codes (based on xbox/playstation), you may need to change these values per controller */ #ifndef RGFW_joystick_codes - -typedef RGFW_ENUM(u8, RGFW_joystick_codes) { - RGFW_JS_A = 0, /* or PS X button */ - RGFW_JS_B = 1, /* or PS circle button */ - RGFW_JS_Y = 2, /* or PS triangle button */ - RGFW_JS_X = 3, /* or PS square button */ - RGFW_JS_START = 9, /* start button */ - RGFW_JS_SELECT = 8, /* select button */ - RGFW_JS_HOME = 10, /* home button */ - RGFW_JS_UP = 13, /* dpad up */ - RGFW_JS_DOWN = 14, /* dpad down*/ - RGFW_JS_LEFT = 15, /* dpad left */ - RGFW_JS_RIGHT = 16, /* dpad right */ - RGFW_JS_L1 = 4, /* left bump */ - RGFW_JS_L2 = 5, /* left trigger*/ - RGFW_JS_R1 = 6, /* right bumper */ - RGFW_JS_R2 = 7, /* right trigger */ -}; - + typedef RGFW_ENUM(u8, RGFW_joystick_codes) { + RGFW_JS_A = 0, /* or PS X button */ + RGFW_JS_B = 1, /* or PS circle button */ + RGFW_JS_Y = 2, /* or PS triangle button */ + RGFW_JS_X = 3, /* or PS square button */ + RGFW_JS_START = 9, /* start button */ + RGFW_JS_SELECT = 8, /* select button */ + RGFW_JS_HOME = 10, /* home button */ + RGFW_JS_UP = 13, /* dpad up */ + RGFW_JS_DOWN = 14, /* dpad down*/ + RGFW_JS_LEFT = 15, /* dpad left */ + RGFW_JS_RIGHT = 16, /* dpad right */ + RGFW_JS_L1 = 4, /* left bump */ + RGFW_JS_L2 = 5, /* left trigger*/ + RGFW_JS_R1 = 6, /* right bumper */ + RGFW_JS_R2 = 7, /* right trigger */ + }; #endif /* basic vector type, if there's not already a point/vector type of choice */ -#ifndef RGFW_vector -typedef struct { i32 x, y; } RGFW_vector; +#ifndef RGFW_point + typedef struct { i32 x, y; } RGFW_point; #endif /* basic rect type, if there's not already a rect type of choice */ @@ -385,11 +414,11 @@ typedef struct { i32 x, y; } RGFW_vector; typedef struct { u32 w, h; } RGFW_area; #endif -#define RGFW_VECTOR(x, y) (RGFW_vector){x, y} +#define RGFW_POINT(x, y) (RGFW_point){x, y} #define RGFW_RECT(x, y, w, h) (RGFW_rect){x, y, w, h} #define RGFW_AREA(w, h) (RGFW_area){w, h} - #ifndef RGFW_NO_MONITOR +#ifndef RGFW_NO_MONITOR typedef struct RGFW_monitor { char name[128]; /* monitor name */ RGFW_rect rect; /* monitor Workarea */ @@ -405,146 +434,132 @@ typedef struct { i32 x, y; } RGFW_vector; RGFWDEF RGFW_monitor* RGFW_getMonitors(void); /* get the primary monitor */ RGFWDEF RGFW_monitor RGFW_getPrimaryMonitor(void); - #endif +#endif - /* NOTE: some parts of the data can represent different things based on the event (read comments in RGFW_Event struct) */ - typedef struct RGFW_Event { - char keyName[16]; /* key name of event*/ +/* NOTE: some parts of the data can represent different things based on the event (read comments in RGFW_Event struct) */ +typedef struct RGFW_Event { + char keyName[16]; /* key name of event*/ - /*! drag and drop data */ - /* 260 max paths with a max length of 260 */ + /*! drag and drop data */ + /* 260 max paths with a max length of 260 */ #ifdef RGFW_ALLOC_DROPFILES - char** droppedFiles; + char** droppedFiles; #else - char droppedFiles[RGFW_MAX_DROPS][RGFW_MAX_PATH]; /*!< dropped files*/ + char droppedFiles[RGFW_MAX_DROPS][RGFW_MAX_PATH]; /*!< dropped files*/ #endif - u32 droppedFilesCount; /*!< house many files were dropped */ - - u32 type; /*!< which event has been sent?*/ - RGFW_vector point; /*!< mouse x, y of event (or drop point) */ - - u32 fps; /*the current fps of the window [the fps is checked when events are checked]*/ - u64 frameTime, frameTime2; /* this is used for counting the fps */ - - u8 keyCode; /*!< keycode of event !!Keycodes defined at the bottom of the RGFW_HEADER part of this file!! */ + u32 droppedFilesCount; /*!< house many files were dropped */ - b8 inFocus; /*if the window is in focus or not (this is always true for MacOS windows due to the api being weird) */ - - u8 lockState; + u32 type; /*!< which event has been sent?*/ + RGFW_point point; /*!< mouse x, y of event (or drop point) */ + + u32 fps; /*the current fps of the window [the fps is checked when events are checked]*/ + u64 frameTime, frameTime2; /* this is used for counting the fps */ + + u8 keyCode; /*!< keycode of event !!Keycodes defined at the bottom of the RGFW_HEADER part of this file!! */ - u16 joystick; /* which joystick this event applies to (if applicable to any) */ + b8 inFocus; /*if the window is in focus or not (this is always true for MacOS windows due to the api being weird) */ - u8 button; /*!< which mouse button has been clicked (0) left (1) middle (2) right OR which joystick button was pressed*/ - double scroll; /* the raw mouse scroll value */ + u8 lockState; - u8 axisesCount; /* number of axises */ - RGFW_vector axis[2]; /* x, y of axises (-100 to 100) */ - } RGFW_Event; /*!< Event structure for checking/getting events */ + u16 joystick; /* which joystick this event applies to (if applicable to any) */ - /* source data for the window (used by the APIs) */ - typedef struct RGFW_window_src { -#ifdef RGFW_WINDOWS - HWND window; /*!< source window */ - HDC hdc; /*!< source HDC */ - u32 hOffset; /*!< height offset for window */ -#endif -#ifdef RGFW_X11 - Display* display; /*!< source display */ - Window window; /*!< source window */ -#endif -#ifdef RGFW_MACOS - u32 display; - void* displayLink; - void* window; - b8 dndPassed; -#endif + u8 button; /*!< which mouse button has been clicked (0) left (1) middle (2) right OR which joystick button was pressed*/ + double scroll; /* the raw mouse scroll value */ -#if (defined(RGFW_OPENGL)) && !defined(RGFW_OSMESA) -#ifdef RGFW_MACOS - void* rSurf; /*!< source graphics context */ -#endif -#ifdef RGFW_WINDOWS - HGLRC rSurf; /*!< source graphics context */ -#endif -#ifdef RGFW_X11 - GLXContext rSurf; /*!< source graphics context */ -#endif -#else + u8 axisesCount; /* number of axises */ + RGFW_point axis[2]; /* x, y of axises (-100 to 100) */ +} RGFW_Event; /*!< Event structure for checking/getting events */ -#ifdef RGFW_OSMESA - OSMesaContext rSurf; -#endif -#endif +/* source data for the window (used by the APIs) */ +typedef struct RGFW_window_src { #ifdef RGFW_WINDOWS - RGFW_area maxSize, minSize; -#if defined(RGFW_DIRECTX) + HWND window; /*!< source window */ + HDC hdc; /*!< source HDC */ + u32 hOffset; /*!< height offset for window */ +#if (defined(RGFW_OPENGL)) && !defined(RGFW_OSMESA) && !defined(RGFW_EGL) + HGLRC ctx; /*!< source graphics context */ +#elif defined(RGFW_OSMESA) + OSMesaContext ctx; +#elif defined(RGFW_DIRECTX) IDXGISwapChain* swapchain; ID3D11RenderTargetView* renderTargetView; ID3D11DepthStencilView* pDepthStencilView; -#endif +#elif defined(RGFW_EGL) + EGLSurface EGL_surface; + EGLDisplay EGL_display; + EGLContext EGL_context; #endif -#if defined(RGFW_MACOS) && !defined(RGFW_MACOS_X11) - void* view; /*apple viewpoint thingy*/ +#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) + HDC hdcMem; + HBITMAP bitmap; #endif - -#ifdef RGFW_EGL + RGFW_area maxSize, minSize; /* for setting max/min resize (RGFW_WINDOWS) */ +#elif defined(RGFW_X11) + Display* display; /*!< source display */ + Window window; /*!< source window */ +#if (defined(RGFW_OPENGL)) && !defined(RGFW_OSMESA) && !defined(RGFW_EGL) + GLXContext ctx; /*!< source graphics context */ +#elif defined(RGFW_OSMESA) + OSMesaContext ctx; +#elif defined(RGFW_EGL) EGLSurface EGL_surface; EGLDisplay EGL_display; EGLContext EGL_context; #endif #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) -#ifdef RGFW_WINDOWS - HBITMAP bitmap; -#endif -#ifdef RGFW_X11 XImage* bitmap; GC gc; #endif -#ifdef RGFW_MACOS +#elif defined(RGFW_MACOS) + u32 display; + void* displayLink; + void* window; + b8 dndPassed; +#if (defined(RGFW_OPENGL)) && !defined(RGFW_OSMESA) && !defined(RGFW_EGL) + void* ctx; /*!< source graphics context */ +#elif defined(RGFW_OSMESA) + OSMesaContext ctx; +#elif defined(RGFW_EGL) + EGLSurface EGL_surface; + EGLDisplay EGL_display; + EGLContext EGL_context; +#endif + + void* view; /*apple viewpoint thingy*/ + +#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) void* bitmap; /* API's bitmap for storing or managing */ void* image; #endif -#if defined(RGFW_BUFFER) && defined(RGFW_WINDOWS) - HDC hdcMem; /* window stored in memory that winapi needs to render buffers */ -#endif +#elif defined(RGFW_WEBASM) + EMSCRIPTEN_WEBGL_CONTEXT_HANDLE ctx; #endif +} RGFW_window_src; - u8 jsPressed[4][16]; /* if a key is currently pressed or not (per joystick) */ - i32 joysticks[4]; /* limit of 4 joysticks at a time */ - u16 joystickCount; /* the actual amount of joysticks */ - RGFW_area scale; /* window scaling */ - -#ifdef RGFW_MACOS - b8 cursorChanged; /* for steve jobs */ -#endif - - u32 winArgs; /* windows args (for RGFW to check) */ - /* - !< if dnd is enabled or on (based on window creating args) - cursorChanged - */ - } RGFW_window_src; - - typedef struct RGFW_window { - RGFW_window_src src; +typedef struct RGFW_window { + RGFW_window_src src; #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) - u8* buffer; /* buffer for non-GPU systems (OSMesa, basic software rendering) */ - /* when rendering using RGFW_BUFFER, the buffer is in the RGBA format */ + u8* buffer; /* buffer for non-GPU systems (OSMesa, basic software rendering) */ + /* when rendering using RGFW_BUFFER, the buffer is in the RGBA format */ #endif - RGFW_Event event; /*!< current event */ + RGFW_Event event; /*!< current event */ + + RGFW_rect r; /* the x, y, w and h of the struct */ + + RGFW_point _lastMousePoint; /* last cusor point (for raw mouse data) */ - RGFW_rect r; /* the x, y, w and h of the struct */ + u32 fpsCap; /*!< the fps cap of the window should run at (change this var to change the fps cap, 0 = no limit)*/ + /*[the fps is capped when events are checked]*/ - u32 fpsCap; /*!< the fps cap of the window should run at (change this var to change the fps cap, 0 = no limit)*/ - /*[the fps is capped when events are checked]*/ - } RGFW_window; /*!< Window structure for managing the window */ + u32 _winArgs; /* windows args (for RGFW to check) */ +} RGFW_window; /*!< Window structure for managing the window */ #if defined(RGFW_X11) || defined(RGFW_MACOS) typedef u64 RGFW_thread; /* thread type unix */ @@ -552,223 +567,266 @@ typedef struct { i32 x, y; } RGFW_vector; typedef void* RGFW_thread; /* thread type for window */ #endif - /* this has to be set before createWindow is called, else the fulscreen size is used */ - RGFWDEF void RGFW_setBufferSize(RGFW_area size); /* the buffer cannot be resized (by RGFW) */ +/* this has to be set before createWindow is called, else the fulscreen size is used */ +RGFWDEF void RGFW_setBufferSize(RGFW_area size); /* the buffer cannot be resized (by RGFW) */ - RGFW_window* RGFW_createWindow( - const char* name, /* name of the window */ - RGFW_rect rect, /* rect of window */ - u16 args /* extra arguments (NULL / (u16)0 means no args used)*/ - ); /*!< function to create a window struct */ +RGFW_window* RGFW_createWindow( + const char* name, /* name of the window */ + RGFW_rect rect, /* rect of window */ + u16 args /* extra arguments (NULL / (u16)0 means no args used)*/ +); /*!< function to create a window struct */ - /* get the size of the screen to an area struct */ - RGFWDEF RGFW_area RGFW_getScreenSize(void); +/* get the size of the screen to an area struct */ +RGFWDEF RGFW_area RGFW_getScreenSize(void); - /* - this function checks an *individual* event (and updates window structure attributes) - this means, using this function without a while loop may cause event lag +/* + this function checks an *individual* event (and updates window structure attributes) + this means, using this function without a while loop may cause event lag - ex. + ex. - while (RGFW_window_checkEvent(win) != NULL) [this keeps checking events until it reaches the last one] + while (RGFW_window_checkEvent(win) != NULL) [this keeps checking events until it reaches the last one] - this function is optional if you choose to use event callbacks, - although you still need some way to tell RGFW to process events eg. `RGFW_window_checkEvents` - */ + this function is optional if you choose to use event callbacks, + although you still need some way to tell RGFW to process events eg. `RGFW_window_checkEvents` +*/ - RGFW_Event* RGFW_window_checkEvent(RGFW_window* win); /*!< check current event (returns a pointer to win->event or NULL if there is no event)*/ +RGFW_Event* RGFW_window_checkEvent(RGFW_window* win); /*!< check current event (returns a pointer to win->event or NULL if there is no event)*/ - /* - check all the events until there are none left, - this should only be used if you're using callbacks only - */ - RGFWDEF void RGFW_window_checkEvents(RGFW_window* win); +/* + for RGFW_window_eventWait and RGFW_window_checkEvents + waitMS -> Allows th e function to keep checking for events even after `RGFW_window_checkEvent == NULL` + if waitMS == 0, the loop will not wait for events + if waitMS == a positive integer, the loop will wait that many miliseconds after there are no more events until it returns + if waitMS == a negative integer, the loop will not return until it gets another event +*/ +typedef RGFW_ENUM(i32, RGFW_eventWait) { + RGFW_NEXT = -1, + RGFW_NO_WAIT = 0 +}; + +/* sleep until RGFW gets an event or the timer ends (defined by OS) */ +RGFWDEF void RGFW_window_eventWait(RGFW_window* win, i32 waitMS); + +/* + check all the events until there are none left, + this should only be used if you're using callbacks only +*/ +RGFWDEF void RGFW_window_checkEvents(RGFW_window* win, i32 waitMS); +/* + Tell RGFW_window_eventWait to stop waiting, to be ran from another thread +*/ +RGFWDEF void RGFW_stopCheckEvents(void); - /*! window managment functions*/ - RGFWDEF void RGFW_window_close(RGFW_window* win); /*!< close the window and free leftover data */ +/*! window managment functions*/ +RGFWDEF void RGFW_window_close(RGFW_window* win); /*!< close the window and free leftover data */ - RGFWDEF void RGFW_window_move(RGFW_window* win, - RGFW_vector v/* new pos*/ - ); +/* moves window to a given point */ +RGFWDEF void RGFW_window_move(RGFW_window* win, + RGFW_point v/* new pos*/ +); - #ifndef RGFW_NO_MONITOR +#ifndef RGFW_NO_MONITOR /* move to a specific monitor */ - RGFWDEF void RGFW_window_moveToMonitor(RGFW_window* win, RGFW_monitor m); - #endif - RGFWDEF void RGFW_window_resize(RGFW_window* win, - RGFW_area a/* new size*/ - ); + RGFWDEF void RGFW_window_moveToMonitor(RGFW_window* win, RGFW_monitor m /* monitor */); +#endif - /* set the minimum size a user can shrink a window */ - RGFWDEF void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a); - /* set the minimum size a user can extend a window */ - RGFWDEF void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a); +/* resize window to a current size/area */ +RGFWDEF void RGFW_window_resize(RGFW_window* win, + RGFW_area a/* new size*/ +); - RGFWDEF void RGFW_window_maximize(RGFW_window* win); /* maximize the window size */ - RGFWDEF void RGFW_window_minimize(RGFW_window* win); /* minimize the window (in taskbar (per OS))*/ - RGFWDEF void RGFW_window_restore(RGFW_window* win); /* restore the window from minimized (per OS)*/ +/* set the minimum size a user can shrink a window to a given size/area */ +RGFWDEF void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a); +/* set the minimum size a user can extend a window to a given size/area */ +RGFWDEF void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a); - RGFWDEF void RGFW_window_setBorder(RGFW_window* win, b8 border); /* if the window should have a border or not (borderless) based on bool value of `border` */ - - RGFWDEF void RGFW_window_setDND(RGFW_window* win, b8 allow); /* turn on / off dnd (RGFW_ALLOW_DND stil must be passed to the window)*/ +RGFWDEF void RGFW_window_maximize(RGFW_window* win); /* maximize the window size */ +RGFWDEF void RGFW_window_minimize(RGFW_window* win); /* minimize the window (in taskbar (per OS))*/ +RGFWDEF void RGFW_window_restore(RGFW_window* win); /* restore the window from minimized (per OS)*/ - #ifndef RGFW_NO_PASSTHROUGH - RGFWDEF void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough); /* turn on / off mouse passthrough */ - #endif +/* if the window should have a border or not (borderless) based on bool value of `border` */ +RGFWDEF void RGFW_window_setBorder(RGFW_window* win, b8 border); - RGFWDEF void RGFW_window_setName(RGFW_window* win, - char* name - ); +/* turn on / off dnd (RGFW_ALLOW_DND stil must be passed to the window)*/ +RGFWDEF void RGFW_window_setDND(RGFW_window* win, b8 allow); - void RGFW_window_setIcon(RGFW_window* win, /*!< source window */ - u8* icon /*!< icon bitmap */, - RGFW_area a /*!< width and height of the bitmap*/, - i32 channels /*!< how many channels the bitmap has (rgb : 3, rgba : 4) */ - ); /*!< image resized by default */ +#ifndef RGFW_NO_PASSTHROUGH + /* turn on / off mouse passthrough */ + RGFWDEF void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough); +#endif - /*!< sets mouse to bitmap (very simular to RGFW_window_setIcon), image NOT resized by default*/ - RGFWDEF void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels); +/* rename window to a given string */ +RGFWDEF void RGFW_window_setName(RGFW_window* win, + char* name +); - /*!< sets the mouse to a standard API cursor (based on RGFW_MOUSE, as seen at the end of the RGFW_HEADER part of this file) */ - RGFWDEF void RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse); +void RGFW_window_setIcon(RGFW_window* win, /*!< source window */ + u8* icon /*!< icon bitmap */, + RGFW_area a /*!< width and height of the bitmap*/, + i32 channels /*!< how many channels the bitmap has (rgb : 3, rgba : 4) */ +); /*!< image resized by default */ - RGFWDEF void RGFW_window_setMouseDefault(RGFW_window* win); /* sets the mouse to1` the default mouse image */ - /* - holds the mouse in place by moving the mouse back each time it moves - you can still use win->event.point to see how much it moved before it was put back in place +/*!< sets mouse to bitmap (very simular to RGFW_window_setIcon), image NOT resized by default*/ +RGFWDEF void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels); - this is useful for a 3D camera - */ - RGFWDEF void RGFW_window_mouseHold(RGFW_window* win, RGFW_area area); - /* undo hold */ - RGFWDEF void RGFW_window_mouseUnhold(RGFW_window* win); +/*!< sets the mouse to a standard API cursor (based on RGFW_MOUSE, as seen at the end of the RGFW_HEADER part of this file) */ +RGFWDEF void RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse); - /* hide the window */ - RGFWDEF void RGFW_window_hide(RGFW_window* win); - /* show the window */ - RGFWDEF void RGFW_window_show(RGFW_window* win); +RGFWDEF void RGFW_window_setMouseDefault(RGFW_window* win); /* sets the mouse to the default mouse icon */ +/* + Locks cursor at the center of the window + win->event.point become raw mouse movement data - /* - makes it so `RGFW_window_shouldClose` returns true - by setting the window event.type to RGFW_quit - */ - RGFWDEF void RGFW_window_setShouldClose(RGFW_window* win); + this is useful for a 3D camera +*/ +RGFWDEF void RGFW_window_mouseHold(RGFW_window* win, RGFW_area area); +/* stop holding the mouse and let it move freely */ +RGFWDEF void RGFW_window_mouseUnhold(RGFW_window* win); - /* where the mouse is on the screen */ - RGFWDEF RGFW_vector RGFW_getGlobalMousePoint(void); +/* hide the window */ +RGFWDEF void RGFW_window_hide(RGFW_window* win); +/* show the window */ +RGFWDEF void RGFW_window_show(RGFW_window* win); - /* where the mouse is on the window */ - RGFWDEF RGFW_vector RGFW_window_getMousePoint(RGFW_window* win); +/* + makes it so `RGFW_window_shouldClose` returns true + by setting the window event.type to RGFW_quit +*/ +RGFWDEF void RGFW_window_setShouldClose(RGFW_window* win); - /* show the mouse or hide the mouse*/ - RGFWDEF void RGFW_window_showMouse(RGFW_window* win, i8 show); - /* move the mouse to a set x, y pos*/ - RGFWDEF void RGFW_window_moveMouse(RGFW_window* win, RGFW_vector v); +/* where the mouse is on the screen */ +RGFWDEF RGFW_point RGFW_getGlobalMousePoint(void); - /* if the window should close (RGFW_close was sent or escape was pressed) */ - RGFWDEF b8 RGFW_window_shouldClose(RGFW_window* win); - /* if window is fullscreen'd */ - RGFWDEF b8 RGFW_window_isFullscreen(RGFW_window* win); - /* if window is hidden */ - RGFWDEF b8 RGFW_window_isHidden(RGFW_window* win); - /* if window is minimized */ - RGFWDEF b8 RGFW_window_isMinimized(RGFW_window* win); - /* if window is maximized */ - RGFWDEF b8 RGFW_window_isMaximized(RGFW_window* win); +/* where the mouse is on the window */ +RGFWDEF RGFW_point RGFW_window_getMousePoint(RGFW_window* win); +/* show the mouse or hide the mouse*/ +RGFWDEF void RGFW_window_showMouse(RGFW_window* win, i8 show); +/* move the mouse to a set x, y pos*/ +RGFWDEF void RGFW_window_moveMouse(RGFW_window* win, RGFW_point v); - #ifndef RGFW_NO_MONITOR - /* - scale the window to the monitor, - this is run by default if the user uses the arg `RGFW_SCALE_TO_MONITOR` during window creation - */ - RGFWDEF void RGFW_window_scaleToMonitor(RGFW_window* win); - /* get the struct of the window's monitor */ - RGFWDEF RGFW_monitor RGFW_window_getMonitor(RGFW_window* win); - #endif +/* if the window should close (RGFW_close was sent or escape was pressed) */ +RGFWDEF b8 RGFW_window_shouldClose(RGFW_window* win); +/* if window is fullscreen'd */ +RGFWDEF b8 RGFW_window_isFullscreen(RGFW_window* win); +/* if window is hidden */ +RGFWDEF b8 RGFW_window_isHidden(RGFW_window* win); +/* if window is minimized */ +RGFWDEF b8 RGFW_window_isMinimized(RGFW_window* win); +/* if window is maximized */ +RGFWDEF b8 RGFW_window_isMaximized(RGFW_window* win); - /*!< make the window the current opengl drawing context */ - RGFWDEF void RGFW_window_makeCurrent(RGFW_window* win); - /*error handling*/ - RGFWDEF b8 RGFW_Error(void); /* returns true if an error has occurred (doesn't print errors itself) */ +#ifndef RGFW_NO_MONITOR +/* +scale the window to the monitor, +this is run by default if the user uses the arg `RGFW_SCALE_TO_MONITOR` during window creation +*/ +RGFWDEF void RGFW_window_scaleToMonitor(RGFW_window* win); +/* get the struct of the window's monitor */ +RGFWDEF RGFW_monitor RGFW_window_getMonitor(RGFW_window* win); +#endif - /*!< if window == NULL, it checks if the key is pressed globally. Otherwise, it checks only if the key is pressed while the window in focus.*/ - RGFWDEF b8 RGFW_isPressed(RGFW_window* win, u8 key); /*!< if key is pressed (key code)*/ +/*!< make the window the current opengl drawing context */ +RGFWDEF void RGFW_window_makeCurrent(RGFW_window* win); - RGFWDEF b8 RGFW_wasPressed(RGFW_window* win, u8 key); /*!< if key was pressed (checks prev keymap only) (key code)*/ +/*error handling*/ +RGFWDEF b8 RGFW_Error(void); /* returns true if an error has occurred (doesn't print errors itself) */ - RGFWDEF b8 RGFW_isHeld(RGFW_window* win, u8 key); /*!< if key is held (key code)*/ - RGFWDEF b8 RGFW_isReleased(RGFW_window* win, u8 key); /*!< if key is released (key code)*/ +/*!< if window == NULL, it checks if the key is pressed globally. Otherwise, it checks only if the key is pressed while the window in focus.*/ +RGFWDEF b8 RGFW_isPressed(RGFW_window* win, u8 key); /*!< if key is pressed (key code)*/ - RGFWDEF b8 RGFW_isClicked(RGFW_window* win, u8 key); +RGFWDEF b8 RGFW_wasPressed(RGFW_window* win, u8 key); /*!< if key was pressed (checks previous state only) (key code)*/ - RGFWDEF b8 RGFW_isMousePressed(RGFW_window* win, u8 button); - RGFWDEF b8 RGFW_isMouseHeld(RGFW_window* win, u8 button); - RGFWDEF b8 RGFW_isMouseReleased(RGFW_window* win, u8 button); - RGFWDEF b8 RGFW_wasMousePressed(RGFW_window* win, u8 button); +RGFWDEF b8 RGFW_isHeld(RGFW_window* win, u8 key); /*!< if key is held (key code)*/ +RGFWDEF b8 RGFW_isReleased(RGFW_window* win, u8 key); /*!< if key is released (key code)*/ -/*! clipboard functions*/ - RGFWDEF char* RGFW_readClipboard(size_t* size); /*!< read clipboard data */ - RGFWDEF void RGFW_clipboardFree(char* str); /* the string returned from RGFW_readClipboard must be freed */ +/* if a key is pressed and then released, pretty much the same as RGFW_isReleased */ +RGFWDEF b8 RGFW_isClicked(RGFW_window* win, u8 key /* key code*/); - RGFWDEF void RGFW_writeClipboard(const char* text, u32 textLen); /*!< write text to the clipboard */ +/* if a mouse button is pressed */ +RGFWDEF b8 RGFW_isMousePressed(RGFW_window* win, u8 button /* mouse button code */ ); +/* if a mouse button is held */ +RGFWDEF b8 RGFW_isMouseHeld(RGFW_window* win, u8 button /* mouse button code */ ); +/* if a mouse button was released */ +RGFWDEF b8 RGFW_isMouseReleased(RGFW_window* win, u8 button /* mouse button code */ ); +/* if a mouse button was pressed (checks previous state only) */ +RGFWDEF b8 RGFW_wasMousePressed(RGFW_window* win, u8 button /* mouse button code */ ); - /* - - - Event callbacks, - these are completely optional, you can use the normal - RGFW_checkEvent() method if you prefer that +/*! clipboard functions*/ +RGFWDEF char* RGFW_readClipboard(size_t* size); /*!< read clipboard data */ +RGFWDEF void RGFW_clipboardFree(char* str); /* the string returned from RGFW_readClipboard must be freed */ - */ +RGFWDEF void RGFW_writeClipboard(const char* text, u32 textLen); /*!< write text to the clipboard */ - /* RGFW_windowMoved, the window and its new rect value */ - typedef void (* RGFW_windowmovefunc)(RGFW_window* win, RGFW_rect r); - /* RGFW_windowResized, the window and its new rect value */ - typedef void (* RGFW_windowresizefunc)(RGFW_window* win, RGFW_rect r); - /* RGFW_quit, the window that was closed */ - typedef void (* RGFW_windowquitfunc)(RGFW_window* win); - /* RGFW_focusIn / RGFW_focusOut, the window who's focus has changed and if its inFocus */ - typedef void (* RGFW_focusfunc)(RGFW_window* win, b8 inFocus); - /* RGFW_mouseEnter / RGFW_mouseLeave, the window that changed, the point of the mouse (enter only) and if the mouse has entered */ - typedef void (* RGFW_mouseNotifyfunc)(RGFW_window* win, RGFW_vector point, b8 status); - /* RGFW_mousePosChanged, the window that the move happened on and the new point of the mouse */ - typedef void (* RGFW_mouseposfunc)(RGFW_window* win, RGFW_vector point); - /* RGFW_dnd_init, the window, the point of the drop on the windows */ - typedef void (* RGFW_dndInitfunc)(RGFW_window* win, RGFW_vector point); - /* RGFW_windowRefresh, the window that needs to be refreshed */ - typedef void (* RGFW_windowrefreshfunc)(RGFW_window* win); - /* RGFW_keyPressed / RGFW_keyReleased, the window that got the event, the keycode, the string version, the state of mod keys, if it was a press (else it's a release) */ - typedef void (* RGFW_keyfunc)(RGFW_window* win, u32 keycode, char keyName[16], u8 lockState, b8 pressed); - /* RGFW_mouseButtonPressed / RGFW_mouseButtonReleased, the window that got the event, the button that was pressed, the scroll value, if it was a press (else it's a release) */ - typedef void (* RGFW_mousebuttonfunc)(RGFW_window* win, u8 button, double scroll, b8 pressed); - /* RGFW_jsButtonPressed / RGFW_jsButtonReleased, the window that got the event, the button that was pressed, the scroll value, if it was a press (else it's a release) */ - typedef void (* RGFW_jsButtonfunc)(RGFW_window* win, u16 joystick, u8 button, b8 pressed); - /* RGFW_jsAxisMove, the window that got the event, the joystick in question, the axis values and the amount of axises */ - typedef void (* RGFW_jsAxisfunc)(RGFW_window* win, u16 joystick, RGFW_vector axis[2], u8 axisesCount); +/* - /* RGFW_dnd, the window that had the drop, the drop data and the amount files dropped */ - #ifdef RGFW_ALLOC_DROPFILES + + Event callbacks, + these are completely optional, you can use the normal + RGFW_checkEvent() method if you prefer that + +*/ + +/* RGFW_windowMoved, the window and its new rect value */ +typedef void (* RGFW_windowmovefunc)(RGFW_window* win, RGFW_rect r); +/* RGFW_windowResized, the window and its new rect value */ +typedef void (* RGFW_windowresizefunc)(RGFW_window* win, RGFW_rect r); +/* RGFW_quit, the window that was closed */ +typedef void (* RGFW_windowquitfunc)(RGFW_window* win); +/* RGFW_focusIn / RGFW_focusOut, the window who's focus has changed and if its inFocus */ +typedef void (* RGFW_focusfunc)(RGFW_window* win, b8 inFocus); +/* RGFW_mouseEnter / RGFW_mouseLeave, the window that changed, the point of the mouse (enter only) and if the mouse has entered */ +typedef void (* RGFW_mouseNotifyfunc)(RGFW_window* win, RGFW_point point, b8 status); +/* RGFW_mousePosChanged, the window that the move happened on and the new point of the mouse */ +typedef void (* RGFW_mouseposfunc)(RGFW_window* win, RGFW_point point); +/* RGFW_dnd_init, the window, the point of the drop on the windows */ +typedef void (* RGFW_dndInitfunc)(RGFW_window* win, RGFW_point point); +/* RGFW_windowRefresh, the window that needs to be refreshed */ +typedef void (* RGFW_windowrefreshfunc)(RGFW_window* win); +/* RGFW_keyPressed / RGFW_keyReleased, the window that got the event, the keycode, the string version, the state of mod keys, if it was a press (else it's a release) */ +typedef void (* RGFW_keyfunc)(RGFW_window* win, u32 keycode, char keyName[16], u8 lockState, b8 pressed); +/* RGFW_mouseButtonPressed / RGFW_mouseButtonReleased, the window that got the event, the button that was pressed, the scroll value, if it was a press (else it's a release) */ +typedef void (* RGFW_mousebuttonfunc)(RGFW_window* win, u8 button, double scroll, b8 pressed); +/* RGFW_jsButtonPressed / RGFW_jsButtonReleased, the window that got the event, the button that was pressed, the scroll value, if it was a press (else it's a release) */ +typedef void (* RGFW_jsButtonfunc)(RGFW_window* win, u16 joystick, u8 button, b8 pressed); +/* RGFW_jsAxisMove, the window that got the event, the joystick in question, the axis values and the amount of axises */ +typedef void (* RGFW_jsAxisfunc)(RGFW_window* win, u16 joystick, RGFW_point axis[2], u8 axisesCount); + +/* RGFW_dnd, the window that had the drop, the drop data and the amount files dropped */ +#ifdef RGFW_ALLOC_DROPFILES typedef void (* RGFW_dndfunc)(RGFW_window* win, char** droppedFiles, u32 droppedFilesCount); - #else +#else typedef void (* RGFW_dndfunc)(RGFW_window* win, char droppedFiles[RGFW_MAX_DROPS][RGFW_MAX_PATH], u32 droppedFilesCount); - #endif - - RGFWDEF void RGFW_setWindowMoveCallback(RGFW_windowmovefunc func); - RGFWDEF void RGFW_setWindowResizeCallback(RGFW_windowresizefunc func); - RGFWDEF void RGFW_setWindowQuitCallback(RGFW_windowquitfunc func); - RGFWDEF void RGFW_setMousePosCallback(RGFW_mouseposfunc func); - RGFWDEF void RGFW_setWindowRefreshCallback(RGFW_windowrefreshfunc func); - RGFWDEF void RGFW_setFocusCallback(RGFW_focusfunc func); - RGFWDEF void RGFW_setMouseNotifyCallBack(RGFW_mouseNotifyfunc func); - RGFWDEF void RGFW_setDndCallback(RGFW_dndfunc func); - RGFWDEF void RGFW_setDndInitCallback(RGFW_dndInitfunc func); - RGFWDEF void RGFW_setKeyCallback(RGFW_keyfunc func); - RGFWDEF void RGFW_setMouseButtonCallback(RGFW_mousebuttonfunc func); - RGFWDEF void RGFW_setjsButtonCallback(RGFW_jsButtonfunc func); - RGFWDEF void RGFW_setjsAxisCallback(RGFW_jsAxisfunc func); +#endif +/* set callback for a window move event */ +RGFWDEF void RGFW_setWindowMoveCallback(RGFW_windowmovefunc func); +/* set callbacksfor a window resize event */ +RGFWDEF void RGFW_setWindowResizeCallback(RGFW_windowresizefunc func); +/* set callbacksfor a window quit event */ +RGFWDEF void RGFW_setWindowQuitCallback(RGFW_windowquitfunc func); +/* set callbacksfor a mouse move event */ +RGFWDEF void RGFW_setMousePosCallback(RGFW_mouseposfunc func); +/* set callbacksfor a window refresh event */ +RGFWDEF void RGFW_setWindowRefreshCallback(RGFW_windowrefreshfunc func); +/* set callbacksfor a window focus change event */ +RGFWDEF void RGFW_setFocusCallback(RGFW_focusfunc func); +/* set callbacksfor a mouse notify event */ +RGFWDEF void RGFW_setMouseNotifyCallBack(RGFW_mouseNotifyfunc func); +/* set callbacksfor a drop event event */ +RGFWDEF void RGFW_setDndCallback(RGFW_dndfunc func); +/* set callbacksfor a start of a drop event */ +RGFWDEF void RGFW_setDndInitCallback(RGFW_dndInitfunc func); +/* set callbacksfor a key (press / release ) event */ +RGFWDEF void RGFW_setKeyCallback(RGFW_keyfunc func); +/* set callbacksfor a mouse button (press / release ) event */ +RGFWDEF void RGFW_setMouseButtonCallback(RGFW_mousebuttonfunc func); +/* set callbacksfor a controller button (press / release ) event */ +RGFWDEF void RGFW_setjsButtonCallback(RGFW_jsButtonfunc func); +/* set callbacksfor a joystick axis mov event */ +RGFWDEF void RGFW_setjsAxisCallback(RGFW_jsAxisfunc func); #ifndef RGFW_NO_THREADS @@ -781,10 +839,10 @@ typedef struct { i32 x, y; } RGFW_vector; which is a good idea generally */ - #if defined(__unix__) || defined(__APPLE__) - typedef void* (* RGFW_threadFunc_ptr)(void*); + #if defined(__unix__) || defined(__APPLE__) || defined(RGFW_WEBASM) + typedef void* (* RGFW_threadFunc_ptr)(void*); #else - typedef DWORD (__stdcall *RGFW_threadFunc_ptr) (LPVOID lpThreadParameter); + typedef DWORD (__stdcall *RGFW_threadFunc_ptr) (LPVOID lpThreadParameter); #endif RGFWDEF RGFW_thread RGFW_createThread(RGFW_threadFunc_ptr ptr, void* args); /*!< create a thread*/ @@ -793,18 +851,25 @@ typedef struct { i32 x, y; } RGFW_vector; RGFWDEF void RGFW_setThreadPriority(RGFW_thread thread, u8 priority); /*!< sets the priority priority */ #endif - /*! gamepad/joystick functions (linux-only currently) */ +/*! gamepad/joystick functions (linux-only currently) */ - /*! joystick count starts at 0*/ - /*!< register joystick to window based on a number (the number is based on when it was connected eg. /dev/js0)*/ - RGFWDEF u16 RGFW_registerJoystick(RGFW_window* win, i32 jsNumber); - RGFWDEF u16 RGFW_registerJoystickF(RGFW_window* win, char* file); +/*! joystick count starts at 0*/ +/*!< register joystick to window based on a number (the number is based on when it was connected eg. /dev/js0)*/ +RGFWDEF u16 RGFW_registerJoystick(RGFW_window* win, i32 jsNumber); +RGFWDEF u16 RGFW_registerJoystickF(RGFW_window* win, char* file); - RGFWDEF u32 RGFW_isPressedJS(RGFW_window* win, u16 controller, u8 button); +RGFWDEF u32 RGFW_isPressedJS(RGFW_window* win, u16 controller, u8 button); - /*! native opengl functions */ +/* supports openGL, directX, OSMesa, EGL and software rendering */ +RGFWDEF void RGFW_window_swapBuffers(RGFW_window* win); /* swap the rendering buffer */ +RGFWDEF void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval); + +RGFWDEF void RGFW_window_setGPURender(RGFW_window* win, i8 set); +RGFWDEF void RGFW_window_setCPURender(RGFW_window* win, i8 set); + +/*! native API functions */ #ifdef RGFW_OPENGL -/*! Get max OpenGL version */ + /*! Get max OpenGL version */ RGFWDEF u8* RGFW_getMaxGLVersion(void); /* OpenGL init hints */ RGFWDEF void RGFW_setGLStencil(i32 stencil); /* set stencil buffer bit size (8 by default) */ @@ -816,14 +881,7 @@ typedef struct { i32 x, y; } RGFW_vector; RGFWDEF void RGFW_setGLVersion(i32 major, i32 minor); RGFWDEF void* RGFW_getProcAddress(const char* procname); /* get native opengl proc address */ RGFWDEF void RGFW_window_makeCurrent_OpenGL(RGFW_window* win); /* to be called by RGFW_window_makeCurrent */ -#endif - /* supports openGL, directX, OSMesa, EGL and software rendering */ - RGFWDEF void RGFW_window_swapBuffers(RGFW_window* win); /* swap the rendering buffer */ - RGFWDEF void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval); - - RGFWDEF void RGFW_window_setGPURender(RGFW_window* win, i8 set); - RGFWDEF void RGFW_window_setCPURender(RGFW_window* win, i8 set); -#ifdef RGFW_DIRECTX +#elif defined(RGFW_DIRECTX) typedef struct { IDXGIFactory* pFactory; IDXGIAdapter* pAdapter; @@ -838,206 +896,211 @@ typedef struct { i32 x, y; } RGFW_vector; RGFWDEF RGFW_directXinfo* RGFW_getDirectXInfo(void); #endif - /*! Supporting functions */ - RGFWDEF void RGFW_window_checkFPS(RGFW_window* win); /*!< updates fps / sets fps to cap (ran by RGFW_window_checkEvent)*/ - RGFWDEF u64 RGFW_getTime(void); /* get time in seconds */ - RGFWDEF u64 RGFW_getTimeNS(void); /* get time in nanoseconds */ - RGFWDEF void RGFW_sleep(u64 microsecond); /* sleep for a set time */ - - typedef RGFW_ENUM(u8, RGFW_Key) { - RGFW_KEY_NULL = 0, - RGFW_Escape, - RGFW_F1, - RGFW_F2, - RGFW_F3, - RGFW_F4, - RGFW_F5, - RGFW_F6, - RGFW_F7, - RGFW_F8, - RGFW_F9, - RGFW_F10, - RGFW_F11, - RGFW_F12, - - RGFW_Backtick, - - RGFW_0, - RGFW_1, - RGFW_2, - RGFW_3, - RGFW_4, - RGFW_5, - RGFW_6, - RGFW_7, - RGFW_8, - RGFW_9, - - RGFW_Minus, - RGFW_Equals, - RGFW_BackSpace, - RGFW_Tab, - RGFW_CapsLock, - RGFW_ShiftL, - RGFW_ControlL, - RGFW_AltL, - RGFW_SuperL, - RGFW_ShiftR, - RGFW_ControlR, - RGFW_AltR, - RGFW_SuperR, - RGFW_Space, - - RGFW_a, - RGFW_b, - RGFW_c, - RGFW_d, - RGFW_e, - RGFW_f, - RGFW_g, - RGFW_h, - RGFW_i, - RGFW_j, - RGFW_k, - RGFW_l, - RGFW_m, - RGFW_n, - RGFW_o, - RGFW_p, - RGFW_q, - RGFW_r, - RGFW_s, - RGFW_t, - RGFW_u, - RGFW_v, - RGFW_w, - RGFW_x, - RGFW_y, - RGFW_z, - - RGFW_Period, - RGFW_Comma, - RGFW_Slash, - RGFW_Bracket, - RGFW_CloseBracket, - RGFW_Semicolon, - RGFW_Return, - RGFW_Quote, - RGFW_BackSlash, - - RGFW_Up, - RGFW_Down, - RGFW_Left, - RGFW_Right, - - RGFW_Delete, - RGFW_Insert, - RGFW_End, - RGFW_Home, - RGFW_PageUp, - RGFW_PageDown, - - RGFW_Numlock, - RGFW_KP_Slash, - RGFW_Multiply, - RGFW_KP_Minus, - RGFW_KP_1, - RGFW_KP_2, - RGFW_KP_3, - RGFW_KP_4, - RGFW_KP_5, - RGFW_KP_6, - RGFW_KP_7, - RGFW_KP_8, - RGFW_KP_9, - RGFW_KP_0, - RGFW_KP_Period, - RGFW_KP_Return, - - final_key, - }; +/*! Supporting functions */ +RGFWDEF void RGFW_window_checkFPS(RGFW_window* win); /*!< updates fps / sets fps to cap (ran by RGFW_window_checkEvent)*/ +RGFWDEF u64 RGFW_getTime(void); /* get time in seconds */ +RGFWDEF u64 RGFW_getTimeNS(void); /* get time in nanoseconds */ +RGFWDEF void RGFW_sleep(u64 milisecond); /* sleep for a set time */ - typedef RGFW_ENUM(u8, RGFW_mouseIcons) { - RGFW_MOUSE_NORMAL = 0, - RGFW_MOUSE_ARROW, - RGFW_MOUSE_IBEAM, - RGFW_MOUSE_CROSSHAIR, - RGFW_MOUSE_POINTING_HAND, - RGFW_MOUSE_RESIZE_EW, - RGFW_MOUSE_RESIZE_NS, - RGFW_MOUSE_RESIZE_NWSE, - RGFW_MOUSE_RESIZE_NESW, - RGFW_MOUSE_RESIZE_ALL, - RGFW_MOUSE_NOT_ALLOWED, - }; +/* + key codes and mouse icon enums +*/ -#endif /* RGFW_HEADER */ +typedef RGFW_ENUM(u8, RGFW_Key) { + RGFW_KEY_NULL = 0, + RGFW_Escape, + RGFW_F1, + RGFW_F2, + RGFW_F3, + RGFW_F4, + RGFW_F5, + RGFW_F6, + RGFW_F7, + RGFW_F8, + RGFW_F9, + RGFW_F10, + RGFW_F11, + RGFW_F12, + + RGFW_Backtick, + + RGFW_0, + RGFW_1, + RGFW_2, + RGFW_3, + RGFW_4, + RGFW_5, + RGFW_6, + RGFW_7, + RGFW_8, + RGFW_9, + + RGFW_Minus, + RGFW_Equals, + RGFW_BackSpace, + RGFW_Tab, + RGFW_CapsLock, + RGFW_ShiftL, + RGFW_ControlL, + RGFW_AltL, + RGFW_SuperL, + RGFW_ShiftR, + RGFW_ControlR, + RGFW_AltR, + RGFW_SuperR, + RGFW_Space, + + RGFW_a, + RGFW_b, + RGFW_c, + RGFW_d, + RGFW_e, + RGFW_f, + RGFW_g, + RGFW_h, + RGFW_i, + RGFW_j, + RGFW_k, + RGFW_l, + RGFW_m, + RGFW_n, + RGFW_o, + RGFW_p, + RGFW_q, + RGFW_r, + RGFW_s, + RGFW_t, + RGFW_u, + RGFW_v, + RGFW_w, + RGFW_x, + RGFW_y, + RGFW_z, + + RGFW_Period, + RGFW_Comma, + RGFW_Slash, + RGFW_Bracket, + RGFW_CloseBracket, + RGFW_Semicolon, + RGFW_Return, + RGFW_Quote, + RGFW_BackSlash, + + RGFW_Up, + RGFW_Down, + RGFW_Left, + RGFW_Right, + + RGFW_Delete, + RGFW_Insert, + RGFW_End, + RGFW_Home, + RGFW_PageUp, + RGFW_PageDown, + + RGFW_Numlock, + RGFW_KP_Slash, + RGFW_Multiply, + RGFW_KP_Minus, + RGFW_KP_1, + RGFW_KP_2, + RGFW_KP_3, + RGFW_KP_4, + RGFW_KP_5, + RGFW_KP_6, + RGFW_KP_7, + RGFW_KP_8, + RGFW_KP_9, + RGFW_KP_0, + RGFW_KP_Period, + RGFW_KP_Return, + + final_key, +}; - /* - Example to get you started : +typedef RGFW_ENUM(u8, RGFW_mouseIcons) { + RGFW_MOUSE_NORMAL = 0, + RGFW_MOUSE_ARROW, + RGFW_MOUSE_IBEAM, + RGFW_MOUSE_CROSSHAIR, + RGFW_MOUSE_POINTING_HAND, + RGFW_MOUSE_RESIZE_EW, + RGFW_MOUSE_RESIZE_NS, + RGFW_MOUSE_RESIZE_NWSE, + RGFW_MOUSE_RESIZE_NESW, + RGFW_MOUSE_RESIZE_ALL, + RGFW_MOUSE_NOT_ALLOWED, +}; - linux : gcc main.c -lX11 -lXcursor -lGL - windows : gcc main.c -lopengl32 -lshell32 -lgdi32 - macos : gcc main.c -framework Foundation -framework AppKit -framework OpenGL -framework CoreVideo +#endif /* RGFW_HEADER */ - #define RGFW_IMPLEMENTATION - #include "RGFW.h" +/* +Example to get you started : - u8 icon[4 * 3 * 3] = {0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF}; +linux : gcc main.c -lX11 -lXcursor -lGL +windows : gcc main.c -lopengl32 -lshell32 -lgdi32 +macos : gcc main.c -framework Foundation -framework AppKit -framework OpenGL -framework CoreVideo - int main() { - RGFW_window* win = RGFW_createWindow("name", RGFW_RECT(500, 500, 500, 500), (u64)0); +#define RGFW_IMPLEMENTATION +#include "RGFW.h" - RGFW_window_setIcon(win, icon, RGFW_AREA(3, 3), 4); +u8 icon[4 * 3 * 3] = {0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF}; - for (;;) { - RGFW_window_checkEvent(win); // NOTE: checking events outside of a while loop may cause input lag - if (win->event.type == RGFW_quit || RGFW_isPressed(win, RGFW_Escape)) - break; +int main() { + RGFW_window* win = RGFW_createWindow("name", RGFW_RECT(500, 500, 500, 500), (u64)0); - RGFW_window_swapBuffers(win); + RGFW_window_setIcon(win, icon, RGFW_AREA(3, 3), 4); - glClearColor(0xFF, 0XFF, 0xFF, 0xFF); - glClear(GL_COLOR_BUFFER_BIT); - } + for (;;) { + RGFW_window_checkEvent(win); // NOTE: checking events outside of a while loop may cause input lag + if (win->event.type == RGFW_quit || RGFW_isPressed(win, RGFW_Escape)) + break; - RGFW_window_close(win); + RGFW_window_swapBuffers(win); + + glClearColor(0xFF, 0XFF, 0xFF, 0xFF); + glClear(GL_COLOR_BUFFER_BIT); } - compiling : + RGFW_window_close(win); +} + + compiling : - if you wish to compile the library all you have to do is create a new file with this in it + if you wish to compile the library all you have to do is create a new file with this in it - rgfw.c - #define RGFW_IMPLEMENTATION - #include "RGFW.h" + rgfw.c + #define RGFW_IMPLEMENTATION + #include "RGFW.h" - then you can use gcc (or whatever compile you wish to use) to compile the library into object file + then you can use gcc (or whatever compile you wish to use) to compile the library into object file - ex. gcc -c RGFW.c -fPIC + ex. gcc -c RGFW.c -fPIC - after you compile the library into an object file, you can also turn the object file into an static or shared library + after you compile the library into an object file, you can also turn the object file into an static or shared library - (commands ar and gcc can be replaced with whatever equivalent your system uses) - static : ar rcs RGFW.a RGFW.o - shared : - windows: - gcc -shared RGFW.o -lopengl32 -lshell32 -lgdi32 -o RGFW.dll - linux: - gcc -shared RGFW.o -lX11 -lXcursor -lGL -o RGFW.so - macos: - gcc -shared RGFW.o -framework Foundation -framework AppKit -framework OpenGL -framework CoreVideo - */ + (commands ar and gcc can be replaced with whatever equivalent your system uses) + static : ar rcs RGFW.a RGFW.o + shared : + windows: + gcc -shared RGFW.o -lopengl32 -lshell32 -lgdi32 -o RGFW.dll + linux: + gcc -shared RGFW.o -lX11 -lXcursor -lGL -o RGFW.so + macos: + gcc -shared RGFW.o -framework Foundation -framework AppKit -framework OpenGL -framework CoreVideo +*/ #ifdef RGFW_X11 -#define RGFW_OS_BASED_VALUE(l, w, m) l -#endif -#ifdef RGFW_WINDOWS -#define RGFW_OS_BASED_VALUE(l, w, m) w -#endif -#ifdef RGFW_MACOS -#define RGFW_OS_BASED_VALUE(l, w, m) m + #define RGFW_OS_BASED_VALUE(l, w, m, a) l +#elif defined(RGFW_WINDOWS) + #define RGFW_OS_BASED_VALUE(l, w, m, a) w +#elif defined(RGFW_MACOS) + #define RGFW_OS_BASED_VALUE(l, w, m, a) m +#elif defined(RGFW_WEBASM) + #define RGFW_OS_BASED_VALUE(l, w, m, a) a #endif + #ifdef RGFW_IMPLEMENTATION #include @@ -1050,217 +1113,233 @@ RGFW_IMPLEMENTATION starts with generic RGFW defines This is the start of keycode data -Why not use macros instead of the numbers itself? -Windows -> Not all virtual keys are macros (VK_0 - VK_1, VK_a - VK_z) -Linux -> Only symcodes are values, (XK_0 - XK_1, XK_a - XK_z) are larger than 0xFF00, I can't find any way to work with them without making the array an unreasonable size -MacOS -> windows and linux already don't have keycodes as macros, so there's no point + Why not use macros instead of the numbers itself? + Windows -> Not all virtual keys are macros (VK_0 - VK_1, VK_a - VK_z) + Linux -> Only symcodes are values, (XK_0 - XK_1, XK_a - XK_z) are larger than 0xFF00, I can't find any way to work with them without making the array an unreasonable size + MacOS -> windows and linux already don't have keycodes as macros, so there's no point */ - u8 RGFW_keycodes[] = { - [RGFW_OS_BASED_VALUE(49, 192, 50)] = RGFW_Backtick, - - [RGFW_OS_BASED_VALUE(19, 0x30, 29)] = RGFW_0, - [RGFW_OS_BASED_VALUE(10, 0x31, 18)] = RGFW_1, - [RGFW_OS_BASED_VALUE(11, 0x32, 19)] = RGFW_2, - [RGFW_OS_BASED_VALUE(12, 0x33, 20)] = RGFW_3, - [RGFW_OS_BASED_VALUE(13, 0x34, 21)] = RGFW_4, - [RGFW_OS_BASED_VALUE(14, 0x35, 23)] = RGFW_5, - [RGFW_OS_BASED_VALUE(15, 0x36, 22)] = RGFW_6, - [RGFW_OS_BASED_VALUE(16, 0x37, 26)] = RGFW_7, - [RGFW_OS_BASED_VALUE(17, 0x38, 28)] = RGFW_8, - [RGFW_OS_BASED_VALUE(18, 0x39, 25)] = RGFW_9, - - [RGFW_OS_BASED_VALUE(65, 0x20, 49)] = RGFW_Space, - - [RGFW_OS_BASED_VALUE(38, 0x41, 0)] = RGFW_a, - [RGFW_OS_BASED_VALUE(56, 0x42, 11)] = RGFW_b, - [RGFW_OS_BASED_VALUE(54, 0x43, 8)] = RGFW_c, - [RGFW_OS_BASED_VALUE(40, 0x44, 2)] = RGFW_d, - [RGFW_OS_BASED_VALUE(26, 0x45, 14)] = RGFW_e, - [RGFW_OS_BASED_VALUE(41, 0x46, 3)] = RGFW_f, - [RGFW_OS_BASED_VALUE(42, 0x47, 5)] = RGFW_g, - [RGFW_OS_BASED_VALUE(43, 0x48, 4)] = RGFW_h, - [RGFW_OS_BASED_VALUE(31, 0x49, 34)] = RGFW_i, - [RGFW_OS_BASED_VALUE(44, 0x4A, 38)] = RGFW_j, - [RGFW_OS_BASED_VALUE(45, 0x4B, 40)] = RGFW_k, - [RGFW_OS_BASED_VALUE(46, 0x4C, 37)] = RGFW_l, - [RGFW_OS_BASED_VALUE(58, 0x4D, 46)] = RGFW_m, - [RGFW_OS_BASED_VALUE(57, 0x4E, 45)] = RGFW_n, - [RGFW_OS_BASED_VALUE(32, 0x4F, 31)] = RGFW_o, - [RGFW_OS_BASED_VALUE(33, 0x50, 35)] = RGFW_p, - [RGFW_OS_BASED_VALUE(24, 0x51, 12)] = RGFW_q, - [RGFW_OS_BASED_VALUE(27, 0x52, 15)] = RGFW_r, - [RGFW_OS_BASED_VALUE(39, 0x53, 1)] = RGFW_s, - [RGFW_OS_BASED_VALUE(28, 0x54, 17)] = RGFW_t, - [RGFW_OS_BASED_VALUE(30, 0x55, 32)] = RGFW_u, - [RGFW_OS_BASED_VALUE(55, 0x56, 9)] = RGFW_v, - [RGFW_OS_BASED_VALUE(25, 0x57, 13)] = RGFW_w, - [RGFW_OS_BASED_VALUE(53, 0x58, 7)] = RGFW_x, - [RGFW_OS_BASED_VALUE(29, 0x59, 16)] = RGFW_y, - [RGFW_OS_BASED_VALUE(52, 0x5A, 6)] = RGFW_z, - - [RGFW_OS_BASED_VALUE(60, 190, 47)] = RGFW_Period, - [RGFW_OS_BASED_VALUE(59, 188, 43)] = RGFW_Comma, - [RGFW_OS_BASED_VALUE(61, 191, 44)] = RGFW_Slash, - [RGFW_OS_BASED_VALUE(34, 219, 33)] = RGFW_Bracket, - [RGFW_OS_BASED_VALUE(35, 221, 30)] = RGFW_CloseBracket, - [RGFW_OS_BASED_VALUE(47, 186, 41)] = RGFW_Semicolon, - [RGFW_OS_BASED_VALUE(48, 222, 39)] = RGFW_Quote, - [RGFW_OS_BASED_VALUE(51, 322, 42)] = RGFW_BackSlash, - - [RGFW_OS_BASED_VALUE(36, 0x0D, 36)] = RGFW_Return, - [RGFW_OS_BASED_VALUE(119, 0x2E, 118)] = RGFW_Delete, - [RGFW_OS_BASED_VALUE(77, 0x90, 72)] = RGFW_Numlock, - [RGFW_OS_BASED_VALUE(106, 0x6F, 82)] = RGFW_KP_Slash, - [RGFW_OS_BASED_VALUE(63, 0x6A, 76)] = RGFW_Multiply, - [RGFW_OS_BASED_VALUE(82, 0x6D, 67)] = RGFW_KP_Minus, - [RGFW_OS_BASED_VALUE(87, 0x61, 84)] = RGFW_KP_1, - [RGFW_OS_BASED_VALUE(88, 0x62, 85)] = RGFW_KP_2, - [RGFW_OS_BASED_VALUE(89, 0x63, 86)] = RGFW_KP_3, - [RGFW_OS_BASED_VALUE(83, 0x64, 87)] = RGFW_KP_4, - [RGFW_OS_BASED_VALUE(84, 0x65, 88)] = RGFW_KP_5, - [RGFW_OS_BASED_VALUE(85, 0x66, 89)] = RGFW_KP_6, - [RGFW_OS_BASED_VALUE(79, 0x67, 90)] = RGFW_KP_7, - [RGFW_OS_BASED_VALUE(80, 0x68, 92)] = RGFW_KP_8, - [RGFW_OS_BASED_VALUE(81, 0x69, 93)] = RGFW_KP_9, - [RGFW_OS_BASED_VALUE(90, 0x60, 83)] = RGFW_KP_0, - [RGFW_OS_BASED_VALUE(91, 0x6E, 65)] = RGFW_KP_Period, - [RGFW_OS_BASED_VALUE(104, 0x92, 77)] = RGFW_KP_Return, - - [RGFW_OS_BASED_VALUE(20, 189, 27)] = RGFW_Minus, - [RGFW_OS_BASED_VALUE(21, 187, 24)] = RGFW_Equals, - [RGFW_OS_BASED_VALUE(22, 8, 51)] = RGFW_BackSpace, - [RGFW_OS_BASED_VALUE(23, 0x09, 48)] = RGFW_Tab, - [RGFW_OS_BASED_VALUE(66, 20, 57)] = RGFW_CapsLock, - [RGFW_OS_BASED_VALUE(50, 0xA0, 56)] = RGFW_ShiftL, - [RGFW_OS_BASED_VALUE(37, 0x11, 59)] = RGFW_ControlL, - [RGFW_OS_BASED_VALUE(64, 164, 58)] = RGFW_AltL, - [RGFW_OS_BASED_VALUE(133, 0x5B, 55)] = RGFW_SuperL, - - #if !defined(RGFW_WINDOWS) && !defined(RGFW_MACOS) - [RGFW_OS_BASED_VALUE(105, 0x11, 59)] = RGFW_ControlR, - [RGFW_OS_BASED_VALUE(135, 0xA4, 55)] = RGFW_SuperR, - #endif +u8 RGFW_keycodes[] = { + [RGFW_OS_BASED_VALUE(49, 192, 50, DOM_VK_BACK_QUOTE)] = RGFW_Backtick, + + [RGFW_OS_BASED_VALUE(19, 0x30, 29, DOM_VK_0)] = RGFW_0, + [RGFW_OS_BASED_VALUE(10, 0x31, 18, DOM_VK_1)] = RGFW_1, + [RGFW_OS_BASED_VALUE(11, 0x32, 19, DOM_VK_2)] = RGFW_2, + [RGFW_OS_BASED_VALUE(12, 0x33, 20, DOM_VK_3)] = RGFW_3, + [RGFW_OS_BASED_VALUE(13, 0x34, 21, DOM_VK_4)] = RGFW_4, + [RGFW_OS_BASED_VALUE(14, 0x35, 23, DOM_VK_5)] = RGFW_5, + [RGFW_OS_BASED_VALUE(15, 0x36, 22, DOM_VK_6)] = RGFW_6, + [RGFW_OS_BASED_VALUE(16, 0x37, 26, DOM_VK_7)] = RGFW_7, + [RGFW_OS_BASED_VALUE(17, 0x38, 28, DOM_VK_8)] = RGFW_8, + [RGFW_OS_BASED_VALUE(18, 0x39, 25, DOM_VK_9)] = RGFW_9, + + [RGFW_OS_BASED_VALUE(65, 0x20, 49, DOM_VK_SPACE)] = RGFW_Space, + + [RGFW_OS_BASED_VALUE(38, 0x41, 0, DOM_VK_A)] = RGFW_a, + [RGFW_OS_BASED_VALUE(56, 0x42, 11, DOM_VK_B)] = RGFW_b, + [RGFW_OS_BASED_VALUE(54, 0x43, 8, DOM_VK_C)] = RGFW_c, + [RGFW_OS_BASED_VALUE(40, 0x44, 2, DOM_VK_D)] = RGFW_d, + [RGFW_OS_BASED_VALUE(26, 0x45, 14, DOM_VK_E)] = RGFW_e, + [RGFW_OS_BASED_VALUE(41, 0x46, 3, DOM_VK_F)] = RGFW_f, + [RGFW_OS_BASED_VALUE(42, 0x47, 5, DOM_VK_G)] = RGFW_g, + [RGFW_OS_BASED_VALUE(43, 0x48, 4, DOM_VK_H)] = RGFW_h, + [RGFW_OS_BASED_VALUE(31, 0x49, 34, DOM_VK_I)] = RGFW_i, + [RGFW_OS_BASED_VALUE(44, 0x4A, 38, DOM_VK_J)] = RGFW_j, + [RGFW_OS_BASED_VALUE(45, 0x4B, 40, DOM_VK_K)] = RGFW_k, + [RGFW_OS_BASED_VALUE(46, 0x4C, 37, DOM_VK_L)] = RGFW_l, + [RGFW_OS_BASED_VALUE(58, 0x4D, 46, DOM_VK_M)] = RGFW_m, + [RGFW_OS_BASED_VALUE(57, 0x4E, 45, DOM_VK_N)] = RGFW_n, + [RGFW_OS_BASED_VALUE(32, 0x4F, 31, DOM_VK_O)] = RGFW_o, + [RGFW_OS_BASED_VALUE(33, 0x50, 35, DOM_VK_P)] = RGFW_p, + [RGFW_OS_BASED_VALUE(24, 0x51, 12, DOM_VK_Q)] = RGFW_q, + [RGFW_OS_BASED_VALUE(27, 0x52, 15, DOM_VK_R)] = RGFW_r, + [RGFW_OS_BASED_VALUE(39, 0x53, 1, DOM_VK_S)] = RGFW_s, + [RGFW_OS_BASED_VALUE(28, 0x54, 17, DOM_VK_T)] = RGFW_t, + [RGFW_OS_BASED_VALUE(30, 0x55, 32, DOM_VK_U)] = RGFW_u, + [RGFW_OS_BASED_VALUE(55, 0x56, 9, DOM_VK_V)] = RGFW_v, + [RGFW_OS_BASED_VALUE(25, 0x57, 13, DOM_VK_W)] = RGFW_w, + [RGFW_OS_BASED_VALUE(53, 0x58, 7, DOM_VK_X)] = RGFW_x, + [RGFW_OS_BASED_VALUE(29, 0x59, 16, DOM_VK_Y)] = RGFW_y, + [RGFW_OS_BASED_VALUE(52, 0x5A, 6, DOM_VK_Z)] = RGFW_z, + + [RGFW_OS_BASED_VALUE(60, 190, 47, DOM_VK_PERIOD)] = RGFW_Period, + [RGFW_OS_BASED_VALUE(59, 188, 43, DOM_VK_COMMA)] = RGFW_Comma, + [RGFW_OS_BASED_VALUE(61, 191, 44, DOM_VK_SLASH)] = RGFW_Slash, + [RGFW_OS_BASED_VALUE(34, 219, 33, DOM_VK_OPEN_BRACKET)] = RGFW_Bracket, + [RGFW_OS_BASED_VALUE(35, 221, 30, DOM_VK_CLOSE_BRACKET)] = RGFW_CloseBracket, + [RGFW_OS_BASED_VALUE(47, 186, 41, DOM_VK_SEMICOLON)] = RGFW_Semicolon, + [RGFW_OS_BASED_VALUE(48, 222, 39, DOM_VK_QUOTE)] = RGFW_Quote, + [RGFW_OS_BASED_VALUE(51, 322, 42, DOM_VK_BACK_SLASH)] = RGFW_BackSlash, + + [RGFW_OS_BASED_VALUE(36, 0x0D, 36, DOM_VK_RETURN)] = RGFW_Return, + [RGFW_OS_BASED_VALUE(119, 0x2E, 118, DOM_VK_DELETE)] = RGFW_Delete, + [RGFW_OS_BASED_VALUE(77, 0x90, 72, DOM_VK_NUM_LOCK)] = RGFW_Numlock, + [RGFW_OS_BASED_VALUE(106, 0x6F, 82, DOM_VK_DIVIDE)] = RGFW_KP_Slash, + [RGFW_OS_BASED_VALUE(63, 0x6A, 76, DOM_VK_MULTIPLY)] = RGFW_Multiply, + [RGFW_OS_BASED_VALUE(82, 0x6D, 67, DOM_VK_SUBTRACT)] = RGFW_KP_Minus, + [RGFW_OS_BASED_VALUE(87, 0x61, 84, DOM_VK_NUMPAD1)] = RGFW_KP_1, + [RGFW_OS_BASED_VALUE(88, 0x62, 85, DOM_VK_NUMPAD2)] = RGFW_KP_2, + [RGFW_OS_BASED_VALUE(89, 0x63, 86, DOM_VK_NUMPAD3)] = RGFW_KP_3, + [RGFW_OS_BASED_VALUE(83, 0x64, 87, DOM_VK_NUMPAD4)] = RGFW_KP_4, + [RGFW_OS_BASED_VALUE(84, 0x65, 88, DOM_VK_NUMPAD5)] = RGFW_KP_5, + [RGFW_OS_BASED_VALUE(85, 0x66, 89, DOM_VK_NUMPAD6)] = RGFW_KP_6, + [RGFW_OS_BASED_VALUE(79, 0x67, 90, DOM_VK_NUMPAD7)] = RGFW_KP_7, + [RGFW_OS_BASED_VALUE(80, 0x68, 92, DOM_VK_NUMPAD8)] = RGFW_KP_8, + [RGFW_OS_BASED_VALUE(81, 0x69, 93, DOM_VK_NUMPAD9)] = RGFW_KP_9, + [RGFW_OS_BASED_VALUE(90, 0x60, 83, DOM_VK_NUMPAD0)] = RGFW_KP_0, + [RGFW_OS_BASED_VALUE(91, 0x6E, 65, DOM_VK_DECIMAL)] = RGFW_KP_Period, + [RGFW_OS_BASED_VALUE(104, 0x92, 77, 0)] = RGFW_KP_Return, + + [RGFW_OS_BASED_VALUE(20, 189, 27, DOM_VK_HYPHEN_MINUS)] = RGFW_Minus, + [RGFW_OS_BASED_VALUE(21, 187, 24, DOM_VK_EQUALS)] = RGFW_Equals, + [RGFW_OS_BASED_VALUE(22, 8, 51, DOM_VK_BACK_SPACE)] = RGFW_BackSpace, + [RGFW_OS_BASED_VALUE(23, 0x09, 48, DOM_VK_TAB)] = RGFW_Tab, + [RGFW_OS_BASED_VALUE(66, 20, 57, DOM_VK_CAPS_LOCK)] = RGFW_CapsLock, + [RGFW_OS_BASED_VALUE(50, 0xA0, 56, DOM_VK_SHIFT)] = RGFW_ShiftL, + [RGFW_OS_BASED_VALUE(37, 0x11, 59, DOM_VK_CONTROL)] = RGFW_ControlL, + [RGFW_OS_BASED_VALUE(64, 164, 58, DOM_VK_ALT)] = RGFW_AltL, + [RGFW_OS_BASED_VALUE(133, 0x5B, 55, DOM_VK_WIN)] = RGFW_SuperL, + + #if !defined(RGFW_WINDOWS) && !defined(RGFW_MACOS) && !defined(RGFW_WEBASM) + [RGFW_OS_BASED_VALUE(105, 0x11, 59, 0)] = RGFW_ControlR, + [RGFW_OS_BASED_VALUE(135, 0xA4, 55, 0)] = RGFW_SuperR, + #endif - #if !defined(RGFW_MACOS) - [RGFW_OS_BASED_VALUE(62, 0x5C, 56)] = RGFW_ShiftR, - [RGFW_OS_BASED_VALUE(108, 165, 58)] = RGFW_AltR, - #endif + #if !defined(RGFW_MACOS) && !defined(RGFW_WEBASM) + [RGFW_OS_BASED_VALUE(62, 0x5C, 56, 0)] = RGFW_ShiftR, + [RGFW_OS_BASED_VALUE(108, 165, 58, 0)] = RGFW_AltR, + #endif - [RGFW_OS_BASED_VALUE(67, 0x70, 127)] = RGFW_F1, - [RGFW_OS_BASED_VALUE(68, 0x71, 121)] = RGFW_F2, - [RGFW_OS_BASED_VALUE(69, 0x72, 100)] = RGFW_F3, - [RGFW_OS_BASED_VALUE(70, 0x73, 119)] = RGFW_F4, - [RGFW_OS_BASED_VALUE(71, 0x74, 97)] = RGFW_F5, - [RGFW_OS_BASED_VALUE(72, 0x75, 98)] = RGFW_F6, - [RGFW_OS_BASED_VALUE(73, 0x76, 99)] = RGFW_F7, - [RGFW_OS_BASED_VALUE(74, 0x77, 101)] = RGFW_F8, - [RGFW_OS_BASED_VALUE(75, 0x78, 102)] = RGFW_F9, - [RGFW_OS_BASED_VALUE(76, 0x79, 110)] = RGFW_F10, - [RGFW_OS_BASED_VALUE(95, 0x7A, 104)] = RGFW_F11, - [RGFW_OS_BASED_VALUE(96, 0x7B, 112)] = RGFW_F12, - [RGFW_OS_BASED_VALUE(111, 0x26, 126)] = RGFW_Up, - [RGFW_OS_BASED_VALUE(116, 0x28, 125)] = RGFW_Down, - [RGFW_OS_BASED_VALUE(113, 0x25, 123)] = RGFW_Left, - [RGFW_OS_BASED_VALUE(114, 0x27, 124)] = RGFW_Right, - [RGFW_OS_BASED_VALUE(118, 0x2D, 115)] = RGFW_Insert, - [RGFW_OS_BASED_VALUE(115, 0x23, 120)] = RGFW_End, - [RGFW_OS_BASED_VALUE(112, 336, 117)] = RGFW_PageUp, - [RGFW_OS_BASED_VALUE(117, 325, 122)] = RGFW_PageDown, - [RGFW_OS_BASED_VALUE(9, 0x1B, 53)] = RGFW_Escape, - [RGFW_OS_BASED_VALUE(110, 0x24, 116)] = RGFW_Home, - }; + [RGFW_OS_BASED_VALUE(67, 0x70, 127, DOM_VK_F1)] = RGFW_F1, + [RGFW_OS_BASED_VALUE(68, 0x71, 121, DOM_VK_F2)] = RGFW_F2, + [RGFW_OS_BASED_VALUE(69, 0x72, 100, DOM_VK_F3)] = RGFW_F3, + [RGFW_OS_BASED_VALUE(70, 0x73, 119, DOM_VK_F4)] = RGFW_F4, + [RGFW_OS_BASED_VALUE(71, 0x74, 97, DOM_VK_F5)] = RGFW_F5, + [RGFW_OS_BASED_VALUE(72, 0x75, 98, DOM_VK_F6)] = RGFW_F6, + [RGFW_OS_BASED_VALUE(73, 0x76, 99, DOM_VK_F7)] = RGFW_F7, + [RGFW_OS_BASED_VALUE(74, 0x77, 101, DOM_VK_F8)] = RGFW_F8, + [RGFW_OS_BASED_VALUE(75, 0x78, 102, DOM_VK_F9)] = RGFW_F9, + [RGFW_OS_BASED_VALUE(76, 0x79, 110, DOM_VK_F10)] = RGFW_F10, + [RGFW_OS_BASED_VALUE(95, 0x7A, 104, DOM_VK_F11)] = RGFW_F11, + [RGFW_OS_BASED_VALUE(96, 0x7B, 112, DOM_VK_F12)] = RGFW_F12, + [RGFW_OS_BASED_VALUE(111, 0x26, 126, DOM_VK_UP)] = RGFW_Up, + [RGFW_OS_BASED_VALUE(116, 0x28, 125, DOM_VK_DOWN)] = RGFW_Down, + [RGFW_OS_BASED_VALUE(113, 0x25, 123, DOM_VK_LEFT)] = RGFW_Left, + [RGFW_OS_BASED_VALUE(114, 0x27, 124, DOM_VK_RIGHT)] = RGFW_Right, + [RGFW_OS_BASED_VALUE(118, 0x2D, 115, DOM_VK_INSERT)] = RGFW_Insert, + [RGFW_OS_BASED_VALUE(115, 0x23, 120, DOM_VK_END)] = RGFW_End, + [RGFW_OS_BASED_VALUE(112, 336, 117, DOM_VK_PAGE_UP)] = RGFW_PageUp, + [RGFW_OS_BASED_VALUE(117, 325, 122, DOM_VK_PAGE_DOWN)] = RGFW_PageDown, + [RGFW_OS_BASED_VALUE(9, 0x1B, 53, DOM_VK_ESCAPE)] = RGFW_Escape, + [RGFW_OS_BASED_VALUE(110, 0x24, 116, DOM_VK_HOME)] = RGFW_Home, +}; - typedef struct { - b8 current : 1; - b8 prev : 1; - } RGFW_keyState; +typedef struct { + b8 current : 1; + b8 prev : 1; +} RGFW_keyState; - RGFW_keyState RGFW_keyboard[final_key] = { {0, 0} }; - - RGFWDEF u32 RGFW_apiKeyCodeToRGFW(u32 keycode); +RGFW_keyState RGFW_keyboard[final_key] = { {0, 0} }; - u32 RGFW_apiKeyCodeToRGFW(u32 keycode) { - if (keycode > sizeof(RGFW_keycodes) / sizeof(u8)) - return 0; - - return RGFW_keycodes[keycode]; - } +RGFWDEF u32 RGFW_apiKeyCodeToRGFW(u32 keycode); - RGFWDEF void RGFW_resetKey(void); - void RGFW_resetKey(void) { - size_t len = final_key; - - size_t i; - for (i = 0; i < len; i++) - RGFW_keyboard[i].prev = 0; - } +u32 RGFW_apiKeyCodeToRGFW(u32 keycode) { + /* make sure the key isn't out of bounds */ + if (keycode > sizeof(RGFW_keycodes) / sizeof(u8)) + return 0; + + return RGFW_keycodes[keycode]; +} + +RGFWDEF void RGFW_resetKey(void); +void RGFW_resetKey(void) { + size_t len = final_key; /* last_key == length */ + + size_t i; /* reset each previous state */ + for (i = 0; i < len; i++) + RGFW_keyboard[i].prev = 0; +} /* this is the end of keycode data */ +/* joystick data */ +u8 RGFW_jsPressed[4][16]; /* if a key is currently pressed or not (per joystick) */ + +i32 RGFW_joysticks[4]; /* limit of 4 joysticks at a time */ +u16 RGFW_joystickCount; /* the actual amount of joysticks */ /* event callback defines start here */ - /* - These exist to avoid the - if (func == NULL) check - for (allegedly) better performance - */ - void RGFW_windowmovefuncEMPTY(RGFW_window* win, RGFW_rect r) { RGFW_UNUSED(win); RGFW_UNUSED(r); } - void RGFW_windowresizefuncEMPTY(RGFW_window* win, RGFW_rect r) { RGFW_UNUSED(win); RGFW_UNUSED(r); } - void RGFW_windowquitfuncEMPTY(RGFW_window* win) { RGFW_UNUSED(win); } - void RGFW_focusfuncEMPTY(RGFW_window* win, b8 inFocus) {RGFW_UNUSED(win); RGFW_UNUSED(inFocus);} - void RGFW_mouseNotifyfuncEMPTY(RGFW_window* win, RGFW_vector point, b8 status) {RGFW_UNUSED(win); RGFW_UNUSED(point); RGFW_UNUSED(status);} - void RGFW_mouseposfuncEMPTY(RGFW_window* win, RGFW_vector point) {RGFW_UNUSED(win); RGFW_UNUSED(point);} - void RGFW_dndInitfuncEMPTY(RGFW_window* win, RGFW_vector point) {RGFW_UNUSED(win); RGFW_UNUSED(point);} - void RGFW_windowrefreshfuncEMPTY(RGFW_window* win) {RGFW_UNUSED(win); } - void RGFW_keyfuncEMPTY(RGFW_window* win, u32 keycode, char keyName[16], u8 lockState, b8 pressed) {RGFW_UNUSED(win); RGFW_UNUSED(keycode); RGFW_UNUSED(keyName); RGFW_UNUSED(lockState); RGFW_UNUSED(pressed);} - void RGFW_mousebuttonfuncEMPTY(RGFW_window* win, u8 button, double scroll, b8 pressed) {RGFW_UNUSED(win); RGFW_UNUSED(button); RGFW_UNUSED(scroll); RGFW_UNUSED(pressed);} - void RGFW_jsButtonfuncEMPTY(RGFW_window* win, u16 joystick, u8 button, b8 pressed){RGFW_UNUSED(win); RGFW_UNUSED(joystick); RGFW_UNUSED(button); RGFW_UNUSED(pressed); } - void RGFW_jsAxisfuncEMPTY(RGFW_window* win, u16 joystick, RGFW_vector axis[2], u8 axisesCount){RGFW_UNUSED(win); RGFW_UNUSED(joystick); RGFW_UNUSED(axis); RGFW_UNUSED(axisesCount); } - - #ifdef RGFW_ALLOC_DROPFILES - void RGFW_dndfuncEMPTY(RGFW_window* win, char** droppedFiles, u32 droppedFilesCount) {RGFW_UNUSED(win); RGFW_UNUSED(droppedFiles); RGFW_UNUSED(droppedFilesCount);} - #else - void RGFW_dndfuncEMPTY(RGFW_window* win, char droppedFiles[RGFW_MAX_DROPS][RGFW_MAX_PATH], u32 droppedFilesCount) {RGFW_UNUSED(win); RGFW_UNUSED(droppedFiles); RGFW_UNUSED(droppedFilesCount);} - #endif +/* + These exist to avoid the + if (func == NULL) check + for (allegedly) better performance +*/ +void RGFW_windowmovefuncEMPTY(RGFW_window* win, RGFW_rect r) { RGFW_UNUSED(win); RGFW_UNUSED(r); } +void RGFW_windowresizefuncEMPTY(RGFW_window* win, RGFW_rect r) { RGFW_UNUSED(win); RGFW_UNUSED(r); } +void RGFW_windowquitfuncEMPTY(RGFW_window* win) { RGFW_UNUSED(win); } +void RGFW_focusfuncEMPTY(RGFW_window* win, b8 inFocus) {RGFW_UNUSED(win); RGFW_UNUSED(inFocus);} +void RGFW_mouseNotifyfuncEMPTY(RGFW_window* win, RGFW_point point, b8 status) {RGFW_UNUSED(win); RGFW_UNUSED(point); RGFW_UNUSED(status);} +void RGFW_mouseposfuncEMPTY(RGFW_window* win, RGFW_point point) {RGFW_UNUSED(win); RGFW_UNUSED(point);} +void RGFW_dndInitfuncEMPTY(RGFW_window* win, RGFW_point point) {RGFW_UNUSED(win); RGFW_UNUSED(point);} +void RGFW_windowrefreshfuncEMPTY(RGFW_window* win) {RGFW_UNUSED(win); } +void RGFW_keyfuncEMPTY(RGFW_window* win, u32 keycode, char keyName[16], u8 lockState, b8 pressed) {RGFW_UNUSED(win); RGFW_UNUSED(keycode); RGFW_UNUSED(keyName); RGFW_UNUSED(lockState); RGFW_UNUSED(pressed);} +void RGFW_mousebuttonfuncEMPTY(RGFW_window* win, u8 button, double scroll, b8 pressed) {RGFW_UNUSED(win); RGFW_UNUSED(button); RGFW_UNUSED(scroll); RGFW_UNUSED(pressed);} +void RGFW_jsButtonfuncEMPTY(RGFW_window* win, u16 joystick, u8 button, b8 pressed){RGFW_UNUSED(win); RGFW_UNUSED(joystick); RGFW_UNUSED(button); RGFW_UNUSED(pressed); } +void RGFW_jsAxisfuncEMPTY(RGFW_window* win, u16 joystick, RGFW_point axis[2], u8 axisesCount){RGFW_UNUSED(win); RGFW_UNUSED(joystick); RGFW_UNUSED(axis); RGFW_UNUSED(axisesCount); } + +#ifdef RGFW_ALLOC_DROPFILES +void RGFW_dndfuncEMPTY(RGFW_window* win, char** droppedFiles, u32 droppedFilesCount) {RGFW_UNUSED(win); RGFW_UNUSED(droppedFiles); RGFW_UNUSED(droppedFilesCount);} +#else +void RGFW_dndfuncEMPTY(RGFW_window* win, char droppedFiles[RGFW_MAX_DROPS][RGFW_MAX_PATH], u32 droppedFilesCount) {RGFW_UNUSED(win); RGFW_UNUSED(droppedFiles); RGFW_UNUSED(droppedFilesCount);} +#endif + +RGFW_windowmovefunc RGFW_windowMoveCallback = RGFW_windowmovefuncEMPTY; +RGFW_windowresizefunc RGFW_windowResizeCallback = RGFW_windowresizefuncEMPTY; +RGFW_windowquitfunc RGFW_windowQuitCallback = RGFW_windowquitfuncEMPTY; +RGFW_mouseposfunc RGFW_mousePosCallback = RGFW_mouseposfuncEMPTY; +RGFW_windowrefreshfunc RGFW_windowRefreshCallback = RGFW_windowrefreshfuncEMPTY; +RGFW_focusfunc RGFW_focusCallback = RGFW_focusfuncEMPTY; +RGFW_mouseNotifyfunc RGFW_mouseNotifyCallBack = RGFW_mouseNotifyfuncEMPTY; +RGFW_dndfunc RGFW_dndCallback = RGFW_dndfuncEMPTY; +RGFW_dndInitfunc RGFW_dndInitCallback = RGFW_dndInitfuncEMPTY; +RGFW_keyfunc RGFW_keyCallback = RGFW_keyfuncEMPTY; +RGFW_mousebuttonfunc RGFW_mouseButtonCallback = RGFW_mousebuttonfuncEMPTY; +RGFW_jsButtonfunc RGFW_jsButtonCallback = RGFW_jsButtonfuncEMPTY; +RGFW_jsAxisfunc RGFW_jsAxisCallback = RGFW_jsAxisfuncEMPTY; + +void RGFW_window_checkEvents(RGFW_window* win, i32 waitMS) { + RGFW_window_eventWait(win, waitMS); - RGFW_windowmovefunc RGFW_windowMoveCallback = RGFW_windowmovefuncEMPTY; - RGFW_windowresizefunc RGFW_windowResizeCallback = RGFW_windowresizefuncEMPTY; - RGFW_windowquitfunc RGFW_windowQuitCallback = RGFW_windowquitfuncEMPTY; - RGFW_mouseposfunc RGFW_mousePosCallback = RGFW_mouseposfuncEMPTY; - RGFW_windowrefreshfunc RGFW_windowRefreshCallback = RGFW_windowrefreshfuncEMPTY; - RGFW_focusfunc RGFW_focusCallback = RGFW_focusfuncEMPTY; - RGFW_mouseNotifyfunc RGFW_mouseNotifyCallBack = RGFW_mouseNotifyfuncEMPTY; - RGFW_dndfunc RGFW_dndCallback = RGFW_dndfuncEMPTY; - RGFW_dndInitfunc RGFW_dndInitCallback = RGFW_dndInitfuncEMPTY; - RGFW_keyfunc RGFW_keyCallback = RGFW_keyfuncEMPTY; - RGFW_mousebuttonfunc RGFW_mouseButtonCallback = RGFW_mousebuttonfuncEMPTY; - RGFW_jsButtonfunc RGFW_jsButtonCallback = RGFW_jsButtonfuncEMPTY; - RGFW_jsAxisfunc RGFW_jsAxisCallback = RGFW_jsAxisfuncEMPTY; - - void RGFW_window_checkEvents(RGFW_window* win) { while (RGFW_window_checkEvent(win) != NULL && RGFW_window_shouldClose(win) == 0) { if (win->event.type == RGFW_quit) return; }} + while (RGFW_window_checkEvent(win) != NULL && RGFW_window_shouldClose(win) == 0) { + if (win->event.type == RGFW_quit) return; + } - void RGFW_setWindowMoveCallback(RGFW_windowmovefunc func) { RGFW_windowMoveCallback = func; } - void RGFW_setWindowResizeCallback(RGFW_windowresizefunc func) { RGFW_windowResizeCallback = func; } - void RGFW_setWindowQuitCallback(RGFW_windowquitfunc func) { RGFW_windowQuitCallback = func; } - void RGFW_setMousePosCallback(RGFW_mouseposfunc func) { RGFW_mousePosCallback = func; } - void RGFW_setWindowRefreshCallback(RGFW_windowrefreshfunc func) { RGFW_windowRefreshCallback = func; } - void RGFW_setFocusCallback(RGFW_focusfunc func) { RGFW_focusCallback = func; } - void RGFW_setMouseNotifyCallBack(RGFW_mouseNotifyfunc func) { RGFW_mouseNotifyCallBack = func; } - void RGFW_setDndCallback(RGFW_dndfunc func) { RGFW_dndCallback = func; } - void RGFW_setDndInitCallback(RGFW_dndInitfunc func) { RGFW_dndInitCallback = func; } - void RGFW_setKeyCallback(RGFW_keyfunc func) { RGFW_keyCallback = func; } - void RGFW_setMouseButtonCallback(RGFW_mousebuttonfunc func) { RGFW_mouseButtonCallback = func; } - void RGFW_setjsButtonCallback(RGFW_jsButtonfunc func) { RGFW_jsButtonCallback = func; } - void RGFW_setjsAxisCallback(RGFW_jsAxisfunc func) { RGFW_jsAxisCallback = func; } + #ifdef RGFW_WEBASM /* webasm needs to run the sleep function for asyncify */ + RGFW_sleep(0); + #endif +} + +void RGFW_setWindowMoveCallback(RGFW_windowmovefunc func) { RGFW_windowMoveCallback = func; } +void RGFW_setWindowResizeCallback(RGFW_windowresizefunc func) { RGFW_windowResizeCallback = func; } +void RGFW_setWindowQuitCallback(RGFW_windowquitfunc func) { RGFW_windowQuitCallback = func; } +void RGFW_setMousePosCallback(RGFW_mouseposfunc func) { RGFW_mousePosCallback = func; } +void RGFW_setWindowRefreshCallback(RGFW_windowrefreshfunc func) { RGFW_windowRefreshCallback = func; } +void RGFW_setFocusCallback(RGFW_focusfunc func) { RGFW_focusCallback = func; } +void RGFW_setMouseNotifyCallBack(RGFW_mouseNotifyfunc func) { RGFW_mouseNotifyCallBack = func; } +void RGFW_setDndCallback(RGFW_dndfunc func) { RGFW_dndCallback = func; } +void RGFW_setDndInitCallback(RGFW_dndInitfunc func) { RGFW_dndInitCallback = func; } +void RGFW_setKeyCallback(RGFW_keyfunc func) { RGFW_keyCallback = func; } +void RGFW_setMouseButtonCallback(RGFW_mousebuttonfunc func) { RGFW_mouseButtonCallback = func; } +void RGFW_setjsButtonCallback(RGFW_jsButtonfunc func) { RGFW_jsButtonCallback = func; } +void RGFW_setjsAxisCallback(RGFW_jsAxisfunc func) { RGFW_jsAxisCallback = func; } /* - no more event call back defines +no more event call back defines */ #define RGFW_ASSERT(check, str) {\ @@ -1270,8 +1349,8 @@ MacOS -> windows and linux already don't have keycodes as macros, so there's no } \ } - b8 RGFW_error = 0; - b8 RGFW_Error() { return RGFW_error; } +b8 RGFW_error = 0; +b8 RGFW_Error(void) { return RGFW_error; } #define SET_ATTRIB(a, v) { \ assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \ @@ -1279,59 +1358,63 @@ MacOS -> windows and linux already don't have keycodes as macros, so there's no attribs[index++] = v; \ } - RGFW_area RGFW_bufferSize = {0, 0}; - void RGFW_setBufferSize(RGFW_area size) { - RGFW_bufferSize = size; - } +RGFW_area RGFW_bufferSize = {0, 0}; +void RGFW_setBufferSize(RGFW_area size) { + RGFW_bufferSize = size; +} - RGFWDEF RGFW_window* RGFW_window_basic_init(RGFW_rect rect, u16 args); +RGFWDEF RGFW_window* RGFW_window_basic_init(RGFW_rect rect, u16 args); - RGFW_window* RGFW_window_basic_init(RGFW_rect rect, u16 args) { - RGFW_window* win = (RGFW_window*) RGFW_MALLOC(sizeof(RGFW_window)); /* make a new RGFW struct */ +/* do a basic initialization for RGFW_window, this is to standard it for each OS */ +RGFW_window* RGFW_window_basic_init(RGFW_rect rect, u16 args) { + RGFW_window* win = (RGFW_window*) RGFW_MALLOC(sizeof(RGFW_window)); /* make a new RGFW struct */ + /* clear out dnd info */ #ifdef RGFW_ALLOC_DROPFILES - win->event.droppedFiles = (char**) RGFW_MALLOC(sizeof(char*) * RGFW_MAX_DROPS); - u32 i; - for (i = 0; i < RGFW_MAX_DROPS; i++) - win->event.droppedFiles[i] = (char*) RGFW_CALLOC(RGFW_MAX_PATH, sizeof(char)); + win->event.droppedFiles = (char**) RGFW_MALLOC(sizeof(char*) * RGFW_MAX_DROPS); + u32 i; + for (i = 0; i < RGFW_MAX_DROPS; i++) + win->event.droppedFiles[i] = (char*) RGFW_CALLOC(RGFW_MAX_PATH, sizeof(char)); #endif - #ifndef RGFW_X11 - RGFW_area screenR = RGFW_getScreenSize(); - #else - win->src.display = XOpenDisplay(NULL); - assert(win->src.display != NULL); - - Screen* scrn = DefaultScreenOfDisplay((Display*)win->src.display); - RGFW_area screenR = RGFW_AREA(scrn->width, scrn->height); - #endif - - if (args & RGFW_FULLSCREEN) - rect = RGFW_RECT(0, 0, screenR.w, screenR.h); - - if (args & RGFW_CENTER) - rect = RGFW_RECT((screenR.w - rect.w) / 2, (screenR.h - rect.h) / 2, rect.w, rect.h); - - /* set and init the new window's data */ - win->r = rect; - win->fpsCap = 0; - win->event.inFocus = 1; - win->event.droppedFilesCount = 0; - win->src.joystickCount = 0; - win->src.winArgs = 0; - win->event.lockState = 0; - - return win; - } - - #ifndef RGFW_NO_MONITOR - void RGFW_window_scaleToMonitor(RGFW_window* win) { - RGFW_monitor monitor = RGFW_window_getMonitor(win); + /* X11 requires us to have a display to get the screen size */ + #ifndef RGFW_X11 + RGFW_area screenR = RGFW_getScreenSize(); + #else + win->src.display = XOpenDisplay(NULL); + assert(win->src.display != NULL); - RGFW_window_resize(win, RGFW_AREA(((u32) monitor.scaleX) * win->r.w, ((u32) monitor.scaleX) * win->r.h)); - } + Screen* scrn = DefaultScreenOfDisplay((Display*)win->src.display); + RGFW_area screenR = RGFW_AREA(scrn->width, scrn->height); #endif + + /* rect based the requested args */ + if (args & RGFW_FULLSCREEN) + rect = RGFW_RECT(0, 0, screenR.w, screenR.h); + + if (args & RGFW_CENTER) + rect = RGFW_RECT((screenR.w - rect.w) / 2, (screenR.h - rect.h) / 2, rect.w, rect.h); + + /* set and init the new window's data */ + win->r = rect; + win->fpsCap = 0; + win->event.inFocus = 1; + win->event.droppedFilesCount = 0; + RGFW_joystickCount = 0; + win->_winArgs = 0; + win->event.lockState = 0; + + return win; +} + +#ifndef RGFW_NO_MONITOR +void RGFW_window_scaleToMonitor(RGFW_window* win) { + RGFW_monitor monitor = RGFW_window_getMonitor(win); + + RGFW_window_resize(win, RGFW_AREA(((u32) monitor.scaleX) * win->r.w, ((u32) monitor.scaleX) * win->r.h)); +} +#endif RGFW_window* RGFW_root = NULL; @@ -1339,192 +1422,185 @@ RGFW_window* RGFW_root = NULL; #define RGFW_HOLD_MOUSE (1L<<2) /*!< hold the moues still */ #define RGFW_MOUSE_LEFT (1L<<3) /* if mouse left the window */ - void RGFW_clipboardFree(char* str) { RGFW_FREE(str); } - - b8 RGFW_mouseButtons[5] = { 0 }; - b8 RGFW_mouseButtons_prev[5]; +void RGFW_clipboardFree(char* str) { RGFW_FREE(str); } - b8 RGFW_isMousePressed(RGFW_window* win, u8 button) { - assert(win != NULL); - return RGFW_mouseButtons[button] && (win != NULL) && win->event.inFocus; - } - b8 RGFW_wasMousePressed(RGFW_window* win, u8 button) { - assert(win != NULL); - return RGFW_mouseButtons_prev[button] && (win != NULL) && win->event.inFocus; - } - b8 RGFW_isMouseHeld(RGFW_window* win, u8 button) { - return (RGFW_isMousePressed(win, button) && RGFW_wasMousePressed(win, button)); - } - b8 RGFW_isMouseReleased(RGFW_window* win, u8 button) { - return (!RGFW_isMousePressed(win, button) && RGFW_wasMousePressed(win, button)); - } +RGFW_keyState RGFW_mouseButtons[5] = { 0 }; - b8 RGFW_isPressed(RGFW_window* win, u8 key) { - assert(win != NULL); - return RGFW_keyboard[key].current && win->event.inFocus; - } +b8 RGFW_isMousePressed(RGFW_window* win, u8 button) { + assert(win != NULL); + return RGFW_mouseButtons[button].current && (win != NULL) && win->event.inFocus; +} +b8 RGFW_wasMousePressed(RGFW_window* win, u8 button) { + assert(win != NULL); + return RGFW_mouseButtons[button].prev && (win != NULL) && win->event.inFocus; +} +b8 RGFW_isMouseHeld(RGFW_window* win, u8 button) { + return (RGFW_isMousePressed(win, button) && RGFW_wasMousePressed(win, button)); +} +b8 RGFW_isMouseReleased(RGFW_window* win, u8 button) { + return (!RGFW_isMousePressed(win, button) && RGFW_wasMousePressed(win, button)); +} - b8 RGFW_wasPressed(RGFW_window* win, u8 key) { - assert(win != NULL); - return RGFW_keyboard[key].prev && win->event.inFocus; - } +b8 RGFW_isPressed(RGFW_window* win, u8 key) { + return RGFW_keyboard[key].current && (win == NULL || win->event.inFocus); +} - b8 RGFW_isHeld(RGFW_window* win, u8 key) { - return (RGFW_isPressed(win, key) && RGFW_wasPressed(win, key)); - } +b8 RGFW_wasPressed(RGFW_window* win, u8 key) { + return RGFW_keyboard[key].prev && (win == NULL || win->event.inFocus); +} - b8 RGFW_isClicked(RGFW_window* win, u8 key) { - return (RGFW_wasPressed(win, key) && !RGFW_isPressed(win, key)); - } +b8 RGFW_isHeld(RGFW_window* win, u8 key) { + return (RGFW_isPressed(win, key) && RGFW_wasPressed(win, key)); +} - b8 RGFW_isReleased(RGFW_window* win, u8 key) { - return (!RGFW_isPressed(win, key) && RGFW_wasPressed(win, key)); - } - - void RGFW_window_makeCurrent(RGFW_window* win) { - assert(win != NULL); +b8 RGFW_isClicked(RGFW_window* win, u8 key) { + return (RGFW_wasPressed(win, key) && !RGFW_isPressed(win, key)); +} -#if defined(RGFW_WINDOWS) && defined(RGFW_DIRECTX) - RGFW_dxInfo.pDeviceContext->lpVtbl->OMSetRenderTargets(RGFW_dxInfo.pDeviceContext, 1, &win->src.renderTargetView, NULL); -#endif +b8 RGFW_isReleased(RGFW_window* win, u8 key) { + return (!RGFW_isPressed(win, key) && RGFW_wasPressed(win, key)); +} -#ifdef RGFW_OPENGL - RGFW_window_makeCurrent_OpenGL(win); +void RGFW_window_makeCurrent(RGFW_window* win) { + assert(win != NULL); + +#if defined(RGFW_WINDOWS) && defined(RGFW_DIRECTX) + RGFW_dxInfo.pDeviceContext->lpVtbl->OMSetRenderTargets(RGFW_dxInfo.pDeviceContext, 1, &win->src.renderTargetView, NULL); +#elif defined(RGFW_OPENGL) + RGFW_window_makeCurrent_OpenGL(win); #endif - } +} - void RGFW_window_setGPURender(RGFW_window* win, i8 set) { - if (!set && !(win->src.winArgs & RGFW_NO_GPU_RENDER)) - win->src.winArgs |= RGFW_NO_GPU_RENDER; +void RGFW_window_setGPURender(RGFW_window* win, i8 set) { + if (!set && !(win->_winArgs & RGFW_NO_GPU_RENDER)) + win->_winArgs |= RGFW_NO_GPU_RENDER; - else if (set && win->src.winArgs & RGFW_NO_GPU_RENDER) - win->src.winArgs ^= RGFW_NO_GPU_RENDER; - } + else if (set && win->_winArgs & RGFW_NO_GPU_RENDER) + win->_winArgs ^= RGFW_NO_GPU_RENDER; +} - void RGFW_window_setCPURender(RGFW_window* win, i8 set) { - if (!set && !(win->src.winArgs & RGFW_NO_CPU_RENDER)) - win->src.winArgs |= RGFW_NO_CPU_RENDER; +void RGFW_window_setCPURender(RGFW_window* win, i8 set) { + if (!set && !(win->_winArgs & RGFW_NO_CPU_RENDER)) + win->_winArgs |= RGFW_NO_CPU_RENDER; - else if (set && win->src.winArgs & RGFW_NO_CPU_RENDER) - win->src.winArgs ^= RGFW_NO_CPU_RENDER; - } + else if (set && win->_winArgs & RGFW_NO_CPU_RENDER) + win->_winArgs ^= RGFW_NO_CPU_RENDER; +} - void RGFW_window_maximize(RGFW_window* win) { - assert(win != NULL); +void RGFW_window_maximize(RGFW_window* win) { + assert(win != NULL); - RGFW_area screen = RGFW_getScreenSize(); + RGFW_area screen = RGFW_getScreenSize(); - RGFW_window_move(win, RGFW_VECTOR(0, 0)); - RGFW_window_resize(win, screen); - } + RGFW_window_move(win, RGFW_POINT(0, 0)); + RGFW_window_resize(win, screen); +} - b8 RGFW_window_shouldClose(RGFW_window* win) { - assert(win != NULL); - return (win->event.type == RGFW_quit || RGFW_isPressed(win, RGFW_Escape)); - } +b8 RGFW_window_shouldClose(RGFW_window* win) { + assert(win != NULL); + return (win->event.type == RGFW_quit || RGFW_isPressed(win, RGFW_Escape)); +} - void RGFW_window_setShouldClose(RGFW_window* win) { win->event.type = RGFW_quit; RGFW_windowQuitCallback(win); } +void RGFW_window_setShouldClose(RGFW_window* win) { win->event.type = RGFW_quit; RGFW_windowQuitCallback(win); } - #ifndef RGFW_NO_MONITOR +#ifndef RGFW_NO_MONITOR void RGFW_window_moveToMonitor(RGFW_window* win, RGFW_monitor m) { - RGFW_window_move(win, RGFW_VECTOR(m.rect.x + win->r.x, m.rect.y + win->r.y)); + RGFW_window_move(win, RGFW_POINT(m.rect.x + win->r.x, m.rect.y + win->r.y)); } - #endif +#endif - RGFWDEF void RGFW_clipCursor(RGFW_rect); - - #if !defined(RGFW_WINDOWS) && !defined(RGFW_MACOS) - void RGFW_clipCursor(RGFW_rect r) { RGFW_UNUSED(r) } - #endif +RGFWDEF void RGFW_captureCursor(RGFW_window* win, RGFW_rect); - void RGFW_window_mouseHold(RGFW_window* win, RGFW_area area) { - if (!(win->src.winArgs & RGFW_HOLD_MOUSE)) { - RGFW_clipCursor(win->r); - win->src.winArgs |= RGFW_HOLD_MOUSE; - } - - if (!area.w && !area.h) - area = RGFW_AREA(win->r.w / 2, win->r.h / 2); +void RGFW_window_mouseHold(RGFW_window* win, RGFW_area area) { + if ((win->_winArgs & RGFW_HOLD_MOUSE)) + return; + + + if (!area.w && !area.h) + area = RGFW_AREA(win->r.w / 2, win->r.h / 2); - #ifndef RGFW_MACOS - RGFW_window_moveMouse(win, RGFW_VECTOR(win->r.x + (area.w), win->r.y + (area.h))); - #endif - } + win->_winArgs |= RGFW_HOLD_MOUSE; + RGFW_captureCursor(win, win->r); + RGFW_window_moveMouse(win, RGFW_POINT(win->r.x + (area.w), win->r.y + (area.h))); +} - void RGFW_window_mouseUnhold(RGFW_window* win) { - if ((win->src.winArgs & RGFW_HOLD_MOUSE)) { - win->src.winArgs ^= RGFW_HOLD_MOUSE; +void RGFW_window_mouseUnhold(RGFW_window* win) { + if ((win->_winArgs & RGFW_HOLD_MOUSE)) { + win->_winArgs ^= RGFW_HOLD_MOUSE; - RGFW_clipCursor(RGFW_RECT(0, 0, 0, 0)); - } + RGFW_captureCursor(win, RGFW_RECT(0, 0, 0, 0)); } +} - void RGFW_window_checkFPS(RGFW_window* win) { - u64 deltaTime = RGFW_getTimeNS() - win->event.frameTime; +void RGFW_window_checkFPS(RGFW_window* win) { + u64 deltaTime = RGFW_getTimeNS() - win->event.frameTime; - u64 fps = round(1e+9 / deltaTime); - win->event.fps = fps; + u64 fps = round(1e+9 / deltaTime); + win->event.fps = fps; - if (win->fpsCap && fps > win->fpsCap) { - u64 frameTimeNS = 1e+9 / win->fpsCap; - u64 sleepTimeMS = (frameTimeNS - deltaTime) / 1e6; + if (win->fpsCap && fps > win->fpsCap) { + u64 frameTimeNS = 1e+9 / win->fpsCap; + u64 sleepTimeMS = (frameTimeNS - deltaTime) / 1e6; - if (sleepTimeMS > 0) { - RGFW_sleep(sleepTimeMS); - win->event.frameTime = 0; - } + if (sleepTimeMS > 0) { + RGFW_sleep(sleepTimeMS); + win->event.frameTime = 0; } - - win->event.frameTime = RGFW_getTimeNS(); - - if (win->fpsCap == 0) - return; - - deltaTime = RGFW_getTimeNS() - win->event.frameTime2; - win->event.fps = round(1e+9 / deltaTime); - win->event.frameTime2 = RGFW_getTimeNS(); } + + win->event.frameTime = RGFW_getTimeNS(); - u32 RGFW_isPressedJS(RGFW_window* win, u16 c, u8 button) { return win->src.jsPressed[c][button]; } + if (win->fpsCap == 0) + return; - #if defined(RGFW_X11) || defined(RGFW_WINDOWS) - void RGFW_window_showMouse(RGFW_window* win, i8 show) { - static u8 RGFW_blk[] = { 0, 0, 0, 0 }; - if (show == 0) - RGFW_window_setMouse(win, RGFW_blk, RGFW_AREA(1, 1), 4); - else - RGFW_window_setMouseDefault(win); - } - #endif + deltaTime = RGFW_getTimeNS() - win->event.frameTime2; + win->event.fps = round(1e+9 / deltaTime); + win->event.frameTime2 = RGFW_getTimeNS(); +} - RGFWDEF void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock); - void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) { - if (capital && !(win->event.lockState & RGFW_CAPSLOCK)) - win->event.lockState |= RGFW_CAPSLOCK; - else if (!capital && (win->event.lockState & RGFW_CAPSLOCK)) - win->event.lockState ^= RGFW_CAPSLOCK; - - if (numlock && !(win->event.lockState & RGFW_NUMLOCK)) - win->event.lockState |= RGFW_NUMLOCK; - else if (!numlock && (win->event.lockState & RGFW_NUMLOCK)) - win->event.lockState ^= RGFW_NUMLOCK; +u32 RGFW_isPressedJS(RGFW_window* win, u16 c, u8 button) { + RGFW_UNUSED(win); + return RGFW_jsPressed[c][button]; +} + +#if defined(RGFW_X11) || defined(RGFW_WINDOWS) + void RGFW_window_showMouse(RGFW_window* win, i8 show) { + static u8 RGFW_blk[] = { 0, 0, 0, 0 }; + if (show == 0) + RGFW_window_setMouse(win, RGFW_blk, RGFW_AREA(1, 1), 4); + else + RGFW_window_setMouseDefault(win); } +#endif - #if defined(RGFW_X11) || defined(RGFW_MACOS) - struct timespec; +RGFWDEF void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock); +void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) { + if (capital && !(win->event.lockState & RGFW_CAPSLOCK)) + win->event.lockState |= RGFW_CAPSLOCK; + else if (!capital && (win->event.lockState & RGFW_CAPSLOCK)) + win->event.lockState ^= RGFW_CAPSLOCK; + + if (numlock && !(win->event.lockState & RGFW_NUMLOCK)) + win->event.lockState |= RGFW_NUMLOCK; + else if (!numlock && (win->event.lockState & RGFW_NUMLOCK)) + win->event.lockState ^= RGFW_NUMLOCK; +} - int nanosleep(const struct timespec* duration, struct timespec* rem); - int clock_gettime(clockid_t clk_id, struct timespec* tp); - int setenv(const char *name, const char *value, int overwrite); +#if defined(RGFW_X11) || defined(RGFW_MACOS) + struct timespec; - void RGFW_window_setDND(RGFW_window* win, b8 allow) { - if (allow && !(win->src.winArgs & RGFW_ALLOW_DND)) - win->src.winArgs |= RGFW_ALLOW_DND; + int nanosleep(const struct timespec* duration, struct timespec* rem); + int clock_gettime(clockid_t clk_id, struct timespec* tp); + int setenv(const char *name, const char *value, int overwrite); - else if (!allow && (win->src.winArgs & RGFW_ALLOW_DND)) - win->src.winArgs ^= RGFW_ALLOW_DND; - } - #endif + void RGFW_window_setDND(RGFW_window* win, b8 allow) { + if (allow && !(win->_winArgs & RGFW_ALLOW_DND)) + win->_winArgs |= RGFW_ALLOW_DND; + + else if (!allow && (win->_winArgs & RGFW_ALLOW_DND)) + win->_winArgs ^= RGFW_ALLOW_DND; + } +#endif /* graphics API spcific code (end of generic code) @@ -1537,15 +1613,20 @@ RGFW_window* RGFW_root = NULL; */ #if defined(RGFW_OPENGL) || defined(RGFW_EGL) || defined(RGFW_OSMESA) -#ifndef __APPLE__ -#include -#else -#ifndef GL_SILENCE_DEPRECATION -#define GL_SILENCE_DEPRECATION -#endif -#include -#include -#endif + #ifdef RGFW_WINDOWS + #define WIN32_LEAN_AND_MEAN + #include + #endif + + #ifndef __APPLE__ + #include + #else + #ifndef GL_SILENCE_DEPRECATION + #define GL_SILENCE_DEPRECATION + #endif + #include + #include + #endif /* EGL, normal OpenGL only */ #if !defined(RGFW_OSMESA) @@ -1585,45 +1666,45 @@ RGFW_window* RGFW_root = NULL; /* OPENGL normal only (no EGL / OSMesa) */ #ifndef RGFW_EGL -#define RGFW_GL_RENDER_TYPE RGFW_OS_BASED_VALUE(GLX_X_VISUAL_TYPE, 0x2003, 73) -#define RGFW_GL_ALPHA_SIZE RGFW_OS_BASED_VALUE(GLX_ALPHA_SIZE, 0x201b, 11) -#define RGFW_GL_DEPTH_SIZE RGFW_OS_BASED_VALUE(GLX_DEPTH_SIZE, 0x2022, 12) -#define RGFW_GL_DOUBLEBUFFER RGFW_OS_BASED_VALUE(GLX_DOUBLEBUFFER, 0x2011, 5) -#define RGFW_GL_STENCIL_SIZE RGFW_OS_BASED_VALUE(GLX_STENCIL_SIZE, 0x2023, 13) -#define RGFW_GL_SAMPLES RGFW_OS_BASED_VALUE(GLX_SAMPLES, 0x2042, 55) -#define RGFW_GL_STEREO RGFW_OS_BASED_VALUE(GLX_STEREO, 0x2012, 6) -#define RGFW_GL_AUX_BUFFERS RGFW_OS_BASED_VALUE(GLX_AUX_BUFFERS, 0x2024, 7) +#define RGFW_GL_RENDER_TYPE RGFW_OS_BASED_VALUE(GLX_X_VISUAL_TYPE, 0x2003, 73, 0) + #define RGFW_GL_ALPHA_SIZE RGFW_OS_BASED_VALUE(GLX_ALPHA_SIZE, 0x201b, 11, 0) + #define RGFW_GL_DEPTH_SIZE RGFW_OS_BASED_VALUE(GLX_DEPTH_SIZE, 0x2022, 12, 0) + #define RGFW_GL_DOUBLEBUFFER RGFW_OS_BASED_VALUE(GLX_DOUBLEBUFFER, 0x2011, 5, 0) + #define RGFW_GL_STENCIL_SIZE RGFW_OS_BASED_VALUE(GLX_STENCIL_SIZE, 0x2023, 13, 0) + #define RGFW_GL_SAMPLES RGFW_OS_BASED_VALUE(GLX_SAMPLES, 0x2042, 55, 0) + #define RGFW_GL_STEREO RGFW_OS_BASED_VALUE(GLX_STEREO, 0x2012, 6, 0) + #define RGFW_GL_AUX_BUFFERS RGFW_OS_BASED_VALUE(GLX_AUX_BUFFERS, 0x2024, 7, 0) #if defined(RGFW_X11) || defined(RGFW_WINDOWS) -#define RGFW_GL_DRAW RGFW_OS_BASED_VALUE(GLX_X_RENDERABLE, 0x2001, 0) -#define RGFW_GL_DRAW_TYPE RGFW_OS_BASED_VALUE(GLX_RENDER_TYPE, 0x2013, 0) -#define RGFW_GL_USE_OPENGL RGFW_OS_BASED_VALUE(GLX_USE_GL, 0x2010, 0) -#define RGFW_GL_FULL_FORMAT RGFW_OS_BASED_VALUE(GLX_TRUE_COLOR, 0x2027, 0) -#define RGFW_GL_RED_SIZE RGFW_OS_BASED_VALUE(GLX_RED_SIZE, 0x2015, 0) -#define RGFW_GL_GREEN_SIZE RGFW_OS_BASED_VALUE(GLX_GREEN_SIZE, 0x2017, 0) -#define RGFW_GL_BLUE_SIZE RGFW_OS_BASED_VALUE(GLX_BLUE_SIZE, 0x2019, 0) -#define RGFW_GL_USE_RGBA RGFW_OS_BASED_VALUE(GLX_RGBA_BIT, 0x202B, 0) + #define RGFW_GL_DRAW RGFW_OS_BASED_VALUE(GLX_X_RENDERABLE, 0x2001, 0, 0) + #define RGFW_GL_DRAW_TYPE RGFW_OS_BASED_VALUE(GLX_RENDER_TYPE, 0x2013, 0, 0) + #define RGFW_GL_USE_OPENGL RGFW_OS_BASED_VALUE(GLX_USE_GL, 0x2010, 0, 0) + #define RGFW_GL_FULL_FORMAT RGFW_OS_BASED_VALUE(GLX_TRUE_COLOR, 0x2027, 0, 0) + #define RGFW_GL_RED_SIZE RGFW_OS_BASED_VALUE(GLX_RED_SIZE, 0x2015, 0, 0) + #define RGFW_GL_GREEN_SIZE RGFW_OS_BASED_VALUE(GLX_GREEN_SIZE, 0x2017, 0, 0) + #define RGFW_GL_BLUE_SIZE RGFW_OS_BASED_VALUE(GLX_BLUE_SIZE, 0x2019, 0, 0) + #define RGFW_GL_USE_RGBA RGFW_OS_BASED_VALUE(GLX_RGBA_BIT, 0x202B, 0, 0) #endif #ifdef RGFW_WINDOWS -#define WGL_COLOR_BITS_ARB 0x2014 -#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 -#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 -#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 -#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 -#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 -#define WGL_SAMPLE_BUFFERS_ARB 0x2041 -#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20a9 -#define WGL_PIXEL_TYPE_ARB 0x2013 -#define WGL_TYPE_RGBA_ARB 0x202B + #define WGL_COLOR_BITS_ARB 0x2014 + #define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 + #define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 + #define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 + #define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 + #define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 + #define WGL_SAMPLE_BUFFERS_ARB 0x2041 + #define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20a9 + #define WGL_PIXEL_TYPE_ARB 0x2013 + #define WGL_TYPE_RGBA_ARB 0x202B -#define WGL_TRANSPARENT_ARB 0x200A + #define WGL_TRANSPARENT_ARB 0x200A #endif static u32* RGFW_initAttribs(u32 useSoftware) { RGFW_UNUSED(useSoftware); static u32 attribs[] = { - #ifndef RGFW_MACOS + #if defined(RGFW_X11) || defined(RGFW_WINDOWS) RGFW_GL_RENDER_TYPE, RGFW_GL_FULL_FORMAT, #endif @@ -1862,7 +1943,7 @@ RGFW_window* RGFW_root = NULL; eglTerminate(win->src.EGL_display); } - + void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) { assert(win != NULL); @@ -1937,9 +2018,11 @@ Start of Linux / Unix defines #include /* for hiding */ #include #include +#include #include /* for data limits (mainly used in drag and drop functions) */ #include +#include #ifdef __linux__ #include @@ -1960,6 +2043,14 @@ Start of Linux / Unix defines typedef GLXContext(*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*); #endif +#if !defined(RGFW_NO_X11_XI_PRELOAD) + typedef int (* PFN_XISelectEvents)(Display*,Window,XIEventMask*,int); + PFN_XISelectEvents XISelectEventsSrc = NULL; + #define XISelectEvents XISelectEventsSrc + + void* X11Xihandle = NULL; +#endif + #if !defined(RGFW_NO_X11_CURSOR) && !defined(RGFW_NO_X11_CURSOR_PRELOAD) PFN_XcursorImageLoadCursor XcursorImageLoadCursorSrc = NULL; PFN_XcursorImageCreate XcursorImageCreateSrc = NULL; @@ -1987,12 +2078,12 @@ Start of Linux / Unix defines win->buffer = RGFW_MALLOC(RGFW_bufferSize.w * RGFW_bufferSize.h * 4); #ifdef RGFW_OSMESA - win->src.rSurf = OSMesaCreateContext(OSMESA_RGBA, NULL); - OSMesaMakeCurrent(win->src.rSurf, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h); + win->src.ctx = OSMesaCreateContext(OSMESA_RGBA, NULL); + OSMesaMakeCurrent(win->src.ctx, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h); #endif win->src.bitmap = XCreateImage( - win->src.display, vi->visual, + win->src.display, XDefaultVisual(win->src.display, vi->screen), vi->depth, ZPixmap, 0, NULL, RGFW_bufferSize.w, RGFW_bufferSize.h, 32, 0 @@ -2018,7 +2109,7 @@ Start of Linux / Unix defines long input_mode; } hints; hints.flags = (1L << 1); - hints.decorations = !border; + hints.decorations = border; XChangeProperty( win->src.display, win->src.window, @@ -2027,6 +2118,36 @@ Start of Linux / Unix defines ); } + void RGFW_captureCursor(RGFW_window* win, RGFW_rect r) { + XIEventMask em; + em.deviceid = XIAllMasterDevices; + + /* grab the cursor if the rect struct isn't zeroed out, else ungrab*/ + if (!r.x && !r.y && r.w && !r.h) { + XUngrabPointer(win->src.display, CurrentTime); + + /* disable raw input */ + unsigned char mask[] = { 0 }; + em.mask_len = sizeof(mask); + em.mask = mask; + XISelectEvents(win->src.display, XDefaultRootWindow(win->src.display), &em, 1); + return; + } + + /* enable raw input */ + unsigned char mask[XIMaskLen(XI_RawMotion)] = { 0 }; + + em.mask_len = sizeof(mask); + em.mask = mask; + XISetMask(mask, XI_RawMotion); + + XISelectEvents(win->src.display, XDefaultRootWindow(win->src.display), &em, 1); + + XGrabPointer(win->src.display, win->src.window, True, PointerMotionMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime); + + RGFW_window_moveMouse(win, RGFW_POINT(win->r.x + (i32)(r.w / 2), win->r.y + (i32)(r.h / 2))); + } + RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) { #if !defined(RGFW_NO_X11_CURSOR) && !defined(RGFW_NO_X11_CURSOR_PRELOAD) if (X11Cursorhandle == NULL) { @@ -2044,6 +2165,20 @@ Start of Linux / Unix defines } #endif +#if !defined(RGFW_NO_X11_XI_PRELOAD) + if (X11Xihandle == NULL) { +#if defined(__CYGWIN__) + X11Xihandle = dlopen("libXi-6.so", RTLD_LAZY | RTLD_LOCAL); +#elif defined(__OpenBSD__) || defined(__NetBSD__) + X11Xihandle = dlopen("libXi.so", RTLD_LAZY | RTLD_LOCAL); +#else + X11Xihandle = dlopen("libXi.so.6", RTLD_LAZY | RTLD_LOCAL); +#endif + + XISelectEventsSrc = (PFN_XISelectEvents) dlsym(X11Xihandle, "XISelectEvents"); + } +#endif + XInitThreads(); /* init X11 threading*/ if (args & RGFW_OPENGL_SOFTWARE) @@ -2068,14 +2203,15 @@ Start of Linux / Unix defines u32 i; for (i = 0; i < (u32)fbcount; i++) { XVisualInfo* vi = glXGetVisualFromFBConfig((Display*) win->src.display, fbc[i]); - if (vi == NULL) + if (vi == NULL) continue; - + XFree(vi); i32 samp_buf, samples; glXGetFBConfigAttrib((Display*) win->src.display, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf); glXGetFBConfigAttrib((Display*) win->src.display, fbc[i], GLX_SAMPLES, &samples); + if ((best_fbc < 0 || samp_buf) && (samples == RGFW_SAMPLES || best_fbc == -1)) { best_fbc = i; } @@ -2090,12 +2226,13 @@ Start of Linux / Unix defines /* Get a visual */ XVisualInfo* vi = glXGetVisualFromFBConfig((Display*) win->src.display, bestFbc); - + XFree(fbc); - + if (args & RGFW_TRANSPARENT_WINDOW) { XMatchVisualInfo((Display*) win->src.display, DefaultScreen((Display*) win->src.display), 32, TrueColor, vi); /* for RGBA backgrounds*/ } + #else XVisualInfo viNorm; @@ -2161,9 +2298,9 @@ Start of Linux / Unix defines GLXContext ctx = NULL; if (RGFW_root != NULL) - ctx = RGFW_root->src.rSurf; + ctx = RGFW_root->src.ctx; - win->src.rSurf = glXCreateContextAttribsARB((Display*) win->src.display, bestFbc, ctx, True, context_attribs); + win->src.ctx = glXCreateContextAttribsARB((Display*) win->src.display, bestFbc, ctx, True, context_attribs); #endif if (RGFW_root == NULL) RGFW_root = win; @@ -2202,7 +2339,7 @@ Start of Linux / Unix defines /* connect the context to the window*/ #ifdef RGFW_OPENGL if ((args & RGFW_NO_INIT_API) == 0) - glXMakeCurrent((Display*) win->src.display, (Drawable) win->src.window, (GLXContext) win->src.rSurf); + glXMakeCurrent((Display*) win->src.display, (Drawable) win->src.window, (GLXContext) win->src.ctx); #endif /* set the background*/ @@ -2212,7 +2349,7 @@ Start of Linux / Unix defines XMoveWindow((Display*) win->src.display, (Drawable) win->src.window, win->r.x, win->r.y); /* move the window to it's proper cords*/ if (args & RGFW_ALLOW_DND) { /* init drag and drop atoms and turn on drag and drop for this window */ - win->src.winArgs |= RGFW_ALLOW_DND; + win->_winArgs |= RGFW_ALLOW_DND; XdndAware = XInternAtom((Display*) win->src.display, "XdndAware", False); XdndTypeList = XInternAtom((Display*) win->src.display, "XdndTypeList", False); @@ -2258,10 +2395,10 @@ Start of Linux / Unix defines return RGFW_AREA(scrn->width, scrn->height); } - RGFW_vector RGFW_getGlobalMousePoint(void) { + RGFW_point RGFW_getGlobalMousePoint(void) { assert(RGFW_root != NULL); - RGFW_vector RGFWMouse; + RGFW_point RGFWMouse; i32 x, y; u32 z; @@ -2271,10 +2408,10 @@ Start of Linux / Unix defines return RGFWMouse; } - RGFW_vector RGFW_window_getMousePoint(RGFW_window* win) { + RGFW_point RGFW_window_getMousePoint(RGFW_window* win) { assert(win != NULL); - RGFW_vector RGFWMouse; + RGFW_point RGFWMouse; i32 x, y; u32 z; @@ -2284,6 +2421,75 @@ Start of Linux / Unix defines return RGFWMouse; } + + int RGFW_eventWait_forceStop[] = {0, 0, 0}; + + void RGFW_stopCheckEvents(void) { + RGFW_eventWait_forceStop[2] = 1; + while (1) { + const char byte = 0; + const ssize_t result = write(RGFW_eventWait_forceStop[1], &byte, 1); + if (result == 1 || result == -1) + break; + } + } + + void RGFW_window_eventWait(RGFW_window* win, i32 waitMS) { + if (waitMS == 0) + return; + + u8 i; + + if (RGFW_eventWait_forceStop[0] == 0 || RGFW_eventWait_forceStop[1] == 0) { + if (pipe(RGFW_eventWait_forceStop) != -1) { + fcntl(RGFW_eventWait_forceStop[0], F_GETFL, 0); + fcntl(RGFW_eventWait_forceStop[0], F_GETFD, 0); + fcntl(RGFW_eventWait_forceStop[1], F_GETFL, 0); + fcntl(RGFW_eventWait_forceStop[1], F_GETFD, 0); + } + } + + struct pollfd fds[] = { + { ConnectionNumber(win->src.display), POLLIN, 0 }, + { RGFW_eventWait_forceStop[0], POLLIN, 0 }, + #ifdef __linux__ /* blank space for 4 joystick files*/ + { -1, POLLIN, 0 }, {-1, POLLIN, 0 }, {-1, POLLIN, 0 }, {-1, POLLIN, 0} + #endif + }; + + u8 index = 2; + + #if defined(__linux__) + for (i = 0; i < RGFW_joystickCount; i++) { + if (RGFW_joysticks[i] == 0) + continue; + + fds[index].fd = RGFW_joysticks[i]; + index++; + } + #endif + + + u64 start = RGFW_getTimeNS(); + + while (XPending(win->src.display) == 0 && waitMS >= -1) { + if (poll(fds, index, waitMS) <= 0) + break; + + if (waitMS > 0) { + waitMS -= (RGFW_getTimeNS() - start) / 1e+6; + } + } + + /* drain any data in the stop request */ + if (RGFW_eventWait_forceStop[2]) { + char data[64]; + read(RGFW_eventWait_forceStop[0], data, sizeof(data)); + + RGFW_eventWait_forceStop[2] = 0; + } + } + typedef struct XDND { long source, version; i32 format; @@ -2307,27 +2513,27 @@ Start of Linux / Unix defines #ifdef __linux__ { u8 i; - for (i = 0; i < win->src.joystickCount; i++) { + for (i = 0; i < RGFW_joystickCount; i++) { struct js_event e; - if (win->src.joysticks[i] == 0) + if (RGFW_joysticks[i] == 0) continue; - i32 flags = fcntl(win->src.joysticks[i], F_GETFL, 0); - fcntl(win->src.joysticks[i], F_SETFL, flags | O_NONBLOCK); + i32 flags = fcntl(RGFW_joysticks[i], F_GETFL, 0); + fcntl(RGFW_joysticks[i], F_SETFL, flags | O_NONBLOCK); ssize_t bytes; - while ((bytes = read(win->src.joysticks[i], &e, sizeof(e))) > 0) { + while ((bytes = read(RGFW_joysticks[i], &e, sizeof(e))) > 0) { switch (e.type) { case JS_EVENT_BUTTON: win->event.type = e.value ? RGFW_jsButtonPressed : RGFW_jsButtonReleased; win->event.button = e.number; - win->src.jsPressed[i][e.number] = e.value; + RGFW_jsPressed[i][e.number] = e.value; RGFW_jsButtonCallback(win, i, e.number, e.value); return &win->event; case JS_EVENT_AXIS: - ioctl(win->src.joysticks[i], JSIOCGAXES, &win->event.axisesCount); + ioctl(RGFW_joysticks[i], JSIOCGAXES, &win->event.axisesCount); if ((e.number == 0 || e.number % 2) && e.number != 1) xAxis = e.value; @@ -2348,10 +2554,14 @@ Start of Linux / Unix defines } #endif + XPending(win->src.display); + XEvent E; /* raw X11 event */ /* if there is no unread qued events, get a new one */ - if (XEventsQueued((Display*) win->src.display, QueuedAlready) + XEventsQueued((Display*) win->src.display, QueuedAfterReading) && win->event.type != RGFW_quit) + if ((QLength(win->src.display) || XEventsQueued((Display*) win->src.display, QueuedAlready) + XEventsQueued((Display*) win->src.display, QueuedAfterReading)) + && win->event.type != RGFW_quit + ) XNextEvent((Display*) win->src.display, &E); else { return NULL; @@ -2412,17 +2622,61 @@ Start of Linux / Unix defines } win->event.button = E.xbutton.button; - RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button]; - RGFW_mouseButtons[win->event.button] = (E.type == ButtonPress); + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + RGFW_mouseButtons[win->event.button].current = (E.type == ButtonPress); RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, (E.type == ButtonPress)); break; case MotionNotify: win->event.point.x = E.xmotion.x; win->event.point.y = E.xmotion.y; + + if ((win->_winArgs & RGFW_HOLD_MOUSE)) { + win->event.point.x = win->_lastMousePoint.x - win->event.point.x; + win->event.point.y = win->_lastMousePoint.y - win->event.point.y; + + RGFW_window_moveMouse(win, RGFW_POINT(win->r.x + (win->r.w / 2), win->r.y + (win->r.h / 2))); + } + + win->_lastMousePoint = RGFW_POINT(E.xmotion.x, E.xmotion.y); + win->event.type = RGFW_mousePosChanged; RGFW_mousePosCallback(win, win->event.point); break; + + case GenericEvent: { + /* MotionNotify is used for mouse events if the mouse isn't held */ + if (!(win->_winArgs & RGFW_HOLD_MOUSE)) { + XFreeEventData(win->src.display, &E.xcookie); + break; + } + + XGetEventData(win->src.display, &E.xcookie); + if (E.xcookie.evtype == XI_RawMotion) { + XIRawEvent *raw = (XIRawEvent *)E.xcookie.data; + if (raw->valuators.mask_len == 0) { + XFreeEventData(win->src.display, &E.xcookie); + break; + } + + double deltaX = 0.0f; + double deltaY = 0.0f; + + /* check if relative motion data exists where we think it does */ + if (XIMaskIsSet(raw->valuators.mask, 0) != 0) + deltaX += raw->raw_values[0]; + if (XIMaskIsSet(raw->valuators.mask, 1) != 0) + deltaY += raw->raw_values[1]; + + win->event.point = RGFW_POINT((u32)-deltaX, (u32)-deltaY); + + win->event.type = RGFW_mousePosChanged; + RGFW_mousePosCallback(win, win->event.point); + } + + XFreeEventData(win->src.display, &E.xcookie); + break; + } case Expose: win->event.type = RGFW_windowRefresh; @@ -2449,11 +2703,11 @@ Start of Linux / Unix defines much of this event (drag and drop code) is source from glfw */ - if ((win->src.winArgs & RGFW_ALLOW_DND) == 0) + if ((win->_winArgs & RGFW_ALLOW_DND) == 0) break; if (E.xclient.message_type == XdndEnter) { - u64 count; + unsigned long count; Atom* formats; Atom real_formats[6]; @@ -2469,7 +2723,7 @@ Start of Linux / Unix defines if (list) { Atom actualType; i32 actualFormat; - u64 bytesAfter; + unsigned long bytesAfter; XGetWindowProperty((Display*) win->src.display, xdnd.source, @@ -2480,8 +2734,8 @@ Start of Linux / Unix defines 4, &actualType, &actualFormat, - (unsigned long*) &count, - (unsigned long*) &bytesAfter, + &count, + &bytesAfter, (u8**) &formats); } else { count = 0; @@ -2497,7 +2751,7 @@ Start of Linux / Unix defines } u32 i; - for (i = 0; i < count; i++) { + for (i = 0; i < (u32)count; i++) { char* name = XGetAtomName((Display*) win->src.display, formats[i]); char* links[2] = { (char*) (const char*) "text/uri-list", (char*) (const char*) "text/plain" }; @@ -2603,15 +2857,15 @@ Start of Linux / Unix defines break; case SelectionNotify: /* this is only for checking for xdnd drops */ - if (E.xselection.property != XdndSelection || !(win->src.winArgs | RGFW_ALLOW_DND)) + if (E.xselection.property != XdndSelection || !(win->_winArgs | RGFW_ALLOW_DND)) break; char* data; - u64 result; + unsigned long result; Atom actualType; i32 actualFormat; - u64 bytesAfter; + unsigned long bytesAfter; XGetWindowProperty((Display*) win->src.display, E.xselection.requestor, E.xselection.property, 0, LONG_MAX, False, E.xselection.target, &actualType, &actualFormat, &result, &bytesAfter, (u8**) &data); @@ -2751,7 +3005,7 @@ Start of Linux / Unix defines return NULL; } - void RGFW_window_move(RGFW_window* win, RGFW_vector v) { + void RGFW_window_move(RGFW_window* win, RGFW_point v) { assert(win != NULL); win->r.x = v.x; win->r.y = v.y; @@ -2942,7 +3196,7 @@ Start of Linux / Unix defines #endif } - void RGFW_window_moveMouse(RGFW_window* win, RGFW_vector v) { + void RGFW_window_moveMouse(RGFW_window* win, RGFW_point v) { assert(win != NULL); XEvent event; @@ -3059,7 +3313,7 @@ Start of Linux / Unix defines XSetSelectionOwner((Display*) RGFW_root->src.display, CLIPBOARD, (Window) RGFW_root->src.window, CurrentTime); XConvertSelection((Display*) RGFW_root->src.display, CLIPBOARD_MANAGER, SAVE_TARGETS, None, (Window) RGFW_root->src.window, CurrentTime); - + for (;;) { XEvent event; @@ -3076,7 +3330,7 @@ Start of Linux / Unix defines const i32 formatCount = sizeof(formats) / sizeof(formats[0]); selectionString = (char*) text; - + if (request->target == TARGETS) { const Atom targets[] = { TARGETS, MULTIPLE, @@ -3096,17 +3350,16 @@ Start of Linux / Unix defines } if (request->target == MULTIPLE) { - Atom* targets; Atom actualType; i32 actualFormat; - u64 count, bytesAfter; + unsigned long count, bytesAfter; XGetWindowProperty((Display*) RGFW_root->src.display, request->requestor, request->property, 0, LONG_MAX, False, ATOM_PAIR, &actualType, &actualFormat, &count, &bytesAfter, (u8**) &targets); - u64 i; - for (i = 0; i < count; i += 2) { + unsigned long i; + for (i = 0; i < (u32)count; i += 2) { i32 j; for (j = 0; j < formatCount; j++) { @@ -3170,14 +3423,14 @@ Start of Linux / Unix defines i32 js = open(file, O_RDONLY); - if (js && win->src.joystickCount < 4) { - win->src.joystickCount++; + if (js && RGFW_joystickCount < 4) { + RGFW_joystickCount++; - win->src.joysticks[win->src.joystickCount - 1] = open(file, O_RDONLY); + RGFW_joysticks[RGFW_joystickCount - 1] = open(file, O_RDONLY); u8 i; for (i = 0; i < 16; i++) - win->src.jsPressed[win->src.joystickCount - 1][i] = 0; + RGFW_jsPressed[RGFW_joystickCount - 1][i] = 0; } @@ -3188,7 +3441,7 @@ Start of Linux / Unix defines #endif } - return win->src.joystickCount - 1; + return RGFW_joystickCount - 1; #endif } @@ -3226,7 +3479,7 @@ Start of Linux / Unix defines Atom actual_type; i32 actual_format; - u64 nitems, bytes_after; + unsigned long nitems, bytes_after; unsigned char* prop_data; i16 status = XGetWindowProperty(win->src.display, (Window) win->src.window, prop, 0, 2, False, @@ -3259,7 +3512,7 @@ Start of Linux / Unix defines Atom actual_type; i32 actual_format; - u64 nitems, bytes_after; + unsigned long nitems, bytes_after; unsigned char* prop_data; i16 status = XGetWindowProperty(win->src.display, (Window) win->src.window, net_wm_state, 0, 1024, False, @@ -3397,7 +3650,7 @@ Start of Linux / Unix defines void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) { assert(win != NULL); - glXMakeCurrent((Display*) win->src.display, (Drawable) win->src.window, (GLXContext) win->src.rSurf); + glXMakeCurrent((Display*) win->src.display, (Drawable) win->src.window, (GLXContext) win->src.ctx); } #endif @@ -3408,7 +3661,7 @@ Start of Linux / Unix defines RGFW_window_makeCurrent(win); /* clear the window*/ - if (!(win->src.winArgs & RGFW_NO_CPU_RENDER)) { + if (!(win->_winArgs & RGFW_NO_CPU_RENDER)) { #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) #ifdef RGFW_OSMESA RGFW_OSMesa_reorganize(); @@ -3433,7 +3686,7 @@ Start of Linux / Unix defines #endif } - if (!(win->src.winArgs & RGFW_NO_GPU_RENDER)) { + if (!(win->_winArgs & RGFW_NO_GPU_RENDER)) { #ifdef RGFW_EGL eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface); #elif defined(RGFW_OPENGL) @@ -3458,6 +3711,10 @@ Start of Linux / Unix defines void RGFW_window_close(RGFW_window* win) { + /* ungrab pointer if it was grabbed */ + if (win->_winArgs & RGFW_HOLD_MOUSE) + XUngrabPointer(win->src.display, CurrentTime); + assert(win != NULL); #ifdef RGFW_EGL RGFW_closeEGL(win); @@ -3472,7 +3729,7 @@ Start of Linux / Unix defines if ((Display*) win->src.display) { #ifdef RGFW_OPENGL - glXDestroyContext((Display*) win->src.display, win->src.rSurf); + glXDestroyContext((Display*) win->src.display, win->src.ctx); #endif if (win == RGFW_root) @@ -3503,24 +3760,38 @@ Start of Linux / Unix defines X11Cursorhandle = NULL; } #endif +#if !defined(RGFW_NO_X11_XI_PRELOAD) + if (X11Xihandle != NULL && RGFW_windowsOpen <= 0) { + dlclose(X11Xihandle); + + X11Xihandle = NULL; + } +#endif if (RGFW_libxshape != NULL && RGFW_windowsOpen <= 0) { dlclose(RGFW_libxshape); RGFW_libxshape = NULL; } + if (RGFW_windowsOpen <= 0) { + if (RGFW_eventWait_forceStop[0] || RGFW_eventWait_forceStop[1]){ + close(RGFW_eventWait_forceStop[0]); + close(RGFW_eventWait_forceStop[1]); + } + + u8 i; + for (i = 0; i < RGFW_joystickCount; i++) + close(RGFW_joysticks[i]); + } + /* set cleared display / window to NULL for error checking */ win->src.display = (Display*) 0; win->src.window = (Window) 0; - u8 i; - for (i = 0; i < win->src.joystickCount; i++) - close(win->src.joysticks[i]); - RGFW_FREE(win); /* free collected window data */ } - u64 RGFW_getTimeNS(void) { + u64 RGFW_getTimeNS(void) { struct timespec ts = { 0 }; clock_gettime(1, &ts); unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec; @@ -3550,6 +3821,8 @@ Start of Linux / Unix defines */ #ifdef RGFW_WINDOWS + #define WIN32_LEAN_AND_MEAN + #include #include #include @@ -3771,8 +4044,8 @@ static HMODULE wglinstance = NULL; win->src.hdcMem = CreateCompatibleDC(win->src.hdc); #if defined(RGFW_OSMESA) - win->src.rSurf = OSMesaCreateContext(OSMESA_RGBA, NULL); - OSMesaMakeCurrent(win->src.rSurf, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h); + win->src.ctx = OSMesaCreateContext(OSMESA_RGBA, NULL); + OSMesaMakeCurrent(win->src.ctx, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h); #endif #else RGFW_UNUSED(win); /* if buffer rendering is not being used */ @@ -3783,14 +4056,25 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ DragAcceptFiles(win->src.window, allow); } - void RGFW_clipCursor(RGFW_rect rect) { + void RGFW_captureCursor(RGFW_window* win, RGFW_rect rect) { + RGFW_UNUSED(win) + if (!rect.x && !rect.y && rect.w && !rect.h) { ClipCursor(NULL); + const RAWINPUTDEVICE id = { 0x01, 0x02, RIDEV_REMOVE, NULL }; + RegisterRawInputDevices(&id, 1, sizeof(id)); + return; } + + RECT clipRect; + GetClientRect(win->src.window, &clipRect); + ClientToScreen(win->src.window, (POINT*) &clipRect.left); + ClientToScreen(win->src.window, (POINT*) &clipRect.right); + ClipCursor(&clipRect); - RECT r = {rect.x, rect.y, rect.x + rect.w, rect.y + rect.h}; - ClipCursor(&r); + const RAWINPUTDEVICE id = { 0x01, 0x02, 0, win->src.window }; + RegisterRawInputDevices(&id, 1, sizeof(id)); } RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) { @@ -3862,7 +4146,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ win->src.window = CreateWindowA(Class.lpszClassName, name, window_style, win->r.x, win->r.y, win->r.w, win->r.h + win->src.hOffset, 0, 0, inh, 0); if (args & RGFW_ALLOW_DND) { - win->src.winArgs |= RGFW_ALLOW_DND; + win->_winArgs |= RGFW_ALLOW_DND; RGFW_window_setDND(win, 1); } win->src.hdc = GetDC(win->src.window); @@ -4000,17 +4284,17 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ SET_ATTRIB(0, 0); - win->src.rSurf = (HGLRC)wglCreateContextAttribsARB(win->src.hdc, NULL, attribs); + win->src.ctx = (HGLRC)wglCreateContextAttribsARB(win->src.hdc, NULL, attribs); } else { fprintf(stderr, "Failed to create an accelerated OpenGL Context\n"); int pixel_format = ChoosePixelFormat(win->src.hdc, &pfd); SetPixelFormat(win->src.hdc, pixel_format, &pfd); - win->src.rSurf = wglCreateContext(win->src.hdc); + win->src.ctx = wglCreateContext(win->src.hdc); } - wglMakeCurrent(win->src.hdc, win->src.rSurf); + wglMakeCurrent(win->src.hdc, win->src.ctx); #endif } @@ -4026,7 +4310,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ if ((args & RGFW_NO_INIT_API) == 0) { ReleaseDC(win->src.window, win->src.hdc); win->src.hdc = GetDC(win->src.window); - wglMakeCurrent(win->src.hdc, win->src.rSurf); + wglMakeCurrent(win->src.hdc, win->src.ctx); } #endif @@ -4059,7 +4343,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ #ifdef RGFW_OPENGL else - wglShareLists(RGFW_root->src.rSurf, win->src.rSurf); + wglShareLists(RGFW_root->src.ctx, win->src.ctx); #endif return win; @@ -4089,19 +4373,19 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ return RGFW_AREA(GetDeviceCaps(GetDC(NULL), HORZRES), GetDeviceCaps(GetDC(NULL), VERTRES)); } - RGFW_vector RGFW_getGlobalMousePoint(void) { + RGFW_point RGFW_getGlobalMousePoint(void) { POINT p; GetCursorPos(&p); - return RGFW_VECTOR(p.x, p.y); + return RGFW_POINT(p.x, p.y); } - RGFW_vector RGFW_window_getMousePoint(RGFW_window* win) { + RGFW_point RGFW_window_getMousePoint(RGFW_window* win) { POINT p; GetCursorPos(&p); ScreenToClient(win->src.window, &p); - return RGFW_VECTOR(p.x, p.y); + return RGFW_POINT(p.x, p.y); } void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) { @@ -4147,6 +4431,8 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ }; static i32 RGFW_checkXInput(RGFW_window* win, RGFW_Event* e) { + RGFW_UNUSED(win) + size_t i; for (i = 0; i < 4; i++) { XINPUT_KEYSTROKE keystroke; @@ -4166,7 +4452,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ // RGFW_jsButtonPressed + 1 = RGFW_jsButtonReleased e->type = RGFW_jsButtonPressed + !(keystroke.Flags & XINPUT_KEYSTROKE_KEYDOWN); e->button = RGFW_xinput2RGFW[keystroke.VirtualKey - 0x5800]; - win->src.jsPressed[i][e->button] = !(keystroke.Flags & XINPUT_KEYSTROKE_KEYDOWN); + RGFW_jsPressed[i][e->button] = !(keystroke.Flags & XINPUT_KEYSTROKE_KEYDOWN); return 1; } @@ -4197,8 +4483,8 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ } e->axisesCount = 2; - RGFW_vector axis1 = RGFW_VECTOR(state.Gamepad.sThumbLX, state.Gamepad.sThumbLY); - RGFW_vector axis2 = RGFW_VECTOR(state.Gamepad.sThumbRX, state.Gamepad.sThumbRY); + RGFW_point axis1 = RGFW_POINT(state.Gamepad.sThumbLX, state.Gamepad.sThumbLY); + RGFW_point axis2 = RGFW_POINT(state.Gamepad.sThumbRX, state.Gamepad.sThumbRY); if (axis1.x != e->axis[0].x || axis1.y != e->axis[0].y || axis2.x != e->axis[1].x || axis2.y != e->axis[1].y) { e->type = RGFW_jsAxisMove; @@ -4216,6 +4502,16 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ return 0; } + void RGFW_stopCheckEvents(void) { + PostMessageW(RGFW_root->src.window, WM_NULL, 0, 0); + } + + void RGFW_window_eventWait(RGFW_window* win, i32 waitMS) { + RGFW_UNUSED(win); + + MsgWaitForMultipleObjects(0, NULL, FALSE, (DWORD) (waitMS * 1e3), QS_ALLINPUT); + } + RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) { assert(win != NULL); @@ -4314,7 +4610,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ case WM_MOUSELEAVE: win->event.type = RGFW_mouseLeave; - win->src.winArgs |= RGFW_MOUSE_LEFT; + win->_winArgs |= RGFW_MOUSE_LEFT; RGFW_mouseNotifyCallBack(win, win->event.point, 0); break; @@ -4380,40 +4676,60 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ } case WM_MOUSEMOVE: + if ((win->_winArgs & RGFW_HOLD_MOUSE)) + break; + win->event.type = RGFW_mousePosChanged; win->event.point.x = GET_X_LPARAM(msg.lParam); win->event.point.y = GET_Y_LPARAM(msg.lParam); - + RGFW_mousePosCallback(win, win->event.point); - if (win->src.winArgs & RGFW_MOUSE_LEFT) { - win->src.winArgs ^= RGFW_MOUSE_LEFT; + if (win->_winArgs & RGFW_MOUSE_LEFT) { + win->_winArgs ^= RGFW_MOUSE_LEFT; win->event.type = RGFW_mouseEnter; RGFW_mouseNotifyCallBack(win, win->event.point, 1); } break; + case WM_INPUT: { + if (!(win->_winArgs & RGFW_HOLD_MOUSE)) + break; + + unsigned size = sizeof(RAWINPUT); + static RAWINPUT raw[sizeof(RAWINPUT)]; + GetRawInputData((HRAWINPUT)msg.lParam, RID_INPUT, raw, &size, sizeof(RAWINPUTHEADER)); + + if (raw->header.dwType != RIM_TYPEMOUSE || (raw->data.mouse.lLastX == 0 && raw->data.mouse.lLastY == 0) ) + break; + + win->event.type = RGFW_mousePosChanged; + win->event.point.x = -raw->data.mouse.lLastX; + win->event.point.y = -raw->data.mouse.lLastY; + break; + } + case WM_LBUTTONDOWN: win->event.button = RGFW_mouseLeft; - RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button]; - RGFW_mouseButtons[win->event.button] = 1; + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + RGFW_mouseButtons[win->event.button].current = 1; win->event.type = RGFW_mouseButtonPressed; RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); break; case WM_RBUTTONDOWN: win->event.button = RGFW_mouseRight; win->event.type = RGFW_mouseButtonPressed; - RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button]; - RGFW_mouseButtons[win->event.button] = 1; + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + RGFW_mouseButtons[win->event.button].current = 1; RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); break; case WM_MBUTTONDOWN: win->event.button = RGFW_mouseMiddle; win->event.type = RGFW_mouseButtonPressed; - RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button]; - RGFW_mouseButtons[win->event.button] = 1; + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + RGFW_mouseButtons[win->event.button].current = 1; RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); break; @@ -4423,8 +4739,8 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ else win->event.button = RGFW_mouseScrollDown; - RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button]; - RGFW_mouseButtons[win->event.button] = 1; + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + RGFW_mouseButtons[win->event.button].current = 1; win->event.scroll = (SHORT) HIWORD(msg.wParam) / (double) WHEEL_DELTA; @@ -4437,24 +4753,24 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ win->event.button = RGFW_mouseLeft; win->event.type = RGFW_mouseButtonReleased; - RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button]; - RGFW_mouseButtons[win->event.button] = 0; + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + RGFW_mouseButtons[win->event.button].current = 0; RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0); break; case WM_RBUTTONUP: win->event.button = RGFW_mouseRight; win->event.type = RGFW_mouseButtonReleased; - RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button]; - RGFW_mouseButtons[win->event.button] = 0; + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + RGFW_mouseButtons[win->event.button].current = 0; RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0); break; case WM_MBUTTONUP: win->event.button = RGFW_mouseMiddle; win->event.type = RGFW_mouseButtonReleased; - RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button]; - RGFW_mouseButtons[win->event.button] = 0; + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + RGFW_mouseButtons[win->event.button].current = 0; RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0); break; @@ -4786,7 +5102,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ #endif #ifdef RGFW_OPENGL - wglDeleteContext((HGLRC) win->src.rSurf); /* delete opengl context */ + wglDeleteContext((HGLRC) win->src.ctx); /* delete opengl context */ #endif DeleteDC(win->src.hdc); /* delete device context */ DestroyWindow(win->src.window); /* delete window */ @@ -4810,7 +5126,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ RGFW_FREE(win); } - void RGFW_window_move(RGFW_window* win, RGFW_vector v) { + void RGFW_window_move(RGFW_window* win, RGFW_point v) { assert(win != NULL); win->r.x = v.x; @@ -4965,10 +5281,10 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ assert(win != NULL); RGFW_UNUSED(file) - return win->src.joystickCount - 1; + return RGFW_joystickCount - 1; } - void RGFW_window_moveMouse(RGFW_window* win, RGFW_vector p) { + void RGFW_window_moveMouse(RGFW_window* win, RGFW_point p) { assert(win != NULL); SetCursorPos(p.x, p.y); @@ -4977,7 +5293,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ #ifdef RGFW_OPENGL void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) { assert(win != NULL); - wglMakeCurrent(win->src.hdc, (HGLRC) win->src.rSurf); + wglMakeCurrent(win->src.hdc, (HGLRC) win->src.ctx); } #endif @@ -5017,7 +5333,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ /* clear the window*/ - if (!(win->src.winArgs & RGFW_NO_CPU_RENDER)) { + if (!(win->_winArgs & RGFW_NO_CPU_RENDER)) { #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) #ifdef RGFW_OSMESA RGFW_OSMesa_reorganize(); @@ -5029,7 +5345,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ #endif } - if (!(win->src.winArgs & RGFW_NO_GPU_RENDER)) { + if (!(win->_winArgs & RGFW_NO_GPU_RENDER)) { #ifdef RGFW_EGL eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface); #elif defined(RGFW_OPENGL) @@ -5161,8 +5477,18 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ #define objc_msgSend_void_id ((void (*)(id, SEL, id))objc_msgSend) #define objc_msgSend_uint ((NSUInteger (*)(id, SEL))objc_msgSend) #define objc_msgSend_void_bool ((void (*)(id, SEL, BOOL))objc_msgSend) +#define objc_msgSend_bool_void ((BOOL (*)(id, SEL))objc_msgSend) #define objc_msgSend_void_SEL ((void (*)(id, SEL, SEL))objc_msgSend) #define objc_msgSend_id ((id (*)(id, SEL))objc_msgSend) +#define objc_msgSend_id_id ((id (*)(id, SEL, id))objc_msgSend) +#define objc_msgSend_id_bool ((BOOL (*)(id, SEL, id))objc_msgSend) +#define objc_msgSend_int ((id (*)(id, SEL, int))objc_msgSend) +#define objc_msgSend_arr ((id (*)(id, SEL, int))objc_msgSend) +#define objc_msgSend_ptr ((id (*)(id, SEL, void*))objc_msgSend) +#define objc_msgSend_class ((id (*)(Class, SEL))objc_msgSend) +#define objc_msgSend_class_char ((id (*)(Class, SEL, char*))objc_msgSend) + + NSApplication* NSApp = NULL; void NSRelease(id obj) { objc_msgSend_void(obj, sel_registerName("release")); @@ -5270,9 +5596,9 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ #define NS_OPENGL_ENUM_DEPRECATED(minVers, maxVers) API_AVAILABLE(macos(minVers)) typedef NS_ENUM(NSInteger, NSOpenGLContextParameter) { NSOpenGLContextParameterSwapInterval NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 222, /* 1 param. 0 -> Don't sync, 1 -> Sync to vertical retrace */ - NSOpenGLContextParameterSurfaceOrder NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 235, /* 1 param. 1 -> Above Window (default), -1 -> Below Window */ - NSOpenGLContextParameterSurfaceOpacity NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 236, /* 1 param. 1-> Surface is opaque (default), 0 -> non-opaque */ - NSOpenGLContextParameterSurfaceBackingSize NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 304, /* 2 params. Width/height of surface backing size */ + NSOpenGLContextParametectxaceOrder NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 235, /* 1 param. 1 -> Above Window (default), -1 -> Below Window */ + NSOpenGLContextParametectxaceOpacity NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 236, /* 1 param. 1-> Surface is opaque (default), 0 -> non-opaque */ + NSOpenGLContextParametectxaceBackingSize NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 304, /* 2 params. Width/height of surface backing size */ NSOpenGLContextParameterReclaimResources NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 308, /* 0 params. */ NSOpenGLContextParameterCurrentRendererID NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 309, /* 1 param. Retrieves the current renderer ID */ NSOpenGLContextParameterGPUVertexProcessing NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 310, /* 1 param. Currently processing vertices with GPU (get) */ @@ -5284,7 +5610,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ NSOpenGLContextParameterSwapRectangleEnable API_DEPRECATED("", macos(10.0, 10.14)) = 201, /* Enable or disable the swap rectangle */ NSOpenGLContextParameterRasterizationEnable API_DEPRECATED("", macos(10.0, 10.14)) = 221, /* Enable or disable all rasterization */ NSOpenGLContextParameterStateValidation API_DEPRECATED("", macos(10.0, 10.14)) = 301, /* Validate state for multi-screen functionality */ - NSOpenGLContextParameterSurfaceSurfaceVolatile API_DEPRECATED("", macos(10.0, 10.14)) = 306, /* 1 param. Surface volatile state */ + NSOpenGLContextParametectxaceSurfaceVolatile API_DEPRECATED("", macos(10.0, 10.14)) = 306, /* 1 param. Surface volatile state */ }; @@ -5498,7 +5824,6 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ NSDragOperation draggingEntered(id self, SEL sel, id sender) { RGFW_UNUSED(sender); RGFW_UNUSED(self); RGFW_UNUSED(sel); - printf("hi\n"); return NSDragOperationCopy; } NSDragOperation draggingUpdated(id self, SEL sel, id sender) { @@ -5507,10 +5832,10 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ RGFW_window* win = NULL; object_getInstanceVariable(self, "RGFW_window", (void*)&win); if (win == NULL) - return true; + return 0; - if (!(win->src.winArgs & RGFW_ALLOW_DND)) { - return false; + if (!(win->_winArgs & RGFW_ALLOW_DND)) { + return 0; } win->event.type = RGFW_dnd_init; @@ -5518,7 +5843,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(sender, sel_registerName("draggingLocation")); - win->event.point = RGFW_VECTOR((u32) p.x, (u32) (win->r.h - p.y)); + win->event.point = RGFW_POINT((u32) p.x, (u32) (win->r.h - p.y)); RGFW_dndInitCallback(win, win->event.point); return NSDragOperationCopy; @@ -5529,7 +5854,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ if (win == NULL) return true; - if (!(win->src.winArgs & RGFW_ALLOW_DND)) { + if (!(win->_winArgs & RGFW_ALLOW_DND)) { return false; } @@ -5544,44 +5869,56 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ RGFW_window* win = NULL; object_getInstanceVariable(self, "RGFW_window", (void*)&win); - if (win == NULL) - return true; - //NSWindow* window = objc_msgSend_id(sender, sel_registerName("draggingDestinationWindow")); - u32 i; - bool found = 0; + if (win == NULL) + return false; + + // NSPasteboard* pasteBoard = objc_msgSend_id(sender, sel_registerName("draggingPasteboard")); - if (!found) - i = 0; + ///////////////////////////// + id pasteBoard = objc_msgSend_id(sender, sel_registerName("draggingPasteboard")); - Class array[] = { objc_getClass("NSURL"), NULL }; - NSPasteboard* pasteBoard = objc_msgSend_id(sender, sel_registerName("draggingPasteboard")); - - char** droppedFiles = (char**) NSPasteboard_readObjectsForClasses(pasteBoard, array, 1, NULL); + // Get the types of data available on the pasteboard + id types = objc_msgSend_id(pasteBoard, sel_registerName("types")); + + // Get the string type for file URLs + id fileURLsType = objc_msgSend_class_char(objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), "NSFilenamesPboardType"); + + // Check if the pasteboard contains file URLs + if (objc_msgSend_id_bool(types, sel_registerName("containsObject:"), fileURLsType) == 0) { + #ifdef RGFW_DEBUG + printf("No files found on the pasteboard.\n"); + #endif - win->event.droppedFilesCount = si_array_len(droppedFiles); + return 0; + } - u32 y; + id fileURLs = objc_msgSend_id_id(pasteBoard, sel_registerName("propertyListForType:"), fileURLsType); + int count = ((int (*)(id, SEL))objc_msgSend)(fileURLs, sel_registerName("count")); - for (y = 0; y < win->event.droppedFilesCount; y++) { - strncpy(win->event.droppedFiles[y], droppedFiles[y], RGFW_MAX_PATH); + if (count == 0) + return 0; - win->event.droppedFiles[y][RGFW_MAX_PATH - 1] = '\0'; + for (int i = 0; i < count; i++) { + id fileURL = objc_msgSend_arr(fileURLs, sel_registerName("objectAtIndex:"), i); + const char *filePath = ((const char* (*)(id, SEL))objc_msgSend)(fileURL, sel_registerName("UTF8String")); + // printf("File: %s\n", filePath); + strncpy(win->event.droppedFiles[i], filePath, RGFW_MAX_PATH); + win->event.droppedFiles[i][RGFW_MAX_PATH - 1] = '\0'; } + win->event.droppedFilesCount = count; win->event.type = RGFW_dnd; win->src.dndPassed = 0; - + NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(sender, sel_registerName("draggingLocation")); - win->event.point = RGFW_VECTOR((u32) p.x, (u32) (win->r.h - p.y)); - + win->event.point = RGFW_POINT((u32) p.x, (u32) (win->r.h - p.y)); + RGFW_dndCallback(win, win->event.droppedFiles, win->event.droppedFilesCount); - return true; + + return false; } - - NSApplication* NSApp = NULL; - static void NSMoveToResourceDir(void) { /* sourced from glfw */ char resourcesPath[255]; @@ -5661,8 +5998,8 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ win->buffer = RGFW_MALLOC(RGFW_bufferSize.w * RGFW_bufferSize.h * 4); #ifdef RGFW_OSMESA - win->src.rSurf = OSMesaCreateContext(OSMESA_RGBA, NULL); - OSMesaMakeCurrent(win->src.rSurf, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h); + win->src.ctx = OSMesaCreateContext(OSMESA_RGBA, NULL); + OSMesaMakeCurrent(win->src.ctx, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h); #endif #else RGFW_UNUSED(win); /* if buffer rendering is not being used */ @@ -5684,6 +6021,10 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ si_func_to_SEL("NSWindow", acceptsFirstResponder); si_func_to_SEL("NSWindow", performKeyEquivalent); + // RR Create an autorelease pool + id pool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc")); + pool = objc_msgSend_id(pool, sel_registerName("init")); + if (NSApp == NULL) { NSApp = objc_msgSend_id((id)objc_getClass("NSApplication"), sel_registerName("sharedApplication")); @@ -5738,7 +6079,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ win->src.view = NSOpenGLView_initWithFrame((NSRect){{0, 0}, {win->r.w, win->r.h}}, format); objc_msgSend_void(win->src.view, sel_registerName("prepareOpenGL")); - win->src.rSurf = objc_msgSend_id(win->src.view, sel_registerName("openGLContext")); + win->src.ctx = objc_msgSend_id(win->src.view, sel_registerName("openGLContext")); } else #endif { @@ -5755,14 +6096,14 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ #ifdef RGFW_OPENGL if ((args & RGFW_NO_INIT_API) == 0) - objc_msgSend_void(win->src.rSurf, sel_registerName("makeCurrentContext")); + objc_msgSend_void(win->src.ctx, sel_registerName("makeCurrentContext")); #endif if (args & RGFW_TRANSPARENT_WINDOW) { #ifdef RGFW_OPENGL if ((args & RGFW_NO_INIT_API) == 0) { i32 opacity = 0; #define NSOpenGLCPSurfaceOpacity 236 - NSOpenGLContext_setValues(win->src.rSurf, &opacity, NSOpenGLCPSurfaceOpacity); + NSOpenGLContext_setValues(win->src.ctx, &opacity, NSOpenGLCPSurfaceOpacity); } #endif @@ -5816,7 +6157,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ objc_msgSend_void_id(win->src.window, sel_registerName("setDelegate:"), delegate); if (args & RGFW_ALLOW_DND) { - win->src.winArgs |= RGFW_ALLOW_DND; + win->_winArgs |= RGFW_ALLOW_DND; NSPasteboardType types[] = {NSPasteboardTypeURL, NSPasteboardTypeFileURL, NSPasteboardTypeString}; NSregisterForDraggedTypes(win->src.window, types, 3); @@ -5850,7 +6191,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ if (!border) { storeType = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable; } - if (!(win->src.winArgs & RGFW_NO_RESIZE)) { + if (!(win->_winArgs & RGFW_NO_RESIZE)) { storeType |= NSWindowStyleMaskResizable; } @@ -5868,20 +6209,20 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ return RGFW_AREA(CGDisplayPixelsWide(display), CGDisplayPixelsHigh(display)); } - RGFW_vector RGFW_getGlobalMousePoint(void) { + RGFW_point RGFW_getGlobalMousePoint(void) { assert(RGFW_root != NULL); CGEventRef e = CGEventCreate(NULL); CGPoint point = CGEventGetLocation(e); CFRelease(e); - return RGFW_VECTOR((u32) point.x, (u32) point.y); /* the point is loaded during event checks */ + return RGFW_POINT((u32) point.x, (u32) point.y); /* the point is loaded during event checks */ } - RGFW_vector RGFW_window_getMousePoint(RGFW_window* win) { + RGFW_point RGFW_window_getMousePoint(RGFW_window* win) { NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(win->src.window, sel_registerName("mouseLocationOutsideOfEventStream")); - return RGFW_VECTOR((u32) p.x, (u32) (win->r.h - p.y)); + return RGFW_POINT((u32) p.x, (u32) (win->r.h - p.y)); } u32 RGFW_keysPressed[10]; /*10 keys at a time*/ @@ -5979,36 +6320,80 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ NSEventModifierFlagNumericPad = 1 << 21 } NSEventModifierFlags; + void RGFW_stopCheckEvents(void) { + id eventPool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc")); + eventPool = objc_msgSend_id(eventPool, sel_registerName("init")); + + NSEvent* e = (NSEvent*) ((id(*)(id, SEL, NSEventType, NSPoint, NSEventModifierFlags, void*, NSInteger, void**, short, NSInteger, NSInteger))objc_msgSend) + (NSApp, sel_registerName("otherEventWithType:location:modifierFlags:timestamp:windowNumber:context:subtype:data1:data2:"), + NSEventTypeApplicationDefined, (NSPoint){0, 0}, 0, 0, 0, NULL, 0, 0, 0); + + ((void (*)(id, SEL, id, bool))objc_msgSend) + (NSApp, sel_registerName("postEvent:atStart:"), e, 1); + + objc_msgSend_bool_void(eventPool, sel_registerName("drain")); + } + + void RGFW_window_eventWait(RGFW_window* win, i32 waitMS) { + RGFW_UNUSED(win); + + id eventPool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc")); + eventPool = objc_msgSend_id(eventPool, sel_registerName("init")); + + void* date = (void*) ((id(*)(id, SEL, double))objc_msgSend) + (objc_getClass("NSDate"), sel_registerName("dateWithTimeIntervalSinceNow:"), waitMS); + + NSEvent* e = (NSEvent*) ((id(*)(id, SEL, NSEventMask, void*, NSString*, bool))objc_msgSend) + (NSApp, sel_registerName("nextEventMatchingMask:untilDate:inMode:dequeue:"), + ULONG_MAX, date, NSString_stringWithUTF8String("kCFRunLoopDefaultMode"), true); + + + if (e) { + objc_msgSend_void_id(NSApp, sel_registerName("sendEvent:"), e); + } + + objc_msgSend_bool_void(eventPool, sel_registerName("drain")); + } + RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) { assert(win != NULL); if (win->event.type == RGFW_quit) return NULL; - + if ((win->event.type == RGFW_dnd || win->event.type == RGFW_dnd_init) && win->src.dndPassed == 0) { win->src.dndPassed = 1; return &win->event; } + id eventPool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc")); + eventPool = objc_msgSend_id(eventPool, sel_registerName("init")); + static void* eventFunc = NULL; - if (eventFunc == NULL) + if (eventFunc == NULL) eventFunc = sel_registerName("nextEventMatchingMask:untilDate:inMode:dequeue:"); - + if ((win->event.type == RGFW_windowMoved || win->event.type == RGFW_windowResized || win->event.type == RGFW_windowRefresh) && win->event.keyCode != 120) { win->event.keyCode = 120; + objc_msgSend_bool_void(eventPool, sel_registerName("drain")); return &win->event; } + void* date = NULL; + NSEvent* e = (NSEvent*) ((id(*)(id, SEL, NSEventMask, void*, NSString*, bool))objc_msgSend) - (NSApp, eventFunc, ULONG_MAX, NULL, NSString_stringWithUTF8String("kCFRunLoopDefaultMode"), true); + (NSApp, eventFunc, ULONG_MAX, date, NSString_stringWithUTF8String("kCFRunLoopDefaultMode"), true); - if (e == NULL) + if (e == NULL) { + objc_msgSend_bool_void(eventPool, sel_registerName("drain")); return NULL; - + } + if (objc_msgSend_id(e, sel_registerName("window")) != win->src.window) { ((void (*)(id, SEL, id, bool))objc_msgSend) (NSApp, sel_registerName("postEvent:atStart:"), e, 0); - + + objc_msgSend_bool_void(eventPool, sel_registerName("drain")); return NULL; } @@ -6020,13 +6405,13 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ win->event.droppedFilesCount = 0; win->event.type = 0; - + switch (objc_msgSend_uint(e, sel_registerName("type"))) { case NSEventTypeMouseEntered: { win->event.type = RGFW_mouseEnter; NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(e, sel_registerName("locationInWindow")); - win->event.point = RGFW_VECTOR((u32) p.x, (u32) (win->r.h - p.y)); + win->event.point = RGFW_POINT((u32) p.x, (u32) (win->r.h - p.y)); RGFW_mouseNotifyCallBack(win, win->event.point, 1); break; } @@ -6110,15 +6495,13 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ case NSEventTypeMouseMoved: win->event.type = RGFW_mousePosChanged; NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(e, sel_registerName("locationInWindow")); - win->event.point = RGFW_VECTOR((u32) p.x, (u32) (win->r.h - p.y)); + win->event.point = RGFW_POINT((u32) p.x, (u32) (win->r.h - p.y)); - if ((win->src.winArgs & RGFW_HOLD_MOUSE)) { + if ((win->_winArgs & RGFW_HOLD_MOUSE)) { p.x = ((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(e, sel_registerName("deltaX")); p.y = ((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(e, sel_registerName("deltaY")); - p.x = ((win->r.w / 2)) + p.x; - p.y = ((win->r.h / 2)) + p.y; - win->event.point = RGFW_VECTOR((u32) p.x, (u32) (p.y)); + win->event.point = RGFW_POINT((u32) p.x, (u32) (p.y)); } RGFW_mousePosCallback(win, win->event.point); @@ -6127,47 +6510,47 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ case NSEventTypeLeftMouseDown: win->event.button = RGFW_mouseLeft; win->event.type = RGFW_mouseButtonPressed; - RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button]; - RGFW_mouseButtons[win->event.button] = 1; + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + RGFW_mouseButtons[win->event.button].current = 1; RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); break; case NSEventTypeOtherMouseDown: win->event.button = RGFW_mouseMiddle; win->event.type = RGFW_mouseButtonPressed; - RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button]; - RGFW_mouseButtons[win->event.button] = 1; + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + RGFW_mouseButtons[win->event.button].current = 1; RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); break; case NSEventTypeRightMouseDown: win->event.button = RGFW_mouseRight; win->event.type = RGFW_mouseButtonPressed; - RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button]; - RGFW_mouseButtons[win->event.button] = 1; + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + RGFW_mouseButtons[win->event.button].current = 1; RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); break; case NSEventTypeLeftMouseUp: win->event.button = RGFW_mouseLeft; win->event.type = RGFW_mouseButtonReleased; - RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button]; - RGFW_mouseButtons[win->event.button] = 0; + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + RGFW_mouseButtons[win->event.button].current = 0; RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0); break; case NSEventTypeOtherMouseUp: win->event.button = RGFW_mouseMiddle; - RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button]; - RGFW_mouseButtons[win->event.button] = 0; + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + RGFW_mouseButtons[win->event.button].current = 0; win->event.type = RGFW_mouseButtonReleased; RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0); break; case NSEventTypeRightMouseUp: win->event.button = RGFW_mouseRight; - RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button]; - RGFW_mouseButtons[win->event.button] = 0; + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + RGFW_mouseButtons[win->event.button].current = 0; win->event.type = RGFW_mouseButtonReleased; RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0); break; @@ -6182,8 +6565,8 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ win->event.button = RGFW_mouseScrollDown; } - RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button]; - RGFW_mouseButtons[win->event.button] = 1; + RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current; + RGFW_mouseButtons[win->event.button].current = 1; win->event.scroll = deltaY; @@ -6197,12 +6580,14 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ } objc_msgSend_void_id(NSApp, sel_registerName("sendEvent:"), e); - + ((void(*)(id, SEL))objc_msgSend)(NSApp, sel_registerName("updateWindows")); + + objc_msgSend_bool_void(eventPool, sel_registerName("drain")); return &win->event; } - void RGFW_window_move(RGFW_window* win, RGFW_vector v) { + void RGFW_window_move(RGFW_window* win, RGFW_point v) { assert(win != NULL); win->r.x = v.x; @@ -6343,14 +6728,16 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ objc_msgSend_void(mouse, sel_registerName("set")); } - void RGFW_clipCursor(RGFW_rect r) { + void RGFW_captureCursor(RGFW_window* win, RGFW_rect r) { + RGFW_UNUSED(win) + CGWarpMouseCursorPosition(CGPointMake(r.x + (r.w / 2), r.y + (r.h / 2))); CGAssociateMouseAndMouseCursorPosition((!r.x && !r.y && r.w && !r.h)); } - void RGFW_window_moveMouse(RGFW_window* win, RGFW_vector v) { + void RGFW_window_moveMouse(RGFW_window* win, RGFW_point v) { RGFW_UNUSED(win); - + CGWarpMouseCursorPosition(CGPointMake(v.x, v.y)); } @@ -6477,13 +6864,13 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ assert(win != NULL); - return win->src.joystickCount - 1; + return RGFW_joystickCount - 1; } #ifdef RGFW_OPENGL void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) { assert(win != NULL); - objc_msgSend_void(win->src.rSurf, sel_registerName("makeCurrentContext")); + objc_msgSend_void(win->src.ctx, sel_registerName("makeCurrentContext")); } #endif @@ -6492,13 +6879,35 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ assert(win != NULL); #if defined(RGFW_OPENGL) - NSOpenGLContext_setValues(win->src.rSurf, &swapInterval, 222); + NSOpenGLContext_setValues(win->src.ctx, &swapInterval, 222); #endif win->fpsCap = (swapInterval == 1) ? 0 : swapInterval; } #endif + // Function to create a CGImageRef from an array of bytes + CGImageRef createImageFromBytes(unsigned char *buffer, int width, int height) + { + // Define color space + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); + // Create bitmap context + CGContextRef context = CGBitmapContextCreate( + buffer, + width, height, + 8, + RGFW_bufferSize.w * 4, + colorSpace, + kCGImageAlphaPremultipliedLast); + // Create image from bitmap context + CGImageRef image = CGBitmapContextCreateImage(context); + // Release the color space and context + CGColorSpaceRelease(colorSpace); + CGContextRelease(context); + + return image; + } + void RGFW_window_swapBuffers(RGFW_window* win) { assert(win != NULL); @@ -6506,13 +6915,12 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ /* clear the window*/ - if (!(win->src.winArgs & RGFW_NO_CPU_RENDER)) { + if (!(win->_winArgs & RGFW_NO_CPU_RENDER)) { #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) #ifdef RGFW_OSMESA RGFW_OSMesa_reorganize(); #endif - RGFW_area area = RGFW_bufferSize; void* view = NSWindow_contentView(win->src.window); void* layer = objc_msgSend_id(view, sel_registerName("layer")); @@ -6520,25 +6928,29 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ sel_registerName("setFrame:"), (NSRect){{0, 0}, {win->r.w, win->r.h}}); - NSBitmapImageRep* rep = NSBitmapImageRep_initWithBitmapData( - &win->buffer, win->r.w, win->r.h, 8, 4, true, false, - "NSDeviceRGBColorSpace", 0, - area.w * 4, 32 - ); - id image = NSAlloc((id)objc_getClass("NSImage")); - NSImage_addRepresentation(image, rep); - objc_msgSend_void_id(layer, sel_registerName("setContents:"), (id) image); - - release(image); - release(rep); + CGImageRef image = createImageFromBytes(win->buffer, win->r.w, win->r.h); + // Get the current graphics context + id graphicsContext = objc_msgSend_class(objc_getClass("NSGraphicsContext"), sel_registerName("currentContext")); + // Get the CGContext from the current NSGraphicsContext + id cgContext = objc_msgSend_id(graphicsContext, sel_registerName("graphicsPort")); + // Draw the image in the context + NSRect bounds = (NSRect){{0,0}, {win->r.w, win->r.h}}; + CGContextDrawImage((void*)cgContext, *(CGRect*)&bounds, image); + // Flush the graphics context to ensure the drawing is displayed + objc_msgSend_id(graphicsContext, sel_registerName("flushGraphics")); + + objc_msgSend_void_id(layer, sel_registerName("setContents:"), (id)image); + objc_msgSend_id(layer, sel_registerName("setNeedsDisplay")); + + CGImageRelease(image); #endif } - if (!(win->src.winArgs & RGFW_NO_GPU_RENDER)) { + if (!(win->_winArgs & RGFW_NO_GPU_RENDER)) { #ifdef RGFW_EGL eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface); #elif defined(RGFW_OPENGL) - objc_msgSend_void(win->src.rSurf, sel_registerName("flushBuffer")); + objc_msgSend_void(win->src.ctx, sel_registerName("flushBuffer")); #endif } @@ -6559,12 +6971,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ RGFW_FREE(win->event.droppedFiles); } #endif - - if (RGFW_root == win) { - objc_msgSend_void_id(NSApp, sel_registerName("terminate:"), (id) win->src.window); - NSApp = NULL; - } - + #ifdef RGFW_BUFFER release(win->src.bitmap); release(win->src.image); @@ -6597,8 +7004,549 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ End of MaOS defines */ -/* unix (macOS, linux) only stuff */ -#if defined(RGFW_X11) || defined(RGFW_MACOS) +/* + Start of Web ASM defines +*/ + +#ifdef RGFW_WEBASM + + +#define RGFW_jsButtonPressed 7 /*!< a joystick button was pressed */ +#define RGFW_jsButtonReleased 8 /*!< a joystick button was released */ +#define RGFW_jsAxisMove 9 /*!< an axis of a joystick was moved*/ + +#define RGFW_mouseEnter 14 /* mouse entered the window */ +#define RGFW_mouseLeave 15 /* mouse left the window */ + +RGFW_Event RGFW_events[20]; +size_t RGFW_eventLen = 0; + +EM_BOOL on_keydown(int eventType, const EmscriptenKeyboardEvent* e, void* userData) { + RGFW_UNUSED(eventType); RGFW_UNUSED(userData); + + RGFW_events[RGFW_eventLen].type = RGFW_keyPressed; + memcpy(RGFW_events[RGFW_eventLen].keyName, e->key, 16); + RGFW_events[RGFW_eventLen].keyCode = RGFW_apiKeyCodeToRGFW(e->keyCode); + RGFW_events[RGFW_eventLen].lockState = 0; + RGFW_eventLen++; + + RGFW_keyboard[RGFW_apiKeyCodeToRGFW(e->keyCode)].prev = RGFW_keyboard[RGFW_apiKeyCodeToRGFW(e->keyCode)].current; + RGFW_keyboard[RGFW_apiKeyCodeToRGFW(e->keyCode)].current = 1; + RGFW_keyCallback(RGFW_root, e->keyCode, RGFW_events[RGFW_eventLen].keyName, 0, 1); + + return EM_TRUE; +} + +EM_BOOL on_keyup(int eventType, const EmscriptenKeyboardEvent* e, void* userData) { + RGFW_UNUSED(eventType); RGFW_UNUSED(userData); + + RGFW_events[RGFW_eventLen].type = RGFW_keyReleased; + memcpy(RGFW_events[RGFW_eventLen].keyName, e->key, 16); + RGFW_events[RGFW_eventLen].keyCode = RGFW_apiKeyCodeToRGFW(e->keyCode); + RGFW_events[RGFW_eventLen].lockState = 0; + RGFW_eventLen++; + + RGFW_keyboard[RGFW_apiKeyCodeToRGFW(e->keyCode)].prev = RGFW_keyboard[RGFW_apiKeyCodeToRGFW(e->keyCode)].current; + RGFW_keyboard[RGFW_apiKeyCodeToRGFW(e->keyCode)].current = 0; + + RGFW_keyCallback(RGFW_root, e->keyCode, RGFW_events[RGFW_eventLen].keyName, 0, 0); + + return EM_TRUE; +} + +EM_BOOL on_resize(int eventType, const EmscriptenUiEvent* e, void* userData) { + RGFW_UNUSED(eventType); RGFW_UNUSED(userData); + + RGFW_events[RGFW_eventLen].type = RGFW_windowResized; + RGFW_eventLen++; + + RGFW_windowResizeCallback(RGFW_root, RGFW_RECT(0, 0, e->windowInnerWidth, e->windowInnerHeight)); + return EM_TRUE; +} + +EM_BOOL on_fullscreenchange(int eventType, const EmscriptenFullscreenChangeEvent* e, void* userData) { + RGFW_UNUSED(eventType); RGFW_UNUSED(userData); + + RGFW_events[RGFW_eventLen].type = RGFW_windowResized; + RGFW_eventLen++; + + RGFW_root->r = RGFW_RECT(0, 0, e->elementWidth, e->elementHeight); + RGFW_windowResizeCallback(RGFW_root, RGFW_root->r); + return EM_TRUE; +} + +EM_BOOL on_focusin(int eventType, const EmscriptenFocusEvent* e, void* userData) { + RGFW_UNUSED(eventType); RGFW_UNUSED(userData); RGFW_UNUSED(e); + + RGFW_events[RGFW_eventLen].type = RGFW_focusIn; + RGFW_eventLen++; + + RGFW_root->event.inFocus = 1; + RGFW_focusCallback(RGFW_root, 1); + return EM_TRUE; +} + +EM_BOOL on_focusout(int eventType, const EmscriptenFocusEvent* e, void* userData) { + RGFW_UNUSED(eventType); RGFW_UNUSED(userData); RGFW_UNUSED(e); + + RGFW_events[RGFW_eventLen].type = RGFW_focusOut; + RGFW_eventLen++; + + RGFW_root->event.inFocus = 0; + RGFW_focusCallback(RGFW_root, 0); + return EM_TRUE; +} + +EM_BOOL on_mousemove(int eventType, const EmscriptenMouseEvent* e, void* userData) { + RGFW_UNUSED(eventType); RGFW_UNUSED(userData); + + RGFW_events[RGFW_eventLen].type = RGFW_mousePosChanged; + + if ((RGFW_root->_winArgs & RGFW_HOLD_MOUSE)) { + RGFW_point p = RGFW_POINT(-e->movementX, -e->movementY); + RGFW_events[RGFW_eventLen].point = p; + } + else + RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->targetX, e->targetY); + RGFW_eventLen++; + + RGFW_mousePosCallback(RGFW_root, RGFW_events[RGFW_eventLen].point); + return EM_TRUE; +} + +EM_BOOL on_mousedown(int eventType, const EmscriptenMouseEvent* e, void* userData) { + RGFW_UNUSED(eventType); RGFW_UNUSED(userData); + + RGFW_events[RGFW_eventLen].type = RGFW_mouseButtonPressed; + RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->targetX, e->targetY); + RGFW_events[RGFW_eventLen].button = e->button + 1; + RGFW_events[RGFW_eventLen].scroll = 0; + + RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current; + RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current = 1; + + RGFW_mouseButtonCallback(RGFW_root, RGFW_events[RGFW_eventLen].button, RGFW_events[RGFW_eventLen].scroll, 1); + RGFW_eventLen++; + + return EM_TRUE; +} + +EM_BOOL on_mouseup(int eventType, const EmscriptenMouseEvent* e, void* userData) { + RGFW_UNUSED(eventType); RGFW_UNUSED(userData); + + RGFW_events[RGFW_eventLen].type = RGFW_mouseButtonReleased; + RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->targetX, e->targetY); + RGFW_events[RGFW_eventLen].button = e->button + 1; + RGFW_events[RGFW_eventLen].scroll = 0; + + RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current; + RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current = 0; + + RGFW_mouseButtonCallback(RGFW_root, RGFW_events[RGFW_eventLen].button, RGFW_events[RGFW_eventLen].scroll, 0); + RGFW_eventLen++; + return EM_TRUE; +} + +EM_BOOL on_wheel(int eventType, const EmscriptenWheelEvent* e, void* userData) { + RGFW_UNUSED(eventType); RGFW_UNUSED(userData); + + RGFW_events[RGFW_eventLen].type = RGFW_mouseButtonPressed; + RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->mouse.targetX, e->mouse.targetY); + RGFW_events[RGFW_eventLen].button = RGFW_mouseScrollUp + (e->deltaY < 0); + RGFW_events[RGFW_eventLen].scroll = e->deltaY; + + RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current; + RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current = 1; + + RGFW_mouseButtonCallback(RGFW_root, RGFW_events[RGFW_eventLen].button, RGFW_events[RGFW_eventLen].scroll, 1); + RGFW_eventLen++; + + return EM_TRUE; +} + +EM_BOOL on_touchstart(int eventType, const EmscriptenTouchEvent* e, void* userData) { + RGFW_UNUSED(eventType); RGFW_UNUSED(userData); + + RGFW_events[RGFW_eventLen].type = RGFW_mouseButtonPressed; + RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->touches[0].targetX, e->touches[0].targetY); + RGFW_events[RGFW_eventLen].button = 1; + RGFW_events[RGFW_eventLen].scroll = 0; + + + RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current; + RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current = 1; + + RGFW_mouseButtonCallback(RGFW_root, RGFW_events[RGFW_eventLen].button, RGFW_events[RGFW_eventLen].scroll, 1); + RGFW_eventLen++; + + return EM_TRUE; +} +EM_BOOL on_touchmove(int eventType, const EmscriptenTouchEvent* e, void* userData) { + RGFW_UNUSED(eventType); RGFW_UNUSED(userData); + + RGFW_events[RGFW_eventLen].type = RGFW_mousePosChanged; + RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->touches[0].targetX, e->touches[0].targetY); + + RGFW_mousePosCallback(RGFW_root, RGFW_events[RGFW_eventLen].point); + RGFW_eventLen++; + + return EM_TRUE; +} + +EM_BOOL on_touchend(int eventType, const EmscriptenTouchEvent* e, void* userData) { + RGFW_UNUSED(eventType); RGFW_UNUSED(userData); + + RGFW_events[RGFW_eventLen].type = RGFW_mouseButtonReleased; + RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->touches[0].targetX, e->touches[0].targetY); + RGFW_events[RGFW_eventLen].button = 1; + RGFW_events[RGFW_eventLen].scroll = 0; + + RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current; + RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current = 0; + + RGFW_mouseButtonCallback(RGFW_root, RGFW_events[RGFW_eventLen].button, RGFW_events[RGFW_eventLen].scroll, 0); + RGFW_eventLen++; + + return EM_TRUE; +} + +EM_BOOL on_touchcancel(int eventType, const EmscriptenTouchEvent* e, void* userData) { RGFW_UNUSED(eventType); RGFW_UNUSED(userData); RGFW_UNUSED(e); return EM_TRUE; } + + +b8 RGFW_stopCheckEvents_bool = RGFW_FALSE; +void RGFW_stopCheckEvents(void) { + RGFW_stopCheckEvents_bool = RGFW_TRUE; +} + +void RGFW_window_eventWait(RGFW_window* win, i32 waitMS) { + RGFW_UNUSED(win); + + u32 start = (u32)(((u64)RGFW_getTimeNS()) / 1e+6); + + while ((RGFW_eventLen == 0) && RGFW_stopCheckEvents_bool == RGFW_FALSE && + (waitMS < 0 || (RGFW_getTimeNS() / 1e+6) - start < waitMS) + ) { + emscripten_sleep(0); + } + + RGFW_stopCheckEvents_bool = RGFW_FALSE; +} + +RGFWDEF void RGFW_init_buffer(RGFW_window* win); +void RGFW_init_buffer(RGFW_window* win) { + #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) + if (RGFW_bufferSize.w == 0 && RGFW_bufferSize.h == 0) + RGFW_bufferSize = RGFW_getScreenSize(); + + win->buffer = RGFW_MALLOC(RGFW_bufferSize.w * RGFW_bufferSize.h * 4); + #ifdef RGFW_OSMESA + win->src.ctx = OSMesaCreateContext(OSMESA_RGBA, NULL); + OSMesaMakeCurrent(win->src.ctx, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h); + #endif + #else + RGFW_UNUSED(win); /* if buffer rendering is not being used */ + #endif +} + +RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) { + RGFW_UNUSED(name) + + RGFW_UNUSED(RGFW_initAttribs); + + RGFW_window* win = RGFW_window_basic_init(rect, args); + + EmscriptenWebGLContextAttributes attrs; + attrs.alpha = EM_TRUE; + attrs.depth = EM_TRUE; + attrs.stencil = RGFW_STENCIL; + attrs.antialias = RGFW_SAMPLES; + attrs.premultipliedAlpha = EM_TRUE; + attrs.preserveDrawingBuffer = EM_FALSE; + attrs.renderViaOffscreenBackBuffer = RGFW_AUX_BUFFERS; + attrs.failIfMajorPerformanceCaveat = EM_FALSE; + attrs.majorVersion = (RGFW_majorVersion == 0) ? 1 : RGFW_majorVersion; + attrs.minorVersion = RGFW_minorVersion; + + attrs.enableExtensionsByDefault = EM_TRUE; + attrs.explicitSwapControl = EM_TRUE; + + emscripten_webgl_init_context_attributes(&attrs); + win->src.ctx = emscripten_webgl_create_context("#canvas", &attrs); + emscripten_webgl_make_context_current(win->src.ctx); + + #ifdef LEGACY_GL_EMULATION + EM_ASM("Module.useWebGL = true; GLImmediate.init();"); + #endif + + emscripten_set_canvas_element_size("#canvas", rect.w, rect.h); + + /* load callbacks */ + emscripten_set_keydown_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, on_keydown); + emscripten_set_keyup_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, on_keyup); + emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, on_resize); + emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, NULL, EM_FALSE, on_fullscreenchange); + emscripten_set_mousemove_callback("#canvas", NULL, EM_FALSE, on_mousemove); + emscripten_set_touchstart_callback("#canvas", NULL, EM_FALSE, on_touchstart); + emscripten_set_touchend_callback("#canvas", NULL, EM_FALSE, on_touchend); + emscripten_set_touchmove_callback("#canvas", NULL, EM_FALSE, on_touchmove); + emscripten_set_touchcancel_callback("#canvas", NULL, EM_FALSE, on_touchcancel); + emscripten_set_mousedown_callback("#canvas", NULL, EM_FALSE, on_mousedown); + emscripten_set_mouseup_callback("#canvas", NULL, EM_FALSE, on_mouseup); + emscripten_set_wheel_callback("#canvas", NULL, EM_FALSE, on_wheel); + emscripten_set_focusin_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, on_focusin); + emscripten_set_focusout_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, on_focusout); + + RGFW_init_buffer(win); + glViewport(0, 0, rect.w, rect.h); + + RGFW_root = win; + + if (args & RGFW_HIDE_MOUSE) { + RGFW_window_showMouse(win, 0); + } + + if (args & RGFW_FULLSCREEN) { + RGFW_window_resize(win, RGFW_getScreenSize()); + } + + return win; +} + +RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) { + static u8 index = 0; + + if (index == 0) + RGFW_resetKey(); + + if (RGFW_eventLen == 0) + return NULL; + + RGFW_events[index].fps = win->event.fps; + RGFW_events[index].frameTime = win->event.frameTime; + RGFW_events[index].frameTime2 = win->event.frameTime2; + RGFW_events[index].inFocus = win->event.inFocus; + + win->event = RGFW_events[index]; + + RGFW_eventLen--; + + if (RGFW_eventLen) + index++; + else + index = 0; + + return &win->event; +} + +void RGFW_window_resize(RGFW_window* win, RGFW_area a) { + RGFW_UNUSED(win) + emscripten_set_canvas_element_size("#canvas", a.w, a.h); +} + +/* NOTE: I don't know if this is possible */ +void RGFW_window_moveMouse(RGFW_window* win, RGFW_point v) { RGFW_UNUSED(win); RGFW_UNUSED(v); } +/* this one might be possible but it looks iffy */ +void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels) { RGFW_UNUSED(win); RGFW_UNUSED(channels) RGFW_UNUSED(a) RGFW_UNUSED(image) } + +const char RGFW_CURSORS[11][12] = { + "default", + "default", + "text", + "crosshair", + "pointer", + "ew-resize", + "ns-resize", + "nwse-resize", + "nesw-resize", + "move", + "not-allowed" +}; + +void RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse) { + RGFW_UNUSED(win) + EM_ASM( { document.getElementById("canvas").style.cursor = UTF8ToString($0); }, RGFW_CURSORS[mouse]); +} + +void RGFW_window_setMouseDefault(RGFW_window* win) { + RGFW_window_setMouseStandard(win, RGFW_MOUSE_NORMAL); +} + +void RGFW_window_showMouse(RGFW_window* win, i8 show) { + if (show) + RGFW_window_setMouseDefault(win); + else + EM_ASM(document.getElementById('canvas').style.cursor = 'none';); +} + +RGFW_point RGFW_getGlobalMousePoint(void) { + RGFW_point point; + point.x = EM_ASM_INT({ + return window.mouseX || 0; + }); + point.y = EM_ASM_INT({ + return window.mouseY || 0; + }); + return point; +} + +void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) { + RGFW_UNUSED(win); + + EM_ASM_({ + var canvas = document.getElementById('canvas'); + if ($0) { + canvas.style.pointerEvents = 'none'; + } else { + canvas.style.pointerEvents = 'auto'; + } + }, passthrough); +} + +void RGFW_writeClipboard(const char* text, u32 textLen) { + RGFW_UNUSED(textLen) + EM_ASM({ navigator.clipboard.writeText(UTF8ToString($0)); }, text); +} + + +char* RGFW_readClipboard(size_t* size) { + /* + placeholder code for later + I'm not sure if this is possible do the the async stuff + */ + + if (size != NULL) + *size = 0; + + char* str = malloc(1); + str[0] = '\0'; + + return str; +} + +void RGFW_window_swapBuffers(RGFW_window* win) { + #ifdef RGFW_BUFFER + if (!(win->_winArgs & RGFW_NO_CPU_RENDER)) { + glEnable(GL_TEXTURE_2D); + + GLuint texture; + glGenTextures(1,&texture); + + //glPixelStorei( GL_PACK_ROW_LENGTH, RGFW_bufferSize.w); + //glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, RGFW_bufferSize.h); + + glBindTexture(GL_TEXTURE_2D,texture); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, RGFW_bufferSize.w, RGFW_bufferSize.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, win->buffer); + + float ratioX = ((float)win->r.w / (float)RGFW_bufferSize.w); + float ratioY = ((float)win->r.h / (float)RGFW_bufferSize.h); + + // Set up the viewport + glClear(GL_COLOR_BUFFER_BIT); + + glBegin(GL_TRIANGLES); + glTexCoord2f(0, ratioY); glColor3f(1, 1, 1); glVertex2f(-1, -1); + glTexCoord2f(0, 0); glColor3f(1, 1, 1); glVertex2f(-1, 1); + glTexCoord2f(ratioX, ratioY); glColor3f(1, 1, 1); glVertex2f(1, -1); + + glTexCoord2f(ratioX, 0); glColor3f(1, 1, 1); glVertex2f(1, 1); + glTexCoord2f(ratioX, ratioY); glColor3f(1, 1, 1); glVertex2f(1, -1); + glTexCoord2f(0, 0); glColor3f(1, 1, 1); glVertex2f(-1, 1); + glEnd(); + + glDeleteTextures(1, &texture); + } + #endif + + emscripten_webgl_commit_frame(); + + if (win->fpsCap == 0 || win->fpsCap < 100) { + emscripten_sleep(0); + } + + RGFW_window_checkFPS(win); +} + + +void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) { + emscripten_webgl_make_context_current(win->src.ctx); +} + +#ifndef RGFW_EGL +void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) { + win->fpsCap = (swapInterval == 1) ? 0 : swapInterval; +} +#endif + +void RGFW_window_close(RGFW_window* win) { + emscripten_webgl_destroy_context(win->src.ctx); + + free(win); +} + +int RGFW_innerWidth(void) { return EM_ASM_INT({ return window.innerWidth; }); } +int RGFW_innerHeight(void) { return EM_ASM_INT({ return window.innerHeight; }); } + +RGFW_area RGFW_getScreenSize(void) { + return RGFW_AREA(RGFW_innerWidth(), RGFW_innerHeight()); +} + +void* RGFW_getProcAddress(const char* procname) { + return emscripten_webgl_get_proc_address(procname); +} + +void RGFW_sleep(u64 milisecond) { + emscripten_sleep(milisecond); +} + +u64 RGFW_getTimeNS(void) { + return emscripten_get_now() * 1e+6; +} + +u64 RGFW_getTime(void) { + return emscripten_get_now() * 1000; +} + +void RGFW_captureCursor(RGFW_window* win, RGFW_rect r) { + RGFW_UNUSED(win) + if (!r.x && !r.y && !r.w && !r.h) { + emscripten_exit_pointerlock(); + return; + } + + emscripten_request_pointerlock("#canvas", 1); +} + +/* unsupported functions */ +RGFW_monitor* RGFW_getMonitors(void) { return NULL; } +RGFW_monitor RGFW_getPrimaryMonitor(void) { return (RGFW_monitor){}; } +void RGFW_window_move(RGFW_window* win, RGFW_point v) { RGFW_UNUSED(win) RGFW_UNUSED(v) } +void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) { RGFW_UNUSED(win) RGFW_UNUSED(a) } +void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) { RGFW_UNUSED(win) RGFW_UNUSED(a) } +void RGFW_window_minimize(RGFW_window* win) { RGFW_UNUSED(win)} +void RGFW_window_restore(RGFW_window* win) { RGFW_UNUSED(win) } +void RGFW_window_setBorder(RGFW_window* win, b8 border) { RGFW_UNUSED(win) RGFW_UNUSED(border) } +void RGFW_window_setDND(RGFW_window* win, b8 allow) { RGFW_UNUSED(win) RGFW_UNUSED(allow) } +void RGFW_window_setName(RGFW_window* win, char* name) { RGFW_UNUSED(win) RGFW_UNUSED(name) } +void RGFW_window_setIcon(RGFW_window* win, u8* icon, RGFW_area a, i32 channels) { RGFW_UNUSED(win) RGFW_UNUSED(icon) RGFW_UNUSED(a) RGFW_UNUSED(channels) } +void RGFW_window_hide(RGFW_window* win) { RGFW_UNUSED(win) } +void RGFW_window_show(RGFW_window* win) {RGFW_UNUSED(win) } +b8 RGFW_window_isHidden(RGFW_window* win) { RGFW_UNUSED(win) return 0; } +b8 RGFW_window_isMinimized(RGFW_window* win) { RGFW_UNUSED(win) return 0; } +b8 RGFW_window_isMaximized(RGFW_window* win) { RGFW_UNUSED(win) return 0; } +RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) { RGFW_UNUSED(win) return (RGFW_monitor){}; } + +#endif + +/* end of web asm defines */ + +/* unix (macOS, linux, web asm) only stuff */ +#if defined(RGFW_X11) || defined(RGFW_MACOS) || defined(RGFW_WEBASM) /* unix threading */ #ifndef RGFW_NO_THREADS #include @@ -6616,6 +7564,8 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ void RGFW_setThreadPriority(RGFW_thread thread, u8 priority) { pthread_setschedprio(thread, priority); } #endif #endif + +#ifndef RGFW_WEBASM /* unix sleep */ void RGFW_sleep(u64 ms) { struct timespec time; @@ -6624,6 +7574,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ nanosleep(&time, NULL); } +#endif #endif /* end of unix / mac stuff*/ #endif /*RGFW_IMPLEMENTATION*/ diff --git a/src/platforms/rcore_desktop_rgfw.c b/src/platforms/rcore_desktop_rgfw.c index cfc091172606..d98c6391db71 100644 --- a/src/platforms/rcore_desktop_rgfw.c +++ b/src/platforms/rcore_desktop_rgfw.c @@ -46,7 +46,7 @@ * **********************************************************************************************/ -#ifdef GRAPHICS_API_OPENGL_ES2 +#if defined(GRAPHICS_API_OPENGL_ES2) #define RGFW_OPENGL_ES2 #endif @@ -182,7 +182,7 @@ static const unsigned short keyMappingRGFW[] = { [RGFW_u] = KEY_U, [RGFW_v] = KEY_V, [RGFW_w] = KEY_W, - [RGFW_x] KEY_X, + [RGFW_x] = KEY_X, [RGFW_y] = KEY_Y, [RGFW_z] = KEY_Z, [RGFW_Bracket] = KEY_LEFT_BRACKET, @@ -483,14 +483,14 @@ void SetWindowIcons(Image *images, int count) // Set title for window void SetWindowTitle(const char *title) { - RGFW_window_setName(platform.window, title); + RGFW_window_setName(platform.window, (char*)title); CORE.Window.title = title; } // Set window position on screen (windowed mode) void SetWindowPosition(int x, int y) { - RGFW_window_move(platform.window, RGFW_VECTOR(x, y)); + RGFW_window_move(platform.window, RGFW_POINT(x, y)); } // Set monitor for the current window @@ -536,7 +536,9 @@ void SetWindowFocused(void) // Get native window handle void *GetWindowHandle(void) { -#ifndef RGFW_WINDOWS +#ifdef RGFW_WEBASM + return (void*)platform.window->src.ctx; +#elif !defined(RGFW_WINDOWS) return (void *)platform.window->src.window; #else return platform.window->src.hwnd; @@ -643,7 +645,7 @@ Vector2 GetWindowScaleDPI(void) { RGFW_monitor monitor = RGFW_window_getMonitor(platform.window); - return (Vector2){((u32)monitor.scaleX)*platform.window->r.w, ((u32) monitor.scaleX)*platform.window->r.h}; + return (Vector2){monitor.scaleX, monitor.scaleX}; } // Set clipboard text content @@ -689,9 +691,8 @@ void EnableCursor(void) void DisableCursor(void) { RGFW_disableCursor = true; - - // Set cursor position in the middle - SetMousePosition(CORE.Window.screen.width/2, CORE.Window.screen.height/2); + + RGFW_window_mouseHold(platform.window, RGFW_AREA(CORE.Window.screen.width / 2, CORE.Window.screen.height / 2)); HideCursor(); } @@ -745,7 +746,7 @@ int SetGamepadMappings(const char *mappings) // Set mouse position XY void SetMousePosition(int x, int y) { - RGFW_window_moveMouse(platform.window, RGFW_VECTOR(x, y)); + RGFW_window_moveMouse(platform.window, RGFW_POINT(x, y)); CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y }; CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition; } @@ -875,10 +876,10 @@ void PollInputEvents(void) //----------------------------------------------------------------------------- CORE.Window.resizedLastFrame = false; -#define RGFW_HOLD_MOUSE (1L<<2) -#if defined(RGFW_X11) //|| defined(RGFW_MACOS) - if (platform.window->src.winArgs & RGFW_HOLD_MOUSE) + #define RGFW_HOLD_MOUSE (1L<<2) + #if defined(RGFW_X11) //|| defined(RGFW_MACOS) + if (platform.window->_winArgs & RGFW_HOLD_MOUSE) { CORE.Input.Mouse.previousPosition = (Vector2){ 0.0f, 0.0f }; CORE.Input.Mouse.currentPosition = (Vector2){ 0.0f, 0.0f }; @@ -1031,17 +1032,17 @@ void PollInputEvents(void) } break; case RGFW_mousePosChanged: { - if (platform.window->src.winArgs & RGFW_HOLD_MOUSE) + if (platform.window->_winArgs & RGFW_HOLD_MOUSE) { CORE.Input.Mouse.previousPosition = (Vector2){ 0.0f, 0.0f }; - if ((event->point.x - (platform.window->r.w/2))*2) + if (event->point.x) CORE.Input.Mouse.previousPosition.x = CORE.Input.Mouse.currentPosition.x; - if ((event->point.y - (platform.window->r.h/2))*2) + if (event->point.y) CORE.Input.Mouse.previousPosition.y = CORE.Input.Mouse.currentPosition.y; - CORE.Input.Mouse.currentPosition.x = (event->point.x - (platform.window->r.w/2))*2; - CORE.Input.Mouse.currentPosition.y = (event->point.y - (platform.window->r.h/2))*2; + CORE.Input.Mouse.currentPosition.x = (float)event->point.x; + CORE.Input.Mouse.currentPosition.y = (float)event->point.y; } else { @@ -1205,8 +1206,6 @@ void PollInputEvents(void) } #endif } - - if (RGFW_disableCursor && platform.window->event.inFocus) RGFW_window_mouseHold(platform.window, RGFW_AREA(0, 0)); //----------------------------------------------------------------------------- } @@ -1258,6 +1257,16 @@ int InitPlatform(void) platform.window = RGFW_createWindow(CORE.Window.title, RGFW_RECT(0, 0, CORE.Window.screen.width, CORE.Window.screen.height), flags); + RGFW_area screenSize = RGFW_getScreenSize(); + CORE.Window.display.width = screenSize.w; + CORE.Window.display.height = screenSize.h; + /* + I think this is needed by Raylib now ? + If so, rcore_destkop_sdl should be updated too + */ + SetupFramebuffer(CORE.Window.display.width, CORE.Window.display.height); + + if (CORE.Window.flags & FLAG_VSYNC_HINT) RGFW_window_swapInterval(platform.window, 1); RGFW_window_makeCurrent(platform.window); From 30f9ca7eb60d527e623066bbdc7257474da2baef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A1zaro=20Albuquerque?= <33807434+lzralbu@users.noreply.github.com> Date: Mon, 22 Jul 2024 16:23:03 -0400 Subject: [PATCH 2/4] A better default that saves the whopping amount of 28KB on the final bundle (#4177) --- src/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index dd940b36c371..9735e267faa7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -70,7 +70,8 @@ endif() if (${PLATFORM} MATCHES "Web") target_link_options(raylib PUBLIC "-sUSE_GLFW=3") if(${GRAPHICS} MATCHES "GRAPHICS_API_OPENGL_ES3") - target_link_options(raylib PUBLIC "-sFULL_ES3") + target_link_options(raylib PUBLIC "-sMIN_WEBGL_VERSION=2") + target_link_options(raylib PUBLIC "-sMAX_WEBGL_VERSION=2") endif() endif() From bbcb0109e150433c27d22cc63124f80af9c5a5c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A1zaro=20Albuquerque?= <33807434+lzralbu@users.noreply.github.com> Date: Tue, 23 Jul 2024 15:10:23 -0400 Subject: [PATCH 3/4] Add default vertex/fragment shader to OpenGL ES 3.0 based on the ones from OpenGL 3.3 (#4178) --- src/rlgl.h | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/rlgl.h b/src/rlgl.h index ccb53a624919..38f9ae8bd7f2 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -4756,7 +4756,16 @@ static void rlLoadShaderDefault(void) "out vec2 fragTexCoord; \n" "out vec4 fragColor; \n" #endif -#if defined(GRAPHICS_API_OPENGL_ES2) + +#if defined(GRAPHICS_API_OPENGL_ES3) + "#version 300 es \n" + "precision mediump float; \n" // Precision required for OpenGL ES3 (WebGL 2) (on some browsers) + "in vec3 vertexPosition; \n" + "in vec2 vertexTexCoord; \n" + "in vec4 vertexColor; \n" + "out vec2 fragTexCoord; \n" + "out vec4 fragColor; \n" +#elif defined(GRAPHICS_API_OPENGL_ES2) "#version 100 \n" "precision mediump float; \n" // Precision required for OpenGL ES2 (WebGL) (on some browsers) "attribute vec3 vertexPosition; \n" @@ -4765,6 +4774,7 @@ static void rlLoadShaderDefault(void) "varying vec2 fragTexCoord; \n" "varying vec4 fragColor; \n" #endif + "uniform mat4 mvp; \n" "void main() \n" "{ \n" @@ -4799,7 +4809,21 @@ static void rlLoadShaderDefault(void) " finalColor = texelColor*colDiffuse*fragColor; \n" "} \n"; #endif -#if defined(GRAPHICS_API_OPENGL_ES2) + +#if defined(GRAPHICS_API_OPENGL_ES3) + "#version 300 es \n" + "precision mediump float; \n" // Precision required for OpenGL ES3 (WebGL 2) + "in vec2 fragTexCoord; \n" + "in vec4 fragColor; \n" + "out vec4 finalColor; \n" + "uniform sampler2D texture0; \n" + "uniform vec4 colDiffuse; \n" + "void main() \n" + "{ \n" + " vec4 texelColor = texture(texture0, fragTexCoord); \n" + " finalColor = texelColor*colDiffuse*fragColor; \n" + "} \n"; +#elif defined(GRAPHICS_API_OPENGL_ES2) "#version 100 \n" "precision mediump float; \n" // Precision required for OpenGL ES2 (WebGL) "varying vec2 fragTexCoord; \n" From f5d2f8d545b68ff8d181818fdd5388201244373a Mon Sep 17 00:00:00 2001 From: Jutastre <44203587+Jutastre@users.noreply.github.com> Date: Wed, 24 Jul 2024 21:21:45 +0200 Subject: [PATCH 4/4] Warning on invalid image data (#4179) * Adds log warnings on invalid file data * Separate error on missing file extension * Changed LOG_ERROR to LOG_WARNING --------- Co-authored-by: Jutastre --- src/rtextures.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/rtextures.c b/src/rtextures.c index d70e2cde89a2..60ce58f4b09f 100644 --- a/src/rtextures.c +++ b/src/rtextures.c @@ -503,7 +503,16 @@ Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, i Image image = { 0 }; // Security check for input data - if ((fileType == NULL) || (fileData == NULL) || (dataSize == 0)) return image; + if ((fileData == NULL) || (dataSize == 0)) + { + TRACELOG(LOG_WARNING, "IMAGE: Invalid file data"); + return image; + } + if (fileType == NULL) + { + TRACELOG(LOG_WARNING, "IMAGE: Missing file extension"); + return image; + } if ((false) #if defined(SUPPORT_FILEFORMAT_PNG)