input: issue basic mouse move event on window leave

This may help with moving the mouse to the screen borders in windowed mode
This commit is contained in:
Megamouse 2025-01-14 00:03:56 +01:00
parent 09580594e6
commit 5c2c4a6649
4 changed files with 56 additions and 37 deletions

View File

@ -31,12 +31,12 @@ void MouseHandlerBase::save(utils::serial& ar)
ar(inited ? m_info.max_connect : 0);
}
bool MouseHandlerBase::is_time_for_update(double elapsed_time)
bool MouseHandlerBase::is_time_for_update(double elapsed_time_ms)
{
steady_clock::time_point now = steady_clock::now();
const double elapsed = (now - last_update).count() / 1000'000.;
const double elapsed_ms = (now - last_update).count() / 1'000'000.;
if (elapsed > elapsed_time)
if (elapsed_ms > elapsed_time_ms)
{
last_update = now;
return true;

View File

@ -127,7 +127,7 @@ protected:
std::vector<Mouse> m_mice;
steady_clock::time_point last_update{};
bool is_time_for_update(double elapsed_time = 10.0); // 4-10 ms, let's use 10 for now
bool is_time_for_update(double elapsed_time_ms = 10.0); // 4-10 ms, let's use 10 for now
public:
shared_mutex mutex;

View File

@ -125,6 +125,18 @@ bool basic_mouse_handler::eventFilter(QObject* target, QEvent* ev)
case QEvent::KeyRelease:
Key(static_cast<QKeyEvent*>(ev), false);
break;
case QEvent::Leave:
{
// Issue mouse move on leave. Otherwise we may not get any mouse event at the screen borders.
const QPoint window_pos = m_target->mapToGlobal(m_target->position()) / m_target->devicePixelRatio();
const QPoint cursor_pos = QCursor::pos() - window_pos;
if (cursor_pos.x() <= 0 || cursor_pos.x() >= m_target->width() || cursor_pos.y() <= 0 || cursor_pos.y() >= m_target->height())
{
MouseMove(cursor_pos);
}
break;
}
default:
return false;
}
@ -218,38 +230,44 @@ void basic_mouse_handler::MouseMove(QMouseEvent* event)
if (is_time_for_update())
{
// get the screen dimensions
const QSize screen = m_target->size();
const QPoint e_pos = event->pos();
if (m_target && m_target->isActive() && get_mouse_lock_state())
{
// get the center of the screen in global coordinates
QPoint p_center = m_target->geometry().topLeft() + QPoint(screen.width() / 2, screen.height() / 2);
// reset the mouse to the center for consistent results since edge movement won't be registered
QCursor::setPos(m_target->screen(), p_center);
// convert the center into screen coordinates
p_center = m_target->mapFromGlobal(p_center);
// current mouse position, starting at the center
static QPoint p_real(p_center);
// get the delta of the mouse position to the screen center
const QPoint p_delta = e_pos - p_center;
// update the current position without leaving the screen borders
p_real.setX(std::clamp(p_real.x() + p_delta.x(), 0, screen.width()));
p_real.setY(std::clamp(p_real.y() + p_delta.y(), 0, screen.height()));
// pass the 'real' position and the current delta to the screen center
MouseHandlerBase::Move(0, p_real.x(), p_real.y(), screen.width(), screen.height(), true, p_delta.x(), p_delta.y());
}
else
{
// pass the absolute position
MouseHandlerBase::Move(0, e_pos.x(), e_pos.y(), screen.width(), screen.height());
}
MouseMove(event->pos());
}
}
void basic_mouse_handler::MouseMove(const QPoint& e_pos)
{
if (!m_target) return;
// get the screen dimensions
const QSize screen = m_target->size();
if (m_target->isActive() && get_mouse_lock_state())
{
// get the center of the screen in global coordinates
QPoint p_center = m_target->geometry().topLeft() + QPoint(screen.width() / 2, screen.height() / 2);
// reset the mouse to the center for consistent results since edge movement won't be registered
QCursor::setPos(m_target->screen(), p_center);
// convert the center into screen coordinates
p_center = m_target->mapFromGlobal(p_center);
// current mouse position, starting at the center
static QPoint p_real(p_center);
// get the delta of the mouse position to the screen center
const QPoint p_delta = e_pos - p_center;
// update the current position without leaving the screen borders
p_real.setX(std::clamp(p_real.x() + p_delta.x(), 0, screen.width()));
p_real.setY(std::clamp(p_real.y() + p_delta.y(), 0, screen.height()));
// pass the 'real' position and the current delta to the screen center
MouseHandlerBase::Move(0, p_real.x(), p_real.y(), screen.width(), screen.height(), true, p_delta.x(), p_delta.y());
}
else
{
// pass the absolute position
MouseHandlerBase::Move(0, e_pos.x(), e_pos.y(), screen.width(), screen.height());
}
}

View File

@ -24,6 +24,7 @@ public:
void MouseButton(QMouseEvent* event, bool pressed);
void MouseScroll(QWheelEvent* event);
void MouseMove(QMouseEvent* event);
void MouseMove(const QPoint& e_pos);
bool eventFilter(QObject* obj, QEvent* ev) override;
private: