Open zepumph opened 4 years ago
To support this same work, above I added the event to be passed through in the fire callback. Please let me know if you feel like that wasn't a good change.
So the "over" pointers is something tricky in general, and there may be better ways for handling it. But in this case, Just a addInputListener( { down: ... } )
is probably better, and would sidestep the assertion issue in this case.
Additionally, the general case is somewhat difficult performance-wise. To ensure full correctness, scenery would need to check what a pointer was over on every scene-graph change (and then immediately sending events). That isn't viable performance-wise.
I think I understand, but don't you feel like this is a pretty basic use case that we should have some scenery listener for. I guess I feel like we can do "better" than just a down listener. Perhaps I am wrong though. For example we need phet-io support for that click to end up in the data stream (at least that is what we have been doing for other listeners.
For example we need phet-io support for that click to end up in the data stream (at least that is what we have been doing for other listeners.
Wouldn't the Scenery input event show up in the data stream? And then the result of closing whatever was closed?
I guess I feel like we can do "better" than just a down listener.
What would be the "better" option?
I've also added a clearOverPointers()
method above that will help resolve these issues (where it can be called once the node is removed and expected to be removed for more than a frame).
I used that and it worked like a charm! Can you explain to me why it didn't work to call "interrupt" in this case? Shouldn't that reset this state (over pointers list) for us so that we don't need to have another public function (aka a "gotcha" to remember).
Interrupting it doesn't change whether pointers are over it, and is likely to be called WHILE pointers are over it, so it could almost cause the opposite issue (missed enter).
Ahh yes, that makes a lot of sense to me. Alright I'm ready to close. Thanks @jonathanolson, I really really appreciate the help.
Reopening. This is still a problem, and I ran into it in https://github.com/phetsims/scenery/issues/1021, where @jonathanolson said in https://github.com/phetsims/equality-explorer/issues/159#issuecomment-689762790:
I believe this is probably related to https://github.com/phetsims/scenery/issues/1021, is there a point where a node with an input listener is removed?
pressListener.clearOverPointers()
is the current workaround.
If we're converting to new input listeners, then shouldn't this be fixed? Is the "clearOverPointers" workaround really an acceptable solution? It sure seems like we should be able to remove an input listener without things breaking.
Labeling with high priority because I'm in the middle of converting my sims to new listeners (e.g. phetsims/equality-explorer#159) and we're about to convert common-code (https://github.com/phetsims/scenery/issues/1078).
Sorry I lost track of this issue. Over to @jonathanolson to recommend a more robust solution than clearOverPointers
.
I ran into this in phetsims/projectile-motion#255, and I agree that this seems pretty fragile. A more robust solution would be nice.
I'm going to be brainstorming a potentially better approach for tracking "over" pointers to nodes... I agree the whole system to this sounds fragile.
Many systems might include a performance hit if implemented (but given our validatePointers overhead, maybe some would be better).
https://github.com/phetsims/scenery/issues/1116#issuecomment-788312270 brought up two potential discussions for solving this further:
@jonathanolson to write some more notes in here.
@jonathanolson, has our work in branchChangeEvents helped to fix this problem? Now we get exit events when things are turned inputEnabled:false (so also enabled:false). Should branchChangeEvents support firing exit events in other cases too?
has our work in branchChangeEvents helped to fix this problem? Now we get exit events when things are turned inputEnabled:false (so also enabled:false). Should branchChangeEvents support firing exit events in other cases too?
I think it minorly helps mitigate.
My understanding is that it's easiest to trigger this when you removeChild
a Node, and we're not firing branchChangeEvents for that. It might be a performance issue to try to detect and fire that.
Removing review label, since it doesn't seem like it's a review of existing code (still leaving assigned).
From working on https://github.com/phetsims/projectile-motion/issues/209. I have a background node that goes behind a keypad, and listens for a press so that it can hide the whole keypad layer (including the aforementioned barrier rectangle). So to review the interaction:
The issue is that when trying to use a PressListener for this (specifically a FireListener) there is a buggy edge case where the background rectangle closes and the listener does not receive an
exit
event. Therefore the mouse (or pointer) is still part of that ObservableArray when I try to reopen the keypad layer and I get an enter event again.A quick way to reproduce is to . . .
patch
```diff Index: js/phet-io/projectile-motion-phet-io-elements-baseline.js IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- js/phet-io/projectile-motion-phet-io-elements-baseline.js (revision 9fc36a1b556b6808be4144e2ecfb8dea3aaa03ad) +++ js/phet-io/projectile-motion-phet-io-elements-baseline.js (date 1574467631809) @@ -1783,7 +1783,7 @@ "phetioTypeName": "PropertyIO- event: NullableIO
", "phetioDynamicElement": false, "phetioDynamicElementArchetype": false, "phetioEventType": "USER", @@ -1793,7 +1793,7 @@ "phetioReadOnly": false, "phetioState": false, "phetioStudioControl": true, - "phetioTypeName": "EmitterIO<>" + "phetioTypeName": "EmitterIO- event: EventIO
", @@ -4630,7 +4630,7 @@ "phetioTypeName": "PropertyIO- event: NullableIO
", "phetioDynamicElement": false, "phetioDynamicElementArchetype": false, "phetioEventType": "USER", @@ -4640,7 +4640,7 @@ "phetioReadOnly": false, "phetioState": false, "phetioStudioControl": true, - "phetioTypeName": "EmitterIO<>" + "phetioTypeName": "EmitterIO- event: EventIO
", @@ -5449,7 +5449,7 @@ "phetioTypeName": "PropertyIO- event: NullableIO
", "phetioDynamicElement": false, "phetioDynamicElementArchetype": false, "phetioEventType": "USER", @@ -5459,7 +5459,7 @@ "phetioReadOnly": false, "phetioState": false, "phetioStudioControl": true, - "phetioTypeName": "EmitterIO<>" + "phetioTypeName": "EmitterIO- event: EventIO
", @@ -5592,7 +5592,7 @@ "phetioTypeName": "PropertyIO- event: NullableIO
", "phetioDynamicElement": false, "phetioDynamicElementArchetype": false, "phetioEventType": "USER", @@ -5602,7 +5602,7 @@ "phetioReadOnly": false, "phetioState": false, "phetioStudioControl": true, - "phetioTypeName": "EmitterIO<>" + "phetioTypeName": "EmitterIO- event: EventIO
", @@ -6242,7 +6242,7 @@ "phetioTypeName": "NodeIO" }, "projectileMotion.general.barrierRectangle.inputListener.firedEmitter": { - "phetioDocumentation": "A function that executes. No arguments.", + "phetioDocumentation": "A function that executes. The arguments are:- event: NullableIO
", "phetioDynamicElement": false, "phetioDynamicElementArchetype": false, "phetioEventType": "USER", @@ -6252,7 +6252,7 @@ "phetioReadOnly": false, "phetioState": false, "phetioStudioControl": true, - "phetioTypeName": "EmitterIO<>" + "phetioTypeName": "EmitterIO- event: EventIO
", @@ -7750,7 +7750,7 @@ "phetioTypeName": "NodeIO" }, "projectileMotion.general.navigationBar.phetButton.phetMenu.aboutMenuItem.inputListener.firedEmitter": { - "phetioDocumentation": "A function that executes. No arguments.", + "phetioDocumentation": "A function that executes. The arguments are:- event: NullableIO
", "phetioDynamicElement": false, "phetioDynamicElementArchetype": false, "phetioEventType": "USER", @@ -7760,7 +7760,7 @@ "phetioReadOnly": false, "phetioState": false, "phetioStudioControl": true, - "phetioTypeName": "EmitterIO<>" + "phetioTypeName": "EmitterIO- event: EventIO
", @@ -7841,7 +7841,7 @@ "phetioTypeName": "NodeIO" }, "projectileMotion.general.navigationBar.phetButton.phetMenu.screenshotMenuItem.inputListener.firedEmitter": { - "phetioDocumentation": "A function that executes. No arguments.", + "phetioDocumentation": "A function that executes. The arguments are:- event: NullableIO
", "phetioDynamicElement": false, "phetioDynamicElementArchetype": false, "phetioEventType": "USER", @@ -7851,7 +7851,7 @@ "phetioReadOnly": false, "phetioState": false, "phetioStudioControl": true, - "phetioTypeName": "EmitterIO<>" + "phetioTypeName": "EmitterIO- event: EventIO
", @@ -8491,7 +8491,7 @@ "phetioTypeName": "NodeIO" }, "projectileMotion.homeScreen.view.dragScreenLargeButton.inputListener.firedEmitter": { - "phetioDocumentation": "A function that executes. No arguments.", + "phetioDocumentation": "A function that executes. The arguments are:- event: NullableIO
", "phetioDynamicElement": false, "phetioDynamicElementArchetype": false, "phetioEventType": "USER", @@ -8501,7 +8501,7 @@ "phetioReadOnly": false, "phetioState": false, "phetioStudioControl": true, - "phetioTypeName": "EmitterIO<>" + "phetioTypeName": "EmitterIO- event: EventIO
", @@ -8647,7 +8647,7 @@ "phetioTypeName": "NodeIO" }, "projectileMotion.homeScreen.view.dragScreenSmallButton.inputListener.firedEmitter": { - "phetioDocumentation": "A function that executes. No arguments.", + "phetioDocumentation": "A function that executes. The arguments are:- event: NullableIO
", "phetioDynamicElement": false, "phetioDynamicElementArchetype": false, "phetioEventType": "USER", @@ -8657,7 +8657,7 @@ "phetioReadOnly": false, "phetioState": false, "phetioStudioControl": true, - "phetioTypeName": "EmitterIO<>" + "phetioTypeName": "EmitterIO- event: EventIO
", @@ -8803,7 +8803,7 @@ "phetioTypeName": "NodeIO" }, "projectileMotion.homeScreen.view.introScreenLargeButton.inputListener.firedEmitter": { - "phetioDocumentation": "A function that executes. No arguments.", + "phetioDocumentation": "A function that executes. The arguments are:- event: NullableIO
", "phetioDynamicElement": false, "phetioDynamicElementArchetype": false, "phetioEventType": "USER", @@ -8813,7 +8813,7 @@ "phetioReadOnly": false, "phetioState": false, "phetioStudioControl": true, - "phetioTypeName": "EmitterIO<>" + "phetioTypeName": "EmitterIO- event: EventIO
", @@ -8959,7 +8959,7 @@ "phetioTypeName": "NodeIO" }, "projectileMotion.homeScreen.view.introScreenSmallButton.inputListener.firedEmitter": { - "phetioDocumentation": "A function that executes. No arguments.", + "phetioDocumentation": "A function that executes. The arguments are:- event: NullableIO
", "phetioDynamicElement": false, "phetioDynamicElementArchetype": false, "phetioEventType": "USER", @@ -8969,7 +8969,7 @@ "phetioReadOnly": false, "phetioState": false, "phetioStudioControl": true, - "phetioTypeName": "EmitterIO<>" + "phetioTypeName": "EmitterIO- event: EventIO
", @@ -9115,7 +9115,7 @@ "phetioTypeName": "NodeIO" }, "projectileMotion.homeScreen.view.labScreenLargeButton.inputListener.firedEmitter": { - "phetioDocumentation": "A function that executes. No arguments.", + "phetioDocumentation": "A function that executes. The arguments are:- event: NullableIO
", "phetioDynamicElement": false, "phetioDynamicElementArchetype": false, "phetioEventType": "USER", @@ -9125,7 +9125,7 @@ "phetioReadOnly": false, "phetioState": false, "phetioStudioControl": true, - "phetioTypeName": "EmitterIO<>" + "phetioTypeName": "EmitterIO- event: EventIO
", @@ -9271,7 +9271,7 @@ "phetioTypeName": "NodeIO" }, "projectileMotion.homeScreen.view.labScreenSmallButton.inputListener.firedEmitter": { - "phetioDocumentation": "A function that executes. No arguments.", + "phetioDocumentation": "A function that executes. The arguments are:- event: NullableIO
", "phetioDynamicElement": false, "phetioDynamicElementArchetype": false, "phetioEventType": "USER", @@ -9281,7 +9281,7 @@ "phetioReadOnly": false, "phetioState": false, "phetioStudioControl": true, - "phetioTypeName": "EmitterIO<>" + "phetioTypeName": "EmitterIO- event: EventIO
", @@ -9518,7 +9518,7 @@ "phetioTypeName": "NodeIO" }, "projectileMotion.homeScreen.view.vectorsScreenLargeButton.inputListener.firedEmitter": { - "phetioDocumentation": "A function that executes. No arguments.", + "phetioDocumentation": "A function that executes. The arguments are:- event: NullableIO
", "phetioDynamicElement": false, "phetioDynamicElementArchetype": false, "phetioEventType": "USER", @@ -9528,7 +9528,7 @@ "phetioReadOnly": false, "phetioState": false, "phetioStudioControl": true, - "phetioTypeName": "EmitterIO<>" + "phetioTypeName": "EmitterIO- event: EventIO
", @@ -9674,7 +9674,7 @@ "phetioTypeName": "NodeIO" }, "projectileMotion.homeScreen.view.vectorsScreenSmallButton.inputListener.firedEmitter": { - "phetioDocumentation": "A function that executes. No arguments.", + "phetioDocumentation": "A function that executes. The arguments are:- event: NullableIO
", "phetioDynamicElement": false, "phetioDynamicElementArchetype": false, "phetioEventType": "USER", @@ -9684,7 +9684,7 @@ "phetioReadOnly": false, "phetioState": false, "phetioStudioControl": true, - "phetioTypeName": "EmitterIO<>" + "phetioTypeName": "EmitterIO- event: EventIO
", @@ -11585,7 +11585,7 @@ "phetioTypeName": "PropertyIO- event: NullableIO
", "phetioDynamicElement": false, "phetioDynamicElementArchetype": false, "phetioEventType": "USER", @@ -11595,7 +11595,7 @@ "phetioReadOnly": false, "phetioState": false, "phetioStudioControl": true, - "phetioTypeName": "EmitterIO<>" + "phetioTypeName": "EmitterIO- event: EventIO
", @@ -13067,7 +13067,7 @@ "phetioTypeName": "PropertyIO- event: NullableIO
", "phetioDynamicElement": false, "phetioDynamicElementArchetype": false, "phetioEventType": "USER", @@ -13077,7 +13077,7 @@ "phetioReadOnly": false, "phetioState": false, "phetioStudioControl": true, - "phetioTypeName": "EmitterIO<>" + "phetioTypeName": "EmitterIO- event: EventIO
", @@ -16472,6 +16472,45 @@ "phetioStudioControl": true, "phetioTypeName": "NodeIO" }, + "projectileMotion.labScreen.view.keypadLayer.clickOutsideFireListener.firedEmitter": { + "phetioDocumentation": "A function that executes. The arguments are:- event: NullableIO
", + "phetioDynamicElement": false, + "phetioDynamicElementArchetype": false, + "phetioEventType": "USER", + "phetioFeatured": false, + "phetioHighFrequency": false, + "phetioPlayback": false, + "phetioReadOnly": false, + "phetioState": false, + "phetioStudioControl": true, + "phetioTypeName": "EmitterIO- event: EventIO
", + "phetioDynamicElement": false, + "phetioDynamicElementArchetype": false, + "phetioEventType": "USER", + "phetioFeatured": false, + "phetioHighFrequency": false, + "phetioPlayback": false, + "phetioReadOnly": false, + "phetioState": false, + "phetioStudioControl": true, + "phetioTypeName": "ActionIO- event: NullableIO
", + "phetioDynamicElement": false, + "phetioDynamicElementArchetype": false, + "phetioEventType": "USER", + "phetioFeatured": false, + "phetioHighFrequency": false, + "phetioPlayback": false, + "phetioReadOnly": false, + "phetioState": false, + "phetioStudioControl": true, + "phetioTypeName": "ActionIO- event: NullableIO
", "phetioDynamicElement": false, "phetioDynamicElementArchetype": false, "phetioEventType": "USER", @@ -18160,7 +18199,7 @@ "phetioReadOnly": false, "phetioState": false, "phetioStudioControl": true, - "phetioTypeName": "EmitterIO<>" + "phetioTypeName": "EmitterIO- event: EventIO
", @@ -23701,7 +23740,7 @@ "phetioTypeName": "NumberDisplayIO" }, "projectileMotion.labScreen.view.projectilePanel.customControl.altitudeControl.numberDisplay.fireListener.firedEmitter": { - "phetioDocumentation": "A function that executes. No arguments.", + "phetioDocumentation": "A function that executes. The arguments are:- event: NullableIO
", "phetioDynamicElement": false, "phetioDynamicElementArchetype": false, "phetioEventType": "USER", @@ -23711,7 +23750,7 @@ "phetioReadOnly": false, "phetioState": false, "phetioStudioControl": true, - "phetioTypeName": "EmitterIO<>" + "phetioTypeName": "EmitterIO- event: EventIO
", @@ -24078,7 +24117,7 @@ "phetioTypeName": "NumberDisplayIO" }, "projectileMotion.labScreen.view.projectilePanel.customControl.diameterControl.numberDisplay.fireListener.firedEmitter": { - "phetioDocumentation": "A function that executes. No arguments.", + "phetioDocumentation": "A function that executes. The arguments are:- event: NullableIO
", "phetioDynamicElement": false, "phetioDynamicElementArchetype": false, "phetioEventType": "USER", @@ -24088,7 +24127,7 @@ "phetioReadOnly": false, "phetioState": false, "phetioStudioControl": true, - "phetioTypeName": "EmitterIO<>" + "phetioTypeName": "EmitterIO- event: EventIO
", @@ -24455,7 +24494,7 @@ "phetioTypeName": "NumberDisplayIO" }, "projectileMotion.labScreen.view.projectilePanel.customControl.dragCoefficientControl.numberDisplay.fireListener.firedEmitter": { - "phetioDocumentation": "A function that executes. No arguments.", + "phetioDocumentation": "A function that executes. The arguments are:- event: NullableIO
", "phetioDynamicElement": false, "phetioDynamicElementArchetype": false, "phetioEventType": "USER", @@ -24465,7 +24504,7 @@ "phetioReadOnly": false, "phetioState": false, "phetioStudioControl": true, - "phetioTypeName": "EmitterIO<>" + "phetioTypeName": "EmitterIO- event: EventIO
", @@ -24832,7 +24871,7 @@ "phetioTypeName": "NumberDisplayIO" }, "projectileMotion.labScreen.view.projectilePanel.customControl.gravityControl.numberDisplay.fireListener.firedEmitter": { - "phetioDocumentation": "A function that executes. No arguments.", + "phetioDocumentation": "A function that executes. The arguments are:- event: NullableIO
", "phetioDynamicElement": false, "phetioDynamicElementArchetype": false, "phetioEventType": "USER", @@ -24842,7 +24881,7 @@ "phetioReadOnly": false, "phetioState": false, "phetioStudioControl": true, - "phetioTypeName": "EmitterIO<>" + "phetioTypeName": "EmitterIO- event: EventIO
", @@ -25209,7 +25248,7 @@ "phetioTypeName": "NumberDisplayIO" }, "projectileMotion.labScreen.view.projectilePanel.customControl.massControl.numberDisplay.fireListener.firedEmitter": { - "phetioDocumentation": "A function that executes. No arguments.", + "phetioDocumentation": "A function that executes. The arguments are:- event: NullableIO
", "phetioDynamicElement": false, "phetioDynamicElementArchetype": false, "phetioEventType": "USER", @@ -25219,7 +25258,7 @@ "phetioReadOnly": false, "phetioState": false, "phetioStudioControl": true, - "phetioTypeName": "EmitterIO<>" + "phetioTypeName": "EmitterIO- event: EventIO
", @@ -35609,7 +35648,7 @@ "phetioTypeName": "PropertyIO- event: NullableIO
", "phetioDynamicElement": false, "phetioDynamicElementArchetype": false, "phetioEventType": "USER", @@ -35619,7 +35658,7 @@ "phetioReadOnly": false, "phetioState": false, "phetioStudioControl": true, - "phetioTypeName": "EmitterIO<>" + "phetioTypeName": "EmitterIO- event: EventIO
", @@ -38456,7 +38495,7 @@ "phetioTypeName": "PropertyIO- event: NullableIO
", "phetioDynamicElement": false, "phetioDynamicElementArchetype": false, "phetioEventType": "USER", @@ -38466,7 +38505,7 @@ "phetioReadOnly": false, "phetioState": false, "phetioStudioControl": true, - "phetioTypeName": "EmitterIO<>" + "phetioTypeName": "EmitterIO- event: EventIO
", @@ -40094,7 +40133,7 @@ "phetioTypeName": "PropertyIO- event: NullableIO
", "phetioDynamicElement": false, "phetioDynamicElementArchetype": false, "phetioEventType": "USER", @@ -40104,7 +40143,7 @@ "phetioReadOnly": false, "phetioState": false, "phetioStudioControl": true, - "phetioTypeName": "EmitterIO<>" + "phetioTypeName": "EmitterIO- event: EventIO
", @@ -41017,7 +41056,7 @@ "phetioTypeName": "PropertyIO- event: NullableIO
", "phetioDynamicElement": false, "phetioDynamicElementArchetype": false, "phetioEventType": "USER", @@ -41027,7 +41066,7 @@ "phetioReadOnly": false, "phetioState": false, "phetioStudioControl": true, - "phetioTypeName": "EmitterIO<>" + "phetioTypeName": "EmitterIO- event: EventIO
", @@ -41160,7 +41199,7 @@ "phetioTypeName": "PropertyIO- event: NullableIO
", "phetioDynamicElement": false, "phetioDynamicElementArchetype": false, "phetioEventType": "USER", @@ -41170,7 +41209,7 @@ "phetioReadOnly": false, "phetioState": false, "phetioStudioControl": true, - "phetioTypeName": "EmitterIO<>" + "phetioTypeName": "EmitterIO- event: EventIO
", Index: js/lab/view/KeypadLayer.js IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- js/lab/view/KeypadLayer.js (revision 9fc36a1b556b6808be4144e2ecfb8dea3aaa03ad) +++ js/lab/view/KeypadLayer.js (date 1574464747734) @@ -10,7 +10,6 @@ 'use strict'; // modules - const DownUpListener = require( 'SCENERY/input/DownUpListener' ); const inherit = require( 'PHET_CORE/inherit' ); const Keypad = require( 'SCENERY_PHET/keypad/Keypad' ); const merge = require( 'PHET_CORE/merge' ); @@ -18,6 +17,7 @@ const Panel = require( 'SUN/Panel' ); const PhetColorScheme = require( 'SCENERY_PHET/PhetColorScheme' ); const Plane = require( 'SCENERY/nodes/Plane' ); + const FireListener = require( 'SCENERY/listeners/FireListener' ); const projectileMotion = require( 'PROJECTILE_MOTION/projectileMotion' ); const ProjectileMotionConstants = require( 'PROJECTILE_MOTION/common/ProjectileMotionConstants' ); const Rectangle = require( 'SCENERY/nodes/Rectangle' ); @@ -61,13 +61,16 @@ Plane.call( this, options ); - // @private clicking outside the keypad cancels the edit - this.clickOutsideListener = new DownUpListener( { - down: function( event ) { + // @private - clicking outside the keypad cancels the edit + this.clickOutsideFireListener = new FireListener( { + fire: function( event ) { if ( event.trail.lastNode() === self ) { self.cancelEdit(); } - } + }, + fireOnDown: true, + tandem: options.tandem.createTandem( 'clickOutsideFireListener' ), + phetioDocumentation: 'listener responsible for hiding the KeypadLayer when space outside of the keypad is pressed.' } ); // @private these will be set when the client calls beginEdit @@ -207,7 +210,7 @@ this.visible = true; // keypadLayer lasts for the lifetime of the sim, so listeners don't need to be disposed - this.addInputListener( this.clickOutsideListener ); + this.addInputListener( this.clickOutsideFireListener ); // execute client-specific hook options.onBeginEdit && options.onBeginEdit(); @@ -224,7 +227,7 @@ // hide the keypad this.visible = false; - this.removeInputListener( this.clickOutsideListener ); + this.removeInputListener( this.clickOutsideFireListener ); // execute client-specific hook this.onEndEdit && this.onEndEdit(); Index: js/phet-io/projectile-motion-phet-io-types.js IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- js/phet-io/projectile-motion-phet-io-types.js (revision 9fc36a1b556b6808be4144e2ecfb8dea3aaa03ad) +++ js/phet-io/projectile-motion-phet-io-types.js (date 1574467631846) @@ -389,6 +389,35 @@ "supertype": "ActionIO<>", "typeName": "EmitterIO<>" }, + "EmitterIOArguments: NullableIO
Return Type: VoidIO", + "events": [], + "methodOrder": [], + "methods": {}, + "parameterTypes": [ + "NullableIO
Arguments: NullableIO
Return Type: VoidIO", "events": [], ```
@jonathanolson do you think there is an easy way detect this case and clear the
overPointers
list?For now I will not go ahead with the conversion to FireListener, but I think this blocks phet-io publication of Projectile Motion because DownUpListener has not had much in the way of phet-io design, especially compared to the PressListener hierarchy.
@ariel-phet please prioritize.