w3c / pointerlock

Pointer Lock
https://w3c.github.io/pointerlock/
Other
17 stars 16 forks source link

feature request : Allow to set pointer position upon release #61

Open nadavsinai opened 4 years ago

nadavsinai commented 4 years ago

Hi,

Here at Philips we develop a medical imaging application that uses requestPointerLock extensively to allow for complex Mouse+keyboard operations on canvas. Specifically, the user may perform really long drags (for example for zooming) , which without the pointerlock would exit the canvas. We have a problem when the operation needs to be communicated via the pointer as well as the change in the image, for example in tools like ‘magnify glass’ tool - When the user releases the mouse, the cursor goes back to its initial location, and the user may have a long way to move the mouse to the new position of the magnify glass

I know this has been discussed a little in #41, but the scenario is different.

we suggest adding two optional arguments to exitPointerLock: a dx and dy to set the pointer to a new position just before making the pointer visible.

document.exitPointerLock(dx, dy);
sirisian commented 2 years ago

I also need this capability for nearly the same reason. I'm building a node editor library that features a large canvas and allows dragging around nodes and creating connections. Dragging around objects inside of the screen and also dragging with panning as they hit the edge is not a use case currently implementable by combing setPointerCapture and requestPointerLock.

Imagine the simple scenario where you drag a rectangle left inside of a large canvas. As you drag left the mouse moves to the left. When the rectangle hits the canvas's left side the displayed mouse needs to stop moving and the canvas should begin panning left.

Using setPointerCapture works until the rectangle hits the left. If you attempt to solve this by calling requestPointerLock (and optionally drawing a fake cursor) you can then scroll left more and all is well. That is until you move the mouse up or down. If you move the cursor up the rectangle moves up but the cursor position stays where the requestPointerLock started. That means when you release the cursor is no longer on top of the rectangle in the same spot.

So the only feasible way for this to work is to allow the cursor position to be defined on exitPointerLock as explained.

With WebGPU releasing it's becoming extremely viable to implement advanced applications offering things like material editors and such directly into the browser. Being able to duplicate the UX found in professional software 1:1 will be important in making these solutions viable.

hvanops commented 1 year ago

Thanks for sharing this feature request and your use cases. It definitely helps to understand the problem you need solved.

One concern that was pointed out to me is that this might open up this use case to the risk of "click jacking", where users are tricked into clicking on things they did not intend to click. It might need extra design work to prevent this abuse and will not be a super quick fix.

This isn't an active work item for us, but is something that we'll watch out for other comments and emojis on for future.

Paril commented 1 year ago

I'm running into this same issue currently, and I think an easy way to avoid the click-jacking risk is to simply clamp the cursor position within the element that has pointer lock access. If you're already accepting a pointer lock, you're already locked into the element, so I don't think there'd be any risk to having the physical cursor moved within that same bound when the lock is relinquished (it's the same place you clicked to get into it). There could be an additional check to ensure that that same element is still directly underneath the cursor or something, but I don't see that being any worse than the page warping a

reillyeon commented 1 year ago

A solution here needs to avoid this being usable to move the cursor to an arbitrary position by rapidly locking and unlocking the cursor.

sirisian commented 1 year ago

A solution here needs to avoid this being usable to move the cursor to an arbitrary position by rapidly locking and unlocking the cursor.

Off the top of my head exitPointerLock can ignore the move if requestPointerLock is called outside of an isTrusted pointer down scope. That would require that to move the cursor the user starts the action with an interaction. This works for my example and @nadavsinai's drag examples while preventing arbitrary lock and move actions that might confuse a user.

Is there a use-case this doesn't account for?

As far as click-jacking I think @Paril is onto something. Most drag examples have the cursor starting and moving to the same area (some kind of working canvas with moving entities generally).

@hvanops Would these kind of solutions be acceptable? I'd like to get something working in browsers for at least the most common use-cases, so having caveats I think is workable to keep it simple.