Add easier keyboard navigation through outputs using page keys

This commit is contained in:
LordGrimmauld 2024-03-09 23:44:43 +01:00
parent 7dabcbb621
commit c725c4fdb6
7 changed files with 169 additions and 21 deletions

View File

@ -40,6 +40,9 @@ set(PROJECT_SOURCES
Keys/CloseSwaymuxKeyListener.h
sway_bindings/swayoutputs.h
Keys/SwitchToKeybindListener.h
Keys/JumpOutputKeyListener.h
Keys/PrevOutputKeyListener.h
Keys/NextOutputKeyListener.h
)
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)

View File

@ -0,0 +1,55 @@
//
// Created by grimmauld on 09.03.24.
//
#ifndef SWAYMUX_JUMPOUTPUTKEYLISTENER_H
#define SWAYMUX_JUMPOUTPUTKEYLISTENER_H
#include <QTreeView>
#include <iostream>
#include <QGuiApplication>
#include "AbstractKeyListener.h"
#include "../tree/SwayTreeModel.h"
#include "../sway_bindings/swayoutputs.h"
class JumpOutputKeyListener : public AbstractKeyListener {
public:
explicit JumpOutputKeyListener(SwayTreeModel *swayTreeModel, QTreeView *treeView) : swayTreeModel(
swayTreeModel), treeView(treeView) {};
void handleKeyEvent(const QKeyEvent *keyEvent) const override {
auto current = treeView->selectionModel()->currentIndex();
auto *selected = swayTreeModel->getSelectedNode(current);
if (selected == nullptr)
return;
auto *output = selected->findOutput();
if (output == nullptr) {
if (selected->node.type == NodeType::root)
output = selected->child(0);
else
return;
}
if (output->parentItem() == nullptr)
return;
auto *toFocus = output->parentItem()->child(output->row() + getOffset(selected));
if (toFocus == nullptr) // happens if index out of bounds
return;
auto focusIndex = swayTreeModel->findIndexByNode(toFocus);
auto modifiers = QGuiApplication::queryKeyboardModifiers();
treeView->selectionModel()->setCurrentIndex(focusIndex, modifiers.testFlag(Qt::ControlModifier)
? QItemSelectionModel::Current
: QItemSelectionModel::ClearAndSelect);
}
[[nodiscard]] inline virtual int getOffset(const SwayTreeNode* selected) const = 0;
private:
SwayTreeModel *swayTreeModel;
QTreeView *treeView;
};
#endif //SWAYMUX_JUMPOUTPUTKEYLISTENER_H

View File

@ -0,0 +1,32 @@
//
// Created by grimmauld on 09.03.24.
//
#ifndef SWAYMUX_NEXTOUTPUTKEYLISTENER_H
#define SWAYMUX_NEXTOUTPUTKEYLISTENER_H
class NextOutputKeyListener : public JumpOutputKeyListener {
public:
explicit NextOutputKeyListener(SwayTreeModel *swayTreeModel, QTreeView *treeView) : JumpOutputKeyListener(
swayTreeModel, treeView) {};
std::string getDescription() override {
return "Jump focus to output below";
}
std::string getKeyText() override {
return "Page Down";
}
[[nodiscard]] bool canAcceptKey(int key) const override {
return key == Qt::Key_PageDown;
}
int getOffset(const SwayTreeNode *selected) const override {
return 1;
}
};
#endif //SWAYMUX_NEXTOUTPUTKEYLISTENER_H

View File

@ -0,0 +1,38 @@
//
// Created by grimmauld on 09.03.24.
//
#ifndef SWAYMUX_PREVOUTPUTKEYLISTENER_H
#define SWAYMUX_PREVOUTPUTKEYLISTENER_H
#include <QTreeView>
#include <iostream>
#include <QGuiApplication>
#include "AbstractKeyListener.h"
#include "../tree/SwayTreeModel.h"
#include "../sway_bindings/swayoutputs.h"
#include "JumpOutputKeyListener.h"
class PrevOutputKeyListener : public JumpOutputKeyListener {
public:
explicit PrevOutputKeyListener(SwayTreeModel *swayTreeModel, QTreeView *treeView) : JumpOutputKeyListener(
swayTreeModel, treeView) {};
std::string getDescription() override {
return "Jump focus to output above";
}
std::string getKeyText() override {
return "Page Up";
}
[[nodiscard]] bool canAcceptKey(int key) const override {
return key == Qt::Key_PageUp;
}
int getOffset(const SwayTreeNode *selected) const override {
return selected != nullptr && selected->node.type != NodeType::output ? 0 : -1;
}
};
#endif //SWAYMUX_PREVOUTPUTKEYLISTENER_H

View File

@ -6,6 +6,9 @@
#include "Keys/CreateWorkspaceKeyListener.h"
#include "Keys/CloseSwaymuxKeyListener.h"
#include "Keys/SwitchToKeybindListener.h"
#include "Keys/PrevOutputKeyListener.h"
#include "Keys/NextOutputKeyListener.h"
#include "Keys/NextOutputKeyListener.h"
#include <QTimer>
#include <iostream>
@ -34,6 +37,8 @@ MainWindow::MainWindow(QWidget *parent)
swayTreeKeyHandler->addListener(new CloseSwaymuxKeyListener());
swayTreeKeyHandler->addListener(new CreateWorkspaceKeyListener(model, ui->treeView));
swayTreeKeyHandler->addListener(new SwitchToKeybindListener(model, ui->treeView));
swayTreeKeyHandler->addListener(new PrevOutputKeyListener(model, ui->treeView));
swayTreeKeyHandler->addListener(new NextOutputKeyListener(model, ui->treeView));
closeHelpKeyHandler = new KeyHandler(ui->tree_page);
closeHelpKeyHandler->addListener(new CloseHelpKeyListener(ui->tree_page));

View File

@ -4,13 +4,13 @@
#include "SwayTreeModel.h"
QModelIndex SwayTreeModel::findFocusedWindowIndex() const {
QModelIndex SwayTreeModel::findIndexByNode(const SwayTreeNode* node) const {
std::vector<int> indices;
for (const auto *head = getRoot()->findFocused(); head != nullptr; head = head->parentItem()) {
for (const auto *head = node; head != nullptr; head = head->parentItem()) {
indices.insert(indices.cbegin(), head->row());
}
// weirdness, idk... ask QT
// weirdness, idk ask QT
QModelIndex idx = this->index(indices.size() < 2 ? 0 : indices[1], 0);
for (int i = 2; i < indices.size(); ++i) {
idx = this->index(indices[i], 0, idx);
@ -21,26 +21,36 @@ QModelIndex SwayTreeModel::findFocusedWindowIndex() const {
std::set<SwayTreeNode *> SwayTreeModel::getSelectedNodes(const QTreeView *treeView) const {
std::set<SwayTreeNode *> selectedNodes;
if (rootItem == nullptr)
return selectedNodes;
auto indexes = treeView->selectionModel()->selectedIndexes();
for (auto i: indexes) {
if (rootItem == nullptr)
return selectedNodes;
std::vector<int> indices;
for (auto j = i; j.isValid(); j = j.parent()) {
indices.insert(indices.cbegin(), j.row());
}
auto *head = rootItem;
for (auto j: indices) {
head = head->child(j);
if (head == nullptr)
goto hell;
}
selectedNodes.insert(head);
hell:;
auto node = getSelectedNode(i);
if (node != nullptr)
selectedNodes.insert(node);
}
return selectedNodes;
}
SwayTreeNode *SwayTreeModel::getSelectedNode(const QModelIndex &i) const {
if (rootItem == nullptr)
return nullptr;
std::vector<int> indices;
for (auto j = i; j.isValid(); j = j.parent()) {
indices.insert(indices.cbegin(), j.row());
}
auto *head = rootItem;
for (auto j: indices) {
head = head->child(j);
if (head == nullptr)
return nullptr;
}
return head;
}

View File

@ -43,10 +43,15 @@ public:
};
[[nodiscard]] QModelIndex findFocusedWindowIndex() const;
[[nodiscard]] inline QModelIndex findFocusedWindowIndex() const {
return findIndexByNode(getRoot()->findFocused());
}
[[nodiscard]] std::set<SwayTreeNode*> getSelectedNodes(const QTreeView* treeView) const;
[[nodiscard]] SwayTreeNode * getSelectedNode(const QModelIndex &i) const;
[[nodiscard]] QModelIndex findIndexByNode(const SwayTreeNode *node) const;
private:
SwayTreeNode * rootItem;