将fn重新映射到OSX上的鼠标左键 [英] Remap `fn` to left mouse button on OSX
问题描述
整天单击鼠标会导致严重的肌腱炎.
I get bad tendinitis from clicking the mouse all day.
过去,我使用Karabiner重新映射fn
键以模拟鼠标左键.但是,它不适用于Sierra.
In the past I used Karabiner to remap the fn
key to simulate a left mouse button. However it doesn't work with Sierra.
我试图在Cocoa中完成此操作,当我按下并释放fn
时,它可以正确地执行鼠标向下/向上操作.
I tried to accomplish this in Cocoa, and it correctly performs mouse-down/up when I press and release fn
.
但是它不能处理双击/三次单击.
However it doesn't handle double-click / triple-click.
另外,在拖动(例如,拖动窗口或选择某些文本)时,在我键入命令之前,视觉上不会发生任何事情,从而完成了操作.
Also when dragging, (e.g. dragging a window, or selecting some text) nothing happens visually until I key-up, whereupon it completes.
如何修改我的代码以实现此目的?
How can I adapt my code to implement this?
首先,我创建一个事件水龙头:
First I create an event tap:
- (BOOL)tapEvents
{
_modifiers = [NSEvent modifierFlags];
if ( ! _eventTap ) {
NSLog( @"Initializing an event tap." );
// kCGHeadInsertEventTap -- new event tap should be inserted before
// any pre-existing event taps at the same location,
_eventTap = CGEventTapCreate( kCGHIDEventTap, // kCGSessionEventTap,
kCGHeadInsertEventTap,
kCGEventTapOptionDefault,
CGEventMaskBit( kCGEventKeyDown )
| CGEventMaskBit( kCGEventFlagsChanged )
| CGEventMaskBit( NSSystemDefined )
,
(CGEventTapCallBack)_tapCallback,
(__bridge void *)(self));
if ( ! _eventTap ) {
NSLog(@"unable to create event tap. must run as root or "
"add privlidges for assistive devices to this app.");
return NO;
}
}
CGEventTapEnable( _eventTap, YES );
return [self isTapActive];
}
现在我实现回调:
CGEventRef _tapCallback(
CGEventTapProxy proxy,
CGEventType type,
CGEventRef event,
Intercept* listener
)
{
//Do not make the NSEvent here.
//NSEvent will throw an exception if we try to make an event from the tap timout type
@autoreleasepool {
if( type == kCGEventTapDisabledByTimeout ) {
NSLog(@"event tap has timed out, re-enabling tap");
[listener tapEvents];
return nil;
}
if( type != kCGEventTapDisabledByUserInput ) {
return [listener processEvent:event];
}
}
return event;
}
最后,我实现了一个processEvent
,它将通过fn键上/下键之外的任何事件进行传递,该事件将转换为鼠标左上/下键:
Finally I implement a processEvent
that will pass through any event apart from fn key up/down, which will get converted to left mouse up/down:
- (CGEventRef)processEvent:(CGEventRef)cgEvent
{
//NSLog( @"- - - - - - -" );
NSEvent* event = [NSEvent eventWithCGEvent:cgEvent];
//NSLog(@"%d,%d", event.data1, event.data2);
//NSEventType type = [event type];
NSUInteger m = event.modifierFlags &
( NSCommandKeyMask | NSAlternateKeyMask | NSShiftKeyMask | NSControlKeyMask | NSAlphaShiftKeyMask | NSFunctionKeyMask );
NSUInteger flags_changed = _modifiers ^ m;
_modifiers = m;
switch( event.type ) {
case NSFlagsChanged:
{
assert(flags_changed);
//NSLog(@"NSFlagsChanged: %d, event.modifierFlags: %lx", event.keyCode, event.modifierFlags);
if( flags_changed & NSFunctionKeyMask ) {
bool isDown = _modifiers & NSFunctionKeyMask;
CGEventType evType = isDown ? kCGEventLeftMouseDown : kCGEventLeftMouseUp;
CGPoint pt = [NSEvent mouseLocation];
CGPoint mousePoint = CGPointMake(pt.x, [NSScreen mainScreen].frame.size.height - pt.y);
CGEventRef theEvent = CGEventCreateMouseEvent(NULL, evType, mousePoint, kCGMouseButtonLeft);
CGEventSetType(theEvent, evType);
CGEventPost(kCGHIDEventTap, theEvent);
CFRelease(theEvent);
//return theEvent;
}
break;
}
}
_lastEvent = [event CGEvent];
CFRetain(_lastEvent); // must retain the event. will be released by the system
return _lastEvent;
}
使用CGEventCreateMouseEvent()进行双击
推荐答案
Karabiner 现在可在macOS上运行10.12及更高版本.
Karabiner now works on macOS 10.12 and later.
这篇关于将fn重新映射到OSX上的鼠标左键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!