自NSStatusItem和一个NSView无法可靠地接收NSTrackingEvents(Cust

2019-09-19 15:37发布

我有一个状态栏项目只有荫试图去显示在鼠标悬停在面板的应用程序。 我迷上了和工作的自定义状态项目(以及相关的视图),但跟踪RECT只接受每十多个发射事件。 这使我相信这是一个竞争条件发生的地方,但我不能找到它。 在我的自定义状态栏项目的看法:

- (id)initWithStatusItem:(NSStatusItem *)statusItem {
    CGFloat itemWidth = [statusItem length];
    CGFloat itemHeight = [[NSStatusBar systemStatusBar] thickness];
    NSRect itemRect = NSMakeRect(0.0, 0.0, itemWidth, itemHeight);
    NSLog(@"itemRect: %@", NSStringFromRect(itemRect));

    if ((self = [super initWithFrame:itemRect])) {
        _statusItem = statusItem;
        _statusItem.view = self;

        NSTrackingAreaOptions options = NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingActiveAlways;
        NSTrackingArea *trackingArea = [[NSTrackingArea alloc] initWithRect:itemRect
                                                                    options:options
                                                                      owner:self
                                                                   userInfo:nil];
        [self addTrackingArea:trackingArea];

        [self.window setIgnoresMouseEvents:NO];
        [self.window setAcceptsMouseMovedEvents:YES];

        self.wantsLayer = YES;
    }
    return self;
}

- (void)mouseEntered:(NSEvent *)theEvent {
    [[NSNotificationCenter defaultCenter] postNotificationName:UAStatusItemMouseEnteredNotification object:nil];
}

- (void)mouseExited:(NSEvent *)theEvent {
    [[NSNotificationCenter defaultCenter] postNotificationName:UAStatusItemMouseExitedNotification object:nil];
}

在大多数的推出,应用程序并不跟踪响应鼠标事件,但每隔一段时间, mouseEntered:mouseExited:方法被正确调用,完全混淆了我。 这到底是怎么回事,我究竟做错了什么?




编辑07月17
我改变了基于流@的答案代码,而是看到了同样的问题:

- (id)initWithStatusItem:(NSStatusItem *)statusItem {
    CGFloat itemWidth = [statusItem length];
    CGFloat itemHeight = [[NSStatusBar systemStatusBar] thickness];
    NSRect itemRect = NSMakeRect(0.0, 0.0, itemWidth, itemHeight);
    NSLog(@"itemRect: %@", NSStringFromRect(itemRect));

    if ((self = [super initWithFrame:itemRect])) {
        _statusItem = statusItem;
        _statusItem.view = self;            

        [self updateTrackingAreas];

        [self.window setIgnoresMouseEvents:NO];
        [self.window setAcceptsMouseMovedEvents:YES];

        self.wantsLayer = YES;
    }
    return self;
}

- (void)updateTrackingAreas {

    if (self.trackingArea)
        [self removeTrackingArea:self.trackingArea];

    [super updateTrackingAreas];

    self.trackingArea = [[NSTrackingArea alloc] initWithRect:CGRectZero
                                                     options:NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingInVisibleRect | NSTrackingActiveAlways
                                                       owner:self
                                                    userInfo:nil];
    [self addTrackingArea:self.trackingArea];
}




编辑2012年7月18日
这里是一个准系统示例项目使用一个众所周知的GitHub项目(由@Stream写的),借以说明问题。 它无法接收鼠标悬停事件可靠,如果在所有。

Answer 1:

我开了DTS要求有苹果看看这个。 这里是回应:

......你开始你的应用程序时使用全屏幕在Xcode。 我没有这样做[前],但我现在可以重现该问题。 从我可以告诉它只能发生在你的应用程序从全屏模式在Xcode中开始。 您的用户将不启动应用这种方式。 这是用了AppKit的全屏模式有问题,而不一定是你的代码。



Answer 2:

我相信你应该只在管理跟踪区域-[NSView updateTrackingAreas] 例如:

- (void)updateTrackingAreas
{
    if (_trackingArea) {
        [self removeTrackingArea:_trackingArea];
    }

    [super updateTrackingAreas];

    NSTrackingAreaOptions options = (NSTrackingMouseEnteredAndExited |
                                     NSTrackingMouseMoved |
                                     NSTrackingInVisibleRect |
                                     NSTrackingActiveAlways);
    _trackingArea = [[NSTrackingArea alloc] initWithRect:CGRectZero
                                                 options:options
                                                   owner:self
                                                userInfo:nil];
    [self addTrackingArea:_trackingArea];
}


文章来源: Custom NSStatusItem and NSView not reliably receiving NSTrackingEvents