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

window of a windows terminal is appending to the end of windows stack #15763

Open
Tracked by #14957
beqabeqa473 opened this issue Jul 26, 2023 · 18 comments
Open
Tracked by #14957
Labels
Area-DefApp Area-Windowing Window frame, quake mode, tearout Help Wanted We encourage anyone to jump in on these. Issue-Bug It either shouldn't be doing this or needs an investigation. Product-Terminal The new Windows Terminal.
Milestone

Comments

@beqabeqa473
Copy link

Windows Terminal version

1.17.11461.0

Windows build number

Version 22H2 (OS Build 19045.3086)

Other Software

No response

Steps to reproduce

Open windows terminal;
Press Alt+Tab to go to another window;
Press Alt+Tab again.

Expected Behavior

I should go to Windows terminal window again by pressing Alt+Tab

Actual Behavior

I am getting second window in the windows stack instead of windows terminal and windows terminal is beeing appended to the end of stack and i need to press alt+shift+tab to find a terminal window

@beqabeqa473 beqabeqa473 added Issue-Bug It either shouldn't be doing this or needs an investigation. Needs-Triage It's a new issue that the core contributor team needs to triage at the next triage meeting labels Jul 26, 2023
@carlos-zamora
Copy link
Member

Hi @beqabeqa473. We've got a few questions for you:

  • Do you happen to know if this happens with other versions of terminal (1.16 or 1.18)?
  • Or other apps on your machine?
  • Maybe only when NVDA is running?

@beqabeqa473
Copy link
Author

Hello.

It happens with 1.16 as well as with 1.18
i cannot tell if this only happens when nvda is running because i cannot test this without nvda, but i think window reorderring should not be nvda fault.

@jry2
Copy link

jry2 commented Jul 28, 2023

I have the same problem on my desktop and laptop. Both with Windows 11. I tried closing the other running applications, but I couldn't locate the problem.

I have been observing the problem for several months, on older versions of Windows 11 and Windows Terminal.

@carlos-zamora carlos-zamora added the Needs-Attention The core contributors need to come back around and look at this ASAP. label Jul 28, 2023
@jry2
Copy link

jry2 commented Aug 9, 2023

This problem is also mentioned in this post: https://superuser.com/questions/1777841/windows-terminal-isnt-added-to-tab-history-when-started-via-the-run-dialog

I can confirm that the WT taskbar icon is indeed not rendered as active (longer horizontal line below the icon), although the window responds normally to keystrokes.

Something changed during the tests and now I am unable to reproduce the problem. I was able to reproduce it when running cmd.exe.

@jry2
Copy link

jry2 commented Aug 9, 2023

wtproblem

@jry2
Copy link

jry2 commented Aug 9, 2023

@petrsol
Copy link

petrsol commented Aug 11, 2023

I have the same problem on my win11 22H2 22621.2134. More accurately, it sometimes works well and sometimes goes to back of windows stack. Unfortunatelly I have no idea how to reproduce it for sure.

@WilliamK7
Copy link

I have the same problem on my win11 22H2 22621.2134. More accurately, it sometimes works well and sometimes goes to back of windows stack. Unfortunatelly I have no idea how to reproduce it for sure.

According to this post, it seems that you need to use Win+R to call Terminal to reproduce

@jry2
Copy link

jry2 commented Aug 11, 2023

I'm not sure if this is the same problem. If I run cmd from the task manager, the window appears in the background, but cursor is blinking. It doesn't accept keys (until after activation). If I run wt instead, everything works correctly.
wtproblem2

@WilliamK7
Copy link

So the temporary solution is to run wt instead of cmd/powershell, right?😀

@zadjii-msft zadjii-msft added Help Wanted We encourage anyone to jump in on these. Product-Terminal The new Windows Terminal. Area-DefApp Area-Windowing Window frame, quake mode, tearout and removed Needs-Triage It's a new issue that the core contributor team needs to triage at the next triage meeting Needs-Attention The core contributors need to come back around and look at this ASAP. labels Aug 23, 2023
@zadjii-msft zadjii-msft added this to the Backlog milestone Aug 23, 2023
@rzvxa
Copy link

rzvxa commented Nov 6, 2023

So the temporary solution is to run wt instead of cmd/powershell, right?😀

It is funny, I have version 1.19.2682.0 and it only works when I launch using cmd/powershell, launching via the Windows terminal starts the process in the background.

@rubenwe
Copy link

rubenwe commented Nov 16, 2023

Same issue here!

@rzvxa
Copy link

rzvxa commented Nov 16, 2023

Same issue here!

Can you try pressing Windows + D and bring your windows up manually again and test it once more?
If that didn't work please also try to restart your machine.

As of today, I observed weird behavior from this bug, I usually put my machine to sleep instead of shutting it down, Last night I turned off my PC after a long time, and today it seemed like the problem had been solved just for it to happen again after a while.
When it started to show this issue again I used Windows + D to get back to the desktop and then brought my browser and other windows up manually from the taskbar and the issue was gone once again.

@lhecker @zadjii-msft if you guys have an idea of where the problem is originating from please give some insight about it, Right now I'm transitioning between jobs and I have some extra free time so maybe I can help with solving it.
If there is already a fix for it in the work let me know so I don't spend any time on it, My day job is game engine development so I think there is a lot of overlap between rendering a game and rendering a terminal. But even with that in mind, it is going to take a while for me to familiarize myself with the codebase.

@lhecker
Copy link
Member

lhecker commented Nov 16, 2023

We haven't started working on this yet and I personally wouldn't know why this happens either - this seems like something that would just need random experimenting.

That said, this bug doesn't happen on my machine in the first place... 😐
If the issue happens mostly (or only) when using Win+R then the cause would be something we call "handoff". I'm not the most familiar with that code or our windowing, but things that worry me generally speaking are these two places:

  • if (const auto hwnd = GetHandle())
    {
    // IMPORTANT!
    //
    // ONLY "restore" if already minimized. If the window is maximized or
    // snapped, a restore will restore-down the window instead.
    if (showOrHide == true && ::IsIconic(hwnd))
    {
    ::PostMessage(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);
    }
    else if (showOrHide == false)
    {
    ::PostMessage(hwnd, WM_SYSCOMMAND, SC_MINIMIZE, 0);
    }
    }

    Since 6b936d9 we propage the visibility of Windows Terminal down to ConPTY so that console applications know whether they're currently visible or not. Also, it allows them to make themselves visible. The current implementation however is imperfect, because Windows Terminal starts in a visible state, while ConPTY starts in an invisible state. So when we send the initial ShowHide message "hey ConPTY you're visible", then it'll trigger a visiblity change in ConPTY. This is (currently) indistinguishable of a programmatic change, and so it'll cause it to emit "hey I just changed visibility" message back to Windows Terminal which will end up calling the above function. Due to the IsIconic check this should then not do anything normally, but I'm a bit worried if this code can be in a race condition with the next bullet point's function. Because if this one is faster than the next one, is it possible that we'll do a SC_RESTORE before we show the window, causing this issue?
  • winrt::fire_and_forget AppHost::_WindowInitializedHandler(const winrt::Windows::Foundation::IInspectable& /*sender*/,
    const winrt::Windows::Foundation::IInspectable& /*arg*/)
    {
    _isWindowInitialized = WindowInitializedState::Initializing;
    // GH#11561: We're totally done being initialized. Resize the window to
    // match the initial settings, and then call ShowWindow to finally make us
    // visible.
    // Use the visibility that we were originally requested with as a base. We
    // can't just use SW_SHOWDEFAULT, because that is set on a per-process
    // basis. That means that a second window needs to have its STARTUPINFO's
    // wShowCmd passed into the original process.
    auto nCmdShow = _launchShowWindowCommand;
    if (WI_IsFlagSet(_launchMode, LaunchMode::MaximizedMode))
    {
    nCmdShow = SW_MAXIMIZE;
    }
    auto weakThis{ weak_from_this() };
    // For inexplicable reasons, again, hop to the BG thread, then back to the
    // UI thread. This is shockingly load bearing - without this, then
    // sometimes, we'll _still_ show the HWND before the XAML island actually
    // paints.
    co_await wil::resume_foreground(_windowLogic.GetRoot().Dispatcher(), winrt::Windows::UI::Core::CoreDispatcherPriority::Low);
    // If we're gone on the other side of this co_await, well, that's fine. Just bail.
    const auto strongThis = weakThis.lock();
    if (!strongThis || _window == nullptr)
    {
    co_return;
    }
    ShowWindow(_window->GetHandle(), nCmdShow);
    // If we didn't start the window hidden (in one way or another), then try to
    // pull ourselves to the foreground. Don't necessarily do a whole "summon",
    // we don't really want to STEAL foreground if someone rightfully took it
    const bool noForeground = nCmdShow == SW_SHOWMINIMIZED ||
    nCmdShow == SW_SHOWNOACTIVATE ||
    nCmdShow == SW_SHOWMINNOACTIVE ||
    nCmdShow == SW_SHOWNA ||
    nCmdShow == SW_FORCEMINIMIZE;
    if (!noForeground)
    {
    SetForegroundWindow(_window->GetHandle());
    _peasantNotifyActivateWindow();
    }
    // Don't set our state to Initialized until after the call to ShowWindow.
    // When we call ShowWindow, the OS will also send us a WM_MOVE, which we'll
    // then use to try and dismiss an open dialog. This creates the unintended
    // side effect of immediately dismissing the initial warning dialog, if
    // there were settings load warnings.
    //
    // In AppHost::_WindowMoved, we'll make sure we're at least initialized
    // before dismissing open dialogs.
    _isWindowInitialized = WindowInitializedState::Initialized;
    }

    This function is responsible for showing the window initially. This code worries me because it does a manual SetForegroundWindow, which I haven't seen in other Win32 applications before. It's also only called once WinUI did its initial layout pass (= quadrillions of CPU cycles, because why), which worries me in combination with the previous bullet point, because of the interaction with IsIconic. (Just to be clear, I'm not sure if the window is considered iconic or not at this point - I'm just guessing). Also, Windows Terminal may launch with multiple windows concurrently and I'm not sure how SetForegroundWindow performs in that situation.

@oldium
Copy link

oldium commented Nov 16, 2023

We haven't started working on this yet and I personally wouldn't know why this happens either - this seems like something that would just need random experimenting.

That said, this bug doesn't happen on my machine in the first place... 😐 If the issue happens mostly (or only) when using Win+R then the cause would be something we call "handoff". I'm not the most familiar with that code or our windowing, but things that worry me generally speaking are these two places:

  • if (const auto hwnd = GetHandle())
    {
    // IMPORTANT!
    //
    // ONLY "restore" if already minimized. If the window is maximized or
    // snapped, a restore will restore-down the window instead.
    if (showOrHide == true && ::IsIconic(hwnd))
    {
    ::PostMessage(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);
    }
    else if (showOrHide == false)
    {
    ::PostMessage(hwnd, WM_SYSCOMMAND, SC_MINIMIZE, 0);
    }
    }

    Since 6b936d9 we propage the visibility of Windows Terminal down to ConPTY so that console applications know whether they're currently visible or not. Also, it allows them to make themselves visible. The current implementation however is imperfect, because Windows Terminal starts in a visible state, while ConPTY starts in an invisible state. So when we send the initial ShowHide message "hey ConPTY you're visible", then it'll trigger a visiblity change in ConPTY. This is (currently) indistinguishable of a programmatic change, and so it'll cause it to emit "hey I just changed visibility" message back to Windows Terminal which will end up calling the above function. Due to the IsIconic check this should then not do anything normally, but I'm a bit worried if this code can be in a race condition with the next bullet point's function. Because if this one is faster than the next one, is it possible that we'll do a SC_RESTORE before we show the window, causing this issue?

  • winrt::fire_and_forget AppHost::_WindowInitializedHandler(const winrt::Windows::Foundation::IInspectable& /*sender*/,
    const winrt::Windows::Foundation::IInspectable& /*arg*/)
    {
    _isWindowInitialized = WindowInitializedState::Initializing;
    // GH#11561: We're totally done being initialized. Resize the window to
    // match the initial settings, and then call ShowWindow to finally make us
    // visible.
    // Use the visibility that we were originally requested with as a base. We
    // can't just use SW_SHOWDEFAULT, because that is set on a per-process
    // basis. That means that a second window needs to have its STARTUPINFO's
    // wShowCmd passed into the original process.
    auto nCmdShow = _launchShowWindowCommand;
    if (WI_IsFlagSet(_launchMode, LaunchMode::MaximizedMode))
    {
    nCmdShow = SW_MAXIMIZE;
    }
    auto weakThis{ weak_from_this() };
    // For inexplicable reasons, again, hop to the BG thread, then back to the
    // UI thread. This is shockingly load bearing - without this, then
    // sometimes, we'll _still_ show the HWND before the XAML island actually
    // paints.
    co_await wil::resume_foreground(_windowLogic.GetRoot().Dispatcher(), winrt::Windows::UI::Core::CoreDispatcherPriority::Low);
    // If we're gone on the other side of this co_await, well, that's fine. Just bail.
    const auto strongThis = weakThis.lock();
    if (!strongThis || _window == nullptr)
    {
    co_return;
    }
    ShowWindow(_window->GetHandle(), nCmdShow);
    // If we didn't start the window hidden (in one way or another), then try to
    // pull ourselves to the foreground. Don't necessarily do a whole "summon",
    // we don't really want to STEAL foreground if someone rightfully took it
    const bool noForeground = nCmdShow == SW_SHOWMINIMIZED ||
    nCmdShow == SW_SHOWNOACTIVATE ||
    nCmdShow == SW_SHOWMINNOACTIVE ||
    nCmdShow == SW_SHOWNA ||
    nCmdShow == SW_FORCEMINIMIZE;
    if (!noForeground)
    {
    SetForegroundWindow(_window->GetHandle());
    _peasantNotifyActivateWindow();
    }
    // Don't set our state to Initialized until after the call to ShowWindow.
    // When we call ShowWindow, the OS will also send us a WM_MOVE, which we'll
    // then use to try and dismiss an open dialog. This creates the unintended
    // side effect of immediately dismissing the initial warning dialog, if
    // there were settings load warnings.
    //
    // In AppHost::_WindowMoved, we'll make sure we're at least initialized
    // before dismissing open dialogs.
    _isWindowInitialized = WindowInitializedState::Initialized;
    }

    This function is responsible for showing the window initially. This code worries me because it does a manual SetForegroundWindow, which I haven't seen in other Win32 applications before. It's also only called once WinUI did its initial layout pass (= quadrillions of CPU cycles, because why), which worries me in combination with the previous bullet point, because of the interaction with IsIconic. (Just to be clear, I'm not sure if the window is considered iconic or not at this point - I'm just guessing). Also, Windows Terminal may launch with multiple windows concurrently and I'm not sure how SetForegroundWindow performs in that situation.

If you are not able to repro, I recommend repeating the steps from my bug report. On my PC it happens once you reorder the Windows Terminal windows stack (click on the first one). Otherwise it looks like it works.

  1. Open File Explorer, place it on the screen so that new Windows Terminal window must open over it.
  2. On address bar of File Explorer, write wt and press Enter.
  3. New Windows Terminal window opens in front of other windows and gets focus.
  4. Switch back to File Explorer's address bar, write wt and press Enter.
  5. New Windows Terminal window opens in front of other windows and gets focus.
  6. Click on the first Windows Terminal window's title bar (move the second Windows Terminal window first - if necessary).
  7. Switch back to File Explorer's address bar, write wt and press Enter.
  8. Observe that the Windows Terminal window is opened in background (not over File Explorer, but below it), has blinking cursor like it has focus, but it does not have focus.

@JollyRgrs
Copy link

not sure if I have the same issue or completely different. I normally launch my first instance of terminal via a taskbar pin to a specific shell (launches ssh.exe directly into a specific box), that has no problem popping on top of things already on the screen. If I use the start menu and open the Windows "Terminal" app, it pops under and is in a random place. At the moment, I have a list of 23 items in my alt+tab view and it gets place 19 (my initial terminal window is in spot 3). If I close all terminal windows and open a terminal via start menu, the first instance works and the second goes in the background, always seemingly in the same spot (I have 5 chrome windows open at the end of my alt+tab (not all my chrome windows, but just some) and it always places just prior to them at the 6th from last spot.

If I go to start and type "wt" and launch it that way, it will always pop up on top . It is just the "Terminal" app option from the start menu (and only instances after the first terminal).

This is Terminal version 1.20.11381.0 on Windows 11 23H2 (OS Build 22631.3737)

@rzvxa
Copy link

rzvxa commented Jun 21, 2024

@JollyRgrs I feel that is related!
I can confirm it is still an issue but I couldn't find the source with the limited time I've put into it, I guess I'm just not familiar with the code base. In addition to that I've only worked with Windows windowing API in game development so it is safe to say that I've used it minimally mostly doing fullscreen.

I would like to give it another try someday but that would be later this year maybe even as far as holidays since I'm busy with other projects.

I really hope some generous soul out there would pick this up before that🥺

@carlos-zamora
Copy link
Member

Copied over from #17484:

Windows Terminal version

1.20.11381.0

Windows build number

10.0.22631.3737

Other Software

No response

Steps to reproduce

  1. Close all Windows terminal windows
  2. Make test.cmd with the contents pause
  3. Open test.cmd with Windows terminal
  4. Change focus to a different application like Edge
  5. Press the Windows key and r, then type wt
  6. Moving the mouse back to the edge window may contribute to reproducing this

Expected Behavior

The new terminal window is on top and has focus.

The expected behavior happens if you skip step 3.

Actual Behavior

Sometimes the new terminal window is behind and does not have focus. The terminal icon in the dock is red.

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 Help Wanted We encourage anyone to jump in on these. Issue-Bug It either shouldn't be doing this or needs an investigation. Product-Terminal The new Windows Terminal.
Projects
None yet
Development

No branches or pull requests