diff --git a/autotests/mock_effectshandler.h b/autotests/mock_effectshandler.h index 9a0f6a6fb2..28f30ce3a8 100644 --- a/autotests/mock_effectshandler.h +++ b/autotests/mock_effectshandler.h @@ -167,8 +167,8 @@ public: void paintWindow(KWin::EffectWindow *, int, const QRegion &, KWin::WindowPaintData &) override {} void postPaintScreen() override {} void postPaintWindow(KWin::EffectWindow *) override {} - void prePaintScreen(KWin::ScreenPrePaintData &, int) override {} - void prePaintWindow(KWin::EffectWindow *, KWin::WindowPrePaintData &, int) override {} + void prePaintScreen(KWin::ScreenPrePaintData &, std::chrono::milliseconds) override {} + void prePaintWindow(KWin::EffectWindow *, KWin::WindowPrePaintData &, std::chrono::milliseconds) override {} QByteArray readRootProperty(long int, long int, int) const override { return QByteArray(); } diff --git a/composite.cpp b/composite.cpp index 1bf598545c..0bae7ef4fd 100644 --- a/composite.cpp +++ b/composite.cpp @@ -681,16 +681,20 @@ void Compositor::performCompositing() // clear all repaints, so that post-pass can add repaints for the next repaint repaints_region = QRegion(); + const std::chrono::nanoseconds now = std::chrono::steady_clock::now().time_since_epoch(); + const std::chrono::milliseconds presentTime = + std::chrono::duration_cast(now); + if (m_framesToTestForSafety > 0 && (m_scene->compositingType() & OpenGLCompositing)) { kwinApp()->platform()->createOpenGLSafePoint(Platform::OpenGLSafePoint::PreFrame); } m_renderTimer.start(); if (kwinApp()->platform()->isPerScreenRenderingEnabled()) { for (int screenId = 0; screenId < screens()->count(); ++screenId) { - m_scene->paint(screenId, repaints, windows); + m_scene->paint(screenId, repaints, windows, presentTime); } } else { - m_scene->paint(-1, repaints, windows); + m_scene->paint(-1, repaints, windows, presentTime); } m_timeSinceLastVBlank = m_renderTimer.elapsed(); if (m_framesToTestForSafety > 0) { diff --git a/effects.cpp b/effects.cpp index 967d7170b2..58c8eebe50 100644 --- a/effects.cpp +++ b/effects.cpp @@ -363,10 +363,10 @@ void EffectsHandlerImpl::reconfigure() } // the idea is that effects call this function again which calls the next one -void EffectsHandlerImpl::prePaintScreen(ScreenPrePaintData& data, int time) +void EffectsHandlerImpl::prePaintScreen(ScreenPrePaintData& data, std::chrono::milliseconds presentTime) { if (m_currentPaintScreenIterator != m_activeEffects.constEnd()) { - (*m_currentPaintScreenIterator++)->prePaintScreen(data, time); + (*m_currentPaintScreenIterator++)->prePaintScreen(data, presentTime); --m_currentPaintScreenIterator; } // no special final code @@ -406,10 +406,10 @@ void EffectsHandlerImpl::postPaintScreen() // no special final code } -void EffectsHandlerImpl::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int time) +void EffectsHandlerImpl::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, std::chrono::milliseconds presentTime) { if (m_currentPaintWindowIterator != m_activeEffects.constEnd()) { - (*m_currentPaintWindowIterator++)->prePaintWindow(w, data, time); + (*m_currentPaintWindowIterator++)->prePaintWindow(w, data, presentTime); --m_currentPaintWindowIterator; } // no special final code diff --git a/effects.h b/effects.h index dd02767bfa..e069886d0b 100644 --- a/effects.h +++ b/effects.h @@ -59,14 +59,14 @@ class KWIN_EXPORT EffectsHandlerImpl : public EffectsHandler public: EffectsHandlerImpl(Compositor *compositor, Scene *scene); ~EffectsHandlerImpl() override; - void prePaintScreen(ScreenPrePaintData& data, int time) override; + void prePaintScreen(ScreenPrePaintData& data, std::chrono::milliseconds presentTime) override; void paintScreen(int mask, const QRegion ®ion, ScreenPaintData& data) override; /** * Special hook to perform a paintScreen but just with the windows on @p desktop. */ void paintDesktop(int desktop, int mask, QRegion region, ScreenPaintData& data); void postPaintScreen() override; - void prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int time) override; + void prePaintWindow(EffectWindow* w, WindowPrePaintData& data, std::chrono::milliseconds presentTime) override; void paintWindow(EffectWindow* w, int mask, const QRegion ®ion, WindowPaintData& data) override; void postPaintWindow(EffectWindow* w) override; void paintEffectFrame(EffectFrame* frame, const QRegion ®ion, double opacity, double frameOpacity) override; diff --git a/effects/backgroundcontrast/contrast.cpp b/effects/backgroundcontrast/contrast.cpp index 2c20a200aa..6e548eec47 100644 --- a/effects/backgroundcontrast/contrast.cpp +++ b/effects/backgroundcontrast/contrast.cpp @@ -336,19 +336,19 @@ void ContrastEffect::uploadGeometry(GLVertexBuffer *vbo, const QRegion ®ion) vbo->setAttribLayout(layout, 2, sizeof(QVector2D)); } -void ContrastEffect::prePaintScreen(ScreenPrePaintData &data, int time) +void ContrastEffect::prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) { m_paintedArea = QRegion(); m_currentContrast = QRegion(); - effects->prePaintScreen(data, time); + effects->prePaintScreen(data, presentTime); } -void ContrastEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int time) +void ContrastEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, std::chrono::milliseconds presentTime) { // this effect relies on prePaintWindow being called in the bottom to top order - effects->prePaintWindow(w, data, time); + effects->prePaintWindow(w, data, presentTime); if (!w->isPaintingEnabled()) { return; diff --git a/effects/backgroundcontrast/contrast.h b/effects/backgroundcontrast/contrast.h index c4ca3e21ab..a2ea3eb10e 100644 --- a/effects/backgroundcontrast/contrast.h +++ b/effects/backgroundcontrast/contrast.h @@ -37,8 +37,8 @@ public: static QMatrix4x4 colorMatrix(qreal contrast, qreal intensity, qreal saturation); void reconfigure(ReconfigureFlags flags) override; - void prePaintScreen(ScreenPrePaintData &data, int time) override; - void prePaintWindow(EffectWindow *w, WindowPrePaintData &data, int time) override; + void prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) override; + void prePaintWindow(EffectWindow *w, WindowPrePaintData &data, std::chrono::milliseconds presentTime) override; void drawWindow(EffectWindow *w, int mask, const QRegion ®ion, WindowPaintData &data) override; void paintEffectFrame(EffectFrame *frame, const QRegion ®ion, double opacity, double frameOpacity) override; diff --git a/effects/blur/blur.cpp b/effects/blur/blur.cpp index 201383aa70..63eae7ec1c 100644 --- a/effects/blur/blur.cpp +++ b/effects/blur/blur.cpp @@ -469,19 +469,19 @@ void BlurEffect::uploadGeometry(GLVertexBuffer *vbo, const QRegion &blurRegion, vbo->setAttribLayout(layout, 2, sizeof(QVector2D)); } -void BlurEffect::prePaintScreen(ScreenPrePaintData &data, int time) +void BlurEffect::prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) { m_paintedArea = QRegion(); m_currentBlur = QRegion(); - effects->prePaintScreen(data, time); + effects->prePaintScreen(data, presentTime); } -void BlurEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int time) +void BlurEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, std::chrono::milliseconds presentTime) { // this effect relies on prePaintWindow being called in the bottom to top order - effects->prePaintWindow(w, data, time); + effects->prePaintWindow(w, data, presentTime); if (!w->isPaintingEnabled()) { return; diff --git a/effects/blur/blur.h b/effects/blur/blur.h index fdf5f135b2..8638abfe8f 100644 --- a/effects/blur/blur.h +++ b/effects/blur/blur.h @@ -40,8 +40,8 @@ public: static bool enabledByDefault(); void reconfigure(ReconfigureFlags flags) override; - void prePaintScreen(ScreenPrePaintData &data, int time) override; - void prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int time) override; + void prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) override; + void prePaintWindow(EffectWindow* w, WindowPrePaintData& data, std::chrono::milliseconds presentTime) override; void drawWindow(EffectWindow *w, int mask, const QRegion ®ion, WindowPaintData &data) override; void paintEffectFrame(EffectFrame *frame, const QRegion ®ion, double opacity, double frameOpacity) override; diff --git a/effects/coverswitch/coverswitch.cpp b/effects/coverswitch/coverswitch.cpp index db8f6d12d4..a42ffa95c2 100644 --- a/effects/coverswitch/coverswitch.cpp +++ b/effects/coverswitch/coverswitch.cpp @@ -34,6 +34,7 @@ CoverSwitchEffect::CoverSwitchEffect() , stop(false) , stopRequested(false) , startRequested(false) + , lastPresentTime(std::chrono::milliseconds::zero()) , zPosition(900.0) , scaleFactor(0.0) , direction(Left) @@ -103,17 +104,23 @@ void CoverSwitchEffect::reconfigure(ReconfigureFlags) } -void CoverSwitchEffect::prePaintScreen(ScreenPrePaintData& data, int time) +void CoverSwitchEffect::prePaintScreen(ScreenPrePaintData& data, std::chrono::milliseconds presentTime) { + std::chrono::milliseconds delta = std::chrono::milliseconds::zero(); + if (lastPresentTime.count()) { + delta = presentTime - lastPresentTime; + } + lastPresentTime = presentTime; + if (mActivated || stop || stopRequested) { data.mask |= Effect::PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS; if (animation || start || stop) { - timeLine.update(std::chrono::milliseconds(time)); + timeLine.update(delta); } if (selected_window == nullptr) abort(); } - effects->prePaintScreen(data, time); + effects->prePaintScreen(data, presentTime); } void CoverSwitchEffect::paintScreen(int mask, const QRegion ®ion, ScreenPaintData& data) @@ -285,6 +292,7 @@ void CoverSwitchEffect::postPaintScreen() } referrencedWindows.clear(); currentWindowList.clear(); + lastPresentTime = std::chrono::milliseconds::zero(); if (startRequested) { startRequested = false; mActivated = true; @@ -538,6 +546,7 @@ void CoverSwitchEffect::slotTabBoxClosed() start = false; animation = false; timeLine.reset(); + lastPresentTime = std::chrono::milliseconds::zero(); } mActivated = false; effects->unrefTabBox(); @@ -907,6 +916,7 @@ void CoverSwitchEffect::abort() } effects->setActiveFullScreenEffect(nullptr); timeLine.reset(); + lastPresentTime = std::chrono::milliseconds::zero(); mActivated = false; stop = false; stopRequested = false; diff --git a/effects/coverswitch/coverswitch.h b/effects/coverswitch/coverswitch.h index d48b39b9e2..a3202f0f2d 100644 --- a/effects/coverswitch/coverswitch.h +++ b/effects/coverswitch/coverswitch.h @@ -42,7 +42,7 @@ public: ~CoverSwitchEffect() override; void reconfigure(ReconfigureFlags) override; - void prePaintScreen(ScreenPrePaintData &data, int time) override; + void prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) override; void paintScreen(int mask, const QRegion ®ion, ScreenPaintData &data) override; void postPaintScreen() override; void paintWindow(EffectWindow *w, int mask, QRegion region, WindowPaintData &data) override; @@ -123,6 +123,7 @@ private: bool stopRequested; bool startRequested; TimeLine timeLine; + std::chrono::milliseconds lastPresentTime; QRect area; float zPosition; float scaleFactor; diff --git a/effects/cube/cube.cpp b/effects/cube/cube.cpp index 9aa45f8a8c..9d8d643895 100644 --- a/effects/cube/cube.cpp +++ b/effects/cube/cube.cpp @@ -50,6 +50,7 @@ CubeEffect::CubeEffect() , wallpaper(nullptr) , texturedCaps(true) , capTexture(nullptr) + , lastPresentTime(std::chrono::milliseconds::zero()) , reflectionPainting(false) , activeScreen(0) , bottomCap(false) @@ -360,8 +361,14 @@ void CubeEffect::startVerticalAnimation(VerticalAnimationState state) verticalAnimationState = state; } -void CubeEffect::prePaintScreen(ScreenPrePaintData& data, int time) +void CubeEffect::prePaintScreen(ScreenPrePaintData& data, std::chrono::milliseconds presentTime) { + std::chrono::milliseconds delta = std::chrono::milliseconds::zero(); + if (lastPresentTime.count()) { + delta = presentTime - lastPresentTime; + } + lastPresentTime = presentTime; + if (activated) { data.mask |= PAINT_SCREEN_TRANSFORMED | Effect::PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS | PAINT_SCREEN_BACKGROUND_FIRST; if (animationState == AnimationState::None && !animations.empty()) { @@ -373,15 +380,15 @@ void CubeEffect::prePaintScreen(ScreenPrePaintData& data, int time) if (animationState != AnimationState::None || verticalAnimationState != VerticalAnimationState::None) { if (animationState != AnimationState::None) { - timeLine.update(std::chrono::milliseconds(time)); + timeLine.update(delta); } if (verticalAnimationState != VerticalAnimationState::None) { - verticalTimeLine.update(std::chrono::milliseconds(time)); + verticalTimeLine.update(delta); } rotateCube(); } } - effects->prePaintScreen(data, time); + effects->prePaintScreen(data, presentTime); } void CubeEffect::paintScreen(int mask, const QRegion ®ion, ScreenPaintData& data) @@ -973,6 +980,7 @@ void CubeEffect::postPaintScreen() animations.clear(); verticalAnimationState = VerticalAnimationState::None; verticalAnimations.clear(); + lastPresentTime = std::chrono::milliseconds::zero(); } else { if (!animations.empty()) startAnimation(animations.dequeue()); @@ -991,10 +999,12 @@ void CubeEffect::postPaintScreen() /* Repaint if there is any animation */ if (animation) { effects->addRepaintFull(); + } else { + lastPresentTime = std::chrono::milliseconds::zero(); } } -void CubeEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int time) +void CubeEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, std::chrono::milliseconds presentTime) { if (activated) { if (cube_painting) { @@ -1046,7 +1056,7 @@ void CubeEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int t data.quads = data.quads.splitAtY(rect.height() - w->y()); } data.setTransformed(); - effects->prePaintWindow(w, data, time); + effects->prePaintWindow(w, data, presentTime); return; } } @@ -1066,7 +1076,7 @@ void CubeEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int t data.quads = data.quads.splitAtY(rect.height() - w->y()); } data.setTransformed(); - effects->prePaintWindow(w, data, time); + effects->prePaintWindow(w, data, presentTime); return; } } @@ -1074,7 +1084,7 @@ void CubeEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int t } } } - effects->prePaintWindow(w, data, time); + effects->prePaintWindow(w, data, presentTime); } void CubeEffect::paintWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data) diff --git a/effects/cube/cube.h b/effects/cube/cube.h index 026f08c494..5388bc3d3b 100644 --- a/effects/cube/cube.h +++ b/effects/cube/cube.h @@ -47,10 +47,10 @@ public: CubeEffect(); ~CubeEffect() override; void reconfigure(ReconfigureFlags) override; - void prePaintScreen(ScreenPrePaintData& data, int time) override; + void prePaintScreen(ScreenPrePaintData& data, std::chrono::milliseconds presentTime) override; void paintScreen(int mask, const QRegion ®ion, ScreenPaintData& data) override; void postPaintScreen() override; - void prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int time) override; + void prePaintWindow(EffectWindow* w, WindowPrePaintData& data, std::chrono::milliseconds presentTime) override; void paintWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data) override; bool borderActivated(ElectricBorder border) override; void grabbedKeyboardEvent(QKeyEvent* e) override; @@ -200,6 +200,7 @@ private: VerticalAnimationState verticalAnimationState; TimeLine verticalTimeLine; QQueue verticalAnimations; + std::chrono::milliseconds lastPresentTime; bool reflectionPainting; std::chrono::milliseconds rotationDuration; diff --git a/effects/cubeslide/cubeslide.cpp b/effects/cubeslide/cubeslide.cpp index a32714a33f..3ed7c46618 100644 --- a/effects/cubeslide/cubeslide.cpp +++ b/effects/cubeslide/cubeslide.cpp @@ -22,6 +22,7 @@ namespace KWin CubeSlideEffect::CubeSlideEffect() : stickyPainting(false) + , lastPresentTime(std::chrono::milliseconds::zero()) , windowMoving(false) , desktopChangedWhileMoving(false) , progressRestriction(0.0f) @@ -64,15 +65,21 @@ void CubeSlideEffect::reconfigure(ReconfigureFlags) useWindowMoving = CubeSlideConfig::useWindowMoving(); } -void CubeSlideEffect::prePaintScreen(ScreenPrePaintData& data, int time) +void CubeSlideEffect::prePaintScreen(ScreenPrePaintData& data, std::chrono::milliseconds presentTime) { + std::chrono::milliseconds delta = std::chrono::milliseconds::zero(); + if (lastPresentTime.count()) { + delta = presentTime - lastPresentTime; + } + lastPresentTime = presentTime; + if (isActive()) { data.mask |= PAINT_SCREEN_TRANSFORMED | PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS | PAINT_SCREEN_BACKGROUND_FIRST; - timeLine.setCurrentTime(timeLine.currentTime() + time); + timeLine.setCurrentTime(timeLine.currentTime() + delta.count()); if (windowMoving && timeLine.currentTime() > progressRestriction * (qreal)timeLine.duration()) timeLine.setCurrentTime(progressRestriction * (qreal)timeLine.duration()); } - effects->prePaintScreen(data, time); + effects->prePaintScreen(data, presentTime); } void CubeSlideEffect::paintScreen(int mask, const QRegion ®ion, ScreenPaintData& data) @@ -169,7 +176,7 @@ void CubeSlideEffect::paintSlideCube(int mask, QRegion region, ScreenPaintData& painting_desktop = effects->currentDesktop(); } -void CubeSlideEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int time) +void CubeSlideEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, std::chrono::milliseconds presentTime) { if (stickyPainting) { if (staticWindows.contains(w)) { @@ -180,7 +187,7 @@ void CubeSlideEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, } else if (isActive() && cube_painting) { if (staticWindows.contains(w)) { w->disablePainting(EffectWindow::PAINT_DISABLED_BY_DESKTOP); - effects->prePaintWindow(w, data, time); + effects->prePaintWindow(w, data, presentTime); return; } QRect rect = effects->clientArea(FullArea, effects->activeScreen(), painting_desktop); @@ -230,7 +237,7 @@ void CubeSlideEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, } else w->disablePainting(EffectWindow::PAINT_DISABLED_BY_DESKTOP); } - effects->prePaintWindow(w, data, time); + effects->prePaintWindow(w, data, presentTime); } void CubeSlideEffect::paintWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data) @@ -375,6 +382,7 @@ void CubeSlideEffect::postPaintScreen() w->setData(WindowForceBackgroundContrastRole, QVariant()); } staticWindows.clear(); + lastPresentTime = std::chrono::milliseconds::zero(); effects->setActiveFullScreenEffect(nullptr); } } @@ -572,6 +580,7 @@ void CubeSlideEffect::slotWindowStepUserMovedResized(EffectWindow* w) windowMoving = false; desktopChangedWhileMoving = false; timeLine.setCurrentTime(0); + lastPresentTime = std::chrono::milliseconds::zero(); if (!slideRotations.isEmpty()) slideRotations.clear(); effects->setActiveFullScreenEffect(nullptr); @@ -652,6 +661,7 @@ void CubeSlideEffect::slotNumberDesktopsChanged() slideRotations.clear(); staticWindows.clear(); + lastPresentTime = std::chrono::milliseconds::zero(); effects->setActiveFullScreenEffect(nullptr); } diff --git a/effects/cubeslide/cubeslide.h b/effects/cubeslide/cubeslide.h index 5625f2fa5f..e4f38ca757 100644 --- a/effects/cubeslide/cubeslide.h +++ b/effects/cubeslide/cubeslide.h @@ -31,10 +31,10 @@ public: CubeSlideEffect(); ~CubeSlideEffect() override; void reconfigure(ReconfigureFlags) override; - void prePaintScreen(ScreenPrePaintData& data, int time) override; + void prePaintScreen(ScreenPrePaintData& data, std::chrono::milliseconds presentTime) override; void paintScreen(int mask, const QRegion ®ion, ScreenPaintData& data) override; void postPaintScreen() override; - void prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int time) override; + void prePaintWindow(EffectWindow* w, WindowPrePaintData& data, std::chrono::milliseconds presentTime) override; void paintWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data) override; bool isActive() const override; @@ -90,6 +90,7 @@ private: bool stickyPainting; QSet staticWindows; QTimeLine timeLine; + std::chrono::milliseconds lastPresentTime; QQueue slideRotations; bool dontSlidePanels; bool dontSlideStickyWindows; diff --git a/effects/desktopgrid/desktopgrid.cpp b/effects/desktopgrid/desktopgrid.cpp index 58f9204c89..e454622ecc 100644 --- a/effects/desktopgrid/desktopgrid.cpp +++ b/effects/desktopgrid/desktopgrid.cpp @@ -49,6 +49,7 @@ DesktopGridEffect::DesktopGridEffect() , windowMove(nullptr) , windowMoveDiff() , windowMoveElevateTimer(new QTimer(this)) + , lastPresentTime(std::chrono::milliseconds::zero()) , gridSize() , orientation(Qt::Horizontal) , activeCell(1, 1) @@ -143,8 +144,17 @@ void DesktopGridEffect::reconfigure(ReconfigureFlags) //----------------------------------------------------------------------------- // Screen painting -void DesktopGridEffect::prePaintScreen(ScreenPrePaintData& data, int time) +void DesktopGridEffect::prePaintScreen(ScreenPrePaintData& data, std::chrono::milliseconds presentTime) { + // The animation code assumes that the time diff cannot be 0, let's work around it. + int time; + if (lastPresentTime.count()) { + time = std::max(1, int((presentTime - lastPresentTime).count())); + } else { + time = 1; + } + lastPresentTime = presentTime; + if (timeline.currentValue() != 0 || activated || (isUsingPresentWindows() && isMotionManagerMovingWindows())) { if (activated) timeline.setCurrentTime(timeline.currentTime() + time); @@ -173,7 +183,7 @@ void DesktopGridEffect::prePaintScreen(ScreenPrePaintData& data, int time) w->setData(WindowForceBlurRole, QVariant(true)); } - effects->prePaintScreen(data, time); + effects->prePaintScreen(data, presentTime); } void DesktopGridEffect::paintScreen(int mask, const QRegion ®ion, ScreenPaintData& data) @@ -237,20 +247,31 @@ void DesktopGridEffect::paintScreen(int mask, const QRegion ®ion, ScreenPaint void DesktopGridEffect::postPaintScreen() { - if (activated ? timeline.currentValue() != 1 : timeline.currentValue() != 0) + bool resetLastPresentTime = true; + + if (activated ? timeline.currentValue() != 1 : timeline.currentValue() != 0) { effects->addRepaintFull(); // Repaint during zoom - if (isUsingPresentWindows() && isMotionManagerMovingWindows()) + resetLastPresentTime = false; + } + if (isUsingPresentWindows() && isMotionManagerMovingWindows()) { effects->addRepaintFull(); + resetLastPresentTime = false; + } if (activated) { for (int i = 0; i < effects->numberOfDesktops(); i++) { if (hoverTimeline[i]->currentValue() != 0.0 && hoverTimeline[i]->currentValue() != 1.0) { // Repaint during soft highlighting effects->addRepaintFull(); + resetLastPresentTime = false; break; } } } + if (resetLastPresentTime) { + lastPresentTime = std::chrono::milliseconds::zero(); + } + for (auto &w : effects->stackingOrder()) { w->setData(WindowForceBlurRole, QVariant()); } @@ -261,7 +282,7 @@ void DesktopGridEffect::postPaintScreen() //----------------------------------------------------------------------------- // Window painting -void DesktopGridEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int time) +void DesktopGridEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, std::chrono::milliseconds presentTime) { if (timeline.currentValue() != 0 || (isUsingPresentWindows() && isMotionManagerMovingWindows())) { if (w->isOnDesktop(paintingDesktop)) { @@ -287,7 +308,7 @@ void DesktopGridEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data } else w->disablePainting(EffectWindow::PAINT_DISABLED_BY_DESKTOP); } - effects->prePaintWindow(w, data, time); + effects->prePaintWindow(w, data, presentTime); } void DesktopGridEffect::paintWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data) @@ -1218,6 +1239,7 @@ void DesktopGridEffect::finish() if (keyboardGrab) effects->ungrabKeyboard(); keyboardGrab = false; + lastPresentTime = std::chrono::milliseconds::zero(); effects->stopMouseInterception(this); effects->setActiveFullScreenEffect(nullptr); if (isUsingPresentWindows()) { diff --git a/effects/desktopgrid/desktopgrid.h b/effects/desktopgrid/desktopgrid.h index ec1aa4799f..321d06fe53 100644 --- a/effects/desktopgrid/desktopgrid.h +++ b/effects/desktopgrid/desktopgrid.h @@ -39,10 +39,10 @@ public: DesktopGridEffect(); ~DesktopGridEffect() override; void reconfigure(ReconfigureFlags) override; - void prePaintScreen(ScreenPrePaintData& data, int time) override; + void prePaintScreen(ScreenPrePaintData& data, std::chrono::milliseconds presentTime) override; void paintScreen(int mask, const QRegion ®ion, ScreenPaintData& data) override; void postPaintScreen() override; - void prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int time) override; + void prePaintWindow(EffectWindow* w, WindowPrePaintData& data, std::chrono::milliseconds presentTime) override; void paintWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data) override; void windowInputMouseEvent(QEvent* e) override; void grabbedKeyboardEvent(QKeyEvent* e) override; @@ -131,6 +131,7 @@ private: QPoint windowMoveDiff; QPoint dragStartPos; QTimer *windowMoveElevateTimer; + std::chrono::milliseconds lastPresentTime; // Soft highlighting QList hoverTimeline; diff --git a/effects/diminactive/diminactive.cpp b/effects/diminactive/diminactive.cpp index 837421f10b..71e8c22e0c 100644 --- a/effects/diminactive/diminactive.cpp +++ b/effects/diminactive/diminactive.cpp @@ -82,9 +82,13 @@ void DimInactiveEffect::reconfigure(ReconfigureFlags flags) effects->addRepaintFull(); } -void DimInactiveEffect::prePaintScreen(ScreenPrePaintData &data, int time) +void DimInactiveEffect::prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) { - const std::chrono::milliseconds delta(time); + std::chrono::milliseconds delta(0); + if (m_lastPresentTime.count()) { + delta = presentTime - m_lastPresentTime; + } + m_lastPresentTime = presentTime; if (m_fullScreenTransition.active) { m_fullScreenTransition.timeLine.update(delta); @@ -96,7 +100,7 @@ void DimInactiveEffect::prePaintScreen(ScreenPrePaintData &data, int time) ++transitionIt; } - effects->prePaintScreen(data, time); + effects->prePaintScreen(data, presentTime); } void DimInactiveEffect::paintWindow(EffectWindow *w, int mask, QRegion region, WindowPaintData &data) @@ -144,6 +148,10 @@ void DimInactiveEffect::postPaintScreen() w->addRepaintFull(); } + if (m_transitions.isEmpty() && !m_fullScreenTransition.active) { + m_lastPresentTime = std::chrono::milliseconds::zero(); + } + effects->postPaintScreen(); } diff --git a/effects/diminactive/diminactive.h b/effects/diminactive/diminactive.h index 9c01f06093..18c90a10a0 100644 --- a/effects/diminactive/diminactive.h +++ b/effects/diminactive/diminactive.h @@ -34,7 +34,7 @@ public: void reconfigure(ReconfigureFlags flags) override; - void prePaintScreen(ScreenPrePaintData &data, int time) override; + void prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) override; void paintWindow(EffectWindow *w, int mask, QRegion region, WindowPaintData &data) override; void postPaintScreen() override; @@ -77,6 +77,7 @@ private: const EffectWindowGroup *m_activeWindowGroup; QHash m_transitions; QHash m_forceDim; + std::chrono::milliseconds m_lastPresentTime = std::chrono::milliseconds::zero(); struct { bool active = false; diff --git a/effects/fallapart/fallapart.cpp b/effects/fallapart/fallapart.cpp index d521180a90..2f4b4fe0f4 100644 --- a/effects/fallapart/fallapart.cpp +++ b/effects/fallapart/fallapart.cpp @@ -36,18 +36,25 @@ void FallApartEffect::reconfigure(ReconfigureFlags) blockSize = FallApartConfig::blockSize(); } -void FallApartEffect::prePaintScreen(ScreenPrePaintData& data, int time) +void FallApartEffect::prePaintScreen(ScreenPrePaintData& data, std::chrono::milliseconds presentTime) { if (!windows.isEmpty()) data.mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS; - effects->prePaintScreen(data, time); + effects->prePaintScreen(data, presentTime); } -void FallApartEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int time) +void FallApartEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, std::chrono::milliseconds presentTime) { - if (windows.contains(w) && isRealWindow(w)) { - if (windows[ w ] < 1) { - windows[ w ] += time / animationTime(1000.); + auto animationIt = windows.find(w); + if (animationIt != windows.end() && isRealWindow(w)) { + if (animationIt->progress < 1) { + int time = 0; + if (animationIt->lastPresentTime.count()) { + time = (presentTime - animationIt->lastPresentTime).count(); + } + animationIt->lastPresentTime = presentTime; + + animationIt->progress += time / animationTime(1000.); data.setTransformed(); w->enablePainting(EffectWindow::PAINT_DISABLED_BY_DELETE); // Request the window to be divided into cells @@ -57,13 +64,14 @@ void FallApartEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, w->unrefWindow(); } } - effects->prePaintWindow(w, data, time); + effects->prePaintWindow(w, data, presentTime); } void FallApartEffect::paintWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data) { - if (windows.contains(w) && isRealWindow(w)) { - const qreal t = windows[w]; + auto animationIt = windows.constFind(w); + if (animationIt != windows.constEnd() && isRealWindow(w)) { + const qreal t = animationIt->progress; WindowQuadList new_quads; int cnt = 0; foreach (WindowQuad quad, data.quads) { // krazy:exclude=foreach @@ -99,7 +107,7 @@ void FallApartEffect::paintWindow(EffectWindow* w, int mask, QRegion region, Win double x = quad[ j ].x() - center.x(); double y = quad[ j ].y() - center.y(); double angle = atan2(y, x); - angle += windows[ w ] * adiff; + angle += animationIt->progress * adiff; double dist = sqrt(x * x + y * y); x = dist * cos(angle); y = dist * sin(angle); @@ -156,7 +164,7 @@ void FallApartEffect::slotWindowClosed(EffectWindow* c) if (e && e != this) return; c->setData(WindowClosedGrabRole, QVariant::fromValue(static_cast(this))); - windows[ c ] = 0; + windows[ c ].progress = 0; c->refWindow(); } diff --git a/effects/fallapart/fallapart.h b/effects/fallapart/fallapart.h index 9fed03b44a..526b1fba06 100644 --- a/effects/fallapart/fallapart.h +++ b/effects/fallapart/fallapart.h @@ -15,6 +15,12 @@ namespace KWin { +struct FallApartAnimation +{ + std::chrono::milliseconds lastPresentTime = std::chrono::milliseconds::zero(); + qreal progress = 0; +}; + class FallApartEffect : public Effect { @@ -23,8 +29,8 @@ class FallApartEffect public: FallApartEffect(); void reconfigure(ReconfigureFlags) override; - void prePaintScreen(ScreenPrePaintData& data, int time) override; - void prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int time) override; + void prePaintScreen(ScreenPrePaintData& data, std::chrono::milliseconds presentTime) override; + void prePaintWindow(EffectWindow* w, WindowPrePaintData& data, std::chrono::milliseconds presentTime) override; void paintWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data) override; void postPaintScreen() override; bool isActive() const override; @@ -46,7 +52,7 @@ public Q_SLOTS: void slotWindowDataChanged(KWin::EffectWindow *w, int role); private: - QHash< EffectWindow*, double > windows; + QHash< EffectWindow*, FallApartAnimation > windows; bool isRealWindow(EffectWindow* w); int blockSize; }; diff --git a/effects/flipswitch/flipswitch.cpp b/effects/flipswitch/flipswitch.cpp index bdc175f9ac..c149fa7f31 100644 --- a/effects/flipswitch/flipswitch.cpp +++ b/effects/flipswitch/flipswitch.cpp @@ -27,6 +27,7 @@ namespace KWin FlipSwitchEffect::FlipSwitchEffect() : m_selectedWindow(nullptr) , m_currentAnimationEasingCurve(QEasingCurve::InOutSine) + , m_lastPresentTime(std::chrono::milliseconds::zero()) , m_active(false) , m_start(false) , m_stop(false) @@ -93,8 +94,14 @@ void FlipSwitchEffect::reconfigure(ReconfigureFlags) m_windowTitle = FlipSwitchConfig::windowTitle(); } -void FlipSwitchEffect::prePaintScreen(ScreenPrePaintData& data, int time) +void FlipSwitchEffect::prePaintScreen(ScreenPrePaintData& data, std::chrono::milliseconds presentTime) { + int time = 0; + if (m_lastPresentTime.count()) { + time = (presentTime - m_lastPresentTime).count(); + } + m_lastPresentTime = presentTime; + if (m_active) { data.mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS; if (m_start) @@ -104,7 +111,7 @@ void FlipSwitchEffect::prePaintScreen(ScreenPrePaintData& data, int time) if (m_animation) m_timeLine.setCurrentTime(m_timeLine.currentTime() + time); } - effects->prePaintScreen(data, time); + effects->prePaintScreen(data, presentTime); } void FlipSwitchEffect::paintScreen(int mask, const QRegion ®ion, ScreenPaintData& data) @@ -318,6 +325,7 @@ void FlipSwitchEffect::postPaintScreen() m_stop = false; m_active = false; m_captionFrame->free(); + m_lastPresentTime = std::chrono::milliseconds::zero(); effects->setActiveFullScreenEffect(nullptr); effects->addRepaintFull(); qDeleteAll(m_windows); @@ -347,7 +355,7 @@ void FlipSwitchEffect::postPaintScreen() effects->postPaintScreen(); } -void FlipSwitchEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int time) +void FlipSwitchEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, std::chrono::milliseconds presentTime) { if (m_active) { if (m_windows.contains(w)) { @@ -364,7 +372,7 @@ void FlipSwitchEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, w->disablePainting(EffectWindow::PAINT_DISABLED_BY_DESKTOP); } } - effects->prePaintWindow(w, data, time); + effects->prePaintWindow(w, data, presentTime); } void FlipSwitchEffect::paintWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data) diff --git a/effects/flipswitch/flipswitch.h b/effects/flipswitch/flipswitch.h index b45ec7ddad..cef9fb1661 100644 --- a/effects/flipswitch/flipswitch.h +++ b/effects/flipswitch/flipswitch.h @@ -35,10 +35,10 @@ public: ~FlipSwitchEffect() override; void reconfigure(ReconfigureFlags) override; - void prePaintScreen(ScreenPrePaintData& data, int time) override; + void prePaintScreen(ScreenPrePaintData& data, std::chrono::milliseconds presentTime) override; void paintScreen(int mask, const QRegion ®ion, ScreenPaintData& data) override; void postPaintScreen() override; - void prePaintWindow(EffectWindow *w, WindowPrePaintData &data, int time) override; + void prePaintWindow(EffectWindow *w, WindowPrePaintData &data, std::chrono::milliseconds presentTime) override; void paintWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data) override; void grabbedKeyboardEvent(QKeyEvent* e) override; void windowInputMouseEvent(QEvent* e) override; @@ -112,6 +112,7 @@ private: QTimeLine m_timeLine; QTimeLine m_startStopTimeLine; QEasingCurve m_currentAnimationEasingCurve; + std::chrono::milliseconds m_lastPresentTime; QRect m_screenArea; int m_activeScreen; bool m_active; diff --git a/effects/glide/glide.cpp b/effects/glide/glide.cpp index 0b0c18d136..ea3d2be75d 100644 --- a/effects/glide/glide.cpp +++ b/effects/glide/glide.cpp @@ -68,29 +68,33 @@ void GlideEffect::reconfigure(ReconfigureFlags flags) m_outParams.opacity.to = GlideConfig::outOpacity(); } -void GlideEffect::prePaintScreen(ScreenPrePaintData &data, int time) +void GlideEffect::prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) { - const std::chrono::milliseconds delta(time); - auto animationIt = m_animations.begin(); while (animationIt != m_animations.end()) { - (*animationIt).update(delta); + std::chrono::milliseconds delta = std::chrono::milliseconds::zero(); + if (animationIt->lastPresentTime.count()) { + delta = presentTime - animationIt->lastPresentTime; + } + animationIt->lastPresentTime = presentTime; + + (*animationIt).timeLine.update(delta); ++animationIt; } data.mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS; - effects->prePaintScreen(data, time); + effects->prePaintScreen(data, presentTime); } -void GlideEffect::prePaintWindow(EffectWindow *w, WindowPrePaintData &data, int time) +void GlideEffect::prePaintWindow(EffectWindow *w, WindowPrePaintData &data, std::chrono::milliseconds presentTime) { if (m_animations.contains(w)) { data.setTransformed(); w->enablePainting(EffectWindow::PAINT_DISABLED_BY_DELETE); } - effects->prePaintWindow(w, data, time); + effects->prePaintWindow(w, data, presentTime); } void GlideEffect::paintWindow(EffectWindow *w, int mask, QRegion region, WindowPaintData &data) @@ -123,7 +127,7 @@ void GlideEffect::paintWindow(EffectWindow *w, int mask, QRegion region, WindowP data.translate(offset.x(), offset.y()); const GlideParams params = w->isDeleted() ? m_outParams : m_inParams; - const qreal t = (*animationIt).value(); + const qreal t = (*animationIt).timeLine.value(); switch (params.edge) { case RotationEdge::Top: @@ -168,7 +172,7 @@ void GlideEffect::postPaintScreen() { auto animationIt = m_animations.begin(); while (animationIt != m_animations.end()) { - if ((*animationIt).done()) { + if ((*animationIt).timeLine.done()) { EffectWindow *w = animationIt.key(); if (w->isDeleted()) { w->unrefWindow(); @@ -215,11 +219,11 @@ void GlideEffect::windowAdded(EffectWindow *w) w->setData(WindowAddedGrabRole, QVariant::fromValue(static_cast(this))); - TimeLine &timeLine = m_animations[w]; - timeLine.reset(); - timeLine.setDirection(TimeLine::Forward); - timeLine.setDuration(m_duration); - timeLine.setEasingCurve(QEasingCurve::InCurve); + GlideAnimation &animation = m_animations[w]; + animation.timeLine.reset(); + animation.timeLine.setDirection(TimeLine::Forward); + animation.timeLine.setDuration(m_duration); + animation.timeLine.setEasingCurve(QEasingCurve::InCurve); effects->addRepaintFull(); } @@ -246,11 +250,11 @@ void GlideEffect::windowClosed(EffectWindow *w) w->refWindow(); w->setData(WindowClosedGrabRole, QVariant::fromValue(static_cast(this))); - TimeLine &timeLine = m_animations[w]; - timeLine.reset(); - timeLine.setDirection(TimeLine::Forward); - timeLine.setDuration(m_duration); - timeLine.setEasingCurve(QEasingCurve::OutCurve); + GlideAnimation &animation = m_animations[w]; + animation.timeLine.reset(); + animation.timeLine.setDirection(TimeLine::Forward); + animation.timeLine.setDuration(m_duration); + animation.timeLine.setEasingCurve(QEasingCurve::OutCurve); effects->addRepaintFull(); } diff --git a/effects/glide/glide.h b/effects/glide/glide.h index d456eebe79..13b315fdab 100644 --- a/effects/glide/glide.h +++ b/effects/glide/glide.h @@ -19,6 +19,12 @@ namespace KWin { +struct GlideAnimation +{ + TimeLine timeLine; + std::chrono::milliseconds lastPresentTime = std::chrono::milliseconds::zero(); +}; + class GlideEffect : public Effect { Q_OBJECT @@ -38,8 +44,8 @@ public: void reconfigure(ReconfigureFlags flags) override; - void prePaintScreen(ScreenPrePaintData &data, int time) override; - void prePaintWindow(EffectWindow *w, WindowPrePaintData &data, int time) override; + void prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) override; + void prePaintWindow(EffectWindow *w, WindowPrePaintData &data, std::chrono::milliseconds presentTime) override; void paintWindow(EffectWindow *w, int mask, QRegion region, WindowPaintData &data) override; void postPaintScreen() override; @@ -76,7 +82,7 @@ private: bool isGlideWindow(EffectWindow *w) const; std::chrono::milliseconds m_duration; - QHash m_animations; + QHash m_animations; struct GlideParams { RotationEdge edge; diff --git a/effects/highlightwindow/highlightwindow.cpp b/effects/highlightwindow/highlightwindow.cpp index 28594c47fa..089c21e08d 100644 --- a/effects/highlightwindow/highlightwindow.cpp +++ b/effects/highlightwindow/highlightwindow.cpp @@ -43,59 +43,76 @@ static bool isInitiallyHidden(EffectWindow* w) return w->isMinimized() || !w->isOnCurrentDesktop(); } -void HighlightWindowEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int time) +void HighlightWindowEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, std::chrono::milliseconds presentTime) { // Calculate window opacities - QHash::iterator opacity = m_windowOpacity.find(w); + QHash::iterator it = m_animations.find(w); if (!m_highlightedWindows.isEmpty()) { // Initial fade out and changing highlight animation - if (opacity == m_windowOpacity.end()) - opacity = m_windowOpacity.insert(w, 0.0f); - float oldOpacity = *opacity; + if (it == m_animations.end()) + it = m_animations.insert(w, HightlightWindowData()); + + int time = 1; + if (it->lastPresentTime.count()) { + time = std::max(1, int((presentTime - it->lastPresentTime).count())); + } + it->lastPresentTime = presentTime; + + float oldOpacity = it->opacity; if (m_highlightedWindows.contains(w)) - *opacity = qMin(1.0f, oldOpacity + time / m_fadeDuration); + it->opacity = qMin(1.0f, oldOpacity + time / m_fadeDuration); else if (w->isNormalWindow() || w->isDialog()) // Only fade out windows - *opacity = qMax(isInitiallyHidden(w) ? 0.0f : 0.15f, oldOpacity - time / m_fadeDuration); + it->opacity = qMax(isInitiallyHidden(w) ? 0.0f : 0.15f, oldOpacity - time / m_fadeDuration); - if (*opacity < 0.98f) + if (it->opacity < 0.98f) data.setTranslucent(); - if (oldOpacity != *opacity) + if (oldOpacity != it->opacity) effects->addRepaint(w->expandedGeometry()); - } else if (m_finishing && m_windowOpacity.contains(w)) { + } else if (m_finishing && m_animations.contains(w)) { // Final fading back in animation - if (opacity == m_windowOpacity.end()) - opacity = m_windowOpacity.insert(w, 0.0f); - float oldOpacity = *opacity; - if (isInitiallyHidden(w)) - *opacity = qMax(0.0f, oldOpacity - time / m_fadeDuration); - else - *opacity = qMin(1.0f, oldOpacity + time / m_fadeDuration); + if (it == m_animations.end()) + it = m_animations.insert(w, HightlightWindowData()); - if (*opacity < 0.98f) + int time = 1; + if (it->lastPresentTime.count()) { + time = std::max(1, int((presentTime - it->lastPresentTime).count())); + } + it->lastPresentTime = presentTime; + + float oldOpacity = it->opacity; + if (isInitiallyHidden(w)) + it->opacity = qMax(0.0f, oldOpacity - time / m_fadeDuration); + else + it->opacity = qMin(1.0f, oldOpacity + time / m_fadeDuration); + + if (it->opacity < 0.98f) data.setTranslucent(); - if (oldOpacity != *opacity) + if (oldOpacity != it->opacity) effects->addRepaint(w->expandedGeometry()); - if (*opacity > 0.98f || *opacity < 0.02f) { - m_windowOpacity.remove(w); // We default to 1.0 - opacity = m_windowOpacity.end(); + if (it->opacity > 0.98f || it->opacity < 0.02f) { + m_animations.remove(w); // We default to 1.0 + it = m_animations.end(); } } // Show tabbed windows and windows on other desktops if highlighted - if (opacity != m_windowOpacity.end() && *opacity > 0.01) { + if (it != m_animations.end() && it->opacity > 0.01) { if (w->isMinimized()) w->enablePainting(EffectWindow::PAINT_DISABLED_BY_MINIMIZE); if (!w->isOnCurrentDesktop()) w->enablePainting(EffectWindow::PAINT_DISABLED_BY_DESKTOP); } - effects->prePaintWindow(w, data, time); + effects->prePaintWindow(w, data, presentTime); } void HighlightWindowEffect::paintWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data) { - data.multiplyOpacity(m_windowOpacity.value(w, 1.0f)); + auto it = m_animations.constFind(w); + if (it != m_animations.constEnd()) { + data.multiplyOpacity(it->opacity); + } effects->paintWindow(w, mask, region, data); } @@ -105,11 +122,11 @@ void HighlightWindowEffect::slotWindowAdded(EffectWindow* w) // The effect is activated thus we need to add it to the opacity hash foreach (const WId id, m_highlightedIds) { if (w == effects->findWindow(id)) { - m_windowOpacity[w] = 1.0; // this window was demanded to be highlighted before it appeared + m_animations[w].opacity = 1.0; // this window was demanded to be highlighted before it appeared return; } } - m_windowOpacity[w] = 0.15; // this window is not currently highlighted + m_animations[w].opacity = 0.15; // this window is not currently highlighted } slotPropertyNotify(w, m_atom, w); // Check initial value } @@ -122,7 +139,7 @@ void HighlightWindowEffect::slotWindowClosed(EffectWindow* w) void HighlightWindowEffect::slotWindowDeleted(EffectWindow* w) { - m_windowOpacity.remove(w); + m_animations.remove(w); } void HighlightWindowEffect::slotPropertyNotify(EffectWindow* w, long a, EffectWindow *addedWindow) @@ -172,7 +189,7 @@ void HighlightWindowEffect::slotPropertyNotify(EffectWindow* w, long a, EffectWi } prepareHighlighting(); if (w) - m_windowOpacity[w] = 1.0; // Because it's not in stackingOrder() yet + m_animations[w].opacity = 1.0; // Because it's not in stackingOrder() yet /* TODO: Finish thumbnails of offscreen windows, not sure if it's worth it though if ( !m_highlightedWindow->isOnCurrentDesktop() ) @@ -238,8 +255,8 @@ void HighlightWindowEffect::prepareHighlighting() // Create window data for every window. Just calling [w] creates it. m_finishing = false; foreach (EffectWindow * w, effects->stackingOrder()) { - if (!m_windowOpacity.contains(w)) // Just in case we are still finishing from last time - m_windowOpacity.insert(w, isInitiallyHidden(w) ? 0.0 : 1.0); + if (!m_animations.contains(w)) // Just in case we are still finishing from last time + m_animations[w].opacity = isInitiallyHidden(w) ? 0.0 : 1.0; if (!m_highlightedWindows.isEmpty()) m_highlightedWindows.at(0)->addRepaintFull(); } @@ -250,8 +267,8 @@ void HighlightWindowEffect::finishHighlighting() m_finishing = true; m_monitorWindow = nullptr; m_highlightedWindows.clear(); - if (!m_windowOpacity.isEmpty()) - m_windowOpacity.constBegin().key()->addRepaintFull(); + if (!m_animations.isEmpty()) + m_animations.constBegin().key()->addRepaintFull(); } void HighlightWindowEffect::highlightWindows(const QVector &windows) @@ -272,7 +289,7 @@ void HighlightWindowEffect::highlightWindows(const QVector bool HighlightWindowEffect::isActive() const { - return !(m_windowOpacity.isEmpty() || effects->isScreenLocked()); + return !(m_animations.isEmpty() || effects->isScreenLocked()); } bool HighlightWindowEffect::provides(Feature feature) diff --git a/effects/highlightwindow/highlightwindow.h b/effects/highlightwindow/highlightwindow.h index b8b80d3cfe..7b5ac17390 100644 --- a/effects/highlightwindow/highlightwindow.h +++ b/effects/highlightwindow/highlightwindow.h @@ -15,6 +15,12 @@ namespace KWin { +struct HightlightWindowData +{ + std::chrono::milliseconds lastPresentTime = std::chrono::milliseconds::zero(); + float opacity = 0; +}; + class HighlightWindowEffect : public Effect { @@ -23,7 +29,7 @@ public: HighlightWindowEffect(); ~HighlightWindowEffect() override; - void prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int time) override; + void prePaintWindow(EffectWindow* w, WindowPrePaintData& data, std::chrono::milliseconds presentTime) override; void paintWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data) override; bool isActive() const override; @@ -49,7 +55,7 @@ private: bool m_finishing; float m_fadeDuration; - QHash m_windowOpacity; + QHash m_animations; long m_atom; QList m_highlightedWindows; diff --git a/effects/kscreen/kscreen.cpp b/effects/kscreen/kscreen.cpp index affa73ddae..06c29aee54 100644 --- a/effects/kscreen/kscreen.cpp +++ b/effects/kscreen/kscreen.cpp @@ -41,6 +41,7 @@ namespace KWin KscreenEffect::KscreenEffect() : Effect() + , m_lastPresentTime(std::chrono::milliseconds::zero()) , m_state(StateNormal) , m_atom(effects->announceSupportProperty("_KDE_KWIN_KSCREEN_SUPPORT", this)) { @@ -67,15 +68,27 @@ void KscreenEffect::reconfigure(ReconfigureFlags flags) std::chrono::milliseconds(animationTime(250))); } -void KscreenEffect::prePaintScreen(ScreenPrePaintData &data, int time) +void KscreenEffect::prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) { + std::chrono::milliseconds delta = std::chrono::milliseconds::zero(); + if (m_lastPresentTime.count()) { + delta = presentTime - m_lastPresentTime; + } + if (m_state == StateFadingIn || m_state == StateFadingOut) { - m_timeLine.update(std::chrono::milliseconds(time)); + m_timeLine.update(delta); if (m_timeLine.done()) { switchState(); } } - effects->prePaintScreen(data, time); + + if (isActive()) { + m_lastPresentTime = presentTime; + } else { + m_lastPresentTime = std::chrono::milliseconds::zero(); + } + + effects->prePaintScreen(data, presentTime); } void KscreenEffect::postPaintScreen() @@ -85,12 +98,12 @@ void KscreenEffect::postPaintScreen() } } -void KscreenEffect::prePaintWindow(EffectWindow *w, WindowPrePaintData &data, int time) +void KscreenEffect::prePaintWindow(EffectWindow *w, WindowPrePaintData &data, std::chrono::milliseconds presentTime) { if (m_state != StateNormal) { data.setTranslucent(); } - effects->prePaintWindow(w, data, time); + effects->prePaintWindow(w, data, presentTime); } void KscreenEffect::paintWindow(EffectWindow *w, int mask, QRegion region, WindowPaintData &data) diff --git a/effects/kscreen/kscreen.h b/effects/kscreen/kscreen.h index 83074239a6..b01ef9f3ac 100644 --- a/effects/kscreen/kscreen.h +++ b/effects/kscreen/kscreen.h @@ -22,9 +22,9 @@ public: KscreenEffect(); ~KscreenEffect() override; - void prePaintScreen(ScreenPrePaintData &data, int time) override; + void prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) override; void postPaintScreen() override; - void prePaintWindow(EffectWindow *w, WindowPrePaintData &data, int time) override; + void prePaintWindow(EffectWindow *w, WindowPrePaintData &data, std::chrono::milliseconds presentTime) override; void paintWindow(EffectWindow *w, int mask, QRegion region, WindowPaintData &data) override; void reconfigure(ReconfigureFlags flags) override; @@ -46,6 +46,7 @@ private: StateFadingIn }; TimeLine m_timeLine; + std::chrono::milliseconds m_lastPresentTime; FadeOutState m_state; xcb_atom_t m_atom; }; diff --git a/effects/lookingglass/lookingglass.cpp b/effects/lookingglass/lookingglass.cpp index 283c89d328..dbc2c5d45b 100644 --- a/effects/lookingglass/lookingglass.cpp +++ b/effects/lookingglass/lookingglass.cpp @@ -38,6 +38,7 @@ LookingGlassEffect::LookingGlassEffect() , m_fbo(nullptr) , m_vbo(nullptr) , m_shader(nullptr) + , m_lastPresentTime(std::chrono::milliseconds::zero()) , m_enabled(false) , m_valid(false) { @@ -179,8 +180,9 @@ void LookingGlassEffect::zoomOut() effects->addRepaint(cursorPos().x() - radius, cursorPos().y() - radius, 2 * radius, 2 * radius); } -void LookingGlassEffect::prePaintScreen(ScreenPrePaintData& data, int time) +void LookingGlassEffect::prePaintScreen(ScreenPrePaintData& data, std::chrono::milliseconds presentTime) { + const int time = m_lastPresentTime.count() ? (presentTime - m_lastPresentTime).count() : 0; if (zoom != target_zoom) { double diff = time / animationTime(500.0); if (target_zoom > zoom) @@ -196,13 +198,18 @@ void LookingGlassEffect::prePaintScreen(ScreenPrePaintData& data, int time) effects->addRepaint(cursorPos().x() - radius, cursorPos().y() - radius, 2 * radius, 2 * radius); } + if (zoom != target_zoom) { + m_lastPresentTime = presentTime; + } else { + m_lastPresentTime = std::chrono::milliseconds::zero(); + } if (m_valid && m_enabled) { data.mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS; // Start rendering to texture GLRenderTarget::pushRenderTarget(m_fbo); } - effects->prePaintScreen(data, time); + effects->prePaintScreen(data, presentTime); } void LookingGlassEffect::slotMouseChanged(const QPoint& pos, const QPoint& old, Qt::MouseButtons, diff --git a/effects/lookingglass/lookingglass.h b/effects/lookingglass/lookingglass.h index 463c3dc325..3394bf505b 100644 --- a/effects/lookingglass/lookingglass.h +++ b/effects/lookingglass/lookingglass.h @@ -34,7 +34,7 @@ public: void reconfigure(ReconfigureFlags) override; - void prePaintScreen(ScreenPrePaintData& data, int time) override; + void prePaintScreen(ScreenPrePaintData& data, std::chrono::milliseconds presentTime) override; void paintScreen(int mask, const QRegion ®ion, ScreenPaintData &data) override; bool isActive() const override; @@ -63,6 +63,7 @@ private: GLRenderTarget *m_fbo; GLVertexBuffer *m_vbo; GLShader *m_shader; + std::chrono::milliseconds m_lastPresentTime; bool m_enabled; bool m_valid; }; diff --git a/effects/magiclamp/magiclamp.cpp b/effects/magiclamp/magiclamp.cpp index 4c7c0fc50a..647f0055bc 100644 --- a/effects/magiclamp/magiclamp.cpp +++ b/effects/magiclamp/magiclamp.cpp @@ -42,13 +42,17 @@ void MagicLampEffect::reconfigure(ReconfigureFlags) m_duration = std::chrono::milliseconds(static_cast(animationTime(d))); } -void MagicLampEffect::prePaintScreen(ScreenPrePaintData& data, int time) +void MagicLampEffect::prePaintScreen(ScreenPrePaintData& data, std::chrono::milliseconds presentTime) { - const std::chrono::milliseconds delta(time); - auto animationIt = m_animations.begin(); while (animationIt != m_animations.end()) { - (*animationIt).update(delta); + std::chrono::milliseconds delta = std::chrono::milliseconds::zero(); + if (animationIt->lastPresentTime.count()) { + delta = presentTime - animationIt->lastPresentTime; + } + animationIt->lastPresentTime = presentTime; + + (*animationIt).timeLine.update(delta); ++animationIt; } @@ -56,10 +60,10 @@ void MagicLampEffect::prePaintScreen(ScreenPrePaintData& data, int time) // whole screen won't be repainted, resulting in artefacts. data.mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS; - effects->prePaintScreen(data, time); + effects->prePaintScreen(data, presentTime); } -void MagicLampEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int time) +void MagicLampEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, std::chrono::milliseconds presentTime) { // Schedule window for transformation if the animation is still in // progress @@ -70,7 +74,7 @@ void MagicLampEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, w->enablePainting(EffectWindow::PAINT_DISABLED_BY_MINIMIZE); } - effects->prePaintWindow(w, data, time); + effects->prePaintWindow(w, data, presentTime); } void MagicLampEffect::paintWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data) @@ -78,7 +82,7 @@ void MagicLampEffect::paintWindow(EffectWindow* w, int mask, QRegion region, Win auto animationIt = m_animations.constFind(w); if (animationIt != m_animations.constEnd()) { // 0 = not minimized, 1 = fully minimized - const qreal progress = (*animationIt).value(); + const qreal progress = (*animationIt).timeLine.value(); QRect geo = w->geometry(); QRect icon = w->iconGeometry(); @@ -301,7 +305,7 @@ void MagicLampEffect::postPaintScreen() { auto animationIt = m_animations.begin(); while (animationIt != m_animations.end()) { - if ((*animationIt).done()) { + if ((*animationIt).timeLine.done()) { animationIt = m_animations.erase(animationIt); } else { ++animationIt; @@ -324,14 +328,14 @@ void MagicLampEffect::slotWindowMinimized(EffectWindow* w) if (effects->activeFullScreenEffect()) return; - TimeLine &timeLine = m_animations[w]; + MagicLampAnimation &animation = m_animations[w]; - if (timeLine.running()) { - timeLine.toggleDirection(); + if (animation.timeLine.running()) { + animation.timeLine.toggleDirection(); } else { - timeLine.setDirection(TimeLine::Forward); - timeLine.setDuration(m_duration); - timeLine.setEasingCurve(QEasingCurve::Linear); + animation.timeLine.setDirection(TimeLine::Forward); + animation.timeLine.setDuration(m_duration); + animation.timeLine.setEasingCurve(QEasingCurve::Linear); } effects->addRepaintFull(); @@ -342,14 +346,14 @@ void MagicLampEffect::slotWindowUnminimized(EffectWindow* w) if (effects->activeFullScreenEffect()) return; - TimeLine &timeLine = m_animations[w]; + MagicLampAnimation &animation = m_animations[w]; - if (timeLine.running()) { - timeLine.toggleDirection(); + if (animation.timeLine.running()) { + animation.timeLine.toggleDirection(); } else { - timeLine.setDirection(TimeLine::Backward); - timeLine.setDuration(m_duration); - timeLine.setEasingCurve(QEasingCurve::Linear); + animation.timeLine.setDirection(TimeLine::Backward); + animation.timeLine.setDuration(m_duration); + animation.timeLine.setEasingCurve(QEasingCurve::Linear); } effects->addRepaintFull(); diff --git a/effects/magiclamp/magiclamp.h b/effects/magiclamp/magiclamp.h index 408236b8b5..91ebdf962e 100644 --- a/effects/magiclamp/magiclamp.h +++ b/effects/magiclamp/magiclamp.h @@ -15,6 +15,12 @@ namespace KWin { +struct MagicLampAnimation +{ + TimeLine timeLine; + std::chrono::milliseconds lastPresentTime = std::chrono::milliseconds::zero(); +}; + class MagicLampEffect : public Effect { @@ -24,8 +30,8 @@ public: MagicLampEffect(); void reconfigure(ReconfigureFlags) override; - void prePaintScreen(ScreenPrePaintData& data, int time) override; - void prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int time) override; + void prePaintScreen(ScreenPrePaintData& data, std::chrono::milliseconds presentTime) override; + void prePaintWindow(EffectWindow* w, WindowPrePaintData& data, std::chrono::milliseconds presentTime) override; void paintWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data) override; void postPaintScreen() override; bool isActive() const override; @@ -43,7 +49,7 @@ public Q_SLOTS: private: std::chrono::milliseconds m_duration; - QHash m_animations; + QHash m_animations; enum IconPosition { Top, diff --git a/effects/magnifier/magnifier.cpp b/effects/magnifier/magnifier.cpp index 8c2176ef17..4aced41fb9 100644 --- a/effects/magnifier/magnifier.cpp +++ b/effects/magnifier/magnifier.cpp @@ -33,6 +33,7 @@ MagnifierEffect::MagnifierEffect() : zoom(1) , target_zoom(1) , polling(false) + , m_lastPresentTime(std::chrono::milliseconds::zero()) , m_texture(nullptr) , m_fbo(nullptr) #ifdef KWIN_HAVE_XRENDER_COMPOSITING @@ -104,8 +105,10 @@ void MagnifierEffect::reconfigure(ReconfigureFlags) toggle(); } -void MagnifierEffect::prePaintScreen(ScreenPrePaintData& data, int time) +void MagnifierEffect::prePaintScreen(ScreenPrePaintData& data, std::chrono::milliseconds presentTime) { + const int time = m_lastPresentTime.count() ? (presentTime - m_lastPresentTime).count() : 0; + if (zoom != target_zoom) { double diff = time / animationTime(500.0); if (target_zoom > zoom) @@ -122,7 +125,14 @@ void MagnifierEffect::prePaintScreen(ScreenPrePaintData& data, int time) } } } - effects->prePaintScreen(data, time); + + if (zoom != target_zoom) { + m_lastPresentTime = presentTime; + } else { + m_lastPresentTime = std::chrono::milliseconds::zero(); + } + + effects->prePaintScreen(data, presentTime); if (zoom != 1.0) data.paint |= magnifierArea().adjusted(-FRAME_WIDTH, -FRAME_WIDTH, FRAME_WIDTH, FRAME_WIDTH); } diff --git a/effects/magnifier/magnifier.h b/effects/magnifier/magnifier.h index 48b87fee41..28deb3499f 100644 --- a/effects/magnifier/magnifier.h +++ b/effects/magnifier/magnifier.h @@ -30,7 +30,7 @@ public: MagnifierEffect(); ~MagnifierEffect() override; void reconfigure(ReconfigureFlags) override; - void prePaintScreen(ScreenPrePaintData& data, int time) override; + void prePaintScreen(ScreenPrePaintData& data, std::chrono::milliseconds presentTime) override; void paintScreen(int mask, const QRegion ®ion, ScreenPaintData& data) override; void postPaintScreen() override; bool isActive() const override; @@ -56,6 +56,7 @@ private: double zoom; double target_zoom; bool polling; // Mouse polling + std::chrono::milliseconds m_lastPresentTime; QSize magnifier_size; GLTexture *m_texture; GLRenderTarget *m_fbo; diff --git a/effects/mouseclick/mouseclick.cpp b/effects/mouseclick/mouseclick.cpp index 01a335bdd3..f1d62b832b 100644 --- a/effects/mouseclick/mouseclick.cpp +++ b/effects/mouseclick/mouseclick.cpp @@ -74,8 +74,10 @@ void MouseClickEffect::reconfigure(ReconfigureFlags) m_font = MouseClickConfig::font(); } -void MouseClickEffect::prePaintScreen(ScreenPrePaintData& data, int time) +void MouseClickEffect::prePaintScreen(ScreenPrePaintData& data, std::chrono::milliseconds presentTime) { + const int time = m_lastPresentTime.count() ? (presentTime - m_lastPresentTime).count() : 0; + foreach (MouseEvent* click, m_clicks) { click->m_time += time; } @@ -95,7 +97,13 @@ void MouseClickEffect::prePaintScreen(ScreenPrePaintData& data, int time) delete first; } - effects->prePaintScreen(data, time); + if (isActive()) { + m_lastPresentTime = presentTime; + } else { + m_lastPresentTime = std::chrono::milliseconds::zero(); + } + + effects->prePaintScreen(data, presentTime); } void MouseClickEffect::paintScreen(int mask, const QRegion ®ion, ScreenPaintData& data) diff --git a/effects/mouseclick/mouseclick.h b/effects/mouseclick/mouseclick.h index ec9cd7af6e..b81a97d5af 100644 --- a/effects/mouseclick/mouseclick.h +++ b/effects/mouseclick/mouseclick.h @@ -92,7 +92,7 @@ public: MouseClickEffect(); ~MouseClickEffect() override; void reconfigure(ReconfigureFlags) override; - void prePaintScreen(ScreenPrePaintData& data, int time) override; + void prePaintScreen(ScreenPrePaintData& data, std::chrono::milliseconds presentTime) override; void paintScreen(int mask, const QRegion ®ion, ScreenPaintData& data) override; void postPaintScreen() override; bool isActive() const override; @@ -161,6 +161,7 @@ private: float m_ringMaxSize; bool m_showText; QFont m_font; + std::chrono::milliseconds m_lastPresentTime = std::chrono::milliseconds::zero(); QList m_clicks; MouseButton* m_buttons[BUTTON_COUNT]; diff --git a/effects/presentwindows/presentwindows.cpp b/effects/presentwindows/presentwindows.cpp index 15a4d132ca..99e3598e94 100644 --- a/effects/presentwindows/presentwindows.cpp +++ b/effects/presentwindows/presentwindows.cpp @@ -46,6 +46,7 @@ PresentWindowsEffect::PresentWindowsEffect() , m_managerWindow(nullptr) , m_needInitialSelection(false) , m_highlightedWindow(nullptr) + , m_lastPresentTime(std::chrono::milliseconds::zero()) , m_filterFrame(nullptr) , m_closeView(nullptr) , m_exposeAction(new QAction(this)) @@ -199,8 +200,17 @@ void PresentWindowsEffect::toggleActiveClass() //----------------------------------------------------------------------------- // Screen painting -void PresentWindowsEffect::prePaintScreen(ScreenPrePaintData &data, int time) +void PresentWindowsEffect::prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) { + // The animation code assumes that the time diff cannot be 0, let's work around it. + int time; + if (m_lastPresentTime.count()) { + time = std::max(1, int((presentTime - m_lastPresentTime).count())); + } else { + time = 1; + } + m_lastPresentTime = presentTime; + m_motionManager.calculate(time); // We need to mark the screen as having been transformed otherwise there will be no repainting @@ -212,7 +222,7 @@ void PresentWindowsEffect::prePaintScreen(ScreenPrePaintData &data, int time) else m_decalOpacity = qMax(0.0, m_decalOpacity - time / m_fadeDuration); - effects->prePaintScreen(data, time); + effects->prePaintScreen(data, presentTime); } void PresentWindowsEffect::paintScreen(int mask, const QRegion ®ion, ScreenPaintData &data) @@ -229,43 +239,58 @@ void PresentWindowsEffect::paintScreen(int mask, const QRegion ®ion, ScreenPa void PresentWindowsEffect::postPaintScreen() { - if (m_motionManager.areWindowsMoving()) + if (m_motionManager.areWindowsMoving()) { effects->addRepaintFull(); - else if (!m_activated && m_motionManager.managingWindows() && !(m_closeView && m_closeView->isVisible())) { - // We have finished moving them back, stop processing - m_motionManager.unmanageAll(); + } else { + m_lastPresentTime = std::chrono::milliseconds::zero(); - DataHash::iterator i = m_windowData.begin(); - while (i != m_windowData.end()) { - delete i.value().textFrame; - delete i.value().iconFrame; - ++i; - } - m_windowData.clear(); + if (!m_activated && m_motionManager.managingWindows() && !(m_closeView && m_closeView->isVisible())) { + // We have finished moving them back, stop processing + m_motionManager.unmanageAll(); - foreach (EffectWindow * w, effects->stackingOrder()) { - w->setData(WindowForceBlurRole, QVariant()); - w->setData(WindowForceBackgroundContrastRole, QVariant()); + DataHash::iterator i = m_windowData.begin(); + while (i != m_windowData.end()) { + delete i.value().textFrame; + delete i.value().iconFrame; + ++i; + } + m_windowData.clear(); + + foreach (EffectWindow * w, effects->stackingOrder()) { + w->setData(WindowForceBlurRole, QVariant()); + w->setData(WindowForceBackgroundContrastRole, QVariant()); + } + effects->setActiveFullScreenEffect(nullptr); + effects->addRepaintFull(); + } else if (m_activated && m_needInitialSelection) { + m_needInitialSelection = false; + QMouseEvent me(QEvent::MouseMove, cursorPos(), Qt::NoButton, Qt::NoButton, Qt::NoModifier); + windowInputMouseEvent(&me); } - effects->setActiveFullScreenEffect(nullptr); - effects->addRepaintFull(); - } else if (m_activated && m_needInitialSelection) { - m_needInitialSelection = false; - QMouseEvent me(QEvent::MouseMove, cursorPos(), Qt::NoButton, Qt::NoButton, Qt::NoModifier); - windowInputMouseEvent(&me); } // Update windows that are changing brightness or opacity - DataHash::const_iterator i; - for (i = m_windowData.constBegin(); i != m_windowData.constEnd(); ++i) { - if (i.value().opacity > 0.0 && i.value().opacity < 1.0) + for (auto i = m_windowData.begin(); i != m_windowData.end(); ++i) { + bool resetLastPresentTime = true; + + if (i.value().opacity > 0.0 && i.value().opacity < 1.0) { i.key()->addRepaintFull(); - if (i.key()->isDesktop() && !m_motionManager.isManaging(i.key())) { - if (i.value().highlight != 0.3) - i.key()->addRepaintFull(); + resetLastPresentTime = false; } - else if (i.value().highlight > 0.0 && i.value().highlight < 1.0) + if (i.key()->isDesktop() && !m_motionManager.isManaging(i.key())) { + if (i.value().highlight != 0.3) { + i.key()->addRepaintFull(); + resetLastPresentTime = false; + } + } + else if (i.value().highlight > 0.0 && i.value().highlight < 1.0) { i.key()->addRepaintFull(); + resetLastPresentTime = false; + } + + if (resetLastPresentTime) { + i->lastPresentTime = std::chrono::milliseconds::zero(); + } } effects->postPaintScreen(); @@ -274,19 +299,28 @@ void PresentWindowsEffect::postPaintScreen() //----------------------------------------------------------------------------- // Window painting -void PresentWindowsEffect::prePaintWindow(EffectWindow *w, WindowPrePaintData &data, int time) +void PresentWindowsEffect::prePaintWindow(EffectWindow *w, WindowPrePaintData &data, std::chrono::milliseconds presentTime) { // TODO: We should also check to see if any windows are fading just in case fading takes longer // than moving the windows when the effect is deactivated. if (m_activated || m_motionManager.areWindowsMoving() || m_closeView) { DataHash::iterator winData = m_windowData.find(w); if (winData == m_windowData.end()) { - effects->prePaintWindow(w, data, time); + effects->prePaintWindow(w, data, presentTime); return; } w->enablePainting(EffectWindow::PAINT_DISABLED_BY_MINIMIZE); // Display always w->enablePainting(EffectWindow::PAINT_DISABLED_BY_DESKTOP); + // The animation code assumes that the time diff cannot be 0, let's work around it. + int time; + if (winData->lastPresentTime.count()) { + time = std::max(1, int((presentTime - winData->lastPresentTime).count())); + } else { + time = 1; + } + winData->lastPresentTime = presentTime; + // Calculate window's opacity // TODO: Minimized windows or windows not on the current desktop are only 75% visible? if (winData->visible) { @@ -333,7 +367,7 @@ void PresentWindowsEffect::prePaintWindow(EffectWindow *w, WindowPrePaintData &d if (isInMotion) data.setTransformed(); // We will be moving this window } - effects->prePaintWindow(w, data, time); + effects->prePaintWindow(w, data, presentTime); } void PresentWindowsEffect::paintWindow(EffectWindow *w, int mask, QRegion region, WindowPaintData &data) diff --git a/effects/presentwindows/presentwindows.h b/effects/presentwindows/presentwindows.h index bd54144c87..8232a1aa94 100644 --- a/effects/presentwindows/presentwindows.h +++ b/effects/presentwindows/presentwindows.h @@ -64,6 +64,7 @@ class PresentWindowsEffect private: // Structures struct WindowData { + std::chrono::milliseconds lastPresentTime = std::chrono::milliseconds::zero(); bool visible; bool deleted; bool referenced; @@ -86,12 +87,12 @@ public: void* proxy() override; // Screen painting - void prePaintScreen(ScreenPrePaintData &data, int time) override; + void prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) override; void paintScreen(int mask, const QRegion ®ion, ScreenPaintData &data) override; void postPaintScreen() override; // Window painting - void prePaintWindow(EffectWindow *w, WindowPrePaintData &data, int time) override; + void prePaintWindow(EffectWindow *w, WindowPrePaintData &data, std::chrono::milliseconds presentTime) override; void paintWindow(EffectWindow *w, int mask, QRegion region, WindowPaintData &data) override; // User interaction @@ -279,6 +280,9 @@ private: DataHash m_windowData; EffectWindow *m_highlightedWindow; + // Timing + std::chrono::milliseconds m_lastPresentTime; + // Grid layout info QList m_gridSizes; diff --git a/effects/resize/resize.cpp b/effects/resize/resize.cpp index b3e32d2080..5063a5b133 100644 --- a/effects/resize/resize.cpp +++ b/effects/resize/resize.cpp @@ -40,19 +40,19 @@ ResizeEffect::~ResizeEffect() { } -void ResizeEffect::prePaintScreen(ScreenPrePaintData& data, int time) +void ResizeEffect::prePaintScreen(ScreenPrePaintData& data, std::chrono::milliseconds presentTime) { if (m_active) { data.mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS; } - AnimationEffect::prePaintScreen(data, time); + AnimationEffect::prePaintScreen(data, presentTime); } -void ResizeEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int time) +void ResizeEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, std::chrono::milliseconds presentTime) { if (m_active && w == m_resizeWindow) data.mask |= PAINT_WINDOW_TRANSFORMED; - AnimationEffect::prePaintWindow(w, data, time); + AnimationEffect::prePaintWindow(w, data, presentTime); } void ResizeEffect::paintWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data) diff --git a/effects/resize/resize.h b/effects/resize/resize.h index a0150ee964..93f561a1dc 100644 --- a/effects/resize/resize.h +++ b/effects/resize/resize.h @@ -28,8 +28,8 @@ public: return ef == Effect::Resize; } inline bool isActive() const override { return m_active || AnimationEffect::isActive(); } - void prePaintScreen(ScreenPrePaintData& data, int time) override; - void prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int time) override; + void prePaintScreen(ScreenPrePaintData& data, std::chrono::milliseconds presentTime) override; + void prePaintWindow(EffectWindow* w, WindowPrePaintData& data, std::chrono::milliseconds presentTime) override; void paintWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data) override; void reconfigure(ReconfigureFlags) override; diff --git a/effects/screenedge/screenedgeeffect.cpp b/effects/screenedge/screenedgeeffect.cpp index 4058fa9d47..07662b7b16 100644 --- a/effects/screenedge/screenedgeeffect.cpp +++ b/effects/screenedge/screenedgeeffect.cpp @@ -65,9 +65,9 @@ void ScreenEdgeEffect::cleanup() m_borders.clear(); } -void ScreenEdgeEffect::prePaintScreen(ScreenPrePaintData &data, int time) +void ScreenEdgeEffect::prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) { - effects->prePaintScreen(data, time); + effects->prePaintScreen(data, presentTime); for (QHash::iterator it = m_borders.begin(); it != m_borders.end(); ++it) { diff --git a/effects/screenedge/screenedgeeffect.h b/effects/screenedge/screenedgeeffect.h index 14a4d5755f..56544a4f7e 100644 --- a/effects/screenedge/screenedgeeffect.h +++ b/effects/screenedge/screenedgeeffect.h @@ -25,7 +25,7 @@ class ScreenEdgeEffect : public Effect public: ScreenEdgeEffect(); ~ScreenEdgeEffect() override; - void prePaintScreen(ScreenPrePaintData &data, int time) override; + void prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) override; void paintScreen(int mask, const QRegion ®ion, ScreenPaintData &data) override; bool isActive() const override; diff --git a/effects/sheet/sheet.cpp b/effects/sheet/sheet.cpp index d2cb7ad2a1..acff5d38c9 100644 --- a/effects/sheet/sheet.cpp +++ b/effects/sheet/sheet.cpp @@ -44,29 +44,33 @@ void SheetEffect::reconfigure(ReconfigureFlags flags) m_duration = std::chrono::milliseconds(static_cast(d)); } -void SheetEffect::prePaintScreen(ScreenPrePaintData &data, int time) +void SheetEffect::prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) { - const std::chrono::milliseconds delta(time); - auto animationIt = m_animations.begin(); while (animationIt != m_animations.end()) { + std::chrono::milliseconds delta = std::chrono::milliseconds::zero(); + if (animationIt->lastPresentTime.count()) { + delta = presentTime - animationIt->lastPresentTime; + } + animationIt->lastPresentTime = presentTime; + (*animationIt).timeLine.update(delta); ++animationIt; } data.mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS; - effects->prePaintScreen(data, time); + effects->prePaintScreen(data, presentTime); } -void SheetEffect::prePaintWindow(EffectWindow *w, WindowPrePaintData &data, int time) +void SheetEffect::prePaintWindow(EffectWindow *w, WindowPrePaintData &data, std::chrono::milliseconds presentTime) { if (m_animations.contains(w)) { data.setTransformed(); w->enablePainting(EffectWindow::PAINT_DISABLED_BY_DELETE); } - effects->prePaintWindow(w, data, time); + effects->prePaintWindow(w, data, presentTime); } void SheetEffect::paintWindow(EffectWindow *w, int mask, QRegion region, WindowPaintData &data) diff --git a/effects/sheet/sheet.h b/effects/sheet/sheet.h index 3a23657725..3665552fd8 100644 --- a/effects/sheet/sheet.h +++ b/effects/sheet/sheet.h @@ -28,8 +28,8 @@ public: void reconfigure(ReconfigureFlags flags) override; - void prePaintScreen(ScreenPrePaintData &data, int time) override; - void prePaintWindow(EffectWindow *w, WindowPrePaintData &data, int time) override; + void prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) override; + void prePaintWindow(EffectWindow *w, WindowPrePaintData &data, std::chrono::milliseconds presentTime) override; void paintWindow(EffectWindow *w, int mask, QRegion region, WindowPaintData &data) override; void postPaintWindow(EffectWindow *w) override; @@ -54,6 +54,7 @@ private: struct Animation { TimeLine timeLine; int parentY; + std::chrono::milliseconds lastPresentTime = std::chrono::milliseconds::zero(); }; QHash m_animations; diff --git a/effects/showfps/showfps.cpp b/effects/showfps/showfps.cpp index 05510350e9..9f1df61382 100644 --- a/effects/showfps/showfps.cpp +++ b/effects/showfps/showfps.cpp @@ -110,12 +110,12 @@ void ShowFpsEffect::reconfigure(ReconfigureFlags) } } -void ShowFpsEffect::prePaintScreen(ScreenPrePaintData& data, int time) +void ShowFpsEffect::prePaintScreen(ScreenPrePaintData& data, std::chrono::milliseconds presentTime) { frames[ frames_pos ] = QDateTime::currentMSecsSinceEpoch(); if (++frames_pos == MAX_FPS) frames_pos = 0; - effects->prePaintScreen(data, time); + effects->prePaintScreen(data, presentTime); data.paint += fps_rect; paint_size[ paints_pos ] = 0; diff --git a/effects/showfps/showfps.h b/effects/showfps/showfps.h index e82ec84447..ed7c19b3b9 100644 --- a/effects/showfps/showfps.h +++ b/effects/showfps/showfps.h @@ -34,7 +34,7 @@ class ShowFpsEffect public: ShowFpsEffect(); void reconfigure(ReconfigureFlags) override; - void prePaintScreen(ScreenPrePaintData& data, int time) override; + void prePaintScreen(ScreenPrePaintData& data, std::chrono::milliseconds presentTime) override; void paintScreen(int mask, const QRegion ®ion, ScreenPaintData& data) override; void paintWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data) override; void postPaintScreen() override; diff --git a/effects/slide/slide.cpp b/effects/slide/slide.cpp index a73836eaac..c944f4c3fe 100644 --- a/effects/slide/slide.cpp +++ b/effects/slide/slide.cpp @@ -62,14 +62,20 @@ void SlideEffect::reconfigure(ReconfigureFlags) m_slideBackground = SlideConfig::slideBackground(); } -void SlideEffect::prePaintScreen(ScreenPrePaintData &data, int time) +void SlideEffect::prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) { - m_timeLine.update(std::chrono::milliseconds(time)); + std::chrono::milliseconds delta = std::chrono::milliseconds::zero(); + if (m_lastPresentTime.count()) { + delta = presentTime - m_lastPresentTime; + } + m_lastPresentTime = presentTime; + + m_timeLine.update(delta); data.mask |= PAINT_SCREEN_TRANSFORMED | PAINT_SCREEN_BACKGROUND_FIRST; - effects->prePaintScreen(data, time); + effects->prePaintScreen(data, presentTime); } /** @@ -249,7 +255,7 @@ bool SlideEffect::isPainted(const EffectWindow *w) const return false; } -void SlideEffect::prePaintWindow(EffectWindow *w, WindowPrePaintData &data, int time) +void SlideEffect::prePaintWindow(EffectWindow *w, WindowPrePaintData &data, std::chrono::milliseconds presentTime) { const bool painted = isPainted(w); if (painted) { @@ -260,7 +266,7 @@ void SlideEffect::prePaintWindow(EffectWindow *w, WindowPrePaintData &data, int if (painted && isTranslated(w)) { data.setTransformed(); } - effects->prePaintWindow(w, data, time); + effects->prePaintWindow(w, data, presentTime); } void SlideEffect::paintWindow(EffectWindow *w, int mask, QRegion region, WindowPaintData &data) @@ -392,6 +398,7 @@ void SlideEffect::stop() m_paintCtx.fullscreenWindows.clear(); m_movingWindow = nullptr; m_active = false; + m_lastPresentTime = std::chrono::milliseconds::zero(); effects->setActiveFullScreenEffect(nullptr); } diff --git a/effects/slide/slide.h b/effects/slide/slide.h index fc64803ef0..56ac539a68 100644 --- a/effects/slide/slide.h +++ b/effects/slide/slide.h @@ -33,11 +33,11 @@ public: void reconfigure(ReconfigureFlags) override; - void prePaintScreen(ScreenPrePaintData &data, int time) override; + void prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) override; void paintScreen(int mask, const QRegion ®ion, ScreenPaintData &data) override; void postPaintScreen() override; - void prePaintWindow(EffectWindow *w, WindowPrePaintData &data, int time) override; + void prePaintWindow(EffectWindow *w, WindowPrePaintData &data, std::chrono::milliseconds presentTime) override; void paintWindow(EffectWindow *w, int mask, QRegion region, WindowPaintData &data) override; bool isActive() const override { @@ -88,6 +88,7 @@ private: QPoint m_startPos; QPoint m_diff; EffectWindow *m_movingWindow = nullptr; + std::chrono::milliseconds m_lastPresentTime = std::chrono::milliseconds::zero(); struct { int desktop; diff --git a/effects/slideback/slideback.cpp b/effects/slideback/slideback.cpp index e6a891422d..4faabba262 100644 --- a/effects/slideback/slideback.cpp +++ b/effects/slideback/slideback.cpp @@ -126,8 +126,14 @@ QRect SlideBackEffect::getSlideDestination(const QRect &windowUnderGeometry, con return slideRect; } -void SlideBackEffect::prePaintScreen(ScreenPrePaintData &data, int time) +void SlideBackEffect::prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) { + int time = 0; + if (m_lastPresentTime.count()) { + time = (presentTime - m_lastPresentTime).count(); + } + m_lastPresentTime = presentTime; + if (motionManager.managingWindows()) { motionManager.calculate(time); data.mask |= Effect::PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS; @@ -137,7 +143,7 @@ void SlideBackEffect::prePaintScreen(ScreenPrePaintData &data, int time) w->setData(WindowForceBlurRole, QVariant(true)); } - effects->prePaintScreen(data, time); + effects->prePaintScreen(data, presentTime); } void SlideBackEffect::postPaintScreen() @@ -153,13 +159,13 @@ void SlideBackEffect::postPaintScreen() effects->postPaintScreen(); } -void SlideBackEffect::prePaintWindow(EffectWindow *w, WindowPrePaintData &data, int time) +void SlideBackEffect::prePaintWindow(EffectWindow *w, WindowPrePaintData &data, std::chrono::milliseconds presentTime) { if (motionManager.isManaging(w)) { data.setTransformed(); } - effects->prePaintWindow(w, data, time); + effects->prePaintWindow(w, data, presentTime); } void SlideBackEffect::paintWindow(EffectWindow *w, int mask, QRegion region, WindowPaintData &data) @@ -242,6 +248,9 @@ void SlideBackEffect::postPaintWindow(EffectWindow* w) } } } + if (!isActive()) { + m_lastPresentTime = std::chrono::milliseconds::zero(); + } effects->postPaintWindow(w); } diff --git a/effects/slideback/slideback.h b/effects/slideback/slideback.h index c10b7e52ba..cf49a345eb 100644 --- a/effects/slideback/slideback.h +++ b/effects/slideback/slideback.h @@ -23,11 +23,11 @@ class SlideBackEffect public: SlideBackEffect(); - void prePaintWindow(EffectWindow *w, WindowPrePaintData &data, int time) override; + void prePaintWindow(EffectWindow *w, WindowPrePaintData &data, std::chrono::milliseconds presentTime) override; void paintWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data) override; void postPaintWindow(EffectWindow* w) override; - void prePaintScreen(ScreenPrePaintData &data, int time) override; + void prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) override; void postPaintScreen() override; bool isActive() const override; @@ -54,6 +54,7 @@ private: QHash destinationList; int m_tabboxActive; QList clippedRegions; + std::chrono::milliseconds m_lastPresentTime = std::chrono::milliseconds::zero(); QRect getSlideDestination(const QRect &windowUnderGeometry, const QRect &windowOverGeometry); bool isWindowUsable(EffectWindow *w); diff --git a/effects/slidingpopups/slidingpopups.cpp b/effects/slidingpopups/slidingpopups.cpp index afb7ceceb1..837228d85c 100644 --- a/effects/slidingpopups/slidingpopups.cpp +++ b/effects/slidingpopups/slidingpopups.cpp @@ -91,19 +91,25 @@ void SlidingPopupsEffect::reconfigure(ReconfigureFlags flags) } } -void SlidingPopupsEffect::prePaintWindow(EffectWindow *w, WindowPrePaintData &data, int time) +void SlidingPopupsEffect::prePaintWindow(EffectWindow *w, WindowPrePaintData &data, std::chrono::milliseconds presentTime) { auto animationIt = m_animations.find(w); if (animationIt == m_animations.end()) { - effects->prePaintWindow(w, data, time); + effects->prePaintWindow(w, data, presentTime); return; } - (*animationIt).timeLine.update(std::chrono::milliseconds(time)); + std::chrono::milliseconds delta = std::chrono::milliseconds::zero(); + if (animationIt->lastPresentTime.count()) { + delta = presentTime - animationIt->lastPresentTime; + } + animationIt->lastPresentTime = presentTime; + + (*animationIt).timeLine.update(delta); data.setTransformed(); w->enablePainting(EffectWindow::PAINT_DISABLED | EffectWindow::PAINT_DISABLED_BY_DELETE); - effects->prePaintWindow(w, data, time); + effects->prePaintWindow(w, data, presentTime); } void SlidingPopupsEffect::paintWindow(EffectWindow *w, int mask, QRegion region, WindowPaintData &data) diff --git a/effects/slidingpopups/slidingpopups.h b/effects/slidingpopups/slidingpopups.h index c6c2c3e189..4480371d6d 100644 --- a/effects/slidingpopups/slidingpopups.h +++ b/effects/slidingpopups/slidingpopups.h @@ -27,7 +27,7 @@ public: SlidingPopupsEffect(); ~SlidingPopupsEffect() override; - void prePaintWindow(EffectWindow *w, WindowPrePaintData &data, int time) override; + void prePaintWindow(EffectWindow *w, WindowPrePaintData &data, std::chrono::milliseconds presentTime) override; void paintWindow(EffectWindow *w, int mask, QRegion region, WindowPaintData &data) override; void postPaintWindow(EffectWindow *w) override; void reconfigure(ReconfigureFlags flags) override; @@ -72,6 +72,7 @@ private: struct Animation { AnimationKind kind; TimeLine timeLine; + std::chrono::milliseconds lastPresentTime = std::chrono::milliseconds::zero(); }; QHash m_animations; diff --git a/effects/snaphelper/snaphelper.cpp b/effects/snaphelper/snaphelper.cpp index 0fd783c083..e6e1e82dd9 100644 --- a/effects/snaphelper/snaphelper.cpp +++ b/effects/snaphelper/snaphelper.cpp @@ -85,13 +85,19 @@ void SnapHelperEffect::reconfigure(ReconfigureFlags flags) std::chrono::milliseconds(static_cast(animationTime(250)))); } -void SnapHelperEffect::prePaintScreen(ScreenPrePaintData &data, int time) +void SnapHelperEffect::prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) { + std::chrono::milliseconds delta = std::chrono::milliseconds::zero(); + if (m_animation.lastPresentTime.count()) { + delta = (presentTime - m_animation.lastPresentTime); + } + m_animation.lastPresentTime = presentTime; + if (m_animation.active) { - m_animation.timeLine.update(std::chrono::milliseconds(time)); + m_animation.timeLine.update(delta); } - effects->prePaintScreen(data, time); + effects->prePaintScreen(data, presentTime); } void SnapHelperEffect::paintScreen(int mask, const QRegion ®ion, ScreenPaintData &data) @@ -244,6 +250,7 @@ void SnapHelperEffect::postPaintScreen() if (m_animation.timeLine.done()) { m_animation.active = false; + m_animation.lastPresentTime = std::chrono::milliseconds::zero(); } effects->postPaintScreen(); diff --git a/effects/snaphelper/snaphelper.h b/effects/snaphelper/snaphelper.h index 4e6c09bd9b..e965c049d8 100644 --- a/effects/snaphelper/snaphelper.h +++ b/effects/snaphelper/snaphelper.h @@ -26,7 +26,7 @@ public: void reconfigure(ReconfigureFlags flags) override; - void prePaintScreen(ScreenPrePaintData &data, int time) override; + void prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) override; void paintScreen(int mask, const QRegion ®ion, ScreenPaintData &data) override; void postPaintScreen() override; @@ -45,6 +45,7 @@ private: struct Animation { bool active = false; TimeLine timeLine; + std::chrono::milliseconds lastPresentTime = std::chrono::milliseconds::zero(); }; Animation m_animation; diff --git a/effects/startupfeedback/startupfeedback.cpp b/effects/startupfeedback/startupfeedback.cpp index e4b156a07f..e65beba2e3 100644 --- a/effects/startupfeedback/startupfeedback.cpp +++ b/effects/startupfeedback/startupfeedback.cpp @@ -68,6 +68,7 @@ StartupFeedbackEffect::StartupFeedbackEffect() , m_active(false) , m_frame(0) , m_progress(0) + , m_lastPresentTime(std::chrono::milliseconds::zero()) , m_type(BouncingFeedback) , m_cursorSize(24) , m_configWatcher(KConfigWatcher::create(KSharedConfig::openConfig("klaunchrc", KConfig::NoGlobals))) @@ -142,8 +143,14 @@ void StartupFeedbackEffect::reconfigure(Effect::ReconfigureFlags flags) } } -void StartupFeedbackEffect::prePaintScreen(ScreenPrePaintData& data, int time) +void StartupFeedbackEffect::prePaintScreen(ScreenPrePaintData& data, std::chrono::milliseconds presentTime) { + int time = 0; + if (m_lastPresentTime.count()) { + time = (presentTime - m_lastPresentTime).count(); + } + m_lastPresentTime = presentTime; + if (m_active) { // need the unclipped version switch(m_type) { @@ -161,7 +168,7 @@ void StartupFeedbackEffect::prePaintScreen(ScreenPrePaintData& data, int time) break; // nothing } } - effects->prePaintScreen(data, time); + effects->prePaintScreen(data, presentTime); } void StartupFeedbackEffect::paintScreen(int mask, const QRegion ®ion, ScreenPaintData& data) @@ -289,6 +296,7 @@ void StartupFeedbackEffect::stop() if (m_active) effects->stopMousePolling(); m_active = false; + m_lastPresentTime = std::chrono::milliseconds::zero(); effects->makeOpenGLContextCurrent(); switch(m_type) { case BouncingFeedback: @@ -324,6 +332,7 @@ void StartupFeedbackEffect::prepareTextures(const QPixmap& pix) default: // for safety m_active = false; + m_lastPresentTime = std::chrono::milliseconds::zero(); break; } } diff --git a/effects/startupfeedback/startupfeedback.h b/effects/startupfeedback/startupfeedback.h index 553fc53c68..aa36066031 100644 --- a/effects/startupfeedback/startupfeedback.h +++ b/effects/startupfeedback/startupfeedback.h @@ -29,7 +29,7 @@ public: ~StartupFeedbackEffect() override; void reconfigure(ReconfigureFlags flags) override; - void prePaintScreen(ScreenPrePaintData& data, int time) override; + void prePaintScreen(ScreenPrePaintData& data, std::chrono::milliseconds presentTime) override; void paintScreen(int mask, const QRegion ®ion, ScreenPaintData& data) override; void postPaintScreen() override; bool isActive() const override; @@ -71,6 +71,7 @@ private: bool m_active; int m_frame; int m_progress; + std::chrono::milliseconds m_lastPresentTime; QScopedPointer m_bouncingTextures[5]; QScopedPointer m_texture; // for passive and blinking FeedbackType m_type; diff --git a/effects/touchpoints/touchpoints.cpp b/effects/touchpoints/touchpoints.cpp index 9af04c9648..1673c2e192 100644 --- a/effects/touchpoints/touchpoints.cpp +++ b/effects/touchpoints/touchpoints.cpp @@ -101,8 +101,13 @@ bool TouchPointsEffect::touchUp(qint32 id, quint32 time) return false; } -void TouchPointsEffect::prePaintScreen(ScreenPrePaintData& data, int time) +void TouchPointsEffect::prePaintScreen(ScreenPrePaintData& data, std::chrono::milliseconds presentTime) { + int time = 0; + if (m_lastPresentTime.count()) { + time = (presentTime - m_lastPresentTime).count(); + } + auto it = m_points.begin(); while (it != m_points.end()) { it->time += time; @@ -113,7 +118,13 @@ void TouchPointsEffect::prePaintScreen(ScreenPrePaintData& data, int time) } } - effects->prePaintScreen(data, time); + if (m_points.isEmpty()) { + m_lastPresentTime = std::chrono::milliseconds::zero(); + } else { + m_lastPresentTime = presentTime; + } + + effects->prePaintScreen(data, presentTime); } void TouchPointsEffect::paintScreen(int mask, const QRegion ®ion, ScreenPaintData& data) diff --git a/effects/touchpoints/touchpoints.h b/effects/touchpoints/touchpoints.h index 2ff4626ea0..13117c6c99 100644 --- a/effects/touchpoints/touchpoints.h +++ b/effects/touchpoints/touchpoints.h @@ -27,7 +27,7 @@ class TouchPointsEffect public: TouchPointsEffect(); ~TouchPointsEffect() override; - void prePaintScreen(ScreenPrePaintData& data, int time) override; + void prePaintScreen(ScreenPrePaintData& data, std::chrono::milliseconds presentTime) override; void paintScreen(int mask, const QRegion ®ion, ScreenPaintData& data) override; void postPaintScreen() override; bool isActive() const override; @@ -80,6 +80,7 @@ private: QVector m_points; QHash m_latestPositions; QHash m_colors; + std::chrono::milliseconds m_lastPresentTime = std::chrono::milliseconds::zero(); }; diff --git a/effects/trackmouse/trackmouse.cpp b/effects/trackmouse/trackmouse.cpp index ea26120ec5..496528afc4 100644 --- a/effects/trackmouse/trackmouse.cpp +++ b/effects/trackmouse/trackmouse.cpp @@ -93,7 +93,7 @@ void TrackMouseEffect::reconfigure(ReconfigureFlags) } } -void TrackMouseEffect::prePaintScreen(ScreenPrePaintData& data, int time) +void TrackMouseEffect::prePaintScreen(ScreenPrePaintData& data, std::chrono::milliseconds presentTime) { QTime t = QTime::currentTime(); m_angle = ((t.second() % 4) * m_angleBase) + (t.msec() / 1000.0 * m_angleBase); @@ -101,7 +101,7 @@ void TrackMouseEffect::prePaintScreen(ScreenPrePaintData& data, int time) m_lastRect[1].moveCenter(cursorPos()); data.paint |= m_lastRect[0].adjusted(-1,-1,1,1); - effects->prePaintScreen(data, time); + effects->prePaintScreen(data, presentTime); } void TrackMouseEffect::paintScreen(int mask, const QRegion ®ion, ScreenPaintData& data) diff --git a/effects/trackmouse/trackmouse.h b/effects/trackmouse/trackmouse.h index d35b087666..386635a125 100644 --- a/effects/trackmouse/trackmouse.h +++ b/effects/trackmouse/trackmouse.h @@ -29,7 +29,7 @@ class TrackMouseEffect public: TrackMouseEffect(); ~TrackMouseEffect() override; - void prePaintScreen(ScreenPrePaintData& data, int time) override; + void prePaintScreen(ScreenPrePaintData& data, std::chrono::milliseconds presentTime) override; void paintScreen(int mask, const QRegion ®ion, ScreenPaintData& data) override; void postPaintScreen() override; void reconfigure(ReconfigureFlags) override; diff --git a/effects/wobblywindows/wobblywindows.cpp b/effects/wobblywindows/wobblywindows.cpp index 3113ed095f..2ece00547c 100644 --- a/effects/wobblywindows/wobblywindows.cpp +++ b/effects/wobblywindows/wobblywindows.cpp @@ -228,7 +228,7 @@ void WobblyWindowsEffect::setDrag(qreal drag) m_drag = drag; } -void WobblyWindowsEffect::prePaintScreen(ScreenPrePaintData& data, int time) +void WobblyWindowsEffect::prePaintScreen(ScreenPrePaintData& data, std::chrono::milliseconds presentTime) { // We need to mark the screen windows as transformed. Otherwise the whole // screen won't be repainted, resulting in artefacts. @@ -237,16 +237,22 @@ void WobblyWindowsEffect::prePaintScreen(ScreenPrePaintData& data, int time) m_updateRegion = QRegion(); } - effects->prePaintScreen(data, time); + effects->prePaintScreen(data, presentTime); } const qreal maxTime = 10.0; -void WobblyWindowsEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int time) +void WobblyWindowsEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, std::chrono::milliseconds presentTime) { - if (windows.contains(w)) { + auto infoIt = windows.find(w); + if (infoIt != windows.end()) { data.setTransformed(); data.quads = data.quads.makeRegularGrid(m_xTesselation, m_yTesselation); bool stop = false; - qreal updateTime = time; + + qreal updateTime = 0; + if (infoIt->lastPresentTime.count()) { + updateTime = (presentTime - infoIt->lastPresentTime).count(); + } + infoIt->lastPresentTime = presentTime; // We have to reset the clip region in order to render clients below // opaque wobbly windows. @@ -264,7 +270,7 @@ void WobblyWindowsEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& da } } - effects->prePaintWindow(w, data, time); + effects->prePaintWindow(w, data, presentTime); } void WobblyWindowsEffect::paintWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data) @@ -464,6 +470,7 @@ void WobblyWindowsEffect::initWobblyInfo(WindowWobblyInfos& wwi, QRect geometry) wwi.bezierSurface = new Pair[wwi.bezierCount]; wwi.status = Moving; + wwi.lastPresentTime = std::chrono::milliseconds::zero(); qreal x = geometry.x(), y = geometry.y(); qreal width = geometry.width(), height = geometry.height(); diff --git a/effects/wobblywindows/wobblywindows.h b/effects/wobblywindows/wobblywindows.h index c4848e3f98..9ebcdfa38f 100644 --- a/effects/wobblywindows/wobblywindows.h +++ b/effects/wobblywindows/wobblywindows.h @@ -43,8 +43,8 @@ public: ~WobblyWindowsEffect() override; void reconfigure(ReconfigureFlags) override; - void prePaintScreen(ScreenPrePaintData& data, int time) override; - void prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int time) override; + void prePaintScreen(ScreenPrePaintData& data, std::chrono::milliseconds presentTime) override; + void prePaintWindow(EffectWindow* w, WindowPrePaintData& data, std::chrono::milliseconds presentTime) override; void paintWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data) override; void postPaintScreen() override; bool isActive() const override; @@ -151,6 +151,8 @@ private: // for resizing. Only sides that have moved will wobble bool can_wobble_top, can_wobble_left, can_wobble_right, can_wobble_bottom; QRect resize_original_rect; + + std::chrono::milliseconds lastPresentTime; }; QHash< const EffectWindow*, WindowWobblyInfos > windows; diff --git a/effects/zoom/zoom.cpp b/effects/zoom/zoom.cpp index 7ef01327a8..3a8238cb75 100644 --- a/effects/zoom/zoom.cpp +++ b/effects/zoom/zoom.cpp @@ -49,6 +49,7 @@ ZoomEffect::ZoomEffect() , xMove(0) , yMove(0) , moveFactor(20.0) + , lastPresentTime(std::chrono::milliseconds::zero()) { initConfig(); QAction* a = nullptr; @@ -249,9 +250,14 @@ void ZoomEffect::reconfigure(ReconfigureFlags) } } -void ZoomEffect::prePaintScreen(ScreenPrePaintData& data, int time) +void ZoomEffect::prePaintScreen(ScreenPrePaintData& data, std::chrono::milliseconds presentTime) { if (zoom != target_zoom) { + int time = 0; + if (lastPresentTime.count()) + time = (presentTime - lastPresentTime).count(); + lastPresentTime = presentTime; + const float zoomDist = qAbs(target_zoom - source_zoom); if (target_zoom > zoom) zoom = qMin(zoom + ((zoomDist * time) / animationTime(150*zoomFactor)), target_zoom); @@ -266,7 +272,7 @@ void ZoomEffect::prePaintScreen(ScreenPrePaintData& data, int time) data.mask |= PAINT_SCREEN_TRANSFORMED; } - effects->prePaintScreen(data, time); + effects->prePaintScreen(data, presentTime); } void ZoomEffect::paintScreen(int mask, const QRegion ®ion, ScreenPaintData& data) @@ -389,6 +395,8 @@ void ZoomEffect::postPaintScreen() { if (zoom != target_zoom) effects->addRepaintFull(); + else + lastPresentTime = std::chrono::milliseconds::zero(); effects->postPaintScreen(); } diff --git a/effects/zoom/zoom.h b/effects/zoom/zoom.h index da754a94f7..6e4acc654a 100644 --- a/effects/zoom/zoom.h +++ b/effects/zoom/zoom.h @@ -43,7 +43,7 @@ public: ZoomEffect(); ~ZoomEffect() override; void reconfigure(ReconfigureFlags flags) override; - void prePaintScreen(ScreenPrePaintData& data, int time) override; + void prePaintScreen(ScreenPrePaintData& data, std::chrono::milliseconds presentTime) override; void paintScreen(int mask, const QRegion ®ion, ScreenPaintData& data) override; void postPaintScreen() override; bool isActive() const override; @@ -119,6 +119,7 @@ private: QTimeLine timeline; int xMove, yMove; double moveFactor; + std::chrono::milliseconds lastPresentTime; }; } // namespace diff --git a/libkwineffects/anidata.cpp b/libkwineffects/anidata.cpp index d2ee9d85b1..0b006ce591 100644 --- a/libkwineffects/anidata.cpp +++ b/libkwineffects/anidata.cpp @@ -64,6 +64,7 @@ AniData::AniData() , startTime(0) , waitAtSource(false) , keepAlive(true) + , lastPresentTime(std::chrono::milliseconds::zero()) { } @@ -80,6 +81,7 @@ AniData::AniData(AnimationEffect::Attribute a, int meta_, const FPx2 &to_, , waitAtSource(waitAtSource_) , keepAlive(keepAlive) , previousWindowPixmapLock(std::move(previousWindowPixmapLock_)) + , lastPresentTime(std::chrono::milliseconds::zero()) { } diff --git a/libkwineffects/anidata_p.h b/libkwineffects/anidata_p.h index c1bedafb4f..ed26e9a40b 100644 --- a/libkwineffects/anidata_p.h +++ b/libkwineffects/anidata_p.h @@ -88,6 +88,7 @@ public: KeepAliveLockPtr keepAliveLock; PreviousWindowPixmapLockPtr previousWindowPixmapLock; AnimationEffect::TerminationFlags terminationFlags; + std::chrono::milliseconds lastPresentTime; }; } // namespace diff --git a/libkwineffects/kwinanimationeffect.cpp b/libkwineffects/kwinanimationeffect.cpp index eb287aaee8..f0a741272f 100644 --- a/libkwineffects/kwinanimationeffect.cpp +++ b/libkwineffects/kwinanimationeffect.cpp @@ -391,11 +391,11 @@ bool AnimationEffect::cancel(quint64 animationId) return false; } -void AnimationEffect::prePaintScreen( ScreenPrePaintData& data, int time ) +void AnimationEffect::prePaintScreen( ScreenPrePaintData& data, std::chrono::milliseconds presentTime ) { Q_D(AnimationEffect); if (d->m_animations.isEmpty()) { - effects->prePaintScreen(data, time); + effects->prePaintScreen(data, presentTime); return; } @@ -415,7 +415,10 @@ void AnimationEffect::prePaintScreen( ScreenPrePaintData& data, int time ) continue; } } else { - anim->timeLine.update(std::chrono::milliseconds(time)); + if (anim->lastPresentTime.count()) { + anim->timeLine.update(presentTime - anim->lastPresentTime); + } + anim->lastPresentTime = presentTime; } if (anim->isActive()) { @@ -465,7 +468,7 @@ void AnimationEffect::prePaintScreen( ScreenPrePaintData& data, int time ) disconnectGeometryChanges(); } - effects->prePaintScreen(data, time); + effects->prePaintScreen(data, presentTime); } static int xCoord(const QRect &r, int flag) { @@ -561,7 +564,7 @@ void AnimationEffect::disconnectGeometryChanges() } -void AnimationEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time ) +void AnimationEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, std::chrono::milliseconds presentTime ) { Q_D(AnimationEffect); if ( d->m_animated ) { @@ -596,7 +599,7 @@ void AnimationEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, } } } - effects->prePaintWindow( w, data, time ); + effects->prePaintWindow(w, data, presentTime); } static inline float geometryCompensation(int flags, float v) diff --git a/libkwineffects/kwinanimationeffect.h b/libkwineffects/kwinanimationeffect.h index 94af2fcfc9..26179a8632 100644 --- a/libkwineffects/kwinanimationeffect.h +++ b/libkwineffects/kwinanimationeffect.h @@ -198,8 +198,8 @@ public: // Reimplemented from KWin::Effect. QString debug(const QString ¶meter) const override; - void prePaintScreen( ScreenPrePaintData& data, int time ) override; - void prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time ) override; + void prePaintScreen( ScreenPrePaintData& data, std::chrono::milliseconds presentTime ) override; + void prePaintWindow( EffectWindow* w, WindowPrePaintData& data, std::chrono::milliseconds presentTime ) override; void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ) override; void postPaintScreen() override; diff --git a/libkwineffects/kwineffects.cpp b/libkwineffects/kwineffects.cpp index 7232143bab..0ed7c467bb 100644 --- a/libkwineffects/kwineffects.cpp +++ b/libkwineffects/kwineffects.cpp @@ -567,9 +567,9 @@ bool Effect::borderActivated(ElectricBorder) return false; } -void Effect::prePaintScreen(ScreenPrePaintData& data, int time) +void Effect::prePaintScreen(ScreenPrePaintData& data, std::chrono::milliseconds presentTime) { - effects->prePaintScreen(data, time); + effects->prePaintScreen(data, presentTime); } void Effect::paintScreen(int mask, const QRegion ®ion, ScreenPaintData& data) @@ -582,9 +582,9 @@ void Effect::postPaintScreen() effects->postPaintScreen(); } -void Effect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int time) +void Effect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, std::chrono::milliseconds presentTime) { - effects->prePaintWindow(w, data, time); + effects->prePaintWindow(w, data, presentTime); } void Effect::paintWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data) diff --git a/libkwineffects/kwineffects.h b/libkwineffects/kwineffects.h index bbc1c3deea..b5c165bb6d 100644 --- a/libkwineffects/kwineffects.h +++ b/libkwineffects/kwineffects.h @@ -402,8 +402,12 @@ public: * * In OpenGL based compositing, the frameworks ensures that the context is current * when this method is invoked. + * + * @a presentTime specifies the expected monotonic time when the rendered frame + * will be displayed on the screen. */ - virtual void prePaintScreen(ScreenPrePaintData& data, int time); + virtual void prePaintScreen(ScreenPrePaintData &data, + std::chrono::milliseconds presentTime); /** * In this method you can: * @li paint something on top of the windows (by painting after calling @@ -436,8 +440,12 @@ public: * * In OpenGL based compositing, the frameworks ensures that the context is current * when this method is invoked. + * + * @a presentTime specifies the expected monotonic time when the rendered frame + * will be displayed on the screen. */ - virtual void prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int time); + virtual void prePaintWindow(EffectWindow *w, WindowPrePaintData &data, + std::chrono::milliseconds presentTime); /** * This is the main method for painting windows. * In this method you can: @@ -824,10 +832,10 @@ public: explicit EffectsHandler(CompositingType type); ~EffectsHandler() override; // for use by effects - virtual void prePaintScreen(ScreenPrePaintData& data, int time) = 0; + virtual void prePaintScreen(ScreenPrePaintData& data, std::chrono::milliseconds presentTime) = 0; virtual void paintScreen(int mask, const QRegion ®ion, ScreenPaintData& data) = 0; virtual void postPaintScreen() = 0; - virtual void prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int time) = 0; + virtual void prePaintWindow(EffectWindow* w, WindowPrePaintData& data, std::chrono::milliseconds presentTime) = 0; virtual void paintWindow(EffectWindow* w, int mask, const QRegion ®ion, WindowPaintData& data) = 0; virtual void postPaintWindow(EffectWindow* w) = 0; virtual void paintEffectFrame(EffectFrame* frame, const QRegion ®ion, double opacity, double frameOpacity) = 0; diff --git a/plugins/scenes/opengl/scene_opengl.cpp b/plugins/scenes/opengl/scene_opengl.cpp index f90f00375d..e1f944b1c1 100644 --- a/plugins/scenes/opengl/scene_opengl.cpp +++ b/plugins/scenes/opengl/scene_opengl.cpp @@ -620,7 +620,8 @@ void SceneOpenGL::aboutToStartPainting(int screenId, const QRegion &damage) m_backend->aboutToStartPainting(screenId, damage); } -void SceneOpenGL::paint(int screenId, const QRegion &damage, const QList &toplevels) +void SceneOpenGL::paint(int screenId, const QRegion &damage, const QList &toplevels, + std::chrono::milliseconds presentTime) { if (m_resetOccurred) { return; // A graphics reset has occurred, do nothing. @@ -658,7 +659,8 @@ void SceneOpenGL::paint(int screenId, const QRegion &damage, const QListisGLES() && screenId == -1) { diff --git a/plugins/scenes/opengl/scene_opengl.h b/plugins/scenes/opengl/scene_opengl.h index 0e6c60c63e..93bcaa4fa9 100644 --- a/plugins/scenes/opengl/scene_opengl.h +++ b/plugins/scenes/opengl/scene_opengl.h @@ -35,7 +35,8 @@ public: ~SceneOpenGL() override; bool initFailed() const override; bool hasPendingFlush() const override; - void paint(int screenId, const QRegion &damage, const QList &windows) override; + void paint(int screenId, const QRegion &damage, const QList &windows, + std::chrono::milliseconds presentTime) override; Scene::EffectFrame *createEffectFrame(EffectFrameImpl *frame) override; Shadow *createShadow(Toplevel *toplevel) override; void screenGeometryChanged(const QSize &size) override; diff --git a/plugins/scenes/qpainter/scene_qpainter.cpp b/plugins/scenes/qpainter/scene_qpainter.cpp index 7a9b525254..a1de2f56ac 100644 --- a/plugins/scenes/qpainter/scene_qpainter.cpp +++ b/plugins/scenes/qpainter/scene_qpainter.cpp @@ -80,7 +80,8 @@ void SceneQPainter::paintGenericScreen(int mask, const ScreenPaintData &data) m_painter->restore(); } -void SceneQPainter::paint(int screenId, const QRegion &_damage, const QList &toplevels) +void SceneQPainter::paint(int screenId, const QRegion &_damage, const QList &toplevels, + std::chrono::milliseconds presentTime) { Q_ASSERT(kwinApp()->platform()->isPerScreenRenderingEnabled()); painted_screen = screenId; @@ -103,7 +104,8 @@ void SceneQPainter::paint(int screenId, const QRegion &_damage, const QListsetWindow(geometry); QRegion updateRegion, validRegion; - paintScreen(&mask, damage.intersected(geometry), QRegion(), &updateRegion, &validRegion); + paintScreen(&mask, damage.intersected(geometry), QRegion(), &updateRegion, &validRegion, + presentTime); paintCursor(updateRegion); m_painter->end(); diff --git a/plugins/scenes/qpainter/scene_qpainter.h b/plugins/scenes/qpainter/scene_qpainter.h index b47b1c18be..d9b304c383 100644 --- a/plugins/scenes/qpainter/scene_qpainter.h +++ b/plugins/scenes/qpainter/scene_qpainter.h @@ -25,7 +25,8 @@ public: ~SceneQPainter() override; bool usesOverlayWindow() const override; OverlayWindow* overlayWindow() const override; - void paint(int screenId, const QRegion &damage, const QList &windows) override; + void paint(int screenId, const QRegion &damage, const QList &windows, + std::chrono::milliseconds presentTime) override; void paintGenericScreen(int mask, const ScreenPaintData &data) override; CompositingType compositingType() const override; bool initFailed() const override; diff --git a/plugins/scenes/xrender/scene_xrender.cpp b/plugins/scenes/xrender/scene_xrender.cpp index b967fe7350..27766e8a71 100644 --- a/plugins/scenes/xrender/scene_xrender.cpp +++ b/plugins/scenes/xrender/scene_xrender.cpp @@ -75,7 +75,8 @@ bool SceneXrender::initFailed() const } // the entry point for painting -void SceneXrender::paint(int screenId, const QRegion &damage, const QList &toplevels) +void SceneXrender::paint(int screenId, const QRegion &damage, const QList &toplevels, + std::chrono::milliseconds presentTime) { painted_screen = screenId; @@ -83,7 +84,7 @@ void SceneXrender::paint(int screenId, const QRegion &damage, const QListshowOverlay(); diff --git a/plugins/scenes/xrender/scene_xrender.h b/plugins/scenes/xrender/scene_xrender.h index 0f31f46961..1816e35303 100644 --- a/plugins/scenes/xrender/scene_xrender.h +++ b/plugins/scenes/xrender/scene_xrender.h @@ -32,7 +32,8 @@ public: CompositingType compositingType() const override { return XRenderCompositing; } - void paint(int screenId, const QRegion &damage, const QList &windows) override; + void paint(int screenId, const QRegion &damage, const QList &windows, + std::chrono::milliseconds presentTime) override; Scene::EffectFrame *createEffectFrame(EffectFrameImpl *frame) override; Shadow *createShadow(Toplevel *toplevel) override; void screenGeometryChanged(const QSize &size) override; diff --git a/scene.cpp b/scene.cpp index 1c065f7787..30ee308d02 100644 --- a/scene.cpp +++ b/scene.cpp @@ -86,7 +86,6 @@ namespace KWin Scene::Scene(QObject *parent) : QObject(parent) { - last_time.invalidate(); // Initialize the timer } Scene::~Scene() @@ -96,13 +95,22 @@ Scene::~Scene() // returns mask and possibly modified region void Scene::paintScreen(int* mask, const QRegion &damage, const QRegion &repaint, - QRegion *updateRegion, QRegion *validRegion, const QMatrix4x4 &projection, const QRect &outputGeometry, const qreal screenScale) + QRegion *updateRegion, QRegion *validRegion, + std::chrono::milliseconds presentTime, + const QMatrix4x4 &projection, const QRect &outputGeometry, + qreal screenScale) { const QSize &screenSize = screens()->size(); const QRegion displayRegion(0, 0, screenSize.width(), screenSize.height()); *mask = (damage == displayRegion) ? 0 : PAINT_SCREEN_REGION; - updateTimeDiff(); + if (Q_UNLIKELY(presentTime < m_expectedPresentTimestamp)) { + qCDebug(KWIN_CORE, "Provided presentation timestamp is invalid: %ld (current: %ld)", + presentTime.count(), m_expectedPresentTimestamp.count()); + } else { + m_expectedPresentTimestamp = presentTime; + } + // preparation step static_cast(effects)->startPaint(); @@ -112,7 +120,7 @@ void Scene::paintScreen(int* mask, const QRegion &damage, const QRegion &repaint pdata.mask = *mask; pdata.paint = region; - effects->prePaintScreen(pdata, time_diff); + effects->prePaintScreen(pdata, m_expectedPresentTimestamp); *mask = pdata.mask; region = pdata.paint; @@ -154,29 +162,9 @@ void Scene::paintScreen(int* mask, const QRegion &damage, const QRegion &repaint Q_ASSERT(!PaintClipper::clip()); } -// Compute time since the last painting pass. -void Scene::updateTimeDiff() -{ - if (!last_time.isValid()) { - // Painting has been idle (optimized out) for some time, - // which means time_diff would be huge and would break animations. - // Simply set it to one (zero would mean no change at all and could - // cause problems). - time_diff = 1; - last_time.start(); - } else - - time_diff = last_time.restart(); - - if (time_diff < 0) // check time rollback - time_diff = 1; -} - // Painting pass is optimized away. void Scene::idle() { - // Don't break time since last paint for the next pass. - last_time.invalidate(); } // the function that'll be eventually called by paintScreen() above @@ -213,7 +201,7 @@ void Scene::paintGenericScreen(int orig_mask, const ScreenPaintData &) data.clip = QRegion(); data.quads = w->buildQuads(); // preparation step - effects->prePaintWindow(effectWindow(w), data, time_diff); + effects->prePaintWindow(effectWindow(w), data, m_expectedPresentTimestamp); #if !defined(QT_NO_DEBUG) if (data.quads.isTransformed()) { qFatal("Pre-paint calls are not allowed to transform quads!"); @@ -306,7 +294,7 @@ void Scene::paintSimpleScreen(int orig_mask, const QRegion ®ion) data.quads = window->buildQuads(); // preparation step - effects->prePaintWindow(effectWindow(window), data, time_diff); + effects->prePaintWindow(effectWindow(window), data, m_expectedPresentTimestamp); #if !defined(QT_NO_DEBUG) if (data.quads.isTransformed()) { qFatal("Pre-paint calls are not allowed to transform quads!"); diff --git a/scene.h b/scene.h index 1b8ea7c432..86506e71da 100644 --- a/scene.h +++ b/scene.h @@ -65,7 +65,8 @@ public: // The entry point for the main part of the painting pass. // returns the time since the last vblank signal - if there's one // ie. "what of this frame is lost to painting" - virtual void paint(int screenId, const QRegion &damage, const QList &windows) = 0; + virtual void paint(int screenId, const QRegion &damage, const QList &windows, + std::chrono::milliseconds presentTime) = 0; /** * Adds the Toplevel to the Scene. @@ -207,7 +208,10 @@ protected: void clearStackingOrder(); // shared implementation, starts painting the screen void paintScreen(int *mask, const QRegion &damage, const QRegion &repaint, - QRegion *updateRegion, QRegion *validRegion, const QMatrix4x4 &projection = QMatrix4x4(), const QRect &outputGeometry = QRect(), const qreal screenScale = 1.0); + QRegion *updateRegion, QRegion *validRegion, + std::chrono::milliseconds presentTime, + const QMatrix4x4 &projection = QMatrix4x4(), + const QRect &outputGeometry = QRect(), qreal screenScale = 1.0); // Render cursor texture in case hardware cursor is disabled/non-applicable virtual void paintCursor(const QRegion ®ion) = 0; friend class EffectsHandlerImpl; @@ -240,8 +244,6 @@ protected: virtual void paintEffectQuickView(EffectQuickView *w) = 0; - // compute time since the last repaint - void updateTimeDiff(); // saved data for 2nd pass of optimized screen painting struct Phase2Data { Window *window = nullptr; @@ -260,14 +262,12 @@ protected: QRegion repaint_region; // The dirty region before it was unioned with repaint_region QRegion damaged_region; - // time since last repaint - int time_diff; - QElapsedTimer last_time; // The screen that is being currently painted int painted_screen = -1; private: void paintWindowThumbnails(Scene::Window *w, const QRegion ®ion, qreal opacity, qreal brightness, qreal saturation); void paintDesktopThumbnails(Scene::Window *w); + std::chrono::milliseconds m_expectedPresentTimestamp = std::chrono::milliseconds::zero(); QHash< Toplevel*, Window* > m_windows; // windows in their stacking order QVector< Window* > stacking_order;