-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Add/implement pc.EVENT_MOUSEOUT and pc.EVENT_MOUSEENTER #4920
base: main
Are you sure you want to change the base?
Conversation
@@ -50,7 +50,7 @@ class MouseEvent { | |||
* @type {number} | |||
*/ | |||
this.y = coords.y; | |||
} else if (isMousePointerLocked()) { | |||
} else if (isMousePointerLocked() || event.type === 'mouseout') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is this necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the same note, what values are coords.x/y on a mouse out event?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is this necessary?
coords = mouse._getTargetCoords(event);
returns null and then the constructor just ends here:
engine/src/platform/input/mouse-event.js
Lines 56 to 58 in 7c582ab
} else { | |
return; | |
} |
Resulting in the entire event being "uninitialized".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the same note, what values are coords.x/y on a mouse out event?
@yaustar There are two cases:
- When mouse is inside the canvas while entering another DOM element,
mouseout
is fired and then its the normalx
/y
- When mouse leaves the window,
_getTargetCoords
returns null andx
/y
sticks to 0 (because_getTargetCoords
returns some proper values).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I see 🤔 This seems fine to me
I also noticed that mouse out event fires in unexpected situations such as: When I click drag and move out of the window, I get the event on the move out and also on button release Kapture.2022-12-13.at.12.45.54.mp4When the PlayCanvas window is not in focus and moving between the active browser window and the PlayCanvas one Kapture.2022-12-13.at.12.49.39.mp4 |
…t talking about pc Elements Co-authored-by: Steven <yaustar@users.noreply.github.com>
@yaustar Thank you for checking, it seems to be default behaviour, I get the same in Firefox and Chrome. The easiest way to test it is any empty page and then just: window.onmouseout = e => console.log(e.target.tagName); I don't know why browsers do it, but do you think PC events should try to filter such cases? |
I'm in two minds about this. On one hand, it makes sense to mirror the native events like we do everywhere else. On the other, it would be nice to have mouse in and mouse out instead of both being on the same event? |
Yea, I share your concerns here, seems like this works best: document.body.onmouseout = console.log; It isn't confused between BODY/HTML, but what I don't like is that it's accessing |
Yeah, let's not do that as the mouse DOM element can be any DOM element too on Wait, is target element not used in the mouse input? 👀 We just listen the window regardless? |
Right, engine/src/platform/input/mouse.js Lines 91 to 102 in c3d5ff7
|
Can we use it to know if we are 'mousing out' or 'in'? |
You mean to have e.g. a small 100x100px canvas and then trigger It should be possible, just that it would deviate from how e.g. the OrbitCamera script used to use it (if we speak about the same thing here). I tested |
That's fine, I wrote that years ago when I wasn't really thinking that closely where I wanted mouse out 😅 |
Yea, it seems more sensible to have it on (I can rewrite it tomorrow if no one comes up with a counter-argument 😅) |
@kungfooman Is this ready for a re-review? |
Yep, I would like that, quick intro: pc.app.mouse.on(pc.EVENT_MOUSEENTER, console.log);
pc.app.mouse.on(pc.EVENT_MOUSEOUT , console.log); or: pc.app.mouse.on(pc.EVENT_MOUSEENTER, _ => console.log("mouse enter", _));
pc.app.mouse.on(pc.EVENT_MOUSEOUT , _ => console.log("mouse out" , _)); |
If the window is not in focus, when the mouse enters, it fires both the ENTER and OUT events (see end of the video). Was this intended? Kapture.2022-12-23.at.14.12.21.mp4 |
Definitely Chrome specific but it's difficult to ship this when it 'doesn't work' with the major browser user share 😅 Edit: Wondering if we should only fire the event if the window is in focus? |
Yeah, I also remember having issues with |
I reported mouse issues in the past and it usually takes some time until issues are fixed, but imo that is the way to go - just someone needs to create a Chrome issue and keep up with it. Issue 356090: mouseout on element triggered on mouseup after entering the element with the mouse button pressed Sounds like they had it before, apparently "fixed", but not quite it seems. For my sake it works good enough besides this have-another-window-over-canvas and I'm not trying to find Chrome specific hacks for that case.
Just for testing: setInterval(()=>console.log(document.hasFocus()), 1000) But I don't see how that would work out nicely, as soon you click outside the tab you won't have any "entering" events anymore? |
There aren't any mousemove events on the app if the tab isn't in focus either so I would argue it's consistent behaviour? |
The mousemove events are always fired, focused or not: pc.app.mouse.on("mousemove", console.log); E.g. for devtools in https://playcanvas.com/viewer if you want to test. Or do you mean something different? |
Hmm, I get different behaviour on Chrome/Mac Kapture.2023-01-06.at.10.48.54.mp4 |
Funny how different the same browser is on different platforms: Peek.2023-01-06.12-49.mp4IIRC Chrome on Windows also sends mousemove even though the window is unfocused, so Mac is the oddball here. Technically it imo makes more sense to not filter events too early, since once they are filtered, there is no way back. And for a dev it would be simple enough to just |
Part of me feels like the engine should be as consistent as possible in the events it fires. If a developer wants the raw events, then there's nothing stopping them registering events on the DOM |
So mousemove shall also be filtered now to make everything work like on a Chrome Mac? |
Ideally, it should be consistent otherwise we would end up with bug reports in the engine. The fact that mouse move is different on a per OS basis is frustrating and truthfully, I don't know what the best way forward here is. We could ship this as is where the behaviour is consistent across OS's browser when the tab is in focus by the user. I think that would be okay given noone has reported about mouse move being an issue when the browser is not in focus. |
It works fine if the active window is not another Chrome window. That's probably why you can't reproduce it as you are checking against VSCode |
src/platform/input/constants.js
Outdated
@@ -52,6 +52,20 @@ export const EVENT_MOUSEUP = 'mouseup'; | |||
*/ | |||
export const EVENT_MOUSEWHEEL = 'mousewheel'; | |||
|
|||
/** | |||
* Name of event fired when the mouse moves out or enters another DOM element. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* Name of event fired when the mouse moves out or enters another DOM element. | |
* Name of event fired when the mouse moves out or enters another DOM element. This can fire on entering a PlayCanvas browser window not in focus so you may want to check with {@link https://developer.mozilla.org/en-US/docs/Web/API/Document/hasFocus document.hasFocus()}. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it really "defocused" or "unfocused"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe 'background' is a better term?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated suggested change with something with less jargon.
Edit: I just saw the commit, that looks fine too :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approved with comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approved with comment
src/platform/input/mouse.js
Outdated
|
||
const opts = platform.passiveEvents ? { passive: false } : false; | ||
window.removeEventListener('mouseup', this._upHandler, opts); | ||
window.removeEventListener('mousedown', this._downHandler, opts); | ||
window.removeEventListener('mousemove', this._moveHandler, opts); | ||
window.removeEventListener('wheel', this._wheelHandler, opts); | ||
if (this._target) { | ||
this._target.removeEventListener('mousein', this._enterHandler, opts); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be mouseenter
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow, nice catch, absolutely and thank you!
Co-authored-by: Steven <yaustar@users.noreply.github.com>
Did you test that on Linux? I tried with another tab of Chrome and I couldn't trigger the bug either. Also tried it with other apps like KolourPaint and it worked nicely. So far I believe we could just point out it only happens on Chrome/Mac, which should be fixed in Chrome/Mac's OS code (until someone brings this issue to some Mac developer attention). |
On have access to Mac unfortunately 😅 Either way, I don't think it's a blocker for the PR |
src/platform/input/constants.js
Outdated
export const EVENT_MOUSEOUT = 'mouseout'; | ||
|
||
/** | ||
* Name of event fired when the mouse moves out or enters another DOM element. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Slightly confused here since the description is identical to the first sentence of the description for EVENT_MOUSEOUT
.
@kungfooman - any thoughts on the last comments here? |
Co-authored-by: Will Eastcott <will@playcanvas.com>
Yea, it's kinda confusing, because However, good catch @willeastcott, because the I will rewrite it to make it clearer, also happy about suggestions. |
Fixes: #739
This event is missing, so devs always had to add custom event handling in their scripts, like here:
engine/scripts/camera/orbit-camera.js
Lines 378 to 388 in b07a438
This will also simplify event handling later on based on #4910, in short
ScriptType#listen
provides:disable
/destroy
enable
I confirm I have read the contributing guidelines and signed the Contributor License Agreement.