Better special workspaces

This commit is contained in:
Thomas Forgione 2025-05-08 15:40:58 +02:00
parent d01e20a89a
commit 7299d9086f
4 changed files with 60 additions and 21 deletions

View File

@ -45,7 +45,7 @@ exec-once = flameshot
exec-once = blueberry-tray
exec-once = nextcloud --background
exec-once = [workspace special:social silent] $social
exec-once = [workspace special:thunderbird silent] thunderbird
exec-once = [workspace special:mail silent] thunderbird
exec-once = [workspace special:terminal silent] alacritty
source = ~/.config/dotfiles/hypr/exec-once.conf
@ -278,8 +278,8 @@ bind = $mainMod SHIFT, code:19, exec, $hyprscript movetoworkspace 10
bind = , Print, exec, grim -g "$(slurp -d)" - | wl-copy
# Example special workspace (scratchpad)
bind = $mainMod, Q, togglespecialworkspace, social
bind = $mainMod, S, togglespecialworkspace, thunderbird
bind = $mainMod, Q, togglespecialworkspace, mail
bind = $mainMod, S, togglespecialworkspace, social
bind = $mainMod, D, togglespecialworkspace, terminal
# Scroll through existing workspaces with mainMod + scroll

View File

@ -5,6 +5,7 @@ import os
import os.path
import subprocess
import sys
import typing
os.chdir(os.path.expanduser('~/.config/dotfiles/hypr'))
bars = "_▂▃▄▅▆▇█"
@ -17,12 +18,13 @@ class Monitor:
A monitor on which many workspaces can appear.
"""
def __init__(self, id: int, name: str):
def __init__(self, id: int, name: str, special_workspace: typing.Optional['Workspace']):
"""
Constructs a monitor from its id and its name.
"""
self.id = id
self.name = name
self.special_workspace = special_workspace
def __eq__(self, other):
"""
@ -50,7 +52,11 @@ class Monitor:
result = json.loads(proc.stdout)
for mon in result:
monitors.append(Monitor(mon['id'], mon['name']))
if mon['specialWorkspace']['id'] == 0:
monitors.append(Monitor(mon['id'], mon['name'], None))
else:
special_workspace = Workspace(mon['specialWorkspace']['id'], mon['specialWorkspace']['name'])
monitors.append(Monitor(mon['id'], mon['name'], special_workspace))
return monitors
@ -90,11 +96,27 @@ class Workspace:
Workspaces with id from 10 * n + k belongs to the same monitor for k in [1, 10].
"""
def __init__(self, id: int):
def __init__(self, id: int, name: str):
"""
Constructs a workspace from its id.
Constructs a workspace from its id and its name.
"""
self.id = id
self.name = name
def is_special(self) -> bool:
"""
Returns true if the workspace is a magic workspace.
"""
return self.id < 0
def special_name(self) -> typing.Optional[str]:
"""
Returns the part after the : if the workspace is special, none otherwise.
"""
if self.is_special():
return ':'.join(self.name.split(':')[1:])
else:
return None
@staticmethod
def active() -> 'Workspace':
@ -103,24 +125,31 @@ class Workspace:
"""
proc = subprocess.run(['hyprctl', 'activeworkspace', '-j'], capture_output=True)
result = json.loads(proc.stdout)
return Workspace(result['id'])
return Workspace(result['id'], result['name'])
def nth(self, n: int, move: bool = False):
def nth(self, n: int, monitor: Monitor, move: bool = False):
"""
Goes to the nth workspace on the same monitor as the current workspace.
Params:
n: workspace to go to, between 1 and 10.
monitor: active monitor.
move: whether you want to move the active window to the new workspace.
"""
new_id = (self.id - 1) // 10 * 10 + n
current = monitor.special_workspace
if current is not None:
subprocess.run(['hyprctl', 'dispatch', 'togglespecialworkspace', current.special_name()])
subprocess.run(['hyprctl', 'dispatch', 'movetoworkspace' if move else 'workspace', str(new_id)])
def previous(self, move: bool = False):
def previous(self, monitor: Monitor, move: bool = False):
"""
Goes to the previous workspace on the same monitor, or the last if we're on the first.
Params:
monitor: active monitor.
move: whether you want to move the active window to the new workspace.
"""
new_id = self.id - 1
@ -128,13 +157,18 @@ class Workspace:
if new_id % 10 == 0:
new_id += 10
current = monitor.special_workspace
if current is not None:
subprocess.run(['hyprctl', 'dispatch', 'togglespecialworkspace', current.special_name()])
subprocess.run(['hyprctl', 'dispatch', 'movetoworkspace' if move else 'workspace', str(new_id)])
def next(self, move: bool = False):
def next(self, monitor: Monitor, move: bool = False):
"""
Goes to the next workspace on the same monitor, or the first if we're on the last.
Params:
monitor: active monitor.
move: whether you want to move the active window to the new workspace.
"""
new_id = self.id + 1
@ -142,6 +176,10 @@ class Workspace:
if new_id % 10 == 1:
new_id -= 10
current = monitor.special_workspace
if current is not None:
subprocess.run(['hyprctl', 'dispatch', 'togglespecialworkspace', current.special_name()])
subprocess.run(['hyprctl', 'dispatch', 'movetoworkspace' if move else 'workspace', str(new_id)])
@ -206,18 +244,21 @@ def main():
return
if sys.argv[1] == 'workspace' or sys.argv[1] == 'movetoworkspace':
monitors = Monitor.all()
monitor = Monitor.active(monitors)
workspace = Workspace.active()
move = sys.argv[1] == 'movetoworkspace'
if sys.argv[2] == 'next':
workspace.next(move)
workspace.next(monitor, move)
elif sys.argv[2] == 'previous':
workspace.previous(move)
workspace.previous(monitor, move)
else:
new_workspace = int(sys.argv[2])
workspace.nth(new_workspace, move)
workspace.nth(new_workspace, monitor, move)
elif sys.argv[1] in ['movewindow', 'focusnextmonitor', 'focuspreviousmonitor']:
monitors = Monitor.all()

View File

@ -34,6 +34,9 @@
"hyprland/workspaces": {
"format": "{icon}",
"format-icons": {
"social": "󰍥 ",
"mail": " ",
"terminal": " ",
"11": "1",
"12": "2",
"13": "3",
@ -62,6 +65,7 @@
"DP-3": [11, 12, 13, 14, 15, 16, 17, 18, 19, 20],
"DP-2": [21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
},
"show-special": true
},
"clock": {
"format": "{:L%A %d %B %H:%M}",

View File

@ -39,14 +39,8 @@ button:hover {
background: inherit;
}
#workspaces {
padding-top: 2px;
padding-left: 5px;
padding-right: 5px;
}
#workspaces button {
padding: 0px 0px;
padding: 0px 2px;
background-color: white;
color: #000000;
border-radius: 50px;