From 6e7d2bec62e5f0169c89e2cc13aba4fbdecfe4d7 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 14 May 2020 11:21:19 -0300 Subject: [PATCH 01/25] add new IWindowImpl members, remove ShowDialog. --- src/Avalonia.Controls/Platform/IWindowImpl.cs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Controls/Platform/IWindowImpl.cs b/src/Avalonia.Controls/Platform/IWindowImpl.cs index 5fa0ec57b5..cf31d30332 100644 --- a/src/Avalonia.Controls/Platform/IWindowImpl.cs +++ b/src/Avalonia.Controls/Platform/IWindowImpl.cs @@ -26,9 +26,21 @@ namespace Avalonia.Platform void SetTitle(string title); /// - /// Shows the window as a dialog. + /// Sets the parent of the window. /// - void ShowDialog(IWindowImpl parent); + /// The parent . + void SetParent(IWindowImpl parent); + + /// + /// Disables the window for example when a modal dialog is open. + /// + /// true if the window is enabled, or false if it is disabled. + void SetEnabled(bool enable); + + /// + /// Called when a disabled window received input. Can be used to activate child windows. + /// + Action GotInputWhenDisabled { get; set; } /// /// Enables or disables system window decorations (title bar, buttons, etc) From e434d68f2e68422318b0f8d0024f73b089dd071f Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 14 May 2020 11:32:44 -0300 Subject: [PATCH 02/25] implement showdialog using new apis. --- src/Avalonia.Controls/Window.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index 7dacf4b2af..7fa21669f7 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Reactive.Linq; @@ -519,7 +520,9 @@ namespace Avalonia.Controls using (BeginAutoSizing()) { - PlatformImpl?.ShowDialog(owner.PlatformImpl); + PlatformImpl.SetParent(owner.PlatformImpl); + owner.PlatformImpl.SetEnabled(false); + PlatformImpl?.Show(); Renderer?.Start(); From a8418189d2bc6dc268e7fccb037a840911c3abc7 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 14 May 2020 11:34:03 -0300 Subject: [PATCH 03/25] win32 implementation uses new apis for showdialog. --- src/Windows/Avalonia.Win32/WindowImpl.cs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 608563cb67..d57884c29e 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -354,19 +354,20 @@ namespace Avalonia.Win32 public virtual void Show() { - SetWindowLongPtr(_hwnd, (int)WindowLongParam.GWL_HWNDPARENT, IntPtr.Zero); + SetWindowLongPtr(_hwnd, (int)WindowLongParam.GWL_HWNDPARENT, _parent != null ? _parent._hwnd : IntPtr.Zero); ShowWindow(_showWindowState); } - public void ShowDialog(IWindowImpl parent) + public Action GotInputWhenDisabled { get; set; } + + public void SetParent(IWindowImpl parent) { _parent = (WindowImpl)parent; _parent._disabledBy.Add(this); - _parent.UpdateEnabled(); - SetWindowLongPtr(_hwnd, (int)WindowLongParam.GWL_HWNDPARENT, ((WindowImpl)parent)._hwnd); - ShowWindow(_showWindowState); } + public void SetEnabled(bool enable) => EnableWindow(_hwnd, enable); + public void BeginMoveDrag(PointerPressedEventArgs e) { _mouseDevice.Capture(null); @@ -723,7 +724,7 @@ namespace Avalonia.Win32 private void UpdateEnabled() { - EnableWindow(_hwnd, _disabledBy.Count == 0); + SetEnabled(_disabledBy.Count == 0); } private void UpdateWindowProperties(WindowProperties newProperties, bool forceChanges = false) From 4fe8e41646e5a483780a76726ee8a590975c2f7f Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 14 May 2020 11:36:58 -0300 Subject: [PATCH 04/25] add x11 implementation. --- src/Avalonia.X11/X11Window.cs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.X11/X11Window.cs b/src/Avalonia.X11/X11Window.cs index 1b3d1a7dda..eb1759aadd 100644 --- a/src/Avalonia.X11/X11Window.cs +++ b/src/Avalonia.X11/X11Window.cs @@ -44,6 +44,8 @@ namespace Avalonia.X11 private HashSet _transientChildren = new HashSet(); private X11Window _transientParent; private double? _scalingOverride; + private bool _disabled; + public object SyncRoot { get; } = new object(); class InputEventContainer @@ -773,6 +775,11 @@ namespace Avalonia.X11 bool ActivateTransientChildIfNeeded() { + if(_disabled) + { + return false; + } + if (_transientChildren.Count == 0) return false; var child = _transientChildren.First(); @@ -1035,12 +1042,18 @@ namespace Avalonia.X11 ChangeWMAtoms(value, _x11.Atoms._NET_WM_STATE_ABOVE); } - public void ShowDialog(IWindowImpl parent) + public void SetParent(IWindowImpl parent) { SetTransientParent((X11Window)parent); - ShowCore(); } + public void SetEnabled(bool enable) + { + _disabled = !enable; + } + + public Action GotInputWhenDisabled { get; set; } + public void SetIcon(IWindowIconImpl icon) { if (icon != null) From cfdd21e43285d684b359a694971bac484bd662fd Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 14 May 2020 11:37:24 -0300 Subject: [PATCH 05/25] add stubs for osx implementation. --- src/Avalonia.Native/WindowImpl.cs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/Avalonia.Native/WindowImpl.cs b/src/Avalonia.Native/WindowImpl.cs index 03a7b4fceb..25cccb6140 100644 --- a/src/Avalonia.Native/WindowImpl.cs +++ b/src/Avalonia.Native/WindowImpl.cs @@ -56,11 +56,6 @@ namespace Avalonia.Native public IAvnWindow Native => _native; - public void ShowDialog(IWindowImpl window) - { - _native.ShowDialog(((WindowImpl)window).Native); - } - public void CanResize(bool value) { _native.CanResize = value; @@ -116,5 +111,15 @@ namespace Avalonia.Native public override IPopupImpl CreatePopup() => _opts.OverlayPopups ? null : new PopupImpl(_factory, _opts, _glFeature, this); + + public Action GotInputWhenDisabled { get; set; } + + public void SetParent(IWindowImpl parent) + { + } + + public void SetEnabled(bool enable) + { + } } } From e1c1775e71cb967aeb48488ecb16296b1af83466 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 14 May 2020 11:37:31 -0300 Subject: [PATCH 06/25] stubs --- .../Remote/PreviewerWindowImpl.cs | 9 +++++++++ src/Avalonia.DesignerSupport/Remote/Stubs.cs | 10 ++++++++++ 2 files changed, 19 insertions(+) diff --git a/src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs b/src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs index 7480b3519c..844489ef97 100644 --- a/src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs +++ b/src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs @@ -83,6 +83,7 @@ namespace Avalonia.DesignerSupport.Remote } public IScreenImpl Screen { get; } = new ScreenStub(); + public Action GotInputWhenDisabled { get; set; } public void Activate() { @@ -115,5 +116,13 @@ namespace Avalonia.DesignerSupport.Remote public void SetTopmost(bool value) { } + + public void SetParent(IWindowImpl parent) + { + } + + public void SetEnabled(bool enable) + { + } } } diff --git a/src/Avalonia.DesignerSupport/Remote/Stubs.cs b/src/Avalonia.DesignerSupport/Remote/Stubs.cs index 82950ce53b..484cf3bc97 100644 --- a/src/Avalonia.DesignerSupport/Remote/Stubs.cs +++ b/src/Avalonia.DesignerSupport/Remote/Stubs.cs @@ -130,7 +130,17 @@ namespace Avalonia.DesignerSupport.Remote { } + public void SetParent(IWindowImpl parent) + { + } + + public void SetEnabled(bool enable) + { + } + public IPopupPositioner PopupPositioner { get; } + + public Action GotInputWhenDisabled { get; set; } } class ClipboardStub : IClipboard From 0116f7ad9616dcff55ccdb987c93b9ee62827a0a Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 14 May 2020 11:58:09 -0300 Subject: [PATCH 07/25] remove disabledBy array on win32. --- src/Avalonia.Controls/Window.cs | 20 +++++++++++++++++++- src/Windows/Avalonia.Win32/WindowImpl.cs | 22 +++++----------------- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index 7fa21669f7..ea4cdb395f 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -69,6 +69,9 @@ namespace Avalonia.Controls /// public class Window : WindowBase, IStyleable, IFocusScope, ILayoutRoot { + private List _children = new List(); + private Window _owner; + /// /// Defines the property. /// @@ -366,6 +369,12 @@ namespace Avalonia.Controls { if (close) { + if(_owner != null) + { + _owner._children.Remove(this); + _owner = null; + } + PlatformImpl?.Dispose(); } } @@ -408,6 +417,14 @@ namespace Avalonia.Controls using (BeginAutoSizing()) { Renderer?.Stop(); + + if (_owner != null) + { + _owner._children.Remove(this); + // update enabled state of parent. + _owner = null; + } + PlatformImpl?.Hide(); } @@ -521,7 +538,8 @@ namespace Avalonia.Controls using (BeginAutoSizing()) { PlatformImpl.SetParent(owner.PlatformImpl); - owner.PlatformImpl.SetEnabled(false); + owner._children.Add(this); + owner.PlatformImpl.SetEnabled(false); PlatformImpl?.Show(); Renderer?.Start(); diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index d57884c29e..192fa2ec0e 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -44,8 +44,7 @@ namespace Avalonia.Win32 private readonly ManagedWindowResizeDragHelper _managedDrag; #endif - private const WindowStyles WindowStateMask = (WindowStyles.WS_MAXIMIZE | WindowStyles.WS_MINIMIZE); - private readonly List _disabledBy; + private const WindowStyles WindowStateMask = (WindowStyles.WS_MAXIMIZE | WindowStyles.WS_MINIMIZE); private readonly TouchDevice _touchDevice; private readonly MouseDevice _mouseDevice; private readonly ManagedDeferredRendererLock _rendererLock; @@ -70,7 +69,6 @@ namespace Avalonia.Win32 public WindowImpl() { - _disabledBy = new List(); _touchDevice = new TouchDevice(); _mouseDevice = new WindowsMouseDevice(); @@ -342,13 +340,6 @@ namespace Avalonia.Win32 public void Hide() { - if (_parent != null) - { - _parent._disabledBy.Remove(this); - _parent.UpdateEnabled(); - _parent = null; - } - UnmanagedMethods.ShowWindow(_hwnd, ShowWindowCommand.Hide); } @@ -363,7 +354,7 @@ namespace Avalonia.Win32 public void SetParent(IWindowImpl parent) { _parent = (WindowImpl)parent; - _parent._disabledBy.Add(this); + SetOwnerHandle(_parent._hwnd); } public void SetEnabled(bool enable) => EnableWindow(_hwnd, enable); @@ -665,7 +656,9 @@ namespace Avalonia.Win32 SetWindowPos(_hwnd, WindowPosZOrder.HWND_NOTOPMOST, x, y, cx, cy, SetWindowPosFlags.SWP_SHOWWINDOW); } } - } + } + + private void SetOwnerHandle(IntPtr handle) => SetWindowLongPtr(_hwnd, (int)WindowLongParam.GWL_HWNDPARENT, handle); private WindowStyles GetWindowStateStyles () { @@ -722,11 +715,6 @@ namespace Avalonia.Win32 } } - private void UpdateEnabled() - { - SetEnabled(_disabledBy.Count == 0); - } - private void UpdateWindowProperties(WindowProperties newProperties, bool forceChanges = false) { var oldProperties = _windowProperties; From 5dffe72af887f89526780c956f00f4267eb6a70c Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 14 May 2020 12:14:38 -0300 Subject: [PATCH 08/25] Closing event re-enabled parent. --- src/Avalonia.Controls/Window.cs | 65 ++++++++++++++++--- .../Avalonia.Win32/WindowImpl.WndProc.cs | 6 -- 2 files changed, 56 insertions(+), 15 deletions(-) diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index ea4cdb395f..cd033ac8ec 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -135,7 +135,7 @@ namespace Avalonia.Controls /// public static readonly RoutedEvent WindowClosedEvent = RoutedEvent.Register("WindowClosed", RoutingStrategies.Direct); - + /// /// Routed event that can be used for global tracking of opening windows /// @@ -187,6 +187,7 @@ namespace Avalonia.Controls : base(impl) { impl.Closing = HandleClosing; + impl.GotInputWhenDisabled = OnGotInputWhenDisabled; impl.WindowStateChanged = HandleWindowStateChanged; _maxPlatformClientSize = PlatformImpl?.MaxClientSize ?? default(Size); this.GetObservable(ClientSizeProperty).Skip(1).Subscribe(x => PlatformImpl?.Resize(x)); @@ -306,7 +307,7 @@ namespace Avalonia.Controls PlatformImpl?.Move(value); } } - + /// /// Starts moving a window with left button being held. Should be called from left mouse button press event handler /// @@ -327,7 +328,7 @@ namespace Avalonia.Controls /// /// Fired before a window is closed. /// - public event EventHandler Closing; + public event EventHandler Closing; /// /// Closes the window. @@ -369,9 +370,9 @@ namespace Avalonia.Controls { if (close) { - if(_owner != null) + if (_owner != null) { - _owner._children.Remove(this); + _owner.RemoveChild(this); _owner = null; } @@ -387,6 +388,16 @@ namespace Avalonia.Controls { var args = new CancelEventArgs(); OnClosing(args); + + if(!args.Cancel) + { + if(_owner != null) + { + _owner.RemoveChild(this); + _owner = null; + } + } + return args.Cancel; } @@ -420,8 +431,7 @@ namespace Avalonia.Controls if (_owner != null) { - _owner._children.Remove(this); - // update enabled state of parent. + _owner.RemoveChild(this); _owner = null; } @@ -538,8 +548,8 @@ namespace Avalonia.Controls using (BeginAutoSizing()) { PlatformImpl.SetParent(owner.PlatformImpl); - owner._children.Add(this); - owner.PlatformImpl.SetEnabled(false); + _owner = owner; + _owner.AddChild(this); PlatformImpl?.Show(); Renderer?.Start(); @@ -562,6 +572,37 @@ namespace Avalonia.Controls return result.Task; } + private void UpdateEnabled() + { + PlatformImpl.SetEnabled(_children.Count == 0); + } + + private void AddChild(Window window) + { + _children.Add(window); + UpdateEnabled(); + } + + private void RemoveChild(Window window) + { + _children.Remove(window); + UpdateEnabled(); + } + + private void OnGotInputWhenDisabled() + { + var firstChild = _children.FirstOrDefault(); + + if (firstChild != null) + { + firstChild.OnGotInputWhenDisabled(); + } + else + { + Activate(); + } + } + private void SetWindowStartupLocation(IWindowBaseImpl owner = null) { var scaling = owner?.Scaling ?? PlatformImpl?.Scaling ?? 1; @@ -652,6 +693,12 @@ namespace Avalonia.Controls RaiseEvent(new RoutedEventArgs(WindowClosedEvent)); base.HandleClosed(); + + if (_owner != null) + { + _owner.RemoveChild(this); + _owner = null; + } } /// diff --git a/src/Windows/Avalonia.Win32/WindowImpl.WndProc.cs b/src/Windows/Avalonia.Win32/WindowImpl.WndProc.cs index 3ea8c1e48f..138553b962 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.WndProc.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.WndProc.cs @@ -77,12 +77,6 @@ namespace Avalonia.Win32 s_instances.Remove(this); Closed?.Invoke(); - if (_parent != null) - { - _parent._disabledBy.Remove(this); - _parent.UpdateEnabled(); - } - _mouseDevice.Dispose(); _touchDevice?.Dispose(); //Free other resources From c8e27b597c6f0d781b33380e8c9d20fc0ab17e51 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 14 May 2020 12:17:59 -0300 Subject: [PATCH 09/25] use owner property. --- src/Avalonia.Controls/Window.cs | 35 ++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index cd033ac8ec..9e0dae2e1f 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -69,8 +69,7 @@ namespace Avalonia.Controls /// public class Window : WindowBase, IStyleable, IFocusScope, ILayoutRoot { - private List _children = new List(); - private Window _owner; + private List _children = new List(); /// /// Defines the property. @@ -370,12 +369,13 @@ namespace Avalonia.Controls { if (close) { - if (_owner != null) + if (Owner is Window owner) { - _owner.RemoveChild(this); - _owner = null; + owner.RemoveChild(this); } + Owner = null; + PlatformImpl?.Dispose(); } } @@ -391,11 +391,12 @@ namespace Avalonia.Controls if(!args.Cancel) { - if(_owner != null) + if (Owner is Window owner) { - _owner.RemoveChild(this); - _owner = null; + owner.RemoveChild(this); } + + Owner = null; } return args.Cancel; @@ -429,12 +430,13 @@ namespace Avalonia.Controls { Renderer?.Stop(); - if (_owner != null) + if (Owner is Window owner) { - _owner.RemoveChild(this); - _owner = null; + owner.RemoveChild(this); } + Owner = null; + PlatformImpl?.Hide(); } @@ -548,8 +550,8 @@ namespace Avalonia.Controls using (BeginAutoSizing()) { PlatformImpl.SetParent(owner.PlatformImpl); - _owner = owner; - _owner.AddChild(this); + Owner = owner; + owner.AddChild(this); PlatformImpl?.Show(); Renderer?.Start(); @@ -694,11 +696,12 @@ namespace Avalonia.Controls base.HandleClosed(); - if (_owner != null) + if (Owner is Window owner) { - _owner.RemoveChild(this); - _owner = null; + owner.RemoveChild(this); } + + Owner = null; } /// From 9b2ff91ea66092d9f89ec1550cb1715093da06ed Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 14 May 2020 12:27:20 -0300 Subject: [PATCH 10/25] fix x11 implementation. --- src/Avalonia.X11/X11Window.cs | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/src/Avalonia.X11/X11Window.cs b/src/Avalonia.X11/X11Window.cs index eb1759aadd..97ba99c3dd 100644 --- a/src/Avalonia.X11/X11Window.cs +++ b/src/Avalonia.X11/X11Window.cs @@ -41,8 +41,6 @@ namespace Avalonia.X11 private IntPtr _renderHandle; private bool _mapped; private bool _wasMappedAtLeastOnce = false; - private HashSet _transientChildren = new HashSet(); - private X11Window _transientParent; private double? _scalingOverride; private bool _disabled; @@ -775,26 +773,19 @@ namespace Avalonia.X11 bool ActivateTransientChildIfNeeded() { - if(_disabled) + if (_disabled) { + GotInputWhenDisabled?.Invoke(); return false; } - if (_transientChildren.Count == 0) - return false; - var child = _transientChildren.First(); - if (!child.ActivateTransientChildIfNeeded()) - child.Activate(); return true; } - + void SetTransientParent(X11Window window, bool informServer = true) - { - _transientParent?._transientChildren.Remove(this); - _transientParent = window; - _transientParent?._transientChildren.Add(this); + { if (informServer) - SetTransientForHint(_transientParent?._handle); + SetTransientForHint(window?._handle); } void SetTransientForHint(IntPtr? parent) From 4e0e72abf66d91bf2c4be6353eaeda13f12e4764 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 14 May 2020 12:59:46 -0300 Subject: [PATCH 11/25] remove redundant call --- src/Avalonia.Controls/Window.cs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index 9e0dae2e1f..74b12cc2be 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -389,16 +389,6 @@ namespace Avalonia.Controls var args = new CancelEventArgs(); OnClosing(args); - if(!args.Cancel) - { - if (Owner is Window owner) - { - owner.RemoveChild(this); - } - - Owner = null; - } - return args.Cancel; } From 313a292fc4d37c1f1130a571764c59929766648c Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 14 May 2020 13:36:48 -0300 Subject: [PATCH 12/25] extend api so that when a parent is set you can state if the current window becomes modal. --- src/Avalonia.Controls/Platform/IWindowImpl.cs | 3 ++- src/Avalonia.Controls/Window.cs | 2 +- src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs | 2 +- src/Avalonia.DesignerSupport/Remote/Stubs.cs | 2 +- src/Avalonia.Native/WindowImpl.cs | 2 +- src/Avalonia.X11/X11Window.cs | 2 +- src/Windows/Avalonia.Win32/WindowImpl.cs | 2 +- 7 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/Avalonia.Controls/Platform/IWindowImpl.cs b/src/Avalonia.Controls/Platform/IWindowImpl.cs index cf31d30332..6bd64ad809 100644 --- a/src/Avalonia.Controls/Platform/IWindowImpl.cs +++ b/src/Avalonia.Controls/Platform/IWindowImpl.cs @@ -29,7 +29,8 @@ namespace Avalonia.Platform /// Sets the parent of the window. /// /// The parent . - void SetParent(IWindowImpl parent); + /// If this window is modal or not. + void SetParent(IWindowImpl parent, bool isModal); /// /// Disables the window for example when a modal dialog is open. diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index 74b12cc2be..b45e8cb4c4 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -539,7 +539,7 @@ namespace Avalonia.Controls using (BeginAutoSizing()) { - PlatformImpl.SetParent(owner.PlatformImpl); + PlatformImpl.SetParent(owner.PlatformImpl, true); Owner = owner; owner.AddChild(this); PlatformImpl?.Show(); diff --git a/src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs b/src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs index 844489ef97..b7299fc9e4 100644 --- a/src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs +++ b/src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs @@ -117,7 +117,7 @@ namespace Avalonia.DesignerSupport.Remote { } - public void SetParent(IWindowImpl parent) + public void SetParent(IWindowImpl parent, bool isModal) { } diff --git a/src/Avalonia.DesignerSupport/Remote/Stubs.cs b/src/Avalonia.DesignerSupport/Remote/Stubs.cs index 484cf3bc97..3512320dc0 100644 --- a/src/Avalonia.DesignerSupport/Remote/Stubs.cs +++ b/src/Avalonia.DesignerSupport/Remote/Stubs.cs @@ -130,7 +130,7 @@ namespace Avalonia.DesignerSupport.Remote { } - public void SetParent(IWindowImpl parent) + public void SetParent(IWindowImpl parent, bool isModal) { } diff --git a/src/Avalonia.Native/WindowImpl.cs b/src/Avalonia.Native/WindowImpl.cs index 25cccb6140..bbacff7988 100644 --- a/src/Avalonia.Native/WindowImpl.cs +++ b/src/Avalonia.Native/WindowImpl.cs @@ -114,7 +114,7 @@ namespace Avalonia.Native public Action GotInputWhenDisabled { get; set; } - public void SetParent(IWindowImpl parent) + public void SetParent(IWindowImpl parent, bool isModal) { } diff --git a/src/Avalonia.X11/X11Window.cs b/src/Avalonia.X11/X11Window.cs index 97ba99c3dd..a0da7a282a 100644 --- a/src/Avalonia.X11/X11Window.cs +++ b/src/Avalonia.X11/X11Window.cs @@ -1033,7 +1033,7 @@ namespace Avalonia.X11 ChangeWMAtoms(value, _x11.Atoms._NET_WM_STATE_ABOVE); } - public void SetParent(IWindowImpl parent) + public void SetParent(IWindowImpl parent, bool isModal) { SetTransientParent((X11Window)parent); } diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 192fa2ec0e..8ba3a87b8f 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -351,7 +351,7 @@ namespace Avalonia.Win32 public Action GotInputWhenDisabled { get; set; } - public void SetParent(IWindowImpl parent) + public void SetParent(IWindowImpl parent, bool isModal) { _parent = (WindowImpl)parent; SetOwnerHandle(_parent._hwnd); From 86ac0ff5a5e1687fac162744bbf17b69c62e9826 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 14 May 2020 14:40:52 -0300 Subject: [PATCH 13/25] OSX implement SetParent --- native/Avalonia.Native/inc/avalonia-native.h | 5 +- native/Avalonia.Native/src/OSX/window.h | 3 +- native/Avalonia.Native/src/OSX/window.mm | 78 +++++++++++-------- src/Avalonia.Controls/Platform/IWindowImpl.cs | 3 +- src/Avalonia.Controls/Window.cs | 2 +- .../Remote/PreviewerWindowImpl.cs | 2 +- src/Avalonia.DesignerSupport/Remote/Stubs.cs | 2 +- src/Avalonia.Native/PopupImpl.cs | 5 ++ src/Avalonia.Native/WindowImpl.cs | 9 ++- src/Avalonia.X11/X11Window.cs | 2 +- src/Windows/Avalonia.Win32/WindowImpl.cs | 2 +- 11 files changed, 68 insertions(+), 45 deletions(-) diff --git a/native/Avalonia.Native/inc/avalonia-native.h b/native/Avalonia.Native/inc/avalonia-native.h index c2a9faf70c..7782165263 100644 --- a/native/Avalonia.Native/inc/avalonia-native.h +++ b/native/Avalonia.Native/inc/avalonia-native.h @@ -267,7 +267,8 @@ AVNCOM(IAvnPopup, 03) : virtual IAvnWindowBase AVNCOM(IAvnWindow, 04) : virtual IAvnWindowBase { - virtual HRESULT ShowDialog (IAvnWindow* parent) = 0; + virtual HRESULT SetEnabled (bool enable) = 0; + virtual HRESULT SetParent (IAvnWindow* parent) = 0; virtual HRESULT SetCanResize(bool value) = 0; virtual HRESULT SetDecorations(SystemDecorations value) = 0; virtual HRESULT SetTitle (void* utf8Title) = 0; @@ -309,6 +310,8 @@ AVNCOM(IAvnWindowEvents, 06) : IAvnWindowBaseEvents virtual bool Closing () = 0; virtual void WindowStateChanged (AvnWindowState state) = 0; + + virtual void GotInputWhenDisabled () = 0; }; AVNCOM(IAvnMacOptions, 07) : IUnknown diff --git a/native/Avalonia.Native/src/OSX/window.h b/native/Avalonia.Native/src/OSX/window.h index 163db36800..ca60914526 100644 --- a/native/Avalonia.Native/src/OSX/window.h +++ b/native/Avalonia.Native/src/OSX/window.h @@ -19,8 +19,7 @@ class WindowBaseImpl; -(void) pollModalSession: (NSModalSession _Nonnull) session; -(void) restoreParentWindow; -(bool) shouldTryToHandleEvents; --(bool) isModal; --(void) setModal: (bool) isModal; +-(void) setEnabled: (bool) enable; -(void) showAppMenuOnly; -(void) showWindowMenuWithAppMenu; -(void) applyMenu:(NSMenu* _Nullable)menu; diff --git a/native/Avalonia.Native/src/OSX/window.mm b/native/Avalonia.Native/src/OSX/window.mm index 06b0c50456..e0f37d9055 100644 --- a/native/Avalonia.Native/src/OSX/window.mm +++ b/native/Avalonia.Native/src/OSX/window.mm @@ -29,6 +29,7 @@ public: NSString* _lastTitle; IAvnMenu* _mainMenu; bool _shown; + bool _isChild; WindowBaseImpl(IAvnWindowBaseEvents* events, IAvnGlContext* gl) { @@ -36,6 +37,7 @@ public: _mainMenu = nullptr; BaseEvents = events; _glContext = gl; + _isChild = false; renderTarget = [[IOSurfaceRenderTarget alloc] initWithOpenGlContext: gl]; View = [[AvnView alloc] initWithParent:this]; @@ -497,12 +499,7 @@ private: virtual HRESULT Show () override { @autoreleasepool - { - if([Window parentWindow] != nil) - [[Window parentWindow] removeChildWindow:Window]; - - [Window setModal:FALSE]; - + { WindowBaseImpl::Show(); HideOrShowTrafficLights(); @@ -511,7 +508,16 @@ private: } } - virtual HRESULT ShowDialog (IAvnWindow* parent) override + virtual HRESULT SetEnabled (bool enable) override + { + @autoreleasepool + { + [Window setEnabled:enable]; + return S_OK; + } + } + + virtual HRESULT SetParent (IAvnWindow* parent) override { @autoreleasepool { @@ -522,12 +528,10 @@ private: if(cparent == nullptr) return E_INVALIDARG; - [Window setModal:TRUE]; - + _isChild = true; [cparent->Window addChildWindow:Window ordered:NSWindowAbove]; - WindowBaseImpl::Show(); - HideOrShowTrafficLights(); + UpdateStyle(); return S_OK; } @@ -883,15 +887,15 @@ protected: switch (_decorations) { case SystemDecorationsNone: - s = s | NSWindowStyleMaskFullSizeContentView | NSWindowStyleMaskMiniaturizable; + s = s | NSWindowStyleMaskFullSizeContentView; break; case SystemDecorationsBorderOnly: - s = s | NSWindowStyleMaskTitled | NSWindowStyleMaskFullSizeContentView | NSWindowStyleMaskMiniaturizable; + s = s | NSWindowStyleMaskTitled | NSWindowStyleMaskFullSizeContentView; break; case SystemDecorationsFull: - s = s | NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskBorderless; + s = s | NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskBorderless; if(_canResize) { @@ -900,6 +904,10 @@ protected: break; } + if(!_isChild) + { + s |= NSWindowStyleMaskMiniaturizable; + } return s; } }; @@ -1089,7 +1097,15 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent - (void)mouseEvent:(NSEvent *)event withType:(AvnRawMouseEventType) type { if([self ignoreUserInput]) + { + auto window = dynamic_cast(_parent.getRaw()); + + if(window != nullptr) + { + window->WindowEvents->GotInputWhenDisabled(); + } return; + } [self becomeFirstResponder]; auto localPoint = [self convertPoint:[event locationInWindow] toView:self]; @@ -1234,7 +1250,16 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent - (void) keyboardEvent: (NSEvent *) event withType: (AvnRawKeyEventType)type { if([self ignoreUserInput]) + { + auto window = dynamic_cast(_parent.getRaw()); + + if(window != nullptr) + { + window->WindowEvents->GotInputWhenDisabled(); + } return; + } + auto key = s_KeyMap[[event keyCode]]; auto timestamp = [event timestamp] * 1000; @@ -1416,7 +1441,7 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent ComPtr _parent; bool _canBecomeKeyAndMain; bool _closed; - bool _isModal; + bool _isEnabled; AvnMenu* _menu; double _lastScaling; } @@ -1538,6 +1563,7 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent _parent = parent; [self setDelegate:self]; _closed = false; + _isEnabled = true; _lastScaling = [self backingScaleFactor]; [self setOpaque:NO]; @@ -1604,28 +1630,12 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent -(bool)shouldTryToHandleEvents { - for(NSWindow* uch in [self childWindows]) - { - auto ch = objc_cast(uch); - if(ch == nil) - continue; - - if(![ch isModal]) - continue; - - return FALSE; - } - return TRUE; -} - --(bool) isModal -{ - return _isModal; + return _isEnabled; } --(void) setModal: (bool) isModal +-(void) setEnabled:(bool)enable { - _isModal = isModal; + _isEnabled = enable; } -(void)makeKeyWindow diff --git a/src/Avalonia.Controls/Platform/IWindowImpl.cs b/src/Avalonia.Controls/Platform/IWindowImpl.cs index 6bd64ad809..cf31d30332 100644 --- a/src/Avalonia.Controls/Platform/IWindowImpl.cs +++ b/src/Avalonia.Controls/Platform/IWindowImpl.cs @@ -29,8 +29,7 @@ namespace Avalonia.Platform /// Sets the parent of the window. /// /// The parent . - /// If this window is modal or not. - void SetParent(IWindowImpl parent, bool isModal); + void SetParent(IWindowImpl parent); /// /// Disables the window for example when a modal dialog is open. diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index b45e8cb4c4..74b12cc2be 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -539,7 +539,7 @@ namespace Avalonia.Controls using (BeginAutoSizing()) { - PlatformImpl.SetParent(owner.PlatformImpl, true); + PlatformImpl.SetParent(owner.PlatformImpl); Owner = owner; owner.AddChild(this); PlatformImpl?.Show(); diff --git a/src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs b/src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs index b7299fc9e4..844489ef97 100644 --- a/src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs +++ b/src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs @@ -117,7 +117,7 @@ namespace Avalonia.DesignerSupport.Remote { } - public void SetParent(IWindowImpl parent, bool isModal) + public void SetParent(IWindowImpl parent) { } diff --git a/src/Avalonia.DesignerSupport/Remote/Stubs.cs b/src/Avalonia.DesignerSupport/Remote/Stubs.cs index 3512320dc0..484cf3bc97 100644 --- a/src/Avalonia.DesignerSupport/Remote/Stubs.cs +++ b/src/Avalonia.DesignerSupport/Remote/Stubs.cs @@ -130,7 +130,7 @@ namespace Avalonia.DesignerSupport.Remote { } - public void SetParent(IWindowImpl parent, bool isModal) + public void SetParent(IWindowImpl parent) { } diff --git a/src/Avalonia.Native/PopupImpl.cs b/src/Avalonia.Native/PopupImpl.cs index b7eec51c85..e4ee293757 100644 --- a/src/Avalonia.Native/PopupImpl.cs +++ b/src/Avalonia.Native/PopupImpl.cs @@ -43,6 +43,11 @@ namespace Avalonia.Native _parent = parent; } + public void GotInputWhenDisabled() + { + // NOP on Popup + } + bool IAvnWindowEvents.Closing() { return true; diff --git a/src/Avalonia.Native/WindowImpl.cs b/src/Avalonia.Native/WindowImpl.cs index bbacff7988..2d084bfe24 100644 --- a/src/Avalonia.Native/WindowImpl.cs +++ b/src/Avalonia.Native/WindowImpl.cs @@ -52,6 +52,11 @@ namespace Avalonia.Native { _parent.WindowStateChanged?.Invoke((WindowState)state); } + + void IAvnWindowEvents.GotInputWhenDisabled () + { + _parent.GotInputWhenDisabled?.Invoke(); + } } public IAvnWindow Native => _native; @@ -114,12 +119,14 @@ namespace Avalonia.Native public Action GotInputWhenDisabled { get; set; } - public void SetParent(IWindowImpl parent, bool isModal) + public void SetParent(IWindowImpl parent) { + _native.SetParent(((WindowImpl)parent).Native); } public void SetEnabled(bool enable) { + _native.SetEnabled(enable); } } } diff --git a/src/Avalonia.X11/X11Window.cs b/src/Avalonia.X11/X11Window.cs index a0da7a282a..97ba99c3dd 100644 --- a/src/Avalonia.X11/X11Window.cs +++ b/src/Avalonia.X11/X11Window.cs @@ -1033,7 +1033,7 @@ namespace Avalonia.X11 ChangeWMAtoms(value, _x11.Atoms._NET_WM_STATE_ABOVE); } - public void SetParent(IWindowImpl parent, bool isModal) + public void SetParent(IWindowImpl parent) { SetTransientParent((X11Window)parent); } diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 8ba3a87b8f..192fa2ec0e 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -351,7 +351,7 @@ namespace Avalonia.Win32 public Action GotInputWhenDisabled { get; set; } - public void SetParent(IWindowImpl parent, bool isModal) + public void SetParent(IWindowImpl parent) { _parent = (WindowImpl)parent; SetOwnerHandle(_parent._hwnd); From 0e59c05b550903b6637d7f07e2ba8d225e14f711 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 14 May 2020 15:10:45 -0300 Subject: [PATCH 14/25] implement closing chain logic. --- src/Avalonia.Controls/Window.cs | 54 ++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 11 deletions(-) diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index 74b12cc2be..1159fc4928 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -358,7 +358,7 @@ namespace Avalonia.Controls bool close = true; try - { + { if (!ignoreCancel && HandleClosing()) { close = false; @@ -369,16 +369,27 @@ namespace Avalonia.Controls { if (close) { - if (Owner is Window owner) - { - owner.RemoveChild(this); - } + CloseInternal(); + } + } + } - Owner = null; + private void CloseInternal () + { + foreach(var child in _children) + { + // if we HandleClosing() before then there will be no children. + child.CloseInternal(); + } - PlatformImpl?.Dispose(); - } + if (Owner is Window owner) + { + owner.RemoveChild(this); } + + Owner = null; + + PlatformImpl?.Dispose(); } /// @@ -386,10 +397,31 @@ namespace Avalonia.Controls /// protected virtual bool HandleClosing() { - var args = new CancelEventArgs(); - OnClosing(args); + bool canClose = true; - return args.Cancel; + foreach(var child in _children) + { + if(!child.HandleClosing()) + { + child.CloseInternal(); + } + else + { + canClose = false; + } + } + + if (canClose) + { + var args = new CancelEventArgs(); + OnClosing(args); + + return args.Cancel; + } + else + { + return !canClose; + } } protected virtual void HandleWindowStateChanged(WindowState state) From 97ae32c619c6707e74a55d55c7d64e305b57512a Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 14 May 2020 15:14:18 -0300 Subject: [PATCH 15/25] fix collection modified exception. --- src/Avalonia.Controls/Window.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index 1159fc4928..086615d7d9 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -399,7 +399,7 @@ namespace Avalonia.Controls { bool canClose = true; - foreach(var child in _children) + foreach(var child in _children.ToList()) { if(!child.HandleClosing()) { From cb57a4313b0e294723cbad68a54e6e72058ab841 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 14 May 2020 15:17:25 -0300 Subject: [PATCH 16/25] make owner property readonly. --- src/Avalonia.Controls/WindowBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/WindowBase.cs b/src/Avalonia.Controls/WindowBase.cs index bb63d1b353..afc01db506 100644 --- a/src/Avalonia.Controls/WindowBase.cs +++ b/src/Avalonia.Controls/WindowBase.cs @@ -109,7 +109,7 @@ namespace Avalonia.Controls public WindowBase Owner { get { return _owner; } - set { SetAndRaise(OwnerProperty, ref _owner, value); } + protected set { SetAndRaise(OwnerProperty, ref _owner, value); } } /// From 84fafd654767e5265d45eadc7037c8043751d3a1 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 14 May 2020 21:19:42 -0300 Subject: [PATCH 17/25] remove isChild flag. --- native/Avalonia.Native/src/OSX/window.mm | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/native/Avalonia.Native/src/OSX/window.mm b/native/Avalonia.Native/src/OSX/window.mm index e0f37d9055..daaee62e34 100644 --- a/native/Avalonia.Native/src/OSX/window.mm +++ b/native/Avalonia.Native/src/OSX/window.mm @@ -29,7 +29,6 @@ public: NSString* _lastTitle; IAvnMenu* _mainMenu; bool _shown; - bool _isChild; WindowBaseImpl(IAvnWindowBaseEvents* events, IAvnGlContext* gl) { @@ -37,7 +36,6 @@ public: _mainMenu = nullptr; BaseEvents = events; _glContext = gl; - _isChild = false; renderTarget = [[IOSurfaceRenderTarget alloc] initWithOpenGlContext: gl]; View = [[AvnView alloc] initWithParent:this]; @@ -528,7 +526,6 @@ private: if(cparent == nullptr) return E_INVALIDARG; - _isChild = true; [cparent->Window addChildWindow:Window ordered:NSWindowAbove]; UpdateStyle(); @@ -904,7 +901,7 @@ protected: break; } - if(!_isChild) + if([Window parentWindow] == nullptr) { s |= NSWindowStyleMaskMiniaturizable; } From d5cdb966185c631c390f96824e3cec17202fdad8 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 14 May 2020 21:22:07 -0300 Subject: [PATCH 18/25] remove duplicate code. --- native/Avalonia.Native/src/OSX/window.mm | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/native/Avalonia.Native/src/OSX/window.mm b/native/Avalonia.Native/src/OSX/window.mm index daaee62e34..fed2176580 100644 --- a/native/Avalonia.Native/src/OSX/window.mm +++ b/native/Avalonia.Native/src/OSX/window.mm @@ -1086,8 +1086,19 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent - (bool) ignoreUserInput { auto parentWindow = objc_cast([self window]); + if(parentWindow == nil || ![parentWindow shouldTryToHandleEvents]) + { + auto window = dynamic_cast(_parent.getRaw()); + + if(window != nullptr) + { + window->WindowEvents->GotInputWhenDisabled(); + } + return TRUE; + } + return FALSE; } @@ -1095,12 +1106,6 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent { if([self ignoreUserInput]) { - auto window = dynamic_cast(_parent.getRaw()); - - if(window != nullptr) - { - window->WindowEvents->GotInputWhenDisabled(); - } return; } @@ -1248,12 +1253,6 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent { if([self ignoreUserInput]) { - auto window = dynamic_cast(_parent.getRaw()); - - if(window != nullptr) - { - window->WindowEvents->GotInputWhenDisabled(); - } return; } From 578443d6e00ec0a1cb134ce48cf01ecbe7f96ad0 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 14 May 2020 21:24:30 -0300 Subject: [PATCH 19/25] nits --- src/Avalonia.Controls/Window.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index 086615d7d9..4b6df20363 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -358,7 +358,7 @@ namespace Avalonia.Controls bool close = true; try - { + { if (!ignoreCancel && HandleClosing()) { close = false; @@ -369,7 +369,7 @@ namespace Avalonia.Controls { if (close) { - CloseInternal(); + CloseInternal(); } } } From c928700febf564fcd8408d64dda61f838c4a09c9 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 14 May 2020 21:24:44 -0300 Subject: [PATCH 20/25] make copy of list before enumerating. --- src/Avalonia.Controls/Window.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index 4b6df20363..07e3d78650 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -376,7 +376,7 @@ namespace Avalonia.Controls private void CloseInternal () { - foreach(var child in _children) + foreach(var child in _children.ToList()) { // if we HandleClosing() before then there will be no children. child.CloseInternal(); From 2501698af1b1c5c65467bf1fb704bb5be69144b7 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 14 May 2020 21:31:51 -0300 Subject: [PATCH 21/25] whitespace --- src/Avalonia.Controls/Window.cs | 14 +++++++------- src/Avalonia.Native/WindowImpl.cs | 6 +++--- src/Windows/Avalonia.Win32/WindowImpl.cs | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index 07e3d78650..194ebeb999 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -69,7 +69,7 @@ namespace Avalonia.Controls /// public class Window : WindowBase, IStyleable, IFocusScope, ILayoutRoot { - private List _children = new List(); + private List _children = new List(); /// /// Defines the property. @@ -374,9 +374,9 @@ namespace Avalonia.Controls } } - private void CloseInternal () + private void CloseInternal() { - foreach(var child in _children.ToList()) + foreach (var child in _children.ToList()) { // if we HandleClosing() before then there will be no children. child.CloseInternal(); @@ -399,9 +399,9 @@ namespace Avalonia.Controls { bool canClose = true; - foreach(var child in _children.ToList()) + foreach (var child in _children.ToList()) { - if(!child.HandleClosing()) + if (!child.HandleClosing()) { child.CloseInternal(); } @@ -454,7 +454,7 @@ namespace Avalonia.Controls if (Owner is Window owner) { - owner.RemoveChild(this); + owner.RemoveChild(this); } Owner = null; @@ -720,7 +720,7 @@ namespace Avalonia.Controls if (Owner is Window owner) { - owner.RemoveChild(this); + owner.RemoveChild(this); } Owner = null; diff --git a/src/Avalonia.Native/WindowImpl.cs b/src/Avalonia.Native/WindowImpl.cs index 2d084bfe24..e91445000a 100644 --- a/src/Avalonia.Native/WindowImpl.cs +++ b/src/Avalonia.Native/WindowImpl.cs @@ -40,7 +40,7 @@ namespace Avalonia.Native bool IAvnWindowEvents.Closing() { - if(_parent.Closing != null) + if (_parent.Closing != null) { return _parent.Closing(); } @@ -53,7 +53,7 @@ namespace Avalonia.Native _parent.WindowStateChanged?.Invoke((WindowState)state); } - void IAvnWindowEvents.GotInputWhenDisabled () + void IAvnWindowEvents.GotInputWhenDisabled() { _parent.GotInputWhenDisabled?.Invoke(); } @@ -71,7 +71,7 @@ namespace Avalonia.Native _native.Decorations = (Interop.SystemDecorations)enabled; } - public void SetTitleBarColor (Avalonia.Media.Color color) + public void SetTitleBarColor(Avalonia.Media.Color color) { _native.SetTitleBarColor(new AvnColor { Alpha = color.A, Red = color.R, Green = color.G, Blue = color.B }); } diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 192fa2ec0e..9bf59a563c 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -44,7 +44,7 @@ namespace Avalonia.Win32 private readonly ManagedWindowResizeDragHelper _managedDrag; #endif - private const WindowStyles WindowStateMask = (WindowStyles.WS_MAXIMIZE | WindowStyles.WS_MINIMIZE); + private const WindowStyles WindowStateMask = (WindowStyles.WS_MAXIMIZE | WindowStyles.WS_MINIMIZE); private readonly TouchDevice _touchDevice; private readonly MouseDevice _mouseDevice; private readonly ManagedDeferredRendererLock _rendererLock; @@ -660,7 +660,7 @@ namespace Avalonia.Win32 private void SetOwnerHandle(IntPtr handle) => SetWindowLongPtr(_hwnd, (int)WindowLongParam.GWL_HWNDPARENT, handle); - private WindowStyles GetWindowStateStyles () + private WindowStyles GetWindowStateStyles() { return GetStyle() & WindowStateMask; } From 1474670710eea4b7f394de4c9bdc557bcb879015 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 14 May 2020 21:33:51 -0300 Subject: [PATCH 22/25] remove method. --- src/Windows/Avalonia.Win32/WindowImpl.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 9bf59a563c..cc4c12ec3c 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -354,7 +354,7 @@ namespace Avalonia.Win32 public void SetParent(IWindowImpl parent) { _parent = (WindowImpl)parent; - SetOwnerHandle(_parent._hwnd); + SetWindowLongPtr(_hwnd, (int)WindowLongParam.GWL_HWNDPARENT, _parent._hwnd); } public void SetEnabled(bool enable) => EnableWindow(_hwnd, enable); @@ -656,9 +656,7 @@ namespace Avalonia.Win32 SetWindowPos(_hwnd, WindowPosZOrder.HWND_NOTOPMOST, x, y, cx, cy, SetWindowPosFlags.SWP_SHOWWINDOW); } } - } - - private void SetOwnerHandle(IntPtr handle) => SetWindowLongPtr(_hwnd, (int)WindowLongParam.GWL_HWNDPARENT, handle); + } private WindowStyles GetWindowStateStyles() { From 0f353769ec5b74540819315cac67f039a7b3681c Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Fri, 15 May 2020 21:20:43 +0300 Subject: [PATCH 23/25] X11Window cleanup --- src/Avalonia.X11/X11Window.cs | 27 ++++----------------------- 1 file changed, 4 insertions(+), 23 deletions(-) diff --git a/src/Avalonia.X11/X11Window.cs b/src/Avalonia.X11/X11Window.cs index 97ba99c3dd..cdd7a64d5d 100644 --- a/src/Avalonia.X11/X11Window.cs +++ b/src/Avalonia.X11/X11Window.cs @@ -746,7 +746,6 @@ namespace Avalonia.X11 void Cleanup() { - SetTransientParent(null, false); if (_xic != IntPtr.Zero) { XDestroyIC(_xic); @@ -782,27 +781,15 @@ namespace Avalonia.X11 return true; } - void SetTransientParent(X11Window window, bool informServer = true) - { - if (informServer) - SetTransientForHint(window?._handle); - } - - void SetTransientForHint(IntPtr? parent) + public void SetParent(IWindowImpl parent) { - if (parent == null || parent == IntPtr.Zero) + if (parent == null || parent.Handle == null || parent.Handle.Handle == IntPtr.Zero) XDeleteProperty(_x11.Display, _handle, _x11.Atoms.XA_WM_TRANSIENT_FOR); else - XSetTransientForHint(_x11.Display, _handle, parent.Value); + XSetTransientForHint(_x11.Display, _handle, parent.Handle.Handle); } public void Show() - { - SetTransientParent(null); - ShowCore(); - } - - void ShowCore() { _wasMappedAtLeastOnce = true; XMapWindow(_x11.Display, _handle); @@ -811,7 +798,6 @@ namespace Avalonia.X11 public void Hide() => XUnmapWindow(_x11.Display, _handle); - public Point PointToClient(PixelPoint point) => new Point((point.X - Position.X) / Scaling, (point.Y - Position.Y) / Scaling); public PixelPoint PointToScreen(Point point) => new PixelPoint( @@ -1032,12 +1018,7 @@ namespace Avalonia.X11 { ChangeWMAtoms(value, _x11.Atoms._NET_WM_STATE_ABOVE); } - - public void SetParent(IWindowImpl parent) - { - SetTransientParent((X11Window)parent); - } - + public void SetEnabled(bool enable) { _disabled = !enable; From 8bcafad8a3bd1730afd6e94126a1ca9a07c4172f Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Fri, 15 May 2020 21:49:29 +0300 Subject: [PATCH 24/25] Fixed ActivateTransientChildIfNeeded --- src/Avalonia.X11/X11Window.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.X11/X11Window.cs b/src/Avalonia.X11/X11Window.cs index cdd7a64d5d..643b037b3f 100644 --- a/src/Avalonia.X11/X11Window.cs +++ b/src/Avalonia.X11/X11Window.cs @@ -775,10 +775,10 @@ namespace Avalonia.X11 if (_disabled) { GotInputWhenDisabled?.Invoke(); - return false; + return true; } - return true; + return false; } public void SetParent(IWindowImpl parent) From 2f1974684e82ac6dc1f757c507a4a0e94953dca9 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 15 May 2020 15:58:52 -0300 Subject: [PATCH 25/25] fix unit test. --- tests/Avalonia.Controls.UnitTests/WindowTests.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/Avalonia.Controls.UnitTests/WindowTests.cs b/tests/Avalonia.Controls.UnitTests/WindowTests.cs index e99be9cfd2..80c8a34ffd 100644 --- a/tests/Avalonia.Controls.UnitTests/WindowTests.cs +++ b/tests/Avalonia.Controls.UnitTests/WindowTests.cs @@ -322,10 +322,9 @@ namespace Avalonia.Controls.UnitTests { var window = new Window(); window.WindowStartupLocation = WindowStartupLocation.CenterOwner; - window.Position = new PixelPoint(60, 40); - window.Owner = parentWindow; + window.Position = new PixelPoint(60, 40); - window.Show(); + window.ShowDialog(parentWindow); var expectedPosition = new PixelPoint( (int)(parentWindow.Position.X + parentWindow.ClientSize.Width / 2 - window.ClientSize.Width / 2),