improve keyboard navigation of game list in three ways:

1) Return key on mac now successfully launches a game
2) up and down arrow keys now move focus out of search field and into game list
3) whenever focus goes into game list it ensures a game is selected
This commit is contained in:
David Griswold 2026-04-02 15:39:04 +03:00
parent 2011f71c54
commit f516e298cc
3 changed files with 48 additions and 3 deletions

View File

@ -2,6 +2,7 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <iostream>
#include <QActionGroup>
#include <QApplication>
#include <QDir>
@ -44,6 +45,36 @@
#include "core/hle/service/fs/archive.h"
#include "qcursor.h"
// On Mac OS X, the Return key does not trigger the activation signal for some reason. Fix it.
void GameListTreeView::keyPressEvent(QKeyEvent* event) {
if (event->key() == Qt::Key_Return) {
const QModelIndex idx = currentIndex();
if (idx.isValid()) {
emit activated(idx);
return;
}
}
QTreeView::keyPressEvent(event);
}
// if focus goes into the game list and nothing is already selected, select the first actual game
void GameListTreeView::focusInEvent(QFocusEvent* event) {
if (!currentIndex().isValid()) {
for (int i = 0; i < model()->rowCount(); i++) {
const QModelIndex folder = model()->index(i, 0);
if (model()->rowCount(folder) > 0) {
const QModelIndex first = model()->index(0, 0, folder);
setCurrentIndex(first);
selectionModel()->select(first,
QItemSelectionModel::Select | QItemSelectionModel::Rows);
break;
}
}
}
QTreeView::focusInEvent(event);
}
GameListSearchField::KeyReleaseEater::KeyReleaseEater(GameList* gamelist, QObject* parent)
: QObject(parent), gamelist{gamelist} {}
@ -88,6 +119,13 @@ bool GameListSearchField::KeyReleaseEater::eventFilter(QObject* obj, QEvent* eve
}
break;
}
// up, down, tab
// If the up arrow, down arrow, or tab key is pressed, this should move focus to the
// treeview
case Qt::Key_Up:
case Qt::Key_Down: {
gamelist->tree_view->setFocus();
}
default:
return QObject::eventFilter(obj, event);
}
@ -355,7 +393,7 @@ GameList::GameList(PlayTime::PlayTimeManager& play_time_manager_, GMainWindow* p
this->main_window = parent;
layout = new QVBoxLayout;
tree_view = new QTreeView;
tree_view = new GameListTreeView;
search_field = new GameListSearchField(this);
item_model = new QStandardItemModel(tree_view);
tree_view->setModel(item_model);
@ -371,7 +409,6 @@ GameList::GameList(PlayTime::PlayTimeManager& play_time_manager_, GMainWindow* p
tree_view->setStyleSheet(QStringLiteral("QTreeView{ border: none; }"));
tree_view->setItemDelegateForColumn(0, new CartridgeIconDelegate(tree_view));
tree_view->header()->setContextMenuPolicy(Qt::CustomContextMenu);
UpdateColumnVisibility();
item_model->insertColumns(0, COLUMN_COUNT);

View File

@ -21,6 +21,7 @@ enum class MediaType : u32;
class GameListWorker;
class GameListDir;
class GameListSearchField;
class GameListTreeView;
class GMainWindow;
class QFileSystemWatcher;
class QHBoxLayout;
@ -140,7 +141,7 @@ private:
GameListSearchField* search_field;
GMainWindow* main_window = nullptr;
QVBoxLayout* layout = nullptr;
QTreeView* tree_view = nullptr;
GameListTreeView* tree_view = nullptr;
QStandardItemModel* item_model = nullptr;
GameListWorker* current_worker = nullptr;
QFileSystemWatcher* watcher = nullptr;

View File

@ -16,6 +16,7 @@
#include <QRunnable>
#include <QStandardItem>
#include <QString>
#include <QTreeView>
#include <QWidget>
#include "citra_qt/uisettings.h"
#include "citra_qt/util/util.h"
@ -529,3 +530,9 @@ private:
QLabel* label_filter_result = nullptr;
QToolButton* button_filter_close = nullptr;
};
class GameListTreeView : public QTreeView {
protected:
void keyPressEvent(QKeyEvent* event) override;
void focusInEvent(QFocusEvent* event) override;
};