Search code examples
swiftnsbutton

detect when button is pressed down and then up Swift macOS


I'm writing an app that send commands to a set top box. The box can receive two types of commands: push and release.

I can get the button pressed on macOs in swift. @IBAction func btnPressed(sender: NSButton) { } in which i send the command and the release. For any command such as change channel, mute or other, all works fine. Instead, for volume up or done, I need, by doing what I do, to click several time to have the volume up or down.

I got the mouse up and down working, detecting where the click happened (inside the NSImageView (if not a button) corresponding to the up and down images) to simulate a long volume up or down press, but I can't get it inside the button pressed method.

is there a way in the 'buttonpressed' method to combine the mouse event in order to simulate a long press while holding the mouse down?

PS: I have googled and searched here also but did not find a hint.


Solution

  • if it can help:

    1 subclass the button class to fire the action on mouseDown and mouseUp (the action will be fired twice)

     class myButton: NSButton {
         override func awakeFromNib() {
         super.awakeFromNib()
        let maskUp = NSEvent.EventTypeMask.leftMouseUp.rawValue
        let maskDown = NSEvent.EventTypeMask.leftMouseDown.rawValue
        let mask = Int( maskUp | maskDown ) // cast from UInt
        //shortest way for the above:
        //let mask = NSEvent.EventTypeMask(arrayLiteral: [.leftMouseUp, .leftMouseDown]).rawValue
        self.sendAction(on: NSEvent.EventTypeMask(rawValue: NSEvent.EventTypeMask.RawValue(mask)))
        //objC gives: [self.button sendActionOn: NSLeftMouseDownMask | NSLeftMouseUpMask];
    }
    

    }

    2: in the storyboard, change the class of the NSButton to your class:

    enter image description here

    3: set the sender of the action to your subclass and check the currentEvent type:

    @IBAction func volUpPressed(sender: myButton) {
        let currEvent = NSApp.currentEvent
        
        if(currEvent?.type == .leftMouseDown) {
            print("volume Up pressed Down")
            //... do your stuff here on mouseDown
        }
        else
        if(currEvent?.type == .leftMouseUp) {
            print("volume Up pressed Up")
            //... do your stuff here on mouseUp
        }
    }