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