Compare commits
31 commits
main
...
release-1.
Author | SHA1 | Date | |
---|---|---|---|
7b775684e8 | |||
2c32f5a0fb | |||
f78008663a | |||
f94b98b488 | |||
f59bde9343 | |||
fc2751e654 | |||
928c87509d | |||
f7e3d889ff | |||
874819dceb | |||
39d16ba94c | |||
603122f247 | |||
b1a21533fe | |||
b19f449895 | |||
f218b0dc76 | |||
f90572d5a1 | |||
616a71dd23 | |||
f012cb92fc | |||
a43cf4ac2a | |||
b310307128 | |||
4fa0dc7ffa | |||
e551184666 | |||
6363dbae69 | |||
7965b39d7b | |||
120bb8ef5e | |||
c5acc3585c | |||
b0cb46f68b | |||
0480597abb | |||
d9ff7d610d | |||
3052ff77e2 | |||
694c73013f | |||
b8b137f0c7 |
3
.github/actions/spelling/expect/expect.txt
vendored
3
.github/actions/spelling/expect/expect.txt
vendored
|
@ -189,6 +189,7 @@ cacafire
|
|||
callee
|
||||
capslock
|
||||
CARETBLINKINGENABLED
|
||||
carlos
|
||||
CARRIAGERETURN
|
||||
cascadia
|
||||
cassert
|
||||
|
@ -2716,6 +2717,7 @@ wixproj
|
|||
wline
|
||||
wlinestream
|
||||
wmain
|
||||
wmemory
|
||||
WMSZ
|
||||
wnd
|
||||
WNDALLOC
|
||||
|
@ -2842,6 +2844,7 @@ YSize
|
|||
YSubstantial
|
||||
YVIRTUALSCREEN
|
||||
YWalk
|
||||
zamora
|
||||
ZCmd
|
||||
ZCtrl
|
||||
zsh
|
||||
|
|
|
@ -215,6 +215,22 @@
|
|||
"type": "integer"
|
||||
}
|
||||
]
|
||||
},
|
||||
"features": {
|
||||
"description": "Sets the DWrite font features for the given font. For example, { \"ss01\": 1, \"liga\":0 } will enable ss01 and disable ligatures.",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^(([A-Za-z0-9]){4})$": { "type": "integer" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"axes": {
|
||||
"description": "Sets the DWrite font axes for the given font. For example, { \"wght\": 200 } will set the font weight to 200.",
|
||||
"type": "object",
|
||||
"patternProperties": {
|
||||
"^([A-Za-z]{4})$": { "type": "number" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
|
@ -299,7 +315,8 @@
|
|||
"down",
|
||||
"previous",
|
||||
"nextInOrder",
|
||||
"previousInOrder"
|
||||
"previousInOrder",
|
||||
"first"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
|
@ -1215,14 +1232,14 @@
|
|||
"type": [ "integer", "string" ],
|
||||
"deprecated": true
|
||||
},
|
||||
"minimizeToTray": {
|
||||
"minimizeToNotificationArea": {
|
||||
"default": "false",
|
||||
"description": "When set to true, minimizing a Terminal window will no longer appear in the taskbar. Instead, a Terminal icon will appear in the system tray through which the user can access their windows.",
|
||||
"description": "When set to true, minimizing a Terminal window will no longer appear in the taskbar. Instead, a Terminal icon will appear in the notification area through which the user can access their windows.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"alwaysShowTrayIcon": {
|
||||
"alwaysShowNotificationIcon": {
|
||||
"default": "false",
|
||||
"description": "When set to true, the Terminal's tray icon will always be shown in the system tray.",
|
||||
"description": "When set to true, the Terminal's notification icon will always be shown in the notification area.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"actions": {
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -8,5 +8,5 @@ Please consult the [license](https://raw.githubusercontent.com/microsoft/cascadi
|
|||
|
||||
### Fonts Included
|
||||
|
||||
* Cascadia Code, Cascadia Mono (2106.17)
|
||||
* from microsoft/cascadia-code@fb0bce69c1c12f6c298b8bc1c1d181868f5daa9a
|
||||
* Cascadia Code, Cascadia Mono (2108.26)
|
||||
* from microsoft/cascadia-code@f91d08f703ee61cf4ae936b9700ca974de2748fe
|
||||
|
|
|
@ -12,6 +12,16 @@
|
|||
<EventProvider Id="EventProvider_TerminalWin32Host" Name="56c06166-2e2e-5f4d-7ff3-74f4b78c87d6" />
|
||||
<EventProvider Id="EventProvider_TerminalRemoting" Name="d6f04aad-629f-539a-77c1-73f5c3e4aa7b" />
|
||||
<EventProvider Id="EventProvider_TerminalDirectX" Name="c93e739e-ae50-5a14-78e7-f171e947535d" />
|
||||
<EventProvider Id="EventProvider_TerminalUIA" Name="e7ebce59-2161-572d-b263-2f16a6afb9e5"/>
|
||||
<!-- Console providers here -->
|
||||
<EventProvider Id="EventProvider-Microsoft.Windows.Console.Launcher" Name="770aa552-671a-5e97-579b-151709ec0dbd"/>
|
||||
<EventProvider Id="EventProvider-Microsoft.Windows.Console.Host" Name="fe1ff234-1f09-50a8-d38d-c44fab43e818"/>
|
||||
<EventProvider Id="EventProvider-Microsoft.Windows.Console.Server" Name="1A541C01-589A-496E-85A7-A9E02170166D"/>
|
||||
<EventProvider Id="EventProvider-Microsoft.Windows.Console.VirtualTerminal.Parser" Name="c9ba2a84-d3ca-5e19-2bd6-776a0910cb9d"/>
|
||||
<EventProvider Id="EventProvider-Microsoft.Windows.Console.Render.VtEngine" Name="c9ba2a95-d3ca-5e19-2bd6-776a0910cb9d"/>
|
||||
<EventProvider Id="EventProvider-Microsoft.Windows.Console.UIA" Name="e7ebce59-2161-572d-b263-2f16a6afb9e5"/>
|
||||
|
||||
<!-- Profile for General Terminal logging -->
|
||||
<Profile Id="Terminal.Verbose.File" Name="Terminal" Description="Terminal" LoggingMode="File" DetailLevel="Verbose">
|
||||
<Collectors>
|
||||
<EventCollectorId Value="EventCollector_Terminal">
|
||||
|
@ -23,6 +33,7 @@
|
|||
<EventProviderId Value="EventProvider_TerminalWin32Host" />
|
||||
<EventProviderId Value="EventProvider_TerminalRemoting" />
|
||||
<EventProviderId Value="EventProvider_TerminalDirectX" />
|
||||
<EventProviderId Value="EventProvider_TerminalUIA" />
|
||||
</EventProviders>
|
||||
</EventCollectorId>
|
||||
</Collectors>
|
||||
|
@ -30,5 +41,27 @@
|
|||
<Profile Id="Terminal.Light.File" Name="Terminal" Description="Terminal" Base="Terminal.Verbose.File" LoggingMode="File" DetailLevel="Light" />
|
||||
<Profile Id="Terminal.Verbose.Memory" Name="Terminal" Description="Terminal" Base="Terminal.Verbose.File" LoggingMode="Memory" DetailLevel="Verbose" />
|
||||
<Profile Id="Terminal.Light.Memory" Name="Terminal" Description="Terminal" Base="Terminal.Verbose.File" LoggingMode="Memory" DetailLevel="Light" />
|
||||
|
||||
<!-- Profile for DefTerm logging. Includes some conhost logging. -->
|
||||
<Profile Id="DefTerm.Verbose.File" Name="DefTerm" Description="DefTerm" LoggingMode="File" DetailLevel="Verbose">
|
||||
<Collectors>
|
||||
<EventCollectorId Value="EventCollector_Terminal">
|
||||
<EventProviders>
|
||||
<EventProviderId Value="EventProvider_TerminalControl" />
|
||||
<EventProviderId Value="EventProvider_TerminalConnection" />
|
||||
<EventProviderId Value="EventProvider_TerminalSettingsModel" />
|
||||
<EventProviderId Value="EventProvider_TerminalApp" />
|
||||
<EventProviderId Value="EventProvider_TerminalWin32Host" />
|
||||
<EventProviderId Value="EventProvider_TerminalRemoting" />
|
||||
<EventProviderId Value="EventProvider-Microsoft.Windows.Console.Launcher" />
|
||||
<EventProviderId Value="EventProvider-Microsoft.Windows.Console.Host" />
|
||||
<EventProviderId Value="EventProvider-Microsoft.Windows.Console.Server" />
|
||||
</EventProviders>
|
||||
</EventCollectorId>
|
||||
</Collectors>
|
||||
</Profile>
|
||||
<Profile Id="DefTerm.Light.File" Name="DefTerm" Description="DefTerm" Base="DefTerm.Verbose.File" LoggingMode="File" DetailLevel="Light" />
|
||||
<Profile Id="DefTerm.Verbose.Memory" Name="DefTerm" Description="DefTerm" Base="DefTerm.Verbose.File" LoggingMode="Memory" DetailLevel="Verbose" />
|
||||
<Profile Id="DefTerm.Light.Memory" Name="DefTerm" Description="DefTerm" Base="DefTerm.Verbose.File" LoggingMode="Memory" DetailLevel="Light" />
|
||||
</Profiles>
|
||||
</WindowsPerformanceRecorder>
|
||||
</WindowsPerformanceRecorder>
|
||||
|
|
|
@ -74,7 +74,7 @@
|
|||
Enabled="false"
|
||||
DisplayName="ms-resource:AppName" />
|
||||
</uap5:Extension>
|
||||
<!-- <uap3:Extension Category="windows.appExtension">
|
||||
<uap3:Extension Category="windows.appExtension">
|
||||
<uap3:AppExtension Name="com.microsoft.windows.console.host"
|
||||
Id="OpenConsole"
|
||||
DisplayName="OpenConsole"
|
||||
|
@ -102,15 +102,15 @@
|
|||
<com:Interface Id="E686C757-9A35-4A1C-B3CE-0BCC8B5C69F4" ProxyStubClsid="3171DE52-6EFA-4AEF-8A9F-D02BD67E7A4F"/>
|
||||
<com:Interface Id="59D55CCE-FC8A-48B4-ACE8-0A9286C6557F" ProxyStubClsid="3171DE52-6EFA-4AEF-8A9F-D02BD67E7A4F"/>
|
||||
</com:ComInterface>
|
||||
</com:Extension> -->
|
||||
</com:Extension>
|
||||
<com:Extension Category="windows.comServer">
|
||||
<com:ComServer>
|
||||
<!-- <com:ExeServer DisplayName="OpenConsole" Executable="OpenConsole.exe">
|
||||
<com:ExeServer DisplayName="OpenConsole" Executable="OpenConsole.exe">
|
||||
<com:Class Id="2EACA947-7F5F-4CFA-BA87-8F7FBEEFBE69"/>
|
||||
</com:ExeServer>
|
||||
<com:ExeServer DisplayName="WindowsTerminal" Executable="WindowsTerminal.exe">
|
||||
<com:Class Id="E12CFF52-A866-4C77-9A90-F570A7AA2C6B"/>
|
||||
</com:ExeServer> -->
|
||||
</com:ExeServer>
|
||||
<com:SurrogateServer DisplayName="WindowsTerminalShellExt">
|
||||
<com:Class Id="9f156763-7844-4dc4-b2b1-901f640f5155" Path="WindowsTerminalShellExt.dll" ThreadingModel="STA"/>
|
||||
</com:SurrogateServer>
|
||||
|
|
|
@ -256,10 +256,14 @@ namespace SettingsModelLocalTests
|
|||
])" };
|
||||
|
||||
// complex command with key chords
|
||||
const std::string actionsString4{ R"([
|
||||
const std::string actionsString4A{ R"([
|
||||
{ "command": { "action": "adjustFontSize", "delta": 1 }, "keys": "ctrl+c" },
|
||||
{ "command": { "action": "adjustFontSize", "delta": 1 }, "keys": "ctrl+d" }
|
||||
])" };
|
||||
const std::string actionsString4B{ R"([
|
||||
{ "command": { "action": "findMatch", "direction": "next" }, "keys": "ctrl+shift+s" },
|
||||
{ "command": { "action": "findMatch", "direction": "prev" }, "keys": "ctrl+shift+r" }
|
||||
])" };
|
||||
|
||||
// command with name and icon and multiple key chords
|
||||
const std::string actionsString5{ R"([
|
||||
|
@ -372,7 +376,8 @@ namespace SettingsModelLocalTests
|
|||
RoundtripTest<implementation::ActionMap>(actionsString3);
|
||||
|
||||
Log::Comment(L"complex commands with key chords");
|
||||
RoundtripTest<implementation::ActionMap>(actionsString4);
|
||||
RoundtripTest<implementation::ActionMap>(actionsString4A);
|
||||
RoundtripTest<implementation::ActionMap>(actionsString4B);
|
||||
|
||||
Log::Comment(L"command with name and icon and multiple key chords");
|
||||
RoundtripTest<implementation::ActionMap>(actionsString5);
|
||||
|
|
|
@ -80,8 +80,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
|||
peasant.IdentifyWindowsRequested({ this, &Monarch::_identifyWindows });
|
||||
peasant.RenameRequested({ this, &Monarch::_renameRequested });
|
||||
|
||||
peasant.ShowTrayIconRequested([this](auto&&, auto&&) { _ShowTrayIconRequestedHandlers(*this, nullptr); });
|
||||
peasant.HideTrayIconRequested([this](auto&&, auto&&) { _HideTrayIconRequestedHandlers(*this, nullptr); });
|
||||
peasant.ShowNotificationIconRequested([this](auto&&, auto&&) { _ShowNotificationIconRequestedHandlers(*this, nullptr); });
|
||||
peasant.HideNotificationIconRequested([this](auto&&, auto&&) { _HideNotificationIconRequestedHandlers(*this, nullptr); });
|
||||
|
||||
_peasants[newPeasantsId] = peasant;
|
||||
|
||||
|
|
|
@ -56,8 +56,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
|||
Windows::Foundation::Collections::IMapView<uint64_t, winrt::hstring> GetPeasantNames();
|
||||
|
||||
TYPED_EVENT(FindTargetWindowRequested, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::FindTargetWindowArgs);
|
||||
TYPED_EVENT(ShowTrayIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(HideTrayIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(ShowNotificationIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(HideNotificationIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
|
||||
private:
|
||||
uint64_t _ourPID;
|
||||
|
|
|
@ -45,7 +45,7 @@ namespace Microsoft.Terminal.Remoting
|
|||
Windows.Foundation.Collections.IMapView<UInt64, String> GetPeasantNames { get; };
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<Object, FindTargetWindowArgs> FindTargetWindowRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> ShowTrayIconRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> HideTrayIconRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> ShowNotificationIconRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> HideNotificationIconRequested;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -226,34 +226,34 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
|||
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||
}
|
||||
|
||||
void Peasant::RequestShowTrayIcon()
|
||||
void Peasant::RequestShowNotificationIcon()
|
||||
{
|
||||
try
|
||||
{
|
||||
_ShowTrayIconRequestedHandlers(*this, nullptr);
|
||||
_ShowNotificationIconRequestedHandlers(*this, nullptr);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOG_CAUGHT_EXCEPTION();
|
||||
}
|
||||
TraceLoggingWrite(g_hRemotingProvider,
|
||||
"Peasant_RequestShowTrayIcon",
|
||||
"Peasant_RequestShowNotificationIcon",
|
||||
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||
}
|
||||
|
||||
void Peasant::RequestHideTrayIcon()
|
||||
void Peasant::RequestHideNotificationIcon()
|
||||
{
|
||||
try
|
||||
{
|
||||
_HideTrayIconRequestedHandlers(*this, nullptr);
|
||||
_HideNotificationIconRequestedHandlers(*this, nullptr);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOG_CAUGHT_EXCEPTION();
|
||||
}
|
||||
TraceLoggingWrite(g_hRemotingProvider,
|
||||
"Peasant_RequestHideTrayIcon",
|
||||
"Peasant_RequestHideNotificationIcon",
|
||||
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||
}
|
||||
|
|
|
@ -28,8 +28,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
|||
void RequestIdentifyWindows();
|
||||
void DisplayWindowId();
|
||||
void RequestRename(const winrt::Microsoft::Terminal::Remoting::RenameRequestArgs& args);
|
||||
void RequestShowTrayIcon();
|
||||
void RequestHideTrayIcon();
|
||||
void RequestShowNotificationIcon();
|
||||
void RequestHideNotificationIcon();
|
||||
|
||||
winrt::Microsoft::Terminal::Remoting::WindowActivatedArgs GetLastActivatedArgs();
|
||||
|
||||
|
@ -42,8 +42,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
|||
TYPED_EVENT(DisplayWindowIdRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(RenameRequested, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::RenameRequestArgs);
|
||||
TYPED_EVENT(SummonRequested, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::SummonWindowBehavior);
|
||||
TYPED_EVENT(ShowTrayIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(HideTrayIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(ShowNotificationIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(HideNotificationIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
|
||||
private:
|
||||
Peasant(const uint64_t testPID);
|
||||
|
|
|
@ -64,8 +64,8 @@ namespace Microsoft.Terminal.Remoting
|
|||
void RequestIdentifyWindows(); // Tells us to raise a IdentifyWindowsRequested
|
||||
void RequestRename(RenameRequestArgs args); // Tells us to raise a RenameRequested
|
||||
void Summon(SummonWindowBehavior behavior);
|
||||
void RequestShowTrayIcon();
|
||||
void RequestHideTrayIcon();
|
||||
void RequestShowNotificationIcon();
|
||||
void RequestHideNotificationIcon();
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<Object, WindowActivatedArgs> WindowActivated;
|
||||
event Windows.Foundation.TypedEventHandler<Object, CommandlineArgs> ExecuteCommandlineRequested;
|
||||
|
@ -73,8 +73,8 @@ namespace Microsoft.Terminal.Remoting
|
|||
event Windows.Foundation.TypedEventHandler<Object, Object> DisplayWindowIdRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, RenameRequestArgs> RenameRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, SummonWindowBehavior> SummonRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> ShowTrayIconRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> HideTrayIconRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> ShowNotificationIconRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> HideNotificationIconRequested;
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass Peasant : IPeasant
|
||||
|
|
|
@ -254,8 +254,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
|||
// window, and when the current monarch dies.
|
||||
|
||||
_monarch.FindTargetWindowRequested({ this, &WindowManager::_raiseFindTargetWindowRequested });
|
||||
_monarch.ShowTrayIconRequested([this](auto&&, auto&&) { _ShowTrayIconRequestedHandlers(*this, nullptr); });
|
||||
_monarch.HideTrayIconRequested([this](auto&&, auto&&) { _HideTrayIconRequestedHandlers(*this, nullptr); });
|
||||
_monarch.ShowNotificationIconRequested([this](auto&&, auto&&) { _ShowNotificationIconRequestedHandlers(*this, nullptr); });
|
||||
_monarch.HideNotificationIconRequested([this](auto&&, auto&&) { _HideNotificationIconRequestedHandlers(*this, nullptr); });
|
||||
|
||||
_BecameMonarchHandlers(*this, nullptr);
|
||||
}
|
||||
|
@ -513,7 +513,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
|||
|
||||
void WindowManager::SummonAllWindows()
|
||||
{
|
||||
if constexpr (Feature_TrayIcon::IsEnabled())
|
||||
if constexpr (Feature_NotificationIcon::IsEnabled())
|
||||
{
|
||||
_monarch.SummonAllWindows();
|
||||
}
|
||||
|
@ -527,28 +527,28 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
|||
}
|
||||
|
||||
// Method Description:
|
||||
// - Ask the monarch to show a tray icon.
|
||||
// - Ask the monarch to show a notification icon.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
winrt::fire_and_forget WindowManager::RequestShowTrayIcon()
|
||||
winrt::fire_and_forget WindowManager::RequestShowNotificationIcon()
|
||||
{
|
||||
co_await winrt::resume_background();
|
||||
_peasant.RequestShowTrayIcon();
|
||||
_peasant.RequestShowNotificationIcon();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Ask the monarch to hide its tray icon.
|
||||
// - Ask the monarch to hide its notification icon.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
winrt::fire_and_forget WindowManager::RequestHideTrayIcon()
|
||||
winrt::fire_and_forget WindowManager::RequestHideNotificationIcon()
|
||||
{
|
||||
auto strongThis{ get_strong() };
|
||||
co_await winrt::resume_background();
|
||||
_peasant.RequestHideTrayIcon();
|
||||
_peasant.RequestHideNotificationIcon();
|
||||
}
|
||||
|
||||
bool WindowManager::DoesQuakeWindowExist()
|
||||
|
|
|
@ -43,14 +43,14 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
|
|||
void SummonAllWindows();
|
||||
Windows::Foundation::Collections::IMapView<uint64_t, winrt::hstring> GetPeasantNames();
|
||||
|
||||
winrt::fire_and_forget RequestShowTrayIcon();
|
||||
winrt::fire_and_forget RequestHideTrayIcon();
|
||||
winrt::fire_and_forget RequestShowNotificationIcon();
|
||||
winrt::fire_and_forget RequestHideNotificationIcon();
|
||||
bool DoesQuakeWindowExist();
|
||||
|
||||
TYPED_EVENT(FindTargetWindowRequested, winrt::Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Remoting::FindTargetWindowArgs);
|
||||
TYPED_EVENT(BecameMonarch, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(ShowTrayIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(HideTrayIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(ShowNotificationIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(HideNotificationIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
|
||||
private:
|
||||
bool _shouldCreateWindow{ false };
|
||||
|
|
|
@ -13,13 +13,13 @@ namespace Microsoft.Terminal.Remoting
|
|||
Boolean IsMonarch { get; };
|
||||
void SummonWindow(SummonWindowSelectionArgs args);
|
||||
void SummonAllWindows();
|
||||
void RequestShowTrayIcon();
|
||||
void RequestHideTrayIcon();
|
||||
void RequestShowNotificationIcon();
|
||||
void RequestHideNotificationIcon();
|
||||
Boolean DoesQuakeWindowExist();
|
||||
Windows.Foundation.Collections.IMapView<UInt64, String> GetPeasantNames();
|
||||
event Windows.Foundation.TypedEventHandler<Object, FindTargetWindowArgs> FindTargetWindowRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> BecameMonarch;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> ShowTrayIconRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> HideTrayIconRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> ShowNotificationIconRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> HideNotificationIconRequested;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -399,8 +399,10 @@ static const std::map<std::string, FocusDirection> focusDirectionMap = {
|
|||
{ "right", FocusDirection::Right },
|
||||
{ "up", FocusDirection::Up },
|
||||
{ "down", FocusDirection::Down },
|
||||
{ "previous", FocusDirection::Previous },
|
||||
{ "nextInOrder", FocusDirection::NextInOrder },
|
||||
{ "previousInOrder", FocusDirection::PreviousInOrder },
|
||||
{ "first", FocusDirection::First },
|
||||
};
|
||||
|
||||
// Method Description:
|
||||
|
|
|
@ -353,6 +353,8 @@ namespace winrt::TerminalApp::implementation
|
|||
co_return ContentDialogResult::None;
|
||||
}
|
||||
|
||||
_dialog = dialog;
|
||||
|
||||
// IMPORTANT: This is necessary as documented in the ContentDialog MSDN docs.
|
||||
// Since we're hosting the dialog in a Xaml island, we need to connect it to the
|
||||
// xaml tree somehow.
|
||||
|
@ -390,6 +392,16 @@ namespace winrt::TerminalApp::implementation
|
|||
// be released so another can be shown
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Dismiss the (only) visible ContentDialog
|
||||
void AppLogic::DismissDialog()
|
||||
{
|
||||
if (auto localDialog = std::exchange(_dialog, nullptr))
|
||||
{
|
||||
localDialog.Hide();
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Displays a dialog for errors found while loading or validating the
|
||||
// settings. Uses the resources under the provided title and content keys
|
||||
|
@ -1442,9 +1454,9 @@ namespace winrt::TerminalApp::implementation
|
|||
return _root->IsQuakeWindow();
|
||||
}
|
||||
|
||||
bool AppLogic::GetMinimizeToTray()
|
||||
bool AppLogic::GetMinimizeToNotificationArea()
|
||||
{
|
||||
if constexpr (Feature_TrayIcon::IsEnabled())
|
||||
if constexpr (Feature_NotificationIcon::IsEnabled())
|
||||
{
|
||||
if (!_loadedInitialSettings)
|
||||
{
|
||||
|
@ -1452,7 +1464,7 @@ namespace winrt::TerminalApp::implementation
|
|||
LoadSettings();
|
||||
}
|
||||
|
||||
return _settings.GlobalSettings().MinimizeToTray();
|
||||
return _settings.GlobalSettings().MinimizeToNotificationArea();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1460,9 +1472,9 @@ namespace winrt::TerminalApp::implementation
|
|||
}
|
||||
}
|
||||
|
||||
bool AppLogic::GetAlwaysShowTrayIcon()
|
||||
bool AppLogic::GetAlwaysShowNotificationIcon()
|
||||
{
|
||||
if constexpr (Feature_TrayIcon::IsEnabled())
|
||||
if constexpr (Feature_NotificationIcon::IsEnabled())
|
||||
{
|
||||
if (!_loadedInitialSettings)
|
||||
{
|
||||
|
@ -1470,7 +1482,7 @@ namespace winrt::TerminalApp::implementation
|
|||
LoadSettings();
|
||||
}
|
||||
|
||||
return _settings.GlobalSettings().AlwaysShowTrayIcon();
|
||||
return _settings.GlobalSettings().AlwaysShowNotificationIcon();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -92,10 +92,11 @@ namespace winrt::TerminalApp::implementation
|
|||
|
||||
winrt::TerminalApp::TaskbarState TaskbarState();
|
||||
|
||||
bool GetMinimizeToTray();
|
||||
bool GetAlwaysShowTrayIcon();
|
||||
bool GetMinimizeToNotificationArea();
|
||||
bool GetAlwaysShowNotificationIcon();
|
||||
|
||||
winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::UI::Xaml::Controls::ContentDialogResult> ShowDialog(winrt::Windows::UI::Xaml::Controls::ContentDialog dialog);
|
||||
void DismissDialog();
|
||||
|
||||
Windows::Foundation::Collections::IMapView<Microsoft::Terminal::Control::KeyChord, Microsoft::Terminal::Settings::Model::Command> GlobalHotkeys();
|
||||
|
||||
|
@ -120,6 +121,7 @@ namespace winrt::TerminalApp::implementation
|
|||
bool _loadedInitialSettings = false;
|
||||
|
||||
std::shared_mutex _dialogLock;
|
||||
winrt::Windows::UI::Xaml::Controls::ContentDialog _dialog;
|
||||
|
||||
::TerminalApp::AppCommandlineArgs _appArgs;
|
||||
::TerminalApp::AppCommandlineArgs _settingsAppArgs;
|
||||
|
|
|
@ -70,8 +70,8 @@ namespace TerminalApp
|
|||
|
||||
TaskbarState TaskbarState{ get; };
|
||||
|
||||
Boolean GetMinimizeToTray();
|
||||
Boolean GetAlwaysShowTrayIcon();
|
||||
Boolean GetMinimizeToNotificationArea();
|
||||
Boolean GetAlwaysShowNotificationIcon();
|
||||
|
||||
FindTargetWindowResult FindTargetWindow(String[] args);
|
||||
|
||||
|
@ -80,6 +80,7 @@ namespace TerminalApp
|
|||
// See IDialogPresenter and TerminalPage's DialogPresenter for more
|
||||
// information.
|
||||
Windows.Foundation.IAsyncOperation<Windows.UI.Xaml.Controls.ContentDialogResult> ShowDialog(Windows.UI.Xaml.Controls.ContentDialog dialog);
|
||||
void DismissDialog();
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<Object, Windows.UI.Xaml.UIElement> SetTitleBarContent;
|
||||
event Windows.Foundation.TypedEventHandler<Object, String> TitleChanged;
|
||||
|
|
|
@ -251,6 +251,27 @@ std::shared_ptr<Pane> Pane::NavigateDirection(const std::shared_ptr<Pane> source
|
|||
return PreviousPane(sourcePane);
|
||||
}
|
||||
|
||||
if (direction == FocusDirection::First)
|
||||
{
|
||||
std::shared_ptr<Pane> firstPane = nullptr;
|
||||
WalkTree([&](auto p) {
|
||||
if (p->_IsLeaf())
|
||||
{
|
||||
firstPane = p;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
// Don't need to do any movement if we are the source and target pane.
|
||||
if (firstPane == sourcePane)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return firstPane;
|
||||
}
|
||||
|
||||
// We are left with directional traversal now
|
||||
// If the focus direction does not match the split direction, the source pane
|
||||
// and its neighbor must necessarily be contained within the same child.
|
||||
|
|
|
@ -653,11 +653,11 @@
|
|||
<data name="CommandPaletteMenuItem" xml:space="preserve">
|
||||
<value>Command Palette</value>
|
||||
</data>
|
||||
<data name="TrayIconFocusTerminal" xml:space="preserve">
|
||||
<data name="NotificationIconFocusTerminal" xml:space="preserve">
|
||||
<value>Focus Terminal</value>
|
||||
<comment>This is displayed as a label for the context menu item that focuses the terminal.</comment>
|
||||
</data>
|
||||
<data name="TrayIconWindowSubmenu" xml:space="preserve">
|
||||
<data name="NotificationIconWindowSubmenu" xml:space="preserve">
|
||||
<value>Windows</value>
|
||||
<comment>This is displayed as a label for the context menu item that holds the submenu of available windows.</comment>
|
||||
</data>
|
||||
|
@ -685,4 +685,14 @@
|
|||
<data name="DropPathTabSplit.Text" xml:space="preserve">
|
||||
<value>Split the window and start in given directory</value>
|
||||
</data>
|
||||
<data name="SetAsDefaultInfoBar.Message" xml:space="preserve">
|
||||
<value>Windows Terminal can be set as the default terminal application in your settings.</value>
|
||||
</data>
|
||||
<data name="InfoBarDismissButton.Content" xml:space="preserve">
|
||||
<value>Don't show again</value>
|
||||
</data>
|
||||
<data name="SetAsDefaultTip_OpenSettingsLink.Content" xml:space="preserve">
|
||||
<value>Open Settings</value>
|
||||
<comment>This is a call-to-action hyperlink; it will open the settings.</comment>
|
||||
</data>
|
||||
</root>
|
||||
|
|
|
@ -274,6 +274,8 @@ namespace winrt::TerminalApp::implementation
|
|||
_defaultPointerCursor = CoreWindow::GetForCurrentThread().PointerCursor();
|
||||
}
|
||||
CATCH_LOG();
|
||||
|
||||
ShowSetAsDefaultInfoBar();
|
||||
}
|
||||
|
||||
winrt::fire_and_forget TerminalPage::NewTerminalByDrop(winrt::Windows::UI::Xaml::DragEventArgs& e)
|
||||
|
@ -2709,11 +2711,38 @@ namespace winrt::TerminalApp::implementation
|
|||
// Method Description:
|
||||
// - Displays a dialog stating the "Touch Keyboard and Handwriting Panel
|
||||
// Service" is disabled.
|
||||
void TerminalPage::ShowKeyboardServiceWarning()
|
||||
void TerminalPage::ShowKeyboardServiceWarning() const
|
||||
{
|
||||
if (auto keyboardWarningInfoBar = FindName(L"KeyboardWarningInfoBar").try_as<MUX::Controls::InfoBar>())
|
||||
if (!_IsMessageDismissed(InfoBarMessage::KeyboardServiceWarning))
|
||||
{
|
||||
keyboardWarningInfoBar.IsOpen(true);
|
||||
if (const auto keyboardServiceWarningInfoBar = FindName(L"KeyboardServiceWarningInfoBar").try_as<MUX::Controls::InfoBar>())
|
||||
{
|
||||
keyboardServiceWarningInfoBar.IsOpen(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Displays a info popup guiding the user into setting their default terminal.
|
||||
void TerminalPage::ShowSetAsDefaultInfoBar() const
|
||||
{
|
||||
if (!CascadiaSettings::IsDefaultTerminalAvailable() || _IsMessageDismissed(InfoBarMessage::SetAsDefault))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// If the user has already configured any terminal for hand-off we
|
||||
// shouldn't inform them again about the possibility to do so.
|
||||
if (CascadiaSettings::IsDefaultTerminalSet())
|
||||
{
|
||||
_DismissMessage(InfoBarMessage::SetAsDefault);
|
||||
return;
|
||||
}
|
||||
|
||||
if (const auto infoBar = FindName(L"SetAsDefaultInfoBar").try_as<MUX::Controls::InfoBar>())
|
||||
{
|
||||
TraceLoggingWrite(g_hTerminalAppProvider, "SetAsDefaultTipPresented", TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES), TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance));
|
||||
infoBar.IsOpen(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3070,4 +3099,100 @@ namespace winrt::TerminalApp::implementation
|
|||
}
|
||||
return profile;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Persists the user's choice not to show information bar warning about "Touch keyboard and Handwriting Panel Service" disabled
|
||||
// Then hides this information buffer.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TerminalPage::_KeyboardServiceWarningInfoDismissHandler(const IInspectable& /*sender*/, const IInspectable& /*args*/) const
|
||||
{
|
||||
_DismissMessage(InfoBarMessage::KeyboardServiceWarning);
|
||||
if (const auto infoBar = FindName(L"KeyboardServiceWarningInfoBar").try_as<MUX::Controls::InfoBar>())
|
||||
{
|
||||
infoBar.IsOpen(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Persists the user's choice not to show the information bar warning about "Windows Terminal can be set as your default terminal application"
|
||||
// Then hides this information buffer.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TerminalPage::_SetAsDefaultDismissHandler(const IInspectable& /*sender*/, const IInspectable& /*args*/)
|
||||
{
|
||||
_DismissMessage(InfoBarMessage::SetAsDefault);
|
||||
if (const auto infoBar = FindName(L"SetAsDefaultInfoBar").try_as<MUX::Controls::InfoBar>())
|
||||
{
|
||||
infoBar.IsOpen(false);
|
||||
}
|
||||
|
||||
TraceLoggingWrite(g_hTerminalAppProvider, "SetAsDefaultTipDismissed", TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES), TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
|
||||
|
||||
_FocusCurrentTab(true);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Dismisses the Default Terminal tip and opens the settings.
|
||||
void TerminalPage::_SetAsDefaultOpenSettingsHandler(const IInspectable& /*sender*/, const IInspectable& /*args*/)
|
||||
{
|
||||
if (const auto infoBar = FindName(L"SetAsDefaultInfoBar").try_as<MUX::Controls::InfoBar>())
|
||||
{
|
||||
infoBar.IsOpen(false);
|
||||
}
|
||||
|
||||
TraceLoggingWrite(g_hTerminalAppProvider, "SetAsDefaultTipInteracted", TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES), TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
|
||||
|
||||
_OpenSettingsUI();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Checks whether information bar message was dismissed earlier (in the application state)
|
||||
// Arguments:
|
||||
// - message: message to look for in the state
|
||||
// Return Value:
|
||||
// - true, if the message was dismissed
|
||||
bool TerminalPage::_IsMessageDismissed(const InfoBarMessage& message)
|
||||
{
|
||||
if (const auto dismissedMessages{ ApplicationState::SharedInstance().DismissedMessages() })
|
||||
{
|
||||
for (const auto& dismissedMessage : dismissedMessages)
|
||||
{
|
||||
if (dismissedMessage == message)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Persists the user's choice to dismiss information bar message (in application state)
|
||||
// Arguments:
|
||||
// - message: message to dismiss
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TerminalPage::_DismissMessage(const InfoBarMessage& message)
|
||||
{
|
||||
const auto applicationState = ApplicationState::SharedInstance();
|
||||
std::vector<InfoBarMessage> messages;
|
||||
|
||||
if (const auto values = applicationState.DismissedMessages())
|
||||
{
|
||||
messages.resize(values.Size());
|
||||
values.GetMany(0, messages);
|
||||
}
|
||||
|
||||
if (std::none_of(messages.begin(), messages.end(), [&](const auto& m) { return m == message; }))
|
||||
{
|
||||
messages.emplace_back(message);
|
||||
}
|
||||
|
||||
applicationState.DismissedMessages(std::move(messages));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,7 +87,8 @@ namespace winrt::TerminalApp::implementation
|
|||
|
||||
winrt::TerminalApp::TaskbarState TaskbarState() const;
|
||||
|
||||
void ShowKeyboardServiceWarning();
|
||||
void ShowKeyboardServiceWarning() const;
|
||||
void ShowSetAsDefaultInfoBar() const;
|
||||
winrt::hstring KeyboardServiceDisabledText();
|
||||
|
||||
winrt::fire_and_forget IdentifyWindow();
|
||||
|
@ -360,6 +361,12 @@ namespace winrt::TerminalApp::implementation
|
|||
|
||||
winrt::Microsoft::Terminal::Settings::Model::Profile GetClosestProfileForDuplicationOfProfile(const winrt::Microsoft::Terminal::Settings::Model::Profile& profile) const noexcept;
|
||||
|
||||
void _KeyboardServiceWarningInfoDismissHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args) const;
|
||||
void _SetAsDefaultDismissHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args);
|
||||
void _SetAsDefaultOpenSettingsHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args);
|
||||
static bool _IsMessageDismissed(const winrt::Microsoft::Terminal::Settings::Model::InfoBarMessage& message);
|
||||
static void _DismissMessage(const winrt::Microsoft::Terminal::Settings::Model::InfoBarMessage& message);
|
||||
|
||||
#pragma region ActionHandlers
|
||||
// These are all defined in AppActionHandlers.cpp
|
||||
#define ON_ALL_ACTIONS(action) DECLARE_ACTION_HANDLER(action);
|
||||
|
|
|
@ -109,13 +109,34 @@
|
|||
PreviewKeyDown="_KeyDownHandler"
|
||||
Visibility="Collapsed" />
|
||||
|
||||
<mux:InfoBar x:Name="KeyboardWarningInfoBar"
|
||||
x:Load="False"
|
||||
IsClosable="True"
|
||||
IsIconVisible="True"
|
||||
IsOpen="False"
|
||||
Message="{x:Bind KeyboardServiceDisabledText, Mode=OneWay}"
|
||||
Severity="Warning" />
|
||||
<StackPanel>
|
||||
<mux:InfoBar x:Name="KeyboardServiceWarningInfoBar"
|
||||
x:Load="False"
|
||||
IsClosable="True"
|
||||
IsIconVisible="True"
|
||||
IsOpen="False"
|
||||
Message="{x:Bind KeyboardServiceDisabledText, Mode=OneWay}"
|
||||
Severity="Warning">
|
||||
<mux:InfoBar.ActionButton>
|
||||
<Button x:Uid="InfoBarDismissButton"
|
||||
Click="_KeyboardServiceWarningInfoDismissHandler" />
|
||||
</mux:InfoBar.ActionButton>
|
||||
</mux:InfoBar>
|
||||
|
||||
<mux:InfoBar x:Name="SetAsDefaultInfoBar"
|
||||
x:Uid="SetAsDefaultInfoBar"
|
||||
x:Load="False"
|
||||
CloseButtonClick="_SetAsDefaultDismissHandler"
|
||||
IsClosable="True"
|
||||
IsIconVisible="True"
|
||||
IsOpen="False"
|
||||
Severity="Informational">
|
||||
<mux:InfoBar.ActionButton>
|
||||
<HyperlinkButton x:Uid="SetAsDefaultTip_OpenSettingsLink"
|
||||
Click="_SetAsDefaultOpenSettingsHandler" />
|
||||
</mux:InfoBar.ActionButton>
|
||||
</mux:InfoBar>
|
||||
</StackPanel>
|
||||
|
||||
<!--
|
||||
A TeachingTip with IsLightDismissEnabled="True" will immediately
|
||||
|
|
|
@ -99,29 +99,57 @@ static HRESULT _duplicateHandle(const HANDLE in, HANDLE& out) noexcept
|
|||
// from the registered handler event function.
|
||||
HRESULT CTerminalHandoff::EstablishPtyHandoff(HANDLE in, HANDLE out, HANDLE signal, HANDLE ref, HANDLE server, HANDLE client)
|
||||
{
|
||||
// Stash a local copy of _pfnHandoff before we stop listening.
|
||||
auto localPfnHandoff = _pfnHandoff;
|
||||
try
|
||||
{
|
||||
// Stash a local copy of _pfnHandoff before we stop listening.
|
||||
auto localPfnHandoff = _pfnHandoff;
|
||||
|
||||
// Because we are REGCLS_SINGLEUSE... we need to `CoRevokeClassObject` after we handle this ONE call.
|
||||
// COM does not automatically clean that up for us. We must do it.
|
||||
s_StopListening();
|
||||
// Because we are REGCLS_SINGLEUSE... we need to `CoRevokeClassObject` after we handle this ONE call.
|
||||
// COM does not automatically clean that up for us. We must do it.
|
||||
s_StopListening();
|
||||
|
||||
std::unique_lock lock{ _mtx };
|
||||
std::unique_lock lock{ _mtx };
|
||||
|
||||
// Report an error if no one registered a handoff function before calling this.
|
||||
RETURN_HR_IF_NULL(E_NOT_VALID_STATE, localPfnHandoff);
|
||||
// Report an error if no one registered a handoff function before calling this.
|
||||
THROW_HR_IF_NULL(E_NOT_VALID_STATE, localPfnHandoff);
|
||||
|
||||
// Duplicate the handles from what we received.
|
||||
// The contract with COM specifies that any HANDLEs we receive from the caller belong
|
||||
// to the caller and will be freed when we leave the scope of this method.
|
||||
// Making our own duplicate copy ensures they hang around in our lifetime.
|
||||
RETURN_IF_FAILED(_duplicateHandle(in, in));
|
||||
RETURN_IF_FAILED(_duplicateHandle(out, out));
|
||||
RETURN_IF_FAILED(_duplicateHandle(signal, signal));
|
||||
RETURN_IF_FAILED(_duplicateHandle(ref, ref));
|
||||
RETURN_IF_FAILED(_duplicateHandle(server, server));
|
||||
RETURN_IF_FAILED(_duplicateHandle(client, client));
|
||||
// Duplicate the handles from what we received.
|
||||
// The contract with COM specifies that any HANDLEs we receive from the caller belong
|
||||
// to the caller and will be freed when we leave the scope of this method.
|
||||
// Making our own duplicate copy ensures they hang around in our lifetime.
|
||||
THROW_IF_FAILED(_duplicateHandle(in, in));
|
||||
THROW_IF_FAILED(_duplicateHandle(out, out));
|
||||
THROW_IF_FAILED(_duplicateHandle(signal, signal));
|
||||
THROW_IF_FAILED(_duplicateHandle(ref, ref));
|
||||
THROW_IF_FAILED(_duplicateHandle(server, server));
|
||||
THROW_IF_FAILED(_duplicateHandle(client, client));
|
||||
|
||||
// Call registered handler from when we started listening.
|
||||
return localPfnHandoff(in, out, signal, ref, server, client);
|
||||
// Call registered handler from when we started listening.
|
||||
THROW_IF_FAILED(localPfnHandoff(in, out, signal, ref, server, client));
|
||||
|
||||
#pragma warning(suppress : 26477)
|
||||
TraceLoggingWrite(
|
||||
g_hTerminalConnectionProvider,
|
||||
"ReceiveTerminalHandoff_Success",
|
||||
TraceLoggingDescription("successfully received a terminal handoff"),
|
||||
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
|
||||
TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
const auto hr = wil::ResultFromCaughtException();
|
||||
|
||||
#pragma warning(suppress : 26477)
|
||||
TraceLoggingWrite(
|
||||
g_hTerminalConnectionProvider,
|
||||
"ReceiveTerminalHandoff_Failed",
|
||||
TraceLoggingDescription("failed while receiving a terminal handoff"),
|
||||
TraceLoggingHResult(hr),
|
||||
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
|
||||
TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
|
||||
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
#include "ConptyConnection.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <userenv.h>
|
||||
|
||||
#include "ConptyConnection.g.cpp"
|
||||
#include "CTerminalHandoff.h"
|
||||
|
@ -161,11 +160,8 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||
environment.clear();
|
||||
});
|
||||
|
||||
{
|
||||
const auto newEnvironmentBlock{ Utils::CreateEnvironmentBlock() };
|
||||
// Populate the environment map with the current environment.
|
||||
RETURN_IF_FAILED(Utils::UpdateEnvironmentMapW(environment, newEnvironmentBlock.get()));
|
||||
}
|
||||
// Populate the environment map with the current environment.
|
||||
RETURN_IF_FAILED(Utils::UpdateEnvironmentMapW(environment));
|
||||
|
||||
{
|
||||
// Convert connection Guid to string and ignore the enclosing '{}'.
|
||||
|
@ -369,6 +365,16 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||
// window is expecting it to be on the first layout.
|
||||
else
|
||||
{
|
||||
#pragma warning(suppress : 26477 26485 26494 26482 26446) // We don't control TraceLoggingWrite
|
||||
TraceLoggingWrite(
|
||||
g_hTerminalConnectionProvider,
|
||||
"ConPtyConnectedToDefterm",
|
||||
TraceLoggingDescription("Event emitted when ConPTY connection is started, for a defterm session"),
|
||||
TraceLoggingGuid(_guid, "SessionGuid", "The WT_SESSION's GUID"),
|
||||
TraceLoggingWideString(_clientName.c_str(), "Client", "The attached client process"),
|
||||
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
|
||||
TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance));
|
||||
|
||||
THROW_IF_FAILED(ConptyResizePseudoConsole(_hPC.get(), dimensions));
|
||||
}
|
||||
|
||||
|
|
|
@ -414,6 +414,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
// This is a scroll event that wasn't initiated by the terminal
|
||||
// itself - it was initiated by the mouse wheel, or the scrollbar.
|
||||
_terminal->UserScrollViewport(viewTop);
|
||||
|
||||
_updatePatternLocations->Run();
|
||||
}
|
||||
|
||||
void ControlCore::AdjustOpacity(const double adjustment)
|
||||
|
@ -1001,6 +1003,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
{
|
||||
_terminal->WritePastedText(hstr);
|
||||
_terminal->ClearSelection();
|
||||
_renderer->TriggerSelection();
|
||||
_terminal->TrySnapOnInput();
|
||||
}
|
||||
|
||||
|
|
|
@ -214,12 +214,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
}
|
||||
else if (_canSendVTMouseInput(modifiers))
|
||||
{
|
||||
const auto adjustment = _core->ScrollOffset() > 0 ? _core->BufferHeight() - _core->ScrollOffset() - _core->ViewHeight() : 0;
|
||||
// If the click happened outside the active region, just don't send any mouse event
|
||||
if (const auto adjustedY = terminalPosition.y() - adjustment; adjustedY >= 0)
|
||||
{
|
||||
_core->SendMouseEvent({ terminalPosition.x(), adjustedY }, pointerUpdateKind, modifiers, 0, toInternalMouseState(buttonState));
|
||||
}
|
||||
_sendMouseEventHelper(terminalPosition, pointerUpdateKind, modifiers, 0, buttonState);
|
||||
}
|
||||
else if (WI_IsFlagSet(buttonState, MouseButtonState::IsLeftButtonDown))
|
||||
{
|
||||
|
@ -287,7 +282,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
// Short-circuit isReadOnly check to avoid warning dialog
|
||||
if (focused && !_core->IsInReadOnlyMode() && _canSendVTMouseInput(modifiers))
|
||||
{
|
||||
_core->SendMouseEvent(terminalPosition, pointerUpdateKind, modifiers, 0, toInternalMouseState(buttonState));
|
||||
_sendMouseEventHelper(terminalPosition, pointerUpdateKind, modifiers, 0, buttonState);
|
||||
}
|
||||
// GH#4603 - don't modify the selection if the pointer press didn't
|
||||
// actually start _in_ the control bounds. Case in point - someone drags
|
||||
|
@ -370,7 +365,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
// Short-circuit isReadOnly check to avoid warning dialog
|
||||
if (!_core->IsInReadOnlyMode() && _canSendVTMouseInput(modifiers))
|
||||
{
|
||||
_core->SendMouseEvent(terminalPosition, pointerUpdateKind, modifiers, 0, toInternalMouseState(buttonState));
|
||||
_sendMouseEventHelper(terminalPosition, pointerUpdateKind, modifiers, 0, buttonState);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -420,11 +415,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
// here with a PointerPoint. However, as of #979, we don't have a
|
||||
// PointerPoint to work with. So, we're just going to do a
|
||||
// mousewheel event manually
|
||||
return _core->SendMouseEvent(terminalPosition,
|
||||
return _sendMouseEventHelper(terminalPosition,
|
||||
WM_MOUSEWHEEL,
|
||||
modifiers,
|
||||
::base::saturated_cast<short>(delta),
|
||||
toInternalMouseState(buttonState));
|
||||
buttonState);
|
||||
}
|
||||
|
||||
const auto ctrlPressed = modifiers.IsCtrlPressed();
|
||||
|
@ -600,6 +595,21 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
return til::point{ pixelPosition / fontSize };
|
||||
}
|
||||
|
||||
bool ControlInteractivity::_sendMouseEventHelper(const til::point terminalPosition,
|
||||
const unsigned int pointerUpdateKind,
|
||||
const ::Microsoft::Terminal::Core::ControlKeyStates modifiers,
|
||||
const SHORT wheelDelta,
|
||||
Control::MouseButtonState buttonState)
|
||||
{
|
||||
const auto adjustment = _core->ScrollOffset() > 0 ? _core->BufferHeight() - _core->ScrollOffset() - _core->ViewHeight() : 0;
|
||||
// If the click happened outside the active region, just don't send any mouse event
|
||||
if (const auto adjustedY = terminalPosition.y() - adjustment; adjustedY >= 0)
|
||||
{
|
||||
return _core->SendMouseEvent({ terminalPosition.x(), adjustedY }, pointerUpdateKind, modifiers, wheelDelta, toInternalMouseState(buttonState));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Creates an automation peer for the Terminal Control, enabling
|
||||
// accessibility on our control.
|
||||
|
|
|
@ -142,6 +142,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
void _sendPastedTextToConnection(std::wstring_view wstr);
|
||||
til::point _getTerminalPosition(const til::point& pixelPosition);
|
||||
|
||||
bool _sendMouseEventHelper(const til::point terminalPosition,
|
||||
const unsigned int pointerUpdateKind,
|
||||
const ::Microsoft::Terminal::Core::ControlKeyStates modifiers,
|
||||
const SHORT wheelDelta,
|
||||
Control::MouseButtonState buttonState);
|
||||
|
||||
friend class ControlUnitTests::ControlCoreTests;
|
||||
friend class ControlUnitTests::ControlInteractivityTests;
|
||||
};
|
||||
|
|
|
@ -43,6 +43,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
{
|
||||
_controlPadding = padding;
|
||||
}
|
||||
void InteractivityAutomationPeer::ParentProvider(AutomationPeer parentProvider)
|
||||
{
|
||||
_parentProvider = parentProvider;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Signals the ui automation client that the terminal's selection has
|
||||
|
@ -110,30 +114,21 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
// ScreenInfoUiaProvider doesn't actually use parameter, so just pass in nullptr
|
||||
THROW_IF_FAILED(_uiaProvider->RangeFromChild(/* IRawElementProviderSimple */ nullptr,
|
||||
&returnVal));
|
||||
|
||||
const auto parentProvider = this->ProviderFromPeer(*this);
|
||||
const auto xutr = winrt::make_self<XamlUiaTextRange>(returnVal, parentProvider);
|
||||
return xutr.as<XamlAutomation::ITextRangeProvider>();
|
||||
return _CreateXamlUiaTextRange(returnVal);
|
||||
}
|
||||
|
||||
XamlAutomation::ITextRangeProvider InteractivityAutomationPeer::RangeFromPoint(Windows::Foundation::Point screenLocation)
|
||||
{
|
||||
UIA::ITextRangeProvider* returnVal;
|
||||
THROW_IF_FAILED(_uiaProvider->RangeFromPoint({ screenLocation.X, screenLocation.Y }, &returnVal));
|
||||
|
||||
const auto parentProvider = this->ProviderFromPeer(*this);
|
||||
const auto xutr = winrt::make_self<XamlUiaTextRange>(returnVal, parentProvider);
|
||||
return xutr.as<XamlAutomation::ITextRangeProvider>();
|
||||
return _CreateXamlUiaTextRange(returnVal);
|
||||
}
|
||||
|
||||
XamlAutomation::ITextRangeProvider InteractivityAutomationPeer::DocumentRange()
|
||||
{
|
||||
UIA::ITextRangeProvider* returnVal;
|
||||
THROW_IF_FAILED(_uiaProvider->get_DocumentRange(&returnVal));
|
||||
|
||||
const auto parentProvider = this->ProviderFromPeer(*this);
|
||||
const auto xutr = winrt::make_self<XamlUiaTextRange>(returnVal, parentProvider);
|
||||
return xutr.as<XamlAutomation::ITextRangeProvider>();
|
||||
return _CreateXamlUiaTextRange(returnVal);
|
||||
}
|
||||
|
||||
XamlAutomation::SupportedTextSelection InteractivityAutomationPeer::SupportedTextSelection()
|
||||
|
@ -180,6 +175,20 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
}
|
||||
#pragma endregion
|
||||
|
||||
XamlAutomation::ITextRangeProvider InteractivityAutomationPeer::_CreateXamlUiaTextRange(UIA::ITextRangeProvider* returnVal) const
|
||||
{
|
||||
// LOAD-BEARING: use _parentProvider->ProviderFromPeer(_parentProvider) instead of this->ProviderFromPeer(*this).
|
||||
// Since we split the automation peer into TermControlAutomationPeer and InteractivityAutomationPeer,
|
||||
// using "this" returns null. This can cause issues with some UIA Client scenarios like any navigation in Narrator.
|
||||
const auto parent{ _parentProvider.get() };
|
||||
if (!parent)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
const auto xutr = winrt::make_self<XamlUiaTextRange>(returnVal, parent.ProviderFromPeer(parent));
|
||||
return xutr.as<XamlAutomation::ITextRangeProvider>();
|
||||
};
|
||||
|
||||
// Method Description:
|
||||
// - extracts the UiaTextRanges from the SAFEARRAY and converts them to Xaml ITextRangeProviders
|
||||
// Arguments:
|
||||
|
@ -194,11 +203,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
|
||||
std::vector<XamlAutomation::ITextRangeProvider> vec;
|
||||
vec.reserve(count);
|
||||
auto parentProvider = this->ProviderFromPeer(*this);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
auto xutr = make_self<XamlUiaTextRange>(providers[i].detach(), parentProvider);
|
||||
vec.emplace_back(xutr.as<XamlAutomation::ITextRangeProvider>());
|
||||
if (auto xutr = _CreateXamlUiaTextRange(providers[i].detach()))
|
||||
{
|
||||
vec.emplace_back(std::move(xutr));
|
||||
}
|
||||
}
|
||||
|
||||
com_array<XamlAutomation::ITextRangeProvider> result{ vec };
|
||||
|
|
|
@ -43,6 +43,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
|
||||
void SetControlBounds(const Windows::Foundation::Rect bounds);
|
||||
void SetControlPadding(const Core::Padding padding);
|
||||
void ParentProvider(Windows::UI::Xaml::Automation::Peers::AutomationPeer parentProvider);
|
||||
|
||||
#pragma region IUiaEventDispatcher
|
||||
void SignalSelectionChanged() override;
|
||||
|
@ -74,8 +75,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
TYPED_EVENT(CursorChanged, IInspectable, IInspectable);
|
||||
|
||||
private:
|
||||
Windows::UI::Xaml::Automation::Provider::ITextRangeProvider _CreateXamlUiaTextRange(::ITextRangeProvider* returnVal) const;
|
||||
|
||||
::Microsoft::WRL::ComPtr<::Microsoft::Terminal::TermControlUiaProvider> _uiaProvider;
|
||||
winrt::Microsoft::Terminal::Control::implementation::ControlInteractivity* _interactivity;
|
||||
weak_ref<Windows::UI::Xaml::Automation::Peers::AutomationPeer> _parentProvider;
|
||||
|
||||
til::rectangle _controlBounds{};
|
||||
til::rectangle _controlPadding{};
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Microsoft.Terminal.Control
|
||||
{
|
||||
[default_interface] runtimeclass InteractivityAutomationPeer :
|
||||
|
@ -10,6 +9,7 @@ namespace Microsoft.Terminal.Control
|
|||
|
||||
void SetControlBounds(Windows.Foundation.Rect bounds);
|
||||
void SetControlPadding(Microsoft.Terminal.Core.Padding padding);
|
||||
void ParentProvider(Windows.UI.Xaml.Automation.Peers.AutomationPeer parentProvider);
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> SelectionChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> TextChanged;
|
||||
|
|
|
@ -840,6 +840,23 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
return;
|
||||
}
|
||||
|
||||
const auto keyStatus = e.KeyStatus();
|
||||
const auto vkey = gsl::narrow_cast<WORD>(e.OriginalKey());
|
||||
const auto scanCode = gsl::narrow_cast<WORD>(keyStatus.ScanCode);
|
||||
auto modifiers = _GetPressedModifierKeys();
|
||||
|
||||
// GH#11076:
|
||||
// For some weird reason we sometimes receive a WM_KEYDOWN
|
||||
// message without vkey or scanCode if a user drags a tab.
|
||||
// The KeyChord constructor has a debug assertion ensuring that all KeyChord
|
||||
// either have a valid vkey/scanCode. This is important, because this prevents
|
||||
// accidential insertion of invalid KeyChords into classes like ActionMap.
|
||||
if (!vkey && !scanCode)
|
||||
{
|
||||
e.Handled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Mark the event as handled and do nothing if we're closing, or the key
|
||||
// was the Windows key.
|
||||
//
|
||||
|
@ -848,19 +865,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
// win32-input-mode, then we'll send all these keystrokes to the
|
||||
// terminal - it's smart enough to ignore the keys it doesn't care
|
||||
// about.
|
||||
if (_IsClosing() ||
|
||||
e.OriginalKey() == VirtualKey::LeftWindows ||
|
||||
e.OriginalKey() == VirtualKey::RightWindows)
|
||||
|
||||
if (_IsClosing() || vkey == VK_LWIN || vkey == VK_RWIN)
|
||||
{
|
||||
e.Handled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
auto modifiers = _GetPressedModifierKeys();
|
||||
const auto vkey = gsl::narrow_cast<WORD>(e.OriginalKey());
|
||||
const auto scanCode = gsl::narrow_cast<WORD>(e.KeyStatus().ScanCode);
|
||||
|
||||
// Short-circuit isReadOnly check to avoid warning dialog
|
||||
if (_core.IsInReadOnlyMode())
|
||||
{
|
||||
|
@ -868,7 +878,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
return;
|
||||
}
|
||||
|
||||
if (e.KeyStatus().IsExtendedKey)
|
||||
if (keyStatus.IsExtendedKey)
|
||||
{
|
||||
modifiers |= ControlKeyStates::EnhancedKey;
|
||||
}
|
||||
|
@ -878,8 +888,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
// will be sent through the TSFInputControl. See GH#1401 for more
|
||||
// details
|
||||
if (modifiers.IsAltPressed() &&
|
||||
(e.OriginalKey() >= VirtualKey::NumberPad0 && e.OriginalKey() <= VirtualKey::NumberPad9))
|
||||
|
||||
(vkey >= VK_NUMPAD0 && vkey <= VK_NUMPAD9))
|
||||
{
|
||||
e.Handled(true);
|
||||
return;
|
||||
|
@ -927,7 +936,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
// Manually prevent keyboard navigation with tab. We want to send tab to
|
||||
// the terminal, and we don't want to be able to escape focus of the
|
||||
// control with tab.
|
||||
e.Handled(e.OriginalKey() == VirtualKey::Tab);
|
||||
e.Handled(vkey == VK_TAB);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
|
|
@ -45,6 +45,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
_contentAutomationPeer.SelectionChanged([this](auto&&, auto&&) { SignalSelectionChanged(); });
|
||||
_contentAutomationPeer.TextChanged([this](auto&&, auto&&) { SignalTextChanged(); });
|
||||
_contentAutomationPeer.CursorChanged([this](auto&&, auto&&) { SignalCursorChanged(); });
|
||||
_contentAutomationPeer.ParentProvider(*this);
|
||||
};
|
||||
|
||||
// Method Description:
|
||||
|
@ -226,30 +227,4 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
// Method Description:
|
||||
// - extracts the UiaTextRanges from the SAFEARRAY and converts them to Xaml ITextRangeProviders
|
||||
// Arguments:
|
||||
// - SAFEARRAY of UIA::UiaTextRange (ITextRangeProviders)
|
||||
// Return Value:
|
||||
// - com_array of Xaml Wrapped UiaTextRange (ITextRangeProviders)
|
||||
com_array<XamlAutomation::ITextRangeProvider> TermControlAutomationPeer::WrapArrayOfTextRangeProviders(SAFEARRAY* textRanges)
|
||||
{
|
||||
// transfer ownership of UiaTextRanges to this new vector
|
||||
auto providers = SafeArrayToOwningVector<::Microsoft::Terminal::TermControlUiaTextRange>(textRanges);
|
||||
int count = gsl::narrow<int>(providers.size());
|
||||
|
||||
std::vector<XamlAutomation::ITextRangeProvider> vec;
|
||||
vec.reserve(count);
|
||||
auto parentProvider = this->ProviderFromPeer(*this);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
auto xutr = make_self<XamlUiaTextRange>(providers[i].detach(), parentProvider);
|
||||
vec.emplace_back(xutr.as<XamlAutomation::ITextRangeProvider>());
|
||||
}
|
||||
|
||||
com_array<XamlAutomation::ITextRangeProvider> result{ vec };
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,7 +78,5 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
private:
|
||||
winrt::Microsoft::Terminal::Control::implementation::TermControl* _termControl;
|
||||
Control::InteractivityAutomationPeer _contentAutomationPeer;
|
||||
|
||||
winrt::com_array<Windows::UI::Xaml::Automation::Provider::ITextRangeProvider> WrapArrayOfTextRangeProviders(SAFEARRAY* textRanges);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "../types/TermControlUiaTextRange.hpp"
|
||||
#include <UIAutomationClient.h>
|
||||
#include <UIAutomationCoreApi.h>
|
||||
#include "../types/UiaTracing.h"
|
||||
|
||||
// the same as COR_E_NOTSUPPORTED
|
||||
// we don't want to import the CLR headers to get it
|
||||
|
@ -182,6 +183,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
|
||||
XamlAutomation::IRawElementProviderSimple XamlUiaTextRange::GetEnclosingElement()
|
||||
{
|
||||
::Microsoft::Console::Types::UiaTracing::TextRange::GetEnclosingElement(*static_cast<::Microsoft::Console::Types::UiaTextRangeBase*>(_uiaProvider.get()));
|
||||
return _parentProvider;
|
||||
}
|
||||
|
||||
|
|
|
@ -849,7 +849,13 @@ WORD Terminal::_TakeVirtualKeyFromLastKeyEvent(const WORD scanCode) noexcept
|
|||
// will release this lock when it's destructed.
|
||||
[[nodiscard]] std::unique_lock<til::ticket_lock> Terminal::LockForReading()
|
||||
{
|
||||
#ifdef NDEBUG
|
||||
return std::unique_lock{ _readWriteLock };
|
||||
#else
|
||||
auto lock = std::unique_lock{ _readWriteLock };
|
||||
_lastLocker = GetCurrentThreadId();
|
||||
return lock;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -859,7 +865,13 @@ WORD Terminal::_TakeVirtualKeyFromLastKeyEvent(const WORD scanCode) noexcept
|
|||
// will release this lock when it's destructed.
|
||||
[[nodiscard]] std::unique_lock<til::ticket_lock> Terminal::LockForWriting()
|
||||
{
|
||||
#ifdef NDEBUG
|
||||
return std::unique_lock{ _readWriteLock };
|
||||
#else
|
||||
auto lock = std::unique_lock{ _readWriteLock };
|
||||
_lastLocker = GetCurrentThreadId();
|
||||
return lock;
|
||||
#endif
|
||||
}
|
||||
|
||||
Viewport Terminal::_GetMutableViewport() const noexcept
|
||||
|
|
|
@ -199,6 +199,7 @@ public:
|
|||
const COORD GetSelectionEnd() const noexcept override;
|
||||
const std::wstring_view GetConsoleTitle() const noexcept override;
|
||||
void ColorSelection(const COORD coordSelectionStart, const COORD coordSelectionEnd, const TextAttribute) override;
|
||||
const bool IsUiaDataInitialized() const noexcept override;
|
||||
#pragma endregion
|
||||
|
||||
void SetWriteInputCallback(std::function<void(std::wstring&)> pfn) noexcept;
|
||||
|
@ -254,6 +255,9 @@ private:
|
|||
// But we can abuse the fact that the surrounding members rarely change and are huge
|
||||
// (std::function is like 64 bytes) to create some natural padding without wasting space.
|
||||
til::ticket_lock _readWriteLock;
|
||||
#ifndef NDEBUG
|
||||
DWORD _lastLocker;
|
||||
#endif
|
||||
|
||||
std::function<void(const int, const int, const int)> _pfnScrollPositionChanged;
|
||||
std::function<void(const til::color)> _pfnBackgroundColorChanged;
|
||||
|
|
|
@ -233,6 +233,9 @@ catch (...)
|
|||
void Terminal::LockConsole() noexcept
|
||||
{
|
||||
_readWriteLock.lock();
|
||||
#ifndef NDEBUG
|
||||
_lastLocker = GetCurrentThreadId();
|
||||
#endif
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -250,3 +253,12 @@ bool Terminal::IsScreenReversed() const noexcept
|
|||
{
|
||||
return _screenReversed;
|
||||
}
|
||||
|
||||
const bool Terminal::IsUiaDataInitialized() const noexcept
|
||||
{
|
||||
// GH#11135: Windows Terminal needs to create and return an automation peer
|
||||
// when a screen reader requests it. However, the terminal might not be fully
|
||||
// initialized yet. So we use this to check if any crucial components of
|
||||
// UiaData are not yet initialized.
|
||||
return !!_buffer;
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
<StackPanel Margin="{StaticResource StandardControlMargin}">
|
||||
<local:SettingContainer x:Uid="AddProfile_Duplicate">
|
||||
<muxc:RadioButtons x:Name="Profiles"
|
||||
AutomationProperties.AccessibilityView="Content"
|
||||
ItemsSource="{x:Bind State.Settings.AllProfiles, Mode=OneWay}">
|
||||
<muxc:RadioButtons.ItemTemplate>
|
||||
<DataTemplate x:DataType="model:Profile">
|
||||
|
|
|
@ -163,7 +163,8 @@
|
|||
ClearSettingValue="{x:Bind Appearance.ClearCursorShape}"
|
||||
HasSettingValue="{x:Bind Appearance.HasCursorShape, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind Appearance.CursorShapeOverrideSource, Mode=OneWay}">
|
||||
<muxc:RadioButtons ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
||||
<muxc:RadioButtons AutomationProperties.AccessibilityView="Content"
|
||||
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
||||
ItemsSource="{x:Bind CursorShapeList, Mode=OneWay}"
|
||||
SelectedItem="{x:Bind CurrentCursorShape, Mode=TwoWay}" />
|
||||
</local:SettingContainer>
|
||||
|
@ -225,7 +226,8 @@
|
|||
HasSettingValue="{x:Bind Appearance.HasBackgroundImageStretchMode, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind Appearance.BackgroundImageStretchModeOverrideSource, Mode=OneWay}"
|
||||
Visibility="{x:Bind Appearance.BackgroundImageSettingsVisible, Mode=OneWay}">
|
||||
<muxc:RadioButtons ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
||||
<muxc:RadioButtons AutomationProperties.AccessibilityView="Content"
|
||||
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
||||
ItemsSource="{x:Bind BackgroundImageStretchModeList, Mode=OneWay}"
|
||||
SelectedItem="{x:Bind CurrentBackgroundImageStretchMode, Mode=TwoWay}" />
|
||||
</local:SettingContainer>
|
||||
|
@ -440,7 +442,8 @@
|
|||
ClearSettingValue="{x:Bind Appearance.ClearIntenseTextStyle}"
|
||||
HasSettingValue="{x:Bind Appearance.HasIntenseTextStyle, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind Appearance.IntenseTextStyleOverrideSource, Mode=OneWay}">
|
||||
<muxc:RadioButtons ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
||||
<muxc:RadioButtons AutomationProperties.AccessibilityView="Content"
|
||||
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
||||
ItemsSource="{x:Bind IntenseTextStyleList, Mode=OneWay}"
|
||||
SelectedItem="{x:Bind CurrentIntenseTextStyle, Mode=TwoWay}" />
|
||||
</local:SettingContainer>
|
||||
|
|
|
@ -198,4 +198,9 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||
globals.Language(currentLanguage);
|
||||
}
|
||||
}
|
||||
|
||||
bool GlobalAppearance::FeatureNotificationIconEnabled() const noexcept
|
||||
{
|
||||
return Feature_NotificationIcon::IsEnabled();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,8 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||
|
||||
void OnNavigatedTo(const winrt::Windows::UI::Xaml::Navigation::NavigationEventArgs& e);
|
||||
|
||||
bool FeatureNotificationIconEnabled() const noexcept;
|
||||
|
||||
WINRT_PROPERTY(Editor::GlobalAppearancePageNavigationState, State, nullptr);
|
||||
GETSET_BINDABLE_ENUM_SETTING(Theme, winrt::Windows::UI::Xaml::ElementTheme, State().Globals, Theme);
|
||||
GETSET_BINDABLE_ENUM_SETTING(TabWidthMode, winrt::Microsoft::UI::Xaml::Controls::TabViewWidthMode, State().Globals, TabWidthMode);
|
||||
|
|
|
@ -25,5 +25,7 @@ namespace Microsoft.Terminal.Settings.Editor
|
|||
|
||||
IInspectable CurrentTabWidthMode;
|
||||
Windows.Foundation.Collections.IObservableVector<Microsoft.Terminal.Settings.Editor.EnumEntry> TabWidthModeList { get; };
|
||||
|
||||
Boolean FeatureNotificationIconEnabled { get; };
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,8 @@
|
|||
|
||||
<!-- Theme -->
|
||||
<local:SettingContainer x:Uid="Globals_Theme">
|
||||
<muxc:RadioButtons ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
||||
<muxc:RadioButtons AutomationProperties.AccessibilityView="Content"
|
||||
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
||||
ItemsSource="{x:Bind ThemeList, Mode=OneWay}"
|
||||
SelectedItem="{x:Bind CurrentTheme, Mode=TwoWay}" />
|
||||
</local:SettingContainer>
|
||||
|
@ -74,7 +75,8 @@
|
|||
|
||||
<!-- Tab Width Mode -->
|
||||
<local:SettingContainer x:Uid="Globals_TabWidthMode">
|
||||
<muxc:RadioButtons ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
||||
<muxc:RadioButtons AutomationProperties.AccessibilityView="Content"
|
||||
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
||||
ItemsSource="{x:Bind TabWidthModeList, Mode=OneWay}"
|
||||
SelectedItem="{x:Bind CurrentTabWidthMode, Mode=TwoWay}" />
|
||||
</local:SettingContainer>
|
||||
|
@ -84,6 +86,18 @@
|
|||
<local:SettingContainer x:Uid="Globals_DisableAnimationsReversed">
|
||||
<ToggleSwitch IsOn="{x:Bind local:Converters.InvertBoolean(State.Globals.DisableAnimations), BindBack=State.Globals.SetInvertedDisableAnimationsValue, Mode=TwoWay}" />
|
||||
</local:SettingContainer>
|
||||
|
||||
<!-- Always Show Notification Icon -->
|
||||
<local:SettingContainer x:Uid="Globals_AlwaysShowNotificationIcon"
|
||||
Visibility="{x:Bind FeatureNotificationIconEnabled}">
|
||||
<ToggleSwitch IsOn="{x:Bind State.Globals.AlwaysShowNotificationIcon, Mode=TwoWay}" />
|
||||
</local:SettingContainer>
|
||||
|
||||
<!-- Minimize To Notification Area -->
|
||||
<local:SettingContainer x:Uid="Globals_MinimizeToNotificationArea"
|
||||
Visibility="{x:Bind FeatureNotificationIconEnabled}">
|
||||
<ToggleSwitch IsOn="{x:Bind State.Globals.MinimizeToNotificationArea, Mode=TwoWay}" />
|
||||
</local:SettingContainer>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</Page>
|
||||
|
|
|
@ -34,7 +34,8 @@
|
|||
|
||||
<!-- Copy Format -->
|
||||
<local:SettingContainer x:Uid="Globals_CopyFormat">
|
||||
<muxc:RadioButtons ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
||||
<muxc:RadioButtons AutomationProperties.AccessibilityView="Content"
|
||||
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
||||
ItemsSource="{x:Bind CopyFormatList, Mode=OneWay}"
|
||||
SelectedItem="{x:Bind CurrentCopyFormat, Mode=TwoWay}" />
|
||||
</local:SettingContainer>
|
||||
|
@ -57,7 +58,8 @@
|
|||
|
||||
<!-- Tab Switcher Mode -->
|
||||
<local:SettingContainer x:Uid="Globals_TabSwitcherMode">
|
||||
<muxc:RadioButtons ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
||||
<muxc:RadioButtons AutomationProperties.AccessibilityView="Content"
|
||||
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
||||
ItemsSource="{x:Bind TabSwitcherModeList}"
|
||||
SelectedItem="{x:Bind CurrentTabSwitcherMode, Mode=TwoWay}" />
|
||||
</local:SettingContainer>
|
||||
|
|
|
@ -33,7 +33,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
|||
void Launch::OnNavigatedTo(const NavigationEventArgs& e)
|
||||
{
|
||||
_State = e.Parameter().as<Editor::LaunchPageNavigationState>();
|
||||
_State.Settings().RefreshDefaultTerminals();
|
||||
}
|
||||
|
||||
IInspectable Launch::CurrentDefaultProfile()
|
||||
|
|
|
@ -134,15 +134,18 @@
|
|||
</local:SettingContainer>
|
||||
|
||||
<!-- Launch Mode -->
|
||||
<local:SettingContainer x:Uid="Globals_LaunchMode">
|
||||
<muxc:RadioButtons ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
||||
<local:SettingContainer x:Name="Globals_LaunchMode"
|
||||
x:Uid="Globals_LaunchMode">
|
||||
<muxc:RadioButtons AutomationProperties.AccessibilityView="Content"
|
||||
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
||||
ItemsSource="{x:Bind LaunchModeList}"
|
||||
SelectedItem="{x:Bind CurrentLaunchMode, Mode=TwoWay}" />
|
||||
</local:SettingContainer>
|
||||
|
||||
<!-- Launch Mode -->
|
||||
<local:SettingContainer x:Uid="Globals_WindowingBehavior">
|
||||
<muxc:RadioButtons ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
||||
<muxc:RadioButtons AutomationProperties.AccessibilityView="Content"
|
||||
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
||||
ItemsSource="{x:Bind WindowingBehaviorList}"
|
||||
SelectedItem="{x:Bind CurrentWindowingBehavior, Mode=TwoWay}" />
|
||||
</local:SettingContainer>
|
||||
|
|
|
@ -304,7 +304,8 @@
|
|||
ClearSettingValue="{x:Bind State.Profile.ClearScrollState}"
|
||||
HasSettingValue="{x:Bind State.Profile.HasScrollState, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind State.Profile.ScrollStateOverrideSource, Mode=OneWay}">
|
||||
<muxc:RadioButtons ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
||||
<muxc:RadioButtons AutomationProperties.AccessibilityView="Content"
|
||||
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
||||
ItemsSource="{x:Bind ScrollStateList, Mode=OneWay}"
|
||||
SelectedItem="{x:Bind CurrentScrollState, Mode=TwoWay}" />
|
||||
</local:SettingContainer>
|
||||
|
@ -409,7 +410,8 @@
|
|||
ClearSettingValue="{x:Bind State.Profile.ClearAntialiasingMode}"
|
||||
HasSettingValue="{x:Bind State.Profile.HasAntialiasingMode, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind State.Profile.AntialiasingModeOverrideSource, Mode=OneWay}">
|
||||
<muxc:RadioButtons ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
||||
<muxc:RadioButtons AutomationProperties.AccessibilityView="Content"
|
||||
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
||||
ItemsSource="{x:Bind AntiAliasingModeList, Mode=OneWay}"
|
||||
SelectedItem="{x:Bind CurrentAntiAliasingMode, Mode=TwoWay}" />
|
||||
</local:SettingContainer>
|
||||
|
@ -447,7 +449,8 @@
|
|||
ClearSettingValue="{x:Bind State.Profile.ClearCloseOnExit}"
|
||||
HasSettingValue="{x:Bind State.Profile.HasCloseOnExit, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind State.Profile.CloseOnExitOverrideSource, Mode=OneWay}">
|
||||
<muxc:RadioButtons ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
||||
<muxc:RadioButtons AutomationProperties.AccessibilityView="Content"
|
||||
ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
|
||||
ItemsSource="{x:Bind CloseOnExitModeList, Mode=OneWay}"
|
||||
SelectedItem="{x:Bind CurrentCloseOnExitMode, Mode=TwoWay}" />
|
||||
</local:SettingContainer>
|
||||
|
|
|
@ -1090,6 +1090,14 @@
|
|||
<value>Pane animations</value>
|
||||
<comment>Header for a control to toggle animations on panes. "Enabled" value enables the animations.</comment>
|
||||
</data>
|
||||
<data name="Globals_AlwaysShowNotificationIcon.Header" xml:space="preserve">
|
||||
<value>Always display an icon in the notification area</value>
|
||||
<comment>Header for a control to toggle whether the notification icon should always be shown.</comment>
|
||||
</data>
|
||||
<data name="Globals_MinimizeToNotificationArea.Header" xml:space="preserve">
|
||||
<value>Hide Terminal in the notification area when it is minimized</value>
|
||||
<comment>Header for a control to toggle whether the terminal should hide itself in the notification area instead of the taskbar when minimized.</comment>
|
||||
</data>
|
||||
<data name="SettingContainer_OverrideMessageBaseLayer" xml:space="preserve">
|
||||
<value>Reset to inherited value.</value>
|
||||
<comment>This button will remove a user's customization from a given setting, restoring it to the value that the profile inherited. This is a text label on a button.</comment>
|
||||
|
@ -1210,4 +1218,4 @@
|
|||
<value>Bold font with bright colors</value>
|
||||
<comment>An option to choose from for the "intense text format" setting. When selected, "intense" text will be rendered as both bold text and in a brighter color</comment>
|
||||
</data>
|
||||
</root>
|
||||
</root>
|
||||
|
|
|
@ -296,7 +296,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
return RS_(L"MoveFocusNextInOrder");
|
||||
case FocusDirection::PreviousInOrder:
|
||||
return RS_(L"MoveFocusPreviousInOrder");
|
||||
case FocusDirection::First:
|
||||
return RS_(L"MoveFocusFirstPane");
|
||||
}
|
||||
|
||||
return winrt::hstring{
|
||||
fmt::format(std::wstring_view(RS_(L"MoveFocusWithArgCommandKey")),
|
||||
directionString)
|
||||
|
@ -326,7 +329,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
return RS_(L"SwapPaneNextInOrder");
|
||||
case FocusDirection::PreviousInOrder:
|
||||
return RS_(L"SwapPanePreviousInOrder");
|
||||
case FocusDirection::First:
|
||||
return RS_(L"SwapPaneFirstPane");
|
||||
}
|
||||
|
||||
return winrt::hstring{
|
||||
fmt::format(std::wstring_view(RS_(L"SwapPaneWithArgCommandKey")),
|
||||
directionString)
|
||||
|
|
|
@ -1410,7 +1410,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
}
|
||||
Json::Value json{ Json::ValueType::objectValue };
|
||||
const auto args{ get_self<FindMatchArgs>(val) };
|
||||
JsonUtils::GetValueForKey(json, DirectionKey, args->_Direction);
|
||||
JsonUtils::SetValueForKey(json, DirectionKey, args->_Direction);
|
||||
return json;
|
||||
}
|
||||
IActionArgs Copy() const
|
||||
|
|
|
@ -35,7 +35,8 @@ namespace Microsoft.Terminal.Settings.Model
|
|||
Down,
|
||||
Previous,
|
||||
PreviousInOrder,
|
||||
NextInOrder
|
||||
NextInOrder,
|
||||
First
|
||||
};
|
||||
|
||||
enum SplitState
|
||||
|
|
|
@ -116,6 +116,26 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
MTSM_APPLICATION_STATE_FIELDS(MTSM_APPLICATION_STATE_GEN)
|
||||
#undef MTSM_APPLICATION_STATE_GEN
|
||||
|
||||
// Method Description:
|
||||
// - See GH#11119. Removes all of the data in this ApplicationState object
|
||||
// and resets it to the defaults. This will delete the state file! That's
|
||||
// the sure-fire way to make sure the data doesn't come back. If we leave
|
||||
// it untouched, then when we go to write the file back out, we'll first
|
||||
// re-read it's contents and try to overlay our new state. However,
|
||||
// nullopts won't remove keys from the JSON, so we'll end up with the
|
||||
// original state in the file.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void ApplicationState::Reset() noexcept
|
||||
try
|
||||
{
|
||||
LOG_LAST_ERROR_IF(!DeleteFile(_path.c_str()));
|
||||
*_state.lock() = {};
|
||||
}
|
||||
CATCH_LOG()
|
||||
|
||||
// Deserializes the state.json at _path into this ApplicationState.
|
||||
// * ANY errors during app state will result in the creation of a new empty state.
|
||||
// * ANY errors during runtime will result in changes being partially ignored.
|
||||
|
|
|
@ -22,7 +22,8 @@ Abstract:
|
|||
// It provides X with the following arguments:
|
||||
// (type, function name, JSON key, ...variadic construction arguments)
|
||||
#define MTSM_APPLICATION_STATE_FIELDS(X) \
|
||||
X(std::unordered_set<winrt::guid>, GeneratedProfiles, "generatedProfiles")
|
||||
X(std::unordered_set<winrt::guid>, GeneratedProfiles, "generatedProfiles") \
|
||||
X(Windows::Foundation::Collections::IVector<winrt::Microsoft::Terminal::Settings::Model::InfoBarMessage>, DismissedMessages, "dismissedMessages")
|
||||
|
||||
namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
{
|
||||
|
@ -35,6 +36,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
|
||||
// Methods
|
||||
void Reload() const noexcept;
|
||||
void Reset() noexcept;
|
||||
|
||||
// General getters/setters
|
||||
winrt::hstring FilePath() const noexcept;
|
||||
|
|
|
@ -3,11 +3,20 @@
|
|||
|
||||
namespace Microsoft.Terminal.Settings.Model
|
||||
{
|
||||
enum InfoBarMessage
|
||||
{
|
||||
KeyboardServiceWarning = 0,
|
||||
SetAsDefault,
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass ApplicationState {
|
||||
static ApplicationState SharedInstance();
|
||||
|
||||
void Reload();
|
||||
void Reset();
|
||||
|
||||
String FilePath { get; };
|
||||
|
||||
Windows.Foundation.Collections.IVector<InfoBarMessage> DismissedMessages { get; set; };
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,10 @@
|
|||
#include "CascadiaSettings.h"
|
||||
#include "CascadiaSettings.g.cpp"
|
||||
|
||||
#include "DefaultTerminal.h"
|
||||
|
||||
#include <LibraryResources.h>
|
||||
#include <WtExeUtils.h>
|
||||
|
||||
#include "AzureCloudShellGenerator.h"
|
||||
#include "PowershellCoreProfileGenerator.h"
|
||||
|
@ -43,7 +46,6 @@ CascadiaSettings::CascadiaSettings(const bool addDynamicProfiles) :
|
|||
_activeProfiles{ winrt::single_threaded_observable_vector<Model::Profile>() },
|
||||
_warnings{ winrt::single_threaded_vector<SettingsLoadWarnings>() },
|
||||
_deserializationErrorMessage{ L"" },
|
||||
_defaultTerminals{ winrt::single_threaded_observable_vector<Model::DefaultTerminal>() },
|
||||
_currentDefaultTerminal{ nullptr }
|
||||
{
|
||||
if (addDynamicProfiles)
|
||||
|
@ -1187,25 +1189,6 @@ winrt::hstring CascadiaSettings::ApplicationVersion()
|
|||
return RS_(L"ApplicationVersionUnknown");
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Forces a refresh of all default terminal state. This hits the registry to
|
||||
// read off the disk, so best to not do it on the UI thread.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none> - Updates internal state
|
||||
void CascadiaSettings::RefreshDefaultTerminals()
|
||||
{
|
||||
_defaultTerminals.Clear();
|
||||
|
||||
for (const auto& term : Model::DefaultTerminal::Available())
|
||||
{
|
||||
_defaultTerminals.Append(term);
|
||||
}
|
||||
|
||||
_currentDefaultTerminal = Model::DefaultTerminal::Current();
|
||||
}
|
||||
|
||||
// Helper to do the version check
|
||||
static bool _isOnBuildWithDefTerm() noexcept
|
||||
{
|
||||
|
@ -1228,35 +1211,42 @@ static bool _isOnBuildWithDefTerm() noexcept
|
|||
// - True if OS supports default terminal. False otherwise.
|
||||
bool CascadiaSettings::IsDefaultTerminalAvailable() noexcept
|
||||
{
|
||||
if (!IsPackaged())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Cached on first use since the OS version shouldn't change while we're running.
|
||||
static bool isAvailable = _isOnBuildWithDefTerm();
|
||||
return isAvailable;
|
||||
}
|
||||
|
||||
bool CascadiaSettings::IsDefaultTerminalSet() noexcept
|
||||
{
|
||||
return DefaultTerminal::HasCurrent();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Returns an iterable collection of all available terminals.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - an iterable collection of all available terminals that could be the default.
|
||||
IObservableVector<Settings::Model::DefaultTerminal> CascadiaSettings::DefaultTerminals() const noexcept
|
||||
IObservableVector<Settings::Model::DefaultTerminal> CascadiaSettings::DefaultTerminals() noexcept
|
||||
{
|
||||
_refreshDefaultTerminals();
|
||||
return _defaultTerminals;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Returns the currently selected default terminal application.
|
||||
// - DANGER! This will be null unless you've called
|
||||
// CascadiaSettings::RefreshDefaultTerminals. At the time of this comment (May
|
||||
|
||||
// 2021), only the Launch page in the settings UI calls that method, so this
|
||||
// value is unset unless you've navigated to that page.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - the selected default terminal application
|
||||
Settings::Model::DefaultTerminal CascadiaSettings::CurrentDefaultTerminal() const noexcept
|
||||
Settings::Model::DefaultTerminal CascadiaSettings::CurrentDefaultTerminal() noexcept
|
||||
{
|
||||
_refreshDefaultTerminals();
|
||||
return _currentDefaultTerminal;
|
||||
}
|
||||
|
||||
|
@ -1266,7 +1256,23 @@ Settings::Model::DefaultTerminal CascadiaSettings::CurrentDefaultTerminal() cons
|
|||
// - terminal - Terminal from `DefaultTerminals` list to set as default
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void CascadiaSettings::CurrentDefaultTerminal(Settings::Model::DefaultTerminal terminal)
|
||||
void CascadiaSettings::CurrentDefaultTerminal(const Settings::Model::DefaultTerminal& terminal)
|
||||
{
|
||||
_currentDefaultTerminal = terminal;
|
||||
}
|
||||
|
||||
// This function is implicitly called by DefaultTerminals/CurrentDefaultTerminal().
|
||||
// It reloads the selection of available, installed terminals and caches them.
|
||||
// WinUI requires us that the `SelectedItem` of a collection is member of the list given to `ItemsSource`.
|
||||
// It's thus important that _currentDefaultTerminal is a member of _defaultTerminals.
|
||||
// Right now this is implicitly the case thanks to DefaultTerminal::Available(),
|
||||
// but in the future it might be worthwhile to change the code to use list indices instead.
|
||||
void CascadiaSettings::_refreshDefaultTerminals()
|
||||
{
|
||||
if (!_defaultTerminals)
|
||||
{
|
||||
auto [defaultTerminals, defaultTerminal] = DefaultTerminal::Available();
|
||||
_defaultTerminals = winrt::single_threaded_observable_vector(std::move(defaultTerminals));
|
||||
_currentDefaultTerminal = std::move(defaultTerminal);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -99,12 +99,12 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
Model::Profile GetProfileForArgs(const Model::NewTerminalArgs& newTerminalArgs) const;
|
||||
|
||||
Model::Profile DuplicateProfile(const Model::Profile& source);
|
||||
void RefreshDefaultTerminals();
|
||||
|
||||
static bool IsDefaultTerminalAvailable() noexcept;
|
||||
Windows::Foundation::Collections::IObservableVector<Model::DefaultTerminal> DefaultTerminals() const noexcept;
|
||||
Model::DefaultTerminal CurrentDefaultTerminal() const noexcept;
|
||||
void CurrentDefaultTerminal(Model::DefaultTerminal terminal);
|
||||
static bool IsDefaultTerminalSet() noexcept;
|
||||
winrt::Windows::Foundation::Collections::IObservableVector<Model::DefaultTerminal> DefaultTerminals() noexcept;
|
||||
Model::DefaultTerminal CurrentDefaultTerminal() noexcept;
|
||||
void CurrentDefaultTerminal(const Model::DefaultTerminal& terminal);
|
||||
|
||||
private:
|
||||
com_ptr<GlobalAppSettings> _globals;
|
||||
|
@ -114,8 +114,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
Windows::Foundation::IReference<SettingsLoadErrors> _loadError;
|
||||
hstring _deserializationErrorMessage;
|
||||
|
||||
Windows::Foundation::Collections::IObservableVector<Model::DefaultTerminal> _defaultTerminals;
|
||||
Model::DefaultTerminal _currentDefaultTerminal;
|
||||
void _refreshDefaultTerminals();
|
||||
|
||||
std::vector<std::unique_ptr<::Microsoft::Terminal::Settings::Model::IDynamicProfileGenerator>> _profileGenerators;
|
||||
|
||||
|
@ -177,6 +176,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
friend class SettingsModelLocalTests::KeyBindingsTests;
|
||||
friend class TerminalAppUnitTests::DynamicProfileTests;
|
||||
friend class TerminalAppUnitTests::JsonTests;
|
||||
|
||||
// defterm
|
||||
winrt::Windows::Foundation::Collections::IObservableVector<Model::DefaultTerminal> _defaultTerminals{ nullptr };
|
||||
Model::DefaultTerminal _currentDefaultTerminal{ nullptr };
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -46,8 +46,8 @@ namespace Microsoft.Terminal.Settings.Model
|
|||
|
||||
Profile GetProfileForArgs(NewTerminalArgs newTerminalArgs);
|
||||
|
||||
void RefreshDefaultTerminals();
|
||||
static Boolean IsDefaultTerminalAvailable { get; };
|
||||
static Boolean IsDefaultTerminalSet { get; };
|
||||
Windows.Foundation.Collections.IObservableVector<DefaultTerminal> DefaultTerminals { get; };
|
||||
DefaultTerminal CurrentDefaultTerminal;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
// "Generated Files" directory.
|
||||
|
||||
#include "ApplicationState.h"
|
||||
#include "DefaultTerminal.h"
|
||||
#include "FileUtils.h"
|
||||
|
||||
using namespace winrt::Microsoft::Terminal::Settings::Model::implementation;
|
||||
|
@ -844,6 +845,20 @@ static bool _IsValidProfileObject(const Json::Value& profileJson)
|
|||
// - a new CascadiaSettings instance created from the values in `json`
|
||||
winrt::com_ptr<CascadiaSettings> CascadiaSettings::FromJson(const Json::Value& json)
|
||||
{
|
||||
const auto settingsString = ReadUTF8FileIfExists(_SettingsPath()).value_or(std::string{});
|
||||
const auto firstTimeSetup = settingsString.empty();
|
||||
|
||||
// GH#11119: If we find that the settings file doesn't exist, or is empty,
|
||||
// then let's quick delete the state file as well. If the user does have a
|
||||
// state file, and not a settings, then they probably tried to reset their
|
||||
// settings. It might have data in it that was only relevant for a previous
|
||||
// iteration of the settings file. If we don't, we'll load the old state and
|
||||
// ignore all dynamic profiles (for example)!
|
||||
if (firstTimeSetup)
|
||||
{
|
||||
ApplicationState::SharedInstance().Reset();
|
||||
}
|
||||
|
||||
auto resultPtr = winrt::make_self<CascadiaSettings>();
|
||||
resultPtr->LayerJson(json);
|
||||
return resultPtr;
|
||||
|
@ -1225,7 +1240,7 @@ void CascadiaSettings::WriteSettingsToDisk() const
|
|||
// otherwise.
|
||||
if (_currentDefaultTerminal)
|
||||
{
|
||||
Model::DefaultTerminal::Current(_currentDefaultTerminal);
|
||||
Model::DefaultTerminal::SetCurrent(_currentDefaultTerminal);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,85 +10,88 @@
|
|||
using namespace winrt::Microsoft::Terminal::Settings;
|
||||
using namespace winrt::Microsoft::Terminal::Settings::Model::implementation;
|
||||
|
||||
winrt::Windows::Foundation::Collections::IVector<Model::DefaultTerminal> DefaultTerminal::_available = winrt::single_threaded_vector<Model::DefaultTerminal>();
|
||||
Model::DefaultTerminal DefaultTerminal::_current = nullptr;
|
||||
|
||||
DefaultTerminal::DefaultTerminal(DelegationConfig::DelegationPackage pkg) :
|
||||
_pkg(pkg)
|
||||
DefaultTerminal::DefaultTerminal(DelegationConfig::DelegationPackage&& pkg) :
|
||||
_pkg{ pkg }
|
||||
{
|
||||
}
|
||||
|
||||
winrt::hstring DefaultTerminal::Name() const
|
||||
{
|
||||
static const std::wstring def{ RS_(L"InboxWindowsConsoleName") };
|
||||
return _pkg.terminal.name.empty() ? winrt::hstring{ def } : winrt::hstring{ _pkg.terminal.name };
|
||||
return _pkg.terminal.name.empty() ? winrt::hstring{ RS_(L"InboxWindowsConsoleName") } : winrt::hstring{ _pkg.terminal.name };
|
||||
}
|
||||
|
||||
winrt::hstring DefaultTerminal::Version() const
|
||||
{
|
||||
// If there's no version information... return empty string instead.
|
||||
if (DelegationConfig::PkgVersion{} == _pkg.terminal.version)
|
||||
const auto& version = _pkg.terminal.version;
|
||||
if (DelegationConfig::PkgVersion{} == version)
|
||||
{
|
||||
return winrt::hstring{};
|
||||
}
|
||||
|
||||
const auto name = fmt::format(L"{}.{}.{}.{}", _pkg.terminal.version.major, _pkg.terminal.version.minor, _pkg.terminal.version.build, _pkg.terminal.version.revision);
|
||||
return winrt::hstring{ name };
|
||||
fmt::wmemory_buffer buffer;
|
||||
fmt::format_to(buffer, L"{}.{}.{}.{}", version.major, version.minor, version.build, version.revision);
|
||||
return winrt::hstring{ buffer.data(), gsl::narrow_cast<winrt::hstring::size_type>(buffer.size()) };
|
||||
}
|
||||
|
||||
winrt::hstring DefaultTerminal::Author() const
|
||||
{
|
||||
static const std::wstring def{ RS_(L"InboxWindowsConsoleAuthor") };
|
||||
return _pkg.terminal.author.empty() ? winrt::hstring{ def } : winrt::hstring{ _pkg.terminal.author };
|
||||
return _pkg.terminal.author.empty() ? winrt::hstring{ RS_(L"InboxWindowsConsoleAuthor") } : winrt::hstring{ _pkg.terminal.author };
|
||||
}
|
||||
|
||||
winrt::hstring DefaultTerminal::Icon() const
|
||||
{
|
||||
static const std::wstring_view def{ L"\uE756" };
|
||||
return _pkg.terminal.logo.empty() ? winrt::hstring{ def } : winrt::hstring{ _pkg.terminal.logo };
|
||||
return _pkg.terminal.logo.empty() ? winrt::hstring{ L"\uE756" } : winrt::hstring{ _pkg.terminal.logo };
|
||||
}
|
||||
|
||||
void DefaultTerminal::Refresh()
|
||||
std::pair<std::vector<Model::DefaultTerminal>, Model::DefaultTerminal> DefaultTerminal::Available()
|
||||
{
|
||||
// The potential of returning nullptr for defaultTerminal feels weird, but XAML can
|
||||
// handle that appropriately and will select nothing as current in the dropdown.
|
||||
std::vector<Model::DefaultTerminal> defaultTerminals;
|
||||
Model::DefaultTerminal defaultTerminal{ nullptr };
|
||||
|
||||
std::vector<DelegationConfig::DelegationPackage> allPackages;
|
||||
DelegationConfig::DelegationPackage currentPackage;
|
||||
LOG_IF_FAILED(DelegationConfig::s_GetAvailablePackages(allPackages, currentPackage));
|
||||
|
||||
for (auto& pkg : allPackages)
|
||||
{
|
||||
// Be a bit careful here: We're moving pkg into the constructor.
|
||||
// Afterwards it'll be invalid, so we need to cache isCurrent.
|
||||
const auto isCurrent = pkg == currentPackage;
|
||||
auto p = winrt::make<DefaultTerminal>(std::move(pkg));
|
||||
|
||||
if (isCurrent)
|
||||
{
|
||||
defaultTerminal = p;
|
||||
}
|
||||
|
||||
defaultTerminals.emplace_back(std::move(p));
|
||||
}
|
||||
|
||||
return { std::move(defaultTerminals), std::move(defaultTerminal) };
|
||||
}
|
||||
|
||||
bool DefaultTerminal::HasCurrent()
|
||||
{
|
||||
std::vector<DelegationConfig::DelegationPackage> allPackages;
|
||||
DelegationConfig::DelegationPackage currentPackage;
|
||||
|
||||
LOG_IF_FAILED(DelegationConfig::s_GetAvailablePackages(allPackages, currentPackage));
|
||||
|
||||
_available.Clear();
|
||||
for (const auto& pkg : allPackages)
|
||||
{
|
||||
auto p = winrt::make<DefaultTerminal>(pkg);
|
||||
|
||||
_available.Append(p);
|
||||
|
||||
if (pkg == currentPackage)
|
||||
{
|
||||
_current = p;
|
||||
}
|
||||
}
|
||||
// Good old conhost has a hardcoded GUID of {00000000-0000-0000-0000-000000000000}.
|
||||
return currentPackage.terminal.clsid != CLSID{};
|
||||
}
|
||||
|
||||
winrt::Windows::Foundation::Collections::IVectorView<Model::DefaultTerminal> DefaultTerminal::Available()
|
||||
{
|
||||
Refresh();
|
||||
return _available.GetView();
|
||||
}
|
||||
|
||||
Model::DefaultTerminal DefaultTerminal::Current()
|
||||
{
|
||||
if (!_current)
|
||||
{
|
||||
Refresh();
|
||||
}
|
||||
|
||||
// The potential of returning nullptr feels weird, but XAML can handle that appropriately
|
||||
// and will select nothing as current in the dropdown.
|
||||
return _current;
|
||||
}
|
||||
|
||||
void DefaultTerminal::Current(const Model::DefaultTerminal& term)
|
||||
void DefaultTerminal::SetCurrent(const Model::DefaultTerminal& term)
|
||||
{
|
||||
THROW_IF_FAILED(DelegationConfig::s_SetDefaultByPackage(winrt::get_self<DefaultTerminal>(term)->_pkg, true));
|
||||
_current = term;
|
||||
|
||||
TraceLoggingWrite(g_hSettingsModelProvider,
|
||||
"DefaultTerminalChanged",
|
||||
TraceLoggingWideString(term.Name().c_str(), "TerminalName", "the name of the default terminal"),
|
||||
TraceLoggingWideString(term.Version().c_str(), "TerminalVersion", "the version of the default terminal"),
|
||||
TraceLoggingWideString(term.Author().c_str(), "TerminalAuthor", "the author of the default terminal"),
|
||||
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),
|
||||
TelemetryPrivacyDataTag(PDT_ProductAndServiceUsage));
|
||||
}
|
||||
|
|
|
@ -27,22 +27,19 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
{
|
||||
struct DefaultTerminal : public DefaultTerminalT<DefaultTerminal>
|
||||
{
|
||||
DefaultTerminal(DelegationConfig::DelegationPackage pkg);
|
||||
explicit DefaultTerminal(DelegationConfig::DelegationPackage&& pkg);
|
||||
|
||||
hstring Name() const;
|
||||
hstring Author() const;
|
||||
hstring Version() const;
|
||||
hstring Icon() const;
|
||||
|
||||
static void Refresh();
|
||||
static Windows::Foundation::Collections::IVectorView<Model::DefaultTerminal> Available();
|
||||
static Model::DefaultTerminal Current();
|
||||
static void Current(const Model::DefaultTerminal& term);
|
||||
static std::pair<std::vector<Model::DefaultTerminal>, Model::DefaultTerminal> Available();
|
||||
static bool HasCurrent();
|
||||
static void SetCurrent(const Model::DefaultTerminal& term);
|
||||
|
||||
private:
|
||||
DelegationConfig::DelegationPackage _pkg;
|
||||
static Windows::Foundation::Collections::IVector<Model::DefaultTerminal> _available;
|
||||
static Model::DefaultTerminal _current;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@ namespace Microsoft.Terminal.Settings.Model
|
|||
String Version { get; };
|
||||
String Icon { get; };
|
||||
|
||||
static DefaultTerminal Current;
|
||||
static Windows.Foundation.Collections.IVectorView<DefaultTerminal> Available { get; };
|
||||
static void SetCurrent(DefaultTerminal term);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,8 +49,8 @@ static constexpr std::string_view StartupActionsKey{ "startupActions" };
|
|||
static constexpr std::string_view FocusFollowMouseKey{ "focusFollowMouse" };
|
||||
static constexpr std::string_view WindowingBehaviorKey{ "windowingBehavior" };
|
||||
static constexpr std::string_view TrimBlockSelectionKey{ "trimBlockSelection" };
|
||||
static constexpr std::string_view AlwaysShowTrayIconKey{ "alwaysShowTrayIcon" };
|
||||
static constexpr std::string_view MinimizeToTrayKey{ "minimizeToTray" };
|
||||
static constexpr std::string_view AlwaysShowNotificationIconKey{ "alwaysShowNotificationIcon" };
|
||||
static constexpr std::string_view MinimizeToNotificationAreaKey{ "minimizeToNotificationArea" };
|
||||
|
||||
static constexpr std::string_view DebugFeaturesKey{ "debugFeatures" };
|
||||
|
||||
|
@ -133,8 +133,8 @@ winrt::com_ptr<GlobalAppSettings> GlobalAppSettings::Copy() const
|
|||
globals->_WindowingBehavior = _WindowingBehavior;
|
||||
globals->_TrimBlockSelection = _TrimBlockSelection;
|
||||
globals->_DetectURLs = _DetectURLs;
|
||||
globals->_MinimizeToTray = _MinimizeToTray;
|
||||
globals->_AlwaysShowTrayIcon = _AlwaysShowTrayIcon;
|
||||
globals->_MinimizeToNotificationArea = _MinimizeToNotificationArea;
|
||||
globals->_AlwaysShowNotificationIcon = _AlwaysShowNotificationIcon;
|
||||
|
||||
globals->_UnparsedDefaultProfile = _UnparsedDefaultProfile;
|
||||
globals->_validDefaultProfile = _validDefaultProfile;
|
||||
|
@ -327,9 +327,9 @@ void GlobalAppSettings::LayerJson(const Json::Value& json)
|
|||
|
||||
JsonUtils::GetValueForKey(json, DetectURLsKey, _DetectURLs);
|
||||
|
||||
JsonUtils::GetValueForKey(json, MinimizeToTrayKey, _MinimizeToTray);
|
||||
JsonUtils::GetValueForKey(json, MinimizeToNotificationAreaKey, _MinimizeToNotificationArea);
|
||||
|
||||
JsonUtils::GetValueForKey(json, AlwaysShowTrayIconKey, _AlwaysShowTrayIcon);
|
||||
JsonUtils::GetValueForKey(json, AlwaysShowNotificationIconKey, _AlwaysShowNotificationIcon);
|
||||
|
||||
// This is a helper lambda to get the keybindings and commands out of both
|
||||
// and array of objects. We'll use this twice, once on the legacy
|
||||
|
@ -427,8 +427,8 @@ Json::Value GlobalAppSettings::ToJson() const
|
|||
JsonUtils::SetValueForKey(json, WindowingBehaviorKey, _WindowingBehavior);
|
||||
JsonUtils::SetValueForKey(json, TrimBlockSelectionKey, _TrimBlockSelection);
|
||||
JsonUtils::SetValueForKey(json, DetectURLsKey, _DetectURLs);
|
||||
JsonUtils::SetValueForKey(json, MinimizeToTrayKey, _MinimizeToTray);
|
||||
JsonUtils::SetValueForKey(json, AlwaysShowTrayIconKey, _AlwaysShowTrayIcon);
|
||||
JsonUtils::SetValueForKey(json, MinimizeToNotificationAreaKey, _MinimizeToNotificationArea);
|
||||
JsonUtils::SetValueForKey(json, AlwaysShowNotificationIconKey, _AlwaysShowNotificationIcon);
|
||||
// clang-format on
|
||||
|
||||
json[JsonKey(ActionsKey)] = _actionMap->ToJson();
|
||||
|
|
|
@ -99,8 +99,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||
INHERITABLE_SETTING(Model::GlobalAppSettings, Model::WindowingMode, WindowingBehavior, Model::WindowingMode::UseNew);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, TrimBlockSelection, false);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, DetectURLs, true);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, MinimizeToTray, false);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, AlwaysShowTrayIcon, false);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, MinimizeToNotificationArea, false);
|
||||
INHERITABLE_SETTING(Model::GlobalAppSettings, bool, AlwaysShowNotificationIcon, false);
|
||||
|
||||
private:
|
||||
guid _defaultProfile;
|
||||
|
|
|
@ -74,8 +74,8 @@ namespace Microsoft.Terminal.Settings.Model
|
|||
INHERITABLE_SETTING(WindowingMode, WindowingBehavior);
|
||||
INHERITABLE_SETTING(Boolean, TrimBlockSelection);
|
||||
INHERITABLE_SETTING(Boolean, DetectURLs);
|
||||
INHERITABLE_SETTING(Boolean, MinimizeToTray);
|
||||
INHERITABLE_SETTING(Boolean, AlwaysShowTrayIcon);
|
||||
INHERITABLE_SETTING(Boolean, MinimizeToNotificationArea);
|
||||
INHERITABLE_SETTING(Boolean, AlwaysShowNotificationIcon);
|
||||
|
||||
Windows.Foundation.Collections.IMapView<String, ColorScheme> ColorSchemes();
|
||||
void AddColorScheme(ColorScheme scheme);
|
||||
|
|
|
@ -177,6 +177,47 @@ namespace Microsoft::Terminal::Settings::Model::JsonUtils
|
|||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct ConversionTrait<std::vector<T>>
|
||||
{
|
||||
std::vector<T> FromJson(const Json::Value& json)
|
||||
{
|
||||
std::vector<T> val;
|
||||
val.reserve(json.size());
|
||||
|
||||
ConversionTrait<T> trait;
|
||||
for (const auto& element : json)
|
||||
{
|
||||
val.push_back(trait.FromJson(element));
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
bool CanConvert(const Json::Value& json) const
|
||||
{
|
||||
ConversionTrait<T> trait;
|
||||
return json.isArray() && std::all_of(json.begin(), json.end(), [trait](const auto& json) mutable -> bool { return trait.CanConvert(json); });
|
||||
}
|
||||
|
||||
Json::Value ToJson(const std::vector<T>& val)
|
||||
{
|
||||
Json::Value json{ Json::arrayValue };
|
||||
|
||||
ConversionTrait<T> trait;
|
||||
for (const auto& v : val)
|
||||
{
|
||||
json.append(trait.ToJson(v));
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
std::string TypeDescription() const
|
||||
{
|
||||
return fmt::format("{}[]", ConversionTrait<T>{}.TypeDescription());
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct ConversionTrait<std::unordered_map<std::string, T>>
|
||||
{
|
||||
|
@ -259,6 +300,42 @@ namespace Microsoft::Terminal::Settings::Model::JsonUtils
|
|||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct ConversionTrait<winrt::Windows::Foundation::Collections::IVector<T>>
|
||||
{
|
||||
winrt::Windows::Foundation::Collections::IVector<T> FromJson(const Json::Value& json)
|
||||
{
|
||||
ConversionTrait<std::vector<T>> trait;
|
||||
return winrt::single_threaded_vector<T>(std::move(trait.FromJson(json)));
|
||||
}
|
||||
|
||||
bool CanConvert(const Json::Value& json) const
|
||||
{
|
||||
ConversionTrait<std::vector<T>> trait;
|
||||
return trait.CanConvert(json);
|
||||
}
|
||||
|
||||
Json::Value ToJson(const winrt::Windows::Foundation::Collections::IVector<T>& val)
|
||||
{
|
||||
Json::Value json{ Json::arrayValue };
|
||||
|
||||
if (val)
|
||||
{
|
||||
ConversionTrait<T> trait;
|
||||
for (const auto& v : val)
|
||||
{
|
||||
json.append(trait.ToJson(v));
|
||||
}
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
std::string TypeDescription() const
|
||||
{
|
||||
return fmt::format("{}[]", ConversionTrait<T>{}.TypeDescription());
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct ConversionTrait<winrt::Windows::Foundation::Collections::IMap<winrt::hstring, T>>
|
||||
{
|
||||
|
|
|
@ -246,6 +246,15 @@
|
|||
<data name="MoveFocusToLastUsedPane" xml:space="preserve">
|
||||
<value>Move focus to the last used pane</value>
|
||||
</data>
|
||||
<data name="MoveFocusNextInOrder" xml:space="preserve">
|
||||
<value>Move focus to the next pane in order</value>
|
||||
</data>
|
||||
<data name="MoveFocusPreviousInOrder" xml:space="preserve">
|
||||
<value>Move focus to the previous pane in order</value>
|
||||
</data>
|
||||
<data name="MoveFocusFirstPane" xml:space="preserve">
|
||||
<value>Move focus to the first pane</value>
|
||||
</data>
|
||||
<data name="SwapPaneCommandKey" xml:space="preserve">
|
||||
<value>Swap pane</value>
|
||||
</data>
|
||||
|
@ -256,6 +265,15 @@
|
|||
<data name="SwapPaneToLastUsedPane" xml:space="preserve">
|
||||
<value>Swap panes with the last used pane</value>
|
||||
</data>
|
||||
<data name="SwapPaneNextInOrder" xml:space="preserve">
|
||||
<value>Swap panes with the next pane in order</value>
|
||||
</data>
|
||||
<data name="SwapPanePreviousInOrder" xml:space="preserve">
|
||||
<value>Swap panes with the previous pane in order</value>
|
||||
</data>
|
||||
<data name="SwapPaneFirstPane" xml:space="preserve">
|
||||
<value>Swap panes with the first pane</value>
|
||||
</data>
|
||||
<data name="NewTabCommandKey" xml:space="preserve">
|
||||
<value>New tab</value>
|
||||
</data>
|
||||
|
@ -436,19 +454,4 @@
|
|||
<value>Windows Console Host</value>
|
||||
<comment>Name describing the usage of the classic windows console as the terminal UI. (`conhost.exe`)</comment>
|
||||
</data>
|
||||
<data name="MoveFocusNextInOrder" xml:space="preserve">
|
||||
<value>Move focus to the next pane in order</value>
|
||||
</data>
|
||||
<data name="MoveFocusPreviousInOrder" xml:space="preserve">
|
||||
<value>Move focus to the previous pane in order</value>
|
||||
</data>
|
||||
<data name="SwapPaneNextInOrder" xml:space="preserve">
|
||||
<value>Swap panes with the next pane in order</value>
|
||||
</data>
|
||||
<data name="SwapPanePreviousInOrder" xml:space="preserve">
|
||||
<value>Swap panes with the previous pane in order</value>
|
||||
</data>
|
||||
<data name="MinimizeToTrayCommandKey" xml:space="preserve">
|
||||
<value>Minimize current window to tray</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
|
@ -337,7 +337,7 @@ struct ::Microsoft::Terminal::Settings::Model::JsonUtils::ConversionTrait<::winr
|
|||
// Possible FocusDirection values
|
||||
JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Settings::Model::FocusDirection)
|
||||
{
|
||||
JSON_MAPPINGS(7) = {
|
||||
JSON_MAPPINGS(8) = {
|
||||
pair_type{ "left", ValueType::Left },
|
||||
pair_type{ "right", ValueType::Right },
|
||||
pair_type{ "up", ValueType::Up },
|
||||
|
@ -345,6 +345,7 @@ JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Settings::Model::FocusDirection)
|
|||
pair_type{ "previous", ValueType::Previous },
|
||||
pair_type{ "previousInOrder", ValueType::PreviousInOrder },
|
||||
pair_type{ "nextInOrder", ValueType::NextInOrder },
|
||||
pair_type{ "first", ValueType::First },
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -480,3 +481,11 @@ JSON_FLAG_MAPPER(::winrt::Microsoft::Terminal::Settings::Model::IntenseStyle)
|
|||
pair_type{ "all", AllSet },
|
||||
};
|
||||
};
|
||||
|
||||
JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Settings::Model::InfoBarMessage)
|
||||
{
|
||||
JSON_MAPPINGS(2) = {
|
||||
pair_type{ "keyboardServiceWarning", ValueType::KeyboardServiceWarning },
|
||||
pair_type{ "setAsDefault", ValueType::SetAsDefault },
|
||||
};
|
||||
};
|
||||
|
|
|
@ -29,8 +29,8 @@
|
|||
"disableAnimations": false,
|
||||
"startupActions": "",
|
||||
"focusFollowMouse": false,
|
||||
"minimizeToTray": false,
|
||||
"alwaysShowTrayIcon": false,
|
||||
"minimizeToNotificationArea": false,
|
||||
"alwaysShowNotificationIcon": false,
|
||||
|
||||
"profiles":
|
||||
[
|
||||
|
@ -348,6 +348,7 @@
|
|||
{ "command": { "action": "moveFocus", "direction": "previous" }, "keys": "ctrl+alt+left"},
|
||||
{ "command": { "action": "moveFocus", "direction": "previousInOrder" } },
|
||||
{ "command": { "action": "moveFocus", "direction": "nextInOrder" } },
|
||||
{ "command": { "action": "moveFocus", "direction": "first" } },
|
||||
{ "command": { "action": "swapPane", "direction": "down" } },
|
||||
{ "command": { "action": "swapPane", "direction": "left" } },
|
||||
{ "command": { "action": "swapPane", "direction": "right" } },
|
||||
|
@ -355,6 +356,7 @@
|
|||
{ "command": { "action": "swapPane", "direction": "previous"} },
|
||||
{ "command": { "action": "swapPane", "direction": "previousInOrder"} },
|
||||
{ "command": { "action": "swapPane", "direction": "nextInOrder"} },
|
||||
{ "command": { "action": "swapPane", "direction": "first" } },
|
||||
{ "command": "togglePaneZoom" },
|
||||
{ "command": "toggleSplitOrientation" },
|
||||
{ "command": "toggleReadOnlyMode" },
|
||||
|
|
|
@ -71,16 +71,16 @@ namespace RemotingUnitTests
|
|||
Remoting::WindowActivatedArgs GetLastActivatedArgs() { throw winrt::hresult_error{}; }
|
||||
void RequestRename(const Remoting::RenameRequestArgs& /*args*/) { throw winrt::hresult_error{}; }
|
||||
void Summon(const Remoting::SummonWindowBehavior& /*args*/) { throw winrt::hresult_error{}; };
|
||||
void RequestShowTrayIcon() { throw winrt::hresult_error{}; };
|
||||
void RequestHideTrayIcon() { throw winrt::hresult_error{}; };
|
||||
void RequestShowNotificationIcon() { throw winrt::hresult_error{}; };
|
||||
void RequestHideNotificationIcon() { throw winrt::hresult_error{}; };
|
||||
TYPED_EVENT(WindowActivated, winrt::Windows::Foundation::IInspectable, Remoting::WindowActivatedArgs);
|
||||
TYPED_EVENT(ExecuteCommandlineRequested, winrt::Windows::Foundation::IInspectable, Remoting::CommandlineArgs);
|
||||
TYPED_EVENT(IdentifyWindowsRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(DisplayWindowIdRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(RenameRequested, winrt::Windows::Foundation::IInspectable, Remoting::RenameRequestArgs);
|
||||
TYPED_EVENT(SummonRequested, winrt::Windows::Foundation::IInspectable, Remoting::SummonWindowBehavior);
|
||||
TYPED_EVENT(ShowTrayIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(HideTrayIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(ShowNotificationIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(HideNotificationIconRequested, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
};
|
||||
|
||||
class RemotingTests
|
||||
|
|
|
@ -63,7 +63,7 @@ AppHost::AppHost() noexcept :
|
|||
// Update our own internal state tracking if we're in quake mode or not.
|
||||
_IsQuakeWindowChanged(nullptr, nullptr);
|
||||
|
||||
_window->SetMinimizeToTrayBehavior(_logic.GetMinimizeToTray());
|
||||
_window->SetMinimizeToNotificationAreaBehavior(_logic.GetMinimizeToNotificationArea());
|
||||
|
||||
// Tell the window to callback to us when it's about to handle a WM_CREATE
|
||||
auto pfn = std::bind(&AppHost::_HandleCreateWindow,
|
||||
|
@ -320,13 +320,13 @@ void AppHost::AppTitleChanged(const winrt::Windows::Foundation::IInspectable& /*
|
|||
// - <none>
|
||||
void AppHost::LastTabClosed(const winrt::Windows::Foundation::IInspectable& /*sender*/, const winrt::TerminalApp::LastTabClosedEventArgs& /*args*/)
|
||||
{
|
||||
if (_windowManager.IsMonarch() && _trayIcon)
|
||||
if (_windowManager.IsMonarch() && _notificationIcon)
|
||||
{
|
||||
_DestroyTrayIcon();
|
||||
_DestroyNotificationIcon();
|
||||
}
|
||||
else if (_window->IsQuakeWindow())
|
||||
{
|
||||
_HideTrayIconRequested();
|
||||
_HideNotificationIconRequested();
|
||||
}
|
||||
|
||||
_window->Close();
|
||||
|
@ -663,14 +663,14 @@ void AppHost::_BecomeMonarch(const winrt::Windows::Foundation::IInspectable& /*s
|
|||
|
||||
if (_windowManager.DoesQuakeWindowExist() ||
|
||||
_window->IsQuakeWindow() ||
|
||||
(_logic.GetAlwaysShowTrayIcon() || _logic.GetMinimizeToTray()))
|
||||
(_logic.GetAlwaysShowNotificationIcon() || _logic.GetMinimizeToNotificationArea()))
|
||||
{
|
||||
_CreateTrayIcon();
|
||||
_CreateNotificationIcon();
|
||||
}
|
||||
|
||||
// These events are coming from peasants that become or un-become quake windows.
|
||||
_windowManager.ShowTrayIconRequested([this](auto&&, auto&&) { _ShowTrayIconRequested(); });
|
||||
_windowManager.HideTrayIconRequested([this](auto&&, auto&&) { _HideTrayIconRequested(); });
|
||||
_windowManager.ShowNotificationIconRequested([this](auto&&, auto&&) { _ShowNotificationIconRequested(); });
|
||||
_windowManager.HideNotificationIconRequested([this](auto&&, auto&&) { _HideNotificationIconRequested(); });
|
||||
}
|
||||
|
||||
void AppHost::_listenForInboundConnections()
|
||||
|
@ -957,12 +957,12 @@ void AppHost::_HandleSettingsChanged(const winrt::Windows::Foundation::IInspecta
|
|||
{
|
||||
_setupGlobalHotkeys();
|
||||
|
||||
// If we're monarch, we need to check some conditions to show the tray icon.
|
||||
// If there's a Quake window somewhere, we'll want to keep the tray icon.
|
||||
// There's two settings - MinimizeToTray and AlwaysShowTrayIcon. If either
|
||||
// one of them are true, we want to make sure there's a tray icon.
|
||||
// If both are false, we want to remove our icon from the tray.
|
||||
// When we remove our icon from the tray, we'll also want to re-summon
|
||||
// If we're monarch, we need to check some conditions to show the notification icon.
|
||||
// If there's a Quake window somewhere, we'll want to keep the notification icon.
|
||||
// There's two settings - MinimizeToNotificationArea and AlwaysShowNotificationIcon. If either
|
||||
// one of them are true, we want to make sure there's a notification icon.
|
||||
// If both are false, we want to remove our icon from the notification area.
|
||||
// When we remove our icon from the notification area, we'll also want to re-summon
|
||||
// any hidden windows, but right now we're not keeping track of who's hidden,
|
||||
// so just summon them all. Tracking the work to do a "summon all minimized" in
|
||||
// GH#10448
|
||||
|
@ -970,36 +970,36 @@ void AppHost::_HandleSettingsChanged(const winrt::Windows::Foundation::IInspecta
|
|||
{
|
||||
if (!_windowManager.DoesQuakeWindowExist())
|
||||
{
|
||||
if (!_trayIcon && (_logic.GetMinimizeToTray() || _logic.GetAlwaysShowTrayIcon()))
|
||||
if (!_notificationIcon && (_logic.GetMinimizeToNotificationArea() || _logic.GetAlwaysShowNotificationIcon()))
|
||||
{
|
||||
_CreateTrayIcon();
|
||||
_CreateNotificationIcon();
|
||||
}
|
||||
else if (_trayIcon && !_logic.GetMinimizeToTray() && !_logic.GetAlwaysShowTrayIcon())
|
||||
else if (_notificationIcon && !_logic.GetMinimizeToNotificationArea() && !_logic.GetAlwaysShowNotificationIcon())
|
||||
{
|
||||
_windowManager.SummonAllWindows();
|
||||
_DestroyTrayIcon();
|
||||
_DestroyNotificationIcon();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_window->SetMinimizeToTrayBehavior(_logic.GetMinimizeToTray());
|
||||
_window->SetMinimizeToNotificationAreaBehavior(_logic.GetMinimizeToNotificationArea());
|
||||
}
|
||||
|
||||
void AppHost::_IsQuakeWindowChanged(const winrt::Windows::Foundation::IInspectable&,
|
||||
const winrt::Windows::Foundation::IInspectable&)
|
||||
{
|
||||
// We want the quake window to be accessible through the tray icon.
|
||||
// This means if there's a quake window _somewhere_, we want the tray icon
|
||||
// to show regardless of the tray icon settings.
|
||||
// This also means we'll need to destroy the tray icon if it was created
|
||||
// We want the quake window to be accessible through the notification icon.
|
||||
// This means if there's a quake window _somewhere_, we want the notification icon
|
||||
// to show regardless of the notification icon settings.
|
||||
// This also means we'll need to destroy the notification icon if it was created
|
||||
// specifically for the quake window. If not, it should not be destroyed.
|
||||
if (!_window->IsQuakeWindow() && _logic.IsQuakeWindow())
|
||||
{
|
||||
_ShowTrayIconRequested();
|
||||
_ShowNotificationIconRequested();
|
||||
}
|
||||
else if (_window->IsQuakeWindow() && !_logic.IsQuakeWindow())
|
||||
{
|
||||
_HideTrayIconRequested();
|
||||
_HideNotificationIconRequested();
|
||||
}
|
||||
|
||||
_window->IsQuakeWindow(_logic.IsQuakeWindow());
|
||||
|
@ -1017,81 +1017,81 @@ void AppHost::_SummonWindowRequested(const winrt::Windows::Foundation::IInspecta
|
|||
}
|
||||
|
||||
// Method Description:
|
||||
// - Creates a Tray Icon and hooks up its handlers
|
||||
// - Creates a Notification Icon and hooks up its handlers
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void AppHost::_CreateTrayIcon()
|
||||
void AppHost::_CreateNotificationIcon()
|
||||
{
|
||||
if constexpr (Feature_TrayIcon::IsEnabled())
|
||||
if constexpr (Feature_NotificationIcon::IsEnabled())
|
||||
{
|
||||
_trayIcon = std::make_unique<TrayIcon>(_window->GetHandle());
|
||||
_notificationIcon = std::make_unique<NotificationIcon>(_window->GetHandle());
|
||||
|
||||
// Hookup the handlers, save the tokens for revoking if settings change.
|
||||
_ReAddTrayIconToken = _window->NotifyReAddTrayIcon([this]() { _trayIcon->ReAddTrayIcon(); });
|
||||
_TrayIconPressedToken = _window->NotifyTrayIconPressed([this]() { _trayIcon->TrayIconPressed(); });
|
||||
_ShowTrayContextMenuToken = _window->NotifyShowTrayContextMenu([this](til::point coord) { _trayIcon->ShowTrayContextMenu(coord, _windowManager.GetPeasantNames()); });
|
||||
_TrayMenuItemSelectedToken = _window->NotifyTrayMenuItemSelected([this](HMENU hm, UINT idx) { _trayIcon->TrayMenuItemSelected(hm, idx); });
|
||||
_trayIcon->SummonWindowRequested([this](auto& args) { _windowManager.SummonWindow(args); });
|
||||
_ReAddNotificationIconToken = _window->NotifyReAddNotificationIcon([this]() { _notificationIcon->ReAddNotificationIcon(); });
|
||||
_NotificationIconPressedToken = _window->NotifyNotificationIconPressed([this]() { _notificationIcon->NotificationIconPressed(); });
|
||||
_ShowNotificationIconContextMenuToken = _window->NotifyShowNotificationIconContextMenu([this](til::point coord) { _notificationIcon->ShowContextMenu(coord, _windowManager.GetPeasantNames()); });
|
||||
_NotificationIconMenuItemSelectedToken = _window->NotifyNotificationIconMenuItemSelected([this](HMENU hm, UINT idx) { _notificationIcon->MenuItemSelected(hm, idx); });
|
||||
_notificationIcon->SummonWindowRequested([this](auto& args) { _windowManager.SummonWindow(args); });
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Deletes our tray icon if we have one.
|
||||
// - Deletes our notification icon if we have one.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void AppHost::_DestroyTrayIcon()
|
||||
void AppHost::_DestroyNotificationIcon()
|
||||
{
|
||||
if constexpr (Feature_TrayIcon::IsEnabled())
|
||||
if constexpr (Feature_NotificationIcon::IsEnabled())
|
||||
{
|
||||
_window->NotifyReAddTrayIcon(_ReAddTrayIconToken);
|
||||
_window->NotifyTrayIconPressed(_TrayIconPressedToken);
|
||||
_window->NotifyShowTrayContextMenu(_ShowTrayContextMenuToken);
|
||||
_window->NotifyTrayMenuItemSelected(_TrayMenuItemSelectedToken);
|
||||
_window->NotifyReAddNotificationIcon(_ReAddNotificationIconToken);
|
||||
_window->NotifyNotificationIconPressed(_NotificationIconPressedToken);
|
||||
_window->NotifyShowNotificationIconContextMenu(_ShowNotificationIconContextMenuToken);
|
||||
_window->NotifyNotificationIconMenuItemSelected(_NotificationIconMenuItemSelectedToken);
|
||||
|
||||
_trayIcon->RemoveIconFromTray();
|
||||
_trayIcon = nullptr;
|
||||
_notificationIcon->RemoveIconFromNotificationArea();
|
||||
_notificationIcon = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void AppHost::_ShowTrayIconRequested()
|
||||
void AppHost::_ShowNotificationIconRequested()
|
||||
{
|
||||
if constexpr (Feature_TrayIcon::IsEnabled())
|
||||
if constexpr (Feature_NotificationIcon::IsEnabled())
|
||||
{
|
||||
if (_windowManager.IsMonarch())
|
||||
{
|
||||
if (!_trayIcon)
|
||||
if (!_notificationIcon)
|
||||
{
|
||||
_CreateTrayIcon();
|
||||
_CreateNotificationIcon();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_windowManager.RequestShowTrayIcon();
|
||||
_windowManager.RequestShowNotificationIcon();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AppHost::_HideTrayIconRequested()
|
||||
void AppHost::_HideNotificationIconRequested()
|
||||
{
|
||||
if constexpr (Feature_TrayIcon::IsEnabled())
|
||||
if constexpr (Feature_NotificationIcon::IsEnabled())
|
||||
{
|
||||
if (_windowManager.IsMonarch())
|
||||
{
|
||||
// Destroy it only if our settings allow it
|
||||
if (_trayIcon &&
|
||||
!_logic.GetAlwaysShowTrayIcon() &&
|
||||
!_logic.GetMinimizeToTray())
|
||||
if (_notificationIcon &&
|
||||
!_logic.GetAlwaysShowNotificationIcon() &&
|
||||
!_logic.GetMinimizeToNotificationArea())
|
||||
{
|
||||
_DestroyTrayIcon();
|
||||
_DestroyNotificationIcon();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_windowManager.RequestHideTrayIcon();
|
||||
_windowManager.RequestHideNotificationIcon();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1108,16 +1108,30 @@ void AppHost::_WindowMoved()
|
|||
{
|
||||
if (_logic)
|
||||
{
|
||||
// Ensure any open ContentDialog is dismissed.
|
||||
// Closing the popup in the UI tree as done below is not sufficient because
|
||||
// it does not terminate the dialog's async operation.
|
||||
_logic.DismissDialog();
|
||||
|
||||
const auto root{ _logic.GetRoot() };
|
||||
|
||||
// This is basically DismissAllPopups which is also in
|
||||
// TerminalSettingsEditor/Utils.h
|
||||
// There isn't a good place that's shared between these two files, but
|
||||
// it's only 5 LOC so whatever.
|
||||
const auto popups{ Media::VisualTreeHelper::GetOpenPopupsForXamlRoot(root.XamlRoot()) };
|
||||
for (const auto& p : popups)
|
||||
try
|
||||
{
|
||||
p.IsOpen(false);
|
||||
// This is basically DismissAllPopups which is also in
|
||||
// TerminalSettingsEditor/Utils.h
|
||||
// There isn't a good place that's shared between these two files, but
|
||||
// it's only 5 LOC so whatever.
|
||||
const auto popups{ Media::VisualTreeHelper::GetOpenPopupsForXamlRoot(root.XamlRoot()) };
|
||||
for (const auto& p : popups)
|
||||
{
|
||||
p.IsOpen(false);
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// We purposely don't log here, because this is exceptionally noisy,
|
||||
// especially on startup, when we're moving the window into place
|
||||
// but might not have a real xamlRoot yet.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include "pch.h"
|
||||
#include "NonClientIslandWindow.h"
|
||||
#include "TrayIcon.h"
|
||||
#include "NotificationIcon.h"
|
||||
|
||||
class AppHost
|
||||
{
|
||||
|
@ -85,13 +85,13 @@ private:
|
|||
void _SummonWindowRequested(const winrt::Windows::Foundation::IInspectable& sender,
|
||||
const winrt::Windows::Foundation::IInspectable& args);
|
||||
|
||||
void _CreateTrayIcon();
|
||||
void _DestroyTrayIcon();
|
||||
void _ShowTrayIconRequested();
|
||||
void _HideTrayIconRequested();
|
||||
std::unique_ptr<TrayIcon> _trayIcon;
|
||||
winrt::event_token _ReAddTrayIconToken;
|
||||
winrt::event_token _TrayIconPressedToken;
|
||||
winrt::event_token _ShowTrayContextMenuToken;
|
||||
winrt::event_token _TrayMenuItemSelectedToken;
|
||||
void _CreateNotificationIcon();
|
||||
void _DestroyNotificationIcon();
|
||||
void _ShowNotificationIconRequested();
|
||||
void _HideNotificationIconRequested();
|
||||
std::unique_ptr<NotificationIcon> _notificationIcon;
|
||||
winrt::event_token _ReAddNotificationIconToken;
|
||||
winrt::event_token _NotificationIconPressedToken;
|
||||
winrt::event_token _ShowNotificationIconContextMenuToken;
|
||||
winrt::event_token _NotificationIconMenuItemSelectedToken;
|
||||
};
|
||||
|
|
|
@ -5,4 +5,4 @@
|
|||
|
||||
// Custom window messages
|
||||
#define CM_UPDATE_TITLE (WM_USER)
|
||||
#define CM_NOTIFY_FROM_TRAY (WM_USER + 1)
|
||||
#define CM_NOTIFY_FROM_NOTIFICATION_AREA (WM_USER + 1)
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include "../types/inc/Viewport.hpp"
|
||||
#include "resource.h"
|
||||
#include "icon.h"
|
||||
#include "TrayIcon.h"
|
||||
#include "NotificationIcon.h"
|
||||
|
||||
extern "C" IMAGE_DOS_HEADER __ImageBase;
|
||||
|
||||
|
@ -570,20 +570,20 @@ long IslandWindow::_calculateTotalSize(const bool isWidth, const long clientSize
|
|||
}
|
||||
}
|
||||
}
|
||||
case CM_NOTIFY_FROM_TRAY:
|
||||
case CM_NOTIFY_FROM_NOTIFICATION_AREA:
|
||||
{
|
||||
switch (LOWORD(lparam))
|
||||
{
|
||||
case NIN_SELECT:
|
||||
case NIN_KEYSELECT:
|
||||
{
|
||||
_NotifyTrayIconPressedHandlers();
|
||||
_NotifyNotificationIconPressedHandlers();
|
||||
return 0;
|
||||
}
|
||||
case WM_CONTEXTMENU:
|
||||
{
|
||||
const til::point eventPoint{ GET_X_LPARAM(wparam), GET_Y_LPARAM(wparam) };
|
||||
_NotifyShowTrayContextMenuHandlers(eventPoint);
|
||||
_NotifyShowNotificationIconContextMenuHandlers(eventPoint);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -591,17 +591,17 @@ long IslandWindow::_calculateTotalSize(const bool isWidth, const long clientSize
|
|||
}
|
||||
case WM_MENUCOMMAND:
|
||||
{
|
||||
_NotifyTrayMenuItemSelectedHandlers((HMENU)lparam, (UINT)wparam);
|
||||
_NotifyNotificationIconMenuItemSelectedHandlers((HMENU)lparam, (UINT)wparam);
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
// We'll want to receive this message when explorer.exe restarts
|
||||
// so that we can re-add our icon to the tray.
|
||||
// so that we can re-add our icon to the notification area.
|
||||
// This unfortunately isn't a switch case because we register the
|
||||
// message at runtime.
|
||||
if (message == WM_TASKBARCREATED)
|
||||
{
|
||||
_NotifyReAddTrayIconHandlers();
|
||||
_NotifyReAddNotificationIconHandlers();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -628,7 +628,7 @@ void IslandWindow::OnResize(const UINT width, const UINT height)
|
|||
void IslandWindow::OnMinimize()
|
||||
{
|
||||
// TODO GH#1989 Stop rendering island content when the app is minimized.
|
||||
if (_minimizeToTray)
|
||||
if (_minimizeToNotificationArea)
|
||||
{
|
||||
HideWindow();
|
||||
}
|
||||
|
@ -1640,9 +1640,9 @@ void IslandWindow::HideWindow()
|
|||
ShowWindow(GetHandle(), SW_HIDE);
|
||||
}
|
||||
|
||||
void IslandWindow::SetMinimizeToTrayBehavior(bool minimizeToTray) noexcept
|
||||
void IslandWindow::SetMinimizeToNotificationAreaBehavior(bool MinimizeToNotificationArea) noexcept
|
||||
{
|
||||
_minimizeToTray = minimizeToTray;
|
||||
_minimizeToNotificationArea = MinimizeToNotificationArea;
|
||||
}
|
||||
|
||||
DEFINE_EVENT(IslandWindow, DragRegionClicked, _DragRegionClickedHandlers, winrt::delegate<>);
|
||||
|
|
|
@ -49,18 +49,18 @@ public:
|
|||
|
||||
void HideWindow();
|
||||
|
||||
void SetMinimizeToTrayBehavior(bool minimizeToTray) noexcept;
|
||||
void SetMinimizeToNotificationAreaBehavior(bool MinimizeToNotificationArea) noexcept;
|
||||
|
||||
DECLARE_EVENT(DragRegionClicked, _DragRegionClickedHandlers, winrt::delegate<>);
|
||||
DECLARE_EVENT(WindowCloseButtonClicked, _windowCloseButtonClickedHandler, winrt::delegate<>);
|
||||
WINRT_CALLBACK(MouseScrolled, winrt::delegate<void(til::point, int32_t)>);
|
||||
WINRT_CALLBACK(WindowActivated, winrt::delegate<void()>);
|
||||
WINRT_CALLBACK(HotkeyPressed, winrt::delegate<void(long)>);
|
||||
WINRT_CALLBACK(NotifyTrayIconPressed, winrt::delegate<void()>);
|
||||
WINRT_CALLBACK(NotifyNotificationIconPressed, winrt::delegate<void()>);
|
||||
WINRT_CALLBACK(NotifyWindowHidden, winrt::delegate<void()>);
|
||||
WINRT_CALLBACK(NotifyShowTrayContextMenu, winrt::delegate<void(til::point)>);
|
||||
WINRT_CALLBACK(NotifyTrayMenuItemSelected, winrt::delegate<void(HMENU, UINT)>);
|
||||
WINRT_CALLBACK(NotifyReAddTrayIcon, winrt::delegate<void()>);
|
||||
WINRT_CALLBACK(NotifyShowNotificationIconContextMenu, winrt::delegate<void(til::point)>);
|
||||
WINRT_CALLBACK(NotifyNotificationIconMenuItemSelected, winrt::delegate<void(HMENU, UINT)>);
|
||||
WINRT_CALLBACK(NotifyReAddNotificationIcon, winrt::delegate<void()>);
|
||||
|
||||
WINRT_CALLBACK(WindowMoved, winrt::delegate<void()>);
|
||||
|
||||
|
@ -125,7 +125,7 @@ protected:
|
|||
|
||||
void _summonWindowRoutineBody(winrt::Microsoft::Terminal::Remoting::SummonWindowBehavior args);
|
||||
|
||||
bool _minimizeToTray{ false };
|
||||
bool _minimizeToNotificationArea{ false };
|
||||
|
||||
private:
|
||||
// This minimum width allows for width the tabs fit
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include "pch.h"
|
||||
#include "icon.h"
|
||||
#include "TrayIcon.h"
|
||||
#include "NotificationIcon.h"
|
||||
#include "CustomWindowMessages.h"
|
||||
|
||||
#include <ScopedResourceLoader.h>
|
||||
|
@ -12,54 +12,54 @@
|
|||
using namespace winrt::Windows::Foundation::Collections;
|
||||
using namespace winrt::Microsoft::Terminal;
|
||||
|
||||
TrayIcon::TrayIcon(const HWND owningHwnd) :
|
||||
NotificationIcon::NotificationIcon(const HWND owningHwnd) :
|
||||
_owningHwnd{ owningHwnd }
|
||||
{
|
||||
CreateTrayIcon();
|
||||
CreateNotificationIcon();
|
||||
}
|
||||
|
||||
TrayIcon::~TrayIcon()
|
||||
NotificationIcon::~NotificationIcon()
|
||||
{
|
||||
RemoveIconFromTray();
|
||||
RemoveIconFromNotificationArea();
|
||||
}
|
||||
|
||||
void TrayIcon::_CreateWindow()
|
||||
void NotificationIcon::_CreateWindow()
|
||||
{
|
||||
WNDCLASSW wc{};
|
||||
wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
|
||||
wc.hInstance = wil::GetModuleInstanceHandle();
|
||||
wc.lpszClassName = L"TRAY_ICON_HOSTING_WINDOW_CLASS";
|
||||
wc.lpszClassName = L"NOTIFICATION_ICON_HOSTING_WINDOW_CLASS";
|
||||
wc.style = CS_HREDRAW | CS_VREDRAW;
|
||||
wc.lpfnWndProc = DefWindowProcW;
|
||||
wc.hIcon = static_cast<HICON>(GetActiveAppIconHandle(true));
|
||||
RegisterClass(&wc);
|
||||
|
||||
_trayIconHwnd = wil::unique_hwnd(CreateWindowW(wc.lpszClassName,
|
||||
wc.lpszClassName,
|
||||
WS_DISABLED,
|
||||
CW_USEDEFAULT,
|
||||
CW_USEDEFAULT,
|
||||
CW_USEDEFAULT,
|
||||
CW_USEDEFAULT,
|
||||
HWND_MESSAGE,
|
||||
nullptr,
|
||||
wc.hInstance,
|
||||
nullptr));
|
||||
_notificationIconHwnd = wil::unique_hwnd(CreateWindowW(wc.lpszClassName,
|
||||
wc.lpszClassName,
|
||||
WS_DISABLED,
|
||||
CW_USEDEFAULT,
|
||||
CW_USEDEFAULT,
|
||||
CW_USEDEFAULT,
|
||||
CW_USEDEFAULT,
|
||||
HWND_MESSAGE,
|
||||
nullptr,
|
||||
wc.hInstance,
|
||||
nullptr));
|
||||
|
||||
WINRT_VERIFY(_trayIconHwnd);
|
||||
WINRT_VERIFY(_notificationIconHwnd);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Creates and adds an icon to the notification tray.
|
||||
// - Creates and adds an icon to the notification area.
|
||||
// If an icon already exists, update the HWND associated
|
||||
// to the icon with this window's HWND.
|
||||
// Arguments:
|
||||
// - <unused>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TrayIcon::CreateTrayIcon()
|
||||
void NotificationIcon::CreateNotificationIcon()
|
||||
{
|
||||
if (!_trayIconHwnd)
|
||||
if (!_notificationIconHwnd)
|
||||
{
|
||||
// Creating a disabled, non visible window just so we can set it
|
||||
// as the foreground window when showing the context menu.
|
||||
|
@ -71,7 +71,7 @@ void TrayIcon::CreateTrayIcon()
|
|||
NOTIFYICONDATA nid{};
|
||||
nid.cbSize = sizeof(NOTIFYICONDATA);
|
||||
|
||||
// This HWND will receive the callbacks sent by the tray icon.
|
||||
// This HWND will receive the callbacks sent by the notification icon.
|
||||
nid.hWnd = _owningHwnd;
|
||||
|
||||
// App-defined identifier of the icon. The HWND and ID are used
|
||||
|
@ -80,7 +80,7 @@ void TrayIcon::CreateTrayIcon()
|
|||
// going to be showing one so the ID doesn't really matter.
|
||||
nid.uID = 1;
|
||||
|
||||
nid.uCallbackMessage = CM_NOTIFY_FROM_TRAY;
|
||||
nid.uCallbackMessage = CM_NOTIFY_FROM_NOTIFICATION_AREA;
|
||||
|
||||
// AppName happens to be in CascadiaPackage's Resources.
|
||||
ScopedResourceLoader loader{ L"Resources" };
|
||||
|
@ -98,7 +98,7 @@ void TrayIcon::CreateTrayIcon()
|
|||
nid.uVersion = NOTIFYICON_VERSION_4;
|
||||
Shell_NotifyIcon(NIM_SETVERSION, &nid);
|
||||
|
||||
_trayIconData = nid;
|
||||
_notificationIconData = nid;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -109,14 +109,14 @@ void TrayIcon::CreateTrayIcon()
|
|||
// - peasants: The map of all peasants that should be available in the context menu.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TrayIcon::ShowTrayContextMenu(const til::point coord,
|
||||
IMapView<uint64_t, winrt::hstring> peasants)
|
||||
void NotificationIcon::ShowContextMenu(const til::point& coord,
|
||||
IMapView<uint64_t, winrt::hstring> peasants)
|
||||
{
|
||||
if (const auto hMenu = _CreateTrayContextMenu(peasants))
|
||||
if (const auto hMenu = _CreateContextMenu(peasants))
|
||||
{
|
||||
// We'll need to set our window to the foreground before calling
|
||||
// TrackPopupMenuEx or else the menu won't dismiss when clicking away.
|
||||
SetForegroundWindow(_trayIconHwnd.get());
|
||||
SetForegroundWindow(_notificationIconHwnd.get());
|
||||
|
||||
// User can select menu items with the left and right buttons.
|
||||
UINT uFlags = TPM_RIGHTBUTTON;
|
||||
|
@ -137,12 +137,12 @@ void TrayIcon::ShowTrayContextMenu(const til::point coord,
|
|||
}
|
||||
|
||||
// Method Description:
|
||||
// - This creates the context menu for our tray icon.
|
||||
// - This creates the context menu for our notification icon.
|
||||
// Arguments:
|
||||
// - peasants: A map of all peasants' ID to their window name.
|
||||
// Return Value:
|
||||
// - The handle to the newly created context menu.
|
||||
HMENU TrayIcon::_CreateTrayContextMenu(IMapView<uint64_t, winrt::hstring> peasants)
|
||||
HMENU NotificationIcon::_CreateContextMenu(IMapView<uint64_t, winrt::hstring> peasants)
|
||||
{
|
||||
auto hMenu = CreatePopupMenu();
|
||||
if (hMenu)
|
||||
|
@ -155,7 +155,7 @@ HMENU TrayIcon::_CreateTrayContextMenu(IMapView<uint64_t, winrt::hstring> peasan
|
|||
SetMenuInfo(hMenu, &mi);
|
||||
|
||||
// Focus Current Terminal Window
|
||||
AppendMenu(hMenu, MF_STRING, gsl::narrow<UINT_PTR>(TrayMenuItemAction::FocusTerminal), RS_(L"TrayIconFocusTerminal").c_str());
|
||||
AppendMenu(hMenu, MF_STRING, gsl::narrow<UINT_PTR>(NotificationIconMenuItemAction::FocusTerminal), RS_(L"NotificationIconFocusTerminal").c_str());
|
||||
AppendMenu(hMenu, MF_SEPARATOR, 0, L"");
|
||||
|
||||
// Submenu for Windows
|
||||
|
@ -178,10 +178,10 @@ HMENU TrayIcon::_CreateTrayContextMenu(IMapView<uint64_t, winrt::hstring> peasan
|
|||
submenuInfo.cbSize = sizeof(MENUINFO);
|
||||
submenuInfo.fMask = MIM_MENUDATA;
|
||||
submenuInfo.dwStyle = MNS_NOTIFYBYPOS;
|
||||
submenuInfo.dwMenuData = (UINT_PTR)TrayMenuItemAction::SummonWindow;
|
||||
submenuInfo.dwMenuData = (UINT_PTR)NotificationIconMenuItemAction::SummonWindow;
|
||||
SetMenuInfo(submenu, &submenuInfo);
|
||||
|
||||
AppendMenu(hMenu, MF_POPUP, (UINT_PTR)submenu, RS_(L"TrayIconWindowSubmenu").c_str());
|
||||
AppendMenu(hMenu, MF_POPUP, (UINT_PTR)submenu, RS_(L"NotificationIconWindowSubmenu").c_str());
|
||||
}
|
||||
}
|
||||
return hMenu;
|
||||
|
@ -189,13 +189,13 @@ HMENU TrayIcon::_CreateTrayContextMenu(IMapView<uint64_t, winrt::hstring> peasan
|
|||
|
||||
// Method Description:
|
||||
// - This is the handler for when one of the menu items are selected within
|
||||
// the tray icon's context menu.
|
||||
// the notification icon's context menu.
|
||||
// Arguments:
|
||||
// - menu: The handle to the menu that holds the menu item that was selected.
|
||||
// - menuItemIndex: The index of the menu item within the given menu.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TrayIcon::TrayMenuItemSelected(const HMENU menu, const UINT menuItemIndex)
|
||||
void NotificationIcon::MenuItemSelected(const HMENU menu, const UINT menuItemIndex)
|
||||
{
|
||||
// Check the menu's data for a specific action.
|
||||
MENUINFO mi{};
|
||||
|
@ -204,7 +204,7 @@ void TrayIcon::TrayMenuItemSelected(const HMENU menu, const UINT menuItemIndex)
|
|||
GetMenuInfo(menu, &mi);
|
||||
if (mi.dwMenuData)
|
||||
{
|
||||
if (gsl::narrow<TrayMenuItemAction>(mi.dwMenuData) == TrayMenuItemAction::SummonWindow)
|
||||
if (gsl::narrow<NotificationIconMenuItemAction>(mi.dwMenuData) == NotificationIconMenuItemAction::SummonWindow)
|
||||
{
|
||||
winrt::Microsoft::Terminal::Remoting::SummonWindowSelectionArgs args{};
|
||||
args.WindowID(GetMenuItemID(menu, menuItemIndex));
|
||||
|
@ -217,10 +217,10 @@ void TrayIcon::TrayMenuItemSelected(const HMENU menu, const UINT menuItemIndex)
|
|||
}
|
||||
|
||||
// Now check the menu item itself for an action.
|
||||
const auto action = gsl::narrow<TrayMenuItemAction>(GetMenuItemID(menu, menuItemIndex));
|
||||
const auto action = gsl::narrow<NotificationIconMenuItemAction>(GetMenuItemID(menu, menuItemIndex));
|
||||
switch (action)
|
||||
{
|
||||
case TrayMenuItemAction::FocusTerminal:
|
||||
case NotificationIconMenuItemAction::FocusTerminal:
|
||||
{
|
||||
winrt::Microsoft::Terminal::Remoting::SummonWindowSelectionArgs args{};
|
||||
args.SummonBehavior().ToggleVisibility(false);
|
||||
|
@ -233,12 +233,12 @@ void TrayIcon::TrayMenuItemSelected(const HMENU menu, const UINT menuItemIndex)
|
|||
}
|
||||
|
||||
// Method Description:
|
||||
// - This is the handler for when the tray icon itself is left-clicked.
|
||||
// - This is the handler for when the notification icon itself is left-clicked.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TrayIcon::TrayIconPressed()
|
||||
void NotificationIcon::NotificationIconPressed()
|
||||
{
|
||||
// No name in the args means summon the mru window.
|
||||
winrt::Microsoft::Terminal::Remoting::SummonWindowSelectionArgs args{};
|
||||
|
@ -249,24 +249,24 @@ void TrayIcon::TrayIconPressed()
|
|||
}
|
||||
|
||||
// Method Description:
|
||||
// - Re-add a tray icon using our currently saved tray icon data.
|
||||
// - Re-add a notification icon using our currently saved notification icon data.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TrayIcon::ReAddTrayIcon()
|
||||
void NotificationIcon::ReAddNotificationIcon()
|
||||
{
|
||||
Shell_NotifyIcon(NIM_ADD, &_trayIconData);
|
||||
Shell_NotifyIcon(NIM_SETVERSION, &_trayIconData);
|
||||
Shell_NotifyIcon(NIM_ADD, &_notificationIconData);
|
||||
Shell_NotifyIcon(NIM_SETVERSION, &_notificationIconData);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Deletes our tray icon.
|
||||
// - Deletes our notification icon.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TrayIcon::RemoveIconFromTray()
|
||||
void NotificationIcon::RemoveIconFromNotificationArea()
|
||||
{
|
||||
Shell_NotifyIcon(NIM_DELETE, &_trayIconData);
|
||||
Shell_NotifyIcon(NIM_DELETE, &_notificationIconData);
|
||||
}
|
39
src/cascadia/WindowsTerminal/NotificationIcon.h
Normal file
39
src/cascadia/WindowsTerminal/NotificationIcon.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "../cascadia/inc/cppwinrt_utils.h"
|
||||
|
||||
// This enumerates all the possible actions
|
||||
// that our notification icon context menu could do.
|
||||
enum class NotificationIconMenuItemAction
|
||||
{
|
||||
FocusTerminal, // Focus the MRU terminal.
|
||||
SummonWindow
|
||||
};
|
||||
|
||||
class NotificationIcon
|
||||
{
|
||||
public:
|
||||
NotificationIcon() = delete;
|
||||
NotificationIcon(const HWND owningHwnd);
|
||||
~NotificationIcon();
|
||||
|
||||
void CreateNotificationIcon();
|
||||
void RemoveIconFromNotificationArea();
|
||||
void ReAddNotificationIcon();
|
||||
|
||||
void NotificationIconPressed();
|
||||
void ShowContextMenu(const til::point& coord, winrt::Windows::Foundation::Collections::IMapView<uint64_t, winrt::hstring> peasants);
|
||||
void MenuItemSelected(const HMENU menu, const UINT menuItemIndex);
|
||||
|
||||
WINRT_CALLBACK(SummonWindowRequested, winrt::delegate<void(winrt::Microsoft::Terminal::Remoting::SummonWindowSelectionArgs)>);
|
||||
|
||||
private:
|
||||
void _CreateWindow();
|
||||
HMENU _CreateContextMenu(winrt::Windows::Foundation::Collections::IMapView<uint64_t, winrt::hstring> peasants);
|
||||
|
||||
wil::unique_hwnd _notificationIconHwnd;
|
||||
HWND _owningHwnd;
|
||||
NOTIFYICONDATA _notificationIconData;
|
||||
};
|
|
@ -47,7 +47,7 @@
|
|||
<ClInclude Include="CustomWindowMessages.h" />
|
||||
<ClInclude Include="IslandWindow.h" />
|
||||
<ClInclude Include="NonClientIslandWindow.h" />
|
||||
<ClInclude Include="TrayIcon.h" />
|
||||
<ClInclude Include="NotificationIcon.h" />
|
||||
<ClInclude Include="VirtualDesktopUtils.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@ -58,7 +58,7 @@
|
|||
<ClCompile Include="AppHost.cpp" />
|
||||
<ClCompile Include="IslandWindow.cpp" />
|
||||
<ClCompile Include="NonClientIslandWindow.cpp" />
|
||||
<ClCompile Include="TrayIcon.cpp" />
|
||||
<ClCompile Include="NotificationIcon.cpp" />
|
||||
<ClCompile Include="VirtualDesktopUtils.cpp" />
|
||||
<ClCompile Include="icon.cpp" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -25,7 +25,7 @@ TRACELOGGING_DEFINE_PROVIDER(
|
|||
// !! BODGY !!
|
||||
// Manually use the resources from TerminalApp as our resources.
|
||||
// The WindowsTerminal project doesn't actually build a Resources.resw file, but
|
||||
// we still need to be able to localize strings for the tray icon menu. Anything
|
||||
// we still need to be able to localize strings for the notification icon menu. Anything
|
||||
// you want localized for WindowsTerminal.exe should be stuck in
|
||||
// ...\TerminalApp\Resources\en-US\Resources.resw
|
||||
#include <LibraryResources.h>
|
||||
|
|
|
@ -83,7 +83,8 @@
|
|||
|
||||
<!-- For ALL build types-->
|
||||
<PropertyGroup Label="Configuration">
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<PlatformToolset Condition="$(MSBuildVersion) < '17.0.0'">v142</PlatformToolset>
|
||||
<PlatformToolset Condition="$(MSBuildVersion) >= '17.0.0'">v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
<name>Feature_EditableActionsPage</name>
|
||||
<description>The Actions page in the settings UI should allow users to edit actions.</description>
|
||||
<stage>AlwaysEnabled</stage>
|
||||
<alwaysDisabledReleaseTokens/>
|
||||
</feature>
|
||||
|
||||
<feature>
|
||||
|
@ -65,8 +64,8 @@
|
|||
</feature>
|
||||
|
||||
<feature>
|
||||
<name>Feature_TrayIcon</name>
|
||||
<description>Controls whether the Tray Icon and related settings (aka. MinimizeToTray and AlwaysShowTrayIcon) are enabled</description>
|
||||
<name>Feature_NotificationIcon</name>
|
||||
<description>Controls whether the Notification Icon and related settings (aka. MinimizeToNotificationArea and AlwaysShowNotificationIcon) are enabled</description>
|
||||
<stage>AlwaysEnabled</stage>
|
||||
<alwaysDisabledReleaseTokens/>
|
||||
</feature>
|
||||
|
@ -76,7 +75,5 @@
|
|||
<description>Whether to show the "defaults" page in the Terminal settings UI</description>
|
||||
<id>10430</id>
|
||||
<stage>AlwaysEnabled</stage>
|
||||
<!-- This feature will not ship to Stable until it is complete. -->
|
||||
<alwaysDisabledReleaseTokens />
|
||||
</feature>
|
||||
</featureStaging>
|
||||
|
|
|
@ -69,5 +69,6 @@ public:
|
|||
const COORD GetSelectionAnchor() const noexcept;
|
||||
const COORD GetSelectionEnd() const noexcept;
|
||||
void ColorSelection(const COORD coordSelectionStart, const COORD coordSelectionEnd, const TextAttribute attr);
|
||||
const bool IsUiaDataInitialized() const noexcept override { return true; }
|
||||
#pragma endregion
|
||||
};
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
#include "../inc/conint.h"
|
||||
#include "../propslib/DelegationConfig.hpp"
|
||||
|
||||
#include "tracing.hpp"
|
||||
|
||||
#if TIL_FEATURE_RECEIVEINCOMINGHANDOFF_ENABLED
|
||||
#include "ITerminalHandoff.h"
|
||||
#endif // TIL_FEATURE_RECEIVEINCOMINGHANDOFF_ENABLED
|
||||
|
@ -69,10 +71,20 @@ try
|
|||
if (SUCCEEDED(DelegationConfig::s_GetDefaultConsoleId(delegationClsid)))
|
||||
{
|
||||
Globals.handoffConsoleClsid = delegationClsid;
|
||||
TraceLoggingWrite(g_hConhostV2EventTraceProvider,
|
||||
"SrvInit_FoundDelegationConsole",
|
||||
TraceLoggingGuid(Globals.handoffConsoleClsid.value(), "ConsoleClsid"),
|
||||
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||
}
|
||||
if (SUCCEEDED(DelegationConfig::s_GetDefaultTerminalId(delegationClsid)))
|
||||
{
|
||||
Globals.handoffTerminalClsid = delegationClsid;
|
||||
TraceLoggingWrite(g_hConhostV2EventTraceProvider,
|
||||
"SrvInit_FoundDelegationTerminal",
|
||||
TraceLoggingGuid(Globals.handoffTerminalClsid.value(), "TerminalClsid"),
|
||||
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -400,7 +412,16 @@ HRESULT ConsoleCreateIoThread(_In_ HANDLE Server,
|
|||
[[maybe_unused]] PCONSOLE_API_MSG connectMessage)
|
||||
try
|
||||
{
|
||||
// Create a telemetry instance here - this singleton is responsible for
|
||||
// setting up the g_hConhostV2EventTraceProvider, which is otherwise not
|
||||
// initialized in the defterm handoff at this point.
|
||||
(void)Telemetry::Instance();
|
||||
|
||||
#if !TIL_FEATURE_RECEIVEINCOMINGHANDOFF_ENABLED
|
||||
TraceLoggingWrite(g_hConhostV2EventTraceProvider,
|
||||
"SrvInit_ReceiveHandoff_Disabled",
|
||||
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
||||
#else // TIL_FEATURE_RECEIVEINCOMINGHANDOFF_ENABLED
|
||||
auto& g = ServiceLocator::LocateGlobals();
|
||||
|
@ -418,9 +439,19 @@ try
|
|||
|
||||
if (!g.handoffTerminalClsid)
|
||||
{
|
||||
TraceLoggingWrite(g_hConhostV2EventTraceProvider,
|
||||
"SrvInit_ReceiveHandoff_NoTerminal",
|
||||
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||
return E_NOT_SET;
|
||||
}
|
||||
|
||||
TraceLoggingWrite(g_hConhostV2EventTraceProvider,
|
||||
"SrvInit_ReceiveHandoff",
|
||||
TraceLoggingGuid(g.handoffTerminalClsid.value(), "TerminalClsid"),
|
||||
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||
|
||||
// Capture handle to the inbox process into a unique handle holder.
|
||||
g.handoffInboxConsoleHandle.reset(hostProcessHandle);
|
||||
|
||||
|
@ -453,9 +484,19 @@ try
|
|||
|
||||
RETURN_IF_WIN32_BOOL_FALSE(CreatePipe(outPipeTheirSide.addressof(), outPipeOurSide.addressof(), nullptr, 0));
|
||||
|
||||
wil::unique_handle clientProcess{ OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, TRUE, static_cast<DWORD>(connectMessage->Descriptor.Process)) };
|
||||
TraceLoggingWrite(g_hConhostV2EventTraceProvider,
|
||||
"SrvInit_ReceiveHandoff_OpenedPipes",
|
||||
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||
|
||||
wil::unique_handle clientProcess{ OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | SYNCHRONIZE, TRUE, static_cast<DWORD>(connectMessage->Descriptor.Process)) };
|
||||
RETURN_LAST_ERROR_IF_NULL(clientProcess.get());
|
||||
|
||||
TraceLoggingWrite(g_hConhostV2EventTraceProvider,
|
||||
"SrvInit_ReceiveHandoff_OpenedClient",
|
||||
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||
|
||||
wil::unique_handle refHandle;
|
||||
RETURN_IF_NTSTATUS_FAILED(DeviceHandle::CreateClientHandle(refHandle.addressof(),
|
||||
Server,
|
||||
|
@ -466,7 +507,18 @@ try
|
|||
|
||||
::Microsoft::WRL::ComPtr<ITerminalHandoff> handoff;
|
||||
|
||||
TraceLoggingWrite(g_hConhostV2EventTraceProvider,
|
||||
"SrvInit_PrepareToCreateDelegationTerminal",
|
||||
TraceLoggingGuid(g.handoffTerminalClsid.value(), "TerminalClsid"),
|
||||
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||
|
||||
RETURN_IF_FAILED(CoCreateInstance(g.handoffTerminalClsid.value(), nullptr, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&handoff)));
|
||||
TraceLoggingWrite(g_hConhostV2EventTraceProvider,
|
||||
"SrvInit_CreatedDelegationTerminal",
|
||||
TraceLoggingGuid(g.handoffTerminalClsid.value(), "TerminalClsid"),
|
||||
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||
|
||||
RETURN_IF_FAILED(handoff->EstablishPtyHandoff(inPipeTheirSide.get(),
|
||||
outPipeTheirSide.get(),
|
||||
|
@ -475,6 +527,11 @@ try
|
|||
serverProcess,
|
||||
clientProcess.get()));
|
||||
|
||||
TraceLoggingWrite(g_hConhostV2EventTraceProvider,
|
||||
"SrvInit_DelegateToTerminalSucceeded",
|
||||
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||
|
||||
inPipeTheirSide.reset();
|
||||
outPipeTheirSide.reset();
|
||||
signalPipeTheirSide.reset();
|
||||
|
|
|
@ -392,6 +392,11 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
const bool IsUiaDataInitialized() const noexcept
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
const std::wstring GetHyperlinkUri(uint16_t /*id*/) const noexcept
|
||||
{
|
||||
return {};
|
||||
|
|
|
@ -3,50 +3,36 @@
|
|||
|
||||
#include "precomp.h"
|
||||
#include "inc/Environment.hpp"
|
||||
#include "wil/token_helpers.h"
|
||||
|
||||
using namespace ::Microsoft::Console::Utils;
|
||||
|
||||
// We cannot use spand or not_null because we're dealing with \0\0-terminated buffers of unknown length
|
||||
#pragma warning(disable : 26481 26429)
|
||||
|
||||
// Function Description:
|
||||
// - Wraps win32's CreateEnvironmentBlock to return a smart pointer.
|
||||
EnvironmentBlockPtr Microsoft::Console::Utils::CreateEnvironmentBlock()
|
||||
{
|
||||
void* newEnvironmentBlock{ nullptr };
|
||||
auto processToken{ wil::open_current_access_token(TOKEN_QUERY | TOKEN_DUPLICATE) };
|
||||
if (!::CreateEnvironmentBlock(&newEnvironmentBlock, processToken.get(), FALSE))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return EnvironmentBlockPtr{ newEnvironmentBlock };
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - Updates an EnvironmentVariableMapW with the current process's unicode
|
||||
// environment variables ignoring ones already set in the provided map.
|
||||
// Arguments:
|
||||
// - map: The map to populate with the current processes's environment variables.
|
||||
// - environmentBlock: Optional environment block to use when filling map. If omitted,
|
||||
// defaults to the current environment.
|
||||
// Return Value:
|
||||
// - S_OK if we succeeded, or an appropriate HRESULT for failing
|
||||
HRESULT Microsoft::Console::Utils::UpdateEnvironmentMapW(EnvironmentVariableMapW& map, void* environmentBlock) noexcept
|
||||
HRESULT Microsoft::Console::Utils::UpdateEnvironmentMapW(EnvironmentVariableMapW& map) noexcept
|
||||
try
|
||||
{
|
||||
wchar_t const* activeEnvironmentBlock{ static_cast<wchar_t const*>(environmentBlock) };
|
||||
LPWCH currentEnvVars{};
|
||||
auto freeCurrentEnv = wil::scope_exit([&] {
|
||||
if (currentEnvVars)
|
||||
{
|
||||
FreeEnvironmentStringsW(currentEnvVars);
|
||||
currentEnvVars = nullptr;
|
||||
}
|
||||
});
|
||||
|
||||
wil::unique_environstrings_ptr currentEnvVars;
|
||||
if (!activeEnvironmentBlock)
|
||||
{
|
||||
currentEnvVars.reset(::GetEnvironmentStringsW());
|
||||
RETURN_HR_IF_NULL(E_OUTOFMEMORY, currentEnvVars);
|
||||
activeEnvironmentBlock = currentEnvVars.get();
|
||||
}
|
||||
currentEnvVars = ::GetEnvironmentStringsW();
|
||||
RETURN_HR_IF_NULL(E_OUTOFMEMORY, currentEnvVars);
|
||||
|
||||
// Each entry is NULL-terminated; block is guaranteed to be double-NULL terminated at a minimum.
|
||||
for (wchar_t const* lastCh{ activeEnvironmentBlock }; *lastCh != '\0'; ++lastCh)
|
||||
for (wchar_t const* lastCh{ currentEnvVars }; *lastCh != '\0'; ++lastCh)
|
||||
{
|
||||
// Copy current entry into temporary map.
|
||||
const size_t cchEntry{ ::wcslen(lastCh) };
|
||||
|
|
|
@ -40,6 +40,7 @@ namespace Microsoft::Console::Types
|
|||
virtual const COORD GetSelectionAnchor() const noexcept = 0;
|
||||
virtual const COORD GetSelectionEnd() const noexcept = 0;
|
||||
virtual void ColorSelection(const COORD coordSelectionStart, const COORD coordSelectionEnd, const TextAttribute attr) = 0;
|
||||
virtual const bool IsUiaDataInitialized() const noexcept = 0;
|
||||
};
|
||||
|
||||
// See docs/virtual-dtors.md for an explanation of why this is weird.
|
||||
|
|
|
@ -220,21 +220,19 @@ IFACEMETHODIMP ScreenInfoUiaProviderBase::SetFocus()
|
|||
|
||||
IFACEMETHODIMP ScreenInfoUiaProviderBase::GetSelection(_Outptr_result_maybenull_ SAFEARRAY** ppRetVal)
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, ppRetVal);
|
||||
*ppRetVal = nullptr;
|
||||
|
||||
_LockConsole();
|
||||
auto Unlock = wil::scope_exit([&]() noexcept {
|
||||
_UnlockConsole();
|
||||
});
|
||||
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, ppRetVal);
|
||||
*ppRetVal = nullptr;
|
||||
HRESULT hr = S_OK;
|
||||
RETURN_HR_IF(E_FAIL, !_pData->IsUiaDataInitialized());
|
||||
|
||||
// make a safe array
|
||||
HRESULT hr = S_OK;
|
||||
*ppRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, 1);
|
||||
if (*ppRetVal == nullptr)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
RETURN_HR_IF_NULL(E_OUTOFMEMORY, *ppRetVal);
|
||||
|
||||
WRL::ComPtr<UiaTextRangeBase> range;
|
||||
if (!_pData->IsSelectionActive())
|
||||
|
@ -272,19 +270,18 @@ IFACEMETHODIMP ScreenInfoUiaProviderBase::GetSelection(_Outptr_result_maybenull_
|
|||
|
||||
IFACEMETHODIMP ScreenInfoUiaProviderBase::GetVisibleRanges(_Outptr_result_maybenull_ SAFEARRAY** ppRetVal)
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, ppRetVal);
|
||||
*ppRetVal = nullptr;
|
||||
|
||||
_LockConsole();
|
||||
auto Unlock = wil::scope_exit([&]() noexcept {
|
||||
_UnlockConsole();
|
||||
});
|
||||
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, ppRetVal);
|
||||
RETURN_HR_IF(E_FAIL, !_pData->IsUiaDataInitialized());
|
||||
|
||||
// make a safe array
|
||||
*ppRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, 1);
|
||||
if (*ppRetVal == nullptr)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
RETURN_HR_IF_NULL(E_OUTOFMEMORY, *ppRetVal);
|
||||
|
||||
WRL::ComPtr<UiaTextRangeBase> range;
|
||||
const auto bufferSize = _pData->GetTextBuffer().GetSize();
|
||||
|
|
|
@ -16,9 +16,6 @@ HRESULT TermControlUiaProvider::RuntimeClassInitialize(_In_ ::Microsoft::Console
|
|||
RETURN_IF_FAILED(ScreenInfoUiaProviderBase::RuntimeClassInitialize(uiaData));
|
||||
|
||||
_controlInfo = controlInfo;
|
||||
|
||||
// TODO GitHub #1914: Re-attach Tracing to UIA Tree
|
||||
//Tracing::s_TraceUia(nullptr, ApiCall::Constructor, nullptr);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
@ -26,11 +23,6 @@ IFACEMETHODIMP TermControlUiaProvider::Navigate(_In_ NavigateDirection direction
|
|||
_COM_Outptr_result_maybenull_ IRawElementProviderFragment** ppProvider) noexcept
|
||||
{
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, ppProvider);
|
||||
|
||||
// TODO GitHub #1914: Re-attach Tracing to UIA Tree
|
||||
/*ApiMsgNavigate apiMsg;
|
||||
apiMsg.Direction = direction;
|
||||
Tracing::s_TraceUia(this, ApiCall::Navigate, &apiMsg);*/
|
||||
*ppProvider = nullptr;
|
||||
|
||||
if (direction == NavigateDirection_Parent)
|
||||
|
|
|
@ -63,20 +63,6 @@ IFACEMETHODIMP TermControlUiaTextRange::Clone(_Outptr_result_maybenull_ ITextRan
|
|||
return hr;
|
||||
}
|
||||
|
||||
#if defined(_DEBUG) && defined(UiaTextRangeBase_DEBUG_MSGS)
|
||||
OutputDebugString(L"Clone\n");
|
||||
std::wstringstream ss;
|
||||
ss << _id << L" cloned to " << (static_cast<UiaTextRangeBase*>(*ppRetVal))->_id;
|
||||
std::wstring str = ss.str();
|
||||
OutputDebugString(str.c_str());
|
||||
OutputDebugString(L"\n");
|
||||
#endif
|
||||
// TODO GitHub #1914: Re-attach Tracing to UIA Tree
|
||||
// tracing
|
||||
/*ApiMsgClone apiMsg;
|
||||
apiMsg.CloneId = static_cast<UiaTextRangeBase*>(*ppRetVal)->GetId();
|
||||
Tracing::s_TraceUia(this, ApiCall::Clone, &apiMsg);*/
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -220,15 +220,18 @@ IFACEMETHODIMP UiaTextRangeBase::CompareEndpoints(_In_ TextPatternRangeEndpoint
|
|||
_Out_ int* pRetVal) noexcept
|
||||
try
|
||||
{
|
||||
RETURN_HR_IF(E_INVALIDARG, pRetVal == nullptr);
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, pRetVal);
|
||||
*pRetVal = 0;
|
||||
|
||||
_pData->LockConsole();
|
||||
auto Unlock = wil::scope_exit([&]() noexcept {
|
||||
_pData->UnlockConsole();
|
||||
});
|
||||
RETURN_HR_IF(E_FAIL, !_pData->IsUiaDataInitialized());
|
||||
|
||||
// get the text range that we're comparing to
|
||||
const UiaTextRangeBase* range = static_cast<UiaTextRangeBase*>(pTargetRange);
|
||||
if (range == nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, range);
|
||||
|
||||
// get endpoint value that we're comparing to
|
||||
const auto other = range->GetEndpoint(targetEndpoint);
|
||||
|
@ -240,10 +243,7 @@ try
|
|||
// This is a temporary solution to comparing two UTRs from different TextBuffers
|
||||
// Ensure both endpoints fit in the current buffer.
|
||||
const auto bufferSize = _pData->GetTextBuffer().GetSize();
|
||||
if (!bufferSize.IsInBounds(mine, true) || !bufferSize.IsInBounds(other, true))
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
RETURN_HR_IF(E_FAIL, !bufferSize.IsInBounds(mine, true) || !bufferSize.IsInBounds(other, true));
|
||||
|
||||
// compare them
|
||||
*pRetVal = bufferSize.CompareInBounds(mine, other, true);
|
||||
|
@ -259,6 +259,7 @@ IFACEMETHODIMP UiaTextRangeBase::ExpandToEnclosingUnit(_In_ TextUnit unit) noexc
|
|||
auto Unlock = wil::scope_exit([&]() noexcept {
|
||||
_pData->UnlockConsole();
|
||||
});
|
||||
RETURN_HR_IF(E_FAIL, !_pData->IsUiaDataInitialized());
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -446,6 +447,12 @@ try
|
|||
RETURN_HR_IF(E_INVALIDARG, ppRetVal == nullptr);
|
||||
*ppRetVal = nullptr;
|
||||
|
||||
_pData->LockConsole();
|
||||
auto Unlock = wil::scope_exit([&]() noexcept {
|
||||
_pData->UnlockConsole();
|
||||
});
|
||||
RETURN_HR_IF(E_FAIL, !_pData->IsUiaDataInitialized());
|
||||
|
||||
// AttributeIDs that require special handling
|
||||
switch (attributeId)
|
||||
{
|
||||
|
@ -607,6 +614,12 @@ try
|
|||
RETURN_HR_IF(E_INVALIDARG, ppRetVal == nullptr);
|
||||
*ppRetVal = nullptr;
|
||||
|
||||
_pData->LockConsole();
|
||||
auto Unlock = wil::scope_exit([&]() noexcept {
|
||||
_pData->UnlockConsole();
|
||||
});
|
||||
RETURN_HR_IF(E_FAIL, !_pData->IsUiaDataInitialized());
|
||||
|
||||
const std::wstring queryText{ text, SysStringLen(text) };
|
||||
const auto bufferSize = _getBufferSize();
|
||||
const auto sensitivity = ignoreCase ? Search::Sensitivity::CaseInsensitive : Search::Sensitivity::CaseSensitive;
|
||||
|
@ -732,6 +745,12 @@ try
|
|||
RETURN_HR_IF(E_INVALIDARG, pRetVal == nullptr);
|
||||
VariantInit(pRetVal);
|
||||
|
||||
_pData->LockConsole();
|
||||
auto Unlock = wil::scope_exit([&]() noexcept {
|
||||
_pData->UnlockConsole();
|
||||
});
|
||||
RETURN_HR_IF(E_FAIL, !_pData->IsUiaDataInitialized());
|
||||
|
||||
// AttributeIDs that require special handling
|
||||
switch (attributeId)
|
||||
{
|
||||
|
@ -819,13 +838,14 @@ CATCH_RETURN();
|
|||
|
||||
IFACEMETHODIMP UiaTextRangeBase::GetBoundingRectangles(_Outptr_result_maybenull_ SAFEARRAY** ppRetVal) noexcept
|
||||
{
|
||||
RETURN_HR_IF(E_INVALIDARG, ppRetVal == nullptr);
|
||||
*ppRetVal = nullptr;
|
||||
|
||||
_pData->LockConsole();
|
||||
auto Unlock = wil::scope_exit([&]() noexcept {
|
||||
_pData->UnlockConsole();
|
||||
});
|
||||
|
||||
RETURN_HR_IF(E_INVALIDARG, ppRetVal == nullptr);
|
||||
*ppRetVal = nullptr;
|
||||
RETURN_HR_IF(E_FAIL, !_pData->IsUiaDataInitialized());
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -927,21 +947,19 @@ CATCH_RETURN();
|
|||
IFACEMETHODIMP UiaTextRangeBase::GetText(_In_ int maxLength, _Out_ BSTR* pRetVal) noexcept
|
||||
try
|
||||
{
|
||||
RETURN_HR_IF(E_INVALIDARG, pRetVal == nullptr);
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, pRetVal);
|
||||
RETURN_HR_IF(E_INVALIDARG, maxLength < -1);
|
||||
*pRetVal = nullptr;
|
||||
|
||||
if (maxLength < -1)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
_pData->LockConsole();
|
||||
auto Unlock = wil::scope_exit([&]() noexcept {
|
||||
_pData->UnlockConsole();
|
||||
});
|
||||
RETURN_HR_IF(E_FAIL, !_pData->IsUiaDataInitialized());
|
||||
|
||||
const auto maxLengthOpt = (maxLength == -1) ?
|
||||
std::nullopt :
|
||||
std::optional<unsigned int>{ maxLength };
|
||||
_pData->LockConsole();
|
||||
auto Unlock = wil::scope_exit([this]() noexcept {
|
||||
_pData->UnlockConsole();
|
||||
});
|
||||
const auto text = _getTextValue(maxLengthOpt);
|
||||
Unlock.reset();
|
||||
|
||||
|
@ -1015,6 +1033,7 @@ try
|
|||
auto Unlock = wil::scope_exit([&]() noexcept {
|
||||
_pData->UnlockConsole();
|
||||
});
|
||||
RETURN_HR_IF(E_FAIL, !_pData->IsUiaDataInitialized());
|
||||
|
||||
const auto wasDegenerate = IsDegenerate();
|
||||
if (count != 0)
|
||||
|
@ -1070,15 +1089,13 @@ IFACEMETHODIMP UiaTextRangeBase::MoveEndpointByUnit(_In_ TextPatternRangeEndpoin
|
|||
{
|
||||
RETURN_HR_IF(E_INVALIDARG, pRetVal == nullptr);
|
||||
*pRetVal = 0;
|
||||
if (count == 0)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
_pData->LockConsole();
|
||||
auto Unlock = wil::scope_exit([&]() noexcept {
|
||||
_pData->UnlockConsole();
|
||||
});
|
||||
RETURN_HR_IF(E_FAIL, !_pData->IsUiaDataInitialized());
|
||||
RETURN_HR_IF(S_OK, count == 0);
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -1116,10 +1133,8 @@ try
|
|||
});
|
||||
|
||||
const UiaTextRangeBase* range = static_cast<UiaTextRangeBase*>(pTargetRange);
|
||||
if (range == nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
RETURN_HR_IF_NULL(E_INVALIDARG, range);
|
||||
RETURN_HR_IF(E_FAIL, !_pData->IsUiaDataInitialized());
|
||||
|
||||
// TODO GH#5406: create a different UIA parent object for each TextBuffer
|
||||
// This is a temporary solution to comparing two UTRs from different TextBuffers
|
||||
|
@ -1127,10 +1142,7 @@ try
|
|||
const auto bufferSize = _pData->GetTextBuffer().GetSize();
|
||||
const auto mine = GetEndpoint(endpoint);
|
||||
const auto other = range->GetEndpoint(targetEndpoint);
|
||||
if (!bufferSize.IsInBounds(mine, true) || !bufferSize.IsInBounds(other, true))
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
RETURN_HR_IF(E_FAIL, !bufferSize.IsInBounds(mine, true) || !bufferSize.IsInBounds(other, true));
|
||||
|
||||
SetEndpoint(endpoint, range->GetEndpoint(targetEndpoint));
|
||||
|
||||
|
@ -1146,6 +1158,7 @@ try
|
|||
auto Unlock = wil::scope_exit([&]() noexcept {
|
||||
_pData->UnlockConsole();
|
||||
});
|
||||
RETURN_HR_IF(E_FAIL, !_pData->IsUiaDataInitialized());
|
||||
|
||||
if (IsDegenerate())
|
||||
{
|
||||
|
@ -1190,6 +1203,7 @@ try
|
|||
auto Unlock = wil::scope_exit([&]() noexcept {
|
||||
_pData->UnlockConsole();
|
||||
});
|
||||
RETURN_HR_IF(E_FAIL, !_pData->IsUiaDataInitialized());
|
||||
|
||||
const auto oldViewport = _pData->GetViewport().ToInclusive();
|
||||
const auto viewportHeight = _getViewportHeight(oldViewport);
|
||||
|
|
|
@ -21,12 +21,9 @@ namespace Microsoft::Console::Utils
|
|||
}
|
||||
};
|
||||
|
||||
using EnvironmentBlockPtr = wil::unique_any<void*, decltype(::DestroyEnvironmentBlock), ::DestroyEnvironmentBlock>;
|
||||
[[nodiscard]] EnvironmentBlockPtr CreateEnvironmentBlock();
|
||||
|
||||
using EnvironmentVariableMapW = std::map<std::wstring, std::wstring, WStringCaseInsensitiveCompare>;
|
||||
|
||||
[[nodiscard]] HRESULT UpdateEnvironmentMapW(EnvironmentVariableMapW& map, void* environmentBlock = nullptr) noexcept;
|
||||
[[nodiscard]] HRESULT UpdateEnvironmentMapW(EnvironmentVariableMapW& map) noexcept;
|
||||
|
||||
[[nodiscard]] HRESULT EnvironmentMapToEnvironmentStringsW(EnvironmentVariableMapW& map,
|
||||
std::vector<wchar_t>& newEnvVars) noexcept;
|
||||
|
|
|
@ -29,7 +29,6 @@ Abstract:
|
|||
|
||||
// Windows Header Files:
|
||||
#include <windows.h>
|
||||
#include <userenv.h>
|
||||
#include <combaseapi.h>
|
||||
#include <UIAutomation.h>
|
||||
#include <objbase.h>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
$pgoBranch = "main"
|
||||
$pgoBranch = "release-1.11"
|
||||
$packageId = "Microsoft.Internal.Windows.Terminal.PGODatabase"
|
||||
|
||||
# Get release version
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
function MakeVersion ( $major, $minor, $datetimeStamp )
|
||||
{
|
||||
$revision, $branch = $datetimeStamp.Split("-")
|
||||
$revision, $branch = $datetimeStamp.Split("-", 2)
|
||||
|
||||
if ( $branch -eq $null )
|
||||
{
|
||||
|
@ -71,5 +71,5 @@ function GetDatetimeStamp ( $pgoBranch )
|
|||
throw "FAILED: Get forkDate"
|
||||
}
|
||||
|
||||
return $forkDate + "-" + $pgoBranch.Replace("/", "_").Replace("-", "_").Replace(".", "_")
|
||||
return $forkDate + "-" + ( $pgoBranch -replace "(/|\.|@|>|<)", "-" )
|
||||
}
|
Loading…
Reference in a new issue