You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MacOS下使用CGEventSetIntegerValueField反转鼠标X轴无效问题

问题:MacOS下反转Magic Trackpad 2 X轴移动无效

我尝试在MacOS上反转Magic Trackpad 2的X轴移动,据了解需要监听NSEventMaskMouseMoved并在callback中进行修改,以下是我的代码:

#import <Foundation/Foundation.h>
#import <CoreGraphics/CoreGraphics.h>
#import <CoreFoundation/CoreFoundation.h>
#import <AppKit/AppKit.h>


static CGEventRef callback(CGEventTapProxy proxy,
                            CGEventType type,
                            CGEventRef eventRef,
                            void *userInfo) {
    if (type == kCGEventMouseMoved) {
        // 获取原始Delta X值
        int64_t deltaX = CGEventGetIntegerValueField(eventRef, kCGMouseEventDeltaX);

        // 反转Delta X值
        int64_t invertedDeltaX = -deltaX;

        // 将反转后的Delta X值设置回原事件
        CGEventSetIntegerValueField(eventRef, kCGMouseEventDeltaX, invertedDeltaX);

        NSLog(@"Original Delta X: %lld", deltaX);
        NSLog(@"Inverted Delta X: %lld", invertedDeltaX);

        return eventRef;
    }

    return eventRef;
}


int main(int argc, const char * argv[]) {
    @autoreleasepool {
        CFMachPortRef tapPort = (CFMachPortRef)CGEventTapCreate(kCGSessionEventTap,
                                               kCGTailAppendEventTap,
                                               kCGEventTapOptionDefault,
                                               NSEventMaskMouseMoved,
                                               callback,
                                               nil);

        if (tapPort) {
            NSLog(@"tapPort created %p", tapPort);
            
            CFRunLoopSourceRef tapSource = (CFRunLoopSourceRef)CFMachPortCreateRunLoopSource(kCFAllocatorDefault, tapPort, 0);
            
            if (tapSource) {
                NSLog(@"tapSource created %p", tapSource);
                
                CFRunLoopAddSource(CFRunLoopGetMain(), tapSource, kCFRunLoopCommonModes);
                
//                CGEventTapEnable(tapSource, true);
                
                CFRunLoopRun();
            } else {
                NSLog(@"tapSource NOT created");
            }
        } else {
            NSLog(@"tapPort NOT created");
        }
        
        
    }
    return 0;
}

日志控制台显示一切正常(已授予Accessibility权限),但鼠标移动事件并未改变,似乎CGEventSetIntegerValueField没有起到作用。请问我是不是操作方式有误?


解决方案

你的代码存在几个关键问题,导致修改后的事件没有被系统正确处理:

1. 事件插入位置错误

你使用了kCGTailAppendEventTap,这会把你的事件tap添加到现有tap队列的末尾,意味着系统已经处理完原始事件后才会执行你的回调,修改后的事件不会影响系统的指针移动逻辑。

修正: 将kCGTailAppendEventTap改为kCGHeadInsertEventTap,让你的回调在系统处理事件之前执行,这样修改后的事件会被系统处理。

2. 事件掩码不完整

仅监听kCGEventMouseMoved不足以覆盖Trackpad的所有指针移动场景(比如拖拽操作时的kCGEventLeftMouseDragged、kCGEventRightMouseDragged等),导致部分移动行为没有被反转。

修正: 使用完整的鼠标移动相关事件掩码:

CGEventMask eventMask = CGEventMaskBit(kCGEventMouseMoved) | 
                        CGEventMaskBit(kCGEventLeftMouseDragged) | 
                        CGEventMaskBit(kCGEventRightMouseDragged) | 
                        CGEventMaskBit(kCGEventOtherMouseDragged);

然后在CGEventTapCreate中传入这个eventMask,替换原来的NSEventMaskMouseMoved。

3. CGEventTapEnable的参数错误且未启用

你注释掉了CGEventTapEnable,并且参数错误(应该传入tapPort而非tapSource),这会导致事件tap可能未正确启用。

修正: 取消注释该行,并修正参数:

CGEventTapEnable(tapPort, true);

修正后的完整代码

#import <Foundation/Foundation.h>
#import <CoreGraphics/CoreGraphics.h>
#import <CoreFoundation/CoreFoundation.h>
#import <AppKit/AppKit.h>


static CGEventRef callback(CGEventTapProxy proxy,
                            CGEventType type,
                            CGEventRef eventRef,
                            void *userInfo) {
    // 处理所有鼠标移动/拖拽事件
    if (type == kCGEventMouseMoved || 
        type == kCGEventLeftMouseDragged || 
        type == kCGEventRightMouseDragged || 
        type == kCGEventOtherMouseDragged) {
        // 获取原始Delta X值
        int64_t deltaX = CGEventGetIntegerValueField(eventRef, kCGMouseEventDeltaX);

        // 反转Delta X值
        int64_t invertedDeltaX = -deltaX;

        // 将反转后的Delta X值设置回原事件
        CGEventSetIntegerValueField(eventRef, kCGMouseEventDeltaX, invertedDeltaX);

        NSLog(@"Original Delta X: %lld", deltaX);
        NSLog(@"Inverted Delta X: %lld", invertedDeltaX);
    }

    return eventRef;
}


int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // 定义完整的鼠标移动事件掩码
        CGEventMask eventMask = CGEventMaskBit(kCGEventMouseMoved) | 
                                CGEventMaskBit(kCGEventLeftMouseDragged) | 
                                CGEventMaskBit(kCGEventRightMouseDragged) | 
                                CGEventMaskBit(kCGEventOtherMouseDragged);

        CFMachPortRef tapPort = (CFMachPortRef)CGEventTapCreate(kCGSessionEventTap,
                                               kCGHeadInsertEventTap,  // 改为头部插入
                                               kCGEventTapOptionDefault,
                                               eventMask,  // 使用完整掩码
                                               callback,
                                               nil);

        if (tapPort) {
            NSLog(@"tapPort created %p", tapPort);
            
            CFRunLoopSourceRef tapSource = (CFRunLoopSourceRef)CFMachPortCreateRunLoopSource(kCFAllocatorDefault, tapPort, 0);
            
            if (tapSource) {
                NSLog(@"tapSource created %p", tapSource);
                
                CFRunLoopAddSource(CFRunLoopGetMain(), tapSource, kCFRunLoopCommonModes);
                
                CGEventTapEnable(tapPort, true);  // 启用tap,参数修正为tapPort
                
                CFRunLoopRun();
            } else {
                NSLog(@"tapSource NOT created");
            }
        } else {
            NSLog(@"tapPort NOT created");
        }
    }
    return 0;
}

内容的提问来源于stack exchange,提问作者Martin Pham

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 15:07:19