From 9d3bd43c6ed48e6276687ccec8b9caabbf8f73d3 Mon Sep 17 00:00:00 2001 From: Jeffery Myers Date: Mon, 1 Jul 2024 13:03:21 -0700 Subject: [PATCH 01/41] [CORE] Fix MSVC warnings/errors and raymath.h in C++ (#4125) * Update raylib_api.* by CI * Fix MSVC warnings. Make raymath.h work in C++ in MSVC * whitespace cleanup --------- Co-authored-by: github-actions[bot] --- src/raymath.h | 10 +++++++--- src/rtextures.c | 4 ++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/raymath.h b/src/raymath.h index 0b6951938..62d52f8fd 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -2549,9 +2549,13 @@ RMAPI void MatrixDecompose(Matrix mat, Vector3 *translation, Quaternion *rotatio // Extract scale const float det = a*A + b*B + c*C; - float scalex = Vector3Length((Vector3){ a, b, c }); - float scaley = Vector3Length((Vector3){ d, e, f }); - float scalez = Vector3Length((Vector3){ g, h, i }); + Vector3 abc = { a, b, c }; + Vector3 def = { d, e, f }; + Vector3 ghi = { g, h, i }; + + float scalex = Vector3Length(abc); + float scaley = Vector3Length(def); + float scalez = Vector3Length(ghi); Vector3 s = { scalex, scaley, scalez }; if (det < 0) s = Vector3Negate(s); diff --git a/src/rtextures.c b/src/rtextures.c index 54bf7c6a0..1e88b64a4 100644 --- a/src/rtextures.c +++ b/src/rtextures.c @@ -3658,7 +3658,7 @@ void ImageDrawLineEx(Image *dst, Vector2 start, Vector2 end, int thick, Color co { // Line is more horizontal // Calculate half the width of the line - int wy = (thick - 1)*sqrtf(dx*dx + dy*dy)/(2*abs(dx)); + int wy = (thick - 1)*(int)sqrtf((float)(dx*dx + dy*dy))/(2*abs(dx)); // Draw additional lines above and below the main line for (int i = 1; i <= wy; i++) @@ -3671,7 +3671,7 @@ void ImageDrawLineEx(Image *dst, Vector2 start, Vector2 end, int thick, Color co { // Line is more vertical or perfectly horizontal // Calculate half the width of the line - int wx = (thick - 1)*sqrtf(dx*dx + dy*dy)/(2*abs(dy)); + int wx = (thick - 1)*(int)sqrtf((float)(dx*dx + dy*dy))/(2*abs(dy)); // Draw additional lines to the left and right of the main line for (int i = 1; i <= wx; i++) From 8fbb447a6d3696766443316afeef6d033629409d Mon Sep 17 00:00:00 2001 From: Frank Kartheuser Date: Thu, 4 Jul 2024 00:01:40 +0200 Subject: [PATCH 02/41] Change SDL_Joystick to SDL_GameController (#4129) With SDL_Joystick my game controller wasn't working properly. That's why I changed it to SDL_GameController. --- src/platforms/rcore_desktop_sdl.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/platforms/rcore_desktop_sdl.c b/src/platforms/rcore_desktop_sdl.c index 9a6d16132..3d6293597 100644 --- a/src/platforms/rcore_desktop_sdl.c +++ b/src/platforms/rcore_desktop_sdl.c @@ -64,7 +64,7 @@ typedef struct { SDL_Window *window; SDL_GLContext glContext; - SDL_Joystick *gamepad[MAX_GAMEPADS]; + SDL_GameController *gamepad[MAX_GAMEPADS]; SDL_Cursor *cursor; bool cursorRelative; } PlatformData; @@ -944,7 +944,7 @@ void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor) if (IsGamepadAvailable(gamepad)) { - SDL_JoystickRumble(platform.gamepad[gamepad], (Uint16)(leftMotor*65535.0f), (Uint16)(rightMotor*65535.0f), (Uint32)(MAX_GAMEPAD_VIBRATION_TIME*1000.0f)); + SDL_GameControllerRumble(platform.gamepad[gamepad], (Uint16)(leftMotor*65535.0f), (Uint16)(rightMotor*65535.0f), (Uint32)(MAX_GAMEPAD_VIBRATION_TIME*1000.0f)); } } @@ -1245,15 +1245,15 @@ void PollInputEvents(void) if (!CORE.Input.Gamepad.ready[jid] && (jid < MAX_GAMEPADS)) { - platform.gamepad[jid] = SDL_JoystickOpen(jid); + platform.gamepad[jid] = SDL_GameControllerOpen(jid); if (platform.gamepad[jid]) { CORE.Input.Gamepad.ready[jid] = true; - CORE.Input.Gamepad.axisCount[jid] = SDL_JoystickNumAxes(platform.gamepad[jid]); + CORE.Input.Gamepad.axisCount[jid] = SDL_JoystickNumAxes(SDL_GameControllerGetJoystick(platform.gamepad[jid])); CORE.Input.Gamepad.axisState[jid][GAMEPAD_AXIS_LEFT_TRIGGER] = -1.0f; CORE.Input.Gamepad.axisState[jid][GAMEPAD_AXIS_RIGHT_TRIGGER] = -1.0f; - strncpy(CORE.Input.Gamepad.name[jid], SDL_JoystickName(platform.gamepad[jid]), 63); + strncpy(CORE.Input.Gamepad.name[jid], SDL_GameControllerNameForIndex(jid), 63); CORE.Input.Gamepad.name[jid][63] = '\0'; } else @@ -1266,15 +1266,15 @@ void PollInputEvents(void) { int jid = event.jdevice.which; - if (jid == SDL_JoystickInstanceID(platform.gamepad[jid])) + if (jid == SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(platform.gamepad[jid]))) { - SDL_JoystickClose(platform.gamepad[jid]); - platform.gamepad[jid] = SDL_JoystickOpen(0); + SDL_GameControllerClose(platform.gamepad[jid]); + platform.gamepad[jid] = SDL_GameControllerOpen(0); CORE.Input.Gamepad.ready[jid] = false; memset(CORE.Input.Gamepad.name[jid], 0, 64); } } break; - case SDL_JOYBUTTONDOWN: + case SDL_CONTROLLERBUTTONDOWN: { int button = -1; @@ -1308,7 +1308,7 @@ void PollInputEvents(void) CORE.Input.Gamepad.lastButtonPressed = button; } } break; - case SDL_JOYBUTTONUP: + case SDL_CONTROLLERBUTTONUP: { int button = -1; @@ -1342,7 +1342,7 @@ void PollInputEvents(void) if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0; } } break; - case SDL_JOYAXISMOTION: + case SDL_CONTROLLERAXISMOTION: { int axis = -1; @@ -1548,15 +1548,15 @@ int InitPlatform(void) // Initialize gamepads for (int i = 0; (i < SDL_NumJoysticks()) && (i < MAX_GAMEPADS); i++) { - platform.gamepad[i] = SDL_JoystickOpen(i); + platform.gamepad[i] = SDL_GameControllerOpen(i); if (platform.gamepad[i]) { CORE.Input.Gamepad.ready[i] = true; - CORE.Input.Gamepad.axisCount[i] = SDL_JoystickNumAxes(platform.gamepad[i]); + CORE.Input.Gamepad.axisCount[i] = SDL_JoystickNumAxes(SDL_GameControllerGetJoystick(platform.gamepad[i])); CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_LEFT_TRIGGER] = -1.0f; CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_RIGHT_TRIGGER] = -1.0f; - strncpy(CORE.Input.Gamepad.name[i], SDL_JoystickName(platform.gamepad[i]), 63); + strncpy(CORE.Input.Gamepad.name[i], SDL_GameControllerNameForIndex(i), 63); CORE.Input.Gamepad.name[i][63] = '\0'; } else TRACELOG(LOG_WARNING, "PLATFORM: Unable to open game controller [ERROR: %s]", SDL_GetError()); From c95b2e88b703e7fee5e7f4e7b0c01906c58f794c Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 4 Jul 2024 11:12:20 +0200 Subject: [PATCH 03/41] Example review --- examples/models/models_loading_gltf.c | 19 +++++++++---------- .../examples/models_loading_gltf.vcxproj | 3 +++ 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/examples/models/models_loading_gltf.c b/examples/models/models_loading_gltf.c index e85b30e6c..8b8838c8d 100644 --- a/examples/models/models_loading_gltf.c +++ b/examples/models/models_loading_gltf.c @@ -30,11 +30,11 @@ int main(void) const int screenWidth = 800; const int screenHeight = 450; - InitWindow(screenWidth, screenHeight, "raylib [models] example - loading gltf"); + InitWindow(screenWidth, screenHeight, "raylib [models] example - loading gltf animations"); // Define the camera to look into our 3d world Camera camera = { 0 }; - camera.position = (Vector3){ 5.0f, 5.0f, 5.0f }; // Camera position + camera.position = (Vector3){ 6.0f, 6.0f, 6.0f }; // Camera position camera.target = (Vector3){ 0.0f, 2.0f, 0.0f }; // Camera looking at point camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target) camera.fovy = 45.0f; // Camera field-of-view Y @@ -42,17 +42,14 @@ int main(void) // Load gltf model Model model = LoadModel("resources/models/gltf/robot.glb"); - + Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position + // Load gltf model animations int animsCount = 0; unsigned int animIndex = 0; unsigned int animCurrentFrame = 0; ModelAnimation *modelAnimations = LoadModelAnimations("resources/models/gltf/robot.glb", &animsCount); - Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position - - DisableCursor(); // Limit cursor to relative movement inside the window - SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- @@ -61,7 +58,8 @@ int main(void) { // Update //---------------------------------------------------------------------------------- - UpdateCamera(&camera, CAMERA_THIRD_PERSON); + UpdateCamera(&camera, CAMERA_ORBITAL); + // Select current animation if (IsMouseButtonPressed(MOUSE_BUTTON_RIGHT)) animIndex = (animIndex + 1)%animsCount; else if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) animIndex = (animIndex + animsCount - 1)%animsCount; @@ -79,10 +77,8 @@ int main(void) ClearBackground(RAYWHITE); BeginMode3D(camera); - DrawModel(model, position, 1.0f, WHITE); // Draw animated model DrawGrid(10, 1.0f); - EndMode3D(); DrawText("Use the LEFT/RIGHT mouse buttons to switch animation", 10, 10, 20, GRAY); @@ -101,3 +97,6 @@ int main(void) return 0; } + + + diff --git a/projects/VS2022/examples/models_loading_gltf.vcxproj b/projects/VS2022/examples/models_loading_gltf.vcxproj index 141fb9423..aba2e6843 100644 --- a/projects/VS2022/examples/models_loading_gltf.vcxproj +++ b/projects/VS2022/examples/models_loading_gltf.vcxproj @@ -376,6 +376,9 @@ + + + {e89d61ac-55de-4482-afd4-df7242ebc859} From 9a280cda0be211ee751cdb44fedab8f1e698be2a Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 4 Jul 2024 11:12:24 +0200 Subject: [PATCH 04/41] Update rlgl.h --- src/rlgl.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/rlgl.h b/src/rlgl.h index 5ab677d98..5b921ab9c 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -844,9 +844,9 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad #define GL_GLEXT_PROTOTYPES #include // OpenGL ES 2.0 extensions library #elif defined(GRAPHICS_API_OPENGL_ES2) - // NOTE: OpenGL ES 2.0 can be enabled on PLATFORM_DESKTOP, + // NOTE: OpenGL ES 2.0 can be enabled on Desktop platforms, // in that case, functions are loaded from a custom glad for OpenGL ES 2.0 - #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_DESKTOP_SDL) + #if defined(PLATFORM_DESKTOP_GLFW) || defined(PLATFORM_DESKTOP_SDL) #define GLAD_GLES2_IMPLEMENTATION #include "external/glad_gles2.h" #else @@ -2390,7 +2390,7 @@ void rlLoadExtensions(void *loader) #elif defined(GRAPHICS_API_OPENGL_ES2) - #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_DESKTOP_SDL) + #if defined(PLATFORM_DESKTOP_GLFW) || defined(PLATFORM_DESKTOP_SDL) // TODO: Support GLAD loader for OpenGL ES 3.0 if (gladLoadGLES2((GLADloadfunc)loader) == 0) TRACELOG(RL_LOG_WARNING, "GLAD: Cannot load OpenGL ES2.0 functions"); else TRACELOG(RL_LOG_INFO, "GLAD: OpenGL ES 2.0 loaded successfully"); From 1039e3c1bd61ce8694c6c191d6b34eb4807e5aae Mon Sep 17 00:00:00 2001 From: kai-z99 <147789796+kai-z99@users.noreply.github.com> Date: Sun, 7 Jul 2024 00:05:25 -0700 Subject: [PATCH 05/41] [rshapes] Give CheckCollisionPointCircle() its own implementation (#4135) * remove function call * fix --- src/rshapes.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/rshapes.c b/src/rshapes.c index 9e7de1e2f..5d5ff02ca 100644 --- a/src/rshapes.c +++ b/src/rshapes.c @@ -2172,7 +2172,9 @@ bool CheckCollisionPointCircle(Vector2 point, Vector2 center, float radius) { bool collision = false; - collision = CheckCollisionCircles(point, 0, center, radius); + float distanceSquared = (point.x - center.x) * (point.x - center.x) + (point.y - center.y) * (point.y - center.y); + + collision = distanceSquared <= radius * radius; return collision; } From a8240722c61d216d96c3f2cab27426ee7b7a3919 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 7 Jul 2024 09:09:34 +0200 Subject: [PATCH 06/41] REVIEWED: `CheckCollisionPointRec()` --- src/rshapes.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rshapes.c b/src/rshapes.c index 5d5ff02ca..89339708a 100644 --- a/src/rshapes.c +++ b/src/rshapes.c @@ -2172,9 +2172,9 @@ bool CheckCollisionPointCircle(Vector2 point, Vector2 center, float radius) { bool collision = false; - float distanceSquared = (point.x - center.x) * (point.x - center.x) + (point.y - center.y) * (point.y - center.y); + float distanceSquared = (point.x - center.x)*(point.x - center.x) + (point.y - center.y)*(point.y - center.y); - collision = distanceSquared <= radius * radius; + if (distanceSquared <= radius*radius) collision = true; return collision; } From b61303244c2731b88d93fe5bc976f5e8e6ff72e3 Mon Sep 17 00:00:00 2001 From: Ninad Sachania Date: Sun, 7 Jul 2024 14:17:44 +0530 Subject: [PATCH 07/41] Fix Reddit badge (#4136) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 79e883034..303bbcdd1 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Ready to learn? Jump to [code examples!](https://www.raylib.com/examples.html) [![License](https://img.shields.io/badge/license-zlib%2Flibpng-blue.svg)](LICENSE) [![Discord Members](https://img.shields.io/discord/426912293134270465.svg?label=Discord&logo=discord)](https://discord.gg/raylib) -[![Subreddit Subscribers](https://img.shields.io/reddit/subreddit-subscribers/raylib?label=reddit%20r%2Fraylib&logo=reddit)](https://www.reddit.com/r/raylib/) +[![Reddit Static Badge](https://img.shields.io/badge/-r%2Fraylib-red?style=flat&logo=reddit&label=reddit)](https://www.reddit.com/r/raylib/) [![Youtube Subscribers](https://img.shields.io/youtube/channel/subscribers/UC8WIBkhYb5sBNqXO1mZ7WSQ?style=flat&label=Youtube&logo=youtube)](https://www.youtube.com/c/raylib) [![Twitch Status](https://img.shields.io/twitch/status/raysan5?style=flat&label=Twitch&logo=twitch)](https://www.twitch.tv/raysan5) From 6dd2a0e64554a37c9ab8c0a6204cb5bb1badc970 Mon Sep 17 00:00:00 2001 From: bohonghuang <1281299809@qq.com> Date: Mon, 8 Jul 2024 02:27:51 +0800 Subject: [PATCH 08/41] [rmodels] Consistent `DrawBillboardPro` with `DrawTexturePro` (#4132) * [rmodels] Re-implement `DrawBillboardPro` * [rmodels] Add comments to `DrawBillboardPro` * [rmodels] Make `DrawBillboardPro` consistent with `DrawTexturePro` * Update raylib_api.* by CI --------- Co-authored-by: github-actions[bot] --- examples/models/models_billboard.c | 12 ++- parser/output/raylib_api.json | 2 +- parser/output/raylib_api.lua | 2 +- parser/output/raylib_api.txt | 2 +- parser/output/raylib_api.xml | 2 +- src/raylib.h | 2 +- src/rmodels.c | 152 +++++++++++------------------ 7 files changed, 71 insertions(+), 103 deletions(-) diff --git a/examples/models/models_billboard.c b/examples/models/models_billboard.c index 237e1b69d..7ad28513f 100644 --- a/examples/models/models_billboard.c +++ b/examples/models/models_billboard.c @@ -44,10 +44,12 @@ int main(void) // NOTE: Billboard locked on axis-Y Vector3 billUp = { 0.0f, 1.0f, 0.0f }; + // Set the height of the rotating billboard to 1.0 with the aspect ratio fixed + Vector2 size = { source.width / source.height, 1.0f }; + // Rotate around origin // Here we choose to rotate around the image center - // NOTE: (-1, 1) is the range where origin.x, origin.y is inside the texture - Vector2 rotateOrigin = { 0.0f }; + Vector2 origin = Vector2Scale(size, 0.5f); // Distance is needed for the correct billboard draw order // Larger distance (further away from the camera) should be drawn prior to smaller distance. @@ -84,11 +86,11 @@ int main(void) if (distanceStatic > distanceRotating) { DrawBillboard(camera, bill, billPositionStatic, 2.0f, WHITE); - DrawBillboardPro(camera, bill, source, billPositionRotating, billUp, (Vector2) {1.0f, 1.0f}, rotateOrigin, rotation, WHITE); + DrawBillboardPro(camera, bill, source, billPositionRotating, billUp, size, origin, rotation, WHITE); } else { - DrawBillboardPro(camera, bill, source, billPositionRotating, billUp, (Vector2) {1.0f, 1.0f}, rotateOrigin, rotation, WHITE); + DrawBillboardPro(camera, bill, source, billPositionRotating, billUp, size, origin, rotation, WHITE); DrawBillboard(camera, bill, billPositionStatic, 2.0f, WHITE); } @@ -108,4 +110,4 @@ int main(void) //-------------------------------------------------------------------------------------- return 0; -} \ No newline at end of file +} diff --git a/parser/output/raylib_api.json b/parser/output/raylib_api.json index 810599d57..ec09abf79 100644 --- a/parser/output/raylib_api.json +++ b/parser/output/raylib_api.json @@ -10400,7 +10400,7 @@ }, { "type": "float", - "name": "size" + "name": "scale" }, { "type": "Color", diff --git a/parser/output/raylib_api.lua b/parser/output/raylib_api.lua index 3bc27ffa9..963b0ef6d 100644 --- a/parser/output/raylib_api.lua +++ b/parser/output/raylib_api.lua @@ -7230,7 +7230,7 @@ return { {type = "Camera", name = "camera"}, {type = "Texture2D", name = "texture"}, {type = "Vector3", name = "position"}, - {type = "float", name = "size"}, + {type = "float", name = "scale"}, {type = "Color", name = "tint"} } }, diff --git a/parser/output/raylib_api.txt b/parser/output/raylib_api.txt index 4aed95a34..406482226 100644 --- a/parser/output/raylib_api.txt +++ b/parser/output/raylib_api.txt @@ -3968,7 +3968,7 @@ Function 466: DrawBillboard() (5 input parameters) Param[1]: camera (type: Camera) Param[2]: texture (type: Texture2D) Param[3]: position (type: Vector3) - Param[4]: size (type: float) + Param[4]: scale (type: float) Param[5]: tint (type: Color) Function 467: DrawBillboardRec() (6 input parameters) Name: DrawBillboardRec diff --git a/parser/output/raylib_api.xml b/parser/output/raylib_api.xml index 32a920a82..9b8a73fa7 100644 --- a/parser/output/raylib_api.xml +++ b/parser/output/raylib_api.xml @@ -2645,7 +2645,7 @@ - + diff --git a/src/raylib.h b/src/raylib.h index 0703131c4..3bc44f03d 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1546,7 +1546,7 @@ RLAPI void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, floa RLAPI void DrawModelWires(Model model, Vector3 position, float scale, Color tint); // Draw a model wires (with texture if set) RLAPI void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters RLAPI void DrawBoundingBox(BoundingBox box, Color color); // Draw bounding box (wires) -RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float size, Color tint); // Draw a billboard texture +RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float scale, Color tint); // Draw a billboard texture RLAPI void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Color tint); // Draw a billboard texture defined by source RLAPI void DrawBillboardPro(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector3 up, Vector2 size, Vector2 origin, float rotation, Color tint); // Draw a billboard texture defined by source and rotation diff --git a/src/rmodels.c b/src/rmodels.c index b67c8e695..31b4c574a 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -3638,11 +3638,11 @@ void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float } // Draw a billboard -void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float size, Color tint) +void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float scale, Color tint) { Rectangle source = { 0.0f, 0.0f, (float)texture.width, (float)texture.height }; - DrawBillboardRec(camera, texture, source, position, (Vector2){ size, size }, tint); + DrawBillboardRec(camera, texture, source, position, (Vector2) { scale*fabsf((float)source.width/source.height), scale }, tint); } // Draw a billboard (part of a texture defined by a rectangle) @@ -3651,116 +3651,82 @@ void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector // NOTE: Billboard locked on axis-Y Vector3 up = { 0.0f, 1.0f, 0.0f }; - DrawBillboardPro(camera, texture, source, position, up, size, Vector2Zero(), 0.0f, tint); + DrawBillboardPro(camera, texture, source, position, up, size, Vector2Scale(size, 0.5), 0.0f, tint); } // Draw a billboard with additional parameters -// NOTE: Size defines the destination rectangle size, stretching the source texture as required void DrawBillboardPro(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector3 up, Vector2 size, Vector2 origin, float rotation, Color tint) { - // NOTE: Billboard size will maintain source rectangle aspect ratio, size will represent billboard width - Vector2 sizeRatio = { size.x*fabsf((float)source.width/source.height), size.y }; - + // Compute the up vector and the right vector Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up); - Vector3 right = { matView.m0, matView.m4, matView.m8 }; - //Vector3 up = { matView.m1, matView.m5, matView.m9 }; + right = Vector3Scale(right, size.x); + up = Vector3Scale(up, size.y); - Vector3 rightScaled = Vector3Scale(right, sizeRatio.x/2); - Vector3 upScaled = Vector3Scale(up, sizeRatio.y/2); - - Vector3 p1 = Vector3Add(rightScaled, upScaled); - Vector3 p2 = Vector3Subtract(rightScaled, upScaled); - - Vector3 topLeft = Vector3Scale(p2, -1); - Vector3 topRight = p1; - Vector3 bottomRight = p2; - Vector3 bottomLeft = Vector3Scale(p1, -1); - - if (rotation != 0.0f) + // Flip the content of the billboard while maintaining the counterclockwise edge rendering order + if (size.x < 0.0f) { - float sinRotation = sinf(rotation*DEG2RAD); - float cosRotation = cosf(rotation*DEG2RAD); - - // NOTE: (-1, 1) is the range where origin.x, origin.y is inside the texture - float rotateAboutX = sizeRatio.x*origin.x/2; - float rotateAboutY = sizeRatio.y*origin.y/2; - - float xtvalue, ytvalue; - float rotatedX, rotatedY; - - xtvalue = Vector3DotProduct(right, topLeft) - rotateAboutX; // Project points to x and y coordinates on the billboard plane - ytvalue = Vector3DotProduct(up, topLeft) - rotateAboutY; - rotatedX = xtvalue*cosRotation - ytvalue*sinRotation + rotateAboutX; // Rotate about the point origin - rotatedY = xtvalue*sinRotation + ytvalue*cosRotation + rotateAboutY; - topLeft = Vector3Add(Vector3Scale(up, rotatedY), Vector3Scale(right, rotatedX)); // Translate back to cartesian coordinates - - xtvalue = Vector3DotProduct(right, topRight) - rotateAboutX; - ytvalue = Vector3DotProduct(up, topRight) - rotateAboutY; - rotatedX = xtvalue*cosRotation - ytvalue*sinRotation + rotateAboutX; - rotatedY = xtvalue*sinRotation + ytvalue*cosRotation + rotateAboutY; - topRight = Vector3Add(Vector3Scale(up, rotatedY), Vector3Scale(right, rotatedX)); - - xtvalue = Vector3DotProduct(right, bottomRight) - rotateAboutX; - ytvalue = Vector3DotProduct(up, bottomRight) - rotateAboutY; - rotatedX = xtvalue*cosRotation - ytvalue*sinRotation + rotateAboutX; - rotatedY = xtvalue*sinRotation + ytvalue*cosRotation + rotateAboutY; - bottomRight = Vector3Add(Vector3Scale(up, rotatedY), Vector3Scale(right, rotatedX)); - - xtvalue = Vector3DotProduct(right, bottomLeft)-rotateAboutX; - ytvalue = Vector3DotProduct(up, bottomLeft)-rotateAboutY; - rotatedX = xtvalue*cosRotation - ytvalue*sinRotation + rotateAboutX; - rotatedY = xtvalue*sinRotation + ytvalue*cosRotation + rotateAboutY; - bottomLeft = Vector3Add(Vector3Scale(up, rotatedY), Vector3Scale(right, rotatedX)); + source.x += size.x; + source.width *= -1.0; + right = Vector3Negate(right); + origin.x *= -1.0f; + } + if (size.y < 0.0f) + { + source.y += size.y; + source.height *= -1.0; + up = Vector3Negate(up); + origin.y *= -1.0f; } - // Translate points to the draw center (position) - topLeft = Vector3Add(topLeft, position); - topRight = Vector3Add(topRight, position); - bottomRight = Vector3Add(bottomRight, position); - bottomLeft = Vector3Add(bottomLeft, position); + // Draw the texture region described by source on the following rectangle in 3D space: + // + // size.x <--. + // 3 ^---------------------------+ 2 \ rotation + // | | / + // | | + // | origin.x position | + // up |.............. | size.y + // | . | + // | . origin.y | + // | . | + // 0 +---------------------------> 1 + // right + Vector3 forward; + if (rotation != 0.0) forward = Vector3CrossProduct(right, up); + + Vector3 origin3D = Vector3Add(Vector3Scale(Vector3Normalize(right), origin.x), Vector3Scale(Vector3Normalize(up), origin.y)); + + Vector3 points[4]; + points[0] = Vector3Zero(); + points[1] = right; + points[2] = Vector3Add(up, right); + points[3] = up; + + for (int i = 0; i < 4; i++) + { + points[i] = Vector3Subtract(points[i], origin3D); + if (rotation != 0.0) points[i] = Vector3RotateByAxisAngle(points[i], forward, rotation * DEG2RAD); + points[i] = Vector3Add(points[i], position); + } + + Vector2 texcoords[4]; + texcoords[0] = (Vector2) { (float)source.x/texture.width, (float)(source.y + source.height)/texture.height }; + texcoords[1] = (Vector2) { (float)(source.x + source.width)/texture.width, (float)(source.y + source.height)/texture.height }; + texcoords[2] = (Vector2) { (float)(source.x + source.width)/texture.width, (float)source.y/texture.height }; + texcoords[3] = (Vector2) { (float)source.x/texture.width, (float)source.y/texture.height }; rlSetTexture(texture.id); - rlBegin(RL_QUADS); + rlColor4ub(tint.r, tint.g, tint.b, tint.a); - - if (sizeRatio.x*sizeRatio.y >= 0.0f) + for (int i = 0; i < 4; i++) { - // Bottom-left corner for texture and quad - rlTexCoord2f((float)source.x/texture.width, (float)source.y/texture.height); - rlVertex3f(topLeft.x, topLeft.y, topLeft.z); - - // Top-left corner for texture and quad - rlTexCoord2f((float)source.x/texture.width, (float)(source.y + source.height)/texture.height); - rlVertex3f(bottomLeft.x, bottomLeft.y, bottomLeft.z); - - // Top-right corner for texture and quad - rlTexCoord2f((float)(source.x + source.width)/texture.width, (float)(source.y + source.height)/texture.height); - rlVertex3f(bottomRight.x, bottomRight.y, bottomRight.z); - - // Bottom-right corner for texture and quad - rlTexCoord2f((float)(source.x + source.width)/texture.width, (float)source.y/texture.height); - rlVertex3f(topRight.x, topRight.y, topRight.z); - } - else - { - // Reverse vertex order if the size has only one negative dimension - rlTexCoord2f((float)(source.x + source.width)/texture.width, (float)source.y/texture.height); - rlVertex3f(topRight.x, topRight.y, topRight.z); - - rlTexCoord2f((float)(source.x + source.width)/texture.width, (float)(source.y + source.height)/texture.height); - rlVertex3f(bottomRight.x, bottomRight.y, bottomRight.z); - - rlTexCoord2f((float)source.x/texture.width, (float)(source.y + source.height)/texture.height); - rlVertex3f(bottomLeft.x, bottomLeft.y, bottomLeft.z); - - rlTexCoord2f((float)source.x/texture.width, (float)source.y/texture.height); - rlVertex3f(topLeft.x, topLeft.y, topLeft.z); + rlTexCoord2f(texcoords[i].x, texcoords[i].y); + rlVertex3f(points[i].x, points[i].y, points[i].z); } rlEnd(); - rlSetTexture(0); } From df4ff4e78b4e2d35f05ffc402a2d72fe4f047a23 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 7 Jul 2024 20:57:18 +0200 Subject: [PATCH 09/41] REVIEWED: Direction must be normalized #4131 --- src/raylib.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/raylib.h b/src/raylib.h index 3bc44f03d..60ec3c23e 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -421,7 +421,7 @@ typedef struct ModelAnimation { // Ray, ray for raycasting typedef struct Ray { Vector3 position; // Ray position (origin) - Vector3 direction; // Ray direction + Vector3 direction; // Ray direction (normalized) } Ray; // RayCollision, ray hit information From bc6cf61794d54158fae94b122e37121ef178b4bb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 7 Jul 2024 18:57:40 +0000 Subject: [PATCH 10/41] Update raylib_api.* by CI --- parser/output/raylib_api.json | 2 +- parser/output/raylib_api.lua | 2 +- parser/output/raylib_api.txt | 2 +- parser/output/raylib_api.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/parser/output/raylib_api.json b/parser/output/raylib_api.json index ec09abf79..c00407dc6 100644 --- a/parser/output/raylib_api.json +++ b/parser/output/raylib_api.json @@ -1058,7 +1058,7 @@ { "type": "Vector3", "name": "direction", - "description": "Ray direction" + "description": "Ray direction (normalized)" } ] }, diff --git a/parser/output/raylib_api.lua b/parser/output/raylib_api.lua index 963b0ef6d..9cbd1b9da 100644 --- a/parser/output/raylib_api.lua +++ b/parser/output/raylib_api.lua @@ -1058,7 +1058,7 @@ return { { type = "Vector3", name = "direction", - description = "Ray direction" + description = "Ray direction (normalized)" } } }, diff --git a/parser/output/raylib_api.txt b/parser/output/raylib_api.txt index 406482226..31433073e 100644 --- a/parser/output/raylib_api.txt +++ b/parser/output/raylib_api.txt @@ -473,7 +473,7 @@ Struct 23: Ray (2 fields) Name: Ray Description: Ray, ray for raycasting Field[1]: Vector3 position // Ray position (origin) - Field[2]: Vector3 direction // Ray direction + Field[2]: Vector3 direction // Ray direction (normalized) Struct 24: RayCollision (4 fields) Name: RayCollision Description: RayCollision, ray hit information diff --git a/parser/output/raylib_api.xml b/parser/output/raylib_api.xml index 9b8a73fa7..51473562c 100644 --- a/parser/output/raylib_api.xml +++ b/parser/output/raylib_api.xml @@ -220,7 +220,7 @@ - + From b8e51794310e58e477cfa630059d061fcd5fa1f4 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 7 Jul 2024 21:02:20 +0200 Subject: [PATCH 11/41] Update rmodels.c --- src/rmodels.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/rmodels.c b/src/rmodels.c index 31b4c574a..c6acff5dc 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -5172,7 +5172,7 @@ static Model LoadGLTF(const char *fileName) // Transform the vertices float *vertices = model.meshes[meshIndex].vertices; - for (int k = 0; k < attribute->count; k++) + for (unsigned int k = 0; k < attribute->count; k++) { Vector3 vt = Vector3Transform((Vector3){ vertices[3*k], vertices[3*k+1], vertices[3*k+2] }, worldMatrix); vertices[3*k] = vt.x; @@ -5196,7 +5196,7 @@ static Model LoadGLTF(const char *fileName) // Transform the normals float *normals = model.meshes[meshIndex].normals; - for (int k = 0; k < attribute->count; k++) + for (unsigned int k = 0; k < attribute->count; k++) { Vector3 nt = Vector3Transform((Vector3){ normals[3*k], normals[3*k+1], normals[3*k+2] }, worldMatrixNormals); normals[3*k] = nt.x; @@ -5220,7 +5220,7 @@ static Model LoadGLTF(const char *fileName) // Transform the tangents float *tangents = model.meshes[meshIndex].tangents; - for (int k = 0; k < attribute->count; k++) + for (unsigned int k = 0; k < attribute->count; k++) { Vector3 tt = Vector3Transform((Vector3){ tangents[3*k], tangents[3*k+1], tangents[3*k+2] }, worldMatrix); tangents[3*k] = tt.x; From 9764fef26260e6fcf671ddffb230360cc1efa1f8 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 7 Jul 2024 21:02:35 +0200 Subject: [PATCH 12/41] Update models_billboard.c --- examples/models/models_billboard.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/models/models_billboard.c b/examples/models/models_billboard.c index 7ad28513f..cfb49e55c 100644 --- a/examples/models/models_billboard.c +++ b/examples/models/models_billboard.c @@ -45,7 +45,7 @@ int main(void) Vector3 billUp = { 0.0f, 1.0f, 0.0f }; // Set the height of the rotating billboard to 1.0 with the aspect ratio fixed - Vector2 size = { source.width / source.height, 1.0f }; + Vector2 size = { source.width/source.height, 1.0f }; // Rotate around origin // Here we choose to rotate around the image center From 598b7f52104a4dd9246ffe01cffcdc0b376cb45c Mon Sep 17 00:00:00 2001 From: NishiOwO <89888985+NishiOwO@users.noreply.github.com> Date: Tue, 9 Jul 2024 05:47:35 +0900 Subject: [PATCH 13/41] Add workaround for NetBSD (#4139) --- src/platforms/rcore_desktop_glfw.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/platforms/rcore_desktop_glfw.c b/src/platforms/rcore_desktop_glfw.c index dbdde9dbd..67cf9deff 100644 --- a/src/platforms/rcore_desktop_glfw.c +++ b/src/platforms/rcore_desktop_glfw.c @@ -1617,6 +1617,10 @@ int InitPlatform(void) CORE.Storage.basePath = GetWorkingDirectory(); //---------------------------------------------------------------------------- +#if defined(__NetBSD__) + // Workaround for NetBSD + char* glfwPlatform = "X11"; +#else char* glfwPlatform = ""; switch (glfwGetPlatform()) { @@ -1626,6 +1630,7 @@ int InitPlatform(void) case GLFW_PLATFORM_X11: glfwPlatform = "X11"; break; case GLFW_PLATFORM_NULL: glfwPlatform = "Null"; break; } +#endif TRACELOG(LOG_INFO, "GLFW platform: %s", glfwPlatform); TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (GLFW): Initialized successfully"); From 3abe728712fb10e215ffcf97a1b06178895692d3 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 8 Jul 2024 22:54:19 +0200 Subject: [PATCH 14/41] Minor tweaks --- src/platforms/rcore_desktop_glfw.c | 4 ++-- src/platforms/rcore_desktop_rgfw.c | 2 +- src/raudio.c | 2 +- src/rmodels.c | 2 +- src/rtext.c | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/platforms/rcore_desktop_glfw.c b/src/platforms/rcore_desktop_glfw.c index 67cf9deff..42c64402f 100644 --- a/src/platforms/rcore_desktop_glfw.c +++ b/src/platforms/rcore_desktop_glfw.c @@ -1619,9 +1619,9 @@ int InitPlatform(void) #if defined(__NetBSD__) // Workaround for NetBSD - char* glfwPlatform = "X11"; + char *glfwPlatform = "X11"; #else - char* glfwPlatform = ""; + char *glfwPlatform = ""; switch (glfwGetPlatform()) { case GLFW_PLATFORM_WIN32: glfwPlatform = "Win32"; break; diff --git a/src/platforms/rcore_desktop_rgfw.c b/src/platforms/rcore_desktop_rgfw.c index d53237fcd..7dfe1f51c 100644 --- a/src/platforms/rcore_desktop_rgfw.c +++ b/src/platforms/rcore_desktop_rgfw.c @@ -79,7 +79,7 @@ void CloseWindow(void); #endif #ifdef _MSC_VER -__declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int CodePage, unsigned long dwFlags, const char* lpMultiByteStr, int cbMultiByte, wchar_t* lpWideCharStr, int cchWideChar); +__declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int CodePage, unsigned long dwFlags, const char *lpMultiByteStr, int cbMultiByte, wchar_t *lpWideCharStr, int cchWideChar); #endif #include "../external/RGFW.h" diff --git a/src/raudio.c b/src/raudio.c index e33712978..21d1adae3 100644 --- a/src/raudio.c +++ b/src/raudio.c @@ -1550,7 +1550,7 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data, else if ((strcmp(fileType, ".ogg") == 0) || (strcmp(fileType, ".OGG") == 0)) { // Open ogg audio stream - stb_vorbis* ctxOgg = stb_vorbis_open_memory((const unsigned char*)data, dataSize, NULL, NULL); + stb_vorbis* ctxOgg = stb_vorbis_open_memory((const unsigned char *)data, dataSize, NULL, NULL); if (ctxOgg != NULL) { diff --git a/src/rmodels.c b/src/rmodels.c index c6acff5dc..50328fca7 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -4294,7 +4294,7 @@ static Model LoadIQM(const char *fileName) // In case file can not be read, return an empty model if (fileDataPtr == NULL) return model; - const char* basePath = GetDirectoryPath(fileName); + const char *basePath = GetDirectoryPath(fileName); // Read IQM header IQMHeader *iqmHeader = (IQMHeader *)fileDataPtr; diff --git a/src/rtext.c b/src/rtext.c index 8daf3a7bc..755b15efd 100644 --- a/src/rtext.c +++ b/src/rtext.c @@ -1572,7 +1572,7 @@ char *TextReplace(const char *text, const char *replace, const char *by) byLen = TextLength(by); // Count the number of replacements needed - insertPoint = (char*)text; + insertPoint = (char *)text; for (count = 0; (temp = strstr(insertPoint, replace)); count++) insertPoint = temp + replaceLen; // Allocate returning string and point temp to it @@ -2339,7 +2339,7 @@ static GlyphInfo *LoadFontDataBDF(const unsigned char *fileData, int dataSize, i int readBytes = 0; // Data bytes read (line) int readVars = 0; // Variables filled by sscanf() - const char *fileText = (const char*)fileData; + const char *fileText = (const char *)fileData; const char *fileTextPtr = fileText; bool fontMalformed = false; // Is the font malformed From 98662b6a4a77994000348891820b6785d4a3b09e Mon Sep 17 00:00:00 2001 From: Colleague Riley Date: Tue, 9 Jul 2024 03:12:03 -0400 Subject: [PATCH 15/41] update RGFW to RGFW 1.0 (#4144) * update RGFW * fix bug with GetCurrentMonitor --- src/external/RGFW.h | 4182 ++++++++++++++-------------- src/platforms/rcore_desktop_rgfw.c | 92 +- 2 files changed, 2125 insertions(+), 2149 deletions(-) diff --git a/src/external/RGFW.h b/src/external/RGFW.h index 86e68a17f..646ecc9a0 100644 --- a/src/external/RGFW.h +++ b/src/external/RGFW.h @@ -37,7 +37,6 @@ This version doesn't work for desktops (I'm pretty sure) #define RGFW_OPENGL_ES2 - (optional) use OpenGL ES (version 2) #define RGFW_OPENGL_ES3 - (optional) use OpenGL ES (version 3) - #define RGFW_VULKAN - (optional) use vulkan for the rendering backend (rather than opengl) #define RGFW_DIRECTX - (optional) use directX for the rendering backend (rather than opengl) (windows only, defaults to opengl for unix) #define RGFW_NO_API - (optional) don't use any rendering API (no opengl, no vulkan, no directX) @@ -59,7 +58,7 @@ /* Credits : - EimaMei/Sacode : Much of the code for creating windows using winapi, Wrote the Silicon library, helped with MacOS Support + EimaMei/Sacode : Much of the code for creating windows using winapi, Wrote the Silicon library, helped with MacOS Support, siliapp.h -> referencing stb - This project is heavily inspired by the stb single header files @@ -72,6 +71,13 @@ Copyright (c) 2002-2006 Marcus Geelnard Copyright (c) 2006-2019 Camilla Löwy + + contributors : (feel free to put yourself here if you contribute) + krisvers -> code review + EimaMei (SaCode) -> code review + Code-Nycticebus -> bug fixes + Rob Rohan -> X11 bugs and missing features + AICDG (@THISISAGOODNAME) -> vulkan support (example) */ #ifndef RGFW_MALLOC @@ -90,6 +96,12 @@ #endif #endif +/* for windows 95 testing (not that it works well) */ +#ifdef RGFW_WIN95 +#define RGFW_NO_MONITOR +#define RGFW_NO_PASSTHROUGH +#endif + #ifndef RGFWDEF #ifdef __APPLE__ #define RGFWDEF static inline @@ -98,8 +110,12 @@ #endif #endif +#ifndef RGFW_ENUM +#define RGFW_ENUM(type, name) type name; enum +#endif + #ifndef RGFW_UNUSED -#define RGFW_UNUSED(x) if (x){} +#define RGFW_UNUSED(x) (void)(x); #endif #ifdef __cplusplus @@ -135,6 +151,10 @@ extern "C" { #endif #endif +#if !defined(b8) + typedef u8 b8; +#endif + #if defined(RGFW_X11) && defined(__APPLE__) #define RGFW_MACOS_X11 #undef __APPLE__ @@ -161,16 +181,18 @@ extern "C" { #undef _X86_ #else #undef _AMD64_ +#ifndef _X86_ #define _X86_ #endif +#endif -#include - +#ifndef RGFW_NO_XINPUT #ifdef __MINGW32__ #include #else #include #endif +#endif #else #if defined(__unix__) || defined(RGFW_MACOS_X11) || defined(RGFW_X11) @@ -192,28 +214,10 @@ extern "C" { #undef RGFW_EGL #endif -#if !defined(RGFW_OSMESA) && !defined(RGFW_EGL) && !defined(RGFW_OPENGL) && !defined (RGFW_VULKAN) && !defined(RGFW_DIRECTX) && !defined(RGFW_BUFFER) && !defined(RGFW_NO_API) +#if !defined(RGFW_OSMESA) && !defined(RGFW_EGL) && !defined(RGFW_OPENGL) && !defined(RGFW_DIRECTX) && !defined(RGFW_BUFFER) && !defined(RGFW_NO_API) #define RGFW_OPENGL #endif -#ifdef RGFW_VULKAN -#ifndef RGFW_MAX_FRAMES_IN_FLIGHT -#define RGFW_MAX_FRAMES_IN_FLIGHT 2 -#endif - -#ifdef RGFW_X11 -#define VK_USE_PLATFORM_XLIB_KHR -#endif -#ifdef RGFW_WINDOWS -#define VK_USE_PLATFORM_WIN32_KHR -#endif -#ifdef RGFW_MACOS -#define VK_USE_PLATFORM_MACOS_MVK -#endif - -#include -#endif - #if defined(RGFW_X11) && (defined(RGFW_OPENGL)) #ifndef GLX_MESA_swap_control #define GLX_MESA_swap_control @@ -244,8 +248,12 @@ extern "C" { #endif #endif - /*! Optional arguments for making a windows */ -#define RGFW_TRANSPARENT_WINDOW (1L<<9) /*!< the window is transparent */ +#ifndef RGFW_ALPHA +#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 */ +#define RGFW_TRANSPARENT_WINDOW (1L<<9) /*!< the window is transparent (only properly works on X11 and MacOS, although it's although for windows) */ #define RGFW_NO_BORDER (1L<<3) /*!< the window doesn't have border */ #define RGFW_NO_RESIZE (1L<<4) /*!< the window cannot be resized by the user */ #define RGFW_ALLOW_DND (1L<<5) /*!< the window supports drag and drop*/ @@ -255,6 +263,7 @@ extern "C" { #define RGFW_OPENGL_SOFTWARE (1L<<11) /*! use OpenGL software rendering */ #define RGFW_COCOA_MOVE_TO_RESOURCE_DIR (1L << 12) /* (cocoa only), move to resource folder */ #define RGFW_SCALE_TO_MONITOR (1L << 13) /* scale the window to the screen */ +#define RGFW_NO_INIT_API (1L << 2) /* DO not init an API (mostly for bindings, you should use `#define RGFW_NO_API` in 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)*/ @@ -298,6 +307,11 @@ extern "C" { #define RGFW_focusIn 12 /*!< window is in focus now */ #define RGFW_focusOut 13 /*!< window is out of focus now */ +#define RGFW_mouseEnter 14 /* mouse entered the window */ +#define RGFW_mouseLeave 15 /* mouse left the window */ + +#define RGFW_windowRefresh 16 /* The window content needs to be refreshed */ + /* attribs change event note The event data is sent straight to the window structure with win->r.x, win->r.y, win->r.w and win->r.h @@ -334,23 +348,25 @@ extern "C" { #define RGFW_NUMLOCK (1L << 2) /*! joystick button codes (based on xbox/playstation), you may need to change these values per controller */ -#ifndef RGFW_JS_A +#ifndef RGFW_joystick_codes -#define RGFW_JS_A 0 /* or PS X button */ -#define RGFW_JS_B 1 /* or PS circle button */ -#define RGFW_JS_Y 2 /* or PS triangle button */ -#define RGFW_JS_X 3 /* or PS square button */ -#define RGFW_JS_START 9 /* start button */ -#define RGFW_JS_SELECT 8 /* select button */ -#define RGFW_JS_HOME 10 /* home button */ -#define RGFW_JS_UP 13 /* dpad up */ -#define RGFW_JS_DOWN 14 /* dpad down*/ -#define RGFW_JS_LEFT 15 /* dpad left */ -#define RGFW_JS_RIGHT 16 /* dpad right */ -#define RGFW_JS_L1 4 /* left bump */ -#define RGFW_JS_L2 5 /* left trigger*/ -#define RGFW_JS_R1 6 /* right bumper */ -#define 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 @@ -373,6 +389,7 @@ typedef struct { i32 x, y; } RGFW_vector; #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 typedef struct RGFW_monitor { char name[128]; /* monitor name */ RGFW_rect rect; /* monitor Workarea */ @@ -388,14 +405,11 @@ typedef struct { i32 x, y; } RGFW_vector; RGFWDEF RGFW_monitor* RGFW_getMonitors(void); /* get the primary monitor */ RGFWDEF RGFW_monitor RGFW_getPrimaryMonitor(void); + #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 { -#ifdef RGFW_WINDOWS char keyName[16]; /* key name of event*/ -#else - char* keyName; /*!< key name of event */ -#endif /*! drag and drop data */ /* 260 max paths with a max length of 260 */ @@ -408,12 +422,13 @@ typedef struct { i32 x, y; } RGFW_vector; u32 type; /*!< which event has been sent?*/ RGFW_vector point; /*!< mouse x, y of event (or drop point) */ - u32 keyCode; /*!< keycode of event !!Keycodes defined at the bottom of the RGFW_HEADER part of this file!! */ - + 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!! */ - u8 inFocus; /*if the window is in focus or not*/ + 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; @@ -441,7 +456,7 @@ typedef struct { i32 x, y; } RGFW_vector; u32 display; void* displayLink; void* window; - u8 dndPassed; + b8 dndPassed; #endif #if (defined(RGFW_OPENGL)) && !defined(RGFW_OSMESA) @@ -455,15 +470,6 @@ typedef struct { i32 x, y; } RGFW_vector; GLXContext rSurf; /*!< source graphics context */ #endif #else -#ifdef RGFW_VULKAN - VkSurfaceKHR rSurf; /*!< source graphics context */ - - /* vulkan data */ - VkSwapchainKHR swapchain; - u32 image_count; - VkImage* swapchain_images; - VkImageView* swapchain_image_views; -#endif #ifdef RGFW_OSMESA OSMesaContext rSurf; @@ -495,6 +501,7 @@ typedef struct { i32 x, y; } RGFW_vector; #endif #ifdef RGFW_X11 XImage* bitmap; + GC gc; #endif #ifdef RGFW_MACOS void* bitmap; /* API's bitmap for storing or managing */ @@ -513,7 +520,7 @@ typedef struct { i32 x, y; } RGFW_vector; RGFW_area scale; /* window scaling */ #ifdef RGFW_MACOS - u8 cursorChanged; /* for steve jobs */ + b8 cursorChanged; /* for steve jobs */ #endif u32 winArgs; /* windows args (for RGFW to check) */ @@ -545,6 +552,9 @@ 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) */ + RGFW_window* RGFW_createWindow( const char* name, /* name of the window */ RGFW_rect rect, /* rect of window */ @@ -561,9 +571,19 @@ typedef struct { i32 x, y; } RGFW_vector; ex. 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` */ - RGFW_Event* RGFW_window_checkEvent(RGFW_window* win); /*!< check events (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); + /*! window managment functions*/ RGFWDEF void RGFW_window_close(RGFW_window* win); /*!< close the window and free leftover data */ @@ -572,9 +592,10 @@ typedef struct { i32 x, y; } RGFW_vector; RGFW_vector v/* new pos*/ ); + #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*/ ); @@ -588,6 +609,14 @@ typedef struct { i32 x, y; } RGFW_vector; 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)*/ + 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)*/ + + #ifndef RGFW_NO_PASSTHROUGH + RGFWDEF void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough); /* turn on / off mouse passthrough */ + #endif + RGFWDEF void RGFW_window_setName(RGFW_window* win, char* name ); @@ -638,16 +667,18 @@ typedef struct { i32 x, y; } RGFW_vector; RGFWDEF void RGFW_window_moveMouse(RGFW_window* win, RGFW_vector v); /* if the window should close (RGFW_close was sent or escape was pressed) */ - RGFWDEF u8 RGFW_window_shouldClose(RGFW_window* win); + RGFWDEF b8 RGFW_window_shouldClose(RGFW_window* win); /* if window is fullscreen'd */ - RGFWDEF u8 RGFW_window_isFullscreen(RGFW_window* win); + RGFWDEF b8 RGFW_window_isFullscreen(RGFW_window* win); /* if window is hidden */ - RGFWDEF u8 RGFW_window_isHidden(RGFW_window* win); + RGFWDEF b8 RGFW_window_isHidden(RGFW_window* win); /* if window is minimized */ - RGFWDEF u8 RGFW_window_isMinimized(RGFW_window* win); + RGFWDEF b8 RGFW_window_isMinimized(RGFW_window* win); /* if window is maximized */ - RGFWDEF u8 RGFW_window_isMaximized(RGFW_window* win); + RGFWDEF b8 RGFW_window_isMaximized(RGFW_window* win); + + #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 @@ -655,53 +686,91 @@ typedef struct { i32 x, y; } RGFW_vector; 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 /*!< make the window the current opengl drawing context */ RGFWDEF void RGFW_window_makeCurrent(RGFW_window* win); /*error handling*/ - RGFWDEF u8 RGFW_Error(void); /* returns true if an error has occurred (doesn't print errors itself) */ + RGFWDEF b8 RGFW_Error(void); /* returns true if an error has occurred (doesn't print errors itself) */ /*!< 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 u8 RGFW_isPressedI(RGFW_window* win, u32 key); /*!< if key is pressed (key code)*/ + RGFWDEF b8 RGFW_isPressed(RGFW_window* win, u8 key); /*!< if key is pressed (key code)*/ - RGFWDEF u8 RGFW_wasPressedI(RGFW_window* win, u32 key); /*!< if key was pressed (checks prev keymap only) (key code)*/ + RGFWDEF b8 RGFW_wasPressed(RGFW_window* win, u8 key); /*!< if key was pressed (checks prev keymap only) (key code)*/ - RGFWDEF u8 RGFW_isHeldI(RGFW_window* win, u32 key); /*!< if key is held (key code)*/ - RGFWDEF u8 RGFW_isReleasedI(RGFW_window* win, u32 key); /*!< if key is released (key code)*/ + 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)*/ - RGFWDEF u8 RGFW_isMousePressed(RGFW_window* win, u8 button); - RGFWDEF u8 RGFW_isMouseHeld(RGFW_window* win, u8 button); - RGFWDEF u8 RGFW_isMouseReleased(RGFW_window* win, u8 button); - RGFWDEF u8 RGFW_wasMousePressed(RGFW_window* win, u8 button); + RGFWDEF b8 RGFW_isClicked(RGFW_window* win, u8 key); - /* - !!Keycodes defined at the bottom of RGFW_HEADER part of this file!! - */ - /*!< converts a key code to it's key string */ - RGFWDEF char* RGFW_keyCodeTokeyStr(u64 key); - /*!< converts a string of a key to it's key code */ - RGFWDEF u32 RGFW_keyStrToKeyCode(char* key); - /*!< if key is pressed (key string) */ -#define RGFW_isPressedS(win, key) RGFW_isPressedI(win, RGFW_keyStrToKeyCode(key)) + 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); /*! clipboard functions*/ RGFWDEF char* RGFW_readClipboard(size_t* size); /*!< read clipboard data */ -#define RGFW_clipboardFree free /* the string returned from RGFW_readClipboard must be freed */ + 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 */ - /* - convert a keyString to a char version - */ - RGFWDEF char RGFW_keystrToChar(const char*); - /* - ex. - "parenleft" -> '(' - "A" -> 'A', - "Return" -> "\n" + /* + + + 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_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 + typedef void (* RGFW_dndfunc)(RGFW_window* win, char** droppedFiles, u32 droppedFilesCount); + #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); + + #ifndef RGFW_NO_THREADS /*! threading functions*/ @@ -715,7 +784,7 @@ typedef struct { i32 x, y; } RGFW_vector; #if defined(__unix__) || defined(__APPLE__) typedef void* (* RGFW_threadFunc_ptr)(void*); #else - typedef DWORD (* RGFW_threadFunc_ptr)(void*); + typedef DWORD (__stdcall *RGFW_threadFunc_ptr) (LPVOID lpThreadParameter); #endif RGFWDEF RGFW_thread RGFW_createThread(RGFW_threadFunc_ptr ptr, void* args); /*!< create a thread*/ @@ -746,63 +815,14 @@ typedef struct { i32 x, y; } RGFW_vector; /*! Set OpenGL version hint */ 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); - -#ifdef RGFW_VULKAN - typedef struct { - VkInstance instance; - VkPhysicalDevice physical_device; - VkDevice device; - - VkDebugUtilsMessengerEXT debugMessenger; - - VkQueue graphics_queue; - VkQueue present_queue; - - VkFramebuffer* framebuffers; - - VkRenderPass render_pass; - VkPipelineLayout pipeline_layout; - VkPipeline graphics_pipeline; - - VkCommandPool command_pool; - VkCommandBuffer* command_buffers; - - VkSemaphore* available_semaphores; - VkSemaphore* finished_semaphore; - VkFence* in_flight_fences; - VkFence* image_in_flight; - size_t current_frame; - } RGFW_vulkanInfo; - - /*! initializes a vulkan rendering context for the RGFW window, - this outputs the vulkan surface into wwin->src.rSurf - other vulkan data is stored in the global instance of the RGFW_vulkanInfo structure which is returned - by the initVulkan() function - RGFW_VULKAN must be defined for this function to be defined - - */ - RGFWDEF RGFW_vulkanInfo* RGFW_initVulkan(RGFW_window* win); - RGFWDEF void RGFW_freeVulkan(void); - - RGFWDEF RGFW_vulkanInfo* RGFW_getVulkanInfo(void); - - RGFWDEF int RGFW_initData(RGFW_window* win); - RGFWDEF void RGFW_createSurface(VkInstance instance, RGFW_window* win); - int RGFW_deviceInitialization(RGFW_window* win); - int RGFW_createSwapchain(RGFW_window* win); - RGFWDEF int RGFW_createRenderPass(void); - int RGFW_createCommandPool(void); - int RGFW_createCommandBuffers(RGFW_window* win); - int RGFW_createSyncObjects(RGFW_window* win); - RGFWDEF int RGFW_createFramebuffers(RGFW_window* win); -#endif - + RGFWDEF void RGFW_window_setCPURender(RGFW_window* win, i8 set); #ifdef RGFW_DIRECTX typedef struct { IDXGIFactory* pFactory; @@ -824,7 +844,7 @@ typedef struct { i32 x, y; } RGFW_vector; RGFWDEF u64 RGFW_getTimeNS(void); /* get time in nanoseconds */ RGFWDEF void RGFW_sleep(u64 microsecond); /* sleep for a set time */ - typedef enum { + typedef RGFW_ENUM(u8, RGFW_Key) { RGFW_KEY_NULL = 0, RGFW_Escape, RGFW_F1, @@ -932,10 +952,12 @@ typedef struct { i32 x, y; } RGFW_vector; RGFW_KP_9, RGFW_KP_0, RGFW_KP_Period, - RGFW_KP_Return - } RGFW_Key; + RGFW_KP_Return, - typedef enum RGFW_mouseIcons { + final_key, + }; + + typedef RGFW_ENUM(u8, RGFW_mouseIcons) { RGFW_MOUSE_NORMAL = 0, RGFW_MOUSE_ARROW, RGFW_MOUSE_IBEAM, @@ -947,7 +969,7 @@ typedef struct { i32 x, y; } RGFW_vector; RGFW_MOUSE_RESIZE_NESW, RGFW_MOUSE_RESIZE_ALL, RGFW_MOUSE_NOT_ALLOWED, - } RGFW_mouseIcons; + }; #endif /* RGFW_HEADER */ @@ -970,7 +992,7 @@ typedef struct { i32 x, y; } RGFW_vector; for (;;) { RGFW_window_checkEvent(win); // NOTE: checking events outside of a while loop may cause input lag - if (win->event.type == RGFW_quit || RGFW_isPressedI(win, RGFW_Escape)) + if (win->event.type == RGFW_quit || RGFW_isPressed(win, RGFW_Escape)) break; RGFW_window_swapBuffers(win); @@ -1024,11 +1046,14 @@ typedef struct { i32 x, y; } RGFW_vector; #include /* - +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 */ u8 RGFW_keycodes[] = { @@ -1146,17 +1171,13 @@ This is the start of keycode data [RGFW_OS_BASED_VALUE(110, 0x24, 116)] = RGFW_Home, }; - #ifdef RGFW_X11 - u8 RGFW_mouseIconSrc[] = {68, 68, 152, 34, 60, 108, 116, 12, 14, 52, 0}; - #elif defined(RGFW_WINDOWS) - u32 RGFW_mouseIconSrc[] = {32512, 32512, 32513, 32515, 32649, 32644, 32645, 32642, 32643, 32646, 32648}; - #elif defined(RGFW_MACOS) - char* RGFW_mouseIconSrc[] = {"arrowCursor", "arrowCursor", "IBeamCursor", "crosshairCursor", "pointingHandCursor", "resizeLeftRightCursor", "resizeUpDownCursor", "_windowResizeNorthWestSouthEastCursor", "_windowResizeNorthEastSouthWestCursor", "closedHandCursor", "operationNotAllowedCursor"}; - #endif - - u8 RGFW_keyboard[128] = { 0 }; - u8 RGFW_keyboard_prev[128]; + typedef struct { + b8 current : 1; + b8 prev : 1; + } RGFW_keyState; + RGFW_keyState RGFW_keyboard[final_key] = { {0, 0} }; + RGFWDEF u32 RGFW_apiKeyCodeToRGFW(u32 keycode); u32 RGFW_apiKeyCodeToRGFW(u32 keycode) { @@ -1166,415 +1187,81 @@ This is the start of keycode data return RGFW_keycodes[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; + } + /* - -this is the end of keycode data - + this is the end of keycode data */ -#ifdef RGFW_WINDOWS -#include +/* + event callback defines start here +*/ -#endif -#ifdef RGFW_MACOS /* - based on silicon.h + 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); } -#ifndef GL_SILENCE_DEPRECATION -#define GL_SILENCE_DEPRECATION -#endif + #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 -#include -#include -#include -#include + 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; - typedef CGRect NSRect; - typedef CGPoint NSPoint; - typedef CGSize NSSize; - - typedef void NSBitmapImageRep; - typedef void NSCursor; - typedef void NSDraggingInfo; - typedef void NSWindow; - typedef void NSApplication; - typedef void NSScreen; - typedef void NSEvent; - typedef void NSString; - typedef void NSOpenGLContext; - typedef void NSPasteboard; - typedef void NSColor; - typedef void NSArray; - typedef void NSImageRep; - typedef void NSImage; - typedef void NSOpenGLView; - - - typedef const char* NSPasteboardType; - typedef unsigned long NSUInteger; - typedef long NSInteger; - typedef NSInteger NSModalResponse; - -#ifdef __arm64__ - /* ARM just uses objc_msgSend */ -#define abi_objc_msgSend_stret objc_msgSend -#define abi_objc_msgSend_fpret objc_msgSend -#else /* __i386__ */ - /* x86 just uses abi_objc_msgSend_fpret and (NSColor *)objc_msgSend_id respectively */ -#define abi_objc_msgSend_stret objc_msgSend_stret -#define abi_objc_msgSend_fpret objc_msgSend_fpret -#endif - -#define NSAlloc(nsclass) objc_msgSend_id((id)nsclass, sel_registerName("alloc")) -#define objc_msgSend_bool ((BOOL (*)(id, SEL))objc_msgSend) -#define objc_msgSend_void ((void (*)(id, SEL))objc_msgSend) -#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_void_SEL ((void (*)(id, SEL, SEL))objc_msgSend) -#define objc_msgSend_id ((id (*)(id, SEL))objc_msgSend) - -#define si_declare_single(class, name, func) \ - void class##_##name(class* obj) { \ - return objc_msgSend_void(obj, sel_registerName(func)); \ - } - - -#define loadFunc(funcName) \ - static void* func = NULL;\ - if (func == NULL) \ - func = sel_registerName(funcName); - - void NSRelease(id obj) { - loadFunc("release"); - objc_msgSend_void(obj, func); - } - -#define release NSRelease - - si_declare_single(NSApplication, finishLaunching, "finishLaunching") - si_declare_single(NSOpenGLContext, flushBuffer, "flushBuffer") - - NSString* NSString_stringWithUTF8String(const char* str) { - loadFunc("stringWithUTF8String:"); - - return ((id(*)(id, SEL, const char*))objc_msgSend) - ((id)objc_getClass("NSString"), func, str); - } - - const char* NSString_to_char(NSString* str) { - return ((const char* (*)(id, SEL)) objc_msgSend) (str, sel_registerName("UTF8String")); - } - - void si_impl_func_to_SEL_with_name(const char* class_name, const char* register_name, void* function) { - Class selected_class; - - if (strcmp(class_name, "NSView") == 0) { - selected_class = objc_getClass("ViewClass"); - } else if (strcmp(class_name, "NSWindow") == 0) { - selected_class = objc_getClass("WindowClass"); - } else { - selected_class = objc_getClass(class_name); - } - - class_addMethod(selected_class, sel_registerName(register_name), (IMP) function, 0); - } - - /* Header for the array. */ - typedef struct siArrayHeader { - size_t count; - /* TODO(EimaMei): Add a `type_width` later on. */ - } siArrayHeader; - - /* Gets the header of the siArray. */ -#define SI_ARRAY_HEADER(s) ((siArrayHeader*)s - 1) - - void* si_array_init_reserve(size_t sizeof_element, size_t count) { - siArrayHeader* ptr = malloc(sizeof(siArrayHeader) + (sizeof_element * count)); - void* array = ptr + sizeof(siArrayHeader); - - siArrayHeader* header = SI_ARRAY_HEADER(array); - header->count = count; - - return array; - } - -#define si_array_len(array) (SI_ARRAY_HEADER(array)->count) -#define si_func_to_SEL(class_name, function) si_impl_func_to_SEL_with_name(class_name, #function":", function) - /* Creates an Objective-C method (SEL) from a regular C function with the option to set the register name.*/ -#define si_func_to_SEL_with_name(class_name, register_name, function) si_impl_func_to_SEL_with_name(class_name, register_name":", function) - - NSRect NSMakeRect(double x, double y, double width, double height) { - NSRect r; - r.origin.x = x; - r.origin.y = y; - r.size.width = width; - r.size.height = height; - - return r; - } - - NSPoint NSMakePoint(double x, double y) { - NSPoint point; - point.x = x; - point.y = y; - return point; - } - - NSSize NSMakeSize(double w, double h) { - NSSize size; - size.width = w; - size.height = h; - return size; - } - - void* si_array_init(void* allocator, size_t sizeof_element, size_t count) { - void* array = si_array_init_reserve(sizeof_element, count); - memcpy(array, allocator, sizeof_element * count); - - return array; - } + 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; }} - unsigned char* NSBitmapImageRep_bitmapData(NSBitmapImageRep* imageRep) { - return ((unsigned char* (*)(id, SEL))objc_msgSend) - (imageRep, sel_registerName("bitmapData")); - } - -#define NS_ENUM(type, name) type name; enum - - typedef NS_ENUM(NSUInteger, NSBitmapFormat) { - NSBitmapFormatAlphaFirst = 1 << 0, // 0 means is alpha last (RGBA, CMYKA, etc.) - NSBitmapFormatAlphaNonpremultiplied = 1 << 1, // 0 means is premultiplied - NSBitmapFormatFloatingPointSamples = 1 << 2, // 0 is integer - - NSBitmapFormatSixteenBitLittleEndian API_AVAILABLE(macos(10.10)) = (1 << 8), - NSBitmapFormatThirtyTwoBitLittleEndian API_AVAILABLE(macos(10.10)) = (1 << 9), - NSBitmapFormatSixteenBitBigEndian API_AVAILABLE(macos(10.10)) = (1 << 10), - NSBitmapFormatThirtyTwoBitBigEndian API_AVAILABLE(macos(10.10)) = (1 << 11) - }; - - NSBitmapImageRep* NSBitmapImageRep_initWithBitmapData(unsigned char** planes, NSInteger width, NSInteger height, NSInteger bps, NSInteger spp, bool alpha, bool isPlanar, const char* colorSpaceName, NSBitmapFormat bitmapFormat, NSInteger rowBytes, NSInteger pixelBits) { - void* func = sel_registerName("initWithBitmapDataPlanes:pixelsWide:pixelsHigh:bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:colorSpaceName:bitmapFormat:bytesPerRow:bitsPerPixel:"); - - return (NSBitmapImageRep*) ((id(*)(id, SEL, unsigned char**, NSInteger, NSInteger, NSInteger, NSInteger, bool, bool, const char*, NSBitmapFormat, NSInteger, NSInteger))objc_msgSend) - (NSAlloc((id)objc_getClass("NSBitmapImageRep")), func, planes, width, height, bps, spp, alpha, isPlanar, NSString_stringWithUTF8String(colorSpaceName), bitmapFormat, rowBytes, pixelBits); - } - - NSColor* NSColor_colorWithSRGB(CGFloat red, CGFloat green, CGFloat blue, CGFloat alpha) { - void* nsclass = objc_getClass("NSColor"); - void* func = sel_registerName("colorWithSRGBRed:green:blue:alpha:"); - return ((id(*)(id, SEL, CGFloat, CGFloat, CGFloat, CGFloat))objc_msgSend) - (nsclass, func, red, green, blue, alpha); - } - - NSCursor* NSCursor_initWithImage(NSImage* newImage, NSPoint aPoint) { - void* func = sel_registerName("initWithImage:hotSpot:"); - void* nsclass = objc_getClass("NSCursor"); - - return (NSCursor*) ((id(*)(id, SEL, id, NSPoint))objc_msgSend) - (NSAlloc(nsclass), func, newImage, aPoint); - } - - void NSImage_addRepresentation(NSImage* image, NSImageRep* imageRep) { - void* func = sel_registerName("addRepresentation:"); - objc_msgSend_void_id(image, func, imageRep); - } - - NSImage* NSImage_initWithSize(NSSize size) { - void* func = sel_registerName("initWithSize:"); - return ((id(*)(id, SEL, NSSize))objc_msgSend) - (NSAlloc((id)objc_getClass("NSImage")), func, size); - } -#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 */ - 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) */ - NSOpenGLContextParameterGPUFragmentProcessing NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 311, /* 1 param. Currently processing fragments with GPU (get) */ - NSOpenGLContextParameterHasDrawable NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 314, /* 1 param. Boolean returned if drawable is attached */ - NSOpenGLContextParameterMPSwapsInFlight NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 315, /* 1 param. Max number of swaps queued by the MP GL engine */ - - NSOpenGLContextParameterSwapRectangle API_DEPRECATED("", macos(10.0, 10.14)) = 200, /* 4 params. Set or get the swap rectangle {x, y, w, h} */ - 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 */ - }; - - - void NSOpenGLContext_setValues(NSOpenGLContext* context, const int* vals, NSOpenGLContextParameter param) { - void* func = sel_registerName("setValues:forParameter:"); - ((void (*)(id, SEL, const int*, NSOpenGLContextParameter))objc_msgSend) - (context, func, vals, param); - } - - void* NSOpenGLPixelFormat_initWithAttributes(const uint32_t* attribs) { - void* func = sel_registerName("initWithAttributes:"); - return (void*) ((id(*)(id, SEL, const uint32_t*))objc_msgSend) - (NSAlloc((id)objc_getClass("NSOpenGLPixelFormat")), func, attribs); - } - - NSOpenGLView* NSOpenGLView_initWithFrame(NSRect frameRect, uint32_t* format) { - void* func = sel_registerName("initWithFrame:pixelFormat:"); - return (NSOpenGLView*) ((id(*)(id, SEL, NSRect, uint32_t*))objc_msgSend) - (NSAlloc((id)objc_getClass("NSOpenGLView")), func, frameRect, format); - } - - void NSCursor_performSelector(NSCursor* cursor, void* selector) { - void* func = sel_registerName("performSelector:"); - objc_msgSend_void_SEL(cursor, func, selector); - } - - NSPasteboard* NSPasteboard_generalPasteboard(void) { - return (NSPasteboard*) objc_msgSend_id((id)objc_getClass("NSPasteboard"), sel_registerName("generalPasteboard")); - } - - NSString** cstrToNSStringArray(char** strs, size_t len) { - static NSString* nstrs[6]; - size_t i; - for (i = 0; i < len; i++) - nstrs[i] = NSString_stringWithUTF8String(strs[i]); - - return nstrs; - } - - const char* NSPasteboard_stringForType(NSPasteboard* pasteboard, NSPasteboardType dataType) { - void* func = sel_registerName("stringForType:"); - return (const char*) NSString_to_char(((id(*)(id, SEL, const char*))objc_msgSend)(pasteboard, func, NSString_stringWithUTF8String(dataType))); - } - - NSArray* c_array_to_NSArray(void* array, size_t len) { - SEL func = sel_registerName("initWithObjects:count:"); - void* nsclass = objc_getClass("NSArray"); - return ((id (*)(id, SEL, void*, NSUInteger))objc_msgSend) - (NSAlloc(nsclass), func, array, len); - } - - void NSregisterForDraggedTypes(void* view, NSPasteboardType* newTypes, size_t len) { - NSString** ntypes = cstrToNSStringArray((char**)newTypes, len); - - NSArray* array = c_array_to_NSArray(ntypes, len); - objc_msgSend_void_id(view, sel_registerName("registerForDraggedTypes:"), array); - NSRelease(array); - } - - NSInteger NSPasteBoard_declareTypes(NSPasteboard* pasteboard, NSPasteboardType* newTypes, size_t len, void* owner) { - NSString** ntypes = cstrToNSStringArray((char**)newTypes, len); - - void* func = sel_registerName("declareTypes:owner:"); - - NSArray* array = c_array_to_NSArray(ntypes, len); - - NSInteger output = ((NSInteger(*)(id, SEL, id, void*))objc_msgSend) - (pasteboard, func, array, owner); - NSRelease(array); - - return output; - } - - bool NSPasteBoard_setString(NSPasteboard* pasteboard, const char* stringToWrite, NSPasteboardType dataType) { - void* func = sel_registerName("setString:forType:"); - return ((bool (*)(id, SEL, id, NSPasteboardType))objc_msgSend) - (pasteboard, func, NSString_stringWithUTF8String(stringToWrite), NSString_stringWithUTF8String(dataType)); - } - - void NSRetain(id obj) { objc_msgSend_void(obj, sel_registerName("retain")); } - - typedef enum NSApplicationActivationPolicy { - NSApplicationActivationPolicyRegular, - NSApplicationActivationPolicyAccessory, - NSApplicationActivationPolicyProhibited - } NSApplicationActivationPolicy; - - typedef NS_ENUM(u32, NSBackingStoreType) { - NSBackingStoreRetained = 0, - NSBackingStoreNonretained = 1, - NSBackingStoreBuffered = 2 - }; - - typedef NS_ENUM(u32, NSWindowStyleMask) { - NSWindowStyleMaskBorderless = 0, - NSWindowStyleMaskTitled = 1 << 0, - NSWindowStyleMaskClosable = 1 << 1, - NSWindowStyleMaskMiniaturizable = 1 << 2, - NSWindowStyleMaskResizable = 1 << 3, - NSWindowStyleMaskTexturedBackground = 1 << 8, /* deprecated */ - NSWindowStyleMaskUnifiedTitleAndToolbar = 1 << 12, - NSWindowStyleMaskFullScreen = 1 << 14, - NSWindowStyleMaskFullSizeContentView = 1 << 15, - NSWindowStyleMaskUtilityWindow = 1 << 4, - NSWindowStyleMaskDocModalWindow = 1 << 6, - NSWindowStyleMaskNonactivatingPanel = 1 << 7, - NSWindowStyleMaskHUDWindow = 1 << 13 - }; - - typedef const char* NSPasteboardType; - NSPasteboardType const NSPasteboardTypeString = "public.utf8-plain-text"; // Replaces NSStringPboardType - - - - typedef NS_ENUM(i32, NSDragOperation) { - NSDragOperationNone = 0, - NSDragOperationCopy = 1, - NSDragOperationLink = 2, - NSDragOperationGeneric = 4, - NSDragOperationPrivate = 8, - NSDragOperationMove = 16, - NSDragOperationDelete = 32, - NSDragOperationEvery = ULONG_MAX, - - //NSDragOperationAll_Obsolete API_DEPRECATED("", macos(10.0,10.10)) = 15, // Use NSDragOperationEvery - //NSDragOperationAll API_DEPRECATED("", macos(10.0,10.10)) = NSDragOperationAll_Obsolete, // Use NSDragOperationEvery - }; - - - NSUInteger NSArray_count(NSArray* array) { - void* func = sel_registerName("count"); - return ((NSUInteger(*)(id, SEL))objc_msgSend)(array, func); - } - - void* NSArray_objectAtIndex(NSArray* array, NSUInteger index) { - void* func = sel_registerName("objectAtIndex:"); - return ((id(*)(id, SEL, NSUInteger))objc_msgSend)(array, func, index); - } - - const char** NSPasteboard_readObjectsForClasses(NSPasteboard* pasteboard, Class* classArray, size_t len, void* options) { - void* func = sel_registerName("readObjectsForClasses:options:"); - - NSArray* array = c_array_to_NSArray(classArray, len); - - NSArray* output = (NSArray*) ((id(*)(id, SEL, id, void*))objc_msgSend) - (pasteboard, func, array, options); - - NSRelease(array); - NSUInteger count = NSArray_count(output); - - const char** res = si_array_init_reserve(sizeof(const char*), count); - - void* path_func = sel_registerName("path"); - - for (NSUInteger i = 0; i < count; i++) { - void* url = NSArray_objectAtIndex(output, i); - NSString* url_str = ((id(*)(id, SEL))objc_msgSend)(url, path_func); - res[i] = NSString_to_char(url_str); - } - - return res; - } - - void* NSWindow_contentView(NSWindow* window) { - void* func = sel_registerName("contentView"); - return objc_msgSend_id(window, func); - } -#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 +*/ #define RGFW_ASSERT(check, str) {\ if (!(check)) { \ @@ -1583,44 +1270,26 @@ this is the end of keycode data } \ } - u8 RGFW_error = 0; - u8 RGFW_Error() { return RGFW_error; } + b8 RGFW_error = 0; + b8 RGFW_Error() { return RGFW_error; } #define SET_ATTRIB(a, v) { \ assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \ attribs[index++] = a; \ attribs[index++] = v; \ } - -#define ADD_ATTRIB(a) { \ - assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \ - attribs[index++] = a; \ -} - -#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); + + RGFW_area RGFW_bufferSize = {0, 0}; + void RGFW_setBufferSize(RGFW_area size) { + RGFW_bufferSize = size; } -#endif - #ifdef RGFW_WINDOWS - __declspec(dllimport) u32 __stdcall timeBeginPeriod(u32 uPeriod); - #endif RGFWDEF RGFW_window* RGFW_window_basic_init(RGFW_rect rect, u16 args); - RGFWDEF void RGFW_init_buffer(RGFW_window* win); 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 */ - #ifdef RGFW_WINDOWS - timeBeginPeriod(1); - #endif - #ifdef RGFW_ALLOC_DROPFILES win->event.droppedFiles = (char**) RGFW_MALLOC(sizeof(char*) * RGFW_MAX_DROPS); u32 i; @@ -1628,13 +1297,6 @@ this is the end of keycode data win->event.droppedFiles[i] = (char*) RGFW_CALLOC(RGFW_MAX_PATH, sizeof(char)); #endif -#ifdef RGFW_X11 - /* open X11 display */ - /* this is done here so the screen size can be accessed */ - win->src.display = XOpenDisplay(NULL); - assert(win->src.display != NULL); -#endif - #ifndef RGFW_X11 RGFW_area screenR = RGFW_getScreenSize(); #else @@ -1657,662 +1319,236 @@ this is the end of keycode data win->event.inFocus = 1; win->event.droppedFilesCount = 0; win->src.joystickCount = 0; -#ifdef RGFW_MACOS - RGFW_window_setMouseDefault(win); -#endif -#ifdef RGFW_WINDOWS - win->src.maxSize = RGFW_AREA(0, 0); - win->src.minSize = RGFW_AREA(0, 0); -#endif 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); RGFW_window_resize(win, RGFW_AREA(((u32) monitor.scaleX) * win->r.w, ((u32) monitor.scaleX) * win->r.h)); } + #endif - void RGFW_init_buffer(RGFW_window* win) { -#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) - RGFW_area area = RGFW_getScreenSize(); -#if !(defined(RGFW_WINDOWS)) || defined(RGFW_OSMESA) - win->buffer = RGFW_MALLOC(area.w * area.h * 4); +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]; + + 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)); + } + + b8 RGFW_isPressed(RGFW_window* win, u8 key) { + assert(win != NULL); + return RGFW_keyboard[key].current && win->event.inFocus; + } + + b8 RGFW_wasPressed(RGFW_window* win, u8 key) { + assert(win != NULL); + return RGFW_keyboard[key].prev && win->event.inFocus; + } + + b8 RGFW_isHeld(RGFW_window* win, u8 key) { + return (RGFW_isPressed(win, key) && RGFW_wasPressed(win, key)); + } + + b8 RGFW_isClicked(RGFW_window* win, u8 key) { + return (RGFW_wasPressed(win, key) && !RGFW_isPressed(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); + +#if defined(RGFW_WINDOWS) && defined(RGFW_DIRECTX) + RGFW_dxInfo.pDeviceContext->lpVtbl->OMSetRenderTargets(RGFW_dxInfo.pDeviceContext, 1, &win->src.renderTargetView, NULL); #endif -#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); -#endif -#ifdef RGFW_X11 - win->src.bitmap = XCreateImage( - win->src.display, DefaultVisual(win->src.display, XDefaultScreen(win->src.display)), - DefaultDepth(win->src.display, XDefaultScreen(win->src.display)), - ZPixmap, 0, NULL, area.w, area.h, - 32, 0 - ); -#endif -#ifdef RGFW_WINDOWS - BITMAPV5HEADER bi = { 0 }; - ZeroMemory(&bi, sizeof(bi)); - bi.bV5Size = sizeof(bi); - bi.bV5Width = area.w; - bi.bV5Height = -((LONG) area.h); - bi.bV5Planes = 1; - bi.bV5BitCount = 32; - bi.bV5Compression = BI_BITFIELDS; - bi.bV5BlueMask = 0x00ff0000; - bi.bV5GreenMask = 0x0000ff00; - bi.bV5RedMask = 0x000000ff; - bi.bV5AlphaMask = 0xff000000; - - win->src.bitmap = CreateDIBSection(win->src.hdc, - (BITMAPINFO*) &bi, - DIB_RGB_COLORS, - (void**) &win->buffer, - NULL, - (DWORD) 0); - - win->src.hdcMem = CreateCompatibleDC(win->src.hdc); -#endif -#else -RGFW_UNUSED(win); /* if buffer rendering is not being used */ +#ifdef 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; + + else if (set && win->src.winArgs & RGFW_NO_GPU_RENDER) + win->src.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; + + else if (set && win->src.winArgs & RGFW_NO_CPU_RENDER) + win->src.winArgs ^= RGFW_NO_CPU_RENDER; + } + + void RGFW_window_maximize(RGFW_window* win) { + assert(win != NULL); + + RGFW_area screen = RGFW_getScreenSize(); + + RGFW_window_move(win, RGFW_VECTOR(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)); + } + + void RGFW_window_setShouldClose(RGFW_window* win) { win->event.type = RGFW_quit; RGFW_windowQuitCallback(win); } + + #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)); + } + #endif + + RGFWDEF void RGFW_clipCursor(RGFW_rect); + + #if !defined(RGFW_WINDOWS) && !defined(RGFW_MACOS) + void RGFW_clipCursor(RGFW_rect r) { RGFW_UNUSED(r) } + #endif + + 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); + + #ifndef RGFW_MACOS + RGFW_window_moveMouse(win, RGFW_VECTOR(win->r.x + (area.w), win->r.y + (area.h))); + #endif + } + + void RGFW_window_mouseUnhold(RGFW_window* win) { + if ((win->src.winArgs & RGFW_HOLD_MOUSE)) { + win->src.winArgs ^= RGFW_HOLD_MOUSE; + + RGFW_clipCursor(RGFW_RECT(0, 0, 0, 0)); + } + } + + void RGFW_window_checkFPS(RGFW_window* win) { + u64 deltaTime = RGFW_getTimeNS() - win->event.frameTime; + + 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 (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(); + } + + u32 RGFW_isPressedJS(RGFW_window* win, u16 c, u8 button) { return win->src.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 + + 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; + } + + #if defined(RGFW_X11) || defined(RGFW_MACOS) + struct timespec; + + 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); + + void RGFW_window_setDND(RGFW_window* win, b8 allow) { + if (allow && !(win->src.winArgs & RGFW_ALLOW_DND)) + win->src.winArgs |= RGFW_ALLOW_DND; + + else if (!allow && (win->src.winArgs & RGFW_ALLOW_DND)) + win->src.winArgs ^= RGFW_ALLOW_DND; + } + #endif + +/* + graphics API spcific code (end of generic code) + starts here +*/ + + +/* + OpenGL defines start here (Normal, EGL, OSMesa) +*/ + #if defined(RGFW_OPENGL) || defined(RGFW_EGL) || defined(RGFW_OSMESA) #ifndef __APPLE__ #include #else +#ifndef GL_SILENCE_DEPRECATION +#define GL_SILENCE_DEPRECATION +#endif #include -#endif +#include #endif -#ifdef RGFW_VULKAN - RGFW_vulkanInfo RGFW_vulkan_info; - - RGFW_vulkanInfo* RGFW_initVulkan(RGFW_window* win) { - assert(win != NULL); - - if ( - RGFW_initData(win) || - RGFW_deviceInitialization(win) || - RGFW_createSwapchain(win) - ) - return NULL; - - u32 graphics_family_index = 0; - u32 present_family_index = 0; - - vkGetDeviceQueue(RGFW_vulkan_info.device, graphics_family_index, 0, &RGFW_vulkan_info.graphics_queue); - vkGetDeviceQueue(RGFW_vulkan_info.device, present_family_index, 0, &RGFW_vulkan_info.present_queue); - - if ( - RGFW_createRenderPass() || - RGFW_createFramebuffers(win) || - RGFW_createCommandPool() || - RGFW_createCommandBuffers(win) || - RGFW_createSyncObjects(win) - ) - return NULL; - - return &RGFW_vulkan_info; - } - - int RGFW_initData(RGFW_window* win) { - assert(win != NULL); - - win->src.swapchain = VK_NULL_HANDLE; - win->src.image_count = 0; - RGFW_vulkan_info.current_frame = 0; - - return 0; - } - - void RGFW_createSurface(VkInstance instance, RGFW_window* win) { - assert(win != NULL); - assert(instance); - - win->src.rSurf = VK_NULL_HANDLE; - -#ifdef RGFW_X11 - VkXlibSurfaceCreateInfoKHR x11 = { VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, 0, 0, (Display*) win->src.display, (Window) win->src.window }; - - vkCreateXlibSurfaceKHR(RGFW_vulkan_info.instance, &x11, NULL, &win->src.rSurf); -#endif -#ifdef RGFW_WINDOWS - VkWin32SurfaceCreateInfoKHR win32 = { VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR, 0, 0, GetModuleHandle(NULL), win->src.window }; - - vkCreateWin32SurfaceKHR(RGFW_vulkan_info.instance, &win32, NULL, &win->src.rSurf); -#endif -#if defined(RGFW_MACOS) && !defined(RGFW_MACOS_X11) - VkMacOSSurfaceCreateFlagsMVK macos = { VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK, 0, 0, win->src.display, win->src.window }; - - vkCreateMacOSSurfaceMVK(RGFW_vulkan_info.instance, &macos, NULL, &win->src.rSurf); -#endif - } - - RGFW_vulkanInfo* RGFW_getVulkanInfo(void) { - return &RGFW_vulkan_info; - } - - int RGFW_deviceInitialization(RGFW_window* win) { - assert(win != NULL); - - VkApplicationInfo appInfo = { 0 }; - appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; - appInfo.pApplicationName = "RGFW app"; - appInfo.apiVersion = VK_MAKE_VERSION(1, 0, 0); - - char* extension = -#ifdef RGFW_WINDOWS - "VK_KHR_win32_surface"; -#elif defined(RGFW_X11) - VK_KHR_XLIB_SURFACE_EXTENSION_NAME; -#elif defined(RGFW_MACOS) - "VK_MVK_macos_surface"; -#else - NULL; -#endif - - VkInstanceCreateInfo instance_create_info = { 0 }; - instance_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; - instance_create_info.pApplicationInfo = &appInfo; - instance_create_info.enabledExtensionCount = extension ? 2 : 0, - instance_create_info.ppEnabledExtensionNames = (const char* [2]){ - VK_KHR_SURFACE_EXTENSION_NAME, - extension - }; - - if (vkCreateInstance(&instance_create_info, NULL, &RGFW_vulkan_info.instance) != VK_SUCCESS) { - fprintf(stderr, "failed to create instance!\n"); - return -1; - } - - - RGFW_createSurface(RGFW_vulkan_info.instance, win); - - u32 deviceCount = 0; - vkEnumeratePhysicalDevices(RGFW_vulkan_info.instance, &deviceCount, NULL); - VkPhysicalDevice* devices = (VkPhysicalDevice*) RGFW_MALLOC(sizeof(VkPhysicalDevice) * deviceCount); - vkEnumeratePhysicalDevices(RGFW_vulkan_info.instance, &deviceCount, devices); - - RGFW_vulkan_info.physical_device = devices[0]; - - u32 queue_family_count = 0; - vkGetPhysicalDeviceQueueFamilyProperties(RGFW_vulkan_info.physical_device, &queue_family_count, NULL); - VkQueueFamilyProperties* queueFamilies = (VkQueueFamilyProperties*) RGFW_MALLOC(sizeof(VkQueueFamilyProperties) * queue_family_count); - vkGetPhysicalDeviceQueueFamilyProperties(RGFW_vulkan_info.physical_device, &queue_family_count, queueFamilies); - - float queuePriority = 1.0f; - - VkPhysicalDeviceFeatures device_features = { 0 }; - - VkDeviceCreateInfo device_create_info = { 0 }; - device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; - VkDeviceQueueCreateInfo queue_create_infos[2] = { - {0}, - {0}, - }; - queue_create_infos[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - queue_create_infos[0].queueCount = 1; - queue_create_infos[0].pQueuePriorities = &queuePriority; - queue_create_infos[1].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - queue_create_infos[1].queueCount = 1; - queue_create_infos[1].pQueuePriorities = &queuePriority; - device_create_info.queueCreateInfoCount = 2; - device_create_info.pQueueCreateInfos = queue_create_infos; - - device_create_info.enabledExtensionCount = 1; - - const char* device_extensions[] = { - VK_KHR_SWAPCHAIN_EXTENSION_NAME - }; - - device_create_info.ppEnabledExtensionNames = device_extensions; - device_create_info.pEnabledFeatures = &device_features; - - if (vkCreateDevice(RGFW_vulkan_info.physical_device, &device_create_info, NULL, &RGFW_vulkan_info.device) != VK_SUCCESS) { - fprintf(stderr, "failed to create logical device!\n"); - return -1; - } - - return 0; - } - - int RGFW_createSwapchain(RGFW_window* win) { - assert(win != NULL); - - VkSurfaceFormatKHR surfaceFormat = { VK_FORMAT_B8G8R8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR }; - VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR; - - VkSurfaceCapabilitiesKHR capabilities = { 0 }; - vkGetPhysicalDeviceSurfaceCapabilitiesKHR(RGFW_vulkan_info.physical_device, win->src.rSurf, &capabilities); - - win->src.image_count = capabilities.minImageCount + 1; - if (capabilities.maxImageCount > 0 && win->src.image_count > capabilities.maxImageCount) { - win->src.image_count = capabilities.maxImageCount; - } - - VkSwapchainCreateInfoKHR swapchain_create_info = { 0 }; - swapchain_create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; - swapchain_create_info.surface = win->src.rSurf; - swapchain_create_info.minImageCount = win->src.image_count; - swapchain_create_info.imageFormat = surfaceFormat.format; - swapchain_create_info.imageColorSpace = surfaceFormat.colorSpace; - swapchain_create_info.imageExtent = (VkExtent2D){ win->r.w, win->r.h }; - swapchain_create_info.imageArrayLayers = 1; - swapchain_create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - swapchain_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; - swapchain_create_info.queueFamilyIndexCount = 2; - swapchain_create_info.preTransform = capabilities.currentTransform; - swapchain_create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; - swapchain_create_info.presentMode = presentMode; - swapchain_create_info.clipped = VK_TRUE; - swapchain_create_info.oldSwapchain = VK_NULL_HANDLE; - - if (vkCreateSwapchainKHR(RGFW_vulkan_info.device, &swapchain_create_info, NULL, &win->src.swapchain) != VK_SUCCESS) { - fprintf(stderr, "failed to create swap chain!\n"); - return -1; - } - - u32 imageCount; - vkGetSwapchainImagesKHR(RGFW_vulkan_info.device, win->src.swapchain, &imageCount, NULL); - win->src.swapchain_images = (VkImage*) RGFW_MALLOC(sizeof(VkImage) * imageCount); - vkGetSwapchainImagesKHR(RGFW_vulkan_info.device, win->src.swapchain, &imageCount, win->src.swapchain_images); - - win->src.swapchain_image_views = (VkImageView*) RGFW_MALLOC(sizeof(VkImageView) * imageCount); - for (u32 i = 0; i < imageCount; i++) { - VkImageViewCreateInfo image_view_cre_infos = { 0 }; - image_view_cre_infos.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - image_view_cre_infos.image = win->src.swapchain_images[i]; - image_view_cre_infos.viewType = VK_IMAGE_VIEW_TYPE_2D; - image_view_cre_infos.format = VK_FORMAT_B8G8R8A8_SRGB; - image_view_cre_infos.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; - image_view_cre_infos.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; - image_view_cre_infos.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; - image_view_cre_infos.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; - image_view_cre_infos.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - image_view_cre_infos.subresourceRange.baseMipLevel = 0; - image_view_cre_infos.subresourceRange.levelCount = 1; - image_view_cre_infos.subresourceRange.baseArrayLayer = 0; - image_view_cre_infos.subresourceRange.layerCount = 1; - if (vkCreateImageView(RGFW_vulkan_info.device, &image_view_cre_infos, NULL, &win->src.swapchain_image_views[i]) != VK_SUCCESS) { - fprintf(stderr, "failed to create image views!"); - return -1; - } - } - - return 0; - } - - int RGFW_createRenderPass(void) { - VkAttachmentDescription color_attachment = { 0 }; - color_attachment.format = VK_FORMAT_B8G8R8A8_SRGB; - color_attachment.samples = VK_SAMPLE_COUNT_1_BIT; - color_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - color_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - color_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - color_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - color_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - color_attachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - - VkAttachmentReference color_attachment_ref = { 0 }; - color_attachment_ref.attachment = 0; - color_attachment_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - - VkSubpassDescription subpass = { 0 }; - subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpass.colorAttachmentCount = 1; - subpass.pColorAttachments = &color_attachment_ref; - - VkSubpassDependency dependency = { 0 }; - dependency.srcSubpass = VK_SUBPASS_EXTERNAL; - dependency.dstSubpass = 0; - dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependency.srcAccessMask = 0; - dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - - VkRenderPassCreateInfo render_pass_info = { 0 }; - render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - render_pass_info.attachmentCount = 1; - render_pass_info.pAttachments = &color_attachment; - render_pass_info.subpassCount = 1; - render_pass_info.pSubpasses = &subpass; - render_pass_info.dependencyCount = 1; - render_pass_info.pDependencies = &dependency; - - if (vkCreateRenderPass(RGFW_vulkan_info.device, &render_pass_info, NULL, &RGFW_vulkan_info.render_pass) != VK_SUCCESS) { - fprintf(stderr, "failed to create render pass\n"); - return -1; // failed to create render pass! - } - return 0; - } - - int RGFW_createCommandPool(void) { - VkCommandPoolCreateInfo pool_info = { 0 }; - pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - pool_info.queueFamilyIndex = 0; - - if (vkCreateCommandPool(RGFW_vulkan_info.device, &pool_info, NULL, &RGFW_vulkan_info.command_pool) != VK_SUCCESS) { - fprintf(stderr, "failed to create command pool\n"); - return -1; // failed to create command pool - } - return 0; - } - - int RGFW_createCommandBuffers(RGFW_window* win) { - assert(win != NULL); - - RGFW_vulkan_info.command_buffers = (VkCommandBuffer*) RGFW_MALLOC(sizeof(VkCommandBuffer) * win->src.image_count); - - VkCommandBufferAllocateInfo allocInfo = { 0 }; - allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - allocInfo.commandPool = RGFW_vulkan_info.command_pool; - allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - allocInfo.commandBufferCount = (u32) win->src.image_count; - - if (vkAllocateCommandBuffers(RGFW_vulkan_info.device, &allocInfo, RGFW_vulkan_info.command_buffers) != VK_SUCCESS) { - return -1; // failed to allocate command buffers; - } - - return 0; - } - - int RGFW_createSyncObjects(RGFW_window* win) { - assert(win != NULL); - - RGFW_vulkan_info.available_semaphores = (VkSemaphore*) RGFW_MALLOC(sizeof(VkSemaphore) * RGFW_MAX_FRAMES_IN_FLIGHT); - RGFW_vulkan_info.finished_semaphore = (VkSemaphore*) RGFW_MALLOC(sizeof(VkSemaphore) * RGFW_MAX_FRAMES_IN_FLIGHT); - RGFW_vulkan_info.in_flight_fences = (VkFence*) RGFW_MALLOC(sizeof(VkFence) * RGFW_MAX_FRAMES_IN_FLIGHT); - RGFW_vulkan_info.image_in_flight = (VkFence*) RGFW_MALLOC(sizeof(VkFence) * win->src.image_count); - - VkSemaphoreCreateInfo semaphore_info = { 0 }; - semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - - VkFenceCreateInfo fence_info = { 0 }; - fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - fence_info.flags = VK_FENCE_CREATE_SIGNALED_BIT; - - for (size_t i = 0; i < RGFW_MAX_FRAMES_IN_FLIGHT; i++) { - if (vkCreateSemaphore(RGFW_vulkan_info.device, &semaphore_info, NULL, &RGFW_vulkan_info.available_semaphores[i]) != VK_SUCCESS || - vkCreateSemaphore(RGFW_vulkan_info.device, &semaphore_info, NULL, &RGFW_vulkan_info.finished_semaphore[i]) != VK_SUCCESS || - vkCreateFence(RGFW_vulkan_info.device, &fence_info, NULL, &RGFW_vulkan_info.in_flight_fences[i]) != VK_SUCCESS) { - fprintf(stderr, "failed to create sync objects\n"); - return -1; // failed to create synchronization objects for a frame - } - } - - for (size_t i = 0; i < win->src.image_count; i++) { - RGFW_vulkan_info.image_in_flight[i] = VK_NULL_HANDLE; - } - - return 0; - } - - int RGFW_createFramebuffers(RGFW_window* win) { - assert(win != NULL); - - RGFW_vulkan_info.framebuffers = (VkFramebuffer*) RGFW_MALLOC(sizeof(VkFramebuffer) * win->src.image_count); - - for (size_t i = 0; i < win->src.image_count; i++) { - VkImageView attachments[] = { win->src.swapchain_image_views[i] }; - - VkFramebufferCreateInfo framebuffer_info = { 0 }; - framebuffer_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - framebuffer_info.renderPass = RGFW_vulkan_info.render_pass; - framebuffer_info.attachmentCount = 1; - framebuffer_info.pAttachments = attachments; - framebuffer_info.width = win->r.w; - framebuffer_info.height = win->r.h; - framebuffer_info.layers = 1; - - if (vkCreateFramebuffer(RGFW_vulkan_info.device, &framebuffer_info, NULL, &RGFW_vulkan_info.framebuffers[i]) != VK_SUCCESS) { - return -1; // failed to create framebuffer - } - } - return 0; - } - - void RGFW_freeVulkan(void) { - vkDeviceWaitIdle(RGFW_vulkan_info.device); - - for (size_t i = 0; i < RGFW_MAX_FRAMES_IN_FLIGHT; i++) { - vkDestroySemaphore(RGFW_vulkan_info.device, RGFW_vulkan_info.finished_semaphore[i], NULL); - vkDestroySemaphore(RGFW_vulkan_info.device, RGFW_vulkan_info.available_semaphores[i], NULL); - vkDestroyFence(RGFW_vulkan_info.device, RGFW_vulkan_info.in_flight_fences[i], NULL); - } - - vkDestroyCommandPool(RGFW_vulkan_info.device, RGFW_vulkan_info.command_pool, NULL); - - vkDestroyPipeline(RGFW_vulkan_info.device, RGFW_vulkan_info.graphics_pipeline, NULL); - vkDestroyPipelineLayout(RGFW_vulkan_info.device, RGFW_vulkan_info.pipeline_layout, NULL); - vkDestroyRenderPass(RGFW_vulkan_info.device, RGFW_vulkan_info.render_pass, NULL); - -#ifdef RGFW_DEBUG - PFN_vkDestroyDebugUtilsMessengerEXT func = (PFN_vkDestroyDebugUtilsMessengerEXT) vkGetInstanceProcAddr(RGFW_vulkan_info.instance, "vkDestroyDebugUtilsMessengerEXT"); - if (func != NULL) { - func(RGFW_vulkan_info.instance, RGFW_vulkan_info.debugMessenger, NULL); - } -#endif - - vkDestroyDevice(RGFW_vulkan_info.device, NULL); - vkDestroyInstance(RGFW_vulkan_info.instance, NULL); - - RGFW_FREE(RGFW_vulkan_info.framebuffers); - RGFW_FREE(RGFW_vulkan_info.command_buffers); - RGFW_FREE(RGFW_vulkan_info.available_semaphores); - RGFW_FREE(RGFW_vulkan_info.finished_semaphore); - RGFW_FREE(RGFW_vulkan_info.in_flight_fences); - RGFW_FREE(RGFW_vulkan_info.image_in_flight); - } - -#endif /* RGFW_VULKAN */ - - RGFW_window* RGFW_root = NULL; - -#ifdef RGFW_X11 -#include -#ifndef RGFW_NO_X11_CURSOR -#include -#endif -#include - -#ifndef RGFW_NO_DPI -#include -#include -#endif -#endif - -#define RGFW_HOLD_MOUSE (1L<<2) /*!< hold the moues still */ - -#ifdef RGFW_WINDOWS -#include -#include -#include -#include -#include -#include -#endif - - u8 RGFW_mouseButtons[5] = { 0 }; - u8 RGFW_mouseButtons_prev[5]; - - u8 RGFW_isMousePressed(RGFW_window* win, u8 button) { - if (win != NULL && !win->event.inFocus) - return 0; - - return RGFW_mouseButtons[button]; - } - u8 RGFW_wasMousePressed(RGFW_window* win, u8 button) { - if (win != NULL && !win->event.inFocus) - return 0; - - return RGFW_mouseButtons_prev[button]; - } - u8 RGFW_isMouseHeld(RGFW_window* win, u8 button) { - return (RGFW_isMousePressed(win, button) && RGFW_wasMousePressed(win, button)); - } - u8 RGFW_isMouseReleased(RGFW_window* win, u8 button) { - return (!RGFW_isMousePressed(win, button) && RGFW_wasMousePressed(win, button)); - } - - u8 RGFW_isPressedI(RGFW_window* win, u32 key) { - RGFW_UNUSED(win); - - return RGFW_keyboard[key]; - } - - u8 RGFW_wasPressedI(RGFW_window* win, u32 key) { - RGFW_UNUSED(win); - - return RGFW_keyboard_prev[key]; - } - - u8 RGFW_isHeldI(RGFW_window* win, u32 key) { - return (RGFW_isPressedI(win, key) && RGFW_wasPressedI(win, key)); - } - - u8 RGFW_isReleasedI(RGFW_window* win, u32 key) { - return (!RGFW_isPressedI(win, key) && RGFW_wasPressedI(win, key)); - } - - char* RGFW_keyCodeTokeyStr(u64 key) { - static char* keyStrs[128] = {"Escape", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "Backtick", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "-", "=", "BackSpace", "Tab", "CapsLock", "ShiftL", "ControlL", "AltL", "SuperL", "ShiftR", "ControlR", "AltR", "SuperR", " ", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", ".", ",", "-", "[", "]", ";", "Return", "'", "\\", "Up", "Down", "Left", "Right", "Delete", "Insert", "End", "Home", "PageUp", "PageDown", "Numlock", "KP_Slash", "Multiply", "KP_Minus", "KP_1", "KP_2", "KP_3", "KP_4", "KP_5", "KP_6", "KP_7", "KP_8", "KP_9", "KP_0", "KP_Period", "KP_Return" }; - - return keyStrs[key]; - } - - u32 RGFW_keyStrToKeyCode(char* key) { - static char* keyStrs[128] = {"Escape", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "Backtick", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "-", "=", "BackSpace", "Tab", "CapsLock", "ShiftL", "ControlL", "AltL", "SuperL", "ShiftR", "ControlR", "AltR", "SuperR", " ", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", ".", ",", "-", "[", "]", ";", "Return", "'", "\\", "Up", "Down", "Left", "Right", "Delete", "Insert", "End", "Home", "PageUp", "PageDown", "Numlock", "KP_Slash", "Multiply", "KP_Minus", "KP_1", "KP_2", "KP_3", "KP_4", "KP_5", "KP_6", "KP_7", "KP_8", "KP_9", "KP_0", "KP_Period", "KP_Return" }; - - key--; - while (key++) { - u32 i; - for (i = 0; i < 128; i++) { - if (*keyStrs[i] == '\1') - continue; - - if (*keyStrs[i] != *key) { - keyStrs[i] = "\1"; - continue; - } - - if (*keyStrs[i] == '\0' && *key == '\0') - return RGFW_apiKeyCodeToRGFW(i); - - else - keyStrs[i]++; - } - - if (*key == '\0') - break; - } - - return 0; - } - - - char RGFW_keystrToChar(const char* str) { - if (str[1] == 0) - return str[0]; - - static const char* map[] = { - "asciitilde", "`", - "grave", "~", - "exclam", "!", - "at", "@", - "numbersign", "#", - "dollar", "$", - "percent", "%%", - "asciicircum", "^", - "ampersand", "&", - "asterisk", "*", - "parenleft", "(", - "parenright", ")", - "underscore", "_", - "minus", "-", - "plus", "+", - "equal", "=", - "braceleft", "{", - "bracketleft", "[", - "bracketright", "]", - "braceright", "}", - "colon", ":", - "semicolon", ";", - "quotedbl", "\"", - "apostrophe", "'", - "bar", "|", - "backslash", "\'", - "less", "<", - "comma", ",", - "greater", ">", - "period", ".", - "question", "?", - "slash", "/", - "space", " ", - "Return", "\n", - "Enter", "\n", - "enter", "\n", - }; - - u8 i = 0; - for (i = 0; i < (sizeof(map) / sizeof(char*)); i += 2) - if (strcmp(map[i], str) == 0) - return *map[i + 1]; - - return '\0'; - } - -#ifndef M_PI -#define M_PI 3.14159265358979323846 /* pi */ -#endif - -#ifndef RGFW_WINDOWS - struct timespec; - - 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); - - u32 RGFW_isPressedJS(RGFW_window* win, u16 c, u8 button) { return win->src.jsPressed[c][button]; } -#else - - typedef u64 (WINAPI * PFN_XInputGetState)(DWORD,XINPUT_STATE*); - PFN_XInputGetState XInputGetStateSRC = NULL; - #define XInputGetState XInputGetStateSRC - static HMODULE RGFW_XInput_dll = NULL; - - u32 RGFW_isPressedJS(RGFW_window* win, u16 c, u8 button) { - RGFW_UNUSED(win) - - XINPUT_STATE state; - if (XInputGetState == NULL || XInputGetState(c, &state) == ERROR_DEVICE_NOT_CONNECTED) - return 0; - - if (button == RGFW_JS_A) return state.Gamepad.wButtons & XINPUT_GAMEPAD_A; - else if (button == RGFW_JS_B) return state.Gamepad.wButtons & XINPUT_GAMEPAD_B; - else if (button == RGFW_JS_Y) return state.Gamepad.wButtons & XINPUT_GAMEPAD_Y; - else if (button == RGFW_JS_X) return state.Gamepad.wButtons & XINPUT_GAMEPAD_X; - else if (button == RGFW_JS_START) return state.Gamepad.wButtons & XINPUT_GAMEPAD_START; - else if (button == RGFW_JS_SELECT) return state.Gamepad.wButtons & XINPUT_GAMEPAD_BACK; - else if (button == RGFW_JS_UP) return state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP; - else if (button == RGFW_JS_DOWN) return state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN; - else if (button == RGFW_JS_LEFT) return state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT; - else if (button == RGFW_JS_RIGHT) return state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT; - else if (button == RGFW_JS_L1) return state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER; - else if (button == RGFW_JS_R1) return state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER; - else if (button == RGFW_JS_L2 && state.Gamepad.bLeftTrigger) return 1; - else if (button == RGFW_JS_R2 && state.Gamepad.bRightTrigger) return 1; - - return 0; - } -#endif - -#if defined(RGFW_OPENGL) || defined(RGFW_EGL) +/* EGL, normal OpenGL only */ +#if !defined(RGFW_OSMESA) i32 RGFW_majorVersion = 0, RGFW_minorVersion = 0; #ifndef RGFW_EGL @@ -2346,6 +1582,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ return version; } +/* OPENGL normal only (no EGL / OSMesa) */ #ifndef RGFW_EGL #define RGFW_GL_RENDER_TYPE RGFW_OS_BASED_VALUE(GLX_X_VISUAL_TYPE, 0x2003, 73) @@ -2377,6 +1614,10 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ #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 #endif static u32* RGFW_initAttribs(u32 useSoftware) { @@ -2412,6 +1653,8 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ #endif #ifdef RGFW_WINDOWS + WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB, + WGL_TRANSPARENT_ARB, TRUE, WGL_COLOR_BITS_ARB, 32, #endif @@ -2459,7 +1702,8 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ return attribs; } -#else +/* EGL only (no OSMesa nor normal OPENGL) */ +#elif defined(RGFW_EGL) #include @@ -2619,14 +1863,71 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ eglTerminate(win->src.EGL_display); } -#endif /* RGFW_EGL */ -#endif /* RGFW_GL stuff? */ + void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) { + assert(win != NULL); + + eglSwapInterval(win->src.EGL_display, swapInterval); - /* - This is where OS specific stuff starts - */ + win->fpsCap = (swapInterval == 1) ? 0 : swapInterval; + + } +#endif /* RGFW_EGL */ + +/* + end of RGFW_EGL defines +*/ + +/* OPENGL Normal / EGL defines only (no OS MESA) Ends here */ + +#elif defined(RGFW_OSMESA) /* OSmesa only */ +RGFWDEF void RGFW_OSMesa_reorganize(void); + +/* reorganize buffer for osmesa */ +void RGFW_OSMesa_reorganize(void) { + u8* row = (u8*) RGFW_MALLOC(win->r.w * 3); + + i32 half_height = win->r.h / 2; + i32 stride = win->r.w * 3; + + i32 y; + for (y = 0; y < half_height; ++y) { + i32 top_offset = y * stride; + i32 bottom_offset = (win->r.h - y - 1) * stride; + memcpy(row, win->buffer + top_offset, stride); + memcpy(win->buffer + top_offset, win->buffer + bottom_offset, stride); + memcpy(win->buffer + bottom_offset, row, stride); + } + + RGFW_FREE(row); +} +#endif /* RGFW_OSMesa */ + +#endif /* RGFW_GL (OpenGL, EGL, OSMesa )*/ + +/* +This is where OS specific stuff starts +*/ + + +/* + + +Start of Linux / Unix defines + + +*/ #ifdef RGFW_X11 +#ifndef RGFW_NO_X11_CURSOR +#include +#endif +#include + +#ifndef RGFW_NO_DPI +#include +#include +#endif + #include #include #include @@ -2634,6 +1935,8 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ #include /* for converting keycode to string */ #include /* for hiding */ +#include +#include #include /* for data limits (mainly used in drag and drop functions) */ #include @@ -2642,6 +1945,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ #include #endif + u8 RGFW_mouseIconSrc[] = { XC_arrow, XC_left_ptr, XC_xterm, XC_crosshair, XC_hand2, XC_sb_h_double_arrow, XC_sb_v_double_arrow, XC_bottom_left_corner, XC_bottom_right_corner, XC_fleur, XC_X_cursor}; /*atoms needed for drag and drop*/ Atom XdndAware, XdndTypeList, XdndSelection, XdndEnter, XdndPosition, XdndStatus, XdndLeave, XdndDrop, XdndFinished, XdndActionCopy, XdndActionMove, XdndActionLink, XdndActionAsk, XdndActionPrivate; @@ -2674,6 +1978,55 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ void* RGFW_getProcAddress(const char* procname) { return (void*) glXGetProcAddress((GLubyte*) procname); } #endif + RGFWDEF void RGFW_init_buffer(RGFW_window* win, XVisualInfo* vi); + void RGFW_init_buffer(RGFW_window* win, XVisualInfo* vi) { +#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.rSurf = OSMesaCreateContext(OSMESA_RGBA, NULL); + OSMesaMakeCurrent(win->src.rSurf, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h); + #endif + + win->src.bitmap = XCreateImage( + win->src.display, vi->visual, + vi->depth, + ZPixmap, 0, NULL, RGFW_bufferSize.w, RGFW_bufferSize.h, + 32, 0 + ); + + win->src.gc = XCreateGC(win->src.display, win->src.window, 0, NULL); + + #else + RGFW_UNUSED(win); /* if buffer rendering is not being used */ + RGFW_UNUSED(vi) + #endif + } + + + + void RGFW_window_setBorder(RGFW_window* win, u8 border) { + static Atom _MOTIF_WM_HINTS = 0; + if (_MOTIF_WM_HINTS == 0 ) + _MOTIF_WM_HINTS = XInternAtom(win->src.display, "_MOTIF_WM_HINTS", False); + + struct __x11WindowHints { + unsigned long flags, functions, decorations, status; + long input_mode; + } hints; + hints.flags = (1L << 1); + hints.decorations = !border; + + XChangeProperty( + win->src.display, win->src.window, + _MOTIF_WM_HINTS, _MOTIF_WM_HINTS, + 32, PropModeReplace, (u8*)&hints, 5 + ); + } + 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) { @@ -2698,7 +2051,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ RGFW_window* win = RGFW_window_basic_init(rect, args); - u64 event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask | FocusChangeMask; /* X11 events accepted*/ + u64 event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask | FocusChangeMask | LeaveWindowMask | EnterWindowMask | ExposureMask; /* X11 events accepted*/ #ifdef RGFW_OPENGL u32* visual_attribs = RGFW_initAttribs(args & RGFW_OPENGL_SOFTWARE); @@ -2740,45 +2093,60 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ XFree(fbc); - u32 valuemask = CWBorderPixel | CWColormap; + if (args & RGFW_TRANSPARENT_WINDOW) { + XMatchVisualInfo((Display*) win->src.display, DefaultScreen((Display*) win->src.display), 32, TrueColor, vi); /* for RGBA backgrounds*/ + } #else - XVisualInfo* vi = (XVisualInfo*) RGFW_MALLOC(sizeof(XVisualInfo)); - vi->screen = DefaultScreen((Display*) win->src.display); - vi->visual = DefaultVisual((Display*) win->src.display, vi->screen); + XVisualInfo viNorm; - vi->depth = 0; - u32 valuemask = 0; + viNorm.visual = DefaultVisual((Display*) win->src.display, DefaultScreen((Display*) win->src.display)); + + viNorm.depth = 0; + XVisualInfo* vi = &viNorm; + + XMatchVisualInfo((Display*) win->src.display, DefaultScreen((Display*) win->src.display), 32, TrueColor, vi); /* for RGBA backgrounds*/ #endif - /* make X window attrubutes*/ XSetWindowAttributes swa; Colormap cmap; swa.colormap = cmap = XCreateColormap((Display*) win->src.display, - RootWindow(win->src.display, vi->screen), + DefaultRootWindow(win->src.display), vi->visual, AllocNone); swa.background_pixmap = None; swa.border_pixel = 0; swa.event_mask = event_mask; + + swa.background_pixel = 0; /* create the window*/ - win->src.window = XCreateWindow((Display*) win->src.display, RootWindow((Display*) win->src.display, vi->screen), win->r.x, win->r.y, win->r.w, win->r.h, + win->src.window = XCreateWindow((Display*) win->src.display, DefaultRootWindow((Display*) win->src.display), win->r.x, win->r.y, win->r.w, win->r.h, 0, vi->depth, InputOutput, vi->visual, - valuemask | CWEventMask, &swa); - + CWColormap | CWBorderPixel | CWBackPixel | CWEventMask, &swa); XFreeColors((Display*) win->src.display, cmap, NULL, 0, 0); - if (args & RGFW_TRANSPARENT_WINDOW) - XMatchVisualInfo((Display*) win->src.display, DefaultScreen((Display*) win->src.display), 32, TrueColor, vi); /* for RGBA backgrounds*/ + #ifdef RGFW_OPENGL XFree(vi); + #endif + // In your .desktop app, if you set the property + // StartupWMClass=RGFW that will assoicate the launcher icon + // with your application - robrohan + XClassHint *hint = XAllocClassHint(); + assert(hint != NULL); + hint->res_class = "RGFW"; + hint->res_name = (char*)name; // just use the window name as the app name + XSetClassHint((Display*) win->src.display, win->src.window, hint); + XFree(hint); + + if ((args & RGFW_NO_INIT_API) == 0) { #ifdef RGFW_OPENGL i32 context_attribs[7] = { 0, 0, 0, 0, 0, 0, 0 }; context_attribs[0] = GLX_CONTEXT_PROFILE_MASK_ARB; context_attribs[1] = GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; - + if (RGFW_majorVersion || RGFW_minorVersion) { context_attribs[2] = GLX_CONTEXT_MAJOR_VERSION_ARB; context_attribs[3] = RGFW_majorVersion; @@ -2800,14 +2168,14 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ if (RGFW_root == NULL) RGFW_root = win; - RGFW_init_buffer(win); - -#ifdef RGFW_VULKAN - RGFW_initVulkan(win); -#endif + RGFW_init_buffer(win, vi); + } + + #ifndef RGFW_NO_MONITOR if (args & RGFW_SCALE_TO_MONITOR) RGFW_window_scaleToMonitor(win); + #endif if (args & RGFW_NO_RESIZE) { /* make it so the user can't resize the window*/ XSizeHints* sh = XAllocSizeHints(); @@ -2820,29 +2188,21 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ } if (args & RGFW_NO_BORDER) { - /* Atom vars for no-border*/ - static Atom window_type = 0; - static Atom value = 0; - - if (window_type == 0) { - window_type = XInternAtom((Display*) win->src.display, "_NET_WM_WINDOW_TYPE", False); - value = XInternAtom((Display*) win->src.display, "_NET_WM_WINDOW_TYPE_DOCK", False); - } - - XChangeProperty((Display*) win->src.display, (Drawable) win->src.window, window_type, XA_ATOM, 32, PropModeReplace, (u8*) &value, 1); /* toggle border*/ + RGFW_window_setBorder(win, 0); } XSelectInput((Display*) win->src.display, (Drawable) win->src.window, event_mask); /* tell X11 what events we want*/ /* make it so the user can't close the window until the program does*/ if (wm_delete_window == 0) - wm_delete_window = XInternAtom((Display*) win->src.display, "WM_DELETE_WINDOW", 1); + wm_delete_window = XInternAtom((Display*) win->src.display, "WM_DELETE_WINDOW", False); XSetWMProtocols((Display*) win->src.display, (Drawable) win->src.window, &wm_delete_window, 1); /* connect the context to the window*/ #ifdef RGFW_OPENGL - glXMakeCurrent((Display*) win->src.display, (Drawable) win->src.window, (GLXContext) win->src.rSurf); + if ((args & RGFW_NO_INIT_API) == 0) + glXMakeCurrent((Display*) win->src.display, (Drawable) win->src.window, (GLXContext) win->src.rSurf); #endif /* set the background*/ @@ -2880,7 +2240,8 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ } #ifdef RGFW_EGL - RGFW_createOpenGLContext(win); + if ((args & RGFW_NO_INIT_API) == 0) + RGFW_createOpenGLContext(win); #endif RGFW_window_setMouseDefault(win); @@ -2933,6 +2294,14 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) { assert(win != NULL); + + if (win->event.type == 0) + RGFW_resetKey(); + + if (win->event.type == RGFW_quit) { + return NULL; + } + win->event.type = 0; #ifdef __linux__ @@ -2942,7 +2311,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ struct js_event e; - if (!win->src.joysticks[i]) + if (win->src.joysticks[i] == 0) continue; i32 flags = fcntl(win->src.joysticks[i], F_GETFL, 0); @@ -2955,6 +2324,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ win->event.type = e.value ? RGFW_jsButtonPressed : RGFW_jsButtonReleased; win->event.button = e.number; win->src.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); @@ -2967,7 +2337,8 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ win->event.axis[e.number / 2].x = xAxis; win->event.axis[e.number / 2].y = yAxis; win->event.type = RGFW_jsAxisMove; - win->event.joystick = e.number / 2; + win->event.joystick = i; + RGFW_jsAxisCallback(win, i, win->event.axis, win->event.axisesCount); return &win->event; default: break; @@ -3005,54 +2376,64 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ /* set event key data */ KeySym sym = XkbKeycodeToKeysym((Display*) win->src.display, E.xkey.keycode, 0, E.xkey.state & ShiftMask ? 1 : 0); win->event.keyCode = RGFW_apiKeyCodeToRGFW(E.xkey.keycode); - win->event.keyName = XKeysymToString(sym); /* convert to string */ + + char* str = XKeysymToString(sym); + if (str != NULL) + strncpy(win->event.keyName, str, 16); - RGFW_keyboard_prev[win->event.keyCode] = RGFW_isPressedI(win, win->event.keyCode); + win->event.keyName[15] = '\0'; + + RGFW_keyboard[win->event.keyCode].prev = RGFW_isPressed(win, win->event.keyCode); /* get keystate data */ win->event.type = (E.type == KeyPress) ? RGFW_keyPressed : RGFW_keyReleased; - if (win->event.type == RGFW_keyReleased) { - if (sym == XK_Caps_Lock && win->event.lockState & RGFW_CAPSLOCK) - win->event.lockState ^= RGFW_CAPSLOCK; - else if (sym == XK_Caps_Lock) - win->event.lockState |= RGFW_CAPSLOCK; + XKeyboardState keystate; + XGetKeyboardControl((Display*) win->src.display, &keystate); - else if (sym == XK_Num_Lock && win->event.lockState & RGFW_NUMLOCK) - win->event.lockState ^= RGFW_NUMLOCK; - else if (sym == XK_Num_Lock) - win->event.lockState |= RGFW_NUMLOCK; - } - - RGFW_keyboard[win->event.keyCode] = (E.type == KeyPress); + RGFW_updateLockState(win, (keystate.led_mask & 1), (keystate.led_mask & 2)); + + RGFW_keyboard[win->event.keyCode].current = (E.type == KeyPress); + RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, (E.type == KeyPress)); break; case ButtonPress: case ButtonRelease: - win->event.type = (E.type == ButtonPress) ? RGFW_mouseButtonPressed : RGFW_mouseButtonReleased; - - if (win->event.button == RGFW_mouseScrollUp) { - win->event.scroll = 1; - } - else if (win->event.button == RGFW_mouseScrollDown) { - win->event.scroll = -1; + win->event.type = E.type; // the events match + + switch(win->event.button) { + case RGFW_mouseScrollUp: + win->event.scroll = 1; + break; + case RGFW_mouseScrollDown: + win->event.scroll = -1; + break; + default: break; } 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_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; win->event.type = RGFW_mousePosChanged; + RGFW_mousePosCallback(win, win->event.point); + break; + + case Expose: + win->event.type = RGFW_windowRefresh; + RGFW_windowRefreshCallback(win); break; case ClientMessage: /* if the client closed the window*/ if (E.xclient.data.l[0] == (i64) wm_delete_window) { win->event.type = RGFW_quit; + RGFW_windowQuitCallback(win); break; } @@ -3071,10 +2452,11 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ if ((win->src.winArgs & RGFW_ALLOW_DND) == 0) break; - u8 formFree = 0; if (E.xclient.message_type == XdndEnter) { u64 count; - Atom* formats = (Atom*) 0; + Atom* formats; + Atom real_formats[6]; + Bool list = E.xclient.data.l[1] & 1; xdnd.source = E.xclient.data.l[0]; @@ -3102,17 +2484,16 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ (unsigned long*) &bytesAfter, (u8**) &formats); } else { - formats = (Atom*) RGFW_MALLOC(E.xclient.data.l[2] + E.xclient.data.l[3] + E.xclient.data.l[4]); - formFree = 1; - count = 0; if (E.xclient.data.l[2] != None) - formats[count++] = E.xclient.data.l[2]; + real_formats[count++] = E.xclient.data.l[2]; if (E.xclient.data.l[3] != None) - formats[count++] = E.xclient.data.l[3]; + real_formats[count++] = E.xclient.data.l[3]; if (E.xclient.data.l[4] != None) - formats[count++] = E.xclient.data.l[4]; + real_formats[count++] = E.xclient.data.l[4]; + + formats = real_formats; } u32 i; @@ -3140,14 +2521,8 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ } } - if (list && formats) { + if (list) { XFree(formats); - formats = (Atom*) 0; - } else if (formFree && formats != (Atom*) 0) { - RGFW_FREE(formats); - - formats = (Atom*) 0; - formFree = 1; } break; @@ -3223,6 +2598,8 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ False, NoEventMask, &reply); XFlush((Display*) win->src.display); } + + RGFW_dndInitCallback(win, win->event.point); break; case SelectionNotify: /* this is only for checking for xdnd drops */ @@ -3293,7 +2670,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ line++; } path[index] = '\0'; - strcpy(win->event.droppedFiles[win->event.droppedFilesCount - 1], path); + strncpy(win->event.droppedFiles[win->event.droppedFilesCount - 1], path, index + 1); } if (data) @@ -3312,37 +2689,54 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ XFlush((Display*) win->src.display); } + RGFW_dndCallback(win, win->event.droppedFiles, win->event.droppedFilesCount); break; case FocusIn: win->event.inFocus = 1; - - XKeyboardState keystate; - XGetKeyboardControl((Display*) win->src.display, &keystate); - win->event.lockState = keystate.led_mask; - win->event.type = RGFW_focusIn; + RGFW_focusCallback(win, 1); break; break; case FocusOut: win->event.inFocus = 0; win->event.type = RGFW_focusOut; + RGFW_focusCallback(win, 0); break; + + case EnterNotify: { + win->event.type = RGFW_mouseEnter; + win->event.point.x = E.xcrossing.x; + win->event.point.y = E.xcrossing.y; + RGFW_mouseNotifyCallBack(win, win->event.point, 1); + break; + } + + case LeaveNotify: { + win->event.type = RGFW_mouseLeave; + RGFW_mouseNotifyCallBack(win, win->event.point, 0); + break; + } + case ConfigureNotify: { - // detect resize + /* detect resize */ if (E.xconfigure.width != win->r.w || E.xconfigure.height != win->r.h) { - win->event.type = RGFW_windowResized; - win->r = RGFW_RECT(win->r.x, win->r.y, E.xconfigure.width, E.xconfigure.height); - break; + win->event.type = RGFW_windowResized; + win->r = RGFW_RECT(win->r.x, win->r.y, E.xconfigure.width, E.xconfigure.height); + RGFW_windowResizeCallback(win, win->r); + break; } - // detect move + /* detect move */ if (E.xconfigure.x != win->r.x || E.xconfigure.y != win->r.y) { - win->event.type = RGFW_windowMoved; - win->r = RGFW_RECT(E.xconfigure.x, E.xconfigure.y, win->r.w, win->r.h); + win->event.type = RGFW_windowMoved; + win->r = RGFW_RECT(E.xconfigure.x, E.xconfigure.y, win->r.w, win->r.h); + RGFW_windowMoveCallback(win, win->r); + break; + } + break; - } } default: { break; @@ -3357,76 +2751,6 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ return NULL; } - void RGFW_window_close(RGFW_window* win) { - assert(win != NULL); - -#ifdef RGFW_VULKAN - for (u32 i = 0; i < win->src.image_count; i++) { - vkDestroyImageView(RGFW_vulkan_info.device, win->src.swapchain_image_views[i], NULL); - } - - vkDestroySwapchainKHR(RGFW_vulkan_info.device, win->src.swapchain, NULL); - vkDestroySurfaceKHR(RGFW_vulkan_info.instance, win->src.rSurf, NULL); - RGFW_FREE(win->src.swapchain_image_views); - RGFW_FREE(win->src.swapchain_images); -#endif - -#ifdef RGFW_EGL - RGFW_closeEGL(win); -#endif - -#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) - if (win->buffer != NULL) { - XDestroyImage((XImage*) win->src.bitmap); - } -#endif - - if ((Display*) win->src.display) { -#ifdef RGFW_OPENGL - glXDestroyContext((Display*) win->src.display, win->src.rSurf); -#endif - - if (win == RGFW_root) - RGFW_root = NULL; - - if ((Drawable) win->src.window) - XDestroyWindow((Display*) win->src.display, (Drawable) win->src.window); /* close the window*/ - - if (win->src.display) - XCloseDisplay((Display*) win->src.display); /* kill the display*/ - } - -#ifdef RGFW_ALLOC_DROPFILES - { - u32 i; - for (i = 0; i < RGFW_MAX_DROPS; i++) - RGFW_FREE(win->event.droppedFiles[i]); - - - RGFW_FREE(win->event.droppedFiles); - } -#endif - - RGFW_windowsOpen--; -#if !defined(RGFW_NO_X11_CURSOR_PRELOAD) && !defined(RGFW_NO_X11_CURSOR) - if (X11Cursorhandle != NULL && RGFW_windowsOpen <= 0) { - dlclose(X11Cursorhandle); - - X11Cursorhandle = NULL; - } -#endif - - /* 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 */ - } - void RGFW_window_move(RGFW_window* win, RGFW_vector v) { assert(win != NULL); win->r.x = v.x; @@ -3447,13 +2771,16 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) { assert(win != NULL); + if (a.w == 0 && a.h == 0) + return; + XSizeHints hints; long flags; XGetWMNormalHints(win->src.display, (Window) win->src.window, &hints, &flags); hints.flags |= PMinSize; - + hints.min_width = a.w; hints.min_height = a.h; @@ -3463,6 +2790,9 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) { assert(win != NULL); + if (a.w == 0 && a.h == 0) + return; + XSizeHints hints; long flags; @@ -3489,13 +2819,51 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ XMapWindow(win->src.display, (Window) win->src.window); XFlush(win->src.display); - } + } void RGFW_window_setName(RGFW_window* win, char* name) { assert(win != NULL); XStoreName((Display*) win->src.display, (Window) win->src.window, name); } + + void* RGFW_libxshape = NULL; + + #ifndef RGFW_NO_PASSTHROUGH + void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) { + assert(win != NULL); + + #if defined(__CYGWIN__) + RGFW_libxshape = dlopen("libXext-6.so", RTLD_LAZY | RTLD_LOCAL); + #elif defined(__OpenBSD__) || defined(__NetBSD__) + RGFW_libxshape = dlopen("libXext.so", RTLD_LAZY | RTLD_LOCAL); + #else + RGFW_libxshape = dlopen("libXext.so.6", RTLD_LAZY | RTLD_LOCAL); + #endif + + typedef void (* PFN_XShapeCombineMask)(Display*,Window,int,int,int,Pixmap,int); + static PFN_XShapeCombineMask XShapeCombineMask; + + typedef void (* PFN_XShapeCombineRegion)(Display*,Window,int,int,int,Region,int); + static PFN_XShapeCombineRegion XShapeCombineRegion; + + if (XShapeCombineMask != NULL) + XShapeCombineMask = (PFN_XShapeCombineMask) dlsym(RGFW_libxshape, "XShapeCombineMask"); + + if (XShapeCombineRegion != NULL) + XShapeCombineRegion = (PFN_XShapeCombineRegion) dlsym(RGFW_libxshape, "XShapeCombineMask"); + + if (passthrough) { + Region region = XCreateRegion(); + XShapeCombineRegion(win->src.display, win->src.window, ShapeInput, 0, 0, region, ShapeSet); + XDestroyRegion(region); + + return; + } + + XShapeCombineMask(win->src.display, win->src.window, ShapeInput, 0, 0, None, ShapeSet); + } + #endif /* the majority function is sourced from GLFW @@ -3587,8 +2955,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ if (event.xbutton.x == v.x && event.xbutton.y == v.y) return; - XWarpPointer(win->src.display, None, None, 0, 0, 0, 0, -event.xbutton.x, -event.xbutton.y); - XWarpPointer(win->src.display, None, None, 0, 0, 0, 0, v.x, v.y); + XWarpPointer(win->src.display, None, win->src.window, 0, 0, 0, 0, (int) v.x - win->r.x, (int) v.y - win->r.y); } RGFWDEF void RGFW_window_disableMouse(RGFW_window* win) { @@ -3654,7 +3021,8 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ if (target == UTF8 || target == XA_STRING) { s = (char*)RGFW_MALLOC(sizeof(char) * sizeN); - strcpy(s, data); + strncpy(s, data, sizeN); + s[sizeN] = '\0'; XFree(data); } @@ -3937,7 +3305,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ XrmValue value; char* type = NULL; - if (XrmGetResource(db, "Xft.dpi", "Xft.Dpi", &type, &value) && type && strcmp(type, "String") == 0) + if (XrmGetResource(db, "Xft.dpi", "Xft.Dpi", &type, &value) && type && strncmp(type, "String", 7) == 0) xdpi = ydpi = atof(value.addr); XrmDestroyDatabase(db); #endif @@ -3955,7 +3323,7 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ monitor.physW = (monitor.rect.w * 25.4f / 96.f); monitor.physH = (monitor.rect.h * 25.4f / 96.f); - strcpy(monitor.name, DisplayString(display)); + strncpy(monitor.name, DisplayString(display), 128); XGetSystemContentScale(display, &monitor.scaleX, &monitor.scaleY); @@ -4024,9 +3392,187 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) { return RGFW_XCreateMonitor(DefaultScreen(win->src.display)); } + + #ifdef RGFW_OPENGL + void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) { + assert(win != NULL); + + glXMakeCurrent((Display*) win->src.display, (Drawable) win->src.window, (GLXContext) win->src.rSurf); + } + #endif + + + void RGFW_window_swapBuffers(RGFW_window* win) { + assert(win != NULL); + + RGFW_window_makeCurrent(win); + + /* clear the window*/ + if (!(win->src.winArgs & RGFW_NO_CPU_RENDER)) { +#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) + #ifdef RGFW_OSMESA + RGFW_OSMesa_reorganize(); + #endif + RGFW_area area = RGFW_bufferSize; + +#ifndef RGFW_X11_DONT_CONVERT_BGR + win->src.bitmap->data = (char*) win->buffer; + u32 x, y; + for (y = 0; y < (u32)win->r.h; y++) { + for (x = 0; x < (u32)win->r.w; x++) { + u32 index = (y * 4 * area.w) + x * 4; + + u8 red = win->src.bitmap->data[index]; + win->src.bitmap->data[index] = win->buffer[index + 2]; + win->src.bitmap->data[index + 2] = red; + + } + } +#endif + XPutImage(win->src.display, (Window) win->src.window, win->src.gc, win->src.bitmap, 0, 0, 0, 0, RGFW_bufferSize.w, RGFW_bufferSize.h); +#endif + } + + if (!(win->src.winArgs & RGFW_NO_GPU_RENDER)) { + #ifdef RGFW_EGL + eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface); + #elif defined(RGFW_OPENGL) + glXSwapBuffers((Display*) win->src.display, (Window) win->src.window); + #endif + } + + RGFW_window_checkFPS(win); + } + + #if !defined(RGFW_EGL) + void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) { + assert(win != NULL); + + #if defined(RGFW_OPENGL) + ((PFNGLXSWAPINTERVALEXTPROC) glXGetProcAddress((GLubyte*) "glXSwapIntervalEXT"))((Display*) win->src.display, (Window) win->src.window, swapInterval); + #endif + + win->fpsCap = (swapInterval == 1) ? 0 : swapInterval; + } + #endif + + + void RGFW_window_close(RGFW_window* win) { + assert(win != NULL); +#ifdef RGFW_EGL + RGFW_closeEGL(win); #endif +#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) + if (win->buffer != NULL) { + XDestroyImage((XImage*) win->src.bitmap); + XFreeGC(win->src.display, win->src.gc); + } +#endif + + if ((Display*) win->src.display) { +#ifdef RGFW_OPENGL + glXDestroyContext((Display*) win->src.display, win->src.rSurf); +#endif + + if (win == RGFW_root) + RGFW_root = NULL; + + if ((Drawable) win->src.window) + XDestroyWindow((Display*) win->src.display, (Drawable) win->src.window); /* close the window*/ + + XCloseDisplay((Display*) win->src.display); /* kill the display*/ + } + +#ifdef RGFW_ALLOC_DROPFILES + { + u32 i; + for (i = 0; i < RGFW_MAX_DROPS; i++) + RGFW_FREE(win->event.droppedFiles[i]); + + + RGFW_FREE(win->event.droppedFiles); + } +#endif + + RGFW_windowsOpen--; +#if !defined(RGFW_NO_X11_CURSOR_PRELOAD) && !defined(RGFW_NO_X11_CURSOR) + if (X11Cursorhandle != NULL && RGFW_windowsOpen <= 0) { + dlclose(X11Cursorhandle); + + X11Cursorhandle = NULL; + } +#endif + + if (RGFW_libxshape != NULL && RGFW_windowsOpen <= 0) { + dlclose(RGFW_libxshape); + RGFW_libxshape = NULL; + } + + /* 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) { + 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; + + return nanoSeconds; + } + + u64 RGFW_getTime(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; + + return (double)(nanoSeconds) * 1e-9; + } +/* + End of linux / unix defines +*/ + +#endif /* RGFW_X11 */ + + +/* + + Start of Windows defines + + +*/ + #ifdef RGFW_WINDOWS + #include + #include + #include + #include + #include + #include + #include + #include + + #ifndef RGFW_NO_XINPUT + typedef DWORD (WINAPI * PFN_XInputGetState)(DWORD,XINPUT_STATE*); + PFN_XInputGetState XInputGetStateSRC = NULL; + #define XInputGetState XInputGetStateSRC + + typedef DWORD (WINAPI * PFN_XInputGetKeystroke)(DWORD, DWORD, PXINPUT_KEYSTROKE); + PFN_XInputGetKeystroke XInputGetKeystrokeSRC = NULL; + #define XInputGetKeystroke XInputGetKeystrokeSRC + + static HMODULE RGFW_XInput_dll = NULL; + #endif + + u32 RGFW_mouseIconSrc[] = {OCR_NORMAL, OCR_NORMAL, OCR_IBEAM, OCR_CROSS, OCR_HAND, OCR_SIZEWE, OCR_SIZENS, OCR_SIZENWSE, OCR_SIZENESW, OCR_SIZEALL, OCR_NO}; + char* createUTF8FromWideStringWin32(const WCHAR* source); #define GL_FRONT 0x0404 @@ -4064,21 +3610,18 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ void* RGFWjoystickApi = NULL; /* these two wgl functions need to be preloaded */ - typedef long long int (WINAPI* wglCreateContextAttribsARB_type)(HDC hdc, HGLRC hShareContext, - const int* attribList); - wglCreateContextAttribsARB_type wglCreateContextAttribsARB = NULL; + typedef HGLRC (WINAPI *PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC hdc, HGLRC hglrc, const int *attribList); + PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL; /* defines for creating ARB attributes */ #define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 #define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 #define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 -#define WGL_TRANSPARENT_ARB 0x200A #define WGL_DRAW_TO_WINDOW_ARB 0x2001 #define WGL_ACCELERATION_ARB 0x2003 #define WGL_NO_ACCELERATION_ARB 0x2025 #define WGL_SUPPORT_OPENGL_ARB 0x2010 #define WGL_DOUBLE_BUFFER_ARB 0x2011 -#define WGL_PIXEL_TYPE_ARB 0x2013 #define WGL_COLOR_BITS_ARB 0x2014 #define WGL_RED_BITS_ARB 0x2015 #define WGL_RED_SHIFT_ARB 0x2016 @@ -4099,7 +3642,6 @@ RGFW_UNUSED(win); /* if buffer rendering is not being used */ #define WGL_DEPTH_BITS_ARB 0x2022 #define WGL_STENCIL_BITS_ARB 0x2023 #define WGL_FULL_ACCELERATION_ARB 0x2027 -#define WGL_TYPE_RGBA_ARB 0x202B #define WGL_CONTEXT_FLAGS_ARB 0x2094 #define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 #define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 @@ -4144,7 +3686,7 @@ static HMODULE wglinstance = NULL; return (void*) GetProcAddress(wglinstance, procname); } - typedef u64 (APIENTRY* PFNWGLCHOOSEPIXELFORMATARBPROC)(HDC hdc, const int* piAttribIList, const FLOAT* pfAttribFList, UINT nMaxFormats, int* piFormats, UINT* nNumFormats); + typedef HRESULT (APIENTRY* PFNWGLCHOOSEPIXELFORMATARBPROC)(HDC hdc, const int* piAttribIList, const FLOAT* pfAttribFList, UINT nMaxFormats, int* piFormats, UINT* nNumFormats); static PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = NULL; #endif @@ -4169,11 +3711,14 @@ static HMODULE wglinstance = NULL; #ifndef RGFW_NO_DPI static HMODULE RGFW_Shcore_dll = NULL; - typedef u64 (WINAPI * PFN_GetDpiForMonitor)(HMONITOR,MONITOR_DPI_TYPE,UINT*,UINT*); + typedef HRESULT (WINAPI * PFN_GetDpiForMonitor)(HMONITOR,MONITOR_DPI_TYPE,UINT*,UINT*); PFN_GetDpiForMonitor GetDpiForMonitorSRC = NULL; #define GetDpiForMonitor GetDpiForMonitorSRC #endif + __declspec(dllimport) u32 __stdcall timeBeginPeriod(u32 uPeriod); + + #ifndef RGFW_NO_XINPUT void RGFW_loadXInput(void) { u32 i; static const char* names[] = { @@ -4188,22 +3733,76 @@ static HMODULE wglinstance = NULL; RGFW_XInput_dll = LoadLibraryA(names[i]); if (RGFW_XInput_dll) { - XInputGetStateSRC = (PFN_XInputGetState)GetProcAddress(RGFW_XInput_dll, "XInputGetState"); + XInputGetStateSRC = (PFN_XInputGetState)(void*)GetProcAddress(RGFW_XInput_dll, "XInputGetState"); if (XInputGetStateSRC == NULL) printf("Failed to load XInputGetState"); } } } + #endif + + 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(); + + BITMAPV5HEADER bi = { 0 }; + ZeroMemory(&bi, sizeof(bi)); + bi.bV5Size = sizeof(bi); + bi.bV5Width = RGFW_bufferSize.w; + bi.bV5Height = -((LONG) RGFW_bufferSize.h); + bi.bV5Planes = 1; + bi.bV5BitCount = 32; + bi.bV5Compression = BI_BITFIELDS; + bi.bV5BlueMask = 0x00ff0000; + bi.bV5GreenMask = 0x0000ff00; + bi.bV5RedMask = 0x000000ff; + bi.bV5AlphaMask = 0xff000000; + + win->src.bitmap = CreateDIBSection(win->src.hdc, + (BITMAPINFO*) &bi, + DIB_RGB_COLORS, + (void**) &win->buffer, + NULL, + (DWORD) 0); + + 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); + #endif +#else +RGFW_UNUSED(win); /* if buffer rendering is not being used */ +#endif + } + + void RGFW_window_setDND(RGFW_window* win, b8 allow) { + DragAcceptFiles(win->src.window, allow); + } + + void RGFW_clipCursor(RGFW_rect rect) { + if (!rect.x && !rect.y && rect.w && !rect.h) { + ClipCursor(NULL); + return; + } + + RECT r = {rect.x, rect.y, rect.x + rect.w, rect.y + rect.h}; + ClipCursor(&r); + } RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) { + #ifndef RGFW_NO_XINPUT if (RGFW_XInput_dll == NULL) RGFW_loadXInput(); - + #endif + #ifndef RGFW_NO_DPI if (RGFW_Shcore_dll == NULL) { RGFW_Shcore_dll = LoadLibraryA("shcore.dll"); - GetDpiForMonitorSRC = (PFN_GetDpiForMonitor)GetProcAddress(RGFW_Shcore_dll, "GetDpiForMonitor"); + GetDpiForMonitorSRC = (PFN_GetDpiForMonitor)(void*)GetProcAddress(RGFW_Shcore_dll, "GetDpiForMonitor"); } #endif @@ -4219,6 +3818,8 @@ static HMODULE wglinstance = NULL; #endif } + timeBeginPeriod(1); + if (name[0] == 0) name = (char*) " "; RGFW_eventWindow.r = RGFW_RECT(-1, -1, -1, -1); @@ -4226,10 +3827,10 @@ static HMODULE wglinstance = NULL; RGFW_window* win = RGFW_window_basic_init(rect, args); - if (RGFW_root == NULL) { - RGFW_root = win; - } - + win->src.maxSize = RGFW_AREA(0, 0); + win->src.minSize = RGFW_AREA(0, 0); + + HINSTANCE inh = GetModuleHandleA(NULL); WNDCLASSA Class = { 0 }; /* Setup the Window class. */ @@ -4260,15 +3861,13 @@ static HMODULE wglinstance = NULL; win->src.hOffset = (windowRect.bottom - windowRect.top) - (clientRect.bottom - clientRect.top); 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_TRANSPARENT_WINDOW) { - SetWindowLongA(win->src.window, GWL_EXSTYLE, GetWindowLongA(win->src.window, GWL_EXSTYLE) | WS_EX_LAYERED); - } if (args & RGFW_ALLOW_DND) { win->src.winArgs |= RGFW_ALLOW_DND; - DragAcceptFiles(win->src.window, TRUE); + RGFW_window_setDND(win, 1); } win->src.hdc = GetDC(win->src.window); + if ((args & RGFW_NO_INIT_API) == 0) { #ifdef RGFW_DIRECTX assert(FAILED(CreateDXGIFactory(&__uuidof(IDXGIFactory), (void**) &RGFW_dxInfo.pFactory)) == 0); @@ -4338,10 +3937,10 @@ static HMODULE wglinstance = NULL; .nVersion = 1, .iPixelType = PFD_TYPE_RGBA, .dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, - .cColorBits = 32, + .cColorBits = 24, .cAlphaBits = 8, .iLayerType = PFD_MAIN_PLANE, - .cDepthBits = 24, + .cDepthBits = 32, .cStencilBits = 8, }; @@ -4352,8 +3951,8 @@ static HMODULE wglinstance = NULL; wglMakeCurrent(dummy_dc, dummy_context); if (wglChoosePixelFormatARB == NULL) { - wglCreateContextAttribsARB = (wglCreateContextAttribsARB_type) wglGetProcAddress("wglCreateContextAttribsARB"); - wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC) wglGetProcAddress("wglChoosePixelFormatARB"); + wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC) (void*) wglGetProcAddress("wglCreateContextAttribsARB"); + wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC) (void*)wglGetProcAddress("wglChoosePixelFormatARB"); } wglMakeCurrent(dummy_dc, 0); @@ -4412,8 +4011,8 @@ static HMODULE wglinstance = NULL; } wglMakeCurrent(win->src.hdc, win->src.rSurf); - wglShareLists(RGFW_root->src.rSurf, win->src.rSurf); #endif + } #ifdef RGFW_OSMESA #ifdef RGFW_LINK_OSM ESA @@ -4424,33 +4023,67 @@ static HMODULE wglinstance = NULL; #endif #ifdef RGFW_OPENGL - ReleaseDC(win->src.window, win->src.hdc); - win->src.hdc = GetDC(win->src.window); - wglMakeCurrent(win->src.hdc, win->src.rSurf); + 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); + } #endif DestroyWindow(dummyWin); RGFW_init_buffer(win); -#ifdef RGFW_VULKAN - RGFW_initVulkan(win); -#endif + #ifndef RGFW_NO_MONITOR if (args & RGFW_SCALE_TO_MONITOR) RGFW_window_scaleToMonitor(win); + #endif #ifdef RGFW_EGL - RGFW_createOpenGLContext(win); + if ((args & RGFW_NO_INIT_API) == 0) + RGFW_createOpenGLContext(win); #endif if (args & RGFW_HIDE_MOUSE) RGFW_window_showMouse(win, 0); + if (args & RGFW_TRANSPARENT_WINDOW) { + SetWindowLong(win->src.window, GWL_EXSTYLE, GetWindowLong(win->src.window, GWL_EXSTYLE) | WS_EX_LAYERED); + SetLayeredWindowAttributes(win->src.window, RGB(255, 255, 255), RGFW_ALPHA, LWA_ALPHA); + } + ShowWindow(win->src.window, SW_SHOWNORMAL); + + if (RGFW_root == NULL) + RGFW_root = win; + + #ifdef RGFW_OPENGL + else + wglShareLists(RGFW_root->src.rSurf, win->src.rSurf); + #endif return win; } + void RGFW_window_setBorder(RGFW_window* win, u8 border) { + DWORD style = GetWindowLong(win->src.window, GWL_STYLE); + + if (border == 0) { + SetWindowLong(win->src.window, GWL_STYLE, style & ~WS_OVERLAPPEDWINDOW); + SetWindowPos( + win->src.window, HWND_TOP, 0, 0, 0, 0, + SWP_NOZORDER | SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE + ); + } + else { + SetWindowLong(win->src.window, GWL_STYLE, style | WS_OVERLAPPEDWINDOW); + SetWindowPos( + win->src.window, HWND_TOP, 0, 0, 0, 0, + SWP_NOZORDER | SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE + ); + } + } + RGFW_area RGFW_getScreenSize(void) { return RGFW_AREA(GetDeviceCaps(GetDC(NULL), HORZRES), GetDeviceCaps(GetDC(NULL), VERTRES)); @@ -4494,98 +4127,55 @@ static HMODULE wglinstance = NULL; ShowWindow(win->src.window, SW_RESTORE); } - static i32 RGFW_checkXInput(RGFW_Event* e) { - static WORD buttons[4]; - static BYTE triggers[4][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} }; + u8 RGFW_xinput2RGFW[] = { + RGFW_JS_A, /* or PS X button */ + RGFW_JS_B, /* or PS circle button */ + RGFW_JS_X, /* or PS square button */ + RGFW_JS_Y, /* or PS triangle button */ + RGFW_JS_R1, /* right bumper */ + RGFW_JS_L1, /* left bump */ + RGFW_JS_L2, /* left trigger*/ + RGFW_JS_R2, /* right trigger */ + 0, 0, 0, 0, 0, 0, 0, 0, + RGFW_JS_UP, /* dpad up */ + RGFW_JS_DOWN, /* dpad down*/ + RGFW_JS_LEFT, /* dpad left */ + RGFW_JS_RIGHT, /* dpad right */ + RGFW_JS_START, /* start button */ + RGFW_JS_SELECT/* select button */ + }; + + static i32 RGFW_checkXInput(RGFW_window* win, RGFW_Event* e) { size_t i; for (i = 0; i < 4; i++) { + XINPUT_KEYSTROKE keystroke; + + if (XInputGetKeystroke == NULL) + return 0; + + DWORD result = XInputGetKeystroke((DWORD)i, 0, &keystroke); + + if ((keystroke.Flags & XINPUT_KEYSTROKE_REPEAT) == 0 && result != ERROR_EMPTY) { + if (result != ERROR_SUCCESS) + return 0; + + if (keystroke.VirtualKey > VK_PAD_BACK) + continue; + + // 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); + + return 1; + } + XINPUT_STATE state; if (XInputGetState == NULL || XInputGetState((DWORD) i, &state) == ERROR_DEVICE_NOT_CONNECTED ) return 0; - - e->button = 0; - if (state.Gamepad.wButtons & XINPUT_GAMEPAD_A && !(buttons[i] & XINPUT_GAMEPAD_A)) { - e->button = RGFW_JS_A; - e->type = RGFW_jsButtonPressed; - buttons[i] = state.Gamepad.wButtons; - return 1; - } else if (state.Gamepad.wButtons & XINPUT_GAMEPAD_B && !(buttons[i] & XINPUT_GAMEPAD_B)) - e->button = RGFW_JS_B; - else if (state.Gamepad.wButtons & XINPUT_GAMEPAD_Y && !(buttons[i] & XINPUT_GAMEPAD_Y)) - e->button = RGFW_JS_Y; - else if (state.Gamepad.wButtons & XINPUT_GAMEPAD_X && !(buttons[i] & XINPUT_GAMEPAD_X)) - e->button = RGFW_JS_X; - else if (state.Gamepad.wButtons & XINPUT_GAMEPAD_START && !(buttons[i] & XINPUT_GAMEPAD_START)) - e->button = RGFW_JS_START; - else if (state.Gamepad.wButtons & XINPUT_GAMEPAD_BACK && !(buttons[i] & XINPUT_GAMEPAD_BACK)) - e->button = RGFW_JS_SELECT; - else if (state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP && !(buttons[i] & XINPUT_GAMEPAD_DPAD_UP)) - e->button = RGFW_JS_UP; - else if (state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN && !(buttons[i] & XINPUT_GAMEPAD_DPAD_DOWN)) - e->button = RGFW_JS_DOWN; - else if (state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT && !(buttons[i] & XINPUT_GAMEPAD_DPAD_LEFT)) - e->button = RGFW_JS_LEFT; - else if (state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT && !(buttons[i] & XINPUT_GAMEPAD_DPAD_RIGHT)) - e->button = RGFW_JS_RIGHT; - else if (state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER && !(buttons[i] & XINPUT_GAMEPAD_LEFT_SHOULDER)) - e->button = RGFW_JS_L1; - else if (state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER && !(buttons[i] & XINPUT_GAMEPAD_RIGHT_SHOULDER)) - e->button = RGFW_JS_R1; - else if (state.Gamepad.bLeftTrigger && triggers[i][0] == 0) - e->button = RGFW_JS_L2; - else if (state.Gamepad.bRightTrigger && triggers[i][1] == 0) - e->button = RGFW_JS_R2; - - triggers[i][0] = state.Gamepad.bLeftTrigger; - triggers[i][1] = state.Gamepad.bRightTrigger; - - if (e->button) { - buttons[i] = state.Gamepad.wButtons; - e->type = RGFW_jsButtonPressed; - return 1; - } - - if (!(state.Gamepad.wButtons & XINPUT_GAMEPAD_A) && (buttons[i] & XINPUT_GAMEPAD_A)) { - e->button = RGFW_JS_A; - e->type = RGFW_jsButtonReleased; - buttons[i] = state.Gamepad.wButtons; - return 1; - } else if (!(state.Gamepad.wButtons & XINPUT_GAMEPAD_B) && (buttons[i] & XINPUT_GAMEPAD_B)) - e->button = RGFW_JS_B; - else if (!(state.Gamepad.wButtons & XINPUT_GAMEPAD_Y) && (buttons[i] & XINPUT_GAMEPAD_Y)) - e->button = RGFW_JS_Y; - else if (!(state.Gamepad.wButtons & XINPUT_GAMEPAD_X) && (buttons[i] & XINPUT_GAMEPAD_X)) - e->button = RGFW_JS_X; - else if (!(state.Gamepad.wButtons & XINPUT_GAMEPAD_START) && (buttons[i] & XINPUT_GAMEPAD_START)) - e->button = RGFW_JS_START; - else if (!(state.Gamepad.wButtons & XINPUT_GAMEPAD_BACK) && (buttons[i] & XINPUT_GAMEPAD_BACK)) - e->button = RGFW_JS_SELECT; - else if (!(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP) && (buttons[i] & XINPUT_GAMEPAD_DPAD_UP)) - e->button = RGFW_JS_UP; - else if (!(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN) && (buttons[i] & XINPUT_GAMEPAD_DPAD_DOWN)) - e->button = RGFW_JS_DOWN; - else if (!(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT) && (buttons[i] & XINPUT_GAMEPAD_DPAD_LEFT)) - e->button = RGFW_JS_LEFT; - else if (!(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) && (buttons[i] & XINPUT_GAMEPAD_DPAD_RIGHT)) - e->button = RGFW_JS_RIGHT; - else if (!(state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER) && (buttons[i] & XINPUT_GAMEPAD_LEFT_SHOULDER)) - e->button = RGFW_JS_L1; - else if (!(state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER) && (buttons[i] & XINPUT_GAMEPAD_RIGHT_SHOULDER)) - e->button = RGFW_JS_R1; - else if (state.Gamepad.bLeftTrigger == 0 && triggers[i][0] != 0) - e->button = RGFW_JS_L2; - else if (state.Gamepad.bRightTrigger == 0 && triggers[i][1] != 0) - e->button = RGFW_JS_R2; - - buttons[i] = state.Gamepad.wButtons; - - if (e->button) { - e->type = RGFW_jsButtonReleased; - return 1; - } #define INPUT_DEADZONE ( 0.24f * (float)(0x7FFF) ) // Default to 24% of the +/- 32767 range. This is a reasonable default value but can be altered if needed. if ((state.Gamepad.sThumbLX < INPUT_DEADZONE && @@ -4629,6 +4219,10 @@ static HMODULE wglinstance = NULL; RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) { assert(win != NULL); + if (win->event.type == RGFW_quit) { + return NULL; + } + MSG msg; if (RGFW_eventWindow.src.window == win->src.window) { @@ -4636,12 +4230,14 @@ static HMODULE wglinstance = NULL; win->r.x = RGFW_eventWindow.r.x; win->r.y = RGFW_eventWindow.r.y; win->event.type = RGFW_windowMoved; + RGFW_windowMoveCallback(win, win->r); } if (RGFW_eventWindow.r.w != -1) { win->r.w = RGFW_eventWindow.r.w; win->r.h = RGFW_eventWindow.r.h; win->event.type = RGFW_windowResized; + RGFW_windowResizeCallback(win, win->r); } RGFW_eventWindow.src.window = NULL; @@ -4650,37 +4246,82 @@ static HMODULE wglinstance = NULL; return &win->event; } + + static HDROP drop; + + if (win->event.type == RGFW_dnd_init) { + if (win->event.droppedFilesCount) { + u32 i; + for (i = 0; i < win->event.droppedFilesCount; i++) + win->event.droppedFiles[i][0] = '\0'; + } + + win->event.droppedFilesCount = 0; + win->event.droppedFilesCount = DragQueryFileW(drop, 0xffffffff, NULL, 0); + //win->event.droppedFiles = (char**)RGFW_CALLOC(win->event.droppedFilesCount, sizeof(char*)); + + u32 i; + for (i = 0; i < win->event.droppedFilesCount; i++) { + const UINT length = DragQueryFileW(drop, i, NULL, 0); + WCHAR* buffer = (WCHAR*) RGFW_CALLOC((size_t) length + 1, sizeof(WCHAR)); + + DragQueryFileW(drop, i, buffer, length + 1); + strncpy(win->event.droppedFiles[i], createUTF8FromWideStringWin32(buffer), RGFW_MAX_PATH); + win->event.droppedFiles[i][RGFW_MAX_PATH - 1] = '\0'; + RGFW_FREE(buffer); + } + + DragFinish(drop); + RGFW_dndCallback(win, win->event.droppedFiles, win->event.droppedFilesCount); + + win->event.type = RGFW_dnd; + return &win->event; + } + win->event.inFocus = (GetForegroundWindow() == win->src.window); - if (RGFW_checkXInput(&win->event)) + if (RGFW_checkXInput(win, &win->event)) return &win->event; - if (win->event.type == RGFW_quit) - return NULL; - static BYTE keyboardState[256]; if (PeekMessageA(&msg, win->src.window, 0u, 0u, PM_REMOVE)) { switch (msg.message) { case WM_CLOSE: case WM_QUIT: + RGFW_windowQuitCallback(win); win->event.type = RGFW_quit; break; case WM_ACTIVATE: win->event.inFocus = (LOWORD(msg.wParam) == WA_INACTIVE); - if (win->event.inFocus) + if (win->event.inFocus) { win->event.type = RGFW_focusIn; - else + RGFW_focusCallback(win, 1); + } + else { win->event.type = RGFW_focusOut; - - break; + RGFW_focusCallback(win, 0); + } + break; + + case WM_PAINT: + win->event.type = RGFW_windowRefresh; + RGFW_windowRefreshCallback(win); + break; + + case WM_MOUSELEAVE: + win->event.type = RGFW_mouseLeave; + win->src.winArgs |= RGFW_MOUSE_LEFT; + RGFW_mouseNotifyCallBack(win, win->event.point, 0); + break; + case WM_KEYUP: { win->event.keyCode = RGFW_apiKeyCodeToRGFW((u32) msg.wParam); - RGFW_keyboard_prev[win->event.keyCode] = RGFW_isPressedI(win, win->event.keyCode); + RGFW_keyboard[win->event.keyCode].prev = RGFW_isPressed(win, win->event.keyCode); static char keyName[16]; @@ -4692,22 +4333,25 @@ static HMODULE wglinstance = NULL; CharLowerBuffA(keyName, 16); } } - + + RGFW_updateLockState(win, (GetKeyState(VK_CAPITAL) & 0x0001), (GetKeyState(VK_NUMLOCK) & 0x0001)); + strncpy(win->event.keyName, keyName, 16); - if (RGFW_isPressedI(win, RGFW_ShiftL)) { + if (RGFW_isPressed(win, RGFW_ShiftL)) { ToAscii((UINT) msg.wParam, MapVirtualKey((UINT) msg.wParam, MAPVK_VK_TO_CHAR), keyboardState, (LPWORD) win->event.keyName, 0); } win->event.type = RGFW_keyReleased; - RGFW_keyboard[win->event.keyCode] = 0; + RGFW_keyboard[win->event.keyCode].current = 0; + RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, 0); break; } case WM_KEYDOWN: { win->event.keyCode = RGFW_apiKeyCodeToRGFW((u32) msg.wParam); - RGFW_keyboard_prev[win->event.keyCode] = RGFW_isPressedI(win, win->event.keyCode); + RGFW_keyboard[win->event.keyCode].prev = RGFW_isPressed(win, win->event.keyCode); static char keyName[16]; @@ -4719,24 +4363,36 @@ static HMODULE wglinstance = NULL; CharLowerBuffA(keyName, 16); } } - + + RGFW_updateLockState(win, (GetKeyState(VK_CAPITAL) & 0x0001), (GetKeyState(VK_NUMLOCK) & 0x0001)); + strncpy(win->event.keyName, keyName, 16); - if (RGFW_isPressedI(win, RGFW_ShiftL) & 0x8000) { + if (RGFW_isPressed(win, RGFW_ShiftL) & 0x8000) { ToAscii((UINT) msg.wParam, MapVirtualKey((UINT) msg.wParam, MAPVK_VK_TO_CHAR), keyboardState, (LPWORD) win->event.keyName, 0); } win->event.type = RGFW_keyPressed; - RGFW_keyboard[win->event.keyCode] = 1; + RGFW_keyboard[win->event.keyCode].current = 1; + RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, 1); break; } case WM_MOUSEMOVE: + win->event.type = RGFW_mousePosChanged; + win->event.point.x = GET_X_LPARAM(msg.lParam); win->event.point.y = GET_Y_LPARAM(msg.lParam); - win->event.type = RGFW_mousePosChanged; + RGFW_mousePosCallback(win, win->event.point); + + if (win->src.winArgs & RGFW_MOUSE_LEFT) { + win->src.winArgs ^= RGFW_MOUSE_LEFT; + win->event.type = RGFW_mouseEnter; + RGFW_mouseNotifyCallBack(win, win->event.point, 1); + } + break; case WM_LBUTTONDOWN: @@ -4744,18 +4400,21 @@ static HMODULE wglinstance = NULL; RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button]; RGFW_mouseButtons[win->event.button] = 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_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_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); break; case WM_MOUSEWHEEL: @@ -4770,6 +4429,7 @@ static HMODULE wglinstance = NULL; win->event.scroll = (SHORT) HIWORD(msg.wParam) / (double) WHEEL_DELTA; win->event.type = RGFW_mouseButtonPressed; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); break; case WM_LBUTTONUP: @@ -4779,6 +4439,7 @@ static HMODULE wglinstance = NULL; RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button]; RGFW_mouseButtons[win->event.button] = 0; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0); break; case WM_RBUTTONUP: win->event.button = RGFW_mouseRight; @@ -4786,6 +4447,7 @@ static HMODULE wglinstance = NULL; RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button]; RGFW_mouseButtons[win->event.button] = 0; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0); break; case WM_MBUTTONUP: win->event.button = RGFW_mouseMiddle; @@ -4793,29 +4455,17 @@ static HMODULE wglinstance = NULL; RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button]; RGFW_mouseButtons[win->event.button] = 0; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0); break; /* much of this event is source from glfw */ - case WM_DROPFILES: { + case WM_DROPFILES: { + win->event.type = RGFW_dnd_init; - if (win->event.droppedFilesCount) { - u32 i; - for (i = 0; i < win->event.droppedFilesCount; i++) - win->event.droppedFiles[i][0] = '\0'; - } - - win->event.droppedFilesCount = 0; - - win->event.type = RGFW_dnd; - - HDROP drop = (HDROP) msg.wParam; + drop = (HDROP) msg.wParam; POINT pt; - u32 i; - - win->event.droppedFilesCount = DragQueryFileW(drop, 0xffffffff, NULL, 0); - //win->event.droppedFiles = (char**)RGFW_CALLOC(win->event.droppedFilesCount, sizeof(char*)); /* Move the mouse to the position of the drop */ DragQueryPoint(drop, &pt); @@ -4823,19 +4473,9 @@ static HMODULE wglinstance = NULL; win->event.point.x = pt.x; win->event.point.y = pt.y; - for (i = 0; i < win->event.droppedFilesCount; i++) { - const UINT length = DragQueryFileW(drop, i, NULL, 0); - WCHAR* buffer = (WCHAR*) RGFW_CALLOC((size_t) length + 1, sizeof(WCHAR)); - - DragQueryFileW(drop, i, buffer, length + 1); - strcpy(win->event.droppedFiles[i], createUTF8FromWideStringWin32(buffer)); - - RGFW_FREE(buffer); - } - - DragFinish(drop); + RGFW_dndInitCallback(win, win->event.point); } - break; + break; case WM_GETMINMAXINFO: { if (win->src.maxSize.w == 0 && win->src.maxSize.h == 0) @@ -4860,18 +4500,10 @@ static HMODULE wglinstance = NULL; else win->event.type = 0; - win->event.lockState = 0; - - if ((GetKeyState(VK_CAPITAL) & 0x0001) != 0) - win->event.lockState |= RGFW_CAPSLOCK; - if ((GetKeyState(VK_NUMLOCK) & 0x0001) != 0) - win->event.lockState |= RGFW_NUMLOCK; - if ((GetKeyState(VK_SCROLL) & 0x0001) != 0) - win->event.lockState |= 3; - - - if (!IsWindow(win->src.window)) + if (!IsWindow(win->src.window)) { win->event.type = RGFW_quit; + RGFW_windowQuitCallback(win); + } if (win->event.type) return &win->event; @@ -4921,7 +4553,8 @@ static HMODULE wglinstance = NULL; info->iIndex++; return TRUE; } - + + #ifndef RGFW_NO_MONITOR RGFW_monitor win32CreateMonitor(HMONITOR src) { RGFW_monitor monitor; MONITORINFO monitorInfo; @@ -4943,7 +4576,7 @@ static HMODULE wglinstance = NULL; for (deviceIndex = 0; EnumDisplayDevicesA(0, (DWORD) deviceIndex, &dd, 0); deviceIndex++) { char* deviceName = dd.DeviceName; if (EnumDisplayDevicesA(deviceName, info.iIndex, &dd, 0)) { - strcpy(monitor.name, dd.DeviceString); /* copy the monitor's name */ + strncpy(monitor.name, dd.DeviceString, 128); /* copy the monitor's name */ break; } } @@ -4975,7 +4608,10 @@ static HMODULE wglinstance = NULL; return monitor; } + #endif /* RGFW_NO_MONITOR */ + + #ifndef RGFW_NO_MONITOR RGFW_monitor RGFW_monitors[6]; BOOL CALLBACK GetMonitorHandle(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) { RGFW_UNUSED(hdcMonitor) @@ -5008,6 +4644,7 @@ static HMODULE wglinstance = NULL; HMONITOR src = MonitorFromWindow(win->src.window, MONITOR_DEFAULTTOPRIMARY); return win32CreateMonitor(src); } + #endif HICON RGFW_loadHandleImage(RGFW_window* win, u8* src, RGFW_area a, BOOL icon) { assert(win != NULL); @@ -5087,10 +4724,8 @@ static HMODULE wglinstance = NULL; if (mouse > (sizeof(RGFW_mouseIconSrc) / sizeof(u32))) return; - - mouse = RGFW_mouseIconSrc[mouse]; - char* icon = MAKEINTRESOURCEA(mouse); + char* icon = MAKEINTRESOURCEA(RGFW_mouseIconSrc[mouse]); SetClassLongPtrA(win->src.window, GCLP_HCURSOR, (LPARAM) LoadCursorA(NULL, icon)); SetCursor(LoadCursorA(NULL, icon)); @@ -5107,21 +4742,6 @@ static HMODULE wglinstance = NULL; void RGFW_window_close(RGFW_window* win) { assert(win != NULL); -#ifdef RGFW_VULKAN - for (u32 i = 0; i < win->src.image_count; i++) { - vkDestroyFramebuffer(RGFW_vulkan_info.device, RGFW_vulkan_info.framebuffers[i], NULL); - } - - for (u32 i = 0; i < win->src.image_count; i++) { - vkDestroyImageView(RGFW_vulkan_info.device, win->src.swapchain_image_views[i], NULL); - } - - vkDestroySwapchainKHR(RGFW_vulkan_info.device, win->src.swapchain, NULL); - vkDestroySurfaceKHR(RGFW_vulkan_info.instance, win->src.rSurf, NULL); - RGFW_FREE(win->src.swapchain_image_views); - RGFW_FREE(win->src.swapchain_images); -#endif - #ifdef RGFW_EGL RGFW_closeEGL(win); #endif @@ -5213,9 +4833,45 @@ static HMODULE wglinstance = NULL; SetWindowTextA(win->src.window, name); } + /* sourced from GLFW */ + #ifndef RGFW_NO_PASSTHROUGH + void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) { + assert(win != NULL); + + COLORREF key = 0; + BYTE alpha = 0; + DWORD flags = 0; + DWORD exStyle = GetWindowLongW(win->src.window, GWL_EXSTYLE); + + if (exStyle & WS_EX_LAYERED) + GetLayeredWindowAttributes(win->src.window, &key, &alpha, &flags); + + if (passthrough) + exStyle |= (WS_EX_TRANSPARENT | WS_EX_LAYERED); + else + { + exStyle &= ~WS_EX_TRANSPARENT; + // NOTE: Window opacity also needs the layered window style so do not + // remove it if the window is alpha blended + if (exStyle & WS_EX_LAYERED) + { + if (!(flags & LWA_ALPHA)) + exStyle &= ~WS_EX_LAYERED; + } + } + + SetWindowLongW(win->src.window, GWL_EXSTYLE, exStyle); + + if (passthrough) { + SetLayeredWindowAttributes(win->src.window, key, alpha, flags); + } + } + #endif + /* much of this function is sourced from GLFW */ void RGFW_window_setIcon(RGFW_window* win, u8* src, RGFW_area a, i32 channels) { assert(win != NULL); + #ifndef RGFW_WIN95 RGFW_UNUSED(channels) HICON handle = RGFW_loadHandleImage(win, src, a, TRUE); @@ -5223,6 +4879,11 @@ static HMODULE wglinstance = NULL; SetClassLongPtrA(win->src.window, GCLP_HICON, (LPARAM) handle); DestroyIcon(handle); + #else + RGFW_UNUSED(src) + RGFW_UNUSED(a) + RGFW_UNUSED(channels) + #endif } char* RGFW_readClipboard(size_t* size) { @@ -5254,6 +4915,8 @@ static HMODULE wglinstance = NULL; if (size != NULL) *size = textLen + 1; + + text[textLen] = '\0'; } /* Release the clipboard data */ @@ -5311,6 +4974,76 @@ static HMODULE wglinstance = NULL; SetCursorPos(p.x, p.y); } + #ifdef RGFW_OPENGL + void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) { + assert(win != NULL); + wglMakeCurrent(win->src.hdc, (HGLRC) win->src.rSurf); + } + #endif + + #ifndef RGFW_EGL + void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) { + assert(win != NULL); + + #if defined(RGFW_OPENGL) + typedef BOOL(APIENTRY* PFNWGLSWAPINTERVALEXTPROC)(int interval); + static PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = NULL; + static void* loadSwapFunc = (void*) 1; + + if (loadSwapFunc == NULL) { + fprintf(stderr, "wglSwapIntervalEXT not supported\n"); + win->fpsCap = (swapInterval == 1) ? 0 : swapInterval; + return; + } + + if (wglSwapIntervalEXT == NULL) { + loadSwapFunc = (void*) wglGetProcAddress("wglSwapIntervalEXT"); + wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC) loadSwapFunc; + } + + if (wglSwapIntervalEXT(swapInterval) == FALSE) + fprintf(stderr, "Failed to set swap interval\n"); + #endif + + win->fpsCap = (swapInterval == 1) ? 0 : swapInterval; + + } + #endif + + void RGFW_window_swapBuffers(RGFW_window* win) { + assert(win != NULL); + + RGFW_window_makeCurrent(win); + + /* clear the window*/ + + if (!(win->src.winArgs & RGFW_NO_CPU_RENDER)) { +#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) + #ifdef RGFW_OSMESA + RGFW_OSMesa_reorganize(); + #endif + + HGDIOBJ oldbmp = SelectObject(win->src.hdcMem, win->src.bitmap); + BitBlt(win->src.hdc, 0, 0, win->r.w, win->r.h, win->src.hdcMem, 0, 0, SRCCOPY); + SelectObject(win->src.hdcMem, oldbmp); +#endif + } + + if (!(win->src.winArgs & RGFW_NO_GPU_RENDER)) { + #ifdef RGFW_EGL + eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface); + #elif defined(RGFW_OPENGL) + SwapBuffers(win->src.hdc); + #endif + + #if defined(RGFW_WINDOWS) && defined(RGFW_DIRECTX) + win->src.swapchain->lpVtbl->Present(win->src.swapchain, 0, 0); + #endif + } + + RGFW_window_checkFPS(win); + } + char* createUTF8FromWideStringWin32(const WCHAR* source) { char* target; i32 size; @@ -5330,15 +5063,395 @@ static HMODULE wglinstance = NULL; return target; } + u64 RGFW_getTimeNS(void) { + LARGE_INTEGER frequency; + QueryPerformanceFrequency(&frequency); + + LARGE_INTEGER counter; + QueryPerformanceCounter(&counter); + + return (u64) (counter.QuadPart * 1e9 / frequency.QuadPart); + } + + u64 RGFW_getTime(void) { + LARGE_INTEGER frequency; + QueryPerformanceFrequency(&frequency); + + LARGE_INTEGER counter; + QueryPerformanceCounter(&counter); + return (u64) (counter.QuadPart / (double) frequency.QuadPart); + } + + void RGFW_sleep(u64 ms) { + Sleep(ms); + } + #ifndef RGFW_NO_THREADS RGFW_thread RGFW_createThread(RGFW_threadFunc_ptr ptr, void* args) { return CreateThread(NULL, 0, ptr, args, 0, NULL); } void RGFW_cancelThread(RGFW_thread thread) { CloseHandle((HANDLE) thread); } void RGFW_joinThread(RGFW_thread thread) { WaitForSingleObject((HANDLE) thread, INFINITE); } void RGFW_setThreadPriority(RGFW_thread thread, u8 priority) { SetThreadPriority((HANDLE) thread, priority); } #endif -#endif +#endif /* RGFW_WINDOWS */ + +/* + End of Windows defines +*/ + + + +/* + + Start of MacOS defines + + +*/ #if defined(RGFW_MACOS) + /* + based on silicon.h + start of cocoa wrapper + */ + +#include +#include +#include +#include +#include + + typedef CGRect NSRect; + typedef CGPoint NSPoint; + typedef CGSize NSSize; + + typedef void NSBitmapImageRep; + typedef void NSCursor; + typedef void NSDraggingInfo; + typedef void NSWindow; + typedef void NSApplication; + typedef void NSScreen; + typedef void NSEvent; + typedef void NSString; + typedef void NSOpenGLContext; + typedef void NSPasteboard; + typedef void NSColor; + typedef void NSArray; + typedef void NSImageRep; + typedef void NSImage; + typedef void NSOpenGLView; + + + typedef const char* NSPasteboardType; + typedef unsigned long NSUInteger; + typedef long NSInteger; + typedef NSInteger NSModalResponse; + +#ifdef __arm64__ + /* ARM just uses objc_msgSend */ +#define abi_objc_msgSend_stret objc_msgSend +#define abi_objc_msgSend_fpret objc_msgSend +#else /* __i386__ */ + /* x86 just uses abi_objc_msgSend_fpret and (NSColor *)objc_msgSend_id respectively */ +#define abi_objc_msgSend_stret objc_msgSend_stret +#define abi_objc_msgSend_fpret objc_msgSend_fpret +#endif + +#define NSAlloc(nsclass) objc_msgSend_id((id)nsclass, sel_registerName("alloc")) +#define objc_msgSend_bool ((BOOL (*)(id, SEL))objc_msgSend) +#define objc_msgSend_void ((void (*)(id, SEL))objc_msgSend) +#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_void_SEL ((void (*)(id, SEL, SEL))objc_msgSend) +#define objc_msgSend_id ((id (*)(id, SEL))objc_msgSend) + + void NSRelease(id obj) { + objc_msgSend_void(obj, sel_registerName("release")); + } + + #define release NSRelease + + NSString* NSString_stringWithUTF8String(const char* str) { + return ((id(*)(id, SEL, const char*))objc_msgSend) + ((id)objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), str); + } + + const char* NSString_to_char(NSString* str) { + return ((const char* (*)(id, SEL)) objc_msgSend) (str, sel_registerName("UTF8String")); + } + + void si_impl_func_to_SEL_with_name(const char* class_name, const char* register_name, void* function) { + Class selected_class; + + if (strcmp(class_name, "NSView") == 0) { + selected_class = objc_getClass("ViewClass"); + } else if (strcmp(class_name, "NSWindow") == 0) { + selected_class = objc_getClass("WindowClass"); + } else { + selected_class = objc_getClass(class_name); + } + + class_addMethod(selected_class, sel_registerName(register_name), (IMP) function, 0); + } + + /* Header for the array. */ + typedef struct siArrayHeader { + size_t count; + /* TODO(EimaMei): Add a `type_width` later on. */ + } siArrayHeader; + + /* Gets the header of the siArray. */ +#define SI_ARRAY_HEADER(s) ((siArrayHeader*)s - 1) + + void* si_array_init_reserve(size_t sizeof_element, size_t count) { + siArrayHeader* ptr = malloc(sizeof(siArrayHeader) + (sizeof_element * count)); + void* array = ptr + sizeof(siArrayHeader); + + siArrayHeader* header = SI_ARRAY_HEADER(array); + header->count = count; + + return array; + } + +#define si_array_len(array) (SI_ARRAY_HEADER(array)->count) +#define si_func_to_SEL(class_name, function) si_impl_func_to_SEL_with_name(class_name, #function":", function) + /* Creates an Objective-C method (SEL) from a regular C function with the option to set the register name.*/ +#define si_func_to_SEL_with_name(class_name, register_name, function) si_impl_func_to_SEL_with_name(class_name, register_name":", function) + + unsigned char* NSBitmapImageRep_bitmapData(NSBitmapImageRep* imageRep) { + return ((unsigned char* (*)(id, SEL))objc_msgSend) + (imageRep, sel_registerName("bitmapData")); + } + +#define NS_ENUM(type, name) type name; enum + + typedef NS_ENUM(NSUInteger, NSBitmapFormat) { + NSBitmapFormatAlphaFirst = 1 << 0, // 0 means is alpha last (RGBA, CMYKA, etc.) + NSBitmapFormatAlphaNonpremultiplied = 1 << 1, // 0 means is premultiplied + NSBitmapFormatFloatingPointSamples = 1 << 2, // 0 is integer + + NSBitmapFormatSixteenBitLittleEndian API_AVAILABLE(macos(10.10)) = (1 << 8), + NSBitmapFormatThirtyTwoBitLittleEndian API_AVAILABLE(macos(10.10)) = (1 << 9), + NSBitmapFormatSixteenBitBigEndian API_AVAILABLE(macos(10.10)) = (1 << 10), + NSBitmapFormatThirtyTwoBitBigEndian API_AVAILABLE(macos(10.10)) = (1 << 11) + }; + + NSBitmapImageRep* NSBitmapImageRep_initWithBitmapData(unsigned char** planes, NSInteger width, NSInteger height, NSInteger bps, NSInteger spp, bool alpha, bool isPlanar, const char* colorSpaceName, NSBitmapFormat bitmapFormat, NSInteger rowBytes, NSInteger pixelBits) { + void* func = sel_registerName("initWithBitmapDataPlanes:pixelsWide:pixelsHigh:bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:colorSpaceName:bitmapFormat:bytesPerRow:bitsPerPixel:"); + + return (NSBitmapImageRep*) ((id(*)(id, SEL, unsigned char**, NSInteger, NSInteger, NSInteger, NSInteger, bool, bool, const char*, NSBitmapFormat, NSInteger, NSInteger))objc_msgSend) + (NSAlloc((id)objc_getClass("NSBitmapImageRep")), func, planes, width, height, bps, spp, alpha, isPlanar, NSString_stringWithUTF8String(colorSpaceName), bitmapFormat, rowBytes, pixelBits); + } + + NSColor* NSColor_colorWithSRGB(CGFloat red, CGFloat green, CGFloat blue, CGFloat alpha) { + void* nsclass = objc_getClass("NSColor"); + void* func = sel_registerName("colorWithSRGBRed:green:blue:alpha:"); + return ((id(*)(id, SEL, CGFloat, CGFloat, CGFloat, CGFloat))objc_msgSend) + (nsclass, func, red, green, blue, alpha); + } + + NSCursor* NSCursor_initWithImage(NSImage* newImage, NSPoint aPoint) { + void* func = sel_registerName("initWithImage:hotSpot:"); + void* nsclass = objc_getClass("NSCursor"); + + return (NSCursor*) ((id(*)(id, SEL, id, NSPoint))objc_msgSend) + (NSAlloc(nsclass), func, newImage, aPoint); + } + + void NSImage_addRepresentation(NSImage* image, NSImageRep* imageRep) { + void* func = sel_registerName("addRepresentation:"); + objc_msgSend_void_id(image, func, imageRep); + } + + NSImage* NSImage_initWithSize(NSSize size) { + void* func = sel_registerName("initWithSize:"); + return ((id(*)(id, SEL, NSSize))objc_msgSend) + (NSAlloc((id)objc_getClass("NSImage")), func, size); + } +#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 */ + 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) */ + NSOpenGLContextParameterGPUFragmentProcessing NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 311, /* 1 param. Currently processing fragments with GPU (get) */ + NSOpenGLContextParameterHasDrawable NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 314, /* 1 param. Boolean returned if drawable is attached */ + NSOpenGLContextParameterMPSwapsInFlight NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 315, /* 1 param. Max number of swaps queued by the MP GL engine */ + + NSOpenGLContextParameterSwapRectangle API_DEPRECATED("", macos(10.0, 10.14)) = 200, /* 4 params. Set or get the swap rectangle {x, y, w, h} */ + 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 */ + }; + + + void NSOpenGLContext_setValues(NSOpenGLContext* context, const int* vals, NSOpenGLContextParameter param) { + void* func = sel_registerName("setValues:forParameter:"); + ((void (*)(id, SEL, const int*, NSOpenGLContextParameter))objc_msgSend) + (context, func, vals, param); + } + + void* NSOpenGLPixelFormat_initWithAttributes(const uint32_t* attribs) { + void* func = sel_registerName("initWithAttributes:"); + return (void*) ((id(*)(id, SEL, const uint32_t*))objc_msgSend) + (NSAlloc((id)objc_getClass("NSOpenGLPixelFormat")), func, attribs); + } + + NSOpenGLView* NSOpenGLView_initWithFrame(NSRect frameRect, uint32_t* format) { + void* func = sel_registerName("initWithFrame:pixelFormat:"); + return (NSOpenGLView*) ((id(*)(id, SEL, NSRect, uint32_t*))objc_msgSend) + (NSAlloc((id)objc_getClass("NSOpenGLView")), func, frameRect, format); + } + + void NSCursor_performSelector(NSCursor* cursor, void* selector) { + void* func = sel_registerName("performSelector:"); + objc_msgSend_void_SEL(cursor, func, selector); + } + + NSPasteboard* NSPasteboard_generalPasteboard(void) { + return (NSPasteboard*) objc_msgSend_id((id)objc_getClass("NSPasteboard"), sel_registerName("generalPasteboard")); + } + + NSString** cstrToNSStringArray(char** strs, size_t len) { + static NSString* nstrs[6]; + size_t i; + for (i = 0; i < len; i++) + nstrs[i] = NSString_stringWithUTF8String(strs[i]); + + return nstrs; + } + + const char* NSPasteboard_stringForType(NSPasteboard* pasteboard, NSPasteboardType dataType) { + void* func = sel_registerName("stringForType:"); + return (const char*) NSString_to_char(((id(*)(id, SEL, const char*))objc_msgSend)(pasteboard, func, NSString_stringWithUTF8String(dataType))); + } + + NSArray* c_array_to_NSArray(void* array, size_t len) { + SEL func = sel_registerName("initWithObjects:count:"); + void* nsclass = objc_getClass("NSArray"); + return ((id (*)(id, SEL, void*, NSUInteger))objc_msgSend) + (NSAlloc(nsclass), func, array, len); + } + + void NSregisterForDraggedTypes(void* view, NSPasteboardType* newTypes, size_t len) { + NSString** ntypes = cstrToNSStringArray((char**)newTypes, len); + + NSArray* array = c_array_to_NSArray(ntypes, len); + objc_msgSend_void_id(view, sel_registerName("registerForDraggedTypes:"), array); + NSRelease(array); + } + + NSInteger NSPasteBoard_declareTypes(NSPasteboard* pasteboard, NSPasteboardType* newTypes, size_t len, void* owner) { + NSString** ntypes = cstrToNSStringArray((char**)newTypes, len); + + void* func = sel_registerName("declareTypes:owner:"); + + NSArray* array = c_array_to_NSArray(ntypes, len); + + NSInteger output = ((NSInteger(*)(id, SEL, id, void*))objc_msgSend) + (pasteboard, func, array, owner); + NSRelease(array); + + return output; + } + + bool NSPasteBoard_setString(NSPasteboard* pasteboard, const char* stringToWrite, NSPasteboardType dataType) { + void* func = sel_registerName("setString:forType:"); + return ((bool (*)(id, SEL, id, NSPasteboardType))objc_msgSend) + (pasteboard, func, NSString_stringWithUTF8String(stringToWrite), NSString_stringWithUTF8String(dataType)); + } + + void NSRetain(id obj) { objc_msgSend_void(obj, sel_registerName("retain")); } + + typedef enum NSApplicationActivationPolicy { + NSApplicationActivationPolicyRegular, + NSApplicationActivationPolicyAccessory, + NSApplicationActivationPolicyProhibited + } NSApplicationActivationPolicy; + + typedef NS_ENUM(u32, NSBackingStoreType) { + NSBackingStoreRetained = 0, + NSBackingStoreNonretained = 1, + NSBackingStoreBuffered = 2 + }; + + typedef NS_ENUM(u32, NSWindowStyleMask) { + NSWindowStyleMaskBorderless = 0, + NSWindowStyleMaskTitled = 1 << 0, + NSWindowStyleMaskClosable = 1 << 1, + NSWindowStyleMaskMiniaturizable = 1 << 2, + NSWindowStyleMaskResizable = 1 << 3, + NSWindowStyleMaskTexturedBackground = 1 << 8, /* deprecated */ + NSWindowStyleMaskUnifiedTitleAndToolbar = 1 << 12, + NSWindowStyleMaskFullScreen = 1 << 14, + NSWindowStyleMaskFullSizeContentView = 1 << 15, + NSWindowStyleMaskUtilityWindow = 1 << 4, + NSWindowStyleMaskDocModalWindow = 1 << 6, + NSWindowStyleMaskNonactivatingPanel = 1 << 7, + NSWindowStyleMaskHUDWindow = 1 << 13 + }; + + typedef const char* NSPasteboardType; + NSPasteboardType const NSPasteboardTypeString = "public.utf8-plain-text"; // Replaces NSStringPboardType + + + + typedef NS_ENUM(i32, NSDragOperation) { + NSDragOperationNone = 0, + NSDragOperationCopy = 1, + NSDragOperationLink = 2, + NSDragOperationGeneric = 4, + NSDragOperationPrivate = 8, + NSDragOperationMove = 16, + NSDragOperationDelete = 32, + NSDragOperationEvery = ULONG_MAX, + + //NSDragOperationAll_Obsolete API_DEPRECATED("", macos(10.0,10.10)) = 15, // Use NSDragOperationEvery + //NSDragOperationAll API_DEPRECATED("", macos(10.0,10.10)) = NSDragOperationAll_Obsolete, // Use NSDragOperationEvery + }; + + void* NSArray_objectAtIndex(NSArray* array, NSUInteger index) { + void* func = sel_registerName("objectAtIndex:"); + return ((id(*)(id, SEL, NSUInteger))objc_msgSend)(array, func, index); + } + + const char** NSPasteboard_readObjectsForClasses(NSPasteboard* pasteboard, Class* classArray, size_t len, void* options) { + void* func = sel_registerName("readObjectsForClasses:options:"); + + NSArray* array = c_array_to_NSArray(classArray, len); + + NSArray* output = (NSArray*) ((id(*)(id, SEL, id, void*))objc_msgSend) + (pasteboard, func, array, options); + + NSRelease(array); + NSUInteger count = ((NSUInteger(*)(id, SEL))objc_msgSend)(output, sel_registerName("count")); + + const char** res = si_array_init_reserve(sizeof(const char*), count); + + void* path_func = sel_registerName("path"); + + for (NSUInteger i = 0; i < count; i++) { + void* url = NSArray_objectAtIndex(output, i); + NSString* url_str = ((id(*)(id, SEL))objc_msgSend)(url, path_func); + res[i] = NSString_to_char(url_str); + } + + return res; + } + + void* NSWindow_contentView(NSWindow* window) { + void* func = sel_registerName("contentView"); + return objc_msgSend_id(window, func); + } + + /* + End of cocoa wrapper + */ + + char* RGFW_mouseIconSrc[] = {"arrowCursor", "arrowCursor", "IBeamCursor", "crosshairCursor", "pointingHandCursor", "resizeLeftRightCursor", "resizeUpDownCursor", "_windowResizeNorthWestSouthEastCursor", "_windowResizeNorthEastSouthWestCursor", "closedHandCursor", "operationNotAllowedCursor"}; void* RGFWnsglFramework = NULL; @@ -5362,20 +5475,18 @@ static HMODULE wglinstance = NULL; return kCVReturnSuccess; } - RGFW_window* RGFW_windows[10]; - u32 RGFW_windows_size = 0; - id NSWindow_delegate(RGFW_window* win) { return (id) objc_msgSend_id(win->src.window, sel_registerName("delegate")); } u32 RGFW_OnClose(void* self) { - u32 i; - for (i = 0; i < RGFW_windows_size; i++) - if (RGFW_windows[i] && NSWindow_delegate(RGFW_windows[i]) == self) { - RGFW_windows[i]->event.type = RGFW_quit; - return true; - } + RGFW_window* win = NULL; + object_getInstanceVariable(self, "RGFW_window", (void*)&win); + if (win == NULL) + return true; + + win->event.type = RGFW_quit; + RGFW_windowQuitCallback(win); return true; } @@ -5386,13 +5497,44 @@ static HMODULE wglinstance = NULL; 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) { - RGFW_UNUSED(sender); RGFW_UNUSED(self); RGFW_UNUSED(sel); + RGFW_UNUSED(sel); + + RGFW_window* win = NULL; + object_getInstanceVariable(self, "RGFW_window", (void*)&win); + if (win == NULL) + return true; + + if (!(win->src.winArgs & RGFW_ALLOW_DND)) { + return false; + } + + win->event.type = RGFW_dnd_init; + 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)); + RGFW_dndInitCallback(win, win->event.point); + return NSDragOperationCopy; } - bool prepareForDragOperation(void) { return true; } + bool prepareForDragOperation(id self) { + RGFW_window* win = NULL; + object_getInstanceVariable(self, "RGFW_window", (void*)&win); + if (win == NULL) + return true; + + if (!(win->src.winArgs & RGFW_ALLOW_DND)) { + return false; + } + + return true; + } void RGFW__osxDraggingEnded(id self, SEL sel, id sender) { RGFW_UNUSED(sender); RGFW_UNUSED(self); RGFW_UNUSED(sel); return; } @@ -5400,16 +5542,15 @@ static HMODULE wglinstance = NULL; bool performDragOperation(id self, SEL sel, id sender) { RGFW_UNUSED(sender); RGFW_UNUSED(self); RGFW_UNUSED(sel); - NSWindow* window = objc_msgSend_id(sender, sel_registerName("draggingDestinationWindow")); + 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; - for (i = 0; i < RGFW_windows_size; i++) - if (RGFW_windows[i]->src.window == window) { - found = 1; - break; - } - if (!found) i = 0; @@ -5418,20 +5559,23 @@ static HMODULE wglinstance = NULL; char** droppedFiles = (char**) NSPasteboard_readObjectsForClasses(pasteBoard, array, 1, NULL); - RGFW_windows[i]->event.droppedFilesCount = si_array_len(droppedFiles); + win->event.droppedFilesCount = si_array_len(droppedFiles); u32 y; - for (y = 0; y < RGFW_windows[i]->event.droppedFilesCount; y++) - strcpy(RGFW_windows[i]->event.droppedFiles[y], droppedFiles[y]); + for (y = 0; y < win->event.droppedFilesCount; y++) { + strncpy(win->event.droppedFiles[y], droppedFiles[y], RGFW_MAX_PATH); - RGFW_windows[i]->event.type = RGFW_dnd; - RGFW_windows[i]->src.dndPassed = 0; + win->event.droppedFiles[y][RGFW_MAX_PATH - 1] = '\0'; + } + + 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)); - RGFW_windows[i]->event.point.x = (i32)p.x; - RGFW_windows[i]->event.point.x = (i32)p.y; + RGFW_dndCallback(win, win->event.droppedFiles, win->event.droppedFilesCount); return true; } @@ -5468,41 +5612,62 @@ static HMODULE wglinstance = NULL; NSSize RGFW__osxWindowResize(void* self, SEL sel, NSSize frameSize) { RGFW_UNUSED(sel); - u32 i; - for (i = 0; i < RGFW_windows_size; i++) { - if (RGFW_windows[i] && NSWindow_delegate(RGFW_windows[i]) == self) { - RGFW_windows[i]->r.w = frameSize.width; - RGFW_windows[i]->r.h = frameSize.height; - RGFW_windows[i]->event.type = RGFW_windowResized; - - return frameSize; - } - } - + RGFW_window* win = NULL; + object_getInstanceVariable(self, "RGFW_window", (void*)&win); + if (win == NULL) + return frameSize; + + win->r.w = frameSize.width; + win->r.h = frameSize.height; + win->event.type = RGFW_windowResized; + RGFW_windowResizeCallback(win, win->r); return frameSize; } void RGFW__osxWindowMove(void* self, SEL sel) { RGFW_UNUSED(sel); - u32 i; - for (i = 0; i < RGFW_windows_size; i++) { - if (RGFW_windows[i] && NSWindow_delegate(RGFW_windows[i]) == self) { - NSRect frame = ((NSRect(*)(id, SEL))abi_objc_msgSend_stret)(RGFW_windows[i]->src.window, sel_registerName("frame")); - RGFW_windows[i]->r.x = (i32) frame.origin.x; - RGFW_windows[i]->r.y = (i32) frame.origin.y; + RGFW_window* win = NULL; + object_getInstanceVariable(self, "RGFW_window", (void*)&win); + if (win == NULL) + return; + + NSRect frame = ((NSRect(*)(id, SEL))abi_objc_msgSend_stret)(win->src.window, sel_registerName("frame")); + win->r.x = (i32) frame.origin.x; + win->r.y = (i32) frame.origin.y; - RGFW_windows[i]->event.type = RGFW_windowMoved; - return; - } - } + win->event.type = RGFW_windowMoved; + RGFW_windowMoveCallback(win, win->r); } - #ifdef __cplusplus - #define APPKIT_EXTERN extern "C" - #else - #define APPKIT_EXTERN extern - #endif + void RGFW__osxUpdateLayer(void* self, SEL sel) { + RGFW_UNUSED(sel); + + RGFW_window* win = NULL; + object_getInstanceVariable(self, "RGFW_window", (void*)&win); + if (win == NULL) + return; + + win->event.type = RGFW_windowRefresh; + RGFW_windowRefreshCallback(win); + } + + 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.rSurf = OSMesaCreateContext(OSMESA_RGBA, NULL); + OSMesaMakeCurrent(win->src.rSurf, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h); + #endif + #else + RGFW_UNUSED(win); /* if buffer rendering is not being used */ + #endif + } NSPasteboardType const NSPasteboardTypeURL = "public.url"; NSPasteboardType const NSPasteboardTypeFileURL = "public.file-url"; @@ -5527,6 +5692,8 @@ static HMODULE wglinstance = NULL; } RGFW_window* win = RGFW_window_basic_init(rect, args); + + RGFW_window_setMouseDefault(win); NSRect windowRect; windowRect.origin.x = win->r.x; @@ -5554,6 +5721,7 @@ static HMODULE wglinstance = NULL; objc_msgSend_void_id(win->src.window, sel_registerName("setTitle:"), str); #ifdef RGFW_OPENGL + if ((args & RGFW_NO_INIT_API) == 0) { void* attrs = RGFW_initAttribs(args & RGFW_OPENGL_SOFTWARE); void* format = NSOpenGLPixelFormat_initWithAttributes(attrs); @@ -5568,17 +5736,17 @@ static HMODULE wglinstance = NULL; printf("Switching to software rendering\n"); } - win->src.view = NSOpenGLView_initWithFrame(NSMakeRect(0, 0, win->r.w, win->r.h), format); + 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")); - -#else - NSRect contentRect = NSMakeRect(0, 0, win->r.w, win->r.h); + } else +#endif + { + NSRect contentRect = (NSRect){{0, 0}, {win->r.w, win->r.h}}; win->src.view = ((id(*)(id, SEL, NSRect))objc_msgSend) (NSAlloc((id)objc_getClass("NSView")), sel_registerName("initWithFrame:"), contentRect); -#endif - + } void* contentView = NSWindow_contentView(win->src.window); objc_msgSend_void_bool(contentView, sel_registerName("setWantsLayer:"), true); @@ -5586,21 +5754,22 @@ static HMODULE wglinstance = NULL; objc_msgSend_void_id(win->src.window, sel_registerName("setContentView:"), win->src.view); #ifdef RGFW_OPENGL - objc_msgSend_void(win->src.rSurf, sel_registerName("makeCurrentContext")); + if ((args & RGFW_NO_INIT_API) == 0) + objc_msgSend_void(win->src.rSurf, sel_registerName("makeCurrentContext")); #endif if (args & RGFW_TRANSPARENT_WINDOW) { #ifdef RGFW_OPENGL + if ((args & RGFW_NO_INIT_API) == 0) { i32 opacity = 0; - NSOpenGLContext_setValues(win->src.rSurf, &opacity, 304); + #define NSOpenGLCPSurfaceOpacity 236 + NSOpenGLContext_setValues(win->src.rSurf, &opacity, NSOpenGLCPSurfaceOpacity); + } #endif objc_msgSend_void_bool(win->src.window, sel_registerName("setOpaque:"), false); objc_msgSend_void_id(win->src.window, sel_registerName("setBackgroundColor:"), NSColor_colorWithSRGB(0, 0, 0, 0)); - - ((void (*)(id, SEL, CGFloat))objc_msgSend) - (win->src.window, sel_registerName("setAlphaValue:"), 0x00); } win->src.display = CGMainDisplayID(); @@ -5610,12 +5779,10 @@ static HMODULE wglinstance = NULL; RGFW_init_buffer(win); -#ifdef RGFW_VULKAN - RGFW_initVulkan(win); -#endif - + #ifndef RGFW_NO_MONITOR if (args & RGFW_SCALE_TO_MONITOR) RGFW_window_scaleToMonitor(win); + #endif if (args & RGFW_HIDE_MOUSE) RGFW_window_showMouse(win, 0); @@ -5624,9 +5791,15 @@ static HMODULE wglinstance = NULL; NSMoveToResourceDir(); Class delegateClass = objc_allocateClassPair(objc_getClass("NSObject"), "WindowDelegate", 0); - + + class_addIvar( + delegateClass, "RGFW_window", + sizeof(RGFW_window*), rint(log2(sizeof(RGFW_window*))), + "L" + ); class_addMethod(delegateClass, sel_registerName("windowWillResize:toSize:"), (IMP) RGFW__osxWindowResize, "{NSSize=ff}@:{NSSize=ff}"); + class_addMethod(delegateClass, sel_registerName("updateLayer:"), (IMP) RGFW__osxUpdateLayer, ""); class_addMethod(delegateClass, sel_registerName("windowWillMove:"), (IMP) RGFW__osxWindowMove, ""); class_addMethod(delegateClass, sel_registerName("windowDidMove:"), (IMP) RGFW__osxWindowMove, ""); class_addMethod(delegateClass, sel_registerName("draggingEntered:"), (IMP)draggingEntered, "l@:@"); @@ -5661,16 +5834,7 @@ static HMODULE wglinstance = NULL; objc_msgSend_void(win->src.window, sel_registerName("makeKeyWindow")); - NSApplication_finishLaunching(NSApp); - - RGFW_windows_size++; - - size_t i; - for (i = 0; i < RGFW_windows_size; i++) - if (!RGFW_windows[i]) { - RGFW_windows[i] = win; - break; - } + objc_msgSend_void(NSApp, sel_registerName("finishLaunching")); if (RGFW_root == NULL) RGFW_root = win; @@ -5681,6 +5845,19 @@ static HMODULE wglinstance = NULL; return win; } + void RGFW_window_setBorder(RGFW_window* win, u8 border) { + NSBackingStoreType storeType = NSWindowStyleMaskBorderless; + if (!border) { + storeType = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable; + } + if (!(win->src.winArgs & RGFW_NO_RESIZE)) { + storeType |= NSWindowStyleMaskResizable; + } + + ((void (*)(id, SEL, NSBackingStoreType))objc_msgSend)(win->src.window, sel_registerName("setStyleMask:"), storeType); + + objc_msgSend_void_bool(win->src.window, sel_registerName("setHasShadow:"), border); + } RGFW_area RGFW_getScreenSize(void) { static CGDirectDisplayID display = 0; @@ -5704,7 +5881,7 @@ static HMODULE wglinstance = NULL; RGFW_vector 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) (p.y)); + return RGFW_VECTOR((u32) p.x, (u32) (win->r.h - p.y)); } u32 RGFW_keysPressed[10]; /*10 keys at a time*/ @@ -5798,16 +5975,17 @@ static HMODULE wglinstance = NULL; NSEventModifierFlagShift = 1 << 17, NSEventModifierFlagControl = 1 << 18, NSEventModifierFlagOption = 1 << 19, - NSEventModifierFlagCommand = 1 << 20 + NSEventModifierFlagCommand = 1 << 20, + NSEventModifierFlagNumericPad = 1 << 21 } NSEventModifierFlags; RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) { assert(win != NULL); - + if (win->event.type == RGFW_quit) - return &win->event; + return NULL; - if (win->event.type == RGFW_dnd && win->src.dndPassed == 0) { + if ((win->event.type == RGFW_dnd || win->event.type == RGFW_dnd_init) && win->src.dndPassed == 0) { win->src.dndPassed = 1; return &win->event; } @@ -5816,7 +5994,7 @@ static HMODULE wglinstance = NULL; if (eventFunc == NULL) eventFunc = sel_registerName("nextEventMatchingMask:untilDate:inMode:dequeue:"); - if ((win->event.type == RGFW_windowMoved || win->event.type == RGFW_windowResized) && win->event.keyCode != 120) { + if ((win->event.type == RGFW_windowMoved || win->event.type == RGFW_windowResized || win->event.type == RGFW_windowRefresh) && win->event.keyCode != 120) { win->event.keyCode = 120; return &win->event; } @@ -5824,7 +6002,6 @@ static HMODULE wglinstance = NULL; NSEvent* e = (NSEvent*) ((id(*)(id, SEL, NSEventMask, void*, NSString*, bool))objc_msgSend) (NSApp, eventFunc, ULONG_MAX, NULL, NSString_stringWithUTF8String("kCFRunLoopDefaultMode"), true); - if (e == NULL) return NULL; @@ -5844,29 +6021,32 @@ static HMODULE wglinstance = NULL; win->event.droppedFilesCount = 0; win->event.type = 0; - bool isKey = (bool) objc_msgSend_bool(win->src.window, sel_registerName("isKeyWindow")); - - if (win->event.inFocus != isKey) { - win->event.inFocus = isKey; - - if (win->event.inFocus) - win->event.type = RGFW_focusIn; - else - win->event.type = RGFW_focusOut; - - return &win->event; - } - 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)); + RGFW_mouseNotifyCallBack(win, win->event.point, 1); + break; + } + + case NSEventTypeMouseExited: + win->event.type = RGFW_mouseLeave; + RGFW_mouseNotifyCallBack(win, win->event.point, 0); + break; + case NSEventTypeKeyDown: { u32 key = (u16) objc_msgSend_uint(e, sel_registerName("keyCode")); win->event.keyCode = RGFW_apiKeyCodeToRGFW(key); - RGFW_keyboard_prev[win->event.keyCode] = RGFW_keyboard[win->event.keyCode]; + RGFW_keyboard[win->event.keyCode].prev = RGFW_keyboard[win->event.keyCode].current; win->event.type = RGFW_keyPressed; - win->event.keyName = (char*)(const char*) NSString_to_char(objc_msgSend_id(e, sel_registerName("characters"))); + char* str = (char*)(const char*) NSString_to_char(objc_msgSend_id(e, sel_registerName("characters"))); + strncpy(win->event.keyName, str, 16); + RGFW_keyboard[win->event.keyCode].current = 1; - RGFW_keyboard[win->event.keyCode] = 1; + RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, 1); break; } @@ -5874,86 +6054,53 @@ static HMODULE wglinstance = NULL; u32 key = (u16) objc_msgSend_uint(e, sel_registerName("keyCode")); win->event.keyCode = RGFW_apiKeyCodeToRGFW(key);; - RGFW_keyboard_prev[win->event.keyCode] = RGFW_keyboard[win->event.keyCode]; + RGFW_keyboard[win->event.keyCode].prev = RGFW_keyboard[win->event.keyCode].current; win->event.type = RGFW_keyReleased; - win->event.keyName = (char*)(const char*) NSString_to_char(objc_msgSend_id(e, sel_registerName("characters"))); + char* str = (char*)(const char*) NSString_to_char(objc_msgSend_id(e, sel_registerName("characters"))); + strncpy(win->event.keyName, str, 16); - RGFW_keyboard[win->event.keyCode] = 0; + RGFW_keyboard[win->event.keyCode].current = 0; + RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, 0); break; } case NSEventTypeFlagsChanged: { u32 flags = objc_msgSend_uint(e, sel_registerName("modifierFlags")); - memcpy(RGFW_keyboard_prev + RGFW_CapsLock, RGFW_keyboard + RGFW_CapsLock, 9); + RGFW_updateLockState(win, ((u32)(flags & NSEventModifierFlagCapsLock) % 255), ((flags & NSEventModifierFlagNumericPad) % 255)); + + u8 i; + for (i = 0; i < 9; i++) + RGFW_keyboard[i + RGFW_CapsLock].prev = 0; + + for (i = 0; i < 5; i++) { + u32 shift = (1 << (i + 16)); + u32 key = i + RGFW_CapsLock; - if ((flags & NSEventModifierFlagCapsLock) && !RGFW_wasPressedI(win, RGFW_CapsLock)) { - RGFW_keyboard[RGFW_CapsLock] = 1; - win->event.type = RGFW_keyPressed; - win->event.keyCode = RGFW_apiKeyCodeToRGFW(57); - break; - } if (!(flags & NSEventModifierFlagCapsLock) && RGFW_wasPressedI(win, RGFW_CapsLock)) { - RGFW_keyboard[RGFW_CapsLock] = 0; - win->event.type = RGFW_keyReleased; - win->event.keyCode = RGFW_apiKeyCodeToRGFW(57); - break; + if ((flags & shift) && !RGFW_wasPressed(win, key)) { + RGFW_keyboard[key].current = 1; + + if (key != RGFW_CapsLock) + RGFW_keyboard[key+ 4].current = 1; + + win->event.type = RGFW_keyPressed; + win->event.keyCode = key; + break; + } + + if (!(flags & shift) && RGFW_wasPressed(win, key)) { + RGFW_keyboard[key].current = 0; + + if (key != RGFW_CapsLock) + RGFW_keyboard[key + 4].current = 0; + + win->event.type = RGFW_keyReleased; + win->event.keyCode = key; + break; + } } - if ((flags & NSEventModifierFlagOption) && !RGFW_wasPressedI(win, RGFW_AltL)) { - RGFW_keyboard[RGFW_AltL] = 1; - RGFW_keyboard[RGFW_AltR] = 1; - win->event.type = RGFW_keyPressed; - win->event.keyCode = RGFW_apiKeyCodeToRGFW(58); - break; - } if (!(flags & NSEventModifierFlagOption) && RGFW_wasPressedI(win, RGFW_AltL)) { - RGFW_keyboard[RGFW_AltL] = 0; - RGFW_keyboard[RGFW_AltR] = 0; - win->event.type = RGFW_keyReleased; - win->event.keyCode = RGFW_apiKeyCodeToRGFW(58); - break; - } - - if ((flags & NSEventModifierFlagControl) && !RGFW_wasPressedI(win, RGFW_ControlL)) { - RGFW_keyboard[RGFW_ControlL] = 1; - RGFW_keyboard[RGFW_ControlR] = 1; - win->event.type = RGFW_keyPressed; - win->event.keyCode = RGFW_apiKeyCodeToRGFW(59); - break; - } if (!(flags & NSEventModifierFlagControl) && RGFW_wasPressedI(win, RGFW_ControlL)) { - RGFW_keyboard[RGFW_ControlL] = 0; - RGFW_keyboard[RGFW_ControlR] = 0; - win->event.type = RGFW_keyReleased; - win->event.keyCode = 59; - break; - } - - if ((flags & NSEventModifierFlagCommand) && !RGFW_wasPressedI(win, RGFW_SuperL)) { - RGFW_keyboard[RGFW_SuperL] = 1; - RGFW_keyboard[RGFW_SuperR] = 1; - win->event.type = RGFW_keyPressed; - win->event.keyCode = RGFW_apiKeyCodeToRGFW(55); - break; - } if (!(flags & NSEventModifierFlagCommand) && RGFW_wasPressedI(win, RGFW_SuperL)) { - RGFW_keyboard[RGFW_SuperL] = 0; - RGFW_keyboard[RGFW_SuperR] = 0; - win->event.type = RGFW_keyReleased; - win->event.keyCode = RGFW_apiKeyCodeToRGFW(55); - break; - } - - if ((flags & NSEventModifierFlagShift) && !RGFW_wasPressedI(win, RGFW_ShiftL)) { - RGFW_keyboard[RGFW_ShiftL] = 1; - RGFW_keyboard[RGFW_ShiftR] = 1; - win->event.type = RGFW_keyPressed; - win->event.keyCode = RGFW_apiKeyCodeToRGFW(56); - break; - } if (!(flags & NSEventModifierFlagShift) && RGFW_wasPressedI(win, RGFW_ShiftL)) { - RGFW_keyboard[RGFW_ShiftL] = 0; - RGFW_keyboard[RGFW_ShiftR] = 0; - win->event.type = RGFW_keyReleased; - win->event.keyCode = RGFW_apiKeyCodeToRGFW(56); - break; - } + RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, win->event.type == RGFW_keyPressed); break; } @@ -5963,8 +6110,18 @@ static HMODULE wglinstance = NULL; 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)); + + if ((win->src.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)); + } + + RGFW_mousePosCallback(win, win->event.point); break; case NSEventTypeLeftMouseDown: @@ -5972,6 +6129,7 @@ static HMODULE wglinstance = NULL; win->event.type = RGFW_mouseButtonPressed; RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button]; RGFW_mouseButtons[win->event.button] = 1; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); break; case NSEventTypeOtherMouseDown: @@ -5979,6 +6137,7 @@ static HMODULE wglinstance = NULL; win->event.type = RGFW_mouseButtonPressed; RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button]; RGFW_mouseButtons[win->event.button] = 1; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); break; case NSEventTypeRightMouseDown: @@ -5986,6 +6145,7 @@ static HMODULE wglinstance = NULL; win->event.type = RGFW_mouseButtonPressed; RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button]; RGFW_mouseButtons[win->event.button] = 1; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); break; case NSEventTypeLeftMouseUp: @@ -5993,6 +6153,7 @@ static HMODULE wglinstance = NULL; win->event.type = RGFW_mouseButtonReleased; RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button]; RGFW_mouseButtons[win->event.button] = 0; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0); break; case NSEventTypeOtherMouseUp: @@ -6000,6 +6161,15 @@ static HMODULE wglinstance = NULL; RGFW_mouseButtons_prev[win->event.button] = RGFW_mouseButtons[win->event.button]; RGFW_mouseButtons[win->event.button] = 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; + win->event.type = RGFW_mouseButtonReleased; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0); break; case NSEventTypeScrollWheel: { @@ -6017,15 +6187,10 @@ static HMODULE wglinstance = NULL; win->event.scroll = deltaY; - win->event.type = RGFW_mouseButtonReleased; + win->event.type = RGFW_mouseButtonPressed; + RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1); 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; - win->event.type = RGFW_mouseButtonReleased; - break; default: break; @@ -6043,7 +6208,7 @@ static HMODULE wglinstance = NULL; win->r.x = v.x; win->r.y = v.y; ((void(*)(id, SEL, NSRect, bool, bool))objc_msgSend) - (win->src.window, sel_registerName("setFrame:display:animate:"), NSMakeRect(win->r.x, win->r.y, win->r.w, win->r.h), true, true); + (win->src.window, sel_registerName("setFrame:display:animate:"), (NSRect){{win->r.x, win->r.y}, {win->r.w, win->r.h}}, true, true); } void RGFW_window_resize(RGFW_window* win, RGFW_area a) { @@ -6052,7 +6217,7 @@ static HMODULE wglinstance = NULL; win->r.w = a.w; win->r.h = a.h; ((void(*)(id, SEL, NSRect, bool, bool))objc_msgSend) - (win->src.window, sel_registerName("setFrame:display:animate:"), NSMakeRect(win->r.x, win->r.y, win->r.w, win->r.h), true, true); + (win->src.window, sel_registerName("setFrame:display:animate:"), (NSRect){{win->r.x, win->r.y}, {win->r.w, win->r.h}}, true, true); } void RGFW_window_minimize(RGFW_window* win) { @@ -6074,14 +6239,26 @@ static HMODULE wglinstance = NULL; objc_msgSend_void_id(win->src.window, sel_registerName("setTitle:"), str); } + #ifndef RGFW_NO_PASSTHROUGH + void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) { + objc_msgSend_void_bool(win->src.window, sel_registerName("setIgnoresMouseEvents:"), passthrough); + } + #endif + void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) { + if (a.w == 0 && a.h == 0) + return; + ((void (*)(id, SEL, NSSize))objc_msgSend) - (win->src.window, sel_registerName("setMinSize:"), NSMakeSize(a.w, a.h)); + (win->src.window, sel_registerName("setMinSize:"), (NSSize){a.w, a.h}); } void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) { + if (a.w == 0 && a.h == 0) + return; + ((void (*)(id, SEL, NSSize))objc_msgSend) - (win->src.window, sel_registerName("setMaxSize:"), NSMakeSize(a.w, a.h)); + (win->src.window, sel_registerName("setMaxSize:"), (NSSize){a.w, a.h}); } void RGFW_window_setIcon(RGFW_window* win, u8* data, RGFW_area area, i32 channels) { @@ -6093,7 +6270,7 @@ static HMODULE wglinstance = NULL; memcpy(NSBitmapImageRep_bitmapData(representation), data, area.w * area.h * channels); // Add ze representation. - void* dock_image = NSImage_initWithSize(NSMakeSize(area.w, area.h)); + void* dock_image = NSImage_initWithSize((NSSize){area.w, area.h}); NSImage_addRepresentation(dock_image, (void*) representation); // Finally, set the dock image to it. @@ -6123,11 +6300,11 @@ static HMODULE wglinstance = NULL; memcpy(NSBitmapImageRep_bitmapData(representation), image, a.w * a.h * channels); // Add ze representation. - void* cursor_image = NSImage_initWithSize(NSMakeSize(a.w, a.h)); + void* cursor_image = NSImage_initWithSize((NSSize){a.w, a.h}); NSImage_addRepresentation(cursor_image, representation); // Finally, set the cursor image. - void* cursor = NSCursor_initWithImage(cursor_image, NSMakePoint(0, 0)); + void* cursor = NSCursor_initWithImage(cursor_image, (NSPoint){0.0, 0.0}); objc_msgSend_void(cursor, sel_registerName("set")); @@ -6166,11 +6343,15 @@ static HMODULE wglinstance = NULL; objc_msgSend_void(mouse, sel_registerName("set")); } + void RGFW_clipCursor(RGFW_rect r) { + 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) { RGFW_UNUSED(win); - assert(win != NULL); - CGWarpMouseCursorPosition(CGPointMake(v.x, v.y)); + CGWarpMouseCursorPosition(CGPointMake(v.x, v.y)); } @@ -6252,19 +6433,23 @@ static HMODULE wglinstance = NULL; return RGFW_NSCreateMonitor(win->src.display); } -#ifdef __cplusplus -#define APPKIT_EXTERN extern "C" -#else -#define APPKIT_EXTERN extern -#endif - char* RGFW_readClipboard(size_t* size) { char* clip = (char*)NSPasteboard_stringForType(NSPasteboard_generalPasteboard(), NSPasteboardTypeString); - size_t clip_len = strlen(clip); + + size_t clip_len = 1; + + if (clip != NULL) { + clip_len = strlen(clip) + 1; + } char* str = (char*)RGFW_MALLOC(sizeof(char) * clip_len); - strcpy(str, clip); + + if (clip != NULL) { + strncpy(str, clip, clip_len); + } + str[clip_len] = '\0'; + if (size != NULL) *size = clip_len; return str; @@ -6295,24 +6480,73 @@ static HMODULE wglinstance = NULL; return win->src.joystickCount - 1; } - void RGFW_window_close(RGFW_window* win) { + #ifdef RGFW_OPENGL + void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) { + assert(win != NULL); + objc_msgSend_void(win->src.rSurf, sel_registerName("makeCurrentContext")); + } + #endif + + #if !defined(RGFW_EGL) + void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) { + assert(win != NULL); + #if defined(RGFW_OPENGL) + + NSOpenGLContext_setValues(win->src.rSurf, &swapInterval, 222); + #endif + + win->fpsCap = (swapInterval == 1) ? 0 : swapInterval; + } + #endif + + void RGFW_window_swapBuffers(RGFW_window* win) { assert(win != NULL); -#ifdef RGFW_VULKAN - for (int i = 0; i < win->src.image_count; i++) { - vkDestroyFramebuffer(RGFW_vulkan_info.device, RGFW_vulkan_info.framebuffers[i], NULL); - } + RGFW_window_makeCurrent(win); - for (int i = 0; i < win->src.image_count; i++) { - vkDestroyImageView(RGFW_vulkan_info.device, win->src.swapchain_image_views[i], NULL); - } + /* clear the window*/ - vkDestroySwapchainKHR(RGFW_vulkan_info.device, win->src.swapchain, NULL); - vkDestroySurfaceKHR(RGFW_vulkan_info.instance, win->src.rSurf, NULL); - RGFW_FREE(win->src.swapchain_image_views); - RGFW_FREE(win->src.swapchain_images); + if (!(win->src.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")); + + ((void(*)(id, SEL, NSRect))objc_msgSend)(layer, + 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); #endif + } + if (!(win->src.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")); + #endif + } + + RGFW_window_checkFPS(win); + } + + void RGFW_window_close(RGFW_window* win) { + assert(win != NULL); release(win->src.view); #ifdef RGFW_ALLOC_DROPFILES @@ -6326,16 +6560,7 @@ static HMODULE wglinstance = NULL; } #endif - u32 i; - for (i = 0; i < RGFW_windows_size; i++) - if (RGFW_windows[i]->src.window == win->src.window) { - RGFW_windows[i] = NULL; - break; - } - - if (!i) { - RGFW_windows_size = 0; - + if (RGFW_root == win) { objc_msgSend_void_id(NSApp, sel_registerName("terminate:"), (id) win->src.window); NSApp = NULL; } @@ -6350,10 +6575,31 @@ static HMODULE wglinstance = NULL; RGFW_FREE(win); } -#endif + u64 RGFW_getTimeNS(void) { + static mach_timebase_info_data_t timebase_info; + if (timebase_info.denom == 0) { + mach_timebase_info(&timebase_info); + } + return mach_absolute_time() * timebase_info.numer / timebase_info.denom; + } + + u64 RGFW_getTime(void) { + static mach_timebase_info_data_t timebase_info; + if (timebase_info.denom == 0) { + mach_timebase_info(&timebase_info); + } + return (double) mach_absolute_time() * (double) timebase_info.numer / ((double) timebase_info.denom * 1e9); + } +#endif /* RGFW_MACOS */ + +/* + End of MaOS defines +*/ + +/* unix (macOS, linux) only stuff */ #if defined(RGFW_X11) || defined(RGFW_MACOS) - +/* unix threading */ #ifndef RGFW_NO_THREADS #include @@ -6370,340 +6616,16 @@ static HMODULE wglinstance = NULL; void RGFW_setThreadPriority(RGFW_thread thread, u8 priority) { pthread_setschedprio(thread, priority); } #endif #endif -#endif - - void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) { - assert(win != NULL); - -#ifdef RGFW_OPENGL -#ifdef RGFW_X11 - glXMakeCurrent((Display*) win->src.display, (Drawable) win->src.window, (GLXContext) win->src.rSurf); -#endif -#ifdef RGFW_WINDOWS - wglMakeCurrent(win->src.hdc, (HGLRC) win->src.rSurf); -#endif -#if defined(RGFW_MACOS) - objc_msgSend_void(win->src.rSurf, sel_registerName("makeCurrentContext")); -#endif -#else -#ifdef RGFW_EGL - eglMakeCurrent(win->src.EGL_display, win->src.EGL_surface, win->src.EGL_surface, win->src.EGL_context); -#endif -#endif - - } - - 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); -#endif - -#ifdef RGFW_OPENGL - RGFW_window_makeCurrent_OpenGL(win); -#endif - } - - void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) { - assert(win != NULL); - -#ifdef RGFW_OPENGL -#ifdef RGFW_X11 - ((PFNGLXSWAPINTERVALEXTPROC) glXGetProcAddress((GLubyte*) "glXSwapIntervalEXT"))((Display*) win->src.display, (Window) win->src.window, swapInterval); -#endif -#ifdef RGFW_WINDOWS - - typedef BOOL(APIENTRY* PFNWGLSWAPINTERVALEXTPROC)(int interval); - static PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = NULL; - static void* loadSwapFunc = (void*) 1; - - if (loadSwapFunc == NULL) { - fprintf(stderr, "wglSwapIntervalEXT not supported\n"); - win->fpsCap = (swapInterval == 1) ? 0 : swapInterval; - return; - } - - if (wglSwapIntervalEXT == NULL) { - loadSwapFunc = (void*) wglGetProcAddress("wglSwapIntervalEXT"); - wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC) loadSwapFunc; - } - - if (wglSwapIntervalEXT(swapInterval) == FALSE) - fprintf(stderr, "Failed to set swap interval\n"); - -#endif -#if defined(RGFW_MACOS) - NSOpenGLContext_setValues(win->src.rSurf, &swapInterval, 222); -#endif -#endif - -#ifdef RGFW_EGL - eglSwapInterval(win->src.EGL_display, swapInterval); -#endif - - win->fpsCap = (swapInterval == 1) ? 0 : swapInterval; - - } - - 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; - - else if (set && win->src.winArgs & RGFW_NO_GPU_RENDER) - win->src.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; - - else if (set && win->src.winArgs & RGFW_NO_CPU_RENDER) - win->src.winArgs ^= RGFW_NO_CPU_RENDER; - } - - - void RGFW_window_swapBuffers(RGFW_window* win) { - assert(win != NULL); - - RGFW_window_makeCurrent(win); - - /* clear the window*/ - - if (!(win->src.winArgs & RGFW_NO_CPU_RENDER)) { -#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) -#ifdef RGFW_OSMESA - u8* row = (u8*) RGFW_MALLOC(win->r.w * 3); - - i32 half_height = win->r.h / 2; - i32 stride = win->r.w * 3; - - i32 y; - for (y = 0; y < half_height; ++y) { - i32 top_offset = y * stride; - i32 bottom_offset = (win->r.h - y - 1) * stride; - memcpy(row, win->buffer + top_offset, stride); - memcpy(win->buffer + top_offset, win->buffer + bottom_offset, stride); - memcpy(win->buffer + bottom_offset, row, stride); - } - - RGFW_FREE(row); -#endif - -#ifdef RGFW_X11 - RGFW_area area = RGFW_getScreenSize(); - -#ifndef RGFW_X11_DONT_CONVERT_BGR - win->src.bitmap->data = (char*) win->buffer; - u32 x, y; - for (y = 0; y < (u32)win->r.h; y++) { - for (x = 0; x < (u32)win->r.w; x++) { - u32 index = (y * 4 * area.w) + x * 4; - - u8 red = win->src.bitmap->data[index]; - win->src.bitmap->data[index] = win->buffer[index + 2]; - win->src.bitmap->data[index + 2] = red; - } - } -#endif - - XPutImage(win->src.display, (Window) win->src.window, XDefaultGC(win->src.display, XDefaultScreen(win->src.display)), win->src.bitmap, 0, 0, 0, 0, win->r.w, win->r.h); -#endif -#ifdef RGFW_WINDOWS - HGDIOBJ oldbmp = SelectObject(win->src.hdcMem, win->src.bitmap); - BitBlt(win->src.hdc, 0, 0, win->r.w, win->r.h, win->src.hdcMem, 0, 0, SRCCOPY); - SelectObject(win->src.hdcMem, oldbmp); -#endif -#if defined(RGFW_MACOS) - RGFW_area area = RGFW_getScreenSize(); - void* view = NSWindow_contentView(win->src.window); - void* layer = objc_msgSend_id(view, sel_registerName("layer")); - - ((void(*)(id, SEL, NSRect))objc_msgSend)(layer, - sel_registerName("setFrame:"), - NSMakeRect(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); -#endif -#endif - -#ifdef RGFW_VULKAN -#ifdef RGFW_PRINT_ERRORS - fprintf(stderr, "RGFW_window_swapBuffers %s\n", "RGFW_window_swapBuffers is not yet supported for Vulkan"); - RGFW_error = 1; -#endif -#endif - } - - if (!(win->src.winArgs & RGFW_NO_GPU_RENDER)) { - #ifdef RGFW_EGL - eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface); - #elif defined(RGFW_OPENGL) - #if defined(RGFW_X11) && defined(RGFW_OPENGL) - glXSwapBuffers((Display*) win->src.display, (Window) win->src.window); - #elif defined(RGFW_WINDOWS) - SwapBuffers(win->src.hdc); - #elif defined(RGFW_MACOS) - NSOpenGLContext_flushBuffer(win->src.rSurf); - #endif - #endif - - #if defined(RGFW_WINDOWS) && defined(RGFW_DIRECTX) - win->src.swapchain->lpVtbl->Present(win->src.swapchain, 0, 0); - #endif - } - - RGFW_window_checkFPS(win); - } - - void RGFW_window_maximize(RGFW_window* win) { - assert(win != NULL); - - RGFW_area screen = RGFW_getScreenSize(); - - RGFW_window_move(win, RGFW_VECTOR(0, 0)); - RGFW_window_resize(win, screen); - } - - u8 RGFW_window_shouldClose(RGFW_window* win) { - assert(win != NULL); - - /* || RGFW_isPressedI(win, RGFW_Escape) */ - return (win->event.type == RGFW_quit || RGFW_isPressedI(win, RGFW_Escape)); - } - - void RGFW_window_setShouldClose(RGFW_window* win) { win->event.type = RGFW_quit; } - - 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)); - } - - void RGFW_window_mouseHold(RGFW_window* win, RGFW_area area) { - if (!(win->src.winArgs & RGFW_HOLD_MOUSE)) { - #ifdef RGFW_WINDOWS - RECT rect = {win->r.x, win->r.y, win->r.x + win->r.w, win->r.y + win->r.h}; - ClipCursor(&rect); - #endif - } - - win->src.winArgs |= RGFW_HOLD_MOUSE; - - if (!area.w && !area.h) - area = RGFW_AREA(win->r.w / 2, win->r.h / 2); - - RGFW_window_moveMouse(win, RGFW_VECTOR(win->r.x + (area.w), win->r.y + (area.h))); - } - - void RGFW_window_mouseUnhold(RGFW_window* win) { - win->src.winArgs ^= RGFW_HOLD_MOUSE; - - #ifdef RGFW_WINDOWS - ClipCursor(NULL); - #endif - } - +/* unix sleep */ void RGFW_sleep(u64 ms) { -#ifndef RGFW_WINDOWS struct timespec time; time.tv_sec = 0; time.tv_nsec = ms * 1e+6; nanosleep(&time, NULL); -#else - Sleep(ms); -#endif - } - - void RGFW_window_checkFPS(RGFW_window* win) { - u64 deltaTime = RGFW_getTimeNS() - win->event.frameTime; - - 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 (sleepTimeMS > 0) { - RGFW_sleep(sleepTimeMS); - win->event.frameTime = 0; - } - } - - win->event.frameTime = RGFW_getTimeNS(); - - if (win->fpsCap) { - u64 deltaTime = RGFW_getTimeNS() - win->event.frameTime2; - - win->event.fps = round(1e+9 / deltaTime); - - win->event.frameTime2 = RGFW_getTimeNS(); - } - } - -#ifdef __APPLE__ -#include -#endif - - u64 RGFW_getTimeNS(void) { -#ifdef RGFW_WINDOWS - LARGE_INTEGER frequency; - QueryPerformanceFrequency(&frequency); - - LARGE_INTEGER counter; - QueryPerformanceCounter(&counter); - - return (u64) (counter.QuadPart * 1e9 / frequency.QuadPart); -#elif defined(__unix__) - 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; - - return nanoSeconds; -#elif defined(__APPLE__) - static mach_timebase_info_data_t timebase_info; - if (timebase_info.denom == 0) { - mach_timebase_info(&timebase_info); - } - return mach_absolute_time() * timebase_info.numer / timebase_info.denom; -#endif - return 0; - } - - u64 RGFW_getTime(void) { -#ifdef RGFW_WINDOWS - LARGE_INTEGER frequency; - QueryPerformanceFrequency(&frequency); - - LARGE_INTEGER counter; - QueryPerformanceCounter(&counter); - return (u64) (counter.QuadPart / (double) frequency.QuadPart); -#elif defined(__unix__) - 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; - - return (double)(nanoSeconds) * 1e-9; -#elif defined(__APPLE__) - static mach_timebase_info_data_t timebase_info; - if (timebase_info.denom == 0) { - mach_timebase_info(&timebase_info); - } - return (double) mach_absolute_time() * (double) timebase_info.numer / ((double) timebase_info.denom * 1e9); -#endif - return 0; } +#endif /* end of unix / mac stuff*/ #endif /*RGFW_IMPLEMENTATION*/ #ifdef __cplusplus diff --git a/src/platforms/rcore_desktop_rgfw.c b/src/platforms/rcore_desktop_rgfw.c index 7dfe1f51c..5bd08217f 100644 --- a/src/platforms/rcore_desktop_rgfw.c +++ b/src/platforms/rcore_desktop_rgfw.c @@ -8,19 +8,17 @@ * - MacOS (Cocoa) * * LIMITATIONS: -* - Limitation 01 -* - Limitation 02 +* - TODO * * POSSIBLE IMPROVEMENTS: -* - Improvement 01 -* - Improvement 02 +* - TODO * * ADDITIONAL NOTES: * - TRACELOG() function is located in raylib [utils] module * * CONFIGURATION: -* #define RCORE_PLATFORM_CUSTOM_FLAG -* Custom flag for rcore on target platform -not used- +* #define RCORE_PLATFORM_RGFW +* Custom flag for rcore on target platform RGFW * * DEPENDENCIES: * - RGFW.h (main library): Windowing and inputs management @@ -244,7 +242,7 @@ bool WindowShouldClose(void) // Toggle fullscreen mode void ToggleFullscreen(void) -{ +{ RGFW_window_maximize(platform.window); ToggleBorderlessWindowed(); } @@ -252,10 +250,9 @@ void ToggleFullscreen(void) // Toggle borderless windowed mode void ToggleBorderlessWindowed(void) { - CORE.Window.flags & FLAG_WINDOW_UNDECORATED; - - if (platform.window != NULL) - TRACELOG(LOG_WARNING, "ToggleBorderlessWindowed() after window creation not available on target platform"); + if (platform.window != NULL) { + RGFW_window_setBorder(platform.window, CORE.Window.flags & FLAG_WINDOW_UNDECORATED); + } } // Set window state: maximized, if resizable @@ -292,6 +289,7 @@ void SetWindowState(unsigned int flags) } if (flags & FLAG_WINDOW_RESIZABLE) { + printf("%i %i\n", platform.window->r.w, platform.window->r.h); RGFW_window_setMaxSize(platform.window, RGFW_AREA(platform.window->r.w, platform.window->r.h)); RGFW_window_setMinSize(platform.window, RGFW_AREA(platform.window->r.w, platform.window->r.h)); } @@ -313,7 +311,7 @@ void SetWindowState(unsigned int flags) } if (flags & FLAG_WINDOW_UNFOCUSED) { - TRACELOG(LOG_WARNING, "SetWindowState() - FLAG_WINDOW_UNFOCUSED is not supported on PLATFORM_DESKTOP_SDL"); + TRACELOG(LOG_WARNING, "SetWindowState() - FLAG_WINDOW_UNFOCUSED is not supported on PLATFORM_DESKTOP_RGFW"); } if (flags & FLAG_WINDOW_TOPMOST) { @@ -325,7 +323,7 @@ void SetWindowState(unsigned int flags) } if (flags & FLAG_WINDOW_TRANSPARENT) { - TRACELOG(LOG_WARNING, "SetWindowState() - FLAG_WINDOW_TRANSPARENT is not supported on PLATFORM_DESKTOP_RGFW"); + TRACELOG(LOG_WARNING, "SetWindowState() - FLAG_WINDOW_TRANSPARENT post window creation post window creation is not supported on PLATFORM_DESKTOP_RGFW"); } if (flags & FLAG_WINDOW_HIGHDPI) { @@ -333,7 +331,7 @@ void SetWindowState(unsigned int flags) } if (flags & FLAG_WINDOW_MOUSE_PASSTHROUGH) { - TRACELOG(LOG_WARNING, "SetWindowState() - FLAG_WINDOW_MOUSE_PASSTHROUGH is not supported on PLATFORM_DESKTOP_RGFW"); + RGFW_window_setMousePassthrough(platform.window, flags & FLAG_WINDOW_MOUSE_PASSTHROUGH); } if (flags & FLAG_BORDERLESS_WINDOWED_MODE) { @@ -408,7 +406,7 @@ void ClearWindowState(unsigned int flags) } if (flags & FLAG_WINDOW_MOUSE_PASSTHROUGH) { - //SDL_SetWindowGrab(platform.window, SDL_TRUE); + RGFW_window_setMousePassthrough(platform.window, flags & FLAG_WINDOW_MOUSE_PASSTHROUGH); TRACELOG(LOG_WARNING, "ClearWindowState() - FLAG_WINDOW_MOUSE_PASSTHROUGH is not supported on PLATFORM_DESKTOP_RGFW"); } if (flags & FLAG_BORDERLESS_WINDOWED_MODE) @@ -566,16 +564,16 @@ int GetMonitorCount(void) // Get number of monitors int GetCurrentMonitor(void) { - int current = 0; RGFW_monitor *mons = RGFW_getMonitors(); RGFW_monitor mon = RGFW_window_getMonitor(platform.window); for (int i = 0; i < 6; i++) { - if ((mons[i].rect.x == mon.rect.x) && (mons[i].rect.y == mon.rect.y)) current = i; + if ((mons[i].rect.x == mon.rect.x) && (mons[i].rect.y == mon.rect.y)) + return i; } - return current; + return 0; } // Get selected monitor position @@ -760,6 +758,62 @@ void SetMouseCursor(int cursor) static KeyboardKey ConvertScancodeToKey(u32 keycode); +/* + TODO, try to make this better (RSGL uses this method too :I ) + sourced from RSGL obviously -> ColleagueRiley +*/ +char RSGL_keystrToChar(const char* str) { + if (str[1] == 0) + return str[0]; + + + static const char* map[] = { + "asciitilde", "`", + "grave", "~", + "exclam", "!", + "at", "@", + "numbersign", "#", + "dollar", "$", + "percent", "%%", + "asciicircum", "^", + "ampersand", "&", + "asterisk", "*", + "parenleft", "(", + "parenright", ")", + "underscore", "_", + "minus", "-", + "plus", "+", + "equal", "=", + "braceleft", "{", + "bracketleft", "[", + "bracketright", "]", + "braceright", "}", + "colon", ":", + "semicolon", ";", + "quotedbl", "\"", + "apostrophe", "'", + "bar", "|", + "backslash", "\'", + "less", "<", + "comma", ",", + "greater", ">", + "period", ".", + "question", "?", + "slash", "/", + "space", " ", + "Return", "\n", + "Enter", "\n", + "enter", "\n", + }; + + u8 i = 0; + for (i = 0; i < (sizeof(map) / sizeof(char*)); i += 2) + if (strcmp(map[i], str) == 0) + return *map[i + 1]; + + return '\0'; +} + // Register all input events void PollInputEvents(void) { @@ -924,7 +978,7 @@ void PollInputEvents(void) if (CORE.Input.Keyboard.charPressedQueueCount < MAX_CHAR_PRESSED_QUEUE) { // Add character (codepoint) to the queue - CORE.Input.Keyboard.charPressedQueue[CORE.Input.Keyboard.charPressedQueueCount] = RGFW_keystrToChar(event->keyName); + CORE.Input.Keyboard.charPressedQueue[CORE.Input.Keyboard.charPressedQueueCount] = RSGL_keystrToChar(event->keyName); CORE.Input.Keyboard.charPressedQueueCount++; } } break; From fa03246d0e6e4911cb9513065f07ed2014430b05 Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 9 Jul 2024 09:21:57 +0200 Subject: [PATCH 16/41] REVIEWED: Code formatting to follow raylib conventions --- src/platforms/rcore_desktop_rgfw.c | 104 ++++++++++++++--------------- 1 file changed, 50 insertions(+), 54 deletions(-) diff --git a/src/platforms/rcore_desktop_rgfw.c b/src/platforms/rcore_desktop_rgfw.c index 5bd08217f..83430f511 100644 --- a/src/platforms/rcore_desktop_rgfw.c +++ b/src/platforms/rcore_desktop_rgfw.c @@ -47,56 +47,55 @@ **********************************************************************************************/ #ifdef GRAPHICS_API_OPENGL_ES2 -#define RGFW_OPENGL_ES2 + #define RGFW_OPENGL_ES2 #endif void ShowCursor(void); void CloseWindow(void); -#ifdef __linux__ -#define _INPUT_EVENT_CODES_H +#if defined(__linux__) + #define _INPUT_EVENT_CODES_H #endif #if defined(__unix__) || defined(__linux__) -#define _XTYPEDEF_FONT + #define _XTYPEDEF_FONT #endif #define RGFW_IMPLEMENTATION #if defined(__WIN32) || defined(__WIN64) -#define WIN32_LEAN_AND_MEAN -#define Rectangle rectangle_win32 -#define CloseWindow CloseWindow_win32 -#define ShowCursor __imp_ShowCursor -#define _APISETSTRING_ + #define WIN32_LEAN_AND_MEAN + #define Rectangle rectangle_win32 + #define CloseWindow CloseWindow_win32 + #define ShowCursor __imp_ShowCursor + #define _APISETSTRING_ #endif -#ifdef __APPLE__ -#define Point NSPOINT -#define Size NSSIZE +#if defined(__APPLE__) + #define Point NSPOINT + #define Size NSSIZE #endif -#ifdef _MSC_VER -__declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int CodePage, unsigned long dwFlags, const char *lpMultiByteStr, int cbMultiByte, wchar_t *lpWideCharStr, int cchWideChar); +#if defined(_MSC_VER) +__declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int CodePage, unsigned long dwFlags, const char *lpMultiByteStr, int cbMultiByte, wchar_t *lpWideCharStr, int cchWideChar); #endif #include "../external/RGFW.h" - - #if defined(__WIN32) || defined(__WIN64) -#undef DrawText -#undef ShowCursor -#undef CloseWindow -#undef Rectangle + #undef DrawText + #undef ShowCursor + #undef CloseWindow + #undef Rectangle #endif -#ifdef __APPLE__ -#undef Point -#undef Size +#if defined(__APPLE__) + #undef Point + #undef Size #endif #include +#include // Required for: strcmp() //---------------------------------------------------------------------------------- // Types and Structures Definition @@ -110,7 +109,9 @@ typedef struct { //---------------------------------------------------------------------------------- extern CoreData CORE; // Global CORE state context -static PlatformData platform = { NULL }; // Platform specific +static PlatformData platform = { NULL }; // Platform specific + +static bool RGFW_disableCursor = false; static const unsigned short keyMappingRGFW[] = { [RGFW_KEY_NULL] = KEY_NULL, @@ -250,7 +251,8 @@ void ToggleFullscreen(void) // Toggle borderless windowed mode void ToggleBorderlessWindowed(void) { - if (platform.window != NULL) { + if (platform.window != NULL) + { RGFW_window_setBorder(platform.window, CORE.Window.flags & FLAG_WINDOW_UNDECORATED); } } @@ -569,8 +571,7 @@ int GetCurrentMonitor(void) for (int i = 0; i < 6; i++) { - if ((mons[i].rect.x == mon.rect.x) && (mons[i].rect.y == mon.rect.y)) - return i; + if ((mons[i].rect.x == mon.rect.x) && (mons[i].rect.y == mon.rect.y)) return i; } return 0; @@ -672,8 +673,6 @@ void HideCursor(void) CORE.Input.Mouse.cursorHidden = true; } -bool RGFW_disableCursor = false; - // Enables cursor (unlock cursor) void EnableCursor(void) { @@ -690,6 +689,7 @@ 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); @@ -727,7 +727,7 @@ void OpenURL(const char *url) if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character"); else { - // TODO: + // TODO: Open URL implementation } } @@ -758,16 +758,12 @@ void SetMouseCursor(int cursor) static KeyboardKey ConvertScancodeToKey(u32 keycode); -/* - TODO, try to make this better (RSGL uses this method too :I ) - sourced from RSGL obviously -> ColleagueRiley -*/ -char RSGL_keystrToChar(const char* str) { - if (str[1] == 0) - return str[0]; +// TODO: Review function to avoid duplicate with RSGL +char RSGL_keystrToChar(const char *str) +{ + if (str[1] == 0) return str[0]; - - static const char* map[] = { + static const char *map[] = { "asciitilde", "`", "grave", "~", "exclam", "!", @@ -806,10 +802,10 @@ char RSGL_keystrToChar(const char* str) { "enter", "\n", }; - u8 i = 0; - for (i = 0; i < (sizeof(map) / sizeof(char*)); i += 2) - if (strcmp(map[i], str) == 0) - return *map[i + 1]; + for (unsigned char i = 0; i < (sizeof(map)/sizeof(char *)); i += 2) + { + if (strcmp(map[i], str) == 0) return *map[i + 1]; + } return '\0'; } @@ -866,25 +862,25 @@ void PollInputEvents(void) } // Register previous mouse states - for (int i = 0; i < MAX_MOUSE_BUTTONS; i++) - CORE.Input.Mouse.previousButtonState[i] = CORE.Input.Mouse.currentButtonState[i]; + for (int i = 0; i < MAX_MOUSE_BUTTONS; i++) CORE.Input.Mouse.previousButtonState[i] = CORE.Input.Mouse.currentButtonState[i]; // Poll input events for current platform //----------------------------------------------------------------------------- CORE.Window.resizedLastFrame = false; +#define RGFW_HOLD_MOUSE (1L<<2) - #define RGFW_HOLD_MOUSE (1L<<2) - #if defined(RGFW_X11) //|| defined(RGFW_MACOS) +#if defined(RGFW_X11) //|| defined(RGFW_MACOS) if (platform.window->src.winArgs & RGFW_HOLD_MOUSE) { CORE.Input.Mouse.previousPosition = (Vector2){ 0.0f, 0.0f }; CORE.Input.Mouse.currentPosition = (Vector2){ 0.0f, 0.0f }; } - else { + else + { CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition; } - #endif +#endif while (RGFW_window_checkEvent(platform.window)) { @@ -901,7 +897,7 @@ void PollInputEvents(void) } } - RGFW_Event* event = &platform.window->event; + RGFW_Event *event = &platform.window->event; // All input events can be processed after polling switch (event->type) @@ -1163,6 +1159,7 @@ void PollInputEvents(void) int button = (axis == GAMEPAD_AXIS_LEFT_TRIGGER)? GAMEPAD_BUTTON_LEFT_TRIGGER_2 : GAMEPAD_BUTTON_RIGHT_TRIGGER_2; int pressed = (value > 0.1f); CORE.Input.Gamepad.currentButtonState[event->joystick][button] = pressed; + if (pressed) CORE.Input.Gamepad.lastButtonPressed = button; else if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0; } @@ -1254,8 +1251,7 @@ int InitPlatform(void) platform.window = RGFW_createWindow(CORE.Window.title, RGFW_RECT(0, 0, CORE.Window.screen.width, CORE.Window.screen.height), flags); - if (CORE.Window.flags & FLAG_VSYNC_HINT) - RGFW_window_swapInterval(platform.window, 1); + if (CORE.Window.flags & FLAG_VSYNC_HINT) RGFW_window_swapInterval(platform.window, 1); RGFW_window_makeCurrent(platform.window); @@ -1320,12 +1316,12 @@ int InitPlatform(void) CORE.Storage.basePath = GetWorkingDirectory(); //---------------------------------------------------------------------------- - #ifdef RGFW_X11 +#ifdef RGFW_X11 for (int i = 0; (i < 4) && (i < MAX_GAMEPADS); i++) { RGFW_registerJoystick(platform.window, i); } - #endif +#endif TRACELOG(LOG_INFO, "PLATFORM: CUSTOM: Initialized successfully"); From 174313acbfa74d2a45fc0207f47ab00fbdb06050 Mon Sep 17 00:00:00 2001 From: SuperUserNameMan <9801802+SuperUserNameMan@users.noreply.github.com> Date: Tue, 9 Jul 2024 09:23:14 +0200 Subject: [PATCH 17/41] `WindowSizeCallback()` should not try to handle DPI since already managed by GLFW (#4143) If `FLAG_WINDOW_HIGHDPI` is set, `InitPlatform()` will aks GLFW to handle resize window content area based on the monitor content scale using : ` glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE); ` So `WindowSizeCallback()` does not have to handle it a second time. --- src/platforms/rcore_desktop_glfw.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/src/platforms/rcore_desktop_glfw.c b/src/platforms/rcore_desktop_glfw.c index 42c64402f..56a4e2619 100644 --- a/src/platforms/rcore_desktop_glfw.c +++ b/src/platforms/rcore_desktop_glfw.c @@ -1669,23 +1669,9 @@ static void WindowSizeCallback(GLFWwindow *window, int width, int height) if (IsWindowFullscreen()) return; // Set current screen size -#if defined(__APPLE__) + CORE.Window.screen.width = width; CORE.Window.screen.height = height; -#else - if ((CORE.Window.flags & FLAG_WINDOW_HIGHDPI) > 0) - { - Vector2 windowScaleDPI = GetWindowScaleDPI(); - - CORE.Window.screen.width = (unsigned int)(width/windowScaleDPI.x); - CORE.Window.screen.height = (unsigned int)(height/windowScaleDPI.y); - } - else - { - CORE.Window.screen.width = width; - CORE.Window.screen.height = height; - } -#endif // NOTE: Postprocessing texture is not scaled to new size } From 74680748b9abe05ceda5d412b61ff99addf72807 Mon Sep 17 00:00:00 2001 From: Jeffery Myers Date: Tue, 9 Jul 2024 10:45:07 -0700 Subject: [PATCH 18/41] [Shapes] Remove duplicate color calls in DrawGrid (#4148) * Update raylib_api.* by CI * No need to call the color 4 times in a row, it's batched --------- Co-authored-by: github-actions[bot] --- src/rmodels.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/rmodels.c b/src/rmodels.c index 50328fca7..c1d56765e 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -1072,16 +1072,10 @@ void DrawGrid(int slices, float spacing) if (i == 0) { rlColor3f(0.5f, 0.5f, 0.5f); - rlColor3f(0.5f, 0.5f, 0.5f); - rlColor3f(0.5f, 0.5f, 0.5f); - rlColor3f(0.5f, 0.5f, 0.5f); } else { rlColor3f(0.75f, 0.75f, 0.75f); - rlColor3f(0.75f, 0.75f, 0.75f); - rlColor3f(0.75f, 0.75f, 0.75f); - rlColor3f(0.75f, 0.75f, 0.75f); } rlVertex3f((float)i*spacing, 0.0f, (float)-halfSlices*spacing); From 44c6cd2d37504a54c37ca9890889d8c34ba3f332 Mon Sep 17 00:00:00 2001 From: InventorXtreme <43659737+InventorXtreme@users.noreply.github.com> Date: Thu, 11 Jul 2024 03:59:26 -0400 Subject: [PATCH 19/41] [build.zig] GLFW Platform Detection Support (#4150) * Zig Both Linux Desktop Platform Support * Formating and Default Fix Made formating fit within raylib standards and changed the default option to support both X11 and wayland on Linux. * caught one hiding tab --- src/build.zig | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/src/build.zig b/src/build.zig index 3b462de61..2da5cbd04 100644 --- a/src/build.zig +++ b/src/build.zig @@ -117,31 +117,29 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std. raylib.addLibraryPath(.{ .cwd_relative = "/usr/lib" }); raylib.addIncludePath(.{ .cwd_relative = "/usr/include" }); + if (options.linux_display_backend == .X11 or options.linux_display_backend == .Both) { - switch (options.linux_display_backend) { - .X11 => { raylib.defineCMacro("_GLFW_X11", null); raylib.linkSystemLibrary("X11"); - }, - .Wayland => { - raylib.defineCMacro("_GLFW_WAYLAND", null); - raylib.linkSystemLibrary("wayland-client"); - raylib.linkSystemLibrary("wayland-cursor"); - raylib.linkSystemLibrary("wayland-egl"); - raylib.linkSystemLibrary("xkbcommon"); - raylib.addIncludePath(b.path("src")); - waylandGenerate(b, raylib, "wayland.xml", "wayland-client-protocol"); - waylandGenerate(b, raylib, "xdg-shell.xml", "xdg-shell-client-protocol"); - waylandGenerate(b, raylib, "xdg-decoration-unstable-v1.xml", "xdg-decoration-unstable-v1-client-protocol"); - waylandGenerate(b, raylib, "viewporter.xml", "viewporter-client-protocol"); - waylandGenerate(b, raylib, "relative-pointer-unstable-v1.xml", "relative-pointer-unstable-v1-client-protocol"); - waylandGenerate(b, raylib, "pointer-constraints-unstable-v1.xml", "pointer-constraints-unstable-v1-client-protocol"); - waylandGenerate(b, raylib, "fractional-scale-v1.xml", "fractional-scale-v1-client-protocol"); - waylandGenerate(b, raylib, "xdg-activation-v1.xml", "xdg-activation-v1-client-protocol"); - waylandGenerate(b, raylib, "idle-inhibit-unstable-v1.xml", "idle-inhibit-unstable-v1-client-protocol"); - }, } + if (options.linux_display_backend == .Wayland or options.linux_display_backend == .Both) { + raylib.defineCMacro("_GLFW_WAYLAND", null); + raylib.linkSystemLibrary("wayland-client"); + raylib.linkSystemLibrary("wayland-cursor"); + raylib.linkSystemLibrary("wayland-egl"); + raylib.linkSystemLibrary("xkbcommon"); + raylib.addIncludePath(b.path("src")); + waylandGenerate(b, raylib, "wayland.xml", "wayland-client-protocol"); + waylandGenerate(b, raylib, "xdg-shell.xml", "xdg-shell-client-protocol"); + waylandGenerate(b, raylib, "xdg-decoration-unstable-v1.xml", "xdg-decoration-unstable-v1-client-protocol"); + waylandGenerate(b, raylib, "viewporter.xml", "viewporter-client-protocol"); + waylandGenerate(b, raylib, "relative-pointer-unstable-v1.xml", "relative-pointer-unstable-v1-client-protocol"); + waylandGenerate(b, raylib, "pointer-constraints-unstable-v1.xml", "pointer-constraints-unstable-v1-client-protocol"); + waylandGenerate(b, raylib, "fractional-scale-v1.xml", "fractional-scale-v1-client-protocol"); + waylandGenerate(b, raylib, "xdg-activation-v1.xml", "xdg-activation-v1-client-protocol"); + waylandGenerate(b, raylib, "idle-inhibit-unstable-v1.xml", "idle-inhibit-unstable-v1-client-protocol"); + } raylib.defineCMacro("PLATFORM_DESKTOP", null); } else { if (options.opengl_version == .auto) { @@ -253,7 +251,7 @@ pub const Options = struct { raygui: bool = false, platform_drm: bool = false, shared: bool = false, - linux_display_backend: LinuxDisplayBackend = .X11, + linux_display_backend: LinuxDisplayBackend = .Both, opengl_version: OpenglVersion = .auto, raygui_dependency_name: []const u8 = "raygui", @@ -284,6 +282,7 @@ pub const OpenglVersion = enum { pub const LinuxDisplayBackend = enum { X11, Wayland, + Both, }; pub fn build(b: *std.Build) !void { From 8d5374a443509036063a350d1649408e009425e7 Mon Sep 17 00:00:00 2001 From: Kai Kitagawa-Jones Date: Thu, 11 Jul 2024 21:31:13 +0200 Subject: [PATCH 20/41] Replace `glGetInteger64v` with `glGetBufferParameteri64v` (#4154) --- src/rlgl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rlgl.h b/src/rlgl.h index 5b921ab9c..ccb53a624 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -4401,7 +4401,7 @@ unsigned int rlGetShaderBufferSize(unsigned int id) #if defined(GRAPHICS_API_OPENGL_43) glBindBuffer(GL_SHADER_STORAGE_BUFFER, id); - glGetInteger64v(GL_SHADER_STORAGE_BUFFER_SIZE, &size); + glGetBufferParameteri64v(GL_SHADER_STORAGE_BUFFER, GL_BUFFER_SIZE, &size); #endif return (size > 0)? (unsigned int)size : 0; From 5ede47618bd9f9a440af648da1b4817e51644994 Mon Sep 17 00:00:00 2001 From: jkaup <29462864+jkaup@users.noreply.github.com> Date: Sun, 14 Jul 2024 00:10:28 +0300 Subject: [PATCH 21/41] Fix crash when switching playback device (#4102) Co-authored-by: jj --- src/external/miniaudio.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/external/miniaudio.h b/src/external/miniaudio.h index 47332e11a..787c626ad 100644 --- a/src/external/miniaudio.h +++ b/src/external/miniaudio.h @@ -21473,7 +21473,9 @@ static ma_result ma_context_get_MMDevice__wasapi(ma_context* pContext, ma_device MA_ASSERT(pContext != NULL); MA_ASSERT(ppMMDevice != NULL); + ma_CoInitializeEx(pContext, NULL, MA_COINIT_VALUE); hr = ma_CoCreateInstance(pContext, &MA_CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, &MA_IID_IMMDeviceEnumerator, (void**)&pDeviceEnumerator); + ma_CoUninitialize(pContext); if (FAILED(hr)) { ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to create IMMDeviceEnumerator.\n"); return ma_result_from_HRESULT(hr); From 576bee5cce1254791561b57f2137e2a3b611d26a Mon Sep 17 00:00:00 2001 From: MrScautHD <65916181+MrScautHD@users.noreply.github.com> Date: Tue, 16 Jul 2024 14:00:00 +0200 Subject: [PATCH 22/41] Adding GetKeyName(int key) (WIP) (#4161) --- src/platforms/rcore_android.c | 7 +++++++ src/platforms/rcore_desktop_glfw.c | 6 ++++++ src/platforms/rcore_desktop_rgfw.c | 7 +++++++ src/platforms/rcore_desktop_sdl.c | 6 ++++++ src/platforms/rcore_drm.c | 7 +++++++ src/platforms/rcore_template.c | 7 +++++++ src/platforms/rcore_web.c | 7 +++++++ 7 files changed, 47 insertions(+) diff --git a/src/platforms/rcore_android.c b/src/platforms/rcore_android.c index 8fc51d0e1..68ae979ee 100644 --- a/src/platforms/rcore_android.c +++ b/src/platforms/rcore_android.c @@ -632,6 +632,13 @@ void SetMouseCursor(int cursor) TRACELOG(LOG_WARNING, "SetMouseCursor() not implemented on target platform"); } +// Get physical key name. +const char *GetKeyName(int key) +{ + TRACELOG(LOG_WARNING, "GetKeyName() not implemented on target platform"); + return ""; +} + // Register all input events void PollInputEvents(void) { diff --git a/src/platforms/rcore_desktop_glfw.c b/src/platforms/rcore_desktop_glfw.c index 56a4e2619..947a80335 100644 --- a/src/platforms/rcore_desktop_glfw.c +++ b/src/platforms/rcore_desktop_glfw.c @@ -1075,6 +1075,12 @@ void SetMouseCursor(int cursor) } } +// Get physical key name. +const char *GetKeyName(int key) +{ + return glfwGetKeyName(key, glfwGetKeyScancode(key)); +} + // Register all input events void PollInputEvents(void) { diff --git a/src/platforms/rcore_desktop_rgfw.c b/src/platforms/rcore_desktop_rgfw.c index 83430f511..cfc091172 100644 --- a/src/platforms/rcore_desktop_rgfw.c +++ b/src/platforms/rcore_desktop_rgfw.c @@ -756,6 +756,13 @@ void SetMouseCursor(int cursor) RGFW_window_setMouseStandard(platform.window, cursor); } +// Get physical key name. +const char *GetKeyName(int key) +{ + TRACELOG(LOG_WARNING, "GetKeyName() not implemented on target platform"); + return ""; +} + static KeyboardKey ConvertScancodeToKey(u32 keycode); // TODO: Review function to avoid duplicate with RSGL diff --git a/src/platforms/rcore_desktop_sdl.c b/src/platforms/rcore_desktop_sdl.c index 3d6293597..794f9e6a0 100644 --- a/src/platforms/rcore_desktop_sdl.c +++ b/src/platforms/rcore_desktop_sdl.c @@ -966,6 +966,12 @@ void SetMouseCursor(int cursor) CORE.Input.Mouse.cursor = cursor; } +// Get physical key name. +const char *GetKeyName(int key) +{ + return SDL_GetKeyName(key); +} + static void UpdateTouchPointsSDL(SDL_TouchFingerEvent event) { CORE.Input.Touch.pointCount = SDL_GetNumTouchFingers(event.touchId); diff --git a/src/platforms/rcore_drm.c b/src/platforms/rcore_drm.c index f888d0e47..291fd93c7 100644 --- a/src/platforms/rcore_drm.c +++ b/src/platforms/rcore_drm.c @@ -628,6 +628,13 @@ void SetMouseCursor(int cursor) TRACELOG(LOG_WARNING, "SetMouseCursor() not implemented on target platform"); } +// Get physical key name. +const char *GetKeyName(int key) +{ + TRACELOG(LOG_WARNING, "GetKeyName() not implemented on target platform"); + return ""; +} + // Register all input events void PollInputEvents(void) { diff --git a/src/platforms/rcore_template.c b/src/platforms/rcore_template.c index 7a48c465e..938f4ed7d 100644 --- a/src/platforms/rcore_template.c +++ b/src/platforms/rcore_template.c @@ -384,6 +384,13 @@ void SetMouseCursor(int cursor) TRACELOG(LOG_WARNING, "SetMouseCursor() not implemented on target platform"); } +// Get physical key name. +const char *GetKeyName(int key) +{ + TRACELOG(LOG_WARNING, "GetKeyName() not implemented on target platform"); + return ""; +} + // Register all input events void PollInputEvents(void) { diff --git a/src/platforms/rcore_web.c b/src/platforms/rcore_web.c index 47b8d42d6..937e15acd 100644 --- a/src/platforms/rcore_web.c +++ b/src/platforms/rcore_web.c @@ -884,6 +884,13 @@ void SetMouseCursor(int cursor) } } +// Get physical key name. +const char *GetKeyName(int key) +{ + TRACELOG(LOG_WARNING, "GetKeyName() not implemented on target platform"); + return ""; +} + // Register all input events void PollInputEvents(void) { From 0c03cbff90acf8afe3976688aaa8239e4b5a637f Mon Sep 17 00:00:00 2001 From: red thing Date: Tue, 16 Jul 2024 05:00:30 -0700 Subject: [PATCH 23/41] Update BINDINGS.md: dray binding supports raylib 5.0 (#4163) --- BINDINGS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BINDINGS.md b/BINDINGS.md index 22b740588..1196acc4e 100644 --- a/BINDINGS.md +++ b/BINDINGS.md @@ -21,7 +21,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers | [ray-cyber](https://github.com/fubark/ray-cyber) | **5.0** | [Cyber](https://cyberscript.dev) | MIT | | [dart-raylib](https://gitlab.com/wolfenrain/dart-raylib) | 4.0 | [Dart](https://dart.dev) | MIT | | [bindbc-raylib3](https://github.com/o3o/bindbc-raylib3) | **5.0** | [D](https://dlang.org) | BSL-1.0 | -| [dray](https://github.com/redthing1/dray) | 4.2 | [D](https://dlang.org) | Apache-2.0 | +| [dray](https://github.com/redthing1/dray) | **5.0** | [D](https://dlang.org) | Apache-2.0 | | [raylib-d](https://github.com/schveiguy/raylib-d) | **5.0** | [D](https://dlang.org) | Zlib | | [rayex](https://github.com/shiryel/rayex) | 3.7 | [elixir](https://elixir-lang.org) | Apache-2.0 | | [raylib-factor](https://github.com/factor/factor/blob/master/extra/raylib/raylib.factor) | 4.5 | [Factor](https://factorcode.org) | BSD | From 24726a4bc2f2c265cfc78b7c56f9a9c2143df4a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A1zaro=20Albuquerque?= <33807434+lzralbu@users.noreply.github.com> Date: Tue, 16 Jul 2024 08:16:41 -0400 Subject: [PATCH 24/41] Removes the redundant USE_AUDIO flag (#4158) --- cmake/CompileDefinitions.cmake | 1 - src/CMakeLists.txt | 7 +++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/cmake/CompileDefinitions.cmake b/cmake/CompileDefinitions.cmake index 0acbe2fa5..cefafdeb7 100644 --- a/cmake/CompileDefinitions.cmake +++ b/cmake/CompileDefinitions.cmake @@ -11,7 +11,6 @@ endfunction() if(${CUSTOMIZE_BUILD}) target_compile_definitions("raylib" PRIVATE EXTERNAL_CONFIG_FLAGS) - define_if("raylib" USE_AUDIO) foreach(FLAG IN LISTS CONFIG_HEADER_FLAGS) string(REGEX MATCH "([^=]+)=(.+)" _ ${FLAG}) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8f4d0e26e..dd940b36c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -29,6 +29,7 @@ set(raylib_public_headers # Sources to be compiled set(raylib_sources + raudio.c rcore.c rmodels.c rshapes.c @@ -47,14 +48,12 @@ endif () # Produces a variable LIBS_PRIVATE that will be used later include(LibraryConfigurations) -if (USE_AUDIO) +if (SUPPORT_MODULE_RAUDIO) MESSAGE(STATUS "Audio Backend: miniaudio") - list(APPEND raylib_sources raudio.c) else () - MESSAGE(STATUS "Audio Backend: None (-DUSE_AUDIO=OFF)") + MESSAGE(STATUS "Audio Backend: None (-DCUSTOMIZE_BUILD=ON -DSUPPORT_MODULE_RAUDIO=OFF)") endif () - add_library(raylib ${raylib_sources} ${raylib_public_headers}) if (NOT BUILD_SHARED_LIBS) From 50000f4b01d090c9ff4cf64415104f7c7dd04f73 Mon Sep 17 00:00:00 2001 From: _Tradam Date: Thu, 18 Jul 2024 15:06:18 -0400 Subject: [PATCH 25/41] added brainfuck bindings (#4169) --- BINDINGS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/BINDINGS.md b/BINDINGS.md index 1196acc4e..f4bc1f69b 100644 --- a/BINDINGS.md +++ b/BINDINGS.md @@ -9,6 +9,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers | [raylib](https://github.com/raysan5/raylib) | **5.0** | [C/C++](https://en.wikipedia.org/wiki/C_(programming_language)) | Zlib | | [raylib-beef](https://github.com/Starpelly/raylib-beef) | **5.0** | [Beef](https://www.beeflang.org) | MIT | | [raylib-boo](https://github.com/Rabios/raylib-boo) | 3.7 | [Boo](http://boo-language.github.io) | MIT | +| [raybit](https://github.com/Alex-Velez/raybit) | 3.7 | [Brainfuck](https://en.wikipedia.org/wiki/Brainfuck) | MIT | | [Raylib-cs](https://github.com/ChrisDill/Raylib-cs) | **5.0** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | Zlib | | [Raylib-CsLo](https://github.com/NotNotTech/Raylib-CsLo) | 4.2 | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | MPL-2.0 | | [Raylib-CSharp-Vinculum](https://github.com/ZeroElectric/Raylib-CSharp-Vinculum) | **5.0** | [C#](https://en.wikipedia.org/wiki/C_Sharp_(programming_language)) | MPL-2.0 | From 61393fff1ffcf0fd3a32ca431e312efbddbf8670 Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 19 Jul 2024 00:39:11 +0200 Subject: [PATCH 26/41] Update rcore_desktop_glfw.c --- src/platforms/rcore_desktop_glfw.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/platforms/rcore_desktop_glfw.c b/src/platforms/rcore_desktop_glfw.c index 947a80335..d03bac153 100644 --- a/src/platforms/rcore_desktop_glfw.c +++ b/src/platforms/rcore_desktop_glfw.c @@ -1638,7 +1638,6 @@ int InitPlatform(void) } #endif - TRACELOG(LOG_INFO, "GLFW platform: %s", glfwPlatform); TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (GLFW): Initialized successfully"); return 0; From 996f50393ec51fa33b361546986afc9762849a76 Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 19 Jul 2024 00:39:58 +0200 Subject: [PATCH 27/41] Minor tweaks --- src/raylib.h | 2 +- src/rcore.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/raylib.h b/src/raylib.h index 60ec3c23e..686e83c9c 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1,6 +1,6 @@ /********************************************************************************************** * -* raylib v5.5 - A simple and easy-to-use library to enjoy videogames programming (www.raylib.com) +* raylib v5.5-dev - A simple and easy-to-use library to enjoy videogames programming (www.raylib.com) * * FEATURES: * - NO external dependencies, all required libraries included with raylib diff --git a/src/rcore.c b/src/rcore.c index e68a9a7d5..c324ce2ac 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -3482,7 +3482,7 @@ static void RecordAutomationEvent(void) currentEventList->events[currentEventList->count].frame = CORE.Time.frameCounter; currentEventList->events[currentEventList->count].type = INPUT_MOUSE_WHEEL_MOTION; currentEventList->events[currentEventList->count].params[0] = (int)CORE.Input.Mouse.currentWheelMove.x; - currentEventList->events[currentEventList->count].params[1] = (int)CORE.Input.Mouse.currentWheelMove.y;; + currentEventList->events[currentEventList->count].params[1] = (int)CORE.Input.Mouse.currentWheelMove.y; currentEventList->events[currentEventList->count].params[2] = 0; TRACELOG(LOG_INFO, "AUTOMATION: Frame: %i | Event type: INPUT_MOUSE_WHEEL_MOTION | Event parameters: %i, %i, %i", currentEventList->events[currentEventList->count].frame, currentEventList->events[currentEventList->count].params[0], currentEventList->events[currentEventList->count].params[1], currentEventList->events[currentEventList->count].params[2]); From aa70d32786f0260d7a6b37e47f14f922366a0d31 Mon Sep 17 00:00:00 2001 From: Julianiolo <50519317+Julianiolo@users.noreply.github.com> Date: Sat, 20 Jul 2024 10:39:14 +0200 Subject: [PATCH 28/41] Fix a dependance of rtexture to rtext (#4171) --- src/rtextures.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/rtextures.c b/src/rtextures.c index 1e88b64a4..dc364d762 100644 --- a/src/rtextures.c +++ b/src/rtextures.c @@ -1213,6 +1213,7 @@ Image GenImageText(int width, int height, const char *text) { Image image = { 0 }; +#ifdef SUPPORT_MODULE_RTEXT int textLength = TextLength(text); int imageViewSize = width*height; @@ -1223,6 +1224,10 @@ Image GenImageText(int width, int height, const char *text) image.mipmaps = 1; memcpy(image.data, text, (textLength > imageViewSize)? imageViewSize : textLength); +#else + TRACELOG(LOG_WARNING, "IMAGE: GenImageText() requires module: rtext"); + image = GenImageColor(width, height, BLACK); // Generating placeholder black image rectangle +#endif return image; } From 2d94d8d06def4a96a8727e148fe12e2095c6799c Mon Sep 17 00:00:00 2001 From: CDM15y Date: Sat, 20 Jul 2024 09:42:55 +0100 Subject: [PATCH 29/41] [examples] Fix PBR and Shadowmap example shaders for GLSL 1.20 (#4167) * Update pbr.fs remove presicion mediump float because it is for GLES, and not desktop GL * Fix shadowmap.fs also suffers the same problem as pbr.fs --- .../shaders/resources/shaders/glsl120/pbr.fs | 16 +++++++--------- .../resources/shaders/glsl120/shadowmap.fs | 8 +++----- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/examples/shaders/resources/shaders/glsl120/pbr.fs b/examples/shaders/resources/shaders/glsl120/pbr.fs index 935bced35..1c5eee00b 100644 --- a/examples/shaders/resources/shaders/glsl120/pbr.fs +++ b/examples/shaders/resources/shaders/glsl120/pbr.fs @@ -1,7 +1,5 @@ #version 120 -precision mediump float; - #define MAX_LIGHTS 4 #define LIGHT_DIRECTIONAL 0 #define LIGHT_POINT 1 @@ -17,12 +15,12 @@ struct Light { }; // Input vertex attributes (from vertex shader) -varying in vec3 fragPosition; -varying in vec2 fragTexCoord; -varying in vec4 fragColor; -varying in vec3 fragNormal; -varying in vec4 shadowPos; -varying in mat3 TBN; +varying vec3 fragPosition; +varying vec2 fragTexCoord; +varying vec4 fragColor; +varying vec3 fragNormal; +varying vec4 shadowPos; +varying mat3 TBN; // Input uniform values @@ -153,4 +151,4 @@ void main() gl_FragColor = vec4(color,1.0); -} \ No newline at end of file +} diff --git a/examples/shaders/resources/shaders/glsl120/shadowmap.fs b/examples/shaders/resources/shaders/glsl120/shadowmap.fs index 668fdeb4b..f43e63823 100644 --- a/examples/shaders/resources/shaders/glsl120/shadowmap.fs +++ b/examples/shaders/resources/shaders/glsl120/shadowmap.fs @@ -1,15 +1,13 @@ #version 120 -precision mediump float; - // This shader is based on the basic lighting shader // This only supports one light, which is directional, and it (of course) supports shadows // Input vertex attributes (from vertex shader) -varying in vec3 fragPosition; -varying in vec2 fragTexCoord; +varying vec3 fragPosition; +varying vec2 fragTexCoord; //varying in vec4 fragColor; -varying in vec3 fragNormal; +varying vec3 fragNormal; // Input uniform values uniform sampler2D texture0; From fc5eab5676341d0dab918ee008810049d6b50dbf Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 21 Jul 2024 10:28:01 +0200 Subject: [PATCH 30/41] Update version to avoid confusions... ...considering that `raylib 5.5` official release could still take some time... --- src/raylib.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/raylib.h b/src/raylib.h index 686e83c9c..1cf34f004 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -84,7 +84,7 @@ #define RAYLIB_VERSION_MAJOR 5 #define RAYLIB_VERSION_MINOR 5 #define RAYLIB_VERSION_PATCH 0 -#define RAYLIB_VERSION "5.5" +#define RAYLIB_VERSION "5.5-dev" // Function specifiers in case library is build/used as a shared library // NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll From fde0dcd0abf8ec2f72872929886b55be95031900 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 21 Jul 2024 10:28:23 +0200 Subject: [PATCH 31/41] ADDED: Working directory info at initialization --- src/rcore.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/rcore.c b/src/rcore.c index c324ce2ac..fb71da0f6 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -683,6 +683,8 @@ void InitWindow(int width, int height, const char *title) // Initialize random seed SetRandomSeed((unsigned int)time(NULL)); + + TRACELOG(LOG_INFO, "SYSTEM: Working Directory: %s", GetWorkingDirectory()); } // Close window and unload OpenGL context From 474ab48f8be5a68ee505d2bc7ca10b297b988e06 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 21 Jul 2024 10:28:34 +0200 Subject: [PATCH 32/41] Update rtextures.c --- src/rtextures.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rtextures.c b/src/rtextures.c index dc364d762..d70e2cde8 100644 --- a/src/rtextures.c +++ b/src/rtextures.c @@ -1213,7 +1213,7 @@ Image GenImageText(int width, int height, const char *text) { Image image = { 0 }; -#ifdef SUPPORT_MODULE_RTEXT +#if defined(SUPPORT_MODULE_RTEXT) int textLength = TextLength(text); int imageViewSize = width*height; From ad72e3ec8fc4d25ed328c26628006f446db496e6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 21 Jul 2024 08:28:53 +0000 Subject: [PATCH 33/41] Update raylib_api.* by CI --- parser/output/raylib_api.json | 2 +- parser/output/raylib_api.lua | 2 +- parser/output/raylib_api.txt | 2 +- parser/output/raylib_api.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/parser/output/raylib_api.json b/parser/output/raylib_api.json index c00407dc6..f149d628f 100644 --- a/parser/output/raylib_api.json +++ b/parser/output/raylib_api.json @@ -27,7 +27,7 @@ { "name": "RAYLIB_VERSION", "type": "STRING", - "value": "5.5", + "value": "5.5-dev", "description": "" }, { diff --git a/parser/output/raylib_api.lua b/parser/output/raylib_api.lua index 9cbd1b9da..7c00fff33 100644 --- a/parser/output/raylib_api.lua +++ b/parser/output/raylib_api.lua @@ -27,7 +27,7 @@ return { { name = "RAYLIB_VERSION", type = "STRING", - value = "5.5", + value = "5.5-dev", description = "" }, { diff --git a/parser/output/raylib_api.txt b/parser/output/raylib_api.txt index 31433073e..73170c860 100644 --- a/parser/output/raylib_api.txt +++ b/parser/output/raylib_api.txt @@ -24,7 +24,7 @@ Define 004: RAYLIB_VERSION_PATCH Define 005: RAYLIB_VERSION Name: RAYLIB_VERSION Type: STRING - Value: "5.5" + Value: "5.5-dev" Description: Define 006: __declspec(x) Name: __declspec(x) diff --git a/parser/output/raylib_api.xml b/parser/output/raylib_api.xml index 51473562c..474bc0473 100644 --- a/parser/output/raylib_api.xml +++ b/parser/output/raylib_api.xml @@ -5,7 +5,7 @@ - + From 047a4da696992722c23f429d8d5805217f268137 Mon Sep 17 00:00:00 2001 From: Jaen Date: Sun, 21 Jul 2024 14:44:34 +0300 Subject: [PATCH 34/41] Fix Carp link - BINDINGS.md (#4175) The current link 404's. Replace it with a fork. --- BINDINGS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BINDINGS.md b/BINDINGS.md index f4bc1f69b..3e840d587 100644 --- a/BINDINGS.md +++ b/BINDINGS.md @@ -150,7 +150,7 @@ These are older raylib bindings that are more than 2 versions old or have not be | [ray.mod](https://github.com/bmx-ng/ray.mod) | 3.0 | [BlitzMax](https://blitzmax.org) | | [raylib-mosaic](https://github.com/pluckyporcupine/raylib-mosaic) | 3.0 | [Mosaic](https://github.com/sal55/langs/tree/master/Mosaic) | | [raylib-xdpw](https://github.com/vtereshkov/raylib-xdpw) | 2.6 | [XD Pascal](https://github.com/vtereshkov/xdpw) | -| [raylib-carp](https://github.com/pluckyporcupine/raylib-carp) | 3.0 | [Carp](https://github.com/carp-lang/Carp) | +| [raylib-carp](https://github.com/sacredbirdman/raylib-carp) | 3.0 | [Carp](https://github.com/carp-lang/Carp) | | [raylib-fb](https://github.com/IchMagBier/raylib-fb) | 3.0 | [FreeBasic](https://www.freebasic.net) | | [raylib-purebasic](https://github.com/D-a-n-i-l-o/raylib-purebasic) | 3.0 | [PureBasic](https://www.purebasic.com) | | [raylib-ats2](https://github.com/mephistopheles-8/raylib-ats2) | 3.0 | [ATS2](http://www.ats-lang.org) | From f1f08861a1dd86cdd054603522a70a4828663a3e Mon Sep 17 00:00:00 2001 From: Colleague Riley Date: Mon, 22 Jul 2024 16:19:09 -0400 Subject: [PATCH 35/41] Update RGFW (#4176) * update RGFW * fix bug with GetCurrentMonitor * update RGFW * update RGFW * clean up merge --- src/external/RGFW.h | 3393 ++++++++++++++++++---------- src/platforms/rcore_desktop_rgfw.c | 49 +- 2 files changed, 2201 insertions(+), 1241 deletions(-) diff --git a/src/external/RGFW.h b/src/external/RGFW.h index 646ecc9a0..5420ccab1 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 + +/* thse OS macros looks better & are standardized */ +/* plus it helps with cross-compiling */ + +#ifdef __EMSCRIPTEN__ + #define RGFW_WEBASM + + #ifndef RGFW_NO_API + #define RGFW_OPENGL + #endif + + #ifdef RGFW_EGL + #undef RGFW_EGL + #endif + + #include + #include #endif #if defined(RGFW_X11) && defined(__APPLE__) -#define RGFW_MACOS_X11 -#undef __APPLE__ + #define RGFW_MACOS_X11 + #undef __APPLE__ #endif -#if defined(_WIN32) && !defined(RGFW_X11) /* (if you're using X11 on windows some how) */ +#if defined(_WIN32) && !defined(RGFW_X11) && !defined(RGFW_WEBASM) /* (if you're using X11 on windows some how) */ + #define RGFW_WINDOWS - /* this name looks better */ - /* plus it helps with cross-compiling because RGFW_X11 won't be accidently defined */ - -#define RGFW_WINDOWS + /* make sure the correct architecture is defined */ + #if defined(_WIN64) + #define _AMD64_ + #undef _X86_ + #else + #undef _AMD64_ + #ifndef _X86_ + #define _X86_ + #endif + #endif -#if defined(_WIN32) && !defined(WIN32) -#define WIN32 -#endif + #ifndef RGFW_NO_XINPUT + #ifdef __MINGW32__ /* try to find the right header */ + #include + #else + #include + #endif + #endif -#if defined(_WIN64) + #if defined(RGFW_DIRECTX) + #include + #include + #include + #include -#ifndef WIN64 -#define WIN64 -#endif + #ifndef __cplusplus + #define __uuidof(T) IID_##T + #endif + #endif -#define _AMD64_ -#undef _X86_ -#else -#undef _AMD64_ -#ifndef _X86_ -#define _X86_ -#endif -#endif - -#ifndef RGFW_NO_XINPUT -#ifdef __MINGW32__ -#include -#else -#include -#endif -#endif - -#else -#if defined(__unix__) || defined(RGFW_MACOS_X11) || defined(RGFW_X11) -#define RGFW_MACOS_X11 -#define RGFW_X11 -#include -#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 + #if defined(__APPLE__) + #warning EGL is not supported for Cocoa, switching back to the native opengl api + #undef RGFW_EGL + #endif + + #include +#elif defined(RGFW_OSMESA) + #ifndef __APPLE__ + #include + #else + #include + #endif #endif -#ifdef 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 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 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!! */ - b8 inFocus; /*if the window is in focus or not (this is always true for MacOS windows due to the api being weird) */ + 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; + u8 lockState; - u16 joystick; /* which joystick this event applies to (if applicable to any) */ + u16 joystick; /* which joystick this event applies to (if applicable to any) */ - 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 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 axisesCount; /* number of axises */ - RGFW_vector axis[2]; /* x, y of axises (-100 to 100) */ - } RGFW_Event; /*!< Event structure for checking/getting events */ + u8 axisesCount; /* number of axises */ + RGFW_point axis[2]; /* x, y of axises (-100 to 100) */ +} RGFW_Event; /*!< Event structure for checking/getting events */ - /* source data for the window (used by the APIs) */ - typedef struct RGFW_window_src { +/* 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 - -#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 - -#ifdef RGFW_OSMESA - OSMesaContext rSurf; -#endif -#endif - -#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 -#endif - -#if defined(RGFW_MACOS) && !defined(RGFW_MACOS_X11) - void* view; /*apple viewpoint thingy*/ -#endif - -#ifdef RGFW_EGL +#elif defined(RGFW_EGL) EGLSurface EGL_surface; EGLDisplay EGL_display; EGLContext EGL_context; #endif #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER) -#ifdef RGFW_WINDOWS + HDC hdcMem; HBITMAP bitmap; #endif -#ifdef RGFW_X11 + 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) 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_rect r; /* the x, y, w and h of the struct */ + + RGFW_point _lastMousePoint; /* last cusor point (for raw mouse data) */ - 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 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 _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); - /*! window managment functions*/ - RGFWDEF void RGFW_window_close(RGFW_window* win); /*!< close the window and free leftover data */ +/* + 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); - RGFWDEF void RGFW_window_move(RGFW_window* win, - RGFW_vector v/* new pos*/ - ); +/* + Tell RGFW_window_eventWait to stop waiting, to be ran from another thread +*/ +RGFWDEF void RGFW_stopCheckEvents(void); - #ifndef RGFW_NO_MONITOR +/*! window managment functions*/ +RGFWDEF void RGFW_window_close(RGFW_window* win); /*!< close the window and free leftover data */ + +/* moves window to a given point */ +RGFWDEF void RGFW_window_move(RGFW_window* win, + RGFW_point v/* new pos*/ +); + +#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); + +/* 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); - #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 +#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 - /*!< make the window the current opengl drawing context */ - RGFWDEF void RGFW_window_makeCurrent(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) */ +/*error handling*/ +RGFWDEF b8 RGFW_Error(void); /* returns true if an error has occurred (doesn't print errors itself) */ - /*!< 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)*/ +/*!< 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_wasPressed(RGFW_window* win, u8 key); /*!< if key was pressed (checks prev keymap only) (key code)*/ +RGFWDEF b8 RGFW_wasPressed(RGFW_window* win, u8 key); /*!< if key was pressed (checks previous state only) (key code)*/ - 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)*/ +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)*/ - RGFWDEF b8 RGFW_isClicked(RGFW_window* win, u8 key); +/* 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 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); +/* 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 */ ); /*! 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 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 */ +RGFWDEF void RGFW_writeClipboard(const char* text, u32 textLen); /*!< write text to the clipboard */ - /* - - - 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_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 - typedef void (* RGFW_dndfunc)(RGFW_window* win, char** droppedFiles, u32 droppedFilesCount); - #else - typedef void (* RGFW_dndfunc)(RGFW_window* win, char droppedFiles[RGFW_MAX_DROPS][RGFW_MAX_PATH], u32 droppedFilesCount); - #endif + + Event callbacks, + these are completely optional, you can use the normal + RGFW_checkEvent() method if you prefer that - 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); +*/ + +/* 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 + typedef void (* RGFW_dndfunc)(RGFW_window* win, char droppedFiles[RGFW_MAX_DROPS][RGFW_MAX_PATH], u32 droppedFilesCount); +#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 */ +/*! 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_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, +/* + key codes and mouse icon enums +*/ - RGFW_Backtick, +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_0, - RGFW_1, - RGFW_2, - RGFW_3, - RGFW_4, - RGFW_5, - RGFW_6, - RGFW_7, - RGFW_8, - RGFW_9, + RGFW_Backtick, - 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_0, + RGFW_1, + RGFW_2, + RGFW_3, + RGFW_4, + RGFW_5, + RGFW_6, + RGFW_7, + RGFW_8, + RGFW_9, - 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_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_Period, - RGFW_Comma, - RGFW_Slash, - RGFW_Bracket, - RGFW_CloseBracket, - RGFW_Semicolon, - RGFW_Return, - RGFW_Quote, - RGFW_BackSlash, + 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_Up, - RGFW_Down, - RGFW_Left, - RGFW_Right, + RGFW_Period, + RGFW_Comma, + RGFW_Slash, + RGFW_Bracket, + RGFW_CloseBracket, + RGFW_Semicolon, + RGFW_Return, + RGFW_Quote, + RGFW_BackSlash, - RGFW_Delete, - RGFW_Insert, - RGFW_End, - RGFW_Home, - RGFW_PageUp, - RGFW_PageDown, + RGFW_Up, + RGFW_Down, + RGFW_Left, + RGFW_Right, - 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, + RGFW_Delete, + RGFW_Insert, + RGFW_End, + RGFW_Home, + RGFW_PageUp, + RGFW_PageDown, - final_key, - }; + 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, - 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, - }; + final_key, +}; + +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, +}; #endif /* RGFW_HEADER */ - /* - Example to get you started : +/* +Example to get you started : - 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 +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 +#define RGFW_IMPLEMENTATION +#include "RGFW.h" + +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}; + +int main() { + RGFW_window* win = RGFW_createWindow("name", RGFW_RECT(500, 500, 500, 500), (u64)0); + + RGFW_window_setIcon(win, icon, RGFW_AREA(3, 3), 4); + + 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_swapBuffers(win); + + glClearColor(0xFF, 0XFF, 0xFF, 0xFF); + glClear(GL_COLOR_BUFFER_BIT); + } + + 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 + + rgfw.c #define RGFW_IMPLEMENTATION #include "RGFW.h" - 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}; + then you can use gcc (or whatever compile you wish to use) to compile the library into object file - int main() { - RGFW_window* win = RGFW_createWindow("name", RGFW_RECT(500, 500, 500, 500), (u64)0); + ex. gcc -c RGFW.c -fPIC - RGFW_window_setIcon(win, icon, RGFW_AREA(3, 3), 4); + after you compile the library into an object file, you can also turn the object file into an static or shared library - 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_swapBuffers(win); - - glClearColor(0xFF, 0XFF, 0xFF, 0xFF); - glClear(GL_COLOR_BUFFER_BIT); - } - - 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 - - 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 - - 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 - - (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, +u8 RGFW_keycodes[] = { + [RGFW_OS_BASED_VALUE(49, 192, 50, DOM_VK_BACK_QUOTE)] = 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(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)] = RGFW_Space, + [RGFW_OS_BASED_VALUE(65, 0x20, 49, DOM_VK_SPACE)] = 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(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)] = 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 - - #if !defined(RGFW_MACOS) - [RGFW_OS_BASED_VALUE(62, 0x5C, 56)] = RGFW_ShiftR, - [RGFW_OS_BASED_VALUE(108, 165, 58)] = 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, - }; - - typedef struct { - b8 current : 1; - b8 prev : 1; - } RGFW_keyState; - - RGFW_keyState RGFW_keyboard[final_key] = { {0, 0} }; + [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, - RGFWDEF u32 RGFW_apiKeyCodeToRGFW(u32 keycode); + [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 - u32 RGFW_apiKeyCodeToRGFW(u32 keycode) { - if (keycode > sizeof(RGFW_keycodes) / sizeof(u8)) - return 0; - - return RGFW_keycodes[keycode]; - } + #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 - 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; - } + [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; + +RGFW_keyState RGFW_keyboard[final_key] = { {0, 0} }; + +RGFWDEF u32 RGFW_apiKeyCodeToRGFW(u32 keycode); + +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); } +/* + 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 +#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; +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; }} +void RGFW_window_checkEvents(RGFW_window* win, i32 waitMS) { + RGFW_window_eventWait(win, waitMS); + + 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); + /* 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); - 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); - - 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)); +} + +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); #if defined(RGFW_WINDOWS) && defined(RGFW_DIRECTX) - RGFW_dxInfo.pDeviceContext->lpVtbl->OMSetRenderTargets(RGFW_dxInfo.pDeviceContext, 1, &win->src.renderTargetView, NULL); + RGFW_dxInfo.pDeviceContext->lpVtbl->OMSetRenderTargets(RGFW_dxInfo.pDeviceContext, 1, &win->src.renderTargetView, NULL); +#elif defined(RGFW_OPENGL) + RGFW_window_makeCurrent_OpenGL(win); #endif +} -#ifdef RGFW_OPENGL - RGFW_window_makeCurrent_OpenGL(win); -#endif - } +void RGFW_window_setGPURender(RGFW_window* win, i8 set) { + if (!set && !(win->_winArgs & RGFW_NO_GPU_RENDER)) + win->_winArgs |= RGFW_NO_GPU_RENDER; - 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; + else 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; - } +void RGFW_window_setCPURender(RGFW_window* win, i8 set) { + if (!set && !(win->_winArgs & RGFW_NO_CPU_RENDER)) + win->_winArgs |= RGFW_NO_CPU_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; + else 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; - } +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_POINT(0, 0)); + RGFW_window_resize(win, screen); +} - RGFW_window_move(win, RGFW_VECTOR(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); - - #ifndef RGFW_MACOS - RGFW_window_moveMouse(win, RGFW_VECTOR(win->r.x + (area.w), win->r.y + (area.h))); - #endif - } - - void RGFW_window_mouseUnhold(RGFW_window* win) { - if ((win->src.winArgs & RGFW_HOLD_MOUSE)) { - win->src.winArgs ^= RGFW_HOLD_MOUSE; - - RGFW_clipCursor(RGFW_RECT(0, 0, 0, 0)); - } - } - - void RGFW_window_checkFPS(RGFW_window* win) { - u64 deltaTime = RGFW_getTimeNS() - win->event.frameTime; - - 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 (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(); - } +void RGFW_window_mouseHold(RGFW_window* win, RGFW_area area) { + if ((win->_winArgs & RGFW_HOLD_MOUSE)) + return; - u32 RGFW_isPressedJS(RGFW_window* win, u16 c, u8 button) { return win->src.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 - 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 (!area.w && !area.h) + area = RGFW_AREA(win->r.w / 2, win->r.h / 2); - 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; + 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->_winArgs & RGFW_HOLD_MOUSE)) { + win->_winArgs ^= RGFW_HOLD_MOUSE; + + RGFW_captureCursor(win, RGFW_RECT(0, 0, 0, 0)); + } +} + +void RGFW_window_checkFPS(RGFW_window* win) { + u64 deltaTime = RGFW_getTimeNS() - win->event.frameTime; + + 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 (sleepTimeMS > 0) { + RGFW_sleep(sleepTimeMS); + win->event.frameTime = 0; + } } - #if defined(RGFW_X11) || defined(RGFW_MACOS) - struct timespec; + 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(); +} - 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); +u32 RGFW_isPressedJS(RGFW_window* win, u16 c, u8 button) { + RGFW_UNUSED(win); + return RGFW_jsPressed[c][button]; +} - void RGFW_window_setDND(RGFW_window* win, b8 allow) { - if (allow && !(win->src.winArgs & RGFW_ALLOW_DND)) - win->src.winArgs |= RGFW_ALLOW_DND; +#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 - else if (!allow && (win->src.winArgs & RGFW_ALLOW_DND)) - win->src.winArgs ^= RGFW_ALLOW_DND; - } - #endif +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; +} + +#if defined(RGFW_X11) || defined(RGFW_MACOS) + struct timespec; + + 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); + + 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; - if (!found) - i = 0; + // NSPasteboard* 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); + ///////////////////////////// + id pasteBoard = objc_msgSend_id(sender, sel_registerName("draggingPasteboard")); - win->event.droppedFilesCount = si_array_len(droppedFiles); + // Get the types of data available on the pasteboard + id types = objc_msgSend_id(pasteBoard, sel_registerName("types")); - u32 y; + // Get the string type for file URLs + id fileURLsType = objc_msgSend_class_char(objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), "NSFilenamesPboardType"); - for (y = 0; y < win->event.droppedFilesCount; y++) { - strncpy(win->event.droppedFiles[y], droppedFiles[y], RGFW_MAX_PATH); + // 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.droppedFiles[y][RGFW_MAX_PATH - 1] = '\0'; + return 0; } + id fileURLs = objc_msgSend_id_id(pasteBoard, sel_registerName("propertyListForType:"), fileURLsType); + int count = ((int (*)(id, SEL))objc_msgSend)(fileURLs, sel_registerName("count")); + + if (count == 0) + return 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 cfc091172..d98c6391d 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 36/41] 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 dd940b36c..9735e267f 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 37/41] 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 ccb53a624..38f9ae8bd 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 38/41] 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 d70e2cde8..60ce58f4b 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) From 5041d20f0064f49a5d552fda40c1f360881f50a0 Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 25 Jul 2024 11:44:49 +0200 Subject: [PATCH 39/41] Update rcore_desktop_glfw.c --- src/platforms/rcore_desktop_glfw.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/platforms/rcore_desktop_glfw.c b/src/platforms/rcore_desktop_glfw.c index d03bac153..8377b880f 100644 --- a/src/platforms/rcore_desktop_glfw.c +++ b/src/platforms/rcore_desktop_glfw.c @@ -1630,15 +1630,16 @@ int InitPlatform(void) char *glfwPlatform = ""; switch (glfwGetPlatform()) { - case GLFW_PLATFORM_WIN32: glfwPlatform = "Win32"; break; - case GLFW_PLATFORM_COCOA: glfwPlatform = "Cocoa"; break; + case GLFW_PLATFORM_WIN32: glfwPlatform = "Win32"; break; + case GLFW_PLATFORM_COCOA: glfwPlatform = "Cocoa"; break; case GLFW_PLATFORM_WAYLAND: glfwPlatform = "Wayland"; break; - case GLFW_PLATFORM_X11: glfwPlatform = "X11"; break; - case GLFW_PLATFORM_NULL: glfwPlatform = "Null"; break; + case GLFW_PLATFORM_X11: glfwPlatform = "X11"; break; + case GLFW_PLATFORM_NULL: glfwPlatform = "Null"; break; + default: break; } #endif - TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (GLFW): Initialized successfully"); + TRACELOG(LOG_INFO, "PLATFORM: DESKTOP (GLFW - %s): Initialized successfully", glfwPlatform); return 0; } From e5a1fc4f20f9daca17a2f76ffe217b1128625d0b Mon Sep 17 00:00:00 2001 From: Dave Green <34277803+SoloByte@users.noreply.github.com> Date: Sat, 27 Jul 2024 20:19:05 +0200 Subject: [PATCH 40/41] No longer set the RL_TEXTURE_FILTER_LINEAR when high dpi flag is enabled. (#4189) --- src/rcore.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/rcore.c b/src/rcore.c index fb71da0f6..af310cfad 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -668,15 +668,7 @@ void InitWindow(int width, int height, const char *title) SetShapesTexture(texture, (Rectangle){ 0.0f, 0.0f, 1.0f, 1.0f }); // WARNING: Module required: rshapes #endif #endif -#if defined(SUPPORT_MODULE_RTEXT) && defined(SUPPORT_DEFAULT_FONT) - if ((CORE.Window.flags & FLAG_WINDOW_HIGHDPI) > 0) - { - // Set default font texture filter for HighDPI (blurry) - // RL_TEXTURE_FILTER_LINEAR - tex filter: BILINEAR, no mipmaps - rlTextureParameters(GetFontDefault().texture.id, RL_TEXTURE_MIN_FILTER, RL_TEXTURE_FILTER_LINEAR); - rlTextureParameters(GetFontDefault().texture.id, RL_TEXTURE_MAG_FILTER, RL_TEXTURE_FILTER_LINEAR); - } -#endif + CORE.Time.frameCounter = 0; CORE.Window.shouldClose = false; From 9e39788e077f1d35c5fe54600f2143423a80bb3d Mon Sep 17 00:00:00 2001 From: maxmutant <32498872+maxmutant@users.noreply.github.com> Date: Sun, 28 Jul 2024 21:07:47 +0100 Subject: [PATCH 41/41] [rcore] fix gamepad axis movement and its automation event recording (#4184) * [rcore] fix gamepad axis movement and its automation event recording This commit fixes 2 issues: - Automation events aren't recorded for negative axis movements on gamepads (e.g. stick going left/up) - 'GetGamepadAxisMovement' drift check isn't working correctly for triggers. Axis values between [-0.1, 0.1] are clamped to 0.0 Behaviour change: - 'GetGamepadAxisMovement' returns default value for each axis, even if gamepad isn't attached. * [rcore] inline body of 'GetGamepadAxisMovementDefault' and remove it --- src/rcore.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/rcore.c b/src/rcore.c index af310cfad..b4bc19f34 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -2952,10 +2952,14 @@ int GetGamepadAxisCount(int gamepad) // Get axis movement vector for a gamepad float GetGamepadAxisMovement(int gamepad, int axis) { - float value = 0; + float value = (axis == GAMEPAD_AXIS_LEFT_TRIGGER || axis == GAMEPAD_AXIS_RIGHT_TRIGGER)? -1.0f : 0.0f; - if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (axis < MAX_GAMEPAD_AXIS) && - (fabsf(CORE.Input.Gamepad.axisState[gamepad][axis]) > 0.1f)) value = CORE.Input.Gamepad.axisState[gamepad][axis]; // 0.1f = GAMEPAD_AXIS_MINIMUM_DRIFT/DELTA + if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (axis < MAX_GAMEPAD_AXIS)) { + float movement = value < 0.0f ? CORE.Input.Gamepad.axisState[gamepad][axis] : fabs(CORE.Input.Gamepad.axisState[gamepad][axis]); + + // 0.1f = GAMEPAD_AXIS_MINIMUM_DRIFT/DELTA + if (movement > value + 0.1f) value = CORE.Input.Gamepad.axisState[gamepad][axis]; + } return value; } @@ -3599,7 +3603,8 @@ static void RecordAutomationEvent(void) for (int axis = 0; axis < MAX_GAMEPAD_AXIS; axis++) { // Event type: INPUT_GAMEPAD_AXIS_MOTION - if (CORE.Input.Gamepad.axisState[gamepad][axis] > 0.1f) + float defaultMovement = (axis == GAMEPAD_AXIS_LEFT_TRIGGER || axis == GAMEPAD_AXIS_RIGHT_TRIGGER)? -1.0f : 0.0f; + if (GetGamepadAxisMovement(gamepad, axis) != defaultMovement) { currentEventList->events[currentEventList->count].frame = CORE.Time.frameCounter; currentEventList->events[currentEventList->count].type = INPUT_GAMEPAD_AXIS_MOTION;