Move to split-monitor-workspaces
This commit is contained in:
parent
dbd6bbd561
commit
fe1730ac4f
|
@ -1,52 +1,18 @@
|
||||||
env = WLR_DRM_DEVICES,/dev/dri/card0:/dev/dri/card1
|
|
||||||
env = WLR_NO_HARDWARE_CURSORS,1
|
env = WLR_NO_HARDWARE_CURSORS,1
|
||||||
env = TERMINAL,alacritty
|
env = TERMINAL,alacritty
|
||||||
|
|
||||||
$scripts = /home/user/.config/scripts
|
$scripts = /home/user/.config/scripts
|
||||||
|
$mainMod = SUPER
|
||||||
|
|
||||||
monitor=DP-2,preferred,0x550,1
|
monitor=DP-2,preferred,0x550,1
|
||||||
monitor=DP-3,preferred,1920x0,1
|
monitor=DP-3,preferred,1920x0,1
|
||||||
monitor=HDMI-A-1,preferred,5760x550,1
|
monitor=HDMI-A-1,preferred,5760x550,1
|
||||||
|
|
||||||
exec-once=hyprpaper
|
exec-once=hyprpaper
|
||||||
exec-once=wl-paste --type text --watch cliphist store
|
exec-once=wl-paste --type text --watch cliphist store
|
||||||
exec-once=wl-paste --type image --watch cliphist store
|
exec-once=wl-paste --type image --watch cliphist store
|
||||||
exec-once=/usr/lib/mate-polkit/polkit-mate-authentication-agent-1
|
exec-once=/usr/lib/mate-polkit/polkit-mate-authentication-agent-1
|
||||||
exec-once=/usr/lib/kdeconnectd
|
exec-once=/usr/lib/kdeconnectd
|
||||||
exec-once=sleep 2 && hyprctl dispatch workspace 21
|
exec-once=waybar
|
||||||
|
|
||||||
workspace=DP-2,11
|
|
||||||
workspace=DP-3,21
|
|
||||||
workspace=HDMI-A-1,1
|
|
||||||
|
|
||||||
workspace=21,monitor:HDMI-A-1, default:true
|
|
||||||
workspace=22,monitor:HDMI-A-1
|
|
||||||
workspace=23,monitor:HDMI-A-1
|
|
||||||
workspace=24,monitor:HDMI-A-1
|
|
||||||
workspace=25,monitor:HDMI-A-1
|
|
||||||
workspace=26,monitor:HDMI-A-1
|
|
||||||
workspace=27,monitor:HDMI-A-1
|
|
||||||
workspace=28,monitor:HDMI-A-1
|
|
||||||
workspace=29,monitor:HDMI-A-1
|
|
||||||
|
|
||||||
workspace=1,monitor:DP-2, default:true
|
|
||||||
workspace=2,monitor:DP-2
|
|
||||||
workspace=3,monitor:DP-2
|
|
||||||
workspace=4,monitor:DP-2
|
|
||||||
workspace=5,monitor:DP-2
|
|
||||||
workspace=6,monitor:DP-2
|
|
||||||
workspace=7,monitor:DP-2
|
|
||||||
workspace=8,monitor:DP-2
|
|
||||||
workspace=9,monitor:DP-2
|
|
||||||
|
|
||||||
workspace=11,monitor:DP-3, default:true
|
|
||||||
workspace=12,monitor:DP-3
|
|
||||||
workspace=13,monitor:DP-3
|
|
||||||
workspace=14,monitor:DP-3
|
|
||||||
workspace=15,monitor:DP-3
|
|
||||||
workspace=16,monitor:DP-3
|
|
||||||
workspace=17,monitor:DP-3
|
|
||||||
workspace=18,monitor:DP-3
|
|
||||||
workspace=19,monitor:DP-3
|
|
||||||
|
|
||||||
# windowrulev2 = tile, class:.*
|
# windowrulev2 = tile, class:.*
|
||||||
windowrulev2 = float, title:^(rofi)(.*)$
|
windowrulev2 = float, title:^(rofi)(.*)$
|
||||||
|
@ -57,8 +23,6 @@ windowrulev2 = minsize 1 1, title:^()$,class:^(steam)$
|
||||||
windowrulev2 = stayfocused, title:^()$,class:^(steam)$
|
windowrulev2 = stayfocused, title:^()$,class:^(steam)$
|
||||||
windowrule = noanim,waybar
|
windowrule = noanim,waybar
|
||||||
|
|
||||||
exec-once=waybar
|
|
||||||
|
|
||||||
binds {
|
binds {
|
||||||
scroll_event_delay=1
|
scroll_event_delay=1
|
||||||
}
|
}
|
||||||
|
@ -122,9 +86,7 @@ gestures {
|
||||||
workspace_swipe_invert = false
|
workspace_swipe_invert = false
|
||||||
}
|
}
|
||||||
|
|
||||||
$mainMod = SUPER
|
|
||||||
|
|
||||||
# Example binds, see https://wiki.hyprland.org/Configuring/Binds/ for more
|
|
||||||
bindr = $mainMod, SUPER_L, exec, pkill rofi || rofi -show drun
|
bindr = $mainMod, SUPER_L, exec, pkill rofi || rofi -show drun
|
||||||
bindr = $mainMod, SUPER_R, exec, pkill rofi || rofi -show drun
|
bindr = $mainMod, SUPER_R, exec, pkill rofi || rofi -show drun
|
||||||
bind = $mainMod, return, exec, $scripts/launch_alacritty.sh $(hyprctl activewindow -j | jq .pid)
|
bind = $mainMod, return, exec, $scripts/launch_alacritty.sh $(hyprctl activewindow -j | jq .pid)
|
||||||
|
@ -177,32 +139,32 @@ binde = $mainMod ALT, H, resizeactive, -20 0
|
||||||
binde = $mainMod ALT, K, resizeactive, 0 -20
|
binde = $mainMod ALT, K, resizeactive, 0 -20
|
||||||
binde = $mainMod ALT, J, resizeactive, 0 20
|
binde = $mainMod ALT, J, resizeactive, 0 20
|
||||||
|
|
||||||
bind = $mainMod, 1, exec, hyprsome workspace 1
|
bind = $mainMod, 1, split-workspace, 1
|
||||||
bind = $mainMod, 2, exec, hyprsome workspace 2
|
bind = $mainMod, 2, split-workspace, 2
|
||||||
bind = $mainMod, 3, exec, hyprsome workspace 3
|
bind = $mainMod, 3, split-workspace, 3
|
||||||
bind = $mainMod, 4, exec, hyprsome workspace 4
|
bind = $mainMod, 4, split-workspace, 4
|
||||||
bind = $mainMod, 5, exec, hyprsome workspace 5
|
bind = $mainMod, 5, split-workspace, 5
|
||||||
bind = $mainMod, 6, exec, hyprsome workspace 6
|
bind = $mainMod, 6, split-workspace, 6
|
||||||
bind = $mainMod, 7, exec, hyprsome workspace 7
|
bind = $mainMod, 7, split-workspace, 7
|
||||||
bind = $mainMod, 8, exec, hyprsome workspace 8
|
bind = $mainMod, 8, split-workspace, 8
|
||||||
bind = $mainMod, 9, exec, hyprsome workspace 9
|
bind = $mainMod, 9, split-workspace, 9
|
||||||
|
|
||||||
bind = $mainMod SHIFT, 1, exec, hyprsome movefocus 1
|
bind = $mainMod SHIFT, 1, split-movetoworkspace, 1
|
||||||
bind = $mainMod SHIFT, 2, exec, hyprsome movefocus 2
|
bind = $mainMod SHIFT, 2, split-movetoworkspace, 2
|
||||||
bind = $mainMod SHIFT, 3, exec, hyprsome movefocus 3
|
bind = $mainMod SHIFT, 3, split-movetoworkspace, 3
|
||||||
bind = $mainMod SHIFT, 4, exec, hyprsome movefocus 4
|
bind = $mainMod SHIFT, 4, split-movetoworkspace, 4
|
||||||
bind = $mainMod SHIFT, 5, exec, hyprsome movefocus 5
|
bind = $mainMod SHIFT, 5, split-movetoworkspace, 5
|
||||||
bind = $mainMod SHIFT, 6, exec, hyprsome movefocus 6
|
bind = $mainMod SHIFT, 6, split-movetoworkspace, 6
|
||||||
bind = $mainMod SHIFT, 7, exec, hyprsome movefocus 7
|
bind = $mainMod SHIFT, 7, split-movetoworkspace, 7
|
||||||
bind = $mainMod SHIFT, 8, exec, hyprsome movefocus 8
|
bind = $mainMod SHIFT, 8, split-movetoworkspace, 8
|
||||||
bind = $mainMod SHIFT, 9, exec, hyprsome movefocus 9
|
bind = $mainMod SHIFT, 9, split-movetoworkspace, 9
|
||||||
|
|
||||||
bind = $mainMod SHIFT, T, exec, hyprsome move-empty
|
bind = $mainMod SHIFT, T, split-movetoworkspace, empty
|
||||||
bind = $mainMod, T, exec, hyprsome focus-empty
|
bind = $mainMod, T, split-workspace, empty
|
||||||
|
|
||||||
# Scroll through existing workspaces with mainMod + scroll
|
# Scroll through existing workspaces with mainMod + scroll
|
||||||
bind = $mainMod, TAB, workspace, m+1
|
bind = $mainMod, TAB, split-workspace, m+1
|
||||||
bind = $mainMod SHIFT, TAB, workspace, m-1
|
bind = $mainMod SHIFT, TAB, split-workspace, m-1
|
||||||
|
|
||||||
# Move/resize windows with mainMod + LMB/RMB and dragging
|
# Move/resize windows with mainMod + LMB/RMB and dragging
|
||||||
bindm = $mainMod, mouse:272, movewindow
|
bindm = $mainMod, mouse:272, movewindow
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
/target
|
|
||||||
/result
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,17 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "hyprsome"
|
|
||||||
description = "A small CLI apps that allows to make Hyprland's workspaces work like Awesome in multi-monitor setup"
|
|
||||||
license = "GPL-3.0"
|
|
||||||
version = "0.1.11"
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
clap = { version = "4.0.15", features = ["derive"] }
|
|
||||||
ipc-rpc = "1.2.2"
|
|
||||||
schemars = "0.8.11"
|
|
||||||
serde = "1.0.145"
|
|
||||||
serde_json = "1.0.86"
|
|
||||||
tokio = "1.21.2"
|
|
||||||
hyprland = "0.3.1"
|
|
|
@ -1,16 +0,0 @@
|
||||||
The GPLv3 License (GPLv3)
|
|
||||||
|
|
||||||
Copyright (c) 2022 Author
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
@ -1,76 +0,0 @@
|
||||||
# Hyprsome
|
|
||||||
Hyprsome is a binary that interacts with Hyprland's Unix socket to make workspaces behave similarly to AwesomeWM in a multi-monitor setup.
|
|
||||||
|
|
||||||
If you're focused on a monitor and press SUPER+[1-9], you'll only switch to the workspaces that are bound to that monitor.
|
|
||||||
|
|
||||||
It is inspired by Swaysome, which does a similar thing for Sway.
|
|
||||||
|
|
||||||
# Installation
|
|
||||||
`
|
|
||||||
cargo install hyprsome
|
|
||||||
`
|
|
||||||
|
|
||||||
# Usage
|
|
||||||
Once the binary is installed, you can modify your ~/.config/hypr/hyprland.conf to accomodate it.
|
|
||||||
Here is an example of a dual monitor setup:
|
|
||||||
|
|
||||||
```
|
|
||||||
monitor=DP-1,1920x1080@60,0x0,1.33
|
|
||||||
monitor=DP-1,transform,1
|
|
||||||
workspace=DP-1,1
|
|
||||||
monitor=HDMI-A-1,3440x1440@100,813x0,1
|
|
||||||
workspace=HDMI-A-1,11
|
|
||||||
```
|
|
||||||
|
|
||||||
Most noteworthy thing here is the 'workspace' keyword that I use to bind a default workspace for each monitor.
|
|
||||||
|
|
||||||
|
|
||||||
Then you can bind workspaces to your different monitors.
|
|
||||||
|
|
||||||
It is very important that you bind your workspaces in order.
|
|
||||||
|
|
||||||
Check the results of `hyprctl monitors`. Bind workspaces from 1 to 9 on your monitor that has 0 as an id.
|
|
||||||
|
|
||||||
Then just bind workspaces by prefixing numbers by the id of the monitor they're bound to.
|
|
||||||
|
|
||||||
Here, HDMI-A-1's id is 1, so I bind workspaces from 11 to 19 to it.
|
|
||||||
|
|
||||||
```
|
|
||||||
workspace=1,monitor:DP-1
|
|
||||||
workspace=2,monitor:DP-1
|
|
||||||
workspace=3,monitor:DP-1
|
|
||||||
workspace=4,monitor:DP-1
|
|
||||||
workspace=5,monitor:DP-1
|
|
||||||
|
|
||||||
workspace=11,monitor:HDMI-A-1
|
|
||||||
workspace=12,monitor:HDMI-A-1
|
|
||||||
workspace=13,monitor:HDMI-A-1
|
|
||||||
workspace=14,monitor:HDMI-A-1
|
|
||||||
workspace=15,monitor:HDMI-A-1
|
|
||||||
```
|
|
||||||
|
|
||||||
Then it's just a matter of making sure your regular workspace keybinds call hyprsome.
|
|
||||||
|
|
||||||
```
|
|
||||||
bind=SUPER,1,exec,hyprsome workspace 1
|
|
||||||
bind=SUPER,2,exec,hyprsome workspace 2
|
|
||||||
bind=SUPER,3,exec,hyprsome workspace 3
|
|
||||||
bind=SUPER,4,exec,hyprsome workspace 4
|
|
||||||
bind=SUPER,5,exec,hyprsome workspace 5
|
|
||||||
|
|
||||||
bind=SUPERSHIFT,1,exec,hyprsome move 1
|
|
||||||
bind=SUPERSHIFT,2,exec,hyprsome move 2
|
|
||||||
bind=SUPERSHIFT,3,exec,hyprsome move 3
|
|
||||||
bind=SUPERSHIFT,4,exec,hyprsome move 4
|
|
||||||
bind=SUPERSHIFT,5,exec,hyprsome move 5
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
# Limitations
|
|
||||||
This is alpha software and my first program in Rust, bugs are bound to happen but nothing that will break your system.
|
|
||||||
|
|
||||||
Some features are most likely missing.
|
|
||||||
|
|
||||||
You can only have 9 workspaces per monitor as of now.
|
|
||||||
|
|
||||||
I haven't worked on supporting monitor hot-plug at all. It may work but it's unlikely.
|
|
|
@ -1,159 +0,0 @@
|
||||||
{
|
|
||||||
"nodes": {
|
|
||||||
"crane": {
|
|
||||||
"inputs": {
|
|
||||||
"flake-compat": "flake-compat",
|
|
||||||
"flake-utils": "flake-utils",
|
|
||||||
"nixpkgs": [
|
|
||||||
"nixpkgs"
|
|
||||||
],
|
|
||||||
"rust-overlay": "rust-overlay"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1684981077,
|
|
||||||
"narHash": "sha256-68X9cFm0RTZm8u0rXPbeBzOVUH5OoUGAfeHHVoxGd9o=",
|
|
||||||
"owner": "ipetkov",
|
|
||||||
"repo": "crane",
|
|
||||||
"rev": "35110cccf28823320f4fd697fcafcb5038683982",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "ipetkov",
|
|
||||||
"repo": "crane",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"flake-compat": {
|
|
||||||
"flake": false,
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1673956053,
|
|
||||||
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
|
|
||||||
"owner": "edolstra",
|
|
||||||
"repo": "flake-compat",
|
|
||||||
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "edolstra",
|
|
||||||
"repo": "flake-compat",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"flake-utils": {
|
|
||||||
"inputs": {
|
|
||||||
"systems": "systems"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1681202837,
|
|
||||||
"narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"rev": "cfacdce06f30d2b68473a46042957675eebb3401",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"flake-utils_2": {
|
|
||||||
"inputs": {
|
|
||||||
"systems": "systems_2"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1685518550,
|
|
||||||
"narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=",
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1685498995,
|
|
||||||
"narHash": "sha256-rdyjnkq87tJp+T2Bm1OD/9NXKSsh/vLlPeqCc/mm7qs=",
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "9cfaa8a1a00830d17487cb60a19bb86f96f09b27",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "NixOS",
|
|
||||||
"ref": "nixpkgs-unstable",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": {
|
|
||||||
"inputs": {
|
|
||||||
"crane": "crane",
|
|
||||||
"flake-utils": "flake-utils_2",
|
|
||||||
"nixpkgs": "nixpkgs"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"rust-overlay": {
|
|
||||||
"inputs": {
|
|
||||||
"flake-utils": [
|
|
||||||
"crane",
|
|
||||||
"flake-utils"
|
|
||||||
],
|
|
||||||
"nixpkgs": [
|
|
||||||
"crane",
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1683080331,
|
|
||||||
"narHash": "sha256-nGDvJ1DAxZIwdn6ww8IFwzoHb2rqBP4wv/65Wt5vflk=",
|
|
||||||
"owner": "oxalica",
|
|
||||||
"repo": "rust-overlay",
|
|
||||||
"rev": "d59c3fa0cba8336e115b376c2d9e91053aa59e56",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "oxalica",
|
|
||||||
"repo": "rust-overlay",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"systems": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1681028828,
|
|
||||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"systems_2": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1681028828,
|
|
||||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": "root",
|
|
||||||
"version": 7
|
|
||||||
}
|
|
|
@ -1,23 +0,0 @@
|
||||||
{
|
|
||||||
inputs = {
|
|
||||||
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
|
||||||
crane.url = "github:ipetkov/crane";
|
|
||||||
crane.inputs.nixpkgs.follows = "nixpkgs";
|
|
||||||
flake-utils.url = "github:numtide/flake-utils";
|
|
||||||
};
|
|
||||||
|
|
||||||
outputs = { self, nixpkgs, crane, flake-utils, ... }:
|
|
||||||
flake-utils.lib.eachDefaultSystem (system:
|
|
||||||
let
|
|
||||||
craneLib = crane.lib.${system};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
packages.default = craneLib.buildPackage {
|
|
||||||
src = craneLib.cleanCargoSource (craneLib.path ./.);
|
|
||||||
# Add extra inputs here or any other derivation settings
|
|
||||||
# doCheck = true;
|
|
||||||
# buildInputs = [];
|
|
||||||
# nativeBuildInputs = [];
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
use hyprland::{
|
|
||||||
data::{Client, Clients},
|
|
||||||
dispatch::{Direction, Dispatch, DispatchType},
|
|
||||||
shared::{HyprData, HyprDataActiveOptional},
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn get_active() -> Option<Client> {
|
|
||||||
Client::get_active().unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get() -> Clients {
|
|
||||||
Clients::get().unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn focus_by_direction(direction: Direction) {
|
|
||||||
let _ = Dispatch::call(DispatchType::MoveFocus(direction));
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
pub mod client;
|
|
||||||
pub mod monitor;
|
|
||||||
pub mod option;
|
|
||||||
pub mod workspace;
|
|
||||||
|
|
||||||
use std::env;
|
|
||||||
use std::io::prelude::*;
|
|
||||||
use std::os::unix::net::UnixStream;
|
|
||||||
|
|
||||||
extern crate serde_json;
|
|
||||||
|
|
||||||
fn send_message(action: &str, args: Vec<&str>) -> String {
|
|
||||||
let env_var_name = "HYPRLAND_INSTANCE_SIGNATURE";
|
|
||||||
|
|
||||||
let hyprland_instance_sig = match env::var(env_var_name) {
|
|
||||||
Ok(v) => v,
|
|
||||||
Err(e) => panic!("${} is not set ({})", env_var_name, e),
|
|
||||||
};
|
|
||||||
|
|
||||||
let socket_path = format!("/tmp/hypr/{}/.socket.sock", hyprland_instance_sig);
|
|
||||||
let mut stream = match UnixStream::connect(socket_path) {
|
|
||||||
Err(_) => panic!("server is not running"),
|
|
||||||
Ok(stream) => stream,
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut message = format!("j/{}", action);
|
|
||||||
args.into_iter()
|
|
||||||
.for_each(|a| message.push_str(&format!(" {}", a)));
|
|
||||||
|
|
||||||
// TODO: stop being stinky and manage errors
|
|
||||||
let _ = stream.write_all(message.as_bytes());
|
|
||||||
let mut response = String::new();
|
|
||||||
|
|
||||||
// TODO: stop being stinky and manage errors
|
|
||||||
let _ = stream.read_to_string(&mut response);
|
|
||||||
response
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
use hyprland::data::{Monitor, Monitors};
|
|
||||||
use hyprland::dispatch::*;
|
|
||||||
use hyprland::shared::HyprData;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
|
||||||
pub struct ActiveWorkspace {
|
|
||||||
pub id: u64,
|
|
||||||
pub name: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_by_id(id: i16) -> Monitor {
|
|
||||||
let mut monitors = get();
|
|
||||||
monitors.find(|m| m.id == id).unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get() -> Monitors {
|
|
||||||
Monitors::get().unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn focus_left() {
|
|
||||||
let _ = Dispatch::call(DispatchType::FocusMonitor(MonitorIdentifier::Direction(
|
|
||||||
Direction::Left,
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn focus_right() {
|
|
||||||
let _ = Dispatch::call(DispatchType::FocusMonitor(MonitorIdentifier::Direction(
|
|
||||||
Direction::Right,
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn focus_up() {
|
|
||||||
let _ = Dispatch::call(DispatchType::FocusMonitor(MonitorIdentifier::Direction(
|
|
||||||
Direction::Up,
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn focus_down() {
|
|
||||||
let _ = Dispatch::call(DispatchType::FocusMonitor(MonitorIdentifier::Direction(
|
|
||||||
Direction::Down,
|
|
||||||
)));
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
const GETOPTIONS: &str = "getoptions";
|
|
||||||
const GENERAL_GAPS_OUT: &str = "general:gaps_out";
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
|
||||||
pub struct HyprlandOption {
|
|
||||||
pub option: String,
|
|
||||||
pub int: i32,
|
|
||||||
pub float: f64,
|
|
||||||
pub str: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_gaps() -> i16 {
|
|
||||||
let response = super::send_message(GETOPTIONS, vec![GENERAL_GAPS_OUT]);
|
|
||||||
let gap_option: HyprlandOption = serde_json::from_str(&response).unwrap();
|
|
||||||
|
|
||||||
gap_option.int as i16
|
|
||||||
}
|
|
|
@ -1,23 +0,0 @@
|
||||||
// TODO: change this file to hyprland-rs
|
|
||||||
const WORKSPACE: &str = "workspace";
|
|
||||||
const DISPATCH: &str = "dispatch";
|
|
||||||
const MOVETOWORKSPACESILENT: &str = "movetoworkspacesilent";
|
|
||||||
const MOVETOWORKSPACE: &str = "movetoworkspace";
|
|
||||||
|
|
||||||
pub fn focus(workspace_number: &u64) {
|
|
||||||
let _ = super::send_message(DISPATCH, vec![WORKSPACE, &workspace_number.to_string()]);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn move_to(workspace_number: &u64) {
|
|
||||||
super::send_message(
|
|
||||||
DISPATCH,
|
|
||||||
vec![MOVETOWORKSPACESILENT, &workspace_number.to_string()],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn move_focus(workspace_number: &u64) {
|
|
||||||
super::send_message(
|
|
||||||
DISPATCH,
|
|
||||||
vec![MOVETOWORKSPACE, &workspace_number.to_string()],
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -1,350 +0,0 @@
|
||||||
use clap::{Parser, Subcommand, ValueEnum};
|
|
||||||
|
|
||||||
mod hyprland_ipc;
|
|
||||||
use hyprland::{
|
|
||||||
data::{Client, Monitor, Transforms, Workspaces},
|
|
||||||
dispatch::Direction, shared::HyprData,
|
|
||||||
};
|
|
||||||
use hyprland_ipc::{client, monitor, option, workspace};
|
|
||||||
|
|
||||||
#[derive(Parser)]
|
|
||||||
#[command(name = "hyprsome")]
|
|
||||||
#[command(author = "sopa0")]
|
|
||||||
#[command(version = "0.1.11")]
|
|
||||||
#[command(about = "Makes hyprland workspaces behave like awesome")]
|
|
||||||
struct Cli {
|
|
||||||
#[command(subcommand)]
|
|
||||||
command: Commands,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Subcommand)]
|
|
||||||
enum Commands {
|
|
||||||
Focus { direction: Directions },
|
|
||||||
Workspace { workspace_number: u64 },
|
|
||||||
Move { workspace_number: u64 },
|
|
||||||
Movefocus { workspace_number: u64 },
|
|
||||||
MoveEmpty,
|
|
||||||
FocusEmpty,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, ValueEnum, Debug)]
|
|
||||||
enum Directions {
|
|
||||||
L,
|
|
||||||
R,
|
|
||||||
U,
|
|
||||||
D,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait MonitorDimensions {
|
|
||||||
fn real_width(&self) -> f32;
|
|
||||||
fn real_height(&self) -> f32;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MonitorDimensions for Monitor {
|
|
||||||
fn real_width(&self) -> f32 {
|
|
||||||
match self.transform {
|
|
||||||
Transforms::Normal
|
|
||||||
| Transforms::Normal180
|
|
||||||
| Transforms::Flipped
|
|
||||||
| Transforms::Flipped180 => self.width as f32 / self.scale,
|
|
||||||
Transforms::Normal90 | Transforms::Normal270 | Transforms::Flipped90 => {
|
|
||||||
self.height as f32 / self.scale
|
|
||||||
}
|
|
||||||
_ => self.width as f32,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn real_height(&self) -> f32 {
|
|
||||||
match self.transform {
|
|
||||||
Transforms::Normal
|
|
||||||
| Transforms::Flipped
|
|
||||||
| Transforms::Normal180
|
|
||||||
| Transforms::Flipped180 => self.height as f32 / self.scale,
|
|
||||||
Transforms::Normal90 | Transforms::Normal270 | Transforms::Flipped90 => {
|
|
||||||
self.width as f32 / self.scale
|
|
||||||
}
|
|
||||||
_ => self.height as f32,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_current_monitor() -> Monitor {
|
|
||||||
monitor::get().find(|m| m.focused).unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: refactor this nonsense
|
|
||||||
pub fn select_workspace(workspace_number: &u64) {
|
|
||||||
let mon = get_current_monitor();
|
|
||||||
match mon.id {
|
|
||||||
0 => workspace::focus(workspace_number),
|
|
||||||
_ => {
|
|
||||||
workspace::focus(
|
|
||||||
&format!("{}{}", mon.id, workspace_number)
|
|
||||||
.parse::<u64>()
|
|
||||||
.unwrap(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_empty_workspace() -> u64 {
|
|
||||||
let mon = get_current_monitor();
|
|
||||||
let mut found = Vec::new();
|
|
||||||
for workspaces in Workspaces::get().iter() {
|
|
||||||
for workspace in workspaces.iter() {
|
|
||||||
if workspace.monitor == mon.name {
|
|
||||||
let mut id = workspace.name.clone();
|
|
||||||
if id.len() > 1 {
|
|
||||||
id = id.chars().nth(1).unwrap().to_string();
|
|
||||||
}
|
|
||||||
found.push(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for i in 1..9 {
|
|
||||||
if !found.contains(&i.to_string()) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 1; // Send to the first workspace if no others are available
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: refactor this nonsense
|
|
||||||
pub fn send_to_workspace(workspace_number: &u64) {
|
|
||||||
let mon = get_current_monitor();
|
|
||||||
match mon.id {
|
|
||||||
0 => workspace::move_to(workspace_number),
|
|
||||||
_ => {
|
|
||||||
workspace::move_to(
|
|
||||||
&format!("{}{}", mon.id, workspace_number)
|
|
||||||
.parse::<u64>()
|
|
||||||
.unwrap(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: refactor this nonsense
|
|
||||||
pub fn movefocus(workspace_number: &u64) {
|
|
||||||
let mon = get_current_monitor();
|
|
||||||
match mon.id {
|
|
||||||
0 => workspace::move_focus(workspace_number),
|
|
||||||
_ => {
|
|
||||||
workspace::move_focus(
|
|
||||||
&format!("{}{}", mon.id, workspace_number)
|
|
||||||
.parse::<u64>()
|
|
||||||
.unwrap(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_leftmost_client_for_monitor(mon_id: i16) -> Client {
|
|
||||||
let clients = client::get();
|
|
||||||
|
|
||||||
clients
|
|
||||||
.into_iter()
|
|
||||||
.filter(|c| c.monitor == mon_id)
|
|
||||||
.min_by_key(|c| c.at.0)
|
|
||||||
.unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn focus_left(aw: Client) {
|
|
||||||
let mon = monitor::get_by_id(aw.monitor);
|
|
||||||
let is_leftmost_client = is_leftmost_client(&aw, &mon);
|
|
||||||
|
|
||||||
if is_leftmost_monitor(&mon) && is_leftmost_client {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if is_leftmost_client {
|
|
||||||
monitor::focus_left();
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
client::focus_by_direction(Direction::Left);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn focus_right(aw: Client) {
|
|
||||||
let mon = monitor::get_by_id(aw.monitor);
|
|
||||||
|
|
||||||
if is_rightmost_monitor(&mon) && is_rightmost_client(&aw, &mon) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if is_rightmost_client(&aw, &mon) {
|
|
||||||
monitor::focus_right();
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
client::focus_by_direction(Direction::Right);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn focus_up(aw: Client) {
|
|
||||||
let mon = monitor::get_by_id(aw.monitor);
|
|
||||||
let is_top_client = is_top_client(&aw, &mon);
|
|
||||||
|
|
||||||
if is_top_monitor(&mon) && is_top_client {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if is_top_client {
|
|
||||||
monitor::focus_up();
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
client::focus_by_direction(Direction::Up);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn focus_down(aw: Client) {
|
|
||||||
let mon = monitor::get_by_id(aw.monitor);
|
|
||||||
let is_bottom_client = is_bottom_client(&aw, &mon);
|
|
||||||
|
|
||||||
if is_bottom_monitor(&mon) && is_bottom_client {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if is_bottom_client {
|
|
||||||
monitor::focus_down();
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
client::focus_by_direction(Direction::Down);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_leftmost_client(aw: &Client, mon: &Monitor) -> bool {
|
|
||||||
let gaps = option::get_gaps();
|
|
||||||
|
|
||||||
if (aw.at.0 - gaps) as i32 == mon.x {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_rightmost_client(aw: &Client, mon: &Monitor) -> bool {
|
|
||||||
let gaps = option::get_gaps();
|
|
||||||
|
|
||||||
if mon.real_width() + mon.x as f32 - gaps as f32 == aw.size.0 as f32 + aw.at.0 as f32 {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_top_client(aw: &Client, mon: &Monitor) -> bool {
|
|
||||||
let gaps = option::get_gaps();
|
|
||||||
|
|
||||||
if mon.y + (gaps as i32) + (mon.reserved.1 as i32) == (aw.at.1 as i32) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_bottom_client(aw: &Client, mon: &Monitor) -> bool {
|
|
||||||
let gaps = option::get_gaps();
|
|
||||||
|
|
||||||
if mon.real_height() + mon.y as f32 - gaps as f32 - mon.reserved.1 as f32
|
|
||||||
== aw.size.1 as f32 + gaps as f32
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_rightmost_monitor(mon: &Monitor) -> bool {
|
|
||||||
let monitors = monitor::get();
|
|
||||||
let max = monitors.into_iter().max_by_key(|m| m.x).unwrap();
|
|
||||||
if max.x == mon.x {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_leftmost_monitor(mon: &Monitor) -> bool {
|
|
||||||
let monitors = monitor::get();
|
|
||||||
let min = monitors.into_iter().min_by_key(|m| m.x).unwrap();
|
|
||||||
if min.x == mon.x {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_top_monitor(mon: &Monitor) -> bool {
|
|
||||||
let monitors = monitor::get();
|
|
||||||
let min = monitors.into_iter().min_by_key(|m| m.y).unwrap();
|
|
||||||
if min.y == mon.y {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_bottom_monitor(mon: &Monitor) -> bool {
|
|
||||||
let monitors = monitor::get();
|
|
||||||
let max = monitors.into_iter().max_by_key(|m| m.y).unwrap();
|
|
||||||
if max.y == mon.y {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let cli = Cli::parse();
|
|
||||||
match &cli.command {
|
|
||||||
Commands::Focus { direction } => match direction {
|
|
||||||
Directions::L => {
|
|
||||||
let aw = client::get_active();
|
|
||||||
|
|
||||||
match aw {
|
|
||||||
Some(aw) => focus_left(aw),
|
|
||||||
None => monitor::focus_left(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
Directions::R => {
|
|
||||||
let aw = client::get_active();
|
|
||||||
|
|
||||||
match aw {
|
|
||||||
Some(aw) => focus_right(aw),
|
|
||||||
None => monitor::focus_right(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
Directions::U => {
|
|
||||||
let aw = client::get_active();
|
|
||||||
|
|
||||||
match aw {
|
|
||||||
Some(aw) => focus_up(aw),
|
|
||||||
None => monitor::focus_up(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
Directions::D => {
|
|
||||||
let aw = client::get_active();
|
|
||||||
|
|
||||||
match aw {
|
|
||||||
Some(aw) => focus_down(aw),
|
|
||||||
None => monitor::focus_down(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Commands::Workspace { workspace_number } => {
|
|
||||||
select_workspace(workspace_number);
|
|
||||||
}
|
|
||||||
Commands::Move { workspace_number } => {
|
|
||||||
send_to_workspace(workspace_number);
|
|
||||||
}
|
|
||||||
Commands::Movefocus { workspace_number } => {
|
|
||||||
movefocus(workspace_number);
|
|
||||||
}
|
|
||||||
Commands::MoveEmpty => {
|
|
||||||
movefocus(&get_empty_workspace());
|
|
||||||
},
|
|
||||||
Commands::FocusEmpty => {
|
|
||||||
select_workspace(&get_empty_workspace());
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue