From d174307bce717ef2467ff1b2d32bf68b9f3a912b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20Br=C3=BCbach?= Date: Sat, 19 Sep 2026 07:23:56 +0200 Subject: [PATCH] [DeckShare] Keep arrow-key navigation between flow items inside a scroll area --- .../general/layout_containers/flow_widget.cpp | 31 ++++++++++++++++--- .../general/layout_containers/flow_widget.h | 7 ++++- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/cockatrice/src/interface/widgets/general/layout_containers/flow_widget.cpp b/cockatrice/src/interface/widgets/general/layout_containers/flow_widget.cpp index 6e04fed5a..05dcf3e8e 100644 --- a/cockatrice/src/interface/widgets/general/layout_containers/flow_widget.cpp +++ b/cockatrice/src/interface/widgets/general/layout_containers/flow_widget.cpp @@ -81,10 +81,15 @@ FlowWidget::FlowWidget(QWidget *parent, /** * @brief Adds a widget to the flow layout within the FlowWidget. * + * The widget is filtered for arrow-key events so keyboard navigation between + * the flow items keeps working even when the flow sits inside a QScrollArea, + * which swallows arrow keys before they can reach FlowWidget::keyPressEvent. + * * @param widget_to_add The widget to add to the flow layout. */ -void FlowWidget::addWidget(QWidget *widget_to_add) const +void FlowWidget::addWidget(QWidget *widget_to_add) { + widget_to_add->installEventFilter(this); flowLayout->addWidget(widget_to_add); } @@ -179,6 +184,23 @@ QLayoutItem *FlowWidget::itemAt(int index) const } void FlowWidget::keyPressEvent(QKeyEvent *event) +{ + if (moveFocus(event)) { + event->accept(); + return; + } + QWidget::keyPressEvent(event); +} + +bool FlowWidget::eventFilter(QObject *watched, QEvent *event) +{ + if (event->type() == QEvent::KeyPress && moveFocus(static_cast(event))) { + return true; + } + return QWidget::eventFilter(watched, event); +} + +bool FlowWidget::moveFocus(QKeyEvent *event) { // Keyboard navigation between the flow items: arrow keys move focus just // like clicking the sibling tiles would. Only items that can take keyboard @@ -186,8 +208,7 @@ void FlowWidget::keyPressEvent(QKeyEvent *event) const bool moveForward = event->key() == Qt::Key_Right || event->key() == Qt::Key_Down; const bool moveBackward = event->key() == Qt::Key_Left || event->key() == Qt::Key_Up; if (!moveForward && !moveBackward) { - QWidget::keyPressEvent(event); - return; + return false; } QList focusableItems; @@ -199,8 +220,7 @@ void FlowWidget::keyPressEvent(QKeyEvent *event) } if (focusableItems.isEmpty()) { - QWidget::keyPressEvent(event); - return; + return false; } int currentIndex = -1; @@ -220,6 +240,7 @@ void FlowWidget::keyPressEvent(QKeyEvent *event) } focusableItems.value(nextIndex)->setFocus(); event->accept(); + return true; } int FlowWidget::count() const diff --git a/cockatrice/src/interface/widgets/general/layout_containers/flow_widget.h b/cockatrice/src/interface/widgets/general/layout_containers/flow_widget.h index 3f3a2be2b..bdcb1e590 100644 --- a/cockatrice/src/interface/widgets/general/layout_containers/flow_widget.h +++ b/cockatrice/src/interface/widgets/general/layout_containers/flow_widget.h @@ -29,7 +29,7 @@ public: Qt::ScrollBarPolicy horizontalPolicy, Qt::ScrollBarPolicy verticalPolicy); - void addWidget(QWidget *widget_to_add) const; + void addWidget(QWidget *widget_to_add); void insertWidgetAtIndex(QWidget *toInsert, int index); void removeWidget(QWidget *widgetToRemove) const; void clearLayout(); @@ -44,10 +44,15 @@ public slots: void setSpacing(int hSpacing, int vSpacing); protected: + bool eventFilter(QObject *watched, QEvent *event) override; void resizeEvent(QResizeEvent *event) override; void keyPressEvent(QKeyEvent *event) override; private: + /// @brief Moves keyboard focus to an adjacent flow item for an arrow-key event. + /// @return True when the event was an arrow key and was handled. + bool moveFocus(QKeyEvent *event); + Qt::Orientation flowDirection; QHBoxLayout *mainLayout; FlowLayout *flowLayout;