Commit graph

284 commits

Author SHA1 Message Date
xdavidwu
0b8791d1c5
wayland: fix pointer cap lost handling
Before this, on compositor without cursor-shape support, a pointer
capability lost of the seat makes foot crash.
2023-07-18 16:09:31 +02:00
Daniel Eklöf
21d99f8dce
terminal: break out scaling factor updating, and reduce number of calls to render_resize()
Break out the logic that updates the terminal’s scaling factor value,
from render_resize(), to a new function, term_update_scale(). This
allows us to update the scaling factor without a full grid resize.

We also change how we pick the scaling factor (when fractional scaling
is not in use). Before, we’d use the highest scaling factor from all
monitors we were mapped on. Now, we use the scaling factor from the
monitor we were *last* mapped on.

Then, add a boolean parameter to term_set_fonts(), and when
false, *don’t* call render_resize_force().

Also change term_font_dpi_changed() to only return true if the font
was changed in any way.

Finally, rewrite update_term_for_output_change() to:

* Call term_update_scale() before doing anything else
* Call render_resize{,_force} *last*, and *only* if either the scale
  or the fonts were updated.

This fixes several things:

* A bug where we failed to update the fonts when fractional scaling
  was in use, and we guessed the initial scale/DPI wrong. The bug
  happened because updated the internal "preferred" scale value, and a
  later call to render_resize() updated the terminal’s scale value,
  but since that code path didn’t call term_font_dpi_changed() (and it
  shouldn’t), the fonts weren’t resized properly.

* It ensures we only resize the grid *once* when the scaling factor,
  or DPI is changed. Before this, we’d resize it twice. And this
  happened when e.g. dragging the window between monitors.
2023-07-18 05:48:01 +02:00
Daniel Eklöf
c96863b188
wayland: error out if there aren’t any monitors available 2023-07-18 05:48:01 +02:00
Daniel Eklöf
b2a29280cb
wayland: use physical DPI on fractional-scale capable compositors
With legacy scaling, we need to use a "scaled", or "logical" DPI
value, that is basically the real DPI value scaled by the monitor’s
scaling factor.

This is necessary to compensate for the compositor downscaling the
surface, for "fake" fractional scaling.

But with true fractional scaling, *we* scale the surface to the final
size. This means we should *not* use the scaled DPI, but the monitor’s
actual DPI.

To facilitate this, store both the scaled and the unscaled DPI value
in the monitor struct.

This patch also changes how we pick the DPI value. Before, we would
use the highest DPI value from all the monitors we were mapped
on. Now, we use the DPI value from the monitor we were *last* mapped
on (typically the window we’re dragging the window *to*).
2023-07-18 05:48:01 +02:00
Daniel Eklöf
59f0a721c4
wayland: fractional_scale_preferred_scale(): only push update if scale has changed
Also, drop wl_window::have_preferred_scale. Check for scale > 0 instead.
2023-07-18 05:48:01 +02:00
Ronan Pigott
b7100d5716 render: use rounding for fractional scale
If we truncate the buffer dimensions we may accidentally submit a
buffer with inappropriate size.
2023-07-15 20:03:16 -07:00
CismonX
d2fcb5343f
input: add basic support for touchscreen input
Closes #517
2023-07-05 16:22:28 +02:00
Daniel Eklöf
c2baaff3c1
cursor-shape: use server-side cursors for custom (OSC-22), if possible
Using a lookup table, try to map the user-provided xcursor string to a
cursor-shape-v1 known shape.

If we succeed, set the user’s custom cursor using server side
cursors (i.e. using cursor-shape-v1).

If not, fallback to trying to load the image ourselves (using
wl_cursor_theme_get_cursor()), and set it using the legacy
wl_pointer_set_cursor().
2023-07-03 14:36:32 +02:00
Daniel Eklöf
c8e13ad393
cursor-shape: add support for server side cursor shapes
This implements support for the new cursor-shape-v1 protocol. When
available, we use it, instead of client-side cursor surfaces, to
select the xcursor shape.

Note that we still need to keep client side pointers, for:

* backward compatibility
* to be able to "hide" the cursor

Closes #1379
2023-07-03 14:36:32 +02:00
Daniel Eklöf
72bc0acfbd
wayland: handle enum value XDG_TOPLEVEL_STATE_SUSPENDED
Added in wayland-protocols-1.32
2023-07-03 14:36:03 +02:00
Daniel Eklöf
5e305fa854
wayland: typo: ‘.’ -> ‘;’
Closes #1392
2023-06-30 08:24:02 +02:00
Daniel Eklöf
ce31cc518a
wayland: surface_scale(): reset buffer scale when using fractional scaling
Since the first frame uses legacy scaling, the surface may have a
buffer scale > 1, which isn’t allowed.
2023-06-29 15:38:24 +02:00
Daniel Eklöf
c61247f317
wayland: surface_scale(): improve debug logging 2023-06-29 15:38:24 +02:00
Daniel Eklöf
8f74b1090a
wayland: use legacy scaling until fractional_scale::preferred_scale() has been called
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.
2023-06-29 15:38:24 +02:00
Daniel Eklöf
d71e588800
wayland: refactor: surface_scale(): pass wl_window pointer, instead of wayland global 2023-06-29 15:38:24 +02:00
Daniel Eklöf
c309c9f572
wayland: surface_scale(): assert surface width/height is a multiple of scale
When doing legacy scaling (non-fractional scaling), assert the
surface’s width and height are multiples of the (integer) scale.
2023-06-29 15:38:24 +02:00
Daniel Eklöf
8a4efb3427
wayland: warn when fractional scaling isn’t available 2023-06-29 15:38:24 +02:00
Daniel Eklöf
64b6b5d2a7
config: dpi-aware: remove ‘auto’ value, and default to ‘no’
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.
2023-06-29 15:38:23 +02:00
Daniel Eklöf
0bdb6580bd
wayland: update terminal when preferred scaling factor changes
When the window’s preferred scaling factor is changed (through the
fractional-scaling protocol), update the terminal; resize font, resize
sub-surfaces etc.
2023-06-29 15:38:23 +02:00
Daniel Eklöf
8ccabb7974
wayland: surface_scale(): implement fractional scaling
This is done by setting the surface’s viewport destination
2023-06-29 15:38:23 +02:00
Daniel Eklöf
36818459e5
wayland: initialize window scale to -1 2023-06-29 15:38:23 +02:00
Daniel Eklöf
e5989d81b9
wayland: instantiate+destroy viewport for pointer surface 2023-06-29 15:38:23 +02:00
Daniel Eklöf
5a60bbc119
wayland: refactor: add a buffer argument to wayl_*_scale() functions
This will be needed later, when using fractional scaling + viewporter
to scale.
2023-06-29 15:38:23 +02:00
Daniel Eklöf
434fd6aa1f
wayland: refactor: wayl_surface_scale(): pass wayl_surface pointer
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).
2023-06-29 15:38:23 +02:00
Daniel Eklöf
ba46a039ac
wayland: refactor: wrap wl_surface pointers in a wayl_surface struct
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).
2023-06-29 15:38:23 +02:00
Daniel Eklöf
c5d533ec71
wayland: add viewport object to sub-surface struct 2023-06-29 15:38:23 +02:00
Daniel Eklöf
0a5073f570
wayland: add wayl_surface_scale(), and wayl_win_scale()
These functions scale a surface+buffer.

For now, only using the legacy scaling
method (wl_surface_set_buffer_scale()).
2023-06-29 15:38:23 +02:00
Daniel Eklöf
913ae94cf9
wayland: add wayl_fractional_scaling()
Returns true if fractional scaling is available.
2023-06-29 15:38:22 +02:00
Daniel Eklöf
29a14632d3
wayland: csd_reload_font(): ‘scale’ is now a float 2023-06-29 15:38:22 +02:00
Daniel Eklöf
6e2a47287a
wayland: pointer.scale: convert to float 2023-06-29 15:38:22 +02:00
Daniel Eklöf
a9ecf1449e
wayland: plumbing for wp-fractional-scale
* 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.
2023-06-29 15:38:22 +02:00
Daniel Eklöf
c51050a9bc
osc: update font subpixel mode, and window opaque compositor hint, on alpha changes
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.
2023-05-26 10:01:32 +02:00
Daniel Eklöf
7f26914583
wayland: ignore configure events for unmapped surfaces
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.
2023-02-25 09:22:20 +01:00
Craig Barnes
f19768e304 wayland: avoid passing NULL to log_msg() in wayl_reload_xcursor_theme()
This pointer ends up being passed to various printf-family functions,
where passing a NULL pointer for an "%s" format specifier invokes
undefined behaviour.
2023-01-06 23:43:51 +00:00
Daniel Eklöf
42c6af0914
wayland: force monitor DPI to 96 when it’s unreasonably high
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.
2022-11-04 17:49:01 +01:00
Daniel Eklöf
2910ca354c
wayland: use fp math all the way when calculating DPI
This fixes an FPE when the monitor’s physical width/height is so small
that the conversion from mm to inch resulted in inches being zero.
2022-11-04 17:42:52 +01:00
Craig Barnes
8f2bda6703 wayland: use BUG() instead of xassert(false)
The latter will expand to the former anyway, so we may as well provide
an explicit error message instead of "assertion failed: 'false'".
2022-11-01 21:04:22 +00:00
Daniel Eklöf
50ae277d90
wayland: don’t crash with a division-by-zero when monitor dimensions are negative
Some compositors set the physical dimensions to -1...
2022-09-23 20:31:08 +02:00
Daniel Eklöf
eafff70439
wayland: #ifdef on XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION
This enables us to compile against wayland-protocols < 1.25
2022-08-12 16:12:36 +02:00
Simon Ser
129e1a9b8e Add support for xdg_toplevel.wm_capabilities
See https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/122
2022-08-04 14:23:03 +02:00
Simon Ser
2f68b421bf Add no-op xdg_toplevel.configure_bounds handler
Next commit uses v5.
2022-08-03 13:50:13 +02:00
Daniel Eklöf
fabffd626b
wayland: log human readable SHM format names in debug builds 2022-06-20 18:58:40 +02:00
Daniel Eklöf
200c5cbc79
wayland: throttle xdg activation token requests for window urgency
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
2022-05-11 21:17:52 +02:00
Daniel Eklöf
ea1aac88db
url-mode: add support for XDG activation when opening URLs
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
2022-05-05 10:02:28 +02:00
Daniel Eklöf
24ee3dcc10
wayland: refactor: remove ‘struct config’ pointer from wayland struct
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
2022-04-17 16:34:04 +02:00
Daniel Eklöf
90a2ca966f
key-binding: new API, for handling sets of key bindings
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
2022-04-17 15:39:51 +02:00
Daniel Eklöf
78fcdc5787
render: implement ‘flash’ and search mode’s ‘dimming’ with a sub-surface
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.
2022-04-16 18:31:02 +02:00
Daniel Eklöf
129deaffa8
wayland: optionally disable pointer input on subsurfaces
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.
2022-04-16 17:41:14 +02:00
Daniel Eklöf
fbcebd4f1c
config: add [csd].hide-when-maximized=yes|no
When enabled, the CSD titlebar will be hidden when the window is
maximized.

Closes #1019
2022-04-16 11:45:50 +02:00
Daniel Eklöf
f9103d4381
wayland: add helper functions wayl_win_csd_{titlebar,borders}_visible() 2022-04-16 11:42:25 +02:00