Skip to content
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
3 changes: 3 additions & 0 deletions HapticKey/Classes/HTKEventTap.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ NS_ASSUME_NONNULL_BEGIN
@protocol HTKEventTapDelegate <NSObject>

@optional
- (void)eventTap:(HTKEventTap *)eventTap didTapCGEvent:(CGEventRef)eventRef;
// Implement this only when the delegate needs to use `NSEvent` for all tapped event.
// In many cases, using `CGEvent` without creating `NSEvent` may be faster and cheap.
- (void)eventTap:(HTKEventTap *)eventTap didTapEvent:(NSEvent *)event;
- (void)eventTapDisabled:(HTKEventTap *)eventTap;

Expand Down
14 changes: 10 additions & 4 deletions HapticKey/Classes/HTKEventTap.m
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,18 @@ static CGEventRef EventTapCallback(CGEventTapProxy proxy, CGEventType type, CGE
break;
}
default: {
// `eventWithCGEvent:` returns an autoreleased `NSEvent` that retains given `CGEvent`.
// without `@autoreleasepool`, this will may leak and also `CGEvent` as well.
NSEvent * const event = [NSEvent eventWithCGEvent:eventRef];

id<HTKEventTapDelegate> const delegate = eventTap.delegate;
if ([delegate respondsToSelector:@selector(eventTap:didTapCGEvent:)]) {
[delegate eventTap:eventTap didTapCGEvent:eventRef];
}

if ([delegate respondsToSelector:@selector(eventTap:didTapEvent:)]) {
// `eventWithCGEvent:` is relatively expensive.
// Do not implement `eventTap:didTapEvent:` if it's not needed.
// NOTE: `eventWithCGEvent:` returns an autoreleased `NSEvent` that retains given `CGEvent`.
// without `@autoreleasepool`, this will may leak and also `CGEvent` as well.
NSEvent * const event = [NSEvent eventWithCGEvent:eventRef];

[delegate eventTap:eventTap didTapEvent:event];
}
break;
Expand Down
15 changes: 10 additions & 5 deletions HapticKey/Classes/HTKFunctionKeyEventListener.m
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,18 @@ - (BOOL)isEnabled

// MARK: - HTKEventTapDelegate

- (void)eventTap:(HTKEventTap *)eventTap didTapEvent:(NSEvent *)event
- (void)eventTap:(HTKEventTap *)eventTap didTapCGEvent:(CGEventRef)eventRef
{
const int64_t keyboardType = CGEventGetIntegerValueField(event.CGEvent, kCGKeyboardEventKeyboardType);
if (keyboardType == kTouchbarKeyboardType && !event.ARepeat) {
const CGEventType eventType = CGEventGetType(eventRef);

const int64_t keyboardType = CGEventGetIntegerValueField(eventRef, kCGKeyboardEventKeyboardType);
const int64_t autorepeat = CGEventGetIntegerValueField(eventRef, kCGKeyboardEventAutorepeat);
const int64_t keycode = CGEventGetIntegerValueField(eventRef, kCGKeyboardEventKeycode);

if (keyboardType == kTouchbarKeyboardType && autorepeat == 0) {
for (NSUInteger index = 0; index < kNumberOfEscAndFunctionKeycodes; index += 1) {
if (kEscAndFunctionKeycodes[index] == event.keyCode) {
switch (event.type) {
if (kEscAndFunctionKeycodes[index] == keycode) {
switch (eventType) {
case NSEventTypeKeyDown:
[self _htk_main_didListenEvent:[[HTKEvent alloc] initWithPhase:HTKEventPhaseBegin]];
break;
Expand Down
35 changes: 22 additions & 13 deletions HapticKey/Classes/HTKTapGestureEventListener.m
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,12 @@
#import "NSTouchDevice.h"

@import AppKit;
@import IOKit;

NS_ASSUME_NONNULL_BEGIN

static const uint32_t kCGEventFieldTouchContextID = 0x92;

@interface HTKTapGestureEventListener () <HTKEventTapDelegate>

@property (nonatomic, readonly) HTKEventTap *eventTap;
Expand Down Expand Up @@ -47,20 +50,26 @@ - (BOOL)isEnabled

// MARK: - HTKEventTapDelegate

- (void)eventTap:(HTKEventTap *)eventTap didTapEvent:(NSEvent *)event
- (void)eventTap:(HTKEventTap *)eventTap didTapCGEvent:(CGEventRef)eventRef
{
for (NSTouch * const touch in [event allTouches]) {
NSTouchDevice * const touchDevice = touch.device;
if (!touch.resting && touchDevice.deviceType == NSTouchDeviceTypeTouchBar) {
switch (touch.phase) {
case NSTouchPhaseBegan:
[self _htk_main_didListenEvent:[[HTKEvent alloc] initWithPhase:HTKEventPhaseBegin]];
return;
case NSTouchPhaseEnded:
[self _htk_main_didListenEvent:[[HTKEvent alloc] initWithPhase:HTKEventPhaseEnd]];
return;
default:
break;
// `eventWithCGEvent:` is relatively expensive.
// Check touch contextID exists or not first. All touches on TouchBar has this ID.
const int64_t contextID = CGEventGetIntegerValueField(eventRef, kCGEventFieldTouchContextID);
if (contextID != 0) {
NSEvent * const event = [NSEvent eventWithCGEvent:eventRef];
for (NSTouch * const touch in [event allTouches]) {
NSTouchDevice * const touchDevice = touch.device;
if (!touch.resting && touchDevice.deviceType == NSTouchDeviceTypeTouchBar) {
switch (touch.phase) {
case NSTouchPhaseBegan:
[self _htk_main_didListenEvent:[[HTKEvent alloc] initWithPhase:HTKEventPhaseBegin]];
return;
case NSTouchPhaseEnded:
[self _htk_main_didListenEvent:[[HTKEvent alloc] initWithPhase:HTKEventPhaseEnd]];
return;
default:
break;
}
}
}
}
Expand Down