~alan-griffiths/compiz-core/Bug-931283

« back to all changes in this revision

Viewing changes to plugins/minimize.c

  • Committer: David Reveman
  • Date: 2006-02-09 06:03:09 UTC
  • Revision ID: git-v1:9959c2b13ded64a5e66359a8097250dc9d87fc1c
Initial revision

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright © 2005 Novell, Inc.
 
3
 *
 
4
 * Permission to use, copy, modify, distribute, and sell this software
 
5
 * and its documentation for any purpose is hereby granted without
 
6
 * fee, provided that the above copyright notice appear in all copies
 
7
 * and that both that copyright notice and this permission notice
 
8
 * appear in supporting documentation, and that the name of
 
9
 * Novell, Inc. not be used in advertising or publicity pertaining to
 
10
 * distribution of the software without specific, written prior permission.
 
11
 * Novell, Inc. makes no representations about the suitability of this
 
12
 * software for any purpose. It is provided "as is" without express or
 
13
 * implied warranty.
 
14
 *
 
15
 * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 
16
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
 
17
 * NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 
18
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
 
19
 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
 
20
 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 
21
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
22
 *
 
23
 * Author: David Reveman <davidr@novell.com>
 
24
 */
 
25
 
 
26
#include <X11/Xatom.h>
 
27
 
 
28
#include <stdlib.h>
 
29
#include <string.h>
 
30
#include <math.h>
 
31
 
 
32
#include <compiz.h>
 
33
 
 
34
#define MIN_SPEED_DEFAULT   1.5f
 
35
#define MIN_SPEED_MIN       0.1f
 
36
#define MIN_SPEED_MAX       50.0f
 
37
#define MIN_SPEED_PRECISION 0.1f
 
38
 
 
39
#define MIN_TIMESTEP_DEFAULT   0.5f
 
40
#define MIN_TIMESTEP_MIN       0.1f
 
41
#define MIN_TIMESTEP_MAX       50.0f
 
42
#define MIN_TIMESTEP_PRECISION 0.1f
 
43
 
 
44
static char *winType[] = {
 
45
    "Toolbar",
 
46
    "Utility",
 
47
    "Dialog",
 
48
    "Normal"
 
49
};
 
50
#define N_WIN_TYPE (sizeof (winType) / sizeof (winType[0]))
 
51
 
 
52
static int displayPrivateIndex;
 
53
 
 
54
typedef struct _MinDisplay {
 
55
    int             screenPrivateIndex;
 
56
    HandleEventProc handleEvent;
 
57
    Atom            winChangeStateAtom;
 
58
    Atom            winIconGeometryAtom;
 
59
} MinDisplay;
 
60
 
 
61
#define MIN_SCREEN_OPTION_SPEED       0
 
62
#define MIN_SCREEN_OPTION_TIMESTEP    1
 
63
#define MIN_SCREEN_OPTION_WINDOW_TYPE 2
 
64
#define MIN_SCREEN_OPTION_NUM         3
 
65
 
 
66
typedef struct _MinScreen {
 
67
    int windowPrivateIndex;
 
68
 
 
69
    CompOption opt[MIN_SCREEN_OPTION_NUM];
 
70
 
 
71
    PreparePaintScreenProc preparePaintScreen;
 
72
    DonePaintScreenProc    donePaintScreen;
 
73
    PaintScreenProc        paintScreen;
 
74
    PaintWindowProc        paintWindow;
 
75
    DamageWindowRectProc   damageWindowRect;
 
76
    FocusWindowProc        focusWindow;
 
77
 
 
78
    float speed;
 
79
    float timestep;
 
80
 
 
81
    unsigned int wMask;
 
82
 
 
83
    int moreAdjust;
 
84
} MinScreen;
 
85
 
 
86
typedef struct _MinWindow {
 
87
    GLfloat xVelocity, yVelocity, xScaleVelocity, yScaleVelocity;
 
88
    GLfloat xScale, yScale;
 
89
    GLfloat tx, ty;
 
90
 
 
91
    Bool adjust;
 
92
 
 
93
    XRectangle icon;
 
94
 
 
95
    int state, newState;
 
96
 
 
97
    int unmapCnt;
 
98
} MinWindow;
 
99
 
 
100
#define GET_MIN_DISPLAY(d)                                  \
 
101
    ((MinDisplay *) (d)->privates[displayPrivateIndex].ptr)
 
102
 
 
103
#define MIN_DISPLAY(d)                   \
 
104
    MinDisplay *md = GET_MIN_DISPLAY (d)
 
105
 
 
106
#define GET_MIN_SCREEN(s, md)                                   \
 
107
    ((MinScreen *) (s)->privates[(md)->screenPrivateIndex].ptr)
 
108
 
 
109
#define MIN_SCREEN(s)                                                \
 
110
    MinScreen *ms = GET_MIN_SCREEN (s, GET_MIN_DISPLAY (s->display))
 
111
 
 
112
#define GET_MIN_WINDOW(w, ms)                                   \
 
113
    ((MinWindow *) (w)->privates[(ms)->windowPrivateIndex].ptr)
 
114
 
 
115
#define MIN_WINDOW(w)                                      \
 
116
    MinWindow *mw = GET_MIN_WINDOW  (w,                    \
 
117
                    GET_MIN_SCREEN  (w->screen,            \
 
118
                    GET_MIN_DISPLAY (w->screen->display)))
 
119
 
 
120
#define NUM_OPTIONS(s) (sizeof ((s)->opt) / sizeof (CompOption))
 
121
 
 
122
static CompOption *
 
123
minGetScreenOptions (CompScreen *screen,
 
124
                     int        *count)
 
125
{
 
126
    MIN_SCREEN (screen);
 
127
 
 
128
    *count = NUM_OPTIONS (ms);
 
129
    return ms->opt;
 
130
}
 
131
 
 
132
static Bool
 
133
minSetScreenOption (CompScreen      *screen,
 
134
                    char            *name,
 
135
                    CompOptionValue *value)
 
136
{
 
137
    CompOption *o;
 
138
    int        index;
 
139
 
 
140
    MIN_SCREEN (screen);
 
141
 
 
142
    o = compFindOption (ms->opt, NUM_OPTIONS (ms), name, &index);
 
143
    if (!o)
 
144
        return FALSE;
 
145
 
 
146
    switch (index) {
 
147
    case MIN_SCREEN_OPTION_SPEED:
 
148
        if (compSetFloatOption (o, value))
 
149
        {
 
150
            ms->speed = o->value.f;
 
151
            return TRUE;
 
152
        }
 
153
        break;
 
154
    case MIN_SCREEN_OPTION_TIMESTEP:
 
155
        if (compSetFloatOption (o, value))
 
156
        {
 
157
            ms->timestep = o->value.f;
 
158
            return TRUE;
 
159
        }
 
160
        break;
 
161
    case MIN_SCREEN_OPTION_WINDOW_TYPE:
 
162
        if (compSetOptionList (o, value))
 
163
        {
 
164
            ms->wMask = compWindowTypeMaskFromStringList (&o->value);
 
165
            return TRUE;
 
166
        }
 
167
    default:
 
168
        break;
 
169
    }
 
170
 
 
171
    return FALSE;
 
172
}
 
173
 
 
174
static void
 
175
minScreenInitOptions (MinScreen *ms)
 
176
{
 
177
    CompOption *o;
 
178
    int        i;
 
179
 
 
180
    o = &ms->opt[MIN_SCREEN_OPTION_SPEED];
 
181
    o->name             = "speed";
 
182
    o->shortDesc        = "Speed";
 
183
    o->longDesc         = "Minimize speed";
 
184
    o->type             = CompOptionTypeFloat;
 
185
    o->value.f          = MIN_SPEED_DEFAULT;
 
186
    o->rest.f.min       = MIN_SPEED_MIN;
 
187
    o->rest.f.max       = MIN_SPEED_MAX;
 
188
    o->rest.f.precision = MIN_SPEED_PRECISION;
 
189
 
 
190
    o = &ms->opt[MIN_SCREEN_OPTION_TIMESTEP];
 
191
    o->name             = "timestep";
 
192
    o->shortDesc        = "Timestep";
 
193
    o->longDesc         = "Minimize timestep";
 
194
    o->type             = CompOptionTypeFloat;
 
195
    o->value.f          = MIN_TIMESTEP_DEFAULT;
 
196
    o->rest.f.min       = MIN_TIMESTEP_MIN;
 
197
    o->rest.f.max       = MIN_TIMESTEP_MAX;
 
198
    o->rest.f.precision = MIN_TIMESTEP_PRECISION;
 
199
 
 
200
    o = &ms->opt[MIN_SCREEN_OPTION_WINDOW_TYPE];
 
201
    o->name              = "window_types";
 
202
    o->shortDesc         = "Window Types";
 
203
    o->longDesc          = "Window types that should be transformed when "
 
204
        "minimized";
 
205
    o->type              = CompOptionTypeList;
 
206
    o->value.list.type   = CompOptionTypeString;
 
207
    o->value.list.nValue = N_WIN_TYPE;
 
208
    o->value.list.value  = malloc (sizeof (CompOptionValue) * N_WIN_TYPE);
 
209
    for (i = 0; i < N_WIN_TYPE; i++)
 
210
        o->value.list.value[i].s = strdup (winType[i]);
 
211
    o->rest.s.string     = windowTypeString;
 
212
    o->rest.s.nString    = nWindowTypeString;
 
213
 
 
214
    ms->wMask = compWindowTypeMaskFromStringList (&o->value);
 
215
}
 
216
 
 
217
static Bool
 
218
minGetWindowIconGeometry (CompWindow *w,
 
219
                          XRectangle *rect)
 
220
{
 
221
    Atom          actual;
 
222
    int           result, format;
 
223
    unsigned long n, left;
 
224
    unsigned char *data;
 
225
 
 
226
    MIN_DISPLAY (w->screen->display);
 
227
 
 
228
    result = XGetWindowProperty (w->screen->display->display, w->id,
 
229
                                 md->winIconGeometryAtom,
 
230
                                 0L, 4L, FALSE, XA_CARDINAL, &actual, &format,
 
231
                                 &n, &left, &data);
 
232
 
 
233
    if (result == Success && n && data)
 
234
    {
 
235
        if (n == 4)
 
236
        {
 
237
            unsigned long *geometry = (unsigned long *) data;
 
238
 
 
239
            rect->x      = geometry[0];
 
240
            rect->y      = geometry[1];
 
241
            rect->width  = geometry[2];
 
242
            rect->height = geometry[3];
 
243
 
 
244
            XFree (data);
 
245
 
 
246
            return TRUE;
 
247
        }
 
248
 
 
249
        XFree (data);
 
250
    }
 
251
 
 
252
    return FALSE;
 
253
}
 
254
 
 
255
static int
 
256
minGetWindowState (CompWindow *w)
 
257
{
 
258
    Atom          actual;
 
259
    int           result, format;
 
260
    unsigned long n, left;
 
261
    unsigned char *data;
 
262
 
 
263
    result = XGetWindowProperty (w->screen->display->display, w->id,
 
264
                                 w->screen->display->wmStateAtom, 0L, 1L, FALSE,
 
265
                                 w->screen->display->wmStateAtom,
 
266
                                 &actual, &format, &n, &left, &data);
 
267
 
 
268
    if (result == Success && n && data)
 
269
    {
 
270
        int state;
 
271
 
 
272
        memcpy (&state, data, sizeof (int));
 
273
        XFree ((void *) data);
 
274
 
 
275
        return state;
 
276
    }
 
277
 
 
278
    return WithdrawnState;
 
279
}
 
280
 
 
281
static int
 
282
adjustMinVelocity (CompWindow *w)
 
283
{
 
284
    float dx, dy, dxs, dys, adjust, amount;
 
285
    float x1, y1, xScale, yScale;
 
286
 
 
287
    MIN_WINDOW (w);
 
288
 
 
289
    if (mw->newState == IconicState)
 
290
    {
 
291
        x1 = mw->icon.x;
 
292
        y1 = mw->icon.y;
 
293
        xScale = (float) mw->icon.width  / w->width;
 
294
        yScale = (float) mw->icon.height / w->height;
 
295
    }
 
296
    else
 
297
    {
 
298
        x1 = w->serverX;
 
299
        y1 = w->serverY;
 
300
        xScale = yScale = 1.0f;
 
301
    }
 
302
 
 
303
    dx = x1 - w->attrib.x;
 
304
 
 
305
    adjust = dx * 0.15f;
 
306
    amount = fabs (dx) * 1.5f;
 
307
    if (amount < 0.5f)
 
308
        amount = 0.5f;
 
309
    else if (amount > 5.0f)
 
310
        amount = 5.0f;
 
311
 
 
312
    mw->xVelocity = (amount * mw->xVelocity + adjust) / (amount + 1.0f);
 
313
 
 
314
    dy = y1 - w->attrib.y;
 
315
 
 
316
    adjust = dy * 0.15f;
 
317
    amount = fabs (dy) * 1.5f;
 
318
    if (amount < 0.5f)
 
319
        amount = 0.5f;
 
320
    else if (amount > 5.0f)
 
321
        amount = 5.0f;
 
322
 
 
323
    mw->yVelocity = (amount * mw->yVelocity + adjust) / (amount + 1.0f);
 
324
 
 
325
    dxs = xScale - mw->xScale;
 
326
 
 
327
    adjust = dxs * 0.15f;
 
328
    amount = fabs (dxs) * 10.0f;
 
329
    if (amount < 0.01f)
 
330
        amount = 0.01f;
 
331
    else if (amount > 0.15f)
 
332
        amount = 0.15f;
 
333
 
 
334
    mw->xScaleVelocity = (amount * mw->xScaleVelocity + adjust) /
 
335
        (amount + 1.0f);
 
336
 
 
337
    dys = yScale - mw->yScale;
 
338
 
 
339
    adjust = dys * 0.15f;
 
340
    amount = fabs (dys) * 10.0f;
 
341
    if (amount < 0.01f)
 
342
        amount = 0.01f;
 
343
    else if (amount > 0.15f)
 
344
        amount = 0.15f;
 
345
 
 
346
    mw->yScaleVelocity = (amount * mw->yScaleVelocity + adjust) /
 
347
        (amount + 1.0f);
 
348
 
 
349
    if (fabs (dx) < 0.1f    && fabs (mw->xVelocity)      < 0.2f   &&
 
350
        fabs (dy) < 0.1f    && fabs (mw->yVelocity)      < 0.2f   &&
 
351
        fabs (dxs) < 0.001f && fabs (mw->xScaleVelocity) < 0.002f &&
 
352
        fabs (dys) < 0.001f && fabs (mw->yScaleVelocity) < 0.002f)
 
353
    {
 
354
        mw->xVelocity = mw->yVelocity = mw->xScaleVelocity =
 
355
            mw->yScaleVelocity = 0.0f;
 
356
        mw->tx = x1 - w->attrib.x;
 
357
        mw->ty = y1 - w->attrib.y;
 
358
        mw->xScale = xScale;
 
359
        mw->yScale = yScale;
 
360
 
 
361
        return 0;
 
362
    }
 
363
 
 
364
    return 1;
 
365
}
 
366
 
 
367
static void
 
368
minPreparePaintScreen (CompScreen *s,
 
369
                       int        msSinceLastPaint)
 
370
{
 
371
    MIN_SCREEN (s);
 
372
 
 
373
    if (ms->moreAdjust)
 
374
    {
 
375
        CompWindow *w;
 
376
        int        steps, dx, dy;
 
377
        float      amount, chunk;
 
378
 
 
379
        amount = msSinceLastPaint * 0.05f * ms->speed;
 
380
        steps  = amount / (0.5f * ms->timestep);
 
381
        if (!steps) steps = 1;
 
382
        chunk  = amount / (float) steps;
 
383
 
 
384
        while (steps--)
 
385
        {
 
386
            ms->moreAdjust = 0;
 
387
 
 
388
            for (w = s->windows; w; w = w->next)
 
389
            {
 
390
                MIN_WINDOW (w);
 
391
 
 
392
                if (mw->adjust)
 
393
                {
 
394
                    mw->adjust = adjustMinVelocity (w);
 
395
 
 
396
                    ms->moreAdjust |= mw->adjust;
 
397
 
 
398
                    mw->tx += mw->xVelocity * chunk;
 
399
                    mw->ty += mw->yVelocity * chunk;
 
400
                    mw->xScale += mw->xScaleVelocity * chunk;
 
401
                    mw->yScale += mw->yScaleVelocity * chunk;
 
402
 
 
403
                    dx = (w->serverX + mw->tx) - w->attrib.x;
 
404
                    dy = (w->serverY + mw->ty) - w->attrib.y;
 
405
 
 
406
                    moveWindow (w, dx, dy, FALSE);
 
407
 
 
408
                    (*s->setWindowScale) (w, mw->xScale, mw->yScale);
 
409
 
 
410
                    if (!mw->adjust)
 
411
                    {
 
412
                        mw->state = mw->newState;
 
413
 
 
414
                        while (mw->unmapCnt)
 
415
                        {
 
416
                            unmapWindow (w);
 
417
                            mw->unmapCnt--;
 
418
                        }
 
419
                    }
 
420
                }
 
421
            }
 
422
 
 
423
            if (!ms->moreAdjust)
 
424
                break;
 
425
        }
 
426
 
 
427
        if (ms->moreAdjust)
 
428
        {
 
429
            for (w = s->windows; w; w = w->next)
 
430
            {
 
431
                MIN_WINDOW (w);
 
432
 
 
433
                if (mw->adjust)
 
434
                    addWindowDamage (w);
 
435
            }
 
436
        }
 
437
    }
 
438
 
 
439
    UNWRAP (ms, s, preparePaintScreen);
 
440
    (*s->preparePaintScreen) (s, msSinceLastPaint);
 
441
    WRAP (ms, s, preparePaintScreen, minPreparePaintScreen);
 
442
}
 
443
 
 
444
static void
 
445
minDonePaintScreen (CompScreen *s)
 
446
{
 
447
    MIN_SCREEN (s);
 
448
 
 
449
    if (ms->moreAdjust)
 
450
    {
 
451
        CompWindow *w;
 
452
 
 
453
        for (w = s->windows; w; w = w->next)
 
454
        {
 
455
            MIN_WINDOW (w);
 
456
 
 
457
            if (mw->adjust)
 
458
                addWindowDamage (w);
 
459
        }
 
460
    }
 
461
 
 
462
    UNWRAP (ms, s, donePaintScreen);
 
463
    (*s->donePaintScreen) (s);
 
464
    WRAP (ms, s, donePaintScreen, minDonePaintScreen);
 
465
}
 
466
 
 
467
static Bool
 
468
minPaintScreen (CompScreen              *s,
 
469
                const ScreenPaintAttrib *sAttrib,
 
470
                Region                  region,
 
471
                unsigned int            mask)
 
472
{
 
473
    Bool status;
 
474
 
 
475
    MIN_SCREEN (s);
 
476
 
 
477
    if (ms->moreAdjust)
 
478
        mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS_MASK;
 
479
 
 
480
    UNWRAP (ms, s, paintScreen);
 
481
    status = (*s->paintScreen) (s, sAttrib, region, mask);
 
482
    WRAP (ms, s, paintScreen, minPaintScreen);
 
483
 
 
484
    return status;
 
485
}
 
486
 
 
487
static Bool
 
488
minPaintWindow (CompWindow              *w,
 
489
                const WindowPaintAttrib *attrib,
 
490
                Region                  region,
 
491
                unsigned int            mask)
 
492
{
 
493
    CompScreen *s = w->screen;
 
494
    Bool       status;
 
495
 
 
496
    MIN_SCREEN (s);
 
497
    MIN_WINDOW (w);
 
498
 
 
499
    if (mw->adjust)
 
500
        mask |= PAINT_WINDOW_TRANSFORMED_MASK;
 
501
 
 
502
    UNWRAP (ms, s, paintWindow);
 
503
    status = (*s->paintWindow) (w, attrib, region, mask);
 
504
    WRAP (ms, s, paintWindow, minPaintWindow);
 
505
 
 
506
    return status;
 
507
}
 
508
 
 
509
static void
 
510
minHandleEvent (CompDisplay *d,
 
511
                XEvent      *event)
 
512
{
 
513
    CompWindow *w;
 
514
 
 
515
    MIN_DISPLAY (d);
 
516
 
 
517
    switch (event->type) {
 
518
    case MapNotify:
 
519
        w = findWindowAtDisplay (d, event->xmap.window);
 
520
        if (w)
 
521
        {
 
522
            MIN_WINDOW (w);
 
523
 
 
524
            if (mw->adjust)
 
525
                mw->state = mw->newState;
 
526
 
 
527
            while (mw->unmapCnt)
 
528
            {
 
529
                unmapWindow (w);
 
530
                mw->unmapCnt--;
 
531
            }
 
532
        }
 
533
        break;
 
534
    case UnmapNotify:
 
535
        w = findWindowAtDisplay (d, event->xunmap.window);
 
536
        if (w && (w->state & CompWindowStateHiddenMask))
 
537
        {
 
538
            MIN_SCREEN (w->screen);
 
539
 
 
540
            if (!w->invisible && (ms->wMask & w->type))
 
541
            {
 
542
                MIN_WINDOW (w);
 
543
 
 
544
                mw->newState = IconicState;
 
545
 
 
546
                if (minGetWindowIconGeometry (w, &mw->icon))
 
547
                {
 
548
                    mw->adjust     = TRUE;
 
549
                    ms->moreAdjust = TRUE;
 
550
 
 
551
                    mw->unmapCnt++;
 
552
                    w->unmapRefCnt++;
 
553
 
 
554
                    addWindowDamage (w);
 
555
                }
 
556
                else
 
557
                {
 
558
                    mw->state = mw->newState;
 
559
                }
 
560
            }
 
561
        }
 
562
    default:
 
563
        break;
 
564
    }
 
565
 
 
566
    UNWRAP (md, d, handleEvent);
 
567
    (*d->handleEvent) (d, event);
 
568
    WRAP (md, d, handleEvent, minHandleEvent);
 
569
}
 
570
 
 
571
static Bool
 
572
minDamageWindowRect (CompWindow *w,
 
573
                     Bool       initial,
 
574
                     BoxPtr     rect)
 
575
{
 
576
    Bool status;
 
577
 
 
578
    MIN_SCREEN (w->screen);
 
579
 
 
580
    if (initial && !w->invisible && (ms->wMask & w->type))
 
581
    {
 
582
        MIN_WINDOW (w);
 
583
 
 
584
        if (mw->state == IconicState)
 
585
        {
 
586
            if (minGetWindowIconGeometry (w, &mw->icon))
 
587
            {
 
588
                if (!mw->adjust)
 
589
                {
 
590
                    mw->adjust     = TRUE;
 
591
                    ms->moreAdjust = TRUE;
 
592
 
 
593
                    mw->tx     = mw->icon.x - w->serverX;
 
594
                    mw->ty     = mw->icon.y - w->serverY;
 
595
                    mw->xScale = (float) mw->icon.width  / w->width;
 
596
                    mw->yScale = (float) mw->icon.height / w->height;
 
597
 
 
598
                    moveWindow (w,
 
599
                                mw->icon.x - w->attrib.x,
 
600
                                mw->icon.y - w->attrib.y,
 
601
                                FALSE);
 
602
 
 
603
                    (*w->screen->setWindowScale) (w, mw->xScale, mw->yScale);
 
604
 
 
605
                    addWindowDamage (w);
 
606
                }
 
607
            }
 
608
        }
 
609
 
 
610
        mw->newState = NormalState;
 
611
    }
 
612
 
 
613
    UNWRAP (ms, w->screen, damageWindowRect);
 
614
    status = (*w->screen->damageWindowRect) (w, initial, rect);
 
615
    WRAP (ms, w->screen, damageWindowRect, minDamageWindowRect);
 
616
 
 
617
    return status;
 
618
}
 
619
 
 
620
static Bool
 
621
minFocusWindow (CompWindow *w)
 
622
{
 
623
    Bool status;
 
624
 
 
625
    MIN_SCREEN (w->screen);
 
626
    MIN_WINDOW (w);
 
627
 
 
628
    if (mw->unmapCnt)
 
629
        return FALSE;
 
630
 
 
631
    UNWRAP (ms, w->screen, focusWindow);
 
632
    status = (*w->screen->focusWindow) (w);
 
633
    WRAP (ms, w->screen, focusWindow, minFocusWindow);
 
634
 
 
635
    return status;
 
636
}
 
637
 
 
638
static Bool
 
639
minInitDisplay (CompPlugin  *p,
 
640
                CompDisplay *d)
 
641
{
 
642
    MinDisplay *md;
 
643
 
 
644
    md = malloc (sizeof (MinDisplay));
 
645
    if (!md)
 
646
        return FALSE;
 
647
 
 
648
    md->screenPrivateIndex = allocateScreenPrivateIndex (d);
 
649
    if (md->screenPrivateIndex < 0)
 
650
    {
 
651
        free (md);
 
652
        return FALSE;
 
653
    }
 
654
 
 
655
    md->winChangeStateAtom  = XInternAtom (d->display, "WM_CHANGE_STATE", 0);
 
656
    md->winIconGeometryAtom =
 
657
        XInternAtom (d->display, "_NET_WM_ICON_GEOMETRY", 0);
 
658
 
 
659
    WRAP (md, d, handleEvent, minHandleEvent);
 
660
 
 
661
    d->privates[displayPrivateIndex].ptr = md;
 
662
 
 
663
    return TRUE;
 
664
}
 
665
 
 
666
static void
 
667
minFiniDisplay (CompPlugin  *p,
 
668
                CompDisplay *d)
 
669
{
 
670
    MIN_DISPLAY (d);
 
671
 
 
672
    freeScreenPrivateIndex (d, md->screenPrivateIndex);
 
673
 
 
674
    UNWRAP (md, d, handleEvent);
 
675
 
 
676
    free (md);
 
677
}
 
678
 
 
679
static Bool
 
680
minInitScreen (CompPlugin *p,
 
681
               CompScreen *s)
 
682
{
 
683
    MinScreen *ms;
 
684
 
 
685
    MIN_DISPLAY (s->display);
 
686
 
 
687
    ms = malloc (sizeof (MinScreen));
 
688
    if (!ms)
 
689
        return FALSE;
 
690
 
 
691
    ms->windowPrivateIndex = allocateWindowPrivateIndex (s);
 
692
    if (ms->windowPrivateIndex < 0)
 
693
    {
 
694
        free (ms);
 
695
        return FALSE;
 
696
    }
 
697
 
 
698
    ms->moreAdjust = FALSE;
 
699
 
 
700
    ms->speed    = MIN_SPEED_DEFAULT;
 
701
    ms->timestep = MIN_TIMESTEP_DEFAULT;
 
702
 
 
703
    minScreenInitOptions (ms);
 
704
 
 
705
    WRAP (ms, s, preparePaintScreen, minPreparePaintScreen);
 
706
    WRAP (ms, s, donePaintScreen, minDonePaintScreen);
 
707
    WRAP (ms, s, paintScreen, minPaintScreen);
 
708
    WRAP (ms, s, paintWindow, minPaintWindow);
 
709
    WRAP (ms, s, damageWindowRect, minDamageWindowRect);
 
710
    WRAP (ms, s, focusWindow, minFocusWindow);
 
711
 
 
712
    s->privates[md->screenPrivateIndex].ptr = ms;
 
713
 
 
714
    return TRUE;
 
715
}
 
716
 
 
717
static void
 
718
minFiniScreen (CompPlugin *p,
 
719
               CompScreen *s)
 
720
{
 
721
    MIN_SCREEN (s);
 
722
 
 
723
    freeWindowPrivateIndex (s, ms->windowPrivateIndex);
 
724
 
 
725
    UNWRAP (ms, s, preparePaintScreen);
 
726
    UNWRAP (ms, s, donePaintScreen);
 
727
    UNWRAP (ms, s, paintScreen);
 
728
    UNWRAP (ms, s, paintWindow);
 
729
    UNWRAP (ms, s, damageWindowRect);
 
730
    UNWRAP (ms, s, focusWindow);
 
731
 
 
732
    free (ms);
 
733
}
 
734
 
 
735
static Bool
 
736
minInitWindow (CompPlugin *p,
 
737
               CompWindow *w)
 
738
{
 
739
    MinWindow *mw;
 
740
 
 
741
    MIN_SCREEN (w->screen);
 
742
 
 
743
    mw = malloc (sizeof (MinWindow));
 
744
    if (!mw)
 
745
        return FALSE;
 
746
 
 
747
    mw->xScale = mw->yScale = 1.0f;
 
748
    mw->tx = mw->ty = 0.0f;
 
749
    mw->adjust = FALSE;
 
750
    mw->xVelocity = mw->yVelocity = 0.0f;
 
751
    mw->xScaleVelocity = mw->yScaleVelocity = 1.0f;
 
752
 
 
753
    mw->unmapCnt = 0;
 
754
 
 
755
    mw->state = mw->newState = minGetWindowState (w);
 
756
 
 
757
    w->privates[ms->windowPrivateIndex].ptr = mw;
 
758
 
 
759
    return TRUE;
 
760
}
 
761
 
 
762
static void
 
763
minFiniWindow (CompPlugin *p,
 
764
               CompWindow *w)
 
765
{
 
766
    MIN_WINDOW (w);
 
767
 
 
768
    while (mw->unmapCnt--)
 
769
        unmapWindow (w);
 
770
 
 
771
    free (mw);
 
772
}
 
773
 
 
774
static Bool
 
775
minInit (CompPlugin *p)
 
776
{
 
777
    displayPrivateIndex = allocateDisplayPrivateIndex ();
 
778
    if (displayPrivateIndex < 0)
 
779
        return FALSE;
 
780
 
 
781
    return TRUE;
 
782
}
 
783
 
 
784
static void
 
785
minFini (CompPlugin *p)
 
786
{
 
787
    if (displayPrivateIndex >= 0)
 
788
        freeDisplayPrivateIndex (displayPrivateIndex);
 
789
}
 
790
 
 
791
CompPluginDep minDeps[] = {
 
792
    { CompPluginRuleBefore, "cube" },
 
793
    { CompPluginRuleBefore, "expose" }
 
794
};
 
795
 
 
796
static CompPluginVTable minVTable = {
 
797
    "minimize",
 
798
    "Minimize Effect",
 
799
    "Transform windows when they are minimized and unminimized",
 
800
    minInit,
 
801
    minFini,
 
802
    minInitDisplay,
 
803
    minFiniDisplay,
 
804
    minInitScreen,
 
805
    minFiniScreen,
 
806
    minInitWindow,
 
807
    minFiniWindow,
 
808
    0, /* GetDisplayOptions */
 
809
    0, /* SetDisplayOption */
 
810
    minGetScreenOptions,
 
811
    minSetScreenOption,
 
812
    minDeps,
 
813
    sizeof (minDeps) / sizeof (minDeps[0])
 
814
};
 
815
 
 
816
CompPluginVTable *
 
817
getCompPluginInfo (void)
 
818
{
 
819
    return &minVTable;
 
820
}