2

Is it possible to check if an NSStatusItem is visible in the system menu bar? It sometimes isn't due to the user having too many status items and the active application menu bar size.

I can check the location of the of the status item via a "hack" like so:

statusRect = [[_statusItem valueForKey:@"window"] frame];

But I can't do the same for is visible: (it always returns true)

BOOL visible = [[_statusItem valueForKey:@"window"] isVisible];
Peter Hosey
  • 95,783
  • 15
  • 211
  • 370
  • Documentation for `isVisible`: “Indicates whether the window is visible onscreen (even when It’s obscured by other windows).” (or menus, although that isn't normally a concern.) – Peter Hosey Mar 29 '13 at 15:25
  • @PeterHosey - thanks, but is there any way around this (to find out if it's really visible without being obscured) –  Mar 29 '13 at 17:06
  • Have you checked if the frame for a hidden item is distinct from one that's showing? `-[NSWindow isVisible]` mostly just indicates if the window has been ordered in. You should check `-screen`. A window only has a screen if its frame overlaps a screen frame. Have you checked the status item's view instead of its window? You should check if the view's `window` is `nil` and whether it `isHidden`. (You may need to assign a custom view to the status item to have something to check.) – Ken Thomases Apr 01 '13 at 12:08

1 Answers1

1

I dont believe it's doable without really bad hacks

My first though:

Have a view in your NSStatusItem and combine the window.isVisible with the view's visibleRect. The status bar can't be obscured by windows anyway.
=> didn't work

2. Try

Have a view in your NSStatusItem and try the hack from Proper way to determine if NSView is drawn
=> didn't work

REALLY evil hack that might work

simulate Mouse Clicks via the accessibility api and see if your view gets the event :


what I tried

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    // Insert code here to initialize your application
    item = [[[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength] retain];
    item.title = @"TEST";
    view = [[DDQuickMenuStatusItemView alloc] init];
    view.item = item;
    view.title = item.title;
    item.view = view;
    
    [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(checkVisible:) userInfo:nil repeats:YES];
}

- (void)checkVisible:(id)timer {
    NSLog(@"NOT WORKING vis: %d", (view.window.isVisible && !NSEqualRects(view.visibleRect, NSZeroRect)));
    NSLog(@"NOT WORKING isDrawn: %d", (view.isDrawn));
}
Community
  • 1
  • 1
Daij-Djan
  • 49,552
  • 17
  • 113
  • 135
  • 2
    Thanks for your hard work! I found a solution thanks to you. Using the accessibility api, I can find the AXUIElelementRef a the view position using AXUIElementCopyElementAtPosition. Then I simply compare the PID (AXUIElementGetPid) with my application PID. –  Apr 02 '13 at 13:05
  • 1
    nice, didn't think of that API! – Daij-Djan Apr 02 '13 at 13:29
  • For those that are interested in how Wesley did this, here's a link that describes some of the work involved: http://stackoverflow.com/a/27589911/869838 – shmim May 22 '15 at 15:21