Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TeachingTip F6 focus in xaml island fix. #6211

Merged
merged 1 commit into from
Nov 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 91 additions & 54 deletions dev/TeachingTip/TeachingTip.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ void TeachingTip::OnApplyTemplate()
base_type::OnApplyTemplate();

m_acceleratorKeyActivatedRevoker.revoke();
m_previewKeyDownForF6Revoker.revoke();
m_effectiveViewportChangedRevoker.revoke();
m_contentSizeChangedRevoker.revoke();
m_closeButtonClickedRevoker.revoke();
Expand Down Expand Up @@ -895,7 +896,24 @@ void TeachingTip::IsOpenChangedToOpen()
}
}

m_acceleratorKeyActivatedRevoker = Dispatcher().AcceleratorKeyActivated(winrt::auto_revoke, { this, &TeachingTip::OnF6AcceleratorKeyClicked });
[this]()
{
if (winrt::IUIElement10 uiElement10 = *this)
{
if (auto const xamlRoot = uiElement10.XamlRoot())
{
if (auto const content = xamlRoot.Content())
{
m_previewKeyDownForF6Revoker = content.PreviewKeyDown(winrt::auto_revoke, { this, &TeachingTip::OnF6PreviewKeyDownClicked });
return;
}
}
};

m_acceleratorKeyActivatedRevoker = Dispatcher().AcceleratorKeyActivated(winrt::auto_revoke, { this, &TeachingTip::OnF6AcceleratorKeyClicked });
return;
}();


// Make sure we are in the correct VSM state after ApplyTemplate and moving the template content from the Control to the Popup:
OnIsLightDismissEnabledChanged();
Expand All @@ -921,6 +939,8 @@ void TeachingTip::IsOpenChangedToClose()
}
}

m_acceleratorKeyActivatedRevoker.revoke();
m_previewKeyDownForF6Revoker.revoke();
m_currentEffectiveTipPlacementMode = winrt::TeachingTipPlacementMode::Auto;
TeachingTipTestHooks::NotifyEffectivePlacementChanged(*this);
}
Expand Down Expand Up @@ -1066,71 +1086,88 @@ void TeachingTip::OnF6AcceleratorKeyClicked(const winrt::CoreDispatcher&, const
args.VirtualKey() == winrt::VirtualKey::F6 &&
args.EventType() == winrt::CoreAcceleratorKeyEventType::KeyDown)
{
// Logging usage telemetry
if (m_hasF6BeenInvoked)
{
__RP_Marker_ClassMemberById(RuntimeProfiler::ProfId_TeachingTip, RuntimeProfiler::ProfMemberId_TeachingTip_F6AccessKey_SubsequentInvocation);
}
else
{
__RP_Marker_ClassMemberById(RuntimeProfiler::ProfId_TeachingTip, RuntimeProfiler::ProfMemberId_TeachingTip_F6AccessKey_FirstInvocation);
m_hasF6BeenInvoked = true;
}
args.Handled(HandleF6Clicked());
}
}

void TeachingTip::OnF6PreviewKeyDownClicked(const winrt::IInspectable&, const winrt::KeyRoutedEventArgs& args)
{
if (!args.Handled() &&
IsOpen() &&
args.Key() == winrt::VirtualKey::F6)
{
args.Handled(HandleF6Clicked());
}
}

bool TeachingTip::HandleF6Clicked()
{
// Logging usage telemetry
if (m_hasF6BeenInvoked)
{
__RP_Marker_ClassMemberById(RuntimeProfiler::ProfId_TeachingTip, RuntimeProfiler::ProfMemberId_TeachingTip_F6AccessKey_SubsequentInvocation);
}
else
{
__RP_Marker_ClassMemberById(RuntimeProfiler::ProfId_TeachingTip, RuntimeProfiler::ProfMemberId_TeachingTip_F6AccessKey_FirstInvocation);
m_hasF6BeenInvoked = true;
}

auto const hasFocusInSubtree = [this, args]()
auto const hasFocusInSubtree = [this]()
{
auto current = winrt::FocusManager::GetFocusedElement().try_as<winrt::DependencyObject>();
if (auto const rootElement = m_rootElement.get())
{
auto current = winrt::FocusManager::GetFocusedElement().try_as<winrt::DependencyObject>();
if (auto const rootElement = m_rootElement.get())
while (current)
{
while (current)
if (current.try_as<winrt::UIElement>() == rootElement)
{
if (current.try_as<winrt::UIElement>() == rootElement)
{
return true;
}
current = winrt::VisualTreeHelper::GetParent(current);
return true;
}
current = winrt::VisualTreeHelper::GetParent(current);
}
return false;
}();

if (hasFocusInSubtree)
{
bool setFocus = SetFocus(m_previouslyFocusedElement.get(), winrt::FocusState::Programmatic);
m_previouslyFocusedElement = nullptr;
args.Handled(setFocus);
}
else
return false;
}();

if (hasFocusInSubtree)
{
bool setFocus = SetFocus(m_previouslyFocusedElement.get(), winrt::FocusState::Programmatic);
m_previouslyFocusedElement = nullptr;
return setFocus;
}
else
{
const winrt::Button f6Button = [this]() -> winrt::Button
{
const winrt::Button f6Button = [this]() -> winrt::Button
auto firstButton = m_closeButton.get();
auto secondButton = m_alternateCloseButton.get();
//Prefer the close button to the alternate, except when there is no content.
if (!CloseButtonContent())
{
auto firstButton = m_closeButton.get();
auto secondButton = m_alternateCloseButton.get();
//Prefer the close button to the alternate, except when there is no content.
if (!CloseButtonContent())
{
std::swap(firstButton, secondButton);
}
if (firstButton && firstButton.Visibility() == winrt::Visibility::Visible)
{
return firstButton;
}
else if (secondButton && secondButton.Visibility() == winrt::Visibility::Visible)
{
return secondButton;
}
return nullptr;
}();

if (f6Button)
std::swap(firstButton, secondButton);
}
if (firstButton && firstButton.Visibility() == winrt::Visibility::Visible)
{
auto const scopedRevoker = f6Button.GettingFocus(winrt::auto_revoke, [this](auto const&, auto const& args) {
m_previouslyFocusedElement = winrt::make_weak(args.OldFocusedElement());
});
const bool setFocus = f6Button.Focus(winrt::FocusState::Keyboard);
args.Handled(setFocus);
return firstButton;
}
else if (secondButton && secondButton.Visibility() == winrt::Visibility::Visible)
{
return secondButton;
}
return nullptr;
}();

if (f6Button)
{
auto const scopedRevoker = f6Button.GettingFocus(winrt::auto_revoke, [this](auto const&, auto const& args) {
m_previouslyFocusedElement = winrt::make_weak(args.OldFocusedElement());
});
const bool setFocus = f6Button.Focus(winrt::FocusState::Keyboard);
return setFocus;
}

return false;
}
}

Expand Down
3 changes: 3 additions & 0 deletions dev/TeachingTip/TeachingTip.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ class TeachingTip :
PropertyChanged_revoker m_automationNameChangedRevoker{};
PropertyChanged_revoker m_automationIdChangedRevoker{};
winrt::CoreDispatcher::AcceleratorKeyActivated_revoker m_acceleratorKeyActivatedRevoker{};
winrt::UIElement::PreviewKeyDown_revoker m_previewKeyDownForF6Revoker{};
winrt::Button::Click_revoker m_closeButtonClickedRevoker{};
winrt::Button::Click_revoker m_alternateCloseButtonClickedRevoker{};
winrt::Button::Click_revoker m_actionButtonClickedRevoker{};
Expand Down Expand Up @@ -115,6 +116,8 @@ class TeachingTip :

void OnContentSizeChanged(const winrt::IInspectable&, const winrt::SizeChangedEventArgs& args);
void OnF6AcceleratorKeyClicked(const winrt::CoreDispatcher&, const winrt::AcceleratorKeyEventArgs& args);
void OnF6PreviewKeyDownClicked(const winrt::IInspectable&, const winrt::KeyRoutedEventArgs& args);
bool HandleF6Clicked();
void OnCloseButtonClicked(const winrt::IInspectable&, const winrt::RoutedEventArgs&);
void OnActionButtonClicked(const winrt::IInspectable&, const winrt::RoutedEventArgs&);
void OnPopupOpened(const winrt::IInspectable&, const winrt::IInspectable&);
Expand Down