Commit graph

573 commits

Author SHA1 Message Date
David Rosca
2c5a23867f
Only brighten palette colors with bold-text-in-bright=palette-based 2021-07-26 19:13:46 +02:00
Daniel Eklöf
7714fcde83
render: render_osd(): use fcft_text_run_rasterize(), if available 2021-07-24 11:02:43 +02:00
Daniel Eklöf
e2e28db7de
render: render_osd(): fix rendering of color bitmap glyphs 2021-07-24 11:02:43 +02:00
Daniel Eklöf
bf285ae00a
render: render_osd(): don’t re-instantiate foreground color for each glyph 2021-07-24 11:02:43 +02:00
Daniel Eklöf
5c683d2c08
render: render_osd(): don’t assume a monospace font 2021-07-24 11:02:43 +02:00
Daniel Eklöf
0cf7a19616
render: csd_title(): use a custom font, sized based on the title bar’s height
We still use the primary font, but use a custom size, based on the
title bar’s height.

This fixes an issue where the window title could be way too small, or
way too big. And changed size when the terminal font size was changed.
2021-07-24 11:02:42 +02:00
Daniel Eklöf
4a41575cb5
render: render_osd() now needs a ‘font’ argument 2021-07-24 11:02:42 +02:00
Daniel Eklöf
5fe23c0215
render: render_osd(): pass font as argument 2021-07-24 11:02:42 +02:00
Daniel Eklöf
3d9536caff
render: refresh CSD in render_refresh_title(), not render_update_title()
This fixes an issue where the CSD title sometimes got stuck on an
“old” title.
2021-07-24 11:02:42 +02:00
Daniel Eklöf
61e4035c23
render: refresh CSDs when updating the title 2021-07-24 11:02:42 +02:00
Daniel Eklöf
468587b67f
render: csd_title(): use render_osd() to render the current window title 2021-07-24 11:02:42 +02:00
Daniel Eklöf
bbc26da87b
render: must now set alpha in bg color when calling render_osd() 2021-07-24 11:02:42 +02:00
Daniel Eklöf
7067c57399
render: render_osd(): set clip region, use background alpha
Set clip region in render_osd(). This ensures we don’t step outside
the pixman buffer when rendering the glyphs.

Furthermore, don’t ignore the alpha channel in the background color.

Move render_osd() to make it visible to the render_csd_*() functions.
2021-07-24 11:02:41 +02:00
Daniel Eklöf
e17c6fcbec
render: color_dim(): retain alpha channel 2021-07-24 11:02:41 +02:00
Timur Celik
a410734f96 render: prevent cells from overflowing into margin 2021-07-20 11:44:27 +02:00
Daniel Eklöf
20fc80e57e
render: use a single backing SHM pool for CSD surface buffers 2021-07-18 16:46:43 +02:00
Daniel Eklöf
53851e13ec
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-17 19:14:42 +02:00
Daniel Eklöf
232fb20269
shm: replace 'locked' attribute with a ref-counter
The initial ref-count is either 1 or 0, depending on whether the
buffer is supposed to be released "immeidately" (meaning, as soon as
the compositor releases it).

Two new user facing functions have been added: shm_addref() and
shm_unref().

Our renderer now uses these two functions instead of manually setting
and clearing the 'locked' attribute.

shm_unref() will decrement the ref-counter, and destroy the buffer
when the counter reaches zero. Except if the buffer is currently
"busy" (compositor owned), in which case destruction is deferred to
the release event. The buffer is still removed from the list though.
2021-07-17 19:14:42 +02:00
Daniel Eklöf
69260dd960
shm: we may exit with busy buffers remaining (seen on KDE) 2021-07-17 19:14:41 +02:00
Daniel Eklöf
99ea47c97a
shm: move ‘size’ to the private buffer struct 2021-07-17 19:14:41 +02:00
Daniel Eklöf
9b6cee825b
shm: rename buffer.mmapped to buffer.data 2021-07-17 19:14:41 +02:00
Timur Celik
91801ae55d render: Allow cells to bleed into their neighbor
This patch adds a `confined` flag to each cell to track if the last
rendered glyph bled into it's right neighbor.  To keep things simple,
bleeding into any other neighbor cell than the immediate right one is
not allowed.  This should cover most use cases.

Before rendering a row we now do a prepass and mark all cells unclean
that are affected by a bleeding neighbor.  If there are consecutive
bleeding cells, the whole group must be re-rendered even if only a
single cell has changed.

The patch also deprecates both old overflowing glyph options
*allow-overflowing-double-width-glyphs* and *pua-double-width* in favor
of a single new one named *overflowing-glyphs*.
2021-07-17 13:22:44 +02:00
Daniel Eklöf
31fad58465
url-mode: use shm_get_many()
If we have lots of URLs, we use up a *lot* of SHM buffers (and thus
pools). Each and every one is a single mmap(), of at least 4K.

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

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

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

Finally, we iterate the URLs again, this time to actually render them.
2021-07-15 18:39:41 +02:00
Daniel Eklöf
7533684d8f
shm: add shm_get_many() - allows buffers to share a single pool
shm_get_many() always returns new buffers (i.e. never old, cached
ones). The newly allocated buffers are also marked for immediate
purging, meaning they’ll be destroyed on the next call to either
shm_get_buffer(), or shm_get_many().

Furthermore, we add a new attribute, ‘locked’, to the buffer
struct. When auto purging buffers, look at this instead of comparing
cookies.

Buffer consumers are expected to set ‘locked’ while they hold a
reference to it, and don’t want it destroyed behind their back.
2021-07-15 18:39:23 +02:00
Daniel Eklöf
5e64c67c25
render: search: set clip region
Fixes crash when the search box has been reduced in height, due to
limited window space.
2021-07-15 18:27:10 +02:00
Daniel Eklöf
628fd39098
render: scrollback indicator: improve handling of very small window sizes 2021-07-15 18:26:26 +02:00
Daniel Eklöf
e259f460f3
render: margins: use correct background color
* Sync actual color used, with how render_cell() selects the
  background color
* Use color_dim_for_search(), not color_dim()
2021-07-15 18:24:27 +02:00
Daniel Eklöf
fcc2e62a7d
render: track alpha directly, rather whether to use it or not 2021-07-15 18:23:49 +02:00
Daniel Eklöf
9658e9cc18
render: tiocswinsz: don’t remove/close the fd passed as argument
There’s a chance the resize timeout FD was closed, and *reused*, after
epoll() told us the FD is readable, but before our callback runs.

Thus, closing the FD provided as an argument is dangerous, as it may
refer to something completely different.
2021-07-14 20:14:10 +02:00
Daniel Eklöf
0c777d825d
Revert "render: don’t assume PIXMAN_a8r8g8b8 for color glyphs"
This reverts commit 9b4796e996.

Sub-pixel anti-aliasing also uses 32-bit glyphs (but x8r8g8b8, instead
of a8r8g8b8)...
2021-07-14 19:56:11 +02:00
Daniel Eklöf
9b4796e996
render: don’t assume PIXMAN_a8r8g8b8 for color glyphs
We may want to use PIXMAN_b8g8r8a8 on big-endian in the future.
2021-07-14 19:46:18 +02:00
Daniel Eklöf
85b63b5e4a
render: require glyph count > 0 and cell-cols also for forced double-width PUAs 2021-07-02 16:48:46 +02:00
Daniel Eklöf
396a5ff79b
allow-overflowing-double-width-glyphs: take glyph offset into account
A narrow, but offset:ed glyph should still be considered double
width.

This patch also fixes a crash, when the maybe-double width glyph is in
the last column. This is a regression.
2021-07-02 16:31:14 +02:00
Daniel Eklöf
cf46acc68f
render: don’t look at glyphs[0]->cols when determining if overflow should be allowed
Use ‘cell_cols’ instead, which is the number of cells we’ll actually
be using.
2021-06-30 18:01:03 +02:00
Daniel Eklöf
fe8ca23cfe
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 17:30:49 +02:00
Daniel Eklöf
b14524215b
render: use cell cols from compose chain, not grapheme
fcft’s view of how many columns a grapheme cluster is may differ from
our own. Make sure the rendered glyph matches the number of columns
that were allocated when the cluster was printed.
2021-06-24 17:30:48 +02:00
Daniel Eklöf
c0d9f92e1a
render: don’t modify the cell’s x position. Fixes broken underlines 2021-06-24 17:30:47 +02:00
Daniel Eklöf
51295cd7a2
render: we’ve already assigned ‘base’ a couple of lines higher up 2021-06-24 17:30:46 +02:00
Daniel Eklöf
96ff29bbd3
render: repair parenthesis after rebase 2021-06-24 17:30:46 +02:00
Daniel Eklöf
b471fe31b1
render: ensure ‘cell_cols’ have been initialized 2021-06-24 17:30:46 +02:00
Daniel Eklöf
50be924285
render: handle fcft_glyph_rasterize() failure correctly 2021-06-24 17:30:46 +02:00
Daniel Eklöf
bd98cb6a73
render: use column count from grapheme instead of first glyph, when we have one 2021-06-24 17:30:46 +02:00
Daniel Eklöf
b9ef703eb1
wip: grapheme shaping 2021-06-24 17:30:45 +02:00
Daniel Eklöf
2a83202fdd
wayland: apply CSD/SSD changes in the surface configure event
The configure event asks the client to change its decoration
    mode. The configured state should not be applied immediately.
    Clients must send an ack_configure in response to this event.
    See xdg_surface.configure and xdg_surface.ack_configure for
    details.

In particular, ”the configured state should *not* be applied
immediately”.

Instead, treat CSD/SSD changes like all other window dimension related
changes: store the to-be mode in win->configure, and apply it in the
surface configure event.

This fixes an issue where foot incorrectly resized the window when the
server switched between CSD/SSD at run-time.
2021-06-23 12:37:56 +02:00
Daniel Eklöf
7334b53d83
config: add csd.button-color option
This option controls the foreground color of the
minimize/maximize/close buttons. I.e. the color used to draw the
minimize/maximize/close glyphs.

It defaults to default background color.
2021-06-20 10:44:50 +02:00
Daniel Eklöf
07b455e882
render: don’t create/destroy the title update timer each time
Create it once when instantiating the terminal. Add a boolean to track
whether the timer is running or not.
2021-06-18 15:53:47 +02:00
Daniel Eklöf
535c82d628
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-18 15:36:58 +02:00
Daniel Eklöf
cf81fff062
config: add underline-offset option
This option allows the user to configure a custom underline
offset. That is, use the user provided offset instead of the font
provided one.

Closes #490
2021-06-17 17:54:21 +02:00
Daniel Eklöf
94b549f93e
vt: emit a tab character if all cells between cursor and tab stop are empty
TAB (\t) move the cursor to the next tab stop. That’s it, according to
the specification.

However, many terminal emulators try to keep tabs in the grid, to be
able to e.g. copy them. That is, copying a text chunk containing tabs
should result in tabs being pasted, not spaces.

In order to do that, we need to print a tab character to the grid. To
improve text reflow of tabs, we also print spaces to the subsequent
cells, up until (but not including) the next tab stop.

However, we can only do this if all the cells between the cursor and
the next tab stop are empty, since (obviously), we cannot overwrite
pre-existing characters.

Finally, while some fonts render tabs as spaces (i.e. an empty glyph),
some use a glyph representing “unprintable” characters, or
similar. Thus, we need to exclude cells with tab characters when
rendering.
2021-06-08 19:53:26 +02:00
Daniel Eklöf
39560a6ff1
render: reverse video only swaps *default* fg/bg
This matches XTerm behavior, and fixes vttest 11.6.6.2:

Test non-VT100 ->
Test ISO-6429 colors ->
Test of VT102-style features with BCE ->
Test of screen features
2021-06-08 19:51:13 +02:00