source/SkiaSharp.Views.Uno/SkiaSharp.Views.Uno.WinUI.Shared/SKSwapChainPanel.cs (122 lines of code) (raw):
using System;
using Uno;
using Windows.ApplicationModel;
using Windows.Graphics.Display;
using Windows.UI.Core;
#if WINUI
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Data;
#else
using Windows.UI.Xaml;
using Windows.UI.Xaml.Data;
#endif
#if WINDOWS || WINUI
namespace SkiaSharp.Views.Windows
#else
namespace SkiaSharp.Views.UWP
#endif
{
public partial class SKSwapChainPanel : FrameworkElement
{
public static bool RaiseOnUnsupported { get; set; } = true;
private static readonly DependencyProperty ProxyVisibilityProperty =
DependencyProperty.Register(
"ProxyVisibility",
typeof(Visibility),
typeof(SKSwapChainPanel),
new PropertyMetadata(Visibility.Visible, OnVisibilityChanged));
private static bool designMode = DesignMode.DesignModeEnabled;
private bool isVisible = true;
private bool enableRenderLoop = false;
// workaround for https://github.com/mono/SkiaSharp/issues/1118
private int loadUnloadCounter = 0;
private void Initialize()
{
if (designMode)
return;
var display = DisplayInformation.GetForCurrentView();
OnDpiChanged(display);
Loaded += OnLoaded;
Unloaded += OnUnloaded;
SizeChanged += OnSizeChanged;
var binding = new Binding
{
Path = new PropertyPath(nameof(Visibility)),
Source = this
};
SetBinding(ProxyVisibilityProperty, binding);
}
public SKSize CanvasSize => GetCanvasSize();
public GRContext GRContext => GetGRContext();
public double ContentsScale { get; private set; }
[NotImplemented]
public bool DrawInBackground
{
get => throw new NotImplementedException();
set => throw new NotImplementedException();
}
public bool EnableRenderLoop
{
get => enableRenderLoop;
set
{
if (enableRenderLoop != value)
{
enableRenderLoop = value;
DoEnableRenderLoop(enableRenderLoop);
}
}
}
public new void Invalidate()
{
_ = Dispatcher.RunAsync(CoreDispatcherPriority.Normal, DoInvalidate);
}
public event EventHandler<SKPaintGLSurfaceEventArgs> PaintSurface;
protected virtual void OnPaintSurface(SKPaintGLSurfaceEventArgs e)
{
// invoke the event
PaintSurface?.Invoke(this, e);
}
private static void OnVisibilityChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is SKSwapChainPanel canvas && e.NewValue is Visibility visibility)
{
canvas.isVisible = visibility == Visibility.Visible;
canvas.DoUpdateBounds();
canvas.Invalidate();
}
}
private void OnDpiChanged(DisplayInformation sender, object args = null)
{
ContentsScale = sender.LogicalDpi / 96.0f;
DoUpdateBounds();
Invalidate();
}
private void OnSizeChanged(object sender, SizeChangedEventArgs e)
{
DoUpdateBounds();
Invalidate();
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
loadUnloadCounter++;
if (loadUnloadCounter != 1)
return;
DoLoaded();
var display = DisplayInformation.GetForCurrentView();
display.DpiChanged += OnDpiChanged;
OnDpiChanged(display);
}
private void OnUnloaded(object sender, RoutedEventArgs e)
{
loadUnloadCounter--;
if (loadUnloadCounter != 0)
return;
DoUnloaded();
var display = DisplayInformation.GetForCurrentView();
display.DpiChanged -= OnDpiChanged;
}
partial void DoLoaded();
partial void DoUnloaded();
partial void DoUpdateBounds();
partial void DoEnableRenderLoop(bool enable);
}
}