Commit graph

440 commits

Author SHA1 Message Date
Daniel Eklöf
a6fc8b5da4
config: line-height, letter-spacing: values are in pt by default, but we allow px
If the value is specified without a unit, then the value is assumed to
be in points, subject to DPI scaling.

The value can optionally have a ‘px’ suffix, in which case the value
is treated as a raw pixel count.
2021-01-11 09:31:08 +01:00
Daniel Eklöf
3eba48d74b
render: offset all glyphs with {horizontal,vertical}-letter-offset 2021-01-11 09:31:06 +01:00
Daniel Eklöf
ba48109a9b
Merge branch 'center-grid-content'
Closes #273
2021-01-07 12:08:31 +01:00
Daniel Eklöf
124759bd2c
render: sixel: fix assertion: x/y coords may be outside visible area
But when they are, width/height must be 0.
2021-01-06 16:57:07 +01:00
Daniel Eklöf
e14c592f39
config: add optional ‘center’ argument to ‘pad’
When set, the grid contents is centered in the window. I.e. the
left/right and top/bottom margins are equal (+- 1px).

This causes the content to “jump” while doing an interactive resize,
but may still be preferred in e.g. a tiling WM.

Closes #273
2021-01-06 11:17:29 +01:00
Daniel Eklöf
dc676f96ce
render: codespell: accomodate -> accommodate 2021-01-04 19:49:24 +01:00
Daniel Eklöf
482690e5fb
render: draw combining characters on top of colored bitmap glyphs (emoji) 2021-01-04 18:32:55 +01:00
Craig Barnes
39b2e46e72 Use wrappers from macros.h instead of bare GCC attributes/pragmas 2021-01-03 08:56:47 +00:00
Daniel Eklöf
5cc2f94668
Merge branch 'box-drawing'
Closes #198
2021-01-03 00:08:08 +01:00
Daniel Eklöf
ae6d8e0c7f
render: mark cell overflowed into as dirty
When tweak.allow-overflowing-double-width-glyphs=yes, then certain
glyphs are allowed to overflow into the neighbouring cell.

However, if the cell “owning” the double-width glyph is erased (_only_
that cell), then the cell overflowed into is not redrawn, causing
part of the double-width glyph to remain on screen.

To avoid checking for these glyphs when printing to the terminal (i.e
at parse time), simply mark both cells as dirty when we render the
overflowing glyph.

Yes, this means that the cells will always be re-rendered. We count on
them only making up a small portion of the screen.
2021-01-02 22:31:07 +01:00
Daniel Eklöf
25d2b03a5c
box-drawing: SEXTANTS, U+1fb00-1fb3b 2021-01-01 21:09:37 +01:00
Daniel Eklöf
7acdb3a0dd
box-drawing: add infrastructure for rendering box drawing characters ourselves
* ‘term’ struct contains an array of 160 fcft glyph pointers
* the glyph pointers are lazily allocated when we need to draw a box
  drawings character
* Filtering out box drawings characters is easy - they are (except
  unicode 13, which isn’t handled yet )all in a single range.
2021-01-01 21:09:31 +01:00
Daniel Eklöf
339acc57cf
render: fix rounding error when calculating background color with alpha
We use pre-multiplied alpha color channels, but were having bad
rounding errors due to the alpha divider being truncated to an
integer.

The algorithm for pre-multiplying a color channel is:

  alpha_divider = 0xffff / alpha
  pre_mult_color = color / alpha_divider

In order to fix the rounding errors, we could turn ‘alpha_divider’
into a double.

That however would introduce a performance penalty since now we’d need
to do floating point math for each cell.

The algorithm can be trivially converted to:

  pre_mult_color = color * alpha / 0xffff

Since both color and alpa values are < 65536, the multiplication is
“safe”; it will not overflow an uint32_t.

Closes #249
2020-12-20 12:25:12 +01:00
Daniel Eklöf
ae01caee8c
render: ime: ensure cursor is visible 2020-12-08 19:17:46 +01:00
Daniel Eklöf
b270f221d0
render: search: render IME pre-edit text correctly, hopefully 2020-12-07 20:44:15 +01:00
Daniel Eklöf
bcfc468fd0
render: ime: adjust cursor cell index when adjusting glyph offset 2020-12-07 20:44:15 +01:00
Daniel Eklöf
d46dcd8ef5
render: ime: wip: pre-edit 2020-12-07 20:44:14 +01:00
Daniel Eklöf
7c420004fb
render: search: don’t access term->search.buf[] directly 2020-12-07 20:44:14 +01:00
Daniel Eklöf
1ea3674029
render: codespell: cound -> count 2020-12-07 20:44:13 +01:00
Daniel Eklöf
b4a0f5b13b
render: search: glyph_offset is in *cells*, cursor position in *characters*
When calculating the offset into the search string, from where to
start rendering, take into account that the cursor position is
in *characters*, and the glyph-offset is in *cells*.
2020-12-07 20:44:13 +01:00
Daniel Eklöf
5ffa65a2e3
render: search: wcsnlen() -> wcswidth() 2020-12-07 20:44:13 +01:00
Daniel Eklöf
a552610fdb
render: search: handle multi-column characters 2020-12-07 20:44:13 +01:00
Daniel Eklöf
dca35215d0
render: search: render colorized glyphs (emojis) correctly 2020-12-07 20:44:13 +01:00
Daniel Eklöf
9ce0edc8bb
render: ime: don’t render pre-edit string in grid while searching
While doing a scrollback search, the pre-edit string should be
rendered in the search box, not in the grid.

Note that we don’t yet support IME in scrollback search mode. This
patch simply prevents the pre-edit text being rendered in the grid,
in the “background”, while searching.
2020-12-07 20:44:12 +01:00
Daniel Eklöf
2078e1675d
render: ime: draw a ‘bar’ cursor when the pre-edit cursor’s begin == end 2020-12-07 20:44:11 +01:00
Daniel Eklöf
83d3ae10ae
render: ime: don’t render cursor if cursor begin == end 2020-12-07 20:44:10 +01:00
Daniel Eklöf
e9f99df2ab
render: ime: calculate on-screen cursor position ourselves
The position calculated by render_grid() may be -1,-1 if the cursor is
currently hidden.

This fixes a crash when trying to input IME while the cursor is
hidden.
2020-12-07 20:44:10 +01:00
Daniel Eklöf
4d90b200f1
render: ignore IME preedit state when deciding which cursor style to render 2020-12-07 20:44:10 +01:00
Daniel Eklöf
05083110c3
ime: make IME compile-time optional 2020-12-07 20:44:10 +01:00
Daniel Eklöf
8c3d48c5cd
ime: render pre-edit text
This is done by allocating cells for the pre-edit text when receiving
the text-input::done() call, and populating them by converting the
utf-8 formatted pre-edit text to wchars.

We also convert the pre-edit cursor position to cell positions (it can
cover multiple cells).

When rendering, we simply render the pre-edit cells on-top off the
regular grid. While doing so, we also mark the underlying, “real”,
cells as dirty, to ensure they are re-rendered when the pre-edit text
is modified or removed.
2020-12-07 20:44:10 +01:00
Craig Barnes
adde947fc5 config: replace union in config struct with simple width/height members 2020-11-30 02:24:38 +00:00
Daniel Eklöf
9a498038d6
resize: don’t reflow text on alt screen
Alt screen applications normally reflow/readjust themselves on a
window resize.

When we do it too, the result is graphical glitches/flashes since our
re-flowed text is rendered in one frame, and the application re-flowed
text soon thereafter.

We can’t avoid rendering some kind of re-flowed frame, since we don’t
know when, or even if, the application will update itself. To avoid
glitches, we need to render, as closely as possible, what the
application itself will render shortly.

This is actually pretty simple; we just need to copy the visible
content over from the old grid to the new grid. We don’t bother with
text re-flow, but simply truncate long lines.

To simplify things, we simply cancel any active selection (since often
times, it will be corrupted anyway when the application redraws
itself).

Since we’re not reflowing text, there’s no need to translate e.g. the
cursor position - we just keep the current position (but bounded to
the new dimensions).

Fun thing: ‘less’ gets corrupted if we don’t leave the cursor at
the (new) bottom row. To handle this, we check if the cursor (before
resize) is at the bottom row, and if so, we move it to the new bottom
row.

Closes #221
2020-11-25 07:47:40 +01:00
Daniel Eklöf
90edc09697
render: don’t call term_arm_blink_timer() from multiple threads
We call term_arm_blink_timer() from render_cell(), which runs in
multiple threads.

This caused multiple blink timer FDs to be created and registered with
the FDM, later causing read failures after one of those FDs had been
closed again.

This rarely happened under normal circumstances, but was easy to
trigger when the whole screen was full of blinking text.

As a small optimization, we don’t bother taking the lock if the timer
FD already is valid.

This is safe, because:

1) If the timer FD isn’t valid, we take the lock and then call
    term_arm_blink_timer(), which again checks if the FD is already
    valid.

2) The blink timer FD cannot be closed while we’re rendering cells. It
   is only disabled in the FDM callback, which cannot execute while
   we’re rendering.
2020-11-23 19:26:00 +01:00
Daniel Eklöf
ecaa3b4135
render: no need to call attrs_to_font(), we already have a font reference 2020-11-22 19:29:43 +01:00
Daniel Eklöf
774dd75542
render: allow-overflow: require a space in the next cell
When checking if we should allow a single-width character double-width
glyph to overflow into the next cell, require the next cell to either
be empty, or contain a space.

Closes #203
2020-11-19 19:24:15 +01:00
Daniel Eklöf
690cf0ab54
render: dim/brighten: multiply/divide instead of add/subtract 2020-11-15 21:04:21 +01:00
Daniel Eklöf
2b8e2b3506
render: dim and brighten colors by adjusting luminance
To do this, we need to convert our RGB to HSL, adjust luminance, and
then convert back to RGB.
2020-11-15 20:05:01 +01:00
Daniel Eklöf
8e779b356e
render: remove debug output 2020-11-15 19:40:25 +01:00
Daniel Eklöf
ee5607b9eb
render: brighten color of bold text if default.bold-text-in-bright=yes
Closes #199
2020-11-14 11:22:35 +01:00
Daniel Eklöf
4b645376fd
render: improve sixel rendering performance
Up until now, we’ve always re-rendered the entire image (the part of
it that is visible at least), *every* time we render a frame.

This is not really needed. In many cases, the cells covered by the
image hasn’t been touched.

Rewrite the sixel rendering code to only render the part of the sixel
image that covers dirty cells.

This is done on a per-row basis. I.e. Each *row* of the image that
covers at least one dirty cell is re-rendered. For this to work, we
now also dirty all cells covered by the image when we emit the image.

Finally, for this to work, the sixels need to be rendered *before* we
do the normal grid render pass (since that will clear all dirty bits).
2020-11-13 16:54:40 +01:00
Daniel Eklöf
beaf220f39
tiocswinsz: fix compilation error on e.g. ppc64
On some platforms, TIOCSWINSZ has a very large value, >
0x80000000.

On some platforms, the `request` argument to `ioctl(3)` is an `int`.

For platforms where both of the above is true, gcc will warn (and
error out if compiled with `-Werror`) on:

  ioctl(fd, TIOCSWINSZ, ...)

To silence this warning, we need to cast `TIOCSWINSZ` to an
integer.

However, doing this on platforms where `request` is an `unsigned long`
will result in `TIOCSWINSZ` being sign-extended (and thus we end up
with an invalid value).

It seems that casting to `unsigned int` works in both cases; it
silences the long -> int conversion warning, while also preserving the
correct value in all cases.
2020-10-29 18:06:04 +01:00
Daniel Eklöf
4283e96865
render: blink switches between foreground and dimmed foreground 2020-10-22 18:41:47 +02:00
Daniel Eklöf
f928c1fa68
wayland: properly restore window size when being un-tiled
Bind to xdg-shell version 2 if available, as this enables us to
track our window’s ‘tiled’ state in the ‘configure’ events.

This in turn allows us to stash the ‘old’ window size when being
tiled, to be used again when restoring the window size when un-tiled.
2020-10-20 20:58:03 +02:00
Daniel Eklöf
f2da822e9a
render: resize: call sixel_reflow() after reflowing grids 2020-10-09 07:44:16 +02:00
Daniel Eklöf
7c6686221f
bell: optionally render margins in red when receiving BEL
Add anew config option, ‘bell=none|set-urgency’. When set to
‘set-urgency’, the margins will be painted in red (if the window did
not have keyboard focus).

This is intended as a cheap replacement for the ‘urgency’ hint, that
doesn’t (yet) exist on Wayland.

Closes #157
2020-10-08 19:55:32 +02:00
Daniel Eklöf
279341dd8e
render: apply opacity correctly when in reverse video mode 2020-10-08 19:53:11 +02:00
Daniel Eklöf
7ffd31e13a
render: remove render_refresh_margins() 2020-09-29 10:08:59 +02:00
Daniel Eklöf
b19e07ad1c
render: term->render.margins is used to explicitly tell us to re-render margins 2020-09-29 10:04:41 +02:00
Daniel Eklöf
2e7102c956
render: fix rounding errors when setting initial window size and scale != 1
An odd cell width/height sometimes resulted in an odd grid
size. Combined with a scaling factor of e.g. 2, that led to a rounding
error when converting pixel sizes to logical window sizes.

As a result, the _next_ configure event would cause us to loose a
pixel, which led to us dropping a row from the grid.
2020-09-17 17:37:58 +02:00
Daniel Eklöf
fdfdbba9a0
render: best-effort attempt to set initial window size in chars when scale != 1
The initial window size is set *before* we’re initially mapped. This
means we don’t (yet) know on which output we’ll be mapped. _That_
means we don’t know which scaling factor to use.

This implements a best effort attempt, where we use the “guessed”
scaling factor. This will always be correct in single-monitor
configurations, but may be wrong in multi-monitor setups with
different scaling factors.
2020-09-14 17:36:56 +02:00