From fb93f3f1b1d4285fca5f9e5b5db6a55979ef5ef3 Mon Sep 17 00:00:00 2001 From: Avery Black Date: Mon, 7 Oct 2024 08:29:52 -0700 Subject: [PATCH] Update palm rejection (#182) * 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 --- README.md | 15 ++++--- VoodooRMI/Configuration/RMIConfiguration.hpp | 4 +- .../Functions/Input/RMITrackpadFunction.cpp | 42 +++++++++---------- VoodooRMI/Info.plist | 2 - VoodooRMI/RMIBus.cpp | 7 ++-- docs/Acpi_Examples/SSDT-VRMI-SBUS.dsl | 5 +++ 6 files changed, 41 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 2a6e6ac..601beac 100644 --- a/README.md +++ b/README.md @@ -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 | @@ -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` diff --git a/VoodooRMI/Configuration/RMIConfiguration.hpp b/VoodooRMI/Configuration/RMIConfiguration.hpp index d6bcfe2..70ac318 100644 --- a/VoodooRMI/Configuration/RMIConfiguration.hpp +++ b/VoodooRMI/Configuration/RMIConfiguration.hpp @@ -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}; diff --git a/VoodooRMI/Functions/Input/RMITrackpadFunction.cpp b/VoodooRMI/Functions/Input/RMITrackpadFunction.cpp index f167477..2e81663 100644 --- a/VoodooRMI/Functions/Input/RMITrackpadFunction.cpp +++ b/VoodooRMI/Functions/Input/RMITrackpadFunction.cpp @@ -154,32 +154,28 @@ 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; @@ -187,8 +183,6 @@ void RMITrackpadFunction::handleReport(RMI2DSensorReport *report) 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; @@ -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 @@ -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]) { @@ -275,6 +267,11 @@ 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; @@ -282,7 +279,8 @@ void RMITrackpadFunction::handleReport(RMI2DSensorReport *report) } } - inputEvent.contact_count = reportIdx; + inputEvent.transducers[0].isPhysicalButtonDown = clickpadState; + inputEvent.contact_count = validFingerCount; inputEvent.timestamp = report->timestamp; sendVoodooInputPacket(kIOMessageVoodooInputMessage, &inputEvent); diff --git a/VoodooRMI/Info.plist b/VoodooRMI/Info.plist index f133063..f09b244 100644 --- a/VoodooRMI/Info.plist +++ b/VoodooRMI/Info.plist @@ -30,8 +30,6 @@ 250 DisableWhileTypingTimeout 250 - FingerMajorMinorDiffMax - 10 ForceTouchType 1 ForceTouchMinPressure diff --git a/VoodooRMI/RMIBus.cpp b/VoodooRMI/RMIBus.cpp index b045bb0..b954ef9 100644 --- a/VoodooRMI/RMIBus.cpp +++ b/VoodooRMI/RMIBus.cpp @@ -233,7 +233,8 @@ void RMIBus::updateConfiguration(OSDictionary* dictionary) { update |= Configuration::loadUInt32Configuration(dictionary, "ForceTouchMinPressure", &conf.forceTouchMinPressure); update |= Configuration::loadUInt32Configuration(dictionary, "ForceTouchType", reinterpret_cast(&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); @@ -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) { diff --git a/docs/Acpi_Examples/SSDT-VRMI-SBUS.dsl b/docs/Acpi_Examples/SSDT-VRMI-SBUS.dsl index 4c0d264..f333018 100644 --- a/docs/Acpi_Examples/SSDT-VRMI-SBUS.dsl +++ b/docs/Acpi_Examples/SSDT-VRMI-SBUS.dsl @@ -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 }) } }