Discussion:
Re: modifying left and right key bindings
(too old to reply)
Michael Stapelberg
2016-06-16 06:47:50 UTC
Permalink
[cc: correct address of i3-discuss]
Hi Michael,
You can request the layout tree from i3 (see
https://i3wm.org/docs/ipc.html#_tree_reply) and send a focus command
with
criteria matching a specific container id, e.g. “[con_id=0xdeadbeef]
focus”.
I haven’t fleshed this idea out more than that, and it might not be very
straight-forward, but I think it’s possible.
I just wanted to try to contextualize your advice from a few weeks
ago.
I had assumed you were recommending that I create a keybinding like
bindsym $mod+f exec my-new-focus right
and that within 'my-new-focus' I would use the i3 IPC interface
(sending GET_TREE and COMMAND). Is that what you had in mind?
Yes.
Looking at the IPC documentation, I think the other alternative would
be to create a server which listens for binding events, then the
bindsym $mod+f exec echo hi
I started to think about the protocol I want to implement, and I came
to the conclusion that for all eight combinations of {focus,move}
{left,right,up,down}, there should be a normal version, as well as two
versions which additionally direct the motion to the parent or child
in the container hierarchy. To distinguish all these combinations, one
starts to run out of modifiers, so I thought maybe a sort of
"prefix-key" would be handy. I wonder if it would be more natural to
use i3's "binding modes" for this, or to just have a server that
listens for binding events.
Using binding modes sounds like the right approach to the concept of a
prefix key.
The other question is what commands to send to i3 in order to modify
the tree. It seems IPC has no SET_TREE command. You explained how to
change the focus to a specific container in your previous message, by
specifying a con_id criterion... but I don't see an analogous way to
move a container from one place to another using e.g. a pair of
con_id's. It seems it might be necessary to invert i3's existing
protocol, including "implicit containers" and so on, to figure out
which "move up/down/left/right" commands to send to accomplish a given
tree modification. I think this could be messy.
Possibly https://github.com/i3/i3/issues/917 is helpful?
If you're busy then I might just start experimenting with the
protocol, but I wanted to run this by you in case you have any
suggestions or comments.
By the way, some of my trouble was fixed by putting
force_focus_wrapping yes
into ~/.i3/config. This eliminates many cases where left and right
fail to be inverses. (Would have been nice to know about it earlier!)
I’m not omnipotent, not even about i3 :). In fact, I don’t use most of its
features, and I can’t keep 7 years worth of development in my head.

I’m glad you found an option which makes your usage of i3 more pleasant,
though.
Thanks,
Frederick
Hi Michael,
I wanted to follow up on a suggestion that you made in response to an
- "focus right" is not always the reverse of "focus left". For
instance, if the rightmost tab is split horizontally, then one
command will cycle through all the windows, but the other will
get
stuck cycling through the children of the tab which has been
split.
Same with "focus up" and "focus down" in the stacking layout,
when a
child is split vertically. It seems it would be cleaner to have
these pairs be strict opposites.
There are several places where the directional commands don’t
strictly
operate on the tree and hence focus left/right are not always direct
opposites. We believe that bottomline, this makes it easier for
users.
Even
if it didn’t make it easier for users, changing it now would be very
disruptive to existing users, so I don’t think we can do much about
it.
If you feel strongly, you might be able to implement your own logic
using
the IPC interface: http://i3wm.org/docs/ipc.html
Now, I've just set up a second monitor for my desktop, and I find it
somewhat annoying that when a certain window is selected (in tabbed
mode), "focus right" switches from one monitor to the other, but
"focus left" stays on the second monitor (it is not the reverse of
"focus right"). You said that it's important to keep the current
behavior because some users are accustomed to it, but you also
suggested that I could arrange something different using i3's IPC
interface. Do mind providing (or pointing me to) a short example of
how to do this? It sounds very powerful and I imagine that you or
somebody else might have some examples lying around which could get me
off to a good start.
Thank you,
Frederick
--
Best regards,
Michael
--
Best regards,
Michael
f***@ofb.net
2016-06-17 05:01:49 UTC
Permalink
Hi Michael,

Thanks for getting back to me!
Post by Michael Stapelberg
The other question is what commands to send to i3 in order to modify
the tree. It seems IPC has no SET_TREE command. You explained how to
change the focus to a specific container in your previous message, by
specifying a con_id criterion... but I don't see an analogous way to
move a container from one place to another using e.g. a pair of
con_id's. It seems it might be necessary to invert i3's existing
protocol, including "implicit containers" and so on, to figure out
which "move up/down/left/right" commands to send to accomplish a given
tree modification. I think this could be messy.
Possibly https://github.com/i3/i3/issues/917 is helpful?
That's an interesting thought, and swaps are definitely useful for
composing permutations in an abstract sense, but I don't think they
would be the right primitive for re-arranging a tree via IPC. I think
you'd need either:

1. A more flexible primitive. Something that lets you move window X
into the Jth position of container N.

2. A SET_TREE command. I looked a bit at layout saving and restoring,
I don't know if it is possible to get SET_TREE using those features
since they are geared towards a slightly different use-case. It might
seem like overkill to overwrite the whole layout tree every time the
user wants to move a window, but after all it is only a few kilobytes
of data? I'm just speculating here.
Post by Michael Stapelberg
By the way, some of my trouble was fixed by putting
force_focus_wrapping yes
into ~/.i3/config. This eliminates many cases where left and right
fail to be inverses. (Would have been nice to know about it earlier!)
I’m not omnipotent, not even about i3 :). In fact, I don’t use most of its
features, and I can’t keep 7 years worth of development in my head.
I’m glad you found an option which makes your usage of i3 more pleasant,
though.
Thanks. Well next time someone complains that backward and forward are
not inverses, you can point them to this option :)

Best wishes,

Frederick
Michael Stapelberg
2016-06-22 07:28:23 UTC
Permalink
Hi Michael,
Thanks for getting back to me!
Post by Michael Stapelberg
The other question is what commands to send to i3 in order to modify
the tree. It seems IPC has no SET_TREE command. You explained how to
change the focus to a specific container in your previous message, by
specifying a con_id criterion... but I don't see an analogous way to
move a container from one place to another using e.g. a pair of
con_id's. It seems it might be necessary to invert i3's existing
protocol, including "implicit containers" and so on, to figure out
which "move up/down/left/right" commands to send to accomplish a given
tree modification. I think this could be messy.
Possibly https://github.com/i3/i3/issues/917 is helpful?
That's an interesting thought, and swaps are definitely useful for
composing permutations in an abstract sense, but I don't think they
would be the right primitive for re-arranging a tree via IPC. I think
1. A more flexible primitive. Something that lets you move window X
into the Jth position of container N.
2. A SET_TREE command. I looked a bit at layout saving and restoring,
I don't know if it is possible to get SET_TREE using those features
since they are geared towards a slightly different use-case. It might
seem like overkill to overwrite the whole layout tree every time the
user wants to move a window, but after all it is only a few kilobytes
of data? I'm just speculating here.
Modifying the IPC interface to allow this doesn’t sound too appealing. The
danger is that the modified/injected state might lead to unimagined
side-effects or outright crashes — we’d need to carefully figure out and
document what modifications are valid. In a way, that’s currently covered
by just providing the existing primitives.

I’m beginning to think that perhaps a custom patch to i3 might be simpler
to achieve what you want.
Post by Michael Stapelberg
By the way, some of my trouble was fixed by putting
force_focus_wrapping yes
into ~/.i3/config. This eliminates many cases where left and right
fail to be inverses. (Would have been nice to know about it earlier!)
I’m not omnipotent, not even about i3 :). In fact, I don’t use most of
its
Post by Michael Stapelberg
features, and I can’t keep 7 years worth of development in my head.
I’m glad you found an option which makes your usage of i3 more pleasant,
though.
Thanks. Well next time someone complains that backward and forward are
not inverses, you can point them to this option :)
Best wishes,
Frederick
--
Best regards,
Michael
f***@ofb.net
2016-06-23 21:47:40 UTC
Permalink
Hi Michael,
[...] I think
1. A more flexible primitive. Something that lets you move window X
into the Jth position of container N.
2. A SET_TREE command. I looked a bit at layout saving and restoring,
I don't know if it is possible to get SET_TREE using those features
since they are geared towards a slightly different use-case. It might
seem like overkill to overwrite the whole layout tree every time the
user wants to move a window, but after all it is only a few kilobytes
of data? I'm just speculating here.
Modifying the IPC interface to allow this doesn’t sound too appealing. The
danger is that the modified/injected state might lead to unimagined
side-effects or outright crashes — we’d need to carefully figure out and
document what modifications are valid. In a way, that’s currently covered
by just providing the existing primitives.
I’m beginning to think that perhaps a custom patch to i3 might be simpler
to achieve what you want.
I'm honored that you're still thinking about this.

I think "force_focus_wrapping" seems to have fixed most of my
annoyance, so it's not very important for me personally to be able to
prototype new movement commands at this point. However, I'm glad to
keep brainstorming with you.

A hypothetical SET_TREE command would require the server to check that

a. windows are not created or destroyed
b. the id<->name mapping is not changed
c. top-level nodes like "root" and LVDS1 are not changed
d. container rectangles have the appropriate containment relationships

I guess I could agree that this is undesirably complicated for the
server. Also, either whoever is prototyping new commands would have to
figure out new container rectangles for when a window moves into a
split container, or the server would have to implement a convention
whereby e.g. leaving the 'rect' unspecified would cue the server to

e. fill in sensible rectangles and move the other windows to make
room.

There is my suggestion #1 above, to implement a new primitive "that
lets you move window X into the Jth position of container N."...

Alternatively, having the IPC client issue a succession of movement
commands might not be so difficult in the end. For example, if I
wanted to implement a command "move right, wrapping to the leftmost
position if we're already on the right side of the container", then my
script could issue GET_TREE, count the number of "move left" commands
needed to get from one side to the other, and issue these in
succession.

Similarly, I could implement a "focus right, not descending into next
container" by checking if the container on the right is
horizontally-split or tabbed, and if so, issuing a "focus parent"
command following the "focus right" command. I think the biggest
downside of this "reverse-engineering" of the existing movement
commands is that it would change based on options that the user might
have set, such as "force_focus_wrapping". But that's not a big concern
for prototyping usage.

I think 'i3' might benefit from having more primitive focus and
movement commands, like "move right to parent", "move right to sibling
with wrapping", "focus up to child". But I don't want to overwhelm you
with suggestions or ruin the elegance of the current design.

Best wishes,

Frederick
Michael Stapelberg
2016-06-25 19:42:45 UTC
Permalink
Hi Michael,
Post by Michael Stapelberg
[...] I think
1. A more flexible primitive. Something that lets you move window X
into the Jth position of container N.
2. A SET_TREE command. I looked a bit at layout saving and restoring,
I don't know if it is possible to get SET_TREE using those features
since they are geared towards a slightly different use-case. It might
seem like overkill to overwrite the whole layout tree every time the
user wants to move a window, but after all it is only a few kilobytes
of data? I'm just speculating here.
Modifying the IPC interface to allow this doesn’t sound too appealing.
The
Post by Michael Stapelberg
danger is that the modified/injected state might lead to unimagined
side-effects or outright crashes — we’d need to carefully figure out and
document what modifications are valid. In a way, that’s currently covered
by just providing the existing primitives.
I’m beginning to think that perhaps a custom patch to i3 might be simpler
to achieve what you want.
I'm honored that you're still thinking about this.
I think "force_focus_wrapping" seems to have fixed most of my
annoyance, so it's not very important for me personally to be able to
prototype new movement commands at this point. However, I'm glad to
keep brainstorming with you.
A hypothetical SET_TREE command would require the server to check that
a. windows are not created or destroyed
b. the id<->name mapping is not changed
c. top-level nodes like "root" and LVDS1 are not changed
d. container rectangles have the appropriate containment relationships
I guess I could agree that this is undesirably complicated for the
server. Also, either whoever is prototyping new commands would have to
Agreed.
figure out new container rectangles for when a window moves into a
split container, or the server would have to implement a convention
whereby e.g. leaving the 'rect' unspecified would cue the server to
e. fill in sensible rectangles and move the other windows to make
room.
There is my suggestion #1 above, to implement a new primitive "that
lets you move window X into the Jth position of container N."...
Alternatively, having the IPC client issue a succession of movement
commands might not be so difficult in the end. For example, if I
wanted to implement a command "move right, wrapping to the leftmost
position if we're already on the right side of the container", then my
script could issue GET_TREE, count the number of "move left" commands
needed to get from one side to the other, and issue these in
succession.
Similarly, I could implement a "focus right, not descending into next
container" by checking if the container on the right is
horizontally-split or tabbed, and if so, issuing a "focus parent"
command following the "focus right" command. I think the biggest
downside of this "reverse-engineering" of the existing movement
commands is that it would change based on options that the user might
have set, such as "force_focus_wrapping". But that's not a big concern
for prototyping usage.
Yes. This sort of complexity is precisely why we’re trying to keep the
number of options at a minimum.
I think 'i3' might benefit from having more primitive focus and
movement commands, like "move right to parent", "move right to sibling
with wrapping", "focus up to child". But I don't want to overwhelm you
with suggestions or ruin the elegance of the current design.
I tend to agree. Unfortunately for your use-case, the focus/move commands
and the various options which influence them weren’t so much designed, but
rather grew historically :).
Best wishes,
Frederick
--
Best regards,
Michael
Loading...