Skip to content

Commit

Permalink
Add support for the BEL control in Windows Terminal (#7679)
Browse files Browse the repository at this point in the history
This commit makes the Windows Terminal play an audible sound when the
`BEL` control character is output.

The `BEL` control was already being forwarded through conpty, so it was
just a matter of hooking up the `WarningBell` dispatch method to
actually play a sound. I've used the `PlaySound` API to output the sound
configured for the "Critical Stop" system event (aka _SystemHand_),
since that is the sound used in conhost.

## Validation

I've manually confirmed that the terminal produces the expected sound
when executing `echo ^G` in a cmd shell, or `printf "\a"` in a WSL bash
shell.

References:
* There is a separate issue (#1608) to deal with configuring the `BEL`
  to trigger visual forms of notification.
* There is also an issue (#2360) requesting an option to disable the
  `BEL`.

Closes #4046
  • Loading branch information
j4james authored Oct 1, 2020
1 parent 386ae04 commit 09cc5f4
Show file tree
Hide file tree
Showing 11 changed files with 52 additions and 0 deletions.
15 changes: 15 additions & 0 deletions src/cascadia/TerminalApp/TerminalPage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "AppLogic.h"
#include "../../types/inc/utils.hpp"

#include <Mmsystem.h>
#include <LibraryResources.h>

#include "TerminalPage.g.cpp"
Expand Down Expand Up @@ -1141,6 +1142,8 @@ namespace winrt::TerminalApp::implementation
// Add an event handler when the terminal wants to paste data from the Clipboard.
term.PasteFromClipboard({ this, &TerminalPage::_PasteFromClipboardHandler });

term.WarningBell({ this, &TerminalPage::_WarningBellHandler });

term.OpenHyperlink({ this, &TerminalPage::_OpenHyperlinkHandler });

// Bind Tab events to the TermControl and the Tab's Pane
Expand Down Expand Up @@ -1801,6 +1804,18 @@ namespace winrt::TerminalApp::implementation
CATCH_LOG();
}

// Method Description:
// - Plays a warning note when triggered by the BEL control character,
// using the sound configured for the "Critical Stop" system event.
// This matches the behavior of the Windows Console host.
// Arguments:
// - <none>
void TerminalPage::_WarningBellHandler(const IInspectable sender, const IInspectable eventArgs)
{
const auto soundAlias = reinterpret_cast<LPCTSTR>(SND_ALIAS_SYSTEMHAND);
PlaySound(soundAlias, NULL, SND_ALIAS_ID | SND_ASYNC | SND_SENTRY);
}

void TerminalPage::_OpenHyperlinkHandler(const IInspectable /*sender*/, const Microsoft::Terminal::TerminalControl::OpenHyperlinkEventArgs eventArgs)
{
try
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalApp/TerminalPage.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ namespace winrt::TerminalApp::implementation
winrt::fire_and_forget _PasteFromClipboardHandler(const IInspectable sender,
const Microsoft::Terminal::TerminalControl::PasteFromClipboardEventArgs eventArgs);

void _WarningBellHandler(const IInspectable sender, const IInspectable eventArgs);
void _OpenHyperlinkHandler(const IInspectable sender, const Microsoft::Terminal::TerminalControl::OpenHyperlinkEventArgs eventArgs);
void _ShowCouldNotOpenDialog(winrt::hstring reason, winrt::hstring uri);
bool _CopyText(const bool singleLine, const Windows::Foundation::IReference<Microsoft::Terminal::TerminalControl::CopyFormat>& formats);
Expand Down
8 changes: 8 additions & 0 deletions src/cascadia/TerminalControl/TermControl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation

_terminal = std::make_unique<::Microsoft::Terminal::Core::Terminal>();

auto pfnWarningBell = std::bind(&TermControl::_TerminalWarningBell, this);
_terminal->SetWarningBellCallback(pfnWarningBell);

auto pfnTitleChanged = std::bind(&TermControl::_TerminalTitleChanged, this, std::placeholders::_1);
_terminal->SetTitleChangedCallback(pfnTitleChanged);

Expand Down Expand Up @@ -2172,6 +2175,11 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
}
}

void TermControl::_TerminalWarningBell()
{
_WarningBellHandlers(*this, nullptr);
}

void TermControl::_TerminalTitleChanged(const std::wstring_view& wstr)
{
_titleChangedHandlers(winrt::hstring{ wstr });
Expand Down
2 changes: 2 additions & 0 deletions src/cascadia/TerminalControl/TermControl.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(CopyToClipboard, _clipboardCopyHandlers, TerminalControl::TermControl, TerminalControl::CopyToClipboardEventArgs);
DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(OpenHyperlink, _openHyperlinkHandlers, TerminalControl::TermControl, TerminalControl::OpenHyperlinkEventArgs);

TYPED_EVENT(WarningBell, IInspectable, IInspectable);
TYPED_EVENT(ConnectionStateChanged, TerminalControl::TermControl, IInspectable);
TYPED_EVENT(Initialized, TerminalControl::TermControl, Windows::UI::Xaml::RoutedEventArgs);
TYPED_EVENT(TabColorChanged, IInspectable, IInspectable);
Expand Down Expand Up @@ -261,6 +262,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
void _SwapChainScaleChanged(Windows::UI::Xaml::Controls::SwapChainPanel const& sender, Windows::Foundation::IInspectable const& args);
void _DoResizeUnderLock(const double newWidth, const double newHeight);
void _RefreshSizeUnderLock();
void _TerminalWarningBell();
void _TerminalTitleChanged(const std::wstring_view& wstr);
void _TerminalTabColorChanged(const std::optional<til::color> color);
void _CopyToClipboard(const std::wstring_view& wstr);
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalControl/TermControl.idl
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,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<Object, Object> WarningBell;

event Windows.Foundation.TypedEventHandler<TermControl, Windows.UI.Xaml.RoutedEventArgs> Initialized;
// This is an event handler forwarder for the underlying connection.
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalCore/ITerminalApi.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ namespace Microsoft::Terminal::Core
virtual bool EraseInLine(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::EraseType eraseType) noexcept = 0;
virtual bool EraseInDisplay(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::EraseType eraseType) noexcept = 0;

virtual bool WarningBell() noexcept = 0;
virtual bool SetWindowTitle(std::wstring_view title) noexcept = 0;

virtual bool SetColorTableEntry(const size_t tableIndex, const DWORD color) noexcept = 0;
Expand Down
5 changes: 5 additions & 0 deletions src/cascadia/TerminalCore/Terminal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -965,6 +965,11 @@ void Terminal::SetWriteInputCallback(std::function<void(std::wstring&)> pfn) noe
_pfnWriteInput.swap(pfn);
}

void Terminal::SetWarningBellCallback(std::function<void()> pfn) noexcept
{
_pfnWarningBell.swap(pfn);
}

void Terminal::SetTitleChangedCallback(std::function<void(const std::wstring_view&)> pfn) noexcept
{
_pfnTitleChanged.swap(pfn);
Expand Down
3 changes: 3 additions & 0 deletions src/cascadia/TerminalCore/Terminal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ class Microsoft::Terminal::Core::Terminal final :
bool EraseCharacters(const size_t numChars) noexcept override;
bool EraseInLine(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::EraseType eraseType) noexcept override;
bool EraseInDisplay(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::EraseType eraseType) noexcept override;
bool WarningBell() noexcept override;
bool SetWindowTitle(std::wstring_view title) noexcept override;
bool SetColorTableEntry(const size_t tableIndex, const COLORREF color) noexcept override;
bool SetCursorStyle(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::CursorStyle cursorStyle) noexcept override;
Expand Down Expand Up @@ -175,6 +176,7 @@ class Microsoft::Terminal::Core::Terminal final :
#pragma endregion

void SetWriteInputCallback(std::function<void(std::wstring&)> pfn) noexcept;
void SetWarningBellCallback(std::function<void()> pfn) noexcept;
void SetTitleChangedCallback(std::function<void(const std::wstring_view&)> pfn) noexcept;
void SetTabColorChangedCallback(std::function<void(const std::optional<til::color>)> pfn) noexcept;
void SetCopyToClipboardCallback(std::function<void(const std::wstring_view&)> pfn) noexcept;
Expand Down Expand Up @@ -207,6 +209,7 @@ class Microsoft::Terminal::Core::Terminal final :

private:
std::function<void(std::wstring&)> _pfnWriteInput;
std::function<void()> _pfnWarningBell;
std::function<void(const std::wstring_view&)> _pfnTitleChanged;
std::function<void(const std::wstring_view&)> _pfnCopyToClipboard;
std::function<void(const int, const int, const int)> _pfnScrollPositionChanged;
Expand Down
8 changes: 8 additions & 0 deletions src/cascadia/TerminalCore/TerminalApi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,14 @@ try
}
CATCH_LOG_RETURN_FALSE()

bool Terminal::WarningBell() noexcept
try
{
_pfnWarningBell();
return true;
}
CATCH_LOG_RETURN_FALSE()

bool Terminal::SetWindowTitle(std::wstring_view title) noexcept
try
{
Expand Down
7 changes: 7 additions & 0 deletions src/cascadia/TerminalCore/TerminalDispatch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,13 @@ try
}
CATCH_LOG_RETURN_FALSE()

bool TerminalDispatch::WarningBell() noexcept
try
{
return _terminalApi.WarningBell();
}
CATCH_LOG_RETURN_FALSE()

bool TerminalDispatch::CarriageReturn() noexcept
try
{
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalCore/TerminalDispatch.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class TerminalDispatch : public Microsoft::Console::VirtualTerminal::TermDispatc
bool LineFeed(const ::Microsoft::Console::VirtualTerminal::DispatchTypes::LineFeedType lineFeedType) noexcept override;

bool EraseCharacters(const size_t numChars) noexcept override;
bool WarningBell() noexcept override;
bool CarriageReturn() noexcept override;
bool SetWindowTitle(std::wstring_view title) noexcept override;

Expand Down

0 comments on commit 09cc5f4

Please sign in to comment.