This way, the initial frame is more likely to get scaled correctly;
foot will guess the initial (integer) scale from the available
monitors, and use that. By using legacy scaling, we force the
compositor to down-scale the image to the correct scale factor.
If we use the new fraction scaling method with an integer scaling
factor, the initial frame gets rendered way too big.
We now default to scaling fonts using the scaling factor, not monitor
DPI.
The ‘auto’ value for dpi-aware has been removed.
Documentation (man pages and README) have been updated to reflect the
new default.
When the window’s preferred scaling factor is changed (through the
fractional-scaling protocol), update the terminal; resize font, resize
sub-surfaces etc.
Instead of passing a raw wl_surface pointer, pass a wayl_surface
pointer.
This is needed later, when using fractional scaling to scale the
surface (since then we need the surface’s viewport object).
And add a viewport object to accompany the surface (to be used when
scaling the surface).
Also rename the wl_surf_subsurf struct to wayl_sub_surface, and add a
wayl_surface object to it, rather than a plain wl_surface pointer (to
also get the viewport pointer).
* Bind the wp-viewporter and wp-fractional-scale-manager globals.
* Create a viewport and fractional-scale when instantiating a window.
* Add fractional-scale listener (that does nothing at the moment).
* Destroy everything on teardown.
When background alpha is changed at runtime (using OSC-11), we (may)
have to update the opaque hint we send to the compositor.
We must also update the subpixel mode used when rendering font
glyphs.
Why?
When the window is fully opaque, we use wl_surface_set_opaque_region()
on the entire surface, to hint to the compositor that it doesn’t have
to blend the window content with whatever is behind the
window. Obviously, if alpha is changed from opaque, to transparent (or
semi-transparent), that hint must be removed.
Sub-pixel mode is harder to explain, but in short, we can’t do
subpixel hinting with a (semi-)transparent background. Thus, similar
to the opaque hint, subpixel antialiasing must be enabled/disabled
when background alpha is changed.
Closes#1249
Note that it is still unclear whether ack:ing a configure event for an
unmapped surface is a protocol violation, or something that should be
handled by the compositor.
According to
https://gitlab.freedesktop.org/wayland/wayland-protocols/-/issues/108,
Kwin, Mutter and Weston handles it, while wlroots does not.
This pointer ends up being passed to various printf-family functions,
where passing a NULL pointer for an "%s" format specifier invokes
undefined behaviour.
If an output has a bogus physical width or height, the DPI can become
so high that the cell width/height is too large for
pixman_image_fill_rectangles(), resulting in a crash in pixman_fill().
Since it doesn’t make any sense to use a DPI that is obviously bogus,
don’t. Force it 96 instead.
When XDG activation support was added to URL mode, we introduced a
regression, where it is possible to flood the Wayland socket with XDG
activation token requests.
Start foot with “foot -o bell.urgency=yes”, then run:
while true; do echo -en ‘\a’; done
Finally, switch keyboard focus to another window. Foot crashes.
Throttle the token requests by limiting the number of outstanding
urgency token requests to 1.
Closes#1065
First, add a ‘token’ argument to spawn(). When non-NULL, spawn() will
set the ‘XDG_ACTIVATION_TOKEN’ environment variable in the forked
process. If DISPLAY is non-NULL, we also set DESKTOP_STARTUP_ID, for
compatibility with X11 applications. Note that failing to set either
of these environment variables are considered non-fatal - i.e. we
ignore failures.
Next, add a helper function, wayl_get_activation_token(), to generate
an XDG activation token, and call a user-provided callback when it’s
‘done (since token generation is asynchronous). This function takes an
optional ‘seat’ and ‘serial’ arguments - when both are non-NULL/zero,
we set the serial on the token. ‘win’ is a required argument, used to
set the surface on the token.
Re-write wayl_win_set_urgent() to use the new helper function.
Finally, rewrite activate_url() to first try to get an activation
token (and spawn the URL launcher in the token callback). If that
fails, or if we don’t have XDG activation support, spawn the URL
launcher immediately (like before this patch).
Closes#1058
The global config doesn’t necessarily reflect the correct
configuration to use - we should *always* use the current terminal
instance’s conf pointer.
* Move selection override modifier mask to the key_binding_set struct
* Always warn if XDG activation is unavailable, not just if
bell.urgent is set (we no longer have access to this information)
* Pass ‘bool presentation_timings’ as a parameter to wayl_init()
* Remove ‘presentation_timings’ member from the ‘terminal’ struct
Closes#932
Up until now, our Wayland seats have been tracking key bindings. This
makes sense, since the seat’s keymap determines how the key bindings
are resolved.
However, tying bindings to the seat/keymap alone isn’t enough, since
we also depend on the current configuration (i.e. user settings) when
resolving a key binding.
This means configurations that doesn’t match the wayland object’s
configuration, currently don’t resolve key bindings correctly. This
applies to footclients where the user has overridden key bindings on
the command line (e.g. --override key-bindings.foo=bar).
Thus, to correctly resolve key bindings, each set of key bindings must
be tied *both* to a seat/keymap, *and* a configuration.
This patch introduces a key-binding manager, with an API to
add/remove/lookup, and load/unload keymaps from sets of key bindings.
In the API, sets are tied to a seat and terminal instance, since this
makes the most sense (we need to instantiate, or incref a set whenever
a new terminal instance is created). Internally, the set is tied to a
seat and the terminal’s configuration.
Sets are *added* when a new seat is added, and when a new terminal
instance is created. Since there can only be one instance of each
seat, sets are always removed when a seat is removed.
Terminals on the other hand can re-use the same configuration (and
typically do). Thus, sets ref-count the configuration. In other words,
when instantiating a new terminal, we may not have to instantiate a
new set of key bindings, but can often be incref:ed instead.
Whenever the keymap changes on a seat, all key bindings sets
associated with that seat reloads (re-resolves) their key bindings.
Closes#931
Search mode and ‘flash’ (OSC-555) both achieves similar visual
effects: flash tints the entire window yellow, and search mode dims
it (except the search match).
But, they do so in completely different ways. Search mode is detected
in render_cell(), and the colors are then dimmed there.
Flash is implemented by blending a yellow, semi-transparent color on
top of the rendered grid.
This patch replaces those two implementations with a single one. We
add a new sub-surface, called the ‘overlay’. In normal mode, it’s
unmapped.
When either search mode, or flash, is enabled, we enable it, and
fill it with a semi-transparent color. Yellow for ‘flash’, and
“black” (i.e. no color) for search mode.
The compositor then blends it with the grid. Hopefully on the GPU,
meaning it’ll be faster than if we blend in software.
There are more performance benefits however. By using a separate
surface, we can do much better damage tracking.
The normal grid rendering code no longer have to care about neither
search mode, nor flash. Thus, we get rid of a couple of ‘if’
statements in render_cell(), which is nice. But more importantly, we
can drop full grid repaints in a couple of circumstances:
* Entering/exiting search mode
* Every frame while flash is active
Now, when rendering the search mode overlay, we do want to do some
damage tracking, also of the overlay.
This, since search mode doesn’t dim the *entire* window. The search
match is *not* dimmed. This is implemented by punching a hole in the
overlay sub-surface. That is, we make part of it *fully*
transparent. The basic idea is to set a clip region that excludes the
search match, and then dim the rest of the overlay.
It’s slightly more complicated than that however, if we want to reuse
the last frame’s overlay buffer (i.e we don’t want to re-render
the *entire* overlay every frame).
In short, we need to:
* Clear (punch hole) in areas that are part of this frame’s search
match, but not the last frame’s (since those parts are _already_
cleared).
* Dim the areas that were part of the last frame’s search match, but
aren’t anymore (the rest of the overlay should already be dimmed).
To do this, we save the last frame’s “holes” (as a pixman
region). Then, when rendering the next frame, we first calculate the
new frame’s “holes” region.
The region to clear is “this frame’s holes minus last frame’s holes”
The region to dim is “last frame’s holes minus this frames holes”.
Finally, we compute the bounding box of all modified cells by taking
the union of the two diff regions mentioned above. This allows us to
limit the buffer damage sent to the compositor.
We have a number of sub-surfaces for which we are *not* interrested in
pointer (or touch) input.
Up until now, we’ve manually dealt with these, by recognizing these
surfaces in all pointer events, and ignoring them.
But, lo and behold, there are better ways of doing this. By clearing
the subsurface’s input region, the compositor will do this for us -
when a pointer is outside a surface’s input region, the event is
passed to the next surface underneath it.
This is exactly what we want! Do this for all subsurfaces, *except*
the CSDs.
When the compositor is asking us to resize ourselves, take
our (visible) CSD borders into account. This is similar to how we
already take the titlebar size into account.
This fixes an issue where the window size “jumps” when the user starts
an interactive resize, when csd.border-width > 0.
This as been observed in GNOME.
In Sway-1.5, sway waits for configure ACKs from hidden windows when
views are being resized. I.e. if you have e.g. a stacked view, with
one or more windows currently not visible, and you resize the stack,
then sway will emit configure events to all windows, and then wait for
ACKs before rendering the resized view.
The problem with this is that sway also does **not** call frame
callbacks on hidden windows. So if we have rendered one frame, and
thus registered a frame callback, we’ll never render any more frames
until the window becomes visible again. Ergo, if you resize the view
interactively, only the first resize actually happens. After that, all
hidden views are “stuck”, causing ACK timeouts.
We worked around this in foot by preempting the frame
callback. I.e. destroying it, and rendering the frame anyway.
This has fixed in sway-1.6, and thus we can remove the workaround.
From the NOTES section of getenv(3):
The string pointed to by the return value of getenv() may be statically
allocated, and can be modified by a subsequent call to getenv()...
So, previously xcursor_theme could be modified by libc to contain
xcursor_size. This has been fixed by getting xcursor_theme after
computing the value of xcursor_size.
The compositor may offer version 4, while we’re still linked against
an old libwayland that does not implement version 4.
While we properly #ifdef the callbacks from version 4, we were still
requesting version 4 (if offered by the compositor), even when
compiled against a too old libwayland.
Closes#876
These are new in version 4 of the wl_output interface (first included
in wayland-1.20).
This allows us to get the name and description of the outputs, also on
compositors without the XDG output interface.