mirror of
https://github.com/microsoft/terminal.git
synced 2026-05-20 13:57:43 +00:00
Compare commits
7 Commits
dev/cazamo
...
dev/duhowe
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d0b9c0a0b0 | ||
|
|
441ec83514 | ||
|
|
39316fb266 | ||
|
|
ed93677edf | ||
|
|
d6d3be40cc | ||
|
|
39822d1a5e | ||
|
|
1395d17e07 |
1
.github/actions/spelling/expect/expect.txt
vendored
1
.github/actions/spelling/expect/expect.txt
vendored
@@ -1104,7 +1104,6 @@ NOSIZE
|
||||
NOSNAPSHOT
|
||||
NOTHOUSANDS
|
||||
NOTICKS
|
||||
notif
|
||||
NOTIMEOUTIFNOTHUNG
|
||||
NOTIMPL
|
||||
NOTOPMOST
|
||||
|
||||
@@ -60,8 +60,7 @@
|
||||
"enum": [
|
||||
"audible",
|
||||
"window",
|
||||
"taskbar",
|
||||
"notification"
|
||||
"taskbar"
|
||||
]
|
||||
}
|
||||
},
|
||||
@@ -71,7 +70,6 @@
|
||||
"audible",
|
||||
"taskbar",
|
||||
"window",
|
||||
"notification",
|
||||
"all",
|
||||
"none"
|
||||
]
|
||||
@@ -2656,21 +2654,10 @@
|
||||
"type": "string"
|
||||
},
|
||||
"warning.confirmCloseAllTabs": {
|
||||
"deprecated": true,
|
||||
"description": "[Deprecated] Use \"warning.confirmOnClose\" instead.",
|
||||
"default": true,
|
||||
"description": "When set to \"true\" closing a window with multiple tabs open will require confirmation. When set to \"false\", the confirmation dialog will not appear.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"warning.confirmOnClose": {
|
||||
"default": "automatic",
|
||||
"description": "Controls when a confirmation dialog appears before closing tabs or windows.",
|
||||
"enum": [
|
||||
"never",
|
||||
"automatic",
|
||||
"always"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"useTabSwitcher": {
|
||||
"description": "[Deprecated] Replaced with the \"tabSwitcherMode\" setting.",
|
||||
"default": true,
|
||||
@@ -2862,85 +2849,6 @@
|
||||
"description": "Sets the sound played when the application emits a BEL. When set to an array, the terminal will pick one of those sounds at random.",
|
||||
"$ref": "#/$defs/BellSound"
|
||||
},
|
||||
"notifyOnActivity": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"taskbar",
|
||||
"audible",
|
||||
"tab",
|
||||
"notification"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"taskbar",
|
||||
"audible",
|
||||
"tab",
|
||||
"notification",
|
||||
"all",
|
||||
"none"
|
||||
]
|
||||
}
|
||||
],
|
||||
"description": "Controls how you are notified when an inactive tab produces new output."
|
||||
},
|
||||
"notifyOnNextPrompt": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"taskbar",
|
||||
"audible",
|
||||
"tab",
|
||||
"notification"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"taskbar",
|
||||
"audible",
|
||||
"tab",
|
||||
"notification",
|
||||
"all",
|
||||
"none"
|
||||
]
|
||||
}
|
||||
],
|
||||
"description": "Controls how you are notified when a new shell prompt is detected. Requires shell integration."
|
||||
},
|
||||
"notifyOnActivityThreshold": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"default": 5,
|
||||
"description": "Minimum number of seconds between consecutive activity notifications for this profile. Use this to suppress repeated notifications from chatty processes. The first notification after the pane has been silent always fires; subsequent notifications within this window are suppressed. Use 0 to always notify."
|
||||
},
|
||||
"notifyOnNextPromptThreshold": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"default": 5,
|
||||
"description": "Suppress the next-prompt notification unless the just-finished command ran for at least this many seconds. Requires shell integration. Use 0 to always notify."
|
||||
},
|
||||
"autoDetectRunningCommand": {
|
||||
"default": false,
|
||||
"description": "Automatically detect when a command is running and show a progress indicator in the tab and taskbar.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"closeOnExit": {
|
||||
"default": "automatic",
|
||||
"description": "Sets how the profile reacts to termination or failure to launch. Possible values:\n -\"graceful\" (close when exit is typed or the process exits normally)\n -\"always\" (always close)\n -\"automatic\" (behave as \"graceful\" only for processes launched by terminal, behave as \"always\" otherwise)\n -\"never\" (never close).\ntrue and false are accepted as synonyms for \"graceful\" and \"never\" respectively.",
|
||||
|
||||
@@ -237,7 +237,6 @@
|
||||
<Capability Name="internetClient" />
|
||||
<rescap:Capability Name="runFullTrust" />
|
||||
<rescap:Capability Name="unvirtualizedResources" />
|
||||
<rescap:Capability Name="appLicensing" />
|
||||
</Capabilities>
|
||||
|
||||
<Extensions>
|
||||
|
||||
@@ -237,7 +237,6 @@
|
||||
<Capability Name="internetClient" />
|
||||
<rescap:Capability Name="runFullTrust" />
|
||||
<rescap:Capability Name="unvirtualizedResources" />
|
||||
<rescap:Capability Name="appLicensing" />
|
||||
</Capabilities>
|
||||
|
||||
<Extensions>
|
||||
|
||||
@@ -185,7 +185,7 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
if (const auto termControl{ _senderOrActiveControl(sender) })
|
||||
{
|
||||
termControl.SendInput(realArgs.Input());
|
||||
termControl.WriteInputString(realArgs.Input(), WriteInputStringType::Raw);
|
||||
args.Handled(true);
|
||||
}
|
||||
}
|
||||
@@ -452,8 +452,11 @@ namespace winrt::TerminalApp::implementation
|
||||
void TerminalPage::_HandlePasteText(const IInspectable& /*sender*/,
|
||||
const ActionEventArgs& args)
|
||||
{
|
||||
_PasteText();
|
||||
args.Handled(true);
|
||||
if (const auto& control{ _GetActiveControl() })
|
||||
{
|
||||
_PasteFromClipboardHandler(control, nullptr);
|
||||
args.Handled(true);
|
||||
}
|
||||
}
|
||||
|
||||
void TerminalPage::_HandleNewTab(const IInspectable& /*sender*/,
|
||||
@@ -801,7 +804,7 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
_RemoveTabs(tabsToRemove);
|
||||
|
||||
actionArgs.Handled(!tabsToRemove.empty());
|
||||
actionArgs.Handled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -837,7 +840,7 @@ namespace winrt::TerminalApp::implementation
|
||||
// tab row, until you mouse over them. Probably has something to do
|
||||
// with tabs not resizing down until there's a mouse exit event.
|
||||
|
||||
actionArgs.Handled(!tabsToRemove.empty());
|
||||
actionArgs.Handled(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1068,15 +1068,6 @@ int AppCommandlineArgs::ParseArgs(winrt::array_view<const winrt::hstring> args)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// When a toast notification is clicked, Windows may launch a new instance
|
||||
// with "--from-toast" as the argument. This is a no-op sentinel — the
|
||||
// in-process Activated handler on the toast already handled activation.
|
||||
// See DesktopNotification.cpp for more details.
|
||||
if (args.size() == 2 && args[1] == L"--from-toast")
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto commands = ::TerminalApp::AppCommandlineArgs::BuildCommands(args);
|
||||
|
||||
for (auto& cmdBlob : commands)
|
||||
|
||||
@@ -15,7 +15,6 @@ namespace winrt::TerminalApp::implementation
|
||||
til::typed_event<IPaneContent> TaskbarProgressChanged;
|
||||
til::typed_event<IPaneContent> ReadOnlyChanged;
|
||||
til::typed_event<IPaneContent> FocusRequested;
|
||||
til::typed_event<IPaneContent, winrt::TerminalApp::NotificationEventArgs> NotificationRequested;
|
||||
|
||||
til::typed_event<winrt::Windows::Foundation::IInspectable, Microsoft::Terminal::Settings::Model::Command> DispatchCommandRequested;
|
||||
};
|
||||
|
||||
@@ -231,12 +231,6 @@
|
||||
Glyph=""
|
||||
Visibility="{x:Bind Item.(local:TabPaletteItem.TabStatus).BellIndicator, Mode=OneWay}" />
|
||||
|
||||
<FontIcon Margin="0,0,8,0"
|
||||
FontFamily="{ThemeResource SymbolThemeFontFamily}"
|
||||
FontSize="8"
|
||||
Glyph=""
|
||||
Visibility="{x:Bind Item.(local:TabPaletteItem.TabStatus).ActivityIndicator, Mode=OneWay}" />
|
||||
|
||||
<FontIcon Margin="0,0,8,0"
|
||||
FontFamily="{ThemeResource SymbolThemeFontFamily}"
|
||||
FontSize="12"
|
||||
|
||||
@@ -1,129 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "DesktopNotification.h"
|
||||
|
||||
#include <WtExeUtils.h>
|
||||
|
||||
using namespace winrt::Windows::UI::Notifications;
|
||||
using namespace winrt::Windows::Data::Xml::Dom;
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
std::atomic<uint64_t> DesktopNotification::_lastNotificationTime{ 0 };
|
||||
|
||||
// Method Description:
|
||||
// - Rate-limits toast notifications so we don't spam the user.
|
||||
// Return Value:
|
||||
// - Returns true if a notification is allowed, false if too recent.
|
||||
bool DesktopNotification::ShouldSendNotification()
|
||||
{
|
||||
const auto now = GetTickCount64();
|
||||
auto last = _lastNotificationTime.load(std::memory_order_relaxed);
|
||||
|
||||
// Subtraction wraps cleanly modulo 2^64, so the delta is correct even
|
||||
// across the (~584 million year) GetTickCount64 rollover.
|
||||
if (now - last < MinNotificationIntervalMs)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Attempt to update; if another thread beat us, that's fine — we'll skip this one.
|
||||
return _lastNotificationTime.compare_exchange_strong(last, now, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Sends a toast notification with the given title and message.
|
||||
// - When the user clicks the toast, the `Activated` callback fires
|
||||
// with the tabIndex that was passed in, so the caller can switch
|
||||
// to the correct tab and summon the window.
|
||||
// Arguments:
|
||||
// - args: The title, message, and tab index to include in the notification.
|
||||
// - activated: A callback invoked on the background thread when the
|
||||
// toast is clicked. The uint32_t parameter is the tab index.
|
||||
void DesktopNotification::SendNotification(const DesktopNotificationArgs& args, std::function<void()> activatedFunc)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!ShouldSendNotification())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Build the toast XML. We use a simple template with a title and body text.
|
||||
//
|
||||
// <toast launch="--from-toast">
|
||||
// <visual>
|
||||
// <binding template="ToastGeneric">
|
||||
// <text>Title</text>
|
||||
// <text>Message</text>
|
||||
// </binding>
|
||||
// </visual>
|
||||
// </toast>
|
||||
auto toastXml = ToastNotificationManager::GetTemplateContent(ToastTemplateType::ToastText02);
|
||||
auto textNodes = toastXml.GetElementsByTagName(L"text");
|
||||
|
||||
// First <text> is the title
|
||||
textNodes.Item(0).InnerText(args.Title);
|
||||
// Second <text> is the body
|
||||
textNodes.Item(1).InnerText(args.Message);
|
||||
|
||||
auto toastElement = toastXml.DocumentElement();
|
||||
|
||||
// When a toast is clicked, Windows launches a new instance of the app
|
||||
// with the "launch" attribute as command-line arguments. We handle
|
||||
// toast activation in-process via the Activated event below, so the
|
||||
// new instance should do nothing. "--from-toast" is recognized by
|
||||
// AppCommandlineArgs::ParseArgs as a no-op sentinel.
|
||||
toastElement.SetAttribute(L"launch", L"--from-toast");
|
||||
|
||||
toastElement.SetAttribute(L"scenario", L"default");
|
||||
|
||||
auto toast = ToastNotification{ toastXml };
|
||||
|
||||
// Set the tag and group to enable notification replacement.
|
||||
// Repeated notifications with the same tag replace the previous one
|
||||
// rather than stacking in the notification center.
|
||||
toast.Tag(args.Tag);
|
||||
toast.Group(L"WindowsTerminal");
|
||||
|
||||
// When the user activates (clicks) the toast, fire the callback.
|
||||
if (activatedFunc)
|
||||
{
|
||||
toast.Activated([activatedFunc](const auto& /*sender*/, const auto& /*eventArgs*/) {
|
||||
activatedFunc();
|
||||
});
|
||||
}
|
||||
|
||||
// For packaged apps, CreateToastNotifier() uses the package identity automatically.
|
||||
// For unpackaged apps, we must pass the explicit AUMID that was registered
|
||||
// at startup via SetCurrentProcessExplicitAppUserModelID.
|
||||
winrt::Windows::UI::Notifications::ToastNotifier notifier{ nullptr };
|
||||
if (IsPackaged())
|
||||
{
|
||||
notifier = ToastNotificationManager::CreateToastNotifier();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Retrieve the AUMID that was set by WindowEmperor at startup.
|
||||
wil::unique_cotaskmem_string aumid;
|
||||
if (SUCCEEDED(GetCurrentProcessExplicitAppUserModelID(&aumid)))
|
||||
{
|
||||
notifier = ToastNotificationManager::CreateToastNotifier(aumid.get());
|
||||
}
|
||||
}
|
||||
if (notifier)
|
||||
{
|
||||
notifier.Show(toast);
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// Toast notification is a best-effort feature. If it fails (e.g., notifications
|
||||
// are disabled, or the app is unpackaged without proper AUMID setup), we silently
|
||||
// ignore the error.
|
||||
LOG_CAUGHT_EXCEPTION();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/*++
|
||||
Copyright (c) Microsoft Corporation
|
||||
Licensed under the MIT license.
|
||||
|
||||
Module Name:
|
||||
- DesktopNotification.h
|
||||
|
||||
Module Description:
|
||||
- Helper for sending Windows desktop toast notifications. Used to surface
|
||||
terminal activity events to the user via the Windows notification center.
|
||||
--*/
|
||||
|
||||
#pragma once
|
||||
#include "pch.h"
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
struct DesktopNotificationArgs
|
||||
{
|
||||
winrt::hstring Title;
|
||||
winrt::hstring Message;
|
||||
winrt::hstring Tag;
|
||||
};
|
||||
|
||||
class DesktopNotification
|
||||
{
|
||||
public:
|
||||
static bool ShouldSendNotification();
|
||||
static void SendNotification(const DesktopNotificationArgs& args, std::function<void()> activatedFunc);
|
||||
|
||||
private:
|
||||
static std::atomic<uint64_t> _lastNotificationTime;
|
||||
|
||||
// Minimum interval between notifications, in milliseconds (GetTickCount64 units).
|
||||
static constexpr uint64_t MinNotificationIntervalMs = 5'000;
|
||||
};
|
||||
}
|
||||
@@ -14,15 +14,6 @@ namespace TerminalApp
|
||||
runtimeclass BellEventArgs
|
||||
{
|
||||
Boolean FlashTaskbar { get; };
|
||||
Boolean SendNotification { get; };
|
||||
};
|
||||
|
||||
runtimeclass NotificationEventArgs
|
||||
{
|
||||
String Title { get; };
|
||||
String Body { get; };
|
||||
Microsoft.Terminal.Control.OutputNotificationStyle Style { get; };
|
||||
Boolean AlwaysNotify { get; };
|
||||
};
|
||||
|
||||
interface IPaneContent
|
||||
@@ -33,7 +24,7 @@ namespace TerminalApp
|
||||
Windows.Foundation.Size MinimumSize { get; };
|
||||
|
||||
String Title { get; };
|
||||
Microsoft.Terminal.Control.TaskbarState TaskbarState { get; };
|
||||
UInt64 TaskbarState { get; };
|
||||
UInt64 TaskbarProgress { get; };
|
||||
Boolean ReadOnly { get; };
|
||||
String Icon { get; };
|
||||
@@ -55,7 +46,6 @@ namespace TerminalApp
|
||||
event Windows.Foundation.TypedEventHandler<IPaneContent, Object> TaskbarProgressChanged;
|
||||
event Windows.Foundation.TypedEventHandler<IPaneContent, Object> ReadOnlyChanged;
|
||||
event Windows.Foundation.TypedEventHandler<IPaneContent, Object> FocusRequested;
|
||||
event Windows.Foundation.TypedEventHandler<IPaneContent, NotificationEventArgs> NotificationRequested;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace winrt::TerminalApp::implementation
|
||||
winrt::Microsoft::Terminal::Settings::Model::INewContentArgs GetNewTerminalArgs(BuildStartupKind kind) const;
|
||||
|
||||
winrt::hstring Title() { return _filePath; }
|
||||
winrt::Microsoft::Terminal::Control::TaskbarState TaskbarState() { return winrt::Microsoft::Terminal::Control::TaskbarState::Clear; }
|
||||
uint64_t TaskbarState() { return 0; }
|
||||
uint64_t TaskbarProgress() { return 0; }
|
||||
bool ReadOnly() { return false; }
|
||||
winrt::hstring Icon() const;
|
||||
|
||||
@@ -3044,14 +3044,15 @@ void Pane::BroadcastChar(const winrt::Microsoft::Terminal::Control::TermControl&
|
||||
}
|
||||
|
||||
void Pane::BroadcastString(const winrt::Microsoft::Terminal::Control::TermControl& sourceControl,
|
||||
const winrt::hstring& text)
|
||||
const winrt::hstring& text,
|
||||
const winrt::Microsoft::Terminal::Control::WriteInputStringType type)
|
||||
{
|
||||
WalkTree([&](const auto& pane) {
|
||||
if (const auto& termControl{ pane->GetTerminalControl() })
|
||||
{
|
||||
if (termControl != sourceControl && !termControl.ReadOnly())
|
||||
{
|
||||
termControl.RawWriteString(text);
|
||||
termControl.WriteInputStringWithoutBroadcast(text, type);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -152,7 +152,7 @@ public:
|
||||
void EnableBroadcast(bool enabled);
|
||||
void BroadcastKey(const winrt::Microsoft::Terminal::Control::TermControl& sourceControl, const WORD vkey, const WORD scanCode, const winrt::Microsoft::Terminal::Core::ControlKeyStates modifiers, const bool keyDown);
|
||||
void BroadcastChar(const winrt::Microsoft::Terminal::Control::TermControl& sourceControl, const wchar_t vkey, const WORD scanCode, const winrt::Microsoft::Terminal::Core::ControlKeyStates modifiers);
|
||||
void BroadcastString(const winrt::Microsoft::Terminal::Control::TermControl& sourceControl, const winrt::hstring& text);
|
||||
void BroadcastString(const winrt::Microsoft::Terminal::Control::TermControl& sourceControl, const winrt::hstring& text, const winrt::Microsoft::Terminal::Control::WriteInputStringType type);
|
||||
|
||||
void UpdateResources(const PaneResources& resources);
|
||||
|
||||
|
||||
@@ -496,48 +496,24 @@
|
||||
<value>Third-Party notices</value>
|
||||
<comment>A hyperlink name for the Terminal's third-party notices</comment>
|
||||
</data>
|
||||
<data name="ConfirmCloseDialog_Cancel" xml:space="preserve">
|
||||
<data name="QuitDialog.CloseButtonText" xml:space="preserve">
|
||||
<value>Cancel</value>
|
||||
</data>
|
||||
<data name="ConfirmCloseDialog_CloseAllTitle" xml:space="preserve">
|
||||
<data name="QuitDialog.PrimaryButtonText" xml:space="preserve">
|
||||
<value>Close all</value>
|
||||
</data>
|
||||
<data name="QuitDialog.Title" xml:space="preserve">
|
||||
<value>Do you want to close all windows?</value>
|
||||
</data>
|
||||
<data name="ConfirmCloseDialog_CloseAllPrimary" xml:space="preserve">
|
||||
<data name="CloseAllDialog.CloseButtonText" xml:space="preserve">
|
||||
<value>Cancel</value>
|
||||
</data>
|
||||
<data name="CloseAllDialog.PrimaryButtonText" xml:space="preserve">
|
||||
<value>Close all</value>
|
||||
</data>
|
||||
<data name="ConfirmCloseDialog_WindowTitle" xml:space="preserve">
|
||||
<data name="CloseAllDialog.Title" xml:space="preserve">
|
||||
<value>Do you want to close all tabs?</value>
|
||||
</data>
|
||||
<data name="ConfirmCloseDialog_WindowPrimary" xml:space="preserve">
|
||||
<value>Close all</value>
|
||||
</data>
|
||||
<data name="ConfirmCloseDialog_TabTitle" xml:space="preserve">
|
||||
<value>Do you want to close this tab?</value>
|
||||
</data>
|
||||
<data name="ConfirmCloseDialog_TabPrimary" xml:space="preserve">
|
||||
<value>Close tab</value>
|
||||
</data>
|
||||
<data name="ConfirmCloseDialog_PaneTitle" xml:space="preserve">
|
||||
<value>Do you want to close this pane?</value>
|
||||
</data>
|
||||
<data name="ConfirmCloseDialog_PanePrimary" xml:space="preserve">
|
||||
<value>Close pane</value>
|
||||
</data>
|
||||
<data name="ConfirmCloseDialog_MultipleTabsTitle" xml:space="preserve">
|
||||
<value>Do you want to close these tabs?</value>
|
||||
</data>
|
||||
<data name="ConfirmCloseDialog_MultipleTabsPrimary" xml:space="preserve">
|
||||
<value>Close tabs</value>
|
||||
</data>
|
||||
<data name="ConfirmCloseDialog_MultiplePanesTitle" xml:space="preserve">
|
||||
<value>Do you want to close these panes?</value>
|
||||
</data>
|
||||
<data name="ConfirmCloseDialog_MultiplePanesPrimary" xml:space="preserve">
|
||||
<value>Close panes</value>
|
||||
</data>
|
||||
<data name="DontAskAgainCheckBox.Content" xml:space="preserve">
|
||||
<value>Don't ask me again</value>
|
||||
</data>
|
||||
<data name="CloseReadOnlyDialog.CloseButtonText" xml:space="preserve">
|
||||
<value>Cancel</value>
|
||||
</data>
|
||||
@@ -769,14 +745,6 @@
|
||||
<value>Windows</value>
|
||||
<comment>This is displayed as a label for the context menu item that holds the submenu of available windows.</comment>
|
||||
</data>
|
||||
<data name="NotificationMessage_TabActivity" xml:space="preserve">
|
||||
<value>Activity in tab "{0}"</value>
|
||||
<comment>{0} is the tab title. Shown as the body of a desktop notification when tab activity is detected.</comment>
|
||||
</data>
|
||||
<data name="NotificationMessage_TabActivityInWindow" xml:space="preserve">
|
||||
<value>Activity in tab "{0}" (window "{1}")</value>
|
||||
<comment>{0} is the tab title, {1} is the window name. Shown as the body of a desktop notification when tab activity is detected and the window has a name.</comment>
|
||||
</data>
|
||||
<data name="DropPathTabRun.Text" xml:space="preserve">
|
||||
<value>Open a new tab in given starting directory</value>
|
||||
</data>
|
||||
@@ -913,10 +881,10 @@
|
||||
<value>If set, the command will be appended to the profile's default command instead of replacing it.</value>
|
||||
</data>
|
||||
<data name="RestartConnectionText" xml:space="preserve">
|
||||
<value>Restart session</value>
|
||||
<value>Restart connection</value>
|
||||
</data>
|
||||
<data name="RestartConnectionToolTip" xml:space="preserve">
|
||||
<value>Restart the session in the active pane</value>
|
||||
<value>Restart the active pane connection</value>
|
||||
</data>
|
||||
<data name="SnippetPaneTitle.Text" xml:space="preserve">
|
||||
<value>Snippets</value>
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace winrt::TerminalApp::implementation
|
||||
winrt::Microsoft::Terminal::Settings::Model::INewContentArgs GetNewTerminalArgs(BuildStartupKind kind) const;
|
||||
|
||||
winrt::hstring Title() { return L"Scratchpad"; }
|
||||
winrt::Microsoft::Terminal::Control::TaskbarState TaskbarState() { return winrt::Microsoft::Terminal::Control::TaskbarState::Clear; }
|
||||
uint64_t TaskbarState() { return 0; }
|
||||
uint64_t TaskbarProgress() { return 0; }
|
||||
bool ReadOnly() { return false; }
|
||||
winrt::hstring Icon() const;
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace winrt::TerminalApp::implementation
|
||||
winrt::Microsoft::Terminal::Settings::Model::INewContentArgs GetNewTerminalArgs(const BuildStartupKind kind) const;
|
||||
|
||||
winrt::hstring Title() { return RS_(L"SettingsTab"); }
|
||||
winrt::Microsoft::Terminal::Control::TaskbarState TaskbarState() { return winrt::Microsoft::Terminal::Control::TaskbarState::Clear; }
|
||||
uint64_t TaskbarState() { return 0; }
|
||||
uint64_t TaskbarProgress() { return 0; }
|
||||
bool ReadOnly() { return false; }
|
||||
winrt::hstring Icon() const;
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace winrt::TerminalApp::implementation
|
||||
winrt::Microsoft::Terminal::Settings::Model::INewContentArgs GetNewTerminalArgs(BuildStartupKind kind) const;
|
||||
|
||||
winrt::hstring Title() { return RS_(L"SnippetPaneTitle/Text"); }
|
||||
winrt::Microsoft::Terminal::Control::TaskbarState TaskbarState() { return winrt::Microsoft::Terminal::Control::TaskbarState::Clear; }
|
||||
uint64_t TaskbarState() { return 0; }
|
||||
uint64_t TaskbarProgress() { return 0; }
|
||||
bool ReadOnly() { return false; }
|
||||
winrt::hstring Icon() const;
|
||||
|
||||
@@ -35,6 +35,7 @@ namespace winrt::TerminalApp::implementation
|
||||
_activePane = nullptr;
|
||||
|
||||
_closePaneMenuItem.Visibility(WUX::Visibility::Collapsed);
|
||||
_restartConnectionMenuItem.Visibility(WUX::Visibility::Collapsed);
|
||||
|
||||
auto firstId = _nextPaneId;
|
||||
|
||||
@@ -85,7 +86,6 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
_MakeTabViewItem();
|
||||
_CreateContextMenu();
|
||||
_UpdateMenuItemStates();
|
||||
|
||||
_headerControl.TabStatus(_tabStatus);
|
||||
|
||||
@@ -123,12 +123,6 @@ namespace winrt::TerminalApp::implementation
|
||||
_bellIndicatorTimer.Stop();
|
||||
}
|
||||
|
||||
void Tab::_ActivityIndicatorTimerTick(const Windows::Foundation::IInspectable& /*sender*/, const Windows::Foundation::IInspectable& /*e*/)
|
||||
{
|
||||
ShowActivityIndicator(false);
|
||||
_activityIndicatorTimer.Stop();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Initializes a TabViewItem for this Tab instance.
|
||||
// Arguments:
|
||||
@@ -335,10 +329,6 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
ShowBellIndicator(false);
|
||||
}
|
||||
if (_tabStatus.ActivityIndicator())
|
||||
{
|
||||
ShowActivityIndicator(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -469,26 +459,6 @@ namespace winrt::TerminalApp::implementation
|
||||
_bellIndicatorTimer.Start();
|
||||
}
|
||||
|
||||
void Tab::ShowActivityIndicator(const bool show)
|
||||
{
|
||||
ASSERT_UI_THREAD();
|
||||
|
||||
_tabStatus.ActivityIndicator(show);
|
||||
}
|
||||
|
||||
void Tab::ActivateActivityIndicatorTimer()
|
||||
{
|
||||
ASSERT_UI_THREAD();
|
||||
|
||||
if (!_activityIndicatorTimer)
|
||||
{
|
||||
_activityIndicatorTimer.Interval(std::chrono::milliseconds(2000));
|
||||
_activityIndicatorTimer.Tick({ get_weak(), &Tab::_ActivityIndicatorTimerTick });
|
||||
}
|
||||
|
||||
_activityIndicatorTimer.Start();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Gets the title string of the last focused terminal control in our tree.
|
||||
// Returns the empty string if there is no such control.
|
||||
@@ -1178,14 +1148,6 @@ namespace winrt::TerminalApp::implementation
|
||||
tab->TabRaiseVisualBell.raise();
|
||||
}
|
||||
|
||||
// Send a desktop toast notification if requested, but only if
|
||||
// the pane isn't already in the belled state. This prevents
|
||||
// sending repeated toasts for repeated BEL characters.
|
||||
if (bellArgs.SendNotification() && !tab->_tabStatus.BellIndicator())
|
||||
{
|
||||
tab->TabToastNotificationRequested.raise(tab->Title(), L"", sender);
|
||||
}
|
||||
|
||||
// Show the bell indicator in the tab header
|
||||
tab->ShowBellIndicator(true);
|
||||
|
||||
@@ -1204,55 +1166,6 @@ namespace winrt::TerminalApp::implementation
|
||||
events.RestartTerminalRequested = terminal.RestartTerminalRequested(winrt::auto_revoke, { get_weak(), &Tab::_bubbleRestartTerminalRequested });
|
||||
}
|
||||
|
||||
events.NotificationRequested = content.NotificationRequested(
|
||||
winrt::auto_revoke,
|
||||
[dispatcher, weakThis](TerminalApp::IPaneContent sender, auto notifArgs) -> safe_void_coroutine {
|
||||
const auto weakThisCopy = weakThis;
|
||||
co_await wil::resume_foreground(dispatcher);
|
||||
if (const auto tab{ weakThisCopy.get() })
|
||||
{
|
||||
const auto activeContent = tab->GetActiveContent();
|
||||
const auto isActivePaneContent = activeContent && activeContent == sender;
|
||||
|
||||
if (!notifArgs.AlwaysNotify() && isActivePaneContent &&
|
||||
tab->_focusState != WUX::FocusState::Unfocused)
|
||||
{
|
||||
co_return;
|
||||
}
|
||||
|
||||
const auto style = notifArgs.Style();
|
||||
|
||||
if (WI_IsFlagSet(style, OutputNotificationStyle::Taskbar))
|
||||
{
|
||||
tab->TabRaiseVisualBell.raise();
|
||||
}
|
||||
|
||||
if (WI_IsFlagSet(style, winrt::Microsoft::Terminal::Control::OutputNotificationStyle::Audible))
|
||||
{
|
||||
if (const auto termContent{ sender.try_as<TerminalApp::TerminalPaneContent>() })
|
||||
{
|
||||
termContent.PlayNotificationSound();
|
||||
}
|
||||
}
|
||||
|
||||
if (WI_IsFlagSet(style, winrt::Microsoft::Terminal::Control::OutputNotificationStyle::Tab))
|
||||
{
|
||||
tab->ShowActivityIndicator(true);
|
||||
|
||||
if (tab->_focusState != WUX::FocusState::Unfocused)
|
||||
{
|
||||
tab->ActivateActivityIndicatorTimer();
|
||||
}
|
||||
}
|
||||
|
||||
if (WI_IsFlagSet(style, winrt::Microsoft::Terminal::Control::OutputNotificationStyle::Notification))
|
||||
{
|
||||
const auto title = notifArgs.Title().empty() ? tab->Title() : notifArgs.Title();
|
||||
tab->TabToastNotificationRequested.raise(title, notifArgs.Body(), sender);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (_tabStatus.IsInputBroadcastActive())
|
||||
{
|
||||
if (const auto& termContent{ content.try_as<TerminalApp::TerminalPaneContent>() })
|
||||
@@ -1309,10 +1222,11 @@ namespace winrt::TerminalApp::implementation
|
||||
const auto taskbarState = state.State();
|
||||
// The progress of the control changed, but not necessarily the progress of the tab.
|
||||
// Set the tab's progress ring to the active pane's progress
|
||||
if (taskbarState != winrt::Microsoft::Terminal::Control::TaskbarState::Clear)
|
||||
if (taskbarState > 0)
|
||||
{
|
||||
if (taskbarState == winrt::Microsoft::Terminal::Control::TaskbarState::Indeterminate)
|
||||
if (taskbarState == 3)
|
||||
{
|
||||
// 3 is the indeterminate state, set the progress ring as such
|
||||
_tabStatus.IsProgressRingIndeterminate(true);
|
||||
}
|
||||
else
|
||||
@@ -1340,7 +1254,7 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
// Method Description:
|
||||
// - Set an indicator on the tab if any pane is in a closed connection state.
|
||||
// - Show/hide the Restart Session context menu entry depending on active pane's state.
|
||||
// - Show/hide the Restart Connection context menu entry depending on active pane's state.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
@@ -1357,6 +1271,13 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
_tabStatus.IsConnectionClosed(isClosed);
|
||||
}
|
||||
|
||||
if (_activePane)
|
||||
{
|
||||
_restartConnectionMenuItem.Visibility(_activePane->IsConnectionClosed() ?
|
||||
WUX::Visibility::Visible :
|
||||
WUX::Visibility::Collapsed);
|
||||
}
|
||||
}
|
||||
|
||||
void Tab::_RestartActivePaneConnection()
|
||||
@@ -1427,22 +1348,6 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
_UpdateMenuItemStates();
|
||||
}
|
||||
|
||||
void Tab::_UpdateMenuItemStates()
|
||||
{
|
||||
// Terminal-specific menu items
|
||||
const auto content = _activePane ? _activePane->GetContent() : nullptr;
|
||||
const auto isTerm = content && content.try_as<winrt::TerminalApp::TerminalPaneContent>() != nullptr;
|
||||
_duplicateTabMenuItem.IsEnabled(isTerm);
|
||||
_exportTabMenuItem.IsEnabled(isTerm);
|
||||
_findMenuItem.IsEnabled(isTerm);
|
||||
_restartConnectionMenuItem.IsEnabled(isTerm);
|
||||
|
||||
// Snippets Pane can technically be split
|
||||
_splitTabMenuItem.IsEnabled(isTerm || (content && content.try_as<winrt::TerminalApp::SnippetsPaneContent>() != nullptr));
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -1488,10 +1393,6 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
tab->ShowBellIndicator(false);
|
||||
}
|
||||
if (tab->_tabStatus.ActivityIndicator())
|
||||
{
|
||||
tab->ShowActivityIndicator(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1751,100 +1652,106 @@ namespace winrt::TerminalApp::implementation
|
||||
Automation::AutomationProperties::SetHelpText(renameTabMenuItem, renameTabToolTip);
|
||||
}
|
||||
|
||||
Controls::MenuFlyoutItem duplicateTabMenuItem;
|
||||
{
|
||||
// "Duplicate tab"
|
||||
Controls::FontIcon duplicateTabSymbol;
|
||||
duplicateTabSymbol.FontFamily(Media::FontFamily{ L"Segoe Fluent Icons, Segoe MDL2 Assets" });
|
||||
duplicateTabSymbol.Glyph(L"\xF5ED");
|
||||
|
||||
_duplicateTabMenuItem.Click({ get_weak(), &Tab::_duplicateTabClicked });
|
||||
_duplicateTabMenuItem.Text(RS_(L"DuplicateTabText"));
|
||||
_duplicateTabMenuItem.Icon(duplicateTabSymbol);
|
||||
duplicateTabMenuItem.Click({ get_weak(), &Tab::_duplicateTabClicked });
|
||||
duplicateTabMenuItem.Text(RS_(L"DuplicateTabText"));
|
||||
duplicateTabMenuItem.Icon(duplicateTabSymbol);
|
||||
|
||||
const auto duplicateTabToolTip = RS_(L"DuplicateTabToolTip");
|
||||
|
||||
WUX::Controls::ToolTipService::SetToolTip(_duplicateTabMenuItem, box_value(duplicateTabToolTip));
|
||||
Automation::AutomationProperties::SetHelpText(_duplicateTabMenuItem, duplicateTabToolTip);
|
||||
WUX::Controls::ToolTipService::SetToolTip(duplicateTabMenuItem, box_value(duplicateTabToolTip));
|
||||
Automation::AutomationProperties::SetHelpText(duplicateTabMenuItem, duplicateTabToolTip);
|
||||
}
|
||||
|
||||
Controls::MenuFlyoutItem splitTabMenuItem;
|
||||
{
|
||||
// "Split tab"
|
||||
Controls::FontIcon splitTabSymbol;
|
||||
splitTabSymbol.FontFamily(Media::FontFamily{ L"Segoe Fluent Icons, Segoe MDL2 Assets" });
|
||||
splitTabSymbol.Glyph(L"\xF246"); // ViewDashboard
|
||||
|
||||
_splitTabMenuItem.Click({ get_weak(), &Tab::_splitTabClicked });
|
||||
_splitTabMenuItem.Text(RS_(L"SplitTabText"));
|
||||
_splitTabMenuItem.Icon(splitTabSymbol);
|
||||
splitTabMenuItem.Click({ get_weak(), &Tab::_splitTabClicked });
|
||||
splitTabMenuItem.Text(RS_(L"SplitTabText"));
|
||||
splitTabMenuItem.Icon(splitTabSymbol);
|
||||
|
||||
const auto splitTabToolTip = RS_(L"SplitTabToolTip");
|
||||
|
||||
WUX::Controls::ToolTipService::SetToolTip(_splitTabMenuItem, box_value(splitTabToolTip));
|
||||
Automation::AutomationProperties::SetHelpText(_splitTabMenuItem, splitTabToolTip);
|
||||
WUX::Controls::ToolTipService::SetToolTip(splitTabMenuItem, box_value(splitTabToolTip));
|
||||
Automation::AutomationProperties::SetHelpText(splitTabMenuItem, splitTabToolTip);
|
||||
}
|
||||
|
||||
Controls::MenuFlyoutItem closePaneMenuItem = _closePaneMenuItem;
|
||||
{
|
||||
// "Close pane"
|
||||
_closePaneMenuItem.Click({ get_weak(), &Tab::_closePaneClicked });
|
||||
_closePaneMenuItem.Text(RS_(L"ClosePaneText"));
|
||||
closePaneMenuItem.Click({ get_weak(), &Tab::_closePaneClicked });
|
||||
closePaneMenuItem.Text(RS_(L"ClosePaneText"));
|
||||
|
||||
const auto closePaneToolTip = RS_(L"ClosePaneToolTip");
|
||||
|
||||
WUX::Controls::ToolTipService::SetToolTip(_closePaneMenuItem, box_value(closePaneToolTip));
|
||||
Automation::AutomationProperties::SetHelpText(_closePaneMenuItem, closePaneToolTip);
|
||||
WUX::Controls::ToolTipService::SetToolTip(closePaneMenuItem, box_value(closePaneToolTip));
|
||||
Automation::AutomationProperties::SetHelpText(closePaneMenuItem, closePaneToolTip);
|
||||
}
|
||||
|
||||
Controls::MenuFlyoutItem exportTabMenuItem;
|
||||
{
|
||||
// "Export tab"
|
||||
Controls::FontIcon exportTabSymbol;
|
||||
exportTabSymbol.FontFamily(Media::FontFamily{ L"Segoe Fluent Icons, Segoe MDL2 Assets" });
|
||||
exportTabSymbol.Glyph(L"\xE74E"); // Save
|
||||
|
||||
_exportTabMenuItem.Click({ get_weak(), &Tab::_exportTextClicked });
|
||||
_exportTabMenuItem.Text(RS_(L"ExportTabText"));
|
||||
_exportTabMenuItem.Icon(exportTabSymbol);
|
||||
exportTabMenuItem.Click({ get_weak(), &Tab::_exportTextClicked });
|
||||
exportTabMenuItem.Text(RS_(L"ExportTabText"));
|
||||
exportTabMenuItem.Icon(exportTabSymbol);
|
||||
|
||||
const auto exportTabToolTip = RS_(L"ExportTabToolTip");
|
||||
|
||||
WUX::Controls::ToolTipService::SetToolTip(_exportTabMenuItem, box_value(exportTabToolTip));
|
||||
Automation::AutomationProperties::SetHelpText(_exportTabMenuItem, exportTabToolTip);
|
||||
WUX::Controls::ToolTipService::SetToolTip(exportTabMenuItem, box_value(exportTabToolTip));
|
||||
Automation::AutomationProperties::SetHelpText(exportTabMenuItem, exportTabToolTip);
|
||||
}
|
||||
|
||||
Controls::MenuFlyoutItem findMenuItem;
|
||||
{
|
||||
// "Find"
|
||||
Controls::FontIcon findSymbol;
|
||||
findSymbol.FontFamily(Media::FontFamily{ L"Segoe Fluent Icons, Segoe MDL2 Assets" });
|
||||
findSymbol.Glyph(L"\xF78B"); // SearchMedium
|
||||
|
||||
_findMenuItem.Click({ get_weak(), &Tab::_findClicked });
|
||||
_findMenuItem.Text(RS_(L"FindText"));
|
||||
_findMenuItem.Icon(findSymbol);
|
||||
findMenuItem.Click({ get_weak(), &Tab::_findClicked });
|
||||
findMenuItem.Text(RS_(L"FindText"));
|
||||
findMenuItem.Icon(findSymbol);
|
||||
|
||||
const auto findToolTip = RS_(L"FindToolTip");
|
||||
|
||||
WUX::Controls::ToolTipService::SetToolTip(_findMenuItem, box_value(findToolTip));
|
||||
Automation::AutomationProperties::SetHelpText(_findMenuItem, findToolTip);
|
||||
WUX::Controls::ToolTipService::SetToolTip(findMenuItem, box_value(findToolTip));
|
||||
Automation::AutomationProperties::SetHelpText(findMenuItem, findToolTip);
|
||||
}
|
||||
|
||||
Controls::MenuFlyoutItem restartConnectionMenuItem = _restartConnectionMenuItem;
|
||||
{
|
||||
// "Restart session"
|
||||
// "Restart connection"
|
||||
Controls::FontIcon restartConnectionSymbol;
|
||||
restartConnectionSymbol.FontFamily(Media::FontFamily{ L"Segoe Fluent Icons, Segoe MDL2 Assets" });
|
||||
restartConnectionSymbol.Glyph(L"\xE72C");
|
||||
|
||||
_restartConnectionMenuItem.Click([weakThis](auto&&, auto&&) {
|
||||
restartConnectionMenuItem.Click([weakThis](auto&&, auto&&) {
|
||||
if (auto tab{ weakThis.get() })
|
||||
{
|
||||
tab->_RestartActivePaneConnection();
|
||||
}
|
||||
});
|
||||
_restartConnectionMenuItem.Text(RS_(L"RestartConnectionText"));
|
||||
_restartConnectionMenuItem.Icon(restartConnectionSymbol);
|
||||
restartConnectionMenuItem.Text(RS_(L"RestartConnectionText"));
|
||||
restartConnectionMenuItem.Icon(restartConnectionSymbol);
|
||||
|
||||
const auto restartConnectionToolTip = RS_(L"RestartConnectionToolTip");
|
||||
|
||||
WUX::Controls::ToolTipService::SetToolTip(_restartConnectionMenuItem, box_value(restartConnectionToolTip));
|
||||
Automation::AutomationProperties::SetHelpText(_restartConnectionMenuItem, restartConnectionToolTip);
|
||||
WUX::Controls::ToolTipService::SetToolTip(restartConnectionMenuItem, box_value(restartConnectionToolTip));
|
||||
Automation::AutomationProperties::SetHelpText(restartConnectionMenuItem, restartConnectionToolTip);
|
||||
}
|
||||
|
||||
// Build the menu
|
||||
@@ -1852,16 +1759,16 @@ namespace winrt::TerminalApp::implementation
|
||||
Controls::MenuFlyoutSeparator menuSeparator;
|
||||
contextMenuFlyout.Items().Append(chooseColorMenuItem);
|
||||
contextMenuFlyout.Items().Append(renameTabMenuItem);
|
||||
contextMenuFlyout.Items().Append(_duplicateTabMenuItem);
|
||||
contextMenuFlyout.Items().Append(_splitTabMenuItem);
|
||||
contextMenuFlyout.Items().Append(duplicateTabMenuItem);
|
||||
contextMenuFlyout.Items().Append(splitTabMenuItem);
|
||||
_AppendMoveMenuItems(contextMenuFlyout);
|
||||
contextMenuFlyout.Items().Append(_exportTabMenuItem);
|
||||
contextMenuFlyout.Items().Append(_findMenuItem);
|
||||
contextMenuFlyout.Items().Append(_restartConnectionMenuItem);
|
||||
contextMenuFlyout.Items().Append(exportTabMenuItem);
|
||||
contextMenuFlyout.Items().Append(findMenuItem);
|
||||
contextMenuFlyout.Items().Append(restartConnectionMenuItem);
|
||||
contextMenuFlyout.Items().Append(menuSeparator);
|
||||
|
||||
auto closeSubMenu = _AppendCloseMenuItems(contextMenuFlyout);
|
||||
closeSubMenu.Items().Append(_closePaneMenuItem);
|
||||
closeSubMenu.Items().Append(closePaneMenuItem);
|
||||
|
||||
// GH#5750 - When the context menu is dismissed with ESC, toss the focus
|
||||
// back to our control.
|
||||
@@ -2315,7 +2222,8 @@ namespace winrt::TerminalApp::implementation
|
||||
if (tab->_tabStatus.IsInputBroadcastActive())
|
||||
{
|
||||
tab->_rootPane->BroadcastString(sender.try_as<TermControl>(),
|
||||
e.Text());
|
||||
e.Text(),
|
||||
static_cast<winrt::Microsoft::Terminal::Control::WriteInputStringType>(e.Type()));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -48,9 +48,6 @@ namespace winrt::TerminalApp::implementation
|
||||
void ShowBellIndicator(const bool show);
|
||||
void ActivateBellIndicatorTimer();
|
||||
|
||||
void ShowActivityIndicator(const bool show);
|
||||
void ActivateActivityIndicatorTimer();
|
||||
|
||||
float CalcSnappedDimension(const bool widthOrHeight, const float dimension) const;
|
||||
std::optional<winrt::Microsoft::Terminal::Settings::Model::SplitDirection> PreCalculateCanSplit(winrt::Microsoft::Terminal::Settings::Model::SplitDirection splitType,
|
||||
const float splitSize,
|
||||
@@ -124,7 +121,6 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
til::typed_event<TerminalApp::Tab, IInspectable> ActivePaneChanged;
|
||||
til::event<winrt::delegate<>> TabRaiseVisualBell;
|
||||
til::event<winrt::delegate<winrt::hstring /*title*/, winrt::hstring /*body*/, winrt::TerminalApp::IPaneContent /*content*/>> TabToastNotificationRequested;
|
||||
til::typed_event<IInspectable, IInspectable> TaskbarProgressChanged;
|
||||
|
||||
// The TabViewIndex is the index this Tab object resides in TerminalPage's _tabs vector.
|
||||
@@ -144,17 +140,11 @@ namespace winrt::TerminalApp::implementation
|
||||
static constexpr double HeaderRenameBoxWidthTitleLength{ std::numeric_limits<double>::infinity() };
|
||||
|
||||
winrt::Windows::UI::Xaml::FocusState _focusState{ winrt::Windows::UI::Xaml::FocusState::Unfocused };
|
||||
winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _duplicateTabMenuItem{};
|
||||
winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _splitTabMenuItem{};
|
||||
winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _closeOtherTabsMenuItem{};
|
||||
winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _closeTabsAfterMenuItem{};
|
||||
winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _moveToNewWindowMenuItem{};
|
||||
winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _moveRightMenuItem{};
|
||||
winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _moveLeftMenuItem{};
|
||||
winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _exportTabMenuItem{};
|
||||
winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _findMenuItem{};
|
||||
winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _restartConnectionMenuItem{};
|
||||
winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _closeOtherTabsMenuItem{};
|
||||
winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _closeTabsAfterMenuItem{};
|
||||
winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _closePaneMenuItem{};
|
||||
winrt::TerminalApp::ShortcutActionDispatch _dispatch;
|
||||
Microsoft::Terminal::Settings::Model::IActionMapView _actionMap{ nullptr };
|
||||
winrt::hstring _keyChord{};
|
||||
@@ -169,6 +159,9 @@ namespace winrt::TerminalApp::implementation
|
||||
std::shared_ptr<Pane> _activePane{ nullptr };
|
||||
std::shared_ptr<Pane> _zoomedPane{ nullptr };
|
||||
|
||||
Windows::UI::Xaml::Controls::MenuFlyoutItem _closePaneMenuItem;
|
||||
Windows::UI::Xaml::Controls::MenuFlyoutItem _restartConnectionMenuItem;
|
||||
|
||||
winrt::Microsoft::Terminal::Settings::Model::IconStyle _lastIconStyle;
|
||||
winrt::hstring _lastIconPath{};
|
||||
std::optional<winrt::Windows::UI::Color> _runtimeTabColor{};
|
||||
@@ -189,7 +182,6 @@ namespace winrt::TerminalApp::implementation
|
||||
winrt::TerminalApp::IPaneContent::ConnectionStateChanged_revoker ConnectionStateChanged;
|
||||
winrt::TerminalApp::IPaneContent::ReadOnlyChanged_revoker ReadOnlyChanged;
|
||||
winrt::TerminalApp::IPaneContent::FocusRequested_revoker FocusRequested;
|
||||
winrt::TerminalApp::IPaneContent::NotificationRequested_revoker NotificationRequested;
|
||||
|
||||
// These events literally only apply if the content is a TermControl.
|
||||
winrt::Microsoft::Terminal::Control::TermControl::KeySent_revoker KeySent;
|
||||
@@ -218,9 +210,6 @@ namespace winrt::TerminalApp::implementation
|
||||
SafeDispatcherTimer _bellIndicatorTimer;
|
||||
void _BellIndicatorTimerTick(const Windows::Foundation::IInspectable& sender, const Windows::Foundation::IInspectable& e);
|
||||
|
||||
SafeDispatcherTimer _activityIndicatorTimer;
|
||||
void _ActivityIndicatorTimerTick(const Windows::Foundation::IInspectable& sender, const Windows::Foundation::IInspectable& e);
|
||||
|
||||
void _UpdateHeaderControlMaxWidth();
|
||||
|
||||
void _CreateContextMenu();
|
||||
@@ -231,7 +220,6 @@ namespace winrt::TerminalApp::implementation
|
||||
void _AttachEventHandlersToPane(std::shared_ptr<Pane> pane);
|
||||
|
||||
void _UpdateActivePane(std::shared_ptr<Pane> pane);
|
||||
void _UpdateMenuItemStates();
|
||||
|
||||
winrt::hstring _GetActiveTitle() const;
|
||||
|
||||
@@ -242,6 +230,8 @@ namespace winrt::TerminalApp::implementation
|
||||
void _UpdateConnectionClosedState();
|
||||
void _RestartActivePaneConnection();
|
||||
|
||||
void _DuplicateTab();
|
||||
|
||||
winrt::Windows::UI::Xaml::Media::Brush _BackgroundBrush();
|
||||
|
||||
void _MakeTabViewItem();
|
||||
|
||||
@@ -32,12 +32,6 @@
|
||||
FontSize="12"
|
||||
Glyph=""
|
||||
Visibility="{x:Bind TabStatus.BellIndicator, Mode=OneWay}" />
|
||||
<FontIcon x:Name="HeaderActivityIndicator"
|
||||
Margin="0,0,8,0"
|
||||
FontFamily="{ThemeResource SymbolThemeFontFamily}"
|
||||
FontSize="8"
|
||||
Glyph=""
|
||||
Visibility="{x:Bind TabStatus.ActivityIndicator, Mode=OneWay}" />
|
||||
<FontIcon x:Name="HeaderZoomIcon"
|
||||
Margin="0,0,8,0"
|
||||
FontFamily="{ThemeResource SymbolThemeFontFamily}"
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
#include "TabRowControl.h"
|
||||
#include "DebugTapConnection.h"
|
||||
#include "DesktopNotification.h"
|
||||
#include "..\TerminalSettingsModel\FileUtils.h"
|
||||
#include "../TerminalSettingsAppAdapterLib/TerminalSettings.h"
|
||||
|
||||
@@ -151,18 +150,6 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
});
|
||||
|
||||
// When a tab requests a desktop toast notification, send the toast
|
||||
// and handle activation by summoning this window and switching to the tab.
|
||||
newTabImpl->TabToastNotificationRequested([weakThis{ get_weak() }, weakTab{ newTabImpl->get_weak() }](const winrt::hstring& title, const winrt::hstring& body, const winrt::TerminalApp::IPaneContent& content) {
|
||||
if (const auto page{ weakThis.get() })
|
||||
{
|
||||
if (const auto tab{ weakTab.get() })
|
||||
{
|
||||
page->_SendDesktopNotification(title, body, tab, content);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
auto tabViewItem = newTabImpl->TabViewItem();
|
||||
_tabView.TabItems().InsertAt(insertPosition, tabViewItem);
|
||||
|
||||
@@ -407,9 +394,7 @@ namespace winrt::TerminalApp::implementation
|
||||
// - Removes the tab (both TerminalControl and XAML) after prompting for approval
|
||||
// Arguments:
|
||||
// - tab: the tab to remove
|
||||
// - skipConfirmClose: if true, skip the confirmOnClose check. Used when
|
||||
// an aggregate confirmation has already been shown (i.e. close other tabs)
|
||||
winrt::Windows::Foundation::IAsyncAction TerminalPage::_HandleCloseTabRequested(winrt::TerminalApp::Tab tab, bool skipConfirmClose)
|
||||
winrt::Windows::Foundation::IAsyncAction TerminalPage::_HandleCloseTabRequested(winrt::TerminalApp::Tab tab)
|
||||
{
|
||||
winrt::com_ptr<TerminalPage> strong;
|
||||
|
||||
@@ -428,24 +413,6 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
}
|
||||
|
||||
// Skip the per-tab confirmOnClose check when the caller has already
|
||||
// shown an aggregate confirmation dialog (e.g. _RemoveTabs).
|
||||
if (!skipConfirmClose)
|
||||
{
|
||||
const auto tabImpl = _GetTabImpl(tab);
|
||||
if (tabImpl && _ShouldWarnOnCloseTab(tabImpl))
|
||||
{
|
||||
const auto weak = get_weak();
|
||||
|
||||
auto warningResult = co_await _ShowConfirmCloseDialog(ConfirmCloseDialogKind::Tab);
|
||||
strong = weak.get();
|
||||
if (!strong || warningResult != ContentDialogResult::Primary)
|
||||
{
|
||||
co_return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto t = winrt::get_self<implementation::Tab>(tab);
|
||||
auto actions = t->BuildStartupActions(BuildStartupKind::None);
|
||||
_AddPreviouslyClosedPaneOrTab(std::move(actions));
|
||||
@@ -815,26 +782,6 @@ namespace winrt::TerminalApp::implementation
|
||||
if (const auto pane{ activeTab->GetActivePane() })
|
||||
{
|
||||
const auto weak = get_weak();
|
||||
|
||||
// Check if we should warn before closing a single pane
|
||||
// (only triggers on Always — Automatic doesn't warn for single pane)
|
||||
const auto setting = _settings.GlobalSettings().ConfirmOnClose();
|
||||
if (setting == ConfirmOnClose::Always)
|
||||
{
|
||||
// If this is the last pane, closing it closes the tab,
|
||||
// so use the tab dialog text instead.
|
||||
const auto kind = activeTab->GetLeafPaneCount() == 1 ? ConfirmCloseDialogKind::Tab : ConfirmCloseDialogKind::Pane;
|
||||
auto warningResult = co_await _ShowConfirmCloseDialog(kind);
|
||||
|
||||
// Hold a strong reference to `this` for the rest of the
|
||||
// method; we may be the last holder after `co_await`.
|
||||
auto strong = weak.get();
|
||||
if (!strong || warningResult != ContentDialogResult::Primary)
|
||||
{
|
||||
co_return;
|
||||
}
|
||||
}
|
||||
|
||||
if (co_await _PaneConfirmCloseReadOnly(pane))
|
||||
{
|
||||
if (const auto strong = weak.get())
|
||||
@@ -848,37 +795,10 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
// Method Description:
|
||||
// - Close all panes with the given IDs sequentially.
|
||||
// - Shows a single aggregate confirmation dialog upfront if the confirmOnClose setting warrants it.
|
||||
// Arguments:
|
||||
// - weakTab: weak reference to the tab that the panes belong to.
|
||||
// - weakTab: weak reference to the tab that the pane belongs to.
|
||||
// - paneIds: collection of the IDs of the panes that are marked for removal.
|
||||
safe_void_coroutine TerminalPage::_ClosePanes(weak_ref<Tab> weakTab, std::vector<uint32_t> paneIds)
|
||||
{
|
||||
// Show a single aggregate confirmation for closing multiple panes.
|
||||
if (_settings.GlobalSettings().ConfirmOnClose() != ConfirmOnClose::Never)
|
||||
{
|
||||
const auto weak = get_weak();
|
||||
auto warningResult = co_await _ShowConfirmCloseDialog(ConfirmCloseDialogKind::MultiplePanes);
|
||||
|
||||
// Hold a strong reference to `this` after the co_await; we may
|
||||
// be the last holder if the page was being torn down.
|
||||
auto strong = weak.get();
|
||||
if (!strong || warningResult != ContentDialogResult::Primary)
|
||||
{
|
||||
co_return;
|
||||
}
|
||||
}
|
||||
_CloseRemainingPanes(weakTab, std::move(paneIds));
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Recursively closes panes by ID, chaining each close via the
|
||||
// ClosedByParent callback. Called after confirmation has already
|
||||
// been handled by _ClosePanes.
|
||||
// Arguments:
|
||||
// - weakTab: weak reference to the tab that the panes belong to
|
||||
// - paneIds: remaining pane IDs to close
|
||||
void TerminalPage::_CloseRemainingPanes(weak_ref<Tab> weakTab, std::vector<uint32_t> paneIds)
|
||||
void TerminalPage::_ClosePanes(weak_ref<Tab> weakTab, std::vector<uint32_t> paneIds)
|
||||
{
|
||||
if (auto strongTab{ weakTab.get() })
|
||||
{
|
||||
@@ -893,9 +813,10 @@ namespace winrt::TerminalApp::implementation
|
||||
pane->ClosedByParent([ids{ std::move(paneIds) }, weakThis{ get_weak() }, weakTab]() {
|
||||
if (auto strongThis{ weakThis.get() })
|
||||
{
|
||||
strongThis->_CloseRemainingPanes(weakTab, std::move(ids));
|
||||
strongThis->_ClosePanes(weakTab, std::move(ids));
|
||||
}
|
||||
});
|
||||
|
||||
// Close the pane which will eventually trigger the closed by parent event
|
||||
_HandleClosePaneRequested(pane);
|
||||
break;
|
||||
@@ -920,37 +841,18 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
// Method Description:
|
||||
// - Closes provided tabs one by one
|
||||
// - Shows a single aggregate confirmation dialog upfront if the confirmOnClose setting warrants it.
|
||||
// Arguments:
|
||||
// - tabs - tabs to remove
|
||||
safe_void_coroutine TerminalPage::_RemoveTabs(const std::vector<winrt::TerminalApp::Tab> tabs)
|
||||
{
|
||||
if (tabs.empty())
|
||||
{
|
||||
co_return;
|
||||
}
|
||||
|
||||
// Show a single aggregate confirmation instead of per-tab dialogs.
|
||||
const auto weak = get_weak();
|
||||
if (_settings.GlobalSettings().ConfirmOnClose() != ConfirmOnClose::Never)
|
||||
{
|
||||
auto warningResult = co_await _ShowConfirmCloseDialog(ConfirmCloseDialogKind::MultipleTabs);
|
||||
|
||||
// Hold a strong reference to `this` after the co_await so that
|
||||
// the for-loop below can safely dispatch on us.
|
||||
auto strong = weak.get();
|
||||
if (!strong || warningResult != ContentDialogResult::Primary)
|
||||
{
|
||||
co_return;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& tab : tabs)
|
||||
{
|
||||
winrt::Windows::Foundation::IAsyncAction action{ nullptr };
|
||||
if (const auto strong = weak.get())
|
||||
{
|
||||
action = _HandleCloseTabRequested(tab, /*skipConfirmClose*/ true);
|
||||
action = _HandleCloseTabRequested(tab);
|
||||
}
|
||||
|
||||
if (!action)
|
||||
@@ -1283,128 +1185,4 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
return _tabs.Size() > 1;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Attempts to find and focus the given tab in this window.
|
||||
// Arguments:
|
||||
// - tab: The tab to focus.
|
||||
// Return Value:
|
||||
// - true if the tab was found and focused, false otherwise.
|
||||
bool TerminalPage::FocusTab(const winrt::TerminalApp::Tab& tab)
|
||||
{
|
||||
if (const auto tabIndex{ _GetTabIndex(tab) })
|
||||
{
|
||||
_SelectTab(tabIndex.value());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Sends a desktop toast notification with the given title and body.
|
||||
// When the toast is activated (clicked), the window is summoned and
|
||||
// the originating tab is focused.
|
||||
// Arguments:
|
||||
// - tabTitle: The title to display in the notification.
|
||||
// - body: The body text. If empty, a standard tab-activity message is built.
|
||||
// - tab: The tab to switch to when the toast is activated.
|
||||
void TerminalPage::_SendDesktopNotification(const winrt::hstring& tabTitle, const winrt::hstring& body, const winrt::com_ptr<Tab>& tab, const winrt::TerminalApp::IPaneContent& content)
|
||||
{
|
||||
// Don't send a notification if the window is focused and the requesting
|
||||
// pane is the active pane. The user is already looking at it.
|
||||
if (_activated && tab == _GetFocusedTabImpl())
|
||||
{
|
||||
if (const auto activePane{ tab->GetActivePane() })
|
||||
{
|
||||
if (activePane->GetContent() == content)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Build the notification message.
|
||||
// If a custom body is provided (e.g. from OSC 777), use the title/body directly.
|
||||
// Otherwise, build the standard tab-activity notification message.
|
||||
winrt::hstring notificationTitle;
|
||||
winrt::hstring message;
|
||||
if (!body.empty())
|
||||
{
|
||||
notificationTitle = tabTitle;
|
||||
message = body;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use the window name if available for context; otherwise just use the tab title.
|
||||
// Use the raw WindowName (not WindowNameForDisplay) so we don't include
|
||||
// the "<unnamed window>" placeholder in the notification body.
|
||||
const auto windowName = _WindowProperties ? _WindowProperties.WindowName() : winrt::hstring{};
|
||||
if (!windowName.empty())
|
||||
{
|
||||
message = RS_fmt(L"NotificationMessage_TabActivityInWindow", std::wstring_view{ tabTitle }, std::wstring_view{ windowName });
|
||||
}
|
||||
else
|
||||
{
|
||||
message = RS_fmt(L"NotificationMessage_TabActivity", std::wstring_view{ tabTitle });
|
||||
}
|
||||
notificationTitle = CascadiaSettings::ApplicationDisplayName();
|
||||
}
|
||||
|
||||
// Use the Tab object's identity hash as a stable toast tag.
|
||||
// This survives tab reordering and cross-window moves.
|
||||
const auto tabHash = std::hash<winrt::Windows::Foundation::IUnknown>{}(*tab);
|
||||
const hstring tabTag{ fmt::format(FMT_COMPILE(L"wt-tab-{:016x}"), tabHash) };
|
||||
|
||||
const implementation::DesktopNotificationArgs args{
|
||||
.Title = notificationTitle,
|
||||
.Message = message,
|
||||
.Tag = tabTag
|
||||
};
|
||||
|
||||
implementation::DesktopNotification::SendNotification(args, [weakThis{ get_weak() }, weakTab{ tab->get_weak() }, weakContent{ winrt::make_weak(content) }]() {
|
||||
if (const auto page{ weakThis.get() })
|
||||
{
|
||||
// The toast Activated callback runs on a background thread.
|
||||
// Marshal to the UI thread for tab focus and window summon.
|
||||
page->Dispatcher().RunAsync(winrt::Windows::UI::Core::CoreDispatcherPriority::Normal, [weakThis, weakTab, weakContent]() {
|
||||
if (const auto p{ weakThis.get() })
|
||||
{
|
||||
if (const auto t{ weakTab.get() })
|
||||
{
|
||||
// Try to find and focus the tab in this window first.
|
||||
if (const auto tabIndex{ p->_GetTabIndex(*t) })
|
||||
{
|
||||
p->SummonWindowRequested.raise(nullptr, nullptr);
|
||||
p->_SelectTab(tabIndex.value());
|
||||
|
||||
// Focus the specific pane that raised the notification.
|
||||
if (const auto paneContent{ weakContent.get() })
|
||||
{
|
||||
const auto rootPane = t->GetRootPane();
|
||||
rootPane->WalkTree([&](const auto& pane) {
|
||||
if (pane->GetContent() == paneContent)
|
||||
{
|
||||
rootPane->FocusPane(pane);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The tab may have moved to another window.
|
||||
// Raise FocusTabRequested so the emperor can
|
||||
// search all windows for it.
|
||||
p->FocusTabRequested.raise(nullptr, *t);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Tab was closed. Just summon this window.
|
||||
p->SummonWindowRequested.raise(nullptr, nullptr);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,28 +9,27 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
// Default to unset, 0%.
|
||||
TaskbarState::TaskbarState() :
|
||||
TaskbarState(winrt::Microsoft::Terminal::Control::TaskbarState::Clear, 0) {};
|
||||
TaskbarState(0, 0) {};
|
||||
|
||||
TaskbarState::TaskbarState(const winrt::Microsoft::Terminal::Control::TaskbarState state, const uint64_t progressParam) :
|
||||
_State{ state },
|
||||
TaskbarState::TaskbarState(const uint64_t dispatchTypesState, const uint64_t progressParam) :
|
||||
_State{ dispatchTypesState },
|
||||
_Progress{ progressParam } {}
|
||||
|
||||
uint64_t TaskbarState::Priority() const
|
||||
{
|
||||
// This seemingly nonsensical ordering is from
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-itaskbarlist3-setprogressstate#how-the-taskbar-button-chooses-the-progress-indicator-for-a-group
|
||||
using TbState = winrt::Microsoft::Terminal::Control::TaskbarState;
|
||||
switch (_State)
|
||||
{
|
||||
case TbState::Clear:
|
||||
case 0: // Clear = 0,
|
||||
return 5;
|
||||
case TbState::Set:
|
||||
case 1: // Set = 1,
|
||||
return 3;
|
||||
case TbState::Error:
|
||||
case 2: // Error = 2,
|
||||
return 1;
|
||||
case TbState::Indeterminate:
|
||||
case 3: // Indeterminate = 3,
|
||||
return 4;
|
||||
case TbState::Paused:
|
||||
case 4: // Paused = 4
|
||||
return 2;
|
||||
}
|
||||
// Here, return 6, to definitely be greater than all the other valid values.
|
||||
|
||||
@@ -16,13 +16,13 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
public:
|
||||
TaskbarState();
|
||||
TaskbarState(const winrt::Microsoft::Terminal::Control::TaskbarState state, const uint64_t progress);
|
||||
TaskbarState(const uint64_t dispatchTypesState, const uint64_t progress);
|
||||
|
||||
static int ComparePriority(const winrt::TerminalApp::TaskbarState& lhs, const winrt::TerminalApp::TaskbarState& rhs);
|
||||
|
||||
uint64_t Priority() const;
|
||||
|
||||
WINRT_PROPERTY(winrt::Microsoft::Terminal::Control::TaskbarState, State, winrt::Microsoft::Terminal::Control::TaskbarState::Clear);
|
||||
WINRT_PROPERTY(uint64_t, State, 0);
|
||||
WINRT_PROPERTY(uint64_t, Progress, 0);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,9 +6,9 @@ namespace TerminalApp
|
||||
[default_interface] runtimeclass TaskbarState
|
||||
{
|
||||
TaskbarState();
|
||||
TaskbarState(Microsoft.Terminal.Control.TaskbarState state, UInt64 progress);
|
||||
TaskbarState(UInt64 dispatchTypesState, UInt64 progress);
|
||||
|
||||
Microsoft.Terminal.Control.TaskbarState State{ get; };
|
||||
UInt64 State{ get; };
|
||||
UInt64 Progress{ get; };
|
||||
UInt64 Priority { get; };
|
||||
}
|
||||
|
||||
@@ -174,7 +174,6 @@
|
||||
<DependentUpon>TerminalPaneContent.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Toast.h" />
|
||||
<ClInclude Include="DesktopNotification.h" />
|
||||
<ClInclude Include="TerminalSettingsCache.h" />
|
||||
<ClInclude Include="SuggestionsControl.h">
|
||||
<DependentUpon>SuggestionsControl.xaml</DependentUpon>
|
||||
@@ -288,7 +287,6 @@
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
|
||||
<ClCompile Include="Toast.cpp" />
|
||||
<ClCompile Include="DesktopNotification.cpp" />
|
||||
<ClCompile Include="TerminalSettingsCache.cpp" />
|
||||
<ClCompile Include="SuggestionsControl.cpp">
|
||||
<DependentUpon>SuggestionsControl.xaml</DependentUpon>
|
||||
|
||||
@@ -884,78 +884,26 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Displays the unified close confirmation dialog configured for the
|
||||
// given scenario. Resets the "don't ask me again" checkbox before showing.
|
||||
// If the user confirms and checked "don't ask me again", sets
|
||||
// confirmOnClose to Never and writes settings to disk.
|
||||
// - Displays a dialog to warn the user that they are about to close all open windows.
|
||||
// Once the user clicks the OK button, shut down the application.
|
||||
// If cancel is clicked, the dialog will close.
|
||||
// - Only one dialog can be visible at a time. If another dialog is visible
|
||||
// when this is called, nothing happens. See _ShowDialog for details
|
||||
winrt::Windows::Foundation::IAsyncOperation<ContentDialogResult> TerminalPage::_ShowConfirmCloseDialog(ConfirmCloseDialogKind kind)
|
||||
winrt::Windows::Foundation::IAsyncOperation<ContentDialogResult> TerminalPage::_ShowQuitDialog()
|
||||
{
|
||||
// Load the dialog (triggers x:Load) and configure its strings.
|
||||
const auto dialog = FindName(L"ConfirmCloseDialog").as<ContentDialog>();
|
||||
return _ShowDialogHelper(L"QuitDialog");
|
||||
}
|
||||
|
||||
winrt::hstring title;
|
||||
winrt::hstring primary;
|
||||
switch (kind)
|
||||
{
|
||||
case ConfirmCloseDialogKind::CloseAll:
|
||||
title = RS_(L"ConfirmCloseDialog_CloseAllTitle");
|
||||
primary = RS_(L"ConfirmCloseDialog_CloseAllPrimary");
|
||||
break;
|
||||
case ConfirmCloseDialogKind::Window:
|
||||
title = RS_(L"ConfirmCloseDialog_WindowTitle");
|
||||
primary = RS_(L"ConfirmCloseDialog_WindowPrimary");
|
||||
break;
|
||||
case ConfirmCloseDialogKind::Tab:
|
||||
title = RS_(L"ConfirmCloseDialog_TabTitle");
|
||||
primary = RS_(L"ConfirmCloseDialog_TabPrimary");
|
||||
break;
|
||||
case ConfirmCloseDialogKind::MultiplePanes:
|
||||
title = RS_(L"ConfirmCloseDialog_MultiplePanesTitle");
|
||||
primary = RS_(L"ConfirmCloseDialog_MultiplePanesPrimary");
|
||||
break;
|
||||
case ConfirmCloseDialogKind::MultipleTabs:
|
||||
title = RS_(L"ConfirmCloseDialog_MultipleTabsTitle");
|
||||
primary = RS_(L"ConfirmCloseDialog_MultipleTabsPrimary");
|
||||
break;
|
||||
case ConfirmCloseDialogKind::Pane:
|
||||
title = RS_(L"ConfirmCloseDialog_PaneTitle");
|
||||
primary = RS_(L"ConfirmCloseDialog_PanePrimary");
|
||||
break;
|
||||
}
|
||||
dialog.Title(winrt::box_value(title));
|
||||
dialog.PrimaryButtonText(primary);
|
||||
dialog.CloseButtonText(RS_(L"ConfirmCloseDialog_Cancel"));
|
||||
|
||||
// BODGY: After a ContentDialog is dismissed, FindName() can no longer
|
||||
// resolve children inside it. Use Content() to get the checkbox directly.
|
||||
const auto checkbox = dialog.Content().as<CheckBox>();
|
||||
checkbox.IsChecked(false);
|
||||
|
||||
auto result = ContentDialogResult::None;
|
||||
if (auto presenter{ _dialogPresenter.get() })
|
||||
{
|
||||
const auto weak = get_weak();
|
||||
result = co_await presenter.ShowDialog(dialog);
|
||||
|
||||
// ShowDialog blocks until the dialog is dismissed, so it is
|
||||
// possible for `this` to be torn down while we wait. Re-acquire
|
||||
// a strong reference before touching any of our state.
|
||||
const auto strong = weak.get();
|
||||
if (!strong)
|
||||
{
|
||||
co_return ContentDialogResult::None;
|
||||
}
|
||||
|
||||
if (result == ContentDialogResult::Primary && checkbox.IsChecked().Value())
|
||||
{
|
||||
_settings.GlobalSettings().ConfirmOnClose(ConfirmOnClose::Never);
|
||||
_settings.WriteSettingsToDisk();
|
||||
}
|
||||
}
|
||||
|
||||
co_return result;
|
||||
// Method Description:
|
||||
// - Displays a dialog for warnings found while closing the terminal app using
|
||||
// key binding with multiple tabs opened. Display messages to warn user
|
||||
// that more than 1 tab is opened, and once the user clicks the OK button, remove
|
||||
// all the tabs and shut down and app. If cancel is clicked, the dialog will close
|
||||
// - Only one dialog can be visible at a time. If another dialog is visible
|
||||
// when this is called, nothing happens. See _ShowDialog for details
|
||||
winrt::Windows::Foundation::IAsyncOperation<ContentDialogResult> TerminalPage::_ShowCloseWarningDialog()
|
||||
{
|
||||
return _ShowDialogHelper(L"CloseAllDialog");
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -2261,13 +2209,12 @@ namespace winrt::TerminalApp::implementation
|
||||
// signal that we want to close everything.
|
||||
safe_void_coroutine TerminalPage::RequestQuit()
|
||||
{
|
||||
const auto setting = _settings.GlobalSettings().ConfirmOnClose();
|
||||
if (setting != ConfirmOnClose::Never && !_displayingCloseDialog)
|
||||
if (!_displayingCloseDialog)
|
||||
{
|
||||
_displayingCloseDialog = true;
|
||||
|
||||
const auto weak = get_weak();
|
||||
auto warningResult = co_await _ShowConfirmCloseDialog(ConfirmCloseDialogKind::CloseAll);
|
||||
auto warningResult = co_await _ShowQuitDialog();
|
||||
const auto strong = weak.get();
|
||||
if (!strong)
|
||||
{
|
||||
@@ -2280,9 +2227,9 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
co_return;
|
||||
}
|
||||
}
|
||||
|
||||
QuitRequested.raise(nullptr, nullptr);
|
||||
QuitRequested.raise(nullptr, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void TerminalPage::PersistState()
|
||||
@@ -2360,59 +2307,12 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Determines whether a close-window action should show a confirmation
|
||||
// dialog, based on the confirmOnClose setting and the current window state.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - true, if a warning dialog should be shown before closing the window
|
||||
bool TerminalPage::_ShouldWarnOnClose() const
|
||||
{
|
||||
const auto setting = _settings.GlobalSettings().ConfirmOnClose();
|
||||
switch (setting)
|
||||
{
|
||||
case ConfirmOnClose::Always:
|
||||
return true;
|
||||
case ConfirmOnClose::Automatic:
|
||||
{
|
||||
// Warn if there's more than one tab, or the one tab has more than one pane.
|
||||
return _HasMultipleTabs() || _GetTabImpl(_tabs.GetAt(0))->GetLeafPaneCount() > 1;
|
||||
}
|
||||
case ConfirmOnClose::Never:
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Determines whether closing a specific tab should show a confirmation
|
||||
// dialog, based on the confirmOnClose setting and the tab's state.
|
||||
// Arguments:
|
||||
// - tab: The tab being closed
|
||||
// Return Value:
|
||||
// - true, if a warning dialog should be shown before closing the tab
|
||||
bool TerminalPage::_ShouldWarnOnCloseTab(const winrt::com_ptr<Tab>& tab) const
|
||||
{
|
||||
const auto setting = _settings.GlobalSettings().ConfirmOnClose();
|
||||
switch (setting)
|
||||
{
|
||||
case ConfirmOnClose::Always:
|
||||
return true;
|
||||
case ConfirmOnClose::Automatic:
|
||||
// Warn if this tab has more than one pane.
|
||||
return tab->GetLeafPaneCount() > 1;
|
||||
case ConfirmOnClose::Never:
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Close the terminal app. If the confirmOnClose setting indicates we should
|
||||
// warn for the current window state, show a warning dialog.
|
||||
// - Close the terminal app. If there is more
|
||||
// than one tab opened, show a warning dialog.
|
||||
safe_void_coroutine TerminalPage::CloseWindow()
|
||||
{
|
||||
if (_ShouldWarnOnClose() &&
|
||||
if (_HasMultipleTabs() &&
|
||||
_settings.GlobalSettings().ConfirmCloseAllTabs() &&
|
||||
!_displayingCloseDialog)
|
||||
{
|
||||
if (_newTabButton && _newTabButton.Flyout())
|
||||
@@ -2421,17 +2321,7 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
_DismissTabContextMenus();
|
||||
_displayingCloseDialog = true;
|
||||
|
||||
const auto weak = get_weak();
|
||||
auto warningResult = co_await _ShowConfirmCloseDialog(ConfirmCloseDialogKind::Window);
|
||||
// Hold a strong reference to `this` after the co_await; we may
|
||||
// be the last holder if the window was already being torn down.
|
||||
auto strong = weak.get();
|
||||
if (!strong)
|
||||
{
|
||||
co_return;
|
||||
}
|
||||
|
||||
auto warningResult = co_await _ShowCloseWarningDialog();
|
||||
_displayingCloseDialog = false;
|
||||
|
||||
if (warningResult != ContentDialogResult::Primary)
|
||||
@@ -3055,9 +2945,7 @@ namespace winrt::TerminalApp::implementation
|
||||
// - Sends the text back to the TermControl through the event's
|
||||
// `HandleClipboardData` member function.
|
||||
// - Does some of this in a background thread, as to not hang/crash the UI thread.
|
||||
// Arguments:
|
||||
// - eventArgs: the PasteFromClipboard event sent from the TermControl
|
||||
safe_void_coroutine TerminalPage::_PasteFromClipboardHandler(const IInspectable sender, const PasteFromClipboardEventArgs eventArgs)
|
||||
safe_void_coroutine TerminalPage::_PasteFromClipboardHandler(const IInspectable sender, const IInspectable /* args */)
|
||||
try
|
||||
{
|
||||
// The old Win32 clipboard API as used below is somewhere in the order of 300-1000x faster than
|
||||
@@ -3065,8 +2953,13 @@ namespace winrt::TerminalApp::implementation
|
||||
const auto weakThis = get_weak();
|
||||
const auto dispatcher = Dispatcher();
|
||||
const auto globalSettings = _settings.GlobalSettings();
|
||||
const auto bracketedPaste = eventArgs.BracketedPasteEnabled();
|
||||
const auto sourceId = sender.try_as<ControlInteractivity>().Id();
|
||||
const auto control = sender.as<TermControl>();
|
||||
// TODO GH#20164 these were added to ease the transition to broadcast group management; fill them in
|
||||
// Used to determine whether to emit empty pastes and strip extra whitespace
|
||||
const auto anyHasBracketedPaste = control && !control.ReadOnly() && control.BracketedPasteEnabled();
|
||||
// Used to determine whether to warn on multi-line paste
|
||||
// If none lack bracketed paste, we can skip the warning.
|
||||
const auto anyHasUnbracketedPaste = !anyHasBracketedPaste;
|
||||
|
||||
// GetClipboardData might block for up to 30s for delay-rendered contents.
|
||||
co_await winrt::resume_background();
|
||||
@@ -3077,8 +2970,11 @@ namespace winrt::TerminalApp::implementation
|
||||
text = clipboard::read();
|
||||
}
|
||||
|
||||
if (!bracketedPaste && globalSettings.TrimPaste())
|
||||
if (!anyHasBracketedPaste && globalSettings.TrimPaste())
|
||||
{
|
||||
// Warning - when broadcast is enabled, this will trim the paste for all receivers.
|
||||
// Until we propagate this decision-making elsewhere, this is safer; broadcast will not auto-submit commands in other panes.
|
||||
// Tracked in GH#20164
|
||||
text = winrt::hstring{ Utils::TrimPaste(text) };
|
||||
}
|
||||
|
||||
@@ -3086,7 +2982,7 @@ namespace winrt::TerminalApp::implementation
|
||||
// Bracketed Paste provides an application a way to know whether the
|
||||
// user pasted, even if there was no applicable content on it. This
|
||||
// behavior is observed in GNOME Terminal, among others.
|
||||
if (!bracketedPaste && text.empty())
|
||||
if (!anyHasBracketedPaste && text.empty())
|
||||
{
|
||||
co_return;
|
||||
}
|
||||
@@ -3098,7 +2994,7 @@ namespace winrt::TerminalApp::implementation
|
||||
// NOTE that this is unsafe, because a shell that doesn't support bracketed paste
|
||||
// will allow an attacker to enable the mode, not realize that, and then accept
|
||||
// the paste as if it was a series of legitimate commands. See GH#13014.
|
||||
warnMultiLine = !bracketedPaste;
|
||||
warnMultiLine = anyHasUnbracketedPaste;
|
||||
break;
|
||||
case WarnAboutMultiLinePaste::Always:
|
||||
warnMultiLine = true;
|
||||
@@ -3168,30 +3064,7 @@ namespace winrt::TerminalApp::implementation
|
||||
// This will end up calling ConptyConnection::WriteInput which calls WriteFile which may block for
|
||||
// an indefinite amount of time. Avoid freezes and deadlocks by running this on a background thread.
|
||||
assert(!dispatcher.HasThreadAccess());
|
||||
eventArgs.HandleClipboardData(text);
|
||||
|
||||
// GH#18821: If broadcast input is active, paste the same text into all other
|
||||
// panes on the tab. We do this here (rather than re-reading the
|
||||
// clipboard per-pane) so that only one paste warning is shown.
|
||||
co_await wil::resume_foreground(dispatcher);
|
||||
if (const auto strongThis = weakThis.get())
|
||||
{
|
||||
if (const auto& tab{ strongThis->_GetFocusedTabImpl() })
|
||||
{
|
||||
if (tab->TabStatus().IsInputBroadcastActive())
|
||||
{
|
||||
tab->GetRootPane()->WalkTree([&](auto&& pane) {
|
||||
if (const auto control = pane->GetTerminalControl())
|
||||
{
|
||||
if (control.ContentId() != sourceId && !control.ReadOnly())
|
||||
{
|
||||
control.RawWriteString(text);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
control.WriteInputString(text, WriteInputStringType::Clipboard);
|
||||
}
|
||||
CATCH_LOG();
|
||||
|
||||
@@ -3546,16 +3419,6 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Paste text from the Windows Clipboard to the focused terminal
|
||||
void TerminalPage::_PasteText()
|
||||
{
|
||||
if (const auto& control{ _GetActiveControl() })
|
||||
{
|
||||
control.PasteTextFromClipboard();
|
||||
}
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - Called when the settings button is clicked. ShellExecutes the settings
|
||||
// file, as to open it in the default editor for .json files. Does this in
|
||||
|
||||
@@ -54,16 +54,6 @@ namespace winrt::TerminalApp::implementation
|
||||
ScrollDown = 1
|
||||
};
|
||||
|
||||
enum class ConfirmCloseDialogKind
|
||||
{
|
||||
Pane,
|
||||
Tab,
|
||||
MultiplePanes,
|
||||
MultipleTabs,
|
||||
Window,
|
||||
CloseAll
|
||||
};
|
||||
|
||||
struct RenameWindowRequestedArgs : RenameWindowRequestedArgsT<RenameWindowRequestedArgs>
|
||||
{
|
||||
WINRT_PROPERTY(winrt::hstring, ProposedName);
|
||||
@@ -178,7 +168,6 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
void OpenSettingsUI();
|
||||
void WindowActivated(const bool activated);
|
||||
bool FocusTab(const winrt::TerminalApp::Tab& tab);
|
||||
|
||||
bool OnDirectKeyEvent(const uint32_t vkey, const uint8_t scanCode, const bool down);
|
||||
|
||||
@@ -203,7 +192,6 @@ namespace winrt::TerminalApp::implementation
|
||||
til::typed_event<IInspectable, IInspectable> IdentifyWindowsRequested;
|
||||
til::typed_event<IInspectable, winrt::TerminalApp::RenameWindowRequestedArgs> RenameWindowRequested;
|
||||
til::typed_event<IInspectable, IInspectable> SummonWindowRequested;
|
||||
til::typed_event<IInspectable, winrt::TerminalApp::Tab> FocusTabRequested;
|
||||
til::typed_event<IInspectable, winrt::Microsoft::Terminal::Control::WindowSizeChangedEventArgs> WindowSizeChanged;
|
||||
|
||||
til::typed_event<IInspectable, IInspectable> OpenSystemMenu;
|
||||
@@ -313,7 +301,8 @@ namespace winrt::TerminalApp::implementation
|
||||
winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::UI::Xaml::Controls::ContentDialogResult> _ShowDialogHelper(const std::wstring_view& name);
|
||||
|
||||
void _ShowAboutDialog();
|
||||
winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::UI::Xaml::Controls::ContentDialogResult> _ShowConfirmCloseDialog(ConfirmCloseDialogKind kind);
|
||||
winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::UI::Xaml::Controls::ContentDialogResult> _ShowQuitDialog();
|
||||
winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::UI::Xaml::Controls::ContentDialogResult> _ShowCloseWarningDialog();
|
||||
winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::UI::Xaml::Controls::ContentDialogResult> _ShowCloseReadOnlyDialog();
|
||||
winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::UI::Xaml::Controls::ContentDialogResult> _ShowMultiLinePasteWarningDialog();
|
||||
winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::UI::Xaml::Controls::ContentDialogResult> _ShowLargePasteWarningDialog();
|
||||
@@ -360,7 +349,7 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
safe_void_coroutine _ExportTab(const Tab& tab, winrt::hstring filepath);
|
||||
|
||||
winrt::Windows::Foundation::IAsyncAction _HandleCloseTabRequested(winrt::TerminalApp::Tab tab, bool skipConfirmClose = false);
|
||||
winrt::Windows::Foundation::IAsyncAction _HandleCloseTabRequested(winrt::TerminalApp::Tab tab);
|
||||
void _CloseTabAtIndex(uint32_t index);
|
||||
void _RemoveTab(const winrt::TerminalApp::Tab& tab);
|
||||
safe_void_coroutine _RemoveTabs(const std::vector<winrt::TerminalApp::Tab> tabs);
|
||||
@@ -411,12 +400,9 @@ namespace winrt::TerminalApp::implementation
|
||||
TerminalApp::Tab _GetTabByTabViewItem(const IInspectable& tabViewItem) const noexcept;
|
||||
|
||||
void _HandleClosePaneRequested(std::shared_ptr<Pane> pane);
|
||||
bool _ShouldWarnOnClose() const;
|
||||
bool _ShouldWarnOnCloseTab(const winrt::com_ptr<Tab>& tab) const;
|
||||
safe_void_coroutine _SetFocusedTab(const winrt::TerminalApp::Tab tab);
|
||||
safe_void_coroutine _CloseFocusedPane();
|
||||
safe_void_coroutine _ClosePanes(weak_ref<Tab> weakTab, std::vector<uint32_t> paneIds);
|
||||
void _CloseRemainingPanes(weak_ref<Tab> weakTab, std::vector<uint32_t> paneIds);
|
||||
void _ClosePanes(weak_ref<Tab> weakTab, std::vector<uint32_t> paneIds);
|
||||
winrt::Windows::Foundation::IAsyncOperation<bool> _PaneConfirmCloseReadOnly(std::shared_ptr<Pane> pane);
|
||||
void _AddPreviouslyClosedPaneOrTab(std::vector<Microsoft::Terminal::Settings::Model::ActionAndArgs>&& args);
|
||||
|
||||
@@ -434,7 +420,7 @@ namespace winrt::TerminalApp::implementation
|
||||
void _SetAcceleratorForMenuItem(Windows::UI::Xaml::Controls::MenuFlyoutItem& menuItem, const winrt::Microsoft::Terminal::Control::KeyChord& keyChord);
|
||||
|
||||
safe_void_coroutine _PasteFromClipboardHandler(const IInspectable sender,
|
||||
const Microsoft::Terminal::Control::PasteFromClipboardEventArgs eventArgs);
|
||||
const IInspectable eventArgs);
|
||||
|
||||
safe_void_coroutine _OpenHyperlinkHandler(const IInspectable sender, const Microsoft::Terminal::Control::OpenHyperlinkEventArgs eventArgs);
|
||||
static bool _IsUriSupported(const winrt::Windows::Foundation::Uri& parsedUri);
|
||||
@@ -585,8 +571,6 @@ namespace winrt::TerminalApp::implementation
|
||||
void _activePaneChanged(winrt::TerminalApp::Tab tab, Windows::Foundation::IInspectable args);
|
||||
safe_void_coroutine _doHandleSuggestions(Microsoft::Terminal::Settings::Model::SuggestionsArgs realArgs);
|
||||
|
||||
void _SendDesktopNotification(const winrt::hstring& tabTitle, const winrt::hstring& body, const winrt::com_ptr<Tab>& tab, const winrt::TerminalApp::IPaneContent& content);
|
||||
|
||||
#pragma region ActionHandlers
|
||||
// These are all defined in AppActionHandlers.cpp
|
||||
#define ON_ALL_ACTIONS(action) DECLARE_ACTION_HANDLER(action);
|
||||
|
||||
@@ -86,12 +86,17 @@
|
||||
Grid.Row="2"
|
||||
x:Load="False" />
|
||||
|
||||
<ContentDialog x:Name="ConfirmCloseDialog"
|
||||
<ContentDialog x:Name="QuitDialog"
|
||||
x:Uid="QuitDialog"
|
||||
Grid.Row="2"
|
||||
x:Load="False"
|
||||
DefaultButton="Primary">
|
||||
<CheckBox x:Uid="DontAskAgainCheckBox" />
|
||||
</ContentDialog>
|
||||
DefaultButton="Primary" />
|
||||
|
||||
<ContentDialog x:Name="CloseAllDialog"
|
||||
x:Uid="CloseAllDialog"
|
||||
Grid.Row="2"
|
||||
x:Load="False"
|
||||
DefaultButton="Primary" />
|
||||
|
||||
<ContentDialog x:Name="CloseReadOnlyDialog"
|
||||
x:Uid="CloseReadOnlyDialog"
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#include "../../types/inc/utils.hpp"
|
||||
|
||||
#include "BellEventArgs.g.cpp"
|
||||
#include "NotificationEventArgs.g.cpp"
|
||||
#include "TerminalPaneContent.g.cpp"
|
||||
|
||||
using namespace winrt::Windows::Foundation;
|
||||
@@ -35,7 +34,6 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
_controlEvents._ConnectionStateChanged = _control.ConnectionStateChanged(winrt::auto_revoke, { this, &TerminalPaneContent::_controlConnectionStateChangedHandler });
|
||||
_controlEvents._WarningBell = _control.WarningBell(winrt::auto_revoke, { get_weak(), &TerminalPaneContent::_controlWarningBellHandler });
|
||||
_controlEvents._PromptStarted = _control.PromptStarted(winrt::auto_revoke, { get_weak(), &TerminalPaneContent::_controlPromptStartedHandler });
|
||||
_controlEvents._CloseTerminalRequested = _control.CloseTerminalRequested(winrt::auto_revoke, { get_weak(), &TerminalPaneContent::_closeTerminalRequestedHandler });
|
||||
_controlEvents._RestartTerminalRequested = _control.RestartTerminalRequested(winrt::auto_revoke, { get_weak(), &TerminalPaneContent::_restartTerminalRequestedHandler });
|
||||
|
||||
@@ -44,8 +42,6 @@ namespace winrt::TerminalApp::implementation
|
||||
_controlEvents._SetTaskbarProgress = _control.SetTaskbarProgress(winrt::auto_revoke, { get_weak(), &TerminalPaneContent::_controlSetTaskbarProgress });
|
||||
_controlEvents._ReadOnlyChanged = _control.ReadOnlyChanged(winrt::auto_revoke, { get_weak(), &TerminalPaneContent::_controlReadOnlyChanged });
|
||||
_controlEvents._FocusFollowMouseRequested = _control.FocusFollowMouseRequested(winrt::auto_revoke, { get_weak(), &TerminalPaneContent::_controlFocusFollowMouseRequested });
|
||||
_controlEvents._OutputStarted = _control.OutputStarted(winrt::auto_revoke, { get_weak(), &TerminalPaneContent::_controlOutputStartedHandler });
|
||||
_controlEvents._OutputBurstEnded = _control.OutputIdle(winrt::auto_revoke, { get_weak(), &TerminalPaneContent::_controlOutputBurstEndedHandler });
|
||||
}
|
||||
void TerminalPaneContent::_removeControlEvents()
|
||||
{
|
||||
@@ -177,16 +173,6 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
TaskbarProgressChanged.raise(*this, nullptr);
|
||||
}
|
||||
|
||||
winrt::Microsoft::Terminal::Control::TaskbarState TerminalPaneContent::TaskbarState()
|
||||
{
|
||||
return _control.TaskbarState();
|
||||
}
|
||||
|
||||
uint64_t TerminalPaneContent::TaskbarProgress()
|
||||
{
|
||||
return _control.TaskbarProgress();
|
||||
}
|
||||
void TerminalPaneContent::_controlReadOnlyChanged(const IInspectable&, const IInspectable&)
|
||||
{
|
||||
ReadOnlyChanged.raise(*this, nullptr);
|
||||
@@ -275,25 +261,6 @@ namespace winrt::TerminalApp::implementation
|
||||
// has the 'visual' flag set
|
||||
// Arguments:
|
||||
// - <unused>
|
||||
void TerminalPaneContent::PlayNotificationSound()
|
||||
{
|
||||
if (_profile)
|
||||
{
|
||||
auto sounds{ _profile.BellSound() };
|
||||
if (sounds && sounds.Size() > 0)
|
||||
{
|
||||
winrt::hstring soundPath{ sounds.GetAt(rand() % sounds.Size()).Resolved() };
|
||||
winrt::Windows::Foundation::Uri uri{ soundPath };
|
||||
_playBellSound(uri);
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto soundAlias = reinterpret_cast<LPCTSTR>(SND_ALIAS_SYSTEMHAND);
|
||||
PlaySound(soundAlias, NULL, SND_ALIAS_ID | SND_ASYNC | SND_SENTRY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TerminalPaneContent::_controlWarningBellHandler(const winrt::Windows::Foundation::IInspectable& /*sender*/,
|
||||
const winrt::Windows::Foundation::IInspectable& /*eventArgs*/)
|
||||
{
|
||||
@@ -305,7 +272,18 @@ namespace winrt::TerminalApp::implementation
|
||||
if (WI_IsFlagSet(_profile.BellStyle(), winrt::Microsoft::Terminal::Settings::Model::BellStyle::Audible))
|
||||
{
|
||||
// Audible is set, play the sound
|
||||
PlayNotificationSound();
|
||||
auto sounds{ _profile.BellSound() };
|
||||
if (sounds && sounds.Size() > 0)
|
||||
{
|
||||
winrt::hstring soundPath{ sounds.GetAt(rand() % sounds.Size()).Resolved() };
|
||||
winrt::Windows::Foundation::Uri uri{ soundPath };
|
||||
_playBellSound(uri);
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto soundAlias = reinterpret_cast<LPCTSTR>(SND_ALIAS_SYSTEMHAND);
|
||||
PlaySound(soundAlias, NULL, SND_ALIAS_ID | SND_ASYNC | SND_SENTRY);
|
||||
}
|
||||
}
|
||||
|
||||
if (WI_IsFlagSet(_profile.BellStyle(), winrt::Microsoft::Terminal::Settings::Model::BellStyle::Window))
|
||||
@@ -313,73 +291,9 @@ namespace winrt::TerminalApp::implementation
|
||||
_control.BellLightOn();
|
||||
}
|
||||
|
||||
// raise the event with the bool values corresponding to the taskbar and notification flags
|
||||
// raise the event with the bool value corresponding to the taskbar flag
|
||||
BellRequested.raise(*this,
|
||||
*winrt::make_self<TerminalApp::implementation::BellEventArgs>(
|
||||
WI_IsFlagSet(_profile.BellStyle(), BellStyle::Taskbar),
|
||||
WI_IsFlagSet(_profile.BellStyle(), BellStyle::Notification)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TerminalPaneContent::_controlPromptStartedHandler(const winrt::Windows::Foundation::IInspectable& /*sender*/,
|
||||
const winrt::Windows::Foundation::IInspectable& /*eventArgs*/)
|
||||
{
|
||||
if (_profile)
|
||||
{
|
||||
const auto notifyStyle = _profile.NotifyOnNextPrompt();
|
||||
if (notifyStyle != OutputNotificationStyle::None)
|
||||
{
|
||||
if (const auto thresholdInSeconds = _profile.NotifyOnNextPromptThreshold(); thresholdInSeconds > 0)
|
||||
{
|
||||
if (_lastOutputStartedAt == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (const auto elapsedMs = GetTickCount64() - _lastOutputStartedAt; elapsedMs < (static_cast<uint64_t>(thresholdInSeconds) * 1000))
|
||||
{
|
||||
_lastOutputStartedAt = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
_lastOutputStartedAt = 0;
|
||||
|
||||
NotificationRequested.raise(*this,
|
||||
*winrt::make_self<TerminalApp::implementation::NotificationEventArgs>(notifyStyle, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TerminalPaneContent::_controlOutputStartedHandler(const winrt::Windows::Foundation::IInspectable& /*sender*/,
|
||||
const winrt::Windows::Foundation::IInspectable& /*eventArgs*/)
|
||||
{
|
||||
_lastOutputStartedAt = GetTickCount64();
|
||||
}
|
||||
|
||||
// The underlying TermControl::OutputIdle event is fired on the trailing
|
||||
// edge of a 100ms-debounced output burst (see ControlCore::Initialize).
|
||||
// When "notifyOnActivity" is enabled, we get one event per burst of
|
||||
// output, which naturally coalesces a stream of output into a single notification.
|
||||
void TerminalPaneContent::_controlOutputBurstEndedHandler(const winrt::Windows::Foundation::IInspectable& /*sender*/,
|
||||
const winrt::Windows::Foundation::IInspectable& /*eventArgs*/)
|
||||
{
|
||||
if (_profile)
|
||||
{
|
||||
const auto notifyStyle = _profile.NotifyOnActivity();
|
||||
if (notifyStyle != OutputNotificationStyle::None)
|
||||
{
|
||||
const auto now = GetTickCount64();
|
||||
const auto thresholdSeconds = _profile.NotifyOnActivityThreshold();
|
||||
if (thresholdSeconds > 0 &&
|
||||
_lastActivityNotificationAt != 0 &&
|
||||
(now - _lastActivityNotificationAt) < (static_cast<uint64_t>(thresholdSeconds) * 1000))
|
||||
{
|
||||
return;
|
||||
}
|
||||
_lastActivityNotificationAt = now;
|
||||
|
||||
NotificationRequested.raise(*this,
|
||||
*winrt::make_self<TerminalApp::implementation::NotificationEventArgs>(notifyStyle, false));
|
||||
*winrt::make_self<TerminalApp::implementation::BellEventArgs>(WI_IsFlagSet(_profile.BellStyle(), BellStyle::Taskbar)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#pragma once
|
||||
#include "TerminalPaneContent.g.h"
|
||||
#include "BellEventArgs.g.h"
|
||||
#include "NotificationEventArgs.g.h"
|
||||
#include "BasicPaneEvents.h"
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
@@ -14,23 +13,10 @@ namespace winrt::TerminalApp::implementation
|
||||
struct BellEventArgs : public BellEventArgsT<BellEventArgs>
|
||||
{
|
||||
public:
|
||||
BellEventArgs(bool flashTaskbar, bool sendNotification) :
|
||||
FlashTaskbar(flashTaskbar), SendNotification(sendNotification) {}
|
||||
BellEventArgs(bool flashTaskbar) :
|
||||
FlashTaskbar(flashTaskbar) {}
|
||||
|
||||
til::property<bool> FlashTaskbar;
|
||||
til::property<bool> SendNotification;
|
||||
};
|
||||
|
||||
struct NotificationEventArgs : public NotificationEventArgsT<NotificationEventArgs>
|
||||
{
|
||||
public:
|
||||
NotificationEventArgs(winrt::Microsoft::Terminal::Control::OutputNotificationStyle style, bool alwaysNotify = true, const winrt::hstring& title = {}, const winrt::hstring& body = {}) :
|
||||
Style(style), AlwaysNotify(alwaysNotify), Title(title), Body(body) {}
|
||||
|
||||
til::property<winrt::Microsoft::Terminal::Control::OutputNotificationStyle> Style;
|
||||
til::property<bool> AlwaysNotify;
|
||||
til::property<winrt::hstring> Title;
|
||||
til::property<winrt::hstring> Body;
|
||||
};
|
||||
|
||||
struct TerminalPaneContent : TerminalPaneContentT<TerminalPaneContent>, BasicPaneEvents
|
||||
@@ -50,7 +36,6 @@ namespace winrt::TerminalApp::implementation
|
||||
void UpdateSettings(const winrt::Microsoft::Terminal::Settings::Model::CascadiaSettings& settings);
|
||||
|
||||
void MarkAsDefterm();
|
||||
void PlayNotificationSound();
|
||||
|
||||
winrt::Microsoft::Terminal::Settings::Model::Profile GetProfile() const
|
||||
{
|
||||
@@ -58,8 +43,8 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
|
||||
winrt::hstring Title() { return _control.Title(); }
|
||||
winrt::Microsoft::Terminal::Control::TaskbarState TaskbarState();
|
||||
uint64_t TaskbarProgress();
|
||||
uint64_t TaskbarState() { return _control.TaskbarState(); }
|
||||
uint64_t TaskbarProgress() { return _control.TaskbarProgress(); }
|
||||
bool ReadOnly() { return _control.ReadOnly(); }
|
||||
winrt::hstring Icon() const;
|
||||
Windows::Foundation::IReference<winrt::Windows::UI::Color> TabColor() const noexcept;
|
||||
@@ -82,18 +67,10 @@ namespace winrt::TerminalApp::implementation
|
||||
winrt::Windows::Media::Playback::MediaPlayer _bellPlayer{ nullptr };
|
||||
bool _bellPlayerCreated{ false };
|
||||
|
||||
// Tracks the GetTickCount64() for NotifyOnActivityThreshold
|
||||
// and NotifyOnNextPromptThreshold respectively.
|
||||
uint64_t _lastActivityNotificationAt{ 0 };
|
||||
uint64_t _lastOutputStartedAt{ 0 };
|
||||
|
||||
struct ControlEventTokens
|
||||
{
|
||||
winrt::Microsoft::Terminal::Control::TermControl::ConnectionStateChanged_revoker _ConnectionStateChanged;
|
||||
winrt::Microsoft::Terminal::Control::TermControl::WarningBell_revoker _WarningBell;
|
||||
winrt::Microsoft::Terminal::Control::TermControl::PromptStarted_revoker _PromptStarted;
|
||||
winrt::Microsoft::Terminal::Control::TermControl::OutputStarted_revoker _OutputStarted;
|
||||
winrt::Microsoft::Terminal::Control::TermControl::OutputIdle_revoker _OutputBurstEnded;
|
||||
winrt::Microsoft::Terminal::Control::TermControl::CloseTerminalRequested_revoker _CloseTerminalRequested;
|
||||
winrt::Microsoft::Terminal::Control::TermControl::RestartTerminalRequested_revoker _RestartTerminalRequested;
|
||||
|
||||
@@ -112,9 +89,6 @@ namespace winrt::TerminalApp::implementation
|
||||
safe_void_coroutine _controlConnectionStateChangedHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& /*args*/);
|
||||
void _controlWarningBellHandler(const winrt::Windows::Foundation::IInspectable& sender,
|
||||
const winrt::Windows::Foundation::IInspectable& e);
|
||||
void _controlPromptStartedHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& eventArgs);
|
||||
void _controlOutputStartedHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& eventArgs);
|
||||
void _controlOutputBurstEndedHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& eventArgs);
|
||||
void _controlReadOnlyChangedHandler(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& e);
|
||||
|
||||
void _controlTitleChanged(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args);
|
||||
|
||||
@@ -11,7 +11,6 @@ namespace TerminalApp
|
||||
Microsoft.Terminal.Control.TermControl GetTermControl();
|
||||
|
||||
void MarkAsDefterm();
|
||||
void PlayNotificationSound();
|
||||
|
||||
Microsoft.Terminal.Settings.Model.Profile GetProfile();
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ namespace winrt::TerminalApp::implementation
|
||||
WINRT_OBSERVABLE_PROPERTY(bool, IsProgressRingActive, PropertyChanged.raise);
|
||||
WINRT_OBSERVABLE_PROPERTY(bool, IsProgressRingIndeterminate, PropertyChanged.raise);
|
||||
WINRT_OBSERVABLE_PROPERTY(bool, BellIndicator, PropertyChanged.raise);
|
||||
WINRT_OBSERVABLE_PROPERTY(bool, ActivityIndicator, PropertyChanged.raise);
|
||||
WINRT_OBSERVABLE_PROPERTY(bool, IsReadOnlyActive, PropertyChanged.raise);
|
||||
WINRT_OBSERVABLE_PROPERTY(uint32_t, ProgressValue, PropertyChanged.raise);
|
||||
WINRT_OBSERVABLE_PROPERTY(bool, IsInputBroadcastActive, PropertyChanged.raise);
|
||||
|
||||
@@ -12,7 +12,6 @@ namespace TerminalApp
|
||||
Boolean IsProgressRingActive { get; set; };
|
||||
Boolean IsProgressRingIndeterminate { get; set; };
|
||||
Boolean BellIndicator { get; set; };
|
||||
Boolean ActivityIndicator { get; set; };
|
||||
UInt32 ProgressValue { get; set; };
|
||||
Boolean IsReadOnlyActive { get; set; };
|
||||
Boolean IsInputBroadcastActive { get; set; };
|
||||
|
||||
@@ -1205,15 +1205,6 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
}
|
||||
|
||||
bool TerminalWindow::FocusTab(const winrt::TerminalApp::Tab& tab)
|
||||
{
|
||||
if (_root)
|
||||
{
|
||||
return _root->FocusTab(tab);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void TerminalWindow::WindowName(const winrt::hstring& name)
|
||||
{
|
||||
const auto oldIsQuakeMode = _WindowProperties->IsQuakeWindow();
|
||||
|
||||
@@ -92,7 +92,6 @@ namespace winrt::TerminalApp::implementation
|
||||
bool ShowTabsFullscreen() const;
|
||||
bool AutoHideWindow();
|
||||
void IdentifyWindow();
|
||||
bool FocusTab(const winrt::TerminalApp::Tab& tab);
|
||||
|
||||
std::optional<uint32_t> LoadPersistedLayoutIdx() const;
|
||||
winrt::Microsoft::Terminal::Settings::Model::WindowLayout LoadPersistedLayout();
|
||||
@@ -222,7 +221,6 @@ namespace winrt::TerminalApp::implementation
|
||||
FORWARDED_TYPED_EVENT(SetTaskbarProgress, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, _root, SetTaskbarProgress);
|
||||
FORWARDED_TYPED_EVENT(IdentifyWindowsRequested, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, IdentifyWindowsRequested);
|
||||
FORWARDED_TYPED_EVENT(SummonWindowRequested, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, SummonWindowRequested);
|
||||
FORWARDED_TYPED_EVENT(FocusTabRequested, Windows::Foundation::IInspectable, winrt::TerminalApp::Tab, _root, FocusTabRequested);
|
||||
FORWARDED_TYPED_EVENT(OpenSystemMenu, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, OpenSystemMenu);
|
||||
FORWARDED_TYPED_EVENT(QuitRequested, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, QuitRequested);
|
||||
FORWARDED_TYPED_EVENT(ShowWindowChanged, Windows::Foundation::IInspectable, winrt::Microsoft::Terminal::Control::ShowWindowArgs, _root, ShowWindowChanged);
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
import "IPaneContent.idl";
|
||||
import "TerminalPage.idl";
|
||||
import "ShortcutActionDispatch.idl";
|
||||
import "Tab.idl";
|
||||
|
||||
namespace TerminalApp
|
||||
{
|
||||
@@ -75,7 +74,6 @@ namespace TerminalApp
|
||||
Boolean ShowTabsFullscreen { get; };
|
||||
|
||||
void IdentifyWindow();
|
||||
Boolean FocusTab(TerminalApp.Tab tab);
|
||||
void SetPersistedLayoutIdx(UInt32 idx);
|
||||
void RequestExitFullscreen();
|
||||
|
||||
@@ -128,7 +126,6 @@ namespace TerminalApp
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> IdentifyWindowsRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> IsQuakeWindowChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> SummonWindowRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, TerminalApp.Tab> FocusTabRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> OpenSystemMenu;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> QuitRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, TerminalApp.SystemMenuChangeArgs> SystemMenuChangeRequested;
|
||||
|
||||
@@ -54,9 +54,6 @@
|
||||
#include <winrt/Windows.Media.Playback.h>
|
||||
#include <winrt/Windows.Management.Deployment.h>
|
||||
|
||||
#include <winrt/Windows.UI.Notifications.h>
|
||||
#include <winrt/Windows.Data.Xml.Dom.h>
|
||||
|
||||
#include <winrt/Microsoft.UI.Xaml.Controls.h>
|
||||
#include <winrt/Microsoft.UI.Xaml.Controls.Primitives.h>
|
||||
#include <winrt/Microsoft.UI.Xaml.XamlTypeInfo.h>
|
||||
|
||||
@@ -139,12 +139,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
auto pfnSearchMissingCommand = [this](auto&& PH1, auto&& PH2) { _terminalSearchMissingCommand(std::forward<decltype(PH1)>(PH1), std::forward<decltype(PH2)>(PH2)); };
|
||||
_terminal->SetSearchMissingCommandCallback(pfnSearchMissingCommand);
|
||||
|
||||
auto pfnPromptStarted = [this] { _terminalPromptStarted(); };
|
||||
_terminal->SetPromptStartedCallback(pfnPromptStarted);
|
||||
|
||||
auto pfnOutputStarted = [this] { _terminalOutputStarted(); };
|
||||
_terminal->SetOutputStartedCallback(pfnOutputStarted);
|
||||
|
||||
auto pfnClearQuickFix = [this] { ClearQuickFix(); };
|
||||
_terminal->SetClearQuickFixCallback(pfnClearQuickFix);
|
||||
|
||||
@@ -504,7 +498,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
// - wstr: the string of characters to write to the terminal connection.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void ControlCore::SendInput(const std::wstring_view wstr)
|
||||
void ControlCore::_sendInput(const std::wstring_view wstr)
|
||||
{
|
||||
if (wstr.empty())
|
||||
{
|
||||
@@ -560,7 +554,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
}
|
||||
if (out)
|
||||
{
|
||||
SendInput(*out);
|
||||
_sendInput(*out);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -718,7 +712,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
}
|
||||
if (out)
|
||||
{
|
||||
SendInput(*out);
|
||||
_sendInput(*out);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -737,7 +731,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
}
|
||||
if (out)
|
||||
{
|
||||
SendInput(*out);
|
||||
_sendInput(*out);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -919,17 +913,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
_hasUnfocusedAppearance = static_cast<bool>(newAppearance);
|
||||
_unfocusedAppearance = _hasUnfocusedAppearance ? newAppearance : settings;
|
||||
|
||||
// Cache the auto-detect setting in an atomic so the off-thread output/prompt
|
||||
// callbacks can read it without synchronizing with _settings. If the effective
|
||||
// taskbar state changes (because a command is currently active and the setting
|
||||
// toggled), notify listeners.
|
||||
const auto nowEnabled = _settings.AutoDetectRunningCommand();
|
||||
const auto wasEnabled = _autoDetectCommandActivity.exchange(nowEnabled, std::memory_order_relaxed);
|
||||
if (wasEnabled != nowEnabled && _commandActive.load(std::memory_order_relaxed))
|
||||
{
|
||||
TaskbarProgressChanged.raise(*this, nullptr);
|
||||
}
|
||||
|
||||
const auto lock = _terminal->LockForWriting();
|
||||
|
||||
_builtinGlyphs = _settings.EnableBuiltinGlyphs();
|
||||
@@ -1468,24 +1451,34 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
// Method Description:
|
||||
// - Pre-process text pasted (presumably from the clipboard)
|
||||
// before sending it over the terminal's connection.
|
||||
void ControlCore::PasteText(const winrt::hstring& hstr)
|
||||
void ControlCore::WriteInputString(const std::wstring_view& str, WriteInputStringType type)
|
||||
{
|
||||
using namespace ::Microsoft::Console::Utils;
|
||||
|
||||
auto filtered = FilterStringForPaste(hstr, CarriageReturnNewline | ControlCodes);
|
||||
if (BracketedPasteEnabled())
|
||||
switch (type)
|
||||
{
|
||||
filtered.insert(0, L"\x1b[200~");
|
||||
filtered.append(L"\x1b[201~");
|
||||
case WriteInputStringType::Clipboard:
|
||||
{
|
||||
using namespace ::Microsoft::Console::Utils;
|
||||
|
||||
auto filtered = FilterStringForPaste(str, CarriageReturnNewline | ControlCodes);
|
||||
if (BracketedPasteEnabled())
|
||||
{
|
||||
filtered.insert(0, L"\x1b[200~");
|
||||
filtered.append(L"\x1b[201~");
|
||||
}
|
||||
|
||||
// It's important to not hold the terminal lock while calling this function as sending the data may take a long time.
|
||||
_sendInput(filtered);
|
||||
|
||||
const auto lock = _terminal->LockForWriting();
|
||||
_terminal->ClearSelection();
|
||||
_updateSelectionUI();
|
||||
_terminal->TrySnapOnInput();
|
||||
return;
|
||||
}
|
||||
case WriteInputStringType::Raw:
|
||||
_sendInput(str);
|
||||
return;
|
||||
}
|
||||
|
||||
// It's important to not hold the terminal lock while calling this function as sending the data may take a long time.
|
||||
SendInput(filtered);
|
||||
|
||||
const auto lock = _terminal->LockForWriting();
|
||||
_terminal->ClearSelection();
|
||||
_updateSelectionUI();
|
||||
_terminal->TrySnapOnInput();
|
||||
}
|
||||
|
||||
FontInfo ControlCore::GetFont() const
|
||||
@@ -1564,17 +1557,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
// - Gets the internal taskbar state value
|
||||
// Return Value:
|
||||
// - The taskbar state of this control
|
||||
const Control::TaskbarState ControlCore::TaskbarState() const noexcept
|
||||
const size_t ControlCore::TaskbarState() const noexcept
|
||||
{
|
||||
const auto lock = _terminal->LockForReading();
|
||||
const auto vtState = static_cast<Control::TaskbarState>(_terminal->GetTaskbarState());
|
||||
if (vtState == Control::TaskbarState::Clear &&
|
||||
_autoDetectCommandActivity.load(std::memory_order_relaxed) &&
|
||||
_commandActive.load(std::memory_order_relaxed))
|
||||
{
|
||||
return Control::TaskbarState::Indeterminate;
|
||||
}
|
||||
return vtState;
|
||||
return _terminal->GetTaskbarState();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
@@ -1623,26 +1609,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
WarningBell.raise(*this, nullptr);
|
||||
}
|
||||
|
||||
void ControlCore::_terminalPromptStarted()
|
||||
{
|
||||
if (_commandActive.exchange(false, std::memory_order_relaxed) &&
|
||||
_autoDetectCommandActivity.load(std::memory_order_relaxed))
|
||||
{
|
||||
TaskbarProgressChanged.raise(*this, nullptr);
|
||||
}
|
||||
PromptStarted.raise(*this, nullptr);
|
||||
}
|
||||
|
||||
void ControlCore::_terminalOutputStarted()
|
||||
{
|
||||
if (!_commandActive.exchange(true, std::memory_order_relaxed) &&
|
||||
_autoDetectCommandActivity.load(std::memory_order_relaxed))
|
||||
{
|
||||
TaskbarProgressChanged.raise(*this, nullptr);
|
||||
}
|
||||
OutputStarted.raise(*this, nullptr);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Called for the Terminal's TitleChanged callback. This will re-raise
|
||||
// a new winrt TypedEvent that can be listened to.
|
||||
@@ -2241,7 +2207,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
// Sending input requires that we're unlocked, because
|
||||
// writing the input pipe may block indefinitely.
|
||||
const auto suspension = _terminal->SuspendLock();
|
||||
SendInput(buffer);
|
||||
_sendInput(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,8 +122,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
til::color ForegroundColor() const;
|
||||
til::color BackgroundColor() const;
|
||||
|
||||
void SendInput(std::wstring_view wstr);
|
||||
void PasteText(const winrt::hstring& hstr);
|
||||
void WriteInputString(const std::wstring_view& str, WriteInputStringType type);
|
||||
bool CopySelectionToClipboard(bool singleLine, bool withControlSequences, const CopyFormat formats);
|
||||
void SelectAll();
|
||||
void ClearSelection();
|
||||
@@ -161,7 +160,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
void OpenCWD();
|
||||
|
||||
#pragma region ICoreState
|
||||
const Control::TaskbarState TaskbarState() const noexcept;
|
||||
const size_t TaskbarState() const noexcept;
|
||||
const size_t TaskbarProgress() const noexcept;
|
||||
|
||||
hstring Title();
|
||||
@@ -275,8 +274,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
til::typed_event<IInspectable, Control::TitleChangedEventArgs> TitleChanged;
|
||||
til::typed_event<IInspectable, Control::WriteToClipboardEventArgs> WriteToClipboard;
|
||||
til::typed_event<> WarningBell;
|
||||
til::typed_event<> PromptStarted;
|
||||
til::typed_event<> OutputStarted;
|
||||
til::typed_event<> TabColorChanged;
|
||||
til::typed_event<> BackgroundColorChanged;
|
||||
til::typed_event<IInspectable, Control::ScrollPositionChangedArgs> ScrollPositionChanged;
|
||||
@@ -322,11 +319,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
|
||||
void _handleControlC();
|
||||
void _sendInputToConnection(std::wstring_view wstr);
|
||||
void _sendInput(std::wstring_view wstr);
|
||||
|
||||
#pragma region TerminalCoreCallbacks
|
||||
void _terminalWarningBell();
|
||||
void _terminalPromptStarted();
|
||||
void _terminalOutputStarted();
|
||||
void _terminalTitleChanged(std::wstring_view wstr);
|
||||
void _terminalScrollPositionChanged(const int viewTop,
|
||||
const int viewHeight,
|
||||
@@ -423,8 +419,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
std::optional<til::point> _lastHoveredCell;
|
||||
uint16_t _lastHoveredId{ 0 };
|
||||
std::atomic<bool> _initializedTerminal{ false };
|
||||
std::atomic<bool> _autoDetectCommandActivity{ false };
|
||||
std::atomic<bool> _commandActive{ false };
|
||||
bool _isReadOnly{ false };
|
||||
bool _closing{ false };
|
||||
|
||||
|
||||
@@ -68,6 +68,14 @@ namespace Microsoft.Terminal.Control
|
||||
Boolean SearchRegexInvalid;
|
||||
};
|
||||
|
||||
enum WriteInputStringType
|
||||
{
|
||||
// Text which is to be passed through unmodified.
|
||||
Raw,
|
||||
// Text which is to be treated as clipboard input, stripped and formatted according to the application's wishes.
|
||||
Clipboard,
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass SelectionColor
|
||||
{
|
||||
SelectionColor();
|
||||
@@ -128,8 +136,7 @@ namespace Microsoft.Terminal.Control
|
||||
Boolean SendCharEvent(Char ch,
|
||||
Int16 scanCode,
|
||||
Microsoft.Terminal.Core.ControlKeyStates modifiers);
|
||||
void SendInput(String text);
|
||||
void PasteText(String text);
|
||||
void WriteInputString(String text, WriteInputStringType type);
|
||||
void SelectAll();
|
||||
void ClearSelection();
|
||||
Boolean ToggleBlockSelection();
|
||||
@@ -192,8 +199,6 @@ namespace Microsoft.Terminal.Control
|
||||
event Windows.Foundation.TypedEventHandler<Object, TitleChangedEventArgs> TitleChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, WriteToClipboardEventArgs> WriteToClipboard;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> WarningBell;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> PromptStarted;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> OutputStarted;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> TabColorChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> BackgroundColorChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> TaskbarProgressChanged;
|
||||
|
||||
@@ -242,14 +242,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
// - Initiate a paste operation.
|
||||
void ControlInteractivity::RequestPasteTextFromClipboard()
|
||||
{
|
||||
auto args = winrt::make<PasteFromClipboardEventArgs>(
|
||||
[core = _core](const winrt::hstring& wstr) {
|
||||
core->PasteText(wstr);
|
||||
},
|
||||
_core->BracketedPasteEnabled());
|
||||
|
||||
// send paste event up to TermApp
|
||||
PasteFromClipboard.raise(*this, std::move(args));
|
||||
PasteFromClipboard.raise(*this, nullptr);
|
||||
}
|
||||
|
||||
void ControlInteractivity::PointerPressed(const uint32_t /*pointerId*/,
|
||||
@@ -309,10 +303,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
const auto isOnOriginalPosition = _lastMouseClickPosNoSelection == pixelPosition;
|
||||
|
||||
// Rounded coordinates for text selection.
|
||||
// Don't round in VT mouse mode; cell-level precision matters more.
|
||||
// Only round for single-click: for double/triple-click, rounding
|
||||
// can push the position to the next cell, selecting the wrong word.
|
||||
const auto round = multiClickMapper == 1 && !_core->IsVtMouseModeEnabled();
|
||||
// Don't round in VT mouse mode; cell-level precision matters more
|
||||
const auto round = !_core->IsVtMouseModeEnabled();
|
||||
_core->LeftClickOnTerminal(_getTerminalPosition(til::point{ pixelPosition }, round),
|
||||
multiClickMapper,
|
||||
altEnabled,
|
||||
|
||||
@@ -92,7 +92,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
void AttachToNewControl();
|
||||
|
||||
til::typed_event<IInspectable, Control::OpenHyperlinkEventArgs> OpenHyperlink;
|
||||
til::typed_event<IInspectable, Control::PasteFromClipboardEventArgs> PasteFromClipboard;
|
||||
til::typed_event<IInspectable, IInspectable> PasteFromClipboard;
|
||||
til::typed_event<IInspectable, Control::ScrollPositionChangedArgs> ScrollPositionChanged;
|
||||
til::typed_event<IInspectable, Control::ContextMenuRequestedEventArgs> ContextMenuRequested;
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ namespace Microsoft.Terminal.Control
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<Object, OpenHyperlinkEventArgs> OpenHyperlink;
|
||||
event Windows.Foundation.TypedEventHandler<Object, ScrollPositionChangedArgs> ScrollPositionChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, PasteFromClipboardEventArgs> PasteFromClipboard;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> PasteFromClipboard;
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> Closed;
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include "TitleChangedEventArgs.g.cpp"
|
||||
#include "ContextMenuRequestedEventArgs.g.cpp"
|
||||
#include "WriteToClipboardEventArgs.g.cpp"
|
||||
#include "PasteFromClipboardEventArgs.g.cpp"
|
||||
#include "OpenHyperlinkEventArgs.g.cpp"
|
||||
#include "NoticeEventArgs.g.cpp"
|
||||
#include "ScrollPositionChangedArgs.g.cpp"
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include "TitleChangedEventArgs.g.h"
|
||||
#include "ContextMenuRequestedEventArgs.g.h"
|
||||
#include "WriteToClipboardEventArgs.g.h"
|
||||
#include "PasteFromClipboardEventArgs.g.h"
|
||||
#include "OpenHyperlinkEventArgs.g.h"
|
||||
#include "NoticeEventArgs.g.h"
|
||||
#include "ScrollPositionChangedArgs.g.h"
|
||||
@@ -83,24 +82,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
std::string _rtf;
|
||||
};
|
||||
|
||||
struct PasteFromClipboardEventArgs : public PasteFromClipboardEventArgsT<PasteFromClipboardEventArgs>
|
||||
{
|
||||
public:
|
||||
PasteFromClipboardEventArgs(std::function<void(const hstring&)> clipboardDataHandler, bool bracketedPasteEnabled) :
|
||||
m_clipboardDataHandler(clipboardDataHandler),
|
||||
_BracketedPasteEnabled{ bracketedPasteEnabled } {}
|
||||
|
||||
void HandleClipboardData(hstring value)
|
||||
{
|
||||
m_clipboardDataHandler(value);
|
||||
};
|
||||
|
||||
WINRT_PROPERTY(bool, BracketedPasteEnabled, false);
|
||||
|
||||
private:
|
||||
std::function<void(const hstring&)> m_clipboardDataHandler;
|
||||
};
|
||||
|
||||
struct OpenHyperlinkEventArgs : public OpenHyperlinkEventArgsT<OpenHyperlinkEventArgs>
|
||||
{
|
||||
public:
|
||||
@@ -235,10 +216,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
struct StringSentEventArgs : public StringSentEventArgsT<StringSentEventArgs>
|
||||
{
|
||||
public:
|
||||
StringSentEventArgs(const winrt::hstring& text) :
|
||||
_Text(text) {}
|
||||
StringSentEventArgs(const winrt::hstring& text, uint32_t type) :
|
||||
_Text(text), _Type(type) {}
|
||||
|
||||
WINRT_PROPERTY(winrt::hstring, Text);
|
||||
WINRT_PROPERTY(uint32_t, Type);
|
||||
};
|
||||
|
||||
struct SearchMissingCommandEventArgs : public SearchMissingCommandEventArgsT<SearchMissingCommandEventArgs>
|
||||
|
||||
@@ -68,12 +68,6 @@ namespace Microsoft.Terminal.Control
|
||||
byte[] Rtf { get; }; // UTF-8, as required by "Rich Text Format"
|
||||
}
|
||||
|
||||
runtimeclass PasteFromClipboardEventArgs
|
||||
{
|
||||
void HandleClipboardData(String data);
|
||||
Boolean BracketedPasteEnabled { get; };
|
||||
}
|
||||
|
||||
runtimeclass OpenHyperlinkEventArgs
|
||||
{
|
||||
OpenHyperlinkEventArgs(String uri);
|
||||
@@ -152,6 +146,7 @@ namespace Microsoft.Terminal.Control
|
||||
runtimeclass StringSentEventArgs
|
||||
{
|
||||
String Text { get; };
|
||||
UInt32 Type { get; }; // We cannot forward-declare WriteInputStringType, and as of GH#20164 this whole event is getting deleted anyway.
|
||||
}
|
||||
|
||||
runtimeclass SearchMissingCommandEventArgs
|
||||
|
||||
@@ -29,30 +29,6 @@ namespace Microsoft.Terminal.Control
|
||||
MinGW,
|
||||
};
|
||||
|
||||
[flags]
|
||||
enum OutputNotificationStyle
|
||||
{
|
||||
None = 0,
|
||||
Taskbar = 0x1,
|
||||
Audible = 0x2,
|
||||
Tab = 0x4,
|
||||
Notification = 0x8,
|
||||
All = 0xffffffff
|
||||
};
|
||||
|
||||
// Mirrors Microsoft::Console::VirtualTerminal::DispatchTypes::TaskbarState
|
||||
// (which is shared with conhost and lives outside the WinRT projection).
|
||||
// Values must remain numerically identical so the conversion at the
|
||||
// ControlCore boundary is a 1:1 cast.
|
||||
enum TaskbarState
|
||||
{
|
||||
Clear = 0,
|
||||
Set = 1,
|
||||
Error = 2,
|
||||
Indeterminate = 3,
|
||||
Paused = 4,
|
||||
};
|
||||
|
||||
// Class Description:
|
||||
// TerminalSettings encapsulates all settings that control the
|
||||
// TermControl's behavior. In these settings there is both the entirety
|
||||
@@ -102,12 +78,6 @@ namespace Microsoft.Terminal.Control
|
||||
PathTranslationStyle PathTranslationStyle { get; };
|
||||
String DragDropDelimiter { get; };
|
||||
|
||||
OutputNotificationStyle NotifyOnActivity { get; };
|
||||
OutputNotificationStyle NotifyOnNextPrompt { get; };
|
||||
Int32 NotifyOnActivityThreshold { get; };
|
||||
Int32 NotifyOnNextPromptThreshold { get; };
|
||||
Boolean AutoDetectRunningCommand { get; };
|
||||
|
||||
// NOTE! When adding something here, make sure to update ControlProperties.h too!
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import "IControlSettings.idl";
|
||||
|
||||
namespace Microsoft.Terminal.Control
|
||||
{
|
||||
enum MarkCategory
|
||||
@@ -33,7 +31,7 @@ namespace Microsoft.Terminal.Control
|
||||
interface ICoreState
|
||||
{
|
||||
String Title { get; };
|
||||
Microsoft.Terminal.Control.TaskbarState TaskbarState { get; };
|
||||
UInt64 TaskbarState { get; };
|
||||
UInt64 TaskbarProgress { get; };
|
||||
|
||||
String WorkingDirectory { get; };
|
||||
|
||||
@@ -238,7 +238,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
{
|
||||
return;
|
||||
}
|
||||
core->SendInput(text);
|
||||
core->WriteInputString(text, WriteInputStringType::Raw);
|
||||
}
|
||||
|
||||
::Microsoft::Console::Render::Renderer* TsfDataProvider::GetRenderer()
|
||||
@@ -393,8 +393,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
// attached content before we set up the throttled func, and that'll A/V
|
||||
_revokers.coreScrollPositionChanged = _core.ScrollPositionChanged(winrt::auto_revoke, { get_weak(), &TermControl::_ScrollPositionChanged });
|
||||
_revokers.WarningBell = _core.WarningBell(winrt::auto_revoke, { get_weak(), &TermControl::_coreWarningBell });
|
||||
_revokers.PromptStarted = _core.PromptStarted(winrt::auto_revoke, { get_weak(), &TermControl::_corePromptStarted });
|
||||
_revokers.OutputStarted = _core.OutputStarted(winrt::auto_revoke, { get_weak(), &TermControl::_coreOutputStarted });
|
||||
|
||||
static constexpr auto AutoScrollUpdateInterval = std::chrono::microseconds(static_cast<int>(1.0 / 30.0 * 1000000));
|
||||
_autoScrollTimer.Interval(AutoScrollUpdateInterval);
|
||||
@@ -914,19 +912,25 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
// - wstr: the string of characters to write to the terminal connection.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void TermControl::SendInput(const winrt::hstring& wstr)
|
||||
void TermControl::WriteInputString(const winrt::hstring& wstr, WriteInputStringType type)
|
||||
{
|
||||
// Dismiss any previewed input.
|
||||
PreviewInput(hstring{});
|
||||
WriteInputStringWithoutBroadcast(wstr, type);
|
||||
|
||||
// only broadcast if there's an actual listener. Saves the overhead of some object creation.
|
||||
if (StringSent)
|
||||
{
|
||||
StringSent.raise(*this, winrt::make<StringSentEventArgs>(wstr));
|
||||
StringSent.raise(*this, winrt::make<StringSentEventArgs>(wstr, static_cast<uint32_t>(type)));
|
||||
}
|
||||
|
||||
RawWriteString(wstr);
|
||||
}
|
||||
|
||||
void TermControl::WriteInputStringWithoutBroadcast(const winrt::hstring& wstr, WriteInputStringType type)
|
||||
{
|
||||
// Dismiss any previewed input.
|
||||
PreviewInput(hstring{});
|
||||
|
||||
_core.WriteInputString(wstr, type);
|
||||
}
|
||||
|
||||
void TermControl::ClearBuffer(Control::ClearBufferType clearType)
|
||||
{
|
||||
_core.ClearBuffer(clearType);
|
||||
@@ -1526,11 +1530,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
return _core.SendCharEvent(character, scanCode, modifiers);
|
||||
}
|
||||
|
||||
void TermControl::RawWriteString(const winrt::hstring& text)
|
||||
{
|
||||
_core.SendInput(text);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Manually handles key events for certain keys that can't be passed to us
|
||||
// normally. Namely, the keys we're concerned with are F7 down and Alt up.
|
||||
@@ -1677,7 +1676,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
// If it encounters a string that isn't, cppwinrt will abort().
|
||||
// It should already be null-terminated, but let's make sure to not crash.
|
||||
buf[buf_len] = L'\0';
|
||||
_core.SendInput(std::wstring_view{ &buf[0], buf_len });
|
||||
_core.WriteInputString(std::wstring_view{ &buf[0], buf_len }, WriteInputStringType::Raw);
|
||||
}
|
||||
|
||||
s = {};
|
||||
@@ -3104,7 +3103,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
auto link{ co_await e.DataView().GetApplicationLinkAsync() };
|
||||
if (const auto strong = weak.get())
|
||||
{
|
||||
_pasteTextWithBroadcast(link.AbsoluteUri());
|
||||
WriteInputString(link.AbsoluteUri(), WriteInputStringType::Clipboard);
|
||||
}
|
||||
}
|
||||
CATCH_LOG();
|
||||
@@ -3116,7 +3115,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
auto link{ co_await e.DataView().GetWebLinkAsync() };
|
||||
if (const auto strong = weak.get())
|
||||
{
|
||||
_pasteTextWithBroadcast(link.AbsoluteUri());
|
||||
WriteInputString(link.AbsoluteUri(), WriteInputStringType::Clipboard);
|
||||
}
|
||||
}
|
||||
CATCH_LOG();
|
||||
@@ -3128,7 +3127,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
auto text{ co_await e.DataView().GetTextAsync() };
|
||||
if (const auto strong = weak.get())
|
||||
{
|
||||
_pasteTextWithBroadcast(text);
|
||||
WriteInputString(text, WriteInputStringType::Clipboard);
|
||||
}
|
||||
}
|
||||
CATCH_LOG();
|
||||
@@ -3226,27 +3225,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
}
|
||||
}
|
||||
|
||||
_pasteTextWithBroadcast(winrt::hstring{ allPathsString });
|
||||
WriteInputString(winrt::hstring{ allPathsString }, WriteInputStringType::Clipboard);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Paste this text, and raise a StringSent, to potentially broadcast this
|
||||
// text to other controls in the app. For certain interactions, like
|
||||
// drag/dropping a file, we want to act like we "pasted" the text (even if
|
||||
// the text didn't come from the clipboard). This lets those interactions
|
||||
// broadcast as well.
|
||||
void TermControl::_pasteTextWithBroadcast(const winrt::hstring& text)
|
||||
{
|
||||
// only broadcast if there's an actual listener. Saves the overhead of some object creation.
|
||||
if (StringSent)
|
||||
{
|
||||
StringSent.raise(*this, winrt::make<StringSentEventArgs>(text));
|
||||
}
|
||||
_core.PasteText(text);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Handle the DragOver event. We'll signal that the drag operation we
|
||||
// support is the "copy" operation, and we'll also customize the
|
||||
@@ -3358,7 +3341,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
// - Gets the internal taskbar state value
|
||||
// Return Value:
|
||||
// - The taskbar state of this control
|
||||
const Control::TaskbarState TermControl::TaskbarState() const noexcept
|
||||
const uint64_t TermControl::TaskbarState() const noexcept
|
||||
{
|
||||
return _core.TaskbarState();
|
||||
}
|
||||
@@ -3728,16 +3711,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
_playWarningBell->Run();
|
||||
}
|
||||
|
||||
void TermControl::_corePromptStarted(const IInspectable& /*sender*/, const IInspectable& /*args*/)
|
||||
{
|
||||
PromptStarted.raise(*this, nullptr);
|
||||
}
|
||||
|
||||
void TermControl::_coreOutputStarted(const IInspectable& /*sender*/, const IInspectable& /*args*/)
|
||||
{
|
||||
OutputStarted.raise(*this, nullptr);
|
||||
}
|
||||
|
||||
hstring TermControl::ReadEntireBuffer() const
|
||||
{
|
||||
return _core.ReadEntireBuffer();
|
||||
@@ -3855,7 +3828,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
void TermControl::_coreOutputIdle(const IInspectable& /*sender*/, const IInspectable& /*args*/)
|
||||
{
|
||||
_refreshSearch();
|
||||
OutputIdle.raise(*this, nullptr);
|
||||
}
|
||||
|
||||
void TermControl::OwningHwnd(uint64_t owner)
|
||||
|
||||
@@ -86,7 +86,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
void ColorSelection(Control::SelectionColor fg, Control::SelectionColor bg, Core::MatchMode matchMode);
|
||||
|
||||
#pragma region ICoreState
|
||||
const Control::TaskbarState TaskbarState() const noexcept;
|
||||
const uint64_t TaskbarState() const noexcept;
|
||||
const uint64_t TaskbarProgress() const noexcept;
|
||||
|
||||
hstring Title();
|
||||
@@ -125,7 +125,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
void ResetFontSize();
|
||||
winrt::Windows::Foundation::Size GetFontSize() const;
|
||||
|
||||
void SendInput(const winrt::hstring& input);
|
||||
void WriteInputString(const winrt::hstring& wstr, WriteInputStringType type);
|
||||
void WriteInputStringWithoutBroadcast(const winrt::hstring& wstr, WriteInputStringType type);
|
||||
void ClearBuffer(Control::ClearBufferType clearType);
|
||||
|
||||
void ToggleShaderEffects();
|
||||
@@ -179,7 +180,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
|
||||
bool RawWriteKeyEvent(const WORD vkey, const WORD scanCode, const winrt::Microsoft::Terminal::Core::ControlKeyStates modifiers, const bool keyDown);
|
||||
bool RawWriteChar(const wchar_t character, const WORD scanCode, const winrt::Microsoft::Terminal::Core::ControlKeyStates modifiers);
|
||||
void RawWriteString(const winrt::hstring& text);
|
||||
|
||||
void ShowContextMenu();
|
||||
bool OpenQuickFixMenu();
|
||||
@@ -211,9 +211,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
til::typed_event<IInspectable, IInspectable> FocusFollowMouseRequested;
|
||||
til::typed_event<Control::TermControl, Windows::UI::Xaml::RoutedEventArgs> Initialized;
|
||||
til::typed_event<> WarningBell;
|
||||
til::typed_event<> PromptStarted;
|
||||
til::typed_event<> OutputStarted;
|
||||
til::typed_event<> OutputIdle;
|
||||
til::typed_event<IInspectable, Control::KeySentEventArgs> KeySent;
|
||||
til::typed_event<IInspectable, Control::CharSentEventArgs> CharSent;
|
||||
til::typed_event<IInspectable, Control::StringSentEventArgs> StringSent;
|
||||
@@ -232,7 +229,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
BUBBLED_FORWARDED_TYPED_EVENT(CompletionsChanged, IInspectable, Control::CompletionsChangedEventArgs);
|
||||
BUBBLED_FORWARDED_TYPED_EVENT(RestartTerminalRequested, IInspectable, IInspectable);
|
||||
BUBBLED_FORWARDED_TYPED_EVENT(WriteToClipboard, IInspectable, Control::WriteToClipboardEventArgs);
|
||||
BUBBLED_FORWARDED_TYPED_EVENT(PasteFromClipboard, IInspectable, Control::PasteFromClipboardEventArgs);
|
||||
BUBBLED_FORWARDED_TYPED_EVENT(PasteFromClipboard, IInspectable, IInspectable);
|
||||
|
||||
// clang-format on
|
||||
|
||||
@@ -427,15 +424,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
void _coreTransparencyChanged(IInspectable sender, Control::TransparencyChangedEventArgs args);
|
||||
void _coreRaisedNotice(const IInspectable& s, const Control::NoticeEventArgs& args);
|
||||
void _coreWarningBell(const IInspectable& sender, const IInspectable& args);
|
||||
void _corePromptStarted(const IInspectable& sender, const IInspectable& args);
|
||||
void _coreOutputStarted(const IInspectable& sender, const IInspectable& args);
|
||||
void _coreOutputIdle(const IInspectable& sender, const IInspectable& args);
|
||||
|
||||
winrt::Windows::Foundation::Point _toPosInDips(const Core::Point terminalCellPos);
|
||||
void _throttledUpdateScrollbar(const ScrollBarUpdate& update);
|
||||
|
||||
void _pasteTextWithBroadcast(const winrt::hstring& text);
|
||||
|
||||
void _contextMenuHandler(IInspectable sender, Control::ContextMenuRequestedEventArgs args);
|
||||
void _showContextMenuAt(const winrt::Windows::Foundation::Point& controlRelativePos);
|
||||
|
||||
@@ -454,8 +447,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
{
|
||||
Control::ControlCore::ScrollPositionChanged_revoker coreScrollPositionChanged;
|
||||
Control::ControlCore::WarningBell_revoker WarningBell;
|
||||
Control::ControlCore::PromptStarted_revoker PromptStarted;
|
||||
Control::ControlCore::OutputStarted_revoker OutputStarted;
|
||||
Control::ControlCore::RendererEnteredErrorState_revoker RendererEnteredErrorState;
|
||||
Control::ControlCore::BackgroundColorChanged_revoker BackgroundColorChanged;
|
||||
Control::ControlCore::FontSizeChanged_revoker FontSizeChanged;
|
||||
|
||||
@@ -64,14 +64,11 @@ namespace Microsoft.Terminal.Control
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<Object, TitleChangedEventArgs> TitleChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, WriteToClipboardEventArgs> WriteToClipboard;
|
||||
event Windows.Foundation.TypedEventHandler<Object, PasteFromClipboardEventArgs> PasteFromClipboard;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> PasteFromClipboard;
|
||||
event Windows.Foundation.TypedEventHandler<Object, OpenHyperlinkEventArgs> OpenHyperlink;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> SetTaskbarProgress;
|
||||
event Windows.Foundation.TypedEventHandler<Object, NoticeEventArgs> RaiseNotice;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> WarningBell;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> PromptStarted;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> OutputStarted;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> OutputIdle;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> HidePointerCursor;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> RestorePointerCursor;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> TabColorChanged;
|
||||
@@ -130,10 +127,12 @@ namespace Microsoft.Terminal.Control
|
||||
void ResetFontSize();
|
||||
|
||||
void ToggleShaderEffects();
|
||||
void SendInput(String input);
|
||||
Boolean RawWriteKeyEvent(UInt16 vkey, UInt16 scanCode, Microsoft.Terminal.Core.ControlKeyStates modifiers, Boolean keyDown);
|
||||
Boolean RawWriteChar(Char character, UInt16 scanCode, Microsoft.Terminal.Core.ControlKeyStates modifiers);
|
||||
void RawWriteString(String text);
|
||||
void WriteInputString(String text, WriteInputStringType type);
|
||||
// This is a stopgap until GH#20164 removes StringSent
|
||||
// It prevents us from entering an infinite broadcast loop
|
||||
void WriteInputStringWithoutBroadcast(String text, WriteInputStringType type);
|
||||
|
||||
void BellLightOn();
|
||||
|
||||
|
||||
@@ -763,11 +763,6 @@ TerminalInput::OutputType Terminal::SendCharEvent(const wchar_t ch, const WORD s
|
||||
// This changed the scrollbar marks - raise a notification to update them
|
||||
_NotifyScrollEvent();
|
||||
}
|
||||
// regardless, notify that we started command output
|
||||
if (_pfnOutputStarted)
|
||||
{
|
||||
_pfnOutputStarted();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1253,7 +1248,7 @@ const std::optional<til::color> Terminal::GetTabColor() const
|
||||
// - Gets the internal taskbar state value
|
||||
// Return Value:
|
||||
// - The taskbar state
|
||||
const Microsoft::Console::VirtualTerminal::DispatchTypes::TaskbarState Microsoft::Terminal::Core::Terminal::GetTaskbarState() const noexcept
|
||||
const size_t Microsoft::Terminal::Core::Terminal::GetTaskbarState() const noexcept
|
||||
{
|
||||
return _taskbarState;
|
||||
}
|
||||
@@ -1282,16 +1277,6 @@ void Microsoft::Terminal::Core::Terminal::SetClearQuickFixCallback(std::function
|
||||
_pfnClearQuickFix.swap(pfn);
|
||||
}
|
||||
|
||||
void Terminal::SetPromptStartedCallback(std::function<void()> pfn) noexcept
|
||||
{
|
||||
_pfnPromptStarted.swap(pfn);
|
||||
}
|
||||
|
||||
void Terminal::SetOutputStartedCallback(std::function<void()> pfn) noexcept
|
||||
{
|
||||
_pfnOutputStarted.swap(pfn);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Stores the search highlighted regions in the terminal
|
||||
void Terminal::SetSearchHighlights(const std::vector<til::point_span>& highlights) noexcept
|
||||
|
||||
@@ -159,7 +159,7 @@ public:
|
||||
|
||||
bool IsVtInputEnabled() const noexcept override;
|
||||
void NotifyBufferRotation(const int delta) override;
|
||||
void NotifyShellIntegrationMark(ShellIntegrationMark mark) override;
|
||||
void NotifyShellIntegrationMark() override;
|
||||
|
||||
void InvokeCompletions(std::wstring_view menuJson, unsigned int replaceLength) override;
|
||||
|
||||
@@ -235,8 +235,6 @@ public:
|
||||
void SetSearchMissingCommandCallback(std::function<void(std::wstring_view, const til::CoordType)> pfn) noexcept;
|
||||
void SetClearQuickFixCallback(std::function<void()> pfn) noexcept;
|
||||
void SetWindowSizeChangedCallback(std::function<void(int32_t, int32_t)> pfn) noexcept;
|
||||
void SetPromptStartedCallback(std::function<void()> pfn) noexcept;
|
||||
void SetOutputStartedCallback(std::function<void()> pfn) noexcept;
|
||||
void SetSearchHighlights(const std::vector<til::point_span>& highlights) noexcept;
|
||||
void SetSearchHighlightFocused(size_t focusedIdx) noexcept;
|
||||
void ScrollToSearchHighlight(til::CoordType searchScrollOffset);
|
||||
@@ -245,7 +243,7 @@ public:
|
||||
|
||||
const std::optional<til::color> GetTabColor() const;
|
||||
|
||||
const ::Microsoft::Console::VirtualTerminal::DispatchTypes::TaskbarState GetTaskbarState() const noexcept;
|
||||
const size_t GetTaskbarState() const noexcept;
|
||||
const size_t GetTaskbarProgress() const noexcept;
|
||||
|
||||
void ColorSelection(const TextAttribute& attr, winrt::Microsoft::Terminal::Core::MatchMode matchMode);
|
||||
@@ -345,8 +343,6 @@ private:
|
||||
std::function<void(std::wstring_view, const til::CoordType)> _pfnSearchMissingCommand;
|
||||
std::function<void()> _pfnClearQuickFix;
|
||||
std::function<void(int32_t, int32_t)> _pfnWindowSizeChanged;
|
||||
std::function<void()> _pfnPromptStarted;
|
||||
std::function<void()> _pfnOutputStarted;
|
||||
|
||||
RenderSettings _renderSettings;
|
||||
std::unique_ptr<::Microsoft::Console::VirtualTerminal::StateMachine> _stateMachine;
|
||||
@@ -367,9 +363,6 @@ private:
|
||||
|
||||
til::enumset<Mode> _systemMode{ Mode::AutoWrap };
|
||||
|
||||
::Microsoft::Console::VirtualTerminal::DispatchTypes::TaskbarState _taskbarState{ ::Microsoft::Console::VirtualTerminal::DispatchTypes::TaskbarState::Clear };
|
||||
size_t _taskbarProgress = 0;
|
||||
|
||||
bool _focused = false;
|
||||
bool _snapOnInput = true;
|
||||
bool _altGrAliasing = true;
|
||||
@@ -378,6 +371,9 @@ private:
|
||||
bool _autoMarkPrompts = false;
|
||||
bool _rainbowSuggestions = false;
|
||||
|
||||
size_t _taskbarState = 0;
|
||||
size_t _taskbarProgress = 0;
|
||||
|
||||
size_t _hyperlinkPatternId = 0;
|
||||
|
||||
std::wstring _answerbackMessage;
|
||||
|
||||
@@ -162,7 +162,7 @@ void Terminal::SetTaskbarProgress(const ::Microsoft::Console::VirtualTerminal::D
|
||||
{
|
||||
_assertLocked();
|
||||
|
||||
_taskbarState = state;
|
||||
_taskbarState = static_cast<size_t>(state);
|
||||
|
||||
switch (state)
|
||||
{
|
||||
@@ -405,26 +405,8 @@ void Terminal::NotifyBufferRotation(const int delta)
|
||||
}
|
||||
}
|
||||
|
||||
void Terminal::NotifyShellIntegrationMark(ShellIntegrationMark mark)
|
||||
void Terminal::NotifyShellIntegrationMark()
|
||||
{
|
||||
// Notify the scrollbar that marks have been added so it can refresh the mark indicators
|
||||
_NotifyScrollEvent();
|
||||
|
||||
switch (mark)
|
||||
{
|
||||
case ShellIntegrationMark::Prompt:
|
||||
if (_pfnPromptStarted)
|
||||
{
|
||||
_pfnPromptStarted();
|
||||
}
|
||||
break;
|
||||
case ShellIntegrationMark::Output:
|
||||
if (_pfnOutputStarted)
|
||||
{
|
||||
_pfnOutputStarted();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -354,11 +354,6 @@ namespace winrt::Microsoft::Terminal::Settings
|
||||
_AllowVtClipboardWrite = profile.AllowVtClipboardWrite();
|
||||
_PathTranslationStyle = profile.PathTranslationStyle();
|
||||
_DragDropDelimiter = profile.DragDropDelimiter();
|
||||
_NotifyOnActivity = profile.NotifyOnActivity();
|
||||
_NotifyOnNextPrompt = profile.NotifyOnNextPrompt();
|
||||
_NotifyOnActivityThreshold = profile.NotifyOnActivityThreshold();
|
||||
_NotifyOnNextPromptThreshold = profile.NotifyOnNextPromptThreshold();
|
||||
_AutoDetectRunningCommand = profile.AutoDetectRunningCommand();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
||||
@@ -135,14 +135,11 @@
|
||||
<TextBlock x:Uid="Globals_WarningsHeader"
|
||||
Style="{StaticResource TextBlockSubHeaderStyle}" />
|
||||
|
||||
<!-- Confirm Close On -->
|
||||
<local:SettingContainer x:Name="ConfirmOnClose"
|
||||
x:Uid="Globals_ConfirmOnClose">
|
||||
<ComboBox AutomationProperties.AccessibilityView="Content"
|
||||
ItemTemplate="{StaticResource EnumComboBoxTemplate}"
|
||||
ItemsSource="{x:Bind ViewModel.ConfirmOnCloseList}"
|
||||
SelectedItem="{x:Bind ViewModel.CurrentConfirmOnClose, Mode=TwoWay}"
|
||||
Style="{StaticResource ComboBoxSettingStyle}" />
|
||||
<!-- Close All Tabs Warning -->
|
||||
<local:SettingContainer x:Name="ConfirmCloseAllTabs"
|
||||
x:Uid="Globals_ConfirmCloseAllTabs">
|
||||
<ToggleSwitch IsOn="{x:Bind ViewModel.ConfirmCloseAllTabs, Mode=TwoWay}"
|
||||
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
|
||||
</local:SettingContainer>
|
||||
|
||||
<!-- Input Service Warning -->
|
||||
|
||||
@@ -17,6 +17,5 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
INITIALIZE_BINDABLE_ENUM_SETTING(TabSwitcherMode, TabSwitcherMode, TabSwitcherMode, L"Globals_TabSwitcherMode", L"Content");
|
||||
INITIALIZE_BINDABLE_ENUM_SETTING(CopyFormat, CopyFormat, winrt::Microsoft::Terminal::Control::CopyFormat, L"Globals_CopyFormat", L"Content");
|
||||
INITIALIZE_BINDABLE_ENUM_SETTING(ConfirmOnClose, ConfirmOnClose, Model::ConfirmOnClose, L"Globals_ConfirmOnClose", L"Content");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
|
||||
GETSET_BINDABLE_ENUM_SETTING(TabSwitcherMode, Model::TabSwitcherMode, _GlobalSettings.TabSwitcherMode);
|
||||
GETSET_BINDABLE_ENUM_SETTING(CopyFormat, winrt::Microsoft::Terminal::Control::CopyFormat, _GlobalSettings.CopyFormatting);
|
||||
GETSET_BINDABLE_ENUM_SETTING(ConfirmOnClose, Model::ConfirmOnClose, _GlobalSettings.ConfirmOnClose);
|
||||
|
||||
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, CopyOnSelect);
|
||||
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, TrimBlockSelection);
|
||||
@@ -31,6 +30,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, DetectURLs);
|
||||
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, SearchWebDefaultQueryUrl);
|
||||
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, WordDelimiters);
|
||||
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, ConfirmCloseAllTabs);
|
||||
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, InputServiceWarning);
|
||||
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, WarnAboutLargePaste);
|
||||
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, WarnAboutMultiLinePaste);
|
||||
|
||||
@@ -12,13 +12,10 @@ namespace Microsoft.Terminal.Settings.Editor
|
||||
InteractionViewModel(Microsoft.Terminal.Settings.Model.GlobalAppSettings globalSettings);
|
||||
|
||||
IInspectable CurrentTabSwitcherMode;
|
||||
Windows.Foundation.Collections.IObservableVector<EnumEntry> TabSwitcherModeList { get; };
|
||||
Windows.Foundation.Collections.IObservableVector<Microsoft.Terminal.Settings.Editor.EnumEntry> TabSwitcherModeList { get; };
|
||||
|
||||
IInspectable CurrentCopyFormat;
|
||||
Windows.Foundation.Collections.IObservableVector<EnumEntry> CopyFormatList { get; };
|
||||
|
||||
IInspectable CurrentConfirmOnClose;
|
||||
Windows.Foundation.Collections.IObservableVector<EnumEntry> ConfirmOnCloseList { get; };
|
||||
Windows.Foundation.Collections.IObservableVector<Microsoft.Terminal.Settings.Editor.EnumEntry> CopyFormatList { get; };
|
||||
|
||||
PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, CopyOnSelect);
|
||||
PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, TrimBlockSelection);
|
||||
@@ -30,6 +27,7 @@ namespace Microsoft.Terminal.Settings.Editor
|
||||
PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, DetectURLs);
|
||||
PERMANENT_OBSERVABLE_PROJECTED_SETTING(String, SearchWebDefaultQueryUrl);
|
||||
PERMANENT_OBSERVABLE_PROJECTED_SETTING(String, WordDelimiters);
|
||||
PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, ConfirmCloseAllTabs);
|
||||
PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, InputServiceWarning);
|
||||
PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, WarnAboutLargePaste);
|
||||
PERMANENT_OBSERVABLE_PROJECTED_SETTING(Microsoft.Terminal.Control.WarnAboutMultiLinePaste, WarnAboutMultiLinePaste);
|
||||
|
||||
@@ -106,14 +106,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
_NotifyChanges(L"CurrentPathTranslationStyle");
|
||||
}
|
||||
else if (viewModelProperty == L"NotifyOnActivity")
|
||||
{
|
||||
_NotifyChanges(L"IsNotifyOnActivityFlagSet", L"NotifyOnActivityPreview");
|
||||
}
|
||||
else if (viewModelProperty == L"NotifyOnNextPrompt")
|
||||
{
|
||||
_NotifyChanges(L"IsNotifyOnNextPromptFlagSet", L"NotifyOnNextPromptPreview");
|
||||
}
|
||||
else if (viewModelProperty == L"Padding")
|
||||
{
|
||||
_parsedPadding = StringToXamlThickness(_profile.Padding());
|
||||
@@ -579,11 +571,10 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
return iconPath.empty() || iconPath == IconPicker::HideIconValue;
|
||||
}
|
||||
|
||||
#pragma region BellStyle
|
||||
hstring ProfileViewModel::BellStylePreview() const
|
||||
{
|
||||
const auto bellStyle = BellStyle();
|
||||
if (WI_AreAllFlagsSet(bellStyle, BellStyle::Audible | BellStyle::Window | BellStyle::Taskbar | BellStyle::Notification))
|
||||
if (WI_AreAllFlagsSet(bellStyle, BellStyle::Audible | BellStyle::Window | BellStyle::Taskbar))
|
||||
{
|
||||
return RS_(L"Profile_BellStyleAll/Content");
|
||||
}
|
||||
@@ -593,7 +584,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
}
|
||||
|
||||
std::vector<hstring> resultList;
|
||||
resultList.reserve(4);
|
||||
resultList.reserve(3);
|
||||
if (WI_IsFlagSet(bellStyle, BellStyle::Audible))
|
||||
{
|
||||
resultList.emplace_back(RS_(L"Profile_BellStyleAudible/Content"));
|
||||
@@ -606,10 +597,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
{
|
||||
resultList.emplace_back(RS_(L"Profile_BellStyleTaskbar/Content"));
|
||||
}
|
||||
if (WI_IsFlagSet(bellStyle, BellStyle::Notification))
|
||||
{
|
||||
resultList.emplace_back(RS_(L"Profile_BellStyleNotification/Content"));
|
||||
}
|
||||
|
||||
// add in the commas
|
||||
hstring result{};
|
||||
@@ -653,154 +640,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
BellStyle(currentStyle);
|
||||
}
|
||||
|
||||
void ProfileViewModel::SetBellStyleNotification(winrt::Windows::Foundation::IReference<bool> on)
|
||||
{
|
||||
auto currentStyle = BellStyle();
|
||||
WI_UpdateFlag(currentStyle, Model::BellStyle::Notification, winrt::unbox_value<bool>(on));
|
||||
BellStyle(currentStyle);
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
#pragma region NotifyOnActivity
|
||||
hstring ProfileViewModel::NotifyOnActivityPreview() const
|
||||
{
|
||||
using Ons = Control::OutputNotificationStyle;
|
||||
const auto style = NotifyOnActivity();
|
||||
if (WI_AreAllFlagsSet(style, Ons::Taskbar | Ons::Audible | Ons::Tab | Ons::Notification))
|
||||
{
|
||||
return RS_(L"Profile_OutputNotificationStyleAll/Content");
|
||||
}
|
||||
else if (style == Ons::None)
|
||||
{
|
||||
return RS_(L"Profile_OutputNotificationStyleNone/Content");
|
||||
}
|
||||
|
||||
std::wstring result;
|
||||
const auto appendIfFlagSet = [&](Ons flag, std::wstring_view resource) {
|
||||
// WI_IsFlagSet requires a compile-time constant flag; `flag` is a runtime parameter here.
|
||||
if ((WI_EnumValue(style) & WI_EnumValue(flag)) != 0)
|
||||
{
|
||||
if (!result.empty())
|
||||
{
|
||||
result.append(L", ");
|
||||
}
|
||||
result.append(resource);
|
||||
}
|
||||
};
|
||||
|
||||
appendIfFlagSet(Ons::Taskbar, RS_(L"Profile_OutputNotificationStyleTaskbar/Content"));
|
||||
appendIfFlagSet(Ons::Audible, RS_(L"Profile_OutputNotificationStyleAudible/Content"));
|
||||
appendIfFlagSet(Ons::Tab, RS_(L"Profile_OutputNotificationStyleTab/Content"));
|
||||
appendIfFlagSet(Ons::Notification, RS_(L"Profile_OutputNotificationStyleNotification/Content"));
|
||||
|
||||
return hstring{ result };
|
||||
}
|
||||
|
||||
bool ProfileViewModel::IsNotifyOnActivityFlagSet(const uint32_t flag)
|
||||
{
|
||||
return (WI_EnumValue(NotifyOnActivity()) & flag) == flag;
|
||||
}
|
||||
|
||||
void ProfileViewModel::SetNotifyOnActivityTaskbar(winrt::Windows::Foundation::IReference<bool> on)
|
||||
{
|
||||
auto currentStyle = NotifyOnActivity();
|
||||
WI_UpdateFlag(currentStyle, Control::OutputNotificationStyle::Taskbar, winrt::unbox_value<bool>(on));
|
||||
NotifyOnActivity(currentStyle);
|
||||
}
|
||||
|
||||
void ProfileViewModel::SetNotifyOnActivityAudible(winrt::Windows::Foundation::IReference<bool> on)
|
||||
{
|
||||
auto currentStyle = NotifyOnActivity();
|
||||
WI_UpdateFlag(currentStyle, Control::OutputNotificationStyle::Audible, winrt::unbox_value<bool>(on));
|
||||
NotifyOnActivity(currentStyle);
|
||||
}
|
||||
|
||||
void ProfileViewModel::SetNotifyOnActivityTab(winrt::Windows::Foundation::IReference<bool> on)
|
||||
{
|
||||
auto currentStyle = NotifyOnActivity();
|
||||
WI_UpdateFlag(currentStyle, Control::OutputNotificationStyle::Tab, winrt::unbox_value<bool>(on));
|
||||
NotifyOnActivity(currentStyle);
|
||||
}
|
||||
|
||||
void ProfileViewModel::SetNotifyOnActivityNotification(winrt::Windows::Foundation::IReference<bool> on)
|
||||
{
|
||||
auto currentStyle = NotifyOnActivity();
|
||||
WI_UpdateFlag(currentStyle, Control::OutputNotificationStyle::Notification, winrt::unbox_value<bool>(on));
|
||||
NotifyOnActivity(currentStyle);
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
#pragma region NotifyOnNextPrompt
|
||||
hstring ProfileViewModel::NotifyOnNextPromptPreview() const
|
||||
{
|
||||
using Ons = Control::OutputNotificationStyle;
|
||||
const auto style = NotifyOnNextPrompt();
|
||||
if (WI_AreAllFlagsSet(style, Ons::Taskbar | Ons::Audible | Ons::Tab | Ons::Notification))
|
||||
{
|
||||
return RS_(L"Profile_OutputNotificationStyleAll/Content");
|
||||
}
|
||||
else if (style == Ons::None)
|
||||
{
|
||||
return RS_(L"Profile_OutputNotificationStyleNone/Content");
|
||||
}
|
||||
|
||||
std::wstring result;
|
||||
const auto appendIfFlagSet = [&](Ons flag, std::wstring_view resource) {
|
||||
// WI_IsFlagSet requires a compile-time constant flag; `flag` is a runtime parameter here.
|
||||
if ((WI_EnumValue(style) & WI_EnumValue(flag)) != 0)
|
||||
{
|
||||
if (!result.empty())
|
||||
{
|
||||
result.append(L", ");
|
||||
}
|
||||
result.append(resource);
|
||||
}
|
||||
};
|
||||
|
||||
appendIfFlagSet(Ons::Taskbar, RS_(L"Profile_OutputNotificationStyleTaskbar/Content"));
|
||||
appendIfFlagSet(Ons::Audible, RS_(L"Profile_OutputNotificationStyleAudible/Content"));
|
||||
appendIfFlagSet(Ons::Tab, RS_(L"Profile_OutputNotificationStyleTab/Content"));
|
||||
appendIfFlagSet(Ons::Notification, RS_(L"Profile_OutputNotificationStyleNotification/Content"));
|
||||
|
||||
return hstring{ result };
|
||||
}
|
||||
|
||||
bool ProfileViewModel::IsNotifyOnNextPromptFlagSet(const uint32_t flag)
|
||||
{
|
||||
return (WI_EnumValue(NotifyOnNextPrompt()) & flag) == flag;
|
||||
}
|
||||
|
||||
void ProfileViewModel::SetNotifyOnNextPromptTaskbar(winrt::Windows::Foundation::IReference<bool> on)
|
||||
{
|
||||
auto currentStyle = NotifyOnNextPrompt();
|
||||
WI_UpdateFlag(currentStyle, Control::OutputNotificationStyle::Taskbar, winrt::unbox_value<bool>(on));
|
||||
NotifyOnNextPrompt(currentStyle);
|
||||
}
|
||||
|
||||
void ProfileViewModel::SetNotifyOnNextPromptAudible(winrt::Windows::Foundation::IReference<bool> on)
|
||||
{
|
||||
auto currentStyle = NotifyOnNextPrompt();
|
||||
WI_UpdateFlag(currentStyle, Control::OutputNotificationStyle::Audible, winrt::unbox_value<bool>(on));
|
||||
NotifyOnNextPrompt(currentStyle);
|
||||
}
|
||||
|
||||
void ProfileViewModel::SetNotifyOnNextPromptTab(winrt::Windows::Foundation::IReference<bool> on)
|
||||
{
|
||||
auto currentStyle = NotifyOnNextPrompt();
|
||||
WI_UpdateFlag(currentStyle, Control::OutputNotificationStyle::Tab, winrt::unbox_value<bool>(on));
|
||||
NotifyOnNextPrompt(currentStyle);
|
||||
}
|
||||
|
||||
void ProfileViewModel::SetNotifyOnNextPromptNotification(winrt::Windows::Foundation::IReference<bool> on)
|
||||
{
|
||||
auto currentStyle = NotifyOnNextPrompt();
|
||||
WI_UpdateFlag(currentStyle, Control::OutputNotificationStyle::Notification, winrt::unbox_value<bool>(on));
|
||||
NotifyOnNextPrompt(currentStyle);
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
#pragma region BellSound
|
||||
|
||||
// Method Description:
|
||||
// - Construct _CurrentBellSounds by importing the _inherited_ value from the model
|
||||
// - Adds a PropertyChanged handler to each BellSoundViewModel to propagate changes to the model
|
||||
@@ -938,7 +777,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
_NotifyChanges(L"CurrentBellSounds");
|
||||
}
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
void ProfileViewModel::DeleteProfile()
|
||||
{
|
||||
|
||||
@@ -46,23 +46,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
void SetBellStyleAudible(winrt::Windows::Foundation::IReference<bool> on);
|
||||
void SetBellStyleWindow(winrt::Windows::Foundation::IReference<bool> on);
|
||||
void SetBellStyleTaskbar(winrt::Windows::Foundation::IReference<bool> on);
|
||||
void SetBellStyleNotification(winrt::Windows::Foundation::IReference<bool> on);
|
||||
|
||||
// notify on activity bits
|
||||
hstring NotifyOnActivityPreview() const;
|
||||
bool IsNotifyOnActivityFlagSet(const uint32_t flag);
|
||||
void SetNotifyOnActivityTaskbar(winrt::Windows::Foundation::IReference<bool> on);
|
||||
void SetNotifyOnActivityAudible(winrt::Windows::Foundation::IReference<bool> on);
|
||||
void SetNotifyOnActivityTab(winrt::Windows::Foundation::IReference<bool> on);
|
||||
void SetNotifyOnActivityNotification(winrt::Windows::Foundation::IReference<bool> on);
|
||||
|
||||
// notify on next prompt bits
|
||||
hstring NotifyOnNextPromptPreview() const;
|
||||
bool IsNotifyOnNextPromptFlagSet(const uint32_t flag);
|
||||
void SetNotifyOnNextPromptTaskbar(winrt::Windows::Foundation::IReference<bool> on);
|
||||
void SetNotifyOnNextPromptAudible(winrt::Windows::Foundation::IReference<bool> on);
|
||||
void SetNotifyOnNextPromptTab(winrt::Windows::Foundation::IReference<bool> on);
|
||||
void SetNotifyOnNextPromptNotification(winrt::Windows::Foundation::IReference<bool> on);
|
||||
|
||||
hstring BellSoundPreview();
|
||||
void RequestAddBellSound(hstring path);
|
||||
@@ -163,11 +146,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, RainbowSuggestions);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, PathTranslationStyle);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, DragDropDelimiter);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, NotifyOnActivity);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, NotifyOnNextPrompt);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, NotifyOnActivityThreshold);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, NotifyOnNextPromptThreshold);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, AutoDetectRunningCommand);
|
||||
|
||||
WINRT_PROPERTY(bool, IsBaseLayer, false);
|
||||
WINRT_PROPERTY(bool, FocusDeleteButton, false);
|
||||
|
||||
@@ -49,21 +49,6 @@ namespace Microsoft.Terminal.Settings.Editor
|
||||
void SetBellStyleAudible(Windows.Foundation.IReference<Boolean> on);
|
||||
void SetBellStyleWindow(Windows.Foundation.IReference<Boolean> on);
|
||||
void SetBellStyleTaskbar(Windows.Foundation.IReference<Boolean> on);
|
||||
void SetBellStyleNotification(Windows.Foundation.IReference<Boolean> on);
|
||||
|
||||
String NotifyOnActivityPreview { get; };
|
||||
Boolean IsNotifyOnActivityFlagSet(UInt32 flag);
|
||||
void SetNotifyOnActivityTaskbar(Windows.Foundation.IReference<Boolean> on);
|
||||
void SetNotifyOnActivityAudible(Windows.Foundation.IReference<Boolean> on);
|
||||
void SetNotifyOnActivityTab(Windows.Foundation.IReference<Boolean> on);
|
||||
void SetNotifyOnActivityNotification(Windows.Foundation.IReference<Boolean> on);
|
||||
|
||||
String NotifyOnNextPromptPreview { get; };
|
||||
Boolean IsNotifyOnNextPromptFlagSet(UInt32 flag);
|
||||
void SetNotifyOnNextPromptTaskbar(Windows.Foundation.IReference<Boolean> on);
|
||||
void SetNotifyOnNextPromptAudible(Windows.Foundation.IReference<Boolean> on);
|
||||
void SetNotifyOnNextPromptTab(Windows.Foundation.IReference<Boolean> on);
|
||||
void SetNotifyOnNextPromptNotification(Windows.Foundation.IReference<Boolean> on);
|
||||
|
||||
String BellSoundPreview { get; };
|
||||
Windows.Foundation.Collections.IObservableVector<BellSoundViewModel> CurrentBellSounds { get; };
|
||||
@@ -156,10 +141,5 @@ namespace Microsoft.Terminal.Settings.Editor
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Microsoft.Terminal.Control.PathTranslationStyle, PathTranslationStyle);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(String, DragDropDelimiter);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, AllowVtClipboardWrite);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Microsoft.Terminal.Control.OutputNotificationStyle, NotifyOnActivity);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Microsoft.Terminal.Control.OutputNotificationStyle, NotifyOnNextPrompt);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Int32, NotifyOnActivityThreshold);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Int32, NotifyOnNextPromptThreshold);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, AutoDetectRunningCommand);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,8 +111,6 @@
|
||||
IsChecked="{x:Bind Profile.IsBellStyleFlagSet(2), BindBack=Profile.SetBellStyleWindow, Mode=TwoWay}" />
|
||||
<CheckBox x:Uid="Profile_BellStyleTaskbar"
|
||||
IsChecked="{x:Bind Profile.IsBellStyleFlagSet(4), BindBack=Profile.SetBellStyleTaskbar, Mode=TwoWay}" />
|
||||
<CheckBox x:Uid="Profile_BellStyleNotification"
|
||||
IsChecked="{x:Bind Profile.IsBellStyleFlagSet(8), BindBack=Profile.SetBellStyleNotification, Mode=TwoWay}" />
|
||||
</StackPanel>
|
||||
</local:SettingContainer>
|
||||
|
||||
@@ -198,84 +196,6 @@
|
||||
</StackPanel>
|
||||
</local:SettingContainer>
|
||||
|
||||
<!-- Notify On Activity -->
|
||||
<local:SettingContainer x:Name="NotifyOnActivity"
|
||||
x:Uid="Profile_NotifyOnActivity"
|
||||
ClearSettingValue="{x:Bind Profile.ClearNotifyOnActivity}"
|
||||
CurrentValue="{x:Bind Profile.NotifyOnActivityPreview, Mode=OneWay}"
|
||||
HasSettingValue="{x:Bind Profile.HasNotifyOnActivity, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind Profile.NotifyOnActivityOverrideSource, Mode=OneWay}"
|
||||
Style="{StaticResource ExpanderSettingContainerStyle}">
|
||||
<StackPanel>
|
||||
<CheckBox x:Uid="Profile_OutputNotificationStyleTaskbar"
|
||||
IsChecked="{x:Bind Profile.IsNotifyOnActivityFlagSet(1), BindBack=Profile.SetNotifyOnActivityTaskbar, Mode=TwoWay}" />
|
||||
<CheckBox x:Uid="Profile_OutputNotificationStyleAudible"
|
||||
IsChecked="{x:Bind Profile.IsNotifyOnActivityFlagSet(2), BindBack=Profile.SetNotifyOnActivityAudible, Mode=TwoWay}" />
|
||||
<CheckBox x:Uid="Profile_OutputNotificationStyleTab"
|
||||
IsChecked="{x:Bind Profile.IsNotifyOnActivityFlagSet(4), BindBack=Profile.SetNotifyOnActivityTab, Mode=TwoWay}" />
|
||||
<CheckBox x:Uid="Profile_OutputNotificationStyleNotification"
|
||||
IsChecked="{x:Bind Profile.IsNotifyOnActivityFlagSet(8), BindBack=Profile.SetNotifyOnActivityNotification, Mode=TwoWay}" />
|
||||
</StackPanel>
|
||||
</local:SettingContainer>
|
||||
|
||||
<!-- Notify On Activity Minimum Duration -->
|
||||
<local:SettingContainer x:Name="NotifyOnActivityThreshold"
|
||||
x:Uid="Profile_NotifyOnActivityThreshold"
|
||||
ClearSettingValue="{x:Bind Profile.ClearNotifyOnActivityThreshold}"
|
||||
HasSettingValue="{x:Bind Profile.HasNotifyOnActivityThreshold, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind Profile.NotifyOnActivityThresholdOverrideSource, Mode=OneWay}">
|
||||
<muxc:NumberBox AutomationProperties.Name="{Binding ElementName=NotifyOnActivityThreshold, Path=Header}"
|
||||
LargeChange="10"
|
||||
Minimum="0"
|
||||
SmallChange="1"
|
||||
Style="{StaticResource NumberBoxSettingStyle}"
|
||||
Value="{x:Bind Profile.NotifyOnActivityThreshold, Mode=TwoWay}" />
|
||||
</local:SettingContainer>
|
||||
|
||||
<!-- Notify On Next Prompt -->
|
||||
<local:SettingContainer x:Name="NotifyOnNextPrompt"
|
||||
x:Uid="Profile_NotifyOnNextPrompt"
|
||||
ClearSettingValue="{x:Bind Profile.ClearNotifyOnNextPrompt}"
|
||||
CurrentValue="{x:Bind Profile.NotifyOnNextPromptPreview, Mode=OneWay}"
|
||||
HasSettingValue="{x:Bind Profile.HasNotifyOnNextPrompt, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind Profile.NotifyOnNextPromptOverrideSource, Mode=OneWay}"
|
||||
Style="{StaticResource ExpanderSettingContainerStyle}">
|
||||
<StackPanel>
|
||||
<CheckBox x:Uid="Profile_OutputNotificationStyleTaskbar"
|
||||
IsChecked="{x:Bind Profile.IsNotifyOnNextPromptFlagSet(1), BindBack=Profile.SetNotifyOnNextPromptTaskbar, Mode=TwoWay}" />
|
||||
<CheckBox x:Uid="Profile_OutputNotificationStyleAudible"
|
||||
IsChecked="{x:Bind Profile.IsNotifyOnNextPromptFlagSet(2), BindBack=Profile.SetNotifyOnNextPromptAudible, Mode=TwoWay}" />
|
||||
<CheckBox x:Uid="Profile_OutputNotificationStyleTab"
|
||||
IsChecked="{x:Bind Profile.IsNotifyOnNextPromptFlagSet(4), BindBack=Profile.SetNotifyOnNextPromptTab, Mode=TwoWay}" />
|
||||
<CheckBox x:Uid="Profile_OutputNotificationStyleNotification"
|
||||
IsChecked="{x:Bind Profile.IsNotifyOnNextPromptFlagSet(8), BindBack=Profile.SetNotifyOnNextPromptNotification, Mode=TwoWay}" />
|
||||
</StackPanel>
|
||||
</local:SettingContainer>
|
||||
|
||||
<!-- Notify On Next Prompt Minimum Duration -->
|
||||
<local:SettingContainer x:Name="NotifyOnNextPromptThreshold"
|
||||
x:Uid="Profile_NotifyOnNextPromptThreshold"
|
||||
ClearSettingValue="{x:Bind Profile.ClearNotifyOnNextPromptThreshold}"
|
||||
HasSettingValue="{x:Bind Profile.HasNotifyOnNextPromptThreshold, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind Profile.NotifyOnNextPromptThresholdOverrideSource, Mode=OneWay}">
|
||||
<muxc:NumberBox AutomationProperties.Name="{Binding ElementName=NotifyOnNextPromptThreshold, Path=Header}"
|
||||
LargeChange="10"
|
||||
Minimum="0"
|
||||
SmallChange="1"
|
||||
Style="{StaticResource NumberBoxSettingStyle}"
|
||||
Value="{x:Bind Profile.NotifyOnNextPromptThreshold, Mode=TwoWay}" />
|
||||
</local:SettingContainer>
|
||||
|
||||
<!-- Auto Detect Running Command -->
|
||||
<local:SettingContainer x:Name="AutoDetectRunningCommand"
|
||||
x:Uid="Profile_AutoDetectRunningCommand"
|
||||
ClearSettingValue="{x:Bind Profile.ClearAutoDetectRunningCommand}"
|
||||
HasSettingValue="{x:Bind Profile.HasAutoDetectRunningCommand, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind Profile.AutoDetectRunningCommandOverrideSource, Mode=OneWay}">
|
||||
<ToggleSwitch IsOn="{x:Bind Profile.AutoDetectRunningCommand, Mode=TwoWay}"
|
||||
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
|
||||
</local:SettingContainer>
|
||||
|
||||
<!-- RightClickContextMenu -->
|
||||
<local:SettingContainer x:Name="RightClickContextMenu"
|
||||
x:Uid="Profile_RightClickContextMenu"
|
||||
|
||||
@@ -1553,74 +1553,6 @@
|
||||
<value>Flash window</value>
|
||||
<comment>An option to choose from for the "bell style" setting. When selected, a visual notification is used to notify the user. In this case, the window is flashed.</comment>
|
||||
</data>
|
||||
<data name="Profile_OutputNotificationStyleNone.Content" xml:space="preserve">
|
||||
<value>None</value>
|
||||
<comment>An option to choose from for the notification style setting. When selected, no notification is sent.</comment>
|
||||
</data>
|
||||
<data name="Profile_OutputNotificationStyleAll.Content" xml:space="preserve">
|
||||
<value>All</value>
|
||||
<comment>An option to choose from for the notification style setting. When selected, all notification methods are used.</comment>
|
||||
</data>
|
||||
<data name="Profile_OutputNotificationStyleTaskbar.Content" xml:space="preserve">
|
||||
<value>Flash taskbar</value>
|
||||
<comment>An option to choose from for the notification style setting. Flashes the taskbar icon.</comment>
|
||||
</data>
|
||||
<data name="Profile_OutputNotificationStyleAudible.Content" xml:space="preserve">
|
||||
<value>Play sound</value>
|
||||
<comment>An option to choose from for the notification style setting. Plays an audible notification sound.</comment>
|
||||
</data>
|
||||
<data name="Profile_OutputNotificationStyleTab.Content" xml:space="preserve">
|
||||
<value>Show tab indicator</value>
|
||||
<comment>An option to choose from for the notification style setting. Shows an activity indicator on the tab.</comment>
|
||||
</data>
|
||||
<data name="Profile_OutputNotificationStyleNotification.Content" xml:space="preserve">
|
||||
<value>Desktop notification</value>
|
||||
<comment>An option to choose from for the notification style setting. Sends a Windows desktop notification (toast).</comment>
|
||||
</data>
|
||||
<data name="Profile_NotifyOnActivity.Header" xml:space="preserve">
|
||||
<value>Notify on activity</value>
|
||||
<comment>Header for a control to set the notification style when a background tab has new activity (output).</comment>
|
||||
</data>
|
||||
<data name="Profile_NotifyOnActivity.HelpText" xml:space="preserve">
|
||||
<value>Choose how to be notified when a background tab produces new output.</value>
|
||||
<comment>Help text for the notify on activity setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_NotifyOnActivityThreshold.Header" xml:space="preserve">
|
||||
<value>Minimum seconds between activity notifications</value>
|
||||
<comment>Header for a numeric control that sets the minimum number of seconds between consecutive "notify on activity" notifications. Useful for chatty programs.</comment>
|
||||
</data>
|
||||
<data name="Profile_NotifyOnActivityThreshold.HelpText" xml:space="preserve">
|
||||
<value>Suppress repeated activity notifications within this many seconds of the previous one. Set to 0 to always notify.</value>
|
||||
<comment>Help text for the minimum duration threshold applied to "notify on activity" notifications.</comment>
|
||||
</data>
|
||||
<data name="Profile_NotifyOnNextPrompt.Header" xml:space="preserve">
|
||||
<value>Notify on next prompt</value>
|
||||
<comment>Header for a control to set the notification style when a new shell prompt is detected (requires shell integration).</comment>
|
||||
</data>
|
||||
<data name="Profile_NotifyOnNextPrompt.HelpText" xml:space="preserve">
|
||||
<value>Choose how to be notified when a command finishes and a new prompt appears. Requires shell integration.</value>
|
||||
<comment>Help text for the notify on next prompt setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_NotifyOnNextPromptThreshold.Header" xml:space="preserve">
|
||||
<value>Minimum duration for the next prompt notification</value>
|
||||
<comment>Header for a numeric control that sets the minimum number of seconds a command must run before its completion triggers a "notify on next prompt" notification.</comment>
|
||||
</data>
|
||||
<data name="Profile_NotifyOnNextPromptThreshold.HelpText" xml:space="preserve">
|
||||
<value>Only notify when the command ran for at least this many seconds. Requires shell integration. Set to 0 to always notify.</value>
|
||||
<comment>Help text for the minimum duration threshold applied to "notify on next prompt" notifications.</comment>
|
||||
</data>
|
||||
<data name="Profile_AutoDetectRunningCommand.Header" xml:space="preserve">
|
||||
<value>Auto-detect running command</value>
|
||||
<comment>Header for a control to configure automatic detection of a running command's progress state.</comment>
|
||||
</data>
|
||||
<data name="Profile_AutoDetectRunningCommand.HelpText" xml:space="preserve">
|
||||
<value>Automatically show a progress indicator when a command is running. Requires shell integration.</value>
|
||||
<comment>Help text for the auto-detect running command setting.</comment>
|
||||
</data>
|
||||
<data name="Profile_BellStyleNotification.Content" xml:space="preserve">
|
||||
<value>Desktop notification</value>
|
||||
<comment>An option to choose from for the "bell style" setting. When selected, a Windows desktop notification (toast) is sent to notify the user.</comment>
|
||||
</data>
|
||||
<data name="ColorScheme_AddNewButton.Text" xml:space="preserve">
|
||||
<value>Add new</value>
|
||||
<comment>Button label that creates a new color scheme.</comment>
|
||||
@@ -2265,26 +2197,6 @@
|
||||
<value>Warn when closing more than one tab</value>
|
||||
<comment>Header for a control to toggle whether to show a confirm dialog box when closing the application with multiple tabs open.</comment>
|
||||
</data>
|
||||
<data name="Globals_ConfirmOnClose.Header" xml:space="preserve">
|
||||
<value>Warn when closing</value>
|
||||
<comment>Header for a dropdown controlling when to show a confirmation dialog before closing.</comment>
|
||||
</data>
|
||||
<data name="Globals_ConfirmOnClose.HelpText" xml:space="preserve">
|
||||
<value>Controls when a confirmation dialog appears before closing tabs or windows. "Always" presents the dialog when closing any pane.</value>
|
||||
<comment>Help text associated with Globals_ConfirmOnClose. "Always" refers to Globals_ConfirmOnCloseAlways.Content.</comment>
|
||||
</data>
|
||||
<data name="Globals_ConfirmOnCloseNever.Content" xml:space="preserve">
|
||||
<value>Never</value>
|
||||
<comment>Option associated with Globals_ConfirmOnClose. "Never" means that the system will never display a warning when closing.</comment>
|
||||
</data>
|
||||
<data name="Globals_ConfirmOnCloseAlways.Content" xml:space="preserve">
|
||||
<value>Always</value>
|
||||
<comment>Option associated with Globals_ConfirmOnClose. "Always" means that the system will always display a warning when closing.</comment>
|
||||
</data>
|
||||
<data name="Globals_ConfirmOnCloseAutomatic.Content" xml:space="preserve">
|
||||
<value>Multiple tabs or panes</value>
|
||||
<comment>Option associated with Globals_ConfirmOnClose. The system will display a warning when multiple tabs or panes are present.</comment>
|
||||
</data>
|
||||
<data name="Globals_InputServiceWarning.Header" xml:space="preserve">
|
||||
<value>Warn when "Touch Keyboard and Handwriting Panel Service" is disabled</value>
|
||||
</data>
|
||||
|
||||
@@ -43,7 +43,6 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
DEFINE_ENUM_MAP(Microsoft::Terminal::Control::TextMeasurement, TextMeasurement);
|
||||
DEFINE_ENUM_MAP(Microsoft::Terminal::Control::AmbiguousWidth, AmbiguousWidth);
|
||||
DEFINE_ENUM_MAP(Microsoft::Terminal::Control::WarnAboutMultiLinePaste, WarnAboutMultiLinePaste);
|
||||
DEFINE_ENUM_MAP(Model::ConfirmOnClose, ConfirmOnClose);
|
||||
|
||||
// Profile Settings
|
||||
DEFINE_ENUM_MAP(Model::CloseOnExitMode, CloseOnExitMode);
|
||||
|
||||
@@ -40,7 +40,6 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::Microsoft::Terminal::Control::TextMeasurement> TextMeasurement();
|
||||
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::Microsoft::Terminal::Control::AmbiguousWidth> AmbiguousWidth();
|
||||
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::Microsoft::Terminal::Control::WarnAboutMultiLinePaste> WarnAboutMultiLinePaste();
|
||||
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, ConfirmOnClose> ConfirmOnClose();
|
||||
|
||||
// Profile Settings
|
||||
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, CloseOnExitMode> CloseOnExitMode();
|
||||
|
||||
@@ -22,7 +22,6 @@ namespace Microsoft.Terminal.Settings.Model
|
||||
static Windows.Foundation.Collections.IMap<String, Microsoft.Terminal.Control.TextMeasurement> TextMeasurement { get; };
|
||||
static Windows.Foundation.Collections.IMap<String, Microsoft.Terminal.Control.AmbiguousWidth> AmbiguousWidth { get; };
|
||||
static Windows.Foundation.Collections.IMap<String, Microsoft.Terminal.Control.WarnAboutMultiLinePaste> WarnAboutMultiLinePaste { get; };
|
||||
static Windows.Foundation.Collections.IMap<String, Microsoft.Terminal.Settings.Model.ConfirmOnClose> ConfirmOnClose { get; };
|
||||
|
||||
// Profile Settings
|
||||
static Windows.Foundation.Collections.IMap<String, Microsoft.Terminal.Settings.Model.CloseOnExitMode> CloseOnExitMode { get; };
|
||||
|
||||
@@ -160,16 +160,7 @@ void GlobalAppSettings::LayerJson(const Json::Value& json, const OriginTag origi
|
||||
_fixupsAppliedDuringLoad = JsonUtils::GetValueForKey(json, LegacyInputServiceWarningKey, _InputServiceWarning) || _fixupsAppliedDuringLoad;
|
||||
_fixupsAppliedDuringLoad = JsonUtils::GetValueForKey(json, LegacyWarnAboutLargePasteKey, _WarnAboutLargePaste) || _fixupsAppliedDuringLoad;
|
||||
_fixupsAppliedDuringLoad = JsonUtils::GetValueForKey(json, LegacyWarnAboutMultiLinePasteKey, _WarnAboutMultiLinePaste) || _fixupsAppliedDuringLoad;
|
||||
// GH#6549 - Migrate legacy "confirmCloseAllTabs" boolean to the new
|
||||
// "confirmOnClose" enum. true -> Automatic, false -> Never.
|
||||
{
|
||||
std::optional<bool> legacyConfirmClose;
|
||||
if (JsonUtils::GetValueForKey(json, LegacyConfirmCloseAllTabsKey, legacyConfirmClose))
|
||||
{
|
||||
_ConfirmOnClose = legacyConfirmClose.value() ? ConfirmOnClose::Automatic : ConfirmOnClose::Never;
|
||||
_fixupsAppliedDuringLoad = true;
|
||||
}
|
||||
}
|
||||
_fixupsAppliedDuringLoad = JsonUtils::GetValueForKey(json, LegacyConfirmCloseAllTabsKey, _ConfirmCloseAllTabs) || _fixupsAppliedDuringLoad;
|
||||
|
||||
#define GLOBAL_SETTINGS_LAYER_JSON(type, name, jsonKey, ...) \
|
||||
JsonUtils::GetValueForKey(json, jsonKey, _##name); \
|
||||
|
||||
@@ -50,13 +50,6 @@ namespace Microsoft.Terminal.Settings.Model
|
||||
AfterCurrentTab,
|
||||
};
|
||||
|
||||
enum ConfirmOnClose
|
||||
{
|
||||
Never = 0,
|
||||
Automatic = 1,
|
||||
Always = 2,
|
||||
};
|
||||
|
||||
[default_interface] runtimeclass GlobalAppSettings {
|
||||
Guid DefaultProfile;
|
||||
|
||||
@@ -68,7 +61,7 @@ namespace Microsoft.Terminal.Settings.Model
|
||||
INHERITABLE_SETTING(Boolean, ShowTabsFullscreen);
|
||||
INHERITABLE_SETTING(NewTabPosition, NewTabPosition);
|
||||
INHERITABLE_SETTING(Boolean, ShowTitleInTitlebar);
|
||||
INHERITABLE_SETTING(ConfirmOnClose, ConfirmOnClose);
|
||||
INHERITABLE_SETTING(Boolean, ConfirmCloseAllTabs);
|
||||
INHERITABLE_SETTING(String, Language);
|
||||
INHERITABLE_SETTING(Microsoft.UI.Xaml.Controls.TabViewWidthMode, TabWidthMode);
|
||||
INHERITABLE_SETTING(Boolean, UseAcrylicInTabRow);
|
||||
|
||||
@@ -38,7 +38,7 @@ Author(s):
|
||||
X(bool, AlwaysShowTabs, "alwaysShowTabs", true) \
|
||||
X(Model::NewTabPosition, NewTabPosition, "newTabPosition", Model::NewTabPosition::AfterLastTab) \
|
||||
X(bool, ShowTitleInTitlebar, "showTerminalTitleInTitlebar", true) \
|
||||
X(Model::ConfirmOnClose, ConfirmOnClose, "warning.confirmOnClose", Model::ConfirmOnClose::Automatic) \
|
||||
X(bool, ConfirmCloseAllTabs, "warning.confirmCloseAllTabs", true) \
|
||||
X(Model::ThemePair, Theme, "theme") \
|
||||
X(hstring, Language, "language") \
|
||||
X(winrt::Microsoft::UI::Xaml::Controls::TabViewWidthMode, TabWidthMode, "tabWidthMode", winrt::Microsoft::UI::Xaml::Controls::TabViewWidthMode::Equal) \
|
||||
@@ -79,42 +79,37 @@ Author(s):
|
||||
// * TerminalSettings.cpp: TerminalSettings::_ApplyProfileSettings
|
||||
// * IControlSettings.idl or ICoreSettings.idl
|
||||
// * ControlProperties.h
|
||||
#define MTSM_PROFILE_SETTINGS(X) \
|
||||
X(int32_t, HistorySize, "historySize", DEFAULT_HISTORY_SIZE) \
|
||||
X(bool, SnapOnInput, "snapOnInput", true) \
|
||||
X(bool, AltGrAliasing, "altGrAliasing", true) \
|
||||
X(hstring, AnswerbackMessage, "answerbackMessage") \
|
||||
X(hstring, Commandline, "commandline", L"%SystemRoot%\\System32\\cmd.exe") \
|
||||
X(Microsoft::Terminal::Control::ScrollbarState, ScrollState, "scrollbarState", Microsoft::Terminal::Control::ScrollbarState::Visible) \
|
||||
X(Microsoft::Terminal::Control::TextAntialiasingMode, AntialiasingMode, "antialiasingMode", Microsoft::Terminal::Control::TextAntialiasingMode::Grayscale) \
|
||||
X(hstring, StartingDirectory, "startingDirectory") \
|
||||
X(IMediaResource, Icon, "icon", implementation::MediaResource::FromString(L"\uE756")) \
|
||||
X(bool, SuppressApplicationTitle, "suppressApplicationTitle", false) \
|
||||
X(guid, ConnectionType, "connectionType") \
|
||||
X(CloseOnExitMode, CloseOnExit, "closeOnExit", CloseOnExitMode::Automatic) \
|
||||
X(hstring, TabTitle, "tabTitle") \
|
||||
X(Model::BellStyle, BellStyle, "bellStyle", BellStyle::Audible) \
|
||||
X(IEnvironmentVariableMap, EnvironmentVariables, "environment", nullptr) \
|
||||
X(bool, RightClickContextMenu, "rightClickContextMenu", false) \
|
||||
X(Windows::Foundation::Collections::IVector<IMediaResource>, BellSound, "bellSound", nullptr) \
|
||||
X(bool, Elevate, "elevate", false) \
|
||||
X(bool, AutoMarkPrompts, "autoMarkPrompts", true) \
|
||||
X(bool, ShowMarks, "showMarksOnScrollbar", false) \
|
||||
X(bool, RepositionCursorWithMouse, "experimental.repositionCursorWithMouse", false) \
|
||||
X(bool, ReloadEnvironmentVariables, "compatibility.reloadEnvironmentVariables", true) \
|
||||
X(bool, RainbowSuggestions, "experimental.rainbowSuggestions", false) \
|
||||
X(bool, ForceVTInput, "compatibility.input.forceVT", false) \
|
||||
X(bool, AllowKittyKeyboardMode, "compatibility.kittyKeyboardMode", true) \
|
||||
X(bool, AllowVtChecksumReport, "compatibility.allowDECRQCRA", false) \
|
||||
X(bool, AllowVtClipboardWrite, "compatibility.allowOSC52", true) \
|
||||
X(bool, AllowKeypadMode, "compatibility.allowDECNKM", false) \
|
||||
X(hstring, DragDropDelimiter, "dragDropDelimiter", L" ") \
|
||||
X(Microsoft::Terminal::Control::PathTranslationStyle, PathTranslationStyle, "pathTranslationStyle", Microsoft::Terminal::Control::PathTranslationStyle::None) \
|
||||
X(Microsoft::Terminal::Control::OutputNotificationStyle, NotifyOnActivity, "notifyOnActivity", Microsoft::Terminal::Control::OutputNotificationStyle::None) \
|
||||
X(Microsoft::Terminal::Control::OutputNotificationStyle, NotifyOnNextPrompt, "notifyOnNextPrompt", Microsoft::Terminal::Control::OutputNotificationStyle::None) \
|
||||
X(int32_t, NotifyOnActivityThreshold, "notifyOnActivityThreshold", 5) \
|
||||
X(int32_t, NotifyOnNextPromptThreshold, "notifyOnNextPromptThreshold", 5) \
|
||||
X(bool, AutoDetectRunningCommand, "autoDetectRunningCommand", false)
|
||||
#define MTSM_PROFILE_SETTINGS(X) \
|
||||
X(int32_t, HistorySize, "historySize", DEFAULT_HISTORY_SIZE) \
|
||||
X(bool, SnapOnInput, "snapOnInput", true) \
|
||||
X(bool, AltGrAliasing, "altGrAliasing", true) \
|
||||
X(hstring, AnswerbackMessage, "answerbackMessage") \
|
||||
X(hstring, Commandline, "commandline", L"%SystemRoot%\\System32\\cmd.exe") \
|
||||
X(Microsoft::Terminal::Control::ScrollbarState, ScrollState, "scrollbarState", Microsoft::Terminal::Control::ScrollbarState::Visible) \
|
||||
X(Microsoft::Terminal::Control::TextAntialiasingMode, AntialiasingMode, "antialiasingMode", Microsoft::Terminal::Control::TextAntialiasingMode::Grayscale) \
|
||||
X(hstring, StartingDirectory, "startingDirectory") \
|
||||
X(IMediaResource, Icon, "icon", implementation::MediaResource::FromString(L"\uE756")) \
|
||||
X(bool, SuppressApplicationTitle, "suppressApplicationTitle", false) \
|
||||
X(guid, ConnectionType, "connectionType") \
|
||||
X(CloseOnExitMode, CloseOnExit, "closeOnExit", CloseOnExitMode::Automatic) \
|
||||
X(hstring, TabTitle, "tabTitle") \
|
||||
X(Model::BellStyle, BellStyle, "bellStyle", BellStyle::Audible) \
|
||||
X(IEnvironmentVariableMap, EnvironmentVariables, "environment", nullptr) \
|
||||
X(bool, RightClickContextMenu, "rightClickContextMenu", false) \
|
||||
X(Windows::Foundation::Collections::IVector<IMediaResource>, BellSound, "bellSound", nullptr) \
|
||||
X(bool, Elevate, "elevate", false) \
|
||||
X(bool, AutoMarkPrompts, "autoMarkPrompts", true) \
|
||||
X(bool, ShowMarks, "showMarksOnScrollbar", false) \
|
||||
X(bool, RepositionCursorWithMouse, "experimental.repositionCursorWithMouse", false) \
|
||||
X(bool, ReloadEnvironmentVariables, "compatibility.reloadEnvironmentVariables", true) \
|
||||
X(bool, RainbowSuggestions, "experimental.rainbowSuggestions", false) \
|
||||
X(bool, ForceVTInput, "compatibility.input.forceVT", false) \
|
||||
X(bool, AllowKittyKeyboardMode, "compatibility.kittyKeyboardMode", true) \
|
||||
X(bool, AllowVtChecksumReport, "compatibility.allowDECRQCRA", false) \
|
||||
X(bool, AllowVtClipboardWrite, "compatibility.allowOSC52", true) \
|
||||
X(bool, AllowKeypadMode, "compatibility.allowDECNKM", false) \
|
||||
X(hstring, DragDropDelimiter, "dragDropDelimiter", L" ") \
|
||||
X(Microsoft::Terminal::Control::PathTranslationStyle, PathTranslationStyle, "pathTranslationStyle", Microsoft::Terminal::Control::PathTranslationStyle::None)
|
||||
|
||||
// Intentionally omitted Profile settings:
|
||||
// * Name
|
||||
|
||||
@@ -29,7 +29,6 @@ namespace Microsoft.Terminal.Settings.Model
|
||||
Audible = 0x1,
|
||||
Window = 0x2,
|
||||
Taskbar = 0x4,
|
||||
Notification = 0x8,
|
||||
All = 0xffffffff
|
||||
};
|
||||
|
||||
@@ -96,10 +95,5 @@ namespace Microsoft.Terminal.Settings.Model
|
||||
|
||||
INHERITABLE_PROFILE_SETTING(Microsoft.Terminal.Control.PathTranslationStyle, PathTranslationStyle);
|
||||
INHERITABLE_PROFILE_SETTING(String, DragDropDelimiter);
|
||||
INHERITABLE_PROFILE_SETTING(Microsoft.Terminal.Control.OutputNotificationStyle, NotifyOnActivity);
|
||||
INHERITABLE_PROFILE_SETTING(Microsoft.Terminal.Control.OutputNotificationStyle, NotifyOnNextPrompt);
|
||||
INHERITABLE_PROFILE_SETTING(Int32, NotifyOnActivityThreshold);
|
||||
INHERITABLE_PROFILE_SETTING(Int32, NotifyOnNextPromptThreshold);
|
||||
INHERITABLE_PROFILE_SETTING(Boolean, AutoDetectRunningCommand);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -702,7 +702,7 @@
|
||||
<comment>When enabled, input will go to all panes in this tab simultaneously</comment>
|
||||
</data>
|
||||
<data name="RestartConnectionKey" xml:space="preserve">
|
||||
<value>Restart session</value>
|
||||
<value>Restart connection</value>
|
||||
</data>
|
||||
<data name="OpenScratchpadKey" xml:space="preserve">
|
||||
<value>Open scratchpad</value>
|
||||
|
||||
@@ -88,34 +88,14 @@ JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Core::MatchMode)
|
||||
};
|
||||
};
|
||||
|
||||
JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Settings::Model::ConfirmOnClose)
|
||||
{
|
||||
JSON_MAPPINGS(3) = {
|
||||
pair_type{ "never", ValueType::Never },
|
||||
pair_type{ "automatic", ValueType::Automatic },
|
||||
pair_type{ "always", ValueType::Always },
|
||||
};
|
||||
|
||||
auto FromJson(const Json::Value& json)
|
||||
{
|
||||
return BaseEnumMapper::FromJson(json);
|
||||
}
|
||||
|
||||
bool CanConvert(const Json::Value& json)
|
||||
{
|
||||
return BaseEnumMapper::CanConvert(json);
|
||||
}
|
||||
};
|
||||
|
||||
JSON_FLAG_MAPPER(::winrt::Microsoft::Terminal::Settings::Model::BellStyle)
|
||||
{
|
||||
static constexpr std::array<pair_type, 7> mappings = {
|
||||
static constexpr std::array<pair_type, 6> mappings = {
|
||||
pair_type{ "none", AllClear },
|
||||
pair_type{ "audible", ValueType::Audible },
|
||||
pair_type{ "visual", ValueType::Window | ValueType::Taskbar },
|
||||
pair_type{ "window", ValueType::Window },
|
||||
pair_type{ "taskbar", ValueType::Taskbar },
|
||||
pair_type{ "notification", ValueType::Notification },
|
||||
pair_type{ "all", AllSet },
|
||||
};
|
||||
|
||||
@@ -139,37 +119,6 @@ JSON_FLAG_MAPPER(::winrt::Microsoft::Terminal::Settings::Model::BellStyle)
|
||||
}
|
||||
};
|
||||
|
||||
JSON_FLAG_MAPPER(::winrt::Microsoft::Terminal::Control::OutputNotificationStyle)
|
||||
{
|
||||
static constexpr std::array<pair_type, 6> mappings = {
|
||||
pair_type{ "none", AllClear },
|
||||
pair_type{ "taskbar", ValueType::Taskbar },
|
||||
pair_type{ "audible", ValueType::Audible },
|
||||
pair_type{ "tab", ValueType::Tab },
|
||||
pair_type{ "notification", ValueType::Notification },
|
||||
pair_type{ "all", AllSet },
|
||||
};
|
||||
|
||||
auto FromJson(const Json::Value& json)
|
||||
{
|
||||
if (json.isBool())
|
||||
{
|
||||
return json.asBool() ? ValueType::Tab : AllClear;
|
||||
}
|
||||
return BaseFlagMapper::FromJson(json);
|
||||
}
|
||||
|
||||
bool CanConvert(const Json::Value& json)
|
||||
{
|
||||
return BaseFlagMapper::CanConvert(json) || json.isBool();
|
||||
}
|
||||
|
||||
Json::Value ToJson(const ::winrt::Microsoft::Terminal::Control::OutputNotificationStyle& style)
|
||||
{
|
||||
return BaseFlagMapper::ToJson(style);
|
||||
}
|
||||
};
|
||||
|
||||
JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Settings::Model::ConvergedAlignment)
|
||||
{
|
||||
// reduce repetition
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
"showAdminShield": true,
|
||||
|
||||
// Miscellaneous
|
||||
"warning.confirmOnClose": "automatic",
|
||||
"confirmCloseAllTabs": true,
|
||||
"theme": "dark",
|
||||
"snapToGridOnResize": true,
|
||||
"disableAnimations": false,
|
||||
|
||||
@@ -1843,15 +1843,6 @@ namespace SettingsModelUnitTests
|
||||
VERIFY_ARE_EQUAL(settings->ProfileDefaults().HasTabTitle(), copyImpl->ProfileDefaults().HasTabTitle());
|
||||
VERIFY_ARE_NOT_EQUAL(settings->ProfileDefaults().TabTitle(), copyImpl->ProfileDefaults().TabTitle());
|
||||
|
||||
// Verify HasXxx independence: setting a previously-inherited value on the clone
|
||||
// should make HasXxx true on the clone but remain false on the original.
|
||||
// SnapOnInput is not set in the JSON, so both should inherit the default.
|
||||
VERIFY_IS_FALSE(settings->AllProfiles().GetAt(0).HasSnapOnInput());
|
||||
VERIFY_IS_FALSE(copyImpl->AllProfiles().GetAt(0).HasSnapOnInput());
|
||||
copyImpl->AllProfiles().GetAt(0).SnapOnInput(false);
|
||||
VERIFY_IS_FALSE(settings->AllProfiles().GetAt(0).HasSnapOnInput());
|
||||
VERIFY_IS_TRUE(copyImpl->AllProfiles().GetAt(0).HasSnapOnInput());
|
||||
|
||||
Log::Comment(L"Test empty profiles.defaults");
|
||||
static constexpr std::string_view emptyPDJson{ R"(
|
||||
{
|
||||
|
||||
@@ -31,10 +31,6 @@ namespace SettingsModelUnitTests
|
||||
TEST_METHOD(TestGenGuidsForProfiles);
|
||||
TEST_METHOD(TestCorrectOldDefaultShellPaths);
|
||||
TEST_METHOD(ProfileDefaultsProhibitedSettings);
|
||||
|
||||
TEST_METHOD(SettingInheritanceFallback);
|
||||
TEST_METHOD(ClearSettingRestoresInheritance);
|
||||
TEST_METHOD(HasSettingAtSpecificLayer);
|
||||
};
|
||||
|
||||
void ProfileTests::ProfileGeneratesGuid()
|
||||
@@ -536,130 +532,4 @@ namespace SettingsModelUnitTests
|
||||
VERIFY_ARE_NOT_EQUAL(L"Default Profile Source", allProfiles.GetAt(2).Source());
|
||||
VERIFY_ARE_NOT_EQUAL(L"foo.exe", allProfiles.GetAt(2).Commandline());
|
||||
}
|
||||
|
||||
void ProfileTests::SettingInheritanceFallback()
|
||||
{
|
||||
// Verify that when no layer defines a setting, the default value is used.
|
||||
// Also verify that when only user defaults defines it, profiles inherit from there.
|
||||
static constexpr std::string_view userSettings{ R"({
|
||||
"profiles": {
|
||||
"defaults": {
|
||||
"historySize": 5000
|
||||
},
|
||||
"list": [
|
||||
{
|
||||
"name": "profile0",
|
||||
"guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}"
|
||||
},
|
||||
{
|
||||
"name": "profile1",
|
||||
"guid": "{6239a42c-1111-49a3-80bd-e8fdd045185c}",
|
||||
"snapOnInput": false
|
||||
}
|
||||
]
|
||||
}
|
||||
})" };
|
||||
|
||||
const auto settings = winrt::make_self<implementation::CascadiaSettings>(userSettings);
|
||||
const auto allProfiles = settings->AllProfiles();
|
||||
|
||||
VERIFY_ARE_EQUAL(2u, allProfiles.Size());
|
||||
|
||||
// profile0: historySize inherited from defaults
|
||||
VERIFY_ARE_EQUAL(5000, allProfiles.GetAt(0).HistorySize());
|
||||
// profile0: snapOnInput not set anywhere, falls back to default (true)
|
||||
VERIFY_ARE_EQUAL(true, allProfiles.GetAt(0).SnapOnInput());
|
||||
|
||||
// profile1: historySize inherited from defaults
|
||||
VERIFY_ARE_EQUAL(5000, allProfiles.GetAt(1).HistorySize());
|
||||
// profile1: snapOnInput explicitly set to false
|
||||
VERIFY_ARE_EQUAL(false, allProfiles.GetAt(1).SnapOnInput());
|
||||
}
|
||||
|
||||
void ProfileTests::ClearSettingRestoresInheritance()
|
||||
{
|
||||
// Verify that clearing a setting at the profile layer causes it to
|
||||
// fall back to the parent's value.
|
||||
static constexpr std::string_view parentString{ R"({
|
||||
"name": "parent",
|
||||
"guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
|
||||
"historySize": 1000,
|
||||
"tabTitle": "ParentTitle"
|
||||
})" };
|
||||
static constexpr std::string_view childString{ R"({
|
||||
"name": "child",
|
||||
"guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
|
||||
"historySize": 2000,
|
||||
"tabTitle": "ChildTitle"
|
||||
})" };
|
||||
|
||||
const auto parentJson = VerifyParseSucceeded(parentString);
|
||||
const auto childJson = VerifyParseSucceeded(childString);
|
||||
|
||||
auto parent = implementation::Profile::FromJson(parentJson);
|
||||
auto child = parent->CreateChild();
|
||||
child->LayerJson(childJson);
|
||||
|
||||
// Verify child has its own values
|
||||
VERIFY_ARE_EQUAL(2000, child->HistorySize());
|
||||
VERIFY_ARE_EQUAL(L"ChildTitle", child->TabTitle());
|
||||
VERIFY_IS_TRUE(child->HasHistorySize());
|
||||
VERIFY_IS_TRUE(child->HasTabTitle());
|
||||
|
||||
// Clear historySize on child: should fall back to parent
|
||||
child->ClearHistorySize();
|
||||
VERIFY_IS_FALSE(child->HasHistorySize());
|
||||
VERIFY_ARE_EQUAL(1000, child->HistorySize());
|
||||
|
||||
// Clear tabTitle on child: should fall back to parent
|
||||
child->ClearTabTitle();
|
||||
VERIFY_IS_FALSE(child->HasTabTitle());
|
||||
VERIFY_ARE_EQUAL(L"ParentTitle", child->TabTitle());
|
||||
}
|
||||
|
||||
void ProfileTests::HasSettingAtSpecificLayer()
|
||||
{
|
||||
// Verify that HasXxx() correctly reports whether a setting is defined
|
||||
// at the current layer vs inherited from a parent.
|
||||
static constexpr std::string_view userSettings{ R"({
|
||||
"profiles": {
|
||||
"defaults": {
|
||||
"historySize": 5000,
|
||||
"tabTitle": "DefaultTitle"
|
||||
},
|
||||
"list": [
|
||||
{
|
||||
"name": "profile0",
|
||||
"guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
|
||||
"historySize": 9001
|
||||
},
|
||||
{
|
||||
"name": "profile1",
|
||||
"guid": "{6239a42c-1111-49a3-80bd-e8fdd045185c}"
|
||||
}
|
||||
]
|
||||
}
|
||||
})" };
|
||||
|
||||
const auto settings = winrt::make_self<implementation::CascadiaSettings>(userSettings);
|
||||
const auto allProfiles = settings->AllProfiles();
|
||||
|
||||
VERIFY_ARE_EQUAL(2u, allProfiles.Size());
|
||||
|
||||
// profile0: historySize is explicitly set
|
||||
VERIFY_IS_TRUE(allProfiles.GetAt(0).HasHistorySize());
|
||||
VERIFY_ARE_EQUAL(9001, allProfiles.GetAt(0).HistorySize());
|
||||
|
||||
// profile0: tabTitle is NOT set at this layer (inherited from defaults)
|
||||
VERIFY_IS_FALSE(allProfiles.GetAt(0).HasTabTitle());
|
||||
VERIFY_ARE_EQUAL(L"DefaultTitle", allProfiles.GetAt(0).TabTitle());
|
||||
|
||||
// profile1: historySize is NOT set at this layer (inherited from defaults)
|
||||
VERIFY_IS_FALSE(allProfiles.GetAt(1).HasHistorySize());
|
||||
VERIFY_ARE_EQUAL(5000, allProfiles.GetAt(1).HistorySize());
|
||||
|
||||
// ProfileDefaults: historySize is set
|
||||
VERIFY_IS_TRUE(settings->ProfileDefaults().HasHistorySize());
|
||||
VERIFY_ARE_EQUAL(5000, settings->ProfileDefaults().HistorySize());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,12 +60,6 @@ namespace SettingsModelUnitTests
|
||||
|
||||
TEST_METHOD(ProfileWithInvalidIcon);
|
||||
|
||||
TEST_METHOD(ModifyProfileSettingAndRoundtrip);
|
||||
TEST_METHOD(ModifyGlobalSettingAndRoundtrip);
|
||||
TEST_METHOD(ModifyColorSchemeAndRoundtrip);
|
||||
TEST_METHOD(FixupUserSettingsDetectsChanges);
|
||||
TEST_METHOD(FixupCommandlinePatching);
|
||||
|
||||
private:
|
||||
// Method Description:
|
||||
// - deserializes and reserializes a json string representing a settings object model of type T
|
||||
@@ -131,7 +125,7 @@ namespace SettingsModelUnitTests
|
||||
|
||||
"trimPaste": true,
|
||||
|
||||
"warning.confirmOnClose": "automatic",
|
||||
"warning.confirmCloseAllTabs" : true,
|
||||
"warning.inputService" : true,
|
||||
"warning.largePaste" : true,
|
||||
"warning.multiLinePaste" : "automatic",
|
||||
@@ -1331,288 +1325,4 @@ namespace SettingsModelUnitTests
|
||||
// what was written in the settings file.
|
||||
VERIFY_ARE_EQUAL(R"(c:\this_icon_had_better_not_exist.tiff)", newResult["profiles"]["list"][0]["icon"].asString());
|
||||
}
|
||||
|
||||
void SerializationTests::ModifyProfileSettingAndRoundtrip()
|
||||
{
|
||||
// Load settings, modify a profile setting via setter, serialize,
|
||||
// and verify the JSON output reflects the change.
|
||||
static constexpr std::string_view settingsJson{ R"(
|
||||
{
|
||||
"defaultProfile": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
|
||||
"profiles": [
|
||||
{
|
||||
"name": "profile0",
|
||||
"guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
|
||||
"historySize": 1000,
|
||||
"commandline": "cmd.exe"
|
||||
}
|
||||
]
|
||||
})" };
|
||||
|
||||
const auto settings{ winrt::make_self<implementation::CascadiaSettings>(settingsJson) };
|
||||
|
||||
// Verify initial value
|
||||
VERIFY_ARE_EQUAL(1000, settings->AllProfiles().GetAt(0).HistorySize());
|
||||
|
||||
// Modify the setting
|
||||
settings->AllProfiles().GetAt(0).HistorySize(5000);
|
||||
VERIFY_ARE_EQUAL(5000, settings->AllProfiles().GetAt(0).HistorySize());
|
||||
|
||||
// Serialize and verify the change is reflected in JSON
|
||||
const auto result{ settings->ToJson() };
|
||||
VERIFY_ARE_EQUAL(5000, result["profiles"]["list"][0]["historySize"].asInt());
|
||||
|
||||
// Verify other settings are preserved
|
||||
VERIFY_ARE_EQUAL("cmd.exe", result["profiles"]["list"][0]["commandline"].asString());
|
||||
|
||||
// Also verify: modify a setting that wasn't previously set
|
||||
settings->AllProfiles().GetAt(0).TabTitle(L"NewTitle");
|
||||
const auto result2{ settings->ToJson() };
|
||||
VERIFY_ARE_EQUAL("NewTitle", result2["profiles"]["list"][0]["tabTitle"].asString());
|
||||
}
|
||||
|
||||
void SerializationTests::ModifyGlobalSettingAndRoundtrip()
|
||||
{
|
||||
// Load settings, modify a global setting, serialize, verify JSON.
|
||||
static constexpr std::string_view settingsJson{ R"(
|
||||
{
|
||||
"defaultProfile": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
|
||||
"initialRows": 30,
|
||||
"alwaysOnTop": false,
|
||||
"profiles": [
|
||||
{
|
||||
"name": "profile0",
|
||||
"guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}"
|
||||
}
|
||||
]
|
||||
})" };
|
||||
|
||||
const auto settings{ winrt::make_self<implementation::CascadiaSettings>(settingsJson) };
|
||||
|
||||
// Verify initial values
|
||||
VERIFY_ARE_EQUAL(30, settings->GlobalSettings().InitialRows());
|
||||
VERIFY_ARE_EQUAL(false, settings->GlobalSettings().AlwaysOnTop());
|
||||
|
||||
// Modify global settings
|
||||
settings->GlobalSettings().InitialRows(50);
|
||||
settings->GlobalSettings().AlwaysOnTop(true);
|
||||
|
||||
// Verify in-memory changes
|
||||
VERIFY_ARE_EQUAL(50, settings->GlobalSettings().InitialRows());
|
||||
VERIFY_ARE_EQUAL(true, settings->GlobalSettings().AlwaysOnTop());
|
||||
|
||||
// Serialize and verify
|
||||
const auto result{ settings->ToJson() };
|
||||
VERIFY_ARE_EQUAL(50, result["initialRows"].asInt());
|
||||
VERIFY_ARE_EQUAL(true, result["alwaysOnTop"].asBool());
|
||||
}
|
||||
|
||||
void SerializationTests::ModifyColorSchemeAndRoundtrip()
|
||||
{
|
||||
// Load settings with a user color scheme, modify it, serialize, verify.
|
||||
static constexpr std::string_view settingsJson{ R"(
|
||||
{
|
||||
"defaultProfile": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
|
||||
"profiles": [
|
||||
{
|
||||
"name": "profile0",
|
||||
"guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}"
|
||||
}
|
||||
],
|
||||
"schemes": [
|
||||
{
|
||||
"name": "MyScheme",
|
||||
"foreground": "#CCCCCC",
|
||||
"background": "#0C0C0C",
|
||||
"cursorColor": "#FFFFFF",
|
||||
"black": "#0C0C0C",
|
||||
"red": "#C50F1F",
|
||||
"green": "#13A10E",
|
||||
"yellow": "#C19C00",
|
||||
"blue": "#0037DA",
|
||||
"purple": "#881798",
|
||||
"cyan": "#3A96DD",
|
||||
"white": "#CCCCCC",
|
||||
"brightBlack": "#767676",
|
||||
"brightRed": "#E74856",
|
||||
"brightGreen": "#16C60C",
|
||||
"brightYellow": "#F9F1A5",
|
||||
"brightBlue": "#3B78FF",
|
||||
"brightPurple": "#B4009E",
|
||||
"brightCyan": "#61D6D6",
|
||||
"brightWhite": "#F2F2F2"
|
||||
}
|
||||
]
|
||||
})" };
|
||||
|
||||
const auto settings{ winrt::make_self<implementation::CascadiaSettings>(settingsJson) };
|
||||
|
||||
// Find and modify the color scheme
|
||||
const auto schemes = settings->GlobalSettings().ColorSchemes();
|
||||
VERIFY_IS_TRUE(schemes.HasKey(L"MyScheme"));
|
||||
auto myScheme = schemes.Lookup(L"MyScheme");
|
||||
|
||||
const auto origForeground = myScheme.Foreground();
|
||||
myScheme.Foreground(til::color{ 0xAA, 0xBB, 0xCC });
|
||||
|
||||
// Serialize and verify the change persists
|
||||
const auto result{ settings->ToJson() };
|
||||
const auto& schemesJson = result["schemes"];
|
||||
bool found = false;
|
||||
for (const auto& scheme : schemesJson)
|
||||
{
|
||||
if (scheme["name"].asString() == "MyScheme")
|
||||
{
|
||||
VERIFY_ARE_EQUAL("#AABBCC", scheme["foreground"].asString());
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
VERIFY_IS_TRUE(found, L"MyScheme should be present in serialized output");
|
||||
}
|
||||
|
||||
void SerializationTests::FixupUserSettingsDetectsChanges()
|
||||
{
|
||||
// Verify that FixupUserSettings returns true when settings need
|
||||
// to be written back (e.g., migration), and false when clean.
|
||||
static constexpr std::string_view cleanSettingsJson{ R"(
|
||||
{
|
||||
"defaultProfile": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
|
||||
"profiles": [
|
||||
{
|
||||
"name": "profile0",
|
||||
"guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
|
||||
"commandline": "cmd.exe"
|
||||
}
|
||||
]
|
||||
})" };
|
||||
|
||||
// Load, fixup, serialize. Reload and verify fixup returns false.
|
||||
implementation::SettingsLoader loader1{ cleanSettingsJson, implementation::LoadStringResource(IDR_DEFAULTS) };
|
||||
loader1.MergeInboxIntoUserSettings();
|
||||
loader1.FinalizeLayering();
|
||||
loader1.FixupUserSettings();
|
||||
const auto settings1 = winrt::make_self<implementation::CascadiaSettings>(std::move(loader1));
|
||||
const auto result1{ settings1->ToJson() };
|
||||
|
||||
// Reload from the serialized output (should be stable)
|
||||
implementation::SettingsLoader loader2{ toString(result1), implementation::LoadStringResource(IDR_DEFAULTS) };
|
||||
loader2.MergeInboxIntoUserSettings();
|
||||
loader2.FinalizeLayering();
|
||||
const auto fixupNeeded = loader2.FixupUserSettings();
|
||||
|
||||
// After a clean roundtrip, no further fixups should be needed
|
||||
VERIFY_IS_FALSE(fixupNeeded, L"A clean roundtrip should not require further fixups");
|
||||
}
|
||||
|
||||
void SerializationTests::FixupCommandlinePatching()
|
||||
{
|
||||
// Verify that FixupUserSettings patches "cmd.exe" to the full path
|
||||
// for the Command Prompt profile, and "powershell.exe" for the
|
||||
// Windows PowerShell profile, and returns true to indicate changes.
|
||||
|
||||
// Case 1: CMD profile with short commandline should be patched
|
||||
static constexpr std::string_view cmdSettingsJson{ R"(
|
||||
{
|
||||
"defaultProfile": "{0caa0dad-35be-5f56-a8ff-afceeeaa6101}",
|
||||
"profiles": [
|
||||
{
|
||||
"name": "Command Prompt",
|
||||
"guid": "{0caa0dad-35be-5f56-a8ff-afceeeaa6101}",
|
||||
"commandline": "cmd.exe"
|
||||
}
|
||||
]
|
||||
})" };
|
||||
|
||||
{
|
||||
implementation::SettingsLoader loader{ cmdSettingsJson, implementation::LoadStringResource(IDR_DEFAULTS) };
|
||||
loader.MergeInboxIntoUserSettings();
|
||||
loader.FinalizeLayering();
|
||||
const auto fixupNeeded = loader.FixupUserSettings();
|
||||
VERIFY_IS_TRUE(fixupNeeded, L"FixupUserSettings should return true when cmd.exe is patched");
|
||||
|
||||
const auto settings = winrt::make_self<implementation::CascadiaSettings>(std::move(loader));
|
||||
const auto cmdProfile = settings->FindProfile(Utils::GuidFromString(L"{0caa0dad-35be-5f56-a8ff-afceeeaa6101}"));
|
||||
VERIFY_IS_NOT_NULL(cmdProfile);
|
||||
VERIFY_ARE_EQUAL(L"%SystemRoot%\\System32\\cmd.exe", cmdProfile.Commandline());
|
||||
}
|
||||
|
||||
// Case 2: PowerShell profile with short commandline should be patched
|
||||
static constexpr std::string_view psSettingsJson{ R"(
|
||||
{
|
||||
"defaultProfile": "{61c54bbd-c2c6-5271-96e7-009a87ff44bf}",
|
||||
"profiles": [
|
||||
{
|
||||
"name": "Windows PowerShell",
|
||||
"guid": "{61c54bbd-c2c6-5271-96e7-009a87ff44bf}",
|
||||
"commandline": "powershell.exe"
|
||||
}
|
||||
]
|
||||
})" };
|
||||
|
||||
{
|
||||
implementation::SettingsLoader loader{ psSettingsJson, implementation::LoadStringResource(IDR_DEFAULTS) };
|
||||
loader.MergeInboxIntoUserSettings();
|
||||
loader.FinalizeLayering();
|
||||
const auto fixupNeeded = loader.FixupUserSettings();
|
||||
VERIFY_IS_TRUE(fixupNeeded, L"FixupUserSettings should return true when powershell.exe is patched");
|
||||
|
||||
const auto settings = winrt::make_self<implementation::CascadiaSettings>(std::move(loader));
|
||||
const auto psProfile = settings->FindProfile(Utils::GuidFromString(L"{61c54bbd-c2c6-5271-96e7-009a87ff44bf}"));
|
||||
VERIFY_IS_NOT_NULL(psProfile);
|
||||
VERIFY_ARE_EQUAL(L"%SystemRoot%\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", psProfile.Commandline());
|
||||
}
|
||||
|
||||
// Case 3: CMD profile with the full path should NOT trigger fixup
|
||||
static constexpr std::string_view cleanCmdSettingsJson{ R"(
|
||||
{
|
||||
"defaultProfile": "{0caa0dad-35be-5f56-a8ff-afceeeaa6101}",
|
||||
"profiles": [
|
||||
{
|
||||
"name": "Command Prompt",
|
||||
"guid": "{0caa0dad-35be-5f56-a8ff-afceeeaa6101}"
|
||||
}
|
||||
]
|
||||
})" };
|
||||
|
||||
{
|
||||
implementation::SettingsLoader loader{ cleanCmdSettingsJson, implementation::LoadStringResource(IDR_DEFAULTS) };
|
||||
loader.MergeInboxIntoUserSettings();
|
||||
loader.FinalizeLayering();
|
||||
const auto fixupNeeded = loader.FixupUserSettings();
|
||||
VERIFY_IS_FALSE(fixupNeeded, L"FixupUserSettings should return false when no patching is needed");
|
||||
|
||||
const auto settings = winrt::make_self<implementation::CascadiaSettings>(std::move(loader));
|
||||
const auto cmdProfile = settings->FindProfile(Utils::GuidFromString(L"{0caa0dad-35be-5f56-a8ff-afceeeaa6101}"));
|
||||
VERIFY_IS_NOT_NULL(cmdProfile);
|
||||
// Should still resolve to the full path via inbox defaults
|
||||
VERIFY_ARE_EQUAL(L"%SystemRoot%\\System32\\cmd.exe", cmdProfile.Commandline());
|
||||
}
|
||||
|
||||
// Case 4: A non-builtin profile with "cmd.exe" should NOT be patched
|
||||
static constexpr std::string_view customCmdSettingsJson{ R"(
|
||||
{
|
||||
"defaultProfile": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
|
||||
"profiles": [
|
||||
{
|
||||
"name": "My Custom CMD",
|
||||
"guid": "{6239a42c-0000-49a3-80bd-e8fdd045185c}",
|
||||
"commandline": "cmd.exe"
|
||||
}
|
||||
]
|
||||
})" };
|
||||
|
||||
{
|
||||
implementation::SettingsLoader loader{ customCmdSettingsJson, implementation::LoadStringResource(IDR_DEFAULTS) };
|
||||
loader.MergeInboxIntoUserSettings();
|
||||
loader.FinalizeLayering();
|
||||
loader.FixupUserSettings();
|
||||
|
||||
const auto settings = winrt::make_self<implementation::CascadiaSettings>(std::move(loader));
|
||||
const auto customProfile = settings->FindProfile(Utils::GuidFromString(L"{6239a42c-0000-49a3-80bd-e8fdd045185c}"));
|
||||
VERIFY_IS_NOT_NULL(customProfile);
|
||||
// Custom profile should keep "cmd.exe" unchanged
|
||||
VERIFY_ARE_EQUAL(L"cmd.exe", customProfile.Commandline());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -265,68 +265,66 @@ void TerminalCoreUnitTests::TerminalApiTest::SetTaskbarProgress()
|
||||
|
||||
auto& stateMachine = *(term._stateMachine);
|
||||
|
||||
using TaskbarState = ::Microsoft::Console::VirtualTerminal::DispatchTypes::TaskbarState;
|
||||
|
||||
// Initial values for taskbar state and progress should be 0
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarState(), TaskbarState::Clear);
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(0));
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(0));
|
||||
|
||||
// Set some values for taskbar state and progress through state machine
|
||||
stateMachine.ProcessString(L"\x1b]9;4;1;50\x1b\\");
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarState(), TaskbarState::Set);
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(1));
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(50));
|
||||
|
||||
// Reset to 0
|
||||
stateMachine.ProcessString(L"\x1b]9;4;0;0\x1b\\");
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarState(), TaskbarState::Clear);
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(0));
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(0));
|
||||
|
||||
// Set an out of bounds value for state
|
||||
stateMachine.ProcessString(L"\x1b]9;4;5;50\x1b\\");
|
||||
// Nothing should have changed (dispatch should have returned false)
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarState(), TaskbarState::Clear);
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(0));
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(0));
|
||||
|
||||
// Set an out of bounds value for progress
|
||||
stateMachine.ProcessString(L"\x1b]9;4;1;999\x1b\\");
|
||||
// Progress should have been clamped to 100
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarState(), TaskbarState::Set);
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(1));
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(100));
|
||||
|
||||
// Don't specify any params
|
||||
stateMachine.ProcessString(L"\x1b]9;4\x1b\\");
|
||||
// State and progress should both be reset to 0
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarState(), TaskbarState::Clear);
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(0));
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(0));
|
||||
|
||||
// Specify additional params
|
||||
stateMachine.ProcessString(L"\x1b]9;4;1;80;123\x1b\\");
|
||||
// Additional params should be ignored, state and progress still set normally
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarState(), TaskbarState::Set);
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(1));
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(80));
|
||||
|
||||
// Edge cases + trailing semicolon testing
|
||||
stateMachine.ProcessString(L"\x1b]9;4;2;\x1b\\");
|
||||
// String should be processed correctly despite the trailing semicolon,
|
||||
// taskbar progress should remain unchanged from previous value
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarState(), TaskbarState::Error);
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(2));
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(80));
|
||||
|
||||
stateMachine.ProcessString(L"\x1b]9;4;3;75\x1b\\");
|
||||
// Given progress value should be ignored because this is the indeterminate state,
|
||||
// so the progress value should remain unchanged
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarState(), TaskbarState::Indeterminate);
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(3));
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(80));
|
||||
|
||||
stateMachine.ProcessString(L"\x1b]9;4;0;50\x1b\\");
|
||||
// Taskbar progress should be 0 (the given value should be ignored)
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarState(), TaskbarState::Clear);
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(0));
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(0));
|
||||
|
||||
stateMachine.ProcessString(L"\x1b]9;4;2;\x1b\\");
|
||||
// String should be processed correctly despite the trailing semicolon,
|
||||
// taskbar progress should be set to a 'minimum', non-zero value
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarState(), TaskbarState::Error);
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(2));
|
||||
VERIFY_IS_GREATER_THAN(term.GetTaskbarProgress(), gsl::narrow<size_t>(0));
|
||||
}
|
||||
|
||||
|
||||
@@ -106,7 +106,7 @@ void AppHost::SetTaskbarProgress(const winrt::Windows::Foundation::IInspectable&
|
||||
if (_windowLogic)
|
||||
{
|
||||
const auto state = _windowLogic.TaskbarState();
|
||||
_window->SetTaskbarProgress(state.State(),
|
||||
_window->SetTaskbarProgress(gsl::narrow_cast<size_t>(state.State()),
|
||||
gsl::narrow_cast<size_t>(state.Progress()));
|
||||
}
|
||||
}
|
||||
@@ -265,7 +265,6 @@ void AppHost::Initialize()
|
||||
|
||||
_revokers.IsQuakeWindowChanged = _windowLogic.IsQuakeWindowChanged(winrt::auto_revoke, { this, &AppHost::_IsQuakeWindowChanged });
|
||||
_revokers.SummonWindowRequested = _windowLogic.SummonWindowRequested(winrt::auto_revoke, { this, &AppHost::_SummonWindowRequested });
|
||||
_revokers.FocusTabRequested = _windowLogic.FocusTabRequested(winrt::auto_revoke, { this, &AppHost::_FocusTabRequested });
|
||||
_revokers.OpenSystemMenu = _windowLogic.OpenSystemMenu(winrt::auto_revoke, { this, &AppHost::_OpenSystemMenu });
|
||||
_revokers.QuitRequested = _windowLogic.QuitRequested(winrt::auto_revoke, { this, &AppHost::_RequestQuitAll });
|
||||
_revokers.ShowWindowChanged = _windowLogic.ShowWindowChanged(winrt::auto_revoke, { this, &AppHost::_ShowWindowChanged });
|
||||
@@ -1065,14 +1064,6 @@ void AppHost::_SummonWindowRequested(const winrt::Windows::Foundation::IInspecta
|
||||
HandleSummon(std::move(summonArgs));
|
||||
}
|
||||
|
||||
void AppHost::_FocusTabRequested(const winrt::Windows::Foundation::IInspectable&,
|
||||
const winrt::TerminalApp::Tab& tab)
|
||||
{
|
||||
// The tab may have moved to another window. Ask the emperor to
|
||||
// search all windows and focus the tab wherever it currently lives.
|
||||
_windowManager->FocusTabInAnyWindow(tab);
|
||||
}
|
||||
|
||||
void AppHost::_OpenSystemMenu(const winrt::Windows::Foundation::IInspectable&,
|
||||
const winrt::Windows::Foundation::IInspectable&)
|
||||
{
|
||||
|
||||
@@ -91,9 +91,6 @@ private:
|
||||
void _SummonWindowRequested(const winrt::Windows::Foundation::IInspectable& sender,
|
||||
const winrt::Windows::Foundation::IInspectable& args);
|
||||
|
||||
void _FocusTabRequested(const winrt::Windows::Foundation::IInspectable& sender,
|
||||
const winrt::TerminalApp::Tab& tab);
|
||||
|
||||
void _OpenSystemMenu(const winrt::Windows::Foundation::IInspectable& sender,
|
||||
const winrt::Windows::Foundation::IInspectable& args);
|
||||
|
||||
@@ -154,7 +151,6 @@ private:
|
||||
winrt::TerminalApp::TerminalWindow::IdentifyWindowsRequested_revoker IdentifyWindowsRequested;
|
||||
winrt::TerminalApp::TerminalWindow::IsQuakeWindowChanged_revoker IsQuakeWindowChanged;
|
||||
winrt::TerminalApp::TerminalWindow::SummonWindowRequested_revoker SummonWindowRequested;
|
||||
winrt::TerminalApp::TerminalWindow::FocusTabRequested_revoker FocusTabRequested;
|
||||
winrt::TerminalApp::TerminalWindow::OpenSystemMenu_revoker OpenSystemMenu;
|
||||
winrt::TerminalApp::TerminalWindow::QuitRequested_revoker QuitRequested;
|
||||
winrt::TerminalApp::TerminalWindow::ShowWindowChanged_revoker ShowWindowChanged;
|
||||
|
||||
@@ -930,28 +930,27 @@ void IslandWindow::FlashTaskbar()
|
||||
// Arguments:
|
||||
// - state: indicates the progress state
|
||||
// - progress: indicates the progress value
|
||||
void IslandWindow::SetTaskbarProgress(const winrt::Microsoft::Terminal::Control::TaskbarState state, const size_t progress)
|
||||
void IslandWindow::SetTaskbarProgress(const size_t state, const size_t progress)
|
||||
{
|
||||
if (_taskbar)
|
||||
{
|
||||
using TbState = winrt::Microsoft::Terminal::Control::TaskbarState;
|
||||
switch (state)
|
||||
{
|
||||
case TbState::Clear:
|
||||
case 0:
|
||||
// removes the taskbar progress indicator
|
||||
_taskbar->SetProgressState(_window.get(), TBPF_NOPROGRESS);
|
||||
break;
|
||||
case TbState::Set:
|
||||
case 1:
|
||||
// sets the progress value to value given by the 'progress' parameter
|
||||
_taskbar->SetProgressState(_window.get(), TBPF_NORMAL);
|
||||
_taskbar->SetProgressValue(_window.get(), progress, 100);
|
||||
break;
|
||||
case TbState::Error:
|
||||
case 2:
|
||||
// sets the progress indicator to an error state
|
||||
_taskbar->SetProgressState(_window.get(), TBPF_ERROR);
|
||||
_taskbar->SetProgressValue(_window.get(), progress, 100);
|
||||
break;
|
||||
case TbState::Indeterminate:
|
||||
case 3:
|
||||
// sets the progress indicator to an indeterminate state.
|
||||
// FIRST, set the progress to "no progress". That'll clear out any
|
||||
// progress value from the previous state. Otherwise, a transition
|
||||
@@ -960,7 +959,7 @@ void IslandWindow::SetTaskbarProgress(const winrt::Microsoft::Terminal::Control:
|
||||
_taskbar->SetProgressState(_window.get(), TBPF_NOPROGRESS);
|
||||
_taskbar->SetProgressState(_window.get(), TBPF_INDETERMINATE);
|
||||
break;
|
||||
case TbState::Paused:
|
||||
case 4:
|
||||
// sets the progress indicator to a pause state
|
||||
_taskbar->SetProgressState(_window.get(), TBPF_PAUSED);
|
||||
_taskbar->SetProgressValue(_window.get(), progress, 100);
|
||||
|
||||
@@ -53,7 +53,7 @@ public:
|
||||
virtual void SetShowTabsFullscreen(const bool newShowTabsFullscreen);
|
||||
|
||||
void FlashTaskbar();
|
||||
void SetTaskbarProgress(const winrt::Microsoft::Terminal::Control::TaskbarState state, const size_t progress);
|
||||
void SetTaskbarProgress(const size_t state, const size_t progress);
|
||||
|
||||
void SummonWindow(winrt::TerminalApp::SummonWindowBehavior args);
|
||||
|
||||
|
||||
@@ -11,8 +11,6 @@
|
||||
#include <wil/token_helpers.h>
|
||||
#include <winrt/TerminalApp.h>
|
||||
#include <sddl.h>
|
||||
#include <propkey.h>
|
||||
#include <propvarutil.h>
|
||||
|
||||
#include "AppHost.h"
|
||||
#include "resource.h"
|
||||
@@ -315,107 +313,6 @@ AppHost* WindowEmperor::_mostRecentWindow() const noexcept
|
||||
return mostRecent;
|
||||
}
|
||||
|
||||
// GH#20053: The shell resolves taskbar grouping identity as: per-window AUMID >
|
||||
// per-process AUMID > auto-derived from exe path. Before we started setting a
|
||||
// process AUMID, both the pinned .lnk and the process used auto-derived
|
||||
// identity, so they matched. Now that we set an explicit AUMID, a pinned .lnk
|
||||
// that predates the AUMID change has no AUMID and still uses auto-derived
|
||||
// identity, causing a mismatch and a duplicate taskbar button.
|
||||
//
|
||||
// To fix this, we check if a pinned taskbar shortcut (.lnk) points to our exe.
|
||||
// If it already carries our AUMID (or no pin exists), we set the process AUMID
|
||||
// normally. If a pin exists WITHOUT our AUMID, we skip setting the process
|
||||
// AUMID for THIS launch (both sides use auto-derived identity, so they match)
|
||||
// and defer stamping the shortcut to process exit. On the next launch, the pin
|
||||
// has our AUMID, so we set the process AUMID to match, and both agree.
|
||||
//
|
||||
// NOTE: On the first launch after pinning, the process AUMID is not set. If
|
||||
// toast notifications are needed in the future, use
|
||||
// ToastNotificationManager::CreateToastNotifier(aumid) with the AUMID string
|
||||
// directly. That API does not depend on SetCurrentProcessExplicitAppUserModelID.
|
||||
// A Start Menu shortcut with the AUMID (separate from the taskbar pin) is also
|
||||
// required for toast routing; see
|
||||
// https://learn.microsoft.com/windows/apps/develop/notifications/app-notifications/send-local-toast-other-apps
|
||||
void WindowEmperor::_setupAumid(const std::wstring& aumid)
|
||||
{
|
||||
const auto ourExePath = wil::GetModuleFileNameW<std::wstring>(nullptr);
|
||||
|
||||
bool needsDeferredStamping = false;
|
||||
std::wstring pinnedLnkPath;
|
||||
|
||||
const auto taskbarGlob = wil::ExpandEnvironmentStringsW<std::wstring>(
|
||||
LR"(%APPDATA%\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\*.lnk)");
|
||||
|
||||
WIN32_FIND_DATAW findData{};
|
||||
const wil::unique_hfind findHandle{ FindFirstFileExW(taskbarGlob.c_str(), FindExInfoBasic, &findData, FindExSearchNameMatch, nullptr, FIND_FIRST_EX_LARGE_FETCH) };
|
||||
if (findHandle)
|
||||
{
|
||||
const auto lastSlash = taskbarGlob.rfind(L'\\');
|
||||
const auto taskbarDir = taskbarGlob.substr(0, lastSlash + 1);
|
||||
|
||||
do
|
||||
{
|
||||
const auto lnkPath = taskbarDir + findData.cFileName;
|
||||
|
||||
wil::com_ptr<IShellLinkW> shellLink;
|
||||
if (FAILED(CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&shellLink))))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto persistFile = shellLink.try_query<IPersistFile>();
|
||||
if (!persistFile || FAILED(persistFile->Load(lnkPath.c_str(), STGM_READ)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
wchar_t targetPath[MAX_PATH]{};
|
||||
if (FAILED(shellLink->GetPath(targetPath, MAX_PATH, nullptr, SLGP_RAWPATH)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (til::compare_ordinal_insensitive(targetPath, ourExePath) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Found a pin pointing to us. Assume it needs stamping unless
|
||||
// we confirm it already has our AUMID.
|
||||
pinnedLnkPath = lnkPath;
|
||||
needsDeferredStamping = true;
|
||||
|
||||
if (const auto propertyStore = shellLink.try_query<IPropertyStore>())
|
||||
{
|
||||
wil::unique_prop_variant pv;
|
||||
if (SUCCEEDED(propertyStore->GetValue(PKEY_AppUserModel_ID, &pv)) &&
|
||||
pv.vt == VT_LPWSTR && pv.pwszVal &&
|
||||
aumid == pv.pwszVal)
|
||||
{
|
||||
needsDeferredStamping = false;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
} while (FindNextFileW(findHandle.get(), &findData));
|
||||
}
|
||||
|
||||
if (needsDeferredStamping)
|
||||
{
|
||||
// The pin exists but doesn't have our AUMID yet. Don't set the process
|
||||
// AUMID or stamp the shortcut now. Writing the shortcut causes the
|
||||
// shell to re-read it immediately, changing the pin's cached identity
|
||||
// mid-launch and creating a mismatch in the opposite direction. Instead,
|
||||
// stamp it at shutdown when the taskbar association no longer matters.
|
||||
_pendingAumidLnkPath = std::move(pinnedLnkPath);
|
||||
_pendingAumid = aumid;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_IF_FAILED(SetCurrentProcessExplicitAppUserModelID(aumid.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
void WindowEmperor::HandleCommandlineArgs(int nCmdShow)
|
||||
{
|
||||
// When running without package identity, set an explicit AppUserModelID so
|
||||
@@ -476,7 +373,7 @@ void WindowEmperor::HandleCommandlineArgs(int nCmdShow)
|
||||
#else
|
||||
fmt::format_to(std::back_inserter(unpackagedAumid), FMT_COMPILE(L".{:08x}"), hash);
|
||||
#endif
|
||||
_setupAumid(unpackagedAumid);
|
||||
LOG_IF_FAILED(SetCurrentProcessExplicitAppUserModelID(unpackagedAumid.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -656,29 +553,6 @@ void WindowEmperor::HandleCommandlineArgs(int nCmdShow)
|
||||
Shell_NotifyIconW(NIM_DELETE, &_notificationIcon);
|
||||
}
|
||||
|
||||
// GH#20053: Deferred shortcut stamping. See _setupAumid() for context.
|
||||
if (!_pendingAumidLnkPath.empty())
|
||||
{
|
||||
wil::com_ptr<IShellLinkW> shellLink;
|
||||
if (SUCCEEDED(CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&shellLink))))
|
||||
{
|
||||
if (const auto persistFile = shellLink.try_query<IPersistFile>();
|
||||
persistFile && SUCCEEDED(persistFile->Load(_pendingAumidLnkPath.c_str(), STGM_READWRITE)))
|
||||
{
|
||||
if (const auto propertyStore = shellLink.try_query<IPropertyStore>())
|
||||
{
|
||||
wil::unique_prop_variant pv;
|
||||
if (SUCCEEDED(InitPropVariantFromString(_pendingAumid.c_str(), &pv)) &&
|
||||
SUCCEEDED(propertyStore->SetValue(PKEY_AppUserModel_ID, pv)) &&
|
||||
SUCCEEDED(propertyStore->Commit()))
|
||||
{
|
||||
persistFile->Save(_pendingAumidLnkPath.c_str(), TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// There's a mysterious crash in XAML on Windows 10 if you just let _app get destroyed (GH#15410).
|
||||
// We also need to ensure that all UI threads exit before WindowEmperor leaves the scope on the main thread (MSFT:46744208).
|
||||
// Both problems can be solved and the shutdown accelerated by using TerminateProcess.
|
||||
@@ -901,25 +775,6 @@ bool WindowEmperor::_summonWindow(const SummonWindowSelectionArgs& args) const
|
||||
return true;
|
||||
}
|
||||
|
||||
void WindowEmperor::FocusTabInAnyWindow(const winrt::TerminalApp::Tab& tab) const
|
||||
{
|
||||
_assertIsMainThread();
|
||||
|
||||
for (const auto& w : _windows)
|
||||
{
|
||||
if (w->Logic().FocusTab(tab))
|
||||
{
|
||||
winrt::TerminalApp::SummonWindowBehavior summonArgs;
|
||||
summonArgs.MoveToCurrentDesktop(false);
|
||||
summonArgs.DropdownDuration(0);
|
||||
summonArgs.ToMonitor(winrt::TerminalApp::MonitorBehavior::InPlace);
|
||||
summonArgs.ToggleVisibility(false);
|
||||
w->HandleSummon(std::move(summonArgs));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WindowEmperor::_summonAllWindows() const
|
||||
{
|
||||
_assertIsMainThread();
|
||||
@@ -1178,14 +1033,7 @@ LRESULT WindowEmperor::_messageHandler(HWND window, UINT const message, WPARAM c
|
||||
{
|
||||
const auto handoff = deserializeHandoffPayload(static_cast<const uint8_t*>(cds->lpData), static_cast<const uint8_t*>(cds->lpData) + cds->cbData);
|
||||
const auto argv = commandlineToArgArray(handoff.args.c_str());
|
||||
// When a toast notification is clicked, Windows launches a new
|
||||
// wt.exe with "--from-toast". That instance hands off here via
|
||||
// WM_COPYDATA. We already handle activation in-process via the
|
||||
// toast's Activated event, so just ignore this handoff.
|
||||
if (argv.size() != 2 || argv[1] != L"--from-toast")
|
||||
{
|
||||
_dispatchCommandlineCommon(argv, handoff.cwd, handoff.env, handoff.show);
|
||||
}
|
||||
_dispatchCommandlineCommon(argv, handoff.cwd, handoff.env, handoff.show);
|
||||
}
|
||||
return 0;
|
||||
case WM_HOTKEY:
|
||||
|
||||
@@ -35,7 +35,6 @@ public:
|
||||
AppHost* GetWindowByName(std::wstring_view name) const noexcept;
|
||||
void CreateNewWindow(winrt::TerminalApp::WindowRequestedArgs args);
|
||||
void HandleCommandlineArgs(int nCmdShow);
|
||||
void FocusTabInAnyWindow(const winrt::TerminalApp::Tab& tab) const;
|
||||
|
||||
private:
|
||||
struct SummonWindowSelectionArgs
|
||||
@@ -69,7 +68,6 @@ private:
|
||||
void _persistState(const winrt::Microsoft::Terminal::Settings::Model::ApplicationState& state) const;
|
||||
void _finalizeSessionPersistence() const;
|
||||
void _checkWindowsForNotificationIcon();
|
||||
void _setupAumid(const std::wstring& aumid);
|
||||
|
||||
wil::unique_hwnd _window;
|
||||
winrt::TerminalApp::App _app{ nullptr };
|
||||
@@ -85,8 +83,6 @@ private:
|
||||
std::optional<bool> _currentSystemThemeIsDark;
|
||||
int32_t _windowCount = 0;
|
||||
int32_t _messageBoxCount = 0;
|
||||
std::wstring _pendingAumidLnkPath;
|
||||
std::wstring _pendingAumid;
|
||||
|
||||
#if 0 // #ifdef NDEBUG
|
||||
static constexpr void _assertIsMainThread() noexcept
|
||||
|
||||
@@ -60,37 +60,32 @@
|
||||
|
||||
// --------------------------- Control Settings ---------------------------
|
||||
// All of these settings are defined in IControlSettings.
|
||||
#define CONTROL_SETTINGS(X) \
|
||||
X(winrt::guid, SessionId) \
|
||||
X(bool, EnableUnfocusedAcrylic, false) \
|
||||
X(winrt::hstring, Padding, DEFAULT_PADDING) \
|
||||
X(winrt::hstring, FontFace, L"Consolas") \
|
||||
X(float, FontSize, DEFAULT_FONT_SIZE) \
|
||||
X(winrt::Windows::UI::Text::FontWeight, FontWeight) \
|
||||
X(IFontFeatureMap, FontFeatures) \
|
||||
X(IFontAxesMap, FontAxes) \
|
||||
X(bool, EnableBuiltinGlyphs, true) \
|
||||
X(bool, EnableColorGlyphs, true) \
|
||||
X(winrt::hstring, CellWidth) \
|
||||
X(winrt::hstring, CellHeight) \
|
||||
X(winrt::hstring, Commandline) \
|
||||
X(winrt::hstring, StartingDirectory) \
|
||||
X(winrt::Microsoft::Terminal::Control::ScrollbarState, ScrollState, winrt::Microsoft::Terminal::Control::ScrollbarState::Visible) \
|
||||
X(winrt::Microsoft::Terminal::Control::TextAntialiasingMode, AntialiasingMode, winrt::Microsoft::Terminal::Control::TextAntialiasingMode::Grayscale) \
|
||||
X(winrt::Microsoft::Terminal::Control::GraphicsAPI, GraphicsAPI) \
|
||||
X(bool, DisablePartialInvalidation, false) \
|
||||
X(bool, SoftwareRendering, false) \
|
||||
X(winrt::Microsoft::Terminal::Control::TextMeasurement, TextMeasurement) \
|
||||
X(winrt::Microsoft::Terminal::Control::AmbiguousWidth, AmbiguousWidth, winrt::Microsoft::Terminal::Control::AmbiguousWidth::Narrow) \
|
||||
X(winrt::Microsoft::Terminal::Control::DefaultInputScope, DefaultInputScope, winrt::Microsoft::Terminal::Control::DefaultInputScope::Default) \
|
||||
X(bool, UseBackgroundImageForWindow, false) \
|
||||
X(bool, ShowMarks, false) \
|
||||
X(winrt::Microsoft::Terminal::Control::CopyFormat, CopyFormatting, 0) \
|
||||
X(bool, RightClickContextMenu, false) \
|
||||
X(winrt::Microsoft::Terminal::Control::PathTranslationStyle, PathTranslationStyle, winrt::Microsoft::Terminal::Control::PathTranslationStyle::None) \
|
||||
X(winrt::Microsoft::Terminal::Control::OutputNotificationStyle, NotifyOnActivity, winrt::Microsoft::Terminal::Control::OutputNotificationStyle::None) \
|
||||
X(winrt::Microsoft::Terminal::Control::OutputNotificationStyle, NotifyOnNextPrompt, winrt::Microsoft::Terminal::Control::OutputNotificationStyle::None) \
|
||||
X(int32_t, NotifyOnActivityThreshold, 5) \
|
||||
X(int32_t, NotifyOnNextPromptThreshold, 5) \
|
||||
X(bool, AutoDetectRunningCommand, false) \
|
||||
#define CONTROL_SETTINGS(X) \
|
||||
X(winrt::guid, SessionId) \
|
||||
X(bool, EnableUnfocusedAcrylic, false) \
|
||||
X(winrt::hstring, Padding, DEFAULT_PADDING) \
|
||||
X(winrt::hstring, FontFace, L"Consolas") \
|
||||
X(float, FontSize, DEFAULT_FONT_SIZE) \
|
||||
X(winrt::Windows::UI::Text::FontWeight, FontWeight) \
|
||||
X(IFontFeatureMap, FontFeatures) \
|
||||
X(IFontAxesMap, FontAxes) \
|
||||
X(bool, EnableBuiltinGlyphs, true) \
|
||||
X(bool, EnableColorGlyphs, true) \
|
||||
X(winrt::hstring, CellWidth) \
|
||||
X(winrt::hstring, CellHeight) \
|
||||
X(winrt::hstring, Commandline) \
|
||||
X(winrt::hstring, StartingDirectory) \
|
||||
X(winrt::Microsoft::Terminal::Control::ScrollbarState, ScrollState, winrt::Microsoft::Terminal::Control::ScrollbarState::Visible) \
|
||||
X(winrt::Microsoft::Terminal::Control::TextAntialiasingMode, AntialiasingMode, winrt::Microsoft::Terminal::Control::TextAntialiasingMode::Grayscale) \
|
||||
X(winrt::Microsoft::Terminal::Control::GraphicsAPI, GraphicsAPI) \
|
||||
X(bool, DisablePartialInvalidation, false) \
|
||||
X(bool, SoftwareRendering, false) \
|
||||
X(winrt::Microsoft::Terminal::Control::TextMeasurement, TextMeasurement) \
|
||||
X(winrt::Microsoft::Terminal::Control::AmbiguousWidth, AmbiguousWidth, winrt::Microsoft::Terminal::Control::AmbiguousWidth::Narrow) \
|
||||
X(winrt::Microsoft::Terminal::Control::DefaultInputScope, DefaultInputScope, winrt::Microsoft::Terminal::Control::DefaultInputScope::Default) \
|
||||
X(bool, UseBackgroundImageForWindow, false) \
|
||||
X(bool, ShowMarks, false) \
|
||||
X(winrt::Microsoft::Terminal::Control::CopyFormat, CopyFormatting, 0) \
|
||||
X(bool, RightClickContextMenu, false) \
|
||||
X(winrt::Microsoft::Terminal::Control::PathTranslationStyle, PathTranslationStyle, winrt::Microsoft::Terminal::Control::PathTranslationStyle::None) \
|
||||
X(winrt::hstring, DragDropDelimiter, L" ")
|
||||
|
||||
@@ -153,9 +153,9 @@ public:
|
||||
// _core.TitleChanged({ get_weak(), &TermControl::_bubbleTitleChanged });
|
||||
#define BUBBLED_FORWARDED_TYPED_EVENT(name, sender, args) \
|
||||
TYPED_EVENT(name, sender, args) \
|
||||
void _bubble##name(const sender& s, const args& a) \
|
||||
void _bubble##name(const sender&, const args& a) \
|
||||
{ \
|
||||
_##name##Handlers(s, a); \
|
||||
_##name##Handlers(*this, a); \
|
||||
}
|
||||
|
||||
// Use this macro to quick implement both the getter and setter for a property.
|
||||
|
||||
@@ -446,7 +446,7 @@ void ConhostInternalGetSet::NotifyBufferRotation(const int)
|
||||
{
|
||||
}
|
||||
|
||||
void ConhostInternalGetSet::NotifyShellIntegrationMark(ShellIntegrationMark /*mark*/)
|
||||
void ConhostInternalGetSet::NotifyShellIntegrationMark()
|
||||
{
|
||||
// Not implemented for conhost - shell integration marks are a Terminal app feature.
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ public:
|
||||
bool IsVtInputEnabled() const override;
|
||||
|
||||
void NotifyBufferRotation(const int delta) override;
|
||||
void NotifyShellIntegrationMark(ShellIntegrationMark mark) override;
|
||||
void NotifyShellIntegrationMark() override;
|
||||
|
||||
void InvokeCompletions(std::wstring_view menuJson, unsigned int replaceLength) override;
|
||||
|
||||
|
||||
@@ -87,16 +87,7 @@ namespace Microsoft::Console::VirtualTerminal
|
||||
virtual bool ResizeWindow(const til::CoordType width, const til::CoordType height) = 0;
|
||||
|
||||
virtual void NotifyBufferRotation(const int delta) = 0;
|
||||
|
||||
enum class ShellIntegrationMark
|
||||
{
|
||||
Prompt,
|
||||
Command,
|
||||
Output,
|
||||
CommandFinished,
|
||||
Other
|
||||
};
|
||||
virtual void NotifyShellIntegrationMark(ShellIntegrationMark mark) = 0;
|
||||
virtual void NotifyShellIntegrationMark() = 0;
|
||||
|
||||
virtual void InvokeCompletions(std::wstring_view menuJson, unsigned int replaceLength) = 0;
|
||||
|
||||
|
||||
@@ -3640,7 +3640,7 @@ void AdaptDispatch::DoConEmuAction(const std::wstring_view string)
|
||||
else if (subParam == 12)
|
||||
{
|
||||
_pages.ActivePage().Buffer().StartCommand();
|
||||
_api.NotifyShellIntegrationMark(ITerminalApi::ShellIntegrationMark::Command);
|
||||
_api.NotifyShellIntegrationMark();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3675,7 +3675,7 @@ void AdaptDispatch::DoITerm2Action(const std::wstring_view string)
|
||||
if (action == L"SetMark")
|
||||
{
|
||||
_pages.ActivePage().Buffer().StartPrompt();
|
||||
_api.NotifyShellIntegrationMark(ITerminalApi::ShellIntegrationMark::Prompt);
|
||||
_api.NotifyShellIntegrationMark();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3713,19 +3713,19 @@ void AdaptDispatch::DoFinalTermAction(const std::wstring_view string)
|
||||
case L'A': // FTCS_PROMPT
|
||||
{
|
||||
_pages.ActivePage().Buffer().StartPrompt();
|
||||
_api.NotifyShellIntegrationMark(ITerminalApi::ShellIntegrationMark::Prompt);
|
||||
_api.NotifyShellIntegrationMark();
|
||||
break;
|
||||
}
|
||||
case L'B': // FTCS_COMMAND_START
|
||||
{
|
||||
_pages.ActivePage().Buffer().StartCommand();
|
||||
_api.NotifyShellIntegrationMark(ITerminalApi::ShellIntegrationMark::Command);
|
||||
_api.NotifyShellIntegrationMark();
|
||||
break;
|
||||
}
|
||||
case L'C': // FTCS_COMMAND_EXECUTED
|
||||
{
|
||||
_pages.ActivePage().Buffer().StartOutput();
|
||||
_api.NotifyShellIntegrationMark(ITerminalApi::ShellIntegrationMark::Output);
|
||||
_api.NotifyShellIntegrationMark();
|
||||
break;
|
||||
}
|
||||
case L'D': // FTCS_COMMAND_FINISHED
|
||||
@@ -3746,7 +3746,7 @@ void AdaptDispatch::DoFinalTermAction(const std::wstring_view string)
|
||||
}
|
||||
|
||||
_pages.ActivePage().Buffer().EndCurrentCommand(error);
|
||||
_api.NotifyShellIntegrationMark(ITerminalApi::ShellIntegrationMark::CommandFinished);
|
||||
_api.NotifyShellIntegrationMark();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -216,7 +216,7 @@ public:
|
||||
Log::Comment(L"NotifyBufferRotation MOCK called...");
|
||||
}
|
||||
|
||||
void NotifyShellIntegrationMark(ShellIntegrationMark /*mark*/) override
|
||||
void NotifyShellIntegrationMark() override
|
||||
{
|
||||
Log::Comment(L"NotifyShellIntegrationMark MOCK called...");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user