~lbrulet-8/compiz-plugins-main/fix-876591

« back to all changes in this revision

Viewing changes to .pc/01-grid-fix-rev87.patch/grid/src/grid.cpp

  • Committer: Package Import Robot
  • Author(s): Didier Roche, David Barth, Didier Roche
  • Date: 2011-09-09 16:21:26 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: package-import@ubuntu.com-20110909162126-vf2y3xv7anhjtq5c
Tags: 1:0.9.5.94-0ubuntu1
[ David Barth ] 
* Test build for release (0.9.5.94) 
* Removed patches integrated upstream:
  - debian/patches/01_grid_defaults.patch
* Add another patch for the same grid, but with other changes
  - debian/patches/01-grid-fix-rev87.patch: prevent eye bleeding

[ Didier Roche ]
* debian/control: bump build-dep for ABI break

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Compiz Fusion Grid plugin
 
3
 *
 
4
 * Copyright (c) 2008 Stephen Kennedy <suasol@gmail.com>
 
5
 * Copyright (c) 2010 Scott Moreau <oreaus@gmail.com>
 
6
 *
 
7
 * This program is free software; you can redistribute it and/or
 
8
 * modify it under the terms of the GNU General Public License
 
9
 * as published by the Free Software Foundation; either version 2
 
10
 * of the License, or (at your option) any later version.
 
11
 *
 
12
 * This program is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
 * GNU General Public License for more details.
 
16
 *
 
17
 * Description:
 
18
 *
 
19
 * Plugin to act like winsplit revolution (http://www.winsplit-revolution.com/)
 
20
 * use <Control><Alt>NUMPAD_KEY to move and tile your windows.
 
21
 *
 
22
 * Press the tiling keys several times to cycle through some tiling options.
 
23
 */
 
24
 
 
25
#include "grid.h"
 
26
 
 
27
static const GridProps gridProps[] =
 
28
{
 
29
    {0,1, 1,1},
 
30
 
 
31
    {0,1, 2,2},
 
32
    {0,1, 1,2},
 
33
    {1,1, 2,2},
 
34
 
 
35
    {0,0, 2,1},
 
36
    {0,0, 1,1},
 
37
    {1,0, 2,1},
 
38
 
 
39
    {0,0, 2,2},
 
40
    {0,0, 1,2},
 
41
    {1,0, 2,2},
 
42
 
 
43
    {0,0, 1,1},
 
44
};
 
45
 
 
46
CompRect
 
47
GridScreen::slotToRect (CompWindow      *w,
 
48
                        const CompRect& slot)
 
49
{
 
50
    return CompRect (slot.x () + w->border ().left,
 
51
                     slot.y () + w->border ().top,
 
52
                     slot.width () - (w->border ().left + w->border ().right),
 
53
                     slot.height () - (w->border ().top + w->border ().bottom));
 
54
}
 
55
 
 
56
CompRect
 
57
GridScreen::constrainSize (CompWindow      *w,
 
58
                           const CompRect& slot)
 
59
{
 
60
    CompRect result;
 
61
    int      cw, ch;
 
62
 
 
63
    result = slotToRect (w, slot);
 
64
 
 
65
    if (w->constrainNewWindowSize (result.width (), result.height (), &cw, &ch))
 
66
    {
 
67
        /* constrained size may put window offscreen, adjust for that case */
 
68
        int dx = result.x () + cw - workarea.right () + w->border ().right;
 
69
        int dy = result.y () + ch - workarea.bottom () + w->border ().bottom;
 
70
 
 
71
        if (dx > 0)
 
72
            result.setX (result.x () - dx);
 
73
        if (dy > 0)
 
74
            result.setY (result.y () - dy);
 
75
 
 
76
        result.setWidth (cw);
 
77
        result.setHeight (ch);
 
78
    }
 
79
 
 
80
    return result;
 
81
}
 
82
 
 
83
void
 
84
GridScreen::getPaintRectangle (CompRect &cRect)
 
85
{
 
86
    if (edgeToGridType () != GridUnknown && optionGetDrawIndicator ())
 
87
        cRect = desiredSlot;
 
88
    else
 
89
        cRect.setGeometry (0, 0, 0, 0);
 
90
}
 
91
 
 
92
int
 
93
applyProgress (int a, int b, float progress)
 
94
{
 
95
        return a < b ?
 
96
         b - (ABS (a - b) * progress) :
 
97
         b + (ABS (a - b) * progress);
 
98
}
 
99
 
 
100
void
 
101
GridScreen::setCurrentRect (Animation &anim)
 
102
{
 
103
        anim.currentRect.setLeft (applyProgress (anim.targetRect.x1 (),
 
104
                                                                                                        anim.fromRect.x1 (),
 
105
                                                                                                        anim.progress));
 
106
        anim.currentRect.setRight (applyProgress (anim.targetRect.x2 (),
 
107
                                                                                                        anim.fromRect.x2 (),
 
108
                                                                                                        anim.progress));
 
109
        anim.currentRect.setTop (applyProgress (anim.targetRect.y1 (),
 
110
                                                                                                        anim.fromRect.y1 (),
 
111
                                                                                                        anim.progress));
 
112
        anim.currentRect.setBottom (applyProgress (anim.targetRect.y2 (),
 
113
                                                                                                        anim.fromRect.y2 (),
 
114
                                                                                                        anim.progress));
 
115
}
 
116
 
 
117
bool
 
118
GridScreen::initiateCommon (CompAction         *action,
 
119
                            CompAction::State  state,
 
120
                            CompOption::Vector &option,
 
121
                            GridType           where,
 
122
                            bool               resize)
 
123
{
 
124
    Window     xid;
 
125
    CompWindow *cw = 0;
 
126
 
 
127
    xid = CompOption::getIntOptionNamed (option, "window");
 
128
    cw  = screen->findWindow (xid);
 
129
 
 
130
    if (where == GridUnknown || screen->otherGrabExist ("move", NULL))
 
131
        return false;
 
132
 
 
133
    if (cw)
 
134
    {
 
135
        XWindowChanges xwc;
 
136
 
 
137
        GRID_WINDOW (cw);
 
138
 
 
139
        if (gw->lastTarget != where)
 
140
            gw->resizeCount = 0;
 
141
 
 
142
        props = gridProps[where];
 
143
 
 
144
        /* get current available area */
 
145
        if (cw == mGrabWindow)
 
146
            workarea = screen->getWorkareaForOutput
 
147
                            (screen->outputDeviceForPoint (pointerX, pointerY));
 
148
        else
 
149
        {
 
150
            workarea = screen->getWorkareaForOutput (cw->outputDevice ());
 
151
 
 
152
            if (props.numCellsX == 1)
 
153
                centerCheck = true;
 
154
 
 
155
            if (!gw->isGridResized)
 
156
                /* Store size not including borders when using a keybinding */
 
157
                gw->originalSize = slotToRect(cw, cw->serverBorderRect ());
 
158
        }
 
159
 
 
160
        if ((cw->state () & MAXIMIZE_STATE) &&
 
161
            (resize || optionGetSnapoffMaximized ()))
 
162
        {
 
163
            /* maximized state interferes with us, clear it */
 
164
            cw->maximize (0);
 
165
        }
 
166
 
 
167
        if (where == GridMaximize && resize)
 
168
        {
 
169
            /* move the window to the correct output */
 
170
            if (cw == mGrabWindow)
 
171
            {
 
172
                xwc.x = workarea.x () + 50;
 
173
                xwc.y = workarea.y () + 50;
 
174
                xwc.width = workarea.width ();
 
175
                xwc.height = workarea.height ();
 
176
                cw->configureXWindow (CWX | CWY, &xwc);
 
177
            }
 
178
            cw->maximize (MAXIMIZE_STATE);
 
179
            gw->isGridResized = true;
 
180
            gw->isGridMaximized = true;
 
181
                for (unsigned int i = 0; i < animations.size (); i++)
 
182
                        animations.at (i).fadingOut = true;
 
183
            return true;
 
184
        }
 
185
 
 
186
        /* Convention:
 
187
         * xxxSlot include decorations (it's the screen area occupied)
 
188
         * xxxRect are undecorated (it's the constrained position
 
189
                                    of the contents)
 
190
         */
 
191
 
 
192
        /* slice and dice to get desired slot - including decorations */
 
193
        desiredSlot.setY (workarea.y () + props.gravityDown *
 
194
                          (workarea.height () / props.numCellsY));
 
195
        desiredSlot.setHeight (workarea.height () / props.numCellsY);
 
196
        desiredSlot.setX (workarea.x () + props.gravityRight *
 
197
                          (workarea.width () / props.numCellsX));
 
198
        desiredSlot.setWidth (workarea.width () / props.numCellsX);
 
199
 
 
200
        /* Adjust for constraints and decorations */
 
201
        desiredRect = constrainSize (cw, desiredSlot);
 
202
        /* Get current rect not including decorations */
 
203
        currentRect.setGeometry (cw->serverX (), cw->serverY (),
 
204
                                 cw->serverWidth (),
 
205
                                 cw->serverHeight ());
 
206
 
 
207
        if (desiredRect.y () == currentRect.y () &&
 
208
            desiredRect.height () == currentRect.height () &&
 
209
            where != GridMaximize && gw->lastTarget == where)
 
210
        {
 
211
            int slotWidth25  = workarea.width () / 4;
 
212
            int slotWidth33  = (workarea.width () / 3) + cw->border ().left;
 
213
            int slotWidth17  = slotWidth33 - slotWidth25;
 
214
            int slotWidth66  = workarea.width () - slotWidth33;
 
215
            int slotWidth75  = workarea.width () - slotWidth25;
 
216
 
 
217
            if (props.numCellsX == 2) /* keys (1, 4, 7, 3, 6, 9) */
 
218
            {
 
219
                if ((currentRect.width () == desiredRect.width () &&
 
220
                    currentRect.x () == desiredRect.x ()) ||
 
221
                    (gw->resizeCount < 1) || (gw->resizeCount > 5))
 
222
                    gw->resizeCount = 3;
 
223
 
 
224
                /* tricky, have to allow for window constraints when
 
225
                 * computing what the 33% and 66% offsets would be
 
226
                 */
 
227
                switch (gw->resizeCount)
 
228
                {
 
229
                    case 1:
 
230
                        desiredSlot.setWidth (slotWidth66);
 
231
                        desiredSlot.setX (workarea.x () +
 
232
                                          props.gravityRight * slotWidth33);
 
233
                        gw->resizeCount++;
 
234
                        break;
 
235
                    case 2:
 
236
                        gw->resizeCount++;
 
237
                        break;
 
238
                    case 3:
 
239
                        desiredSlot.setWidth (slotWidth33);
 
240
                        desiredSlot.setX (workarea.x () +
 
241
                                          props.gravityRight * slotWidth66);
 
242
                        gw->resizeCount++;
 
243
                        break;
 
244
                    case 4:
 
245
                        desiredSlot.setWidth (slotWidth25);
 
246
                        desiredSlot.setX (workarea.x () +
 
247
                                          props.gravityRight * slotWidth75);
 
248
                        gw->resizeCount++;
 
249
                        break;
 
250
                    case 5:
 
251
                        desiredSlot.setWidth (slotWidth75);
 
252
                        desiredSlot.setX (workarea.x () +
 
253
                                          props.gravityRight * slotWidth25);
 
254
                        gw->resizeCount++;
 
255
                        break;
 
256
                    default:
 
257
                        break;
 
258
                }
 
259
            }
 
260
            else /* keys (2, 5, 8) */
 
261
            {
 
262
 
 
263
                if ((currentRect.width () == desiredRect.width () &&
 
264
                    currentRect.x () == desiredRect.x ()) ||
 
265
                    (gw->resizeCount < 1) || (gw->resizeCount > 5))
 
266
                    gw->resizeCount = 1;
 
267
            
 
268
                switch (gw->resizeCount)
 
269
                {
 
270
                    case 1:
 
271
                        desiredSlot.setWidth (workarea.width () -
 
272
                                             (slotWidth17 * 2));
 
273
                        desiredSlot.setX (workarea.x () + slotWidth17);
 
274
                        gw->resizeCount++;
 
275
                        break;
 
276
                    case 2:
 
277
                        desiredSlot.setWidth ((slotWidth25 * 2) +
 
278
                                              (slotWidth17 * 2));
 
279
                        desiredSlot.setX (workarea.x () +
 
280
                                         (slotWidth25 - slotWidth17));
 
281
                        gw->resizeCount++;
 
282
                        break;
 
283
                    case 3:
 
284
                        desiredSlot.setWidth ((slotWidth25 * 2));
 
285
                        desiredSlot.setX (workarea.x () + slotWidth25);
 
286
                        gw->resizeCount++;
 
287
                        break;
 
288
                    case 4:
 
289
                        desiredSlot.setWidth (slotWidth33 -
 
290
                            (cw->border ().left + cw->border ().right));
 
291
                        desiredSlot.setX (workarea.x () + slotWidth33);
 
292
                        gw->resizeCount++;
 
293
                        break;
 
294
                    case 5:
 
295
                        gw->resizeCount++;
 
296
                        break;
 
297
                    default:
 
298
                        break;
 
299
                }
 
300
            }
 
301
 
 
302
            if (gw->resizeCount == 6)
 
303
                gw->resizeCount = 1;
 
304
 
 
305
            desiredRect = constrainSize (cw, desiredSlot);
 
306
        }
 
307
 
 
308
        xwc.x = desiredRect.x ();
 
309
        xwc.y = desiredRect.y ();
 
310
        xwc.width  = desiredRect.width ();
 
311
        xwc.height = desiredRect.height ();
 
312
 
 
313
        /* Store a copy of xwc since configureXWindow changes it's values */
 
314
        XWindowChanges wc = xwc;
 
315
 
 
316
        if (cw->mapNum ())
 
317
            cw->sendSyncRequest ();
 
318
 
 
319
        /* TODO: animate move+resize */
 
320
        if (resize)
 
321
        {
 
322
            cw->configureXWindow (CWX | CWY | CWWidth | CWHeight, &xwc);
 
323
            gw->isGridResized = true;
 
324
            gw->isGridMaximized = false;
 
325
                for (unsigned int i = 0; i < animations.size (); i++)
 
326
                        animations.at (i).fadingOut = true;
 
327
        }
 
328
 
 
329
        /* This centers a window if it could not be resized to the desired
 
330
         * width. Without this, it can look buggy when desired width is
 
331
         * beyond the minimum or maximum width of the window.
 
332
         */
 
333
        if (centerCheck)
 
334
        {
 
335
            if ((cw->serverBorderRect ().width () >
 
336
                 desiredSlot.width ()) ||
 
337
                 cw->serverBorderRect ().width () <
 
338
                 desiredSlot.width ())
 
339
            {
 
340
                wc.x = (workarea.width () >> 1) -
 
341
                      ((cw->serverBorderRect ().width () >> 1) -
 
342
                        cw->border ().left);
 
343
                cw->configureXWindow (CWX, &wc);
 
344
            }
 
345
 
 
346
            centerCheck = false;
 
347
        }
 
348
 
 
349
        gw->lastTarget = where;
 
350
    }
 
351
 
 
352
    return true;
 
353
}
 
354
 
 
355
void
 
356
GridScreen::glPaintRectangle (const GLScreenPaintAttrib &sAttrib,
 
357
                              const GLMatrix            &transform,
 
358
                              CompOutput                *output)
 
359
{
 
360
    CompRect rect;
 
361
    GLMatrix sTransform (transform);
 
362
        std::vector<Animation>::iterator iter;
 
363
 
 
364
    getPaintRectangle (rect);
 
365
 
 
366
        for (unsigned int i = 0; i < animations.size (); i++)
 
367
                setCurrentRect (animations.at (i));
 
368
 
 
369
    glPushMatrix ();
 
370
 
 
371
    sTransform.toScreenSpace (output, -DEFAULT_Z_CAMERA);
 
372
 
 
373
    glLoadMatrixf (sTransform.getMatrix ());
 
374
 
 
375
    glDisableClientState (GL_TEXTURE_COORD_ARRAY);
 
376
    glEnable (GL_BLEND);
 
377
 
 
378
        for (iter = animations.begin (); iter != animations.end () && animating; iter++)
 
379
        {
 
380
                GLushort *color;
 
381
                Animation& anim = *iter;
 
382
                float alpha = (float) optionGetFillColorAlpha () / 65535.0f * anim.opacity;
 
383
 
 
384
                /* fill rectangle */
 
385
                glColor4f (((float) optionGetFillColorRed () / 65535.0f) * alpha,
 
386
                           ((float) optionGetFillColorGreen () / 65535.0f) * alpha,
 
387
                           ((float) optionGetFillColorBlue () / 65535.0f) * alpha,
 
388
                           alpha);
 
389
 
 
390
                /* fill rectangle */
 
391
                glRecti (anim.currentRect.x1 (), anim.currentRect.y2 (),
 
392
                                 anim.currentRect.x2 (), anim.currentRect.y1 ());
 
393
 
 
394
                /* Set outline rect smaller to avoid damage issues */
 
395
                anim.currentRect.setGeometry (anim.currentRect.x () + 1,
 
396
                                              anim.currentRect.y () + 1,
 
397
                                              anim.currentRect.width () - 2,
 
398
                                              anim.currentRect.height () - 2);
 
399
 
 
400
                /* draw outline */
 
401
                color = optionGetOutlineColor ();
 
402
 
 
403
                /* draw outline */
 
404
                glColor4f (((float) optionGetOutlineColorRed () / 65535.0f) * alpha,
 
405
                           ((float) optionGetOutlineColorGreen () / 65535.0f) * alpha,
 
406
                           ((float) optionGetOutlineColorBlue () / 65535.0f) * alpha,
 
407
                           ((float) optionGetOutlineColorAlpha () / 65535.0f) * anim.opacity);
 
408
 
 
409
                glColor4us (color[0], color[1], color[2], anim.opacity * color[3]);
 
410
 
 
411
                glLineWidth (2.0);
 
412
 
 
413
                glBegin (GL_LINE_LOOP);
 
414
                glVertex2i (anim.currentRect.x1 (),     anim.currentRect.y1 ());
 
415
                glVertex2i (anim.currentRect.x2 (),     anim.currentRect.y1 ());
 
416
                glVertex2i (anim.currentRect.x2 (),     anim.currentRect.y2 ());
 
417
                glVertex2i (anim.currentRect.x1 (),     anim.currentRect.y2 ());
 
418
                glEnd ();
 
419
        }
 
420
 
 
421
        if (!animating)
 
422
        {
 
423
                /* fill rectangle */
 
424
                glColor4usv (optionGetFillColor ());
 
425
                glRecti (rect.x1 (), rect.y2 (), rect.x2 (), rect.y1 ());
 
426
 
 
427
                /* Set outline rect smaller to avoid damage issues */
 
428
                rect.setGeometry (rect.x () + 1, rect.y () + 1,
 
429
                                  rect.width () - 2, rect.height () - 2);
 
430
 
 
431
                /* draw outline */
 
432
                glColor4usv (optionGetOutlineColor ());
 
433
                glLineWidth (2.0);
 
434
                glBegin (GL_LINE_LOOP);
 
435
                glVertex2i (rect.x1 (), rect.y1 ());
 
436
                glVertex2i (rect.x2 (), rect.y1 ());
 
437
                glVertex2i (rect.x2 (), rect.y2 ());
 
438
                glVertex2i (rect.x1 (), rect.y2 ());
 
439
                glEnd ();
 
440
        }
 
441
 
 
442
    /* clean up */
 
443
    glColor4usv (defaultColor);
 
444
    glDisable (GL_BLEND);
 
445
    glEnableClientState (GL_TEXTURE_COORD_ARRAY);
 
446
    glPopMatrix ();
 
447
}
 
448
 
 
449
bool
 
450
GridScreen::glPaintOutput (const GLScreenPaintAttrib &attrib,
 
451
                           const GLMatrix            &matrix,
 
452
                           const CompRegion          &region,
 
453
                           CompOutput                *output,
 
454
                           unsigned int              mask)
 
455
{
 
456
    bool status;
 
457
 
 
458
    status = glScreen->glPaintOutput (attrib, matrix, region, output, mask);
 
459
 
 
460
    glPaintRectangle (attrib, matrix, output);
 
461
 
 
462
    return status;
 
463
}
 
464
 
 
465
GridType
 
466
GridScreen::edgeToGridType ()
 
467
{
 
468
    GridType ret;
 
469
 
 
470
    switch (edge) {
 
471
    case Left:
 
472
        ret = (GridType) optionGetLeftEdgeAction ();
 
473
        break;
 
474
    case Right:
 
475
        ret = (GridType) optionGetRightEdgeAction ();
 
476
        break;
 
477
    case Top:
 
478
        ret = (GridType) optionGetTopEdgeAction ();
 
479
        break;
 
480
    case Bottom:
 
481
        ret = (GridType) optionGetBottomEdgeAction ();
 
482
        break;
 
483
    case TopLeft:
 
484
        ret = (GridType) optionGetTopLeftCornerAction ();
 
485
        break;
 
486
    case TopRight:
 
487
        ret = (GridType) optionGetTopRightCornerAction ();
 
488
        break;
 
489
    case BottomLeft:
 
490
        ret = (GridType) optionGetBottomLeftCornerAction ();
 
491
        break;
 
492
    case BottomRight:
 
493
        ret = (GridType) optionGetBottomRightCornerAction ();
 
494
        break;
 
495
    case NoEdge:
 
496
    default:
 
497
        ret = GridUnknown;
 
498
        break;
 
499
    }
 
500
 
 
501
    return ret;
 
502
}
 
503
 
 
504
void
 
505
GridScreen::handleEvent (XEvent *event)
 
506
{
 
507
    CompOutput out;
 
508
 
 
509
    screen->handleEvent (event);
 
510
 
 
511
    if (event->type != MotionNotify || !mGrabWindow)
 
512
        return;
 
513
 
 
514
    out = screen->outputDevs ().at (
 
515
                   screen->outputDeviceForPoint (CompPoint (pointerX, pointerY)));
 
516
 
 
517
    /* Detect corners first */
 
518
    /* Bottom Left */
 
519
    if (pointerY > (out.y () + out.height () - optionGetBottomEdgeThreshold()) &&
 
520
        pointerX < out.x () + optionGetLeftEdgeThreshold())
 
521
        edge = BottomLeft;
 
522
    /* Bottom Right */
 
523
    else if (pointerY > (out.y () + out.height () - optionGetBottomEdgeThreshold()) &&
 
524
             pointerX > (out.x () + out.width () - optionGetRightEdgeThreshold()))
 
525
        edge = BottomRight;
 
526
    /* Top Left */
 
527
    else if (pointerY < optionGetTopEdgeThreshold() &&
 
528
            pointerX < optionGetLeftEdgeThreshold())
 
529
        edge = TopLeft;
 
530
    /* Top Right */
 
531
    else if (pointerY < out.y () + optionGetTopEdgeThreshold() &&
 
532
             pointerX > (out.x () + out.width () - optionGetRightEdgeThreshold()))
 
533
        edge = TopRight;
 
534
    /* Left */
 
535
    else if (pointerX < out.x () + optionGetLeftEdgeThreshold())
 
536
        edge = Left;
 
537
    /* Right */
 
538
    else if (pointerX > (out.x () + out.width () - optionGetRightEdgeThreshold()))
 
539
        edge = Right;
 
540
    /* Top */
 
541
    else if (pointerY < out.y () + optionGetTopEdgeThreshold())
 
542
        edge = Top;
 
543
    /* Bottom */
 
544
    else if (pointerY > (out.y () + out.height () - optionGetBottomEdgeThreshold()))
 
545
        edge = Bottom;
 
546
    /* No Edge */
 
547
    else
 
548
        edge = NoEdge;
 
549
 
 
550
    /* Detect when cursor enters another output */
 
551
 
 
552
    currentWorkarea = screen->getWorkareaForOutput
 
553
                            (screen->outputDeviceForPoint (pointerX, pointerY));
 
554
    if (lastWorkarea != currentWorkarea)
 
555
    {
 
556
        lastWorkarea = currentWorkarea;
 
557
 
 
558
        if (cScreen)
 
559
            cScreen->damageRegion (desiredSlot);
 
560
 
 
561
        initiateCommon (0, 0, o, edgeToGridType (), false);
 
562
 
 
563
        if (cScreen)
 
564
            cScreen->damageRegion (desiredSlot);
 
565
    }
 
566
 
 
567
    /* Detect edge region change */
 
568
 
 
569
    if (lastEdge != edge)
 
570
    {
 
571
                lastSlot = desiredSlot;
 
572
 
 
573
                if (edge == NoEdge)
 
574
                        desiredSlot.setGeometry (0, 0, 0, 0);
 
575
 
 
576
                if (cScreen)
 
577
                        cScreen->damageRegion (desiredSlot);
 
578
 
 
579
                initiateCommon (0, 0, o, edgeToGridType (), false);
 
580
 
 
581
                if (cScreen)
 
582
                        cScreen->damageRegion (desiredSlot);
 
583
 
 
584
                if (lastSlot != desiredSlot)
 
585
                {
 
586
                        if (animations.size ())
 
587
                                /* Begin fading previous animation instance */
 
588
                                animations.at (animations.size () - 1).fadingOut = true;
 
589
 
 
590
                        if (edge != NoEdge)
 
591
                        {
 
592
                                CompWindow *cw = screen->findWindow (screen->activeWindow ());
 
593
                                animations.push_back (Animation ());
 
594
                                int current = animations.size () - 1;
 
595
                                animations.at (current).fromRect        = cw->serverBorderRect ();
 
596
                                animations.at (current).currentRect     = cw->serverBorderRect ();
 
597
                                animations.at (current).timer = animations.at (current).duration;
 
598
                                animations.at (current).targetRect = desiredSlot;
 
599
 
 
600
                                if (lastEdge == NoEdge || !animating)
 
601
                                {
 
602
                                        /* Cursor has entered edge region from non-edge region */
 
603
                                        animating = true;
 
604
                                        glScreen->glPaintOutputSetEnabled (this, true);
 
605
                                        cScreen->preparePaintSetEnabled (this, true);
 
606
                                        cScreen->donePaintSetEnabled (this, true);
 
607
                                }
 
608
                        }
 
609
                }
 
610
 
 
611
                lastEdge = edge;
 
612
    }
 
613
 
 
614
    GRID_WINDOW (screen->findWindow
 
615
                                (CompOption::getIntOptionNamed (o, "window")));
 
616
 
 
617
    if ((gw->pointerBufDx > SNAPOFF_THRESHOLD ||
 
618
         gw->pointerBufDy > SNAPOFF_THRESHOLD ||
 
619
         gw->pointerBufDx < -SNAPOFF_THRESHOLD ||
 
620
         gw->pointerBufDy < -SNAPOFF_THRESHOLD) &&
 
621
         gw->isGridResized &&
 
622
         optionGetSnapbackWindows ())
 
623
            restoreWindow (0, 0, o);
 
624
}
 
625
 
 
626
void
 
627
GridWindow::grabNotify (int          x,
 
628
                        int          y,
 
629
                        unsigned int state,
 
630
                        unsigned int mask)
 
631
{
 
632
    if (screen->grabExist ("move"))
 
633
    {
 
634
        gScreen->o.push_back (CompOption ("window", CompOption::TypeInt));
 
635
        gScreen->o[0].value ().set ((int) window->id ());
 
636
 
 
637
        screen->handleEventSetEnabled (gScreen, true);
 
638
        gScreen->mGrabWindow = window;
 
639
        pointerBufDx = pointerBufDy = 0;
 
640
 
 
641
        if (!isGridResized && gScreen->optionGetSnapbackWindows ())
 
642
            /* Store size not including borders when grabbing with cursor */
 
643
            originalSize = gScreen->slotToRect(window,
 
644
                                                    window->serverBorderRect ());
 
645
    }
 
646
 
 
647
    if (screen->grabExist ("resize"))
 
648
    {
 
649
        isGridResized = false;
 
650
        resizeCount = 0;
 
651
    }
 
652
 
 
653
    window->grabNotify (x, y, state, mask);
 
654
}
 
655
 
 
656
void
 
657
GridWindow::ungrabNotify ()
 
658
{
 
659
    if (window == gScreen->mGrabWindow)
 
660
    {
 
661
        gScreen->initiateCommon
 
662
                        (0, 0, gScreen->o, gScreen->edgeToGridType (), true);
 
663
 
 
664
        screen->handleEventSetEnabled (gScreen, false);
 
665
        gScreen->mGrabWindow = NULL;
 
666
        gScreen->cScreen->damageRegion (gScreen->desiredSlot);
 
667
    }
 
668
 
 
669
    gScreen->edge = NoEdge;
 
670
 
 
671
    window->ungrabNotify ();
 
672
}
 
673
 
 
674
void
 
675
GridWindow::moveNotify (int dx, int dy, bool immediate)
 
676
{
 
677
    window->moveNotify (dx, dy, immediate);
 
678
 
 
679
    pointerBufDx += dx;
 
680
    pointerBufDy += dy;
 
681
}
 
682
 
 
683
bool
 
684
GridScreen::restoreWindow (CompAction         *action,
 
685
                           CompAction::State  state,
 
686
                           CompOption::Vector &option)
 
687
{
 
688
    XWindowChanges xwc;
 
689
    CompWindow *cw = screen->findWindow (screen->activeWindow ());
 
690
 
 
691
    if (!cw)
 
692
        return false;
 
693
 
 
694
    GRID_WINDOW (cw);
 
695
 
 
696
    if (!gw->isGridResized)
 
697
        return false;
 
698
 
 
699
    if (gw->isGridMaximized & !(cw->state () & MAXIMIZE_STATE))
 
700
            gw->isGridMaximized = false;
 
701
    else
 
702
    {
 
703
        if (cw == mGrabWindow)
 
704
        {
 
705
            xwc.x = pointerX - (gw->originalSize.width () >> 1);
 
706
            xwc.y = pointerY + (cw->border ().top >> 1);
 
707
        }
 
708
        else
 
709
        {
 
710
            xwc.x = gw->originalSize.x ();
 
711
            xwc.y = gw->originalSize.y ();
 
712
        }
 
713
        xwc.width  = gw->originalSize.width ();
 
714
        xwc.height = gw->originalSize.height ();
 
715
        cw->maximize (0);
 
716
        cw->configureXWindow (CWX | CWY | CWWidth | CWHeight, &xwc);
 
717
        gw->pointerBufDx = 0;
 
718
        gw->pointerBufDy = 0;
 
719
    }
 
720
    gw->isGridResized = false;
 
721
    gw->resizeCount = 0;
 
722
 
 
723
    return true;
 
724
}
 
725
 
 
726
void
 
727
GridScreen::snapbackOptionChanged (CompOption *option,
 
728
                                    Options    num)
 
729
{
 
730
    GRID_WINDOW (screen->findWindow
 
731
                    (CompOption::getIntOptionNamed (o, "window")));
 
732
    gw->isGridResized = false;
 
733
    gw->isGridMaximized = false;
 
734
    gw->resizeCount = 0;
 
735
}
 
736
 
 
737
void
 
738
GridScreen::preparePaint (int msSinceLastPaint)
 
739
{
 
740
        std::vector<Animation>::iterator iter;
 
741
 
 
742
        for (iter = animations.begin (); iter != animations.end (); iter++)
 
743
        {
 
744
                Animation& anim = *iter;
 
745
                anim.timer -= msSinceLastPaint;
 
746
 
 
747
                if (anim.timer < 0)
 
748
                        anim.timer = 0;
 
749
 
 
750
                if (anim.fadingOut)
 
751
                        anim.opacity -= msSinceLastPaint * 0.002;
 
752
                else
 
753
                        if (anim.opacity < 1.0f)
 
754
                                anim.opacity = anim.progress * anim.progress;
 
755
                        else
 
756
                                anim.opacity = 1.0f;
 
757
 
 
758
                if (anim.opacity < 0)
 
759
                {
 
760
                        anim.opacity = 0.0f;
 
761
                        anim.fadingOut = false;
 
762
                        anim.complete = true;
 
763
                }
 
764
 
 
765
                anim.progress = (anim.duration - anim.timer) / anim.duration;
 
766
        }
 
767
 
 
768
    cScreen->preparePaint (msSinceLastPaint);
 
769
}
 
770
 
 
771
void
 
772
GridScreen::donePaint ()
 
773
{
 
774
        std::vector<Animation>::iterator iter;
 
775
 
 
776
        for (iter = animations.begin (); iter != animations.end (); )
 
777
        {
 
778
                Animation& anim = *iter;
 
779
                if (anim.complete)
 
780
                        iter = animations.erase(iter);
 
781
                else
 
782
                        iter++;
 
783
        }
 
784
 
 
785
        if (animations.empty ())
 
786
        {
 
787
                cScreen->preparePaintSetEnabled (this, false);
 
788
                cScreen->donePaintSetEnabled (this, false);
 
789
                if (edge == NoEdge)
 
790
                        glScreen->glPaintOutputSetEnabled (this, false);
 
791
                animations.clear ();
 
792
                animating = false;
 
793
        }
 
794
 
 
795
        cScreen->damageScreen ();
 
796
 
 
797
    cScreen->donePaint ();
 
798
}
 
799
 
 
800
Animation::Animation ()
 
801
{
 
802
        progress = 0.0f;
 
803
        fromRect = CompRect (0, 0, 0, 0);
 
804
        targetRect = CompRect (0, 0, 0, 0);
 
805
        currentRect = CompRect (0, 0, 0, 0);
 
806
        opacity = 0.0f;
 
807
        timer = 0.0f;
 
808
        duration = 250;
 
809
        complete = false;
 
810
        fadingOut = false;
 
811
}
 
812
 
 
813
 
 
814
GridScreen::GridScreen (CompScreen *screen) :
 
815
    PluginClassHandler<GridScreen, CompScreen> (screen),
 
816
    cScreen (CompositeScreen::get (screen)),
 
817
    glScreen (GLScreen::get (screen)),
 
818
    centerCheck (false),
 
819
    mGrabWindow (NULL),
 
820
    animating (false)
 
821
{
 
822
 
 
823
    ScreenInterface::setHandler (screen, false);
 
824
    CompositeScreenInterface::setHandler (cScreen, false);
 
825
    GLScreenInterface::setHandler (glScreen, false);
 
826
 
 
827
    edge = lastEdge = NoEdge;
 
828
    currentWorkarea = lastWorkarea = screen->getWorkareaForOutput
 
829
                            (screen->outputDeviceForPoint (pointerX, pointerY));
 
830
 
 
831
        animations.clear ();
 
832
 
 
833
#define GRIDSET(opt,where,resize)                                              \
 
834
    optionSet##opt##Initiate (boost::bind (&GridScreen::initiateCommon, this,  \
 
835
                                           _1, _2, _3, where, resize))
 
836
 
 
837
    GRIDSET (PutCenterKey, GridCenter, true);
 
838
    GRIDSET (PutLeftKey, GridLeft, true);
 
839
    GRIDSET (PutRightKey, GridRight, true);
 
840
    GRIDSET (PutTopKey, GridTop, true);
 
841
    GRIDSET (PutBottomKey, GridBottom, true);
 
842
    GRIDSET (PutTopleftKey, GridTopLeft, true);
 
843
    GRIDSET (PutToprightKey, GridTopRight, true);
 
844
    GRIDSET (PutBottomleftKey, GridBottomLeft, true);
 
845
    GRIDSET (PutBottomrightKey, GridBottomRight, true);
 
846
    GRIDSET (PutMaximizeKey, GridMaximize, true);
 
847
 
 
848
#undef GRIDSET
 
849
 
 
850
    optionSetSnapbackWindowsNotify (boost::bind (&GridScreen::
 
851
                                    snapbackOptionChanged, this, _1, _2));
 
852
 
 
853
    optionSetPutRestoreKeyInitiate (boost::bind (&GridScreen::
 
854
                                            restoreWindow, this, _1, _2, _3));
 
855
 
 
856
}
 
857
 
 
858
GridWindow::GridWindow (CompWindow *window) :
 
859
    PluginClassHandler <GridWindow, CompWindow> (window),
 
860
    window (window),
 
861
    gScreen (GridScreen::get (screen)),
 
862
    isGridResized (false),
 
863
    isGridMaximized (false),
 
864
    pointerBufDx (0),
 
865
    pointerBufDy (0),
 
866
    resizeCount (0),
 
867
    lastTarget (GridUnknown)
 
868
{
 
869
    WindowInterface::setHandler (window);
 
870
}
 
871
 
 
872
/* Initial plugin init function called. Checks to see if we are ABI
 
873
 * compatible with core, otherwise unload */
 
874
 
 
875
bool
 
876
GridPluginVTable::init ()
 
877
{
 
878
    if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION))
 
879
        return false;
 
880
 
 
881
    return true;
 
882
}