Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| dca411a3dd | |||
| 9c821d3e7b | |||
| 468daecbe9 | |||
| 982336be7c | |||
| 44bcbda690 |
@@ -1,5 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.10.0)
|
||||
project(hyprland-toggle-tiling VERSION 0.1.0 LANGUAGES C CXX)
|
||||
project(hyprland-toggle-tiling VERSION 1.4.0 LANGUAGES C CXX)
|
||||
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(json URL https://github.com/nlohmann/json/releases/download/v3.12.0/json.tar.xz)
|
||||
|
||||
16
README.md
16
README.md
@@ -29,6 +29,7 @@ Check out [the demo](https://typofelho.ddns.net/TypoMustakes/hyprland-toggle-til
|
||||
Let's say you switched to tiling mode. From that point on, new windows will open in tiling mode as well.
|
||||
Switch to floating mode again and newly opened windows will be in floating mode.
|
||||
- Floating/tiling window rules are isolated between workspaces. You can set one workspace to be floating, and all the rest to tiling for example.
|
||||
- Returns applied rule for the current workspace. Useful for scripting.
|
||||
- Useful for workflows that require both tiling and floating window management.
|
||||
- Lightweight and easy to integrate with your Hyprland setup.
|
||||
|
||||
@@ -42,7 +43,7 @@ You may install this program [from the AUR.](https://aur.archlinux.org/packages/
|
||||
|
||||
### Download the release
|
||||
|
||||
You can also [download the release binary.](https://typofelho.ddns.net/TypoMustakes/hyprland-toggle-tiling/releases/tag/1.1.0)
|
||||
You can also [download the release binary.](https://typofelho.ddns.net/TypoMustakes/hyprland-toggle-tiling/releases)
|
||||
|
||||
or go nuts and...
|
||||
|
||||
@@ -75,8 +76,19 @@ or go nuts and...
|
||||
|
||||
# Usage
|
||||
```shell
|
||||
./htt <config-file-path>
|
||||
./htt <config-file-path> (-q)
|
||||
```
|
||||
- `-q`: Print the rule applied on the current workspace to STDOUT, but don't change anything. If there isn't an active rule for the current workspace, it returns a tiling rule. The returned string is a valid Hyprland window rule configuration line, like so:
|
||||
|
||||
```shell
|
||||
# (On workspace 2...)
|
||||
$ ./htt ~/.cache/htt/rules -q
|
||||
|
||||
windowrule = tile on, match:workspace 2
|
||||
```
|
||||
Potential applications for this are mainly scripts, like my waybar module here:
|
||||

|
||||
|
||||
- If the specified configuration file does not exist, it will be created.
|
||||
- If the configuration contains existing rules, this should still work, but your existing configuration will probably get a bit messy, syntax-wise. I advise against it.
|
||||
|
||||
|
||||
BIN
assets/waybar_module.gif
Normal file
BIN
assets/waybar_module.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.5 MiB |
@@ -9,19 +9,29 @@
|
||||
class HyprlandService {
|
||||
private:
|
||||
static std::string configFilePath;
|
||||
public:
|
||||
static void setConfigFilePath(std::string);
|
||||
static std::string getConfigFilePath();
|
||||
|
||||
static std::list<Workspace> getWorkspaces();
|
||||
static std::optional<Workspace> getWorkspace(int);
|
||||
static Workspace getCurrentWorkspace();
|
||||
|
||||
static std::list<Client> getClients();
|
||||
static std::list<Client> getClientsOnActiveWorkspace();
|
||||
static Client getActiveClient();
|
||||
|
||||
static bool isFloatingRulePresent(int);
|
||||
static bool isFloatingRulePresent(Workspace);
|
||||
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&);
|
||||
static bool isFloatingRulePresent();
|
||||
|
||||
static void setClientFloating(Client);
|
||||
static void setClientTiled(Client);
|
||||
public:
|
||||
static void toggleFloating();
|
||||
static void moveToWorkspace(int);
|
||||
static void setConfigFilePath(std::string);
|
||||
static WindowRule getActiveWorkspaceRule();
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include "../include/HyprlandService.h"
|
||||
#include "../include/ShellService.h"
|
||||
#include "../include/Macros.h"
|
||||
@@ -22,11 +24,35 @@ std::string HyprlandService::getConfigFilePath() {
|
||||
return configFilePath;
|
||||
};
|
||||
|
||||
std::list<Workspace> HyprlandService::getWorkspaces() {
|
||||
json j = json::parse(ShellService::exec(HYPRCTL_BINARY " workspaces -j"));
|
||||
return j.get<std::list<Workspace>>();
|
||||
}
|
||||
|
||||
std::optional<Workspace> HyprlandService::getWorkspace(int id) {
|
||||
std::list<Workspace> workspaces = getWorkspaces();
|
||||
|
||||
for (auto it = workspaces.begin(); it != workspaces.end(); ) {
|
||||
if (it->id == id) {
|
||||
return *it;
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
Workspace HyprlandService::getCurrentWorkspace() {
|
||||
json j = json::parse(ShellService::exec(HYPRCTL_BINARY " activeworkspace -j"));
|
||||
return j.get<Workspace>();
|
||||
};
|
||||
|
||||
Client HyprlandService::getActiveClient() {
|
||||
json j = json::parse(ShellService::exec(HYPRCTL_BINARY " activewindow -j"));
|
||||
return j.get<Client>();
|
||||
}
|
||||
|
||||
std::list<Client> HyprlandService::getClients() {
|
||||
json j = json::parse(ShellService::exec(HYPRCTL_BINARY " clients -j"));
|
||||
return j.get<std::list<Client>>();
|
||||
@@ -57,18 +83,14 @@ std::list<WindowRule> HyprlandService::getWindowRules() {
|
||||
return rules;
|
||||
};
|
||||
|
||||
void HyprlandService::setClientFloating(Client& c) {
|
||||
void HyprlandService::setClientFloating(Client c) {
|
||||
ShellService::exec(HYPRCTL_BINARY " dispatch setfloating address:" + c.address);
|
||||
};
|
||||
|
||||
void HyprlandService::setClientTiled(Client& c) {
|
||||
void HyprlandService::setClientTiled(Client c) {
|
||||
ShellService::exec(HYPRCTL_BINARY " dispatch settiled address:" + c.address);
|
||||
}
|
||||
|
||||
void HyprlandService::toggleClientFloating(Client& c) {
|
||||
ShellService::exec(HYPRCTL_BINARY " dispatch togglefloating address:" + c.address);
|
||||
};
|
||||
|
||||
//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) {
|
||||
@@ -122,16 +144,56 @@ void HyprlandService::removeRule(WindowRule rule) {
|
||||
//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
|
||||
bool HyprlandService::isFloatingRulePresent(int workspaceId) {
|
||||
std::list<WindowRule> rules = getWindowRules();
|
||||
int id = getCurrentWorkspace().id;
|
||||
|
||||
for (auto& rule : rules) {
|
||||
if (rule.workspaceID == id && rule.tile == false) {
|
||||
if (rule.workspaceID == workspaceId && rule.tile == false) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
bool HyprlandService::isFloatingRulePresent(Workspace workspace) {
|
||||
return isFloatingRulePresent(workspace.id);
|
||||
};
|
||||
|
||||
WindowRule HyprlandService::getActiveWorkspaceRule() {
|
||||
std::list<WindowRule> rules = getWindowRules();
|
||||
int id = getCurrentWorkspace().id;
|
||||
|
||||
for (auto& rule : rules) {
|
||||
if (rule.workspaceID == id) {
|
||||
return rule;
|
||||
}
|
||||
}
|
||||
|
||||
//If no rule is found, return a default rule (tiled)
|
||||
return WindowRule {.tile = true, .workspaceID = id};
|
||||
};
|
||||
|
||||
void HyprlandService::moveToWorkspace(int workspaceId) {
|
||||
if (isFloatingRulePresent(workspaceId)) {
|
||||
setClientFloating(getActiveClient());
|
||||
} else {
|
||||
setClientTiled(getActiveClient());
|
||||
}
|
||||
|
||||
ShellService::exec(HYPRCTL_BINARY " dispatch movetoworkspace " + std::to_string(workspaceId));
|
||||
}
|
||||
|
||||
void HyprlandService::toggleFloating() {
|
||||
if (isFloatingRulePresent(getCurrentWorkspace())) {
|
||||
for (auto& c : getClientsOnActiveWorkspace()) {
|
||||
setClientTiled(c);
|
||||
}
|
||||
setFloatingRule(false);
|
||||
} else {
|
||||
for (auto& c : getClientsOnActiveWorkspace()) {
|
||||
setClientFloating(c);
|
||||
}
|
||||
setFloatingRule(true);
|
||||
}
|
||||
}
|
||||
|
||||
44
src/main.cpp
44
src/main.cpp
@@ -1,23 +1,37 @@
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include "../include/HyprlandService.h"
|
||||
|
||||
int main(int argc, char** argv){
|
||||
if (argc < 2) {
|
||||
std::cerr << "Usage: " << argv[0] << " <config_file_path>\n";
|
||||
void help(char* execPath) {
|
||||
std::cerr << "Usage: " << execPath << " <config_file_path> (flags)\n\n";
|
||||
std::cerr << "Flags:\n\n";
|
||||
std::cerr << "-q:\t\tQuery current windowing mode, don't change anything.\n\t\tReturns Hyprland window rule active on current workspace.\n\t\tIf no rule is active, returns a default tiled rule.\n\n";
|
||||
std::cerr << "-m [integer]:\tMove currently active window to specified workspace.\n\t\tUpon moving, the window will adapt to the windowing mode of the new workspace.\n\t\tDoesn't work with -q.\n";
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
HyprlandService::setConfigFilePath(argv[1]);
|
||||
int main(int argc, char** argv) {
|
||||
if (argc >= 2) {
|
||||
HyprlandService::setConfigFilePath(argv[1]);
|
||||
|
||||
if (HyprlandService::isFloatingRulePresent()) {
|
||||
for (auto& c : HyprlandService::getClientsOnActiveWorkspace()) {
|
||||
HyprlandService::setClientTiled(c);
|
||||
}
|
||||
HyprlandService::setFloatingRule(false);
|
||||
if (argc == 2) {
|
||||
HyprlandService::toggleFloating();
|
||||
}
|
||||
else if (argc == 3 && argv[2] == std::string("-q")) {
|
||||
std::cout << HyprlandService::getActiveWorkspaceRule().toString() << std::endl;
|
||||
} else if (argc == 4 && argv[2] == std::string("-m")) {
|
||||
int workspace = 0;
|
||||
try {
|
||||
HyprlandService::moveToWorkspace(std::stoi(argv[3]));
|
||||
} catch (std::invalid_argument) {
|
||||
help(argv[0]);
|
||||
}
|
||||
} else {
|
||||
help(argv[0]);
|
||||
}
|
||||
} else {
|
||||
for (auto& c : HyprlandService::getClientsOnActiveWorkspace()) {
|
||||
HyprlandService::setClientFloating(c);
|
||||
}
|
||||
HyprlandService::setFloatingRule(true);
|
||||
help(argv[0]);
|
||||
}
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user