Ejemplo n.º 1
0
        internal static bool SetFocusedElementWithDirection(
            DependencyObject pElement,
            FocusState focusState,
            bool animateIfBringIntoView,
            bool forceBringIntoView,
            FocusNavigationDirection focusNavigationDirection)
        {
            DependencyObject spElementToFocus = pElement;
            Control?         spControlToFocus;
            bool             pFocusUpdated = false;

            if (pElement == null)
            {
                throw new ArgumentNullException(nameof(pElement));
            }

            spControlToFocus = spElementToFocus as Control;
            if (spControlToFocus != null)
            {
                // For control, use IControl.Focus, for safer backward compat
                if (animateIfBringIntoView)
                {
                    // Set the flag that indicates that the Focus change operation
                    // needs to use an animation if the element is brouhgt into view.
                    (spControlToFocus as Control).SetAnimateIfBringIntoView();
                }

                pFocusUpdated = (spControlToFocus as Control).FocusWithDirection(focusState, focusNavigationDirection);
            }
            else
            {
                bool isShiftPressed  = (focusNavigationDirection == FocusNavigationDirection.Previous);
                bool isProcessingTab = (focusNavigationDirection == FocusNavigationDirection.Next) || isShiftPressed;

                // Set focus on non-controls, like Hyperlink.
                DependencyObject?spElementToFocusDO;
                spElementToFocusDO = spElementToFocus as DependencyObject;
                FocusManager? focusManager = VisualTree.GetFocusManagerForElement(spElementToFocusDO);
                FocusMovement movement     = new FocusMovement(
                    spElementToFocusDO,
                    focusNavigationDirection,
                    focusState);
                movement.ForceBringIntoView     = forceBringIntoView;
                movement.AnimateIfBringIntoView = animateIfBringIntoView;
                movement.IsProcessingTab        = isProcessingTab;
                movement.IsShiftPressed         = isShiftPressed;
                var result = focusManager?.SetFocusedElement(movement);
                pFocusUpdated = result?.WasMoved ?? false;
            }

            return(pFocusUpdated);
        }
Ejemplo n.º 2
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);
        }
Ejemplo n.º 3
0
        internal bool Focus(FocusState focusState, bool animateIfBringIntoView, FocusNavigationDirection focusNavigationDirection = FocusNavigationDirection.None)
        {
            // Get FocusManager
            var pFocusManager = VisualTree.GetFocusManagerForElement(this, VisualTree.LookupOptions.NoFallback);

            if (pFocusManager == null)
            {
                return(false);
            }

            // FocusMovement is OK with NULL parameter, sets focusChanged to false
            FocusMovement movement = new FocusMovement(this, focusNavigationDirection, focusState);

            movement.AnimateIfBringIntoView = animateIfBringIntoView;
            FocusMovementResult result = pFocusManager.SetFocusedElement(movement);
            var focusChanged           = result.WasMoved;

            return(focusChanged);
        }
Ejemplo n.º 4
0
 public FocusMovementResult SetFocusedElement(FocusMovement movement) =>
 SetFocusedElementResult ?? new FocusMovementResult();
Ejemplo n.º 5
0
        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);
        }