Skip to content

Instantly share code, notes, and snippets.

@lyahdav
Created September 30, 2020 18:51
Show Gist options
  • Save lyahdav/403c4087a2900fe6ded8493cb99bca0b to your computer and use it in GitHub Desktop.
Save lyahdav/403c4087a2900fe6ded8493cb99bca0b to your computer and use it in GitHub Desktop.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#include "pch.h"
#include "FocusZoneViewManager.h"
#include "ViewControl.h"
#include "DynamicAutomationProperties.h"
#include <Modules/NativeUIManager.h>
#include <Utils/AccessibilityUtils.h>
#include <Utils/PropertyUtils.h>
#include <INativeUIManager.h>
#include <IReactInstance.h>
#include <winrt/Windows.System.h>
#include <winrt/Windows.UI.Core.h>
#include <winrt/Windows.UI.Xaml.Input.h>
#include <winrt/Windows.UI.Xaml.Controls.Primitives.h>
namespace winrt {
using namespace Windows::Foundation;
using namespace Windows::UI;
using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Controls;
using namespace Windows::UI::Xaml::Controls::Primitives;
using namespace Windows::UI::Xaml::Media;
} // namespace winrt
namespace react {
namespace uwp {
FocusZoneViewManager::FocusZoneViewManager(const std::shared_ptr<IReactInstance> &reactInstance) : Super(reactInstance) {}
const char *FocusZoneViewManager::GetName() const {
return "FocusZoneView";
}
XamlView FocusZoneViewManager::CreateViewCore(int64_t /*tag*/) {
auto panel = winrt::make<winrt::react::uwp::implementation::ViewPanel>();
panel.VerticalAlignment(winrt::VerticalAlignment::Stretch);
panel.HorizontalAlignment(winrt::HorizontalAlignment::Stretch);
m_panelKeyDownRevoker = panel.KeyDown(winrt::auto_revoke, [=](const winrt::IInspectable &sender, const winrt::KeyRoutedEventArgs &e) {
OnKeyDown(sender, e);
});
return panel.as<XamlView>();
}
void FocusZoneViewManager::OnKeyDown(const winrt::IInspectable &sender, const winrt::KeyRoutedEventArgs &e) {
winrt::XamlRoot xamlRoot = nullptr;
auto wkinstance = GetReactInstance();
if (auto instance = wkinstance.lock()) {
xamlRoot = static_cast<NativeUIManager *>(instance->NativeUIManager())->tryGetXamlRoot();
}
if (!xamlRoot) {
return;
}
auto senderFrameworkElement = sender.try_as<winrt::FrameworkElement>();
auto focusedElement = winrt::FocusManager::GetFocusedElement(xamlRoot).try_as<winrt::DependencyObject>();
winrt::FindNextElementOptions findNextElementOptions = winrt::FindNextElementOptions();
findNextElementOptions.SearchRoot(xamlRoot.Content());
if (e.Key() == winrt::Windows::System::VirtualKey::Up) {
auto firstFocusableElement =
winrt::FocusManager::FindFirstFocusableElement(senderFrameworkElement).try_as<winrt::DependencyObject>();
auto isFirstElementFocused = firstFocusableElement == focusedElement;
if (!isFirstElementFocused)
{
winrt::FocusManager::TryMoveFocus(winrt::FocusNavigationDirection::Previous, findNextElementOptions);
e.Handled(true);
}
} else if (e.Key() == winrt::Windows::System::VirtualKey::Down) {
auto lastFocusableElement = winrt::FocusManager::FindLastFocusableElement(senderFrameworkElement).try_as<winrt::DependencyObject>();
auto isLastElementFocused = lastFocusableElement == focusedElement;
if (!isLastElementFocused)
{
winrt::FocusManager::TryMoveFocus(winrt::FocusNavigationDirection::Next, findNextElementOptions);
e.Handled(true);
}
} else if (e.Key() == winrt::Windows::System::VirtualKey::Tab) {
auto const &coreWindow = winrt::CoreWindow::GetForCurrentThread();
auto isShiftDown = KeyboardHelper::IsModifiedKeyPressed(coreWindow, winrt::Windows::System::VirtualKey::Shift);
auto exclusionRect = winrt::Rect(ViewPanel::GetLeft(senderFrameworkElement), ViewPanel::GetTop(senderFrameworkElement), senderFrameworkElement.Width(), senderFrameworkElement.Height());
// auto exclusionRect = winrt::LayoutInformation::GetLayoutSlot(sender.try_as<winrt::FrameworkElement>());
findNextElementOptions.ExclusionRect(exclusionRect);
auto nextElement = winrt::FocusManager::FindNextElement(isShiftDown ? winrt::FocusNavigationDirection::Up : winrt::FocusNavigationDirection::Down, findNextElementOptions);
winrt::FocusManager::TryFocusAsync(nextElement, winrt::FocusState::Programmatic);
e.Handled(true);
}
}
} // namespace uwp
} // namespace react
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment