I've been trying to solve this very frustrating issue and I'm hoping someone can help. I am trying to create an NSWindow which has multiple views. The views can overlap each other. These are the requirements.

First Attempt
I have attempted this by trying the following. Unfortunately this simply doesn't work.
In NSWindow
override func awakeFromNib() {
self.refreshElements()
self.titlebarAppearsTransparent = true
self.isMovableByWindowBackground = true
}
In my custom views
class Blue: NSView {
public override var mouseDownCanMoveWindow: Bool { return true }
}
class Yellow: NSView {
public override var mouseDownCanMoveWindow: Bool { return false }
}
Second Attempt
Then I have tried implementing mouseDown mouseDragged and mouseUp in Blue. I would calculate the mouse movement and self.setFrame(frameRect:display:animate:) on the window. This worked OK in that I could control moving the window but it had a couple of issues. One no matter what the window movement is always slower. I think it's animating even when I set the animate property to false. Also it does not active Expose as other windows do.
Third Attempt
This is as close as I can get to the behavior I want with one major issue. The initial mouseDown does not register. So you can't click on the blue view and drag and move the window. You have mouseDown, mouseUp, then mouseDown again in order for dragging to move the window.
public class MyWindow: NSWindow {
@IBOutlet var blue: NSView!
@IBOutlet var yellow: NSView!
public override func awakeFromNib() {
self.titlebarAppearsTransparent = true
self.isMovable = false
self.isMovableByWindowBackground = true
}
public override func mouseDown(with event: NSEvent) {
let point = event.locationInWindow
let move = NSPointInRect(point, self.blue.frame)
self.isMovableByWindowBackground = move
self.isMovable = move
super.mouseDown(with: event)
}
public override func mouseDragged(with event: NSEvent) {
super.mouseDragged(with: event)
}
}
My preferred method is method 3. It is the cleanest code and outside of the unusual behavior of having to click then click again in order for things to work everything else is perfect. My question is how can I force the initial click to also register with the window after it is dynamically set to allow movement?
Since macOS 10.11, NSWindow has had the method performDrag(with:) for this purpose. It initiates window dragging just like what's done when the user clicks and drags the title bar. Your blue view can simply call that in its override of mouseDown().
The thing with mouseDownCanMoveWindow is that it simply passes the question along to the superview. Unless all ancestor views up to the window's content view all return true, it won't matter.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With