From 1eee17345bf2958f0179794a4b21fb9d15469196 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Pedro?= Date: Thu, 6 Jul 2017 17:45:21 +0100 Subject: [PATCH 01/25] Implemented Window.WindowStartupLocation and WindowBase.Owner. --- src/Avalonia.Controls/Window.cs | 28 +++++++ src/Avalonia.Controls/WindowBase.cs | 15 ++++ .../WindowStartupLocation.cs | 23 ++++++ src/Avalonia.DotNetCoreRuntime/AppBuilder.cs | 3 + .../WindowTests.cs | 77 ++++++++++++++++++- 5 files changed, 143 insertions(+), 3 deletions(-) create mode 100644 src/Avalonia.Controls/WindowStartupLocation.cs diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index 3802f2b6ea..3535510ce3 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -183,6 +183,15 @@ namespace Avalonia.Controls set { SetValue(IconProperty, value); } } + /// + /// Gets or sets the startup location of the window. + /// + public WindowStartupLocation WindowStartupLocation + { + get; + set; + } + /// Size ILayoutRoot.MaxClientSize => _maxPlatformClientSize; @@ -246,6 +255,7 @@ namespace Avalonia.Controls s_windows.Add(this); EnsureInitialized(); + SetWindowStartupLocation(); IsVisible = true; LayoutManager.Instance.ExecuteInitialLayoutPass(this); @@ -285,6 +295,7 @@ namespace Avalonia.Controls s_windows.Add(this); EnsureInitialized(); + SetWindowStartupLocation(); IsVisible = true; LayoutManager.Instance.ExecuteInitialLayoutPass(this); @@ -321,6 +332,23 @@ namespace Avalonia.Controls } } + void SetWindowStartupLocation() + { + if (WindowStartupLocation == WindowStartupLocation.CenterScreen) + { + var positionAsSize = PlatformImpl.MaxClientSize / 2 - ClientSize / 2; + Position = new Point(positionAsSize.Width, positionAsSize.Height); + } + else if (WindowStartupLocation == WindowStartupLocation.CenterOwner) + { + if (Owner != null) + { + var positionAsSize = Owner.ClientSize / 2 - ClientSize / 2; + Position = Owner.Position + new Point(positionAsSize.Width, positionAsSize.Height); + } + } + } + /// void INameScope.Register(string name, object element) { diff --git a/src/Avalonia.Controls/WindowBase.cs b/src/Avalonia.Controls/WindowBase.cs index fbdf64b14a..dd1e8fbef1 100644 --- a/src/Avalonia.Controls/WindowBase.cs +++ b/src/Avalonia.Controls/WindowBase.cs @@ -29,6 +29,12 @@ namespace Avalonia.Controls public static readonly DirectProperty IsActiveProperty = AvaloniaProperty.RegisterDirect(nameof(IsActive), o => o.IsActive); + /// + /// Defines the property. + /// + public static readonly StyledProperty OwnerProperty = + AvaloniaProperty.Register(nameof(Owner)); + private bool _hasExecutedInitialLayoutPass; private bool _isActive; private bool _ignoreVisibilityChange; @@ -100,6 +106,15 @@ namespace Avalonia.Controls private set; } + /// + /// Gets or sets the owner of the window. + /// + public WindowBase Owner + { + get { return GetValue(OwnerProperty); } + set { SetValue(OwnerProperty, value); } + } + /// /// Activates the window. /// diff --git a/src/Avalonia.Controls/WindowStartupLocation.cs b/src/Avalonia.Controls/WindowStartupLocation.cs new file mode 100644 index 0000000000..1818636076 --- /dev/null +++ b/src/Avalonia.Controls/WindowStartupLocation.cs @@ -0,0 +1,23 @@ +namespace Avalonia.Controls +{ + /// + /// Determines the startup location of the window. + /// + public enum WindowStartupLocation + { + /// + /// The startup location is defined by the Position property. + /// + Manual, + + /// + /// The startup location is the center of the screen. + /// + CenterScreen, + + /// + /// The startup location is the center of the owner window. If the owner window is not specified, the startup location will be . + /// + CenterOwner + } +} diff --git a/src/Avalonia.DotNetCoreRuntime/AppBuilder.cs b/src/Avalonia.DotNetCoreRuntime/AppBuilder.cs index 2b9b3083b1..bf8d7a20fd 100644 --- a/src/Avalonia.DotNetCoreRuntime/AppBuilder.cs +++ b/src/Avalonia.DotNetCoreRuntime/AppBuilder.cs @@ -10,6 +10,9 @@ using Avalonia.Shared.PlatformSupport; namespace Avalonia { + /// + /// Initializes platform-specific services for an . + /// public sealed class AppBuilder : AppBuilderBase { /// diff --git a/tests/Avalonia.Controls.UnitTests/WindowTests.cs b/tests/Avalonia.Controls.UnitTests/WindowTests.cs index e0dd908bbb..83f86ce5a0 100644 --- a/tests/Avalonia.Controls.UnitTests/WindowTests.cs +++ b/tests/Avalonia.Controls.UnitTests/WindowTests.cs @@ -68,7 +68,7 @@ namespace Avalonia.Controls.UnitTests } [Fact] - public void IsVisible_Should_Be_False_Atfer_Hide() + public void IsVisible_Should_Be_False_After_Hide() { using (UnitTestApplication.Start(TestServices.StyledWindow)) { @@ -82,7 +82,7 @@ namespace Avalonia.Controls.UnitTests } [Fact] - public void IsVisible_Should_Be_False_Atfer_Close() + public void IsVisible_Should_Be_False_After_Close() { using (UnitTestApplication.Start(TestServices.StyledWindow)) { @@ -96,7 +96,7 @@ namespace Avalonia.Controls.UnitTests } [Fact] - public void IsVisible_Should_Be_False_Atfer_Impl_Signals_Close() + public void IsVisible_Should_Be_False_After_Impl_Signals_Close() { var windowImpl = new Mock(); windowImpl.SetupProperty(x => x.Closed); @@ -191,5 +191,76 @@ namespace Avalonia.Controls.UnitTests // AvaloniaLocator scopes. ((IList)Window.OpenWindows).Clear(); } + + [Fact] + public void Window_Should_Be_Centered_When_Window_Startup_Location_Is_Center_Screen() + { + var windowImpl = new Mock(); + windowImpl.SetupProperty(x => x.Position); + windowImpl.Setup(x => x.ClientSize).Returns(new Size(800, 480)); + windowImpl.Setup(x => x.MaxClientSize).Returns(new Size(1920, 1080)); + windowImpl.Setup(x => x.Scaling).Returns(1); + + using (UnitTestApplication.Start(TestServices.StyledWindow)) + { + var window = new Window(); + window.WindowStartupLocation = WindowStartupLocation.CenterScreen; + window.Position = new Point(60, 40); + + window.Show(); + + var expectedPosition = new Point( + window.PlatformImpl.MaxClientSize.Width / 2 - window.ClientSize.Width / 2, + window.PlatformImpl.MaxClientSize.Height / 2 - window.ClientSize.Height / 2); + + Assert.Equal(window.Position, expectedPosition); + } + } + + [Fact] + public void Window_Should_Be_Centered_Relative_To_Owner_When_Window_Startup_Location_Is_Center_Owner() + { + var parentWindowImpl = new Mock(); + parentWindowImpl.SetupProperty(x => x.Position); + parentWindowImpl.Setup(x => x.ClientSize).Returns(new Size(800, 480)); + parentWindowImpl.Setup(x => x.MaxClientSize).Returns(new Size(1920, 1080)); + parentWindowImpl.Setup(x => x.Scaling).Returns(1); + + var windowImpl = new Mock(); + windowImpl.SetupProperty(x => x.Position); + windowImpl.Setup(x => x.ClientSize).Returns(new Size(320, 200)); + windowImpl.Setup(x => x.MaxClientSize).Returns(new Size(1920, 1080)); + windowImpl.Setup(x => x.Scaling).Returns(1); + + var parentWindowServices = TestServices.StyledWindow.With( + windowingPlatform: new MockWindowingPlatform(() => parentWindowImpl.Object)); + + var windowServices = TestServices.StyledWindow.With( + windowingPlatform: new MockWindowingPlatform(() => windowImpl.Object)); + + using (UnitTestApplication.Start(parentWindowServices)) + { + var parentWindow = new Window(); + parentWindow.Position = new Point(60, 40); + + parentWindow.Show(); + + using (UnitTestApplication.Start(windowServices)) + { + var window = new Window(); + window.WindowStartupLocation = WindowStartupLocation.CenterOwner; + window.Position = new Point(60, 40); + window.Owner = parentWindow; + + window.Show(); + + var expectedPosition = new Point( + parentWindow.Position.X + parentWindow.ClientSize.Width / 2 - window.ClientSize.Width / 2, + parentWindow.Position.Y + parentWindow.ClientSize.Height / 2 - window.ClientSize.Height / 2); + + Assert.Equal(window.Position, expectedPosition); + } + } + } } } From 87e8cb892384127b7be314a7da8678bc1deefe44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Pedro?= Date: Sat, 8 Jul 2017 18:14:06 +0100 Subject: [PATCH 02/25] Fixed PossibleNullReferenceException. --- src/Avalonia.Controls/Window.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index 3535510ce3..7f0cab3237 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -336,8 +336,11 @@ namespace Avalonia.Controls { if (WindowStartupLocation == WindowStartupLocation.CenterScreen) { - var positionAsSize = PlatformImpl.MaxClientSize / 2 - ClientSize / 2; - Position = new Point(positionAsSize.Width, positionAsSize.Height); + if (PlatformImpl != null) + { + var positionAsSize = PlatformImpl.MaxClientSize / 2 - ClientSize / 2; + Position = new Point(positionAsSize.Width, positionAsSize.Height); + } } else if (WindowStartupLocation == WindowStartupLocation.CenterOwner) { From e54d0c75d1c64f26be1aa6e67fede778729e0040 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Pedro?= Date: Sun, 9 Jul 2017 14:03:22 +0100 Subject: [PATCH 03/25] Property changes. --- src/Avalonia.Controls/Window.cs | 13 +++++++++++-- src/Avalonia.Controls/WindowBase.cs | 9 +++++---- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index 7f0cab3237..f60768980d 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -78,9 +78,16 @@ namespace Avalonia.Controls public static readonly StyledProperty IconProperty = AvaloniaProperty.Register(nameof(Icon)); + /// + /// Defines the proeprty. + /// + public static readonly DirectProperty WindowStartupLocationProperty = + AvaloniaProperty.RegisterDirect(nameof(WindowStartupLocation), o => o.WindowStartupLocation); + private readonly NameScope _nameScope = new NameScope(); private object _dialogResult; private readonly Size _maxPlatformClientSize; + private WindowStartupLocation _windowStartupLoction; /// /// Initializes static members of the class. @@ -188,8 +195,8 @@ namespace Avalonia.Controls /// public WindowStartupLocation WindowStartupLocation { - get; - set; + get { return _windowStartupLoction; } + set { SetAndRaise(WindowStartupLocationProperty, ref _windowStartupLoction, value); } } /// @@ -336,6 +343,8 @@ namespace Avalonia.Controls { if (WindowStartupLocation == WindowStartupLocation.CenterScreen) { + // This should be using a Screen API, but we don't have one yet and + // PlatformImpl.MaxClientSize is the best we have. if (PlatformImpl != null) { var positionAsSize = PlatformImpl.MaxClientSize / 2 - ClientSize / 2; diff --git a/src/Avalonia.Controls/WindowBase.cs b/src/Avalonia.Controls/WindowBase.cs index dd1e8fbef1..dd1e0ae842 100644 --- a/src/Avalonia.Controls/WindowBase.cs +++ b/src/Avalonia.Controls/WindowBase.cs @@ -32,12 +32,13 @@ namespace Avalonia.Controls /// /// Defines the property. /// - public static readonly StyledProperty OwnerProperty = - AvaloniaProperty.Register(nameof(Owner)); + public static readonly DirectProperty OwnerProperty = + AvaloniaProperty.RegisterDirect(nameof(Owner), o => o.Owner); private bool _hasExecutedInitialLayoutPass; private bool _isActive; private bool _ignoreVisibilityChange; + private WindowBase _owner; static WindowBase() { @@ -111,8 +112,8 @@ namespace Avalonia.Controls /// public WindowBase Owner { - get { return GetValue(OwnerProperty); } - set { SetValue(OwnerProperty, value); } + get { return _owner; } + set { SetAndRaise(OwnerProperty, ref _owner, value); } } /// From efb9fd4c5732db991a6e70e7c410226bea68202c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Pedro?= Date: Sun, 6 Aug 2017 18:02:16 +0100 Subject: [PATCH 04/25] Added missing setters. --- src/Avalonia.Controls/Window.cs | 5 ++++- src/Avalonia.Controls/WindowBase.cs | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index f60768980d..a94609122a 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -82,7 +82,10 @@ namespace Avalonia.Controls /// Defines the proeprty. /// public static readonly DirectProperty WindowStartupLocationProperty = - AvaloniaProperty.RegisterDirect(nameof(WindowStartupLocation), o => o.WindowStartupLocation); + AvaloniaProperty.RegisterDirect( + nameof(WindowStartupLocation), + o => o.WindowStartupLocation, + (o, v) => o.WindowStartupLocation = v); private readonly NameScope _nameScope = new NameScope(); private object _dialogResult; diff --git a/src/Avalonia.Controls/WindowBase.cs b/src/Avalonia.Controls/WindowBase.cs index dd1e0ae842..73d6d8c7cc 100644 --- a/src/Avalonia.Controls/WindowBase.cs +++ b/src/Avalonia.Controls/WindowBase.cs @@ -33,7 +33,10 @@ namespace Avalonia.Controls /// Defines the property. /// public static readonly DirectProperty OwnerProperty = - AvaloniaProperty.RegisterDirect(nameof(Owner), o => o.Owner); + AvaloniaProperty.RegisterDirect( + nameof(Owner), + o => o.Owner, + (o, v) => o.Owner = v); private bool _hasExecutedInitialLayoutPass; private bool _isActive; From 2cc4b41acc7521f72fe552cfbf079c85f06199dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Pedro?= Date: Tue, 3 Oct 2017 22:12:11 +0100 Subject: [PATCH 05/25] Use Screen API. --- src/Avalonia.Controls/Screens.cs | 2 +- src/Avalonia.Controls/Window.cs | 11 ++++------- src/Windows/Avalonia.Win32/ScreenImpl.cs | 4 ++-- .../Avalonia.Controls.UnitTests/WindowTests.cs | 18 ++++++++++++------ 4 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/Avalonia.Controls/Screens.cs b/src/Avalonia.Controls/Screens.cs index b8ddce3aea..2bfddc048b 100644 --- a/src/Avalonia.Controls/Screens.cs +++ b/src/Avalonia.Controls/Screens.cs @@ -39,7 +39,7 @@ namespace Avalonia.Controls return currMaxScreen; } - public Screen SceenFromPoint(Point point) + public Screen ScreenFromPoint(Point point) { return All.FirstOrDefault(x=>x.Bounds.Contains(point)); } diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index 4cbd73841b..7890a7dd5a 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -376,13 +376,10 @@ namespace Avalonia.Controls { if (WindowStartupLocation == WindowStartupLocation.CenterScreen) { - // This should be using a Screen API, but we don't have one yet and - // PlatformImpl.MaxClientSize is the best we have. - if (PlatformImpl != null) - { - var positionAsSize = PlatformImpl.MaxClientSize / 2 - ClientSize / 2; - Position = new Point(positionAsSize.Width, positionAsSize.Height); - } + var screen = Screens.ScreenFromPoint(Bounds.Position); + + if (screen != null) + Position = screen.WorkingArea.CenterRect(new Rect(ClientSize)).Position; } else if (WindowStartupLocation == WindowStartupLocation.CenterOwner) { diff --git a/src/Windows/Avalonia.Win32/ScreenImpl.cs b/src/Windows/Avalonia.Win32/ScreenImpl.cs index 4f4331e461..113b2811dc 100644 --- a/src/Windows/Avalonia.Win32/ScreenImpl.cs +++ b/src/Windows/Avalonia.Win32/ScreenImpl.cs @@ -41,8 +41,8 @@ namespace Avalonia.Win32 Rect avaloniaBounds = new Rect(bounds.left, bounds.top, bounds.right - bounds.left, bounds.bottom - bounds.top); Rect avaloniaWorkArea = - new Rect(workingArea.left, workingArea.top, workingArea.right - bounds.left, - workingArea.bottom - bounds.top); + new Rect(workingArea.left, workingArea.top, workingArea.right - workingArea.left, + workingArea.bottom - workingArea.top); screens[index] = new WinScreen(avaloniaBounds, avaloniaWorkArea, monitorInfo.dwFlags == 1, monitor); diff --git a/tests/Avalonia.Controls.UnitTests/WindowTests.cs b/tests/Avalonia.Controls.UnitTests/WindowTests.cs index 4de1cfe356..6168421919 100644 --- a/tests/Avalonia.Controls.UnitTests/WindowTests.cs +++ b/tests/Avalonia.Controls.UnitTests/WindowTests.cs @@ -239,32 +239,38 @@ namespace Avalonia.Controls.UnitTests } [Fact] - public void Window_Should_Be_Centered_When_Window_Startup_Location_Is_Center_Screen() + public void Window_Should_Be_Centered_When_WindowStartupLocation_Is_CenterScreen() { + var screen1 = new Mock(new Rect(new Size(1920, 1080)), new Rect(new Size(1920, 1040)), true); + var screen2 = new Mock(new Rect(new Size(1366, 768)), new Rect(new Size(1366, 728)), false); + + var screens = new Mock(); + screens.Setup(x => x.AllScreens).Returns(new Screen[] { screen1.Object, screen2.Object }); + var windowImpl = new Mock(); windowImpl.SetupProperty(x => x.Position); windowImpl.Setup(x => x.ClientSize).Returns(new Size(800, 480)); - windowImpl.Setup(x => x.MaxClientSize).Returns(new Size(1920, 1080)); windowImpl.Setup(x => x.Scaling).Returns(1); + windowImpl.Setup(x => x.Screen).Returns(screens.Object); using (UnitTestApplication.Start(TestServices.StyledWindow)) { - var window = new Window(); + var window = new Window(windowImpl.Object); window.WindowStartupLocation = WindowStartupLocation.CenterScreen; window.Position = new Point(60, 40); window.Show(); var expectedPosition = new Point( - window.PlatformImpl.MaxClientSize.Width / 2 - window.ClientSize.Width / 2, - window.PlatformImpl.MaxClientSize.Height / 2 - window.ClientSize.Height / 2); + screen1.Object.WorkingArea.Size.Width / 2 - window.ClientSize.Width / 2, + screen1.Object.WorkingArea.Size.Height / 2 - window.ClientSize.Height / 2); Assert.Equal(window.Position, expectedPosition); } } [Fact] - public void Window_Should_Be_Centered_Relative_To_Owner_When_Window_Startup_Location_Is_Center_Owner() + public void Window_Should_Be_Centered_Relative_To_Owner_When_WindowStartupLocation_Is_CenterOwner() { var parentWindowImpl = new Mock(); parentWindowImpl.SetupProperty(x => x.Position); From e55ec59ec31ca1015cebe9c40f747f7327c96251 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Sat, 27 Jan 2018 17:18:39 +0100 Subject: [PATCH 06/25] WIP --- Avalonia.sln | 49 -------- .../Avalonia.DotNetCoreRuntime.csproj | 2 +- .../Avalonia.Win32.Interop.csproj | 4 + .../WinForms}/WinFormsAvaloniaControlHost.cs | 1 - .../Avalonia.Win32/Avalonia.Win32.csproj | 106 +++--------------- .../Embedding/EmbeddedWindowImpl.cs | 50 ++++----- .../Avalonia.Win32/Properties/AssemblyInfo.cs | 2 - src/Windows/Avalonia.Win32/Win32Platform.cs | 4 - src/Windows/Avalonia.Win32/WindowImpl.cs | 13 +-- 9 files changed, 47 insertions(+), 184 deletions(-) rename src/Windows/{Avalonia.Win32/Embedding => Avalonia.Win32.Interop/WinForms}/WinFormsAvaloniaControlHost.cs (99%) diff --git a/Avalonia.sln b/Avalonia.sln index 7cf2cf3b8a..6215ff61a1 100644 --- a/Avalonia.sln +++ b/Avalonia.sln @@ -126,10 +126,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RenderTest", "samples\Rende EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog.Android", "samples\ControlCatalog.Android\ControlCatalog.Android.csproj", "{29132311-1848-4FD6-AE0C-4FF841151BD3}" EndProject -Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Avalonia.Win32.Shared", "src\Windows\Avalonia.Win32\Avalonia.Win32.Shared.shproj", "{9DEFC6B7-845B-4D8F-AFC0-D32BF0032B8C}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Win32.NetStandard", "src\Windows\Avalonia.Win32.NetStandard\Avalonia.Win32.NetStandard.csproj", "{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.DotNetCoreRuntime", "src\Avalonia.DotNetCoreRuntime\Avalonia.DotNetCoreRuntime.csproj", "{7863EA94-F0FB-4386-BF8C-E5BFA761560A}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Skia", "src\Skia\Avalonia.Skia\Avalonia.Skia.csproj", "{7D2D3083-71DD-4CC9-8907-39A0D86FB322}" @@ -196,14 +192,11 @@ Global GlobalSection(SharedMSBuildProjectFiles) = preSolution src\Shared\RenderHelpers\RenderHelpers.projitems*{3c4c0cb4-0c0f-4450-a37b-148c84ff905f}*SharedItemsImports = 13 src\Shared\RenderHelpers\RenderHelpers.projitems*{3e908f67-5543-4879-a1dc-08eace79b3cd}*SharedItemsImports = 4 - src\Windows\Avalonia.Win32\Avalonia.Win32.Shared.projitems*{40759a76-d0f2-464e-8000-6ff0f5c4bd7c}*SharedItemsImports = 4 src\Shared\PlatformSupport\PlatformSupport.projitems*{4488ad85-1495-4809-9aa4-ddfe0a48527e}*SharedItemsImports = 4 src\Shared\PlatformSupport\PlatformSupport.projitems*{4a1abb09-9047-4bd5-a4ad-a055e52c5ee0}*SharedItemsImports = 4 src\Shared\PlatformSupport\PlatformSupport.projitems*{7863ea94-f0fb-4386-bf8c-e5bfa761560a}*SharedItemsImports = 4 src\Shared\PlatformSupport\PlatformSupport.projitems*{7b92af71-6287-4693-9dcb-bd5b6e927e23}*SharedItemsImports = 4 src\Shared\RenderHelpers\RenderHelpers.projitems*{7d2d3083-71dd-4cc9-8907-39a0d86fb322}*SharedItemsImports = 4 - src\Windows\Avalonia.Win32\Avalonia.Win32.Shared.projitems*{811a76cf-1cf6-440f-963b-bbe31bd72a82}*SharedItemsImports = 4 - src\Windows\Avalonia.Win32\Avalonia.Win32.Shared.projitems*{9defc6b7-845b-4d8f-afc0-d32bf0032b8c}*SharedItemsImports = 13 tests\Avalonia.RenderTests\Avalonia.RenderTests.projitems*{dabfd304-d6a4-4752-8123-c2ccf7ac7831}*SharedItemsImports = 4 src\Shared\PlatformSupport\PlatformSupport.projitems*{e4d9629c-f168-4224-3f51-a5e482ffbc42}*SharedItemsImports = 13 EndGlobalSection @@ -1994,46 +1987,6 @@ Global {29132311-1848-4FD6-AE0C-4FF841151BD3}.Release|x86.ActiveCfg = Release|Any CPU {29132311-1848-4FD6-AE0C-4FF841151BD3}.Release|x86.Build.0 = Release|Any CPU {29132311-1848-4FD6-AE0C-4FF841151BD3}.Release|x86.Deploy.0 = Release|Any CPU - {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU - {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU - {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU - {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU - {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU - {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU - {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Ad-Hoc|NetCoreOnly.ActiveCfg = Release|Any CPU - {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Ad-Hoc|NetCoreOnly.Build.0 = Release|Any CPU - {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU - {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Ad-Hoc|x86.Build.0 = Release|Any CPU - {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.AppStore|Any CPU.ActiveCfg = Release|Any CPU - {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.AppStore|Any CPU.Build.0 = Release|Any CPU - {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.AppStore|iPhone.ActiveCfg = Release|Any CPU - {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.AppStore|iPhone.Build.0 = Release|Any CPU - {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU - {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU - {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.AppStore|NetCoreOnly.ActiveCfg = Release|Any CPU - {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.AppStore|NetCoreOnly.Build.0 = Release|Any CPU - {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.AppStore|x86.ActiveCfg = Release|Any CPU - {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.AppStore|x86.Build.0 = Release|Any CPU - {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Debug|iPhone.Build.0 = Debug|Any CPU - {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU - {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Debug|NetCoreOnly.ActiveCfg = Debug|Any CPU - {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Debug|NetCoreOnly.Build.0 = Debug|Any CPU - {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Debug|x86.ActiveCfg = Debug|Any CPU - {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Debug|x86.Build.0 = Debug|Any CPU - {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Release|Any CPU.Build.0 = Release|Any CPU - {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Release|iPhone.ActiveCfg = Release|Any CPU - {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Release|iPhone.Build.0 = Release|Any CPU - {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU - {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Release|NetCoreOnly.ActiveCfg = Release|Any CPU - {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Release|NetCoreOnly.Build.0 = Release|Any CPU - {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Release|x86.ActiveCfg = Release|Any CPU - {40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Release|x86.Build.0 = Release|Any CPU {7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU {7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU {7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU @@ -2623,8 +2576,6 @@ Global {C7A69145-60B6-4882-97D6-A3921DD43978} = {A0CC0258-D18C-4AB3-854F-7101680FC3F9} {F1FDC5B0-4654-416F-AE69-E3E9BBD87801} = {9B9E3891-2366-4253-A952-D08BCEB71098} {29132311-1848-4FD6-AE0C-4FF841151BD3} = {9B9E3891-2366-4253-A952-D08BCEB71098} - {9DEFC6B7-845B-4D8F-AFC0-D32BF0032B8C} = {B39A8919-9F95-48FE-AD7B-76E08B509888} - {40759A76-D0F2-464E-8000-6FF0F5C4BD7C} = {B39A8919-9F95-48FE-AD7B-76E08B509888} {7D2D3083-71DD-4CC9-8907-39A0D86FB322} = {3743B0F2-CC41-4F14-A8C8-267F579BF91E} {BB1F7BB5-6AD4-4776-94D9-C09D0A972658} = {B9894058-278A-46B5-B6ED-AD613FCC03B3} {39D7B147-1A5B-47C2-9D01-21FB7C47C4B3} = {9B9E3891-2366-4253-A952-D08BCEB71098} diff --git a/src/Avalonia.DotNetCoreRuntime/Avalonia.DotNetCoreRuntime.csproj b/src/Avalonia.DotNetCoreRuntime/Avalonia.DotNetCoreRuntime.csproj index 8630e7b228..a7586ac7ac 100644 --- a/src/Avalonia.DotNetCoreRuntime/Avalonia.DotNetCoreRuntime.csproj +++ b/src/Avalonia.DotNetCoreRuntime/Avalonia.DotNetCoreRuntime.csproj @@ -19,7 +19,7 @@ - + diff --git a/src/Windows/Avalonia.Win32.Interop/Avalonia.Win32.Interop.csproj b/src/Windows/Avalonia.Win32.Interop/Avalonia.Win32.Interop.csproj index 368e5986b2..7b480ef328 100644 --- a/src/Windows/Avalonia.Win32.Interop/Avalonia.Win32.Interop.csproj +++ b/src/Windows/Avalonia.Win32.Interop/Avalonia.Win32.Interop.csproj @@ -34,6 +34,7 @@ + @@ -48,6 +49,9 @@ UnmanagedMethods.cs + + Component + diff --git a/src/Windows/Avalonia.Win32/Embedding/WinFormsAvaloniaControlHost.cs b/src/Windows/Avalonia.Win32.Interop/WinForms/WinFormsAvaloniaControlHost.cs similarity index 99% rename from src/Windows/Avalonia.Win32/Embedding/WinFormsAvaloniaControlHost.cs rename to src/Windows/Avalonia.Win32.Interop/WinForms/WinFormsAvaloniaControlHost.cs index a484d6c0d2..fe626f4d38 100644 --- a/src/Windows/Avalonia.Win32/Embedding/WinFormsAvaloniaControlHost.cs +++ b/src/Windows/Avalonia.Win32.Interop/WinForms/WinFormsAvaloniaControlHost.cs @@ -1,7 +1,6 @@ using System; using System.ComponentModel; using System.Windows.Forms; -using Avalonia.Controls; using Avalonia.Controls.Embedding; using Avalonia.Input; using Avalonia.VisualTree; diff --git a/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj b/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj index 92d973238e..eee6156274 100644 --- a/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj +++ b/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj @@ -1,104 +1,24 @@ - - - + - Debug - AnyCPU - {811A76CF-1CF6-440F-963B-BBE31BD72A82} - Library - Properties - Avalonia.Win32 - Avalonia.Win32 - v4.6.1 - 512 - - + netstandard2.0 - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - bin\Debug\Avalonia.Win32.xml + true - CS1591 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - bin\Release\Avalonia.Win32.xml - true - CS1591 - true - - - - - - - - - - - - + + + + + + + + - - - Component - - - + - - {D211E587-D8BC-45B9-95A4-F297C8FA5200} - Avalonia.Animation - - - {B09B78D8-9B26-48B0-9149-D64A2F120F3F} - Avalonia.Base - - - {D2221C82-4A25-4583-9B43-D791E3F6820C} - Avalonia.Controls - - - {7062AE20-5DCC-4442-9645-8195BDECE63E} - Avalonia.Diagnostics - - - {62024B2D-53EB-4638-B26B-85EEAA54866E} - Avalonia.Input - - - {6B0ED19D-A08B-461C-A9D9-A9EE40B0C06B} - Avalonia.Interactivity - - - {42472427-4774-4C81-8AFF-9F27B8E31721} - Avalonia.Layout - - - {EB582467-6ABB-43A1-B052-E981BA910E3A} - Avalonia.Visuals - - - {F1BAA01A-F176-4C6A-B39D-5B40BB1B148F} - Avalonia.Styling - + - - - \ No newline at end of file diff --git a/src/Windows/Avalonia.Win32/Embedding/EmbeddedWindowImpl.cs b/src/Windows/Avalonia.Win32/Embedding/EmbeddedWindowImpl.cs index d27c28cb67..5e91ede4a5 100644 --- a/src/Windows/Avalonia.Win32/Embedding/EmbeddedWindowImpl.cs +++ b/src/Windows/Avalonia.Win32/Embedding/EmbeddedWindowImpl.cs @@ -9,34 +9,34 @@ namespace Avalonia.Win32 { class EmbeddedWindowImpl : WindowImpl, IEmbeddableWindowImpl { - private static readonly System.Windows.Forms.UserControl WinFormsControl = new System.Windows.Forms.UserControl(); + //private static readonly System.Windows.Forms.UserControl WinFormsControl = new System.Windows.Forms.UserControl(); - public static IntPtr DefaultParentWindow = WinFormsControl.Handle; + //public static IntPtr DefaultParentWindow = WinFormsControl.Handle; - protected override IntPtr CreateWindowOverride(ushort atom) - { - var hWnd = UnmanagedMethods.CreateWindowEx( - 0, - atom, - null, - (int)UnmanagedMethods.WindowStyles.WS_CHILD, - 0, - 0, - 640, - 480, - DefaultParentWindow, - IntPtr.Zero, - IntPtr.Zero, - IntPtr.Zero); - return hWnd; - } + //protected override IntPtr CreateWindowOverride(ushort atom) + //{ + // var hWnd = UnmanagedMethods.CreateWindowEx( + // 0, + // atom, + // null, + // (int)UnmanagedMethods.WindowStyles.WS_CHILD, + // 0, + // 0, + // 640, + // 480, + // DefaultParentWindow, + // IntPtr.Zero, + // IntPtr.Zero, + // IntPtr.Zero); + // return hWnd; + //} - protected override IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam) - { - if(msg == (uint)UnmanagedMethods.WindowsMessage.WM_KILLFOCUS) - LostFocus?.Invoke(); - return base.WndProc(hWnd, msg, wParam, lParam); - } + //protected override IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam) + //{ + // if(msg == (uint)UnmanagedMethods.WindowsMessage.WM_KILLFOCUS) + // LostFocus?.Invoke(); + // return base.WndProc(hWnd, msg, wParam, lParam); + //} public event Action LostFocus; } diff --git a/src/Windows/Avalonia.Win32/Properties/AssemblyInfo.cs b/src/Windows/Avalonia.Win32/Properties/AssemblyInfo.cs index 5b4d2cef23..38ec891f76 100644 --- a/src/Windows/Avalonia.Win32/Properties/AssemblyInfo.cs +++ b/src/Windows/Avalonia.Win32/Properties/AssemblyInfo.cs @@ -3,7 +3,5 @@ using Avalonia.Platform; using Avalonia.Win32; -using System.Reflection; -[assembly: AssemblyTitle("Avalonia.Win32")] [assembly: ExportWindowingSubsystem(OperatingSystemType.WinNT, 1, "Win32", typeof(Win32Platform), nameof(Win32Platform.Initialize))] diff --git a/src/Windows/Avalonia.Win32/Win32Platform.cs b/src/Windows/Avalonia.Win32/Win32Platform.cs index e265749249..a490e59cb7 100644 --- a/src/Windows/Avalonia.Win32/Win32Platform.cs +++ b/src/Windows/Avalonia.Win32/Win32Platform.cs @@ -196,13 +196,9 @@ namespace Avalonia.Win32 public IEmbeddableWindowImpl CreateEmbeddableWindow() { -#if NETSTANDARD - throw new NotSupportedException(); -#else var embedded = new EmbeddedWindowImpl(); embedded.Show(); return embedded; -#endif } public IPopupImpl CreatePopup() diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 348468e0e7..d9b5e25c63 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -1,29 +1,24 @@ // 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 Avalonia.Input; using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics.CodeAnalysis; -using System.Linq; +using System.Reactive.Disposables; using System.Runtime.InteropServices; using Avalonia.Controls; -using System.Reactive.Disposables; +using Avalonia.Input; using Avalonia.Input.Raw; using Avalonia.Platform; +using Avalonia.Rendering; using Avalonia.Win32.Input; using Avalonia.Win32.Interop; using static Avalonia.Win32.Interop.UnmanagedMethods; -using Avalonia.Rendering; -using Avalonia.Threading; -#if NETSTANDARD -using Win32Exception = Avalonia.Win32.NetStandard.AvaloniaWin32Exception; -#endif namespace Avalonia.Win32 { - class WindowImpl : IWindowImpl + public class WindowImpl : IWindowImpl { private static readonly List s_instances = new List(); From 728c19eb8639e7d5cd438344d9d48e730d3971a4 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Sun, 28 Jan 2018 17:17:29 +0100 Subject: [PATCH 07/25] Removed unused files. --- .../Avalonia.Win32.Shared.projitems | 34 ---- src/Windows/Avalonia.Win32/Settings.StyleCop | 184 ------------------ 2 files changed, 218 deletions(-) delete mode 100644 src/Windows/Avalonia.Win32/Avalonia.Win32.Shared.projitems delete mode 100644 src/Windows/Avalonia.Win32/Settings.StyleCop diff --git a/src/Windows/Avalonia.Win32/Avalonia.Win32.Shared.projitems b/src/Windows/Avalonia.Win32/Avalonia.Win32.Shared.projitems deleted file mode 100644 index 6f13747cb6..0000000000 --- a/src/Windows/Avalonia.Win32/Avalonia.Win32.Shared.projitems +++ /dev/null @@ -1,34 +0,0 @@ - - - - $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - true - 9defc6b7-845b-4d8f-afc0-d32bf0032b8c - - - Avalonia.Win32.Shared - - - - - - - - - - - - - - - - - - - - - - Properties\SharedAssemblyInfo.cs - - - \ No newline at end of file diff --git a/src/Windows/Avalonia.Win32/Settings.StyleCop b/src/Windows/Avalonia.Win32/Settings.StyleCop deleted file mode 100644 index 5bd6cda777..0000000000 --- a/src/Windows/Avalonia.Win32/Settings.StyleCop +++ /dev/null @@ -1,184 +0,0 @@ - - - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - - - \ No newline at end of file From 0e126d2b0638014646dc11590ec27f8dcf31e12b Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Sun, 28 Jan 2018 19:09:27 +0100 Subject: [PATCH 08/25] Reimplement EmbeddedWindowImpl. Without System.Windows.Forms. --- .../Embedding/EmbeddedWindowImpl.cs | 104 +++++++++++++----- 1 file changed, 76 insertions(+), 28 deletions(-) diff --git a/src/Windows/Avalonia.Win32/Embedding/EmbeddedWindowImpl.cs b/src/Windows/Avalonia.Win32/Embedding/EmbeddedWindowImpl.cs index 5e91ede4a5..3871936605 100644 --- a/src/Windows/Avalonia.Win32/Embedding/EmbeddedWindowImpl.cs +++ b/src/Windows/Avalonia.Win32/Embedding/EmbeddedWindowImpl.cs @@ -2,6 +2,9 @@ // Licensed under the MIT license. See licence.md file in the project root for full license information. using System; +using System.ComponentModel; +using System.Runtime.InteropServices; +using System.Windows.Forms; using Avalonia.Platform; using Avalonia.Win32.Interop; @@ -9,35 +12,80 @@ namespace Avalonia.Win32 { class EmbeddedWindowImpl : WindowImpl, IEmbeddableWindowImpl { - //private static readonly System.Windows.Forms.UserControl WinFormsControl = new System.Windows.Forms.UserControl(); - - //public static IntPtr DefaultParentWindow = WinFormsControl.Handle; - - //protected override IntPtr CreateWindowOverride(ushort atom) - //{ - // var hWnd = UnmanagedMethods.CreateWindowEx( - // 0, - // atom, - // null, - // (int)UnmanagedMethods.WindowStyles.WS_CHILD, - // 0, - // 0, - // 640, - // 480, - // DefaultParentWindow, - // IntPtr.Zero, - // IntPtr.Zero, - // IntPtr.Zero); - // return hWnd; - //} - - //protected override IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam) - //{ - // if(msg == (uint)UnmanagedMethods.WindowsMessage.WM_KILLFOCUS) - // LostFocus?.Invoke(); - // return base.WndProc(hWnd, msg, wParam, lParam); - //} + private static IntPtr DefaultParentWindow = CreateParentWindow(); + private static UnmanagedMethods.WndProc _wndProcDelegate; + + protected override IntPtr CreateWindowOverride(ushort atom) + { + var hWnd = UnmanagedMethods.CreateWindowEx( + 0, + atom, + null, + (int)UnmanagedMethods.WindowStyles.WS_CHILD, + 0, + 0, + 640, + 480, + DefaultParentWindow, + IntPtr.Zero, + IntPtr.Zero, + IntPtr.Zero); + return hWnd; + } + + protected override IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam) + { + if (msg == (uint)UnmanagedMethods.WindowsMessage.WM_KILLFOCUS) + LostFocus?.Invoke(); + return base.WndProc(hWnd, msg, wParam, lParam); + } public event Action LostFocus; + + private static IntPtr CreateParentWindow() + { + _wndProcDelegate = new UnmanagedMethods.WndProc(ParentWndProc); + + var wndClassEx = new UnmanagedMethods.WNDCLASSEX + { + cbSize = Marshal.SizeOf(), + hInstance = UnmanagedMethods.GetModuleHandle(null), + lpfnWndProc = _wndProcDelegate, + lpszClassName = "AvaloniaEmbeddedWindow-" + Guid.NewGuid(), + }; + + var atom = UnmanagedMethods.RegisterClassEx(ref wndClassEx); + + if (atom == 0) + { + throw new Win32Exception(); + } + + var hwnd = UnmanagedMethods.CreateWindowEx( + 0, + atom, + null, + (int)UnmanagedMethods.WindowStyles.WS_OVERLAPPEDWINDOW, + UnmanagedMethods.CW_USEDEFAULT, + UnmanagedMethods.CW_USEDEFAULT, + UnmanagedMethods.CW_USEDEFAULT, + UnmanagedMethods.CW_USEDEFAULT, + IntPtr.Zero, + IntPtr.Zero, + IntPtr.Zero, + IntPtr.Zero); + + if (hwnd == IntPtr.Zero) + { + throw new Win32Exception(); + } + + return hwnd; + } + + private static IntPtr ParentWndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam) + { + return UnmanagedMethods.DefWindowProc(hWnd, msg, wParam, lParam); + } } } From 79f35161be956bdd7baa896d55effd8de05a268d Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Sun, 28 Jan 2018 19:13:33 +0100 Subject: [PATCH 09/25] Use correct CharSet for WNDCLASSEX And prepend `Avalonia-` to window class. Looking in Spy++ I noticed that our window class name was garbage because the `CharSet` on `WNDCLASSEX` was wrong. Fix that and include "Avalonia" in our window classes. --- src/Windows/Avalonia.Win32/Embedding/EmbeddedWindowImpl.cs | 1 - src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs | 2 +- src/Windows/Avalonia.Win32/WindowImpl.cs | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Windows/Avalonia.Win32/Embedding/EmbeddedWindowImpl.cs b/src/Windows/Avalonia.Win32/Embedding/EmbeddedWindowImpl.cs index 3871936605..cb9c753f4d 100644 --- a/src/Windows/Avalonia.Win32/Embedding/EmbeddedWindowImpl.cs +++ b/src/Windows/Avalonia.Win32/Embedding/EmbeddedWindowImpl.cs @@ -4,7 +4,6 @@ using System; using System.ComponentModel; using System.Runtime.InteropServices; -using System.Windows.Forms; using Avalonia.Platform; using Avalonia.Win32.Interop; diff --git a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs index a0518cf92e..f13dd3272c 100644 --- a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs +++ b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs @@ -1098,7 +1098,7 @@ namespace Avalonia.Win32.Interop } } - [StructLayout(LayoutKind.Sequential)] + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct WNDCLASSEX { public int cbSize; diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index d9b5e25c63..3ba926b42a 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -641,7 +641,7 @@ namespace Avalonia.Win32 // Ensure that the delegate doesn't get garbage collected by storing it as a field. _wndProcDelegate = new UnmanagedMethods.WndProc(WndProc); - _className = Guid.NewGuid().ToString(); + _className = "Avalonia-" + Guid.NewGuid(); UnmanagedMethods.WNDCLASSEX wndClassEx = new UnmanagedMethods.WNDCLASSEX { From a6cfbdac9338e55a33ea24ab9f7ff72eae077dac Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 29 Jan 2018 20:45:49 +0100 Subject: [PATCH 10/25] Remove Avalonia.Win32.NetStandard dir. --- .../Avalonia.Win32.NetStandard.csproj | 49 ----- .../ComStreamWrapper.cs | 197 ------------------ .../Avalonia.Win32.NetStandard/Gdip.cs | 128 ------------ .../Avalonia.Win32.NetStandard/IconImpl.cs | 45 ---- .../NativeWin32Platform.cs | 30 --- .../Win32Exception.cs | 12 -- 6 files changed, 461 deletions(-) delete mode 100644 src/Windows/Avalonia.Win32.NetStandard/Avalonia.Win32.NetStandard.csproj delete mode 100644 src/Windows/Avalonia.Win32.NetStandard/ComStreamWrapper.cs delete mode 100644 src/Windows/Avalonia.Win32.NetStandard/Gdip.cs delete mode 100644 src/Windows/Avalonia.Win32.NetStandard/IconImpl.cs delete mode 100644 src/Windows/Avalonia.Win32.NetStandard/NativeWin32Platform.cs delete mode 100644 src/Windows/Avalonia.Win32.NetStandard/Win32Exception.cs diff --git a/src/Windows/Avalonia.Win32.NetStandard/Avalonia.Win32.NetStandard.csproj b/src/Windows/Avalonia.Win32.NetStandard/Avalonia.Win32.NetStandard.csproj deleted file mode 100644 index bae634b030..0000000000 --- a/src/Windows/Avalonia.Win32.NetStandard/Avalonia.Win32.NetStandard.csproj +++ /dev/null @@ -1,49 +0,0 @@ - - - netstandard2.0 - False - false - Avalonia.Win32 - Avalonia.Win32 - - - true - full - false - bin\Debug\ - TRACE;DEBUG;NETSTANDARD - prompt - 4 - true - - - pdbonly - true - bin\Release\ - TRACE;NETSTANDARD - prompt - 4 - true - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Windows/Avalonia.Win32.NetStandard/ComStreamWrapper.cs b/src/Windows/Avalonia.Win32.NetStandard/ComStreamWrapper.cs deleted file mode 100644 index 083021f58d..0000000000 --- a/src/Windows/Avalonia.Win32.NetStandard/ComStreamWrapper.cs +++ /dev/null @@ -1,197 +0,0 @@ -// -// System.Drawing.ComIStreamWrapper.cs -// -// Author: -// Kornél Pál -// -// Copyright (C) 2005-2008 Kornél Pál -// - -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -using System; -using System.IO; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Runtime.InteropServices.ComTypes; -using STATSTG = System.Runtime.InteropServices.ComTypes.STATSTG; - -namespace Avalonia.Win32 -{ - // Stream to IStream wrapper for COM interop - internal sealed class ComIStreamWrapper : IStream - { - private const int STG_E_INVALIDFUNCTION = unchecked((int)0x80030001); - - private readonly Stream baseStream; - private long position = -1; - - internal ComIStreamWrapper(Stream stream) - { - baseStream = stream; - } - - private void SetSizeToPosition() - { - if (position != -1) - { - if (position > baseStream.Length) - baseStream.SetLength(position); - baseStream.Position = position; - position = -1; - } - } - - public void Read(byte[] pv, int cb, IntPtr pcbRead) - { - int read = 0; - - if (cb != 0) - { - SetSizeToPosition(); - read = baseStream.Read(pv, 0, cb); - } - - if (pcbRead != IntPtr.Zero) - Marshal.WriteInt32(pcbRead, read); - } - - public void Write(byte[] pv, int cb, IntPtr pcbWritten) - { - if (cb != 0) - { - SetSizeToPosition(); - baseStream.Write(pv, 0, cb); - } - - if (pcbWritten != IntPtr.Zero) - Marshal.WriteInt32(pcbWritten, cb); - } - - public void Seek(long dlibMove, int dwOrigin, IntPtr plibNewPosition) - { - long length = baseStream.Length; - long newPosition; - - switch ((SeekOrigin)dwOrigin) - { - case SeekOrigin.Begin: - newPosition = dlibMove; - break; - case SeekOrigin.Current: - if (position == -1) - newPosition = baseStream.Position + dlibMove; - else - newPosition = position + dlibMove; - break; - case SeekOrigin.End: - newPosition = length + dlibMove; - break; - default: - throw new COMException(null, STG_E_INVALIDFUNCTION); - } - - if (newPosition > length) - position = newPosition; - else - { - baseStream.Position = newPosition; - position = -1; - } - - if (plibNewPosition != IntPtr.Zero) - Marshal.WriteInt64(plibNewPosition, newPosition); - } - - public void SetSize(long libNewSize) - { - baseStream.SetLength(libNewSize); - } - - public void CopyTo(IStream pstm, long cb, IntPtr pcbRead, IntPtr pcbWritten) - { - byte[] buffer; - long written = 0; - int read; - int count; - - if (cb != 0) - { - if (cb < 4096) - count = (int)cb; - else - count = 4096; - buffer = new byte[count]; - SetSizeToPosition(); - while (true) - { - if ((read = baseStream.Read(buffer, 0, count)) == 0) - break; - pstm.Write(buffer, read, IntPtr.Zero); - written += read; - if (written >= cb) - break; - if (cb - written < 4096) - count = (int)(cb - written); - } - } - - if (pcbRead != IntPtr.Zero) - Marshal.WriteInt64(pcbRead, written); - if (pcbWritten != IntPtr.Zero) - Marshal.WriteInt64(pcbWritten, written); - } - - public void Commit(int grfCommitFlags) - { - baseStream.Flush(); - SetSizeToPosition(); - } - - public void Revert() - { - throw new COMException(null, STG_E_INVALIDFUNCTION); - } - - public void LockRegion(long libOffset, long cb, int dwLockType) - { - throw new COMException(null, STG_E_INVALIDFUNCTION); - } - - public void UnlockRegion(long libOffset, long cb, int dwLockType) - { - throw new COMException(null, STG_E_INVALIDFUNCTION); - } - - public void Stat(out STATSTG pstatstg, int grfStatFlag) - { - pstatstg = new STATSTG(); - pstatstg.cbSize = baseStream.Length; - } - - public void Clone(out IStream ppstm) - { - ppstm = null; - throw new COMException(null, STG_E_INVALIDFUNCTION); - } - } -} \ No newline at end of file diff --git a/src/Windows/Avalonia.Win32.NetStandard/Gdip.cs b/src/Windows/Avalonia.Win32.NetStandard/Gdip.cs deleted file mode 100644 index b3d1c28689..0000000000 --- a/src/Windows/Avalonia.Win32.NetStandard/Gdip.cs +++ /dev/null @@ -1,128 +0,0 @@ -// -// Code copy-pasted from from Mono / System.Drawing.*.cs -// Original license below: -// -// Authors: -// Alexandre Pigolkine (pigolkine@gmx.de) -// Jordi Mas (jordi@ximian.com) -// Sanjay Gupta (gsanjay@novell.com) -// Ravindra (rkumar@novell.com) -// Peter Dennis Bartok (pbartok@novell.com) -// Sebastien Pouliot -// -// -// Copyright (C) 2004, 2007 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Runtime.InteropServices.ComTypes; -using System.Text; -using System.Threading.Tasks; - -namespace Avalonia.Win32 -{ - static class Gdip - { - public enum Status - { - Ok = 0, - GenericError = 1, - InvalidParameter = 2, - OutOfMemory = 3, - ObjectBusy = 4, - InsufficientBuffer = 5, - NotImplemented = 6, - Win32Error = 7, - WrongState = 8, - Aborted = 9, - FileNotFound = 10, - ValueOverflow = 11, - AccessDenied = 12, - UnknownImageFormat = 13, - FontFamilyNotFound = 14, - FontStyleNotFound = 15, - NotTrueTypeFont = 16, - UnsupportedGdiplusVersion = 17, - GdiplusNotInitialized = 18, - PropertyNotFound = 19, - PropertyNotSupported = 20, - ProfileNotFound = 21 - } - - [StructLayout(LayoutKind.Sequential)] - internal struct GdiplusStartupInput - { - // internalted to silent compiler - internal uint GdiplusVersion; - internal IntPtr DebugEventCallback; - internal int SuppressBackgroundThread; - internal int SuppressExternalCodecs; - - internal static GdiplusStartupInput MakeGdiplusStartupInput() - { - GdiplusStartupInput result = new GdiplusStartupInput(); - result.GdiplusVersion = 1; - result.DebugEventCallback = IntPtr.Zero; - result.SuppressBackgroundThread = 0; - result.SuppressExternalCodecs = 0; - return result; - } - } - - [StructLayout(LayoutKind.Sequential)] - internal struct GdiplusStartupOutput - { - internal IntPtr NotificationHook; - internal IntPtr NotificationUnhook; - - internal static GdiplusStartupOutput MakeGdiplusStartupOutput() - { - GdiplusStartupOutput result = new GdiplusStartupOutput(); - result.NotificationHook = result.NotificationUnhook = IntPtr.Zero; - return result; - } - } - - - [DllImport("gdiplus.dll")] - public static extern Status GdiplusStartup(ref ulong token, ref GdiplusStartupInput input, ref GdiplusStartupOutput output); - - [DllImport("gdiplus.dll", ExactSpelling = true, CharSet = CharSet.Unicode)] - public static extern Status GdipLoadImageFromStream([MarshalAs(UnmanagedType.Interface, MarshalTypeRef = typeof(IStream))] IStream stream, out IntPtr image); - [DllImport("gdiplus.dll")] - public static extern Status GdipCreateHICONFromBitmap(IntPtr bmp, out IntPtr HandleIcon); - - [DllImport("gdiplus.dll")] - internal static extern Status GdipDisposeImage(IntPtr image); - - static Gdip() - { - ulong token = 0; - var input = GdiplusStartupInput.MakeGdiplusStartupInput(); - var output = GdiplusStartupOutput.MakeGdiplusStartupOutput(); - GdiplusStartup(ref token, ref input, ref output); - } - } -} diff --git a/src/Windows/Avalonia.Win32.NetStandard/IconImpl.cs b/src/Windows/Avalonia.Win32.NetStandard/IconImpl.cs deleted file mode 100644 index 49d039e655..0000000000 --- a/src/Windows/Avalonia.Win32.NetStandard/IconImpl.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices; -using System.Runtime.InteropServices.ComTypes; -using System.Text; -using System.Threading.Tasks; -using Avalonia.Platform; - -namespace Avalonia.Win32 -{ - public class IconImpl : IWindowIconImpl - { - private readonly MemoryStream _ms; - - public IconImpl(Stream data) - { - _ms = new MemoryStream(); - data.CopyTo(_ms); - _ms.Seek(0, SeekOrigin.Begin); - IntPtr bitmap; - var status = Gdip.GdipLoadImageFromStream(new ComIStreamWrapper(_ms), out bitmap); - if (status != Gdip.Status.Ok) - throw new Exception("Unable to load icon, gdip status: " + (int) status); - IntPtr icon; - status = Gdip.GdipCreateHICONFromBitmap(bitmap, out icon); - if (status != Gdip.Status.Ok) - throw new Exception("Unable to create HICON, gdip status: " + (int)status); - Gdip.GdipDisposeImage(bitmap); - HIcon = icon; - } - - public IntPtr HIcon { get;} - public void Save(Stream outputStream) - { - lock (_ms) - { - _ms.Seek(0, SeekOrigin.Begin); - _ms.CopyTo(outputStream); - } - } - - } -} diff --git a/src/Windows/Avalonia.Win32.NetStandard/NativeWin32Platform.cs b/src/Windows/Avalonia.Win32.NetStandard/NativeWin32Platform.cs deleted file mode 100644 index 2695a5b8b6..0000000000 --- a/src/Windows/Avalonia.Win32.NetStandard/NativeWin32Platform.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Avalonia.Platform; - -namespace Avalonia.Win32 -{ - partial class Win32Platform - { - //TODO: An actual implementation - public IWindowIconImpl LoadIcon(string fileName) - { - //No file IO for netstandard, still waiting for proper net core tooling - throw new NotSupportedException(); - } - - public IWindowIconImpl LoadIcon(Stream stream) => new IconImpl(stream); - - public IWindowIconImpl LoadIcon(IBitmapImpl bitmap) - { - var ms = new MemoryStream(); - bitmap.Save(ms); - ms.Seek(0, SeekOrigin.Begin); - return new IconImpl(ms); - } - } -} diff --git a/src/Windows/Avalonia.Win32.NetStandard/Win32Exception.cs b/src/Windows/Avalonia.Win32.NetStandard/Win32Exception.cs deleted file mode 100644 index 45926a881d..0000000000 --- a/src/Windows/Avalonia.Win32.NetStandard/Win32Exception.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Avalonia.Win32.NetStandard -{ - class AvaloniaWin32Exception : Exception - { - } -} From 695c48382bda8aefb1e2871a3264ed44f823efc3 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Sat, 17 Feb 2018 15:26:59 +0100 Subject: [PATCH 11/25] Fix AllowUnsafeBlocks. Was only enabled in debug build. --- src/Windows/Avalonia.Win32/Avalonia.Win32.csproj | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj b/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj index 691f635f2c..e055f3c20f 100644 --- a/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj +++ b/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj @@ -1,8 +1,6 @@  netstandard2.0 - - true From 41570cbe9c4f96f1c53ac568d824d3248004d76c Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Sat, 17 Feb 2018 15:47:28 +0100 Subject: [PATCH 12/25] Updated cake package spec. --- packages.cake | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages.cake b/packages.cake index bc290fce22..134340f459 100644 --- a/packages.cake +++ b/packages.cake @@ -376,8 +376,7 @@ public class Packages }, Files = new [] { - new NuSpecContent { Source = "Avalonia.Win32/bin/" + parameters.DirSuffix + "/Avalonia.Win32.dll", Target = "lib/net45" }, - new NuSpecContent { Source = "Avalonia.Win32.NetStandard/bin/" + parameters.DirSuffix + "/netstandard2.0/Avalonia.Win32.dll", Target = "lib/netstandard2.0" } + new NuSpecContent { Source = "Avalonia.Win32/bin/" + parameters.DirSuffix + "/netstandard2.0/Avalonia.Win32.dll", Target = "lib/netstandard2.0" } }, BasePath = context.Directory("./src/Windows"), OutputDirectory = parameters.NugetRoot From 915c4bba9dde573eb6b3870f2f2dfb67026a31ce Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Sun, 18 Feb 2018 20:48:53 +0100 Subject: [PATCH 13/25] Include Avalonia.Win32 in NetCoreOnly build. --- Avalonia.sln | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Avalonia.sln b/Avalonia.sln index 6215ff61a1..5855edba5a 100644 --- a/Avalonia.sln +++ b/Avalonia.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.27130.2024 +VisualStudioVersion = 15.0.27130.2027 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Base", "src\Avalonia.Base\Avalonia.Base.csproj", "{B09B78D8-9B26-48B0-9149-D64A2F120F3F}" EndProject @@ -11,7 +11,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Layout", "src\Aval EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Windows", "Windows", "{B39A8919-9F95-48FE-AD7B-76E08B509888}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Win32", "src\Windows\Avalonia.Win32\Avalonia.Win32.csproj", "{811A76CF-1CF6-440F-963B-BBE31BD72A82}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Win32", "src\Windows\Avalonia.Win32\Avalonia.Win32.csproj", "{811A76CF-1CF6-440F-963B-BBE31BD72A82}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Direct2D1", "src\Windows\Avalonia.Direct2D1\Avalonia.Direct2D1.csproj", "{3E908F67-5543-4879-A1DC-08EACE79B3CD}" EndProject @@ -362,6 +362,7 @@ Global {811A76CF-1CF6-440F-963B-BBE31BD72A82}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU {811A76CF-1CF6-440F-963B-BBE31BD72A82}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU {811A76CF-1CF6-440F-963B-BBE31BD72A82}.Debug|NetCoreOnly.ActiveCfg = Debug|Any CPU + {811A76CF-1CF6-440F-963B-BBE31BD72A82}.Debug|NetCoreOnly.Build.0 = Debug|Any CPU {811A76CF-1CF6-440F-963B-BBE31BD72A82}.Debug|x86.ActiveCfg = Debug|Any CPU {811A76CF-1CF6-440F-963B-BBE31BD72A82}.Debug|x86.Build.0 = Debug|Any CPU {811A76CF-1CF6-440F-963B-BBE31BD72A82}.Release|Any CPU.ActiveCfg = Release|Any CPU From 320265139eccd16759f5cded2c99e91f6b4eb161 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Sun, 18 Feb 2018 21:11:45 +0100 Subject: [PATCH 14/25] Include Avalonia.Win32 in NetCoreOnly release build. --- Avalonia.sln | 1 + 1 file changed, 1 insertion(+) diff --git a/Avalonia.sln b/Avalonia.sln index 5855edba5a..88914fe188 100644 --- a/Avalonia.sln +++ b/Avalonia.sln @@ -372,6 +372,7 @@ Global {811A76CF-1CF6-440F-963B-BBE31BD72A82}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU {811A76CF-1CF6-440F-963B-BBE31BD72A82}.Release|iPhoneSimulator.Build.0 = Release|Any CPU {811A76CF-1CF6-440F-963B-BBE31BD72A82}.Release|NetCoreOnly.ActiveCfg = Release|Any CPU + {811A76CF-1CF6-440F-963B-BBE31BD72A82}.Release|NetCoreOnly.Build.0 = Release|Any CPU {811A76CF-1CF6-440F-963B-BBE31BD72A82}.Release|x86.ActiveCfg = Release|Any CPU {811A76CF-1CF6-440F-963B-BBE31BD72A82}.Release|x86.Build.0 = Release|Any CPU {3E908F67-5543-4879-A1DC-08EACE79B3CD}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU From 4f3ad17a0dad16ec212744ba82cae31edbeb4e4d Mon Sep 17 00:00:00 2001 From: Jess Date: Sun, 25 Feb 2018 15:51:06 +0900 Subject: [PATCH 15/25] updated README.md with Open Collective badges and icons --- readme.md | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/readme.md b/readme.md index f074faa2c4..5a5d40c984 100644 --- a/readme.md +++ b/readme.md @@ -2,9 +2,9 @@ # Avalonia -| Gitter Chat | Windows Build Status | Linux/Mac Build Status | -|---|---|---| -| [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/AvaloniaUI/Avalonia?utm_campaign=pr-badge&utm_content=badge&utm_medium=badge&utm_source=badge) | [![Build status](https://ci.appveyor.com/api/projects/status/hubk3k0w9idyibfg/branch/master?svg=true)](https://ci.appveyor.com/project/AvaloniaUI/Avalonia/branch/master) | [![Build Status](https://travis-ci.org/AvaloniaUI/Avalonia.svg?branch=master)](https://travis-ci.org/AvaloniaUI/Avalonia) | +| Gitter Chat | Windows Build Status | Linux/Mac Build Status | Open Collective | +|---|---|---|---| +| [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/AvaloniaUI/Avalonia?utm_campaign=pr-badge&utm_content=badge&utm_medium=badge&utm_source=badge) | [![Build status](https://ci.appveyor.com/api/projects/status/hubk3k0w9idyibfg/branch/master?svg=true)](https://ci.appveyor.com/project/AvaloniaUI/Avalonia/branch/master) | [![Build Status](https://travis-ci.org/AvaloniaUI/Avalonia.svg?branch=master)](https://travis-ci.org/AvaloniaUI/Avalonia) | [![Backers on Open Collective](https://opencollective.com/Avalonia/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/Avalonia/sponsors/badge.svg)](#sponsors) | ## About @@ -48,3 +48,33 @@ See the [build instructions here](http://avaloniaui.net/contributing/build). ## Contributing Please read the [contribution guidelines](http://avaloniaui.net/contributing/contributing) before submitting a pull request. + +### Contributors + +This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)]. + + + +### Backers + +Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/Avalonia#backer)] + + + + +### Sponsors + +Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/Avalonia#sponsor)] + + + + + + + + + + + + + From 487f3eb10ec6130c031581a53773f5c4211c2f37 Mon Sep 17 00:00:00 2001 From: lindexi Date: Sun, 25 Feb 2018 20:21:41 +0800 Subject: [PATCH 16/25] check action is null If the user give the null to InvokeAsync, what is his intention --- src/Avalonia.Base/Threading/Dispatcher.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Avalonia.Base/Threading/Dispatcher.cs b/src/Avalonia.Base/Threading/Dispatcher.cs index 7d29a4f969..cf7acb3e8a 100644 --- a/src/Avalonia.Base/Threading/Dispatcher.cs +++ b/src/Avalonia.Base/Threading/Dispatcher.cs @@ -81,12 +81,14 @@ namespace Avalonia.Threading /// public Task InvokeAsync(Action action, DispatcherPriority priority = DispatcherPriority.Normal) { + Contract.Requires(action != null); return _jobRunner?.InvokeAsync(action, priority); } /// public void Post(Action action, DispatcherPriority priority = DispatcherPriority.Normal) { + Contract.Requires(action != null); _jobRunner?.Post(action, priority); } From f559f0b24057c8e75b2f5fffe029c2c674e7562a Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Sun, 25 Feb 2018 22:11:56 +0100 Subject: [PATCH 17/25] Merge WinFormsWin32Platform in Win32Platform. --- src/Windows/Avalonia.Win32/Win32Platform.cs | 38 ++++++++++++++- .../Avalonia.Win32/WinFormsWin32Platform.cs | 47 ------------------- 2 files changed, 37 insertions(+), 48 deletions(-) delete mode 100644 src/Windows/Avalonia.Win32/WinFormsWin32Platform.cs diff --git a/src/Windows/Avalonia.Win32/Win32Platform.cs b/src/Windows/Avalonia.Win32/Win32Platform.cs index a490e59cb7..4e1ba618a8 100644 --- a/src/Windows/Avalonia.Win32/Win32Platform.cs +++ b/src/Windows/Avalonia.Win32/Win32Platform.cs @@ -16,6 +16,7 @@ using Avalonia.Win32.Interop; using Avalonia.Controls; using Avalonia.Rendering; using Avalonia.Threading; +using System.IO; #if NETSTANDARD using Win32Exception = Avalonia.Win32.NetStandard.AvaloniaWin32Exception; #else @@ -40,7 +41,7 @@ namespace Avalonia namespace Avalonia.Win32 { - partial class Win32Platform : IPlatformThreadingInterface, IPlatformSettings, IWindowingPlatform, IPlatformIconLoader + class Win32Platform : IPlatformThreadingInterface, IPlatformSettings, IWindowingPlatform, IPlatformIconLoader { private static readonly Win32Platform s_instance = new Win32Platform(); private static uint _uiThread; @@ -205,5 +206,40 @@ namespace Avalonia.Win32 { return new PopupImpl(); } + + public IWindowIconImpl LoadIcon(string fileName) + { + using (var stream = File.OpenRead(fileName)) + { + return CreateIconImpl(stream); + } + } + + public IWindowIconImpl LoadIcon(Stream stream) + { + return CreateIconImpl(stream); + } + + public IWindowIconImpl LoadIcon(IBitmapImpl bitmap) + { + using (var memoryStream = new MemoryStream()) + { + bitmap.Save(memoryStream); + return new IconImpl(new System.Drawing.Bitmap(memoryStream)); + } + } + + private static IconImpl CreateIconImpl(Stream stream) + { + try + { + return new IconImpl(new System.Drawing.Icon(stream)); + } + catch (ArgumentException) + { + return new IconImpl(new System.Drawing.Bitmap(stream)); + } + } + } } diff --git a/src/Windows/Avalonia.Win32/WinFormsWin32Platform.cs b/src/Windows/Avalonia.Win32/WinFormsWin32Platform.cs deleted file mode 100644 index ec666e1f37..0000000000 --- a/src/Windows/Avalonia.Win32/WinFormsWin32Platform.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Avalonia.Platform; - -namespace Avalonia.Win32 -{ - partial class Win32Platform - { - public IWindowIconImpl LoadIcon(string fileName) - { - using (var stream = File.OpenRead(fileName)) - { - return CreateImpl(stream); - } - } - - public IWindowIconImpl LoadIcon(Stream stream) - { - return CreateImpl(stream); - } - - public IWindowIconImpl LoadIcon(IBitmapImpl bitmap) - { - using (var memoryStream = new MemoryStream()) - { - bitmap.Save(memoryStream); - return new IconImpl(new System.Drawing.Bitmap(memoryStream)); - } - } - - private static IconImpl CreateImpl(Stream stream) - { - try - { - return new IconImpl(new System.Drawing.Icon(stream)); - } - catch (ArgumentException) - { - return new IconImpl(new System.Drawing.Bitmap(stream)); - } - } - } -} From 604700e9e795130354d13b3af7dc421c58a9702e Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Mon, 26 Feb 2018 20:01:39 +0300 Subject: [PATCH 18/25] Fixed iOS --- build/Rx.props | 1 - samples/ControlCatalog.iOS/ControlCatalog.iOS.csproj | 5 ++--- src/iOS/Avalonia.iOS/EmulatedFramebuffer.cs | 9 +++++++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/build/Rx.props b/build/Rx.props index 323026f5e2..7078e31195 100644 --- a/build/Rx.props +++ b/build/Rx.props @@ -5,6 +5,5 @@ - diff --git a/samples/ControlCatalog.iOS/ControlCatalog.iOS.csproj b/samples/ControlCatalog.iOS/ControlCatalog.iOS.csproj index 77f38d3bd7..c1c5cdcaf7 100644 --- a/samples/ControlCatalog.iOS/ControlCatalog.iOS.csproj +++ b/samples/ControlCatalog.iOS/ControlCatalog.iOS.csproj @@ -170,15 +170,14 @@ Avalonia.Themes.Default - {D2D3083-71DD-4CC9-8907-39A0D86FB322} + {7d2d3083-71dd-4cc9-8907-39a0d86fb322} Avalonia.Skia - false - false {d0a739b9-3c68-4ba6-a328-41606954b6bd} ControlCatalog + \ No newline at end of file diff --git a/src/iOS/Avalonia.iOS/EmulatedFramebuffer.cs b/src/iOS/Avalonia.iOS/EmulatedFramebuffer.cs index 58cf6edd78..517b372ba4 100644 --- a/src/iOS/Avalonia.iOS/EmulatedFramebuffer.cs +++ b/src/iOS/Avalonia.iOS/EmulatedFramebuffer.cs @@ -16,11 +16,15 @@ namespace Avalonia.iOS /// class EmulatedFramebuffer : ILockedFramebuffer { + private nfloat _viewWidth; + private nfloat _viewHeight; public EmulatedFramebuffer(UIView view) { var factor = (int) UIScreen.MainScreen.Scale; var frame = view.Frame; + _viewWidth = frame.Width; + _viewHeight = frame.Height; Width = (int) frame.Width * factor; Height = (int) frame.Height * factor; RowBytes = Width * 4; @@ -41,9 +45,9 @@ namespace Avalonia.iOS using (var context = UIGraphics.GetCurrentContext()) { // flip the image for CGContext.DrawImage - context.TranslateCTM(0, Height); + context.TranslateCTM(0, _viewHeight); context.ScaleCTM(1, -1); - context.DrawImage(new CGRect(0, 0, Width, Height), image); + context.DrawImage(new CGRect(0, 0, _viewWidth, _viewHeight), image); } Marshal.FreeHGlobal(Address); Address = IntPtr.Zero; @@ -57,3 +61,4 @@ namespace Avalonia.iOS public PixelFormat Format { get; } } } + From e5a3370acd47f4570d2ba0a2b472de1aa923938f Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Tue, 27 Feb 2018 00:01:50 +0300 Subject: [PATCH 19/25] Fixes #1405 --- src/OSX/Avalonia.MonoMac/ClipboardImpl.cs | 31 +++++++++++++++++++++ src/OSX/Avalonia.MonoMac/MonoMacPlatform.cs | 2 ++ 2 files changed, 33 insertions(+) create mode 100644 src/OSX/Avalonia.MonoMac/ClipboardImpl.cs diff --git a/src/OSX/Avalonia.MonoMac/ClipboardImpl.cs b/src/OSX/Avalonia.MonoMac/ClipboardImpl.cs new file mode 100644 index 0000000000..f7b98c0c1f --- /dev/null +++ b/src/OSX/Avalonia.MonoMac/ClipboardImpl.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Avalonia.Input.Platform; +using MonoMac.AppKit; + +namespace Avalonia.MonoMac +{ + class ClipboardImpl : IClipboard + { + public Task GetTextAsync() + { + return Task.FromResult(NSPasteboard.GeneralPasteboard.GetStringForType(NSPasteboard.NSStringType)); + } + + public Task SetTextAsync(string text) + { + NSPasteboard.GeneralPasteboard.ClearContents(); + if (text != null) + NSPasteboard.GeneralPasteboard.SetStringForType(text, NSPasteboard.NSStringType); + return Task.CompletedTask; + } + + public async Task ClearAsync() + { + NSPasteboard.GeneralPasteboard.ClearContents(); + } + } +} + diff --git a/src/OSX/Avalonia.MonoMac/MonoMacPlatform.cs b/src/OSX/Avalonia.MonoMac/MonoMacPlatform.cs index a6b1f1d5b4..5907459459 100644 --- a/src/OSX/Avalonia.MonoMac/MonoMacPlatform.cs +++ b/src/OSX/Avalonia.MonoMac/MonoMacPlatform.cs @@ -3,6 +3,7 @@ using System.Threading; using Avalonia.Controls; using Avalonia.Controls.Platform; using Avalonia.Input; +using Avalonia.Input.Platform; using Avalonia.Platform; using Avalonia.Rendering; using MonoMac.AppKit; @@ -32,6 +33,7 @@ namespace Avalonia.MonoMac .Bind().ToConstant(this) .Bind().ToConstant(this) .Bind().ToSingleton() + .Bind().ToSingleton() .Bind().ToConstant(s_renderLoop) .Bind().ToConstant(PlatformThreadingInterface.Instance); } From 20e7db8587460f20b3096db165e6555ccb91b58d Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Tue, 27 Feb 2018 00:08:23 +0300 Subject: [PATCH 20/25] Bump version so nightly builds will be treated as newer ones --- parameters.cake | 2 +- src/Shared/SharedAssemblyInfo.cs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/parameters.cake b/parameters.cake index c727b3107f..e224cce151 100644 --- a/parameters.cake +++ b/parameters.cake @@ -97,7 +97,7 @@ public class Parameters else { // Use AssemblyVersion with Build as version - Version += "-build" + context.EnvironmentVariable("APPVEYOR_BUILD_NUMBER") + "-alpha"; + Version += "-build" + context.EnvironmentVariable("APPVEYOR_BUILD_NUMBER") + "-beta"; } } diff --git a/src/Shared/SharedAssemblyInfo.cs b/src/Shared/SharedAssemblyInfo.cs index 98047b4cc8..44ebef4cd2 100644 --- a/src/Shared/SharedAssemblyInfo.cs +++ b/src/Shared/SharedAssemblyInfo.cs @@ -14,6 +14,6 @@ using System.Runtime.CompilerServices; [assembly: AssemblyTrademark("")] [assembly: NeutralResourcesLanguage("en")] -[assembly: AssemblyVersion("0.6.0")] -[assembly: AssemblyFileVersion("0.6.0")] -[assembly: AssemblyInformationalVersion("0.6.0")] +[assembly: AssemblyVersion("0.6.2")] +[assembly: AssemblyFileVersion("0.6.2")] +[assembly: AssemblyInformationalVersion("0.6.2")] From 6e1c7e37a84270fed27ebf86c2ba38620969175e Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Tue, 27 Feb 2018 19:59:40 +0300 Subject: [PATCH 21/25] Fixed Styles preview substitute --- src/Avalonia.DesignerSupport/DesignWindowLoader.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.DesignerSupport/DesignWindowLoader.cs b/src/Avalonia.DesignerSupport/DesignWindowLoader.cs index 9ad2a216b4..5235beee0f 100644 --- a/src/Avalonia.DesignerSupport/DesignWindowLoader.cs +++ b/src/Avalonia.DesignerSupport/DesignWindowLoader.cs @@ -54,7 +54,7 @@ namespace Avalonia.DesignerSupport } }; } - if (loaded is Application) + else if (loaded is Application) control = new TextBlock {Text = "Application can't be previewed in design view"}; else control = (Control) loaded; @@ -73,4 +73,4 @@ namespace Avalonia.DesignerSupport return window; } } -} \ No newline at end of file +} From f94381acac60e9c00695175f623fcbab51096b23 Mon Sep 17 00:00:00 2001 From: sdoroff Date: Wed, 28 Feb 2018 15:41:13 -0500 Subject: [PATCH 22/25] Adds Methods Weakly Subscribe to CollectionChange --- .../Collections/AvaloniaListExtensions.cs | 26 +++- .../NotifyCollectionChangedExtensions.cs | 127 ++++++++++++++++++ 2 files changed, 148 insertions(+), 5 deletions(-) create mode 100644 src/Avalonia.Base/Collections/NotifyCollectionChangedExtensions.cs diff --git a/src/Avalonia.Base/Collections/AvaloniaListExtensions.cs b/src/Avalonia.Base/Collections/AvaloniaListExtensions.cs index 54cd132b95..b27b06a277 100644 --- a/src/Avalonia.Base/Collections/AvaloniaListExtensions.cs +++ b/src/Avalonia.Base/Collections/AvaloniaListExtensions.cs @@ -34,14 +34,18 @@ namespace Avalonia.Collections /// /// An action called when the collection is reset. /// + /// + /// Indicates if a weak subscription should be used to track changes to the collection. + /// /// A disposable used to terminate the subscription. public static IDisposable ForEachItem( this IAvaloniaReadOnlyList collection, Action added, Action removed, - Action reset) + Action reset, + bool weakSubscription = false) { - return collection.ForEachItem((_, i) => added(i), (_, i) => removed(i), reset); + return collection.ForEachItem((_, i) => added(i), (_, i) => removed(i), reset, weakSubscription); } /// @@ -63,12 +67,16 @@ namespace Avalonia.Collections /// An action called when the collection is reset. This will be followed by calls to /// for each item present in the collection after the reset. /// + /// + /// Indicates if a weak subscription should be used to track changes to the collection. + /// /// A disposable used to terminate the subscription. public static IDisposable ForEachItem( this IAvaloniaReadOnlyList collection, Action added, Action removed, - Action reset) + Action reset, + bool weakSubscription = false) { void Add(int index, IList items) { @@ -118,9 +126,17 @@ namespace Avalonia.Collections }; Add(0, (IList)collection); - collection.CollectionChanged += handler; - return Disposable.Create(() => collection.CollectionChanged -= handler); + if (weakSubscription) + { + return collection.WeakSubscribe(handler); + } + else + { + collection.CollectionChanged += handler; + + return Disposable.Create(() => collection.CollectionChanged -= handler); + } } public static IAvaloniaReadOnlyList CreateDerivedList( diff --git a/src/Avalonia.Base/Collections/NotifyCollectionChangedExtensions.cs b/src/Avalonia.Base/Collections/NotifyCollectionChangedExtensions.cs new file mode 100644 index 0000000000..d295cb91ce --- /dev/null +++ b/src/Avalonia.Base/Collections/NotifyCollectionChangedExtensions.cs @@ -0,0 +1,127 @@ +// 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; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Reactive; +using System.Reactive.Disposables; +using System.Reactive.Linq; +using System.Reactive.Subjects; +using Avalonia.Utilities; + +namespace Avalonia.Collections +{ + public static class NotifyCollectionChangedExtensions + { + /// + /// Gets a weak observable for the CollectionChanged event. + /// + /// The collection. + /// An observable. + public static IObservable GetWeakCollectionChangedObservable( + this INotifyCollectionChanged collection) + { + Contract.Requires(collection != null); + + return new WeakCollectionChangedObservable(new WeakReference(collection)); + } + + /// + /// Subcribes to the CollectionChanged event using a weak subscription. + /// + /// The collection. + /// + /// An action called when the collection event is raised. + /// + /// A disposable used to terminate the subscription. + public static IDisposable WeakSubscribe( + this INotifyCollectionChanged collection, + NotifyCollectionChangedEventHandler handler) + { + Contract.Requires(collection != null); + Contract.Requires(handler != null); + + return + collection.GetWeakCollectionChangedObservable() + .Subscribe(e => handler.Invoke(collection, e)); + } + + /// + /// Subcribes to the CollectionChanged event using a weak subscription. + /// + /// The collection. + /// + /// An action called when the collection event is raised. + /// + /// A disposable used to terminate the subscription. + public static IDisposable WeakSubscribe( + this INotifyCollectionChanged collection, + Action handler) + { + Contract.Requires(collection != null); + Contract.Requires(handler != null); + + return + collection.GetWeakCollectionChangedObservable() + .Subscribe(handler); + } + + private class WeakCollectionChangedObservable : ObservableBase, + IWeakSubscriber + { + private WeakReference _sourceReference; + private readonly Subject _changed = new Subject(); + + private int _count; + + public WeakCollectionChangedObservable(WeakReference source) + { + _sourceReference = source; + } + + public void OnEvent(object sender, NotifyCollectionChangedEventArgs e) + { + _changed.OnNext(e); + } + + protected override IDisposable SubscribeCore(IObserver observer) + { + if (_sourceReference.TryGetTarget(out INotifyCollectionChanged instance)) + { + if (_count++ == 0) + { + WeakSubscriptionManager.Subscribe( + instance, + nameof(instance.CollectionChanged), + this); + } + + return Observable.Using(() => Disposable.Create(DecrementCount), _ => _changed) + .Subscribe(observer); + } + else + { + _changed.OnCompleted(); + observer.OnCompleted(); + return Disposable.Empty; + } + } + + private void DecrementCount() + { + if (--_count == 0) + { + if (_sourceReference.TryGetTarget(out INotifyCollectionChanged instance)) + { + WeakSubscriptionManager.Unsubscribe( + instance, + nameof(instance.CollectionChanged), + this); + } + } + } + } + } +} From 6103bab8606a04588d4ff232250076e9a4f344d4 Mon Sep 17 00:00:00 2001 From: sdoroff Date: Wed, 28 Feb 2018 15:41:56 -0500 Subject: [PATCH 23/25] Altered ItemsControl to use Weak CollectionChange Subscription --- src/Avalonia.Controls/ItemsControl.cs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/Avalonia.Controls/ItemsControl.cs b/src/Avalonia.Controls/ItemsControl.cs index 4366de1cd6..6a26e29187 100644 --- a/src/Avalonia.Controls/ItemsControl.cs +++ b/src/Avalonia.Controls/ItemsControl.cs @@ -1,6 +1,7 @@ // 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; using System.Collections.Generic; using System.Collections.Specialized; @@ -54,6 +55,7 @@ namespace Avalonia.Controls private IEnumerable _items = new AvaloniaList(); private IItemContainerGenerator _itemContainerGenerator; + private IDisposable _itemsCollectionChangedSubscription; /// /// Initializes static members of the class. @@ -326,12 +328,8 @@ namespace Avalonia.Controls /// The event args. protected virtual void ItemsChanged(AvaloniaPropertyChangedEventArgs e) { - var incc = e.OldValue as INotifyCollectionChanged; - - if (incc != null) - { - incc.CollectionChanged -= ItemsCollectionChanged; - } + _itemsCollectionChangedSubscription?.Dispose(); + _itemsCollectionChangedSubscription = null; var oldValue = e.OldValue as IEnumerable; var newValue = e.NewValue as IEnumerable; @@ -428,7 +426,7 @@ namespace Avalonia.Controls if (incc != null) { - incc.CollectionChanged += ItemsCollectionChanged; + _itemsCollectionChangedSubscription = incc.WeakSubscribe(ItemsCollectionChanged); } } From 5fecddef513878c8e335a3e61317b456ef076d36 Mon Sep 17 00:00:00 2001 From: Vinicius de Melo Rocha Date: Thu, 1 Mar 2018 08:18:16 -0300 Subject: [PATCH 24/25] Update README.md with new contributing link --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 5a5d40c984..eeee39dabe 100644 --- a/readme.md +++ b/readme.md @@ -51,7 +51,7 @@ Please read the [contribution guidelines](http://avaloniaui.net/contributing/con ### Contributors -This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)]. +This project exists thanks to all the people who contribute. [[Contribute](http://avaloniaui.net/contributing/contributing)]. From 27ab312be5b7e76efbba0d5245f29d4ee77bb5d7 Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Thu, 1 Mar 2018 19:59:15 +0300 Subject: [PATCH 25/25] Fixed nuget deps --- build/System.Drawing.Common.props | 5 +++++ packages.cake | 4 ++-- src/OSX/Avalonia.MonoMac/Avalonia.MonoMac.csproj | 3 --- src/Windows/Avalonia.Win32/Avalonia.Win32.csproj | 6 ++---- 4 files changed, 9 insertions(+), 9 deletions(-) create mode 100644 build/System.Drawing.Common.props diff --git a/build/System.Drawing.Common.props b/build/System.Drawing.Common.props new file mode 100644 index 0000000000..a568152bbd --- /dev/null +++ b/build/System.Drawing.Common.props @@ -0,0 +1,5 @@ + + + + + diff --git a/packages.cake b/packages.cake index 134340f459..17411aef4c 100644 --- a/packages.cake +++ b/packages.cake @@ -370,10 +370,10 @@ public class Packages new NuGetPackSettings() { Id = "Avalonia.Win32", - Dependencies = new [] + Dependencies = new DependencyBuilder(this) { new NuSpecDependency() { Id = "Avalonia", Version = parameters.Version } - }, + }.Deps(new string[]{null}, "System.Drawing.Common"), Files = new [] { new NuSpecContent { Source = "Avalonia.Win32/bin/" + parameters.DirSuffix + "/netstandard2.0/Avalonia.Win32.dll", Target = "lib/netstandard2.0" } diff --git a/src/OSX/Avalonia.MonoMac/Avalonia.MonoMac.csproj b/src/OSX/Avalonia.MonoMac/Avalonia.MonoMac.csproj index 3a279c05fb..5f6be91571 100644 --- a/src/OSX/Avalonia.MonoMac/Avalonia.MonoMac.csproj +++ b/src/OSX/Avalonia.MonoMac/Avalonia.MonoMac.csproj @@ -8,9 +8,6 @@ - - - diff --git a/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj b/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj index e055f3c20f..5f26e4ad3e 100644 --- a/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj +++ b/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj @@ -13,7 +13,5 @@ - - - - \ No newline at end of file + +