private IInputElement? GetPreviousTabStop()

in src/Avalonia.Base/Input/FocusManager.cs [714:832]


        private IInputElement? GetPreviousTabStop(IInputElement? currentTabStop = null, bool ignoreCurrentTabStop = false)
        {
            var focused = currentTabStop ?? Current;
            if (focused == null || _contentRoot == null)
            {
                return null;
            }
            IInputElement? newTabStop = (focused as InputElement)?.GetPreviousTabStopOverride();
            IInputElement? currentCompare = focused;

            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)
                    {
                        newTabStop = GetFirstFocusableElement(current, current);
                        break;
                    }

                    if (IsValidTabStopSearchCandidate(parent) && parent is InputElement p && KeyboardNavigation.GetTabNavigation(p) == KeyboardNavigationMode.Once)
                    {
                        if (FocusHelpers.IsFocusable(parent))
                        {
                            newTabStop = parent;
                        }
                        else
                        {
                            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, false, ref currentPassed, ref currentCompare);

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

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

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

                    if (newTabStop == null && FocusHelpers.IsPotentialTabStop(parent) && FocusHelpers.IsFocusable(parent))
                    {
                        if (parent is InputElement iE && KeyboardNavigation.GetTabNavigation(iE) == KeyboardNavigationMode.Cycle)
                        {
                            newTabStop = GetLastFocusableElement(parent, null);
                        }
                        else
                        {
                            newTabStop = parent;
                        }
                    }
                    else
                    {
                        if (newTabStop != null && FocusHelpers.CanHaveFocusableChildren(newTabStop as AvaloniaObject))
                        {
                            newTabStop = GetLastFocusableElement(newTabStop, null);
                        }
                    }

                    if (newTabStop != null)
                        break;

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

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

            return newTabStop;
        }