Changeset View
Changeset View
Standalone View
Standalone View
effects/glide/glide.cpp
1 | /******************************************************************** | 1 | /******************************************************************** | ||
---|---|---|---|---|---|
2 | KWin - the KDE window manager | 2 | KWin - the KDE window manager | ||
3 | This file is part of the KDE project. | 3 | This file is part of the KDE project. | ||
4 | 4 | | |||
5 | Copyright (C) 2007 Philip Falkner <philip.falkner@gmail.com> | 5 | Copyright (C) 2007 Philip Falkner <philip.falkner@gmail.com> | ||
6 | Copyright (C) 2009 Martin Gräßlin <mgraesslin@kde.org> | 6 | Copyright (C) 2009 Martin Gräßlin <mgraesslin@kde.org> | ||
7 | Copyright (C) 2010 Alexandre Pereira <pereira.alex@gmail.com> | 7 | Copyright (C) 2010 Alexandre Pereira <pereira.alex@gmail.com> | ||
8 | Copyright (C) 2018 Vlad Zagorodniy <vladzzag@gmail.com> | ||||
8 | 9 | | |||
9 | This program is free software; you can redistribute it and/or modify | 10 | This program is free software; you can redistribute it and/or modify | ||
10 | it under the terms of the GNU General Public License as published by | 11 | it under the terms of the GNU General Public License as published by | ||
11 | the Free Software Foundation; either version 2 of the License, or | 12 | the Free Software Foundation; either version 2 of the License, or | ||
12 | (at your option) any later version. | 13 | (at your option) any later version. | ||
13 | 14 | | |||
14 | This program is distributed in the hope that it will be useful, | 15 | This program is distributed in the hope that it will be useful, | ||
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | GNU General Public License for more details. | 18 | GNU General Public License for more details. | ||
18 | 19 | | |||
19 | You should have received a copy of the GNU General Public License | 20 | You should have received a copy of the GNU General Public License | ||
20 | along with this program. If not, see <http://www.gnu.org/licenses/>. | 21 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
21 | *********************************************************************/ | 22 | *********************************************************************/ | ||
22 | 23 | | |||
24 | // own | ||||
23 | #include "glide.h" | 25 | #include "glide.h" | ||
26 | | ||||
24 | // KConfigSkeleton | 27 | // KConfigSkeleton | ||
25 | #include "glideconfig.h" | 28 | #include "glideconfig.h" | ||
26 | 29 | | |||
30 | // Qt | ||||
31 | #include <QMatrix4x4> | ||||
27 | #include <QSet> | 32 | #include <QSet> | ||
28 | #include <QString> | | |||
29 | #include <QTimeLine> | | |||
30 | | ||||
31 | // Effect is based on fade effect by Philip Falkner | | |||
32 | 33 | | |||
33 | namespace KWin | 34 | namespace KWin | ||
34 | { | 35 | { | ||
35 | 36 | | |||
36 | static const int IsGlideWindow = 0x22A982D4; | | |||
37 | | ||||
38 | static const QSet<QString> s_blacklist { | 37 | static const QSet<QString> s_blacklist { | ||
39 | "ksmserver ksmserver", | 38 | QStringLiteral("ksmserver ksmserver"), | ||
40 | "ksplashx ksplashx", | 39 | QStringLiteral("ksplashqml ksplashqml"), | ||
41 | "ksplashsimple ksplashsimple", | 40 | QStringLiteral("ksplashsimple ksplashsimple"), | ||
42 | "ksplashqml ksplashqml" | 41 | QStringLiteral("ksplashx ksplashx") | ||
43 | }; | 42 | }; | ||
44 | 43 | | |||
45 | GlideEffect::GlideEffect() | 44 | GlideEffect::GlideEffect() | ||
46 | : Effect() | | |||
47 | { | 45 | { | ||
48 | initConfig<GlideConfig>(); | 46 | initConfig<GlideConfig>(); | ||
49 | reconfigure(ReconfigureAll); | 47 | reconfigure(ReconfigureAll); | ||
50 | connect(effects, SIGNAL(windowAdded(KWin::EffectWindow*)), this, SLOT(slotWindowAdded(KWin::EffectWindow*))); | | |||
51 | connect(effects, SIGNAL(windowClosed(KWin::EffectWindow*)), this, SLOT(slotWindowClosed(KWin::EffectWindow*))); | | |||
52 | connect(effects, SIGNAL(windowDeleted(KWin::EffectWindow*)), this, SLOT(slotWindowDeleted(KWin::EffectWindow*))); | | |||
53 | 48 | | |||
54 | 49 | connect(effects, &EffectsHandler::windowAdded, this, &GlideEffect::windowAdded); | |||
55 | connect(effects, &EffectsHandler::windowDataChanged, this, &GlideEffect::cancelWindowGrab); | 50 | connect(effects, &EffectsHandler::windowClosed, this, &GlideEffect::windowClosed); | ||
51 | connect(effects, &EffectsHandler::windowDeleted, this, &GlideEffect::windowDeleted); | ||||
52 | connect(effects, &EffectsHandler::windowDataChanged, this, &GlideEffect::windowDataChanged); | ||||
56 | } | 53 | } | ||
57 | 54 | | |||
58 | GlideEffect::~GlideEffect() = default; | 55 | GlideEffect::~GlideEffect() = default; | ||
59 | 56 | | |||
60 | bool GlideEffect::supported() | 57 | void GlideEffect::reconfigure(ReconfigureFlags flags) | ||
61 | { | 58 | { | ||
62 | return effects->isOpenGLCompositing() && effects->animationsSupported(); | 59 | Q_UNUSED(flags) | ||
63 | } | | |||
64 | 60 | | |||
65 | void GlideEffect::reconfigure(ReconfigureFlags) | | |||
66 | { | | |||
67 | // Fetch config with KConfigXT | | |||
68 | GlideConfig::self()->read(); | 61 | GlideConfig::self()->read(); | ||
69 | duration = animationTime<GlideConfig>(350); | 62 | m_duration = std::chrono::milliseconds(animationTime<GlideConfig>(160)); | ||
70 | effect = (EffectStyle) GlideConfig::glideEffect(); | 63 | | ||
71 | angle = GlideConfig::glideAngle(); | 64 | m_inParams.edge = static_cast<RotationEdge>(GlideConfig::inRotationEdge()); | ||
65 | m_inParams.angle.from = GlideConfig::inRotationAngle(); | ||||
66 | m_inParams.angle.to = 0.0; | ||||
67 | m_inParams.distance.from = GlideConfig::inDistance(); | ||||
68 | m_inParams.distance.to = 0.0; | ||||
69 | m_inParams.opacity.from = GlideConfig::inOpacity(); | ||||
70 | m_inParams.opacity.to = 1.0; | ||||
71 | | ||||
72 | m_outParams.edge = static_cast<RotationEdge>(GlideConfig::outRotationEdge()); | ||||
73 | m_outParams.angle.from = 0.0; | ||||
74 | m_outParams.angle.to = GlideConfig::outRotationAngle(); | ||||
75 | m_outParams.distance.from = 0.0; | ||||
76 | m_outParams.distance.to = GlideConfig::outDistance(); | ||||
77 | m_outParams.opacity.from = 1.0; | ||||
78 | m_outParams.opacity.to = GlideConfig::outOpacity(); | ||||
72 | } | 79 | } | ||
73 | 80 | | |||
74 | void GlideEffect::prePaintScreen(ScreenPrePaintData& data, int time) | 81 | void GlideEffect::prePaintScreen(ScreenPrePaintData &data, int time) | ||
75 | { | 82 | { | ||
76 | if (!windows.isEmpty()) | 83 | const std::chrono::milliseconds delta(time); | ||
84 | | ||||
85 | auto animationIt = m_animations.begin(); | ||||
86 | while (animationIt != m_animations.end()) { | ||||
87 | (*animationIt).update(delta); | ||||
88 | ++animationIt; | ||||
89 | } | ||||
90 | | ||||
77 | data.mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS; | 91 | data.mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS; | ||
92 | | ||||
78 | effects->prePaintScreen(data, time); | 93 | effects->prePaintScreen(data, time); | ||
79 | } | 94 | } | ||
80 | 95 | | |||
81 | void GlideEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int time) | 96 | void GlideEffect::prePaintWindow(EffectWindow *w, WindowPrePaintData &data, int time) | ||
82 | { | 97 | { | ||
83 | InfoHash::iterator info = windows.find(w); | 98 | if (m_animations.contains(w)) { | ||
84 | if (info != windows.end()) { | | |||
85 | data.setTransformed(); | 99 | data.setTransformed(); | ||
86 | if (info->added) | | |||
87 | info->timeLine->setCurrentTime(info->timeLine->currentTime() + time); | | |||
88 | else if (info->closed) { | | |||
89 | info->timeLine->setCurrentTime(info->timeLine->currentTime() - time); | | |||
90 | if (info->deleted) | | |||
91 | w->enablePainting(EffectWindow::PAINT_DISABLED_BY_DELETE); | 100 | w->enablePainting(EffectWindow::PAINT_DISABLED_BY_DELETE); | ||
92 | } | 101 | } | ||
93 | } | | |||
94 | 102 | | |||
95 | effects->prePaintWindow(w, data, time); | 103 | effects->prePaintWindow(w, data, time); | ||
96 | | ||||
97 | // if the window isn't to be painted, then let's make sure | | |||
98 | // to track its progress | | |||
99 | if (info != windows.end() && !w->isPaintingEnabled() && !effects->activeFullScreenEffect()) | | |||
100 | w->addRepaintFull(); | | |||
101 | } | 104 | } | ||
102 | 105 | | |||
103 | void GlideEffect::paintWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data) | 106 | void GlideEffect::paintWindow(EffectWindow *w, int mask, QRegion region, WindowPaintData &data) | ||
104 | { | 107 | { | ||
105 | InfoHash::const_iterator info = windows.constFind(w); | 108 | auto animationIt = m_animations.constFind(w); | ||
106 | if (info != windows.constEnd()) { | 109 | if (animationIt == m_animations.constEnd()) { | ||
107 | const double progress = info->timeLine->currentValue(); | 110 | effects->paintWindow(w, mask, region, data); | ||
111 | return; | ||||
112 | } | ||||
113 | | ||||
114 | // Perspective projection distorts objects near edges | ||||
115 | // of the viewport. This is critical because distortions | ||||
116 | // near edges of the viewport are not desired with this effect. | ||||
117 | // To fix this, the center of the window will be moved to the origin, | ||||
118 | // after applying perspective projection, the center is moved back | ||||
119 | // to its "original" projected position. Overall, this is how the window | ||||
120 | // will be transformed: | ||||
121 | // [move to the origin] -> [rotate] -> [translate] -> | ||||
122 | // -> [perspective projection] -> [reverse "move to the origin"] | ||||
123 | const QMatrix4x4 oldProjMatrix = data.screenProjectionMatrix(); | ||||
124 | const QRectF windowGeo = w->geometry(); | ||||
125 | const QVector3D invOffset = oldProjMatrix.map(QVector3D(windowGeo.center())); | ||||
126 | QMatrix4x4 invOffsetMatrix; | ||||
127 | invOffsetMatrix.translate(invOffset.x(), invOffset.y()); | ||||
128 | data.setProjectionMatrix(invOffsetMatrix * oldProjMatrix); | ||||
129 | | ||||
130 | // Move the center of the window to the origin. | ||||
131 | const QRectF screenGeo = effects->virtualScreenGeometry(); | ||||
132 | const QPointF offset = screenGeo.center() - windowGeo.center(); | ||||
133 | data.translate(offset.x(), offset.y()); | ||||
134 | | ||||
135 | const GlideParams params = w->isDeleted() ? m_outParams : m_inParams; | ||||
136 | const qreal t = (*animationIt).value(); | ||||
137 | | ||||
138 | switch (params.edge) { | ||||
139 | case RotationEdge::Top: | ||||
108 | data.setRotationAxis(Qt::XAxis); | 140 | data.setRotationAxis(Qt::XAxis); | ||
109 | data.setRotationAngle(angle * (1 - progress)); | 141 | data.setRotationOrigin(QVector3D(0, 0, 0)); | ||
110 | data.multiplyOpacity(progress); | 142 | data.setRotationAngle(-interpolate(params.angle.from, params.angle.to, t)); | ||
111 | switch(effect) { | | |||
112 | default: | | |||
113 | case GlideInOut: | | |||
114 | if (info->added) | | |||
115 | glideIn(w, data, info); | | |||
116 | else if (info->closed) | | |||
117 | glideOut(w, data, info); | | |||
118 | break; | 143 | break; | ||
119 | case GlideOutIn: | 144 | | ||
120 | if (info->added) | 145 | case RotationEdge::Right: | ||
121 | glideOut(w, data, info); | 146 | data.setRotationAxis(Qt::YAxis); | ||
122 | if (info->closed) | 147 | data.setRotationOrigin(QVector3D(w->width(), 0, 0)); | ||
123 | glideIn(w, data, info); | 148 | data.setRotationAngle(-interpolate(params.angle.from, params.angle.to, t)); | ||
149 | break; | ||||
150 | | ||||
151 | case RotationEdge::Bottom: | ||||
152 | data.setRotationAxis(Qt::XAxis); | ||||
153 | data.setRotationOrigin(QVector3D(0, w->height(), 0)); | ||||
154 | data.setRotationAngle(interpolate(params.angle.from, params.angle.to, t)); | ||||
155 | break; | ||||
156 | | ||||
157 | case RotationEdge::Left: | ||||
158 | data.setRotationAxis(Qt::YAxis); | ||||
159 | data.setRotationOrigin(QVector3D(0, 0, 0)); | ||||
160 | data.setRotationAngle(interpolate(params.angle.from, params.angle.to, t)); | ||||
161 | break; | ||||
162 | | ||||
163 | default: | ||||
164 | // Fallback to Top. | ||||
165 | data.setRotationAxis(Qt::XAxis); | ||||
166 | data.setRotationOrigin(QVector3D(0, 0, 0)); | ||||
167 | data.setRotationAngle(-interpolate(params.angle.from, params.angle.to, t)); | ||||
124 | break; | 168 | break; | ||
125 | case GlideIn: glideIn(w, data, info); break; | | |||
126 | case GlideOut: glideOut(w, data, info); break; | | |||
127 | } | | |||
128 | } | 169 | } | ||
170 | | ||||
171 | data.setZTranslation(-interpolate(params.distance.from, params.distance.to, t)); | ||||
172 | data.multiplyOpacity(interpolate(params.opacity.from, params.opacity.to, t)); | ||||
173 | | ||||
129 | effects->paintWindow(w, mask, region, data); | 174 | effects->paintWindow(w, mask, region, data); | ||
130 | } | 175 | } | ||
131 | 176 | | |||
132 | void GlideEffect::glideIn(EffectWindow* w, WindowPaintData& data, const InfoHash::const_iterator &info) | 177 | void GlideEffect::postPaintScreen() | ||
133 | { | 178 | { | ||
134 | const double progress = info->timeLine->currentValue(); | 179 | auto animationIt = m_animations.begin(); | ||
135 | data *= progress; | 180 | while (animationIt != m_animations.end()) { | ||
136 | data.translate(int(w->width() / 2 * (1 - progress)), int(w->height() / 2 * (1 - progress))); | 181 | if ((*animationIt).done()) { | ||
182 | EffectWindow *w = animationIt.key(); | ||||
183 | if (w->isDeleted()) { | ||||
184 | w->unrefWindow(); | ||||
185 | } | ||||
186 | animationIt = m_animations.erase(animationIt); | ||||
187 | } else { | ||||
188 | ++animationIt; | ||||
189 | } | ||||
137 | } | 190 | } | ||
138 | 191 | | |||
139 | void GlideEffect::glideOut(EffectWindow* w, WindowPaintData& data, const InfoHash::const_iterator &info) | 192 | effects->addRepaintFull(); | ||
140 | { | 193 | effects->postPaintScreen(); | ||
141 | const double progress = info->timeLine->currentValue(); | | |||
142 | data *= (2 - progress); | | |||
143 | data.translate(- int(w->width() / 2 * (1 - progress)), - int(w->height() / 2 * (1 - progress))); | | |||
144 | } | 194 | } | ||
145 | 195 | | |||
146 | void GlideEffect::postPaintWindow(EffectWindow* w) | 196 | bool GlideEffect::isActive() const | ||
147 | { | 197 | { | ||
148 | InfoHash::iterator info = windows.find(w); | 198 | return !m_animations.isEmpty(); | ||
149 | if (info != windows.end()) { | | |||
150 | if (info->added && info->timeLine->currentValue() == 1.0) { | | |||
151 | windows.remove(w); | | |||
152 | effects->addRepaintFull(); | | |||
153 | } else if (info->closed && info->timeLine->currentValue() == 0.0) { | | |||
154 | info->closed = false; | | |||
155 | if (info->deleted) { | | |||
156 | windows.remove(w); | | |||
157 | w->unrefWindow(); | | |||
158 | } | 199 | } | ||
159 | effects->addRepaintFull(); | 200 | | ||
201 | bool GlideEffect::supported() | ||||
202 | { | ||||
203 | return effects->isOpenGLCompositing() | ||||
204 | && effects->animationsSupported(); | ||||
160 | } | 205 | } | ||
161 | if (info->added || info->closed) | 206 | | ||
162 | w->addRepaintFull(); | 207 | void GlideEffect::windowAdded(EffectWindow *w) | ||
208 | { | ||||
209 | if (effects->activeFullScreenEffect()) { | ||||
210 | return; | ||||
163 | } | 211 | } | ||
164 | effects->postPaintWindow(w); | 212 | | ||
213 | if (!isGlideWindow(w)) { | ||||
214 | return; | ||||
165 | } | 215 | } | ||
166 | 216 | | |||
167 | void GlideEffect::slotWindowAdded(EffectWindow* w) | 217 | if (!w->isVisible()) { | ||
168 | { | | |||
169 | if (!isGlideWindow(w)) | | |||
170 | return; | 218 | return; | ||
171 | w->setData(IsGlideWindow, true); | 219 | } | ||
220 | | ||||
172 | const void *addGrab = w->data(WindowAddedGrabRole).value<void*>(); | 221 | const void *addGrab = w->data(WindowAddedGrabRole).value<void*>(); | ||
173 | if (addGrab && addGrab != this) | 222 | if (addGrab && addGrab != this) { | ||
174 | return; | 223 | return; | ||
224 | } | ||||
225 | | ||||
175 | w->setData(WindowAddedGrabRole, QVariant::fromValue(static_cast<void*>(this))); | 226 | w->setData(WindowAddedGrabRole, QVariant::fromValue(static_cast<void*>(this))); | ||
176 | 227 | | |||
177 | InfoHash::iterator it = windows.find(w); | 228 | TimeLine &timeLine = m_animations[w]; | ||
178 | WindowInfo *info = (it == windows.end()) ? &windows[w] : &it.value(); | 229 | timeLine.reset(); | ||
179 | info->added = true; | 230 | timeLine.setDirection(TimeLine::Forward); | ||
180 | info->closed = false; | 231 | timeLine.setDuration(m_duration); | ||
181 | info->deleted = false; | 232 | timeLine.setEasingCurve(QEasingCurve::InCurve); | ||
182 | delete info->timeLine; | 233 | | ||
183 | info->timeLine = new QTimeLine(duration); | 234 | effects->addRepaintFull(); | ||
184 | info->timeLine->setCurveShape(QTimeLine::EaseOutCurve); | | |||
185 | w->addRepaintFull(); | | |||
186 | } | 235 | } | ||
187 | 236 | | |||
188 | void GlideEffect::slotWindowClosed(EffectWindow* w) | 237 | void GlideEffect::windowClosed(EffectWindow *w) | ||
189 | { | 238 | { | ||
190 | if (!isGlideWindow(w)) | 239 | if (effects->activeFullScreenEffect()) { | ||
191 | return; | 240 | return; | ||
241 | } | ||||
242 | | ||||
243 | if (!isGlideWindow(w)) { | ||||
244 | return; | ||||
245 | } | ||||
246 | | ||||
247 | if (!w->isVisible()) { | ||||
248 | return; | ||||
249 | } | ||||
250 | | ||||
192 | const void *closeGrab = w->data(WindowClosedGrabRole).value<void*>(); | 251 | const void *closeGrab = w->data(WindowClosedGrabRole).value<void*>(); | ||
193 | if (closeGrab && closeGrab != this) | 252 | if (closeGrab && closeGrab != this) { | ||
194 | return; | 253 | return; | ||
254 | } | ||||
255 | | ||||
195 | w->refWindow(); | 256 | w->refWindow(); | ||
196 | w->setData(WindowClosedGrabRole, QVariant::fromValue(static_cast<void*>(this))); | 257 | w->setData(WindowClosedGrabRole, QVariant::fromValue(static_cast<void*>(this))); | ||
197 | 258 | | |||
198 | InfoHash::iterator it = windows.find(w); | 259 | TimeLine &timeLine = m_animations[w]; | ||
199 | WindowInfo *info = (it == windows.end()) ? &windows[w] : &it.value(); | 260 | timeLine.reset(); | ||
200 | info->added = false; | 261 | timeLine.setDirection(TimeLine::Forward); | ||
201 | info->closed = true; | 262 | timeLine.setDuration(m_duration); | ||
202 | info->deleted = true; | 263 | timeLine.setEasingCurve(QEasingCurve::OutCurve); | ||
203 | delete info->timeLine; | | |||
204 | info->timeLine = new QTimeLine(duration); | | |||
205 | info->timeLine->setCurveShape(QTimeLine::EaseInCurve); | | |||
206 | info->timeLine->setCurrentTime(info->timeLine->duration()); | | |||
207 | w->addRepaintFull(); | | |||
208 | } | | |||
209 | 264 | | |||
210 | void GlideEffect::slotWindowDeleted(EffectWindow* w) | 265 | effects->addRepaintFull(); | ||
211 | { | | |||
212 | windows.remove(w); | | |||
213 | } | 266 | } | ||
214 | 267 | | |||
215 | bool GlideEffect::isGlideWindow(EffectWindow* w) | 268 | void GlideEffect::windowDeleted(EffectWindow *w) | ||
216 | { | 269 | { | ||
217 | if (effects->activeFullScreenEffect()) | 270 | m_animations.remove(w); | ||
218 | return false; | | |||
219 | if (!w->isVisible()) | | |||
220 | return false; | | |||
221 | if (s_blacklist.contains(w->windowClass())) | | |||
222 | return false; | | |||
223 | if (w->data(IsGlideWindow).toBool()) | | |||
224 | return true; | | |||
225 | if (w->hasDecoration()) | | |||
226 | return true; | | |||
227 | if (!w->isManaged() || w->isMenu() || w->isNotification() || w->isDesktop() || | | |||
228 | w->isDock() || w->isSplash() || w->isToolbar()) | | |||
229 | return false; | | |||
230 | return true; | | |||
231 | } | 271 | } | ||
232 | 272 | | |||
233 | bool GlideEffect::isActive() const | 273 | void GlideEffect::windowDataChanged(EffectWindow *w, int role) | ||
234 | { | 274 | { | ||
235 | return !windows.isEmpty(); | 275 | if (role != WindowAddedGrabRole && role != WindowClosedGrabRole) { | ||
276 | return; | ||||
236 | } | 277 | } | ||
237 | 278 | | |||
238 | void GlideEffect::cancelWindowGrab(EffectWindow *w, int grabRole) | 279 | if (w->data(role).value<void*>() == this) { | ||
239 | { | | |||
240 | if (grabRole != WindowAddedGrabRole && grabRole != WindowClosedGrabRole) { | | |||
241 | return; | 280 | return; | ||
242 | } | 281 | } | ||
243 | if (!w->data(IsGlideWindow).toBool()) { | 282 | | ||
283 | auto animationIt = m_animations.find(w); | ||||
284 | if (animationIt == m_animations.end()) { | ||||
244 | return; | 285 | return; | ||
245 | } | 286 | } | ||
246 | if (w->data(grabRole).value<void*>() != this) { | 287 | | ||
247 | windows.remove(w); | 288 | if (w->isDeleted() && role == WindowClosedGrabRole) { | ||
248 | w->setData(IsGlideWindow, false); | 289 | w->unrefWindow(); | ||
249 | } | 290 | } | ||
291 | | ||||
292 | m_animations.erase(animationIt); | ||||
250 | } | 293 | } | ||
251 | 294 | | |||
252 | GlideEffect::WindowInfo::WindowInfo() | 295 | bool GlideEffect::isGlideWindow(EffectWindow *w) const | ||
253 | : deleted(false) | | |||
254 | , added(false) | | |||
255 | , closed(false) | | |||
256 | , timeLine(0) | | |||
257 | { | 296 | { | ||
297 | if (s_blacklist.contains(w->windowClass())) { | ||||
298 | return false; | ||||
258 | } | 299 | } | ||
259 | 300 | | |||
260 | GlideEffect::WindowInfo::~WindowInfo() | 301 | if (w->hasDecoration()) { | ||
261 | { | 302 | return true; | ||
262 | delete timeLine; | 303 | } | ||
304 | | ||||
305 | if (!w->isManaged()) { | ||||
306 | return false; | ||||
307 | } | ||||
308 | | ||||
309 | return w->isNormalWindow() | ||||
310 | || w->isDialog(); | ||||
263 | } | 311 | } | ||
264 | 312 | | |||
265 | } // namespace | 313 | } // namespace KWin |