Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds BORDERLESS_WINDOWED_MODE for PLATFORM_DESKTOP #3216

Merged
merged 1 commit into from Aug 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/raylib.h
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,7 @@ typedef enum {
FLAG_WINDOW_TRANSPARENT = 0x00000010, // Set to allow transparent framebuffer
FLAG_WINDOW_HIGHDPI = 0x00002000, // Set to support HighDPI
FLAG_WINDOW_MOUSE_PASSTHROUGH = 0x00004000, // Set to support mouse passthrough, only supported when FLAG_WINDOW_UNDECORATED
FLAG_BORDERLESS_WINDOWED_MODE = 0x00008000, // Set to run program in borderless windowed mode
FLAG_MSAA_4X_HINT = 0x00000020, // Set to try enabling MSAA 4X
FLAG_INTERLACED_HINT = 0x00010000 // Set to try enabling interlaced video format (for V3D)
} ConfigFlags;
Expand Down Expand Up @@ -947,6 +948,7 @@ RLAPI bool IsWindowState(unsigned int flag); // Check if on
RLAPI void SetWindowState(unsigned int flags); // Set window configuration state using flags (only PLATFORM_DESKTOP)
RLAPI void ClearWindowState(unsigned int flags); // Clear window configuration state flags
RLAPI void ToggleFullscreen(void); // Toggle window state: fullscreen/windowed (only PLATFORM_DESKTOP)
RLAPI void ToggleBorderlessWindowed(void); // Toggle window state: borderless windowed (only PLATFORM_DESKTOP)
RLAPI void MaximizeWindow(void); // Set window state: maximized, if resizable (only PLATFORM_DESKTOP)
RLAPI void MinimizeWindow(void); // Set window state: minimized, if resizable (only PLATFORM_DESKTOP)
RLAPI void RestoreWindow(void); // Set window state: not minimized/maximized (only PLATFORM_DESKTOP)
Expand Down
92 changes: 92 additions & 0 deletions src/rcore.c
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,8 @@ typedef struct CoreData {
Size render; // Framebuffer width and height (render area, including black bars if required)
Point renderOffset; // Offset from render area (must be divided by 2)
Matrix screenScale; // Matrix to scale screen (framebuffer rendering)
Point previousPosition; // Previous screen position (required on borderless windowed toggle)
Size previousScreen; // Previous screen size (required on borderless windowed toggle)

char **dropFilepaths; // Store dropped files paths pointers (provided by GLFW)
unsigned int dropFileCount; // Count dropped files strings
Expand Down Expand Up @@ -1324,6 +1326,82 @@ void ToggleFullscreen(void)
#endif
}

// Toggle borderless windowed mode (only PLATFORM_DESKTOP)
void ToggleBorderlessWindowed(void)
{
#if defined(PLATFORM_DESKTOP)
// Leave fullscreen before attempting to set borderless windowed mode and get screen position from it
bool wasOnFullscreen = false;
if (CORE.Window.fullscreen)
{
CORE.Window.previousPosition = CORE.Window.position;
ToggleFullscreen();
wasOnFullscreen = true;
}

const int monitor = GetCurrentMonitor();
int monitorCount;
GLFWmonitor **monitors = glfwGetMonitors(&monitorCount);
if ((monitor >= 0) && (monitor < monitorCount))
{
const GLFWvidmode *mode = glfwGetVideoMode(monitors[monitor]);
if (mode)
{
if (!IsWindowState(FLAG_BORDERLESS_WINDOWED_MODE))
{
// Store screen position and size
// NOTE: If it was on fullscreen, screen position was already stored, so skip setting it here
if (!wasOnFullscreen) glfwGetWindowPos(CORE.Window.handle, &CORE.Window.previousPosition.x, &CORE.Window.previousPosition.y);
CORE.Window.previousScreen = CORE.Window.screen;

// Set undecorated and topmost modes and flags
glfwSetWindowAttrib(CORE.Window.handle, GLFW_DECORATED, GLFW_FALSE);
CORE.Window.flags |= FLAG_WINDOW_UNDECORATED;
glfwSetWindowAttrib(CORE.Window.handle, GLFW_FLOATING, GLFW_TRUE);
CORE.Window.flags |= FLAG_WINDOW_TOPMOST;

// Get monitor position and size
int monitorPosX = 0;
int monitorPosY = 0;
glfwGetMonitorPos(monitors[monitor], &monitorPosX, &monitorPosY);
const int monitorWidth = mode->width;
const int monitorHeight = mode->height;
glfwSetWindowSize(CORE.Window.handle, monitorWidth, monitorHeight);

// Set screen position and size
glfwSetWindowPos(CORE.Window.handle, monitorPosX, monitorPosY);
glfwSetWindowSize(CORE.Window.handle, monitorWidth, monitorHeight);
raysan5 marked this conversation as resolved.
Show resolved Hide resolved

// Refocus window
glfwFocusWindow(CORE.Window.handle);

CORE.Window.flags |= FLAG_BORDERLESS_WINDOWED_MODE;
}
else
{
// Remove topmost and undecorated modes and flags
glfwSetWindowAttrib(CORE.Window.handle, GLFW_FLOATING, GLFW_FALSE);
CORE.Window.flags &= ~FLAG_WINDOW_TOPMOST;
glfwSetWindowAttrib(CORE.Window.handle, GLFW_DECORATED, GLFW_TRUE);
CORE.Window.flags &= ~FLAG_WINDOW_UNDECORATED;

// Return previous screen size and position
// NOTE: The order matters here, it must set size first, then set position, otherwise the screen will be positioned incorrectly
glfwSetWindowSize(CORE.Window.handle, CORE.Window.previousScreen.width, CORE.Window.previousScreen.height);
glfwSetWindowPos(CORE.Window.handle, CORE.Window.previousPosition.x, CORE.Window.previousPosition.y);

// Refocus window
glfwFocusWindow(CORE.Window.handle);

CORE.Window.flags &= ~FLAG_BORDERLESS_WINDOWED_MODE;
}
}
else TRACELOG(LOG_WARNING, "GLFW: Failed to find video mode for selected monitor");
}
else TRACELOG(LOG_WARNING, "GLFW: Failed to find selected monitor");
#endif
}

// Set window state: maximized, if resizable (only PLATFORM_DESKTOP)
void MaximizeWindow(void)
{
Expand Down Expand Up @@ -1373,6 +1451,13 @@ void SetWindowState(unsigned int flags)
CORE.Window.flags |= FLAG_VSYNC_HINT;
}

// State change: FLAG_BORDERLESS_WINDOWED_MODE
// NOTE: This must be handled before FLAG_FULLSCREEN_MODE because ToggleBorderlessWindowed() needs to get some fullscreen values if fullscreen is running
if (((CORE.Window.flags & FLAG_BORDERLESS_WINDOWED_MODE) != (flags & FLAG_BORDERLESS_WINDOWED_MODE)) && ((flags & FLAG_BORDERLESS_WINDOWED_MODE) > 0))
{
ToggleBorderlessWindowed(); // NOTE: Window state flag updated inside function
}

// State change: FLAG_FULLSCREEN_MODE
if ((CORE.Window.flags & FLAG_FULLSCREEN_MODE) != (flags & FLAG_FULLSCREEN_MODE))
{
Expand Down Expand Up @@ -1483,6 +1568,13 @@ void ClearWindowState(unsigned int flags)
CORE.Window.flags &= ~FLAG_VSYNC_HINT;
}

// State change: FLAG_BORDERLESS_WINDOWED_MODE
// NOTE: This must be handled before FLAG_FULLSCREEN_MODE because ToggleBorderlessWindowed() needs to get some fullscreen values if fullscreen is running
if (((CORE.Window.flags & FLAG_BORDERLESS_WINDOWED_MODE) > 0) && ((flags & FLAG_BORDERLESS_WINDOWED_MODE) > 0))
{
ToggleBorderlessWindowed(); // NOTE: Window state flag updated inside function
}

// State change: FLAG_FULLSCREEN_MODE
if (((CORE.Window.flags & FLAG_FULLSCREEN_MODE) > 0) && ((flags & FLAG_FULLSCREEN_MODE) > 0))
{
Expand Down
Loading