From 9678bbacbe801752ce5e34862d6e5dc5cf5baa24 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Fri, 13 Sep 2024 11:27:46 +0200 Subject: [PATCH] Revert "Make sure Popups do not attempt to take focus when they are shown (#16365)" This reverts commit 80d73e44113294ad28d0441c4ed7a1a449eb00dc. --- native/Avalonia.Native/src/OSX/AvnView.mm | 17 +------------- src/Avalonia.Native/PopupImpl.cs | 28 +++++++++++------------ src/Avalonia.Native/TopLevelImpl.cs | 2 +- src/Windows/Avalonia.Win32/PopupImpl.cs | 19 +++++++++++++++ 4 files changed, 35 insertions(+), 31 deletions(-) diff --git a/native/Avalonia.Native/src/OSX/AvnView.mm b/native/Avalonia.Native/src/OSX/AvnView.mm index 65b63e647f..6c626c3b9d 100644 --- a/native/Avalonia.Native/src/OSX/AvnView.mm +++ b/native/Avalonia.Native/src/OSX/AvnView.mm @@ -297,22 +297,7 @@ ) ) ) - { - WindowBaseImpl* windowBase = dynamic_cast(_parent.getRaw()); - - if(windowBase != nullptr){ - WindowBaseImpl* parent = windowBase->Parent; - - if(parent != nullptr){ - auto parentWindow = parent->Window; - - [parentWindow makeFirstResponder:parent->View]; - } - } else{ - [self becomeFirstResponder]; - } - } - + [self becomeFirstResponder]; if(_parent != nullptr) { diff --git a/src/Avalonia.Native/PopupImpl.cs b/src/Avalonia.Native/PopupImpl.cs index 301299e623..e0d7a0a3eb 100644 --- a/src/Avalonia.Native/PopupImpl.cs +++ b/src/Avalonia.Native/PopupImpl.cs @@ -8,6 +8,8 @@ namespace Avalonia.Native class PopupImpl : WindowBaseImpl, IPopupImpl { private readonly ITopLevelImpl _parent; + private readonly IAvnPopup _native; + private readonly AvaloniaNativeTextInputMethod _inputMethod; public PopupImpl(IAvaloniaNativeFactory factory, ITopLevelImpl parent) : base(factory) @@ -16,7 +18,7 @@ namespace Avalonia.Native using (var e = new PopupEvents(this)) { - Init(new MacOSTopLevelHandle(factory.CreatePopup(e)), factory.CreateScreens()); + Init(new MacOSTopLevelHandle(_native = factory.CreatePopup(e)), factory.CreateScreens()); } PopupPositioner = new ManagedPopupPositioner(new ManagedPopupPositionerPopupImplHelper(parent, MoveResize)); @@ -26,15 +28,10 @@ namespace Avalonia.Native parent = popupImpl._parent; } - if (parent is WindowBaseImpl windowBaseImpl) - { - Native!.SetParent(windowBaseImpl.Native); - } - //Use the parent's input context to process events if (parent is TopLevelImpl topLevelImpl) { - InputMethod = topLevelImpl.InputMethod; + _inputMethod = topLevelImpl.InputMethod; } } @@ -43,13 +40,6 @@ namespace Avalonia.Native base.Init(handle, screens); } - public override void Dispose() - { - Native!.SetParent(null); - - base.Dispose(); - } - private void MoveResize(PixelPoint position, Size size, double scaling) { Position = position; @@ -81,6 +71,16 @@ namespace Avalonia.Native } } + public override void Show(bool activate, bool isDialog) + { + var parent = _parent; + while (parent is PopupImpl p) + parent = p._parent; + if (parent is WindowImpl w) + w.Native.TakeFocusFromChildren(); + base.Show(false, isDialog); + } + public override IPopupImpl CreatePopup() => new PopupImpl(Factory, this); public void SetWindowManagerAddShadowHint(bool enabled) diff --git a/src/Avalonia.Native/TopLevelImpl.cs b/src/Avalonia.Native/TopLevelImpl.cs index 64ca23d2a5..7d19906d29 100644 --- a/src/Avalonia.Native/TopLevelImpl.cs +++ b/src/Avalonia.Native/TopLevelImpl.cs @@ -110,7 +110,7 @@ internal class TopLevelImpl : ITopLevelImpl, IFramebufferPlatformSurface public IAvnTopLevel? Native => _handle?.Native; public IPlatformHandle? Handle => _handle; - public AvaloniaNativeTextInputMethod? InputMethod { get; protected set; } + public AvaloniaNativeTextInputMethod? InputMethod { get; private set; } public Size ClientSize { get diff --git a/src/Windows/Avalonia.Win32/PopupImpl.cs b/src/Windows/Avalonia.Win32/PopupImpl.cs index bb62ef152d..8889ca59b8 100644 --- a/src/Windows/Avalonia.Win32/PopupImpl.cs +++ b/src/Windows/Avalonia.Win32/PopupImpl.cs @@ -22,6 +22,25 @@ namespace Avalonia.Win32 { // Popups are always shown non-activated. UnmanagedMethods.ShowWindow(Handle.Handle, UnmanagedMethods.ShowWindowCommand.ShowNoActivate); + + // We need to steal focus if it's held by a child window of our toplevel window + var parent = _parent; + while(parent != null) + { + if(parent is PopupImpl pi) + parent = pi._parent; + else + break; + } + + if(parent == null) + return; + + var focusOwner = UnmanagedMethods.GetFocus(); + if (focusOwner != IntPtr.Zero && + UnmanagedMethods.GetAncestor(focusOwner, UnmanagedMethods.GetAncestorFlags.GA_ROOT) + == parent.Handle?.Handle) + UnmanagedMethods.SetFocus(parent.Handle.Handle); } protected override bool ShouldTakeFocusOnClick => false;