JetBrains / compose-multiplatform

Compose Multiplatform, a modern UI framework for Kotlin that makes building performant and beautiful user interfaces easy and enjoyable.
https://jetbrains.com/lp/compose-multiplatform
Apache License 2.0
15.27k stars 1.11k forks source link

[Desktop] Can't capture native inputs in windows using windowHandle #4934

Closed MohamedRejeb closed 3 weeks ago

MohamedRejeb commented 3 weeks ago

I was trying capturing native input events in desktop to get some data related to stylus (pressure, tilt...) and I used window.windowHandle to access native window and it's working fine for macos. But for windows I realised that the HWND created by the windowHandle is different than the HWND coming with the events when the cursor is on top of my composables. But when I move the cursor on top of the window top bar or on top of swing components the HWND coming with the events is the same as the HWND from the windowHandle in case of interop blending is disabled but when I enable interop blending even hovering on top of swing components gives a different HWND than the events. I'm not sure what's happening exactly behind the scenes but I think that compose is getting rendered on a kind of invisible window on top of the swing window (Sometimes closing the app doesn't go well and only the compose content disappears but the window and swing components remains visible which increased my suspicion that there's two windows on top of each other).

Affected platforms

Versions

MatkovIvan commented 3 weeks ago

HWND is handle for any native view on Windows, not "window" handle. Compose provides it as-is from AWT.

Interop blending is just putting Compose above the interop and makes it transparent. So since events are received to top-most view, yes, it's not the same to swing. For interop view compose redispatching events to right view manually via AWT/Swing API.

So the situation is explainable but it's about implementation defaults of not only Compose but also AWT/Swing.

MohamedRejeb commented 3 weeks ago

Is there a way to get the handle for Compose view?

MatkovIvan commented 3 weeks ago

Well Compose has a few views internally. Public windowHandle is for rendering one (used in skia). Getting handle for other components again is AWT implementation details (with all lightweight/heavyweight specifics), but theoretically it should seem something like https://stackoverflow.com/a/413895/1703290 Another reference: https://github.com/openjdk/jdk/blob/8ffc35d117846a7a2aa08afed662273d2f887770/src/java.desktop/windows/native/libawt/windows/awt_Component.h#L165 But again, please note that it might vary across JDK distributions

MohamedRejeb commented 3 weeks ago

Currently it's working fine. I'm accepting events from all views of the window but sometimes I'm getting some unwanted events (ex: events for window top bar) which is filtered now using PointerEventType.Enter and PointerEventType.Exit to enable/disable the listener. But I want to improve it more by forcing a single HWND to receive the events from. I will check the references.

Thank you!