From f977d2228e22ffe7e3749e74a83bcd8708736346 Mon Sep 17 00:00:00 2001 From: lindexi Date: Sat, 23 Nov 2024 18:41:53 +0800 Subject: [PATCH] Fix the known valuator do not update. (#17321) * Fix the known valuator do not update. Before this change, the properties Pressure, Touch Major, and Touch Minor would not update when the device changed. After this change, the properties Pressure, Touch Major, and Touch Minor will refresh their values in response to device changes. * Fix to not setting a value to null when a property could not be found --- src/Avalonia.X11/XI2Manager.cs | 97 ++++++++++++++++++++-------------- 1 file changed, 56 insertions(+), 41 deletions(-) diff --git a/src/Avalonia.X11/XI2Manager.cs b/src/Avalonia.X11/XI2Manager.cs index d105fbaaad..0f7c71eb55 100644 --- a/src/Avalonia.X11/XI2Manager.cs +++ b/src/Avalonia.X11/XI2Manager.cs @@ -42,10 +42,15 @@ namespace Avalonia.X11 public DeviceInfo(XIDeviceInfo info) { Id = info.Deviceid; - Update(info.Classes, info.NumClasses); + UpdateCore(info.Classes, info.NumClasses); } public virtual void Update(XIAnyClassInfo** classes, int num) + { + UpdateCore(classes, num); + } + + private void UpdateCore(XIAnyClassInfo** classes, int num) { var valuators = new List(); var scrollers = new List(); @@ -73,8 +78,49 @@ namespace Avalonia.X11 private class PointerDeviceInfo : DeviceInfo { - public PointerDeviceInfo(XIDeviceInfo info) : base(info) + public PointerDeviceInfo(XIDeviceInfo info, X11Info x11Info) : base(info) + { + _x11 = x11Info; + + UpdateKnownValuator(); + } + + private readonly X11Info _x11; + + private void UpdateKnownValuator() + { + // ABS_MT_TOUCH_MAJOR ABS_MT_TOUCH_MINOR + // https://www.kernel.org/doc/html/latest/input/multi-touch-protocol.html + var touchMajorAtom = XInternAtom(_x11.Display, "Abs MT Touch Major", false); + var touchMinorAtom = XInternAtom(_x11.Display, "Abs MT Touch Minor", false); + + var pressureAtom = XInternAtom(_x11.Display, "Abs MT Pressure", false); + + PressureXIValuatorClassInfo = null; + TouchMajorXIValuatorClassInfo = null; + TouchMinorXIValuatorClassInfo = null; + + foreach (var xiValuatorClassInfo in Valuators) + { + if (xiValuatorClassInfo.Label == pressureAtom) + { + PressureXIValuatorClassInfo = xiValuatorClassInfo; + } + else if (xiValuatorClassInfo.Label == touchMajorAtom) + { + TouchMajorXIValuatorClassInfo = xiValuatorClassInfo; + } + else if (xiValuatorClassInfo.Label == touchMinorAtom) + { + TouchMinorXIValuatorClassInfo = xiValuatorClassInfo; + } + } + } + + public override void Update(XIAnyClassInfo** classes, int num) { + base.Update(classes, num); + UpdateKnownValuator(); } public bool HasScroll(ParsedDeviceEvent ev) @@ -94,16 +140,15 @@ namespace Avalonia.X11 return false; } - + + public XIValuatorClassInfo? PressureXIValuatorClassInfo { get; private set; } + public XIValuatorClassInfo? TouchMajorXIValuatorClassInfo { get; private set; } + public XIValuatorClassInfo? TouchMinorXIValuatorClassInfo { get; private set; } } private PointerDeviceInfo _pointerDevice; private AvaloniaX11Platform _platform; - private XIValuatorClassInfo? _pressureXIValuatorClassInfo; - private XIValuatorClassInfo? _touchMajorXIValuatorClassInfo; - private XIValuatorClassInfo? _touchMinorXIValuatorClassInfo; - public bool Init(AvaloniaX11Platform platform) { _platform = platform; @@ -115,42 +160,12 @@ namespace Avalonia.X11 { if (devices[c].Use == XiDeviceType.XIMasterPointer) { - _pointerDevice = new PointerDeviceInfo(devices[c]); + _pointerDevice = new PointerDeviceInfo(devices[c], _x11); break; } } if(_pointerDevice == null) return false; - - if (_multitouch) - { - // ABS_MT_TOUCH_MAJOR ABS_MT_TOUCH_MINOR - // https://www.kernel.org/doc/html/latest/input/multi-touch-protocol.html - var touchMajorAtom = XInternAtom(_x11.Display, "Abs MT Touch Major", false); - var touchMinorAtom = XInternAtom(_x11.Display, "Abs MT Touch Minor", false); - - var pressureAtom = XInternAtom(_x11.Display, "Abs MT Pressure", false); - - var pressureXIValuatorClassInfo = _pointerDevice.Valuators.FirstOrDefault(t => t.Label == pressureAtom); - if (pressureXIValuatorClassInfo.Label == pressureAtom) - { - // Why check twice? The XIValuatorClassInfo is struct, so the FirstOrDefault will return the default struct when not found. - _pressureXIValuatorClassInfo = pressureXIValuatorClassInfo; - } - - var touchMajorXIValuatorClassInfo = _pointerDevice.Valuators.FirstOrDefault(t => t.Label == touchMajorAtom); - if (touchMajorXIValuatorClassInfo.Label == touchMajorAtom) - { - _touchMajorXIValuatorClassInfo = touchMajorXIValuatorClassInfo; - } - - var touchMinorXIValuatorClassInfo = _pointerDevice.Valuators.FirstOrDefault(t => t.Label == touchMinorAtom); - if (touchMinorXIValuatorClassInfo.Label == touchMinorAtom) - { - _touchMinorXIValuatorClassInfo = touchMinorXIValuatorClassInfo; - } - } - /* int mask = 0; @@ -275,7 +290,7 @@ namespace Avalonia.X11 Position = ev.Position }; - if (_pressureXIValuatorClassInfo is {} valuatorClassInfo) + if (_pointerDevice.PressureXIValuatorClassInfo is {} valuatorClassInfo) { if (ev.Valuators.TryGetValue(valuatorClassInfo.Number, out var pressureValue)) { @@ -285,7 +300,7 @@ namespace Avalonia.X11 } } - if(_touchMajorXIValuatorClassInfo is {} touchMajorXIValuatorClassInfo) + if(_pointerDevice.TouchMajorXIValuatorClassInfo is {} touchMajorXIValuatorClassInfo) { double? touchMajor = null; double? touchMinor = null; @@ -308,7 +323,7 @@ namespace Avalonia.X11 if (touchMajor != null) { - if(_touchMinorXIValuatorClassInfo is {} touchMinorXIValuatorClassInfo) + if(_pointerDevice.TouchMinorXIValuatorClassInfo is {} touchMinorXIValuatorClassInfo) { if (ev.Valuators.TryGetValue(touchMinorXIValuatorClassInfo.Number, out var touchMinorValue)) {