diff --git a/.ncrunch/Avalonia.LinuxFramebuffer.v3.ncrunchproject b/.ncrunch/Avalonia.LinuxFramebuffer.v3.ncrunchproject
new file mode 100644
index 0000000000..6800b4a3fe
--- /dev/null
+++ b/.ncrunch/Avalonia.LinuxFramebuffer.v3.ncrunchproject
@@ -0,0 +1,5 @@
+
+
+ True
+
+
\ No newline at end of file
diff --git a/Avalonia.sln b/Avalonia.sln
index 3fb5ec2693..cc166bc495 100644
--- a/Avalonia.sln
+++ b/Avalonia.sln
@@ -1,6 +1,6 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
-VisualStudioVersion = 15.0.26228.9
+VisualStudioVersion = 15.0.26228.4
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Base", "src\Avalonia.Base\Avalonia.Base.csproj", "{B09B78D8-9B26-48B0-9149-D64A2F120F3F}"
EndProject
@@ -185,6 +185,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Targets", "Targets", "{4D6F
build\UnitTests.NetCore.targets = build\UnitTests.NetCore.targets
EndProjectSection
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Linux", "Linux", "{86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.LinuxFramebuffer", "src\Linux\Avalonia.LinuxFramebuffer\Avalonia.LinuxFramebuffer.csproj", "{854568D5-13D1-4B4F-B50D-534DC7EFD3C9}"
+EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
src\Skia\Avalonia.Skia\Avalonia.Skia.projitems*{2f59f3d0-748d-4652-b01e-e0d954756308}*SharedItemsImports = 13
@@ -2503,6 +2507,46 @@ Global
{39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.Release|Mono.Build.0 = Release|Any CPU
{39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.Release|x86.ActiveCfg = Release|Any CPU
{39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.Release|x86.Build.0 = Release|Any CPU
+ {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
+ {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
+ {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
+ {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
+ {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Ad-Hoc|Mono.ActiveCfg = Debug|Any CPU
+ {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Ad-Hoc|Mono.Build.0 = Debug|Any CPU
+ {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
+ {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
+ {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
+ {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.AppStore|Any CPU.Build.0 = Debug|Any CPU
+ {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
+ {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.AppStore|iPhone.Build.0 = Debug|Any CPU
+ {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.AppStore|Mono.ActiveCfg = Debug|Any CPU
+ {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.AppStore|Mono.Build.0 = Debug|Any CPU
+ {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.AppStore|x86.ActiveCfg = Debug|Any CPU
+ {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.AppStore|x86.Build.0 = Debug|Any CPU
+ {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Debug|Mono.ActiveCfg = Debug|Any CPU
+ {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Debug|Mono.Build.0 = Debug|Any CPU
+ {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Debug|x86.Build.0 = Debug|Any CPU
+ {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Release|Any CPU.Build.0 = Release|Any CPU
+ {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Release|iPhone.Build.0 = Release|Any CPU
+ {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Release|Mono.ActiveCfg = Release|Any CPU
+ {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Release|Mono.Build.0 = Release|Any CPU
+ {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Release|x86.ActiveCfg = Release|Any CPU
+ {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -2561,5 +2605,6 @@ Global
{39D7B147-1A5B-47C2-9D01-21FB7C47C4B3} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{F3AC8BC1-27F5-4255-9AFC-04ABFD11683A} = {74487168-7D91-487E-BF93-055F2251461E}
{4D6FAF79-58B4-482F-9122-0668C346364C} = {74487168-7D91-487E-BF93-055F2251461E}
+ {854568D5-13D1-4B4F-B50D-534DC7EFD3C9} = {86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B}
EndGlobalSection
EndGlobal
diff --git a/appveyor.yml b/appveyor.yml
index 3c36c2fcd3..c9cd4baf80 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,6 +1,7 @@
-os: Visual Studio 2017
+os: Previous Visual Studio 2017
platform:
- Any CPU
+skip_branch_with_pr: true
configuration:
- Release
environment:
diff --git a/build.cake b/build.cake
index a36a3bb536..1e29b33fc1 100644
--- a/build.cake
+++ b/build.cake
@@ -4,7 +4,7 @@
#addin "nuget:?package=Polly&version=4.2.0"
#addin "nuget:?package=NuGet.Core&version=2.12.0"
-#tool "nuget:https://dotnet.myget.org/F/nuget-build/?package=NuGet.CommandLine&version=4.3.0-beta1-2361&prerelease"
+#tool "nuget:https://dotnet.myget.org/F/nuget-build/?package=NuGet.CommandLine&version=4.3.0-preview1-3980&prerelease"
#tool "nuget:?package=JetBrains.dotMemoryUnit&version=2.1.20150828.125449"
///////////////////////////////////////////////////////////////////////////////
// TOOLS
diff --git a/packages.cake b/packages.cake
index c3d0eb0bab..f030c73a06 100644
--- a/packages.cake
+++ b/packages.cake
@@ -198,7 +198,6 @@ public class Packages
new NuSpecDependency() { Id = "System.Threading.ThreadPool", TargetFramework = "netcoreapp1.0", Version = "4.3.0" },
new NuSpecDependency() { Id = "Microsoft.Extensions.DependencyModel", TargetFramework = "netcoreapp1.0", Version = "1.1.0" },
new NuSpecDependency() { Id = "NETStandard.Library", TargetFramework = "netcoreapp1.0", Version = "1.6.0" },
- new NuSpecDependency() { Id = "Microsoft.NETCore.Portable.Compatibility", TargetFramework = "netcoreapp1.0", Version = "1.0.1" },
new NuSpecDependency() { Id = "Splat", TargetFramework = "netcoreapp1.0", Version = SplatVersion },
new NuSpecDependency() { Id = "Serilog", TargetFramework = "netcoreapp1.0", Version = SerilogVersion },
new NuSpecDependency() { Id = "Sprache", TargetFramework = "netcoreapp1.0", Version = SpracheVersion },
@@ -429,8 +428,7 @@ public class Packages
//netstandard1.3
new NuSpecDependency() { Id = "Avalonia", TargetFramework = "netstandard1.3", Version = parameters.Version },
new NuSpecDependency() { Id = "SkiaSharp", TargetFramework = "netstandard1.3", Version = SkiaSharpVersion },
- new NuSpecDependency() { Id = "NETStandard.Library", TargetFramework = "netstandard1.3", Version = "1.6.0" },
- new NuSpecDependency() { Id = "Microsoft.NETCore.Portable.Compatibility", TargetFramework = "netstandard1.3", Version = "1.0.1" }
+ new NuSpecDependency() { Id = "NETStandard.Library", TargetFramework = "netstandard1.3", Version = "1.6.0" }
},
Files = new []
{
@@ -460,6 +458,24 @@ public class Packages
},
BasePath = context.Directory("./"),
OutputDirectory = parameters.NugetRoot
+ },
+ ///////////////////////////////////////////////////////////////////////////////
+ // Avalonia.LinuxFramebuffer
+ ///////////////////////////////////////////////////////////////////////////////
+ new NuGetPackSettings()
+ {
+ Id = "Avalonia.LinuxFramebuffer",
+ Dependencies = new []
+ {
+ new NuSpecDependency() { Id = "Avalonia", Version = parameters.Version },
+ new NuSpecDependency() { Id = "Avalonia.Skia.Desktop", Version = parameters.Version }
+ },
+ Files = new []
+ {
+ new NuSpecContent { Source = "Avalonia.LinuxFramebuffer/bin/" + parameters.DirSuffix + "/netstandard1.3/Avalonia.LinuxFramebuffer.dll", Target = "lib/netstandard1.3" }
+ },
+ BasePath = context.Directory("./src/Linux/"),
+ OutputDirectory = parameters.NugetRoot
}
};
diff --git a/readme.md b/readme.md
index 0cc2b05e9d..2149aff386 100644
--- a/readme.md
+++ b/readme.md
@@ -3,7 +3,7 @@
| Gitter Chat | Windows Build Status | Linux/Mac Build Status | Code Coverage |
|---|---|---|---|
-| [](https://gitter.im/AvaloniaUI/Avalonia?utm_campaign=pr-badge&utm_content=badge&utm_medium=badge&utm_source=badge) | [](https://ci.appveyor.com/project/AvaloniaUI/Avalonia/branch/master) | [](https://travis-ci.org/AvaloniaUI/Avalonia) | [](https://codecov.io/gh/AvaloniaUI/Avalonia) |
+| [](https://gitter.im/AvaloniaUI/Avalonia?utm_campaign=pr-badge&utm_content=badge&utm_medium=badge&utm_source=badge) | [](https://ci.appveyor.com/project/AvaloniaUI/Avalonia/branch/master) | [](https://travis-ci.org/AvaloniaUI/Avalonia) | [](https://codecov.io/gh/AvaloniaUI/Avalonia) |
A multi-platform .NET UI framework. It can run on Windows, Linux, Mac OS X, iOS and Android.
diff --git a/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj b/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj
index d43c3a060e..e0e848b91b 100644
--- a/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj
+++ b/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj
@@ -7,6 +7,7 @@
+
diff --git a/samples/ControlCatalog.NetCore/Program.cs b/samples/ControlCatalog.NetCore/Program.cs
index 57a508f923..7c67a239e6 100644
--- a/samples/ControlCatalog.NetCore/Program.cs
+++ b/samples/ControlCatalog.NetCore/Program.cs
@@ -1,4 +1,5 @@
using System;
+using System.Linq;
using Avalonia;
namespace ControlCatalog.NetCore
@@ -7,9 +8,22 @@ namespace ControlCatalog.NetCore
{
static void Main(string[] args)
{
- AppBuilder.Configure()
- .UsePlatformDetect()
- .Start();
+ if (args.Contains("--fbdev")) AppBuilder.Configure().InitializeWithLinuxFramebuffer(tl =>
+ {
+ tl.Content = new MainView();
+ System.Threading.ThreadPool.QueueUserWorkItem(_ => ConsoleSilencer());
+ });
+ else
+ AppBuilder.Configure()
+ .UsePlatformDetect()
+ .Start();
+ }
+
+ static void ConsoleSilencer()
+ {
+ Console.CursorVisible = false;
+ while (true)
+ Console.ReadKey(true);
}
}
}
\ No newline at end of file
diff --git a/src/Avalonia.Controls/Button.cs b/src/Avalonia.Controls/Button.cs
index 8f617466ed..24daa545ba 100644
--- a/src/Avalonia.Controls/Button.cs
+++ b/src/Avalonia.Controls/Button.cs
@@ -226,7 +226,7 @@ namespace Avalonia.Controls
}
///
- protected override void OnPointerReleased(PointerEventArgs e)
+ protected override void OnPointerReleased(PointerReleasedEventArgs e)
{
base.OnPointerReleased(e);
diff --git a/src/Avalonia.Controls/Presenters/TextPresenter.cs b/src/Avalonia.Controls/Presenters/TextPresenter.cs
index 43088eb0ea..a2b5f3f8b4 100644
--- a/src/Avalonia.Controls/Presenters/TextPresenter.cs
+++ b/src/Avalonia.Controls/Presenters/TextPresenter.cs
@@ -127,11 +127,11 @@ namespace Avalonia.Controls.Presenters
base.Render(context);
if (selectionStart == selectionEnd)
- {
+ {
var backgroundColor = (((Control)TemplatedParent).GetValue(BackgroundProperty) as SolidColorBrush)?.Color;
var caretBrush = Brushes.Black;
- if(backgroundColor.HasValue)
+ if (backgroundColor.HasValue)
{
byte red = (byte)~(backgroundColor.Value.R);
byte green = (byte)~(backgroundColor.Value.G);
@@ -139,7 +139,7 @@ namespace Avalonia.Controls.Presenters
caretBrush = new SolidColorBrush(Color.FromRgb(red, green, blue));
}
-
+
if (_caretBlink)
{
var charPos = FormattedText.HitTestTextPosition(CaretIndex);
diff --git a/src/Avalonia.Controls/Primitives/Thumb.cs b/src/Avalonia.Controls/Primitives/Thumb.cs
index 1fef48f55b..065b1aedbe 100644
--- a/src/Avalonia.Controls/Primitives/Thumb.cs
+++ b/src/Avalonia.Controls/Primitives/Thumb.cs
@@ -86,7 +86,7 @@ namespace Avalonia.Controls.Primitives
RaiseEvent(ev);
}
- protected override void OnPointerReleased(PointerEventArgs e)
+ protected override void OnPointerReleased(PointerReleasedEventArgs e)
{
if (_lastPoint.HasValue)
{
diff --git a/src/Avalonia.Controls/TextBlock.cs b/src/Avalonia.Controls/TextBlock.cs
index 9d71dcfe73..c7a77bdf0e 100644
--- a/src/Avalonia.Controls/TextBlock.cs
+++ b/src/Avalonia.Controls/TextBlock.cs
@@ -116,7 +116,7 @@ namespace Avalonia.Controls
this.GetObservable(TextAlignmentProperty).Select(_ => Unit.Default),
this.GetObservable(FontSizeProperty).Select(_ => Unit.Default),
this.GetObservable(FontStyleProperty).Select(_ => Unit.Default),
- this.GetObservable(FontWeightProperty).Select(_=>Unit.Default))
+ this.GetObservable(FontWeightProperty).Select(_ => Unit.Default))
.Subscribe(_ =>
{
InvalidateFormattedText();
diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs
index 719e888dd4..9748e5e772 100644
--- a/src/Avalonia.Controls/TextBox.cs
+++ b/src/Avalonia.Controls/TextBox.cs
@@ -522,7 +522,7 @@ namespace Avalonia.Controls
}
}
- protected override void OnPointerReleased(PointerEventArgs e)
+ protected override void OnPointerReleased(PointerReleasedEventArgs e)
{
if (_presenter != null && e.Device.Captured == _presenter)
{
diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs
index d7a7a9f0eb..75587dcaec 100644
--- a/src/Avalonia.Controls/Window.cs
+++ b/src/Avalonia.Controls/Window.cs
@@ -281,7 +281,9 @@ namespace Avalonia.Controls
var modal = PlatformImpl.ShowDialog();
var result = new TaskCompletionSource();
- Observable.FromEventPattern(this, nameof(Closed))
+ Observable.FromEventPattern(
+ x => this.Closed += x,
+ x => this.Closed -= x)
.Take(1)
.Subscribe(_ =>
{
diff --git a/src/Avalonia.HtmlRenderer/HtmlControl.cs b/src/Avalonia.HtmlRenderer/HtmlControl.cs
index ca8dcec2e1..88a6e5fda4 100644
--- a/src/Avalonia.HtmlRenderer/HtmlControl.cs
+++ b/src/Avalonia.HtmlRenderer/HtmlControl.cs
@@ -413,7 +413,7 @@ namespace Avalonia.Controls.Html
///
/// Handle mouse up to handle selection and link click.
///
- protected override void OnPointerReleased(PointerEventArgs e)
+ protected override void OnPointerReleased(PointerReleasedEventArgs e)
{
base.OnPointerReleased(e);
LeftMouseButton = false;
diff --git a/src/Avalonia.Input/InputElement.cs b/src/Avalonia.Input/InputElement.cs
index 652b58f0b5..6385f7197b 100644
--- a/src/Avalonia.Input/InputElement.cs
+++ b/src/Avalonia.Input/InputElement.cs
@@ -473,7 +473,7 @@ namespace Avalonia.Input
/// Called before the event occurs.
///
/// The event args.
- protected virtual void OnPointerReleased(PointerEventArgs e)
+ protected virtual void OnPointerReleased(PointerReleasedEventArgs e)
{
}
diff --git a/src/Avalonia.Visuals/Media/FormattedTextStyleSpan.cs b/src/Avalonia.Visuals/Media/FormattedTextStyleSpan.cs
index 75bf76c996..96a5c05c74 100644
--- a/src/Avalonia.Visuals/Media/FormattedTextStyleSpan.cs
+++ b/src/Avalonia.Visuals/Media/FormattedTextStyleSpan.cs
@@ -2,8 +2,17 @@
namespace Avalonia.Media
{
+ ///
+ /// Describes the formatting for a span of text in a object.
+ ///
public class FormattedTextStyleSpan
{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The index of the first character in the span.
+ /// The length of the span.
+ /// The span's foreground brush.
public FormattedTextStyleSpan(
int startIndex,
int length,
@@ -14,8 +23,19 @@ namespace Avalonia.Media
ForegroundBrush = foregroundBrush;
}
+ ///
+ /// Gets the index of the first character in the span.
+ ///
public int StartIndex { get; }
+
+ ///
+ /// Gets the length of the span.
+ ///
public int Length { get; }
+
+ ///
+ /// Gets the span's foreground brush.
+ ///
public IBrush ForegroundBrush { get; }
}
}
diff --git a/src/Avalonia.Visuals/Media/Typeface.cs b/src/Avalonia.Visuals/Media/Typeface.cs
index b05d5d02e5..12540b67e7 100644
--- a/src/Avalonia.Visuals/Media/Typeface.cs
+++ b/src/Avalonia.Visuals/Media/Typeface.cs
@@ -1,10 +1,19 @@
using System;
-using Avalonia.Media;
namespace Avalonia.Media
{
+ ///
+ /// Represents a typeface.
+ ///
public class Typeface
{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The name of the font family.
+ /// The font size, in DIPs.
+ /// The font style.
+ /// The font weight.
public Typeface(
string fontFamilyName,
double fontSize,
@@ -27,9 +36,24 @@ namespace Avalonia.Media
Weight = weight;
}
+ ///
+ /// Gets the name of the font family.
+ ///
public string FontFamilyName { get; }
+
+ ///
+ /// Gets the size of the font in DIPs.
+ ///
public double FontSize { get; }
+
+ ///
+ /// Gets the font style.
+ ///
public FontStyle Style { get; }
+
+ ///
+ /// Gets the font weight.
+ ///
public FontWeight Weight { get; }
}
}
diff --git a/src/Gtk/Avalonia.Cairo/Media/StreamGeometryImpl.cs b/src/Gtk/Avalonia.Cairo/Media/StreamGeometryImpl.cs
index 7d59988918..b0a8cd4fb0 100644
--- a/src/Gtk/Avalonia.Cairo/Media/StreamGeometryImpl.cs
+++ b/src/Gtk/Avalonia.Cairo/Media/StreamGeometryImpl.cs
@@ -52,7 +52,7 @@ namespace Avalonia.Cairo.Media
public Rect GetRenderBounds(double strokeThickness)
{
// TODO: Calculate properly.
- return Bounds.TransformToAABB(Transform).Inflate(strokeThickness);
+ return Bounds.TransformToAABB(Transform).Inflate(strokeThickness);
}
public IStreamGeometryContextImpl Open()
diff --git a/src/Linux/Avalonia.LinuxFramebuffer/Avalonia.LinuxFramebuffer.csproj b/src/Linux/Avalonia.LinuxFramebuffer/Avalonia.LinuxFramebuffer.csproj
new file mode 100644
index 0000000000..3a3e08135d
--- /dev/null
+++ b/src/Linux/Avalonia.LinuxFramebuffer/Avalonia.LinuxFramebuffer.csproj
@@ -0,0 +1,14 @@
+
+
+ netstandard1.3
+ true
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Linux/Avalonia.LinuxFramebuffer/EvDevDevice.cs b/src/Linux/Avalonia.LinuxFramebuffer/EvDevDevice.cs
new file mode 100644
index 0000000000..7b399863f7
--- /dev/null
+++ b/src/Linux/Avalonia.LinuxFramebuffer/EvDevDevice.cs
@@ -0,0 +1,89 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace Avalonia.LinuxFramebuffer
+{
+ unsafe class EvDevDevice
+ {
+ private static readonly Lazy> AllMouseDevices = new Lazy>(()
+ => OpenMouseDevices());
+
+ private static List OpenMouseDevices()
+ {
+ var rv = new List();
+ foreach (var dev in Directory.GetFiles("/dev/input", "event*").Select(Open))
+ {
+ if (!dev.IsMouse)
+ NativeUnsafeMethods.close(dev.Fd);
+ else
+ rv.Add(dev);
+ }
+ return rv;
+ }
+
+ public static IReadOnlyList MouseDevices => AllMouseDevices.Value;
+
+
+ public int Fd { get; }
+ private IntPtr _dev;
+ public string Name { get; }
+ public List EventTypes { get; private set; } = new List();
+ public input_absinfo? AbsX { get; }
+ public input_absinfo? AbsY { get; }
+
+ public EvDevDevice(int fd, IntPtr dev)
+ {
+ Fd = fd;
+ _dev = dev;
+ Name = Marshal.PtrToStringAnsi(NativeUnsafeMethods.libevdev_get_name(_dev));
+ foreach (EvType type in Enum.GetValues(typeof(EvType)))
+ {
+ if (NativeUnsafeMethods.libevdev_has_event_type(dev, type) != 0)
+ EventTypes.Add(type);
+ }
+ var ptr = NativeUnsafeMethods.libevdev_get_abs_info(dev, (int) AbsAxis.ABS_X);
+ if (ptr != null)
+ AbsX = *ptr;
+ ptr = NativeUnsafeMethods.libevdev_get_abs_info(dev, (int)AbsAxis.ABS_Y);
+ if (ptr != null)
+ AbsY = *ptr;
+ }
+
+ public input_event? NextEvent()
+ {
+ input_event ev;
+ if (NativeUnsafeMethods.libevdev_next_event(_dev, 2, out ev) == 0)
+ return ev;
+ return null;
+ }
+
+ public bool IsMouse => EventTypes.Contains(EvType.EV_REL);
+
+ public static EvDevDevice Open(string device)
+ {
+ var fd = NativeUnsafeMethods.open(device, 2048, 0);
+ if (fd <= 0)
+ throw new Exception($"Unable to open {device} code {Marshal.GetLastWin32Error()}");
+ IntPtr dev;
+ var rc = NativeUnsafeMethods.libevdev_new_from_fd(fd, out dev);
+ if (rc < 0)
+ {
+ NativeUnsafeMethods.close(fd);
+ throw new Exception($"Unable to initialize evdev for {device} code {Marshal.GetLastWin32Error()}");
+ }
+ return new EvDevDevice(fd, dev);
+ }
+
+
+ }
+
+ public class EvDevAxisInfo
+ {
+ public int Minimum { get; set; }
+ public int Maximum { get; set; }
+ }
+}
diff --git a/src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs b/src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs
new file mode 100644
index 0000000000..193d2c1d05
--- /dev/null
+++ b/src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs
@@ -0,0 +1,68 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+using Avalonia.Input;
+using Avalonia.Input.Raw;
+using Avalonia.Platform;
+using Avalonia.Threading;
+
+namespace Avalonia.LinuxFramebuffer
+{
+ class FramebufferToplevelImpl : IEmbeddableWindowImpl
+ {
+ private readonly LinuxFramebuffer _fb;
+ private bool _renderQueued;
+ public IInputRoot InputRoot { get; private set; }
+
+ public FramebufferToplevelImpl(LinuxFramebuffer fb)
+ {
+ _fb = fb;
+ Invalidate(default(Rect));
+ var mice = new Mice(ClientSize.Width, ClientSize.Height);
+ mice.Start();
+ mice.Event += e => Input?.Invoke(e);
+ }
+
+ public void Dispose()
+ {
+ throw new NotSupportedException();
+ }
+
+
+ public void Invalidate(Rect rect)
+ {
+ if(_renderQueued)
+ return;
+ _renderQueued = true;
+ Dispatcher.UIThread.InvokeAsync(() =>
+ {
+ Paint?.Invoke(new Rect(default(Point), ClientSize));
+ _renderQueued = false;
+ });
+ }
+
+ public void SetInputRoot(IInputRoot inputRoot)
+ {
+ InputRoot = inputRoot;
+ }
+
+ public Point PointToClient(Point point) => point;
+
+ public Point PointToScreen(Point point) => point;
+
+ public void SetCursor(IPlatformHandle cursor)
+ {
+ }
+
+ public Size ClientSize => _fb.PixelSize;
+ public double Scaling => 1;
+ public IEnumerable