Skip to content

Commit daf98af

Browse files
committed
Add support for getting DPI from the window (SDL)
1 parent a166042 commit daf98af

3 files changed

Lines changed: 73 additions & 11 deletions

File tree

sources/engine/Stride.Games/SDL/GameFormSDL.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ namespace Stride.Games
1515
/// </summary>
1616
public class GameFormSDL : Window
1717
{
18-
#region Initialization
18+
#region Initialization
19+
1920
/// <summary>
2021
/// Initializes a new instance of the 'GameForm' class.
2122
/// </summary>
@@ -39,9 +40,11 @@ public GameFormSDL(string text) : base(text)
3940
RestoredActions += GameForm_RestoredActions;
4041
KeyDownActions += GameFormSDL_KeyDownActions;
4142
}
43+
4244
#endregion
4345

4446
#region Events
47+
4548
/// <summary>
4649
/// Occurs when [app activated].
4750
/// </summary>
@@ -75,6 +78,7 @@ public GameFormSDL(string text) : base(text)
7578
#endregion
7679

7780
#region Implementation
81+
7882
// TODO: The code below is taken from GameForm.cs of the Windows Desktop implementation. This needs reviewing
7983
private FormWindowState previousWindowState;
8084

sources/engine/Stride.Games/SDL/GameWindowSDL.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ protected override void Initialize(GameContext<Window> gameContext)
109109

110110
window.ClientSize = new Size2(width, height);
111111

112-
window.MouseEnterActions += WindowOnMouseEnterActions;
112+
window.MouseEnterActions += WindowOnMouseEnterActions;
113113
window.MouseLeaveActions += WindowOnMouseLeaveActions;
114114

115115
var gameForm = window as GameFormSDL;
@@ -120,7 +120,7 @@ protected override void Initialize(GameContext<Window> gameContext)
120120
gameForm.SizeChanged += OnClientSizeChanged;
121121
gameForm.CloseActions += GameForm_CloseActions;
122122
gameForm.FullscreenToggle += OnFullscreenToggle;
123-
123+
gameForm.DisplayChangedActions += WindowOnDisplayChangedActions;
124124
}
125125
else
126126
{
@@ -380,6 +380,12 @@ public override bool Focused
380380
}
381381
}
382382

383+
private void WindowOnDisplayChangedActions(WindowEvent sdlWindowEvent)
384+
{
385+
Dpi = new Int2((int) window.Dpi);
386+
DpiScale = window.DpiScale;
387+
}
388+
383389
protected override void Destroy()
384390
{
385391
if (window != null)

sources/engine/Stride.Graphics/SDL/Window.cs

Lines changed: 60 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public unsafe class Window : IDisposable
1515

1616
private Silk.NET.SDL.Window* sdlHandle;
1717

18-
#region Initialization
18+
#region Initialization
1919

2020
private static readonly object initLock = new();
2121

@@ -95,11 +95,10 @@ public Window(string title, IntPtr parent)
9595
// Create the SDL window and then extract the native handle.
9696
sdlHandle = SDL.CreateWindow(title, Sdl.WindowposUndefined, Sdl.WindowposUndefined, 640, 480, (uint)flags);
9797
}
98-
9998

10099
if (sdlHandle == null)
101100
{
102-
throw new Exception("Cannot allocate SDL Window: " + SDL.GetErrorS());
101+
throw new Exception("Cannot allocate SDL Window: " + SDL.GetErrorS());
103102
}
104103

105104
SysWMInfo info = default;
@@ -127,6 +126,13 @@ public Window(string title, IntPtr parent)
127126
{
128127
Handle = (IntPtr)info.Info.Cocoa.Window;
129128
}
129+
130+
var displayIndex = SDL.GetWindowDisplayIndex(sdlHandle);
131+
if (displayIndex == -1)
132+
displayIndex = 0;
133+
134+
DisplayIndex = displayIndex;
135+
130136
Application.RegisterWindow(this);
131137
Application.ProcessEvents();
132138
}
@@ -343,7 +349,7 @@ public Size2 Size
343349
}
344350
set { SDL.SetWindowSize(sdlHandle, value.Width, value.Height); }
345351
}
346-
352+
347353
/// <summary>
348354
/// The opacity of the window.
349355
/// </summary>
@@ -468,6 +474,30 @@ public FormBorderStyle FormBorderStyle
468474
}
469475
}
470476

477+
/// <summary>
478+
/// DPI (dots per inch) of the Window.
479+
/// </summary>
480+
public float Dpi
481+
{
482+
get
483+
{
484+
float ddpi, hdpi, vdpi;
485+
486+
if (SDL.GetDisplayDPI(DisplayIndex, &ddpi, &hdpi, &vdpi) != 0)
487+
{
488+
// Failed to get DPI, return a default value of 96 which is the standard DPI for many platforms.
489+
return 96.0f;
490+
}
491+
492+
return ddpi;
493+
}
494+
}
495+
496+
/// <summary>
497+
/// DPI scaling factor of the Window. 100 % corresponds to a DPI of 96.
498+
/// </summary>
499+
public float DpiScale => Dpi / 96.0f;
500+
471501
public void SetRelativeMouseMode(bool enabled)
472502
{
473503
SDL.SetRelativeMouseMode(enabled ? SdlBool.True : SdlBool.False);
@@ -511,6 +541,7 @@ public void SetRelativeMouseMode(bool enabled)
511541
public event WindowEventDelegate MouseLeaveActions;
512542
public event WindowEventDelegate FocusGainedActions;
513543
public event WindowEventDelegate FocusLostActions;
544+
public event WindowEventDelegate DisplayChangedActions;
514545
public event DropEventDelegate DropFileActions;
515546

516547
/// <summary>
@@ -576,7 +607,7 @@ public virtual void ProcessEvent(Event e)
576607
case EventType.Fingerup:
577608
FingerReleaseActions?.Invoke(e.Tfinger);
578609
break;
579-
610+
580611
case EventType.Dropfile:
581612
DropFileActions?.Invoke(Silk.NET.Core.Native.SilkMarshal.PtrToString((IntPtr)e.Drop.File, Silk.NET.Core.Native.NativeStringEncoding.UTF8));
582613
break;
@@ -632,12 +663,27 @@ public virtual void ProcessEvent(Event e)
632663
case WindowEventID.FocusLost:
633664
FocusLostActions?.Invoke(e.Window);
634665
break;
635-
}
666+
667+
case WindowEventID.DisplayChanged:
668+
OnDisplayChanged(e.Window);
669+
break;
670+
}
636671
break;
637672
}
638673
}
639674
}
640675

676+
private void OnDisplayChanged(WindowEvent e)
677+
{
678+
var displayIndex = SDL.GetWindowDisplayIndex(sdlHandle);
679+
if (displayIndex == -1)
680+
displayIndex = 0;
681+
682+
DisplayIndex = displayIndex;
683+
684+
DisplayChangedActions?.Invoke(e);
685+
}
686+
641687
/// <summary>
642688
/// Platform specific handle for Window.
643689
/// </summary>
@@ -654,6 +700,11 @@ public virtual void ProcessEvent(Event e)
654700
/// </summary>
655701
public IntPtr Display { get; private set; }
656702

703+
/// <summary>
704+
/// Index of the display where the current Window is being shown.
705+
/// </summary>
706+
public int DisplayIndex { get; private set; }
707+
657708
/// <summary>
658709
/// Surface of current Window (valid only for Android).
659710
/// </summary>
@@ -672,7 +723,8 @@ public bool Exists
672723
get { return SdlHandle != IntPtr.Zero; }
673724
}
674725

675-
#region Disposal
726+
#region Disposal
727+
676728
~Window()
677729
{
678730
Dispose(false);
@@ -712,7 +764,7 @@ protected virtual void Dispose(bool disposing)
712764
Handle = IntPtr.Zero;
713765
}
714766
}
715-
767+
716768
// This code added to correctly implement the disposable pattern.
717769
public void Dispose()
718770
{

0 commit comments

Comments
 (0)