From 671361c80567de107a2069d4ac450d570e662573 Mon Sep 17 00:00:00 2001 From: Dariusz Komosinski Date: Tue, 10 Sep 2019 00:02:05 +0200 Subject: [PATCH 01/13] Remove extra lambda allocations from render loop. --- .../Rendering/DeferredRenderer.cs | 52 +++++++++++-------- src/Avalonia.Visuals/Rendering/RenderLoop.cs | 14 ++++- 2 files changed, 42 insertions(+), 24 deletions(-) diff --git a/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs b/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs index bf1799bbdc..64df472e93 100644 --- a/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs +++ b/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs @@ -246,22 +246,7 @@ namespace Avalonia.Rendering { try { - IDrawingContextImpl GetContext() - { - if (context != null) - return context; - if ((RenderTarget as IRenderTargetWithCorruptionInfo)?.IsCorrupted == true) - { - RenderTarget.Dispose(); - RenderTarget = null; - } - if (RenderTarget == null) - RenderTarget = ((IRenderRoot)_root).CreateRenderTarget(); - return context = RenderTarget.CreateDrawingContext(this); - - } - - var (scene, updated) = UpdateRenderLayersAndConsumeSceneIfNeeded(GetContext); + var (scene, updated) = UpdateRenderLayersAndConsumeSceneIfNeeded(ref context); using (scene) { @@ -271,9 +256,9 @@ namespace Avalonia.Rendering if (DrawDirtyRects) _dirtyRectsDisplay.Tick(); if (overlay) - RenderOverlay(scene.Item, GetContext()); + RenderOverlay(scene.Item, ref context); if (updated || forceComposite || overlay) - RenderComposite(scene.Item, GetContext()); + RenderComposite(scene.Item, ref context); } } } @@ -291,7 +276,7 @@ namespace Avalonia.Rendering } } - private (IRef scene, bool updated) UpdateRenderLayersAndConsumeSceneIfNeeded(Func contextFactory, + private (IRef scene, bool updated) UpdateRenderLayersAndConsumeSceneIfNeeded(ref IDrawingContextImpl context, bool recursiveCall = false) { IRef sceneRef; @@ -304,7 +289,8 @@ namespace Avalonia.Rendering var scene = sceneRef.Item; if (scene.Generation != _lastSceneId) { - var context = contextFactory(); + context = context ?? CreateDrawingContext(); + Layers.Update(scene, context); RenderToLayers(scene); @@ -325,7 +311,7 @@ namespace Avalonia.Rendering if (!recursiveCall && Dispatcher.UIThread.CheckAccess() && NeedsUpdate) { UpdateScene(); - var (rs, _) = UpdateRenderLayersAndConsumeSceneIfNeeded(contextFactory, true); + var (rs, _) = UpdateRenderLayersAndConsumeSceneIfNeeded(ref context, true); return (rs, true); } @@ -432,8 +418,10 @@ namespace Avalonia.Rendering } - private void RenderOverlay(Scene scene, IDrawingContextImpl parentContent) + private void RenderOverlay(Scene scene, ref IDrawingContextImpl parentContent) { + parentContent = parentContent ?? CreateDrawingContext(); + if (DrawDirtyRects) { var overlay = GetOverlay(parentContent, scene.Size, scene.Scaling); @@ -460,8 +448,10 @@ namespace Avalonia.Rendering } } - private void RenderComposite(Scene scene, IDrawingContextImpl context) + private void RenderComposite(Scene scene, ref IDrawingContextImpl context) { + context = context ?? CreateDrawingContext(); + context.Clear(Colors.Transparent); var clientRect = new Rect(scene.Size); @@ -503,6 +493,22 @@ namespace Avalonia.Rendering } } + private IDrawingContextImpl CreateDrawingContext() + { + if ((RenderTarget as IRenderTargetWithCorruptionInfo)?.IsCorrupted == true) + { + RenderTarget.Dispose(); + RenderTarget = null; + } + + if (RenderTarget == null) + { + RenderTarget = ((IRenderRoot)_root).CreateRenderTarget(); + } + + return RenderTarget.CreateDrawingContext(this); + } + private void UpdateScene() { Dispatcher.UIThread.VerifyAccess(); diff --git a/src/Avalonia.Visuals/Rendering/RenderLoop.cs b/src/Avalonia.Visuals/Rendering/RenderLoop.cs index 64a8427290..140688f8bc 100644 --- a/src/Avalonia.Visuals/Rendering/RenderLoop.cs +++ b/src/Avalonia.Visuals/Rendering/RenderLoop.cs @@ -91,7 +91,19 @@ namespace Avalonia.Rendering { try { - if (_items.Any(item => item.NeedsUpdate) && + bool needsUpdate = false; + + foreach (IRenderLoopTask item in _items) + { + if (item.NeedsUpdate) + { + needsUpdate = true; + + break; + } + } + + if (needsUpdate && Interlocked.CompareExchange(ref _inUpdate, 1, 0) == 0) { _dispatcher.Post(() => From c755334ddece0d094435d50e3c8942cf9572190b Mon Sep 17 00:00:00 2001 From: Dariusz Komosinski Date: Tue, 10 Sep 2019 22:12:38 +0200 Subject: [PATCH 02/13] Review feedback. --- .../Rendering/DeferredRenderer.cs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs b/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs index 64df472e93..efcc555159 100644 --- a/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs +++ b/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs @@ -289,7 +289,7 @@ namespace Avalonia.Rendering var scene = sceneRef.Item; if (scene.Generation != _lastSceneId) { - context = context ?? CreateDrawingContext(); + EnsureDrawingContext(ref context); Layers.Update(scene, context); @@ -420,7 +420,7 @@ namespace Avalonia.Rendering private void RenderOverlay(Scene scene, ref IDrawingContextImpl parentContent) { - parentContent = parentContent ?? CreateDrawingContext(); + EnsureDrawingContext(ref parentContent); if (DrawDirtyRects) { @@ -450,7 +450,7 @@ namespace Avalonia.Rendering private void RenderComposite(Scene scene, ref IDrawingContextImpl context) { - context = context ?? CreateDrawingContext(); + EnsureDrawingContext(ref context); context.Clear(Colors.Transparent); @@ -493,8 +493,13 @@ namespace Avalonia.Rendering } } - private IDrawingContextImpl CreateDrawingContext() + private void EnsureDrawingContext(ref IDrawingContextImpl context) { + if (context != null) + { + return; + } + if ((RenderTarget as IRenderTargetWithCorruptionInfo)?.IsCorrupted == true) { RenderTarget.Dispose(); @@ -506,7 +511,7 @@ namespace Avalonia.Rendering RenderTarget = ((IRenderRoot)_root).CreateRenderTarget(); } - return RenderTarget.CreateDrawingContext(this); + context = RenderTarget.CreateDrawingContext(this); } private void UpdateScene() From 3902730301a994821223802a05350d231ccc2f97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Pedro?= Date: Fri, 13 Sep 2019 15:14:28 +0100 Subject: [PATCH 03/13] Use Microsoft.NETFramework.ReferenceAssemblies. --- build/NetFX.props | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/build/NetFX.props b/build/NetFX.props index 4d2841714b..ed5cb6dd69 100644 --- a/build/NetFX.props +++ b/build/NetFX.props @@ -1,11 +1,7 @@ - - - /usr/lib/mono/4.6.1-api - /Library/Frameworks/Mono.framework/Versions/Current/lib/mono/4.6.1-api - - - /usr/lib/mono/4.7-api/ - /Library/Frameworks/Mono.framework/Versions/Current/lib/mono/4.7-api - + + + + + From 2362b5a847749decf630369b91bf04a8682d75ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dariusz=20Komosi=C5=84ski?= Date: Fri, 13 Sep 2019 17:07:32 +0200 Subject: [PATCH 04/13] Cleanup KeyGesture code. Add constructor taking non-deprecated arguments. --- src/Avalonia.Input/KeyGesture.cs | 131 ++++++++++-------- .../KeyGestureTests.cs | 20 +-- 2 files changed, 81 insertions(+), 70 deletions(-) diff --git a/src/Avalonia.Input/KeyGesture.cs b/src/Avalonia.Input/KeyGesture.cs index 2377edf640..0928b87264 100644 --- a/src/Avalonia.Input/KeyGesture.cs +++ b/src/Avalonia.Input/KeyGesture.cs @@ -1,41 +1,60 @@ +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + using System; using System.Collections.Generic; using System.Linq; namespace Avalonia.Input { + /// + /// Defines a keyboard input combination. + /// public sealed class KeyGesture : IEquatable { + private static readonly Dictionary s_keySynonyms = new Dictionary + { + { "+", Key.OemPlus }, { "-", Key.OemMinus }, { ".", Key.OemPeriod } + }; + public KeyGesture() { - } - public KeyGesture(Key key, InputModifiers modifiers = InputModifiers.None) + [Obsolete("Use constructor taking KeyModifiers")] + public KeyGesture(Key key, InputModifiers modifiers) + { + Key = key; + KeyModifiers = (KeyModifiers)(((int)modifiers) & 0xf); + } + + public KeyGesture(Key key, KeyModifiers modifiers = KeyModifiers.None) { Key = key; - Modifiers = modifiers; + KeyModifiers = modifiers; } - + public bool Equals(KeyGesture other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; - return Key == other.Key && Modifiers == other.Modifiers; + + return Key == other.Key && KeyModifiers == other.KeyModifiers; } public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; - return obj is KeyGesture && Equals((KeyGesture) obj); + + return obj is KeyGesture && Equals((KeyGesture)obj); } public override int GetHashCode() { unchecked { - return ((int) Key*397) ^ (int) Modifiers; + return ((int)Key * 397) ^ (int)KeyModifiers; } } @@ -49,85 +68,85 @@ namespace Avalonia.Input return !Equals(left, right); } - public Key Key { get; set; } + public Key Key { get; } [Obsolete("Use KeyModifiers")] - public InputModifiers Modifiers - { - get => (InputModifiers)KeyModifiers; - set => KeyModifiers = (KeyModifiers)(((int)value) & 0xf); - } - - public KeyModifiers KeyModifiers { get; set; } + public InputModifiers Modifiers => (InputModifiers)KeyModifiers; - - static readonly Dictionary KeySynonyms = new Dictionary - { - {"+", Key.OemPlus }, - {"-", Key.OemMinus}, - {".", Key.OemPeriod } - }; - - //TODO: Move that to external key parser - static Key ParseKey(string key) - { - Key rv; - if (KeySynonyms.TryGetValue(key.ToLower(), out rv)) - return rv; - return (Key)Enum.Parse(typeof (Key), key, true); - } - - static InputModifiers ParseModifier(string modifier) - { - if (modifier.Equals("ctrl", StringComparison.OrdinalIgnoreCase)) - return InputModifiers.Control; - return (InputModifiers) Enum.Parse(typeof (InputModifiers), modifier, true); - } + public KeyModifiers KeyModifiers { get; } public static KeyGesture Parse(string gesture) { - //string.Split can't be used here because "Ctrl++" is a perfectly valid key gesture + // string.Split can't be used here because "Ctrl++" is a perfectly valid key gesture - var parts = new List(); + var key = Key.None; + var keyModifiers = KeyModifiers.None; var cstart = 0; + for (var c = 0; c <= gesture.Length; c++) { var ch = c == gesture.Length ? '\0' : gesture[c]; - if (c == gesture.Length || (ch == '+' && cstart != c)) + bool isLast = c == gesture.Length; + + if (isLast || (ch == '+' && cstart != c)) { - parts.Add(gesture.Substring(cstart, c - cstart)); + var partSpan = gesture.AsSpan(cstart, c - cstart).Trim(); + + if (isLast) + { + key = ParseKey(partSpan.ToString()); + } + else + { + keyModifiers |= ParseModifier(partSpan); + } + cstart = c + 1; } } - for (var c = 0; c < parts.Count; c++) - parts[c] = parts[c].Trim(); - var rv = new KeyGesture(); - for (var c = 0; c < parts.Count; c++) - { - if (c == parts.Count - 1) - rv.Key = ParseKey(parts[c]); - else - rv.Modifiers |= ParseModifier(parts[c]); - } - return rv; + return new KeyGesture(key, keyModifiers); } public override string ToString() { var parts = new List(); - foreach (var flag in Enum.GetValues(typeof (InputModifiers)).Cast()) + + foreach (var flag in Enum.GetValues(typeof(KeyModifiers)).Cast()) { - if (Modifiers.HasFlag(flag) && flag != InputModifiers.None) + if (KeyModifiers.HasFlag(flag) && flag != KeyModifiers.None) + { parts.Add(flag.ToString()); + } } + parts.Add(Key.ToString()); + return string.Join(" + ", parts); } - public bool Matches(KeyEventArgs keyEvent) => ResolveNumPadOperationKey(keyEvent.Key) == Key && keyEvent.Modifiers == Modifiers; + public bool Matches(KeyEventArgs keyEvent) => ResolveNumPadOperationKey(keyEvent.Key) == Key && keyEvent.KeyModifiers == KeyModifiers; + + // TODO: Move that to external key parser + private static Key ParseKey(string key) + { + if (s_keySynonyms.TryGetValue(key.ToLower(), out Key rv)) + return rv; + + return (Key)Enum.Parse(typeof(Key), key, true); + } + + private static KeyModifiers ParseModifier(ReadOnlySpan modifier) + { + if (modifier.Equals("ctrl".AsSpan(), StringComparison.OrdinalIgnoreCase)) + { + return KeyModifiers.Control; + } + + return (KeyModifiers)Enum.Parse(typeof(KeyModifiers), modifier.ToString(), true); + } private Key ResolveNumPadOperationKey(Key key) { diff --git a/tests/Avalonia.Input.UnitTests/KeyGestureTests.cs b/tests/Avalonia.Input.UnitTests/KeyGestureTests.cs index 006ed1140e..95eaab30de 100644 --- a/tests/Avalonia.Input.UnitTests/KeyGestureTests.cs +++ b/tests/Avalonia.Input.UnitTests/KeyGestureTests.cs @@ -1,8 +1,4 @@ -using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using Xunit; namespace Avalonia.Input.UnitTests @@ -11,13 +7,11 @@ namespace Avalonia.Input.UnitTests { public static readonly IEnumerable SampleData = new object[][] { - new object[]{"Ctrl+A", new KeyGesture {Key = Key.A, Modifiers = InputModifiers.Control}}, - new object[]{" \tShift\t+Alt +B", new KeyGesture {Key = Key.B, Modifiers = InputModifiers.Shift|InputModifiers.Alt} }, - new object[]{"Control++", new KeyGesture {Key = Key.OemPlus, Modifiers = InputModifiers.Control} } + new object[]{"Ctrl+A", new KeyGesture(Key.A, InputModifiers.Control)}, + new object[]{" \tShift\t+Alt +B", new KeyGesture(Key.B, InputModifiers.Shift | InputModifiers.Alt) }, + new object[]{"Control++", new KeyGesture(Key.OemPlus, InputModifiers.Control) } }; - - - + [Theory] [MemberData(nameof(SampleData))] public void Key_Gesture_Is_Able_To_Parse_Sample_Data(string text, KeyGesture gesture) @@ -31,10 +25,8 @@ namespace Avalonia.Input.UnitTests [InlineData(Key.OemPeriod, Key.Decimal)] public void Key_Gesture_Matches_NumPad_To_Regular_Digit(Key gestureKey, Key pressedKey) { - var keyGesture = new KeyGesture - { - Key = gestureKey - }; + var keyGesture = new KeyGesture(gestureKey); + Assert.True(keyGesture.Matches(new KeyEventArgs { Key = pressedKey From d409090b90af0021e7183a661a433fe4a7d715b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dariusz=20Komosi=C5=84ski?= Date: Fri, 13 Sep 2019 17:10:56 +0200 Subject: [PATCH 05/13] Fix unit tests. Remove default ctor. --- src/Avalonia.Input/KeyGesture.cs | 4 ---- tests/Avalonia.Controls.UnitTests/Utils/HotKeyManagerTests.cs | 4 ++-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/Avalonia.Input/KeyGesture.cs b/src/Avalonia.Input/KeyGesture.cs index 0928b87264..5eaee4833c 100644 --- a/src/Avalonia.Input/KeyGesture.cs +++ b/src/Avalonia.Input/KeyGesture.cs @@ -17,10 +17,6 @@ namespace Avalonia.Input { "+", Key.OemPlus }, { "-", Key.OemMinus }, { ".", Key.OemPeriod } }; - public KeyGesture() - { - } - [Obsolete("Use constructor taking KeyModifiers")] public KeyGesture(Key key, InputModifiers modifiers) { diff --git a/tests/Avalonia.Controls.UnitTests/Utils/HotKeyManagerTests.cs b/tests/Avalonia.Controls.UnitTests/Utils/HotKeyManagerTests.cs index df522397ee..dd3b113d5d 100644 --- a/tests/Avalonia.Controls.UnitTests/Utils/HotKeyManagerTests.cs +++ b/tests/Avalonia.Controls.UnitTests/Utils/HotKeyManagerTests.cs @@ -24,8 +24,8 @@ namespace Avalonia.Controls.UnitTests.Utils .Bind().ToConstant(new WindowingPlatformMock()) .Bind().ToConstant(styler.Object); - var gesture1 = new KeyGesture {Key = Key.A, Modifiers = InputModifiers.Control}; - var gesture2 = new KeyGesture {Key = Key.B, Modifiers = InputModifiers.Control}; + var gesture1 = new KeyGesture(Key.A, InputModifiers.Control); + var gesture2 = new KeyGesture(Key.B, InputModifiers.Control); var tl = new Window(); var button = new Button(); From 9de04b3297b326f62eb086e86d492acd2d9e3dac Mon Sep 17 00:00:00 2001 From: Jumar Macato Date: Sat, 14 Sep 2019 19:23:33 +0800 Subject: [PATCH 06/13] Fix drive enumeration crash on Windows's Managed File Dialog. --- src/Windows/Avalonia.Win32/WindowsMountedVolumeInfoListener.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Windows/Avalonia.Win32/WindowsMountedVolumeInfoListener.cs b/src/Windows/Avalonia.Win32/WindowsMountedVolumeInfoListener.cs index a17e6b8b51..6fc4851dc9 100644 --- a/src/Windows/Avalonia.Win32/WindowsMountedVolumeInfoListener.cs +++ b/src/Windows/Avalonia.Win32/WindowsMountedVolumeInfoListener.cs @@ -32,6 +32,7 @@ namespace Avalonia.Win32 var allDrives = DriveInfo.GetDrives(); var mountVolInfos = allDrives + .Where(p => p.IsReady) .Select(p => new MountedVolumeInfo() { VolumeLabel = p.VolumeLabel, From f4100fd8a4ff743d6ce60d93cb47949c69d8ccf8 Mon Sep 17 00:00:00 2001 From: Jumar Macato Date: Sat, 14 Sep 2019 19:37:19 +0800 Subject: [PATCH 07/13] Set Path as name if there's no volume label. --- src/Windows/Avalonia.Win32/WindowsMountedVolumeInfoListener.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Windows/Avalonia.Win32/WindowsMountedVolumeInfoListener.cs b/src/Windows/Avalonia.Win32/WindowsMountedVolumeInfoListener.cs index 6fc4851dc9..c1c17c6507 100644 --- a/src/Windows/Avalonia.Win32/WindowsMountedVolumeInfoListener.cs +++ b/src/Windows/Avalonia.Win32/WindowsMountedVolumeInfoListener.cs @@ -35,7 +35,8 @@ namespace Avalonia.Win32 .Where(p => p.IsReady) .Select(p => new MountedVolumeInfo() { - VolumeLabel = p.VolumeLabel, + VolumeLabel = string.IsNullOrEmpty(p.VolumeLabel.Trim()) ? p.RootDirectory.FullName + : p.VolumeLabel, VolumePath = p.RootDirectory.FullName, VolumeSizeBytes = (ulong)p.TotalSize }) From 2afa74e62862f7b53b58160b0c1ac1580107ff61 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Sat, 14 Sep 2019 19:05:20 +0100 Subject: [PATCH 08/13] include drive letter on windows. --- src/Windows/Avalonia.Win32/WindowsMountedVolumeInfoListener.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Windows/Avalonia.Win32/WindowsMountedVolumeInfoListener.cs b/src/Windows/Avalonia.Win32/WindowsMountedVolumeInfoListener.cs index c1c17c6507..db4c916052 100644 --- a/src/Windows/Avalonia.Win32/WindowsMountedVolumeInfoListener.cs +++ b/src/Windows/Avalonia.Win32/WindowsMountedVolumeInfoListener.cs @@ -36,7 +36,7 @@ namespace Avalonia.Win32 .Select(p => new MountedVolumeInfo() { VolumeLabel = string.IsNullOrEmpty(p.VolumeLabel.Trim()) ? p.RootDirectory.FullName - : p.VolumeLabel, + : $"{p.VolumeLabel} ({p.Name})", VolumePath = p.RootDirectory.FullName, VolumeSizeBytes = (ulong)p.TotalSize }) From 06a4a1af5ba992355441c4440af75b3e30b72160 Mon Sep 17 00:00:00 2001 From: Dariusz Komosinski Date: Sun, 15 Sep 2019 01:29:17 +0200 Subject: [PATCH 09/13] Add failing unit test. --- .../WeakEventHandlerManagerTests.cs | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/tests/Avalonia.Base.UnitTests/WeakEventHandlerManagerTests.cs b/tests/Avalonia.Base.UnitTests/WeakEventHandlerManagerTests.cs index 9ed6590821..81b882308d 100644 --- a/tests/Avalonia.Base.UnitTests/WeakEventHandlerManagerTests.cs +++ b/tests/Avalonia.Base.UnitTests/WeakEventHandlerManagerTests.cs @@ -36,7 +36,7 @@ namespace Avalonia.Base.UnitTests } [Fact] - public void EventShoudBePassedToSubscriber() + public void EventShouldBePassedToSubscriber() { bool handled = false; var subscriber = new Subscriber(() => handled = true); @@ -47,7 +47,23 @@ namespace Avalonia.Base.UnitTests Assert.True(handled); } - + [Fact] + public void EventShouldNotBeRaisedAfterUnsubscribe() + { + bool handled = false; + var subscriber = new Subscriber(() => handled = true); + var source = new EventSource(); + WeakEventHandlerManager.Subscribe(source, "Event", + subscriber.OnEvent); + + WeakEventHandlerManager.Unsubscribe(source, "Event", + subscriber.OnEvent); + + source.Fire(); + + Assert.False(handled); + } + [Fact] public void EventHandlerShouldNotBeKeptAlive() { From 3030427c07d3d38c869a42aab0ad44e64b7dcc18 Mon Sep 17 00:00:00 2001 From: Dariusz Komosinski Date: Sun, 15 Sep 2019 01:33:32 +0200 Subject: [PATCH 10/13] Fix unsubscribe not doing anything due to wrong check. --- src/Avalonia.Base/Utilities/WeakEventHandlerManager.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Avalonia.Base/Utilities/WeakEventHandlerManager.cs b/src/Avalonia.Base/Utilities/WeakEventHandlerManager.cs index b59ed166bc..607e2a147b 100644 --- a/src/Avalonia.Base/Utilities/WeakEventHandlerManager.cs +++ b/src/Avalonia.Base/Utilities/WeakEventHandlerManager.cs @@ -161,9 +161,8 @@ namespace Avalonia.Utilities for (int c = 0; c < _count; ++c) { var reference = _data[c].Subscriber; - TSubscriber instance; - if (reference != null && reference.TryGetTarget(out instance) && instance == s) + if (reference != null && reference.TryGetTarget(out TSubscriber instance) && instance == (TSubscriber)s.Target) { _data[c] = default; removed = true; From 213600f6c23b247d561727963face70b23d7fec3 Mon Sep 17 00:00:00 2001 From: Dariusz Komosinski Date: Sun, 15 Sep 2019 01:47:04 +0200 Subject: [PATCH 11/13] Use Equals. --- src/Avalonia.Base/Utilities/WeakEventHandlerManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Base/Utilities/WeakEventHandlerManager.cs b/src/Avalonia.Base/Utilities/WeakEventHandlerManager.cs index 607e2a147b..f4cec98628 100644 --- a/src/Avalonia.Base/Utilities/WeakEventHandlerManager.cs +++ b/src/Avalonia.Base/Utilities/WeakEventHandlerManager.cs @@ -162,7 +162,7 @@ namespace Avalonia.Utilities { var reference = _data[c].Subscriber; - if (reference != null && reference.TryGetTarget(out TSubscriber instance) && instance == (TSubscriber)s.Target) + if (reference != null && reference.TryGetTarget(out TSubscriber instance) && Equals(instance, s.Target)) { _data[c] = default; removed = true; From 16a8ff862b32dbdb3113dcd5f84bc21aaf13ee59 Mon Sep 17 00:00:00 2001 From: Yatao Li Date: Mon, 16 Sep 2019 00:49:27 +0800 Subject: [PATCH 12/13] X11: map super to win key --- src/Avalonia.X11/X11KeyTransform.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.X11/X11KeyTransform.cs b/src/Avalonia.X11/X11KeyTransform.cs index 87a4174c06..59f1da564c 100644 --- a/src/Avalonia.X11/X11KeyTransform.cs +++ b/src/Avalonia.X11/X11KeyTransform.cs @@ -104,8 +104,8 @@ namespace Avalonia.X11 {X11Key.x, Key.X}, {X11Key.y, Key.Y}, {X11Key.z, Key.Z}, - {X11Key.Meta_L, Key.LWin }, - {X11Key.Meta_R, Key.RWin }, + {X11Key.Super_L, Key.LWin }, + {X11Key.Super_R, Key.RWin }, {X11Key.Menu, Key.Apps}, //{ X11Key.?, Key.Sleep } {X11Key.KP_0, Key.NumPad0}, From c1c7f57ee6c13971216ac5b9f49ce42ca43abbcb Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 16 Sep 2019 10:04:37 +0200 Subject: [PATCH 13/13] Disable vertical scrollbar in ItemsRepeater page. --- samples/ControlCatalog/MainView.xaml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/samples/ControlCatalog/MainView.xaml b/samples/ControlCatalog/MainView.xaml index c35f8a3c0c..c99a6b117b 100644 --- a/samples/ControlCatalog/MainView.xaml +++ b/samples/ControlCatalog/MainView.xaml @@ -24,7 +24,6 @@ - @@ -34,12 +33,15 @@ - + + + - + @@ -50,12 +52,12 @@ - + Light Dark - +