Replies: 2 comments 2 replies
-
I believe all the issues arise because a column can contain a mix of automatic and fixed sized windows. When a column is in When you switch a column into This way it would "just work" for most people, but if you need the ability to have manual resizing, you still can, and you can be explicit about it, rather than doing it on accident. |
Beta Was this translation helpful? Give feedback.
-
I implemented weighted height distribution in 66f23c3. Please give it a try and see if anything feels weird or broken. One edge case I found is: if you have multiple windows in a column and the column is taller than the screen (e.g. there are some min-sized windows there and the others are made too tall), then resizing one of the fixed-size windows will cause the sizes to jump to pad the column to screen height, as the non-min-sized windows get automatically weighted. |
Beta Was this translation helpful? Give feedback.
-
Currently, it's quite easy to end up with columns shorter or taller than the screen height. This can be confusing and annoying. Let's figure out a solution.
How it currently works
Window height can be in two states:
When you vertically resize a window, it becomes fixed-height. To go back to automatic, you can use a double-vertical-resize click, the
reset-window-height
action, or expel the window into a new column.For comparison, column width also has a third state: proportion of a screen width as a percentage. I intentionally designed heights to not have a proportion state. My reasoning was that if you vertically resize a window, you probably want some particular thing to fit in it (i.e. exactly 20 lines in a terminal), and therefore the height should become fixed and not change as you move the window across monitors (which can have different height, therefore resulting in a different window height after the proportion calculation).
Constraints
Wayland windows have a final say in their size. They can decide to be smaller than the screen (i.e. fixed-size dialogs) or bigger than the screen. This is not really a problem as it is generally clear how to deal with this, whatever the height distribution algorithm.
Windows bigger than the screen could use some way to scroll them up and down, but that is out of scope for this discussion.
Windows generally tell the compositor their minimum and maximum size, so the height distribution algorithm can take this into account. The occasional client doesn't (used to be a problem with Qt), which can result in column height not matching screen height even with an automatically-sized window. That is also out of scope for this discussion.
Currently, the height distribution algorithm does not take maximum window height into account if it is different from the minimum window height (i.e., fixed size dialogs work, but windows with max height and no min height do not work). This is due to how the algorithm needs to iterate to find a fixed point solution for automatic window heights. You can either take all minimum sizes into account (what it currently does), or all maximum heights into account, but taking both into account is much more complicated (?) and I don't think it is guaranteed to find a fixed point solution (?). This is not really a problem because windows don't generally have max height that is not equal to min height.
Problems
The main problem is that generally people expect a tiling layout to always pad the column height to the screen height. Currently, it seems to work this way right until it doesn't.
For a single-window column this is at least obvious (you resized the window => it is no longer full height). For a multi-window column it appears to work at first, because as you resize one window, the second window remains automatically-sized, and expands to fill the space. However, as soon as you also resize the second window, both windows are now fixed-height, so they no longer add up to the screen height.
There's currently another minor problem. If you have three automatic windows in a column and resize the middle one, it will resize "in the center" rather than only on the edge that you are resizing. It works this way because the middle window gets a fixed height, whereas automatic top and bottom windows distribute the remaining height equally among themselves. This makes sense for a
set-window-height
key binding as it doesn't specify the edge, but it doesn't really make sense for mouse resizing. It would be nice if the new sizing algorithm would solve this.A related problem is that with two windows in a column, you can resize the top window by its top edge, which is weird (since it is the other edge that is resizing). I thought about this quite a bit when implementing interactive resizing, but I realized that there are way too many edge cases to handle this correctly with the current system (one example: a column with two windows, top has a min size; you resize the bottom window up by its top edge; at some point you hit the min size for the top window which would need to block you from resizing any further; this gets arbitrarily complicated with more windows with different min sizes in the column).
There are situations where you might want window heights to work as proportions. Someone was trying to use niri for presenting (not exactly a supported case but nevertheless). They arranged windows in columns on their monitor, then moved the workspace to the projector output, which had a different resolution. The expectation was that window heights will be moved as proportions, just like column widths.
I think this problem is not particularly pressing, as this only kinda works for the specific case when your windows upscale their contents to fit the size (image/video viewers). If they don't, your layout will likely break anyway.
Things that should work
Here are some important use cases that should ideally still work with whatever system we decide on:
Resizing a single window to smaller or bigger than the screen. Useful for taking exact resolution screenshots, or for viewing videos in native resolution.
Resizing a window in a column with many windows should not cause other windows to spontaneously change their sizes.
What I mean by this is, imagine we have a column with two small fixed-size windows, one big fixed-size window and one automatic window. When I start to resize the automatic window, if the algorithm were to change all other windows to automatic at that instant, the other windows would all spontaneously snap to exactly 1/3 of the remaining height each. This is something I'd like to avoid.
Resizing one (or more?) window in a column to a fixed size which is then preserved when moving across monitors or when adding more windows into that column.
This is the case I mentioned above, when you have for example two terminals in a column, and you resize one of them to fit exactly 20 lines. Then you move the entire column to a second, smaller monitor. The window that you resized should remain exactly 20 lines in size, and not become smaller.
Resizing a window should not unnecessarily fix heights of other windows in the column. I.e., moving the column to a different monitor should let things resize to that monitor's height.
Potential solutions
While writing all of this down, I've got this rough idea in my mind. Add a "weight" to the automatic height state. When distributing height among automatic windows, instead of distributing it equally, distribute it according to the weights. This is similar to how
flex-grow
works in CSS, or how the fraction unit works in Typst.When resizing a window, all other windows in a column instantly change to Automatic with weights computed in such a way as to preserve their apparent visual heights. This means that as you resize a window, other windows will resize proportionally to their initial sizes, while the entire column will maintain its full height equal to the monitor height.
I haven't thought too hard about this yet, let alone tried implementing it, so I'm not sure if this will work, or if it will hit some edge cases. It doesn't solve problems 2–4 but that's fine, we can do one thing at a time.
Beta Was this translation helpful? Give feedback.
All reactions