34
34
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
37
#include "animation-internal.h"
39
39
// ===================== Effect: Dodge =========================
42
fxDodgeProcessSubject (CompWindow *wCur,
50
rect.width = WIN_W(wCur);
51
rect.height = WIN_H(wCur);
52
Region wCurRegion = XCreateRegion();
53
XUnionRectWithRegion(&rect, &emptyRegion, wCurRegion);
56
Region intersectionRegion = XCreateRegion();
57
XIntersectRegion(wRegion, wCurRegion,
59
if (!XEmptyRegion(intersectionRegion))
60
XUnionRegion(dodgeRegion, wCurRegion, dodgeRegion);
63
XUnionRegion(dodgeRegion, wCurRegion, dodgeRegion);
67
fxDodgeFindDodgeBox (CompWindow *w, XRectangle *dodgeBox)
69
ANIM_SCREEN(w->screen);
42
DodgeAnim::applyDodgeTransform ()
44
if (mDodgeData->isDodgeSubject && mDodgeDirection == DodgeDirectionNone)
50
if (mDodgeMaxAmountX != 0)
51
amountX = sin (M_PI * mTransformProgress) * mDodgeMaxAmountX;
53
if (mDodgeMaxAmountY != 0)
54
amountY = sin (M_PI * mTransformProgress) * mDodgeMaxAmountY;
56
mTransform.translate (amountX, amountY, 0.0f);
60
DodgeAnim::moveUpdate ()
62
if (mDodgeData->isDodgeSubject &&
63
mDodgeDirection == DodgeDirectionXY)
65
mDodgeDirection = DodgeDirectionNone;
70
CompWindow *wBottommost =
71
ExtensionPluginAnimation::getBottommostInRestackChain (mWindow);
73
// Update dodge amount for the dodgers of all subjects
74
// in the restack chain
75
RestackPersistentData *dataCur;
76
for (CompWindow *wCur = wBottommost; wCur;
77
wCur = dataCur->mMoreToBePaintedNext)
79
AnimWindow *awCur = AnimWindow::get (wCur);
80
dataCur = static_cast<RestackPersistentData *>
81
(awCur->persistentData["restack"]);
85
Animation *curAnim = awCur->curAnimation ();
86
if (!curAnim || curAnim->info () != AnimEffectDodge)
89
DodgePersistentData *dodgeDataDodger;
91
// Update dodge amount for each dodger
92
for (CompWindow *dw = mDodgeData->dodgeChainStart; dw;
93
dw = dodgeDataDodger->dodgeChainNext)
95
AnimWindow *adw = AnimWindow::get (dw);
97
static_cast<DodgePersistentData *>
98
(adw->persistentData["dodge"]);
100
DodgeAnim *animDodger =
101
dynamic_cast<DodgeAnim *> (adw->curAnimation ());
105
if (animDodger->mDodgeSubjectWin &&
106
animDodger->mTransformProgress <= 0.5f)
108
animDodger->updateDodgerDodgeAmount ();
116
/// Should only be called for non-subjects.
118
DodgeAnim::updateDodgerDodgeAmount ()
72
120
// Find the box to be dodged, it can contain multiple windows
73
121
// when there are dialog/utility windows of subject windows
74
// (stacked in the moreToBePaintedNext chain)
122
// (stacked in the mMoreToBePaintedNext chain).
75
123
// Then this would be a bounding box of the subject windows
76
124
// intersecting with dodger.
77
Region wRegion = XCreateRegion();
78
Region dodgeRegion = XCreateRegion();
83
rect.width = WIN_W(w);
84
rect.height = WIN_H(w);
86
int dodgeMaxAmount = (int)aw->dodgeMaxAmount;
88
// to compute if subject(s) intersect with dodger w,
89
// enlarge dodger window's box so that it encloses all of the covered
90
// region during dodge movement. This corrects the animation when
91
// there are >1 subjects (a window with its dialog/utility windows).
92
switch (aw->dodgeDirection)
95
rect.y += dodgeMaxAmount;
96
rect.height -= dodgeMaxAmount;
99
rect.height += dodgeMaxAmount;
102
rect.x += dodgeMaxAmount;
103
rect.width -= dodgeMaxAmount;
106
rect.width += dodgeMaxAmount;
109
XUnionRectWithRegion(&rect, &emptyRegion, wRegion);
112
CompWindow *wCur = aw->dodgeSubjectWin;
113
for (; wCur; wCur = awCur->moreToBePaintedNext)
115
fxDodgeProcessSubject(wCur, wRegion, dodgeRegion,
116
wCur == aw->dodgeSubjectWin);
117
awCur = GET_ANIM_WINDOW(wCur, as);
122
AnimWindow *awSubj = GET_ANIM_WINDOW(aw->dodgeSubjectWin, as);
123
wCur = awSubj->moreToBePaintedPrev;
124
for (; wCur; wCur = awCur->moreToBePaintedPrev)
126
fxDodgeProcessSubject(wCur, wRegion, dodgeRegion, FALSE);
127
awCur = GET_ANIM_WINDOW(wCur, as);
132
XClipBox(dodgeRegion, dodgeBox);
125
CompRect subjectRect (unionRestackChain (mDodgeSubjectWin).boundingRect ());
127
// Update dodge amount if subject window(s) moved during dodge
128
float newDodgeAmount =
129
getDodgeAmount (subjectRect, mWindow, mDodgeDirection);
131
// Only update if amount got larger
132
if ((mDodgeDirection == DodgeDirectionDown && newDodgeAmount > 0 ||
133
mDodgeDirection == DodgeDirectionUp && newDodgeAmount < 0) &&
134
abs (newDodgeAmount) > abs (mDodgeMaxAmountY))
136
mDodgeMaxAmountY = newDodgeAmount;
138
else if ((mDodgeDirection == DodgeDirectionRight && newDodgeAmount > 0 ||
139
mDodgeDirection == DodgeDirectionLeft && newDodgeAmount < 0) &&
140
abs (newDodgeAmount) > abs (mDodgeMaxAmountX))
142
mDodgeMaxAmountX = newDodgeAmount;
136
applyDodgeTransform (CompWindow * w, CompTransform *transform)
147
DodgeAnim::dodgeProgress ()
140
if (aw->isDodgeSubject)
143
float amount = sin(M_PI * aw->com.transformProgress) * aw->dodgeMaxAmount;
145
if (aw->dodgeDirection > 1) // if x axis
146
matrixTranslate (transform, amount, 0.0f, 0.0f);
148
matrixTranslate (transform, 0.0f, amount, 0.0f);
149
float forwardProgress = progressLinear ();
151
forwardProgress = 1 - forwardProgress;
152
return forwardProgress;
152
fxDodgeAnimStep (CompWindow *w, float time)
154
defaultAnimStep (w, time);
158
aw->com.transformProgress = 0;
160
float forwardProgress = defaultAnimProgress (w);
161
if (forwardProgress > aw->com.transformStartProgress)
158
TransformAnim::step ();
160
mTransformProgress = 0;
162
float forwardProgress = dodgeProgress ();
163
if (forwardProgress > mTransformStartProgress)
163
aw->com.transformProgress =
164
(forwardProgress - aw->com.transformStartProgress) /
165
(1 - aw->com.transformStartProgress);
165
// Compute transform progress and normalize
167
(forwardProgress - mTransformStartProgress) /
168
(1 - mTransformStartProgress);
168
if (!aw->isDodgeSubject && !aw->dodgeSubjectWin)
171
if (!mDodgeData->isDodgeSubject && !mDodgeSubjectWin)
169
172
compLogMessage ("animation", CompLogLevelError,
170
173
"%s: %d: Dodge subject missing!",
171
174
__FILE__, __LINE__);
172
if (!aw->isDodgeSubject &&
173
aw->dodgeSubjectWin &&
174
aw->com.transformProgress <= 0.5f)
177
applyDodgeTransform ();
181
DodgeAnim::updateTransform (GLMatrix &wTransform)
183
TransformAnim::updateTransform (wTransform);
187
DodgeAnim::postPreparePaint ()
189
// Only dodge subjects (with dodger chains) should be processed here
190
if (!mDodgeData || !mDodgeData->isDodgeSubject ||
191
!mDodgeData->dodgeChainStart)
194
if (!mRestackData || !mRestackData->restackInfo ())
197
if (mDodgeData->skipPostPrepareScreen)
200
// Find the bottommost subject in restack chain
201
CompWindow *wBottommost = mWindow;
202
RestackPersistentData *dataCur;
203
for (CompWindow *wCur = mRestackData->mMoreToBePaintedPrev; wCur;
204
wCur = dataCur->mMoreToBePaintedPrev)
177
fxDodgeFindDodgeBox (w, &dodgeBox);
179
// Update dodge amount if subject window is moved during dodge
180
float newDodgeAmount =
181
DODGE_AMOUNT_BOX(dodgeBox, w, aw->dodgeDirection);
183
// Only update if amount got larger
184
if (((newDodgeAmount > 0 && aw->dodgeMaxAmount > 0) ||
185
(newDodgeAmount < 0 && aw->dodgeMaxAmount < 0)) &&
186
abs(newDodgeAmount) > abs(aw->dodgeMaxAmount))
188
aw->dodgeMaxAmount = newDodgeAmount;
207
dataCur = static_cast<RestackPersistentData *>
208
(AnimWindow::get (wCur)->persistentData["restack"]);
192
matrixGetIdentity (&aw->com.transform);
193
applyDodgeTransform (w, &aw->com.transform);
197
fxDodgeUpdateWindowTransform (CompWindow *w,
198
CompTransform *wTransform)
202
if (aw->isDodgeSubject)
205
applyTransform (wTransform, &aw->com.transform);
209
fxDodgePostPreparePaintScreen (CompWindow *w)
211
ANIM_SCREEN(w->screen);
214
// Only dodge subjects should be processed here
215
if (!aw->isDodgeSubject)
218
if (!aw->restackInfo)
221
if (aw->skipPostPrepareScreen)
212
AnimWindow *awBottommost = AnimWindow::get (wBottommost);
213
RestackPersistentData *restackDataBottommost =
214
static_cast<RestackPersistentData *>
215
(awBottommost->persistentData["restack"]);
217
// Find the first dodging window that hasn't yet
218
// reached 50% progress yet. The subject window should be
219
// painted right behind that one (or right in front of it
220
// if subject is being lowered).
221
RestackPersistentData *restackDataDodger;
222
DodgePersistentData *dodgeDataDodger;
226
AnimWindow *adw = NULL;
227
for (dw = aw->dodgeChainStart; dw; dw = adw->dodgeChainNext)
224
for (dw = mDodgeData->dodgeChainStart; dw;
225
dw = dodgeDataDodger->dodgeChainNext)
229
adw = GET_ANIM_WINDOW(dw, as);
232
// find the first dodging window that hasn't yet
233
// reached 50% progress yet. The subject window should be
234
// painted right behind that one (or right in front of it if
235
// the subject window is being lowered).
236
if (!(adw->com.transformProgress > 0.5f))
227
AnimWindow *adw = AnimWindow::get (dw);
228
restackDataDodger = static_cast<RestackPersistentData *>
229
(adw->persistentData["restack"]);
230
dodgeDataDodger = static_cast<DodgePersistentData *>
231
(adw->persistentData["dodge"]);
233
DodgeAnim *animDodger =
234
dynamic_cast<DodgeAnim *> (adw->curAnimation ());
236
if (!(animDodger->mTransformProgress > 0.5f))
239
AnimWindow *awOldHost = NULL;
241
if (aw->restackInfo->raised &&
242
dw != aw->winThisIsPaintedBefore) // w's host is changing
240
if (restackDataBottommost->restackInfo ()->raised &&
241
// if mWindow's host should change
242
dw != restackDataBottommost->mWinThisIsPaintedBefore)
244
if (aw->winThisIsPaintedBefore)
244
if (restackDataBottommost->mWinThisIsPaintedBefore)
246
246
// Clear old host
247
awOldHost = GET_ANIM_WINDOW(aw->winThisIsPaintedBefore, as);
248
awOldHost->winToBePaintedBeforeThis = NULL;
247
RestackPersistentData *dataOldHost =
248
static_cast<RestackPersistentData *>
249
(AnimWindow::get (restackDataBottommost->
250
mWinThisIsPaintedBefore)->
251
persistentData["restack"]);
252
dataOldHost->mWinToBePaintedBeforeThis = 0;
250
if (dw && adw) // if a dodgy win. is still at <0.5 progress
254
// if a dodger win. is still at <0.5 progress
255
if (dw && restackDataDodger)
252
// Put subject right behind adw (new host)
253
adw->winToBePaintedBeforeThis = w;
257
// Put subject right behind new host
258
restackDataDodger->mWinToBePaintedBeforeThis = wBottommost;
255
// otherwise all dodgy win.s have passed 0.5 progress
260
// otherwise all dodger win.s have passed 0.5 progress
257
CompWindow *wCur = w;
262
CompWindow *wCur = wBottommost;
260
AnimWindow *awCur = GET_ANIM_WINDOW(wCur, as);
261
awCur->winThisIsPaintedBefore = dw; // dw can be null, which is ok
262
wCur = awCur->moreToBePaintedNext;
265
RestackPersistentData *dataCur =
266
static_cast<RestackPersistentData *>
267
(AnimWindow::get (wCur)->persistentData["restack"]);
268
// dw can be null, which is ok
269
dataCur->mWinThisIsPaintedBefore = dw;
270
wCur = dataCur->mMoreToBePaintedNext;
265
else if (!aw->restackInfo->raised)
273
else if (!restackDataBottommost->restackInfo ()->raised)
267
// Put subject right in front of dw
268
// But we need to find the dodgy window above dw
269
// (since we need to put subject *behind* another one)
271
CompWindow *wDodgeChainAbove = NULL;
273
if (dw && adw) // if a dodgy win. is still at <0.5 progress
275
// Put the subject right in front of dw.
276
// But we need to find the (dodger) window above dw
277
// (since we need to put the subject *behind* a window).
279
CompWindow *wDodgeChainAbove = 0;
281
// if a dodger win. is still at <0.5 progress
282
if (dw && dodgeDataDodger)
275
if (adw->dodgeChainPrev)
276
wDodgeChainAbove = adw->dodgeChainPrev;
284
if (dodgeDataDodger->dodgeChainPrev)
286
wDodgeChainAbove = dodgeDataDodger->dodgeChainPrev;
278
wDodgeChainAbove = aw->restackInfo->wOldAbove;
290
// Use the wOldAbove of topmost subject
291
wDodgeChainAbove = mRestackData->restackInfo ()->wOldAbove;
280
293
if (!wDodgeChainAbove)
281
294
compLogMessage ("animation", CompLogLevelError,
282
295
"%s: error at line %d", __FILE__, __LINE__);
283
else if (aw->winThisIsPaintedBefore !=
296
else if (restackDataBottommost->mWinThisIsPaintedBefore !=
284
297
wDodgeChainAbove) // w's host is changing
286
AnimWindow *adw2 = GET_ANIM_WINDOW(wDodgeChainAbove, as);
299
RestackPersistentData *dataNewHost =
300
static_cast<RestackPersistentData *>
301
(AnimWindow::get (wDodgeChainAbove)->
302
persistentData["restack"]);
288
// Put subject right behind adw2 (new host)
289
adw2->winToBePaintedBeforeThis = w;
304
// Put subject right behind new host
305
dataNewHost->mWinToBePaintedBeforeThis = wBottommost;
292
if (aw->winThisIsPaintedBefore &&
293
aw->winThisIsPaintedBefore != wDodgeChainAbove)
308
if (restackDataBottommost->mWinThisIsPaintedBefore &&
309
restackDataBottommost->mWinThisIsPaintedBefore != wDodgeChainAbove)
295
awOldHost = GET_ANIM_WINDOW(aw->winThisIsPaintedBefore, as);
297
311
// Clear old host
298
awOldHost->winToBePaintedBeforeThis = NULL;
300
// otherwise all dodgy win.s have passed 0.5 progress
302
// wDodgeChainAbove can be null, which is ok
303
aw->winThisIsPaintedBefore = wDodgeChainAbove;
308
fxDodgeUpdateBB (CompOutput *output,
314
if (!aw->isDodgeSubject)
315
compTransformUpdateBB (output, w, BB);
312
RestackPersistentData *dataOldHost =
313
static_cast<RestackPersistentData *>
314
(AnimWindow::get (restackDataBottommost->
315
mWinThisIsPaintedBefore)->
316
persistentData["restack"]);
317
dataOldHost->mWinToBePaintedBeforeThis = 0;
319
// otherwise all dodger win.s have passed 0.5 progress
321
CompWindow *wCur = wBottommost;
324
RestackPersistentData *dataCur =
325
static_cast<RestackPersistentData *>
326
(AnimWindow::get (wCur)->persistentData["restack"]);
327
// wDodgeChainAbove can be null, which is ok
328
dataCur->mWinThisIsPaintedBefore = wDodgeChainAbove;
329
wCur = dataCur->mMoreToBePaintedNext;
335
DodgeAnim::shouldDamageWindowOnStart ()
337
// for dodging windows only, when subject is fixed
338
return !(mDodgeMode == AnimationOptions::DodgeModeFixedClickedWindow &&
339
mDodgeData->isDodgeSubject);
343
DodgeAnim::updateBB (CompOutput &output)
345
TransformAnim::updateBB (output);
348
DodgeAnim::DodgeAnim (CompWindow *w,
349
WindowEvent curWindowEvent,
351
const AnimEffect info,
352
const CompRect &icon) :
353
Animation::Animation (w, curWindowEvent, duration, info, icon),
354
TransformAnim::TransformAnim (w, curWindowEvent, duration, info, icon),
355
RestackAnim::RestackAnim (w, curWindowEvent, duration, info, icon),
356
mDodgeSubjectWin (0),
357
mDodgeMaxAmountX (0),
358
mDodgeMaxAmountY (0),
359
mDodgeDirection (DodgeDirectionNone),
360
mDodgeMode (optValI (AnimationOptions::DodgeMode)),
361
mDodgeData (static_cast<DodgePersistentData *>
362
(AnimWindow::get (w)->persistentData["dodge"]))
367
DodgeAnim::cleanUp (bool closing,
370
// Remove this window from its subject's dodger chain
371
if (mDodgeSubjectWin)
373
CompWindow *w = mDodgeSubjectWin;
374
AnimWindow *aw = AnimWindow::get (w);
375
Animation *curAnim = aw->curAnimation ();
376
DodgePersistentData *dodgeData = static_cast<DodgePersistentData *>
377
(aw->persistentData["dodge"]);
379
if (curAnim && curAnim->info () == AnimEffectDodge &&
380
// Only process subjects with a dodge chain
381
dodgeData && dodgeData->dodgeChainStart &&
382
dodgeData->isDodgeSubject)
384
// Go through each dodger, checking if this is that one
386
DodgePersistentData *dodgeDataDodger;
387
for (CompWindow *dw = dodgeData->dodgeChainStart; dw;
388
dw = dodgeDataDodger->dodgeChainNext)
390
AnimWindow *adw = AnimWindow::get (dw);
391
dodgeDataDodger = static_cast<DodgePersistentData *>
392
(adw->persistentData["dodge"]);
395
// Remove mWindow from the chain
396
CompWindow *dwNext = dodgeDataDodger->dodgeChainNext;
399
AnimWindow *adwNext = AnimWindow::get (dwNext);
400
DodgePersistentData *dodgeDataDodgerNext =
401
static_cast<DodgePersistentData *>
402
(adwNext->persistentData["dodge"]);
403
dodgeDataDodgerNext->dodgeChainPrev =
404
dodgeDataDodger->dodgeChainPrev;
406
CompWindow *dwPrev = dodgeDataDodger->dodgeChainPrev;
409
AnimWindow *adwPrev = AnimWindow::get (dwPrev);
410
DodgePersistentData *dodgeDataDodgerPrev =
411
static_cast<DodgePersistentData *>
412
(adwPrev->persistentData["dodge"]);
413
dodgeDataDodgerPrev->dodgeChainNext =
414
dodgeDataDodger->dodgeChainNext;
416
if (dodgeData->dodgeChainStart == mWindow)
417
dodgeData->dodgeChainStart =
418
dodgeDataDodger->dodgeChainNext;
419
dodgeDataDodger->dodgeChainPrev = 0;
420
dodgeDataDodger->dodgeChainNext = 0;
425
// Reset dodge parameters
426
//if (!(restackData->mMoreToBePaintedPrev ||
427
// restackData->mMoreToBePaintedNext))
429
mDodgeData->isDodgeSubject = false;
430
mDodgeData->skipPostPrepareScreen = false;
432
RestackAnim::cleanUp (closing, destructing);
436
DodgeAnim::getDodgeAmount (CompRect &rect,
440
CompRect dRect (dw->inputRect ().x () +
441
(dw->outputRect ().x () - dw->inputRect ().x ()) / 2,
442
dw->inputRect ().y () +
443
(dw->outputRect ().y () - dw->inputRect ().y ()) / 2,
444
(dw->inputRect ().width () +
445
dw->outputRect ().width ()) / 2,
446
(dw->inputRect ().height () +
447
dw->outputRect ().height ()) / 2);
452
case DodgeDirectionUp:
453
amount = (rect.y () - (dRect.y () + dRect.height ()));
455
case DodgeDirectionDown:
456
amount = (rect.y () + rect.height () - dRect.y ());
458
case DodgeDirectionLeft:
459
amount = (rect.x () - (dRect.x () + dRect.width ()));
461
case DodgeDirectionRight:
462
amount = (rect.x () + rect.width () - dRect.x ());
471
DodgeAnim::processCandidate (CompWindow *candidateWin,
472
CompWindow *subjectWin,
473
CompRegion &candidateAndSubjectIntersection,
474
int &numSelectedCandidates)
476
AnimWindow *aCandidateWin = AnimWindow::get (candidateWin);
477
AnimScreen *as = AnimScreen::get (::screen);
479
if ((!aCandidateWin->curAnimation () ||
480
aCandidateWin->curAnimation ()->info () == AnimEffectDodge) &&
481
candidateWin != subjectWin) // don't let the subject dodge itself
483
// Mark this window for dodge
485
bool nonMatching = false;
486
if (as->getMatchingAnimSelection (candidateWin, AnimEventFocus, 0) !=
490
numSelectedCandidates++;
491
DodgePersistentData *data = static_cast<DodgePersistentData *>
492
(aCandidateWin->persistentData["dodge"]);
493
data->dodgeOrder = numSelectedCandidates;
494
if (nonMatching) // Use neg. values for non-matching windows
495
data->dodgeOrder *= -1;
500
DodgeAnim::postInitiateRestackAnim (int numSelectedCandidates,
506
DodgePersistentData *dataSubject = mDodgeData;
510
dataSubject->isDodgeSubject = true;
511
dataSubject->dodgeChainStart = 0;
513
if (mRestackData && mRestackData->mIsSecondary)
515
mTransformStartProgress = 0;
516
return; // We're done here
518
float maxTransformTotalProgress = 0;
519
float dodgeMaxStartProgress =
520
numSelectedCandidates * optValF (AnimationOptions::DodgeGapRatio) *
523
CompWindow *wDodgeChainLastVisited = 0;
525
// dw: Dodger window(s)
526
for (CompWindow *dw = wStart; dw && dw != wEnd->next; dw = dw->next)
528
AnimWindow *adw = AnimWindow::get (dw);
529
DodgePersistentData *dataDodger = static_cast<DodgePersistentData *>
530
(adw->persistentData["dodge"]);
533
if (dataDodger->dodgeOrder == 0)
536
// Initiate dodge for this window
538
bool stationaryDodger = false;
539
if (dataDodger->dodgeOrder < 0)
541
dataDodger->dodgeOrder *= -1; // Make it positive again
542
stationaryDodger = true;
544
if (!adw->curAnimation ())
546
// Create dodge animation for dodger
547
adw->createFocusAnimation (AnimEffectDodge);
548
ExtensionPluginAnimation *extPlugin =
549
static_cast<ExtensionPluginAnimation *>
550
(getExtensionPluginInfo ());
551
extPlugin->incrementCurRestackAnimCount ();
554
DodgeAnim *animDodger =
555
dynamic_cast<DodgeAnim *> (adw->curAnimation ());
557
animDodger->mDodgeSubjectWin = mWindow;
559
if (mDodgeMode == AnimationOptions::DodgeModeFixedClickedWindow)
561
// Slight change in dodge movement start
562
// to reflect stacking order of dodger windows
564
animDodger->mTransformStartProgress =
565
dodgeMaxStartProgress *
566
(dataDodger->dodgeOrder - 1) / numSelectedCandidates;
568
animDodger->mTransformStartProgress =
569
dodgeMaxStartProgress *
570
(1 - (float)dataDodger->dodgeOrder / numSelectedCandidates);
574
animDodger->mTransformStartProgress = 0;
576
float transformTotalProgress =
577
1 + animDodger->mTransformStartProgress;
579
if (maxTransformTotalProgress < transformTotalProgress)
580
maxTransformTotalProgress = transformTotalProgress;
583
animDodger->mTransformStartProgress /= transformTotalProgress;
585
if (stationaryDodger)
587
animDodger->mTransformStartProgress = 0;
588
transformTotalProgress = 0;
591
animDodger->mTotalTime = transformTotalProgress * duration;
592
animDodger->mRemainingTime = animDodger->mTotalTime;
594
// Put window on dodge chain
596
// if dodge chain was started before
597
if (wDodgeChainLastVisited)
599
DodgePersistentData *dataDodgeChainLastVisited =
600
static_cast<DodgePersistentData *>
601
(AnimWindow::get (wDodgeChainLastVisited)->
602
persistentData["dodge"]);
605
dataDodgeChainLastVisited->dodgeChainNext = dw;
608
dataDodgeChainLastVisited->dodgeChainPrev = dw;
610
else if (raised) // mark chain start
612
dataSubject->dodgeChainStart = dw;
616
dataDodger->dodgeChainPrev = wDodgeChainLastVisited;
617
dataDodger->dodgeChainNext = 0;
621
dataDodger->dodgeChainPrev = 0;
622
dataDodger->dodgeChainNext = wDodgeChainLastVisited;
625
wDodgeChainLastVisited = dw;
627
// Reset back to 0 for the next dodge calculation
628
dataDodger->dodgeOrder = 0;
631
// if subject is being lowered,
632
// point chain-start to the topmost doding window
634
dataSubject->dodgeChainStart = wDodgeChainLastVisited;
636
mTotalTime = maxTransformTotalProgress * duration;
637
mRemainingTime = mTotalTime;
641
DodgeAnim::calculateDodgeAmounts ()
643
// holds whether each side of the subject is covered by dodgers or not
644
bool coveredSides[4] = {false, false, false, false};
646
// maximum distance between a dodger window and the subject in X and Y axes
648
int maxDistXActual = 0;
650
int maxDistYActual = 0;
652
CompRect subjectRect (unionRestackChain (mWindow).boundingRect ());
654
// Go through each dodger, calculating its dodge amount.
656
DodgePersistentData *dodgeDataDodger;
657
for (CompWindow *dw = mDodgeData->dodgeChainStart; dw;
658
dw = dodgeDataDodger->dodgeChainNext)
660
AnimWindow *adw = AnimWindow::get (dw);
662
dodgeDataDodger = static_cast<DodgePersistentData *>
663
(adw->persistentData["dodge"]);
665
DodgeAnim *animDodger =
666
dynamic_cast<DodgeAnim *> (adw->curAnimation ());
670
// Find direction (left, right, up, down) that minimizes dodge amount
674
for (int i = 0; i < 4; i++)
676
DodgeAnim::getDodgeAmount (subjectRect, dw, (DodgeDirection)i);
678
int amountMinActual = dodgeAmount[0];
679
int amountMinAbs = abs (amountMinActual);
681
for (int i=1; i<4; i++)
683
int absAmount = abs (dodgeAmount[i]);
684
if (amountMinAbs > absAmount)
686
amountMinAbs = absAmount;
687
amountMinActual = dodgeAmount[i];
691
if (iMin == DodgeDirectionUp ||
692
iMin == DodgeDirectionDown)
694
animDodger->mDodgeMaxAmountX = 0;
695
animDodger->mDodgeMaxAmountY = dodgeAmount[iMin];
696
if (mDodgeMode == AnimationOptions::DodgeModeAllMoving &&
697
maxDistY < amountMinAbs)
699
maxDistY = amountMinAbs;
700
maxDistYActual = amountMinActual;
705
animDodger->mDodgeMaxAmountX = dodgeAmount[iMin];
706
animDodger->mDodgeMaxAmountY = 0;
707
if (mDodgeMode == AnimationOptions::DodgeModeAllMoving && maxDistX < amountMinAbs)
709
maxDistX = amountMinAbs;
710
maxDistXActual = amountMinActual;
713
animDodger->mDodgeDirection = (DodgeDirection)iMin;
715
coveredSides[iMin] = true;
718
if (mDodgeMode == AnimationOptions::DodgeModeFixedClickedWindow)
720
// Subject doesn't move
721
mDodgeMaxAmountX = 0;
722
mDodgeMaxAmountY = 0;
723
mDodgeDirection = DodgeDirectionNone;
727
// Subject should dodge in an axis if only one side is
728
// covered by a dodger.
729
bool subjectDodgesInX = (coveredSides[DodgeDirectionLeft] ^
730
coveredSides[DodgeDirectionRight]);
731
bool subjectDodgesInY = (coveredSides[DodgeDirectionUp] ^
732
coveredSides[DodgeDirectionDown]);
734
float dodgeAmountX = subjectDodgesInX ? -maxDistXActual / 2 : 0;
735
float dodgeAmountY = subjectDodgesInY ? -maxDistYActual / 2 : 0;
736
DodgeDirection dodgeDirection;
738
if (!subjectDodgesInX && !subjectDodgesInY)
739
dodgeDirection = DodgeDirectionNone;
741
dodgeDirection = DodgeDirectionXY;
743
CompWindow *wBottommost =
744
ExtensionPluginAnimation::getBottommostInRestackChain (mWindow);
748
float offsetIncrementX = (dodgeAmountX == 0 ? 0 :
749
100 * dodgeAmountX / fabs (dodgeAmountX));
750
float offsetIncrementY = (dodgeAmountY == 0 ? 0 :
751
100 * dodgeAmountY / fabs (dodgeAmountY));
753
// Set dodge amount and direction for all subjects
754
// in the restack chain
755
RestackPersistentData *dataCur;
756
for (CompWindow *wCur = wBottommost; wCur;
757
wCur = dataCur->mMoreToBePaintedNext,
758
offsetX += offsetIncrementX,
759
offsetY += offsetIncrementY)
761
AnimWindow *awCur = AnimWindow::get (wCur);
763
dataCur = static_cast<RestackPersistentData *>
764
(awCur->persistentData["restack"]);
768
Animation *curAnim = awCur->curAnimation ();
769
if (!curAnim || curAnim->info () != AnimEffectDodge)
771
DodgeAnim *dodgeAnim = dynamic_cast<DodgeAnim *> (curAnim);
773
dodgeAnim->mDodgeMaxAmountX = dodgeAmountX + offsetX;
774
dodgeAnim->mDodgeMaxAmountY = dodgeAmountY + offsetY;
775
dodgeAnim->mDodgeDirection = dodgeDirection;
777
dodgeAnim->mTransformStartProgress = 0;
780
if (dodgeDirection == DodgeDirectionXY)
782
// Go through each dodger, adjusting its dodge amount if the
783
// subject(s) is dodging in that axis (X or Y).
785
DodgePersistentData *dodgeDataDodger;
786
for (CompWindow *dw = mDodgeData->dodgeChainStart; dw;
787
dw = dodgeDataDodger->dodgeChainNext)
789
AnimWindow *adw = AnimWindow::get (dw);
791
dodgeDataDodger = static_cast<DodgePersistentData *>
792
(adw->persistentData["dodge"]);
794
DodgeAnim *animDodger =
795
dynamic_cast<DodgeAnim *> (adw->curAnimation ());
799
// if both dodge in X axis
800
if (subjectDodgesInX && animDodger->mDodgeMaxAmountX != 0)
802
if (animDodger->mDodgeMaxAmountX *
803
(animDodger->mDodgeMaxAmountX + dodgeAmountX) < 0)
805
// If the sign is going to change, just reset instead
806
animDodger->mDodgeMaxAmountX = 0;
809
animDodger->mDodgeMaxAmountX += dodgeAmountX;
812
// if both dodge in Y axis
813
if (subjectDodgesInY && animDodger->mDodgeMaxAmountY != 0)
815
if (animDodger->mDodgeMaxAmountY *
816
(animDodger->mDodgeMaxAmountY + dodgeAmountY) < 0)
818
// If the sign is going to change, just reset instead
819
animDodger->mDodgeMaxAmountY = 0;
822
animDodger->mDodgeMaxAmountY += dodgeAmountY;
830
DodgeAnim::paintedElsewhere ()
834
mRestackData->mWinThisIsPaintedBefore && // has to be currently hosted
836
mDodgeData->isDodgeSubject &&
842
DodgePersistentData::DodgePersistentData () :
843
isDodgeSubject (false),
844
skipPostPrepareScreen (false),