void CommandBarFlyoutCommandBar::OnKeyDown()

in dev/CommandBarFlyout/CommandBarFlyoutCommandBar.cpp [928:1066]


void CommandBarFlyoutCommandBar::OnKeyDown(
    winrt::KeyRoutedEventArgs const& args)
{
    COMMANDBARFLYOUT_TRACE_INFO(*this, TRACE_MSG_METH_STR, METH_NAME, this,
        TypeLogging::KeyRoutedEventArgsToString(args).c_str());

    if (args.Handled())
    {
        return;
    }

    switch (args.Key())
    {
    case winrt::VirtualKey::Tab:
    {
        if (SecondaryCommands().Size() > 0 && !IsOpen())
        {
            // Ensure the secondary commands flyout is open ...
            IsOpen(true);

            // ... and focus the first focusable command
            FocusCommand(
                SecondaryCommands() /*commands*/,
                nullptr /*moreButton*/,
                winrt::FocusState::Keyboard /*focusState*/,
                true /*firstCommand*/,
                SharedHelpers::IsRS3OrHigher() /*ensureTabStopUniqueness*/);
        }
        break;
    }

    case winrt::VirtualKey::Escape:
    {
        if (auto owningFlyout = m_owningFlyout.get())
        {
            owningFlyout.Hide();
            args.Handled(true);
        }
        break;
    }

    case winrt::VirtualKey::Right:
    case winrt::VirtualKey::Left:
    case winrt::VirtualKey::Down:
    case winrt::VirtualKey::Up:
    {
        const bool isRightToLeft = m_primaryItemsRoot && m_primaryItemsRoot.get().FlowDirection() == winrt::FlowDirection::RightToLeft;
        const bool isLeft = (args.Key() == winrt::VirtualKey::Left && !isRightToLeft) || (args.Key() == winrt::VirtualKey::Right && isRightToLeft);
        const bool isRight = (args.Key() == winrt::VirtualKey::Right && !isRightToLeft) || (args.Key() == winrt::VirtualKey::Left && isRightToLeft);
        const bool isDown = args.Key() == winrt::VirtualKey::Down;
        const bool isUp = args.Key() == winrt::VirtualKey::Up;

        // To avoid code duplication, we'll use the key directionality to determine
        // both which control list to use and in which direction to iterate through
        // it to find the next control to focus.  Then we'll do that iteration
        // to focus the next control.
        auto const& accessibleControls{ isUp || isDown ? m_verticallyAccessibleControls : m_horizontallyAccessibleControls };
        int const startIndex = isLeft || isUp ? accessibleControls.Size() - 1 : 0;
        int const endIndex = isLeft || isUp ? -1 : accessibleControls.Size();
        int const deltaIndex = isLeft || isUp ? -1 : 1;
        bool const shouldLoop = isUp || isDown;
        winrt::Control focusedControl{ nullptr };
        int focusedControlIndex = -1;

        for (int i = startIndex;
            // We'll stop looping at the end index unless we're looping,
            // in which case we want to wrap back around to the start index.
            (i != endIndex || shouldLoop) ||
            // If we found a focused control but have looped all the way back around,
            // then there wasn't another control to focus, so we should quit.
            (focusedControlIndex > 0 && i == focusedControlIndex);
            i += deltaIndex)
        {
            // If we've reached the end index, that means we want to loop.
            // We'll wrap around to the start index.
            if (i == endIndex)
            {
                MUX_ASSERT(shouldLoop);

                if (focusedControl)
                {
                    i = startIndex;
                }
                else
                {
                    // If no focused control was found after going through the entire list of controls,
                    // then we have nowhere for focus to go.  Let's early-out in that case.
                    break;
                }
            }

            auto const& control = accessibleControls.GetAt(i);

            // If we've yet to find the focused control, we'll keep looking for it.
            // Otherwise, we'll try to focus the next control after it.
            if (!focusedControl)
            {
                if (control.FocusState() != winrt::FocusState::Unfocused)
                {
                    focusedControl = control;
                    focusedControlIndex = i;
                }
            }
            else if (IsControlFocusable(control, false /*checkTabStop*/))
            {
                // If the control we're trying to focus is in the secondary command list,
                // then we'll make sure that that list is open before trying to focus the control.
                if (auto const& controlAsCommandBarElement = control.try_as<winrt::ICommandBarElement>())
                {
                    uint32_t index = 0;
                    if (SecondaryCommands().IndexOf(controlAsCommandBarElement, index) && !IsOpen())
                    {
                        IsOpen(true);
                    }
                }

                if (FocusControl(
                    accessibleControls.GetAt(i) /*newFocus*/,
                    focusedControl /*oldFocus*/,
                    winrt::FocusState::Keyboard /*focusState*/,
                    true /*updateTabStop*/))
                {
                    args.Handled(true);
                    break;
                }
            }
        }

        if (!args.Handled())
        {
            // Occurs for example with Right key while MoreButton has focus. Stay on that MoreButton.
            args.Handled(true);
        }
        break;
    }
    }

    __super::OnKeyDown(args);
}