aboutsummaryrefslogtreecommitdiff
path: root/scripts/sway-toolwait
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/sway-toolwait')
-rwxr-xr-xscripts/sway-toolwait134
1 files changed, 134 insertions, 0 deletions
diff --git a/scripts/sway-toolwait b/scripts/sway-toolwait
new file mode 100755
index 0000000..562cc49
--- /dev/null
+++ b/scripts/sway-toolwait
@@ -0,0 +1,134 @@
+#!/usr/bin/env -S python3 -B
+# https://gitlab.com/wef/dotfiles/-/blob/master/bin/sway-toolwait
+TIME_STAMP="20230321.220111"
+
+# dependencies: i3ipc: https://i3ipc-python.readthedocs.io/en/latest/
+
+# Copyright (C) 2020-2022 Bob Hepple <bob dot hepple at gmail dot com>
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or (at
+# your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+from i3ipc import Connection
+import argparse
+import subprocess, sys
+import time
+from multiprocessing import Process
+
+sys.dont_write_bytecode = True
+
+global parser, i3, retval, args, start_time
+
+def verbose(msg):
+ if args.verbose:
+ elapsed_time = time.time() - start_time
+ print(f"{elapsed_time}s: {parser.prog}: {msg}")
+
+def sleep_and_run_command():
+ "This runs in a separate process"
+ s = 0.1 # just enough to let i3ipc.main() loop start
+ verbose(f"Runner process sleeping for {s}s")
+ time.sleep(s)
+ verbose(f"Running: {args.command}")
+ # perhaps a simple fork/spawn here would suffice (and be quicker?)
+ subprocess.Popen(args.command)
+
+def on_window(i3, e):
+ "callback function from i3ipc.main() loop"
+ verbose(f"Got a {e.change} window event:")
+ if e.ipc_data['container']['app_id']:
+ verbose(f"app_id: {e.ipc_data['container']['app_id']}")
+ else:
+ verbose(f"Class: {e.ipc_data['container']['window_properties']['class']}, instance: {e.ipc_data['container']['window_properties']['instance']}")
+
+ waitfor = args.command[0]
+ if args.waitfor:
+ waitfor = args.waitfor
+
+ finished = False
+ if args.nocheck:
+ finished = True
+ else:
+ if e.ipc_data['container']['app_id']:
+ new_window = e.ipc_data['container']['app_id']
+ else:
+ new_window = e.ipc_data['container']['window_properties']['instance']
+ if new_window == waitfor:
+ verbose(f"a new window for '{waitfor}' appeared")
+ finished = True
+ else:
+ verbose(f"a new window appeared '{new_window}' but I'm waiting for '{waitfor}'")
+
+ if finished:
+ i3.main_quit() # else continue to wait
+
+if __name__ == "__main__":
+
+ parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter,
+ description="""
+Run 'command', wait for a window to open, then exit. If no window
+appears in 'timeout' seconds (eg by running a non-GUI program like
+'date') then terminate.
+""",
+ epilog="""eg.
+
+ %(prog)s firefox # this gives time for the window to be created before:
+ swaymsg -q "floating disable; border none"
+
+To run more complex commands use "--". eg.
+
+ %(prog)s -- bash -c "some complex bash commands"
+
+This may be similar to the ancient Sun OpenWindows command toolwait or
+the X11 version at
+http://www.ibiblio.org/pub/linux/X11/xutils/toolwait-0.9.tar.gz
+ """)
+ parser.add_argument('-n', '--nocheck', dest='nocheck', action='store_true',
+ help='don\'t check that the window that opens is for that command (default = %(default)s)')
+ parser.add_argument('-v', '--verbose', dest='verbose', action='store_true', help='verbose operation')
+ parser.add_argument('-m', '--mark', dest='mark', type=str, help='mark to add to window', default='')
+ parser.add_argument('-t', '--timeout', dest='timeout', type=float, help='timeout (default = %(default)s secs)', default=30.0)
+ parser.add_argument('-w', '--waitfor', dest='waitfor', help='app_id (wayland) or instance string (xwayland) to wait for')
+ parser.add_argument('command', nargs='+', help='command to run')
+ args = parser.parse_args()
+
+ i3 = Connection()
+ i3.on('window::new', on_window)
+
+ retval = 1
+ start_time = time.time()
+ # run the command without waiting ie in background:
+ Process(target=sleep_and_run_command).start()
+ i3.main(timeout=args.timeout)
+
+ # i3ipc gives no indication that a timeout has occured, so check the clock:
+ elapsed_time = time.time() - start_time
+ if elapsed_time <= args.timeout:
+ verbose(f"'{args.command} took {elapsed_time}secs to create its first window")
+ retval = 0
+ else:
+ verbose(f"timed out after {args.timeout} secs")
+
+ if args.mark != '':
+ mark_cmd = f'swaymsg -q mark "{args.mark}"'
+ verbose(f"Running: {mark_cmd}")
+ subprocess.run([mark_cmd], shell=True)
+
+ verbose(f"terminated, retval={retval}")
+ sys.exit(retval)
+
+# Local variables:
+# mode: python
+# time-stamp-pattern: "4/TIME_STAMP=\"%:y%02m%02d.%02H%02M%02S\""
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# End: