Skip to content

Commit

Permalink
Merge commit '26d67d9c0af0a05b0e65aa76537006862d39535b' into dev/mini…
Browse files Browse the repository at this point in the history
…ksa/msgs
  • Loading branch information
zadjii-msft committed Apr 13, 2022
2 parents 6bdc8c9 + 26d67d9 commit 69b77ca
Show file tree
Hide file tree
Showing 27 changed files with 231 additions and 15 deletions.
1 change: 1 addition & 0 deletions .github/actions/spelling/allow/apis.txt
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ REGCLS
RETURNCMD
rfind
roundf
ROOTOWNER
RSHIFT
SACL
schandle
Expand Down
10 changes: 10 additions & 0 deletions src/cascadia/TerminalApp/TerminalPage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ namespace winrt::TerminalApp::implementation

// Method Description:
// - implements the IInitializeWithWindow interface from shobjidl_core.
// - We're going to use this HWND as the owner for the ConPTY windows, via
// ConptyConnection::ReparentWindow. We need this for applications that
// call GetConsoleWindow, and attempt to open a MessageBox for the
// console. By marking the conpty windows as owned by the Terminal HWND,
// the message box will be owned by the Terminal window as well.
// - see GH#2988
HRESULT TerminalPage::Initialize(HWND hwnd)
{
_hostingHwnd = hwnd;
Expand Down Expand Up @@ -2429,6 +2435,10 @@ namespace winrt::TerminalApp::implementation
term.WindowVisibilityChanged(_visible);
}

if (_hostingHwnd.has_value())
{
term.OwningHwnd(reinterpret_cast<uint64_t>(*_hostingHwnd));
}
return term;
}

Expand Down
21 changes: 21 additions & 0 deletions src/cascadia/TerminalConnection/ConptyConnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,10 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
{
THROW_IF_FAILED(ConptyShowHidePseudoConsole(_hPC.get(), _initialVisibility));
}
if (_initialParentHwnd != 0)
{
THROW_IF_FAILED(ConptyReparentPseudoConsole(_hPC.get(), reinterpret_cast<HWND>(_initialParentHwnd)));
}

THROW_IF_FAILED(_LaunchAttachedClient());
}
Expand All @@ -334,6 +338,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance));

THROW_IF_FAILED(ConptyResizePseudoConsole(_hPC.get(), dimensions));
THROW_IF_FAILED(ConptyReparentPseudoConsole(_hPC.get(), reinterpret_cast<HWND>(_initialParentHwnd)));
}

_startTime = std::chrono::high_resolution_clock::now();
Expand Down Expand Up @@ -502,6 +507,22 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
}
}

void ConptyConnection::ReparentWindow(const uint64_t newParent)
{
// If we haven't started connecting at all, stash this HWND to use once we have started.
if (!_isStateAtOrBeyond(ConnectionState::Connecting))
{
_initialParentHwnd = newParent;
}
// Otherwise, just inform the conpty of the new owner window handle.
// This shouldn't be hittable until GH#5000 / GH#1256, when it's
// possible to reparent terminals to different windows.
else if (_isConnected())
{
THROW_IF_FAILED(ConptyReparentPseudoConsole(_hPC.get(), reinterpret_cast<HWND>(newParent)));
}
}

void ConptyConnection::Close() noexcept
try
{
Expand Down
4 changes: 4 additions & 0 deletions src/cascadia/TerminalConnection/ConptyConnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,11 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
void Resize(uint32_t rows, uint32_t columns);
void Close() noexcept;
void ClearBuffer();

void ShowHide(const bool show);

void ReparentWindow(const uint64_t newParent);

winrt::guid Guid() const noexcept;
winrt::hstring Commandline() const;

Expand Down Expand Up @@ -66,6 +69,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation

uint32_t _initialRows{};
uint32_t _initialCols{};
uint64_t _initialParentHwnd{ 0 };
hstring _commandline{};
hstring _startingDirectory{};
hstring _startingTitle{};
Expand Down
3 changes: 3 additions & 0 deletions src/cascadia/TerminalConnection/ConptyConnection.idl
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,11 @@ namespace Microsoft.Terminal.TerminalConnection
String Commandline { get; };

void ClearBuffer();

void ShowHide(Boolean show);

void ReparentWindow(UInt64 newParent);

static event NewConnectionHandler NewConnection;
static void StartInboundListener();
static void StopInboundListener();
Expand Down
8 changes: 8 additions & 0 deletions src/cascadia/TerminalControl/ControlCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const auto height = vp.Height();
_connection.Resize(height, width);

if (_OwningHwnd != 0)
{
if (auto conpty{ _connection.try_as<TerminalConnection::ConptyConnection>() })
{
conpty.ReparentWindow(_OwningHwnd);
}
}

// Override the default width and height to match the size of the swapChainPanel
_settings->InitialCols(width);
_settings->InitialRows(height);
Expand Down
5 changes: 5 additions & 0 deletions src/cascadia/TerminalControl/ControlCore.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation

void WindowVisibilityChanged(const bool showOrHide);

// TODO:GH#1256 - When a tab can be torn out or otherwise reparented to
// another window, this value will need a custom setter, so that we can
// also update the connection.
WINRT_PROPERTY(uint64_t, OwningHwnd, 0);

RUNTIME_SETTING(double, Opacity, _settings->Opacity());
RUNTIME_SETTING(bool, UseAcrylic, _settings->UseAcrylic());

Expand Down
3 changes: 3 additions & 0 deletions src/cascadia/TerminalControl/ICoreState.idl
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,8 @@ namespace Microsoft.Terminal.Control
Microsoft.Terminal.TerminalConnection.ConnectionState ConnectionState { get; };

Microsoft.Terminal.Core.Scheme ColorScheme { get; set; };

UInt64 OwningHwnd;

};
}
10 changes: 10 additions & 0 deletions src/cascadia/TerminalControl/TermControl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2807,4 +2807,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
}

void TermControl::OwningHwnd(uint64_t owner)
{
_core.OwningHwnd(owner);
}

uint64_t TermControl::OwningHwnd()
{
return _core.OwningHwnd();
}

}
3 changes: 3 additions & 0 deletions src/cascadia/TerminalControl/TermControl.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
bool BracketedPasteEnabled() const noexcept;

double BackgroundOpacity() const;

uint64_t OwningHwnd();
void OwningHwnd(uint64_t owner);
#pragma endregion

void ScrollViewport(int viewTop);
Expand Down
5 changes: 5 additions & 0 deletions src/cascadia/WindowsTerminal/IslandWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ IslandWindow::~IslandWindow()
_source.Close();
}

HWND IslandWindow::GetInteropHandle() const
{
return _interopWindowHandle;
}

// Method Description:
// - Create the actual window that we'll use for the application.
// Arguments:
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/WindowsTerminal/IslandWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class IslandWindow :
virtual void MakeWindow() noexcept;
void Close();
virtual void OnSize(const UINT width, const UINT height);
HWND GetInteropHandle() const;

[[nodiscard]] virtual LRESULT MessageHandler(UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept override;
void OnResize(const UINT width, const UINT height) override;
Expand Down
46 changes: 46 additions & 0 deletions src/host/PtySignalInputThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ DWORD WINAPI PtySignalInputThread::StaticThreadProc(_In_ LPVOID lpParameter)
// (in and screen buffers) haven't yet been initialized.
// - NOTE: Call under LockConsole() to ensure other threads have an opportunity
// to set early-work state.
// - We need to do this specifically on the thread with the message pump. If the
// window is created on another thread, then the window won't have a message
// pump associated with it, and a DPI change in the connected terminal could
// end up HANGING THE CONPTY (for example).
// Arguments:
// - <none>
// Return Value:
Expand All @@ -71,6 +75,12 @@ void PtySignalInputThread::ConnectConsole() noexcept
{
_DoShowHide(_initialShowHide->show);
}

// If we were given a owner HWND, then manually start the pseudo window now.
if (_earlyReparent)
{
_DoSetWindowParent(*_earlyReparent);
}
}

// Method Description:
Expand Down Expand Up @@ -150,6 +160,28 @@ void PtySignalInputThread::ConnectConsole() noexcept

break;
}
case PtySignal::SetParent:
{
SetParentData reparentMessage = { 0 };
_GetData(&reparentMessage, sizeof(reparentMessage));

LockConsole();
auto Unlock = wil::scope_exit([&] { UnlockConsole(); });

// If the client app hasn't yet connected, stash the new owner.
// We'll later (PtySignalInputThread::ConnectConsole) use the value
// to set up the owner of the conpty window.
if (!_consoleConnected)
{
_earlyReparent = reparentMessage;
}
else
{
_DoSetWindowParent(reparentMessage);
}

break;
}
default:
{
THROW_HR(E_UNEXPECTED);
Expand Down Expand Up @@ -183,6 +215,20 @@ void PtySignalInputThread::_DoShowHide(const bool show)
_pConApi->ShowWindow(show);
}

// Method Description:
// - Update the owner of the pseudo-window we're using for the conpty HWND. This
// allows to mark the pseudoconsole windows as "owner" by the terminal HWND
// that's actually hosting them.
// - Refer to GH#2988
// Arguments:
// - data - Packet information containing owner HWND information
// Return Value:
// - <none>
void PtySignalInputThread::_DoSetWindowParent(const SetParentData& data)
{
_pConApi->ReparentWindow(data.handle);
}

// Method Description:
// - Retrieves bytes from the file stream and exits or throws errors should the pipe state
// be compromised.
Expand Down
11 changes: 11 additions & 0 deletions src/host/PtySignalInputThread.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ namespace Microsoft::Console
{
ShowHideWindow = 1,
ClearBuffer = 2,
SetParent = 3,
ResizeWindow = 8
};

Expand All @@ -50,14 +51,21 @@ namespace Microsoft::Console
unsigned short sx;
unsigned short sy;
};

struct ShowHideData
{
unsigned short show; // used as a bool, but passed as a ushort
};

struct SetParentData
{
uint64_t handle;
};

[[nodiscard]] HRESULT _InputThread();
bool _GetData(_Out_writes_bytes_(cbBuffer) void* const pBuffer, const DWORD cbBuffer);
void _DoResizeWindow(const ResizeWindowData& data);
void _DoSetWindowParent(const SetParentData& data);
void _DoClearBuffer();
void _DoShowHide(const bool show);
void _Shutdown();
Expand All @@ -69,5 +77,8 @@ namespace Microsoft::Console
std::optional<ResizeWindowData> _earlyResize;
std::optional<ShowHideData> _initialShowHide;
std::unique_ptr<Microsoft::Console::VirtualTerminal::ConGetSet> _pConApi;

public:
std::optional<SetParentData> _earlyReparent;
};
}
5 changes: 5 additions & 0 deletions src/host/VtIo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,11 @@ bool VtIo::IsUsingVt() const

if (_pPtySignalInputThread)
{
// IMPORTANT! Start the pseudo window on this thread. This thread has a
// message pump. If you DON'T, then a DPI change in the owning hwnd will
// cause us to get a dpi change as well, which we'll never deque and
// handle, effectively HANGING THE OWNER HWND.
//
// Let the signal thread know that the console is connected
_pPtySignalInputThread->ConnectConsole();
}
Expand Down
14 changes: 14 additions & 0 deletions src/host/outputStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -905,3 +905,17 @@ void ConhostInternalGetSet::UpdateSoftFont(const gsl::span<const uint16_t> bitPa
pRender->UpdateSoftFont(bitPattern, cellSize, centeringHint);
}
}

void ConhostInternalGetSet::ReparentWindow(const uint64_t handle)
{
// This will initialize s_interactivityFactory for us. It will also
// conveniently return 0 when we're on OneCore.
//
// If the window hasn't been created yet, by some other call to
// LocatePseudoWindow, then this will also initialize the owner of the
// window.
if (const auto psuedoHwnd{ ServiceLocator::LocatePseudoWindow(reinterpret_cast<HWND>(handle)) })
{
LOG_LAST_ERROR_IF_NULL(::SetParent(psuedoHwnd, reinterpret_cast<HWND>(handle)));
}
}
2 changes: 2 additions & 0 deletions src/host/outputStream.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ class ConhostInternalGetSet final : public Microsoft::Console::VirtualTerminal::
const SIZE cellSize,
const size_t centeringHint) override;

void ReparentWindow(const uint64_t handle);

private:
void _modifyLines(const size_t count, const bool insert);

Expand Down
2 changes: 2 additions & 0 deletions src/inc/conpty-static.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ HRESULT WINAPI ConptyClearPseudoConsole(HPCON hPC);

HRESULT WINAPI ConptyShowHidePseudoConsole(HPCON hPC, bool show);

HRESULT WINAPI ConptyReparentPseudoConsole(HPCON hPC, HWND newParent);

VOID WINAPI ConptyClosePseudoConsole(HPCON hPC);

HRESULT WINAPI ConptyPackPseudoConsole(HANDLE hServerProcess, HANDLE hRef, HANDLE hSignal, HPCON* phPC);
Expand Down
Loading

0 comments on commit 69b77ca

Please sign in to comment.