Floating rules are now isolated between workspaces
This commit is contained in:
@@ -11,6 +11,7 @@ add_executable(htt
|
||||
src/Workspace.cpp
|
||||
src/ShellService.cpp
|
||||
src/FileService.cpp
|
||||
src/WindowRule.cpp
|
||||
src/Client.cpp)
|
||||
target_link_libraries(htt PRIVATE nlohmann_json::nlohmann_json)
|
||||
target_include_directories(htt PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
#ifndef FILE_SERVICES_H
|
||||
#define FILE_SERVICES_H
|
||||
#ifndef FILE_SERVICE_H
|
||||
#define FILE_SERVICE_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class FileServices {
|
||||
class FileService {
|
||||
public:
|
||||
static bool doesNonEmptyFileExist(std::string);
|
||||
static void emptyFile(std::string);
|
||||
static void createOrOverwriteFile(std::string, std::string);
|
||||
static void appendToFile(std::string, std::string);
|
||||
static void deleteNthLine(std::string, int);
|
||||
static std::vector<std::string> readLines(std::string);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -4,13 +4,17 @@
|
||||
#include <list>
|
||||
#include "Workspace.h"
|
||||
#include "Client.h"
|
||||
#include "WindowRule.h"
|
||||
|
||||
class HyprlandService {
|
||||
public:
|
||||
static Workspace getCurrentWorkspace();
|
||||
static std::list<Client> getClients();
|
||||
static std::list<Client> getClientsOnActiveWorkspace();
|
||||
static std::list<WindowRule> getWindowRules();
|
||||
static std::optional<WindowRule> findConflictingRule(WindowRule);
|
||||
static void setFloatingRule(bool);
|
||||
static void removeRule(WindowRule);
|
||||
static void setClientFloating(Client&);
|
||||
static void setClientTiled(Client&);
|
||||
static void toggleClientFloating(Client&);
|
||||
|
||||
@@ -9,6 +9,6 @@
|
||||
#define ECHO_PATH "/usr/bin/echo"
|
||||
#define CAT_PATH "/usr/bin/cat"
|
||||
|
||||
#define FLOATING_RULE "windowrule = float,class:.*"
|
||||
#define FLOATING_RULE "windowrule = float, onworkspace:"
|
||||
|
||||
#endif
|
||||
20
include/WindowRule.h
Normal file
20
include/WindowRule.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef WINDOW_RULE_H
|
||||
#define WINDOW_RULE_H
|
||||
|
||||
#include <string>
|
||||
|
||||
class WindowRule {
|
||||
public:
|
||||
//true -> tiling mode
|
||||
//false -> floating mode
|
||||
bool tile;
|
||||
|
||||
//Which workspace to apply to
|
||||
int workspaceID;
|
||||
|
||||
std::string toString();
|
||||
|
||||
static WindowRule parse(std::string);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -4,19 +4,55 @@
|
||||
#include "../include/Macros.h"
|
||||
#include "../include/ShellService.h"
|
||||
|
||||
bool FileServices::doesNonEmptyFileExist(std::string path) {
|
||||
bool FileService::doesNonEmptyFileExist(std::string path) {
|
||||
std::ifstream file(path);
|
||||
return file.good() && file.peek() != std::ifstream::traits_type::eof();
|
||||
};
|
||||
|
||||
void FileServices::emptyFile(std::string path) {
|
||||
void FileService::emptyFile(std::string path) {
|
||||
std::stringstream cmd;
|
||||
cmd << CAT_PATH << " " << NULL_PATH << " > " << path;
|
||||
ShellService::exec(cmd.str().c_str());
|
||||
};
|
||||
|
||||
void FileServices::createOrOverwriteFile(std::string path, std::string content) {
|
||||
void FileService::createOrOverwriteFile(std::string path, std::string content) {
|
||||
std::stringstream cmd;
|
||||
cmd << ECHO_PATH << " " << content << " > " << path;
|
||||
ShellService::exec(cmd.str().c_str());
|
||||
};
|
||||
|
||||
void FileService::appendToFile(std::string path, std::string content) {
|
||||
std::stringstream cmd;
|
||||
cmd << ECHO_PATH << " \"" << "\n" << content << "\" >> " << path;
|
||||
ShellService::exec(cmd.str().c_str());
|
||||
};
|
||||
|
||||
void FileService::deleteNthLine(std::string path, int n) {
|
||||
std::vector<std::string> lines = readLines(path);
|
||||
|
||||
if (n < 0 || n >= static_cast<int>(lines.size())) {
|
||||
// Out of bounds, do nothing
|
||||
return;
|
||||
}
|
||||
|
||||
lines.erase(lines.begin() + n);
|
||||
|
||||
std::ofstream file(path, std::ios::trunc);
|
||||
for (size_t i = 0; i < lines.size(); ++i) {
|
||||
file << lines[i];
|
||||
if (i != lines.size() - 1) {
|
||||
file << '\n';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> FileService::readLines(std::string path) {
|
||||
std::vector<std::string> lines;
|
||||
std::ifstream file(path);
|
||||
std::string line;
|
||||
|
||||
while (std::getline(file, line)) {
|
||||
lines.push_back(line);
|
||||
}
|
||||
return lines;
|
||||
};
|
||||
@@ -17,8 +17,8 @@ std::list<Client> HyprlandService::getClients() {
|
||||
};
|
||||
|
||||
std::list<Client> HyprlandService::getClientsOnActiveWorkspace() {
|
||||
std::list<Client> clients = HyprlandService::getClients();
|
||||
int activeWorkspaceID = HyprlandService::getCurrentWorkspace().id;
|
||||
std::list<Client> clients = getClients();
|
||||
int activeWorkspaceID = getCurrentWorkspace().id;
|
||||
|
||||
for (auto it = clients.begin(); it != clients.end(); ) {
|
||||
if (it->workspace.id != activeWorkspaceID) {
|
||||
@@ -31,6 +31,16 @@ std::list<Client> HyprlandService::getClientsOnActiveWorkspace() {
|
||||
return clients;
|
||||
};
|
||||
|
||||
std::list<WindowRule> HyprlandService::getWindowRules() {
|
||||
std::list<WindowRule> rules;
|
||||
|
||||
for (auto& line : FileService::readLines(ShellService::getHomePath()+FLOATING_RULE_CONF_FILE)) {
|
||||
rules.push_back(WindowRule::parse(line));
|
||||
}
|
||||
|
||||
return rules;
|
||||
};
|
||||
|
||||
void HyprlandService::setClientFloating(Client& c) {
|
||||
ShellService::exec(HYPRCTL_BINARY " dispatch setfloating address:" + c.address);
|
||||
};
|
||||
@@ -43,15 +53,69 @@ void HyprlandService::toggleClientFloating(Client& c) {
|
||||
ShellService::exec(HYPRCTL_BINARY " dispatch togglefloating address:" + c.address);
|
||||
};
|
||||
|
||||
void HyprlandService::setFloatingRule(bool b) {
|
||||
if (b) {
|
||||
FileServices::createOrOverwriteFile(ShellService::getHomePath()+FLOATING_RULE_CONF_FILE, FLOATING_RULE);
|
||||
}
|
||||
else {
|
||||
FileServices::emptyFile(ShellService::getHomePath()+FLOATING_RULE_CONF_FILE);
|
||||
//on = true -> creates a window rule to ENABLE floating mode for currently active workspace
|
||||
//on = false -> creates a window rule to DISABLE floating mode for currently active workspace
|
||||
void HyprlandService::setFloatingRule(bool on) {
|
||||
WindowRule rule {.tile = !on, .workspaceID = getCurrentWorkspace().id};
|
||||
auto conflictingRule = findConflictingRule(rule);
|
||||
if (conflictingRule.has_value()) {
|
||||
removeRule(conflictingRule.value());
|
||||
}
|
||||
|
||||
FileService::appendToFile(
|
||||
ShellService::getHomePath() + FLOATING_RULE_CONF_FILE,
|
||||
rule.toString()
|
||||
);
|
||||
};
|
||||
|
||||
bool HyprlandService::isFloatingRulePresent() {
|
||||
return FileServices::doesNonEmptyFileExist(ShellService::getHomePath()+FLOATING_RULE_CONF_FILE);
|
||||
std::optional<WindowRule> HyprlandService::findConflictingRule(WindowRule subject) {
|
||||
std::list<WindowRule> rules = getWindowRules();
|
||||
int id = getCurrentWorkspace().id;
|
||||
|
||||
for (auto& rule : rules) {
|
||||
if (rule.tile == !subject.tile && rule.workspaceID == subject.workspaceID)
|
||||
{
|
||||
return rule;
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
};
|
||||
|
||||
void HyprlandService::removeRule(WindowRule rule) {
|
||||
std::list<WindowRule> rules = getWindowRules();
|
||||
int index = 0;
|
||||
int foundIndex = -1;
|
||||
|
||||
for (auto& it : rules) {
|
||||
if (it.toString() == rule.toString())
|
||||
{
|
||||
foundIndex = index;
|
||||
break;
|
||||
}
|
||||
++index;
|
||||
}
|
||||
|
||||
if (foundIndex != -1) {
|
||||
FileService::deleteNthLine(
|
||||
ShellService::getHomePath() + FLOATING_RULE_CONF_FILE,
|
||||
foundIndex
|
||||
);
|
||||
}
|
||||
|
||||
//else: rule not found, do nothing
|
||||
}
|
||||
|
||||
bool HyprlandService::isFloatingRulePresent() {
|
||||
//Checks if there's a valid window rule in place that enables floating mode for the currently active workspace
|
||||
std::list<WindowRule> rules = getWindowRules();
|
||||
int id = getCurrentWorkspace().id;
|
||||
|
||||
for (auto& rule : rules) {
|
||||
if (rule.workspaceID == id && rule.tile == false) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
31
src/WindowRule.cpp
Normal file
31
src/WindowRule.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
#include <algorithm>
|
||||
#include "../include/WindowRule.h"
|
||||
|
||||
std::string WindowRule::toString() {
|
||||
std::string mode = this->tile ? "tile" : "float";
|
||||
|
||||
return "windowrule = " + mode + ", onworkspace:" + std::to_string(this->workspaceID);
|
||||
};
|
||||
|
||||
WindowRule WindowRule::parse(std::string ruleStr) {
|
||||
WindowRule rule;
|
||||
// Remove spaces for easier parsing
|
||||
ruleStr.erase(std::remove(ruleStr.begin(), ruleStr.end(), ' '), ruleStr.end());
|
||||
|
||||
// Find mode
|
||||
auto modePos = ruleStr.find("windowrule=");
|
||||
if (modePos != std::string::npos) {
|
||||
auto commaPos = ruleStr.find(',', modePos);
|
||||
std::string mode = ruleStr.substr(modePos + 11, commaPos - (modePos + 11));
|
||||
rule.tile = (mode == "tile");
|
||||
}
|
||||
|
||||
// Find workspace
|
||||
auto wsPos = ruleStr.find("onworkspace:");
|
||||
if (wsPos != std::string::npos) {
|
||||
std::string wsStr = ruleStr.substr(wsPos + 12);
|
||||
rule.workspaceID = std::stoi(wsStr);
|
||||
}
|
||||
|
||||
return rule;
|
||||
}
|
||||
Reference in New Issue
Block a user