-
Notifications
You must be signed in to change notification settings - Fork 15
fix:手掌擦 #419
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: beta
Are you sure you want to change the base?
fix:手掌擦 #419
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -44,6 +44,9 @@ public partial class MainWindow : Window | |
| /// 多点触控延迟时间(毫秒) | ||
| /// </summary> | ||
| private const double MULTI_TOUCH_DELAY_MS = 100; | ||
| private bool isMultiTouchTimerActive; | ||
| private bool isPalmEraserActive; | ||
| private bool palmEraserWasEnabledBeforeMultiTouch; | ||
|
|
||
| /// <summary> | ||
| /// 保存画布上的非笔画元素(如图片、媒体元素等) | ||
|
|
@@ -227,6 +230,12 @@ private void BorderMultiTouchMode_MouseUp(object sender, MouseButtonEventArgs e) | |
| RestoreNonStrokeElements(preservedElements); | ||
| isInMultiTouchMode = false; | ||
|
|
||
| if (palmEraserWasEnabledBeforeMultiTouch) | ||
| { | ||
| Settings.Canvas.EnablePalmEraser = true; | ||
| if (ToggleSwitchEnablePalmEraser != null) | ||
| ToggleSwitchEnablePalmEraser.IsOn = true; | ||
| } | ||
| } | ||
| else | ||
| { | ||
|
|
@@ -247,6 +256,11 @@ private void BorderMultiTouchMode_MouseUp(object sender, MouseButtonEventArgs e) | |
| // 恢复非笔画元素 | ||
| RestoreNonStrokeElements(preservedElements); | ||
| isInMultiTouchMode = true; | ||
|
|
||
| palmEraserWasEnabledBeforeMultiTouch = Settings.Canvas.EnablePalmEraser; | ||
| Settings.Canvas.EnablePalmEraser = false; | ||
| if (ToggleSwitchEnablePalmEraser != null) | ||
| ToggleSwitchEnablePalmEraser.IsOn = false; | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -703,21 +717,13 @@ private void Main_Grid_TouchDown(object sender, TouchEventArgs e) | |
| /// <param name="e">触摸事件参数</param> | ||
| /// <returns>返回触摸边界宽度</returns> | ||
| /// <remarks> | ||
| /// 根据触摸事件参数计算触摸边界宽度,包括以下逻辑: | ||
| /// 1. 获取触摸点的边界 | ||
| /// 2. 如果不是四边红外屏幕,使用边界宽度 | ||
| /// 3. 如果是四边红外屏幕,使用边界宽度和高度的平方根 | ||
| /// 4. 如果是特殊屏幕,乘以触摸倍数 | ||
| /// 5. 返回计算得到的触摸边界宽度 | ||
| /// 手掌擦阈值与特殊屏 <c>TouchMultiplier</c> 在激活逻辑中单独参与计算,此处仅返回几何接触尺寸。 | ||
| /// </remarks> | ||
| public double GetTouchBoundWidth(TouchEventArgs e) | ||
| { | ||
| var args = e.GetTouchPoint(null).Bounds; | ||
| double value; | ||
| if (!Settings.Advanced.IsQuadIR) value = args.Width; | ||
| else value = Math.Sqrt(args.Width * args.Height); //四边红外 | ||
| if (Settings.Advanced.IsSpecialScreen) value *= Settings.Advanced.TouchMultiplier; | ||
| return value; | ||
| if (!Settings.Advanced.IsQuadIR) return args.Width; | ||
| return Math.Sqrt(args.Width * args.Height); | ||
| } | ||
|
|
||
| /// <summary> | ||
|
|
@@ -741,28 +747,146 @@ public double GetTouchBoundWidth(TouchEventArgs e) | |
| /// </remarks> | ||
| private void InkCanvas_PreviewTouchDown(object sender, TouchEventArgs e) | ||
| { | ||
| var touchPointForBar = e.GetTouchPoint(this); | ||
| var floatingBarBounds = ViewboxFloatingBar.TransformToAncestor(this).TransformBounds( | ||
| new Rect(0, 0, ViewboxFloatingBar.ActualWidth, ViewboxFloatingBar.ActualHeight)); | ||
| if (floatingBarBounds.Contains(touchPointForBar.Position)) | ||
| return; | ||
|
|
||
| if ((inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint | ||
| || inkCanvas.EditingMode == InkCanvasEditingMode.EraseByStroke) | ||
| && !isPalmEraserActive) | ||
| { | ||
| return; | ||
| } | ||
|
|
||
| if (drawingShapeMode != 0) | ||
| { | ||
| inkCanvas.EditingMode = InkCanvasEditingMode.None; | ||
| SetCursorBasedOnEditingMode(inkCanvas); | ||
| inkCanvas.CaptureTouch(e.TouchDevice); | ||
| ViewboxFloatingBar.IsHitTestVisible = false; | ||
| BlackboardUIGridForInkReplay.IsHitTestVisible = false; | ||
|
|
||
| isTouchDown = true; | ||
|
|
||
| if (dec.Count == 0) | ||
| { | ||
| var inkTouchPoint = e.GetTouchPoint(inkCanvas); | ||
| if (drawingShapeMode == 24 || drawingShapeMode == 25) | ||
| { | ||
| if (drawMultiStepShapeCurrentStep == 0) | ||
| iniP = inkTouchPoint.Position; | ||
| } | ||
| else | ||
| { | ||
| iniP = inkTouchPoint.Position; | ||
| } | ||
| lastTouchDownStrokeCollection = inkCanvas.Strokes.Clone(); | ||
| } | ||
| dec.Add(e.TouchDevice.Id); | ||
| return; | ||
| } | ||
|
|
||
| SetCursorBasedOnEditingMode(inkCanvas); | ||
| inkCanvas.CaptureTouch(e.TouchDevice); | ||
| ViewboxFloatingBar.IsHitTestVisible = false; | ||
| BlackboardUIGridForInkReplay.IsHitTestVisible = false; | ||
|
|
||
| lastTouchDownTime = DateTime.Now; | ||
| dec.Add(e.TouchDevice.Id); | ||
| //设备1个的时候,记录中心点 | ||
|
|
||
| if (Settings.Canvas.EnablePalmEraser && !isPalmEraserActive && drawingShapeMode == 0) | ||
| { | ||
| var touchPoint = e.GetTouchPoint(inkCanvas); | ||
| double boundWidth = GetTouchBoundWidth(e); | ||
|
|
||
| if ((Settings.Advanced.TouchMultiplier != 0 || !Settings.Advanced.IsSpecialScreen) | ||
| && (boundWidth > BoundsWidth)) | ||
| { | ||
| double thresholdMultiplier; | ||
| switch (Settings.Canvas.PalmEraserSensitivity) | ||
| { | ||
| case 0: | ||
| thresholdMultiplier = 3.0; | ||
| break; | ||
| case 1: | ||
| thresholdMultiplier = 2.5; | ||
| break; | ||
| case 2: | ||
| default: | ||
| thresholdMultiplier = 2.0; | ||
| break; | ||
| } | ||
|
|
||
| double EraserThresholdValue = Settings.Startup.IsEnableNibMode | ||
| ? Settings.Advanced.NibModeBoundsWidthThresholdValue | ||
| : Settings.Advanced.FingerModeBoundsWidthThresholdValue; | ||
|
|
||
| if (boundWidth > BoundsWidth * EraserThresholdValue * thresholdMultiplier) | ||
| { | ||
| boundWidth *= Settings.Startup.IsEnableNibMode | ||
| ? Settings.Advanced.NibModeBoundsWidthEraserSize | ||
| : Settings.Advanced.FingerModeBoundsWidthEraserSize; | ||
|
|
||
| if (Settings.Advanced.IsSpecialScreen) | ||
| boundWidth *= Settings.Advanced.TouchMultiplier; | ||
| inkCanvas.EditingMode = InkCanvasEditingMode.EraseByPoint; | ||
| isPalmEraserActive = true; | ||
|
|
||
| EnableEraserOverlay(); | ||
| eraserWidth = boundWidth; | ||
| UpdateEraserStyle(); | ||
| touchPoint = e.GetTouchPoint(inkCanvas); | ||
| EraserOverlay_PointerDown(sender); | ||
| EraserOverlay_PointerMove(sender, touchPoint.Position); | ||
| if (Settings.Canvas.IsShowCursor) | ||
| { | ||
| inkCanvas.ForceCursor = false; | ||
| inkCanvas.UseCustomCursor = false; | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if (dec.Count == 1) | ||
| { | ||
| var touchPoint = e.GetTouchPoint(inkCanvas); | ||
| centerPoint = touchPoint.Position; | ||
|
|
||
| //记录第一根手指点击时的 StrokeCollection | ||
| lastTouchDownStrokeCollection = inkCanvas.Strokes.Clone(); | ||
| } | ||
| //设备两个及两个以上,将画笔功能关闭 | ||
|
|
||
| if (dec.Count > 1 || isSingleFingerDragMode || !Settings.Gesture.IsEnableTwoFingerGesture) | ||
| { | ||
| if (isInMultiTouchMode || !Settings.Gesture.IsEnableTwoFingerGesture) return; | ||
| if (inkCanvas.EditingMode == InkCanvasEditingMode.None || | ||
| inkCanvas.EditingMode == InkCanvasEditingMode.Select) return; | ||
| var timeSinceLastTouch = (DateTime.Now - lastTouchDownTime).TotalMilliseconds; | ||
| if (timeSinceLastTouch < MULTI_TOUCH_DELAY_MS && inkCanvas.EditingMode == InkCanvasEditingMode.Ink) | ||
| { | ||
| if (!isMultiTouchTimerActive) | ||
| { | ||
| isMultiTouchTimerActive = true; | ||
| var remainingTime = MULTI_TOUCH_DELAY_MS - timeSinceLastTouch; | ||
| Task.Delay((int)remainingTime).ContinueWith(_ => | ||
| { | ||
| Dispatcher.Invoke(() => | ||
| { | ||
| if (dec.Count > 1 && inkCanvas.EditingMode == InkCanvasEditingMode.Ink) | ||
| inkCanvas.EditingMode = InkCanvasEditingMode.None; | ||
| isMultiTouchTimerActive = false; | ||
| }); | ||
| }); | ||
| } | ||
| return; | ||
| } | ||
|
|
||
| lastInkCanvasEditingMode = inkCanvas.EditingMode; | ||
| inkCanvas.EditingMode = InkCanvasEditingMode.None; | ||
| if (inkCanvas.EditingMode != InkCanvasEditingMode.EraseByPoint | ||
| && inkCanvas.EditingMode != InkCanvasEditingMode.EraseByStroke | ||
| && drawingShapeMode == 0) | ||
| { | ||
| inkCanvas.EditingMode = InkCanvasEditingMode.None; | ||
| } | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -776,6 +900,11 @@ private void InkCanvas_PreviewTouchDown(object sender, TouchEventArgs e) | |
| /// </remarks> | ||
| private void InkCanvas_PreviewTouchMove(object sender, TouchEventArgs e) | ||
| { | ||
| if (isPalmEraserActive) | ||
| { | ||
| var touchPoint = e.GetTouchPoint(inkCanvas); | ||
| EraserOverlay_PointerMove(sender, touchPoint.Position); | ||
| } | ||
| } | ||
|
|
||
| /// <summary> | ||
|
|
@@ -802,32 +931,18 @@ private void InkCanvas_PreviewTouchMove(object sender, TouchEventArgs e) | |
| /// </remarks> | ||
| private void InkCanvas_PreviewTouchUp(object sender, TouchEventArgs e) | ||
| { | ||
| if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint && !isPalmEraserActive) | ||
| { | ||
| return; | ||
| } | ||
| inkCanvas.ReleaseAllTouchCaptures(); | ||
| ViewboxFloatingBar.IsHitTestVisible = true; | ||
| BlackboardUIGridForInkReplay.IsHitTestVisible = true; | ||
|
|
||
| //手势完成后切回之前的状态 | ||
| if (dec.Count > 1) | ||
| if (inkCanvas.EditingMode == InkCanvasEditingMode.None) | ||
| inkCanvas.EditingMode = lastInkCanvasEditingMode; | ||
| dec.Remove(e.TouchDevice.Id); | ||
|
|
||
| if (dec.Count == 0) | ||
| { | ||
| isSingleFingerDragMode = false; | ||
| isWaitUntilNextTouchDown = false; | ||
| if (drawingShapeMode == 0 | ||
| && inkCanvas.EditingMode != InkCanvasEditingMode.EraseByPoint | ||
| && inkCanvas.EditingMode != InkCanvasEditingMode.EraseByStroke | ||
| && inkCanvas.EditingMode != InkCanvasEditingMode.Select | ||
| && inkCanvas.EditingMode != InkCanvasEditingMode.None) | ||
| { | ||
| if (lastInkCanvasEditingMode != InkCanvasEditingMode.None) | ||
| { | ||
| inkCanvas.EditingMode = lastInkCanvasEditingMode; | ||
| } | ||
| } | ||
| } | ||
| if (dec.Count <= 1) | ||
| isMultiTouchTimerActive = false; | ||
|
|
||
| if (drawingShapeMode != 0) | ||
| { | ||
|
|
@@ -839,12 +954,10 @@ private void InkCanvas_PreviewTouchUp(object sender, TouchEventArgs e) | |
| { | ||
| if (drawMultiStepShapeCurrentStep == 0) | ||
| { | ||
| // 第一笔完成,进入第二笔 | ||
| drawMultiStepShapeCurrentStep = 1; | ||
| } | ||
| else | ||
| { | ||
| // 第二笔完成,完成绘制 | ||
| var mouseArgs = new MouseButtonEventArgs(Mouse.PrimaryDevice, 0, MouseButton.Left) | ||
| { | ||
| RoutedEvent = MouseLeftButtonUpEvent, | ||
|
|
@@ -864,6 +977,36 @@ private void InkCanvas_PreviewTouchUp(object sender, TouchEventArgs e) | |
| } | ||
| } | ||
|
|
||
| if (drawingShapeMode == 0) | ||
| { | ||
| if (dec.Count > 1) | ||
| { | ||
| if (inkCanvas.EditingMode == InkCanvasEditingMode.None) | ||
| { | ||
| if (lastInkCanvasEditingMode != InkCanvasEditingMode.EraseByPoint) | ||
| inkCanvas.EditingMode = lastInkCanvasEditingMode; | ||
| } | ||
| } | ||
| else if (dec.Count == 0) | ||
| { | ||
| isSingleFingerDragMode = false; | ||
| isWaitUntilNextTouchDown = false; | ||
|
|
||
| if (inkCanvas.EditingMode == InkCanvasEditingMode.None && | ||
| lastInkCanvasEditingMode != InkCanvasEditingMode.None && | ||
| lastInkCanvasEditingMode != InkCanvasEditingMode.EraseByPoint) | ||
| { | ||
| inkCanvas.EditingMode = lastInkCanvasEditingMode; | ||
| } | ||
|
|
||
| if (isPalmEraserActive) | ||
| { | ||
| isPalmEraserActive = false; | ||
| DisableEraserOverlay(); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The palm-eraser teardown calls Useful? React with 👍 / 👎. |
||
| } | ||
| } | ||
| } | ||
|
|
||
| inkCanvas.Opacity = 1; | ||
|
|
||
| if (dec.Count == 0) | ||
|
|
@@ -961,6 +1104,9 @@ private void Main_Grid_ManipulationCompleted(object sender, ManipulationComplete | |
| /// </remarks> | ||
| private void Main_Grid_ManipulationDelta(object sender, ManipulationDeltaEventArgs e) | ||
| { | ||
| if (inkCanvas.EditingMode == InkCanvasEditingMode.EraseByPoint) | ||
| return; | ||
|
|
||
| if (isInMultiTouchMode || !Settings.Gesture.IsEnableTwoFingerGesture) return; | ||
|
|
||
| bool hasMultipleManipulators = e.Manipulators.Count() >= 2; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When the last touch is released, this block only clears
isPalmEraserActiveand never restoresinkCanvas.EditingModefromEraseByPoint. BecausePreviewTouchDownnow returns early whenever mode isEraseByPointandisPalmEraserActiveis false, touch input can get stuck after one palm-erase gesture (no further touch inking/gesture handling until another path changes the mode). Persist and restore the pre-palm mode (typically Ink) when deactivating palm eraser.Useful? React with 👍 / 👎.