diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 903f9e3843..a3bbc33418 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -35,9 +35,9 @@ jobs:
version: 6.0.401
- task: UseDotNet@2
- displayName: 'Use .NET Core SDK 7.0.100-rc.2.22477.23'
+ displayName: 'Use .NET Core SDK 7.0'
inputs:
- version: 7.0.100-rc.2.22477.23
+ version: 7.0.100
- task: CmdLine@2
displayName: 'Install Workloads'
@@ -72,9 +72,9 @@ jobs:
version: 6.0.401
- task: UseDotNet@2
- displayName: 'Use .NET Core SDK 7.0.100-rc.2.22477.23'
+ displayName: 'Use .NET Core SDK 7.0.100'
inputs:
- version: 7.0.100-rc.2.22477.23
+ version: 7.0.100
- task: CmdLine@2
displayName: 'Install Workloads'
@@ -143,9 +143,9 @@ jobs:
version: 6.0.401
- task: UseDotNet@2
- displayName: 'Use .NET Core SDK 7.0.100-rc.2.22477.23'
+ displayName: 'Use .NET Core SDK 7.0.100'
inputs:
- version: 7.0.100-rc.2.22477.23
+ version: 7.0.100
- task: CmdLine@2
displayName: 'Install Workloads'
diff --git a/global.json b/global.json
index dc6da556b3..a9318b212f 100644
--- a/global.json
+++ b/global.json
@@ -1,6 +1,6 @@
{
"sdk": {
- "version": "7.0.100-rc.2.22477.23",
+ "version": "7.0.100",
"rollForward": "latestFeature"
},
"msbuild-sdks": {
diff --git a/native/Avalonia.Native/src/OSX/rendertarget.mm b/native/Avalonia.Native/src/OSX/rendertarget.mm
index 2075cc85ab..1c22c91207 100644
--- a/native/Avalonia.Native/src/OSX/rendertarget.mm
+++ b/native/Avalonia.Native/src/OSX/rendertarget.mm
@@ -183,8 +183,11 @@ static IAvnGlSurfaceRenderTarget* CreateGlRenderTarget(IOSurfaceRenderTarget* ta
[_layer setContents: (__bridge IOSurface*) surface->surface];
}
[CATransaction commit];
- [CATransaction flush];
}
+ // This can trigger event processing on the main thread
+ // which might need to lock the renderer
+ // which can cause a deadlock. So flush call is outside of the lock
+ [CATransaction flush];
}
else
dispatch_async(dispatch_get_main_queue(), ^{
diff --git a/nukebuild/Build.cs b/nukebuild/Build.cs
index 7425c344c3..2295c0beda 100644
--- a/nukebuild/Build.cs
+++ b/nukebuild/Build.cs
@@ -145,8 +145,25 @@ partial class Build : NukeBuild
{
Information($"Running tests from {projectName}");
var project = Solution.GetProject(projectName).NotNull("project != null");
+ // Nuke and MSBuild tools have build-in helpers to get target frameworks from the project.
+ // Unfortunately, it gets broken with every second SDK update, so we had to do it manually.
+ var fileXml = XDocument.Parse(File.ReadAllText(project.Path));
+ var targetFrameworks = fileXml.Descendants("TargetFrameworks")
+ .FirstOrDefault()?.Value.Split(';').Select(f => f.Trim());
+ if (targetFrameworks is null)
+ {
+ var targetFramework = fileXml.Descendants("TargetFramework").FirstOrDefault()?.Value;
+ if (targetFramework is not null)
+ {
+ targetFrameworks = new[] { targetFramework };
+ }
+ }
+ if (targetFrameworks is null)
+ {
+ throw new InvalidOperationException("No target frameworks were found in the test project");
+ }
- foreach (var fw in project.GetTargetFrameworks())
+ foreach (var fw in targetFrameworks)
{
if (fw.StartsWith("net4")
&& RuntimeInformation.IsOSPlatform(OSPlatform.Linux)
diff --git a/nukebuild/_build.csproj b/nukebuild/_build.csproj
index 865d935ad7..92d9732e91 100644
--- a/nukebuild/_build.csproj
+++ b/nukebuild/_build.csproj
@@ -16,8 +16,8 @@
-
-
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs
index 984eb775b5..4e972d504a 100644
--- a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs
+++ b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs
@@ -165,6 +165,28 @@ namespace Avalonia.Android.Platform.SkiaPlatform
_tl.Draw();
}
+ protected override void DispatchDraw(global::Android.Graphics.Canvas canvas)
+ {
+ // Workaround issue #9230 on where screen remains gray after splash screen.
+ // base.DispatchDraw should punch a hole into the canvas so the surface
+ // can be seen below, but it does not.
+ if (OperatingSystem.IsAndroidVersionAtLeast(29))
+ {
+ // Android 10+ does this (BlendMode was new)
+ var paint = new Paint();
+ paint.SetColor(0);
+ paint.BlendMode = BlendMode.Clear;
+ canvas.DrawRect(0, 0, Width, Height, paint);
+ }
+ else
+ {
+ // Android 9 did this
+ canvas.DrawColor(Color.Transparent, PorterDuff.Mode.Clear);
+ }
+
+ base.DispatchDraw(canvas);
+ }
+
protected override bool DispatchGenericPointerEvent(MotionEvent e)
{
bool callBase;
diff --git a/src/Avalonia.Base/Layout/UniformGridLayoutState.cs b/src/Avalonia.Base/Layout/UniformGridLayoutState.cs
index d6b5a30bfc..65cdf4c94b 100644
--- a/src/Avalonia.Base/Layout/UniformGridLayoutState.cs
+++ b/src/Avalonia.Base/Layout/UniformGridLayoutState.cs
@@ -117,12 +117,12 @@ namespace Avalonia.Layout
double extraMinorPixelsForEachItem = 0.0;
if (!double.IsInfinity(availableSizeMinor))
{
- var numItemsPerColumn = Math.Min(
+ var numItemsPerColumn = (int)Math.Min(
maxItemsPerLine,
Math.Max(1.0, availableSizeMinor / (itemSizeMinor + minorItemSpacing)));
var usedSpace = (numItemsPerColumn * (itemSizeMinor + minorItemSpacing)) - minorItemSpacing;
- var remainingSpace = ((int)(availableSizeMinor - usedSpace));
- extraMinorPixelsForEachItem = remainingSpace / ((int)numItemsPerColumn);
+ var remainingSpace = availableSizeMinor - usedSpace;
+ extraMinorPixelsForEachItem = (int)(remainingSpace / numItemsPerColumn);
}
if (stretch == UniformGridLayoutItemsStretch.Fill)
diff --git a/src/Avalonia.Controls.ColorPicker/ColorPalettes/MaterialColorPalette.cs b/src/Avalonia.Controls.ColorPicker/ColorPalettes/MaterialColorPalette.cs
index 8fa7ede77e..d009926bc5 100644
--- a/src/Avalonia.Controls.ColorPicker/ColorPalettes/MaterialColorPalette.cs
+++ b/src/Avalonia.Controls.ColorPicker/ColorPalettes/MaterialColorPalette.cs
@@ -42,6 +42,11 @@ namespace Avalonia.Controls
Red800 = 0xFFC62828,
Red900 = 0xFFB71C1C,
+ RedA100 = 0xFFFF8A80,
+ RedA200 = 0xFFFF5252,
+ RedA400 = 0xFFFF1744,
+ RedA700 = 0xFFD50000,
+
// Pink
Pink50 = 0xFFFCE4EC,
Pink100 = 0xFFF8BBD0,
@@ -54,6 +59,11 @@ namespace Avalonia.Controls
Pink800 = 0xFFAD1457,
Pink900 = 0xFF880E4F,
+ PinkA100 = 0xFFFF80AB,
+ PinkA200 = 0xFFFF4081,
+ PinkA400 = 0xFFF50057,
+ PinkA700 = 0xFFC51162,
+
// Purple
Purple50 = 0xFFF3E5F5,
Purple100 = 0xFFE1BEE7,
@@ -66,6 +76,11 @@ namespace Avalonia.Controls
Purple800 = 0xFF6A1B9A,
Purple900 = 0xFF4A148C,
+ PurpleA100 = 0xFFEA80FC,
+ PurpleA200 = 0xFFE040FB,
+ PurpleA400 = 0xFFD500F9,
+ PurpleA700 = 0xFFAA00FF,
+
// Deep Purple
DeepPurple50 = 0xFFEDE7F6,
DeepPurple100 = 0xFFD1C4E9,
@@ -78,6 +93,11 @@ namespace Avalonia.Controls
DeepPurple800 = 0xFF4527A0,
DeepPurple900 = 0xFF311B92,
+ DeepPurpleA100 = 0xFFB388FF,
+ DeepPurpleA200 = 0xFF7C4DFF,
+ DeepPurpleA400 = 0xFF651FFF,
+ DeepPurpleA700 = 0xFF6200EA,
+
// Indigo
Indigo50 = 0xFFE8EAF6,
Indigo100 = 0xFFC5CAE9,
@@ -90,6 +110,11 @@ namespace Avalonia.Controls
Indigo800 = 0xFF283593,
Indigo900 = 0xFF1A237E,
+ IndigoA100 = 0xFF8C9EFF,
+ IndigoA200 = 0xFF536DFE,
+ IndigoA400 = 0xFF3D5AFE,
+ IndigoA700 = 0xFF304FFE,
+
// Blue
Blue50 = 0xFFE3F2FD,
Blue100 = 0xFFBBDEFB,
@@ -102,6 +127,11 @@ namespace Avalonia.Controls
Blue800 = 0xFF1565C0,
Blue900 = 0xFF0D47A1,
+ BlueA100 = 0xFF82B1FF,
+ BlueA200 = 0xFF448AFF,
+ BlueA400 = 0xFF2979FF,
+ BlueA700 = 0xFF2962FF,
+
// Light Blue
LightBlue50 = 0xFFE1F5FE,
LightBlue100 = 0xFFB3E5FC,
@@ -114,6 +144,11 @@ namespace Avalonia.Controls
LightBlue800 = 0xFF0277BD,
LightBlue900 = 0xFF01579B,
+ LightBlueA100 = 0xFF80D8FF,
+ LightBlueA200 = 0xFF40C4FF,
+ LightBlueA400 = 0xFF00B0FF,
+ LightBlueA700 = 0xFF0091EA,
+
// Cyan
Cyan50 = 0xFFE0F7FA,
Cyan100 = 0xFFB2EBF2,
@@ -126,6 +161,11 @@ namespace Avalonia.Controls
Cyan800 = 0xFF00838F,
Cyan900 = 0xFF006064,
+ CyanA100 = 0xFF84FFFF,
+ CyanA200 = 0xFF18FFFF,
+ CyanA400 = 0xFF00E5FF,
+ CyanA700 = 0xFF00B8D4,
+
// Teal
Teal50 = 0xFFE0F2F1,
Teal100 = 0xFFB2DFDB,
@@ -138,6 +178,11 @@ namespace Avalonia.Controls
Teal800 = 0xFF00695C,
Teal900 = 0xFF004D40,
+ TealA100 = 0xFFA7FFEB,
+ TealA200 = 0xFF64FFDA,
+ TealA400 = 0xFF1DE9B6,
+ TealA700 = 0xFF00BFA5,
+
// Green
Green50 = 0xFFE8F5E9,
Green100 = 0xFFC8E6C9,
@@ -150,6 +195,11 @@ namespace Avalonia.Controls
Green800 = 0xFF2E7D32,
Green900 = 0xFF1B5E20,
+ GreenA100 = 0xFFB9F6CA,
+ GreenA200 = 0xFF69F0AE,
+ GreenA400 = 0xFF00E676,
+ GreenA700 = 0xFF00C853,
+
// Light Green
LightGreen50 = 0xFFF1F8E9,
LightGreen100 = 0xFFDCEDC8,
@@ -162,6 +212,11 @@ namespace Avalonia.Controls
LightGreen800 = 0xFF558B2F,
LightGreen900 = 0xFF33691E,
+ LightGreenA100 = 0xFFCCFF90,
+ LightGreenA200 = 0xFFB2FF59,
+ LightGreenA400 = 0xFF76FF03,
+ LightGreenA700 = 0xFF64DD17,
+
// Lime
Lime50 = 0xFFF9FBE7,
Lime100 = 0xFFF0F4C3,
@@ -174,6 +229,11 @@ namespace Avalonia.Controls
Lime800 = 0xFF9E9D24,
Lime900 = 0xFF827717,
+ LimeA100 = 0xFFF4FF81,
+ LimeA200 = 0xFFEEFF41,
+ LimeA400 = 0xFFC6FF00,
+ LimeA700 = 0xFFAEEA00,
+
// Yellow
Yellow50 = 0xFFFFFDE7,
Yellow100 = 0xFFFFF9C4,
@@ -186,6 +246,11 @@ namespace Avalonia.Controls
Yellow800 = 0xFFF9A825,
Yellow900 = 0xFFF57F17,
+ YellowA100 = 0xFFFFFF8D,
+ YellowA200 = 0xFFFFFF00,
+ YellowA400 = 0xFFFFEA00,
+ YellowA700 = 0xFFFFD600,
+
// Amber
Amber50 = 0xFFFFF8E1,
Amber100 = 0xFFFFECB3,
@@ -198,6 +263,11 @@ namespace Avalonia.Controls
Amber800 = 0xFFFF8F00,
Amber900 = 0xFFFF6F00,
+ AmberA100 = 0xFFFFE57F,
+ AmberA200 = 0xFFFFD740,
+ AmberA400 = 0xFFFFC400,
+ AmberA700 = 0xFFFFAB00,
+
// Orange
Orange50 = 0xFFFFF3E0,
Orange100 = 0xFFFFE0B2,
@@ -210,6 +280,11 @@ namespace Avalonia.Controls
Orange800 = 0xFFEF6C00,
Orange900 = 0xFFE65100,
+ OrangeA100 = 0xFFFFD180,
+ OrangeA200 = 0xFFFFAB40,
+ OrangeA400 = 0xFFFF9100,
+ OrangeA700 = 0xFFFF6D00,
+
// Deep Orange
DeepOrange50 = 0xFFFBE9E7,
DeepOrange100 = 0xFFFFCCBC,
@@ -222,6 +297,11 @@ namespace Avalonia.Controls
DeepOrange800 = 0xFFD84315,
DeepOrange900 = 0xFFBF360C,
+ DeepOrangeA100 = 0xFFFF9E80,
+ DeepOrangeA200 = 0xFFFF6E40,
+ DeepOrangeA400 = 0xFFFF3D00,
+ DeepOrangeA700 = 0xFFDD2C00,
+
// Brown
Brown50 = 0xFFEFEBE9,
Brown100 = 0xFFD7CCC8,
@@ -257,6 +337,9 @@ namespace Avalonia.Controls
BlueGray700 = 0xFF455A64,
BlueGray800 = 0xFF37474F,
BlueGray900 = 0xFF263238,
+
+ Black = 0xFF000000,
+ White = 0xFFFFFFFF,
}
// See: https://material.io/design/color/the-color-system.html#tools-for-picking-colors
diff --git a/src/Linux/Avalonia.LinuxFramebuffer/DrmOutputOptions.cs b/src/Linux/Avalonia.LinuxFramebuffer/DrmOutputOptions.cs
index e92ad02c7a..ce843952e7 100644
--- a/src/Linux/Avalonia.LinuxFramebuffer/DrmOutputOptions.cs
+++ b/src/Linux/Avalonia.LinuxFramebuffer/DrmOutputOptions.cs
@@ -23,5 +23,11 @@ namespace Avalonia.LinuxFramebuffer
/// Default: R0 G0 B0 A0
///
public Color InitialBufferSwappingColor { get; set; } = new Color(0, 0, 0, 0);
+
+ ///
+ /// specific the video mode with which the DrmOutput should be created, if it is not found it will fallback to the preferred mode.
+ /// If NULL preferred mode will be used.
+ ///
+ public PixelSize? VideoMode { get; set; }
}
}
diff --git a/src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputBackend.Pointer.cs b/src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputBackend.Pointer.cs
new file mode 100644
index 0000000000..ef039a38bc
--- /dev/null
+++ b/src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputBackend.Pointer.cs
@@ -0,0 +1,110 @@
+using System;
+using Avalonia.Input;
+using Avalonia.Input.Raw;
+using Avalonia.Logging;
+using static Avalonia.LinuxFramebuffer.Input.LibInput.LibInputNativeUnsafeMethods;
+
+namespace Avalonia.LinuxFramebuffer.Input.LibInput;
+
+public partial class LibInputBackend
+{
+ private MouseDevice _mouse = new MouseDevice();
+ private Point _mousePosition;
+ private const string Pointer = LibInput + "/" + nameof(Pointer);
+
+ private void HandlePointer(IntPtr ev, LibInputEventType type)
+ {
+ var modifiers = RawInputModifiers.None; //TODO: support input modifiers
+ var pev = libinput_event_get_pointer_event(ev);
+ var info = _screen.ScaledSize;
+ var ts = libinput_event_pointer_get_time_usec(pev) / 1000;
+ switch (type)
+ {
+ case LibInputEventType.LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
+ _mousePosition = new Point(libinput_event_pointer_get_absolute_x_transformed(pev, (int)info.Width),
+ libinput_event_pointer_get_absolute_y_transformed(pev, (int)info.Height));
+ ScheduleInput(new RawPointerEventArgs(_mouse, ts, _inputRoot, RawPointerEventType.Move, _mousePosition,
+ modifiers));
+ break;
+ case LibInputEventType.LIBINPUT_EVENT_POINTER_BUTTON:
+ {
+ var button = (EvKey)libinput_event_pointer_get_button(pev);
+ var buttonState = libinput_event_pointer_get_button_state(pev);
+
+ RawPointerEventArgs evnt = button switch
+ {
+ EvKey.BTN_LEFT when buttonState == 1
+ => new(_mouse, ts, _inputRoot, RawPointerEventType.LeftButtonDown, _mousePosition, modifiers),
+ EvKey.BTN_LEFT when buttonState == 0
+ => new(_mouse, ts, _inputRoot, RawPointerEventType.LeftButtonUp, _mousePosition, modifiers),
+ EvKey.BTN_RIGHT when buttonState == 1
+ => new(_mouse, ts, _inputRoot, RawPointerEventType.RightButtonUp, _mousePosition, modifiers),
+ EvKey.BTN_RIGHT when buttonState == 2
+ => new(_mouse, ts, _inputRoot, RawPointerEventType.RightButtonDown, _mousePosition, modifiers),
+ EvKey.BTN_MIDDLE when buttonState == 1
+ => new(_mouse, ts, _inputRoot, RawPointerEventType.MiddleButtonDown, _mousePosition, modifiers),
+ EvKey.BTN_MIDDLE when buttonState == 2
+ => new(_mouse, ts, _inputRoot, RawPointerEventType.MiddleButtonUp, _mousePosition, modifiers),
+ _ => default,
+ };
+ if (evnt is not null)
+ {
+ ScheduleInput(evnt);
+ }
+ else
+ {
+ Logger.TryGet(LogEventLevel.Warning, Pointer)
+ ?.Log(this, $"The button {button} is not associated");
+ }
+ }
+ break;
+ // Backward compatibility with low-res wheel
+ case LibInputEventType.LIBINPUT_EVENT_POINTER_AXIS:
+ {
+ var sourceAxis = libinput_event_pointer_get_axis_source(pev);
+ switch (sourceAxis)
+ {
+ case LibInputPointerAxisSource.LIBINPUT_POINTER_AXIS_SOURCE_WHEEL:
+ {
+ var value = libinput_event_pointer_get_axis_value_discrete(pev,
+ LibInputPointerAxis.LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
+ ScheduleInput(new RawMouseWheelEventArgs(_mouse
+ , ts
+ , _inputRoot
+ , _mousePosition
+ , new Vector(0, -value)
+ , modifiers));
+ }
+ break;
+ case LibInputPointerAxisSource.LIBINPUT_POINTER_AXIS_SOURCE_FINGER:
+ case LibInputPointerAxisSource.LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS:
+ case LibInputPointerAxisSource.LIBINPUT_POINTER_AXIS_SOURCE_WHEEL_TILT:
+ default:
+ Logger.TryGet(LogEventLevel.Debug, Pointer)
+ ?.Log(this, $"The pointer axis {sourceAxis} is not managed.");
+ break;
+ }
+ }
+ break;
+ // Hi-Res wheel
+ case LibInputEventType.LIBINPUT_EVENT_POINTER_SCROLL_WHEEL:
+ {
+ var value = new Vector(0,
+ -libinput_event_pointer_get_scroll_value_v120(pev,
+ LibInputPointerAxis.LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL) / 120);
+ ScheduleInput(new RawMouseWheelEventArgs(_mouse
+ , ts
+ , _inputRoot
+ , _mousePosition
+ , value
+ , modifiers));
+ }
+ break;
+ default:
+ Logger.TryGet(LogEventLevel.Warning, Pointer)
+ ?.Log(this, $"The pointer event {type} is not mapped.");
+ break;
+ }
+
+ }
+}
diff --git a/src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputBackend.cs b/src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputBackend.cs
index 702ae3f8e5..77e8202fac 100644
--- a/src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputBackend.cs
+++ b/src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputBackend.cs
@@ -4,18 +4,16 @@ using System.IO;
using System.Threading;
using Avalonia.Input;
using Avalonia.Input.Raw;
-using static Avalonia.LinuxFramebuffer.Input.LibInput.LibInputNativeUnsafeMethods;
+using static Avalonia.LinuxFramebuffer.Input.LibInput.LibInputNativeUnsafeMethods;
namespace Avalonia.LinuxFramebuffer.Input.LibInput
{
- public class LibInputBackend : IInputBackend
+ public partial class LibInputBackend : IInputBackend
{
private IScreenInfoProvider _screen;
private IInputRoot _inputRoot;
private readonly Queue _inputThreadActions = new Queue();
private TouchDevice _touch = new TouchDevice();
- private MouseDevice _mouse = new MouseDevice();
- private Point _mousePosition;
-
+ private const string LibInput = nameof(Avalonia.LinuxFramebuffer) + "/" + nameof(Avalonia.LinuxFramebuffer.Input) + "/" + nameof(LibInput);
private readonly RawEventGroupingThreadingHelper _inputQueue;
private Action _onInput;
private Dictionary _pointers = new Dictionary();
@@ -24,13 +22,13 @@ namespace Avalonia.LinuxFramebuffer.Input.LibInput
{
var ctx = libinput_path_create_context();
_inputQueue = new(e => _onInput?.Invoke(e));
- new Thread(()=>InputThread(ctx)).Start();
+ new Thread(() => InputThread(ctx)).Start();
}
private unsafe void InputThread(IntPtr ctx)
{
var fd = libinput_get_fd(ctx);
-
+
var timeval = stackalloc IntPtr[2];
@@ -38,12 +36,11 @@ namespace Avalonia.LinuxFramebuffer.Input.LibInput
libinput_path_add_device(ctx, f);
while (true)
{
-
IntPtr ev;
libinput_dispatch(ctx);
while ((ev = libinput_get_event(ctx)) != IntPtr.Zero)
{
-
+
var type = libinput_event_get_type(ev);
if (type >= LibInputEventType.LIBINPUT_EVENT_TOUCH_DOWN &&
type <= LibInputEventType.LIBINPUT_EVENT_TOUCH_CANCEL)
@@ -52,12 +49,12 @@ namespace Avalonia.LinuxFramebuffer.Input.LibInput
if (type >= LibInputEventType.LIBINPUT_EVENT_POINTER_MOTION
&& type <= LibInputEventType.LIBINPUT_EVENT_POINTER_AXIS)
HandlePointer(ev, type);
-
+
libinput_event_destroy(ev);
libinput_dispatch(ctx);
}
- pollfd pfd = new pollfd {fd = fd, events = 1};
+ pollfd pfd = new pollfd { fd = fd, events = 1 };
NativeUnsafeMethods.poll(&pfd, new IntPtr(1), 10);
}
}
@@ -67,7 +64,7 @@ namespace Avalonia.LinuxFramebuffer.Input.LibInput
private void HandleTouch(IntPtr ev, LibInputEventType type)
{
var tev = libinput_event_get_touch_event(ev);
- if(tev == IntPtr.Zero)
+ if (tev == IntPtr.Zero)
return;
if (type < LibInputEventType.LIBINPUT_EVENT_TOUCH_FRAME)
{
@@ -102,44 +99,6 @@ namespace Avalonia.LinuxFramebuffer.Input.LibInput
}
}
- private void HandlePointer(IntPtr ev, LibInputEventType type)
- {
- //TODO: support input modifiers
- var pev = libinput_event_get_pointer_event(ev);
- var info = _screen.ScaledSize;
- var ts = libinput_event_pointer_get_time_usec(pev) / 1000;
- if (type == LibInputEventType.LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE)
- {
- _mousePosition = new Point(libinput_event_pointer_get_absolute_x_transformed(pev, (int)info.Width),
- libinput_event_pointer_get_absolute_y_transformed(pev, (int)info.Height));
- ScheduleInput(new RawPointerEventArgs(_mouse, ts, _inputRoot, RawPointerEventType.Move, _mousePosition,
- RawInputModifiers.None));
- }
- else if (type == LibInputEventType.LIBINPUT_EVENT_POINTER_BUTTON)
- {
- var button = (EvKey)libinput_event_pointer_get_button(pev);
- var buttonState = libinput_event_pointer_get_button_state(pev);
-
-
- var evnt = button == EvKey.BTN_LEFT ?
- (buttonState == 1 ? RawPointerEventType.LeftButtonDown : RawPointerEventType.LeftButtonUp) :
- button == EvKey.BTN_MIDDLE ?
- (buttonState == 1 ? RawPointerEventType.MiddleButtonDown : RawPointerEventType.MiddleButtonUp) :
- button == EvKey.BTN_RIGHT ?
- (buttonState == 1 ?
- RawPointerEventType.RightButtonDown :
- RawPointerEventType.RightButtonUp) :
- (RawPointerEventType)(-1);
- if (evnt == (RawPointerEventType)(-1))
- return;
-
-
- ScheduleInput(
- new RawPointerEventArgs(_mouse, ts, _inputRoot, evnt, _mousePosition, RawInputModifiers.None));
- }
-
- }
-
public void Initialize(IScreenInfoProvider screen, Action onInput)
{
_screen = screen;
diff --git a/src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputNativeUnsafeMethods.cs b/src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputNativeUnsafeMethods.cs
index 0492090461..df6defb653 100644
--- a/src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputNativeUnsafeMethods.cs
+++ b/src/Linux/Avalonia.LinuxFramebuffer/Input/LibInput/LibInputNativeUnsafeMethods.cs
@@ -77,6 +77,9 @@ namespace Avalonia.LinuxFramebuffer.Input.LibInput
LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE,
LIBINPUT_EVENT_POINTER_BUTTON,
LIBINPUT_EVENT_POINTER_AXIS,
+ LIBINPUT_EVENT_POINTER_SCROLL_WHEEL,
+ LIBINPUT_EVENT_POINTER_SCROLL_FINGER,
+ LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS,
LIBINPUT_EVENT_TOUCH_DOWN = 500,
LIBINPUT_EVENT_TOUCH_UP,
LIBINPUT_EVENT_TOUCH_MOTION,
@@ -97,8 +100,38 @@ namespace Avalonia.LinuxFramebuffer.Input.LibInput
LIBINPUT_EVENT_GESTURE_PINCH_END,
LIBINPUT_EVENT_SWITCH_TOGGLE = 900,
}
-
-
+
+ public enum LibInputPointerAxisSource
+ {
+ /**
+ * The event is caused by the rotation of a wheel.
+ **/
+ LIBINPUT_POINTER_AXIS_SOURCE_WHEEL = 1,
+ /**
+ * The event is caused by the movement of one or more fingers on a device.
+ **/
+ LIBINPUT_POINTER_AXIS_SOURCE_FINGER,
+ /**
+ * The event is caused by the motion of some device.
+ **/
+ LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS,
+ /**
+ * The event is caused by the tilting of a mouse wheel rather than
+ * its rotation. This method is commonly used on mice without
+ * separate horizontal scroll wheels.
+ * @deprecated This axis source is deprecated as of libinput 1.16.
+ * It was never used by any device before libinput 1.16. All wheel
+ * tilt devices use @ref LIBINPUT_POINTER_AXIS_SOURCE_WHEEL instead.
+ **/
+ LIBINPUT_POINTER_AXIS_SOURCE_WHEEL_TILT,
+ };
+
+ public enum LibInputPointerAxis
+ {
+ LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL = 0,
+ LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL = 1,
+ };
+
[DllImport(LibInput)]
public extern static void libinput_event_destroy(IntPtr ev);
@@ -119,21 +152,29 @@ namespace Avalonia.LinuxFramebuffer.Input.LibInput
[DllImport(LibInput)]
public extern static IntPtr libinput_event_get_pointer_event(IntPtr ev);
-
-
+
[DllImport(LibInput)]
public extern static ulong libinput_event_pointer_get_time_usec(IntPtr ev);
[DllImport(LibInput)]
public extern static double libinput_event_pointer_get_absolute_x_transformed(IntPtr ev, int width);
-
+
[DllImport(LibInput)]
public extern static double libinput_event_pointer_get_absolute_y_transformed(IntPtr ev, int height);
-
+
[DllImport(LibInput)]
public extern static int libinput_event_pointer_get_button(IntPtr ev);
[DllImport(LibInput)]
public extern static int libinput_event_pointer_get_button_state(IntPtr ev);
+
+ [DllImport(LibInput)]
+ public extern static LibInputPointerAxisSource libinput_event_pointer_get_axis_source(IntPtr ev);
+
+ [DllImport((LibInput))]
+ public extern static double libinput_event_pointer_get_axis_value_discrete(IntPtr ev, LibInputPointerAxis axis);
+
+ [DllImport(LibInput)]
+ public extern static double libinput_event_pointer_get_scroll_value_v120(IntPtr ev, LibInputPointerAxis axis);
}
}
diff --git a/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs b/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs
index 5c7ec2bbd2..a4d7d8b1eb 100644
--- a/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs
+++ b/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs
@@ -51,7 +51,16 @@ namespace Avalonia.LinuxFramebuffer.Output
if(connector == null)
throw new InvalidOperationException("Unable to find connected DRM connector");
- var mode = connector.Modes.OrderByDescending(x => x.IsPreferred)
+ DrmModeInfo? mode = null;
+
+ if (options?.VideoMode != null)
+ {
+ mode = connector.Modes
+ .FirstOrDefault(x => x.Resolution.Width == options.VideoMode.Value.Width &&
+ x.Resolution.Height == options.VideoMode.Value.Height);
+ }
+
+ mode ??= connector.Modes.OrderByDescending(x => x.IsPreferred)
.ThenByDescending(x => x.Resolution.Width * x.Resolution.Height)
//.OrderByDescending(x => x.Resolution.Width * x.Resolution.Height)
.FirstOrDefault();
diff --git a/src/Web/Avalonia.Web/Avalonia.Web.targets b/src/Web/Avalonia.Web/Avalonia.Web.targets
index b6a09b33ef..22363b33d8 100644
--- a/src/Web/Avalonia.Web/Avalonia.Web.targets
+++ b/src/Web/Avalonia.Web/Avalonia.Web.targets
@@ -12,7 +12,7 @@
true
-
+
true
full
true