diff --git a/CMakeLists.txt b/CMakeLists.txt index ed040fc..8727485 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/Keys/JumpOutputKeyListener.h b/Keys/JumpOutputKeyListener.h new file mode 100644 index 0000000..86e8744 --- /dev/null +++ b/Keys/JumpOutputKeyListener.h @@ -0,0 +1,55 @@ +// +// Created by grimmauld on 09.03.24. +// + +#ifndef SWAYMUX_JUMPOUTPUTKEYLISTENER_H +#define SWAYMUX_JUMPOUTPUTKEYLISTENER_H + +#include +#include +#include +#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 diff --git a/Keys/NextOutputKeyListener.h b/Keys/NextOutputKeyListener.h new file mode 100644 index 0000000..fb44bed --- /dev/null +++ b/Keys/NextOutputKeyListener.h @@ -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 diff --git a/Keys/PrevOutputKeyListener.h b/Keys/PrevOutputKeyListener.h new file mode 100644 index 0000000..24109ae --- /dev/null +++ b/Keys/PrevOutputKeyListener.h @@ -0,0 +1,38 @@ +// +// Created by grimmauld on 09.03.24. +// + +#ifndef SWAYMUX_PREVOUTPUTKEYLISTENER_H +#define SWAYMUX_PREVOUTPUTKEYLISTENER_H + +#include +#include +#include +#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 diff --git a/mainwindow.cpp b/mainwindow.cpp index 7fbb46d..766d325 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -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 #include @@ -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)); diff --git a/tree/SwayTreeModel.cpp b/tree/SwayTreeModel.cpp index 6adf585..731987f 100644 --- a/tree/SwayTreeModel.cpp +++ b/tree/SwayTreeModel.cpp @@ -4,13 +4,13 @@ #include "SwayTreeModel.h" -QModelIndex SwayTreeModel::findFocusedWindowIndex() const { +QModelIndex SwayTreeModel::findIndexByNode(const SwayTreeNode* node) const { std::vector 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 SwayTreeModel::getSelectedNodes(const QTreeView *treeView) const { std::set selectedNodes; + if (rootItem == nullptr) + return selectedNodes; + auto indexes = treeView->selectionModel()->selectedIndexes(); for (auto i: indexes) { - if (rootItem == nullptr) - return selectedNodes; - - std::vector 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 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; +} + + + diff --git a/tree/SwayTreeModel.h b/tree/SwayTreeModel.h index 3091f66..4abe021 100644 --- a/tree/SwayTreeModel.h +++ b/tree/SwayTreeModel.h @@ -43,10 +43,15 @@ public: }; - [[nodiscard]] QModelIndex findFocusedWindowIndex() const; + [[nodiscard]] inline QModelIndex findFocusedWindowIndex() const { + return findIndexByNode(getRoot()->findFocused()); + } [[nodiscard]] std::set getSelectedNodes(const QTreeView* treeView) const; + [[nodiscard]] SwayTreeNode * getSelectedNode(const QModelIndex &i) const; + + [[nodiscard]] QModelIndex findIndexByNode(const SwayTreeNode *node) const; private: SwayTreeNode * rootItem;