Mouse events on popup menu view seem to be incorrect in Sonoma.

as I open the pop-up menu and move the mouse before that opened, MouseEntered Event and MouseExited Event are called when mouse moved.

The following trackingAreas options are inclued in the view in pop-up area.

  • NSTrackingInVisibleRect, NSTrackingMouseEnteredAndExited, NSTrackingMouseMoved, NSTrackingActiveInKeyWindow

LocationInWindow of MouseExitedEvent seem to be incorrect.

This problems does not occur in the following cases.

  • Do not move the mouse until the popup is fully opened.
  • Left mouse button down on pop-up area.
  • Move the mouse out of the pop-up area.

This issue occurs in Sonoma(MacOS14.0) and later.

I would like to know if this is a code issue or a bug in the OS Version.

AppDelegate.h

#import <Cocoa/Cocoa.h>

@interface ViewInPopup : NSView {
    NSString* resultStr;
    
    NSUInteger enteredCount;
    NSPoint lastEnteredPos;
    
    NSUInteger exitedCount;
    NSPoint lastExitedPos;
    
    NSUInteger movedCount;
    NSPoint lastMovedPos;
    
    NSTrackingArea* trackingArea;
}

@end

@interface AppDelegate : NSObject <NSApplicationDelegate> {
    NSMenu* myMenu;
    ViewInPopup* viewInPopup;
}

- (IBAction)onClickButton:(id)sender;


@end

AppDelegate.mm

#import "AppDelegate.h"

@interface ViewInPopup ()

- (void)showResult:(NSEvent*)event;

@end

@implementation ViewInPopup

- (id)initWithFrame:(NSRect)frameRect
{
    self = [super initWithFrame:frameRect];
    [self setWantsLayer:TRUE];
    [[self layer] setBackgroundColor:[NSColor redColor].CGColor];
    return self;
}

- (void)drawRect:(NSRect)dirtyRect
{
    [super drawRect:dirtyRect];
    [resultStr drawInRect:[self bounds] withAttributes:nil];
}

- (void)updateTrackingAreas
{
    if (trackingArea) {
        [self removeTrackingArea:trackingArea];
    }
    NSTrackingAreaOptions options = NSTrackingInVisibleRect | NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingActiveInKeyWindow;
    trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds] options:options owner:self userInfo:nil];
    [self addTrackingArea:trackingArea];
    
    [super updateTrackingAreas];
}

- (void)mouseEntered:(NSEvent *)event
{
    [self showResult:event];
    [super mouseEntered:event];
}

- (void)mouseExited:(NSEvent *)event
{
    [self showResult:event];
    [super mouseExited:event];
}

- (void)mouseMoved:(NSEvent *)event
{
    [self showResult:event];
    [super mouseMoved:event];
}

- (void)showResult:(NSEvent*)event
{
    NSString* eventTypeStr = @"";
    switch (event.type) {
        case NSEventTypeMouseEntered:
            eventTypeStr = @"Entered";
            [[self layer] setBackgroundColor:[NSColor redColor].CGColor];
            if (enteredCount >= NSUIntegerMax) {
                enteredCount = 0;
            } else {
                enteredCount++;
            }
            lastEnteredPos = event.locationInWindow;
            break;
        case NSEventTypeMouseExited:
            eventTypeStr = @"Exited";
            [[self layer] setBackgroundColor:[NSColor blueColor].CGColor];
            if (exitedCount >= NSUIntegerMax) {
                exitedCount = 0;
            } else {
                exitedCount++;
            }
            lastExitedPos = event.locationInWindow;
            break;
        case NSEventTypeMouseMoved:
            eventTypeStr = @"Moved";
            [[self layer] setBackgroundColor:[NSColor greenColor].CGColor];
            if (movedCount >= NSUIntegerMax) {
                movedCount = 0;
            } else {
                movedCount++;
            }
            lastMovedPos = event.locationInWindow;
            break;
        default:
            return;
    }
    resultStr = [NSString stringWithFormat:@"LastEventType:%@\n\nEnteredCount:%ld\nLastEnteredPosition:(%f, %f)\n\nExitedCount:%ld\nLastExitedPosition:(%f %f)\n\nMovedCount:%ld\nLastMovedPosition:(%f, %f)", eventTypeStr, enteredCount, lastEnteredPos.x, lastEnteredPos.y, exitedCount, lastExitedPos.x, lastExitedPos.y, movedCount, lastMovedPos.x, lastMovedPos.y];
    [self setNeedsDisplay:YES];
}

@end

@interface AppDelegate ()

@property (strong) IBOutlet NSWindow *window;
@end

@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    // Insert code here to initialize your application
    myMenu = [[NSMenu alloc] init];
    NSMenuItem* item = [[NSMenuItem alloc] init];
    [myMenu addItem:item];
    
    viewInPopup = [[ViewInPopup alloc] initWithFrame:NSMakeRect(0, 0, 300, 300)];
    [item setView:viewInPopup];
    
}


- (void)applicationWillTerminate:(NSNotification *)aNotification {
    // Insert code here to tear down your application
}


- (BOOL)applicationSupportsSecureRestorableState:(NSApplication *)app {
    return YES;
}

- (IBAction)onClickButton:(id)sender
{
    [myMenu popUpMenuPositioningItem:nil atLocation:NSZeroPoint inView:(NSView*)sender];
}

@end
Post not yet marked as solved Up vote post of nwj Down vote post of nwj
756 views

Replies

Hi!

I have the very same issue, just with a status item menu. Did you ever find a solution for it?

Hey!

Having the same issue which makes using custom view's with highlight support not possible on macOS Sonoma. @nwj did you find any workarounds for this issue?

Preparing a feedback report to get an official position from Apple. Will post on the forum.