terminal
terminal copied to clipboard
Terminal doesn't respect "start /max" and "/min" parameters when running a console app as default terminal
Windows Terminal version
1.11.3471.0
Windows build number
10.0.22000.434
Other Software
Seemingly any console application (cmd, powershell, python, batch file) -- I'm using python as an example here.
Steps to reproduce
- set terminal as default terminal
- open command prompt in terminal
- run for example "start /max python.exe" (or powershell, or cmd, or some batch file)
- the window will show windowed, not maximised
Expected Behavior
New window starts maximised, as it does when the default Windows console is set.
The correct behaviour also happens if you run wt.exe itself, i.e. "start /max wt python"
Actual Behavior
New window starts windowed
The /min parameter is even worse. "start /min python.exe" starts the classic console, while "start /min wt python.exe" does make a minimised WT window, but you can't switch to it for some reason.
![image](https://user-images.githubusercontent.com/77467869/149322631-e15ab497-a415-4f2c-bd55-65e337d6672f.png)
![image](https://user-images.githubusercontent.com/77467869/149322963-65b55f15-29e4-4b07-a5fc-a4e7855d6519.png)
Alright, so there are three elements here. From the bottom up:
-
start /min wt python.exe
we're tracking in #9053, so feel free to continue that element there. - "
start /min python.exe
opens conhost" This is kinda by design for now. There are a LOT of apps that run commandline tools in "hidden" console windows, so defterm is pretty aggressive about not attaching to those kinds of launches. We don't necessarily want to pop up a Terminal window when a console window wouldn't have been visible to the user. - "
start /max python.exe
doesn't open the Terminal maximized" now, that's a real issue. Or at least, it's something we should have an answer for.
We may need to pass some blob of parameters to defterm invocations describing how the terminal application should be launched. That might take care of both /min
and /max
.
Lemme add @miniksa, see what he thinks
(fat fingered enter, sorry about that)
Without knowing the details of what's possible, I'd expect Terminal to honor relevant fields in STARTUPINFO
after a handoff from conhost. When a new tab (not a window) is created, I'd expect it to use lpTitle
and -- if they're still relevant in any way -- dwXCountChars
, dwYCountChars
, and dwFillAttribute
. When a new window is created, I'd expect it to honor the window's initial show state, position, and size: wShowWindow
, dx
, dy
, dwXSize
, and dwYSize
. If honoring a setting isn't possible or isn't relevant when using Terminal as the default, please document it for STARTUPINFO
, or document it in the console docs.
I understand skipping the handoff to Terminal if wShowWindow
is SW_HIDE
(0). A hidden Terminal window would be dysfunctional since a console app can't programmatically restore the window, and neither can the user. I don't understand skipping the handoff for SW_SHOWMINIMIZED
(2), SW_MINIMIZE
(6), SW_SHOWMINNOACTIVE
(7), and SW_FORCEMINIMIZE
(11). In principle, the user can easily restore a minimized terminal. Maybe this was implemented because Terminal doesn't support wShowWindow
properly. For example, as mentioned above, start /min wt
is broken. It's better to use the classic console until that gets fixed.
Without knowing the details of what's possible, I'd expect Terminal to honor relevant fields in
STARTUPINFO
after a handoff from conhost. When a new tab (not a window) is created, I'd expect it to uselpTitle
and -- if they're still relevant in any way --dwXCountChars
,dwYCountChars
, anddwFillAttribute
. When a new window is created, I'd expect it to honor the window's initial show state, position, and size:wShowWindow
,dx
,dy
,dwXSize
, anddwYSize
. If honoring a setting isn't possible or isn't relevant when using Terminal as the default, please document it forSTARTUPINFO
, or document it in the console docs.
I get doing lpTitle
. That should be easy even if inserting a tab into an existing window. I guess same for dwFillAttribute
.
But for the other ones related to sizing and visibility... I think what I'd do is... if the inbound connection specified any of those, I'd ensure the monarch/peasant granted them a fresh window to manipulate however they specified without tampering with the user's existing window. So they can only "join" automatically if they're not going to mess with what is existing and are flexible with the layout.
I understand skipping the handoff to Terminal if
wShowWindow
isSW_HIDE
(0). A hidden Terminal window would be dysfunctional since a console app can't programmatically restore the window, and neither can the user. I don't understand skipping the handoff forSW_SHOWMINIMIZED
(2),SW_MINIMIZE
(6),SW_SHOWMINNOACTIVE
(7), andSW_FORCEMINIMIZE
(11). In principle, the user can easily restore a minimized terminal. Maybe this was implemented because Terminal doesn't supportwShowWindow
properly. For example, as mentioned above,start /min wt
is broken. It's better to use the classic console until that gets fixed.
This was just a matter of scoping it. You're right, Terminal doesn't support wShowWindow
completely/properly yet and we hadn't thought through all those scenarios, so the minimum scope to get the "hard part" of the actual handoff out of the way was my goal. Additionally, when I was doing my testing, two things stood out to me: 1. Applications that don't set any of the flags or any settings and ask for a completely blank console session are most commonly destined for an interactive session. 2. Applications that mess with all the flags during the ::CreateProcess
call are usually extraordinarily sensitive to changes and performance characteristics, so I didn't want to impact them right away.
Brief notes from 1-1:
- conhost reads the
Cac
, decides if it wants to handoff. It does not drain theCac
from the driver - openconsole gets handed off to, it reads the driver. The message in flight has the original
Cac
so OpenConsole can read the startup info, without rev'ing the defterm interface. We know this works because the OpenConsole does get the title from the STARTUPINFO, so OpenConsole does get that info somehow.
Rev'ing ITerminalHandoff
is okay, since that's OpenConsole
->WindowsTerminal
and that's all in the package.
Verbatims
- start /max python
- start minimized? - maybe best we not
- I'd expect it to use lpTitle
- I'd expect it to honor the window's initial show state, position, and size: wShowWindow, dx, dy, dwXSize, and dwYSize. If honoring a setting isn't possible or isn't relevant when using Terminal as the default, please document it for STARTUPINFO, or document it in the console docs.
- I'd ensure the monarch/peasant granted them a fresh window to manipulate however they specified without tampering with the user's existing window. So they can only "join" automatically if they're not going to mess with what is existing and are flexible with the layout.
- if we get the lnk filename or the exe path from ITerminalHandoff, we can cobble together a fake profile (based on the console settings in the lnk or registry) that "looks-like-" what conhost would have looked like for that lnk or exe
- font
- colors (? how will this work with schemes?)
- cursor
- icon
Todo's
- [ ]
start /max python
- [ ]
STARTUP_INFO
members:- [x]
lpTitle
- [ ]
wShowWindow
- [ ]
dx
- [ ]
dy
- [ ]
dwXSize
- [ ]
dwYSize
- [ ] When x/y/w/h are specified, and the monarch wants to attach to an existing window, instead create a new window with those args.
- [x]
- [ ] Properties from
lnk
/reg
:- [ ] font
- [ ] colors (? how will this work with schemes?)
- [ ] cursor
- [ ] icon
- Probably able to fake with
start "C:\WINDOWS\system32\notepad.EXE" cmd
- Probably able to fake with
Notes
- in
srvinit.cpp@ConsoleEstablishHandoff
, we attempt tohandoff->EstablishPtyHandoff
to the Terminal. There, we have aPCONSOLE_API_MSG connectMessage
we can use. - (elsewhere)
IoDispatchers::ConsoleHandleConnectionRequest
is responsible for unpacking the connection request. It creates aCONSOLE_API_CONNECTINFO
viaConsoleInitializeConnectInfo(PCONSOLE_API_MSG,...)
-
srvinit.cpp@ConsoleInitializeConnectInfo
shows how we unpack/pack that thing. - pay attention to the
Cac->ConsoleInfo
member, that's aSettings
, a la the console settings. -
srvinit.cpp@ConsoleAllocateConsole
shows how we create a conhost with that - Especially
Settings::ApplyStartupInfo
- refer to https://github.com/microsoft/terminal/blob/7b775684e8206abdd12a6720252d0888f1c9d6d0/src/interactivity/win32/SystemConfigurationProvider.cpp#L172-L188 for the icon loading
- OpenConsole!615061
-
Note: For discussion:
I'm leaning towards closing this out with the combo of #14222 and #13838. We can pass the startup info into the Terminal now, but I'm reluctant to change the behavior where defterm filters out start /min cli-app.exe
invocations. start /min wt cli-app.exe
will work, and start /max cli-app.exe
will both launch into the terminal, and start /min cli-app.exe
will open a minimized conhost running cli-app.exe
. As further noted in https://github.com/microsoft/terminal/pull/14222#issuecomment-1499276623