Moving Window triggers MouseMovement

I have Metal by Tutorials and chapter 9, navigating a 3d Scene the mouse is hooked up to rotate the scene. However, when one clicks on the window titlebar to move the window that also rotates the scene (the GameController framework seems to include the titlebar as part of the window). Is there a way to limit the triggering to just the active window view, and not moving the window as well.

Hi @charleskerr64 and welcome to the forum :blush:

I find the GameController framework a bit lacking in this area.

One solution is to add a tracking area to the window. (This is macOS only - you’d surround any macOS only commands with the necessary #if os(macOS) test.)

Change the input controller.

  1. In InputController.swift, add this property to InputController:
var canMouseDown = false
  1. In init, change the GCMouse pressedChangedHandler closure to:
self.leftMouseDown = self.canMouseDown && pressed

Create a metalview subclass

  1. In MetalView.swift, add this code to the bottom of the file:
class MyMTKView: MTKView {
  override func mouseDown(with event: NSEvent) {
    InputController.shared.canMouseDown = true
  }

  override func mouseUp(with event: NSEvent) {
    InputController.shared.canMouseDown = false
  }
}
  1. In MetalView.swift, in MetalView, change the definition of metalView to be MyMTKView(). In MetalViewRepresentable, change the binding to be MyMTKView.

Add the tracking area

  1. in MetalView.swift, in makeNSView(context:), replace metalView with:
let trackingArea = NSTrackingArea(
  rect: metalView.bounds,
  options: [
    .activeWhenFirstResponder,
    .mouseMoved,
    .enabledDuringMouseDrag
  ],
  owner: self, userInfo: nil)
metalView.addTrackingArea(trackingArea)
return metalView

This adds a tracking area to the view.

The app recognises the mouse tracking area, and when there’s a mouse event, the app calls the overridden mouse methods. mouseDown(with:) is only called if the event occurs inside metalView.

You set canMouseDown in the Input Controller, so that you can test there whether the mouse is inside the window.

There may be a better way of doing it, but there’s not too much code here.

1 Like

Thanks! I finally took a tad different approach. I subclass MTKView, and add the mouseDown/mouseUp overrides.

    override func mouseUp(with event: NSEvent) {
        if event.buttonNumber == 0 {
            InputController.shared.leftMouseDown = false
            InputController.shared.removeMouseObserver()
        }
    }
    override func mouseDown(with event: NSEvent) {
        if event.buttonNumber == 0 {
            InputController.shared.leftMouseDown = true
            InputController.shared.addMouseObserver()

I then changed InputController init to only capture the scroll wheel:

        // we are only going to monitor the scrolling wheel
        center.addObserver( forName: .GCMouseDidConnect, object: nil, queue: nil) { notification in
            let mouse = notification.object as? GCMouse
            mouse?.mouseInput?.scroll.valueChangedHandler = { _, xValue, yValue in
                self.mouseScroll.x = xValue
                self.mouseScroll.y = yValue
            }
        }

And finally added two methods to InputController:

    func addMouseObserver() {
        for mouse in GCMouse.mice() {
            mouse.mouseInput?.mouseMovedHandler = { _, deltaX, deltaY in
                self.mouseDelta = Point(x: deltaX, y: deltaY)
            }
        }
    }
    func removeMouseObserver() {
        for mouse in GCMouse.mice() {
            mouse.mouseInput?.mouseMovedHandler = nil
        }
    }

That way I only get the mouse movement interrupts when the mouse is down.
Since I am making a utility tool (map editor), only getting the mouse when needed is ok for me. I appreciate your input, wanted to ensure I was on the correct track

1 Like

Oh, I wanted to say, I really enjoy the Book. I don’t think I would have ever gotten past the “hump” on Metal without it. The style/examples has been great!

My only “negative”, is I had to buy it twice. I got it originally off Amazon, and then found out about the ability to get an ePub version direct (but had to buy it again). Luckily I use it a lot, so that isn’t the end of the world.

Again, I appreciate the quality of the book, thanks again!

1 Like

Thank you for your kind words! It’s so great to hear that the book has helped.

I’m sorry you had to get it twice though. That’s annoying.

1 Like

Well, the book has been great, so I can choose to ignore that fact of the double cost.

I don’t find actual books like this anymore, much less something that isn’t solely geared to IOS. It has been great, and I hope you continue! I hope you consider doing one on SceneKit (although I realize that may be on the way out), especially with working with Metal, and especially on macOS (or just don’t make it only IOS!)

1 Like