From 452cac33b86f8ecd87788ba0eb0633d779c155d1 Mon Sep 17 00:00:00 2001 From: Maicon Santana Date: Wed, 1 Oct 2025 17:31:03 +0100 Subject: [PATCH] [examples] Add `core_monitor_change` (#5215) * Add core monitor change example * Add monitor drawing and more information * Update monitor information every frame * Show info and window position inside the rectangle --- examples/core/core_monitor_change.c | 170 ++++++++++++++++++++++++++ examples/core/core_monitor_change.png | Bin 0 -> 17430 bytes 2 files changed, 170 insertions(+) create mode 100644 examples/core/core_monitor_change.c create mode 100644 examples/core/core_monitor_change.png diff --git a/examples/core/core_monitor_change.c b/examples/core/core_monitor_change.c new file mode 100644 index 000000000..8983556af --- /dev/null +++ b/examples/core/core_monitor_change.c @@ -0,0 +1,170 @@ +/******************************************************************************************* +* +* raylib [core] example - monitor change +* +* Example complexity rating: [★☆☆☆] 1/4 +* +* Example originally created with raylib 5.5, last time updated with raylib 5.6 +* +* Example contributed by Maicon Santana (@maiconpintoabreu) and reviewed by Ramon Santamaria (@raysan5) +* +* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, +* BSD-like license that allows static linking with closed source software +* +* Copyright (c) 2025-2025 Maicon Santana (@maiconpintoabreu) +* +********************************************************************************************/ + +#include "raylib.h" + +#define MAX_MONITORS 10 + +// Monitor Details +typedef struct Monitor { + Vector2 position; + char *name; + int width; + int height; + int physicalWidth; + int physicalHeight; + int refreshRate; +} Monitor; + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + Monitor monitors[MAX_MONITORS] = { 0 }; + + InitWindow(screenWidth, screenHeight, "raylib [core] example - monitor change"); + + int currentMonitorIndex = GetCurrentMonitor(); + int monitorCount = 0; + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + + // Variables to find the max x and Y to calculate the scale + int maxWidth = 1; + int maxHeight = 1; + + // Monitor offset is to fix when monitor position x is negative + int monitorOffsetX = 0; + + // Rebuild monitors array every frame + monitorCount = GetMonitorCount(); + for (int i = 0; i < monitorCount; i++) + { + monitors[i] = (Monitor){ + GetMonitorPosition(i), + GetMonitorName(i), + GetMonitorWidth(i), + GetMonitorHeight(i), + GetMonitorPhysicalWidth(i), + GetMonitorPhysicalHeight(i), + GetMonitorRefreshRate(i) + }; + if (monitors[i].position.x < monitorOffsetX) monitorOffsetX = monitors[i].position.x*-1; + + const int width = monitors[i].position.x + monitors[i].width; + const int height = monitors[i].position.y + monitors[i].height; + + if (maxWidth < width) maxWidth = width; + if (maxHeight < height) maxHeight = height; + } + + if (IsKeyPressed(KEY_ENTER) && monitorCount > 1) + { + currentMonitorIndex += 1; + + // Set index to 0 if the last one + if(currentMonitorIndex == monitorCount) currentMonitorIndex = 0; + + SetWindowMonitor(currentMonitorIndex); // Move window to currentMonitorIndex + } + else + { + // Get currentMonitorIndex if manually moved + currentMonitorIndex = GetCurrentMonitor(); + } + const Monitor currentMonitor = monitors[currentMonitorIndex]; + + float monitorScale = 0.6; + + if(maxHeight > maxWidth + monitorOffsetX) monitorScale *= ((float)screenHeight/(float)maxHeight); + else monitorScale *= ((float)screenWidth/(float)(maxWidth + monitorOffsetX)); + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + DrawText("Press [Enter] to move window to next monitor available", 20, 20, 20, DARKGRAY); + + DrawRectangleLines(20, 60, screenWidth - 40, screenHeight - 100, DARKGRAY); + + // Draw Monitor Rectangles with information inside + for (int i = 0; i < monitorCount; i++) + { + // Calculate retangle position and size using monitorScale + const Rectangle rec = (Rectangle){ + (monitors[i].position.x + monitorOffsetX) * monitorScale + 140, + monitors[i].position.y * monitorScale + 80, + monitors[i].width * monitorScale, + monitors[i].height * monitorScale + }; + + // Draw monitor name and information inside the rectangle + DrawText(TextFormat("[%i] %s", i, monitors[i].name), rec.x + 10, rec.y + (int)(100*monitorScale), (int)(120*monitorScale), BLUE); + DrawText( + TextFormat("Resolution: [%ipx x %ipx]\nRefreshRate: [%ihz]\nPhysical Size: [%imm x %imm]\nPosition: %3.0f x %3.0f", + monitors[i].width, + monitors[i].height, + monitors[i].refreshRate, + monitors[i].physicalWidth, + monitors[i].physicalHeight, + monitors[i].position.x, + monitors[i].position.y + ), rec.x + 10, rec.y + (int)(200*monitorScale), (int)(120*monitorScale), DARKGRAY); + + // Highlight current monitor + if (i == currentMonitorIndex) + { + DrawRectangleLinesEx(rec, 5, RED); + Vector2 windowPosition = (Vector2){ (GetWindowPosition().x + monitorOffsetX)*monitorScale + 140, GetWindowPosition().y*monitorScale + 80 }; + + // Draw window position based on monitors + DrawRectangleV(windowPosition, (Vector2){screenWidth * monitorScale, screenHeight * monitorScale}, Fade(GREEN, 0.5)); + } + else + { + DrawRectangleLinesEx(rec, 5, GRAY); + } + + } + + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} \ No newline at end of file diff --git a/examples/core/core_monitor_change.png b/examples/core/core_monitor_change.png new file mode 100644 index 0000000000000000000000000000000000000000..81f9eed875bf8edf2c11e911cad5265418e054ed GIT binary patch literal 17430 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 Zly29Kl|6^!7#J8BJYD@<);T3K0RS~3s5t-t literal 0 HcmV?d00001