3 # I, Ian Kelling, follow the GNU license recommendations at
4 # https://www.gnu.org/licenses/license-recommendations.en.html. They
5 # recommend that small programs, < 300 lines, be licensed under the
6 # Apache License 2.0. This file contains or is part of one or more small
7 # programs. If a small program grows beyond 300 lines, I plan to change
8 # to a recommended GPL license.
10 # Copyright 2024 Ian Kelling
12 # Licensed under the Apache License, Version 2.0 (the "License");
13 # you may not use this file except in compliance with the License.
14 # You may obtain a copy of the License at
16 # http://www.apache.org/licenses/LICENSE-2.0
18 # Unless required by applicable law or agreed to in writing, software
19 # distributed under the License is distributed on an "AS IS" BASIS,
20 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 # See the License for the specific language governing permissions and
22 # limitations under the License.
25 # There are only 2 cases where I want single window split containers.
27 # * just before creating a new window in it.
29 # * When I want to make 1 window a split container and bring an existing
30 # window into it. In vanilla i3, this is super awkward. Usually, you are
31 # starting out focused on the window you want to move into the
32 # container. So, you focus the window which is to become a container,
33 # split it, focus the window you want to join the container, move it
34 # into that container. 4 actions, totally annoying. Lets simplify this
35 # to 2 actions, a key to say what split we want, then a key to say which
36 # direction to move the current window. Since we have a hook that erases
37 # all single window split containers on focus change, we can consider a
38 # single window split container to indicate the split we want.
42 from i3ipc
import Connection
, Event
44 from pprint
import pprint
48 def find_parent(i3
, window_id
):
50 Find the parent of a given window id
53 def finder(con
, parent
, gp
):
54 if con
.id == window_id
:
56 for node
in con
.nodes
:
57 res
= finder(node
, con
, parent
)
62 return finder(i3
.get_tree(), None, None)
67 Set the layout/split for the currently
68 focused window to either vertical or
69 horizontal, depending on its width/height
72 direction
= sys
.argv
[1]
74 win
= i3
.get_tree().find_focused()
75 parent
, gp
= find_parent(i3
, win
.id)
76 layout
= parent
.layout
78 if (parent
and gp
and len(parent
.nodes
) == 1):
80 if os
.path
.exists('/tmp/iank-i3-no-auto'):
83 open('/tmp/iank-i3-no-auto', 'a')
84 i3
.command('focus ' + direction
)
87 if (layout
== 'splith'):
88 i3
.command('split horizontal')
89 elif (layout
== 'splitv'):
90 i3
.command('split vertical')
91 elif (layout
== 'tabbed'):
92 i3
.command('split vertical')
93 i3
.command('layout tabbed')
95 i3
.command('[con_id=%s] focus' % win
.id)
96 i3
.command('move ' + direction
)
98 os
.remove('/tmp/iank-i3-no-auto')
100 i3
.command('move ' + direction
)
108 if __name__
== "__main__":