diff --git a/Avalonia.sln b/Avalonia.sln index 9670327d67..0bae725d33 100644 --- a/Avalonia.sln +++ b/Avalonia.sln @@ -135,7 +135,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Linux", "Linux", "{86C53C40 EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.LinuxFramebuffer", "src\Linux\Avalonia.LinuxFramebuffer\Avalonia.LinuxFramebuffer.csproj", "{854568D5-13D1-4B4F-B50D-534DC7EFD3C9}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Win32.Interop", "src\Windows\Avalonia.Win32.Interop\Avalonia.Win32.Interop.csproj", "{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Win32.Interoperability", "src\Windows\Avalonia.Win32.Interoperability\Avalonia.Win32.Interoperability.csproj", "{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Skia.RenderTests", "tests\Avalonia.Skia.RenderTests\Avalonia.Skia.RenderTests.csproj", "{E1582370-37B3-403C-917F-8209551B1634}" EndProject @@ -251,6 +251,7 @@ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Generators.Sandbox", "samples\Generators.Sandbox\Generators.Sandbox.csproj", "{A82AD1BC-EBE6-4FC3-A13B-D52A50297533}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AppWithoutLifetime", "samples\AppWithoutLifetime\AppWithoutLifetime.csproj", "{F8928267-688E-4A51-989C-612A72446D33}" +EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SafeAreaDemo", "samples\SafeAreaDemo\SafeAreaDemo.csproj", "{6B60A970-D5D2-49C2-8BAB-F9C7973B74B6}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SafeAreaDemo.Android", "samples\SafeAreaDemo.Android\SafeAreaDemo.Android.csproj", "{22E3BC08-EAF7-4889-BDC4-B4D3046C4E2D}" diff --git a/dirs.proj b/dirs.proj index d29aa61fcb..120212bd9f 100644 --- a/dirs.proj +++ b/dirs.proj @@ -14,11 +14,11 @@ + - - + + - diff --git a/nukebuild/_build.csproj b/nukebuild/_build.csproj index 8999b7ca76..30e1200220 100644 --- a/nukebuild/_build.csproj +++ b/nukebuild/_build.csproj @@ -35,6 +35,12 @@ + + + + dirs.proj + + diff --git a/samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj b/samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj index c6405dabb6..2c47effa38 100644 --- a/samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj +++ b/samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj @@ -4,10 +4,17 @@ Exe net461 x64 + true + ../ControlCatalog.NetCore/app.manifest + + + + + diff --git a/samples/ControlCatalog.Desktop/Program.cs b/samples/ControlCatalog.Desktop/Program.cs index 4d28f15e2c..eeb2095201 100644 --- a/samples/ControlCatalog.Desktop/Program.cs +++ b/samples/ControlCatalog.Desktop/Program.cs @@ -3,6 +3,8 @@ using System.Linq; using Avalonia; using Avalonia.Controls; using Avalonia.Platform; +using ControlCatalog.NetCore; +using ControlCatalog.Pages; namespace ControlCatalog { @@ -18,6 +20,15 @@ namespace ControlCatalog public static AppBuilder BuildAvaloniaApp() => AppBuilder.Configure() .LogToTrace() + .AfterSetup(builder => + { + builder.Instance!.AttachDevTools(new Avalonia.Diagnostics.DevToolsOptions() + { + StartupScreenIndex = 1, + }); + + EmbedSample.Implementation = new EmbedSampleWin(); + }) .UsePlatformDetect(); private static void ConfigureAssetAssembly(AppBuilder builder) diff --git a/samples/interop/WindowsInteropTest/EmbedToWinFormsDemo.Designer.cs b/samples/interop/WindowsInteropTest/EmbedToWinFormsDemo.Designer.cs index b5dccffd4d..d8b0724520 100644 --- a/samples/interop/WindowsInteropTest/EmbedToWinFormsDemo.Designer.cs +++ b/samples/interop/WindowsInteropTest/EmbedToWinFormsDemo.Designer.cs @@ -1,4 +1,4 @@ -using Avalonia.Win32.Embedding; +using Avalonia.Win32.Interoperability; namespace WindowsInteropTest { @@ -116,4 +116,4 @@ namespace WindowsInteropTest private System.Windows.Forms.GroupBox groupBox2; private WinFormsAvaloniaControlHost avaloniaHost; } -} \ No newline at end of file +} diff --git a/samples/interop/WindowsInteropTest/EmbedToWinFormsDemo.cs b/samples/interop/WindowsInteropTest/EmbedToWinFormsDemo.cs index e6603a817b..d37ed13559 100644 --- a/samples/interop/WindowsInteropTest/EmbedToWinFormsDemo.cs +++ b/samples/interop/WindowsInteropTest/EmbedToWinFormsDemo.cs @@ -1,35 +1,14 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Data; -using System.Drawing; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Forms; -using Avalonia.Controls; -using Avalonia.Rendering; -using Avalonia.VisualTree; +using System.Windows.Forms; using ControlCatalog; namespace WindowsInteropTest { public partial class EmbedToWinFormsDemo : Form { - private readonly IRenderer _renderer; - public EmbedToWinFormsDemo() { InitializeComponent(); avaloniaHost.Content = new MainView(); - _renderer = ((TopLevel)avaloniaHost.Content.GetVisualRoot()).Renderer; - _renderer.Start(); - } - - protected override void OnClosed(EventArgs e) - { - _renderer.Stop(); - base.OnClosed(e); } } } diff --git a/samples/interop/WindowsInteropTest/EmbedToWpfDemo.xaml b/samples/interop/WindowsInteropTest/EmbedToWpfDemo.xaml deleted file mode 100644 index 1d8dc32a69..0000000000 --- a/samples/interop/WindowsInteropTest/EmbedToWpfDemo.xaml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/samples/interop/WindowsInteropTest/EmbedToWpfDemo.xaml.cs b/samples/interop/WindowsInteropTest/EmbedToWpfDemo.xaml.cs deleted file mode 100644 index e1476106ee..0000000000 --- a/samples/interop/WindowsInteropTest/EmbedToWpfDemo.xaml.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; -using Avalonia; -using Avalonia.Controls; -using Avalonia.Rendering; -using Avalonia.VisualTree; -using ControlCatalog; -using Window = System.Windows.Window; - -namespace WindowsInteropTest -{ - /// - /// Interaction logic for EmbedToWpfDemo.xaml - /// - public partial class EmbedToWpfDemo : Window - { - private IRenderer _renderer; - public EmbedToWpfDemo() - { - InitializeComponent(); - var view = new MainView(); - Host.Content = view; - var tl = (TopLevel)view.GetVisualRoot(); - tl.AttachDevTools(); - _renderer = tl.Renderer; - _renderer.Start(); - var btn = (Avalonia.Controls.Button) RightBtn.Content; - btn.Click += delegate - { - btn.Content += "!"; - }; - - } - - protected override void OnClosed(EventArgs e) - { - _renderer.Stop(); - base.OnClosed(e); - } - } -} diff --git a/samples/interop/WindowsInteropTest/Program.cs b/samples/interop/WindowsInteropTest/Program.cs index c2d30c67bb..4ebb88642b 100644 --- a/samples/interop/WindowsInteropTest/Program.cs +++ b/samples/interop/WindowsInteropTest/Program.cs @@ -16,14 +16,9 @@ namespace WindowsInteropTest System.Windows.Forms.Application.SetCompatibleTextRenderingDefault(false); AppBuilder.Configure() .UseWin32() - .UseDirect2D1() - .With(new Win32PlatformOptions - { - UseWindowsUIComposition = false, - ShouldRenderOnUIThread = true // necessary for WPF - }) + .UseSkia() .SetupWithoutStarting(); - System.Windows.Forms.Application.Run(new SelectorForm()); + System.Windows.Forms.Application.Run(new EmbedToWinFormsDemo()); } } } diff --git a/samples/interop/WindowsInteropTest/SelectorForm.Designer.cs b/samples/interop/WindowsInteropTest/SelectorForm.Designer.cs deleted file mode 100644 index 7cf402913e..0000000000 --- a/samples/interop/WindowsInteropTest/SelectorForm.Designer.cs +++ /dev/null @@ -1,76 +0,0 @@ -namespace WindowsInteropTest -{ - partial class SelectorForm - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { - this.btnEmbedToWinForms = new System.Windows.Forms.Button(); - this.btnEmbedToWpf = new System.Windows.Forms.Button(); - this.SuspendLayout(); - // - // btnEmbedToWinForms - // - this.btnEmbedToWinForms.Location = new System.Drawing.Point(12, 12); - this.btnEmbedToWinForms.Name = "btnEmbedToWinForms"; - this.btnEmbedToWinForms.Size = new System.Drawing.Size(201, 86); - this.btnEmbedToWinForms.TabIndex = 0; - this.btnEmbedToWinForms.Text = "Embed to WinForms"; - this.btnEmbedToWinForms.UseVisualStyleBackColor = true; - this.btnEmbedToWinForms.Click += new System.EventHandler(this.btnEmbedToWinForms_Click); - // - // btnEmbedToWpf - // - this.btnEmbedToWpf.Location = new System.Drawing.Point(219, 12); - this.btnEmbedToWpf.Name = "btnEmbedToWpf"; - this.btnEmbedToWpf.Size = new System.Drawing.Size(201, 86); - this.btnEmbedToWpf.TabIndex = 1; - this.btnEmbedToWpf.Text = "Embed to WPF"; - this.btnEmbedToWpf.UseVisualStyleBackColor = true; - this.btnEmbedToWpf.Click += new System.EventHandler(this.btnEmbedToWpf_Click); - // - // SelectorForm - // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(432, 284); - this.Controls.Add(this.btnEmbedToWpf); - this.Controls.Add(this.btnEmbedToWinForms); - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; - this.MaximizeBox = false; - this.Name = "SelectorForm"; - this.Text = "Interop"; - this.ResumeLayout(false); - - } - - #endregion - - private System.Windows.Forms.Button btnEmbedToWinForms; - private System.Windows.Forms.Button btnEmbedToWpf; - } -} - diff --git a/samples/interop/WindowsInteropTest/SelectorForm.cs b/samples/interop/WindowsInteropTest/SelectorForm.cs deleted file mode 100644 index 6430694f79..0000000000 --- a/samples/interop/WindowsInteropTest/SelectorForm.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Data; -using System.Drawing; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Forms; - -namespace WindowsInteropTest -{ - public partial class SelectorForm : Form - { - public SelectorForm() - { - InitializeComponent(); - } - - private void btnEmbedToWinForms_Click(object sender, EventArgs e) - { - new EmbedToWinFormsDemo().ShowDialog(this); - } - - private void btnEmbedToWpf_Click(object sender, EventArgs e) - { - new EmbedToWpfDemo().ShowDialog(); - } - } -} diff --git a/samples/interop/WindowsInteropTest/SelectorForm.resx b/samples/interop/WindowsInteropTest/SelectorForm.resx deleted file mode 100644 index 1af7de150c..0000000000 --- a/samples/interop/WindowsInteropTest/SelectorForm.resx +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/samples/interop/WindowsInteropTest/WindowsInteropTest.csproj b/samples/interop/WindowsInteropTest/WindowsInteropTest.csproj index 95f77f6df9..22387c5a05 100644 --- a/samples/interop/WindowsInteropTest/WindowsInteropTest.csproj +++ b/samples/interop/WindowsInteropTest/WindowsInteropTest.csproj @@ -1,15 +1,15 @@  WinExe - net461 - x64 + net461;net6.0-windows true true - + + diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs index ec6b3f7421..92444b9c07 100644 --- a/src/Avalonia.Controls/TopLevel.cs +++ b/src/Avalonia.Controls/TopLevel.cs @@ -391,7 +391,7 @@ namespace Avalonia.Controls /// An describing the window handle, or null if the handle /// could not be retrieved. /// - public IPlatformHandle? TryGetPlatformHandle() => ((IWindowBaseImpl?) PlatformImpl)?.Handle; + public IPlatformHandle? TryGetPlatformHandle() => (PlatformImpl as IWindowBaseImpl)?.Handle; /// /// Gets the renderer for the window. diff --git a/src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj b/src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj index 9d4b04d244..78da843f42 100644 --- a/src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj +++ b/src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj @@ -17,6 +17,7 @@ + diff --git a/src/Windows/Avalonia.Win32.Interop/WinForms/WinFormsAvaloniaControlHost.cs b/src/Windows/Avalonia.Win32.Interop/WinForms/WinFormsAvaloniaControlHost.cs deleted file mode 100644 index 8d73bde919..0000000000 --- a/src/Windows/Avalonia.Win32.Interop/WinForms/WinFormsAvaloniaControlHost.cs +++ /dev/null @@ -1,75 +0,0 @@ -using System; -using System.ComponentModel; -using System.Windows.Forms; -using Avalonia.Controls.Embedding; -using Avalonia.Input; -using Avalonia.VisualTree; -using Avalonia.Win32.Interop; -using WinFormsControl = System.Windows.Forms.Control; - -namespace Avalonia.Win32.Embedding -{ - [ToolboxItem(true)] - public class WinFormsAvaloniaControlHost : WinFormsControl - { - private readonly EmbeddableControlRoot _root = new EmbeddableControlRoot(); - - private IntPtr WindowHandle => ((WindowImpl) _root?.PlatformImpl)?.Handle?.Handle ?? IntPtr.Zero; - - public WinFormsAvaloniaControlHost() - { - SetStyle(ControlStyles.AllPaintingInWmPaint, true); - UnmanagedMethods.SetParent(WindowHandle, Handle); - _root.Prepare(); - if (_root.IsFocused) - _root.FocusManager.ClearFocus(); - _root.GotFocus += RootGotFocus; - - FixPosition(); - } - - public Avalonia.Controls.Control Content - { - get { return (Avalonia.Controls.Control)_root.Content; } - set { _root.Content = value; } - } - - protected override void Dispose(bool disposing) - { - if (disposing) - _root.Dispose(); - base.Dispose(disposing); - } - - private void RootGotFocus(object sender, Interactivity.RoutedEventArgs e) - { - UnmanagedMethods.SetFocus(WindowHandle); - } - - protected override void OnGotFocus(EventArgs e) - { - if (_root != null) - UnmanagedMethods.SetFocus(WindowHandle); - } - - - void FixPosition() - { - if (_root != null && Width > 0 && Height > 0) - UnmanagedMethods.MoveWindow(WindowHandle, 0, 0, Width, Height, true); - } - - - - protected override void OnResize(EventArgs e) - { - FixPosition(); - base.OnResize(e); - } - - protected override void OnPaint(PaintEventArgs e) - { - - } - } -} diff --git a/src/Windows/Avalonia.Win32.Interop/Wpf/CursorShim.cs b/src/Windows/Avalonia.Win32.Interop/Wpf/CursorShim.cs deleted file mode 100644 index 2ad6287689..0000000000 --- a/src/Windows/Avalonia.Win32.Interop/Wpf/CursorShim.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; -using System.Linq; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Runtime.Serialization; -using System.Windows.Input; - -namespace Avalonia.Win32.Interop.Wpf -{ - static class CursorShim - { - public static Cursor FromHCursor(IntPtr hcursor) - { - var field = typeof(Cursor).GetFields(BindingFlags.NonPublic | BindingFlags.Instance) - .FirstOrDefault(f => f.FieldType == typeof(SafeHandle)); - if (field == null) - return null; - var rv = (Cursor) FormatterServices.GetUninitializedObject(typeof(Cursor)); - field.SetValue(rv, new SafeHandleShim(hcursor)); - return rv; - } - - class SafeHandleShim : SafeHandle - { - public SafeHandleShim(IntPtr hcursor) : base(new IntPtr(-1), false) - { - this.handle = hcursor; - } - - protected override bool ReleaseHandle() => true; - - public override bool IsInvalid => false; - } - } -} diff --git a/src/Windows/Avalonia.Win32.Interop/Wpf/Direct2DImageSurface.cs b/src/Windows/Avalonia.Win32.Interop/Wpf/Direct2DImageSurface.cs deleted file mode 100644 index f900204504..0000000000 --- a/src/Windows/Avalonia.Win32.Interop/Wpf/Direct2DImageSurface.cs +++ /dev/null @@ -1,202 +0,0 @@ -using System; -using System.Runtime.InteropServices; -using System.Windows; -using System.Windows.Interop; -using Avalonia.Direct2D1; -using SharpDX.Direct2D1; -using SharpDX.Direct3D11; -using SharpDX.Direct3D9; -using SharpDX.DXGI; -using AlphaMode = SharpDX.Direct2D1.AlphaMode; -using Device = SharpDX.Direct3D11.Device; -using Format = SharpDX.DXGI.Format; -using Query = SharpDX.Direct3D11.Query; -using QueryType = SharpDX.Direct3D11.QueryType; -using RenderTarget = SharpDX.Direct2D1.RenderTarget; -using Surface = SharpDX.DXGI.Surface; -using Usage = SharpDX.Direct3D9.Usage; - -namespace Avalonia.Win32.Interop.Wpf -{ - class Direct2DImageSurface : IExternalDirect2DRenderTargetSurface, IDisposable - { - class SwapBuffer: IDisposable - { - private readonly Query _event; - private readonly SharpDX.Direct3D11.Resource _resource; - private readonly SharpDX.Direct3D11.Resource _sharedResource; - public SharpDX.Direct3D9.Surface Texture { get; } - public RenderTarget Target { get;} - public IntSize Size { get; } - - public SwapBuffer(IntSize size, Vector dpi) - { - int width = (int) size.Width; - int height = (int) size.Height; - _event = new Query(s_dxDevice, new QueryDescription {Type = QueryType.Event}); - using (var texture = new Texture2D(s_dxDevice, new Texture2DDescription - { - Width = width, - Height = height, - ArraySize = 1, - MipLevels = 1, - Format = Format.B8G8R8A8_UNorm, - Usage = ResourceUsage.Default, - SampleDescription = new SampleDescription(2, 0), - BindFlags = BindFlags.RenderTarget, - })) - using (var surface = texture.QueryInterface()) - - { - _resource = texture.QueryInterface(); - - Target = new RenderTarget(Direct2D1Platform.Direct2D1Factory, surface, - new RenderTargetProperties - { - DpiX = (float) dpi.X, - DpiY = (float) dpi.Y, - MinLevel = FeatureLevel.Level_10, - PixelFormat = new PixelFormat(Format.B8G8R8A8_UNorm, AlphaMode.Premultiplied), - - }); - } - using (var texture = new Texture2D(s_dxDevice, new Texture2DDescription - { - Width = width, - Height = height, - ArraySize = 1, - MipLevels = 1, - Format = Format.B8G8R8A8_UNorm, - Usage = ResourceUsage.Default, - SampleDescription = new SampleDescription(1, 0), - BindFlags = BindFlags.RenderTarget|BindFlags.ShaderResource, - OptionFlags = ResourceOptionFlags.Shared, - })) - using (var resource = texture.QueryInterface()) - { - _sharedResource = texture.QueryInterface(); - var handle = resource.SharedHandle; - using (var texture9 = new Texture(s_d3DDevice, texture.Description.Width, - texture.Description.Height, 1, - Usage.RenderTarget, SharpDX.Direct3D9.Format.A8R8G8B8, Pool.Default, ref handle)) - Texture = texture9.GetSurfaceLevel(0); - } - Size = size; - } - - public void Dispose() - { - Texture?.Dispose(); - Target?.Dispose(); - _resource?.Dispose(); - _sharedResource?.Dispose(); - _event?.Dispose(); - } - - public void Flush() - { - s_dxDevice.ImmediateContext.ResolveSubresource(_resource, 0, _sharedResource, 0, Format.B8G8R8A8_UNorm); - s_dxDevice.ImmediateContext.Flush(); - s_dxDevice.ImmediateContext.End(_event); - s_dxDevice.ImmediateContext.GetData(_event).Dispose(); - } - } - - private D3DImage _image; - private SwapBuffer _backBuffer; - private readonly WpfTopLevelImpl _impl; - private static Device s_dxDevice; - private static Direct3DEx s_d3DContext; - private static DeviceEx s_d3DDevice; - private Vector _oldDpi; - - - [DllImport("user32.dll", SetLastError = false)] - private static extern IntPtr GetDesktopWindow(); - - static void EnsureDirectX() - { - if(s_d3DDevice != null) - return; - s_d3DContext = new Direct3DEx(); - - SharpDX.Direct3D9.PresentParameters presentparams = new SharpDX.Direct3D9.PresentParameters - { - Windowed = true, - SwapEffect = SharpDX.Direct3D9.SwapEffect.Discard, - DeviceWindowHandle = GetDesktopWindow(), - PresentationInterval = PresentInterval.Default - }; - s_dxDevice = s_dxDevice ?? AvaloniaLocator.Current.GetRequiredService() - .QueryInterface(); - s_d3DDevice = new DeviceEx(s_d3DContext, 0, DeviceType.Hardware, IntPtr.Zero, CreateFlags.HardwareVertexProcessing | CreateFlags.Multithreaded | CreateFlags.FpuPreserve, presentparams); - - } - - public Direct2DImageSurface(WpfTopLevelImpl impl) - { - _impl = impl; - } - - public RenderTarget GetOrCreateRenderTarget() - { - EnsureDirectX(); - var scale = _impl.GetScaling(); - var size = new IntSize(_impl.ActualWidth * scale.X, _impl.ActualHeight * scale.Y); - var dpi = scale * 96; - - if (_backBuffer!=null && _backBuffer.Size == size) - return _backBuffer.Target; - - if (_image == null || _oldDpi.X != dpi.X || _oldDpi.Y != dpi.Y) - { - _image = new D3DImage(dpi.X, dpi.Y); - _oldDpi = dpi; - } - _impl.ImageSource = _image; - - RemoveAndDispose(ref _backBuffer); - if (size == default) - { - _image.Lock(); - _image.SetBackBuffer(D3DResourceType.IDirect3DSurface9, IntPtr.Zero); - _image.Unlock(); - return null; - } - _backBuffer = new SwapBuffer(size, dpi); - - return _backBuffer.Target; - } - - static void RemoveAndDispose(ref T d) where T : IDisposable - { - d?.Dispose(); - d = default; - } - - void Swap() - { - _backBuffer.Flush(); - _image.Lock(); - _image.SetBackBuffer(D3DResourceType.IDirect3DSurface9, _backBuffer?.Texture?.NativePointer ?? IntPtr.Zero, true); - _image.AddDirtyRect(new Int32Rect(0, 0, _image.PixelWidth, _image.PixelHeight)); - _image.Unlock(); - } - - public void DestroyRenderTarget() - { - RemoveAndDispose(ref _backBuffer); - } - - public void BeforeDrawing() - { - - } - - public void AfterDrawing() => Swap(); - public void Dispose() - { - RemoveAndDispose(ref _backBuffer); - } - } -} diff --git a/src/Windows/Avalonia.Win32.Interop/Wpf/IntSize.cs b/src/Windows/Avalonia.Win32.Interop/Wpf/IntSize.cs deleted file mode 100644 index 3bfbf4bd92..0000000000 --- a/src/Windows/Avalonia.Win32.Interop/Wpf/IntSize.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System; - -namespace Avalonia.Win32.Interop.Wpf -{ - struct IntSize : IEquatable - { - public bool Equals(IntSize other) - { - return Width == other.Width && Height == other.Height; - } - - public IntSize(int width, int height) - { - Width = width; - Height = height; - } - - public IntSize(double width, double height) : this((int) width, (int) height) - { - - } - - public static implicit operator IntSize(System.Windows.Size size) - { - return new IntSize {Width = (int) size.Width, Height = (int) size.Height}; - } - - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is IntSize size && Equals(size); - } - - public override int GetHashCode() - { - unchecked - { - return (Width * 397) ^ Height; - } - } - - public static bool operator ==(IntSize left, IntSize right) - { - return left.Equals(right); - } - - public static bool operator !=(IntSize left, IntSize right) - { - return !left.Equals(right); - } - - public int Width { get; set; } - public int Height { get; set; } - } -} diff --git a/src/Windows/Avalonia.Win32.Interop/Wpf/WpfAvaloniaHost.cs b/src/Windows/Avalonia.Win32.Interop/Wpf/WpfAvaloniaHost.cs deleted file mode 100644 index 7883c28153..0000000000 --- a/src/Windows/Avalonia.Win32.Interop/Wpf/WpfAvaloniaHost.cs +++ /dev/null @@ -1,110 +0,0 @@ -using System; -using System.Threading; -using System.Windows; -using System.Windows.Markup; - -namespace Avalonia.Win32.Interop.Wpf -{ - [ContentProperty("Content")] - public class WpfAvaloniaHost : FrameworkElement, IDisposable, IAddChild - { - private WpfTopLevelImpl _impl; - private readonly SynchronizationContext _sync; - private bool _hasChildren; - public WpfAvaloniaHost() - { - _sync = SynchronizationContext.Current; - _impl = new WpfTopLevelImpl(); - _impl.ControlRoot.Prepare(); - _impl.Visibility = Visibility.Visible; - SnapsToDevicePixels = true; - UseLayoutRounding = true; - PresentationSource.AddSourceChangedHandler(this, OnSourceChanged); - } - - private void OnSourceChanged(object sender, SourceChangedEventArgs e) - { - if (e.NewSource != null && !_hasChildren) - { - AddLogicalChild(_impl); - AddVisualChild(_impl); - _hasChildren = true; - } - else - { - RemoveVisualChild(_impl); - RemoveLogicalChild(_impl); - _hasChildren = false; - } - } - - public object Content - { - get => _impl.ControlRoot.Content; - set => _impl.ControlRoot.Content = value; - } - - //Separate class is needed to prevent accidental resurrection - class Disposer - { - private readonly WpfTopLevelImpl _impl; - - public Disposer(WpfTopLevelImpl impl) - { - _impl = impl; - } - - public void Callback(object state) - { - _impl.Dispose(); - } - } - - protected override System.Windows.Size MeasureOverride(System.Windows.Size constraint) - { - _impl.InvalidateMeasure(); - _impl.Measure(constraint); - return _impl.DesiredSize; - } - - protected override System.Windows.Size ArrangeOverride(System.Windows.Size arrangeSize) - { - _impl.Arrange(new System.Windows.Rect(arrangeSize)); - return arrangeSize; - } - - protected override int VisualChildrenCount => 1; - protected override System.Windows.Media.Visual GetVisualChild(int index) => _impl; - - ~WpfAvaloniaHost() - { - if (_impl != null) - _sync.Post(new Disposer(_impl).Callback, null); - } - - public void Dispose() - { - if (_impl != null) - { - RemoveVisualChild(_impl); - RemoveLogicalChild(_impl); - _impl.Dispose(); - _impl = null; - GC.SuppressFinalize(this); - } - } - - void IAddChild.AddChild(object value) - { - if (Content == null) - Content = value; - else - throw new InvalidOperationException(); - } - - void IAddChild.AddText(string text) - { - // - } - } -} diff --git a/src/Windows/Avalonia.Win32.Interop/Wpf/WpfInteropExtensions.cs b/src/Windows/Avalonia.Win32.Interop/Wpf/WpfInteropExtensions.cs deleted file mode 100644 index cbfc259eda..0000000000 --- a/src/Windows/Avalonia.Win32.Interop/Wpf/WpfInteropExtensions.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace Avalonia.Win32.Interop.Wpf -{ - static class WpfInteropExtensions - { - public static System.Windows.Point ToWpfPoint(this Point pt) => new System.Windows.Point(pt.X, pt.Y); - public static System.Windows.Point ToWpfPoint(this PixelPoint pt) => new System.Windows.Point(pt.X, pt.Y); - public static Point ToAvaloniaPoint(this System.Windows.Point pt) => new Point(pt.X, pt.Y); - public static PixelPoint ToAvaloniaPixelPoint(this System.Windows.Point pt) => new PixelPoint((int)pt.X, (int)pt.Y); - public static System.Windows.Size ToWpfSize(this Size pt) => new System.Windows.Size(pt.Width, pt.Height); - public static Size ToAvaloniaSize(this System.Windows.Size pt) => new Size(pt.Width, pt.Height); - } -} diff --git a/src/Windows/Avalonia.Win32.Interop/Wpf/WpfMouseDevice.cs b/src/Windows/Avalonia.Win32.Interop/Wpf/WpfMouseDevice.cs deleted file mode 100644 index 2be9c1a558..0000000000 --- a/src/Windows/Avalonia.Win32.Interop/Wpf/WpfMouseDevice.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using Avalonia.Controls.Embedding; -using Avalonia.Input; -using Avalonia.VisualTree; - -namespace Avalonia.Win32.Interop.Wpf -{ - class WpfMouseDevice : MouseDevice - { - private readonly WpfTopLevelImpl _impl; - - public WpfMouseDevice(WpfTopLevelImpl impl) : base(new WpfMousePointer(impl)) - { - _impl = impl; - } - - class WpfMousePointer : Pointer - { - private readonly WpfTopLevelImpl _impl; - - public WpfMousePointer(WpfTopLevelImpl impl) : base(Pointer.GetNextFreeId(), PointerType.Mouse, true) - { - _impl = impl; - } - - protected override void PlatformCapture(IInputElement control) - { - if (control == null) - { - System.Windows.Input.Mouse.Capture(null); - } - else if (((control as Visual)?.GetVisualRoot() as EmbeddableControlRoot)?.PlatformImpl != _impl) - throw new ArgumentException("Visual belongs to unknown toplevel"); - else - System.Windows.Input.Mouse.Capture(_impl); - } - } - - } -} diff --git a/src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs b/src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs deleted file mode 100644 index a74cc69c48..0000000000 --- a/src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs +++ /dev/null @@ -1,254 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Windows; -using System.Windows.Input; -using System.Windows.Interop; -using System.Windows.Media; -using Avalonia.Controls; -using Avalonia.Controls.Embedding; -using Avalonia.Input; -using Avalonia.Input.Raw; -using Avalonia.Layout; -using Avalonia.Platform; -using Avalonia.Rendering; -using Avalonia.Rendering.Composition; -using Key = Avalonia.Input.Key; -using KeyEventArgs = System.Windows.Input.KeyEventArgs; -using MouseButton = System.Windows.Input.MouseButton; - -namespace Avalonia.Win32.Interop.Wpf -{ - class WpfTopLevelImpl : FrameworkElement, ITopLevelImpl - { - private HwndSource _currentHwndSource; - private readonly HwndSourceHook _hook; - private readonly ITopLevelImpl _ttl; - private IInputRoot _inputRoot; - private readonly IEnumerable _surfaces; - private readonly IMouseDevice _mouse; - private readonly IKeyboardDevice _keyboard; - private Size _finalSize; - - public EmbeddableControlRoot ControlRoot { get; } - internal ImageSource ImageSource { get; set; } - - public class CustomControlRoot : EmbeddableControlRoot, IEmbeddedLayoutRoot - { - public CustomControlRoot(WpfTopLevelImpl impl) : base(impl) - { - EnforceClientSize = false; - } - - protected override void OnMeasureInvalidated() - { - ((FrameworkElement)PlatformImpl)?.InvalidateMeasure(); - } - - public Size AllocatedSize => ClientSize; - } - - public WpfTopLevelImpl() - { - PresentationSource.AddSourceChangedHandler(this, OnSourceChanged); - _hook = WndProc; - _ttl = this; - _surfaces = new object[] {new WritableBitmapSurface(this), new Direct2DImageSurface(this)}; - _mouse = new WpfMouseDevice(this); - _keyboard = AvaloniaLocator.Current.GetService(); - - ControlRoot = new CustomControlRoot(this); - SnapsToDevicePixels = true; - Focusable = true; - DataContextChanged += delegate - { - ControlRoot.DataContext = DataContext; - }; - } - - private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam, ref bool handled) - { - if (msg == (int)UnmanagedMethods.WindowsMessage.WM_DPICHANGED) - _ttl.ScalingChanged?.Invoke(_ttl.RenderScaling); - return IntPtr.Zero; - } - - private void OnSourceChanged(object sender, SourceChangedEventArgs e) - { - _currentHwndSource?.RemoveHook(_hook); - _currentHwndSource = e.NewSource as HwndSource; - _currentHwndSource?.AddHook(_hook); - _ttl.ScalingChanged?.Invoke(_ttl.RenderScaling); - } - - public void Dispose() - { - _ttl.Closed?.Invoke(); - foreach(var d in _surfaces.OfType()) - d.Dispose(); - } - - Size ITopLevelImpl.ClientSize => _finalSize; - Size? ITopLevelImpl.FrameSize => null; - - double ITopLevelImpl.RenderScaling => PresentationSource.FromVisual(this)?.CompositionTarget?.TransformToDevice.M11 ?? 1; - - IEnumerable ITopLevelImpl.Surfaces => _surfaces; - - private Size _previousSize; - protected override System.Windows.Size ArrangeOverride(System.Windows.Size finalSize) - { - _finalSize = finalSize.ToAvaloniaSize(); - if (_finalSize == _previousSize) - return finalSize; - _previousSize = _finalSize; - _ttl.Resized?.Invoke(finalSize.ToAvaloniaSize(), WindowResizeReason.Unspecified); - return base.ArrangeOverride(finalSize); - } - - protected override System.Windows.Size MeasureOverride(System.Windows.Size availableSize) - { - ControlRoot.Measure(availableSize.ToAvaloniaSize()); - return ControlRoot.DesiredSize.ToWpfSize(); - } - - protected override void OnRender(DrawingContext drawingContext) - { - if(ActualHeight == 0 || ActualWidth == 0) - return; - _ttl.Paint?.Invoke(new Rect(0, 0, ActualWidth, ActualHeight)); - if (ImageSource != null) - drawingContext.DrawImage(ImageSource, new System.Windows.Rect(0, 0, ActualWidth, ActualHeight)); - } - - - public Compositor Compositor => Win32Platform.Compositor; - void ITopLevelImpl.SetInputRoot(IInputRoot inputRoot) => _inputRoot = inputRoot; - - Point ITopLevelImpl.PointToClient(PixelPoint point) => PointFromScreen(point.ToWpfPoint()).ToAvaloniaPoint(); - - PixelPoint ITopLevelImpl.PointToScreen(Point point) => PointToScreen(point.ToWpfPoint()).ToAvaloniaPixelPoint(); - - protected override void OnLostFocus(RoutedEventArgs e) => LostFocus?.Invoke(); - - static RawInputModifiers GetModifiers(MouseEventArgs e) - { - var state = Keyboard.Modifiers; - var rv = default(RawInputModifiers); - if (state.HasFlag(ModifierKeys.Windows)) - rv |= RawInputModifiers.Meta; - if (state.HasFlag(ModifierKeys.Alt)) - rv |= RawInputModifiers.Alt; - if (state.HasFlag(ModifierKeys.Control)) - rv |= RawInputModifiers.Control; - if (state.HasFlag(ModifierKeys.Shift)) - rv |= RawInputModifiers.Shift; - if (e != null) - { - if (e.LeftButton == MouseButtonState.Pressed) - rv |= RawInputModifiers.LeftMouseButton; - if (e.RightButton == MouseButtonState.Pressed) - rv |= RawInputModifiers.RightMouseButton; - if (e.MiddleButton == MouseButtonState.Pressed) - rv |= RawInputModifiers.MiddleMouseButton; - } - return rv; - } - - void MouseEvent(RawPointerEventType type, MouseEventArgs e) - => _ttl.Input?.Invoke(new RawPointerEventArgs(_mouse, (uint)e.Timestamp, _inputRoot, type, - e.GetPosition(this).ToAvaloniaPoint(), GetModifiers(e))); - - protected override void OnMouseDown(MouseButtonEventArgs e) - { - RawPointerEventType type; - if(e.ChangedButton == MouseButton.Left) - type = RawPointerEventType.LeftButtonDown; - else if (e.ChangedButton == MouseButton.Middle) - type = RawPointerEventType.MiddleButtonDown; - else if (e.ChangedButton == MouseButton.Right) - type = RawPointerEventType.RightButtonDown; - else - return; - MouseEvent(type, e); - Focus(); - } - - protected override void OnMouseUp(MouseButtonEventArgs e) - { - RawPointerEventType type; - if (e.ChangedButton == MouseButton.Left) - type = RawPointerEventType.LeftButtonUp; - else if (e.ChangedButton == MouseButton.Middle) - type = RawPointerEventType.MiddleButtonUp; - else if (e.ChangedButton == MouseButton.Right) - type = RawPointerEventType.RightButtonUp; - else - return; - MouseEvent(type, e); - Focus(); - } - - protected override void OnMouseMove(MouseEventArgs e) - { - MouseEvent(RawPointerEventType.Move, e); - } - - protected override void OnMouseWheel(MouseWheelEventArgs e) => - _ttl.Input?.Invoke(new RawMouseWheelEventArgs(_mouse, (uint) e.Timestamp, _inputRoot, - e.GetPosition(this).ToAvaloniaPoint(), new Vector(0, e.Delta), GetModifiers(e))); - - protected override void OnMouseLeave(MouseEventArgs e) => MouseEvent(RawPointerEventType.LeaveWindow, e); - - protected override void OnKeyDown(KeyEventArgs e) - => _ttl.Input?.Invoke(new RawKeyEventArgs(_keyboard, (uint) e.Timestamp, _inputRoot, RawKeyEventType.KeyDown, - (Key) e.Key, - GetModifiers(null))); - - protected override void OnKeyUp(KeyEventArgs e) - => _ttl.Input?.Invoke(new RawKeyEventArgs(_keyboard, (uint)e.Timestamp, _inputRoot, RawKeyEventType.KeyUp, - (Key)e.Key, - GetModifiers(null))); - - protected override void OnTextInput(TextCompositionEventArgs e) - => _ttl.Input?.Invoke(new RawTextInputEventArgs(_keyboard, (uint) e.Timestamp, _inputRoot, e.Text)); - - void ITopLevelImpl.SetCursor(ICursorImpl cursor) - { - if (cursor == null) - Cursor = Cursors.Arrow; - else if (cursor is IPlatformHandle handle) - Cursor = CursorShim.FromHCursor(handle.Handle); - } - - Action ITopLevelImpl.Input { get; set; } //TODO - Action ITopLevelImpl.Paint { get; set; } - Action ITopLevelImpl.Resized { get; set; } - Action ITopLevelImpl.ScalingChanged { get; set; } - - Action ITopLevelImpl.TransparencyLevelChanged { get; set; } - - Action ITopLevelImpl.Closed { get; set; } - public new Action LostFocus { get; set; } - - internal Vector GetScaling() - { - var src = PresentationSource.FromVisual(this)?.CompositionTarget; - if (src == null) - return new Vector(1, 1); - return new Vector(src.TransformToDevice.M11, src.TransformToDevice.M22); - } - - public IPopupImpl CreatePopup() => null; - - public void SetTransparencyLevelHint(IReadOnlyList transparencyLevel) { } - - public WindowTransparencyLevel TransparencyLevel => WindowTransparencyLevel.None; - - public void SetFrameThemeVariant(PlatformThemeVariant themeVariant) { } - - public AcrylicPlatformCompensationLevels AcrylicCompensationLevels { get; } = new AcrylicPlatformCompensationLevels(1, 1, 1); - - public object TryGetFeature(Type featureType) => null; - } -} diff --git a/src/Windows/Avalonia.Win32.Interop/Wpf/WritableBitmapSurface.cs b/src/Windows/Avalonia.Win32.Interop/Wpf/WritableBitmapSurface.cs deleted file mode 100644 index 04b4a53580..0000000000 --- a/src/Windows/Avalonia.Win32.Interop/Wpf/WritableBitmapSurface.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System; -using System.Windows; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using Avalonia.Controls.Platform.Surfaces; -using Avalonia.Platform; -using PixelFormat = Avalonia.Platform.PixelFormat; - -namespace Avalonia.Win32.Interop.Wpf -{ - class WritableBitmapSurface : IFramebufferPlatformSurface - { - private readonly WpfTopLevelImpl _impl; - private WriteableBitmap _bitmap; - public WritableBitmapSurface(WpfTopLevelImpl impl) - { - _impl = impl; - } - - public ILockedFramebuffer Lock() - { - var scale = _impl.GetScaling(); - var size = new Size(_impl.ActualWidth * scale.X, _impl.ActualHeight * scale.Y); - var dpi = scale * 96; - if (_bitmap == null || _bitmap.PixelWidth != (int) size.Width || _bitmap.PixelHeight != (int) size.Height) - { - _bitmap = new WriteableBitmap((int) size.Width, (int) size.Height, dpi.X, dpi.Y, - System.Windows.Media.PixelFormats.Bgra32, null); - } - return new LockedFramebuffer(_impl, _bitmap, dpi); - } - - internal class LockedFramebuffer : ILockedFramebuffer - { - private readonly WpfTopLevelImpl _impl; - private readonly WriteableBitmap _bitmap; - - public LockedFramebuffer(WpfTopLevelImpl impl, WriteableBitmap bitmap, Vector dpi) - { - _impl = impl; - _bitmap = bitmap; - Dpi = dpi; - _bitmap.Lock(); - } - - public void Dispose() - { - _bitmap.AddDirtyRect(new Int32Rect(0, 0, _bitmap.PixelWidth, _bitmap.PixelHeight)); - _bitmap.Unlock(); - /* - using (var fileStream = new FileStream("c:\\tools\\wat.png", FileMode.Create)) - { - BitmapEncoder encoder = new PngBitmapEncoder(); - encoder.Frames.Add(BitmapFrame.Create(_bitmap)); - encoder.Save(fileStream); - }*/ - _impl.ImageSource = _bitmap; - } - - public IntPtr Address => _bitmap.BackBuffer; - public PixelSize Size => new PixelSize(_bitmap.PixelWidth, _bitmap.PixelHeight); - public int RowBytes => _bitmap.BackBufferStride; - public Vector Dpi { get; } - public PixelFormat Format => PixelFormat.Bgra8888; - } - } -} diff --git a/src/Windows/Avalonia.Win32.Interop/Avalonia.Win32.Interop.csproj b/src/Windows/Avalonia.Win32.Interoperability/Avalonia.Win32.Interoperability.csproj similarity index 61% rename from src/Windows/Avalonia.Win32.Interop/Avalonia.Win32.Interop.csproj rename to src/Windows/Avalonia.Win32.Interoperability/Avalonia.Win32.Interoperability.csproj index 08c4f85dc8..68c6fa69c9 100644 --- a/src/Windows/Avalonia.Win32.Interop/Avalonia.Win32.Interop.csproj +++ b/src/Windows/Avalonia.Win32.Interoperability/Avalonia.Win32.Interoperability.csproj @@ -1,20 +1,18 @@ - net461 + net461;net6.0-windows true - true true - true true - true Avalonia.Win32.Interoperability + - - + + diff --git a/src/Windows/Avalonia.Win32.Interoperability/WinForms/WinFormsAvaloniaControlHost.cs b/src/Windows/Avalonia.Win32.Interoperability/WinForms/WinFormsAvaloniaControlHost.cs new file mode 100644 index 0000000000..1f8c30030c --- /dev/null +++ b/src/Windows/Avalonia.Win32.Interoperability/WinForms/WinFormsAvaloniaControlHost.cs @@ -0,0 +1,116 @@ +using System; +using System.ComponentModel; +using System.Windows.Forms; +using Avalonia.Controls.Embedding; +using Avalonia.Win32.Interop; +using WinFormsControl = System.Windows.Forms.Control; +using AvControl = Avalonia.Controls.Control; + +namespace Avalonia.Win32.Interoperability; + +/// +/// An element that allows you to host a Avalonia control on a Windows Forms page. +/// +[ToolboxItem(true)] +public class WinFormsAvaloniaControlHost : WinFormsControl +{ + private AvControl? _content; + private EmbeddableControlRoot? _root; + + private IntPtr WindowHandle => _root?.TryGetPlatformHandle()?.Handle ?? IntPtr.Zero; + + /// + /// Initializes a new instance of the class. + /// + public WinFormsAvaloniaControlHost() + { + SetStyle(ControlStyles.AllPaintingInWmPaint, true); + } + + /// + /// Gets or sets the Avalonia control hosted by the element. + /// + public AvControl? Content + { + get => _content; + set + { + if (_content != value) + { + _content = value; + if (_root is not null) + { + _root.Content = value; + } + } + } + } + + /// + protected override void OnHandleCreated(EventArgs e) + { + _root = new(); + _root.Content = _content; + _root.Prepare(); + _root.StartRendering(); + _root.GotFocus += RootGotFocus; + + FixPosition(); + + UnmanagedMethods.SetParent(WindowHandle, Handle); + base.OnHandleCreated(e); + } + + /// + protected override void OnHandleDestroyed(EventArgs e) + { + _root?.StopRendering(); + _root?.Dispose(); + _root = null; + base.OnHandleDestroyed(e); + } + + /// + protected override void Dispose(bool disposing) + { + if (disposing) + { + _root?.Dispose(); + _root = null; + } + base.Dispose(disposing); + } + + private void RootGotFocus(object? sender, Interactivity.RoutedEventArgs e) + { + UnmanagedMethods.SetFocus(WindowHandle); + } + + /// + protected override void OnGotFocus(EventArgs e) + { + var handle = WindowHandle; + if (handle != default) + UnmanagedMethods.SetFocus(handle); + } + + private void FixPosition() + { + var handle = WindowHandle; + if (handle != default && Width > 0 && Height > 0) + UnmanagedMethods.MoveWindow(handle, 0, 0, Width, Height, true); + } + + /// + protected override void OnResize(EventArgs e) + { + FixPosition(); + base.OnResize(e); + } + + /// + protected override void OnPaint(PaintEventArgs e) + { + + } +} diff --git a/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj b/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj index 61f5996a94..2384ef6b6c 100644 --- a/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj +++ b/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj @@ -27,7 +27,7 @@ $(NoWarn);CA1416 - + diff --git a/src/tools/Avalonia.Designer.HostApp/Program.cs b/src/tools/Avalonia.Designer.HostApp/Program.cs index 4472dac4e3..43e6101446 100644 --- a/src/tools/Avalonia.Designer.HostApp/Program.cs +++ b/src/tools/Avalonia.Designer.HostApp/Program.cs @@ -8,7 +8,7 @@ namespace Avalonia.Designer.HostApp { class Program { -#if NET461 +#if NETFRAMEWORK private static string s_appDir; private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) diff --git a/tests/Avalonia.UnitTests/InvariantCultureFixture.cs b/tests/Avalonia.UnitTests/InvariantCultureFixture.cs index 6dfc6d4202..c46dca5de6 100644 --- a/tests/Avalonia.UnitTests/InvariantCultureFixture.cs +++ b/tests/Avalonia.UnitTests/InvariantCultureFixture.cs @@ -17,22 +17,13 @@ namespace Avalonia.UnitTests public InvariantCultureFixture() { -#if NET461 - _restore = Thread.CurrentThread.CurrentCulture; - Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; -#else _restore = CultureInfo.CurrentCulture; CultureInfo.CurrentCulture = CultureInfo.InvariantCulture; -#endif } public void Dispose() { -#if NET461 - Thread.CurrentThread.CurrentCulture = _restore; -#else CultureInfo.CurrentCulture = _restore; -#endif } } }