This enables quickly tapping focus right-left to keep typing in the
current window while showing the next window.
Resolves https://github.com/YaLTeR/niri/issues/26
Combine the redraw state variables into one enum, and refactor to get
rid of the requirement that a VBlank must queue a subsequent redraw.
Also fix the bug where ongoing animations that produced no damage could
stall the redrawing.
Under some circumstances, the compositor can get into a commit-frame
callback busy loop with a client. For example, if a client redraws on
frame callbacks, but the resulting frame has empty damage (e.g. the
damaged part of the client is outside the monitor). Or if the client
simply commits with empty damage (looking at you, Firefox).
This behavior is compliant with the Wayland specification and with the
intended idea of frame callbacks, but causes a lot of unnecessary CPU
usage in the client and the compositor.
To solve this problem, this commit introduces frame callback throttling.
Every surface may only receive a single frame callback in one
monitor refresh cycle. If a surface commits resulting in no KMS frame
submission, a timer is created, that will fire at the predicted would-
be-VBlank time, and send the accumulated frame callbacks.
This way, a surface that redraws on frame callbacks will not notice
any change in frame callback delivery, if its commits suddenly stop
producing KMS updates.
This works similar to tabs in Firefox: when you create a tab and then
close it without focusing any other tabs, the focus returns to the
previously-focused tab, rather than the usual next tab. The logic is
that in this case, the new tab was likely transient, and the user wants
to get right back to what they were doing.
In niri's case, this also serves as a workaround for wl-clipboard
spawning and destroying a window, messing up the focus.