diff --git a/lib/components/canvas/canvas_gesture_detector.dart b/lib/components/canvas/canvas_gesture_detector.dart index 8d2cb2863..813173a24 100644 --- a/lib/components/canvas/canvas_gesture_detector.dart +++ b/lib/components/canvas/canvas_gesture_detector.dart @@ -23,6 +23,7 @@ class CanvasGestureDetector extends StatefulWidget { required this.onDrawUpdate, required this.onDrawEnd, required this.onPressureChanged, + required this.onStylusButtonChanged, required this.undo, required this.redo, @@ -45,6 +46,7 @@ class CanvasGestureDetector extends StatefulWidget { /// Called when the pressure of the stylus changes, /// pressure is negative if stylus button is pressed final ValueChanged onPressureChanged; + final ValueChanged onStylusButtonChanged; final VoidCallback undo; final VoidCallback redo; @@ -202,15 +204,26 @@ class _CanvasGestureDetectorState extends State { void _listenerPointerEvent(PointerEvent event) { double? pressure; + bool stylusButtonPressed = false; + if (event.kind == PointerDeviceKind.stylus) { pressure = event.pressure; + stylusButtonPressed = event.buttons == kPrimaryStylusButton; } else if (event.kind == PointerDeviceKind.invertedStylus) { - pressure = -event.pressure; + pressure = event.pressure; + stylusButtonPressed = true; // treat eraser as stylus button } else if (Platform.isLinux && event.pressureMin != event.pressureMax) { // if min == max, then the device isn't pressure sensitive pressure = event.pressure; } + widget.onPressureChanged(pressure); + widget.onStylusButtonChanged(stylusButtonPressed); + } + + void _listenerPointerUpEvent(PointerEvent event) { + widget.onPressureChanged(null); + widget.onStylusButtonChanged(false); } @override @@ -222,6 +235,7 @@ class _CanvasGestureDetectorState extends State { Listener( onPointerDown: _listenerPointerEvent, onPointerMove: _listenerPointerEvent, + onPointerUp: _listenerPointerUpEvent, child: GestureDetector( onSecondaryTapUp: (TapUpDetails details) => widget.undo(), onTertiaryTapUp: (TapUpDetails details) => widget.redo(), diff --git a/lib/components/toolbar/toolbar.dart b/lib/components/toolbar/toolbar.dart index de227f1de..cdfa73ceb 100644 --- a/lib/components/toolbar/toolbar.dart +++ b/lib/components/toolbar/toolbar.dart @@ -131,11 +131,7 @@ class _ToolbarState extends State { void toggleEraser() { toolOptionsType = ToolOptions.hide; - if (widget.currentTool is Eraser) { - widget.setTool(Pen.currentPen); - } else { - widget.setTool(Eraser()); - } + widget.setTool(Eraser()); // this toggles eraser } void toggleColorOptions() { setState(() { diff --git a/lib/pages/editor/editor.dart b/lib/pages/editor/editor.dart index 3248f2def..f30340b93 100644 --- a/lib/pages/editor/editor.dart +++ b/lib/pages/editor/editor.dart @@ -127,6 +127,11 @@ class EditorState extends State { /// Whether the platform can rasterize a pdf bool canRasterPdf = true; + /// The tool that was used before switching to the eraser. + Tool? tmpTool; + /// If the stylus button is pressed. + bool stylusButtonPressed = false; + @override void initState() { DynamicMaterialApp.addFullscreenListener(_setState); @@ -466,8 +471,6 @@ class EditorState extends State { int? dragPageIndex; double? currentPressure; - /// if [pressureWasNegative], switch back to pen when pressure becomes positive again - bool pressureWasNegative = false; bool isDrawGesture(ScaleStartDetails details) { if (coreInfo.readOnly) return false; @@ -626,11 +629,6 @@ class EditorState extends State { } }); autosaveAfterDelay(); - - if (pressureWasNegative) { - pressureWasNegative = false; - currentTool = Pen.currentPen; - } } void onInteractionEnd(ScaleEndDetails details) { // reset after 1ms to keep track of the same gesture only @@ -639,13 +637,27 @@ class EditorState extends State { lastSeenPointerCount = 0; }); } - void onPressureChanged(double? pressure) { - currentPressure = pressure == 0.0 ? null : pressure; - if (currentPressure == null) return; - if (currentPressure! < 0) { - pressureWasNegative = true; + void onPressureChanged(double? pressure) { + currentPressure = pressure == 0 ? null : pressure; + } + void onStylusButtonChanged(bool buttonPressed) { + stylusButtonPressed = buttonPressed; + + if (buttonPressed) { + if (currentTool is Eraser) return; + tmpTool = currentTool; + if (currentTool is Pen && dragPageIndex != null) { + // if the pen is currently drawing, end the stroke + (currentTool as Pen).onDragEnd(); + } currentTool = Eraser(); + setState(() {}); + } else { + if (tmpTool == null) return; + currentTool = tmpTool!; + tmpTool = null; + setState(() {}); } } @@ -1107,6 +1119,7 @@ class EditorState extends State { onDrawStart: onDrawStart, onDrawUpdate: onDrawUpdate, onDrawEnd: onDrawEnd, + onStylusButtonChanged: onStylusButtonChanged, onPressureChanged: onPressureChanged, undo: undo, @@ -1189,6 +1202,18 @@ class EditorState extends State { setTool: (tool) { setState(() { + if (tool is Eraser) { + // setTool(Eraser) is called to toggle eraser + if (currentTool is Eraser && tmpTool != null) { + // switch to previous tool + tool = tmpTool!; + tmpTool = null; + } else { + // store previous tool to restore it later + tmpTool = currentTool; + } + } + currentTool = tool; if (currentTool is Highlighter) {