Skip to content
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

[Bug] InteractiveOrientationWidget stuck in active state #3144

Open
Antti-Palola opened this issue Oct 10, 2024 · 13 comments · May be fixed by #3204
Open

[Bug] InteractiveOrientationWidget stuck in active state #3144

Antti-Palola opened this issue Oct 10, 2024 · 13 comments · May be fixed by #3204
Labels
module: widget Gaps and errors in interactive widgets type: bug 🐞 Errors in functionality

Comments

@Antti-Palola
Copy link
Contributor

Bug description

InteractiveOrientationWidget stops the main view from working anymore. Can be fixed by clicking on the widget again.

Steps to reproduce

Go to https://kitware.github.io/vtk-js/examples/InteractiveOrientationWidget.html

  • Start a quick mouse drag from orientation widget and end the drag outside the widget in the canvas area.
  • OrientationMarkerWidget triggers orientation change but keeps active state
  • Try to rotate model
  • Model is stuck

Detailed Behavior

This often happens if you want to spin your model around and start the drag too close to the widget.

getActive returns true and thus the mouse event is aborted.

Expected Behavior

The widget never gets stuck in active mode.

The same kind of behavior can be caused by starting a normal model rotate and ending the drag outside browser: model will stay in rotation mode. Could this be improved by ending LeftButtonPress event on "drags outside"? I guess this event is somehow virtually created from pointerup/pointerdown events.

Environment

  • vtk.js version: latest
  • Browsers: any
  • OS: any
@Antti-Palola Antti-Palola added the type: bug 🐞 Errors in functionality label Oct 10, 2024
@finetjul
Copy link
Member

I do not reproduce the error on Windows/Chrome + Windows/Firefox. Can you record a video with your mouse cursor ?

@finetjul finetjul added the module: widget Gaps and errors in interactive widgets label Oct 11, 2024
@koskimas
Copy link

Here you go.

Macos 14.6.1
Chrome 29.0.6668.70

Screen.Recording.2024-10-11.at.9.38.26.mov.webm

@finetjul
Copy link
Member

Can you confirm it is a mac only problem ?

Do you reproduce the issue with a mouse ? touch pad ?
(I know there are some subtle differences with Mac mouse events)

@koskimas
Copy link

I'm pretty sure this happens on linux and windows too, but we'll test other OSes and pointer devices on that same example and get back to you.

@daker
Copy link
Collaborator

daker commented Oct 11, 2024

OS: Windows 11
Nvidia GPU
Mouse

Enregistrement.de.l.ecran.2024-10-11.101047.mp4

@finetjul
Copy link
Member

I still can't reproduce on my Windows laptop :-(

@daker
Copy link
Collaborator

daker commented Oct 11, 2024

This happen on both FF & Chrome, note that i can still zoom in/out with the mousewheel but not able to rotate the cone

@Antti-Palola
Copy link
Contributor Author

Can this be approached with a more code review heavy debugging. Wherever the internals of the mouse press handlers are created, is there a possibility that the mouseup is somehow misplaced?

@koskimas
Copy link

koskimas commented Oct 15, 2024

I don't have a reproduction since I don't know exactly how, but it seems to happen even without touching the orientation widget. The view is stuck several times a day on my normal usage.

Four other people at our company have reported this issue.

@Antti-Palola
Copy link
Contributor Author

Found an easy way to cause sticking. If you run the example locally after editing the widget bounds to not be 0.45 times the input bounds, it's like 50% times stuck when dragging from model and mouseUpping on top of indicator.

export function createInteractiveOrientationWidget(bounds) {
const widget = vtkInteractiveOrientationWidget.newInstance();
widget.placeWidget(bounds);
widget.setBounds(bounds.map((v) => v * 0.45));
return widget;

export function createInteractiveOrientationWidget(bounds) {
  const widget = vtkInteractiveOrientationWidget.newInstance();
  widget.placeWidget(bounds);
  widget.setBounds(bounds.map((v) => v));

  return widget;
}
stuck_interactiveOrientationWidget_safari.webm

MacOS 14.6, Safari 17.6 & FF 130 & Chrome 129

@floryst
Copy link
Collaborator

floryst commented Oct 15, 2024

I've isolated the problem. There are two parts to it: how the orientation widget operates with its own renderer, and how the widget manager behaves when there are multiple renderers.

In the orientation widget example, there are two renderers: the primary one that fills the screen and contains the cone. This renderer sits in the background. The second renderer takes up a small portion of the lower left part of the viewport and contains the widget. Importantly, the boundary of this smaller renderer is larger than the orientation widget.

The vtkWidgetManager is associated to the orientation widget renderer. This means widget selection and deselection events only occur for mouse actions inside the corner renderer. When a mouse move event occurs on top of the widget, the widget is activated. When the mouse moves off of the widget but remains inside the corner renderer, the widget is deactivated.

The bug manifests when the mouse moves fast enough such that the first mouse move event occurs on top of the widget, then the next mouse move event occurs outside of the small renderer. Since no mouse move event occurred inside the small renderer but off the widget, the widget is not deactivated. No clicking is needed; just position the mouse on the widget, then move the mouse as quickly as you can to the cone. If successful, you can't move the cone anymore.

One possible solution to this is in handleEvent. If the event should not be handled, then deactivate all widgets associated with the widget manager. (Or at minimum, deactivate all widgets if the mouse event is on a different renderer.) I think this makes sense; if you're interacting on one renderer, you don't expect to be interact with widgets on another renderer.

const handleEvent = async (callData, fromTouchEvent = false) => {
if (
!model.isAnimating &&
model.pickingEnabled &&
callData.pokedRenderer === model._renderer
) {
const callID = Symbol('UpdateSelection');
model._currentUpdateSelectionCallID = callID;
await updateSelection(callData, fromTouchEvent, callID);
}
};
.

@jord1e
Copy link

jord1e commented Jan 8, 2025

@floryst Do you know if there is a workaround for this issue at the moment?

I guess the "orientationMarkerWidget" is necessary to register the click, so we need its renderer (which causes the problem?):
widgetManager.setRenderer(orientationMarkerWidget.getRenderer());

Firefox (latest)/W10/vtk.js latest (although its been a problem for a while now)

@floryst floryst linked a pull request Jan 10, 2025 that will close this issue
5 tasks
@floryst
Copy link
Collaborator

floryst commented Jan 10, 2025

@jord1e you can try out #3204 to see if it fixes the issue for you. There is an alternative that might be better overall, but #3204 is the easiest (currently untested) fix that I can come up with.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
module: widget Gaps and errors in interactive widgets type: bug 🐞 Errors in functionality
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants