diff --git a/widgetry/src/event_ctx.rs b/widgetry/src/event_ctx.rs index c90f344d7d..703e074d49 100644 --- a/widgetry/src/event_ctx.rs +++ b/widgetry/src/event_ctx.rs @@ -34,6 +34,7 @@ pub struct EventCtx<'a> { pub prerender: &'a Prerender, pub(crate) style: &'a mut Style, pub(crate) updates_requested: Vec, + pub(crate) canvas_movement_called: bool, } impl<'a> EventCtx<'a> { @@ -63,6 +64,7 @@ impl<'a> EventCtx<'a> { /// auto-pan at the edge of the screen, using arrow keys, etc) depend on options set. Returns /// true if the canvas moved at all. pub fn canvas_movement(&mut self) -> bool { + self.canvas_movement_called = true; let prev = (self.canvas.cam_x, self.canvas.cam_y, self.canvas.cam_zoom); self.updates_requested .extend(self.canvas.handle_event(&mut self.input)); @@ -82,6 +84,7 @@ impl<'a> EventCtx<'a> { prerender: self.prerender, style: self.style, updates_requested: vec![], + canvas_movement_called: false, }; let result = cb(&mut tmp); self.updates_requested.extend(tmp.updates_requested); @@ -269,6 +272,7 @@ impl<'a> LoadingScreen<'a> { prerender: self.prerender, style: &mut self.style, updates_requested: vec![], + canvas_movement_called: false, }; let mut txt = Text::from(Line(&self.title).small_heading()); diff --git a/widgetry/src/runner.rs b/widgetry/src/runner.rs index 060d951714..81b2b24c7f 100644 --- a/widgetry/src/runner.rs +++ b/widgetry/src/runner.rs @@ -107,12 +107,28 @@ impl State { prerender, style: &mut self.style, updates_requested: vec![], + canvas_movement_called: false, }; let started = Instant::now(); self.app.event(&mut ctx); if DEBUG_PERFORMANCE { println!("- event() took {}s", elapsed_seconds(started)); } + + // If the user is dragging the canvas, but then another UI state interrupts things + // (like a panel popping up that blocks the canvas) and canvas_movement() isn't called + // for this event, then cancel the drag. + if ctx.canvas.drag_canvas_from.is_some() && !ctx.canvas_movement_called { + ctx.canvas.drag_canvas_from = None; + // TODO When the user releases the mouse button, it'll count as + // normal_left_click(). An example why this is a bug: + // + // 1) Start dragging the map in A/B Street's sandbox mode + // 2) Press escape, bringing up a menu + // 3) Release the mouse while hovering off of the panel + // This counts as clicking "off the panel" and closes it immediately. + } + // TODO We should always do has_been_consumed, but various hacks prevent this from being // true. For now, just avoid the specific annoying redraw case when a KeyRelease event // is unused. @@ -339,6 +355,7 @@ pub fn run< prerender: &prerender, style: &mut style, updates_requested: vec![], + canvas_movement_called: false, }); timer.stop("setup app"); let app = App {