@@ -15,23 +15,23 @@ public unsafe class Window : IDisposable
1515
1616 private Silk . NET . SDL . Window * sdlHandle ;
1717
18- #region Initialization
18+ #region Initialization
1919
2020 /// <summary>
2121 /// Initializes static members of the <see cref="Window"/> class.
2222 /// </summary>
2323 static Window ( )
2424 {
25- SDL = Silk . NET . SDL . Sdl . GetApi ( ) ;
25+ SDL = Sdl . GetApi ( ) ;
2626
27- // jklawreszuk: Workaround for wayland (see #2487 for more details)
27+ // jklawreszuk: Workaround for wayland (see #2487 for more details)
2828 // TODO: Wayland SDL_EGL_MakeCurrent does not cover multi-context scenario (https://github.com/libsdl-org/SDL/issues/9072)
2929 if ( OperatingSystem . IsLinux ( ) )
3030 SDL . SetHint ( "SDL_VIDEODRIVER" , "x11" ) ;
3131
3232 SDL . Init ( Sdl . InitEverything ) ;
3333
34- // Pass first mouse event when user clicked on window
34+ // Pass first mouse event when user clicked on window
3535 SDL . SetHint ( Sdl . HintMouseFocusClickthrough , "1" ) ;
3636
3737 // Don't leave fullscreen on focus loss
@@ -73,11 +73,10 @@ public Window(string title, IntPtr parent)
7373 // Create the SDL window and then extract the native handle.
7474 sdlHandle = SDL . CreateWindow ( title , Sdl . WindowposUndefined , Sdl . WindowposUndefined , 640 , 480 , ( uint ) flags ) ;
7575 }
76-
7776
7877 if ( sdlHandle == null )
7978 {
80- throw new Exception ( "Cannot allocate SDL Window: " + SDL . GetErrorS ( ) ) ;
79+ throw new Exception ( "Cannot allocate SDL Window: " + SDL . GetErrorS ( ) ) ;
8180 }
8281
8382 SysWMInfo info = default ;
@@ -105,6 +104,13 @@ public Window(string title, IntPtr parent)
105104 {
106105 Handle = ( IntPtr ) info . Info . Cocoa . Window ;
107106 }
107+
108+ var displayIndex = SDL . GetWindowDisplayIndex ( sdlHandle ) ;
109+ if ( displayIndex == - 1 )
110+ displayIndex = 0 ;
111+
112+ DisplayIndex = displayIndex ;
113+
108114 Application . RegisterWindow ( this ) ;
109115 Application . ProcessEvents ( ) ;
110116 }
@@ -321,7 +327,7 @@ public Size2 Size
321327 }
322328 set { SDL . SetWindowSize ( sdlHandle , value . Width , value . Height ) ; }
323329 }
324-
330+
325331 /// <summary>
326332 /// The opacity of the window.
327333 /// </summary>
@@ -446,6 +452,30 @@ public FormBorderStyle FormBorderStyle
446452 }
447453 }
448454
455+ /// <summary>
456+ /// DPI (dots per inch) of the Window.
457+ /// </summary>
458+ public float Dpi
459+ {
460+ get
461+ {
462+ float ddpi , hdpi , vdpi ;
463+
464+ if ( SDL . GetDisplayDPI ( DisplayIndex , & ddpi , & hdpi , & vdpi ) != 0 )
465+ {
466+ // Failed to get DPI, return a default value of 96 which is the standard DPI for many platforms.
467+ return 96.0f ;
468+ }
469+
470+ return ddpi ;
471+ }
472+ }
473+
474+ /// <summary>
475+ /// DPI scaling factor of the Window. 100 % corresponds to a DPI of 96.
476+ /// </summary>
477+ public float DpiScale => Dpi / 96.0f ;
478+
449479 public void SetRelativeMouseMode ( bool enabled )
450480 {
451481 SDL . SetRelativeMouseMode ( enabled ? SdlBool . True : SdlBool . False ) ;
@@ -489,6 +519,7 @@ public void SetRelativeMouseMode(bool enabled)
489519 public event WindowEventDelegate MouseLeaveActions ;
490520 public event WindowEventDelegate FocusGainedActions ;
491521 public event WindowEventDelegate FocusLostActions ;
522+ public event WindowEventDelegate DisplayChangedActions ;
492523 public event DropEventDelegate DropFileActions ;
493524
494525 /// <summary>
@@ -554,7 +585,7 @@ public virtual void ProcessEvent(Event e)
554585 case EventType . Fingerup :
555586 FingerReleaseActions ? . Invoke ( e . Tfinger ) ;
556587 break ;
557-
588+
558589 case EventType . Dropfile :
559590 DropFileActions ? . Invoke ( Silk . NET . Core . Native . SilkMarshal . PtrToString ( ( IntPtr ) e . Drop . File , Silk . NET . Core . Native . NativeStringEncoding . UTF8 ) ) ;
560591 break ;
@@ -610,12 +641,27 @@ public virtual void ProcessEvent(Event e)
610641 case WindowEventID . FocusLost :
611642 FocusLostActions ? . Invoke ( e . Window ) ;
612643 break ;
613- }
644+
645+ case WindowEventID . DisplayChanged :
646+ OnDisplayChanged ( e . Window ) ;
647+ break ;
648+ }
614649 break ;
615650 }
616651 }
617652 }
618653
654+ private void OnDisplayChanged ( WindowEvent e )
655+ {
656+ var displayIndex = SDL . GetWindowDisplayIndex ( sdlHandle ) ;
657+ if ( displayIndex == - 1 )
658+ displayIndex = 0 ;
659+
660+ DisplayIndex = displayIndex ;
661+
662+ DisplayChangedActions ? . Invoke ( e ) ;
663+ }
664+
619665 /// <summary>
620666 /// Platform specific handle for Window.
621667 /// </summary>
@@ -632,6 +678,11 @@ public virtual void ProcessEvent(Event e)
632678 /// </summary>
633679 public IntPtr Display { get ; private set ; }
634680
681+ /// <summary>
682+ /// Index of the display where the current Window is being shown.
683+ /// </summary>
684+ public int DisplayIndex { get ; private set ; }
685+
635686 /// <summary>
636687 /// Surface of current Window (valid only for Android).
637688 /// </summary>
@@ -650,7 +701,8 @@ public bool Exists
650701 get { return SdlHandle != IntPtr . Zero ; }
651702 }
652703
653- #region Disposal
704+ #region Disposal
705+
654706 ~ Window ( )
655707 {
656708 Dispose ( false ) ;
@@ -690,7 +742,7 @@ protected virtual void Dispose(bool disposing)
690742 Handle = IntPtr . Zero ;
691743 }
692744 }
693-
745+
694746 // This code added to correctly implement the disposable pattern.
695747 public void Dispose ( )
696748 {
0 commit comments