Let P
be an NSPopover and view
be an NSView that is a subview contained within P
.
I want to take the frame of view
and convert it to the screen's coordinate system. Normally, you would do that like this:
NSRect frameRelativeToWindow = [self convertRect:self.frame relativeToView:nil];
[self.window convertRectToScreen:frameRelativeToWindow];
However, because view
is in an NSPopover, its window
property is nil and the above method will return NSZeroRect: [0, 0, 0, 0]
So, how can I get my view's frame in screen coordinates if the view is in an NSPopover?
[self window]
to get the containing NSWindow object. Doing that in a popover, however, returns nil.The following code assumes, that you have
NSPopoverDelegate
As hamstergene pointed out, the popover's window won't be available until it is shown.
When the popoverWillShow:
delegate method gets called, your popover view's window should be an instance of _NSPopoverWindow
(and not nil
).
- (void)popoverWillShow:(NSNotification *)notification
{
NSWindow* popOverWindow = self.view.window;
NSRect popoverRectInScreenCoords = [popOverWindow convertRectToScreen:self.view.frame];
NSLog(@"Popover Rect in Screen Coords:%@", NSStringFromRect(popoverRectInScreenCoords));
}
Update
Bryan (the OP) posted a solution to his problem in the comments.
The issue wasn't NSPopover
itself. The actual reason for the nil
window for some of his subviews was NSTableView
, which releases non-visible NSTableCellViews
.
As a workaround he implemented viewDidMoveToWindow
in his custom NSTableCellView
subclass. When viewDidMoveToWindow:
gets called, the table cell view already has a window that can be used to perform coordinate conversion.