6

我正在尝试使用以下代码获得 MacBook Pro 触控板压力:

CGEventRef eventTapCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef eventRef, void *refcon) {
    NSEvent *event = [NSEvent eventWithCGEvent:eventRef];

    NSLog(@"%lld", (int64_t)CGEventGetIntegerValueField(eventRef, kCGMouseEventPressure)); // returns 0
    NSLog(@"%lld", (int64_t)CGEventGetIntegerValueField(eventRef, kCGTabletEventPointPressure)); // returns 0
    NSLog(@"%lld", (int64_t)CGEventGetIntegerValueField(eventRef, kCGTabletEventTangentialPressure)); // returns 0

    NSLog(@"%f", [event pressure]); // Assertion failure

    return eventRef;
}

你知道怎么做吗?

4

2 回答 2

4

如果设备支持(即强制触摸触控板),则可以使用压力数据。自 2015 年左右以来,MacBook 上已经配备了 Force touch 触控板。Magic Trackpad 也提供 Force touch。

这篇博文有一个检测强制触摸设备的方法,虽然我没有尝试过。

我的机器是 2016 款 MacBook Pro,带有触控板。我可以使用以下代码获得压力:

[self.window trackEventsMatchingMask:NSEventMaskPressure 
    timeout:NSEventDurationForever 
    mode:NSEventTrackingRunLoopMode 
    handler:^(NSEvent * _Nonnull event, BOOL * _Nonnull stop) {
        NSLog(@"%f", event.pressure);
    }];

输出:

2018-02-09 18:16:10.986036-0800 forcetouch[4587:4164200] 0.437820
2018-02-09 18:16:10.993772-0800 forcetouch[4587:4164200] 0.457504
2018-02-09 18:16:11.001883-0800 forcetouch[4587:4164200] 0.476486
2018-02-09 18:16:11.010654-0800 forcetouch[4587:4164200] 0.494812
2018-02-09 18:16:11.017738-0800 forcetouch[4587:4164200] 0.512497
2018-02-09 18:16:11.028129-0800 forcetouch[4587:4164200] 0.529556
2018-02-09 18:16:11.033769-0800 forcetouch[4587:4164200] 0.546021
2018-02-09 18:16:11.042117-0800 forcetouch[4587:4164200] 0.561905
2018-02-09 18:16:11.049869-0800 forcetouch[4587:4164200] 0.577240

但是,我看到您正在使用事件水龙头。

我试过你的代码,当我检查时kCGMouseEventPressure我得到1. 当我检查时,event.pressure我也得到1. 所以我收到了一个你没有的值——我猜你没有强制触摸硬件?但我没有收到实际的压力值。

我不确定如何使用事件点击来获得它。

这适用于我的 2016 MacBook Pro。请注意,这台机器有一个强制触摸触控板。我不确定这会在没有强制触摸触控板的机器上返回什么。但是希望这能给你更多的想法。

开发人员的强制触摸

NSEvent - 压力

于 2018-02-10T02:13:22.953 回答
3

上面答案的片段:

[self.window trackEventsMatchingMask:NSEventMaskPressure 
    timeout:NSEventDurationForever 
    mode:NSEventTrackingRunLoopMode 
    handler:^(NSEvent * _Nonnull event, BOOL * _Nonnull stop) {
        NSLog(@"%f", event.pressure);
    }];

似乎正在阻止窗口响应任何鼠标事件。我认为这可能是由于https://developer.apple.com/documentation/appkit/nswindow/1419727-trackevents的这句话

每个事件都从事件队列中移除,然后传递给跟踪处理程序

我不是 Cocoa 事件架构方面的专家,但我突然想到会trackEventsMachingTask拦截事件。

我的解决方法是这样的:

NSEvent *(^monitor)(NSEvent *event) = ^NSEvent *(NSEvent *event) {
    NSLog(@"pressure = %f", event.pressure);
    return event;
};

[NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskPressure
                                      handler:monitor];

根据https://developer.apple.com/documentation/appkit/nsevent/1534971-addlocalmonitorforeventsaddLocalMonitorForEventsMatchingMask的 block 参数传递了指向事件的指针,只要 block 不返回nil,就会定期调度事件。

于 2019-02-16T06:29:05.353 回答