-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rework the gaps code so sizes are correct and to prevent broken layouts #4298
Conversation
To make sure inner gaps don't generate unequally sized windows always apply a total of one inner gap to all children. Doing just this would result in half-gaps around the workspace border so compensate for that by adding gaps to the workspace. Fixes swaywm#4296
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The weird addition of
#include "pango.h"
insway/tree/workspace.c
was just to getMIN()
andMAX()
.
Considering that these are not defined in pango.h
, but one of the headers included in that file, I'm not a fan of this approach.
Another thing to consider is making it so the gap clamping considers both width and height so that they are equal in both directions. I'm not sure which method is better. Thoughts?
It should also be noted in sway.5
that the inner gaps may be smaller or omitted entirely when there isn't enough space available.
Definitely. My next sentence was exactly that sway should include its own macros.
Whenever the gaps get clamped the result is always going to be a bit odd and this should only really happen in extreme cases. But I think this way should work better. Right now if the window doesn't have enough space horizontally but does vertically the vertical gaps to the other containers are all correct. The way you suggest would result in unequal vertical gaps even though the window fits fine vertically.
Makes sense, I'll add that. I reused the sane width/height values from the resize command. I don't know if those values should be placed somewhere global in the code and possibly also referred to in the documentation somewhere. |
4fd592a
to
3b738b7
Compare
I've moved the macros and the static values to |
Large inner gaps can lead to broken rendering with width/height going negative. Limit the gaps so that they never make the windows smaller than a minimum sensible size (the same used for the resize command). Fixes swaywm#4294
Just like with inner gaps, outer gaps must be capped so that the workspace doesn't run out of space. Since here we have different gaps in all four directions clamp them in a way that at least maintains the relative sizing of the gaps vertically and horizontally. Fixes swaywm#4300
I've fixed all the issues and reimplemented the workspace gaps handling. The code is now correct as it clamps gaps after both outer and inner gaps are applied. Only when we have a total gap (and outer gaps can supposedly be negative) can we then clamp with the correct logic. The code also becomes simpler that way. |
I've found another bug with negative outer gaps filed as #4304 and added a fix for that as well. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few small tweaks and this will be good to merge
c->current_gaps.left = c->x == ws->x ? ws->gaps_inner : 0; | ||
int gaps_horizontal = MAX(0, MIN(ws->gaps_inner, c->width - MIN_SANE_W)); | ||
int gaps_horizontal1 = gaps_horizontal / 2; | ||
int gaps_horizontal2 = gaps_horizontal - gaps_horizontal1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand the idea of making this mirror the workspace gaps section, but I think the cleanness of the following outweighs it.
int gaps_horizontal = MAX(0, MIN(ws->gaps_inner, c->width - MIN_SANE_W));
c->current_gaps.left = gaps_horizontal / 2;
c->current_gaps.right = gaps_horizontal - c->current_gaps.left;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had that like that once upon a time :)
// to match the half gaps that the children have all already added around | ||
// themselves. We use the opposite order for the two halves so that the | ||
// sum adds up to the correct total gap size in all circumstances. | ||
int gaps_horizontal1 = ws->gaps_inner / 2; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the following would be cleaner:
int inner_gaps_left = ws->gaps_inner / 2;
ws->current_gaps.left += inner_gaps_left;
ws->current_gaps.right = ws->gaps_inner - inner_gaps_left;
sway/tree/workspace.c
Outdated
// inner gaps. | ||
int mingaps = ws->layout == L_TABBED || | ||
ws->layout == L_STACKED ? 0 : -ws->gaps_inner; | ||
ws->current_gaps.left = MAX(mingaps, ws->current_gaps.left); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is right. The outer gaps should be able to negate the inner gaps for that side, but this would allow for it to negate double the inner gaps. I think these should all be like ws->current_gaps.left = MAX(0, ws->current_gaps.left)
.
It looks like this function was just missing a call to prevent_invalid_outer_gaps
in between setting the outer gaps and inner gaps.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do you get a double negation? I've gotten rid of prevent_invalid_outer_gaps
completely, it doesn't seem workable to cover all cases with that. It just does that calculation on apply instead. So it allows the outer gaps to at most be -ws->gaps_inner
for tiled containers to then allow those to be negated by the child gaps. It also seems to make more sense to not manipulate the values the user actually sets himself as the workspace may change sizes by moving from one output to another.
This reminds me of another corner case. If the gaps are large enough that the gap clamping will apply in the children the negative gap will not be properly negated... That doesn't seem trivial to fix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do you get a double negation?
Any values where outer == -2 * inner
should work, but the following should make it easily visible
swaymsg -- gaps outer all set -400, gaps inner all set 200
So it allows the outer gaps to at most be
-ws->gaps_inner
Currently, it is being checked after inner gaps are calculated so it actually makes sure that all gaps are at most -ws->gaps_inner
, which is incorrect.
This reminds me of another corner case. If the gaps are large enough that the gap clamping will apply in the children the negative gap will not be properly negated
Can you try explaining that further? When would that occur?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently, it is being checked after inner gaps are calculated so it actually makes sure that all gaps are at most
-ws->gaps_inner
, which is incorrect.
It's correct because the children will then apply ws->gaps_inner
themselves and thus negate that. That's why I only do it for tiled children, as for stacked/tabbed we apply the inner gaps right here so clamping to 0 is correct.
Can you try explaining that further? When would that occur?
Set outer gaps to -1000 and inner gaps to +1000. Now start opening windows. At first it's correct with no outer gaps but gaps within windows. As you open more windows and the inner gaps get clamped the windows start falling outside the screen. This is going to be annoying to fix...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's still wrong though, because clamping needs to be to half size only per edge...
But this doesn't work generally because of the other bug. I'll have to think of a better solution.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've pushed a fix for the half-sized per edge, but this is not mergeable like this because of the other bug. It also doesn't even work always like this because since after the gap clamping it can be negative, the code that adjusts outer gaps can return broken results.
a0ed94f
to
7df7c37
Compare
Since outer gaps can be negative we need to robustly prevent the resulting gaps from ending up negative. The previous code only did this on workspace creation but the gaps can change after that. Fixes swaywm#4304
I think I have a plan to make everything work but it's a completely different solution from this. It would go something like:
I haven't written the code yet but it only makes sense to do that on top of #4293. |
I've implemented the plan on top of #4293 and it worked really well: pedrocr/sway@layout_improvement...pedrocr:gaps_rework The code ends up simpler and easier to reason about. And even after the clamping code it's a net reduction in code:
|
Closed in favor of #4310 |
Fixes for issues #4296 and #4294. They're built on top of each other because they're touching the same code and the reworking of the calculation to make the gaps even makes it easier to then write the code to cap the gaps.
The weird addition of
#include "pango.h"
insway/tree/workspace.c
was just to getMIN()
andMAX()
. This is probably not ok and sway should instead include its own definitions of these macros.--
Fixes #4294
Fixes #4296
Fixes #4304