I have several keyboard shortcuts that my app is using and I would like to dynamically build the correct CGEventFlags for each shortcut. I know there are questions that describe how to do this with a static event, but I would like to run dynamic CGEvents and I'm having trouble elegantly creating the correct value. I'll also be honest, bit masks don't make much sense to me. Is there any way to convert this to the dynamically get the correct CGEventFlag? Here's what I've been trying to do without success:
let shortcut = "control shift option command L"
var flags = [CGEventFlags]()
if shortcut.contains("control ") { flags.append(.maskControl) }
if shortcut.contains("shift ") { flags.append(.maskShift) }
if shortcut.contains("option ") { flags.append(.maskAlternate) }
if shortcut.contains("command ") { flags.append(.maskCommand) }
let mask = flags.someConversionFunction()...
CodePudding user response:
CGEventFlags
conforms to OptionSet
, which means that you can use set operations on it (as OptionSet
inherits from SetAlgebra
) and not worry about bit operations at all.
So basically, think of a variable of type CGEventFlags
as a set of flags. For example, you can insert
and remove
flags from it, as well as forming union
s and intersection
s with other CGEventFlags
.
var flags: CGEventFlags = []
if shortcut.contains("control ") { flags.insert(.maskControl) }
if shortcut.contains("shift ") { flags.insert(.maskShift) }
if shortcut.contains("option ") { flags.insert(.maskAlternate) }
if shortcut.contains("command ") { flags.insert(.maskCommand) }
// now you can assign "flags" to CGEvent.flags
If you do have a [CGEventFlags]
and want to convert to a single CGEventFlags
, just use the init(_:)
initialiser - this is the same initialiser as the one you use to convert [Int]
to a Set<Int>
. It's a bit counterintuitive, but CGEventFlags
is a set of CGEventFlags
.
Here I rewrote your code to be less imperative (without the mutable var
), as an example of converting from [CGEventFlags]
to CGEventFlags
:
let shortcut = "control shift option command L"
let eventFlagDictionary: [_: CGEventFlags] = [
"control": .maskControl,
"shift": .maskShift,
"option": .maskAlternate,
"command": .maskCommand
]
let flags = CGEventFlags(
// the below is a [CGEventFlags]
shortcut.split(separator: " ")
.compactMap { eventFlagDictionary[String($0)] }
)