@@ -78,6 +78,9 @@ public WebViewEnvironment(ICoreWebView2Environment environment) {
7878 private boolean ignoreFocus ;
7979 private String lastCustomText ;
8080
81+ record CursorPosition (Point location , boolean isInsideBrowser ) {};
82+ private CursorPosition previousCursorPosition = new CursorPosition (new Point (0 , 0 ), false );
83+
8184 static {
8285 NativeClearSessions = () -> {
8386 ICoreWebView2CookieManager manager = getCookieManager ();
@@ -654,6 +657,7 @@ void setupBrowser(int hr, long pv) {
654657 browser .addListener (SWT .FocusIn , this ::browserFocusIn );
655658 browser .addListener (SWT .Resize , this ::browserResize );
656659 browser .addListener (SWT .Move , this ::browserMove );
660+ scheduleMouseMovementHandling ();
657661
658662 containingEnvironment .instances ().add (this );
659663 // Sometimes when the shell of the browser is opened before the browser is
@@ -709,6 +713,52 @@ void browserResize(Event event) {
709713 controller .put_IsVisible (true );
710714}
711715
716+ private void scheduleMouseMovementHandling () {
717+ browser .getDisplay ().timerExec (100 , () -> {
718+ if (browser .isDisposed ()) {
719+ return ;
720+ }
721+ if (browser .isVisible () && hasDisplayFocus ()) {
722+ handleMouseMovement ();
723+ }
724+ scheduleMouseMovementHandling ();
725+ });
726+ }
727+
728+ private void handleMouseMovement () {
729+ final Point currentCursorLocation = browser .getDisplay ().getCursorLocation ();
730+ Point cursorLocationInControlCoordinate = browser .toControl (currentCursorLocation );
731+ boolean isCursorInsideBrowser = browser .getBounds ().contains (cursorLocationInControlCoordinate );
732+ boolean hasCursorLocationChanged = !currentCursorLocation .equals (previousCursorPosition .location );
733+
734+ boolean mousePassedBrowserBorder = previousCursorPosition .isInsideBrowser != isCursorInsideBrowser ;
735+ boolean mouseMovedInsideBrowser = isCursorInsideBrowser && hasCursorLocationChanged ;
736+ if (mousePassedBrowserBorder ) {
737+ if (isCursorInsideBrowser ) {
738+ sendMouseEvent (cursorLocationInControlCoordinate , SWT .MouseEnter );
739+ } else {
740+ sendMouseEvent (cursorLocationInControlCoordinate , SWT .MouseExit );
741+ }
742+ } else if (mouseMovedInsideBrowser ) {
743+ sendMouseEvent (cursorLocationInControlCoordinate , SWT .MouseMove );
744+ }
745+ previousCursorPosition = new CursorPosition (currentCursorLocation , isCursorInsideBrowser );
746+ }
747+
748+ private void sendMouseEvent (Point cursorLocationInControlCoordinate , int mouseEvent ) {
749+ Event newEvent = new Event ();
750+ newEvent .widget = browser ;
751+ Point position = cursorLocationInControlCoordinate ;
752+ newEvent .x = position .x ;
753+ newEvent .y = position .y ;
754+ newEvent .type = mouseEvent ;
755+ browser .notifyListeners (newEvent .type , newEvent );
756+ }
757+
758+ private boolean hasDisplayFocus () {
759+ return browser .getDisplay ().getFocusControl () != null ;
760+ }
761+
712762@ Override
713763public Object evaluate (String script ) throws SWTException {
714764 // Feature in WebView2. ExecuteScript works regardless of IsScriptEnabled setting.
0 commit comments