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] Dragging window causes focus toggling, plus eats mouse event(s) #10767

Open
ConnorKrammer opened this issue Aug 25, 2024 · 9 comments
Open
Labels
platform: Windows status: needs triage This issue needs to triage, applied to new issues type: bug

Comments

@ConnorKrammer
Copy link

ConnorKrammer commented Aug 25, 2024

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:

  • When clicking without prior focus:

    • Focus gained
    • Mouse down
    • Focus lost
    • Focus gained
  • When clicking with prior focus:

    • Mouse down
    • Focus lost
    • Focus gained

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:

  • When clicking without prior focus:

    • Focus gained
    • (delay)
    • Focus lost
    • Focus gained
  • When clicking with prior focus:

    • (delay)
    • Focus lost
    • Focus gained

(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:

  • The delay is not present when clicking on a webview drag region. It only appears when clicking on the native window frame.
  • When clicking on the native window frame, the focus toggle seems to occur after a small delay of around half a second, at least on my system.
  • If the window has prior focus and the click is released faster than that, the focus toggle may not be observed at all, though it will always appear if the click is held for a time before releasing.
  • For whatever reason, without prior focus, this effect seems not to be sensitive to how long the mouse is held down. Clicking, even quickly, will cause focus/unfocus/focus.
  • When I accidentally introduced a great deal of lag by using the webview dev tools and Window Detective to observe window messages at the same time, this bug disappeared, both when interacting with the native window frame and within drag regions within the webview. Extra focus/unfocus events were not observed, nor were mouse up events eaten. I suspect that enough lag was introduced in just the right places that the misbehaving code's ordering was changed, causing it to no longer manifest the bug.

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)

  • Green indicates messages that were sent after clicking down with the left mouse button.
  • Orange indicates messages also sent while the left mouse button is held down, but which only triggered after a ~500ms delay (note the timestamps), and which appear to correlate with the focus toggle issue I describe above.
  • Blue indicates messages that were sent after releasing the left mouse button.

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 ConnorKrammer added status: needs triage This issue needs to triage, applied to new issues type: bug labels Aug 25, 2024
@ConnorKrammer
Copy link
Author

ConnorKrammer commented Aug 25, 2024

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.

@1739616529
Copy link

遇到了一样的问题

@1739616529
Copy link

当窗口聚焦时, 点击 data-tauri-drag-region attr dom元素会触发 blur 事件

@amrbashir
Copy link
Member

Thanks for the detailed issue, the problem is that when clicking inside data-tauri-drag-region, we simulate another mouse click on the window "Caption (titlebar) area", see implementation here https://github.com/tauri-apps/tao/blob/2fffdc9db73edbd529f4c3cf889b33029cefd955/src/platform_impl/windows/window.rs#L517 and so the mouse up event will never fire or at least not on the webview.

A fix for that might be sending a mouse up event to the webview, but the webview is created by another process and we may not even be able to send the click to it. Also the webview team decided they won't provide an API to access the webview HWND because it is created from another process.

We maybe able to fix this another way by using WebView2 in composition mode instead of hosted mode, but we can't do that until we drop Windows 7 support.

Alternatively, you could try WebView2 app-region: drag CSS (supported only on Windows), we tried to make data-tauri-drag-region use that under the hood, but broke compatibility with other platforms, see this PR for more context #9860

@ConnorKrammer
Copy link
Author

@amrbashir Thanks for linking to the relevant piece of code, and suggesting a possible workaround. Do you have any idea why the window loses and regains focus when clicking? In my reproduction I logged window focus changes from within the webview, but it's not just the webview that experiences the loss of focus: if you print logs in response to WindowEvent::Focused from the Rust side, you'll see it happen there too.

@amrbashir
Copy link
Member

I am not sure I quite follow what you mean. Could you explain a bit more or provide a repro

@ConnorKrammer
Copy link
Author

@amrbashir Two things are going on here, on a click that triggers the bug:

  • mouse up events are being swallowed/discarded
  • window focus is toggling when it shouldn't

You gave a hypothesis for why the former is happening, but not the latter, so I was asking about it. It's all described in detail in the original post, though if you mistake it to be about just the one issue, the other, related one may recede into the background.

Here's what I'm referring to, though:

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

  • When clicking without prior focus:
    • Focus gained
    • Mouse down
    • Focus lost
    • Focus gained

The mouse up event is missing, but also, there's an additional "focus lost / focus gained" in there. If initially unfocused, the only change in focus state that should occur is a singular gain in focus. The last two bullet points shouldn't be present at all.

Similarly, when already focused, there should be no change in the focus state at all. Nevertheless:

  • When clicking with prior focus:
    • Mouse down
    • Focus lost
    • Focus gained

We still observe a loss and regain of focus.

On top of that, this bug occurs even when dragging by the native title bar, which is entirely outside the webview.

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

Might be worth re-reading the original post with that additional context in mind, since I think it may have been missed the first time.

The original post also contains a full reproduction of the given behaviour. It all still reproduces on the latest release version of Tauri.

@amrbashir
Copy link
Member

These are still related to the same issue. I have added an explanation below

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

  • When clicking without prior focus:

    • Focus gained > this is normal
    • Mouse down > then mouse down is captured by tauri and starts dragging
    • Focus lost > focus is lost because we simulated a click on titlebar (even if hidden)
    • Focus gained > drag ended, but mouse is still inside the webview and it regained focus

Similarly, when already focused, there should be no change in the focus state at all. Nevertheless:

  • When clicking with prior focus:

    • Mouse down > this is normal then mouse down is captured by tauri and starts dragging
    • Focus lost > focus is lost because we simulated a click on titlebar (even if hidden)
    • Focus gained > drag ended, but mouse is still inside the webview and it regained focus

@amrbashir
Copy link
Member

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

  • When clicking without prior focus:

    • Focus gained
    • (delay)
    • Focus lost
    • Focus gained
  • When clicking with prior focus:

    • (delay)
    • Focus lost
    • Focus gained

This one is a bit interesting and weird but I think it is because Whenever the window hosting the webview gains focus, we automatically focus the webview. See https://github.com/tauri-apps/wry/blob/c1b26b9612bf5c5a9e4e0185f73739a2444343cd/src/webview2/mod.rs#L1077-L1080

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
platform: Windows status: needs triage This issue needs to triage, applied to new issues type: bug
Projects
None yet
Development

No branches or pull requests

4 participants