88
99namespace Silk . NET . Windowing . SDL3 ;
1010
11- internal class SdlDisplay ( uint id ) : IDisplay
11+ internal class SdlDisplay : IDisplay
1212{
13- public uint Id { get ; } = id ;
13+ private Rectangle < float > _bounds ;
14+ private Rectangle < float > _workArea ;
15+
16+ public SdlDisplay ( SdlSurface surface , uint id )
17+ {
18+ Surface = surface ;
19+ Id = id ;
20+ _bounds = Bounds ;
21+ _workArea = WorkArea ;
22+ }
23+
24+ public uint Id { get ; }
25+ public SdlSurface Surface { get ; }
26+
1427 public Rectangle < float > Bounds
1528 {
1629 get
@@ -50,14 +63,14 @@ public IReadOnlyList<VideoMode>? KnownVideoModes
5063 return _silkModes ;
5164 }
5265
53- var videoModes = DisplayModes ;
54- var ret = new VideoMode [ videoModes . Length + 1 ] ;
66+ UpdateDisplayModes ( ) ;
67+ var ret = new VideoMode [ _displayModes . Length + 1 ] ;
5568 ret [ 0 ] = default ; // This is to change back to non-fullscreen.
56- for ( nuint i = 0 ; ( int ) i < videoModes . Length ; i ++ )
69+ for ( nuint i = 0 ; ( int ) i < _displayModes . Length ; i ++ )
5770 {
58- ref var videoMode = ref videoModes [ i ] . Handle ;
71+ ref var videoMode = ref _displayModes [ i ] . Handle ;
5972 ret [ i + 1 ] = new VideoMode (
60- ( int ) i ,
73+ ( int ) ( i + 1 ) ,
6174 new Vector2 ( videoMode . W , videoMode . H ) ,
6275 videoMode . RefreshRate
6376 ) ;
@@ -67,37 +80,78 @@ public IReadOnlyList<VideoMode>? KnownVideoModes
6780 }
6881 }
6982
70- [ field: AllowNull , MaybeNull ]
83+ private Ptr < DisplayMode > [ ] ? _displayModes ;
84+
7185 internal Ptr < DisplayMode > [ ] DisplayModes
7286 {
7387 get
7488 {
75- if ( field is not null )
89+ if ( _displayModes is not null )
7690 {
77- return field ;
91+ return _displayModes ;
7892 }
7993
80- var count = 0 ;
81- var videoModes = Sdl . GetFullscreenDisplayModes ( Id , count . AsRef ( ) ) ;
82- if ( videoModes == nullptr )
83- {
84- Sdl . ThrowError ( ) ;
85- }
94+ UpdateDisplayModes ( ) ;
95+ return _displayModes ;
96+ }
97+ }
8698
87- field = new Ptr < DisplayMode > [ count ] ;
88- videoModes . AsSpan ( count ) . CopyTo ( field ) ;
89- Sdl . Free ( ( Ref ) videoModes ) ;
90- return field ;
99+ [ MemberNotNull ( nameof ( _displayModes ) ) ]
100+ private bool UpdateDisplayModes ( )
101+ {
102+ DebugPrint ( ) ;
103+ var count = 0 ;
104+ var videoModes = Sdl . GetFullscreenDisplayModes ( Id , count . AsRef ( ) ) ;
105+ if ( videoModes == nullptr )
106+ {
107+ Sdl . ThrowError ( ) ;
91108 }
109+
110+ var span = videoModes . AsSpan ( count ) ;
111+ if ( _displayModes ? . Length == count && span . SequenceEqual ( _displayModes ) )
112+ {
113+ return false ;
114+ }
115+
116+ var wasNull = _displayModes is null ;
117+ _displayModes = new Ptr < DisplayMode > [ count ] ;
118+ videoModes . AsSpan ( count ) . CopyTo ( _displayModes ) ;
119+ Sdl . Free ( ( Ref ) videoModes ) ;
120+ _silkModes = null ;
121+ if ( ! wasNull )
122+ {
123+ DebugPrint ( "Raising KnownVideoModesChanged" ) ;
124+ _knownVideoModesChanged ? . Invoke ( new DisplayVideoModeAvailabilityChangeEvent ( ) ) ;
125+ }
126+
127+ return ! wasNull ;
92128 }
93129
94130 public bool IsPrimary => Sdl . GetPrimaryDisplay ( ) == Id ;
95131
96132 public string Name => Sdl . GetDisplayName ( Id ) . ReadToString ( ) ;
97133
98134 public event Action < DisplayCoordinatesEvent > ? CoordinatesChanged ;
99- public event Action < DisplayVideoModeAvailabilityChangeEvent > ? KnownVideoModesChanged ;
100- public event Action < VideoModeChangeEvent > ? VideoModeChanged ;
135+ private Action < DisplayVideoModeAvailabilityChangeEvent > ? _knownVideoModesChanged ;
136+
137+ public event Action < DisplayVideoModeAvailabilityChangeEvent > ? KnownVideoModesChanged
138+ {
139+ add
140+ {
141+ if ( value is null )
142+ {
143+ return ;
144+ }
145+
146+ if ( _displayModes is null )
147+ {
148+ UpdateDisplayModes ( ) ;
149+ }
150+
151+ _knownVideoModesChanged += value ;
152+ }
153+ remove => _knownVideoModesChanged -= value ;
154+ }
101155
102156 private bool Equals ( SdlDisplay other ) => Id == other . Id ;
103157
@@ -108,4 +162,15 @@ obj is not null
108162 && ( ReferenceEquals ( this , obj ) || ( obj . GetType ( ) == GetType ( ) && Equals ( ( SdlDisplay ) obj ) ) ) ;
109163
110164 public override int GetHashCode ( ) => ( int ) Id ;
165+
166+ public void OnCoordinatesChanged ( )
167+ {
168+ DebugPrint ( "Raising CoordinatesChanged..." ) ;
169+ CoordinatesChanged ? . Invoke (
170+ new DisplayCoordinatesEvent ( Surface , this , _bounds , Bounds , _workArea , WorkArea )
171+ ) ;
172+ }
173+
174+ // If _displayModes is null, user doesn't care.
175+ public bool OnModeChanged ( ) => _displayModes is not null && UpdateDisplayModes ( ) ;
111176}
0 commit comments