diff --git a/libkwineffects/kwineffects.cpp b/libkwineffects/kwineffects.cpp index 45a075a14e..ff70b5aaac 100644 --- a/libkwineffects/kwineffects.cpp +++ b/libkwineffects/kwineffects.cpp @@ -840,23 +840,24 @@ void WindowMotionManager::manage(EffectWindow *w) smoothness = effects->animationTimeFactor() * 4.0; } - m_managedWindows[ w ] = WindowMotion(); - m_managedWindows[ w ].translation.setStrength(strength); - m_managedWindows[ w ].translation.setSmoothness(smoothness); - m_managedWindows[ w ].scale.setStrength(strength * 1.33); - m_managedWindows[ w ].scale.setSmoothness(smoothness / 2.0); + WindowMotion &motion = m_managedWindows[ w ]; + motion.translation.setStrength(strength); + motion.translation.setSmoothness(smoothness); + motion.scale.setStrength(strength * 1.33); + motion.scale.setSmoothness(smoothness / 2.0); - m_managedWindows[ w ].translation.setValue(w->pos()); - m_managedWindows[ w ].scale.setValue(QPointF(1.0, 1.0)); + motion.translation.setValue(w->pos()); + motion.scale.setValue(QPointF(1.0, 1.0)); } void WindowMotionManager::unmanage(EffectWindow *w) { - if (!m_managedWindows.contains(w)) - return; - - QPointF diffT = m_managedWindows[ w ].translation.distance(); - QPointF diffS = m_managedWindows[ w ].scale.distance(); + /// superflous, see below +// if (!m_managedWindows.contains(w)) +// return; + /// this makes no sense?! +// QPointF diffT = m_managedWindows[ w ].translation.distance(); +// QPointF diffS = m_managedWindows[ w ].scale.distance(); m_movingWindowsSet.remove(w); m_managedWindows.remove(w); @@ -884,130 +885,151 @@ void WindowMotionManager::calculate(int time) QHash::iterator it = m_managedWindows.begin(); for (; it != m_managedWindows.end(); it++) { WindowMotion *motion = &it.value(); - bool stopped = false; + EffectWindow *window = it.key(); + int stopped = 0; // TODO: What happens when distance() == 0 but we are still moving fast? // TODO: Motion needs to be calculated from the window's center - QPointF diffT = motion->translation.distance(); - if (diffT != QPoint(0.0, 0.0)) { + Motion2D *trans = &motion->translation; + if (trans->distance().isNull()) + ++stopped; + else { // Still moving - motion->translation.calculate(time); - diffT = motion->translation.distance(); - if (qAbs(diffT.x()) < 0.5 && qAbs(motion->translation.velocity().x()) < 0.2 && - qAbs(diffT.y()) < 0.5 && qAbs(motion->translation.velocity().y()) < 0.2) { + trans->calculate(time); + const short fx = trans->target().x() <= window->x() ? -1 : 1; + const short fy = trans->target().y() <= window->y() ? -1 : 1; + if (trans->distance().x()*fx/0.5 < 1.0 && trans->velocity().x()*fx/0.2 < 1.0 && + trans->distance().y()*fy/0.5 < 1.0 && trans->velocity().y()*fy/0.2 < 1.0) { // Hide tiny oscillations motion->translation.finish(); - diffT = QPoint(0.0, 0.0); - stopped = true; + ++stopped; } } - QPointF diffS = motion->scale.distance(); - if (diffS != QPoint(0.0, 0.0)) { + Motion2D *scale = &motion->scale; + if (scale->distance().isNull()) + ++stopped; + else { // Still scaling - motion->scale.calculate(time); - diffS = motion->scale.distance(); - if (qAbs(diffS.x()) < 0.001 && qAbs(motion->scale.velocity().x()) < 0.05 && - qAbs(diffS.y()) < 0.001 && qAbs(motion->scale.velocity().y()) < 0.05) { + scale->calculate(time); + const short fx = scale->target().x() < 1.0 ? -1 : 1; + const short fy = scale->target().y() < 1.0 ? -1 : 1; + if (scale->distance().x()*fx/0.001 < 1.0 && scale->velocity().x()*fx/0.05 < 1.0 && + scale->distance().y()*fy/0.001 < 1.0 && scale->velocity().y()*fy/0.05 < 1.0) { // Hide tiny oscillations motion->scale.finish(); - diffS = QPoint(0.0, 0.0); - stopped = true; + ++stopped; } } // We just finished this window's motion - if (stopped && diffT == QPoint(0.0, 0.0) && diffS == QPoint(0.0, 0.0)) + if (stopped == 2) m_movingWindowsSet.remove(it.key()); } } void WindowMotionManager::reset() { - if (!m_managedWindows.count()) - return; - - EffectWindowList windows = m_managedWindows.keys(); - - for (int i = 0; i < windows.size(); i++) { - EffectWindow *w = windows.at(i); - m_managedWindows[ w ].translation.setTarget(w->pos()); - m_managedWindows[ w ].translation.finish(); - m_managedWindows[ w ].scale.setTarget(QPointF(1.0, 1.0)); - m_managedWindows[ w ].scale.finish(); + QHash::iterator it = m_managedWindows.begin(); + for (; it != m_managedWindows.end(); it++) { + WindowMotion *motion = &it.value(); + EffectWindow *window = it.key(); + motion->translation.setTarget(window->pos()); + motion->translation.finish(); + motion->scale.setTarget(QPointF(1.0, 1.0)); + motion->scale.finish(); } } void WindowMotionManager::reset(EffectWindow *w) { - if (!m_managedWindows.contains(w)) + QHash::iterator it = m_managedWindows.find(w); + if (it == m_managedWindows.end()) return; - m_managedWindows[ w ].translation.setTarget(w->pos()); - m_managedWindows[ w ].translation.finish(); - m_managedWindows[ w ].scale.setTarget(QPointF(1.0, 1.0)); - m_managedWindows[ w ].scale.finish(); + WindowMotion *motion = &it.value(); + motion->translation.setTarget(w->pos()); + motion->translation.finish(); + motion->scale.setTarget(QPointF(1.0, 1.0)); + motion->scale.finish(); } void WindowMotionManager::apply(EffectWindow *w, WindowPaintData &data) { - if (!m_managedWindows.contains(w)) + QHash::iterator it = m_managedWindows.find(w); + if (it == m_managedWindows.end()) return; // TODO: Take into account existing scale so that we can work with multiple managers (E.g. Present windows + grid) - data.xTranslate += m_managedWindows[ w ].translation.value().x() - w->x(); - data.yTranslate += m_managedWindows[ w ].translation.value().y() - w->y(); - data.xScale *= m_managedWindows[ w ].scale.value().x(); - data.yScale *= m_managedWindows[ w ].scale.value().y(); + WindowMotion *motion = &it.value(); + data.xTranslate += motion->translation.value().x() - w->x(); + data.yTranslate += motion->translation.value().y() - w->y(); + data.xScale *= motion->scale.value().x(); + data.yScale *= motion->scale.value().y(); } void WindowMotionManager::moveWindow(EffectWindow *w, QPoint target, double scale, double yScale) { - if (!m_managedWindows.contains(w)) + QHash::iterator it = m_managedWindows.find(w); + if (it == m_managedWindows.end()) abort(); // Notify the effect author that they did something wrong + WindowMotion *motion = &it.value(); + if (yScale == 0.0) yScale = scale; QPointF scalePoint(scale, yScale); - if (m_managedWindows[ w ].translation.value() == target && - m_managedWindows[ w ].scale.value() == scalePoint) + if (motion->translation.value() == target && motion->scale.value() == scalePoint) return; // Window already at that position - m_managedWindows[ w ].translation.setTarget(target); - m_managedWindows[ w ].scale.setTarget(scalePoint); + motion->translation.setTarget(target); + motion->scale.setTarget(scalePoint); m_movingWindowsSet << w; } QRectF WindowMotionManager::transformedGeometry(EffectWindow *w) const { + QHash::const_iterator it = m_managedWindows.constFind(w); + if (it == m_managedWindows.end()) + return w->geometry(); + + const WindowMotion *motion = &it.value(); QRectF geometry(w->geometry()); // TODO: Take into account existing scale so that we can work with multiple managers (E.g. Present windows + grid) - geometry.moveTo(m_managedWindows[ w ].translation.value()); - geometry.setWidth(geometry.width() * m_managedWindows[ w ].scale.value().x()); - geometry.setHeight(geometry.height() * m_managedWindows[ w ].scale.value().y()); + geometry.moveTo(motion->translation.value()); + geometry.setWidth(geometry.width() * motion->scale.value().x()); + geometry.setHeight(geometry.height() * motion->scale.value().y()); return geometry; } void WindowMotionManager::setTransformedGeometry(EffectWindow *w, const QRectF &geometry) { - m_managedWindows[ w ].translation.setValue(geometry.topLeft()); - m_managedWindows[ w ].scale.setValue(QPointF(geometry.width() / qreal(w->width()), - geometry.height() / qreal(w->height()))); + QHash::iterator it = m_managedWindows.find(w); + if (it == m_managedWindows.end()) + return; + WindowMotion *motion = &it.value(); + motion->translation.setValue(geometry.topLeft()); + motion->scale.setValue(QPointF(geometry.width() / qreal(w->width()), geometry.height() / qreal(w->height()))); } QRectF WindowMotionManager::targetGeometry(EffectWindow *w) const { + QHash::const_iterator it = m_managedWindows.constFind(w); + if (it == m_managedWindows.end()) + return w->geometry(); + + const WindowMotion *motion = &it.value(); QRectF geometry(w->geometry()); // TODO: Take into account existing scale so that we can work with multiple managers (E.g. Present windows + grid) - geometry.moveTo(m_managedWindows[ w ].translation.target()); - geometry.setWidth(geometry.width() * m_managedWindows[ w ].scale.target().x()); - geometry.setHeight(geometry.height() * m_managedWindows[ w ].scale.target().y()); + geometry.moveTo(motion->translation.target()); + geometry.setWidth(geometry.width() * motion->scale.target().x()); + geometry.setHeight(geometry.height() * motion->scale.target().y()); return geometry; }