diff --git a/src/Uno.UI/UI/Xaml/Controls/Page/Page.mux.cs b/src/Uno.UI/UI/Xaml/Controls/Page/Page.mux.cs index ad0cb2afe50e..97e7c3d5e7b2 100644 --- a/src/Uno.UI/UI/Xaml/Controls/Page/Page.mux.cs +++ b/src/Uno.UI/UI/Xaml/Controls/Page/Page.mux.cs @@ -10,6 +10,7 @@ using Uno.Extensions; using Uno.UI.Extensions; using Uno.UI.Xaml.Core; +using Uno.UI.Xaml.Input; using Windows.UI.Xaml.Automation.Peers; namespace Windows.UI.Xaml.Controls @@ -19,6 +20,7 @@ public partial class Page private protected override void OnLoaded() { base.OnLoaded(); + var spCurrentFocusedElement = this.GetFocusedElement(); var focusManager = VisualTree.GetFocusManagerForElement(this); @@ -26,6 +28,17 @@ private protected override void OnLoaded() if (setDefaultFocus && spCurrentFocusedElement == null) { + // Uno specific: If the page is focusable itself, we want to + // give it focus instead of the first element. + if (FocusProperties.IsFocusable(this)) + { + this.SetFocusedElement( + this, + FocusState.Programmatic, + animateIfBringIntoView: false); + return; + } + // Set the focus on the first focusable control var spFirstFocusableElementCDO = focusManager?.GetFirstFocusableElement(this); @@ -36,6 +49,8 @@ private protected override void OnLoaded() focusManager.InitialFocus = true; TrySetFocusedElement(spFirstFocusableElementDO); + + focusManager.InitialFocus = false; } if (spFirstFocusableElementCDO == null) diff --git a/src/Uno.UI/UI/Xaml/Input/FocusManager.Android.cs b/src/Uno.UI/UI/Xaml/Input/FocusManager.Android.cs index bc923a8474bd..3b8f08653af2 100644 --- a/src/Uno.UI/UI/Xaml/Input/FocusManager.Android.cs +++ b/src/Uno.UI/UI/Xaml/Input/FocusManager.Android.cs @@ -8,6 +8,7 @@ using Windows.UI.Xaml.Controls; using Android.Graphics; using Windows.UI.ViewManagement; +using Uno.UI.Xaml.Core; namespace Windows.UI.Xaml.Input { @@ -18,7 +19,13 @@ private static void FocusNative(UIElement element) // TODO Uno: Handle Hyperlink focus if (element is Control control) { - control.RequestFocus(); + var focusManager = VisualTree.GetFocusManagerForElement(control); + if (element is Android.Views.View androidView && + androidView.Focusable && + focusManager?.InitialFocus == false) // Do not focus natively on initial focus so the soft keyboard is not opened + { + control.RequestFocus(); + } // Forcefully try to bring the control into view when keyboard is open to accommodate adjust nothing mode if (InputPane.GetForCurrentView().Visible) diff --git a/src/Uno.UI/UI/Xaml/Input/FocusManager.iOS.cs b/src/Uno.UI/UI/Xaml/Input/FocusManager.iOS.cs index 35d4a6062be7..f055fa6e4177 100644 --- a/src/Uno.UI/UI/Xaml/Input/FocusManager.iOS.cs +++ b/src/Uno.UI/UI/Xaml/Input/FocusManager.iOS.cs @@ -5,11 +5,21 @@ using UIKit; using Uno.UI.Extensions; using Windows.UI.Xaml.Controls; +using Windows.UI.ViewManagement; +using Uno.UI.Xaml.Core; namespace Windows.UI.Xaml.Input { public partial class FocusManager - { - private static void FocusNative(UIElement control) => control?.BecomeFirstResponder(); + { + private static void FocusNative(UIElement control) + { + var focusManager = VisualTree.GetFocusManagerForElement(control); + if (control?.CanBecomeFirstResponder == true && + focusManager?.InitialFocus == false) // Do not focus natively on initial focus so the soft keyboard is not opened + { + control.BecomeFirstResponder(); + } + } } } diff --git a/src/Uno.UI/UI/Xaml/Input/FocusManager.macOS.cs b/src/Uno.UI/UI/Xaml/Input/FocusManager.macOS.cs index 4febee1d5c11..f37a52311895 100644 --- a/src/Uno.UI/UI/Xaml/Input/FocusManager.macOS.cs +++ b/src/Uno.UI/UI/Xaml/Input/FocusManager.macOS.cs @@ -10,6 +10,12 @@ namespace Windows.UI.Xaml.Input { public partial class FocusManager { - private static void FocusNative(UIElement control) => control?.BecomeFirstResponder(); + private static void FocusNative(UIElement control) + { + if (control?.AcceptsFirstResponder() == true) + { + Window.Current?.NativeWindow?.MakeFirstResponder(control); + } + } } } diff --git a/src/Uno.UI/UI/Xaml/Input/FocusManager.wasm.cs b/src/Uno.UI/UI/Xaml/Input/FocusManager.wasm.cs index 3fec909f06f8..5e0f516e95fe 100644 --- a/src/Uno.UI/UI/Xaml/Input/FocusManager.wasm.cs +++ b/src/Uno.UI/UI/Xaml/Input/FocusManager.wasm.cs @@ -82,6 +82,14 @@ internal static bool FocusNative(UIElement element) return false; } + var focusManager = VisualTree.GetFocusManagerForElement(element); + + if (focusManager?.InitialFocus == true) + { + // Do not focus natively on initial focus so the soft keyboard is not opened + return false; + } + if (element is TextBox textBox) { return textBox.FocusTextView(); diff --git a/src/Uno.UI/UI/Xaml/Window.macOS.cs b/src/Uno.UI/UI/Xaml/Window.macOS.cs index 6d9a5072081f..cd9b38d8b6cc 100644 --- a/src/Uno.UI/UI/Xaml/Window.macOS.cs +++ b/src/Uno.UI/UI/Xaml/Window.macOS.cs @@ -1,18 +1,18 @@ -using CoreGraphics; -using Foundation; using System; +using System.Drawing; using System.Linq; using System.Runtime.InteropServices; using AppKit; +using CoreGraphics; +using Foundation; +using Uno.UI; +using Uno.UI.Controls; +using Uno.UI.Xaml.Core; using Windows.Foundation; using Windows.Foundation.Metadata; using Windows.UI.Core; -using Uno.UI.Controls; -using System.Drawing; using Windows.UI.ViewManagement; -using Uno.UI; using Windows.UI.Xaml.Controls; -using Uno.UI.Xaml.Core; namespace Windows.UI.Xaml { @@ -62,6 +62,8 @@ public Window() InitializeCommon(); } + internal NSWindow NativeWindow => _window; + private void ObserveOrientationAndSize() { _windowResizeNotificationObject = NSNotificationCenter.DefaultCenter.AddObserver(