KWin
Loading...
Searching...
No Matches
motionmanager.cpp
Go to the documentation of this file.
1/*
2 SPDX-FileCopyrightText: 2006 Lubos Lunak <l.lunak@kde.org>
3 SPDX-FileCopyrightText: 2009 Lucas Murray <lmurray@undefinedfire.com>
4 SPDX-FileCopyrightText: 2010, 2011 Martin Gräßlin <mgraesslin@kde.org>
5
6 SPDX-License-Identifier: GPL-2.0-or-later
7*/
8
10
11namespace KWin
12{
13
14/***************************************************************
15 Motion1D
16***************************************************************/
17
18Motion1D::Motion1D(double initial, double strength, double smoothness)
19 : Motion<double>(initial, strength, smoothness)
20{
21}
22
24 : Motion<double>(other)
25{
26}
27
31
32/***************************************************************
33 Motion2D
34***************************************************************/
35
36Motion2D::Motion2D(QPointF initial, double strength, double smoothness)
37 : Motion<QPointF>(initial, strength, smoothness)
38{
39}
40
42 : Motion<QPointF>(other)
43{
44}
45
49
50/***************************************************************
51 WindowMotionManager
52***************************************************************/
53
54WindowMotionManager::WindowMotionManager(bool useGlobalAnimationModifier)
55 : m_useGlobalAnimationModifier(useGlobalAnimationModifier)
56
57{
58 // TODO: Allow developer to modify motion attributes
59} // TODO: What happens when the window moves by an external force?
60
64
66{
67 if (m_managedWindows.contains(w)) {
68 return;
69 }
70
71 double strength = 0.08;
72 double smoothness = 4.0;
73 if (m_useGlobalAnimationModifier && effects->animationTimeFactor()) {
74 // If the factor is == 0 then we just skip the calculation completely
75 strength = 0.08 / effects->animationTimeFactor();
76 smoothness = effects->animationTimeFactor() * 4.0;
77 }
78
79 WindowMotion &motion = m_managedWindows[w];
80 motion.translation.setStrength(strength);
81 motion.translation.setSmoothness(smoothness);
82 motion.scale.setStrength(strength * 1.33);
83 motion.scale.setSmoothness(smoothness / 2.0);
84
85 motion.translation.setValue(w->pos());
86 motion.scale.setValue(QPointF(1.0, 1.0));
87}
88
90{
91 m_movingWindowsSet.remove(w);
92 m_managedWindows.remove(w);
93}
94
96{
97 m_managedWindows.clear();
98 m_movingWindowsSet.clear();
99}
100
102{
104 // Just skip it completely if the user wants no animation
105 m_movingWindowsSet.clear();
106 QHash<EffectWindow *, WindowMotion>::iterator it = m_managedWindows.begin();
107 for (; it != m_managedWindows.end(); ++it) {
108 WindowMotion *motion = &it.value();
109 motion->translation.finish();
110 motion->scale.finish();
111 }
112 }
113
114 QHash<EffectWindow *, WindowMotion>::iterator it = m_managedWindows.begin();
115 for (; it != m_managedWindows.end(); ++it) {
116 WindowMotion *motion = &it.value();
117 int stopped = 0;
118
119 // TODO: What happens when distance() == 0 but we are still moving fast?
120 // TODO: Motion needs to be calculated from the window's center
121
122 Motion2D *trans = &motion->translation;
123 if (trans->distance().isNull()) {
124 ++stopped;
125 } else {
126 // Still moving
127 trans->calculate(time);
128 const short fx = trans->target().x() <= trans->startValue().x() ? -1 : 1;
129 const short fy = trans->target().y() <= trans->startValue().y() ? -1 : 1;
130 if (trans->distance().x() * fx / 0.5 < 1.0 && trans->velocity().x() * fx / 0.2 < 1.0
131 && trans->distance().y() * fy / 0.5 < 1.0 && trans->velocity().y() * fy / 0.2 < 1.0) {
132 // Hide tiny oscillations
133 motion->translation.finish();
134 ++stopped;
135 }
136 }
137
138 Motion2D *scale = &motion->scale;
139 if (scale->distance().isNull()) {
140 ++stopped;
141 } else {
142 // Still scaling
143 scale->calculate(time);
144 const short fx = scale->target().x() < 1.0 ? -1 : 1;
145 const short fy = scale->target().y() < 1.0 ? -1 : 1;
146 if (scale->distance().x() * fx / 0.001 < 1.0 && scale->velocity().x() * fx / 0.05 < 1.0
147 && scale->distance().y() * fy / 0.001 < 1.0 && scale->velocity().y() * fy / 0.05 < 1.0) {
148 // Hide tiny oscillations
149 motion->scale.finish();
150 ++stopped;
151 }
152 }
153
154 // We just finished this window's motion
155 if (stopped == 2) {
156 m_movingWindowsSet.remove(it.key());
157 }
158 }
159}
160
162{
163 QHash<EffectWindow *, WindowMotion>::iterator it = m_managedWindows.begin();
164 for (; it != m_managedWindows.end(); ++it) {
165 WindowMotion *motion = &it.value();
166 EffectWindow *window = it.key();
167 motion->translation.setTarget(window->pos());
168 motion->translation.finish();
169 motion->scale.setTarget(QPointF(1.0, 1.0));
170 motion->scale.finish();
171 }
172}
173
175{
176 QHash<EffectWindow *, WindowMotion>::iterator it = m_managedWindows.find(w);
177 if (it == m_managedWindows.end()) {
178 return;
179 }
180
181 WindowMotion *motion = &it.value();
182 motion->translation.setTarget(w->pos());
183 motion->translation.finish();
184 motion->scale.setTarget(QPointF(1.0, 1.0));
185 motion->scale.finish();
186}
187
189{
190 QHash<EffectWindow *, WindowMotion>::iterator it = m_managedWindows.find(w);
191 if (it == m_managedWindows.end()) {
192 return;
193 }
194
195 // TODO: Take into account existing scale so that we can work with multiple managers (E.g. Present windows + grid)
196 WindowMotion *motion = &it.value();
197 data += (motion->translation.value() - QPointF(w->x(), w->y()));
198 data *= QVector2D(motion->scale.value());
199}
200
201void WindowMotionManager::moveWindow(EffectWindow *w, QPoint target, double scale, double yScale)
202{
203 QHash<EffectWindow *, WindowMotion>::iterator it = m_managedWindows.find(w);
204 Q_ASSERT(it != m_managedWindows.end()); // Notify the effect author that they did something wrong
205
206 WindowMotion *motion = &it.value();
207
208 if (yScale == 0.0) {
209 yScale = scale;
210 }
211 QPointF scalePoint(scale, yScale);
212
213 if (motion->translation.value() == target && motion->scale.value() == scalePoint) {
214 return; // Window already at that position
215 }
216
217 motion->translation.setTarget(target);
218 motion->scale.setTarget(scalePoint);
219
220 m_movingWindowsSet << w;
221}
222
224{
225 QHash<EffectWindow *, WindowMotion>::const_iterator it = m_managedWindows.constFind(w);
226 if (it == m_managedWindows.end()) {
227 return w->frameGeometry();
228 }
229
230 const WindowMotion *motion = &it.value();
231 QRectF geometry(w->frameGeometry());
232
233 // TODO: Take into account existing scale so that we can work with multiple managers (E.g. Present windows + grid)
234 geometry.moveTo(motion->translation.value());
235 geometry.setWidth(geometry.width() * motion->scale.value().x());
236 geometry.setHeight(geometry.height() * motion->scale.value().y());
237
238 return geometry;
239}
240
242{
243 QHash<EffectWindow *, WindowMotion>::iterator it = m_managedWindows.find(w);
244 if (it == m_managedWindows.end()) {
245 return;
246 }
247 WindowMotion *motion = &it.value();
248 motion->translation.setValue(geometry.topLeft());
249 motion->scale.setValue(QPointF(geometry.width() / qreal(w->width()), geometry.height() / qreal(w->height())));
250}
251
253{
254 QHash<EffectWindow *, WindowMotion>::const_iterator it = m_managedWindows.constFind(w);
255 if (it == m_managedWindows.end()) {
256 return w->frameGeometry();
257 }
258
259 const WindowMotion *motion = &it.value();
260 QRectF geometry(w->frameGeometry());
261
262 // TODO: Take into account existing scale so that we can work with multiple managers (E.g. Present windows + grid)
263 geometry.moveTo(motion->translation.target());
264 geometry.setWidth(geometry.width() * motion->scale.target().x());
265 geometry.setHeight(geometry.height() * motion->scale.target().y());
266
267 return geometry;
268}
269
270EffectWindow *WindowMotionManager::windowAtPoint(QPoint point, bool useStackingOrder) const
271{
272 // TODO: Stacking order uses EffectsHandler::stackingOrder() then filters by m_managedWindows
273 QHash<EffectWindow *, WindowMotion>::ConstIterator it = m_managedWindows.constBegin();
274 while (it != m_managedWindows.constEnd()) {
275 if (exclusiveContains(transformedGeometry(it.key()), point)) {
276 return it.key();
277 }
278 ++it;
279 }
280
281 return nullptr;
282}
283
284} // namespace KWin
Representation of a window used by/for Effect classes.
QRectF frameGeometry() const
A single 1D motion dynamics object.
Motion1D(double initial=0.0, double strength=0.08, double smoothness=4.0)
A single 2D motion dynamics object.
Motion2D(QPointF initial=QPointF(), double strength=0.08, double smoothness=4.0)
T velocity() const
void setTarget(const T target)
void setSmoothness(const double smoothness)
void calculate(const int msec)
T target() const
void setStrength(const double strength)
T value() const
void setValue(const T value)
T distance() const
EffectWindow * windowAtPoint(QPoint point, bool useStackingOrder=true) const
WindowMotionManager(bool useGlobalAnimationModifier=true)
void unmanage(EffectWindow *w)
void manage(EffectWindow *w)
QRectF targetGeometry(EffectWindow *w) const
void apply(EffectWindow *w, WindowPaintData &data)
void moveWindow(EffectWindow *w, QPoint target, double scale=1.0, double yScale=0.0)
QRectF transformedGeometry(EffectWindow *w) const
void setTransformedGeometry(EffectWindow *w, const QRectF &geometry)
EffectsHandler * effects