2019-06-15 22:22:44 +02:00
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
|
|
#include <stdint.h>
|
|
|
|
|
|
#include <stdbool.h>
|
|
|
|
|
|
#include <stddef.h>
|
|
|
|
|
|
|
2019-06-19 10:04:47 +02:00
|
|
|
|
#include <threads.h>
|
2019-07-29 20:13:26 +02:00
|
|
|
|
#include <semaphore.h>
|
2019-06-19 10:04:47 +02:00
|
|
|
|
|
2020-08-20 19:25:35 +02:00
|
|
|
|
#if defined(FOOT_GRAPHEME_CLUSTERING)
|
|
|
|
|
|
#include <utf8proc.h>
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
2019-12-01 13:43:51 +01:00
|
|
|
|
#include <tllist.h>
|
2019-12-01 14:03:24 +01:00
|
|
|
|
#include <fcft/fcft.h>
|
2019-12-01 13:43:51 +01:00
|
|
|
|
|
composed: store compose chains in a binary search tree
The previous implementation stored compose chains in a dynamically
allocated array. Adding a chain was easy: resize the array and append
the new chain at the end. Looking up a compose chain given a compose
chain key/index was also easy: just index into the array.
However, searching for a pre-existing chain given a codepoint sequence
was very slow. Since the array wasn’t sorted, we typically had to scan
through the entire array, just to realize that there is no
pre-existing chain, and that we need to add a new one.
Since this happens for *each* codepoint in a grapheme cluster, things
quickly became really slow.
Things were ok:ish as long as the compose chain struct was small, as
that made it possible to hold all the chains in the cache. Once the
number of chains reached a certain point, or when we were forced to
bump maximum number of allowed codepoints in a chain, we started
thrashing the cache and things got much much worse.
So what can we do?
We can’t sort the array, because
a) that would invalidate all existing chain keys in the grid (and
iterating the entire scrollback and updating compose keys is *not* an
option).
b) inserting a chain becomes slow as we need to first find _where_ to
insert it, and then memmove() the rest of the array.
This patch uses a binary search tree to store the chains instead of a
simple array.
The tree is sorted on a “key”, which is the XOR of all codepoints,
truncated to the CELL_COMB_CHARS_HI-CELL_COMB_CHARS_LO range.
The grid now stores CELL_COMB_CHARS_LO+key, instead of
CELL_COMB_CHARS_LO+index.
Since the key is truncated, collisions may occur. This is handled by
incrementing the key by 1.
Lookup is of course slower than before, O(log n) instead of
O(1).
Insertion is slightly slower as well: technically it’s O(log n)
instead of O(1). However, we also need to take into account the
re-allocating the array will occasionally force a full copy of the
array when it cannot simply be growed.
But finding a pre-existing chain is now *much* faster: O(log n)
instead of O(n). In most cases, the first lookup will either
succeed (return a true match), or fail (return NULL). However, since
key collisions are possible, it may also return false matches. This
means we need to verify the contents of the chain before deciding to
use it instead of inserting a new chain. But remember that this
comparison was being done for each and every chain in the previous
implementation.
With lookups being much faster, and in particular, no longer requiring
us to check the chain contents for every singlec chain, we can now use
a dynamically allocated ‘chars’ array in the chain. This was
previously a hardcoded array of 10 chars.
Using a dynamic allocated array means looking in the array is slower,
since we now need two loads: one to load the pointer, and a second to
load _from_ the pointer.
As a result, the base size of a compose chain (i.e. an “empty” chain)
has now been reduced from 48 bytes to 32. A chain with two codepoints
is 40 bytes. This means we have up to 4 codepoints while still using
less, or the same amount, of memory as before.
Furthermore, the Unicode random test (i.e. write random “unicode”
chars) is now **faster** than current master (i.e. before text-shaping
support was added), **with** test-shaping enabled. With text-shaping
disabled, we’re _even_ faster.
2021-06-24 13:17:07 +02:00
|
|
|
|
#include "composed.h"
|
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
|
|
|
|
#include "config.h"
|
2021-01-15 20:39:45 +00:00
|
|
|
|
#include "debug.h"
|
2019-10-28 18:25:19 +01:00
|
|
|
|
#include "fdm.h"
|
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
|
|
|
|
#include "key-binding.h"
|
2020-08-04 23:28:16 +01:00
|
|
|
|
#include "macros.h"
|
2020-05-21 20:17:29 +02:00
|
|
|
|
#include "reaper.h"
|
shm: refactor: move away from a single, global, buffer list
Up until now, *all* buffers have been tracked in a single, global
buffer list. We've used 'cookies' to separate buffers from different
contexts (so that shm_get_buffer() doesn't try to re-use e.g. a
search-box buffer for the main grid).
This patch refactors this, and completely removes the global
list.
Instead of cookies, we now use 'chains'. A chain tracks both the
properties to apply to newly created buffers (scrollable, number of
pixman instances to instantiate etc), as well as the instantiated
buffers themselves.
This means there's strictly speaking not much use for shm_fini()
anymore, since its up to the chain owner to call shm_chain_free(),
which will also purge all buffers.
However, since purging a buffer may be deferred, if the buffer is
owned by the compositor at the time of the call to shm_purge() or
shm_chain_free(), we still keep a global 'deferred' list, on to which
deferred buffers are pushed. shm_fini() iterates this list and
destroys the buffers _even_ if they are still owned by the
compositor. This only happens at program termination, and not when
destroying a terminal instance. I.e. closing a window in a “foot
--server” does *not* trigger this.
Each terminal instatiates a number of chains, and these chains are
destroyed when the terminal instance is destroyed. Note that some
buffers may be put on the deferred list, as mentioned above.
2021-07-16 16:48:49 +02:00
|
|
|
|
#include "shm.h"
|
2019-10-27 13:06:39 +01:00
|
|
|
|
#include "wayland.h"
|
2019-06-19 14:17:43 +02:00
|
|
|
|
|
2021-11-20 16:29:57 +01:00
|
|
|
|
enum color_source {
|
|
|
|
|
|
COLOR_DEFAULT,
|
|
|
|
|
|
COLOR_BASE16,
|
|
|
|
|
|
COLOR_BASE256,
|
|
|
|
|
|
COLOR_RGB,
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2019-07-10 18:48:46 +02:00
|
|
|
|
/*
|
|
|
|
|
|
* Note: we want the cells to be as small as possible. Larger cells
|
|
|
|
|
|
* means fewer scrollback lines (or performance drops due to cache
|
2019-08-02 18:19:07 +02:00
|
|
|
|
* misses)
|
|
|
|
|
|
*
|
|
|
|
|
|
* Note that the members are laid out optimized for x86
|
|
|
|
|
|
*/
|
2019-06-16 16:44:42 +02:00
|
|
|
|
struct attributes {
|
2021-04-17 22:11:14 +02:00
|
|
|
|
bool bold:1;
|
|
|
|
|
|
bool dim:1;
|
|
|
|
|
|
bool italic:1;
|
|
|
|
|
|
bool underline:1;
|
|
|
|
|
|
bool strikethrough:1;
|
|
|
|
|
|
bool blink:1;
|
|
|
|
|
|
bool conceal:1;
|
|
|
|
|
|
bool reverse:1;
|
2019-08-02 18:19:07 +02:00
|
|
|
|
uint32_t fg:24;
|
2019-07-10 18:48:46 +02:00
|
|
|
|
|
2021-04-17 22:11:14 +02:00
|
|
|
|
bool clean:1;
|
2021-11-20 16:29:57 +01:00
|
|
|
|
enum color_source fg_src:2;
|
|
|
|
|
|
enum color_source bg_src:2;
|
2021-06-15 11:45:27 +02:00
|
|
|
|
bool confined:1;
|
selection: don’t require two cell attr bits for selection updating
When updating the selection (i.e when changing it - adding or removing
cells to the selection), we need to do two things:
* Unset the ‘selected’ bit on all cells that are no longer selected.
* Set the ‘selected’ bit on all cells that *are* selected.
Since it’s quite tricky to calculate the difference between the “old”
and “new” selection, this is done by first un-selecting the old
selection, and then selecting the new, updated selection. I.e. first
we clear the ‘selected’ bit from *all* cells, and then we re-set it on
those cells that are still selected.
This process also dirties the cells, to make sure they are
re-rendered (needed to reflect their new selected/un-selected status).
To avoid dirtying *all* previously selected, and newly selected cells,
we have used an algorithm that first runs a “pre-pass”, marking all
cells that *will* be selected as such. The un-select pass would then
skip (no dirty) cells that have been marked by the pre-pass. Finally,
the select pass would only dirty cells that have *not* been marked by
the pre-pass.
In short, we only dirty cells whose selection state have *changed*.
To do this, we used a second ‘selected’ bit in the cell attribute
struct.
Those bits are *scarce*.
This patch implements an alternative algorithm, that frees up one of
the two ‘selected’ bits.
This is done by lazy allocating a bitmask for the entire grid. The
pre-pass sets bits in the bitmask. Thus, after the pre-pass, the
bitmask has set bits for all cells that *will* be selected.
The un-select pass simply skips cells with a one-bit in the
bitmask. Cells without a one-bit in the bitmask are dirtied, and their
‘selected’ bit is cleared.
The select-pass doesn’t even have to look at the bitmask - if the cell
already has its ‘selected’ bit set, it does nothing. Otherwise it sets
it and dirties the cell.
The bitmask is implemented as an array of arrays of 64-bit
integers. Each outer element represents one row. These pointers are
calloc():ed before starting the pre-pass.
The pre-pass allocates the inner arrays on demand.
The unselect pass is designed to handle both the complete absence of a
bitmask, as well as row entries being NULL (both means the cell
is *not* pre-marked, and will thus be dirtied).
2021-08-13 17:45:09 +02:00
|
|
|
|
bool selected:1;
|
2021-04-17 22:11:14 +02:00
|
|
|
|
bool url:1;
|
2019-08-02 18:19:07 +02:00
|
|
|
|
uint32_t bg:24;
|
|
|
|
|
|
};
|
2021-04-17 22:11:14 +02:00
|
|
|
|
static_assert(sizeof(struct attributes) == 8, "VT attribute struct too large");
|
2019-06-16 16:44:42 +02:00
|
|
|
|
|
2021-06-24 19:15:53 +02:00
|
|
|
|
/* Last valid Unicode code point is 0x0010FFFFul */
|
|
|
|
|
|
#define CELL_COMB_CHARS_LO 0x00200000ul
|
|
|
|
|
|
#define CELL_COMB_CHARS_HI (CELL_COMB_CHARS_LO + 0x3fffffff)
|
|
|
|
|
|
#define CELL_SPACER (CELL_COMB_CHARS_HI + 1)
|
2020-07-14 16:49:11 +02:00
|
|
|
|
|
2019-06-16 16:44:42 +02:00
|
|
|
|
struct cell {
|
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
2021-08-21 14:50:42 +02:00
|
|
|
|
char32_t wc;
|
2019-06-16 16:44:42 +02:00
|
|
|
|
struct attributes attrs;
|
2019-08-02 18:19:07 +02:00
|
|
|
|
};
|
|
|
|
|
|
static_assert(sizeof(struct cell) == 12, "bad size");
|
2019-06-15 22:22:44 +02:00
|
|
|
|
|
2019-06-25 20:11:08 +02:00
|
|
|
|
struct scroll_region {
|
|
|
|
|
|
int start;
|
|
|
|
|
|
int end;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2019-07-08 13:57:31 +02:00
|
|
|
|
struct coord {
|
2019-06-29 21:15:32 +02:00
|
|
|
|
int col;
|
2019-07-08 13:57:31 +02:00
|
|
|
|
int row;
|
2019-06-29 21:15:32 +02:00
|
|
|
|
};
|
|
|
|
|
|
|
2022-04-09 15:09:02 +02:00
|
|
|
|
struct range {
|
|
|
|
|
|
struct coord start;
|
|
|
|
|
|
struct coord end;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2019-11-17 09:44:31 +01:00
|
|
|
|
struct cursor {
|
|
|
|
|
|
struct coord point;
|
2019-11-17 09:46:20 +01:00
|
|
|
|
bool lcf;
|
2019-11-17 09:44:31 +01:00
|
|
|
|
};
|
|
|
|
|
|
|
2019-10-29 21:09:37 +01:00
|
|
|
|
enum damage_type {DAMAGE_SCROLL, DAMAGE_SCROLL_REVERSE,
|
|
|
|
|
|
DAMAGE_SCROLL_IN_VIEW, DAMAGE_SCROLL_REVERSE_IN_VIEW};
|
|
|
|
|
|
|
2019-06-19 14:17:43 +02:00
|
|
|
|
struct damage {
|
|
|
|
|
|
enum damage_type type;
|
2020-04-26 12:47:19 +02:00
|
|
|
|
struct scroll_region region;
|
|
|
|
|
|
int lines;
|
2019-06-19 14:17:43 +02:00
|
|
|
|
};
|
|
|
|
|
|
|
2021-02-13 12:31:55 +01:00
|
|
|
|
struct row_uri_range {
|
|
|
|
|
|
int start;
|
|
|
|
|
|
int end;
|
2021-02-13 13:44:58 +01:00
|
|
|
|
uint64_t id;
|
2021-02-13 12:31:55 +01:00
|
|
|
|
char *uri;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct row_data {
|
2021-11-26 19:55:27 +01:00
|
|
|
|
struct {
|
|
|
|
|
|
struct row_uri_range *v;
|
|
|
|
|
|
uint32_t size;
|
|
|
|
|
|
uint32_t count;
|
|
|
|
|
|
} uri_ranges;
|
2021-02-13 12:31:55 +01:00
|
|
|
|
};
|
|
|
|
|
|
|
2019-07-08 13:57:31 +02:00
|
|
|
|
struct row {
|
|
|
|
|
|
struct cell *cells;
|
osc: add support for OSC 133;A (prompt markers)
This patch adds support for the OSC-133;A sequence, introduced by
FinalTerm and implemented by iTerm2, Kitty and more. See
https://iterm2.com/documentation-one-page.html#documentation-escape-codes.html.
The shell emits the OSC just before printing the prompt. This lets the
terminal know where, in the scrollback, there are prompts.
We implement this using a simple boolean in the row struct ("this row
has a prompt"). The prompt marker must be reflowed along with the text
on window resizes.
In an ideal world, erasing, or overwriting the cell where the OSC was
emitted, would remove the prompt mark. Since we don't store this
information in the cell struct, we can't do that. The best we can do
is reset it in erase_line(). This works well enough in the "normal"
screen, when used with a "normal" shell. It doesn't really work in
fullscreen apps, on the alt screen. But that doesn't matter since we
don't support jumping between prompts on the alt screen anyway.
To be able to jump between prompts, two new key bindings have been
added: prompt-prev and prompt-next, bound to ctrl+shift+z and
ctrl+shift+x respectively.
prompt-prev will jump to the previous, not currently visible, prompt,
by moving the viewport, ensuring the prompt is at the top of the
screen.
prompt-next jumps to the next prompt, visible or not. Again, by moving
the viewport to ensure the prompt is at the top of the screen. If
we're at the bottom of the scrollback, the viewport is instead moved
as far down as possible.
Closes #30
2022-06-15 18:44:23 +02:00
|
|
|
|
struct row_data *extra;
|
|
|
|
|
|
|
2019-07-08 13:57:31 +02:00
|
|
|
|
bool dirty;
|
2020-02-14 22:39:26 +01:00
|
|
|
|
bool linebreak;
|
osc: add support for OSC 133;A (prompt markers)
This patch adds support for the OSC-133;A sequence, introduced by
FinalTerm and implemented by iTerm2, Kitty and more. See
https://iterm2.com/documentation-one-page.html#documentation-escape-codes.html.
The shell emits the OSC just before printing the prompt. This lets the
terminal know where, in the scrollback, there are prompts.
We implement this using a simple boolean in the row struct ("this row
has a prompt"). The prompt marker must be reflowed along with the text
on window resizes.
In an ideal world, erasing, or overwriting the cell where the OSC was
emitted, would remove the prompt mark. Since we don't store this
information in the cell struct, we can't do that. The best we can do
is reset it in erase_line(). This works well enough in the "normal"
screen, when used with a "normal" shell. It doesn't really work in
fullscreen apps, on the alt screen. But that doesn't matter since we
don't support jumping between prompts on the alt screen anyway.
To be able to jump between prompts, two new key bindings have been
added: prompt-prev and prompt-next, bound to ctrl+shift+z and
ctrl+shift+x respectively.
prompt-prev will jump to the previous, not currently visible, prompt,
by moving the viewport, ensuring the prompt is at the top of the
screen.
prompt-next jumps to the next prompt, visible or not. Again, by moving
the viewport to ensure the prompt is at the top of the screen. If
we're at the bottom of the scrollback, the viewport is instead moved
as far down as possible.
Closes #30
2022-06-15 18:44:23 +02:00
|
|
|
|
|
|
|
|
|
|
/* Shell integration */
|
|
|
|
|
|
bool prompt_marker;
|
2019-07-08 13:57:31 +02:00
|
|
|
|
};
|
|
|
|
|
|
|
2020-03-13 18:44:23 +01:00
|
|
|
|
struct sixel {
|
|
|
|
|
|
void *data;
|
|
|
|
|
|
pixman_image_t *pix;
|
|
|
|
|
|
int width;
|
|
|
|
|
|
int height;
|
|
|
|
|
|
int rows;
|
2020-06-06 13:59:46 +02:00
|
|
|
|
int cols;
|
2020-03-13 18:44:23 +01:00
|
|
|
|
struct coord pos;
|
2021-03-09 17:23:55 +01:00
|
|
|
|
bool opaque;
|
2020-03-13 18:44:23 +01:00
|
|
|
|
};
|
|
|
|
|
|
|
2021-11-16 16:32:58 +01:00
|
|
|
|
enum kitty_kbd_flags {
|
|
|
|
|
|
KITTY_KBD_DISAMBIGUATE = 0x01,
|
|
|
|
|
|
KITTY_KBD_REPORT_EVENT = 0x02,
|
2021-11-16 19:55:23 +01:00
|
|
|
|
KITTY_KBD_REPORT_ALTERNATE = 0x04,
|
2021-11-16 16:32:58 +01:00
|
|
|
|
KITTY_KBD_REPORT_ALL = 0x08,
|
|
|
|
|
|
KITTY_KBD_REPORT_ASSOCIATED = 0x10,
|
2021-11-29 21:03:33 +01:00
|
|
|
|
KITTY_KBD_SUPPORTED = (KITTY_KBD_DISAMBIGUATE |
|
|
|
|
|
|
KITTY_KBD_REPORT_EVENT |
|
2021-12-07 19:55:52 +01:00
|
|
|
|
KITTY_KBD_REPORT_ALTERNATE |
|
kitty: implement “report associated text”
In this mode, key events that generate text now add a third CSI
parameter, indicating the actual codepoint.
Remember that we always use the *unshifted* key in the CSI
escapes. With this mode, those CSI escapes now also included the text
codepoint. I.e. what would have been emitted, had we not generated a
CSI escape.
As far as I can tell, this mode has no effect unless “report all keys
as escape sequences” is enabled (reason being, without that, there
aren’t any text events that generate CSIs - they’re always emitted
as-is).
Note that Kitty itself seems to be somewhat buggy in this mode. At
least on Wayland, with my Swedish layout. For example ‘a’ and ‘A’ does
generate the expected CSIs, but ‘å’ and ‘Å’ appears to be treated as
non-text input.
Furthermore, Kitty optimizes away the modifier parameter, if no
modifiers are pressed (e.g. CSI 97;;97u), while we always emit the
modifier (CSI 97;1;97u).
Related to #319
2021-12-06 23:01:41 +01:00
|
|
|
|
KITTY_KBD_REPORT_ALL |
|
|
|
|
|
|
KITTY_KBD_REPORT_ASSOCIATED),
|
2021-11-16 16:32:58 +01:00
|
|
|
|
};
|
|
|
|
|
|
|
2019-06-15 22:22:44 +02:00
|
|
|
|
struct grid {
|
2019-07-08 13:57:31 +02:00
|
|
|
|
int num_rows;
|
2019-07-10 16:27:55 +02:00
|
|
|
|
int num_cols;
|
2019-07-01 12:23:38 +02:00
|
|
|
|
int offset;
|
2019-07-09 16:26:36 +02:00
|
|
|
|
int view;
|
2019-06-29 21:23:36 +02:00
|
|
|
|
|
2021-01-15 18:02:17 +01:00
|
|
|
|
/*
|
|
|
|
|
|
* Note: the cursor (not the *saved* cursor) could most likely be
|
|
|
|
|
|
* global state in the term struct.
|
|
|
|
|
|
*
|
|
|
|
|
|
* However, we have grid specific functions that does not have
|
|
|
|
|
|
* access to the owning term struct, but does need access to the
|
|
|
|
|
|
* cursor.
|
|
|
|
|
|
*/
|
2020-04-16 18:51:14 +02:00
|
|
|
|
struct cursor cursor;
|
|
|
|
|
|
struct cursor saved_cursor;
|
|
|
|
|
|
|
2019-07-08 13:57:31 +02:00
|
|
|
|
struct row **rows;
|
|
|
|
|
|
struct row *cur_row;
|
2019-06-15 22:22:44 +02:00
|
|
|
|
|
2019-06-25 20:11:08 +02:00
|
|
|
|
tll(struct damage) scroll_damage;
|
2020-03-13 18:44:23 +01:00
|
|
|
|
tll(struct sixel) sixel_images;
|
2021-11-16 16:32:58 +01:00
|
|
|
|
|
|
|
|
|
|
struct {
|
|
|
|
|
|
enum kitty_kbd_flags flags[8];
|
|
|
|
|
|
uint8_t idx;
|
|
|
|
|
|
} kitty_kbd;
|
|
|
|
|
|
|
2019-06-15 22:22:44 +02:00
|
|
|
|
};
|
|
|
|
|
|
|
2019-06-23 14:12:20 +02:00
|
|
|
|
struct vt_subparams {
|
|
|
|
|
|
unsigned value[16];
|
2020-02-01 19:24:46 +01:00
|
|
|
|
uint8_t idx;
|
2019-06-23 14:12:20 +02:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct vt_param {
|
|
|
|
|
|
unsigned value;
|
|
|
|
|
|
struct vt_subparams sub;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2019-06-15 22:22:44 +02:00
|
|
|
|
struct vt {
|
|
|
|
|
|
int state; /* enum state */
|
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
2021-08-21 14:50:42 +02:00
|
|
|
|
char32_t last_printed;
|
2020-08-20 19:25:35 +02:00
|
|
|
|
#if defined(FOOT_GRAPHEME_CLUSTERING)
|
|
|
|
|
|
utf8proc_int32_t grapheme_state;
|
|
|
|
|
|
#endif
|
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
2021-08-21 14:50:42 +02:00
|
|
|
|
char32_t utf8;
|
2019-06-15 22:22:44 +02:00
|
|
|
|
struct {
|
2019-06-23 14:12:20 +02:00
|
|
|
|
struct vt_param v[16];
|
2020-02-01 19:24:46 +01:00
|
|
|
|
uint8_t idx;
|
2019-06-15 22:22:44 +02:00
|
|
|
|
} params;
|
2021-02-13 12:34:11 +01:00
|
|
|
|
|
vt: don’t ignore extra private/intermediate characters
Take ‘\E(#0’ for example - this is *not* the same as ‘\E(0’.
Up until now, foot has however treated them as the same escape,
because the handler for ‘\E(0’ didn’t verify there weren’t any _other_
private characters present.
Fix this by turning the ‘private’ array into a single 4-byte
integer. This allows us to match *all* privates with a single
comparison.
Private characters are added to the LSB first, and MSB last. This
means we can check for single privates in pretty much the same way as
before:
switch (term->vt.private) {
case ‘?’:
...
break;
}
Checking for two (or more) is much uglier, but foot only supports
a *single* escape with two privates, and no escapes with three or
more:
switch (term->vt.private) {
case 0x243f: /* ‘?$’ */
...
break;
}
The ‘clear’ action remains simple (and fast), with a single write
operation.
Collecting privates is potentially _slightly_ more complex than
before; we now need mask and compare, instead of simply comparing,
when checking how many privates we already have.
We _could_ add a counter, which would make collecting privates easier,
but this would add an additional write to the ‘clean’ action which is
really bad since it’s in the hot path.
2020-12-16 14:30:49 +01:00
|
|
|
|
uint32_t private; /* LSB=priv0, MSB=priv3 */
|
2021-02-13 12:34:11 +01:00
|
|
|
|
|
|
|
|
|
|
struct attributes attrs;
|
|
|
|
|
|
struct attributes saved_attrs;
|
|
|
|
|
|
|
2019-06-15 22:22:44 +02:00
|
|
|
|
struct {
|
2019-07-19 08:59:35 +02:00
|
|
|
|
uint8_t *data;
|
|
|
|
|
|
size_t size;
|
2019-07-05 09:46:48 +02:00
|
|
|
|
size_t idx;
|
2021-10-20 12:48:37 +01:00
|
|
|
|
bool bel; /* true if OSC string was terminated by BEL */
|
2019-06-15 22:22:44 +02:00
|
|
|
|
} osc;
|
2021-02-13 12:34:11 +01:00
|
|
|
|
|
|
|
|
|
|
/* Start coordinate for current OSC-8 URI */
|
|
|
|
|
|
struct {
|
2021-02-13 13:44:07 +01:00
|
|
|
|
uint64_t id;
|
2021-02-13 12:34:11 +01:00
|
|
|
|
char *uri;
|
|
|
|
|
|
} osc8;
|
|
|
|
|
|
|
2020-01-12 11:55:22 +01:00
|
|
|
|
struct {
|
|
|
|
|
|
uint8_t *data;
|
|
|
|
|
|
size_t size;
|
|
|
|
|
|
size_t idx;
|
2020-02-21 21:53:23 +01:00
|
|
|
|
void (*put_handler)(struct terminal *term, uint8_t c);
|
2020-01-12 11:55:22 +01:00
|
|
|
|
void (*unhook_handler)(struct terminal *term);
|
|
|
|
|
|
} dcs;
|
2019-06-15 22:22:44 +02:00
|
|
|
|
};
|
|
|
|
|
|
|
2019-11-05 13:27:37 +01:00
|
|
|
|
enum cursor_origin { ORIGIN_ABSOLUTE, ORIGIN_RELATIVE };
|
|
|
|
|
|
enum cursor_keys { CURSOR_KEYS_DONTCARE, CURSOR_KEYS_NORMAL, CURSOR_KEYS_APPLICATION };
|
2019-07-09 11:07:06 +02:00
|
|
|
|
enum keypad_keys { KEYPAD_DONTCARE, KEYPAD_NUMERICAL, KEYPAD_APPLICATION };
|
2019-07-04 19:17:18 +02:00
|
|
|
|
enum charset { CHARSET_ASCII, CHARSET_GRAPHIC };
|
2021-06-09 09:51:48 +01:00
|
|
|
|
enum charset_designator { G0, G1, G2, G3 };
|
2019-06-23 14:12:20 +02:00
|
|
|
|
|
2019-11-17 10:00:30 +01:00
|
|
|
|
struct charsets {
|
2021-06-09 09:51:48 +01:00
|
|
|
|
enum charset_designator selected;
|
|
|
|
|
|
enum charset_designator saved;
|
2019-11-17 10:00:30 +01:00
|
|
|
|
enum charset set[4]; /* G0-G3 */
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2019-07-05 14:24:51 +02:00
|
|
|
|
/* *What* to report */
|
|
|
|
|
|
enum mouse_tracking {
|
|
|
|
|
|
MOUSE_NONE,
|
|
|
|
|
|
MOUSE_X10, /* ?9h */
|
2019-11-29 22:30:56 +01:00
|
|
|
|
MOUSE_CLICK, /* ?1000h - report mouse clicks */
|
2019-07-05 14:24:51 +02:00
|
|
|
|
MOUSE_DRAG, /* ?1002h - report clicks and drag motions */
|
2019-11-29 22:30:56 +01:00
|
|
|
|
MOUSE_MOTION, /* ?1003h - report clicks and motion */
|
2019-07-05 14:24:51 +02:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/* *How* to report */
|
|
|
|
|
|
enum mouse_reporting {
|
|
|
|
|
|
MOUSE_NORMAL,
|
|
|
|
|
|
MOUSE_UTF8, /* ?1005h */
|
|
|
|
|
|
MOUSE_SGR, /* ?1006h */
|
|
|
|
|
|
MOUSE_URXVT, /* ?1015h */
|
2021-12-30 05:13:45 -06:00
|
|
|
|
MOUSE_SGR_PIXELS, /* ?1016h */
|
2019-07-05 14:24:51 +02:00
|
|
|
|
};
|
|
|
|
|
|
|
2021-01-06 10:53:27 +01:00
|
|
|
|
enum selection_kind {
|
|
|
|
|
|
SELECTION_NONE,
|
|
|
|
|
|
SELECTION_CHAR_WISE,
|
|
|
|
|
|
SELECTION_WORD_WISE,
|
|
|
|
|
|
SELECTION_LINE_WISE,
|
|
|
|
|
|
SELECTION_BLOCK
|
|
|
|
|
|
};
|
2020-08-12 18:50:49 +02:00
|
|
|
|
enum selection_direction {SELECTION_UNDIR, SELECTION_LEFT, SELECTION_RIGHT};
|
2020-10-11 18:18:18 +02:00
|
|
|
|
enum selection_scroll_direction {SELECTION_SCROLL_NOT, SELECTION_SCROLL_UP, SELECTION_SCROLL_DOWN};
|
2022-04-21 18:54:27 +02:00
|
|
|
|
enum search_direction { SEARCH_BACKWARD_SAME_POSITION, SEARCH_BACKWARD, SEARCH_FORWARD };
|
2020-01-03 23:29:45 +01:00
|
|
|
|
|
2019-11-03 01:03:52 +01:00
|
|
|
|
struct ptmx_buffer {
|
|
|
|
|
|
void *data;
|
|
|
|
|
|
size_t len;
|
|
|
|
|
|
size_t idx;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2020-02-24 22:38:35 +01:00
|
|
|
|
enum term_surface {
|
|
|
|
|
|
TERM_SURF_NONE,
|
|
|
|
|
|
TERM_SURF_GRID,
|
|
|
|
|
|
TERM_SURF_TITLE,
|
|
|
|
|
|
TERM_SURF_BORDER_LEFT,
|
|
|
|
|
|
TERM_SURF_BORDER_RIGHT,
|
|
|
|
|
|
TERM_SURF_BORDER_TOP,
|
|
|
|
|
|
TERM_SURF_BORDER_BOTTOM,
|
2020-03-02 20:29:28 +01:00
|
|
|
|
TERM_SURF_BUTTON_MINIMIZE,
|
|
|
|
|
|
TERM_SURF_BUTTON_MAXIMIZE,
|
|
|
|
|
|
TERM_SURF_BUTTON_CLOSE,
|
2020-02-24 22:38:35 +01:00
|
|
|
|
};
|
|
|
|
|
|
|
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 17:49:46 +02:00
|
|
|
|
enum overlay_style {
|
2022-08-08 16:31:28 +02:00
|
|
|
|
OVERLAY_NONE,
|
|
|
|
|
|
OVERLAY_SEARCH,
|
|
|
|
|
|
OVERLAY_FLASH,
|
|
|
|
|
|
OVERLAY_UNICODE_MODE,
|
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 17:49:46 +02:00
|
|
|
|
};
|
|
|
|
|
|
|
2020-08-22 09:14:18 +02:00
|
|
|
|
typedef tll(struct ptmx_buffer) ptmx_buffer_list_t;
|
|
|
|
|
|
|
2022-03-22 19:07:06 +01:00
|
|
|
|
enum url_action { URL_ACTION_COPY, URL_ACTION_LAUNCH, URL_ACTION_PERSISTENT };
|
2021-01-31 11:12:07 +01:00
|
|
|
|
struct url {
|
2021-02-13 13:45:59 +01:00
|
|
|
|
uint64_t id;
|
2021-02-13 12:28:53 +01:00
|
|
|
|
char *url;
|
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
2021-08-21 14:50:42 +02:00
|
|
|
|
char32_t *key;
|
2022-04-09 15:09:02 +02:00
|
|
|
|
struct range range;
|
2021-02-04 20:55:08 +01:00
|
|
|
|
enum url_action action;
|
2021-02-14 21:29:22 +01:00
|
|
|
|
bool url_mode_dont_change_url_attr; /* Entering/exiting URL mode doesn’t touch the cells’ attr.url */
|
2021-05-22 16:42:43 +02:00
|
|
|
|
bool osc8;
|
2021-07-11 10:06:12 +02:00
|
|
|
|
bool duplicate;
|
2021-01-31 11:12:07 +01:00
|
|
|
|
};
|
2021-02-06 20:01:52 +01:00
|
|
|
|
typedef tll(struct url) url_list_t;
|
2021-01-31 11:12:07 +01:00
|
|
|
|
|
2019-06-15 22:22:44 +02:00
|
|
|
|
struct terminal {
|
2019-10-28 18:25:19 +01:00
|
|
|
|
struct fdm *fdm;
|
2020-05-21 20:17:29 +02:00
|
|
|
|
struct reaper *reaper;
|
2020-02-08 14:09:06 +01:00
|
|
|
|
const struct config *conf;
|
2019-10-28 18:25:19 +01:00
|
|
|
|
|
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
2021-08-21 14:50:42 +02:00
|
|
|
|
void (*ascii_printer)(struct terminal *term, char32_t c);
|
2021-03-14 19:19:10 +01:00
|
|
|
|
|
2019-06-19 10:04:47 +02:00
|
|
|
|
pid_t slave;
|
2019-06-17 18:57:12 +02:00
|
|
|
|
int ptmx;
|
2019-06-29 21:03:28 +02:00
|
|
|
|
|
2020-11-24 20:55:41 +01:00
|
|
|
|
struct vt vt;
|
|
|
|
|
|
struct grid *grid;
|
2020-02-08 14:09:06 +01:00
|
|
|
|
struct grid normal;
|
|
|
|
|
|
struct grid alt;
|
2020-11-24 20:55:41 +01:00
|
|
|
|
|
|
|
|
|
|
int cols; /* number of columns */
|
|
|
|
|
|
int rows; /* number of rows */
|
|
|
|
|
|
struct scroll_region scroll_region;
|
|
|
|
|
|
|
|
|
|
|
|
struct charsets charsets;
|
|
|
|
|
|
struct charsets saved_charsets; /* For save/restore cursor + attributes */
|
|
|
|
|
|
|
|
|
|
|
|
bool auto_margin;
|
|
|
|
|
|
bool insert_mode;
|
|
|
|
|
|
bool reverse;
|
|
|
|
|
|
bool hide_cursor;
|
|
|
|
|
|
bool reverse_wrap;
|
|
|
|
|
|
bool bracketed_paste;
|
|
|
|
|
|
bool focus_events;
|
|
|
|
|
|
bool alt_scrolling;
|
2021-11-11 17:43:39 +01:00
|
|
|
|
bool modify_other_keys_2; /* True when modifyOtherKeys=2 (i.e. “CSI >4;2m”) */
|
2020-11-24 20:55:41 +01:00
|
|
|
|
enum cursor_origin origin;
|
|
|
|
|
|
enum cursor_keys cursor_keys_mode;
|
|
|
|
|
|
enum keypad_keys keypad_keys_mode;
|
|
|
|
|
|
enum mouse_tracking mouse_tracking;
|
|
|
|
|
|
enum mouse_reporting mouse_reporting;
|
2022-01-01 13:56:50 +01:00
|
|
|
|
char *mouse_user_cursor; /* For OSC-22 */
|
2020-11-24 20:55:41 +01:00
|
|
|
|
|
|
|
|
|
|
tll(int) tab_stops;
|
2020-02-08 14:09:06 +01:00
|
|
|
|
|
unicode-combining: store seen combining chains "globally" in the term struct
Instead of storing combining data per cell, realize that most
combinations are re-occurring and that there's lots of available space
left in the unicode range, and store seen base+combining combinations
chains in a per-terminal array.
When we encounter a combining character, we first try to pre-compose,
like before. If that fails, we then search for the current
base+combining combo in the list of previously seen combinations. If
not found there either, we allocate a new combo and add it to the
list. Regardless, the result is an index into this array. We store
this index, offsetted by COMB_CHARS_LO=0x40000000ul in the cell.
When rendering, we need to check if the cell character is a plain
character, or if it's a composed character (identified by checking if
the cell character is >= COMB_CHARS_LO).
Then we render the grapheme pretty much like before.
2020-05-03 11:03:22 +02:00
|
|
|
|
size_t composed_count;
|
|
|
|
|
|
struct composed *composed;
|
|
|
|
|
|
|
2020-11-24 20:55:41 +01:00
|
|
|
|
/* Temporary: for FDM */
|
|
|
|
|
|
struct {
|
|
|
|
|
|
bool is_armed;
|
|
|
|
|
|
int lower_fd;
|
|
|
|
|
|
int upper_fd;
|
|
|
|
|
|
} delayed_render_timer;
|
|
|
|
|
|
|
2020-04-21 19:29:36 +02:00
|
|
|
|
struct fcft_font *fonts[4];
|
2020-10-20 21:04:47 +02:00
|
|
|
|
struct config_font *font_sizes[4];
|
2021-03-20 15:32:31 +01:00
|
|
|
|
struct pt_or_px font_line_height;
|
2020-07-26 07:45:03 +02:00
|
|
|
|
float font_dpi;
|
2021-09-19 11:58:34 +02:00
|
|
|
|
bool font_is_sized_by_dpi;
|
2021-01-07 17:00:58 +01:00
|
|
|
|
int16_t font_x_ofs;
|
|
|
|
|
|
int16_t font_y_ofs;
|
2020-04-21 19:29:36 +02:00
|
|
|
|
enum fcft_subpixel font_subpixel;
|
2020-02-08 14:09:06 +01:00
|
|
|
|
|
2021-09-14 09:50:49 +02:00
|
|
|
|
struct {
|
|
|
|
|
|
struct fcft_glyph **box_drawing;
|
|
|
|
|
|
struct fcft_glyph **braille;
|
|
|
|
|
|
struct fcft_glyph **legacy;
|
|
|
|
|
|
|
|
|
|
|
|
#define GLYPH_BOX_DRAWING_FIRST 0x2500
|
|
|
|
|
|
#define GLYPH_BOX_DRAWING_LAST 0x259F
|
|
|
|
|
|
#define GLYPH_BOX_DRAWING_COUNT \
|
|
|
|
|
|
(GLYPH_BOX_DRAWING_LAST - GLYPH_BOX_DRAWING_FIRST + 1)
|
|
|
|
|
|
|
|
|
|
|
|
#define GLYPH_BRAILLE_FIRST 0x2800
|
|
|
|
|
|
#define GLYPH_BRAILLE_LAST 0x28FF
|
|
|
|
|
|
#define GLYPH_BRAILLE_COUNT \
|
|
|
|
|
|
(GLYPH_BRAILLE_LAST - GLYPH_BRAILLE_FIRST + 1)
|
|
|
|
|
|
|
|
|
|
|
|
#define GLYPH_LEGACY_FIRST 0x1FB00
|
|
|
|
|
|
#define GLYPH_LEGACY_LAST 0x1FB9B
|
|
|
|
|
|
#define GLYPH_LEGACY_COUNT \
|
|
|
|
|
|
(GLYPH_LEGACY_LAST - GLYPH_LEGACY_FIRST + 1)
|
|
|
|
|
|
} custom_glyphs;
|
2020-12-26 16:24:16 +01:00
|
|
|
|
|
2020-08-22 09:14:18 +02:00
|
|
|
|
bool is_sending_paste_data;
|
|
|
|
|
|
ptmx_buffer_list_t ptmx_buffers;
|
|
|
|
|
|
ptmx_buffer_list_t ptmx_paste_buffers;
|
2019-11-03 01:03:52 +01:00
|
|
|
|
|
2020-08-16 16:38:57 +02:00
|
|
|
|
struct {
|
|
|
|
|
|
bool esc_prefix;
|
|
|
|
|
|
bool eight_bit;
|
|
|
|
|
|
} meta;
|
|
|
|
|
|
|
2020-11-11 18:26:47 +01:00
|
|
|
|
bool num_lock_modifier;
|
2020-12-10 18:22:48 +01:00
|
|
|
|
bool bell_action_enabled;
|
2020-10-11 17:44:29 +02:00
|
|
|
|
|
2020-08-16 16:57:39 +02:00
|
|
|
|
/* Saved DECSET modes - we save the SET state */
|
2020-08-16 16:38:57 +02:00
|
|
|
|
struct {
|
2021-02-23 14:20:59 +01:00
|
|
|
|
bool origin:1;
|
|
|
|
|
|
bool application_cursor_keys:1;
|
2022-03-19 13:14:54 +00:00
|
|
|
|
bool application_keypad_keys:1;
|
2021-02-23 14:20:59 +01:00
|
|
|
|
bool reverse:1;
|
|
|
|
|
|
bool show_cursor:1;
|
|
|
|
|
|
bool reverse_wrap:1;
|
|
|
|
|
|
bool auto_margin:1;
|
|
|
|
|
|
bool cursor_blink:1;
|
|
|
|
|
|
bool bracketed_paste:1;
|
|
|
|
|
|
bool focus_events:1;
|
|
|
|
|
|
bool alt_scrolling:1;
|
|
|
|
|
|
//bool mouse_x10:1;
|
|
|
|
|
|
bool mouse_click:1;
|
|
|
|
|
|
bool mouse_drag:1;
|
|
|
|
|
|
bool mouse_motion:1;
|
|
|
|
|
|
//bool mouse_utf8:1;
|
|
|
|
|
|
bool mouse_sgr:1;
|
|
|
|
|
|
bool mouse_urxvt:1;
|
2021-12-30 05:13:45 -06:00
|
|
|
|
bool mouse_sgr_pixels:1;
|
2021-02-23 14:20:59 +01:00
|
|
|
|
bool meta_eight_bit:1;
|
|
|
|
|
|
bool meta_esc_prefix:1;
|
|
|
|
|
|
bool num_lock_modifier:1;
|
|
|
|
|
|
bool bell_action_enabled:1;
|
|
|
|
|
|
bool alt_screen:1;
|
|
|
|
|
|
bool ime:1;
|
2021-04-25 18:35:46 +01:00
|
|
|
|
bool app_sync_updates:1;
|
2021-02-23 14:20:59 +01:00
|
|
|
|
|
2021-07-14 19:17:44 +02:00
|
|
|
|
bool sixel_display_mode:1;
|
2021-02-23 14:20:59 +01:00
|
|
|
|
bool sixel_private_palette:1;
|
|
|
|
|
|
bool sixel_cursor_right_of_graphics:1;
|
2020-08-16 16:38:57 +02:00
|
|
|
|
} xtsave;
|
|
|
|
|
|
|
2021-07-04 17:59:40 +02:00
|
|
|
|
bool window_title_has_been_set;
|
2019-07-21 17:35:53 +02:00
|
|
|
|
char *window_title;
|
2019-07-21 17:48:06 +02:00
|
|
|
|
tll(char *) window_title_stack;
|
2019-07-04 19:17:18 +02:00
|
|
|
|
|
2019-07-22 19:15:56 +02:00
|
|
|
|
struct {
|
|
|
|
|
|
bool active;
|
|
|
|
|
|
int fd;
|
|
|
|
|
|
} flash;
|
2019-07-21 19:14:19 +02:00
|
|
|
|
|
2019-07-22 19:17:57 +02:00
|
|
|
|
struct {
|
|
|
|
|
|
enum { BLINK_ON, BLINK_OFF } state;
|
|
|
|
|
|
int fd;
|
|
|
|
|
|
} blink;
|
2019-07-21 20:11:20 +02:00
|
|
|
|
|
2019-08-12 21:22:38 +02:00
|
|
|
|
int scale;
|
2019-07-05 10:16:56 +02:00
|
|
|
|
int width; /* pixels */
|
|
|
|
|
|
int height; /* pixels */
|
2020-10-20 20:58:03 +02:00
|
|
|
|
int stashed_width;
|
|
|
|
|
|
int stashed_height;
|
2020-02-24 18:38:11 +01:00
|
|
|
|
struct {
|
|
|
|
|
|
int left;
|
|
|
|
|
|
int right;
|
|
|
|
|
|
int top;
|
|
|
|
|
|
int bottom;
|
|
|
|
|
|
} margins;
|
2019-07-05 10:16:56 +02:00
|
|
|
|
int cell_width; /* pixels per cell, x-wise */
|
|
|
|
|
|
int cell_height; /* pixels per cell, y-wise */
|
2019-06-29 21:08:08 +02:00
|
|
|
|
|
2019-07-21 10:58:09 +02:00
|
|
|
|
struct {
|
|
|
|
|
|
uint32_t fg;
|
|
|
|
|
|
uint32_t bg;
|
2019-08-21 18:50:24 +02:00
|
|
|
|
uint32_t table[256];
|
2020-01-03 21:53:16 +01:00
|
|
|
|
uint16_t alpha;
|
2021-04-07 08:09:40 +02:00
|
|
|
|
uint32_t selection_fg;
|
|
|
|
|
|
uint32_t selection_bg;
|
|
|
|
|
|
bool use_custom_selection;
|
2019-07-21 10:58:09 +02:00
|
|
|
|
} colors;
|
2019-06-29 21:15:32 +02:00
|
|
|
|
|
2019-07-22 20:15:14 +02:00
|
|
|
|
enum cursor_style cursor_style;
|
2019-12-15 15:07:56 +01:00
|
|
|
|
struct {
|
term: split cursor blink state into two
There are two different escape sequences that can be used to set the
cursor blink state: ‘CSI ? 12 h/l’ and ‘CSI Ps SP q’.
Up until now, they both modified the same internal state in foot. This
meant you could enable a blinking cursor with e.g. ‘CSI ? 12 h’ and
then disable it with ‘CSI 2 SP q’.
Since the ‘CSI ? 12’ escapes are used in the civis/cnorm/cvvis
terminfo entries, applications often ended up disabling the blink
state on exit (typically be emitting ‘cnorm’), requiring users to
manually re-enable blinking.
By splitting the internal state into two separate states, we can
improve the situation.
The cursor will blink if at least one of the two have been enabled.
The setting in foot.ini sets the default state of the ‘CSI Ps SP q’
escape.
This means if the user has enabled blinking in the configuration, the
cursor will blink regardless of civis/cnorm/cvvis. Which probably is
what the user wants.
If the user has NOT enabled blinking, civis/cnorm/cvvis act as
intended: cvvis blink, civis and cnorm do not.
If an application overrides the cursor blink/style with ‘CSI Ps SP q’,
that will override the user’s setting in foot.ini. But most likely
that too is intended (for example, the user may have configured the
application to use a different cursor style). And, a well written
application will emit the ‘Se’ terminfo sequence on exit, which in
foot is defined to ‘CSI SP q’, which will reset both the style and
blink state to the user configured style/state.
Closes #218
2020-11-26 18:09:32 +01:00
|
|
|
|
bool decset; /* Blink enabled via '\E[?12h' */
|
|
|
|
|
|
bool deccsusr; /* Blink enabled via '\E[X q' */
|
2019-12-15 15:07:56 +01:00
|
|
|
|
int fd;
|
term: split cursor blink state into two
There are two different escape sequences that can be used to set the
cursor blink state: ‘CSI ? 12 h/l’ and ‘CSI Ps SP q’.
Up until now, they both modified the same internal state in foot. This
meant you could enable a blinking cursor with e.g. ‘CSI ? 12 h’ and
then disable it with ‘CSI 2 SP q’.
Since the ‘CSI ? 12’ escapes are used in the civis/cnorm/cvvis
terminfo entries, applications often ended up disabling the blink
state on exit (typically be emitting ‘cnorm’), requiring users to
manually re-enable blinking.
By splitting the internal state into two separate states, we can
improve the situation.
The cursor will blink if at least one of the two have been enabled.
The setting in foot.ini sets the default state of the ‘CSI Ps SP q’
escape.
This means if the user has enabled blinking in the configuration, the
cursor will blink regardless of civis/cnorm/cvvis. Which probably is
what the user wants.
If the user has NOT enabled blinking, civis/cnorm/cvvis act as
intended: cvvis blink, civis and cnorm do not.
If an application overrides the cursor blink/style with ‘CSI Ps SP q’,
that will override the user’s setting in foot.ini. But most likely
that too is intended (for example, the user may have configured the
application to use a different cursor style). And, a well written
application will emit the ‘Se’ terminfo sequence on exit, which in
foot is defined to ‘CSI SP q’, which will reset both the style and
blink state to the user configured style/state.
Closes #218
2020-11-26 18:09:32 +01:00
|
|
|
|
enum { CURSOR_BLINK_ON, CURSOR_BLINK_OFF } state;
|
2019-12-15 15:07:56 +01:00
|
|
|
|
} cursor_blink;
|
2019-07-23 18:54:58 +02:00
|
|
|
|
struct {
|
|
|
|
|
|
uint32_t text;
|
|
|
|
|
|
uint32_t cursor;
|
|
|
|
|
|
} cursor_color;
|
2019-06-29 21:23:36 +02:00
|
|
|
|
|
2019-07-10 20:57:09 +02:00
|
|
|
|
struct {
|
2020-01-03 23:29:45 +01:00
|
|
|
|
enum selection_kind kind;
|
2020-08-12 18:50:49 +02:00
|
|
|
|
enum selection_direction direction;
|
2022-04-09 15:09:02 +02:00
|
|
|
|
struct range coords;
|
2020-08-11 09:55:33 +02:00
|
|
|
|
bool ongoing;
|
2021-01-02 21:38:41 +01:00
|
|
|
|
bool spaces_only; /* SELECTION_SEMANTIC_WORD */
|
selection: auto-scroll: selection keeps scrolling while mouse is outside grid
Moving the mouse outside the grid while we have an on-going selection
now starts a timer. The interval of this timer depends on the mouse’s
distance from the grid - the further away the mouse is, the shorter
interval.
On each timer timeout, we scroll one line, and update the
selection. Thus, the shorter the interval, the faster we scroll.
The timer is canceled as soon as the mouse enters the grid again, or
the selection is either canceled or finalized.
The timer FD is created and destroyed on-demand.
Most of the logic is now in selection.c. The exception is the
calculation of the timer interval, which depends on the mouse’s
position. Thus, this is done in input.c.
The scroll+selection update logic needs to know a) which direction
we’re scrolling in, and b) which *column* the selection should be
updated with.
If the mouse is outside the grid’s left or right margins, the stored
mouse column will be -1. I.e. we don’t know whether the mouse is on
the left or right side of the grid. This is why the caller, that
starts the timer, must provide this value.
The same applies to top and bottom margins, but since we already have
the scroll *direction*, which row value to use can be derived from this.
2020-10-11 15:44:20 +02:00
|
|
|
|
|
2022-04-09 15:09:02 +02:00
|
|
|
|
struct range pivot;
|
2021-01-03 13:11:46 +01:00
|
|
|
|
|
selection: auto-scroll: selection keeps scrolling while mouse is outside grid
Moving the mouse outside the grid while we have an on-going selection
now starts a timer. The interval of this timer depends on the mouse’s
distance from the grid - the further away the mouse is, the shorter
interval.
On each timer timeout, we scroll one line, and update the
selection. Thus, the shorter the interval, the faster we scroll.
The timer is canceled as soon as the mouse enters the grid again, or
the selection is either canceled or finalized.
The timer FD is created and destroyed on-demand.
Most of the logic is now in selection.c. The exception is the
calculation of the timer interval, which depends on the mouse’s
position. Thus, this is done in input.c.
The scroll+selection update logic needs to know a) which direction
we’re scrolling in, and b) which *column* the selection should be
updated with.
If the mouse is outside the grid’s left or right margins, the stored
mouse column will be -1. I.e. we don’t know whether the mouse is on
the left or right side of the grid. This is why the caller, that
starts the timer, must provide this value.
The same applies to top and bottom margins, but since we already have
the scroll *direction*, which row value to use can be derived from this.
2020-10-11 15:44:20 +02:00
|
|
|
|
struct {
|
|
|
|
|
|
int fd;
|
|
|
|
|
|
int col;
|
|
|
|
|
|
enum selection_scroll_direction direction;
|
|
|
|
|
|
} auto_scroll;
|
2019-07-10 20:57:09 +02:00
|
|
|
|
} selection;
|
|
|
|
|
|
|
2019-08-27 17:23:28 +02:00
|
|
|
|
bool is_searching;
|
|
|
|
|
|
struct {
|
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
2021-08-21 14:50:42 +02:00
|
|
|
|
char32_t *buf;
|
2019-08-27 17:23:28 +02:00
|
|
|
|
size_t len;
|
|
|
|
|
|
size_t sz;
|
2019-08-29 21:02:35 +02:00
|
|
|
|
size_t cursor;
|
2019-08-27 19:33:19 +02:00
|
|
|
|
|
|
|
|
|
|
int original_view;
|
|
|
|
|
|
bool view_followed_offset;
|
|
|
|
|
|
struct coord match;
|
|
|
|
|
|
size_t match_len;
|
2022-01-27 18:36:28 +01:00
|
|
|
|
|
|
|
|
|
|
struct {
|
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
2021-08-21 14:50:42 +02:00
|
|
|
|
char32_t *buf;
|
2022-01-27 18:36:28 +01:00
|
|
|
|
size_t len;
|
|
|
|
|
|
} last;
|
2019-08-27 17:23:28 +02:00
|
|
|
|
} search;
|
|
|
|
|
|
|
2019-10-27 18:51:14 +01:00
|
|
|
|
struct wayland *wl;
|
2019-10-27 19:08:48 +01:00
|
|
|
|
struct wl_window *window;
|
2020-01-02 16:06:35 +01:00
|
|
|
|
bool visual_focus;
|
2020-07-11 09:04:46 +02:00
|
|
|
|
bool kbd_focus;
|
2020-02-24 22:38:35 +01:00
|
|
|
|
enum term_surface active_surface;
|
2019-10-27 12:57:37 +01:00
|
|
|
|
|
2019-07-24 20:11:49 +02:00
|
|
|
|
struct {
|
shm: refactor: move away from a single, global, buffer list
Up until now, *all* buffers have been tracked in a single, global
buffer list. We've used 'cookies' to separate buffers from different
contexts (so that shm_get_buffer() doesn't try to re-use e.g. a
search-box buffer for the main grid).
This patch refactors this, and completely removes the global
list.
Instead of cookies, we now use 'chains'. A chain tracks both the
properties to apply to newly created buffers (scrollable, number of
pixman instances to instantiate etc), as well as the instantiated
buffers themselves.
This means there's strictly speaking not much use for shm_fini()
anymore, since its up to the chain owner to call shm_chain_free(),
which will also purge all buffers.
However, since purging a buffer may be deferred, if the buffer is
owned by the compositor at the time of the call to shm_purge() or
shm_chain_free(), we still keep a global 'deferred' list, on to which
deferred buffers are pushed. shm_fini() iterates this list and
destroys the buffers _even_ if they are still owned by the
compositor. This only happens at program termination, and not when
destroying a terminal instance. I.e. closing a window in a “foot
--server” does *not* trigger this.
Each terminal instatiates a number of chains, and these chains are
destroyed when the terminal instance is destroyed. Note that some
buffers may be put on the deferred list, as mentioned above.
2021-07-16 16:48:49 +02:00
|
|
|
|
struct {
|
|
|
|
|
|
struct buffer_chain *grid;
|
|
|
|
|
|
struct buffer_chain *search;
|
|
|
|
|
|
struct buffer_chain *scrollback_indicator;
|
|
|
|
|
|
struct buffer_chain *render_timer;
|
|
|
|
|
|
struct buffer_chain *url;
|
2021-07-18 16:46:43 +02:00
|
|
|
|
struct buffer_chain *csd;
|
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 17:49:46 +02:00
|
|
|
|
struct buffer_chain *overlay;
|
shm: refactor: move away from a single, global, buffer list
Up until now, *all* buffers have been tracked in a single, global
buffer list. We've used 'cookies' to separate buffers from different
contexts (so that shm_get_buffer() doesn't try to re-use e.g. a
search-box buffer for the main grid).
This patch refactors this, and completely removes the global
list.
Instead of cookies, we now use 'chains'. A chain tracks both the
properties to apply to newly created buffers (scrollable, number of
pixman instances to instantiate etc), as well as the instantiated
buffers themselves.
This means there's strictly speaking not much use for shm_fini()
anymore, since its up to the chain owner to call shm_chain_free(),
which will also purge all buffers.
However, since purging a buffer may be deferred, if the buffer is
owned by the compositor at the time of the call to shm_purge() or
shm_chain_free(), we still keep a global 'deferred' list, on to which
deferred buffers are pushed. shm_fini() iterates this list and
destroys the buffers _even_ if they are still owned by the
compositor. This only happens at program termination, and not when
destroying a terminal instance. I.e. closing a window in a “foot
--server” does *not* trigger this.
Each terminal instatiates a number of chains, and these chains are
destroyed when the terminal instance is destroyed. Note that some
buffers may be put on the deferred list, as mentioned above.
2021-07-16 16:48:49 +02:00
|
|
|
|
} chains;
|
|
|
|
|
|
|
2020-03-06 19:16:54 +01:00
|
|
|
|
/* Scheduled for rendering, as soon-as-possible */
|
|
|
|
|
|
struct {
|
|
|
|
|
|
bool grid;
|
|
|
|
|
|
bool csd;
|
|
|
|
|
|
bool search;
|
2021-01-31 11:12:07 +01:00
|
|
|
|
bool urls;
|
2020-03-06 19:16:54 +01:00
|
|
|
|
} refresh;
|
|
|
|
|
|
|
|
|
|
|
|
/* Scheduled for rendering, in the next frame callback */
|
|
|
|
|
|
struct {
|
|
|
|
|
|
bool grid;
|
|
|
|
|
|
bool csd;
|
|
|
|
|
|
bool search;
|
2021-01-31 11:12:07 +01:00
|
|
|
|
bool urls;
|
2020-03-06 19:16:54 +01:00
|
|
|
|
} pending;
|
|
|
|
|
|
|
2020-09-29 10:03:00 +02:00
|
|
|
|
bool margins; /* Someone explicitly requested a refresh of the margins */
|
2020-10-08 19:55:32 +02:00
|
|
|
|
bool urgency; /* Signal 'urgency' (paint borders red) */
|
2020-09-29 10:03:00 +02:00
|
|
|
|
|
render: use a timer instead of relying on the frame callback for title update throttling
Using the frame callback works most of the time, but e.g. Sway doesn’t
call it while the window is hidden, and thus prevents us from updating
the title in e.g. stacked views.
This patch uses a timer FD instead. We store a timestamp from when the
title was last updated. When the application wants to update the
title, we first check if we already have a timer running, and if so,
does nothing.
If no timer is running, check the timestamp. If enough time has
passed, update the title immediately.
If not, instantiate a timer and wait for it to trigger.
Set the minimum time between two updates to ~8ms (twice per frame, for
a 60Hz output, and ~once per frame on a 120Hz output).
Closes #591
2021-06-15 17:27:50 +02:00
|
|
|
|
struct {
|
2022-01-15 14:56:13 +05:30
|
|
|
|
struct timespec last_update;
|
2021-06-18 15:53:47 +02:00
|
|
|
|
bool is_armed;
|
render: use a timer instead of relying on the frame callback for title update throttling
Using the frame callback works most of the time, but e.g. Sway doesn’t
call it while the window is hidden, and thus prevents us from updating
the title in e.g. stacked views.
This patch uses a timer FD instead. We store a timestamp from when the
title was last updated. When the application wants to update the
title, we first check if we already have a timer running, and if so,
does nothing.
If no timer is running, check the timestamp. If enough time has
passed, update the title immediately.
If not, instantiate a timer and wait for it to trigger.
Set the minimum time between two updates to ~8ms (twice per frame, for
a 60Hz output, and ~once per frame on a 120Hz output).
Closes #591
2021-06-15 17:27:50 +02:00
|
|
|
|
int timer_fd;
|
|
|
|
|
|
} title;
|
|
|
|
|
|
|
2021-11-06 12:01:57 +01:00
|
|
|
|
uint32_t scrollback_lines; /* Number of scrollback lines, from conf (TODO: move out from render struct?) */
|
2019-07-24 20:21:41 +02:00
|
|
|
|
|
2020-01-12 12:40:42 +01:00
|
|
|
|
struct {
|
|
|
|
|
|
bool enabled;
|
|
|
|
|
|
int timer_fd;
|
2020-01-12 12:55:19 +01:00
|
|
|
|
} app_sync_updates;
|
2020-01-12 12:40:42 +01:00
|
|
|
|
|
2020-01-04 19:56:59 +01:00
|
|
|
|
/* Render threads + synchronization primitives */
|
2019-07-29 20:13:26 +02:00
|
|
|
|
struct {
|
2021-11-06 12:01:57 +01:00
|
|
|
|
uint16_t count;
|
2019-07-29 20:13:26 +02:00
|
|
|
|
sem_t start;
|
|
|
|
|
|
sem_t done;
|
|
|
|
|
|
mtx_t lock;
|
|
|
|
|
|
tll(int) queue;
|
|
|
|
|
|
thrd_t *threads;
|
|
|
|
|
|
struct buffer *buf;
|
|
|
|
|
|
} workers;
|
|
|
|
|
|
|
2019-07-24 20:21:41 +02:00
|
|
|
|
/* Last rendered cursor position */
|
|
|
|
|
|
struct {
|
render: remove most of the special handling of cursor rendering
Previously, we had to explicitly render the old cursor cell *before*
applying scrolling damage.
We then rendered all the dirty rows, *without* rendering the cursor -
even if the cursor cell was among the dirty rows.
Finally, when everything else was done, we explicitly rendered the
cursor cell.
This meant a lot of code, and unnecessary render_cell() calls, along
with unnecessary wl_surface_damage_buffer() calls.
This was a necessary in the early design of foot, but not anymore.
We can simply mark both the old cursor cell, and the current one, as
dirty and let the normal rendering framework render it. All we need to
do is pass the cursor column to render_row(), so that it can pass
has_cursor=true in the appropriate call to render_cell(). We pass -1
here for all rows, except the cursor's row, where we pass the actual
cursor column.
With this, there's no need to calculate whether the cursor is visible
or not; just mark it's cell as dirty, and if that row is visible, the
normal rendering will take care of it.
This also simplifies the state needed to be saved between two frames;
we only need a row pointer, and the cursor column index.
Part of https://codeberg.org/dnkl/foot/issues/35
2020-07-12 12:56:10 +02:00
|
|
|
|
struct row *row;
|
|
|
|
|
|
int col;
|
2020-07-15 08:21:41 +02:00
|
|
|
|
bool hidden;
|
2019-07-24 20:21:41 +02:00
|
|
|
|
} last_cursor;
|
|
|
|
|
|
|
2019-11-02 01:28:29 +01:00
|
|
|
|
struct buffer *last_buf; /* Buffer we rendered to last time */
|
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 17:49:46 +02:00
|
|
|
|
|
|
|
|
|
|
enum overlay_style last_overlay_style;
|
|
|
|
|
|
struct buffer *last_overlay_buf;
|
|
|
|
|
|
pixman_region32_t last_overlay_clip;
|
2019-12-31 15:39:40 +01:00
|
|
|
|
|
2020-01-05 15:25:24 +01:00
|
|
|
|
size_t search_glyph_offset;
|
2020-01-05 15:16:40 +01:00
|
|
|
|
|
2022-10-05 17:05:44 +02:00
|
|
|
|
struct {
|
|
|
|
|
|
struct grid *grid;
|
|
|
|
|
|
int screen_rows;
|
|
|
|
|
|
} resizing;
|
|
|
|
|
|
|
2019-12-31 15:39:40 +01:00
|
|
|
|
struct timespec input_time;
|
2019-07-24 20:11:49 +02:00
|
|
|
|
} render;
|
2019-10-27 11:46:18 +01:00
|
|
|
|
|
2020-02-21 21:53:23 +01:00
|
|
|
|
struct {
|
2020-02-22 11:30:30 +01:00
|
|
|
|
enum {
|
|
|
|
|
|
SIXEL_DECSIXEL, /* DECSIXEL body part ", $, -, ? ... ~ */
|
|
|
|
|
|
SIXEL_DECGRA, /* DECGRA Set Raster Attributes " Pan; Pad; Ph; Pv */
|
|
|
|
|
|
SIXEL_DECGRI, /* DECGRI Graphics Repeat Introducer ! Pn Ch */
|
2020-11-24 20:55:41 +01:00
|
|
|
|
SIXEL_DECGCI, /* DECGCI Graphics Color Introducer # Pc; Pu; Px; Py; Pz */
|
2020-02-22 11:30:30 +01:00
|
|
|
|
} state;
|
2020-02-22 10:54:52 +01:00
|
|
|
|
|
|
|
|
|
|
struct coord pos; /* Current sixel coordinate */
|
2021-03-07 14:44:16 +01:00
|
|
|
|
int max_non_empty_row_no;
|
2021-03-06 22:05:40 +01:00
|
|
|
|
size_t row_byte_ofs; /* Byte position into image, for current row */
|
2020-02-22 10:54:52 +01:00
|
|
|
|
int color_idx; /* Current palette index */
|
2021-02-16 19:37:49 +01:00
|
|
|
|
uint32_t *private_palette; /* Private palette, used when private mode 1070 is enabled */
|
|
|
|
|
|
uint32_t *shared_palette; /* Shared palette, used when private mode 1070 is disabled */
|
|
|
|
|
|
uint32_t *palette; /* Points to either private_palette or shared_palette */
|
2021-09-05 11:08:13 +02:00
|
|
|
|
uint32_t color;
|
2020-02-22 10:46:35 +01:00
|
|
|
|
|
|
|
|
|
|
struct {
|
2020-02-22 10:54:52 +01:00
|
|
|
|
uint32_t *data; /* Raw image data, in ARGB */
|
|
|
|
|
|
int width; /* Image width, in pixels */
|
|
|
|
|
|
int height; /* Image height, in pixels */
|
2020-02-22 10:46:35 +01:00
|
|
|
|
} image;
|
2020-02-21 21:53:23 +01:00
|
|
|
|
|
sixel: implement private mode 80 - sixel scrolling
When enabled (the default), sixels behave much like normal output; the
start where the cursor is, and the cursor moves with the
sixel. I.e. after emitting a sixel the cursor is left after the image;
either to the right, if private mode 8452 is enabled, or otherwise on
the next line. Terminal content is scrolled up if the sixel is larger
than the screen.
When disabled, sixels *always* start at (0,0), the cursor never moves,
and the terminal content never scrolls.
In other words, the ‘disabled’ mode is a much simpler mode.
All we need to do to support both modes is re-write the sixel-emitting
loop to:
* break early if we’re “out of rows”, i.e. we’ve reached the bottom of
the screen.
* not linefeed, or move the cursor when scrolling is disabled
This patch also fixes a bug in the (new) implementation of private
mode 8452.
When emitting a sixel, we may break it up into smaller pieces, to
ensure a single sixel (as tracked internally) does not cross the
scrollback wrap-around.
The code that checked if we should do a linefeed or not, would skip
the linefeed on the last row of *each* such sixel piece. The correct
thing to do is to skip it only on the last row of the *last* piece.
I chose not to fix this bug in a separate patch since doing so would
have meant re-writing it again when implementing private mode 80.
2021-02-26 09:28:03 +01:00
|
|
|
|
bool scrolling:1; /* Private mode 80 */
|
|
|
|
|
|
bool use_private_palette:1; /* Private mode 1070 */
|
|
|
|
|
|
bool cursor_right_of_graphics:1; /* Private mode 8452 */
|
2021-02-16 19:37:49 +01:00
|
|
|
|
|
2020-08-15 19:39:00 +01:00
|
|
|
|
unsigned params[5]; /* Collected parameters, for RASTER, COLOR_SPEC */
|
2020-02-22 11:30:30 +01:00
|
|
|
|
unsigned param; /* Currently collecting parameter, for RASTER, COLOR_SPEC and REPEAT */
|
2020-02-22 10:54:52 +01:00
|
|
|
|
unsigned param_idx; /* Parameters seen */
|
2020-02-22 14:02:00 +01:00
|
|
|
|
|
2021-03-09 17:23:55 +01:00
|
|
|
|
bool transparent_bg;
|
2021-09-05 10:27:13 +02:00
|
|
|
|
uint32_t default_bg;
|
2021-03-09 17:23:55 +01:00
|
|
|
|
|
2020-02-22 14:02:00 +01:00
|
|
|
|
/* Application configurable */
|
2020-02-22 21:03:24 +01:00
|
|
|
|
unsigned palette_size; /* Number of colors in palette */
|
|
|
|
|
|
unsigned max_width; /* Maximum image width, in pixels */
|
|
|
|
|
|
unsigned max_height; /* Maximum image height, in pixels */
|
2020-02-21 21:53:23 +01:00
|
|
|
|
} sixel;
|
|
|
|
|
|
|
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-22 10:22:41 +01:00
|
|
|
|
/* TODO: wrap in a struct */
|
2021-02-06 20:01:52 +01:00
|
|
|
|
url_list_t urls;
|
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
2021-08-21 14:50:42 +02:00
|
|
|
|
char32_t url_keys[5];
|
2021-02-14 14:18:11 +01:00
|
|
|
|
bool urls_show_uri_on_jump_label;
|
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-22 10:22:41 +01:00
|
|
|
|
struct grid *url_grid_snapshot;
|
2021-01-31 11:12:07 +01:00
|
|
|
|
|
2020-12-03 18:36:56 +01:00
|
|
|
|
#if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED
|
2021-03-23 13:03:07 +01:00
|
|
|
|
bool ime_enabled;
|
2020-12-03 18:36:56 +01:00
|
|
|
|
#endif
|
2020-12-02 18:52:50 +01:00
|
|
|
|
|
2021-07-31 19:08:51 +02:00
|
|
|
|
struct {
|
|
|
|
|
|
bool in_progress;
|
|
|
|
|
|
bool client_has_terminated;
|
|
|
|
|
|
int terminate_timeout_fd;
|
|
|
|
|
|
int exit_status;
|
|
|
|
|
|
|
|
|
|
|
|
void (*cb)(void *data, int exit_code);
|
|
|
|
|
|
void *cb_data;
|
|
|
|
|
|
} shutdown;
|
2019-12-21 15:27:17 +01:00
|
|
|
|
|
|
|
|
|
|
char *foot_exe;
|
2019-12-21 15:35:54 +01:00
|
|
|
|
char *cwd;
|
2019-06-15 22:22:44 +02:00
|
|
|
|
};
|
2019-06-29 21:03:28 +02:00
|
|
|
|
|
2020-07-31 17:09:06 +02:00
|
|
|
|
extern const char *const XCURSOR_HIDDEN;
|
2020-07-09 09:52:11 +02:00
|
|
|
|
extern const char *const XCURSOR_LEFT_PTR;
|
|
|
|
|
|
extern const char *const XCURSOR_TEXT;
|
2022-02-07 20:32:28 +05:30
|
|
|
|
extern const char *const XCURSOR_TEXT_FALLBACK;
|
2020-07-09 09:52:11 +02:00
|
|
|
|
//extern const char *const XCURSOR_HAND2;
|
|
|
|
|
|
extern const char *const XCURSOR_TOP_LEFT_CORNER;
|
|
|
|
|
|
extern const char *const XCURSOR_TOP_RIGHT_CORNER;
|
|
|
|
|
|
extern const char *const XCURSOR_BOTTOM_LEFT_CORNER;
|
|
|
|
|
|
extern const char *const XCURSOR_BOTTOM_RIGHT_CORNER;
|
|
|
|
|
|
extern const char *const XCURSOR_LEFT_SIDE;
|
|
|
|
|
|
extern const char *const XCURSOR_RIGHT_SIDE;
|
|
|
|
|
|
extern const char *const XCURSOR_TOP_SIDE;
|
|
|
|
|
|
extern const char *const XCURSOR_BOTTOM_SIDE;
|
|
|
|
|
|
|
2019-10-28 18:25:19 +01:00
|
|
|
|
struct config;
|
|
|
|
|
|
struct terminal *term_init(
|
2020-05-21 20:17:29 +02:00
|
|
|
|
const struct config *conf, struct fdm *fdm, struct reaper *reaper,
|
|
|
|
|
|
struct wayland *wayl, const char *foot_exe, const char *cwd,
|
2022-04-11 12:19:40 +02:00
|
|
|
|
const char *token, int argc, char *const *argv, char *const *envp,
|
2019-11-01 20:34:32 +01:00
|
|
|
|
void (*shutdown_cb)(void *data, int exit_code), void *shutdown_data);
|
|
|
|
|
|
|
2019-10-30 20:03:11 +01:00
|
|
|
|
bool term_shutdown(struct terminal *term);
|
2019-10-28 18:25:19 +01:00
|
|
|
|
int term_destroy(struct terminal *term);
|
|
|
|
|
|
|
2021-03-14 19:19:10 +01:00
|
|
|
|
void term_update_ascii_printer(struct terminal *term);
|
2021-06-09 09:51:48 +01:00
|
|
|
|
void term_single_shift(struct terminal *term, enum charset_designator idx);
|
2021-03-14 19:19:10 +01:00
|
|
|
|
|
2019-08-01 20:51:11 +02:00
|
|
|
|
void term_reset(struct terminal *term, bool hard);
|
2019-11-03 00:27:39 +01:00
|
|
|
|
bool term_to_slave(struct terminal *term, const void *data, size_t len);
|
2020-08-22 09:14:18 +02:00
|
|
|
|
bool term_paste_data_to_slave(
|
|
|
|
|
|
struct terminal *term, const void *data, size_t len);
|
2019-08-01 20:51:11 +02:00
|
|
|
|
|
term: implement term_font_dpi_changed()
This function reloads the font *if* the DPI has changed. To handle
user run-time adjusted font sizes, we record the number of adjustments
made.
Then, when re-loading the font, we first load the font as specified in
the configuration. Then, we re-apply the size adjustment using
font_size_adjust().
Note that this means we end up loading the fonts twice; first using
the default size (but with adjusted DPI), and then again with the
adjusted size. This can probably be improved upon.
The existing font code has been refactored to avoid code
duplication. For example, term_init() now calls
term_font_dpi_changed() to load the initial fonts, instead of directly
instantiating them.
Finally, the way we calculate the DPI to use has changed: instead of
using the highest DPI of all available outputs, we use the highest DPI
of the output's we're actually mapped on. If we're not mapped at all,
we use the globally highest DPI.
Doing it this way means we usually only have to load the fonts
once. Otherwise, we'd end up using the default DPI of 96 when the
terminal is first instantiated (since it's not mapped at that time).
On a single monitor system, we'll use the globally highest DPI at
first, before being mapped. Then when we get mapped, we re-load the
fonts using the highest mapped DPI. But since they'll be the same,
we can skip actually reloading the fonts.
2020-02-15 19:08:14 +01:00
|
|
|
|
bool term_font_size_increase(struct terminal *term);
|
|
|
|
|
|
bool term_font_size_decrease(struct terminal *term);
|
|
|
|
|
|
bool term_font_size_reset(struct terminal *term);
|
2021-05-13 11:10:51 +02:00
|
|
|
|
bool term_font_dpi_changed(struct terminal *term, int old_scale);
|
2020-04-20 18:37:59 +02:00
|
|
|
|
void term_font_subpixel_changed(struct terminal *term);
|
pt-or-px: heed the dpi-aware setting
Before this patch, pt-or-px values, like letter-spacing, were *always*
scaled using the current DPI value.
This is wrong; if the fonts are scaled using the output’s scaling
factor, then so should all other point values.
This also fixes an issue where e.g. letter-spacing would use one DPI
value at startup, but then when increasing/decreasing or resetting the
font size, would be re-calculated using a different DPI value, leading
to completely different spacing.
This happened when there were multiple monitors, with different DPI
values, and foot guessed the initial DPI value wrong. Normally, foot
would correct itself as soon as the window was mapped, and the
“correct” DPI value known. But if the fonts were scaled using the
scaling factor, it was possible that the font reload never happened.
This patch also updates the thickness calculation (for LIGHT and HEAVY
box drawing characters) to use the scaling factor when appropriate.
Closes #680
2021-08-13 17:38:56 +02:00
|
|
|
|
|
2021-04-30 20:31:47 +02:00
|
|
|
|
int term_pt_or_px_as_pixels(
|
|
|
|
|
|
const struct terminal *term, const struct pt_or_px *pt_or_px);
|
|
|
|
|
|
|
2020-04-20 18:37:59 +02:00
|
|
|
|
|
2020-04-30 17:22:57 +02:00
|
|
|
|
void term_window_configured(struct terminal *term);
|
2020-02-08 14:09:06 +01:00
|
|
|
|
|
2019-07-11 09:51:51 +02:00
|
|
|
|
void term_damage_rows(struct terminal *term, int start, int end);
|
|
|
|
|
|
void term_damage_rows_in_view(struct terminal *term, int start, int end);
|
|
|
|
|
|
|
2019-06-29 21:03:28 +02:00
|
|
|
|
void term_damage_all(struct terminal *term);
|
2019-07-10 14:32:40 +02:00
|
|
|
|
void term_damage_view(struct terminal *term);
|
2019-07-11 09:51:51 +02:00
|
|
|
|
|
2020-09-29 10:03:00 +02:00
|
|
|
|
void term_damage_cursor(struct terminal *term);
|
|
|
|
|
|
void term_damage_margins(struct terminal *term);
|
|
|
|
|
|
|
2019-08-28 17:25:42 +02:00
|
|
|
|
void term_reset_view(struct terminal *term);
|
|
|
|
|
|
|
2019-06-29 21:03:28 +02:00
|
|
|
|
void term_damage_scroll(
|
|
|
|
|
|
struct terminal *term, enum damage_type damage_type,
|
|
|
|
|
|
struct scroll_region region, int lines);
|
|
|
|
|
|
|
2019-07-08 13:57:31 +02:00
|
|
|
|
void term_erase(
|
2021-12-25 19:12:51 +01:00
|
|
|
|
struct terminal *term,
|
|
|
|
|
|
int start_row, int start_col,
|
|
|
|
|
|
int end_row, int end_col);
|
2021-07-16 16:45:36 +02:00
|
|
|
|
void term_erase_scrollback(struct terminal *term);
|
2019-06-29 21:03:28 +02:00
|
|
|
|
|
2019-11-17 18:52:27 +01:00
|
|
|
|
int term_row_rel_to_abs(const struct terminal *term, int row);
|
2019-11-05 13:27:37 +01:00
|
|
|
|
void term_cursor_home(struct terminal *term);
|
2019-06-29 21:03:28 +02:00
|
|
|
|
void term_cursor_to(struct terminal *term, int row, int col);
|
|
|
|
|
|
void term_cursor_left(struct terminal *term, int count);
|
|
|
|
|
|
void term_cursor_right(struct terminal *term, int count);
|
|
|
|
|
|
void term_cursor_up(struct terminal *term, int count);
|
|
|
|
|
|
void term_cursor_down(struct terminal *term, int count);
|
term: split cursor blink state into two
There are two different escape sequences that can be used to set the
cursor blink state: ‘CSI ? 12 h/l’ and ‘CSI Ps SP q’.
Up until now, they both modified the same internal state in foot. This
meant you could enable a blinking cursor with e.g. ‘CSI ? 12 h’ and
then disable it with ‘CSI 2 SP q’.
Since the ‘CSI ? 12’ escapes are used in the civis/cnorm/cvvis
terminfo entries, applications often ended up disabling the blink
state on exit (typically be emitting ‘cnorm’), requiring users to
manually re-enable blinking.
By splitting the internal state into two separate states, we can
improve the situation.
The cursor will blink if at least one of the two have been enabled.
The setting in foot.ini sets the default state of the ‘CSI Ps SP q’
escape.
This means if the user has enabled blinking in the configuration, the
cursor will blink regardless of civis/cnorm/cvvis. Which probably is
what the user wants.
If the user has NOT enabled blinking, civis/cnorm/cvvis act as
intended: cvvis blink, civis and cnorm do not.
If an application overrides the cursor blink/style with ‘CSI Ps SP q’,
that will override the user’s setting in foot.ini. But most likely
that too is intended (for example, the user may have configured the
application to use a different cursor style). And, a well written
application will emit the ‘Se’ terminfo sequence on exit, which in
foot is defined to ‘CSI SP q’, which will reset both the style and
blink state to the user configured style/state.
Closes #218
2020-11-26 18:09:32 +01:00
|
|
|
|
void term_cursor_blink_update(struct terminal *term);
|
2019-06-29 21:03:28 +02:00
|
|
|
|
|
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
2021-08-21 14:50:42 +02:00
|
|
|
|
void term_print(struct terminal *term, char32_t wc, int width);
|
2020-01-20 18:34:32 +01:00
|
|
|
|
|
2019-06-29 21:03:28 +02:00
|
|
|
|
void term_scroll(struct terminal *term, int rows);
|
|
|
|
|
|
void term_scroll_reverse(struct terminal *term, int rows);
|
|
|
|
|
|
|
|
|
|
|
|
void term_scroll_partial(
|
|
|
|
|
|
struct terminal *term, struct scroll_region region, int rows);
|
|
|
|
|
|
void term_scroll_reverse_partial(
|
|
|
|
|
|
struct terminal *term, struct scroll_region region, int rows);
|
|
|
|
|
|
|
2020-07-14 09:29:10 +02:00
|
|
|
|
void term_carriage_return(struct terminal *term);
|
2019-07-10 16:02:03 +02:00
|
|
|
|
void term_linefeed(struct terminal *term);
|
|
|
|
|
|
void term_reverse_index(struct terminal *term);
|
|
|
|
|
|
|
2019-12-17 19:11:27 +01:00
|
|
|
|
void term_arm_blink_timer(struct terminal *term);
|
|
|
|
|
|
|
2021-01-15 17:08:30 +01:00
|
|
|
|
void term_save_cursor(struct terminal *term);
|
2020-03-16 12:00:25 +01:00
|
|
|
|
void term_restore_cursor(struct terminal *term, const struct cursor *cursor);
|
2019-07-23 17:57:07 +02:00
|
|
|
|
|
2020-01-02 19:35:32 +01:00
|
|
|
|
void term_visual_focus_in(struct terminal *term);
|
|
|
|
|
|
void term_visual_focus_out(struct terminal *term);
|
2020-01-02 19:29:42 +01:00
|
|
|
|
void term_kbd_focus_in(struct terminal *term);
|
|
|
|
|
|
void term_kbd_focus_out(struct terminal *term);
|
2020-07-08 18:16:43 +02:00
|
|
|
|
void term_mouse_down(
|
|
|
|
|
|
struct terminal *term, int button, int row, int col,
|
2021-12-30 05:13:45 -06:00
|
|
|
|
int row_pixels, int col_pixels,
|
2020-07-08 18:16:43 +02:00
|
|
|
|
bool shift, bool alt, bool ctrl);
|
|
|
|
|
|
void term_mouse_up(
|
|
|
|
|
|
struct terminal *term, int button, int row, int col,
|
2021-12-30 05:13:45 -06:00
|
|
|
|
int row_pixels, int col_pixels,
|
2020-07-08 18:16:43 +02:00
|
|
|
|
bool shift, bool alt, bool ctrl);
|
|
|
|
|
|
void term_mouse_motion(
|
|
|
|
|
|
struct terminal *term, int button, int row, int col,
|
2021-12-30 05:13:45 -06:00
|
|
|
|
int row_pixels, int col_pixels,
|
2020-07-08 18:16:43 +02:00
|
|
|
|
bool shift, bool alt, bool ctrl);
|
2021-12-24 15:21:37 +01:00
|
|
|
|
bool term_mouse_grabbed(const struct terminal *term, const struct seat *seat);
|
2019-11-28 19:35:47 +01:00
|
|
|
|
void term_xcursor_update(struct terminal *term);
|
2020-07-31 17:09:06 +02:00
|
|
|
|
void term_xcursor_update_for_seat(struct terminal *term, struct seat *seat);
|
2022-01-01 13:56:50 +01:00
|
|
|
|
void term_set_user_mouse_cursor(struct terminal *term, const char *cursor);
|
2019-07-21 17:35:53 +02:00
|
|
|
|
|
|
|
|
|
|
void term_set_window_title(struct terminal *term, const char *title);
|
2019-07-30 22:06:02 +02:00
|
|
|
|
void term_flash(struct terminal *term, unsigned duration_ms);
|
2020-10-08 19:55:32 +02:00
|
|
|
|
void term_bell(struct terminal *term);
|
2019-12-21 15:27:17 +01:00
|
|
|
|
bool term_spawn_new(const struct terminal *term);
|
2020-01-12 12:43:28 +01:00
|
|
|
|
|
2020-01-12 12:55:19 +01:00
|
|
|
|
void term_enable_app_sync_updates(struct terminal *term);
|
|
|
|
|
|
void term_disable_app_sync_updates(struct terminal *term);
|
2020-02-24 22:38:35 +01:00
|
|
|
|
|
|
|
|
|
|
enum term_surface term_surface_kind(
|
|
|
|
|
|
const struct terminal *term, const struct wl_surface *surface);
|
2020-07-15 11:31:38 +02:00
|
|
|
|
|
2020-07-15 11:33:37 +02:00
|
|
|
|
bool term_scrollback_to_text(
|
|
|
|
|
|
const struct terminal *term, char **text, size_t *len);
|
|
|
|
|
|
bool term_view_to_text(
|
|
|
|
|
|
const struct terminal *term, char **text, size_t *len);
|
2020-12-03 18:36:56 +01:00
|
|
|
|
|
2020-12-04 18:39:11 +01:00
|
|
|
|
bool term_ime_is_enabled(const struct terminal *term);
|
|
|
|
|
|
void term_ime_enable(struct terminal *term);
|
|
|
|
|
|
void term_ime_disable(struct terminal *term);
|
2021-03-23 13:03:07 +01:00
|
|
|
|
bool term_ime_reset(struct terminal *term);
|
2020-12-20 15:01:21 -07:00
|
|
|
|
void term_ime_set_cursor_rect(
|
|
|
|
|
|
struct terminal *term, int x, int y, int width, int height);
|
2021-01-31 11:12:07 +01:00
|
|
|
|
|
|
|
|
|
|
void term_urls_reset(struct terminal *term);
|
|
|
|
|
|
void term_collect_urls(struct terminal *term);
|
2021-02-13 12:34:48 +01:00
|
|
|
|
|
2021-02-13 13:44:07 +01:00
|
|
|
|
void term_osc8_open(struct terminal *term, uint64_t id, const char *uri);
|
2021-02-13 12:34:48 +01:00
|
|
|
|
void term_osc8_close(struct terminal *term);
|
2020-08-20 19:25:35 +02:00
|
|
|
|
|
|
|
|
|
|
static inline void term_reset_grapheme_state(struct terminal *term)
|
|
|
|
|
|
{
|
|
|
|
|
|
#if defined(FOOT_GRAPHEME_CLUSTERING)
|
|
|
|
|
|
term->vt.grapheme_state = 0;
|
|
|
|
|
|
#endif
|
|
|
|
|
|
}
|