diff --git a/src/Avalonia.Base/Media/KnownColors.cs b/src/Avalonia.Base/Media/KnownColors.cs index 8f07b5f8ac..ae2fca5a60 100644 --- a/src/Avalonia.Base/Media/KnownColors.cs +++ b/src/Avalonia.Base/Media/KnownColors.cs @@ -1,10 +1,11 @@ using System; using System.Reflection; using System.Collections.Generic; +using Avalonia.SourceGenerator; namespace Avalonia.Media { - internal static class KnownColors + internal static partial class KnownColors { private static readonly IReadOnlyDictionary _knownColorNames; private static readonly IReadOnlyDictionary _knownColors; @@ -12,23 +13,25 @@ namespace Avalonia.Media private static readonly Dictionary _knownBrushes; #endif + [GenerateEnumValueDictionary()] + private static partial Dictionary GetKnownColors(); + static KnownColors() { var knownColorNames = new Dictionary(StringComparer.OrdinalIgnoreCase); var knownColors = new Dictionary(); - foreach (var field in typeof(KnownColor).GetRuntimeFields()) + foreach (var field in GetKnownColors()) { - if (field.FieldType != typeof(KnownColor)) continue; - var knownColor = (KnownColor)field.GetValue(null)!; + var knownColor = field.Value; if (knownColor == KnownColor.None) continue; - knownColorNames.Add(field.Name, knownColor); + knownColorNames.Add(field.Key, knownColor); // some known colors have the same value, so use the first if (!knownColors.ContainsKey((uint)knownColor)) { - knownColors.Add((uint)knownColor, field.Name); + knownColors.Add((uint)knownColor, field.Key); } } diff --git a/src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj b/src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj index dc9064b262..eef574d297 100644 --- a/src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj +++ b/src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj @@ -108,4 +108,5 @@ + diff --git a/src/Avalonia.X11/X11Atoms.cs b/src/Avalonia.X11/X11Atoms.cs index cfda68f9e8..424db94e0a 100644 --- a/src/Avalonia.X11/X11Atoms.cs +++ b/src/Avalonia.X11/X11Atoms.cs @@ -39,183 +39,176 @@ using static Avalonia.X11.XLib; namespace Avalonia.X11 { - internal class X11Atoms + internal partial class X11Atoms { private readonly IntPtr _display; // Our atoms - public readonly IntPtr AnyPropertyType = (IntPtr)0; - public readonly IntPtr XA_PRIMARY = (IntPtr)1; - public readonly IntPtr XA_SECONDARY = (IntPtr)2; - public readonly IntPtr XA_ARC = (IntPtr)3; - public readonly IntPtr XA_ATOM = (IntPtr)4; - public readonly IntPtr XA_BITMAP = (IntPtr)5; - public readonly IntPtr XA_CARDINAL = (IntPtr)6; - public readonly IntPtr XA_COLORMAP = (IntPtr)7; - public readonly IntPtr XA_CURSOR = (IntPtr)8; - public readonly IntPtr XA_CUT_BUFFER0 = (IntPtr)9; - public readonly IntPtr XA_CUT_BUFFER1 = (IntPtr)10; - public readonly IntPtr XA_CUT_BUFFER2 = (IntPtr)11; - public readonly IntPtr XA_CUT_BUFFER3 = (IntPtr)12; - public readonly IntPtr XA_CUT_BUFFER4 = (IntPtr)13; - public readonly IntPtr XA_CUT_BUFFER5 = (IntPtr)14; - public readonly IntPtr XA_CUT_BUFFER6 = (IntPtr)15; - public readonly IntPtr XA_CUT_BUFFER7 = (IntPtr)16; - public readonly IntPtr XA_DRAWABLE = (IntPtr)17; - public readonly IntPtr XA_FONT = (IntPtr)18; - public readonly IntPtr XA_INTEGER = (IntPtr)19; - public readonly IntPtr XA_PIXMAP = (IntPtr)20; - public readonly IntPtr XA_POINT = (IntPtr)21; - public readonly IntPtr XA_RECTANGLE = (IntPtr)22; - public readonly IntPtr XA_RESOURCE_MANAGER = (IntPtr)23; - public readonly IntPtr XA_RGB_COLOR_MAP = (IntPtr)24; - public readonly IntPtr XA_RGB_BEST_MAP = (IntPtr)25; - public readonly IntPtr XA_RGB_BLUE_MAP = (IntPtr)26; - public readonly IntPtr XA_RGB_DEFAULT_MAP = (IntPtr)27; - public readonly IntPtr XA_RGB_GRAY_MAP = (IntPtr)28; - public readonly IntPtr XA_RGB_GREEN_MAP = (IntPtr)29; - public readonly IntPtr XA_RGB_RED_MAP = (IntPtr)30; - public readonly IntPtr XA_STRING = (IntPtr)31; - public readonly IntPtr XA_VISUALID = (IntPtr)32; - public readonly IntPtr XA_WINDOW = (IntPtr)33; - public readonly IntPtr XA_WM_COMMAND = (IntPtr)34; - public readonly IntPtr XA_WM_HINTS = (IntPtr)35; - public readonly IntPtr XA_WM_CLIENT_MACHINE = (IntPtr)36; - public readonly IntPtr XA_WM_ICON_NAME = (IntPtr)37; - public readonly IntPtr XA_WM_ICON_SIZE = (IntPtr)38; - public readonly IntPtr XA_WM_NAME = (IntPtr)39; - public readonly IntPtr XA_WM_NORMAL_HINTS = (IntPtr)40; - public readonly IntPtr XA_WM_SIZE_HINTS = (IntPtr)41; - public readonly IntPtr XA_WM_ZOOM_HINTS = (IntPtr)42; - public readonly IntPtr XA_MIN_SPACE = (IntPtr)43; - public readonly IntPtr XA_NORM_SPACE = (IntPtr)44; - public readonly IntPtr XA_MAX_SPACE = (IntPtr)45; - public readonly IntPtr XA_END_SPACE = (IntPtr)46; - public readonly IntPtr XA_SUPERSCRIPT_X = (IntPtr)47; - public readonly IntPtr XA_SUPERSCRIPT_Y = (IntPtr)48; - public readonly IntPtr XA_SUBSCRIPT_X = (IntPtr)49; - public readonly IntPtr XA_SUBSCRIPT_Y = (IntPtr)50; - public readonly IntPtr XA_UNDERLINE_POSITION = (IntPtr)51; - public readonly IntPtr XA_UNDERLINE_THICKNESS = (IntPtr)52; - public readonly IntPtr XA_STRIKEOUT_ASCENT = (IntPtr)53; - public readonly IntPtr XA_STRIKEOUT_DESCENT = (IntPtr)54; - public readonly IntPtr XA_ITALIC_ANGLE = (IntPtr)55; - public readonly IntPtr XA_X_HEIGHT = (IntPtr)56; - public readonly IntPtr XA_QUAD_WIDTH = (IntPtr)57; - public readonly IntPtr XA_WEIGHT = (IntPtr)58; - public readonly IntPtr XA_POINT_SIZE = (IntPtr)59; - public readonly IntPtr XA_RESOLUTION = (IntPtr)60; - public readonly IntPtr XA_COPYRIGHT = (IntPtr)61; - public readonly IntPtr XA_NOTICE = (IntPtr)62; - public readonly IntPtr XA_FONT_NAME = (IntPtr)63; - public readonly IntPtr XA_FAMILY_NAME = (IntPtr)64; - public readonly IntPtr XA_FULL_NAME = (IntPtr)65; - public readonly IntPtr XA_CAP_HEIGHT = (IntPtr)66; - public readonly IntPtr XA_WM_CLASS = (IntPtr)67; - public readonly IntPtr XA_WM_TRANSIENT_FOR = (IntPtr)68; + public IntPtr AnyPropertyType = (IntPtr)0; + public IntPtr XA_PRIMARY = (IntPtr)1; + public IntPtr XA_SECONDARY = (IntPtr)2; + public IntPtr XA_ARC = (IntPtr)3; + public IntPtr XA_ATOM = (IntPtr)4; + public IntPtr XA_BITMAP = (IntPtr)5; + public IntPtr XA_CARDINAL = (IntPtr)6; + public IntPtr XA_COLORMAP = (IntPtr)7; + public IntPtr XA_CURSOR = (IntPtr)8; + public IntPtr XA_CUT_BUFFER0 = (IntPtr)9; + public IntPtr XA_CUT_BUFFER1 = (IntPtr)10; + public IntPtr XA_CUT_BUFFER2 = (IntPtr)11; + public IntPtr XA_CUT_BUFFER3 = (IntPtr)12; + public IntPtr XA_CUT_BUFFER4 = (IntPtr)13; + public IntPtr XA_CUT_BUFFER5 = (IntPtr)14; + public IntPtr XA_CUT_BUFFER6 = (IntPtr)15; + public IntPtr XA_CUT_BUFFER7 = (IntPtr)16; + public IntPtr XA_DRAWABLE = (IntPtr)17; + public IntPtr XA_FONT = (IntPtr)18; + public IntPtr XA_INTEGER = (IntPtr)19; + public IntPtr XA_PIXMAP = (IntPtr)20; + public IntPtr XA_POINT = (IntPtr)21; + public IntPtr XA_RECTANGLE = (IntPtr)22; + public IntPtr XA_RESOURCE_MANAGER = (IntPtr)23; + public IntPtr XA_RGB_COLOR_MAP = (IntPtr)24; + public IntPtr XA_RGB_BEST_MAP = (IntPtr)25; + public IntPtr XA_RGB_BLUE_MAP = (IntPtr)26; + public IntPtr XA_RGB_DEFAULT_MAP = (IntPtr)27; + public IntPtr XA_RGB_GRAY_MAP = (IntPtr)28; + public IntPtr XA_RGB_GREEN_MAP = (IntPtr)29; + public IntPtr XA_RGB_RED_MAP = (IntPtr)30; + public IntPtr XA_STRING = (IntPtr)31; + public IntPtr XA_VISUALID = (IntPtr)32; + public IntPtr XA_WINDOW = (IntPtr)33; + public IntPtr XA_WM_COMMAND = (IntPtr)34; + public IntPtr XA_WM_HINTS = (IntPtr)35; + public IntPtr XA_WM_CLIENT_MACHINE = (IntPtr)36; + public IntPtr XA_WM_ICON_NAME = (IntPtr)37; + public IntPtr XA_WM_ICON_SIZE = (IntPtr)38; + public IntPtr XA_WM_NAME = (IntPtr)39; + public IntPtr XA_WM_NORMAL_HINTS = (IntPtr)40; + public IntPtr XA_WM_SIZE_HINTS = (IntPtr)41; + public IntPtr XA_WM_ZOOM_HINTS = (IntPtr)42; + public IntPtr XA_MIN_SPACE = (IntPtr)43; + public IntPtr XA_NORM_SPACE = (IntPtr)44; + public IntPtr XA_MAX_SPACE = (IntPtr)45; + public IntPtr XA_END_SPACE = (IntPtr)46; + public IntPtr XA_SUPERSCRIPT_X = (IntPtr)47; + public IntPtr XA_SUPERSCRIPT_Y = (IntPtr)48; + public IntPtr XA_SUBSCRIPT_X = (IntPtr)49; + public IntPtr XA_SUBSCRIPT_Y = (IntPtr)50; + public IntPtr XA_UNDERLINE_POSITION = (IntPtr)51; + public IntPtr XA_UNDERLINE_THICKNESS = (IntPtr)52; + public IntPtr XA_STRIKEOUT_ASCENT = (IntPtr)53; + public IntPtr XA_STRIKEOUT_DESCENT = (IntPtr)54; + public IntPtr XA_ITALIC_ANGLE = (IntPtr)55; + public IntPtr XA_X_HEIGHT = (IntPtr)56; + public IntPtr XA_QUAD_WIDTH = (IntPtr)57; + public IntPtr XA_WEIGHT = (IntPtr)58; + public IntPtr XA_POINT_SIZE = (IntPtr)59; + public IntPtr XA_RESOLUTION = (IntPtr)60; + public IntPtr XA_COPYRIGHT = (IntPtr)61; + public IntPtr XA_NOTICE = (IntPtr)62; + public IntPtr XA_FONT_NAME = (IntPtr)63; + public IntPtr XA_FAMILY_NAME = (IntPtr)64; + public IntPtr XA_FULL_NAME = (IntPtr)65; + public IntPtr XA_CAP_HEIGHT = (IntPtr)66; + public IntPtr XA_WM_CLASS = (IntPtr)67; + public IntPtr XA_WM_TRANSIENT_FOR = (IntPtr)68; - public readonly IntPtr EDID; + public IntPtr EDID; - public readonly IntPtr WM_PROTOCOLS; - public readonly IntPtr WM_DELETE_WINDOW; - public readonly IntPtr WM_TAKE_FOCUS; - public readonly IntPtr _NET_SUPPORTED; - public readonly IntPtr _NET_CLIENT_LIST; - public readonly IntPtr _NET_NUMBER_OF_DESKTOPS; - public readonly IntPtr _NET_DESKTOP_GEOMETRY; - public readonly IntPtr _NET_DESKTOP_VIEWPORT; - public readonly IntPtr _NET_CURRENT_DESKTOP; - public readonly IntPtr _NET_DESKTOP_NAMES; - public readonly IntPtr _NET_ACTIVE_WINDOW; - public readonly IntPtr _NET_WORKAREA; - public readonly IntPtr _NET_SUPPORTING_WM_CHECK; - public readonly IntPtr _NET_VIRTUAL_ROOTS; - public readonly IntPtr _NET_DESKTOP_LAYOUT; - public readonly IntPtr _NET_SHOWING_DESKTOP; - public readonly IntPtr _NET_CLOSE_WINDOW; - public readonly IntPtr _NET_MOVERESIZE_WINDOW; - public readonly IntPtr _NET_WM_MOVERESIZE; - public readonly IntPtr _NET_RESTACK_WINDOW; - public readonly IntPtr _NET_REQUEST_FRAME_EXTENTS; - public readonly IntPtr _NET_WM_NAME; - public readonly IntPtr _NET_WM_VISIBLE_NAME; - public readonly IntPtr _NET_WM_ICON_NAME; - public readonly IntPtr _NET_WM_VISIBLE_ICON_NAME; - public readonly IntPtr _NET_WM_DESKTOP; - public readonly IntPtr _NET_WM_WINDOW_TYPE; - public readonly IntPtr _NET_WM_STATE; - public readonly IntPtr _NET_WM_ALLOWED_ACTIONS; - public readonly IntPtr _NET_WM_STRUT; - public readonly IntPtr _NET_WM_STRUT_PARTIAL; - public readonly IntPtr _NET_WM_ICON_GEOMETRY; - public readonly IntPtr _NET_WM_ICON; - public readonly IntPtr _NET_WM_PID; - public readonly IntPtr _NET_WM_HANDLED_ICONS; - public readonly IntPtr _NET_WM_USER_TIME; - public readonly IntPtr _NET_FRAME_EXTENTS; - public readonly IntPtr _NET_WM_PING; - public readonly IntPtr _NET_WM_SYNC_REQUEST; - public readonly IntPtr _NET_WM_SYNC_REQUEST_COUNTER; - public readonly IntPtr _NET_SYSTEM_TRAY_S; - public readonly IntPtr _NET_SYSTEM_TRAY_ORIENTATION; - public readonly IntPtr _NET_SYSTEM_TRAY_OPCODE; - public readonly IntPtr _NET_WM_STATE_MAXIMIZED_HORZ; - public readonly IntPtr _NET_WM_STATE_MAXIMIZED_VERT; - public readonly IntPtr _NET_WM_STATE_FULLSCREEN; - public readonly IntPtr _XEMBED; - public readonly IntPtr _XEMBED_INFO; - public readonly IntPtr _MOTIF_WM_HINTS; - public readonly IntPtr _NET_WM_STATE_SKIP_TASKBAR; - public readonly IntPtr _NET_WM_STATE_ABOVE; - public readonly IntPtr _NET_WM_STATE_MODAL; - public readonly IntPtr _NET_WM_STATE_HIDDEN; - public readonly IntPtr _NET_WM_CONTEXT_HELP; - public readonly IntPtr _NET_WM_WINDOW_OPACITY; - public readonly IntPtr _NET_WM_WINDOW_TYPE_DESKTOP; - public readonly IntPtr _NET_WM_WINDOW_TYPE_DOCK; - public readonly IntPtr _NET_WM_WINDOW_TYPE_TOOLBAR; - public readonly IntPtr _NET_WM_WINDOW_TYPE_MENU; - public readonly IntPtr _NET_WM_WINDOW_TYPE_UTILITY; - public readonly IntPtr _NET_WM_WINDOW_TYPE_SPLASH; - public readonly IntPtr _NET_WM_WINDOW_TYPE_DIALOG; - public readonly IntPtr _NET_WM_WINDOW_TYPE_NORMAL; - public readonly IntPtr CLIPBOARD; - public readonly IntPtr CLIPBOARD_MANAGER; - public readonly IntPtr SAVE_TARGETS; - public readonly IntPtr MULTIPLE; - public readonly IntPtr PRIMARY; - public readonly IntPtr OEMTEXT; - public readonly IntPtr UNICODETEXT; - public readonly IntPtr TARGETS; - public readonly IntPtr UTF8_STRING; - public readonly IntPtr UTF16_STRING; - public readonly IntPtr ATOM_PAIR; - public readonly IntPtr MANAGER; - public readonly IntPtr _KDE_NET_WM_BLUR_BEHIND_REGION; - public readonly IntPtr INCR; + public IntPtr WM_PROTOCOLS; + public IntPtr WM_DELETE_WINDOW; + public IntPtr WM_TAKE_FOCUS; + public IntPtr _NET_SUPPORTED; + public IntPtr _NET_CLIENT_LIST; + public IntPtr _NET_NUMBER_OF_DESKTOPS; + public IntPtr _NET_DESKTOP_GEOMETRY; + public IntPtr _NET_DESKTOP_VIEWPORT; + public IntPtr _NET_CURRENT_DESKTOP; + public IntPtr _NET_DESKTOP_NAMES; + public IntPtr _NET_ACTIVE_WINDOW; + public IntPtr _NET_WORKAREA; + public IntPtr _NET_SUPPORTING_WM_CHECK; + public IntPtr _NET_VIRTUAL_ROOTS; + public IntPtr _NET_DESKTOP_LAYOUT; + public IntPtr _NET_SHOWING_DESKTOP; + public IntPtr _NET_CLOSE_WINDOW; + public IntPtr _NET_MOVERESIZE_WINDOW; + public IntPtr _NET_WM_MOVERESIZE; + public IntPtr _NET_RESTACK_WINDOW; + public IntPtr _NET_REQUEST_FRAME_EXTENTS; + public IntPtr _NET_WM_NAME; + public IntPtr _NET_WM_VISIBLE_NAME; + public IntPtr _NET_WM_ICON_NAME; + public IntPtr _NET_WM_VISIBLE_ICON_NAME; + public IntPtr _NET_WM_DESKTOP; + public IntPtr _NET_WM_WINDOW_TYPE; + public IntPtr _NET_WM_STATE; + public IntPtr _NET_WM_ALLOWED_ACTIONS; + public IntPtr _NET_WM_STRUT; + public IntPtr _NET_WM_STRUT_PARTIAL; + public IntPtr _NET_WM_ICON_GEOMETRY; + public IntPtr _NET_WM_ICON; + public IntPtr _NET_WM_PID; + public IntPtr _NET_WM_HANDLED_ICONS; + public IntPtr _NET_WM_USER_TIME; + public IntPtr _NET_FRAME_EXTENTS; + public IntPtr _NET_WM_PING; + public IntPtr _NET_WM_SYNC_REQUEST; + public IntPtr _NET_WM_SYNC_REQUEST_COUNTER; + public IntPtr _NET_SYSTEM_TRAY_S; + public IntPtr _NET_SYSTEM_TRAY_ORIENTATION; + public IntPtr _NET_SYSTEM_TRAY_OPCODE; + public IntPtr _NET_WM_STATE_MAXIMIZED_HORZ; + public IntPtr _NET_WM_STATE_MAXIMIZED_VERT; + public IntPtr _NET_WM_STATE_FULLSCREEN; + public IntPtr _XEMBED; + public IntPtr _XEMBED_INFO; + public IntPtr _MOTIF_WM_HINTS; + public IntPtr _NET_WM_STATE_SKIP_TASKBAR; + public IntPtr _NET_WM_STATE_ABOVE; + public IntPtr _NET_WM_STATE_MODAL; + public IntPtr _NET_WM_STATE_HIDDEN; + public IntPtr _NET_WM_CONTEXT_HELP; + public IntPtr _NET_WM_WINDOW_OPACITY; + public IntPtr _NET_WM_WINDOW_TYPE_DESKTOP; + public IntPtr _NET_WM_WINDOW_TYPE_DOCK; + public IntPtr _NET_WM_WINDOW_TYPE_TOOLBAR; + public IntPtr _NET_WM_WINDOW_TYPE_MENU; + public IntPtr _NET_WM_WINDOW_TYPE_UTILITY; + public IntPtr _NET_WM_WINDOW_TYPE_SPLASH; + public IntPtr _NET_WM_WINDOW_TYPE_DIALOG; + public IntPtr _NET_WM_WINDOW_TYPE_NORMAL; + public IntPtr CLIPBOARD; + public IntPtr CLIPBOARD_MANAGER; + public IntPtr SAVE_TARGETS; + public IntPtr MULTIPLE; + public IntPtr PRIMARY; + public IntPtr OEMTEXT; + public IntPtr UNICODETEXT; + public IntPtr TARGETS; + public IntPtr UTF8_STRING; + public IntPtr UTF16_STRING; + public IntPtr ATOM_PAIR; + public IntPtr MANAGER; + public IntPtr _KDE_NET_WM_BLUR_BEHIND_REGION; + public IntPtr INCR; private readonly Dictionary _namesToAtoms = new Dictionary(); private readonly Dictionary _atomsToNames = new Dictionary(); public X11Atoms(IntPtr display) { _display = display; + PopulateAtoms(display); + } - // make sure this array stays in sync with the statements below - - var fields = typeof(X11Atoms).GetFields() - .Where(f => f.FieldType == typeof(IntPtr) && (IntPtr)f.GetValue(this) == IntPtr.Zero).ToArray(); - var atomNames = fields.Select(f => f.Name).ToArray(); - - IntPtr[] atoms = new IntPtr [atomNames.Length]; - ; - - XInternAtoms(display, atomNames, atomNames.Length, true, atoms); - - for (var c = 0; c < fields.Length; c++) + private void InitAtom(ref IntPtr field, string name, IntPtr value) + { + if (value != IntPtr.Zero) { - _namesToAtoms[fields[c].Name] = atoms[c]; - _atomsToNames[atoms[c]] = fields[c].Name; - fields[c].SetValue(this, atoms[c]); + field = value; + _namesToAtoms[name] = value; + _atomsToNames[value] = name; } } diff --git a/src/Avalonia.X11/X11CursorFactory.cs b/src/Avalonia.X11/X11CursorFactory.cs index 60f035cd7e..6041b53a62 100644 --- a/src/Avalonia.X11/X11CursorFactory.cs +++ b/src/Avalonia.X11/X11CursorFactory.cs @@ -5,13 +5,14 @@ using System.Runtime.InteropServices; using Avalonia.Controls.Platform.Surfaces; using Avalonia.Input; using Avalonia.Platform; +using Avalonia.SourceGenerator; using Avalonia.Utilities; #nullable enable namespace Avalonia.X11 { - class X11CursorFactory : ICursorFactory + partial class X11CursorFactory : ICursorFactory { private static readonly byte[] NullCursorData = new byte[] { 0 }; @@ -48,11 +49,14 @@ namespace Avalonia.X11 {StandardCursorType.TopRightCorner, CursorFontShape.XC_top_right_corner}, }; + [GenerateEnumValueList] + private static partial CursorFontShape[] GetAllCursorShapes(); + public X11CursorFactory(IntPtr display) { _display = display; _nullCursor = GetNullCursor(display); - _cursors = Enum.GetValues(typeof(CursorFontShape)).Cast() + _cursors = GetAllCursorShapes() .ToDictionary(id => id, id => XLib.XCreateFontCursor(_display, id)); } diff --git a/src/Avalonia.X11/X11Platform.cs b/src/Avalonia.X11/X11Platform.cs index cc9737668d..81c2a69aac 100644 --- a/src/Avalonia.X11/X11Platform.cs +++ b/src/Avalonia.X11/X11Platform.cs @@ -278,7 +278,8 @@ namespace Avalonia "llvmpipe" }; - public string WmClass { get; set; } = Assembly.GetEntryAssembly()?.GetName()?.Name; + + public string WmClass { get; set; } /// /// Enables multitouch support. The default value is true. @@ -287,6 +288,18 @@ namespace Avalonia /// Multitouch allows a surface (a touchpad or touchscreen) to recognize the presence of more than one point of contact with the surface at the same time. /// public bool? EnableMultiTouch { get; set; } = true; + + public X11PlatformOptions() + { + try + { + WmClass = Assembly.GetEntryAssembly()?.GetName()?.Name; + } + catch + { + // + } + } } public static class AvaloniaX11PlatformExtensions { diff --git a/src/Shared/SourceGeneratorAttributes.cs b/src/Shared/SourceGeneratorAttributes.cs index ac7c82c469..3f00fbef57 100644 --- a/src/Shared/SourceGeneratorAttributes.cs +++ b/src/Shared/SourceGeneratorAttributes.cs @@ -38,4 +38,12 @@ namespace Avalonia.SourceGenerator } } + + internal class GenerateEnumValueDictionaryAttribute : Attribute + { + } + + internal class GenerateEnumValueListAttribute : Attribute + { + } } diff --git a/src/tools/DevGenerators/EnumMemberDictionaryGenerator.cs b/src/tools/DevGenerators/EnumMemberDictionaryGenerator.cs new file mode 100644 index 0000000000..42612c7ce0 --- /dev/null +++ b/src/tools/DevGenerators/EnumMemberDictionaryGenerator.cs @@ -0,0 +1,94 @@ +using System.IO; +using System.Linq; +using System.Text; +using Generator; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace DevGenerators; + +[Generator(LanguageNames.CSharp)] +public class EnumMemberDictionaryGenerator : IIncrementalGenerator +{ + const string DictionaryAttributeFullName = "global::Avalonia.SourceGenerator.GenerateEnumValueDictionaryAttribute"; + const string ListAttributeFullName = "global::Avalonia.SourceGenerator.GenerateEnumValueListAttribute"; + + public void Initialize(IncrementalGeneratorInitializationContext context) + { + var allMethodsWithAttributes = context.SyntaxProvider + .CreateSyntaxProvider( + static (s, _) => s is MethodDeclarationSyntax + { + AttributeLists.Count: > 0, + } md && md.Modifiers.Any(m=>m.IsKind(SyntaxKind.PartialKeyword)), + static (context, _) => + (IMethodSymbol)context.SemanticModel.GetDeclaredSymbol(context.Node)!); + + var all = allMethodsWithAttributes + .Where(s => + s.HasAttributeWithFullyQualifiedName(DictionaryAttributeFullName) + || s.HasAttributeWithFullyQualifiedName(ListAttributeFullName) + ).Collect(); + context.RegisterSourceOutput(all, static (context, methods) => + { + foreach (var typeGroup in methods.GroupBy(f => f.ContainingType)) + { + var classBuilder = new StringBuilder(); + if (typeGroup.Key.ContainingNamespace != null) + classBuilder + .AppendLine("using System;") + .Append("namespace ") + .Append(typeGroup.Key.ContainingNamespace) + .AppendLine(";"); + classBuilder + .Append("partial class ") + .AppendLine(typeGroup.Key.Name) + .AppendLine("{"); + + foreach (var method in typeGroup) + { + var namedReturn = method.ReturnType as INamedTypeSymbol; + var arrayReturn = method.ReturnType as IArrayTypeSymbol; + + if ((namedReturn != null && namedReturn.Arity > 0) || arrayReturn != null) + { + ITypeSymbol enumType = namedReturn != null + ? namedReturn.TypeArguments.Last() + : arrayReturn!.ElementType; + + var isDic = method.HasAttributeWithFullyQualifiedName(DictionaryAttributeFullName); + + classBuilder + .Pad(1) + .Append("private static partial " + method.ReturnType + " " + method.Name + "()") + .AppendLine().Pad(4).Append(" => new ").Append(method.ReturnType).AppendLine("{"); + foreach (var member in enumType.GetMembers()) + { + if (member.Name == ".ctor") + continue; + + if (isDic) + classBuilder.Pad(2) + .Append("{\"") + .Append(member.Name) + .Append("\", ") + .Append(member.ToString()) + .AppendLine("},"); + else + classBuilder.Pad(2).Append(member.ToString()).AppendLine(","); + } + + classBuilder.Pad(1).AppendLine("};"); + } + } + classBuilder.AppendLine("}"); + + context.AddSource(typeGroup.Key.GetFullyQualifiedName().Replace(":", ""), classBuilder.ToString()); + } + }); + + + } + +} \ No newline at end of file diff --git a/src/tools/DevGenerators/X11AtomsGenerator.cs b/src/tools/DevGenerators/X11AtomsGenerator.cs new file mode 100644 index 0000000000..daf003c4c4 --- /dev/null +++ b/src/tools/DevGenerators/X11AtomsGenerator.cs @@ -0,0 +1,73 @@ +using System.IO; +using System.Linq; +using System.Text; +using Generator; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace DevGenerators; + +[Generator(LanguageNames.CSharp)] +public class X11AtomsGenerator : IIncrementalGenerator +{ + public void Initialize(IncrementalGeneratorInitializationContext context) + { + var x11AtomsClasses = context.SyntaxProvider + .CreateSyntaxProvider( + static (s, _) => s is ClassDeclarationSyntax + { + Identifier.Text: "X11Atoms" + }, + static (context, _) => + (INamedTypeSymbol)context.SemanticModel.GetDeclaredSymbol(context.Node)!); + + var all = x11AtomsClasses.Collect(); + context.RegisterSourceOutput(all, static (context, classes) => + { + foreach (var cl in classes) + { + var classBuilder = new StringBuilder(); + if (cl.ContainingNamespace != null) + classBuilder + .AppendLine("using System;") + .AppendLine("using static Avalonia.X11.XLib;") + .Append("namespace ") + .Append(cl.ContainingNamespace) + .AppendLine(";"); + classBuilder + .Append("partial class ") + .AppendLine(cl.Name) + .AppendLine("{"); + + var fields = cl.GetMembers().OfType() + .Where(f => f.Type.Name == "IntPtr" + && f.DeclaredAccessibility == Accessibility.Public).ToList(); + + classBuilder.Pad(1).AppendLine("private void PopulateAtoms(IntPtr display)").Pad(1).AppendLine("{"); + classBuilder.Pad(2).Append("var atoms = new IntPtr[").Append(fields.Count).AppendLine("];"); + classBuilder.Pad(2).Append("var atomNames = new string[").Append(fields.Count).AppendLine("] {"); + + + for (int c = 0; c < fields.Count; c++) + classBuilder.Pad(3).Append("\"").Append(fields[c].Name).AppendLine("\","); + classBuilder.Pad(2).AppendLine("};"); + + classBuilder.Pad(2).AppendLine("XInternAtoms(display, atomNames, atomNames.Length, true, atoms);"); + + for (int c = 0; c < fields.Count; c++) + classBuilder.Pad(2).Append("InitAtom(ref ").Append(fields[c].Name).Append(", \"") + .Append(fields[c].Name).Append("\", atoms[").Append(c).AppendLine("]);"); + + + classBuilder.Pad(1).AppendLine("}"); + classBuilder.AppendLine("}"); + + context.AddSource(cl.GetFullyQualifiedName().Replace(":", ""), classBuilder.ToString()); + } + }); + + + } + +} \ No newline at end of file