Skip to content

Commit

Permalink
Merge branch 'master' into feature/embedded-automation-roots
Browse files Browse the repository at this point in the history
  • Loading branch information
grokys authored Aug 8, 2023
2 parents 40a3549 + 655f199 commit 8ab5a55
Show file tree
Hide file tree
Showing 10 changed files with 294 additions and 61 deletions.
5 changes: 3 additions & 2 deletions nukebuild/Build.cs
Original file line number Diff line number Diff line change
Expand Up @@ -279,8 +279,9 @@ void DoMemoryTest()
if(!Numerge.NugetPackageMerger.Merge(Parameters.NugetIntermediateRoot, Parameters.NugetRoot, config,
new NumergeNukeLogger()))
throw new Exception("Package merge failed");
RefAssemblyGenerator.GenerateRefAsmsInPackage(Parameters.NugetRoot / "Avalonia." +
Parameters.Version + ".nupkg");
RefAssemblyGenerator.GenerateRefAsmsInPackage(
Parameters.NugetRoot / $"Avalonia.{Parameters.Version}.nupkg",
Parameters.NugetRoot / $"Avalonia.{Parameters.Version}.snupkg");
});

Target ValidateApiDiff => _ => _
Expand Down
109 changes: 67 additions & 42 deletions nukebuild/RefAssemblyGenerator.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
#nullable enable

using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using ILRepacking;
using Mono.Cecil;
using Mono.Cecil.Cil;

public class RefAssemblyGenerator
{
class Resolver : DefaultAssemblyResolver, IAssemblyResolver
{
private readonly string _dir;
Dictionary<string, AssemblyDefinition> _cache = new();
readonly string _dir;
readonly Dictionary<string, AssemblyDefinition> _cache = new();

public Resolver(string dir)
{
Expand All @@ -31,17 +33,17 @@ public override AssemblyDefinition Resolve(AssemblyNameReference name, ReaderPar

public static void PatchRefAssembly(string file)
{
var reader = typeof(RefAssemblyGenerator).Assembly.GetManifestResourceStream("avalonia.snk");
var reader = typeof(RefAssemblyGenerator).Assembly.GetManifestResourceStream("avalonia.snk")!;
var snk = new byte[reader.Length];
reader.Read(snk, 0, snk.Length);
reader.ReadExactly(snk, 0, snk.Length);

var def = AssemblyDefinition.ReadAssembly(file, new ReaderParameters
{
ReadWrite = true,
InMemory = true,
ReadSymbols = true,
SymbolReaderProvider = new DefaultSymbolReaderProvider(false),
AssemblyResolver = new Resolver(Path.GetDirectoryName(file))
SymbolReaderProvider = new DefaultSymbolReaderProvider(throwIfNoSymbol: true),
AssemblyResolver = new Resolver(Path.GetDirectoryName(file)!)
});

var obsoleteAttribute = def.MainModule.ImportReference(new TypeReference("System", "ObsoleteAttribute", def.MainModule,
Expand All @@ -58,7 +60,7 @@ public static void PatchRefAssembly(string file)
{
StrongNameKeyBlob = snk,
WriteSymbols = def.MainModule.HasSymbols,
SymbolWriterProvider = new EmbeddedPortablePdbWriterProvider(),
SymbolWriterProvider = new PortablePdbWriterProvider(),
DeterministicMvid = def.MainModule.HasSymbols
});
}
Expand Down Expand Up @@ -146,7 +148,7 @@ static void HideMethod(MethodDefinition m)
m.Attributes = ((m.Attributes | dflags) ^ dflags) | MethodAttributes.Assembly;
}

static void MarkAsUnstable(IMemberDefinition def, MethodReference obsoleteCtor, ICustomAttribute unstableAttribute)
static void MarkAsUnstable(IMemberDefinition def, MethodReference obsoleteCtor, ICustomAttribute? unstableAttribute)
{
if (def.CustomAttributes.Any(a => a.AttributeType.FullName == "System.ObsoleteAttribute"))
return;
Expand All @@ -172,43 +174,66 @@ static void MarkAsUnstable(IMemberDefinition def, MethodReference obsoleteCtor,
});
}

public static void GenerateRefAsmsInPackage(string packagePath)
public static void GenerateRefAsmsInPackage(string mainPackagePath, string symbolsPackagePath)
{
using (var archive = new ZipArchive(File.Open(packagePath, FileMode.Open, FileAccess.ReadWrite),
ZipArchiveMode.Update))
using var mainArchive = OpenPackage(mainPackagePath);
using var symbolsArchive = OpenPackage(symbolsPackagePath);

foreach (var entry in mainArchive.Entries
.Where(e => e.FullName.StartsWith("ref/", StringComparison.Ordinal))
.ToArray())
{
foreach (var entry in archive.Entries.ToList())
{
if (entry.FullName.StartsWith("ref/"))
entry.Delete();
}

foreach (var entry in archive.Entries.ToList())
entry.Delete();
}

foreach (var libEntry in GetLibEntries(mainArchive, ".xml"))
{
var refEntry = mainArchive.CreateEntry("ref/" + libEntry.FullName.Substring(4), CompressionLevel.Optimal);
using var src = libEntry.Open();
using var dst = refEntry.Open();
src.CopyTo(dst);
}

var pdbEntries = GetLibEntries(symbolsArchive, ".pdb").ToDictionary(e => e.FullName);

var libs = GetLibEntries(mainArchive, ".dll")
.Select(e => (NameParts: e.FullName.Split('/'), Entry: e))
.Select(e => (
Tfm: e.NameParts[1],
DllName: e.NameParts[2],
DllEntry: e.Entry,
PdbName: Path.ChangeExtension(e.NameParts[2], ".pdb"),
PdbEntry: pdbEntries.TryGetValue(Path.ChangeExtension(e.Entry.FullName, ".pdb"), out var pdbEntry) ?
pdbEntry :
throw new InvalidOperationException($"Missing symbols for {e.Entry.FullName}")))
.GroupBy(e => e.Tfm);

foreach (var tfm in libs)
{
using var _ = Helpers.UseTempDir(out var temp);

foreach (var lib in tfm)
{
if (entry.FullName.StartsWith("lib/") && entry.Name.EndsWith(".xml"))
{
var newEntry = archive.CreateEntry("ref/" + entry.FullName.Substring(4),
CompressionLevel.Optimal);
using (var src = entry.Open())
using (var dst = newEntry.Open())
src.CopyTo(dst);
}
}
var extractedDllPath = Path.Combine(temp, lib.DllName);
var extractedPdbPath = Path.Combine(temp, lib.PdbName);

lib.DllEntry.ExtractToFile(extractedDllPath);
lib.PdbEntry.ExtractToFile(extractedPdbPath);

var libs = archive.Entries.Where(e => e.FullName.StartsWith("lib/") && e.FullName.EndsWith(".dll"))
.Select((e => new { s = e.FullName.Split('/'), e = e }))
.Select(e => new { Tfm = e.s[1], Name = e.s[2], Entry = e.e })
.GroupBy(x => x.Tfm);
foreach(var tfm in libs)
using (Helpers.UseTempDir(out var temp))
{
foreach (var l in tfm)
l.Entry.ExtractToFile(Path.Combine(temp, l.Name));
foreach (var l in tfm)
PatchRefAssembly(Path.Combine(temp, l.Name));
foreach (var l in tfm)
archive.CreateEntryFromFile(Path.Combine(temp, l.Name), $"ref/{l.Tfm}/{l.Name}");
}
PatchRefAssembly(extractedDllPath);

mainArchive.CreateEntryFromFile(extractedDllPath, $"ref/{lib.Tfm}/{lib.DllName}");
symbolsArchive.CreateEntryFromFile(extractedPdbPath, $"ref/{lib.Tfm}/{lib.PdbName}");
}
}

static ZipArchive OpenPackage(string packagePath)
=> new(File.Open(packagePath, FileMode.Open, FileAccess.ReadWrite), ZipArchiveMode.Update);

static ZipArchiveEntry[] GetLibEntries(ZipArchive archive, string extension)
=> archive.Entries
.Where(e => e.FullName.StartsWith("lib/", StringComparison.Ordinal)
&& e.FullName.EndsWith(extension, StringComparison.Ordinal))
.ToArray();
}
}
5 changes: 5 additions & 0 deletions src/Android/Avalonia.Android/AndroidInputMethod.cs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,11 @@ private void _client_SelectionChanged(object sender, EventArgs e)

private void OnSelectionChanged()
{
if (Client is null)
{
return;
}

var selection = Client.Selection;

_imm.UpdateSelection(_host, selection.Start, selection.End, selection.Start, selection.End);
Expand Down
4 changes: 2 additions & 2 deletions src/Avalonia.Controls/HotkeyManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -149,10 +149,10 @@ static HotKeyManager()
return;

var control = args.Sender as Control;
if (control is not IClickableControl)
if (control is not IClickableControl and not ICommandSource)
{
Logging.Logger.TryGet(Logging.LogEventLevel.Warning, Logging.LogArea.Control)?.Log(control,
$"The element {args.Sender.GetType().Name} does not implement IClickableControl and does not support binding a HotKey ({args.NewValue}).");
$"The element {args.Sender.GetType().Name} does not implement IClickableControl nor ICommandSource and does not support binding a HotKey ({args.NewValue}).");
return;
}

Expand Down
1 change: 1 addition & 0 deletions src/Avalonia.Controls/TopLevel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,7 @@ private protected virtual void HandleClosed()
Renderer.SceneInvalidated -= SceneInvalidated;
// We need to wait for the renderer to complete any in-flight operations
Renderer.Dispose();
StopRendering();

Debug.Assert(PlatformImpl != null);
// The PlatformImpl is completely invalid at this point
Expand Down
36 changes: 22 additions & 14 deletions src/Avalonia.X11/X11Window.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
using Avalonia.OpenGL.Egl;
using Avalonia.Platform;
using Avalonia.Platform.Storage;
using Avalonia.Rendering;
using Avalonia.Rendering.Composition;
using Avalonia.Threading;
using Avalonia.X11.Glx;
Expand All @@ -36,6 +35,7 @@ internal unsafe partial class X11Window : IWindowImpl, IPopupImpl, IXI2Client
{
private readonly AvaloniaX11Platform _platform;
private readonly bool _popup;
private readonly bool _overrideRedirect;
private readonly X11Info _x11;
private XConfigureEvent? _configure;
private PixelPoint? _configurePoint;
Expand Down Expand Up @@ -72,10 +72,11 @@ private enum XSyncState
WaitPaint
}

public X11Window(AvaloniaX11Platform platform, IWindowImpl? popupParent)
public X11Window(AvaloniaX11Platform platform, IWindowImpl? popupParent, bool overrideRedirect = false)
{
_platform = platform;
_popup = popupParent != null;
_overrideRedirect = _popup || overrideRedirect;
_x11 = platform.Info;
_mouse = new MouseDevice();
_touch = new TouchDevice();
Expand All @@ -92,7 +93,7 @@ public X11Window(AvaloniaX11Platform platform, IWindowImpl? popupParent)
| SetWindowValuemask.BackPixmap | SetWindowValuemask.BackingStore
| SetWindowValuemask.BitGravity | SetWindowValuemask.WinGravity;

if (_popup)
if (_overrideRedirect)
{
attr.override_redirect = 1;
valueMask |= SetWindowValuemask.OverrideRedirect;
Expand Down Expand Up @@ -155,7 +156,7 @@ public X11Window(AvaloniaX11Platform platform, IWindowImpl? popupParent)
else
_renderHandle = _handle;

Handle = new SurfacePlatformHandle(this);
Handle = new PlatformHandle(_handle, "XID");
_realSize = new PixelSize(defaultWidth, defaultHeight);
platform.Windows[_handle] = OnEvent;
XEventMask ignoredMask = XEventMask.SubstructureRedirectMask
Expand All @@ -165,15 +166,18 @@ public X11Window(AvaloniaX11Platform platform, IWindowImpl? popupParent)
ignoredMask |= platform.XI2.AddWindow(_handle, this);
var mask = new IntPtr(0xffffff ^ (int)ignoredMask);
XSelectInput(_x11.Display, _handle, mask);
var protocols = new[]
if (!_overrideRedirect)
{
_x11.Atoms.WM_DELETE_WINDOW
};
XSetWMProtocols(_x11.Display, _handle, protocols, protocols.Length);
XChangeProperty(_x11.Display, _handle, _x11.Atoms._NET_WM_WINDOW_TYPE, _x11.Atoms.XA_ATOM,
32, PropertyMode.Replace, new[] {_x11.Atoms._NET_WM_WINDOW_TYPE_NORMAL}, 1);
var protocols = new[]
{
_x11.Atoms.WM_DELETE_WINDOW
};
XSetWMProtocols(_x11.Display, _handle, protocols, protocols.Length);
XChangeProperty(_x11.Display, _handle, _x11.Atoms._NET_WM_WINDOW_TYPE, _x11.Atoms.XA_ATOM,
32, PropertyMode.Replace, new[] { _x11.Atoms._NET_WM_WINDOW_TYPE_NORMAL }, 1);

SetWmClass(_platform.Options.WmClass);
SetWmClass(_platform.Options.WmClass);
}

var surfaces = new List<object>
{
Expand All @@ -187,7 +191,7 @@ public X11Window(AvaloniaX11Platform platform, IWindowImpl? popupParent)
if (glx != null)
surfaces.Insert(0, new GlxGlPlatformSurface(new SurfaceInfo(this, _x11.DeferredDisplay, _handle, _renderHandle)));

surfaces.Add(Handle);
surfaces.Add(new SurfacePlatformHandle(this));

Surfaces = surfaces.ToArray();
UpdateMotifHints();
Expand Down Expand Up @@ -257,6 +261,8 @@ public PixelSize Size

private void UpdateMotifHints()
{
if(_overrideRedirect)
return;
var functions = MotifFunctions.Move | MotifFunctions.Close | MotifFunctions.Resize |
MotifFunctions.Minimize | MotifFunctions.Maximize;
var decorations = MotifDecorations.Menu | MotifDecorations.Title | MotifDecorations.Border |
Expand Down Expand Up @@ -286,6 +292,8 @@ private void UpdateMotifHints()

private void UpdateSizeHints(PixelSize? preResize)
{
if(_overrideRedirect)
return;
var min = _minMaxSize.minSize;
var max = _minMaxSize.maxSize;

Expand Down Expand Up @@ -507,7 +515,7 @@ private void OnEvent(ref XEvent ev)
}
UpdateImePosition();

if (changedSize && !updatedSizeViaScaling && !_popup)
if (changedSize && !updatedSizeViaScaling && !_overrideRedirect)
Resized?.Invoke(ClientSize, WindowResizeReason.Unspecified);

}, DispatcherPriority.AsyncRenderTargetResize);
Expand Down Expand Up @@ -984,7 +992,7 @@ private void Resize(Size clientSize, bool force, WindowResizeReason reason)
XConfigureResizeWindow(_x11.Display, _renderHandle, pixelSize);
XFlush(_x11.Display);

if (force || !_wasMappedAtLeastOnce || (_popup && needImmediatePopupResize))
if (force || !_wasMappedAtLeastOnce || (_overrideRedirect && needImmediatePopupResize))
{
_realSize = pixelSize;
Resized?.Invoke(ClientSize, reason);
Expand Down
1 change: 1 addition & 0 deletions src/Windows/Avalonia.Win32/DataObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ public Win32Com.IEnumFORMATETC Clone()


private IDataObject _wrapped;
public IDataObject Wrapped => _wrapped;

public DataObject(IDataObject wrapped)
{
Expand Down
2 changes: 1 addition & 1 deletion src/Windows/Avalonia.Win32/OleDropTarget.cs
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ public static IDataObject GetAvaloniaObjectFromCOM(Win32Com.IDataObject pDataObj

if (MicroComRuntime.TryUnwrapManagedObject(pDataObj) is DataObject dataObject)
{
return dataObject;
return dataObject.Wrapped;
}
return new OleDataObject(pDataObj);
}
Expand Down
Loading

0 comments on commit 8ab5a55

Please sign in to comment.