X-Git-Url: https://iankelling.org/git/?a=blobdiff_plain;f=i3-split-maybe;h=d8bd54c67745bfb06b073d6e8165b8395d7a68ec;hb=dab96f8fa4c701db13ba734fa0c07b5d12fc8fae;hp=69e42c547a723841fae1b7b9ba1cb4ced7ce9088;hpb=12e4748d67a2891d120f0ce7c29c2cf44a6119df;p=distro-setup diff --git a/i3-split-maybe b/i3-split-maybe index 69e42c5..d8bd54c 100755 --- a/i3-split-maybe +++ b/i3-split-maybe @@ -1,82 +1,118 @@ -#!/bin/bash -# I, Ian Kelling, follow the GNU license recommendations at -# https://www.gnu.org/licenses/license-recommendations.en.html. They -# recommend that small programs, < 300 lines, be licensed under the -# Apache License 2.0. This file contains or is part of one or more small -# programs. If a small program grows beyond 300 lines, I plan to switch -# its license to GPL. +#!/usr/bin/python3 -# Copyright 2024 Ian Kelling - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -set -e; . /usr/local/lib/bash-bear; set +e - -# We use this along with -# /a/opt/i3-alternating-layout/alternating_layouts.py to anticipate when -# we want to split/tab windows. There are 2 options of when to do it: -# just after a window is created, or just before a window is -# created. +# This anticipates when we want to tab windows. There are 2 options of +# when to do it: just after a window is created, or just before a window +# is created. # -# *Doing it after a window is created allows you to move a window into +# * Doing it after a window is created allows you to move a window into # the split that only has 1 window, whereas the other way doesn't. For # my use cases, I think I don't really want to move it into the split if -# it is a tabbed split. +# it is a tabbed split. upon further reflection, I've determined that +# single window containers are inherently confusing because they tend to +# exist and get nested at unexpected times and then it is unclear how to +# get rid of them and what is going on and the benefit is generally not +# worth it. This command helps identify single window containers during +# testing: /a/opt/i3ipc-python/examples/i3-debug-console.py # -# *Doing it just before a windows is created, you need to -# call this script, which means wrapping launch of a program, which I -# have no way to do for all cases, I just do it for the common programs -# I have bound to keys in i3. +# * Doing it just before a windows is created, you need to call this +# script, which means wrapping launch of a program, which I have no way +# to do for all cases, I just do it for the common programs I have bound +# to keys in i3. # -# * Doing it after a window is created also leaves that split behind if -# * the window is closed. I partially deal with that below. +# * Note: doing it just before a window is created also leaves that split behind if +# the window is closed, and I don't want single window splits hanging around, +# so I close them out in # # I have a keybind which disables both, it runs /b/ds/i3-auto-layout-toggle -if [[ -e /tmp/iank-i3-no-auto ]]; then - exit 0 -fi +import sys +import os +from i3ipc import Connection, Event +# for debugging +#from pprint import pprint + + +def find_parent(i3, window_id): + """ + Find the parent of a given window id + """ + + def finder(con, parent, gp): + if con.id == window_id: + return (parent, gp) + for node in con.nodes: + res = finder(node, con, parent) + if res: + return res + return None + + return finder(i3.get_tree(), None, None) + + +def set_layout(i3): + """ + Set the layout/split for the currently + focused window to either vertical or + horizontal, depending on its width/height + """ + + if os.path.isfile("/tmp/iank-i3-no-auto"): + return + + win = i3.get_tree().find_focused() + parent, gp = find_parent(i3, win.id) + + + workspace = win.workspace() + #pprint(vars(workspace.rect)) + + screen_width = workspace.rect.width + screen_height = workspace.rect.height + half_w = screen_width / 2 + 1 + half_h = screen_height / 2 + 1 + + w = win.rect.width + h = win.rect.height + ph = parent.rect.height + pw = parent.rect.width -tmp=$(mktemp) + # There is potential for future use with < 1920, but I'm + # not thinking about it yet. + if ( screen_width < 1920 or parent.layout == 'tabbed' or gp.layout == 'tabbed'): + return -i3-msg -t get_workspaces | jq ".[]| select(.focused==true) | .rect | .width, .height" >$tmp + # print('d2: len(parent.nodes)', len(parent.nodes),' > 1', + # 'and ( ph ',ph,' > h + 10',h + 10,' or pw',pw,' > w',w,' )', + # 'and w <= half_w',half_w,'+ and h <= half_h',half_h) -{ read -r screen_width; read -r screen_height; } <$tmp + # h + 10 because a tabbed window loses high compared to its parent. + # Note, it is redundant since we check above if the parent is tabbed, + # but just being cautious. + if (len(parent.nodes) > 1 + and ( ph > h + 10 or pw > w ) + and w <= half_w and h <= half_h ): + i3.command('split vertical, layout tabbed') +# print('d1: tabbed') -i3-msg -t get_tree | jq -r ".. | select(.focused? == true).rect | .width, .height" >$tmp -half_w=$(( screen_width / 2 + 100 )) -half_h=$(( screen_height / 2 + 100 )) +### further potential use cases: +# We could automatically do a vertical split when there are 2 or 3 +# horizontal windows. -{ read -r w; read -r h; } <$tmp +# We could undo a vertical split when we close out windows. +# elif (( w == screen_width )); then +# # if we had 2 windows on screen, made them vertical splits, then +# # closed one, it stays vertical split, but we want it horizontal at +# # that point. So, make it horizontal here. +# m i3-msg "split horizontal" -if (( screen_width < 1920 )); then - # haven't considered this case yet - exit 0 -fi +def main(): + i3 = Connection() + set_layout(i3) -if (( w < half_w && h < half_h )); then - i3-msg "split vertical, layout tabbed" -elif (( w == screen_width )); then - : - # if we had 2 windows on screen, made them vertical splits, then - # closed one, it stays vertical split, but we want it horizontal at - # that point. So, make it horizontal here. - i3-msg "split horizontal" -fi -rm -f $tmp +if __name__ == "__main__": + main()