mirror of
https://github.com/microsoft/terminal.git
synced 2026-04-20 05:01:03 +00:00
Compare commits
14 Commits
main
...
dev/migrie
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f2296e08f7 | ||
|
|
2e5776f527 | ||
|
|
728e81f7da | ||
|
|
7be3c7b9cb | ||
|
|
ad12c5b8a3 | ||
|
|
756a1d4d6d | ||
|
|
a0adf411a7 | ||
|
|
20dcfd098b | ||
|
|
267d379747 | ||
|
|
8a132d6b77 | ||
|
|
d449c86a33 | ||
|
|
cd8ff95c1a | ||
|
|
19cfe09bda | ||
|
|
e8d1933b9e |
@@ -76,6 +76,36 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"OutputNotificationStyle": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"taskbar",
|
||||
"audible",
|
||||
"tab",
|
||||
"notification"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"taskbar",
|
||||
"audible",
|
||||
"tab",
|
||||
"notification",
|
||||
"all",
|
||||
"none"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"BellSound": {
|
||||
"default": "",
|
||||
"description": "Sets the file location of the sound played when the application emits a BEL character. If the path is invalid no sound will be played. This property also accepts an array of sounds and the terminal will pick one at random.",
|
||||
@@ -94,6 +124,14 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"AutoDetectRunningCommand": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"disabled",
|
||||
"automatic",
|
||||
"progress"
|
||||
]
|
||||
},
|
||||
"BuiltinSuggestionSource": {
|
||||
"type": "string",
|
||||
"anyOf": [
|
||||
@@ -3174,6 +3212,21 @@
|
||||
"mingw"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"notifyOnInactiveOutput": {
|
||||
"default": "none",
|
||||
"description": "Controls how the terminal notifies you when a background pane produces output. Supported values include `taskbar`, `audible`, `tab`, and `notification`. Can be set to true (equivalent to `tab`), false/none (disabled), a single string, or an array of strings.",
|
||||
"$ref": "#/$defs/OutputNotificationStyle"
|
||||
},
|
||||
"notifyOnNextPrompt": {
|
||||
"default": "none",
|
||||
"description": "Controls how the terminal notifies you when a running command finishes and the shell returns to a prompt. Requires shell integration. Supported values include `taskbar`, `audible`, `tab`, and `notification`. Can be set to true (equivalent to `tab`), false/none (disabled), a single string, or an array of strings.",
|
||||
"$ref": "#/$defs/OutputNotificationStyle"
|
||||
},
|
||||
"autoDetectRunningCommand": {
|
||||
"default": "disabled",
|
||||
"description": "Controls automatic detection of running commands via shell integration marks. When set to `automatic`, an indeterminate progress indicator is shown on the tab while a command is executing. When set to `progress`, the terminal will also attempt to detect progress percentages from command output. Requires shell integration.",
|
||||
"$ref": "#/$defs/AutoDetectRunningCommand"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace winrt::TerminalApp::implementation
|
||||
til::typed_event<> ConnectionStateChanged;
|
||||
til::typed_event<IPaneContent> CloseRequested;
|
||||
til::typed_event<IPaneContent, winrt::TerminalApp::BellEventArgs> BellRequested;
|
||||
til::typed_event<IPaneContent, winrt::TerminalApp::NotificationEventArgs> NotificationRequested;
|
||||
til::typed_event<IPaneContent> TitleChanged;
|
||||
til::typed_event<IPaneContent> TabColorChanged;
|
||||
til::typed_event<IPaneContent> TaskbarProgressChanged;
|
||||
|
||||
104
src/cascadia/TerminalApp/DesktopNotification.cpp
Normal file
104
src/cascadia/TerminalApp/DesktopNotification.cpp
Normal file
@@ -0,0 +1,104 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
||||
#include "DesktopNotification.h"
|
||||
|
||||
using namespace winrt::Windows::UI::Notifications;
|
||||
using namespace winrt::Windows::Data::Xml::Dom;
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
std::atomic<int64_t> DesktopNotification::_lastNotificationTime{ 0 };
|
||||
|
||||
bool DesktopNotification::ShouldSendNotification()
|
||||
{
|
||||
FILETIME ft{};
|
||||
GetSystemTimeAsFileTime(&ft);
|
||||
const auto now = (static_cast<int64_t>(ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
|
||||
auto last = _lastNotificationTime.load(std::memory_order_relaxed);
|
||||
|
||||
if (now - last < MinNotificationIntervalTicks)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Attempt to update; if another thread beat us, that's fine — we'll skip this one.
|
||||
_lastNotificationTime.compare_exchange_strong(last, now, std::memory_order_relaxed);
|
||||
return true;
|
||||
}
|
||||
|
||||
void DesktopNotification::SendNotification(
|
||||
const DesktopNotificationArgs& args,
|
||||
std::function<void(uint32_t tabIndex)> activated)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!ShouldSendNotification())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Build the toast XML. We use a simple template with a title and body text.
|
||||
//
|
||||
// <toast launch="__fromToast">
|
||||
// <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. "__fromToast" is recognized by
|
||||
// AppCommandlineArgs::ParseArgs as a no-op sentinel.
|
||||
toastElement.SetAttribute(L"launch", L"__fromToast");
|
||||
|
||||
// Set the scenario to "reminder" to ensure the toast shows even in DND,
|
||||
// and the group/tag to allow replacement of repeated notifications.
|
||||
toastElement.SetAttribute(L"scenario", L"default");
|
||||
|
||||
auto toast = ToastNotification{ toastXml };
|
||||
|
||||
// Set the tag and group to enable notification replacement.
|
||||
// Using the tab index as a tag means repeated output from the same tab
|
||||
// replaces the previous notification rather than stacking.
|
||||
toast.Tag(fmt::format(FMT_COMPILE(L"wt-tab-{}"), args.TabIndex));
|
||||
toast.Group(L"WindowsTerminal");
|
||||
|
||||
// When the user activates (clicks) the toast, fire the callback.
|
||||
if (activated)
|
||||
{
|
||||
const auto tabIndex = args.TabIndex;
|
||||
toast.Activated([activated, tabIndex](const auto& /*sender*/, const auto& /*eventArgs*/) {
|
||||
activated(tabIndex);
|
||||
});
|
||||
}
|
||||
|
||||
// For packaged apps, CreateToastNotifier() uses the package identity automatically.
|
||||
// For unpackaged apps, we need to provide an AUMID, but that case is less common
|
||||
// and toast notifications may not be supported without additional setup.
|
||||
auto notifier = ToastNotificationManager::CreateToastNotifier();
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
52
src/cascadia/TerminalApp/DesktopNotification.h
Normal file
52
src/cascadia/TerminalApp/DesktopNotification.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*++
|
||||
Copyright (c) Microsoft Corporation
|
||||
Licensed under the MIT license.
|
||||
|
||||
Module Name:
|
||||
- DesktopNotification.h
|
||||
|
||||
Module Description:
|
||||
- Helper for sending Windows desktop toast notifications. Used by the
|
||||
`OutputNotificationStyle::Notification` flag to surface activity
|
||||
and prompt-return 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;
|
||||
uint32_t TabIndex{ 0 };
|
||||
};
|
||||
|
||||
class DesktopNotification
|
||||
{
|
||||
public:
|
||||
// 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.
|
||||
//
|
||||
// activated: A callback invoked on the background thread when the
|
||||
// toast is clicked. The uint32_t parameter is the tab index.
|
||||
static void SendNotification(
|
||||
const DesktopNotificationArgs& args,
|
||||
std::function<void(uint32_t tabIndex)> activated);
|
||||
|
||||
// Rate-limits toast notifications so we don't spam the user.
|
||||
// Returns true if a notification is allowed, false if too recent.
|
||||
static bool ShouldSendNotification();
|
||||
|
||||
private:
|
||||
static std::atomic<int64_t> _lastNotificationTime;
|
||||
|
||||
// Minimum interval between notifications, in 100ns ticks (FILETIME units).
|
||||
// 5 seconds = 5 * 10,000,000
|
||||
static constexpr int64_t MinNotificationIntervalTicks = 50'000'000LL;
|
||||
};
|
||||
}
|
||||
@@ -14,6 +14,13 @@ namespace TerminalApp
|
||||
runtimeclass BellEventArgs
|
||||
{
|
||||
Boolean FlashTaskbar { get; };
|
||||
Boolean SendNotification { get; };
|
||||
};
|
||||
|
||||
runtimeclass NotificationEventArgs
|
||||
{
|
||||
Microsoft.Terminal.Control.OutputNotificationStyle Style { get; };
|
||||
Boolean OnlyWhenInactive { get; };
|
||||
};
|
||||
|
||||
interface IPaneContent
|
||||
@@ -41,6 +48,7 @@ namespace TerminalApp
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> ConnectionStateChanged;
|
||||
event Windows.Foundation.TypedEventHandler<IPaneContent, BellEventArgs> BellRequested;
|
||||
event Windows.Foundation.TypedEventHandler<IPaneContent, NotificationEventArgs> NotificationRequested;
|
||||
event Windows.Foundation.TypedEventHandler<IPaneContent, Object> TitleChanged;
|
||||
event Windows.Foundation.TypedEventHandler<IPaneContent, Object> TabColorChanged;
|
||||
event Windows.Foundation.TypedEventHandler<IPaneContent, Object> TaskbarProgressChanged;
|
||||
|
||||
@@ -923,4 +923,16 @@
|
||||
<data name="InvalidRegex" xml:space="preserve">
|
||||
<value>An invalid regular expression was found.</value>
|
||||
</data>
|
||||
<data name="NotificationTitle" xml:space="preserve">
|
||||
<value>Windows Terminal</value>
|
||||
<comment>Title shown in desktop toast notifications for tab activity.</comment>
|
||||
</data>
|
||||
<data name="NotificationMessage_TabActivity" xml:space="preserve">
|
||||
<value>Tab "{0}" has new activity</value>
|
||||
<comment>{Locked="{0}"}Message shown in a desktop toast notification when a tab produces output. {0} is the tab title.</comment>
|
||||
</data>
|
||||
<data name="NotificationMessage_TabActivityInWindow" xml:space="preserve">
|
||||
<value>Tab "{0}" in {1} has new activity</value>
|
||||
<comment>{Locked="{0}"}{Locked="{1}"}Message shown in a desktop toast notification when a tab produces output. {0} is the tab title. {1} is the window name.</comment>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -123,6 +123,15 @@ namespace winrt::TerminalApp::implementation
|
||||
_bellIndicatorTimer.Stop();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Called when the timer for the activity indicator in the tab header fires
|
||||
// - Removes the activity indicator from the tab header
|
||||
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:
|
||||
@@ -329,6 +338,11 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
ShowBellIndicator(false);
|
||||
}
|
||||
// When we gain focus, remove the activity indicator if it is active
|
||||
if (_tabStatus.ActivityIndicator())
|
||||
{
|
||||
ShowActivityIndicator(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -459,6 +473,29 @@ namespace winrt::TerminalApp::implementation
|
||||
_bellIndicatorTimer.Start();
|
||||
}
|
||||
|
||||
void Tab::ShowActivityIndicator(const bool show)
|
||||
{
|
||||
ASSERT_UI_THREAD();
|
||||
|
||||
_tabStatus.ActivityIndicator(show);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Activates the timer for the activity indicator in the tab
|
||||
// - Called if a notification was raised when the tab already has focus
|
||||
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.
|
||||
@@ -1068,6 +1105,7 @@ namespace winrt::TerminalApp::implementation
|
||||
dispatcher,
|
||||
til::throttled_func_options{
|
||||
.delay = std::chrono::milliseconds{ 200 },
|
||||
.leading = true,
|
||||
.trailing = true,
|
||||
},
|
||||
[weakThis]() {
|
||||
@@ -1148,6 +1186,14 @@ 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(), tab->TabViewIndex());
|
||||
}
|
||||
|
||||
// Show the bell indicator in the tab header
|
||||
tab->ShowBellIndicator(true);
|
||||
|
||||
@@ -1161,6 +1207,63 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
});
|
||||
|
||||
events.NotificationRequested = content.NotificationRequested(
|
||||
winrt::auto_revoke,
|
||||
[dispatcher, weakThis](TerminalApp::IPaneContent sender, auto notificationArgs) -> safe_void_coroutine {
|
||||
const auto weakThisCopy = weakThis;
|
||||
co_await wil::resume_foreground(dispatcher);
|
||||
if (const auto tab{ weakThisCopy.get() })
|
||||
{
|
||||
// For NotifyOnInactiveOutput (OnlyWhenInactive=true), suppress
|
||||
// ALL notification styles when the sender is the active pane.
|
||||
// For NotifyOnNextPrompt (OnlyWhenInactive=false), always fire.
|
||||
const auto activeContent = tab->GetActiveContent();
|
||||
const auto isActivePaneContent = activeContent && activeContent == sender;
|
||||
|
||||
if (notificationArgs.OnlyWhenInactive() && isActivePaneContent &&
|
||||
tab->_focusState != WUX::FocusState::Unfocused)
|
||||
{
|
||||
co_return;
|
||||
}
|
||||
|
||||
const auto style = notificationArgs.Style();
|
||||
|
||||
if (WI_IsFlagSet(style, OutputNotificationStyle::Taskbar))
|
||||
{
|
||||
// Flash the taskbar button
|
||||
tab->TabRaiseVisualBell.raise();
|
||||
}
|
||||
|
||||
if (WI_IsFlagSet(style, winrt::Microsoft::Terminal::Control::OutputNotificationStyle::Audible))
|
||||
{
|
||||
// Play the notification sound via the pane's bell infrastructure
|
||||
// (respects BellSound profile setting, uses MediaPlayer, etc.)
|
||||
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))
|
||||
{
|
||||
// Request a desktop toast notification.
|
||||
// TerminalPage subscribes to this event and handles sending the toast
|
||||
// and processing its activation (summoning the window + switching tabs).
|
||||
tab->TabToastNotificationRequested.raise(tab->Title(), tab->TabViewIndex());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (const auto& terminal{ content.try_as<TerminalApp::TerminalPaneContent>() })
|
||||
{
|
||||
events.RestartTerminalRequested = terminal.RestartTerminalRequested(winrt::auto_revoke, { get_weak(), &Tab::_bubbleRestartTerminalRequested });
|
||||
@@ -1393,6 +1496,11 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
tab->ShowBellIndicator(false);
|
||||
}
|
||||
// Also remove the activity indicator
|
||||
if (tab->_tabStatus.ActivityIndicator())
|
||||
{
|
||||
tab->ShowActivityIndicator(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -48,6 +48,9 @@ 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,
|
||||
@@ -121,6 +124,7 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
til::typed_event<TerminalApp::Tab, IInspectable> ActivePaneChanged;
|
||||
til::event<winrt::delegate<>> TabRaiseVisualBell;
|
||||
til::event<winrt::delegate<winrt::hstring /*title*/, uint32_t /*tabIndex*/>> TabToastNotificationRequested;
|
||||
til::typed_event<IInspectable, IInspectable> TaskbarProgressChanged;
|
||||
|
||||
// The TabViewIndex is the index this Tab object resides in TerminalPage's _tabs vector.
|
||||
@@ -176,6 +180,7 @@ namespace winrt::TerminalApp::implementation
|
||||
struct ContentEventTokens
|
||||
{
|
||||
winrt::TerminalApp::IPaneContent::BellRequested_revoker BellRequested;
|
||||
winrt::TerminalApp::IPaneContent::NotificationRequested_revoker NotificationRequested;
|
||||
winrt::TerminalApp::IPaneContent::TitleChanged_revoker TitleChanged;
|
||||
winrt::TerminalApp::IPaneContent::TabColorChanged_revoker TabColorChanged;
|
||||
winrt::TerminalApp::IPaneContent::TaskbarProgressChanged_revoker TaskbarProgressChanged;
|
||||
@@ -210,6 +215,9 @@ 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();
|
||||
|
||||
@@ -32,6 +32,12 @@
|
||||
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}"
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "DebugTapConnection.h"
|
||||
#include "..\TerminalSettingsModel\FileUtils.h"
|
||||
#include "../TerminalSettingsAppAdapterLib/TerminalSettings.h"
|
||||
#include "DesktopNotification.h"
|
||||
|
||||
#include <shlobj.h>
|
||||
|
||||
@@ -150,6 +151,15 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
});
|
||||
|
||||
// When a tab requests a desktop toast notification (OutputNotificationStyle::Notification),
|
||||
// send the toast and handle activation by summoning this window and switching to the tab.
|
||||
newTabImpl->TabToastNotificationRequested([weakThis{ get_weak() }](const winrt::hstring& title, uint32_t tabIndex) {
|
||||
if (const auto page{ weakThis.get() })
|
||||
{
|
||||
page->_SendDesktopNotification(title, tabIndex);
|
||||
}
|
||||
});
|
||||
|
||||
auto tabViewItem = newTabImpl->TabViewItem();
|
||||
_tabView.TabItems().InsertAt(insertPosition, tabViewItem);
|
||||
|
||||
@@ -1185,4 +1195,56 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
return _tabs.Size() > 1;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Sends a Windows desktop toast notification for a tab. When the user clicks
|
||||
// the toast, summon this window and switch to the specified tab.
|
||||
// Arguments:
|
||||
// - tabTitle: The title of the tab to display in the notification.
|
||||
// - tabIndex: The index of the tab to switch to when the toast is activated.
|
||||
void TerminalPage::_SendDesktopNotification(const winrt::hstring& tabTitle, uint32_t tabIndex)
|
||||
{
|
||||
// Build the notification message.
|
||||
// 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{};
|
||||
winrt::hstring message;
|
||||
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 });
|
||||
}
|
||||
|
||||
implementation::DesktopNotificationArgs args;
|
||||
args.Title = RS_(L"NotificationTitle");
|
||||
args.Message = message;
|
||||
args.TabIndex = tabIndex;
|
||||
|
||||
// Capture a weak ref and the dispatcher so we can marshal back to the UI thread
|
||||
// when the toast is activated.
|
||||
auto weakThis = get_weak();
|
||||
auto dispatcher = Dispatcher();
|
||||
|
||||
implementation::DesktopNotification::SendNotification(
|
||||
args,
|
||||
[weakThis, dispatcher, tabIndex](uint32_t /*activatedTabIndex*/) -> void {
|
||||
// The toast Activated callback fires on a background thread.
|
||||
// We need to dispatch to the UI thread to summon the window and switch tabs.
|
||||
[](auto weakThis, auto dispatcher, auto tabIndex) -> safe_void_coroutine {
|
||||
co_await wil::resume_foreground(dispatcher);
|
||||
if (const auto page{ weakThis.get() })
|
||||
{
|
||||
// Summon this window (bring to foreground)
|
||||
page->SummonWindowRequested.raise(nullptr, nullptr);
|
||||
|
||||
// Switch to the tab that triggered the notification
|
||||
page->_SelectTab(tabIndex);
|
||||
}
|
||||
}(weakThis, dispatcher, tabIndex);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,6 +173,7 @@
|
||||
<ClInclude Include="SettingsPaneContent.h">
|
||||
<DependentUpon>TerminalPaneContent.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DesktopNotification.h" />
|
||||
<ClInclude Include="Toast.h" />
|
||||
<ClInclude Include="TerminalSettingsCache.h" />
|
||||
<ClInclude Include="SuggestionsControl.h">
|
||||
@@ -286,6 +287,7 @@
|
||||
<DependentUpon>TerminalPaneContent.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
|
||||
<ClCompile Include="DesktopNotification.cpp" />
|
||||
<ClCompile Include="Toast.cpp" />
|
||||
<ClCompile Include="TerminalSettingsCache.cpp" />
|
||||
<ClCompile Include="SuggestionsControl.cpp">
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
<ClCompile Include="fzf/fzf.cpp">
|
||||
<Filter>fzf</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DesktopNotification.cpp" />
|
||||
<ClCompile Include="Toast.cpp" />
|
||||
<ClCompile Include="LanguageProfileNotifier.cpp" />
|
||||
<ClCompile Include="TerminalSettingsCache.cpp" />
|
||||
@@ -58,6 +59,7 @@
|
||||
<ClInclude Include="fzf/fzf.h">
|
||||
<Filter>fzf</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DesktopNotification.h" />
|
||||
<ClInclude Include="Toast.h" />
|
||||
<ClInclude Include="LanguageProfileNotifier.h" />
|
||||
<ClInclude Include="WindowsPackageManagerFactory.h" />
|
||||
|
||||
@@ -570,6 +570,8 @@ 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, uint32_t tabIndex);
|
||||
|
||||
#pragma region ActionHandlers
|
||||
// These are all defined in AppActionHandlers.cpp
|
||||
#define ON_ALL_ACTIONS(action) DECLARE_ACTION_HANDLER(action);
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "../../types/inc/utils.hpp"
|
||||
|
||||
#include "BellEventArgs.g.cpp"
|
||||
#include "NotificationEventArgs.g.cpp"
|
||||
#include "TerminalPaneContent.g.cpp"
|
||||
|
||||
using namespace winrt::Windows::Foundation;
|
||||
@@ -34,8 +35,11 @@ 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._OutputStarted = _control.OutputStarted(winrt::auto_revoke, { get_weak(), &TerminalPaneContent::_controlOutputStartedHandler });
|
||||
_controlEvents._CloseTerminalRequested = _control.CloseTerminalRequested(winrt::auto_revoke, { get_weak(), &TerminalPaneContent::_closeTerminalRequestedHandler });
|
||||
_controlEvents._RestartTerminalRequested = _control.RestartTerminalRequested(winrt::auto_revoke, { get_weak(), &TerminalPaneContent::_restartTerminalRequestedHandler });
|
||||
_controlEvents._OutputIdle = _control.OutputIdle(winrt::auto_revoke, { get_weak(), &TerminalPaneContent::_controlOutputIdleHandler });
|
||||
|
||||
_controlEvents._TitleChanged = _control.TitleChanged(winrt::auto_revoke, { get_weak(), &TerminalPaneContent::_controlTitleChanged });
|
||||
_controlEvents._TabColorChanged = _control.TabColorChanged(winrt::auto_revoke, { get_weak(), &TerminalPaneContent::_controlTabColorChanged });
|
||||
@@ -261,6 +265,30 @@ namespace winrt::TerminalApp::implementation
|
||||
// has the 'visual' flag set
|
||||
// Arguments:
|
||||
// - <unused>
|
||||
// Method Description:
|
||||
// - Plays the notification sound using the profile's BellSound setting if
|
||||
// configured; otherwise falls back to the system "Critical Stop" sound.
|
||||
// Reused by the warning bell handler, NotifyOnNextPrompt, and
|
||||
// NotifyOnInactiveOutput (called from Tab after the active-pane check).
|
||||
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*/)
|
||||
{
|
||||
@@ -271,19 +299,7 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
if (WI_IsFlagSet(_profile.BellStyle(), winrt::Microsoft::Terminal::Settings::Model::BellStyle::Audible))
|
||||
{
|
||||
// Audible is set, play the sound
|
||||
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);
|
||||
}
|
||||
PlayNotificationSound();
|
||||
}
|
||||
|
||||
if (WI_IsFlagSet(_profile.BellStyle(), winrt::Microsoft::Terminal::Settings::Model::BellStyle::Window))
|
||||
@@ -291,9 +307,112 @@ namespace winrt::TerminalApp::implementation
|
||||
_control.BellLightOn();
|
||||
}
|
||||
|
||||
// raise the event with the bool value corresponding to the taskbar flag
|
||||
// raise the event with the bool values corresponding to the taskbar and notification flags
|
||||
BellRequested.raise(*this,
|
||||
*winrt::make_self<TerminalApp::implementation::BellEventArgs>(WI_IsFlagSet(_profile.BellStyle(), BellStyle::Taskbar)));
|
||||
*winrt::make_self<TerminalApp::implementation::BellEventArgs>(
|
||||
WI_IsFlagSet(_profile.BellStyle(), BellStyle::Taskbar),
|
||||
WI_IsFlagSet(_profile.BellStyle(), BellStyle::Notification)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Returns the taskbar state, accounting for auto-detected running command progress.
|
||||
// VT-set progress (OSC 9;4) takes precedence over auto-detected progress.
|
||||
uint64_t TerminalPaneContent::TaskbarState()
|
||||
{
|
||||
const auto vtState = _control.TaskbarState();
|
||||
// VT-set progress takes precedence over auto-detected progress
|
||||
if (vtState != 0)
|
||||
{
|
||||
return vtState;
|
||||
}
|
||||
// Auto-detected indeterminate progress (between command start and prompt return)
|
||||
if (_autoDetectActive)
|
||||
{
|
||||
return 3; // TaskbarState::Indeterminate
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Returns the taskbar progress, accounting for auto-detected running command progress.
|
||||
uint64_t TerminalPaneContent::TaskbarProgress()
|
||||
{
|
||||
const auto vtState = _control.TaskbarState();
|
||||
// VT-set progress takes precedence
|
||||
if (vtState != 0)
|
||||
{
|
||||
return _control.TaskbarProgress();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Raised when a shell integration prompt mark (133;A) is received, indicating
|
||||
// the command has finished and we're back at a prompt.
|
||||
// - Checks NotifyOnNextPrompt setting and raises NotificationRequested.
|
||||
// - If autoDetectRunningCommand is enabled, clears the indeterminate progress ring.
|
||||
void TerminalPaneContent::_controlPromptStartedHandler(const winrt::Windows::Foundation::IInspectable& /*sender*/,
|
||||
const winrt::Windows::Foundation::IInspectable& /*eventArgs*/)
|
||||
{
|
||||
if (_profile)
|
||||
{
|
||||
// Check NotifyOnNextPrompt setting and raise a notification.
|
||||
// Pass OnlyWhenInactive=true so Tab suppresses notifications when
|
||||
// this pane is active in a focused tab.
|
||||
const auto notifyStyle = _profile.NotifyOnNextPrompt();
|
||||
if (static_cast<int>(notifyStyle) != 0)
|
||||
{
|
||||
NotificationRequested.raise(*this,
|
||||
*winrt::make_self<TerminalApp::implementation::NotificationEventArgs>(notifyStyle, true));
|
||||
}
|
||||
|
||||
// If autoDetectRunningCommand is enabled, clear the progress ring
|
||||
const auto autoDetect = _profile.AutoDetectRunningCommand();
|
||||
if (autoDetect != AutoDetectRunningCommand::Disabled && _autoDetectActive)
|
||||
{
|
||||
_autoDetectActive = false;
|
||||
TaskbarProgressChanged.raise(*this, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Raised when a shell integration command output mark (133;C) is received,
|
||||
// indicating a command has started executing.
|
||||
// - If autoDetectRunningCommand is enabled, shows an indeterminate progress ring.
|
||||
void TerminalPaneContent::_controlOutputStartedHandler(const winrt::Windows::Foundation::IInspectable& /*sender*/,
|
||||
const winrt::Windows::Foundation::IInspectable& /*eventArgs*/)
|
||||
{
|
||||
if (_profile)
|
||||
{
|
||||
const auto autoDetect = _profile.AutoDetectRunningCommand();
|
||||
if (autoDetect != AutoDetectRunningCommand::Disabled && !_autoDetectActive)
|
||||
{
|
||||
_autoDetectActive = true;
|
||||
TaskbarProgressChanged.raise(*this, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Raised when output stops being produced for ~100ms (debounced).
|
||||
// Used to detect output in inactive panes for NotifyOnInactiveOutput.
|
||||
// - Raises NotificationRequested so Tab can show activity indicators.
|
||||
void TerminalPaneContent::_controlOutputIdleHandler(const winrt::Windows::Foundation::IInspectable& /*sender*/,
|
||||
const winrt::Windows::Foundation::IInspectable& /*eventArgs*/)
|
||||
{
|
||||
if (_profile)
|
||||
{
|
||||
const auto notifyStyle = _profile.NotifyOnInactiveOutput();
|
||||
if (static_cast<int>(notifyStyle) != 0)
|
||||
{
|
||||
// Raise NotificationRequested so Tab can handle Taskbar/Tab/Audible flags.
|
||||
// Pass OnlyWhenInactive=true so Tab skips notifications for the active pane.
|
||||
// Note: Audible is handled by Tab (not here) so it can be gated on active state.
|
||||
NotificationRequested.raise(*this,
|
||||
*winrt::make_self<TerminalApp::implementation::NotificationEventArgs>(notifyStyle, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#pragma once
|
||||
#include "TerminalPaneContent.g.h"
|
||||
#include "BellEventArgs.g.h"
|
||||
#include "NotificationEventArgs.g.h"
|
||||
#include "BasicPaneEvents.h"
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
@@ -13,10 +14,21 @@ namespace winrt::TerminalApp::implementation
|
||||
struct BellEventArgs : public BellEventArgsT<BellEventArgs>
|
||||
{
|
||||
public:
|
||||
BellEventArgs(bool flashTaskbar) :
|
||||
FlashTaskbar(flashTaskbar) {}
|
||||
BellEventArgs(bool flashTaskbar, bool sendNotification) :
|
||||
FlashTaskbar(flashTaskbar), SendNotification(sendNotification) {}
|
||||
|
||||
til::property<bool> FlashTaskbar;
|
||||
til::property<bool> SendNotification;
|
||||
};
|
||||
|
||||
struct NotificationEventArgs : public NotificationEventArgsT<NotificationEventArgs>
|
||||
{
|
||||
public:
|
||||
NotificationEventArgs(winrt::Microsoft::Terminal::Control::OutputNotificationStyle style, bool onlyWhenInactive = false) :
|
||||
Style(style), OnlyWhenInactive(onlyWhenInactive) {}
|
||||
|
||||
til::property<winrt::Microsoft::Terminal::Control::OutputNotificationStyle> Style;
|
||||
til::property<bool> OnlyWhenInactive;
|
||||
};
|
||||
|
||||
struct TerminalPaneContent : TerminalPaneContentT<TerminalPaneContent>, BasicPaneEvents
|
||||
@@ -36,6 +48,7 @@ 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
|
||||
{
|
||||
@@ -43,8 +56,8 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
|
||||
winrt::hstring Title() { return _control.Title(); }
|
||||
uint64_t TaskbarState() { return _control.TaskbarState(); }
|
||||
uint64_t TaskbarProgress() { return _control.TaskbarProgress(); }
|
||||
uint64_t TaskbarState();
|
||||
uint64_t TaskbarProgress();
|
||||
bool ReadOnly() { return _control.ReadOnly(); }
|
||||
winrt::hstring Icon() const;
|
||||
Windows::Foundation::IReference<winrt::Windows::UI::Color> TabColor() const noexcept;
|
||||
@@ -66,11 +79,15 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
winrt::Windows::Media::Playback::MediaPlayer _bellPlayer{ nullptr };
|
||||
bool _bellPlayerCreated{ false };
|
||||
std::atomic<bool> _autoDetectActive{ false };
|
||||
|
||||
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 _OutputIdle;
|
||||
winrt::Microsoft::Terminal::Control::TermControl::CloseTerminalRequested_revoker _CloseTerminalRequested;
|
||||
winrt::Microsoft::Terminal::Control::TermControl::RestartTerminalRequested_revoker _RestartTerminalRequested;
|
||||
|
||||
@@ -89,6 +106,12 @@ 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& e);
|
||||
void _controlOutputStartedHandler(const winrt::Windows::Foundation::IInspectable& sender,
|
||||
const winrt::Windows::Foundation::IInspectable& e);
|
||||
void _controlOutputIdleHandler(const winrt::Windows::Foundation::IInspectable& sender,
|
||||
const winrt::Windows::Foundation::IInspectable& e);
|
||||
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,6 +11,7 @@ namespace TerminalApp
|
||||
Microsoft.Terminal.Control.TermControl GetTermControl();
|
||||
|
||||
void MarkAsDefterm();
|
||||
void PlayNotificationSound();
|
||||
|
||||
Microsoft.Terminal.Settings.Model.Profile GetProfile();
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ 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,6 +12,7 @@ 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; };
|
||||
|
||||
@@ -54,6 +54,9 @@
|
||||
#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>
|
||||
|
||||
@@ -118,6 +118,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
auto pfnWarningBell = [this] { _terminalWarningBell(); };
|
||||
_terminal->SetWarningBellCallback(pfnWarningBell);
|
||||
|
||||
auto pfnPromptStarted = [this] { _terminalPromptStarted(); };
|
||||
_terminal->SetPromptStartedCallback(pfnPromptStarted);
|
||||
|
||||
auto pfnOutputStarted = [this] { _terminalOutputStarted(); };
|
||||
_terminal->SetOutputStartedCallback(pfnOutputStarted);
|
||||
|
||||
auto pfnTitleChanged = [this](auto&& PH1) { _terminalTitleChanged(std::forward<decltype(PH1)>(PH1)); };
|
||||
_terminal->SetTitleChangedCallback(pfnTitleChanged);
|
||||
|
||||
@@ -1590,9 +1596,37 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
// Since this can only ever be triggered by output from the connection,
|
||||
// then the Terminal already has the write lock when calling this
|
||||
// callback.
|
||||
if (_restoring)
|
||||
{
|
||||
return;
|
||||
}
|
||||
WarningBell.raise(*this, nullptr);
|
||||
}
|
||||
|
||||
void ControlCore::_terminalPromptStarted()
|
||||
{
|
||||
// Since this can only ever be triggered by output from the connection,
|
||||
// then the Terminal already has the write lock when calling this
|
||||
// callback.
|
||||
if (_restoring)
|
||||
{
|
||||
return;
|
||||
}
|
||||
PromptStarted.raise(*this, nullptr);
|
||||
}
|
||||
|
||||
void ControlCore::_terminalOutputStarted()
|
||||
{
|
||||
// Since this can only ever be triggered by output from the connection,
|
||||
// then the Terminal already has the write lock when calling this
|
||||
// callback.
|
||||
if (_restoring)
|
||||
{
|
||||
return;
|
||||
}
|
||||
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.
|
||||
@@ -1650,6 +1684,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
|
||||
void ControlCore::_terminalTaskbarProgressChanged()
|
||||
{
|
||||
if (_restoring)
|
||||
{
|
||||
return;
|
||||
}
|
||||
TaskbarProgressChanged.raise(*this, nullptr);
|
||||
}
|
||||
|
||||
@@ -1667,6 +1705,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
// - duration - How long the note should be sustained (in microseconds).
|
||||
void ControlCore::_terminalPlayMidiNote(const int noteNumber, const int velocity, const std::chrono::microseconds duration)
|
||||
{
|
||||
if (_restoring)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// The UI thread might try to acquire the console lock from time to time.
|
||||
// --> Unlock it, so the UI doesn't hang while we're busy.
|
||||
const auto suspension = _terminal->SuspendLock();
|
||||
@@ -1839,8 +1881,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
_terminal->SerializeMainBuffer(handle);
|
||||
}
|
||||
|
||||
void ControlCore::RestoreFromPath(const wchar_t* path) const
|
||||
void ControlCore::RestoreFromPath(const wchar_t* path)
|
||||
{
|
||||
// Suppress notifications (bells, prompt-returned, command-started, etc.)
|
||||
// while we replay persisted buffer content. Without this, restoring a
|
||||
// session fires the same events that live output would, producing
|
||||
// unwanted audible bells, tab activity indicators, and taskbar flashes.
|
||||
_restoring = true;
|
||||
const auto restoreComplete = wil::scope_exit([&] { _restoring = false; });
|
||||
|
||||
wil::unique_handle file{ CreateFileW(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, nullptr) };
|
||||
|
||||
// This block of code exists temporarily to fix buffer dumps that were
|
||||
|
||||
@@ -154,7 +154,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
|
||||
void Close();
|
||||
void PersistTo(HANDLE handle) const;
|
||||
void RestoreFromPath(const wchar_t* path) const;
|
||||
void RestoreFromPath(const wchar_t* path);
|
||||
|
||||
void ClearQuickFix();
|
||||
|
||||
@@ -276,6 +276,8 @@ 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;
|
||||
@@ -324,6 +326,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
|
||||
#pragma region TerminalCoreCallbacks
|
||||
void _terminalWarningBell();
|
||||
void _terminalPromptStarted();
|
||||
void _terminalOutputStarted();
|
||||
void _terminalTitleChanged(std::wstring_view wstr);
|
||||
void _terminalScrollPositionChanged(const int viewTop,
|
||||
const int viewHeight,
|
||||
@@ -420,6 +424,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
std::optional<til::point> _lastHoveredCell;
|
||||
uint16_t _lastHoveredId{ 0 };
|
||||
std::atomic<bool> _initializedTerminal{ false };
|
||||
std::atomic<bool> _restoring{ false };
|
||||
bool _isReadOnly{ false };
|
||||
bool _closing{ false };
|
||||
|
||||
|
||||
@@ -191,6 +191,8 @@ 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;
|
||||
|
||||
@@ -29,6 +29,23 @@ namespace Microsoft.Terminal.Control
|
||||
MinGW,
|
||||
};
|
||||
|
||||
[flags]
|
||||
enum OutputNotificationStyle
|
||||
{
|
||||
Taskbar = 0x1,
|
||||
Audible = 0x2,
|
||||
Tab = 0x4,
|
||||
Notification = 0x8,
|
||||
All = 0xffffffff
|
||||
};
|
||||
|
||||
enum AutoDetectRunningCommand
|
||||
{
|
||||
Disabled,
|
||||
Automatic,
|
||||
Progress
|
||||
};
|
||||
|
||||
// Class Description:
|
||||
// TerminalSettings encapsulates all settings that control the
|
||||
// TermControl's behavior. In these settings there is both the entirety
|
||||
@@ -77,6 +94,10 @@ namespace Microsoft.Terminal.Control
|
||||
|
||||
PathTranslationStyle PathTranslationStyle { get; };
|
||||
|
||||
OutputNotificationStyle NotifyOnInactiveOutput { get; };
|
||||
OutputNotificationStyle NotifyOnNextPrompt { get; };
|
||||
AutoDetectRunningCommand AutoDetectRunningCommand { get; };
|
||||
|
||||
// NOTE! When adding something here, make sure to update ControlProperties.h too!
|
||||
};
|
||||
}
|
||||
|
||||
@@ -393,6 +393,8 @@ 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);
|
||||
@@ -3699,6 +3701,16 @@ 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();
|
||||
@@ -3820,6 +3832,7 @@ 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)
|
||||
|
||||
@@ -212,6 +212,9 @@ 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;
|
||||
@@ -425,6 +428,8 @@ 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);
|
||||
@@ -450,6 +455,8 @@ 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;
|
||||
|
||||
@@ -68,6 +68,9 @@ namespace Microsoft.Terminal.Control
|
||||
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;
|
||||
|
||||
@@ -751,6 +751,11 @@ TerminalInput::OutputType Terminal::SendCharEvent(const wchar_t ch, const WORD s
|
||||
// This changed the scrollbar marks - raise a notification to update them
|
||||
_NotifyScrollEvent();
|
||||
}
|
||||
// regardless, start notify that we started command output
|
||||
if (_pfnOutputStarted)
|
||||
{
|
||||
_pfnOutputStarted();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1265,6 +1270,16 @@ 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
|
||||
|
||||
@@ -156,7 +156,7 @@ public:
|
||||
|
||||
bool IsVtInputEnabled() const noexcept override;
|
||||
void NotifyBufferRotation(const int delta) override;
|
||||
void NotifyShellIntegrationMark() override;
|
||||
void NotifyShellIntegrationMark(ShellIntegrationMark mark) override;
|
||||
|
||||
void InvokeCompletions(std::wstring_view menuJson, unsigned int replaceLength) override;
|
||||
|
||||
@@ -232,6 +232,8 @@ 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);
|
||||
@@ -340,6 +342,8 @@ 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;
|
||||
|
||||
@@ -400,8 +400,26 @@ void Terminal::NotifyBufferRotation(const int delta)
|
||||
}
|
||||
}
|
||||
|
||||
void Terminal::NotifyShellIntegrationMark()
|
||||
void Terminal::NotifyShellIntegrationMark(ShellIntegrationMark mark)
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -353,6 +353,10 @@ namespace winrt::Microsoft::Terminal::Settings
|
||||
_AllowVtChecksumReport = profile.AllowVtChecksumReport();
|
||||
_AllowVtClipboardWrite = profile.AllowVtClipboardWrite();
|
||||
_PathTranslationStyle = profile.PathTranslationStyle();
|
||||
|
||||
_NotifyOnInactiveOutput = profile.NotifyOnInactiveOutput();
|
||||
_NotifyOnNextPrompt = profile.NotifyOnNextPrompt();
|
||||
_AutoDetectRunningCommand = profile.AutoDetectRunningCommand();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
||||
@@ -40,6 +40,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
INITIALIZE_BINDABLE_ENUM_SETTING_REVERSE_ORDER(CloseOnExitMode, CloseOnExitMode, winrt::Microsoft::Terminal::Settings::Model::CloseOnExitMode, L"Profile_CloseOnExit", L"Content");
|
||||
INITIALIZE_BINDABLE_ENUM_SETTING(ScrollState, ScrollbarState, winrt::Microsoft::Terminal::Control::ScrollbarState, L"Profile_ScrollbarVisibility", L"Content");
|
||||
INITIALIZE_BINDABLE_ENUM_SETTING(PathTranslationStyle, PathTranslationStyle, winrt::Microsoft::Terminal::Control::PathTranslationStyle, L"Profile_PathTranslationStyle", L"Content");
|
||||
INITIALIZE_BINDABLE_ENUM_SETTING(AutoDetectRunningCommand, AutoDetectRunningCommand, winrt::Microsoft::Terminal::Control::AutoDetectRunningCommand, L"Profile_AutoDetectRunningCommand", L"Content");
|
||||
|
||||
_InitializeCurrentBellSounds();
|
||||
|
||||
@@ -574,7 +575,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
hstring ProfileViewModel::BellStylePreview() const
|
||||
{
|
||||
const auto bellStyle = BellStyle();
|
||||
if (WI_AreAllFlagsSet(bellStyle, BellStyle::Audible | BellStyle::Window | BellStyle::Taskbar))
|
||||
if (WI_AreAllFlagsSet(bellStyle, BellStyle::Audible | BellStyle::Window | BellStyle::Taskbar | BellStyle::Notification))
|
||||
{
|
||||
return RS_(L"Profile_BellStyleAll/Content");
|
||||
}
|
||||
@@ -584,7 +585,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
}
|
||||
|
||||
std::vector<hstring> resultList;
|
||||
resultList.reserve(3);
|
||||
resultList.reserve(4);
|
||||
if (WI_IsFlagSet(bellStyle, BellStyle::Audible))
|
||||
{
|
||||
resultList.emplace_back(RS_(L"Profile_BellStyleAudible/Content"));
|
||||
@@ -597,6 +598,10 @@ 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{};
|
||||
@@ -640,6 +645,177 @@ 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);
|
||||
}
|
||||
|
||||
// ===================== NotifyOnInactiveOutput =====================
|
||||
|
||||
hstring ProfileViewModel::NotifyOnInactiveOutputPreview() const
|
||||
{
|
||||
using Ons = Control::OutputNotificationStyle;
|
||||
const auto style = NotifyOnInactiveOutput();
|
||||
if (WI_AreAllFlagsSet(style, Ons::Taskbar | Ons::Audible | Ons::Tab | Ons::Notification))
|
||||
{
|
||||
return RS_(L"Profile_OutputNotificationStyleAll/Content");
|
||||
}
|
||||
else if (style == static_cast<Ons>(0))
|
||||
{
|
||||
return RS_(L"Profile_OutputNotificationStyleNone/Content");
|
||||
}
|
||||
|
||||
std::vector<hstring> resultList;
|
||||
resultList.reserve(4);
|
||||
if (WI_IsFlagSet(style, Ons::Taskbar))
|
||||
{
|
||||
resultList.emplace_back(RS_(L"Profile_OutputNotificationStyleTaskbar/Content"));
|
||||
}
|
||||
if (WI_IsFlagSet(style, Ons::Audible))
|
||||
{
|
||||
resultList.emplace_back(RS_(L"Profile_OutputNotificationStyleAudible/Content"));
|
||||
}
|
||||
if (WI_IsFlagSet(style, Ons::Tab))
|
||||
{
|
||||
resultList.emplace_back(RS_(L"Profile_OutputNotificationStyleTab/Content"));
|
||||
}
|
||||
if (WI_IsFlagSet(style, Ons::Notification))
|
||||
{
|
||||
resultList.emplace_back(RS_(L"Profile_OutputNotificationStyleNotification/Content"));
|
||||
}
|
||||
|
||||
hstring result{};
|
||||
for (auto&& entry : resultList)
|
||||
{
|
||||
if (result.empty())
|
||||
{
|
||||
result = entry;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = result + L", " + entry;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ProfileViewModel::IsNotifyOnInactiveOutputFlagSet(const uint32_t flag)
|
||||
{
|
||||
return (WI_EnumValue(NotifyOnInactiveOutput()) & flag) == flag;
|
||||
}
|
||||
|
||||
void ProfileViewModel::SetNotifyOnInactiveOutputTaskbar(winrt::Windows::Foundation::IReference<bool> on)
|
||||
{
|
||||
auto currentStyle = NotifyOnInactiveOutput();
|
||||
WI_UpdateFlag(currentStyle, Control::OutputNotificationStyle::Taskbar, winrt::unbox_value<bool>(on));
|
||||
NotifyOnInactiveOutput(currentStyle);
|
||||
}
|
||||
|
||||
void ProfileViewModel::SetNotifyOnInactiveOutputAudible(winrt::Windows::Foundation::IReference<bool> on)
|
||||
{
|
||||
auto currentStyle = NotifyOnInactiveOutput();
|
||||
WI_UpdateFlag(currentStyle, Control::OutputNotificationStyle::Audible, winrt::unbox_value<bool>(on));
|
||||
NotifyOnInactiveOutput(currentStyle);
|
||||
}
|
||||
|
||||
void ProfileViewModel::SetNotifyOnInactiveOutputTab(winrt::Windows::Foundation::IReference<bool> on)
|
||||
{
|
||||
auto currentStyle = NotifyOnInactiveOutput();
|
||||
WI_UpdateFlag(currentStyle, Control::OutputNotificationStyle::Tab, winrt::unbox_value<bool>(on));
|
||||
NotifyOnInactiveOutput(currentStyle);
|
||||
}
|
||||
|
||||
void ProfileViewModel::SetNotifyOnInactiveOutputNotification(winrt::Windows::Foundation::IReference<bool> on)
|
||||
{
|
||||
auto currentStyle = NotifyOnInactiveOutput();
|
||||
WI_UpdateFlag(currentStyle, Control::OutputNotificationStyle::Notification, winrt::unbox_value<bool>(on));
|
||||
NotifyOnInactiveOutput(currentStyle);
|
||||
}
|
||||
|
||||
// ===================== 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 == static_cast<Ons>(0))
|
||||
{
|
||||
return RS_(L"Profile_OutputNotificationStyleNone/Content");
|
||||
}
|
||||
|
||||
std::vector<hstring> resultList;
|
||||
resultList.reserve(4);
|
||||
if (WI_IsFlagSet(style, Ons::Taskbar))
|
||||
{
|
||||
resultList.emplace_back(RS_(L"Profile_OutputNotificationStyleTaskbar/Content"));
|
||||
}
|
||||
if (WI_IsFlagSet(style, Ons::Audible))
|
||||
{
|
||||
resultList.emplace_back(RS_(L"Profile_OutputNotificationStyleAudible/Content"));
|
||||
}
|
||||
if (WI_IsFlagSet(style, Ons::Tab))
|
||||
{
|
||||
resultList.emplace_back(RS_(L"Profile_OutputNotificationStyleTab/Content"));
|
||||
}
|
||||
if (WI_IsFlagSet(style, Ons::Notification))
|
||||
{
|
||||
resultList.emplace_back(RS_(L"Profile_OutputNotificationStyleNotification/Content"));
|
||||
}
|
||||
|
||||
hstring result{};
|
||||
for (auto&& entry : resultList)
|
||||
{
|
||||
if (result.empty())
|
||||
{
|
||||
result = entry;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = result + L", " + entry;
|
||||
}
|
||||
}
|
||||
return 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);
|
||||
}
|
||||
|
||||
// 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
|
||||
|
||||
@@ -46,6 +46,23 @@ 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 inactive output bits
|
||||
hstring NotifyOnInactiveOutputPreview() const;
|
||||
bool IsNotifyOnInactiveOutputFlagSet(const uint32_t flag);
|
||||
void SetNotifyOnInactiveOutputTaskbar(winrt::Windows::Foundation::IReference<bool> on);
|
||||
void SetNotifyOnInactiveOutputAudible(winrt::Windows::Foundation::IReference<bool> on);
|
||||
void SetNotifyOnInactiveOutputTab(winrt::Windows::Foundation::IReference<bool> on);
|
||||
void SetNotifyOnInactiveOutputNotification(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);
|
||||
@@ -146,12 +163,17 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, RainbowSuggestions);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, PathTranslationStyle);
|
||||
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, NotifyOnInactiveOutput);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, NotifyOnNextPrompt);
|
||||
OBSERVABLE_PROJECTED_SETTING(_profile, AutoDetectRunningCommand);
|
||||
|
||||
WINRT_PROPERTY(bool, IsBaseLayer, false);
|
||||
WINRT_PROPERTY(bool, FocusDeleteButton, false);
|
||||
GETSET_BINDABLE_ENUM_SETTING(AntiAliasingMode, Microsoft::Terminal::Control::TextAntialiasingMode, AntialiasingMode);
|
||||
GETSET_BINDABLE_ENUM_SETTING(CloseOnExitMode, Microsoft::Terminal::Settings::Model::CloseOnExitMode, CloseOnExit);
|
||||
GETSET_BINDABLE_ENUM_SETTING(ScrollState, Microsoft::Terminal::Control::ScrollbarState, ScrollState);
|
||||
GETSET_BINDABLE_ENUM_SETTING(PathTranslationStyle, Microsoft::Terminal::Control::PathTranslationStyle, PathTranslationStyle);
|
||||
GETSET_BINDABLE_ENUM_SETTING(AutoDetectRunningCommand, Microsoft::Terminal::Control::AutoDetectRunningCommand, AutoDetectRunningCommand);
|
||||
|
||||
private:
|
||||
Model::Profile _profile;
|
||||
|
||||
@@ -49,6 +49,24 @@ 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 NotifyOnInactiveOutputPreview { get; };
|
||||
Boolean IsNotifyOnInactiveOutputFlagSet(UInt32 flag);
|
||||
void SetNotifyOnInactiveOutputTaskbar(Windows.Foundation.IReference<Boolean> on);
|
||||
void SetNotifyOnInactiveOutputAudible(Windows.Foundation.IReference<Boolean> on);
|
||||
void SetNotifyOnInactiveOutputTab(Windows.Foundation.IReference<Boolean> on);
|
||||
void SetNotifyOnInactiveOutputNotification(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);
|
||||
|
||||
IInspectable CurrentAutoDetectRunningCommand;
|
||||
Windows.Foundation.Collections.IObservableVector<Microsoft.Terminal.Settings.Editor.EnumEntry> AutoDetectRunningCommandList { get; };
|
||||
|
||||
String BellSoundPreview { get; };
|
||||
Windows.Foundation.Collections.IObservableVector<BellSoundViewModel> CurrentBellSounds { get; };
|
||||
@@ -140,5 +158,8 @@ namespace Microsoft.Terminal.Settings.Editor
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, RainbowSuggestions);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Microsoft.Terminal.Control.PathTranslationStyle, PathTranslationStyle);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, AllowVtClipboardWrite);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Microsoft.Terminal.Control.OutputNotificationStyle, NotifyOnInactiveOutput);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Microsoft.Terminal.Control.OutputNotificationStyle, NotifyOnNextPrompt);
|
||||
OBSERVABLE_PROJECTED_PROFILE_SETTING(Microsoft.Terminal.Control.AutoDetectRunningCommand, AutoDetectRunningCommand);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,6 +111,8 @@
|
||||
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>
|
||||
|
||||
@@ -196,6 +198,59 @@
|
||||
</StackPanel>
|
||||
</local:SettingContainer>
|
||||
|
||||
<!-- Notify On Inactive Output -->
|
||||
<local:SettingContainer x:Name="NotifyOnInactiveOutput"
|
||||
x:Uid="Profile_NotifyOnInactiveOutput"
|
||||
ClearSettingValue="{x:Bind Profile.ClearNotifyOnInactiveOutput}"
|
||||
CurrentValue="{x:Bind Profile.NotifyOnInactiveOutputPreview, Mode=OneWay}"
|
||||
HasSettingValue="{x:Bind Profile.HasNotifyOnInactiveOutput, Mode=OneWay}"
|
||||
SettingOverrideSource="{x:Bind Profile.NotifyOnInactiveOutputOverrideSource, Mode=OneWay}"
|
||||
Style="{StaticResource ExpanderSettingContainerStyle}">
|
||||
<StackPanel>
|
||||
<CheckBox x:Uid="Profile_OutputNotificationStyleTaskbar"
|
||||
IsChecked="{x:Bind Profile.IsNotifyOnInactiveOutputFlagSet(1), BindBack=Profile.SetNotifyOnInactiveOutputTaskbar, Mode=TwoWay}" />
|
||||
<CheckBox x:Uid="Profile_OutputNotificationStyleAudible"
|
||||
IsChecked="{x:Bind Profile.IsNotifyOnInactiveOutputFlagSet(2), BindBack=Profile.SetNotifyOnInactiveOutputAudible, Mode=TwoWay}" />
|
||||
<CheckBox x:Uid="Profile_OutputNotificationStyleTab"
|
||||
IsChecked="{x:Bind Profile.IsNotifyOnInactiveOutputFlagSet(4), BindBack=Profile.SetNotifyOnInactiveOutputTab, Mode=TwoWay}" />
|
||||
<CheckBox x:Uid="Profile_OutputNotificationStyleNotification"
|
||||
IsChecked="{x:Bind Profile.IsNotifyOnInactiveOutputFlagSet(8), BindBack=Profile.SetNotifyOnInactiveOutputNotification, Mode=TwoWay}" />
|
||||
</StackPanel>
|
||||
</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>
|
||||
|
||||
<!-- 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}">
|
||||
<ComboBox AutomationProperties.AccessibilityView="Content"
|
||||
ItemTemplate="{StaticResource EnumComboBoxTemplate}"
|
||||
ItemsSource="{x:Bind Profile.AutoDetectRunningCommandList, Mode=OneWay}"
|
||||
SelectedItem="{x:Bind Profile.CurrentAutoDetectRunningCommand, Mode=TwoWay}"
|
||||
Style="{StaticResource ComboBoxSettingStyle}" />
|
||||
</local:SettingContainer>
|
||||
|
||||
<!-- RightClickContextMenu -->
|
||||
<local:SettingContainer x:Name="RightClickContextMenu"
|
||||
x:Uid="Profile_RightClickContextMenu"
|
||||
|
||||
@@ -1553,6 +1553,10 @@
|
||||
<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_BellStyleNotification.Content" xml:space="preserve">
|
||||
<value>Send 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>
|
||||
@@ -2748,4 +2752,92 @@
|
||||
<value>Type to filter icons</value>
|
||||
<comment>Placeholder text for a text box to filter and select an icon.</comment>
|
||||
</data>
|
||||
<!-- OutputNotificationStyle shared checkbox labels -->
|
||||
<data name="Profile_OutputNotificationStyleTaskbar.Content" xml:space="preserve">
|
||||
<value>Flash taskbar</value>
|
||||
<comment>An option to choose from for a notification style setting. When selected, the taskbar is flashed.</comment>
|
||||
</data>
|
||||
<data name="Profile_OutputNotificationStyleAudible.Content" xml:space="preserve">
|
||||
<value>Audible</value>
|
||||
<comment>An option to choose from for a notification style setting. When selected, an audible cue is played.</comment>
|
||||
</data>
|
||||
<data name="Profile_OutputNotificationStyleTab.Content" xml:space="preserve">
|
||||
<value>Tab indicator</value>
|
||||
<comment>An option to choose from for a notification style setting. When selected, an activity indicator is shown on the tab.</comment>
|
||||
</data>
|
||||
<data name="Profile_OutputNotificationStyleNotification.Content" xml:space="preserve">
|
||||
<value>Desktop notification</value>
|
||||
<comment>An option to choose from for a notification style setting. When selected, a desktop toast notification is sent.</comment>
|
||||
</data>
|
||||
<data name="Profile_OutputNotificationStyleAll/Content" xml:space="preserve">
|
||||
<value>All</value>
|
||||
<comment>An option label for notification style. Shown when all notification styles are enabled.</comment>
|
||||
</data>
|
||||
<data name="Profile_OutputNotificationStyleNone/Content" xml:space="preserve">
|
||||
<value>None</value>
|
||||
<comment>An option label for notification style. Shown when no notification styles are enabled.</comment>
|
||||
</data>
|
||||
<!-- NotifyOnInactiveOutput -->
|
||||
<data name="Profile_NotifyOnInactiveOutput.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||
<value>Notify on inactive output</value>
|
||||
<comment>Name for a control to select how the app notifies the user when an inactive pane produces output.</comment>
|
||||
</data>
|
||||
<data name="Profile_NotifyOnInactiveOutput.Header" xml:space="preserve">
|
||||
<value>Notify on inactive output</value>
|
||||
<comment>Header for a control to select how the app notifies the user when an inactive pane produces output.</comment>
|
||||
</data>
|
||||
<data name="Profile_NotifyOnInactiveOutput.HelpText" xml:space="preserve">
|
||||
<value>Controls how you are notified when a background pane produces new output.</value>
|
||||
<comment>A description for what the "notify on inactive output" setting does.</comment>
|
||||
</data>
|
||||
<!-- NotifyOnNextPrompt -->
|
||||
<data name="Profile_NotifyOnNextPrompt.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||
<value>Notify on next prompt</value>
|
||||
<comment>Name for a control to select how the app notifies the user when a command finishes and the shell returns to a prompt.</comment>
|
||||
</data>
|
||||
<data name="Profile_NotifyOnNextPrompt.Header" xml:space="preserve">
|
||||
<value>Notify on next prompt</value>
|
||||
<comment>Header for a control to select how the app notifies the user when a command finishes and the shell returns to a prompt.</comment>
|
||||
</data>
|
||||
<data name="Profile_NotifyOnNextPrompt.HelpText" xml:space="preserve">
|
||||
<value>Controls how you are notified when a running command finishes and the shell returns to a prompt. Requires shell integration.</value>
|
||||
<comment>A description for what the "notify on next prompt" setting does.</comment>
|
||||
</data>
|
||||
<!-- AutoDetectRunningCommand -->
|
||||
<data name="Profile_AutoDetectRunningCommand.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||
<value>Auto-detect running command</value>
|
||||
<comment>Name for a control to select how the app detects and indicates a running command.</comment>
|
||||
</data>
|
||||
<data name="Profile_AutoDetectRunningCommand.Header" xml:space="preserve">
|
||||
<value>Auto-detect running command</value>
|
||||
<comment>Header for a control to select how the app detects and indicates a running command.</comment>
|
||||
</data>
|
||||
<data name="Profile_AutoDetectRunningCommand.HelpText" xml:space="preserve">
|
||||
<value>Controls whether and how the terminal automatically shows progress while a command is running. Requires shell integration.</value>
|
||||
<comment>A description for what the "auto-detect running command" setting does.</comment>
|
||||
</data>
|
||||
<data name="Profile_AutoDetectRunningCommand_Disabled.Content" xml:space="preserve">
|
||||
<value>Disabled</value>
|
||||
<comment>An option to choose from for the "auto-detect running command" setting. When selected, no auto-detection occurs.</comment>
|
||||
</data>
|
||||
<data name="Profile_AutoDetectRunningCommand_Automatic.Content" xml:space="preserve">
|
||||
<value>Automatic</value>
|
||||
<comment>An option to choose from for the "auto-detect running command" setting. When selected, an indeterminate progress ring is shown while a command is running.</comment>
|
||||
</data>
|
||||
<data name="Profile_AutoDetectRunningCommand_Progress.Content" xml:space="preserve">
|
||||
<value>Progress</value>
|
||||
<comment>An option to choose from for the "auto-detect running command" setting. When selected, the terminal attempts to detect progress percentage from command output.</comment>
|
||||
</data>
|
||||
<data name="Profile_AutoDetectRunningCommandDisabled.Content" xml:space="preserve">
|
||||
<value>Disabled</value>
|
||||
<comment>An option to choose from for the "auto-detect running command" setting. When selected, no auto-detection occurs.</comment>
|
||||
</data>
|
||||
<data name="Profile_AutoDetectRunningCommandAutomatic.Content" xml:space="preserve">
|
||||
<value>Automatic</value>
|
||||
<comment>An option to choose from for the "auto-detect running command" setting. When selected, an indeterminate progress ring is shown while a command is running.</comment>
|
||||
</data>
|
||||
<data name="Profile_AutoDetectRunningCommandProgress.Content" xml:space="preserve">
|
||||
<value>Progress</value>
|
||||
<comment>An option to choose from for the "auto-detect running command" setting. When selected, the terminal attempts to detect progress percentage from command output.</comment>
|
||||
</data>
|
||||
</root>
|
||||
@@ -53,6 +53,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
DEFINE_ENUM_MAP(Microsoft::Terminal::Settings::Model::IntenseStyle, IntenseTextStyle);
|
||||
DEFINE_ENUM_MAP(Microsoft::Terminal::Core::AdjustTextMode, AdjustIndistinguishableColors);
|
||||
DEFINE_ENUM_MAP(Microsoft::Terminal::Control::PathTranslationStyle, PathTranslationStyle);
|
||||
DEFINE_ENUM_MAP(Microsoft::Terminal::Control::AutoDetectRunningCommand, AutoDetectRunningCommand);
|
||||
|
||||
// Actions
|
||||
DEFINE_ENUM_MAP(Microsoft::Terminal::Settings::Model::ResizeDirection, ResizeDirection);
|
||||
|
||||
@@ -51,6 +51,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::Microsoft::Terminal::Settings::Model::IntenseStyle> IntenseTextStyle();
|
||||
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::Microsoft::Terminal::Core::AdjustTextMode> AdjustIndistinguishableColors();
|
||||
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::Microsoft::Terminal::Control::PathTranslationStyle> PathTranslationStyle();
|
||||
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::Microsoft::Terminal::Control::AutoDetectRunningCommand> AutoDetectRunningCommand();
|
||||
|
||||
// Actions
|
||||
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::Microsoft::Terminal::Settings::Model::ResizeDirection> ResizeDirection();
|
||||
|
||||
@@ -33,6 +33,7 @@ namespace Microsoft.Terminal.Settings.Model
|
||||
static Windows.Foundation.Collections.IMap<String, UInt16> FontWeight { get; };
|
||||
static Windows.Foundation.Collections.IMap<String, Microsoft.Terminal.Settings.Model.IntenseStyle> IntenseTextStyle { get; };
|
||||
static Windows.Foundation.Collections.IMap<String, Microsoft.Terminal.Control.PathTranslationStyle> PathTranslationStyle { get; };
|
||||
static Windows.Foundation.Collections.IMap<String, Microsoft.Terminal.Control.AutoDetectRunningCommand> AutoDetectRunningCommand { get; };
|
||||
|
||||
// Actions
|
||||
static Windows.Foundation.Collections.IMap<String, Microsoft.Terminal.Settings.Model.ResizeDirection> ResizeDirection { get; };
|
||||
|
||||
@@ -79,36 +79,39 @@ 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(Microsoft::Terminal::Control::PathTranslationStyle, PathTranslationStyle, "pathTranslationStyle", Microsoft::Terminal::Control::PathTranslationStyle::None)
|
||||
#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(Microsoft::Terminal::Control::PathTranslationStyle, PathTranslationStyle, "pathTranslationStyle", Microsoft::Terminal::Control::PathTranslationStyle::None) \
|
||||
X(Microsoft::Terminal::Control::OutputNotificationStyle, NotifyOnInactiveOutput, "notifyOnInactiveOutput", Microsoft::Terminal::Control::OutputNotificationStyle{ 0 }) \
|
||||
X(Microsoft::Terminal::Control::OutputNotificationStyle, NotifyOnNextPrompt, "notifyOnNextPrompt", Microsoft::Terminal::Control::OutputNotificationStyle{ 0 }) \
|
||||
X(Microsoft::Terminal::Control::AutoDetectRunningCommand, AutoDetectRunningCommand, "autoDetectRunningCommand", Microsoft::Terminal::Control::AutoDetectRunningCommand::Disabled)
|
||||
|
||||
// Intentionally omitted Profile settings:
|
||||
// * Name
|
||||
|
||||
@@ -29,6 +29,7 @@ namespace Microsoft.Terminal.Settings.Model
|
||||
Audible = 0x1,
|
||||
Window = 0x2,
|
||||
Taskbar = 0x4,
|
||||
Notification = 0x8,
|
||||
All = 0xffffffff
|
||||
};
|
||||
|
||||
@@ -94,5 +95,9 @@ namespace Microsoft.Terminal.Settings.Model
|
||||
INHERITABLE_PROFILE_SETTING(Boolean, AllowVtClipboardWrite);
|
||||
|
||||
INHERITABLE_PROFILE_SETTING(Microsoft.Terminal.Control.PathTranslationStyle, PathTranslationStyle);
|
||||
|
||||
INHERITABLE_PROFILE_SETTING(Microsoft.Terminal.Control.OutputNotificationStyle, NotifyOnInactiveOutput);
|
||||
INHERITABLE_PROFILE_SETTING(Microsoft.Terminal.Control.OutputNotificationStyle, NotifyOnNextPrompt);
|
||||
INHERITABLE_PROFILE_SETTING(Microsoft.Terminal.Control.AutoDetectRunningCommand, AutoDetectRunningCommand);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,12 +90,13 @@ JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Core::MatchMode)
|
||||
|
||||
JSON_FLAG_MAPPER(::winrt::Microsoft::Terminal::Settings::Model::BellStyle)
|
||||
{
|
||||
static constexpr std::array<pair_type, 6> mappings = {
|
||||
static constexpr std::array<pair_type, 7> 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 },
|
||||
};
|
||||
|
||||
@@ -119,6 +120,46 @@ 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::Control::AutoDetectRunningCommand)
|
||||
{
|
||||
JSON_MAPPINGS(3) = {
|
||||
pair_type{ "disabled", ValueType::Disabled },
|
||||
pair_type{ "automatic", ValueType::Automatic },
|
||||
pair_type{ "progress", ValueType::Progress },
|
||||
};
|
||||
};
|
||||
|
||||
JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Settings::Model::ConvergedAlignment)
|
||||
{
|
||||
// reduce repetition
|
||||
|
||||
@@ -353,6 +353,23 @@ void WindowEmperor::HandleCommandlineArgs(int nCmdShow)
|
||||
#endif
|
||||
}
|
||||
|
||||
// Toast notification activations launch a new unelevated instance of the
|
||||
// app with "__fromToast" as the sole command-line argument. It will always
|
||||
// start a new instance of our exe.
|
||||
//
|
||||
// However, we're also able to just handle the .Activated event on the toast
|
||||
// itself, so we don't care about this process we're spawning. So before we
|
||||
// do _anything_ else, if we were created for a toast, just immediately
|
||||
// bail.
|
||||
const auto args = commandlineToArgArray(GetCommandLineW());
|
||||
{
|
||||
if (args.size() == 2 && args[1] == L"__fromToast")
|
||||
{
|
||||
TerminateProcess(GetCurrentProcess(), 0);
|
||||
__assume(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Windows Terminal is a single-instance application. Either acquire ownership
|
||||
// over the mutex, or hand off the command line to the existing instance.
|
||||
const auto mutex = acquireMutexOrAttemptHandoff(windowClassName.c_str(), nCmdShow);
|
||||
@@ -406,8 +423,6 @@ void WindowEmperor::HandleCommandlineArgs(int nCmdShow)
|
||||
}
|
||||
}
|
||||
|
||||
const auto args = commandlineToArgArray(GetCommandLineW());
|
||||
|
||||
if (args.size() == 2 && args[1] == L"-Embedding")
|
||||
{
|
||||
// We were launched for ConPTY handoff. We have no windows and also don't want to exit.
|
||||
|
||||
@@ -60,31 +60,34 @@
|
||||
|
||||
// --------------------------- 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)
|
||||
#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, NotifyOnInactiveOutput, winrt::Microsoft::Terminal::Control::OutputNotificationStyle{ 0 }) \
|
||||
X(winrt::Microsoft::Terminal::Control::OutputNotificationStyle, NotifyOnNextPrompt, winrt::Microsoft::Terminal::Control::OutputNotificationStyle{ 0 }) \
|
||||
X(winrt::Microsoft::Terminal::Control::AutoDetectRunningCommand, AutoDetectRunningCommand, winrt::Microsoft::Terminal::Control::AutoDetectRunningCommand::Disabled)
|
||||
|
||||
@@ -424,7 +424,7 @@ void ConhostInternalGetSet::NotifyBufferRotation(const int)
|
||||
{
|
||||
}
|
||||
|
||||
void ConhostInternalGetSet::NotifyShellIntegrationMark()
|
||||
void ConhostInternalGetSet::NotifyShellIntegrationMark(ShellIntegrationMark /*mark*/)
|
||||
{
|
||||
// Not implemented for conhost - shell integration marks are a Terminal app feature.
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ public:
|
||||
bool IsVtInputEnabled() const override;
|
||||
|
||||
void NotifyBufferRotation(const int delta) override;
|
||||
void NotifyShellIntegrationMark() override;
|
||||
void NotifyShellIntegrationMark(ShellIntegrationMark mark) override;
|
||||
|
||||
void InvokeCompletions(std::wstring_view menuJson, unsigned int replaceLength) override;
|
||||
|
||||
|
||||
@@ -85,7 +85,16 @@ namespace Microsoft::Console::VirtualTerminal
|
||||
virtual bool ResizeWindow(const til::CoordType width, const til::CoordType height) = 0;
|
||||
|
||||
virtual void NotifyBufferRotation(const int delta) = 0;
|
||||
virtual void NotifyShellIntegrationMark() = 0;
|
||||
|
||||
enum class ShellIntegrationMark
|
||||
{
|
||||
Prompt,
|
||||
Command,
|
||||
Output,
|
||||
CommandFinished,
|
||||
Other
|
||||
};
|
||||
virtual void NotifyShellIntegrationMark(ShellIntegrationMark mark) = 0;
|
||||
|
||||
virtual void InvokeCompletions(std::wstring_view menuJson, unsigned int replaceLength) = 0;
|
||||
|
||||
|
||||
@@ -3583,7 +3583,7 @@ void AdaptDispatch::DoConEmuAction(const std::wstring_view string)
|
||||
else if (subParam == 12)
|
||||
{
|
||||
_pages.ActivePage().Buffer().StartCommand();
|
||||
_api.NotifyShellIntegrationMark();
|
||||
_api.NotifyShellIntegrationMark(ITerminalApi::ShellIntegrationMark::Command);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3614,7 +3614,7 @@ void AdaptDispatch::DoITerm2Action(const std::wstring_view string)
|
||||
if (action == L"SetMark")
|
||||
{
|
||||
_pages.ActivePage().Buffer().StartPrompt();
|
||||
_api.NotifyShellIntegrationMark();
|
||||
_api.NotifyShellIntegrationMark(ITerminalApi::ShellIntegrationMark::Prompt);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3648,19 +3648,19 @@ void AdaptDispatch::DoFinalTermAction(const std::wstring_view string)
|
||||
case L'A': // FTCS_PROMPT
|
||||
{
|
||||
_pages.ActivePage().Buffer().StartPrompt();
|
||||
_api.NotifyShellIntegrationMark();
|
||||
_api.NotifyShellIntegrationMark(ITerminalApi::ShellIntegrationMark::Prompt);
|
||||
break;
|
||||
}
|
||||
case L'B': // FTCS_COMMAND_START
|
||||
{
|
||||
_pages.ActivePage().Buffer().StartCommand();
|
||||
_api.NotifyShellIntegrationMark();
|
||||
_api.NotifyShellIntegrationMark(ITerminalApi::ShellIntegrationMark::Command);
|
||||
break;
|
||||
}
|
||||
case L'C': // FTCS_COMMAND_EXECUTED
|
||||
{
|
||||
_pages.ActivePage().Buffer().StartOutput();
|
||||
_api.NotifyShellIntegrationMark();
|
||||
_api.NotifyShellIntegrationMark(ITerminalApi::ShellIntegrationMark::Output);
|
||||
break;
|
||||
}
|
||||
case L'D': // FTCS_COMMAND_FINISHED
|
||||
@@ -3681,7 +3681,7 @@ void AdaptDispatch::DoFinalTermAction(const std::wstring_view string)
|
||||
}
|
||||
|
||||
_pages.ActivePage().Buffer().EndCurrentCommand(error);
|
||||
_api.NotifyShellIntegrationMark();
|
||||
_api.NotifyShellIntegrationMark(ITerminalApi::ShellIntegrationMark::CommandFinished);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -207,7 +207,7 @@ public:
|
||||
Log::Comment(L"NotifyBufferRotation MOCK called...");
|
||||
}
|
||||
|
||||
void NotifyShellIntegrationMark() override
|
||||
void NotifyShellIntegrationMark(ShellIntegrationMark /*mark*/) override
|
||||
{
|
||||
Log::Comment(L"NotifyShellIntegrationMark MOCK called...");
|
||||
}
|
||||
|
||||
@@ -417,8 +417,15 @@ function Invoke-CodeFormat() {
|
||||
)
|
||||
|
||||
$clangFormatPath = & 'C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe' -latest -find "**\x64\bin\clang-format.exe"
|
||||
If ([String]::IsNullOrEmpty($clangFormatPath)) {
|
||||
# try again with prerelease versions of Visual Studio,
|
||||
# and just take the first
|
||||
$clangFormatPath = & 'C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe' -prerelease -find "**\clang-format.exe" | Select-Object -First 1
|
||||
}
|
||||
|
||||
If ([String]::IsNullOrEmpty($clangFormatPath)) {
|
||||
Write-Error "No Visual Studio-supplied version of clang-format could be found."
|
||||
return -1
|
||||
}
|
||||
|
||||
$root = Find-OpenConsoleRoot
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
rem run clang-format on c++ files
|
||||
|
||||
powershell -noprofile "import-module %OPENCON_TOOLS%\openconsole.psm1; Invoke-CodeFormat"
|
||||
pwsh -noprofile "import-module %OPENCON_TOOLS%\openconsole.psm1; Invoke-CodeFormat"
|
||||
|
||||
Reference in New Issue
Block a user