简体   繁体   中英

Mavericks and NSStatusItem's custom view with multiple monitors

Since Mavericks each screen has its own status bar. This also means that an application running in the status bar (using NSStatusItem) theoretically has multiple NSStatusItem objects associated. In practice, although the user might see multiple "instances" of your NSStatusItem, it's just one (I've tested this). Now the following problem occurs when you're working with a custom view in your status icon: when the user clicks the status icon, I programmatically "highlight" it using the drawStatusBarBackgroundInRect method. The problem is that each "instance" of the status icon (one per screen) is highlighted although the user just clicked one. This behavior is different from a status icon without a custom view. Is there a way to implement this correctly?

For a good example just click on the Dropbox status icon when you're using multiple displays. You'll notice the selection of the icon on the other screen too.

The response from Apple from mentioned by JLinX Apple Dev Forums' thread:

Status Items with multiple menu bars

10.9 introduces multiple menu bars, each of which draws the status items. If your status item has a custom view, this view is positioned in one menu bar, and other menu bars get a “clone”, which looks identical. The clones are not exposed in the API. The clones are drawn by redirecting your custom view's drawing into another window. This means that your status item should not make assumptions about the drawing destination. For example, it should not assume that a call to drawRect: is destined for the view's window, or that the resolution of the drawing destination matches the resolution of the status item's screen. You must also not assume that the status item is on any particular display, except as described below. The clones are only redrawn in NSDefaultRunLoopMode. This allows the status item to limit highlighting to one display, by driving the run loop in another mode, such as NSEventTrackingRunLoopMode. For example, if you wish to simulate a menu, you would implement mouseDown: to show your window, and run the run loop in NSEventTrackingRunLoopMode until you determine that the window should be dismissed. While the run loop is in this mode, only the true status item will redraw. Clone status items will not redraw, and therefore they will not show any highlight applied to the true status item. When a clone status item is clicked, the clone exchanges locations with the true status item. This means that the location and screen of the status item window is reliable from within mouseDown:. You can access this information from your custom view, for example, using [[view window] screen] to position a window on the same screen as the status item.

You question is discussed here . Try to draw your custom view in a run loop other than the default run loop to differentiate between screens...

Alternatively, you can just draw the selection in your view instead of talking to the status item.

- (void)drawRect:(NSRect)dirtyRect
{
    if( active )
    {
         [[NSColor selectedMenuItemColor] set];
         NSRectFill(self.bounds);
    }
}

this will draw across both your view and the clone.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM