From 737e5460484d88366a975339f521d08de1ca1e27 Mon Sep 17 00:00:00 2001 From: Gess1t Date: Tue, 8 Oct 2024 23:57:30 +0200 Subject: [PATCH 01/19] Fix back button during setup & edit --- .../ViewModels/GestureSetupWizardViewModel.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Touch-Gestures.UX/ViewModels/GestureSetupWizardViewModel.cs b/Touch-Gestures.UX/ViewModels/GestureSetupWizardViewModel.cs index 6fd8b50..2660310 100644 --- a/Touch-Gestures.UX/ViewModels/GestureSetupWizardViewModel.cs +++ b/Touch-Gestures.UX/ViewModels/GestureSetupWizardViewModel.cs @@ -46,7 +46,7 @@ public GestureSetupWizardViewModel() GestureSelectionScreenViewModel.BackRequested += OnBackRequestedAhead; GestureSelectionScreenViewModel.GestureSelected += OnGestureSelected; - GestureSetupScreenViewModel.BackRequested += OnBackRequestedAhead; + //GestureSetupScreenViewModel.BackRequested += OnBackRequestedAhead; } public GestureSetupWizardViewModel(Rect bounds) : this() @@ -70,10 +70,10 @@ public GestureSetupWizardViewModel(Rect bounds) : this() protected override void GoBack() { - if (NextViewModel is GestureSelectionScreenViewModel || (NextViewModel is GestureSetupScreenViewModel && _editedGesture != null)) - BackRequested?.Invoke(this, EventArgs.Empty); - else + if (NextViewModel is GestureSetupScreenViewModel && _editedGesture == null) NextViewModel = GestureSelectionScreenViewModel; + else if (NextViewModel is GestureSelectionScreenViewModel || NextViewModel is GestureSetupScreenViewModel) + BackRequested?.Invoke(this, EventArgs.Empty); } /// From a9ac856e2a88d8c2485cd7dde2b39f8f3aaf48b1 Mon Sep 17 00:00:00 2001 From: Gess1t Date: Wed, 9 Oct 2024 00:00:17 +0200 Subject: [PATCH 02/19] Add IsMultiTouch to Settings & change version to 1 --- .../Entities/BindableProfile.cs | 39 ++++++++++++++++++- .../Entities/SerializableProfile.cs | 6 ++- .../Entities/SerializableSettings.cs | 2 +- Touch-Gestures.Lib/Entities/Settings.cs | 2 +- .../Interfaces/IGesturesProfile.cs | 19 +++++++++ 5 files changed, 63 insertions(+), 5 deletions(-) create mode 100644 Touch-Gestures.Lib/Interfaces/IGesturesProfile.cs diff --git a/Touch-Gestures.Lib/Entities/BindableProfile.cs b/Touch-Gestures.Lib/Entities/BindableProfile.cs index f116f12..ca75722 100644 --- a/Touch-Gestures.Lib/Entities/BindableProfile.cs +++ b/Touch-Gestures.Lib/Entities/BindableProfile.cs @@ -1,19 +1,19 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Collections.ObjectModel; using System.Reflection; using Newtonsoft.Json; using OpenTabletDriver.Plugin; using TouchGestures.Lib.Entities.Gestures; using TouchGestures.Lib.Entities.Gestures.Bases; using TouchGestures.Lib.Entities.Tablet; +using TouchGestures.Lib.Interfaces; using TouchGestures.Lib.Serializables.Gestures; namespace TouchGestures.Lib.Entities { [JsonObject(MemberSerialization.OptIn)] - public class BindableProfile : IEnumerable + public class BindableProfile : IGesturesProfile { public event EventHandler? ProfileChanged; @@ -22,6 +22,9 @@ public class BindableProfile : IEnumerable [JsonProperty] public string Name { get; set; } = string.Empty; + [JsonProperty] + public bool IsMultiTouch { get; set; } = true; + [JsonProperty] public List TapGestures { get; set; } = new(); @@ -89,6 +92,30 @@ public void Add(Gesture gesture) } } + public void Remove(Gesture gesture) + { + switch(gesture) + { + case BindableTapGesture tapGesture: + TapGestures.Remove(tapGesture); + break; + case BindableHoldGesture holdGesture: + HoldGestures.Remove(holdGesture); + break; + case BindableSwipeGesture swipeGesture: + SwipeGestures.Remove(swipeGesture); + break; + case BindablePanGesture panGesture: + PanGestures.Remove(panGesture); + break; + case BindablePinchGesture pinchGesture: + RemovePinch(pinchGesture); + break; + default: + throw new ArgumentException("Unknown gesture type."); + } + } + public void Update(SerializableProfile profile, SharedTabletReference tablet, Dictionary identifierToPlugin) { FromSerializable(profile, identifierToPlugin, tablet, this); @@ -113,6 +140,14 @@ private void AddPinch(BindablePinchGesture pinchGesture) RotateGestures.Add(pinchGesture); } + private void RemovePinch(BindablePinchGesture pinchGesture) + { + if (pinchGesture.DistanceThreshold > 0) + PinchGestures.Remove(pinchGesture); + else + RotateGestures.Remove(pinchGesture); + } + #endregion #region Event Handlers diff --git a/Touch-Gestures.Lib/Entities/SerializableProfile.cs b/Touch-Gestures.Lib/Entities/SerializableProfile.cs index c202b5a..3e03e87 100644 --- a/Touch-Gestures.Lib/Entities/SerializableProfile.cs +++ b/Touch-Gestures.Lib/Entities/SerializableProfile.cs @@ -3,16 +3,20 @@ using System.Collections.Generic; using Newtonsoft.Json; using TouchGestures.Lib.Entities.Gestures.Bases; +using TouchGestures.Lib.Interfaces; using TouchGestures.Lib.Serializables.Gestures; namespace TouchGestures.Lib.Entities { [JsonObject(MemberSerialization.OptIn)] - public class SerializableProfile : IEnumerable + public class SerializableProfile : IGesturesProfile { [JsonProperty] public string Name { get; set; } = string.Empty; + [JsonProperty] + public bool IsMultiTouch { get; set; } = true; + [JsonProperty] public List TapGestures { get; set; } = new(); diff --git a/Touch-Gestures.Lib/Entities/SerializableSettings.cs b/Touch-Gestures.Lib/Entities/SerializableSettings.cs index 5314b8d..4718600 100644 --- a/Touch-Gestures.Lib/Entities/SerializableSettings.cs +++ b/Touch-Gestures.Lib/Entities/SerializableSettings.cs @@ -7,7 +7,7 @@ namespace TouchGestures.Lib.Entities public class SerializableSettings { [JsonProperty] - public int Version { get; set; } + public int Version { get; set; } = 1; [JsonProperty] public List Profiles { get; set; } = new(); diff --git a/Touch-Gestures.Lib/Entities/Settings.cs b/Touch-Gestures.Lib/Entities/Settings.cs index ba4b216..3a289ea 100644 --- a/Touch-Gestures.Lib/Entities/Settings.cs +++ b/Touch-Gestures.Lib/Entities/Settings.cs @@ -38,7 +38,7 @@ public Settings() #region Properties [JsonProperty] - public int Version { get; set; } + public int Version { get; set; } = 1; [JsonProperty] public List Profiles { get; set; } = new(); diff --git a/Touch-Gestures.Lib/Interfaces/IGesturesProfile.cs b/Touch-Gestures.Lib/Interfaces/IGesturesProfile.cs new file mode 100644 index 0000000..2a8f7d6 --- /dev/null +++ b/Touch-Gestures.Lib/Interfaces/IGesturesProfile.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; +using Newtonsoft.Json; +using TouchGestures.Lib.Entities.Gestures.Bases; + +namespace TouchGestures.Lib.Interfaces +{ + public interface IGesturesProfile : IEnumerable + { + [JsonProperty] + string Name { get; } + + [JsonProperty] + bool IsMultiTouch { get; } + + void Add(Gesture gesture); + + void Remove(Gesture gesture); + } +} \ No newline at end of file From 3802dcd74b0568716c72a1acdd5f9aec65af4bc8 Mon Sep 17 00:00:00 2001 From: Gess1t Date: Wed, 9 Oct 2024 00:04:23 +0200 Subject: [PATCH 03/19] Prepare UX for Soft Keys Support for pens --- .../Attributes/MultiTouchOnlyAttribute.cs | 9 +++++++++ .../ViewModels/BindingsOverviewViewModel.cs | 6 ++++-- .../Controls/Setups/GestureSetupViewModel.cs | 15 +++++++++++++++ .../Controls/Setups/HoldSetupViewModel.cs | 6 ++++-- .../Controls/Setups/PanSetupViewModel.cs | 3 ++- .../Controls/Setups/PinchSetupViewModel.cs | 5 ++++- .../Controls/Setups/RotateSetupViewModel.cs | 3 ++- .../Controls/Setups/SwipeSetupViewModel.cs | 3 ++- .../Controls/Setups/TapSetupViewModel.cs | 15 ++++++++++++--- .../Controls/Tiles/GestureTileViewModel.cs | 13 ++++++++++--- .../ViewModels/GestureSelectionScreenViewModel.cs | 6 ++++++ .../ViewModels/GestureSetupScreenViewModel.cs | 15 +++++++++++++-- .../ViewModels/GestureSetupWizardViewModel.cs | 5 +++-- .../Views/Gestures/GestureSelectionScreen.axaml | 2 +- 14 files changed, 87 insertions(+), 19 deletions(-) create mode 100644 Touch-Gestures.UX/Attributes/MultiTouchOnlyAttribute.cs diff --git a/Touch-Gestures.UX/Attributes/MultiTouchOnlyAttribute.cs b/Touch-Gestures.UX/Attributes/MultiTouchOnlyAttribute.cs new file mode 100644 index 0000000..c0216b0 --- /dev/null +++ b/Touch-Gestures.UX/Attributes/MultiTouchOnlyAttribute.cs @@ -0,0 +1,9 @@ +using System; + +namespace TouchGestures.UX.Attributes; + +[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] +public sealed class MultiTouchOnlyAttribute(bool isMultiTouchOnly) : Attribute +{ + public bool IsMultiTouchOnly { get; } = isMultiTouchOnly; +} diff --git a/Touch-Gestures.UX/ViewModels/BindingsOverviewViewModel.cs b/Touch-Gestures.UX/ViewModels/BindingsOverviewViewModel.cs index 4dcd385..f689e37 100644 --- a/Touch-Gestures.UX/ViewModels/BindingsOverviewViewModel.cs +++ b/Touch-Gestures.UX/ViewModels/BindingsOverviewViewModel.cs @@ -214,7 +214,8 @@ public void StartSetupWizard() var x = Math.Round(SelectedTablet.Reference.Size.X, 5); var y = Math.Round(SelectedTablet.Reference.Size.Y, 5); - var setupWizard = new GestureSetupWizardViewModel(new Rect(0, 0, x, y)); + var setupWizard = new GestureSetupWizardViewModel(new Rect(0, 0, x, y), + SelectedTablet.Profile.IsMultiTouch); setupWizard.SetupCompleted += OnSetupCompleted; setupWizard.BackRequested += OnBackRequestedAhead; @@ -325,7 +326,8 @@ private void OnEditRequested(object? sender, EventArgs e) var x = Math.Round(SelectedTablet.Reference.Size.X, 5); var y = Math.Round(SelectedTablet.Reference.Size.Y, 5); - var setupWizard = new GestureSetupWizardViewModel(new Rect(0, 0, x, y)); + var setupWizard = new GestureSetupWizardViewModel(new Rect(0, 0, x, y), + SelectedTablet.Profile.IsMultiTouch); // We need to check whenever the edit is completed & when te user goes back setupWizard.EditCompleted += (s, args) => OnEditCompleted(s, bindingDisplay, args); diff --git a/Touch-Gestures.UX/ViewModels/Controls/Setups/GestureSetupViewModel.cs b/Touch-Gestures.UX/ViewModels/Controls/Setups/GestureSetupViewModel.cs index 365f48e..a78bd4a 100644 --- a/Touch-Gestures.UX/ViewModels/Controls/Setups/GestureSetupViewModel.cs +++ b/Touch-Gestures.UX/ViewModels/Controls/Setups/GestureSetupViewModel.cs @@ -127,6 +127,21 @@ public int SelectedGestureSetupPickIndex } } + /// + /// Whether single touch gestures are supported for this setup. + /// + public virtual bool SingleTouchSupported { get; } = true; + + /// + /// Whether option selection is enabled for this setup when not multi-touch. + /// + public virtual bool SingleTouchOptionSelectionEnabled { get; } = true; + + /// + /// Whether this setup is for a multi-touch gesture or not. + /// + public bool IsMultiTouchSetup { get; set; } = true; + #endregion #region Methods diff --git a/Touch-Gestures.UX/ViewModels/Controls/Setups/HoldSetupViewModel.cs b/Touch-Gestures.UX/ViewModels/Controls/Setups/HoldSetupViewModel.cs index d2d91c3..3e1e000 100644 --- a/Touch-Gestures.UX/ViewModels/Controls/Setups/HoldSetupViewModel.cs +++ b/Touch-Gestures.UX/ViewModels/Controls/Setups/HoldSetupViewModel.cs @@ -20,7 +20,8 @@ namespace TouchGestures.UX.ViewModels.Controls.Setups; #nullable enable [Name("Hold"), Icon("Assets/Setups/Hold/hold.png"), - Description("A gesture completed by holding any specified number of fingers down for a specified amount of time")] + Description("A gesture completed by holding any specified number of fingers down for a specified amount of time"), + MultiTouchOnly(false)] public partial class HoldSetupViewModel : TapSetupViewModel { private readonly SerializableHoldGesture _gesture; @@ -49,6 +50,7 @@ public HoldSetupViewModel(Gesture gesture, Rect fullArea) : this(true) SelectedGestureSetupPickIndex = serializedHoldGesture.RequiredTouchesCount - 1; BindingDisplay.PluginProperty = serializedHoldGesture.PluginProperty; + BindingDisplay.Description = $"{serializedHoldGesture.RequiredTouchesCount}-Touch Hold"; SetupArea(fullArea, serializedHoldGesture.Bounds); } @@ -80,7 +82,7 @@ public HoldSetupViewModel(bool isEditing = false) SelectedGestureSetupPickIndex = 0; - BindingDisplay = new BindingDisplayViewModel(); + BindingDisplay = new BindingDisplayViewModel("1-Touch Hold", string.Empty, null); AreaDisplay = new AreaDisplayViewModel(); _gesture = new SerializableHoldGesture(); diff --git a/Touch-Gestures.UX/ViewModels/Controls/Setups/PanSetupViewModel.cs b/Touch-Gestures.UX/ViewModels/Controls/Setups/PanSetupViewModel.cs index d7578f8..f1efc60 100644 --- a/Touch-Gestures.UX/ViewModels/Controls/Setups/PanSetupViewModel.cs +++ b/Touch-Gestures.UX/ViewModels/Controls/Setups/PanSetupViewModel.cs @@ -19,7 +19,8 @@ namespace TouchGestures.UX.ViewModels.Controls.Setups; using static AssetLoaderExtensions; [Name("Pan"), Icon("Assets/Setups/Swipe/swipe_up.png"), - Description("A gesture that can be repeated by swiping in a specified direction, without releasing the touch point.")] + Description("A gesture that can be repeated by swiping in a specified direction, without releasing the touch point."), + MultiTouchOnly(false)] public partial class PanSetupViewModel : SwipeSetupViewModel { private readonly SerializablePanGesture _gesture; diff --git a/Touch-Gestures.UX/ViewModels/Controls/Setups/PinchSetupViewModel.cs b/Touch-Gestures.UX/ViewModels/Controls/Setups/PinchSetupViewModel.cs index ddf9cc4..b72dc49 100644 --- a/Touch-Gestures.UX/ViewModels/Controls/Setups/PinchSetupViewModel.cs +++ b/Touch-Gestures.UX/ViewModels/Controls/Setups/PinchSetupViewModel.cs @@ -20,7 +20,8 @@ namespace TouchGestures.UX.ViewModels.Controls.Setups; #nullable enable [Name("Pinch"), Icon("Assets/Setups/Pinch/pinch_inner.png"), - Description("A gesture completed by pinching, simillar to how you would zoom in, in various application")] + Description("A gesture completed by pinching, simillar to how you would zoom in, in various application"), + MultiTouchOnly(true)] public partial class PinchSetupViewModel : GestureSetupViewModel { private readonly SerializablePinchGesture _gesture; @@ -33,6 +34,8 @@ public partial class PinchSetupViewModel : GestureSetupViewModel [ObservableProperty] protected bool _isInner; + public override bool SingleTouchSupported { get; } = false; + #endregion #region Constructors diff --git a/Touch-Gestures.UX/ViewModels/Controls/Setups/RotateSetupViewModel.cs b/Touch-Gestures.UX/ViewModels/Controls/Setups/RotateSetupViewModel.cs index 2f87ce7..a5b7180 100644 --- a/Touch-Gestures.UX/ViewModels/Controls/Setups/RotateSetupViewModel.cs +++ b/Touch-Gestures.UX/ViewModels/Controls/Setups/RotateSetupViewModel.cs @@ -20,7 +20,8 @@ namespace TouchGestures.UX.ViewModels.Controls.Setups; #nullable enable [Name("Rotation"), Icon("Assets/Setups/Rotation/rotation_clockwise.png"), - Description("A gesture completed by pinching & rotating 2 fingers, simillar to how you would rotate a map in various application")] + Description("A gesture completed by pinching & rotating 2 fingers, simillar to how you would rotate a map in various application"), + MultiTouchOnly(true)] public partial class RotateSetupViewModel : PinchSetupViewModel { private readonly SerializablePinchGesture _gesture; diff --git a/Touch-Gestures.UX/ViewModels/Controls/Setups/SwipeSetupViewModel.cs b/Touch-Gestures.UX/ViewModels/Controls/Setups/SwipeSetupViewModel.cs index 2d2b4db..a449dc6 100644 --- a/Touch-Gestures.UX/ViewModels/Controls/Setups/SwipeSetupViewModel.cs +++ b/Touch-Gestures.UX/ViewModels/Controls/Setups/SwipeSetupViewModel.cs @@ -21,7 +21,8 @@ namespace TouchGestures.UX.ViewModels.Controls.Setups; using static AssetLoaderExtensions; [Name("Swipe"), Icon("Assets/Setups/Swipe/swipe_up.png"), -Description("A gesture completed by swiping in a specified direction, then releasing the touch point.")] + Description("A gesture completed by swiping in a specified direction, then releasing the touch point."), + MultiTouchOnly(false)] public partial class SwipeSetupViewModel : GestureSetupViewModel { private readonly SerializableSwipeGesture _gesture; diff --git a/Touch-Gestures.UX/ViewModels/Controls/Setups/TapSetupViewModel.cs b/Touch-Gestures.UX/ViewModels/Controls/Setups/TapSetupViewModel.cs index d96a0bc..308c0ba 100644 --- a/Touch-Gestures.UX/ViewModels/Controls/Setups/TapSetupViewModel.cs +++ b/Touch-Gestures.UX/ViewModels/Controls/Setups/TapSetupViewModel.cs @@ -20,7 +20,8 @@ namespace TouchGestures.UX.ViewModels.Controls.Setups; #nullable enable [Name("Tap"), Icon("Assets/Setups/Tap/tap_triple.png"), - Description("A gesture completed by tapping with any specified number of fingers")] + Description("A gesture completed by tapping with any specified number of fingers"), + MultiTouchOnly(false)] public partial class TapSetupViewModel : GestureSetupViewModel { private readonly SerializableTapGesture _gesture; @@ -70,7 +71,7 @@ public TapSetupViewModel(bool isEditing = false) SelectedGestureSetupPickIndex = 0; - BindingDisplay = new BindingDisplayViewModel(); + BindingDisplay = new BindingDisplayViewModel("1-Touch Tap", string.Empty, null); AreaDisplay = new AreaDisplayViewModel(); _gesture = new SerializableTapGesture(); @@ -96,6 +97,7 @@ public TapSetupViewModel(Gesture gesture, Rect fullArea) : this(true) SelectedGestureSetupPickIndex = serializedTapGesture.RequiredTouchesCount - 1; BindingDisplay.PluginProperty = serializedTapGesture.PluginProperty; + BindingDisplay.Description = $"{serializedTapGesture.RequiredTouchesCount}-Touch Tap"; SetupArea(fullArea, serializedTapGesture.Bounds); } @@ -109,11 +111,18 @@ protected override void SubscribeToSettingsChanges() #endregion + #region Properties + + public override bool SingleTouchOptionSelectionEnabled { get; } = false; + + #endregion + #region Methods protected override void GoBack() { - if (IsBindingSelectionStepActive) // Step 2 + // We skip the option selection in the case a setup is single-touch. (Pen) + if (IsBindingSelectionStepActive && IsMultiTouchSetup) // Step 2 { IsBindingSelectionStepActive = false; IsOptionsSelectionStepActive = true; diff --git a/Touch-Gestures.UX/ViewModels/Controls/Tiles/GestureTileViewModel.cs b/Touch-Gestures.UX/ViewModels/Controls/Tiles/GestureTileViewModel.cs index d54ce01..eadcbd9 100644 --- a/Touch-Gestures.UX/ViewModels/Controls/Tiles/GestureTileViewModel.cs +++ b/Touch-Gestures.UX/ViewModels/Controls/Tiles/GestureTileViewModel.cs @@ -7,9 +7,9 @@ namespace TouchGestures.UX.ViewModels.Controls.Tiles { - [Name("Non-Implemented")] - [Description("This gesture has not been implemented yet")] - [Icon("")] + [Name("Non-Implemented"), Icon(""), + Description("This gesture has not been implemented yet"), + MultiTouchOnly(false)] public partial class GestureTileViewModel : GestureTileViewModel where T : GestureSetupViewModel, new() { private const string DEFAULT_NAME = "Non-Implemented"; @@ -20,10 +20,12 @@ public GestureTileViewModel() var nameAttribute = (NameAttribute?)Attribute.GetCustomAttribute(typeof(T), typeof(NameAttribute)); var descriptionAttribute = (DescriptionAttribute?)Attribute.GetCustomAttribute(typeof(T), typeof(DescriptionAttribute)); var iconAttribute = (IconAttribute?)Attribute.GetCustomAttribute(typeof(T), typeof(IconAttribute)); + var multiTouchOnlyAttribute = (MultiTouchOnlyAttribute?)Attribute.GetCustomAttribute(typeof(T), typeof(MultiTouchOnlyAttribute)); GestureName = nameAttribute?.Name ?? DEFAULT_NAME; Description = descriptionAttribute?.Description ?? DEFAULT_DESCRIPTION; Icon = iconAttribute?.Icon; + IsMultiTouchOnly = multiTouchOnlyAttribute?.IsMultiTouchOnly ?? false; AssociatedSetup = new T(); } @@ -43,6 +45,11 @@ public partial class GestureTileViewModel : ViewModelBase [ObservableProperty] private GestureSetupViewModel _associatedSetup = new(); + [ObservableProperty] + private bool _isEnabled = true; + + public bool IsMultiTouchOnly { get; init; } + public event EventHandler? Selected; [RelayCommand] diff --git a/Touch-Gestures.UX/ViewModels/GestureSelectionScreenViewModel.cs b/Touch-Gestures.UX/ViewModels/GestureSelectionScreenViewModel.cs index 1d19c66..ecf94ea 100644 --- a/Touch-Gestures.UX/ViewModels/GestureSelectionScreenViewModel.cs +++ b/Touch-Gestures.UX/ViewModels/GestureSelectionScreenViewModel.cs @@ -84,6 +84,12 @@ public string SearchText #region Methods + public void HideMultiTouchTiles(bool isMultiTouch = true) + { + foreach (var gestureTileViewModel in CurrentGestureTiles) + gestureTileViewModel.IsEnabled = isMultiTouch || gestureTileViewModel.IsMultiTouchOnly == false; + } + protected override void GoBack() => BackRequested?.Invoke(this, EventArgs.Empty); #endregion diff --git a/Touch-Gestures.UX/ViewModels/GestureSetupScreenViewModel.cs b/Touch-Gestures.UX/ViewModels/GestureSetupScreenViewModel.cs index ec1e2bf..1611de6 100644 --- a/Touch-Gestures.UX/ViewModels/GestureSetupScreenViewModel.cs +++ b/Touch-Gestures.UX/ViewModels/GestureSetupScreenViewModel.cs @@ -30,12 +30,23 @@ public GestureSetupScreenViewModel() /// Start the gesture setup process. /// /// The view model to start the setup with. - public void StartSetup(GestureSetupViewModel gestureSetupViewModel) + public void StartSetup(GestureSetupViewModel gestureSetupViewModel, bool isMultiTouch = false) { NextViewModel = gestureSetupViewModel; NextViewModel.BackRequested += OnBackRequestedAhead; - gestureSetupViewModel.IsOptionsSelectionStepActive = true; + // There shouldn't be a situation where an unsupported gesture should make its way here normally, + // as these are hidden during the selection process. + + gestureSetupViewModel.IsOptionsSelectionStepActive = false; + + // Check if single touch even matters for the setup. + if (isMultiTouch || gestureSetupViewModel.SingleTouchOptionSelectionEnabled) + gestureSetupViewModel.IsOptionsSelectionStepActive = true; + else + gestureSetupViewModel.IsBindingSelectionStepActive = true; + + gestureSetupViewModel.IsMultiTouchSetup = isMultiTouch; } protected override void GoBack() diff --git a/Touch-Gestures.UX/ViewModels/GestureSetupWizardViewModel.cs b/Touch-Gestures.UX/ViewModels/GestureSetupWizardViewModel.cs index 2660310..c8a0f2f 100644 --- a/Touch-Gestures.UX/ViewModels/GestureSetupWizardViewModel.cs +++ b/Touch-Gestures.UX/ViewModels/GestureSetupWizardViewModel.cs @@ -36,7 +36,7 @@ public partial class GestureSetupWizardViewModel : NavigableViewModel #region Constructors - public GestureSetupWizardViewModel() + public GestureSetupWizardViewModel(bool isMultiTouch = true) { NextViewModel = _gestureSelectionScreenViewModel; @@ -45,11 +45,12 @@ public GestureSetupWizardViewModel() GestureSelectionScreenViewModel.BackRequested += OnBackRequestedAhead; GestureSelectionScreenViewModel.GestureSelected += OnGestureSelected; + GestureSelectionScreenViewModel.HideMultiTouchTiles(isMultiTouch); //GestureSetupScreenViewModel.BackRequested += OnBackRequestedAhead; } - public GestureSetupWizardViewModel(Rect bounds) : this() + public GestureSetupWizardViewModel(Rect bounds, bool isMultiTouch = true) : this(isMultiTouch) { _bounds = bounds; } diff --git a/Touch-Gestures.UX/Views/Gestures/GestureSelectionScreen.axaml b/Touch-Gestures.UX/Views/Gestures/GestureSelectionScreen.axaml index 228445d..7f1a1b5 100644 --- a/Touch-Gestures.UX/Views/Gestures/GestureSelectionScreen.axaml +++ b/Touch-Gestures.UX/Views/Gestures/GestureSelectionScreen.axaml @@ -57,7 +57,7 @@ + Command="{Binding SelectGestureCommand}" IsEnabled="{Binding IsEnabled}" IsVisible="{Binding IsEnabled}" Margin="4" /> From 81dcefd0fd9f38029277134a61eacc92fc6fb2ae Mon Sep 17 00:00:00 2001 From: Gess1t Date: Wed, 9 Oct 2024 00:48:15 +0200 Subject: [PATCH 04/19] Fix Multi Touch setting not being passed to setups --- .../ViewModels/GestureSetupWizardViewModel.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Touch-Gestures.UX/ViewModels/GestureSetupWizardViewModel.cs b/Touch-Gestures.UX/ViewModels/GestureSetupWizardViewModel.cs index c8a0f2f..e1177d0 100644 --- a/Touch-Gestures.UX/ViewModels/GestureSetupWizardViewModel.cs +++ b/Touch-Gestures.UX/ViewModels/GestureSetupWizardViewModel.cs @@ -17,6 +17,7 @@ public partial class GestureSetupWizardViewModel : NavigableViewModel private Gesture _editedGesture = null!; private Rect _bounds; + private bool _isMultiTouch; #region Observable Fields @@ -39,6 +40,8 @@ public partial class GestureSetupWizardViewModel : NavigableViewModel public GestureSetupWizardViewModel(bool isMultiTouch = true) { NextViewModel = _gestureSelectionScreenViewModel; + + _isMultiTouch = isMultiTouch; PropertyChanging += OnPropertyChanging; PropertyChanged += OnGestureChanged; @@ -106,7 +109,7 @@ public void Edit(GestureBindingDisplayViewModel bindingDisplay) // Subscribe to the events setupViewModel.EditCompleted += OnEditCompleted; - GestureSetupScreenViewModel.StartSetup(setupViewModel); + GestureSetupScreenViewModel.StartSetup(setupViewModel, _isMultiTouch); NextViewModel = GestureSetupScreenViewModel; } @@ -132,7 +135,7 @@ private void OnGestureSelected(object? sender, GestureTileViewModel selectedTile associatedSetup.AreaDisplay = new(_bounds); - GestureSetupScreenViewModel.StartSetup(associatedSetup); + GestureSetupScreenViewModel.StartSetup(associatedSetup, _isMultiTouch); NextViewModel = GestureSetupScreenViewModel; } From aa3f27949e4c08ebc30c3a1477be955ac4c78361 Mon Sep 17 00:00:00 2001 From: Gess1t Date: Wed, 9 Oct 2024 00:49:01 +0200 Subject: [PATCH 05/19] Potentially fix some warnings in a non-destructive way --- .../Controls/Containers/GestureBindingDisplay.axaml.cs | 4 ++-- Touch-Gestures.UX/Views/Gestures/Setups/HoldSetup.axaml.cs | 4 +++- Touch-Gestures.UX/Views/Gestures/Setups/PanSetup.axaml.cs | 4 +++- Touch-Gestures.UX/Views/Gestures/Setups/PinchSetup.axaml.cs | 4 +++- Touch-Gestures.UX/Views/Gestures/Setups/RotateSetup.axaml.cs | 4 +++- Touch-Gestures.UX/Views/Gestures/Setups/SwipeSetup.axaml.cs | 4 +++- Touch-Gestures.UX/Views/Gestures/Setups/TapSetup.axaml.cs | 4 +++- 7 files changed, 20 insertions(+), 8 deletions(-) diff --git a/Touch-Gestures.UX/Controls/Containers/GestureBindingDisplay.axaml.cs b/Touch-Gestures.UX/Controls/Containers/GestureBindingDisplay.axaml.cs index 496056f..921a156 100644 --- a/Touch-Gestures.UX/Controls/Containers/GestureBindingDisplay.axaml.cs +++ b/Touch-Gestures.UX/Controls/Containers/GestureBindingDisplay.axaml.cs @@ -1,8 +1,8 @@ -using OpenTabletDriver.External.Avalonia.Controls; +using Avalonia.Controls; namespace TouchGestures.UX.Controls.Containers { - public partial class GestureBindingDisplay : BindingDisplay + public partial class GestureBindingDisplay : UserControl { public GestureBindingDisplay() { diff --git a/Touch-Gestures.UX/Views/Gestures/Setups/HoldSetup.axaml.cs b/Touch-Gestures.UX/Views/Gestures/Setups/HoldSetup.axaml.cs index b09b064..f0db2ec 100644 --- a/Touch-Gestures.UX/Views/Gestures/Setups/HoldSetup.axaml.cs +++ b/Touch-Gestures.UX/Views/Gestures/Setups/HoldSetup.axaml.cs @@ -1,6 +1,8 @@ +using Avalonia.Controls; + namespace TouchGestures.UX.Views.Gestures.Setups; -public partial class HoldSetup : GestureSetup +public partial class HoldSetup : UserControl { public HoldSetup() { diff --git a/Touch-Gestures.UX/Views/Gestures/Setups/PanSetup.axaml.cs b/Touch-Gestures.UX/Views/Gestures/Setups/PanSetup.axaml.cs index f54d289..773ec38 100644 --- a/Touch-Gestures.UX/Views/Gestures/Setups/PanSetup.axaml.cs +++ b/Touch-Gestures.UX/Views/Gestures/Setups/PanSetup.axaml.cs @@ -1,6 +1,8 @@ +using Avalonia.Controls; + namespace TouchGestures.UX.Views.Gestures.Setups; -public partial class PanSetup : GestureSetup +public partial class PanSetup : UserControl { public PanSetup() { diff --git a/Touch-Gestures.UX/Views/Gestures/Setups/PinchSetup.axaml.cs b/Touch-Gestures.UX/Views/Gestures/Setups/PinchSetup.axaml.cs index d30dccf..8ab577c 100644 --- a/Touch-Gestures.UX/Views/Gestures/Setups/PinchSetup.axaml.cs +++ b/Touch-Gestures.UX/Views/Gestures/Setups/PinchSetup.axaml.cs @@ -1,6 +1,8 @@ +using Avalonia.Controls; + namespace TouchGestures.UX.Views.Gestures.Setups; -public partial class RotateSetup : GestureSetup +public partial class RotateSetup : UserControl { public RotateSetup() { diff --git a/Touch-Gestures.UX/Views/Gestures/Setups/RotateSetup.axaml.cs b/Touch-Gestures.UX/Views/Gestures/Setups/RotateSetup.axaml.cs index 66f4a31..9092d97 100644 --- a/Touch-Gestures.UX/Views/Gestures/Setups/RotateSetup.axaml.cs +++ b/Touch-Gestures.UX/Views/Gestures/Setups/RotateSetup.axaml.cs @@ -1,6 +1,8 @@ +using Avalonia.Controls; + namespace TouchGestures.UX.Views.Gestures.Setups; -public partial class PinchSetup : GestureSetup +public partial class PinchSetup : UserControl { public PinchSetup() { diff --git a/Touch-Gestures.UX/Views/Gestures/Setups/SwipeSetup.axaml.cs b/Touch-Gestures.UX/Views/Gestures/Setups/SwipeSetup.axaml.cs index 2f3a6b5..3a53f89 100644 --- a/Touch-Gestures.UX/Views/Gestures/Setups/SwipeSetup.axaml.cs +++ b/Touch-Gestures.UX/Views/Gestures/Setups/SwipeSetup.axaml.cs @@ -1,6 +1,8 @@ +using Avalonia.Controls; + namespace TouchGestures.UX.Views.Gestures.Setups; -public partial class SwipeSetup : GestureSetup +public partial class SwipeSetup : UserControl { public SwipeSetup() { diff --git a/Touch-Gestures.UX/Views/Gestures/Setups/TapSetup.axaml.cs b/Touch-Gestures.UX/Views/Gestures/Setups/TapSetup.axaml.cs index 8e9d074..09d6e52 100644 --- a/Touch-Gestures.UX/Views/Gestures/Setups/TapSetup.axaml.cs +++ b/Touch-Gestures.UX/Views/Gestures/Setups/TapSetup.axaml.cs @@ -1,6 +1,8 @@ +using Avalonia.Controls; + namespace TouchGestures.UX.Views.Gestures.Setups; -public partial class TapSetup : GestureSetup +public partial class TapSetup : UserControl { public TapSetup() { From 21571e42b56930d96a0e78ce5f9ed456b30f4028 Mon Sep 17 00:00:00 2001 From: Gess1t Date: Wed, 9 Oct 2024 02:56:13 +0200 Subject: [PATCH 06/19] Implemented Plugin side of Pen Gestures (Now working) --- Touch-Gestures-0.6.x/GesturesHandler.cs | 30 ++-- Touch-Gestures-0.6.x/PenGesturesHandler.cs | 125 +++++++++++++++++ .../Entities/BindableProfile.cs | 16 ++- .../Entities/Tablet/TouchReport.cs | 23 ++++ Touch-Gestures/GesturesHandler.cs | 18 +-- Touch-Gestures/PenGesturesHandler.cs | 130 ++++++++++++++++++ 6 files changed, 315 insertions(+), 27 deletions(-) create mode 100644 Touch-Gestures-0.6.x/PenGesturesHandler.cs create mode 100644 Touch-Gestures.Lib/Entities/Tablet/TouchReport.cs create mode 100644 Touch-Gestures/PenGesturesHandler.cs diff --git a/Touch-Gestures-0.6.x/GesturesHandler.cs b/Touch-Gestures-0.6.x/GesturesHandler.cs index 3a0c3da..36fd296 100644 --- a/Touch-Gestures-0.6.x/GesturesHandler.cs +++ b/Touch-Gestures-0.6.x/GesturesHandler.cs @@ -28,21 +28,20 @@ public class GesturesHandler : IPositionedPipelineElement, IDispo { #region Constants - public const string PLUGIN_NAME = "Touch Gestures"; + private const string PLUGIN_NAME = "Touch Gestures"; #endregion #region Fields - - private GesturesDaemonBase? _daemon; - private TouchSettings _touchSettings = TouchSettings.Default; - private IOutputMode? _outputMode; - private BindableProfile? _profile; - private SharedTabletReference? _tablet; + + protected TouchSettings _touchSettings = TouchSettings.Default; + protected IOutputMode? _outputMode; + protected GesturesDaemonBase? _daemon; + protected BindableProfile? _profile; + protected SharedTabletReference? _tablet; private bool _awaitingDaemon; private bool _hasPreviousGestureStarted; - #endregion #region Initialization @@ -91,7 +90,7 @@ public void Initialize() Log.Write(PLUGIN_NAME, "Touch Gestures Daemon has not been enabled, please enable it in the 'Tools' tab", LogLevel.Error); } - private void InitializeCore(TabletReference tablet) + protected virtual void InitializeCore(TabletReference tablet) { _tablet = tablet.ToShared(_touchSettings); @@ -112,7 +111,7 @@ private void InitializeCore(TabletReference tablet) } } - private void FetchTouchSettings() + protected void FetchTouchSettings() { if (_Driver is Driver driver && Tablet != null) { @@ -132,7 +131,7 @@ private void FetchTouchSettings() } } - private void AddServices() + protected void AddServices() { if (_tablet is BulletproofSharedTabletReference btablet) { @@ -175,7 +174,7 @@ private void AddServices() #region Methods - public void Consume(IDeviceReport report) + public virtual void Consume(IDeviceReport report) { if (report is ITouchReport touchReport) { @@ -220,10 +219,13 @@ public void HandleConflictingGestures(IEnumerable gestures, ITouchRepor #region Events Handlers + public void OnEmit(IDeviceReport e) + => Emit?.Invoke(e); + public void OnDaemonLoaded(object? sender, EventArgs e) => Initialize(); - public void OnProfileChanged(object? sender, EventArgs e) + public virtual void OnProfileChanged(object? sender, EventArgs e) { if (_profile == null) { @@ -256,7 +258,7 @@ public void OnProfileChanged(object? sender, EventArgs e) Log.Debug(PLUGIN_NAME, "Settings updated"); } - private void SortGestures() + protected void SortGestures() { if (_profile == null) return; diff --git a/Touch-Gestures-0.6.x/PenGesturesHandler.cs b/Touch-Gestures-0.6.x/PenGesturesHandler.cs new file mode 100644 index 0000000..f181462 --- /dev/null +++ b/Touch-Gestures-0.6.x/PenGesturesHandler.cs @@ -0,0 +1,125 @@ +using System; +using System.Numerics; +using OpenTabletDriver.Plugin; +using OpenTabletDriver.Plugin.Attributes; +using OpenTabletDriver.Plugin.Tablet; +using OpenTabletDriver.Plugin.Tablet.Touch; +using TouchGestures.Extensions; +using TouchGestures.Lib.Entities.Tablet; + +namespace TouchGestures +{ + [PluginName(PLUGIN_NAME)] + public class PenGesturesHandler : GesturesHandler + { + #region Constants + + private const string PLUGIN_NAME = "Pen Gestures"; + + #endregion + + #region Fields + + private readonly TouchReport _stubReport = new(1); + private readonly TouchPoint _stubPoint = new(); + + #endregion + + #region Initialization + + protected override void InitializeCore(TabletReference tablet) + { + _tablet = tablet.ToShared(_touchSettings); + _tablet.Name = $"{_tablet.Name} (Pen Only)"; + + AddServices(); + + if (_daemon != null) + { + _daemon.AddTablet(_tablet); + _profile = _daemon.GetSettingsForTablet(_tablet.Name); + + if (_profile != null) + { + _profile.IsMultiTouch = false; + _profile.ProfileChanged += OnProfileChanged; + OnProfileChanged(this, EventArgs.Empty); + } + + Log.Write(PLUGIN_NAME, "Now handling touch gesture for: " + _tablet.Name); + } + } + + #endregion + + #region Methods + + public override void Consume(IDeviceReport report) + { + if (report is ITabletReport tabletReport) + { + if (tabletReport.Pressure > 0) + { + _stubPoint.Position = tabletReport.Position; + _stubReport.Touches[0] = _stubPoint; + } + else + _stubReport.Touches[0] = null; + + if (_daemon != null && _daemon.IsReady) + { + // Iterate through all conflicting gestures + HandleConflictingGestures(TapGestures, _stubReport); + HandleConflictingGestures(HoldGestures, _stubReport); + + // Iterate through all non-conflicting gestures + foreach (var gesture in NonConflictingGestures) + gesture.OnInput(_stubReport.Touches); + } + } + + OnEmit(report); + } + + #endregion + + #region Events Handlers + + public override void OnProfileChanged(object? sender, EventArgs e) + { + if (_profile == null) + { + Log.Write(PLUGIN_NAME, "Settings are null", LogLevel.Error); + return; + } + + if (_tablet != null) + { + var lpmm = _tablet.PenDigitizer?.GetLPMM() ?? Vector2.Zero; + + if (_tablet.PenDigitizer != null && lpmm != Vector2.Zero) + _profile.UpdateLPMM(_tablet); + else + Log.Write(PLUGIN_NAME, "LPMM is zero, this usually means that 'Touch Settings' hasn't been enabled or its maxes are set to zero", LogLevel.Error); + } + + TapGestures.Clear(); + HoldGestures.Clear(); + NonConflictingGestures.Clear(); + + SortGestures(); + + TapGestures.AddRange(_profile.TapGestures); + HoldGestures.AddRange(_profile.HoldGestures); + + NonConflictingGestures.AddRange(_profile.SwipeGestures); + NonConflictingGestures.AddRange(_profile.PanGestures); + NonConflictingGestures.AddRange(_profile.PinchGestures); + NonConflictingGestures.AddRange(_profile.RotateGestures); + + Log.Debug(PLUGIN_NAME, "Settings updated"); + } + + #endregion + } +} diff --git a/Touch-Gestures.Lib/Entities/BindableProfile.cs b/Touch-Gestures.Lib/Entities/BindableProfile.cs index ca75722..c1513ea 100644 --- a/Touch-Gestures.Lib/Entities/BindableProfile.cs +++ b/Touch-Gestures.Lib/Entities/BindableProfile.cs @@ -1,6 +1,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Numerics; using System.Reflection; using Newtonsoft.Json; using OpenTabletDriver.Plugin; @@ -125,11 +126,16 @@ public void Update(SerializableProfile profile, SharedTabletReference tablet, Di public void UpdateLPMM(SharedTabletReference tablet) { - if (tablet.TouchDigitizer == null) - return; + Vector2? lpmm; - foreach (var gesture in this) - gesture.LinesPerMM = tablet.TouchDigitizer.GetLPMM(); + if (IsMultiTouch) + lpmm = tablet.TouchDigitizer?.GetLPMM(); + else + lpmm = tablet.PenDigitizer?.GetLPMM(); + + if (lpmm != null && lpmm != Vector2.Zero) + foreach (var gesture in this) + gesture.LinesPerMM = (Vector2)lpmm; } private void AddPinch(BindablePinchGesture pinchGesture) @@ -165,6 +171,7 @@ public static BindableProfile FromSerializable(SerializableProfile profile, Dict { var result = existingProfile ?? new BindableProfile(); result.Name = profile.Name; + result.IsMultiTouch = profile.IsMultiTouch; if (existingProfile != null) { @@ -238,6 +245,7 @@ public static SerializableProfile ToSerializable(BindableProfile profile, Dictio var result = new SerializableProfile(); { result.Name = profile.Name; + result.IsMultiTouch = profile.IsMultiTouch; } foreach (var gesture in profile.TapGestures) diff --git a/Touch-Gestures.Lib/Entities/Tablet/TouchReport.cs b/Touch-Gestures.Lib/Entities/Tablet/TouchReport.cs new file mode 100644 index 0000000..2706751 --- /dev/null +++ b/Touch-Gestures.Lib/Entities/Tablet/TouchReport.cs @@ -0,0 +1,23 @@ +using System; +using OpenTabletDriver.Plugin.Tablet.Touch; + +#nullable disable + +namespace TouchGestures.Lib.Entities.Tablet +{ + public class TouchReport : ITouchReport + { + public TouchReport() {} + + public TouchReport(byte count = 0) + { + Touches = new TouchPoint[count]; + + for (int i = 0; i < count; i++) + Touches[i] = new TouchPoint(); + } + + public TouchPoint[] Touches { get; set; } = Array.Empty(); + public byte[] Raw { get; set; } + } +} \ No newline at end of file diff --git a/Touch-Gestures/GesturesHandler.cs b/Touch-Gestures/GesturesHandler.cs index 4216348..1e1864f 100644 --- a/Touch-Gestures/GesturesHandler.cs +++ b/Touch-Gestures/GesturesHandler.cs @@ -24,16 +24,16 @@ public class GesturesHandler : IFilter, IGateFilter, IInitialize, IDisposable { #region Constants - public const string PLUGIN_NAME = "Touch Gestures"; + private const string PLUGIN_NAME = "Touch Gestures"; #endregion #region Fields - private TouchSettings _touchSettings => TouchSettings.Instance ?? TouchSettings.Default; - private GesturesDaemonBase? _daemon; - private BindableProfile? _profile; - private SharedTabletReference? _tablet; + protected TouchSettings _touchSettings => TouchSettings.Instance ?? TouchSettings.Default; + protected GesturesDaemonBase? _daemon; + protected BindableProfile? _profile; + protected SharedTabletReference? _tablet; private bool _hasPreviousGestureStarted; #endregion @@ -47,7 +47,7 @@ public GesturesHandler() #endif } - public void Initialize() + public virtual void Initialize() { if (!_touchSettings.IsTouchToggled) return; @@ -102,7 +102,7 @@ private void WaitForDebugger() public Vector2 Filter(Vector2 input) => input; - public bool Pass(IDeviceReport report, ref ITabletReport tabletreport) + public virtual bool Pass(IDeviceReport report, ref ITabletReport tabletreport) { if (report is ITouchReport touchReport) { @@ -147,7 +147,7 @@ public void HandleConflictingGestures(IEnumerable gestures, ITouchRepor #region Events Handlers - public void OnProfileChanged(object? sender, EventArgs e) + public virtual void OnProfileChanged(object? sender, EventArgs e) { if (_profile == null) { @@ -180,7 +180,7 @@ public void OnProfileChanged(object? sender, EventArgs e) Log.Debug(PLUGIN_NAME, "Settings updated"); } - private void SortGestures() + protected void SortGestures() { if (_profile == null) return; diff --git a/Touch-Gestures/PenGesturesHandler.cs b/Touch-Gestures/PenGesturesHandler.cs new file mode 100644 index 0000000..b3b6e52 --- /dev/null +++ b/Touch-Gestures/PenGesturesHandler.cs @@ -0,0 +1,130 @@ +using System; +using System.Numerics; +using OpenTabletDriver.Plugin; +using OpenTabletDriver.Plugin.Attributes; +using OpenTabletDriver.Plugin.Tablet; +using OpenTabletDriver.Plugin.Tablet.Touch; +using TouchGestures.Extensions; +using TouchGestures.Lib.Entities; +using TouchGestures.Lib.Entities.Tablet; + +namespace TouchGestures +{ + [PluginName(PLUGIN_NAME)] + public class PenGesturesHandler : GesturesHandler + { + #region Constants + + private const string PLUGIN_NAME = "Pen Gestures"; + + #endregion + + #region Fields + + private readonly TouchReport _stubReport = new(1); + private readonly TouchPoint _stubPoint = new(); + + #endregion + + #region Constructors + + public override void Initialize() + { + _daemon = GesturesDaemonBase.Instance; + + if (Info.Driver.Tablet != null && _daemon != null) + { + _tablet = Info.Driver.Tablet.ToShared(_touchSettings); + _tablet.Name = $"{_tablet.Name} (Pen Only)"; + + _daemon.AddTablet(_tablet); + _profile = _daemon.GetSettingsForTablet(_tablet.Name); + + if (_profile != null) + { + _profile.IsMultiTouch = false; + _profile.ProfileChanged += OnProfileChanged; + OnProfileChanged(this, EventArgs.Empty); + } + + Log.Write(PLUGIN_NAME, "Now handling touch gesture for: " + _tablet.Name); + } + + if (_daemon == null) + { + Log.Write(PLUGIN_NAME, "Touch Gestures Daemon has not been enabled, please enable it in the 'Tools' tab", LogLevel.Error); + return; + } + } + + #endregion + + #region Methods + + public override bool Pass(IDeviceReport report, ref ITabletReport tabletreport) + { + if (report is ITabletReport tabletReport) + { + if (tabletReport.Pressure > 0) + { + _stubPoint.Position = tabletReport.Position; + _stubReport.Touches[0] = _stubPoint; + } + else + _stubReport.Touches[0] = null; + + if (_daemon != null && _daemon.IsReady && _touchSettings.IsTouchToggled) + { + // Iterate through all conflicting gestures + HandleConflictingGestures(TapGestures, _stubReport); + HandleConflictingGestures(HoldGestures, _stubReport); + + // Iterate through all non-conflicting gestures + foreach (var gesture in NonConflictingGestures) + gesture.OnInput(_stubReport.Touches); + } + } + + return true; + } + + #endregion + + #region Events Handlers + + public override void OnProfileChanged(object? sender, EventArgs e) + { + if (_profile == null) + { + Log.Write(PLUGIN_NAME, "Settings are null", LogLevel.Error); + return; + } + + if (_tablet != null) + { + if (_tablet.TouchDigitizer != null && _tablet.PenDigitizer?.GetLPMM() != Vector2.Zero) + _profile.UpdateLPMM(_tablet); + else + Log.Write(PLUGIN_NAME, "LPMM is zero, this is very unusual as the tablet's specifications should be defined in the internal tablet configuration.", LogLevel.Error); + } + + TapGestures.Clear(); + HoldGestures.Clear(); + NonConflictingGestures.Clear(); + + SortGestures(); + + TapGestures.AddRange(_profile.TapGestures); + HoldGestures.AddRange(_profile.HoldGestures); + + NonConflictingGestures.AddRange(_profile.SwipeGestures); + NonConflictingGestures.AddRange(_profile.PanGestures); + NonConflictingGestures.AddRange(_profile.PinchGestures); + NonConflictingGestures.AddRange(_profile.RotateGestures); + + Log.Debug(PLUGIN_NAME, "Settings updated"); + } + + #endregion + } +} From c8fe8c7a6e829bedbbd36d29f2e7a34754919350 Mon Sep 17 00:00:00 2001 From: Gess1t Date: Wed, 9 Oct 2024 15:43:14 +0200 Subject: [PATCH 07/19] Remove leftover touch check in the 0.6.x Pen only Plugin --- Touch-Gestures-0.6.x/GesturesHandler.cs | 4 ++-- Touch-Gestures-0.6.x/PenGesturesHandler.cs | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/Touch-Gestures-0.6.x/GesturesHandler.cs b/Touch-Gestures-0.6.x/GesturesHandler.cs index 36fd296..0c1e332 100644 --- a/Touch-Gestures-0.6.x/GesturesHandler.cs +++ b/Touch-Gestures-0.6.x/GesturesHandler.cs @@ -39,7 +39,7 @@ public class GesturesHandler : IPositionedPipelineElement, IDispo protected GesturesDaemonBase? _daemon; protected BindableProfile? _profile; protected SharedTabletReference? _tablet; - private bool _awaitingDaemon; + protected bool _awaitingDaemon; private bool _hasPreviousGestureStarted; #endregion @@ -69,7 +69,7 @@ private static void WaitForDebugger() } } - public void Initialize() + public virtual void Initialize() { FetchTouchSettings(); diff --git a/Touch-Gestures-0.6.x/PenGesturesHandler.cs b/Touch-Gestures-0.6.x/PenGesturesHandler.cs index f181462..b4e3f8b 100644 --- a/Touch-Gestures-0.6.x/PenGesturesHandler.cs +++ b/Touch-Gestures-0.6.x/PenGesturesHandler.cs @@ -5,6 +5,7 @@ using OpenTabletDriver.Plugin.Tablet; using OpenTabletDriver.Plugin.Tablet.Touch; using TouchGestures.Extensions; +using TouchGestures.Lib.Entities; using TouchGestures.Lib.Entities.Tablet; namespace TouchGestures @@ -27,6 +28,22 @@ public class PenGesturesHandler : GesturesHandler #region Initialization + public override void Initialize() + { + // Filters are loaded before tools for some reasons, so we have to wait for the daemon to be loaded + _daemon = GesturesDaemonBase.Instance; + + // OTD 0.6.4.0 doesn't dispose of plugins when detecting tablets, so unsubscribing early is necessary + GesturesDaemonBase.DaemonLoaded -= OnDaemonLoaded; + _awaitingDaemon = false; + + if (Tablet != null) + InitializeCore(Tablet); + + if (_daemon == null) + Log.Write(PLUGIN_NAME, "Touch Gestures Daemon has not been enabled, please enable it in the 'Tools' tab", LogLevel.Error); + } + protected override void InitializeCore(TabletReference tablet) { _tablet = tablet.ToShared(_touchSettings); From c4fb4469b6b8a696583ed22c2c7e30300dc85924 Mon Sep 17 00:00:00 2001 From: Gess1t Date: Wed, 9 Oct 2024 19:12:35 +0200 Subject: [PATCH 08/19] Remove abstract on BackRequested event in NavigableViewModel to properly fix warnings --- .../ViewModels/BindingsOverviewViewModel.cs | 5 ----- .../Controls/Setups/GestureSetupViewModel.cs | 6 ------ .../ViewModels/GestureSelectionScreenViewModel.cs | 8 -------- .../ViewModels/GestureSetupScreenViewModel.cs | 14 ++------------ .../ViewModels/GestureSetupWizardViewModel.cs | 6 +++--- Touch-Gestures.UX/ViewModels/MainViewModel.cs | 9 +-------- Touch-Gestures.UX/ViewModels/NavigableViewModel.cs | 8 ++++++-- 7 files changed, 12 insertions(+), 44 deletions(-) diff --git a/Touch-Gestures.UX/ViewModels/BindingsOverviewViewModel.cs b/Touch-Gestures.UX/ViewModels/BindingsOverviewViewModel.cs index f689e37..e45d20c 100644 --- a/Touch-Gestures.UX/ViewModels/BindingsOverviewViewModel.cs +++ b/Touch-Gestures.UX/ViewModels/BindingsOverviewViewModel.cs @@ -71,7 +71,6 @@ public BindingsOverviewViewModel() IsReady = false; NextViewModel = this; - BackRequested = null!; } public BindingsOverviewViewModel(MainViewModel mainViewModel) @@ -83,7 +82,6 @@ public BindingsOverviewViewModel(MainViewModel mainViewModel) _parentViewModel.Disconnected += OnDisconnected; NextViewModel = this; - BackRequested = null!; } public BindingsOverviewViewModel(MainViewModel mainViewModel, SerializableSettings settings) : this(mainViewModel) @@ -94,8 +92,6 @@ public BindingsOverviewViewModel(MainViewModel mainViewModel, SerializableSettin #region Events private event EventHandler? TabletChanged; - - public override event EventHandler? BackRequested; public event EventHandler? SaveRequested; public event EventHandler? ProfileChanged; @@ -478,7 +474,6 @@ public void Dispose() SaveRequested = null; ProfileChanged = null; - BackRequested = null; GC.SuppressFinalize(this); } diff --git a/Touch-Gestures.UX/ViewModels/Controls/Setups/GestureSetupViewModel.cs b/Touch-Gestures.UX/ViewModels/Controls/Setups/GestureSetupViewModel.cs index a78bd4a..fb7ef9b 100644 --- a/Touch-Gestures.UX/ViewModels/Controls/Setups/GestureSetupViewModel.cs +++ b/Touch-Gestures.UX/ViewModels/Controls/Setups/GestureSetupViewModel.cs @@ -77,8 +77,6 @@ public partial class GestureSetupViewModel : NavigableViewModel, IDisposable public GestureSetupViewModel() { - BackRequested = null!; - CanGoBack = true; CanGoNext = false; @@ -98,8 +96,6 @@ protected virtual void SubscribeToSettingsChanges() #region Events - public override event EventHandler? BackRequested; - public event EventHandler? SetupCompleted; public event EventHandler? EditCompleted; @@ -146,8 +142,6 @@ public int SelectedGestureSetupPickIndex #region Methods - protected override void GoBack() => BackRequested?.Invoke(this, EventArgs.Empty); - [RelayCommand(CanExecute = nameof(CanGoNext))] protected virtual void GoNext() => throw new NotImplementedException("GoNext has not been overriden."); diff --git a/Touch-Gestures.UX/ViewModels/GestureSelectionScreenViewModel.cs b/Touch-Gestures.UX/ViewModels/GestureSelectionScreenViewModel.cs index ecf94ea..a28c21b 100644 --- a/Touch-Gestures.UX/ViewModels/GestureSelectionScreenViewModel.cs +++ b/Touch-Gestures.UX/ViewModels/GestureSelectionScreenViewModel.cs @@ -76,12 +76,6 @@ public string SearchText #endregion - #region Events - - public override event EventHandler? BackRequested; - - #endregion - #region Methods public void HideMultiTouchTiles(bool isMultiTouch = true) @@ -90,8 +84,6 @@ public void HideMultiTouchTiles(bool isMultiTouch = true) gestureTileViewModel.IsEnabled = isMultiTouch || gestureTileViewModel.IsMultiTouchOnly == false; } - protected override void GoBack() => BackRequested?.Invoke(this, EventArgs.Empty); - #endregion #region Event Handlers diff --git a/Touch-Gestures.UX/ViewModels/GestureSetupScreenViewModel.cs b/Touch-Gestures.UX/ViewModels/GestureSetupScreenViewModel.cs index 1611de6..7531c60 100644 --- a/Touch-Gestures.UX/ViewModels/GestureSetupScreenViewModel.cs +++ b/Touch-Gestures.UX/ViewModels/GestureSetupScreenViewModel.cs @@ -10,17 +10,7 @@ public partial class GestureSetupScreenViewModel : NavigableViewModel { #region Constructors - public GestureSetupScreenViewModel() - { - BackRequested = null!; - CanGoBack = true; - } - - #endregion - - #region Events - - public override event EventHandler? BackRequested; + public GestureSetupScreenViewModel() => CanGoBack = true; #endregion @@ -54,7 +44,7 @@ protected override void GoBack() if (NextViewModel != null) NextViewModel.BackRequested -= OnBackRequestedAhead; - BackRequested?.Invoke(this, EventArgs.Empty); + base.GoBack(); } #endregion diff --git a/Touch-Gestures.UX/ViewModels/GestureSetupWizardViewModel.cs b/Touch-Gestures.UX/ViewModels/GestureSetupWizardViewModel.cs index e1177d0..529f877 100644 --- a/Touch-Gestures.UX/ViewModels/GestureSetupWizardViewModel.cs +++ b/Touch-Gestures.UX/ViewModels/GestureSetupWizardViewModel.cs @@ -50,6 +50,8 @@ public GestureSetupWizardViewModel(bool isMultiTouch = true) GestureSelectionScreenViewModel.GestureSelected += OnGestureSelected; GestureSelectionScreenViewModel.HideMultiTouchTiles(isMultiTouch); + CanGoBack = true; + //GestureSetupScreenViewModel.BackRequested += OnBackRequestedAhead; } @@ -62,8 +64,6 @@ public GestureSetupWizardViewModel(Rect bounds, bool isMultiTouch = true) : this #region Events - public override event EventHandler? BackRequested; - public event EventHandler? SetupCompleted; public event EventHandler? EditCompleted; @@ -77,7 +77,7 @@ protected override void GoBack() if (NextViewModel is GestureSetupScreenViewModel && _editedGesture == null) NextViewModel = GestureSelectionScreenViewModel; else if (NextViewModel is GestureSelectionScreenViewModel || NextViewModel is GestureSetupScreenViewModel) - BackRequested?.Invoke(this, EventArgs.Empty); + base.GoBack(); } /// diff --git a/Touch-Gestures.UX/ViewModels/MainViewModel.cs b/Touch-Gestures.UX/ViewModels/MainViewModel.cs index 413c25f..492d6a0 100644 --- a/Touch-Gestures.UX/ViewModels/MainViewModel.cs +++ b/Touch-Gestures.UX/ViewModels/MainViewModel.cs @@ -12,10 +12,7 @@ using System.Linq; using TouchGestures.Lib.Entities; using System.Threading; -using TouchGestures.UX.Events; using Avalonia.Threading; -using System.Numerics; -using Avalonia; using Newtonsoft.Json; using TouchGestures.Lib.Converters; using TouchGestures.Lib.Entities.Tablet; @@ -86,8 +83,6 @@ public MainViewModel() BindingsOverviewViewModel.SaveRequested += OnSaveRequested; BindingsOverviewViewModel.ProfileChanged += OnProfileChanged; - BackRequested = null!; - CanGoBack = false; // TODO: Change in production to the home view //NextViewModel = _gestureSetupWizardViewModel; @@ -122,8 +117,6 @@ private void InitializeClient() public event EventHandler? SettingsChanged; - public override event EventHandler? BackRequested; - public event EventHandler? Ready; public event EventHandler? Disconnected; @@ -329,7 +322,7 @@ private async Task OnTabletsChangedCore(object? sender, IEnumerable OnSettingsChanged(_settings)); Dispatcher.UIThread.Post(() => BindingsOverviewViewModel.SetTablets(tablets)); - } + } } // diff --git a/Touch-Gestures.UX/ViewModels/NavigableViewModel.cs b/Touch-Gestures.UX/ViewModels/NavigableViewModel.cs index 24d3f5a..a7db854 100644 --- a/Touch-Gestures.UX/ViewModels/NavigableViewModel.cs +++ b/Touch-Gestures.UX/ViewModels/NavigableViewModel.cs @@ -8,7 +8,7 @@ namespace TouchGestures.UX.ViewModels; public abstract partial class NavigableViewModel : ViewModelBase { - public abstract event EventHandler? BackRequested; + public event EventHandler? BackRequested; public bool CanGoBack { get; init; } @@ -16,5 +16,9 @@ public abstract partial class NavigableViewModel : ViewModelBase protected NavigableViewModel? _nextViewModel = null; [RelayCommand(CanExecute = nameof(CanGoBack))] - protected abstract void GoBack(); + protected virtual void GoBack() + { + if (CanGoBack) + BackRequested?.Invoke(this, EventArgs.Empty); + } } \ No newline at end of file From af5d434aaf14af37925a42834354a9a186ac777d Mon Sep 17 00:00:00 2001 From: Gess1t Date: Thu, 10 Oct 2024 01:50:33 +0200 Subject: [PATCH 09/19] Use Tablet Digitizer in 0.5.x instead of auxiliary Additionally throw an null exception if it's null. --- .../Extensions/TabletReferenceExtensions.cs | 6 +++- .../Extensions/TabletStateExtensions.cs | 28 +++++++++++-------- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/Touch-Gestures-0.6.x/Extensions/TabletReferenceExtensions.cs b/Touch-Gestures-0.6.x/Extensions/TabletReferenceExtensions.cs index 9dffd17..20aea7b 100644 --- a/Touch-Gestures-0.6.x/Extensions/TabletReferenceExtensions.cs +++ b/Touch-Gestures-0.6.x/Extensions/TabletReferenceExtensions.cs @@ -1,3 +1,4 @@ +using System; using System.Numerics; using OpenTabletDriver.Desktop.Reflection; using OpenTabletDriver.Plugin.Tablet; @@ -11,7 +12,10 @@ public static class TabletReferenceExtensions { public static SharedTabletReference ToShared(this TabletReference tablet, TouchSettings touchSettings) { - var digitizer = tablet.Properties.Specifications.Digitizer; + var digitizer = tablet?.Properties?.Specifications?.Digitizer; + + if (tablet == null || digitizer == null) + throw new ArgumentNullException(nameof(tablet)); var penDigitizer = new SharedTabletDigitizer { diff --git a/Touch-Gestures/Extensions/TabletStateExtensions.cs b/Touch-Gestures/Extensions/TabletStateExtensions.cs index aa57703..bcfd91e 100644 --- a/Touch-Gestures/Extensions/TabletStateExtensions.cs +++ b/Touch-Gestures/Extensions/TabletStateExtensions.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using OpenTabletDriver.Plugin.Tablet; using OTD.EnhancedOutputMode.Lib.Tools; @@ -9,6 +10,9 @@ public static class TabletStateExtensions { public static SharedTabletReference ToShared(this TabletState tablet, TouchSettings touchSettings) { + if (tablet == null || tablet.Digitizer == null) + throw new ArgumentNullException(nameof(tablet)); + var digitizer = new SharedTabletDigitizer { Width = tablet.Digitizer.Width, @@ -25,25 +29,25 @@ public static SharedTabletReference ToShared(this TabletState tablet, TouchSetti MaxY = touchSettings.MaxY }; - var featureInitReport = tablet.Auxiliary.FeatureInitReport == null - ? new List() - : new List { tablet.Auxiliary.FeatureInitReport }; + var featureInitReport = tablet.Digitizer.FeatureInitReport == null + ? new List() + : new List { tablet.Digitizer.FeatureInitReport }; - var outputInitReport = tablet.Auxiliary.OutputInitReport == null + var outputInitReport = tablet.Digitizer.OutputInitReport == null ? new List() - : new List { tablet.Auxiliary.OutputInitReport }; + : new List { tablet.Digitizer.OutputInitReport }; var identifier = new SharedDeviceIdentifier { - VendorID = tablet.Auxiliary.VendorID, - ProductID = tablet.Auxiliary.ProductID, - InputReportLength = tablet.Auxiliary.InputReportLength, - OutputReportLength = tablet.Auxiliary.OutputReportLength, - ReportParser = tablet.Auxiliary.ReportParser, + VendorID = tablet.Digitizer.VendorID, + ProductID = tablet.Digitizer.ProductID, + InputReportLength = tablet.Digitizer.InputReportLength, + OutputReportLength = tablet.Digitizer.OutputReportLength, + ReportParser = tablet.Digitizer.ReportParser, FeatureInitReport = featureInitReport, OutputInitReport = outputInitReport, - DeviceStrings = tablet.Auxiliary.DeviceStrings, - InitializationStrings = tablet.Auxiliary.InitializationStrings + DeviceStrings = tablet.Digitizer.DeviceStrings, + InitializationStrings = tablet.Digitizer.InitializationStrings }; return new SharedTabletReference(tablet.TabletProperties.Name, digitizer, touchDigitizer, identifier); From 8281cd08fb33b3da8e4dcebaf78b392fb0fa6ec9 Mon Sep 17 00:00:00 2001 From: Gess1t Date: Thu, 10 Oct 2024 01:58:25 +0200 Subject: [PATCH 10/19] Simplify getting lpmm depending on whether a profile is Multi-touch or not --- Touch-Gestures.Lib/Entities/BindableProfile.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Touch-Gestures.Lib/Entities/BindableProfile.cs b/Touch-Gestures.Lib/Entities/BindableProfile.cs index c1513ea..87c6b02 100644 --- a/Touch-Gestures.Lib/Entities/BindableProfile.cs +++ b/Touch-Gestures.Lib/Entities/BindableProfile.cs @@ -126,12 +126,8 @@ public void Update(SerializableProfile profile, SharedTabletReference tablet, Di public void UpdateLPMM(SharedTabletReference tablet) { - Vector2? lpmm; - - if (IsMultiTouch) - lpmm = tablet.TouchDigitizer?.GetLPMM(); - else - lpmm = tablet.PenDigitizer?.GetLPMM(); + Vector2? lpmm = IsMultiTouch ? tablet.TouchDigitizer?.GetLPMM() : + tablet.PenDigitizer?.GetLPMM(); if (lpmm != null && lpmm != Vector2.Zero) foreach (var gesture in this) From e0b14e48ba2e211b9d4073970108fe5226523ac8 Mon Sep 17 00:00:00 2001 From: Gess1t Date: Thu, 10 Oct 2024 02:09:52 +0200 Subject: [PATCH 11/19] Add some documentation to profiles --- .../Entities/BindableProfile.cs | 8 ++++++++ .../Interfaces/IGesturesProfile.cs | 19 +++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/Touch-Gestures.Lib/Entities/BindableProfile.cs b/Touch-Gestures.Lib/Entities/BindableProfile.cs index 87c6b02..881f4b8 100644 --- a/Touch-Gestures.Lib/Entities/BindableProfile.cs +++ b/Touch-Gestures.Lib/Entities/BindableProfile.cs @@ -48,6 +48,14 @@ public class BindableProfile : IGesturesProfile #region Methods + /// + /// Constructs the bindings for this profile using a set builder. + /// + /// The Tablet owning these bindings. + /// + /// TODO: Apply abstraction to bindings so that we use inherited classes or builders + /// Instead of . + /// public virtual void ConstructBindings(SharedTabletReference? tablet = null) { foreach (var gesture in TapGestures) diff --git a/Touch-Gestures.Lib/Interfaces/IGesturesProfile.cs b/Touch-Gestures.Lib/Interfaces/IGesturesProfile.cs index 2a8f7d6..9e133aa 100644 --- a/Touch-Gestures.Lib/Interfaces/IGesturesProfile.cs +++ b/Touch-Gestures.Lib/Interfaces/IGesturesProfile.cs @@ -6,14 +6,33 @@ namespace TouchGestures.Lib.Interfaces { public interface IGesturesProfile : IEnumerable { + /// + /// The name of the tablet associated with the profile. + /// + /// + /// "(Pen Only)" may be append to the name of the profile if it is a pen (Single Touch) profile.
+ /// See for more information. + ///
[JsonProperty] string Name { get; } + /// + /// Whether or not the profile is a multi-touch profile. + /// + /// + /// May also indicate that the profile is a pen (Single Touch) profile when false. + /// [JsonProperty] bool IsMultiTouch { get; } + /// + /// Add a gesture to the profile. + /// void Add(Gesture gesture); + /// + /// Remove a gesture from the profile. + /// void Remove(Gesture gesture); } } \ No newline at end of file From c0de67d20e064fdfcbfa2a7f0dfbec8c3f9f1822 Mon Sep 17 00:00:00 2001 From: Gess1t Date: Thu, 10 Oct 2024 02:14:02 +0200 Subject: [PATCH 12/19] Remove extra newline in doc --- Touch-Gestures.Lib/Entities/BindableProfile.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Touch-Gestures.Lib/Entities/BindableProfile.cs b/Touch-Gestures.Lib/Entities/BindableProfile.cs index 881f4b8..77dd549 100644 --- a/Touch-Gestures.Lib/Entities/BindableProfile.cs +++ b/Touch-Gestures.Lib/Entities/BindableProfile.cs @@ -53,8 +53,7 @@ public class BindableProfile : IGesturesProfile ///
/// The Tablet owning these bindings. /// - /// TODO: Apply abstraction to bindings so that we use inherited classes or builders - /// Instead of . + /// TODO: Apply abstraction to bindings so that we use inherited classes or builders Instead of . /// public virtual void ConstructBindings(SharedTabletReference? tablet = null) { From e3c977eccbdc7d888665859a9c98fcbc90a7f3a9 Mon Sep 17 00:00:00 2001 From: Gess1t Date: Thu, 10 Oct 2024 02:28:52 +0200 Subject: [PATCH 13/19] Implement 'Clear()' Method in Bindable Profile to reduce bloat in FromSerializable() --- .../Entities/BindableProfile.cs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/Touch-Gestures.Lib/Entities/BindableProfile.cs b/Touch-Gestures.Lib/Entities/BindableProfile.cs index 77dd549..8541c8e 100644 --- a/Touch-Gestures.Lib/Entities/BindableProfile.cs +++ b/Touch-Gestures.Lib/Entities/BindableProfile.cs @@ -124,6 +124,16 @@ public void Remove(Gesture gesture) } } + public void Clear() + { + TapGestures.Clear(); + HoldGestures.Clear(); + SwipeGestures.Clear(); + PanGestures.Clear(); + PinchGestures.Clear(); + RotateGestures.Clear(); + } + public void Update(SerializableProfile profile, SharedTabletReference tablet, Dictionary identifierToPlugin) { FromSerializable(profile, identifierToPlugin, tablet, this); @@ -177,14 +187,7 @@ public static BindableProfile FromSerializable(SerializableProfile profile, Dict result.IsMultiTouch = profile.IsMultiTouch; if (existingProfile != null) - { - result.TapGestures.Clear(); - result.HoldGestures.Clear(); - result.SwipeGestures.Clear(); - result.PanGestures.Clear(); - result.PinchGestures.Clear(); - result.RotateGestures.Clear(); - } + result.Clear(); foreach (var gesture in profile.TapGestures) { From 382a39ea2a7adb9137072b16ac7d700d3a62cf95 Mon Sep 17 00:00:00 2001 From: Gess1t Date: Thu, 10 Oct 2024 23:13:53 +0200 Subject: [PATCH 14/19] Avoid changing the current profile if tablets change --- Touch-Gestures.UX/ViewModels/BindingsOverviewViewModel.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Touch-Gestures.UX/ViewModels/BindingsOverviewViewModel.cs b/Touch-Gestures.UX/ViewModels/BindingsOverviewViewModel.cs index e45d20c..9d0ac3a 100644 --- a/Touch-Gestures.UX/ViewModels/BindingsOverviewViewModel.cs +++ b/Touch-Gestures.UX/ViewModels/BindingsOverviewViewModel.cs @@ -172,7 +172,10 @@ public void SetTablets(IEnumerable tablets) Tablets.Add(overview); } - SelectedTablet = Tablets.FirstOrDefault(); + if (SelectedTablet != null) + SelectedTablet = Tablets.FirstOrDefault(x => x.Name == SelectedTablet.Name); + + SelectedTablet ??= Tablets.FirstOrDefault(); if (SelectedTablet != null) SelectedTabletIndex = Tablets.IndexOf(SelectedTablet); From 13d5e23e312e3841b37480b9dcf715c6832293a1 Mon Sep 17 00:00:00 2001 From: Gess1t Date: Thu, 10 Oct 2024 23:15:21 +0200 Subject: [PATCH 15/19] Make sure to remove Tablet from active tablets when disposing (Now if only OpenTabletDriver actually disposed of filters when the owning device disconnected instead of leaving them as is indefinitely) --- Touch-Gestures-0.6.x/GesturesHandler.cs | 3 +++ Touch-Gestures/GesturesHandler.cs | 3 +++ 2 files changed, 6 insertions(+) diff --git a/Touch-Gestures-0.6.x/GesturesHandler.cs b/Touch-Gestures-0.6.x/GesturesHandler.cs index 0c1e332..800117b 100644 --- a/Touch-Gestures-0.6.x/GesturesHandler.cs +++ b/Touch-Gestures-0.6.x/GesturesHandler.cs @@ -284,6 +284,9 @@ public void Dispose() if (_awaitingDaemon) GesturesDaemonBase.DaemonLoaded -= OnDaemonLoaded; + if (_tablet != null) + _daemon?.RemoveTablet(_tablet); + _awaitingDaemon = false; GC.SuppressFinalize(this); diff --git a/Touch-Gestures/GesturesHandler.cs b/Touch-Gestures/GesturesHandler.cs index 1e1864f..47152a7 100644 --- a/Touch-Gestures/GesturesHandler.cs +++ b/Touch-Gestures/GesturesHandler.cs @@ -203,6 +203,9 @@ public void Dispose() if (_profile != null) _profile.ProfileChanged -= OnProfileChanged; + if (_tablet != null) + _daemon?.RemoveTablet(_tablet); + GC.SuppressFinalize(this); } From 0961f24244e5a606076c0cd565f66baf617e26ed Mon Sep 17 00:00:00 2001 From: Gess1t Date: Tue, 29 Oct 2024 13:45:23 +0100 Subject: [PATCH 16/19] Separate gesture specific TODO into their own file Also update TODO with new tasks, following #14 --- TODO-Gestures.md | 106 ++++++++++++++++++++++++++++++++++++ TODO.md | 137 +++++++++++------------------------------------ 2 files changed, 138 insertions(+), 105 deletions(-) create mode 100644 TODO-Gestures.md diff --git a/TODO-Gestures.md b/TODO-Gestures.md new file mode 100644 index 0000000..1c6f7a6 --- /dev/null +++ b/TODO-Gestures.md @@ -0,0 +1,106 @@ +## Un-ordered List + +- [x] Absolute Position based gestures (Need to start at a specific point) +- [x] Relative Position based gestures (Can be started from anywhere) + +### Node-Based Gestures + +- [ ] Gesture Recording +- [ ] Gesture Recognition + - [ ] Any single touch in a start nodes is a gesture + - [ ] More than 2 touches is a gesture +- [ ] Manual Gesture Setup + - [-] Node Types + - [-] Shared Elements + - [x] IsGestureStart (bool) (length == 1 || index == 0) + - [x] IsGestureEnd (bool) (length == 1 || index == length - 1) + - [x] Position (Vector2) + - [x] Allowed Position Deviation (double) + - [x] Timestamp (double) + - [x] Allowed Timestamp Deviation (double) + - [x] IsHold (bool) + - [x] Hold Duration (double) + - [x] Nodes Can be dragged + - [ ] Nodes Can be resized (Only for the start and end nodes) + - [ ] Rectangle + - [ ] Circle + +### Basic Gestures + +#### Gestures + +- [x] Tap (Any) + - [x] Relative + - [x] Absolute + +- [x] Hold (Any) + - [x] Relative + - [x] Absolute + +- [x] Swipe (Single) + - [x] Relative + - [x] Absolute + +- [x] Pan (Single) + - [x] Relative + - [x] Absolute + +- [x] Pinch (Single) + - [x] Relative + - [x] Absolute + +- [x] Rotate (Single) + - [x] Relative + - [x] Absolute + +#### Gestures Unit Tests + +- [x] Tap (Any) + - [x] Relative + - [x] Absolute + +- [x] Hold (Any) + - [x] Relative + - [x] Absolute + +- [x] Swipe (Single) + - [x] Relative + - [x] Absolute + +- [x] Pan (Single) + - [x] Relative + - [x] Absolute + +- [x] Pinch (Single) + - [x] Relative + - [x] Absolute + +- [x] Rotate (Single) + - [x] Relative + - [x] Absolute + +#### Gestures Setup + +- [x] Tap (Any) + - [x] Relative + - [x] Absolute + +- [x] Hold (Any) + - [x] Relative + - [x] Absolute + +- [x] Swipe (Single) + - [x] Relative + - [x] Absolute + +- [x] Pan (Single) + - [x] Relative + - [x] Absolute + +- [x] Pinch (Single) + - [x] Relative + - [x] Absolute + +- [x] Rotate (Single) + - [x] Relative + - [x] Absolute \ No newline at end of file diff --git a/TODO.md b/TODO.md index 03fc719..3bab142 100644 --- a/TODO.md +++ b/TODO.md @@ -4,112 +4,17 @@ ~~Add a `OnExternalGestureCompleted` event to `IGestures` with as parameter an GestureCompletedEventArgs that contains the gesture type and the gesture data.~~ -## Un-ordered List - -- [x] Absolute Position based gestures (Need to start at a specific point) -- [x] Relative Position based gestures (Can be started from anywhere) - -### Node-Based Gestures +## Medium Priority Tasks -- [ ] Gesture Recording -- [ ] Gesture Recognition - - [ ] Any single touch in a start nodes is a gesture - - [ ] More than 2 touches is a gesture -- [ ] Manual Gesture Setup - - [-] Node Types - - [-] Shared Elements - - [x] IsGestureStart (bool) (length == 1 || index == 0) - - [x] IsGestureEnd (bool) (length == 1 || index == length - 1) - - [x] Position (Vector2) - - [x] Allowed Position Deviation (double) - - [x] Timestamp (double) - - [x] Allowed Timestamp Deviation (double) - - [x] IsHold (bool) - - [x] Hold Duration (double) - - [x] Nodes Can be dragged - - [ ] Nodes Can be resized (Only for the start and end nodes) - - [ ] Rectangle - - [ ] Circle - -### Basic Gestures - -#### Gestures - -- [x] Tap (Any) - - [x] Relative - - [x] Absolute - -- [x] Hold (Any) - - [x] Relative - - [x] Absolute - -- [x] Swipe (Single) - - [x] Relative - - [x] Absolute - -- [x] Pan (Single) - - [x] Relative - - [x] Absolute - -- [x] Pinch (Single) - - [x] Relative - - [x] Absolute - -- [x] Rotate (Single) - - [x] Relative - - [x] Absolute - -#### Gestures Unit Tests - -- [x] Tap (Any) - - [x] Relative - - [x] Absolute - -- [x] Hold (Any) - - [x] Relative - - [x] Absolute - -- [x] Swipe (Single) - - [x] Relative - - [x] Absolute - -- [x] Pan (Single) - - [x] Relative - - [x] Absolute - -- [x] Pinch (Single) - - [x] Relative - - [x] Absolute - -- [x] Rotate (Single) - - [x] Relative - - [x] Absolute - -#### Gestures Setup - -- [x] Tap (Any) - - [x] Relative - - [x] Absolute +### Bindings Rework -- [x] Hold (Any) - - [x] Relative - - [x] Absolute +- [ ] Wrap different versions of Binding under a single generic interface, with a `Press()` and `Release()` method. -- [x] Swipe (Single) - - [x] Relative - - [x] Absolute +### Debugger -- [x] Pan (Single) - - [x] Relative - - [x] Absolute +- [ ] Implement an In-app gesture debugger, draw the inputs as well as state changes when they happen. (Simillar to osu!lazer's replay analyzer or Rewind) -- [x] Pinch (Single) - - [x] Relative - - [x] Absolute - -- [x] Rotate (Single) - - [x] Relative - - [x] Absolute +## Documentation ### Dev Documentation (Github Wiki) @@ -122,6 +27,32 @@ For each of these topics, indicates in which way such systems could be improved, - [ ] Gesture Setup - [ ] Gesture Unit Tests +- [ ] Intended behaviors + - [ ] UX + - [ ] Connection Screen + - [ ] Binding Overview (Main View) + - [ ] Gesture Setup + - [ ] Gesture Selection Screen + - [ ] Gesture Setup Screen + - [ ] Options Selection Screen + - [ ] Binding Selection Screen + - [ ] Tweaks Screen (Area & Gesture specific tweaks) + - [ ] Gesture Editing + - [ ] Gesture Removal + + - [ ] Gestures + - [ ] Tap + - [ ] Hold + - [ ] Swipe + - [ ] Pan + - [ ] Pinch + - [ ] Rotate + +- [ ] UX Testing Procedures +- [ ] Gesture Testing Procedures + - [ ] Unit Tests + - [ ] Manual Testing + ### User Documentation (Github Pages) - [ ] A download link for the current platform & another to the github releases page @@ -146,7 +77,3 @@ For each of these topics, indicates in which way such systems could be improved, - [-] FAQ - [-] Basic - [-] Troubleshooting - -### Bindings Rework - -- [ ] Wrap different versions of Binding under a single generic interface, with a `Press()` and `Release()` method. From 12e287b0292f33c7c0cbf7c576be806613dc73fb Mon Sep 17 00:00:00 2001 From: Gess1t Date: Wed, 30 Oct 2024 19:56:15 +0100 Subject: [PATCH 17/19] Use contains instead of StartsWith --- Touch-Gestures.UX/ViewModels/BindingsOverviewViewModel.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Touch-Gestures.UX/ViewModels/BindingsOverviewViewModel.cs b/Touch-Gestures.UX/ViewModels/BindingsOverviewViewModel.cs index 9d0ac3a..5eb9389 100644 --- a/Touch-Gestures.UX/ViewModels/BindingsOverviewViewModel.cs +++ b/Touch-Gestures.UX/ViewModels/BindingsOverviewViewModel.cs @@ -248,7 +248,7 @@ private void OnSearchTextChanged(string text) if (string.IsNullOrWhiteSpace(text)) CurrentGestureBindings.AddRange(SelectedTablet.Gestures); else - CurrentGestureBindings.AddRange(SelectedTablet.Gestures.Where(x => GestureNameStartsWith(x, text))); + CurrentGestureBindings.AddRange(SelectedTablet.Gestures.Where(x => GestureNameContains(x, text))); } /// @@ -452,6 +452,11 @@ private static bool GestureNameStartsWith(GestureBindingDisplayViewModel gesture return gestureTileViewModel.Description?.StartsWith(text, StringComparison.CurrentCultureIgnoreCase) ?? false; } + private static bool GestureNameContains(GestureBindingDisplayViewModel gestureTileViewModel, string text) + { + return gestureTileViewModel.Description?.Contains(text, StringComparison.CurrentCultureIgnoreCase) ?? false; + } + #endregion #region Disposal From 93bda5170a4ce704cb1994961d275c575bcc439e Mon Sep 17 00:00:00 2001 From: Gess1t Date: Tue, 26 Nov 2024 18:02:10 +0100 Subject: [PATCH 18/19] Update README how to help section --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0dc03c0..11d82f2 100644 --- a/README.md +++ b/README.md @@ -32,9 +32,11 @@ I may be able to help you out & your question may help others in the future by b ## I am a Developer, how can i help? -- Currently i'm having issues dealing with both versions at the same time, mostly because of an ongoing bug in .NET project handling. +- Packaging for Linux & MacOS (Binary Tar for each platforms + .deb?) + +- ~~Currently i'm having issues dealing with both versions at the same time, mostly because of an ongoing bug in .NET project handling. It seems to be currently impossible to have have a multi-target project & have dependencies change depending on the target framework. -What i'm noticing is that, the dependency with the highest version is always used, even if it's not compatible with the framework that is being targeted. +What i'm noticing is that, the dependency with the highest version is always used, even if it's not compatible with the framework that is being targeted.~~ - You can't use multiple gestures at the same time, as gestures with higher requirements will cancel out the lower ones. From dec7d422ede264b5e92bd4bc0e1a37b0f23aa95e Mon Sep 17 00:00:00 2001 From: Gess1t Date: Tue, 26 Nov 2024 19:15:40 +0100 Subject: [PATCH 19/19] Remove installer suffix as it's not needed anymore --- Touch-Gestures.Installer/TouchGesturesInstaller.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Touch-Gestures.Installer/TouchGesturesInstaller.cs b/Touch-Gestures.Installer/TouchGesturesInstaller.cs index abdf8a8..50e4969 100644 --- a/Touch-Gestures.Installer/TouchGesturesInstaller.cs +++ b/Touch-Gestures.Installer/TouchGesturesInstaller.cs @@ -26,11 +26,10 @@ public class TouchGesturesInstaller : ITool private static readonly FileInfo location = new(assembly.Location); private static readonly DirectoryInfo? pluginsDirectory = location.Directory?.Parent; - private static readonly string AssemblySuffix = OTD_VERSION == "0.5.x" ? "" : $"-{OTD_VERSION}"; private readonly DirectoryInfo OTDEnhancedOutputModeDirectory = null!; - private readonly string dependenciesResourcePath = $"Touch-Gestures.Installer{AssemblySuffix}.Touch-Gestures-{OTD_VERSION}.zip"; + private readonly string dependenciesResourcePath = $"Touch-Gestures.Installer.Touch-Gestures-{OTD_VERSION}.zip"; public TouchGesturesInstaller() {