DiffState keeps track of a virtual cursor in order to skip emitting
cursor location changes when a previous text change has already moved
the cursor to the desired position. However, currently the code always
advances the cursor by 1 column for each added text change regardless
of the width of the text.
Fix behavior by advancing the cursor by the width of the text.
To avoid having to add a new variable, make 'self.cursor' contain
the cursor position for the next cell instead of the current cell.
In addition, add a test verifying the behavior.
The present code for creating diffs between surface regions processes
visible cells from both surfaces in lockstep. This only works when
the cells at each position have the same width in each surface.
When widths differ, the iterators go out of sync and end up comparing
cells in different positions of the surface, resulting in incorrect
diffs.
Fix this by instead iterating over the source surface ('other'), and
for each cell locating the corresponding cell in the target surface
to compare against.
To apply the fix to all three diffing functions, outline the per-line
code to a new function and call it in each function.
Also add a test that verifies the behavior in such case with differing
cell widths.
Procedure is:
* Download the `NerdFontsSymbolsOnly.zip` release asset
* Extract the font into assets/fonts
* Run the codegen to update nerdfonts_data.rs:
`cd termwiz/codgen ; cargo run`
* Apply formatting: `cd ../../ ; cargo +nightly fmt`
* Update the list of symbols in the docs:
* edit `docs/config/lua/wezterm/nerdfonts.md`
* delete the table
* Run the embedded vim command that will regenerate the table
refs: https://github.com/wez/wezterm/pull/4656
When MaxColors is 16M, the "palette index" is treated by "setaf" as a true color, not the classic 256 color. Users of `PaletteIndex` expects 256 color and let's fallback to SGR.
For example, setaf on tmux-direct is:
setaf=\E[%?%p1%{8}%<%t3%p1%d%e38:2::%p1%{65536}%/%d:%p1%{256}%/%{255}%&%d:%p1%{255}%&%d%;m,
It only special treats the first 8 colors (which means `rgb(0,0,0..8)` cannot be rendered with `setaf`).
This isn't currently possible, but
https://github.com/wez/wezterm/issues/4223 will introduce that
possibility. This commit causes width > 2 to "overflow" into
the heap-stored variant.
Sequences that are long enough to produce a column width > 2 are
likely to already be long enough in bytes to overlow into the
heap-stored variant anyway.
Factor out the probe_screen_size method from the Terminal
trait and put it into a ProbeCapabilities struct.
This makes it easier to introduce other sorts of probed
information without making the Terminal trait grow all sorts
of additional methods.
A Terminal may choose not to support probing, which it cannot
if it doesn't have Read + Write handles to an underlying terminal
(such as some special cases in wezterm).
Neither of these understand image protocols, and both are
an additional processing layer between the application and
wezterm.
This commit detects and wraps OSC sequences in tmux's passthru
sequence so that the data is passed on to wezterm rather than
elided from the data stream.
For image protocols in both tmux and conpty, work a little
smarter and explicitly move the cursor position to the same
location that wezterm would move it to. That prevents the
display from being as mangled by tmux/conpty due to a diverging
understanding of the cursor position.
The logic isn't perfect, and can result in the x-coordinate
being incorrect, and this won't work with the new --position
argument either in its current state, without adding a lot
of complexity to deal with scrolling and relative and absolute
positioning handling.
To facilitate that, a new termwiz Terminal trait method has
been added to probe the terminal name, version, cell and pixel
dimensions. It's not pretty.
refs: https://github.com/wez/wezterm/issues/3624
refs: https://github.com/wez/wezterm/issues/3716
There were a couple of layers of issue here:
* In the ImageDataType::decode method, we didn't detect and do something
reasonable when the decoded image had 0 frames, later leading to
a panic in glyphcache when trying to index frame 0 of an empty vec.
* We shouldn't have been using ImageDataType::decode for window
background images
* Make the fallback/placeholder black rather than fully transparent
in the more modern decoder thread routine that we use for image
decoding at the gui layer.
refs: #3614
We need access to the underlying raw/physical key in order
to correctly encode in some modes, so we need the full KeyEvent
struct for that.
Move the encoder up so it sits alongside the win32 input mode
encoder.
This should give us better results for both shifted/unshifted
and the "base layout" (US english) representations of a number
of keys.
Note that this is still not 100% technically correct: the unshifted
keys require knowledge of the keyboard layout that we don't have
at this OS-independent layer.
Right now we're assuming a US layout to unshift punctuation, which
is not right if you're not using that layout. To resolve that,
more work is needed on each OS to be able to extract that information
and then to store it in the KeyEvent.
refs: https://github.com/wez/wezterm/issues/3479
refs: https://github.com/wez/wezterm/issues/2546
We were missing encoding of these for the base xterm encoding
(I haven't daily driven a keyboard with a numpad in over 10 years!).
Improve mapping for the kitty protocol.
refs: https://github.com/wez/wezterm/issues/3478
This commit teaches the termwiz layer about positional modifiers,
and expands our modifier concept to also pass through led states
such as caps lock and num lock.
Those aren't actually keyboard modifiers, but the state is useful
to recognize.
Adjust the shift key normalization so that we don't uppercase
alpha characters when both SHIFT and CAPS_LOCK are held.
This processing will remove both SHIFT and CAPS_LOCK in that
situation.
Add a method to KeyEvent that will undo the OS keyboard layer
normalization of positional to generic modifier key presses.
eg: the OS may map LeftControl -> Control, but we actually
prefer to have LeftControl so if we can unambiguously reverse
that mapping, we do so.
refs: #3476
refs: #3475
- v2.0 no longer derives a bunch of traits (Debug, Clone, Copy, PartialEq, Eq)
by default, so I manually derived them.
- It also changed the snapshot results so I updated them:
An empty bitflags struct is no longer displayed as `None` but as
`BitFlags(0x0)`.
- `bits` is no longer a field but a method so I added the missing
parenthesis.
* Translate from File to EncodedFile as needed
* Adopt blob leases in the mux server
* Fix an issue where the first image sent by the mux server would
be replaced on the client by its background image, if configured.
Removed the ImageData::id field to resolve this: you should use
the hash field instead to identify and disambiguate images.
Bumped the termwiz API version because this is conceptually
a breaking change to the API
refs: https://github.com/wez/wezterm/issues/3343
Adopt the new blob lease layer to storing and referencing
image files.
This reduces the number of open files needed when
images are being displayed in the terminal.
refs: https://github.com/wez/wezterm/issues/3263
Input data:
\e_Ga=T,f=32,s=10,v=22,c=1,r=1,m=1\e\\e_Gm=1;/xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T//P=\e\\e_Gm=1;/xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T//P=\e\\e_Gm=0\e\
There were two issues in handling this:
* We expected there to be `;payload` in the first transmission packet,
but there wasn't one, so we ignored it as ill-formed.
* The standard base64 decoder in the rust ecosystem is super strict
and rejects the "sloppy" python base64 encoder output that isn't
strictly conformant with the RFC. We need to jump through some
hoops to get it to relax and accept the input.
refs: https://github.com/wez/wezterm/issues/2716
Continuing from the previous commit, this shifts:
* In-memory data -> temporary file
* Image decoding -> background thread
The background thread asynchronously decodes frames and
sends them to the render thread via a bounded channel.
While decoding frames, it writes them, uncompressed, to
a scratch file so that when the animation loops, it is
a very cheap operation to rewind and pull that data
from the file, without having to burn CPU to re-decode
the data from the start.
Memory usage is bounded to 4 uncompressed frames while
decoding, then 3 uncompressed frames (triple buffered)
while looping over the rest.
However, disk usage is N uncompressed frames.
refs: https://github.com/wez/wezterm/issues/3263
This makes decoding animation frames a lazy operation, but it
comes at the cost of needing to re-decode the image from scratch
when it loops, because the image crate doesn't provide a way
to rewind its frame iterator.
That initial decode can have a significant time cost; a small
webp file consistently takes 150ms to decode, which is too
much to do inline in the render thread.
Next steps will be to move that cost off the render thread.