@@ -80,7 +80,17 @@ -(AvnView*) initWithParent: (TopLevelImpl*) parent
8080 [self setLayerContentsRedrawPolicy: NSViewLayerContentsRedrawDuringViewResize];
8181
8282 _parent = parent;
83- _area = nullptr ;
83+
84+ // NSTrackingInVisibleRect makes AppKit follow the visible bounds of the view.
85+ // Because of this, the tracking area does not need to change on resize.
86+ // Do not remove and add the area again on each live-resize tick.
87+ // If you do, AppKit queues synthetic enter and exit events with stale locations.
88+ // These events corrupt the pointer position after a resize and force it to the top left.
89+ NSTrackingAreaOptions options = NSTrackingActiveAlways | NSTrackingMouseMoved |
90+ NSTrackingMouseEnteredAndExited | NSTrackingEnabledDuringMouseDrag | NSTrackingInVisibleRect;
91+ _area = [[NSTrackingArea alloc ] initWithRect: NSZeroRect options: options owner: self userInfo: nullptr ];
92+ [self addTrackingArea: _area];
93+
8494 _lastPixelSize.Height = 100 ;
8595 _lastPixelSize.Width = 100 ;
8696 [self registerForDraggedTypes: @[@" public.data" , GetAvnCustomDataType ()]];
@@ -128,25 +138,12 @@ -(void)setFrameSize:(NSSize)newSize
128138{
129139 [super setFrameSize: newSize];
130140
131- if (_area != nullptr )
132- {
133- [self removeTrackingArea: _area];
134- _area = nullptr ;
135- }
136-
137141 auto parent = _parent.tryGet ();
138142 if (parent == nullptr )
139143 {
140144 return ;
141145 }
142146
143- NSRect rect = NSZeroRect ;
144- rect.size = newSize;
145-
146- NSTrackingAreaOptions options = NSTrackingActiveAlways | NSTrackingMouseMoved | NSTrackingMouseEnteredAndExited | NSTrackingEnabledDuringMouseDrag;
147- _area = [[NSTrackingArea alloc ] initWithRect: rect options: options owner: self userInfo: nullptr ];
148- [self addTrackingArea: _area];
149-
150147 parent->UpdateCursor ();
151148
152149 auto fsize = [self convertSizeToBacking: [self frame ].size];
@@ -258,8 +255,12 @@ - (void)mouseEvent:(NSEvent *)event withType:(AvnRawMouseEventType) type
258255 return ;
259256 }
260257
261- NSPoint eventLocation = [event locationInWindow ];
262-
258+ // AppKit synthesizes enter and exit events for the tracked geometry.
259+ // They can have stale locations. Use the current pointer location instead.
260+ NSPoint eventLocation = event.type == NSEventTypeMouseEntered || event.type == NSEventTypeMouseExited
261+ ? [[self window ] mouseLocationOutsideOfEventStream ]
262+ : [event locationInWindow ];
263+
263264 auto viewLocation = [self convertPoint: NSMakePoint (0 , 0 ) toView: nil ];
264265
265266 auto localPoint = NSMakePoint (eventLocation.x - viewLocation.x , viewLocation.y - eventLocation.y );
@@ -392,7 +393,10 @@ - (void)mouseEvent:(NSEvent *)event withType:(AvnRawMouseEventType) type
392393 parent->TopLevelEvents ->RawMouseEvent (type, pointerType, timestamp, modifiers, point, delta, pressure, xTilt, yTilt);
393394 }
394395
395- [super mouseMoved: event];
396+ // This handler is shared by all mouse event types. Only real mouse-moved
397+ // events must continue up the responder chain as mouseMoved:
398+ if (event.type == NSEventTypeMouseMoved)
399+ [super mouseMoved: event];
396400}
397401
398402- (BOOL ) resignFirstResponder
@@ -560,7 +564,10 @@ - (void)swipeWithEvent:(NSEvent *)event
560564
561565- (void )mouseEntered : (NSEvent *)event
562566{
563- [self mouseEvent: event withType: Move];
567+ // If the pointer is not inside the view, the enter event is false. Ignore it.
568+ NSPoint location = [self convertPoint: [[self window ] mouseLocationOutsideOfEventStream ] fromView: nil ];
569+ if (NSPointInRect (location, self.bounds ))
570+ [self mouseEvent: event withType: Move];
564571 [super mouseEntered: event];
565572}
566573
0 commit comments