diff --git a/jme3-lwjgl3/src/main/java/com/jme3/input/lwjgl/SdlMouseInput.java b/jme3-lwjgl3/src/main/java/com/jme3/input/lwjgl/SdlMouseInput.java index de41223c81..e78c5e6eb5 100644 --- a/jme3-lwjgl3/src/main/java/com/jme3/input/lwjgl/SdlMouseInput.java +++ b/jme3-lwjgl3/src/main/java/com/jme3/input/lwjgl/SdlMouseInput.java @@ -92,6 +92,7 @@ public class SdlMouseInput implements MouseInput { private float windowCoordHeight = 1f; private boolean cursorVisible = true; + private boolean windowFocused = true; private boolean x11WarpGrabMode; private boolean ignoreNextX11WarpEvent; private boolean initialized; @@ -131,6 +132,9 @@ public void onSDLEvent(SDL_Event event) { if (type == SDL_EVENT_WINDOW_FOCUS_GAINED) { if (event.window().windowID() == context.getWindowId()) { + windowFocused = true; + refreshWindowMetrics(); + initCurrentMousePosition(); setCursorVisible(cursorVisible); } return; @@ -138,8 +142,10 @@ public void onSDLEvent(SDL_Event event) { if (type == SDL_EVENT_WINDOW_FOCUS_LOST) { if (event.window().windowID() == context.getWindowId()) { + windowFocused = false; x11WarpGrabMode = false; ignoreNextX11WarpEvent = false; + mouseMotionEvents.clear(); SDL_CaptureMouse(false); SDL_SetWindowMouseGrab(context.getWindowHandle(), false); SDL_SetWindowRelativeMouseMode(context.getWindowHandle(), false); @@ -154,6 +160,9 @@ public void onSDLEvent(SDL_Event event) { if (event.motion().windowID() != context.getWindowId()) { return; } + if (!windowFocused) { + return; + } refreshWindowMetrics(); final boolean relativeMode = SDL_GetWindowRelativeMouseMode(context.getWindowHandle()); final int x; diff --git a/jme3-lwjgl3/src/test/java/com/jme3/input/lwjgl/SdlMouseInputTest.java b/jme3-lwjgl3/src/test/java/com/jme3/input/lwjgl/SdlMouseInputTest.java new file mode 100644 index 0000000000..5a77ab4cf4 --- /dev/null +++ b/jme3-lwjgl3/src/test/java/com/jme3/input/lwjgl/SdlMouseInputTest.java @@ -0,0 +1,50 @@ +package com.jme3.input.lwjgl; + +import com.jme3.system.lwjgl.LwjglWindow; +import java.lang.reflect.Field; +import java.util.Queue; +import org.junit.jupiter.api.Test; +import org.lwjgl.sdl.SDL_Event; + +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.lwjgl.sdl.SDLEvents.SDL_EVENT_MOUSE_MOTION; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class SdlMouseInputTest { + + @Test + public void shouldIgnoreMouseMotionWhenWindowIsUnfocused() throws Exception { + LwjglWindow context = mock(LwjglWindow.class); + when(context.getWindowId()).thenReturn(7); + + SdlMouseInput mouseInput = new SdlMouseInput(context); + setField(mouseInput, "windowFocused", false); + + SDL_Event event = SDL_Event.calloc(); + try { + event.type(SDL_EVENT_MOUSE_MOTION); + event.motion().windowID(7); + + mouseInput.onSDLEvent(event); + } finally { + event.free(); + } + + Queue mouseMotionEvents = getField(mouseInput, "mouseMotionEvents"); + assertTrue(mouseMotionEvents.isEmpty()); + } + + private static void setField(Object target, String fieldName, Object value) throws Exception { + Field field = target.getClass().getDeclaredField(fieldName); + field.setAccessible(true); + field.set(target, value); + } + + @SuppressWarnings("unchecked") + private static T getField(Object target, String fieldName) throws Exception { + Field field = target.getClass().getDeclaredField(fieldName); + field.setAccessible(true); + return (T) field.get(target); + } +}