Commit Graph

14 Commits

Author SHA1 Message Date
Leonard Hecker
fc0a06c3b6 Preserve the cursor row during Clear Buffer (#18976)
Introduces an ABI change to the ConptyClearPseudoConsole signal.
Otherwise, we have to make it so that the API call always retains
the row the cursor is on, but I feel like that makes it worse.

Closes #18732
Closes #18878

## Validation Steps Performed
* Launch `ConsoleMonitor.exe`
* Create some text above & below the cursor in PowerShell
* Clear Buffer
* Buffer is cleared except for the cursor row 
* ...same in ConPTY 
2025-06-25 16:31:28 +00:00
Leonard Hecker
4386bf07fd Avoid focus loops in ConPTY (#17829)
This fixes a lot of subtle issues:
* Avoid emitting another de-/iconify VT sequence when
  we encounter a (de)iconify VT sequence during parsing.
* Avoid emitting a de-/iconify VT sequence when
  a focus event is received on the signal pipe.
* Avoid emitting such sequences on startup.
* Avoid emitting multiple such sequences
  when rapidly un-/focusing the window.

It's also a minor cleanup, because the `GA_ROOTOWNER` is not security
relevant. It was added because there was concern that someone can just
spawn a ConPTY session, tell it that it's focused, and spawn a child
which is now focused. But why would someone do that, when the console
IOCTLs to do so are not just publicly available but also documented?

I also disabled the IME window.

## Validation Steps Performed
* First:
  ```cpp
  int main() {
      for (bool show = false;; show = !show) {
          printf(show ? "Show in 3s...\n" : "Hide in 3s...\n");
          Sleep(3000);
          ShowWindow(GetConsoleWindow(), show ? SW_SHOW : SW_HIDE);
      }
  }
  ```
* PowerShell 5's `Get-Credential` gains focus 
* `sleep 5; Get-Credential` and focus another app. WT should start
  blinking in the taskbar. Restore it. The popup has focus 
* Run `:hardcopy` in vim: Window is shown centered at (0,0) ✖️
  But that's okay because it does that already anyway 
* `Connect-AzAccount` doesn't crash PowerShell 
2024-10-08 11:37:33 -05:00
Leonard Hecker
3c78e01ab5 Fix a potential deadlock for PtySignal::SetParent (#14463)
This changeset consists of two parts:
* Refactor `PtySignalInputThread` to move more code from `_InputThread`
  into the various `_Do*` handlers. This allows us to precisely control
  console locking behavior which is the cause of this bug.
* Add the 1-line fix to `_DoSetWindowParent` to unlock the console before
  calling foreign functions (`SetWindowLongPtrW` in this case).

This fix is theoretical in nature, based on a memory dump from an affected user
and most likely fixes: https://developercommunity.visualstudio.com/t/10199439

## Validation Steps Performed
* ConPTY tests complete. 
2022-12-01 23:13:18 +00:00
Leonard Hecker
b6b1ff8b2c Wait for clients to exit on ConPTY shutdown (#14282)
#14160 didn't fix #14132 entirely. There seems to be a race condition left
where (on my system) 9 out of 10 times everything works correctly,
but sometimes OpenConsole exits, while pwsh and bash keep running.

My leading theory is that the new code is exiting OpenConsole faster than the
old code. This prevents clients from calling console APIs, etc. causing them
to get stuck. The old code (and new code) calls `ExitProcess` when the ConPTY
pipes break and I think this is wrong: In conhost when you close the window we
only call `CloseConsoleProcessState` via the `WM_CLOSE` event and that's it.
Solution: Remove the call to `RundownAndExit` for ConPTY.

During testing I found that continuously printing text inside msys2 will cause
child processes to only exit slowly one by one every 5 seconds.
This happens because `CloseConsoleProcessState` calls `HandleCtrlEvent` without
holding the console lock. This creates a race condition where most of the time
the console IO thread is the one picking up the `CTRL_CLOSE_EVENT`. But that's
problematic because the `CTRL_CLOSE_EVENT` leads to a `ConsoleControl` call of
type `ConsoleEndTask` which calls back into conhost's IO thread and
so you got the IO thread waiting on itself to respond.
Solution: Don't race conditions.

## Validation Steps Performed
* `Enter-VsDevShell` and close the tab
  Everything exits after 5s 
* Run msys2 bash from within pwsh and close the tab
  Everything exits instantly 
* Run `cat bigfile.txt` and close the tab
  Everything exits instantly 
* Patch `conhost.exe` with `sfpcopy`, as well as `KernelBase.dll`
  with the recent changes to `winconpty`, then launch and exit
  shells and applications via VS Code's terminal 
* On the main branch without this modification remove the call to
  `TriggerTeardown` in `RundownAndExit` (this speeds up the shutdown).
  Run (msys2's) `bash.exe --login` and hold enter and then press Ctrl+Shift+W
  simultaneously. The tab should close and randomly OpenConsole should exit
  early while pwsh/bash keep running. Then retry this with this branch and
  observe how the child processes don't stick around forever anymore. 
2022-11-29 21:15:45 +01:00
Mike Griese
77215d9d77 Fix ShowWindow(GetConsoleWindow()) (#13118)
A bad merge, that actually revealed a horrible bug.

There was a secret conflict between the code in #12526 and #12515. 69b77ca was a bad merge that hid just how bad the issue was. Fixing the one line `nullptr`->`this` in `InteractivityFactory` resulted in a window that would flash uncontrollably, as it minimized and restored itself in a loop. Great. 

This can seemingly be fixed by making sure that the conpty window is initially created with the owner already set, rather than relying on a `SetParent` call in post. This does pose some complications for the #1256 future we're approaching. However, this is a blocking bug _now_, and we can figure out the tearout/`SetParent` thing in post. 

* fixes #13066.
* Tested with the script in that issue.
* Window doesn't flash uncontrollably.
* `gci | ogv` still works right
* I work here.
* Opening a new tab doesn't spontaneously cause the window to minimize
* Restoring from minimized doesn't yeet focus to an invisible window
* Opening a new tab doesn't yeet focus to an invisible window
* There _is_ a viable way to call `GetAncestor` s.t. it returns the Terminal's hwnd in Terminal, and the console's in Conhost


The `SW_SHOWNOACTIVATE` change is also quite load bearing. With just `SW_NORMAL`, the pseudo window (which is invisible!) gets activated whenever the terminal window is restored from minimized. That's BAD.


There's actually more to this as well. 


Calling `SetParent` on a window that is `WS_VISIBLE` will cause the OS to hide the window, make it a _child_ window, then call `SW_SHOW` on the window to re-show it. `SW_SHOW`, however, will cause the OS to also set that window as the _foreground_ window, which would result in the pty's hwnd stealing the foreground away from the owning terminal window. That's bad.

`SetWindowLongPtr` seems to do the job of changing who the window owner is, without all the other side effects of reparenting the window. 

Without `SetParent`, however, the pty HWND is no longer a descendant of the Terminal HWND, so that means `GA_ROOT` can no longer be used to find the owner's hwnd. For even more insanity, without `WS_POPUP`, none of the values of `GetAncestor` will actually get the terminal HWND. So, now we also need `WS_POPUP` on the pty hwnd. To get at the Terminal hwnd, you'll need

```c++
GetAncestor(GetConsoleWindow(), GA_ROOTOWNER)
```
2022-05-18 17:25:06 -05:00
James Holderness
f4e0d9f2bd Merge the TerminalDispatch and AdaptDispatch classes (#13024)
## Summary of the Pull Request

This PR replaces the `TerminalDispatch` class with the `AdaptDispatch` class from conhost, so we're no longer duplicating the VT functionality in two places. It also gives us a more complete VT implementation on the Terminal side, so it should work better in pass-through mode.

## References

This is essentially part two of PR #12703.

## PR Checklist
* [x] Closes #3849
* [x] CLA signed.
* [ ] Tests added/passed
* [ ] Documentation updated.
* [ ] Schema updated.
* [x] I've discussed this with core contributors already. Issue number where discussion took place: #12662

## Detailed Description of the Pull Request / Additional comments

The first thing was to give the `ConGetSet` interface a new name, since it's now no longer specific to conhost. I went with `ITerminalApi`, since that was the equivalent interface on the terminal side, and it still seemed like a generic enough name. I also changed the way the api is managed by the `AdaptDispatch` class, so it's now stored as a reference rather than a `unique_ptr`, which more closely matches the way the `TerminalDispatch` class worked.

I then had to make sure that `AdaptDispatch` actually included all of the functionality currently in `TerminalDispatch`. That meant copying across the code for bracketed paste mode, the copy to clipboard operation, and the various ConEmu OSC operations. This also required a few new methods to the `ConGetSet`/`ITerminalApi` interface, but for now these are just stubs in conhost.

Then there were a few thing in the api interface that needed cleaning up. The `ReparentWindow` method doesn't belong there, so I've moved that into `PtySignalInputThread` class. And the `WriteInput` method was too low-level for the Terminal requirements, so I've replaced that with a `ReturnResponse` method which takes a `wstring_view`.

It was then a matter of getting the `Terminal` class to implement all the methods in the new `ITerminalApi` interface that it didn't already have. This was mostly mapping to existing functionality, but there are still a number of methods that I've had to leave as stubs for now. However, what we have is still good enough that I could then nuke the `TerminalDispatch` class from the Terminal code and replace it with `AdaptDispatch`.

One oddity that came up in testing, though, was the `AdaptDispatch` implementation of `EraseAll` would push a blank line into the scrollback when called on an empty buffer, whereas the previous terminal implementation did not. That caused problems for the conpty connection, because one of the first things it does on startup is send an `ED 2` sequence. I've now updated the `AdaptDispatch` implementation to match the behavior of the terminal implementation in that regard.

Another problem was that the terminal implementation of the color table commands had special handling for the background color to notify the application window that it needed to repaint the background. I didn't want to have to push the color table operations through the `ITerminalApi` interface, so I've instead moved the handling of the background update into the renderer, initiated by a flag on the `TriggerRefreshAll` method.

## Validation Steps Performed

Surprisingly this PR didn't require a lot of changes to get the unit tests working again. There were just a few methods used from the original `ITerminalApi` that have now been removed, and which needed an equivalent replacement. Also the updated behavior of the `EraseAll` method in conhost resulted in a change to the expected cursor position in one of the screen buffer tests.

In terms of manual testing, I've tried out all the different shells in Windows Terminal to make sure there wasn't anything obviously wrong. And I've run a bunch of the tests from _vttest_ to try and get a wider coverage of the VT functionality, and confirmed everything still works at least as well as it used to. I've also run some of my own tests to verify the operations that had to be copied from `TerminalDispatch` to `AdaptDispatch`.
2022-05-04 11:14:51 +00:00
Michael Niksa
6b936d9a74 Propagate show/hide window calls against the ConPTY pseudo window to the Terminal (#12515)
Propagate show/hide window calls against the ConPTY pseudo window to the Terminal

## PR Checklist
* [x] Closes #12570 
* [x] I work here
* [x] Manual Tests passed
* [x] Spec Link: →[Doc Link](https://github.com/microsoft/terminal/blob/dev/miniksa/msgs/doc/specs/%2312570%20-%20Show%20Hide%20operations%20on%20GetConsoleWindow%20via%20PTY.md)←

## Detailed Description of the Pull Request / Additional comments
- See the spec. It's pretty much everything I went through deciding on this.

## Validation Steps Performed
- [x] Manual validation against scratch application calling all of the `::ShowWindow` commands against the pseudo console "fake window" and observing the real terminal window state
2022-04-27 18:20:14 +00:00
Mike Griese
26d67d9c0a Enable the Terminal to tell ConPTY who the owner is (#12526)
## Window shenanigans, part the first:

This PR enables terminals to tell ConPTY what the owning window for the
pseudo window should be. This allows thigs like MessageBoxes created by
console applications to work. It also enables console apps to use
`GetAncestor(GetConsoleWindow(), GA_ROOT)`  to get directly at the HWND
of the Terminal (but _don't please_).

This is tested with our internal partners and seems to work for their
scenario. 

See #2988, #12799, #12515, #12570.

## PR Checklist
This is 1/3 of #2988.
2022-04-12 17:44:01 -05:00
Leonard Hecker
825efda32f Remove wasteful virtuals according to SizeBench (#11889)
This commit removes some pure virtual base classes from conhost,
found with the help of SizeBench. This reduces binary size by 5kB.
The reduction in code size however is the main benefit of this.

Additionally this fixes a mysterious, undebuggable crash in
~RenderThread(), caused by a Control Flow Guard failure when
the class was destroyed over its IRenderThread interface.

## PR Checklist
* [x] I work here
* [x] Tests added/passed

## Validation Steps Performed
* Printing text works 
* Printing VT works 
* Performance is alright 
2022-01-07 17:55:58 +00:00
Mike Griese
6268a4779c Implement and action for manually clearing the Terminal (and conpty) buffer (#10906)
## Summary of the Pull Request

![clear-buffer-000](https://user-images.githubusercontent.com/18356694/127570078-90c6089e-0430-4dfc-bcd4-a0cde20c9167.gif)

This adds a new action, `clearBuffer`. It accepts 3 values for the `clear` type:
* `"clear": "screen"`: Clear the terminal viewport content. Leaves the scrollback untouched. Moves the cursor row to the top of the viewport (unmodified).
* `"clear": "scrollback"`: Clear the scrollback. Leaves the viewport untouched.
* `"clear": "all"`: (**default**) Clear the scrollback and the visible viewport. Moves the cursor row to the top of the viewport (unmodified).

"Clear Buffer" has also been added to `defaults.json`.

## References
* From microsoft/vscode#75141 originally

## PR Checklist
* [x] Closes #1193
* [x] Closes #1882
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated

## Detailed Description of the Pull Request / Additional comments

This is a bit tricky, because we need to plumb it all the way through conpty to clear the buffer. If we don't, then conpty will immediately just redraw the screen. So this sends a signal to the attached conpty, and then waits for conpty to draw the updated, cleared, screen back to us.

## Validation Steps Performed
* works for each of the three clear types as expected
* tests pass.
* works even with `ping -t 8.8.8.8` as you'd hope.
2021-09-02 14:59:42 +00:00
Michael Niksa
1b79cc87c3 Fix startup race of resizing ConPTY (#10449)
Fix startup race of resizing ConPTY

- Depending on what the timing and ordering is of the message coming in
  from the signal thread, it may be applied to the startup structure
  after the I/O thread has begun initializing the console buffer
  structures but before it has signaled that it is done and the signal
  thread is ready to make changes directly. This likely happens because
  the end of the I/O thread setup has a weird unlock/lock jog for the
  input thread and the signal thread might have been scheduled in the
  middle of it.
- My resolution here is to ensure that the signal thread just keeps
  storing the latest resize message until it is told that everything is
  initialized. Whomever comes in to tell the signal thread this
  information (under lock) will pickup and run the resize if one came in
  before everything was ready. This should resolve the race.

## Validation Steps Performed
- o-sdn-o confirms this resolves their issue

Closes #10400
2021-06-22 19:23:16 +00:00
adiviness
9b92986b49 add clang-format conf to the project, format the c++ code (#1141) 2019-06-11 13:27:09 -07:00
Bartosz Brachaczek
73ad742c12 Fix signatures of some callback functions (#871)
* Fix signatures of callback functions

* Fix calling conventions of callback functions

* Remove now-unnecessary casts of pointers to callback functions
2019-05-17 20:32:51 +00:00
Dustin Howett
d4d59fa339 Initial release of the Windows Terminal source code
This commit introduces all of the Windows Terminal and Console Host source,
under the MIT license.
2019-05-02 15:29:04 -07:00