From 965057a7e2af47c0df73f1feb5b71db21ebda923 Mon Sep 17 00:00:00 2001 From: artyom Date: Sat, 13 Oct 2018 20:04:15 +0300 Subject: [PATCH 1/5] Fix WhenActivated ignoring WindowBase --- .../AvaloniaActivationForViewFetcher.cs | 34 +++++++++++++++--- .../AvaloniaActivationForViewFetcherTest.cs | 35 +++++++++++++++++++ 2 files changed, 64 insertions(+), 5 deletions(-) diff --git a/src/Avalonia.ReactiveUI/AvaloniaActivationForViewFetcher.cs b/src/Avalonia.ReactiveUI/AvaloniaActivationForViewFetcher.cs index 828d8024e6..cf386a235e 100644 --- a/src/Avalonia.ReactiveUI/AvaloniaActivationForViewFetcher.cs +++ b/src/Avalonia.ReactiveUI/AvaloniaActivationForViewFetcher.cs @@ -6,6 +6,7 @@ using System.Reflection; using System.Reactive.Linq; using Avalonia; using Avalonia.VisualTree; +using Avalonia.Controls; using ReactiveUI; namespace Avalonia @@ -20,18 +21,41 @@ namespace Avalonia public IObservable GetActivationForView(IActivatable view) { if (!(view is IVisual visual)) return Observable.Return(false); - var viewLoaded = Observable + if (view is WindowBase window) return GetActivationForWindowBase(window); + return GetActivationForVisual(visual); + } + + private IObservable GetActivationForWindowBase(WindowBase window) + { + var windowLoaded = Observable + .FromEventPattern( + x => window.Initialized += x, + x => window.Initialized -= x) + .Select(args => true); + var windowUnloaded = Observable + .FromEventPattern( + x => window.Closed += x, + x => window.Closed -= x) + .Select(args => false); + return windowLoaded + .Merge(windowUnloaded) + .DistinctUntilChanged(); + } + + private IObservable GetActivationForVisual(IVisual visual) + { + var visualLoaded = Observable .FromEventPattern( x => visual.AttachedToVisualTree += x, - x => visual.DetachedFromVisualTree -= x) + x => visual.AttachedToVisualTree -= x) .Select(args => true); - var viewUnloaded = Observable + var visualUnloaded = Observable .FromEventPattern( x => visual.DetachedFromVisualTree += x, x => visual.DetachedFromVisualTree -= x) .Select(args => false); - return viewLoaded - .Merge(viewUnloaded) + return visualLoaded + .Merge(visualUnloaded) .DistinctUntilChanged(); } } diff --git a/tests/Avalonia.ReactiveUI.UnitTests/AvaloniaActivationForViewFetcherTest.cs b/tests/Avalonia.ReactiveUI.UnitTests/AvaloniaActivationForViewFetcherTest.cs index 97701f8437..bda55276a8 100644 --- a/tests/Avalonia.ReactiveUI.UnitTests/AvaloniaActivationForViewFetcherTest.cs +++ b/tests/Avalonia.ReactiveUI.UnitTests/AvaloniaActivationForViewFetcherTest.cs @@ -32,6 +32,21 @@ namespace Avalonia } } + public class TestWindowWithWhenActivated : Window, IActivatable + { + public bool Active { get; private set; } + + public TestWindowWithWhenActivated() + { + this.WhenActivated(disposables => { + Active = true; + Disposable + .Create(() => Active = false) + .DisposeWith(disposables); + }); + } + } + [Fact] public void Visual_Element_Is_Activated_And_Deactivated() { @@ -85,5 +100,25 @@ namespace Avalonia fakeRenderedDecorator.Child = null; Assert.False(userControl.Active); } + + [Fact] + public void Activation_For_View_Fetcher_Should_Support_Windows() + { + Locator.CurrentMutable.RegisterConstant( + new AvaloniaActivationForViewFetcher(), + typeof(IActivationForViewFetcher)); + + using (var application = UnitTestApplication.Start(TestServices.MockWindowingPlatform)) + { + var window = new TestWindowWithWhenActivated(); + Assert.False(window.Active); + + window.Show(); + Assert.True(window.Active); + + window.Close(); + Assert.False(window.Active); + } + } } } \ No newline at end of file From e2f09b5324a0f38ced9b3af4823b2cb4083a5d51 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Thu, 18 Oct 2018 19:19:48 +0200 Subject: [PATCH 2/5] Added failing test for #1765. --- .../ApplicationTests.cs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/tests/Avalonia.Controls.UnitTests/ApplicationTests.cs b/tests/Avalonia.Controls.UnitTests/ApplicationTests.cs index 694a6d2278..df14c808db 100644 --- a/tests/Avalonia.Controls.UnitTests/ApplicationTests.cs +++ b/tests/Avalonia.Controls.UnitTests/ApplicationTests.cs @@ -113,5 +113,21 @@ namespace Avalonia.Controls.UnitTests Assert.Throws(() => { Application.Current.Run(null); }); } } + + [Fact] + public void Raises_ResourcesChanged_When_Event_Handler_Added_After_Resources_Has_Been_Accessed() + { + // Test for #1765. + using (UnitTestApplication.Start()) + { + var resources = Application.Current.Resources; + var raised = false; + + Application.Current.ResourcesChanged += (s, e) => raised = true; + resources["foo"] = "bar"; + + Assert.True(raised); + } + } } -} \ No newline at end of file +} From 5ac1430a065a4110df5b7827d627894fe5cb534b Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Thu, 18 Oct 2018 19:21:31 +0200 Subject: [PATCH 3/5] Make sure Application.ResourcesChanged is raised. Previously if `Application.ResourcesChanged` was null when `Resources` was created, adding the handler via `_resources.ResourcesChanged += ResourcesChanged` did nothing because `ResourcesChanged` was null. --- src/Avalonia.Controls/Application.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Controls/Application.cs b/src/Avalonia.Controls/Application.cs index 37796ff9ba..1d4e4cbeaa 100644 --- a/src/Avalonia.Controls/Application.cs +++ b/src/Avalonia.Controls/Application.cs @@ -122,11 +122,11 @@ namespace Avalonia if (_resources != null) { hadResources = _resources.Count > 0; - _resources.ResourcesChanged -= ResourcesChanged; + _resources.ResourcesChanged -= ThisResourcesChanged; } _resources = value; - _resources.ResourcesChanged += ResourcesChanged; + _resources.ResourcesChanged += ThisResourcesChanged; if (hadResources || _resources.Count > 0) { @@ -343,5 +343,10 @@ namespace Avalonia .Bind().ToConstant(clock) .GetService()?.Add(clock); } + + private void ThisResourcesChanged(object sender, ResourcesChangedEventArgs e) + { + ResourcesChanged?.Invoke(this, e); + } } } From d41f681884b5c139b662dbaa517345d8f1e17984 Mon Sep 17 00:00:00 2001 From: Tom Daffin Date: Fri, 19 Oct 2018 05:39:46 -0600 Subject: [PATCH 4/5] Map gdk keys for left and right ctrl, shift and alt --- src/Gtk/Avalonia.Gtk3/KeyTransform.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Gtk/Avalonia.Gtk3/KeyTransform.cs b/src/Gtk/Avalonia.Gtk3/KeyTransform.cs index 29ee6aaeb5..48bcb93e48 100644 --- a/src/Gtk/Avalonia.Gtk3/KeyTransform.cs +++ b/src/Gtk/Avalonia.Gtk3/KeyTransform.cs @@ -156,12 +156,12 @@ namespace Avalonia.Gtk.Common { GdkKey.R4, Key.F24 }, { GdkKey.Num_Lock, Key.NumLock }, { GdkKey.Scroll_Lock, Key.Scroll }, - //{ GdkKey.?, Key.LeftShift } - //{ GdkKey.?, Key.RightShift } - //{ GdkKey.?, Key.LeftCtrl } - //{ GdkKey.?, Key.RightCtrl } - //{ GdkKey.?, Key.LeftAlt } - //{ GdkKey.?, Key.RightAlt } + { GdkKey.Shift_L, Key.LeftShift }, + { GdkKey.Shift_R, Key.RightShift }, + { GdkKey.Control_L, Key.LeftCtrl }, + { GdkKey.Control_R, Key.RightCtrl }, + { GdkKey.Alt_L, Key.LeftAlt }, + { GdkKey.Alt_R, Key.RightAlt }, //{ GdkKey.?, Key.BrowserBack } //{ GdkKey.?, Key.BrowserForward } //{ GdkKey.?, Key.BrowserRefresh } From fb62c3b0eff02e144fae4dded8f319b10835bf21 Mon Sep 17 00:00:00 2001 From: Tom Daffin Date: Sat, 20 Oct 2018 07:02:29 -0600 Subject: [PATCH 5/5] Map Gdk keys for numpad 0-9, caps lock and page down --- src/Gtk/Avalonia.Gtk3/KeyTransform.cs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Gtk/Avalonia.Gtk3/KeyTransform.cs b/src/Gtk/Avalonia.Gtk3/KeyTransform.cs index 48bcb93e48..ae85d618d1 100644 --- a/src/Gtk/Avalonia.Gtk3/KeyTransform.cs +++ b/src/Gtk/Avalonia.Gtk3/KeyTransform.cs @@ -15,7 +15,7 @@ namespace Avalonia.Gtk.Common { GdkKey.Clear, Key.Clear }, { GdkKey.Return, Key.Return }, { GdkKey.Pause, Key.Pause }, - //{ GdkKey.?, Key.CapsLock } + { GdkKey.Caps_Lock, Key.CapsLock }, //{ GdkKey.?, Key.HangulMode } //{ GdkKey.?, Key.JunjaMode } //{ GdkKey.?, Key.FinalMode } @@ -27,7 +27,7 @@ namespace Avalonia.Gtk.Common //{ GdkKey.?, Key.ImeModeChange } { GdkKey.space, Key.Space }, { GdkKey.Prior, Key.Prior }, - //{ GdkKey.?, Key.PageDown } + { GdkKey.Page_Down, Key.PageDown }, { GdkKey.End, Key.End }, { GdkKey.KP_End, Key.End }, { GdkKey.Home, Key.Home }, @@ -114,16 +114,16 @@ namespace Avalonia.Gtk.Common //{ GdkKey.?, Key.RWin } //{ GdkKey.?, Key.Apps } //{ GdkKey.?, Key.Sleep } - //{ GdkKey.?, Key.NumPad0 } - //{ GdkKey.?, Key.NumPad1 } - //{ GdkKey.?, Key.NumPad2 } - //{ GdkKey.?, Key.NumPad3 } - //{ GdkKey.?, Key.NumPad4 } - //{ GdkKey.?, Key.NumPad5 } - //{ GdkKey.?, Key.NumPad6 } - //{ GdkKey.?, Key.NumPad7 } - //{ GdkKey.?, Key.NumPad8 } - //{ GdkKey.?, Key.NumPad9 } + { GdkKey.KP_0, Key.NumPad0 }, + { GdkKey.KP_1, Key.NumPad1 }, + { GdkKey.KP_2, Key.NumPad2 }, + { GdkKey.KP_3, Key.NumPad3 }, + { GdkKey.KP_4, Key.NumPad4 }, + { GdkKey.KP_5, Key.NumPad5 }, + { GdkKey.KP_6, Key.NumPad6 }, + { GdkKey.KP_7, Key.NumPad7 }, + { GdkKey.KP_8, Key.NumPad8 }, + { GdkKey.KP_9, Key.NumPad9 }, { GdkKey.multiply, Key.Multiply }, //{ GdkKey.?, Key.Add } //{ GdkKey.?, Key.Separator }