These flags are used with WSL (Bash on Windows) and are commonly used.
(e.g. a pager status bar, man pages, etc.)
The most difficult part of this commit is figuring out when Windows
respects the flags versus ignores them. Apparently it deliberately
ignores them for backwards-compatibility with some programs.
If the terminal is placed in an alternate mode using DECCKM, then we
need to generate different input escape sequences for WSL (and other
programs using ENABLE_VIRTUAL_TERMINAL_INPUT). AFAIK, there is no way
for winpty to detect whether an alternate mode is enabled, but it only
seems to affect a small number of keys, so send those keys as window
messages.
We don't send *all* keys as window messages, because the console may try
to interpret some of them. It doesn't interpret the arrow keys and
Home/End, AFAICT, and those seem to be the only keys affected by DECCKM.
(The console's line-input mode *does* care about these navigation keys,
but in that case, WriteConsoleInput and window messages work equally well.)
DECCKM only seems to affect the keys when there is no modifier key.
I believe that by using SendMessage, winpty-agent will block until the
keys are appended to the console input buffer. I'm not sure how to verify
it. If this *weren't* the case, there could be a danger of key input
being transposed. It seems unlikely to be an issue.
Fixes https://github.com/rprichard/winpty/issues/90
The wrapper enables the undocumented mode flag 0x200 on the CONIN handle,
which directs the Windows console to replace most KeyDown input records
with sequences of plain bytes, which are escape sequences for control and
navigation keys.
This particular solution reencodes escape sequences and looks roughly
similar to what the Windows console generates, with a few differences:
* For Alt-Backspace, winpty generates ^[ ^?, whereras Windows generates
^[ ^H.
* For Shift/Alt/Ctrl-modified sequences, winpty encodes the mask of
modifiers into the escape sequences.
* winpty generates ^[ Z for Shift-Tab, rather than ^I.
* winpty generates ^[ E for the NumPad "clear/5" key, rather than nothing.
I'm still not sure winpty *ought* to do this reencoding. I don't think
generating KeyUp events is necessary. In principle, it might be
needed/useful for dealing with various terminals. WSL bash.exe always
sets TERM to xterm, and even if changing it is correct w.r.t. input, it's
not necessarily correct for output -- the Windows console system is
expecting to see TERM=xterm output, which it uses to updates it screen
buffer. (I'm not sure that matters, much, though. I suppose
TERM=xterm-256color could be a problem?)
Fixes https://github.com/rprichard/winpty/issues/82
By default, winpty now puts a new console into QuickEdit mode. If the
agents detects that the console has disabled QuickEdit and enabled
ENABLE_MOUSE_INPUT, then it puts the terminal into mouse mode.
This convention doesn't work with all Windows programs -- it does work
with Far Manager and "winpty-agent.exe --show-input --with-mouse". The
practice is described in one of Raymond Chen's posts[1].
For other programs, winpty.exe still has a --mouse option, and I wrote a
script in misc/ConinMode.ps1 that controls the QuickEdit (and InsertMode)
flags from the command-line, which is useful, because the console
properties dialog is inaccessible from within winpty.
[1] https://blogs.msdn.microsoft.com/oldnewthing/20130506-00/?p=4453
Calling SetProcessWindowStation in winpty_open isn't thread-safe -- another
thread may be doing something with the window station. The call also
appears to interfere with the clipboard, which has affected IntelliJ.
A previous commit disabled the use of the background desktop for Windows 7
and up, where it seems unnecessary. This commit fixes the issue for XP
and Vista by spawning the agent twice in winpty_open:
1. winpty_open first spawns an agent with no attached console, which
creates the background desktop and sends its name back on the control
pipe.
2. Then it spawns the primary agent invocation as usual.
3. Once the primary agent's control pipe is connected, winty_open allows
the first agent to exit.
Fixes https://github.com/rprichard/winpty/issues/58
The new API improves upon the old API in a number of ways:
* The old API provided a single data pipe for input and output, and it
provided the pipe in the form of a HANDLE opened with
FILE_FLAG_OVERLAPPED. Using a bare HANDLE is difficult in higher-level
languages, and overlapped/asynchronous I/O is hard to get right.
winpty_close closed the data pipe, which also didn't help things, though
I think the handle could have been duplicated.
Using a single handle for input and output complicates shutdown. When
the child process exits, the agent scrapes the final output, then closes
the data pipe once its written. It's possible that a winpty client will
first detect the closed pipe when it's writing *input* rather than
reading output, which seems wrong. (On the other hand, the agent
doesn't implement "backpressure" for either input or output (yet), and
if it did, it's possible that post-exit shutdown should interrupt a
blocked write into the console input queue. I need to think about it
more.)
The new API splits the data pipe into CONIN and CONOUT pipes, which are
accessed by filename. After `winpty_open` returns, the client queries
pipe names using `winpty_conin_name` and `winpty_conout_name`, then
opens them using any mechanism, low-level or high-level, blocking or
overlapped.
* The old libwinpty handled errors by killing the process. The new
libwinpty uses C++ exceptions internally and translates exceptions at
API boundaries using:
- a boolean error result (e.g. BOOL, NULL-vs-non-NULL)
- a potentially heap-allocated winpty_error_t object returned via an
optional winpty_error_ptr_t parameter. That parameter can be NULL.
If it isn't, then an error code and message can be queried from the
error object. The winpty_error_t object must be freed with
winpty_error_free.
* winpty_start_process is renamed to winpty_spawn. winpty_open and
winpty_spawn accept a "config" object which holds parameters. New
configuration options can be added without disturbing the source or
binary API.
* The winpty_get_exit_code and winpty_get_process_id APIs are removed.
The winpty_spawn function has an out parameter providing the child's
process and thread HANDLEs (duplicated from the agent via
DuplicateHandle). The winpty client can call GetExitCodeProcess and
GetProcessId (as well as the WaitForXXX APIs to wait for child exit).
My motivation at the moment is that I'm trying to share a
git checkout between multiple VMs using VirtualBox's Shared
Folders feature. git in the guest VM isn't able to see the
executable bits from the host due to the VirtualBox/SMB/CIFS
layer. Instead, it thinks text files are non-executable,
unless they have a shebang line. That's a sensible way to
set the flags anyway, so set them like that.
With this commit, there's still one file that isn't handled:
src/shared/GetCommitHash.cmd. It's still marked executable,
but it lacks a shebang line, so the guest thinks it's
non-executable. I'm not sure it should be changed.
There are three reasons for this change:
* It's consistent with MSYS2, which already renamed console.exe to
winpty.exe.
* winpty.exe is less likely to clash with another program.
* winpty.exe is easier to search for online. If someone unfamiliar with
winpty is asked to run console.exe, they might have a hard time figuring
out where console.exe comes from.
The old behavior can be restored by passing UNIX_ADAPTER_EXE=console.exe
to `make`, or by simply renaming the binary after-the-fact, or with
`alias`, etc.
* ^[O is Shift-Alt-O, not Alt-O. Alt-O is ^[o
* '[' is not a valid virtualkey. It's typically VK_OEM_4 on a US
keyboard, but it needs to be looked up dynamically.
* The unicodeChar fields should be 'O' and '[', not NUL.
* Add a --showkey argument to the unix adapter.
My Ubuntu machine has a nice showkey -a utility that dumps keys, but I
can't find something similar for Cygwin/MSYS. It's a very useful tool
for debugging UNIX terminal interoperability, so add it to the unix
adapter.
* Add WINPTY_DEBUG=input to log input bytes and console key events.