1 /*****************************************************************
2 KWin - the KDE window manager
3 This file is part of the KDE project.
5 Copyright (C) 2008 Cédric Borgese <cedric.borgese@gmail.com>
7 You can Freely distribute this program under the GNU General Public
8 License. See the file "COPYING" for the exact licensing terms.
9 ******************************************************************/
12 #include "wobblywindows.h"
15 #include <kconfiggroup.h>
20 #define ASSERT1 assert
25 //#define COMPUTE_STATS
27 // if you enable it and run kwin in a terminal from the session it manages,
28 // be sure to redirect the output of kwin in a file or
29 // you'll propably get deadlocks.
30 //#define VERBOSE_MODE
32 #if defined COMPUTE_STATS && !defined VERBOSE_MODE
34 # warning "You enable COMPUTE_STATS without VERBOSE_MODE, computed stats will not be printed."
41 static const qreal STIFFNESS
= 0.15;
42 static const qreal DRAG
= 0.80;
43 static const qreal MOVEFACTOR
= 0.10;
45 static const int XTESSELATION
= 20;
46 static const int YTESSELATION
= 20;
48 static const qreal MINVELOCITY
= 0.0;
49 static const qreal MAXVELOCITY
= 1000.0;
50 static const qreal STOPVELOCITY
= 0.5;
51 static const qreal MINACCELERATION
= 0.0;
52 static const qreal MAXACCELERATION
= 1000.0;
53 static const qreal STOPACCELERATION
= 5.0;
67 qreal minAcceleration
;
68 qreal maxAcceleration
;
69 qreal stopAcceleration
;
71 bool moveEffectEnabled
;
72 bool openEffectEnabled
;
73 bool closeEffectEnabled
;
76 static const ParameterSet set_0
=
94 static const ParameterSet set_1
=
112 static const ParameterSet set_2
=
130 static const ParameterSet set_3
=
148 static const ParameterSet set_4
=
166 static const ParameterSet pset
[5] = { set_0
, set_1
, set_2
, set_3
, set_4
};
168 KWIN_EFFECT(wobblywindows
, WobblyWindowsEffect
)
170 WobblyWindowsEffect::WobblyWindowsEffect()
172 reconfigure( ReconfigureAll
);
175 WobblyWindowsEffect::~WobblyWindowsEffect()
177 if (!windows
.empty())
179 // we should be empty at this point...
180 // emit a warning and clean the list.
181 kDebug(1212) << "Windows list not empty. Left items : " << windows
.count();
182 QHash
< const EffectWindow
*, WindowWobblyInfos
>::iterator i
;
183 for (i
= windows
.begin(); i
!= windows
.end(); ++i
)
185 freeWobblyInfo(i
.value());
190 void WobblyWindowsEffect::reconfigure( ReconfigureFlags
)
192 KConfigGroup conf
= effects
->effectConfig("Wobbly");
195 QString settingsMode
= conf
.readEntry("Settings", "Auto");
196 if (settingsMode
!= "Custom")
198 unsigned int wobblynessLevel
= conf
.readEntry("WobblynessLevel", 0);
199 if (wobblynessLevel
> 4)
201 kDebug(1212) << "Wrong value for \"WobblynessLevel\" : " << wobblynessLevel
;
204 setParameterSet(pset
[wobblynessLevel
]);
206 if (conf
.readEntry("AdvancedMode", false))
208 m_stiffness
= conf
.readEntry("Stiffness", STIFFNESS
* 100.0) / 100.0;
209 m_drag
= conf
.readEntry("Drag", DRAG
* 100.0) / 100.0;
210 m_move_factor
= conf
.readEntry("MoveFactor", MOVEFACTOR
* 100.0) / 100.0;
213 else // Custom method, read all values from config file.
215 m_stiffness
= conf
.readEntry("Stiffness", STIFFNESS
);
216 m_drag
= conf
.readEntry("Drag", DRAG
);
217 m_move_factor
= conf
.readEntry("MoveFactor", MOVEFACTOR
);
219 m_xTesselation
= conf
.readEntry("XTesselation", XTESSELATION
);
220 m_yTesselation
= conf
.readEntry("YTesselation", YTESSELATION
);
222 m_minVelocity
= conf
.readEntry("MinVelocity", MINVELOCITY
);
223 m_maxVelocity
= conf
.readEntry("MaxVelocity", MAXVELOCITY
);
224 m_stopVelocity
= conf
.readEntry("StopVelocity", STOPVELOCITY
);
225 m_minAcceleration
= conf
.readEntry("MinAcceleration", MINACCELERATION
);
226 m_maxAcceleration
= conf
.readEntry("MaxAcceleration", MAXACCELERATION
);
227 m_stopAcceleration
= conf
.readEntry("StopAcceleration", STOPACCELERATION
);
229 m_moveEffectEnabled
= conf
.readEntry("MoveEffect", true);
230 m_openEffectEnabled
= conf
.readEntry("OpenEffect", false);
231 // disable close effect by default for now as it doesn't do what I want.
232 m_closeEffectEnabled
= conf
.readEntry("CloseEffect", false);
235 m_moveWobble
= conf
.readEntry("MoveWobble", true);
236 m_resizeWobble
= conf
.readEntry("ResizeWobble", true);
238 #if defined VERBOSE_MODE
239 kDebug(1212) << "Parameters :\n" <<
240 "move : " << m_moveEffectEnabled
<< ", open : " << m_openEffectEnabled
<< ", close : " << m_closeEffectEnabled
<< "\n"
241 "grid(" << m_stiffness
<< ", " << m_drag
<< ", " << m_move_factor
<< ")\n" <<
242 "velocity(" << m_minVelocity
<< ", " << m_maxVelocity
<< ", " << m_stopVelocity
<< ")\n" <<
243 "acceleration(" << m_minAcceleration
<< ", " << m_maxAcceleration
<< ", " << m_stopAcceleration
<< ")\n" <<
244 "tesselation(" << m_xTesselation
<< ", " << m_yTesselation
<< ")";
249 void WobblyWindowsEffect::setParameterSet(const ParameterSet
& pset
)
251 m_stiffness
= pset
.stiffness
;
253 m_move_factor
= pset
.move_factor
;
255 m_xTesselation
= pset
.xTesselation
;
256 m_yTesselation
= pset
.yTesselation
;
258 m_minVelocity
= pset
.minVelocity
;
259 m_maxVelocity
= pset
.maxVelocity
;
260 m_stopVelocity
= pset
.stopVelocity
;
261 m_minAcceleration
= pset
.minAcceleration
;
262 m_maxAcceleration
= pset
.maxAcceleration
;
263 m_stopAcceleration
= pset
.stopAcceleration
;
265 m_moveEffectEnabled
= pset
.moveEffectEnabled
;
266 m_openEffectEnabled
= pset
.openEffectEnabled
;
267 m_closeEffectEnabled
= pset
.closeEffectEnabled
;
270 void WobblyWindowsEffect::setVelocityThreshold(qreal m_minVelocity
)
272 this->m_minVelocity
= m_minVelocity
;
275 void WobblyWindowsEffect::setMoveFactor(qreal factor
)
277 m_move_factor
= factor
;
280 void WobblyWindowsEffect::setStiffness(qreal stiffness
)
282 m_stiffness
= stiffness
;
285 void WobblyWindowsEffect::setDrag(qreal drag
)
290 void WobblyWindowsEffect::prePaintScreen(ScreenPrePaintData
& data
, int time
)
292 // We need to mark the screen windows as transformed. Otherwise the whole
293 // screen won't be repainted, resulting in artefacts.
294 // Could we just set a subset of the screen to be repainted ?
295 if (windows
.count() != 0)
297 data
.mask
|= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS
;
300 // this set the QRect invalid.
301 m_updateRegion
.setWidth(0);
303 effects
->prePaintScreen(data
, time
);
305 const qreal maxTime
= 10.0;
306 void WobblyWindowsEffect::prePaintWindow(EffectWindow
* w
, WindowPrePaintData
& data
, int time
)
308 if (windows
.contains(w
))
310 data
.setTransformed();
311 data
.quads
= data
.quads
.makeRegularGrid(m_xTesselation
, m_yTesselation
);
313 qreal updateTime
= time
;
315 while (!stop
&& (updateTime
> maxTime
))
317 #if defined VERBOSE_MODE
318 kDebug(1212) << "loop time " << updateTime
<< " / " << time
;
320 stop
= !updateWindowWobblyDatas(w
, maxTime
);
321 updateTime
-= maxTime
;
323 if (!stop
&& updateTime
> 0)
325 updateWindowWobblyDatas(w
, updateTime
);
329 effects
->prePaintWindow(w
, data
, time
);
332 void WobblyWindowsEffect::paintWindow(EffectWindow
* w
, int mask
, QRegion region
, WindowPaintData
& data
)
334 if(windows
.contains(w
))
336 WindowWobblyInfos
& wwi
= windows
[w
];
337 int tx
= w
->geometry().x();
338 int ty
= w
->geometry().y();
339 for (int i
= 0; i
< data
.quads
.count(); ++i
)
341 for(int j
= 0; j
< 4; ++j
)
343 WindowVertex
& v
= data
.quads
[i
][j
];
344 Pair oldPos
= {tx
+ v
.x(), ty
+ v
.y()};
345 Pair newPos
= computeBezierPoint(wwi
, oldPos
);
346 v
.move(newPos
.x
- tx
, newPos
.y
- ty
);
351 // Call the next effect.
352 effects
->paintWindow(w
, mask
, region
, data
);
355 void WobblyWindowsEffect::postPaintScreen()
357 if (!windows
.isEmpty())
359 effects
->addRepaint(m_updateRegion
);
362 // Call the next effect.
363 effects
->postPaintScreen();
366 void WobblyWindowsEffect::windowUserMovedResized(EffectWindow
* w
, bool first
, bool last
)
368 if (m_moveEffectEnabled
&& first
&& !w
->isSpecialWindow() &&
369 ((w
->isUserMove() && m_moveWobble
) || (w
->isUserResize() && m_resizeWobble
)))
371 if (!windows
.contains(w
))
373 WindowWobblyInfos new_wwi
;
374 initWobblyInfo(new_wwi
, w
->geometry());
375 windows
[w
] = new_wwi
;
378 WindowWobblyInfos
& wwi
= windows
[w
];
380 const QRectF
& rect
= w
->geometry();
382 qreal x_increment
= rect
.width() / (wwi
.width
-1.0);
383 qreal y_increment
= rect
.height() / (wwi
.height
-1.0);
385 Pair picked
= {cursorPos().x(), cursorPos().y()};
386 int indx
= (picked
.x
- rect
.x()) / x_increment
;
387 int indy
= (picked
.y
- rect
.y()) / y_increment
;
388 int pickedPointIndex
= indy
*wwi
.width
+ indx
;
389 if (pickedPointIndex
< 0)
391 kDebug(1212) << "Picked index == " << pickedPointIndex
<< " with (" << cursorPos().x() << "," << cursorPos().y() << ")";
392 pickedPointIndex
= 0;
394 else if (static_cast<unsigned int>(pickedPointIndex
) > wwi
.count
- 1)
396 kDebug(1212) << "Picked index == " << pickedPointIndex
<< " with (" << cursorPos().x() << "," << cursorPos().y() << ")";
397 pickedPointIndex
= wwi
.count
- 1;
399 #if defined VERBOSE_MODE
400 kDebug(1212) << "Original Picked point -- x : " << picked
.x
<< " - y : " << picked
.y
;
402 wwi
.constraint
[pickedPointIndex
] = true;
404 if (w
->isUserResize())
406 if (picked
.x
> rect
.center().x())
407 if (picked
.y
> rect
.center().y())
408 // picked somewhere in the bottom right, so constrain the top left corner too
409 wwi
.locked
[0] = wwi
.constraint
[0] = true;
411 wwi
.locked
[wwi
.count
-wwi
.width
] = wwi
.constraint
[wwi
.count
-wwi
.width
] = true;
413 if (picked
.y
> rect
.center().y())
414 wwi
.locked
[wwi
.width
-1] = wwi
.constraint
[wwi
.width
-1] = true;
416 wwi
.locked
[wwi
.count
-1] = wwi
.constraint
[wwi
.count
-1] = true;
419 else if (m_moveEffectEnabled
&& last
)
421 if (windows
.contains(w
))
423 WindowWobblyInfos
& wwi
= windows
[w
];
429 void WobblyWindowsEffect::windowAdded(EffectWindow
* w
)
431 if (m_openEffectEnabled
)
433 if(windows
.contains(w
))
435 // could this happen ??
436 WindowWobblyInfos
& wwi
= windows
[w
];
441 WindowWobblyInfos new_wwi
;
442 initWobblyInfo(new_wwi
, w
->geometry());
443 wobblyOpenInit(new_wwi
);
444 windows
[w
] = new_wwi
;
449 void WobblyWindowsEffect::windowClosed(EffectWindow
* w
)
451 if(windows
.contains(w
))
453 WindowWobblyInfos
& wwi
= windows
[w
];
454 if (m_closeEffectEnabled
)
456 wobblyCloseInit(wwi
, w
);
465 else if (m_closeEffectEnabled
)
467 WindowWobblyInfos new_wwi
;
468 initWobblyInfo(new_wwi
, w
->geometry());
469 wobblyCloseInit(new_wwi
, w
);
470 windows
[w
] = new_wwi
;
475 void WobblyWindowsEffect::wobblyOpenInit(WindowWobblyInfos
& wwi
) const
477 Pair middle
= { (wwi
.origin
[0].x
+ wwi
.origin
[15].x
)/2, (wwi
.origin
[0].y
+ wwi
.origin
[15].y
)/2 };
479 for (unsigned int j
=0; j
<4; ++j
)
481 for (unsigned int i
=0; i
<4; ++i
)
483 unsigned int idx
= j
*4 + i
;
484 wwi
.constraint
[idx
] = false;
485 wwi
.locked
[idx
] = false;
486 wwi
.position
[idx
].x
= (wwi
.position
[idx
].x
+ 3*middle
.x
)/4;
487 wwi
.position
[idx
].y
= (wwi
.position
[idx
].y
+ 3*middle
.y
)/4;
490 wwi
.status
= Openning
;
493 void WobblyWindowsEffect::wobblyCloseInit(WindowWobblyInfos
& wwi
, EffectWindow
* w
) const
495 const QRectF
& rect
= w
->geometry();
496 QPointF center
= rect
.center();
497 int x1
= (rect
.x() + 3*center
.x())/4;
498 int x2
= (rect
.x() + rect
.width() + 3*center
.x())/4;
499 int y1
= (rect
.y() + 3*center
.y())/4;
500 int y2
= (rect
.y() + rect
.height() + 3*center
.y())/4;
501 wwi
.closeRect
.setCoords(x1
, y1
, x2
, y2
);
503 // for closing, not yet used...
504 for (unsigned int j
=0; j
<4; ++j
)
506 for (unsigned int i
=0; i
<4; ++i
)
508 unsigned int idx
= j
*4 + i
;
509 wwi
.constraint
[idx
] = false;
510 wwi
.locked
[idx
] = false;
513 wwi
.status
= Closing
;
516 void WobblyWindowsEffect::initWobblyInfo(WindowWobblyInfos
& wwi
, QRect geometry
) const
522 wwi
.bezierWidth
= m_xTesselation
;
523 wwi
.bezierHeight
= m_yTesselation
;
524 wwi
.bezierCount
= m_xTesselation
* m_yTesselation
;
526 wwi
.origin
= new Pair
[wwi
.count
];
527 wwi
.position
= new Pair
[wwi
.count
];
528 wwi
.velocity
= new Pair
[wwi
.count
];
529 wwi
.acceleration
= new Pair
[wwi
.count
];
530 wwi
.buffer
= new Pair
[wwi
.count
];
531 wwi
.constraint
= new bool[wwi
.count
];
532 wwi
.locked
= new bool[wwi
.count
];
534 wwi
.bezierSurface
= new Pair
[wwi
.bezierCount
];
538 qreal x
= geometry
.x(), y
= geometry
.y();
539 qreal width
= geometry
.width(), height
= geometry
.height();
541 Pair initValue
= {x
, y
};
542 static const Pair nullPair
= {0.0, 0.0};
544 qreal x_increment
= width
/ (wwi
.width
-1.0);
545 qreal y_increment
= height
/ (wwi
.height
-1.0);
547 for (unsigned int j
=0; j
<4; ++j
)
549 for (unsigned int i
=0; i
<4; ++i
)
551 unsigned int idx
= j
*4 + i
;
552 wwi
.origin
[idx
] = initValue
;
553 wwi
.position
[idx
] = initValue
;
554 wwi
.velocity
[idx
] = nullPair
;
555 wwi
.constraint
[idx
] = false;
556 wwi
.locked
[idx
] = false;
557 if (i
!= 4-2) // x grid count - 2, i.e. not the last point
559 initValue
.x
+= x_increment
;
563 initValue
.x
= width
+ x
;
565 initValue
.x
= initValue
.x
;
568 initValue
.x
= initValue
.x
;
569 if (j
!= 4-2) // y grid count - 2, i.e. not the last point
571 initValue
.y
+= y_increment
;
575 initValue
.y
= height
+ y
;
577 initValue
.y
= initValue
.y
;
581 void WobblyWindowsEffect::freeWobblyInfo(WindowWobblyInfos
& wwi
) const
584 delete[] wwi
.position
;
585 delete[] wwi
.velocity
;
586 delete[] wwi
.acceleration
;
588 delete[] wwi
.constraint
;
591 delete[] wwi
.bezierSurface
;
594 WobblyWindowsEffect::Pair
WobblyWindowsEffect::computeBezierPoint(const WindowWobblyInfos
& wwi
, Pair point
) const
596 // compute the input value
597 Pair topleft
= wwi
.origin
[0];
598 Pair bottomright
= wwi
.origin
[wwi
.count
-1];
600 // ASSERT1(point.x >= topleft.x);
601 // ASSERT1(point.y >= topleft.y);
602 // ASSERT1(point.x <= bottomright.x);
603 // ASSERT1(point.y <= bottomright.y);
605 qreal tx
= (point
.x
- topleft
.x
) / (bottomright
.x
- topleft
.x
);
606 qreal ty
= (point
.y
- topleft
.y
) / (bottomright
.y
- topleft
.y
);
613 // compute polynomial coeff
616 px
[0] = (1-tx
)*(1-tx
)*(1-tx
);
617 px
[1] = 3*(1-tx
)*(1-tx
)*tx
;
618 px
[2] = 3*(1-tx
)*tx
*tx
;
622 py
[0] = (1-ty
)*(1-ty
)*(1-ty
);
623 py
[1] = 3*(1-ty
)*(1-ty
)*ty
;
624 py
[2] = 3*(1-ty
)*ty
*ty
;
627 Pair res
= {0.0, 0.0};
629 for (unsigned int j
= 0; j
< 4; ++j
)
631 for (unsigned int i
= 0; i
< 4; ++i
)
633 // this assume the grid is 4*4
634 res
.x
+= px
[i
] * py
[j
] * wwi
.position
[i
+ j
* wwi
.width
].x
;
635 res
.y
+= px
[i
] * py
[j
] * wwi
.position
[i
+ j
* wwi
.width
].y
;
645 static inline void fixVectorBounds(WobblyWindowsEffect::Pair
& vec
, qreal min
, qreal max
)
647 if (fabs(vec
.x
) < min
)
651 else if (fabs(vec
.x
) > max
)
663 if (fabs(vec
.y
) < min
)
667 else if (fabs(vec
.y
) > max
)
680 static inline void computeVectorBounds(WobblyWindowsEffect::Pair
& vec
, WobblyWindowsEffect::Pair
& bound
)
682 if (fabs(vec
.x
) < bound
.x
)
684 bound
.x
= fabs(vec
.x
);
686 else if (fabs(vec
.x
) > bound
.y
)
688 bound
.y
= fabs(vec
.x
);
690 if (fabs(vec
.y
) < bound
.x
)
692 bound
.x
= fabs(vec
.y
);
694 else if (fabs(vec
.y
) > bound
.y
)
696 bound
.y
= fabs(vec
.y
);
700 } // close the anonymous namespace
702 bool WobblyWindowsEffect::updateWindowWobblyDatas(EffectWindow
* w
, qreal time
)
704 QRectF rect
= w
->geometry();
705 WindowWobblyInfos
& wwi
= windows
[w
];
707 if (wwi
.status
== Closing
)
709 rect
= wwi
.closeRect
;
712 qreal x_length
= rect
.width() / (wwi
.width
-1.0);
713 qreal y_length
= rect
.height() / (wwi
.height
-1.0);
715 #if defined VERBOSE_MODE
716 kDebug(1212) << "time " << time
;
717 kDebug(1212) << "increment x " << x_length
<< " // y" << y_length
;
720 Pair origine
= {rect
.x(), rect
.y()};
722 for (unsigned int j
=0; j
<wwi
.height
; ++j
)
724 for (unsigned int i
=0; i
<wwi
.width
; ++i
)
726 wwi
.origin
[wwi
.width
*j
+ i
] = origine
;
727 if (i
!= wwi
.width
-2)
729 origine
.x
+= x_length
;
733 origine
.x
= rect
.width() + rect
.x();
736 origine
.x
= rect
.x();
737 if (j
!= wwi
.height
-2)
739 origine
.y
+= y_length
;
743 origine
.y
= rect
.height() + rect
.y();
753 // compute acceleration, velocity and position for each point
759 if (wwi
.constraint
[0])
761 Pair window_pos
= wwi
.origin
[0];
762 Pair current_pos
= wwi
.position
[0];
763 Pair move
= {window_pos
.x
- current_pos
.x
, window_pos
.y
- current_pos
.y
};
764 Pair accel
= {move
.x
*m_stiffness
, move
.y
*m_stiffness
};
765 wwi
.acceleration
[0] = accel
;
769 Pair
& pos
= wwi
.position
[0];
770 neibourgs
[0] = wwi
.position
[1];
771 neibourgs
[1] = wwi
.position
[wwi
.width
];
773 acceleration
.x
= ((neibourgs
[0].x
- pos
.x
) - x_length
)*m_stiffness
+ (neibourgs
[1].x
- pos
.x
)*m_stiffness
;
774 acceleration
.y
= ((neibourgs
[1].y
- pos
.y
) - y_length
)*m_stiffness
+ (neibourgs
[0].y
- pos
.y
)*m_stiffness
;
779 wwi
.acceleration
[0] = acceleration
;
784 if (wwi
.constraint
[wwi
.width
-1])
786 Pair window_pos
= wwi
.origin
[wwi
.width
-1];
787 Pair current_pos
= wwi
.position
[wwi
.width
-1];
788 Pair move
= {window_pos
.x
- current_pos
.x
, window_pos
.y
- current_pos
.y
};
789 Pair accel
= {move
.x
*m_stiffness
, move
.y
*m_stiffness
};
790 wwi
.acceleration
[wwi
.width
-1] = accel
;
794 Pair
& pos
= wwi
.position
[wwi
.width
-1];
795 neibourgs
[0] = wwi
.position
[wwi
.width
-2];
796 neibourgs
[1] = wwi
.position
[2*wwi
.width
-1];
798 acceleration
.x
= (x_length
- (pos
.x
- neibourgs
[0].x
))*m_stiffness
+ (neibourgs
[1].x
- pos
.x
)*m_stiffness
;
799 acceleration
.y
= ((neibourgs
[1].y
- pos
.y
) - y_length
)*m_stiffness
+ (neibourgs
[0].y
- pos
.y
)*m_stiffness
;
804 wwi
.acceleration
[wwi
.width
-1] = acceleration
;
809 if (wwi
.constraint
[wwi
.width
*(wwi
.height
-1)])
811 Pair window_pos
= wwi
.origin
[wwi
.width
*(wwi
.height
-1)];
812 Pair current_pos
= wwi
.position
[wwi
.width
*(wwi
.height
-1)];
813 Pair move
= {window_pos
.x
- current_pos
.x
, window_pos
.y
- current_pos
.y
};
814 Pair accel
= {move
.x
*m_stiffness
, move
.y
*m_stiffness
};
815 wwi
.acceleration
[wwi
.width
*(wwi
.height
-1)] = accel
;
819 Pair
& pos
= wwi
.position
[wwi
.width
*(wwi
.height
-1)];
820 neibourgs
[0] = wwi
.position
[wwi
.width
*(wwi
.height
-1)+1];
821 neibourgs
[1] = wwi
.position
[wwi
.width
*(wwi
.height
-2)];
823 acceleration
.x
= ((neibourgs
[0].x
- pos
.x
) - x_length
)*m_stiffness
+ (neibourgs
[1].x
- pos
.x
)*m_stiffness
;
824 acceleration
.y
= (y_length
- (pos
.y
- neibourgs
[1].y
))*m_stiffness
+ (neibourgs
[0].y
- pos
.y
)*m_stiffness
;
829 wwi
.acceleration
[wwi
.width
*(wwi
.height
-1)] = acceleration
;
834 if (wwi
.constraint
[wwi
.count
-1])
836 Pair window_pos
= wwi
.origin
[wwi
.count
-1];
837 Pair current_pos
= wwi
.position
[wwi
.count
-1];
838 Pair move
= {window_pos
.x
- current_pos
.x
, window_pos
.y
- current_pos
.y
};
839 Pair accel
= {move
.x
*m_stiffness
, move
.y
*m_stiffness
};
840 wwi
.acceleration
[wwi
.count
-1] = accel
;
844 Pair
& pos
= wwi
.position
[wwi
.count
-1];
845 neibourgs
[0] = wwi
.position
[wwi
.count
-2];
846 neibourgs
[1] = wwi
.position
[wwi
.width
*(wwi
.height
-1)-1];
848 acceleration
.x
= (x_length
- (pos
.x
- neibourgs
[0].x
))*m_stiffness
+ (neibourgs
[1].x
- pos
.x
)*m_stiffness
;
849 acceleration
.y
= (y_length
- (pos
.y
- neibourgs
[1].y
))*m_stiffness
+ (neibourgs
[0].y
- pos
.y
)*m_stiffness
;
854 wwi
.acceleration
[wwi
.count
-1] = acceleration
;
861 for (unsigned int i
=1; i
<wwi
.width
-1; ++i
)
863 if (wwi
.constraint
[i
])
865 Pair window_pos
= wwi
.origin
[i
];
866 Pair current_pos
= wwi
.position
[i
];
867 Pair move
= {window_pos
.x
- current_pos
.x
, window_pos
.y
- current_pos
.y
};
868 Pair accel
= {move
.x
*m_stiffness
, move
.y
*m_stiffness
};
869 wwi
.acceleration
[i
] = accel
;
873 Pair
& pos
= wwi
.position
[i
];
874 neibourgs
[0] = wwi
.position
[i
-1];
875 neibourgs
[1] = wwi
.position
[i
+1];
876 neibourgs
[2] = wwi
.position
[i
+wwi
.width
];
878 acceleration
.x
= (x_length
- (pos
.x
- neibourgs
[0].x
))*m_stiffness
+ ((neibourgs
[1].x
- pos
.x
) - x_length
)*m_stiffness
+ (neibourgs
[2].x
- pos
.x
)*m_stiffness
;
879 acceleration
.y
= ((neibourgs
[2].y
- pos
.y
) - y_length
)*m_stiffness
+ (neibourgs
[0].y
- pos
.y
)*m_stiffness
+ (neibourgs
[1].y
- pos
.y
)*m_stiffness
;
884 wwi
.acceleration
[i
] = acceleration
;
889 for (unsigned int i
=wwi
.width
*(wwi
.height
-1)+1; i
<wwi
.count
-1; ++i
)
891 if (wwi
.constraint
[i
])
893 Pair window_pos
= wwi
.origin
[i
];
894 Pair current_pos
= wwi
.position
[i
];
895 Pair move
= {window_pos
.x
- current_pos
.x
, window_pos
.y
- current_pos
.y
};
896 Pair accel
= {move
.x
*m_stiffness
, move
.y
*m_stiffness
};
897 wwi
.acceleration
[i
] = accel
;
901 Pair
& pos
= wwi
.position
[i
];
902 neibourgs
[0] = wwi
.position
[i
-1];
903 neibourgs
[1] = wwi
.position
[i
+1];
904 neibourgs
[2] = wwi
.position
[i
-wwi
.width
];
906 acceleration
.x
= (x_length
- (pos
.x
- neibourgs
[0].x
))*m_stiffness
+ ((neibourgs
[1].x
- pos
.x
) - x_length
)*m_stiffness
+ (neibourgs
[2].x
- pos
.x
)*m_stiffness
;
907 acceleration
.y
= (y_length
- (pos
.y
- neibourgs
[2].y
))*m_stiffness
+ (neibourgs
[0].y
- pos
.y
)*m_stiffness
+ (neibourgs
[1].y
- pos
.y
)*m_stiffness
;
912 wwi
.acceleration
[i
] = acceleration
;
917 for (unsigned int i
=wwi
.width
; i
<wwi
.width
*(wwi
.height
-1); i
+=wwi
.width
)
919 if (wwi
.constraint
[i
])
921 Pair window_pos
= wwi
.origin
[i
];
922 Pair current_pos
= wwi
.position
[i
];
923 Pair move
= {window_pos
.x
- current_pos
.x
, window_pos
.y
- current_pos
.y
};
924 Pair accel
= {move
.x
*m_stiffness
, move
.y
*m_stiffness
};
925 wwi
.acceleration
[i
] = accel
;
929 Pair
& pos
= wwi
.position
[i
];
930 neibourgs
[0] = wwi
.position
[i
+1];
931 neibourgs
[1] = wwi
.position
[i
-wwi
.width
];
932 neibourgs
[2] = wwi
.position
[i
+wwi
.width
];
934 acceleration
.x
= ((neibourgs
[0].x
- pos
.x
) - x_length
)*m_stiffness
+ (neibourgs
[1].x
- pos
.x
)*m_stiffness
+ (neibourgs
[2].x
- pos
.x
)*m_stiffness
;
935 acceleration
.y
= (y_length
- (pos
.y
- neibourgs
[1].y
))*m_stiffness
+ ((neibourgs
[2].y
- pos
.y
) - y_length
)*m_stiffness
+ (neibourgs
[0].y
- pos
.y
)*m_stiffness
;
940 wwi
.acceleration
[i
] = acceleration
;
945 for (unsigned int i
=2*wwi
.width
-1; i
<wwi
.count
-1; i
+=wwi
.width
)
947 if (wwi
.constraint
[i
])
949 Pair window_pos
= wwi
.origin
[i
];
950 Pair current_pos
= wwi
.position
[i
];
951 Pair move
= {window_pos
.x
- current_pos
.x
, window_pos
.y
- current_pos
.y
};
952 Pair accel
= {move
.x
*m_stiffness
, move
.y
*m_stiffness
};
953 wwi
.acceleration
[i
] = accel
;
957 Pair
& pos
= wwi
.position
[i
];
958 neibourgs
[0] = wwi
.position
[i
-1];
959 neibourgs
[1] = wwi
.position
[i
-wwi
.width
];
960 neibourgs
[2] = wwi
.position
[i
+wwi
.width
];
962 acceleration
.x
= (x_length
- (pos
.x
- neibourgs
[0].x
))*m_stiffness
+ (neibourgs
[1].x
- pos
.x
)*m_stiffness
+ (neibourgs
[2].x
- pos
.x
)*m_stiffness
;
963 acceleration
.y
= (y_length
- (pos
.y
- neibourgs
[1].y
))*m_stiffness
+ ((neibourgs
[2].y
- pos
.y
) - y_length
)*m_stiffness
+ (neibourgs
[0].y
- pos
.y
)*m_stiffness
;
968 wwi
.acceleration
[i
] = acceleration
;
972 // for the inner points
973 for (unsigned int j
=1; j
<wwi
.height
-1; ++j
)
975 for (unsigned int i
=1; i
<wwi
.width
-1; ++i
)
977 unsigned int index
= i
+j
*wwi
.width
;
979 if (wwi
.constraint
[index
])
981 Pair window_pos
= wwi
.origin
[index
];
982 Pair current_pos
= wwi
.position
[index
];
983 Pair move
= {window_pos
.x
- current_pos
.x
, window_pos
.y
- current_pos
.y
};
984 Pair accel
= {move
.x
*m_stiffness
, move
.y
*m_stiffness
};
985 wwi
.acceleration
[index
] = accel
;
989 Pair
& pos
= wwi
.position
[index
];
990 neibourgs
[0] = wwi
.position
[index
-1];
991 neibourgs
[1] = wwi
.position
[index
+1];
992 neibourgs
[2] = wwi
.position
[index
-wwi
.width
];
993 neibourgs
[3] = wwi
.position
[index
+wwi
.width
];
995 acceleration
.x
= ((neibourgs
[0].x
- pos
.x
) - x_length
)*m_stiffness
+
996 (x_length
- (pos
.x
- neibourgs
[1].x
))*m_stiffness
+
997 (neibourgs
[2].x
- pos
.x
)*m_stiffness
+
998 (neibourgs
[3].x
- pos
.x
)*m_stiffness
;
999 acceleration
.y
= (y_length
- (pos
.y
- neibourgs
[2].y
))*m_stiffness
+
1000 ((neibourgs
[3].y
- pos
.y
) - y_length
)*m_stiffness
+
1001 (neibourgs
[0].y
- pos
.y
)*m_stiffness
+
1002 (neibourgs
[1].y
- pos
.y
)*m_stiffness
;
1004 acceleration
.x
/= 4;
1005 acceleration
.y
/= 4;
1007 wwi
.acceleration
[index
] = acceleration
;
1012 heightRingLinearMean(&wwi
.acceleration
, wwi
);
1014 #if defined COMPUTE_STATS
1015 Pair accBound
= {m_maxAcceleration
, m_minAcceleration
};
1016 Pair velBound
= {m_maxVelocity
, m_minVelocity
};
1019 // compute the new velocity of each vertex.
1020 for (unsigned int i
= 0; i
< wwi
.count
; ++i
)
1022 Pair acc
= wwi
.acceleration
[i
];
1023 fixVectorBounds(acc
, m_minAcceleration
, m_maxAcceleration
);
1025 #if defined COMPUTE_STATS
1026 computeVectorBounds(acc
, accBound
);
1029 Pair
& vel
= wwi
.velocity
[i
];
1030 vel
.x
= acc
.x
*time
+ vel
.x
*m_drag
;
1031 vel
.y
= acc
.y
*time
+ vel
.y
*m_drag
;
1033 acc_sum
+= fabs(acc
.x
) + fabs(acc
.y
);
1036 heightRingLinearMean(&wwi
.velocity
, wwi
);
1038 Pair topLeftCorner
= {-10000.0, -10000.0};
1039 Pair bottomRightCorner
= {10000.0, 10000.0};
1041 // compute the new pos of each vertex.
1042 for (unsigned int i
= 0; i
< wwi
.count
; ++i
)
1044 Pair
& pos
= wwi
.position
[i
];
1045 Pair
& vel
= wwi
.velocity
[i
];
1047 fixVectorBounds(vel
, m_minVelocity
, m_maxVelocity
);
1048 #if defined COMPUTE_STATS
1049 computeVectorBounds(vel
, velBound
);
1052 pos
.x
+= vel
.x
*time
*m_move_factor
;
1053 pos
.y
+= vel
.y
*time
*m_move_factor
;
1055 if (pos
.x
< topLeftCorner
.x
)
1057 topLeftCorner
.x
= pos
.x
;
1059 if (pos
.x
> bottomRightCorner
.x
)
1061 bottomRightCorner
.x
= pos
.x
;
1063 if (pos
.y
< topLeftCorner
.y
)
1065 topLeftCorner
.y
= pos
.y
;
1067 if (pos
.y
> bottomRightCorner
.y
)
1069 bottomRightCorner
.y
= pos
.y
;
1072 vel_sum
+= fabs(vel
.x
) + fabs(vel
.y
);
1076 wwi
.position
[i
] = wwi
.origin
[i
];
1078 #if defined VERBOSE_MODE
1079 if (wwi
.constraint
[i
])
1081 kDebug(1212) << "Constraint point ** vel : " << vel
.x
<< "," << vel
.y
<< " ** move : " << vel
.x
*time
<< "," << vel
.y
*time
;
1086 #if defined VERBOSE_MODE
1087 # if defined COMPUTE_STATS
1088 kDebug(1212) << "Acceleration bounds (" << accBound
.x
<< ", " << accBound
.y
<< ")";
1089 kDebug(1212) << "Velocity bounds (" << velBound
.x
<< ", " << velBound
.y
<< ")";
1091 kDebug(1212) << "sum_acc : " << acc_sum
<< " *** sum_vel :" << vel_sum
;
1094 if (wwi
.status
!= Moving
&& acc_sum
< m_stopAcceleration
&& vel_sum
< m_stopVelocity
)
1096 if (wwi
.status
== Closing
)
1100 freeWobblyInfo(wwi
);
1105 QRect
windowRect(topLeftCorner
.x
, topLeftCorner
.y
,
1106 bottomRightCorner
.x
- topLeftCorner
.x
, bottomRightCorner
.y
- topLeftCorner
.y
);
1107 if (m_updateRegion
.isValid())
1109 m_updateRegion
= m_updateRegion
.united(windowRect
);
1113 m_updateRegion
= windowRect
;
1119 void WobblyWindowsEffect::heightRingLinearMean(Pair
** datas_pointer
, WindowWobblyInfos
& wwi
)
1121 Pair
* datas
= *datas_pointer
;
1128 Pair
& res
= wwi
.buffer
[0];
1129 Pair vit
= datas
[0];
1130 neibourgs
[0] = datas
[1];
1131 neibourgs
[1] = datas
[wwi
.width
];
1132 neibourgs
[2] = datas
[wwi
.width
+1];
1134 res
.x
= (neibourgs
[0].x
+ neibourgs
[1].x
+ neibourgs
[2].x
+ 3.0*vit
.x
) / 6.0;
1135 res
.y
= (neibourgs
[0].y
+ neibourgs
[1].y
+ neibourgs
[2].y
+ 3.0*vit
.y
) / 6.0;
1141 Pair
& res
= wwi
.buffer
[wwi
.width
-1];
1142 Pair vit
= datas
[wwi
.width
-1];
1143 neibourgs
[0] = datas
[wwi
.width
-2];
1144 neibourgs
[1] = datas
[2*wwi
.width
-1];
1145 neibourgs
[2] = datas
[2*wwi
.width
-2];
1147 res
.x
= (neibourgs
[0].x
+ neibourgs
[1].x
+ neibourgs
[2].x
+ 3.0*vit
.x
) / 6.0;
1148 res
.y
= (neibourgs
[0].y
+ neibourgs
[1].y
+ neibourgs
[2].y
+ 3.0*vit
.y
) / 6.0;
1154 Pair
& res
= wwi
.buffer
[wwi
.width
*(wwi
.height
-1)];
1155 Pair vit
= datas
[wwi
.width
*(wwi
.height
-1)];
1156 neibourgs
[0] = datas
[wwi
.width
*(wwi
.height
-1)+1];
1157 neibourgs
[1] = datas
[wwi
.width
*(wwi
.height
-2)];
1158 neibourgs
[2] = datas
[wwi
.width
*(wwi
.height
-2)+1];
1160 res
.x
= (neibourgs
[0].x
+ neibourgs
[1].x
+ neibourgs
[2].x
+ 3.0*vit
.x
) / 6.0;
1161 res
.y
= (neibourgs
[0].y
+ neibourgs
[1].y
+ neibourgs
[2].y
+ 3.0*vit
.y
) / 6.0;
1167 Pair
& res
= wwi
.buffer
[wwi
.count
-1];
1168 Pair vit
= datas
[wwi
.count
-1];
1169 neibourgs
[0] = datas
[wwi
.count
-2];
1170 neibourgs
[1] = datas
[wwi
.width
*(wwi
.height
-1)-1];
1171 neibourgs
[2] = datas
[wwi
.width
*(wwi
.height
-1)-2];
1173 res
.x
= (neibourgs
[0].x
+ neibourgs
[1].x
+ neibourgs
[2].x
+ 3.0*vit
.x
) / 6.0;
1174 res
.y
= (neibourgs
[0].y
+ neibourgs
[1].y
+ neibourgs
[2].y
+ 3.0*vit
.y
) / 6.0;
1181 for (unsigned int i
=1; i
<wwi
.width
-1; ++i
)
1183 Pair
& res
= wwi
.buffer
[i
];
1184 Pair vit
= datas
[i
];
1185 neibourgs
[0] = datas
[i
-1];
1186 neibourgs
[1] = datas
[i
+1];
1187 neibourgs
[2] = datas
[i
+wwi
.width
];
1188 neibourgs
[3] = datas
[i
+wwi
.width
-1];
1189 neibourgs
[4] = datas
[i
+wwi
.width
+1];
1191 res
.x
= (neibourgs
[0].x
+ neibourgs
[1].x
+ neibourgs
[2].x
+ neibourgs
[3].x
+ neibourgs
[4].x
+ 5.0*vit
.x
) / 10.0;
1192 res
.y
= (neibourgs
[0].y
+ neibourgs
[1].y
+ neibourgs
[2].y
+ neibourgs
[3].y
+ neibourgs
[4].y
+ 5.0*vit
.y
) / 10.0;
1196 for (unsigned int i
=wwi
.width
*(wwi
.height
-1)+1; i
<wwi
.count
-1; ++i
)
1198 Pair
& res
= wwi
.buffer
[i
];
1199 Pair vit
= datas
[i
];
1200 neibourgs
[0] = datas
[i
-1];
1201 neibourgs
[1] = datas
[i
+1];
1202 neibourgs
[2] = datas
[i
-wwi
.width
];
1203 neibourgs
[3] = datas
[i
-wwi
.width
-1];
1204 neibourgs
[4] = datas
[i
-wwi
.width
+1];
1206 res
.x
= (neibourgs
[0].x
+ neibourgs
[1].x
+ neibourgs
[2].x
+ neibourgs
[3].x
+ neibourgs
[4].x
+ 5.0*vit
.x
) / 10.0;
1207 res
.y
= (neibourgs
[0].y
+ neibourgs
[1].y
+ neibourgs
[2].y
+ neibourgs
[3].y
+ neibourgs
[4].y
+ 5.0*vit
.y
) / 10.0;
1211 for (unsigned int i
=wwi
.width
; i
<wwi
.width
*(wwi
.height
-1); i
+=wwi
.width
)
1213 Pair
& res
= wwi
.buffer
[i
];
1214 Pair vit
= datas
[i
];
1215 neibourgs
[0] = datas
[i
+1];
1216 neibourgs
[1] = datas
[i
-wwi
.width
];
1217 neibourgs
[2] = datas
[i
+wwi
.width
];
1218 neibourgs
[3] = datas
[i
-wwi
.width
+1];
1219 neibourgs
[4] = datas
[i
+wwi
.width
+1];
1221 res
.x
= (neibourgs
[0].x
+ neibourgs
[1].x
+ neibourgs
[2].x
+ neibourgs
[3].x
+ neibourgs
[4].x
+ 5.0*vit
.x
) / 10.0;
1222 res
.y
= (neibourgs
[0].y
+ neibourgs
[1].y
+ neibourgs
[2].y
+ neibourgs
[3].y
+ neibourgs
[4].y
+ 5.0*vit
.y
) / 10.0;
1226 for (unsigned int i
=2*wwi
.width
-1; i
<wwi
.count
-1; i
+=wwi
.width
)
1228 Pair
& res
= wwi
.buffer
[i
];
1229 Pair vit
= datas
[i
];
1230 neibourgs
[0] = datas
[i
-1];
1231 neibourgs
[1] = datas
[i
-wwi
.width
];
1232 neibourgs
[2] = datas
[i
+wwi
.width
];
1233 neibourgs
[3] = datas
[i
-wwi
.width
-1];
1234 neibourgs
[4] = datas
[i
+wwi
.width
-1];
1236 res
.x
= (neibourgs
[0].x
+ neibourgs
[1].x
+ neibourgs
[2].x
+ neibourgs
[3].x
+ neibourgs
[4].x
+ 5.0*vit
.x
) / 10.0;
1237 res
.y
= (neibourgs
[0].y
+ neibourgs
[1].y
+ neibourgs
[2].y
+ neibourgs
[3].y
+ neibourgs
[4].y
+ 5.0*vit
.y
) / 10.0;
1240 // for the inner points
1241 for (unsigned int j
=1; j
<wwi
.height
-1; ++j
)
1243 for (unsigned int i
=1; i
<wwi
.width
-1; ++i
)
1245 unsigned int index
= i
+j
*wwi
.width
;
1247 Pair
& res
= wwi
.buffer
[index
];
1248 Pair
& vit
= datas
[index
];
1249 neibourgs
[0] = datas
[index
-1];
1250 neibourgs
[1] = datas
[index
+1];
1251 neibourgs
[2] = datas
[index
-wwi
.width
];
1252 neibourgs
[3] = datas
[index
+wwi
.width
];
1253 neibourgs
[4] = datas
[index
-wwi
.width
-1];
1254 neibourgs
[5] = datas
[index
-wwi
.width
+1];
1255 neibourgs
[6] = datas
[index
+wwi
.width
-1];
1256 neibourgs
[7] = datas
[index
+wwi
.width
+1];
1258 res
.x
= (neibourgs
[0].x
+ neibourgs
[1].x
+ neibourgs
[2].x
+ neibourgs
[3].x
+ neibourgs
[4].x
+ neibourgs
[5].x
+ neibourgs
[6].x
+ neibourgs
[7].x
+ 8.0*vit
.x
) / 16.0;
1259 res
.y
= (neibourgs
[0].y
+ neibourgs
[1].y
+ neibourgs
[2].y
+ neibourgs
[3].y
+ neibourgs
[4].y
+ neibourgs
[5].y
+ neibourgs
[6].y
+ neibourgs
[7].y
+ 8.0*vit
.y
) / 16.0;
1264 *datas_pointer
= wwi
.buffer
;