Commit graph

85 commits

Author SHA1 Message Date
Daniel Eklöf
20923bb2e8
grid: refactor: first step towards a more generic range handling 2024-06-26 18:39:23 +02:00
Daniel Eklöf
8716ca5784
url-mode: disable IME mode while URL-mode is active
This prevents the IME from stealing "our" key-presses, and thus
preventing the user from opening URLs.

Closes #1718, hopefully.
2024-05-21 08:37:39 +02:00
Daniel Eklöf
7999975016
Don't use fancy Unicode quotes, stick to ASCII 2024-02-06 12:36:45 +01:00
Daniel Eklöf
0aefc2c65d
input: remove the concept of "significant" modifiers
For the purpose of matching key bindings, "significant" modifiers are
no more.

We're really only interested in filtering out "locked"
modifiers. We're already doing this, so there's no need to *also*
match against a set of "significant" modifiers.

Furthermore, we *never* want to consider locked keys (e.g. when
emitting escapes to the client application), thus we can filter those
out already when retrieving the set of active modifiers.

The exception is the kitty keyboard protocol, which has support for
CapsLock and NumLock. Since we're already re-retrieving the "consumed"
modifiers (using the GTK style, rather than normal "XKB" style, to
better match the kitty terminal), we might as well re-retrieve the
effective modifiers as well.
2024-02-06 11:08:42 +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
58d967b2f3
Codespell fixes 2023-10-03 14:11:55 +02:00
Daniel Eklöf
54722369d8
url-mode: don't strip the file:// prefix from localhost URIs
Before this patch, the file://<host> prefix was stripped from URIs,
when the hostname matched the current host (that is, for "local"
URLs).

Unfortunately, the way this was done caused other parts of the URI to
be stripped as well. For example, the 'query' and 'fragment' parts.

This patch simply removes all special casing of file:// URIs.

Since the URL is passed to a generic opener (i.e. we don't have a
special opener application for file:// URIs), the opener helper must
handle the file:// prefix anyway.

Closes #1474
2023-09-21 18:32:57 +02:00
Daniel Eklöf
4f3f614457
url-mode: handle wide chars and grapheme clusters when auto-detecting URLs
* Skip spacer cells. This fixes an issue where characters following a
  double-width character weren't detect properly.

* Unpack grapheme clusters (i.e. cells with multiple codepoints), and
  iterate all their codepoints.

Closes #1465
2023-08-21 16:26:18 +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
3b41379be4
quirks: sway does not damage surface beneath sub-surface, when unmapped
When unmapping a sub-surface, Sway <= 1.8 does not damage the surface
beneath the sub-surface.

https://github.com/swaywm/sway/issues/6960

The workaround is to manually damage the main surface. Previously,
this was done when exiting scrollback search, and after the ‘flash’
OSC. But other sub-surfaces, that may also be unmapped, did not.

This patch adds a quirk handler that does this, and calls it when:

* Exiting scrollback search
* Ending the ‘flash’ OSC
* Exiting unicode input mode
* Clearing URL labels
* Removing the scrollback position indicator

Closes #1335
2023-05-12 14:51:05 +02:00
Daniel Eklöf
76d494484f
url-mode: tag cells after snapshot:ing the grid
Before this patch, hyperlinked cells were tagged with the “URL”
attribute (thus instructing the renderer to draw an
underline) *before* the grid was snapshot.

When exiting URL mode, the cells were once again updated, this time
removing the URL attribute.

But what if an escape sequence had modified the grid _while we were in
URL mode_? Depending on the sequence, it could move cells around in
such a way, that when exiting URL mode, the affected cells weren’t
updated correctly. I.e. we left some cells with the URL attribute
still set.

The fix is simple: tag cells in the snapshot:ed grid only (which isn’t
affected by any escape sequence received while in URL mode). Not in
the *actual* grid (which _is_ affected).
2022-11-30 10:51:45 +01:00
Daniel Eklöf
c753cf8f45
url-mode: connect osc-8 links only when both ID and URI matches
Before this, two OSC-8 links with a matching ID would be connected
even if their URIs weren’t the same. This is against the spec:

  The same id is only used for connecting character cells whose URIs
  is also the same. Character cells pointing to different URIs should
  never be underlined together when hovering over.

https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda#hover-underlining-and-the-id-parameter
2022-08-30 17:55:14 +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
dd03e10c6c
url-mode: allow locked modifiers while handling label letter input
This fixes an issue where labels couldn’t be activated if e.g. NumLock
was enabled.
2022-04-20 21:50:49 +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
501a9fbb5e
url-mode: add a key binding that enables “persistent” URL mode
This is an alternative to ‘show-urls-launch’, where we stay in URL
mode after activating an URL.

Closes #964
2022-04-17 11:24:27 +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
Merlin Büge
5539eac590
fix some small typos 2022-04-13 09:41:10 +02:00
Daniel Eklöf
5b1f1602bc
refactor: add a ‘range’ struct, grouping a start and end coord together 2022-04-09 15:09:02 +02:00
Daniel Eklöf
1e63dddb89
input: don’t allow non-significant modifiers when matching untranslated symbols
When matching “untranslated” bindings (by matching the base symbol of
the key, e.g. ctrl+shift+2 in US layout), require that no
non-significant modifiers are active.

This fixes an issue where AltGr was “ignored”, and would cause certain
combinations to match a key binding.

Example: ctrl+altgr+0, on many European layouts matched against the
default ctrl+0 (reset the font size), instead of emitting ^]

To make this work, we now need to filter out “locked”
modifiers (e.g. NumLock and CapsLock). Otherwise having e.g. NumLock
active would prevent *all* untranslated matching to fail.

Closes #983
2022-03-20 13:29:29 +01:00
Daniel Eklöf
fed90646d3
input/search/url: pass pointer-to key-binding struct to execute() 2022-02-09 17:51:05 +01:00
Daniel Eklöf
dcd79065c8
wayland: unify key- and mouse-binding structs 2022-02-09 17:51:04 +01:00
Daniel Eklöf
e0227266ca
fcft: adapt to API changes in fcft-3.x
Fcft no longer uses wchar_t, but plain uint32_t to represent
codepoints.

Since we do a fair amount of string operations in foot, it still makes
sense to use something that actually _is_ a string (or character),
rather than an array of uint32_t.

For this reason, we switch out all wchar_t usage in foot to
char32_t. We also verify, at compile-time, that char32_t used
UTF-32 (which is what fcft expects).

Unfortunately, there are no string functions for char32_t. To avoid
having to re-implement all wcs*() functions, we add a small wrapper
layer of c32*() functions.

These wrapper functions take char32_t arguments, but then simply call
the corresponding wcs*() function.

For this to work, wcs*() must _also_ be UTF-32 compatible. We can
check for the presence of the  __STDC_ISO_10646__ macro. If set,
wchar_t is at least 4 bytes and its internal representation is UTF-32.

FreeBSD does *not* define this macro, because its internal wchar_t
representation depends on the current locale. It _does_ use UTF-32
_if_ the current locale is UTF-8.

Since foot enforces UTF-8, we simply need to check if __FreeBSD__ is
defined.

Other fcft API changes:

* fcft_glyph_rasterize() -> fcft_codepoint_rasterize()
* font.space_advance has been removed
* ‘tags’ have been removed from fcft_grapheme_rasterize()
* ‘fcft_log_init()’ removed
* ‘fcft_init()’ and ‘fcft_fini()’ must be explicitly called
2022-02-05 17:00:54 +01:00
Daniel Eklöf
ccee08a393
osc8: uri ranges: use a dynamically re-sizable array instead of a tllist 2021-11-26 20:09:15 +01:00
Daniel Eklöf
0c03e9a766
config: add url.uri-characters
This option specifies the characters allowed in the auto-detected
URLs.

Any character not in this set constitutes an URL delimiter, and will
never be included in auto-detected URLs.

This option does not affect OSC-8 URLs.

Closes #654
2021-08-09 18:25:36 +02:00
Daniel Eklöf
31fad58465
url-mode: use shm_get_many()
If we have lots of URLs, we use up a *lot* of SHM buffers (and thus
pools). Each and every one is a single mmap(), of at least 4K.

Since all URL labels are created and destroyed at the same time, it
makes sense to use a single pool for all buffers.

To do this, we must now do two passes; first one to generate the
actual string (label content), and to calculate the label sizes.

Then we use this information to allocate all SHM buffers at once, from
the same pool.

Finally, we iterate the URLs again, this time to actually render them.
2021-07-15 18:39:41 +02:00
Daniel Eklöf
f030c87ee6
url-mode: abort when running into un-allocated scrollback memory
When tagging URL cells (in preparation for rendering URL mode), we
loop the URL’s entire range, setting the `url` attribute of all cells,
and dirtying the rows.

It is possible to create URLs that are invalid, and wrap around the
scrollback, even though the scrollback hasn’t yet been filled. For
example, by starting an OSC-8 URL, moving the cursor, and then closing
the OSC-8 URL.

These URLs are invalid, but are still rendered just fine. “Fine” being
relative - they will typically fill the entire screen. But at least
that’s a very clear indication for the user that’s something is wrong.

The problem is when we hit un-allocated scrollback rows. We didn’t
check for NULL rows, and crashed.

This has now been fixed.
2021-07-11 11:31:11 +02:00
Daniel Eklöf
cf6d04f9f2
url-mode: fix crash when removing duplicate and/or overlapping URLs
Removing overlaping and duplicated URLs is done by running two nested
loops, that both iterate the same URL list.

When a duplicate is found, one of the URLs is destroyed and removed
from the list.

Deleting and removing an item *is* safe, but only as long as _no
other_ iterator has references to it.

In this case, if we remove an item from e.g. the inner iterator, we’ll
crash if the outer iterator’s *next* item is the item being removed.

Closes #627
2021-07-11 10:06:12 +02:00
Daniel Eklöf
0a6e7e6167
url-mode: purge SHM pixmaps when destroying URLs
Unlike other surface types, the SHM cookie depends on the address of
each URL instance. This means if we enable, disable, and then enable
URL mode again (thus showing exactly the same URLs as the first time),
the URLs will have new addresses, and thus the old SHM pixmaps will
not get purged automatically.

So, manually purge them when destroying the URLs.
2021-07-11 09:59:17 +02:00
Daniel Eklöf
974c3acd78
url-mode: off-by-one error in end-point column of auto-detected URLs
When an auto-detected URL ended *on* the right-most column, the URL
endpoint was off by one, resulting in the underline in URL mode being
one character short.
2021-06-02 08:11:14 +02:00
Daniel Eklöf
a9e8ba0932
url-mode: codespell 2021-05-22 17:08:14 +02:00
Daniel Eklöf
5605eb9040
url-mode: remove overlapping URLs, not just duplicates
echo -e '\e]8;;https://www.foo.bar\e\\https://www.foo\e]8;;\e\\.bar'

will produce an OSC-8 URL (https://www.foo) that is slightly shorter
than the auto-detected one (https://www.foo.bar).

This produces strange results in URL mode. For example, if
url.osc8-underline=always, the OSC8 underline will be removed when
url-mode is exited.

This patch changes the behavior so that auto-detected URLs that
overlap OSC-8 URLs are removed.

Note that OSC-8 URLs cannot overlap with each other, and that
auto-detected URLs also cannot overlap with each other.
2021-05-22 16:42:43 +02:00
Daniel Eklöf
53516aceec
config: add url.protocols
This makes the protocols recognized by auto-detected URLs
configurable.

Closes #531
2021-05-22 14:50:47 +02:00
Daniel Eklöf
0f483d65ce
config: move url-mode related options to a dedicated section, ‘url’ 2021-05-22 14:50:47 +02:00
Daniel Eklöf
be980a6282
url-mode: fix auto-detection of URLs in the top corner of the viewport
The ‘proto_chars’ variable is kind of like a FIFO, where characters
from the grid is pushed to the back of it. I.e. the last <n> bytes are
at the *end* of the array.

This was what the protocol matching logic expected. However, it was
only true after reading ‘max_prot_len’ characters from the
grid. Before that, the last <n> bytes from the grid was in
the *beginning* of ‘proto_chars’.

This meant we did not detect URLs starting in the top left corner of
the viewport. Test case:

  foot sh -c "echo http://test.com && sleep 9999"
2021-03-06 13:06:54 +01:00
Daniel Eklöf
93b02cf2b8
url-mode: ignore keys with modifiers 2021-03-04 09:43:44 +01:00
Daniel Eklöf
5e64e06a55
input: rewrite of how we match foot’s own key bindings
Bindings are matched in one out of three ways:

* By translated (by XKB) symbols
* By untranslated symbols
* By raw key codes

A translated symbol is affected by pressed modifiers, some of which
can be “consumed”. Consumed modifiers to not partake in the comparison
with the binding’s modifiers. In this mode, ctrl+shift+2 maps to
ctrl+@ on a US layout.

Untranslated symbols, or un-shifted symbols refer to the “base” symbol
of the pressed key, i.e. it’s unaffected by modifiers. In this mode,
consumed modifiers *do* partake in the comparison with the binding’s
modifiers, and ctrl+shift+2 maps to ctrl+shift+2 on a US layout.

More examples: ctrl+shift+u maps to ctrl+U in the translated lookup,
while ctrl+shift+u maps to ctrl+shift+u in the untranslated lookup.

Finally, we also match raw key codes. This allows our bindings to work
using the same physical keys when the user switches between latin and
non-latin layouts.

This means key bindings in foot.ini *must* not include both +shift+
and a *shifted* key. I.e. ctrl+shift+U is not a valid combo as it
cannot be triggered. Unfortunately, this was how you were supposed to
write bindings up until now... so, we try to detect such bindings, log
a deprecation warning and then “fix” the binding for the user.

When specifying bindings in foot.ini, both ctrl+U and ctrl+shift+u are
valid, and will work. The latter is preferred though, since we cannot
detect the raw key code for the former variant. Personally, I also
prefer the latter one because it is more explicit; it’s more obvious
which keys are involved.

However, in some cases it makes more sense to use the other
variant. Typically for non-letter combos.
2021-03-04 09:43:43 +01:00
Daniel Eklöf
b87b8f1170
Revert "url-mode: ignore keys with modifiers"
This reverts commit e5cd09bf3f.

This needs to be applied on the consume-modifiers-for-key-bindings
branch.
2021-03-04 09:34:37 +01:00
Daniel Eklöf
e5cd09bf3f
url-mode: ignore keys with modifiers 2021-03-04 08:54:38 +01:00
Daniel Eklöf
ae0f20a536
url-mode: damage current view before entering URL mode
Clear scroll damage and damage the entire viewport before entering URL
mode. This will cause us to do a full screen redraw both when entering
URL mode, and later when exiting it.

Clearing the scroll damage is necessary to ensure we don’t apply it
twice (once for the snapshot:ed grid, and later again for the real
grid), as that would result in an incorrect pixmap.

But, since we’ve cleared the scroll damage, we need to damage the
entire view to ensure we redraw the contents correctly.
2021-02-26 09:15:46 +01:00
Daniel Eklöf
bc71e06d5f
url-mode: dirty the “last cursor” cell before taking the snapshot
This ensures the “last cursor” cell is re-drawn (without a cursor, if
the cursor has moved), both in the snapshot:ed grid, and later, when
we switch back to the real grid.

We must also be careful and reset term->render.last_cursor.row
both when *entering* and *leaving* URL mode, to ensure it doesn’t
point to an invalid row.
2021-02-26 09:15:45 +01:00
Daniel Eklöf
aa10cd54ea
url-mode: no need to damage the entire view when exiting URL mode
The renderer will simply apply *all* accumulated damage at once, when
we render the real grid.
2021-02-26 09:15:45 +01:00
Daniel Eklöf
54b5ae95c1
url-mode: snapshot screen state when entering URL mode
Previously, we automatically exited URL mode whenever we received data
on the PTY. This was done since we don’t know _what_ has changed on
the screen, and we don’t want to display misleading jump labels.

However, this becomes a problem in curses-like applications that
periodically updates part of the screen. For example, a statusbar with
a clock.

This patch changes this behavior; instead of cancelling URL mode when
receiving PTY data, we snapshot the grid when entering URL mode.

When *rendering*, we use the snapshot:ed grid, while PTY updates
modify the “real” grid.

Snapshot:ing the grid means taking a full/deep copy of the current
grid, including sixel images etc.

Finally, it isn’t necessary to “damage” the entire view
when *entering* URL mode, since we’re at that point the renderer is in
sync with the grid. But we *do* need to damage the entire view when
exiting URL mode, since the grid changes on the “real” grid hasn’t
been tracked by the renderer.
2021-02-26 09:15:45 +01:00
Daniel Eklöf
8365fde980
url-mode: redirect stdin/stdout/stderr to /dev/null when opening an URL
This fixex an issue where TUI programs started in the parent
terminal (when running nested terminals).
2021-02-24 21:30:58 +01:00
Daniel Eklöf
7ee5247525
url-mode: disable debug logging 2021-02-23 14:59:54 +01:00
Daniel Eklöf
11464a65de
url-mode: use the same key combo for all occurrences of an URL 2021-02-21 20:15:33 +01:00
Daniel Eklöf
2074f8b656
urls: OSC-8 URLs can now optionally be underlined outside of url-mode
This patch adds a new configuration option,
‘osc8-underline=url-mode|always’.

When set to ‘url-mode’, OSC-8 URLs are only
highlighted (i.e. underlined) in url-mode, just like auto-detected
URLs.

When set to ‘always’, they are always underlined, regardless of mode,
and regardless of their other attributes.

This is implemented by tagging collected URLs with a boolean,
instructing urls_render() and urls_reset() whether they should update
the cells’ ‘url’ attribute or not.

The OSC-8 collecter sets this based on the value of ‘osc8-underline’.

Finally, when closing an OSC-8 URL, the cells are immediately tagged
with the ‘url’ attribute if ‘osc8-underline’ is set to ‘always’.
2021-02-21 20:15:32 +01:00
Daniel Eklöf
06a9ffa763
urls: add key binding that toggles whether URLs are displayed on jump-label
By default, the URL isn’t shown on the jump-label. For auto-detect
URLs, doing so is virtually always useless, as the URL is already
visible in the grid.

For OSC-8 URLs however, the URL is often _not_ visible in the
grid. Many times, seeing the URL is still not needed (if you’re doing
‘ls --hyperlink’, you already know what the URIs are).

But it is still useful to have a way to show the URLs.

This patch adds a new key binding action that can be used in url-mode
to toggle the URL on and off in the jump label.

It is bound to ctrl+t by default.
2021-02-21 20:15:31 +01:00
Daniel Eklöf
cc43c1b704
urls: remove free-form ‘text’ member from URL struct 2021-02-21 20:15:31 +01:00
Daniel Eklöf
cf651d361f
url-mode: remove duplicate URLs
Remove URLs with the same start and end coordinates. Such duplicate
URLs can be created by emitting an OSC-8 URL with matching grid
content:

  \E]8;;http://foo\E\\http://foo\E]8;;\E\\
2021-02-21 20:15:31 +01:00