enter workspaces (scratchpad listing is broken apparently....)
This commit is contained in:
parent
7a669fee4a
commit
25d48d79af
8 changed files with 145 additions and 17 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -75,4 +75,5 @@ cmake-build-debug
|
|||
# --------
|
||||
*.dll
|
||||
*.exe
|
||||
build
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ set(PROJECT_SOURCES
|
|||
Keys/CloseSwaymuxKeyListener.h
|
||||
Keys/CloseSwaymuxKeyListener.h
|
||||
sway_bindings/swayoutputs.h
|
||||
Keys/SwitchToKeybindListener.h
|
||||
)
|
||||
|
||||
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
|
||||
|
|
|
@ -36,7 +36,7 @@ public:
|
|||
int i = 1; // workspace 1 is the first one. We don't expect our users to be programmers.
|
||||
for (; used_workspaces.contains(std::to_string(i)); ++i) {}
|
||||
cmd << "workspace number " << i;
|
||||
auto resp = SwayTreeModel::sway.sendIPC(swaymsg(0, cmd.str().c_str(), cmd.str().length()));
|
||||
auto resp = SwayTreeModel::sway.sendIPC(swaymsg(0, cmd.str()));
|
||||
std::cout << resp.msg << "\n";
|
||||
QApplication::quit();
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ public:
|
|||
[[nodiscard]] bool canAcceptKey(int key) const override {
|
||||
return key == Qt::Key_C;
|
||||
}
|
||||
|
||||
private:
|
||||
SwayTreeModel *swayTreeModel;
|
||||
QTreeView *treeView;
|
||||
};
|
||||
|
|
101
Keys/SwitchToKeybindListener.h
Normal file
101
Keys/SwitchToKeybindListener.h
Normal file
|
@ -0,0 +1,101 @@
|
|||
//
|
||||
// Created by grimmauld on 08.03.24.
|
||||
//
|
||||
|
||||
#ifndef SWAYMUX_SWITCHTOKEYBINDLISTENER_H
|
||||
#define SWAYMUX_SWITCHTOKEYBINDLISTENER_H
|
||||
|
||||
#include <QTreeView>
|
||||
#include <iostream>
|
||||
#include "AbstractKeyListener.h"
|
||||
#include "../tree/SwayTreeModel.h"
|
||||
#include "../sway_bindings/swayoutputs.h"
|
||||
|
||||
class SwitchToKeybindListener : public AbstractKeyListener {
|
||||
public:
|
||||
explicit SwitchToKeybindListener(SwayTreeModel *swayTreeModel, QTreeView *treeView) : swayTreeModel(
|
||||
swayTreeModel), treeView(treeView) {}
|
||||
|
||||
void handleKeyEvent(const QKeyEvent *keyEvent) const override {
|
||||
auto *root = swayTreeModel->getRoot();
|
||||
if (root == nullptr)
|
||||
return;
|
||||
|
||||
Formatter cmd;
|
||||
auto selectedNodes = swayTreeModel->getSelectedNodes(treeView);
|
||||
if (selectedNodes.empty())
|
||||
return;
|
||||
|
||||
auto availableOutputs = SwayOutputList(SwayTreeModel::sway);
|
||||
if (selectedNodes.size() == 1) {
|
||||
auto *selected = *selectedNodes.begin();
|
||||
if (availableOutputs.isOutputValid(selected->findOutput())) {
|
||||
switch (selected->node.type) {
|
||||
case NodeType::output:
|
||||
cmd << "focus output " << selected->node.name;
|
||||
break;
|
||||
case NodeType::workspace:
|
||||
cmd << "workspace " << selected->node.name;
|
||||
break;
|
||||
case NodeType::con:
|
||||
case NodeType::floating_con:
|
||||
cmd << "[con_id=" << selected->node.id << "] focus";
|
||||
break;
|
||||
case NodeType::root:
|
||||
return; // this should never happen! isOutputValid should guard against this.
|
||||
}
|
||||
std::cout << cmd.str() << "\n";
|
||||
auto resp = SwayTreeModel::sway.sendIPC(swaymsg(0, cmd.str()));
|
||||
std::cout << resp.msg << "\n";
|
||||
QApplication::quit();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
auto used_workspaces = root->accumulateWorkspaces();
|
||||
int newWorkspace = 1; // workspace 1 is the first one. We don't expect our users to be programmers.
|
||||
for (; used_workspaces.contains(std::to_string(newWorkspace)); ++newWorkspace) {}
|
||||
|
||||
|
||||
std::set<int> containersToMove;
|
||||
for (auto* container: selectedNodes) {
|
||||
auto containers = container->accumulateContainers();
|
||||
for (auto* containerToMove : container->accumulateContainers()) {
|
||||
containersToMove.insert(containerToMove->node.id);
|
||||
}
|
||||
}
|
||||
|
||||
if (containersToMove.empty())
|
||||
return;
|
||||
|
||||
for (auto id: containersToMove) {
|
||||
cmd << "[con_id=" << id << "] focus , move container workspace " << newWorkspace << " ; ";
|
||||
}
|
||||
|
||||
cmd << "workspace number " << newWorkspace;
|
||||
|
||||
std::cout << cmd.str() << "\n";
|
||||
auto resp = SwayTreeModel::sway.sendIPC(swaymsg(0, cmd.str()));
|
||||
std::cout << resp.msg << "\n";
|
||||
QApplication::quit();
|
||||
}
|
||||
|
||||
std::string getDescription() override {
|
||||
return "Switch to selected container. If multiple containers or a container from scratchpad is selected,\ncreate new workspace and move all windows that are part of the selection to it.";
|
||||
}
|
||||
|
||||
std::string getKeyText() override {
|
||||
return "ENTER";
|
||||
}
|
||||
|
||||
[[nodiscard]] bool canAcceptKey(int key) const override {
|
||||
return key == Qt::Key_Enter || key == Qt::Key_Return;
|
||||
}
|
||||
|
||||
private:
|
||||
SwayTreeModel *swayTreeModel;
|
||||
QTreeView *treeView;
|
||||
};
|
||||
|
||||
|
||||
#endif //SWAYMUX_SWITCHTOKEYBINDLISTENER_H
|
|
@ -5,6 +5,7 @@
|
|||
#include "Keys/CloseHelpKeyListener.h"
|
||||
#include "Keys/CreateWorkspaceKeyListener.h"
|
||||
#include "Keys/CloseSwaymuxKeyListener.h"
|
||||
#include "Keys/SwitchToKeybindListener.h"
|
||||
#include <QTimer>
|
||||
#include <iostream>
|
||||
|
||||
|
@ -32,6 +33,7 @@ MainWindow::MainWindow(QWidget *parent)
|
|||
swayTreeKeyHandler->addListener(new HelpKeyListener(ui->help_page));
|
||||
swayTreeKeyHandler->addListener(new CloseSwaymuxKeyListener());
|
||||
swayTreeKeyHandler->addListener(new CreateWorkspaceKeyListener(model, ui->treeView));
|
||||
swayTreeKeyHandler->addListener(new SwitchToKeybindListener(model, ui->treeView));
|
||||
|
||||
closeHelpKeyHandler = new KeyHandler(ui->tree_page);
|
||||
closeHelpKeyHandler->addListener(new CloseHelpKeyListener(ui->tree_page));
|
||||
|
|
|
@ -15,6 +15,8 @@ struct swaymsg {
|
|||
explicit swaymsg(const unsigned int payloadType, const char *msg) : swaymsg(payloadType, msg,
|
||||
msg == nullptr ? 0 : strlen(msg)) {};
|
||||
|
||||
explicit swaymsg(const unsigned int payloadType, const std::string& msg) : swaymsg(payloadType, msg.c_str(), msg.length()) {};
|
||||
|
||||
explicit swaymsg(const unsigned int payloadType, const char *msg, const unsigned int payload_len)
|
||||
: payload_len(payload_len), payload_type(payloadType) {
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <map>
|
||||
#include <vector>
|
||||
#include <QVariant>
|
||||
#include <iostream>
|
||||
|
||||
template<class T>
|
||||
class AbstractTreeNode {
|
||||
|
@ -56,6 +57,21 @@ public:
|
|||
return nullptr;
|
||||
};
|
||||
|
||||
[[nodiscard]] std::set<T *> accumulateMatchingChildrenRecursive(std::function<bool(const T *)> test) const {
|
||||
std::set<T *> matching;
|
||||
if (test((const T *) this)) {
|
||||
matching.insert((T *) this);
|
||||
}
|
||||
|
||||
for (int i = 0; i < childCount(); ++i) {
|
||||
auto *c = child(i);
|
||||
for(T * element: c->accumulateMatchingChildrenRecursive(test)) {
|
||||
matching.insert(element);
|
||||
}
|
||||
}
|
||||
return matching;
|
||||
}
|
||||
|
||||
[[nodiscard]] const T *findChildRecursive(std::function<bool(const T *)> test) const {
|
||||
if (test((const T *) this))
|
||||
return (const T*) this;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <utility>
|
||||
#include <iostream>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
|
@ -96,7 +97,6 @@ struct SwayRecord {
|
|||
urgent(rep["urgent"]),
|
||||
sticky(rep["sticky"]),
|
||||
focused(rep["focused"]) {};
|
||||
|
||||
const int id;
|
||||
const std::string name;
|
||||
const NodeType::NodeType type;
|
||||
|
@ -170,24 +170,29 @@ public:
|
|||
return this->findParentRecursive(matchNodeType(NodeType::workspace));
|
||||
}
|
||||
|
||||
[[nodiscard]] std::set<std::string> accumulateWorkspaces() const {
|
||||
std::set<std::string> workspaces;
|
||||
if (node.type == NodeType::workspace) {
|
||||
workspaces.insert(node.name);
|
||||
return workspaces; // assumption: no workspaces within workspaces. This might be dangerous for the future, but is currently not a sway feature.
|
||||
}
|
||||
[[nodiscard]] inline std::set<SwayTreeNode *> accumulateContainers() const {
|
||||
return accumulateMatchingChildrenRecursive(matchNodeType({NodeType::con, NodeType::floating_con}));
|
||||
}
|
||||
|
||||
for (int i = 0; i < childCount(); ++i) {
|
||||
auto child_workspaces = child(i)->accumulateWorkspaces();
|
||||
workspaces.insert(child_workspaces.cbegin(), child_workspaces.cend());
|
||||
}
|
||||
return workspaces;
|
||||
[[nodiscard]] std::set<std::string> accumulateWorkspaces() const {
|
||||
auto workspaces = accumulateMatchingChildrenRecursive(matchNodeType(NodeType::workspace));
|
||||
std::set<std::string> result;
|
||||
std::transform(workspaces.begin(), workspaces.end(), std::inserter(result, result.begin()),
|
||||
[](const SwayTreeNode *workspace) { return workspace->node.name; });
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
[[nodiscard]] static std::function<bool(const SwayTreeNode *)> matchNodeType(const NodeType::NodeType type) {
|
||||
return [type](const SwayTreeNode *testNode) {
|
||||
return testNode->node.type == type;
|
||||
[[nodiscard]] static std::function<bool(const SwayTreeNode *)> matchNodeType(NodeType::NodeType type) {
|
||||
return matchNodeType(std::vector{type});
|
||||
}
|
||||
|
||||
[[nodiscard]] static std::function<bool(const SwayTreeNode *)>
|
||||
matchNodeType(const std::vector<NodeType::NodeType>& types) {
|
||||
return [types](const SwayTreeNode *testNode) {
|
||||
return std::ranges::any_of(types.begin(), types.end(), [testNode](const auto t) {
|
||||
return testNode->node.type == t;
|
||||
});
|
||||
};
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue