renderer: fix mouse motion in VRR (#12665)

This commit is contained in:
Szwagi 2026-01-31 13:37:01 +00:00 committed by GitHub
parent 4330b49a84
commit cbeb6984e7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 63 additions and 105 deletions

View file

@ -737,17 +737,26 @@ Vector2D CPointerManager::closestValid(const Vector2D& pos) {
}
void CPointerManager::damageIfSoftware() {
if (g_pCompositor->m_unsafeState)
return;
auto b = getCursorBoxGlobal().expand(4);
for (auto const& mw : m_monitorStates) {
if (mw->monitor.expired() || !mw->monitor->m_output)
auto monitor = mw->monitor.lock();
if (!monitor || !monitor->m_output || monitor->isMirror())
continue;
if ((mw->softwareLocks > 0 || mw->hardwareFailed || g_pConfigManager->shouldUseSoftwareCursors(mw->monitor.lock())) &&
b.overlaps({mw->monitor->m_position, mw->monitor->m_size})) {
g_pHyprRenderer->damageBox(b, mw->monitor->shouldSkipScheduleFrameOnMouseEvent());
break;
}
auto usesSoftwareCursor = (mw->softwareLocks > 0 || mw->hardwareFailed || g_pConfigManager->shouldUseSoftwareCursors(monitor));
if (!usesSoftwareCursor)
continue;
auto shouldAddDamage = !monitor->shouldSkipScheduleFrameOnMouseEvent() && b.overlaps({monitor->m_position, monitor->m_size});
if (!shouldAddDamage)
continue;
CBox damageBox = b.copy().translate(-monitor->m_position).scale(monitor->m_scale).round();
monitor->addDamage(damageBox);
}
}
@ -924,20 +933,6 @@ void CPointerManager::attachPointer(SP<IPointer> pointer) {
PROTO::idle->onActivity();
});
listener->frame = pointer->m_pointerEvents.frame.listen([] {
bool shouldSkip = false;
if (!g_pSeatManager->m_mouse.expired() && g_pInputManager->isLocked()) {
auto PMONITOR = Desktop::focusState()->monitor().get();
if (PMONITOR && PMONITOR->shouldSkipScheduleFrameOnMouseEvent()) {
auto fsWindow = PMONITOR->m_activeWorkspace->getFullscreenWindow();
shouldSkip = fsWindow && fsWindow->m_isX11;
}
}
g_pSeatManager->m_isPointerFrameSkipped = shouldSkip;
if (!g_pSeatManager->m_isPointerFrameSkipped)
g_pSeatManager->sendPointerFrame();
});
listener->swipeBegin = pointer->m_pointerEvents.swipeBegin.listen([](const IPointer::SSwipeBeginEvent& event) {
g_pInputManager->onSwipeBegin(event);
@ -1089,7 +1084,7 @@ void CPointerManager::detachTablet(SP<CTablet> tablet) {
std::erase_if(m_tabletListeners, [tablet](const auto& e) { return e->tablet.expired() || e->tablet == tablet; });
}
void CPointerManager::damageCursor(PHLMONITOR pMonitor) {
void CPointerManager::damageCursor(PHLMONITOR pMonitor, bool skipFrameSchedule) {
for (auto const& mw : m_monitorStates) {
if (mw->monitor != pMonitor)
continue;
@ -1099,7 +1094,7 @@ void CPointerManager::damageCursor(PHLMONITOR pMonitor) {
if (b.empty())
return;
g_pHyprRenderer->damageBox(b);
g_pHyprRenderer->damageBox(b, skipFrameSchedule);
return;
}
@ -1108,22 +1103,3 @@ void CPointerManager::damageCursor(PHLMONITOR pMonitor) {
Vector2D CPointerManager::cursorSizeLogical() {
return m_currentCursorImage.size / m_currentCursorImage.scale;
}
void CPointerManager::storeMovement(uint64_t time, const Vector2D& delta, const Vector2D& deltaUnaccel) {
m_storedTime = time;
m_storedDelta += delta;
m_storedUnaccel += deltaUnaccel;
}
void CPointerManager::setStoredMovement(uint64_t time, const Vector2D& delta, const Vector2D& deltaUnaccel) {
m_storedTime = time;
m_storedDelta = delta;
m_storedUnaccel = deltaUnaccel;
}
void CPointerManager::sendStoredMovement() {
PROTO::relativePointer->sendRelativeMotion(m_storedTime * 1000, m_storedDelta, m_storedUnaccel);
m_storedTime = 0;
m_storedDelta = Vector2D{};
m_storedUnaccel = Vector2D{};
}

View file

@ -55,14 +55,11 @@ class CPointerManager {
// this is needed e.g. during screensharing where
// the software cursors aren't locked during the cursor move, but they
// are rendered later.
void damageCursor(PHLMONITOR pMonitor);
void damageCursor(PHLMONITOR pMonitor, bool skipFrameSchedule = false);
//
Vector2D position();
Vector2D cursorSizeLogical();
void storeMovement(uint64_t time, const Vector2D& delta, const Vector2D& deltaUnaccel);
void setStoredMovement(uint64_t time, const Vector2D& delta, const Vector2D& deltaUnaccel);
void sendStoredMovement();
void recheckEnteredOutputs();
@ -95,7 +92,6 @@ class CPointerManager {
CHyprSignalListener motionAbsolute;
CHyprSignalListener button;
CHyprSignalListener axis;
CHyprSignalListener frame;
CHyprSignalListener swipeBegin;
CHyprSignalListener swipeEnd;
@ -154,10 +150,6 @@ class CPointerManager {
Vector2D m_pointerPos = {0, 0};
uint64_t m_storedTime = 0;
Vector2D m_storedDelta = {0, 0};
Vector2D m_storedUnaccel = {0, 0};
struct SMonitorPointerState {
SMonitorPointerState(const PHLMONITOR& m) : monitor(m) {}
~SMonitorPointerState() = default;

View file

@ -127,9 +127,6 @@ class CSeatManager {
void setGrab(SP<CSeatGrab> grab); // nullptr removes
SP<CSeatGrab> m_seatGrab;
bool m_isPointerFrameSkipped = false;
bool m_isPointerFrameCommit = false;
private:
struct SSeatResourceContainer {
SSeatResourceContainer(SP<CWLSeatResource>);

View file

@ -198,7 +198,7 @@ static void handleUpdate(CAnimatedVariable<VarType>& av, bool warp) {
}
// manually schedule a frame
if (PMONITOR)
if (PMONITOR && !PMONITOR->inFullscreenMode())
g_pCompositor->scheduleFrameForMonitor(PMONITOR, Aquamarine::IOutput::AQ_SCHEDULE_ANIMATION);
}

View file

@ -130,16 +130,10 @@ void CInputManager::onMouseMoved(IPointer::SMotionEvent e) {
const auto DELTA = *PNOACCEL == 1 ? unaccel : delta;
if (g_pSeatManager->m_isPointerFrameSkipped)
g_pPointerManager->storeMovement(e.timeMs, DELTA, unaccel);
else
g_pPointerManager->setStoredMovement(e.timeMs, DELTA, unaccel);
PROTO::relativePointer->sendRelativeMotion(sc<uint64_t>(e.timeMs) * 1000, DELTA, unaccel);
if (e.mouse)
recheckMouseWarpOnMouseInput();
PROTO::relativePointer->sendRelativeMotion(sc<uint64_t>(e.timeMs) * 1000, delta, unaccel);
g_pPointerManager->move(DELTA);
mouseMoveUnified(e.timeMs, false, e.mouse);
@ -151,6 +145,8 @@ void CInputManager::onMouseMoved(IPointer::SMotionEvent e) {
if (e.mouse)
m_lastMousePos = getMouseCoordsInternal();
g_pSeatManager->sendPointerFrame();
}
void CInputManager::onMouseWarp(IPointer::SMotionAbsoluteEvent e) {
@ -676,6 +672,8 @@ void CInputManager::onMouseButton(IPointer::SButtonEvent e) {
m_focusHeldByButtons = false;
m_refocusHeldByButtons = false;
}
g_pSeatManager->sendPointerFrame();
}
void CInputManager::processMouseRequest(const CSeatManager::SSetCursorEvent& event) {
@ -954,6 +952,7 @@ void CInputManager::onMouseWheel(IPointer::SAxisEvent e, SP<IPointer> pointer) {
int32_t deltaDiscrete = std::abs(discrete) != 0 && std::abs(discrete) < 1 ? std::copysign(1, discrete) : std::round(discrete);
g_pSeatManager->sendPointerAxis(e.timeMs, e.axis, delta, deltaDiscrete, value120, e.source, WL_POINTER_AXIS_RELATIVE_DIRECTION_IDENTICAL);
g_pSeatManager->sendPointerFrame();
}
Vector2D CInputManager::getMouseCoordsInternal() {