Browse Source

Merge branch 'master' into feature/intermediate-points

pull/7413/head
Max Katz 4 years ago
committed by GitHub
parent
commit
6c634ec695
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 61
      src/Avalonia.X11/X11Window.cs
  2. 137
      src/Web/Avalonia.Web.Blazor/AvaloniaView.razor.cs

61
src/Avalonia.X11/X11Window.cs

@ -6,6 +6,7 @@ using System.Linq;
using System.Reactive.Disposables;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using Avalonia.Controls;
using Avalonia.Controls.Platform;
using Avalonia.Controls.Primitives.PopupPositioning;
@ -50,9 +51,6 @@ namespace Avalonia.X11
private bool _disabled;
private TransparencyHelper _transparencyHelper;
private RawEventGrouper _rawEventGrouper;
public object SyncRoot { get; } = new object();
private bool _useRenderWindow = false;
public X11Window(AvaloniaX11Platform platform, IWindowImpl popupParent)
{
@ -314,13 +312,8 @@ namespace Avalonia.X11
public double RenderScaling
{
get
{
lock (SyncRoot)
return _scaling;
}
private set => _scaling = value;
get => Interlocked.CompareExchange(ref _scaling, 0.0, 0.0);
private set => Interlocked.Exchange(ref _scaling, value);
}
public double DesktopScaling => RenderScaling;
@ -375,11 +368,6 @@ namespace Avalonia.X11
}
void OnEvent(ref XEvent ev)
{
lock (SyncRoot)
OnEventSync(ref ev);
}
void OnEventSync(ref XEvent ev)
{
if (ev.type == XEventName.MapNotify)
{
@ -541,32 +529,29 @@ namespace Avalonia.X11
private bool UpdateScaling(bool skipResize = false)
{
lock (SyncRoot)
double newScaling;
if (_scalingOverride.HasValue)
newScaling = _scalingOverride.Value;
else
{
double newScaling;
if (_scalingOverride.HasValue)
newScaling = _scalingOverride.Value;
else
{
var monitor = _platform.X11Screens.Screens.OrderBy(x => x.PixelDensity)
.FirstOrDefault(m => m.Bounds.Contains(Position));
newScaling = monitor?.PixelDensity ?? RenderScaling;
}
if (RenderScaling != newScaling)
{
var oldScaledSize = ClientSize;
RenderScaling = newScaling;
ScalingChanged?.Invoke(RenderScaling);
UpdateImePosition();
SetMinMaxSize(_scaledMinMaxSize.minSize, _scaledMinMaxSize.maxSize);
if(!skipResize)
Resize(oldScaledSize, true, PlatformResizeReason.DpiChange);
return true;
}
var monitor = _platform.X11Screens.Screens.OrderBy(x => x.PixelDensity)
.FirstOrDefault(m => m.Bounds.Contains(Position));
newScaling = monitor?.PixelDensity ?? RenderScaling;
}
return false;
if (RenderScaling != newScaling)
{
var oldScaledSize = ClientSize;
RenderScaling = newScaling;
ScalingChanged?.Invoke(RenderScaling);
UpdateImePosition();
SetMinMaxSize(_scaledMinMaxSize.minSize, _scaledMinMaxSize.maxSize);
if(!skipResize)
Resize(oldScaledSize, true, PlatformResizeReason.DpiChange);
return true;
}
return false;
}
private WindowState _lastWindowState;

137
src/Web/Avalonia.Web.Blazor/AvaloniaView.razor.cs

@ -26,8 +26,8 @@ namespace Avalonia.Web.Blazor
private InputHelperInterop _canvasHelper = null!;
private ElementReference _htmlCanvas;
private ElementReference _inputElement;
private double _dpi;
private SKSize _canvasSize;
private double _dpi = 1;
private SKSize _canvasSize = new (100, 100);
private GRContext? _context;
private GRGlInterface? _glInterface;
@ -249,71 +249,55 @@ namespace Avalonia.Web.Blazor
[Parameter(CaptureUnmatchedValues = true)]
public IReadOnlyDictionary<string, object>? AdditionalAttributes { get; set; }
protected override void OnAfterRender(bool firstRender)
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
Threading.Dispatcher.UIThread.Post(async () =>
_inputHelper = await InputHelperInterop.ImportAsync(Js, _inputElement);
_canvasHelper = await InputHelperInterop.ImportAsync(Js, _htmlCanvas);
_inputHelper.Hide();
_canvasHelper.SetCursor("default");
_topLevelImpl.SetCssCursor = x =>
{
_inputHelper.SetCursor(x); //macOS
_canvasHelper.SetCursor(x); //windows
};
Console.WriteLine("starting html canvas setup");
_interop = await SKHtmlCanvasInterop.ImportAsync(Js, _htmlCanvas, OnRenderFrame);
Console.WriteLine("Interop created");
_jsGlInfo = _interop.InitGL();
Console.WriteLine("jsglinfo created - init gl");
// create the SkiaSharp context
if (_context == null)
{
_inputHelper = await InputHelperInterop.ImportAsync(Js, _inputElement);
_canvasHelper = await InputHelperInterop.ImportAsync(Js, _htmlCanvas);
_inputHelper.Hide();
_canvasHelper.SetCursor("default");
_topLevelImpl.SetCssCursor = x =>
{
_inputHelper.SetCursor(x);//macOS
_canvasHelper.SetCursor(x);//windows
};
Console.WriteLine("starting html canvas setup");
_interop = await SKHtmlCanvasInterop.ImportAsync(Js, _htmlCanvas, OnRenderFrame);
Console.WriteLine("Interop created");
_jsGlInfo = _interop.InitGL();
Console.WriteLine("jsglinfo created - init gl");
_sizeWatcher = await SizeWatcherInterop.ImportAsync(Js, _htmlCanvas, OnSizeChanged);
_dpiWatcher = await DpiWatcherInterop.ImportAsync(Js, OnDpiChanged);
Console.WriteLine("watchers created.");
// create the SkiaSharp context
if (_context == null)
{
Console.WriteLine("create glcontext");
_glInterface = GRGlInterface.Create();
_context = GRContext.CreateGl(_glInterface);
var options = AvaloniaLocator.Current.GetService<SkiaOptions>();
// bump the default resource cache limit
_context.SetResourceCacheLimit(options?.MaxGpuResourceSizeBytes ?? 32 * 1024 * 1024);
Console.WriteLine("glcontext created and resource limit set");
}
_topLevelImpl.SetSurface(_context, _jsGlInfo, ColorType,
new PixelSize((int)_canvasSize.Width, (int)_canvasSize.Height), _dpi);
_initialised = true;
_topLevel.Prepare();
_topLevel.Renderer.Start();
// Note: this is technically a hack, but it's a kinda unique use case when
// we want to blit the previous frame
// renderer doesn't have much control over the render target
// we render on the UI thread
// We also don't want to have it as a meaningful public API.
// Therefore we have InternalsVisibleTo hack here.
if (_topLevel.Renderer is DeferredRenderer dr)
{
dr.Render(true);
}
Invalidate();
});
Console.WriteLine("create glcontext");
_glInterface = GRGlInterface.Create();
_context = GRContext.CreateGl(_glInterface);
var options = AvaloniaLocator.Current.GetService<SkiaOptions>();
// bump the default resource cache limit
_context.SetResourceCacheLimit(options?.MaxGpuResourceSizeBytes ?? 32 * 1024 * 1024);
Console.WriteLine("glcontext created and resource limit set");
}
_topLevelImpl.SetSurface(_context, _jsGlInfo, ColorType,
new PixelSize((int)_canvasSize.Width, (int)_canvasSize.Height), _dpi);
_initialised = true;
_topLevel.Prepare();
_topLevel.Renderer.Start();
Invalidate();
_sizeWatcher = await SizeWatcherInterop.ImportAsync(Js, _htmlCanvas, OnSizeChanged);
_dpiWatcher = await DpiWatcherInterop.ImportAsync(Js, OnDpiChanged);
}
}
@ -335,16 +319,28 @@ namespace Avalonia.Web.Blazor
_interop.Dispose();
}
private void OnDpiChanged(double newDpi)
private void ForceBlit()
{
_dpi = newDpi;
// Note: this is technically a hack, but it's a kinda unique use case when
// we want to blit the previous frame
// renderer doesn't have much control over the render target
// we render on the UI thread
// We also don't want to have it as a meaningful public API.
// Therefore we have InternalsVisibleTo hack here.
_topLevelImpl.SetClientSize(_canvasSize, _dpi);
if (_topLevel.Renderer is DeferredRenderer dr)
{
dr.Render(true);
}
}
private void OnDpiChanged(double newDpi)
{
_dpi = newDpi;
_topLevelImpl.SetClientSize(_canvasSize, _dpi);
ForceBlit();
Invalidate();
}
@ -357,17 +353,14 @@ namespace Avalonia.Web.Blazor
_topLevelImpl.SetClientSize(_canvasSize, _dpi);
if (_topLevel.Renderer is DeferredRenderer dr)
{
dr.Render(true);
}
ForceBlit();
Invalidate();
}
public void Invalidate()
{
if (!_initialised || _canvasSize.Width <= 0 || _canvasSize.Height <= 0 || _dpi <= 0 || _jsGlInfo == null)
if (!_initialised || _jsGlInfo == null)
{
Console.WriteLine("invalidate ignored");
return;

Loading…
Cancel
Save