diff --git a/src/modules/event/sdl/Event.cpp b/src/modules/event/sdl/Event.cpp index e5c3f4219..c1f217a9c 100644 --- a/src/modules/event/sdl/Event.cpp +++ b/src/modules/event/sdl/Event.cpp @@ -51,6 +51,13 @@ static void windowToDPICoords(double *x, double *y) window->windowToDPICoords(x, y); } +static void clampToWindow(double *x, double *y) +{ + auto window = Module::getInstance(Module::M_WINDOW); + if (window) + window->clampPositionInWindow(x, y); +} + #ifndef LOVE_MACOSX static void normalizedToDPICoords(double *x, double *y) { @@ -253,8 +260,16 @@ Message *Event::convert(const SDL_Event &e) double y = (double) e.motion.y; double xrel = (double) e.motion.xrel; double yrel = (double) e.motion.yrel; + + // SDL reports mouse coordinates outside the window bounds when click-and- + // dragging. For compatibility we clamp instead since user code may not be + // able to handle out-of-bounds coordinates. SDL has a hint to turn off + // auto capture, but it doesn't report the mouse's position at the edge of + // the window if the mouse moves fast enough when it's off. + clampToWindow(&x, &y); windowToDPICoords(&x, &y); windowToDPICoords(&xrel, &yrel); + vargs.emplace_back(x); vargs.emplace_back(y); vargs.emplace_back(xrel); @@ -280,7 +295,10 @@ Message *Event::convert(const SDL_Event &e) double px = (double) e.button.x; double py = (double) e.button.y; + + clampToWindow(&px, &py); windowToDPICoords(&px, &py); + vargs.emplace_back(px); vargs.emplace_back(py); vargs.emplace_back((double) button); diff --git a/src/modules/mouse/sdl/Mouse.cpp b/src/modules/mouse/sdl/Mouse.cpp index d8a8290dc..8ff555ea2 100644 --- a/src/modules/mouse/sdl/Mouse.cpp +++ b/src/modules/mouse/sdl/Mouse.cpp @@ -49,6 +49,13 @@ static void DPIToWindowCoords(double *x, double *y) window->DPIToWindowCoords(x, y); } +static void clampToWindow(double *x, double *y) +{ + auto window = Module::getInstance(Module::M_WINDOW); + if (window) + window->clampPositionInWindow(x, y); +} + const char *Mouse::getName() const { return "love.mouse.sdl"; @@ -119,24 +126,16 @@ bool Mouse::isCursorSupported() const double Mouse::getX() const { - int x; - SDL_GetMouseState(&x, nullptr); - - double dx = (double) x; - windowToDPICoords(&dx, nullptr); - - return dx; + double x, y; + getPosition(x, y); + return x; } double Mouse::getY() const { - int y; - SDL_GetMouseState(nullptr, &y); - - double dy = (double) y; - windowToDPICoords(nullptr, &dy); - - return dy; + double x, y; + getPosition(x, y); + return y; } void Mouse::getPosition(double &x, double &y) const @@ -146,6 +145,14 @@ void Mouse::getPosition(double &x, double &y) const x = (double) mx; y = (double) my; + + // SDL reports mouse coordinates outside the window bounds when click-and- + // dragging. For compatibility we clamp instead since user code may not be + // able to handle out-of-bounds coordinates. SDL has a hint to turn off + // auto capture, but it doesn't report the mouse's position at the edge of + // the window if the mouse moves fast enough when it's off. + clampToWindow(&x, &y); + windowToDPICoords(&x, &y); } diff --git a/src/modules/window/Window.h b/src/modules/window/Window.h index 430516fe6..8b010bace 100644 --- a/src/modules/window/Window.h +++ b/src/modules/window/Window.h @@ -193,6 +193,8 @@ public: virtual int getPixelWidth() const = 0; virtual int getPixelHeight() const = 0; + virtual void clampPositionInWindow(double *wx, double *wy) const = 0; + // Note: window-space coordinates are not necessarily the same as // density-independent units (which toPixels and fromPixels use.) virtual void windowToPixelCoords(double *x, double *y) const = 0; diff --git a/src/modules/window/sdl/Window.cpp b/src/modules/window/sdl/Window.cpp index f2290112a..e9175f3d4 100644 --- a/src/modules/window/sdl/Window.cpp +++ b/src/modules/window/sdl/Window.cpp @@ -1124,6 +1124,13 @@ int Window::getPixelHeight() const return pixelHeight; } +void Window::clampPositionInWindow(double *wx, double *wy) const +{ + if (wx != nullptr) + *wx = std::min(std::max(0.0, *wx), (double) getWidth() - 1); + if (wy != nullptr) + *wy = std::min(std::max(0.0, *wy), (double) getHeight() - 1); +} void Window::windowToPixelCoords(double *x, double *y) const { diff --git a/src/modules/window/sdl/Window.h b/src/modules/window/sdl/Window.h index ad7c093b9..02b9e788a 100644 --- a/src/modules/window/sdl/Window.h +++ b/src/modules/window/sdl/Window.h @@ -104,6 +104,8 @@ public: int getPixelWidth() const override; int getPixelHeight() const override; + void clampPositionInWindow(double *wx, double *wy) const override; + void windowToPixelCoords(double *x, double *y) const override; void pixelToWindowCoords(double *x, double *y) const override;