Since we don't have a draw-image-and-rescale primitive, and since
we'd have to scale every time we drew the glyph, it makes sense to
cache the pre-scaled glyph in the atlas.
Tested only on windows with a USB serial connector to my NUC running
linux.
This allows opening up wezterm on a serial port connection.
Serial is closer to a tty than a pty, so it is a bit different
to configure and use.
This commit allows running:
```
wezterm serial COM3
```
to open a window that connects to the specified COM port.
You can change the baud rate with:
```
wezterm serial --baud 9600 COM3
```
There are more options that could be set, but I'm a bit lazy and
have only exposed the baud rate to the wezterm cli so far.
Previously we had the logic for this in wezterm itself; it would know
how to figure out which shell to run, or whether we should run a
different program by default (the `default_prog` setting).
This was OK, but when I added support for ssh we hit a conceptual
issue: the local side of the ssh session doesn't have any information
about the shell that should be invoked on the remote side and instead
needs to ask the remote to figure that out. The interfaces defined
in the code didn't allow for this.
This commit formalizes the concept of a default program and allows
it to be carried through to the pty layer, including over ssh sessions.
Since we now have enough smarts to figure out the local shell and the
local home dir, I've removed the logic that run `login -pf` on macos
by default; this should make the terminal startup very slightly faster
on macos, but since I'm currently on a windows system, I can only test
linux and windows on this side of this commit. I'll follow up on macos
later.
This makes it a bit more convenient to control when and which
multiplexer(s) you want to connect to.
Now that each domain must have a name in the configuration file,
we can address them more conveniently from the command line.
This is mostly useful for folks on Windows, as you can also run
`wezterm start ssh user@host some command` to run the `ssh` binary in a
local pty and let it manage your ssh session.
On Windows the local pty currently breaks mouse reporting
(see https://github.com/microsoft/terminal/issues/376) so it is
desirable to avoid using a local pty if we're going to talk to a
remote system.
This commit makes it a bit more convenient to establish an ad-hoc ssh
session with a pty on a remote host. This method uses libssh2 under the
covers and thus doesn't support gssapi, which is potentially frustrating
for kerberized environments, but works ok for the majority of users.
There are two issues that I want to resolve in follow up work:
* The TERM has to be sent very early in the channel establishment,
before we "know" the TERM in the `portable-pty` interface. Will need to
figure out how to specify that earlier in an appropriate way.
* Similarly, if no command is specified, we should request the use
of the shell subsystem but we don't have a way to capture this
intend with the cmdbuilder. Will need to solve this too.
They don't always work, so let's just not use them when under wsl.
Since we now know how to detect when we're running under wsl, we
can use that knowledge to bypass permission checking for the unix
domain sockets automatically too.
This helps diagnose problems where stderr is not visible.
Let's also capture them to the `log` stream too, and clarify
toml parsing errors, and fix the underlying problem with
ssh_domains not being allowed to be left unspecified.
I was too focused on the wsl case and didn't test this. We can't
redirect the process handles without causing some problems with
starting up cmd.exe. Comment out that portion of the code for
the moment.
This adds some plumbing so that a domain can indicate whether it is
attached or not, but is not yet smart enough to detect a closed
connection and mark itself as detached.
The sync_channel was originally added as a brake to avoid swamping
the event loop, but we've subsequently grown a more formal rate
limiting config for this.
The rate limiter is superior because it allows making forward
progress over time, whereas the bounded channel is a hard blocking
limit.
When making a large paste the app on the other end will typically
emit a lot of output. If our reader is blocked on the sync channel
the output of the pty can be blocked, and that in turn will block
our attempt to write to the pty.
We cannot simply set the pty to non-blocking mode because non-blocking
ptys are not a thing on windows, and in the interest of not silently
breaking windows, I prefer to make the unix side of things match
that architecture.
anyway: TL;DR is that we don't need the bounded channel now that
we have rate control to manage swamping the event loop, so we
can simplify this code.
For unix and tls clients, if connect_automatically is set
and we're not running the server, then instantiate and connect
to those domains when we start the app.
As part of this I realized that we weren't mapping the remote
tab to the local tab for unilateral pushes, so add some stuff
to support that.
cmd-t now spawns in the same domain as the active tab,
cmd-shift-t spawns in the default domain.
It is possible to define bindings to spawn in an arbitrary domain.
In the early days we relied upon the bounded length of a sync channel
to put back pressure on the output from a child command. We're no
longer using that kind of channel, so here's a more deliberate and
measurable rate limiting implementation.
The `ratelimit_output_bytes_per_second` configuration setting defaults
to 2MB/s and constrains the amount of text we send to the escape
sequence parser.
This value was selected based on it being a combination of responsive
to ctrl-c while outputing a lot of data and still generating sleeps
to remain within the constraints.
This does mean that terminal benchmarks that test how quickly you
can dump text to the terminal will hit this artifical upper limit
and are thus not going to be a true measure of performance.
This removes some redundancy and overhead around setting up the
connection (the native_tls crate doesn't provide PEM functions,
despite every deployment I've ever seen only ever using PEM certs),
but more importantly, gives the control needed to make hostname
verification work in a PKI setup with unusual CN values.
Problem scenario was:
* spawn a window
* resize it larger
* spawn a new tab
When working with a mux client tab, the surface size in the new tab
didn't reflect the size of the remote surface, so the rendering was
messed up.
Arrange to know the size up front.
Repeated moves or wheel events are collapsed so that we don't clog up
the queue. The queue size doesn't matter as much as the latency of
processing a large queue. For fast or repeated moves the queue can grow
rather quickly, and with what is currently ~25-50 ms round trip per
entry for a remote session, that is a poor UX.
The latency is not great, and there are more authentication and
authorization features that need to be added, but this shows that
we can connect and talk to a remote muxer.
This do_paint call was added in 8995974124
but I don't think it was intentional; it looks like an accidental commit
of something during debugging.
The intent is that we tick over and paint every tick (~50ms) and this
behavior here was causing us to paint after every input event, which is
undesirable when processing the selection.
refs: https://github.com/wez/wezterm/issues/33
When using WSL, we want to place the unix socket on NTFS and that
reports an insecure set of permissions which cause us to refuse
to start up.
As a bit of a gross hack, allow skipping that check by setting an
environmental variable:
```
WEZTERM_SKIP_MUX_SOCK_PERMISSIONS_CHECK= wezterm start --front-end muxserver
```
that works best in conjunction with this in the WSL `.wezterm.toml`
file: (swap `wez` with your username):
```
mux_server_unix_domain_socket_path = "/mnt/c/Users/wez/.local/share/wezterm/sock"
```
refs: https://github.com/wez/wezterm/issues/33
spawn now requires that the window_id be passed in; this makes it
a bit easier to spawn a remote tab into an existing window.
As part of this, beef up how we manage the window/tab association.
The Domain::spawn interface needs to be adjusted to allow indicating
which window we want to spawn into, or whether the spawn should
create a new window, but aside from that, we can now attach to
a mux server and instantiate tabs and windows!
The client domain stuff is now what I'd describe as almost
basically functional. It's not a great experience because
the latency is a bit high (it uses the coarse render data
as a proof of concept, and polls that every 100ms), and doesn't
connect the clipboard to the remote session. It also doesn't
enumerate and instantiate tabs for existing tabs on the remote
server, and doesn't have a way to gracefully detach from the
remote.
However, it is possible to connect and spawn tabs and interact
with them.
This removes some awkwardness in the impl by allowing casting
to a concrete implementation. This is a pattern I want to use
more widely and this diff proves the concept.
The idea is that we can use this to spawn a tab in a
specific domain. For example, "spawn tab in domain of current tab"
or "spawn tab in default domain".
Usage example is to put this in your `wezterm.toml` to get the
macOS CMD-M shortcut for minimizing a window:
```
[[keys]]
key = "m"
mods = "CMD"
action = "Hide"
```
Refs: https://github.com/wez/wezterm/issues/32
This was blocked by some awkwardness in figuring out which
gui frontend was in use and queueing up the spawn and then
more ugliness in glutin.
That has subsequently been sorted out with the newer executor
stuff, so cut this over.
This is a tiny baby step towards a bigger key binding config
and thus refs: https://github.com/wez/wezterm/issues/32
I noticed that things were feeling laggy in general and when I
added some debugging prints I noticed that we were getting a
continuous stream of CursorMoved events with the same coordinates
while the window had focus.
This diff short circuits mouse processing in that situation and
makes things feel a bit more snappy.