22// Use of this source code is governed by a BSD-style license that can be
33// found in the LICENSE file.
44
5+ #import < OCMock/OCMock.h>
56#import " flutter/shell/platform/darwin/macos/framework/Source/FlutterMutatorView.h"
7+ #import " flutter/shell/platform/darwin/macos/framework/Source/FlutterView.h"
68
79#include " third_party/googletest/googletest/include/gtest/gtest.h"
810
@@ -563,4 +565,152 @@ void ExpectTransform3DEqual(const CATransform3D& t, const CATransform3D& u) {
563565 EXPECT_EQ ([mutatorView hitTest: NSMakePoint (50 , 50 )], platformView);
564566 EXPECT_EQ ([mutatorView hitTest: NSMakePoint (50 , 10 )], platformView);
565567 EXPECT_EQ ([mutatorView hitTest: NSMakePoint (10 , 50 )], platformView);
568+ }
569+
570+ @interface FlutterCursorCoordinatorTest : NSObject
571+
572+ @end
573+
574+ @implementation FlutterCursorCoordinatorTest
575+ - (void )testCoordinatorEventWithinFlutterContent {
576+ id flutterView = OCMClassMock ([FlutterView class ]);
577+ FlutterCursorCoordinator* coordinator =
578+ [[FlutterCursorCoordinator alloc ] initWithFlutterView: flutterView];
579+ {
580+ id platformView = OCMClassMock ([NSView class ]);
581+ OCMStub ([flutterView cursorUpdate: [OCMArg any ]]);
582+ id mutatorView = OCMStrictClassMock ([FlutterMutatorView class ]);
583+ OCMStub ([mutatorView platformView ]).andReturn (platformView);
584+ CGPoint location = NSMakePoint (50 , 50 );
585+ OCMStub ([mutatorView convertPoint: location fromView: [OCMArg any ]]).andReturn (location);
586+ NSEvent * event = [NSEvent mouseEventWithType: NSEventTypeMouseMoved
587+ location: location
588+ modifierFlags: 0
589+ timestamp: 0
590+ windowNumber: 0
591+ context: nil
592+ eventNumber: 0
593+ clickCount: 0
594+ pressure: 0 ];
595+ [coordinator processMouseMoveEvent: event
596+ forMutatorView: mutatorView
597+ overlayRegion: {CGRectMake (0 , 0 , 100 , 100 )}];
598+ OCMVerify ([flutterView cursorUpdate: event]);
599+ }
600+ {
601+ id platformView = OCMClassMock ([NSView class ]);
602+ // Make sure once event is handled the coordinator will not send cursorUpdate again.
603+ OCMReject ([flutterView cursorUpdate: [OCMArg any ]]);
604+ id mutatorView = OCMStrictClassMock ([FlutterMutatorView class ]);
605+ OCMStub ([mutatorView platformView ]).andReturn (platformView);
606+ CGPoint location = NSMakePoint (50 , 50 );
607+ OCMStub ([mutatorView convertPoint: location fromView: [OCMArg any ]]).andReturn (location);
608+ NSEvent * event = [NSEvent mouseEventWithType: NSEventTypeMouseMoved
609+ location: location
610+ modifierFlags: 0
611+ timestamp: 0
612+ windowNumber: 0
613+ context: nil
614+ eventNumber: 0
615+ clickCount: 0
616+ pressure: 0 ];
617+ [coordinator processMouseMoveEvent: event
618+ forMutatorView: mutatorView
619+ overlayRegion: {CGRectMake (0 , 0 , 100 , 100 )}];
620+ }
621+ EXPECT_TRUE (coordinator.cleanupScheduled );
622+ [[NSRunLoop mainRunLoop ] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.1 ]];
623+ EXPECT_FALSE (coordinator.cleanupScheduled );
624+ }
625+
626+ - (void )testCoordinatorEventOutsideFlutterContent {
627+ id flutterView = OCMClassMock ([FlutterView class ]);
628+ OCMReject ([flutterView cursorUpdate: [OCMArg any ]]);
629+ FlutterCursorCoordinator* coordinator =
630+ [[FlutterCursorCoordinator alloc ] initWithFlutterView: flutterView];
631+ id platformViewWindow = OCMClassMock ([NSWindow class ]);
632+ {
633+ id platformView = OCMClassMock ([NSView class ]);
634+ OCMStub ([platformViewWindow invalidateCursorRectsForView: platformView]);
635+ OCMStub ([platformView window ]).andReturn (platformViewWindow);
636+ OCMStub ([flutterView cursorUpdate: [OCMArg any ]]);
637+ id mutatorView = OCMStrictClassMock ([FlutterMutatorView class ]);
638+ OCMStub ([mutatorView platformView ]).andReturn (platformView);
639+ CGPoint location = NSMakePoint (150 , 150 );
640+ OCMStub ([mutatorView convertPoint: location fromView: [OCMArg any ]]).andReturn (location);
641+ NSEvent * event = [NSEvent mouseEventWithType: NSEventTypeMouseMoved
642+ location: location
643+ modifierFlags: 0
644+ timestamp: 0
645+ windowNumber: 0
646+ context: nil
647+ eventNumber: 0
648+ clickCount: 0
649+ pressure: 0 ];
650+ [coordinator processMouseMoveEvent: event
651+ forMutatorView: mutatorView
652+ overlayRegion: {CGRectMake (0 , 0 , 100 , 100 )}];
653+ OCMVerify ([platformViewWindow invalidateCursorRectsForView: platformView]);
654+ }
655+ {
656+ // Make sure this is not called again for subsequent invocation during same run loop turn.
657+ OCMReject ([platformViewWindow invalidateCursorRectsForView: [OCMArg any ]]);
658+
659+ id platformView = OCMClassMock ([NSView class ]);
660+ OCMStub ([platformViewWindow invalidateCursorRectsForView: platformView]);
661+ OCMStub ([platformView window ]).andReturn (platformViewWindow);
662+ OCMStub ([flutterView cursorUpdate: [OCMArg any ]]);
663+ id mutatorView = OCMStrictClassMock ([FlutterMutatorView class ]);
664+ OCMStub ([mutatorView platformView ]).andReturn (platformView);
665+ CGPoint location = NSMakePoint (150 , 150 );
666+ OCMStub ([mutatorView convertPoint: location fromView: [OCMArg any ]]).andReturn (location);
667+ NSEvent * event = [NSEvent mouseEventWithType: NSEventTypeMouseMoved
668+ location: location
669+ modifierFlags: 0
670+ timestamp: 0
671+ windowNumber: 0
672+ context: nil
673+ eventNumber: 0
674+ clickCount: 0
675+ pressure: 0 ];
676+ [coordinator processMouseMoveEvent: event
677+ forMutatorView: mutatorView
678+ overlayRegion: {CGRectMake (0 , 0 , 100 , 100 )}];
679+ }
680+ EXPECT_TRUE (coordinator.cleanupScheduled );
681+ [[NSRunLoop mainRunLoop ] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.1 ]];
682+ EXPECT_FALSE (coordinator.cleanupScheduled );
683+
684+ // Check that invalidateCursorRectsForView is called again
685+ platformViewWindow = OCMClassMock ([NSWindow class ]);
686+ {
687+ id platformView = OCMClassMock ([NSView class ]);
688+ OCMStub ([platformViewWindow invalidateCursorRectsForView: platformView]);
689+ OCMStub ([platformView window ]).andReturn (platformViewWindow);
690+ OCMStub ([flutterView cursorUpdate: [OCMArg any ]]);
691+ id mutatorView = OCMStrictClassMock ([FlutterMutatorView class ]);
692+ OCMStub ([mutatorView platformView ]).andReturn (platformView);
693+ CGPoint location = NSMakePoint (150 , 150 );
694+ OCMStub ([mutatorView convertPoint: location fromView: [OCMArg any ]]).andReturn (location);
695+ NSEvent * event = [NSEvent mouseEventWithType: NSEventTypeMouseMoved
696+ location: location
697+ modifierFlags: 0
698+ timestamp: 0
699+ windowNumber: 0
700+ context: nil
701+ eventNumber: 0
702+ clickCount: 0
703+ pressure: 0 ];
704+ [coordinator processMouseMoveEvent: event
705+ forMutatorView: mutatorView
706+ overlayRegion: {CGRectMake (0 , 0 , 100 , 100 )}];
707+ OCMVerify ([platformViewWindow invalidateCursorRectsForView: platformView]);
708+ }
709+ [[NSRunLoop mainRunLoop ] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.1 ]];
710+ }
711+ @end
712+
713+ TEST (FlutterMutatorViewTest, CursorCoordinator) {
714+ [[[FlutterCursorCoordinatorTest alloc ] init ] testCoordinatorEventWithinFlutterContent ];
715+ [[[FlutterCursorCoordinatorTest alloc ] init ] testCoordinatorEventOutsideFlutterContent ];
566716}
0 commit comments