modifierFlags Monterey

Hello

Using a MacBook Pro Intel with macOS 12.7.6 Monterey, I test in Objective-C an event for the option key but it is not working

- (void)keyDown:(NSEvent *)event {
    printf("%s %p\n", __FUNCTION__, self);
    BOOL altFlag  = [event modifierFlags] & NSEventModifierFlagOption;
    if (altFlag) {
        // UpdateClass
        printf("option pressed\n");
    } else {
        printf("option not pressed\n");
    }
}

The same in Swift works fine

    override func keyDown(with event: NSEvent) {
        if event.modifierFlags.contains(.option) {
            print("option pressed")
        } else {
            print("option NOT pressed")
        }
    }

The Obj-C code works fine on a MacBook Air Tahoe 26.3

Any idea why it does not work on the macOS 12.7.6 Intel?

Many Thanks Jean

Answered by Frameworks Engineer in 877401022

Try re-expressing your condition as

([event modifierFlags] & NSEventModifierFlagOption) != 0

This is a behavior with BOOL and bitmasks that catches a lot of people by surprise. What’s happening here is that your bitwise operation is producing a NSEventModifierFlags value that is a single bit at 1 << 19, and then that value is being implicitly coerced into a BOOL.

The definition of BOOL varies by platform and architecture; on modern targets it’s a C99 bool, but on older targets it is a char. (Search up the OBJC_BOOL_IS_BOOL preprocessor define for more information.)

When your bitmask result is implicitly cast into a char, it is truncated to the lowest order byte which is all zeroes. You can avoid this by doing a test that produces a boolean result, like != 0.

Hello Jean,

Thanks for your question, and the sample code. Can you please confirm what the value of modifierFlags is when this method is called in the respective cases? (Objective-C on Monterey Intel, Objective-C on Tahoe, and in Swift on the respective platforms?

Thanks,

Richard Yeh  Developer Technical Support

Accepted Answer

Try re-expressing your condition as

([event modifierFlags] & NSEventModifierFlagOption) != 0

This is a behavior with BOOL and bitmasks that catches a lot of people by surprise. What’s happening here is that your bitwise operation is producing a NSEventModifierFlags value that is a single bit at 1 << 19, and then that value is being implicitly coerced into a BOOL.

The definition of BOOL varies by platform and architecture; on modern targets it’s a C99 bool, but on older targets it is a char. (Search up the OBJC_BOOL_IS_BOOL preprocessor define for more information.)

When your bitmask result is implicitly cast into a char, it is truncated to the lowest order byte which is all zeroes. You can avoid this by doing a test that produces a boolean result, like != 0.

modifierFlags Monterey
 
 
Q