@@ -18,6 +18,16 @@ namespace WindowSwitcher.Windows;
1818
1919public partial class FloatingWindow : Window , IFloatingPreviewWindow
2020{
21+ private const double ResizeGripThickness = 8d ;
22+ private static readonly Cursor DefaultCursor = new ( StandardCursorType . Arrow ) ;
23+ private static readonly Cursor TopSideCursor = new ( StandardCursorType . TopSide ) ;
24+ private static readonly Cursor BottomSideCursor = new ( StandardCursorType . BottomSide ) ;
25+ private static readonly Cursor LeftSideCursor = new ( StandardCursorType . LeftSide ) ;
26+ private static readonly Cursor RightSideCursor = new ( StandardCursorType . RightSide ) ;
27+ private static readonly Cursor TopLeftCornerCursor = new ( StandardCursorType . TopLeftCorner ) ;
28+ private static readonly Cursor TopRightCornerCursor = new ( StandardCursorType . TopRightCorner ) ;
29+ private static readonly Cursor BottomLeftCornerCursor = new ( StandardCursorType . BottomLeftCorner ) ;
30+ private static readonly Cursor BottomRightCornerCursor = new ( StandardCursorType . BottomRightCorner ) ;
2131 private volatile bool _isPointerInside ;
2232 private bool _closeRequestedByHost ;
2333 private readonly IFloatingWindowHost _floatingWindowHost ;
@@ -119,10 +129,92 @@ private void SetInitialWindowSettings()
119129 private void CanvasPointerPressed ( object ? sender , PointerPressedEventArgs e )
120130 {
121131 _floatingWindowHost . SetActivePreview ( this ) ;
122- if ( ConfigFileAccessor . GetInstance ( ) . ReadConfig ( config => config . MoveWindows ) )
132+
133+ bool moveWindows = ConfigFileAccessor . GetInstance ( ) . ReadConfig ( config => config . MoveWindows ) ;
134+
135+ if ( TryBeginResizeDrag ( e ) )
136+ return ;
137+
138+ if ( moveWindows )
123139 BeginMoveDrag ( e ) ;
124140 }
125141
142+ private bool TryBeginResizeDrag ( PointerPressedEventArgs e )
143+ {
144+ if ( ! CanResize )
145+ return false ;
146+
147+ PointerPoint pointerPoint = e . GetCurrentPoint ( this ) ;
148+ if ( ! pointerPoint . Properties . IsLeftButtonPressed )
149+ return false ;
150+
151+ WindowEdge ? resizeEdge = ResolveResizeEdge ( pointerPoint . Position ) ;
152+ if ( ! resizeEdge . HasValue )
153+ return false ;
154+
155+ BeginResizeDrag ( resizeEdge . Value , e ) ;
156+ return true ;
157+ }
158+
159+ private WindowEdge ? ResolveResizeEdge ( Point pointerPosition )
160+ {
161+ if ( Width <= 0 || Height <= 0 )
162+ return null ;
163+
164+ bool isNearLeft = pointerPosition . X <= ResizeGripThickness ;
165+ bool isNearRight = pointerPosition . X >= Width - ResizeGripThickness ;
166+ bool isNearTop = pointerPosition . Y <= ResizeGripThickness ;
167+ bool isNearBottom = pointerPosition . Y >= Height - ResizeGripThickness ;
168+
169+ if ( isNearTop && isNearLeft )
170+ return WindowEdge . NorthWest ;
171+ if ( isNearTop && isNearRight )
172+ return WindowEdge . NorthEast ;
173+ if ( isNearBottom && isNearLeft )
174+ return WindowEdge . SouthWest ;
175+ if ( isNearBottom && isNearRight )
176+ return WindowEdge . SouthEast ;
177+ if ( isNearTop )
178+ return WindowEdge . North ;
179+ if ( isNearBottom )
180+ return WindowEdge . South ;
181+ if ( isNearLeft )
182+ return WindowEdge . West ;
183+ if ( isNearRight )
184+ return WindowEdge . East ;
185+
186+ return null ;
187+ }
188+
189+ private void UpdateResizeCursor ( PointerEventArgs e )
190+ {
191+ if ( ! CanResize )
192+ {
193+ WindowCanvas . Cursor = DefaultCursor ;
194+ return ;
195+ }
196+
197+ PointerPoint pointerPoint = e . GetCurrentPoint ( this ) ;
198+ WindowEdge ? edge = ResolveResizeEdge ( pointerPoint . Position ) ;
199+ WindowCanvas . Cursor = ResolveCursor ( edge ) ;
200+ }
201+
202+ private static Cursor ResolveCursor ( WindowEdge ? edge )
203+ {
204+ return edge switch
205+ {
206+ WindowEdge . North => TopSideCursor ,
207+ WindowEdge . South => BottomSideCursor ,
208+ WindowEdge . West => LeftSideCursor ,
209+ WindowEdge . East => RightSideCursor ,
210+ WindowEdge . NorthWest => TopLeftCornerCursor ,
211+ WindowEdge . NorthEast => TopRightCornerCursor ,
212+ WindowEdge . SouthWest => BottomLeftCornerCursor ,
213+ WindowEdge . SouthEast => BottomRightCornerCursor ,
214+ _ => DefaultCursor ,
215+ } ;
216+ }
217+
126218 private void CanvasPointerReleased ( object ? sender , PointerReleasedEventArgs e )
127219 {
128220 _winAccessorBase . RaiseWindow ( WindowConfig . WindowId ) ;
@@ -131,6 +223,8 @@ private void CanvasPointerReleased(object? sender, PointerReleasedEventArgs e)
131223
132224 private void CanvasPointerEntered ( object ? sender , PointerEventArgs e )
133225 {
226+ UpdateResizeCursor ( e ) ;
227+
134228 if ( _isPointerInside )
135229 return ;
136230 _isPointerInside = true ;
@@ -154,6 +248,12 @@ private void CanvasPointerEntered(object? sender, PointerEventArgs e)
154248 private void CanvasPointerExited ( object ? sender , PointerEventArgs e )
155249 {
156250 _isPointerInside = false ;
251+ WindowCanvas . Cursor = DefaultCursor ;
252+ }
253+
254+ private void CanvasPointerMoved ( object ? sender , PointerEventArgs e )
255+ {
256+ UpdateResizeCursor ( e ) ;
157257 }
158258
159259 private void FloatingWindowResized ( object ? sender , WindowResizedEventArgs e )
@@ -224,7 +324,6 @@ private void ApplySettingsCore(bool refreshPreviewPipeline)
224324 config . UseFixedWindowSize ,
225325 config . WindowWidth ,
226326 config . WindowHeight ,
227- config . ShowWindowDecorations ,
228327 config . PreviewHighlightColor ,
229328 } ) ;
230329
@@ -241,9 +340,10 @@ private void ApplySettingsCore(bool refreshPreviewPipeline)
241340 Height = WindowConfig . WindowHeight ;
242341 }
243342
244- SystemDecorations = configSnapshot . ShowWindowDecorations
245- ? SystemDecorations . Full
246- : SystemDecorations . BorderOnly ;
343+ if ( ! CanResize )
344+ WindowCanvas . Cursor = DefaultCursor ;
345+
346+ SystemDecorations = SystemDecorations . BorderOnly ;
247347
248348 if ( Color . TryParse ( configSnapshot . PreviewHighlightColor , out Color highlightColor ) )
249349 {
0 commit comments