Let Escape step back out of the folio, so Tab cannot trap keyboard users

Tab cycles the folio's items, which means focusNextPrevChild() has to
refuse the usual focus traversal. On its own that leaves someone working
without a mouse able to reach the drawing area and never leave it -- the
exact person the Tab cycling was added for.

Escape now steps back out in two stages: it drops the selection first,
then hands focus to the next widget. The one-shot m_releasing_focus flag
is what lets that second Escape through the override.

Verified under Xvfb: with an item selected, Escape clears it (193k pixels
change); a second Escape changes nothing visually; a Tab after that moves
widget focus in the toolbar (306 pixels) instead of selecting on the
canvas, which is the behaviour of a view that no longer holds focus.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
ispyisail
2026-09-15 11:32:42 +12:00
parent 22469813fe
commit d9db6e59e7
2 changed files with 20 additions and 1 deletions
+18 -1
View File
@@ -715,7 +715,11 @@ void DiagramView::focusInEvent(QFocusEvent *e) {
*/
bool DiagramView::focusNextPrevChild(bool next)
{
Q_UNUSED(next)
//Escape asked for focus to leave; allow exactly this one traversal.
if (m_releasing_focus) {
m_releasing_focus = false;
return QGraphicsView::focusNextPrevChild(next);
}
return false;
}
@@ -734,6 +738,19 @@ void DiagramView::keyPressEvent(QKeyEvent *e)
DiagramContent dc(m_diagram);
switch(e -> key())
{
case Qt::Key_Escape:
//Tab cycles the folio's items rather than moving focus (see
//focusNextPrevChild above), so without this there would be no
//way off the canvas for someone working without a mouse.
//Escape steps back out: first it drops the selection, then it
//hands focus to the next widget.
if (m_diagram && !m_diagram->selectedItems().isEmpty()) {
m_diagram->clearSelection();
} else {
m_releasing_focus = true;
focusNextChild();
}
return;
case Qt::Key_PageUp:
current_project->changeTabUp();
return;
+2
View File
@@ -81,6 +81,8 @@ class DiagramView : public QGraphicsView
void keyReleaseEvent(QKeyEvent *) override;
bool event(QEvent *) override;
bool focusNextPrevChild(bool next) override;
///Set for one call only, by the Escape handler, to let focus leave the view.
bool m_releasing_focus = false;
void paintEvent(QPaintEvent *event) override;
void mousePressEvent(QMouseEvent *) override;
void mouseMoveEvent(QMouseEvent *) override;