~ubuntu-branches/ubuntu/oneiric/compiz/oneiric-proposed

« back to all changes in this revision

Viewing changes to .pc/fix-764330.patch/plugins/move/src/move.cpp

  • Committer: Package Import Robot
  • Author(s): Omer Akram, Daniel van Vugt, Omer Akram
  • Date: 2012-02-10 16:11:19 UTC
  • Revision ID: package-import@ubuntu.com-20120210161119-9cajsah0bjz1176o
Tags: 1:0.9.6+bzr20110929-0ubuntu6.2
[ Daniel van Vugt ]
* Fix slow/stuttering display with fglrx (LP: #763005)

[ Omer Akram ]
* debian/patches/fix-764330.patch:
  - Moving windows lags behind the mouse by 1-2 seconds;
    appear to freeze when dragging. (LP: #764330)

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 <stdio.h>
 
27
#include <stdlib.h>
 
28
#include <string.h>
 
29
 
 
30
#include <X11/cursorfont.h>
 
31
 
 
32
#include <core/atoms.h>
 
33
#include "move.h"
 
34
 
 
35
COMPIZ_PLUGIN_20090315 (move, MovePluginVTable)
 
36
 
 
37
static bool
 
38
moveInitiate (CompAction      *action,
 
39
              CompAction::State state,
 
40
              CompOption::Vector &options)
 
41
{
 
42
    CompWindow *w;
 
43
    Window     xid;
 
44
 
 
45
    MOVE_SCREEN (screen);
 
46
 
 
47
    xid = CompOption::getIntOptionNamed (options, "window");
 
48
 
 
49
    w = screen->findWindow (xid);
 
50
    if (w && (w->actions () & CompWindowActionMoveMask))
 
51
    {
 
52
        CompRect     workArea;
 
53
        unsigned int mods;
 
54
        int          x, y, button;
 
55
        bool         sourceExternalApp;
 
56
 
 
57
        CompScreen *s = screen;
 
58
 
 
59
        mods = CompOption::getIntOptionNamed (options, "modifiers", 0);
 
60
 
 
61
        x = CompOption::getIntOptionNamed (options, "x", w->geometry ().x () +
 
62
                                           (w->size ().width () / 2));
 
63
        y = CompOption::getIntOptionNamed (options, "y", w->geometry ().y () +
 
64
                                           (w->size ().height () / 2));
 
65
 
 
66
        button = CompOption::getIntOptionNamed (options, "button", -1);
 
67
 
 
68
        if (s->otherGrabExist ("move", NULL))
 
69
            return false;
 
70
 
 
71
        if (ms->w)
 
72
            return false;
 
73
 
 
74
        if (w->type () & (CompWindowTypeDesktopMask |
 
75
                       CompWindowTypeDockMask    |
 
76
                       CompWindowTypeFullscreenMask))
 
77
            return false;
 
78
 
 
79
        if (w->overrideRedirect ())
 
80
            return false;
 
81
 
 
82
        if (state & CompAction::StateInitButton)
 
83
            action->setState (action->state () | CompAction::StateTermButton);
 
84
 
 
85
        if (ms->region)
 
86
        {
 
87
            XDestroyRegion (ms->region);
 
88
            ms->region = NULL;
 
89
        }
 
90
 
 
91
        ms->status = RectangleOut;
 
92
 
 
93
        ms->savedX = w->serverGeometry ().x ();
 
94
        ms->savedY = w->serverGeometry ().y ();
 
95
 
 
96
        ms->x = 0;
 
97
        ms->y = 0;
 
98
 
 
99
        lastPointerX = x;
 
100
        lastPointerY = y;
 
101
 
 
102
        sourceExternalApp =
 
103
            CompOption::getBoolOptionNamed (options, "external", false);
 
104
        ms->yConstrained = sourceExternalApp && ms->optionGetConstrainY ();
 
105
 
 
106
        ms->origState = w->state ();
 
107
 
 
108
        workArea = s->getWorkareaForOutput (w->outputDevice ());
 
109
 
 
110
        ms->snapBackY = w->serverGeometry ().y () - workArea.y ();
 
111
        ms->snapOffY  = y - workArea.y ();
 
112
 
 
113
        if (!ms->grab)
 
114
            ms->grab = s->pushGrab (ms->moveCursor, "move");
 
115
 
 
116
        if (ms->grab)
 
117
        {
 
118
            unsigned int grabMask = CompWindowGrabMoveMask |
 
119
                                    CompWindowGrabButtonMask;
 
120
 
 
121
            if (sourceExternalApp)
 
122
                grabMask |= CompWindowGrabExternalAppMask;
 
123
 
 
124
            ms->w = w;
 
125
 
 
126
            ms->releaseButton = button;
 
127
 
 
128
            w->grabNotify (x, y, mods, grabMask);
 
129
 
 
130
            /* Click raise happens implicitly on buttons 1, 2 and 3 so don't
 
131
             * restack this window again if the action buttonbinding was from
 
132
             * one of those buttons */
 
133
            if (screen->getOption ("raise_on_click")->value ().b () &&
 
134
                button != Button1 && button != Button2 && button != Button3)
 
135
                w->updateAttributes (CompStackingUpdateModeAboveFullscreen);
 
136
 
 
137
            if (state & CompAction::StateInitKey)
 
138
            {
 
139
                int xRoot, yRoot;
 
140
 
 
141
                xRoot = w->geometry ().x () + (w->size ().width () / 2);
 
142
                yRoot = w->geometry ().y () + (w->size ().height () / 2);
 
143
 
 
144
                s->warpPointer (xRoot - pointerX, yRoot - pointerY);
 
145
            }
 
146
 
 
147
            if (ms->moveOpacity != OPAQUE)
 
148
            {
 
149
                MOVE_WINDOW (w);
 
150
 
 
151
                if (mw->cWindow)
 
152
                    mw->cWindow->addDamage ();
 
153
                if (mw->gWindow)
 
154
                mw->gWindow->glPaintSetEnabled (mw, true);
 
155
            }
 
156
        }
 
157
    }
 
158
 
 
159
    return false;
 
160
}
 
161
 
 
162
static bool
 
163
moveTerminate (CompAction      *action,
 
164
               CompAction::State state,
 
165
               CompOption::Vector &options)
 
166
{
 
167
    MOVE_SCREEN (screen);
 
168
 
 
169
    if (ms->w)
 
170
    {
 
171
        if (state & CompAction::StateCancel)
 
172
            ms->w->move (ms->savedX - ms->w->geometry ().x (),
 
173
                         ms->savedY - ms->w->geometry ().y (), false);
 
174
 
 
175
        ms->w->syncPosition ();
 
176
 
 
177
        /* update window attributes as window constraints may have
 
178
           changed - needed e.g. if a maximized window was moved
 
179
           to another output device */
 
180
        ms->w->updateAttributes (CompStackingUpdateModeNone);
 
181
 
 
182
        ms->w->ungrabNotify ();
 
183
 
 
184
        if (ms->grab)
 
185
        {
 
186
            screen->removeGrab (ms->grab, NULL);
 
187
            ms->grab = NULL;
 
188
        }
 
189
 
 
190
        if (ms->moveOpacity != OPAQUE)
 
191
        {
 
192
            MOVE_WINDOW (ms->w);
 
193
 
 
194
            if (mw->cWindow)
 
195
                mw->cWindow->addDamage ();
 
196
            if (mw->gWindow)
 
197
                mw->gWindow->glPaintSetEnabled (mw, false);
 
198
        }
 
199
 
 
200
        ms->w             = 0;
 
201
        ms->releaseButton = 0;
 
202
    }
 
203
 
 
204
    action->setState (action->state () & ~(CompAction::StateTermKey |
 
205
                                           CompAction::StateTermButton));
 
206
 
 
207
    return false;
 
208
}
 
209
 
 
210
/* creates a region containing top and bottom struts. only struts that are
 
211
   outside the screen workarea are considered. */
 
212
static Region
 
213
moveGetYConstrainRegion (CompScreen *s)
 
214
{
 
215
    CompWindow   *w;
 
216
    Region       region;
 
217
    REGION       r;
 
218
    CompRect     workArea;
 
219
    BoxRec       extents;
 
220
    unsigned int i;
 
221
 
 
222
    region = XCreateRegion ();
 
223
    if (!region)
 
224
        return NULL;
 
225
 
 
226
    r.rects    = &r.extents;
 
227
    r.numRects = r.size = 1;
 
228
 
 
229
    r.extents.x1 = MINSHORT;
 
230
    r.extents.y1 = 0;
 
231
    r.extents.x2 = 0;
 
232
    r.extents.y2 = s->height ();
 
233
 
 
234
    XUnionRegion (&r, region, region);
 
235
 
 
236
    r.extents.x1 = s->width ();
 
237
    r.extents.x2 = MAXSHORT;
 
238
 
 
239
    XUnionRegion (&r, region, region);
 
240
 
 
241
    for (i = 0; i < s->outputDevs ().size (); i++)
 
242
    {
 
243
        XUnionRegion (s->outputDevs ()[i].region (), region, region);
 
244
 
 
245
        workArea = s->getWorkareaForOutput (i);
 
246
        extents = s->outputDevs ()[i].region ()->extents;
 
247
 
 
248
        foreach (w, s->windows ())
 
249
        {
 
250
            if (!w->mapNum ())
 
251
                continue;
 
252
 
 
253
            if (w->struts ())
 
254
            {
 
255
                r.extents.x1 = w->struts ()->top.x;
 
256
                r.extents.y1 = w->struts ()->top.y;
 
257
                r.extents.x2 = r.extents.x1 + w->struts ()->top.width;
 
258
                r.extents.y2 = r.extents.y1 + w->struts ()->top.height;
 
259
 
 
260
                if (r.extents.x1 < extents.x1)
 
261
                    r.extents.x1 = extents.x1;
 
262
                if (r.extents.x2 > extents.x2)
 
263
                    r.extents.x2 = extents.x2;
 
264
                if (r.extents.y1 < extents.y1)
 
265
                    r.extents.y1 = extents.y1;
 
266
                if (r.extents.y2 > extents.y2)
 
267
                    r.extents.y2 = extents.y2;
 
268
 
 
269
                if (r.extents.x1 < r.extents.x2 && r.extents.y1 < r.extents.y2)
 
270
                {
 
271
                    if (r.extents.y2 <= workArea.y ())
 
272
                        XSubtractRegion (region, &r, region);
 
273
                }
 
274
 
 
275
                r.extents.x1 = w->struts ()->bottom.x;
 
276
                r.extents.y1 = w->struts ()->bottom.y;
 
277
                r.extents.x2 = r.extents.x1 + w->struts ()->bottom.width;
 
278
                r.extents.y2 = r.extents.y1 + w->struts ()->bottom.height;
 
279
 
 
280
                if (r.extents.x1 < extents.x1)
 
281
                    r.extents.x1 = extents.x1;
 
282
                if (r.extents.x2 > extents.x2)
 
283
                    r.extents.x2 = extents.x2;
 
284
                if (r.extents.y1 < extents.y1)
 
285
                    r.extents.y1 = extents.y1;
 
286
                if (r.extents.y2 > extents.y2)
 
287
                    r.extents.y2 = extents.y2;
 
288
 
 
289
                if (r.extents.x1 < r.extents.x2 && r.extents.y1 < r.extents.y2)
 
290
                {
 
291
                    if (r.extents.y1 >= workArea.bottom ())
 
292
                        XSubtractRegion (region, &r, region);
 
293
                }
 
294
            }
 
295
        }
 
296
    }
 
297
 
 
298
    return region;
 
299
}
 
300
 
 
301
static void
 
302
moveHandleMotionEvent (CompScreen *s,
 
303
                       int        xRoot,
 
304
                       int        yRoot)
 
305
{
 
306
    MOVE_SCREEN (s);
 
307
 
 
308
    if (ms->grab)
 
309
    {
 
310
        int          dx, dy;
 
311
        int          wX, wY;
 
312
        int          wWidth, wHeight;
 
313
        CompWindow   *w;
 
314
 
 
315
        w = ms->w;
 
316
 
 
317
        wX      = w->geometry ().x ();
 
318
        wY      = w->geometry ().y ();
 
319
        wWidth  = w->geometry ().width () +
 
320
                  w->geometry ().border () * 2;
 
321
        wHeight = w->geometry ().height () +
 
322
                  w->geometry ().border () * 2;
 
323
 
 
324
        ms->x += xRoot - lastPointerX;
 
325
        ms->y += yRoot - lastPointerY;
 
326
 
 
327
        if (w->type () & CompWindowTypeFullscreenMask)
 
328
        {
 
329
            dx = dy = 0;
 
330
        }
 
331
        else
 
332
        {
 
333
            CompRect workArea;
 
334
            int      min, max;
 
335
 
 
336
            dx = ms->x;
 
337
            dy = ms->y;
 
338
 
 
339
            workArea = s->getWorkareaForOutput (w->outputDevice ());
 
340
 
 
341
            if (ms->yConstrained)
 
342
            {
 
343
                if (!ms->region)
 
344
                    ms->region = moveGetYConstrainRegion (s);
 
345
 
 
346
                /* make sure that the top border extents or the top row of
 
347
                   pixels are within what is currently our valid screen
 
348
                   region */
 
349
                if (ms->region)
 
350
                {
 
351
                    int x, y, width, height;
 
352
                    int status;
 
353
 
 
354
                    x      = wX + dx - w->border ().left;
 
355
                    y      = wY + dy - w->border ().top;
 
356
                    width  = wWidth + w->border ().left + w->border ().right;
 
357
                    height = w->border ().top ? w->border ().top : 1;
 
358
 
 
359
                    status = XRectInRegion (ms->region, x, y,
 
360
                                            (unsigned int) width,
 
361
                                            (unsigned int) height);
 
362
 
 
363
                    /* only constrain movement if previous position was valid */
 
364
                    if (ms->status == RectangleIn)
 
365
                    {
 
366
                        int xStatus = status;
 
367
 
 
368
                        while (dx && xStatus != RectangleIn)
 
369
                        {
 
370
                            xStatus = XRectInRegion (ms->region,
 
371
                                                     x, y - dy,
 
372
                                                     (unsigned int) width,
 
373
                                                     (unsigned int) height);
 
374
 
 
375
                            if (xStatus != RectangleIn)
 
376
                                dx += (dx < 0) ? 1 : -1;
 
377
 
 
378
                            x = wX + dx - w->border ().left;
 
379
                        }
 
380
 
 
381
                        while (dy && status != RectangleIn)
 
382
                        {
 
383
                            status = XRectInRegion (ms->region,
 
384
                                                    x, y,
 
385
                                                    (unsigned int) width,
 
386
                                                    (unsigned int) height);
 
387
 
 
388
                            if (status != RectangleIn)
 
389
                                dy += (dy < 0) ? 1 : -1;
 
390
 
 
391
                            y = wY + dy - w->border ().top;
 
392
                        }
 
393
                    }
 
394
                    else
 
395
                    {
 
396
                        ms->status = status;
 
397
                    }
 
398
                }
 
399
            }
 
400
 
 
401
            if (ms->optionGetSnapoffMaximized ())
 
402
            {
 
403
                if (w->state () & CompWindowStateMaximizedVertMask)
 
404
                {
 
405
                    if (abs (yRoot - workArea.y () - ms->snapOffY) >= SNAP_OFF)
 
406
                    {
 
407
                        if (!s->otherGrabExist ("move", NULL))
 
408
                        {
 
409
                            int width = w->serverGeometry ().width ();
 
410
 
 
411
                            w->saveMask () |= CWX | CWY;
 
412
 
 
413
                            if (w->saveMask ()& CWWidth)
 
414
                                width = w->saveWc ().width;
 
415
 
 
416
                            w->saveWc ().x = xRoot - (width >> 1);
 
417
                            w->saveWc ().y = yRoot + (w->border ().top >> 1);
 
418
 
 
419
                            ms->x = ms->y = 0;
 
420
 
 
421
                            w->maximize (0);
 
422
 
 
423
                            ms->snapOffY = ms->snapBackY;
 
424
 
 
425
                            return;
 
426
                        }
 
427
                    }
 
428
                }
 
429
                else if (ms->origState & CompWindowStateMaximizedVertMask)
 
430
                {
 
431
                    if (abs (yRoot - workArea.y () - ms->snapBackY) < SNAP_BACK)
 
432
                    {
 
433
                        if (!s->otherGrabExist ("move", NULL))
 
434
                        {
 
435
                            int wy;
 
436
 
 
437
                            /* update server position before maximizing
 
438
                               window again so that it is maximized on
 
439
                               correct output */
 
440
                            w->syncPosition ();
 
441
 
 
442
                            w->maximize (ms->origState);
 
443
 
 
444
                            wy  = workArea.y () + (w->border ().top >> 1);
 
445
                            wy += w->sizeHints ().height_inc >> 1;
 
446
 
 
447
                            s->warpPointer (0, wy - pointerY);
 
448
 
 
449
                            return;
 
450
                        }
 
451
                    }
 
452
                }
 
453
            }
 
454
 
 
455
            if (w->state () & CompWindowStateMaximizedVertMask)
 
456
            {
 
457
                min = workArea.y () + w->border ().top;
 
458
                max = workArea.bottom () - w->border ().bottom - wHeight;
 
459
 
 
460
                if (wY + dy < min)
 
461
                    dy = min - wY;
 
462
                else if (wY + dy > max)
 
463
                    dy = max - wY;
 
464
            }
 
465
 
 
466
            if (w->state () & CompWindowStateMaximizedHorzMask)
 
467
            {
 
468
                if (wX > (int) s->width () ||
 
469
                    wX + w->size ().width () < 0)
 
470
                    return;
 
471
 
 
472
                if (wX + wWidth < 0)
 
473
                    return;
 
474
 
 
475
                min = workArea.x () + w->border ().left;
 
476
                max = workArea.right () - w->border ().right - wWidth;
 
477
 
 
478
                if (wX + dx < min)
 
479
                    dx = min - wX;
 
480
                else if (wX + dx > max)
 
481
                    dx = max - wX;
 
482
            }
 
483
        }
 
484
 
 
485
        if (dx || dy)
 
486
        {
 
487
            w->move (wX + dx - w->geometry ().x (),
 
488
                     wY + dy - w->geometry ().y (), false);
 
489
 
 
490
            if (ms->optionGetLazyPositioning () &&
 
491
                ms->hasCompositing &&
 
492
                !MoveWindow::get (ms->w)->mLocked)
 
493
            {
 
494
                /* FIXME: This form of lazy positioning is broken and should
 
495
                   be replaced asap. Current code exists just to avoid a
 
496
                   major performance regression in the 0.5.2 release. */
 
497
                w->serverGeometry ().setX (w->geometry ().x ());
 
498
                w->serverGeometry ().setY (w->geometry ().y ());
 
499
            }
 
500
            else
 
501
            {
 
502
                w->syncPosition ();
 
503
            }
 
504
 
 
505
            ms->x -= dx;
 
506
            ms->y -= dy;
 
507
        }
 
508
    }
 
509
}
 
510
 
 
511
/* FIXME: This is a hack to prevent a race condition
 
512
 * when core is processing ConfigureNotify events. It
 
513
 * MUST be removed after 0.9.6 when we can break ABI
 
514
 * and do lazy positioning correctly ! */
 
515
 
 
516
void
 
517
MoveScreen::handleCompizEvent (const char *plugin, const char *event, CompOption::Vector &options)
 
518
{
 
519
    if (w)
 
520
    {
 
521
        if (std::string ("core") == std::string (plugin))
 
522
        {
 
523
            if (std::string ("lock_position") == std::string (event))
 
524
            {
 
525
                Window xid = CompOption::getIntOptionNamed (options, "window", 0);
 
526
                int    lock = CompOption::getIntOptionNamed (options, "active", 0);
 
527
 
 
528
                if (xid == ROOTPARENT (w))
 
529
                    MoveWindow::get (w)->mLocked = lock ? true : false;
 
530
            }
 
531
        }
 
532
    }
 
533
 
 
534
    screen->handleCompizEvent (plugin, event, options);
 
535
}
 
536
 
 
537
void
 
538
MoveScreen::handleEvent (XEvent *event)
 
539
{
 
540
    switch (event->type) {
 
541
        case ButtonPress:
 
542
        case ButtonRelease:
 
543
            if (event->xbutton.root == screen->root ())
 
544
            {
 
545
                if (grab)
 
546
                {
 
547
                    if (releaseButton == -1 ||
 
548
                        releaseButton == (int) event->xbutton.button)
 
549
                    {
 
550
                        moveTerminate (&optionGetInitiateButton (),
 
551
                                       CompAction::StateTermButton,
 
552
                                       noOptions);
 
553
                    }
 
554
                }
 
555
            }
 
556
            break;
 
557
        case KeyPress:
 
558
            if (event->xkey.root == screen->root ())
 
559
            {
 
560
                if (grab)
 
561
                {
 
562
                    unsigned int i;
 
563
 
 
564
                    for (i = 0; i < NUM_KEYS; i++)
 
565
                    {
 
566
                        if (event->xkey.keycode == key[i])
 
567
                        {
 
568
                            XWarpPointer (screen->dpy (), None, None,
 
569
                                          0, 0, 0, 0,
 
570
                                          mKeys[i].dx * KEY_MOVE_INC,
 
571
                                          mKeys[i].dy * KEY_MOVE_INC);
 
572
                            break;
 
573
                        }
 
574
                    }
 
575
                }
 
576
            }
 
577
            break;
 
578
        case MotionNotify:
 
579
            if (event->xmotion.root == screen->root ())
 
580
                moveHandleMotionEvent (screen, pointerX, pointerY);
 
581
            break;
 
582
        case EnterNotify:
 
583
        case LeaveNotify:
 
584
            if (event->xcrossing.root == screen->root ())
 
585
                moveHandleMotionEvent (screen, pointerX, pointerY);
 
586
            break;
 
587
        case ClientMessage:
 
588
            if (event->xclient.message_type == Atoms::wmMoveResize)
 
589
            {
 
590
                CompWindow *w;
 
591
                unsigned   long type = (unsigned long) event->xclient.data.l[2];
 
592
 
 
593
                MOVE_SCREEN (screen);
 
594
 
 
595
                if (type == WmMoveResizeMove ||
 
596
                    type == WmMoveResizeMoveKeyboard)
 
597
                {
 
598
                    w = screen->findWindow (event->xclient.window);
 
599
                    if (w)
 
600
                    {
 
601
                        CompOption::Vector o;
 
602
 
 
603
                        o.push_back (CompOption ("window", CompOption::TypeInt));
 
604
                        o[0].value ().set ((int) event->xclient.window);
 
605
 
 
606
                        o.push_back (CompOption ("external",
 
607
                                     CompOption::TypeBool));
 
608
                        o[1].value ().set (true);
 
609
 
 
610
                        if (event->xclient.data.l[2] == WmMoveResizeMoveKeyboard)
 
611
                        {
 
612
                            moveInitiate (&optionGetInitiateKey (),
 
613
                                          CompAction::StateInitKey, o);
 
614
                        }
 
615
                        else
 
616
                        {
 
617
 
 
618
                            /* TODO: not only button 1 */
 
619
                            if (pointerMods & Button1Mask)
 
620
                            {
 
621
                                o.push_back (CompOption ("modifiers", CompOption::TypeInt));
 
622
                                o[2].value ().set ((int) pointerMods);
 
623
 
 
624
                                o.push_back (CompOption ("x", CompOption::TypeInt));
 
625
                                o[3].value ().set ((int) event->xclient.data.l[0]);
 
626
 
 
627
                                o.push_back (CompOption ("y", CompOption::TypeInt));
 
628
                                o[4].value ().set ((int) event->xclient.data.l[1]);
 
629
 
 
630
                                o.push_back (CompOption ("button", CompOption::TypeInt));
 
631
                                o[5].value ().set ((int) (event->xclient.data.l[3] ?
 
632
                                               event->xclient.data.l[3] : -1));
 
633
 
 
634
                                moveInitiate (&optionGetInitiateButton (),
 
635
                                              CompAction::StateInitButton, o);
 
636
 
 
637
                                moveHandleMotionEvent (screen, pointerX, pointerY);
 
638
                            }
 
639
                        }
 
640
                    }
 
641
                }
 
642
                else if (ms->w && type == WmMoveResizeCancel)
 
643
                {
 
644
                    if (ms->w->id () == event->xclient.window)
 
645
                    {
 
646
                        moveTerminate (&optionGetInitiateButton (),
 
647
                                       CompAction::StateCancel, noOptions);
 
648
                        moveTerminate (&optionGetInitiateKey (),
 
649
                                       CompAction::StateCancel, noOptions);
 
650
 
 
651
                    }
 
652
                }
 
653
            }
 
654
            break;
 
655
        case DestroyNotify:
 
656
            if (w && w->id () == event->xdestroywindow.window)
 
657
            {
 
658
                moveTerminate (&optionGetInitiateButton (), 0, noOptions);
 
659
                moveTerminate (&optionGetInitiateKey (), 0, noOptions);
 
660
            }
 
661
            break;
 
662
        case UnmapNotify:
 
663
            if (w && w->id () == event->xunmap.window)
 
664
            {
 
665
                moveTerminate (&optionGetInitiateButton (), 0, noOptions);
 
666
                moveTerminate (&optionGetInitiateKey (), 0, noOptions);
 
667
            }
 
668
        default:
 
669
            break;
 
670
    }
 
671
 
 
672
    screen->handleEvent (event);
 
673
}
 
674
 
 
675
bool
 
676
MoveWindow::glPaint (const GLWindowPaintAttrib &attrib,
 
677
                     const GLMatrix            &transform,
 
678
                     const CompRegion          &region,
 
679
                     unsigned int              mask)
 
680
{
 
681
    GLWindowPaintAttrib sAttrib = attrib;
 
682
    bool                status;
 
683
 
 
684
    MOVE_SCREEN (screen);
 
685
 
 
686
    if (ms->grab)
 
687
    {
 
688
        if (ms->w == window && ms->moveOpacity != OPAQUE)
 
689
        {
 
690
            /* modify opacity of windows that are not active */
 
691
            sAttrib.opacity = (sAttrib.opacity * ms->moveOpacity) >> 16;
 
692
        }
 
693
    }
 
694
 
 
695
    status = gWindow->glPaint (sAttrib, transform, region, mask);
 
696
 
 
697
    return status;
 
698
}
 
699
 
 
700
void
 
701
MoveScreen::updateOpacity ()
 
702
{
 
703
    moveOpacity = (optionGetOpacity () * OPAQUE) / 100;
 
704
}
 
705
 
 
706
MoveScreen::MoveScreen (CompScreen *screen) :
 
707
    PluginClassHandler<MoveScreen,CompScreen> (screen),
 
708
    w (0),
 
709
    region (NULL),
 
710
    status (RectangleOut),
 
711
    releaseButton (0),
 
712
    grab (NULL),
 
713
    hasCompositing (false),
 
714
    yConstrained (false)
 
715
{
 
716
 
 
717
    updateOpacity ();
 
718
 
 
719
    for (unsigned int i = 0; i < NUM_KEYS; i++)
 
720
        key[i] = XKeysymToKeycode (screen->dpy (),
 
721
                                   XStringToKeysym (mKeys[i].name));
 
722
 
 
723
    moveCursor = XCreateFontCursor (screen->dpy (), XC_fleur);
 
724
    if (CompositeScreen::get (screen))
 
725
        hasCompositing =
 
726
            CompositeScreen::get (screen)->compositingActive ();
 
727
 
 
728
    optionSetOpacityNotify (boost::bind (&MoveScreen::updateOpacity, this));
 
729
 
 
730
    optionSetInitiateButtonInitiate (moveInitiate);
 
731
    optionSetInitiateButtonTerminate (moveTerminate);
 
732
 
 
733
    optionSetInitiateKeyInitiate (moveInitiate);
 
734
    optionSetInitiateKeyTerminate (moveTerminate);
 
735
 
 
736
    ScreenInterface::setHandler (screen);
 
737
}
 
738
 
 
739
MoveScreen::~MoveScreen ()
 
740
{
 
741
    if (region)
 
742
        XDestroyRegion (region);
 
743
 
 
744
    if (moveCursor)
 
745
        XFreeCursor (screen->dpy (), moveCursor);
 
746
}
 
747
 
 
748
bool
 
749
MovePluginVTable::init ()
 
750
{
 
751
    if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION))
 
752
         return false;
 
753
 
 
754
    return true;
 
755
}
 
756