mirror of
https://github.com/microsoft/terminal.git
synced 2025-12-11 04:38:24 -06:00
Implement ConEmu's OSC 9;4 to set the taskbar progress indicator (#8055)
This commit implements the OSC 9;4 sequence per the [ConEmu style]. | sequence | description | | ------------ | ------------ | | `ESC ] 9 ; 4 ; st ; pr ST` | Set progress state on taskbar and tab. | | | When `st` is: | | | | | | `0`: remove progress. | | | `1`: set progress value to `pr` (number, 0-100). | | | `2`: set the taskbar to the "Error" state | | | `3`: set the taskbar to the "Indeterminate" state | | | `4`: set the taskbar to the "Warning" state | We've also extended this with: * st 3: set indeterminate state * st 4: set paused state We handle multiple tabs sending the sequence by using the the last focused control's taskbar state/progress. Upon receiving the sequence in `TerminalApi`, we send an event that gets caught by `TerminalPage`. `TerminalPage` then fires another event that gets caught by `AppHost` and that's where we set the taskbar progress. Closes #3004 [ConEmu style]: https://conemu.github.io/en/AnsiEscapeCodes.html#ConEmu_specific_OSC
This commit is contained in:
parent
c41e078e85
commit
16e8a84cfb
@ -32,6 +32,8 @@ IInheritable
|
||||
IMap
|
||||
IObject
|
||||
IStorage
|
||||
ITaskbar
|
||||
llabs
|
||||
LCID
|
||||
llabs
|
||||
localtime
|
||||
@ -42,6 +44,7 @@ NCHITTEST
|
||||
NCLBUTTONDBLCLK
|
||||
NCRBUTTONDBLCLK
|
||||
NOAGGREGATION
|
||||
NOPROGRESS
|
||||
NOREDIRECTIONBITMAP
|
||||
oaidl
|
||||
ocidl
|
||||
@ -63,6 +66,7 @@ sregex
|
||||
STDCPP
|
||||
strchr
|
||||
syscall
|
||||
TBPF
|
||||
THEMECHANGED
|
||||
tmp
|
||||
tx
|
||||
|
||||
@ -1051,6 +1051,32 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Gets the taskbar state value from the last active control
|
||||
// Return Value:
|
||||
// - The taskbar state of the last active control
|
||||
size_t AppLogic::GetLastActiveControlTaskbarState()
|
||||
{
|
||||
if (_root)
|
||||
{
|
||||
return _root->GetLastActiveControlTaskbarState();
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Gets the taskbar progress value from the last active control
|
||||
// Return Value:
|
||||
// - The taskbar progress of the last active control
|
||||
size_t AppLogic::GetLastActiveControlTaskbarProgress()
|
||||
{
|
||||
if (_root)
|
||||
{
|
||||
return _root->GetLastActiveControlTaskbarProgress();
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Sets the initial commandline to process on startup, and attempts to
|
||||
// parse it. Commands will be parsed into a list of ShortcutActions that
|
||||
|
||||
@ -50,6 +50,9 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
void WindowCloseButtonClicked();
|
||||
|
||||
size_t GetLastActiveControlTaskbarState();
|
||||
size_t GetLastActiveControlTaskbarProgress();
|
||||
|
||||
winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::UI::Xaml::Controls::ContentDialogResult> ShowDialog(winrt::Windows::UI::Xaml::Controls::ContentDialog dialog);
|
||||
|
||||
// -------------------------------- WinRT Events ---------------------------------
|
||||
@ -110,6 +113,7 @@ namespace winrt::TerminalApp::implementation
|
||||
FORWARDED_TYPED_EVENT(FocusModeChanged, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, _root, FocusModeChanged);
|
||||
FORWARDED_TYPED_EVENT(FullscreenChanged, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, _root, FullscreenChanged);
|
||||
FORWARDED_TYPED_EVENT(AlwaysOnTopChanged, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, _root, AlwaysOnTopChanged);
|
||||
FORWARDED_TYPED_EVENT(SetTaskbarProgress, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, _root, SetTaskbarProgress);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -52,6 +52,9 @@ namespace TerminalApp
|
||||
void TitlebarClicked();
|
||||
void WindowCloseButtonClicked();
|
||||
|
||||
UInt64 GetLastActiveControlTaskbarState();
|
||||
UInt64 GetLastActiveControlTaskbarProgress();
|
||||
|
||||
// See IDialogPresenter and TerminalPage's DialogPresenter for more
|
||||
// information.
|
||||
Windows.Foundation.IAsyncOperation<Windows.UI.Xaml.Controls.ContentDialogResult> ShowDialog(Windows.UI.Xaml.Controls.ContentDialog dialog);
|
||||
@ -63,5 +66,6 @@ namespace TerminalApp
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> FocusModeChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> FullscreenChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> AlwaysOnTopChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> SetTaskbarProgress;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1132,6 +1132,9 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
term.OpenHyperlink({ this, &TerminalPage::_OpenHyperlinkHandler });
|
||||
|
||||
// Add an event handler for when the terminal wants to set a progress indicator on the taskbar
|
||||
term.SetTaskbarProgress({ this, &TerminalPage::_SetTaskbarProgressHandler });
|
||||
|
||||
// Bind Tab events to the TermControl and the Tab's Pane
|
||||
hostingTab.Initialize(term);
|
||||
|
||||
@ -1984,6 +1987,16 @@ namespace winrt::TerminalApp::implementation
|
||||
return control.CopySelectionToClipboard(singleLine, formats);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Send an event (which will be caught by AppHost) to set the progress indicator on the taskbar
|
||||
// Arguments:
|
||||
// - sender (not used)
|
||||
// - eventArgs: the arguments specifying how to set the progress indicator
|
||||
void TerminalPage::_SetTaskbarProgressHandler(const IInspectable /*sender*/, const IInspectable /*eventArgs*/)
|
||||
{
|
||||
_setTaskbarProgressHandlers(*this, nullptr);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Paste text from the Windows Clipboard to the focused terminal
|
||||
void TerminalPage::_PasteText()
|
||||
@ -2365,6 +2378,32 @@ namespace winrt::TerminalApp::implementation
|
||||
_dialogPresenter = dialogPresenter;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Gets the taskbar state value from the last active control
|
||||
// Return Value:
|
||||
// - The taskbar state of the last active control
|
||||
size_t TerminalPage::GetLastActiveControlTaskbarState()
|
||||
{
|
||||
if (auto control{ _GetActiveControl() })
|
||||
{
|
||||
return gsl::narrow_cast<size_t>(control.TaskbarState());
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Gets the taskbar progress value from the last active control
|
||||
// Return Value:
|
||||
// - The taskbar progress of the last active control
|
||||
size_t TerminalPage::GetLastActiveControlTaskbarProgress()
|
||||
{
|
||||
if (auto control{ _GetActiveControl() })
|
||||
{
|
||||
return gsl::narrow_cast<size_t>(control.TaskbarProgress());
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - This is the method that App will call when the titlebar
|
||||
// has been clicked. It dismisses any open flyouts.
|
||||
@ -2890,4 +2929,5 @@ namespace winrt::TerminalApp::implementation
|
||||
DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TerminalPage, FocusModeChanged, _focusModeChangedHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TerminalPage, FullscreenChanged, _fullscreenChangedHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TerminalPage, AlwaysOnTopChanged, _alwaysOnTopChangedHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TerminalPage, SetTaskbarProgress, _setTaskbarProgressHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
}
|
||||
|
||||
@ -71,6 +71,9 @@ namespace winrt::TerminalApp::implementation
|
||||
winrt::TerminalApp::IDialogPresenter DialogPresenter() const;
|
||||
void DialogPresenter(winrt::TerminalApp::IDialogPresenter dialogPresenter);
|
||||
|
||||
size_t GetLastActiveControlTaskbarState();
|
||||
size_t GetLastActiveControlTaskbarProgress();
|
||||
|
||||
void ShowKeyboardServiceWarning();
|
||||
winrt::hstring KeyboardServiceDisabledText();
|
||||
|
||||
@ -81,6 +84,7 @@ namespace winrt::TerminalApp::implementation
|
||||
DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(FocusModeChanged, _focusModeChangedHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(FullscreenChanged, _fullscreenChangedHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(AlwaysOnTopChanged, _alwaysOnTopChangedHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(SetTaskbarProgress, _setTaskbarProgressHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable);
|
||||
TYPED_EVENT(Initialized, winrt::Windows::Foundation::IInspectable, winrt::Windows::UI::Xaml::RoutedEventArgs);
|
||||
|
||||
private:
|
||||
@ -195,6 +199,8 @@ namespace winrt::TerminalApp::implementation
|
||||
void _ShowCouldNotOpenDialog(winrt::hstring reason, winrt::hstring uri);
|
||||
bool _CopyText(const bool singleLine, const Windows::Foundation::IReference<Microsoft::Terminal::TerminalControl::CopyFormat>& formats);
|
||||
|
||||
void _SetTaskbarProgressHandler(const IInspectable sender, const IInspectable eventArgs);
|
||||
|
||||
void _PasteText();
|
||||
|
||||
void _ControlNoticeRaisedHandler(const IInspectable sender, const Microsoft::Terminal::TerminalControl::NoticeEventArgs eventArgs);
|
||||
|
||||
@ -29,6 +29,9 @@ namespace TerminalApp
|
||||
void ShowKeyboardServiceWarning();
|
||||
String KeyboardServiceDisabledText { get; };
|
||||
|
||||
UInt64 GetLastActiveControlTaskbarState();
|
||||
UInt64 GetLastActiveControlTaskbarProgress();
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<Object, String> TitleChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, LastTabClosedEventArgs> LastTabClosed;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Windows.UI.Xaml.UIElement> SetTitleBarContent;
|
||||
@ -36,5 +39,6 @@ namespace TerminalApp
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> FullscreenChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> AlwaysOnTopChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Windows.UI.Xaml.RoutedEventArgs> Initialized;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> SetTaskbarProgress;
|
||||
}
|
||||
}
|
||||
|
||||
@ -105,6 +105,7 @@ namespace winrt::TerminalApp::implementation
|
||||
if (lastFocusedControl)
|
||||
{
|
||||
lastFocusedControl.Focus(_focusState);
|
||||
lastFocusedControl.TaskbarProgressChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -107,6 +107,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
auto pfnCopyToClipboard = std::bind(&TermControl::_CopyToClipboard, this, std::placeholders::_1);
|
||||
_terminal->SetCopyToClipboardCallback(pfnCopyToClipboard);
|
||||
|
||||
_terminal->TaskbarProgressChangedCallback([&]() { TermControl::TaskbarProgressChanged(); });
|
||||
|
||||
// This event is explicitly revoked in the destructor: does not need weak_ref
|
||||
auto onReceiveOutputFn = [this](const hstring str) {
|
||||
_terminal->Write(str);
|
||||
@ -3091,6 +3093,33 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
return coreColor.has_value() ? Windows::Foundation::IReference<winrt::Windows::UI::Color>(coreColor.value()) : nullptr;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Sends an event (which will be caught by TerminalPage and forwarded to AppHost after)
|
||||
// to set the progress indicator on the taskbar
|
||||
winrt::fire_and_forget TermControl::TaskbarProgressChanged()
|
||||
{
|
||||
co_await resume_foreground(Dispatcher(), CoreDispatcherPriority::High);
|
||||
_setTaskbarProgressHandlers(*this, nullptr);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Gets the internal taskbar state value
|
||||
// Return Value:
|
||||
// - The taskbar state of this control
|
||||
const size_t TermControl::TaskbarState() const noexcept
|
||||
{
|
||||
return _terminal->GetTaskbarState();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Gets the internal taskbar progress value
|
||||
// Return Value:
|
||||
// - The taskbar progress of this control
|
||||
const size_t TermControl::TaskbarProgress() const noexcept
|
||||
{
|
||||
return _terminal->GetTaskbarProgress();
|
||||
}
|
||||
|
||||
// -------------------------------- WinRT Events ---------------------------------
|
||||
// Winrt events need a method for adding a callback to the event and removing the callback.
|
||||
// These macros will define them both for you.
|
||||
@ -3101,6 +3130,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TermControl, PasteFromClipboard, _clipboardPasteHandlers, TerminalControl::TermControl, TerminalControl::PasteFromClipboardEventArgs);
|
||||
DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TermControl, CopyToClipboard, _clipboardCopyHandlers, TerminalControl::TermControl, TerminalControl::CopyToClipboardEventArgs);
|
||||
DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TermControl, OpenHyperlink, _openHyperlinkHandlers, TerminalControl::TermControl, TerminalControl::OpenHyperlinkEventArgs);
|
||||
DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TermControl, SetTaskbarProgress, _setTaskbarProgressHandlers, TerminalControl::TermControl, IInspectable);
|
||||
DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TermControl, RaiseNotice, _raiseNoticeHandlers, TerminalControl::TermControl, TerminalControl::NoticeEventArgs);
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
@ -158,6 +158,10 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
|
||||
Windows::Foundation::IReference<winrt::Windows::UI::Color> TabColor() noexcept;
|
||||
|
||||
winrt::fire_and_forget TaskbarProgressChanged();
|
||||
const size_t TaskbarState() const noexcept;
|
||||
const size_t TaskbarProgress() const noexcept;
|
||||
|
||||
// clang-format off
|
||||
// -------------------------------- WinRT Events ---------------------------------
|
||||
DECLARE_EVENT(TitleChanged, _titleChangedHandlers, TerminalControl::TitleChangedEventArgs);
|
||||
@ -167,6 +171,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
|
||||
DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(PasteFromClipboard, _clipboardPasteHandlers, TerminalControl::TermControl, TerminalControl::PasteFromClipboardEventArgs);
|
||||
DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(CopyToClipboard, _clipboardCopyHandlers, TerminalControl::TermControl, TerminalControl::CopyToClipboardEventArgs);
|
||||
DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(OpenHyperlink, _openHyperlinkHandlers, TerminalControl::TermControl, TerminalControl::OpenHyperlinkEventArgs);
|
||||
DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(SetTaskbarProgress, _setTaskbarProgressHandlers, TerminalControl::TermControl, IInspectable);
|
||||
DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(RaiseNotice, _raiseNoticeHandlers, TerminalControl::TermControl, TerminalControl::NoticeEventArgs);
|
||||
|
||||
TYPED_EVENT(WarningBell, IInspectable, IInspectable);
|
||||
|
||||
@ -74,6 +74,7 @@ namespace Microsoft.Terminal.TerminalControl
|
||||
event Windows.Foundation.TypedEventHandler<TermControl, CopyToClipboardEventArgs> CopyToClipboard;
|
||||
event Windows.Foundation.TypedEventHandler<TermControl, PasteFromClipboardEventArgs> PasteFromClipboard;
|
||||
event Windows.Foundation.TypedEventHandler<TermControl, OpenHyperlinkEventArgs> OpenHyperlink;
|
||||
event Windows.Foundation.TypedEventHandler<TermControl, Object> SetTaskbarProgress;
|
||||
event Windows.Foundation.TypedEventHandler<TermControl, NoticeEventArgs> RaiseNotice;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> WarningBell;
|
||||
|
||||
@ -105,6 +106,10 @@ namespace Microsoft.Terminal.TerminalControl
|
||||
void SendInput(String input);
|
||||
void ToggleRetroEffect();
|
||||
|
||||
void TaskbarProgressChanged();
|
||||
UInt64 TaskbarState { get; };
|
||||
UInt64 TaskbarProgress { get; };
|
||||
|
||||
Windows.Foundation.IReference<Windows.UI.Color> TabColor { get; };
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> TabColorChanged;
|
||||
}
|
||||
|
||||
@ -63,6 +63,8 @@ namespace Microsoft::Terminal::Core
|
||||
virtual bool AddHyperlink(std::wstring_view uri, std::wstring_view params) noexcept = 0;
|
||||
virtual bool EndHyperlink() noexcept = 0;
|
||||
|
||||
virtual bool SetTaskbarProgress(const size_t state, const size_t progress) noexcept = 0;
|
||||
|
||||
protected:
|
||||
ITerminalApi() = default;
|
||||
};
|
||||
|
||||
@ -50,7 +50,9 @@ Terminal::Terminal() :
|
||||
_snapOnInput{ true },
|
||||
_altGrAliasing{ true },
|
||||
_blockSelection{ false },
|
||||
_selection{ std::nullopt }
|
||||
_selection{ std::nullopt },
|
||||
_taskbarState{ 0 },
|
||||
_taskbarProgress{ 0 }
|
||||
{
|
||||
auto dispatch = std::make_unique<TerminalDispatch>(*this);
|
||||
auto engine = std::make_unique<OutputStateMachineEngine>(std::move(dispatch));
|
||||
@ -1102,6 +1104,16 @@ void Terminal::SetBackgroundCallback(std::function<void(const COLORREF)> pfn) no
|
||||
_pfnBackgroundColorChanged.swap(pfn);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Allows settings a callback for settings the taskbar progress indicator
|
||||
// Arguments:
|
||||
// - pfn: a function callback that takes 2 size_t parameters, one indicating the progress state
|
||||
// and the other indicating the progress value
|
||||
void Microsoft::Terminal::Core::Terminal::TaskbarProgressChangedCallback(std::function<void()> pfn) noexcept
|
||||
{
|
||||
_pfnTaskbarProgressChanged.swap(pfn);
|
||||
}
|
||||
|
||||
void Terminal::_InitializeColorTable()
|
||||
try
|
||||
{
|
||||
@ -1168,3 +1180,21 @@ BlinkingState& Terminal::GetBlinkingState() const noexcept
|
||||
{
|
||||
return _blinkingState;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Gets the internal taskbar state value
|
||||
// Return Value:
|
||||
// - The taskbar state
|
||||
const size_t Microsoft::Terminal::Core::Terminal::GetTaskbarState() const noexcept
|
||||
{
|
||||
return _taskbarState;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Gets the internal taskbar progress value
|
||||
// Return Value:
|
||||
// - The taskbar progress
|
||||
const size_t Microsoft::Terminal::Core::Terminal::GetTaskbarProgress() const noexcept
|
||||
{
|
||||
return _taskbarProgress;
|
||||
}
|
||||
|
||||
@ -115,6 +115,8 @@ public:
|
||||
|
||||
bool AddHyperlink(std::wstring_view uri, std::wstring_view params) noexcept override;
|
||||
bool EndHyperlink() noexcept override;
|
||||
|
||||
bool SetTaskbarProgress(const size_t state, const size_t progress) noexcept override;
|
||||
#pragma endregion
|
||||
|
||||
#pragma region ITerminalInput
|
||||
@ -185,6 +187,7 @@ public:
|
||||
void SetScrollPositionChangedCallback(std::function<void(const int, const int, const int)> pfn) noexcept;
|
||||
void SetCursorPositionChangedCallback(std::function<void()> pfn) noexcept;
|
||||
void SetBackgroundCallback(std::function<void(const COLORREF)> pfn) noexcept;
|
||||
void TaskbarProgressChangedCallback(std::function<void()> pfn) noexcept;
|
||||
|
||||
void SetCursorOn(const bool isOn);
|
||||
bool IsCursorBlinkingAllowed() const noexcept;
|
||||
@ -196,6 +199,9 @@ public:
|
||||
|
||||
Microsoft::Console::Render::BlinkingState& GetBlinkingState() const noexcept;
|
||||
|
||||
const size_t GetTaskbarState() const noexcept;
|
||||
const size_t GetTaskbarProgress() const noexcept;
|
||||
|
||||
#pragma region TextSelection
|
||||
// These methods are defined in TerminalSelection.cpp
|
||||
enum class SelectionExpansionMode
|
||||
@ -221,6 +227,7 @@ private:
|
||||
std::function<void(const COLORREF)> _pfnBackgroundColorChanged;
|
||||
std::function<void()> _pfnCursorPositionChanged;
|
||||
std::function<void(const std::optional<til::color>)> _pfnTabColorChanged;
|
||||
std::function<void()> _pfnTaskbarProgressChanged;
|
||||
|
||||
std::unique_ptr<::Microsoft::Console::VirtualTerminal::StateMachine> _stateMachine;
|
||||
std::unique_ptr<::Microsoft::Console::VirtualTerminal::TerminalInput> _terminalInput;
|
||||
@ -240,6 +247,9 @@ private:
|
||||
bool _altGrAliasing;
|
||||
bool _suppressApplicationTitle;
|
||||
|
||||
size_t _taskbarState;
|
||||
size_t _taskbarProgress;
|
||||
|
||||
size_t _hyperlinkPatternId;
|
||||
|
||||
#pragma region Text Selection
|
||||
|
||||
@ -600,3 +600,21 @@ bool Terminal::EndHyperlink() noexcept
|
||||
_buffer->SetCurrentAttributes(attr);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Updates the taskbar progress indicator
|
||||
// Arguments:
|
||||
// - state: indicates the progress state
|
||||
// - progress: indicates the progress value
|
||||
// Return Value:
|
||||
// - true
|
||||
bool Terminal::SetTaskbarProgress(const size_t state, const size_t progress) noexcept
|
||||
{
|
||||
_taskbarState = state;
|
||||
_taskbarProgress = progress;
|
||||
if (_pfnTaskbarProgressChanged)
|
||||
{
|
||||
_pfnTaskbarProgressChanged();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3,6 +3,9 @@
|
||||
|
||||
#include "pch.h"
|
||||
#include "TerminalDispatch.hpp"
|
||||
#include "../../types/inc/utils.hpp"
|
||||
|
||||
using namespace Microsoft::Console;
|
||||
using namespace ::Microsoft::Terminal::Core;
|
||||
using namespace ::Microsoft::Console::VirtualTerminal;
|
||||
|
||||
@ -399,6 +402,60 @@ bool TerminalDispatch::EndHyperlink() noexcept
|
||||
return _terminalApi.EndHyperlink();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Performs a ConEmu action
|
||||
// - Currently, the only action we support is setting the taskbar state/progress
|
||||
// Arguments:
|
||||
// - string: contains the parameters that define which action we do
|
||||
// Return Value:
|
||||
// - true
|
||||
bool TerminalDispatch::DoConEmuAction(const std::wstring_view string) noexcept
|
||||
{
|
||||
unsigned int state = 0;
|
||||
unsigned int progress = 0;
|
||||
|
||||
const auto parts = Utils::SplitString(string, L';');
|
||||
unsigned int subParam = 0;
|
||||
|
||||
// For now, the only ConEmu action we support is setting the taskbar state/progress,
|
||||
// which has a sub param value of 4
|
||||
if (parts.size() < 1 || !Utils::StringToUint(til::at(parts, 0), subParam) || subParam != 4)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (parts.size() >= 2)
|
||||
{
|
||||
// A state parameter is defined, parse it out
|
||||
const auto stateSuccess = Utils::StringToUint(til::at(parts, 1), state);
|
||||
if (!stateSuccess)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (parts.size() >= 3)
|
||||
{
|
||||
// A progress parameter is also defined, parse it out
|
||||
const auto progressSuccess = Utils::StringToUint(til::at(parts, 2), progress);
|
||||
if (!progressSuccess)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (state > TaskbarMaxState)
|
||||
{
|
||||
// state is out of bounds, return false
|
||||
return false;
|
||||
}
|
||||
if (progress > TaskbarMaxProgress)
|
||||
{
|
||||
// progress is greater than the maximum allowed value, clamp it to the max
|
||||
progress = TaskbarMaxProgress;
|
||||
}
|
||||
return _terminalApi.SetTaskbarProgress(state, progress);
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Support routine for routing private mode parameters to be set/reset as flags
|
||||
// Arguments:
|
||||
|
||||
@ -4,6 +4,9 @@
|
||||
#include "../../terminal/adapter/termDispatch.hpp"
|
||||
#include "ITerminalApi.hpp"
|
||||
|
||||
static constexpr size_t TaskbarMaxState{ 4 };
|
||||
static constexpr size_t TaskbarMaxProgress{ 100 };
|
||||
|
||||
class TerminalDispatch : public Microsoft::Console::VirtualTerminal::TermDispatch
|
||||
{
|
||||
public:
|
||||
@ -67,6 +70,8 @@ public:
|
||||
bool AddHyperlink(const std::wstring_view uri, const std::wstring_view params) noexcept override;
|
||||
bool EndHyperlink() noexcept override;
|
||||
|
||||
bool DoConEmuAction(const std::wstring_view string) noexcept override;
|
||||
|
||||
private:
|
||||
::Microsoft::Terminal::Core::ITerminalApi& _terminalApi;
|
||||
|
||||
|
||||
@ -38,6 +38,8 @@ namespace TerminalCoreUnitTests
|
||||
TEST_METHOD(AddHyperlink);
|
||||
TEST_METHOD(AddHyperlinkCustomId);
|
||||
TEST_METHOD(AddHyperlinkCustomIdDifferentUri);
|
||||
|
||||
TEST_METHOD(SetTaskbarProgress);
|
||||
};
|
||||
};
|
||||
|
||||
@ -339,3 +341,50 @@ void TerminalCoreUnitTests::TerminalApiTest::AddHyperlinkCustomIdDifferentUri()
|
||||
VERIFY_ARE_EQUAL(tbi.GetHyperlinkUriFromId(oldAttributes.GetHyperlinkId()), L"test.url");
|
||||
VERIFY_ARE_NOT_EQUAL(oldAttributes.GetHyperlinkId(), tbi.GetCurrentAttributes().GetHyperlinkId());
|
||||
}
|
||||
|
||||
void TerminalCoreUnitTests::TerminalApiTest::SetTaskbarProgress()
|
||||
{
|
||||
Terminal term;
|
||||
DummyRenderTarget emptyRT;
|
||||
term.Create({ 100, 100 }, 0, emptyRT);
|
||||
|
||||
auto& stateMachine = *(term._stateMachine);
|
||||
|
||||
// Initial values for taskbar state and progress should be 0
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(0));
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(0));
|
||||
|
||||
// Set some values for taskbar state and progress through state machine
|
||||
stateMachine.ProcessString(L"\x1b]9;4;1;50\x9c");
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(1));
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(50));
|
||||
|
||||
// Reset to 0
|
||||
stateMachine.ProcessString(L"\x1b]9;4;0;0\x9c");
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(0));
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(0));
|
||||
|
||||
// Set an out of bounds value for state
|
||||
stateMachine.ProcessString(L"\x1b]9;4;5;50\x9c");
|
||||
// Nothing should have changed (dispatch should have returned false)
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(0));
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(0));
|
||||
|
||||
// Set an out of bounds value for progress
|
||||
stateMachine.ProcessString(L"\x1b]9;4;1;999\x9c");
|
||||
// Progress should have been clamped to 100
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(1));
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(100));
|
||||
|
||||
// Don't specify any params
|
||||
stateMachine.ProcessString(L"\x1b]9;4\x9c");
|
||||
// State and progress should both be reset to 0
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(0));
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(0));
|
||||
|
||||
// Specify additional params
|
||||
stateMachine.ProcessString(L"\x1b]9;4;1;80;123\x9c");
|
||||
// Additional params should be ignored, state and progress still set normally
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarState(), gsl::narrow<size_t>(1));
|
||||
VERIFY_ARE_EQUAL(term.GetTaskbarProgress(), gsl::narrow<size_t>(80));
|
||||
}
|
||||
|
||||
@ -79,6 +79,23 @@ bool AppHost::OnDirectKeyEvent(const uint32_t vkey, const uint8_t scanCode, cons
|
||||
return false;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Event handler to update the taskbar progress indicator
|
||||
// - Upon receiving the event, we ask the underlying logic for the taskbar state/progress values
|
||||
// of the last active control
|
||||
// Arguments:
|
||||
// - sender: not used
|
||||
// - args: not used
|
||||
void AppHost::SetTaskbarProgress(const winrt::Windows::Foundation::IInspectable& /*sender*/, const winrt::Windows::Foundation::IInspectable& /*args*/)
|
||||
{
|
||||
if (_logic)
|
||||
{
|
||||
const auto state = gsl::narrow_cast<size_t>(_logic.GetLastActiveControlTaskbarState());
|
||||
const auto progress = gsl::narrow_cast<size_t>(_logic.GetLastActiveControlTaskbarProgress());
|
||||
_window->SetTaskbarProgress(state, progress);
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Retrieve any commandline args passed on the commandline, and pass them to
|
||||
// the app logic for processing.
|
||||
@ -171,6 +188,7 @@ void AppHost::Initialize()
|
||||
|
||||
_logic.TitleChanged({ this, &AppHost::AppTitleChanged });
|
||||
_logic.LastTabClosed({ this, &AppHost::LastTabClosed });
|
||||
_logic.SetTaskbarProgress({ this, &AppHost::SetTaskbarProgress });
|
||||
|
||||
_window->UpdateTitle(_logic.Title());
|
||||
|
||||
|
||||
@ -18,6 +18,7 @@ public:
|
||||
void LastTabClosed(const winrt::Windows::Foundation::IInspectable& sender, const winrt::TerminalApp::LastTabClosedEventArgs& args);
|
||||
void Initialize();
|
||||
bool OnDirectKeyEvent(const uint32_t vkey, const uint8_t scanCode, const bool down);
|
||||
void SetTaskbarProgress(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args);
|
||||
|
||||
private:
|
||||
bool _useNonClientArea;
|
||||
|
||||
@ -261,6 +261,15 @@ void IslandWindow::Initialize()
|
||||
|
||||
_rootGrid = winrt::Windows::UI::Xaml::Controls::Grid();
|
||||
_source.Content(_rootGrid);
|
||||
|
||||
// initialize the taskbar object
|
||||
if (auto taskbar = wil::CoCreateInstanceNoThrow<ITaskbarList3>(CLSID_TaskbarList))
|
||||
{
|
||||
if (SUCCEEDED(taskbar->HrInit()))
|
||||
{
|
||||
_taskbar = std::move(taskbar);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IslandWindow::OnSize(const UINT width, const UINT height)
|
||||
@ -576,6 +585,48 @@ void IslandWindow::SetAlwaysOnTop(const bool alwaysOnTop)
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Sets the taskbar progress indicator
|
||||
// - We follow the ConEmu style for the state and progress values,
|
||||
// more details at https://conemu.github.io/en/AnsiEscapeCodes.html#ConEmu_specific_OSC
|
||||
// Arguments:
|
||||
// - state: indicates the progress state
|
||||
// - progress: indicates the progress value
|
||||
void IslandWindow::SetTaskbarProgress(const size_t state, const size_t progress)
|
||||
{
|
||||
if (_taskbar)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case 0:
|
||||
// removes the taskbar progress indicator
|
||||
_taskbar->SetProgressState(_window.get(), TBPF_NOPROGRESS);
|
||||
break;
|
||||
case 1:
|
||||
// sets the progress value to value given by the 'progress' parameter
|
||||
_taskbar->SetProgressState(_window.get(), TBPF_NORMAL);
|
||||
_taskbar->SetProgressValue(_window.get(), progress, 100);
|
||||
break;
|
||||
case 2:
|
||||
// sets the progress indicator to an error state
|
||||
_taskbar->SetProgressState(_window.get(), TBPF_ERROR);
|
||||
_taskbar->SetProgressValue(_window.get(), progress, 100);
|
||||
break;
|
||||
case 3:
|
||||
// sets the progress indicator to an indeterminate state
|
||||
_taskbar->SetProgressState(_window.get(), TBPF_INDETERMINATE);
|
||||
break;
|
||||
case 4:
|
||||
// sets the progress indicator to a pause state
|
||||
_taskbar->SetProgressState(_window.get(), TBPF_PAUSED);
|
||||
_taskbar->SetProgressValue(_window.get(), progress, 100);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// From GdiEngine::s_SetWindowLongWHelper
|
||||
void _SetWindowLongWHelper(const HWND hWnd, const int nIndex, const LONG dwNewLong) noexcept
|
||||
{
|
||||
|
||||
@ -35,6 +35,8 @@ public:
|
||||
void FullscreenChanged(const bool fullscreen);
|
||||
void SetAlwaysOnTop(const bool alwaysOnTop);
|
||||
|
||||
void SetTaskbarProgress(const size_t state, const size_t progress);
|
||||
|
||||
#pragma endregion
|
||||
|
||||
DECLARE_EVENT(DragRegionClicked, _DragRegionClickedHandlers, winrt::delegate<>);
|
||||
@ -74,6 +76,8 @@ protected:
|
||||
|
||||
LONG _getDesiredWindowStyle() const;
|
||||
|
||||
wil::com_ptr<ITaskbarList3> _taskbar;
|
||||
|
||||
void _OnGetMinMaxInfo(const WPARAM wParam, const LPARAM lParam);
|
||||
long _calculateTotalSize(const bool isWidth, const long clientSize, const long nonClientSize);
|
||||
|
||||
|
||||
@ -29,6 +29,7 @@ Abstract:
|
||||
#include <cstring>
|
||||
#include <shellscalingapi.h>
|
||||
#include <windowsx.h>
|
||||
#include <ShObjIdl.h>
|
||||
|
||||
// Manually include til after we include Windows.Foundation to give it winrt superpowers
|
||||
#define BLOCK_TIL
|
||||
|
||||
@ -122,6 +122,8 @@ public:
|
||||
|
||||
virtual bool AddHyperlink(const std::wstring_view uri, const std::wstring_view params) = 0;
|
||||
virtual bool EndHyperlink() = 0;
|
||||
|
||||
virtual bool DoConEmuAction(const std::wstring_view string) = 0;
|
||||
};
|
||||
inline Microsoft::Console::VirtualTerminal::ITermDispatch::~ITermDispatch() {}
|
||||
#pragma warning(pop)
|
||||
|
||||
@ -2383,6 +2383,16 @@ bool AdaptDispatch::EndHyperlink()
|
||||
return _pConApi->PrivateEndHyperlink();
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Ascribes to the ITermDispatch interface
|
||||
// - Not actually used in conhost
|
||||
// Return Value:
|
||||
// - false (so that the command gets flushed to terminal)
|
||||
bool AdaptDispatch::DoConEmuAction(const std::wstring_view /*string*/) noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Determines whether we should pass any sequence that manipulates
|
||||
// TerminalInput's input generator through the PTY. It encapsulates
|
||||
|
||||
@ -123,6 +123,8 @@ namespace Microsoft::Console::VirtualTerminal
|
||||
bool AddHyperlink(const std::wstring_view uri, const std::wstring_view params) override;
|
||||
bool EndHyperlink() override;
|
||||
|
||||
bool DoConEmuAction(const std::wstring_view string) noexcept override;
|
||||
|
||||
private:
|
||||
enum class ScrollDirection
|
||||
{
|
||||
|
||||
@ -116,4 +116,6 @@ public:
|
||||
|
||||
bool AddHyperlink(const std::wstring_view /*uri*/, const std::wstring_view /*params*/) noexcept override { return false; }
|
||||
bool EndHyperlink() noexcept override { return false; }
|
||||
|
||||
bool DoConEmuAction(const std::wstring_view /*string*/) noexcept override { return false; }
|
||||
};
|
||||
|
||||
@ -733,6 +733,11 @@ bool OutputStateMachineEngine::ActionOscDispatch(const wchar_t /*wch*/,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OscActionCodes::ConEmuAction:
|
||||
{
|
||||
success = _dispatch->DoConEmuAction(string);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// If no functions to call, overall dispatch was a failure.
|
||||
success = false;
|
||||
|
||||
@ -160,6 +160,7 @@ namespace Microsoft::Console::VirtualTerminal
|
||||
SetWindowProperty = 3, // Not implemented
|
||||
SetColor = 4,
|
||||
Hyperlink = 8,
|
||||
ConEmuAction = 9,
|
||||
SetForegroundColor = 10,
|
||||
SetBackgroundColor = 11,
|
||||
SetCursorColor = 12,
|
||||
|
||||
@ -1456,6 +1456,11 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DoConEmuAction(const std::wstring_view /*string*/) noexcept override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t _cursorDistance;
|
||||
size_t _line;
|
||||
size_t _column;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user