Skip to content

Commit

Permalink
Update palm rejection (#182)
Browse files Browse the repository at this point in the history
* Use palm type instead of disabling transducer

* Remove extra check

* Remove unused FingerMajorMinorDiff setting

* Ugh this value needs to be configurable

* Do not try to detect size of wx/wy

* Make max contact size configurable

* Update palm rejection wording

* Update README
  • Loading branch information
1Revenger1 authored Oct 7, 2024
1 parent da3ccc2 commit fb93f3f
Show file tree
Hide file tree
Showing 6 changed files with 41 additions and 34 deletions.
15 changes: 9 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ There is no support for this kext being loaded into Library/Extensions or System

## Configuration

The values below can be edited under Info.plist within the kext itself - these can be changed without recompiling
The values below can be configured through either `ioio` or ACPI. An example SSDT can be found under [the ACPI examples folder](/docs/Acpi_Examples).
**Note** that using non-integer value causes undefined behaviour which may prevent the kext from loading

| Value | Default | Description |
Expand All @@ -120,13 +120,16 @@ The values below can be edited under Info.plist within the kext itself - these c
| `TrackpointScrollMultiplierY` | 20 | Same as the above, except applied to the Y axis |
| `TrackpointDeadzone` | 1 | Minimum value at which trackpoint reports will be accepted. This is subtracted from the input of the trackpoint, so setting this extremely high will reduce trackpoint resolution |
| `MinYDiffThumbDetection` | 200 | Minimum distance between the second lowest and lowest finger in which Minimum Y logic is used to detect the thumb rather than using the z value from the trackpad. Setting this higher means that the thumb must be farther from the other fingers before the y coordinate is used to detect the thumb, rather than using finger area. Keeping this smaller is preferable as finger area logic seems to only be useful when all 4 fingers are grouped together closely, where the thumb is more likely to be pressing down more |
| `FingerMajorMinorDiffMax` | 10 | Max difference between the width and height of a touch input before it's invalid |
| `PalmRejectionWidth` | 10 | Percent (out of 100) width of trackpad which is used for palm rejection on the left and right side of the trackpad |
| `PalmRejectionWidth` | 60 | Percent (out of 100) height of trackpad which is used for palm rejection on the left and right side of the trackpad (starting from the top) |
| `PalmRejectionTrackpointHeight` | 20 | Percent (out of 100) height of trackpad which is used for palm rejection across the top of the trackpad |
| `PalmRejectionMaxObjWidth` | 255 | Max contact width before contact is considered accidental. This value can be acquired by experimentation using Rehabman's `ioio`. |
| `PalmRejectionMaxObjHeight` | 255 | Max contact height before contact is considered accidental. This value can be acquired by experimentation using Rehabman's `ioio`. |
| `PalmRejectionWidth` | 10 | Percent (out of 100) width of trackpad which is used as a low confidence zone on the left and right side of the trackpad |
| `PalmRejectionWidth` | 60 | Percent (out of 100) height of trackpad which is used as a low confidence zone on the left and right side of the trackpad (starting from the top) |
| `PalmRejectionTrackpointHeight` | 20 | Percent (out of 100) height of trackpad which is used as a low confidence zone across the top of the trackpad |

Note that you can use Rehabman's ioio to set properties temporarily (until the next reboot).
`ioio -s RMIBus ForceTouchEmulation false`
`ioio -s RMIBus ForceTouchType 0`
`ioio -s RMIBus PalmRejectionMaxObjWidth 5`
`ioio -s RMIBus PalmRejectionMaxObjHeight 6`

## Building
1) `git submodule update --init --recursive`
Expand Down
4 changes: 3 additions & 1 deletion VoodooRMI/Configuration/RMIConfiguration.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,12 @@ struct RmiConfiguration {
/* RMI2DSensor */
uint32_t forceTouchMinPressure {80};
uint32_t minYDiffGesture {200};
uint32_t fingerMajorMinorMax {10};
// Time units are in milliseconds
uint64_t disableWhileTypingTimeout {2000};
uint64_t disableWhileTrackpointTimeout {2000};
// Palm Rejection
uint8_t palmRejectionMaxObjWidth {0xFF};
uint8_t palmRejectionMaxObjHeight {0xFF};
// Percentage out of 100
uint8_t palmRejectionWidth {15};
uint8_t palmRejectionHeight {80};
Expand Down
42 changes: 20 additions & 22 deletions VoodooRMI/Functions/Input/RMITrackpadFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,41 +154,35 @@ void RMITrackpadFunction::handleReport(RMI2DSensorReport *report)
((report->timestamp - lastTrackpointTS) < (conf.disableWhileTrackpointTimeout * MILLI_TO_NANO));

size_t maxIdx = report->fingers > MAX_FINGERS ? MAX_FINGERS : report->fingers;
size_t reportIdx = 0;
for (int i = 0; i < maxIdx; i++) {
rmi_2d_sensor_abs_object obj = report->objs[i];

bool isValidObj = obj.type == RMI_2D_OBJECT_FINGER ||
obj.type == RMI_2D_OBJECT_STYLUS; /*||*/
obj.type == RMI_2D_OBJECT_STYLUS ||
// Allow inaccurate objects as they are likely invalid, which we want to track still
// This can be a random finger or one which was lifted up slightly
// obj.type == RMI_2D_OBJECT_INACCURATE;
obj.type == RMI_2D_OBJECT_INACCURATE;

auto& transducer = inputEvent.transducers[reportIdx];
auto& transducer = inputEvent.transducers[i];
transducer.isTransducerActive = isValidObj;
transducer.secondaryId = i;

// Finger lifted, make finger valid
if (!isValidObj) {
if (fingerState[i] != RMI_FINGER_LIFTED) reportIdx++;
fingerState[i] = RMI_FINGER_LIFTED;
transducer.isPhysicalButtonDown = false;
transducer.currentCoordinates.pressure = 0;
continue;
}

validFingerCount++;
reportIdx++;

transducer.isTransducerActive = true;
transducer.previousCoordinates = transducer.currentCoordinates;
transducer.currentCoordinates.width = obj.z / 2.0;
transducer.timestamp = report->timestamp;

transducer.currentCoordinates.x = obj.x;
transducer.currentCoordinates.y = data.maxY - obj.y;

int deltaWidth = abs(obj.wx - obj.wy);

switch (fingerState[i]) {
case RMI_FINGER_LIFTED:
fingerState[i] = RMI_FINGER_STARTED_IN_ZONE;
Expand All @@ -214,13 +208,13 @@ void RMITrackpadFunction::handleReport(RMI2DSensorReport *report)
/* fall through */
case RMI_FINGER_VALID:
if (obj.z > RMI_2D_MAX_Z ||
deltaWidth > conf.fingerMajorMinorMax) {
obj.wx > conf.palmRejectionMaxObjWidth ||
obj.wy > conf.palmRejectionMaxObjHeight ||
obj.type == RMI_2D_OBJECT_INACCURATE) {

fingerState[i] = RMI_FINGER_INVALID;
}

transducer.isPhysicalButtonDown = clickpadState;

// Force touch emulation only works with clickpads (button underneath trackpad)
// Lock finger in place and in force touch until lifted
// Checks for VALID input before registering as force touch
Expand All @@ -236,24 +230,22 @@ void RMITrackpadFunction::handleReport(RMI2DSensorReport *report)
break;
}

transducer.isPhysicalButtonDown = false;
transducer.currentCoordinates = transducer.previousCoordinates;
transducer.currentCoordinates.pressure = RMI_MT2_MAX_PRESSURE;
break;
case RMI_FINGER_INVALID:
transducer.isTransducerActive = false;
continue;
break;
}

transducer.isTransducerActive = fingerState[i] == RMI_FINGER_VALID || fingerState[i] == RMI_FINGER_FORCE_TOUCH;
transducer.isTransducerActive = fingerState[i] != RMI_FINGER_STARTED_IN_ZONE && fingerState[i] != RMI_FINGER_LIFTED;

IOLogDebug("Finger num: %d (%s) (%d, %d) [Z: %u WX: %u WY: %u FingerType: %d Pressure : %d Button: %d]",
IOLogDebug("Finger num: %d (%s) (%d, %d) [Z: %u WX: %u WY: %u FingerType: %d Pressure: %d]",
i,
transducer.isTransducerActive ? "valid" : "invalid",
fingerState[i] != RMI_FINGER_INVALID ? "valid" : "invalid",
obj.x, obj.y, obj.z, obj.wx, obj.wy,
transducer.fingerType,
transducer.currentCoordinates.pressure,
transducer.isPhysicalButtonDown);
transducer.currentCoordinates.pressure
);
}

if (validFingerCount >= 4 && freeFingerTypes[kMT2FingerTypeThumb]) {
Expand All @@ -275,14 +267,20 @@ void RMITrackpadFunction::handleReport(RMI2DSensorReport *report)
if (trans.fingerType == kMT2FingerTypeUndefined) {
trans.fingerType = getFingerType();
}

if (fingerState[i] == RMI_FINGER_INVALID) {
freeFingerTypes[trans.fingerType] = true;
trans.fingerType = kMT2FingerTypePalm;
}
} else {
// Free finger
freeFingerTypes[trans.fingerType] = true;
trans.fingerType = kMT2FingerTypeUndefined;
}
}

inputEvent.contact_count = reportIdx;
inputEvent.transducers[0].isPhysicalButtonDown = clickpadState;
inputEvent.contact_count = validFingerCount;
inputEvent.timestamp = report->timestamp;

sendVoodooInputPacket(kIOMessageVoodooInputMessage, &inputEvent);
Expand Down
2 changes: 0 additions & 2 deletions VoodooRMI/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@
<integer>250</integer>
<key>DisableWhileTypingTimeout</key>
<integer>250</integer>
<key>FingerMajorMinorDiffMax</key>
<integer>10</integer>
<key>ForceTouchType</key>
<integer>1</integer>
<key>ForceTouchMinPressure</key>
Expand Down
7 changes: 4 additions & 3 deletions VoodooRMI/RMIBus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,8 @@ void RMIBus::updateConfiguration(OSDictionary* dictionary) {
update |= Configuration::loadUInt32Configuration(dictionary, "ForceTouchMinPressure", &conf.forceTouchMinPressure);
update |= Configuration::loadUInt32Configuration(dictionary, "ForceTouchType", reinterpret_cast<UInt32 *>(&conf.forceTouchType));
update |= Configuration::loadUInt32Configuration(dictionary, "MinYDiffThumbDetection", &conf.minYDiffGesture);
update |= Configuration::loadUInt32Configuration(dictionary, "FingerMajorMinorDiffMax", &conf.fingerMajorMinorMax);
update |= Configuration::loadUInt8Configuration(dictionary, "PalmRejectionMaxObjWidth", &conf.palmRejectionMaxObjWidth);
update |= Configuration::loadUInt8Configuration(dictionary, "PalmRejectionMaxObjHeight", &conf.palmRejectionMaxObjHeight);
update |= Configuration::loadUInt8Configuration(dictionary, "PalmRejectionWidth", &conf.palmRejectionWidth);
update |= Configuration::loadUInt8Configuration(dictionary, "PalmRejectionHeight", &conf.palmRejectionHeight);
update |= Configuration::loadUInt8Configuration(dictionary, "PalmRejectionTrackpointHeight", &conf.palmRejectionHeightTrackpoint);
Expand Down Expand Up @@ -303,8 +304,8 @@ void RMIBus::publishVoodooInputProperties() {
setProperty(VOODOO_INPUT_LOGICAL_MAX_X_KEY, trackpadData.maxX, 16);
setProperty(VOODOO_INPUT_LOGICAL_MAX_Y_KEY, trackpadData.maxY, 16);
// Need to be in 0.01mm units
setProperty(VOODOO_INPUT_PHYSICAL_MAX_X_KEY, trackpadData.sizeX * 100, 16);
setProperty(VOODOO_INPUT_PHYSICAL_MAX_Y_KEY, trackpadData.sizeY * 100, 16);
setProperty(VOODOO_INPUT_PHYSICAL_MAX_X_KEY, trackpadData.sizeX * 100, 32);
setProperty(VOODOO_INPUT_PHYSICAL_MAX_Y_KEY, trackpadData.sizeY * 100, 32);
setProperty(VOODOO_INPUT_TRANSFORM_KEY, 0ull, 32);

if (trackpointFunction != nullptr) {
Expand Down
5 changes: 5 additions & 0 deletions docs/Acpi_Examples/SSDT-VRMI-SBUS.dsl
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ DefinitionBlock ("", "SSDT", 2, "GWYD", "Set", 0) {
// 1 = Clickpad button + Size threshold
// 2 = Size threshold
"ForceTouchType", 0,
// Configure max contact size. These
// will very likely be different on
// other laptops.
"PalmRejectionMaxObjWidth", 5,
"PalmRejectionMaxObjHeight", 6
})
}
}

0 comments on commit fb93f3f

Please sign in to comment.