11// Licensed to the .NET Foundation under one or more agreements.
22// The .NET Foundation licenses this file to you under the MIT license.
33
4+ using System . Runtime . CompilerServices ;
45using Silk . NET . Maths ;
56using Silk . NET . SDL ;
67
@@ -14,14 +15,16 @@ internal class SdlBoundedPointerTarget(SdlInputBackend backend) : IPointerTarget
1415 public Box3D < float > Bounds =>
1516 new ( new Vector3D < float > ( Bounds2D . Min , 0 ) , new Vector3D < float > ( Bounds2D . Max , 1 ) ) ;
1617
17- public static Box2D < float > CalculateBounds ( ISdl sdl )
18+ /// <inheritdoc />
19+ public int GetPointCount ( IPointerDevice pointer ) => PointerTargetExtensions . GetPointCount ( this , pointer ) ;
20+
21+ /// <inheritdoc />
22+ public TargetPoint GetPoint ( IPointerDevice pointer , int point ) => PointerTargetExtensions . GetPoint ( this , pointer , point ) ;
23+
24+ public static unsafe Box2D < float > CalculateAllDisplayBounds ( ISdl sdl )
1825 {
19- var minX = float . PositiveInfinity ;
20- var minY = float . PositiveInfinity ;
21- var maxX = float . NegativeInfinity ;
22- var maxY = float . NegativeInfinity ;
2326 var displayCount = 0 ;
24- var displays = sdl . GetDisplays ( displayCount . AsRef ( ) ) ;
27+ var displays = sdl . GetDisplays ( & displayCount ) ;
2528 if ( displays == nullptr )
2629 {
2730 // Looks like we can't support windowed mouse input.
@@ -31,66 +34,124 @@ public static Box2D<float> CalculateBounds(ISdl sdl)
3134
3235 if ( displayCount == 0 ) // ???
3336 {
34- sdl . Free ( ( Ref ) displays ) ;
37+ sdl . Free ( displays ) ;
3538 return default ;
3639 }
3740
41+ var bounds = new Box2D < float > ( float . MaxValue , float . MaxValue , float . MinValue , float . MinValue ) ;
42+
3843 for ( var i = 0 ; i < displayCount ; i ++ )
3944 {
40- Rect rect = default ;
41- if ( ! sdl . GetDisplayBounds ( displays [ ( nuint ) i ] , rect . AsRef ( ) ) )
42- {
43- return default ;
44- }
45+ var b = CalculateDisplayBounds ( sdl , displays [ i ] ) ;
46+ bounds = bounds . ExtendBy ( b ) ;
47+ }
48+
49+ sdl . Free ( displays ) ;
50+ return default ;
51+ }
4552
46- minX = float . Min ( minX , rect . X ) ;
47- minY = float . Min ( minY , rect . Y ) ;
48- maxX = float . Max ( maxX , rect . X + rect . W ) ;
49- maxY = float . Max ( maxY , rect . Y + rect . H ) ;
53+ public static unsafe Box2D < float > CalculateDisplayBounds ( ISdl sdl , uint sdlDisplayId )
54+ {
55+ if ( sdlDisplayId == 0 )
56+ {
57+ // https://wiki.libsdl.org/SDL3/SDL_DisplayID
58+ return default ;
5059 }
5160
52- sdl . Free ( ( Ref ) displays ) ;
53- if ( minX <= maxX && minY <= maxY )
61+ Rect rect = default ;
62+ var gotDisplayBounds = sdl . GetDisplayBounds ( sdlDisplayId , & rect ) ;
63+ if ( gotDisplayBounds == 0 )
5464 {
55- return new Box2D < float > ( minX , minY , maxX , maxY ) ;
65+ SdlLog . Error ( $ "Failed to get display from ID { sdlDisplayId } .") ;
66+ return default ;
5667 }
5768
58- return default ;
69+ return new Box2D < float > ( rect . X , rect . Y , rect . X + rect . W , rect . Y + rect . H ) ;
5970 }
6071
61- public int GetPointCount ( IPointerDevice pointer )
72+ public static unsafe Box2D < float > CalculateWindowBounds ( ISdl sdl , WindowHandle window )
6273 {
63- if ( pointer is not SdlBoundedPointerDevice { IsBounded : true } device )
74+ Vector2D < int > windowSize = default ;
75+ var gotSize = sdl . GetWindowSize ( window , & windowSize . X , & windowSize . Y ) ; ;
76+ if ( gotSize == 0 )
6477 {
65- return 0 ;
78+ SdlLog . Error ( "Failed to get window size for window." ) ;
79+ return default ;
6680 }
6781
68- if ( device . Backend == Backend )
82+ Vector2D < int > windowPosition = default ;
83+ var gotPos = sdl . GetWindowPosition ( window , & windowPosition . X , & windowPosition . Y ) ;
84+ if ( gotPos == 0 )
6985 {
70- //return Bounds != default ? device.BoundedPoints.List.Count : 0;
86+ SdlLog . Error ( "Failed to get window position for window." ) ;
87+ return default ;
7188 }
7289
73- throw new NotImplementedException ( ) ;
74- // return device.Backend.BoundedPointerTarget.GetPointCount(pointer );
90+ var windowEndPos = windowPosition + windowSize ;
91+ return new Box2D < float > ( windowPosition . X , windowPosition . Y , windowEndPos . X , windowEndPos . Y ) ;
7592 }
7693
77- public TargetPoint GetPoint ( IPointerDevice pointer , int point )
94+ public static Box2D < float > CalculateWindowBounds ( ISdl sdl , uint windowId )
7895 {
79- if (
80- pointer is not SdlBoundedPointerDevice { IsBounded : true } device
81- || point < 0
82- //|| point >= device.BoundedPoints.List.Count
83- )
96+ var window = sdl . GetWindowFromID ( windowId ) ;
97+ if ( window == nullptr )
8498 {
99+ SdlLog . Error ( $ "Failed to get window from ID { windowId } .") ;
85100 return default ;
86101 }
87102
88- if ( device . Backend != Backend )
103+ return CalculateWindowBounds ( sdl , window ) ;
104+ }
105+ }
106+
107+
108+ internal static class PointerTargetExtensions
109+ {
110+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
111+ public static bool AppliesTo ( this IPointerDevice device , IPointerTarget target ) => device . Targets . Contains ( target ) ;
112+
113+ extension ( IPointerTarget target )
114+ {
115+ /// <summary>
116+ /// A default implementation of <see cref="IPointerTarget.GetPointCount(IPointerDevice)"/>
117+ /// that iterates over all points.
118+ /// </summary>
119+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
120+ public int GetPointCount ( IPointerDevice pointer )
89121 {
90- // return device.Backend.BoundedPointerTarget.GetPoint(pointer, point);
122+ var points = pointer . State . Points ;
123+ var count = 0 ;
124+ var pointerPointsCount = points . Count ;
125+ for ( var i = 0 ; i < pointerPointsCount ; i ++ )
126+ {
127+ if ( points [ i ] . Target == target )
128+ {
129+ ++ count ;
130+ }
131+ }
132+
133+ return count ;
91134 }
92135
93- throw new NotImplementedException ( ) ;
94- // return Bounds != default ? device.BoundedPoints.List[point] : default;
136+ /// <summary>
137+ /// A default implementation of <see cref="IPointerTarget.GetPoint(IPointerDevice, int)"/>
138+ /// that iterates over all points.
139+ /// </summary>
140+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
141+ public TargetPoint GetPoint ( IPointerDevice pointer , int point )
142+ {
143+ var points = pointer . State . Points ;
144+ var pointerPointsCount = points . Count ;
145+ for ( var i = 0 ; i < pointerPointsCount ; i ++ )
146+ {
147+ var targetPoint = points [ i ] ;
148+ if ( targetPoint . Target == target && point -- == 0 )
149+ {
150+ return targetPoint ;
151+ }
152+ }
153+
154+ return default ;
155+ }
95156 }
96157}
0 commit comments