Skip to content

28 thumb bug - #29

Merged
NullPointerDepressiveDisorder merged 9 commits into
mainfrom
28-thumb-bug
Dec 20, 2025
Merged

28 thumb bug#29
NullPointerDepressiveDisorder merged 9 commits into
mainfrom
28-thumb-bug

Conversation

@NullPointerDepressiveDisorder

@NullPointerDepressiveDisorder NullPointerDepressiveDisorder commented Dec 19, 2025

Copy link
Copy Markdown
Owner

This pull request adds comprehensive palm rejection features to MiddleDrag, improving gesture reliability and reducing accidental activations caused by palms or unintended touches. It introduces three configurable palm rejection methods—exclusion zone, modifier key requirement, and contact size filtering—along with a new menu section for user configuration. Preferences are persisted, and the gesture recognizer logic is updated to enforce these new filters.

Palm Rejection Features:

  • Added three palm rejection methods:
    • Exclusion zone (ignores touches in the bottom portion of the trackpad).
    • Modifier key requirement (gesture only activates when a specific modifier key is held).
    • Contact size filter (ignores touches with a large contact area, typical of palms). [1] [2] [3] [4] [5] [6]

User Preferences and Configuration:

  • Extended UserPreferences and GestureConfiguration to support new palm rejection options, including their default values and conversion logic. [1] [2] [3]
  • Updated PreferencesManager to persist new palm rejection settings and ensure correct loading/saving from UserDefaults. [1] [2]

Menu Bar UI Enhancements:

  • Added a "Palm Rejection" submenu in the menu bar with options to enable/disable each palm rejection method and select their parameters (zone size, modifier key type, contact size threshold). [1] [2]
  • Implemented corresponding action handlers to update preferences and reconfigure the gesture recognizer when palm rejection settings change.

Gesture Recognition Logic:

  • Updated the gesture recognizer to apply palm rejection filters before processing touches, ensuring only valid fingers are considered for gesture activation. [1] [2]

General Code Improvements:

  • Minor formatting and code style improvements in menu construction for better readability and maintainability. [1] [2] [3]

These changes provide users with robust control over palm rejection, reducing false positives and improving the overall experience when using MiddleDrag.

- Add ModifierKeyType enum with shift/control/option/command
- Add exclusion zone preferences (enabled, size)
- Add modifier key preferences (requireKey, keyType)
- Add contact size filter preferences (enabled, maxSize)
- Update GestureConfiguration with palm rejection fields
- Update UserPreferences.gestureConfig to include new options
- Add UserDefaults keys for exclusion zone settings
- Add UserDefaults keys for modifier key settings
- Add UserDefaults keys for contact size filter settings
- Register defaults for all new preferences
- Update loadPreferences() to load new settings
- Update savePreferences() to persist new settings
- Add modifier key check at start of processTouches()
- Filter touches in exclusion zone (bottom of trackpad)
- Filter touches exceeding max contact size threshold
- Add getModifierFlags() helper using CGEventSource
- Cancel active gesture if modifier key released
- Add createPalmRejectionMenu() with three sections
- Add exclusion zone toggle and size options (10-25%)
- Add modifier key toggle and key type selector
- Add contact size filter toggle and threshold options
- Add action methods for all new preferences
- Dynamically show/hide options based on toggle state
Copilot AI review requested due to automatic review settings December 19, 2025 20:02
@NullPointerDepressiveDisorder NullPointerDepressiveDisorder linked an issue Dec 19, 2025 that may be closed by this pull request
@NullPointerDepressiveDisorder NullPointerDepressiveDisorder added the bug Something isn't working label Dec 19, 2025
Comment thread MiddleDrag/Core/GestureRecognizer.swift Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds palm rejection functionality to prevent accidental activation of gestures by thumbs/palms resting on the trackpad. The implementation provides three configurable palm rejection methods to improve gesture recognition accuracy.

Key Changes:

  • Added exclusion zone filtering to ignore touches in the bottom portion of the trackpad where palms typically rest
  • Added modifier key requirement option to require holding a key (Shift/Control/Option/Command) for gesture activation
  • Added contact size filtering to reject large touch contacts that are likely palms rather than intentional finger touches

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
MiddleDrag/Utilities/PreferencesManager.swift Added persistence layer for six new palm rejection preferences (exclusion zone, modifier key, and contact size filter settings)
MiddleDrag/UI/MenuBarController.swift Added comprehensive UI controls in the Advanced menu for configuring all three palm rejection methods with dynamic sub-options
MiddleDrag/Models/GestureModels.swift Added ModifierKeyType enum and six new fields to GestureConfiguration and UserPreferences for palm rejection settings
MiddleDrag/Core/GestureRecognizer.swift Implemented palm rejection logic: modifier key checking, exclusion zone filtering, and contact size filtering in touch processing

Comment thread MiddleDrag/Core/GestureRecognizer.swift
Comment thread MiddleDrag/Core/GestureRecognizer.swift
Comment thread MiddleDrag/Models/GestureModels.swift
- Add tests for GestureConfiguration palm rejection defaults
- Add tests for UserPreferences palm rejection defaults
- Add test for UserPreferences -> GestureConfiguration mapping
- Add tests for ModifierKeyType display names and raw values
- Add test for ModifierKeyType CaseIterable conformance
- Add new test file GestureRecognizerTests.swift with 12 tests
- Add tests for modifier key requirement (all 4 types)
- Add tests for exclusion zone filtering
- Add tests for contact size filtering
- Add combined filter test
- Add GestureRecognizer.swift to test target

Includes MockGestureRecognizerDelegate for testing callbacks.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.

Comment thread MiddleDrag/Managers/MultitouchManager.swift Outdated
Comment thread MiddleDragTests/GestureRecognizerTests.swift
The comment claimed modifier flags were captured on the main thread,
but deviceMonitor callback actually runs on a framework-managed
background thread. CGEventSource.flagsState is thread-safe per Apple
docs, so this is fine, but the comment was inaccurate.
Add 4 new tests for scenarios where some touches are filtered
while others pass palm rejection filters:

- testExclusionZone_PartialFiltering_FiveTouchesThreePass
- testContactSizeFilter_PartialFiltering_FiveTouchesThreePass
- testCombinedFilters_PartialFiltering_SixTouchesThreePass
- testPartialFiltering_InsufficientRemainingTouches

These verify gestures activate when exactly 3 valid touches
remain after filtering, regardless of total touch count.
@NullPointerDepressiveDisorder
NullPointerDepressiveDisorder merged commit 7c8e289 into main Dec 20, 2025
6 checks passed
@NullPointerDepressiveDisorder
NullPointerDepressiveDisorder deleted the 28-thumb-bug branch December 20, 2025 12:57
middledrag-releaser Bot pushed a commit that referenced this pull request Dec 20, 2025
* feat: add ModifierKeyType enum and palm rejection preferences

- Add ModifierKeyType enum with shift/control/option/command
- Add exclusion zone preferences (enabled, size)
- Add modifier key preferences (requireKey, keyType)
- Add contact size filter preferences (enabled, maxSize)
- Update GestureConfiguration with palm rejection fields
- Update UserPreferences.gestureConfig to include new options

* feat: add persistence for palm rejection preferences

- Add UserDefaults keys for exclusion zone settings
- Add UserDefaults keys for modifier key settings
- Add UserDefaults keys for contact size filter settings
- Register defaults for all new preferences
- Update loadPreferences() to load new settings
- Update savePreferences() to persist new settings

* feat: implement palm rejection touch filtering

- Add modifier key check at start of processTouches()
- Filter touches in exclusion zone (bottom of trackpad)
- Filter touches exceeding max contact size threshold
- Add getModifierFlags() helper using CGEventSource
- Cancel active gesture if modifier key released

* feat: add Palm Rejection submenu to Advanced menu

- Add createPalmRejectionMenu() with three sections
- Add exclusion zone toggle and size options (10-25%)
- Add modifier key toggle and key type selector
- Add contact size filter toggle and threshold options
- Add action methods for all new preferences
- Dynamically show/hide options based on toggle state

* refactor: Pass modifier flags to gesture recognizer from main thread for reliable state.

* test: add palm rejection configuration and ModifierKeyType tests

- Add tests for GestureConfiguration palm rejection defaults
- Add tests for UserPreferences palm rejection defaults
- Add test for UserPreferences -> GestureConfiguration mapping
- Add tests for ModifierKeyType display names and raw values
- Add test for ModifierKeyType CaseIterable conformance

* test: add GestureRecognizerTests for palm rejection filters

- Add new test file GestureRecognizerTests.swift with 12 tests
- Add tests for modifier key requirement (all 4 types)
- Add tests for exclusion zone filtering
- Add tests for contact size filtering
- Add combined filter test
- Add GestureRecognizer.swift to test target

Includes MockGestureRecognizerDelegate for testing callbacks.

* docs: fix misleading comment about thread context

The comment claimed modifier flags were captured on the main thread,
but deviceMonitor callback actually runs on a framework-managed
background thread. CGEventSource.flagsState is thread-safe per Apple
docs, so this is fine, but the comment was inaccurate.

* test: add partial filter tests for palm rejection

Add 4 new tests for scenarios where some touches are filtered
while others pass palm rejection filters:

- testExclusionZone_PartialFiltering_FiveTouchesThreePass
- testContactSizeFilter_PartialFiltering_FiveTouchesThreePass
- testCombinedFilters_PartialFiltering_SixTouchesThreePass
- testPartialFiltering_InsufficientRemainingTouches

These verify gestures activate when exactly 3 valid touches
remain after filtering, regardless of total touch count.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Three Finger Activation

2 participants