From 3e4c89eaf0b856695046fec561fadeeeae514ce4 Mon Sep 17 00:00:00 2001 From: PowerfulBacon <26465327+PowerfulBacon@users.noreply.github.com> Date: Fri, 5 Jun 2026 22:06:45 +0100 Subject: [PATCH 1/4] Borderless windows --- .../Graphics/Clyde/Clyde.Windowing.cs | 33 ++++++++++++++----- Robust.Client/Graphics/Clyde/ClydeHeadless.cs | 20 ++++++----- .../Clyde/Windowing/IWindowingImpl.cs | 5 +-- .../Graphics/Clyde/Windowing/Sdl3.Window.cs | 33 ++++++++++++++----- .../Clyde/Windowing/Sdl3.WindowThread.cs | 18 +++++++--- Robust.Client/Graphics/IClydeWindow.cs | 5 +-- .../Graphics/WindowCreateParameters.cs | 1 + 7 files changed, 81 insertions(+), 34 deletions(-) diff --git a/Robust.Client/Graphics/Clyde/Clyde.Windowing.cs b/Robust.Client/Graphics/Clyde/Clyde.Windowing.cs index 62cb3cdb4f4..8b73d05f63c 100644 --- a/Robust.Client/Graphics/Clyde/Clyde.Windowing.cs +++ b/Robust.Client/Graphics/Clyde/Clyde.Windowing.cs @@ -1,10 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Numerics; -using System.Runtime.InteropServices; -using System.Threading; -using System.Threading.Tasks; using Robust.Client.Input; using Robust.Client.UserInterface; using Robust.Shared; @@ -14,13 +7,19 @@ using Robust.Shared.Utility; using SixLabors.ImageSharp; using SixLabors.ImageSharp.PixelFormats; +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Numerics; +using System.Threading; +using System.Threading.Tasks; using TerraFX.Interop.Windows; using FrameEventArgs = Robust.Shared.Timing.FrameEventArgs; using GL = OpenToolkit.Graphics.OpenGL4.GL; namespace Robust.Client.Graphics.Clyde { - internal partial class Clyde + internal partial class Clyde { private readonly List _windows = new(); private readonly List _windowHandles = new(); @@ -282,6 +281,13 @@ public void SetWindowTitle(string title) _windowing!.WindowSetTitle(_mainWindow!, title); } + private void SetWindowTitleBarVisible(WindowReg reg, bool visible) + { + DebugTools.AssertNotNull(_windowing); + + _windowing!.WindowSetTitleBarVisible(reg, visible); + } + public void SetWindowMonitor(IClydeMonitor monitor) { DebugTools.AssertNotNull(_windowing); @@ -342,6 +348,7 @@ public IClydeWindow CreateWindow(WindowCreateParameters parameters) _mainWindow = reg; reg.IsVisible = parameters.Visible; + reg.IsTitleBarVisible = parameters.TitleBarVisible; _windows.Add(reg); _windowHandles.Add(reg.Handle); @@ -415,7 +422,7 @@ public bool VsyncEnabled private void WindowModeChanged(int mode) { - _windowMode = (WindowMode) mode; + _windowMode = (WindowMode)mode; _windowing?.UpdateMainWindowMode(); } @@ -495,6 +502,7 @@ private abstract class WindowReg public bool IsMinimized; public string Title = ""; public bool IsVisible; + public bool IsTitleBarVisible; public IClydeWindow? Owner; public bool DisposeOnClose; @@ -554,6 +562,12 @@ public bool IsVisible set => _clyde.SetWindowVisible(Reg, value); } + public bool IsTitleBarVisible + { + get => Reg.IsTitleBarVisible; + set => _clyde.SetWindowTitleBarVisible(Reg, value); + } + public Vector2 ContentScale => Reg.WindowScale; public bool DisposeOnClose @@ -607,6 +621,7 @@ public void SetWindowProgress(WindowProgressState state, float value) } public nint? WindowsHWnd => _clyde._windowing!.WindowGetWin32Window(Reg); + } private sealed class MonitorHandle : IClydeMonitor diff --git a/Robust.Client/Graphics/Clyde/ClydeHeadless.cs b/Robust.Client/Graphics/Clyde/ClydeHeadless.cs index 093527e6b99..1a2d7f33c22 100644 --- a/Robust.Client/Graphics/Clyde/ClydeHeadless.cs +++ b/Robust.Client/Graphics/Clyde/ClydeHeadless.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Numerics; -using System.Threading.Tasks; using JetBrains.Annotations; -using Robust.Client.Audio; using Robust.Client.Input; using Robust.Client.ResourceManagement; using Robust.Client.UserInterface; @@ -16,6 +10,11 @@ using Robust.Shared.Timing; using SixLabors.ImageSharp; using SixLabors.ImageSharp.PixelFormats; +using System; +using System.Collections.Generic; +using System.IO; +using System.Numerics; +using System.Threading.Tasks; using Color = Robust.Shared.Maths.Color; namespace Robust.Client.Graphics.Clyde @@ -47,7 +46,7 @@ public ClydeHeadless() SixLabors.ImageSharp.Configuration.Default.PreferContiguousImageBuffers = true; var mainRt = new DummyRenderWindow(this); - var window = new DummyWindow(mainRt) {Id = new WindowId(1)}; + var window = new DummyWindow(mainRt) { Id = new WindowId(1) }; _windows.Add(window); MainWindow = window; @@ -111,6 +110,10 @@ public void SetWindowTitle(string title) // Nada. } + public void SetWindowTitleBarVisible(bool visible) + { + } + public void SetWindowMonitor(IClydeMonitor monitor) { // Nada. @@ -283,7 +286,7 @@ public void TextInputStop() // Nada. } - public ClydeHandle LoadShader(ParsedShader shader, string? name = null, Dictionary? defines = null) + public ClydeHandle LoadShader(ParsedShader shader, string? name = null, Dictionary? defines = null) { return default; } @@ -579,6 +582,7 @@ public DummyWindow(IRenderTarget renderTarget) public bool IsFocused => false; public bool IsMinimized => false; public bool IsVisible { get; set; } = true; + public bool IsTitleBarVisible { get; set; } = true; public Vector2 ContentScale => Vector2.One; public bool DisposeOnClose { get; set; } public event Action? RequestClosed { add { } remove { } } diff --git a/Robust.Client/Graphics/Clyde/Windowing/IWindowingImpl.cs b/Robust.Client/Graphics/Clyde/Windowing/IWindowingImpl.cs index 34b5eae6d4c..e8426f89755 100644 --- a/Robust.Client/Graphics/Clyde/Windowing/IWindowingImpl.cs +++ b/Robust.Client/Graphics/Clyde/Windowing/IWindowingImpl.cs @@ -1,9 +1,9 @@ -using System; -using System.Threading.Tasks; using Robust.Client.Input; using Robust.Shared.Maths; using SixLabors.ImageSharp; using SixLabors.ImageSharp.PixelFormats; +using System; +using System.Threading.Tasks; namespace Robust.Client.Graphics.Clyde { @@ -38,6 +38,7 @@ private interface IWindowingImpl void WindowDestroy(WindowReg reg); void WindowSetTitle(WindowReg window, string title); + void WindowSetTitleBarVisible(WindowReg window, bool visible); void WindowSetMonitor(WindowReg window, IClydeMonitor monitor); void WindowSetSize(WindowReg window, Vector2i size); void WindowSetVisible(WindowReg window, bool visible); diff --git a/Robust.Client/Graphics/Clyde/Windowing/Sdl3.Window.cs b/Robust.Client/Graphics/Clyde/Windowing/Sdl3.Window.cs index dd12203219d..acc2dde822a 100644 --- a/Robust.Client/Graphics/Clyde/Windowing/Sdl3.Window.cs +++ b/Robust.Client/Graphics/Clyde/Windowing/Sdl3.Window.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Numerics; using System.Runtime.CompilerServices; using System.Threading.Tasks; @@ -265,14 +265,14 @@ private void WinThreadWinDestroy(CmdWinDestroy cmd) switch (_videoDriver) { case SdlVideoDriver.Windows: - { - var hWnd = SDL.SDL_GetPointerProperty( - props, - SDL.SDL_PROP_WINDOW_WIN32_HWND_POINTER, - 0); - WsiShared.SetWindowStyleNoTitleOptionsWindows((HWND)hWnd); - break; - } + { + var hWnd = SDL.SDL_GetPointerProperty( + props, + SDL.SDL_PROP_WINDOW_WIN32_HWND_POINTER, + 0); + WsiShared.SetWindowStyleNoTitleOptionsWindows((HWND)hWnd); + break; + } case SdlVideoDriver.X11: unsafe { @@ -415,11 +415,26 @@ public void WindowSetTitle(WindowReg window, string title) }); } + public void WindowSetTitleBarVisible(WindowReg window, bool visible) + { + window.IsTitleBarVisible = visible; + SendCmd(new CmdWinSetTitleBarVisible + { + Window = WinPtr(window), + Visible = visible, + }); + } + private static void WinThreadWinSetTitle(CmdWinSetTitle cmd) { SDL.SDL_SetWindowTitle(cmd.Window, cmd.Title); } + private static void WinThreadWinSetTitleBarVisible(CmdWinSetTitleBarVisible cmd) + { + SDL.SDL_SetWindowBordered(cmd.Window, cmd.Visible); + } + public void WindowSetMonitor(WindowReg window, IClydeMonitor monitor) { // API isn't really used and kinda wack, don't feel like figuring it out for SDL3 yet. diff --git a/Robust.Client/Graphics/Clyde/Windowing/Sdl3.WindowThread.cs b/Robust.Client/Graphics/Clyde/Windowing/Sdl3.WindowThread.cs index ebf9820d070..26b2d4695d8 100644 --- a/Robust.Client/Graphics/Clyde/Windowing/Sdl3.WindowThread.cs +++ b/Robust.Client/Graphics/Clyde/Windowing/Sdl3.WindowThread.cs @@ -1,12 +1,12 @@ -using System; -using System.Runtime.CompilerServices; -using System.Threading.Channels; -using System.Threading.Tasks; using Robust.Shared; using Robust.Shared.Maths; using SDL3; using SixLabors.ImageSharp; using SixLabors.ImageSharp.PixelFormats; +using System; +using System.Runtime.CompilerServices; +using System.Threading.Channels; +using System.Threading.Tasks; namespace Robust.Client.Graphics.Clyde; @@ -81,6 +81,10 @@ private void ProcessSdl3Cmd(CmdBase cmdb) WinThreadWinSetTitle(cmd); break; + case CmdWinSetTitleBarVisible cmd: + WinThreadWinSetTitleBarVisible(cmd); + break; + case CmdSetClipboard cmd: WinThreadSetClipboard(cmd); break; @@ -291,6 +295,12 @@ private sealed class CmdWinSetTitle : CmdBase public required string Title; } + private sealed class CmdWinSetTitleBarVisible : CmdBase + { + public nint Window; + public required bool Visible; + } + private sealed class CmdCursorCreate : CmdBase { public required Image Bytes; diff --git a/Robust.Client/Graphics/IClydeWindow.cs b/Robust.Client/Graphics/IClydeWindow.cs index 257bc10b702..15e6f5e79e7 100644 --- a/Robust.Client/Graphics/IClydeWindow.cs +++ b/Robust.Client/Graphics/IClydeWindow.cs @@ -1,8 +1,8 @@ -using System; -using System.Numerics; using Robust.Shared.Map; using Robust.Shared.Maths; using SDL3; +using System; +using System.Numerics; namespace Robust.Client.Graphics { @@ -20,6 +20,7 @@ public interface IClydeWindow : IDisposable bool IsFocused { get; } bool IsMinimized { get; } bool IsVisible { get; set; } + bool IsTitleBarVisible { get; set; } Vector2 ContentScale { get; } /// diff --git a/Robust.Client/Graphics/WindowCreateParameters.cs b/Robust.Client/Graphics/WindowCreateParameters.cs index 171d4ef83b5..d64a305215e 100644 --- a/Robust.Client/Graphics/WindowCreateParameters.cs +++ b/Robust.Client/Graphics/WindowCreateParameters.cs @@ -9,6 +9,7 @@ public sealed class WindowCreateParameters public string Title = ""; public bool Maximized; public bool Visible = true; + public bool TitleBarVisible = true; public IClydeMonitor? Monitor; public bool Fullscreen; From 565d0d4a8d24a0ff9e58ae935b6a07f1e6a3f233 Mon Sep 17 00:00:00 2001 From: PowerfulBacon <26465327+PowerfulBacon@users.noreply.github.com> Date: Sat, 6 Jun 2026 07:35:17 +0100 Subject: [PATCH 2/4] Apply suggestion from @PowerfulBacon --- Robust.Client/Graphics/Clyde/Windowing/Sdl3.Window.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Robust.Client/Graphics/Clyde/Windowing/Sdl3.Window.cs b/Robust.Client/Graphics/Clyde/Windowing/Sdl3.Window.cs index acc2dde822a..6bf5f49ae75 100644 --- a/Robust.Client/Graphics/Clyde/Windowing/Sdl3.Window.cs +++ b/Robust.Client/Graphics/Clyde/Windowing/Sdl3.Window.cs @@ -415,6 +415,12 @@ public void WindowSetTitle(WindowReg window, string title) }); } + + private static void WinThreadWinSetTitle(CmdWinSetTitle cmd) + { + SDL.SDL_SetWindowTitle(cmd.Window, cmd.Title); + } + public void WindowSetTitleBarVisible(WindowReg window, bool visible) { window.IsTitleBarVisible = visible; @@ -425,11 +431,6 @@ public void WindowSetTitleBarVisible(WindowReg window, bool visible) }); } - private static void WinThreadWinSetTitle(CmdWinSetTitle cmd) - { - SDL.SDL_SetWindowTitle(cmd.Window, cmd.Title); - } - private static void WinThreadWinSetTitleBarVisible(CmdWinSetTitleBarVisible cmd) { SDL.SDL_SetWindowBordered(cmd.Window, cmd.Visible); From 81bb5d470d6aeef3c21ff617ceb3055545c08c27 Mon Sep 17 00:00:00 2001 From: PowerfulBacon <26465327+PowerfulBacon@users.noreply.github.com> Date: Tue, 9 Jun 2026 18:34:34 +0100 Subject: [PATCH 3/4] Adds in a release note --- RELEASE-NOTES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index e60a7b1ed48..090015d5978 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -39,7 +39,7 @@ END TEMPLATE--> ### New features -*None yet* +* Added the ability to set Clyde windows to borderless mode. ### Bugfixes From 28819ca65ecbb4dbc11a2969da3d03cc940d8d2f Mon Sep 17 00:00:00 2001 From: PowerfulBacon <26465327+PowerfulBacon@users.noreply.github.com> Date: Tue, 9 Jun 2026 19:34:51 +0100 Subject: [PATCH 4/4] titlebar => bordered --- Robust.Client/Graphics/Clyde/Clyde.Windowing.cs | 14 +++++++------- Robust.Client/Graphics/Clyde/ClydeHeadless.cs | 2 +- .../Graphics/Clyde/Windowing/IWindowingImpl.cs | 10 ++++++++-- .../Graphics/Clyde/Windowing/Sdl3.Window.cs | 10 +++++----- .../Graphics/Clyde/Windowing/Sdl3.WindowThread.cs | 6 +++--- Robust.Client/Graphics/IClydeWindow.cs | 5 ++++- 6 files changed, 28 insertions(+), 19 deletions(-) diff --git a/Robust.Client/Graphics/Clyde/Clyde.Windowing.cs b/Robust.Client/Graphics/Clyde/Clyde.Windowing.cs index 8b73d05f63c..3768211b34c 100644 --- a/Robust.Client/Graphics/Clyde/Clyde.Windowing.cs +++ b/Robust.Client/Graphics/Clyde/Clyde.Windowing.cs @@ -281,11 +281,11 @@ public void SetWindowTitle(string title) _windowing!.WindowSetTitle(_mainWindow!, title); } - private void SetWindowTitleBarVisible(WindowReg reg, bool visible) + private void SetWindowBordered(WindowReg reg, bool visible) { DebugTools.AssertNotNull(_windowing); - _windowing!.WindowSetTitleBarVisible(reg, visible); + _windowing!.WindowSetBordered(reg, visible); } public void SetWindowMonitor(IClydeMonitor monitor) @@ -348,7 +348,7 @@ public IClydeWindow CreateWindow(WindowCreateParameters parameters) _mainWindow = reg; reg.IsVisible = parameters.Visible; - reg.IsTitleBarVisible = parameters.TitleBarVisible; + reg.IsBordered = parameters.TitleBarVisible; _windows.Add(reg); _windowHandles.Add(reg.Handle); @@ -502,7 +502,7 @@ private abstract class WindowReg public bool IsMinimized; public string Title = ""; public bool IsVisible; - public bool IsTitleBarVisible; + public bool IsBordered; public IClydeWindow? Owner; public bool DisposeOnClose; @@ -562,10 +562,10 @@ public bool IsVisible set => _clyde.SetWindowVisible(Reg, value); } - public bool IsTitleBarVisible + public bool IsBordered { - get => Reg.IsTitleBarVisible; - set => _clyde.SetWindowTitleBarVisible(Reg, value); + get => Reg.IsBordered; + set => _clyde.SetWindowBordered(Reg, value); } public Vector2 ContentScale => Reg.WindowScale; diff --git a/Robust.Client/Graphics/Clyde/ClydeHeadless.cs b/Robust.Client/Graphics/Clyde/ClydeHeadless.cs index 1a2d7f33c22..76fd1600cb6 100644 --- a/Robust.Client/Graphics/Clyde/ClydeHeadless.cs +++ b/Robust.Client/Graphics/Clyde/ClydeHeadless.cs @@ -582,7 +582,7 @@ public DummyWindow(IRenderTarget renderTarget) public bool IsFocused => false; public bool IsMinimized => false; public bool IsVisible { get; set; } = true; - public bool IsTitleBarVisible { get; set; } = true; + public bool IsBordered { get; set; } = true; public Vector2 ContentScale => Vector2.One; public bool DisposeOnClose { get; set; } public event Action? RequestClosed { add { } remove { } } diff --git a/Robust.Client/Graphics/Clyde/Windowing/IWindowingImpl.cs b/Robust.Client/Graphics/Clyde/Windowing/IWindowingImpl.cs index e8426f89755..6ef3f47d368 100644 --- a/Robust.Client/Graphics/Clyde/Windowing/IWindowingImpl.cs +++ b/Robust.Client/Graphics/Clyde/Windowing/IWindowingImpl.cs @@ -21,7 +21,7 @@ private interface IWindowingImpl void TerminateWindowLoop(); // Event pump - void ProcessEvents(bool single=false); + void ProcessEvents(bool single = false); void FlushDispose(); // Cursor @@ -38,7 +38,13 @@ private interface IWindowingImpl void WindowDestroy(WindowReg reg); void WindowSetTitle(WindowReg window, string title); - void WindowSetTitleBarVisible(WindowReg window, bool visible); + /// + /// Toggles the visibility of the window's border, including the title + /// bar. + /// + /// The window to affect. + /// The visibility of the border & titlebar to be set. + void WindowSetBordered(WindowReg window, bool visible); void WindowSetMonitor(WindowReg window, IClydeMonitor monitor); void WindowSetSize(WindowReg window, Vector2i size); void WindowSetVisible(WindowReg window, bool visible); diff --git a/Robust.Client/Graphics/Clyde/Windowing/Sdl3.Window.cs b/Robust.Client/Graphics/Clyde/Windowing/Sdl3.Window.cs index 6bf5f49ae75..02a791391b0 100644 --- a/Robust.Client/Graphics/Clyde/Windowing/Sdl3.Window.cs +++ b/Robust.Client/Graphics/Clyde/Windowing/Sdl3.Window.cs @@ -418,20 +418,20 @@ public void WindowSetTitle(WindowReg window, string title) private static void WinThreadWinSetTitle(CmdWinSetTitle cmd) { - SDL.SDL_SetWindowTitle(cmd.Window, cmd.Title); + SDL.SDL_SetWindowTitle(cmd.Window, cmd.Title); } - public void WindowSetTitleBarVisible(WindowReg window, bool visible) + public void WindowSetBordered(WindowReg window, bool visible) { - window.IsTitleBarVisible = visible; - SendCmd(new CmdWinSetTitleBarVisible + window.IsBordered = visible; + SendCmd(new CmdWinSetBordered { Window = WinPtr(window), Visible = visible, }); } - private static void WinThreadWinSetTitleBarVisible(CmdWinSetTitleBarVisible cmd) + private static void WinThreadWinSetBordered(CmdWinSetBordered cmd) { SDL.SDL_SetWindowBordered(cmd.Window, cmd.Visible); } diff --git a/Robust.Client/Graphics/Clyde/Windowing/Sdl3.WindowThread.cs b/Robust.Client/Graphics/Clyde/Windowing/Sdl3.WindowThread.cs index 26b2d4695d8..0f140f2aa5d 100644 --- a/Robust.Client/Graphics/Clyde/Windowing/Sdl3.WindowThread.cs +++ b/Robust.Client/Graphics/Clyde/Windowing/Sdl3.WindowThread.cs @@ -81,8 +81,8 @@ private void ProcessSdl3Cmd(CmdBase cmdb) WinThreadWinSetTitle(cmd); break; - case CmdWinSetTitleBarVisible cmd: - WinThreadWinSetTitleBarVisible(cmd); + case CmdWinSetBordered cmd: + WinThreadWinSetBordered(cmd); break; case CmdSetClipboard cmd: @@ -295,7 +295,7 @@ private sealed class CmdWinSetTitle : CmdBase public required string Title; } - private sealed class CmdWinSetTitleBarVisible : CmdBase + private sealed class CmdWinSetBordered : CmdBase { public nint Window; public required bool Visible; diff --git a/Robust.Client/Graphics/IClydeWindow.cs b/Robust.Client/Graphics/IClydeWindow.cs index 15e6f5e79e7..2cecf7a04cd 100644 --- a/Robust.Client/Graphics/IClydeWindow.cs +++ b/Robust.Client/Graphics/IClydeWindow.cs @@ -20,7 +20,10 @@ public interface IClydeWindow : IDisposable bool IsFocused { get; } bool IsMinimized { get; } bool IsVisible { get; set; } - bool IsTitleBarVisible { get; set; } + /// + /// If set to false, then the titlebar and border of the window will be hidden. + /// + bool IsBordered { get; set; } Vector2 ContentScale { get; } ///