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 = blueberry-tray
exec-once = nextcloud --background exec-once = nextcloud --background
exec-once = [workspace special:social silent] $social 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 exec-once = [workspace special:terminal silent] alacritty
source = ~/.config/dotfiles/hypr/exec-once.conf 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 bind = , Print, exec, grim -g "$(slurp -d)" - | wl-copy
# Example special workspace (scratchpad) # Example special workspace (scratchpad)
bind = $mainMod, Q, togglespecialworkspace, social bind = $mainMod, Q, togglespecialworkspace, mail
bind = $mainMod, S, togglespecialworkspace, thunderbird bind = $mainMod, S, togglespecialworkspace, social
bind = $mainMod, D, togglespecialworkspace, terminal bind = $mainMod, D, togglespecialworkspace, terminal
# Scroll through existing workspaces with mainMod + scroll # Scroll through existing workspaces with mainMod + scroll

View File

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

View File

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

View File

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