diff --git a/src/Avalonia.X11/X11Platform.cs b/src/Avalonia.X11/X11Platform.cs index 7043c60ae7..cc9737668d 100644 --- a/src/Avalonia.X11/X11Platform.cs +++ b/src/Avalonia.X11/X11Platform.cs @@ -277,7 +277,8 @@ namespace Avalonia // and sometimes attempts to use GLX might cause a segfault "llvmpipe" }; - public string WmClass { get; set; } = Assembly.GetEntryAssembly()?.GetName()?.Name ?? "AvaloniaApplication"; + + public string WmClass { get; set; } = Assembly.GetEntryAssembly()?.GetName()?.Name; /// /// Enables multitouch support. The default value is true. diff --git a/src/Avalonia.X11/X11Window.cs b/src/Avalonia.X11/X11Window.cs index 009ccb6159..7b34705b3b 100644 --- a/src/Avalonia.X11/X11Window.cs +++ b/src/Avalonia.X11/X11Window.cs @@ -168,8 +168,7 @@ namespace Avalonia.X11 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); - if (platform.Options.WmClass != null) - SetWmClass(platform.Options.WmClass); + SetWmClass(_platform.Options.WmClass); var surfaces = new List { @@ -1082,12 +1081,24 @@ namespace Avalonia.X11 public void SetWmClass(string wmClass) { - var data = Encoding.ASCII.GetBytes(wmClass); - fixed (void* pdata = data) + // See https://tronche.com/gui/x/icccm/sec-4.html#WM_CLASS + // We don't actually parse the application's command line, so we only use RESOURCE_NAME and argv[0] + var appId = Environment.GetEnvironmentVariable("RESOURCE_NAME") + ?? Process.GetCurrentProcess().ProcessName; + + var encodedAppId = Encoding.ASCII.GetBytes(appId); + var encodedWmClass = Encoding.ASCII.GetBytes(wmClass ?? appId); + + var hint = XAllocClassHint(); + fixed(byte* pAppId = encodedAppId) + fixed (byte* pWmClass = encodedWmClass) { - XChangeProperty(_x11.Display, _handle, _x11.Atoms.XA_WM_CLASS, _x11.Atoms.XA_STRING, 8, - PropertyMode.Replace, pdata, data.Length); + hint->res_name = pAppId; + hint->res_class = pWmClass; + XSetClassHint(_x11.Display, _handle, hint); } + + XFree(hint); } public void SetMinMaxSize(Size minSize, Size maxSize) diff --git a/src/Avalonia.X11/XLib.cs b/src/Avalonia.X11/XLib.cs index 464ec4f1c8..753d5f530c 100644 --- a/src/Avalonia.X11/XLib.cs +++ b/src/Avalonia.X11/XLib.cs @@ -109,6 +109,9 @@ namespace Avalonia.X11 [DllImport(libX11)] public static extern int XFree(IntPtr data); + + [DllImport(libX11)] + public static extern int XFree(void* data); [DllImport(libX11)] public static extern int XRaiseWindow(IntPtr display, IntPtr window); @@ -628,6 +631,12 @@ namespace Avalonia.X11 return XISelectEvents(display, window, emasks, devices.Count); } + + [DllImport(libX11)] + public static extern XClassHint* XAllocClassHint(); + + [DllImport(libX11)] + public static extern int XSetClassHint(IntPtr display, IntPtr window, XClassHint* class_hints); public struct XGeometry { @@ -639,6 +648,11 @@ namespace Avalonia.X11 public int bw; public int d; } + public struct XClassHint + { + public byte* res_name; + public byte* res_class; + } public struct XSyncValue { public int Hi; diff --git a/src/Skia/Avalonia.Skia/ImmutableBitmap.cs b/src/Skia/Avalonia.Skia/ImmutableBitmap.cs index 5628ae177c..a80f406989 100644 --- a/src/Skia/Avalonia.Skia/ImmutableBitmap.cs +++ b/src/Skia/Avalonia.Skia/ImmutableBitmap.cs @@ -57,7 +57,8 @@ namespace Avalonia.Skia public ImmutableBitmap(Stream stream, int decodeSize, bool horizontal, BitmapInterpolationMode interpolationMode) { using (var skStream = new SKManagedStream(stream)) - using (var codec = SKCodec.Create(skStream)) + using (var skData = SKData.Create(skStream)) + using (var codec = SKCodec.Create(skData)) { var info = codec.Info; diff --git a/src/Skia/Avalonia.Skia/WriteableBitmapImpl.cs b/src/Skia/Avalonia.Skia/WriteableBitmapImpl.cs index 506edf0627..80bfcc5973 100644 --- a/src/Skia/Avalonia.Skia/WriteableBitmapImpl.cs +++ b/src/Skia/Avalonia.Skia/WriteableBitmapImpl.cs @@ -4,7 +4,6 @@ using System.Threading; using Avalonia.Media.Imaging; using Avalonia.Platform; using Avalonia.Skia.Helpers; -using Avalonia.Media.Imaging; using SkiaSharp; namespace Avalonia.Skia @@ -25,8 +24,9 @@ namespace Avalonia.Skia public WriteableBitmapImpl(Stream stream) { using (var skiaStream = new SKManagedStream(stream)) + using (var skData = SKData.Create(skiaStream)) { - _bitmap = SKBitmap.Decode(skiaStream); + _bitmap = SKBitmap.Decode(skData); if (_bitmap == null) { @@ -41,7 +41,8 @@ namespace Avalonia.Skia public WriteableBitmapImpl(Stream stream, int decodeSize, bool horizontal, BitmapInterpolationMode interpolationMode) { using (var skStream = new SKManagedStream(stream)) - using (var codec = SKCodec.Create(skStream)) + using (var skData = SKData.Create(skStream)) + using (var codec = SKCodec.Create(skData)) { var info = codec.Info;