Skip to content

Instantly share code, notes, and snippets.

@windwp
Created June 11, 2020 10:03
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save windwp/e5ada09aa8bfcb11da9961cebdde9c9b to your computer and use it in GitHub Desktop.
Save windwp/e5ada09aa8bfcb11da9961cebdde9c9b to your computer and use it in GitHub Desktop.
update i3 swallow
#!/usr/bin/env python3
#-----------------------------------------------
# used to swallow a terminal window in i3
#
# INSTALL
# Install python 3 and install i3ipc libary
# pip3 install i3ipc
# download this scrript and put it to your i3 config folder and run
# chmod +x $HOME/.config/i3/i3-swallow.py
# python3 $HOME/.config/i3/i3-swallow.py
#
# You can add this script to your i3 config file.
# exec --no-startup-id python3 $HOME/.config/i3/i3-swallow.py
# reload i3 and try run xclock
#----------------------------------------------------
#
# this version will try to get the last position when you close graphic appliation
# It can't restore if the graphic appliation is on top of layout ,It restore 80% position
import i3ipc
import subprocess
from time import sleep
import pprint
swallowDict={}
i3 = i3ipc.Connection()
def unMarkAllNode(node,marked):
for mark in node.marks:
if mark==marked:
i3.command('[con_id=%s] unmark' % (node.id))
return True
for node in node.nodes:
if(unMarkAllNode(node,marked)):
return True
return False
def hideSwallowParent(node, windowId, swallowId):
if(str(node.window) == str(windowId)):
global swallowDict
i3.command('[con_id=%s] focus' % swallowId)
i3.command('[con_id=%s] move to scratchpad' % node.id)
i3.command('[con_id=%s] mark swallowParent' % node.parent.id)
swallowDict[str(swallowId)] = {
"id": node.id,
"layout": node.layout,
"index":node.parent.nodes.index(node),
"parent_nodes":len(node.parent.nodes)-1, # minus to hided window,
}
return True
for node in node.nodes:
if(hideSwallowParent(node, windowId, swallowId)):
return True
return False
def getParentNodePid(node):
# get parent of pid because terminal spwan shell(zsh or fish) and then spawn that child process
output = subprocess.getoutput(
"ps -o ppid= -p $(ps -o ppid= -p $(xprop -id %d _NET_WM_PID | cut -d' ' -f3 ))" % (node.window))
return output
def getWindowIdfromPId(pid):
output = subprocess.getoutput("xdotool search -pid %s" % pid)
return output
def on_new(self, event):
workspace = i3.get_tree().find_focused().workspace()
# if we can find parent have pid container map to any node in workspace we will hide it
parentContainerPid = getParentNodePid(event.container)
parentContainerWid = getWindowIdfromPId(parentContainerPid)
for item in workspace.nodes:
hideSwallowParent(item, parentContainerWid, event.container.id)
def on_close(self, event):
global swallowDict
swallow = swallowDict.get(str(event.container.id))
if swallow != None:
focusWindow=i3.get_tree().find_focused()
workspace = i3.get_tree().find_focused().root()
window = i3.get_tree().find_by_id(swallow["id"])
if window != None:
del swallowDict[str(event.container.id)]
i3.command(
'[con_id=%s] scratchpad show;floating disable;focus' % (window.id))
i3.command('[con_id=%s] move container to mark swallowParent'% (window.id))
parentMarked=workspace.find_marked("swallowParent")
targetWindow=None
if (swallow["index"] < len(focusWindow.parent.nodes)):
targetWindow = focusWindow.parent.nodes[swallow['index']]
if( targetWindow==None and len(parentMarked)>0 and len(parentMarked[0].nodes)>0):
if (swallow["index"] < len(parentMarked[0].nodes)):
targetWindow = parentMarked[0].nodes[swallow['index']]
if(targetWindow!=None):
i3.command('[con_id=%s] swap container with con_id %d'% (window.id,targetWindow.id))
i3.command('[con_id=%s] focus'% (window.id))
def on_move(self,event):
swallow = swallowDict.get(str(event.container.id))
if swallow != None:
focusWindow=i3.get_tree().find_focused()
if focusWindow!=None:
for item in focusWindow.workspace().nodes:
unMarkAllNode(item,'swallowParent')
i3.command('[con_id=%s] mark swallowParent' % focusWindow.parent.id)
swallow["layout"]=focusWindow.layout
swallow["index"]=focusWindow.parent.nodes.index(focusWindow)
swallow["parent_nodes"]=len(focusWindow.parent.nodes)
def on_binding(self,event):
pass
# Subscribe to events
i3.on("window::new", on_new)
i3.on("window::move",on_move)
i3.on("window::close",on_close)
i3.on("binding",on_binding)
i3.main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment