1
0
mirror of https://github.com/emilk/egui.git synced 2026-06-26 14:49:06 -04:00

Avoid repaints on device mouse motion outside window (#7866)

## Summary
- Ignore raw device mouse motion unless the window is focused and the
pointer is inside it
- Also handles pointers starting down and then moving into or out of the
window (drag & drop)
- Prevents global mouse motion from triggering continuous repaint loops
- Applies to both glow and wgpu backends

## Testing
- I ran the check script, nothing seemed to fail

---------

Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
This commit is contained in:
Matthew Runo
2026-03-02 04:00:18 -08:00
committed by GitHub
parent 4e43e65756
commit 9276778181
4 changed files with 43 additions and 9 deletions

View File

@@ -448,12 +448,21 @@ impl WinitApp for GlowWinitApp<'_> {
if let Some(viewport) = glutin
.focused_viewport
.and_then(|viewport| glutin.viewports.get_mut(&viewport))
&& let Some(window) = viewport.window.as_ref()
{
if let Some(egui_winit) = viewport.egui_winit.as_mut() {
egui_winit.on_mouse_motion(delta);
if !window.has_focus()
&& !viewport
.egui_winit
.as_ref()
.map(|state| state.is_any_pointer_button_down())
.unwrap_or(false)
{
return Ok(EventResult::Wait);
}
if let Some(window) = viewport.window.as_ref() {
if let Some(egui_winit) = viewport.egui_winit.as_mut()
&& egui_winit.on_mouse_motion(delta)
{
return Ok(EventResult::RepaintNext(window.id()));
}
}

View File

@@ -454,12 +454,21 @@ impl WinitApp for WgpuWinitApp<'_> {
if let Some(viewport) = shared
.focused_viewport
.and_then(|viewport| shared.viewports.get_mut(&viewport))
&& let Some(window) = viewport.window.as_ref()
{
if let Some(egui_winit) = viewport.egui_winit.as_mut() {
egui_winit.on_mouse_motion(delta);
if !window.has_focus()
&& !viewport
.egui_winit
.as_ref()
.map(|state| state.is_any_pointer_button_down())
.unwrap_or(false)
{
return Ok(EventResult::Wait);
}
if let Some(window) = viewport.window.as_ref() {
if let Some(egui_winit) = viewport.egui_winit.as_mut()
&& egui_winit.on_mouse_motion(delta)
{
return Ok(EventResult::RepaintNext(window.id()));
}
}

View File

@@ -640,11 +640,27 @@ impl State {
self.has_sent_ime_enabled = false;
}
pub fn on_mouse_motion(&mut self, delta: (f64, f64)) {
/// Returns `true` if the event was sent to egui.
pub fn on_mouse_motion(&mut self, delta: (f64, f64)) -> bool {
if !self.is_pointer_in_window() && !self.any_pointer_button_down {
return false;
}
self.egui_input.events.push(egui::Event::MouseMoved(Vec2 {
x: delta.0 as f32,
y: delta.1 as f32,
}));
true
}
/// Returns `true` when the pointer is currently inside the window.
pub fn is_pointer_in_window(&self) -> bool {
self.pointer_pos_in_points.is_some()
}
/// Returns `true` if any pointer button is currently held down.
pub fn is_any_pointer_button_down(&self) -> bool {
self.any_pointer_button_down
}
/// Call this when there is a new [`accesskit::ActionRequest`].

View File

@@ -97,12 +97,12 @@ You should add the following to your `.gitignore`:
* …have a low resolution to avoid growth in repo size
* …have a low comparison threshold to avoid the test passing despite unwanted differences (the default threshold should be fine for most usecases!)
### What do do when CI / another computer produces a different image?
### What to do when CI / another computer produces a different image?
The default tolerance settings should be fine for almost all gui comparison tests.
However, especially when you're using custom rendering, you may observe images difference with different setups leading to unexpected test failures.
First check whether the difference is due to a change in enabled rendering features, potentially due to difference in hardware (/software renderer) capabilitites.
First check whether the difference is due to a change in enabled rendering features, potentially due to difference in hardware (/software renderer) capabilities.
Generally you should carefully enforcing the same set of features for all test runs, but this may happen nonetheless.
Once you validated that the differences are miniscule and hard to avoid, you can try to _carefully_ adjust the comparison tolerance setting (`SnapshotOptions::threshold`, TODO([#5683](https://github.com/emilk/egui/issues/5683)): as well as number of pixels allowed to differ) for the specific test.