diff --git a/Avalonia.sln b/Avalonia.sln index 56f33c2a6b..d17bb2ed97 100644 --- a/Avalonia.sln +++ b/Avalonia.sln @@ -50,8 +50,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Input.UnitTests", EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Direct2D1.UnitTests", "tests\Avalonia.Direct2D1.UnitTests\Avalonia.Direct2D1.UnitTests.csproj", "{EFB11458-9CDF-41C0-BE4F-44AF45A4CAB8}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Cairo.RenderTests", "tests\Avalonia.RenderTests\Avalonia.Cairo.RenderTests.csproj", "{E106CF37-4066-4615-B684-172A6D30B058}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Markup.Xaml.UnitTests", "tests\Avalonia.Markup.Xaml.UnitTests\Avalonia.Markup.Xaml.UnitTests.csproj", "{99135EAB-653D-47E4-A378-C96E1278CA44}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Markup", "Markup", "{8B6A8209-894F-4BA1-B880-965FD453982C}" @@ -67,10 +65,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{A689DE EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Gtk", "Gtk", "{B9894058-278A-46B5-B6ED-AD613FCC03B3}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Gtk", "src\Gtk\Avalonia.Gtk\Avalonia.Gtk.csproj", "{54F237D5-A70A-4752-9656-0C70B1A7B047}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Cairo", "src\Gtk\Avalonia.Cairo\Avalonia.Cairo.csproj", "{FB05AC90-89BA-4F2F-A924-F37875FB547C}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.ReactiveUI", "src\Avalonia.ReactiveUI\Avalonia.ReactiveUI.csproj", "{6417B24E-49C2-4985-8DB2-3AB9D898EC91}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.HtmlRenderer", "src\Avalonia.HtmlRenderer\Avalonia.HtmlRenderer.csproj", "{5FB2B005-0A7F-4DAD-ADD4-3ED01444E63D}" @@ -127,8 +121,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Interop", "Interop", "{A0CC EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsInteropTest", "samples\interop\WindowsInteropTest\WindowsInteropTest.csproj", "{C7A69145-60B6-4882-97D6-A3921DD43978}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GtkInteropDemo", "samples\interop\GtkInteropDemo\GtkInteropDemo.csproj", "{BD7F352C-6DC1-4740-BAF2-2D34A038728C}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.DotNetFrameworkRuntime", "src\Avalonia.DotNetFrameworkRuntime\Avalonia.DotNetFrameworkRuntime.csproj", "{4A1ABB09-9047-4BD5-A4AD-A055E52C5EE0}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RenderTest", "samples\RenderTest\RenderTest.csproj", "{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}" @@ -204,9 +196,7 @@ Global 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 - tests\Avalonia.RenderTests\Avalonia.RenderTests.projitems*{e106cf37-4066-4615-b684-172a6d30b058}*SharedItemsImports = 4 src\Shared\PlatformSupport\PlatformSupport.projitems*{e4d9629c-f168-4224-3f51-a5e482ffbc42}*SharedItemsImports = 13 - src\Shared\RenderHelpers\RenderHelpers.projitems*{fb05ac90-89ba-4f2f-a924-f37875fb547c}*SharedItemsImports = 4 EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution Ad-Hoc|Any CPU = Ad-Hoc|Any CPU @@ -1053,44 +1043,6 @@ Global {EFB11458-9CDF-41C0-BE4F-44AF45A4CAB8}.Release|Mono.ActiveCfg = Release|Any CPU {EFB11458-9CDF-41C0-BE4F-44AF45A4CAB8}.Release|x86.ActiveCfg = Release|Any CPU {EFB11458-9CDF-41C0-BE4F-44AF45A4CAB8}.Release|x86.Build.0 = Release|Any CPU - {E106CF37-4066-4615-B684-172A6D30B058}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU - {E106CF37-4066-4615-B684-172A6D30B058}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU - {E106CF37-4066-4615-B684-172A6D30B058}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU - {E106CF37-4066-4615-B684-172A6D30B058}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU - {E106CF37-4066-4615-B684-172A6D30B058}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU - {E106CF37-4066-4615-B684-172A6D30B058}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU - {E106CF37-4066-4615-B684-172A6D30B058}.Ad-Hoc|Mono.ActiveCfg = Debug|Any CPU - {E106CF37-4066-4615-B684-172A6D30B058}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU - {E106CF37-4066-4615-B684-172A6D30B058}.Ad-Hoc|x86.Build.0 = Debug|Any CPU - {E106CF37-4066-4615-B684-172A6D30B058}.AppStore|Any CPU.ActiveCfg = Release|Any CPU - {E106CF37-4066-4615-B684-172A6D30B058}.AppStore|Any CPU.Build.0 = Release|Any CPU - {E106CF37-4066-4615-B684-172A6D30B058}.AppStore|iPhone.ActiveCfg = Release|Any CPU - {E106CF37-4066-4615-B684-172A6D30B058}.AppStore|iPhone.Build.0 = Release|Any CPU - {E106CF37-4066-4615-B684-172A6D30B058}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU - {E106CF37-4066-4615-B684-172A6D30B058}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU - {E106CF37-4066-4615-B684-172A6D30B058}.AppStore|Mono.ActiveCfg = Debug|Any CPU - {E106CF37-4066-4615-B684-172A6D30B058}.AppStore|x86.ActiveCfg = Debug|Any CPU - {E106CF37-4066-4615-B684-172A6D30B058}.AppStore|x86.Build.0 = Debug|Any CPU - {E106CF37-4066-4615-B684-172A6D30B058}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E106CF37-4066-4615-B684-172A6D30B058}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E106CF37-4066-4615-B684-172A6D30B058}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {E106CF37-4066-4615-B684-172A6D30B058}.Debug|iPhone.Build.0 = Debug|Any CPU - {E106CF37-4066-4615-B684-172A6D30B058}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {E106CF37-4066-4615-B684-172A6D30B058}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU - {E106CF37-4066-4615-B684-172A6D30B058}.Debug|Mono.ActiveCfg = Debug|Any CPU - {E106CF37-4066-4615-B684-172A6D30B058}.Debug|Mono.Build.0 = Debug|Any CPU - {E106CF37-4066-4615-B684-172A6D30B058}.Debug|x86.ActiveCfg = Debug|Any CPU - {E106CF37-4066-4615-B684-172A6D30B058}.Debug|x86.Build.0 = Debug|Any CPU - {E106CF37-4066-4615-B684-172A6D30B058}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E106CF37-4066-4615-B684-172A6D30B058}.Release|Any CPU.Build.0 = Release|Any CPU - {E106CF37-4066-4615-B684-172A6D30B058}.Release|iPhone.ActiveCfg = Release|Any CPU - {E106CF37-4066-4615-B684-172A6D30B058}.Release|iPhone.Build.0 = Release|Any CPU - {E106CF37-4066-4615-B684-172A6D30B058}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU - {E106CF37-4066-4615-B684-172A6D30B058}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {E106CF37-4066-4615-B684-172A6D30B058}.Release|Mono.ActiveCfg = Release|Any CPU - {E106CF37-4066-4615-B684-172A6D30B058}.Release|Mono.Build.0 = Release|Any CPU - {E106CF37-4066-4615-B684-172A6D30B058}.Release|x86.ActiveCfg = Release|Any CPU - {E106CF37-4066-4615-B684-172A6D30B058}.Release|x86.Build.0 = Release|Any CPU {99135EAB-653D-47E4-A378-C96E1278CA44}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU {99135EAB-653D-47E4-A378-C96E1278CA44}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU {99135EAB-653D-47E4-A378-C96E1278CA44}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU @@ -1167,82 +1119,6 @@ Global {3E53A01A-B331-47F3-B828-4A5717E77A24}.Release|Mono.Build.0 = Release|Any CPU {3E53A01A-B331-47F3-B828-4A5717E77A24}.Release|x86.ActiveCfg = Release|Any CPU {3E53A01A-B331-47F3-B828-4A5717E77A24}.Release|x86.Build.0 = Release|Any CPU - {54F237D5-A70A-4752-9656-0C70B1A7B047}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU - {54F237D5-A70A-4752-9656-0C70B1A7B047}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU - {54F237D5-A70A-4752-9656-0C70B1A7B047}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU - {54F237D5-A70A-4752-9656-0C70B1A7B047}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU - {54F237D5-A70A-4752-9656-0C70B1A7B047}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU - {54F237D5-A70A-4752-9656-0C70B1A7B047}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU - {54F237D5-A70A-4752-9656-0C70B1A7B047}.Ad-Hoc|Mono.ActiveCfg = Debug|Any CPU - {54F237D5-A70A-4752-9656-0C70B1A7B047}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU - {54F237D5-A70A-4752-9656-0C70B1A7B047}.Ad-Hoc|x86.Build.0 = Debug|Any CPU - {54F237D5-A70A-4752-9656-0C70B1A7B047}.AppStore|Any CPU.ActiveCfg = Release|Any CPU - {54F237D5-A70A-4752-9656-0C70B1A7B047}.AppStore|Any CPU.Build.0 = Release|Any CPU - {54F237D5-A70A-4752-9656-0C70B1A7B047}.AppStore|iPhone.ActiveCfg = Release|Any CPU - {54F237D5-A70A-4752-9656-0C70B1A7B047}.AppStore|iPhone.Build.0 = Release|Any CPU - {54F237D5-A70A-4752-9656-0C70B1A7B047}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU - {54F237D5-A70A-4752-9656-0C70B1A7B047}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU - {54F237D5-A70A-4752-9656-0C70B1A7B047}.AppStore|Mono.ActiveCfg = Debug|Any CPU - {54F237D5-A70A-4752-9656-0C70B1A7B047}.AppStore|x86.ActiveCfg = Debug|Any CPU - {54F237D5-A70A-4752-9656-0C70B1A7B047}.AppStore|x86.Build.0 = Debug|Any CPU - {54F237D5-A70A-4752-9656-0C70B1A7B047}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {54F237D5-A70A-4752-9656-0C70B1A7B047}.Debug|Any CPU.Build.0 = Debug|Any CPU - {54F237D5-A70A-4752-9656-0C70B1A7B047}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {54F237D5-A70A-4752-9656-0C70B1A7B047}.Debug|iPhone.Build.0 = Debug|Any CPU - {54F237D5-A70A-4752-9656-0C70B1A7B047}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {54F237D5-A70A-4752-9656-0C70B1A7B047}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU - {54F237D5-A70A-4752-9656-0C70B1A7B047}.Debug|Mono.ActiveCfg = Debug|Any CPU - {54F237D5-A70A-4752-9656-0C70B1A7B047}.Debug|Mono.Build.0 = Debug|Any CPU - {54F237D5-A70A-4752-9656-0C70B1A7B047}.Debug|x86.ActiveCfg = Debug|Any CPU - {54F237D5-A70A-4752-9656-0C70B1A7B047}.Debug|x86.Build.0 = Debug|Any CPU - {54F237D5-A70A-4752-9656-0C70B1A7B047}.Release|Any CPU.ActiveCfg = Release|Any CPU - {54F237D5-A70A-4752-9656-0C70B1A7B047}.Release|Any CPU.Build.0 = Release|Any CPU - {54F237D5-A70A-4752-9656-0C70B1A7B047}.Release|iPhone.ActiveCfg = Release|Any CPU - {54F237D5-A70A-4752-9656-0C70B1A7B047}.Release|iPhone.Build.0 = Release|Any CPU - {54F237D5-A70A-4752-9656-0C70B1A7B047}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU - {54F237D5-A70A-4752-9656-0C70B1A7B047}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {54F237D5-A70A-4752-9656-0C70B1A7B047}.Release|Mono.ActiveCfg = Release|Any CPU - {54F237D5-A70A-4752-9656-0C70B1A7B047}.Release|Mono.Build.0 = Release|Any CPU - {54F237D5-A70A-4752-9656-0C70B1A7B047}.Release|x86.ActiveCfg = Release|Any CPU - {54F237D5-A70A-4752-9656-0C70B1A7B047}.Release|x86.Build.0 = Release|Any CPU - {FB05AC90-89BA-4F2F-A924-F37875FB547C}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU - {FB05AC90-89BA-4F2F-A924-F37875FB547C}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU - {FB05AC90-89BA-4F2F-A924-F37875FB547C}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU - {FB05AC90-89BA-4F2F-A924-F37875FB547C}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU - {FB05AC90-89BA-4F2F-A924-F37875FB547C}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU - {FB05AC90-89BA-4F2F-A924-F37875FB547C}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU - {FB05AC90-89BA-4F2F-A924-F37875FB547C}.Ad-Hoc|Mono.ActiveCfg = Debug|Any CPU - {FB05AC90-89BA-4F2F-A924-F37875FB547C}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU - {FB05AC90-89BA-4F2F-A924-F37875FB547C}.Ad-Hoc|x86.Build.0 = Debug|Any CPU - {FB05AC90-89BA-4F2F-A924-F37875FB547C}.AppStore|Any CPU.ActiveCfg = Release|Any CPU - {FB05AC90-89BA-4F2F-A924-F37875FB547C}.AppStore|Any CPU.Build.0 = Release|Any CPU - {FB05AC90-89BA-4F2F-A924-F37875FB547C}.AppStore|iPhone.ActiveCfg = Release|Any CPU - {FB05AC90-89BA-4F2F-A924-F37875FB547C}.AppStore|iPhone.Build.0 = Release|Any CPU - {FB05AC90-89BA-4F2F-A924-F37875FB547C}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU - {FB05AC90-89BA-4F2F-A924-F37875FB547C}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU - {FB05AC90-89BA-4F2F-A924-F37875FB547C}.AppStore|Mono.ActiveCfg = Debug|Any CPU - {FB05AC90-89BA-4F2F-A924-F37875FB547C}.AppStore|x86.ActiveCfg = Debug|Any CPU - {FB05AC90-89BA-4F2F-A924-F37875FB547C}.AppStore|x86.Build.0 = Debug|Any CPU - {FB05AC90-89BA-4F2F-A924-F37875FB547C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FB05AC90-89BA-4F2F-A924-F37875FB547C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FB05AC90-89BA-4F2F-A924-F37875FB547C}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {FB05AC90-89BA-4F2F-A924-F37875FB547C}.Debug|iPhone.Build.0 = Debug|Any CPU - {FB05AC90-89BA-4F2F-A924-F37875FB547C}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {FB05AC90-89BA-4F2F-A924-F37875FB547C}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU - {FB05AC90-89BA-4F2F-A924-F37875FB547C}.Debug|Mono.ActiveCfg = Debug|Any CPU - {FB05AC90-89BA-4F2F-A924-F37875FB547C}.Debug|Mono.Build.0 = Debug|Any CPU - {FB05AC90-89BA-4F2F-A924-F37875FB547C}.Debug|x86.ActiveCfg = Debug|Any CPU - {FB05AC90-89BA-4F2F-A924-F37875FB547C}.Debug|x86.Build.0 = Debug|Any CPU - {FB05AC90-89BA-4F2F-A924-F37875FB547C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FB05AC90-89BA-4F2F-A924-F37875FB547C}.Release|Any CPU.Build.0 = Release|Any CPU - {FB05AC90-89BA-4F2F-A924-F37875FB547C}.Release|iPhone.ActiveCfg = Release|Any CPU - {FB05AC90-89BA-4F2F-A924-F37875FB547C}.Release|iPhone.Build.0 = Release|Any CPU - {FB05AC90-89BA-4F2F-A924-F37875FB547C}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU - {FB05AC90-89BA-4F2F-A924-F37875FB547C}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {FB05AC90-89BA-4F2F-A924-F37875FB547C}.Release|Mono.ActiveCfg = Release|Any CPU - {FB05AC90-89BA-4F2F-A924-F37875FB547C}.Release|Mono.Build.0 = Release|Any CPU - {FB05AC90-89BA-4F2F-A924-F37875FB547C}.Release|x86.ActiveCfg = Release|Any CPU - {FB05AC90-89BA-4F2F-A924-F37875FB547C}.Release|x86.Build.0 = Release|Any CPU {6417B24E-49C2-4985-8DB2-3AB9D898EC91}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU {6417B24E-49C2-4985-8DB2-3AB9D898EC91}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU {6417B24E-49C2-4985-8DB2-3AB9D898EC91}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU @@ -1985,46 +1861,6 @@ Global {C7A69145-60B6-4882-97D6-A3921DD43978}.Release|Mono.ActiveCfg = Release|Any CPU {C7A69145-60B6-4882-97D6-A3921DD43978}.Release|x86.ActiveCfg = Release|Any CPU {C7A69145-60B6-4882-97D6-A3921DD43978}.Release|x86.Build.0 = Release|Any CPU - {BD7F352C-6DC1-4740-BAF2-2D34A038728C}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU - {BD7F352C-6DC1-4740-BAF2-2D34A038728C}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU - {BD7F352C-6DC1-4740-BAF2-2D34A038728C}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU - {BD7F352C-6DC1-4740-BAF2-2D34A038728C}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU - {BD7F352C-6DC1-4740-BAF2-2D34A038728C}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU - {BD7F352C-6DC1-4740-BAF2-2D34A038728C}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU - {BD7F352C-6DC1-4740-BAF2-2D34A038728C}.Ad-Hoc|Mono.ActiveCfg = Release|Any CPU - {BD7F352C-6DC1-4740-BAF2-2D34A038728C}.Ad-Hoc|Mono.Build.0 = Release|Any CPU - {BD7F352C-6DC1-4740-BAF2-2D34A038728C}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU - {BD7F352C-6DC1-4740-BAF2-2D34A038728C}.Ad-Hoc|x86.Build.0 = Release|Any CPU - {BD7F352C-6DC1-4740-BAF2-2D34A038728C}.AppStore|Any CPU.ActiveCfg = Release|Any CPU - {BD7F352C-6DC1-4740-BAF2-2D34A038728C}.AppStore|Any CPU.Build.0 = Release|Any CPU - {BD7F352C-6DC1-4740-BAF2-2D34A038728C}.AppStore|iPhone.ActiveCfg = Release|Any CPU - {BD7F352C-6DC1-4740-BAF2-2D34A038728C}.AppStore|iPhone.Build.0 = Release|Any CPU - {BD7F352C-6DC1-4740-BAF2-2D34A038728C}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU - {BD7F352C-6DC1-4740-BAF2-2D34A038728C}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU - {BD7F352C-6DC1-4740-BAF2-2D34A038728C}.AppStore|Mono.ActiveCfg = Release|Any CPU - {BD7F352C-6DC1-4740-BAF2-2D34A038728C}.AppStore|Mono.Build.0 = Release|Any CPU - {BD7F352C-6DC1-4740-BAF2-2D34A038728C}.AppStore|x86.ActiveCfg = Release|Any CPU - {BD7F352C-6DC1-4740-BAF2-2D34A038728C}.AppStore|x86.Build.0 = Release|Any CPU - {BD7F352C-6DC1-4740-BAF2-2D34A038728C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BD7F352C-6DC1-4740-BAF2-2D34A038728C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BD7F352C-6DC1-4740-BAF2-2D34A038728C}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {BD7F352C-6DC1-4740-BAF2-2D34A038728C}.Debug|iPhone.Build.0 = Debug|Any CPU - {BD7F352C-6DC1-4740-BAF2-2D34A038728C}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {BD7F352C-6DC1-4740-BAF2-2D34A038728C}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU - {BD7F352C-6DC1-4740-BAF2-2D34A038728C}.Debug|Mono.ActiveCfg = Debug|Any CPU - {BD7F352C-6DC1-4740-BAF2-2D34A038728C}.Debug|Mono.Build.0 = Debug|Any CPU - {BD7F352C-6DC1-4740-BAF2-2D34A038728C}.Debug|x86.ActiveCfg = Debug|Any CPU - {BD7F352C-6DC1-4740-BAF2-2D34A038728C}.Debug|x86.Build.0 = Debug|Any CPU - {BD7F352C-6DC1-4740-BAF2-2D34A038728C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BD7F352C-6DC1-4740-BAF2-2D34A038728C}.Release|Any CPU.Build.0 = Release|Any CPU - {BD7F352C-6DC1-4740-BAF2-2D34A038728C}.Release|iPhone.ActiveCfg = Release|Any CPU - {BD7F352C-6DC1-4740-BAF2-2D34A038728C}.Release|iPhone.Build.0 = Release|Any CPU - {BD7F352C-6DC1-4740-BAF2-2D34A038728C}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU - {BD7F352C-6DC1-4740-BAF2-2D34A038728C}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {BD7F352C-6DC1-4740-BAF2-2D34A038728C}.Release|Mono.ActiveCfg = Release|Any CPU - {BD7F352C-6DC1-4740-BAF2-2D34A038728C}.Release|Mono.Build.0 = Release|Any CPU - {BD7F352C-6DC1-4740-BAF2-2D34A038728C}.Release|x86.ActiveCfg = Release|Any CPU - {BD7F352C-6DC1-4740-BAF2-2D34A038728C}.Release|x86.Build.0 = Release|Any CPU {4A1ABB09-9047-4BD5-A4AD-A055E52C5EE0}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU {4A1ABB09-9047-4BD5-A4AD-A055E52C5EE0}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU {4A1ABB09-9047-4BD5-A4AD-A055E52C5EE0}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU @@ -2576,11 +2412,8 @@ Global {DABFD304-D6A4-4752-8123-C2CCF7AC7831} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B} {AC18926A-E784-40FE-B09D-BB0FE2B599F0} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B} {EFB11458-9CDF-41C0-BE4F-44AF45A4CAB8} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B} - {E106CF37-4066-4615-B684-172A6D30B058} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B} {99135EAB-653D-47E4-A378-C96E1278CA44} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B} {3E53A01A-B331-47F3-B828-4A5717E77A24} = {8B6A8209-894F-4BA1-B880-965FD453982C} - {54F237D5-A70A-4752-9656-0C70B1A7B047} = {B9894058-278A-46B5-B6ED-AD613FCC03B3} - {FB05AC90-89BA-4F2F-A924-F37875FB547C} = {B9894058-278A-46B5-B6ED-AD613FCC03B3} {E4D9629C-F168-4224-3F51-A5E482FFBC42} = {A689DEF5-D50F-4975-8B72-124C9EB54066} {6417E941-21BC-467B-A771-0DE389353CE6} = {8B6A8209-894F-4BA1-B880-965FD453982C} {8EF392D5-1416-45AA-9956-7CBBC3229E8A} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B} @@ -2602,7 +2435,6 @@ Global {FBCAF3D0-2808-4934-8E96-3F607594517B} = {9B9E3891-2366-4253-A952-D08BCEB71098} {A0CC0258-D18C-4AB3-854F-7101680FC3F9} = {9B9E3891-2366-4253-A952-D08BCEB71098} {C7A69145-60B6-4882-97D6-A3921DD43978} = {A0CC0258-D18C-4AB3-854F-7101680FC3F9} - {BD7F352C-6DC1-4740-BAF2-2D34A038728C} = {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} diff --git a/Avalonia.sln.DotSettings b/Avalonia.sln.DotSettings index 1fd6f8d092..d61208c358 100644 --- a/Avalonia.sln.DotSettings +++ b/Avalonia.sln.DotSettings @@ -1,4 +1,5 @@  + True ExplicitlyExcluded ExplicitlyExcluded ExplicitlyExcluded diff --git a/appveyor.yml b/appveyor.yml index ca548b6b0a..aa8c19ace4 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -16,9 +16,7 @@ environment: init: - ps: if (Test-Path env:nuget_address) {[System.IO.File]::AppendAllText("C:\Windows\System32\drivers\etc\hosts", "`n$($env:nuget_address)`tapi.nuget.org")} install: - - if not exist gtk-sharp-2.12.26.msi appveyor DownloadFile http://download.xamarin.com/GTKforWindows/Windows/gtk-sharp-2.12.26.msi - if not exist dotnet-2.0.0.exe appveyor DownloadFile https://download.microsoft.com/download/0/F/D/0FD852A4-7EA1-4E2A-983A-0484AC19B92C/dotnet-sdk-2.0.0-win-x64.exe -FileName "dotnet-2.0.0.exe" - - ps: Start-Process -FilePath "msiexec" -ArgumentList "/i gtk-sharp-2.12.26.msi /quiet /qn /norestart" -Wait - ps: Start-Process -FilePath "dotnet-2.0.0.exe" -ArgumentList "/quiet" -Wait - cmd: set PATH=%programfiles(x86)%\GtkSharp\2.12\bin\;%PATH% before_build: @@ -36,5 +34,4 @@ artifacts: - path: artifacts\zip\*.zip - path: artifacts\inspectcode.xml cache: - - gtk-sharp-2.12.26.msi - - dotnet-1.0.1.exe + - dotnet-2.0.0.exe diff --git a/build.cake b/build.cake index b7b349b12b..eb5918832e 100644 --- a/build.cake +++ b/build.cake @@ -2,16 +2,15 @@ // ADDINS /////////////////////////////////////////////////////////////////////////////// -#addin "nuget:?package=Polly&version=4.2.0" -#addin "nuget:?package=NuGet.Core&version=2.12.0" -#tool "nuget:?package=xunit.runner.console&version=2.2.0" -#tool "nuget:https://dotnet.myget.org/F/nuget-build/?package=NuGet.CommandLine&version=4.3.0-preview1-3980&prerelease" +#addin "nuget:?package=Polly&version=5.3.1" +#addin "nuget:?package=NuGet.Core&version=2.14.0" +#tool "nuget:?package=NuGet.CommandLine&version=4.3.0" #tool "nuget:?package=JetBrains.ReSharper.CommandLineTools&version=2017.1.20170613.162720" /////////////////////////////////////////////////////////////////////////////// // TOOLS /////////////////////////////////////////////////////////////////////////////// -#tool "nuget:?package=xunit.runner.console&version=2.2.0" +#tool "nuget:?package=xunit.runner.console&version=2.3.0-beta5-build3769" /////////////////////////////////////////////////////////////////////////////// // USINGS @@ -213,8 +212,8 @@ Task("Run-Unit-Tests") .ToList(); var toolPath = (parameters.IsPlatformAnyCPU || parameters.IsPlatformX86) ? - "./tools/xunit.runner.console/tools/xunit.console.x86.exe" : - "./tools/xunit.runner.console/tools/xunit.console.exe"; + Context.Tools.Resolve("xunit.console.x86.exe") : + Context.Tools.Resolve("xunit.console.exe"); var xUnitSettings = new XUnit2Settings { @@ -353,10 +352,12 @@ Task("Run-Leak-Tests") var report = "tests\\Avalonia.LeakTests\\bin\\Release\\report.xml"; if(System.IO.File.Exists(report)) System.IO.File.Delete(report); + + var toolXunitConsoleX86 = Context.Tools.Resolve("xunit.console.x86.exe").FullPath; var proc = System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo { FileName="tests\\Avalonia.LeakTests\\toolproject\\bin\\dotMemoryUnit.exe", - Arguments="-targetExecutable=\"tools\\xunit.runner.console\\tools\\xunit.console.x86.exe\" -returnTargetExitCode -- tests\\Avalonia.LeakTests\\bin\\Release\\Avalonia.LeakTests.dll -xml tests\\Avalonia.LeakTests\\bin\\Release\\report.xml ", + Arguments="-targetExecutable=\"" + toolXunitConsoleX86 + "\" -returnTargetExitCode -- tests\\Avalonia.LeakTests\\bin\\Release\\Avalonia.LeakTests.dll -xml tests\\Avalonia.LeakTests\\bin\\Release\\report.xml ", UseShellExecute = false, }); var st = System.Diagnostics.Stopwatch.StartNew(); @@ -392,8 +393,7 @@ Task("Inspect") "src\\markup\\avalonia.markup.xaml\\portablexaml\\portable.xaml.github"}; Information("Running code inspections"); - - StartProcess("tools\\JetBrains.ReSharper.CommandLineTools\\tools\\inspectcode.exe", + StartProcess(Context.Tools.Resolve("inspectcode.exe"), new ProcessSettings{ Arguments = "--output=artifacts\\inspectcode.xml --profile=Avalonia.sln.DotSettings Avalonia.sln" }); Information("Analyzing report"); var doc = XDocument.Parse(System.IO.File.ReadAllText("artifacts\\inspectcode.xml")); diff --git a/build/NetFX.props b/build/NetFX.props new file mode 100644 index 0000000000..d8b2daf13a --- /dev/null +++ b/build/NetFX.props @@ -0,0 +1,6 @@ + + + /usr/lib/mono/4.6.1-api + /Library/Frameworks/Mono.framework/Versions/Current/lib/mono/4.6.1-api + + diff --git a/build/XUnit.props b/build/XUnit.props index 9d4d401743..42fe9b6d7a 100644 --- a/build/XUnit.props +++ b/build/XUnit.props @@ -1,13 +1,14 @@  - + - - - - - - + + + + + + + @@ -24,4 +25,5 @@ true + diff --git a/docs/guidelines/build.md b/docs/guidelines/build.md index 0cf91d913a..559790b197 100644 --- a/docs/guidelines/build.md +++ b/docs/guidelines/build.md @@ -2,13 +2,7 @@ ## Windows -Avalonia requires at least Visual Studio 2017 to build on Windows. - -### Install GTK Sharp - -For the moment under windows, you must have [gtk-sharp](http://www.mono-project.com/download/#download-win) -installed. Note that after installing the package your machine may require a restart before GTK# is -added to your path. We hope to remove or make this dependency optional at some point in the future. +Avalonia requires at least Visual Studio 2017 and .NET Core SDK 2.0 to build on Windows. ### Clone the Avalonia repository @@ -22,69 +16,28 @@ git submodule update --init Open the `Avalonia.sln` solution in Visual Studio 2015 or newer. The free Visual Studio Community edition works fine. Run the `Samples\ControlCatalog.Desktop` project to see the sample application. -## Linux - -### Install the latest version of Mono +## Linux/OSX -To build Avalonia under Linux, you need to have a recent version of Mono installed. Mono is a cross- -platform, open source .Net platform. There is a very good chance that the version of Mono that came -with your Linux distribution is too old, so you want to install a more up-to-date version. The most -convenient way to to this is through your package manager. The Mono project has great [installation -instructions for many popular Linux distros](http://www.mono-project.com/docs/getting-started/install/linux). +It's *not* possible to build the *whole* project on Linux/OSX. You can only build the subset targeting .NET Standard and .NET Core (which is, however, sufficient to get UI working on Linux/OSX). If you want to something that involves changing platform-specific APIs you'll need a Windows machine. -This will make the most up-to-date Mono release available through your package manager, and offer -you updates as they become available. - -Once you have your package manager configured for the Mono repository, install the `mono-devel` -package, for example on ubuntu: - -``` -sudo apt-get install mono-devel -``` +MonoDevelop, Xamarin Studio and Visual Studio for Mac aren't capable of properly opening our solution. You can use Rider (at least 2017.2 EAP) or VSCode instead. They will fail to load most of platform specific projects, but you don't need them to run on .NET Core. -Once installed, check the version of mono to ensure it's at least 4.4.2: +### Install the latest version of .NET Core -``` -mono --version -``` +Go to https://www.microsoft.com/net/core and follow instructions for your OS. You need SDK (not just "runtime") package. ### Clone the Avalonia repository ``` git clone https://github.com/AvaloniaUI/Avalonia.git -git submodule update --init -``` - -### Restore nuget packages - -``` -cd Avalonia -mkdir -p .nuget -wget -O .nuget/nuget.exe https://dist.nuget.org/win-x86-commandline/latest/nuget.exe -mono .nuget/nuget.exe restore Avalonia.sln +git submodule update --init --recursive ``` ### Build and Run Avalonia -To build Avalonia in the `Debug` configuration: - -``` -xbuild /p:Platform=Mono /p:Configuration=Debug Avalonia.sln -``` - -You should now be able to run the ControlCatalog.Desktop sample: - ``` -mono ./samples/ControlCatalog.Desktop/bin/Debug/ControlCatalog.Desktop.exe +samples/ControlCatalog.NetCore +dotnet restore +dotnet run ``` -### Building Avalonia in MonoDevelop - -Flatpak version will *NOT* work. Version from https://github.com/cra0zy/monodevelop-run-installer/ might work if you are very lucky. Make sure that you have the latest version of Mono (from alpha update channel) and .NET Core SDK. Make sure to follow `FrameworkPathOverride` workaround from https://github.com/dotnet/sdk/issues/335 - -### Building and running Avalonia in Rider - -For Linux/OSX you'll probably need to apply workaround from https://github.com/dotnet/sdk/issues/335 - -Just add `export FrameworkPathOverride=/usr/lib/mono/4.6.1-api` (or `export FrameworkPathOverride=/Library/Frameworks/Mono.framework/Versions/Current/lib/mono/4.6.1-api` for OSX) - diff --git a/packages.cake b/packages.cake index 7ada627200..a22ff65e72 100644 --- a/packages.cake +++ b/packages.cake @@ -375,23 +375,6 @@ public class Packages OutputDirectory = parameters.NugetRoot }, /////////////////////////////////////////////////////////////////////////////// - // Avalonia.Gtk - /////////////////////////////////////////////////////////////////////////////// - new NuGetPackSettings() - { - Id = "Avalonia.Gtk", - Dependencies = new [] - { - new NuSpecDependency() { Id = "Avalonia", Version = parameters.Version } - }, - Files = new [] - { - new NuSpecContent { Source = "Avalonia.Gtk.dll", Target = "lib/net45" } - }, - BasePath = context.Directory("./src/Gtk/Avalonia.Gtk/bin/" + parameters.DirSuffix), - OutputDirectory = parameters.NugetRoot - }, - /////////////////////////////////////////////////////////////////////////////// // Avalonia.Gtk3 /////////////////////////////////////////////////////////////////////////////// new NuGetPackSettings() @@ -409,23 +392,6 @@ public class Packages OutputDirectory = parameters.NugetRoot }, /////////////////////////////////////////////////////////////////////////////// - // Avalonia.Cairo - /////////////////////////////////////////////////////////////////////////////// - new NuGetPackSettings() - { - Id = "Avalonia.Cairo", - Dependencies = new [] - { - new NuSpecDependency() { Id = "Avalonia", Version = parameters.Version } - }, - Files = new [] - { - new NuSpecContent { Source = "Avalonia.Cairo.dll", Target = "lib/net45" } - }, - BasePath = context.Directory("./src/Gtk/Avalonia.Cairo/bin/" + parameters.DirSuffix), - OutputDirectory = parameters.NugetRoot - }, - /////////////////////////////////////////////////////////////////////////////// // Avalonia.Skia /////////////////////////////////////////////////////////////////////////////// new NuGetPackSettings() @@ -471,19 +437,11 @@ public class Packages Id = "Avalonia.Desktop", Dependencies = new [] { - //Full .NET - new NuSpecDependency() { Id = "Avalonia.Direct2D1", TargetFramework="net45", Version = parameters.Version }, - new NuSpecDependency() { Id = "Avalonia.Gtk", TargetFramework="net45", Version = parameters.Version }, - new NuSpecDependency() { Id = "Avalonia.Cairo", TargetFramework="net45", Version = parameters.Version }, - new NuSpecDependency() { Id = "Avalonia.Win32", TargetFramework="net45", Version = parameters.Version }, - new NuSpecDependency() { Id = "Avalonia.Skia", TargetFramework="net45", Version = parameters.Version }, - new NuSpecDependency() { Id = "Avalonia.Gtk3", TargetFramework="net45", Version = parameters.Version }, - new NuSpecDependency() { Id = "Avalonia.MonoMac", TargetFramework="net45", Version = parameters.Version }, - //.NET Core - new NuSpecDependency() { Id = "Avalonia.Win32", TargetFramework="netcoreapp2.0", Version = parameters.Version }, - new NuSpecDependency() { Id = "Avalonia.Skia", TargetFramework="netcoreapp2.0", Version = parameters.Version }, - new NuSpecDependency() { Id = "Avalonia.Gtk3", TargetFramework="netcoreapp2.0", Version = parameters.Version }, - new NuSpecDependency() { Id = "Avalonia.MonoMac", TargetFramework="netcoreapp2.0", Version = parameters.Version } + new NuSpecDependency() { Id = "Avalonia.Direct2D1", Version = parameters.Version }, + new NuSpecDependency() { Id = "Avalonia.Win32", Version = parameters.Version }, + new NuSpecDependency() { Id = "Avalonia.Skia", Version = parameters.Version }, + new NuSpecDependency() { Id = "Avalonia.Gtk3", Version = parameters.Version }, + new NuSpecDependency() { Id = "Avalonia.MonoMac", Version = parameters.Version } }, Files = new NuSpecContent[] { diff --git a/readme.md b/readme.md index 9f16405726..3f4840fce2 100644 --- a/readme.md +++ b/readme.md @@ -7,7 +7,7 @@ A multi-platform .NET UI framework. It can run on Windows, Linux, Mac OS X, iOS and Android. -![](docs/images/screen.png) +[![](docs/images/screen.png)](https://youtu.be/wHcB3sGLVYg) Desktop platforms: @@ -36,7 +36,7 @@ Try out the ControlCatalog to give it a quick demo. Avalonia is a multi-platform windowing toolkit - somewhat like WPF - that is intended to be multi- platform. It supports XAML, lookless controls and a flexible styling system, and runs on Windows -using Direct2D and other operating systems using Gtk & Cairo. +using Direct2D and other operating systems using Skia and OS-specific windowing backend (GTK, Cocoa, etc). ## Current Status diff --git a/samples/BindingTest/BindingTest.csproj b/samples/BindingTest/BindingTest.csproj index b4dd17194b..d7d349fbdf 100644 --- a/samples/BindingTest/BindingTest.csproj +++ b/samples/BindingTest/BindingTest.csproj @@ -148,14 +148,6 @@ {811a76cf-1cf6-440f-963b-bbe31bd72a82} Avalonia.Win32 - - {54F237D5-A70A-4752-9656-0C70B1A7B047} - Avalonia.Gtk - - - {FB05AC90-89BA-4F2F-A924-F37875FB547C} - Avalonia.Cairo - diff --git a/samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj b/samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj index 91d24f9152..3f4679086e 100644 --- a/samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj +++ b/samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj @@ -63,18 +63,10 @@ {4A1ABB09-9047-4BD5-A4AD-A055E52C5EE0} Avalonia.DotNetFrameworkRuntime - - {FB05AC90-89BA-4F2F-A924-F37875FB547C} - Avalonia.Cairo - {bb1f7bb5-6ad4-4776-94d9-c09d0a972658} Avalonia.Gtk3 - - {54F237D5-A70A-4752-9656-0C70B1A7B047} - Avalonia.Gtk - {3E53A01A-B331-47F3-B828-4A5717E77A24} Avalonia.Markup.Xaml diff --git a/samples/ControlCatalog/Assets/test_icon.ico b/samples/ControlCatalog/Assets/test_icon.ico index 9d1074ad13..da8d49ff9b 100644 Binary files a/samples/ControlCatalog/Assets/test_icon.ico and b/samples/ControlCatalog/Assets/test_icon.ico differ diff --git a/samples/ControlCatalog/ControlCatalog.csproj b/samples/ControlCatalog/ControlCatalog.csproj index 76114c385b..11ff531514 100644 --- a/samples/ControlCatalog/ControlCatalog.csproj +++ b/samples/ControlCatalog/ControlCatalog.csproj @@ -69,6 +69,9 @@ Designer + + Designer + Designer @@ -131,12 +134,15 @@ MenuPage.xaml + + ProgressBarPage.xaml + RadioButtonPage.xaml SliderPage.xaml - + TreeViewPage.xaml @@ -146,6 +152,7 @@ ToolTipPage.xaml + diff --git a/samples/ControlCatalog/MainView.xaml b/samples/ControlCatalog/MainView.xaml index 6c432a90ac..0940316ce9 100644 --- a/samples/ControlCatalog/MainView.xaml +++ b/samples/ControlCatalog/MainView.xaml @@ -16,6 +16,7 @@ + diff --git a/samples/ControlCatalog/MainView.xaml.cs b/samples/ControlCatalog/MainView.xaml.cs index a3b8708c29..0be5d25a09 100644 --- a/samples/ControlCatalog/MainView.xaml.cs +++ b/samples/ControlCatalog/MainView.xaml.cs @@ -13,11 +13,20 @@ namespace ControlCatalog { this.InitializeComponent(); if (AvaloniaLocator.Current.GetService().GetRuntimeInfo().IsDesktop) - ((IList) this.FindControl("Sidebar").Items).Add(new TabItem() + { + IList tabItems = ((IList)this.FindControl("Sidebar").Items); + tabItems.Add(new TabItem() { Header = "Dialogs", Content = new DialogsPage() }); + tabItems.Add(new TabItem() + { + Header = "Screens", + Content = new ScreenPage() + }); + + } } private void InitializeComponent() diff --git a/samples/ControlCatalog/MainWindow.xaml.cs b/samples/ControlCatalog/MainWindow.xaml.cs index ed0bffdf10..e620a77e52 100644 --- a/samples/ControlCatalog/MainWindow.xaml.cs +++ b/samples/ControlCatalog/MainWindow.xaml.cs @@ -11,6 +11,7 @@ namespace ControlCatalog { this.InitializeComponent(); this.AttachDevTools(); + //Renderer.DrawFps = true; //Renderer.DrawDirtyRects = Renderer.DrawFps = true; } diff --git a/samples/ControlCatalog/Pages/ProgressBarPage.xaml b/samples/ControlCatalog/Pages/ProgressBarPage.xaml new file mode 100644 index 0000000000..bf40e68630 --- /dev/null +++ b/samples/ControlCatalog/Pages/ProgressBarPage.xaml @@ -0,0 +1,24 @@ + + + ProgressBar + A progress bar control + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/samples/ControlCatalog/Pages/ProgressBarPage.xaml.cs b/samples/ControlCatalog/Pages/ProgressBarPage.xaml.cs new file mode 100644 index 0000000000..56792b3908 --- /dev/null +++ b/samples/ControlCatalog/Pages/ProgressBarPage.xaml.cs @@ -0,0 +1,18 @@ +using Avalonia.Controls; +using Avalonia.Markup.Xaml; + +namespace ControlCatalog.Pages +{ + public class ProgressBarPage : UserControl + { + public ProgressBarPage() + { + this.InitializeComponent(); + } + + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); + } + } +} diff --git a/samples/ControlCatalog/Pages/ScreenPage.cs b/samples/ControlCatalog/Pages/ScreenPage.cs new file mode 100644 index 0000000000..34aa85b8aa --- /dev/null +++ b/samples/ControlCatalog/Pages/ScreenPage.cs @@ -0,0 +1,62 @@ +using System; +using Avalonia; +using Avalonia.Controls; +using Avalonia.Markup.Xaml; +using Avalonia.Media; +using Avalonia.Platform; + +namespace ControlCatalog.Pages +{ + public class ScreenPage : UserControl + { + private double _leftMost; + + protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) + { + base.OnAttachedToVisualTree(e); + Window w = (Window)VisualRoot; + w.PositionChanged += (sender, args) => InvalidateVisual(); + } + + public override void Render(DrawingContext context) + { + base.Render(context); + Window w = (Window)VisualRoot; + Screen[] screens = w.Screens.All; + + Pen p = new Pen(Brushes.Black); + if (screens != null) + foreach (Screen screen in screens) + { + if (screen.Bounds.X / 10f < _leftMost) + { + _leftMost = screen.Bounds.X / 10f; + InvalidateVisual(); + return; + } + + Rect boundsRect = new Rect(screen.Bounds.X / 10f + Math.Abs(_leftMost), screen.Bounds.Y / 10f, screen.Bounds.Width / 10f, + screen.Bounds.Height / 10f); + Rect workingAreaRect = new Rect(screen.WorkingArea.X / 10f + Math.Abs(_leftMost), screen.WorkingArea.Y / 10f, screen.WorkingArea.Width / 10f, + screen.WorkingArea.Height / 10f); + context.DrawRectangle(p, boundsRect); + context.DrawRectangle(p, workingAreaRect); + + FormattedText text = new FormattedText(); + text.Text = $"Bounds: {screen.Bounds.Width}:{screen.Bounds.Height}"; + context.DrawText(Brushes.Black, boundsRect.Position.WithY(boundsRect.Size.Height), text); + + text.Text = $"WorkArea: {screen.WorkingArea.Width}:{screen.WorkingArea.Height}"; + context.DrawText(Brushes.Black, boundsRect.Position.WithY(boundsRect.Size.Height + 20), text); + + text.Text = $"Primary: {screen.Primary}"; + context.DrawText(Brushes.Black, boundsRect.Position.WithY(boundsRect.Size.Height + 40), text); + + text.Text = $"Current: {screen.Equals(w.Screens.ScreenFromBounds(new Rect(w.Position, w.Bounds.Size)))}"; + context.DrawText(Brushes.Black, boundsRect.Position.WithY(boundsRect.Size.Height + 60), text); + } + + context.DrawRectangle(p, new Rect(w.Position.X / 10f + Math.Abs(_leftMost), w.Position.Y / 10, w.Bounds.Width / 10, w.Bounds.Height / 10)); + } + } +} \ No newline at end of file diff --git a/samples/ControlCatalog/Pages/ToolTipPage.xaml b/samples/ControlCatalog/Pages/ToolTipPage.xaml index 5cf7fee4d1..aa7d60bd11 100644 --- a/samples/ControlCatalog/Pages/ToolTipPage.xaml +++ b/samples/ControlCatalog/Pages/ToolTipPage.xaml @@ -10,7 +10,7 @@ HorizontalAlignment="Center"> @@ -24,7 +24,7 @@ diff --git a/samples/ControlCatalog/Program.cs b/samples/ControlCatalog/Program.cs deleted file mode 100644 index f975b91834..0000000000 --- a/samples/ControlCatalog/Program.cs +++ /dev/null @@ -1,126 +0,0 @@ -using Avalonia.Logging.Serilog; -using Serilog; -using System; -using System.Linq; -using Avalonia; - -namespace ControlCatalog -{ - internal class Program - { - static void Main(string[] args) - { - InitializeLogging(); - - new App() - .ConfigureRenderSystem(args) - .LoadFromXaml() - .RunWithMainWindow(); - } - - // This will be made into a runtime configuration extension soon! - private static void InitializeLogging() - { -#if DEBUG - SerilogLogger.Initialize(new LoggerConfiguration() - .MinimumLevel.Warning() - .WriteTo.Trace(outputTemplate: "{Area}: {Message}") - .CreateLogger()); -#endif - } - - } - - ///////////////////////////////////////////////////////////////////////////////////////////////////////////// - // Experimental: Would like to move this into a shared location once I figure out the best place for it - // considering all common libraries are PCL and do not have access to Environment.OSVersion.Platform - // nor do they have access to the platform specific render/subsystem extensions. - // - // Perhaps via DI we register each system with a priority/rank - // - public static class RenderSystemExtensions - { - [Flags] - enum RenderSystem - { - None = 0, - GTK = 1, - Skia = 2, - Direct2D = 4 - }; - - /// - /// Default (Optimal) render system for a particular platform - /// - /// - private static RenderSystem DefaultRenderSystem() - { - switch (Environment.OSVersion.Platform) - { - case PlatformID.MacOSX: - return RenderSystem.GTK; - - case PlatformID.Unix: - return RenderSystem.GTK; - - case PlatformID.Win32Windows: - return RenderSystem.Direct2D; - } - - return RenderSystem.None; - } - - /// - /// Returns an array of avalidable rendering systems in priority order - /// - /// - private static RenderSystem[] AvailableRenderSystems() - { - switch (Environment.OSVersion.Platform) - { - case PlatformID.MacOSX: - return new RenderSystem[] { RenderSystem.GTK, RenderSystem.Skia }; - - case PlatformID.Unix: - return new RenderSystem[] { RenderSystem.GTK, RenderSystem.Skia }; - - case PlatformID.Win32Windows: - return new RenderSystem[] { RenderSystem.Direct2D, RenderSystem.Skia, RenderSystem.GTK }; - } - - return new RenderSystem[0]; - } - - /// - /// Selects the optimal render system for desktop platforms. Supports cmd line overrides - /// - /// - /// - public static TApp ConfigureRenderSystem(this TApp app, string[] args) where TApp : Application - { - // So this all works great under Windows where it can support - // ALL configurations. But on OSX/Unix we cannot use Direct2D - // - if (args.Contains("--gtk") || DefaultRenderSystem() == RenderSystem.GTK) - { - app.UseGtk(); - app.UseCairo(); - } - else - { - app.UseWin32(); - - if (args.Contains("--skia") || DefaultRenderSystem() == RenderSystem.Skia) - { - app.UseSkia(); - } - else - { - app.UseDirect2D(); - } - } - - return app; - } - } -} diff --git a/samples/RenderTest/RenderTest.csproj b/samples/RenderTest/RenderTest.csproj index 974b8802ac..0141ad29c6 100644 --- a/samples/RenderTest/RenderTest.csproj +++ b/samples/RenderTest/RenderTest.csproj @@ -132,14 +132,6 @@ {3e10a5fa-e8da-48b1-ad44-6a5b6cb7750f} Avalonia.Themes.Default - - {fb05ac90-89ba-4f2f-a924-f37875fb547c} - Avalonia.Cairo - - - {54f237d5-a70a-4752-9656-0c70b1a7b047} - Avalonia.Gtk - {3e53a01a-b331-47f3-b828-4a5717e77a24} Avalonia.Markup.Xaml diff --git a/samples/VirtualizationTest/VirtualizationTest.csproj b/samples/VirtualizationTest/VirtualizationTest.csproj index 9d31a6cb86..58775926cc 100644 --- a/samples/VirtualizationTest/VirtualizationTest.csproj +++ b/samples/VirtualizationTest/VirtualizationTest.csproj @@ -134,14 +134,6 @@ {811a76cf-1cf6-440f-963b-bbe31bd72a82} Avalonia.Win32 - - {FB05AC90-89BA-4F2F-A924-F37875FB547C} - Avalonia.Cairo - - - {54F237D5-A70A-4752-9656-0C70B1A7B047} - Avalonia.Gtk - diff --git a/samples/interop/GtkInteropDemo/App.config b/samples/interop/GtkInteropDemo/App.config deleted file mode 100644 index 8324aa6ff1..0000000000 --- a/samples/interop/GtkInteropDemo/App.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/samples/interop/GtkInteropDemo/GtkInteropDemo.csproj b/samples/interop/GtkInteropDemo/GtkInteropDemo.csproj deleted file mode 100644 index 8382426620..0000000000 --- a/samples/interop/GtkInteropDemo/GtkInteropDemo.csproj +++ /dev/null @@ -1,154 +0,0 @@ - - - - - Debug - AnyCPU - {BD7F352C-6DC1-4740-BAF2-2D34A038728C} - WinExe - Properties - GtkInteropDemo - GtkInteropDemo - v4.6.1 - 512 - true - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - false - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - - - - - - - - - - - - - - - - - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - - - - - - - {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 - - - {4a1abb09-9047-4bd5-a4ad-a055e52c5ee0} - Avalonia.DotNetFrameworkRuntime - - - {62024b2d-53eb-4638-b26b-85eeaa54866e} - Avalonia.Input - - - {6b0ed19d-a08b-461c-a9d9-a9ee40b0c06b} - Avalonia.Interactivity - - - {42472427-4774-4c81-8aff-9f27b8e31721} - Avalonia.Layout - - - {6417b24e-49c2-4985-8db2-3ab9d898ec91} - Avalonia.ReactiveUI - - - {eb582467-6abb-43a1-b052-e981ba910e3a} - Avalonia.Visuals - - - {f1baa01a-f176-4c6a-b39d-5b40bb1b148f} - Avalonia.Styling - - - {3e10a5fa-e8da-48b1-ad44-6a5b6cb7750f} - Avalonia.Themes.Default - - - {fb05ac90-89ba-4f2f-a924-f37875fb547c} - Avalonia.Cairo - - - {54f237d5-a70a-4752-9656-0c70b1a7b047} - Avalonia.Gtk - - - {3e53a01a-b331-47f3-b828-4a5717e77a24} - Avalonia.Markup.Xaml - - - {6417e941-21bc-467b-a771-0de389353ce6} - Avalonia.Markup - - - {7d2d3083-71dd-4cc9-8907-39a0d86fb322} - Avalonia.Skia - - - {d0a739b9-3c68-4ba6-a328-41606954b6bd} - ControlCatalog - - - - - \ No newline at end of file diff --git a/samples/interop/GtkInteropDemo/MainWindow.cs b/samples/interop/GtkInteropDemo/MainWindow.cs deleted file mode 100644 index 2c193f24e8..0000000000 --- a/samples/interop/GtkInteropDemo/MainWindow.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Avalonia.Diagnostics; -using Avalonia.Gtk.Embedding; -using ControlCatalog; -using Gtk; - -namespace GtkInteropDemo -{ - class MainWindow : Window - { - public MainWindow() : base("Gtk Embedding Demo") - { - var root = new HBox(); - var left = new VBox(); - left.Add(new Button("I'm GTK button")); - left.Add(new Calendar()); - root.PackEnd(left, false, false, 0); - var host = new GtkAvaloniaControlHost() {Content = new MainView()}; - host.SetSizeRequest(600, 600); - root.PackStart(host, true, true, 0); - Add(root); - - ShowAll(); - } - } -} diff --git a/samples/interop/GtkInteropDemo/Program.cs b/samples/interop/GtkInteropDemo/Program.cs deleted file mode 100644 index 7dd39c74ca..0000000000 --- a/samples/interop/GtkInteropDemo/Program.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Avalonia; -using Avalonia.Controls; -using ControlCatalog; - -namespace GtkInteropDemo -{ - static class Program - { - /// - /// The main entry point for the application. - /// - [STAThread] - static void Main() - { - AppBuilder.Configure().UseGtk().UseCairo().SetupWithoutStarting(); - new MainWindow().Show(); - Gtk.Application.Run(); - } - } -} diff --git a/samples/interop/GtkInteropDemo/Properties/AssemblyInfo.cs b/samples/interop/GtkInteropDemo/Properties/AssemblyInfo.cs deleted file mode 100644 index 8aaf28c2f0..0000000000 --- a/samples/interop/GtkInteropDemo/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("GtkInteropDemo")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("GtkInteropDemo")] -[assembly: AssemblyCopyright("Copyright © 2016")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("bd7f352c-6dc1-4740-baf2-2d34a038728c")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/samples/interop/GtkInteropDemo/Properties/Resources.Designer.cs b/samples/interop/GtkInteropDemo/Properties/Resources.Designer.cs deleted file mode 100644 index f79a8bf680..0000000000 --- a/samples/interop/GtkInteropDemo/Properties/Resources.Designer.cs +++ /dev/null @@ -1,71 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace GtkInteropDemo.Properties -{ - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources - { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() - { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager - { - get - { - if ((resourceMan == null)) - { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("GtkInteropDemo.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture - { - get - { - return resourceCulture; - } - set - { - resourceCulture = value; - } - } - } -} diff --git a/samples/interop/GtkInteropDemo/Properties/Resources.resx b/samples/interop/GtkInteropDemo/Properties/Resources.resx deleted file mode 100644 index af7dbebbac..0000000000 --- a/samples/interop/GtkInteropDemo/Properties/Resources.resx +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/samples/interop/GtkInteropDemo/Properties/Settings.Designer.cs b/samples/interop/GtkInteropDemo/Properties/Settings.Designer.cs deleted file mode 100644 index 8173ee7dfa..0000000000 --- a/samples/interop/GtkInteropDemo/Properties/Settings.Designer.cs +++ /dev/null @@ -1,30 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace GtkInteropDemo.Properties -{ - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase - { - - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default - { - get - { - return defaultInstance; - } - } - } -} diff --git a/samples/interop/GtkInteropDemo/Properties/Settings.settings b/samples/interop/GtkInteropDemo/Properties/Settings.settings deleted file mode 100644 index 39645652af..0000000000 --- a/samples/interop/GtkInteropDemo/Properties/Settings.settings +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/src/Android/Avalonia.Android/AndroidThreadingInterface.cs b/src/Android/Avalonia.Android/AndroidThreadingInterface.cs index 6327be12a5..2e5b2902f4 100644 --- a/src/Android/Avalonia.Android/AndroidThreadingInterface.cs +++ b/src/Android/Avalonia.Android/AndroidThreadingInterface.cs @@ -12,6 +12,7 @@ using Android.Runtime; using Android.Views; using Android.Widget; using Avalonia.Platform; +using Avalonia.Threading; namespace Avalonia.Android { @@ -78,13 +79,13 @@ namespace Avalonia.Android private void EnsureInvokeOnMainThread(Action action) => _handler.Post(action); - public void Signal() + public void Signal(DispatcherPriority prio) { - EnsureInvokeOnMainThread(() => Signaled?.Invoke()); + EnsureInvokeOnMainThread(() => Signaled?.Invoke(null)); } public bool CurrentThreadIsLoopThread => Looper.MainLooper.Thread.Equals(Java.Lang.Thread.CurrentThread()); - public event Action Signaled; + public event Action Signaled; } } \ No newline at end of file diff --git a/src/Android/Avalonia.Android/Platform/SkiaPlatform/PopupImpl.cs b/src/Android/Avalonia.Android/Platform/SkiaPlatform/PopupImpl.cs index efbc71b808..0b683239fb 100644 --- a/src/Android/Avalonia.Android/Platform/SkiaPlatform/PopupImpl.cs +++ b/src/Android/Avalonia.Android/Platform/SkiaPlatform/PopupImpl.cs @@ -36,6 +36,8 @@ namespace Avalonia.Android.Platform.SkiaPlatform _clientSize = value; UpdateParams(); } + + public IScreenImpl Screen { get; } public Point Position { diff --git a/src/Avalonia.Base/Platform/IPlatformThreadingInterface.cs b/src/Avalonia.Base/Platform/IPlatformThreadingInterface.cs index 8101e4b550..68f9e2c631 100644 --- a/src/Avalonia.Base/Platform/IPlatformThreadingInterface.cs +++ b/src/Avalonia.Base/Platform/IPlatformThreadingInterface.cs @@ -3,6 +3,7 @@ using System; using System.Threading; +using Avalonia.Threading; namespace Avalonia.Platform { @@ -21,10 +22,10 @@ namespace Avalonia.Platform /// An used to stop the timer. IDisposable StartTimer(TimeSpan interval, Action tick); - void Signal(); + void Signal(DispatcherPriority priority); bool CurrentThreadIsLoopThread { get; } - event Action Signaled; + event Action Signaled; } } diff --git a/src/Avalonia.Base/Threading/AvaloniaSynchronizationContext.cs b/src/Avalonia.Base/Threading/AvaloniaSynchronizationContext.cs index c32aeed0b4..7a0249f876 100644 --- a/src/Avalonia.Base/Threading/AvaloniaSynchronizationContext.cs +++ b/src/Avalonia.Base/Threading/AvaloniaSynchronizationContext.cs @@ -36,7 +36,7 @@ namespace Avalonia.Threading /// public override void Post(SendOrPostCallback d, object state) { - Dispatcher.UIThread.InvokeAsync(() => d(state)); + Dispatcher.UIThread.InvokeAsync(() => d(state), DispatcherPriority.Send); } /// @@ -45,7 +45,7 @@ namespace Avalonia.Threading if (Dispatcher.UIThread.CheckAccess()) d(state); else - Dispatcher.UIThread.InvokeTaskAsync(() => d(state)).Wait(); + Dispatcher.UIThread.InvokeTaskAsync(() => d(state), DispatcherPriority.Send).Wait(); } } } \ No newline at end of file diff --git a/src/Avalonia.Base/Threading/Dispatcher.cs b/src/Avalonia.Base/Threading/Dispatcher.cs index d46b7142f4..a60b663bed 100644 --- a/src/Avalonia.Base/Threading/Dispatcher.cs +++ b/src/Avalonia.Base/Threading/Dispatcher.cs @@ -60,7 +60,7 @@ namespace Avalonia.Threading public void MainLoop(CancellationToken cancellationToken) { var platform = AvaloniaLocator.Current.GetService(); - cancellationToken.Register(platform.Signal); + cancellationToken.Register(() => platform.Signal(DispatcherPriority.Send)); platform.RunLoop(cancellationToken); } @@ -69,7 +69,7 @@ namespace Avalonia.Threading /// public void RunJobs() { - _jobRunner?.RunJobs(); + _jobRunner?.RunJobs(null); } /// diff --git a/src/Avalonia.Base/Threading/DispatcherPriority.cs b/src/Avalonia.Base/Threading/DispatcherPriority.cs index 8d6be6eeec..1faa2da7f8 100644 --- a/src/Avalonia.Base/Threading/DispatcherPriority.cs +++ b/src/Avalonia.Base/Threading/DispatcherPriority.cs @@ -10,10 +10,10 @@ namespace Avalonia.Threading public enum DispatcherPriority { /// - /// The job will not be processed. + /// Minimum possible priority /// - Inactive = 0, - + MinValue = 1, + /// /// The job will be processed when the system is idle. /// @@ -48,20 +48,30 @@ namespace Avalonia.Threading /// The job will be processed with the same priority as render. /// Render = 7, - + + /// + /// The job will be processed with the same priority as render. + /// + Layout = 8, + /// /// The job will be processed with the same priority as data binding. /// - DataBind = 8, + DataBind = 9, /// /// The job will be processed with normal priority. /// - Normal = 9, + Normal = 10, /// /// The job will be processed before other asynchronous operations. /// - Send = 10, + Send = 11, + + /// + /// Maximum possible priority + /// + MaxValue = 11 } } diff --git a/src/Avalonia.Base/Threading/JobRunner.cs b/src/Avalonia.Base/Threading/JobRunner.cs index e212cd9a2e..c2040a0982 100644 --- a/src/Avalonia.Base/Threading/JobRunner.cs +++ b/src/Avalonia.Base/Threading/JobRunner.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using Avalonia.Platform; @@ -13,29 +14,45 @@ namespace Avalonia.Threading /// internal class JobRunner { - private readonly Queue _queue = new Queue(); + + private IPlatformThreadingInterface _platform; + private Queue[] _queues = Enumerable.Range(0, (int) DispatcherPriority.MaxValue + 1) + .Select(_ => new Queue()).ToArray(); + public JobRunner(IPlatformThreadingInterface platform) { _platform = platform; } + Job GetNextJob(DispatcherPriority minimumPriority) + { + for (int c = (int) DispatcherPriority.MaxValue; c >= (int) minimumPriority; c--) + { + var q = _queues[c]; + lock (q) + { + if (q.Count > 0) + return q.Dequeue(); + } + } + return null; + } + /// /// Runs continuations pushed on the loop. /// - public void RunJobs() + /// Priority to execute jobs for. Pass null if platform doesn't have internal priority system + public void RunJobs(DispatcherPriority? priority) { + var minimumPriority = priority ?? DispatcherPriority.MinValue; while (true) { - Job job; - - lock (_queue) - { - if (_queue.Count == 0) - return; - job = _queue.Dequeue(); - } + var job = GetNextJob(minimumPriority); + if (job == null) + return; + if (job.TaskCompletionSource == null) { @@ -77,7 +94,6 @@ namespace Avalonia.Threading /// The priority with which to invoke the method. internal void Post(Action action, DispatcherPriority priority) { - // TODO: Respect priority. AddJob(new Job(action, priority, true)); } @@ -92,13 +108,14 @@ namespace Avalonia.Threading private void AddJob(Job job) { var needWake = false; - lock (_queue) + var queue = _queues[(int) job.Priority]; + lock (queue) { - needWake = _queue.Count == 0; - _queue.Enqueue(job); + needWake = queue.Count == 0; + queue.Enqueue(job); } if (needWake) - _platform?.Signal(); + _platform?.Signal(job.Priority); } /// diff --git a/src/Avalonia.Base/Threading/SingleThreadDispatcher.cs b/src/Avalonia.Base/Threading/SingleThreadDispatcher.cs deleted file mode 100644 index 76d47b30b0..0000000000 --- a/src/Avalonia.Base/Threading/SingleThreadDispatcher.cs +++ /dev/null @@ -1,60 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Avalonia.Platform; - -namespace Avalonia.Threading -{ - public class SingleThreadDispatcher : Dispatcher - { - class ThreadingInterface : IPlatformThreadingInterface - { - private readonly AutoResetEvent _evnt = new AutoResetEvent(false); - private readonly JobRunner _timerJobRunner; - - public ThreadingInterface() - { - _timerJobRunner = new JobRunner(this); - } - - public void RunLoop(CancellationToken cancellationToken) - { - while (!cancellationToken.IsCancellationRequested) - { - _evnt.WaitOne(); - if (cancellationToken.IsCancellationRequested) - return; - Signaled?.Invoke(); - _timerJobRunner.RunJobs(); - } - } - - public IDisposable StartTimer(TimeSpan interval, Action tick) - => AvaloniaLocator.Current.GetService().StartSystemTimer(interval, - () => _timerJobRunner.Post(tick, DispatcherPriority.Normal)); - - public void Signal() => _evnt.Set(); - //TODO: Actually perform a check - public bool CurrentThreadIsLoopThread => true; - - public event Action Signaled; - } - - public SingleThreadDispatcher() : base(new ThreadingInterface()) - { - } - - public static Dispatcher StartNew(CancellationToken token) - { - var dispatcher = new SingleThreadDispatcher(); - AvaloniaLocator.Current.GetService().PostThreadPoolItem(() => - { - dispatcher.MainLoop(token); - }); - return dispatcher; - } - } -} diff --git a/src/Avalonia.Base/Utilities/WeakTimer.cs b/src/Avalonia.Base/Utilities/WeakTimer.cs index a68ed9072f..5c44a6d122 100644 --- a/src/Avalonia.Base/Utilities/WeakTimer.cs +++ b/src/Avalonia.Base/Utilities/WeakTimer.cs @@ -23,7 +23,6 @@ namespace Avalonia.Utilities _timer = new DispatcherTimer(); _timer.Tick += delegate { OnTick(); }; - _timer.Start(); } private void OnTick() diff --git a/src/Avalonia.Controls/Orientation.cs b/src/Avalonia.Controls/Orientation.cs new file mode 100644 index 0000000000..fe998c024a --- /dev/null +++ b/src/Avalonia.Controls/Orientation.cs @@ -0,0 +1,21 @@ +// 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. + +namespace Avalonia.Controls +{ + /// + /// Defines vertical or horizontal orientation. + /// + public enum Orientation + { + /// + /// Horizontal orientation. + /// + Horizontal, + + /// + /// Vertical orientation. + /// + Vertical, + } +} diff --git a/src/Avalonia.Controls/Platform/IScreenImpl.cs b/src/Avalonia.Controls/Platform/IScreenImpl.cs new file mode 100644 index 0000000000..dafa1de473 --- /dev/null +++ b/src/Avalonia.Controls/Platform/IScreenImpl.cs @@ -0,0 +1,9 @@ +namespace Avalonia.Platform +{ + public interface IScreenImpl + { + int ScreenCount { get; } + + Screen[] AllScreens { get; } + } +} \ No newline at end of file diff --git a/src/Avalonia.Controls/Platform/IWindowBaseImpl.cs b/src/Avalonia.Controls/Platform/IWindowBaseImpl.cs index a5c7c60843..0a01cf3df4 100644 --- a/src/Avalonia.Controls/Platform/IWindowBaseImpl.cs +++ b/src/Avalonia.Controls/Platform/IWindowBaseImpl.cs @@ -65,5 +65,10 @@ namespace Avalonia.Platform /// Sets the client size of the toplevel. /// void Resize(Size clientSize); + + /// + /// Gets platform specific display information + /// + IScreenImpl Screen { get; } } } \ No newline at end of file diff --git a/src/Avalonia.Controls/Platform/Screen.cs b/src/Avalonia.Controls/Platform/Screen.cs new file mode 100644 index 0000000000..5aa8c2c392 --- /dev/null +++ b/src/Avalonia.Controls/Platform/Screen.cs @@ -0,0 +1,18 @@ +namespace Avalonia.Platform +{ + public class Screen + { + public Rect Bounds { get; } + + public Rect WorkingArea { get; } + + public bool Primary { get; } + + public Screen(Rect bounds, Rect workingArea, bool primary) + { + this.Bounds = bounds; + this.WorkingArea = workingArea; + this.Primary = primary; + } + } +} \ No newline at end of file diff --git a/src/Avalonia.Controls/Primitives/ScrollBar.cs b/src/Avalonia.Controls/Primitives/ScrollBar.cs index 0f69e4e5bc..009e1d0ab8 100644 --- a/src/Avalonia.Controls/Primitives/ScrollBar.cs +++ b/src/Avalonia.Controls/Primitives/ScrollBar.cs @@ -30,7 +30,7 @@ namespace Avalonia.Controls.Primitives /// Defines the property. /// public static readonly StyledProperty OrientationProperty = - AvaloniaProperty.Register(nameof(Orientation)); + AvaloniaProperty.Register(nameof(Orientation), Orientation.Vertical); private Button _lineUpButton; private Button _lineDownButton; diff --git a/src/Avalonia.Controls/Primitives/Track.cs b/src/Avalonia.Controls/Primitives/Track.cs index a9b6afc172..663b7a22d5 100644 --- a/src/Avalonia.Controls/Primitives/Track.cs +++ b/src/Avalonia.Controls/Primitives/Track.cs @@ -165,7 +165,7 @@ namespace Avalonia.Controls.Primitives if (increaseButton != null) { - increaseButton.Arrange(new Rect(0, firstHeight + thumbHeight, finalSize.Width, remaining - firstHeight)); + increaseButton.Arrange(new Rect(0, firstHeight + thumbHeight, finalSize.Width, Math.Max(remaining - firstHeight, 0))); } } diff --git a/src/Avalonia.Controls/ProgressBar.cs b/src/Avalonia.Controls/ProgressBar.cs index a31a27ddfe..0ff3a78c1f 100644 --- a/src/Avalonia.Controls/ProgressBar.cs +++ b/src/Avalonia.Controls/ProgressBar.cs @@ -1,8 +1,12 @@ // 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.Reactive.Linq; + +using Avalonia.Animation; using Avalonia.Controls.Primitives; -using Avalonia.Controls.Templates; +using Avalonia.Layout; namespace Avalonia.Controls { @@ -11,11 +15,38 @@ namespace Avalonia.Controls /// public class ProgressBar : RangeBase { + public static readonly StyledProperty IsIndeterminateProperty = + AvaloniaProperty.Register(nameof(IsIndeterminate)); + + public static readonly StyledProperty OrientationProperty = + AvaloniaProperty.Register(nameof(Orientation), Orientation.Horizontal); + private Border _indicator; + private IndeterminateAnimation _indeterminateAnimation; static ProgressBar() { ValueProperty.Changed.AddClassHandler(x => x.ValueChanged); + + HorizontalAlignmentProperty.OverrideDefaultValue(HorizontalAlignment.Left); + VerticalAlignmentProperty.OverrideDefaultValue(VerticalAlignment.Top); + + IsIndeterminateProperty.Changed.AddClassHandler( + (p, e) => { if (p._indicator != null) p.UpdateIsIndeterminate((bool)e.NewValue); }); + OrientationProperty.Changed.AddClassHandler( + (p, e) => { if (p._indicator != null) p.UpdateOrientation((Orientation)e.NewValue); }); + } + + public bool IsIndeterminate + { + get => GetValue(IsIndeterminateProperty); + set => SetValue(IsIndeterminateProperty, value); + } + + public Orientation Orientation + { + get => GetValue(OrientationProperty); + set => SetValue(OrientationProperty, value); } /// @@ -29,21 +60,123 @@ namespace Avalonia.Controls protected override void OnTemplateApplied(TemplateAppliedEventArgs e) { _indicator = e.NameScope.Get("PART_Indicator"); + UpdateIndicator(Bounds.Size); + UpdateOrientation(Orientation); + UpdateIsIndeterminate(IsIndeterminate); } private void UpdateIndicator(Size bounds) { if (_indicator != null) { - double percent = Maximum == Minimum ? 1.0 : (Value - Minimum) / (Maximum - Minimum); - _indicator.Width = bounds.Width * percent; + if (IsIndeterminate) + { + if (Orientation == Orientation.Horizontal) + _indicator.Width = bounds.Width / 5.0; + else + _indicator.Height = bounds.Height / 5.0; + } + else + { + double percent = Maximum == Minimum ? 1.0 : (Value - Minimum) / (Maximum - Minimum); + + if (Orientation == Orientation.Horizontal) + _indicator.Width = bounds.Width * percent; + else + _indicator.Height = bounds.Height * percent; + } + } + } + + private void UpdateOrientation(Orientation orientation) + { + if (orientation == Orientation.Horizontal) + { + MinHeight = 14; + MinWidth = 200; + + _indicator.HorizontalAlignment = HorizontalAlignment.Left; + _indicator.VerticalAlignment = VerticalAlignment.Stretch; + } + else + { + MinHeight = 200; + MinWidth = 14; + + _indicator.HorizontalAlignment = HorizontalAlignment.Stretch; + _indicator.VerticalAlignment = VerticalAlignment.Bottom; } } + private void UpdateIsIndeterminate(bool isIndeterminate) + { + if (isIndeterminate) + if (_indeterminateAnimation == null || _indeterminateAnimation.Disposed) + _indeterminateAnimation = IndeterminateAnimation.StartAnimation(this); + else + _indeterminateAnimation?.Dispose(); + } + private void ValueChanged(AvaloniaPropertyChangedEventArgs e) { UpdateIndicator(Bounds.Size); } + + private class IndeterminateAnimation : IDisposable + { + private WeakReference _progressBar; + private IDisposable _indeterminateBindSubscription; + private TimeSpan _startTime; + private bool _disposed; + + public bool Disposed => _disposed; + + private IndeterminateAnimation(ProgressBar progressBar) + { + _progressBar = new WeakReference(progressBar); + _startTime = Animate.Stopwatch.Elapsed; + _indeterminateBindSubscription = Animate.Timer.TakeWhile(x => (x - _startTime).TotalSeconds <= 4.0) + .Select(GetAnimationRect) + .Finally(() => _startTime = Animate.Stopwatch.Elapsed) + .Repeat() + .Subscribe(AnimationTick); + } + + public static IndeterminateAnimation StartAnimation(ProgressBar progressBar) + { + return new IndeterminateAnimation(progressBar); + } + + private Rect GetAnimationRect(TimeSpan time) + { + if (_progressBar.TryGetTarget(out var progressBar)) + { + if (progressBar.Orientation == Orientation.Horizontal) + return new Rect(-progressBar._indicator.Width - 5 + (time - _startTime).TotalSeconds / 4.0 * (progressBar.Bounds.Width + progressBar._indicator.Width + 10), 0, progressBar._indicator.Bounds.Width, progressBar._indicator.Bounds.Height); + else + return new Rect(0, progressBar.Bounds.Height + 5 - (time - _startTime).TotalSeconds / 4.0 * (progressBar.Bounds.Height + progressBar._indicator.Height + 10), progressBar._indicator.Bounds.Width, progressBar._indicator.Bounds.Height); + } + else + { + _indeterminateBindSubscription.Dispose(); + return Rect.Empty; + } + } + + private void AnimationTick(Rect rect) + { + if (_progressBar.TryGetTarget(out var progressBar)) + progressBar._indicator.Arrange(rect); + else + _indeterminateBindSubscription.Dispose(); + } + + public void Dispose() + { + _indeterminateBindSubscription?.Dispose(); + _disposed = true; + } + } } } diff --git a/src/Avalonia.Controls/Screens.cs b/src/Avalonia.Controls/Screens.cs new file mode 100644 index 0000000000..b8ddce3aea --- /dev/null +++ b/src/Avalonia.Controls/Screens.cs @@ -0,0 +1,54 @@ +using System.Linq; +using Avalonia.Platform; +using Avalonia.Utilities; +using Avalonia.VisualTree; + +namespace Avalonia.Controls +{ + public class Screens + { + private readonly IScreenImpl _iScreenImpl; + + public int ScreenCount => _iScreenImpl.ScreenCount; + public Screen[] All => _iScreenImpl?.AllScreens; + public Screen Primary => All.FirstOrDefault(x => x.Primary); + + public Screens(IScreenImpl iScreenImpl) + { + _iScreenImpl = iScreenImpl; + } + + public Screen ScreenFromBounds(Rect bounds){ + + Screen currMaxScreen = null; + double maxAreaSize = 0; + foreach (Screen screen in All) + { + double left = MathUtilities.Clamp(bounds.X, screen.Bounds.X, screen.Bounds.X + screen.Bounds.Width); + double top = MathUtilities.Clamp(bounds.Y, screen.Bounds.Y, screen.Bounds.Y + screen.Bounds.Height); + double right = MathUtilities.Clamp(bounds.X + bounds.Width, screen.Bounds.X, screen.Bounds.X + screen.Bounds.Width); + double bottom = MathUtilities.Clamp(bounds.Y + bounds.Height, screen.Bounds.Y, screen.Bounds.Y + screen.Bounds.Height); + double area = (right - left) * (bottom - top); + if (area > maxAreaSize) + { + maxAreaSize = area; + currMaxScreen = screen; + } + } + + return currMaxScreen; + } + + public Screen SceenFromPoint(Point point) + { + return All.FirstOrDefault(x=>x.Bounds.Contains(point)); + } + + public Screen ScreenFromVisual(IVisual visual) + { + Point tl = visual.PointToScreen(visual.Bounds.TopLeft); + Point br = visual.PointToScreen(visual.Bounds.BottomRight); + return ScreenFromBounds(new Rect(tl,br)); + } + } +} \ No newline at end of file diff --git a/src/Avalonia.Controls/StackPanel.cs b/src/Avalonia.Controls/StackPanel.cs index 26a755e5f1..0e12fb3283 100644 --- a/src/Avalonia.Controls/StackPanel.cs +++ b/src/Avalonia.Controls/StackPanel.cs @@ -6,22 +6,6 @@ using Avalonia.Input; namespace Avalonia.Controls { - /// - /// Defines vertical or horizontal orientation. - /// - public enum Orientation - { - /// - /// Vertical orientation. - /// - Vertical, - - /// - /// Horizontal orientation. - /// - Horizontal, - } - /// /// A panel which lays out its children horizontally or vertically. /// @@ -37,7 +21,7 @@ namespace Avalonia.Controls /// Defines the property. /// public static readonly StyledProperty OrientationProperty = - AvaloniaProperty.Register(nameof(Orientation)); + AvaloniaProperty.Register(nameof(Orientation), Orientation.Vertical); /// /// Initializes static members of the class. diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index 9c0245a714..64912f20df 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -119,6 +119,7 @@ namespace Avalonia.Controls : base(impl) { _maxPlatformClientSize = PlatformImpl?.MaxClientSize ?? default(Size); + Screens = new Screens(PlatformImpl?.Screen); } /// @@ -135,6 +136,8 @@ namespace Avalonia.Controls remove { _nameScope.Unregistered -= value; } } + public Screens Screens { get; private set; } + /// /// Gets the platform-specific window implementation. /// diff --git a/src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.csproj b/src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.csproj index 181f5e3a1e..27bd5e630b 100644 --- a/src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.csproj +++ b/src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.csproj @@ -18,4 +18,5 @@ - \ No newline at end of file + + diff --git a/src/Avalonia.Layout/LayoutManager.cs b/src/Avalonia.Layout/LayoutManager.cs index 3244f5e7dc..f8911dc036 100644 --- a/src/Avalonia.Layout/LayoutManager.cs +++ b/src/Avalonia.Layout/LayoutManager.cs @@ -203,7 +203,7 @@ namespace Avalonia.Layout { if (!_queued && !_running) { - Dispatcher.UIThread.InvokeAsync(ExecuteLayoutPass, DispatcherPriority.Render); + Dispatcher.UIThread.InvokeAsync(ExecuteLayoutPass, DispatcherPriority.Layout); _queued = true; } } diff --git a/src/Avalonia.Themes.Default/ProgressBar.xaml b/src/Avalonia.Themes.Default/ProgressBar.xaml index 4acff26537..82f385e16b 100644 --- a/src/Avalonia.Themes.Default/ProgressBar.xaml +++ b/src/Avalonia.Themes.Default/ProgressBar.xaml @@ -1,8 +1,6 @@ \ No newline at end of file diff --git a/src/Avalonia.Visuals/Media/GradientBrush.cs b/src/Avalonia.Visuals/Media/GradientBrush.cs index 52edf12e7f..8c2c9a2c01 100644 --- a/src/Avalonia.Visuals/Media/GradientBrush.cs +++ b/src/Avalonia.Visuals/Media/GradientBrush.cs @@ -21,8 +21,8 @@ namespace Avalonia.Media /// /// Defines the property. /// - public static readonly StyledProperty> GradientStopsProperty = - AvaloniaProperty.Register>(nameof(Opacity)); + public static readonly StyledProperty> GradientStopsProperty = + AvaloniaProperty.Register>(nameof(Opacity)); /// /// Initializes a new instance of the class. @@ -46,7 +46,7 @@ namespace Avalonia.Media /// Gets or sets the brush's gradient stops. /// [Content] - public IReadOnlyList GradientStops + public IList GradientStops { get { return GetValue(GradientStopsProperty); } set { SetValue(GradientStopsProperty, value); } diff --git a/src/Avalonia.Visuals/Media/IGradientBrush.cs b/src/Avalonia.Visuals/Media/IGradientBrush.cs index ce064c4a1f..390ce6ee5b 100644 --- a/src/Avalonia.Visuals/Media/IGradientBrush.cs +++ b/src/Avalonia.Visuals/Media/IGradientBrush.cs @@ -10,7 +10,7 @@ namespace Avalonia.Media /// /// Gets the brush's gradient stops. /// - IReadOnlyList GradientStops { get; } + IList GradientStops { get; } /// /// Gets the brush's spread method that defines how to draw a gradient that doesn't fill diff --git a/src/Avalonia.Visuals/Media/Immutable/ImmutableGradientBrush.cs b/src/Avalonia.Visuals/Media/Immutable/ImmutableGradientBrush.cs index e8507f8fc3..ca67789c7f 100644 --- a/src/Avalonia.Visuals/Media/Immutable/ImmutableGradientBrush.cs +++ b/src/Avalonia.Visuals/Media/Immutable/ImmutableGradientBrush.cs @@ -16,7 +16,7 @@ namespace Avalonia.Media.Immutable /// The opacity of the brush. /// The spread method. protected ImmutableGradientBrush( - IReadOnlyList gradientStops, + IList gradientStops, double opacity, GradientSpreadMethod spreadMethod) { @@ -36,7 +36,7 @@ namespace Avalonia.Media.Immutable } /// - public IReadOnlyList GradientStops { get; } + public IList GradientStops { get; } /// public double Opacity { get; } diff --git a/src/Avalonia.Visuals/Media/Immutable/ImmutableLinearGradientBrush.cs b/src/Avalonia.Visuals/Media/Immutable/ImmutableLinearGradientBrush.cs index b46ee951f7..39ddc305fb 100644 --- a/src/Avalonia.Visuals/Media/Immutable/ImmutableLinearGradientBrush.cs +++ b/src/Avalonia.Visuals/Media/Immutable/ImmutableLinearGradientBrush.cs @@ -20,7 +20,7 @@ namespace Avalonia.Media.Immutable /// The start point for the gradient. /// The end point for the gradient. public ImmutableLinearGradientBrush( - IReadOnlyList gradientStops, + IList gradientStops, double opacity = 1, GradientSpreadMethod spreadMethod = GradientSpreadMethod.Pad, RelativePoint? startPoint = null, diff --git a/src/Avalonia.Visuals/Media/Immutable/ImmutableRadialGradientBrush.cs b/src/Avalonia.Visuals/Media/Immutable/ImmutableRadialGradientBrush.cs index cc2c7b3697..672a45ebc4 100644 --- a/src/Avalonia.Visuals/Media/Immutable/ImmutableRadialGradientBrush.cs +++ b/src/Avalonia.Visuals/Media/Immutable/ImmutableRadialGradientBrush.cs @@ -22,7 +22,7 @@ namespace Avalonia.Media.Immutable /// The horizontal and vertical radius of the outermost circle of the radial gradient. /// public ImmutableRadialGradientBrush( - IReadOnlyList gradientStops, + IList gradientStops, double opacity = 1, GradientSpreadMethod spreadMethod = GradientSpreadMethod.Pad, RelativePoint? center = null, diff --git a/src/Avalonia.Visuals/Media/LineGeometry.cs b/src/Avalonia.Visuals/Media/LineGeometry.cs index 323bfa5a7e..0952d9644f 100644 --- a/src/Avalonia.Visuals/Media/LineGeometry.cs +++ b/src/Avalonia.Visuals/Media/LineGeometry.cs @@ -27,7 +27,7 @@ namespace Avalonia.Media /// public static readonly StyledProperty EndPointProperty = AvaloniaProperty.Register(nameof(EndPoint)); - private bool _isDirty; + private bool _isDirty = true; public Point EndPoint { diff --git a/src/Avalonia.Visuals/Media/PathMarkupParser.cs b/src/Avalonia.Visuals/Media/PathMarkupParser.cs index 145013d76b..fbc189546c 100644 --- a/src/Avalonia.Visuals/Media/PathMarkupParser.cs +++ b/src/Avalonia.Visuals/Media/PathMarkupParser.cs @@ -21,7 +21,10 @@ namespace Avalonia.Media { 'L', Command.Line }, { 'H', Command.HorizontalLine }, { 'V', Command.VerticalLine }, + { 'Q', Command.QuadraticBezierCurve }, + { 'T', Command.SmoothQuadraticBezierCurve }, { 'C', Command.CubicBezierCurve }, + { 'S', Command.SmoothCubicBezierCurve }, { 'A', Command.Arc }, { 'Z', Command.Close }, }; @@ -55,6 +58,9 @@ namespace Avalonia.Media HorizontalLine, VerticalLine, CubicBezierCurve, + QuadraticBezierCurve, + SmoothCubicBezierCurve, + SmoothQuadraticBezierCurve, Arc, Close, } @@ -71,7 +77,8 @@ namespace Avalonia.Media { Command command = Command.None; Point point = new Point(); - bool relative = false; + bool relative = false; + Point? previousControlPoint = null; while (ReadCommand(reader, ref command, ref relative)) { @@ -79,6 +86,7 @@ namespace Avalonia.Media { case Command.FillRule: _context.SetFillRule(ReadFillRule(reader)); + previousControlPoint = null; break; case Command.Move: @@ -90,11 +98,13 @@ namespace Avalonia.Media point = ReadPoint(reader, point, relative); _context.BeginFigure(point, true); openFigure = true; + previousControlPoint = null; break; case Command.Line: point = ReadPoint(reader, point, relative); _context.LineTo(point); + previousControlPoint = null; break; case Command.HorizontalLine: @@ -108,6 +118,7 @@ namespace Avalonia.Media } _context.LineTo(point); + previousControlPoint = null; break; case Command.VerticalLine: @@ -121,18 +132,57 @@ namespace Avalonia.Media } _context.LineTo(point); + previousControlPoint = null; break; + case Command.QuadraticBezierCurve: + { + Point handle = ReadPoint(reader, point, relative); + previousControlPoint = handle; + ReadSeparator(reader); + point = ReadPoint(reader, point, relative); + _context.QuadraticBezierTo(handle, point); + break; + } + + case Command.SmoothQuadraticBezierCurve: + { + Point end = ReadPoint(reader, point, relative); + + if(previousControlPoint != null) + previousControlPoint = MirrorControlPoint((Point)previousControlPoint, point); + + _context.QuadraticBezierTo(previousControlPoint ?? point, end); + point = end; + break; + } + case Command.CubicBezierCurve: { Point point1 = ReadPoint(reader, point, relative); ReadSeparator(reader); Point point2 = ReadPoint(reader, point, relative); + previousControlPoint = point2; ReadSeparator(reader); point = ReadPoint(reader, point, relative); _context.CubicBezierTo(point1, point2, point); break; } + + case Command.SmoothCubicBezierCurve: + { + Point point2 = ReadPoint(reader, point, relative); + ReadSeparator(reader); + Point end = ReadPoint(reader, point, relative); + + if(previousControlPoint != null) + previousControlPoint = MirrorControlPoint((Point)previousControlPoint, point); + + _context.CubicBezierTo(previousControlPoint ?? point, point2, end); + previousControlPoint = point2; + point = end; + break; + } case Command.Arc: { @@ -147,12 +197,14 @@ namespace Avalonia.Media point = ReadPoint(reader, point, relative); _context.ArcTo(point, size, rotationAngle, isLargeArc, sweepDirection); + previousControlPoint = null; break; } case Command.Close: _context.EndFigure(true); openFigure = false; + previousControlPoint = null; break; default: @@ -167,6 +219,12 @@ namespace Avalonia.Media } } + private Point MirrorControlPoint(Point controlPoint, Point center) + { + Point dir = (controlPoint - center); + return center + -dir; + } + private static bool ReadCommand( StringReader reader, ref Command command, @@ -243,6 +301,9 @@ namespace Avalonia.Media (c == 'E' && !readExponent) || char.IsDigit(c)) { + if (b.Length != 0 && !readExponent && c == '-') + break; + b.Append(c); reader.Read(); diff --git a/src/Avalonia.Visuals/Media/PolylineGeometry.cs b/src/Avalonia.Visuals/Media/PolylineGeometry.cs index 7c47e7d04d..b23bb88729 100644 --- a/src/Avalonia.Visuals/Media/PolylineGeometry.cs +++ b/src/Avalonia.Visuals/Media/PolylineGeometry.cs @@ -27,7 +27,7 @@ namespace Avalonia.Media AvaloniaProperty.Register(nameof(IsFilled)); private Points _points; - private bool _isDirty; + private bool _isDirty = true; private IDisposable _pointsObserver; static PolylineGeometry() diff --git a/src/Avalonia.Visuals/Properties/AssemblyInfo.cs b/src/Avalonia.Visuals/Properties/AssemblyInfo.cs index ded650e2ed..87347d64b1 100644 --- a/src/Avalonia.Visuals/Properties/AssemblyInfo.cs +++ b/src/Avalonia.Visuals/Properties/AssemblyInfo.cs @@ -10,6 +10,5 @@ using Avalonia.Metadata; [assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Animation")] [assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Media")] -[assembly: InternalsVisibleTo("Avalonia.Cairo.RenderTests")] [assembly: InternalsVisibleTo("Avalonia.Direct2D1.RenderTests")] [assembly: InternalsVisibleTo("Avalonia.Skia.RenderTests")] \ No newline at end of file diff --git a/src/Avalonia.Visuals/Rendering/DefaultRenderLoop.cs b/src/Avalonia.Visuals/Rendering/DefaultRenderLoop.cs index a4e8e6f0c2..5dff3715b3 100644 --- a/src/Avalonia.Visuals/Rendering/DefaultRenderLoop.cs +++ b/src/Avalonia.Visuals/Rendering/DefaultRenderLoop.cs @@ -15,7 +15,7 @@ namespace Avalonia.Rendering /// public class DefaultRenderLoop : IRenderLoop { - private IPlatformThreadingInterface _threading; + private IRuntimePlatform _runtime; private int _subscriberCount; private EventHandler _tick; private IDisposable _subscription; @@ -78,12 +78,12 @@ namespace Avalonia.Rendering /// protected virtual IDisposable StartCore(Action tick) { - if (_threading == null) + if (_runtime == null) { - _threading = AvaloniaLocator.Current.GetService(); + _runtime = AvaloniaLocator.Current.GetService(); } - return _threading.StartTimer(TimeSpan.FromSeconds(1.0 / FramesPerSecond), tick); + return _runtime.StartSystemTimer(TimeSpan.FromSeconds(1.0 / FramesPerSecond), tick); } /// diff --git a/src/Gtk/Avalonia.Cairo/Avalonia.Cairo.csproj b/src/Gtk/Avalonia.Cairo/Avalonia.Cairo.csproj deleted file mode 100644 index 460db98895..0000000000 --- a/src/Gtk/Avalonia.Cairo/Avalonia.Cairo.csproj +++ /dev/null @@ -1,109 +0,0 @@ - - - - - Debug - AnyCPU - {FB05AC90-89BA-4F2F-A924-F37875FB547C} - Library - Properties - Avalonia.Cairo - Avalonia.Cairo - v4.6.1 - 512 - - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - - - - - - - - - - - - - - - Properties\SharedAssemblyInfo.cs - - - - - - - - - - - - - - - - - - - - {D211E587-D8BC-45B9-95A4-F297C8FA5200} - Avalonia.Animation - - - {B09B78D8-9B26-48B0-9149-D64A2F120F3F} - Avalonia.Base - - - {d2221c82-4a25-4583-9b43-d791e3f6820c} - Avalonia.Controls - - - {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/Gtk/Avalonia.Cairo/CairoExtensions.cs b/src/Gtk/Avalonia.Cairo/CairoExtensions.cs deleted file mode 100644 index daea3b0239..0000000000 --- a/src/Gtk/Avalonia.Cairo/CairoExtensions.cs +++ /dev/null @@ -1,64 +0,0 @@ -// 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. - -namespace Avalonia.Cairo -{ - using Cairo = global::Cairo; - - public static class CairoExtensions - { - public static Cairo.Color ToCairo(this Avalonia.Media.Color color) - { - return new Cairo.Color(color.R / 255.0, color.G / 255.0, color.B / 255.0, color.A / 255.0); - } - - public static Cairo.Matrix ToCairo(this Matrix m) - { - return new Cairo.Matrix(m.M11, m.M12, m.M21, m.M22, m.M31, m.M32); - } - - public static Cairo.PointD ToCairo(this Point p) - { - return new Cairo.PointD(p.X, p.Y); - } - - public static Cairo.Rectangle ToCairo(this Rect rect) - { - return new Cairo.Rectangle(rect.X, rect.Y, rect.Width, rect.Height); - } - - public static Rect ToAvalonia(this Cairo.Rectangle rect) - { - return new Rect(rect.X, rect.Y, rect.Width, rect.Height); - } - - public static Rect ToAvalonia(this Pango.Rectangle rect) - { - return new Rect( - Pango.Units.ToDouble(rect.X), - Pango.Units.ToDouble(rect.Y), - Pango.Units.ToDouble(rect.Width), - Pango.Units.ToDouble(rect.Height)); - } - - public static Pango.Weight ToCairo(this Avalonia.Media.FontWeight weight) - { - return (Pango.Weight)weight; - } - - public static Pango.Alignment ToCairo(this Avalonia.Media.TextAlignment alignment) - { - if (alignment == Avalonia.Media.TextAlignment.Left) - { - return Pango.Alignment.Left; - } - - if (alignment == Avalonia.Media.TextAlignment.Center) - { - return Pango.Alignment.Center; - } - - return Pango.Alignment.Right; - } - } -} \ No newline at end of file diff --git a/src/Gtk/Avalonia.Cairo/CairoPlatform.cs b/src/Gtk/Avalonia.Cairo/CairoPlatform.cs deleted file mode 100644 index e3578874a3..0000000000 --- a/src/Gtk/Avalonia.Cairo/CairoPlatform.cs +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright (c) The Avalonia Project. All rights reserved. -// Licensed under the MIT license. See licence.md file in the project root for full license information. - -using System; -using System.Collections.Generic; -using System.Linq; -using Avalonia.Cairo.Media; -using Avalonia.Cairo.Media.Imaging; -using Avalonia.Media; -using Avalonia.Platform; -using Avalonia.Controls; - -namespace Avalonia -{ - public static class GtkApplicationExtensions - { - public static T UseCairo(this T builder) where T : AppBuilderBase, new() - { - builder.UseRenderingSubsystem(Cairo.CairoPlatform.Initialize, "Cairo"); - return builder; - } - } -} - -namespace Avalonia.Cairo -{ - using System.IO; - using global::Cairo; - using Rendering; - - public class CairoPlatform : IPlatformRenderInterface - { - private static readonly CairoPlatform s_instance = new CairoPlatform(); - - private static readonly Pango.Context s_pangoContext = CreatePangoContext(); - - public static void Initialize() => AvaloniaLocator.CurrentMutable.Bind().ToConstant(s_instance); - - public IBitmapImpl CreateBitmap(int width, int height) - { - return new BitmapImpl(new Gdk.Pixbuf(Gdk.Colorspace.Rgb, true, 32, width, height)); - } - - public IFormattedTextImpl CreateFormattedText( - string text, - Typeface typeface, - TextAlignment textAlignment, - TextWrapping wrapping, - Size constraint, - IReadOnlyList spans) - { - return new FormattedTextImpl( - s_pangoContext, - text, - typeface, - textAlignment, - wrapping, - constraint, - spans); - } - - public IRenderTarget CreateRenderTarget(IEnumerable surfaces) - { - var accessor = surfaces?.OfType>().FirstOrDefault(); - if(accessor!=null) - return new RenderTarget(accessor); - - throw new NotSupportedException(string.Format( - "Don't know how to create a Cairo renderer from any of the provided surfaces.")); - } - - public IRenderTargetBitmapImpl CreateRenderTargetBitmap(int width, int height, double dpiX, double dpiY) - { - return new RenderTargetBitmapImpl(new ImageSurface(Format.Argb32, width, height)); - } - - public IStreamGeometryImpl CreateStreamGeometry() - { - return new StreamGeometryImpl(); - } - - public IBitmapImpl LoadBitmap(string fileName) - { - var pixbuf = new Gdk.Pixbuf(fileName); - - return new BitmapImpl(pixbuf); - } - - public IBitmapImpl LoadBitmap(Stream stream) - { - var pixbuf = new Gdk.Pixbuf(stream); - - return new BitmapImpl(pixbuf); - } - - private static Pango.Context CreatePangoContext() - { - Gtk.Application.Init(); - return new Gtk.Invisible().CreatePangoContext(); - } - - public IBitmapImpl LoadBitmap(PixelFormat format, IntPtr data, int width, int height, int stride) - { - throw new NotSupportedException("No proper control over pixel format with Cairo, use Skia backend instead"); - } - - public IWritableBitmapImpl CreateWritableBitmap(int width, int height, PixelFormat? fmt) - { - throw new NotSupportedException("No proper support with Cairo, use Skia backend instead"); - } - } -} diff --git a/src/Gtk/Avalonia.Cairo/Media/BrushImpl.cs b/src/Gtk/Avalonia.Cairo/Media/BrushImpl.cs deleted file mode 100644 index 7008c7a66f..0000000000 --- a/src/Gtk/Avalonia.Cairo/Media/BrushImpl.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using global::Cairo; - -namespace Avalonia.Cairo -{ - public abstract class BrushImpl : IDisposable - { - public Pattern PlatformBrush { get; protected set; } - - public void Dispose() - { - if (this.PlatformBrush != null) - this.PlatformBrush.Dispose(); - } - } -} - diff --git a/src/Gtk/Avalonia.Cairo/Media/DrawingContext.cs b/src/Gtk/Avalonia.Cairo/Media/DrawingContext.cs deleted file mode 100644 index 99b0a2ec73..0000000000 --- a/src/Gtk/Avalonia.Cairo/Media/DrawingContext.cs +++ /dev/null @@ -1,415 +0,0 @@ -// Copyright (c) The Avalonia Project. All rights reserved. -// Licensed under the MIT license. See licence.md file in the project root for full license information. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reactive.Disposables; -using Avalonia.Cairo.Media.Imaging; -using Avalonia.Media; -using Avalonia.Platform; -using Avalonia.Rendering; -// ReSharper disable PossibleNullReferenceException - -namespace Avalonia.Cairo.Media -{ - using Cairo = global::Cairo; - - /// - /// Draws using Cairo. - /// - public class DrawingContext : IDrawingContextImpl, IDisposable - { - private readonly Cairo.Context _context; - private readonly IVisualBrushRenderer _visualBrushRenderer; - private readonly Stack _maskStack = new Stack(); - - /// - /// Initializes a new instance of the class. - /// - /// The target surface. - public DrawingContext(Cairo.Surface surface, IVisualBrushRenderer visualBrushRenderer) - { - _context = new Cairo.Context(surface); - _visualBrushRenderer = visualBrushRenderer; - } - - /// - /// Initializes a new instance of the class. - /// - /// The GDK drawable. - public DrawingContext(Gdk.Drawable drawable, IVisualBrushRenderer visualBrushRenderer) - { - _context = Gdk.CairoHelper.Create(drawable); - _visualBrushRenderer = visualBrushRenderer; - } - - private Matrix _transform = Matrix.Identity; - /// - /// Gets the current transform of the drawing context. - /// - public Matrix Transform - { - get { return _transform; } - set - { - _transform = value; - _context.Matrix = value.ToCairo(); - - } - } - - public void Clear(Color color) - { - _context.SetSourceRGBA(color.R, color.G, color.B, color.A); - _context.Paint(); - } - - /// - /// Ends a draw operation. - /// - public void Dispose() - { - _context.Dispose(); - } - - /// - /// Draws a bitmap image. - /// - /// The bitmap image. - /// The opacity to draw with. - /// The rect in the image to draw. - /// The rect in the output to draw to. - public void DrawImage(IBitmapImpl bitmap, double opacity, Rect sourceRect, Rect destRect) - { - var pixbuf = bitmap as Gdk.Pixbuf; - var rtb = bitmap as RenderTargetBitmapImpl; - var size = new Size(pixbuf?.Width ?? rtb.PixelWidth, pixbuf?.Height ?? rtb.PixelHeight); - var scale = new Vector(destRect.Width / sourceRect.Width, destRect.Height / sourceRect.Height); - - _context.Save(); - _context.Scale(scale.X, scale.Y); - destRect /= scale; - - _context.PushGroup(); - - if (pixbuf != null) - { - Gdk.CairoHelper.SetSourcePixbuf( - _context, - pixbuf, - -sourceRect.X + destRect.X, - -sourceRect.Y + destRect.Y); - } - else - { - _context.SetSourceSurface( - rtb.Surface, - (int)(-sourceRect.X + destRect.X), - (int)(-sourceRect.Y + destRect.Y)); - } - - _context.Rectangle(destRect.ToCairo()); - _context.Fill(); - _context.PopGroupToSource(); - _context.PaintWithAlpha(opacityOverride); - _context.Restore(); - } - - public void DrawImage(IBitmapImpl source, IBrush opacityMask, Rect opacityMaskRect, Rect destRect) - { - PushOpacityMask(opacityMask, opacityMaskRect); - DrawImage(source, 1, new Rect(0, 0, source.PixelWidth, source.PixelHeight), destRect); - PopOpacityMask(); - } - - /// - /// Draws a line. - /// - /// The stroke pen. - /// The first point of the line. - /// The second point of the line. - public void DrawLine(Pen pen, Point p1, Point p2) - { - var size = new Rect(p1, p2).Size; - - using (var p = SetPen(pen, size)) - { - _context.MoveTo(p1.ToCairo()); - _context.LineTo(p2.ToCairo()); - _context.Stroke(); - } - } - - /// - /// Draws a geometry. - /// - /// The fill brush. - /// The stroke pen. - /// The geometry. - public void DrawGeometry(IBrush brush, Pen pen, IGeometryImpl geometry) - { - var impl = geometry as StreamGeometryImpl; - - var oldMatrix = Transform; - Transform = impl.Transform * Transform; - - - if (brush != null) - { - _context.AppendPath(impl.Path); - using (var b = SetBrush(brush, geometry.Bounds.Size)) - { - _context.FillRule = impl.FillRule == FillRule.EvenOdd - ? Cairo.FillRule.EvenOdd - : Cairo.FillRule.Winding; - - if (pen != null) - _context.FillPreserve(); - else - _context.Fill(); - } - } - Transform = oldMatrix; - - if (pen != null) - { - _context.AppendPath(impl.Path); - using (var p = SetPen(pen, geometry.Bounds.Size)) - { - _context.Stroke(); - } - } - } - - /// - /// Draws the outline of a rectangle. - /// - /// The pen. - /// The rectangle bounds. - public void DrawRectangle(Pen pen, Rect rect, float cornerRadius) - { - using (var p = SetPen(pen, rect.Size)) - { - _context.Rectangle(rect.ToCairo()); - _context.Stroke(); - } - } - - /// - /// Draws text. - /// - /// The foreground brush. - /// The upper-left corner of the text. - /// The text. - public void DrawText(IBrush foreground, Point origin, IFormattedTextImpl text) - { - var layout = ((FormattedTextImpl)text).Layout; - _context.MoveTo(origin.X, origin.Y); - - using (var b = SetBrush(foreground, new Size(0, 0))) - { - Pango.CairoHelper.ShowLayout(_context, layout); - } - } - - /// - /// Draws a filled rectangle. - /// - /// The brush. - /// The rectangle bounds. - public void FillRectangle(IBrush brush, Rect rect, float cornerRadius) - { - using (var b = SetBrush(brush, rect.Size)) - { - _context.Rectangle(rect.ToCairo()); - _context.Fill(); - } - } - - /// - /// Pushes a clip rectange. - /// - /// The clip rectangle. - /// A disposable used to undo the clip rectangle. - public void PushClip(Rect clip) - { - _context.Save(); - _context.Rectangle(clip.ToCairo()); - _context.Clip(); - } - - public void PopClip() - { - _context.Restore(); - } - - readonly Stack _opacityStack = new Stack(); - - /// - /// Pushes an opacity value. - /// - /// The opacity. - /// A disposable used to undo the opacity. - public void PushOpacity(double opacity) - { - _opacityStack.Push(opacityOverride); - - if (opacity < 1.0f) - opacityOverride *= opacity; - - } - - public void PopOpacity() - { - opacityOverride = _opacityStack.Pop(); - } - - /// - /// Pushes a matrix transformation. - /// - /// The matrix - /// A disposable used to undo the transformation. - public IDisposable PushTransform(Matrix matrix) - { - _context.Save(); - _context.Transform(matrix.ToCairo()); - - return Disposable.Create(() => - { - _context.Restore(); - }); - } - - private double opacityOverride = 1.0f; - - private IDisposable SetBrush(IBrush brush, Size destinationSize) - { - _context.Save(); - - BrushImpl impl = CreateBrushImpl(brush, destinationSize); - - _context.SetSource(impl.PlatformBrush); - return Disposable.Create(() => - { - impl.Dispose(); - _context.Restore(); - }); - } - - private BrushImpl CreateBrushImpl(IBrush brush, Size destinationSize) - { - var solid = brush as ISolidColorBrush; - var linearGradientBrush = brush as ILinearGradientBrush; - var radialGradientBrush = brush as IRadialGradientBrush; - var imageBrush = brush as IImageBrush; - var visualBrush = brush as IVisualBrush; - BrushImpl impl = null; - - if (solid != null) - { - impl = new SolidColorBrushImpl(solid, opacityOverride); - } - else if (linearGradientBrush != null) - { - impl = new LinearGradientBrushImpl(linearGradientBrush, destinationSize); - } - else if (radialGradientBrush != null) - { - impl = new RadialGradientBrushImpl(radialGradientBrush, destinationSize); - } - else if (imageBrush != null) - { - impl = new ImageBrushImpl(imageBrush, (BitmapImpl)imageBrush.Source.PlatformImpl, destinationSize); - } - else if (visualBrush != null) - { - if (_visualBrushRenderer != null) - { - var intermediateSize = _visualBrushRenderer.GetRenderTargetSize(visualBrush); - - if (intermediateSize.Width >= 1 && intermediateSize.Height >= 1) - { - using (var intermediate = new Cairo.ImageSurface(Cairo.Format.ARGB32, (int)intermediateSize.Width, (int)intermediateSize.Height)) - { - using (var ctx = new RenderTarget(intermediate).CreateDrawingContext(_visualBrushRenderer)) - { - ctx.Clear(Colors.Transparent); - _visualBrushRenderer.RenderVisualBrush(ctx, visualBrush); - } - - return new ImageBrushImpl( - visualBrush, - new RenderTargetBitmapImpl(intermediate), - destinationSize); - } - } - } - else - { - throw new NotSupportedException("No IVisualBrushRenderer was supplied to DrawingContextImpl."); - } - } - else - { - impl = new SolidColorBrushImpl(null, opacityOverride); - } - - return impl; - } - - private IDisposable SetPen(Pen pen, Size destinationSize) - { - if (pen.DashStyle != null) - { - if (pen.DashStyle.Dashes != null && pen.DashStyle.Dashes.Count > 0) - { - var cray = pen.DashStyle.Dashes.ToArray(); - _context.SetDash(cray, pen.DashStyle.Offset); - } - } - - _context.LineWidth = pen.Thickness; - _context.MiterLimit = pen.MiterLimit; - - // Line caps and joins are currently broken on Cairo. I've defaulted them to sensible defaults for now. - // Cairo does not have StartLineCap, EndLineCap, and DashCap properties, whereas Direct2D does. - // TODO: Figure out a solution for this. - _context.LineJoin = Cairo.LineJoin.Miter; - _context.LineCap = Cairo.LineCap.Butt; - - if (pen.Brush == null) - return Disposable.Empty; - - return SetBrush(pen.Brush, destinationSize); - } - - public void PushGeometryClip(IGeometryImpl clip) - { - _context.Save(); - _context.AppendPath(((StreamGeometryImpl)clip).Path); - _context.Clip(); - } - - public void PopGeometryClip() - { - _context.Restore(); - } - - public void PushOpacityMask(IBrush mask, Rect bounds) - { - _context.PushGroup(); - var impl = CreateBrushImpl(mask, bounds.Size); - _maskStack.Push(impl); - } - - public void PopOpacityMask() - { - _context.PopGroupToSource(); - var brushImpl = _maskStack.Pop(); - - _context.Mask(brushImpl.PlatformBrush); - brushImpl.Dispose(); - } - } -} diff --git a/src/Gtk/Avalonia.Cairo/Media/FormattedTextImpl.cs b/src/Gtk/Avalonia.Cairo/Media/FormattedTextImpl.cs deleted file mode 100644 index b8e4d1efec..0000000000 --- a/src/Gtk/Avalonia.Cairo/Media/FormattedTextImpl.cs +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright (c) The Avalonia Project. All rights reserved. -// Licensed under the MIT license. See licence.md file in the project root for full license information. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Avalonia.Media; -using Avalonia.Platform; - -namespace Avalonia.Cairo.Media -{ - public class FormattedTextImpl : IFormattedTextImpl - { - private Size _constraint; - - static double CorrectScale(double input) - { - return input * 0.75; - } - - public FormattedTextImpl( - Pango.Context context, - string text, - Typeface typeface, - TextAlignment textAlignment, - TextWrapping wrapping, - Size constraint, - IReadOnlyList spans) - { - Contract.Requires(context != null); - Contract.Requires(text != null); - - Layout = new Pango.Layout(context); - Layout.SetText(text); - - Layout.FontDescription = new Pango.FontDescription - { - Family = typeface?.FontFamilyName ?? "monospace", - Size = Pango.Units.FromDouble(CorrectScale(typeface?.FontSize ?? 12)), - Style = (Pango.Style)(typeface?.Style ?? FontStyle.Normal), - Weight = (typeface?.Weight ?? FontWeight.Normal).ToCairo(), - }; - - Layout.Alignment = textAlignment.ToCairo(); - Layout.Attributes = new Pango.AttrList(); - Layout.Width = double.IsPositiveInfinity(constraint.Width) ? -1 : Pango.Units.FromDouble(constraint.Width); - - if (spans != null) - { - foreach (var span in spans) - { - if (span.ForegroundBrush is SolidColorBrush scb) - { - var color = new Pango.Color(); - color.Parse(string.Format("#{0}", scb.Color.ToString().Substring(3))); - - var brushAttr = new Pango.AttrForeground(color); - brushAttr.StartIndex = (uint)TextIndexToPangoIndex(span.StartIndex); - brushAttr.EndIndex = (uint)TextIndexToPangoIndex(span.StartIndex + span.Length); - - this.Layout.Attributes.Insert(brushAttr); - } - } - } - - Size = Measure(); - } - - public FormattedTextImpl(Pango.Layout layout) - { - Layout = layout; - Size = Measure(); - } - - public string Text => Layout.Text; - - public Size Constraint => _constraint; - - public Size Size { get; } - - public Pango.Layout Layout { get; } - - public IEnumerable GetLines() - { - return new FormattedTextLine[0]; - } - - public TextHitTestResult HitTestPoint(Point point) - { - int textPosition; - int trailing; - - var isInside = Layout.XyToIndex( - Pango.Units.FromDouble(point.X), - Pango.Units.FromDouble(point.Y), - out textPosition, - out trailing); - - textPosition = PangoIndexToTextIndex(textPosition); - - return new TextHitTestResult - { - IsInside = isInside, - TextPosition = textPosition, - IsTrailing = trailing == 0, - }; - } - - int PangoIndexToTextIndex(int pangoIndex) - { - return Encoding.UTF8.GetString(Encoding.UTF8.GetBytes(Text), 0, Math.Min(pangoIndex, Text.Length)).Length; - } - - public Rect HitTestTextPosition(int index) - { - return Layout.IndexToPos(TextIndexToPangoIndex(index)).ToAvalonia(); - } - - int TextIndexToPangoIndex(int textIndex) - { - return Encoding.UTF8.GetByteCount(textIndex < Text.Length ? Text.Remove(textIndex) : Text); - } - - public IEnumerable HitTestTextRange(int index, int length) - { - var ranges = new List(); - - for (var i = 0; i < length; i++) - { - ranges.Add(HitTestTextPosition(index + i)); - } - - return ranges; - } - - private Size Measure() - { - int width; - int height; - Layout.GetPixelSize(out width, out height); - - return new Size(width, height); - } - } -} diff --git a/src/Gtk/Avalonia.Cairo/Media/ImageBrushImpl.cs b/src/Gtk/Avalonia.Cairo/Media/ImageBrushImpl.cs deleted file mode 100644 index 14c9dee9e2..0000000000 --- a/src/Gtk/Avalonia.Cairo/Media/ImageBrushImpl.cs +++ /dev/null @@ -1,56 +0,0 @@ -using Avalonia.Media; -using Avalonia.Platform; -using Avalonia.Rendering.Utilities; -using global::Cairo; - -namespace Avalonia.Cairo.Media -{ - public class ImageBrushImpl : BrushImpl - { - public ImageBrushImpl( - ITileBrush brush, - IBitmapImpl bitmap, - Size targetSize) - { - var calc = new TileBrushCalculator(brush, new Size(bitmap.PixelWidth, bitmap.PixelHeight), targetSize); - - using (var intermediate = new ImageSurface(Format.ARGB32, (int)calc.IntermediateSize.Width, (int)calc.IntermediateSize.Height)) - { - using (var context = new RenderTarget(intermediate).CreateDrawingContext(null)) - { - var rect = new Rect(0, 0, bitmap.PixelWidth, bitmap.PixelHeight); - - context.Clear(Colors.Transparent); - context.PushClip(calc.IntermediateClip); - context.Transform = calc.IntermediateTransform; - context.DrawImage(bitmap, 1, rect, rect); - context.PopClip(); - } - - var result = new SurfacePattern(intermediate); - - if ((brush.TileMode & TileMode.FlipXY) != 0) - { - // TODO: Currently always FlipXY as that's all cairo supports natively. - // Support separate FlipX and FlipY by drawing flipped images to intermediate - // surface. - result.Extend = Extend.Reflect; - } - else - { - result.Extend = Extend.Repeat; - } - - if (brush.TileMode != TileMode.None) - { - var matrix = result.Matrix; - matrix.InitTranslate(-calc.DestinationRect.X, -calc.DestinationRect.Y); - result.Matrix = matrix; - } - - PlatformBrush = result; - } - } - } -} - diff --git a/src/Gtk/Avalonia.Cairo/Media/Imaging/BitmapImpl.cs b/src/Gtk/Avalonia.Cairo/Media/Imaging/BitmapImpl.cs deleted file mode 100644 index 5c1e5e7d96..0000000000 --- a/src/Gtk/Avalonia.Cairo/Media/Imaging/BitmapImpl.cs +++ /dev/null @@ -1,35 +0,0 @@ -// 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 Avalonia.Platform; - -namespace Avalonia.Cairo.Media.Imaging -{ - using System.IO; - using Cairo = global::Cairo; - - public class BitmapImpl : Gdk.Pixbuf, IBitmapImpl - { - public BitmapImpl(Gdk.Pixbuf pixbuf) - :base(pixbuf.SaveToBuffer("png")) - { - } - - public int PixelWidth => Width; - - public int PixelHeight => Height; - - public void Save(string fileName) - { - // TODO: Test - Save(fileName, "png"); - } - - public void Save(Stream stream) - { - var buffer = SaveToBuffer("png"); - stream.Write(buffer, 0, buffer.Length); - } - } -} diff --git a/src/Gtk/Avalonia.Cairo/Media/Imaging/RenderTargetBitmapImpl.cs b/src/Gtk/Avalonia.Cairo/Media/Imaging/RenderTargetBitmapImpl.cs deleted file mode 100644 index fa8a3132d5..0000000000 --- a/src/Gtk/Avalonia.Cairo/Media/Imaging/RenderTargetBitmapImpl.cs +++ /dev/null @@ -1,58 +0,0 @@ -// 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 Avalonia.Media; -using Avalonia.Platform; -using Avalonia.Rendering; - -namespace Avalonia.Cairo.Media.Imaging -{ - using System.IO; - using Cairo = global::Cairo; - - public class RenderTargetBitmapImpl : IRenderTargetBitmapImpl - { - - private readonly RenderTarget _renderTarget; - public RenderTargetBitmapImpl(Cairo.ImageSurface surface) - { - Surface = surface; - _renderTarget = new RenderTarget(Surface); - } - - public int PixelWidth => Surface.Width; - - public int PixelHeight => Surface.Height; - - public void Dispose() - { - _renderTarget.Dispose(); - } - - public Cairo.ImageSurface Surface - { - get; - } - - public void Save(string fileName) - { - Surface.WriteToPng(fileName); - } - - public IDrawingContextImpl CreateDrawingContext(IVisualBrushRenderer visualBrushRenderer) - { - return _renderTarget.CreateDrawingContext(visualBrushRenderer); - } - - public void Save(Stream stream) - { - var tempFileName = Path.GetTempFileName(); - Surface.WriteToPng(tempFileName); - using (var tempFile = new FileStream(tempFileName, FileMode.Create)) - { - tempFile.CopyTo(stream); - } - } - } -} \ No newline at end of file diff --git a/src/Gtk/Avalonia.Cairo/Media/LinearGradientBrushImpl.cs b/src/Gtk/Avalonia.Cairo/Media/LinearGradientBrushImpl.cs deleted file mode 100644 index 1e82da4059..0000000000 --- a/src/Gtk/Avalonia.Cairo/Media/LinearGradientBrushImpl.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using Avalonia.Media; -using global::Cairo; - -namespace Avalonia.Cairo -{ - public class LinearGradientBrushImpl : BrushImpl - { - public LinearGradientBrushImpl(ILinearGradientBrush brush, Size destinationSize) - { - var start = brush.StartPoint.ToPixels(destinationSize); - var end = brush.EndPoint.ToPixels(destinationSize); - - this.PlatformBrush = new LinearGradient(start.X, start.Y, end.X, end.Y); - - foreach (var stop in brush.GradientStops) - ((LinearGradient)this.PlatformBrush).AddColorStop(stop.Offset, stop.Color.ToCairo()); - - ((LinearGradient)this.PlatformBrush).Extend = Extend.Pad; - } - } -} - diff --git a/src/Gtk/Avalonia.Cairo/Media/RadialGradientBrushImpl.cs b/src/Gtk/Avalonia.Cairo/Media/RadialGradientBrushImpl.cs deleted file mode 100644 index 03385f8d86..0000000000 --- a/src/Gtk/Avalonia.Cairo/Media/RadialGradientBrushImpl.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using Avalonia.Media; -using global::Cairo; - -namespace Avalonia.Cairo -{ - public class RadialGradientBrushImpl : BrushImpl - { - public RadialGradientBrushImpl(IRadialGradientBrush brush, Size destinationSize) - { - var center = brush.Center.ToPixels(destinationSize); - var gradientOrigin = brush.GradientOrigin.ToPixels(destinationSize); - var radius = brush.Radius * Math.Min(destinationSize.Width, destinationSize.Height); - - this.PlatformBrush = new RadialGradient(center.X, center.Y, 1, gradientOrigin.X, gradientOrigin.Y, radius); - this.PlatformBrush.Matrix = Matrix.Identity.ToCairo(); - - foreach (var stop in brush.GradientStops) - { - ((RadialGradient)this.PlatformBrush).AddColorStop(stop.Offset, stop.Color.ToCairo()); - } - - ((RadialGradient)this.PlatformBrush).Extend = Extend.Pad; - } - } -} - diff --git a/src/Gtk/Avalonia.Cairo/Media/SolidColorBrushImpl.cs b/src/Gtk/Avalonia.Cairo/Media/SolidColorBrushImpl.cs deleted file mode 100644 index 86f8aa7f25..0000000000 --- a/src/Gtk/Avalonia.Cairo/Media/SolidColorBrushImpl.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using global::Cairo; - -namespace Avalonia.Cairo -{ - public class SolidColorBrushImpl : BrushImpl - { - public SolidColorBrushImpl(Avalonia.Media.ISolidColorBrush brush, double opacityOverride = 1.0f) - { - var color = brush?.Color.ToCairo() ?? new Color(); - - if (brush != null) - color.A = Math.Min(brush.Opacity, color.A); - - if (opacityOverride < 1.0f) - color.A = Math.Min(opacityOverride, color.A); - - this.PlatformBrush = new SolidPattern(color); - } - } -} - diff --git a/src/Gtk/Avalonia.Cairo/Media/StreamGeometryContextImpl.cs b/src/Gtk/Avalonia.Cairo/Media/StreamGeometryContextImpl.cs deleted file mode 100644 index ca16ab5630..0000000000 --- a/src/Gtk/Avalonia.Cairo/Media/StreamGeometryContextImpl.cs +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright (c) The Avalonia Project. All rights reserved. -// Licensed under the MIT license. See licence.md file in the project root for full license information. - -using System; -using System.Collections.Generic; -using Avalonia.Media; -using Avalonia.Platform; -using Avalonia.RenderHelpers; - -namespace Avalonia.Cairo.Media -{ - using Cairo = global::Cairo; - - public class StreamGeometryContextImpl : IStreamGeometryContextImpl - { - private readonly StreamGeometryImpl _target; - private Point _currentPoint; - public StreamGeometryContextImpl(StreamGeometryImpl target, Cairo.Path path) - { - _target = target; - - _surf = new Cairo.ImageSurface (Cairo.Format.Argb32, 0, 0); - _context = new Cairo.Context (_surf); - this.Path = path; - - if (this.Path != null) - { - _context.AppendPath(this.Path); - } - } - - public void ArcTo(Point point, Size size, double rotationAngle, bool isLargeArc, SweepDirection sweepDirection) - { - ArcToHelper.ArcTo(this, _currentPoint, point, size, rotationAngle, isLargeArc, sweepDirection); - _currentPoint = point; - } - - public void BeginFigure(Point startPoint, bool isFilled) - { - if (this.Path == null) - { - _context.MoveTo(startPoint.ToCairo()); - _currentPoint = startPoint; - } - } - - public void CubicBezierTo(Point point1, Point point2, Point point3) - { - if (this.Path == null) - { - _context.CurveTo(point1.ToCairo(), point2.ToCairo(), point3.ToCairo()); - _currentPoint = point3; - } - } - - public void QuadraticBezierTo(Point control, Point endPoint) - { - if (this.Path == null) - { - QuadBezierHelper.QuadraticBezierTo(this, _currentPoint, control, endPoint); - _currentPoint = endPoint; - } - } - - internal bool FillContains(Point point) - { - using (var context = new Cairo.Context(new Cairo.ImageSurface(Cairo.Format.Argb32, 0, 0))) - { - context.AppendPath(Path); - return context.InFill(point.X, point.Y); - } - } - - internal bool StrokeContains(Pen pen, Point point) - { - using (var context = new Cairo.Context(new Cairo.ImageSurface(Cairo.Format.Argb32, 0, 0))) - { - context.AppendPath(Path); - return context.InStroke(point.X, point.Y); - } - } - - public void LineTo(Point point) - { - if (this.Path == null) - { - _context.LineTo(point.ToCairo()); - _currentPoint = point; - } - } - - private readonly Cairo.Context _context; - private readonly Cairo.ImageSurface _surf; - public Cairo.Path Path { get; private set; } - public Rect Bounds { get; private set; } - - public void EndFigure(bool isClosed) - { - if (this.Path == null) - { - if (isClosed) - _context.ClosePath (); - } - } - - public void SetFillRule(FillRule fillRule) - { - _target.FillRule = fillRule; - } - - - public void Dispose() - { - if (this.Path == null) - { - Path = _context.CopyPath(); - Bounds = _context.FillExtents().ToAvalonia(); - } - - _context.Dispose (); - _surf.Dispose (); - } - } -} diff --git a/src/Gtk/Avalonia.Cairo/Media/StreamGeometryImpl.cs b/src/Gtk/Avalonia.Cairo/Media/StreamGeometryImpl.cs deleted file mode 100644 index b0a8cd4fb0..0000000000 --- a/src/Gtk/Avalonia.Cairo/Media/StreamGeometryImpl.cs +++ /dev/null @@ -1,86 +0,0 @@ -// 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 Avalonia.Media; -using Avalonia.Platform; -using System.Collections.Generic; - -namespace Avalonia.Cairo.Media -{ - using Cairo = global::Cairo; - - public class StreamGeometryImpl : IStreamGeometryImpl - { - public StreamGeometryImpl() - { - _impl = new StreamGeometryContextImpl(this, null); - } - - public StreamGeometryImpl(StreamGeometryContextImpl impl) - { - _impl = impl; - } - - public Rect Bounds - { - get { return _impl.Bounds; } - } - - public Cairo.Path Path - { - get { return _impl.Path; } - } - - private readonly StreamGeometryContextImpl _impl; - - private Matrix _transform = Matrix.Identity; - - public Matrix Transform - { - get { return _transform; } - private set { _transform = value; } - } - - public FillRule FillRule { get; set; } - - public IStreamGeometryImpl Clone() - { - return new StreamGeometryImpl(_impl); - } - - public Rect GetRenderBounds(double strokeThickness) - { - // TODO: Calculate properly. - return Bounds.TransformToAABB(Transform).Inflate(strokeThickness); - } - - public IStreamGeometryContextImpl Open() - { - return _impl; - } - - public bool FillContains(Point point) - { - return _impl.FillContains(point); - } - - public IGeometryImpl Intersect(IGeometryImpl geometry) - { - throw new NotImplementedException(); - } - - public bool StrokeContains(Pen pen, Point point) - { - return _impl.StrokeContains(pen, point); - } - - /// - public IGeometryImpl WithTransform(Matrix transform) - { - var result = (StreamGeometryImpl)Clone(); - result.Transform = transform; - return result; - } - } -} diff --git a/src/Gtk/Avalonia.Cairo/Properties/AssemblyInfo.cs b/src/Gtk/Avalonia.Cairo/Properties/AssemblyInfo.cs deleted file mode 100644 index 709f1eb22a..0000000000 --- a/src/Gtk/Avalonia.Cairo/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,25 +0,0 @@ -// 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.Cairo; -using Avalonia.Platform; -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Avalonia.Cairo")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("f999ba8b-64e7-40cc-98a4-003f1852d2a3")] - -[assembly: ExportRenderingSubsystem(OperatingSystemType.WinNT, 3, "Cairo", typeof(CairoPlatform), nameof(CairoPlatform.Initialize), RequiresWindowingSubsystem = "GTK")] -[assembly: ExportRenderingSubsystem(OperatingSystemType.Linux, 2, "Cairo", typeof(CairoPlatform), nameof(CairoPlatform.Initialize), RequiresWindowingSubsystem = "GTK")] -[assembly: ExportRenderingSubsystem(OperatingSystemType.OSX, 3, "Cairo", typeof(CairoPlatform), nameof(CairoPlatform.Initialize), RequiresWindowingSubsystem = "GTK")] diff --git a/src/Gtk/Avalonia.Cairo/RenderTarget.cs b/src/Gtk/Avalonia.Cairo/RenderTarget.cs deleted file mode 100644 index b18c07377b..0000000000 --- a/src/Gtk/Avalonia.Cairo/RenderTarget.cs +++ /dev/null @@ -1,58 +0,0 @@ -// 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.Runtime.InteropServices; -using Avalonia.Cairo.Media; -using Avalonia.Media; -using Avalonia.Platform; -using Avalonia.Rendering; -using Gtk; -using DrawingContext = Avalonia.Media.DrawingContext; - -namespace Avalonia.Cairo -{ - using global::Cairo; - - /// - /// A cairo render target. - /// - public class RenderTarget : IRenderTarget - { - private readonly Surface _surface; - private readonly Func _drawableAccessor; - - - /// - /// Initializes a new instance of the class. - /// - /// The window. - /// The width of the window. - /// The height of the window. - public RenderTarget(Func drawable) - { - _drawableAccessor = drawable; - } - - public RenderTarget(ImageSurface surface) - { - _surface = surface; - } - - /// - /// Creates a cairo surface that targets a platform-specific resource. - /// - /// The visual brush renderer to use. - /// A surface wrapped in an . - public IDrawingContextImpl CreateDrawingContext(IVisualBrushRenderer visualBrushRenderer) - { - if (_drawableAccessor != null) - return new Media.DrawingContext(_drawableAccessor(), visualBrushRenderer); - if (_surface != null) - return new Media.DrawingContext(_surface, visualBrushRenderer); - throw new InvalidOperationException("Unspecified render target"); - } - - public void Dispose() => _surface?.Dispose(); - } -} diff --git a/src/Gtk/Avalonia.Cairo/app.config b/src/Gtk/Avalonia.Cairo/app.config deleted file mode 100644 index 754c958222..0000000000 --- a/src/Gtk/Avalonia.Cairo/app.config +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/src/Gtk/Avalonia.Gtk/Avalonia.Gtk.csproj b/src/Gtk/Avalonia.Gtk/Avalonia.Gtk.csproj deleted file mode 100644 index 6049869424..0000000000 --- a/src/Gtk/Avalonia.Gtk/Avalonia.Gtk.csproj +++ /dev/null @@ -1,104 +0,0 @@ - - - - Debug - AnyCPU - {54F237D5-A70A-4752-9656-0C70B1A7B047} - Library - Avalonia.Gtk - Avalonia.Gtk - v4.6.1 - - - - - true - full - false - bin\Debug - DEBUG; - prompt - 4 - false - - - full - true - bin\Release - prompt - 4 - false - - - - - - - - - - - - - Properties\SharedAssemblyInfo.cs - - - - - - - - - - - - - - - - - - - - - - - - {D211E587-D8BC-45B9-95A4-F297C8FA5200} - Avalonia.Animation - - - {B09B78D8-9B26-48B0-9149-D64A2F120F3F} - Avalonia.Base - - - {7062ae20-5dcc-4442-9645-8195bdece63e} - Avalonia.Diagnostics - - - {62024B2D-53EB-4638-B26B-85EEAA54866E} - Avalonia.Input - - - {EB582467-6ABB-43A1-B052-E981BA910E3A} - Avalonia.Visuals - - - {42472427-4774-4C81-8AFF-9F27B8E31721} - Avalonia.Layout - - - {D2221C82-4A25-4583-9B43-D791E3F6820C} - Avalonia.Controls - - - {F1BAA01A-F176-4C6A-B39D-5B40BB1B148F} - Avalonia.Styling - - - {6B0ED19D-A08B-461C-A9D9-A9EE40B0C06B} - Avalonia.Interactivity - - - - \ No newline at end of file diff --git a/src/Gtk/Avalonia.Gtk/ClipboardImpl.cs b/src/Gtk/Avalonia.Gtk/ClipboardImpl.cs deleted file mode 100644 index db59789bc9..0000000000 --- a/src/Gtk/Avalonia.Gtk/ClipboardImpl.cs +++ /dev/null @@ -1,42 +0,0 @@ -// 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.Threading.Tasks; -using Gdk; -using Avalonia.Input.Platform; - -namespace Avalonia.Gtk -{ - using Gtk = global::Gtk; - - internal class ClipboardImpl : IClipboard - { - private static Gtk.Clipboard GetClipboard() => Gtk.Clipboard.GetForDisplay(Display.Default, new Atom(IntPtr.Zero)); - - public Task GetTextAsync() - { - var clip = GetClipboard(); - var tcs = new TaskCompletionSource(); - clip.RequestText((_, text) => - { - tcs.TrySetResult(text); - }); - return tcs.Task; - } - - public Task SetTextAsync(string text) - { - using (var cl = GetClipboard()) - cl.Text = text; - return Task.FromResult(0); - } - - public Task ClearAsync() - { - using (var cl = GetClipboard()) - cl.Clear(); - return Task.FromResult(0); - } - } -} diff --git a/src/Gtk/Avalonia.Gtk/CursorFactory.cs b/src/Gtk/Avalonia.Gtk/CursorFactory.cs deleted file mode 100644 index bd8166c59e..0000000000 --- a/src/Gtk/Avalonia.Gtk/CursorFactory.cs +++ /dev/null @@ -1,85 +0,0 @@ -// 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.Collections.Generic; -using Gdk; -using Avalonia.Input; -using Avalonia.Platform; - -namespace Avalonia.Gtk -{ - using Gtk = global::Gtk; - - internal class CursorFactory : IStandardCursorFactory - { - public static CursorFactory Instance { get; } = new CursorFactory(); - - private CursorFactory() - { - } - - private static readonly Dictionary CursorTypeMapping = new Dictionary - - { - {StandardCursorType.AppStarting, CursorType.Watch}, - {StandardCursorType.Arrow, CursorType.LeftPtr}, - {StandardCursorType.Cross, CursorType.Cross}, - {StandardCursorType.Hand, CursorType.Hand1}, - {StandardCursorType.Ibeam, CursorType.Xterm}, - {StandardCursorType.No, Gtk.Stock.Cancel}, - {StandardCursorType.SizeAll, CursorType.Sizing}, - //{ StandardCursorType.SizeNorthEastSouthWest, 32643 }, - {StandardCursorType.SizeNorthSouth, CursorType.SbVDoubleArrow}, - //{ StandardCursorType.SizeNorthWestSouthEast, 32642 }, - {StandardCursorType.SizeWestEast, CursorType.SbHDoubleArrow}, - {StandardCursorType.UpArrow, CursorType.BasedArrowUp}, - {StandardCursorType.Wait, CursorType.Watch}, - {StandardCursorType.Help, Gtk.Stock.Help}, - {StandardCursorType.TopSide, CursorType.TopSide}, - {StandardCursorType.BottomSize, CursorType.BottomSide}, - {StandardCursorType.LeftSide, CursorType.LeftSide}, - {StandardCursorType.RightSide, CursorType.RightSide}, - {StandardCursorType.TopLeftCorner, CursorType.TopLeftCorner}, - {StandardCursorType.TopRightCorner, CursorType.TopRightCorner}, - {StandardCursorType.BottomLeftCorner, CursorType.BottomLeftCorner}, - {StandardCursorType.BottomRightCorner, CursorType.BottomRightCorner} - }; - - private static readonly Dictionary Cache = - new Dictionary(); - - private Gdk.Cursor GetCursor(object desc) - { - Gdk.Cursor rv; - var name = desc as string; - if (name != null) - { - var theme = Gtk.IconTheme.Default; - var icon = theme.LoadIcon(name, 32, default(Gtk.IconLookupFlags)); - rv = icon == null ? new Gdk.Cursor(CursorType.XCursor) : new Gdk.Cursor(Display.Default, icon, 0, 0); - } - else - { - rv = new Gdk.Cursor((CursorType)desc); - } - - rv.Owned = false; - return rv; - } - - public IPlatformHandle GetCursor(StandardCursorType cursorType) - { - IPlatformHandle rv; - if (!Cache.TryGetValue(cursorType, out rv)) - { - Cache[cursorType] = - rv = - new PlatformHandle( - GetCursor(CursorTypeMapping[cursorType]).Handle, - "GTKCURSOR"); - } - - return rv; - } - } -} diff --git a/src/Gtk/Avalonia.Gtk/EmbeddableImpl.cs b/src/Gtk/Avalonia.Gtk/EmbeddableImpl.cs deleted file mode 100644 index 4e8085a057..0000000000 --- a/src/Gtk/Avalonia.Gtk/EmbeddableImpl.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reactive.Disposables; -using System.Text; -using System.Threading.Tasks; -using Avalonia.Platform; -using Gdk; -using Gtk; -using Action = System.Action; -using WindowEdge = Avalonia.Controls.WindowEdge; - -namespace Avalonia.Gtk -{ - class EmbeddableImpl : TopLevelImpl, IEmbeddableWindowImpl - { -#pragma warning disable CS0067 // Method not used - public event Action LostFocus; -#pragma warning restore CS0067 - - public EmbeddableImpl(DrawingArea area) : base(area) - { - area.Events = EventMask.AllEventsMask; - area.SizeAllocated += Plug_SizeAllocated; - } - - public EmbeddableImpl() : this(new PlatformHandleAwareDrawingArea()) - { - } - - private void Plug_SizeAllocated(object o, SizeAllocatedArgs args) - { - Resized?.Invoke(new Size(args.Allocation.Width, args.Allocation.Height)); - } - - public override Size ClientSize - { - get { return new Size(Widget.Allocation.Width, Widget.Allocation.Height); } - } - - } -} diff --git a/src/Gtk/Avalonia.Gtk/Embedding/GtkAvaloniaControlHost.cs b/src/Gtk/Avalonia.Gtk/Embedding/GtkAvaloniaControlHost.cs deleted file mode 100644 index 5594a3c13f..0000000000 --- a/src/Gtk/Avalonia.Gtk/Embedding/GtkAvaloniaControlHost.cs +++ /dev/null @@ -1,77 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Avalonia.Controls; -using Avalonia.Controls.Embedding; -using Avalonia.Diagnostics; -using Avalonia.Input; -using Avalonia.Interactivity; -using Avalonia.Layout; -using Avalonia.Platform; -using Avalonia.VisualTree; -using Gdk; -using Gtk; - -namespace Avalonia.Gtk.Embedding -{ - public class GtkAvaloniaControlHost : DrawingArea, IPlatformHandle - { - private EmbeddableControlRoot _root; - - public GtkAvaloniaControlHost() - { - _root = new EmbeddableControlRoot(new EmbeddableImpl(this)); - _root.Prepare(); - if (_root.IsFocused) - Unfocus(); - _root.GotFocus += RootGotFocus; - CanFocus = true; - } - - void Unfocus() - { - var focused = (IVisual)FocusManager.Instance.Current; - if (focused == null) - return; - while (focused.VisualParent != null) - focused = focused.VisualParent; - - if (focused == _root) - KeyboardDevice.Instance.SetFocusedElement(null, NavigationMethod.Unspecified, InputModifiers.None); - } - - protected override bool OnFocusOutEvent(EventFocus evnt) - { - Unfocus(); - return false; - } - - private void RootGotFocus(object sender, RoutedEventArgs e) - { - this.HasFocus = true; - GdkWindow.Focus(0); - } - - private Control _content; - - public Control Content - { - get { return _content; } - set - { - _content = value; - if (_root != null) - { - _root.Content = value; - _root.Prepare(); - } - } - } - - IntPtr IPlatformHandle.Handle => PlatformHandleAwareWindow.GetNativeWindow(GdkWindow); - - string IPlatformHandle.HandleDescriptor => "HWND"; - } -} diff --git a/src/Gtk/Avalonia.Gtk/FramebufferManager.cs b/src/Gtk/Avalonia.Gtk/FramebufferManager.cs deleted file mode 100644 index 5ec49fb91f..0000000000 --- a/src/Gtk/Avalonia.Gtk/FramebufferManager.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using Avalonia.Controls.Platform.Surfaces; -using Avalonia.Platform; - -namespace Avalonia.Gtk -{ - class FramebufferManager : IFramebufferPlatformSurface, IDisposable - { - private readonly TopLevelImpl _window; - private SurfaceFramebuffer _fb; - - public FramebufferManager(TopLevelImpl window) - { - _window = window; - } - - public void Dispose() - { - _fb?.Deallocate(); - } - - public ILockedFramebuffer Lock() - { - if(_window.CurrentDrawable == null) - throw new InvalidOperationException("Window is not in drawing state"); - - var drawable = _window.CurrentDrawable; - var width = (int) _window.ClientSize.Width; - var height = (int) _window.ClientSize.Height; - if (_fb == null || _fb.Width != width || - _fb.Height != height) - { - _fb?.Deallocate(); - _fb = new SurfaceFramebuffer(width, height); - } - _fb.SetDrawable(drawable); - return _fb; - } - } -} diff --git a/src/Gtk/Avalonia.Gtk/GtkExtensions.cs b/src/Gtk/Avalonia.Gtk/GtkExtensions.cs deleted file mode 100644 index b9bb9a778a..0000000000 --- a/src/Gtk/Avalonia.Gtk/GtkExtensions.cs +++ /dev/null @@ -1,15 +0,0 @@ -// 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. - -namespace Avalonia.Gtk -{ - using Gtk = global::Gtk; - - public static class GtkExtensions - { - public static Rect ToAvalonia(this Gdk.Rectangle rect) - { - return new Rect(rect.Left, rect.Top, rect.Right, rect.Bottom); - } - } -} diff --git a/src/Gtk/Avalonia.Gtk/GtkPlatform.cs b/src/Gtk/Avalonia.Gtk/GtkPlatform.cs deleted file mode 100644 index f449229c53..0000000000 --- a/src/Gtk/Avalonia.Gtk/GtkPlatform.cs +++ /dev/null @@ -1,140 +0,0 @@ -// 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.Reactive.Disposables; -using System.Threading; -using Avalonia.Controls.Platform; -using Avalonia.Input.Platform; -using Avalonia.Input; -using Avalonia.Platform; -using Avalonia.Controls; - -namespace Avalonia -{ - public static class GtkApplicationExtensions - { - public static T UseGtk(this T builder) where T : AppBuilderBase, new() - { - builder.UseWindowingSubsystem(Gtk.GtkPlatform.Initialize, "Gtk"); - return builder; - } - } -} - -namespace Avalonia.Gtk -{ - using System.IO; - using Rendering; - using Gtk = global::Gtk; - - public class GtkPlatform : IPlatformThreadingInterface, IPlatformSettings, IWindowingPlatform, IPlatformIconLoader - { - private static readonly GtkPlatform s_instance = new GtkPlatform(); - private static Thread _uiThread; - - public GtkPlatform() - { - Gtk.Application.Init(); - } - - public Size DoubleClickSize => new Size(4, 4); - - public TimeSpan DoubleClickTime => TimeSpan.FromMilliseconds(Gtk.Settings.Default.DoubleClickTime); - public double RenderScalingFactor { get; } = 1; - public double LayoutScalingFactor { get; } = 1; - - public static void Initialize() - { - AvaloniaLocator.CurrentMutable - .Bind().ToConstant(s_instance) - .Bind().ToSingleton() - .Bind().ToConstant(CursorFactory.Instance) - .Bind().ToConstant(GtkKeyboardDevice.Instance) - .Bind().ToConstant(s_instance) - .Bind().ToConstant(s_instance) - .Bind().ToConstant(new DefaultRenderLoop(60)) - .Bind().ToSingleton() - .Bind().ToConstant(s_instance); - _uiThread = Thread.CurrentThread; - } - - public bool HasMessages() - { - return Gtk.Application.EventsPending(); - } - - public void ProcessMessage() - { - Gtk.Application.RunIteration(); - } - - public void RunLoop(CancellationToken cancellationToken) - { - while (!cancellationToken.IsCancellationRequested) - Gtk.Application.RunIteration(); - } - - public IDisposable StartTimer(TimeSpan interval, Action tick) - { - var result = true; - var handle = GLib.Timeout.Add( - (uint)interval.TotalMilliseconds, - () => - { - tick(); - return result; - }); - - return Disposable.Create(() => result = false); - } - - - - public void Signal() - { - Gtk.Application.Invoke(delegate { Signaled?.Invoke(); }); - } - - public bool CurrentThreadIsLoopThread => Thread.CurrentThread == _uiThread; - - public event Action Signaled; - public IWindowImpl CreateWindow() - { - return new WindowImpl(); - } - - public IEmbeddableWindowImpl CreateEmbeddableWindow() => new EmbeddableImpl(); - - public IPopupImpl CreatePopup() - { - return new PopupImpl(); - } - - public IWindowIconImpl LoadIcon(string fileName) - { - return new IconImpl(new Gdk.Pixbuf(fileName)); - } - - public IWindowIconImpl LoadIcon(Stream stream) - { - return new IconImpl(new Gdk.Pixbuf(stream)); - } - - public IWindowIconImpl LoadIcon(IBitmapImpl bitmap) - { - if (bitmap is Gdk.Pixbuf) - { - return new IconImpl((Gdk.Pixbuf)bitmap); - } - else - { - using (var memoryStream = new MemoryStream()) - { - bitmap.Save(memoryStream); - return new IconImpl(new Gdk.Pixbuf(memoryStream)); - } - } - } - } -} \ No newline at end of file diff --git a/src/Gtk/Avalonia.Gtk/IconImpl.cs b/src/Gtk/Avalonia.Gtk/IconImpl.cs deleted file mode 100644 index 3203e59f21..0000000000 --- a/src/Gtk/Avalonia.Gtk/IconImpl.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Avalonia.Platform; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Gdk; -using System.IO; - -namespace Avalonia.Gtk -{ - class IconImpl : IWindowIconImpl - { - public IconImpl(Pixbuf pixbuf) - { - Pixbuf = pixbuf; - } - - public Pixbuf Pixbuf { get; } - - public void Save(Stream stream) - { - var buffer = Pixbuf.SaveToBuffer("png"); - stream.Write(buffer, 0, buffer.Length); - } - } -} diff --git a/src/Gtk/Avalonia.Gtk/Input/GtkKeyboardDevice.cs b/src/Gtk/Avalonia.Gtk/Input/GtkKeyboardDevice.cs deleted file mode 100644 index a97a6190f1..0000000000 --- a/src/Gtk/Avalonia.Gtk/Input/GtkKeyboardDevice.cs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) The Avalonia Project. All rights reserved. -// Licensed under the MIT license. See licence.md file in the project root for full license information. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Text; -using Avalonia.Input; - - -namespace Avalonia.Gtk -{ - public class GtkKeyboardDevice : KeyboardDevice - { - public new static GtkKeyboardDevice Instance { get; } = new GtkKeyboardDevice(); - } -} \ No newline at end of file diff --git a/src/Gtk/Avalonia.Gtk/Input/GtkMouseDevice.cs b/src/Gtk/Avalonia.Gtk/Input/GtkMouseDevice.cs deleted file mode 100644 index c5de869647..0000000000 --- a/src/Gtk/Avalonia.Gtk/Input/GtkMouseDevice.cs +++ /dev/null @@ -1,29 +0,0 @@ -// 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; -namespace Avalonia.Gtk -{ - public class GtkMouseDevice : MouseDevice - { - private static readonly GtkMouseDevice s_instance; - - private Point _clientPosition; - - static GtkMouseDevice() - { - s_instance = new GtkMouseDevice(); - } - - private GtkMouseDevice() - { - } - - public static new GtkMouseDevice Instance => s_instance; - - internal void SetClientPosition(Point p) - { - _clientPosition = p; - } - } -} \ No newline at end of file diff --git a/src/Gtk/Avalonia.Gtk/MyClass.cs b/src/Gtk/Avalonia.Gtk/MyClass.cs deleted file mode 100644 index 589431fcb1..0000000000 --- a/src/Gtk/Avalonia.Gtk/MyClass.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; - -namespace Avalonia.Gtk -{ - public class MyClass - { - public MyClass () - { - } - } -} - diff --git a/src/Gtk/Avalonia.Gtk/PopupImpl.cs b/src/Gtk/Avalonia.Gtk/PopupImpl.cs deleted file mode 100644 index 41ee4354fe..0000000000 --- a/src/Gtk/Avalonia.Gtk/PopupImpl.cs +++ /dev/null @@ -1,16 +0,0 @@ -// 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 Gtk; -using Avalonia.Platform; - -namespace Avalonia.Gtk -{ - public class PopupImpl : WindowImpl, IPopupImpl - { - public PopupImpl() - : base(WindowType.Popup) - { - } - } -} diff --git a/src/Gtk/Avalonia.Gtk/Properties/AssemblyInfo.cs b/src/Gtk/Avalonia.Gtk/Properties/AssemblyInfo.cs deleted file mode 100644 index 67e5f6dc17..0000000000 --- a/src/Gtk/Avalonia.Gtk/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,15 +0,0 @@ -// 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.Gtk; -using Avalonia.Platform; -using System.Reflection; - -// Information about this assembly is defined by the following attributes. -// Change them to the values specific to your project. -[assembly: AssemblyTitle("Avalonia.Gtk")] - -[assembly: ExportWindowingSubsystem(OperatingSystemType.WinNT, 3, "GTK", typeof(GtkPlatform), nameof(GtkPlatform.Initialize))] -[assembly: ExportWindowingSubsystem(OperatingSystemType.Linux, 2, "GTK", typeof(GtkPlatform), nameof(GtkPlatform.Initialize))] -[assembly: ExportWindowingSubsystem(OperatingSystemType.OSX, 3, "GTK", typeof(GtkPlatform), nameof(GtkPlatform.Initialize))] - diff --git a/src/Gtk/Avalonia.Gtk/SurfaceFramebuffer.cs b/src/Gtk/Avalonia.Gtk/SurfaceFramebuffer.cs deleted file mode 100644 index 29f4ce1d15..0000000000 --- a/src/Gtk/Avalonia.Gtk/SurfaceFramebuffer.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Avalonia.Controls.Platform.Surfaces; -using Avalonia.Platform; -using Cairo; -using Gdk; - -namespace Avalonia.Gtk -{ - class SurfaceFramebuffer : ILockedFramebuffer - { - private Drawable _drawable; - private ImageSurface _surface; - - public SurfaceFramebuffer(int width, int height) - { - _surface = new ImageSurface(Cairo.Format.RGB24, width, height); - } - - public void SetDrawable(Drawable drawable) - { - _drawable = drawable; - _surface.Flush(); - } - - public void Deallocate() - { - _surface.Dispose(); - _surface = null; - } - - public void Dispose() - { - using (var ctx = CairoHelper.Create(_drawable)) - { - _surface.MarkDirty(); - ctx.SetSourceSurface(_surface, 0, 0); - ctx.Paint(); - } - _drawable = null; - } - - public IntPtr Address => _surface.DataPtr; - public int Width => _surface.Width; - public int Height => _surface.Height; - public int RowBytes => _surface.Stride; - //TODO: Proper DPI detect - public Vector Dpi => new Vector(96, 96); - public PixelFormat Format => PixelFormat.Bgra8888; - } -} - diff --git a/src/Gtk/Avalonia.Gtk/SystemDialogImpl.cs b/src/Gtk/Avalonia.Gtk/SystemDialogImpl.cs deleted file mode 100644 index 05dc1bf02d..0000000000 --- a/src/Gtk/Avalonia.Gtk/SystemDialogImpl.cs +++ /dev/null @@ -1,88 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Avalonia.Controls; -using Avalonia.Controls.Platform; -using Avalonia.Platform; - -namespace Avalonia.Gtk -{ - using global::Gtk; - class SystemDialogImpl : ISystemDialogImpl - { - public Task ShowFileDialogAsync(FileDialog dialog, IWindowImpl parent) - { - var tcs = new TaskCompletionSource(); - var dlg = new global::Gtk.FileChooserDialog(dialog.Title, ((TopLevelImpl)parent)?.Widget.Toplevel as Window, - dialog is OpenFileDialog - ? FileChooserAction.Open - : FileChooserAction.Save, - "Cancel", ResponseType.Cancel, - "Open", ResponseType.Accept) - { - SelectMultiple = (dialog as OpenFileDialog)?.AllowMultiple ?? false, - }; - foreach (var filter in dialog.Filters) - { - var ffilter = new FileFilter() - { - Name = filter.Name + " (" + string.Join(";", filter.Extensions.Select(e => "*." + e)) + ")" - }; - foreach (var ext in filter.Extensions) - ffilter.AddPattern("*." + ext); - dlg.AddFilter(ffilter); - } - dlg.SetFilename(dialog.InitialFileName); - dlg.Modal = true; - - dlg.Response += (_, args) => - { - if (args.ResponseId == ResponseType.Accept) - tcs.TrySetResult(dlg.Filenames); - dlg.Hide(); - dlg.Dispose(); - }; - - dlg.Close += delegate - { - tcs.TrySetResult(null); - dlg.Dispose(); - }; - dlg.Show(); - return tcs.Task; - } - - public Task ShowFolderDialogAsync(OpenFolderDialog dialog, IWindowImpl parent) - { - var tcs = new TaskCompletionSource(); - var dlg = new global::Gtk.FileChooserDialog(dialog.Title, ((TopLevelImpl)parent)?.Widget.Toplevel as Window, - FileChooserAction.SelectFolder, - "Cancel", ResponseType.Cancel, - "Select Folder", ResponseType.Accept) - { - - }; - - dlg.Modal = true; - - dlg.Response += (_, args) => - { - if (args.ResponseId == ResponseType.Accept) - tcs.TrySetResult(dlg.Filename); - - dlg.Hide(); - dlg.Dispose(); - }; - - dlg.Close += delegate - { - tcs.TrySetResult(null); - dlg.Dispose(); - }; - dlg.Show(); - return tcs.Task; - } - } -} diff --git a/src/Gtk/Avalonia.Gtk/TopLevelImpl.cs b/src/Gtk/Avalonia.Gtk/TopLevelImpl.cs deleted file mode 100644 index 5c18d015d4..0000000000 --- a/src/Gtk/Avalonia.Gtk/TopLevelImpl.cs +++ /dev/null @@ -1,320 +0,0 @@ -// Copyright (c) The Avalonia Project. All rights reserved. -// Licensed under the MIT license. See licence.md file in the project root for full license information. - -using System; -using System.Collections.Generic; -using Avalonia.Input; -using Avalonia.Input.Raw; -using Avalonia.Platform; -using Gdk; -using Action = System.Action; -using WindowEdge = Avalonia.Controls.WindowEdge; -using GLib; -using Avalonia.Rendering; - -namespace Avalonia.Gtk -{ - using Gtk = global::Gtk; - - public abstract class TopLevelImpl : ITopLevelImpl - { - private IInputRoot _inputRoot; - private Gtk.Widget _widget; - private FramebufferManager _framebuffer; - - private Gtk.IMContext _imContext; - - private uint _lastKeyEventTimestamp; - - private static readonly Gdk.Cursor DefaultCursor = new Gdk.Cursor(CursorType.LeftPtr); - - protected TopLevelImpl(Gtk.Widget window) - { - _widget = window; - _framebuffer = new FramebufferManager(this); - Init(); - } - - void Init() - { - Handle = _widget as IPlatformHandle; - _widget.Events = EventMask.AllEventsMask; - _imContext = new Gtk.IMMulticontext(); - _imContext.Commit += ImContext_Commit; - _widget.Realized += OnRealized; - _widget.Realize(); - _widget.ButtonPressEvent += OnButtonPressEvent; - _widget.ButtonReleaseEvent += OnButtonReleaseEvent; - _widget.ScrollEvent += OnScrollEvent; - _widget.Destroyed += OnDestroyed; - _widget.KeyPressEvent += OnKeyPressEvent; - _widget.KeyReleaseEvent += OnKeyReleaseEvent; - _widget.ExposeEvent += OnExposeEvent; - _widget.MotionNotifyEvent += OnMotionNotifyEvent; - - - } - - public IPlatformHandle Handle { get; private set; } - public Gtk.Widget Widget => _widget; - public Gdk.Drawable CurrentDrawable { get; private set; } - - void OnRealized (object sender, EventArgs eventArgs) - { - _imContext.ClientWindow = _widget.GdkWindow; - } - - public abstract Size ClientSize { get; } - - public Size MaxClientSize - { - get - { - // TODO: This should take into account things such as taskbar and window border - // thickness etc. - return new Size(_widget.Screen.Width, _widget.Screen.Height); - } - } - - public IMouseDevice MouseDevice => GtkMouseDevice.Instance; - - public Avalonia.Controls.WindowState WindowState - { - get - { - switch (_widget.GdkWindow.State) - { - case Gdk.WindowState.Iconified: - return Controls.WindowState.Minimized; - case Gdk.WindowState.Maximized: - return Controls.WindowState.Maximized; - default: - return Controls.WindowState.Normal; - } - } - - set - { - switch (value) - { - case Controls.WindowState.Minimized: - _widget.GdkWindow.Iconify(); - break; - case Controls.WindowState.Maximized: - _widget.GdkWindow.Maximize(); - break; - case Controls.WindowState.Normal: - _widget.GdkWindow.Deiconify(); - _widget.GdkWindow.Unmaximize(); - break; - } - } - } - - public double Scaling => 1; - - public Action Activated { get; set; } - - public Action Closed { get; set; } - - - public Action Deactivated { get; set; } - - public Action Input { get; set; } - - public Action Paint { get; set; } - - public Action Resized { get; set; } - - public Action PositionChanged { get; set; } - - public Action ScalingChanged { get; set; } - - public IEnumerable Surfaces => new object[] - { - Handle, - new Func(() => CurrentDrawable), - _framebuffer - }; - - public IPopupImpl CreatePopup() - { - return new PopupImpl(); - } - - public IRenderer CreateRenderer(IRenderRoot root) - { - return new ImmediateRenderer(root); - } - - public void Invalidate(Rect rect) - { - if (_widget?.GdkWindow != null) - _widget.GdkWindow.InvalidateRect( - new Rectangle((int) rect.X, (int) rect.Y, (int) rect.Width, (int) rect.Height), true); - } - - public Point PointToClient(Point point) - { - int x, y; - _widget.GdkWindow.GetDeskrelativeOrigin(out x, out y); - - return new Point(point.X - x, point.Y - y); - } - - public Point PointToScreen(Point point) - { - int x, y; - _widget.GdkWindow.GetDeskrelativeOrigin(out x, out y); - return new Point(point.X + x, point.Y + y); - } - - public void SetInputRoot(IInputRoot inputRoot) - { - _inputRoot = inputRoot; - } - - - public void SetCursor(IPlatformHandle cursor) - { - _widget.GdkWindow.Cursor = cursor != null ? new Gdk.Cursor(cursor.Handle) : DefaultCursor; - } - - public void Show() => _widget.Show(); - - public void Hide() => _widget.Hide(); - - private static InputModifiers GetModifierKeys(ModifierType state) - { - var rv = InputModifiers.None; - if (state.HasFlag(ModifierType.ControlMask)) - rv |= InputModifiers.Control; - if (state.HasFlag(ModifierType.ShiftMask)) - rv |= InputModifiers.Shift; - if (state.HasFlag(ModifierType.Mod1Mask)) - rv |= InputModifiers.Control; - if(state.HasFlag(ModifierType.Button1Mask)) - rv |= InputModifiers.LeftMouseButton; - if (state.HasFlag(ModifierType.Button2Mask)) - rv |= InputModifiers.RightMouseButton; - if (state.HasFlag(ModifierType.Button3Mask)) - rv |= InputModifiers.MiddleMouseButton; - return rv; - } - - void OnButtonPressEvent(object o, Gtk.ButtonPressEventArgs args) - { - var evnt = args.Event; - var e = new RawMouseEventArgs( - GtkMouseDevice.Instance, - evnt.Time, - _inputRoot, - evnt.Button == 1 - ? RawMouseEventType.LeftButtonDown - : evnt.Button == 3 ? RawMouseEventType.RightButtonDown : RawMouseEventType.MiddleButtonDown, - new Point(evnt.X, evnt.Y), GetModifierKeys(evnt.State)); - Input(e); - } - - void OnScrollEvent(object o, Gtk.ScrollEventArgs args) - { - var evnt = args.Event; - double step = 1; - var delta = new Vector(); - if (evnt.Direction == ScrollDirection.Down) - delta = new Vector(0, -step); - else if (evnt.Direction == ScrollDirection.Up) - delta = new Vector(0, step); - else if (evnt.Direction == ScrollDirection.Right) - delta = new Vector(-step, 0); - if (evnt.Direction == ScrollDirection.Left) - delta = new Vector(step, 0); - var e = new RawMouseWheelEventArgs(GtkMouseDevice.Instance, evnt.Time, _inputRoot, new Point(evnt.X, evnt.Y), delta, GetModifierKeys(evnt.State)); - Input(e); - } - - protected void OnButtonReleaseEvent(object o, Gtk.ButtonReleaseEventArgs args) - { - var evnt = args.Event; - var e = new RawMouseEventArgs( - GtkMouseDevice.Instance, - evnt.Time, - _inputRoot, - evnt.Button == 1 - ? RawMouseEventType.LeftButtonUp - : evnt.Button == 3 ? RawMouseEventType.RightButtonUp : RawMouseEventType.MiddleButtonUp, - new Point(evnt.X, evnt.Y), GetModifierKeys(evnt.State)); - Input(e); - } - - void OnDestroyed(object sender, EventArgs eventArgs) - { - Closed(); - } - - private void ProcessKeyEvent(EventKey evnt) - { - - _lastKeyEventTimestamp = evnt.Time; - if (_imContext.FilterKeypress(evnt)) - return; - var e = new RawKeyEventArgs( - GtkKeyboardDevice.Instance, - evnt.Time, - evnt.Type == EventType.KeyPress ? RawKeyEventType.KeyDown : RawKeyEventType.KeyUp, - Common.KeyTransform.ConvertKey(evnt.Key), GetModifierKeys(evnt.State)); - Input(e); - } - - [ConnectBefore] - void OnKeyPressEvent(object o, Gtk.KeyPressEventArgs args) - { - args.RetVal = true; - ProcessKeyEvent(args.Event); - } - - void OnKeyReleaseEvent(object o, Gtk.KeyReleaseEventArgs args) - { - args.RetVal = true; - ProcessKeyEvent(args.Event); - } - - private void ImContext_Commit(object o, Gtk.CommitArgs args) - { - Input(new RawTextInputEventArgs(GtkKeyboardDevice.Instance, _lastKeyEventTimestamp, args.Str)); - } - - void OnExposeEvent(object o, Gtk.ExposeEventArgs args) - { - CurrentDrawable = args.Event.Window; - Paint(args.Event.Area.ToAvalonia()); - CurrentDrawable = null; - args.RetVal = true; - } - - void OnMotionNotifyEvent(object o, Gtk.MotionNotifyEventArgs args) - { - var evnt = args.Event; - var position = new Point(evnt.X, evnt.Y); - - GtkMouseDevice.Instance.SetClientPosition(position); - - var e = new RawMouseEventArgs( - GtkMouseDevice.Instance, - evnt.Time, - _inputRoot, - RawMouseEventType.Move, - position, GetModifierKeys(evnt.State)); - Input(e); - args.RetVal = true; - } - - public void Dispose() - { - _framebuffer.Dispose(); - _widget.Hide(); - _widget.Dispose(); - _widget = null; - } - } -} diff --git a/src/Gtk/Avalonia.Gtk/WindowImpl.cs b/src/Gtk/Avalonia.Gtk/WindowImpl.cs deleted file mode 100644 index 2c1826c509..0000000000 --- a/src/Gtk/Avalonia.Gtk/WindowImpl.cs +++ /dev/null @@ -1,133 +0,0 @@ -using System; -using System.Reactive.Disposables; -using Avalonia.Platform; -using Gdk; - -namespace Avalonia.Gtk -{ - using Gtk = global::Gtk; - - public class WindowImpl : TopLevelImpl, IWindowImpl - { - private Gtk.Window _window; - private Gtk.Window Window => _window ?? (_window = (Gtk.Window)Widget); - - public WindowImpl(Gtk.WindowType type) : base(new PlatformHandleAwareWindow(type)) - { - Init(); - } - - public WindowImpl() - : base(new PlatformHandleAwareWindow(Gtk.WindowType.Toplevel) {DefaultSize = new Gdk.Size(900, 480)}) - { - Init(); - } - - void Init() - { - Window.FocusActivated += OnFocusActivated; - Window.ConfigureEvent += OnConfigureEvent; - _lastClientSize = ClientSize; - _lastPosition = Position; - } - - private Size _lastClientSize; - private Point _lastPosition; - - void OnConfigureEvent(object o, Gtk.ConfigureEventArgs args) - { - var evnt = args.Event; - args.RetVal = true; - var newSize = new Size(evnt.Width, evnt.Height); - - if (newSize != _lastClientSize) - { - Resized(newSize); - _lastClientSize = newSize; - } - - var newPosition = new Point(evnt.X, evnt.Y); - - if (newPosition != _lastPosition) - { - PositionChanged(newPosition); - _lastPosition = newPosition; - } - } - - public override Size ClientSize - { - get - { - int width; - int height; - Window.GetSize(out width, out height); - return new Size(width, height); - } - } - - public void Resize(Size value) - { - Window.Resize((int)value.Width, (int)value.Height); - } - - public void SetTitle(string title) - { - Window.Title = title; - } - - void IWindowBaseImpl.Activate() - { - _window.Activate(); - } - - void OnFocusActivated(object sender, EventArgs eventArgs) - { - Activated(); - } - - public void BeginMoveDrag() - { - int x, y; - ModifierType mod; - Window.Screen.RootWindow.GetPointer(out x, out y, out mod); - Window.BeginMoveDrag(1, x, y, 0); - } - - public void BeginResizeDrag(Controls.WindowEdge edge) - { - int x, y; - ModifierType mod; - Window.Screen.RootWindow.GetPointer(out x, out y, out mod); - Window.BeginResizeDrag((Gdk.WindowEdge)(int)edge, 1, x, y, 0); - } - - public Point Position - { - get - { - int x, y; - Window.GetPosition(out x, out y); - return new Point(x, y); - } - set { Window.Move((int)value.X, (int)value.Y); } - } - - public IDisposable ShowDialog() - { - Window.Modal = true; - Window.Show(); - - return Disposable.Empty; - } - - public void SetSystemDecorations(bool enabled) => Window.Decorated = enabled; - - public void SetIcon(IWindowIconImpl icon) - { - Window.Icon = ((IconImpl)icon).Pixbuf; - } - - public void ShowTaskbarIcon(bool value) => Window.SkipTaskbarHint = !value; - } -} \ No newline at end of file diff --git a/src/Gtk/Avalonia.Gtk/Windows.cs b/src/Gtk/Avalonia.Gtk/Windows.cs deleted file mode 100644 index fe325f4114..0000000000 --- a/src/Gtk/Avalonia.Gtk/Windows.cs +++ /dev/null @@ -1,91 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; -using Avalonia.Platform; -using Gdk; -using Gtk; -using Window = Gtk.Window; -using WindowType = Gtk.WindowType; - -namespace Avalonia.Gtk -{ - class PlatformHandleAwareWindow : Window, IPlatformHandle - { - public PlatformHandleAwareWindow(WindowType type) : base(type) - { - Events = EventMask.AllEventsMask; - } - - IntPtr IPlatformHandle.Handle => GetNativeWindow(); - public string HandleDescriptor => "HWND"; - - - [DllImport("libgdk-win32-2.0-0.dll", CallingConvention = CallingConvention.Cdecl)] - static extern IntPtr gdk_win32_drawable_get_handle(IntPtr gdkWindow); - - [DllImport("libgtk-x11-2.0.so.0", CallingConvention = CallingConvention.Cdecl)] - static extern IntPtr gdk_x11_drawable_get_xid(IntPtr gdkWindow); - - [DllImport("libgdk-quartz-2.0-0.dylib", CallingConvention = CallingConvention.Cdecl)] - static extern IntPtr gdk_quartz_window_get_nswindow(IntPtr gdkWindow); - - IntPtr _nativeWindow; - - IntPtr GetNativeWindow() - { - if (_nativeWindow != IntPtr.Zero) - return _nativeWindow; - return _nativeWindow = GetNativeWindow(GdkWindow); - } - - public static IntPtr GetNativeWindow(Gdk.Window window) - { - IntPtr h = window.Handle; - - //Try whatever backend that works - try - { - return gdk_quartz_window_get_nswindow(h); - } - catch - { - } - try - { - return gdk_x11_drawable_get_xid(h); - } - catch - { - } - return gdk_win32_drawable_get_handle(h); - } - - protected override bool OnConfigureEvent(EventConfigure evnt) - { - base.OnConfigureEvent(evnt); - return false; - } - } - - class PlatformHandleAwareDrawingArea : DrawingArea, IPlatformHandle - { - - - - IntPtr IPlatformHandle.Handle => GetNativeWindow(); - public string HandleDescriptor => "HWND"; - IntPtr _nativeWindow; - - IntPtr GetNativeWindow() - { - - if (_nativeWindow != IntPtr.Zero) - return _nativeWindow; - Realize(); - return _nativeWindow = PlatformHandleAwareWindow.GetNativeWindow(GdkWindow); - } - } -} diff --git a/src/Gtk/Avalonia.Gtk3/Avalonia.Gtk3.csproj b/src/Gtk/Avalonia.Gtk3/Avalonia.Gtk3.csproj index b58a83b3d2..f1b990f349 100644 --- a/src/Gtk/Avalonia.Gtk3/Avalonia.Gtk3.csproj +++ b/src/Gtk/Avalonia.Gtk3/Avalonia.Gtk3.csproj @@ -1,7 +1,6 @@  netstandard2.0 - False false @@ -25,34 +24,6 @@ - - KeyTransform.cs - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Gtk/Avalonia.Gtk3/FramebufferManager.cs b/src/Gtk/Avalonia.Gtk3/FramebufferManager.cs index 41e174bce4..b0cc668569 100644 --- a/src/Gtk/Avalonia.Gtk3/FramebufferManager.cs +++ b/src/Gtk/Avalonia.Gtk3/FramebufferManager.cs @@ -23,11 +23,11 @@ namespace Avalonia.Gtk3 public ILockedFramebuffer Lock() { - if(_window.CurrentCairoContext == IntPtr.Zero) - throw new InvalidOperationException("Window is not in drawing state"); - var width = (int) _window.ClientSize.Width; - var height = (int) _window.ClientSize.Height; - return new ImageSurfaceFramebuffer(_window.CurrentCairoContext, _window.GtkWidget, width, height); + // This method may be called from non-UI thread, don't touch anything that calls back to GTK/GDK + var s = _window.ClientSize; + var width = (int) s.Width; + var height = (int) s.Height; + return new ImageSurfaceFramebuffer(_window, width, height, _window.LastKnownScaleFactor); } } } diff --git a/src/Gtk/Avalonia.Gtk3/Gtk3Platform.cs b/src/Gtk/Avalonia.Gtk3/Gtk3Platform.cs index 4ea1a5af56..b36a1cda91 100644 --- a/src/Gtk/Avalonia.Gtk3/Gtk3Platform.cs +++ b/src/Gtk/Avalonia.Gtk3/Gtk3Platform.cs @@ -12,6 +12,7 @@ using Avalonia.Input.Platform; using Avalonia.Platform; using Avalonia.Rendering; using Avalonia.Gtk3; +using Avalonia.Threading; namespace Avalonia.Gtk3 { @@ -21,6 +22,7 @@ namespace Avalonia.Gtk3 internal static readonly MouseDevice Mouse = new MouseDevice(); internal static readonly KeyboardDevice Keyboard = new KeyboardDevice(); internal static IntPtr App { get; set; } + public static bool UseDeferredRendering = true; public static void Initialize() { Resolver.Resolve(); @@ -65,37 +67,42 @@ namespace Avalonia.Gtk3 public IDisposable StartTimer(TimeSpan interval, Action tick) { - return GlibTimeout.StarTimer((uint) interval.TotalMilliseconds, tick); + var msec = interval.TotalMilliseconds; + if (msec <= 0) + throw new ArgumentException("Don't know how to create a timer with zero or negative interval"); + var imsec = (uint) msec; + if (imsec == 0) + imsec = 1; + return GlibTimeout.StarTimer(imsec, tick); } - private bool _signaled = false; + private bool[] _signaled = new bool[(int) DispatcherPriority.MaxValue + 1]; object _lock = new object(); - - public void Signal() + public void Signal(DispatcherPriority prio) { + var idx = (int) prio; lock(_lock) - if (!_signaled) + if (!_signaled[idx]) { - _signaled = true; - GlibTimeout.Add(0, () => + _signaled[idx] = true; + GlibTimeout.Add(GlibPriority.FromDispatcherPriority(prio), 0, () => { lock (_lock) { - _signaled = false; + _signaled[idx] = false; } - Signaled?.Invoke(); + Signaled?.Invoke(prio); return false; }); } } - public event Action Signaled; + public event Action Signaled; [ThreadStatic] private static bool s_tlsMarker; public bool CurrentThreadIsLoopThread => s_tlsMarker; - } } @@ -103,10 +110,11 @@ namespace Avalonia { public static class Gtk3AppBuilderExtensions { - public static T UseGtk3(this AppBuilderBase builder, ICustomGtk3NativeLibraryResolver resolver = null) + public static T UseGtk3(this AppBuilderBase builder, bool deferredRendering = true, ICustomGtk3NativeLibraryResolver resolver = null) where T : AppBuilderBase, new() { Resolver.Custom = resolver; + Gtk3Platform.UseDeferredRendering = deferredRendering; return builder.UseWindowingSubsystem(Gtk3Platform.Initialize, "GTK3"); } } diff --git a/src/Gtk/Avalonia.Gtk3/GtkScreen.cs b/src/Gtk/Avalonia.Gtk3/GtkScreen.cs new file mode 100644 index 0000000000..7c28dd47b9 --- /dev/null +++ b/src/Gtk/Avalonia.Gtk3/GtkScreen.cs @@ -0,0 +1,24 @@ +using Avalonia.Platform; + +namespace Avalonia.Gtk3 +{ + public class GtkScreen : Screen + { + private readonly int _screenId; + + public GtkScreen(Rect bounds, Rect workingArea, bool primary, int screenId) : base(bounds, workingArea, primary) + { + this._screenId = screenId; + } + + public override int GetHashCode() + { + return _screenId; + } + + public override bool Equals(object obj) + { + return (obj is GtkScreen screen) ? this._screenId == screen._screenId : base.Equals(obj); + } + } +} \ No newline at end of file diff --git a/src/Gtk/Avalonia.Gtk3/IDeferredRenderOperation.cs b/src/Gtk/Avalonia.Gtk3/IDeferredRenderOperation.cs new file mode 100644 index 0000000000..8c1456726c --- /dev/null +++ b/src/Gtk/Avalonia.Gtk3/IDeferredRenderOperation.cs @@ -0,0 +1,9 @@ +using System; + +namespace Avalonia.Gtk3 +{ + public interface IDeferredRenderOperation : IDisposable + { + void RenderNow(); + } +} \ No newline at end of file diff --git a/src/Gtk/Avalonia.Gtk3/ImageSurfaceFramebuffer.cs b/src/Gtk/Avalonia.Gtk3/ImageSurfaceFramebuffer.cs index 61b1e69aa2..182da7df58 100644 --- a/src/Gtk/Avalonia.Gtk3/ImageSurfaceFramebuffer.cs +++ b/src/Gtk/Avalonia.Gtk3/ImageSurfaceFramebuffer.cs @@ -1,27 +1,29 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; using Avalonia.Controls.Platform.Surfaces; using Avalonia.Gtk3.Interop; using Avalonia.Platform; +using Avalonia.Threading; namespace Avalonia.Gtk3 { class ImageSurfaceFramebuffer : ILockedFramebuffer { - private IntPtr _context; + private readonly WindowBaseImpl _impl; private readonly GtkWidget _widget; private CairoSurface _surface; private int _factor; - - public ImageSurfaceFramebuffer(IntPtr context, GtkWidget widget, int width, int height) + private object _lock = new object(); + public ImageSurfaceFramebuffer(WindowBaseImpl impl, int width, int height, int factor) { - _context = context; - _widget = widget; - _factor = (int)(Native.GtkWidgetGetScaleFactor?.Invoke(_widget) ?? 1u); + _impl = impl; + _widget = impl.GtkWidget; + _factor = factor; width *= _factor; height *= _factor; _surface = Native.CairoImageSurfaceCreate(1, width, height); @@ -32,18 +34,97 @@ namespace Avalonia.Gtk3 RowBytes = Native.CairoImageSurfaceGetStride(_surface); Native.CairoSurfaceFlush(_surface); } + + static void Draw(IntPtr context, CairoSurface surface, double factor) + { + + Native.CairoSurfaceMarkDirty(surface); + Native.CairoScale(context, 1d / factor, 1d / factor); + Native.CairoSetSourceSurface(context, surface, 0, 0); + Native.CairoPaint(context); + + } + /* + static Stopwatch St =Stopwatch.StartNew(); + private static int _frames; + private static int _fps;*/ + static void DrawToWidget(GtkWidget widget, CairoSurface surface, int width, int height, double factor) + { + if(surface == null || widget.IsClosed) + return; + var window = Native.GtkWidgetGetWindow(widget); + if(window == IntPtr.Zero) + return; + var rc = new GdkRectangle {Width = width, Height = height}; + Native.GdkWindowBeginPaintRect(window, ref rc); + var context = Native.GdkCairoCreate(window); + Draw(context, surface, factor); + /* + _frames++; + var el = St.Elapsed; + if (el.TotalSeconds > 1) + { + _fps = (int) (_frames / el.TotalSeconds); + _frames = 0; + St = Stopwatch.StartNew(); + } + + Native.CairoSetSourceRgba(context, 1, 0, 0, 1); + Native.CairoMoveTo(context, 20, 20); + Native.CairoSetFontSize(context, 30); + using (var txt = new Utf8Buffer("FPS: " + _fps)) + Native.CairoShowText(context, txt); + */ + + Native.CairoDestroy(context); + Native.GdkWindowEndPaint(window); + } + + class RenderOp : IDeferredRenderOperation + { + private readonly GtkWidget _widget; + private CairoSurface _surface; + private readonly double _factor; + private readonly int _width; + private readonly int _height; + + public RenderOp(GtkWidget widget, CairoSurface _surface, double factor, int width, int height) + { + _widget = widget; + this._surface = _surface; + _factor = factor; + _width = width; + _height = height; + } + + public void Dispose() + { + _surface?.Dispose(); + _surface = null; + } + + public void RenderNow() + { + DrawToWidget(_widget, _surface, _width, _height, _factor); + } + } public void Dispose() { - if(_context == IntPtr.Zero || _surface == null) - return; - Native.CairoSurfaceMarkDirty(_surface); - Native.CairoScale(_context, 1d / _factor, 1d / _factor); - Native.CairoSetSourceSurface(_context, _surface, 0, 0); - Native.CairoPaint(_context); - _context = IntPtr.Zero; - _surface.Dispose(); - _surface = null; + lock (_lock) + { + if (Dispatcher.UIThread.CheckAccess()) + { + if (_impl.CurrentCairoContext != IntPtr.Zero) + Draw(_impl.CurrentCairoContext, _surface, _factor); + else + DrawToWidget(_widget, _surface, Width, Height, _factor); + _surface.Dispose(); + } + else + _impl.SetNextRenderOperation(new RenderOp(_widget, _surface, _factor, Width, Height)); + _surface = null; + } } public IntPtr Address { get; } diff --git a/src/Gtk/Avalonia.Gtk3/Interop/CairoSurface.cs b/src/Gtk/Avalonia.Gtk3/Interop/CairoSurface.cs index 7838be9305..87a70c4d35 100644 --- a/src/Gtk/Avalonia.Gtk3/Interop/CairoSurface.cs +++ b/src/Gtk/Avalonia.Gtk3/Interop/CairoSurface.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Runtime.InteropServices; namespace Avalonia.Gtk3.Interop diff --git a/src/Gtk/Avalonia.Gtk3/Interop/GObject.cs b/src/Gtk/Avalonia.Gtk3/Interop/GObject.cs index 9766e8ca36..8d14515d28 100644 --- a/src/Gtk/Avalonia.Gtk3/Interop/GObject.cs +++ b/src/Gtk/Avalonia.Gtk3/Interop/GObject.cs @@ -46,7 +46,30 @@ namespace Avalonia.Gtk3.Interop class GtkImContext : GObject { - + } + + class GdkScreen : GObject + { + public GdkScreen() : base(IntPtr.Zero, false) + { + } + + public GdkScreen(IntPtr handle, bool owned = true) : base(handle, owned) + { + this.handle = handle; + } + } + + class UnownedGdkScreen : GdkScreen + { + public UnownedGdkScreen() : base(IntPtr.Zero, false) + { + } + + public UnownedGdkScreen(IntPtr handle, bool owned = true) : base(IntPtr.Zero, false) + { + this.handle = handle; + } } class GtkDialog : GtkWindow diff --git a/src/Gtk/Avalonia.Gtk3/Interop/GlibPriority.cs b/src/Gtk/Avalonia.Gtk3/Interop/GlibPriority.cs new file mode 100644 index 0000000000..add4ba3c02 --- /dev/null +++ b/src/Gtk/Avalonia.Gtk3/Interop/GlibPriority.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Avalonia.Threading; + +namespace Avalonia.Gtk3.Interop +{ + static class GlibPriority + { + public static int High = -100; + public static int Default = 0; + public static int HighIdle = 100; + public static int GtkResize = HighIdle + 10; + public static int GtkPaint = HighIdle + 20; + public static int DefaultIdle = 200; + public static int Low = 300; + public static int GdkEvents = Default; + public static int GdkRedraw = HighIdle + 20; + + public static int FromDispatcherPriority(DispatcherPriority prio) + { + if (prio == DispatcherPriority.Send) + return High; + if (prio == DispatcherPriority.Normal) + return Default; + if (prio == DispatcherPriority.DataBind) + return Default + 1; + if (prio == DispatcherPriority.Layout) + return Default + 2; + if (prio == DispatcherPriority.Render) + return Default + 3; + if (prio == DispatcherPriority.Loaded) + return GtkPaint + 20; + if (prio == DispatcherPriority.Input) + return GtkPaint + 21; + if (prio == DispatcherPriority.Background) + return DefaultIdle + 1; + if (prio == DispatcherPriority.ContextIdle) + return DefaultIdle + 2; + if (prio == DispatcherPriority.ApplicationIdle) + return DefaultIdle + 3; + if (prio == DispatcherPriority.SystemIdle) + return DefaultIdle + 4; + throw new ArgumentException("Unknown priority"); + + } + } +} diff --git a/src/Gtk/Avalonia.Gtk3/Interop/GlibTimeout.cs b/src/Gtk/Avalonia.Gtk3/Interop/GlibTimeout.cs index 9971d8881d..be886ea1c7 100644 --- a/src/Gtk/Avalonia.Gtk3/Interop/GlibTimeout.cs +++ b/src/Gtk/Avalonia.Gtk3/Interop/GlibTimeout.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; +using Avalonia.Threading; namespace Avalonia.Gtk3.Interop { @@ -30,10 +31,11 @@ namespace Avalonia.Gtk3.Interop } - public static void Add(uint interval, Func callback) + public static void Add(int priority, uint interval, Func callback) { var handle = GCHandle.Alloc(callback); - Native.GTimeoutAdd(interval, PinnedHandler, GCHandle.ToIntPtr(handle)); + //Native.GTimeoutAdd(interval, PinnedHandler, GCHandle.ToIntPtr(handle)); + Native.GTimeoutAddFull(priority, interval, PinnedHandler, GCHandle.ToIntPtr(handle), IntPtr.Zero); } class Timer : IDisposable @@ -48,8 +50,10 @@ namespace Avalonia.Gtk3.Interop public static IDisposable StarTimer(uint interval, Action tick) { + if (interval == 0) + throw new ArgumentException("Don't know how to create a timer with zero or negative interval"); var timer = new Timer (); - GlibTimeout.Add(interval, + GlibTimeout.Add(GlibPriority.FromDispatcherPriority(DispatcherPriority.Background), interval, () => { if (timer.Stopped) diff --git a/src/Gtk/Avalonia.Gtk3/Interop/Native.cs b/src/Gtk/Avalonia.Gtk3/Interop/Native.cs index ffc1d380a3..c96fb23366 100644 --- a/src/Gtk/Avalonia.Gtk3/Interop/Native.cs +++ b/src/Gtk/Avalonia.Gtk3/Interop/Native.cs @@ -20,6 +20,27 @@ namespace Avalonia.Gtk3.Interop { public static class D { + [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)] + public delegate gint16 gdk_display_get_n_screens(IntPtr display); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)] + public delegate UnownedGdkScreen gdk_display_get_screen(IntPtr display, gint16 num); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)] + public delegate UnownedGdkScreen gdk_display_get_default_screen (IntPtr display); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)] + public delegate gint16 gdk_screen_get_n_monitors(GdkScreen screen); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)] + public delegate gint16 gdk_screen_get_primary_monitor(GdkScreen screen); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)] + public delegate void gdk_screen_get_monitor_geometry(GdkScreen screen, gint16 num, ref GdkRectangle rect); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)] + public delegate void gdk_screen_get_monitor_workarea(GdkScreen screen, gint16 num, ref GdkRectangle rect); + [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)] public delegate IntPtr gtk_application_new(Utf8Buffer appId, int flags); @@ -148,24 +169,48 @@ namespace Avalonia.Gtk3.Interop [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)] public delegate void cairo_surface_mark_dirty(CairoSurface surface); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)] + public delegate void cairo_surface_write_to_png(CairoSurface surface, Utf8Buffer path); [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)] public delegate void cairo_surface_flush(CairoSurface surface); [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)] public delegate void cairo_surface_destroy(IntPtr surface); - + [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)] public delegate void cairo_set_source_surface(IntPtr cr, CairoSurface surface, double x, double y); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)] + public delegate void cairo_set_source_rgba(IntPtr cr, double r, double g, double b, double a); [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)] public delegate void cairo_scale(IntPtr context, double sx, double sy); [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)] public delegate void cairo_paint(IntPtr context); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)] + public delegate void cairo_show_text(IntPtr context, Utf8Buffer text); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)] + public delegate void cairo_set_font_size(IntPtr context, double size); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)] + public delegate void cairo_select_font_face(IntPtr context, Utf8Buffer face, int slant, int weight); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)] + public delegate void cairo_move_to(IntPtr context, double x, double y); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)] + public delegate void cairo_destroy(IntPtr context); [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)] public delegate void gtk_widget_queue_draw_area(GtkWidget widget, int x, int y, int width, int height); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)] + public delegate void gtk_widget_add_tick_callback(GtkWidget widget, TickCallback callback, IntPtr userData, IntPtr destroy); [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)] public delegate GtkImContext gtk_im_multicontext_new(); @@ -191,17 +236,17 @@ namespace Avalonia.Gtk3.Interop [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)] public delegate GdkWindowState gdk_window_get_state(IntPtr window); - [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)] - public delegate void gdk_window_iconify(IntPtr window); + [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)] + public delegate void gtk_window_iconify(GtkWindow window); - [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)] - public delegate void gdk_window_deiconify(IntPtr window); + [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)] + public delegate void gtk_window_deiconify(GtkWindow window); - [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)] - public delegate void gdk_window_maximize(IntPtr window); + [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)] + public delegate void gtk_window_maximize(GtkWindow window); - [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)] - public delegate void gdk_window_unmaximize(IntPtr window); + [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)] + public delegate void gtk_window_unmaximize(GtkWindow window); [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)] public delegate void gtk_window_set_geometry_hints(GtkWindow window, IntPtr geometry_widget, ref GdkGeometry geometry, GdkWindowHints geom_mask); @@ -215,6 +260,15 @@ namespace Avalonia.Gtk3.Interop [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)] public delegate void gdk_window_begin_resize_drag(IntPtr window, WindowEdge edge, gint button, gint root_x, gint root_y, guint32 timestamp); + [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)] + public delegate void gdk_window_process_updates(IntPtr window, bool updateChildren); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)] + public delegate void gdk_window_begin_paint_rect(IntPtr window, ref GdkRectangle rect); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)] + public delegate void gdk_window_end_paint(IntPtr window); + [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)] public delegate void gdk_event_request_motions(IntPtr ev); @@ -252,6 +306,9 @@ namespace Avalonia.Gtk3.Interop public delegate bool gdk_pixbuf_save_to_bufferv(Pixbuf pixbuf, out IntPtr buffer, out IntPtr buffer_size, Utf8Buffer type, IntPtr option_keys, IntPtr option_values, out IntPtr error); + [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)] + public delegate IntPtr gdk_cairo_create(IntPtr window); + [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gobject)] public delegate void g_object_unref(IntPtr instance); @@ -266,7 +323,10 @@ namespace Avalonia.Gtk3.Interop [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Glib)] public delegate ulong g_timeout_add(uint interval, timeout_callback callback, IntPtr data); - + + [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Glib)] + public delegate ulong g_timeout_add_full(int prio, uint interval, timeout_callback callback, IntPtr data, IntPtr destroy); + [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Glib)] public delegate ulong g_free(IntPtr data); @@ -288,6 +348,9 @@ namespace Avalonia.Gtk3.Interop [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate bool signal_onevent(IntPtr gtkWidget, IntPtr ev, IntPtr userData); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void monitors_changed(IntPtr screen, IntPtr userData); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate bool signal_commit(IntPtr gtkWidget, IntPtr utf8string, IntPtr userData); @@ -296,9 +359,20 @@ namespace Avalonia.Gtk3.Interop [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void GtkClipboardTextReceivedFunc(IntPtr clipboard, IntPtr utf8string, IntPtr userdata); - } + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate bool TickCallback(IntPtr widget, IntPtr clock, IntPtr userdata); + + + } + public static D.gdk_display_get_n_screens GdkDisplayGetNScreens; + public static D.gdk_display_get_screen GdkDisplayGetScreen; + public static D.gdk_display_get_default_screen GdkDisplayGetDefaultScreen; + public static D.gdk_screen_get_n_monitors GdkScreenGetNMonitors; + public static D.gdk_screen_get_primary_monitor GdkScreenGetPrimaryMonitor; + public static D.gdk_screen_get_monitor_geometry GdkScreenGetMonitorGeometry; + public static D.gdk_screen_get_monitor_workarea GdkScreenGetMonitorWorkarea; public static D.gtk_window_set_decorated GtkWindowSetDecorated; public static D.gtk_window_set_skip_taskbar_hint GtkWindowSetSkipTaskbarHint; public static D.gtk_window_get_skip_taskbar_hint GtkWindowGetSkipTaskbarHint; @@ -336,6 +410,7 @@ namespace Avalonia.Gtk3.Interop public static D.g_signal_connect_object GSignalConnectObject; public static D.g_signal_handler_disconnect GSignalHandlerDisconnect; public static D.g_timeout_add GTimeoutAdd; + public static D.g_timeout_add_full GTimeoutAddFull; public static D.g_free GFree; public static D.g_slist_free GSlistFree; public static D.g_memory_input_stream_new_from_data GMemoryInputStreamNewFromData; @@ -343,6 +418,7 @@ namespace Avalonia.Gtk3.Interop public static D.gtk_widget_set_events GtkWidgetSetEvents; public static D.gdk_window_invalidate_rect GdkWindowInvalidateRect; public static D.gtk_widget_queue_draw_area GtkWidgetQueueDrawArea; + public static D.gtk_widget_add_tick_callback GtkWidgetAddTickCallback; public static D.gtk_widget_activate GtkWidgetActivate; public static D.gtk_clipboard_get_for_display GtkClipboardGetForDisplay; public static D.gtk_clipboard_request_text GtkClipboardRequestText; @@ -361,13 +437,17 @@ namespace Avalonia.Gtk3.Interop public static D.gdk_window_get_origin GdkWindowGetOrigin; public static D.gdk_window_get_pointer GdkWindowGetPointer; public static D.gdk_window_get_state GdkWindowGetState; - public static D.gdk_window_iconify GdkWindowIconify; - public static D.gdk_window_deiconify GdkWindowDeiconify; - public static D.gdk_window_maximize GdkWindowMaximize; - public static D.gdk_window_unmaximize GdkWindowUnmaximize; + public static D.gtk_window_iconify GtkWindowIconify; + public static D.gtk_window_deiconify GtkWindowDeiconify; + public static D.gtk_window_maximize GtkWindowMaximize; + public static D.gtk_window_unmaximize GtkWindowUnmaximize; public static D.gdk_window_begin_move_drag GdkWindowBeginMoveDrag; public static D.gdk_window_begin_resize_drag GdkWindowBeginResizeDrag; public static D.gdk_event_request_motions GdkEventRequestMotions; + public static D.gdk_window_process_updates GdkWindowProcessUpdates; + public static D.gdk_window_begin_paint_rect GdkWindowBeginPaintRect; + public static D.gdk_window_end_paint GdkWindowEndPaint; + public static D.gdk_pixbuf_new_from_file GdkPixbufNewFromFile; public static D.gtk_icon_theme_get_default GtkIconThemeGetDefault; @@ -376,16 +456,24 @@ namespace Avalonia.Gtk3.Interop public static D.gdk_window_set_cursor GdkWindowSetCursor; public static D.gdk_pixbuf_new_from_stream GdkPixbufNewFromStream; public static D.gdk_pixbuf_save_to_bufferv GdkPixbufSaveToBufferv; - + public static D.gdk_cairo_create GdkCairoCreate; + public static D.cairo_image_surface_create CairoImageSurfaceCreate; public static D.cairo_image_surface_get_data CairoImageSurfaceGetData; public static D.cairo_image_surface_get_stride CairoImageSurfaceGetStride; public static D.cairo_surface_mark_dirty CairoSurfaceMarkDirty; + public static D.cairo_surface_write_to_png CairoSurfaceWriteToPng; public static D.cairo_surface_flush CairoSurfaceFlush; public static D.cairo_surface_destroy CairoSurfaceDestroy; public static D.cairo_set_source_surface CairoSetSourceSurface; + public static D.cairo_set_source_rgba CairoSetSourceRgba; public static D.cairo_scale CairoScale; public static D.cairo_paint CairoPaint; + public static D.cairo_show_text CairoShowText; + public static D.cairo_select_font_face CairoSelectFontFace; + public static D.cairo_set_font_size CairoSetFontSize; + public static D.cairo_move_to CairoMoveTo; + public static D.cairo_destroy CairoDestroy; } public enum GtkWindowType diff --git a/src/Gtk/Avalonia.Gtk3/Interop/Resolver.cs b/src/Gtk/Avalonia.Gtk3/Interop/Resolver.cs index 764cbfd6b6..31625e3f27 100644 --- a/src/Gtk/Avalonia.Gtk3/Interop/Resolver.cs +++ b/src/Gtk/Avalonia.Gtk3/Interop/Resolver.cs @@ -140,13 +140,11 @@ namespace Avalonia.Gtk3.Interop var nativeHandleNames = new[] { "gdk_win32_window_get_handle", "gdk_x11_window_get_xid", "gdk_quartz_window_get_nswindow" }; foreach (var name in nativeHandleNames) { - try - { - Native.GetNativeGdkWindowHandle = (Native.D.gdk_get_native_handle)Marshal - .GetDelegateForFunctionPointer(loader.GetProcAddress(dlls[GtkDll.Gdk], name, false), typeof(Native.D.gdk_get_native_handle)); - break; - } - catch { } + var ptr = loader.GetProcAddress(dlls[GtkDll.Gdk], name, true); + if (ptr == IntPtr.Zero) + continue; + Native.GetNativeGdkWindowHandle = (Native.D.gdk_get_native_handle) Marshal + .GetDelegateForFunctionPointer(ptr, typeof(Native.D.gdk_get_native_handle)); } if (Native.GetNativeGdkWindowHandle == null) throw new Exception($"Unable to locate any of [{string.Join(", ", nativeHandleNames)}] in libgdk"); diff --git a/src/Gtk/Avalonia.Gtk/KeyTransform.cs b/src/Gtk/Avalonia.Gtk3/KeyTransform.cs similarity index 99% rename from src/Gtk/Avalonia.Gtk/KeyTransform.cs rename to src/Gtk/Avalonia.Gtk3/KeyTransform.cs index 77de8d18a3..de3a4766a1 100644 --- a/src/Gtk/Avalonia.Gtk/KeyTransform.cs +++ b/src/Gtk/Avalonia.Gtk3/KeyTransform.cs @@ -4,11 +4,8 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using Avalonia.Input; -#if GTK3_PINVOKE using Avalonia.Gtk3; -#else -using GdkKey = Gdk.Key; -#endif + namespace Avalonia.Gtk.Common { static class KeyTransform diff --git a/src/Gtk/Avalonia.Gtk3/ScreenImpl.cs b/src/Gtk/Avalonia.Gtk3/ScreenImpl.cs new file mode 100644 index 0000000000..786c9a2cf0 --- /dev/null +++ b/src/Gtk/Avalonia.Gtk3/ScreenImpl.cs @@ -0,0 +1,57 @@ +using System; +using Avalonia.Controls; +using Avalonia.Gtk3.Interop; +using Avalonia.Platform; +using Avalonia.Utilities; + +namespace Avalonia.Gtk3 +{ + internal class ScreenImpl : IScreenImpl + { + public int ScreenCount + { + get => AllScreens.Length; + } + + private Screen[] _allScreens; + public Screen[] AllScreens + { + get + { + if (_allScreens == null) + { + IntPtr display = Native.GdkGetDefaultDisplay(); + GdkScreen screen = Native.GdkDisplayGetDefaultScreen(display); + short primary = Native.GdkScreenGetPrimaryMonitor(screen); + Screen[] screens = new Screen[Native.GdkScreenGetNMonitors(screen)]; + for (short i = 0; i < screens.Length; i++) + { + GdkRectangle workArea = new GdkRectangle(), geometry = new GdkRectangle(); + Native.GdkScreenGetMonitorGeometry(screen, i, ref geometry); + Native.GdkScreenGetMonitorWorkarea(screen, i, ref workArea); + Rect workAreaRect = new Rect(workArea.X, workArea.Y, workArea.Width, workArea.Height); + Rect geometryRect = new Rect(geometry.X, geometry.Y, geometry.Width, geometry.Height); + GtkScreen s = new GtkScreen(geometryRect, workAreaRect, i == primary, i); + screens[i] = s; + } + + _allScreens = screens; + } + + return _allScreens; + } + } + + public ScreenImpl() + { + IntPtr display = Native.GdkGetDefaultDisplay(); + GdkScreen screen = Native.GdkDisplayGetDefaultScreen(display); + Signal.Connect(screen, "monitors-changed", MonitorsChanged); + } + + private unsafe void MonitorsChanged(IntPtr screen, IntPtr userData) + { + _allScreens = null; + } + } +} \ No newline at end of file diff --git a/src/Gtk/Avalonia.Gtk3/WindowBaseImpl.cs b/src/Gtk/Avalonia.Gtk3/WindowBaseImpl.cs index 4464059efb..bfec3db756 100644 --- a/src/Gtk/Avalonia.Gtk3/WindowBaseImpl.cs +++ b/src/Gtk/Avalonia.Gtk3/WindowBaseImpl.cs @@ -10,6 +10,7 @@ using Avalonia.Input; using Avalonia.Input.Raw; using Avalonia.Platform; using Avalonia.Rendering; +using Avalonia.Threading; namespace Avalonia.Gtk3 { @@ -25,6 +26,9 @@ namespace Avalonia.Gtk3 private double _lastScaling; private uint _lastKbdEvent; private uint _lastSmoothScrollEvent; + private GCHandle _gcHandle; + private object _lock = new object(); + private IDeferredRenderOperation _nextRenderOperation; public WindowBaseImpl(GtkWindow gtkWidget) { @@ -50,11 +54,20 @@ namespace Avalonia.Gtk3 Connect("destroy", OnDestroy); Native.GtkWidgetRealize(gtkWidget); _lastSize = ClientSize; + if (Gtk3Platform.UseDeferredRendering) + { + Native.GtkWidgetSetDoubleBuffered(gtkWidget, false); + _gcHandle = GCHandle.Alloc(this); + Native.GtkWidgetAddTickCallback(GtkWidget, PinnedStaticCallback, GCHandle.ToIntPtr(_gcHandle), IntPtr.Zero); + + } } private bool OnConfigured(IntPtr gtkwidget, IntPtr ev, IntPtr userdata) { - var size = ClientSize; + int w, h; + Native.GtkWindowGetSize(GtkWidget, out w, out h); + var size = ClientSize = new Size(w, h); if (_lastSize != size) { Resized?.Invoke(size); @@ -120,7 +133,7 @@ namespace Avalonia.Gtk3 ? RawMouseEventType.LeftButtonDown : evnt->button == 3 ? RawMouseEventType.RightButtonDown : RawMouseEventType.MiddleButtonDown, new Point(evnt->x, evnt->y), GetModifierKeys(evnt->state)); - Input?.Invoke(e); + OnInput(e); return true; } @@ -148,7 +161,7 @@ namespace Avalonia.Gtk3 _inputRoot, RawMouseEventType.Move, position, GetModifierKeys(evnt->state)); - Input(e); + OnInput(e); return true; } @@ -177,7 +190,7 @@ namespace Avalonia.Gtk3 } var e = new RawMouseWheelEventArgs(Gtk3Platform.Mouse, evnt->time, _inputRoot, new Point(evnt->x, evnt->y), delta, GetModifierKeys(evnt->state)); - Input(e); + OnInput(e); return true; } @@ -192,7 +205,7 @@ namespace Avalonia.Gtk3 evnt->time, evnt->type == GdkEventType.KeyPress ? RawKeyEventType.KeyDown : RawKeyEventType.KeyUp, Avalonia.Gtk.Common.KeyTransform.ConvertKey((GdkKey)evnt->keyval), GetModifierKeys((GdkModifierType)evnt->state)); - Input(e); + OnInput(e); return true; } @@ -200,7 +213,7 @@ namespace Avalonia.Gtk3 { var evnt = (GdkEventCrossing*) pev; var position = new Point(evnt->x, evnt->y); - Input(new RawMouseEventArgs(Gtk3Platform.Mouse, + OnInput(new RawMouseEventArgs(Gtk3Platform.Mouse, evnt->time, _inputRoot, RawMouseEventType.Move, @@ -210,7 +223,7 @@ namespace Avalonia.Gtk3 private unsafe bool OnCommit(IntPtr gtkwidget, IntPtr utf8string, IntPtr userdata) { - Input(new RawTextInputEventArgs(Gtk3Platform.Keyboard, _lastKbdEvent, Utf8Buffer.StringFromPtr(utf8string))); + OnInput(new RawTextInputEventArgs(Gtk3Platform.Keyboard, _lastKbdEvent, Utf8Buffer.StringFromPtr(utf8string))); return true; } @@ -222,12 +235,52 @@ namespace Avalonia.Gtk3 private bool OnDraw(IntPtr gtkwidget, IntPtr cairocontext, IntPtr userdata) { - CurrentCairoContext = cairocontext; - Paint?.Invoke(new Rect(ClientSize)); - CurrentCairoContext = IntPtr.Zero; + if (!Gtk3Platform.UseDeferredRendering) + { + CurrentCairoContext = cairocontext; + Paint?.Invoke(new Rect(ClientSize)); + CurrentCairoContext = IntPtr.Zero; + } + return true; + } + + private static Native.D.TickCallback PinnedStaticCallback = StaticTickCallback; + + static bool StaticTickCallback(IntPtr widget, IntPtr clock, IntPtr userData) + { + var impl = (WindowBaseImpl) GCHandle.FromIntPtr(userData).Target; + impl.OnRenderTick(); return true; } + public void SetNextRenderOperation(IDeferredRenderOperation op) + { + lock (_lock) + { + _nextRenderOperation?.Dispose(); + _nextRenderOperation = op; + } + } + + private void OnRenderTick() + { + IDeferredRenderOperation op = null; + lock (_lock) + { + if (_nextRenderOperation != null) + { + op = _nextRenderOperation; + _nextRenderOperation = null; + } + } + if (op != null) + { + op?.RenderNow(); + op?.Dispose(); + } + } + + public void Dispose() { //We are calling it here, since signal handler will be detached @@ -236,6 +289,10 @@ namespace Avalonia.Gtk3 foreach(var d in Disposables.AsEnumerable().Reverse()) d.Dispose(); Disposables.Clear(); + if (_gcHandle.IsAllocated) + { + _gcHandle.Free(); + } } public Size MaxClientSize @@ -249,7 +306,7 @@ namespace Avalonia.Gtk3 public IMouseDevice MouseDevice => Gtk3Platform.Mouse; - public double Scaling => (double) 1 / (Native.GtkWidgetGetScaleFactor?.Invoke(GtkWidget) ?? 1); + public double Scaling => LastKnownScaleFactor = (int) (Native.GtkWidgetGetScaleFactor?.Invoke(GtkWidget) ?? 1); public IPlatformHandle Handle => this; @@ -270,11 +327,17 @@ namespace Avalonia.Gtk3 { if(GtkWidget.IsClosed) return; - Native.GtkWidgetQueueDrawArea(GtkWidget, (int)rect.X, (int)rect.Y, (int)rect.Width, (int)rect.Height); + var s = ClientSize; + Native.GtkWidgetQueueDrawArea(GtkWidget, 0, 0, (int) s.Width, (int) s.Height); } public void SetInputRoot(IInputRoot inputRoot) => _inputRoot = inputRoot; + void OnInput(RawInputEventArgs args) + { + Dispatcher.UIThread.InvokeAsync(() => Input?.Invoke(args), DispatcherPriority.Input); + } + public Point PointToClient(Point point) { int x, y; @@ -323,17 +386,8 @@ namespace Avalonia.Gtk3 } - public Size ClientSize - { - get - { - if (GtkWidget.IsClosed) - return new Size(); - int w, h; - Native.GtkWindowGetSize(GtkWidget, out w, out h); - return new Size(w, h); - } - } + public Size ClientSize { get; private set; } + public int LastKnownScaleFactor { get; private set; } public void Resize(Size value) { @@ -341,6 +395,11 @@ namespace Avalonia.Gtk3 return; Native.GtkWindowResize(GtkWidget, (int)value.Width, (int)value.Height); } + + public IScreenImpl Screen + { + get; + } = new ScreenImpl(); public Point Position { @@ -358,7 +417,10 @@ namespace Avalonia.Gtk3 public IRenderer CreateRenderer(IRenderRoot root) { - return new ImmediateRenderer(root); + var loop = AvaloniaLocator.Current.GetService(); + return Gtk3Platform.UseDeferredRendering + ? (IRenderer) new DeferredRenderer(root, loop) + : new ImmediateRenderer(root); } } } diff --git a/src/Gtk/Avalonia.Gtk3/WindowImpl.cs b/src/Gtk/Avalonia.Gtk3/WindowImpl.cs index e6935c4f20..c586661a7a 100644 --- a/src/Gtk/Avalonia.Gtk3/WindowImpl.cs +++ b/src/Gtk/Avalonia.Gtk3/WindowImpl.cs @@ -1,4 +1,5 @@ using System; +using System.Linq.Expressions; using Avalonia.Controls; using Avalonia.Gtk3.Interop; using Avalonia.Platform; @@ -31,15 +32,14 @@ namespace Avalonia.Gtk3 } set { - var w = Native.GtkWidgetGetWindow(GtkWidget); if (value == WindowState.Minimized) - Native.GdkWindowIconify(w); + Native.GtkWindowIconify(GtkWidget); else if (value == WindowState.Maximized) - Native.GdkWindowMaximize(w); + Native.GtkWindowMaximize(GtkWidget); else { - Native.GdkWindowUnmaximize(w); - Native.GdkWindowDeiconify(w); + Native.GtkWindowUnmaximize(GtkWidget); + Native.GtkWindowDeiconify(GtkWidget); } } } diff --git a/src/Linux/Avalonia.LinuxFramebuffer/PlatformThreadingInterface.cs b/src/Linux/Avalonia.LinuxFramebuffer/PlatformThreadingInterface.cs index 9231649754..3aef6944af 100644 --- a/src/Linux/Avalonia.LinuxFramebuffer/PlatformThreadingInterface.cs +++ b/src/Linux/Avalonia.LinuxFramebuffer/PlatformThreadingInterface.cs @@ -6,6 +6,7 @@ using System.Threading; using System.Threading.Tasks; using Avalonia.Platform; using Avalonia.Rendering; +using Avalonia.Threading; namespace Avalonia.LinuxFramebuffer { @@ -30,7 +31,7 @@ namespace Avalonia.LinuxFramebuffer while (true) { if (0 == WaitHandle.WaitAny(handles)) - Signaled?.Invoke(); + Signaled?.Invoke(null); else { while (true) @@ -97,7 +98,7 @@ namespace Avalonia.LinuxFramebuffer } - public void Signal() + public void Signal(DispatcherPriority prio) { _signaled.Set(); } @@ -105,7 +106,7 @@ namespace Avalonia.LinuxFramebuffer [ThreadStatic] private static bool TlsCurrentThreadIsLoopThread; public bool CurrentThreadIsLoopThread => TlsCurrentThreadIsLoopThread; - public event Action Signaled; + public event Action Signaled; public event EventHandler Tick; } diff --git a/src/OSX/Avalonia.MonoMac/Helpers.cs b/src/OSX/Avalonia.MonoMac/Helpers.cs index b4e3f7e0b7..454b775cc0 100644 --- a/src/OSX/Avalonia.MonoMac/Helpers.cs +++ b/src/OSX/Avalonia.MonoMac/Helpers.cs @@ -1,6 +1,8 @@ using System; + using System.ComponentModel; using MonoMac.AppKit; using MonoMac.CoreGraphics; + using MonoMac.OpenGL; namespace Avalonia.MonoMac { @@ -27,5 +29,14 @@ namespace Avalonia.MonoMac return new CGPoint(pt.X, t - pt.Y); } + public static Rect ConvertRectY(this Rect rect) + { + return new Rect(rect.Position.WithY(rect.Y + rect.Height).ConvertPointY(), rect.Size); + } + + public static CGRect ConvertRectY(this CGRect rect) + { + return new CGRect(new CGPoint(rect.X, rect.Y + rect.Height).ConvertPointY(), rect.Size); + } } } diff --git a/src/OSX/Avalonia.MonoMac/MacScreen.cs b/src/OSX/Avalonia.MonoMac/MacScreen.cs new file mode 100644 index 0000000000..3d5ab0769f --- /dev/null +++ b/src/OSX/Avalonia.MonoMac/MacScreen.cs @@ -0,0 +1,25 @@ +using System; +using Avalonia.Platform; + +namespace Avalonia.MonoMac +{ + public class MacScreen : Screen + { + private readonly IntPtr handle; + + public MacScreen(Rect bounds, Rect workingArea, bool primary, IntPtr handle) : base(bounds, workingArea, primary) + { + this.handle = handle; + } + + public override int GetHashCode() + { + return (int)handle; + } + + public override bool Equals(object obj) + { + return (obj is MacScreen screen) ? this.handle == screen.handle : base.Equals(obj); + } + } +} \ No newline at end of file diff --git a/src/OSX/Avalonia.MonoMac/MonoMacPlatform.cs b/src/OSX/Avalonia.MonoMac/MonoMacPlatform.cs index 2c9710c05a..0deea7fb44 100644 --- a/src/OSX/Avalonia.MonoMac/MonoMacPlatform.cs +++ b/src/OSX/Avalonia.MonoMac/MonoMacPlatform.cs @@ -14,6 +14,9 @@ namespace Avalonia.MonoMac internal readonly MouseDevice MouseDevice = new MouseDevice(); readonly KeyboardDevice _keyboardDevice = new KeyboardDevice(); internal static NSApplication App; + private static bool s_monoMacInitialized; + private static bool s_showInDock = true; + void DoInitialize() { AvaloniaLocator.CurrentMutable @@ -26,7 +29,7 @@ namespace Avalonia.MonoMac .Bind().ToSingleton() .Bind().ToConstant(PlatformThreadingInterface.Instance); - InitializeCocoaApp(); + InitializeMonoMac(); } public static void Initialize() @@ -36,12 +39,29 @@ namespace Avalonia.MonoMac } - void InitializeCocoaApp() + void InitializeMonoMac() { + if(s_monoMacInitialized) + return; NSApplication.Init(); App = NSApplication.SharedApplication; - App.ActivationPolicy = NSApplicationActivationPolicy.Regular; + UpdateActivationPolicy(); + s_monoMacInitialized = true; + } + static void UpdateActivationPolicy() => App.ActivationPolicy = ShowInDock + ? NSApplicationActivationPolicy.Regular + : NSApplicationActivationPolicy.Accessory; + + public static bool ShowInDock + { + get => s_showInDock; + set + { + s_showInDock = value; + if (s_monoMacInitialized) + UpdateActivationPolicy(); + } } diff --git a/src/OSX/Avalonia.MonoMac/PlatformThreadingInterface.cs b/src/OSX/Avalonia.MonoMac/PlatformThreadingInterface.cs index 5da38bf0de..80c854f5a5 100644 --- a/src/OSX/Avalonia.MonoMac/PlatformThreadingInterface.cs +++ b/src/OSX/Avalonia.MonoMac/PlatformThreadingInterface.cs @@ -1,6 +1,7 @@ using System; using System.Threading; using Avalonia.Platform; +using Avalonia.Threading; using MonoMac.AppKit; using MonoMac.CoreGraphics; using MonoMac.Foundation; @@ -13,12 +14,12 @@ namespace Avalonia.MonoMac public static PlatformThreadingInterface Instance { get; } = new PlatformThreadingInterface(); public bool CurrentThreadIsLoopThread => NSThread.Current.IsMainThread; - public event Action Signaled; + public event Action Signaled; public IDisposable StartTimer(TimeSpan interval, Action tick) => NSTimer.CreateRepeatingScheduledTimer(interval, () => tick()); - public void Signal() + public void Signal(DispatcherPriority prio) { lock (this) { @@ -34,7 +35,7 @@ namespace Avalonia.MonoMac return; _signaled = false; } - Signaled?.Invoke(); + Signaled?.Invoke(null); }); } diff --git a/src/OSX/Avalonia.MonoMac/ScreenImpl.cs b/src/OSX/Avalonia.MonoMac/ScreenImpl.cs new file mode 100644 index 0000000000..bf8545a300 --- /dev/null +++ b/src/OSX/Avalonia.MonoMac/ScreenImpl.cs @@ -0,0 +1,51 @@ +using Avalonia.Controls; +using Avalonia.Platform; +using Avalonia.Utilities; +using MonoMac.AppKit; +using MonoMac.Foundation; + +namespace Avalonia.MonoMac +{ + public class ScreenImpl : IScreenImpl + { + private const string NSApplicationDidChangeScreenParametersNotification = "NSApplicationDidChangeScreenParametersNotification"; + + public int ScreenCount + { + get => NSScreen.Screens.Length; + } + + private Screen[] _allScreens; + public Screen[] AllScreens + { + get + { + if (_allScreens == null) + { + NSScreen[] screens = NSScreen.Screens; + Screen[] s = new Screen[screens.Length]; + NSScreen primary = NSScreen.MainScreen; + for (int i = 0; i < screens.Length; i++) + { + Rect bounds = screens[i].Frame.ToAvaloniaRect().ConvertRectY(); + Rect workArea = screens[i].VisibleFrame.ToAvaloniaRect().ConvertRectY(); + s[i] = new MacScreen(bounds, workArea, i == 0, screens[i].Handle); + } + + _allScreens = s; + } + return _allScreens; + } + } + + public ScreenImpl() + { + NSNotificationCenter.DefaultCenter.AddObserver(NSApplicationDidChangeScreenParametersNotification, MonitorsChanged); + } + + private void MonitorsChanged(NSNotification notification) + { + _allScreens = null; + } + } +} \ No newline at end of file diff --git a/src/OSX/Avalonia.MonoMac/WindowBaseImpl.cs b/src/OSX/Avalonia.MonoMac/WindowBaseImpl.cs index fdb2434698..9ce1756aae 100644 --- a/src/OSX/Avalonia.MonoMac/WindowBaseImpl.cs +++ b/src/OSX/Avalonia.MonoMac/WindowBaseImpl.cs @@ -153,6 +153,11 @@ namespace Avalonia.MonoMac Position = pos; } + public IScreenImpl Screen + { + get; + } = new ScreenImpl(); + public override Point PointToClient(Point point) { var cocoaScreenPoint = point.ToMonoMacPoint().ConvertPointY(); diff --git a/src/Skia/Avalonia.Skia/BitmapImpl.cs b/src/Skia/Avalonia.Skia/BitmapImpl.cs index 9f807b8c1d..ce3efded11 100644 --- a/src/Skia/Avalonia.Skia/BitmapImpl.cs +++ b/src/Skia/Avalonia.Skia/BitmapImpl.cs @@ -48,7 +48,7 @@ namespace Avalonia.Skia public BitmapDrawingContext(SKBitmap bitmap, Vector dpi, IVisualBrushRenderer visualBrushRenderer) : this(CreateSurface(bitmap), dpi, visualBrushRenderer) { - + CanUseLcdRendering = false; } private static SKSurface CreateSurface(SKBitmap bitmap) diff --git a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs index 7a83835b10..eadcc05744 100644 --- a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs +++ b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs @@ -16,7 +16,7 @@ namespace Avalonia.Skia private readonly IDisposable[] _disposables; private readonly IVisualBrushRenderer _visualBrushRenderer; private Stack maskStack = new Stack(); - + protected bool CanUseLcdRendering = true; public SKCanvas Canvas { get; private set; } public DrawingContextImpl( @@ -45,7 +45,7 @@ namespace Avalonia.Skia var s = sourceRect.ToSKRect(); var d = destRect.ToSKRect(); using (var paint = new SKPaint() - { Color = new SKColor(255, 255, 255, (byte)(255 * opacity)) }) + { Color = new SKColor(255, 255, 255, (byte)(255 * opacity * _currentOpacity)) }) { Canvas.DrawBitmap(impl.Bitmap, s, d, paint); } @@ -345,7 +345,7 @@ namespace Avalonia.Skia using (var paint = CreatePaint(foreground, text.Size)) { var textImpl = (FormattedTextImpl)text; - textImpl.Draw(this, Canvas, origin.ToSKPoint(), paint); + textImpl.Draw(this, Canvas, origin.ToSKPoint(), paint, CanUseLcdRendering); } } diff --git a/src/Skia/Avalonia.Skia/FormattedTextImpl.cs b/src/Skia/Avalonia.Skia/FormattedTextImpl.cs index c73e1dbcbe..f727d033cc 100644 --- a/src/Skia/Avalonia.Skia/FormattedTextImpl.cs +++ b/src/Skia/Avalonia.Skia/FormattedTextImpl.cs @@ -171,8 +171,10 @@ namespace Avalonia.Skia } internal void Draw(DrawingContextImpl context, - SKCanvas canvas, SKPoint origin, - DrawingContextImpl.PaintWrapper foreground) + SKCanvas canvas, + SKPoint origin, + DrawingContextImpl.PaintWrapper foreground, + bool canUseLcdRendering) { /* TODO: This originated from Native code, it might be useful for debugging character positions as * we improve the FormattedText support. Will need to port this to C# obviously. Rmove when @@ -206,7 +208,7 @@ namespace Avalonia.Skia SKPaint currentPaint = null; try { - ApplyWrapperTo(ref currentPaint, foreground, ref currd, paint); + ApplyWrapperTo(ref currentPaint, foreground, ref currd, paint, canUseLcdRendering); bool hasCusomFGBrushes = _foregroundBrushes.Any(); for (int c = 0; c < _skiaLines.Count; c++) @@ -243,7 +245,7 @@ namespace Avalonia.Skia subStr = Text.Substring(i, len); - ApplyWrapperTo(ref currentPaint, currentWrapper, ref currd, paint); + ApplyWrapperTo(ref currentPaint, currentWrapper, ref currd, paint, canUseLcdRendering); canvas.DrawText(subStr, currX, origin.Y + line.Top + _lineOffset, paint); @@ -277,12 +279,13 @@ namespace Avalonia.Skia private List _skiaLines; private static void ApplyWrapperTo(ref SKPaint current, DrawingContextImpl.PaintWrapper wrapper, - ref IDisposable curr, SKPaint paint) + ref IDisposable curr, SKPaint paint, bool canUseLcdRendering) { if (current == wrapper.Paint) return; curr?.Dispose(); curr = wrapper.ApplyTo(paint); + paint.LcdRenderText = canUseLcdRendering; } private static bool IsBreakChar(char c) diff --git a/src/Windows/Avalonia.Win32.Interop/Avalonia.Win32.Interop.csproj b/src/Windows/Avalonia.Win32.Interop/Avalonia.Win32.Interop.csproj index 817b753157..368e5986b2 100644 --- a/src/Windows/Avalonia.Win32.Interop/Avalonia.Win32.Interop.csproj +++ b/src/Windows/Avalonia.Win32.Interop/Avalonia.Win32.Interop.csproj @@ -94,10 +94,6 @@ {eb582467-6abb-43a1-b052-e981ba910e3a} Avalonia.Visuals - - {fb05ac90-89ba-4f2f-a924-f37875fb547c} - Avalonia.Cairo - {3e53a01a-b331-47f3-b828-4a5717e77a24} Avalonia.Markup.Xaml diff --git a/src/Windows/Avalonia.Win32/Avalonia.Win32.Shared.projitems b/src/Windows/Avalonia.Win32/Avalonia.Win32.Shared.projitems index 4599a0741e..6f13747cb6 100644 --- a/src/Windows/Avalonia.Win32/Avalonia.Win32.Shared.projitems +++ b/src/Windows/Avalonia.Win32/Avalonia.Win32.Shared.projitems @@ -20,10 +20,12 @@ + + Properties\SharedAssemblyInfo.cs diff --git a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs index 4fed7a34f4..fb4aefbf36 100644 --- a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs +++ b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs @@ -616,6 +616,12 @@ namespace Avalonia.Win32.Interop public const int SizeOf_BITMAPINFOHEADER = 40; + [DllImport("user32.dll")] + public static extern bool EnumDisplayMonitors(IntPtr hdc, IntPtr lprcClip, + MonitorEnumDelegate lpfnEnum, IntPtr dwData); + + public delegate bool MonitorEnumDelegate(IntPtr hMonitor, IntPtr hdcMonitor, ref Rect lprcMonitor, IntPtr dwData); + [DllImport("user32.dll", SetLastError = true)] public static extern IntPtr GetDC(IntPtr hWnd); @@ -903,6 +909,9 @@ namespace Avalonia.Win32.Interop [DllImport("user32.dll")] public static extern IntPtr MonitorFromPoint(POINT pt, MONITOR dwFlags); + [DllImport("user32.dll")] + public static extern IntPtr MonitorFromRect(RECT rect, MONITOR dwFlags); + [DllImport("user32.dll")] public static extern IntPtr MonitorFromWindow(IntPtr hwnd, MONITOR dwFlags); @@ -1021,6 +1030,14 @@ namespace Avalonia.Win32.Interop public int top; public int right; public int bottom; + + public RECT(Rect rect) + { + left = (int)rect.X; + top = (int)rect.Y; + right = (int)(rect.X + rect.Width); + bottom = (int)(rect.Y + rect.Height); + } } public struct TRACKMOUSEEVENT diff --git a/src/Windows/Avalonia.Win32/ScreenImpl.cs b/src/Windows/Avalonia.Win32/ScreenImpl.cs new file mode 100644 index 0000000000..4f4331e461 --- /dev/null +++ b/src/Windows/Avalonia.Win32/ScreenImpl.cs @@ -0,0 +1,64 @@ +// 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.Linq; +using Avalonia.Controls; +using Avalonia.Platform; +using Avalonia.Utilities; +using static Avalonia.Win32.Interop.UnmanagedMethods; + +#if NETSTANDARD +using Win32Exception = Avalonia.Win32.NetStandard.AvaloniaWin32Exception; +#endif + +namespace Avalonia.Win32 +{ + public class ScreenImpl : IScreenImpl + { + public int ScreenCount + { + get => GetSystemMetrics(SystemMetric.SM_CMONITORS); + } + + private Screen[] _allScreens; + public Screen[] AllScreens + { + get + { + if (_allScreens == null) + { + int index = 0; + Screen[] screens = new Screen[ScreenCount]; + EnumDisplayMonitors(IntPtr.Zero, IntPtr.Zero, + (IntPtr monitor, IntPtr hdcMonitor, ref Rect lprcMonitor, IntPtr data) => + { + MONITORINFO monitorInfo = new MONITORINFO(); + if (GetMonitorInfo(monitor, monitorInfo)) + { + RECT bounds = monitorInfo.rcMonitor; + RECT workingArea = monitorInfo.rcWork; + 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); + screens[index] = + new WinScreen(avaloniaBounds, avaloniaWorkArea, monitorInfo.dwFlags == 1, + monitor); + index++; + } + return true; + }, IntPtr.Zero); + _allScreens = screens; + } + return _allScreens; + } + } + + public void InvalidateScreensCache() + { + _allScreens = null; + } + } +} diff --git a/src/Windows/Avalonia.Win32/Win32Platform.cs b/src/Windows/Avalonia.Win32/Win32Platform.cs index d8e9256156..a260efd9b9 100644 --- a/src/Windows/Avalonia.Win32/Win32Platform.cs +++ b/src/Windows/Avalonia.Win32/Win32Platform.cs @@ -15,6 +15,7 @@ using Avalonia.Win32.Input; using Avalonia.Win32.Interop; using Avalonia.Controls; using Avalonia.Rendering; +using Avalonia.Threading; #if NETSTANDARD using Win32Exception = Avalonia.Win32.NetStandard.AvaloniaWin32Exception; #else @@ -137,7 +138,7 @@ namespace Avalonia.Win32 private static readonly int SignalW = unchecked((int) 0xdeadbeaf); private static readonly int SignalL = unchecked((int)0x12345678); - public void Signal() + public void Signal(DispatcherPriority prio) { UnmanagedMethods.PostMessage( _hwnd, @@ -148,14 +149,14 @@ namespace Avalonia.Win32 public bool CurrentThreadIsLoopThread => _uiThread == UnmanagedMethods.GetCurrentThreadId(); - public event Action Signaled; + public event Action Signaled; [SuppressMessage("Microsoft.StyleCop.CSharp.NamingRules", "SA1305:FieldNamesMustNotUseHungarianNotation", Justification = "Using Win32 naming for consistency.")] private IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam) { if (msg == (int) UnmanagedMethods.WindowsMessage.WM_DISPATCH_WORK_ITEM && wParam.ToInt64() == SignalW && lParam.ToInt64() == SignalL) { - Signaled?.Invoke(); + Signaled?.Invoke(null); } return UnmanagedMethods.DefWindowProc(hWnd, msg, wParam, lParam); } diff --git a/src/Windows/Avalonia.Win32/WinScreen.cs b/src/Windows/Avalonia.Win32/WinScreen.cs new file mode 100644 index 0000000000..2f8dcb0f3e --- /dev/null +++ b/src/Windows/Avalonia.Win32/WinScreen.cs @@ -0,0 +1,25 @@ +using System; +using Avalonia.Platform; + +namespace Avalonia.Win32 +{ + public class WinScreen : Screen + { + private readonly IntPtr _hMonitor; + + public WinScreen(Rect bounds, Rect workingArea, bool primary, IntPtr hMonitor) : base(bounds, workingArea, primary) + { + this._hMonitor = hMonitor; + } + + public override int GetHashCode() + { + return (int)_hMonitor; + } + + public override bool Equals(object obj) + { + return (obj is WinScreen screen) ? this._hMonitor == screen._hMonitor : base.Equals(obj); + } + } +} \ No newline at end of file diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 9c13a6d9b8..348468e0e7 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -16,6 +16,7 @@ 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 @@ -103,6 +104,11 @@ namespace Avalonia.Win32 } } + public IScreenImpl Screen + { + get; + } = new ScreenImpl(); + public IRenderer CreateRenderer(IRenderRoot root) { @@ -598,6 +604,10 @@ namespace Avalonia.Win32 case UnmanagedMethods.WindowsMessage.WM_MOVE: PositionChanged?.Invoke(new Point((short)(ToInt32(lParam) & 0xffff), (short)(ToInt32(lParam) >> 16))); return IntPtr.Zero; + + case UnmanagedMethods.WindowsMessage.WM_DISPLAYCHANGE: + (Screen as ScreenImpl)?.InvalidateScreensCache(); + return IntPtr.Zero; } #if USE_MANAGED_DRAG diff --git a/src/iOS/Avalonia.iOS/PlatformThreadingInterface.cs b/src/iOS/Avalonia.iOS/PlatformThreadingInterface.cs index e2e72f4c3c..6d6a5e22ca 100644 --- a/src/iOS/Avalonia.iOS/PlatformThreadingInterface.cs +++ b/src/iOS/Avalonia.iOS/PlatformThreadingInterface.cs @@ -9,6 +9,7 @@ using CoreAnimation; using Foundation; using Avalonia.Platform; using Avalonia.Shared.PlatformSupport; +using Avalonia.Threading; namespace Avalonia.iOS { @@ -18,7 +19,7 @@ namespace Avalonia.iOS public static PlatformThreadingInterface Instance { get; } = new PlatformThreadingInterface(); public bool CurrentThreadIsLoopThread => NSThread.Current.IsMainThread; - public event Action Signaled; + public event Action Signaled; public void RunLoop(CancellationToken cancellationToken) { //Mobile platforms are using external main loop @@ -53,7 +54,7 @@ namespace Avalonia.iOS public IDisposable StartTimer(TimeSpan interval, Action tick) => NSTimer.CreateRepeatingScheduledTimer(interval, _ => tick()); - public void Signal() + public void Signal(DispatcherPriority prio) { lock (this) { @@ -65,7 +66,7 @@ namespace Avalonia.iOS { lock (this) _signaled = false; - Signaled?.Invoke(); + Signaled?.Invoke(null); }); } } diff --git a/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Threading.cs b/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Threading.cs index c4c5414e7f..229a34643d 100644 --- a/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Threading.cs +++ b/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Threading.cs @@ -6,6 +6,7 @@ using System.Reactive.Subjects; using System.Threading; using System.Threading.Tasks; using Avalonia.Platform; +using Avalonia.Threading; using Avalonia.UnitTests; using Xunit; @@ -147,14 +148,14 @@ namespace Avalonia.Base.UnitTests public bool CurrentThreadIsLoopThread { get; set; } - public event Action Signaled; + public event Action Signaled; public void RunLoop(CancellationToken cancellationToken) { throw new NotImplementedException(); } - public void Signal() + public void Signal(DispatcherPriority prio) { throw new NotImplementedException(); } diff --git a/tests/Avalonia.Controls.UnitTests/AppBuilderTests.cs b/tests/Avalonia.Controls.UnitTests/AppBuilderTests.cs index 9de97b41cc..867f740a3a 100644 --- a/tests/Avalonia.Controls.UnitTests/AppBuilderTests.cs +++ b/tests/Avalonia.Controls.UnitTests/AppBuilderTests.cs @@ -99,7 +99,7 @@ namespace Avalonia.Controls.UnitTests } } - [Fact] + [Fact (Skip = "We don't have rendering modules with dependencies right now")] public void LoadsRenderingModuleWithoutDependenciesWhenNoModuleMatches() { using (AvaloniaLocator.EnterScope()) @@ -107,7 +107,7 @@ namespace Avalonia.Controls.UnitTests ResetModuleLoadStates(); var builder = AppBuilder.Configure() .UseWindowingSubsystem(() => { }) - .UseRenderingSubsystem(() => { }, "Cairo"); + .UseRenderingSubsystem(() => { }, "TBD"); builder.UseAvaloniaModules().SetupWithoutStarting(); Assert.True(DefaultRenderingModule.IsLoaded); Assert.False(Direct2DModule.IsLoaded); diff --git a/tests/Avalonia.RenderTests/Avalonia.Cairo.RenderTests.csproj b/tests/Avalonia.RenderTests/Avalonia.Cairo.RenderTests.csproj deleted file mode 100644 index 98256529bc..0000000000 --- a/tests/Avalonia.RenderTests/Avalonia.Cairo.RenderTests.csproj +++ /dev/null @@ -1,105 +0,0 @@ - - - - Debug - AnyCPU - {E106CF37-4066-4615-B684-172A6D30B058} - Library - Properties - Avalonia.Cairo.RenderTests - Avalonia.Cairo.RenderTests - v4.6.1 - 512 - - - - true - full - false - ..\..\artifacts\tests\ - TRACE;DEBUG;AVALONIA_CAIRO - prompt - 4 - - - pdbonly - true - ..\..\artifacts\tests\ - TRACE;AVALONIA_CAIRO - prompt - 4 - - - - - - - - - {FB05AC90-89BA-4F2F-A924-F37875FB547C} - Avalonia.Cairo - - - {D211E587-D8BC-45B9-95A4-F297C8FA5200} - Avalonia.Animation - - - {B09B78D8-9B26-48B0-9149-D64A2F120F3F} - Avalonia.Base - - - {D2221C82-4A25-4583-9B43-D791E3F6820C} - Avalonia.Controls - - - {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 - - - - - - - - - - - - - - False - - - False - - - False - - - False - - - - - - - - - - \ No newline at end of file diff --git a/tests/Avalonia.RenderTests/Avalonia.Direct2D1.RenderTests.csproj b/tests/Avalonia.RenderTests/Avalonia.Direct2D1.RenderTests.csproj index a1c323ceb0..445f8b0368 100644 --- a/tests/Avalonia.RenderTests/Avalonia.Direct2D1.RenderTests.csproj +++ b/tests/Avalonia.RenderTests/Avalonia.Direct2D1.RenderTests.csproj @@ -72,9 +72,6 @@ Avalonia.Styling - - - diff --git a/tests/Avalonia.RenderTests/Avalonia.RenderTests.projitems b/tests/Avalonia.RenderTests/Avalonia.RenderTests.projitems index a3ca0c7493..ff729a6b48 100644 --- a/tests/Avalonia.RenderTests/Avalonia.RenderTests.projitems +++ b/tests/Avalonia.RenderTests/Avalonia.RenderTests.projitems @@ -14,6 +14,7 @@ + diff --git a/tests/Avalonia.RenderTests/Controls/BorderTests.cs b/tests/Avalonia.RenderTests/Controls/BorderTests.cs index ef33ecad8e..3bd5a6e1cb 100644 --- a/tests/Avalonia.RenderTests/Controls/BorderTests.cs +++ b/tests/Avalonia.RenderTests/Controls/BorderTests.cs @@ -7,9 +7,7 @@ using Avalonia.Layout; using Avalonia.Media; using Xunit; -#if AVALONIA_CAIRO -namespace Avalonia.Cairo.RenderTests.Controls -#elif AVALONIA_SKIA +#if AVALONIA_SKIA namespace Avalonia.Skia.RenderTests #else namespace Avalonia.Direct2D1.RenderTests.Controls @@ -149,11 +147,8 @@ namespace Avalonia.Direct2D1.RenderTests.Controls CompareImages(); } -#if AVALONIA_CAIRO - [Fact(Skip = "Font scaling currently broken on cairo")] -#else + [Fact] -#endif public async Task Border_Centers_Content_Horizontally() { Decorator target = new Decorator @@ -180,11 +175,7 @@ namespace Avalonia.Direct2D1.RenderTests.Controls CompareImages(); } -#if AVALONIA_CAIRO - [Fact(Skip = "Font scaling currently broken on cairo")] -#else [Fact] -#endif public async Task Border_Centers_Content_Vertically() { Decorator target = new Decorator @@ -211,11 +202,7 @@ namespace Avalonia.Direct2D1.RenderTests.Controls CompareImages(); } -#if AVALONIA_CAIRO - [Fact(Skip = "Font scaling currently broken on cairo")] -#else [Fact] -#endif public async Task Border_Stretches_Content_Horizontally() { Decorator target = new Decorator @@ -242,11 +229,7 @@ namespace Avalonia.Direct2D1.RenderTests.Controls CompareImages(); } -#if AVALONIA_CAIRO - [Fact(Skip = "Font scaling currently broken on cairo")] -#else [Fact] -#endif public async Task Border_Stretches_Content_Vertically() { Decorator target = new Decorator @@ -273,11 +256,7 @@ namespace Avalonia.Direct2D1.RenderTests.Controls CompareImages(); } -#if AVALONIA_CAIRO - [Fact(Skip = "Font scaling currently broken on cairo")] -#else [Fact] -#endif public async Task Border_Left_Aligns_Content() { Decorator target = new Decorator @@ -304,11 +283,7 @@ namespace Avalonia.Direct2D1.RenderTests.Controls CompareImages(); } -#if AVALONIA_CAIRO - [Fact(Skip = "Font scaling currently broken on cairo")] -#else [Fact] -#endif public async Task Border_Right_Aligns_Content() { Decorator target = new Decorator @@ -335,11 +310,7 @@ namespace Avalonia.Direct2D1.RenderTests.Controls CompareImages(); } -#if AVALONIA_CAIRO - [Fact(Skip = "Font scaling currently broken on cairo")] -#else [Fact] -#endif public async Task Border_Top_Aligns_Content() { Decorator target = new Decorator @@ -366,11 +337,7 @@ namespace Avalonia.Direct2D1.RenderTests.Controls CompareImages(); } -#if AVALONIA_CAIRO - [Fact(Skip = "Font scaling currently broken on cairo")] -#else [Fact] -#endif public async Task Border_Bottom_Aligns_Content() { Decorator target = new Decorator diff --git a/tests/Avalonia.RenderTests/Controls/CustomRenderTests.cs b/tests/Avalonia.RenderTests/Controls/CustomRenderTests.cs index e4630d8265..8356e78cc3 100644 --- a/tests/Avalonia.RenderTests/Controls/CustomRenderTests.cs +++ b/tests/Avalonia.RenderTests/Controls/CustomRenderTests.cs @@ -8,9 +8,7 @@ using Avalonia.Layout; using Avalonia.Media; using Xunit; -#if AVALONIA_CAIRO -namespace Avalonia.Cairo.RenderTests.Controls -#elif AVALONIA_SKIA +#if AVALONIA_SKIA namespace Avalonia.Skia.RenderTests #else namespace Avalonia.Direct2D1.RenderTests.Controls diff --git a/tests/Avalonia.RenderTests/Controls/ImageTests.cs b/tests/Avalonia.RenderTests/Controls/ImageTests.cs index 9c1d3624d1..593593ba3c 100644 --- a/tests/Avalonia.RenderTests/Controls/ImageTests.cs +++ b/tests/Avalonia.RenderTests/Controls/ImageTests.cs @@ -8,9 +8,7 @@ using Avalonia.Media; using Avalonia.Media.Imaging; using Xunit; -#if AVALONIA_CAIRO -namespace Avalonia.Cairo.RenderTests.Controls -#elif AVALONIA_SKIA +#if AVALONIA_SKIA namespace Avalonia.Skia.RenderTests #else namespace Avalonia.Direct2D1.RenderTests.Controls diff --git a/tests/Avalonia.RenderTests/Controls/TextBlockTests.cs b/tests/Avalonia.RenderTests/Controls/TextBlockTests.cs index 5b1d76cd0f..a5d06a1b0e 100644 --- a/tests/Avalonia.RenderTests/Controls/TextBlockTests.cs +++ b/tests/Avalonia.RenderTests/Controls/TextBlockTests.cs @@ -6,9 +6,7 @@ using Avalonia.Layout; using Avalonia.Media; using Xunit; -#if AVALONIA_CAIRO -namespace Avalonia.Cairo.RenderTests.Controls -#elif AVALONIA_SKIA +#if AVALONIA_SKIA namespace Avalonia.Skia.RenderTests #else namespace Avalonia.Direct2D1.RenderTests.Controls diff --git a/tests/Avalonia.RenderTests/GeometryClippingTests.cs b/tests/Avalonia.RenderTests/GeometryClippingTests.cs index a1ce8097bd..01af638e6d 100644 --- a/tests/Avalonia.RenderTests/GeometryClippingTests.cs +++ b/tests/Avalonia.RenderTests/GeometryClippingTests.cs @@ -7,9 +7,7 @@ using System.Text; using Xunit; using System.Threading.Tasks; -#if AVALONIA_CAIRO -namespace Avalonia.Cairo.RenderTests -#elif AVALONIA_SKIA +#if AVALONIA_SKIA namespace Avalonia.Skia.RenderTests #else namespace Avalonia.Direct2D1.RenderTests diff --git a/tests/Avalonia.RenderTests/Media/BitmapTests.cs b/tests/Avalonia.RenderTests/Media/BitmapTests.cs index 33c14fb975..f01f78ae94 100644 --- a/tests/Avalonia.RenderTests/Media/BitmapTests.cs +++ b/tests/Avalonia.RenderTests/Media/BitmapTests.cs @@ -13,9 +13,7 @@ using Avalonia.Media.Imaging; using Avalonia.Platform; using Xunit; -#if AVALONIA_CAIRO -namespace Avalonia.Cairo.RenderTests.Media -#elif AVALONIA_SKIA +#if AVALONIA_SKIA namespace Avalonia.Skia.RenderTests #else namespace Avalonia.Direct2D1.RenderTests.Media @@ -105,11 +103,7 @@ namespace Avalonia.Direct2D1.RenderTests.Media CompareImagesNoRenderer(testName); } -#if AVALONIA_CAIRO - //wontfix -#else [Theory] -#endif [InlineData(PixelFormat.Bgra8888), InlineData(PixelFormat.Rgba8888)] public void WritableBitmapShouldBeUsable(PixelFormat fmt) { diff --git a/tests/Avalonia.RenderTests/Media/FormattedTextImplTests.cs b/tests/Avalonia.RenderTests/Media/FormattedTextImplTests.cs index 4f8aeb93ac..a8f9d42c1e 100644 --- a/tests/Avalonia.RenderTests/Media/FormattedTextImplTests.cs +++ b/tests/Avalonia.RenderTests/Media/FormattedTextImplTests.cs @@ -9,9 +9,7 @@ using System.Linq; using System.Text; using Xunit; -#if AVALONIA_CAIRO -namespace Avalonia.Cairo.RenderTests.Media -#elif AVALONIA_SKIA +#if AVALONIA_SKIA namespace Avalonia.Skia.RenderTests #else @@ -86,11 +84,8 @@ namespace Avalonia.Direct2D1.RenderTests.Media widthConstraint); } -#if AVALONIA_CAIRO - [Theory(Skip = "TODO: Font scaling currently broken on cairo")] -#else + [Theory] -#endif [InlineData("", FontSize, 0, FontSizeHeight)] [InlineData("x", FontSize, 7.20, FontSizeHeight)] [InlineData(stringword, FontSize, 28.80, FontSizeHeight)] @@ -114,12 +109,8 @@ namespace Avalonia.Direct2D1.RenderTests.Media Assert.Equal(expHeight, linesHeight, 2); } - -#if AVALONIA_CAIRO - [Theory(Skip = "TODO: Font scaling currently broken on cairo")] -#else + [Theory] -#endif [InlineData("", 1, -1, TextWrapping.NoWrap)] [InlineData("x", 1, -1, TextWrapping.NoWrap)] [InlineData(stringword, 1, -1, TextWrapping.NoWrap)] @@ -142,12 +133,8 @@ namespace Avalonia.Direct2D1.RenderTests.Media var lines = constrained.GetLines().ToArray(); Assert.Equal(linesCount, lines.Count()); } - -#if AVALONIA_CAIRO - [Theory(Skip = "TODO: Font scaling currently broken on cairo")] -#else + [Theory] -#endif [InlineData("x", 0, 0, true, false, 0)] [InlineData(stringword, -1, -1, false, false, 0)] [InlineData(stringword, 25, 13, true, false, 3)] @@ -181,12 +168,8 @@ namespace Avalonia.Direct2D1.RenderTests.Media Assert.Equal(isInside, htRes.IsInside); Assert.Equal(isTrailing, htRes.IsTrailing); } - -#if AVALONIA_CAIRO - [Theory(Skip = "TODO: Font scaling currently broken on cairo")] -#else + [Theory] -#endif [InlineData("", 0, 0, 0, 0, FontSizeHeight)] [InlineData("x", 0, 0, 0, 7.20, FontSizeHeight)] [InlineData("x", -1, 7.20, 0, 0, FontSizeHeight)] @@ -207,12 +190,8 @@ namespace Avalonia.Direct2D1.RenderTests.Media Assert.Equal(width, r.Width, 2); Assert.Equal(height, r.Height, 2); } - -#if AVALONIA_CAIRO - [Theory(Skip = "TODO: Font scaling currently broken on cairo")] -#else + [Theory] -#endif [InlineData("x", 0, 200, 200 - 7.20, 0, 7.20, FontSizeHeight)] [InlineData(stringword, 0, 200, 171.20, 0, 7.20, FontSizeHeight)] [InlineData(stringword, 3, 200, 200 - 7.20, 0, 7.20, FontSizeHeight)] @@ -230,12 +209,8 @@ namespace Avalonia.Direct2D1.RenderTests.Media Assert.Equal(width, r.Width, 2); Assert.Equal(height, r.Height, 2); } - -#if AVALONIA_CAIRO - [Theory(Skip = "TODO: Font scaling currently broken on cairo")] -#else + [Theory] -#endif [InlineData("x", 0, 200, 100 - 7.20 / 2, 0, 7.20, FontSizeHeight)] [InlineData(stringword, 0, 200, 85.6, 0, 7.20, FontSizeHeight)] [InlineData(stringword, 3, 200, 100 + 7.20, 0, 7.20, FontSizeHeight)] @@ -253,12 +228,8 @@ namespace Avalonia.Direct2D1.RenderTests.Media Assert.Equal(width, r.Width, 2); Assert.Equal(height, r.Height, 2); } - -#if AVALONIA_CAIRO - [Theory(Skip = "TODO: Font scaling currently broken on cairo")] -#else + [Theory] -#endif [InlineData("x", 0, 1, "0,0,7.20,13.59")] [InlineData(stringword, 0, 4, "0,0,28.80,13.59")] [InlineData(stringmiddlenewlines, 10, 10, "0,13.59,57.61,13.59")] diff --git a/tests/Avalonia.RenderTests/Media/ImageBrushTests.cs b/tests/Avalonia.RenderTests/Media/ImageBrushTests.cs index b8f81696b1..6381bceadc 100644 --- a/tests/Avalonia.RenderTests/Media/ImageBrushTests.cs +++ b/tests/Avalonia.RenderTests/Media/ImageBrushTests.cs @@ -9,9 +9,7 @@ using Avalonia.Media; using Avalonia.Media.Imaging; using Xunit; -#if AVALONIA_CAIRO -namespace Avalonia.Cairo.RenderTests.Media -#elif AVALONIA_SKIA +#if AVALONIA_SKIA namespace Avalonia.Skia.RenderTests #else namespace Avalonia.Direct2D1.RenderTests.Media @@ -366,11 +364,8 @@ namespace Avalonia.Direct2D1.RenderTests.Media CompareImages(); } -#if AVALONIA_CAIRO - [Fact(Skip = "TileMode.FlipX not yet supported on cairo")] -#else + [Fact] -#endif public async Task ImageBrush_NoStretch_FlipX_TopLeftDest() { Decorator target = new Decorator @@ -393,12 +388,8 @@ namespace Avalonia.Direct2D1.RenderTests.Media await RenderToFile(target); CompareImages(); } - -#if AVALONIA_CAIRO - [Fact(Skip = "TileMode.FlipY not yet supported on cairo")] -#else + [Fact] -#endif public async Task ImageBrush_NoStretch_FlipY_TopLeftDest() { Decorator target = new Decorator diff --git a/tests/Avalonia.RenderTests/Media/LinearGradientBrushTests.cs b/tests/Avalonia.RenderTests/Media/LinearGradientBrushTests.cs index e7889672b9..062c7d88f5 100644 --- a/tests/Avalonia.RenderTests/Media/LinearGradientBrushTests.cs +++ b/tests/Avalonia.RenderTests/Media/LinearGradientBrushTests.cs @@ -10,9 +10,7 @@ using System.Text; using System.Threading.Tasks; using Xunit; -#if AVALONIA_CAIRO -namespace Avalonia.Cairo.RenderTests.Media -#elif AVALONIA_SKIA +#if AVALONIA_SKIA namespace Avalonia.Skia.RenderTests #else namespace Avalonia.Direct2D1.RenderTests.Media diff --git a/tests/Avalonia.RenderTests/Media/RadialGradientBrushTests.cs b/tests/Avalonia.RenderTests/Media/RadialGradientBrushTests.cs index 383c8ee0f8..b3e214f863 100644 --- a/tests/Avalonia.RenderTests/Media/RadialGradientBrushTests.cs +++ b/tests/Avalonia.RenderTests/Media/RadialGradientBrushTests.cs @@ -10,9 +10,7 @@ using System.Text; using System.Threading.Tasks; using Xunit; -#if AVALONIA_CAIRO -namespace Avalonia.Cairo.RenderTests.Media -#elif AVALONIA_SKIA +#if AVALONIA_SKIA namespace Avalonia.Skia.RenderTests #else namespace Avalonia.Direct2D1.RenderTests.Media diff --git a/tests/Avalonia.RenderTests/Media/VisualBrushTests.cs b/tests/Avalonia.RenderTests/Media/VisualBrushTests.cs index 9ec901535a..60589f6a00 100644 --- a/tests/Avalonia.RenderTests/Media/VisualBrushTests.cs +++ b/tests/Avalonia.RenderTests/Media/VisualBrushTests.cs @@ -9,9 +9,7 @@ using Avalonia.Media; using Avalonia.Media.Imaging; using Xunit; -#if AVALONIA_CAIRO -namespace Avalonia.Cairo.RenderTests.Media -#elif AVALONIA_SKIA +#if AVALONIA_SKIA namespace Avalonia.Skia.RenderTests #else namespace Avalonia.Direct2D1.RenderTests.Media @@ -85,10 +83,8 @@ namespace Avalonia.Direct2D1.RenderTests.Media await RenderToFile(target); CompareImages(); } - -#if AVALONIA_CAIRO - [Fact(Skip = "Font scaling currently broken on cairo")] -#elif AVALONIA_SKIA_SKIP_FAIL + +#if AVALONIA_SKIA_SKIP_FAIL [Fact(Skip = "FIXME")] #else [Fact] @@ -142,9 +138,7 @@ namespace Avalonia.Direct2D1.RenderTests.Media CompareImages(); } -#if AVALONIA_CAIRO - [Fact(Skip = "Font scaling currently broken on cairo")] -#elif AVALONIA_SKIA_SKIP_FAIL +#if AVALONIA_SKIA_SKIP_FAIL [Fact(Skip = "FIXME")] #else [Fact] @@ -171,9 +165,7 @@ namespace Avalonia.Direct2D1.RenderTests.Media CompareImages(); } -#if AVALONIA_CAIRO - [Fact(Skip = "Font scaling currently broken on cairo")] -#elif AVALONIA_SKIA_SKIP_FAIL +#if AVALONIA_SKIA_SKIP_FAIL [Fact(Skip = "FIXME")] #else [Fact] @@ -200,9 +192,7 @@ namespace Avalonia.Direct2D1.RenderTests.Media CompareImages(); } -#if AVALONIA_CAIRO - [Fact(Skip = "Font scaling currently broken on cairo")] -#elif AVALONIA_SKIA_SKIP_FAIL +#if AVALONIA_SKIA_SKIP_FAIL [Fact(Skip = "FIXME")] #else [Fact] @@ -253,9 +243,7 @@ namespace Avalonia.Direct2D1.RenderTests.Media CompareImages(); } -#if AVALONIA_CAIRO - [Fact(Skip = "Font scaling currently broken on cairo")] -#elif AVALONIA_SKIA_SKIP_FAIL +#if AVALONIA_SKIA_SKIP_FAIL [Fact(Skip = "FIXME")] #else [Fact] @@ -337,9 +325,7 @@ namespace Avalonia.Direct2D1.RenderTests.Media CompareImages(); } -#if AVALONIA_CAIRO - [Fact(Skip = "TileMode.FlipX not yet supported on cairo")] -#elif AVALONIA_SKIA_SKIP_FAIL +#if AVALONIA_SKIA_SKIP_FAIL [Fact(Skip = "FIXME")] #else [Fact] @@ -367,9 +353,7 @@ namespace Avalonia.Direct2D1.RenderTests.Media CompareImages(); } -#if AVALONIA_CAIRO - [Fact(Skip = "TileMode.FlipY not yet supported on cairo")] -#elif AVALONIA_SKIA_SKIP_FAIL +#if AVALONIA_SKIA_SKIP_FAIL [Fact(Skip = "FIXME")] #else [Fact] @@ -397,9 +381,7 @@ namespace Avalonia.Direct2D1.RenderTests.Media CompareImages(); } -#if AVALONIA_CAIRO - [Fact(Skip = "Font scaling currently broken on cairo")] -#elif AVALONIA_SKIA_SKIP_FAIL +#if AVALONIA_SKIA_SKIP_FAIL [Fact(Skip = "FIXME")] #else [Fact] @@ -427,9 +409,7 @@ namespace Avalonia.Direct2D1.RenderTests.Media CompareImages(); } -#if AVALONIA_CAIRO - [Fact(Skip = "Font scaling currently broken on cairo")] -#elif AVALONIA_SKIA_SKIP_FAIL +#if AVALONIA_SKIA_SKIP_FAIL [Fact(Skip = "FIXME")] #else [Fact] diff --git a/tests/Avalonia.RenderTests/OpacityMaskTests.cs b/tests/Avalonia.RenderTests/OpacityMaskTests.cs index b49f04f3ee..b53d9a70b1 100644 --- a/tests/Avalonia.RenderTests/OpacityMaskTests.cs +++ b/tests/Avalonia.RenderTests/OpacityMaskTests.cs @@ -7,9 +7,7 @@ using System.Text; using Xunit; using System.Threading.Tasks; -#if AVALONIA_CAIRO -namespace Avalonia.Cairo.RenderTests -#elif AVALONIA_SKIA +#if AVALONIA_SKIA namespace Avalonia.Skia.RenderTests #else namespace Avalonia.Direct2D1.RenderTests diff --git a/tests/Avalonia.RenderTests/SVGPathTests.cs b/tests/Avalonia.RenderTests/SVGPathTests.cs new file mode 100644 index 0000000000..d1ed0ae1cf --- /dev/null +++ b/tests/Avalonia.RenderTests/SVGPathTests.cs @@ -0,0 +1,53 @@ +using Avalonia.Controls; +using Avalonia.Controls.Shapes; +using Avalonia.Media; +using System; +using System.Collections.Generic; +using System.Text; +using Xunit; +using System.Threading.Tasks; + +#if AVALONIA_CAIRO +namespace Avalonia.Cairo.RenderTests +#elif AVALONIA_SKIA +namespace Avalonia.Skia.RenderTests +#else +namespace Avalonia.Direct2D1.RenderTests +#endif +{ + public class SVGPathTests : TestBase + { + public SVGPathTests() + :base("SVGPath") + { + } + + [Fact] + public async Task SVGPath() + { + var target = new Canvas + { + Background = Brushes.Yellow, + Width = 76, + Height = 76, + Children = new Avalonia.Controls.Controls + { + new Path + { + Width = 32, + Height = 40, + [Canvas.LeftProperty] = 23, + [Canvas.TopProperty] = 18, + Stretch = Stretch.Fill, + Fill = Brushes.Black, + //Coffee Maker by Becris from the Noun Project + Data = StreamGeometry.Parse("M5,51v4c0,1.654,1.346,3,3,3h7v3c0,0.552,0.447,1,1,1h8c0.553,0,1-0.448,1-1v-3h18v3c0,0.552,0.447,1,1,1h8 c0.553,0,1-0.448,1-1v-3c2.757,0,5-2.243,5-5V13V7c0-2.757-2.243-5-5-5H11C8.243,2,6,4.243,6,7v2c0,2.757,2.243,5,5,5h1.743 l-2.717,11.775c-0.068,0.297,0.002,0.609,0.192,0.848C10.407,26.861,10.695,27,11,27h4c0.431,0,0.812-0.275,0.948-0.684L18.721,18 h1.499l1.811,7.243C22.142,25.688,22.541,26,23,26h12c0.459,0,0.858-0.312,0.97-0.757L37.78,18h6.658l-3.235,29.11 C41.147,47.618,40.72,48,40.21,48h-4.167c0.873-1.159,1.203-2.622,0.897-4.047L35,34.895v-2.481l2.707-2.707 c0.286-0.286,0.372-0.716,0.217-1.09C37.77,28.244,37.404,28,37,28H22c-0.553,0-1,0.448-1,1v0.719l-2.758-0.689 c-0.443-0.111-0.906,0.094-1.123,0.496l-7,13l1.762,0.948l6.631-12.315L21,31.781v3.115l-1.94,9.057 c-0.306,1.426,0.025,2.889,0.897,4.048H8C6.346,48,5,49.346,5,51z M23,60h-6v-2h6V60z M51,60h-6v-2h6V60z M8,9V7 c0-1.654,1.346-3,3-3h42c1.654,0,3,1.346,3,3v5H46H14h-3C9.346,12,8,10.654,8,9z M34.219,24H23.781l-1.5-6h13.438L34.219,24z M44.66,16H37H21h-3c-0.431,0-0.812,0.275-0.948,0.684L14.279,25h-2.022l2.539-11h30.087l-0.185,1.662L44.66,16z M43.191,47.331 L46.896,14H56v39c0,1.654-1.346,3-3,3h-1h-8H24h-8H8c-0.552,0-1-0.449-1-1v-4c0-0.551,0.448-1,1-1h15.948h8.104h8.158 C41.741,50,43.022,48.853,43.191,47.331z M23,30h11.586l-1.293,1.293C33.105,31.48,33,31.735,33,32v2H23V30z M21.614,46.886 c-0.571-0.708-0.79-1.624-0.6-2.514L22.809,36h10.383l1.794,8.372c0.19,0.89-0.028,1.806-0.6,2.514 C33.813,47.594,32.963,48,32.052,48h-8.104C23.037,48,22.187,47.594,21.614,46.886z") + } + } + }; + + await RenderToFile(target); + CompareImages(); + } + } +} diff --git a/tests/Avalonia.RenderTests/Shapes/EllipseTests.cs b/tests/Avalonia.RenderTests/Shapes/EllipseTests.cs index 9687e817e3..257607d5b5 100644 --- a/tests/Avalonia.RenderTests/Shapes/EllipseTests.cs +++ b/tests/Avalonia.RenderTests/Shapes/EllipseTests.cs @@ -7,9 +7,7 @@ using Avalonia.Controls.Shapes; using Avalonia.Media; using Xunit; -#if AVALONIA_CAIRO -namespace Avalonia.Cairo.RenderTests.Shapes -#elif AVALONIA_SKIA +#if AVALONIA_SKIA namespace Avalonia.Skia.RenderTests #else namespace Avalonia.Direct2D1.RenderTests.Shapes diff --git a/tests/Avalonia.RenderTests/Shapes/LineTests.cs b/tests/Avalonia.RenderTests/Shapes/LineTests.cs index a5897a2948..a30882fb0d 100644 --- a/tests/Avalonia.RenderTests/Shapes/LineTests.cs +++ b/tests/Avalonia.RenderTests/Shapes/LineTests.cs @@ -7,9 +7,7 @@ using Avalonia.Controls.Shapes; using Avalonia.Media; using Xunit; -#if AVALONIA_CAIRO -namespace Avalonia.Cairo.RenderTests.Shapes -#elif AVALONIA_SKIA +#if AVALONIA_SKIA namespace Avalonia.Skia.RenderTests #else namespace Avalonia.Direct2D1.RenderTests.Shapes @@ -21,12 +19,8 @@ namespace Avalonia.Direct2D1.RenderTests.Shapes : base(@"Shapes\Line") { } - -#if !AVALONIA_CAIRO + [Fact] -#else - [Fact(Skip = "Fails on Cairo")] -#endif public async Task Line_1px_Stroke() { Decorator target = new Decorator @@ -45,12 +39,8 @@ namespace Avalonia.Direct2D1.RenderTests.Shapes await RenderToFile(target); CompareImages(); } - -#if !AVALONIA_CAIRO + [Fact] -#else - [Fact(Skip = "Fails on Cairo")] -#endif public async Task Line_1px_Stroke_Reversed() { Decorator target = new Decorator diff --git a/tests/Avalonia.RenderTests/Shapes/PathTests.cs b/tests/Avalonia.RenderTests/Shapes/PathTests.cs index 0fc3246635..9a580794f8 100644 --- a/tests/Avalonia.RenderTests/Shapes/PathTests.cs +++ b/tests/Avalonia.RenderTests/Shapes/PathTests.cs @@ -7,9 +7,7 @@ using Avalonia.Layout; using Avalonia.Media; using Xunit; -#if AVALONIA_CAIRO -namespace Avalonia.Cairo.RenderTests.Shapes -#elif AVALONIA_SKIA +#if AVALONIA_SKIA namespace Avalonia.Skia.RenderTests #else namespace Avalonia.Direct2D1.RenderTests.Shapes @@ -25,11 +23,8 @@ namespace Avalonia.Direct2D1.RenderTests.Shapes { } -#if AVALONIA_CAIRO - [Fact(Skip = "Broken in Cairo: waiting for Skia")] -#else + [Fact] -#endif public async Task Line_Absolute() { Decorator target = new Decorator @@ -49,12 +44,8 @@ namespace Avalonia.Direct2D1.RenderTests.Shapes await RenderToFile(target); CompareImages(); } - -#if AVALONIA_CAIRO - [Fact(Skip = "Broken in Cairo: waiting for Skia")] -#else + [Fact] -#endif public async Task Line_Relative() { Decorator target = new Decorator @@ -74,12 +65,8 @@ namespace Avalonia.Direct2D1.RenderTests.Shapes await RenderToFile(target); CompareImages(); } - -#if AVALONIA_CAIRO - [Fact(Skip = "Broken in Cairo: waiting for Skia")] -#else + [Fact] -#endif public async Task HorizontalLine_Absolute() { Decorator target = new Decorator @@ -99,12 +86,8 @@ namespace Avalonia.Direct2D1.RenderTests.Shapes await RenderToFile(target); CompareImages(); } - -#if AVALONIA_CAIRO - [Fact(Skip = "Broken in Cairo: waiting for Skia")] -#else + [Fact] -#endif public async Task HorizontalLine_Relative() { Decorator target = new Decorator @@ -124,12 +107,8 @@ namespace Avalonia.Direct2D1.RenderTests.Shapes await RenderToFile(target); CompareImages(); } - -#if AVALONIA_CAIRO - [Fact(Skip = "Broken in Cairo: waiting for Skia")] -#else + [Fact] -#endif public async Task VerticalLine_Absolute() { Decorator target = new Decorator @@ -149,12 +128,8 @@ namespace Avalonia.Direct2D1.RenderTests.Shapes await RenderToFile(target); CompareImages(); } - -#if AVALONIA_CAIRO - [Fact(Skip = "Broken in Cairo: waiting for Skia")] -#else + [Fact] -#endif public async Task VerticalLine_Relative() { Decorator target = new Decorator @@ -174,12 +149,8 @@ namespace Avalonia.Direct2D1.RenderTests.Shapes await RenderToFile(target); CompareImages(); } - -#if AVALONIA_CAIRO - [Fact(Skip = "Broken in Cairo: waiting for Skia")] -#else + [Fact] -#endif public async Task CubicBezier_Absolute() { Decorator target = new Decorator @@ -200,12 +171,8 @@ namespace Avalonia.Direct2D1.RenderTests.Shapes await RenderToFile(target); CompareImages(); } - -#if AVALONIA_CAIRO - [Fact(Skip = "Broken in Cairo: waiting for Skia")] -#else + [Fact] -#endif public async Task CubicBezier_Relative() { Decorator target = new Decorator @@ -226,12 +193,8 @@ namespace Avalonia.Direct2D1.RenderTests.Shapes await RenderToFile(target); CompareImages(); } - -#if AVALONIA_CAIRO - [Fact(Skip = "Broken in Cairo: waiting for Skia")] -#else + [Fact] -#endif public async Task Arc_Absolute() { Decorator target = new Decorator @@ -252,12 +215,8 @@ namespace Avalonia.Direct2D1.RenderTests.Shapes await RenderToFile(target); CompareImages(); } - -#if AVALONIA_CAIRO - [Fact(Skip = "Broken in Cairo: waiting for Skia")] -#else + [Fact] -#endif public async Task Arc_Relative() { Decorator target = new Decorator @@ -375,9 +334,7 @@ namespace Avalonia.Direct2D1.RenderTests.Shapes CompareImages(); } -#if AVALONIA_CAIRO - [Fact(Skip = "Path with StrokeDashCap, StrokeStartLineCap, StrokeEndLineCap rendering is not implemented in Cairo yet")] -#elif AVALONIA_SKIA_SKIP_FAIL +#if AVALONIA_SKIA_SKIP_FAIL [Fact(Skip = "FIXME")] #else [Fact] diff --git a/tests/Avalonia.RenderTests/Shapes/PolygonTests.cs b/tests/Avalonia.RenderTests/Shapes/PolygonTests.cs index 415f0b4e85..aae5706810 100644 --- a/tests/Avalonia.RenderTests/Shapes/PolygonTests.cs +++ b/tests/Avalonia.RenderTests/Shapes/PolygonTests.cs @@ -7,9 +7,7 @@ using Avalonia.Controls.Shapes; using Avalonia.Media; using Xunit; -#if AVALONIA_CAIRO -namespace Avalonia.Cairo.RenderTests.Shapes -#elif AVALONIA_SKIA +#if AVALONIA_SKIA namespace Avalonia.Skia.RenderTests #else namespace Avalonia.Direct2D1.RenderTests.Shapes @@ -21,12 +19,8 @@ namespace Avalonia.Direct2D1.RenderTests.Shapes : base(@"Shapes\Polygon") { } - -#if AVALONIA_CAIRO - [Fact(Skip = "Caused by cairo bug")] -#else + [Fact] -#endif public async Task Polygon_1px_Stroke() { Decorator target = new Decorator @@ -48,11 +42,7 @@ namespace Avalonia.Direct2D1.RenderTests.Shapes CompareImages(); } -#if AVALONIA_CAIRO - [Fact(Skip = "Caused by cairo bug")] -#else [Fact] -#endif public async Task Polygon_NonUniformFill() { Decorator target = new Decorator diff --git a/tests/Avalonia.RenderTests/Shapes/PolylineTests.cs b/tests/Avalonia.RenderTests/Shapes/PolylineTests.cs index 684529dd4b..3b586d55ea 100644 --- a/tests/Avalonia.RenderTests/Shapes/PolylineTests.cs +++ b/tests/Avalonia.RenderTests/Shapes/PolylineTests.cs @@ -7,9 +7,7 @@ using Avalonia.Controls.Shapes; using Avalonia.Media; using Xunit; -#if AVALONIA_CAIRO -namespace Avalonia.Cairo.RenderTests.Shapes -#elif AVALONIA_SKIA +#if AVALONIA_SKIA namespace Avalonia.Skia.RenderTests #else namespace Avalonia.Direct2D1.RenderTests.Shapes @@ -22,11 +20,7 @@ namespace Avalonia.Direct2D1.RenderTests.Shapes { } -#if AVALONIA_CAIRO - [Fact(Skip = "Caused by cairo bug")] -#else [Fact] -#endif public async Task Polyline_1px_Stroke() { var polylinePoints = new Point[] { new Point(0, 0), new Point(5, 0), new Point(6, -2), new Point(7, 3), new Point(8, -3), @@ -49,12 +43,8 @@ namespace Avalonia.Direct2D1.RenderTests.Shapes await RenderToFile(target); CompareImages(); } - -#if AVALONIA_CAIRO - [Fact(Skip = "Caused by cairo bug")] -#else + [Fact] -#endif public async Task Polyline_10px_Stroke_PenLineJoin() { var polylinePoints = new Point[] { new Point(0, 0), new Point(5, 0), new Point(6, -2), new Point(7, 3), new Point(8, -3), diff --git a/tests/Avalonia.RenderTests/Shapes/RectangleTests.cs b/tests/Avalonia.RenderTests/Shapes/RectangleTests.cs index 5fa424103f..d48765a360 100644 --- a/tests/Avalonia.RenderTests/Shapes/RectangleTests.cs +++ b/tests/Avalonia.RenderTests/Shapes/RectangleTests.cs @@ -7,9 +7,7 @@ using Avalonia.Controls.Shapes; using Avalonia.Media; using Xunit; -#if AVALONIA_CAIRO -namespace Avalonia.Cairo.RenderTests.Shapes -#elif AVALONIA_SKIA +#if AVALONIA_SKIA namespace Avalonia.Skia.RenderTests #else namespace Avalonia.Direct2D1.RenderTests.Shapes diff --git a/tests/Avalonia.RenderTests/TestBase.cs b/tests/Avalonia.RenderTests/TestBase.cs index 80168c1237..409870ed0f 100644 --- a/tests/Avalonia.RenderTests/TestBase.cs +++ b/tests/Avalonia.RenderTests/TestBase.cs @@ -13,18 +13,14 @@ using Avalonia.Platform; using System.Threading.Tasks; using System; using System.Threading; - -#if AVALONIA_CAIRO -using Avalonia.Cairo; -#elif AVALONIA_SKIA +using Avalonia.Threading; +#if AVALONIA_SKIA using Avalonia.Skia; #else using Avalonia.Direct2D1; #endif -#if AVALONIA_CAIRO -namespace Avalonia.Cairo.RenderTests -#elif AVALONIA_SKIA +#if AVALONIA_SKIA namespace Avalonia.Skia.RenderTests #else namespace Avalonia.Direct2D1.RenderTests @@ -37,9 +33,7 @@ namespace Avalonia.Direct2D1.RenderTests static TestBase() { -#if AVALONIA_CAIRO - CairoPlatform.Initialize(); -#elif AVALONIA_SKIA +#if AVALONIA_SKIA SkiaPlatform.Initialize(); #else Direct2D1Platform.Initialize(); @@ -155,14 +149,14 @@ namespace Avalonia.Direct2D1.RenderTests public Thread MainThread { get; set; } - public event Action Signaled; + public event Action Signaled; public void RunLoop(CancellationToken cancellationToken) { throw new NotImplementedException(); } - public void Signal() + public void Signal(DispatcherPriority prio) { throw new NotImplementedException(); } diff --git a/tests/Avalonia.RenderTests/app.config b/tests/Avalonia.RenderTests/app.config deleted file mode 100644 index 24ccddee3e..0000000000 --- a/tests/Avalonia.RenderTests/app.config +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/tests/TestFiles/Cairo/Controls/Border/Border_1px_Border.expected.png b/tests/TestFiles/Cairo/Controls/Border/Border_1px_Border.expected.png deleted file mode 100644 index 24239d5799..0000000000 Binary files a/tests/TestFiles/Cairo/Controls/Border/Border_1px_Border.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Controls/Border/Border_2px_Border.expected.png b/tests/TestFiles/Cairo/Controls/Border/Border_2px_Border.expected.png deleted file mode 100644 index cebe42f3df..0000000000 Binary files a/tests/TestFiles/Cairo/Controls/Border/Border_2px_Border.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Controls/Border/Border_Bottom_Aligns_Content.expected.png b/tests/TestFiles/Cairo/Controls/Border/Border_Bottom_Aligns_Content.expected.png deleted file mode 100644 index 97ad212701..0000000000 Binary files a/tests/TestFiles/Cairo/Controls/Border/Border_Bottom_Aligns_Content.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Controls/Border/Border_Brush_Offsets_Content.expected.png b/tests/TestFiles/Cairo/Controls/Border/Border_Brush_Offsets_Content.expected.png deleted file mode 100644 index d1c13a9e57..0000000000 Binary files a/tests/TestFiles/Cairo/Controls/Border/Border_Brush_Offsets_Content.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Controls/Border/Border_Centers_Content_Horizontally.expected.png b/tests/TestFiles/Cairo/Controls/Border/Border_Centers_Content_Horizontally.expected.png deleted file mode 100644 index 77a7601e13..0000000000 Binary files a/tests/TestFiles/Cairo/Controls/Border/Border_Centers_Content_Horizontally.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Controls/Border/Border_Centers_Content_Vertically.expected.png b/tests/TestFiles/Cairo/Controls/Border/Border_Centers_Content_Vertically.expected.png deleted file mode 100644 index ff0c7b5984..0000000000 Binary files a/tests/TestFiles/Cairo/Controls/Border/Border_Centers_Content_Vertically.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Controls/Border/Border_Fill.expected.png b/tests/TestFiles/Cairo/Controls/Border/Border_Fill.expected.png deleted file mode 100644 index 8e08d02f66..0000000000 Binary files a/tests/TestFiles/Cairo/Controls/Border/Border_Fill.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Controls/Border/Border_Left_Aligns_Content.expected.png b/tests/TestFiles/Cairo/Controls/Border/Border_Left_Aligns_Content.expected.png deleted file mode 100644 index 5f0166406b..0000000000 Binary files a/tests/TestFiles/Cairo/Controls/Border/Border_Left_Aligns_Content.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Controls/Border/Border_Margin_Offsets_Content.expected.png b/tests/TestFiles/Cairo/Controls/Border/Border_Margin_Offsets_Content.expected.png deleted file mode 100644 index 1fa36969e5..0000000000 Binary files a/tests/TestFiles/Cairo/Controls/Border/Border_Margin_Offsets_Content.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Controls/Border/Border_Nested_Rotate.expected.png b/tests/TestFiles/Cairo/Controls/Border/Border_Nested_Rotate.expected.png deleted file mode 100644 index 54d3bb9cec..0000000000 Binary files a/tests/TestFiles/Cairo/Controls/Border/Border_Nested_Rotate.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Controls/Border/Border_Padding_Offsets_Content.expected.png b/tests/TestFiles/Cairo/Controls/Border/Border_Padding_Offsets_Content.expected.png deleted file mode 100644 index 1fa36969e5..0000000000 Binary files a/tests/TestFiles/Cairo/Controls/Border/Border_Padding_Offsets_Content.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Controls/Border/Border_Right_Aligns_Content.expected.png b/tests/TestFiles/Cairo/Controls/Border/Border_Right_Aligns_Content.expected.png deleted file mode 100644 index 3ee5e25b7c..0000000000 Binary files a/tests/TestFiles/Cairo/Controls/Border/Border_Right_Aligns_Content.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Controls/Border/Border_Stretches_Content_Horizontally.expected.png b/tests/TestFiles/Cairo/Controls/Border/Border_Stretches_Content_Horizontally.expected.png deleted file mode 100644 index e255633894..0000000000 Binary files a/tests/TestFiles/Cairo/Controls/Border/Border_Stretches_Content_Horizontally.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Controls/Border/Border_Stretches_Content_Vertically.expected.png b/tests/TestFiles/Cairo/Controls/Border/Border_Stretches_Content_Vertically.expected.png deleted file mode 100644 index e255633894..0000000000 Binary files a/tests/TestFiles/Cairo/Controls/Border/Border_Stretches_Content_Vertically.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Controls/Border/Border_Top_Aligns_Content.expected.png b/tests/TestFiles/Cairo/Controls/Border/Border_Top_Aligns_Content.expected.png deleted file mode 100644 index ca04ee9121..0000000000 Binary files a/tests/TestFiles/Cairo/Controls/Border/Border_Top_Aligns_Content.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Controls/CustomRender/Clip.expected.png b/tests/TestFiles/Cairo/Controls/CustomRender/Clip.expected.png deleted file mode 100644 index c64045d17e..0000000000 Binary files a/tests/TestFiles/Cairo/Controls/CustomRender/Clip.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Controls/CustomRender/GeometryClip.expected.png b/tests/TestFiles/Cairo/Controls/CustomRender/GeometryClip.expected.png deleted file mode 100644 index bb39bf62ca..0000000000 Binary files a/tests/TestFiles/Cairo/Controls/CustomRender/GeometryClip.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Controls/CustomRender/Opacity.expected.png b/tests/TestFiles/Cairo/Controls/CustomRender/Opacity.expected.png deleted file mode 100644 index 66d12819f4..0000000000 Binary files a/tests/TestFiles/Cairo/Controls/CustomRender/Opacity.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Controls/CustomRender/OpacityMask.expected.png b/tests/TestFiles/Cairo/Controls/CustomRender/OpacityMask.expected.png deleted file mode 100644 index 212a4f1eaa..0000000000 Binary files a/tests/TestFiles/Cairo/Controls/CustomRender/OpacityMask.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Controls/Image/Image_Stretch_Fill.expected.png b/tests/TestFiles/Cairo/Controls/Image/Image_Stretch_Fill.expected.png deleted file mode 100644 index 2980a94b70..0000000000 Binary files a/tests/TestFiles/Cairo/Controls/Image/Image_Stretch_Fill.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Controls/Image/Image_Stretch_None.expected.png b/tests/TestFiles/Cairo/Controls/Image/Image_Stretch_None.expected.png deleted file mode 100644 index 58eebe2251..0000000000 Binary files a/tests/TestFiles/Cairo/Controls/Image/Image_Stretch_None.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Controls/Image/Image_Stretch_Uniform.expected.png b/tests/TestFiles/Cairo/Controls/Image/Image_Stretch_Uniform.expected.png deleted file mode 100644 index 588c6515c5..0000000000 Binary files a/tests/TestFiles/Cairo/Controls/Image/Image_Stretch_Uniform.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Controls/Image/Image_Stretch_UniformToFill.expected.png b/tests/TestFiles/Cairo/Controls/Image/Image_Stretch_UniformToFill.expected.png deleted file mode 100644 index 98d421f98c..0000000000 Binary files a/tests/TestFiles/Cairo/Controls/Image/Image_Stretch_UniformToFill.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Controls/Image/test.png b/tests/TestFiles/Cairo/Controls/Image/test.png deleted file mode 100644 index ed4f82f847..0000000000 Binary files a/tests/TestFiles/Cairo/Controls/Image/test.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/GeometryClipping/Geometry_Clip_Clips_Path.expected.png b/tests/TestFiles/Cairo/GeometryClipping/Geometry_Clip_Clips_Path.expected.png deleted file mode 100644 index 1218293ab3..0000000000 Binary files a/tests/TestFiles/Cairo/GeometryClipping/Geometry_Clip_Clips_Path.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_Fill_NoTile.expected.png b/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_Fill_NoTile.expected.png deleted file mode 100644 index 73d147bf77..0000000000 Binary files a/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_Fill_NoTile.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_FlipXY_TopLeftDest.expected.png b/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_FlipXY_TopLeftDest.expected.png deleted file mode 100644 index f99f56ec14..0000000000 Binary files a/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_FlipXY_TopLeftDest.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_FlipX_TopLeftDest.expected.png b/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_FlipX_TopLeftDest.expected.png deleted file mode 100644 index 4d89f995c4..0000000000 Binary files a/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_FlipX_TopLeftDest.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_FlipY_TopLeftDest.expected.png b/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_FlipY_TopLeftDest.expected.png deleted file mode 100644 index 75c53f0c28..0000000000 Binary files a/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_FlipY_TopLeftDest.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_NoTile_Alignment_BottomRight.expected.png b/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_NoTile_Alignment_BottomRight.expected.png deleted file mode 100644 index a13b34ba2d..0000000000 Binary files a/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_NoTile_Alignment_BottomRight.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_NoTile_Alignment_Center.expected.png b/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_NoTile_Alignment_Center.expected.png deleted file mode 100644 index 14704f751c..0000000000 Binary files a/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_NoTile_Alignment_Center.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_NoTile_Alignment_TopLeft.expected.png b/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_NoTile_Alignment_TopLeft.expected.png deleted file mode 100644 index 7ebac13d30..0000000000 Binary files a/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_NoTile_Alignment_TopLeft.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_NoTile_BottomRightQuarterDest.expected.png b/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_NoTile_BottomRightQuarterDest.expected.png deleted file mode 100644 index dd41cb98c3..0000000000 Binary files a/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_NoTile_BottomRightQuarterDest.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_NoTile_BottomRightQuarterSource.expected.png b/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_NoTile_BottomRightQuarterSource.expected.png deleted file mode 100644 index ab9f2b76e3..0000000000 Binary files a/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_NoTile_BottomRightQuarterSource.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_NoTile_BottomRightQuarterSource_BottomRightQuarterDest.expected.png b/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_NoTile_BottomRightQuarterSource_BottomRightQuarterDest.expected.png deleted file mode 100644 index fea4a2a8e9..0000000000 Binary files a/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_NoTile_BottomRightQuarterSource_BottomRightQuarterDest.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_Tile_BottomRightQuarterSource_CenterQuarterDest.expected.png b/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_Tile_BottomRightQuarterSource_CenterQuarterDest.expected.png deleted file mode 100644 index afd39c2360..0000000000 Binary files a/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_Tile_BottomRightQuarterSource_CenterQuarterDest.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_Tile_Fill.expected.png b/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_Tile_Fill.expected.png deleted file mode 100644 index c38dcfbcfd..0000000000 Binary files a/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_Tile_Fill.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_Tile_Small_Image.expected.png b/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_Tile_Small_Image.expected.png deleted file mode 100644 index 669da6ca1a..0000000000 Binary files a/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_Tile_Small_Image.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_Tile_UniformToFill.expected.png b/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_Tile_UniformToFill.expected.png deleted file mode 100644 index 59e9aea5df..0000000000 Binary files a/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_Tile_UniformToFill.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_UniformToFill_NoTile.expected.png b/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_UniformToFill_NoTile.expected.png deleted file mode 100644 index e173fa6cee..0000000000 Binary files a/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_UniformToFill_NoTile.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_Uniform_NoTile.expected.png b/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_Uniform_NoTile.expected.png deleted file mode 100644 index de73af8170..0000000000 Binary files a/tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_Uniform_NoTile.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Media/ImageBrush/github_icon.png b/tests/TestFiles/Cairo/Media/ImageBrush/github_icon.png deleted file mode 100644 index cd053c5fe1..0000000000 Binary files a/tests/TestFiles/Cairo/Media/ImageBrush/github_icon.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Media/ImageBrush/github_icon_small.png b/tests/TestFiles/Cairo/Media/ImageBrush/github_icon_small.png deleted file mode 100644 index 5799bdfdce..0000000000 Binary files a/tests/TestFiles/Cairo/Media/ImageBrush/github_icon_small.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Media/LinearGradientBrush/LinearGradientBrush_RedBlue_Horizontal_Fill.expected.png b/tests/TestFiles/Cairo/Media/LinearGradientBrush/LinearGradientBrush_RedBlue_Horizontal_Fill.expected.png deleted file mode 100644 index 9d11e8b233..0000000000 Binary files a/tests/TestFiles/Cairo/Media/LinearGradientBrush/LinearGradientBrush_RedBlue_Horizontal_Fill.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Media/LinearGradientBrush/LinearGradientBrush_RedBlue_Vertical_Fill.expected.png b/tests/TestFiles/Cairo/Media/LinearGradientBrush/LinearGradientBrush_RedBlue_Vertical_Fill.expected.png deleted file mode 100644 index d09c0c30b4..0000000000 Binary files a/tests/TestFiles/Cairo/Media/LinearGradientBrush/LinearGradientBrush_RedBlue_Vertical_Fill.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Media/RadialGradientBrush/RadialGradientBrush_RedBlue.expected.png b/tests/TestFiles/Cairo/Media/RadialGradientBrush/RadialGradientBrush_RedBlue.expected.png deleted file mode 100644 index 871a90caf3..0000000000 Binary files a/tests/TestFiles/Cairo/Media/RadialGradientBrush/RadialGradientBrush_RedBlue.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Fill_NoTile.expected.png b/tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Fill_NoTile.expected.png deleted file mode 100644 index 842e541de9..0000000000 Binary files a/tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Fill_NoTile.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_FlipXY_TopLeftDest.expected.png b/tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_FlipXY_TopLeftDest.expected.png deleted file mode 100644 index c719a0328b..0000000000 Binary files a/tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_FlipXY_TopLeftDest.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_FlipX_TopLeftDest.expected.png b/tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_FlipX_TopLeftDest.expected.png deleted file mode 100644 index c64b88dc68..0000000000 Binary files a/tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_FlipX_TopLeftDest.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_FlipY_TopLeftDest.expected.png b/tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_FlipY_TopLeftDest.expected.png deleted file mode 100644 index a6e8b0688c..0000000000 Binary files a/tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_FlipY_TopLeftDest.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_NoTile_Alignment_BottomRight.expected.png b/tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_NoTile_Alignment_BottomRight.expected.png deleted file mode 100644 index a13b34ba2d..0000000000 Binary files a/tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_NoTile_Alignment_BottomRight.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_NoTile_Alignment_Center.expected.png b/tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_NoTile_Alignment_Center.expected.png deleted file mode 100644 index 9150e62edf..0000000000 Binary files a/tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_NoTile_Alignment_Center.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_NoTile_Alignment_TopLeft.expected.png b/tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_NoTile_Alignment_TopLeft.expected.png deleted file mode 100644 index 7ebac13d30..0000000000 Binary files a/tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_NoTile_Alignment_TopLeft.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_NoTile_BottomRightQuarterDest.expected.png b/tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_NoTile_BottomRightQuarterDest.expected.png deleted file mode 100644 index c8ac46f84c..0000000000 Binary files a/tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_NoTile_BottomRightQuarterDest.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_NoTile_BottomRightQuarterSource.expected.png b/tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_NoTile_BottomRightQuarterSource.expected.png deleted file mode 100644 index ab9f2b76e3..0000000000 Binary files a/tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_NoTile_BottomRightQuarterSource.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_NoTile_BottomRightQuarterSource_BottomRightQuarterDest.expected.png b/tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_NoTile_BottomRightQuarterSource_BottomRightQuarterDest.expected.png deleted file mode 100644 index fea4a2a8e9..0000000000 Binary files a/tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_NoTile_BottomRightQuarterSource_BottomRightQuarterDest.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_Tile_BottomRightQuarterSource_CenterQuarterDest.expected.png b/tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_Tile_BottomRightQuarterSource_CenterQuarterDest.expected.png deleted file mode 100644 index afd39c2360..0000000000 Binary files a/tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_Tile_BottomRightQuarterSource_CenterQuarterDest.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_UniformToFill_NoTile.expected.png b/tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_UniformToFill_NoTile.expected.png deleted file mode 100644 index f56ff5f5f6..0000000000 Binary files a/tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_UniformToFill_NoTile.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Uniform_NoTile.expected.png b/tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Uniform_NoTile.expected.png deleted file mode 100644 index d0a982fcd5..0000000000 Binary files a/tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Uniform_NoTile.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Media/VisualBrush/github_icon.png b/tests/TestFiles/Cairo/Media/VisualBrush/github_icon.png deleted file mode 100644 index cd053c5fe1..0000000000 Binary files a/tests/TestFiles/Cairo/Media/VisualBrush/github_icon.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/OpacityMask/Opacity_Mask_Masks_Element.expected.png b/tests/TestFiles/Cairo/OpacityMask/Opacity_Mask_Masks_Element.expected.png deleted file mode 100644 index f57c675b7a..0000000000 Binary files a/tests/TestFiles/Cairo/OpacityMask/Opacity_Mask_Masks_Element.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/SVGPath/SVGPath.expected.png b/tests/TestFiles/Cairo/SVGPath/SVGPath.expected.png new file mode 100644 index 0000000000..9830048810 Binary files /dev/null and b/tests/TestFiles/Cairo/SVGPath/SVGPath.expected.png differ diff --git a/tests/TestFiles/Cairo/Shapes/Ellipse/Circle_1px_Stroke.expected.png b/tests/TestFiles/Cairo/Shapes/Ellipse/Circle_1px_Stroke.expected.png deleted file mode 100644 index e637006545..0000000000 Binary files a/tests/TestFiles/Cairo/Shapes/Ellipse/Circle_1px_Stroke.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Shapes/Line/Line_1px_Stroke.expected.png b/tests/TestFiles/Cairo/Shapes/Line/Line_1px_Stroke.expected.png deleted file mode 100644 index f0a6a9b109..0000000000 Binary files a/tests/TestFiles/Cairo/Shapes/Line/Line_1px_Stroke.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Shapes/Line/Line_1px_Stroke_Reversed.expected.png b/tests/TestFiles/Cairo/Shapes/Line/Line_1px_Stroke_Reversed.expected.png deleted file mode 100644 index 9ed7e713a9..0000000000 Binary files a/tests/TestFiles/Cairo/Shapes/Line/Line_1px_Stroke_Reversed.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Shapes/Line/Line_1px_Stroke_Vertical.expected.png b/tests/TestFiles/Cairo/Shapes/Line/Line_1px_Stroke_Vertical.expected.png deleted file mode 100644 index 845961351c..0000000000 Binary files a/tests/TestFiles/Cairo/Shapes/Line/Line_1px_Stroke_Vertical.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Shapes/Path/Arc_Absolute.expected.png b/tests/TestFiles/Cairo/Shapes/Path/Arc_Absolute.expected.png deleted file mode 100644 index 113cc908e6..0000000000 Binary files a/tests/TestFiles/Cairo/Shapes/Path/Arc_Absolute.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Shapes/Path/Arc_Relative.expected.png b/tests/TestFiles/Cairo/Shapes/Path/Arc_Relative.expected.png deleted file mode 100644 index 113cc908e6..0000000000 Binary files a/tests/TestFiles/Cairo/Shapes/Path/Arc_Relative.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Shapes/Path/CubicBezier_Absolute.expected.png b/tests/TestFiles/Cairo/Shapes/Path/CubicBezier_Absolute.expected.png deleted file mode 100644 index 8c8f5350ee..0000000000 Binary files a/tests/TestFiles/Cairo/Shapes/Path/CubicBezier_Absolute.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Shapes/Path/CubicBezier_Relative.expected.png b/tests/TestFiles/Cairo/Shapes/Path/CubicBezier_Relative.expected.png deleted file mode 100644 index 8c8f5350ee..0000000000 Binary files a/tests/TestFiles/Cairo/Shapes/Path/CubicBezier_Relative.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Shapes/Path/HorizontalLine_Absolute.expected.png b/tests/TestFiles/Cairo/Shapes/Path/HorizontalLine_Absolute.expected.png deleted file mode 100644 index 546ffec3bb..0000000000 Binary files a/tests/TestFiles/Cairo/Shapes/Path/HorizontalLine_Absolute.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Shapes/Path/HorizontalLine_Relative.expected.png b/tests/TestFiles/Cairo/Shapes/Path/HorizontalLine_Relative.expected.png deleted file mode 100644 index 546ffec3bb..0000000000 Binary files a/tests/TestFiles/Cairo/Shapes/Path/HorizontalLine_Relative.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Shapes/Path/Line_Absolute.expected.png b/tests/TestFiles/Cairo/Shapes/Path/Line_Absolute.expected.png deleted file mode 100644 index 4661a6a8c4..0000000000 Binary files a/tests/TestFiles/Cairo/Shapes/Path/Line_Absolute.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Shapes/Path/Path_100px_Triangle_Centered.expected.png b/tests/TestFiles/Cairo/Shapes/Path/Path_100px_Triangle_Centered.expected.png deleted file mode 100644 index dab965f988..0000000000 Binary files a/tests/TestFiles/Cairo/Shapes/Path/Path_100px_Triangle_Centered.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Shapes/Path/Path_Expander_With_Border.expected.png b/tests/TestFiles/Cairo/Shapes/Path/Path_Expander_With_Border.expected.png deleted file mode 100644 index 4a7f4c26b0..0000000000 Binary files a/tests/TestFiles/Cairo/Shapes/Path/Path_Expander_With_Border.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Shapes/Path/Path_Tick_Scaled.expected.png b/tests/TestFiles/Cairo/Shapes/Path/Path_Tick_Scaled.expected.png deleted file mode 100644 index cb4466a21f..0000000000 Binary files a/tests/TestFiles/Cairo/Shapes/Path/Path_Tick_Scaled.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Shapes/Path/Path_Tick_Scaled_Stroke_8px.expected.png b/tests/TestFiles/Cairo/Shapes/Path/Path_Tick_Scaled_Stroke_8px.expected.png deleted file mode 100644 index 355edf84c2..0000000000 Binary files a/tests/TestFiles/Cairo/Shapes/Path/Path_Tick_Scaled_Stroke_8px.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Shapes/Path/VerticalLine_Absolute.expected.png b/tests/TestFiles/Cairo/Shapes/Path/VerticalLine_Absolute.expected.png deleted file mode 100644 index b2e2beafd4..0000000000 Binary files a/tests/TestFiles/Cairo/Shapes/Path/VerticalLine_Absolute.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Shapes/Path/VerticalLine_Relative.expected.png b/tests/TestFiles/Cairo/Shapes/Path/VerticalLine_Relative.expected.png deleted file mode 100644 index ff36de2a5c..0000000000 Binary files a/tests/TestFiles/Cairo/Shapes/Path/VerticalLine_Relative.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Shapes/Polygon/Polygon_1px_Stroke.expected.png b/tests/TestFiles/Cairo/Shapes/Polygon/Polygon_1px_Stroke.expected.png deleted file mode 100644 index f62be2d4bf..0000000000 Binary files a/tests/TestFiles/Cairo/Shapes/Polygon/Polygon_1px_Stroke.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Shapes/Polygon/Polygon_NonUniformFill.expected.png b/tests/TestFiles/Cairo/Shapes/Polygon/Polygon_NonUniformFill.expected.png deleted file mode 100644 index 0888c74c30..0000000000 Binary files a/tests/TestFiles/Cairo/Shapes/Polygon/Polygon_NonUniformFill.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Shapes/Polyline/Polyline_10px_Stroke_PenLineJoin.expected.png b/tests/TestFiles/Cairo/Shapes/Polyline/Polyline_10px_Stroke_PenLineJoin.expected.png deleted file mode 100644 index d908a572cb..0000000000 Binary files a/tests/TestFiles/Cairo/Shapes/Polyline/Polyline_10px_Stroke_PenLineJoin.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Shapes/Polyline/Polyline_1px_Stroke.expected.png b/tests/TestFiles/Cairo/Shapes/Polyline/Polyline_1px_Stroke.expected.png deleted file mode 100644 index 7cbe87fa6c..0000000000 Binary files a/tests/TestFiles/Cairo/Shapes/Polyline/Polyline_1px_Stroke.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Shapes/Rectangle/Rectangle_1px_Stroke.expected.png b/tests/TestFiles/Cairo/Shapes/Rectangle/Rectangle_1px_Stroke.expected.png deleted file mode 100644 index 24239d5799..0000000000 Binary files a/tests/TestFiles/Cairo/Shapes/Rectangle/Rectangle_1px_Stroke.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Shapes/Rectangle/Rectangle_2px_Stroke.expected.png b/tests/TestFiles/Cairo/Shapes/Rectangle/Rectangle_2px_Stroke.expected.png deleted file mode 100644 index cebe42f3df..0000000000 Binary files a/tests/TestFiles/Cairo/Shapes/Rectangle/Rectangle_2px_Stroke.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Shapes/Rectangle/Rectangle_Stroke_Fill.expected.png b/tests/TestFiles/Cairo/Shapes/Rectangle/Rectangle_Stroke_Fill.expected.png deleted file mode 100644 index d1c13a9e57..0000000000 Binary files a/tests/TestFiles/Cairo/Shapes/Rectangle/Rectangle_Stroke_Fill.expected.png and /dev/null differ diff --git a/tests/TestFiles/Cairo/Shapes/Rectangle/Rectangle_Stroke_Fill_ClipToBounds.expected.png b/tests/TestFiles/Cairo/Shapes/Rectangle/Rectangle_Stroke_Fill_ClipToBounds.expected.png deleted file mode 100644 index d1c13a9e57..0000000000 Binary files a/tests/TestFiles/Cairo/Shapes/Rectangle/Rectangle_Stroke_Fill_ClipToBounds.expected.png and /dev/null differ diff --git a/tests/TestFiles/Direct2D1/SVGPath/SVGPath.expected.png b/tests/TestFiles/Direct2D1/SVGPath/SVGPath.expected.png new file mode 100644 index 0000000000..9830048810 Binary files /dev/null and b/tests/TestFiles/Direct2D1/SVGPath/SVGPath.expected.png differ diff --git a/tests/TestFiles/Skia/SVGPath/SVGPath.expected.png b/tests/TestFiles/Skia/SVGPath/SVGPath.expected.png new file mode 100644 index 0000000000..9830048810 Binary files /dev/null and b/tests/TestFiles/Skia/SVGPath/SVGPath.expected.png differ diff --git a/tools/packages.config b/tools/packages.config index 5657d953fc..e0dd39bd2b 100644 --- a/tools/packages.config +++ b/tools/packages.config @@ -1,4 +1,4 @@ - +