Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make sure foreground access works for DefTerm #13247

Merged
11 commits merged into from
Jun 9, 2022

Conversation

zadjii-msft
Copy link
Member

@zadjii-msft zadjii-msft commented Jun 8, 2022

See also: #12799, the origin of much of this.

This change evolved over multiple phases.

Part the first

When we create a defterm connection in TerminalPage::_OnNewConnection,
we don't have the hosting HWND yet, so the tab gets created without one.
We'll later get called with the owner, in Initialize.

To remedy this, we need to:

  • In Initialize, make sure to update any existing controls with the
    new owner.
  • In ControlCore, actually propogate the new owner down to the
    connection

Part the second

DefTerm launches don't actually request focus mode, so the Terminal
never sends them focus events. We need those focus events so that the
console can request foreground rights.

To remedy this, we need to:

  • pass --win32input to the commandline used to initialize OpenConsole
    in ConPTY mode. We request focus events at the same time we request
    win32-input-mode.
  • I also added --resizeQuirk, because by all accounts that should be
    there
    . Resizing in defterm windows should be wacky without it, and
    I'm a little surprised we haven't seen any bugs due to this yet.

Part the third

ConsoleSetForeground expects a HANDLE to the process we want to give
foreground rights to. The problem is, the wire format we used also
decided that a HANDLE value was a good idea. It's not. If we pass the
literal value of the HANDLE to the process from OpenConsole to conhost,
so conhost can call that API, the value that conhost uses there will
most likely be an invalid handle. The HANDLE's value is its value in
OpenConsole, not in conhost.

To remedy this, we need to:

  • Just not forward ConsoleSetForeground. Turns out, we can just call
    that in OpenConsole safely. There's no validation. So just instantiate
    a static version of the Win32 version of ConsoleControl, just to use
    for SetForeground. (thanks Dustin)

  • Tested manually - Win+R powershell, notepad spawns on top.

Closes #13211

@ghost ghost added Area-DefApp Area-Windowing Window frame, quake mode, tearout Issue-Bug It either shouldn't be doing this or needs an investigation. Priority-0 Bugs that we consider release-blocking/recall-class (P0) Product-Terminal The new Windows Terminal. Severity-Blocking We won't ship a release like this! No-siree. labels Jun 8, 2022
@github-actions

This comment was marked as resolved.

Copy link
Member

@DHowett DHowett left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Chatted offline, there might be a better way. However, I love the signature changes and clarifying comments. We should keep those.

@ghost ghost added the Needs-Author-Feedback The original author of the issue/PR needs to come back and respond to something label Jun 8, 2022
@ghost ghost removed the Needs-Author-Feedback The original author of the issue/PR needs to come back and respond to something label Jun 9, 2022
};

struct HostSignalSetForegroundData
{
uint32_t sizeInBytes;
uint32_t processId;
uint32_t processId; // THIS IS A HANDLE, NOT A PID
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

blame @miniksa

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Brain fart. Sorry.

@DHowett DHowett added the Needs-Second It's a PR that needs another sign-off label Jun 9, 2022
@ghost ghost requested review from PankajBhojwani, carlos-zamora and lhecker June 9, 2022 20:35
@DHowett
Copy link
Member

DHowett commented Jun 9, 2022

Nits: When you prep this as a commit message, remove the commit IDs from the body (they aren't meaningful once squashed), and remove the original notes about the thing we didn't do / the summary/details section

@DHowett
Copy link
Member

DHowett commented Jun 9, 2022

Moved from body:


See also: #12799, the origin of much of this.

This change evolved over multiple phases.

Part the first (4de1ef7)

When we create a defterm connection in TerminalPage::_OnNewConnection, we don't have the hosting HWND yet, so the tab gets created without one. We'll later get called with the owner, in Initialize.

To remedy this, we need to:

  • In Initialize, make sure to update any existing controls with the new owner.
  • In ControlCore, actually propogate the new owner down to the connection

Part the second (5ab0799)

DefTerm launches don't actually request focus mode, so the Terminal never sends them focus events. We need those focus events so that the console can request foreground rights.

To remedy this, we need to:

  • pass --win32input to the commandline used to initialize OpenConsole in ConPTY mode. We request focus events at the same time we request win32-input-mode.
  • I also added --resizeQuirk, because by all accounts that should be there. Resizing in defterm windows should be wacky without it, and I'm a little surprised we haven't seen any bugs due to this yet.

Part the third (e970f7c)

Part the third was changed dramatically, original summary here.

There's certain OS-side checks that make it so only the original conhost can call the ConsoleControl APIs. When launched as the delegation console, OpenConsole forwards these calls to the original conhost that spawned it. The one in question here is ConsoleSetForeground. That expects a HANDLE to the process we want to give foreground rights to. The problem is, the wire format we used also decided that a HANDLE value was a good idea. It's not. If we pass the literal value of the HANDLE to the process from OpenConsole to conhost, so conhost can call that API, the value that conhost uses there will most likely be an invalid handle. The HANDLE's value is its value in OpenConsole, not in conhost.

To remedy this, we need to:

  • Duplicate client process handles to the original conhost when running in delegation console mode
  • Pass the value of the handle in the conhost process space to RemoteConsoleControl instead.

This is necessarily tricky, because we assumingly can't make conhost-side changes here. We have to assume that new Terminal's will be running on older versions of Windows 11, and also older Terminals will be running on newer Windows 11's (with this fix). If there's a mismatch in what either is expecting, then the whole thing'll blow up.

By duplicating the handle into the conhost, we can keep passing a HANDLE value that conhost will pass straight through on all versions of Windows 11. That also means OpenConsole needs to manage the lifetime of that handle, because old conhosts will NEVER be able to know that there's a new HANDLE in their process space.

Part the fourth, (55a7331)

ConsoleSetForeground expects a HANDLE to the process we want to give foreground rights to. The problem is, the wire format we used also decided that a HANDLE value was a good idea. It's not. If we pass the literal value of the HANDLE to the process from OpenConsole to conhost, so conhost can call that API, the value that conhost uses there will most likely be an invalid handle. The HANDLE's value is its value in OpenConsole, not in conhost.

To remedy this, we need to:

Copy link
Member

@lhecker lhecker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I love this PR. The comments are great and explain the problems well.
What --resizeQuirk and --win32input mean is not that well explained in this PR and might be hard to understand for newcomers, but I believe that this is clearly out of scope for the PR.

@DHowett DHowett added the AutoMerge Marked for automatic merge by the bot when requirements are met label Jun 9, 2022
@ghost
Copy link

ghost commented Jun 9, 2022

Hello @DHowett!

Because this pull request has the AutoMerge label, I will be glad to assist with helping to merge this pull request once all check-in policies pass.

p.s. you can customize the way I help with merging this pull request, such as holding this pull request until a specific person approves. Simply @mention me (@msftbot) and give me an instruction to get started! Learn more here.

@ghost ghost merged commit 2a7dd8b into main Jun 9, 2022
@ghost ghost deleted the dev/migrie/b/13211-defterm-focus-foreground branch June 9, 2022 23:12
@ghost ghost removed the Needs-Second It's a PR that needs another sign-off label Jun 10, 2022
DHowett pushed a commit that referenced this pull request Jun 30, 2022
See also: #12799, the origin of much of this.

This change evolved over multiple phases.

When we create a defterm connection in `TerminalPage::_OnNewConnection`,
we don't have the hosting HWND yet, so the tab gets created without one.
We'll later get called with the owner, in `Initialize`.

To remedy this, we need to:
* In `Initialize`, make sure to update any existing controls with the
  new owner.
* In `ControlCore`, actually propogate the new owner down to the
  connection

DefTerm launches don't actually request focus mode, so the Terminal
never sends them focus events. We need those focus events so that the
console can request foreground rights.

To remedy this, we need to:
* pass `--win32input` to the commandline used to initialize OpenConsole
  in ConPTY mode. We request focus events at the same time we request
  win32-input-mode.
* I also added `--resizeQuirk`, because _by all accounts that should be
  there_. Resizing in defterm windows should be _wacky_ without it, and
  I'm a little surprised we haven't seen any bugs due to this yet.

`ConsoleSetForeground` expects a `HANDLE` to the process we want to give
foreground rights to. The problem is, the wire format we used _also_
decided that a HANDLE value was a good idea. It's not. If we pass the
literal value of the HANDLE to the process from OpenConsole to conhost,
so conhost can call that API, the value that conhost uses there will
most likely be an invalid handle. The HANDLE's value is its value in
_OpenConsole_, not in conhost.

To remedy this, we need to:
* Just not forward `ConsoleSetForeground`. Turns out, we _can_ just call
  that in OpenConsole safely. There's no validation. So just instantiate
  a static version of the Win32 version of ConsoleControl, just to use
  for SetForeground. (thanks Dustin)

* [x] Tested manually - Win+R `powershell`, `notepad` spawns on top.

Closes #13211

(cherry picked from commit 2a7dd8b)
Service-Card-Id: 83026847
Service-Version: 1.14
@ghost
Copy link

ghost commented Jul 6, 2022

🎉Windows Terminal v1.14.186 has been released which incorporates this pull request.:tada:

Handy links:

@ghost
Copy link

ghost commented Jul 6, 2022

🎉Windows Terminal Preview v1.15.186 has been released which incorporates this pull request.:tada:

Handy links:

This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-DefApp Area-Windowing Window frame, quake mode, tearout AutoMerge Marked for automatic merge by the bot when requirements are met Issue-Bug It either shouldn't be doing this or needs an investigation. Priority-0 Bugs that we consider release-blocking/recall-class (P0) Product-Terminal The new Windows Terminal. Severity-Blocking We won't ship a release like this! No-siree.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

GUI apps still don't open in the foreground, from a default terminal launch
4 participants