~hypodermia/ubuntu/oneiric/compiz/fix-for-bug-301174

« back to all changes in this revision

Viewing changes to .pc/01_bzr_fix_resize.patch/plugins/resize/src/resize.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Didier Roche
  • Date: 2011-04-07 18:06:44 UTC
  • mfrom: (0.168.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20110407180644-7xwnirf7k3zotc2w
Tags: 1:0.9.4+bzr20110407-0ubuntu2
* New upstream snapshot:
  - fix unity-window-decorator crashed with SIGSEGV in event_filter_funct
    (LP: #711561)
* debian/patches/086_new_grid_defaults.patch:
  - change threshold to 15 on sides and 20 on top to work well with the new
    animtion
* debian/patches/01_bzr_fix_grid_on_multimonitor.patch,
  01_bzr_fix_resize.patch, 01_bzr_fix_grid_premultiply.patch:
  - from upstream bzr, fix grid on multimonitor and colors handling
* debian/patches/086_new_grid_defaults.patch,
  debian/patches/029_default_options.patch:
  - set the resize grid shadow to orange (LP: #752711)

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
#include <math.h>
 
30
 
 
31
#include <X11/Xatom.h>
 
32
#include <X11/cursorfont.h>
 
33
 
 
34
#include <core/core.h>
 
35
#include <core/atoms.h>
 
36
#include "resize.h"
 
37
 
 
38
COMPIZ_PLUGIN_20090315 (resize, ResizePluginVTable)
 
39
 
 
40
void
 
41
ResizeScreen::getPaintRectangle (BoxPtr pBox)
 
42
{
 
43
    pBox->x1 = geometry.x - w->border ().left;
 
44
    pBox->y1 = geometry.y - w->border ().top;
 
45
    pBox->x2 = geometry.x + geometry.width +
 
46
               w->serverGeometry ().border () * 2 + w->border ().right;
 
47
 
 
48
    if (w->shaded ())
 
49
        pBox->y2 = geometry.y + w->size ().height () + w->border ().bottom;
 
50
    else
 
51
        pBox->y2 = geometry.y + geometry.height +
 
52
                   w->serverGeometry ().border () * 2 + w->border ().bottom;
 
53
}
 
54
 
 
55
void
 
56
ResizeWindow::getStretchScale (BoxPtr pBox, float *xScale, float *yScale)
 
57
{
 
58
    CompRect rect (window->borderRect ());
 
59
 
 
60
    *xScale = (rect.width ())  ? (pBox->x2 - pBox->x1) /
 
61
                                 (float) rect.width () : 1.0f;
 
62
    *yScale = (rect.height ()) ? (pBox->y2 - pBox->y1) /
 
63
                                 (float) rect.height () : 1.0f;
 
64
}
 
65
 
 
66
void
 
67
ResizeScreen::getStretchRectangle (BoxPtr pBox)
 
68
{
 
69
    BoxRec box;
 
70
    float  xScale, yScale;
 
71
 
 
72
    getPaintRectangle (&box);
 
73
    ResizeWindow::get (w)->getStretchScale (&box, &xScale, &yScale);
 
74
 
 
75
    pBox->x1 = (int) (box.x1 - (w->output ().left - w->border ().left) * xScale);
 
76
    pBox->y1 = (int) (box.y1 - (w->output ().top - w->border ().top) * yScale);
 
77
    pBox->x2 = (int) (box.x2 + w->output ().right * xScale);
 
78
    pBox->y2 = (int) (box.y2 + w->output ().bottom * yScale);
 
79
}
 
80
 
 
81
void
 
82
ResizeScreen::damageRectangle (BoxPtr pBox)
 
83
{
 
84
    int x1, x2, y1, y2;
 
85
 
 
86
    x1 = pBox->x1 - 1;
 
87
    y1 = pBox->y1 - 1;
 
88
    x2 = pBox->x2 + 1;
 
89
    y2 = pBox->y2 + 1;
 
90
 
 
91
    if (cScreen)
 
92
        cScreen->damageRegion (CompRect (x1, y1, x2 - x1, y2 - y1));
 
93
}
 
94
 
 
95
Cursor
 
96
ResizeScreen::cursorFromResizeMask (unsigned int mask)
 
97
{
 
98
    Cursor cursor;
 
99
 
 
100
    if (mask & ResizeLeftMask)
 
101
    {
 
102
        if (mask & ResizeDownMask)
 
103
            cursor = downLeftCursor;
 
104
        else if (mask & ResizeUpMask)
 
105
            cursor = upLeftCursor;
 
106
        else
 
107
            cursor = leftCursor;
 
108
    }
 
109
    else if (mask & ResizeRightMask)
 
110
    {
 
111
        if (mask & ResizeDownMask)
 
112
            cursor = downRightCursor;
 
113
        else if (mask & ResizeUpMask)
 
114
            cursor = upRightCursor;
 
115
        else
 
116
            cursor = rightCursor;
 
117
    }
 
118
    else if (mask & ResizeUpMask)
 
119
    {
 
120
        cursor = upCursor;
 
121
    }
 
122
    else
 
123
    {
 
124
        cursor = downCursor;
 
125
    }
 
126
 
 
127
    return cursor;
 
128
}
 
129
 
 
130
void
 
131
ResizeScreen::sendResizeNotify ()
 
132
{
 
133
    XEvent xev;
 
134
 
 
135
    xev.xclient.type    = ClientMessage;
 
136
    xev.xclient.display = screen->dpy ();
 
137
    xev.xclient.format  = 32;
 
138
 
 
139
    xev.xclient.message_type = resizeNotifyAtom;
 
140
    xev.xclient.window       = w->id ();
 
141
 
 
142
    xev.xclient.data.l[0] = geometry.x;
 
143
    xev.xclient.data.l[1] = geometry.y;
 
144
    xev.xclient.data.l[2] = geometry.width;
 
145
    xev.xclient.data.l[3] = geometry.height;
 
146
    xev.xclient.data.l[4] = 0;
 
147
 
 
148
    XSendEvent (screen->dpy (), screen->root (), false,
 
149
                SubstructureRedirectMask | SubstructureNotifyMask, &xev);
 
150
}
 
151
 
 
152
void
 
153
ResizeScreen::updateWindowProperty ()
 
154
{
 
155
    CompOption::Vector data = resizeInformationAtom.getReadTemplate ();;
 
156
    CompOption::Value v;
 
157
 
 
158
    if (data.size () != 4)
 
159
        return;
 
160
 
 
161
    v = geometry.x;
 
162
    data.at (0).set (v);
 
163
 
 
164
    v = geometry.y;
 
165
    data.at (1).set (v);
 
166
 
 
167
    v = geometry.width;
 
168
    data.at (2).set (v);
 
169
 
 
170
    v = geometry.height;
 
171
    data.at (3).set (v);
 
172
 
 
173
    resizeInformationAtom.updateProperty (w->id (), data, XA_CARDINAL);
 
174
}
 
175
 
 
176
void
 
177
ResizeScreen::finishResizing ()
 
178
{
 
179
    w->ungrabNotify ();
 
180
 
 
181
    resizeInformationAtom.deleteProperty (w->id ());
 
182
 
 
183
    w = NULL;
 
184
}
 
185
 
 
186
#define TOUCH_LEFT 1
 
187
#define TOUCH_RIGHT 2
 
188
#define TOUCH_TOP 3
 
189
#define TOUCH_BOTTOM 4
 
190
 
 
191
static unsigned int
 
192
findTouchingOutput (int touchPoint, unsigned int side)
 
193
{
 
194
    for (unsigned int i = 0; i < screen->outputDevs ().size (); i++)
 
195
    {
 
196
        CompOutput &o = screen->outputDevs ().at (i);
 
197
        if (side == TOUCH_LEFT)
 
198
        {
 
199
            if (o.left () == touchPoint)
 
200
                return  i;
 
201
        }
 
202
        if (side == TOUCH_RIGHT)
 
203
        {
 
204
            if (o.right () == touchPoint)
 
205
                return  i;
 
206
        }
 
207
        if (side == TOUCH_TOP)
 
208
        {
 
209
            if (o.top () == touchPoint)
 
210
                return  i;
 
211
        }
 
212
        if (side == TOUCH_BOTTOM)
 
213
        {
 
214
            if (o.bottom () == touchPoint)
 
215
                return  i;
 
216
        }
 
217
    }
 
218
 
 
219
    return -1;
 
220
}
 
221
 
 
222
static void
 
223
getPointForTp (unsigned int tp, unsigned int output, int &op, int &wap)
 
224
{
 
225
    CompRect og = CompRect (screen->outputDevs ().at (output));
 
226
    CompRect wag = screen->outputDevs ().at (output).workArea ();
 
227
 
 
228
    switch (tp)
 
229
    {
 
230
        case TOUCH_LEFT:
 
231
            op = og.right ();
 
232
            wap = wag.right ();
 
233
            break;
 
234
        case TOUCH_RIGHT:
 
235
            op = og.left ();
 
236
            wap = wag.left ();
 
237
            break;
 
238
        case TOUCH_TOP:
 
239
            op = og.bottom ();
 
240
            wap = wag.bottom ();
 
241
            break;
 
242
        case TOUCH_BOTTOM:
 
243
            op = og.top ();
 
244
            wap = wag.top ();
 
245
            break;
 
246
        default:
 
247
            return;
 
248
    }
 
249
}
 
250
 
 
251
/* Be a little bit intelligent about how we calculate
 
252
 * the workarea. Basically we want to be enclosed in
 
253
 * any area that is obstructed by panels, but not
 
254
 * where two outputs meet
 
255
 *
 
256
 * Also, it does not make sense to resize over
 
257
 * non-touching outputs, so detect that case too
 
258
 * */
 
259
 
 
260
static int
 
261
getOutputForEdge (int windowOutput, unsigned int touch, bool skipFirst)
 
262
{
 
263
    int op, wap;
 
264
    int ret = windowOutput;
 
265
 
 
266
    getPointForTp (touch, windowOutput, op, wap);
 
267
 
 
268
    if ((op == wap) || skipFirst)
 
269
    {
 
270
        int co = windowOutput;
 
271
 
 
272
        do
 
273
        {
 
274
            int oco = co;
 
275
 
 
276
            co = findTouchingOutput (op, touch);
 
277
 
 
278
            /* Could not find a leftmost output from here
 
279
             * so we must have hit the edge of the universe */
 
280
            if (co == -1)
 
281
            {
 
282
                ret = oco;
 
283
                co = -1;
 
284
                break;
 
285
            }
 
286
 
 
287
            getPointForTp (touch, co, op, wap);
 
288
 
 
289
            /* There is something in the way here.... */
 
290
            if (op != wap)
 
291
            {
 
292
                ret = co;
 
293
                co = -1;
 
294
            }
 
295
        }
 
296
        while (co != -1);
 
297
    }
 
298
 
 
299
    return ret;
 
300
}
 
301
 
 
302
static bool
 
303
resizeInitiate (CompAction         *action,
 
304
                CompAction::State  state,
 
305
                CompOption::Vector &options,
 
306
                unsigned int       mode)
 
307
{
 
308
    CompWindow *w;
 
309
    Window     xid;
 
310
 
 
311
    xid = CompOption::getIntOptionNamed (options, "window");
 
312
 
 
313
    w = screen->findWindow (xid);
 
314
    if (w && (w->actions () & CompWindowActionResizeMask))
 
315
    {
 
316
        unsigned int mask;
 
317
        int          x, y;
 
318
        int          button;
 
319
 
 
320
        RESIZE_SCREEN (screen);
 
321
 
 
322
        CompWindow::Geometry server = w->serverGeometry ();
 
323
 
 
324
        x = CompOption::getIntOptionNamed (options, "x", pointerX);
 
325
        y = CompOption::getIntOptionNamed (options, "y", pointerY);
 
326
 
 
327
        button = CompOption::getIntOptionNamed (options, "button", -1);
 
328
 
 
329
        mask = CompOption::getIntOptionNamed (options, "direction");
 
330
 
 
331
        /* Initiate the resize in the direction suggested by the
 
332
         * sector of the window the mouse is in, eg drag in top left
 
333
         * will resize up and to the left.  Keyboard resize starts out
 
334
         * with the cursor in the middle of the window and then starts
 
335
         * resizing the edge corresponding to the next key press. */
 
336
        if (state & CompAction::StateInitKey)
 
337
        {
 
338
            mask = 0;
 
339
        }
 
340
        else if (!mask)
 
341
        {
 
342
            int sectorSizeX = server.width () / 3;
 
343
            int sectorSizeY = server.height () / 3;
 
344
            int posX        = x - server.x ();
 
345
            int posY        = y - server.y ();
 
346
 
 
347
            if (posX < sectorSizeX)
 
348
                mask |= ResizeLeftMask;
 
349
            else if (posX > (2 * sectorSizeX))
 
350
                mask |= ResizeRightMask;
 
351
 
 
352
            if (posY < sectorSizeY)
 
353
                mask |= ResizeUpMask;
 
354
            else if (posY > (2 * sectorSizeY))
 
355
                mask |= ResizeDownMask;
 
356
 
 
357
            /* if the pointer was in the middle of the window,
 
358
               just prevent input to the window */
 
359
 
 
360
            if (!mask)
 
361
                return true;
 
362
        }
 
363
 
 
364
        if (screen->otherGrabExist ("resize", NULL))
 
365
            return false;
 
366
 
 
367
        if (rs->w)
 
368
            return false;
 
369
 
 
370
        if (w->type () & (CompWindowTypeDesktopMask |
 
371
                          CompWindowTypeDockMask         |
 
372
                          CompWindowTypeFullscreenMask))
 
373
            return false;
 
374
 
 
375
        if (w->overrideRedirect ())
 
376
            return false;
 
377
 
 
378
        if (state & CompAction::StateInitButton)
 
379
            action->setState (action->state () | CompAction::StateTermButton);
 
380
 
 
381
        if (w->shaded ())
 
382
            mask &= ~(ResizeUpMask | ResizeDownMask);
 
383
 
 
384
        rs->w    = w;
 
385
        rs->mask = mask;
 
386
 
 
387
        rs->savedGeometry.x      = server.x ();
 
388
        rs->savedGeometry.y      = server.y ();
 
389
        rs->savedGeometry.width  = server.width ();
 
390
        rs->savedGeometry.height = server.height ();
 
391
 
 
392
        rs->geometry = rs->savedGeometry;
 
393
 
 
394
        rs->pointerDx = x - pointerX;
 
395
        rs->pointerDy = y - pointerY;
 
396
 
 
397
        rs->centered =  rs->optionGetResizeFromCenterMatch ().evaluate (w);
 
398
 
 
399
        if ((w->state () & MAXIMIZE_STATE) == MAXIMIZE_STATE)
 
400
        {
 
401
            /* if the window is fully maximized, showing the outline or
 
402
               rectangle would be visually distracting as the window can't
 
403
               be resized anyway; so we better don't use them in this case */
 
404
            rs->mode = ResizeOptions::ModeNormal;
 
405
        }
 
406
        else if (!rs->gScreen || !rs->cScreen ||
 
407
                 !rs->cScreen->compositingActive ())
 
408
        {
 
409
            rs->mode = ResizeOptions::ModeNormal;
 
410
        }
 
411
        else
 
412
        {
 
413
            rs->mode = mode;
 
414
        }
 
415
 
 
416
        if (rs->mode != ResizeOptions::ModeNormal)
 
417
        {
 
418
            RESIZE_WINDOW (w);
 
419
            if (rw->gWindow && rs->mode == ResizeOptions::ModeStretch)
 
420
                rw->gWindow->glPaintSetEnabled (rw, true);
 
421
            if (rw->cWindow && rs->mode == ResizeOptions::ModeStretch)
 
422
                rw->cWindow->damageRectSetEnabled (rw, true);
 
423
            rs->gScreen->glPaintOutputSetEnabled (rs, true);
 
424
        }
 
425
 
 
426
        if (!rs->grabIndex)
 
427
        {
 
428
            Cursor cursor;
 
429
 
 
430
            if (state & CompAction::StateInitKey)
 
431
                cursor = rs->middleCursor;
 
432
            else
 
433
                cursor = rs->cursorFromResizeMask (mask);
 
434
 
 
435
            rs->grabIndex = screen->pushGrab (cursor, "resize");
 
436
        }
 
437
 
 
438
        if (rs->grabIndex)
 
439
        {
 
440
            BoxRec box;
 
441
            unsigned int grabMask = CompWindowGrabResizeMask |
 
442
                                    CompWindowGrabButtonMask;
 
443
            bool sourceExternalApp =
 
444
                CompOption::getBoolOptionNamed (options, "external", false);
 
445
 
 
446
            if (sourceExternalApp)
 
447
                grabMask |= CompWindowGrabExternalAppMask;
 
448
 
 
449
            rs->releaseButton = button;
 
450
 
 
451
            w->grabNotify (x, y, state, grabMask);
 
452
 
 
453
            if (screen->getOption ("raise_on_click")->value ().b ())
 
454
                w->updateAttributes (CompStackingUpdateModeAboveFullscreen);
 
455
 
 
456
            /* using the paint rectangle is enough here
 
457
               as we don't have any stretch yet */
 
458
            rs->getPaintRectangle (&box);
 
459
            rs->damageRectangle (&box);
 
460
 
 
461
            if (state & CompAction::StateInitKey)
 
462
            {
 
463
                int xRoot, yRoot;
 
464
 
 
465
                xRoot = server.x () + (server.width () / 2);
 
466
                yRoot = server.y () + (server.height () / 2);
 
467
 
 
468
                screen->warpPointer (xRoot - pointerX, yRoot - pointerY);
 
469
            }
 
470
 
 
471
            rs->isConstrained = sourceExternalApp;
 
472
 
 
473
            /* Update offWorkAreaConstrained and workArea at grab time */
 
474
            rs->offWorkAreaConstrained = false;
 
475
            if (sourceExternalApp)
 
476
            {
 
477
                int output = w->outputDevice ();
 
478
                int lco, tco, bco, rco;
 
479
                bool sl = screen->outputDevs ().at (output).workArea ().left () >
 
480
                          w->serverGeometry ().left ();
 
481
                bool sr = screen->outputDevs ().at (output).workArea ().right () <
 
482
                          w->serverGeometry ().right ();
 
483
                bool st = screen->outputDevs ().at (output).workArea ().top () >
 
484
                          w->serverGeometry ().top ();
 
485
                bool sb = screen->outputDevs ().at (output).workArea ().bottom () <
 
486
                          w->serverGeometry ().bottom ();
 
487
 
 
488
                lco = tco = bco = rco = output;
 
489
 
 
490
                /* Prevent resizing beyond work area edges when resize is
 
491
                   initiated externally (e.g. with window frame or menu)
 
492
                   and not with a key (e.g. alt+button) */
 
493
                rs->offWorkAreaConstrained = true;
 
494
 
 
495
                lco = getOutputForEdge (output, TOUCH_RIGHT, sl);
 
496
                rco = getOutputForEdge (output, TOUCH_LEFT, sr);
 
497
                tco = getOutputForEdge (output, TOUCH_BOTTOM, st);
 
498
                bco = getOutputForEdge (output, TOUCH_TOP, sb);
 
499
 
 
500
                /* Now we need to form one big rect which describes
 
501
                 * the available workarea */
 
502
 
 
503
                int left = screen->outputDevs ().at (lco).workArea ().left ();
 
504
                int right = screen->outputDevs ().at (rco).workArea ().right ();
 
505
                int top = screen->outputDevs ().at (tco).workArea ().top ();
 
506
                int bottom = screen->outputDevs ().at (bco).workArea ().bottom ();
 
507
 
 
508
                if (rs->grabWindowWorkArea)
 
509
                    delete rs->grabWindowWorkArea;
 
510
 
 
511
                rs->grabWindowWorkArea = new CompRect (0, 0, 0, 0);
 
512
                rs->grabWindowWorkArea->setLeft (left);
 
513
                rs->grabWindowWorkArea->setRight (right);
 
514
                rs->grabWindowWorkArea->setTop (top);
 
515
                rs->grabWindowWorkArea->setBottom (bottom);
 
516
 
 
517
 
 
518
                rs->inRegionStatus   = false;
 
519
                rs->lastGoodHotSpotY = -1;
 
520
                rs->lastGoodSize     = w->serverSize ();
 
521
 
 
522
                /* Combine the work areas of all outputs */
 
523
                rs->constraintRegion = emptyRegion;
 
524
                foreach (CompOutput &output, ::screen->outputDevs ())
 
525
                    rs->constraintRegion += output.workArea ();
 
526
            }
 
527
        }
 
528
    }
 
529
 
 
530
    return false;
 
531
}
 
532
 
 
533
static bool
 
534
resizeInitiateDefaultMode (CompAction         *action,
 
535
                           CompAction::State  state,
 
536
                           CompOption::Vector &options)
 
537
{
 
538
    CompWindow   *w;
 
539
    unsigned int mode;
 
540
 
 
541
    RESIZE_SCREEN (screen);
 
542
 
 
543
    w = screen->findWindow (CompOption::getIntOptionNamed (options, "window"));
 
544
    if (!w)
 
545
        return false;
 
546
 
 
547
    mode = rs->optionGetMode ();
 
548
 
 
549
    if (rs->optionGetNormalMatch ().evaluate (w))
 
550
        mode = ResizeOptions::ModeNormal;
 
551
    if (rs->optionGetOutlineMatch ().evaluate (w))
 
552
        mode = ResizeOptions::ModeOutline;
 
553
    if (rs->optionGetRectangleMatch ().evaluate (w))
 
554
        mode = ResizeOptions::ModeRectangle;
 
555
    if (rs->optionGetStretchMatch ().evaluate (w))
 
556
        mode = ResizeOptions::ModeStretch;
 
557
 
 
558
    return resizeInitiate (action, state, options, mode);
 
559
}
 
560
 
 
561
static bool
 
562
resizeTerminate (CompAction         *action,
 
563
                 CompAction::State  state,
 
564
                 CompOption::Vector &options)
 
565
{
 
566
    RESIZE_SCREEN (screen);
 
567
 
 
568
    if (rs->w)
 
569
    {
 
570
        CompWindow     *w = rs->w;
 
571
        XWindowChanges xwc;
 
572
        unsigned int   mask = 0;
 
573
 
 
574
        if (rs->mode == ResizeOptions::ModeNormal)
 
575
        {
 
576
            if (state & CompAction::StateCancel)
 
577
            {
 
578
                xwc.x      = rs->savedGeometry.x;
 
579
                xwc.y      = rs->savedGeometry.y;
 
580
                xwc.width  = rs->savedGeometry.width;
 
581
                xwc.height = rs->savedGeometry.height;
 
582
 
 
583
                mask = CWX | CWY | CWWidth | CWHeight;
 
584
            }
 
585
        }
 
586
        else
 
587
        {
 
588
            XRectangle geometry;
 
589
 
 
590
            if (state & CompAction::StateCancel)
 
591
                geometry = rs->savedGeometry;
 
592
            else
 
593
                geometry = rs->geometry;
 
594
 
 
595
            if (memcmp (&geometry, &rs->savedGeometry, sizeof (geometry)) == 0)
 
596
            {
 
597
                BoxRec box;
 
598
 
 
599
                if (rs->mode == ResizeOptions::ModeStretch)
 
600
                    rs->getStretchRectangle (&box);
 
601
                else
 
602
                    rs->getPaintRectangle (&box);
 
603
 
 
604
                rs->damageRectangle (&box);
 
605
            }
 
606
            else
 
607
            {
 
608
                xwc.x      = geometry.x;
 
609
                xwc.y      = geometry.y;
 
610
                xwc.width  = geometry.width;
 
611
                xwc.height = geometry.height;
 
612
 
 
613
                mask = CWX | CWY | CWWidth | CWHeight;
 
614
            }
 
615
 
 
616
            if (rs->mode != ResizeOptions::ModeNormal)
 
617
            {
 
618
                RESIZE_WINDOW (rs->w);
 
619
                if (rw->gWindow && rs->mode == ResizeOptions::ModeStretch)
 
620
                    rw->gWindow->glPaintSetEnabled (rw, false);
 
621
                if (rw->cWindow && rs->mode == ResizeOptions::ModeStretch)
 
622
                    rw->cWindow->damageRectSetEnabled (rw, false);
 
623
                rs->gScreen->glPaintOutputSetEnabled (rs, false);
 
624
            }
 
625
        }
 
626
 
 
627
        if ((mask & CWWidth) &&
 
628
            xwc.width == (int) w->serverGeometry ().width ())
 
629
            mask &= ~CWWidth;
 
630
 
 
631
        if ((mask & CWHeight) &&
 
632
            xwc.height == (int) w->serverGeometry ().height ())
 
633
            mask &= ~CWHeight;
 
634
 
 
635
        if (mask)
 
636
        {
 
637
            if (mask & (CWWidth | CWHeight))
 
638
                w->sendSyncRequest ();
 
639
 
 
640
            w->configureXWindow (mask, &xwc);
 
641
        }
 
642
 
 
643
        if (!(mask & (CWWidth | CWHeight)))
 
644
            rs->finishResizing ();
 
645
 
 
646
        if (rs->grabIndex)
 
647
        {
 
648
            screen->removeGrab (rs->grabIndex, NULL);
 
649
            rs->grabIndex = 0;
 
650
        }
 
651
 
 
652
        rs->releaseButton = 0;
 
653
    }
 
654
 
 
655
    action->setState (action->state () & ~(CompAction::StateTermKey |
 
656
                                           CompAction::StateTermButton));
 
657
 
 
658
    return false;
 
659
}
 
660
 
 
661
 
 
662
void
 
663
ResizeScreen::updateWindowSize ()
 
664
{
 
665
    if (w->syncWait ())
 
666
        return;
 
667
 
 
668
    if (w->serverGeometry ().width ()  != geometry.width ||
 
669
        w->serverGeometry ().height () != geometry.height)
 
670
    {
 
671
        XWindowChanges xwc;
 
672
 
 
673
        xwc.x      = geometry.x;
 
674
        xwc.y      = geometry.y;
 
675
        xwc.width  = geometry.width;
 
676
        xwc.height = geometry.height;
 
677
 
 
678
        w->sendSyncRequest ();
 
679
 
 
680
        w->configureXWindow (CWX | CWY | CWWidth | CWHeight, &xwc);
 
681
    }
 
682
}
 
683
 
 
684
void
 
685
ResizeScreen::handleKeyEvent (KeyCode keycode)
 
686
{
 
687
    if (grabIndex && w)
 
688
    {
 
689
        int        widthInc, heightInc;
 
690
 
 
691
        widthInc  = w->sizeHints ().width_inc;
 
692
        heightInc = w->sizeHints ().height_inc;
 
693
 
 
694
        if (widthInc < MIN_KEY_WIDTH_INC)
 
695
            widthInc = MIN_KEY_WIDTH_INC;
 
696
 
 
697
        if (heightInc < MIN_KEY_HEIGHT_INC)
 
698
            heightInc = MIN_KEY_HEIGHT_INC;
 
699
 
 
700
        for (unsigned int i = 0; i < NUM_KEYS; i++)
 
701
        {
 
702
            if (keycode != key[i])
 
703
                continue;
 
704
 
 
705
            if (mask & rKeys[i].warpMask)
 
706
            {
 
707
                XWarpPointer (screen->dpy (), None, None, 0, 0, 0, 0,
 
708
                              rKeys[i].dx * widthInc, rKeys[i].dy * heightInc);
 
709
            }
 
710
            else
 
711
            {
 
712
                int x, y, left, top, width, height;
 
713
 
 
714
                CompWindow::Geometry server = w->serverGeometry ();
 
715
                const CompWindowExtents    &border  = w->border ();
 
716
 
 
717
                left   = server.x () - border.left;
 
718
                top    = server.y () - border.top;
 
719
                width  = border.left + server.width () + border.right;
 
720
                height = border.top  + server.height () + border.bottom;
 
721
 
 
722
                x = left + width  * (rKeys[i].dx + 1) / 2;
 
723
                y = top  + height * (rKeys[i].dy + 1) / 2;
 
724
 
 
725
                screen->warpPointer (x - pointerX, y - pointerY);
 
726
 
 
727
                mask = rKeys[i].resizeMask;
 
728
 
 
729
                screen->updateGrab (grabIndex, cursor[i]);
 
730
            }
 
731
            break;
 
732
        }
 
733
    }
 
734
}
 
735
 
 
736
void
 
737
ResizeScreen::handleMotionEvent (int xRoot, int yRoot)
 
738
{
 
739
    if (grabIndex)
 
740
    {
 
741
        BoxRec box;
 
742
        int    wi, he, cwi, che;        /* size of window contents (c prefix for constrained)*/
 
743
        int    wX, wY, wWidth, wHeight; /* rect. for window contents+borders */
 
744
        int    workAreaSnapDistance = 15;
 
745
 
 
746
        wi = savedGeometry.width;
 
747
        he = savedGeometry.height;
 
748
 
 
749
        if (!mask)
 
750
        {
 
751
            int        xDist, yDist;
 
752
            int        minPointerOffsetX, minPointerOffsetY;
 
753
 
 
754
            CompWindow::Geometry server = w->serverGeometry ();
 
755
 
 
756
            xDist = xRoot - (server.x () + (server.width () / 2));
 
757
            yDist = yRoot - (server.y () + (server.height () / 2));
 
758
 
 
759
            /* decision threshold is 10% of window size */
 
760
            minPointerOffsetX = MIN (20, server.width () / 10);
 
761
            minPointerOffsetY = MIN (20, server.height () / 10);
 
762
 
 
763
            /* if we reached the threshold in one direction,
 
764
               make the threshold in the other direction smaller
 
765
               so there is a chance that this threshold also can
 
766
               be reached (by diagonal movement) */
 
767
            if (abs (xDist) > minPointerOffsetX)
 
768
                minPointerOffsetY /= 2;
 
769
            else if (abs (yDist) > minPointerOffsetY)
 
770
                minPointerOffsetX /= 2;
 
771
 
 
772
            if (abs (xDist) > minPointerOffsetX)
 
773
            {
 
774
                if (xDist > 0)
 
775
                    mask |= ResizeRightMask;
 
776
                else
 
777
                    mask |= ResizeLeftMask;
 
778
            }
 
779
 
 
780
            if (abs (yDist) > minPointerOffsetY)
 
781
            {
 
782
                if (yDist > 0)
 
783
                    mask |= ResizeDownMask;
 
784
                else
 
785
                    mask |= ResizeUpMask;
 
786
            }
 
787
 
 
788
            /* if the pointer movement was enough to determine a
 
789
               direction, warp the pointer to the appropriate edge
 
790
               and set the right cursor */
 
791
            if (mask)
 
792
            {
 
793
                Cursor     cursor;
 
794
                CompAction *action;
 
795
                int        pointerAdjustX = 0;
 
796
                int        pointerAdjustY = 0;
 
797
 
 
798
                action = &optionGetInitiateKey ();
 
799
                action->setState (action->state () |
 
800
                                  CompAction::StateTermButton);
 
801
 
 
802
                if (mask & ResizeRightMask)
 
803
                        pointerAdjustX = server.x () + server.width () +
 
804
                                         w->border ().right - xRoot;
 
805
                else if (mask & ResizeLeftMask)
 
806
                        pointerAdjustX = server.x () - w->border ().left -
 
807
                                         xRoot;
 
808
 
 
809
                if (mask & ResizeDownMask)
 
810
                        pointerAdjustY = server.y () + server.height () +
 
811
                                         w->border ().bottom - yRoot;
 
812
                else if (mask & ResizeUpMask)
 
813
                        pointerAdjustY = server.y () - w->border ().top - yRoot;
 
814
 
 
815
                screen->warpPointer (pointerAdjustX, pointerAdjustY);
 
816
 
 
817
                cursor = cursorFromResizeMask (mask);
 
818
                screen->updateGrab (grabIndex, cursor);
 
819
            }
 
820
        }
 
821
        else
 
822
        {
 
823
            /* only accumulate pointer movement if a mask is
 
824
               already set as we don't have a use for the
 
825
               difference information otherwise */
 
826
 
 
827
            if (centered)
 
828
            {
 
829
                pointerDx += (xRoot - lastPointerX) * 2;
 
830
                pointerDy += (yRoot - lastPointerY) * 2;
 
831
            }
 
832
            else
 
833
            {
 
834
                pointerDx += xRoot - lastPointerX;
 
835
                pointerDy += yRoot - lastPointerY;
 
836
            }
 
837
            
 
838
            /* If we hit the edge of the screen while resizing
 
839
             * the window and the adjacent window edge has not hit
 
840
             * the edge of the screen, then accumulate pointer motion
 
841
             * in the opposite direction. (So the apparant x / y
 
842
             * mixup here is intentional)
 
843
             */
 
844
 
 
845
            if (isConstrained)
 
846
            {
 
847
                if (mask == ResizeLeftMask)
 
848
                {
 
849
                    if (xRoot == 0 &&
 
850
                        geometry.x - w->border ().left > grabWindowWorkArea->left ())
 
851
                        pointerDx += abs (yRoot - lastPointerY) * -1;
 
852
                }
 
853
                else if (mask == ResizeRightMask)
 
854
                {
 
855
                    if (xRoot == screen->width () -1 &&
 
856
                        geometry.x + geometry.width + w->border ().right < grabWindowWorkArea->right ())
 
857
                        pointerDx += abs (yRoot - lastPointerY);
 
858
                }
 
859
                if (mask == ResizeUpMask)
 
860
                {
 
861
                    if (yRoot == 0 &&
 
862
                        geometry.y - w->border ().top > grabWindowWorkArea->top ())
 
863
                        pointerDy += abs (xRoot - lastPointerX) * -1;
 
864
                }
 
865
                else if (mask == ResizeDownMask)
 
866
                {
 
867
                    if (yRoot == screen->height () -1 &&
 
868
                        geometry.y + geometry.height + w->border ().bottom < grabWindowWorkArea->bottom ())
 
869
                        pointerDx += abs (yRoot - lastPointerY);
 
870
                }
 
871
            }
 
872
        }
 
873
 
 
874
        if (mask & ResizeLeftMask)
 
875
            wi -= pointerDx;
 
876
        else if (mask & ResizeRightMask)
 
877
            wi += pointerDx;
 
878
 
 
879
        if (mask & ResizeUpMask)
 
880
            he -= pointerDy;
 
881
        else if (mask & ResizeDownMask)
 
882
            he += pointerDy;
 
883
 
 
884
        if (w->state () & CompWindowStateMaximizedVertMask)
 
885
            he = w->serverGeometry ().height ();
 
886
 
 
887
        if (w->state () & CompWindowStateMaximizedHorzMask)
 
888
            wi = w->serverGeometry ().width ();
 
889
 
 
890
        cwi = wi;
 
891
        che = he;
 
892
 
 
893
        if (w->constrainNewWindowSize (wi, he, &cwi, &che))
 
894
        {
 
895
            Box box;
 
896
 
 
897
            /* Also, damage relevant paint rectangles */
 
898
            if (mode == ResizeOptions::ModeRectangle ||
 
899
                mode == ResizeOptions::ModeOutline)
 
900
                getPaintRectangle (&box);
 
901
            else if (mode == ResizeOptions::ModeStretch)
 
902
                getStretchRectangle (&box);
 
903
 
 
904
            damageRectangle (&box);
 
905
        }
 
906
 
 
907
        /* constrain to work area */
 
908
        if (offWorkAreaConstrained)
 
909
        {
 
910
            if (mask & ResizeUpMask)
 
911
            {
 
912
                int decorTop = savedGeometry.y + savedGeometry.height -
 
913
                    (che + w->border ().top);
 
914
 
 
915
                if (grabWindowWorkArea->y () > decorTop)
 
916
                    che -= grabWindowWorkArea->y () - decorTop;
 
917
            }
 
918
            if (mask & ResizeDownMask)
 
919
            {
 
920
                int decorBottom = savedGeometry.y + che + w->border ().bottom;
 
921
 
 
922
                if (decorBottom >
 
923
                    grabWindowWorkArea->y () + grabWindowWorkArea->height ())
 
924
                    che -= decorBottom - (grabWindowWorkArea->y () +
 
925
                                          grabWindowWorkArea->height ());
 
926
            }
 
927
            if (mask & ResizeLeftMask)
 
928
            {
 
929
                int decorLeft = savedGeometry.x + savedGeometry.width -
 
930
                    (cwi + w->border ().left);
 
931
 
 
932
                if (grabWindowWorkArea->x () > decorLeft)
 
933
                    cwi -= grabWindowWorkArea->x () - decorLeft;
 
934
            }
 
935
            if (mask & ResizeRightMask)
 
936
            {
 
937
                int decorRight = savedGeometry.x + cwi + w->border ().right;
 
938
 
 
939
                if (decorRight >
 
940
                    grabWindowWorkArea->x () + grabWindowWorkArea->width ())
 
941
                    cwi -= decorRight - (grabWindowWorkArea->x () +
 
942
                                         grabWindowWorkArea->width ());
 
943
            }
 
944
        }
 
945
 
 
946
        wi = cwi;
 
947
        he = che;
 
948
 
 
949
        /* compute rect. for window + borders */
 
950
        wWidth  = wi + w->border ().left + w->border ().right;
 
951
        wHeight = he + w->border ().top + w->border ().bottom;
 
952
 
 
953
        if (centered)
 
954
        {
 
955
            if (mask & ResizeLeftMask)
 
956
                wX = geometry.x + geometry.width -
 
957
                     (wi + w->border ().left);
 
958
            else
 
959
                wX = geometry.x - w->border ().left;
 
960
 
 
961
            if (mask & ResizeUpMask)
 
962
                wY = geometry.y + geometry.height -
 
963
                     (he + w->border ().top);
 
964
            else
 
965
                wY = geometry.y - w->border ().top;
 
966
        }
 
967
        else
 
968
        {
 
969
            if (mask & ResizeLeftMask)
 
970
                wX = savedGeometry.x + savedGeometry.width -
 
971
                     (wi + w->border ().left);
 
972
            else
 
973
                wX = savedGeometry.x - w->border ().left;
 
974
 
 
975
            if (mask & ResizeUpMask)
 
976
                wY = savedGeometry.y + savedGeometry.height -
 
977
                     (he + w->border ().top);
 
978
            else
 
979
                wY = savedGeometry.y - w->border ().top;
 
980
        }
 
981
 
 
982
        /* Check if resized edge(s) are near output work-area boundaries */
 
983
        foreach (CompOutput &output, ::screen->outputDevs ())
 
984
        {
 
985
            const CompRect &workArea = output.workArea ();
 
986
 
 
987
            /* if window and work-area intersect in x axis */
 
988
            if (wX + wWidth > workArea.x () &&
 
989
                wX < workArea.x2 ())
 
990
            {
 
991
                if (mask & ResizeLeftMask)
 
992
                {
 
993
                    int dw = workArea.x () - wX;
 
994
 
 
995
                    if (0 < dw && dw < workAreaSnapDistance)
 
996
                    {
 
997
                        wi     -= dw;
 
998
                        wWidth -= dw;
 
999
                        wX     += dw;
 
1000
                    }
 
1001
                }
 
1002
                else if (mask & ResizeRightMask)
 
1003
                {
 
1004
                    int dw = wX + wWidth - workArea.x2 ();
 
1005
 
 
1006
                    if (0 < dw && dw < workAreaSnapDistance)
 
1007
                    {
 
1008
                        wi     -= dw;
 
1009
                        wWidth -= dw;
 
1010
                    }
 
1011
                }
 
1012
            }
 
1013
 
 
1014
            /* if window and work-area intersect in y axis */
 
1015
            if (wY + wHeight > workArea.y () &&
 
1016
                wY < workArea.y2 ())
 
1017
            {
 
1018
                if (mask & ResizeUpMask)
 
1019
                {
 
1020
                    int dh = workArea.y () - wY;
 
1021
 
 
1022
                    if (0 < dh && dh < workAreaSnapDistance)
 
1023
                    {
 
1024
                        he      -= dh;
 
1025
                        wHeight -= dh;
 
1026
                        wY      += dh;
 
1027
                    }
 
1028
                }
 
1029
                else if (mask & ResizeDownMask)
 
1030
                {
 
1031
                    int dh = wY + wHeight - workArea.y2 ();
 
1032
 
 
1033
                    if (0 < dh && dh < workAreaSnapDistance)
 
1034
                    {
 
1035
                        he      -= dh;
 
1036
                        wHeight -= dh;
 
1037
                    }
 
1038
                }
 
1039
            }
 
1040
        }
 
1041
 
 
1042
        if (isConstrained)
 
1043
        {
 
1044
            int minWidth  = 50;
 
1045
            int minHeight = 50;
 
1046
 
 
1047
            /* rect. for a minimal height window + borders
 
1048
               (used for the constraining in X axis) */
 
1049
            int minimalInputHeight = minHeight +
 
1050
                                     w->border ().top + w->border ().bottom;
 
1051
 
 
1052
            /* small hot-spot square (on window's corner or edge) that is to be
 
1053
               constrained to the combined output work-area region */
 
1054
            int x, y;
 
1055
            int width = w->border ().top; /* square size = title bar height */
 
1056
            int height = width;
 
1057
            bool status; /* whether or not hot-spot is in the region */
 
1058
 
 
1059
            /* compute x & y for constrained hot-spot rect */
 
1060
            if (mask & ResizeLeftMask)
 
1061
                x = wX;
 
1062
            else if (mask & ResizeRightMask)
 
1063
                x = wX + wWidth - width;
 
1064
            else
 
1065
                x = MIN (MAX (xRoot, wX), wX + wWidth - width);
 
1066
 
 
1067
            if (mask & ResizeUpMask)
 
1068
                y = wY;
 
1069
            else if (mask & ResizeDownMask)
 
1070
                y = wY + wHeight - height;
 
1071
            else
 
1072
                y = MIN (MAX (yRoot, wY), wY + wHeight - height);
 
1073
 
 
1074
            status = constraintRegion.contains (x, y, width, height);
 
1075
 
 
1076
            /* only constrain movement if previous position was valid */
 
1077
            if (inRegionStatus)
 
1078
            {
 
1079
                bool xStatus = false;
 
1080
                int yForXResize = y;
 
1081
                int nx = x;
 
1082
                int nw = wi;
 
1083
                int nh = he;
 
1084
 
 
1085
                if (mask & (ResizeLeftMask | ResizeRightMask))
 
1086
                {
 
1087
                    xStatus = status;
 
1088
 
 
1089
                    if (mask & ResizeUpMask)
 
1090
                        yForXResize = wY + wHeight - minimalInputHeight;
 
1091
                    else if (mask & ResizeDownMask)
 
1092
                        yForXResize = wY + minimalInputHeight - height;
 
1093
                    else
 
1094
                        yForXResize = y;
 
1095
 
 
1096
                    if (!constraintRegion.contains (x, yForXResize,
 
1097
                                                    width, height))
 
1098
                    {
 
1099
                        if (lastGoodHotSpotY >= 0)
 
1100
                            yForXResize = lastGoodHotSpotY;
 
1101
                        else
 
1102
                            yForXResize = y;
 
1103
                    }
 
1104
                }
 
1105
                if (mask & ResizeLeftMask)
 
1106
                {
 
1107
                    while ((nw > minWidth) && !xStatus)
 
1108
                    {
 
1109
                        xStatus = constraintRegion.contains (nx, yForXResize,
 
1110
                                                             width, height);
 
1111
                        if (!xStatus)
 
1112
                        {
 
1113
                            nw--;
 
1114
                            nx++;
 
1115
                        }
 
1116
                    }
 
1117
                    if (nw > minWidth)
 
1118
                    {
 
1119
                        x = nx;
 
1120
                        wi = nw;
 
1121
                    }
 
1122
                }
 
1123
                else if (mask & ResizeRightMask)
 
1124
                {
 
1125
                    while ((nw > minWidth) && !xStatus)
 
1126
                    {
 
1127
                        xStatus = constraintRegion.contains (nx, yForXResize,
 
1128
                                                             width, height);
 
1129
                        if (!xStatus)
 
1130
                        {
 
1131
                            nw--;
 
1132
                            nx--;
 
1133
                        }
 
1134
                    }
 
1135
                    if (nw > minWidth)
 
1136
                    {
 
1137
                        x = nx;
 
1138
                        wi = nw;
 
1139
                    }
 
1140
                }
 
1141
 
 
1142
                if (mask & ResizeUpMask)
 
1143
                {
 
1144
                    while ((nh > minHeight) && !status)
 
1145
                    {
 
1146
                        status = constraintRegion.contains (x, y,
 
1147
                                                            width, height);
 
1148
                        if (!status)
 
1149
                        {
 
1150
                            nh--;
 
1151
                            y++;
 
1152
                        }
 
1153
                    }
 
1154
                    if (nh > minHeight)
 
1155
                        he = nh;
 
1156
                }
 
1157
                else if (mask & ResizeDownMask)
 
1158
                {
 
1159
                    while ((nh > minHeight) && !status)
 
1160
                    {
 
1161
                        status = constraintRegion.contains (x, y,
 
1162
                                                            width, height);
 
1163
                        if (!status)
 
1164
                        {
 
1165
                            nh--;
 
1166
                            y--;
 
1167
                        }
 
1168
                    }
 
1169
                    if (nh > minHeight)
 
1170
                        he = nh;
 
1171
                }
 
1172
 
 
1173
                if (((mask & (ResizeLeftMask | ResizeRightMask)) && xStatus) ||
 
1174
                    ((mask & (ResizeUpMask | ResizeDownMask)) && status))
 
1175
                {
 
1176
                    /* hot-spot inside work-area region, store good values */
 
1177
                    lastGoodHotSpotY = y;
 
1178
                    lastGoodSize     = CompSize (wi, he);
 
1179
                }
 
1180
                else
 
1181
                {
 
1182
                    /* failed to find a good hot-spot position, restore size */
 
1183
                    wi = lastGoodSize.width ();
 
1184
                    he = lastGoodSize.height ();
 
1185
                }
 
1186
            }
 
1187
            else
 
1188
            {
 
1189
                inRegionStatus = status;
 
1190
            }
 
1191
        }
 
1192
 
 
1193
        if (mode != ResizeOptions::ModeNormal)
 
1194
        {
 
1195
            if (mode == ResizeOptions::ModeStretch)
 
1196
                getStretchRectangle (&box);
 
1197
            else
 
1198
                getPaintRectangle (&box);
 
1199
 
 
1200
            damageRectangle (&box);
 
1201
        }
 
1202
 
 
1203
        if (centered)
 
1204
        {
 
1205
            if ((mask & ResizeLeftMask) || (mask & ResizeRightMask))
 
1206
                geometry.x -= ((wi - geometry.width) / 2);
 
1207
            if ((mask & ResizeUpMask) || (mask & ResizeDownMask))
 
1208
                geometry.y -= ((he - geometry.height) / 2);
 
1209
        }
 
1210
        else
 
1211
        {
 
1212
            if (mask & ResizeLeftMask)
 
1213
                geometry.x -= wi - geometry.width;
 
1214
            if (mask & ResizeUpMask)
 
1215
                geometry.y -= he - geometry.height;
 
1216
        }
 
1217
 
 
1218
        geometry.width  = wi;
 
1219
        geometry.height = he;
 
1220
 
 
1221
        if (mode != ResizeOptions::ModeNormal)
 
1222
        {
 
1223
            if (mode == ResizeOptions::ModeStretch)
 
1224
                getStretchRectangle (&box);
 
1225
            else
 
1226
                getPaintRectangle (&box);
 
1227
 
 
1228
            damageRectangle (&box);
 
1229
        }
 
1230
        else
 
1231
        {
 
1232
            updateWindowSize ();
 
1233
        }
 
1234
 
 
1235
        updateWindowProperty ();
 
1236
        sendResizeNotify ();
 
1237
    }
 
1238
}
 
1239
 
 
1240
void
 
1241
ResizeScreen::handleEvent (XEvent *event)
 
1242
{
 
1243
    switch (event->type) {
 
1244
        case KeyPress:
 
1245
            if (event->xkey.root == screen->root ())
 
1246
                handleKeyEvent (event->xkey.keycode);
 
1247
            break;
 
1248
        case ButtonRelease:
 
1249
            if (event->xbutton.root == screen->root ())
 
1250
            {
 
1251
                if (grabIndex)
 
1252
                {
 
1253
                    if (releaseButton         == -1 ||
 
1254
                        (int) event->xbutton.button == releaseButton)
 
1255
                    {
 
1256
                        CompAction *action = &optionGetInitiateButton ();
 
1257
 
 
1258
                        resizeTerminate (action, CompAction::StateTermButton,
 
1259
                                         noOptions);
 
1260
                    }
 
1261
                }
 
1262
            }
 
1263
            break;
 
1264
        case MotionNotify:
 
1265
            if (event->xmotion.root == screen->root ())
 
1266
                handleMotionEvent (pointerX, pointerY);
 
1267
            break;
 
1268
        case EnterNotify:
 
1269
        case LeaveNotify:
 
1270
            if (event->xcrossing.root == screen->root ())
 
1271
                handleMotionEvent (pointerX, pointerY);
 
1272
            break;
 
1273
        case ClientMessage:
 
1274
            if (event->xclient.message_type == Atoms::wmMoveResize)
 
1275
            {
 
1276
                CompWindow    *w;
 
1277
                unsigned long type = event->xclient.data.l[2];
 
1278
 
 
1279
                RESIZE_SCREEN (screen);
 
1280
 
 
1281
                if (type <= WmMoveResizeSizeLeft ||
 
1282
                    type == WmMoveResizeSizeKeyboard)
 
1283
                {
 
1284
                    w = screen->findWindow (event->xclient.window);
 
1285
                    if (w)
 
1286
                    {
 
1287
                        CompOption::Vector o (0);
 
1288
 
 
1289
                        o.push_back (CompOption ("window",
 
1290
                                     CompOption::TypeInt));
 
1291
                        o[0].value ().set ((int) event->xclient.window);
 
1292
 
 
1293
                        o.push_back (CompOption ("external",
 
1294
                                     CompOption::TypeBool));
 
1295
                        o[1].value ().set (true);
 
1296
 
 
1297
                        if (event->xclient.data.l[2] == WmMoveResizeSizeKeyboard)
 
1298
                        {
 
1299
                            resizeInitiateDefaultMode (&optionGetInitiateKey (),
 
1300
                                                       CompAction::StateInitKey,
 
1301
                                                       o);
 
1302
                        }
 
1303
                        else
 
1304
                        {
 
1305
                            static unsigned int mask[] = {
 
1306
                                ResizeUpMask | ResizeLeftMask,
 
1307
                                ResizeUpMask,
 
1308
                                ResizeUpMask | ResizeRightMask,
 
1309
                                ResizeRightMask,
 
1310
                                ResizeDownMask | ResizeRightMask,
 
1311
                                ResizeDownMask,
 
1312
                                ResizeDownMask | ResizeLeftMask,
 
1313
                                ResizeLeftMask,
 
1314
                            };
 
1315
 
 
1316
                            /* TODO: not only button 1 */
 
1317
                            if (pointerMods & Button1Mask)
 
1318
                            {
 
1319
                                o.push_back (CompOption ("modifiers",
 
1320
                                             CompOption::TypeInt));
 
1321
                                o.push_back (CompOption ("x",
 
1322
                                             CompOption::TypeInt));
 
1323
                                o.push_back (CompOption ("y",
 
1324
                                             CompOption::TypeInt));
 
1325
                                o.push_back (CompOption ("direction",
 
1326
                                             CompOption::TypeInt));
 
1327
                                o.push_back (CompOption ("button",
 
1328
                                             CompOption::TypeInt));
 
1329
 
 
1330
                                o[2].value ().set ((int) pointerMods);
 
1331
                                o[3].value ().set
 
1332
                                    ((int) event->xclient.data.l[0]);
 
1333
                                o[4].value ().set
 
1334
                                    ((int) event->xclient.data.l[1]);
 
1335
                                o[5].value ().set
 
1336
                                    ((int) mask[event->xclient.data.l[2]]);
 
1337
                                o[6].value ().set
 
1338
                                    ((int) (event->xclient.data.l[3] ?
 
1339
                                     event->xclient.data.l[3] : -1));
 
1340
 
 
1341
                                resizeInitiateDefaultMode (
 
1342
                                    &optionGetInitiateButton (),
 
1343
                                    CompAction::StateInitButton, o);
 
1344
 
 
1345
                                ResizeScreen::get (screen)->
 
1346
                                    handleMotionEvent (pointerX, pointerY);
 
1347
                            }
 
1348
                        }
 
1349
                    }
 
1350
                }
 
1351
                else if (rs->w && type == WmMoveResizeCancel)
 
1352
                {
 
1353
                    if (rs->w->id () == event->xclient.window)
 
1354
                    {
 
1355
                        resizeTerminate (&optionGetInitiateButton (),
 
1356
                                         CompAction::StateCancel, noOptions);
 
1357
                        resizeTerminate (&optionGetInitiateKey (),
 
1358
                                         CompAction::StateCancel, noOptions);
 
1359
                    }
 
1360
                }
 
1361
            }
 
1362
            break;
 
1363
        case DestroyNotify:
 
1364
            if (w && w->id () == event->xdestroywindow.window)
 
1365
            {
 
1366
                resizeTerminate (&optionGetInitiateButton (), 0, noOptions);
 
1367
                resizeTerminate (&optionGetInitiateKey (), 0, noOptions);
 
1368
            }
 
1369
            break;
 
1370
        case UnmapNotify:
 
1371
            if (w && w->id () == event->xunmap.window)
 
1372
            {
 
1373
                resizeTerminate (&optionGetInitiateButton (), 0, noOptions);
 
1374
                resizeTerminate (&optionGetInitiateKey (), 0, noOptions);
 
1375
            }
 
1376
        default:
 
1377
            break;
 
1378
    }
 
1379
 
 
1380
    if (event->type == screen->xkbEvent () && w)
 
1381
    {
 
1382
        XkbAnyEvent *xkbEvent = (XkbAnyEvent *) event;
 
1383
 
 
1384
        if (xkbEvent->xkb_type == XkbStateNotify)
 
1385
        {
 
1386
            XkbStateNotifyEvent *stateEvent = (XkbStateNotifyEvent *) event;
 
1387
 
 
1388
            /* Check if we need to change to outline mode */
 
1389
 
 
1390
            unsigned int mods = 0xffffffff;
 
1391
            bool         modifierMode = false;
 
1392
            int          oldMode = mode;
 
1393
            if (outlineMask)
 
1394
                mods = outlineMask;
 
1395
 
 
1396
            if ((stateEvent->mods & mods) == mods)
 
1397
            {
 
1398
                modifierMode = true;
 
1399
                mode = ResizeOptions::ModeOutline;
 
1400
            }
 
1401
 
 
1402
            mods = 0xffffffff;
 
1403
            if (rectangleMask)
 
1404
                mods = rectangleMask;
 
1405
 
 
1406
            if ((stateEvent->mods & mods) == mods)
 
1407
            {
 
1408
                modifierMode = true;
 
1409
                mode = ResizeOptions::ModeRectangle;
 
1410
            }
 
1411
 
 
1412
            mods = 0xffffffff;
 
1413
            if (stretchMask)
 
1414
                mods = stretchMask;
 
1415
 
 
1416
            if ((stateEvent->mods & mods) == mods)
 
1417
            {
 
1418
                modifierMode = true;
 
1419
                mode = ResizeOptions::ModeStretch;
 
1420
            }
 
1421
 
 
1422
            mods = 0xffffffff;
 
1423
            if (centeredMask)
 
1424
                mods = centeredMask;
 
1425
 
 
1426
            if (!modifierMode)
 
1427
                mode = optionGetMode ();
 
1428
 
 
1429
            if (oldMode != mode)
 
1430
            {
 
1431
                Box box;
 
1432
 
 
1433
                getStretchRectangle (&box);
 
1434
                damageRectangle (&box);
 
1435
                getPaintRectangle (&box);
 
1436
                damageRectangle (&box);
 
1437
 
 
1438
                box.x1 = w->outputRect ().x ();
 
1439
                box.y1 = w->outputRect ().y ();
 
1440
                box.x2 = box.x1 + w->outputRect ().width ();
 
1441
                box.y2 = box.y1 + w->outputRect ().height ();
 
1442
 
 
1443
                damageRectangle (&box);
 
1444
            }
 
1445
 
 
1446
            if ((stateEvent->mods & mods) == mods)
 
1447
                centered = true;
 
1448
            else if ((w &&
 
1449
                      !optionGetResizeFromCenterMatch ().evaluate (w)))
 
1450
                centered = false;
 
1451
        }
 
1452
    }
 
1453
 
 
1454
    screen->handleEvent (event);
 
1455
 
 
1456
    if (event->type == screen->syncEvent () + XSyncAlarmNotify)
 
1457
    {
 
1458
        if (w)
 
1459
        {
 
1460
            XSyncAlarmNotifyEvent *sa;
 
1461
 
 
1462
            sa = (XSyncAlarmNotifyEvent *) event;
 
1463
 
 
1464
            if (w->syncAlarm () == sa->alarm)
 
1465
                updateWindowSize ();
 
1466
        }
 
1467
    }
 
1468
}
 
1469
 
 
1470
void
 
1471
ResizeWindow::resizeNotify (int dx, int dy, int dwidth, int dheight)
 
1472
{
 
1473
    window->resizeNotify (dx, dy, dwidth, dheight);
 
1474
 
 
1475
    if (rScreen->w == window && !rScreen->grabIndex)
 
1476
        rScreen->finishResizing ();
 
1477
}
 
1478
 
 
1479
void
 
1480
ResizeScreen::glPaintRectangle (const GLScreenPaintAttrib &sAttrib,
 
1481
                                const GLMatrix            &transform,
 
1482
                                CompOutput                *output,
 
1483
                                unsigned short            *borderColor,
 
1484
                                unsigned short            *fillColor)
 
1485
{
 
1486
    BoxRec   box;
 
1487
    GLMatrix sTransform (transform);
 
1488
 
 
1489
    getPaintRectangle (&box);
 
1490
 
 
1491
    glPushMatrix ();
 
1492
 
 
1493
    sTransform.toScreenSpace (output, -DEFAULT_Z_CAMERA);
 
1494
 
 
1495
    glLoadMatrixf (sTransform.getMatrix ());
 
1496
 
 
1497
    glDisableClientState (GL_TEXTURE_COORD_ARRAY);
 
1498
    glEnable (GL_BLEND);
 
1499
 
 
1500
    /* fill rectangle */
 
1501
    if (fillColor)
 
1502
    {
 
1503
        glColor4usv (fillColor);
 
1504
        glRecti (box.x1, box.y2, box.x2, box.y1);
 
1505
    }
 
1506
 
 
1507
    /* draw outline */
 
1508
    glColor4usv (borderColor);
 
1509
    glLineWidth (2.0);
 
1510
    glBegin (GL_LINE_LOOP);
 
1511
    glVertex2i (box.x1, box.y1);
 
1512
    glVertex2i (box.x2, box.y1);
 
1513
    glVertex2i (box.x2, box.y2);
 
1514
    glVertex2i (box.x1, box.y2);
 
1515
    glEnd ();
 
1516
 
 
1517
    /* clean up */
 
1518
    glColor4usv (defaultColor);
 
1519
    glDisable (GL_BLEND);
 
1520
    glEnableClientState (GL_TEXTURE_COORD_ARRAY);
 
1521
    glPopMatrix ();
 
1522
}
 
1523
 
 
1524
bool
 
1525
ResizeScreen::glPaintOutput (const GLScreenPaintAttrib &sAttrib,
 
1526
                             const GLMatrix            &transform,
 
1527
                             const CompRegion          &region,
 
1528
                             CompOutput                *output,
 
1529
                             unsigned int              mask)
 
1530
{
 
1531
    bool status;
 
1532
 
 
1533
    if (w)
 
1534
    {
 
1535
        if (mode == ResizeOptions::ModeStretch)
 
1536
            mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS_MASK;
 
1537
    }
 
1538
 
 
1539
    status = gScreen->glPaintOutput (sAttrib, transform, region, output, mask);
 
1540
 
 
1541
    if (status && w)
 
1542
    {
 
1543
        unsigned short *border, *fill;
 
1544
 
 
1545
        border = optionGetBorderColor ();
 
1546
        fill   = optionGetFillColor ();
 
1547
 
 
1548
        switch (mode) {
 
1549
            case ResizeOptions::ModeOutline:
 
1550
                glPaintRectangle (sAttrib, transform, output, border, NULL);
 
1551
                break;
 
1552
            case ResizeOptions::ModeRectangle:
 
1553
                glPaintRectangle (sAttrib, transform, output, border, fill);
 
1554
            default:
 
1555
                break;
 
1556
        }
 
1557
    }
 
1558
 
 
1559
    return status;
 
1560
}
 
1561
 
 
1562
bool
 
1563
ResizeWindow::glPaint (const GLWindowPaintAttrib &attrib,
 
1564
                       const GLMatrix            &transform,
 
1565
                       const CompRegion          &region,
 
1566
                       unsigned int              mask)
 
1567
{
 
1568
    bool       status;
 
1569
 
 
1570
    if (window == rScreen->w && rScreen->mode == ResizeOptions::ModeStretch)
 
1571
    {
 
1572
        GLMatrix       wTransform (transform);
 
1573
        BoxRec         box;
 
1574
        float          xOrigin, yOrigin;
 
1575
        float          xScale, yScale;
 
1576
        int            x, y;
 
1577
 
 
1578
        if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK)
 
1579
            return false;
 
1580
 
 
1581
        status = gWindow->glPaint (attrib, transform, region,
 
1582
                                   mask | PAINT_WINDOW_NO_CORE_INSTANCE_MASK);
 
1583
 
 
1584
        GLFragment::Attrib fragment (gWindow->lastPaintAttrib ());
 
1585
 
 
1586
        if (window->alpha () || fragment.getOpacity () != OPAQUE)
 
1587
            mask |= PAINT_WINDOW_TRANSLUCENT_MASK;
 
1588
 
 
1589
        rScreen->getPaintRectangle (&box);
 
1590
        getStretchScale (&box, &xScale, &yScale);
 
1591
 
 
1592
        x = window->geometry (). x ();
 
1593
        y = window->geometry (). y ();
 
1594
 
 
1595
        xOrigin = x - window->border ().left;
 
1596
        yOrigin = y - window->border ().top;
 
1597
 
 
1598
        wTransform.translate (xOrigin, yOrigin, 0.0f);
 
1599
        wTransform.scale (xScale, yScale, 1.0f);
 
1600
        wTransform.translate ((rScreen->geometry.x - x) / xScale - xOrigin,
 
1601
                              (rScreen->geometry.y - y) / yScale - yOrigin,
 
1602
                              0.0f);
 
1603
 
 
1604
        glPushMatrix ();
 
1605
        glLoadMatrixf (wTransform.getMatrix ());
 
1606
 
 
1607
        gWindow->glDraw (wTransform, fragment, region,
 
1608
                         mask | PAINT_WINDOW_TRANSFORMED_MASK);
 
1609
 
 
1610
        glPopMatrix ();
 
1611
    }
 
1612
    else
 
1613
    {
 
1614
        status = gWindow->glPaint (attrib, transform, region, mask);
 
1615
    }
 
1616
 
 
1617
    return status;
 
1618
}
 
1619
 
 
1620
bool
 
1621
ResizeWindow::damageRect (bool initial, const CompRect &rect)
 
1622
{
 
1623
    bool status = false;
 
1624
 
 
1625
    if (window == rScreen->w && rScreen->mode == ResizeOptions::ModeStretch)
 
1626
    {
 
1627
        BoxRec box;
 
1628
 
 
1629
        rScreen->getStretchRectangle (&box);
 
1630
        rScreen->damageRectangle (&box);
 
1631
 
 
1632
        status = true;
 
1633
    }
 
1634
 
 
1635
    status |= cWindow->damageRect (initial, rect);
 
1636
 
 
1637
    return status;
 
1638
}
 
1639
 
 
1640
/* We have to make some assumptions here in order to do this neatly,
 
1641
 * see build/generated/resize_options.h for more info */
 
1642
 
 
1643
#define ResizeModeShiftMask (1 << 0)
 
1644
#define ResizeModeAltMask (1 << 1)
 
1645
#define ResizeModeControlMask (1 << 2)
 
1646
#define ResizeModeMetaMask (1 << 3)
 
1647
 
 
1648
void
 
1649
ResizeScreen::resizeMaskValueToKeyMask (int        valueMask,
 
1650
                                        int        *mask)
 
1651
{
 
1652
    if (valueMask & ResizeModeShiftMask)
 
1653
        *mask |= ShiftMask;
 
1654
    if (valueMask & ResizeModeAltMask)
 
1655
        *mask |= CompAltMask;
 
1656
    if (valueMask & ResizeModeControlMask)
 
1657
        *mask |= ControlMask;
 
1658
    if (valueMask & ResizeModeMetaMask)
 
1659
        *mask |= CompMetaMask;
 
1660
}
 
1661
 
 
1662
void
 
1663
ResizeScreen::optionChanged (CompOption             *option,
 
1664
                             ResizeOptions::Options num)
 
1665
{
 
1666
    int *mask = NULL;
 
1667
    int valueMask = 0;
 
1668
 
 
1669
    switch (num)
 
1670
    {
 
1671
        case ResizeOptions::OutlineModifier:
 
1672
            mask = &outlineMask;
 
1673
            valueMask = optionGetOutlineModifierMask ();
 
1674
            break;
 
1675
        case ResizeOptions::RectangleModifier:
 
1676
            mask = &rectangleMask;
 
1677
            valueMask = optionGetRectangleModifierMask ();
 
1678
            break;
 
1679
        case ResizeOptions::StretchModifier:
 
1680
            mask = &stretchMask;
 
1681
            valueMask = optionGetStretchModifierMask ();
 
1682
            break;
 
1683
        case ResizeOptions::CenteredModifier:
 
1684
            mask = &centeredMask;
 
1685
            valueMask = optionGetCenteredModifierMask ();
 
1686
            break;
 
1687
        default:
 
1688
            break;
 
1689
    }
 
1690
 
 
1691
    if (mask)
 
1692
        resizeMaskValueToKeyMask (valueMask, mask);
 
1693
}
 
1694
 
 
1695
ResizeScreen::ResizeScreen (CompScreen *s) :
 
1696
    PluginClassHandler<ResizeScreen,CompScreen> (s),
 
1697
    gScreen (GLScreen::get (s)),
 
1698
    cScreen (CompositeScreen::get (s)),
 
1699
    w (NULL),
 
1700
    outlineMask (0),
 
1701
    rectangleMask (0),
 
1702
    stretchMask (0),
 
1703
    centeredMask (0),
 
1704
    releaseButton (0),
 
1705
    isConstrained (false),
 
1706
    offWorkAreaConstrained (true),
 
1707
    grabWindowWorkArea (NULL)
 
1708
{
 
1709
    CompOption::Vector atomTemplate;
 
1710
    Display *dpy = s->dpy ();
 
1711
    ResizeOptions::ChangeNotify notify =
 
1712
               boost::bind (&ResizeScreen::optionChanged, this, _1, _2);
 
1713
 
 
1714
    atomTemplate.resize (4);
 
1715
 
 
1716
    for (int i = 0; i < 4; i++)
 
1717
    {
 
1718
        char buf[4];
 
1719
        snprintf (buf, 4, "%i", i);
 
1720
        CompString tmpName (buf);
 
1721
 
 
1722
        atomTemplate.at (i).setName (tmpName, CompOption::TypeInt);
 
1723
    }
 
1724
 
 
1725
    resizeNotifyAtom = XInternAtom (s->dpy (), "_COMPIZ_RESIZE_NOTIFY", 0);
 
1726
    resizeInformationAtom = PropertyWriter ("_COMPIZ_RESIZE_INFORMATION",
 
1727
                                            atomTemplate);
 
1728
 
 
1729
    for (unsigned int i = 0; i < NUM_KEYS; i++)
 
1730
        key[i] = XKeysymToKeycode (s->dpy (), XStringToKeysym (rKeys[i].name));
 
1731
 
 
1732
    grabIndex = 0;
 
1733
 
 
1734
    leftCursor      = XCreateFontCursor (dpy, XC_left_side);
 
1735
    rightCursor     = XCreateFontCursor (dpy, XC_right_side);
 
1736
    upCursor        = XCreateFontCursor (dpy, XC_top_side);
 
1737
    upLeftCursor    = XCreateFontCursor (dpy, XC_top_left_corner);
 
1738
    upRightCursor   = XCreateFontCursor (dpy, XC_top_right_corner);
 
1739
    downCursor      = XCreateFontCursor (dpy, XC_bottom_side);
 
1740
    downLeftCursor  = XCreateFontCursor (dpy, XC_bottom_left_corner);
 
1741
    downRightCursor = XCreateFontCursor (dpy, XC_bottom_right_corner);
 
1742
    middleCursor    = XCreateFontCursor (dpy, XC_fleur);
 
1743
 
 
1744
    cursor[0] = leftCursor;
 
1745
    cursor[1] = rightCursor;
 
1746
    cursor[2] = upCursor;
 
1747
    cursor[3] = downCursor;
 
1748
 
 
1749
    optionSetInitiateKeyInitiate (resizeInitiateDefaultMode);
 
1750
    optionSetInitiateKeyTerminate (resizeTerminate);
 
1751
    optionSetInitiateButtonInitiate (resizeInitiateDefaultMode);
 
1752
    optionSetInitiateButtonTerminate (resizeTerminate);
 
1753
 
 
1754
    optionSetOutlineModifierNotify (notify);
 
1755
    optionSetRectangleModifierNotify (notify);
 
1756
    optionSetStretchModifierNotify (notify);
 
1757
    optionSetCenteredModifierNotify (notify);
 
1758
 
 
1759
    resizeMaskValueToKeyMask (optionGetOutlineModifierMask (), &outlineMask);
 
1760
    resizeMaskValueToKeyMask (optionGetRectangleModifierMask (), &rectangleMask);
 
1761
    resizeMaskValueToKeyMask (optionGetStretchModifierMask (), &stretchMask);
 
1762
    resizeMaskValueToKeyMask (optionGetCenteredModifierMask (), &centeredMask);
 
1763
 
 
1764
    ScreenInterface::setHandler (s);
 
1765
 
 
1766
    if (gScreen)
 
1767
        GLScreenInterface::setHandler (gScreen, false);
 
1768
}
 
1769
 
 
1770
ResizeScreen::~ResizeScreen ()
 
1771
{
 
1772
    Display *dpy = screen->dpy ();
 
1773
 
 
1774
    if (leftCursor)
 
1775
        XFreeCursor (dpy, leftCursor);
 
1776
    if (rightCursor)
 
1777
        XFreeCursor (dpy, rightCursor);
 
1778
    if (upCursor)
 
1779
        XFreeCursor (dpy, upCursor);
 
1780
    if (downCursor)
 
1781
        XFreeCursor (dpy, downCursor);
 
1782
    if (middleCursor)
 
1783
        XFreeCursor (dpy, middleCursor);
 
1784
    if (upLeftCursor)
 
1785
        XFreeCursor (dpy, upLeftCursor);
 
1786
    if (upRightCursor)
 
1787
        XFreeCursor (dpy, upRightCursor);
 
1788
    if (downLeftCursor)
 
1789
        XFreeCursor (dpy, downLeftCursor);
 
1790
    if (downRightCursor)
 
1791
        XFreeCursor (dpy, downRightCursor);
 
1792
}
 
1793
 
 
1794
ResizeWindow::ResizeWindow (CompWindow *w) :
 
1795
    PluginClassHandler<ResizeWindow,CompWindow> (w),
 
1796
    window (w),
 
1797
    gWindow (GLWindow::get (w)),
 
1798
    cWindow (CompositeWindow::get (w)),
 
1799
    rScreen (ResizeScreen::get (screen))
 
1800
{
 
1801
    WindowInterface::setHandler (window);
 
1802
 
 
1803
    if (cWindow)
 
1804
        CompositeWindowInterface::setHandler (cWindow, false);
 
1805
 
 
1806
    if (gWindow)
 
1807
        GLWindowInterface::setHandler (gWindow, false);
 
1808
}
 
1809
 
 
1810
 
 
1811
ResizeWindow::~ResizeWindow ()
 
1812
{
 
1813
}
 
1814
 
 
1815
 
 
1816
bool
 
1817
ResizePluginVTable::init ()
 
1818
{
 
1819
    if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION))
 
1820
         return false;
 
1821
 
 
1822
    return true;
 
1823
}
 
1824