Commit graph

330 commits

Author SHA1 Message Date
tokyo4j
eeaecba723 wayland: fix global listener for xdg_toplevel_icon_manager_v1 2025-05-24 19:06:29 +09:00
Daniel Eklöf
664cdcc65c
cursor-shape: add 'dnd-ask' and 'all-resize'
These (non-css) cursor shapes were added to the cursor-shape-v1
protocol in wayland-protocols 1.42.

We don't need (or use them at all) internally, but add them to the
list we use to translate from shape names to shape enums. This allows
users to set a custom shape (via OSC-22), while still using server
side cursors (i.e. no need to fallback to client-side cursors).

If we try to set a shape not implemented by the server, we get a
protocol error and foot exits. This is bad.

So, make sure we don't do that:

1. First, we need to explicitly bind v2 if implemented by the server
2. Track the bound version number in the wayland struct
3. When matching shape enum, skip shapes not supported in the
   currently bound version of the cursor-shape protocol
2025-05-22 06:59:33 +02:00
Daniel Eklöf
d266599881
wayland: configure: don't commit if we have a pending refresh
Currently, if the following occurs:

1. foot has AxB size
2. Compositor sends CxD size
3. foot detects a resize, acks and saves CxD, but doesn't redraw immediately
4. Compositor sends CxD size again (due to a toplevel state array
   change, for example)

Then foot will detect no resize occurred, and will do an "empty"
commit immediately.

In this particular case that's wrong, since we're effectively
acking+committing the initial AxB size.

Fix by only doing the immediate commit if there's no size
change **and** there's no pending refresh.

Note: normally, we'd resize and refresh+commit immediately, but if
we're waiting for a frame callback, then the refresh+commit will be
delayed (i.e. scheduled). This is what we're checking here.

Closes #2105
2025-05-21 13:07:49 +02:00
Daniel Eklöf
970e13db8d
config: tweak.surface-bit-depth: add support for 16-bit surfaces
This adds supports for 16-bit surfaces, using the new
PIXMAN_a16b16g16r16 buffer format. This maps to
WL_SHM_FORMAT_ABGR16161616 (little-endian).

Use the new 16-bit surfaces by default, when
gamma-correct-blending=yes.
2025-05-03 09:04:15 +02:00
Daniel Eklöf
5080e271c2
wayland: attempt to log protocol errors on failure to flush
When failing to flush, and the error is EPIPE, attempt to read and
dispatch events. This ensures protocol errors are logged.
2025-05-02 13:46:18 +02:00
Daniel Eklöf
237db6e771
wayland: always call wl_display_dispatch_pending() at least once, after reading
This fixes an issue where protocol errors aren't reported. I'm
guessing the read succeeds, but that prepare_read() _also_ succeeds
immediately, since there aren't any events to dispatch (only log the
protocol error).

By calling dispatch unconditionally, we ensure any error messages are
printed. Then we proceed to loop prepare_read() + dispatch_pending()
until the queue is empty.
2025-05-02 13:43:59 +02:00
Daniel Eklöf
e5a0755451
config: tweak.surface-bit-depth now defaults to 'auto'
When set to 'auto', use 10-bit surfaces if gamma-correct blending is
enabled, and 8-bit surfaces otherwise.

Note that we may still fallback to 8-bit surfaces (without disabling
gamma-correct blending) if the compositor does not support 10-bit
surfaces.

Closes #2082
2025-05-01 08:54:30 +02:00
Daniel Eklöf
b07ce56321
config: gamma-correct-blending: disable by default 2025-05-01 08:09:08 +02:00
Daniel Eklöf
23431e3ecf
wayland+input: add support for toplevel edge constraints
Edge constraints are new (not yet available in a wayland-protocols
release) toplevel states, acting as a complement to the existing tiled
states.

Tiled tells us we shouldn't draw shadows etc *outside our window
geometry*.

Constrained tells us the window cannot be resized in the constrained
direction.

This patch does a couple of things:

* Recognize the new states when debug logging

* Change is_top_left() etc to look at the new constrained state
  instead of the tiled state. These functions are used when both
  choosing cursor shape, and when determining if/how to resize a
  window on a CSD edge click-and-drag.

* Update cursor shape selection to use the default (left_ptr) shape
  when on a constrained edge (or corner).

* Update CSD resize triggering, to not trigger a resize when attempted
  on a constrained edge (or corner).

See
86750c99ed:

    An edge constraint is an complementery state to the tiled state,
    meaning that it's not only tiled, but constrained in a way that it
    can't resize in that direction.

    This typically means that the constrained edge is tiled against a
    monitor edge. An example configuration is two windows tiled next
    to each other on a single monitor. Together they cover the whole
    work area.

    The left window would have the following tiled and edge constraint
    state:

        [ tiled_top, tiled_right, tiled_bottom, tiled_left,
          constrained_top, constrained_bottom, constrained_left ]

    while the right window would have the following:

        [ tiled_top, tiled_right, tiled_bottom, tiled_left,
          constrained_top, constrained_bottom, constrained_right ]

    This aims to replace and deprecate the
    `gtk_surface1.configure_edges` event and the
    `gtk_surface1.edge_constraint` enum.
2025-04-07 13:41:37 +02:00
Dominique Martinet
091aa90f1a
wayland: handle xdg-shell edge constraints
wayland-protocols commit 86750c99ed06 ("xdg-shell: Add edge
constraints") added a few more enums to handle, making the build fail
with -Werror:
../wayland.c: In function ‘xdg_toplevel_configure’:
../wayland.c:878:9: error: enumeration value ‘XDG_TOPLEVEL_STATE_CONSTRAINED_LEFT’ not handled in switch [-Werror=switch]
  878 |         switch (*state) {
      |         ^~~~~~
../wayland.c:878:9: error: enumeration value ‘XDG_TOPLEVEL_STATE_CONSTRAINED_RIGHT’ not handled in switch [-Werror=switch]
../wayland.c:878:9: error: enumeration value ‘XDG_TOPLEVEL_STATE_CONSTRAINED_TOP’ not handled in switch [-Werror=switch]
../wayland.c:878:9: error: enumeration value ‘XDG_TOPLEVEL_STATE_CONSTRAINED_BOTTOM’ not handled in switch [-Werror=switch]

(This is not part of any release yet, but can be used when building with
the submodule)

From a quick look it sounds like the meaning is the same as tiling as
far as we are concerned so handle these as we do of tiling.
2025-04-07 13:03:30 +02:00
Daniel Eklöf
d48a1c53f5
meson: require wayland-protocols >= 1.41 2025-03-13 13:28:34 +01:00
Daniel Eklöf
ccf625b991
render: gamma-correct blending
This implements gamma-correct blending, which mainly affects font
rendering.

The implementation requires compile-time availability of the new
color-management protocol (available in wayland-protocols >= 1.41),
and run-time support for the same in the compositor (specifically, the
EXT_LINEAR TF function and sRGB primaries).

How it works: all colors are decoded from sRGB to linear (using a
lookup table, generated in the exact same way pixman generates it's
internal conversion tables) before being used by pixman. The resulting
image buffer is thus in decoded/linear format. We use the
color-management protocol to inform the compositor of this, by tagging
the wayland surfaces with the 'ext_linear' image attribute.

Sixes: all colors are sRGB internally, and decoded to linear before
being used in any sixels. Thus, the image buffers will contain linear
colors. This is important, since otherwise there would be a
decode/encode penalty every time a sixel is blended to the grid.

Emojis: we require fcft >= 3.2, which adds support for sRGB decoding
color glyphs. Meaning, the emoji pixman surfaces can be blended
directly to the grid, just like sixels.

Gamma-correct blending is enabled by default *when the compositor
supports it*. There's a new option to explicitly enable/disable it:
gamma-correct-blending=no|yes. If set to 'yes', and the compositor
does not implement the required color-management features, warning
logs are emitted.

There's a loss of precision when storing linear pixels in 8-bit
channels. For this reason, this patch also adds supports for 10-bit
surfaces. For now, this is disabled by default since such surfaces
only have 2 bits for alpha. It can be enabled with
tweak.surface-bit-depth=10-bit.

Perhaps, in the future, we can enable it by default if:

* gamma-correct blending is enabled
* the user has not enabled a transparent background
2025-03-05 18:45:01 +01:00
Daniel Eklöf
2a07a2e6b9
Add support for the new Wayland protocol xdg-system-bell
From the release notes:

    system bell - allowing e.g. terminal emulators to hand off system
    bell alerts to the compositor for among other things accessibility
    purposes

The new protocol is used when the new config option
bell.system=yes (and the compositor implements the protocol,
obviously).

The system bell is rung independent of whether the foot window has
keyboard focus or not (thus relying on compositor configuration to
determine whether anything should be done or not in response to the
bell).

The new option is enabled by default.
2025-01-17 10:21:50 +01:00
Daniel Eklöf
c6208a98c8
main: include toplevel-icon support in --version output 2024-09-13 09:04:18 +02:00
Daniel Eklöf
b34137dde3
toplevel-icon: set to app-id, instead of hardcoding to "foot"
And, special case "footclient", and map it to "foot".
2024-09-13 09:04:17 +02:00
Daniel Eklöf
0cb07027f2
wayland: set toplevel icon
If the xdg-toplevel-icon-v1 protocol is available, and we have the
corresponding manager global, set the toplevel icon to "foot".

Note: we do *not* provide any pixel data. This is by design; we want
to keep things simple.

To be able to provide pixel data, we would have to either:

* embed the raw pixel data in the foot binary
* link against either libpng or/and e.g. nanosvg, locate, at run-time,
  the paths to our own icons, and load them at run-time.
* link against either libpng or/and e.g. nanosvg, and, at run-time, do
  a full icon lookup. This would also require us to add a config option
  for which icon theme to use.

Of the two, I would prefer the first option. But, let's skip this
completely for now.

By providing the icon as a name, the compositor will have to lookup
the icon itself. Compositors supporting icons is likely to already
support this.

So what do we gain by implementing this protocol? Compositors no
longer has to parse .desktop files and map our app-id to find the icon
to use.

There's one question remaining. With this patch, the icon name is
hardcoded to "foot", just like our .desktop files. But, perhaps we
should use the app-id instead? And if so, should we also change the
icon when the app-id changes?

My gut feeling is, yes, we should use the app-id instead, and yes, we
should update the icon when the app-id is changed at run-time.
2024-09-13 09:04:17 +02:00
Daniel Eklöf
28a1c67dd5
wayland: bind the xdg-toplevel-icon manager global 2024-09-13 09:04:17 +02:00
Daniel Eklöf
69f56b86b7
wayland: add wayl_activate()
wayl_activate() takes an XDG activation token and does an XDG
activation request.
2024-07-23 07:17:21 +02:00
Daniel Eklöf
e11a4ab6af
wayland: #ifdef guard code related to wl_shm_release() 2024-07-18 14:27:40 +02:00
Daniel Eklöf
4f25e1ba9f
wayland: use wl_shm v2 if available 2024-07-18 08:23:25 +02:00
Daniel Eklöf
c45231ef89
input: don't reset the XKB compose state in keymap()
When the compositor sends a new keymap, don't reset the XKB compose
state.

This is done by initializing the XKB context, along with the compose
state, when binding the seat, instead of in keymap().

Then, in keymap(), simply stop destroying the old xkb state. Only
destroy, and re-create the keymap state.

Closes #1744
2024-06-22 08:00:13 +02:00
Daniel Eklöf
aea16ba5d2
input: implement wl_pointer::axis_value120()
This implements high resolution mouse wheel scroll events. A "normal"
scroll step corresponds to the value 120. Anything less than that is a
partial scroll step.

This event replaces axis_discrete(), when we bind wl_seat v8 (which we
now do, when available).

We calculate the number of degrees that is required to scroll a single
line, based off of the scrollback.multiplier value.

Each high-res event accumulates, until we have at least the number of
degress required to scroll one, or more lines.

The remaining degrees are kept, and added to in the next scroll event.

Closes #1738
2024-06-18 14:09:03 +02:00
Daniel Eklöf
3c96d0b68e
render: use single-pixel buffers for overlays, when possible
The unicode-mode, and flash overlays are single color buffers. This
means we can use the single-pixel buffer protocol.

It's undefined whether the compositor will release the buffer or not;
to make things easier, simply destroy the buffer as soon as we've
committed it.

Note that since compositors don't necessarily release single-pixel
buffers, we can't plug them into our own buffer interface. This means
we can't use buffer pointers to check if we can re-use the previous
buffer (i.e. we can skip comitting a new buffer), or if we have to
create a new one.

It's _almost_ enough to just check if the last overlay style is the
same as the current one. Except that that doesn't take window resizes
into account...
2024-05-22 13:48:46 +02:00
Daniel Eklöf
e753bb953b
wayland: remove has_wl_compositor_v6
We deviate slightly from the specification, in that we don't assume a
preferred buffer scale of 1. Instead, we "guess" the scale *until we
receive a surface_preferred_buffer_scale event.

Because of this, we don't need the has_wl_compositor_v6 member, as
it's enough to check if we have a non-zero 'preferred buffer scale'.
2024-04-12 15:35:25 +02:00
Daniel Eklöf
88a3b54ca3
wayland: only use the surface preferred scale if set by the compositor
Before this patch, we would, in some cases, fallback to the surface
preferred (not fractional) scaling, even though the compositor hadn't
actually published a preferred buffer scale; the presence of a v6
compositor interface doesn't mean we've actually received a preferred
scale yet.
2024-04-05 16:19:47 +02:00
Daniel Eklöf
578765ad83
wayland: skip loading cursor theme when using server side cursors
We don't need the client side cursor theme when using server side
cursors.
2024-03-16 15:36:44 +01:00
Daniel Eklöf
67f97cbca1
shm: use XRGB surfaces when we know we wont be using transparency 2024-02-21 16:29:10 +01:00
Daniel Eklöf
bc8c2e0112
wayland: regression: use correct scaling factor when calling render_resize()
When an output property (such as scaling factor) has changed, we need
to call render_resize() to ensure the window surface is correct (for
example, we may have to change its scale).

The width/height parameters are in *logical* pixels (i.e. already
scaled). For render_resize() to work correctly when the scale is being
changed, it needs to be called with *current* logical size. This means
we need to scale our current width/height using the *old* scaling
factor.
2024-02-07 16:22:33 +01:00
Daniel Eklöf
7999975016
Don't use fancy Unicode quotes, stick to ASCII 2024-02-06 12:36:45 +01:00
Andrew J. Hesford
21a8d832ce
feature: add resize-by-cells option to constrain window sizes...
...to multiples of the cell size, and preserve grid size when changing
fonts or display scales in floating windows.
2024-02-05 12:14:53 +01:00
Craig Barnes
e0f3703ae6
util: add streq() function and use in place of strcmp(...) == 0 2024-02-05 12:09:52 +01:00
Daniel Eklöf
43e27a8843
wayland: 'mode' is unused when LOG_ENABLE_DBG is not set 2024-01-24 20:00:18 +01:00
Leonardo Hernández Hernández
7e3da3007b
wayland: use wl_compositor version 6 when available 2024-01-24 20:00:18 +01:00
Daniel Eklöf
a2283c8229
wayland: surface_scale_explicit_width_height(): dont assert width/height are valid for scale, take 2
764248bb0d modified
wayl_surface_scale_explicit_width_height() to not assert the surface
size is valid for the given scaling factor. This, since that function
is only used when scaling a mouse pointer surface.

However, that commit only updated the code path run when fractional
scaling is available (i.e. when the compositor implements the
fractional-scale-v1 protocol).

The legacy code path, that does integer scaling, was still asserting
the surface width/height were divisible with the scaling factor.

For the same reasons this isn't true with fractional scaling
available, it's not true with integer scaling. Fix by skipping the
assertions.

This patch also converts the assertions to more verbose BUG() calls,
that prints more information on the numbers involved.

Closes #1573
2024-01-09 16:47:41 +01:00
Daniel Eklöf
883368572f
wayland: debug: log wm-capabilities as human-readable strings 2023-10-02 16:34:54 +02:00
Daniel Eklöf
b2963bbf80
changelog: crash when xdg token is set, but compositor does not support activation 2023-09-21 18:31:46 +02:00
Alyssa Ross
9257273d84
wayland: check activation supported before activating
It's possible for token to be set when the compositor doesn't support
activation, and this caused a segfault.  For example, this can happen
when overriding WAYLAND_DISPLAY to point to a compositor that doesn't
support activation, in a terminal running under one that does, and so
has set XDG_ACTIVATION_TOKEN.
2023-09-21 06:59:48 +00:00
CismonX
f0f0d02bf7
input: improve touch handling on pointer presense
No longer inhibits touch event handling when terminal window
has pointer focus.  Instead, inhibit touch event when at least
one pointer button is held down.

This change improves user experience when using foot with both
a mouse and a touchscreen.

Closes #1428.
2023-08-24 00:45:20 +08:00
Daniel Eklöf
698c5b54f3
wayland: cursor-shape-v1 is now always available
Since we're requiring wayland-protocols >= 1.32
2023-08-07 16:53:19 +02:00
Daniel Eklöf
7eee415b75
wayland: fractional-scale-v1 is now always available
Since we're requiring wayland-protocols >= 1.32
2023-08-07 16:53:19 +02:00
Daniel Eklöf
d59a4e7a77
wayland: xdg-activation is now always available
Since we're requiring wayland-protocols >= 1.32
2023-08-07 16:53:19 +02:00
Daniel Eklöf
764248bb0d
wayl_surface_scale_explicit_width_height(): don’t assert width/height are valid for scale
This function is only called directly when scaling the mouse
pointer. The mouse pointer is never guaranteed to have a valid width
and height, so skip the width/height assertions for it.
2023-07-29 08:18:00 +02:00
Daniel Eklöf
1782474481
fractional scaling: another round(!) of rounding fixes
* Ensure buffer sizes are valid. That is, ensure that
  size / scale * scale == size.
* Do size calculation of the window geometry in the same way we
  calculate the CSD offsets.
2023-07-28 16:03:13 +02:00
Daniel Eklöf
9d75c55146
wayland: don't try to use a non-existing viewporter interface
When instantiating the viewport for a pointer surface, we didn't first
check if the compositor implements the viewporter interface.

This triggered a crash when a) foot was compiled with fractional
scaling, and b) the compositor did not implement the viewporter
interface.

Closes #1444
2023-07-28 15:42:28 +02:00
Daniel Eklöf
613c61abb4
scaling: always round the scaling factor when converting to int
* In all calls to wl_subsurface_set_position()
* (wp_viewport_set_destination() already does this)
* Whenever we use the scale to calculate margins (search box,
  scrollback indicator etc)
* Since the scaling factor is stored as a float (and not a double),
  use roundf() instead of round()
2023-07-25 16:48:50 +02:00
Daniel Eklöf
0a61cfc3be
wayland: update terminals (fonts etc) on xdg_output_handle_done()
Monitor DPI depends on information from both the wl_output and the
xdg_output interfaces.

Before this patch, terminals were only updated after changes to the
wl_output interfaces (thus depending on xdg output changes being
pushed by the compositor before wl_output changes).

That assumption (xdg_output happening before wl_output) isn’t always
true.

This patch fixes the issue by updating the terminals in the
xdg_output’s “done” event.

Closes #1431
2023-07-23 20:12:13 +02:00
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