mirror of
https://github.com/microsoft/terminal.git
synced 2025-12-21 02:47:49 -05:00
Merge commit '26d67d9c0af0a05b0e65aa76537006862d39535b' into dev/miniksa/msgs
This commit is contained in:
1
.github/actions/spelling/allow/apis.txt
vendored
1
.github/actions/spelling/allow/apis.txt
vendored
@@ -145,6 +145,7 @@ REGCLS
|
|||||||
RETURNCMD
|
RETURNCMD
|
||||||
rfind
|
rfind
|
||||||
roundf
|
roundf
|
||||||
|
ROOTOWNER
|
||||||
RSHIFT
|
RSHIFT
|
||||||
SACL
|
SACL
|
||||||
schandle
|
schandle
|
||||||
|
|||||||
@@ -60,6 +60,12 @@ namespace winrt::TerminalApp::implementation
|
|||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
// - implements the IInitializeWithWindow interface from shobjidl_core.
|
// - 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)
|
HRESULT TerminalPage::Initialize(HWND hwnd)
|
||||||
{
|
{
|
||||||
_hostingHwnd = hwnd;
|
_hostingHwnd = hwnd;
|
||||||
@@ -2429,6 +2435,10 @@ namespace winrt::TerminalApp::implementation
|
|||||||
term.WindowVisibilityChanged(_visible);
|
term.WindowVisibilityChanged(_visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_hostingHwnd.has_value())
|
||||||
|
{
|
||||||
|
term.OwningHwnd(reinterpret_cast<uint64_t>(*_hostingHwnd));
|
||||||
|
}
|
||||||
return term;
|
return term;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -316,6 +316,10 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||||||
{
|
{
|
||||||
THROW_IF_FAILED(ConptyShowHidePseudoConsole(_hPC.get(), _initialVisibility));
|
THROW_IF_FAILED(ConptyShowHidePseudoConsole(_hPC.get(), _initialVisibility));
|
||||||
}
|
}
|
||||||
|
if (_initialParentHwnd != 0)
|
||||||
|
{
|
||||||
|
THROW_IF_FAILED(ConptyReparentPseudoConsole(_hPC.get(), reinterpret_cast<HWND>(_initialParentHwnd)));
|
||||||
|
}
|
||||||
|
|
||||||
THROW_IF_FAILED(_LaunchAttachedClient());
|
THROW_IF_FAILED(_LaunchAttachedClient());
|
||||||
}
|
}
|
||||||
@@ -334,6 +338,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||||||
TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance));
|
TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance));
|
||||||
|
|
||||||
THROW_IF_FAILED(ConptyResizePseudoConsole(_hPC.get(), dimensions));
|
THROW_IF_FAILED(ConptyResizePseudoConsole(_hPC.get(), dimensions));
|
||||||
|
THROW_IF_FAILED(ConptyReparentPseudoConsole(_hPC.get(), reinterpret_cast<HWND>(_initialParentHwnd)));
|
||||||
}
|
}
|
||||||
|
|
||||||
_startTime = std::chrono::high_resolution_clock::now();
|
_startTime = std::chrono::high_resolution_clock::now();
|
||||||
@@ -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
|
void ConptyConnection::Close() noexcept
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -35,8 +35,11 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||||||
void Resize(uint32_t rows, uint32_t columns);
|
void Resize(uint32_t rows, uint32_t columns);
|
||||||
void Close() noexcept;
|
void Close() noexcept;
|
||||||
void ClearBuffer();
|
void ClearBuffer();
|
||||||
|
|
||||||
void ShowHide(const bool show);
|
void ShowHide(const bool show);
|
||||||
|
|
||||||
|
void ReparentWindow(const uint64_t newParent);
|
||||||
|
|
||||||
winrt::guid Guid() const noexcept;
|
winrt::guid Guid() const noexcept;
|
||||||
winrt::hstring Commandline() const;
|
winrt::hstring Commandline() const;
|
||||||
|
|
||||||
@@ -66,6 +69,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||||||
|
|
||||||
uint32_t _initialRows{};
|
uint32_t _initialRows{};
|
||||||
uint32_t _initialCols{};
|
uint32_t _initialCols{};
|
||||||
|
uint64_t _initialParentHwnd{ 0 };
|
||||||
hstring _commandline{};
|
hstring _commandline{};
|
||||||
hstring _startingDirectory{};
|
hstring _startingDirectory{};
|
||||||
hstring _startingTitle{};
|
hstring _startingTitle{};
|
||||||
|
|||||||
@@ -14,8 +14,11 @@ namespace Microsoft.Terminal.TerminalConnection
|
|||||||
String Commandline { get; };
|
String Commandline { get; };
|
||||||
|
|
||||||
void ClearBuffer();
|
void ClearBuffer();
|
||||||
|
|
||||||
void ShowHide(Boolean show);
|
void ShowHide(Boolean show);
|
||||||
|
|
||||||
|
void ReparentWindow(UInt64 newParent);
|
||||||
|
|
||||||
static event NewConnectionHandler NewConnection;
|
static event NewConnectionHandler NewConnection;
|
||||||
static void StartInboundListener();
|
static void StartInboundListener();
|
||||||
static void StopInboundListener();
|
static void StopInboundListener();
|
||||||
|
|||||||
@@ -265,6 +265,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||||||
const auto height = vp.Height();
|
const auto height = vp.Height();
|
||||||
_connection.Resize(height, width);
|
_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
|
// Override the default width and height to match the size of the swapChainPanel
|
||||||
_settings->InitialCols(width);
|
_settings->InitialCols(width);
|
||||||
_settings->InitialRows(height);
|
_settings->InitialRows(height);
|
||||||
|
|||||||
@@ -170,6 +170,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||||||
|
|
||||||
void WindowVisibilityChanged(const bool showOrHide);
|
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(double, Opacity, _settings->Opacity());
|
||||||
RUNTIME_SETTING(bool, UseAcrylic, _settings->UseAcrylic());
|
RUNTIME_SETTING(bool, UseAcrylic, _settings->UseAcrylic());
|
||||||
|
|
||||||
|
|||||||
@@ -24,5 +24,8 @@ namespace Microsoft.Terminal.Control
|
|||||||
Microsoft.Terminal.TerminalConnection.ConnectionState ConnectionState { get; };
|
Microsoft.Terminal.TerminalConnection.ConnectionState ConnectionState { get; };
|
||||||
|
|
||||||
Microsoft.Terminal.Core.Scheme ColorScheme { get; set; };
|
Microsoft.Terminal.Core.Scheme ColorScheme { get; set; };
|
||||||
|
|
||||||
|
UInt64 OwningHwnd;
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,6 +61,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||||||
bool BracketedPasteEnabled() const noexcept;
|
bool BracketedPasteEnabled() const noexcept;
|
||||||
|
|
||||||
double BackgroundOpacity() const;
|
double BackgroundOpacity() const;
|
||||||
|
|
||||||
|
uint64_t OwningHwnd();
|
||||||
|
void OwningHwnd(uint64_t owner);
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
void ScrollViewport(int viewTop);
|
void ScrollViewport(int viewTop);
|
||||||
|
|||||||
@@ -41,6 +41,11 @@ IslandWindow::~IslandWindow()
|
|||||||
_source.Close();
|
_source.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HWND IslandWindow::GetInteropHandle() const
|
||||||
|
{
|
||||||
|
return _interopWindowHandle;
|
||||||
|
}
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
// - Create the actual window that we'll use for the application.
|
// - Create the actual window that we'll use for the application.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ public:
|
|||||||
virtual void MakeWindow() noexcept;
|
virtual void MakeWindow() noexcept;
|
||||||
void Close();
|
void Close();
|
||||||
virtual void OnSize(const UINT width, const UINT height);
|
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;
|
[[nodiscard]] virtual LRESULT MessageHandler(UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept override;
|
||||||
void OnResize(const UINT width, const UINT height) override;
|
void OnResize(const UINT width, const UINT height) override;
|
||||||
|
|||||||
@@ -56,6 +56,10 @@ DWORD WINAPI PtySignalInputThread::StaticThreadProc(_In_ LPVOID lpParameter)
|
|||||||
// (in and screen buffers) haven't yet been initialized.
|
// (in and screen buffers) haven't yet been initialized.
|
||||||
// - NOTE: Call under LockConsole() to ensure other threads have an opportunity
|
// - NOTE: Call under LockConsole() to ensure other threads have an opportunity
|
||||||
// to set early-work state.
|
// 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:
|
// Arguments:
|
||||||
// - <none>
|
// - <none>
|
||||||
// Return Value:
|
// Return Value:
|
||||||
@@ -71,6 +75,12 @@ void PtySignalInputThread::ConnectConsole() noexcept
|
|||||||
{
|
{
|
||||||
_DoShowHide(_initialShowHide->show);
|
_DoShowHide(_initialShowHide->show);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we were given a owner HWND, then manually start the pseudo window now.
|
||||||
|
if (_earlyReparent)
|
||||||
|
{
|
||||||
|
_DoSetWindowParent(*_earlyReparent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method Description:
|
// Method Description:
|
||||||
@@ -150,6 +160,28 @@ void PtySignalInputThread::ConnectConsole() noexcept
|
|||||||
|
|
||||||
break;
|
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:
|
default:
|
||||||
{
|
{
|
||||||
THROW_HR(E_UNEXPECTED);
|
THROW_HR(E_UNEXPECTED);
|
||||||
@@ -183,6 +215,20 @@ void PtySignalInputThread::_DoShowHide(const bool show)
|
|||||||
_pConApi->ShowWindow(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:
|
// Method Description:
|
||||||
// - Retrieves bytes from the file stream and exits or throws errors should the pipe state
|
// - Retrieves bytes from the file stream and exits or throws errors should the pipe state
|
||||||
// be compromised.
|
// be compromised.
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ namespace Microsoft::Console
|
|||||||
{
|
{
|
||||||
ShowHideWindow = 1,
|
ShowHideWindow = 1,
|
||||||
ClearBuffer = 2,
|
ClearBuffer = 2,
|
||||||
|
SetParent = 3,
|
||||||
ResizeWindow = 8
|
ResizeWindow = 8
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -50,14 +51,21 @@ namespace Microsoft::Console
|
|||||||
unsigned short sx;
|
unsigned short sx;
|
||||||
unsigned short sy;
|
unsigned short sy;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ShowHideData
|
struct ShowHideData
|
||||||
{
|
{
|
||||||
unsigned short show; // used as a bool, but passed as a ushort
|
unsigned short show; // used as a bool, but passed as a ushort
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SetParentData
|
||||||
|
{
|
||||||
|
uint64_t handle;
|
||||||
|
};
|
||||||
|
|
||||||
[[nodiscard]] HRESULT _InputThread();
|
[[nodiscard]] HRESULT _InputThread();
|
||||||
bool _GetData(_Out_writes_bytes_(cbBuffer) void* const pBuffer, const DWORD cbBuffer);
|
bool _GetData(_Out_writes_bytes_(cbBuffer) void* const pBuffer, const DWORD cbBuffer);
|
||||||
void _DoResizeWindow(const ResizeWindowData& data);
|
void _DoResizeWindow(const ResizeWindowData& data);
|
||||||
|
void _DoSetWindowParent(const SetParentData& data);
|
||||||
void _DoClearBuffer();
|
void _DoClearBuffer();
|
||||||
void _DoShowHide(const bool show);
|
void _DoShowHide(const bool show);
|
||||||
void _Shutdown();
|
void _Shutdown();
|
||||||
@@ -69,5 +77,8 @@ namespace Microsoft::Console
|
|||||||
std::optional<ResizeWindowData> _earlyResize;
|
std::optional<ResizeWindowData> _earlyResize;
|
||||||
std::optional<ShowHideData> _initialShowHide;
|
std::optional<ShowHideData> _initialShowHide;
|
||||||
std::unique_ptr<Microsoft::Console::VirtualTerminal::ConGetSet> _pConApi;
|
std::unique_ptr<Microsoft::Console::VirtualTerminal::ConGetSet> _pConApi;
|
||||||
|
|
||||||
|
public:
|
||||||
|
std::optional<SetParentData> _earlyReparent;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -300,6 +300,11 @@ bool VtIo::IsUsingVt() const
|
|||||||
|
|
||||||
if (_pPtySignalInputThread)
|
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
|
// Let the signal thread know that the console is connected
|
||||||
_pPtySignalInputThread->ConnectConsole();
|
_pPtySignalInputThread->ConnectConsole();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -905,3 +905,17 @@ void ConhostInternalGetSet::UpdateSoftFont(const gsl::span<const uint16_t> bitPa
|
|||||||
pRender->UpdateSoftFont(bitPattern, cellSize, centeringHint);
|
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)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -117,6 +117,8 @@ public:
|
|||||||
const SIZE cellSize,
|
const SIZE cellSize,
|
||||||
const size_t centeringHint) override;
|
const size_t centeringHint) override;
|
||||||
|
|
||||||
|
void ReparentWindow(const uint64_t handle);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void _modifyLines(const size_t count, const bool insert);
|
void _modifyLines(const size_t count, const bool insert);
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ HRESULT WINAPI ConptyClearPseudoConsole(HPCON hPC);
|
|||||||
|
|
||||||
HRESULT WINAPI ConptyShowHidePseudoConsole(HPCON hPC, bool show);
|
HRESULT WINAPI ConptyShowHidePseudoConsole(HPCON hPC, bool show);
|
||||||
|
|
||||||
|
HRESULT WINAPI ConptyReparentPseudoConsole(HPCON hPC, HWND newParent);
|
||||||
|
|
||||||
VOID WINAPI ConptyClosePseudoConsole(HPCON hPC);
|
VOID WINAPI ConptyClosePseudoConsole(HPCON hPC);
|
||||||
|
|
||||||
HRESULT WINAPI ConptyPackPseudoConsole(HANDLE hServerProcess, HANDLE hRef, HANDLE hSignal, HPCON* phPC);
|
HRESULT WINAPI ConptyPackPseudoConsole(HANDLE hServerProcess, HANDLE hRef, HANDLE hSignal, HPCON* phPC);
|
||||||
|
|||||||
@@ -289,9 +289,10 @@ using namespace Microsoft::Console::Interactivity;
|
|||||||
// that GetConsoleWindow returns a real value.
|
// that GetConsoleWindow returns a real value.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// - hwnd: Receives the value of the newly created window's HWND.
|
// - hwnd: Receives the value of the newly created window's HWND.
|
||||||
|
// - owner: the HWND that should be the initial owner of the pseudo window.
|
||||||
// Return Value:
|
// Return Value:
|
||||||
// - STATUS_SUCCESS on success, otherwise an appropriate error.
|
// - STATUS_SUCCESS on success, otherwise an appropriate error.
|
||||||
[[nodiscard]] NTSTATUS InteractivityFactory::CreatePseudoWindow(HWND& hwnd)
|
[[nodiscard]] NTSTATUS InteractivityFactory::CreatePseudoWindow(HWND& hwnd, const HWND owner)
|
||||||
{
|
{
|
||||||
hwnd = nullptr;
|
hwnd = nullptr;
|
||||||
ApiLevel level;
|
ApiLevel level;
|
||||||
@@ -311,21 +312,30 @@ using namespace Microsoft::Console::Interactivity;
|
|||||||
pseudoClass.lpfnWndProc = s_PseudoWindowProc;
|
pseudoClass.lpfnWndProc = s_PseudoWindowProc;
|
||||||
RegisterClass(&pseudoClass);
|
RegisterClass(&pseudoClass);
|
||||||
|
|
||||||
|
// Note that because we're not specifying WS_CHILD, this window
|
||||||
|
// will become an _owned_ window, not a _child_ window. This is
|
||||||
|
// important - child windows report their position as relative
|
||||||
|
// to their parent window, while owned windows are still
|
||||||
|
// relative to the desktop. (there are other subtleties as well
|
||||||
|
// as far as the difference between parent/child and owner/owned
|
||||||
|
// windows). Evan K said we should do it this way, and he
|
||||||
|
// definitely knows.
|
||||||
const auto windowStyle = WS_OVERLAPPEDWINDOW;
|
const auto windowStyle = WS_OVERLAPPEDWINDOW;
|
||||||
const auto exStyles = WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT | WS_EX_LAYERED;
|
const auto exStyles = WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT | WS_EX_LAYERED;
|
||||||
// Attempt to create window
|
|
||||||
|
// Attempt to create window.
|
||||||
hwnd = CreateWindowExW(exStyles,
|
hwnd = CreateWindowExW(exStyles,
|
||||||
PSEUDO_WINDOW_CLASS,
|
PSEUDO_WINDOW_CLASS,
|
||||||
nullptr,
|
nullptr,
|
||||||
windowStyle, //WS_CHILD, //WS_OVERLAPPEDWINDOW,
|
windowStyle,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
HWND_DESKTOP, // owner
|
owner,
|
||||||
nullptr,
|
nullptr,
|
||||||
nullptr,
|
nullptr,
|
||||||
this);
|
nullptr);
|
||||||
|
|
||||||
if (hwnd == nullptr)
|
if (hwnd == nullptr)
|
||||||
{
|
{
|
||||||
@@ -335,7 +345,6 @@ using namespace Microsoft::Console::Interactivity;
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef BUILD_ONECORE_INTERACTIVITY
|
#ifdef BUILD_ONECORE_INTERACTIVITY
|
||||||
case ApiLevel::OneCore:
|
case ApiLevel::OneCore:
|
||||||
hwnd = 0;
|
hwnd = 0;
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ namespace Microsoft::Console::Interactivity
|
|||||||
[[nodiscard]] NTSTATUS CreateAccessibilityNotifier(_Inout_ std::unique_ptr<IAccessibilityNotifier>& notifier);
|
[[nodiscard]] NTSTATUS CreateAccessibilityNotifier(_Inout_ std::unique_ptr<IAccessibilityNotifier>& notifier);
|
||||||
[[nodiscard]] NTSTATUS CreateSystemConfigurationProvider(_Inout_ std::unique_ptr<ISystemConfigurationProvider>& provider);
|
[[nodiscard]] NTSTATUS CreateSystemConfigurationProvider(_Inout_ std::unique_ptr<ISystemConfigurationProvider>& provider);
|
||||||
|
|
||||||
[[nodiscard]] NTSTATUS CreatePseudoWindow(HWND& hwnd);
|
[[nodiscard]] NTSTATUS CreatePseudoWindow(HWND& hwnd, const HWND owner);
|
||||||
void SetPseudoWindowCallback(std::function<void(bool)> func);
|
void SetPseudoWindowCallback(std::function<void(bool)> func);
|
||||||
|
|
||||||
// Wndproc
|
// Wndproc
|
||||||
|
|||||||
@@ -309,10 +309,11 @@ void ServiceLocator::SetPseudoWindowCallback(std::function<void(bool)> func)
|
|||||||
// Method Description:
|
// Method Description:
|
||||||
// - Retrieves the pseudo console window, or attempts to instantiate one.
|
// - Retrieves the pseudo console window, or attempts to instantiate one.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// - <none>
|
// - owner: (defaults to 0 `HWND_DESKTOP`) the HWND that should be the initial
|
||||||
|
// owner of the pseudo window.
|
||||||
// Return Value:
|
// Return Value:
|
||||||
// - a reference to the pseudoconsole window.
|
// - a reference to the pseudoconsole window.
|
||||||
HWND ServiceLocator::LocatePseudoWindow()
|
HWND ServiceLocator::LocatePseudoWindow(const HWND owner)
|
||||||
{
|
{
|
||||||
NTSTATUS status = STATUS_SUCCESS;
|
NTSTATUS status = STATUS_SUCCESS;
|
||||||
if (!s_pseudoWindowInitialized)
|
if (!s_pseudoWindowInitialized)
|
||||||
@@ -325,7 +326,7 @@ HWND ServiceLocator::LocatePseudoWindow()
|
|||||||
if (NT_SUCCESS(status))
|
if (NT_SUCCESS(status))
|
||||||
{
|
{
|
||||||
HWND hwnd;
|
HWND hwnd;
|
||||||
status = s_interactivityFactory->CreatePseudoWindow(hwnd);
|
status = s_interactivityFactory->CreatePseudoWindow(hwnd, owner);
|
||||||
s_pseudoWindow.reset(hwnd);
|
s_pseudoWindow.reset(hwnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,8 +338,6 @@ HWND ServiceLocator::LocatePseudoWindow()
|
|||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
#pragma endregion
|
|
||||||
|
|
||||||
#pragma region Private Methods
|
#pragma region Private Methods
|
||||||
|
|
||||||
[[nodiscard]] NTSTATUS ServiceLocator::LoadInteractivityFactory()
|
[[nodiscard]] NTSTATUS ServiceLocator::LoadInteractivityFactory()
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ namespace Microsoft::Console::Interactivity
|
|||||||
[[nodiscard]] virtual NTSTATUS CreateSystemConfigurationProvider(_Inout_ std::unique_ptr<ISystemConfigurationProvider>& provider) = 0;
|
[[nodiscard]] virtual NTSTATUS CreateSystemConfigurationProvider(_Inout_ std::unique_ptr<ISystemConfigurationProvider>& provider) = 0;
|
||||||
|
|
||||||
virtual void SetPseudoWindowCallback(std::function<void(bool)> func) = 0;
|
virtual void SetPseudoWindowCallback(std::function<void(bool)> func) = 0;
|
||||||
[[nodiscard]] virtual NTSTATUS CreatePseudoWindow(HWND& hwnd) = 0;
|
[[nodiscard]] virtual NTSTATUS CreatePseudoWindow(HWND& hwnd, const HWND owner) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline IInteractivityFactory::~IInteractivityFactory() {}
|
inline IInteractivityFactory::~IInteractivityFactory() {}
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ namespace Microsoft::Console::Interactivity
|
|||||||
static Globals& LocateGlobals();
|
static Globals& LocateGlobals();
|
||||||
|
|
||||||
static void SetPseudoWindowCallback(std::function<void(bool)> func);
|
static void SetPseudoWindowCallback(std::function<void(bool)> func);
|
||||||
static HWND LocatePseudoWindow();
|
static HWND LocatePseudoWindow(const HWND owner = 0 /*HWND_DESKTOP*/);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ServiceLocator(ServiceLocator const&) = delete;
|
ServiceLocator(ServiceLocator const&) = delete;
|
||||||
|
|||||||
@@ -112,5 +112,7 @@ namespace Microsoft::Console::VirtualTerminal
|
|||||||
virtual void UpdateSoftFont(const gsl::span<const uint16_t> bitPattern,
|
virtual void UpdateSoftFont(const gsl::span<const uint16_t> bitPattern,
|
||||||
const SIZE cellSize,
|
const SIZE cellSize,
|
||||||
const size_t centeringHint) = 0;
|
const size_t centeringHint) = 0;
|
||||||
|
|
||||||
|
virtual void ReparentWindow(const uint64_t handle) = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -428,6 +428,11 @@ public:
|
|||||||
VERIFY_ARE_EQUAL(_expectedCellSize.cy, cellSize.cy);
|
VERIFY_ARE_EQUAL(_expectedCellSize.cy, cellSize.cy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ReparentWindow(const uint64_t /*handle*/)
|
||||||
|
{
|
||||||
|
Log::Comment(L"ReparentWindow MOCK called...");
|
||||||
|
}
|
||||||
|
|
||||||
void PrepData()
|
void PrepData()
|
||||||
{
|
{
|
||||||
PrepData(CursorDirection::UP); // if called like this, the cursor direction doesn't matter.
|
PrepData(CursorDirection::UP); // if called like this, the cursor direction doesn't matter.
|
||||||
|
|||||||
@@ -269,7 +269,6 @@ HRESULT _ShowHidePseudoConsole(_In_ const PseudoConsole* const pPty, const bool
|
|||||||
{
|
{
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned short signalPacket[2];
|
unsigned short signalPacket[2];
|
||||||
signalPacket[0] = PTY_SIGNAL_SHOWHIDE_WINDOW;
|
signalPacket[0] = PTY_SIGNAL_SHOWHIDE_WINDOW;
|
||||||
signalPacket[1] = show;
|
signalPacket[1] = show;
|
||||||
@@ -278,6 +277,36 @@ HRESULT _ShowHidePseudoConsole(_In_ const PseudoConsole* const pPty, const bool
|
|||||||
return fSuccess ? S_OK : HRESULT_FROM_WIN32(GetLastError());
|
return fSuccess ? S_OK : HRESULT_FROM_WIN32(GetLastError());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - Sends a message to the pseudoconsole informing it that it should use the
|
||||||
|
// given window handle as the owner for the conpty's pseudo window. This
|
||||||
|
// allows the response given to GetConsoleWindow() to be a HWND that's owned
|
||||||
|
// by the actual hosting terminal's HWND.
|
||||||
|
// Arguments:
|
||||||
|
// - pPty: A pointer to a PseudoConsole struct.
|
||||||
|
// - newParent: The new owning window
|
||||||
|
// Return Value:
|
||||||
|
// - S_OK if the call succeeded, else an appropriate HRESULT for failing to
|
||||||
|
// write the resize message to the pty.
|
||||||
|
#pragma warning(suppress : 26461)
|
||||||
|
// an HWND is technically a void*, but that confuses static analysis here.
|
||||||
|
HRESULT _ReparentPseudoConsole(_In_ const PseudoConsole* const pPty, _In_ const HWND newParent)
|
||||||
|
{
|
||||||
|
if (pPty == nullptr)
|
||||||
|
{
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
// sneaky way to pack a short and a uint64_t in a relatively literal way.
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
struct _signal
|
||||||
|
{
|
||||||
|
const unsigned short id;
|
||||||
|
const uint64_t hwnd;
|
||||||
|
} data{ PTY_SIGNAL_REPARENT_WINDOW, (uint64_t)(newParent) };
|
||||||
|
#pragma pack(pop)
|
||||||
|
const BOOL fSuccess = WriteFile(pPty->hSignal, &data, sizeof(data), nullptr, nullptr);
|
||||||
|
return fSuccess ? S_OK : HRESULT_FROM_WIN32(GetLastError());
|
||||||
|
}
|
||||||
|
|
||||||
// Function Description:
|
// Function Description:
|
||||||
// - This closes each of the members of a PseudoConsole. It does not free the
|
// - This closes each of the members of a PseudoConsole. It does not free the
|
||||||
// data associated with the PseudoConsole. This is helpful for testing,
|
// data associated with the PseudoConsole. This is helpful for testing,
|
||||||
@@ -465,6 +494,22 @@ extern "C" HRESULT WINAPI ConptyShowHidePseudoConsole(_In_ HPCON hPC, bool show)
|
|||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - Sends a message to the pseudoconsole informing it that it should use the
|
||||||
|
// given window handle as the owner for the conpty's pseudo window. This
|
||||||
|
// allows the response given to GetConsoleWindow() to be a HWND that's owned
|
||||||
|
// by the actual hosting terminal's HWND.
|
||||||
|
// - Used to support GH#2988
|
||||||
|
extern "C" HRESULT WINAPI ConptyReparentPseudoConsole(_In_ HPCON hPC, HWND newParent)
|
||||||
|
{
|
||||||
|
const PseudoConsole* const pPty = (PseudoConsole*)hPC;
|
||||||
|
HRESULT hr = pPty == nullptr ? E_INVALIDARG : S_OK;
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = _ReparentPseudoConsole(pPty, newParent);
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
// Function Description:
|
// Function Description:
|
||||||
// Closes the conpty and all associated state.
|
// Closes the conpty and all associated state.
|
||||||
// Client applications attached to the conpty will also behave as though the
|
// Client applications attached to the conpty will also behave as though the
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ typedef struct _PseudoConsole
|
|||||||
// the signal pipe.
|
// the signal pipe.
|
||||||
#define PTY_SIGNAL_SHOWHIDE_WINDOW (1u)
|
#define PTY_SIGNAL_SHOWHIDE_WINDOW (1u)
|
||||||
#define PTY_SIGNAL_CLEAR_WINDOW (2u)
|
#define PTY_SIGNAL_CLEAR_WINDOW (2u)
|
||||||
|
#define PTY_SIGNAL_REPARENT_WINDOW (3u)
|
||||||
#define PTY_SIGNAL_RESIZE_WINDOW (8u)
|
#define PTY_SIGNAL_RESIZE_WINDOW (8u)
|
||||||
|
|
||||||
// CreatePseudoConsole Flags
|
// CreatePseudoConsole Flags
|
||||||
@@ -38,6 +39,7 @@ HRESULT _CreatePseudoConsole(const HANDLE hToken,
|
|||||||
|
|
||||||
HRESULT _ResizePseudoConsole(_In_ const PseudoConsole* const pPty, _In_ const COORD size);
|
HRESULT _ResizePseudoConsole(_In_ const PseudoConsole* const pPty, _In_ const COORD size);
|
||||||
HRESULT _ClearPseudoConsole(_In_ const PseudoConsole* const pPty);
|
HRESULT _ClearPseudoConsole(_In_ const PseudoConsole* const pPty);
|
||||||
|
HRESULT _ReparentPseudoConsole(_In_ const PseudoConsole* const pPty, _In_ const HWND newParent);
|
||||||
void _ClosePseudoConsoleMembers(_In_ PseudoConsole* pPty);
|
void _ClosePseudoConsoleMembers(_In_ PseudoConsole* pPty);
|
||||||
VOID _ClosePseudoConsole(_In_ PseudoConsole* pPty);
|
VOID _ClosePseudoConsole(_In_ PseudoConsole* pPty);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user