Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Obtaining modifier key pressed in CGEvent tap

Having setup an event tap, I'm not able to identify what modifier key was pressed given a CGEvent.

 CGEventFlags flagsP;

 flagsP=CGEventGetFlags(event);

 NSLog(@"flags: 0x%llX",flagsP);
 NSLog(@"stored: 0x%llX",kCGEventFlagMaskCommand);

 if (flagsP==kCGEventFlagMaskCommand) {
       NSLog(@"command pressed");
    }

Given the above snippet, the first NSLog returns a different value from the second NSLog. No surprise that the conditional is never triggered when the command modifier key is pressed.

I need to identify whether command, alternate, option, control or shift are pressed for a given CGEvent. First though, I need help to understand why the above isn't working.

Thanks!

like image 389
the979kid Avatar asked May 20 '26 01:05

the979kid


1 Answers

These are bit masks, which will be bitwise-ORed together into the value you receive from CGEventGetFlags (or pass when creating an event yourself).

You can't test equality here because no single bit mask will be equal to a combination of multiple bit masks. You need to test equality of a single bit.

To extract a single bit mask's value from a combined bit mask, use the bitwise-AND (&) operator. Then, compare that to the single bit mask you're interested in:

BOOL commandKeyIsPressed = (flagsP & kCGEventFlagMaskCommand) == kCGEventFlagMaskCommand;

Why both?

The & expression evaluates to the same type as its operands, which is CGEventFlags in this case, which may not fit in the size of a BOOL, which is a signed char. The == expression resolves that to 1 or 0, which is all that will fit in a BOOL.

Other solutions to that problem include negating the value twice (!!) and declaring the variable as bool or _Bool rather than Boolean or BOOL. C99's _Bool type (synonymized to bool when you include stdbool.h) forces its value to be either 1 or 0, just as the == and !! solutions do.

like image 78
Peter Hosey Avatar answered May 22 '26 05:05

Peter Hosey