Ver código fonte

Add Tap size to IPlatformSettings.

And refactor that interface while we're at it. Also add a `DefaultPlatformSettings` implementation instead of implementing it in each backend with slightly different values.
Steven Kirk 3 anos atrás
pai
commit
d0eb38b6ba

+ 3 - 1
src/Avalonia.Base/Input/Gestures.cs

@@ -1,5 +1,6 @@
 using System;
 using Avalonia.Interactivity;
+using Avalonia.Platform;
 using Avalonia.VisualTree;
 
 namespace Avalonia.Input
@@ -125,7 +126,8 @@ namespace Avalonia.Input
                     e.InitialPressMouseButton is MouseButton.Left or MouseButton.Right)
                 {
                     var point = e.GetCurrentPoint((IVisual)target);
-                    var tapSize = new Size(4, 4);
+                    var settings = AvaloniaLocator.Current.GetService<IPlatformSettings>();
+                    var tapSize = settings?.GetTapSize(point.Pointer.Type) ?? new Size(4, 4);
                     var tapRect = new Rect(s_lastPressPoint, new Size())
                         .Inflate(new Thickness(tapSize.Width, tapSize.Height));
 

+ 2 - 2
src/Avalonia.Base/Input/MouseDevice.cs

@@ -128,8 +128,8 @@ namespace Avalonia.Input
                 if (source != null)
                 {
                     var settings = AvaloniaLocator.Current.GetService<IPlatformSettings>();
-                    var doubleClickTime = settings?.DoubleClickTime.TotalMilliseconds ?? 500;
-                    var doubleClickSize = settings?.DoubleClickSize ?? new Size(4, 4);
+                    var doubleClickTime = settings?.GetDoubleTapTime(PointerType.Mouse).TotalMilliseconds ?? 500;
+                    var doubleClickSize = settings?.GetDoubleTapSize(PointerType.Mouse) ?? new Size(4, 4);
 
                     if (!_lastClickRect.Contains(p) || timestamp - _lastClickTime > doubleClickTime)
                     {

+ 3 - 2
src/Avalonia.Base/Input/PenDevice.cs

@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using System.Reflection;
 using Avalonia.Input.Raw;
 using Avalonia.Platform;
 
@@ -77,8 +78,8 @@ namespace Avalonia.Input
             {
                 pointer.Capture(source);
                 var settings = AvaloniaLocator.Current.GetService<IPlatformSettings>();
-                var doubleClickTime = settings?.DoubleClickTime.TotalMilliseconds ?? 500;
-                var doubleClickSize = settings?.DoubleClickSize ?? new Size(4, 4);
+                var doubleClickTime = settings?.GetDoubleTapTime(PointerType.Pen).TotalMilliseconds ?? 500;
+                var doubleClickSize = settings?.GetDoubleTapSize(PointerType.Pen) ?? new Size(4, 4);
 
                 if (!_lastClickRect.Contains(p) || timestamp - _lastClickTime > doubleClickTime)
                 {

+ 5 - 2
src/Avalonia.Base/Input/TouchDevice.cs

@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using System.Reflection;
 using Avalonia.Input.Raw;
 using Avalonia.Platform;
 
@@ -59,16 +60,18 @@ namespace Avalonia.Input
                 else
                 {
                     var settings = AvaloniaLocator.Current.GetRequiredService<IPlatformSettings>();
+                    var doubleClickTime = settings?.GetDoubleTapTime(PointerType.Touch).TotalMilliseconds ?? 500;
+                    var doubleClickSize = settings?.GetDoubleTapSize(PointerType.Touch) ?? new Size(4, 4);
 
                     if (!_lastClickRect.Contains(args.Position)
-                        || ev.Timestamp - _lastClickTime > settings.TouchDoubleClickTime.TotalMilliseconds)
+                        || ev.Timestamp - _lastClickTime > doubleClickTime)
                     {
                         _clickCount = 0;
                     }
                     ++_clickCount;
                     _lastClickTime = ev.Timestamp;
                     _lastClickRect = new Rect(args.Position, new Size())
-                        .Inflate(new Thickness(settings.TouchDoubleClickSize.Width / 2, settings.TouchDoubleClickSize.Height / 2));
+                        .Inflate(new Thickness(doubleClickSize.Width / 2, doubleClickSize.Height / 2));
                 }
 
                 target.RaiseEvent(new PointerPressedEventArgs(target, pointer,

+ 30 - 0
src/Avalonia.Base/Platform/DefaultPlatformSettings.cs

@@ -0,0 +1,30 @@
+using System;
+using Avalonia.Input;
+
+namespace Avalonia.Platform
+{
+    /// <summary>
+    /// A default implementation of <see cref="IPlatformSettings"/> for platforms which don't have
+    /// an OS-specific implementation.
+    /// </summary>
+    public class DefaultPlatformSettings : IPlatformSettings
+    {
+        public Size GetTapSize(PointerType type)
+        {
+            return type switch
+            {
+                PointerType.Touch => new(10, 10),
+                _ => new(4, 4),
+            };
+        }
+        public Size GetDoubleTapSize(PointerType type)
+        {
+            return type switch
+            {
+                PointerType.Touch => new(16, 16),
+                _ => new(4, 4),
+            };
+        }
+        public TimeSpan GetDoubleTapTime(PointerType type) => TimeSpan.FromMilliseconds(500);
+    }
+}

+ 15 - 7
src/Avalonia.Base/Platform/IPlatformSettings.cs

@@ -1,4 +1,5 @@
 using System;
+using Avalonia.Input;
 using Avalonia.Metadata;
 
 namespace Avalonia.Platform
@@ -6,18 +7,25 @@ namespace Avalonia.Platform
     [Unstable]
     public interface IPlatformSettings
     {
-        Size DoubleClickSize { get; }
-
-        TimeSpan DoubleClickTime { get; }
+        /// <summary>
+        /// The size of the rectangle around the location of a pointer down that a pointer up
+        /// must occur within in order to register a tap gesture, in device-independent pixels.
+        /// </summary>
+        /// <param name="type">The pointer type.</param>
+        Size GetTapSize(PointerType type);
 
         /// <summary>
-        /// Determines the size of the area within that you should click twice in order for a double click to be counted.
+        /// The size of the rectangle around the location of a pointer down that a pointer up
+        /// must occur within in order to register a double-tap gesture, in device-independent
+        /// pixels.
         /// </summary>
-        Size TouchDoubleClickSize { get; }
+        /// <param name="type">The pointer type.</param>
+        Size GetDoubleTapSize(PointerType type);
 
         /// <summary>
-        /// Determines the time span that what will be used to determine the double-click.
+        /// Gets the maximum time that may occur between the first and second click of a double-
+        /// tap gesture.
         /// </summary>
-        TimeSpan TouchDoubleClickTime { get; }
+        TimeSpan GetDoubleTapTime(PointerType type);
     }
 }

+ 2 - 9
src/Avalonia.DesignerSupport/Remote/PreviewerWindowingPlatform.cs

@@ -9,7 +9,7 @@ using Avalonia.Rendering;
 
 namespace Avalonia.DesignerSupport.Remote
 {
-    class PreviewerWindowingPlatform : IWindowingPlatform, IPlatformSettings
+    class PreviewerWindowingPlatform : IWindowingPlatform
     {
         static readonly IKeyboardDevice Keyboard = new KeyboardDevice();
         private static IAvaloniaRemoteTransportConnection s_transport;
@@ -51,7 +51,7 @@ namespace Avalonia.DesignerSupport.Remote
                 .Bind<IClipboard>().ToSingleton<ClipboardStub>()
                 .Bind<ICursorFactory>().ToSingleton<CursorFactoryStub>()
                 .Bind<IKeyboardDevice>().ToConstant(Keyboard)
-                .Bind<IPlatformSettings>().ToConstant(instance)
+                .Bind<IPlatformSettings>().ToSingleton<DefaultPlatformSettings>()
                 .Bind<IPlatformThreadingInterface>().ToConstant(threading)
                 .Bind<IRenderLoop>().ToConstant(new RenderLoop())
                 .Bind<IRenderTimer>().ToConstant(new DefaultRenderTimer(60))
@@ -60,12 +60,5 @@ namespace Avalonia.DesignerSupport.Remote
                 .Bind<PlatformHotkeyConfiguration>().ToSingleton<PlatformHotkeyConfiguration>();
 
         }
-
-        public Size DoubleClickSize { get; } = new Size(2, 2);
-        public TimeSpan DoubleClickTime { get; } = TimeSpan.FromMilliseconds(500);
-
-        public Size TouchDoubleClickSize => new Size(16, 16);
-
-        public TimeSpan TouchDoubleClickTime => DoubleClickTime;
     }
 }

+ 1 - 1
src/Avalonia.Headless/AvaloniaHeadlessPlatform.cs

@@ -63,7 +63,7 @@ namespace Avalonia.Headless
                 .Bind<IPlatformThreadingInterface>().ToConstant(new HeadlessPlatformThreadingInterface())
                 .Bind<IClipboard>().ToSingleton<HeadlessClipboardStub>()
                 .Bind<ICursorFactory>().ToSingleton<HeadlessCursorFactoryStub>()
-                .Bind<IPlatformSettings>().ToConstant(new HeadlessPlatformSettingsStub())
+                .Bind<IPlatformSettings>().ToSingleton<DefaultPlatformSettings>()
                 .Bind<IPlatformIconLoader>().ToSingleton<HeadlessIconLoaderStub>()
                 .Bind<IKeyboardDevice>().ToConstant(new KeyboardDevice())
                 .Bind<IRenderLoop>().ToConstant(new RenderLoop())

+ 0 - 10
src/Avalonia.Headless/HeadlessPlatformStubs.cs

@@ -65,16 +65,6 @@ namespace Avalonia.Headless
         }
     }
 
-    class HeadlessPlatformSettingsStub : IPlatformSettings
-    {
-        public Size DoubleClickSize { get; } = new Size(2, 2);
-        public TimeSpan DoubleClickTime { get; } = TimeSpan.FromMilliseconds(500);
-
-        public Size TouchDoubleClickSize => new Size(16,16);
-
-        public TimeSpan TouchDoubleClickTime => DoubleClickTime;
-    }
-
     class HeadlessGlyphTypefaceImpl : IGlyphTypeface
     {
         public FontMetrics Metrics => new FontMetrics

+ 2 - 12
src/Avalonia.Native/AvaloniaNativePlatform.cs

@@ -14,7 +14,7 @@ using MicroCom.Runtime;
 
 namespace Avalonia.Native
 {
-    class AvaloniaNativePlatform : IPlatformSettings, IWindowingPlatform
+    class AvaloniaNativePlatform : IWindowingPlatform
     {
         private readonly IAvaloniaNativeFactory _factory;
         private AvaloniaNativePlatformOptions _options;
@@ -26,16 +26,6 @@ namespace Avalonia.Native
         internal static readonly KeyboardDevice KeyboardDevice = new KeyboardDevice();
         [CanBeNull] internal static Compositor Compositor { get; private set; }
 
-        public Size DoubleClickSize => new Size(4, 4);
-
-        public TimeSpan DoubleClickTime => TimeSpan.FromMilliseconds(500); //TODO
-
-        /// <inheritdoc cref="IPlatformSettings.TouchDoubleClickSize"/>
-        public Size TouchDoubleClickSize => new Size(16, 16);
-
-        /// <inheritdoc cref="IPlatformSettings.TouchDoubleClickTime"/>
-        public TimeSpan TouchDoubleClickTime => DoubleClickTime;
-
         public static AvaloniaNativePlatform Initialize(IntPtr factory, AvaloniaNativePlatformOptions options)
         {
             var result = new AvaloniaNativePlatform(MicroComRuntime.CreateProxyFor<IAvaloniaNativeFactory>(factory, true));
@@ -113,7 +103,7 @@ namespace Avalonia.Native
                 .Bind<ICursorFactory>().ToConstant(new CursorFactory(_factory.CreateCursorFactory()))
                 .Bind<IPlatformIconLoader>().ToSingleton<IconLoader>()
                 .Bind<IKeyboardDevice>().ToConstant(KeyboardDevice)
-                .Bind<IPlatformSettings>().ToConstant(this)
+                .Bind<IPlatformSettings>().ToSingleton<DefaultPlatformSettings>()
                 .Bind<IWindowingPlatform>().ToConstant(this)
                 .Bind<IClipboard>().ToConstant(new ClipboardImpl(_factory.CreateClipboard()))
                 .Bind<IRenderTimer>().ToConstant(new DefaultRenderTimer(60))

+ 4 - 2
src/Avalonia.Native/DoubleClickHelper.cs

@@ -1,3 +1,4 @@
+using Avalonia.Input;
 using Avalonia.Platform;
 
 namespace Avalonia.Native
@@ -13,7 +14,8 @@ namespace Avalonia.Native
             Point p)
         {
             var settings = AvaloniaLocator.Current.GetService<IPlatformSettings>();
-            var doubleClickTime = settings.DoubleClickTime.TotalMilliseconds;
+            var doubleClickTime = settings?.GetDoubleTapTime(PointerType.Mouse).TotalMilliseconds ?? 500;
+            var doubleClickSize = settings?.GetDoubleTapSize(PointerType.Mouse) ?? new Size(4, 4);
 
             if (!_lastClickRect.Contains(p) || timestamp - _lastClickTime > doubleClickTime)
             {
@@ -23,7 +25,7 @@ namespace Avalonia.Native
             ++_clickCount;
             _lastClickTime = timestamp;
             _lastClickRect = new Rect(p, new Size())
-                .Inflate(new Thickness(settings.DoubleClickSize.Width / 2, settings.DoubleClickSize.Height / 2));
+                .Inflate(new Thickness(doubleClickSize.Width / 2, doubleClickSize.Height / 2));
 
             return _clickCount == 2;
         }

+ 0 - 17
src/Avalonia.X11/Stubs.cs

@@ -1,17 +0,0 @@
-using System;
-using Avalonia.Platform;
-
-namespace Avalonia.X11
-{
-    class PlatformSettingsStub : IPlatformSettings
-    {
-        public Size DoubleClickSize { get; } = new Size(2, 2);
-        public TimeSpan DoubleClickTime { get; } = TimeSpan.FromMilliseconds(500);
-
-        /// <inheritdoc cref="IPlatformSettings.TouchDoubleClickSize"/>
-        public Size TouchDoubleClickSize => new Size(16, 16);
-
-        /// <inheritdoc cref="IPlatformSettings.TouchDoubleClickTime"/>
-        public TimeSpan TouchDoubleClickTime => DoubleClickTime;
-    }
-}

+ 1 - 1
src/Avalonia.X11/X11Platform.cs

@@ -80,7 +80,7 @@ namespace Avalonia.X11
                 .Bind<IKeyboardDevice>().ToFunc(() => KeyboardDevice)
                 .Bind<ICursorFactory>().ToConstant(new X11CursorFactory(Display))
                 .Bind<IClipboard>().ToConstant(new X11Clipboard(this))
-                .Bind<IPlatformSettings>().ToConstant(new PlatformSettingsStub())
+                .Bind<IPlatformSettings>().ToSingleton<DefaultPlatformSettings>()
                 .Bind<IPlatformIconLoader>().ToConstant(new X11IconLoader())
                 .Bind<IMountedVolumeInfoProvider>().ToConstant(new LinuxMountedVolumeInfoProvider())
                 .Bind<IPlatformLifetimeEventsImpl>().ToConstant(new X11PlatformLifetimeEvents(this));

+ 1 - 1
src/Linux/Avalonia.LinuxFramebuffer/LinuxFramebufferPlatform.cs

@@ -51,7 +51,7 @@ namespace Avalonia.LinuxFramebuffer
                 .Bind<IRenderLoop>().ToConstant(new RenderLoop())
                 .Bind<ICursorFactory>().ToTransient<CursorFactoryStub>()
                 .Bind<IKeyboardDevice>().ToConstant(new KeyboardDevice())
-                .Bind<IPlatformSettings>().ToSingleton<PlatformSettings>()
+                .Bind<IPlatformSettings>().ToSingleton<DefaultPlatformSettings>()
                 .Bind<PlatformHotkeyConfiguration>().ToSingleton<PlatformHotkeyConfiguration>();
             
             Compositor = new Compositor(

+ 0 - 9
src/Linux/Avalonia.LinuxFramebuffer/Stubs.cs

@@ -14,13 +14,4 @@ namespace Avalonia.LinuxFramebuffer
             public void Dispose() { }
         }
     }
-    internal class PlatformSettings : IPlatformSettings
-    {
-        public Size DoubleClickSize { get; } = new Size(4, 4);
-        public TimeSpan DoubleClickTime { get; } = new TimeSpan(0, 0, 0, 0, 500);
-
-        public Size TouchDoubleClickSize => new Size(16,16);
-
-        public TimeSpan TouchDoubleClickTime => DoubleClickTime;
-    }
 }

+ 20 - 7
src/Web/Avalonia.Web/WindowingPlatform.cs

@@ -45,13 +45,6 @@ namespace Avalonia.Web
                 .Bind<PlatformHotkeyConfiguration>().ToSingleton<PlatformHotkeyConfiguration>();
         }
 
-        public Size DoubleClickSize { get; } = new Size(2, 2);
-
-        public TimeSpan DoubleClickTime { get; } = TimeSpan.FromMilliseconds(500);
-
-        public Size TouchDoubleClickSize => new Size(16, 16);
-
-        public TimeSpan TouchDoubleClickTime => DoubleClickTime;
         public void RunLoop(CancellationToken cancellationToken)
         {
             throw new NotSupportedException();
@@ -101,5 +94,25 @@ namespace Avalonia.Web
         {
             return AvaloniaLocator.Current.GetRequiredService<IRuntimePlatform>();
         }
+
+        Size IPlatformSettings.GetTapSize(PointerType type)
+        {
+            return type switch
+            {
+                PointerType.Touch => new(10, 10),
+                _ => new(4, 4),
+            };
+        }
+
+        Size IPlatformSettings.GetDoubleTapSize(PointerType type)
+        {
+            return type switch
+            {
+                PointerType.Touch => new(16, 16),
+                _ => new(4, 4),
+            };
+        }
+
+        TimeSpan IPlatformSettings.GetDoubleTapTime(PointerType type) => TimeSpan.FromMilliseconds(500);
     }
 }

+ 20 - 11
src/Windows/Avalonia.Win32/Win32Platform.cs

@@ -130,17 +130,6 @@ namespace Avalonia.Win32
         
         internal static Compositor Compositor { get; private set; }
 
-        public Size DoubleClickSize => new Size(
-            UnmanagedMethods.GetSystemMetrics(UnmanagedMethods.SystemMetric.SM_CXDOUBLECLK),
-            UnmanagedMethods.GetSystemMetrics(UnmanagedMethods.SystemMetric.SM_CYDOUBLECLK));
-
-        public TimeSpan DoubleClickTime => TimeSpan.FromMilliseconds(UnmanagedMethods.GetDoubleClickTime());
-
-        /// <inheritdoc cref="IPlatformSettings.TouchDoubleClickSize"/>
-        public Size TouchDoubleClickSize => new Size(16,16);
-
-        /// <inheritdoc cref="IPlatformSettings.TouchDoubleClickTime"/>
-        public TimeSpan TouchDoubleClickTime => DoubleClickTime;
         public static void Initialize()
         {
             Initialize(new Win32PlatformOptions());
@@ -398,5 +387,25 @@ namespace Avalonia.Win32
 
             SetProcessDPIAware();
         }
+
+        Size IPlatformSettings.GetTapSize(PointerType type)
+        {
+            return type switch
+            {
+                PointerType.Touch => new(10, 10),
+                _ => new(GetSystemMetrics(SystemMetric.SM_CXDRAG), GetSystemMetrics(SystemMetric.SM_CYDRAG)),
+            };
+        }
+
+        Size IPlatformSettings.GetDoubleTapSize(PointerType type)
+        {
+            return type switch
+            {
+                PointerType.Touch => new(16, 16),
+                _ => new(GetSystemMetrics(SystemMetric.SM_CXDOUBLECLK), GetSystemMetrics(SystemMetric.SM_CYDOUBLECLK)),
+            };
+        }
+
+        TimeSpan IPlatformSettings.GetDoubleTapTime(PointerType type) => TimeSpan.FromMilliseconds(GetDoubleClickTime());
     }
 }

+ 2 - 15
src/iOS/Avalonia.iOS/Platform.cs

@@ -28,32 +28,19 @@ namespace Avalonia.iOS
         public static EaglFeature GlFeature;
         public static DisplayLinkTimer Timer;
         internal static Compositor Compositor { get; private set; }
-        
-        class PlatformSettings : IPlatformSettings
-        {
-            /// <inheritdoc cref="IPlatformSettings.TouchDoubleClickSize"/>
-            public Size TouchDoubleClickSize => new Size(10, 10);
-
-            /// <inheritdoc cref="IPlatformSettings.TouchDoubleClickTime"/>
-            public TimeSpan TouchDoubleClickTime => TimeSpan.FromMilliseconds(500);
-
-            public Size DoubleClickSize => new Size(4, 4);
-
-            public TimeSpan DoubleClickTime => TouchDoubleClickTime;
-        }
 
         public static void Register()
         {
             GlFeature ??= new EaglFeature();
             Timer ??= new DisplayLinkTimer();
             var keyboard = new KeyboardDevice();
-            
+
             AvaloniaLocator.CurrentMutable
                 .Bind<IPlatformOpenGlInterface>().ToConstant(GlFeature)
                 .Bind<ICursorFactory>().ToConstant(new CursorFactoryStub())
                 .Bind<IWindowingPlatform>().ToConstant(new WindowingPlatformStub())
                 .Bind<IClipboard>().ToConstant(new ClipboardImpl())
-                .Bind<IPlatformSettings>().ToConstant(new PlatformSettings())
+                .Bind<IPlatformSettings>().ToSingleton<DefaultPlatformSettings>()
                 .Bind<IPlatformIconLoader>().ToConstant(new PlatformIconLoaderStub())
                 .Bind<PlatformHotkeyConfiguration>().ToSingleton<PlatformHotkeyConfiguration>()
                 .Bind<IRenderLoop>().ToSingleton<RenderLoop>()

+ 1 - 1
tests/Avalonia.Base.UnitTests/Input/TouchDeviceTests.cs

@@ -209,7 +209,7 @@ namespace Avalonia.Input.UnitTests
             var unitTestApp = UnitTestApplication.Start(
                 new TestServices(inputManager: new InputManager()));
             var iSettingsMock = new Mock<IPlatformSettings>();
-            iSettingsMock.Setup(x => x.TouchDoubleClickTime).Returns(doubleClickTime);
+            iSettingsMock.Setup(x => x.GetDoubleTapTime(It.IsAny<PointerType>())).Returns(doubleClickTime);
             AvaloniaLocator.CurrentMutable.BindToSelf(this)
                .Bind<IPlatformSettings>().ToConstant(iSettingsMock.Object);
             return unitTestApp;