diff --git a/irr/include/IrrlichtDevice.h b/irr/include/IrrlichtDevice.h index edc6ead61a32f..0c422ea891fc5 100644 --- a/irr/include/IrrlichtDevice.h +++ b/irr/include/IrrlichtDevice.h @@ -198,6 +198,9 @@ class IrrlichtDevice : public virtual IReferenceCounted or similar. */ virtual bool supportsTouchEvents() const { return false; } + //! Checks whether windowing uses the Wayland protocol. + virtual bool isUsingWayland() const { return false; } + //! Get the current color format of the window /** \return Color format of the window. */ virtual video::ECOLOR_FORMAT getColorFormat() const = 0; diff --git a/irr/src/CIrrDeviceSDL.cpp b/irr/src/CIrrDeviceSDL.cpp index f7974202fe31e..d67fba8432571 100644 --- a/irr/src/CIrrDeviceSDL.cpp +++ b/irr/src/CIrrDeviceSDL.cpp @@ -1248,6 +1248,15 @@ bool CIrrDeviceSDL::supportsTouchEvents() const return true; } +//! Checks whether windowing uses the Wayland protocol. +bool CIrrDeviceSDL::isUsingWayland() const +{ + if (!Window) + return false; + auto *name = SDL_GetCurrentVideoDriver(); + return name && !strcmp(name, "wayland"); +} + //! returns if window is active. if not, nothing need to be drawn bool CIrrDeviceSDL::isWindowActive() const { diff --git a/irr/src/CIrrDeviceSDL.h b/irr/src/CIrrDeviceSDL.h index b52422423c940..eb2250f2a33d7 100644 --- a/irr/src/CIrrDeviceSDL.h +++ b/irr/src/CIrrDeviceSDL.h @@ -96,6 +96,9 @@ class CIrrDeviceSDL : public CIrrDeviceStub //! Checks if the Irrlicht device supports touch events. bool supportsTouchEvents() const override; + //! Checks whether windowing uses the Wayland protocol. + bool isUsingWayland() const override; + //! Get the position of this window on screen core::position2di getWindowPosition() override; diff --git a/src/client/game.cpp b/src/client/game.cpp index d2da5dda311c2..e8adf54cf2f66 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -754,6 +754,7 @@ class Game { f32 m_repeat_dig_time; f32 m_cache_cam_smoothing; + bool m_enable_relative_mode = false; bool m_invert_mouse; bool m_enable_hotbar_mouse_wheel; bool m_invert_hotbar_mouse_wheel; @@ -896,6 +897,11 @@ bool Game::startup(bool *kill, m_first_loop_after_window_activation = true; + // In principle we could always enable relative mouse mode, but it causes weird + // bugs on some setups (e.g. #14932), so we enable it only when it's required. + // That is: on Wayland, because it does not support mouse repositioning + m_enable_relative_mode = device->isUsingWayland(); + m_touch_use_crosshair = g_settings->getBool("touch_use_crosshair"); g_client_translations->clear(); @@ -2349,8 +2355,10 @@ void Game::updateCameraDirection(CameraOrientation *cam, float dtime) Since Minetest has its own code to synthesize mouse events from touch events, this results in duplicated input. To avoid that, we don't enable relative mouse mode if we're in touchscreen mode. */ - if (cur_control) - cur_control->setRelativeMode(!g_touchcontrols && !isMenuActive()); + if (cur_control) { + cur_control->setRelativeMode(m_enable_relative_mode && + !g_touchcontrols && !isMenuActive()); + } if ((device->isWindowActive() && device->isWindowFocused() && !isMenuActive()) || input->isRandom()) {