Stylus Testing Bugs: Hover Issues On Real Devices
Hey guys! Let's dive into some nitty-gritty details about the bugs we've found while testing our Flutter app with a stylus on actual devices. We've run into some interesting problems specifically related to hover interactions. So, let’s break it down and see what’s going on.
Hover Issues on Canvas Page Icons
So, the first head-scratcher we encountered was on the canvas page. Whenever we hover over the top three icons with a stylus, things start acting up. Let's take a closer look at the error logs we're seeing. It seems like the app is trying to render the Scribble widget, but we're also getting a ton of skipped frames. This suggests that the main thread is getting overloaded, which is never a good sign. Here’s a snippet of the logs:
I/flutter (22025): 렌더링: Scribble 위젯
I/Choreographer(22025): Skipped 30 frames! The application may be doing too much work on its main thread.
I/ViewRootImpl(22025): updatePointerIcon pointerType = 20001, calling pid = 22025
D/InputManager(22025): setPointerIconType iconId = 20001, callingPid = 22025
I/ViewRootImpl(22025): updatePointerIcon pointerType = 1002, calling pid = 22025
D/InputManager(22025): setPointerIconType iconId = 1002, callingPid = 22025
I/ViewRootImpl(22025): updatePointerIcon pointerType = 20001, calling pid = 22025
D/InputManager(22025): setPointerIconType iconId = 20001, callingPid = 22025
We see that the Choreographer
is skipping frames, indicating performance issues. The system is also rapidly updating the pointer icon, which could be related to the hover interaction. It looks like we need to optimize how the Scribble widget is rendered or find a more efficient way to handle hover events. Maybe there’s some redundant processing happening on each hover that’s bogging things down.
Additionally, we're seeing an assertion failure related to pointer events. Check this out:
══╡ EXCEPTION CAUGHT BY GESTURES LIBRARY ╞══════════════════════════════════════════════════════════
The following assertion was thrown while handling a pointer data packet:
'package:flutter/src/rendering/mouse_tracker.dart': Failed assertion: line 224 pos 12: '(event is
PointerAddedEvent) == (lastEvent is PointerRemovedEvent)': is not true.
Either the assertion indicates an error in the framework itself, or we should provide substantially
more information in this error message to help you determine and fix the underlying cause.
In either case, please report this assertion by filing a bug on GitHub:
https://github.com/flutter/flutter/issues/new?template=02_bug.yml
When the exception was thrown, this was the stack:
#2 MouseTracker._shouldMarkStateDirty (package:flutter/src/rendering/mouse_tracker.dart:224:12)
#3 MouseTracker.updateWithEvent (package:flutter/src/rendering/mouse_tracker.dart:321:10)
#4 RendererBinding.dispatchEvent (package:flutter/src/rendering/binding.dart:466:20)
#5 GestureBinding._handlePointerEventImmediately (package:flutter/src/gestures/binding.dart:437:7)
#6 GestureBinding.handlePointerEvent (package:flutter/src/gestures/binding.dart:394:5)
#7 GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:341:7)
#8 GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:308:9)
#9 _invoke1 (dart:ui/hooks.dart:347:13)
#10 PlatformDispatcher._dispatchPointerDataPacket (dart:ui/platform_dispatcher.dart:467:7)
#11 _dispatchPointerDataPacket (dart:ui/hooks.dart:282:31)
(elided 2 frames from class _AssertionError)
══════════════
This assertion failure suggests a mismatch in pointer events. It seems like the MouseTracker
in Flutter's rendering library is expecting a PointerRemovedEvent
after a PointerAddedEvent
, but that’s not happening. This could be a bug in how Flutter handles stylus input, or it might be an issue in our code where we’re not correctly managing the pointer states. We need to investigate the gesture handling and ensure that pointer events are being dispatched and processed in the correct order. Perhaps there's a race condition or an incorrect state update when the stylus hovers over the icons.
Hover Issues on Graph View Edges
Next up, we’ve got some trouble in the graph view. When hovering over the edges (the lines connecting nodes) in the graph, we're seeing another error. This one looks like it’s related to the overlay management in the Flame engine, which we're using for the graph view. Here’s the error message:
E/flutter (22025): [ERROR:flutter/runtime/dart_vm_initializer.cc(40)] Unhandled Exception: 'package:flame/src/game/overlay_manager.dart': Failed assertion: line 59 pos 7: '_builders.containsKey(name)': Trying to add an unknown overlay "edge7def1417-12e2-4f59-87c7-154742a8d3cc-link@1-ea0a8a35-d1dc-41d5-aad9-0866258cb2a8"
E/flutter (22025): #0 _AssertionError._doThrowNew (dart:core-patch/errors_patch.dart:67:4)
E/flutter (22025): #1 _AssertionError._throwNew (dart:core-patch/errors_patch.dart:49:5)
E/flutter (22025): #2 OverlayManager._addImpl (package:flame/src/game/overlay_manager.dart:59:7)
E/flutter (22025): #3 OverlayManager.add (package:flame/src/game/overlay_manager.dart:41:24)
E/flutter (22025): #4 EdgeComponent.onHoverEnter.<anonymous closure> (package:flutter_graph_view/widgets/edge_component.dart:86:26)
E/flutter (22025): #5 new Future.delayed.<anonymous closure> (dart:async/future.dart:419:42)
E/flutter (22025): #6 Timer._createTimer.<anonymous closure> (dart:async-patch/timer_patch.dart:18:15)
E/flutter (22025): #7 _Timer._runTimers (dart:isolate-patch/timer_impl.dart:410:19)
E/flutter (22025): #8 _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:441:5)
E/flutter (22025): #9 _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:193:12)
E/flutter (22025):
The error message indicates that we’re trying to add an overlay with a name that’s not registered in the OverlayManager
. This is happening inside the onHoverEnter
method of the EdgeComponent
. It looks like we’re dynamically generating overlay names based on the edge’s properties, but something is going wrong, and the overlay isn't being properly registered. This could be a race condition, a naming conflict, or a simple oversight in how we’re setting up the overlays. We need to ensure that every overlay we try to add is correctly registered with the OverlayManager
beforehand. Maybe there is an issue with how the overlay name is generated or a mismatch between when the overlay is added and when it's defined.
Possible Causes and Solutions
Okay, so let’s recap and brainstorm some potential causes and solutions for these stylus hover issues.
Canvas Page Icons
- Performance Overload: The skipped frames suggest that rendering the Scribble widget or handling hover events is too taxing on the main thread. We could try optimizing the rendering process, perhaps by debouncing the hover events or using more efficient drawing techniques. Think about reducing the number of rebuilds or using caching mechanisms to avoid redundant computations.
- Pointer Event Mismatch: The assertion failure indicates a problem with how pointer events are being handled. We need to dive deep into the gesture handling code and ensure that
PointerAddedEvent
andPointerRemovedEvent
are correctly paired. It might be helpful to add some logging to track the sequence of events and identify where the mismatch is occurring. Consider using Flutter'sListener
widget to get more fine-grained control over event handling.
Graph View Edges
- Overlay Management: The error with the
OverlayManager
suggests that we’re not correctly registering overlays before trying to add them. We need to review the code that generates overlay names and ensures that each name is unique and registered. It could also be a timing issue where we’re trying to add the overlay before it’s fully initialized. Double-check that the overlay builders are properly set up and that the names match the expected format. Implementing a registration system that ensures all overlays are known to the manager before being added could also solve this.
Next Steps
So, what's the plan of action, guys? Here’s what I think we should do:
- Profiling: Use Flutter’s performance profiling tools to identify the bottlenecks in the canvas page rendering. This will help us pinpoint exactly what’s causing the skipped frames.
- Gesture Handling Debugging: Add detailed logging to the gesture handling code to track the sequence of pointer events. This should help us understand why the assertion is failing.
- Overlay Registration Review: Carefully review the overlay management code in the graph view, paying close attention to how overlay names are generated and registered. We might need to implement a more robust registration system.
- Stylus-Specific Testing: Focus our testing efforts specifically on stylus interactions. It’s clear that there are some unique issues that don’t show up with mouse or touch input.
By systematically investigating these issues and implementing the solutions above, we can iron out these bugs and make our app shine with stylus input. Let's get to work and make this app even better! Remember, high-quality content and providing value to readers (and users!) is what we're all about. Let’s keep it casual, friendly, and effective!