diff --git a/client.cpp b/client.cpp index eb082fad59..3d334a1bbe 100644 --- a/client.cpp +++ b/client.cpp @@ -353,8 +353,22 @@ void Client::destroyClient() deleteClient(this, Allowed); } +// DnD handling for input shaping is broken in the clients for all Qt versions before 4.8.3 +// NOTICE do not query the Qt version macro, this is a runtime problem! +// TODO KDE5 remove this +static inline bool qtBefore483() +{ + QStringList l = QString(qVersion()).split("."); + // "4.x.y" + return l.at(1).toUInt() < 5 && l.at(1).toUInt() < 9 && l.at(2).toUInt() < 3; +} + void Client::updateInputWindow() { + static bool brokenQtInputHandling = qtBefore483(); + if (brokenQtInputHandling) + return; + QRegion region; if (!noBorder()) { diff --git a/libkwineffects/kwinanimationeffect.cpp b/libkwineffects/kwinanimationeffect.cpp index e0a66941b1..5ed4308cba 100644 --- a/libkwineffects/kwinanimationeffect.cpp +++ b/libkwineffects/kwinanimationeffect.cpp @@ -30,10 +30,10 @@ QElapsedTimer AnimationEffect::s_clock; struct AnimationEffectPrivate { public: - AnimationEffectPrivate() { m_animated = m_damageDirty = false; } + AnimationEffectPrivate() { m_animated = m_damageDirty = m_animationsTouched = false; } AnimationEffect::AniMap m_animations; EffectWindowList m_zombies; - bool m_animated, m_damageDirty, m_needSceneRepaint; + bool m_animated, m_damageDirty, m_needSceneRepaint, m_animationsTouched; }; } @@ -182,6 +182,8 @@ void AnimationEffect::animate( EffectWindow *w, Attribute a, uint meta, int ms, it->first.append(AniData(a, meta, ms, to, curve, delay, from, waitAtSource)); it->second = QRect(); + d->m_animationsTouched = true; + if (delay > 0) { QTimer::singleShot(delay, this, SLOT(triggerRepaint())); if (waitAtSource) @@ -200,16 +202,19 @@ void AnimationEffect::prePaintScreen( ScreenPrePaintData& data, int time ) return; } + d->m_animationsTouched = false; AniMap::iterator entry = d->m_animations.begin(), mapEnd = d->m_animations.end(); d->m_animated = false; // short int transformed = 0; while (entry != mapEnd) { bool invalidateLayerRect = false; QList::iterator anim = entry->first.begin(), animEnd = entry->first.end(); + int animCounter = 0; while (anim != animEnd) { if (anim->startTime > clock()) { if (!anim->waitAtSource) { ++anim; + ++animCounter; continue; } } else { @@ -221,8 +226,25 @@ void AnimationEffect::prePaintScreen( ScreenPrePaintData& data, int time ) // transformed = true; d->m_animated = true; ++anim; + ++animCounter; } else { - animationEnded(entry.key(), anim->attribute, anim->meta); + EffectWindow *oldW = entry.key(); + AniData *aData = &(*anim); + animationEnded(oldW, anim->attribute, anim->meta); + // NOTICE animationEnded is an external call and might have called "::animate" + // as a result our iterators could now point random junk on the heap + // so we've to restore the former states, ie. find our window list and animation + if (d->m_animationsTouched) { + d->m_animationsTouched = false; + entry = d->m_animations.begin(), mapEnd = d->m_animations.end(); + while (entry.key() != oldW && entry != mapEnd) + ++entry; + Q_ASSERT(entry != mapEnd); // usercode should not delete animations from animationEnded (not even possible atm.) + anim = entry->first.begin(), animEnd = entry->first.end(); + Q_ASSERT(animCounter < entry->first.count()); + for (int i = 0; i < animCounter; ++i) + ++anim; + } anim = entry->first.erase(anim); invalidateLayerRect = d->m_damageDirty = true; animEnd = entry->first.end();