#!/usr/bin/python3 # This script requires i3ipc-python package (install it from a system package manager # or pip). # It adds icons to the workspace name for each open window. # Set your keybindings like this: set $workspace1 workspace number 1 # Add your icons to WINDOW_ICONS. # Based on https://github.com/maximbaz/dotfiles/blob/master/bin/i3-autoname-workspaces import argparse import i3ipc import logging import re import signal import sys WINDOW_ICONS = { "alacritty": "", "audacious": "", "azote": "", "balena-etcher": "", "Chromium": "", "chromium": "", "code": "", "discord": "", "engrampa": "", "firefox": "", "firefox-esr": "", "foot": "", "gimp-2.10": "", "gimp-2.99": "", "Google-chrome": "", "google-chrome": "", "gpk-application": "", "kitty": "", "libreoffice-startcenter": "", "libreoffice-writer": "", "libreoffice-calc": "", "libreoffice-impress": "", "libreoffice-draw": "", "lximage-qt": "", "mate-calc": "", "mpv": "", "nheko": "", "nwg-look": "", "nwg-displays": "", "org.telegram.desktop": "", "org.qbittorrent.qBittorrent": "", "org.pwmt.zathura": "", "org.inkscape.inkscape": "", "pavucontrol": "", "pluma": "", "pcmanfm": "", "pcmanfm-qt": "", "simple-scan": "", "software-properties-gtk": "", "steam": "", "sway-input-config": "", "telegram": "", "Thunderbird": "", "thunderbird": "", "transmission-gtk": "", "vlc": "" } DEFAULT_ICON = "" def icon_for_window(window): name = None if window.app_id is not None and len(window.app_id) > 0: name = window.app_id.lower() elif window.window_class is not None and len(window.window_class) > 0: name = window.window_class.lower() if name in WINDOW_ICONS: return WINDOW_ICONS[name] logging.info("No icon available for window with name: %s" % str(name)) return DEFAULT_ICON def rename_workspaces(ipc): for workspace in ipc.get_tree().workspaces(): name_parts = parse_workspace_name(workspace.name) icon_tuple = () for w in workspace: if w.app_id is not None or w.window_class is not None: icon = icon_for_window(w) if not ARGUMENTS.duplicates and icon in icon_tuple: continue icon_tuple += (icon,) name_parts["icons"] = " ".join(icon_tuple) + " " new_name = construct_workspace_name(name_parts) ipc.command('rename workspace "%s" to "%s"' % (workspace.name, new_name)) def undo_window_renaming(ipc): for workspace in ipc.get_tree().workspaces(): name_parts = parse_workspace_name(workspace.name) name_parts["icons"] = None new_name = construct_workspace_name(name_parts) ipc.command('rename workspace "%s" to "%s"' % (workspace.name, new_name)) ipc.main_quit() sys.exit(0) def parse_workspace_name(name): return re.match( "(?P[0-9]+):?(?P\w+)? ?(?P.+)?", name ).groupdict() def construct_workspace_name(parts): new_name = str(parts["num"]) if parts["shortname"] or parts["icons"]: new_name += ":" if parts["shortname"]: new_name += parts["shortname"] if parts["icons"]: new_name += " " + parts["icons"] return new_name if __name__ == "__main__": parser = argparse.ArgumentParser( description="This script automatically changes the workspace name in sway depending on your open applications." ) parser.add_argument( "--duplicates", "-d", action="store_true", help="Set it when you want an icon for each instance of the same application per workspace.", ) parser.add_argument( "--logfile", "-l", type=str, default="/tmp/sway-autoname-workspaces.log", help="Path for the logfile.", ) args = parser.parse_args() global ARGUMENTS ARGUMENTS = args logging.basicConfig( level=logging.INFO, filename=ARGUMENTS.logfile, filemode="w", format="%(message)s", ) ipc = i3ipc.Connection() for sig in [signal.SIGINT, signal.SIGTERM]: signal.signal(sig, lambda signal, frame: undo_window_renaming(ipc)) def window_event_handler(ipc, e): if e.change in ["new", "close", "move"]: rename_workspaces(ipc) ipc.on("window", window_event_handler) rename_workspaces(ipc) ipc.main()