Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to not send middle clicks to specific applications #91

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 54 additions & 17 deletions MiddleClick/Controller.m
Original file line number Diff line number Diff line change
Expand Up @@ -247,19 +247,21 @@ CGEventRef mouseCallback(CGEventTapProxy proxy, CGEventType type,
CGEventRef event, void* refcon)
{
if (needToClick) {
if (threeDown && type == kCGEventLeftMouseDown) {
wasThreeDown = YES;
CGEventSetType(event, kCGEventOtherMouseDown);
CGEventSetIntegerValueField(event, kCGMouseEventButtonNumber,
kCGMouseButtonCenter);
threeDown = NO;
}

if (wasThreeDown && type == kCGEventLeftMouseUp) {
wasThreeDown = NO;
CGEventSetType(event, kCGEventOtherMouseUp);
CGEventSetIntegerValueField(event, kCGMouseEventButtonNumber,
kCGMouseButtonCenter);
if (!isIgnoredAppBundle(CGEventGetLocation(event))) {
if (threeDown && type == kCGEventLeftMouseDown) {
wasThreeDown = YES;
CGEventSetType(event, kCGEventOtherMouseDown);
CGEventSetIntegerValueField(event, kCGMouseEventButtonNumber,
kCGMouseButtonCenter);
threeDown = NO;
}

if (wasThreeDown && type == kCGEventLeftMouseUp) {
wasThreeDown = NO;
CGEventSetType(event, kCGEventOtherMouseUp);
CGEventSetIntegerValueField(event, kCGMouseEventButtonNumber,
kCGMouseButtonCenter);
}
}
}
return event;
Expand Down Expand Up @@ -291,10 +293,12 @@ int touchCallback(int device, Finger* data, int nFingers, double timestamp,
CGPoint ourLoc = CGEventGetLocation(ourEvent);
CFRelease(ourEvent);

CGMouseButton buttonType = kCGMouseButtonCenter;

postMouseEvent(kCGEventOtherMouseDown, buttonType, ourLoc);
postMouseEvent(kCGEventOtherMouseUp, buttonType, ourLoc);
if (!isIgnoredAppBundle(ourLoc)) {
CGMouseButton buttonType = kCGMouseButtonCenter;

postMouseEvent(kCGEventOtherMouseDown, buttonType, ourLoc);
postMouseEvent(kCGEventOtherMouseUp, buttonType, ourLoc);
}
}
}
} else if (nFingers > 0 && touchStartTime == NULL) {
Expand Down Expand Up @@ -355,6 +359,39 @@ - (void)restartListeners
[self startUnstableListeners];
}

/// Check if window at a given point belongs to an ignored app bundle
static BOOL isIgnoredAppBundle(CGPoint point) {
NSArray* ignoredAppBundles = [[NSUserDefaults standardUserDefaults] arrayForKey:kIgnoredAppBundles];
// only check if there are ignored app bundles
if ([ignoredAppBundles count] == 0) {
return false;
}

point.y = [[NSScreen mainScreen] frame].size.height - point.y;

NSInteger windowNumber = [NSWindow windowNumberAtPoint:point belowWindowWithWindowNumber:0];

bool ignored = false;

CFArrayRef windows = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
for (NSDictionary* window in (__bridge NSArray*)windows) {
if ([window[(NSString*)kCGWindowNumber] integerValue] == windowNumber) {
int pid = (int)[window[(NSString*)kCGWindowOwnerPID] integerValue];
NSRunningApplication* app = [NSRunningApplication runningApplicationWithProcessIdentifier: pid];

NSString* appBundle = [app bundleIdentifier];
if ([ignoredAppBundles containsObject:appBundle]) {
ignored = true;
}

break;
}
}

CFRelease(windows);
return ignored;
}

/// Callback when a multitouch device is added.
void multitouchDeviceAddedCallback(void* _controller,
io_iterator_t iterator)
Expand Down
4 changes: 4 additions & 0 deletions MiddleClick/PreferenceKeys.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,7 @@
// The maximum interval in milliseconds between touch and release for a tap to be considered valid.
#define kMaxTimeDeltaMs @"maxTimeDelta"
#define kMaxTimeDeltaMsDefault 300

// List of applications that should be ignored
#define kIgnoredAppBundles @"ignoredAppBundles"
#define kIgnoredAppBundlesDefault [NSArray array]
2 changes: 2 additions & 0 deletions MiddleClick/main.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ int main(int argc, char* argv[])
kFingersNum,
kMaxDistanceDelta,
kMaxTimeDeltaMs,
kIgnoredAppBundles
};
id objects[] = {
[NSNumber numberWithInt:kFingersNumDefault],
[NSNumber numberWithFloat:kMaxDistanceDeltaDefault],
[NSNumber numberWithInt:kMaxTimeDeltaMsDefault],
[NSArray arrayWithArray:kIgnoredAppBundlesDefault]
};
NSUInteger count = sizeof(objects) / sizeof(id);
NSDictionary *appDefaults = [NSDictionary
Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,14 @@ defaults write com.rouge41.middleClick maxTimeDelta 150

> Default is 300

### Ignoring certain applications

- You can disable MiddleClick for certain app windows by providing a list of app bundles to ignore

```ps1
defaults write com.rouge41.middleClick ignoredAppBundles -array com.microsoft.rdc.macos com.apple.Terminal
```

---

<details>
Expand Down