Commit graph

621 commits

Author SHA1 Message Date
Daniel Eklöf
96f23b4c64
ime: track IME focus independently from keyboard focus
Replace the seat->ime.focused boolean with a terminal instace pointer,
seat->ime_focus.

Set and reset this on ime::enter() and ime::leave() events, and use
this instead of seat->kbd_focus on all other IME events.

This fixes two issues:

a) buggy compositors that sometimes sends an IME enter event without
  first having sent a keyboard enter event.

b) seats may be IME capable while still lacking the keyboard
  capability. Such seats will *always* see IME enter events without a
  corresponding keyboard enter event.
2022-06-15 19:25:33 +02:00
Daniel Eklöf
2cbcfb3159
render: fix refresh logic of pending csd|search|url
Our CSDs, the search-box and URL labels are all implemented using
sub-surfaces, synchronized with the main grid.

This means we *must* commit the main surface as well, when updating
one of these sub-surfaces.

The logic for doing so in the frame callback was flawed, and only
triggered when the main grid was actually dirty.

That is, e.g. search box updates that did not also resulted in grid
updates (for example - pasting a search criteria that doesn’t match),
did not result in a UI refresh.

Closes #1040
2022-04-24 12:04:06 +02:00
Daniel Eklöf
2085621bf4
render: overlay: reset ‘start_col’ after handling the first row 2022-04-17 19:26:54 +02:00
Daniel Eklöf
24ee3dcc10
wayland: refactor: remove ‘struct config’ pointer from wayland struct
The global config doesn’t necessarily reflect the correct
configuration to use - we should *always* use the current terminal
instance’s conf pointer.

* Move selection override modifier mask to the key_binding_set struct
* Always warn if XDG activation is unavailable, not just if
  bell.urgent is set (we no longer have access to this information)
* Pass ‘bool presentation_timings’ as a parameter to wayl_init()
* Remove ‘presentation_timings’ member from the ‘terminal’ struct

Closes #932
2022-04-17 16:34:04 +02:00
Daniel Eklöf
9e3c71c277
render: overlay: apply weston quirk 2022-04-17 11:04:27 +02:00
Daniel Eklöf
90c91d6148
search/render: initial support for highlighting all visible matches
Before this patch, only the currently “selected” match was
highlighted (by having the “selected” attribute, and by *not* dimming
it, like the rest of the grid during a scrollback search).

With this patch, we now highlight matches within the viewport. While
searching, only the “primary” match is searched-for, and tracked.

Then, when rendering a frame, we find all “secondary” matches as
well. “holes” are added to the search-mode overlay by the means of an
search-match iterator.

The iterator’s text matching logic is *very* similar to what we do
when the search criteria has been updated, and we re-search the
scrollback. It should be possible to refactor this, and share code.
2022-04-16 19:26:20 +02:00
Daniel Eklöf
78fcdc5787
render: implement ‘flash’ and search mode’s ‘dimming’ with a sub-surface
Search mode and ‘flash’ (OSC-555) both achieves similar visual
effects: flash tints the entire window yellow, and search mode dims
it (except the search match).

But, they do so in completely different ways. Search mode is detected
in render_cell(), and the colors are then dimmed there.

Flash is implemented by blending a yellow, semi-transparent color on
top of the rendered grid.

This patch replaces those two implementations with a single one. We
add a new sub-surface, called the ‘overlay’. In normal mode, it’s
unmapped.

When either search mode, or flash, is enabled, we enable it, and
fill it with a semi-transparent color. Yellow for ‘flash’, and
“black” (i.e. no color) for search mode.

The compositor then blends it with the grid. Hopefully on the GPU,
meaning it’ll be faster than if we blend in software.

There are more performance benefits however. By using a separate
surface, we can do much better damage tracking.

The normal grid rendering code no longer have to care about neither
search mode, nor flash. Thus, we get rid of a couple of ‘if’
statements in render_cell(), which is nice. But more importantly, we
can drop full grid repaints in a couple of circumstances:

* Entering/exiting search mode
* Every frame while flash is active

Now, when rendering the search mode overlay, we do want to do some
damage tracking, also of the overlay.

This, since search mode doesn’t dim the *entire* window. The search
match is *not* dimmed. This is implemented by punching a hole in the
overlay sub-surface. That is, we make part of it *fully*
transparent. The basic idea is to set a clip region that excludes the
search match, and then dim the rest of the overlay.

It’s slightly more complicated than that however, if we want to reuse
the last frame’s overlay buffer (i.e we don’t want to re-render
the *entire* overlay every frame).

In short, we need to:

* Clear (punch hole) in areas that are part of this frame’s search
  match, but not the last frame’s (since those parts are _already_
  cleared).
* Dim the areas that were part of the last frame’s search match, but
  aren’t anymore (the rest of the overlay should already be dimmed).

To do this, we save the last frame’s “holes” (as a pixman
region). Then, when rendering the next frame, we first calculate the
new frame’s “holes” region.

The region to clear is “this frame’s holes minus last frame’s holes”
The region to dim is “last frame’s holes minus this frames holes”.

Finally, we compute the bounding box of all modified cells by taking
the union of the two diff regions mentioned above. This allows us to
limit the buffer damage sent to the compositor.
2022-04-16 18:31:02 +02:00
Daniel Eklöf
129deaffa8
wayland: optionally disable pointer input on subsurfaces
We have a number of sub-surfaces for which we are *not* interrested in
pointer (or touch) input.

Up until now, we’ve manually dealt with these, by recognizing these
surfaces in all pointer events, and ignoring them.

But, lo and behold, there are better ways of doing this. By clearing
the subsurface’s input region, the compositor will do this for us -
when a pointer is outside a surface’s input region, the event is
passed to the next surface underneath it.

This is exactly what we want! Do this for all subsurfaces, *except*
the CSDs.
2022-04-16 17:41:14 +02:00
Daniel Eklöf
979f48a62f
render: take (visible) CSD border size into account when setting initial size 2022-04-16 11:42:26 +02:00
Daniel Eklöf
f9103d4381
wayland: add helper functions wayl_win_csd_{titlebar,borders}_visible() 2022-04-16 11:42:25 +02:00
Daniel Eklöf
0e477e2c5e
render: take visible border width into account when setting window geometry
This fixes e.g. window snapping in GNOME.
2022-04-16 10:57:45 +02:00
Daniel Eklöf
5b1f1602bc
refactor: add a ‘range’ struct, grouping a start and end coord together 2022-04-09 15:09:02 +02:00
Daniel Eklöf
5ce1589c60
render: ensure an underline cursor is not positioned too low
The underline cursor is positioned just below regular underlines. A
bug in the positioning logic related to this, sometimes resulted in
the cursor being thinner than what it should be, or even invisible.

Fixes #1005
2022-04-06 18:17:59 +02:00
Daniel Eklöf
757768dbe5
config: rename csd.color.close -> quit
This fixes a compilation error on FreeBSD:

../../foot/render.c:2055:45: error: no member named 'epoll_shim_close' in 'struct config::(anonymous at ../../foot/config.h:254:9)'
        conf_color = &term->conf->csd.color.close;
                      ~~~~~~~~~~~~~~~~~~~~~ ^

/usr/local/include/libepoll-shim/epoll-shim/detail/common.h:8:15:
note: expanded from macro 'close': #define close epoll_shim_close
2022-02-09 17:51:05 +01:00
Ashish SHUKLA
4df73585e7
Specify a fallback mouse cursor
`text' cursor is not available in lots of cursor themes, but `xterm'
is, so specify `xterm' as a fallback cursor name.
2022-02-07 22:15:47 +05:30
Daniel Eklöf
e4f9dc7d58
render: add render_xcursor_is_valid()
Returns true if the provided cursor name is non-NULL, and exist in the
currently loaded xcursor theme.
2022-02-07 17:28:37 +01:00
Daniel Eklöf
92ebe00927
render: call wl_cursor_theme_get_cursor() earlier
Before this patch, wl_cursor_theme_get_cursor() was called in the FDM
hook, just before we’re about to update the mouse cursor “for real”.

This relies on seat->pointer.xcursor still being valid. This is true
as long as we’re only using our compiled-in static xcursor names, but
not otherwise.

Now, we call wl_cursor_theme_get_cursor() in render_xcursor_set(). At
this point, we *know* seat->pointer.xcursor is valid.

There is a slight chance of added overhead here, if the client
application is switching mouse grabbing on/off rapidly. Before, the
calls to wl_cursor_theme_get_cursor() would automatically be
throttled.

However, the main point of delaying the actual pointer update to the FDM
hook is to throttle the *Wayland* calls. And this is still happening:
wl_cursor_theme_get_cursor() is client-side only.
2022-02-07 17:28:28 +01:00
Daniel Eklöf
003ea4904d
render: resize: add TODO: translate pivot coords 2022-02-07 10:42:32 +01:00
Daniel Eklöf
a187271ca4
render: resize: finalize selection before reflowing the grid
This fixes a crash caused by the selection’s pivot point not being
translated during reflow.

While we could simply reflow the pivot point as well, testing shows
irregular behavior with ongoing selections across window resizes, with
different compositors behaving differently.

For now, we simply finalize the selection, instead of trying to handle
ongoing selections.

Closes #922
2022-02-07 10:38:30 +01:00
Daniel Eklöf
e0227266ca
fcft: adapt to API changes in fcft-3.x
Fcft no longer uses wchar_t, but plain uint32_t to represent
codepoints.

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

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

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

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

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

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

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

Other fcft API changes:

* fcft_glyph_rasterize() -> fcft_codepoint_rasterize()
* font.space_advance has been removed
* ‘tags’ have been removed from fcft_grapheme_rasterize()
* ‘fcft_log_init()’ removed
* ‘fcft_init()’ and ‘fcft_fini()’ must be explicitly called
2022-02-05 17:00:54 +01:00
Pranjal Kole
0da19a81bc replace gettimeofday with clock_gettime
POSIX.1-2008 has marked gettimeofday(2) as obsolete, recommending the
use of clock_gettime(2) instead.

CLOCK_MONOTONIC has been used instead of CLOCK_REALTIME because it is
unaffected by manual changes in the system clock. This makes it better
for our purposes, namely, measuring the difference between two points in
time.

tv_sec has been casted to long in most places since POSIX does not
define the actual type of time_t.
2022-01-15 21:35:45 +05:30
Daniel Eklöf
891fce6236
config: convert tweak.render_timer to an enum 2022-01-13 12:08:20 +01:00
Daniel Eklöf
abec4f4e71
render: csd: scale border width when rendering the CSD border’s visible part 2021-12-29 18:11:51 +01:00
Daniel Eklöf
8ac2bcff67
render: limit the unfocused block cursor’s outline width
Ensure the outline width doesn’t exceed the cell width/height.
2021-12-29 18:05:00 +01:00
Daniel Eklöf
ef8d5ebca0
render: scale the width out the outline of the unfocused block cursor 2021-12-28 20:57:24 +01:00
Daniel Eklöf
c2bf2d3650
csi: store color index, not actual color, in cell’s fg/bg attributes
When using indexed colors (i.e. SGR 30/40/90/100), store the index
into the cell’s fg/bg attributes, not the actual color value.

This has a couple of consequences:

Color table lookup is now done when rendering. This means a rendered
cell will always reflect the *current* color table, not the color
table that was in use when the cell was printed to.

This simplifies the OSC-4/104 logic, since we no longer need to update
the grid - we just have to damage it to trigger rendering.

Furthermore, this change simplifies the VT parsing, since we no longer
need to do any memory loads (except loading the SGR parameter values),
only writes.
2021-12-26 12:37:48 +01:00
Daniel Eklöf
41f7f8b7fa
render: make sure ‘maximized’ button doesn’t use negative coordinates 2021-12-22 20:31:38 +01:00
Daniel Eklöf
521bd84a99
config: csd.border_width now always reflects the full/total width 2021-12-22 20:21:46 +01:00
Daniel Eklöf
90cfdcf1a5
Merge branch 'window-menu' 2021-11-30 22:10:27 +01:00
Daniel Eklöf
3afe317e46
render: fix csd border rendering glitch when width > 5px
CSD borders are always *at least* 5px. If url.border-width=0, those
5px are all fully transparent (and act as interactive resize handles).

As csd.border-width increases, the number of transparent pixels
decrease. Once csd.border-width >= 5, the border is fully opaque.

When csd.border-width > 5, then width of the border is (obviously)
more than 5px. But, when rendering the opaque part of the border, we
still used 5px for the invisible part, which caused some pixman
rectangles to have negative x/y coordinates.

This resulted in rendering glitches due to overflows in pixman when
rendering the borders.

The fix is to ensure the total border size is always at least, but
not *always* 5px. That is, set it to max(5, csd.border-width).

This patch also fixes an issue where the CSD borders were not
dimmed (like the titlebar) when the window looses input focus.

Closes #823
2021-11-29 19:32:49 +01:00
Jonas Ådahl
38741baf9a input: Add support for xdg_toplevl.show_window_menu()
This makes, if the compositor supports it, the window menu appear when
right clicking on the title bar.
2021-11-29 16:26:40 +01:00
Daniel Eklöf
d46af6bd7a
term: track cell color source
Each cell now tracks it’s current color source:

* default fg/bg
* base16 fg/bg (maps to *both* the regular and bright colors)
* base256 fg/bg
* RGB

Note that we don’t have enough bits to separate the regular from the
bright colors. These _shouldn’t_ be the same, so we ought to be
fine...
2021-11-20 16:46:38 +01:00
Daniel Eklöf
c01904a2c7
config: add [colors].dim0-7
This allows you to configure custom colors to be used when colors are
being dimmed (`\E[2m`).

It is implemented by color matching (just like
bold-text-in-bright=palette-based); the color-to-be-dimmed is matched
against the current color palette.

If it matches one of the regular colors (colors 0-7), the
corresponding “dim” color will be used.

If it matches one of the bright colors (colors 8-15), the
corresponding “regular” color will be used (but *only* if the “dim”
color has been set).

Otherwise, the color is dimmed by reducing its luminance.

The default behavior, i.e. when dim0-7 hasn’t been configured, is to
dim by reducing luminance for *all* colors. I.e. we don’t do any color
matching at all. In particular, this means that dimming a bright color
will *not* result in the corresponding “regular” color.

Closes #776
2021-11-13 17:39:08 +01:00
Daniel Eklöf
d29c3cf7b7
config: add {str,value}_to_uint{16,32}()
This allows us to pass the final pointer directly to the conversion
functions, as well as allowing us to print outside-range errors.
2021-11-13 11:04:29 +01:00
Daniel Eklöf
e69c3e5b1e
render: csd_part: we don’t use the ‘src’ pixman image 2021-10-29 19:31:09 +02:00
Daniel Eklöf
5e4de143de
csd: add support for a visible border
When we’re using CSDs, we’ve up until now rendered a 5px invisible
border. This border handles interactive resizing. I.e. hovering it
changes the mouse cursor, and mouse button events are used to start an
interactive resize.

This patch makes it possible to color part of (or the entire) border,
with a configurable color.

To facilitate this, two new options have been added:

* csd.border-width
* csd.border-color

border-width defaults to 0, resulting in the look we’re used to.

border-color defaults to the title bar color. If the title bar color
hasn’t been set, it defaults to the default foreground color (just
like the title bar color does).

This means that, setting border-width but not border-color, results in
a border that blends with the title bar.
2021-10-27 18:32:28 +02:00
Daniel Eklöf
5b66592a57
render: tab -> spaces 2021-10-20 20:03:15 +02:00
feeptr@codeberg.org
650cfa18ef config, render: scrollback indicator: allow configuring scrollback indicator colors 2021-10-09 16:59:52 -04:00
feeptr
304aacdb7a fix crashes when resizing after CSD enabled at runtime with csd.size = 0 2021-10-04 18:14:58 -04:00
Daniel Eklöf
37b15adcd8
term: turn ‘box-drawings’ array into three dynamically allocated arrays
The box_drawings array is now quite large, and uses up ~4K
when *empty*.

This patch splits it up into three separate, dynamically allocated
arrays; one for the traditional box+line drawing and block elements
glyphs, one for braille, and one for the legacy computing symbols.

When we need to render a glyph, the *entire* array (that it belongs
to) is allocated.

I.e this is one step closer to a dynamic glyph cache (like the one
fcft uses), but doesn’t go all the way.

This is especially nice for people with
‘box-drawings-uses-font-glyphs=yes’; for them, the custom glyphs now
uses 3*8 bytes (for the three array pointers), instead of 4K.
2021-09-14 09:50:49 +02:00
Daniel Eklöf
896825f50c
render: codespell: aquire -> acquire 2021-09-12 19:22:14 +02:00
Daniel Eklöf
b4c759e2de
box-drawing: add braille characters
Render braille ourselves, instead of using font glyphs. Decoding a
braille character is easy enough; there are 256 codepoints,
represented by an 8-bit integer (i.e. subtract the Unicode codepoint
offset, 0x2800, and you’re left with an integer in the range 0-255).

Each bit corresponds to a dot. The first 6 bits represent the upper 6
dots, while the two last bits represent the fourth (and last) row of
dots.

The hard part is sizing the dots and the spacing between them.

The aim is to have the spacing between the dots be the same size as
the dots themselves, and to have the margins on each side be half the
size of the dots.

In a perfectly sized cell, this means two braille characters next to
each other will be evenly spaced.

This is however almost never the case. The layout logic currently:

* Set dot size to either the width / 4, or height / 8, depending on
  which one is smallest.

* Horizontal spacing is initialized to the width / 4

* Vertical spacing is initialized to the height / 8

* Horizontal margins are initialized to the horizontal spacing / 2

* Vertical margins are initialized to the vertical spacing / 2.

Next, we calculate the number of “remaining” pixels. That is, if we
add the left margin, two dots and the spacing between, how many pixels
are left on the horizontal axis?

These pixels are distributed in the following order (we “stop” as soon
as we run out of pixels):

* If the dot size is 0 (happens for very small font sizes), increase
  it to 1.
* If the margins are 0, increase them to 1.
* If we have enough pixels (need at 2 horizontal and 4 vertical),
  increase the dot size.
* Increase spacing.
* Increase margins.

Closes #702
2021-09-12 19:22:12 +02:00
Daniel Eklöf
26859a5168
render: unref clip region 2021-09-04 20:08:23 +02:00
Daniel Eklöf
ae70596a50
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-16 19:15:41 +02:00
Daniel Eklöf
41a8f2fc65
render: run the “overflowing glyphs” prepass *before* rendering sixels
This fixes an issue where the left-most column of a sixel was
“overwritten” by the cell content.

This patch also rewrites the prepass logic, to try to reduce the
number of loads performed.

The new logic loops each row from left to right, looking for dirty
cells. When a dirty cell is found, we first scan backwards, until we
find a non-overflowing cell. That cell is unaffected by the
overflowing cell we’re currently dealing with.

We can also stop as soon as we see a dirty cell, since that cell will
already have been dealt with.

Then, we scan forward, dirtying cells until we see a non-overflowing
cell. That first non-overflowing cell is also dirtied, but after that
we break.

The last loop, that scans forward, advances the same cell pointer used
in the outer loop.
2021-08-11 18:26:00 +02:00
Daniel Eklöf
1c43fdbea4
box-drawing: add U+1FB3C-U+1FB6F, U+1FB9A and U+1FB9B
These are the “wedges” from the Unicode 13 “Legacy Computing” symbols.

Closes #474
2021-08-05 18:25:01 +02:00
Daniel Eklöf
03f952cf4d
term: consolidate shutdown related state into an anonymous struct 2021-07-31 19:08:51 +02:00
Daniel Eklöf
384b1c330f
term: asynchronous client application termination
When the foot window is closed, and we need to terminate the client application,
do this in an asynchronous fashion:

* Don’t do a blocking call to waitpid(), instead, rely on the reaper callback
* Use a timer FD to implement the timeout before sending SIGKILL (instead of
  using SIGALRM).
* Send SIGTERM immediately (we used to *just* close the PTY, and then wait 2
  seconds before sending SIGTERM).
* Raise the timeout from 2 seconds to 60

Full shutdown now depends on *two* asynchronous tasks - unmapping the window,
and waiting for the client application to terminate.

Only when *both* of these have completed do we proceed and call term_destroy(),
and the user provided shutdown callback.
2021-07-31 18:18:48 +02:00
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