Browse Source

Merge remote-tracking branch 'upstream/master' into gtk-pinvoke

pull/875/head
Nikita Tsukanov 9 years ago
parent
commit
6e1fc14938
  1. 35
      Avalonia.sln
  2. 3
      build.cake
  3. 5
      samples/ControlCatalog.Android/ControlCatalog.Android.csproj
  4. 24
      samples/ControlCatalog.Android/MainActivity.cs
  5. 25
      src/Android/Avalonia.Android/AndroidPlatform.cs
  6. 12
      src/Android/Avalonia.Android/AndroidThreadingInterface.cs
  7. 9
      src/Android/Avalonia.Android/Avalonia.Android.csproj
  8. 50
      src/Android/Avalonia.Android/AvaloniaActivity.cs
  9. 59
      src/Android/Avalonia.Android/AvaloniaView.cs
  10. 101
      src/Android/Avalonia.Android/Platform/SkiaPlatform/AndroidFramebuffer.cs
  11. 8
      src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs
  12. 44
      src/Android/Avalonia.Android/Platform/SkiaPlatform/MainWindowImpl.cs
  13. 37
      src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs
  14. 60
      src/Android/Avalonia.Android/Platform/Specific/AvaloniaActivity.cs
  15. 2
      src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidKeyboardEventsHelper.cs
  16. 2
      src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidTouchEventsHelper.cs
  17. 12
      src/Android/Avalonia.Android/Platform/Specific/IAndroidActivity.cs
  18. 12
      src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj
  19. 32
      src/Android/Avalonia.AndroidTestApplication/MainActivity.cs
  20. 3
      src/Avalonia.Controls/Expander.cs
  21. 5
      src/Avalonia.Controls/Platform/IWindowImpl.cs
  22. 9
      src/Avalonia.Controls/Platform/Surfaces/ILockedFramebuffer.cs
  23. 20
      src/Avalonia.Controls/Window.cs
  24. 4
      src/Avalonia.Visuals/Platform/IPlatformRenderInterface.cs
  25. 2
      src/Gtk/Avalonia.Cairo/CairoPlatform.cs
  26. 4
      src/Gtk/Avalonia.Gtk/Avalonia.Gtk.csproj
  27. 11
      src/Gtk/Avalonia.Gtk/FramebufferManager.cs
  28. 58
      src/Gtk/Avalonia.Gtk/PixbufFramebuffer.cs
  29. 55
      src/Gtk/Avalonia.Gtk/SurfaceFramebuffer.cs
  30. 35
      src/Gtk/Avalonia.Gtk/WindowImplBase.cs
  31. 7
      src/Skia/Avalonia.Skia.Android.TestApp/App.cs
  32. 138
      src/Skia/Avalonia.Skia.Android.TestApp/Avalonia.Skia.Android.TestApp.csproj
  33. 26
      src/Skia/Avalonia.Skia.Android.TestApp/Avalonia.Skia.Android.TestApp.v2.ncrunchproject
  34. 78
      src/Skia/Avalonia.Skia.Android.TestApp/MainActivity.cs
  35. 5
      src/Skia/Avalonia.Skia.Android.TestApp/Properties/AndroidManifest.xml
  36. 30
      src/Skia/Avalonia.Skia.Android.TestApp/Properties/AssemblyInfo.cs
  37. 114
      src/Skia/Avalonia.Skia.Android.TestApp/Resources/Resource.Designer.cs
  38. BIN
      src/Skia/Avalonia.Skia.Android.TestApp/Resources/drawable/Icon.png
  39. 13
      src/Skia/Avalonia.Skia.Android.TestApp/Resources/layout/Main.axml
  40. 5
      src/Skia/Avalonia.Skia.Android.TestApp/Resources/values/Strings.xml
  41. 9
      src/Skia/Avalonia.Skia.Android/AndroidPlatformRenderInterface.cs
  42. 24
      src/Skia/Avalonia.Skia.Android/AndroidRenderTarget.cs
  43. 4
      src/Skia/Avalonia.Skia.Android/Avalonia.Skia.Android.csproj
  44. 106
      src/Skia/Avalonia.Skia.Android/RenderTarget.cs
  45. 39
      src/Skia/Avalonia.Skia.Android/SkiaRenderView.cs
  46. 1
      src/Skia/Avalonia.Skia.iOS/Avalonia.Skia.iOS.csproj
  47. 0
      src/Skia/Avalonia.Skia.iOS/WindowDrawingContextImpl.cs
  48. 1
      src/Skia/Avalonia.Skia/Avalonia.Skia.projitems
  49. 6
      src/Skia/Avalonia.Skia/BitmapImpl.cs
  50. 2
      src/Skia/Avalonia.Skia/PlatformRenderInterface.cs
  51. 71
      src/Windows/Avalonia.Win32/WindowFramebuffer.cs
  52. 31
      src/Windows/Avalonia.Win32/WindowImpl.cs
  53. 10
      src/iOS/Avalonia.iOS/AvaloniaView.cs

35
Avalonia.sln

@ -99,8 +99,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Skia.Desktop", "sr
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Skia.Android", "src\Skia\Avalonia.Skia.Android\Avalonia.Skia.Android.csproj", "{BD43F7C0-396B-4AA1-BAD9-DFDE54D51298}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Skia.Android.TestApp", "src\Skia\Avalonia.Skia.Android.TestApp\Avalonia.Skia.Android.TestApp.csproj", "{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Skia.iOS.TestApp", "src\Skia\Avalonia.Skia.iOS.TestApp\Avalonia.Skia.iOS.TestApp.csproj", "{DA49C5F3-BE95-461C-B999-072128CCF59E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Skia.iOS", "src\Skia\Avalonia.Skia.iOS\Avalonia.Skia.iOS.csproj", "{47BE08A7-5985-410B-9FFC-2264B8EA595F}"
@ -1474,38 +1472,6 @@ Global
{BD43F7C0-396B-4AA1-BAD9-DFDE54D51298}.Release|Mono.ActiveCfg = Release|Any CPU
{BD43F7C0-396B-4AA1-BAD9-DFDE54D51298}.Release|x86.ActiveCfg = Release|Any CPU
{BD43F7C0-396B-4AA1-BAD9-DFDE54D51298}.Release|x86.Build.0 = Release|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Ad-Hoc|Mono.ActiveCfg = Debug|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Ad-Hoc|x86.Deploy.0 = Debug|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.AppStore|iPhone.ActiveCfg = Release|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.AppStore|Mono.ActiveCfg = Debug|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.AppStore|x86.ActiveCfg = Debug|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.AppStore|x86.Build.0 = Debug|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.AppStore|x86.Deploy.0 = Debug|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Debug|Mono.ActiveCfg = Debug|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Debug|x86.ActiveCfg = Debug|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Debug|x86.Build.0 = Debug|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Debug|x86.Deploy.0 = Debug|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Release|Any CPU.Build.0 = Release|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Release|Any CPU.Deploy.0 = Release|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Release|iPhone.ActiveCfg = Release|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Release|Mono.ActiveCfg = Release|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Release|x86.ActiveCfg = Release|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Release|x86.Build.0 = Release|Any CPU
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Release|x86.Deploy.0 = Release|Any CPU
{DA49C5F3-BE95-461C-B999-072128CCF59E}.Ad-Hoc|Any CPU.ActiveCfg = Ad-Hoc|iPhone
{DA49C5F3-BE95-461C-B999-072128CCF59E}.Ad-Hoc|iPhone.ActiveCfg = Ad-Hoc|iPhone
{DA49C5F3-BE95-461C-B999-072128CCF59E}.Ad-Hoc|iPhone.Build.0 = Ad-Hoc|iPhone
@ -2404,7 +2370,6 @@ Global
{2F59F3D0-748D-4652-B01E-E0D954756308} = {3743B0F2-CC41-4F14-A8C8-267F579BF91E}
{925DD807-B651-475F-9F7C-CBEB974CE43D} = {3743B0F2-CC41-4F14-A8C8-267F579BF91E}
{BD43F7C0-396B-4AA1-BAD9-DFDE54D51298} = {3743B0F2-CC41-4F14-A8C8-267F579BF91E}
{F92E55A5-ED73-4CCB-AB4B-0541B6757F31} = {3743B0F2-CC41-4F14-A8C8-267F579BF91E}
{DA49C5F3-BE95-461C-B999-072128CCF59E} = {3743B0F2-CC41-4F14-A8C8-267F579BF91E}
{47BE08A7-5985-410B-9FFC-2264B8EA595F} = {3743B0F2-CC41-4F14-A8C8-267F579BF91E}
{7B92AF71-6287-4693-9DCB-BD5B6E927E23} = {7CF9789C-F1D3-4D0E-90E5-F1DF67A2753F}

3
build.cake

@ -197,6 +197,7 @@ var SystemReactiveVersion = packageVersions["System.Reactive"].FirstOrDefault().
var SkiaSharpVersion = packageVersions["SkiaSharp"].FirstOrDefault().Item1;
var SharpDXVersion = packageVersions["SharpDX"].FirstOrDefault().Item1;
var SharpDXDirect2D1Version = packageVersions["SharpDX.Direct2D1"].FirstOrDefault().Item1;
var SharpDXDirect3D11Version = packageVersions["SharpDX.Direct3D11"].FirstOrDefault().Item1;
var SharpDXDXGIVersion = packageVersions["SharpDX.DXGI"].FirstOrDefault().Item1;
Information("Package: Serilog, version: {0}", SerilogVersion);
@ -206,6 +207,7 @@ Information("Package: System.Reactive, version: {0}", SystemReactiveVersion);
Information("Package: SkiaSharp, version: {0}", SkiaSharpVersion);
Information("Package: SharpDX, version: {0}", SharpDXVersion);
Information("Package: SharpDX.Direct2D1, version: {0}", SharpDXDirect2D1Version);
Information("Package: SharpDX.Direct3D11, version: {0}", SharpDXDirect3D11Version);
Information("Package: SharpDX.DXGI, version: {0}", SharpDXDXGIVersion);
var SetNuGetNuspecCommonProperties = new Action<NuGetPackSettings> ((nuspec) => {
@ -441,6 +443,7 @@ var nuspecNuGetSettingsDesktop = new []
new NuSpecDependency() { Id = "Avalonia", Version = version },
new NuSpecDependency() { Id = "SharpDX", Version = SharpDXVersion },
new NuSpecDependency() { Id = "SharpDX.Direct2D1", Version = SharpDXDirect2D1Version },
new NuSpecDependency() { Id = "SharpDX.Direct3D11", Version = SharpDXDirect3D11Version },
new NuSpecDependency() { Id = "SharpDX.DXGI", Version = SharpDXDXGIVersion }
},
Files = new []

5
samples/ControlCatalog.Android/ControlCatalog.Android.csproj

@ -32,9 +32,12 @@
<EmbedAssembliesIntoApk>False</EmbedAssembliesIntoApk>
<BundleAssemblies>False</BundleAssemblies>
<AndroidCreatePackagePerAbi>False</AndroidCreatePackagePerAbi>
<AndroidSupportedAbis>armeabi,armeabi-v7a,x86</AndroidSupportedAbis>
<AndroidSupportedAbis>armeabi;armeabi-v7a;x86</AndroidSupportedAbis>
<Debugger>Xamarin</Debugger>
<AndroidEnableMultiDex>False</AndroidEnableMultiDex>
<AotAssemblies>False</AotAssemblies>
<EnableLLVM>False</EnableLLVM>
<EnableProguard>False</EnableProguard>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>

24
samples/ControlCatalog.Android/MainActivity.cs

@ -1,9 +1,8 @@
using System;
using Android.App;
using Android.OS;
using Android.Content.PM;
using Avalonia.Android.Platform.Specific;
using Avalonia.Android;
using Avalonia.Controls;
using Avalonia.Controls.Templates;
using Avalonia.Markup.Xaml;
@ -17,29 +16,16 @@ namespace ControlCatalog.Android
[Activity(Label = "ControlCatalog.Android", MainLauncher = true, Icon = "@drawable/icon", LaunchMode = LaunchMode.SingleInstance)]
public class MainActivity : AvaloniaActivity
{
public MainActivity() : base(typeof (App))
{
}
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
App app;
if (Avalonia.Application.Current != null)
app = (App)Avalonia.Application.Current;
else
if (Avalonia.Application.Current == null)
{
app = new App();
AppBuilder.Configure(app)
AppBuilder.Configure(new App())
.UseAndroid()
.UseSkia()
.SetupWithoutStarting();
Content = new MainView();
}
var mainWindow = new MainWindow();
app.Run(mainWindow);
base.OnCreate(savedInstanceState);
}
}
}

25
src/Android/Avalonia.Android/AndroidPlatform.cs

@ -1,5 +1,8 @@
using System;
using System.IO;
using System.Linq;
using Android.Content;
using Android.Views;
using Avalonia.Android.Platform;
using Avalonia.Android.Platform.Input;
using Avalonia.Android.Platform.SkiaPlatform;
@ -8,6 +11,7 @@ using Avalonia.Controls.Platform;
using Avalonia.Input;
using Avalonia.Input.Platform;
using Avalonia.Platform;
using Avalonia.Rendering;
using Avalonia.Shared.PlatformSupport;
using Avalonia.Skia;
@ -17,7 +21,8 @@ namespace Avalonia
{
public static T UseAndroid<T>(this T builder) where T : AppBuilderBase<T>, new()
{
builder.UseWindowingSubsystem(Android.AndroidPlatform.Initialize, "Android");
builder.UseWindowingSubsystem(() => Android.AndroidPlatform.Initialize(builder.Instance), "Android");
builder.UseSkia();
return builder;
}
}
@ -25,7 +30,7 @@ namespace Avalonia
namespace Avalonia.Android
{
public class AndroidPlatform : IPlatformSettings, IWindowingPlatform
class AndroidPlatform : IPlatformSettings, IWindowingPlatform
{
public static readonly AndroidPlatform Instance = new AndroidPlatform();
public Size DoubleClickSize => new Size(4, 4);
@ -40,7 +45,7 @@ namespace Avalonia.Android
_scalingFactor = global::Android.App.Application.Context.Resources.DisplayMetrics.ScaledDensity;
}
public static void Initialize()
public static void Initialize(Avalonia.Application app)
{
AvaloniaLocator.CurrentMutable
.Bind<IClipboard>().ToTransient<ClipboardImpl>()
@ -51,24 +56,22 @@ namespace Avalonia.Android
.Bind<IPlatformThreadingInterface>().ToConstant(new AndroidThreadingInterface())
.Bind<ISystemDialogImpl>().ToTransient<SystemDialogImpl>()
.Bind<IWindowingPlatform>().ToConstant(Instance)
.Bind<IPlatformIconLoader>().ToSingleton<PlatformIconLoader>();
.Bind<IPlatformIconLoader>().ToSingleton<PlatformIconLoader>()
.Bind<IRenderLoop>().ToConstant(new DefaultRenderLoop(60))
SkiaPlatform.Initialize();
}
.Bind<IAssetLoader>().ToConstant(new AssetLoader(app.GetType().Assembly));
public void Init(Type applicationType)
{
StandardRuntimePlatformServices.Register(applicationType.Assembly);
SkiaPlatform.Initialize();
}
public IWindowImpl CreateWindow()
{
return new WindowImpl();
throw new NotSupportedException();
}
public IEmbeddableWindowImpl CreateEmbeddableWindow()
{
throw new NotImplementedException();
throw new NotSupportedException();
}
public IPopupImpl CreatePopup()

12
src/Android/Avalonia.Android/AndroidThreadingInterface.cs

@ -51,10 +51,16 @@ namespace Avalonia.Android
scheduled = true;
EnsureInvokeOnMainThread(() =>
{
tick();
lock (l)
try
{
scheduled = false;
tick();
}
finally
{
lock (l)
{
scheduled = false;
}
}
});
}

9
src/Android/Avalonia.Android/Avalonia.Android.csproj

@ -63,16 +63,17 @@
<ItemGroup>
<Compile Include="AndroidPlatform.cs" />
<Compile Include="AndroidThreadingInterface.cs" />
<Compile Include="AvaloniaActivity.cs" />
<Compile Include="AvaloniaView.cs" />
<Compile Include="PlatformIconLoader.cs" />
<Compile Include="Platform\ClipboardImpl.cs" />
<Compile Include="CursorFactory.cs" />
<Compile Include="Platform\Input\AndroidKeyboardDevice.cs" />
<Compile Include="Platform\Input\AndroidMouseDevice.cs" />
<Compile Include="Platform\SkiaPlatform\MainWindowImpl.cs" />
<Compile Include="Platform\SkiaPlatform\WindowImpl.cs" />
<Compile Include="Platform\SkiaPlatform\AndroidFramebuffer.cs" />
<Compile Include="Platform\SkiaPlatform\InvalidationAwareSurfaceView.cs" />
<Compile Include="Platform\SkiaPlatform\TopLevelImpl.cs" />
<Compile Include="Platform\Specific\IAndroidView.cs" />
<Compile Include="Platform\Specific\IAndroidActivity.cs" />
<Compile Include="Platform\Specific\AvaloniaActivity.cs" />
<Compile Include="Platform\Specific\Helpers\AndroidTouchEventsHelper.cs" />
<Compile Include="Platform\Specific\Helpers\AndroidKeyboardEventsHelper.cs" />
<Compile Include="Resources\Resource.Designer.cs" />

50
src/Android/Avalonia.Android/AvaloniaActivity.cs

@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
namespace Avalonia.Android
{
public abstract class AvaloniaActivity : Activity
{
AvaloniaView _view;
object _content;
protected override void OnCreate(Bundle savedInstanceState)
{
RequestWindowFeature(WindowFeatures.NoTitle);
_view = new AvaloniaView(this);
if(_content != null)
_view.Content = _content;
SetContentView(_view);
TakeKeyEvents(true);
base.OnCreate(savedInstanceState);
}
public object Content
{
get
{
return _content;
}
set
{
_content = value;
if (_view != null)
_view.Content = value;
}
}
public override bool DispatchKeyEvent(KeyEvent e)
{
return _view.DispatchKeyEvent(e);
}
}
}

59
src/Android/Avalonia.Android/AvaloniaView.cs

@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Avalonia.Android.Platform.SkiaPlatform;
using Avalonia.Controls.Embedding;
using Avalonia.Platform;
namespace Avalonia.Android
{
public class AvaloniaView : FrameLayout
{
private readonly EmbeddableControlRoot _root;
private readonly ViewImpl _view;
public AvaloniaView(Context context) : base(context)
{
_view = new ViewImpl(context);
AddView(_view);
_root = new EmbeddableControlRoot(_view);
_root.Prepare();
}
public object Content
{
get { return _root.Content; }
set { _root.Content = value; }
}
public override bool DispatchKeyEvent(KeyEvent e)
{
return _view.DispatchKeyEvent(e);
}
class ViewImpl : TopLevelImpl, IEmbeddableWindowImpl
{
public event Action LostFocus;
public ViewImpl(Context context) : base(context)
{
Focusable = true;
FocusChange += ViewImpl_FocusChange;
}
private void ViewImpl_FocusChange(object sender, FocusChangeEventArgs e)
{
if(!e.HasFocus)
LostFocus?.Invoke();
}
}
}
}

101
src/Android/Avalonia.Android/Platform/SkiaPlatform/AndroidFramebuffer.cs

@ -0,0 +1,101 @@
using System;
using System.Runtime.InteropServices;
using Android.Runtime;
using Android.Views;
using Avalonia.Controls.Platform.Surfaces;
namespace Avalonia.Android.Platform.SkiaPlatform
{
class AndroidFramebuffer : ILockedFramebuffer
{
private IntPtr _window;
public AndroidFramebuffer(Surface surface)
{
_window = ANativeWindow_fromSurface(JNIEnv.Handle, surface.Handle);
ANativeWindow_Buffer buffer;
var rc = new ARect()
{
right = Width = ANativeWindow_getWidth(_window),
bottom = Height = ANativeWindow_getHeight(_window)
};
ANativeWindow_lock(_window, out buffer, ref rc);
Format = buffer.format == AndroidPixelFormat.WINDOW_FORMAT_RGB_565
? PixelFormat.Rgb565 : PixelFormat.Rgba8888;
RowBytes = buffer.stride * (Format == PixelFormat.Rgb565 ? 2 : 4);
Address = buffer.bits;
}
public void Dispose()
{
ANativeWindow_unlockAndPost(_window);
ANativeWindow_release(_window);
_window = IntPtr.Zero;
Address = IntPtr.Zero;
}
public IntPtr Address { get; set; }
public int Width { get; }
public int Height { get; }
public int RowBytes { get; }
public Size Dpi { get; } = new Size(96, 96);
public PixelFormat Format { get; }
[DllImport("android")]
internal static extern IntPtr ANativeWindow_fromSurface(IntPtr jniEnv, IntPtr handle);
[DllImport("android")]
internal static extern int ANativeWindow_getWidth(IntPtr window);
[DllImport("android")]
internal static extern int ANativeWindow_getHeight(IntPtr window);
[DllImport("android")]
internal static extern void ANativeWindow_release(IntPtr window);
[DllImport("android")]
internal static extern void ANativeWindow_unlockAndPost(IntPtr window);
[DllImport("android")]
internal static extern int ANativeWindow_lock(IntPtr window, out ANativeWindow_Buffer outBuffer, ref ARect inOutDirtyBounds);
public enum AndroidPixelFormat
{
WINDOW_FORMAT_RGBA_8888 = 1,
WINDOW_FORMAT_RGBX_8888 = 2,
WINDOW_FORMAT_RGB_565 = 4,
}
internal struct ARect
{
public int left;
public int top;
public int right;
public int bottom;
}
internal struct ANativeWindow_Buffer
{
// The number of pixels that are show horizontally.
public int width;
// The number of pixels that are shown vertically.
public int height;
// The number of *pixels* that a line in the buffer takes in
// memory. This may be >= width.
public int stride;
// The format of the buffer. One of WINDOW_FORMAT_*
public AndroidPixelFormat format;
// The actual bits.
public IntPtr bits;
// Do not touch.
uint reserved1;
uint reserved2;
uint reserved3;
uint reserved4;
uint reserved5;
uint reserved6;
}
}
}

8
src/Skia/Avalonia.Skia.Android/SkiaView.cs → src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs

@ -14,16 +14,16 @@ using Android.Widget;
using Avalonia.Media;
using Avalonia.Platform;
namespace Avalonia.Skia.Android
namespace Avalonia.Android
{
public abstract class SkiaView : SurfaceView, ISurfaceHolderCallback, IPlatformHandle
public abstract class InvalidationAwareSurfaceView : SurfaceView, ISurfaceHolderCallback, IPlatformHandle
{
private readonly Activity _context;
private readonly Context _context;
bool _invalidateQueued;
readonly object _lock = new object();
private readonly Handler _handler;
public SkiaView(Activity context) : base(context)
public InvalidationAwareSurfaceView(Context context) : base(context)
{
_context = context;
Holder.AddCallback(this);

44
src/Android/Avalonia.Android/Platform/SkiaPlatform/MainWindowImpl.cs

@ -1,44 +0,0 @@
using Android.Views;
using Avalonia.Android.Platform.Specific;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Platform;
namespace Avalonia.Android.Platform.SkiaPlatform
{
public class MainWindowImpl :
WindowImpl
, IWindowImpl
{
public MainWindowImpl()
{
}
public new WindowState WindowState
{
get { return WindowState.Normal; }
set { }
}
protected override void Init()
{
base.Init();
HandleEvents = true;
_keyboardHelper.ActivateAutoShowKeybord();
}
void ITopLevelImpl.Show()
{
(Parent as ViewGroup)?.RemoveAllViews();
AvaloniaLocator.Current.GetService<IAndroidActivity>().ContentView = this;
//this.Visibility = ViewStates.Visible;
}
void ITopLevelImpl.SetInputRoot(IInputRoot inputRoot)
{
base.SetInputRoot(inputRoot);
_keyboardHelper.UpdateKeyboardState(inputRoot);
}
}
}

37
src/Android/Avalonia.Android/Platform/SkiaPlatform/WindowImpl.cs → src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs

@ -7,32 +7,30 @@ using Avalonia.Android.Platform.Specific.Helpers;
using Avalonia.Input;
using Avalonia.Input.Raw;
using Avalonia.Platform;
using Avalonia.Skia.Android;
using System;
using System.Collections.Generic;
using Avalonia.Controls;
using Avalonia.Controls.Platform.Surfaces;
namespace Avalonia.Android.Platform.SkiaPlatform
{
public class WindowImpl : SkiaView, IAndroidView, IWindowImpl, ISurfaceHolderCallback
class TopLevelImpl : InvalidationAwareSurfaceView, IAndroidView, ITopLevelImpl,
ISurfaceHolderCallback, IFramebufferPlatformSurface
{
protected AndroidKeyboardEventsHelper<WindowImpl> _keyboardHelper;
protected AndroidKeyboardEventsHelper<TopLevelImpl> _keyboardHelper;
private AndroidTouchEventsHelper<WindowImpl> _touchHelper;
private AndroidTouchEventsHelper<TopLevelImpl> _touchHelper;
public WindowImpl(Context context) : base((Activity)context)
public TopLevelImpl(Context context) : base(context)
{
_keyboardHelper = new AndroidKeyboardEventsHelper<WindowImpl>(this);
_touchHelper = new AndroidTouchEventsHelper<WindowImpl>(this, () => InputRoot, p => GetAvaloniaPointFromEvent(p));
_keyboardHelper = new AndroidKeyboardEventsHelper<TopLevelImpl>(this);
_touchHelper = new AndroidTouchEventsHelper<TopLevelImpl>(this, () => InputRoot, p => GetAvaloniaPointFromEvent(p));
MaxClientSize = new Size(Resources.DisplayMetrics.WidthPixels, Resources.DisplayMetrics.HeightPixels);
ClientSize = MaxClientSize;
Init();
}
public WindowImpl() : this(AvaloniaLocator.Current.GetService<IAndroidActivity>().Activity)
{
}
void ISurfaceHolderCallback.SurfaceChanged(ISurfaceHolder holder, Format format, int width, int height)
{
@ -46,11 +44,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform
base.SurfaceChanged(holder, format, width, height);
}
protected virtual void Init()
{
}
private bool _handleEvents;
public bool HandleEvents
@ -96,6 +90,8 @@ namespace Avalonia.Android.Platform.SkiaPlatform
IPlatformHandle ITopLevelImpl.Handle => this;
public IEnumerable<object> Surfaces => new object[] { this };
public void Activate()
{
}
@ -109,11 +105,6 @@ namespace Avalonia.Android.Platform.SkiaPlatform
{
}
public void SetCoverTaskbarWhenMaximized(bool enable)
{
//Not supported
}
public void Invalidate(Rect rect)
{
if (Holder?.Surface?.IsValid == true) base.Invalidate();
@ -195,6 +186,6 @@ namespace Avalonia.Android.Platform.SkiaPlatform
// No window icons for mobile platforms
}
public IEnumerable<object> Surfaces => new object[] {this};
ILockedFramebuffer IFramebufferPlatformSurface.Lock()=>new AndroidFramebuffer(Holder.Surface);
}
}

60
src/Android/Avalonia.Android/Platform/Specific/AvaloniaActivity.cs

@ -1,60 +0,0 @@
using System;
using Android.App;
using Android.OS;
using Android.Views;
using Android.Widget;
namespace Avalonia.Android.Platform.Specific
{
public class AvaloniaActivity : Activity, IAndroidActivity
{
private IAndroidView _contentView;
public AvaloniaActivity(Type applicationType)
{
AndroidPlatform.Instance.Init(applicationType);
}
public Activity Activity => this;
public IAndroidView ContentView
{
get
{
return this._contentView;
}
set
{
this._contentView = value;
var fl = new FrameLayout(this);
fl.AddView(this._contentView.View);
//this.SetContentView(value.View);
this.SetContentView(fl);
}
}
protected override void OnCreate(Bundle savedInstanceState)
{
AvaloniaLocator.CurrentMutable.Bind<IAndroidActivity>().ToConstant(this);
RequestWindowFeature(WindowFeatures.NoTitle);
base.OnCreate(savedInstanceState);
}
public override void SetContentView(View view)
{
base.SetContentView(view);
TakeKeyEvents(true);
}
public override bool DispatchKeyEvent(KeyEvent e)
{
if (_contentView != null)
{
_contentView.View.DispatchKeyEvent(e);
}
return base.DispatchKeyEvent(e);
}
}
}

2
src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidKeyboardEventsHelper.cs

@ -12,7 +12,7 @@ using System.ComponentModel;
namespace Avalonia.Android.Platform.Specific.Helpers
{
public class AndroidKeyboardEventsHelper<TView> : IDisposable where TView : View, IWindowImpl, IAndroidView
public class AndroidKeyboardEventsHelper<TView> : IDisposable where TView : View, ITopLevelImpl, IAndroidView
{
private TView _view;
private IInputElement _lastFocusedElement;

2
src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidTouchEventsHelper.cs

@ -8,7 +8,7 @@ using System;
namespace Avalonia.Android.Platform.Specific.Helpers
{
public class AndroidTouchEventsHelper<TView> : IDisposable where TView : View, IWindowImpl, IAndroidView
public class AndroidTouchEventsHelper<TView> : IDisposable where TView : View, ITopLevelImpl, IAndroidView
{
private TView _view;
public bool HandleEvents { get; set; }

12
src/Android/Avalonia.Android/Platform/Specific/IAndroidActivity.cs

@ -1,12 +0,0 @@
using Android.App;
using Android.Views;
namespace Avalonia.Android.Platform.Specific
{
public interface IAndroidActivity
{
Activity Activity { get; }
IAndroidView ContentView { get; set; }
}
}

12
src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj

@ -20,7 +20,7 @@
<AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugSymbols>True</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
@ -29,16 +29,16 @@
<WarningLevel>4</WarningLevel>
<AndroidUseSharedRuntime>True</AndroidUseSharedRuntime>
<AndroidLinkMode>None</AndroidLinkMode>
<AndroidLinkSkip />
<EmbedAssembliesIntoApk>False</EmbedAssembliesIntoApk>
<EmbedAssembliesIntoApk>True</EmbedAssembliesIntoApk>
<BundleAssemblies>False</BundleAssemblies>
<AndroidCreatePackagePerAbi>False</AndroidCreatePackagePerAbi>
<AndroidSupportedAbis>armeabi,armeabi-v7a,x86</AndroidSupportedAbis>
<AndroidStoreUncompressedFileExtensions />
<MandroidI18n />
<AndroidSupportedAbis>armeabi;armeabi-v7a;x86</AndroidSupportedAbis>
<Debugger>Xamarin</Debugger>
<AndroidEnableMultiDex>False</AndroidEnableMultiDex>
<DevInstrumentationEnabled>True</DevInstrumentationEnabled>
<AotAssemblies>False</AotAssemblies>
<EnableLLVM>False</EnableLLVM>
<EnableProguard>False</EnableProguard>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>

32
src/Android/Avalonia.AndroidTestApplication/MainActivity.cs

@ -2,7 +2,7 @@ using System;
using Android.App;
using Android.Content.PM;
using Android.OS;
using Avalonia.Android.Platform.Specific;
using Avalonia.Android;
using Avalonia.Controls;
using Avalonia.Controls.Templates;
using Avalonia.Markup.Xaml;
@ -17,36 +17,24 @@ namespace Avalonia.AndroidTestApplication
Icon = "@drawable/icon",
LaunchMode = LaunchMode.SingleInstance/*,
ScreenOrientation = ScreenOrientation.Landscape*/)]
public class MainBaseActivity : AvaloniaActivity
public class MainBaseActivity : Activity
{
public MainBaseActivity() : base(typeof (App))
{
}
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
App app;
if (Avalonia.Application.Current != null)
app = (App)Avalonia.Application.Current;
else
if (Avalonia.Application.Current == null)
{
app = new App();
AppBuilder.Configure(app)
AppBuilder.Configure<App>()
.UseAndroid()
.UseSkia()
.SetupWithoutStarting();
}
app.Run();
SetContentView(new AvaloniaView(this) { Content = App.CreateSimpleWindow() });
}
}
public class App : Application
{
public void Run()
public override void Initialize()
{
Styles.Add(new DefaultTheme());
@ -55,18 +43,14 @@ namespace Avalonia.AndroidTestApplication
new Uri("resm:Avalonia.Themes.Default.Accents.BaseLight.xaml?assembly=Avalonia.Themes.Default"));
Styles.Add(baseLight);
var wnd = App.CreateSimpleWindow();
wnd.AttachDevTools();
Run(wnd);
}
// This provides a simple UI tree for testing input handling, drawing, etc
public static Window CreateSimpleWindow()
public static ContentControl CreateSimpleWindow()
{
Window window = new Window
ContentControl window = new ContentControl()
{
Title = "Avalonia Test Application",
Background = Brushes.Red,
Content = new StackPanel
{

3
src/Avalonia.Controls/Expander.cs

@ -31,7 +31,8 @@ namespace Avalonia.Controls
AvaloniaProperty.RegisterDirect<Expander, bool>(
nameof(IsExpanded),
o => o.IsExpanded,
(o, v) => o.IsExpanded = v);
(o, v) => o.IsExpanded = v,
defaultBindingMode: Data.BindingMode.TwoWay);
static Expander()
{

5
src/Avalonia.Controls/Platform/IWindowImpl.cs

@ -35,11 +35,6 @@ namespace Avalonia.Platform
/// </summary>
void SetSystemDecorations(bool enabled);
/// <summary>
/// When system decorations are disabled sets if the maximized state covers the entire screen or just the working area.
/// </summary>
void SetCoverTaskbarWhenMaximized(bool enable);
/// <summary>
/// Sets the icon of this window.
/// </summary>

9
src/Avalonia.Controls/Platform/Surfaces/ILockedFramebuffer.cs

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Avalonia.Controls.Platform.Surfaces
{
@ -12,22 +8,27 @@ namespace Avalonia.Controls.Platform.Surfaces
/// Address of the first pixel
/// </summary>
IntPtr Address { get; }
/// <summary>
/// Framebuffer width
/// </summary>
int Width { get; }
/// <summary>
/// Framebuffer height
/// </summary>
int Height { get; }
/// <summary>
/// Number of bytes per row
/// </summary>
int RowBytes { get; }
/// <summary>
/// DPI of underling screen
/// </summary>
Size Dpi { get; }
/// <summary>
/// Pixel format
/// </summary>

20
src/Avalonia.Controls/Window.cs

@ -64,13 +64,6 @@ namespace Avalonia.Controls
public static readonly StyledProperty<bool> HasSystemDecorationsProperty =
AvaloniaProperty.Register<Window, bool>(nameof(HasSystemDecorations), true);
/// <summary>
/// Sets if the window should cover the taskbar when maximized. Only applies to Windows
/// with HasSystemDecorations = false.
/// </summary>
public static readonly StyledProperty<bool> CoverTaskbarOnMaximizeProperty =
AvaloniaProperty.Register<Window, bool>(nameof(CoverTaskbarOnMaximize), true);
/// <summary>
/// Defines the <see cref="Title"/> property.
/// </summary>
@ -97,9 +90,6 @@ namespace Avalonia.Controls
HasSystemDecorationsProperty.Changed.AddClassHandler<Window>(
(s, e) => s.PlatformImpl.SetSystemDecorations((bool) e.NewValue));
CoverTaskbarOnMaximizeProperty.Changed.AddClassHandler<Window>(
(s, e) => s.PlatformImpl.SetCoverTaskbarWhenMaximized((bool)e.NewValue));
IconProperty.Changed.AddClassHandler<Window>((s, e) => s.PlatformImpl.SetIcon(((WindowIcon)e.NewValue).PlatformImpl));
}
@ -168,16 +158,6 @@ namespace Avalonia.Controls
set { SetValue(HasSystemDecorationsProperty, value); }
}
/// <summary>
/// Sets if the window should cover the taskbar when maximized. Only applies to Windows
/// with HasSystemDecorations = false.
/// </summary>
public bool CoverTaskbarOnMaximize
{
get { return GetValue(CoverTaskbarOnMaximizeProperty); }
set { SetValue(CoverTaskbarOnMaximizeProperty, value); }
}
/// <summary>
/// Gets or sets the minimized/maximized state of the window.
/// </summary>

4
src/Avalonia.Visuals/Platform/IPlatformRenderInterface.cs

@ -41,7 +41,9 @@ namespace Avalonia.Platform
/// <summary>
/// Creates a renderer.
/// </summary>
/// <param name="surfaces">The list of native platform's surfaces that can be used for output.</param>
/// <param name="surfaces">
/// The list of native platform surfaces that can be used for output.
/// </param>
/// <returns>An <see cref="IRenderTarget"/>.</returns>
IRenderTarget CreateRenderTarget(IEnumerable<object> surfaces);

2
src/Gtk/Avalonia.Cairo/CairoPlatform.cs

@ -59,7 +59,7 @@ namespace Avalonia.Cairo
return new RenderTarget(accessor);
throw new NotSupportedException(string.Format(
"Don't know how to create a Cairo renderer from any of provided surfaces"));
"Don't know how to create a Cairo renderer from any of the provided surfaces."));
}
public IRenderTargetBitmapImpl CreateRenderTargetBitmap(int width, int height)

4
src/Gtk/Avalonia.Gtk/Avalonia.Gtk.csproj

@ -30,6 +30,8 @@
<ConsolePause>false</ConsolePause>
</PropertyGroup>
<ItemGroup>
<Reference Include="Mono.Cairo, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
</Reference>
<Reference Include="System" />
<Reference Include="gtk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
<Reference Include="atk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
@ -50,7 +52,7 @@
<Compile Include="Embedding\GtkAvaloniaControlHost.cs" />
<Compile Include="FramebufferManager.cs" />
<Compile Include="IconImpl.cs" />
<Compile Include="PixbufFramebuffer.cs" />
<Compile Include="SurfaceFramebuffer.cs" />
<Compile Include="SystemDialogImpl.cs" />
<Compile Include="CursorFactory.cs" />
<Compile Include="GtkExtensions.cs" />

11
src/Gtk/Avalonia.Gtk/FramebufferManager.cs

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Avalonia.Controls.Platform.Surfaces;
namespace Avalonia.Gtk
@ -10,7 +6,8 @@ namespace Avalonia.Gtk
class FramebufferManager : IFramebufferPlatformSurface, IDisposable
{
private readonly WindowImplBase _window;
private PixbufFramebuffer _fb;
private SurfaceFramebuffer _fb;
public FramebufferManager(WindowImplBase window)
{
_window = window;
@ -32,8 +29,8 @@ namespace Avalonia.Gtk
if (_fb == null || _fb.Width != width ||
_fb.Height != height)
{
_fb?.Dispose();
_fb = new PixbufFramebuffer(width, height);
_fb?.Deallocate();
_fb = new SurfaceFramebuffer(width, height);
}
_fb.SetDrawable(drawable);
return _fb;

58
src/Gtk/Avalonia.Gtk/PixbufFramebuffer.cs

@ -1,58 +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 Gdk;
namespace Avalonia.Gtk
{
class PixbufFramebuffer : ILockedFramebuffer
{
private Pixbuf _pixbuf;
private Drawable _drawable;
public PixbufFramebuffer(int width, int height)
{
_pixbuf = new Pixbuf(Gdk.Colorspace.Rgb, false, 8, width, height);
}
public void SetDrawable(Drawable drawable)
{
_drawable = drawable;
}
public void Deallocate()
{
_pixbuf.Dispose();
_pixbuf = null;
}
public void Dispose()
{
using (var gc = new Gdk.GC(_drawable))
_drawable.DrawPixbuf(gc, _pixbuf, 0, 0, 0, 0, Width, Height, RgbDither.None, 0, 0);
_drawable = null;
}
public IntPtr Address => _pixbuf.Pixels;
public int Width => _pixbuf.Width;
public int Height => _pixbuf.Height;
public int RowBytes => _pixbuf.Rowstride;
//TODO: Proper DPI detect
public Size Dpi => new Size(96, 96);
public PixelFormat Format
{
get
{
if (AvaloniaLocator.Current.GetService<IRuntimePlatform>().GetRuntimeInfo().OperatingSystem ==
OperatingSystemType.WinNT)
return PixelFormat.Bgra8888;
return PixelFormat.Rgba8888;
}
}
}
}

55
src/Gtk/Avalonia.Gtk/SurfaceFramebuffer.cs

@ -0,0 +1,55 @@
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 Size Dpi => new Size(96, 96);
public PixelFormat Format => PixelFormat.Bgra8888;
}
}

35
src/Gtk/Avalonia.Gtk/WindowImplBase.cs

@ -3,17 +3,13 @@
using System;
using System.Collections.Generic;
using System.Reactive.Disposables;
using System.Runtime.InteropServices;
using Gdk;
using Avalonia.Controls;
using Avalonia.Controls.Platform.Surfaces;
using Avalonia.Input;
using Avalonia.Input.Raw;
using Avalonia.Platform;
using Avalonia.Input;
using Avalonia.Threading;
using Gdk;
using Action = System.Action;
using WindowEdge = Avalonia.Controls.WindowEdge;
using GLib;
namespace Avalonia.Gtk
{
@ -23,8 +19,6 @@ namespace Avalonia.Gtk
{
private IInputRoot _inputRoot;
protected Gtk.Widget _window;
public Gtk.Widget Widget => _window;
public Gdk.Drawable CurrentDrawable { get; private set; }
private FramebufferManager _framebuffer;
private Gtk.IMContext _imContext;
@ -56,10 +50,13 @@ namespace Avalonia.Gtk
_window.KeyReleaseEvent += OnKeyReleaseEvent;
_window.ExposeEvent += OnExposeEvent;
_window.MotionNotifyEvent += OnMotionNotifyEvent;
}
public IPlatformHandle Handle { get; private set; }
public Gtk.Widget Widget => _window;
public Gdk.Drawable CurrentDrawable { get; private set; }
void OnRealized (object sender, EventArgs eventArgs)
{
@ -130,6 +127,13 @@ namespace Avalonia.Gtk
public Action<double> ScalingChanged { get; set; }
public IEnumerable<object> Surfaces => new object[]
{
Handle,
new Func<Gdk.Drawable>(() => CurrentDrawable),
_framebuffer
};
public IPopupImpl CreatePopup()
{
return new PopupImpl();
@ -267,6 +271,7 @@ namespace Avalonia.Gtk
Input(e);
}
[ConnectBefore]
void OnKeyPressEvent(object o, Gtk.KeyPressEventArgs args)
{
args.RetVal = true;
@ -309,11 +314,6 @@ namespace Avalonia.Gtk
args.RetVal = true;
}
public void SetCoverTaskbarWhenMaximized(bool enable)
{
// No action neccesary on Gtk.
}
public void Dispose()
{
_framebuffer.Dispose();
@ -321,12 +321,5 @@ namespace Avalonia.Gtk
_window.Dispose();
_window = null;
}
public IEnumerable<object> Surfaces => new object[]
{
Handle,
new Func<Gdk.Drawable>(() => CurrentDrawable),
_framebuffer
};
}
}

7
src/Skia/Avalonia.Skia.Android.TestApp/App.cs

@ -1,7 +0,0 @@

namespace Avalonia.Skia.Android.TestApp
{
public class App : Application
{
}
}

138
src/Skia/Avalonia.Skia.Android.TestApp/Avalonia.Skia.Android.TestApp.csproj

@ -1,138 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}</ProjectGuid>
<ProjectTypeGuids>{EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Avalonia.Skia.Android.TestApp</RootNamespace>
<AssemblyName>Avalonia.Skia.Android.TestApp</AssemblyName>
<FileAlignment>512</FileAlignment>
<AndroidApplication>true</AndroidApplication>
<AndroidResgenFile>Resources\Resource.Designer.cs</AndroidResgenFile>
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
<AndroidUseLatestPlatformSdk>False</AndroidUseLatestPlatformSdk>
<TargetFrameworkVersion>v4.4</TargetFrameworkVersion>
<AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>True</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AndroidUseSharedRuntime>True</AndroidUseSharedRuntime>
<AndroidLinkMode>None</AndroidLinkMode>
<EmbedAssembliesIntoApk>False</EmbedAssembliesIntoApk>
<BundleAssemblies>False</BundleAssemblies>
<AndroidCreatePackagePerAbi>False</AndroidCreatePackagePerAbi>
<AndroidSupportedAbis>armeabi;armeabi-v7a;x86</AndroidSupportedAbis>
<Debugger>Xamarin</Debugger>
<AndroidEnableMultiDex>False</AndroidEnableMultiDex>
<DevInstrumentationEnabled>True</DevInstrumentationEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AndroidUseSharedRuntime>False</AndroidUseSharedRuntime>
<AndroidLinkMode>Full</AndroidLinkMode>
<EmbedAssembliesIntoApk>True</EmbedAssembliesIntoApk>
<BundleAssemblies>False</BundleAssemblies>
<AndroidCreatePackagePerAbi>False</AndroidCreatePackagePerAbi>
<Debugger>Xamarin</Debugger>
<AotAssemblies>False</AotAssemblies>
<EnableLLVM>False</EnableLLVM>
<AndroidEnableMultiDex>False</AndroidEnableMultiDex>
<EnableProguard>False</EnableProguard>
<DebugSymbols>False</DebugSymbols>
<AndroidSupportedAbis>armeabi;armeabi-v7a;x86</AndroidSupportedAbis>
</PropertyGroup>
<ItemGroup>
<Reference Include="Mono.Android" />
<Reference Include="mscorlib" />
<Reference Include="System" />
<Reference Include="System.Collections" />
<Reference Include="System.Core" />
<Reference Include="System.Runtime" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="App.cs" />
<Compile Include="MainActivity.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Resources\Resource.Designer.cs" />
</ItemGroup>
<ItemGroup>
<None Include="Properties\AndroidManifest.xml" />
<AndroidResource Include="Resources\layout\Main.axml" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Android\Avalonia.Android\Avalonia.Android.csproj">
<Project>{7b92af71-6287-4693-9dcb-bd5b6e927e23}</Project>
<Name>Avalonia.Android</Name>
</ProjectReference>
<ProjectReference Include="..\..\Avalonia.Animation\Avalonia.Animation.csproj">
<Project>{d211e587-d8bc-45b9-95a4-f297c8fa5200}</Project>
<Name>Avalonia.Animation</Name>
</ProjectReference>
<ProjectReference Include="..\..\Avalonia.Base\Avalonia.Base.csproj">
<Project>{b09b78d8-9b26-48b0-9149-d64a2f120f3f}</Project>
<Name>Avalonia.Base</Name>
</ProjectReference>
<ProjectReference Include="..\..\Avalonia.Controls\Avalonia.Controls.csproj">
<Project>{d2221c82-4a25-4583-9b43-d791e3f6820c}</Project>
<Name>Avalonia.Controls</Name>
</ProjectReference>
<ProjectReference Include="..\..\Avalonia.DotNetFrameworkRuntime\Avalonia.DotNetFrameworkRuntime.csproj">
<Project>{4a1abb09-9047-4bd5-a4ad-a055e52c5ee0}</Project>
<Name>Avalonia.DotNetFrameworkRuntime</Name>
</ProjectReference>
<ProjectReference Include="..\..\Avalonia.Input\Avalonia.Input.csproj">
<Project>{62024b2d-53eb-4638-b26b-85eeaa54866e}</Project>
<Name>Avalonia.Input</Name>
</ProjectReference>
<ProjectReference Include="..\..\Avalonia.Interactivity\Avalonia.Interactivity.csproj">
<Project>{6b0ed19d-a08b-461c-a9d9-a9ee40b0c06b}</Project>
<Name>Avalonia.Interactivity</Name>
</ProjectReference>
<ProjectReference Include="..\..\Avalonia.Layout\Avalonia.Layout.csproj">
<Project>{42472427-4774-4c81-8aff-9f27b8e31721}</Project>
<Name>Avalonia.Layout</Name>
</ProjectReference>
<ProjectReference Include="..\..\Avalonia.Visuals\Avalonia.Visuals.csproj">
<Project>{eb582467-6abb-43a1-b052-e981ba910e3a}</Project>
<Name>Avalonia.Visuals</Name>
</ProjectReference>
<ProjectReference Include="..\..\Avalonia.Styling\Avalonia.Styling.csproj">
<Project>{f1baa01a-f176-4c6a-b39d-5b40bb1b148f}</Project>
<Name>Avalonia.Styling</Name>
</ProjectReference>
<ProjectReference Include="..\Avalonia.Skia.Android\Avalonia.Skia.Android.csproj">
<Project>{bd43f7c0-396b-4aa1-bad9-dfde54d51298}</Project>
<Name>Avalonia.Skia.Android</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\Icon.png" />
<AndroidResource Include="Resources\values\Strings.xml" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

26
src/Skia/Avalonia.Skia.Android.TestApp/Avalonia.Skia.Android.TestApp.v2.ncrunchproject

@ -1,26 +0,0 @@
<ProjectConfiguration>
<AutoDetectNugetBuildDependencies>true</AutoDetectNugetBuildDependencies>
<BuildPriority>1000</BuildPriority>
<CopyReferencedAssembliesToWorkspace>false</CopyReferencedAssembliesToWorkspace>
<ConsiderInconclusiveTestsAsPassing>false</ConsiderInconclusiveTestsAsPassing>
<PreloadReferencedAssemblies>false</PreloadReferencedAssemblies>
<AllowDynamicCodeContractChecking>true</AllowDynamicCodeContractChecking>
<AllowStaticCodeContractChecking>false</AllowStaticCodeContractChecking>
<AllowCodeAnalysis>false</AllowCodeAnalysis>
<IgnoreThisComponentCompletely>true</IgnoreThisComponentCompletely>
<RunPreBuildEvents>false</RunPreBuildEvents>
<RunPostBuildEvents>false</RunPostBuildEvents>
<PreviouslyBuiltSuccessfully>false</PreviouslyBuiltSuccessfully>
<InstrumentAssembly>true</InstrumentAssembly>
<PreventSigningOfAssembly>false</PreventSigningOfAssembly>
<AnalyseExecutionTimes>true</AnalyseExecutionTimes>
<DetectStackOverflow>true</DetectStackOverflow>
<IncludeStaticReferencesInWorkspace>true</IncludeStaticReferencesInWorkspace>
<DefaultTestTimeout>60000</DefaultTestTimeout>
<UseBuildConfiguration />
<UseBuildPlatform />
<ProxyProcessPath />
<UseCPUArchitecture>AutoDetect</UseCPUArchitecture>
<MSTestThreadApartmentState>STA</MSTestThreadApartmentState>
<BuildProcessArchitecture>x86</BuildProcessArchitecture>
</ProjectConfiguration>

78
src/Skia/Avalonia.Skia.Android.TestApp/MainActivity.cs

@ -1,78 +0,0 @@
using Android.App;
using Android.OS;
using Android.Views;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Media;
namespace Avalonia.Skia.Android.TestApp
{
[Activity(Label = "Avalonia.Skia.Android.TestApp", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
App app;
if (Avalonia.Application.Current != null)
app = (App)Avalonia.Application.Current;
else
{
app = new App();
AppBuilder.Configure(app)
.UseAndroid()
.UseSkia()
.SetupWithoutStarting();
}
SetContentView(new MainView(this));
}
class MainView : SkiaRenderView
{
float _radians = 0;
public MainView(Activity context) : base(context)
{
}
protected override void OnRender(DrawingContext ctx)
{
ctx.FillRectangle(Brushes.Green, new Rect(0, 0, Width, Height));
var rc = new Rect(0, 0, Width/3, Height/3);
using (ctx.PushPostTransform(
Avalonia.Matrix.CreateTranslation(-Width/6, -Width/6)*
Avalonia.Matrix.CreateRotation(_radians)*
Avalonia.Matrix.CreateTranslation(Width/2, Height/2)))
{
ctx.FillRectangle(new LinearGradientBrush()
{
GradientStops =
{
new GradientStop() {Color = Colors.Blue},
new GradientStop(Colors.Red, 1)
}
}, rc, 5);
}
}
public override bool OnTouchEvent(MotionEvent e)
{
if (e.Action == MotionEventActions.Down)
return true;
if (e.Action == MotionEventActions.Move)
{
_radians = (e.RawY + e.RawY)/100;
Invalidate();
return true;
}
return base.OnTouchEvent(e);
}
}
}
}

5
src/Skia/Avalonia.Skia.Android.TestApp/Properties/AndroidManifest.xml

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="Avalonia.Skia.Android.TestApp" android:versionCode="1" android:versionName="1.0">
<uses-sdk />
<application android:label="Avalonia.Skia.Android.TestApp" android:icon="@drawable/Icon"></application>
</manifest>

30
src/Skia/Avalonia.Skia.Android.TestApp/Properties/AssemblyInfo.cs

@ -1,30 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Android.App;
// 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.Skia.Android.TestApp")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Avalonia.Skia.Android.TestApp")]
[assembly: AssemblyCopyright("Copyright © 2015")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
// 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")]

114
src/Skia/Avalonia.Skia.Android.TestApp/Resources/Resource.Designer.cs

@ -1,114 +0,0 @@
#pragma warning disable 1591
//------------------------------------------------------------------------------
// <auto-generated>
// 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.
// </auto-generated>
//------------------------------------------------------------------------------
[assembly: global::Android.Runtime.ResourceDesignerAttribute("Avalonia.Skia.Android.TestApp.Resource", IsApplication=true)]
namespace Avalonia.Skia.Android.TestApp
{
[System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "1.0.0.0")]
public partial class Resource
{
static Resource()
{
global::Android.Runtime.ResourceIdManager.UpdateIdValues();
}
public static void UpdateIdValues()
{
global::Avalonia.Android.Resource.String.ApplicationName = global::Avalonia.Skia.Android.TestApp.Resource.String.ApplicationName;
global::Avalonia.Android.Resource.String.Hello = global::Avalonia.Skia.Android.TestApp.Resource.String.Hello;
}
public partial class Attribute
{
static Attribute()
{
global::Android.Runtime.ResourceIdManager.UpdateIdValues();
}
private Attribute()
{
}
}
public partial class Drawable
{
// aapt resource value: 0x7f020000
public const int Icon = 2130837504;
static Drawable()
{
global::Android.Runtime.ResourceIdManager.UpdateIdValues();
}
private Drawable()
{
}
}
public partial class Id
{
// aapt resource value: 0x7f050000
public const int MyButton = 2131034112;
static Id()
{
global::Android.Runtime.ResourceIdManager.UpdateIdValues();
}
private Id()
{
}
}
public partial class Layout
{
// aapt resource value: 0x7f030000
public const int Main = 2130903040;
static Layout()
{
global::Android.Runtime.ResourceIdManager.UpdateIdValues();
}
private Layout()
{
}
}
public partial class String
{
// aapt resource value: 0x7f040001
public const int ApplicationName = 2130968577;
// aapt resource value: 0x7f040000
public const int Hello = 2130968576;
static String()
{
global::Android.Runtime.ResourceIdManager.UpdateIdValues();
}
private String()
{
}
}
}
}
#pragma warning restore 1591

BIN
src/Skia/Avalonia.Skia.Android.TestApp/Resources/drawable/Icon.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

13
src/Skia/Avalonia.Skia.Android.TestApp/Resources/layout/Main.axml

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<Button
android:id="@+id/MyButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/Hello"
/>
</LinearLayout>

5
src/Skia/Avalonia.Skia.Android.TestApp/Resources/values/Strings.xml

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="Hello">Hello World, Click Me!</string>
<string name="ApplicationName">Avalonia.Skia.Android.TestApp</string>
</resources>

9
src/Skia/Avalonia.Skia.Android/AndroidPlatformRenderInterface.cs

@ -9,6 +9,7 @@ using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Avalonia.Controls.Platform.Surfaces;
using Avalonia.Platform;
namespace Avalonia.Skia
@ -17,10 +18,10 @@ namespace Avalonia.Skia
{
public IRenderTarget CreateRenderTarget(IEnumerable<object> surfaces)
{
var surfaceView = surfaces?.OfType<SurfaceView>().FirstOrDefault();
if (surfaceView == null)
throw new ArgumentException("Avalonia.Skia.Android is only capable of drawing on SurfaceView");
return new WindowRenderTarget(surfaceView);
var fb = surfaces?.OfType<IFramebufferPlatformSurface>().FirstOrDefault();
if (fb == null)
throw new ArgumentException("Avalonia.Skia.Android is only capable of drawing on framebuffer");
return new FramebufferRenderTarget(fb);
}
}
}

24
src/Skia/Avalonia.Skia.Android/AndroidRenderTarget.cs

@ -1,24 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Avalonia.Media;
using Avalonia.Platform;
namespace Avalonia.Skia
{
/// <summary>
/// We will likely need platform specific pieces to support HW acceleration
/// so leaving this class here for now as placeholder.
/// </summary>
internal partial class RenderTarget : IRenderTarget
{
}
}

4
src/Skia/Avalonia.Skia.Android/Avalonia.Skia.Android.csproj

@ -88,10 +88,6 @@
</ItemGroup>
<ItemGroup>
<Compile Include="AndroidPlatformRenderInterface.cs" />
<Compile Include="AndroidRenderTarget.cs" />
<Compile Include="RenderTarget.cs" />
<Compile Include="SkiaRenderView.cs" />
<Compile Include="SkiaView.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />

106
src/Skia/Avalonia.Skia.Android/RenderTarget.cs

@ -1,106 +0,0 @@
using System;
using Avalonia.Media;
using Avalonia.Platform;
using SkiaSharp;
using Android.Graphics;
using Android.Views;
namespace Avalonia.Skia
{
internal partial class RenderTarget : IRenderTarget
{
public SKSurface Surface { get; protected set; }
public virtual DrawingContext CreateDrawingContext()
{
return
new DrawingContext(
new DrawingContextImpl(Surface.Canvas));
}
public void Dispose()
{
// Nothing to do here.
}
}
internal class WindowRenderTarget : RenderTarget
{
private readonly SurfaceView _surfaceView;
Bitmap _bitmap;
int Width { get; set; }
int Height { get; set; }
public WindowRenderTarget(SurfaceView surfaceView)
{
_surfaceView = surfaceView;
FixSize();
}
private void FixSize()
{
int width, height;
GetPlatformWindowSize(out width, out height);
if (Width == width && Height == height)
return;
Width = width;
Height = height;
if (Surface != null)
{
Surface.Dispose();
}
if (_bitmap != null)
{
_bitmap.Dispose();
}
_bitmap = Bitmap.CreateBitmap(width, height, Bitmap.Config.Argb8888);
Surface = SKSurface.Create(width, height, SKImageInfo.PlatformColorType, SKAlphaType.Premul, _bitmap.LockPixels(), width * 4);
}
private void GetPlatformWindowSize(out int w, out int h)
{
w = _surfaceView.Width;
h = _surfaceView.Height;
}
public override DrawingContext CreateDrawingContext()
{
FixSize();
var canvas = Surface.Canvas;
canvas.RestoreToCount(0);
canvas.Save();
canvas.Clear(SKColors.Red);
canvas.ResetMatrix();
return
new DrawingContext(
new WindowDrawingContextImpl(this));
}
public void Present()
{
Canvas canvas = null;
try
{
canvas = _surfaceView.Holder.LockCanvas(null);
_bitmap.UnlockPixels();
canvas.DrawBitmap(_bitmap, 0, 0, null);
}
catch (Exception)
{
}
finally
{
if (canvas != null)
_surfaceView.Holder.UnlockCanvasAndPost(canvas);
}
_bitmap.UnlockPixels();
}
}
}

39
src/Skia/Avalonia.Skia.Android/SkiaRenderView.cs

@ -1,39 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Avalonia.Media;
using Avalonia.Platform;
namespace Avalonia.Skia.Android
{
public abstract class SkiaRenderView : SkiaView
{
private IRenderTarget _renderTarget;
public SkiaRenderView(Activity context) : base(context)
{
_renderTarget =
AvaloniaLocator.Current.GetService<IPlatformRenderInterface>()
.CreateRenderTarget(new object[]{this});
}
protected override void Draw()
{
if (_renderTarget == null)
return;
using (var ctx = _renderTarget.CreateDrawingContext())
OnRender(ctx);
}
protected abstract void OnRender(DrawingContext ctx);
}
}

1
src/Skia/Avalonia.Skia.iOS/Avalonia.Skia.iOS.csproj

@ -41,6 +41,7 @@
<Compile Include="RenderTarget.cs" />
<Compile Include="SkiaView.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="WindowDrawingContextImpl.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="SkiaSharp, Version=1.54.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">

0
src/Skia/Avalonia.Skia/WindowDrawingContextImpl.cs → src/Skia/Avalonia.Skia.iOS/WindowDrawingContextImpl.cs

1
src/Skia/Avalonia.Skia/Avalonia.Skia.projitems

@ -18,7 +18,6 @@
<Compile Include="$(MSBuildThisFileDirectory)SkiaSharpExtensions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)StreamGeometryImpl.cs" />
<Compile Include="$(MSBuildThisFileDirectory)TypefaceCache.cs" />
<Compile Include="$(MSBuildThisFileDirectory)WindowDrawingContextImpl.cs" />
</ItemGroup>
<ItemGroup>
<None Include="$(MSBuildThisFileDirectory)readme.md" />

6
src/Skia/Avalonia.Skia/BitmapImpl.cs

@ -24,7 +24,11 @@ namespace Avalonia.Skia
{
PixelHeight = height;
PixelWidth = width;
Bitmap = new SKBitmap(width, height, SKImageInfo.PlatformColorType, SKAlphaType.Premul);
var colorType = SKImageInfo.PlatformColorType;
var runtime = AvaloniaLocator.Current?.GetService<IRuntimePlatform>()?.GetRuntimeInfo();
if (runtime?.IsDesktop == true && runtime?.OperatingSystem == OperatingSystemType.Linux)
colorType = SKColorType.Bgra8888;
Bitmap = new SKBitmap(width, height, colorType, SKAlphaType.Premul);
}
public void Dispose()

2
src/Skia/Avalonia.Skia/PlatformRenderInterface.cs

@ -55,8 +55,6 @@ namespace Avalonia.Skia
return new Renderer(root, renderLoop);
}
public IRenderTargetBitmapImpl CreateRenderTargetBitmap(int width, int height)
{
if (width < 1)

71
src/Windows/Avalonia.Win32/WindowFramebuffer.cs

@ -18,8 +18,7 @@ namespace Avalonia.Win32
{
private readonly IntPtr _handle;
private IntPtr _pBitmap;
UnmanagedMethods.BITMAPINFOHEADER _bmpInfo;
private UnmanagedMethods.BITMAPINFOHEADER _bmpInfo;
public WindowFramebuffer(IntPtr handle, int width, int height)
{
@ -38,7 +37,38 @@ namespace Avalonia.Win32
_pBitmap = Marshal.AllocHGlobal(width * height * 4);
}
~WindowFramebuffer()
{
Deallocate();
}
public IntPtr Address => _pBitmap;
public int RowBytes => Width * 4;
public PixelFormat Format => PixelFormat.Bgra8888;
public Size Dpi
{
get
{
if (UnmanagedMethods.ShCoreAvailable)
{
uint dpix, dpiy;
var monitor = UnmanagedMethods.MonitorFromWindow(_handle,
UnmanagedMethods.MONITOR.MONITOR_DEFAULTTONEAREST);
if (UnmanagedMethods.GetDpiForMonitor(
monitor,
UnmanagedMethods.MONITOR_DPI_TYPE.MDT_EFFECTIVE_DPI,
out dpix,
out dpiy) == 0)
{
return new Size(dpix, dpiy);
}
}
return new Size(96, 96);
}
}
public int Width => _bmpInfo.biWidth;
@ -73,11 +103,9 @@ namespace Avalonia.Win32
return true;
}
public void Dispose()
{
//It's not an *actual* dispose. This call meand "We are done drawing"
//It's not an *actual* dispose. This call means "We are done drawing"
DrawToWindow(_handle);
}
@ -89,38 +117,5 @@ namespace Avalonia.Win32
_pBitmap = IntPtr.Zero;
}
}
~WindowFramebuffer()
{
Deallocate();
}
public IntPtr Address => _pBitmap;
public int RowBytes => Width * 4;
public PixelFormat Format => PixelFormat.Bgra8888;
public Size Dpi
{
get
{
if (UnmanagedMethods.ShCoreAvailable)
{
uint dpix, dpiy;
var monitor = UnmanagedMethods.MonitorFromWindow(_handle,
UnmanagedMethods.MONITOR.MONITOR_DEFAULTTONEAREST);
if (UnmanagedMethods.GetDpiForMonitor(
monitor,
UnmanagedMethods.MONITOR_DPI_TYPE.MDT_EFFECTIVE_DPI,
out dpix,
out dpiy) == 0)
{
return new Size(dpix, dpiy);
}
}
return new Size(96, 96);
}
}
}
}

31
src/Windows/Avalonia.Win32/WindowImpl.cs

@ -34,10 +34,10 @@ namespace Avalonia.Win32
private bool _trackingMouse;
private bool _isActive;
private bool _decorated = true;
private bool _coverTaskBarWhenMaximized = true;
private double _scaling = 1;
private WindowState _showWindowState;
private FramebufferManager _framebuffer;
public WindowImpl()
{
CreateWindow();
@ -164,6 +164,11 @@ namespace Avalonia.Win32
}
}
public IEnumerable<object> Surfaces => new object[]
{
Handle, _framebuffer
};
public void Activate()
{
UnmanagedMethods.SetActiveWindow(_hwnd);
@ -681,8 +686,6 @@ namespace Avalonia.Win32
{
UnmanagedMethods.ShowWindowCommand command;
bool maximizeFillsDesktop = false; // otherwise we cover entire screen.
switch (state)
{
case WindowState.Minimized:
@ -690,11 +693,6 @@ namespace Avalonia.Win32
break;
case WindowState.Maximized:
command = ShowWindowCommand.Maximize;
if (!_decorated && !_coverTaskBarWhenMaximized)
{
maximizeFillsDesktop = true;
}
break;
case WindowState.Normal:
@ -707,7 +705,7 @@ namespace Avalonia.Win32
UnmanagedMethods.ShowWindow(_hwnd, command);
if (maximizeFillsDesktop)
if (state == WindowState.Maximized)
{
MaximizeWithoutCoveringTaskbar();
}
@ -754,20 +752,5 @@ namespace Avalonia.Win32
return (int)(ptr.ToInt64() & 0xffffffff);
}
public void SetCoverTaskbarWhenMaximized(bool enable)
{
_coverTaskBarWhenMaximized = enable;
if (_showWindowState == WindowState.Maximized)
{
ShowWindow(WindowState.Maximized);
}
}
public IEnumerable<object> Surfaces => new object[]
{
Handle, _framebuffer
};
}
}

10
src/iOS/Avalonia.iOS/AvaloniaView.cs

@ -149,6 +149,9 @@ namespace Avalonia.iOS
}
public Size MaxClientSize => Bounds.Size.ToAvalonia();
public IEnumerable<object> Surfaces => new object[] { this };
public void SetTitle(string title)
{
//Not supported
@ -170,11 +173,6 @@ namespace Avalonia.iOS
//Not supported
}
public void SetCoverTaskbarWhenMaximized(bool enable)
{
//Not supported
}
public override void TouchesEnded(NSSet touches, UIEvent evt)
{
var touch = touches.AnyObject as UITouch;
@ -232,8 +230,6 @@ namespace Avalonia.iOS
public void SetIcon(IWindowIconImpl icon)
{
}
public IEnumerable<object> Surfaces => new object[]{this};
}
class AvaloniaViewController : UIViewController

Loading…
Cancel
Save