From ed84e444287a8a932fee4a9f48e8b12af3a8b2ad Mon Sep 17 00:00:00 2001 From: Malte Langkabel Date: Wed, 5 Aug 2026 13:58:27 +0200 Subject: [PATCH] stop panning when the view loses focus Holding A or D while a modal opened - the escape menu, a schematic choice, game over - left the pan key held forever: the key-up went to the dialog and never reached the view, so the world panned on its own once the dialog closed. Panning runs on wall-clock time rather than ticks, so pausing did not mask it either. Focus loss now drops every held action. This is a behaviour change, not a move, so it is its own commit; it is only three lines because the input mapper already owns the held state and can clear all of it at once. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01JcReq7hVk4KUPhTDKWAG7K --- src/ui/GameWorldView.cpp | 13 +++++++++++++ src/ui/GameWorldView.h | 4 ++++ 2 files changed, 17 insertions(+) diff --git a/src/ui/GameWorldView.cpp b/src/ui/GameWorldView.cpp index 6b56bce..595dba2 100644 --- a/src/ui/GameWorldView.cpp +++ b/src/ui/GameWorldView.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -2361,10 +2362,22 @@ void GameWorldView::keyReleaseEvent(QKeyEvent* event) } if (m_inputMapper.handleKeyRelease(event)) { return; } // Releasing Shift discards the copied building settings (REQ-BLD-COPY-CONFIG). + // Stays here rather than moving to the input mapper: Shift is the modifier of a + // mouse gesture, not a keyboard action of its own. if (event->key() == Qt::Key_Shift) { m_copiedConfig.reset(); } QOpenGLWidget::keyReleaseEvent(event); } +void GameWorldView::focusOutEvent(QFocusEvent* event) +{ + // Without this, holding A while a modal opens (the escape menu, a schematic + // choice, game over) leaves the pan key held: the key-up goes to the dialog, + // never here, and the view pans on its own once the dialog closes. Panning runs + // on wall-clock time, so pausing does not mask it either. + m_inputMapper.releaseAll(); + QOpenGLWidget::focusOutEvent(event); +} + void GameWorldView::mousePressEvent(QMouseEvent* event) { const WorldCoordinates coordinates = getCoordinates(); diff --git a/src/ui/GameWorldView.h b/src/ui/GameWorldView.h index 532add0..1aa8858 100644 --- a/src/ui/GameWorldView.h +++ b/src/ui/GameWorldView.h @@ -107,6 +107,10 @@ protected: void paintGL() override; void keyPressEvent(QKeyEvent* event) override; void keyReleaseEvent(QKeyEvent* event) override; + // Key-up never arrives for a key that was still held when focus moved away — + // to a modal dialog, another widget, or another window. Any held action would + // otherwise stay held forever, so focus loss drops all of them. + void focusOutEvent(QFocusEvent* event) override; void mousePressEvent(QMouseEvent* event) override; void mouseMoveEvent(QMouseEvent* event) override; void mouseReleaseEvent(QMouseEvent* event) override;