【问题标题】:Remap `fn` to left mouse button on OSX将“fn”重新映射到 OSX 上的鼠标左键
【发布时间】:2017-10-30 20:35:58
【问题描述】:

我整天点击鼠标得了严重的肌腱炎。

过去我使用 Karabiner 重新映射 fn 键来模拟鼠标左键。但是它不适用于 Sierra。

我尝试在 Cocoa 中完成此操作,当我按下并释放 fn 时,它正确执行鼠标向下/向上操作。

但是它不处理双击/三次单击。

此外,在拖动时(例如拖动窗口或选择某些文本),在我按下键完成之前,视觉上没有任何反应。

如何调整我的代码来实现这一点?


首先我创建一个事件点击:

- (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 键向上/向下之外的任何事件,该事件将转换为鼠标左键向上/向下:

- (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;
}

编辑:Performing a double click using CGEventCreateMouseEvent()

编辑:OSX assign left mouse click to a keyboard key

【问题讨论】:

  • 我对这个问题没有任何贡献,但我要指出,Apple 非常致力于支持可访问性问题,这似乎是。我建议尝试在 Apple 找到合适的人,将其作为操作系统支持的功能提出来,该功能将出现在 System Prefs 的 Accessibility 面板中。实际上,您是否知道辅助功能中已经存在鼠标键功能?我从未尝试过,但我注意到它确实允许您使用数字键盘上的“5”键作为鼠标按钮的代理。
  • 对于双击和三次单击,您必须使用CGEventSetIntegerValueField() 设置事件的kCGMouseEventClickState 值。您可以通过跟踪最后一次的时间并与[NSEvent doubleClickInterval] 进行比较来确定点击是否足够快。您也应该跟踪位置,因为我认为点击之间的大移动会重置点击计数。对于拖动,您必须将鼠标移动的事件转换为鼠标拖动的事件(kCGEventLeftMouseDraggedNSEventTypeLeftMouseDragged)。
  • 怎么样。换手(至少 temp'y )。有没有想过用脚踏板来点击?我知道这听起来很傻,但它可能有帮助。最后,更换你使用的鼠标......也许试试像罗技的大理石鼠标这样的滚珠鼠标。
  • 做完这一切...
  • @Pi - 嗯。 . ,好吧,我必须附和 bhaller 所说的话——也许会引起 Apple 的注意?它当然不会受到伤害。你知道吗,我也会告诉他们。这是个好主意,实施起来也相当简单

标签: macos cocoa keyboard remap mouse-buttons


【解决方案1】:

Karabiner 现在适用于 macOS 10.12 及更高版本。

【讨论】:

    猜你喜欢
    • 2012-10-14
    • 2019-11-26
    • 1970-01-01
    • 2018-08-05
    • 2013-07-22
    • 2018-10-07
    • 1970-01-01
    • 2021-09-27
    • 1970-01-01
    相关资源
    最近更新 更多