1

我正在制作一个类似于 GeekTool 的应用程序。我不太熟悉 GeekTool 在内部的工作方式,但它的外观和行为相似。基本上我有一个覆盖整个屏幕的无边框窗口,这很好用。我目前在“kCGDesktopIconWindowLevel”层上有窗口,但是我不能与桌面上的任何东西交互(移动/打开文件等)。当我在此级别( kCGDesktopIconWindowLevel-1 )下有一层窗口时,我可以与桌面交互,但不能与我的窗口交互,我需要能够交互。无论如何我可以从上层接收点击或将它们发送到下层吗?

顺便说一句,如果您对如何实现这一点有更好的想法但避免这个问题,我将不胜感激。

4

1 回答 1

1

我建议您在以下位置创建一个这样的事件点击(从这个答案中提取)applicationDidFinishLaunching:

CGEventMask emask;
CFMachPortRef myEventTap;
CFRunLoopSourceRef eventTapRLSrc;

// We only want one kind of event at the moment: Left mouse down
emask = CGEventMaskBit(kCGEventLeftMouseDown);

// Create the Tap
myEventTap = CGEventTapCreate (
    kCGSessionEventTap, // Catch all events for current user session
    kCGTailAppendEventTap, // Append to end of EventTap list
    kCGEventTapOptionListenOnly, // We only listen, we don't modify
    emask,
    &myEventTapCallback,
    NULL // We need no extra data in the callback
);

// Create a RunLoop Source for it
eventTapRLSrc = CFMachPortCreateRunLoopSource(
    kCFAllocatorDefault,
    myEventTap,
    0
);

// Add the source to the current RunLoop
CFRunLoopAddSource(
    CFRunLoopGetCurrent(),
    eventTapRLSrc,
    kCFRunLoopDefaultMode
);

将您的窗口设置为通常忽略鼠标事件——[myWindow setIgnoresMouseEvents: YES];

然后你的事件点击会寻找它想要“捕捉”的鼠标点击——像这样:

static CGEventRef myEventTapCallback (
    CGEventTapProxy proxy,
    CGEventType type,
    CGEventRef event,
    void * refcon
) {
    CGPoint mouseLocation;

    // If we would get different kind of events, we can distinguish them
    // by the variable "type", but we know we only get mouse moved events

    mouseLocation = CGEventGetLocation(event);

    // Figure out if the mouse is clicking on something we want to "catch"
    if (/* want this click */)
       [myWindow setIgnoresMouseEvents: NO];

    // Pass on the event, we must not modify it anyway, we are a listener
    return event;
}

鼠标事件完成后,将窗口返回到忽略鼠标事件。

于 2012-11-30T20:36:04.663 回答