Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 62 additions & 28 deletions src/wallpaper/wallpaperswitcheritem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ class WallpaperSlot : public WallpaperItem
{
setLive(true);
}
// False only while parked off-screen before its first reveal.
bool shown = true;
};

WallpaperSwitcherItem::WallpaperSwitcherItem(QQuickItem *parent)
Expand All @@ -52,6 +54,8 @@ WallpaperSwitcherItem::WallpaperSwitcherItem(QQuickItem *parent)

WallpaperSwitcherItem::~WallpaperSwitcherItem()
{
if (m_slideAnim)
m_slideAnim->stop(); // finish handler still has live slots here
delete m_oldSlot;
delete m_currentSlot;
}
Expand Down Expand Up @@ -118,18 +122,18 @@ QString WallpaperSwitcherItem::source() const
return m_currentSlot ? m_currentSlot->source() : QString();
}

int WallpaperSwitcherItem::opacityDuration() const
int WallpaperSwitcherItem::transitionDuration() const
{
return m_opacityDuration;
return m_transitionDuration;
}

void WallpaperSwitcherItem::setOpacityDuration(int duration)
void WallpaperSwitcherItem::setTransitionDuration(int duration)
{
if (m_opacityDuration == duration)
if (m_transitionDuration == duration)
return;

m_opacityDuration = duration;
Q_EMIT opacityDurationChanged();
m_transitionDuration = duration;
Q_EMIT transitionDurationChanged();
}

void WallpaperSwitcherItem::slowDown()
Expand Down Expand Up @@ -171,8 +175,8 @@ void WallpaperSwitcherItem::handleWorkspaceAdded()
void WallpaperSwitcherItem::switchToNewSlot()
{
auto *newSlot = new WallpaperSlot(this);
QQuickItemPrivate::get(newSlot)->anchors()->setFill(this);
newSlot->setOpacity(0);
newSlot->setVisible(false);
newSlot->shown = false;
newSlot->setOutput(m_output);
newSlot->setWorkspace(m_workspace);

Expand All @@ -181,46 +185,76 @@ void WallpaperSwitcherItem::switchToNewSlot()
return;
}

m_oldSlot = m_currentSlot;
// Curtain effect: park the new wallpaper fully off-screen right, then
// slide it over the old one like a curtain being drawn across.
newSlot->setWidth(width());
newSlot->setHeight(height());
newSlot->setX(width());

// Settle any in-flight transition first so the screen always keeps a
// fully visible wallpaper while the next one waits for ready.
if (m_slideAnim) {
m_slideAnim->stop(); // finished -> finishSlideIn completes the current slot
m_slideAnim = nullptr;
}
Comment on lines +196 to +199
if (m_currentSlot) {
if (m_currentSlot->shown) {
if (m_oldSlot)
m_oldSlot->deleteLater();
m_oldSlot = m_currentSlot;
} else {
m_currentSlot->deleteLater(); // parked, never shown
}
}
m_currentSlot = newSlot;

Q_EMIT sourceChanged();

auto *fadeOut = new QPropertyAnimation(m_oldSlot, "opacity");
fadeOut->setDuration(m_opacityDuration);
fadeOut->setStartValue(1.0);
fadeOut->setEndValue(0.0);
fadeOut->setEasingCurve(QEasingCurve::InOutQuad);
connect(fadeOut, &QPropertyAnimation::finished, this, &WallpaperSwitcherItem::onAnimationFinished);
fadeOut->start(QAbstractAnimation::DeleteWhenStopped);

auto *interface = TreelandWallpaperSurfaceInterfaceV1::get(newSlot->source());
if (interface && interface->wallpaperReady()) {
startFadeIn(newSlot);
startSlideIn(newSlot);
} else if (interface) {
connect(interface,
&TreelandWallpaperSurfaceInterfaceV1::ready,
this,
[this, newSlot]() {
if (m_currentSlot == newSlot)
startFadeIn(newSlot);
[this, guard = QPointer<WallpaperSlot>(newSlot)]() {
if (guard && m_currentSlot == guard.data())
startSlideIn(guard);
},
Qt::SingleShotConnection);
}
}

void WallpaperSwitcherItem::startFadeIn(WallpaperSlot *slot)
void WallpaperSwitcherItem::startSlideIn(WallpaperSlot *slot)
{
auto *anim = new QPropertyAnimation(slot, "opacity");
anim->setDuration(m_opacityDuration);
anim->setStartValue(0.0);
anim->setEndValue(1.0);
anim->setEasingCurve(QEasingCurve::InOutQuad);
if (width() <= 0.0 || height() <= 0.0) {
finishSlideIn(slot);
return;
}

slot->shown = true;
slot->setVisible(true);
auto *anim = new QPropertyAnimation(slot, "x");
anim->setDuration(m_transitionDuration);
anim->setStartValue(width());
anim->setEndValue(0.0);
anim->setEasingCurve(QEasingCurve::OutCubic);
connect(anim, &QPropertyAnimation::finished, this, [this, guard = QPointer<WallpaperSlot>(slot)]() {
finishSlideIn(guard);
});
m_slideAnim = anim;
anim->start(QAbstractAnimation::DeleteWhenStopped);
}

void WallpaperSwitcherItem::onAnimationFinished()
void WallpaperSwitcherItem::finishSlideIn(WallpaperSlot *slot)
{
if (m_currentSlot != slot)
return;

slot->shown = true;
slot->setVisible(true);
slot->setX(0);
QQuickItemPrivate::get(slot)->anchors()->setFill(this);
if (m_oldSlot) {
m_oldSlot->deleteLater();
m_oldSlot = nullptr;
Expand Down
17 changes: 10 additions & 7 deletions src/wallpaper/wallpaperswitcheritem.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

Q_MOC_INCLUDE("workspace/workspace.h")

class QPropertyAnimation;

class WallpaperSlot;
class TreelandWallpaperSurfaceInterfaceV1;

Expand All @@ -26,7 +28,7 @@ class WallpaperSwitcherItem : public QQuickItem
Q_PROPERTY(WorkspaceModel *workspace READ workspace WRITE setWorkspace NOTIFY workspaceChanged FINAL)
Q_PROPERTY(bool play READ play WRITE setPlay NOTIFY playChanged FINAL)
Q_PROPERTY(QString source READ source NOTIFY sourceChanged FINAL)
Q_PROPERTY(int opacityDuration READ opacityDuration WRITE setOpacityDuration NOTIFY opacityDurationChanged FINAL)
Q_PROPERTY(int transitionDuration READ transitionDuration WRITE setTransitionDuration NOTIFY transitionDurationChanged FINAL)

QML_NAMED_ELEMENT(WallpaperSwitcher)
QML_ADDED_IN_VERSION(1, 0)
Expand All @@ -46,8 +48,8 @@ class WallpaperSwitcherItem : public QQuickItem

QString source() const;

int opacityDuration() const;
void setOpacityDuration(int duration);
int transitionDuration() const;
void setTransitionDuration(int duration);

Q_INVOKABLE void slowDown();

Expand All @@ -56,21 +58,22 @@ class WallpaperSwitcherItem : public QQuickItem
void workspaceChanged();
void playChanged();
void sourceChanged();
void opacityDurationChanged();
void transitionDurationChanged();

private:
void handleWallpaperUpdate();
void handleWorkspaceAdded();
void switchToNewSlot();
void onAnimationFinished();
void startFadeIn(WallpaperSlot *slot);
void startSlideIn(WallpaperSlot *slot);
void finishSlideIn(WallpaperSlot *slot);

QPointer<WorkspaceModel> m_workspace;
QPointer<WOutput> m_output;
bool m_play = true;
QString m_source;
int m_opacityDuration = 500;
int m_transitionDuration = 500;

QPointer<QPropertyAnimation> m_slideAnim;
WallpaperSlot *m_currentSlot = nullptr;
WallpaperSlot *m_oldSlot = nullptr;
};
Loading