Example #1
0
        private static IAsyncOperation <FocusMovementResult> TryFocusAsyncImpl(
            DependencyObject pElement,
            FocusState focusState)
        {
            FocusManager?focusManager = VisualTree.GetFocusManagerForElement(pElement);

            if (focusManager == null)
            {
                throw new InvalidOperationException("Element is not part of the visual tree.");
            }

            FocusMovement movement = new FocusMovement(pElement, FocusNavigationDirection.None, focusState);

            var spFocusAsyncOperation = new FocusAsyncOperation(movement.CorrelationId);
            var asyncOperation        = spFocusAsyncOperation.CreateAsyncOperation();

            if (FocusProperties.IsFocusable(pElement) == false)
            {
                // We need to start and complete the async operation since this is a no-op

                spFocusAsyncOperation.CoreSetResults(new FocusMovementResult());
                spFocusAsyncOperation.CoreFireCompletion();
                return(asyncOperation);
            }

            // TODO Uno specific: Do not use async operations, only simulated
            //movement.ShouldCompleteAsyncOperation = focusManager.TrySetAsyncOperation(spFocusAsyncOperation);
            if (movement.ShouldCompleteAsyncOperation)
            {
                //spFocusAsyncOperation.StartOperation();
            }

            var result = focusManager.SetFocusedElement(movement);

            // TODO Uno specific: Simulate async completion.
            spFocusAsyncOperation?.CoreSetResults(result);
            spFocusAsyncOperation?.CoreFireCompletion();

            // Async operation is not guaranteed to be released synchronously.
            // Therefore, we let UpdateFocus to handle the responsibility of releasing it.
            //spFocusAsyncOperation.Detach();

            return(asyncOperation);
        }
        private static bool TryMoveFocusStatic(
            FocusNavigationDirection focusNavigationDirection,
            FindNextElementOptions?pFocusNavigationOverride,
            ref IAsyncOperation <FocusMovementResult>?asyncOperation,
            bool useAsync)
        {
            DependencyObject?searchRootAsDO = null;
            Rect             hintRect;
            Rect             exclusionRect;
            XYFocusNavigationStrategyOverride navigationStrategyOverride;
            XYFocusOptions xyFocusOptions = new XYFocusOptions();
            var            pIsFocusMoved  = false;

            FindNextElementOptions?options = pFocusNavigationOverride;

            bool ignoreOcclusivity;
            FocusAsyncOperation?spFocusAsyncOperation = null;

            DXamlCore pCore = DXamlCore.Current;

            if (pCore == null)
            {
                throw new InvalidOperationException("XamlCore is not set.");
            }

            FocusManager?focusManager           = null;
            ContentRoot? contentRoot            = null;
            var          contentRootCoordinator = pCore.GetHandle().ContentRootCoordinator;

            if (options != null)
            {
                var searchRoot = options.SearchRoot;
                exclusionRect = options.ExclusionRect;
                hintRect      = options.HintRect;
                navigationStrategyOverride = options.XYFocusNavigationStrategyOverride;
                ignoreOcclusivity          = options.IgnoreOcclusivity;
                searchRootAsDO             = searchRoot as DependencyObject;

                if (searchRootAsDO != null)
                {
                    contentRoot  = VisualTree.GetContentRootForElement(searchRootAsDO);
                    focusManager = contentRoot?.FocusManager;

                    if (focusManager == null)
                    {
                        throw new InvalidOperationException("Search root is not part of the visual tree.");
                    }
                }
                else if (pCore.GetHandle().InitializationType == InitializationType.IslandsOnly)
                {
                    // SearchRoot must exist for islands/ desktop
                    throw new ArgumentException("The search root must not be null.");
                }
                else
                {
                    contentRoot = contentRootCoordinator?.CoreWindowContentRoot;
                }

                // If we are being passed in the public root visual of a XamlRoot as the SearchRoot, then override the SearchRoot to be the RootVisual.
                // This will enable searching through both the public root visual and the popup root. We will also allow Next/Prev.
                bool shouldOverrideSearchRoot =
                    contentRoot != null &&
                    GetAppVisibleXamlRootContent(contentRoot) == searchRootAsDO;

                if (shouldOverrideSearchRoot)
                {
                    searchRootAsDO = contentRoot !.VisualTree.RootElement;
                }
                else
                {
                    if (focusNavigationDirection != FocusNavigationDirection.Up &&
                        focusNavigationDirection != FocusNavigationDirection.Down &&
                        focusNavigationDirection != FocusNavigationDirection.Left &&
                        focusNavigationDirection != FocusNavigationDirection.Right)
                    {
                        throw new ArgumentOutOfRangeException(
                                  "Focus navigation directions Next, Previous, and None " +
                                  "are not supported when using FindNextElementOptions");
                    }
                }

                xyFocusOptions.NavigationStrategyOverride = navigationStrategyOverride;
                xyFocusOptions.IgnoreOcclusivity          = ignoreOcclusivity;

                Rect exclusionRectNative = exclusionRect;
                Rect hintRectNative      = hintRect;

                if (searchRootAsDO != null)
                {
                    xyFocusOptions.SearchRoot = searchRootAsDO;
                }

                if (!exclusionRectNative.IsUniform)
                {
                    xyFocusOptions.ExclusionRect = exclusionRectNative;
                }

                if (!hintRectNative.IsUniform)
                {
                    xyFocusOptions.FocusHintRectangle = hintRectNative;
                }

                if (contentRoot != null)
                {
                    var scale = RootScale.GetRasterizationScaleForContentRoot(contentRoot);
                    ConvertOptionsRectsToPhysical(scale, xyFocusOptions);
                }
            }

            if (focusManager == null)
            {
                // Return error if call is without focus navigation option in islands/ desktop
                if (pCore.GetHandle().InitializationType == InitializationType.IslandsOnly)
                {
                    throw new InvalidOperationException("Focus navigation options must be set for desktop apps.");
                }

                // For compat reasons, these FocusManager static APIs need to always use the CoreWindow as the
                // ContentRoot, so explicitly return the CoreWindow content root.
                if (contentRoot == null)
                {
                    contentRoot = contentRootCoordinator?.CoreWindowContentRoot;
                }
                if (contentRoot == null)
                {
                    return(pIsFocusMoved);
                }

                focusManager = contentRoot.FocusManager;
            }

            FocusMovement movement = new FocusMovement(xyFocusOptions, focusNavigationDirection, null);

            if (useAsync)
            {
                spFocusAsyncOperation = new FocusAsyncOperation(movement.CorrelationId);
                asyncOperation        = spFocusAsyncOperation.CreateAsyncOperation();

                // Async operation is not guaranteed to be released synchronously.
                // Therefore, we let UpdateFocus to handle the responsibility of releasing it.
                // TODO Uno specific: Do not use async operations, only simulated
                // movement.ShouldCompleteAsyncOperation = focusManager.TrySetAsyncOperation(spFocusAsyncOperation);

                if (movement.ShouldCompleteAsyncOperation)
                {
                    //spFocusAsyncOperation.StartOperation();
                }
            }

            FocusMovementResult result = focusManager.FindAndSetNextFocus(movement);

            // TODO Uno specific: Simulate async completion.
            spFocusAsyncOperation?.CoreSetResults(result);
            spFocusAsyncOperation?.CoreFireCompletion();

            // We ignore result.GetHResult() here because this is a "Try" function
            pIsFocusMoved = result.WasMoved;

            // Async operation is not guaranteed to be released synchronously.
            // Therefore, we let UpdateFocus to handle the responsibility of releasing it.
            //spFocusAsyncOperation.Detach();

            return(pIsFocusMoved);
        }