private static object?FindNextFocus( FocusNavigationDirection focusNavigationDirection, XYFocusOptions xyFocusOptions) { if (focusNavigationDirection == FocusNavigationDirection.None) { throw new ArgumentOutOfRangeException(nameof(focusNavigationDirection)); } var core = DXamlCore.Current; if (core == null) { throw new InvalidOperationException("XamlCore is not set."); } FocusManager?focusManager = null; if (xyFocusOptions.SearchRoot is DependencyObject searchRoot) { focusManager = VisualTree.GetFocusManagerForElement(searchRoot); } else if (core.GetHandle().InitializationType == InitializationType.IslandsOnly) { // Return error if searchRoot is not valid in islands/ desktop mode throw new ArgumentException("The search root must not be null."); } else { // For compat reasons, these FocusManager static APIs need to always use the CoreWindow as the // ContentRoot, so explicitly return the CoreWindow content root. var contentRootCoordinator = core.GetHandle().ContentRootCoordinator; var contentRoot = contentRootCoordinator?.CoreWindowContentRoot; if (contentRoot == null) { return(null); } focusManager = contentRoot.FocusManager; } if (focusManager == null) { return(null); } var root = focusManager.ContentRoot; var scale = RootScale.GetRasterizationScaleForContentRoot(root); ConvertOptionsRectsToPhysical(scale, xyFocusOptions); var candidate = focusManager.FindNextFocus( new FindFocusOptions(focusNavigationDirection), xyFocusOptions); return(candidate); }
internal static bool UseLayoutRoundingForBorderThickness(FrameworkElement element) { // Only snap BorderThickness if: // 1) LayoutRounding is enabled - prerequisite for any pixel snapping. // 2) There is no CornerRadius - we cannot guarantee snapping when there is a CornerRadius. // 3) Plateau != 1.0 - this snapping is to ensure that integral values of BorderThickness don't cause subpixel rendering at high plateau. // TODO: Remove check for plateau, BorderThickness should be consistently rounded at all plateaus. //return (RootScale.GetRasterizationScaleForElement(element) != 1.0f) && // element.GetUseLayoutRounding() && // (!HasNonZeroCornerRadius(element.GetCornerRadius())); return((RootScale.GetRasterizationScaleForElement(element) != 1.0f) && element.GetUseLayoutRounding() && (!HasNonZeroCornerRadius(element.GetCornerRadius()))); }
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); }