~mjuhasz/compiz-plugins-main/fix-834248

« back to all changes in this revision

Viewing changes to put/src/put.cpp

  • Committer: Sam Spilsbury
  • Date: 2011-07-12 08:07:45 UTC
  • Revision ID: sam.spilsbury@canonical.com-20110712080745-glytqbjoa84xeo0f
Sync in changes from upstream

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2006 Darryll Truchan <moppsy@comcast.net>
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or
 
5
 * modify it under the terms of the GNU General Public License
 
6
 * as published by the Free Software Foundation; either version 2
 
7
 * of the License, or (at your option) any later version.
 
8
 *
 
9
 * This program is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
 * GNU General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License
 
15
 * along with this program; if not, write to the Free Software
 
16
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
17
 *
 
18
 */
 
19
 
 
20
#include "put.h"
 
21
 
 
22
#include <cmath>
 
23
 
 
24
COMPIZ_PLUGIN_20090315 (put, PutPluginVTable);
 
25
 
 
26
#define PUT_ONLY_EMPTY(type) (type >= PutEmptyBottomLeft && \
 
27
                              type <= PutEmptyTopRight)
 
28
 
 
29
#define TOP_BORDER(w) ((w)->border ().top)
 
30
#define LEFT_BORDER(w) ((w)->border ().left)
 
31
#define RIGHT_BORDER(w) ((w)->border ().right + 2 * (w)->serverGeometry ().border ())
 
32
#define BOTTOM_BORDER(w) ((w)->border ().bottom + 2 * (w)->serverGeometry ().border ())
 
33
 
 
34
#define HALF_WIDTH(w) ((w)->serverWidth () / 2 + (w)->serverGeometry ().border ())
 
35
#define HALF_HEIGHT(w) ((w)->serverHeight () / 2 + (w)->serverGeometry ().border ())
 
36
 
 
37
/*
 
38
 * Maximumize functions
 
39
 * Functions are from Maximumize plugin
 
40
 * (Author:Kristian Lyngstøl  <kristian@bohemians.org>)
 
41
 */
 
42
 
 
43
/* Generates a region containing free space (here the
 
44
 * active window counts as free space). The region argument
 
45
 * is the start-region (ie: the output dev).
 
46
 * Logic borrowed from opacify (courtesy of myself).
 
47
 */
 
48
CompRegion
 
49
PutScreen::emptyRegion (CompWindow      *window,
 
50
                        const CompRect& outputRect)
 
51
{
 
52
    CompRegion newRegion;
 
53
 
 
54
    newRegion += outputRect;
 
55
 
 
56
    foreach(CompWindow *w, screen->windows ())
 
57
    {
 
58
        if (w->id () == window->id ())
 
59
            continue;
 
60
 
 
61
        if (w->invisible () || /*w->hidden () ||*/ w->minimized ())
 
62
            continue;
 
63
 
 
64
        if (w->wmType () & CompWindowTypeDesktopMask)
 
65
            continue;
 
66
 
 
67
        if (w->wmType () & CompWindowTypeDockMask)
 
68
        {
 
69
            if (w->struts ())
 
70
            {
 
71
                CompRegion tmpRegion;
 
72
 
 
73
                tmpRegion += w->struts ()->left;
 
74
                tmpRegion += w->struts ()->right;
 
75
                tmpRegion += w->struts ()->top;
 
76
                tmpRegion += w->struts ()->bottom;
 
77
 
 
78
                newRegion -= tmpRegion;
 
79
            }
 
80
            continue;
 
81
        }
 
82
 
 
83
        newRegion -= w->serverBorderRect ();
 
84
    }
 
85
 
 
86
    return newRegion;
 
87
}
 
88
 
 
89
/* Returns true if box a has a larger area than box b.
 
90
 */
 
91
bool
 
92
PutScreen::boxCompare (const CompRect& a,
 
93
                       const CompRect& b)
 
94
{
 
95
    int areaA, areaB;
 
96
 
 
97
    areaA = a.width () * a.height ();
 
98
    areaB = b.width () * b.height ();
 
99
 
 
100
    return (areaA > areaB);
 
101
}
 
102
 
 
103
/* Extends the given box for Window w to fit as much space in region r.
 
104
 * If XFirst is true, it will first expand in the X direction,
 
105
 * then Y. This is because it gives different results.
 
106
 * PS: Decorations are icky.
 
107
 */
 
108
 
 
109
#define LEFT   0
 
110
#define RIGHT  1
 
111
#define TOP    2
 
112
#define BOTTOM 3
 
113
 
 
114
inline void
 
115
addToCorner (CompRect&    rect,
 
116
             unsigned int corner,
 
117
             const short  inc)
 
118
{
 
119
    switch (corner) {
 
120
        case LEFT:
 
121
            rect.setX (rect.x () + inc);
 
122
            break;
 
123
        case RIGHT:
 
124
            rect.setWidth (rect.width () + inc);
 
125
            break;
 
126
        case TOP:
 
127
            rect.setY (rect.y () + inc);
 
128
            break;
 
129
        case BOTTOM:
 
130
            rect.setHeight (rect.height () + inc);
 
131
            break;
 
132
    }
 
133
}
 
134
 
 
135
inline void
 
136
expandCorner (CompWindow        *w,
 
137
              CompRect&         tmp,
 
138
              const CompRegion& r,
 
139
              unsigned int      corner,
 
140
              int               direction)
 
141
{
 
142
    bool touch = false;
 
143
 
 
144
#define CHECKREC                                                               \
 
145
    r.contains (CompRect (tmp.x () - LEFT_BORDER (w),                         \
 
146
                          tmp.y () - TOP_BORDER (w),                          \
 
147
                          tmp.width () + LEFT_BORDER (w) + RIGHT_BORDER (w), \
 
148
                          tmp.height () + TOP_BORDER (w) + BOTTOM_BORDER (w)))
 
149
 
 
150
    while (CHECKREC) {
 
151
        addToCorner (tmp, corner, direction);
 
152
        touch = true;
 
153
    }
 
154
 
 
155
    if (touch)
 
156
        addToCorner (tmp, corner, -direction);
 
157
 
 
158
#undef CHECKREC
 
159
}
 
160
 
 
161
CompRect
 
162
PutScreen::extendBox (CompWindow        *w,
 
163
                      const CompRect&   tmp,
 
164
                      const CompRegion& r,
 
165
                      bool              xFirst,
 
166
                      bool              left,
 
167
                      bool              right,
 
168
                      bool              up,
 
169
                      bool              down)
 
170
{
 
171
    short int counter = 0;
 
172
    CompRect  result = tmp;
 
173
 
 
174
    while (counter < 1)
 
175
    {
 
176
        if ((xFirst && counter == 0) || (!xFirst && counter == 1))
 
177
        {
 
178
            if (left)
 
179
                expandCorner (w, result, r, LEFT, -1);
 
180
 
 
181
            if (right)
 
182
                expandCorner (w, result, r, RIGHT, 1);
 
183
 
 
184
            counter++;
 
185
        }
 
186
 
 
187
        if ((xFirst && counter == 1) || (!xFirst && counter == 0))
 
188
        {
 
189
            if (down)
 
190
                expandCorner (w, result, r, BOTTOM, 1);
 
191
 
 
192
            if (up)
 
193
                expandCorner (w, result, r, TOP, -1);
 
194
 
 
195
            counter++;
 
196
        }
 
197
    }
 
198
 
 
199
    return result;
 
200
}
 
201
 
 
202
/* Create a box for resizing in the given region
 
203
 * Also shrinks the window box in case of minor overlaps.
 
204
 * FIXME: should be somewhat cleaner.
 
205
 */
 
206
CompRect
 
207
PutScreen::findRect (CompWindow        *w,
 
208
                     const CompRegion& r,
 
209
                     bool              left,
 
210
                     bool              right,
 
211
                     bool              up,
 
212
                     bool              down)
 
213
{
 
214
    CompRect windowBox, ansA, ansB, orig;
 
215
 
 
216
    windowBox.setGeometry (w->serverX (), w->serverY (),
 
217
                           w->serverWidth (), w->serverHeight ());
 
218
 
 
219
    orig = windowBox;
 
220
 
 
221
    ansA = extendBox (w, windowBox, r, true, left, right, up, down);
 
222
    ansB = extendBox (w, windowBox, r, false, left, right, up, down);
 
223
 
 
224
    if (boxCompare (orig, ansA) && boxCompare (orig, ansB))
 
225
        return orig;
 
226
 
 
227
    if (boxCompare (ansA, ansB))
 
228
        return ansA;
 
229
    else
 
230
        return ansB;
 
231
 
 
232
}
 
233
 
 
234
/* Calls out to compute the resize */
 
235
unsigned int
 
236
PutScreen::computeResize (CompWindow     *w,
 
237
                          XWindowChanges *xwc,
 
238
                          bool           left,
 
239
                          bool           right,
 
240
                          bool           up,
 
241
                          bool           down)
 
242
{
 
243
    unsigned int mask = 0;
 
244
    CompRect     box;
 
245
    CompRegion   region;
 
246
    int          outputDevice = w->outputDevice ();
 
247
 
 
248
    region = emptyRegion (w, screen->outputDevs ()[outputDevice]);
 
249
    box    = findRect (w, region, left, right, up, down);
 
250
 
 
251
    if (box.x () != w->serverX ())
 
252
        mask |= CWX;
 
253
 
 
254
    if (box.y () != w->serverY ())
 
255
        mask |= CWY;
 
256
 
 
257
    if (box.width () != w->serverWidth ())
 
258
        mask |= CWWidth;
 
259
 
 
260
    if (box.height () != w->height ())
 
261
        mask |= CWHeight;
 
262
 
 
263
    xwc->x = box.x ();
 
264
    xwc->y = box.y ();
 
265
    xwc->width = box.width ();
 
266
    xwc->height = box.height ();
 
267
 
 
268
    return mask;
 
269
}
 
270
 
 
271
/*
 
272
 * End of Maximumize functions
 
273
 */
 
274
 
 
275
/*
 
276
 * calculate the velocity for the moving window
 
277
 */
 
278
int
 
279
PutScreen::adjustVelocity (CompWindow *w)
 
280
{
 
281
    float dx, dy, adjust, amount;
 
282
    float x1, y1;
 
283
 
 
284
    PUT_WINDOW (w);
 
285
 
 
286
    x1 = pw->targetX;
 
287
    y1 = pw->targetY;
 
288
 
 
289
    dx = x1 - (w->x () + pw->tx);
 
290
    dy = y1 - (w->y () + pw->ty);
 
291
 
 
292
    adjust = dx * 0.15f;
 
293
    amount = fabs (dx) * 1.5;
 
294
    if (amount < 0.5f)
 
295
        amount = 0.5f;
 
296
    else if (amount > 5.0f)
 
297
        amount = 5.0f;
 
298
 
 
299
    pw->xVelocity = (amount * pw->xVelocity + adjust) / (amount + 1.0f);
 
300
 
 
301
    adjust = dy * 0.15f;
 
302
    amount = fabs (dy) * 1.5f;
 
303
    if (amount < 0.5f)
 
304
        amount = 0.5f;
 
305
    else if (amount > 5.0f)
 
306
        amount = 5.0f;
 
307
 
 
308
    pw->yVelocity = (amount * pw->yVelocity + adjust) / (amount + 1.0f);
 
309
 
 
310
    if (fabs (dx) < 0.1f && fabs (pw->xVelocity) < 0.2f &&
 
311
        fabs (dy) < 0.1f && fabs (pw->yVelocity) < 0.2f)
 
312
    {
 
313
        /* animation done */
 
314
        pw->xVelocity = pw->yVelocity = 0.0f;
 
315
 
 
316
        pw->tx = x1 - w->x ();
 
317
        pw->ty = y1 - w->y ();
 
318
        return 0;
 
319
    }
 
320
    return 1;
 
321
}
 
322
 
 
323
void
 
324
PutScreen::finishWindowMovement (CompWindow *w)
 
325
{
 
326
    PUT_WINDOW (w);
 
327
 
 
328
    w->move (pw->targetX - w->x (),
 
329
             pw->targetY - w->y (),
 
330
             true);
 
331
    w->syncPosition ();
 
332
 
 
333
    if (w->state () & (MAXIMIZE_STATE | CompWindowStateFullscreenMask))
 
334
        w->updateAttributes (CompStackingUpdateModeNone);
 
335
}
 
336
 
 
337
unsigned int
 
338
PutScreen::getOutputForWindow (CompWindow *w)
 
339
{
 
340
    PUT_WINDOW (w);
 
341
 
 
342
    if (!pw->adjust)
 
343
        return w->outputDevice ();
 
344
 
 
345
    /* outputDeviceForWindow uses the server geometry,
 
346
       so specialcase a running animation, which didn't
 
347
       apply the server geometry yet */
 
348
    CompWindow::Geometry geom;
 
349
 
 
350
    geom.set (w->x () + pw->tx, w->y () + pw->ty,
 
351
              w->width (), w->height (), w->geometry ().border ());
 
352
 
 
353
    return screen->outputDeviceForGeometry (geom);
 
354
}
 
355
 
 
356
CompPoint
 
357
PutScreen::getDistance (CompWindow         *w,
 
358
                        PutType            type,
 
359
                        CompOption::Vector &option)
 
360
{
 
361
    CompScreen *s = screen;
 
362
    int        x, y, dx, dy, posX, posY;
 
363
    int        viewport, output;
 
364
    CompRect   workArea;
 
365
    CompPoint  result;
 
366
 
 
367
    PUT_SCREEN (s);
 
368
    PUT_WINDOW (w);
 
369
 
 
370
    posX = CompOption::getIntOptionNamed (option,"x", 0);
 
371
    posY = CompOption::getIntOptionNamed (option,"y", 0);
 
372
 
 
373
    /* get the output device number from the options list */
 
374
    output = CompOption::getIntOptionNamed (option,"output", -1);
 
375
    /* no output in options list -> use the current output */
 
376
    if (output == -1)
 
377
    {
 
378
        /* no output given, so use the current output if
 
379
           this wasn't a double tap */
 
380
 
 
381
        if (ps->lastType != type || ps->lastWindow != w->id ())
 
382
            output = getOutputForWindow (w);
 
383
    }
 
384
    else
 
385
    {
 
386
        /* make sure the output number is not out of bounds */
 
387
        output = MIN (output,  (int) s->outputDevs ().size () - 1);
 
388
    }
 
389
 
 
390
    if (output == -1)
 
391
    {
 
392
        /* user double-tapped the key, so use the screen work area */
 
393
        workArea = s->workArea ();
 
394
        /* set the type to unknown to have a toggle-type behaviour
 
395
           between 'use output work area' and 'use screen work area' */
 
396
        ps->lastType = PutUnknown;
 
397
    }
 
398
    else
 
399
    {
 
400
        /* single tap or output provided via options list,
 
401
           use the output work area */
 
402
        workArea = s->getWorkareaForOutput (output);
 
403
        ps->lastType = type;
 
404
    }
 
405
 
 
406
    if (PUT_ONLY_EMPTY (type))
 
407
    {
 
408
        unsigned int   mask;
 
409
        XWindowChanges xwc;
 
410
        bool           left, right, up, down;
 
411
 
 
412
        left = right = up = down = false;
 
413
 
 
414
        switch (type) {
 
415
            case PutEmptyBottomLeft:
 
416
                left = down = true;
 
417
                break;
 
418
            case PutEmptyBottom:
 
419
                down = true;
 
420
                break;
 
421
            case PutEmptyBottomRight:
 
422
                right = down = true;
 
423
                break;
 
424
            case PutEmptyLeft:
 
425
                left = true;
 
426
                break;
 
427
            case PutEmptyCenter:
 
428
                left = right = up = down = true;
 
429
                break;
 
430
            case PutEmptyRight:
 
431
                right = true;
 
432
                break;
 
433
            case PutEmptyTopLeft:
 
434
                left = up = true;
 
435
                break;
 
436
            case PutEmptyTop:
 
437
                up = true;
 
438
                break;
 
439
            case PutEmptyTopRight:
 
440
                right = up = true;
 
441
                break;
 
442
            default:
 
443
                break;
 
444
        }
 
445
 
 
446
        mask = computeResize (w, &xwc, left,right,up,down);
 
447
        if (mask)
 
448
        {
 
449
            if (w->constrainNewWindowSize (xwc.width, xwc.height,
 
450
                                           &xwc.width, &xwc.height))
 
451
                mask |= CWWidth | CWHeight;
 
452
        }
 
453
 
 
454
        workArea.setGeometry (xwc.x, xwc.y, xwc.width, xwc.height);
 
455
    }
 
456
    /* the windows location */
 
457
    x = w->x () + pw->tx;
 
458
    y = w->y () + pw->ty;
 
459
 
 
460
    switch (type) {
 
461
    case PutEmptyCenter:
 
462
    case PutCenter:
 
463
        /* center of the screen */
 
464
        dx = (workArea.width () / 2) - HALF_WIDTH (w) -
 
465
              w->serverGeometry ().border () - (x - workArea.x ());
 
466
        dy = (workArea.height () / 2) - HALF_HEIGHT (w) -
 
467
              w->serverGeometry ().border () - (y - workArea.y ());
 
468
        break;
 
469
    case PutLeft:
 
470
        /* center of the left edge */
 
471
        dx = -(x - workArea.x ()) + LEFT_BORDER (w) + ps->optionGetPadLeft ();
 
472
        dy = (workArea.height () / 2) - HALF_HEIGHT (w) -
 
473
             (y - workArea.y ());
 
474
        break;
 
475
    case PutEmptyLeft:
 
476
        /* center of the left edge */
 
477
        workArea.setX (workArea.x () - LEFT_BORDER (w));
 
478
        dx = -(x - workArea.x ()) + LEFT_BORDER (w) + ps->optionGetPadLeft ();
 
479
        dy = (workArea.height () / 2) - HALF_HEIGHT (w) -
 
480
             (y - workArea.y ());
 
481
        break;
 
482
    case PutTopLeft:
 
483
        /* top left corner */
 
484
        dx = -(x - workArea.x ()) + LEFT_BORDER (w) + ps->optionGetPadLeft ();
 
485
        dy = -(y - workArea.y ()) + TOP_BORDER (w) + ps->optionGetPadTop ();
 
486
        break;
 
487
    case PutEmptyTopLeft:
 
488
        /* top left corner */
 
489
        workArea.setX (workArea.x () - LEFT_BORDER (w));
 
490
        workArea.setY (workArea.y () - TOP_BORDER (w));
 
491
        dx = -(x - workArea.x ()) + LEFT_BORDER (w) + ps->optionGetPadLeft ();
 
492
        dy = -(y - workArea.y ()) + TOP_BORDER (w) + ps->optionGetPadTop ();
 
493
        break;
 
494
    case PutTop:
 
495
        /* center of top edge */
 
496
        dx = (workArea.width () / 2) - HALF_WIDTH (w) -
 
497
             (x - workArea.x ());
 
498
        dy = -(y - workArea.y ()) + TOP_BORDER (w) + ps->optionGetPadTop ();
 
499
        break;
 
500
    case PutEmptyTop:
 
501
        /* center of top edge */
 
502
        workArea.setY (workArea.x () - TOP_BORDER (w));
 
503
        dx = (workArea.width () / 2) - HALF_WIDTH (w) -
 
504
             (x - workArea.x ());
 
505
        dy = -(y - workArea.y ()) + TOP_BORDER (w) + ps->optionGetPadTop ();
 
506
        break;
 
507
    case PutTopRight:
 
508
        /* top right corner */
 
509
        dx = workArea.width () - w->serverWidth () - (x - workArea.x ()) -
 
510
             RIGHT_BORDER (w) - ps->optionGetPadRight ();
 
511
        dy = -(y - workArea.y ()) + TOP_BORDER (w) + ps->optionGetPadTop ();
 
512
        break;
 
513
    case PutEmptyTopRight:
 
514
        /* top right corner */
 
515
        workArea.setX (workArea.x () + RIGHT_BORDER (w));
 
516
        workArea.setY (workArea.y () - TOP_BORDER (w));
 
517
        dx = workArea.width () - w->serverWidth () - (x - workArea.x ()) -
 
518
             RIGHT_BORDER (w) - ps->optionGetPadRight ();
 
519
        dy = -(y - workArea.y ()) + TOP_BORDER (w) + ps->optionGetPadTop ();
 
520
        break;
 
521
    case PutRight:
 
522
        /* center of right edge */
 
523
        dx = workArea.width () - w->serverWidth () - (x - workArea.x ()) -
 
524
             RIGHT_BORDER (w) - ps->optionGetPadRight ();
 
525
        dy = (workArea.height () / 2) - HALF_HEIGHT (w) -
 
526
             (y - workArea.y ());
 
527
        break;
 
528
    case PutEmptyRight:
 
529
        /* center of right edge */
 
530
        workArea.setX (workArea.x () + RIGHT_BORDER (w));
 
531
        dx = workArea.width () - w->serverWidth () - (x - workArea.x ()) -
 
532
             RIGHT_BORDER (w) - ps->optionGetPadRight ();
 
533
        dy = (workArea.height () / 2) - HALF_HEIGHT (w) -
 
534
             (y - workArea.y ());
 
535
        break;
 
536
    case PutBottomRight:
 
537
        /* bottom right corner */
 
538
        dx = workArea.width () - w->serverWidth () - (x - workArea.x ()) -
 
539
            RIGHT_BORDER (w) - ps->optionGetPadRight ();
 
540
        dy = workArea.height () - w->serverHeight () - (y - workArea.y ()) -
 
541
            BOTTOM_BORDER (w) - ps->optionGetPadBottom ();
 
542
        break;
 
543
    case PutEmptyBottomRight:
 
544
        /* bottom right corner */
 
545
        workArea.setX (workArea.x () + RIGHT_BORDER (w));
 
546
        workArea.setY (workArea.y () + BOTTOM_BORDER (w));
 
547
        dx = workArea.width () - w->serverWidth () - (x - workArea.x ()) -
 
548
             RIGHT_BORDER (w) - ps->optionGetPadRight ();
 
549
        dy = workArea.height () - w->serverHeight () - (y - workArea.y ()) -
 
550
             BOTTOM_BORDER (w)- ps->optionGetPadBottom ();
 
551
        break;
 
552
    case PutBottom:
 
553
        /* center of bottom edge */
 
554
        dx = (workArea.width () / 2) - HALF_WIDTH (w) -
 
555
             (x - workArea.x ());
 
556
        dy = workArea.height () - w->serverHeight () - (y - workArea.y ()) -
 
557
             BOTTOM_BORDER (w) - ps->optionGetPadBottom ();
 
558
        break;
 
559
    case PutEmptyBottom:
 
560
        /* center of bottom edge */
 
561
        workArea.setY (workArea.y () + BOTTOM_BORDER (w));
 
562
        dx = (workArea.width () / 2) - HALF_WIDTH (w) -
 
563
             (x - workArea.x ());
 
564
        dy = workArea.height () - w->serverHeight () - (y - workArea.y ()) -
 
565
             BOTTOM_BORDER (w) - ps->optionGetPadBottom ();
 
566
        break;
 
567
    case PutBottomLeft:
 
568
        /* bottom left corner */
 
569
        dx = -(x - workArea.x ()) + LEFT_BORDER (w) + ps->optionGetPadLeft ();
 
570
        dy = workArea.height () - w->serverHeight () - (y - workArea.y ()) -
 
571
             BOTTOM_BORDER (w) - ps->optionGetPadBottom ();
 
572
        break;
 
573
    case PutEmptyBottomLeft:
 
574
        /* bottom left corner */
 
575
        workArea.setX (workArea.x () - LEFT_BORDER (w));
 
576
        workArea.setY (workArea.y () + BOTTOM_BORDER (w));
 
577
        dx = -(x - workArea.x ()) + LEFT_BORDER (w) + ps->optionGetPadLeft ();
 
578
        dy = workArea.height () - w->serverHeight () - (y - workArea.y ()) -
 
579
             BOTTOM_BORDER (w) - ps->optionGetPadBottom ();
 
580
        break;
 
581
    case PutRestore:
 
582
        /* back to last position */
 
583
        dx = pw->lastX - x;
 
584
        dy = pw->lastY - y;
 
585
        break;
 
586
    case PutViewport:
 
587
        {
 
588
            int vpX, vpY, hDirection, vDirection;
 
589
 
 
590
            /* get the viewport to move to from the options list */
 
591
            viewport = CompOption::getIntOptionNamed (option, "viewport", -1);
 
592
 
 
593
            /* if viewport wasn't supplied, bail out */
 
594
            if (viewport < 0)
 
595
                return result;
 
596
 
 
597
            /* split 1D viewport value into 2D x and y viewport */
 
598
            vpX = viewport % s->vpSize ().width ();
 
599
            vpY = viewport / s->vpSize ().width ();
 
600
            if (vpY > (int) s->vpSize ().height ())
 
601
                vpY = s->vpSize ().height () - 1;
 
602
 
 
603
            /* take the shortest horizontal path to the destination viewport */
 
604
            hDirection = (vpX - s->vp ().x ());
 
605
            if (hDirection > (int) s->vpSize ().width () / 2)
 
606
                hDirection = (hDirection - s->vpSize ().width ());
 
607
            else if (hDirection < - ((int) s->vpSize ().width ()) / 2)
 
608
                hDirection = (hDirection + s->vpSize ().width ());
 
609
 
 
610
            /* we need to do this for the vertical destination viewport too */
 
611
            vDirection = (vpY - s->vp ().y ());
 
612
            if (vDirection > (int) s->vpSize ().height () / 2)
 
613
                vDirection = (vDirection - s->vpSize ().height ());
 
614
            else if (vDirection < -((int) s->vpSize ().height ()) / 2)
 
615
                vDirection = (vDirection + s->vpSize ().height ());
 
616
 
 
617
            dx = s->width () * hDirection;
 
618
            dy = s->height () * vDirection;
 
619
            break;
 
620
        }
 
621
    case PutViewportLeft:
 
622
        /* move to the viewport on the left */
 
623
        dx = (s->vp ().x () >= 1) ? -s->width () : 0;
 
624
        dy = 0;
 
625
        break;
 
626
    case PutViewportRight:
 
627
        /* move to the viewport on the right */
 
628
        dx = (s->vp ().x () < s->vpSize ().width ()-1) ? s->width () : 0;
 
629
        dy = 0;
 
630
        break;
 
631
    case PutViewportUp:
 
632
        /* move to the viewport above */
 
633
        dx = 0;
 
634
        dy = (s->vp ().y () >= 1) ? -s->height () : 0;
 
635
        break;
 
636
    case PutViewportDown:
 
637
        /* move to the viewport below */
 
638
        dx = 0;
 
639
        dy = (s->vp ().y () < s->vpSize ().height ()-1) ? s->height () : 0;
 
640
        break;
 
641
    case PutNextOutput:
 
642
        {
 
643
            int        outputNum, currentNum;
 
644
            int        nOutputDev = s->outputDevs ().size ();
 
645
            CompOutput *currentOutput, *newOutput;
 
646
 
 
647
            if (nOutputDev < 2)
 
648
                return result;
 
649
 
 
650
            currentNum = getOutputForWindow (w);
 
651
            outputNum  = (currentNum + 1) % nOutputDev;
 
652
            outputNum  = CompOption::getIntOptionNamed (option,"output",
 
653
                                                        outputNum);
 
654
 
 
655
            if (outputNum >= nOutputDev)
 
656
                return result;
 
657
 
 
658
            currentOutput = &s->outputDevs ().at(currentNum);
 
659
            newOutput     = &s->outputDevs ().at(outputNum);
 
660
 
 
661
            /* move by the distance of the output center points */
 
662
            dx = (newOutput->x1 () + newOutput->width () / 2) -
 
663
                 (currentOutput->x1 () + currentOutput->width () / 2);
 
664
            dy = (newOutput->y1 () + newOutput->height () / 2) -
 
665
                 (currentOutput->y1 () + currentOutput->height () / 2);
 
666
 
 
667
            /* update work area for new output */
 
668
            workArea = newOutput->workArea ();
 
669
        }
 
670
        break;
 
671
    case PutAbsolute:
 
672
        /* move the window to an exact position */
 
673
        if (posX < 0)
 
674
            /* account for a specified negative position,
 
675
               like geometry without (-0) */
 
676
            dx = posX + s->width () - w->serverWidth () - x - RIGHT_BORDER (w);
 
677
        else
 
678
            dx = posX - x + LEFT_BORDER (w);
 
679
 
 
680
        if (posY < 0)
 
681
            /* account for a specified negative position,
 
682
               like geometry without (-0) */
 
683
            dy = posY + s->height () - w->height () - y - BOTTOM_BORDER (w);
 
684
        else
 
685
            dy = posY - y + TOP_BORDER (w);
 
686
        break;
 
687
    case PutRelative:
 
688
        /* move window by offset */
 
689
        dx = posX;
 
690
        dy = posY;
 
691
        break;
 
692
    case PutPointer:
 
693
        {
 
694
            /* move the window to the pointers position
 
695
             * using the current quad of the screen to determine
 
696
             * which corner to move to the pointer
 
697
             */
 
698
            int          rx, ry;
 
699
            Window       root, child;
 
700
            int          winX, winY;
 
701
            unsigned int pMask;
 
702
 
 
703
            /* get the pointers position from the X server */
 
704
            if (XQueryPointer (s->dpy (), w->id (), &root, &child,
 
705
                               &rx, &ry, &winX, &winY, &pMask))
 
706
            {
 
707
                if (ps->optionGetWindowCenter ())
 
708
                {
 
709
                    /* window center */
 
710
                    dx = rx - HALF_WIDTH (w) - x;
 
711
                    dy = ry - HALF_HEIGHT (w) - y;
 
712
                }
 
713
                else if (rx < (int) s->workArea ().width () / 2 &&
 
714
                         ry < (int) s->workArea ().height () / 2)
 
715
                {
 
716
                    /* top left quad */
 
717
                    dx = rx - x + LEFT_BORDER (w);
 
718
                    dy = ry - y + TOP_BORDER (w);
 
719
                }
 
720
                else if (rx < (int) s->workArea ().width () / 2 &&
 
721
                         ry >= (int) s->workArea ().height () / 2)
 
722
                {
 
723
                    /* bottom left quad */
 
724
                    dx = rx - x + LEFT_BORDER (w);
 
725
                    dy = ry - w->height () - y - BOTTOM_BORDER (w);
 
726
                }
 
727
                else if (rx >= (int) s->workArea ().width () / 2 &&
 
728
                         ry < (int) s->workArea ().height () / 2)
 
729
                {
 
730
                    /* top right quad */
 
731
                    dx = rx - w->width () - x - RIGHT_BORDER (w);
 
732
                    dy = ry - y + TOP_BORDER (w);
 
733
                }
 
734
                else
 
735
                {
 
736
                    /* bottom right quad */
 
737
                    dx = rx - w->width () - x - RIGHT_BORDER (w);
 
738
                    dy = ry - w->height () - y - BOTTOM_BORDER (w);
 
739
                }
 
740
            }
 
741
            else
 
742
            {
 
743
                dx = dy = 0;
 
744
            }
 
745
        }
 
746
        break;
 
747
    default:
 
748
        /* if an unknown type is specified, do nothing */
 
749
        dx = dy = 0;
 
750
        break;
 
751
    }
 
752
 
 
753
    if ((dx || dy) && ps->optionGetAvoidOffscreen () &&
 
754
        !(w->type () & CompWindowTypeFullscreenMask))
 
755
    {
 
756
        /* avoids window borders offscreen, but allow full
 
757
           viewport movements */
 
758
        int               inDx, dxBefore;
 
759
        int               inDy, dyBefore;
 
760
        CompWindowExtents extents, area;
 
761
 
 
762
        inDx = dxBefore = dx % s->width ();
 
763
        inDy = dyBefore = dy % s->height ();
 
764
 
 
765
        extents.left   = x + inDx - LEFT_BORDER (w);
 
766
        extents.top    = y + inDy - TOP_BORDER (w);
 
767
        extents.right  = x + inDx + w->serverWidth () + RIGHT_BORDER (w);
 
768
        extents.bottom = y + inDy + w->serverHeight () + BOTTOM_BORDER (w);
 
769
 
 
770
        area.left   = workArea.left () + ps->optionGetPadLeft ();
 
771
        area.top    = workArea.top () + ps->optionGetPadTop ();
 
772
        area.right  = workArea.right () - ps->optionGetPadRight ();
 
773
        area.bottom = workArea.bottom () - ps->optionGetPadBottom ();
 
774
 
 
775
        if (extents.left < area.left)
 
776
        {
 
777
            inDx += area.left - extents.left;
 
778
        }
 
779
        else if (w->serverWidth () <= workArea.width () &&
 
780
                 extents.right > area.right)
 
781
        {
 
782
            inDx += area.right - extents.right;
 
783
        }
 
784
 
 
785
        if (extents.top < area.top)
 
786
        {
 
787
            inDy += area.top - extents.top;
 
788
        }
 
789
        else if (w->serverHeight () <= workArea.height () &&
 
790
                 extents.bottom > area.bottom)
 
791
        {
 
792
            inDy += area.bottom - extents.bottom;
 
793
        }
 
794
 
 
795
        /* apply the change */
 
796
        dx += inDx - dxBefore;
 
797
        dy += inDy - dyBefore;
 
798
    }
 
799
 
 
800
    result.set (dx, dy);
 
801
 
 
802
    return result;
 
803
}
 
804
 
 
805
void
 
806
PutScreen::preparePaint (int ms)
 
807
{
 
808
 
 
809
    PUT_SCREEN (screen);
 
810
 
 
811
    if (ps->moreAdjust && ps->grabIndex)
 
812
    {
 
813
        int        steps;
 
814
        float      amount, chunk;
 
815
 
 
816
        amount = ms * 0.025f * ps->optionGetSpeed ();
 
817
        steps = amount / (0.5f * ps->optionGetTimestep ());
 
818
        if (!steps)
 
819
            steps = 1;
 
820
        chunk = amount / (float)steps;
 
821
 
 
822
        while (steps--)
 
823
        {
 
824
            Window endAnimationWindow = None;
 
825
 
 
826
            ps->moreAdjust = 0;
 
827
            foreach(CompWindow *w, screen->windows ())
 
828
            {
 
829
                PUT_WINDOW (w);
 
830
 
 
831
                if (pw->adjust)
 
832
                {
 
833
                    pw->adjust = adjustVelocity (w);
 
834
                    ps->moreAdjust |= pw->adjust;
 
835
 
 
836
                    pw->tx += pw->xVelocity * chunk;
 
837
                    pw->ty += pw->yVelocity * chunk;
 
838
 
 
839
                    if (!pw->adjust)
 
840
                    {
 
841
                        /* animation done */
 
842
                        finishWindowMovement (w);
 
843
 
 
844
                        if (w->id  () == screen->activeWindow ())
 
845
                            endAnimationWindow = w->id ();
 
846
 
 
847
                        pw->tx = pw->ty = 0;
 
848
                    }
 
849
                }
 
850
            }
 
851
            if (!ps->moreAdjust)
 
852
            {
 
853
                /* unfocus moved window if enabled */
 
854
                if (ps->optionGetUnfocusWindow ())
 
855
                    screen->focusDefaultWindow ();
 
856
                else if (endAnimationWindow)
 
857
                    screen->sendWindowActivationRequest (endAnimationWindow);
 
858
                break;
 
859
            }
 
860
        }
 
861
    }
 
862
 
 
863
    cScreen->preparePaint (ms);
 
864
}
 
865
 
 
866
/* This is the guts of the paint function. You can transform the way the
 
867
 * entire output is painted or you can just draw things on screen with openGL.
 
868
 * The unsigned int here is a mask for painting the screen, see opengl/opengl.h
 
869
 * on how you can change it
 
870
 */
 
871
 
 
872
bool
 
873
PutScreen::glPaintOutput (const GLScreenPaintAttrib     &attrib,
 
874
                          const GLMatrix                &transform,
 
875
                          const CompRegion              &region,
 
876
                          CompOutput                    *output,
 
877
                          unsigned int                  mask)
 
878
{
 
879
    bool status;
 
880
 
 
881
    PUT_SCREEN (screen);
 
882
 
 
883
    if (ps->moreAdjust)
 
884
        mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS_MASK;
 
885
 
 
886
    status = gScreen->glPaintOutput (attrib, transform, region, output, mask);
 
887
 
 
888
    return status;
 
889
}
 
890
 
 
891
void
 
892
PutScreen::donePaint ()
 
893
{
 
894
    PUT_SCREEN (screen);
 
895
 
 
896
    if (ps->moreAdjust && ps->grabIndex)
 
897
    {
 
898
        cScreen->damageScreen (); // FIXME
 
899
    }
 
900
    else
 
901
    {
 
902
        if (ps->grabIndex)
 
903
        {
 
904
            /* release the screen grab */
 
905
            screen->removeGrab (ps->grabIndex, NULL);
 
906
            ps->grabIndex = 0;
 
907
        }
 
908
    }
 
909
 
 
910
    cScreen->donePaint ();
 
911
}
 
912
 
 
913
/* This is our event handler. It directly hooks into the screen's X Event handler and allows us to handle
 
914
 * our raw X Events
 
915
 */
 
916
 
 
917
void
 
918
PutScreen::handleEvent (XEvent *event)
 
919
{
 
920
    switch (event->type) {
 
921
    /* handle client events */
 
922
    case ClientMessage:
 
923
        /* accept the custom atom for putting windows */
 
924
        if (event->xclient.message_type == compizPutWindowAtom)
 
925
        {
 
926
            CompWindow *w;
 
927
 
 
928
            w = screen->findWindow (event->xclient.window);
 
929
            if (w)
 
930
            {
 
931
                /*
 
932
                 * get the values from the xclientmessage event and populate
 
933
                 * the options for put initiate
 
934
                 *
 
935
                 * the format is 32
 
936
                 * and the data is
 
937
                 * l[0] = x position - unused (for future PutExact)
 
938
                 * l[1] = y position - unused (for future PutExact)
 
939
                 * l[2] = viewport number
 
940
                 * l[3] = put type, int value from enum
 
941
                 * l[4] = output number
 
942
                 */
 
943
                CompOption::Vector opt (5);
 
944
 
 
945
                CompOption::Value value0 = (int) event->xclient.window;
 
946
                opt.push_back (CompOption ( "window",CompOption::TypeInt));
 
947
                opt[0].set (value0);
 
948
 
 
949
                CompOption::Value value1 = (int) event->xclient.data.l[0];
 
950
                opt.push_back (CompOption ( "x",CompOption::TypeInt));
 
951
                opt[1].set (value1);
 
952
 
 
953
                CompOption::Value value2 = (int) event->xclient.data.l[1];
 
954
                opt.push_back (CompOption ( "y",CompOption::TypeInt));
 
955
                opt[2].set (value2);
 
956
 
 
957
                CompOption::Value value3 = (int) event->xclient.data.l[2];
 
958
                opt.push_back (CompOption ( "viewport",CompOption::TypeInt));
 
959
                opt[3].set (value3);
 
960
 
 
961
                CompOption::Value value4 = (int) event->xclient.data.l[4];
 
962
                opt.push_back (CompOption ( "output",CompOption::TypeInt));
 
963
                opt[4].set (value4);
 
964
 
 
965
                initiateCommon (NULL, 0, opt,
 
966
                                (PutType) event->xclient.data.l[3]);
 
967
            }
 
968
        }
 
969
        break;
 
970
    default:
 
971
        break;
 
972
    }
 
973
    screen->handleEvent (event);
 
974
}
 
975
 
 
976
/* This gets called whenever the window needs to be repainted.
 
977
 * WindowPaintAttrib gives you some attributes like brightness/saturation etc
 
978
 * to play around with. GLMatrix is the window's transformation matrix. The
 
979
 * unsigned int is the mask, have a look at opengl.h on what you can do
 
980
 * with it */
 
981
bool
 
982
PutWindow::glPaint (const GLWindowPaintAttrib &attrib,
 
983
                    const GLMatrix            &transform,
 
984
                    const CompRegion          &region,
 
985
                    unsigned int              mask)
 
986
{
 
987
    GLMatrix wTransform (transform);
 
988
 
 
989
    if (adjust)
 
990
    {
 
991
        wTransform.translate (tx, ty, 0.0f);
 
992
        mask |= PAINT_WINDOW_TRANSFORMED_MASK;
 
993
    }
 
994
 
 
995
    return gWindow->glPaint (attrib, wTransform, region, mask);
 
996
}
 
997
 
 
998
/*
 
999
 * initiate action callback
 
1000
 */
 
1001
bool
 
1002
PutScreen::initiateCommon (CompAction         *action,
 
1003
                           CompAction::State  state,
 
1004
                           CompOption::Vector &option,
 
1005
                           PutType            type)
 
1006
{
 
1007
    CompWindow *w;
 
1008
    Window     xid;
 
1009
 
 
1010
    xid = CompOption::getIntOptionNamed (option,  "window", 0);
 
1011
    if (!xid)
 
1012
        xid = screen->activeWindow ();
 
1013
 
 
1014
    w = screen->findWindow (xid);
 
1015
    if (w)
 
1016
    {
 
1017
        CompScreen *s = screen;
 
1018
        CompPoint  delta;
 
1019
 
 
1020
        /* we don't want to do anything with override redirect windows */
 
1021
        if (w->overrideRedirect ())
 
1022
            return false;
 
1023
 
 
1024
        /* we don't want to be moving the desktop and docks */
 
1025
        if (w->type () & (CompWindowTypeDesktopMask |
 
1026
                          CompWindowTypeDockMask))
 
1027
            return false;
 
1028
 
 
1029
        /* don't move windows without move action */
 
1030
        if (!(w->actions () & CompWindowActionMoveMask))
 
1031
            return false;
 
1032
 
 
1033
        /* only allow movement of fullscreen windows to next output */
 
1034
        if (type != PutNextOutput &&
 
1035
            (w->type () & CompWindowTypeFullscreenMask))
 
1036
        {
 
1037
            return false;
 
1038
        }
 
1039
 
 
1040
        /*
 
1041
         * handle the put types
 
1042
         */
 
1043
        delta = getDistance (w, type, option);
 
1044
 
 
1045
        /* don't do anything if there is nothing to do */
 
1046
        if (!delta.x () && !delta.y ())
 
1047
            return true;
 
1048
 
 
1049
        if (!grabIndex)
 
1050
        {
 
1051
            /* this will keep put from working while something
 
1052
               else has a screen grab */
 
1053
            if (s->otherGrabExist ("put", NULL))
 
1054
                return false;
 
1055
 
 
1056
            /* we are ok, so grab the screen */
 
1057
            grabIndex = s->pushGrab (s->invisibleCursor (), "put");
 
1058
        }
 
1059
 
 
1060
        if (grabIndex)
 
1061
        {
 
1062
            PUT_WINDOW (w);
 
1063
 
 
1064
            lastWindow = w->id ();
 
1065
 
 
1066
            /* save the windows position in the saveMask
 
1067
             * this is used when unmaximizing the window
 
1068
             */
 
1069
            if (w->saveMask () & CWX)
 
1070
                w->saveWc ().x += delta.x ();
 
1071
 
 
1072
            if (w->saveMask () & CWY)
 
1073
                w->saveWc ().y += delta.y ();
 
1074
 
 
1075
            /* Make sure everyting starts out at the windows
 
1076
               current position */
 
1077
            pw->lastX = w->x () + pw->tx;
 
1078
            pw->lastY = w->y () + pw->ty;
 
1079
 
 
1080
            pw->targetX = pw->lastX + delta.x ();
 
1081
            pw->targetY = pw->lastY + delta.y ();
 
1082
 
 
1083
            /* mark for animation */
 
1084
            pw->adjust = true;
 
1085
            moreAdjust = true;
 
1086
 
 
1087
            /* cause repainting */
 
1088
            pw->cWindow->addDamage ();
 
1089
        }
 
1090
    }
 
1091
 
 
1092
    /* tell event.c handleEvent to not call XAllowEvents */
 
1093
    return false;
 
1094
}
 
1095
 
 
1096
PutType
 
1097
PutScreen::typeFromString (const CompString &type)
 
1098
{
 
1099
    if (type == "absolute")
 
1100
        return PutAbsolute;
 
1101
    else if (type == "relative")
 
1102
        return PutRelative;
 
1103
    else if (type == "pointer")
 
1104
        return PutPointer;
 
1105
    else if (type == "viewport")
 
1106
        return (PutType) PutViewport;
 
1107
    else if (type == "viewportleft")
 
1108
        return PutViewportLeft;
 
1109
    else if (type == "viewportright")
 
1110
        return PutViewportRight;
 
1111
    else if (type == "viewportup")
 
1112
        return PutViewportUp;
 
1113
    else if (type == "viewportdown")
 
1114
        return PutViewportDown;
 
1115
    else if (type == "nextoutput")
 
1116
        return PutNextOutput;
 
1117
    else if (type == "restore")
 
1118
        return PutRestore;
 
1119
    else if (type == "bottomleft")
 
1120
        return PutBottomLeft;
 
1121
    else if (type == "emptybottomleft")
 
1122
        return PutEmptyBottomLeft;
 
1123
    else if (type == "left")
 
1124
        return PutLeft;
 
1125
    else if (type == "emptyleft")
 
1126
        return PutEmptyLeft;
 
1127
    else if (type == "topleft")
 
1128
        return PutTopLeft;
 
1129
    else if (type == "emptytopleft")
 
1130
        return PutEmptyTopLeft;
 
1131
    else if (type == "top")
 
1132
        return PutTop;
 
1133
    else if (type == "emptytop")
 
1134
        return PutEmptyTop;
 
1135
    else if (type == "topright")
 
1136
        return PutTopRight;
 
1137
    else if (type == "emptytopright")
 
1138
        return PutEmptyTopRight;
 
1139
    else if (type == "right")
 
1140
        return PutRight;
 
1141
    else if (type == "emptyright")
 
1142
        return PutEmptyRight;
 
1143
    else if (type == "bottomright")
 
1144
        return PutBottomRight;
 
1145
    else if (type == "emptybottomright")
 
1146
        return PutEmptyBottomRight;
 
1147
    else if (type == "bottom")
 
1148
        return PutBottom;
 
1149
    else if (type == "emptybottom")
 
1150
        return PutEmptyBottom;
 
1151
    else if (type == "center")
 
1152
        return PutCenter;
 
1153
    else if (type == "emptycenter")
 
1154
        return PutEmptyCenter;
 
1155
    else
 
1156
        return PutUnknown;
 
1157
}
 
1158
 
 
1159
 
 
1160
bool
 
1161
PutScreen::initiate (CompAction         *action,
 
1162
                     CompAction::State  state,
 
1163
                     CompOption::Vector &option)
 
1164
{
 
1165
    PutType    type = PutUnknown;
 
1166
    CompString typeString;
 
1167
 
 
1168
    typeString = CompOption::getStringOptionNamed (option, "type");
 
1169
    if (!typeString.empty ())
 
1170
        type = typeFromString (typeString);
 
1171
 
 
1172
/*    if (type == (PutType) PutViewport)
 
1173
        return toViewport (action, state, option);
 
1174
    else*/
 
1175
    return initiateCommon (action, state, option,type);
 
1176
}
 
1177
 
 
1178
bool
 
1179
PutScreen::toViewport (CompAction         *action,
 
1180
                       CompAction::State  state,
 
1181
                       CompOption::Vector &option,
 
1182
                       int vp)
 
1183
{
 
1184
    int last = option.size ();
 
1185
    option.resize(last+1);
 
1186
    option[last].setName ("viewport",CompOption::TypeInt);
 
1187
    option[last].value ().set (vp-1);
 
1188
 
 
1189
    return initiateCommon (action, state, option, (PutType) PutViewport);
 
1190
}
 
1191
 
 
1192
 
 
1193
PutScreen::PutScreen (CompScreen *screen) :
 
1194
    PluginClassHandler <PutScreen, CompScreen> (screen),
 
1195
    PutOptions (),
 
1196
    screen (screen),
 
1197
    cScreen (CompositeScreen::get (screen)),
 
1198
    gScreen (GLScreen::get (screen)),
 
1199
    lastWindow (None),
 
1200
    lastType (PutUnknown),
 
1201
    moreAdjust (false),
 
1202
    grabIndex (0)
 
1203
{
 
1204
    ScreenInterface::setHandler (screen);
 
1205
    CompositeScreenInterface::setHandler (cScreen);
 
1206
    GLScreenInterface::setHandler (gScreen);
 
1207
 
 
1208
    compizPutWindowAtom = XInternAtom(screen->dpy (),
 
1209
                                      "_COMPIZ_PUT_WINDOW", 0);
 
1210
 
 
1211
    optionSetPutPutInitiate (boost::bind (&PutScreen::initiate, this,
 
1212
                                          _1, _2, _3));
 
1213
 
 
1214
#define setAction(action, type) \
 
1215
    optionSet##action##KeyInitiate (boost::bind (&PutScreen::initiateCommon,   \
 
1216
                                              this, _1,_2,_3,type));           \
 
1217
    optionSet##action##ButtonInitiate (boost::bind (&PutScreen::initiateCommon,\
 
1218
                                              this, _1,_2,_3,type))
 
1219
 
 
1220
    setAction (PutRestore, PutRestore);
 
1221
    setAction (PutPointer, PutPointer);
 
1222
    setAction (PutNextOutput, PutNextOutput);
 
1223
    setAction (PutCenter, PutCenter);
 
1224
    setAction (PutEmptyCenter, PutEmptyCenter);
 
1225
    setAction (PutLeft, PutLeft);
 
1226
    setAction (PutEmptyLeft, PutEmptyLeft);
 
1227
    setAction (PutRight, PutRight);
 
1228
    setAction (PutEmptyRight, PutEmptyRight);
 
1229
    setAction (PutTop, PutTop);
 
1230
    setAction (PutEmptyTop, PutEmptyTop);
 
1231
    setAction (PutBottom, PutBottom);
 
1232
    setAction (PutEmptyBottom, PutEmptyBottom);
 
1233
    setAction (PutTopleft, PutTopLeft);
 
1234
    setAction (PutEmptyTopleft, PutEmptyTopLeft);
 
1235
    setAction (PutTopright, PutTopRight);
 
1236
    setAction (PutEmptyTopright, PutEmptyTopRight);
 
1237
    setAction (PutBottomleft, PutBottomLeft);
 
1238
    setAction (PutEmptyBottomleft, PutEmptyBottomLeft);
 
1239
    setAction (PutBottomright, PutBottomRight);
 
1240
    setAction (PutEmptyBottomright, PutEmptyBottomRight);
 
1241
 
 
1242
#define setViewportAction(num)                                                 \
 
1243
    optionSetPutViewport##num##KeyInitiate(boost::bind (&PutScreen::toViewport,\
 
1244
                                this, _1,_2,_3,num));
 
1245
 
 
1246
    setViewportAction(1);
 
1247
    setViewportAction(2);
 
1248
    setViewportAction(3);
 
1249
    setViewportAction(4);
 
1250
    setViewportAction(5);
 
1251
    setViewportAction(6);
 
1252
    setViewportAction(7);
 
1253
    setViewportAction(8);
 
1254
    setViewportAction(9);
 
1255
    setViewportAction(10);
 
1256
    setViewportAction(11);
 
1257
    setViewportAction(12);
 
1258
 
 
1259
#define setDirectionAction(action) \
 
1260
    optionSet##action##KeyInitiate(boost::bind (&PutScreen::initiateCommon, \
 
1261
                                                this, _1,_2,_3,action))
 
1262
 
 
1263
    setDirectionAction(PutViewportLeft);
 
1264
    setDirectionAction(PutViewportRight);
 
1265
    setDirectionAction(PutViewportUp);
 
1266
    setDirectionAction(PutViewportDown);
 
1267
}
 
1268
 
 
1269
PutWindow::PutWindow (CompWindow *window) :
 
1270
    PluginClassHandler <PutWindow, CompWindow> (window),
 
1271
    window (window),
 
1272
    cWindow (CompositeWindow::get (window)),
 
1273
    gWindow (GLWindow::get (window)),
 
1274
    xVelocity (0),
 
1275
    yVelocity (0),
 
1276
    tx (0),
 
1277
    ty (0),
 
1278
    lastX (window->serverX ()),
 
1279
    lastY (window->serverY ()),
 
1280
    adjust (false)
 
1281
{
 
1282
    WindowInterface::setHandler (window);
 
1283
    CompositeWindowInterface::setHandler (cWindow);
 
1284
    GLWindowInterface::setHandler (gWindow);
 
1285
}
 
1286
 
 
1287
bool
 
1288
PutPluginVTable::init ()
 
1289
{
 
1290
    if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION))
 
1291
         return false;
 
1292
    if (!CompPlugin::checkPluginABI ("composite", COMPIZ_COMPOSITE_ABI))
 
1293
         return false;
 
1294
    if (!CompPlugin::checkPluginABI ("opengl", COMPIZ_OPENGL_ABI))
 
1295
         return false;
 
1296
 
 
1297
    return true;
 
1298
}