Skip to content

Instantly share code, notes, and snippets.

@m-bartlett
Created January 8, 2022 04:05
Show Gist options
  • Save m-bartlett/2b01be24333db8ff7f56f51b0a3d719a to your computer and use it in GitHub Desktop.
Save m-bartlett/2b01be24333db8ff7f56f51b0a3d719a to your computer and use it in GitHub Desktop.
i3 dropdown terminal using your favorite terminal™️ in a special i3 container and the i3 scratchpad workspace
#!/usr/bin/env python3
import i3ipc
DROPDOWN_IDENTIFIER = "dropdown"
DROPDOWN_CHILD_IDENTIFIER = "dropdownchild"
INITIAL_TERMINAL_QUANTITY = 3
TERMINAL_COMMAND = f"terminal -n {DROPDOWN_CHILD_IDENTIFIER}"
HEIGHT_PERCENTAGE = 33
i3 = i3ipc.Connection()
tree = i3.get_tree()
focused = tree.find_focused()
workspace_rect = focused.workspace().rect
toggle_dropdown_command = f"""
[con_mark={DROPDOWN_IDENTIFIER}] scratchpad show,
resize set {workspace_rect.width} px {workspace_rect.height*HEIGHT_PERCENTAGE//100} px,
move absolute position {workspace_rect.x}px {workspace_rect.y}px
"""
replies = i3.command(toggle_dropdown_command)
if all([r.success for r in replies]): exit(0)
# If we make it here, no container had the special dropdown mark.
# i3 resets marks if it gets reloaded, so search for container whose instance name is identifier
try:
dropdown = tree.find_instanced(DROPDOWN_IDENTIFIER)[0].parent
for r in i3.command(f'[con_id={dropdown.id}] mark --add {DROPDOWN_IDENTIFIER}'):
print(r.error)
print('found instance')
except IndexError:
# Last resort, spawn a new dropdown container with our terminals
import subprocess
import shlex
import json
import tempfile
def terminal(): # Launch a background terminal process
subprocess.Popen( shlex.split(TERMINAL_COMMAND),
shell=False,
stdin=None,
stdout=None,
stderr=None,
close_fds=True )
terminal_placeholder = {
"border": "pixel",
"layout": "splith",
"current_border_width": 1,
"floating": "auto_off",
"percent": 0.30,
"swallows": [{ "instance": DROPDOWN_CHILD_IDENTIFIER }]
}
swallowable_layout = {
"border": "none",
"floating": "auto_off",
"layout": "splith",
"type": "con",
"name": DROPDOWN_IDENTIFIER,
"instance": DROPDOWN_IDENTIFIER,
"marks": [DROPDOWN_IDENTIFIER],
"nodes": [terminal_placeholder] * INITIAL_TERMINAL_QUANTITY
}
with tempfile.NamedTemporaryFile('w', delete=True) as f:
f.write(json.dumps(swallowable_layout))
f.flush()
i3.command(f'append_layout {f.name}')
i3.command(f'[con_mark={DROPDOWN_IDENTIFIER}] move scratchpad')
for i in range(INITIAL_TERMINAL_QUANTITY):
terminal()
finally:
i3.command(toggle_dropdown_command)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment