From 42738aa85ec9bcf651ebbc5559c9e3db4853b5a7 Mon Sep 17 00:00:00 2001 From: Carlos Zamora Date: Wed, 26 Jul 2023 17:01:49 -0700 Subject: [PATCH 1/4] Make screen reader announce successful MovePane and MoveTab actions --- .../TerminalApp/AppActionHandlers.cpp | 23 ++++++++++++++++++- .../Resources/en-US/Resources.resw | 8 ++++++- src/cascadia/TerminalApp/TerminalPage.cpp | 5 ++++ src/cascadia/TerminalApp/TerminalPage.h | 1 + 4 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/cascadia/TerminalApp/AppActionHandlers.cpp b/src/cascadia/TerminalApp/AppActionHandlers.cpp index cad581983f3..5659ba814a5 100644 --- a/src/cascadia/TerminalApp/AppActionHandlers.cpp +++ b/src/cascadia/TerminalApp/AppActionHandlers.cpp @@ -8,6 +8,7 @@ #include "../WinRTUtils/inc/WtExeUtils.h" #include "../../types/inc/utils.hpp" #include "Utils.h" +#include using namespace winrt::Windows::ApplicationModel::DataTransfer; using namespace winrt::Windows::UI::Xaml; @@ -209,7 +210,17 @@ namespace winrt::TerminalApp::implementation } else if (const auto& realArgs = args.ActionArgs().try_as()) { - auto moved = _MovePane(realArgs); + const auto moved = _MovePane(realArgs); + if (moved) + { + if (auto autoPeer = Automation::Peers::FrameworkElementAutomationPeer::FromElement(*this)) + { + autoPeer.RaiseNotificationEvent(Automation::Peers::AutomationNotificationKind::ActionCompleted, + Automation::Peers::AutomationNotificationProcessing::ImportantMostRecent, + RS_(L"TerminalPage_PaneMovedAnnouncement"), + L"TerminalPageMovePane" /* unique name for this notification category */); + } + } args.Handled(moved); } } @@ -813,6 +824,16 @@ namespace winrt::TerminalApp::implementation if (const auto& realArgs = actionArgs.ActionArgs().try_as()) { auto moved = _MoveTab(realArgs); + if (moved) + { + if (auto autoPeer = Automation::Peers::FrameworkElementAutomationPeer::FromElement(*this)) + { + autoPeer.RaiseNotificationEvent(Automation::Peers::AutomationNotificationKind::ActionCompleted, + Automation::Peers::AutomationNotificationProcessing::ImportantMostRecent, + RS_(L"TerminalPage_TabMovedAnnouncement"), + L"TerminalPageMoveTab" /* unique name for this notification category */); + } + } actionArgs.Handled(moved); } } diff --git a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw index 80f0a9df574..0f32d0b0529 100644 --- a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw @@ -840,4 +840,10 @@ Run as Administrator This text is displayed on context menu for profile entries in add new tab button. - \ No newline at end of file + + Pane moved successfully + + + Tab moved successfully + + diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 8140af22b3e..3d02616c3ce 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -287,6 +287,11 @@ namespace winrt::TerminalApp::implementation ShowSetAsDefaultInfoBar(); } + Windows::UI::Xaml::Automation::Peers::AutomationPeer TerminalPage::OnCreateAutomationPeer() + { + return Automation::Peers::FrameworkElementAutomationPeer(*this); + } + // Method Description: // - This is a bit of trickiness: If we're running unelevated, and the user // passed in only --elevate actions, the we don't _actually_ want to diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index 7a6866e20ec..de1b7d04627 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -101,6 +101,7 @@ namespace winrt::TerminalApp::implementation void SetSettings(Microsoft::Terminal::Settings::Model::CascadiaSettings settings, bool needRefreshUI); void Create(); + Windows::UI::Xaml::Automation::Peers::AutomationPeer OnCreateAutomationPeer(); bool ShouldImmediatelyHandoffToElevated(const Microsoft::Terminal::Settings::Model::CascadiaSettings& settings) const; void HandoffToElevated(const Microsoft::Terminal::Settings::Model::CascadiaSettings& settings); From 946e3716ff57bb5328617a35d6395a5c8305558e Mon Sep 17 00:00:00 2001 From: Carlos Zamora Date: Tue, 22 Aug 2023 14:09:16 -0700 Subject: [PATCH 2/4] Include more info in announcements --- .../TerminalApp/AppActionHandlers.cpp | 22 +------ .../Resources/en-US/Resources.resw | 30 +++++++-- src/cascadia/TerminalApp/TabManagement.cpp | 9 +++ src/cascadia/TerminalApp/TerminalPage.cpp | 61 ++++++++++++++++++- 4 files changed, 94 insertions(+), 28 deletions(-) diff --git a/src/cascadia/TerminalApp/AppActionHandlers.cpp b/src/cascadia/TerminalApp/AppActionHandlers.cpp index 5659ba814a5..7b0927c8640 100644 --- a/src/cascadia/TerminalApp/AppActionHandlers.cpp +++ b/src/cascadia/TerminalApp/AppActionHandlers.cpp @@ -211,16 +211,6 @@ namespace winrt::TerminalApp::implementation else if (const auto& realArgs = args.ActionArgs().try_as()) { const auto moved = _MovePane(realArgs); - if (moved) - { - if (auto autoPeer = Automation::Peers::FrameworkElementAutomationPeer::FromElement(*this)) - { - autoPeer.RaiseNotificationEvent(Automation::Peers::AutomationNotificationKind::ActionCompleted, - Automation::Peers::AutomationNotificationProcessing::ImportantMostRecent, - RS_(L"TerminalPage_PaneMovedAnnouncement"), - L"TerminalPageMovePane" /* unique name for this notification category */); - } - } args.Handled(moved); } } @@ -823,17 +813,7 @@ namespace winrt::TerminalApp::implementation { if (const auto& realArgs = actionArgs.ActionArgs().try_as()) { - auto moved = _MoveTab(realArgs); - if (moved) - { - if (auto autoPeer = Automation::Peers::FrameworkElementAutomationPeer::FromElement(*this)) - { - autoPeer.RaiseNotificationEvent(Automation::Peers::AutomationNotificationKind::ActionCompleted, - Automation::Peers::AutomationNotificationProcessing::ImportantMostRecent, - RS_(L"TerminalPage_TabMovedAnnouncement"), - L"TerminalPageMoveTab" /* unique name for this notification category */); - } - } + const auto moved = _MoveTab(realArgs); actionArgs.Handled(moved); } } diff --git a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw index 0f32d0b0529..bad10b13bfe 100644 --- a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw @@ -840,10 +840,32 @@ Run as Administrator This text is displayed on context menu for profile entries in add new tab button. - - Pane moved successfully + + Active pane moved to "{0}" tab + {Locked="{0}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the tab the pane was moved to. - - Tab moved successfully + + "{0}" tab moved to "{1}" window + {Locked="{0}"}{Locked="{1}"}This text is read out by screen readers upon a successful tab movement. {0} is the name of the tab. {1} is the name of the window the tab was moved to. + + + "{0}" tab moved to new window + {Locked="{0}"}This text is read out by screen readers upon a successful tab movement. {0} is the name of the tab. + + + "{0}" tab moved to position "{1}" + {Locked="{0}"}{Locked="{1}"}This text is read out by screen readers upon a successful tab movement. {0} is the name of the tab. {1} is the new tab index in the tab row. + + + Active pane moved to "{0}" tab in "{1}" window + {Locked="{0}"}{Locked="{1}"}This text is read out by screen readers upon a successful pane movement. {0} is the name of the tab the pane was moved to. {1} is the name of the window the pane was moved to. + + + Active pane moved to new window + This text is read out by screen readers upon a successful pane movement to a new window. + + + Active pane moved to new tab + This text is read out by screen readers upon a successful pane movement to a new tab within the existing window. diff --git a/src/cascadia/TerminalApp/TabManagement.cpp b/src/cascadia/TerminalApp/TabManagement.cpp index 8d8cca21ef6..d9b133c1223 100644 --- a/src/cascadia/TerminalApp/TabManagement.cpp +++ b/src/cascadia/TerminalApp/TabManagement.cpp @@ -1087,6 +1087,15 @@ namespace winrt::TerminalApp::implementation _tabView.TabItems().RemoveAt(currentTabIndex); _tabView.TabItems().InsertAt(newTabIndex, tabViewItem); _tabView.SelectedItem(tabViewItem); + + if (auto autoPeer = Automation::Peers::FrameworkElementAutomationPeer::FromElement(*this)) + { + const auto tabTitle = tab.Title(); + autoPeer.RaiseNotificationEvent(Automation::Peers::AutomationNotificationKind::ActionCompleted, + Automation::Peers::AutomationNotificationProcessing::ImportantMostRecent, + fmt::format(std::wstring_view{ RS_(L"TerminalPage_TabMovedAnnouncement_Direction") }, tabTitle, newTabIndex), + L"TerminalPageMoveTabWithDirection" /* unique name for this notification category */); + } } } diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 3d02616c3ce..d91bf7ce4b4 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -2011,10 +2011,31 @@ namespace winrt::TerminalApp::implementation { if (const auto pane{ terminalTab->GetActivePane() }) { + // Get the tab title _before_ moving things around in case the tabIdx doesn't point to the right one after the move + const auto tabTitle = _tabs.GetAt(tabIdx).Title(); + auto startupActions = pane->BuildStartupActions(0, 1, true, true); _DetachPaneFromWindow(pane); - _MoveContent(std::move(startupActions.args), args.Window(), args.TabIndex()); + _MoveContent(std::move(startupActions.args), windowId, tabIdx); focusedTab->DetachPane(); + + if (auto autoPeer = Automation::Peers::FrameworkElementAutomationPeer::FromElement(*this)) + { + if (windowId == L"new") + { + autoPeer.RaiseNotificationEvent(Automation::Peers::AutomationNotificationKind::ActionCompleted, + Automation::Peers::AutomationNotificationProcessing::ImportantMostRecent, + RS_(L"TerminalPage_PaneMovedAnnouncement_NewWindow"), + L"TerminalPageMovePaneToNewWindow" /* unique name for this notification category */); + } + else + { + autoPeer.RaiseNotificationEvent(Automation::Peers::AutomationNotificationKind::ActionCompleted, + Automation::Peers::AutomationNotificationProcessing::ImportantMostRecent, + fmt::format(std::wstring_view{ RS_(L"TerminalPage_PaneMovedAnnouncement_ExistingWindow") }, tabTitle, windowId), + L"TerminalPageMovePaneToExistingWindow" /* unique name for this notification category */); + } + } return true; } } @@ -2040,11 +2061,27 @@ namespace winrt::TerminalApp::implementation auto pane = focusedTab->DetachPane(); targetTab->AttachPane(pane); _SetFocusedTab(*targetTab); + + if (auto autoPeer = Automation::Peers::FrameworkElementAutomationPeer::FromElement(*this)) + { + const auto tabTitle = targetTab->Title(); + autoPeer.RaiseNotificationEvent(Automation::Peers::AutomationNotificationKind::ActionCompleted, + Automation::Peers::AutomationNotificationProcessing::ImportantMostRecent, + fmt::format(std::wstring_view{ RS_(L"TerminalPage_PaneMovedAnnouncement_ExistingTab") }, tabTitle), + L"TerminalPageMovePaneToExistingTab" /* unique name for this notification category */); + } } else { auto pane = focusedTab->DetachPane(); _CreateNewTabFromPane(pane); + if (auto autoPeer = Automation::Peers::FrameworkElementAutomationPeer::FromElement(*this)) + { + autoPeer.RaiseNotificationEvent(Automation::Peers::AutomationNotificationKind::ActionCompleted, + Automation::Peers::AutomationNotificationProcessing::ImportantMostRecent, + RS_(L"TerminalPage_PaneMovedAnnouncement_NewTab"), + L"TerminalPageMovePaneToNewTab" /* unique name for this notification category */); + } } return true; @@ -2116,8 +2153,27 @@ namespace winrt::TerminalApp::implementation { auto startupActions = terminalTab->BuildStartupActions(true); _DetachTabFromWindow(terminalTab); - _MoveContent(std::move(startupActions), args.Window(), 0); + _MoveContent(std::move(startupActions), windowId, 0); _RemoveTab(*terminalTab); + + if (auto autoPeer = Automation::Peers::FrameworkElementAutomationPeer::FromElement(*this)) + { + const auto tabTitle = terminalTab->Title(); + if (windowId == L"new") + { + autoPeer.RaiseNotificationEvent(Automation::Peers::AutomationNotificationKind::ActionCompleted, + Automation::Peers::AutomationNotificationProcessing::ImportantMostRecent, + fmt::format(std::wstring_view{ RS_(L"TerminalPage_TabMovedAnnouncement_NewWindow") }, tabTitle), + L"TerminalPageMoveTabToNewWindow" /* unique name for this notification category */); + } + else + { + autoPeer.RaiseNotificationEvent(Automation::Peers::AutomationNotificationKind::ActionCompleted, + Automation::Peers::AutomationNotificationProcessing::ImportantMostRecent, + fmt::format(std::wstring_view{ RS_(L"TerminalPage_TabMovedAnnouncement_Default") }, tabTitle, windowId), + L"TerminalPageMoveTabToExistingWindow" /* unique name for this notification category */); + } + } return true; } } @@ -5010,5 +5066,4 @@ namespace winrt::TerminalApp::implementation return profileMenuItemFlyout; } - } From dbfef4d33535909530f4531d683d450b87023bd0 Mon Sep 17 00:00:00 2001 From: Carlos Zamora Date: Fri, 25 Aug 2023 08:50:14 -0700 Subject: [PATCH 3/4] remove unused LibResources.h --- src/cascadia/TerminalApp/AppActionHandlers.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/cascadia/TerminalApp/AppActionHandlers.cpp b/src/cascadia/TerminalApp/AppActionHandlers.cpp index 7b0927c8640..438179e11c4 100644 --- a/src/cascadia/TerminalApp/AppActionHandlers.cpp +++ b/src/cascadia/TerminalApp/AppActionHandlers.cpp @@ -8,7 +8,6 @@ #include "../WinRTUtils/inc/WtExeUtils.h" #include "../../types/inc/utils.hpp" #include "Utils.h" -#include using namespace winrt::Windows::ApplicationModel::DataTransfer; using namespace winrt::Windows::UI::Xaml; From 6c33bdc28c4453c41df298fba7780fb3b205350b Mon Sep 17 00:00:00 2001 From: Carlos Zamora Date: Fri, 25 Aug 2023 09:05:05 -0700 Subject: [PATCH 4/4] 1-index --- src/cascadia/TerminalApp/TabManagement.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cascadia/TerminalApp/TabManagement.cpp b/src/cascadia/TerminalApp/TabManagement.cpp index f1ed8a7c618..0d8bcbee26f 100644 --- a/src/cascadia/TerminalApp/TabManagement.cpp +++ b/src/cascadia/TerminalApp/TabManagement.cpp @@ -1050,7 +1050,7 @@ namespace winrt::TerminalApp::implementation const auto tabTitle = tab.Title(); autoPeer.RaiseNotificationEvent(Automation::Peers::AutomationNotificationKind::ActionCompleted, Automation::Peers::AutomationNotificationProcessing::ImportantMostRecent, - fmt::format(std::wstring_view{ RS_(L"TerminalPage_TabMovedAnnouncement_Direction") }, tabTitle, newTabIndex), + fmt::format(std::wstring_view{ RS_(L"TerminalPage_TabMovedAnnouncement_Direction") }, tabTitle, newTabIndex + 1), L"TerminalPageMoveTabWithDirection" /* unique name for this notification category */); } }