tauri-apps / tauri

Build smaller, faster, and more secure desktop applications with a web frontend.
https://tauri.app
Apache License 2.0
81.83k stars 2.45k forks source link

[bug] Dragging window causes focus toggling, plus eats mouse event(s) #10767

Open ConnorKrammer opened 3 weeks ago

ConnorKrammer commented 3 weeks ago

Describe the bug

On Windows, clicking any draggable region within a Tauri window causes a toggling of window focus and the loss of certain mouse events as observed by the webview. This occurs both with parts of the window which are within the native frame (e.g. titlebar, resize borders), and designated drag regions within the webview. When clicking in a webview drag region, the loss of the mouse up event very rarely seems to cause the window to get stuck in a dragging state, such that it will follow the mouse until the user clicks again.

While draggable regions are associated with this behaviour, actually dragging them is unnecessary. Only clicking is required, though in certain cases you may need to hold the click for a moment before releasing.

A prior issue describes what I believe to be the same problem. I've opened a new issue to provide additional information and up-to-date reproductions steps, since this actually bit me when developing my current project.

When clicking on a drag region within the webview, the following events are observed by the webview in this order:

Notice the absence of a mouse up event: this will seemingly never be observed by event listeners in the webview. (If you double-click instead of single clicking, then the second mouse up event will be visible: but this is only because it triggers the window maximize handler instead of the drag start handler.)

When clicking in the native window frame area, outside the webview, the observed events are similar, with the addition of a delay:

(No mouse events are seen by the webview in this case, but this is expected, since they occur in the frame area beyond the webview's bounds.)

About the delay:

I'm not certain the delay will replicate on every system, but the gap is suspiciously close to 500ms.

Here's a recording of a trace of the window messages, captured using Window Detective. Starting without focus on the window, I mouse over the native titlebar, pause, click down, hold for a moment, and then release. While the mouse button is held down, the mouse is not moved at all.

Tauri focus issue - window messages

Here also is a static screenshot of those window messages after the fact, with coloured bars drawn along the left-hand side so that you can easily associate them with the cause:

screenshot  2024-08-24 20-32-27 (annotated)

I poked through the Tauri internals a bit to see if I could figure out exactly where this was happening, but I'm still getting familiar with the project and with Rust, so I'm not very effective yet. I hope the above information can help someone else with a better grasp of the project pinpoint where it's happening.

Do let me know if there's anything further information I could provide that would be useful.

Reproduction

  1. Create a minimal Tauri program using create-tauri-app:

    cargo create-tauri-app --rc
  2. Add core:window:allow-start-dragging to the program permissions.

  3. Insert the following code at the end of main.js:

    // Misc. setup. Can be ignored.
    let dragRegion = document.createElement('div');
    dragRegion.style.height = '100%';
    dragRegion.style.width = '100%';
    dragRegion.style.position = 'fixed';
    dragRegion.style.top = '0';
    dragRegion.style.left = '0';
    dragRegion.style.display = 'flex';
    dragRegion.style.justifyContent = 'center';
    dragRegion.style.alignItems = 'center';
    dragRegion.style.backgroundColor = 'grey';
    document.body.append(dragRegion);
    
    let label = document.createElement('div');
    label.textContent = 'Drag anywhere in the grey region to move the window.';
    label.style.pointerEvents = 'none';
    dragRegion.append(label);
    
    // Make document draggable via its interior
    // Requires core:window:allow-start-dragging
    dragRegion.setAttribute('data-tauri-drag-region', '');
    
    // Make change of focus observable
    window.addEventListener('focus', () => console.log('Focus gained'));
    window.addEventListener('blur', () => console.log('Focus lost'));
    
    // Make mouse events observable
    //
    // We use capturing listeners so that we see the event before Tauri calls both
    // preventDefault() and stopPropagation() on it (see: drag.js).
    document.addEventListener('mousedown', () => console.log('> Mouse down'), { capture: true });
    document.addEventListener('mouseup', () => console.log('> Mouse up'), { capture: true });
  4. Run the program in dev mode:

    cargo tauri dev
  5. Open the dev tools and watch the messages logged in the console as the window is clicked.

Expected behavior

The window should not lose focus when it is clicked while already focused. Mouse up events within the webview should not be silently ignored, even when clicking on a drag region.

Full tauri info output

[✔] Environment
    - OS: Windows 10.0.19045 X64
    ✔ WebView2: 127.0.2651.105
    ✔ MSVC: Visual Studio Community 2022
    ✔ rustc: 1.80.0 (051478957 2024-07-21)
    ✔ cargo: 1.80.0 (376290515 2024-07-16)
    ✔ rustup: 1.27.1 (54dd3d00f 2024-04-24)
    ✔ Rust toolchain: stable-x86_64-pc-windows-msvc (environment override by RUSTUP_TOOLCHAIN)
    - node: 18.12.1
    - npm: 8.19.2

[-] Packages
    - tauri [RUST]: 2.0.0-rc.6
    - tauri-build [RUST]: 2.0.0-rc.6
    - wry [RUST]: 0.42.0
    - tao [RUST]: 0.29.1
    - tauri-cli [RUST]: 2.0.0-rc.3
    - @tauri-apps/api : not installed!
    - @tauri-apps/cli [NPM]: 2.0.0-rc.3

[-] App
    - build-type: bundle
    - CSP: unset
    - frontendDist: ../src

Stack trace

No response

Additional context

No response

ConnorKrammer commented 3 weeks ago

After thinking to record the window messages under the laggy conditions that cause the focus bug to disappear, I produced the following merged chart that shows the diff between a buggy execution and a bug-free execution. Messages arrive in the following order, with the messages on the left, under the "bug only" column, being present only when logging messages under bug-manifesting conditions. Messages on the right are present only under bug-free conditions, and in the middle we have messages which appear to be constant between the buggy and bug-free cases.

(Some messages appear to be duplicated, but only because of how Window Detective lists them: when applicable, there's one entry for when the message is posted, and a second for when the message is returned. You can see this annotated in the screenshots above, but not when I transcribe the messages in text only.)

Common Messages
WM_MOUSEACTIVATE
WM_MOUSEACTIVATE
WM_SETCURSOR
WM_SETCURSOR
WM_NCLBUTTONDOWN
WM_WINDOWNPOSCHANGING
WM_WINDOWNPOSCHANGING
WM_WINDOWNPOSCHANGED
WM_WINDOWNPOSCHANGED
WM_ACTIVATEAPP
WM_ACTIVATEAPP
WM_NCACTIVATE
WM_NCACTIVATE
WM_ACTIVATE
WM_IME_SETCONTEXT
WM_IME_NOTIFY
WM_IME_NOTIFY
WM_IME_SETCONTEXT
WM_SETFOCUS
WM_KILLFOCUS
WM_KILLFOCUS
WM_IME_SETCONTEXT
WM_IME_SETCONTEXT
WM_SETFOCUS
WM_ACTIVATE
WM_SYSCOMMAND
WM_MOUSEMOVE
Bug Only
WM_CAPTURECHANGED
WM_CAPTURECHANGED
WM_GETMINMAXINFO
WM_GETMINMAXINFO
WM_ENTERSIZEMOVE
WM_ENTERSIZEMOVE
WM_NCMOUSELEAVE
WM_MOUSEMOVE
WM_MOUSEMOVE
Common Messages
WM_LBUTTONUP
WM_CAPTURECHANGED
WM_CAPTURECHANGED
WM_WINDOWPOSCHANGING
WM_WINDOWPOSCHANGING
Bug Only
WM_EXITSIZEMOVE
WM_EXITSIZEMOVE
Common Messages
WM_SYSCOMMAND
Bug-Free Only
WM_NCMOUSELEAVE
Common Messages
WM_SETCURSOR
WM_SETCURSOR
WM_NCMOUSEMOVE

Note the second chunk, where the first bug-only section appears. The messages in that chunk match up with those I highlighted in orange in my first comment.