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 protected])
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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com
This email sent to [email protected]