Last active
November 28, 2023 19:54
-
-
Save omenius/36002dc4dc699016b11c71f7a956c02a to your computer and use it in GitHub Desktop.
better-i3-focus
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
""" | |
This script imitates the native 'i3-msg focus [right/left]' functionality | |
with the exception that it totally ignores any non-visible tabs. | |
requires: pip install i3ipc | |
takes exactly one argument: [right|left] | |
""" | |
from sys import argv | |
if argv[1] == "right": | |
direction = 1 | |
elif argv[1] == "left": | |
direction = -1 | |
else: | |
exit() | |
from i3ipc import Connection | |
i3 = Connection() | |
# Recursively look for the last focused item inside a node | |
def find_focused(node): | |
if node.focus: | |
return find_focused( node.find_by_id(node.focus[0]) ) | |
else: | |
return node | |
# Find the window on the right/left side of the given node | |
def find_neighbor_window(node): | |
child = node | |
container = node.parent | |
while container and container.layout != "output": | |
if( container.layout != "splitv"): | |
current_node_idx = container.nodes.index(child) | |
# Find node on argv[1] side of current node if exists | |
dest_idx = current_node_idx + direction | |
if dest_idx != -1 and len(container.nodes) > dest_idx: | |
return find_focused(container.nodes[dest_idx]) | |
# Go to parent and try again if not exhausted | |
child = container | |
container = container.parent | |
# Finds the child of the nearest parent tab container or "tab page" | |
def find_tab_page(node): | |
container = node | |
while container.parent: | |
if container.parent.layout == "tabbed": | |
return container | |
container = container.parent | |
return | |
# Finds the appropriate tab container where we can perform the move | |
def find_correct_node(node): | |
tab_page = find_tab_page(node) | |
if tab_page is None: | |
return | |
neighbor_win = find_neighbor_window(node) | |
if neighbor_win is None or neighbor_win in tab_page.descendants(): | |
return | |
tab_container = tab_page.parent | |
super_tab_container = find_correct_node(tab_container) | |
if super_tab_container: | |
return super_tab_container | |
else: | |
return tab_container | |
# Finally, do the magic | |
focused = i3.get_tree().find_focused() | |
super_node = find_correct_node(focused) | |
if super_node: | |
i3.command(f'[con_id="{super_node.id}"] focus, focus {argv[1]}') | |
else: | |
i3.command(f'focus {argv[1]}') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment