GCMouseInput mouseMovedHandler called only after scroll

Hi,

I'm my game I'm using GCController to check for inputs, I have the following handlers set for when the current mouse changes

override func mouseDidBecomeCurrent(_ mouse: GCMouse) {
        guard let mouseInput = mouse.mouseInput else { return }

        mouseInput.mouseMovedHandler = { (input, deltaX, deltaY) in
            print("x: \(deltaX), y: \(deltaY), mouse: \(input.leftButton.isPressed)")
            if (input.leftButton.isPressed) {
                let delta: SIMD2<Float> = [deltaX, deltaY]
                self.cameraManager.current.rotate(delta: delta)
            }
        }
     
        mouseInput.scroll.valueChangedHandler = { (dpad, deltaX, deltaY) in
            print(dpad)
            self.cameraManager.current.zoom(delta: deltaY)
        }
    }

override func mouseStopBeingCurrent(_ mouse: GCMouse {
    guard let mouseInput = mouse.mouseInput else { return }
    mouseInput.mouseMovedHandler = nil
    mouseInput.scroll.valueChangedHandler = nil
}

I receive move mouse events as expected but .leftButton.isPressed on my input is always false until I scroll my trackpad.

I'm also tracking mouse movements in view controller so I get the mouse position on screen and not just the deltas.

let trackingArea = NSTrackingArea(rect: metalView.bounds, options: [.activeWhenFirstResponder, .mouseMoved, .enabledDuringMouseDrag], owner: self, userInfo: nil)

metalView.addTrackingArea(trackingArea)

Can the tracker cause this type of conflict?

Accepted Reply

Expanding on this....

I noticed this only occurs when there are multiple mice attached, in my case a wireless trackpad in addition to the Macbook's internal trackpad. I'm attaching the handlers when a different mouse becomes current but this seems to only occur when I do a gesture on either trackpad.

On start, the last connected device is the current one, according to my tests and logs, it seems to always be the internal trackpad.

I still receive tracking notifications from either device and the cursor moves as expected. However moving the cursor or clicking any button on either device does not trigger a notification indicating the device became current

Replies

Expanding on this....

I noticed this only occurs when there are multiple mice attached, in my case a wireless trackpad in addition to the Macbook's internal trackpad. I'm attaching the handlers when a different mouse becomes current but this seems to only occur when I do a gesture on either trackpad.

On start, the last connected device is the current one, according to my tests and logs, it seems to always be the internal trackpad.

I still receive tracking notifications from either device and the cursor moves as expected. However moving the cursor or clicking any button on either device does not trigger a notification indicating the device became current

Did not intent to mark this question as accepted, not sure how to revert it

I've removed checking for mouse button presses inside the mouse moved event, I noticed that though the method is guaranteed to be called on move events no matter where the move originated, the handler called used is not guaranteed to be the same handler for the device that originated the event. For example, when clicking and dragging from a device that's not current, the move handler used is the handler of the current device giving inaccurate button information inside the move callback

mouseInput.mouseMovedHandler = { (input, deltaX, deltaY) in
    if (self.cameraRotationEnabled) {
         let delta: SIMD2<Float> = [deltaX, deltaY]
         self.cameraManager.current.rotate(delta: delta)
    }
}

            
mouseInput.leftButton.valueChangedHandler = { (button, value, pressed) in
    self.cameraRotationEnabled = pressed
}

mouseInput.scroll.valueChangedHandler = { (dpad, deltaX, deltaY) in
    self.cameraManager.current.zoom(delta: deltaY)
}