182 lines
4.8 KiB
Python
182 lines
4.8 KiB
Python
#!/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"
|
|
FA_STEAM = "\uF1B6"
|
|
|
|
WINDOW_ICONS = {
|
|
"Blender": FA_CUBE,
|
|
"chromium": FA_CHROME,
|
|
"code": FA_CODE,
|
|
"code-oss": FA_CODE,
|
|
"emacs": FA_CODE,
|
|
"evince": FA_FILE_PDF_O,
|
|
"feh": FA_PICTURE_O,
|
|
"Firefox": FA_FIREFOX,
|
|
"gimp-2.10": FA_PAINT_BRUSH,
|
|
"gnome-calendar": FA_CALENDAR,
|
|
"Gnome-terminal": FA_TERMINAL,
|
|
"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,
|
|
"org.gnome.Nautilus": FA_FOLDER,
|
|
"pulseeffects": FA_VOLUME_UP,
|
|
"slic3r-gui": FA_CUBE,
|
|
"slic3r-prusa3d": FA_CUBE,
|
|
"spotify": FA_SPOTIFY,
|
|
"Steam": FA_STEAM,
|
|
"subl": FA_CODE,
|
|
"subl3": FA_CODE,
|
|
"telegram-desktop": FA_TELEGRAM,
|
|
"Thunar": FA_FOLDER,
|
|
"thunar": FA_FOLDER,
|
|
"transmission-gtk": FA_DOWNLOAD,
|
|
"urxvt": FA_TERMINAL,
|
|
"xfce4-terminal": FA_TERMINAL,
|
|
}
|
|
|
|
WAYLAND_ICONS = {
|
|
"Blender": FA_CUBE,
|
|
"chromium": FA_CHROME,
|
|
"code": FA_CODE,
|
|
"code-oss": FA_CODE,
|
|
"emacs": FA_CODE,
|
|
"evince": FA_FILE_PDF_O,
|
|
"feh": FA_PICTURE_O,
|
|
"firefox": FA_FIREFOX,
|
|
"gimp-2.10": FA_PAINT_BRUSH,
|
|
"gnome-calendar": FA_CALENDAR,
|
|
"gnome-terminal-server": FA_TERMINAL,
|
|
"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,
|
|
"org.gnome.Nautilus": FA_FOLDER,
|
|
"pulseeffects": FA_VOLUME_UP,
|
|
"slic3r-gui": FA_CUBE,
|
|
"slic3r-prusa3d": FA_CUBE,
|
|
"spotify": FA_SPOTIFY,
|
|
"Steam": FA_STEAM,
|
|
"subl": FA_CODE,
|
|
"subl3": FA_CODE,
|
|
"telegramdesktop": FA_TELEGRAM,
|
|
"termite": FA_TERMINAL,
|
|
"thunar": FA_FOLDER,
|
|
"transmission-gtk": FA_DOWNLOAD,
|
|
"urxvt": FA_TERMINAL,
|
|
"xfce4-terminal": 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):
|
|
if window.app_id:
|
|
# Wayland
|
|
if window.app_id in WAYLAND_ICONS:
|
|
return WAYLAND_ICONS[window.app_id]
|
|
else:
|
|
print(f"No icon available for app ID '{window.app_id}'")
|
|
return "*"
|
|
|
|
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()
|