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 (Cocoa-dev@lists.apple.com)

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 arch...@mail-archive.com

Reply via email to