I've been meaning to do this for a while; this commit moves
the escape sequence parsing into the thread that reads the
pty output which achieves two goals:
* Large escape sequences (eg: image protocols) that span multiple
4k buffers can be processed without ping-ponging between the
reader thread and the main gui thread
* That parsing can happen in the reader thread, keeping the gui
thread more responsive.
These changes free up the CPU during intensive operations such
as timg video playback.
This is a slight layering violation, in that this processing
really belongs to local pane (or any pane that embeds Terminal),
rather than generically at the Mux layer, but it's not any
worse a violation than `advance_bytes` already was.
refs: https://github.com/wez/wezterm/issues/537
The leftmost pixel was being set to at least 1 by the scale
function.
Fix that up by computing the x coordinate without calling
the scale function.
refs: https://github.com/wez/wezterm/issues/536
Using a boxed slice means that we hold exactly the memory required
for the file data, rather than the next-power-of-two, which can
be wasteful when a large number of images are being sent to
the terminal.
This is a API breaking change for termwiz, so bump its version.
refs: #534
While adding gif support I let this become unbounded.
This commit resolves that by categorizing images as either
single frame or animations.
Single frame images are decoded and held entirely in the texture
atlas, so occupy no additional space beyond the image file contents
and their sprite region in the texture atlas.
Animations are decoded into a set of frame bitmaps. There can be
up to 16 animations (each with their full set of frames) cached.
The individual frames may also exist within the texture atlas
if space permits.
refs: #534
https://i.giphy.com/media/3owvKqP4VSydZE4pvq/200w.gif cannot
be decoded as an animated gif due to this error: `No end code in lzw stream`
Ensure that we don't completely fail to process the render phase
as a result.
Previously, invalidation for animation was driven by the cursor
blink rate, which meant that animated gifs/pngs could not play
faster than 5fps (default blink interval is 200ms).
This commit calculates the next invalidation time based on the
closes next frame time of all animated cells in the viewport.
This is first draft; the animation rate is currently tied
to the cursor_blink_rate setting, so if the gif has frames that
are intended to display more frequently than that, they will
animate more slowly.
Animation is only carried out while the window has focus.
Animation increases the load on the GPU and thus uses more power.
It's kinda fun to stick one of these animated pixel gifs in the background:
https://imgur.com/gallery/F9DAH
During a live resize, we could queue up a lot of `window-resized`
events, which is undesirable.
This commit introduces a simple but effective mechanism to manage this;
a given event can have at most one executing and one pending copy.
So if we get a burst of resize events (eg: during a live window resize)
that might have previously queued hundreds of discrete events, we now
get a more manageable situation with 1 executing and 1 queued.
With this change, a given event can only have 1 executing instance at a
time (with the exception that the open-uri event doesn't go through this
mechanism).
refs: https://github.com/wez/wezterm/issues/291
The previous behavior was to always treat ctrl-alt as altgr on Windows,
this has been done to better support altgr through a VNC session,
but this is very unintuitive when you don't need this behavior.
ref: #472
This is to support <https://github.com/wez/wezterm/issues/291>.
The window resized event happens asynchronously wrt. processing
a window resize, triggering at the end of the normal window
resize handling.
This commit introduces the notion of whether we are in full screen
mode or not in the underlying event callback, which is useful to
gate the desired feature, which is: when in full screen mode,
increase the padding for the window to center its content.
While poking around at this, I noticed that we weren't passing
the per-window config down to the code that computes the quad
locations for the window.
This commit also changes the font size increase/decrease behavior
so that in full screen mode it doesn't try to resize the window.
```lua
local wezterm = require 'wezterm';
wezterm.on("window-resized", function(window, pane)
local window_dims = window:get_dimensions();
local pane_dims = pane:get_dimensions();
local overrides = window:get_config_overrides() or {}
if not window_dims.is_full_screen then
if not overrides.window_padding then
-- not changing anything
return;
end
overrides.window_padding = nil;
else
-- Use only the middle 33%
local third = math.floor(window_dims.pixel_width / 3)
local new_padding = {
left = third,
right = third,
top = 0,
bottom = 0
};
if overrides.window_padding and new_padding.left == overrides.window_padding.left then
-- padding is same, avoid triggering further changes
return
end
overrides.window_padding = new_padding
end
window:set_config_overrides(overrides)
end);
return {
}
```
I'm calling it a temporary defeat on the shaping changes;
this commit effectively reverts the series of changes made
to support slicing up ligatures like `->` when the cursor
moves through them.
They've introduced so many issues and I've spent hours
that haven't resulted in a complete solution, so I've
disabled those changes by putting them behind a boolean
option.
I'll revisit them after I've cut the next release.
refs: https://github.com/wez/wezterm/issues/478
Manual test scenario:
```
wezterm -n --config adjust_window_size_when_changing_font_size=false --config 'exit_behavior="Hold"' start -- sh -c "echo '(...)'"
```
then CTRL +/- to change font size; the first cell of the `...` was
previously random garbage, now is more consistent.
refs: https://github.com/wez/wezterm/issues/478
mouse move events in the tab bar, and paint events, could cause
the title bar state to be recomputed.
Make sure that we don't trigger the status event to trigger for those.
refs: https://github.com/wez/wezterm/issues/500
I've only tested this on macos, but it should be cross platform,
with the caveat that Wayland doesn't let a window position itself,
so this won't work there.
We were using the value that was active when the window was created,
and never updating it.
This commit sweeps the interval check into the existing periodic
window maintenance routine.
refs: https://github.com/wez/wezterm/issues/500
The API isn't finalized; this is proof of concept for putting something
in the area to the right of the new tab button.
The info will be right aligned to the tab area.
```lua
local wezterm = require 'wezterm';
wezterm.on("update-right-status", function(window, pane)
-- demonstrates shelling out to get some external status.
-- wezterm will parse escape sequences output by the
-- child process and include them in the status area, too.
local success, date, stderr = wezterm.run_child_process({"date"})
-- Make it italic and underlined
window:set_right_status(wezterm.format({
{Attribute={Underline="Single"}},
{Attribute={Italic=true}},
{Text="Hello "..date},
}));
end)
return {
}
```
refs: https://github.com/wez/wezterm/issues/500
As explained in the docs included in this commit, ideally this
wouldn't be needed, but due to a long-standing hinting bug in
freetype <https://gitlab.freedesktop.org/freetype/freetype/-/issues/761>
it seems most expedient to just render our own block glyphs,
so that's what this does!
refs: #433
This commit expands on the prior commits to introduce the concept
of per-window configuration overrides.
Each TermWindow maintains json compatible object value holding
a map of config key -> config value overrides.
When the window notices that the config has changed, the config
file is loaded, the CLI overrides (if any) are applied, and then
finally the per-window overrides, before attempting to coerce
the resultant lua value into a Config object.
This mechanism has some important constraints:
* Only data can be assigned to the overrides. Closures or special
lua userdata object handles are not permitted. This is because
the lifetime of those objects is tied to the lua context in which
they were parsed, which doesn't really exist in the context of
the window.
* Only simple keys are supported for the per-window overrides.
That means that trying to override a very specific field of
a deeply structured value (eg: something like `font_rules[1].italic = false`
isn't able to be expressed in this scheme. Instead, you would
need to assign the entire `font_rules` key. I don't anticipate
this being a common desire at this time; if more advance manipulations
are required, then I have some thoughts on an event where arbitrary
lua modifications can be applied.
The implementation details are fairly straight-forward, but in testing
the two examplary use cases I noticed that some hangovers from
supporting overrides for a couple of font related options meant that the
window-specific config wasn't being honored. I've removed the code that
handled those overrides in favor of the newer more general CLI option
override support, and threaded the config through to the font code.
closes: #469closes: #329
`wezterm`, `wezterm-gui` and `wezterm-mux-server` now all support
a new `--config name=value` CLI option that can be specified
multiple times to supply config overrides.
Since there isn't a simple, direct way to update arbitrary fields
of a struct in Rust (there's no runtime reflection), we do this
work in lua.
The config file returns a config table. Before that is mapped
to the Rust Config type, we have a new phase that takes each
of the `--config` values and applies it to the config table.
For example, you can think of configuration as working like this
if wezterm is started as `wezterm --config foo="bar"`:
```lua
config = load_config_file();
config.foo = "bar";
return config;
```
The `--config name=value` option is split into `name` and `value`
parts. The name part is literally concatenated with `config` in
the generated lua code, so the name MUST be valid in that context.
The `value` portion is literally inserted verbatim as the rvalue in the
assignment. Not quoting or other processing is done, which means
that you can (and must!) use the same form that you would use in
the config file for the RHS. Strings must be quoted. This allows
you to use more complicated expressions on the right hand side,
such as:
```
wezterm --config 'font=wezterm.font("Fira Code")'
```
The overrides stick for the lifetime of the process; even if
you change the config file and reload, then the value specified
by the override will take precedence.
refs: https://github.com/wez/wezterm/issues/469
refs: https://github.com/wez/wezterm/issues/499
This is defined as a trait method on Pane (default: false), and has the
obvious transitive equivalent methods in Tab and Window (eg: if all
contained items are `can_close_without_prompting`, then that container
is also `can_close_without_prompting`).
The intent is to avoid bothering the user to confirm closing a window
when the content is not stateful and doesn't warrant it.
For example: the window that is displayed in the event of a
configuration error really shouldn't prompt to the user to confirm
closing it.
All termwiztermtab panes are `can_close_without_prompting==true`
to effect this policy.
In the future, we could teach LocalPane to lookup the session leader
process against a list of "uninteresting" or "stateless" processes
and return an appropriate result (as suggested in
https://github.com/wez/wezterm/issues/280). That functionality
is NOT part of this commit.
`exit_behavior = "Hold"` will keep the pane alive until explicitly
closed. More details in the docs that are part of this commit.
refs: https://github.com/wez/wezterm/issues/499
The Cascadia Code font has ligatures for `---` that consist of
a triple wide glyph followed by two zero-width glyphs. Rewrite
that into a single glyph that spans three cells and remove the
zero-width glyphs from the shaped info.
refs: https://github.com/wez/wezterm/issues/478
Connect the gui to the new shaping logic; this means that we
can now correctly render fg/bg color when the cursor moves
through the cells that comprise a ligature.
refs: https://github.com/wez/wezterm/issues/478
This function is intended to deal with certain kinds of ligatures
and certain combining sequences that don't have corresponding glyphs.
It isn't hooked up to the gui yet, but does have unit tests that
are probably mostly correct.
refs: https://github.com/wez/wezterm/issues/478
Refine the colorization logic to make it more of a blending operation.
Previously, we were relying on opengl to carry out blending between
layers on our behalf, but that wasn't perfect.
This commit is inspired by this post:
https://www.puredevsoftware.com/blog/2019/01/22/sub-pixel-gamma-correct-font-rendering/
and factors in the background color when computing the colorized
glyph.
This appears to reduce the dark fringes/edges that we were seeing
before, without noticeably changing the brightness of the result.
refs: #491
https://learnopengl.com/Advanced-Lighting/Gamma-Correction suggests
some good practices:
* Only enable SRGB output on the final draw call, so that all prior
stages can operate on linear values and avoid converting to/from
linear multiple times.
* The SRGBA textures automatically linearize when sampled, but:
* The RGB data must be SRGB (non-linear)
* The A channel is assumed to be linear!
This commit nudges us closer to that by:
* Converting the freetype coverage map from its linear value to
non-linear when rasterizing.
* Splitting the shader files into one per stage (background, lines,
glyphs) and only setting outputs_srgb for the glyph stage
refs: #491
This allows explicitly manipulating the hue, saturation, brightness
of the text rendered in the terminal, allowing users to dial in
the accidental effect that was introduced by
d886de8300
For example, this will punch up the brightness:
```
foreground_text_hsb = {
hue = 1.0,
saturation = 1.0,
brightness = 1.5,
},
```
refs: https://github.com/wez/wezterm/issues/491
This commit:
* Fixes up the alpha blending draw parameters as discussed in
https://github.com/glium/glium/issues/1844 and
https://github.com/PistonDevelopers/conrod/issues/1347
* Introduces `colorize` and `colorize_hsv` functions to the shader.
comments in the code explain those functions in detail.
As of this commit, `colorize_hsv` is what is used now. To my
eye on this mac, it produces blended glyphs with less noticeable
dark antialiasing fringes.
refs: #470
Is it *right*? Hard to say, but it looks better than
the behavior I see with master at the moment.
This is a partial revert of #413, but respins it to
try to get a better alpha value for glyphs.
refs: #413
refs: #470
We weren't didn't treat the "No existing hyperlink, No new hyperlink"
case as no change in hyperlink, and were invalidating the window on
every mouse except for those over text with a hyperlink.
* Add cli option --config-file
* Update cli arg doc & make it conflict with skipping config
* When the config is given explicitly (either using --config-file or via WEZTERM_CONFIG_FILE), failing to load this file will use the default config.
* Otherwise the config file is searched one by one in a few directories.
Dead key processing respects the
`send_composed_key_when_left_alt_is_pressed` and
`send_composed_key_when_right_alt_is_pressed` options.
See doc changes included in this commit for more info.
refs: https://github.com/wez/wezterm/issues/410
This commit changes mouse-based selection and middle click to use the
PrimarySelection.
CTRL-SHIFT-{C,V} use Clipboard.
{SHIFT,CTRL}-Insert use PrimarySelection.
`CompleteSelection` and `CompleteSelectionOrOpenLinkAtMouseCursor` now
require a parameter to specify the destination clipboard.
Removed the `default_clipboard_XXX` options added in
8dad34fa61 in favor of just explicitly
assigning the key/mouse bindings.
closes: #417
* Adds `CopyTo` and `PasteFrom` assignments that specify the
destination/source.
* Adds `default_clipboard_copy_destination` and `default_paste_source`
config options that specify the default destination/source for
existing `Copy` and `Paste` operations (for @bew)
* Deprecating `PastePrimarySelection` in favor of `PasteFrom`.
* Added `CTRL-Insert` -> `Copy` (for @Babar)
Aside from the new key assignment, these changes shouldn't change
the default behavior, but do make it easier to consider changing
that in a later commit.
They should allow for example:
* Set `default_clipboard_copy_destination = "PrimarySelection"` to
prevent populating the clipboard by default when using the mouse.
* Overriding the CTRL-Insert, CTRL-SHIFT-C to explicitly populate
the clipboard
* Set `default_paste_source = "PrimarySelection"` for middle click
to paste the selection.
* Overriding SHIFT-Insert, CTRL-SHIFT-V to explicitly paste from
the clipboard.
refs: #417
* Add ClearBuffer action
Clears all lines, both visible and those scrolled off the top of the viewport, making the prompt line the new first line and resetting the scrollbar thumb to the full height of the window.
This is the behavior that Hyper / xterm has for clearing the terminal.
* Combine ClearBuffer into ClearScrollback as enum with associated erase mode
Makes it easier to manage the different options of clearing the terminal.
The default is true, which means that adjusting the font size will
cause the window to resize to preserve the number of rows/cols in
the terminal.
When set to false, the window size is preserved and the number of
terminal rows/cols is adjusted instead.
refs: https://github.com/wez/wezterm/issues/431
This appears to have been broken since the introduction of mouse
assignments :-/
This commit adds Pane::is_alt_screen_active so that the gui layer
can tell whether the alt screen is active, and allow passing down
the event.
refs: #429