#!/usr/bin/env python3 # Taken from https://gist.github.com/bgavran/462c9391a49a835546f9bf9c15ce56f9 # and slightly modified by me (https://github.com/SijmenSchoon). # # This script listens for i3 events and updates workspace names to show icons # for running programs. It contains icons for a few programs, but more can # easily be added by inserting them into WINDOW_ICONS below. # # Dependencies # * xorg-xprop - install through system package manager # * i3ipc - install with pip import i3ipc import subprocess as proc import re # Add icons here for common programs you use. The keys are the X window class # (WM_CLASS) names and the icons can be any text you want to display. However # most of these are character codes for font awesome: # http://fortawesome.github.io/Font-Awesome/icons/ FA_CHROME = "\uf268" FA_CODE = "\uf121" FA_DOWNLOAD = "\uf019" FA_FILE_PDF_O = "\uf1c1" FA_FILE_TEXT_O = "\uf0f6" FA_FILES_O = "\uf0c5" FA_FIREFOX = "\uf269" FA_PICTURE_O = "\uf03e" FA_SPOTIFY = "\uf1bc" FA_TERMINAL = "\uf120" FA_TELEGRAM = "\uf3fe" FA_CUBE = "\uf1b2" FA_PAINT_BRUSH = "\uf1fc" FA_BOOK = "\uf02d" FA_FOLDER = "\uf07c" FA_CALENDAR = "\uf133" FA_BEZIER_CURVE = "\uf55b" FA_VECTOR_SQUARE = "\uf5cb" FA_VOLUME_UP = "\uf028" WINDOW_ICONS = { "Firefox": FA_FIREFOX, "Gnome-terminal": FA_TERMINAL, "chromium": FA_CHROME, "code": FA_CODE, "emacs": FA_CODE, "evince": FA_FILE_PDF_O, "feh": FA_PICTURE_O, "gimp-2.10": FA_PAINT_BRUSH, "gnome-calendar": FA_CALENDAR, "google-chrome": FA_CHROME, "inkscape": FA_PAINT_BRUSH, "jetbrains-pycharm": FA_CODE, "jetbrains-webstorm": FA_CODE, "libreoffice": FA_FILE_TEXT_O, "mupdf": FA_FILE_PDF_O, "nautilus": FA_FOLDER, "notion-nativefier-102b2f": FA_BOOK, "pulseeffects": FA_VOLUME_UP, "slic3r-prusa3d": FA_CUBE, "spotify": FA_SPOTIFY, "subl": FA_CODE, "subl3": FA_CODE, "telegram-desktop": FA_TELEGRAM, "transmission-gtk": FA_DOWNLOAD, "thunar": FA_FOLDER, "urxvt": FA_TERMINAL, } i3 = i3ipc.Connection() def xprop(win_id, property): """ Return an array of the values for the given property from xprop. Requires xorg-xprop to be installed. """ try: prop = proc.check_output(['xprop', '-id', str(win_id), property], stderr=proc.DEVNULL) prop = prop.decode('utf-8') return re.findall('"([^"]+)"', prop) except proc.CalledProcessError: print(f"Unable to get property for window '{win_id}'") return None def icon_for_window(window): classes = xprop(window.window, 'WM_CLASS') if classes: for cls in classes: if cls in WINDOW_ICONS: return WINDOW_ICONS[cls] print('No icon available for window with classes: %s' % str(classes)) return '*' def rename(): """Rename all workspaces based on the present windows.""" for workspace in i3.get_tree().workspaces(): icons = " ".join(icon_for_window(w) for w in workspace.leaves()) new_name = f"{workspace.num}" if icons: new_name += f": {icons}" i3.command(f'rename workspace "{workspace.name}" to "{new_name}"') def on_change(i3, e): """Call rename() on relevant window events.""" print(f"{e.change}") if e.change in ['new', 'close', 'move']: rename() def main(): rename() i3.on('window', on_change) i3.main() if __name__ == "__main__": main()