~vanvugt/compiz-animation-plugin/fix-915236

« back to all changes in this revision

Viewing changes to src/restack.cpp

  • Committer: Erkin Bahceci
  • Date: 2009-07-15 16:05:10 UTC
  • Revision ID: git-v1:6eeaa209932c6039edd4c362c352f242468a118a
Initial C++ port. Dodge and magic lamp changes.

- New dodge mode: all windows moving (made the default).
- Fixed dodge artifacts/weirdness showing up in certain situations.
- Magic Lamp renamed to Magic Lamp Wavy.
- Vacuum renamed to Magic Lamp, allowed for minimize (made the default).
- Separated restack stuff (dodge and focus-fade) from animation core.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Animation plugin for compiz/beryl
 
3
 *
 
4
 * animation.c
 
5
 *
 
6
 * Copyright : (C) 2006 Erkin Bahceci
 
7
 * E-mail    : erkinbah@gmail.com
 
8
 *
 
9
 * Based on Wobbly and Minimize plugins by
 
10
 *           : David Reveman
 
11
 * E-mail    : davidr@novell.com>
 
12
 *
 
13
 * Particle system added by : (C) 2006 Dennis Kasprzyk
 
14
 * E-mail                   : onestone@beryl-project.org
 
15
 *
 
16
 * Beam-Up added by : Florencio Guimaraes
 
17
 * E-mail           : florencio@nexcorp.com.br
 
18
 *
 
19
 * Hexagon tessellator added by : Mike Slegeir
 
20
 * E-mail                       : mikeslegeir@mail.utexas.edu>
 
21
 *
 
22
 * This program is free software; you can redistribute it and/or
 
23
 * modify it under the terms of the GNU General Public License
 
24
 * as published by the Free Software Foundation; either version 2
 
25
 * of the License, or (at your option) any later version.
 
26
 *
 
27
 * This program is distributed in the hope that it will be useful,
 
28
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
29
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
30
 * GNU General Public License for more details.
 
31
 *
 
32
 * You should have received a copy of the GNU General Public License
 
33
 * along with this program; if not, write to the Free Software
 
34
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
35
 */
 
36
 
 
37
#include "private.h"
 
38
 
 
39
// =====================  Restack  =========================
 
40
 
 
41
RestackAnim::RestackAnim (CompWindow *w,
 
42
                          WindowEvent curWindowEvent,
 
43
                          float duration,
 
44
                          const AnimEffect info,
 
45
                          const CompRect &icon) :
 
46
    Animation::Animation (w, curWindowEvent, duration, info, icon)
 
47
{
 
48
    mRestackData = static_cast<RestackPersistentData *>
 
49
        (AnimWindow::get (w)->persistentData["restack"]);
 
50
}
 
51
 
 
52
void
 
53
RestackAnim::cleanUp (bool closing, bool destructing)
 
54
{
 
55
    if (mRestackData->restackInfo ())
 
56
        mRestackData->resetRestackInfo ();
 
57
 
 
58
    bool thereIsUnfinishedChainElem = false;
 
59
 
 
60
    // Look for still playing windows in parent-child chain
 
61
    CompWindow *wCur = mRestackData->mMoreToBePaintedNext;
 
62
    while (wCur)
 
63
    {
 
64
        AnimWindow *awCur = AnimWindow::get (wCur);
 
65
 
 
66
        if (awCur->curAnimation () &&
 
67
            awCur->curAnimation ()->remainingTime () > 0)
 
68
        {
 
69
            thereIsUnfinishedChainElem = true;
 
70
            break;
 
71
        }
 
72
        RestackPersistentData *dataCur = static_cast<RestackPersistentData *>
 
73
            (awCur->persistentData["restack"]);
 
74
        wCur = dataCur->mMoreToBePaintedNext;
 
75
    }
 
76
    if (!thereIsUnfinishedChainElem)
 
77
    {
 
78
        wCur = mRestackData->mMoreToBePaintedPrev;
 
79
        while (wCur)
 
80
        {
 
81
            AnimWindow *awCur = AnimWindow::get (wCur);
 
82
 
 
83
            if (awCur->curAnimation () &&
 
84
                awCur->curAnimation ()->remainingTime () > 0)
 
85
            {
 
86
                thereIsUnfinishedChainElem = true;
 
87
                break;
 
88
            }
 
89
            RestackPersistentData *dataCur =
 
90
                static_cast<RestackPersistentData *>
 
91
                (awCur->persistentData["restack"]);
 
92
            wCur = dataCur->mMoreToBePaintedPrev;
 
93
        }
 
94
    }
 
95
 
 
96
    if (closing || destructing || !thereIsUnfinishedChainElem)
 
97
    {
 
98
        // Finish off all windows in parent-child chain
 
99
        CompWindow *wCur = mRestackData->mMoreToBePaintedNext;
 
100
        while (wCur)
 
101
        {
 
102
            AnimWindow *awCur = AnimWindow::get (wCur);
 
103
            RestackPersistentData *dataCur =
 
104
                static_cast<RestackPersistentData *>
 
105
                (awCur->persistentData["restack"]);
 
106
            wCur = dataCur->mMoreToBePaintedNext;
 
107
            static_cast<ExtensionPluginAnimation *>
 
108
                (getExtensionPluginInfo ())->cleanUpParentChildChainItem (awCur);
 
109
        }
 
110
        wCur = mWindow;
 
111
        while (wCur)
 
112
        {
 
113
            AnimWindow *awCur = AnimWindow::get (wCur);
 
114
            RestackPersistentData *dataCur =
 
115
                static_cast<RestackPersistentData *>
 
116
                (awCur->persistentData["restack"]);
 
117
            wCur = dataCur->mMoreToBePaintedPrev;
 
118
            static_cast<ExtensionPluginAnimation *>
 
119
                (getExtensionPluginInfo ())->cleanUpParentChildChainItem (awCur);
 
120
        }
 
121
    }
 
122
 
 
123
    ExtensionPluginAnimation *extPlugin =
 
124
        static_cast<ExtensionPluginAnimation *> (getExtensionPluginInfo ());
 
125
    extPlugin->decrementCurRestackAnimCount ();
 
126
}
 
127
 
 
128
bool
 
129
RestackAnim::initiateRestackAnim (int duration)
 
130
{
 
131
    CompWindow *wStart = 0;
 
132
    CompWindow *wEnd = 0;
 
133
    CompWindow *wOldAbove = 0;
 
134
 
 
135
    if (!mRestackData)
 
136
        return false;
 
137
 
 
138
    ExtensionPluginAnimation *extPlugin =
 
139
        static_cast<ExtensionPluginAnimation *> (getExtensionPluginInfo ());
 
140
    extPlugin->incrementCurRestackAnimCount ();
 
141
 
 
142
    // If a focus chain (application with open dialog, etc.) is the subject,
 
143
    // in compiz++, their order changes during restack (which wasn't the case
 
144
    // in compiz 0.8. e.g: (subject chain: a b, dodger: x) (a: secondary)
 
145
    // a b x
 
146
    // b x a
 
147
    // x a b
 
148
    if (mRestackData->mIsSecondary)
 
149
    {
 
150
        if (!mRestackData->mMoreToBePaintedNext)
 
151
            return false;
 
152
 
 
153
        AnimWindow *awAbove =
 
154
            AnimWindow::get (mRestackData->mMoreToBePaintedNext);
 
155
        RestackPersistentData *dataAbove = static_cast<RestackPersistentData *>
 
156
            (awAbove->persistentData["restack"]);
 
157
 
 
158
        mTotalTime = awAbove->curAnimation ()->totalTime ();
 
159
        mRemainingTime = mTotalTime;
 
160
 
 
161
        if (dataAbove && dataAbove->mWinThisIsPaintedBefore)
 
162
        {
 
163
            // Host this subject instead, on the above subject's host
 
164
            mRestackData->getHostedOnWin (mWindow,
 
165
                                          dataAbove->mWinThisIsPaintedBefore);
 
166
        }
 
167
        // do basic secondary subject initialization
 
168
        postInitiateRestackAnim (0, 0, 0, 0, false);
 
169
 
 
170
        return true; // We're done here
 
171
    }
 
172
 
 
173
    RestackInfo *restackInfo = mRestackData->restackInfo ();
 
174
    bool raised = true;
 
175
 
 
176
    if (restackInfo)
 
177
    {
 
178
        wStart = restackInfo->wStart;
 
179
        wEnd = restackInfo->wEnd;
 
180
        wOldAbove = restackInfo->wOldAbove;
 
181
        raised = restackInfo->raised;
 
182
    }
 
183
 
 
184
    // Find union region of all windows that will be
 
185
    // faded through by w. If the region is empty, don't
 
186
    // run focus fade effect.
 
187
 
 
188
    CompRegion fadeRegion;
 
189
 
 
190
    int numSelectedCandidates = 0;
 
191
 
 
192
    CompRegion subjectsRegion (unionRestackChain (mWindow));
 
193
 
 
194
    // Compute subject win. region
 
195
 
 
196
    // wCand: Dodge or Focus fade candidate window
 
197
    for (CompWindow *wCand = wStart; wCand && wCand != wEnd->next;
 
198
         wCand = wCand->next)
 
199
    {
 
200
        RestackPersistentData *dataCand = static_cast<RestackPersistentData *>
 
201
            (AnimWindow::get (wCand)->persistentData["restack"]);
 
202
        if (!extPlugin->relevantForRestackAnim (wCand))
 
203
            continue;
 
204
 
 
205
        // Skip windows that have been restacked
 
206
        if (wCand != wEnd && dataCand->restackInfo ())
 
207
            continue;
 
208
 
 
209
        if (wCand->minimized ())
 
210
            continue;
 
211
 
 
212
        if (!CompositeWindow::get (wCand)->pixmap ())
 
213
            continue;
 
214
 
 
215
        if (//skipSubjectWindows () &&
 
216
            onSameRestackChain (mWindow, wCand))
 
217
            continue;
 
218
 
 
219
        // Compute intersection of this (wCand) with subject
 
220
        CompRegion candidateWinRegion (wCand->inputRect ());
 
221
        CompRegion candidateAndSubjectIntersection
 
222
            (candidateWinRegion.intersected (subjectsRegion));
 
223
        fadeRegion += candidateAndSubjectIntersection;
 
224
 
 
225
        if (!candidateAndSubjectIntersection.isEmpty ())
 
226
            processCandidate (wCand, mWindow, candidateAndSubjectIntersection,
 
227
                              numSelectedCandidates);
 
228
    }
 
229
 
 
230
    if (fadeRegion.isEmpty ())
 
231
    {
 
232
        // empty intersection -> won't be drawn
 
233
        return false;
 
234
    }
 
235
    if (wOldAbove)
 
236
    {
 
237
        // Store this window in the next window
 
238
        // so that this is drawn before that, i.e. in its old place
 
239
        mRestackData->getHostedOnWin (mWindow, wOldAbove);
 
240
    }
 
241
 
 
242
    postInitiateRestackAnim (numSelectedCandidates, duration,
 
243
                             wStart, wEnd, raised);
 
244
 
 
245
    // Handle other subjects down the chain if there are any
 
246
    if (mRestackData->mMoreToBePaintedPrev)
 
247
    {
 
248
        RestackPersistentData *dataCur;
 
249
        for (CompWindow *wCur = mRestackData->mMoreToBePaintedPrev; wCur;
 
250
             wCur = dataCur->mMoreToBePaintedPrev)
 
251
        {
 
252
            dataCur = static_cast<RestackPersistentData *>
 
253
                (AnimWindow::get (wCur)->persistentData["restack"]);
 
254
            if (!dataCur)
 
255
                break;
 
256
            dataCur->mIsSecondary = true;
 
257
        }
 
258
    }
 
259
    return true;
 
260
}
 
261
 
 
262
bool
 
263
RestackAnim::onSameRestackChain (CompWindow *wSubject, CompWindow *wOther)
 
264
{
 
265
    RestackPersistentData *dataCur;
 
266
    for (CompWindow *wCur = wSubject; wCur;
 
267
         wCur = dataCur->mMoreToBePaintedNext)
 
268
    {
 
269
        if (wOther == wCur)
 
270
            return true;
 
271
        dataCur = static_cast<RestackPersistentData *>
 
272
            (AnimWindow::get (wCur)->persistentData["restack"]);
 
273
        if (!dataCur)
 
274
            break;
 
275
    }
 
276
 
 
277
    RestackPersistentData *dataSubj = static_cast<RestackPersistentData *>
 
278
            (AnimWindow::get (wSubject)->
 
279
             persistentData["restack"]);
 
280
    for (CompWindow *wCur = dataSubj->mMoreToBePaintedPrev; wCur;
 
281
         wCur = dataCur->mMoreToBePaintedPrev)
 
282
    {
 
283
        if (wOther == wCur)
 
284
            return true;
 
285
        dataCur = static_cast<RestackPersistentData *>
 
286
            (AnimWindow::get (wCur)->persistentData["restack"]);
 
287
        if (!dataCur)
 
288
            break;
 
289
    }
 
290
}
 
291
 
 
292
bool
 
293
RestackAnim::overNewCopy ()
 
294
{
 
295
    bool lowering = (mRestackData->restackInfo () &&
 
296
                     !mRestackData->restackInfo ()->raised);
 
297
 
 
298
    // Reverse behavior if lowering (i.e. not raising)
 
299
    return (!lowering && mRestackData->mVisitCount == 2 ||
 
300
            lowering && mRestackData->mVisitCount == 1);
 
301
}
 
302
 
 
303
CompRegion
 
304
RestackAnim::unionRestackChain (CompWindow *w)
 
305
{
 
306
    CompRegion unionRegion;
 
307
 
 
308
    RestackPersistentData *dataCur;
 
309
    for (CompWindow *wCur = w; wCur;
 
310
         wCur = dataCur->mMoreToBePaintedNext)
 
311
    {
 
312
        unionRegion += wCur->inputRect ();
 
313
        dataCur = static_cast<RestackPersistentData *>
 
314
            (AnimWindow::get (wCur)->persistentData["restack"]);
 
315
        if (!dataCur)
 
316
            break;
 
317
    }
 
318
 
 
319
    RestackPersistentData *dataSubj = static_cast<RestackPersistentData *>
 
320
            (AnimWindow::get (w)->
 
321
             persistentData["restack"]);
 
322
    for (CompWindow *wCur = dataSubj->mMoreToBePaintedPrev; wCur;
 
323
         wCur = dataCur->mMoreToBePaintedPrev)
 
324
    {
 
325
        unionRegion += wCur->inputRect ();
 
326
        dataCur = static_cast<RestackPersistentData *>
 
327
            (AnimWindow::get (wCur)->persistentData["restack"]);
 
328
        if (!dataCur)
 
329
            break;
 
330
    }
 
331
 
 
332
    return unionRegion;
 
333
}
 
334
 
 
335
RestackInfo::RestackInfo (CompWindow *wRestacked,
 
336
                          CompWindow *wStart,
 
337
                          CompWindow *wEnd,
 
338
                          CompWindow *wOldAbove,
 
339
                          bool raised) :
 
340
    wRestacked (wRestacked),
 
341
    wStart (wStart),
 
342
    wEnd (wEnd),
 
343
    wOldAbove (wOldAbove),
 
344
    raised (raised)
 
345
{
 
346
}
 
347
 
 
348
RestackPersistentData::RestackPersistentData () :
 
349
    PersistentData (),
 
350
    mRestackInfo (0),
 
351
    mWinToBePaintedBeforeThis (0),
 
352
    mWinThisIsPaintedBefore (0),
 
353
    mMoreToBePaintedPrev (0),
 
354
    mMoreToBePaintedNext (0),
 
355
    mWinPassingThrough (0),
 
356
    mWalkerOverNewCopy (false),
 
357
    mVisitCount (0),
 
358
    mIsSecondary (false)
 
359
{
 
360
}
 
361
 
 
362
RestackPersistentData::~RestackPersistentData ()
 
363
{
 
364
    if (mRestackInfo)
 
365
        delete mRestackInfo;
 
366
}
 
367
 
 
368
void
 
369
RestackPersistentData::setRestackInfo (CompWindow *wRestacked,
 
370
                                       CompWindow *wStart,
 
371
                                       CompWindow *wEnd,
 
372
                                       CompWindow *wOldAbove,
 
373
                                       bool raised)
 
374
{
 
375
    if (mRestackInfo)
 
376
        delete mRestackInfo;
 
377
    mRestackInfo =
 
378
        new RestackInfo (wRestacked, wStart, wEnd, wOldAbove, raised);
 
379
}
 
380
 
 
381
/// Make this window be hosted on (i.e. drawn before) the given window.
 
382
void
 
383
RestackPersistentData::getHostedOnWin (CompWindow *wGuest, CompWindow *wHost)
 
384
{
 
385
    RestackPersistentData *dataHost = static_cast<RestackPersistentData *>
 
386
        (AnimWindow::get (wHost)->persistentData["restack"]);
 
387
    dataHost->mWinToBePaintedBeforeThis = wGuest;
 
388
    mWinThisIsPaintedBefore = wHost;
 
389
}
 
390