From efb8f2997eb5c04f8e5aff5f095b42f0f93f1777 Mon Sep 17 00:00:00 2001 From: Syphdias Date: Thu, 27 Oct 2022 19:36:29 +0200 Subject: [PATCH 1/3] Add depth limit as argument for how often to autotile Currently the script will autotile (vsplit/hsplit) every window focused on with no limit. At a certain depth this behaviour is not desirably to me and I want to add more windows to the same container. Especially for terminals I prefer to have more space horizontally than vertically to see the entire line if possible. To achieve this, I add a optional parameter to prevent further autotiling after the specified limit. For example with a 16:9 display and a depth limit of 1, it will split horizontally first and then only split vertically but in the same container. ``` ________________ | | | |--------| | | |-------| |--------| | |________|_______| ``` As a side effect, this enables stacking and tabbed layouts after reaching the limit. The default behavior is still the same with an infinite limit for how deep to autotile. --- autotiling/main.py | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/autotiling/main.py b/autotiling/main.py index 50868ee..5560949 100644 --- a/autotiling/main.py +++ b/autotiling/main.py @@ -47,7 +47,7 @@ def save_string(string, file): print(e) -def switch_splitting(i3, e, debug, workspaces): +def switch_splitting(i3, e, debug, workspaces, depth_limit): try: con = i3.get_tree().find_focused() if con and not workspaces or (str(con.workspace().num) in workspaces): @@ -59,6 +59,22 @@ def switch_splitting(i3, e, debug, workspaces): # We are on sway is_floating = con.type == "floating_con" + if depth_limit: + # Assume we reached the depth limit, unless we can find a workspace + depth_limit_reached = True + current_con = con + for _ in range(depth_limit): + # Check if parent of the current con is a workspace + current_con = current_con.parent + if current_con.type == "workspace": + # Found the workspace within the depth limitation + depth_limit_reached = False + + if depth_limit_reached: + if debug: + print("Debug: Depth limit reached") + return + is_full_screen = con.fullscreen_mode == 1 is_stacked = con.parent.layout == "stacked" is_tabbed = con.parent.layout == "tabbed" @@ -101,6 +117,11 @@ def main(): nargs="*", type=str, default=[], ) + parser.add_argument("-l", + "--limit", + help="limit how often autotiling will split a container; default: 0 (no limit)", + type=int, + default=0, ) """ Changing event subscription has already been the objective of several pull request. To avoid doing this again and again, let's allow to specify them in the `--events` argument. @@ -129,7 +150,7 @@ def main(): print("No events specified", file=sys.stderr) sys.exit(1) - handler = partial(switch_splitting, debug=args.debug, workspaces=args.workspaces) + handler = partial(switch_splitting, debug=args.debug, workspaces=args.workspaces, depth_limit=args.limit) i3 = Connection() for e in args.events: try: From ef9815dac7225659a1b2fdb3f0f69534c52e10c2 Mon Sep 17 00:00:00 2001 From: Syphdias Date: Sun, 30 Oct 2022 17:42:33 +0100 Subject: [PATCH 2/3] Ignore containers for depth if they have 1 child node With lots of splits the hierarchy can get deeper than normal, if containers get closed. i3 does not flatten this hierarchy (atm). This means that the depth option does needs to ignore containers that only contain one child/node. This is done only incrementing the current depth when checking against the limit if the nodes of the parent container is bigger than 1. --- autotiling/main.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/autotiling/main.py b/autotiling/main.py index 5560949..941863b 100644 --- a/autotiling/main.py +++ b/autotiling/main.py @@ -63,12 +63,21 @@ def switch_splitting(i3, e, debug, workspaces, depth_limit): # Assume we reached the depth limit, unless we can find a workspace depth_limit_reached = True current_con = con - for _ in range(depth_limit): - # Check if parent of the current con is a workspace - current_con = current_con.parent + current_depth = 0 + while current_depth < depth_limit: + # Check if we found the workspace of the current container if current_con.type == "workspace": # Found the workspace within the depth limitation depth_limit_reached = False + break + + # Look at the parent for next iteration + current_con = current_con.parent + + # Only count up the depth, if the container has more than + # one container as child + if len(current_con.nodes) > 1: + current_depth += 1 if depth_limit_reached: if debug: From 75b309c99502492b2409597a14bf3472ef4c3ff3 Mon Sep 17 00:00:00 2001 From: Syphdias Date: Mon, 31 Oct 2022 12:18:12 +0100 Subject: [PATCH 3/3] Add information about --limit The help and README did not go into details what exactly the --limit option does. Since it can be used to imitate a master-stack layout, and can enable tabbed or stacking layouts to some degree, this adds the explanation in the section talking about this limitation. It softens the limitations of autotiling while still stressing that tabbed and stacked layouts may behave unexpectedly and are not supported by autotiling. --- README.md | 27 ++++++++++++++++++++------- autotiling/main.py | 3 ++- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 14375b7..9325ed1 100644 --- a/README.md +++ b/README.md @@ -12,18 +12,28 @@ action](https://img.youtube.com/vi/UWRZuhn92bQ/0.jpg)](https://www.youtube.com/w ## PLEASE DO READ THIS -The script does one thing: it checks the window height / width ratio, and executes -the equivalent of either `swaymsg splitv` or `swaymsg splith`. Nothing less, nothing more. Yes, it may make -stacking and tabbed layouts behave oddly. No, nothing can be done about it. If you like stacking/tabbed layouts, -you may use them on workspaces with autotiling turned off (`--workspaces` argument). Do not submit issues about it. +The script does one thing: it checks the window height / width ratio, and +executes the equivalent of either `swaymsg splitv` or `swaymsg splith`. Nothing +less, nothing more. This may make stack and tabbed layouts behave oddly. +Unfortunately, there is nothing that can be done about it – please, do not +submit issues about it –, but there are two workaround that you can try. -For instance, you may configure autotiling to work on odd workspaces, but not on even: +One option is, to enable autotiling on certain workspaces only. For instance, +you could configure autotiling to be enabled on odd workspaces, but not on +even ones: ```text ### Autostart - exec autotiling -w 1 3 5 7 9 + exec_always autotiling -w 1 3 5 7 9 ``` +Another option you can try, is setting `--limit` and only use stacking or +tabbing on the lowest level. A good place to start would be `--limit 2`. Open +four windows with the third and fourth window in the same container as two. This +might mimic a master-stack layout and you should now be able to switch to +stacking or tabbed. Beware that the decision on how to split is still based on +the height / width ratio. + ## Installation The script has been packaged for the following distributions: @@ -54,6 +64,9 @@ optional arguments: -w [WORKSPACES ...], --workspaces [WORKSPACES ...] restricts autotiling to certain workspaces; example: autotiling --workspaces 8 9 + -l LIMIT, --limit LIMIT + limit how often autotiling will split a container; try "2", if you like + master-stack layouts; default: 0 (no limit) -e [EVENTS ...], --events [EVENTS ...] list of events to trigger switching split orientation; default: WINDOW MODE ``` @@ -64,4 +77,4 @@ Changing event subscription has already been the objective of several pull reque starting from v1.6 you may specify them in the `-e` | `--events` argument. If no value given, the script will subscribe to `Event.WINDOW` and `Event.MODE`, as if it was executed with `autotiling -e WINDOW MODE`. See [altdesktop/i3ipc-python`](https://github.com/altdesktop/i3ipc-python/blob/a670f24e7e04f509de8161cf760afe929c22ae93/i3ipc/events.py#L12) -for event enumeration. \ No newline at end of file +for event enumeration. diff --git a/autotiling/main.py b/autotiling/main.py index 941863b..38f236c 100644 --- a/autotiling/main.py +++ b/autotiling/main.py @@ -128,7 +128,8 @@ def main(): default=[], ) parser.add_argument("-l", "--limit", - help="limit how often autotiling will split a container; default: 0 (no limit)", + help='limit how often autotiling will split a container; ' + 'try "2", if you like master-stack layouts; default: 0 (no limit)', type=int, default=0, ) """