diff --git a/doc/cascadia/profiles.schema.json b/doc/cascadia/profiles.schema.json
index 07e584c6b..319e0bae7 100644
--- a/doc/cascadia/profiles.schema.json
+++ b/doc/cascadia/profiles.schema.json
@@ -1401,7 +1401,8 @@
"properties": {
"acrylicOpacity": {
"default": 0.5,
- "description": "When useAcrylic is set to true, it sets the transparency of the window for the profile. Accepts floating point values from 0-1 (default 0.5).",
+ "description": "[deprecated] Please use `opacity` instead.",
+ "deprecated": true,
"maximum": 1,
"minimum": 0,
"type": "number"
@@ -1614,6 +1615,13 @@
"minLength": 1,
"type": "string"
},
+ "opacity": {
+ "default": 100,
+ "description": "Sets the opacity of the window for the profile. Accepts values from 0-100. Defaults to 50 when useAcrylic is set to true.",
+ "maximum": 100,
+ "minimum": 0,
+ "type": "number"
+ },
"padding": {
"default": "8, 8, 8, 8",
"description": "Sets the padding around the text within the window. Can have three different formats:\n -\"#\" sets the same padding for all sides \n -\"#, #\" sets the same padding for left-right and top-bottom\n -\"#, #, #, #\" sets the padding individually for left, top, right, and bottom.",
diff --git a/scratch/ScratchIslandApp/Package/Package.wapproj b/scratch/ScratchIslandApp/Package/Package.wapproj
index 262719541..f7458a902 100644
--- a/scratch/ScratchIslandApp/Package/Package.wapproj
+++ b/scratch/ScratchIslandApp/Package/Package.wapproj
@@ -140,12 +140,12 @@
-
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
-
+
diff --git a/scratch/ScratchIslandApp/SampleApp/MySettings.h b/scratch/ScratchIslandApp/SampleApp/MySettings.h
index 34643f7fe..4d34b8624 100644
--- a/scratch/ScratchIslandApp/SampleApp/MySettings.h
+++ b/scratch/ScratchIslandApp/SampleApp/MySettings.h
@@ -45,7 +45,7 @@ namespace winrt::SampleApp::implementation
WINRT_PROPERTY(winrt::hstring, ProfileName);
WINRT_PROPERTY(bool, UseAcrylic, false);
- WINRT_PROPERTY(double, TintOpacity, 0.5);
+ WINRT_PROPERTY(double, Opacity, .5);
WINRT_PROPERTY(winrt::hstring, Padding, DEFAULT_PADDING);
WINRT_PROPERTY(winrt::hstring, FontFace, L"Consolas");
WINRT_PROPERTY(int32_t, FontSize, DEFAULT_FONT_SIZE);
diff --git a/scratch/ScratchIslandApp/SampleApp/SampleAppLib.vcxproj b/scratch/ScratchIslandApp/SampleApp/SampleAppLib.vcxproj
index 54a6c5706..04b9b0824 100644
--- a/scratch/ScratchIslandApp/SampleApp/SampleAppLib.vcxproj
+++ b/scratch/ScratchIslandApp/SampleApp/SampleAppLib.vcxproj
@@ -147,13 +147,13 @@
-
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
-
+
diff --git a/scratch/ScratchIslandApp/SampleApp/dll/SampleApp.vcxproj b/scratch/ScratchIslandApp/SampleApp/dll/SampleApp.vcxproj
index 23b157e9d..59d500ccc 100644
--- a/scratch/ScratchIslandApp/SampleApp/dll/SampleApp.vcxproj
+++ b/scratch/ScratchIslandApp/SampleApp/dll/SampleApp.vcxproj
@@ -80,13 +80,13 @@
-
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
-
+
diff --git a/scratch/ScratchIslandApp/SampleApp/packages.config b/scratch/ScratchIslandApp/SampleApp/packages.config
index 9de6f1b8d..78467467c 100644
--- a/scratch/ScratchIslandApp/SampleApp/packages.config
+++ b/scratch/ScratchIslandApp/SampleApp/packages.config
@@ -1,6 +1,6 @@
-
+
diff --git a/scratch/ScratchIslandApp/WindowExe/WindowExe.vcxproj b/scratch/ScratchIslandApp/WindowExe/WindowExe.vcxproj
index e8cb725b7..4332ae5d0 100644
--- a/scratch/ScratchIslandApp/WindowExe/WindowExe.vcxproj
+++ b/scratch/ScratchIslandApp/WindowExe/WindowExe.vcxproj
@@ -120,14 +120,14 @@
-
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
-
+
diff --git a/scratch/ScratchIslandApp/WindowExe/packages.config b/scratch/ScratchIslandApp/WindowExe/packages.config
index 3d9e08c4b..d55a833a5 100644
--- a/scratch/ScratchIslandApp/WindowExe/packages.config
+++ b/scratch/ScratchIslandApp/WindowExe/packages.config
@@ -2,6 +2,6 @@
-
+
diff --git a/src/cascadia/CascadiaPackage/CascadiaPackage.wapproj b/src/cascadia/CascadiaPackage/CascadiaPackage.wapproj
index b18c6d57a..ba722f246 100644
--- a/src/cascadia/CascadiaPackage/CascadiaPackage.wapproj
+++ b/src/cascadia/CascadiaPackage/CascadiaPackage.wapproj
@@ -146,12 +146,12 @@
-
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
-
+
diff --git a/src/cascadia/LocalTests_SettingsModel/SettingsModel.LocalTests.vcxproj b/src/cascadia/LocalTests_SettingsModel/SettingsModel.LocalTests.vcxproj
index ac1af0396..576c89e7d 100644
--- a/src/cascadia/LocalTests_SettingsModel/SettingsModel.LocalTests.vcxproj
+++ b/src/cascadia/LocalTests_SettingsModel/SettingsModel.LocalTests.vcxproj
@@ -98,10 +98,10 @@
x86$(Platform)
- <_MUXBinRoot>"$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\runtimes\win10-$(Native-Platform)\native\"
+ <_MUXBinRoot>"$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\runtimes\win10-$(Native-Platform)\native\"
-
+
diff --git a/src/cascadia/LocalTests_TerminalApp/TerminalApp.LocalTests.vcxproj b/src/cascadia/LocalTests_TerminalApp/TerminalApp.LocalTests.vcxproj
index a6340764b..95d8ea17f 100644
--- a/src/cascadia/LocalTests_TerminalApp/TerminalApp.LocalTests.vcxproj
+++ b/src/cascadia/LocalTests_TerminalApp/TerminalApp.LocalTests.vcxproj
@@ -92,11 +92,11 @@
x86$(Platform)
- <_MUXBinRoot>"$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\runtimes\win10-$(Native-Platform)\native\"
+ <_MUXBinRoot>"$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\runtimes\win10-$(Native-Platform)\native\"
-
+
diff --git a/src/cascadia/LocalTests_TerminalApp/TestHostApp/TestHostApp.vcxproj b/src/cascadia/LocalTests_TerminalApp/TestHostApp/TestHostApp.vcxproj
index cef96d52f..722ce9f5d 100644
--- a/src/cascadia/LocalTests_TerminalApp/TestHostApp/TestHostApp.vcxproj
+++ b/src/cascadia/LocalTests_TerminalApp/TestHostApp/TestHostApp.vcxproj
@@ -123,7 +123,7 @@
-
+
diff --git a/src/cascadia/Remoting/Monarch.cpp b/src/cascadia/Remoting/Monarch.cpp
index 9bf60fc8b..c16eb52e9 100644
--- a/src/cascadia/Remoting/Monarch.cpp
+++ b/src/cascadia/Remoting/Monarch.cpp
@@ -50,6 +50,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
// - Add the given peasant to the list of peasants we're tracking. This
// Peasant may have already been assigned an ID. If it hasn't, then give
// it an ID.
+ // - NB: this takes a unique_lock on _peasantsMutex.
// Arguments:
// - peasant: the new Peasant to track.
// Return Value:
@@ -71,10 +72,24 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
{
// Peasant already had an ID (from an older monarch). Leave that one
// be. Make sure that the next peasant's ID is higher than it.
- _nextPeasantID = providedID >= _nextPeasantID ? providedID + 1 : _nextPeasantID;
+ // If multiple peasants are added concurrently we keep trying to update
+ // until we get to set the new id.
+ uint64_t current;
+ do
+ {
+ current = _nextPeasantID.load(std::memory_order_relaxed);
+ } while (current <= providedID && !_nextPeasantID.compare_exchange_weak(current, providedID + 1, std::memory_order_relaxed));
}
auto newPeasantsId = peasant.GetID();
+
+ // Keep track of which peasant we are
+ // SAFETY: this is only true for one peasant, and each peasant
+ // is only added to a monarch once, so we do not need synchronization here.
+ if (peasant.GetPID() == _ourPID)
+ {
+ _ourPeasantId = newPeasantsId;
+ }
// Add an event listener to the peasant's WindowActivated event.
peasant.WindowActivated({ this, &Monarch::_peasantWindowActivated });
peasant.IdentifyWindowsRequested({ this, &Monarch::_identifyWindows });
@@ -84,7 +99,10 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
peasant.HideNotificationIconRequested([this](auto&&, auto&&) { _HideNotificationIconRequestedHandlers(*this, nullptr); });
peasant.QuitAllRequested({ this, &Monarch::_handleQuitAll });
- _peasants[newPeasantsId] = peasant;
+ {
+ std::unique_lock lock{ _peasantsMutex };
+ _peasants[newPeasantsId] = peasant;
+ }
TraceLoggingWrite(g_hRemotingProvider,
"Monarch_AddPeasant",
@@ -124,9 +142,15 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
// closing all windows.
_QuitAllRequestedHandlers(*this, nullptr);
+ _quitting.store(true);
// Tell all peasants to exit.
- const auto callback = [&](const auto& /*id*/, const auto& p) {
- p.Quit();
+ const auto callback = [&](const auto& id, const auto& p) {
+ // We want to tell our peasant to quit last, so that we don't try
+ // to perform a bunch of elections on quit.
+ if (id != _ourPeasantId)
+ {
+ p.Quit();
+ }
};
const auto onError = [&](const auto& id) {
TraceLoggingWrite(g_hRemotingProvider,
@@ -137,18 +161,46 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
};
_forEachPeasant(callback, onError);
+
+ {
+ std::shared_lock lock{ _peasantsMutex };
+ const auto peasantSearch = _peasants.find(_ourPeasantId);
+ if (peasantSearch != _peasants.end())
+ {
+ peasantSearch->second.Quit();
+ }
+ else
+ {
+ // Somehow we don't have our own peasant, this should never happen.
+ // We are trying to quit anyways so just fail here.
+ assert(peasantSearch != _peasants.end());
+ }
+ }
}
// Method Description:
// - Tells the monarch that a peasant is being closed.
+ // - NB: this (separately) takes unique locks on _peasantsMutex and
+ // _mruPeasantsMutex.
// Arguments:
// - peasantId: the id of the peasant
// Return Value:
// -
void Monarch::SignalClose(const uint64_t peasantId)
{
- _clearOldMruEntries(peasantId);
- _peasants.erase(peasantId);
+ // If we are quitting we don't care about maintaining our list of
+ // peasants anymore, and don't need to notify the host that something
+ // changed.
+ if (_quitting.load(std::memory_order_acquire))
+ {
+ return;
+ }
+
+ _clearOldMruEntries({ peasantId });
+ {
+ std::unique_lock lock{ _peasantsMutex };
+ _peasants.erase(peasantId);
+ }
_WindowClosedHandlers(nullptr, nullptr);
}
@@ -160,23 +212,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
// - the number of active peasants.
uint64_t Monarch::GetNumberOfPeasants()
{
- auto num = 0;
- auto callback = [&](const auto& /*id*/, const auto& p) {
- // Check that the peasant is alive, and if so increment the count
- p.GetID();
- num += 1;
- };
- auto onError = [](const auto& id) {
- TraceLoggingWrite(g_hRemotingProvider,
- "Monarch_GetNumberOfPeasants_Failed",
- TraceLoggingInt64(id, "peasantID", "The ID of the peasant which we could not enumerate"),
- TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
- TraceLoggingKeyword(TIL_KEYWORD_TRACE));
- };
-
- _forEachPeasant(callback, onError);
-
- return num;
+ std::shared_lock lock{ _peasantsMutex };
+ return _peasants.size();
}
// Method Description:
@@ -197,16 +234,25 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
// Method Description:
// - Lookup a peasant by its ID. If the peasant has died, this will also
// remove the peasant from our list of peasants.
+ // - NB: this (separately) takes unique locks on _peasantsMutex and
+ // _mruPeasantsMutex.
// Arguments:
// - peasantID: The ID Of the peasant to find
+ // - clearMruPeasantOnFailure: When true this function will handle clearing
+ // from _mruPeasants if a peasant was not found, otherwise the caller is
+ // expected to handle that cleanup themselves.
// Return Value:
// - the peasant if it exists in our map, otherwise null
- Remoting::IPeasant Monarch::_getPeasant(uint64_t peasantID)
+ Remoting::IPeasant Monarch::_getPeasant(uint64_t peasantID, bool clearMruPeasantOnFailure)
{
try
{
- const auto peasantSearch = _peasants.find(peasantID);
- auto maybeThePeasant = peasantSearch == _peasants.end() ? nullptr : peasantSearch->second;
+ IPeasant maybeThePeasant = nullptr;
+ {
+ std::shared_lock lock{ _peasantsMutex };
+ const auto peasantSearch = _peasants.find(peasantID);
+ maybeThePeasant = peasantSearch == _peasants.end() ? nullptr : peasantSearch->second;
+ }
// Ask the peasant for their PID. This will validate that they're
// actually still alive.
if (maybeThePeasant)
@@ -218,12 +264,19 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
catch (...)
{
LOG_CAUGHT_EXCEPTION();
- // Remove the peasant from the list of peasants
- _peasants.erase(peasantID);
- // Remove the peasant from the list of MRU windows. They're dead.
- // They can't be the MRU anymore.
- _clearOldMruEntries(peasantID);
+ // Remove the peasant from the list of peasants
+ {
+ std::unique_lock lock{ _peasantsMutex };
+ _peasants.erase(peasantID);
+ }
+
+ if (clearMruPeasantOnFailure)
+ {
+ // Remove the peasant from the list of MRU windows. They're dead.
+ // They can't be the MRU anymore.
+ _clearOldMruEntries({ peasantID });
+ }
return nullptr;
}
}
@@ -244,39 +297,27 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
return 0;
}
- std::vector peasantsToErase{};
uint64_t result = 0;
- for (const auto& [id, p] : _peasants)
- {
- try
- {
- auto otherName = p.WindowName();
- if (otherName == name)
- {
- result = id;
- break;
- }
- }
- catch (...)
- {
- LOG_CAUGHT_EXCEPTION();
- // Normally, we'd just erase the peasant here. However, we can't
- // erase from the map while we're iterating over it like this.
- // Instead, pull a good ole Java and collect this id for removal
- // later.
- peasantsToErase.push_back(id);
- }
- }
- // Remove the dead peasants we came across while iterating.
- for (const auto& id : peasantsToErase)
- {
- // Remove the peasant from the list of peasants
- _peasants.erase(id);
- // Remove the peasant from the list of MRU windows. They're dead.
- // They can't be the MRU anymore.
- _clearOldMruEntries(id);
- }
+ const auto callback = [&](const auto& id, const auto& p) {
+ auto otherName = p.WindowName();
+ if (otherName == name)
+ {
+ result = id;
+ return false;
+ }
+ return true;
+ };
+
+ const auto onError = [&](const auto& id) {
+ TraceLoggingWrite(g_hRemotingProvider,
+ "Monarch_lookupPeasantIdForName_Failed",
+ TraceLoggingInt64(id, "peasantID", "The ID of the peasant which we could not get the name of"),
+ TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
+ TraceLoggingKeyword(TIL_KEYWORD_TRACE));
+ };
+
+ _forEachPeasant(callback, onError);
TraceLoggingWrite(g_hRemotingProvider,
"Monarch_lookupPeasantIdForName",
@@ -328,33 +369,42 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
// - Helper for removing a peasant from the list of MRU peasants. We want to
// do this both when the peasant dies, and also when the peasant is newly
// activated (so that we don't leave an old entry for it in the list).
+ // - NB: This takes a unique lock on _mruPeasantsMutex.
// Arguments:
- // - peasantID: The ID of the peasant to remove from the MRU list
+ // - peasantIds: The list of peasant IDs to remove from the MRU list
// Return Value:
// -
- void Monarch::_clearOldMruEntries(const uint64_t peasantID)
+ void Monarch::_clearOldMruEntries(const std::unordered_set& peasantIds)
{
- auto result = std::find_if(_mruPeasants.begin(),
- _mruPeasants.end(),
- [peasantID](auto&& other) {
- return peasantID == other.PeasantID();
- });
-
- if (result != std::end(_mruPeasants))
+ if (peasantIds.size() == 0)
{
- TraceLoggingWrite(g_hRemotingProvider,
- "Monarch_RemovedPeasantFromDesktop",
- TraceLoggingUInt64(peasantID, "peasantID", "The ID of the peasant"),
- TraceLoggingGuid(result->DesktopID(), "desktopGuid", "The GUID of the previous desktop the window was on"),
- TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
- TraceLoggingKeyword(TIL_KEYWORD_TRACE));
-
- _mruPeasants.erase(result);
+ return;
}
+
+ std::unique_lock lock{ _mruPeasantsMutex };
+ auto partition = std::remove_if(_mruPeasants.begin(), _mruPeasants.end(), [&](const auto& p) {
+ const auto id = p.PeasantID();
+ // remove the element if it was found in the list to erase.
+ if (peasantIds.count(id) == 1)
+ {
+ TraceLoggingWrite(g_hRemotingProvider,
+ "Monarch_RemovedPeasantFromDesktop",
+ TraceLoggingUInt64(id, "peasantID", "The ID of the peasant"),
+ TraceLoggingGuid(p.DesktopID(), "desktopGuid", "The GUID of the previous desktop the window was on"),
+ TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
+ TraceLoggingKeyword(TIL_KEYWORD_TRACE));
+ return true;
+ }
+ return false;
+ });
+
+ // Remove everything that was in the list
+ _mruPeasants.erase(partition, _mruPeasants.end());
}
// Method Description:
// - Actually handle inserting the WindowActivatedArgs into our list of MRU windows.
+ // - NB: this takes a unique_lock on _mruPeasantsMutex.
// Arguments:
// - localArgs: an in-proc WindowActivatedArgs that we should add to our list of MRU windows.
// Return Value:
@@ -365,19 +415,22 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
// * Check all the current lists to look for this peasant.
// remove it from any where it exists.
- _clearOldMruEntries(localArgs->PeasantID());
+ _clearOldMruEntries({ localArgs->PeasantID() });
// * If the current desktop doesn't have a vector, add one.
const auto desktopGuid{ localArgs->DesktopID() };
- // * Add this args list. By using lower_bound with insert, we can get it
- // into exactly the right spot, without having to re-sort the whole
- // array.
- _mruPeasants.insert(std::lower_bound(_mruPeasants.begin(),
- _mruPeasants.end(),
- *localArgs,
- [](const auto& first, const auto& second) { return first.ActivatedTime() > second.ActivatedTime(); }),
- *localArgs);
+ {
+ std::unique_lock lock{ _mruPeasantsMutex };
+ // * Add this args list. By using lower_bound with insert, we can get it
+ // into exactly the right spot, without having to re-sort the whole
+ // array.
+ _mruPeasants.insert(std::lower_bound(_mruPeasants.begin(),
+ _mruPeasants.end(),
+ *localArgs,
+ [](const auto& first, const auto& second) { return first.ActivatedTime() > second.ActivatedTime(); }),
+ *localArgs);
+ }
TraceLoggingWrite(g_hRemotingProvider,
"Monarch_SetMostRecentPeasant",
@@ -391,6 +444,9 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
// Method Description:
// - Retrieves the ID of the MRU peasant window. If requested, will limit
// the search to windows that are on the current desktop.
+ // - NB: This method will hold a shared lock on _mruPeasantsMutex and
+ // potentially a unique_lock on _peasantsMutex at the same time.
+ // Separately it might hold a unique_lock on _mruPeasantsMutex.
// Arguments:
// - limitToCurrentDesktop: if true, only return the MRU peasant that's
// actually on the current desktop.
@@ -403,8 +459,13 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
// - the ID of the most recent peasant, otherwise 0 if we could not find one.
uint64_t Monarch::_getMostRecentPeasantID(const bool limitToCurrentDesktop, const bool ignoreQuakeWindow)
{
+ std::shared_lock lock{ _mruPeasantsMutex };
if (_mruPeasants.empty())
{
+ // unlock the mruPeasants mutex to make sure we can't deadlock here.
+ lock.unlock();
+ // Only need a shared lock for read
+ std::shared_lock peasantsLock{ _peasantsMutex };
// We haven't yet been told the MRU peasant. Just use the first one.
// This is just gonna be a random one, but really shouldn't happen
// in practice. The WindowManager should set the MRU peasant
@@ -445,15 +506,17 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
// - If it isn't on the current desktop, we'll loop again, on the
// following peasant.
// * If we don't care, then we'll just return that one.
- //
- // We're not just using an iterator because the contents of the list
- // might change while we're iterating here (if the peasant is dead we'll
- // remove it from the list).
- int positionInList = 0;
- while (_mruPeasants.cbegin() + positionInList < _mruPeasants.cend())
+ uint64_t result = 0;
+ std::unordered_set peasantsToErase{};
+ for (const auto& mruWindowArgs : _mruPeasants)
{
- const auto mruWindowArgs{ *(_mruPeasants.begin() + positionInList) };
- const auto peasant{ _getPeasant(mruWindowArgs.PeasantID()) };
+ // Try to get the peasant, but do not have _getPeasant clean up old
+ // _mruPeasants because we are iterating here.
+ // SAFETY: _getPeasant can take a unique_lock on _peasantsMutex if
+ // it detects a peasant is dead. Currently _getMostRecentPeasantId
+ // is the only method that holds a lock on both _mruPeasantsMutex and
+ // _peasantsMutex at the same time so there cannot be a deadlock here.
+ const auto peasant{ _getPeasant(mruWindowArgs.PeasantID(), false) };
if (!peasant)
{
TraceLoggingWrite(g_hRemotingProvider,
@@ -467,6 +530,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
// We'll go through the loop again. We removed the current one
// at positionInList, so the next one in positionInList will be
// a new, different peasant.
+ peasantsToErase.emplace(mruWindowArgs.PeasantID());
continue;
}
@@ -504,7 +568,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
"true if this window was in fact on the current desktop"),
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
- return mruWindowArgs.PeasantID();
+ result = mruWindowArgs.PeasantID();
+ break;
}
// If this window wasn't on the current desktop, another one
// might be. We'll increment positionInList below, and try
@@ -518,20 +583,30 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
- return mruWindowArgs.PeasantID();
+ result = mruWindowArgs.PeasantID();
+ break;
}
- positionInList++;
}
- // Here, we've checked all the windows, and none of them was both alive
- // and the most recent (on this desktop). Just return 0 - the caller
- // will use this to create a new window.
- TraceLoggingWrite(g_hRemotingProvider,
- "Monarch_getMostRecentPeasantID_NotFound",
- TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
- TraceLoggingKeyword(TIL_KEYWORD_TRACE));
+ lock.unlock();
- return 0;
+ if (peasantsToErase.size() > 0)
+ {
+ _clearOldMruEntries(peasantsToErase);
+ }
+
+ if (result == 0)
+ {
+ // Here, we've checked all the windows, and none of them was both alive
+ // and the most recent (on this desktop). Just return 0 - the caller
+ // will use this to create a new window.
+ TraceLoggingWrite(g_hRemotingProvider,
+ "Monarch_getMostRecentPeasantID_NotFound",
+ TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
+ TraceLoggingKeyword(TIL_KEYWORD_TRACE));
+ }
+
+ return result;
}
// Method Description:
@@ -855,7 +930,10 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
Windows::Foundation::Collections::IVectorView Monarch::GetPeasantInfos()
{
std::vector names;
- names.reserve(_peasants.size());
+ {
+ std::shared_lock lock{ _peasantsMutex };
+ names.reserve(_peasants.size());
+ }
const auto func = [&](const auto& id, const auto& p) -> void {
names.push_back({ id, p.WindowName(), p.ActiveTabTitle() });
diff --git a/src/cascadia/Remoting/Monarch.h b/src/cascadia/Remoting/Monarch.h
index 2e8e40aa1..7ec904499 100644
--- a/src/cascadia/Remoting/Monarch.h
+++ b/src/cascadia/Remoting/Monarch.h
@@ -7,6 +7,7 @@
#include "Peasant.h"
#include "../cascadia/inc/cppwinrt_utils.h"
#include "WindowActivatedArgs.h"
+#include
// We sure different GUIDs here depending on whether we're running a Release,
// Preview, or Dev build. This ensures that different installs don't
@@ -69,23 +70,29 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
private:
uint64_t _ourPID;
- uint64_t _nextPeasantID{ 1 };
- uint64_t _thisPeasantID{ 0 };
+ std::atomic _nextPeasantID{ 1 };
+ uint64_t _ourPeasantId{ 0 };
+
+ // When we're quitting we do not care as much about handling some events that we know will be triggered
+ std::atomic _quitting{ false };
winrt::com_ptr _desktopManager{ nullptr };
std::unordered_map _peasants;
-
std::vector _mruPeasants;
+ // These should not be locked at the same time to prevent deadlocks
+ // unless they are both shared_locks.
+ std::shared_mutex _peasantsMutex{};
+ std::shared_mutex _mruPeasantsMutex{};
- winrt::Microsoft::Terminal::Remoting::IPeasant _getPeasant(uint64_t peasantID);
+ winrt::Microsoft::Terminal::Remoting::IPeasant _getPeasant(uint64_t peasantID, bool clearMruPeasantOnFailure = true);
uint64_t _getMostRecentPeasantID(bool limitToCurrentDesktop, const bool ignoreQuakeWindow);
uint64_t _lookupPeasantIdForName(std::wstring_view name);
void _peasantWindowActivated(const winrt::Windows::Foundation::IInspectable& sender,
const winrt::Microsoft::Terminal::Remoting::WindowActivatedArgs& args);
void _doHandleActivatePeasant(const winrt::com_ptr& args);
- void _clearOldMruEntries(const uint64_t peasantID);
+ void _clearOldMruEntries(const std::unordered_set& peasantIds);
void _forAllPeasantsIgnoringTheDead(std::function callback,
std::function errorCallback);
@@ -107,6 +114,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
// returns false.
// - If any single peasant is dead, then we'll call onError and then add it to a
// list of peasants to clean up once the loop ends.
+ // - NB: this (separately) takes unique locks on _peasantsMutex and
+ // _mruPeasantsMutex.
// Arguments:
// - func: The function to call on each peasant
// - onError: The function to call if a peasant is dead.
@@ -119,44 +128,55 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
using R = std::invoke_result_t;
static constexpr auto IsVoid = std::is_void_v;
- std::vector peasantsToErase;
-
- for (const auto& [id, p] : _peasants)
+ std::unordered_set peasantsToErase;
{
- try
+ std::shared_lock lock{ _peasantsMutex };
+
+ for (const auto& [id, p] : _peasants)
{
- if constexpr (IsVoid)
+ try
{
- func(id, p);
- }
- else
- {
- if (!func(id, p))
+ if constexpr (IsVoid)
{
- break;
+ func(id, p);
+ }
+ else
+ {
+ if (!func(id, p))
+ {
+ break;
+ }
}
}
- }
- catch (const winrt::hresult_error& exception)
- {
- onError(id);
+ catch (const winrt::hresult_error& exception)
+ {
+ onError(id);
- if (exception.code() == 0x800706ba) // The RPC server is unavailable.
- {
- peasantsToErase.emplace_back(id);
- }
- else
- {
- LOG_CAUGHT_EXCEPTION();
- throw;
+ if (exception.code() == 0x800706ba) // The RPC server is unavailable.
+ {
+ peasantsToErase.emplace(id);
+ }
+ else
+ {
+ LOG_CAUGHT_EXCEPTION();
+ throw;
+ }
}
}
}
- for (const auto& id : peasantsToErase)
+ if (peasantsToErase.size() > 0)
{
- _peasants.erase(id);
- _clearOldMruEntries(id);
+ // Don't hold a lock on _peasants and _mruPeasants at the same
+ // time to avoid deadlocks.
+ {
+ std::unique_lock lock{ _peasantsMutex };
+ for (const auto& id : peasantsToErase)
+ {
+ _peasants.erase(id);
+ }
+ }
+ _clearOldMruEntries(peasantsToErase);
}
}
diff --git a/src/cascadia/Remoting/WindowManager.cpp b/src/cascadia/Remoting/WindowManager.cpp
index e3b85e0a2..9a71fcef0 100644
--- a/src/cascadia/Remoting/WindowManager.cpp
+++ b/src/cascadia/Remoting/WindowManager.cpp
@@ -324,6 +324,14 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
+ // If the peasant asks us to quit we should not try to act in future elections.
+ _peasant.QuitRequested([weakThis{ get_weak() }](auto&&, auto&&) {
+ if (auto wm = weakThis.get())
+ {
+ wm->_monarchWaitInterrupt.SetEvent();
+ }
+ });
+
return _peasant;
}
diff --git a/src/cascadia/TerminalApp/App.xaml b/src/cascadia/TerminalApp/App.xaml
index bc77872e3..251028dee 100644
--- a/src/cascadia/TerminalApp/App.xaml
+++ b/src/cascadia/TerminalApp/App.xaml
@@ -20,7 +20,8 @@
-
+
-
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
-
+
diff --git a/src/cascadia/TerminalApp/TerminalPage.xaml b/src/cascadia/TerminalApp/TerminalPage.xaml
index eea2039f6..b6a4676dd 100644
--- a/src/cascadia/TerminalApp/TerminalPage.xaml
+++ b/src/cascadia/TerminalApp/TerminalPage.xaml
@@ -9,10 +9,11 @@
xmlns:local="using:TerminalApp"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:mux="using:Microsoft.UI.Xaml.Controls"
+ Background="Transparent"
mc:Ignorable="d">
+ Background="Transparent">
diff --git a/src/cascadia/TerminalApp/TerminalTab.cpp b/src/cascadia/TerminalApp/TerminalTab.cpp
index f5e2ca206..53c75eb6f 100644
--- a/src/cascadia/TerminalApp/TerminalTab.cpp
+++ b/src/cascadia/TerminalApp/TerminalTab.cpp
@@ -1400,11 +1400,22 @@ namespace winrt::TerminalApp::implementation
deselectedTabBrush.Color(deselectedTabColor);
// currently if a tab has a custom color, a deselected state is
- // signified by using the same color with a bit ot transparency
+ // signified by using the same color with a bit of transparency
+ //
+ // Prior to MUX 2.7, we set TabViewItemHeaderBackground, but now we can
+ // use TabViewItem().Background() for that. HOWEVER,
+ // TabViewItem().Background() only sets the color of the tab background
+ // when the TabViewItem is unselected. So we still need to set the other
+ // properties ourselves.
+ TabViewItem().Background(deselectedTabBrush);
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderBackgroundSelected"), selectedTabBrush);
- TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderBackground"), deselectedTabBrush);
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderBackgroundPointerOver"), hoverTabBrush);
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderBackgroundPressed"), selectedTabBrush);
+
+ // TabViewItem().Foreground() unfortunately does not work for us. It
+ // sets the color for the text when the TabViewItem isn't selected, but
+ // not when it is hovered, pressed, dragged, or selected, so we'll need
+ // to just set them all anyways.
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderForeground"), fontBrush);
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderForegroundSelected"), fontBrush);
TabViewItem().Resources().Insert(winrt::box_value(L"TabViewItemHeaderForegroundPointerOver"), fontBrush);
@@ -1442,7 +1453,6 @@ namespace winrt::TerminalApp::implementation
void TerminalTab::_ClearTabBackgroundColor()
{
winrt::hstring keys[] = {
- L"TabViewItemHeaderBackground",
L"TabViewItemHeaderBackgroundSelected",
L"TabViewItemHeaderBackgroundPointerOver",
L"TabViewItemHeaderForeground",
@@ -1463,6 +1473,9 @@ namespace winrt::TerminalApp::implementation
}
}
+ // Clear out the Background.
+ TabViewItem().Background(nullptr);
+
_RefreshVisualState();
_colorCleared();
}
@@ -1487,7 +1500,7 @@ namespace winrt::TerminalApp::implementation
// -
void TerminalTab::_RefreshVisualState()
{
- if (_focusState != FocusState::Unfocused)
+ if (TabViewItem().IsSelected())
{
VisualStateManager::GoToState(TabViewItem(), L"Normal", true);
VisualStateManager::GoToState(TabViewItem(), L"Selected", true);
diff --git a/src/cascadia/TerminalApp/dll/TerminalApp.vcxproj b/src/cascadia/TerminalApp/dll/TerminalApp.vcxproj
index 5f9d3f7c7..a5d865776 100644
--- a/src/cascadia/TerminalApp/dll/TerminalApp.vcxproj
+++ b/src/cascadia/TerminalApp/dll/TerminalApp.vcxproj
@@ -89,13 +89,13 @@
-
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
-
+
diff --git a/src/cascadia/TerminalApp/packages.config b/src/cascadia/TerminalApp/packages.config
index 9de6f1b8d..78467467c 100644
--- a/src/cascadia/TerminalApp/packages.config
+++ b/src/cascadia/TerminalApp/packages.config
@@ -1,6 +1,6 @@
-
+
diff --git a/src/cascadia/TerminalConnection/ConptyConnection.cpp b/src/cascadia/TerminalConnection/ConptyConnection.cpp
index 5c2373fd2..b6ad2ce7f 100644
--- a/src/cascadia/TerminalConnection/ConptyConnection.cpp
+++ b/src/cascadia/TerminalConnection/ConptyConnection.cpp
@@ -16,6 +16,10 @@
#include "LibraryResources.h"
using namespace ::Microsoft::Console;
+using namespace std::string_view_literals;
+
+// Format is: "DecimalResult (HexadecimalForm)"
+static constexpr auto _errorFormat = L"{0} ({0:#010x})"sv;
// Notes:
// There is a number of ways that the Conpty connection can be terminated (voluntarily or not):
@@ -417,7 +421,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
const auto hr = wil::ResultFromCaughtException();
winrt::hstring failureText{ fmt::format(std::wstring_view{ RS_(L"ProcessFailedToLaunch") },
- gsl::narrow_cast(hr),
+ fmt::format(_errorFormat, hr),
_commandline) };
_TerminalOutputHandlers(failureText);
@@ -444,7 +448,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
{
try
{
- winrt::hstring exitText{ fmt::format(std::wstring_view{ RS_(L"ProcessExited") }, status) };
+ winrt::hstring exitText{ fmt::format(std::wstring_view{ RS_(L"ProcessExited") }, fmt::format(_errorFormat, status)) };
_TerminalOutputHandlers(L"\r\n");
_TerminalOutputHandlers(exitText);
}
diff --git a/src/cascadia/TerminalConnection/Resources/en-US/Resources.resw b/src/cascadia/TerminalConnection/Resources/en-US/Resources.resw
index d32f59269..7af3cf590 100644
--- a/src/cascadia/TerminalConnection/Resources/en-US/Resources.resw
+++ b/src/cascadia/TerminalConnection/Resources/en-US/Resources.resw
@@ -205,15 +205,15 @@
[process exited with code {0}]
- The first argument {0} is the (positive) error code of the process. When there is no error, the number ZERO will be displayed.
+ The first argument {0} is the error code of the process. When there is no error, the number ZERO will be displayed.
- [error {0:#08x} when launching `{1}']
- The first argument {0...} is the hexadecimal error code. The second argument {1} is the user-specified path to a program.
+ [error {0} when launching `{1}']
+ The first argument {0} is the error code. The second argument {1} is the user-specified path to a program.
If this string is broken to multiple lines, it will not be displayed properly.Could not access starting directory "{0}"The first argument {0} is a path to a directory on the filesystem, as provided by the user.
-
\ No newline at end of file
+
diff --git a/src/cascadia/TerminalConnection/TerminalConnection.vcxproj b/src/cascadia/TerminalConnection/TerminalConnection.vcxproj
index 5cfd57c40..f594bc46f 100644
--- a/src/cascadia/TerminalConnection/TerminalConnection.vcxproj
+++ b/src/cascadia/TerminalConnection/TerminalConnection.vcxproj
@@ -56,7 +56,9 @@
-
+
+ Designer
+
@@ -88,11 +90,11 @@
- $(IntDir)..\OpenConsoleProxy;%(AdditionalIncludeDirectories)
+ $(IntDir)..\OpenConsoleProxy;%(AdditionalIncludeDirectories)$(OpenConsoleCommonOutDir)\conptylib.lib;%(AdditionalDependencies)
-
+
\ No newline at end of file
diff --git a/src/cascadia/TerminalConnection/TerminalConnection.vcxproj.filters b/src/cascadia/TerminalConnection/TerminalConnection.vcxproj.filters
index 12a9cc6c4..a7d2f9092 100644
--- a/src/cascadia/TerminalConnection/TerminalConnection.vcxproj.filters
+++ b/src/cascadia/TerminalConnection/TerminalConnection.vcxproj.filters
@@ -32,6 +32,7 @@
+
diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp
index eac350c2a..e09eb93ae 100644
--- a/src/cascadia/TerminalControl/ControlCore.cpp
+++ b/src/cascadia/TerminalControl/ControlCore.cpp
@@ -276,7 +276,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// GH#5098: Inform the engine of the opacity of the default text background.
if (_settings.UseAcrylic())
{
- _renderEngine->SetDefaultTextBackgroundOpacity(::base::saturated_cast(_settings.TintOpacity()));
+ _renderEngine->SetDefaultTextBackgroundOpacity(::base::saturated_cast(_settings.Opacity()));
}
THROW_IF_FAILED(_renderEngine->Enable());
@@ -425,41 +425,17 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return;
}
- auto newOpacity = std::clamp(_settings.TintOpacity() + adjustment,
+ auto newOpacity = std::clamp(_settings.Opacity() + adjustment,
0.0,
1.0);
- if (_settings.UseAcrylic())
- {
- try
- {
- _settings.TintOpacity(newOpacity);
- if (newOpacity >= 1.0)
- {
- _settings.UseAcrylic(false);
- }
- else
- {
- // GH#5098: Inform the engine of the new opacity of the default text background.
- SetBackgroundOpacity(::base::saturated_cast(newOpacity));
- }
+ // GH#5098: Inform the engine of the new opacity of the default text background.
+ SetBackgroundOpacity(::base::saturated_cast(newOpacity));
- auto eventArgs = winrt::make_self(newOpacity);
- _TransparencyChangedHandlers(*this, *eventArgs);
- }
- CATCH_LOG();
- }
- else if (adjustment < 0)
- {
- _settings.UseAcrylic(true);
+ _settings.Opacity(newOpacity);
- //Setting initial opacity set to 1 to ensure smooth transition to acrylic during mouse scroll
- newOpacity = std::clamp(1.0 + adjustment, 0.0, 1.0);
- _settings.TintOpacity(newOpacity);
-
- auto eventArgs = winrt::make_self(newOpacity);
- _TransparencyChangedHandlers(*this, *eventArgs);
- }
+ auto eventArgs = winrt::make_self(newOpacity);
+ _TransparencyChangedHandlers(*this, *eventArgs);
}
void ControlCore::ToggleShaderEffects()
@@ -1003,6 +979,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
{
_terminal->WritePastedText(hstr);
_terminal->ClearSelection();
+ _renderer->TriggerSelection();
_terminal->TrySnapOnInput();
}
diff --git a/src/cascadia/TerminalControl/IControlAppearance.idl b/src/cascadia/TerminalControl/IControlAppearance.idl
index a0fa0a0ad..fd06bc853 100644
--- a/src/cascadia/TerminalControl/IControlAppearance.idl
+++ b/src/cascadia/TerminalControl/IControlAppearance.idl
@@ -13,6 +13,7 @@ namespace Microsoft.Terminal.Control
Windows.UI.Xaml.VerticalAlignment BackgroundImageVerticalAlignment;
Boolean IntenseIsBold;
// IntenseIsBright is in Core Appearance
+ Double Opacity;
// Experimental settings
Boolean RetroTerminalEffect;
diff --git a/src/cascadia/TerminalControl/IControlSettings.idl b/src/cascadia/TerminalControl/IControlSettings.idl
index 56aab7395..1b67df91f 100644
--- a/src/cascadia/TerminalControl/IControlSettings.idl
+++ b/src/cascadia/TerminalControl/IControlSettings.idl
@@ -29,7 +29,6 @@ namespace Microsoft.Terminal.Control
String ProfileName;
Boolean UseAcrylic;
- Double TintOpacity;
ScrollbarState ScrollState;
String FontFace;
diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp
index 115f9afc5..fc74dd0a9 100644
--- a/src/cascadia/TerminalControl/TermControl.cpp
+++ b/src/cascadia/TerminalControl/TermControl.cpp
@@ -428,6 +428,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// -
void TermControl::_InitializeBackgroundBrush()
{
+ auto appearance = _settings.try_as();
if (_settings.UseAcrylic())
{
// See if we've already got an acrylic background brush
@@ -449,7 +450,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
acrylic.TintColor(bgColor);
// Apply brush settings
- acrylic.TintOpacity(_settings.TintOpacity());
+ acrylic.TintOpacity(appearance.Opacity());
// Apply brush to control if it's not already there
if (RootGrid().Background() != acrylic)
@@ -458,15 +459,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
// GH#5098: Inform the engine of the new opacity of the default text background.
- _core.SetBackgroundOpacity(::base::saturated_cast(_settings.TintOpacity()));
+ _core.SetBackgroundOpacity(::base::saturated_cast(appearance.Opacity()));
}
else
{
Media::SolidColorBrush solidColor{};
+ solidColor.Opacity(_settings.Opacity());
RootGrid().Background(solidColor);
// GH#5098: Inform the engine of the new opacity of the default text background.
- _core.SetBackgroundOpacity(1.0f);
+ _core.SetBackgroundOpacity(appearance.Opacity());
}
}
@@ -497,7 +499,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
else if (auto solidColor = RootGrid().Background().try_as())
{
+ const auto originalOpacity = solidColor.Opacity();
solidColor.Color(bg);
+ solidColor.Opacity(originalOpacity);
}
}
}
diff --git a/src/cascadia/TerminalControl/TermControl.xaml b/src/cascadia/TerminalControl/TermControl.xaml
index 94aa92c5f..663ccf7ce 100644
--- a/src/cascadia/TerminalControl/TermControl.xaml
+++ b/src/cascadia/TerminalControl/TermControl.xaml
@@ -14,6 +14,7 @@
d:DesignWidth="1024"
AllowDrop="True"
AllowFocusOnInteraction="True"
+ Background="Transparent"
CharacterReceived="_CharacterHandler"
DragOver="_DragOverHandler"
Drop="_DragDropHandler"
diff --git a/src/cascadia/TerminalSettingsEditor/MainPage.xaml b/src/cascadia/TerminalSettingsEditor/MainPage.xaml
index 9576102a1..9d24ac109 100644
--- a/src/cascadia/TerminalSettingsEditor/MainPage.xaml
+++ b/src/cascadia/TerminalSettingsEditor/MainPage.xaml
@@ -8,6 +8,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
+ Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
mc:Ignorable="d">
diff --git a/src/cascadia/TerminalSettingsEditor/Microsoft.Terminal.Settings.Editor.vcxproj b/src/cascadia/TerminalSettingsEditor/Microsoft.Terminal.Settings.Editor.vcxproj
index e60fccb32..e4335126c 100644
--- a/src/cascadia/TerminalSettingsEditor/Microsoft.Terminal.Settings.Editor.vcxproj
+++ b/src/cascadia/TerminalSettingsEditor/Microsoft.Terminal.Settings.Editor.vcxproj
@@ -312,12 +312,12 @@
-
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
-
+
\ No newline at end of file
diff --git a/src/cascadia/TerminalSettingsEditor/Profiles.h b/src/cascadia/TerminalSettingsEditor/Profiles.h
index e1ceba5d0..54d7d4108 100644
--- a/src/cascadia/TerminalSettingsEditor/Profiles.h
+++ b/src/cascadia/TerminalSettingsEditor/Profiles.h
@@ -22,7 +22,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void SetAcrylicOpacityPercentageValue(double value)
{
- AcrylicOpacity(winrt::Microsoft::Terminal::Settings::Editor::Converters::PercentageValueToPercentage(value));
+ _profile.DefaultAppearance().Opacity(winrt::Microsoft::Terminal::Settings::Editor::Converters::PercentageValueToPercentage(value));
};
void SetPadding(double value)
@@ -66,7 +66,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
OBSERVABLE_PROJECTED_SETTING(_profile, TabColor);
OBSERVABLE_PROJECTED_SETTING(_profile, SuppressApplicationTitle);
OBSERVABLE_PROJECTED_SETTING(_profile, UseAcrylic);
- OBSERVABLE_PROJECTED_SETTING(_profile, AcrylicOpacity);
OBSERVABLE_PROJECTED_SETTING(_profile, ScrollState);
OBSERVABLE_PROJECTED_SETTING(_profile, Padding);
OBSERVABLE_PROJECTED_SETTING(_profile, Commandline);
@@ -78,6 +77,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
OBSERVABLE_PROJECTED_SETTING(_profile.DefaultAppearance(), Background);
OBSERVABLE_PROJECTED_SETTING(_profile.DefaultAppearance(), SelectionBackground);
OBSERVABLE_PROJECTED_SETTING(_profile.DefaultAppearance(), CursorColor);
+ OBSERVABLE_PROJECTED_SETTING(_profile.DefaultAppearance(), Opacity);
OBSERVABLE_PROJECTED_SETTING(_profile, HistorySize);
OBSERVABLE_PROJECTED_SETTING(_profile, SnapOnInput);
OBSERVABLE_PROJECTED_SETTING(_profile, AltGrAliasing);
diff --git a/src/cascadia/TerminalSettingsEditor/Profiles.idl b/src/cascadia/TerminalSettingsEditor/Profiles.idl
index 4ecc48899..482a19671 100644
--- a/src/cascadia/TerminalSettingsEditor/Profiles.idl
+++ b/src/cascadia/TerminalSettingsEditor/Profiles.idl
@@ -47,7 +47,7 @@ namespace Microsoft.Terminal.Settings.Editor
OBSERVABLE_PROJECTED_PROFILE_SETTING(Windows.Foundation.IReference, TabColor);
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, SuppressApplicationTitle);
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, UseAcrylic);
- OBSERVABLE_PROJECTED_PROFILE_SETTING(Double, AcrylicOpacity);
+ OBSERVABLE_PROJECTED_PROFILE_SETTING(Double, Opacity);
OBSERVABLE_PROJECTED_PROFILE_SETTING(Microsoft.Terminal.Control.ScrollbarState, ScrollState);
OBSERVABLE_PROJECTED_PROFILE_SETTING(String, Padding);
OBSERVABLE_PROJECTED_PROFILE_SETTING(String, Commandline);
@@ -109,6 +109,6 @@ namespace Microsoft.Terminal.Settings.Editor
IInspectable CurrentScrollState;
Windows.Foundation.Collections.IObservableVector ScrollStateList { get; };
- Windows.UI.Xaml.Controls.Slider AcrylicOpacitySlider { get; };
+ Windows.UI.Xaml.Controls.Slider OpacitySlider { get; };
}
}
diff --git a/src/cascadia/TerminalSettingsEditor/Profiles.xaml b/src/cascadia/TerminalSettingsEditor/Profiles.xaml
index 5e11e2450..24e6a7fe1 100644
--- a/src/cascadia/TerminalSettingsEditor/Profiles.xaml
+++ b/src/cascadia/TerminalSettingsEditor/Profiles.xaml
@@ -238,11 +238,33 @@
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw
index 4c39ba4d1..a21ae08e3 100644
--- a/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw
+++ b/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw
@@ -495,6 +495,14 @@
Sets the transparency of the window.A description for what the "acrylic opacity" setting does. Presented near "Profile_AcrylicOpacity.Header".
+
+ Background Opacity
+ Header for a control to determine the level of opacity for the background of the control. The user can choose to make the background of the app more or less opaque.
+
+
+ Sets the transparency of the window.
+ A description for what the "opacity" setting does. Presented near "Profile_Opacity.Header".
+
AdvancedHeader for a sub-page of profile settings focused on more advanced scenarios.
@@ -986,6 +994,10 @@
AcrylicHeader for a group of settings related to the acrylic texture rendering on the background of the app.
+
+ Transparency
+ Header for a group of settings related to transparency, including the acrylic texture rendering on the background of the app.
+
Background imageHeader for a group of settings that control the image presented on the background of the app. Presented near "Profile_BackgroundImage" and other keys starting with "Profile_BackgroundImage".
diff --git a/src/cascadia/TerminalSettingsEditor/packages.config b/src/cascadia/TerminalSettingsEditor/packages.config
index ecf244764..bd1e02e27 100644
--- a/src/cascadia/TerminalSettingsEditor/packages.config
+++ b/src/cascadia/TerminalSettingsEditor/packages.config
@@ -1,5 +1,5 @@
-
+
diff --git a/src/cascadia/TerminalSettingsModel/AppearanceConfig.cpp b/src/cascadia/TerminalSettingsModel/AppearanceConfig.cpp
index 67eb279ea..1f8c88758 100644
--- a/src/cascadia/TerminalSettingsModel/AppearanceConfig.cpp
+++ b/src/cascadia/TerminalSettingsModel/AppearanceConfig.cpp
@@ -26,6 +26,8 @@ static constexpr std::string_view BackgroundImageAlignmentKey{ "backgroundImageA
static constexpr std::string_view RetroTerminalEffectKey{ "experimental.retroTerminalEffect" };
static constexpr std::string_view PixelShaderPathKey{ "experimental.pixelShaderPath" };
static constexpr std::string_view IntenseTextStyleKey{ "intenseTextStyle" };
+static constexpr std::string_view LegacyAcrylicTransparencyKey{ "acrylicOpacity" };
+static constexpr std::string_view OpacityKey{ "opacity" };
winrt::Microsoft::Terminal::Settings::Model::implementation::AppearanceConfig::AppearanceConfig(const winrt::weak_ref sourceProfile) :
_sourceProfile(sourceProfile)
@@ -50,6 +52,7 @@ winrt::com_ptr AppearanceConfig::CopyAppearance(const winrt::c
appearance->_RetroTerminalEffect = sourceAppearance->_RetroTerminalEffect;
appearance->_PixelShaderPath = sourceAppearance->_PixelShaderPath;
appearance->_IntenseTextStyle = sourceAppearance->_IntenseTextStyle;
+ appearance->_Opacity = sourceAppearance->_Opacity;
return appearance;
}
@@ -71,6 +74,7 @@ Json::Value AppearanceConfig::ToJson() const
JsonUtils::SetValueForKey(json, RetroTerminalEffectKey, _RetroTerminalEffect);
JsonUtils::SetValueForKey(json, PixelShaderPathKey, _PixelShaderPath);
JsonUtils::SetValueForKey(json, IntenseTextStyleKey, _IntenseTextStyle);
+ JsonUtils::SetValueForKey(json, OpacityKey, _Opacity, JsonUtils::OptionalConverter{});
return json;
}
@@ -102,6 +106,8 @@ void AppearanceConfig::LayerJson(const Json::Value& json)
JsonUtils::GetValueForKey(json, RetroTerminalEffectKey, _RetroTerminalEffect);
JsonUtils::GetValueForKey(json, PixelShaderPathKey, _PixelShaderPath);
JsonUtils::GetValueForKey(json, IntenseTextStyleKey, _IntenseTextStyle);
+ JsonUtils::GetValueForKey(json, LegacyAcrylicTransparencyKey, _Opacity);
+ JsonUtils::GetValueForKey(json, OpacityKey, _Opacity, JsonUtils::OptionalConverter{});
}
winrt::Microsoft::Terminal::Settings::Model::Profile AppearanceConfig::SourceProfile()
diff --git a/src/cascadia/TerminalSettingsModel/AppearanceConfig.h b/src/cascadia/TerminalSettingsModel/AppearanceConfig.h
index 7a0c47985..d28b9a92c 100644
--- a/src/cascadia/TerminalSettingsModel/AppearanceConfig.h
+++ b/src/cascadia/TerminalSettingsModel/AppearanceConfig.h
@@ -53,6 +53,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
INHERITABLE_SETTING(Model::IAppearanceConfig, bool, RetroTerminalEffect, false);
INHERITABLE_SETTING(Model::IAppearanceConfig, hstring, PixelShaderPath, L"");
INHERITABLE_SETTING(Model::IAppearanceConfig, Model::IntenseStyle, IntenseTextStyle, Model::IntenseStyle::Bright);
+ INHERITABLE_SETTING(Model::IAppearanceConfig, double, Opacity, 1.0);
private:
winrt::weak_ref _sourceProfile;
diff --git a/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp b/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp
index e98592ce4..c2b2fceb2 100644
--- a/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp
+++ b/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp
@@ -307,7 +307,6 @@ winrt::Microsoft::Terminal::Settings::Model::Profile CascadiaSettings::Duplicate
DUPLICATE_SETTING_MACRO(TabColor);
DUPLICATE_SETTING_MACRO(SuppressApplicationTitle);
DUPLICATE_SETTING_MACRO(UseAcrylic);
- DUPLICATE_SETTING_MACRO(AcrylicOpacity);
DUPLICATE_SETTING_MACRO(ScrollState);
DUPLICATE_SETTING_MACRO(Padding);
DUPLICATE_SETTING_MACRO(Commandline);
@@ -347,6 +346,7 @@ winrt::Microsoft::Terminal::Settings::Model::Profile CascadiaSettings::Duplicate
DUPLICATE_SETTING_MACRO_SUB(appearance, target, RetroTerminalEffect);
DUPLICATE_SETTING_MACRO_SUB(appearance, target, CursorShape);
DUPLICATE_SETTING_MACRO_SUB(appearance, target, CursorHeight);
+ DUPLICATE_SETTING_MACRO_SUB(appearance, target, Opacity);
}
// UnfocusedAppearance is treated as a single setting,
diff --git a/src/cascadia/TerminalSettingsModel/IAppearanceConfig.idl b/src/cascadia/TerminalSettingsModel/IAppearanceConfig.idl
index b33cf23e7..af89f55e8 100644
--- a/src/cascadia/TerminalSettingsModel/IAppearanceConfig.idl
+++ b/src/cascadia/TerminalSettingsModel/IAppearanceConfig.idl
@@ -51,5 +51,6 @@ namespace Microsoft.Terminal.Settings.Model
INHERITABLE_APPEARANCE_SETTING(Boolean, RetroTerminalEffect);
INHERITABLE_APPEARANCE_SETTING(String, PixelShaderPath);
INHERITABLE_APPEARANCE_SETTING(IntenseStyle, IntenseTextStyle);
+ INHERITABLE_APPEARANCE_SETTING(Double, Opacity);
};
}
diff --git a/src/cascadia/TerminalSettingsModel/Microsoft.Terminal.Settings.ModelLib.vcxproj b/src/cascadia/TerminalSettingsModel/Microsoft.Terminal.Settings.ModelLib.vcxproj
index 971096375..3c56c6620 100644
--- a/src/cascadia/TerminalSettingsModel/Microsoft.Terminal.Settings.ModelLib.vcxproj
+++ b/src/cascadia/TerminalSettingsModel/Microsoft.Terminal.Settings.ModelLib.vcxproj
@@ -241,12 +241,13 @@
-
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
-
+
-
-
\ No newline at end of file
+
+
diff --git a/src/cascadia/WindowsTerminal/packages.config b/src/cascadia/WindowsTerminal/packages.config
index f2f5c3f58..2b5489325 100644
--- a/src/cascadia/WindowsTerminal/packages.config
+++ b/src/cascadia/WindowsTerminal/packages.config
@@ -2,7 +2,7 @@
-
-
-
+
+
+
diff --git a/src/cascadia/WindowsTerminal/pch.h b/src/cascadia/WindowsTerminal/pch.h
index 01d2f04a7..59f24e949 100644
--- a/src/cascadia/WindowsTerminal/pch.h
+++ b/src/cascadia/WindowsTerminal/pch.h
@@ -67,6 +67,7 @@ Abstract:
#include
#include
#include
+#include
#include
#include
diff --git a/src/cascadia/WindowsTerminalUniversal/WindowsTerminalUniversal.vcxproj b/src/cascadia/WindowsTerminalUniversal/WindowsTerminalUniversal.vcxproj
index ab1d88cdb..6a0cf3d03 100644
--- a/src/cascadia/WindowsTerminalUniversal/WindowsTerminalUniversal.vcxproj
+++ b/src/cascadia/WindowsTerminalUniversal/WindowsTerminalUniversal.vcxproj
@@ -87,14 +87,14 @@
-
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
-
+
diff --git a/src/cascadia/ut_app/TerminalApp.UnitTests.vcxproj b/src/cascadia/ut_app/TerminalApp.UnitTests.vcxproj
index 6925f252e..32bafde87 100644
--- a/src/cascadia/ut_app/TerminalApp.UnitTests.vcxproj
+++ b/src/cascadia/ut_app/TerminalApp.UnitTests.vcxproj
@@ -92,7 +92,7 @@
x86$(Platform)
- <_MUXBinRoot>"$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.5.0-prerelease.201202003\runtimes\win10-$(Native-Platform)\native\"
+ <_MUXBinRoot>"$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\runtimes\win10-$(Native-Platform)\native\"