diff --git a/samples/ControlCatalog.NetCore/Program.cs b/samples/ControlCatalog.NetCore/Program.cs index d98a068d84..b1bacc6483 100644 --- a/samples/ControlCatalog.NetCore/Program.cs +++ b/samples/ControlCatalog.NetCore/Program.cs @@ -115,10 +115,6 @@ namespace ControlCatalog.NetCore UseDBusMenu = true, EnableIme = true }) - .With(new Win32PlatformOptions - { - EnableMultitouch = true - }) .UseSkia() .AfterSetup(builder => { diff --git a/samples/ControlCatalog/Pages/PointersPage.xaml.cs b/samples/ControlCatalog/Pages/PointersPage.xaml.cs index b9f08d8887..16d7ecceb5 100644 --- a/samples/ControlCatalog/Pages/PointersPage.xaml.cs +++ b/samples/ControlCatalog/Pages/PointersPage.xaml.cs @@ -62,7 +62,7 @@ Position: ??? ???"; e.Pointer.Capture(null); e.Handled = true; } - else + else if (e.Pointer.Captured is not null) { throw new InvalidOperationException("How?"); } diff --git a/src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs b/src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs index 5343b57251..33501ece06 100644 --- a/src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs +++ b/src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs @@ -47,18 +47,6 @@ namespace Avalonia.Android } } - [Obsolete("deprecated")] - public override void Invalidate(global::Android.Graphics.Rect dirty) - { - Invalidate(); - } - - [Obsolete("deprecated")] - public override void Invalidate(int l, int t, int r, int b) - { - Invalidate(); - } - public void SurfaceChanged(ISurfaceHolder holder, Format format, int width, int height) { Log.Info("AVALONIA", "Surface Changed"); diff --git a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs index dc74214170..17a0d6b63a 100644 --- a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs +++ b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; + using Android.Content; using Android.Graphics; using Android.Views; @@ -30,7 +31,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform private readonly IFramebufferPlatformSurface _framebuffer; private readonly AndroidKeyboardEventsHelper _keyboardHelper; - private readonly AndroidTouchEventsHelper _touchHelper; + private readonly AndroidMotionEventsHelper _pointerHelper; private readonly ITextInputMethodImpl _textInputMethod; private ViewImpl _view; @@ -39,8 +40,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform _view = new ViewImpl(avaloniaView.Context, this, placeOnTop); _textInputMethod = new AndroidInputMethod(_view); _keyboardHelper = new AndroidKeyboardEventsHelper(this); - _touchHelper = new AndroidTouchEventsHelper(this, () => InputRoot, - GetAvaloniaPointFromEvent); + _pointerHelper = new AndroidMotionEventsHelper(this); _gl = GlPlatformSurface.TryCreate(this); _framebuffer = new FramebufferManager(this); @@ -160,10 +160,19 @@ namespace Avalonia.Android.Platform.SkiaPlatform _tl.Draw(); } + protected override bool DispatchGenericPointerEvent(MotionEvent e) + { + bool callBase; + bool? result = _tl._pointerHelper.DispatchMotionEvent(e, out callBase); + bool baseResult = callBase ? base.DispatchGenericPointerEvent(e) : false; + + return result != null ? result.Value : baseResult; + } + public override bool DispatchTouchEvent(MotionEvent e) { bool callBase; - bool? result = _tl._touchHelper.DispatchTouchEvent(e, out callBase); + bool? result = _tl._pointerHelper.DispatchMotionEvent(e, out callBase); bool baseResult = callBase ? base.DispatchTouchEvent(e) : false; return result != null ? result.Value : baseResult; diff --git a/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidMotionEventsHelper.cs b/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidMotionEventsHelper.cs new file mode 100644 index 0000000000..ce385ebe34 --- /dev/null +++ b/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidMotionEventsHelper.cs @@ -0,0 +1,251 @@ +using System; +using System.Collections.Generic; + +using Android.Views; + +using Avalonia.Android.Platform.SkiaPlatform; +using Avalonia.Collections.Pooled; +using Avalonia.Input; +using Avalonia.Input.Raw; + +#nullable enable + +namespace Avalonia.Android.Platform.Specific.Helpers +{ + internal class AndroidMotionEventsHelper : IDisposable + { + private static readonly PooledList s_intermediatePointsPooledList = new(ClearMode.Never); + private static readonly float s_radiansToDegree = (float)(180f * Math.PI); + private readonly TouchDevice _touchDevice; + private readonly MouseDevice _mouseDevice; + private readonly PenDevice _penDevice; + private readonly TopLevelImpl _view; + private bool _disposed; + + public AndroidMotionEventsHelper(TopLevelImpl view) + { + _touchDevice = new TouchDevice(); + _penDevice = new PenDevice(); + _mouseDevice = new MouseDevice(); + _view = view; + } + + public bool? DispatchMotionEvent(MotionEvent e, out bool callBase) + { + callBase = true; + if (_disposed) + { + return null; + } + + var eventTime = (ulong)DateTime.Now.Millisecond; + var inputRoot = _view.InputRoot; + var actionMasked = e.ActionMasked; + var modifiers = GetModifiers(e.MetaState, e.ButtonState); + + if (actionMasked == MotionEventActions.Move) + { + for (int index = 0; index < e.PointerCount; index++) + { + var toolType = e.GetToolType(index); + var device = GetDevice(toolType); + var eventType = toolType == MotionEventToolType.Finger ? RawPointerEventType.TouchUpdate : RawPointerEventType.Move; + var point = CreatePoint(e, index); + modifiers |= GetToolModifiers(toolType); + + // ButtonState reports only mouse buttons, but not touch or stylus pointer. + if (toolType != MotionEventToolType.Mouse) + { + modifiers |= RawInputModifiers.LeftMouseButton; + } + + var args = new RawTouchEventArgs(device, eventTime, inputRoot, eventType, point, modifiers, e.GetPointerId(index)) + { + IntermediatePoints = new Lazy?>(() => + { + var site = e.HistorySize; + s_intermediatePointsPooledList.Clear(); + s_intermediatePointsPooledList.Capacity = site; + + for (int pos = 0; pos < site; pos++) + { + s_intermediatePointsPooledList.Add(CreateHistoricalPoint(e, index, pos)); + } + + return s_intermediatePointsPooledList; + }) + }; + _view.Input(args); + } + } + else + { + var index = e.ActionIndex; + var toolType = e.GetToolType(index); + var device = GetDevice(toolType); + modifiers |= GetToolModifiers(toolType); + var point = CreatePoint(e, index); + + if (actionMasked == MotionEventActions.Scroll && toolType == MotionEventToolType.Mouse) + { + var delta = new Vector(e.GetAxisValue(Axis.Hscroll), e.GetAxisValue(Axis.Vscroll)); + var args = new RawMouseWheelEventArgs(device, eventTime, inputRoot, point.Position, delta, RawInputModifiers.None); + _view.Input(args); + } + else + { + var eventType = GetActionType(e, actionMasked, toolType); + if (eventType >= 0) + { + var args = new RawTouchEventArgs(device, eventTime, inputRoot, eventType, point, modifiers, e.GetPointerId(index)); + _view.Input(args); + } + } + } + + return true; + } + + private static RawInputModifiers GetModifiers(MetaKeyStates metaState, MotionEventButtonState buttonState) + { + var modifiers = RawInputModifiers.None; + if (metaState.HasAnyFlag(MetaKeyStates.ShiftOn)) + { + modifiers |= RawInputModifiers.Shift; + } + if (metaState.HasAnyFlag(MetaKeyStates.CtrlOn)) + { + modifiers |= RawInputModifiers.Control; + } + if (metaState.HasAnyFlag(MetaKeyStates.AltOn)) + { + modifiers |= RawInputModifiers.Alt; + } + if (metaState.HasAnyFlag(MetaKeyStates.MetaOn)) + { + modifiers |= RawInputModifiers.Meta; + } + if (buttonState.HasAnyFlag(MotionEventButtonState.Primary)) + { + modifiers |= RawInputModifiers.LeftMouseButton; + } + if (buttonState.HasAnyFlag(MotionEventButtonState.Secondary)) + { + modifiers |= RawInputModifiers.RightMouseButton; + } + if (buttonState.HasAnyFlag(MotionEventButtonState.Tertiary)) + { + modifiers |= RawInputModifiers.MiddleMouseButton; + } + if (buttonState.HasAnyFlag(MotionEventButtonState.Back)) + { + modifiers |= RawInputModifiers.XButton1MouseButton; + } + if (buttonState.HasAnyFlag(MotionEventButtonState.Forward)) + { + modifiers |= RawInputModifiers.XButton2MouseButton; + } + if (buttonState.HasAnyFlag(MotionEventButtonState.StylusPrimary)) + { + modifiers |= RawInputModifiers.PenBarrelButton; + } + return modifiers; + } + +#pragma warning disable CA1416 // Validate platform compatibility + private static RawPointerEventType GetActionType(MotionEvent e, MotionEventActions actionMasked, MotionEventToolType toolType) + { + var isTouch = toolType == MotionEventToolType.Finger; + var isMouse = toolType == MotionEventToolType.Mouse; + switch (actionMasked) + { + // DOWN + case MotionEventActions.Down when !isMouse: + case MotionEventActions.PointerDown when !isMouse: + return isTouch ? RawPointerEventType.TouchBegin : RawPointerEventType.LeftButtonDown; + case MotionEventActions.ButtonPress: + return e.ActionButton switch + { + MotionEventButtonState.Back => RawPointerEventType.XButton1Down, + MotionEventButtonState.Forward => RawPointerEventType.XButton2Down, + MotionEventButtonState.Primary => RawPointerEventType.LeftButtonDown, + MotionEventButtonState.Secondary => RawPointerEventType.RightButtonDown, + MotionEventButtonState.StylusPrimary => RawPointerEventType.LeftButtonDown, + MotionEventButtonState.StylusSecondary => RawPointerEventType.RightButtonDown, + MotionEventButtonState.Tertiary => RawPointerEventType.MiddleButtonDown, + _ => RawPointerEventType.LeftButtonDown + }; + // UP + case MotionEventActions.Up when !isMouse: + case MotionEventActions.PointerUp when !isMouse: + return isTouch ? RawPointerEventType.TouchEnd : RawPointerEventType.LeftButtonUp; + case MotionEventActions.ButtonRelease: + return e.ActionButton switch + { + MotionEventButtonState.Back => RawPointerEventType.XButton1Up, + MotionEventButtonState.Forward => RawPointerEventType.XButton2Up, + MotionEventButtonState.Primary => RawPointerEventType.LeftButtonUp, + MotionEventButtonState.Secondary => RawPointerEventType.RightButtonUp, + MotionEventButtonState.StylusPrimary => RawPointerEventType.LeftButtonUp, + MotionEventButtonState.StylusSecondary => RawPointerEventType.RightButtonUp, + MotionEventButtonState.Tertiary => RawPointerEventType.MiddleButtonUp, + _ => RawPointerEventType.LeftButtonUp + }; + // MOVE + case MotionEventActions.Outside: + case MotionEventActions.HoverMove: + case MotionEventActions.Move: + return isTouch ? RawPointerEventType.TouchUpdate : RawPointerEventType.Move; + // CANCEL + case MotionEventActions.Cancel: + return isTouch ? RawPointerEventType.TouchCancel : RawPointerEventType.LeaveWindow; + default: + return (RawPointerEventType)(-1); + } + } +#pragma warning restore CA1416 // Validate platform compatibility + + private IPointerDevice GetDevice(MotionEventToolType type) + { + return type switch + { + MotionEventToolType.Mouse => _mouseDevice, + MotionEventToolType.Stylus => _penDevice, + MotionEventToolType.Eraser => _penDevice, + MotionEventToolType.Finger => _touchDevice, + _ => _touchDevice + }; + } + + private RawPointerPoint CreatePoint(MotionEvent e, int index) + { + return new RawPointerPoint + { + Position = new Point(e.GetX(index), e.GetY(index)) / _view.RenderScaling, + Pressure = Math.Min(e.GetPressure(index), 1), // android pressure can depend on the device, can be mixed up with "GetSize", may be larger than 1.0f on some devices + Twist = e.GetOrientation(index) * s_radiansToDegree + }; + } + + private RawPointerPoint CreateHistoricalPoint(MotionEvent e, int index, int pos) + { + return new RawPointerPoint + { + Position = new Point(e.GetHistoricalX(index, pos), e.GetHistoricalY(index, pos)) / _view.RenderScaling, + Pressure = Math.Min(e.GetHistoricalPressure(index, pos), 1), + Twist = e.GetHistoricalOrientation(index, pos) * s_radiansToDegree + }; + } + + private static RawInputModifiers GetToolModifiers(MotionEventToolType toolType) + { + // Android "Eraser" indicates Inverted pen OR actual Eraser. So we have to go both here. + return toolType == MotionEventToolType.Eraser ? RawInputModifiers.PenInverted | RawInputModifiers.PenEraser : RawInputModifiers.None; + } + + public void Dispose() + { + _disposed = true; + } + } +} diff --git a/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidTouchEventsHelper.cs b/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidTouchEventsHelper.cs deleted file mode 100644 index 6142598514..0000000000 --- a/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidTouchEventsHelper.cs +++ /dev/null @@ -1,85 +0,0 @@ -using System; -using Android.Views; -using Avalonia.Input; -using Avalonia.Input.Raw; -using Avalonia.Platform; - -namespace Avalonia.Android.Platform.Specific.Helpers -{ - public class AndroidTouchEventsHelper : IDisposable where TView : ITopLevelImpl, IAndroidView - { - private TView _view; - public bool HandleEvents { get; set; } - - public AndroidTouchEventsHelper(TView view, Func getInputRoot, Func getPointfunc) - { - this._view = view; - HandleEvents = true; - _getPointFunc = getPointfunc; - _getInputRoot = getInputRoot; - } - - private TouchDevice _touchDevice = new TouchDevice(); - private Func _getPointFunc; - private Func _getInputRoot; - - public bool? DispatchTouchEvent(MotionEvent e, out bool callBase) - { - if (!HandleEvents) - { - callBase = true; - return null; - } - - var eventTime = DateTime.Now; - - //Basic touch support - var pointerEventType = e.Action switch - { - MotionEventActions.Down => RawPointerEventType.TouchBegin, - MotionEventActions.Up => RawPointerEventType.TouchEnd, - MotionEventActions.Cancel => RawPointerEventType.TouchCancel, - _ => RawPointerEventType.TouchUpdate - }; - - if (e.Action.HasFlag(MotionEventActions.PointerDown)) - { - pointerEventType = RawPointerEventType.TouchBegin; - } - - if (e.Action.HasFlag(MotionEventActions.PointerUp)) - { - pointerEventType = RawPointerEventType.TouchEnd; - } - - for (int i = 0; i < e.PointerCount; i++) - { - //if point is in view otherwise it's possible avalonia not to find the proper window to dispatch the event - var point = _getPointFunc(e, i); - - double x = _view.View.GetX(); - double y = _view.View.GetY(); - double r = x + _view.View.Width; - double b = y + _view.View.Height; - - if (x <= point.X && r >= point.X && y <= point.Y && b >= point.Y) - { - var inputRoot = _getInputRoot(); - - var mouseEvent = new RawTouchEventArgs(_touchDevice, (uint)eventTime.Ticks, inputRoot, - i == e.ActionIndex ? pointerEventType : RawPointerEventType.TouchUpdate, point, RawInputModifiers.None, e.GetPointerId(i)); - _view.Input(mouseEvent); - } - } - - callBase = true; - //if return false events for move and up are not received!!! - return e.Action != MotionEventActions.Up; - } - - public void Dispose() - { - HandleEvents = false; - } - } -} diff --git a/src/Avalonia.Base/Input/Raw/RawPointerEventArgs.cs b/src/Avalonia.Base/Input/Raw/RawPointerEventArgs.cs index 0e4e0ed3e2..b8f6f99ae8 100644 --- a/src/Avalonia.Base/Input/Raw/RawPointerEventArgs.cs +++ b/src/Avalonia.Base/Input/Raw/RawPointerEventArgs.cs @@ -137,9 +137,13 @@ namespace Avalonia.Input.Raw /// public Point Position { get; set; } + /// public float Twist { get; set; } + /// public float Pressure { get; set; } + /// public float XTilt { get; set; } + /// public float YTilt { get; set; } 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.Base/VisualTree/VisualExtensions.cs b/src/Avalonia.Base/VisualTree/VisualExtensions.cs index 128a39c082..a1b8894604 100644 --- a/src/Avalonia.Base/VisualTree/VisualExtensions.cs +++ b/src/Avalonia.Base/VisualTree/VisualExtensions.cs @@ -413,7 +413,7 @@ namespace Avalonia.VisualTree Index = index, ZIndex = element.ZIndex, }) - .OrderBy(x => x, null) + .OrderBy(x => x, ZOrderElement.Comparer) .Select(x => x.Element!); } @@ -448,6 +448,19 @@ namespace Avalonia.VisualTree public int Index { get; set; } public int ZIndex { get; set; } + class ZOrderComparer : IComparer + { + public int Compare(ZOrderElement? x, ZOrderElement? y) + { + if (ReferenceEquals(x, y)) return 0; + if (ReferenceEquals(null, y)) return 1; + if (ReferenceEquals(null, x)) return -1; + return x.CompareTo(y); + } + } + + public static IComparer Comparer { get; } = new ZOrderComparer(); + public int CompareTo(ZOrderElement? other) { if (other is null) 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.Controls.DataGrid/Collections/DataGridSortDescription.cs b/src/Avalonia.Controls.DataGrid/Collections/DataGridSortDescription.cs index ff222658db..ab73ed73c7 100644 --- a/src/Avalonia.Controls.DataGrid/Collections/DataGridSortDescription.cs +++ b/src/Avalonia.Controls.DataGrid/Collections/DataGridSortDescription.cs @@ -12,9 +12,6 @@ namespace Avalonia.Collections { public virtual string PropertyPath => null; - [Obsolete("Use Direction property to read or override sorting direction.")] - public virtual bool Descending => Direction == ListSortDirection.Descending; - public virtual ListSortDirection Direction => ListSortDirection.Ascending; public bool HasPropertyPath => !String.IsNullOrEmpty(PropertyPath); public abstract IComparer Comparer { get; } @@ -254,13 +251,6 @@ namespace Avalonia.Collections return new DataGridPathSortDescription(propertyPath, direction, null, culture); } - - [Obsolete("Use overload taking a ListSortDirection.")] - public static DataGridSortDescription FromPath(string propertyPath, bool descending, CultureInfo culture = null) - { - return new DataGridPathSortDescription(propertyPath, descending ? ListSortDirection.Descending : ListSortDirection.Ascending, null, culture); - } - public static DataGridSortDescription FromPath(string propertyPath, ListSortDirection direction, IComparer comparer) { return new DataGridPathSortDescription(propertyPath, direction, comparer, null); diff --git a/src/Avalonia.Controls/Notifications/WindowNotificationManager.cs b/src/Avalonia.Controls/Notifications/WindowNotificationManager.cs index 2449f4c15c..630276767a 100644 --- a/src/Avalonia.Controls/Notifications/WindowNotificationManager.cs +++ b/src/Avalonia.Controls/Notifications/WindowNotificationManager.cs @@ -102,15 +102,12 @@ namespace Avalonia.Controls.Notifications Content = content }; - if (notification != null) + notificationControl.NotificationClosed += (sender, args) => { - notificationControl.NotificationClosed += (sender, args) => - { - notification.OnClose?.Invoke(); + notification?.OnClose?.Invoke(); - _items?.Remove(sender); - }; - } + _items?.Remove(sender); + }; notificationControl.PointerPressed += (sender, args) => { diff --git a/src/Avalonia.Dialogs/ManagedFileChooser.cs b/src/Avalonia.Dialogs/ManagedFileChooser.cs index 199a4d6620..ee2ab42d6f 100644 --- a/src/Avalonia.Dialogs/ManagedFileChooser.cs +++ b/src/Avalonia.Dialogs/ManagedFileChooser.cs @@ -36,9 +36,8 @@ namespace Avalonia.Dialogs if (_quickLinksRoot != null) { var isQuickLink = _quickLinksRoot.IsLogicalAncestorOf(e.Source as Control); -#pragma warning disable CS0618 // Type or member is obsolete + if (e.ClickCount == 2 || isQuickLink) -#pragma warning restore CS0618 // Type or member is obsolete { if (model.ItemType == ManagedFileChooserItemType.File) { 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/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs b/src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs index a0e7fd7dcf..168b9835dd 100644 --- a/src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs +++ b/src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs @@ -158,9 +158,6 @@ namespace Avalonia.Markup.Xaml.XamlIl.Runtime string.Join(",", lst.Select(e => $"`{e.ClrAssemblyName}:{e.ClrNamespace}.{name}`"))); } } - - [Obsolete("Don't use", true)] - public static readonly IServiceProvider RootServiceProviderV1 = new RootServiceProvider(null); // Don't emit debug symbols for this code so debugger will be forced to step into XAML instead #line hidden 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/Skia/Avalonia.Skia/Helpers/DrawingContextHelper.cs b/src/Skia/Avalonia.Skia/Helpers/DrawingContextHelper.cs index a078c364a2..ec33770356 100644 --- a/src/Skia/Avalonia.Skia/Helpers/DrawingContextHelper.cs +++ b/src/Skia/Avalonia.Skia/Helpers/DrawingContextHelper.cs @@ -1,5 +1,4 @@ -using System; -using Avalonia.Platform; +using Avalonia.Platform; using Avalonia.Rendering; using SkiaSharp; @@ -29,72 +28,5 @@ namespace Avalonia.Skia.Helpers return new DrawingContextImpl(createInfo); } - /// - /// Unsupported - Wraps a GPU Backed SkiaSurface in an Avalonia DrawingContext. - /// - [Obsolete] - public static IDrawingContextImpl WrapSkiaSurface(this SKSurface surface, GRContext grContext, Vector dpi, params IDisposable[] disposables) - { - var createInfo = new DrawingContextImpl.CreateInfo - { - GrContext = grContext, - Surface = surface, - Dpi = dpi, - DisableTextLcdRendering = false, - }; - - return new DrawingContextImpl(createInfo, disposables); - } - - /// - /// Unsupported - Wraps a non-GPU Backed SkiaSurface in an Avalonia DrawingContext. - /// - [Obsolete] - public static IDrawingContextImpl WrapSkiaSurface(this SKSurface surface, Vector dpi, params IDisposable[] disposables) - { - var createInfo = new DrawingContextImpl.CreateInfo - { - Surface = surface, - Dpi = dpi, - DisableTextLcdRendering = false, - }; - - return new DrawingContextImpl(createInfo, disposables); - } - - [Obsolete] - public static IDrawingContextImpl CreateDrawingContext(Size size, Vector dpi, GRContext grContext = null) - { - if (grContext is null) - { - var surface = SKSurface.Create( - new SKImageInfo( - (int)Math.Ceiling(size.Width), - (int)Math.Ceiling(size.Height), - SKImageInfo.PlatformColorType, - SKAlphaType.Premul)); - - return WrapSkiaSurface(surface, dpi, surface); - } - else - { - var surface = SKSurface.Create(grContext, false, - new SKImageInfo( - (int)Math.Ceiling(size.Width), - (int)Math.Ceiling(size.Height), - SKImageInfo.PlatformColorType, - SKAlphaType.Premul)); - - return WrapSkiaSurface(surface, grContext, dpi, surface); - } - } - - [Obsolete] - public static void DrawTo(this IDrawingContextImpl source, IDrawingContextImpl destination, SKPaint paint = null) - { - var src = (DrawingContextImpl)source; - var dst = (DrawingContextImpl)destination; - dst.Canvas.DrawSurface(src.Surface, new SKPoint(0, 0), paint); - } } } diff --git a/src/Windows/Avalonia.Win32/Win32Platform.cs b/src/Windows/Avalonia.Win32/Win32Platform.cs index 2b8070fb04..29b4baeeb0 100644 --- a/src/Windows/Avalonia.Win32/Win32Platform.cs +++ b/src/Windows/Avalonia.Win32/Win32Platform.cs @@ -65,15 +65,6 @@ namespace Avalonia "Microsoft Basic Render" }; - /// - /// Enables multitouch support. The default value is true. - /// - /// - /// 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. - /// - [Obsolete("Multitouch is always enabled on supported Windows versions")] - public bool? EnableMultitouch { get; set; } = true; - /// /// Embeds popups to the window when set to true. The default value is false. /// 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