private IInputElement? GetNextTabStop()

in src/Avalonia.Base/Input/FocusManager.cs [606:712]


        private IInputElement? GetNextTabStop(IInputElement? currentTabStop = null, bool ignoreCurrentTabStop = false)
        {
            var focused = currentTabStop ?? Current;
            if (focused == null || _contentRoot == null)
            {
                return null;
            }

            IInputElement? currentCompare = focused;
            IInputElement? newTabStop = (focused as InputElement)?.GetNextTabStopOverride();

            if (newTabStop == null && !ignoreCurrentTabStop
                && (FocusHelpers.IsVisible(focused) && (FocusHelpers.CanHaveFocusableChildren(focused as AvaloniaObject) || FocusHelpers.CanHaveChildren(focused))))
            {
                newTabStop = GetFirstFocusableElement(focused, newTabStop);
            }

            if (newTabStop == null)
            {
                var currentPassed = false;
                var current = focused;
                var parent = FocusHelpers.GetFocusParent(focused);
                var parentIsRootVisual = parent == (_contentRoot as Visual)?.VisualRoot;

                while (parent != null && !parentIsRootVisual && newTabStop == null)
                {
                    if (IsValidTabStopSearchCandidate(current) && current is InputElement c && KeyboardNavigation.GetTabNavigation(c) == KeyboardNavigationMode.Cycle)
                    {
                        if (current == GetParentTabStopElement(focused))
                        {
                            newTabStop = GetFirstFocusableElement(focused, null);
                        }
                        else
                        {
                            newTabStop = GetFirstFocusableElement(current, current);
                        }
                        break;
                    }

                    if (IsValidTabStopSearchCandidate(parent) && parent is InputElement p && KeyboardNavigation.GetTabNavigation(p) == KeyboardNavigationMode.Once)
                    {
                        current = parent;
                        parent = FocusHelpers.GetFocusParent(focused);
                        if (parent == null)
                            break;
                    }
                    else if (!IsValidTabStopSearchCandidate(parent))
                    {
                        var parentElement = GetParentTabStopElement(parent);
                        if (parentElement == null)
                        {
                            parent = GetRootOfPopupSubTree(current) as IInputElement;

                            if (parent != null)
                            {
                                newTabStop = GetNextOrPreviousTabStopInternal(parent, current, newTabStop, true, ref currentPassed, ref currentCompare);

                                if (newTabStop != null && !FocusHelpers.IsFocusable(newTabStop))
                                {
                                    newTabStop = GetFirstFocusableElement(newTabStop, null);
                                }
                                if (newTabStop == null)
                                {
                                    newTabStop = GetFirstFocusableElement(parent, null);
                                }
                                break;
                            }

                            parent = (_contentRoot as Visual)?.VisualRoot as IInputElement;
                        }
                        else if (parentElement is InputElement pIE && KeyboardNavigation.GetTabNavigation(pIE) == KeyboardNavigationMode.None)
                        {
                            current = pIE;
                            parent = FocusHelpers.GetFocusParent(current);
                            if (parent == null)
                                break;
                        }
                        else
                        {
                            parent = parentElement as IInputElement;
                        }
                    }

                    newTabStop = GetNextOrPreviousTabStopInternal(parent, current, newTabStop, true, ref currentPassed, ref currentCompare);

                    if (newTabStop != null && !FocusHelpers.IsFocusable(newTabStop) && FocusHelpers.CanHaveFocusableChildren(newTabStop as AvaloniaObject))
                    {
                        newTabStop = GetFirstFocusableElement(newTabStop, null);
                    }

                    if (newTabStop != null)
                        break;

                    if (IsValidTabStopSearchCandidate(parent))
                    {
                        current = parent;
                    }

                    parent = FocusHelpers.GetFocusParent(parent);
                    currentPassed = false;

                    parentIsRootVisual = parent == (_contentRoot as Visual)?.VisualRoot;
                }
            }

            return newTabStop;
        }