summaryrefslogtreecommitdiff
path: root/workspace_watcher.py
diff options
context:
space:
mode:
Diffstat (limited to 'workspace_watcher.py')
-rw-r--r--workspace_watcher.py342
1 files changed, 0 insertions, 342 deletions
diff --git a/workspace_watcher.py b/workspace_watcher.py
deleted file mode 100644
index 03a65ac..0000000
--- a/workspace_watcher.py
+++ /dev/null
@@ -1,342 +0,0 @@
-from functools import reduce
-from enum import Enum
-import subprocess
-import time
-import i3ipc
-from time import sleep
-
-
-APP_CMD = {
- "SystemMonitor": {
- "run": ['bash', "/home/myo/script.sh"],
- "name": "SystemMonitor",
- "geometry": {
- "x": 10, "y": 10, "w": 400, "h": 1060
- },
- "scratch": "hidden1",
- # "skip_startup": False,
- },
- "newsboatterm":{
- "run": ['alacritty', '-T', 'newsboatterm', '-e', 'newsboat'],
- "name": "newsboatterm",
- "geometry": {
- "x": 420, "y": 10, "w": 1200, "h": 353
- },
- "scratch": "hidden2",
- # "skip_startup": True,
- },
- "termusicoverlay":{
- "run": ['alacritty', '-T', 'termusicoverlay', '-e', 'termusic'],
- "name": "termusicoverlay",
- "geometry": {
- "x": 420, "y": 373, "w": 1200, "h": 696
- },
- "scratch": "hidden2",
- # "skip_startup": True,
- },
- "todo":{
- "run": ['alacritty', '-T', 'todo', '-e', 'helix', '~/todo/todo'],
- "name": "todo",
- "geometry": {
- "x": 420, "y": 373, "w": 1200, "h": 696
- },
- "scratch": "hidden3",
- # "skip_startup": True,
- },
-}
-
-def gen_app_list_by_scratches():
- res = dict()
- for item in APP_CMD.values():
- if res.get(item["scratch"]):
- res[item["scratch"]].append(item)
- else:
- res[item["scratch"]] = [item]
- return res
-
-
-APP_NAMES = APP_CMD.keys()
-APPS_BY_SCRATCHES = gen_app_list_by_scratches()
-SCRATCHES = {item["scratch"] for item in APP_CMD.values()}
-LAST_WORKSPACE = None
-
-i3 = i3ipc.Connection()
-
-is_stashed = True
-
-class Status(Enum):
- stashed=0
- hidden1=1
- hidden2=2
- hidden3=3
-
-overlay_status = Status(0)
-
-toggled = False
-# stashed_focus_hist = [True, True]
-
-def float_and_resize(win, geometry):
- win_id = win.id
- i3.command(f"[con_id={win_id}] floating enable")
- i3.command(f"[con_id={win_id}] resize set {geometry['w']} {geometry['h']}")
- i3.command(f"[con_id={win_id}] move position {geometry['x']} {geometry['y']}")
-
-
-def cleanup_unneded_instances(
- tree,
- scratches=None,
-) -> bool:
- print("======= cleanup")
- print("scratches", scratches)
- if not scratches:
- scratches = list(SCRATCHES)
-
- all_apps = reduce(lambda x, y: x + y, [APPS_BY_SCRATCHES[item] for item in scratches])
- print("all apps", all_apps)
-
- res = True
- for name in APP_NAMES:
- matching = list(filter(lambda w: w.workspace() and w.workspace().name not in SCRATCHES, search(tree, name)))
- if len(matching) > 0:
- for win in matching[1:]:
- win.command('kill')
- float_and_resize(matching[0], APP_CMD[name]["geometry"])
- move_to_scratchpad(matching[0], APP_CMD[name]['scratch'])
- res = False
- return
-
-
-def search(tree, name):
- return filter(lambda w: w.name and w.name == name, tree.leaves())
-
-def resp_if_needed(tree, targets):
- # dead = gather_dead(
- # tree,
- # targets
- # )
- dead = filter(
- lambda app: not all(search(tree, app["name"])), targets
- )
- if dead:
- spawn(dead)
- sleep(0.5)
- return True
-
-def gather_dead(tree, targets):
- res = list()
- for app in targets:
- if not list(search(tree, app["name"])):
- res.append(app)
- return res
-
-
-def cleanup(
- tree,
- name,
-) -> bool:
- matching = list(filter(lambda w: w.workspace() and w.workspace().name not in SCRATCHES, search(tree, name)))
- if len(matching) > 0:
- for win in matching[1:]:
- win.command('kill')
- float_and_resize(matching[0], APP_CMD[name]["geometry"])
- move_to_scratchpad(matching[0], APP_CMD[name]['scratch'])
- global overlay_status
- overlay_status = Status(0)
- return True
- return False
-
-def move_to_scratchpad(win, scratch):
- if scratch == "scratchpad":
- i3.command(f'[con_id={win.id}] move to {scratch}')
- else:
- i3.command(f'[con_id={win.id}] move to workspace {scratch}')
-
-
-def on_window_close(i3conn, event):
- win = event.container
- if not win.name or not win.name in APP_NAMES:
- ws = i3.get_tree().find_focused().workspace()
- if overlay_status == Status.stashed and not ws.nodes:
- showup(i3.get_tree(), ws)
- # resp_if_needed(i3conn.get_tree())
- # if not cleanup_unneded_instances(i3.get_tree()):
- # spawn()
- # return
-
-i3.on("window::close", on_window_close)
-
-def showup(tree, ws, show_scratches=None, focus_win=None):
- print('==== showup')
- print('show scratches', show_scratches)
- if not show_scratches:
- show_scratches = ['hidden1']
- all_apps = APPS_BY_SCRATCHES['hidden1']
- else:
- all_apps = reduce(lambda x, y: x + y,[APPS_BY_SCRATCHES[item] for item in show_scratches])
-
- # global overlay_status
- # overlay_status = Status()
- if resp_if_needed(
- tree,
- all_apps,
- ):
- tree = i3.get_tree()
- for app in all_apps:
- # if app["skip_startup"] and not app["scratch"] == show_scratch and not FULL_OVERLAY_SPAWN:
- # return
- matching = list(filter(lambda w: w.name and w.name == app["name"], tree.leaves()))
- win = matching[0]
- float_and_resize(win, app['geometry'])
- win.command(f'move container to workspace {ws.name}')
- if focus_win == app["name"]:
- win.command('focus')
-
-
-def on_workspace_focus(i3conn, event):
- print('========== focus ')
- global LAST_WORKSPACE, overlay_status
- ws = event.current
- if ws is None:
- return
- if (
- not ws.nodes
- and ws.name != LAST_WORKSPACE
- and overlay_status == Status.stashed
- ):
- showup(i3.get_tree(), ws)
- else:
- cleanup_unneded_instances(i3.get_tree())
- LAST_WORKSPACE = ws.name
- overlay_shown = False
- overlay_shown2 = False
-
-
-i3.on("workspace::focus", on_workspace_focus)
-
-
-def on_new_windnow(i3conn, event):
- win = event.container
- if win.name and win.name in APP_NAMES:
- if cleanup_unneded_instances(i3.get_tree()):
- return
- if overlay_status == Status.stashed:
- return
- ws = win.workspace()
- if ws and ws.nodes:
- return cleanup_unneded_instances(i3.get_tree())
- if win.floating != "user_on" and win.floating != "auto_on":
- return cleanup_unneded_instances(i3.get_tree())
-
-
-i3.on("window::new", on_new_windnow)
-
-def on_window_floating(i3conn, event):
- win = event.container
- ws = i3.get_tree().find_focused().workspace()
- if ws and ws.nodes:
- cleanup_unneded_instances(i3.get_tree())
- elif win.floating == "user_on":
- showup(i3.get_tree(), ws)
- else:
- cleanup_unneded_instances(i3.get_tree())
-
-i3.on("window::floating", on_window_floating)
-
-def clean_other_scratches(tree, keep=None):
- if not keep:
- keep={"hidden1"}
- cleanup_unneded_instances(
- tree,
- list(SCRATCHES - keep)
- )
-
-def on_binding(i3conn, event):
- global overlay_status
- match event.binding.command:
- case 'exec --no-startup-id echo "show_partial_overlay"':
- if overlay_status == Status.hidden1:
- cleanup_unneded_instances(
- i3.get_tree(),
- ["hidden1"]
- )
- overlay_status = Status(0)
- else:
- ws = i3.get_tree().find_focused().workspace()
- showup(i3.get_tree(), ws, ['hidden1'], focus_win="SystemMonitor")
- case 'exec --no-startup-id echo "show_overlay_1"':
- if overlay_status == Status.hidden2:
- overlay_status = Status(0)
- cleanup_unneded_instances(
- i3.get_tree(),
- ["hidden1", 'hidden2']
- )
- else:
- clean_other_scratches(i3conn.get_tree(), {"hidden1", "hidden2"})
- ws = i3.get_tree().find_focused().workspace()
- showup(i3.get_tree(), ws, ['hidden1', 'hidden2'], "SystemMonitor")
- case 'exec --no-startup-id echo "show_overlay_2"':
- if overlay_status == Status.hidden3:
- overlay_status = Status(0)
- cleanup_unneded_instances(i3.get_tree(), ["hidden1", "hidden3"])
- else:
- clean_other_scratches(i3conn.get_tree(), {"hidden1", "hidden3"})
- ws = i3.get_tree().find_focused().workspace()
- showup(i3.get_tree(), ws, ['hidden1', 'hidden3'], "todo")
-
-i3.on("binding", on_binding)
-
-def spawn(targets=None):
- if not targets:
- targets = APP_CMD.values()
- if not cleanup_unneded_instances(i3.get_tree()):
- for app in targets:
- res = subprocess.Popen(app["run"])
- print(res)
-
-
-
-
- # # Wait and find its window
- # for _ in range(50):
- # time.sleep(0.1)
- # for win in i3.get_tree().leaves():
- # if APP_MARK in win.marks:
- # return # already marked
- # # Find unmarked new window in focused workspace
- # new_win = [
- # w for w in focused_ws.leaves()
- # if APP_MARK not in w.marks
- # ]
- # if new_win:
- # float_and_resize(new_win[0].id)
- # return
-
-# def move_to_scratch_if_other_windows():
-# ws = i3.get_tree().find_focused().workspace()
-# app_win = next((w for w in ws.leaves() if APP_MARK in w.marks), None)
-# if not app_win:
-# return
-# others = [w for w in ws.leaves() if w.id != app_win.id]
-# if others:
-# i3.command(f"[con_mark={APP_MARK}] move scratchpad")
-
-# def kill_duplicate_instances():
-# app_windows = [w for w in i3.get_tree().leaves() if APP_MARK in w.marks]
-# if len(app_windows) <= 1:
-# return
-# # Keep one, kill others
-# keep_id = app_windows[0].id
-# for w in app_windows[1:]:
-# i3.command(f"[con_id={w.id}] kill")
-
-# def on_window_new(i3conn, e):
-# move_to_scratch_if_other_windows()
-# kill_duplicate_instances()
-
-# spawn_and_mark_app()
-
-# i3.on("window::new", on_window_new)
-# i3.on('workspace::focus', on_workspace_focus)
-
-spawn()
-i3.main()