Re: Wrong placement with -[NSWindow initWithContentRect:styleMask:backing:defer:screen:]
Re: Wrong placement with -[NSWindow initWithContentRect:styleMask:backing:defer:screen:]
- Subject: Re: Wrong placement with -[NSWindow initWithContentRect:styleMask:backing:defer:screen:]
- From: Graham Cox <email@hidden>
- Date: Tue, 9 Feb 2010 11:25:14 +1100
On 09/02/2010, at 5:12 AM, Jack Repenning wrote:
> In that regard, it's interesting to note that -[NSMenu popUpMenuPositioningItem:atLocation:inView:] behaves perfectly when passed the mouse location directly. That makes it about a hundred times easier than the approach I presently use, which involves several coordinate transformations between local-screen, whole-screen, and single-window coordinates (which, yes, I've checked again and again, but still might be the culprit, they being so convoluted). But this routine is new for 10.6, and I'm trying to support back to 10.4.
Well, there is [NSMenu popUpContextMenu: withEvent: forView:] which goes back to 10.0, and does exactly the same with the exception of positioning a given item under the location you pass. That can be worked around if necessary.
The coordinate transformations shouldn't be that difficult - you need two only - view-to-window and window-to-screen. For example, I make my own little custom floater window that is similar to a tooltip, and position it using this method which is in a NSWindow subclass:
- (void) positionAtPoint:(NSPoint) p inView:(NSView*) view
{
// places the window at the point <p> as expressed in the coordinate system of <view>.
p = [view convertPoint:p toView:nil];
[self setFrameTopLeftPoint:[[v window] convertBaseToScreen:p]];
}
For a mouse location derived from an NSEvent, you don't even need the first conversion because all mouse location values are already in window coordinates within the event. So perhaps you're over-thinking the transformations?
Incidentally when I make the window itself, I don't attempt to force a location at that time - my -init method looks like:
- (id) initWithContentRect:(NSRect) contentRect
styleMask:(NSUInteger) styleMask
backing:(NSBackingStoreType) bufferingType
defer:(BOOL) deferCreation
{
self = [super initWithContentRect:contentRect
styleMask:styleMask
backing:bufferingType
defer:deferCreation];
if ( self )
{
// insert a bunch of views for displaying the window's content
}
return self;
}
And when this is invoked by a class convenience method for constructing the window, that actual rect I pass is NSZeroRect. The frame size of the window is derived from its content (like a tooltip) and the position is set usually from a mouse location when tracking in a view. I checked it just now to verify that it works across multiple monitors without the issue you're seeing and it does.
GCInfoFloater* fi = [[GCInfoFloater alloc] initWithContentRect:NSZeroRect
styleMask:NSBorderlessWindowMask
backing:NSBackingStoreBuffered
defer:YES];
I also have an almost identical class that operates as a custom pop-up "menu" but is in fact just a borderless window. It uses essentially the same code as above for both creation and positioning when popped up.
> "For some definition of 'close to'" sure sounds like it might be the behavior I'm seeing, but I'm unfamiliar with "the so-called 'standard' and 'user' states." Can you hint me a bit more on that?
That might be a red herring after all.
But this has to do with the zoom state of a window. 'Standard' state is the window's zoomed out state, and 'User' state is where the user has positioned and sized the window manually. The zoom button toggles between the two, but in order to know which state the window currently is in, it tests its current frame against the screen bounds. If the frame is 'close' to the edge - and I think classically 'close to' has meant within +/- 4 pixels of the screen's -availableRect - then 'standard' state is assumed, otherwise 'user' state is assumed. This will only affect you if you are programmatically zooming the window using the -zoom: or -performZoom: method and the current state needs to be figured out. If you directly set the frame, this is bypassed. The discussion in the docs for [NSWindow zoom:] has a more detail on this process.
--Graham
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden