[i34wm][i3ass][i3fyra] --rotate|--move [request] #231
Labels
No labels
Arch PKGBUILD
bug
build
commandline
duplicate
enhancement
font
good first issue
help wanted
implemented
is-it-really-a-bug?
necromancy
not-reproducable
question
reproducable
rofi
solved?
stalled
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
bud/i3ass#231
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
i3fyra --rotate [sibling|family]is a great succes and very welcome addition to [i34wm], works like a charm.Excuse me if this is actually two request, in stead of one; but the behaviour is so similar I thought I'd of them as one in the first place (see idea 1 and idea 2 respectively)
Would it be possible to make i3fyra rotate in order of containers in i3ass? This will probably/maybe require yet another big chunk of rewriting code (or not, i don't know?).
i3fyra -Rfor i3fyra --rotate`Idea 1
This would basically be a conditionally invoked, but sequential
i3fyra --rotate/i3fyra --movecommands, issued to the PARENT I3FYRA CONTAINER (and only the VISUAL ones, dependingi3fyra --rotate [right|clockwise|clock|c]would cause the following movement of containers:(( the opposite behaviour will probably be named
i3fyra --rotate [left|anticlockwise|aclock|a]))example
on my screen (container C focused):
A B
C D
i3fyra --rotate [right|clockwise|clock|c]would give meC B
A D
another `i3fyra --rotate [right|clockwise|clock|c]' would give me
A C
D B
another `i3fyra --rotate [right|clockwise|clock|c]' would give me
D A
B C
another
i3fyra --rotate [right|clockwise|clock|c]would return to the originalA B
C D
I've considered the following breaking changes in regards to my request above:
1) Of course
i3fyra --rotate [right|clockwise|clock|c]should only 'rotate' through VISIBLE containers, meaning if:on my screen:
A B
A D
i3fyra --rotate [right|clockwise|clock|c]would give meD A
D B
i3fyra --rotate [right|clockwise|clock|c]would give meB D
B A
another `i3fyra --rotate [right|clockwise|clock|c]' would return to the original
A B
A D
2) just a minor afterthought; if:
on my screem
C B
C B
i3fyra --rotate [right|clockwise|clock|c]would give meB C
B C
at this point,
i3fyra --rotate [right|clockwise|clock|c] would essentially be the same asi3fyra --rotate family`Idea 2
I'd like a similar function not moving** the i3fyra CONTAINERS around, but only the focused container..
In my mind it could for example be an additional argument to
i3fyra --moveand those would bei3fyra --move [clockwise|clock|c]andi3fyra --move anticlockwise|aclock|a].This would still fit the current scripts, as the
--moveoption for a destination i3fyra CONTAINER is CaPs-SeNsItIvE as of now, anyway.Another contender would be
i3fyra --cycle [right|r|clockwise|clock|cvsi3fyra --cycle [left|l|anticlockwise|aclock|a]example:
on my screen, window in i3fyra CONTAINER C is focused
A B
C* D
i3fyra --move [clockwise|clock|c]would function the same asi3fyra --move upA* B
C D
another
i3fyra --move [clockwise|clock|c]would function the same asi3fyra --move rightA B*
C D
another
i3fyra --move [clockwise|clock|c]would function the same asi3fyra --move downA B
C D*
another
i3fyra --move [clockwise|clock|c]would return to the original stateA B
C* D
1) I've considered more breaking features for this one, but it basically boils down to being able to consider which i3fyra CONTAINERS are currently VISIBLE (otherwise, the command
i3fyra --movewill triger (un)hiding the next container, in stead of cycling through the VISIBLE containers.THanks for the amazing work @budRich ; love the ass.
Would above functinoality be possible within i3ass, or is this a case of 'you should write your personal bash script'
Well everything is possible, and i can very much see how both ideas can be useful. The complicated part is to have clockwise/anti-clockwise move in different directions, to do that we need to keep track of the previous actual direction (u,r,l,d) that clockwise was. due to the nature of i3ass, where depending on what we have done to the layout since last clockwise action, it will be very difficult have clockwise mean what we want.
So i wonder if the feature(s) instead can't be shaped into u,r,l,d at least the idea1, where as i understand we basically swap location of the containers while keeping the size of the locations constant, i think this could be hooked in to the current move system without breaking or writing too much code.
But for idea2, as of now, i think it will be too hard to do it in a generic way where it reliably works on a layout in motion. but if you know your layout and know that left is left and up is up and B is B it is not difficult to achieve it. There is proably an elegant solution to make it reliable and generic, but i can't see it now.
I have had this feeling for as long as this project existed, that i can replace 1000 lines of my calculating positions stuff with a 5 line formula that just works. The relation between four directions and four quadrants is what it's all about, but, i have not found the solution, i3ass is just a polished brute force to this problem.
in summary, i will meditate on idea1 but probably with u,r,l,d logic. I think this is a completely different thing than the current --rotate, and i now want to rename current --rotate to --swap.
I get worried with the whole clockwise catch all directions, it gets weird with time, i usually have my desktop sessions running for weeks, and it is not unlikely that in such a session it goes days between firing the command. at the same time, i can definitely see it as sweet to just bash one key combo, to cycle a window till it fits.
Hmm, maybe it doesn't matter that we keep track of the direction, clockwise is not dependent on the previous motion, but the current location of the container.. yeah, forget all i wrote before i will try to do a generic focus clockwise script. if i get that working it will be easy i think to morph it into idea1 and idea2
hi @budRich
I was kinda confused for a sec w/ what you wrote before, but yeah, so....
You are right, it IS a completely different thing, maybe the name of rotate made me think about it in the first place, .
+
In the meantime, I had actually already made an
alias i34swap='i3fyra --rotate';p. We hive-minded there.It's the same feeling probably as to why
i3fyra --orientation togglecould've beeni3fyra --mirror(don't get itchy fingers right now and change the syntax on me!)I think the quote above is the exact thing that makes the idea click (as in, you understand what I meant).
( I might even go as far as to say such a feature will make dwm default functionality (as well as xmonad's) as a dynamic tiling manager feasible, but it will maintain i3wm manual tiling capablities as to edit your window managament as you wish 'on the fly'. )
Yeah, I'd figure it might be possible exactly because you don't have to keep track of the previous movement. That is, because i3ass already kind of 'keeps track' because it has family/sibling/cousin relationships right there in the i3list array, as well as knowing when to hide or not hide, depending on visible/invisible containers...
Im gonna think out loud a bit here, i think the "easiest" will be to think of the operations as swaps,
this is output of i3list with A container focused:
I think the secret formula is figuring out where we want to go, considering regular ABCD grid, A clockwise want to go to B, if B doesn't exist, it is D and last C. When we know where to go we swap those containers, say all four containers are visible, we swap A with B:
now, we swap B with D ie swap swapped with it's first prio.
and finally C with D ie swap swapped with previously untouced.
If target (A) has no sibling (C):
it is the same formula:
Switch A with B:
Swap the swapped with it's old sibling, ie swap swapped with previously untouced:
If target has no cousin (D):
Same first step, but next swap is with old cousins, e swap swapped with previously untouced:
Targets first prio (twin, B) not visible:
Swap A with Prio2 (D), swap swapped with previously untouced:
otherwise we have less than 3 siblings, ie swap or do nothing (only 1 container visible).
This is where i need to brute force, because prio looks like this:
hmm, there is a pattern, A and D and B and C has the same prio, all has cousin as second prio.
Knowing where to go with three containers it is the same formula, with four containers we also need to know the prio for the prio of the first swapped container.
Yeah, this will work if some CS math genius stumble upon this and can spot some bitflip magic we can use here instead, please necrobump this issue.
also counterclockwise prio:
cousin is always second prio, so first and last is one or the other..
I scripted:
You need the latest next version for it to work. One thing i realized is that we need to decide what the swap actually does here. As the script works now it is a full swap, i.e cycle swap full layout, will shuffle all containers and rename the marks, which means that i3king will now plop new windows into the renamed container, which is different from how other i3fyra container shuffling works, where i have virtual positions that keep track of where the OG containers are. I think you understand what i mean, and if not, try shuffling containers with the script and trigger i3king positioning.
I could hook this up with the virtual position thing as well, but i am not sure if that is what we want? I think of it like this: My personal idea is that the four containers represent a shape ( long(A), square(B), tall(D), main/large(C) ) and different applications fit different shapes, so when i3king positions a window it prioritize the shape. But applications can also be grouped by function, say two main applications like: text editor and browser, i want them in the same group.
So the problem now is that if i cycle the main container with browser in it, to the shape of square and spawn a text editor, it will be positioned in the main/large container but not grouped with the browser.
To be honest, it feels kind of weird, and i can just imagine it being a lot more weird for someone not part of this discussion.
Above problem is only relevant to swap, implementing move (idea2) is trivial, and that will not cause any other issues so i can do that, but i am wondering if maybe "cycle swap" is a too complex feature to include in i3ass.
Also there are still lots of corner cases not covered by the script, it obviously only works on i3fyra ws, but i never added any tests for that, and it will not work perfectly if the layout of the containers aren't tabbed. but these are easy to fix.
i went ahead and added move function also, just wanted to feel how it felt:
and it is good, move and focus cycle are both super nice. But i don't think swap in this form is really useful. i wonder if it is possible to hook it into i3fyra, and single key cycle will shuffle the layout, but retain the shape and groups, this would mean given we have the shapes i described earlier ( long(A), square(B), main/large(C), tall(D) ) , if main(C) is focused and we cycle swap CC, we end up with main at D . If size and group of main is retained, it will mean that no matter how we look at it, long will now be in B. And that breaks the cycle, since cycling like we do in the script would have meant that long(A) would become long(C), and tall(D) would be tall(B) above large/main(D).
I think in my shape oriented layout i could make a script that single key cycles and follows my rules , rule is that families stay intact, long is above/below main and square is above/below tall. with that in mind cycling C CC -> D will also imply B CC -> A, so A -> B and D -> C, which is just a normal mirror swap (which can be done with the new --swap family), continue cycling C CC will mirror it with B and i don't think we really need to swap the remaining two containers here? cycling C (now at B) CC -> A, we now need to put long in C, not touching the remaining two containers, this could also be done with the new --swap family.. hmm, this might actually be what we should do, it will let us cycle the position of a single container around the grid with a single command. Maybe this is exactly what you said before, never the less i will try to implement it.
The rule can also be generic and is not about shapes it goes like this: when we trigger cycle we will get a target container (this is layout[] array in the script), if target container is not in the same family as current container, we --swap family, otherwise we --swap sibling !
i did it, and also realized i forgot to tell i3fyra that i renamed --rotat -> --swap so it didn't work, i fixed that. New script using i3fyra --swap to swap, is a lot more simple (also doesn't depend on the newly added i3list container ID output thing, but whatever)
I think this version of swap makes more sense, and it requires 0 additional messing with marks or rethinking the purpose of the universe, one side effect that might be confusing is that if you cycle swap a container wihtout a sibling it will always mirror families (dang, now i also want to rename --swap to --mirror, but i think i got burned the last time i tried to rename it)
dang it, i was hoping that using i3viswiz and i3fyra to focus and move would automatically work even for containers that have splith/v layouts, and it kind of do work but because i have been so smarty pants about how to find the target window in i3viswiz it will result in some containers will never be on the cycle path. And as i see it to fix this we need to figure out what container(s) is in the four corners, then make sure jump to the correct corner container when approriate, f.i. if container a is splitv we need to target top left corner when going from B to A, but if we go from C to A in this case we want to target the bottom container (ie normal move/focus up). It is all completely doable, but it will take a more time than i was hoping for, but i will do it.. meanwhile here is updated script with i3fyra and i3viswiz for moving and focusing:
See screenshot below, black rect is approximately the focus path, notice how top left and top right window is never visited.

i just realized that if i have to do this, get corner windows, i might as well make a semi generic version that works without i3fyra. see, as long as a window is adjacent to the workspace border, we can figure out what direction CC and CW is, with the caveat that we could end up in a crazy layout where the path would get lost. in theory this could happen in i3fyra as well, if a container nests more than one layout, i will just assume that is never the case, but i am aware..
Ok i finally nailed it, this got really hairy, i needed a way to get first and last container in each fyra group, so i added that to i3list. (i first tried adding it properly in i3viswiz, but it was easier to do in i3list).
God damn it, i just found a new issue, above script works perfectly as long as all four containers are visible, but if one is missing it gets weird. i don't know man, i guess i can bruteforce it for 3 and possibly 2 (it probably gets weird here as well if both layouts are not tabbed or stacked). As you can see every single movement and layout combination is its own corner case, this is getting way too hairy for my liking.
One solution, could be to hack i3viswiz so we can offset the search point. As it is now, if you search left the vertical search point will be at the center of the container, what we want is for the search point to be more or less at the extreme top or bottom (or left or right), yeah, that could work i will give it a try tomorrow.
ok, i hacked viswiz to allow for offsetting search pos, and it worked. then i realized that the internal last focused window pathfinding shenanigans was what was breaking layouts where we only had three fyra containers. so i added an option to ignore pathfinding shenanigans, and it worked. But now i found the last corner case, if we only have two fyra containers, say C and A, with a horizontal main orientation, and one or more of C and A has splith layout, we end up in a impossible scenario i think:
if direction is CW and we are in C1, we will go right till we end up in A, all good. CW A will turn direction to right, going to C4, but now you see, CW from C4 should according to all logic focus A which it does, but the hidden purpose of this cycling command is that we can visit all container, but no matter how you look at it from this point it gets sketchy. One "solution" would be that we now when we go CW from A -> C4, for the next CW trigger, we change CW to CC so we keep going right till we end up in A, but here we get the same problem, no CC will just go from A -> C1 back and forth.
Aha, this is what we should do, if no fyra container has the opposite split as the main split, we force CW to always be right (or down if mainsplit is splitv), and CC to always be left (or up), that should cycle all visible containers, because we viswiz wraps at workspace, if user hasn't configured, but that can probably be bypassed for this. yes, thats what i need to do.
Dear diary, i finally got the issue described above solved. And found a bug in the shared main.awk script, that didn't store output values properly so workspace focus wrapping has not worked at all since that bug was introduced.. but i fixed it. I know stumbled upon another corner case, see screenshot below:
there are actually two corner cases issues that can happen when we have 3 fyra containers and one (or more) of them has the same split as the main, in this case splith. Here is screenshot with the short circuit highlighted:
The leftmost, is only between two containers, and it is possible by simply inverting the direction if next focus is going to same container as preiously focused, easy to get needed info from i3viswiz. The right most short circuit is a bit more involved, but i managed to write a test that catches that as well, so that when last container of C has focus, instead of taking the short cut to D (or B depending on rotation), we revert direction, meaning second to last container of C now has focus, it feels good. but, the direction we want to go is still to the right. So i thought, if i keep the test for if previously focused is the same as next to be focused and invert direction if that is the case, it should work. And it does work! but, that means that now we cannot change rotation, changing rotation is literally to focus the last container that had focus. I can limit that to only apply when a container has the same split as main, and only when 3 fyra containers are visible, but it is imo not good enough. I am out of ideas for today i think...
the problem is really that when a container like C in the image is vertically maximized, it is more or less impossible to know if clockwise is left or right, now i simply use the container name, so in C (which is the bottom container) clockwise is left, and A CW is right. The blue arrow, a counter clockwise CC rotation: B -> C (second choice since A is missing), C -> D , since it is splith there is a test that will make sure we are at the last container (ie we have completed C) before proceeding, that test passes and we move to D, D -> B. hmm, i guess if we inverted direction when B -> C so the instead of going left we go right, which would warp to the first container of C would solve everything.
hmm, how to express that test.
If target containers layout is the same as main split, and target is first or last. no this will not work, we have to do something like this. target container is same as main, and target container is last and direction is left (or up on mainsplit=spliv), we focus the first container instead of the last. same logic applies if direction is right, and target is first in a splith container. we can't simply invert the direction, incase our own layout is splith, yeah, that will do it.
I finally got it working. When i fixed the green arrow shortcut thing it introduced a new edge case, imagine a CC movement warping C1 -> B, but now imagine B also being splith, so we would warp to B(last), if we now do CC again, target container is D (direction down) but since we are in a hsplit we first need to "complete" it i.e. be in the last before we can move to D, but we are in last C, so we jump to D, then Last C, and never visit the earlier containers in B...
I had to add yet more tests to catch this problem, and when i now sit here with the final script i realize that it is kind of crap, it is sweet as long as there are only tabbed and maybe one split container, but as soon as layout is a bit more crazy with two or more non tabbed/stacked layouts it just feels jank, especially now with all this edge case warping so focus doesn't flow naturally at all...
Meanwhile focusing in directions u|l|r|d works exactly as expected, and now flawlessly. I actually found yet another sneaky bug in the viswiz algorithm for finding windows that prevented warping of focus within a workspace vertically.
So I have decided to scrap this whole feature from i3ass, i will polish the script a bit and publish it in the forum (discussion tab on github) .
But the cycle swap, felt nice, is more or less fool proof and simple. I will add it as an option to i3fyra swap,
i3fyra --swap cycle.or here is the "final" script in case i never polish and pub in disucssions:
it relies on some fixes in i3ass not yet commited, but i will commit.