@@ -7,6 +7,9 @@ internal sealed class DeviceSurface : Control
77{
88 private const int LogicalWidth = 800 ;
99 private const int LogicalHeight = 480 ;
10+ // Ignore ordinary mouse jitter so a click remains a tap instead of
11+ // becoming the first step of a scrolling gesture.
12+ private const int TouchDragThreshold = 8 ;
1013 private const int TouchReportIntervalMs = 16 ;
1114 private const float CanvasWidth = 800f ;
1215 private const float CanvasHeight = 420f ;
@@ -352,8 +355,6 @@ protected override void OnMouseDown(MouseEventArgs e)
352355 _touching = true ;
353356 _touchStart = e . Location ;
354357 _activeSecondary = _touchMode == TouchDisplayMode . Button ? SegmentAt ( e . Location ) : - 1 ;
355- if ( _touchMode == TouchDisplayMode . TouchBar )
356- EmitTouch ( e . Location , force : true ) ;
357358 Invalidate ( ) ;
358359 }
359360 }
@@ -368,7 +369,8 @@ protected override void OnMouseMove(MouseEventArgs e)
368369 UpdateHover ( e . Location ) ;
369370 return ;
370371 }
371- if ( _touchMode == TouchDisplayMode . TouchBar )
372+ if ( _touchMode == TouchDisplayMode . TouchBar &&
373+ ( _lastTouchLocation is not null || StartHorizontalTouchDrag ( e . Location ) ) )
372374 EmitTouch ( e . Location ) ;
373375 }
374376 UpdateHover ( e . Location ) ;
@@ -399,11 +401,13 @@ protected override void OnMouseUp(MouseEventArgs e)
399401 {
400402 if ( _touchMode == TouchDisplayMode . TouchBar )
401403 {
402- // ARX has no separate release flag. The physical controller
403- // reports the contact from its first point through its final
404- // point; Stream Dock derives taps and scrolling from that
405- // sequence and the pause after it.
406- EmitTouch ( e . Location , force : true ) ;
404+ FlushPendingTouch ( ) ;
405+ if ( _lastTouchLocation is null && ! HasTouchDragStarted ( e . Location ) )
406+ {
407+ // Sending this on MouseDown makes scrollable modules jump.
408+ // Wait until release so a stationary click is one point.
409+ EmitTouch ( e . Location , force : true ) ;
410+ }
407411 }
408412 else
409413 {
@@ -487,6 +491,26 @@ private int SegmentAt(Point location) =>
487491 private RectangleF TouchSegment ( int index ) =>
488492 new ( _touchRect . Left + index * _touchRect . Width / 4 , _touchRect . Top , _touchRect . Width / 4 , _touchRect . Height ) ;
489493
494+ private bool HasTouchDragStarted ( Point location )
495+ {
496+ var deltaX = location . X - _touchStart . X ;
497+ var deltaY = location . Y - _touchStart . Y ;
498+ return deltaX * deltaX + deltaY * deltaY >= TouchDragThreshold * TouchDragThreshold ;
499+ }
500+
501+ private bool StartHorizontalTouchDrag ( Point location )
502+ {
503+ var deltaX = location . X - _touchStart . X ;
504+ var deltaY = location . Y - _touchStart . Y ;
505+ if ( ! HasTouchDragStarted ( location ) || Math . Abs ( deltaX ) < Math . Abs ( deltaY ) )
506+ return false ;
507+
508+ // Seed the gesture at the real press point only after it has been
509+ // classified as a drag, preventing taps from moving the content.
510+ EmitTouch ( _touchStart , force : true ) ;
511+ return true ;
512+ }
513+
490514 private void EmitTouch ( Point location , bool force = false )
491515 {
492516 if ( _lastTouchLocation == location )
0 commit comments