From 2459157d991cec82e6d703daa25f9671d1795d2a Mon Sep 17 00:00:00 2001 From: lindexi Date: Tue, 22 Oct 2024 10:21:53 +0800 Subject: [PATCH] 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. --- src/Avalonia.X11/XI2Manager.cs | 96 +++++++++++++++++++--------------- 1 file changed, 55 insertions(+), 41 deletions(-) diff --git a/src/Avalonia.X11/XI2Manager.cs b/src/Avalonia.X11/XI2Manager.cs index fb46fa8222f..22a8f708de4 100644 --- a/src/Avalonia.X11/XI2Manager.cs +++ b/src/Avalonia.X11/XI2Manager.cs @@ -40,10 +40,15 @@ private class DeviceInfo 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(); @@ -71,8 +76,48 @@ public void UpdateValuators(Dictionary valuators) 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); + + var pressureXIValuatorClassInfo = 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 = Valuators.FirstOrDefault(t => t.Label == touchMajorAtom); + if (touchMajorXIValuatorClassInfo.Label == touchMajorAtom) + { + TouchMajorXIValuatorClassInfo = touchMajorXIValuatorClassInfo; + } + + var touchMinorXIValuatorClassInfo = Valuators.FirstOrDefault(t => t.Label == touchMinorAtom); + if (touchMinorXIValuatorClassInfo.Label == touchMinorAtom) + { + TouchMinorXIValuatorClassInfo = touchMinorXIValuatorClassInfo; + } + } + + public override void Update(XIAnyClassInfo** classes, int num) + { + base.Update(classes, num); + UpdateKnownValuator(); } public bool HasScroll(ParsedDeviceEvent ev) @@ -92,16 +137,15 @@ public bool HasMotion(ParsedDeviceEvent ev) 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; @@ -113,42 +157,12 @@ public bool Init(AvaloniaX11Platform platform) { 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; @@ -273,7 +287,7 @@ private void OnDeviceEvent(IXI2Client client, ParsedDeviceEvent ev) Position = ev.Position }; - if (_pressureXIValuatorClassInfo is {} valuatorClassInfo) + if (_pointerDevice.PressureXIValuatorClassInfo is {} valuatorClassInfo) { if (ev.Valuators.TryGetValue(valuatorClassInfo.Number, out var pressureValue)) { @@ -283,7 +297,7 @@ private void OnDeviceEvent(IXI2Client client, ParsedDeviceEvent ev) } } - if(_touchMajorXIValuatorClassInfo is {} touchMajorXIValuatorClassInfo) + if(_pointerDevice.TouchMajorXIValuatorClassInfo is {} touchMajorXIValuatorClassInfo) { double? touchMajor = null; double? touchMinor = null; @@ -304,7 +318,7 @@ private void OnDeviceEvent(IXI2Client client, ParsedDeviceEvent ev) if (touchMajor != null) { - if(_touchMinorXIValuatorClassInfo is {} touchMinorXIValuatorClassInfo) + if(_pointerDevice.TouchMinorXIValuatorClassInfo is {} touchMinorXIValuatorClassInfo) { if (ev.Valuators.TryGetValue(touchMinorXIValuatorClassInfo.Number, out var touchMinorValue)) {