6

I'm looking for a way to check the state of the option-key in SwiftUI on macOS.

I.e. depending on whether the option key is pressed or not I want to perform different actions in the .onTapGesture closure.

mic
  • 907
  • 6
  • 17

3 Answers3

11

macOS-only SwiftUI has .modifiers modifier to specify EventModifiers, so your case is covered like in below example:

Rectangle()
    .fill(Color.yellow)
    .frame(width: 100, height: 40)
    .gesture(TapGesture().modifiers(.option).onEnded {
        print("Do anyting on OPTION+CLICK")
    })
    .onTapGesture {
        print("Do anyting on CLICK")
    }
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Asperi
  • 228,894
  • 20
  • 464
  • 690
4

While using the modifiers method on the gesture should probably be preferred, one can also actually test for the option key itself using CGEventSource in CoreGraphics:

import CoreGraphics

extension CGKeyCode
{
    static let kVK_Option     : CGKeyCode = 0x3A
    static let kVK_RightOption: CGKeyCode = 0x3D
    
    var isPressed: Bool {
        CGEventSource.keyState(.combinedSessionState, key: self)
    }
    
    static var optionKeyPressed: Bool {
        return Self.kVK_Option.isPressed || Self.kVK_RightOption.isPressed
    }
}

This lets you detect the option key (or any other keys for that matter) in contexts where there isn't a modifier property or method.

The key codes in the extension can be renamed to be more Swifty, but those are the names that go way back to Classic MacOS's Toolbox and were defined in Inside Macintosh. I have a gist containing all the old key codes.

Chip Jarred
  • 2,600
  • 7
  • 12
  • Nice, works great for my purposes, thanks. Getting keys events in SwiftUI is such a drag. – Chris Jun 24 '21 at 08:08
  • I'm glad it was helpful! And yeah, it's pretty clear that SwiftUI was designed first and foremost for iOS. It's getting better for macOS, but you still have to do a lot of extra work to make it work and feel like a proper Mac application. The menu bar ("main menu") can be another pain point. – Chip Jarred Jun 24 '21 at 20:04
1

2022

.onTapGesture {
   if NSEvent.modifierFlags.contains(.option) {
       print("Option key Tap")
   } else {
       print("Tap")
   }
}
.onDrag {
    if NSEvent.modifierFlags.contains(.option) {
        return NSItemProvider(object: "\(item.id)" as NSString)
    }
                    
    return NSItemProvider()
}
Andrew_STOP_RU_WAR_IN_UA
  • 9,318
  • 5
  • 65
  • 101