-
Notifications
You must be signed in to change notification settings - Fork 1
Window and Displays
VOID's public window/display API is platform-neutral.
SDL3 handles the native platform work internally, but normal game code works with VOID types such as:
WindowDisplayManagerDisplayInfoDisplayIdDisplayModeWindowCapabilities
var settings = GameSettings.Instance
.SetWindow(1280, 720)
.SetViewport(320, 180)
.SetDisplay(0)
.SetVsync(true)
.Build();SetWindow is the native window size.
SetViewport is the internal render size before presentation/scaling.
GameSettings.Instance.SetWindowScaleMode(
WindowScaleMode.Fit);Available modes:
StretchPixelPerfectFitFillNone
For a low-resolution pixel-art game:
GameSettings.Instance
.SetWindow(1280, 720)
.SetViewport(320, 180)
.SetWindowScaleMode(
WindowScaleMode.PixelPerfect);The logical viewport is also the coordinate space used by camera screen/world conversion. Raw mouse positions are window-relative, so keep the presentation scale in mind when using mouse coordinates with a camera.
See Camera → Screen and World Conversion and Input → Mouse.
Window setters queue changes.
Call ApplyChanges() when ready:
Game.Instance.Window
.SetSize(1600, 900)
.SetTitle("My Game - Level 2")
.SetVSync(false)
.ApplyChanges();Other runtime settings:
Game.Instance.Window
.SetMode(WindowMode.Borderless)
.ApplyChanges();Get all current displays:
IReadOnlyList<DisplayInfo> displays =
DisplayManager.GetDisplays();
foreach (var display in displays)
{
Console.WriteLine(
$"{display.Index}: {display.Name} " +
$"{display.CurrentMode} " +
$"Scale={display.ContentScale:0.##}");
}Primary display:
DisplayInfo primary =
DisplayManager.PrimaryDisplay;By index:
DisplayInfo second =
DisplayManager.GetDisplay(1);Display enumeration indices can change when monitors are connected or disconnected.
For a long-lived reference, keep the DisplayId:
DisplayId id =
DisplayManager.GetDisplay(1).Id;
if (DisplayManager.TryGetDisplay(id, out var display))
{
Console.WriteLine(display.Name);
}At startup:
GameSettings.Instance.SetDisplay(1);At runtime:
Game.Instance.Window
.SetDisplay(1)
.ApplyChanges();or:
DisplayId id =
DisplayManager.GetDisplay(1).Id;
Game.Instance.Window
.SetDisplay(id)
.ApplyChanges();Whether the operation is possible depends on the active native backend. See Backend Capabilities.
Desktop fullscreen keeps the selected display's current desktop mode:
var settings = GameSettings.Instance
.SetDisplay(0)
.SetDesktopFullscreen()
.Build();At runtime:
Game.Instance.Window
.SetDesktopFullscreen()
.ApplyChanges();Request a resolution and optional refresh rate:
var settings = GameSettings.Instance
.SetDisplay(0)
.SetFullscreenMode(
1920,
1080,
144f)
.Build();A refresh rate of 0 lets the platform choose the closest available rate.
At runtime:
Game.Instance.Window
.SetFullscreenMode(
1920,
1080,
144f)
.ApplyChanges();Or select one of the reported modes:
DisplayInfo display =
DisplayManager.GetDisplay(0);
DisplayMode mode =
display.SupportedModes[0];
Game.Instance.Window
.SetFullscreenMode(mode)
.ApplyChanges();Window window = Game.Instance.Window;
Vect2 windowSize = window.WindowSize;
Vect2 renderSize = window.RenderSize;
WindowMode mode = window.Mode;
bool vsync = window.VSyncEnabled;
bool focused = window.IsFocused;
bool open = window.IsOpen;
DisplayInfo display = window.CurrentDisplay;
int displayIndex = window.DisplayIndex;Game.Instance.Window.OnWindowResized = size =>
{
Console.WriteLine($"Resized: {size}");
};
Game.Instance.Window.OnFocusGained = () =>
{
Console.WriteLine("Focus gained");
};
Game.Instance.Window.OnFocusLost = () =>
{
Console.WriteLine("Focus lost");
};
Game.Instance.Window.OnDisplayChanged = change =>
{
Console.WriteLine(
$"{change.Kind}: {change.Display}");
};Display-wide notifications are also available:
DisplayManager.Changed += change =>
{
Console.WriteLine(change.Kind);
};The actual window system matters, especially on Linux.
WindowCapabilities caps =
Game.Instance.Window.Capabilities;
Console.WriteLine(caps.Backend);
Console.WriteLine(caps.BackendName);
Console.WriteLine(caps.CanPositionWindow);
Console.WriteLine(caps.SupportsDisplayModes);Useful capability flags include:
CanPositionWindowCanSelectWindowedDisplayCanSelectDesktopFullscreenDisplayCanSelectExclusiveFullscreenDisplaySupportsDisplayEnumerationSupportsDisplayModesSupportsContentScaleUsesCompositorWindowPlacement
Native Wayland generally lets the compositor control placement of ordinary top-level windows.
Do not assume an app can arbitrarily move a normal window from one monitor to another.
If your code depends on display placement, inspect WindowCapabilities rather than assuming the operating system tells the whole story.
VOID's default Linux policy is:
LinuxWindowBackend.X11ThenWaylandIt tries X11/XWayland first and falls back to native Wayland.
You can change it:
GameSettings.Instance
.SetLinuxWindowBackend(
LinuxWindowBackend.Auto);or force one:
GameSettings.Instance
.SetLinuxWindowBackend(
LinuxWindowBackend.X11);GameSettings.Instance
.SetLinuxWindowBackend(
LinuxWindowBackend.Wayland);This setting has no effect on Windows or macOS.
A Wayland desktop running VOID through XWayland reports NativeWindowBackend.X11, because that is the backend SDL actually initialized.
VOID keeps convenience methods for the primary display:
Vect2 desktop =
Window.GetDesktopResolution();
List<Vect2> modes =
Window.GetSupportedResolutions();
bool supported =
Window.IsResolutionSupported(
1920,
1080);For new multi-monitor code, prefer DisplayManager.
Home · Getting Started · Rendering · Custom Renderers · GitHub · Report an Issue
Built with VOID Engine · MIT License