mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-10-24 10:08:00 -06:00
M3: give the kept button release back before the next press (Wayland)
The release a desktop grab kept from egui was appended to the next input, so when that input carried the press of a second resize or move the button ended the frame up and the drag stopped. It now goes before the input's first primary press; only a release ahead of any press counts as the kept one, since a quick click's release belongs to its own press. Found by CodeRabbit in review of #3970. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017rPQFoRmQbw8vWhGgGVrRs
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
0b63a73c04
commit
185c2dbc36
@@ -247,15 +247,23 @@ pub fn desktop_grab(ctx: &egui::Context, command: egui::ViewportCommand) {
|
||||
}
|
||||
|
||||
/// After `desktop_grab`, add the primary button's release to the next input, unless it brings one.
|
||||
/// The release goes before the input's first press (the next resize or move, or a click), which
|
||||
/// egui would otherwise end straight away; a release after that press is the press's own.
|
||||
pub fn release_after_desktop_grab(ctx: &egui::Context, raw: &mut egui::RawInput) {
|
||||
if ctx.data_mut(|d| d.remove_temp::<()>(grab_id())).is_none() {
|
||||
return;
|
||||
}
|
||||
let released = raw.events.iter().any(|e| matches!(e, egui::Event::PointerButton { button: egui::PointerButton::Primary, pressed: false, .. }));
|
||||
if !released {
|
||||
let (pos, modifiers) = ctx.input(|i| (i.pointer.interact_pos().unwrap_or_default(), i.modifiers));
|
||||
raw.events.push(egui::Event::PointerButton { pos, button: egui::PointerButton::Primary, pressed: false, modifiers });
|
||||
}
|
||||
let first = raw.events.iter().enumerate().find_map(|(n, e)| match e {
|
||||
egui::Event::PointerButton { button: egui::PointerButton::Primary, pressed, .. } => Some((n, *pressed)),
|
||||
_ => None,
|
||||
});
|
||||
let at = match first {
|
||||
Some((_, false)) => return,
|
||||
Some((n, true)) => n,
|
||||
None => raw.events.len(),
|
||||
};
|
||||
let (pos, modifiers) = ctx.input(|i| (i.pointer.interact_pos().unwrap_or_default(), i.modifiers));
|
||||
raw.events.insert(at, egui::Event::PointerButton { pos, button: egui::PointerButton::Primary, pressed: false, modifiers });
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -342,4 +350,43 @@ mod tests {
|
||||
super::release_after_desktop_grab(&ctx, &mut raw);
|
||||
assert_eq!(releases(&raw), 1, "not doubled when the input brings it");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_release_goes_before_the_press_of_the_next_grab() {
|
||||
let button = |pressed| egui::Event::PointerButton {
|
||||
pos: Pos2::new(5.0, 5.0),
|
||||
button: egui::PointerButton::Primary,
|
||||
pressed,
|
||||
modifiers: egui::Modifiers::NONE,
|
||||
};
|
||||
let primary = |raw: &egui::RawInput| {
|
||||
raw.events
|
||||
.iter()
|
||||
.filter_map(|e| if let egui::Event::PointerButton { pressed, .. } = e { Some(*pressed) } else { None })
|
||||
.collect::<Vec<_>>()
|
||||
};
|
||||
let ctx = egui::Context::default();
|
||||
let frame = |events: Vec<egui::Event>, grab: Option<egui::ViewportCommand>| {
|
||||
let mut raw = egui::RawInput { events, ..Default::default() };
|
||||
super::release_after_desktop_grab(&ctx, &mut raw);
|
||||
let order = primary(&raw);
|
||||
ctx.run_ui(raw, |ui| {
|
||||
if let Some(command) = grab.clone() {
|
||||
super::desktop_grab(ui.ctx(), command);
|
||||
}
|
||||
})
|
||||
.textures_delta
|
||||
.clear();
|
||||
order
|
||||
};
|
||||
// The press of the first resize starts the grab; the desktop keeps its release.
|
||||
frame(vec![egui::Event::PointerMoved(Pos2::new(5.0, 5.0)), button(true)], Some(egui::ViewportCommand::BeginResize(ResizeDirection::East)));
|
||||
// The next input brings the press of the second resize.
|
||||
assert_eq!(frame(vec![button(true)], None), [false, true], "the kept release, then the new press");
|
||||
assert!(ctx.input(|i| i.pointer.primary_down()), "the second resize holds the button");
|
||||
|
||||
// A quick click's release belongs to its own press, not to the grab before it.
|
||||
frame(vec![], Some(egui::ViewportCommand::StartDrag));
|
||||
assert_eq!(frame(vec![button(true), button(false)], None), [false, true, false]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user