Search code examples
objective-cmacoscocoanswindowappkit

Allow click and dragging a view to drag the window itself?


I'm using a textured window that has a tab bar along the top of it, just below the title bar.

I've used -setContentBorderThickness:forEdge: on the window to make the gradient look right, and to make sure sheets slide out from the right position.

What's not working however, is dragging the window around. It works if I click and drag the area that's actually the title bar, but since the title bar gradient spills into a (potentially/often empty) tab bar, it's really easy to click too low and it feels really frustrating when you try to drag and realise the window is not moving.

I notice NSToolbar, while occupying roughly the same amount of space below the title bar, allows the window to be dragged around when the cursor is over it. How does one implement this?

Thanks.

Tab Bar


Solution

  • I found this here:

    -(void)mouseDown:(NSEvent *)theEvent {    
        NSRect  windowFrame = [[self window] frame];
    
        initialLocation = [NSEvent mouseLocation];
    
        initialLocation.x -= windowFrame.origin.x;
        initialLocation.y -= windowFrame.origin.y;
    }
    
    - (void)mouseDragged:(NSEvent *)theEvent {
        NSPoint currentLocation;
        NSPoint newOrigin;
    
        NSRect  screenFrame = [[NSScreen mainScreen] frame];
        NSRect  windowFrame = [self frame];
    
        currentLocation = [NSEvent mouseLocation];
        newOrigin.x = currentLocation.x - initialLocation.x;
        newOrigin.y = currentLocation.y - initialLocation.y;
    
        // Don't let window get dragged up under the menu bar
        if( (newOrigin.y+windowFrame.size.height) > (screenFrame.origin.y+screenFrame.size.height) ){
            newOrigin.y=screenFrame.origin.y + (screenFrame.size.height-windowFrame.size.height);
        }
    
        //go ahead and move the window to the new location
        [[self window] setFrameOrigin:newOrigin];
    }
    

    It works fine, though I'm not 100% sure I'm doing it correctly. There's one bug I've found so far, and that's if the drag begins inside a subview (a tab itself) and then enters the superview (the tab bar). The window jumps around. Some -hitTest: magic, or possibly even just invalidating initialLocation on mouseUp should probably fix that.