Merge remote-tracking branch 'origin/main' into dev/migrie/f/653-QUAKE-MODE
12
.github/actions/spelling/dictionary/apis.txt
vendored
|
@ -6,15 +6,19 @@ bitfields
|
|||
CLASSNOTAVAILABLE
|
||||
cmdletbinding
|
||||
COLORPROPERTY
|
||||
COMDLG
|
||||
CXICON
|
||||
CYICON
|
||||
D2DERR_SHADER_COMPILE_FAILED
|
||||
dataobject
|
||||
DERR
|
||||
dlldata
|
||||
DONTADDTORECENT
|
||||
environstrings
|
||||
EXPCMDFLAGS
|
||||
EXPCMDSTATE
|
||||
FILTERSPEC
|
||||
FORCEFILESYSTEM
|
||||
FORCEMINIMIZE
|
||||
frac
|
||||
fullkbd
|
||||
|
@ -24,6 +28,7 @@ GETHIGHCONTRAST
|
|||
Hashtable
|
||||
HIGHCONTRASTON
|
||||
HIGHCONTRASTW
|
||||
hotkeys
|
||||
href
|
||||
IActivation
|
||||
IApp
|
||||
|
@ -32,12 +37,13 @@ IAsync
|
|||
IBind
|
||||
IBox
|
||||
IClass
|
||||
IConnection
|
||||
IComparable
|
||||
IConnection
|
||||
ICustom
|
||||
IDialog
|
||||
IDirect
|
||||
IExplorer
|
||||
IFile
|
||||
IInheritable
|
||||
IMap
|
||||
IObject
|
||||
|
@ -63,6 +69,7 @@ NCLBUTTONDBLCLK
|
|||
NCRBUTTONDBLCLK
|
||||
NOAGGREGATION
|
||||
NOASYNC
|
||||
NOCHANGEDIR
|
||||
NOPROGRESS
|
||||
NOREDIRECTIONBITMAP
|
||||
ntprivapi
|
||||
|
@ -72,10 +79,11 @@ otms
|
|||
OUTLINETEXTMETRICW
|
||||
overridable
|
||||
PAGESCROLL
|
||||
PICKFOLDERS
|
||||
pmr
|
||||
REGCLS
|
||||
RETURNCMD
|
||||
REGCLS
|
||||
RETURNCMD
|
||||
rfind
|
||||
roundf
|
||||
RSHIFT
|
||||
|
|
1
.github/actions/spelling/expect/expect.txt
vendored
|
@ -2397,6 +2397,7 @@ titlebar
|
|||
TITLEISLINKNAME
|
||||
TJson
|
||||
tl
|
||||
TLambda
|
||||
TLEN
|
||||
Tlg
|
||||
Tlgdata
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<XesUseOneStoreVersioning>true</XesUseOneStoreVersioning>
|
||||
<XesBaseYearForStoreVersion>2021</XesBaseYearForStoreVersion>
|
||||
<VersionMajor>1</VersionMajor>
|
||||
<VersionMinor>8</VersionMinor>
|
||||
<VersionMinor>9</VersionMinor>
|
||||
<VersionInfoProductName>Windows Terminal</VersionInfoProductName>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
Before Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 5.4 KiB |
Before Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 2 KiB |
Before Width: | Height: | Size: 6.6 KiB |
Before Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 9.8 KiB |
Before Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 9.8 KiB |
Before Width: | Height: | Size: 9.7 KiB |
Before Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 5.4 KiB |
Before Width: | Height: | Size: 2 KiB |
Before Width: | Height: | Size: 2 KiB |
Before Width: | Height: | Size: 6.5 KiB |
Before Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 9.5 KiB |
Before Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 9.3 KiB |
Before Width: | Height: | Size: 9.3 KiB |
Before Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 6.6 KiB |
Before Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 8.3 KiB |
Before Width: | Height: | Size: 8.2 KiB |
|
@ -281,9 +281,9 @@ bool TextBuffer::_AssertValidDoubleByteSequence(const DbcsAttribute dbcsAttribut
|
|||
// - false otherwise (out of memory)
|
||||
bool TextBuffer::_PrepareForDoubleByteSequence(const DbcsAttribute dbcsAttribute)
|
||||
{
|
||||
// Assert the buffer state is ready for this character
|
||||
// This function corrects most errors. If this is false, we had an uncorrectable one.
|
||||
FAIL_FAST_IF(!(_AssertValidDoubleByteSequence(dbcsAttribute))); // Shouldn't be uncorrectable sequences unless something is very wrong.
|
||||
// This function corrects most errors. If this is false, we had an uncorrectable one which
|
||||
// older versions of conhost simply let pass by unflinching.
|
||||
LOG_HR_IF(E_NOT_VALID_STATE, !(_AssertValidDoubleByteSequence(dbcsAttribute))); // Shouldn't be uncorrectable sequences unless something is very wrong.
|
||||
|
||||
bool fSuccess = true;
|
||||
// Now compensate if we don't have enough space for the upcoming double byte sequence
|
||||
|
|
|
@ -54,7 +54,6 @@
|
|||
<uap:ShowOn Tile="square310x310Logo"/>
|
||||
</uap:ShowNameOnTiles>
|
||||
</uap:DefaultTile>
|
||||
<uap:SplashScreen Image="Images\SplashScreen.png"/>
|
||||
</uap:VisualElements>
|
||||
|
||||
<Extensions>
|
||||
|
|
|
@ -55,7 +55,6 @@
|
|||
<uap:ShowOn Tile="square310x310Logo"/>
|
||||
</uap:ShowNameOnTiles>
|
||||
</uap:DefaultTile>
|
||||
<uap:SplashScreen Image="Images\SplashScreen.png"/>
|
||||
</uap:VisualElements>
|
||||
|
||||
<Extensions>
|
||||
|
|
|
@ -55,7 +55,6 @@
|
|||
<uap:ShowOn Tile="square310x310Logo"/>
|
||||
</uap:ShowNameOnTiles>
|
||||
</uap:DefaultTile>
|
||||
<uap:SplashScreen Image="Images\SplashScreen.png"/>
|
||||
</uap:VisualElements>
|
||||
|
||||
<Extensions>
|
||||
|
|
|
@ -954,6 +954,10 @@ namespace TerminalAppLocalTests
|
|||
|
||||
void TabTests::TestWindowRenameSuccessful()
|
||||
{
|
||||
BEGIN_TEST_METHOD_PROPERTIES()
|
||||
TEST_METHOD_PROPERTY(L"IsolationLevel", L"Method")
|
||||
END_TEST_METHOD_PROPERTIES()
|
||||
|
||||
auto page = _commonSetup();
|
||||
page->RenameWindowRequested([&page](auto&&, const winrt::TerminalApp::RenameWindowRequestedArgs args) {
|
||||
// In the real terminal, this would bounce up to the monarch and
|
||||
|
@ -980,6 +984,10 @@ namespace TerminalAppLocalTests
|
|||
}
|
||||
void TabTests::TestWindowRenameFailure()
|
||||
{
|
||||
BEGIN_TEST_METHOD_PROPERTIES()
|
||||
TEST_METHOD_PROPERTY(L"IsolationLevel", L"Method")
|
||||
END_TEST_METHOD_PROPERTIES()
|
||||
|
||||
auto page = _commonSetup();
|
||||
page->RenameWindowRequested([&page](auto&&, auto&&) {
|
||||
// In the real terminal, this would bounce up to the monarch and
|
||||
|
|
|
@ -252,8 +252,8 @@ namespace winrt::TerminalApp::implementation
|
|||
{
|
||||
if (const auto& realArgs = args.ActionArgs().try_as<SwitchToTabArgs>())
|
||||
{
|
||||
const auto handled = _SelectTab({ realArgs.TabIndex() });
|
||||
args.Handled(handled);
|
||||
_SelectTab({ realArgs.TabIndex() });
|
||||
args.Handled(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -719,9 +719,9 @@ namespace winrt::TerminalApp::implementation
|
|||
const auto newName = realArgs.Name();
|
||||
const auto request = winrt::make_self<implementation::RenameWindowRequestedArgs>(newName);
|
||||
_RenameWindowRequestedHandlers(*this, *request);
|
||||
args.Handled(true);
|
||||
}
|
||||
}
|
||||
args.Handled(false);
|
||||
}
|
||||
|
||||
void TerminalPage::_HandleOpenWindowRenamer(const IInspectable& /*sender*/,
|
||||
|
|
|
@ -43,6 +43,9 @@
|
|||
Color="#f1707a" />
|
||||
<SolidColorBrush x:Key="CloseButtonStrokePressed"
|
||||
Color="Black" />
|
||||
<SolidColorBrush x:Key="CloseButtonBackground"
|
||||
Color="#00e81123" />
|
||||
<Color x:Key="CloseButtonBackgroundColor">#00e81123</Color>
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="Dark">
|
||||
<x:Double x:Key="CaptionButtonStrokeWidth">1.0</x:Double>
|
||||
|
@ -69,6 +72,9 @@
|
|||
Color="#f1707a" />
|
||||
<SolidColorBrush x:Key="CloseButtonStrokePressed"
|
||||
Color="Black" />
|
||||
<SolidColorBrush x:Key="CloseButtonBackground"
|
||||
Color="#00e81123" />
|
||||
<Color x:Key="CloseButtonBackgroundColor">#00e81123</Color>
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="HighContrast">
|
||||
<x:Double x:Key="CaptionButtonStrokeWidth">3.0</x:Double>
|
||||
|
@ -268,6 +274,10 @@
|
|||
ResourceKey="CloseButtonStrokePointerOver" />
|
||||
<StaticResource x:Key="CaptionButtonStrokePressed"
|
||||
ResourceKey="CloseButtonStrokePressed" />
|
||||
<StaticResource x:Key="CaptionButtonBackground"
|
||||
ResourceKey="CloseButtonBackground" />
|
||||
<StaticResource x:Key="CaptionButtonBackgroundColor"
|
||||
ResourceKey="CloseButtonBackgroundColor" />
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="Dark">
|
||||
<StaticResource x:Key="CaptionButtonBackgroundPointerOver"
|
||||
|
@ -278,6 +288,10 @@
|
|||
ResourceKey="CloseButtonStrokePointerOver" />
|
||||
<StaticResource x:Key="CaptionButtonStrokePressed"
|
||||
ResourceKey="CloseButtonStrokePressed" />
|
||||
<StaticResource x:Key="CaptionButtonBackground"
|
||||
ResourceKey="CloseButtonBackground" />
|
||||
<StaticResource x:Key="CaptionButtonBackgroundColor"
|
||||
ResourceKey="CloseButtonBackgroundColor" />
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="HighContrast">
|
||||
<StaticResource x:Key="CaptionButtonBackgroundPointerOver"
|
||||
|
|
|
@ -2708,8 +2708,12 @@ namespace winrt::TerminalApp::implementation
|
|||
void TerminalPage::_RequestWindowRename(const winrt::hstring& newName)
|
||||
{
|
||||
auto request = winrt::make<implementation::RenameWindowRequestedArgs>(newName);
|
||||
// The WindowRenamer is _not_ a Toast - we want it to stay open until the user dismisses it.
|
||||
WindowRenamer().IsOpen(false);
|
||||
// The WindowRenamer is _not_ a Toast - we want it to stay open until
|
||||
// the user dismisses it.
|
||||
if (WindowRenamer())
|
||||
{
|
||||
WindowRenamer().IsOpen(false);
|
||||
}
|
||||
_RenameWindowRequestedHandlers(*this, request);
|
||||
// We can't just use request.Successful here, because the handler might
|
||||
// (will) be handling this asynchronously, so when control returns to
|
||||
|
|
|
@ -666,6 +666,11 @@ namespace winrt::TerminalApp::implementation
|
|||
|
||||
_RecalculateAndApplyReadOnly();
|
||||
|
||||
if (const auto control{ pane->GetTerminalControl() })
|
||||
{
|
||||
control.TaskbarProgressChanged();
|
||||
}
|
||||
|
||||
// Raise our own ActivePaneChanged event.
|
||||
_ActivePaneChangedHandlers();
|
||||
}
|
||||
|
|
|
@ -132,6 +132,8 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||
|
||||
THROW_LAST_ERROR_IF_NULL(_hOutputThread);
|
||||
|
||||
LOG_IF_FAILED(SetThreadDescription(_hOutputThread.get(), L"AzureConnection Output Thread"));
|
||||
|
||||
_transitionToState(ConnectionState::Connecting);
|
||||
}
|
||||
|
||||
|
|
|
@ -278,6 +278,8 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||
|
||||
THROW_LAST_ERROR_IF_NULL(_hOutputThread);
|
||||
|
||||
LOG_IF_FAILED(SetThreadDescription(_hOutputThread.get(), L"ConptyConnection Output Thread"));
|
||||
|
||||
_clientExitWait.reset(CreateThreadpoolWait(
|
||||
[](PTP_CALLBACK_INSTANCE /*callbackInstance*/, PVOID context, PTP_WAIT /*wait*/, TP_WAIT_RESULT /*waitResult*/) noexcept {
|
||||
ConptyConnection* const pInstance = static_cast<ConptyConnection*>(context);
|
||||
|
|
|
@ -39,6 +39,9 @@ constexpr const auto TsfRedrawInterval = std::chrono::milliseconds(100);
|
|||
// The minimum delay between updating the locations of regex patterns
|
||||
constexpr const auto UpdatePatternLocationsInterval = std::chrono::milliseconds(500);
|
||||
|
||||
// The minimum delay between emitting warning bells
|
||||
constexpr const auto TerminalWarningBellInterval = std::chrono::milliseconds(1000);
|
||||
|
||||
DEFINE_ENUM_FLAG_OPERATORS(winrt::Microsoft::Terminal::Control::CopyFormat);
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
|
@ -91,7 +94,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
// GH#8969: pre-seed working directory to prevent potential races
|
||||
_terminal->SetWorkingDirectory(_settings.StartingDirectory());
|
||||
|
||||
auto pfnWarningBell = std::bind(&TermControl::_TerminalWarningBell, this);
|
||||
auto pfnWarningBell = [this]() {
|
||||
_playWarningBell->Run();
|
||||
};
|
||||
_terminal->SetWarningBellCallback(pfnWarningBell);
|
||||
|
||||
auto pfnTitleChanged = std::bind(&TermControl::_TerminalTitleChanged, this, std::placeholders::_1);
|
||||
|
@ -167,6 +172,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
UpdatePatternLocationsInterval,
|
||||
Dispatcher());
|
||||
|
||||
_playWarningBell = std::make_shared<ThrottledFunc<>>(
|
||||
[weakThis = get_weak()]() {
|
||||
if (auto control{ weakThis.get() })
|
||||
{
|
||||
control->_TerminalWarningBell();
|
||||
}
|
||||
},
|
||||
TerminalWarningBellInterval,
|
||||
Dispatcher());
|
||||
|
||||
_updateScrollBar = std::make_shared<ThrottledFunc<ScrollBarUpdate>>(
|
||||
[weakThis = get_weak()](const auto& update) {
|
||||
if (auto control{ weakThis.get() })
|
||||
|
@ -306,13 +321,17 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
// terminal.
|
||||
co_await winrt::resume_foreground(Dispatcher());
|
||||
|
||||
_UpdateSettingsFromUIThread(_settings);
|
||||
// Take the lock before calling the helper functions to update the settings and appearance
|
||||
auto lock = _terminal->LockForWriting();
|
||||
|
||||
_UpdateSettingsFromUIThreadUnderLock(_settings);
|
||||
|
||||
auto appearance = _settings.try_as<IControlAppearance>();
|
||||
if (!_focused && _UnfocusedAppearance)
|
||||
{
|
||||
appearance = _UnfocusedAppearance;
|
||||
}
|
||||
_UpdateAppearanceFromUIThread(appearance);
|
||||
_UpdateAppearanceFromUIThreadUnderLock(appearance);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -323,7 +342,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
{
|
||||
// Dispatch a call to the UI thread
|
||||
co_await winrt::resume_foreground(Dispatcher());
|
||||
_UpdateAppearanceFromUIThread(newAppearance);
|
||||
|
||||
// Take the lock before calling the helper function to update the appearance
|
||||
auto lock = _terminal->LockForWriting();
|
||||
_UpdateAppearanceFromUIThreadUnderLock(newAppearance);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -366,17 +388,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
// issue that causes one of our hstring -> wstring_view conversions to result in garbage,
|
||||
// but only from a coroutine context. See GH#8723.
|
||||
// - INVARIANT: This method must be called from the UI thread.
|
||||
// - INVARIANT: This method can only be called if the caller has the writing lock on the terminal.
|
||||
// Arguments:
|
||||
// - newSettings: the new settings to set
|
||||
void TermControl::_UpdateSettingsFromUIThread(IControlSettings newSettings)
|
||||
void TermControl::_UpdateSettingsFromUIThreadUnderLock(IControlSettings newSettings)
|
||||
{
|
||||
if (_closing)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = _terminal->LockForWriting();
|
||||
|
||||
// Update our control settings
|
||||
_ApplyUISettings(_settings);
|
||||
|
||||
|
@ -420,10 +441,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
|
||||
// Method Description:
|
||||
// - Updates the appearance
|
||||
// - This should only be called from the UI thread
|
||||
// - INVARIANT: This method must be called from the UI thread.
|
||||
// - INVARIANT: This method can only be called if the caller has the writing lock on the terminal.
|
||||
// Arguments:
|
||||
// - newAppearance: the new appearance to set
|
||||
void TermControl::_UpdateAppearanceFromUIThread(IControlAppearance newAppearance)
|
||||
void TermControl::_UpdateAppearanceFromUIThreadUnderLock(IControlAppearance newAppearance)
|
||||
{
|
||||
if (_closing)
|
||||
{
|
||||
|
@ -472,14 +494,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
TSFInputControl().Foreground(foregroundBrush);
|
||||
|
||||
// Update the terminal core with its new Core settings
|
||||
auto lock = _terminal->LockForWriting();
|
||||
_terminal->UpdateAppearance(newAppearance);
|
||||
|
||||
// Update DxEngine settings under the lock
|
||||
_renderEngine->SetSelectionBackground(til::color{ newAppearance.SelectionBackground() });
|
||||
_renderEngine->SetRetroTerminalEffect(newAppearance.RetroTerminalEffect());
|
||||
_renderEngine->SetPixelShaderPath(newAppearance.PixelShaderPath());
|
||||
_renderer->TriggerRedrawAll();
|
||||
if (_renderEngine)
|
||||
{
|
||||
// Update DxEngine settings under the lock
|
||||
_renderEngine->SetSelectionBackground(til::color{ newAppearance.SelectionBackground() });
|
||||
_renderEngine->SetRetroTerminalEffect(newAppearance.RetroTerminalEffect());
|
||||
_renderEngine->SetPixelShaderPath(newAppearance.PixelShaderPath());
|
||||
_renderer->TriggerRedrawAll();
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -800,9 +824,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
const auto viewInPixels = Viewport::FromDimensions({ 0, 0 }, windowSize);
|
||||
LOG_IF_FAILED(dxEngine->SetWindowSize({ viewInPixels.Width(), viewInPixels.Height() }));
|
||||
|
||||
// Update DxEngine's SelectionBackground
|
||||
dxEngine->SetSelectionBackground(til::color{ _settings.SelectionBackground() });
|
||||
|
||||
const auto vp = dxEngine->GetViewportInCharacters(viewInPixels);
|
||||
const auto width = vp.Width();
|
||||
const auto height = vp.Height();
|
||||
|
@ -820,8 +841,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
// the first paint will be ignored!
|
||||
dxEngine->SetWarningCallback(std::bind(&TermControl::_RendererWarning, this, std::placeholders::_1));
|
||||
|
||||
dxEngine->SetRetroTerminalEffect(_settings.RetroTerminalEffect());
|
||||
dxEngine->SetPixelShaderPath(_settings.PixelShaderPath());
|
||||
dxEngine->SetForceFullRepaintRendering(_settings.ForceFullRepaintRendering());
|
||||
dxEngine->SetSoftwareRendering(_settings.SoftwareRendering());
|
||||
|
||||
|
@ -910,6 +929,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
// becomes a no-op.
|
||||
this->Focus(FocusState::Programmatic);
|
||||
|
||||
// Now that the renderer is set up, update the appearance for initialization
|
||||
_UpdateAppearanceFromUIThreadUnderLock(_settings);
|
||||
|
||||
_initializedTerminal = true;
|
||||
} // scope for TerminalLock
|
||||
|
||||
|
@ -1418,6 +1440,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
_selectionNeedsToBeCopied = true;
|
||||
}
|
||||
|
||||
if (_terminal->IsSelectionActive())
|
||||
{
|
||||
// GH#9787: if selection is active we don't want to track the touchdown position
|
||||
// so that dragging the mouse will extend the selection rather than starting the new one
|
||||
_singleClickTouchdownPos = std::nullopt;
|
||||
}
|
||||
|
||||
_renderer->TriggerSelection();
|
||||
}
|
||||
else if (point.Properties().IsRightButtonPressed())
|
||||
|
|
|
@ -145,6 +145,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
|
||||
std::shared_ptr<ThrottledFunc<>> _updatePatternLocations;
|
||||
|
||||
std::shared_ptr<ThrottledFunc<>> _playWarningBell;
|
||||
|
||||
struct ScrollBarUpdate
|
||||
{
|
||||
std::optional<double> newValue;
|
||||
|
@ -198,8 +200,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
|
||||
winrt::Windows::UI::Xaml::Controls::SwapChainPanel::LayoutUpdated_revoker _layoutUpdatedRevoker;
|
||||
|
||||
void _UpdateSettingsFromUIThread(IControlSettings newSettings);
|
||||
void _UpdateAppearanceFromUIThread(IControlAppearance newAppearance);
|
||||
void _UpdateSettingsFromUIThreadUnderLock(IControlSettings newSettings);
|
||||
void _UpdateAppearanceFromUIThreadUnderLock(IControlAppearance newAppearance);
|
||||
bool _isReadOnly{ false };
|
||||
|
||||
void _ApplyUISettings(const IControlSettings&);
|
||||
|
|
|
@ -49,8 +49,6 @@
|
|||
<Grid HorizontalAlignment="Stretch"
|
||||
ColumnSpacing="8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="16" />
|
||||
<!-- icon -->
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<!-- command label -->
|
||||
<ColumnDefinition Width="*" />
|
||||
|
@ -59,7 +57,7 @@
|
|||
<!-- gutter for scrollbar -->
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock Grid.Column="1"
|
||||
<TextBlock Grid.Column="0"
|
||||
HorizontalAlignment="Left"
|
||||
Text="{x:Bind Name, Mode=OneWay}" />
|
||||
|
||||
|
@ -71,7 +69,7 @@
|
|||
AutomationProperties to Raw here, unlike in the
|
||||
CommandPalette. We're not quite sure why.
|
||||
-->
|
||||
<Border Grid.Column="2"
|
||||
<Border Grid.Column="1"
|
||||
Padding="2,0,2,0"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
|
|
|
@ -182,6 +182,11 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||
return false;
|
||||
}
|
||||
|
||||
uint64_t MainPage::GetHostingWindow() const noexcept
|
||||
{
|
||||
return reinterpret_cast<uint64_t>(_hostingHwnd.value_or(nullptr));
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - Called when the NavigationView is loaded. Navigates to the first item in the NavigationView, if no item is selected
|
||||
// Arguments:
|
||||
|
|
|
@ -24,6 +24,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||
|
||||
void SetHostingWindow(uint64_t hostingWindow) noexcept;
|
||||
bool TryPropagateHostingWindow(IInspectable object) noexcept;
|
||||
uint64_t GetHostingWindow() const noexcept;
|
||||
|
||||
TYPED_EVENT(OpenJson, Windows::Foundation::IInspectable, Model::SettingsTarget);
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ namespace Microsoft.Terminal.Settings.Editor
|
|||
interface IHostedInWindow
|
||||
{
|
||||
Boolean TryPropagateHostingWindow(IInspectable i);
|
||||
UInt64 GetHostingWindow();
|
||||
}
|
||||
|
||||
[default_interface] runtimeclass MainPage : Windows.UI.Xaml.Controls.Page, IHostedInWindow
|
||||
|
|
|
@ -300,6 +300,12 @@
|
|||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemDefinitionGroup>
|
||||
<Link>
|
||||
<AdditionalDependencies>shell32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
|
||||
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
|
|
|
@ -15,9 +15,6 @@ using namespace winrt::Windows::UI::Xaml::Data;
|
|||
using namespace winrt::Windows::UI::Xaml::Navigation;
|
||||
using namespace winrt::Windows::Foundation;
|
||||
using namespace winrt::Windows::Foundation::Collections;
|
||||
using namespace winrt::Windows::Storage;
|
||||
using namespace winrt::Windows::Storage::AccessCache;
|
||||
using namespace winrt::Windows::Storage::Pickers;
|
||||
using namespace winrt::Microsoft::Terminal::Settings::Model;
|
||||
|
||||
static const std::array<winrt::guid, 2> InBoxProfileGuids{
|
||||
|
@ -25,6 +22,64 @@ static const std::array<winrt::guid, 2> InBoxProfileGuids{
|
|||
winrt::guid{ 0x0caa0dad, 0x35be, 0x5f56, { 0xa8, 0xff, 0xaf, 0xce, 0xee, 0xaa, 0x61, 0x01 } } // Command Prompt
|
||||
};
|
||||
|
||||
// Function Description:
|
||||
// - This function presents a File Open "common dialog" and returns its selected file asynchronously.
|
||||
// Parameters:
|
||||
// - customize: A lambda that receives an IFileDialog* to customize.
|
||||
// Return value:
|
||||
// (async) path to the selected item.
|
||||
template<typename TLambda>
|
||||
static winrt::Windows::Foundation::IAsyncOperation<winrt::hstring> OpenFilePicker(HWND parentHwnd, TLambda&& customize)
|
||||
{
|
||||
auto fileDialog{ winrt::create_instance<IFileDialog>(CLSID_FileOpenDialog) };
|
||||
DWORD flags{};
|
||||
THROW_IF_FAILED(fileDialog->GetOptions(&flags));
|
||||
THROW_IF_FAILED(fileDialog->SetOptions(flags | FOS_FORCEFILESYSTEM | FOS_NOCHANGEDIR | FOS_DONTADDTORECENT)); // filesystem objects only; no recent places
|
||||
customize(fileDialog.get());
|
||||
|
||||
auto hr{ fileDialog->Show(parentHwnd) };
|
||||
if (!SUCCEEDED(hr))
|
||||
{
|
||||
if (hr == HRESULT_FROM_WIN32(ERROR_CANCELLED))
|
||||
{
|
||||
co_return winrt::hstring{};
|
||||
}
|
||||
THROW_HR(hr);
|
||||
}
|
||||
|
||||
winrt::com_ptr<IShellItem> result;
|
||||
THROW_IF_FAILED(fileDialog->GetResult(result.put()));
|
||||
|
||||
wil::unique_cotaskmem_string filePath;
|
||||
THROW_IF_FAILED(result->GetDisplayName(SIGDN_FILESYSPATH, &filePath));
|
||||
|
||||
co_return winrt::hstring{ filePath.get() };
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - Helper that opens a file picker pre-seeded with image file types.
|
||||
static winrt::Windows::Foundation::IAsyncOperation<winrt::hstring> OpenImagePicker(HWND parentHwnd)
|
||||
{
|
||||
static constexpr COMDLG_FILTERSPEC supportedImageFileTypes[] = {
|
||||
{ L"All Supported Bitmap Types (*.jpg, *.jpeg, *.png, *.bmp, *.gif, *.tiff, *.ico)", L"*.jpg;*.jpeg;*.png;*.bmp;*.gif;*.tiff;*.ico" },
|
||||
{ L"All Files (*.*)", L"*.*" }
|
||||
};
|
||||
|
||||
static constexpr winrt::guid clientGuidImagePicker{ 0x55675F54, 0x74A1, 0x4552, { 0xA3, 0x9D, 0x94, 0xAE, 0x85, 0xD8, 0xF2, 0x7A } };
|
||||
return OpenFilePicker(parentHwnd, [](auto&& dialog) {
|
||||
THROW_IF_FAILED(dialog->SetClientGuid(clientGuidImagePicker));
|
||||
try
|
||||
{
|
||||
auto pictureFolderShellItem{ winrt::capture<IShellItem>(&SHGetKnownFolderItem, FOLDERID_PicturesLibrary, KF_FLAG_DEFAULT, nullptr) };
|
||||
dialog->SetDefaultFolder(pictureFolderShellItem.get());
|
||||
}
|
||||
CATCH_LOG(); // non-fatal
|
||||
THROW_IF_FAILED(dialog->SetFileTypes(ARRAYSIZE(supportedImageFileTypes), supportedImageFileTypes));
|
||||
THROW_IF_FAILED(dialog->SetFileTypeIndex(1)); // the array is 1-indexed
|
||||
THROW_IF_FAILED(dialog->SetDefaultExtension(L"jpg;jpeg;png;bmp;gif;tiff;ico"));
|
||||
});
|
||||
}
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
Windows::Foundation::Collections::IObservableVector<Editor::Font> ProfileViewModel::_MonospaceFontList{ nullptr };
|
||||
|
@ -582,20 +637,11 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||
{
|
||||
auto lifetime = get_strong();
|
||||
|
||||
FileOpenPicker picker;
|
||||
|
||||
_State.WindowRoot().TryPropagateHostingWindow(picker); // if we don't do this, there's no HWND for it to attach to
|
||||
picker.ViewMode(PickerViewMode::Thumbnail);
|
||||
picker.SuggestedStartLocation(PickerLocationId::PicturesLibrary);
|
||||
|
||||
// Converted into a BitmapImage. This list of supported image file formats is from BitmapImage documentation
|
||||
// https://docs.microsoft.com/en-us/uwp/api/Windows.UI.Xaml.Media.Imaging.BitmapImage?view=winrt-19041#remarks
|
||||
picker.FileTypeFilter().ReplaceAll({ L".jpg", L".jpeg", L".png", L".bmp", L".gif", L".tiff", L".ico" });
|
||||
|
||||
StorageFile file = co_await picker.PickSingleFileAsync();
|
||||
if (file != nullptr)
|
||||
const auto parentHwnd{ reinterpret_cast<HWND>(_State.WindowRoot().GetHostingWindow()) };
|
||||
auto file = co_await OpenImagePicker(parentHwnd);
|
||||
if (!file.empty())
|
||||
{
|
||||
_State.Profile().BackgroundImagePath(file.Path());
|
||||
_State.Profile().BackgroundImagePath(file);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -603,20 +649,11 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||
{
|
||||
auto lifetime = get_strong();
|
||||
|
||||
FileOpenPicker picker;
|
||||
|
||||
_State.WindowRoot().TryPropagateHostingWindow(picker); // if we don't do this, there's no HWND for it to attach to
|
||||
picker.ViewMode(PickerViewMode::Thumbnail);
|
||||
picker.SuggestedStartLocation(PickerLocationId::PicturesLibrary);
|
||||
|
||||
// Converted into a BitmapIconSource. This list of supported image file formats is from BitmapImage documentation
|
||||
// https://docs.microsoft.com/en-us/uwp/api/Windows.UI.Xaml.Media.Imaging.BitmapImage?view=winrt-19041#remarks
|
||||
picker.FileTypeFilter().ReplaceAll({ L".jpg", L".jpeg", L".png", L".bmp", L".gif", L".tiff", L".ico" });
|
||||
|
||||
StorageFile file = co_await picker.PickSingleFileAsync();
|
||||
if (file != nullptr)
|
||||
const auto parentHwnd{ reinterpret_cast<HWND>(_State.WindowRoot().GetHostingWindow()) };
|
||||
auto file = co_await OpenImagePicker(parentHwnd);
|
||||
if (!file.empty())
|
||||
{
|
||||
_State.Profile().Icon(file.Path());
|
||||
_State.Profile().Icon(file);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -624,32 +661,54 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||
{
|
||||
auto lifetime = get_strong();
|
||||
|
||||
FileOpenPicker picker;
|
||||
static constexpr COMDLG_FILTERSPEC supportedFileTypes[] = {
|
||||
{ L"Executable Files (*.exe, *.cmd, *.bat)", L"*.exe;*.cmd;*.bat" },
|
||||
{ L"All Files (*.*)", L"*.*" }
|
||||
};
|
||||
|
||||
_State.WindowRoot().TryPropagateHostingWindow(picker); // if we don't do this, there's no HWND for it to attach to
|
||||
picker.ViewMode(PickerViewMode::Thumbnail);
|
||||
picker.SuggestedStartLocation(PickerLocationId::ComputerFolder);
|
||||
picker.FileTypeFilter().ReplaceAll({ L".bat", L".exe", L".cmd" });
|
||||
static constexpr winrt::guid clientGuidExecutables{ 0x2E7E4331, 0x0800, 0x48E6, { 0xB0, 0x17, 0xA1, 0x4C, 0xD8, 0x73, 0xDD, 0x58 } };
|
||||
const auto parentHwnd{ reinterpret_cast<HWND>(_State.WindowRoot().GetHostingWindow()) };
|
||||
auto path = co_await OpenFilePicker(parentHwnd, [](auto&& dialog) {
|
||||
THROW_IF_FAILED(dialog->SetClientGuid(clientGuidExecutables));
|
||||
try
|
||||
{
|
||||
auto folderShellItem{ winrt::capture<IShellItem>(&SHGetKnownFolderItem, FOLDERID_ComputerFolder, KF_FLAG_DEFAULT, nullptr) };
|
||||
dialog->SetDefaultFolder(folderShellItem.get());
|
||||
}
|
||||
CATCH_LOG(); // non-fatal
|
||||
THROW_IF_FAILED(dialog->SetFileTypes(ARRAYSIZE(supportedFileTypes), supportedFileTypes));
|
||||
THROW_IF_FAILED(dialog->SetFileTypeIndex(1)); // the array is 1-indexed
|
||||
THROW_IF_FAILED(dialog->SetDefaultExtension(L"exe;cmd;bat"));
|
||||
});
|
||||
|
||||
StorageFile file = co_await picker.PickSingleFileAsync();
|
||||
if (file != nullptr)
|
||||
if (!path.empty())
|
||||
{
|
||||
_State.Profile().Commandline(file.Path());
|
||||
_State.Profile().Commandline(path);
|
||||
}
|
||||
}
|
||||
|
||||
fire_and_forget Profiles::StartingDirectory_Click(IInspectable const&, RoutedEventArgs const&)
|
||||
{
|
||||
auto lifetime = get_strong();
|
||||
FolderPicker picker;
|
||||
_State.WindowRoot().TryPropagateHostingWindow(picker); // if we don't do this, there's no HWND for it to attach to
|
||||
picker.SuggestedStartLocation(PickerLocationId::DocumentsLibrary);
|
||||
picker.FileTypeFilter().ReplaceAll({ L"*" });
|
||||
StorageFolder folder = co_await picker.PickSingleFolderAsync();
|
||||
if (folder != nullptr)
|
||||
const auto parentHwnd{ reinterpret_cast<HWND>(_State.WindowRoot().GetHostingWindow()) };
|
||||
auto folder = co_await OpenFilePicker(parentHwnd, [](auto&& dialog) {
|
||||
static constexpr winrt::guid clientGuidFolderPicker{ 0xAADAA433, 0xB04D, 0x4BAE, { 0xB1, 0xEA, 0x1E, 0x6C, 0xD1, 0xCD, 0xA6, 0x8B } };
|
||||
THROW_IF_FAILED(dialog->SetClientGuid(clientGuidFolderPicker));
|
||||
try
|
||||
{
|
||||
auto folderShellItem{ winrt::capture<IShellItem>(&SHGetKnownFolderItem, FOLDERID_ComputerFolder, KF_FLAG_DEFAULT, nullptr) };
|
||||
dialog->SetDefaultFolder(folderShellItem.get());
|
||||
}
|
||||
CATCH_LOG(); // non-fatal
|
||||
|
||||
DWORD flags{};
|
||||
THROW_IF_FAILED(dialog->GetOptions(&flags));
|
||||
THROW_IF_FAILED(dialog->SetOptions(flags | FOS_PICKFOLDERS)); // folders only
|
||||
});
|
||||
|
||||
if (!folder.empty())
|
||||
{
|
||||
StorageApplicationPermissions::FutureAccessList().AddOrReplace(L"PickedFolderToken", folder);
|
||||
_State.Profile().StartingDirectory(folder.Path());
|
||||
_State.Profile().StartingDirectory(folder);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
#include <winrt/Windows.Foundation.Collections.h>
|
||||
#include <winrt/Windows.Storage.h>
|
||||
#include <winrt/Windows.Storage.AccessCache.h>
|
||||
#include <winrt/Windows.Storage.Pickers.h>
|
||||
|
||||
#include <winrt/Windows.UI.h>
|
||||
#include <winrt/Windows.UI.Core.h>
|
||||
|
@ -54,7 +53,8 @@
|
|||
#include <winrt/Microsoft.Terminal.Control.h>
|
||||
#include <winrt/Microsoft.Terminal.Settings.Model.h>
|
||||
|
||||
#include "shobjidl_core.h"
|
||||
#include <shlobj.h>
|
||||
#include <shobjidl_core.h>
|
||||
#include <dwrite.h>
|
||||
#include <dwrite_1.h>
|
||||
|
||||
|
|
|
@ -221,13 +221,26 @@ winrt::Microsoft::Terminal::Settings::Model::Profile CascadiaSettings::ProfileDe
|
|||
// - a reference to the new profile
|
||||
winrt::Microsoft::Terminal::Settings::Model::Profile CascadiaSettings::CreateNewProfile()
|
||||
{
|
||||
if (_allProfiles.Size() == std::numeric_limits<uint32_t>::max())
|
||||
{
|
||||
// Shouldn't really happen
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
winrt::hstring newName{};
|
||||
for (uint32_t candidateIndex = 0; candidateIndex < _allProfiles.Size() + 1; candidateIndex++)
|
||||
{
|
||||
// There is a theoretical unsigned integer wraparound, which is OK
|
||||
newName = fmt::format(L"Profile {}", _allProfiles.Size() + 1 + candidateIndex);
|
||||
if (std::none_of(begin(_allProfiles), end(_allProfiles), [&](auto&& profile) { return profile.Name() == newName; }))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
auto newProfile{ _userDefaultProfileSettings->CreateChild() };
|
||||
_allProfiles.Append(*newProfile);
|
||||
|
||||
// Give the new profile a distinct name so a guid is properly generated
|
||||
const winrt::hstring newName{ fmt::format(L"Profile {}", _allProfiles.Size()) };
|
||||
newProfile->Name(newName);
|
||||
|
||||
_allProfiles.Append(*newProfile);
|
||||
return *newProfile;
|
||||
}
|
||||
|
||||
|
|
|
@ -381,6 +381,9 @@ void Profile::_FinalizeInheritance()
|
|||
{
|
||||
if (auto defaultAppearanceImpl = get_self<AppearanceConfig>(_DefaultAppearance))
|
||||
{
|
||||
// Clear any existing parents first, we don't want duplicates from any previous
|
||||
// calls to this function
|
||||
defaultAppearanceImpl->ClearParents();
|
||||
for (auto& parent : _parents)
|
||||
{
|
||||
if (auto parentDefaultAppearanceImpl = parent->_DefaultAppearance.try_as<AppearanceConfig>())
|
||||
|
|
|
@ -362,6 +362,8 @@
|
|||
// Visual Adjustments
|
||||
{ "command": { "action": "adjustFontSize", "delta": 1 }, "keys": "ctrl+=" },
|
||||
{ "command": { "action": "adjustFontSize", "delta": -1 }, "keys": "ctrl+-" },
|
||||
{ "command": { "action": "adjustFontSize", "delta": 1 }, "keys": "ctrl+numpad_plus" },
|
||||
{ "command": { "action": "adjustFontSize", "delta": -1 }, "keys": "ctrl+numpad_minus" },
|
||||
{ "command": "resetFontSize", "keys": "ctrl+0" },
|
||||
|
||||
// Other commands
|
||||
|
|
|
@ -765,6 +765,91 @@ void IslandWindow::_SetIsBorderless(const bool borderlessEnabled)
|
|||
SWP_SHOWWINDOW | SWP_FRAMECHANGED | SWP_NOACTIVATE);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Called when entering fullscreen, with the window's current monitor rect and work area.
|
||||
// - The current window position, dpi, work area, and maximized state are stored, and the
|
||||
// window is positioned to the monitor rect.
|
||||
void IslandWindow::_SetFullscreenPosition(const RECT rcMonitor, const RECT rcWork)
|
||||
{
|
||||
HWND const hWnd = GetHandle();
|
||||
|
||||
::GetWindowRect(hWnd, &_rcWindowBeforeFullscreen);
|
||||
_dpiBeforeFullscreen = GetDpiForWindow(hWnd);
|
||||
_fWasMaximizedBeforeFullscreen = IsZoomed(hWnd);
|
||||
_rcWorkBeforeFullscreen = rcWork;
|
||||
|
||||
SetWindowPos(hWnd,
|
||||
HWND_TOP,
|
||||
rcMonitor.left,
|
||||
rcMonitor.top,
|
||||
rcMonitor.right - rcMonitor.left,
|
||||
rcMonitor.bottom - rcMonitor.top,
|
||||
SWP_FRAMECHANGED);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Called when exiting fullscreen, with the window's current monitor work area.
|
||||
// - The window is restored to its previous position, migrating that previous position to the
|
||||
// window's current monitor (if the current work area or window DPI have changed).
|
||||
// - A fullscreen window's monitor can be changed by win+shift+left/right hotkeys or monitor
|
||||
// topology changes (for example unplugging a monitor or disconnecting a remote session).
|
||||
void IslandWindow::_RestoreFullscreenPosition(const RECT rcWork)
|
||||
{
|
||||
HWND const hWnd = GetHandle();
|
||||
|
||||
// If the window was previously maximized, re-maximize the window.
|
||||
if (_fWasMaximizedBeforeFullscreen)
|
||||
{
|
||||
ShowWindow(hWnd, SW_SHOWMAXIMIZED);
|
||||
SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Start with the stored window position.
|
||||
RECT rcRestore = _rcWindowBeforeFullscreen;
|
||||
|
||||
// If the window DPI has changed, re-size the stored position by the change in DPI. This
|
||||
// ensures the window restores to the same logical size (even if to a monitor with a different
|
||||
// DPI/ scale factor).
|
||||
UINT dpiWindow = GetDpiForWindow(hWnd);
|
||||
rcRestore.right = rcRestore.left + MulDiv(rcRestore.right - rcRestore.left, dpiWindow, _dpiBeforeFullscreen);
|
||||
rcRestore.bottom = rcRestore.top + MulDiv(rcRestore.bottom - rcRestore.top, dpiWindow, _dpiBeforeFullscreen);
|
||||
|
||||
// Offset the stored position by the difference in work area.
|
||||
OffsetRect(&rcRestore,
|
||||
rcWork.left - _rcWorkBeforeFullscreen.left,
|
||||
rcWork.top - _rcWorkBeforeFullscreen.top);
|
||||
|
||||
// Enforce that our position is entirely within the bounds of our work area.
|
||||
// Prefer the top-left be on-screen rather than bottom-right (right before left, bottom before top).
|
||||
if (rcRestore.right > rcWork.right)
|
||||
{
|
||||
OffsetRect(&rcRestore, rcWork.right - rcRestore.right, 0);
|
||||
}
|
||||
if (rcRestore.left < rcWork.left)
|
||||
{
|
||||
OffsetRect(&rcRestore, rcWork.left - rcRestore.left, 0);
|
||||
}
|
||||
if (rcRestore.bottom > rcWork.bottom)
|
||||
{
|
||||
OffsetRect(&rcRestore, 0, rcWork.bottom - rcRestore.bottom);
|
||||
}
|
||||
if (rcRestore.top < rcWork.top)
|
||||
{
|
||||
OffsetRect(&rcRestore, 0, rcWork.top - rcRestore.top);
|
||||
}
|
||||
|
||||
// Show the window at the computed position.
|
||||
SetWindowPos(hWnd,
|
||||
HWND_TOP,
|
||||
rcRestore.left,
|
||||
rcRestore.top,
|
||||
rcRestore.right - rcRestore.left,
|
||||
rcRestore.bottom - rcRestore.top,
|
||||
SWP_SHOWWINDOW | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Controls setting us into or out of fullscreen mode. Largely taken from
|
||||
// Window::SetIsFullscreen in conhost.
|
||||
|
@ -780,7 +865,7 @@ void IslandWindow::_SetIsFullscreen(const bool fullscreenEnabled)
|
|||
// It is possible to enter _SetIsFullscreen even if we're already in full
|
||||
// screen. Use the old is in fullscreen flag to gate checks that rely on the
|
||||
// current state.
|
||||
const auto oldIsInFullscreen = _fullscreen;
|
||||
const bool fChangingFullscreen = (fullscreenEnabled != _fullscreen);
|
||||
_fullscreen = fullscreenEnabled;
|
||||
|
||||
HWND const hWnd = GetHandle();
|
||||
|
@ -796,61 +881,27 @@ void IslandWindow::_SetIsFullscreen(const bool fullscreenEnabled)
|
|||
WI_UpdateFlag(exWindowStyle, WS_EX_WINDOWEDGE, !_fullscreen);
|
||||
_SetWindowLongWHelper(hWnd, GWL_EXSTYLE, exWindowStyle);
|
||||
|
||||
// When entering/exiting fullscreen mode, we also need to backup/restore the
|
||||
// current window size, and resize the window to match the new state.
|
||||
_BackupWindowSizes(oldIsInFullscreen);
|
||||
_ApplyWindowSize();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Used in entering/exiting fullscreen mode. Saves the current window size,
|
||||
// and the full size of the monitor, for use in _ApplyWindowSize.
|
||||
// - Taken from conhost's Window::_BackupWindowSizes
|
||||
// Arguments:
|
||||
// - fCurrentIsInFullscreen: true if we're currently in fullscreen mode.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void IslandWindow::_BackupWindowSizes(const bool fCurrentIsInFullscreen)
|
||||
{
|
||||
if (_fullscreen)
|
||||
// Only change the window position if changing fullscreen state.
|
||||
if (fChangingFullscreen)
|
||||
{
|
||||
// Note: the current window size depends on the current state of the
|
||||
// window. So don't back it up if we're already in full screen.
|
||||
if (!fCurrentIsInFullscreen)
|
||||
{
|
||||
_nonFullscreenWindowSize = GetWindowRect();
|
||||
}
|
||||
// Get the monitor info for the window's current monitor.
|
||||
MONITORINFO mi = {};
|
||||
mi.cbSize = sizeof(mi);
|
||||
GetMonitorInfo(MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST), &mi);
|
||||
|
||||
// get and back up the current monitor's size
|
||||
HMONITOR const hCurrentMonitor = MonitorFromWindow(GetHandle(), MONITOR_DEFAULTTONEAREST);
|
||||
MONITORINFO currMonitorInfo;
|
||||
currMonitorInfo.cbSize = sizeof(currMonitorInfo);
|
||||
if (GetMonitorInfo(hCurrentMonitor, &currMonitorInfo))
|
||||
if (_fullscreen)
|
||||
{
|
||||
_fullscreenWindowSize = currMonitorInfo.rcMonitor;
|
||||
// Store the window's current position and size the window to the monitor.
|
||||
_SetFullscreenPosition(mi.rcMonitor, mi.rcWork);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Restore the stored window position.
|
||||
_RestoreFullscreenPosition(mi.rcWork);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Applies the appropriate window size for transitioning to/from fullscreen mode.
|
||||
// - Taken from conhost's Window::_ApplyWindowSize
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void IslandWindow::_ApplyWindowSize()
|
||||
{
|
||||
const auto newSize = _fullscreen ? _fullscreenWindowSize : _nonFullscreenWindowSize;
|
||||
LOG_IF_WIN32_BOOL_FALSE(SetWindowPos(GetHandle(),
|
||||
HWND_TOP,
|
||||
newSize.left,
|
||||
newSize.top,
|
||||
newSize.right - newSize.left,
|
||||
newSize.bottom - newSize.top,
|
||||
SWP_FRAMECHANGED | SWP_NOACTIVATE));
|
||||
}
|
||||
|
||||
void IslandWindow::UnsetHotkeys(const std::vector<winrt::Microsoft::Terminal::Control::KeyChord>& hotkeyList)
|
||||
{
|
||||
for (int i = 0; i < hotkeyList.size(); i++)
|
||||
|
|
|
@ -72,15 +72,17 @@ protected:
|
|||
[[nodiscard]] LRESULT _OnSizing(const WPARAM wParam, const LPARAM lParam);
|
||||
|
||||
bool _borderless{ false };
|
||||
bool _fullscreen{ false };
|
||||
bool _alwaysOnTop{ false };
|
||||
RECT _fullscreenWindowSize;
|
||||
RECT _nonFullscreenWindowSize;
|
||||
bool _fullscreen{ false };
|
||||
bool _fWasMaximizedBeforeFullscreen{ false };
|
||||
RECT _rcWindowBeforeFullscreen;
|
||||
RECT _rcWorkBeforeFullscreen;
|
||||
UINT _dpiBeforeFullscreen;
|
||||
|
||||
virtual void _SetIsBorderless(const bool borderlessEnabled);
|
||||
virtual void _SetIsFullscreen(const bool fullscreenEnabled);
|
||||
void _BackupWindowSizes(const bool currentIsInFullscreen);
|
||||
void _ApplyWindowSize();
|
||||
void _RestoreFullscreenPosition(const RECT rcWork);
|
||||
void _SetFullscreenPosition(const RECT rcMonitor, const RECT rcWork);
|
||||
|
||||
LONG _getDesiredWindowStyle() const;
|
||||
|
||||
|
|
|
@ -182,6 +182,7 @@ bool PtySignalInputThread::_GetData(_Out_writes_bytes_(cbBuffer) void* const pBu
|
|||
RETURN_LAST_ERROR_IF_NULL(hThread);
|
||||
_hThread.reset(hThread);
|
||||
_dwThreadId = dwThreadId;
|
||||
LOG_IF_FAILED(SetThreadDescription(hThread, L"ConPTY Signal Handler Thread"));
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
|
|
@ -176,6 +176,7 @@ DWORD VtInputThread::_InputThread()
|
|||
RETURN_LAST_ERROR_IF_NULL(hThread);
|
||||
_hThread.reset(hThread);
|
||||
_dwThreadId = dwThreadId;
|
||||
LOG_IF_FAILED(SetThreadDescription(hThread, L"ConPTY Input Handler Thread"));
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
|
|
@ -130,35 +130,6 @@ bool ConhostInternalGetSet::SetConsoleCursorPosition(const COORD position)
|
|||
return SUCCEEDED(ServiceLocator::LocateGlobals().api.SetConsoleCursorPositionImpl(info, clampedPosition));
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Connects the GetConsoleCursorInfo API call directly into our Driver Message servicing call inside Conhost.exe
|
||||
// Arguments:
|
||||
// - cursorInfo - Structure to receive console cursor rendering info
|
||||
// Return Value:
|
||||
// - true if successful (see DoSrvGetConsoleCursorInfo). false otherwise.
|
||||
bool ConhostInternalGetSet::GetConsoleCursorInfo(CONSOLE_CURSOR_INFO& cursorInfo) const
|
||||
{
|
||||
bool visible;
|
||||
DWORD size;
|
||||
|
||||
ServiceLocator::LocateGlobals().api.GetConsoleCursorInfoImpl(_io.GetActiveOutputBuffer(), size, visible);
|
||||
cursorInfo.bVisible = visible;
|
||||
cursorInfo.dwSize = size;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Connects the SetConsoleCursorInfo API call directly into our Driver Message servicing call inside Conhost.exe
|
||||
// Arguments:
|
||||
// - cursorInfo - Updated size/visibility information to modify the cursor rendering behavior.
|
||||
// Return Value:
|
||||
// - true if successful (see DoSrvSetConsoleCursorInfo). false otherwise.
|
||||
bool ConhostInternalGetSet::SetConsoleCursorInfo(const CONSOLE_CURSOR_INFO& cursorInfo)
|
||||
{
|
||||
const bool visible = !!cursorInfo.bVisible;
|
||||
return SUCCEEDED(ServiceLocator::LocateGlobals().api.SetConsoleCursorInfoImpl(_io.GetActiveOutputBuffer(), cursorInfo.dwSize, visible));
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Retrieves the current TextAttribute of the active screen buffer.
|
||||
// Arguments:
|
||||
|
|
|
@ -59,9 +59,6 @@ public:
|
|||
|
||||
bool SetConsoleCursorPosition(const COORD position) override;
|
||||
|
||||
bool GetConsoleCursorInfo(CONSOLE_CURSOR_INFO& cursorInfo) const override;
|
||||
bool SetConsoleCursorInfo(const CONSOLE_CURSOR_INFO& cursorInfo) override;
|
||||
|
||||
bool PrivateGetTextAttributes(TextAttribute& attrs) const override;
|
||||
bool PrivateSetTextAttributes(const TextAttribute& attrs) override;
|
||||
|
||||
|
|
|
@ -2684,26 +2684,6 @@ bool SCREEN_INFORMATION::IsCursorInMargins(const COORD cursorPosition) const noe
|
|||
return cursorPosition.Y <= margins.Bottom && cursorPosition.Y >= margins.Top;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Gets the region of the buffer that should be used for scrolling within the
|
||||
// scroll margins. If the scroll margins aren't set, it returns the entire
|
||||
// buffer size.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - The area of the buffer within the scroll margins
|
||||
Viewport SCREEN_INFORMATION::GetScrollingRegion() const noexcept
|
||||
{
|
||||
const auto buffer = GetBufferSize();
|
||||
const bool marginsSet = AreMarginsSet();
|
||||
const auto marginRect = GetAbsoluteScrollMargins().ToInclusive();
|
||||
const auto margin = Viewport::FromInclusive({ buffer.Left(),
|
||||
marginsSet ? marginRect.Top : buffer.Top(),
|
||||
buffer.RightInclusive(),
|
||||
marginsSet ? marginRect.Bottom : buffer.BottomInclusive() });
|
||||
return margin;
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Engages the legacy VT handling quirk; see TextAttribute::StripErroneousVT16VersionsOfLegacyDefaults
|
||||
void SCREEN_INFORMATION::SetIgnoreLegacyEquivalentVTAttributes() noexcept
|
||||
|
|
|
@ -202,7 +202,6 @@ public:
|
|||
void SetScrollMargins(const Microsoft::Console::Types::Viewport margins);
|
||||
bool AreMarginsSet() const noexcept;
|
||||
bool IsCursorInMargins(const COORD cursorPosition) const noexcept;
|
||||
Microsoft::Console::Types::Viewport GetScrollingRegion() const noexcept;
|
||||
|
||||
[[nodiscard]] NTSTATUS UseAlternateScreenBuffer();
|
||||
void UseMainScreenBuffer();
|
||||
|
|
|
@ -322,6 +322,7 @@ HRESULT ConsoleCreateIoThread(_In_ HANDLE Server,
|
|||
|
||||
HANDLE const hThread = CreateThread(nullptr, 0, ConsoleIoThread, connectMessage, 0, nullptr);
|
||||
RETURN_HR_IF(E_HANDLE, hThread == nullptr);
|
||||
LOG_IF_FAILED(SetThreadDescription(hThread, L"Console Driver Message IO Thread"));
|
||||
LOG_IF_WIN32_BOOL_FALSE(CloseHandle(hThread)); // The thread will run on its own and close itself. Free the associated handle.
|
||||
|
||||
// See MSFT:19918626
|
||||
|
|
|
@ -27,6 +27,7 @@ HANDLE ConsoleInputThread::Start()
|
|||
{
|
||||
_hThread = hThread;
|
||||
_dwThreadId = dwThreadId;
|
||||
LOG_IF_FAILED(SetThreadDescription(hThread, L"Win32 Window Message Input Thread"));
|
||||
}
|
||||
|
||||
return hThread;
|
||||
|
|
|
@ -60,11 +60,13 @@ Window::Window() :
|
|||
_fIsInFullscreen(false),
|
||||
_pSettings(nullptr),
|
||||
_hWnd(nullptr),
|
||||
_pUiaProvider(nullptr)
|
||||
_pUiaProvider(nullptr),
|
||||
_fWasMaximizedBeforeFullscreen(false),
|
||||
_dpiBeforeFullscreen(0)
|
||||
{
|
||||
ZeroMemory((void*)&_rcClientLast, sizeof(_rcClientLast));
|
||||
ZeroMemory((void*)&_rcNonFullscreenWindowSize, sizeof(_rcNonFullscreenWindowSize));
|
||||
ZeroMemory((void*)&_rcFullscreenWindowSize, sizeof(_rcFullscreenWindowSize));
|
||||
ZeroMemory((void*)&_rcWindowBeforeFullscreen, sizeof(_rcWindowBeforeFullscreen));
|
||||
ZeroMemory((void*)&_rcWorkBeforeFullscreen, sizeof(_rcWorkBeforeFullscreen));
|
||||
}
|
||||
|
||||
Window::~Window()
|
||||
|
@ -1095,11 +1097,90 @@ bool Window::IsInFullscreen() const
|
|||
return _fIsInFullscreen;
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Called when entering fullscreen, with the window's current monitor rect and work area.
|
||||
// - The current window position, dpi, work area, and maximized state are stored, and the
|
||||
// window is positioned to the monitor rect.
|
||||
void Window::_SetFullscreenPosition(const RECT rcMonitor, const RECT rcWork)
|
||||
{
|
||||
::GetWindowRect(GetWindowHandle(), &_rcWindowBeforeFullscreen);
|
||||
_dpiBeforeFullscreen = GetDpiForWindow(GetWindowHandle());
|
||||
_fWasMaximizedBeforeFullscreen = IsZoomed(GetWindowHandle());
|
||||
_rcWorkBeforeFullscreen = rcWork;
|
||||
|
||||
SetWindowPos(GetWindowHandle(),
|
||||
HWND_TOP,
|
||||
rcMonitor.left,
|
||||
rcMonitor.top,
|
||||
rcMonitor.right - rcMonitor.left,
|
||||
rcMonitor.bottom - rcMonitor.top,
|
||||
SWP_FRAMECHANGED);
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Called when exiting fullscreen, with the window's current monitor work area.
|
||||
// - The window is restored to its previous position, migrating that previous position to the
|
||||
// window's current monitor (if the current work area or window DPI have changed).
|
||||
// - A fullscreen window's monitor can be changed by win+shift+left/right hotkeys or monitor
|
||||
// topology changes (for example unplugging a monitor or disconnecting a remote session).
|
||||
void Window::_RestoreFullscreenPosition(const RECT rcWork)
|
||||
{
|
||||
// If the window was previously maximized, re-maximize the window.
|
||||
if (_fWasMaximizedBeforeFullscreen)
|
||||
{
|
||||
ShowWindow(GetWindowHandle(), SW_SHOWMAXIMIZED);
|
||||
SetWindowPos(GetWindowHandle(), HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Start with the stored window position.
|
||||
RECT rcRestore = _rcWindowBeforeFullscreen;
|
||||
|
||||
// If the window DPI has changed, re-size the stored position by the change in DPI. This
|
||||
// ensures the window restores to the same logical size (even if to a monitor with a different
|
||||
// DPI/ scale factor).
|
||||
UINT dpiWindow = GetDpiForWindow(GetWindowHandle());
|
||||
rcRestore.right = rcRestore.left + MulDiv(rcRestore.right - rcRestore.left, dpiWindow, _dpiBeforeFullscreen);
|
||||
rcRestore.bottom = rcRestore.top + MulDiv(rcRestore.bottom - rcRestore.top, dpiWindow, _dpiBeforeFullscreen);
|
||||
|
||||
// Offset the stored position by the difference in work area.
|
||||
OffsetRect(&rcRestore,
|
||||
rcWork.left - _rcWorkBeforeFullscreen.left,
|
||||
rcWork.top - _rcWorkBeforeFullscreen.top);
|
||||
|
||||
// Enforce that our position is entirely within the bounds of our work area.
|
||||
// Prefer the top-left be on-screen rather than bottom-right (right before left, bottom before top).
|
||||
if (rcRestore.right > rcWork.right)
|
||||
{
|
||||
OffsetRect(&rcRestore, rcWork.right - rcRestore.right, 0);
|
||||
}
|
||||
if (rcRestore.left < rcWork.left)
|
||||
{
|
||||
OffsetRect(&rcRestore, rcWork.left - rcRestore.left, 0);
|
||||
}
|
||||
if (rcRestore.bottom > rcWork.bottom)
|
||||
{
|
||||
OffsetRect(&rcRestore, 0, rcWork.bottom - rcRestore.bottom);
|
||||
}
|
||||
if (rcRestore.top < rcWork.top)
|
||||
{
|
||||
OffsetRect(&rcRestore, 0, rcWork.top - rcRestore.top);
|
||||
}
|
||||
|
||||
// Show the window at the computed position.
|
||||
SetWindowPos(GetWindowHandle(),
|
||||
HWND_TOP,
|
||||
rcRestore.left,
|
||||
rcRestore.top,
|
||||
rcRestore.right - rcRestore.left,
|
||||
rcRestore.bottom - rcRestore.top,
|
||||
SWP_SHOWWINDOW | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
|
||||
}
|
||||
|
||||
void Window::SetIsFullscreen(const bool fFullscreenEnabled)
|
||||
{
|
||||
// It is possible to enter SetIsFullScreen even if we're already in full screen.
|
||||
// Use the old is in fullscreen flag to gate checks that rely on the current state.
|
||||
bool fOldIsInFullscreen = _fIsInFullscreen;
|
||||
const bool fChangingFullscreen = (fFullscreenEnabled != _fIsInFullscreen);
|
||||
_fIsInFullscreen = fFullscreenEnabled;
|
||||
|
||||
HWND const hWnd = GetWindowHandle();
|
||||
|
@ -1135,48 +1216,30 @@ void Window::SetIsFullscreen(const bool fFullscreenEnabled)
|
|||
}
|
||||
SetWindowLongW(hWnd, GWL_EXSTYLE, dwExWindowStyle);
|
||||
|
||||
_BackupWindowSizes(fOldIsInFullscreen);
|
||||
_ApplyWindowSize();
|
||||
}
|
||||
|
||||
void Window::_BackupWindowSizes(const bool fCurrentIsInFullscreen)
|
||||
{
|
||||
if (_fIsInFullscreen)
|
||||
// Only change the window position if changing fullscreen state.
|
||||
if (fChangingFullscreen)
|
||||
{
|
||||
// Note: the current window size depends on the current state of the window.
|
||||
// So don't back it up if we're already in full screen.
|
||||
if (!fCurrentIsInFullscreen)
|
||||
{
|
||||
_rcNonFullscreenWindowSize = GetWindowRect();
|
||||
}
|
||||
// Get the monitor info for the window's current monitor.
|
||||
MONITORINFO mi = {};
|
||||
mi.cbSize = sizeof(mi);
|
||||
GetMonitorInfo(MonitorFromWindow(GetWindowHandle(), MONITOR_DEFAULTTONEAREST), &mi);
|
||||
|
||||
// get and back up the current monitor's size
|
||||
HMONITOR const hCurrentMonitor = MonitorFromWindow(GetWindowHandle(), MONITOR_DEFAULTTONEAREST);
|
||||
MONITORINFO currMonitorInfo;
|
||||
currMonitorInfo.cbSize = sizeof(currMonitorInfo);
|
||||
if (GetMonitorInfo(hCurrentMonitor, &currMonitorInfo))
|
||||
if (_fIsInFullscreen)
|
||||
{
|
||||
_rcFullscreenWindowSize = currMonitorInfo.rcMonitor;
|
||||
// Store the window's current position and size the window to the monitor.
|
||||
_SetFullscreenPosition(mi.rcMonitor, mi.rcWork);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Restore the stored window position.
|
||||
_RestoreFullscreenPosition(mi.rcWork);
|
||||
|
||||
SCREEN_INFORMATION& siAttached = GetScreenInfo();
|
||||
siAttached.MakeCurrentCursorVisible();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Window::_ApplyWindowSize()
|
||||
{
|
||||
const RECT rcNewSize = _fIsInFullscreen ? _rcFullscreenWindowSize : _rcNonFullscreenWindowSize;
|
||||
|
||||
SetWindowPos(GetWindowHandle(),
|
||||
HWND_TOP,
|
||||
rcNewSize.left,
|
||||
rcNewSize.top,
|
||||
RECT_WIDTH(&rcNewSize),
|
||||
RECT_HEIGHT(&rcNewSize),
|
||||
SWP_FRAMECHANGED);
|
||||
|
||||
SCREEN_INFORMATION& siAttached = GetScreenInfo();
|
||||
siAttached.MakeCurrentCursorVisible();
|
||||
}
|
||||
|
||||
void Window::ToggleFullscreen()
|
||||
{
|
||||
SetIsFullscreen(!IsInFullscreen());
|
||||
|
|
|
@ -147,12 +147,13 @@ namespace Microsoft::Console::Interactivity::Win32
|
|||
RECT _rcClientLast;
|
||||
|
||||
// Full screen
|
||||
void _BackupWindowSizes(const bool fCurrentIsInFullscreen);
|
||||
void _ApplyWindowSize();
|
||||
|
||||
void _RestoreFullscreenPosition(const RECT rcWork);
|
||||
void _SetFullscreenPosition(const RECT rcMonitor, const RECT rcWork);
|
||||
bool _fIsInFullscreen;
|
||||
RECT _rcFullscreenWindowSize;
|
||||
RECT _rcNonFullscreenWindowSize;
|
||||
bool _fWasMaximizedBeforeFullscreen;
|
||||
RECT _rcWindowBeforeFullscreen;
|
||||
RECT _rcWorkBeforeFullscreen;
|
||||
UINT _dpiBeforeFullscreen;
|
||||
|
||||
// math helpers
|
||||
void _CalculateWindowRect(const COORD coordWindowInChars,
|
||||
|
|
|
@ -226,18 +226,15 @@ using namespace Microsoft::Console::Types;
|
|||
_UpdateSystemMetrics();
|
||||
s_ReinitializeFontsForDPIChange();
|
||||
|
||||
if (IsInFullscreen())
|
||||
{
|
||||
// If we're a full screen window, completely ignore what the DPICHANGED says as it will be bigger than the monitor and
|
||||
// instead just ensure that the window is still taking up the full screen.
|
||||
SetIsFullscreen(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// this is the RECT that the system suggests.
|
||||
RECT* const prcNewScale = (RECT*)lParam;
|
||||
SetWindowPos(hWnd, HWND_TOP, prcNewScale->left, prcNewScale->top, RECT_WIDTH(prcNewScale), RECT_HEIGHT(prcNewScale), SWP_NOZORDER | SWP_NOACTIVATE);
|
||||
}
|
||||
// This is the RECT that the system suggests.
|
||||
RECT* const prcNewScale = (RECT*)lParam;
|
||||
SetWindowPos(hWnd,
|
||||
HWND_TOP,
|
||||
prcNewScale->left,
|
||||
prcNewScale->top,
|
||||
RECT_WIDTH(prcNewScale),
|
||||
RECT_HEIGHT(prcNewScale),
|
||||
SWP_NOZORDER | SWP_NOACTIVATE);
|
||||
|
||||
_fInDPIChange = false;
|
||||
|
||||
|
|
|
@ -136,6 +136,7 @@ RenderThread::~RenderThread()
|
|||
else
|
||||
{
|
||||
_hThread = hThread;
|
||||
LOG_IF_FAILED(SetThreadDescription(hThread, L"Rendering Output Thread"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
|
||||
// Routine Description:
|
||||
// - Initializes a ConsoleWaitBlock
|
||||
// - ConsoleWaitBlocks will self-manage their position in their two queues.
|
||||
// - They will push themselves into the tail and store the iterator for constant deletion time later.
|
||||
// - ConsoleWaitBlocks will mostly self-manage their position in their two queues.
|
||||
// - They will be pushed into the tail and the resulting iterator stored for constant deletion time later.
|
||||
// Arguments:
|
||||
// - pProcessQueue - The queue attached to the client process ID that requested this action
|
||||
// - pObjectQueue - The queue attached to the console object that will service the action when data arrives
|
||||
|
@ -30,9 +30,6 @@ ConsoleWaitBlock::ConsoleWaitBlock(_In_ ConsoleWaitQueue* const pProcessQueue,
|
|||
_pObjectQueue(THROW_HR_IF_NULL(E_INVALIDARG, pObjectQueue)),
|
||||
_pWaiter(THROW_HR_IF_NULL(E_INVALIDARG, pWaiter))
|
||||
{
|
||||
_itProcessQueue = _pProcessQueue->_blocks.insert(_pProcessQueue->_blocks.end(), this);
|
||||
_itObjectQueue = _pObjectQueue->_blocks.insert(_pObjectQueue->_blocks.end(), this);
|
||||
|
||||
_WaitReplyMessage = *pWaitReplyMessage;
|
||||
|
||||
// We will write the original message back (with updated out parameters/payload) when the request is finally serviced.
|
||||
|
@ -87,6 +84,10 @@ ConsoleWaitBlock::~ConsoleWaitBlock()
|
|||
pObjectQueue,
|
||||
pWaitReplyMessage,
|
||||
pWaiter);
|
||||
|
||||
// Set the iterators on the wait block so that it can remove itself later.
|
||||
pWaitBlock->_itProcessQueue = pProcessQueue->_blocks.insert(pProcessQueue->_blocks.end(), pWaitBlock);
|
||||
pWaitBlock->_itObjectQueue = pObjectQueue->_blocks.insert(pObjectQueue->_blocks.end(), pWaitBlock);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
|
|
|
@ -29,10 +29,8 @@ namespace Microsoft::Console::VirtualTerminal
|
|||
{
|
||||
public:
|
||||
virtual ~ConGetSet() = default;
|
||||
virtual bool GetConsoleCursorInfo(CONSOLE_CURSOR_INFO& cursorInfo) const = 0;
|
||||
virtual bool GetConsoleScreenBufferInfoEx(CONSOLE_SCREEN_BUFFER_INFOEX& screenBufferInfo) const = 0;
|
||||
virtual bool SetConsoleScreenBufferInfoEx(const CONSOLE_SCREEN_BUFFER_INFOEX& screenBufferInfo) = 0;
|
||||
virtual bool SetConsoleCursorInfo(const CONSOLE_CURSOR_INFO& cursorInfo) = 0;
|
||||
virtual bool SetConsoleCursorPosition(const COORD position) = 0;
|
||||
|
||||
virtual bool PrivateIsVtInputEnabled() const = 0;
|
||||
|
|
|
@ -98,32 +98,6 @@ public:
|
|||
return _setConsoleCursorPositionResult;
|
||||
}
|
||||
|
||||
bool GetConsoleCursorInfo(CONSOLE_CURSOR_INFO& cursorInfo) const override
|
||||
{
|
||||
Log::Comment(L"GetConsoleCursorInfo MOCK called...");
|
||||
|
||||
if (_getConsoleCursorInfoResult)
|
||||
{
|
||||
cursorInfo.dwSize = _cursorSize;
|
||||
cursorInfo.bVisible = _cursorVisible;
|
||||
}
|
||||
|
||||
return _getConsoleCursorInfoResult;
|
||||
}
|
||||
|
||||
bool SetConsoleCursorInfo(const CONSOLE_CURSOR_INFO& cursorInfo) override
|
||||
{
|
||||
Log::Comment(L"SetConsoleCursorInfo MOCK called...");
|
||||
|
||||
if (_setConsoleCursorInfoResult)
|
||||
{
|
||||
VERIFY_ARE_EQUAL(_expectedCursorSize, cursorInfo.dwSize);
|
||||
VERIFY_ARE_EQUAL(_expectedCursorVisible, !!cursorInfo.bVisible);
|
||||
}
|
||||
|
||||
return _setConsoleCursorInfoResult;
|
||||
}
|
||||
|
||||
bool SetConsoleWindowInfo(const bool absolute, const SMALL_RECT& window) override
|
||||
{
|
||||
Log::Comment(L"SetConsoleWindowInfo MOCK called...");
|
||||
|
@ -624,8 +598,6 @@ public:
|
|||
// APIs succeed by default
|
||||
_setConsoleCursorPositionResult = TRUE;
|
||||
_getConsoleScreenBufferInfoExResult = TRUE;
|
||||
_getConsoleCursorInfoResult = TRUE;
|
||||
_setConsoleCursorInfoResult = TRUE;
|
||||
_privateGetTextAttributesResult = TRUE;
|
||||
_privateSetTextAttributesResult = TRUE;
|
||||
_privateWriteConsoleInputWResult = TRUE;
|
||||
|
@ -645,11 +617,7 @@ public:
|
|||
// Call cursor positions separately
|
||||
PrepCursor(xact, yact);
|
||||
|
||||
_cursorSize = 33;
|
||||
_expectedCursorSize = _cursorSize;
|
||||
|
||||
_cursorVisible = TRUE;
|
||||
_expectedCursorVisible = _cursorVisible;
|
||||
|
||||
// Attribute default is gray on black.
|
||||
_attribute = TextAttribute{ FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED };
|
||||
|
@ -775,12 +743,9 @@ public:
|
|||
COORD _cursorPos = { 0, 0 };
|
||||
SMALL_RECT _expectedScrollRegion = { 0, 0, 0, 0 };
|
||||
|
||||
DWORD _cursorSize = 0;
|
||||
bool _cursorVisible = false;
|
||||
|
||||
COORD _expectedCursorPos = { 0, 0 };
|
||||
DWORD _expectedCursorSize = 0;
|
||||
bool _expectedCursorVisible = false;
|
||||
|
||||
TextAttribute _attribute = {};
|
||||
TextAttribute _expectedAttribute = {};
|
||||
|
@ -792,8 +757,6 @@ public:
|
|||
|
||||
bool _getConsoleScreenBufferInfoExResult = false;
|
||||
bool _setConsoleCursorPositionResult = false;
|
||||
bool _getConsoleCursorInfoResult = false;
|
||||
bool _setConsoleCursorInfoResult = false;
|
||||
bool _privateGetTextAttributesResult = false;
|
||||
bool _privateSetTextAttributesResult = false;
|
||||
bool _privateWriteConsoleInputWResult = false;
|
||||
|
|