Пользовательские NSStatusItem и NSView ненадежно получают NSTrackingEvents
У меня есть приложение только в строке состояния, которое я пытаюсь отобразить на панели mouseOver. У меня есть пользовательский элемент состояния (и связанный с ним вид), подключенный и работающий, но прямоугольник отслеживания получает события только приблизительно через каждые дюжины запусков. Это заставляет меня верить, что где-то происходит гонка, но я не могу ее найти. В моем пользовательском представлении строки состояния:
- (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:
методы вызываются должным образом, меня полностью смущает. Что здесь происходит и что я делаю не так?
РЕДАКТИРОВАТЬ 17/17/2012
Я изменил код, основываясь на ответе @Streams, но увидел ту же проблему:
- (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];
}
РЕДАКТИРОВАТЬ 18/18/2012
Вот пример проекта barebones, который использует хорошо известный проект Github (написанный @Stream), чтобы показать проблему. Он не может получать события наведения мыши надежно, если вообще.
2 ответа
Я открыл запрос DTS, чтобы Apple взглянула на это. Вот ответ:
... вы используете полноэкранный режим в Xcode при запуске приложения. Я не делал этого [раньше], но теперь я могу воспроизвести проблему. Из того, что я могу сказать, это происходит только тогда, когда ваше приложение запускается из полноэкранного режима в XCode. Ваши пользователи не будут запускать приложение таким образом. Это проблема полноэкранного режима AppKit, а не обязательно вашего кода.
Я считаю, что вы должны управлять областями отслеживания только в -[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];
}