Skip to content

Commit

Permalink
Fix the known valuator do not update.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
lindexi authored and walterlv committed Oct 22, 2024
1 parent cfa643a commit 2459157
Showing 1 changed file with 55 additions and 41 deletions.
96 changes: 55 additions & 41 deletions src/Avalonia.X11/XI2Manager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<XIValuatorClassInfo>();
var scrollers = new List<XIScrollClassInfo>();
Expand Down Expand Up @@ -71,8 +76,48 @@ public void UpdateValuators(Dictionary<int, double> 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)
Expand All @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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))
{
Expand All @@ -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;
Expand All @@ -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))
{
Expand Down

0 comments on commit 2459157

Please sign in to comment.