~mniess/ubuntu/precise/compiz-plugins-main/lp953278

« back to all changes in this revision

Viewing changes to .pc/workarounds_923087.patch/workarounds/src/workarounds.cpp

  • Committer: Package Import Robot
  • Author(s): Didier Roche, Sam Spilsbury, Didier Roche
  • Date: 2012-02-16 15:14:05 UTC
  • Revision ID: package-import@ubuntu.com-20120216151405-97yrj541b3earjcw
Tags: 1:0.9.7.0~bzr19-0ubuntu2
[ Sam Spilsbury ]
* debian/patches/expo_api_931927.patch
* debian/patches/workarounds_923087.patch
  - adjust for API breaks (LP: #931927, #923087)

[ Didier Roche ]
* debian/control:
  - build-dep on latest compiz-dev for ABI dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2007 Andrew Riedi <andrewriedi@gmail.com>
 
3
 *
 
4
 * Sticky window handling and OpenGL fixes:
 
5
 * Copyright (c) 2007 Dennis Kasprzyk <onestone@opencompositing.org>
 
6
 *
 
7
 * Ported to Compiz 0.9:
 
8
 * Copyright (c) 2008 Sam Spilsbury <smspillaz@gmail.com>
 
9
 *
 
10
 * This program is free software; you can redistribute it and/or modify
 
11
 * it under the terms of the GNU General Public License as published by
 
12
 * the Free Software Foundation; either version 2 of the License, or
 
13
 * (at your option) any later version.
 
14
 *
 
15
 * This program is distributed in the hope that it will be useful,
 
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
18
 * GNU General Public License for more details.
 
19
 *
 
20
 * You should have received a copy of the GNU General Public License
 
21
 * along with this program; if not, write to the Free Software
 
22
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
23
 *
 
24
 * This plug-in for Metacity-like workarounds.
 
25
 */
 
26
 
 
27
#include "workarounds.h"
 
28
 
 
29
bool haveOpenGL;
 
30
 
 
31
COMPIZ_PLUGIN_20090315 (workarounds, WorkaroundsPluginVTable);
 
32
 
 
33
/*
 
34
 * WorkaroundsWindow::clearInputShape
 
35
 *
 
36
 */
 
37
void
 
38
WorkaroundsWindow::clearInputShape (HideInfo *hideInfo)
 
39
{
 
40
    XRectangle  *rects;
 
41
    int         count = 0, ordering;
 
42
    Window      xid = hideInfo->shapeWindow;
 
43
 
 
44
    rects = XShapeGetRectangles (screen->dpy (), xid, ShapeInput,
 
45
                                 &count, &ordering);
 
46
 
 
47
    if (count == 0)
 
48
        return;
 
49
 
 
50
    /* check if the returned shape exactly matches the window shape -
 
51
     *      if that is true, the window currently has no set input shape */
 
52
    if ((count == 1) &&
 
53
        (rects[0].x == -window->serverGeometry ().border ()) &&
 
54
        (rects[0].y == -window->serverGeometry ().border ()) &&
 
55
        (rects[0].width == (window->serverGeometry ().width () +
 
56
        window->serverGeometry ().border ())) &&
 
57
        (rects[0].height == (window->serverGeometry ().height () +
 
58
        window->serverGeometry ().border ())))
 
59
    {
 
60
        count = 0;
 
61
    }
 
62
 
 
63
    if (hideInfo->inputRects)
 
64
        XFree (hideInfo->inputRects);
 
65
 
 
66
    hideInfo->inputRects = rects;
 
67
    hideInfo->nInputRects = count;
 
68
    hideInfo->inputRectOrdering = ordering;
 
69
 
 
70
    XShapeSelectInput (screen->dpy (), xid, NoEventMask);
 
71
 
 
72
    XShapeCombineRectangles (screen->dpy (), xid, ShapeInput, 0, 0,
 
73
                             NULL, 0, ShapeSet, 0);
 
74
 
 
75
    XShapeSelectInput (screen->dpy (), xid, ShapeNotify);
 
76
}
 
77
 
 
78
/*
 
79
 * GroupWindow::restoreInputShape
 
80
 *
 
81
 */
 
82
void
 
83
WorkaroundsWindow::restoreInputShape (HideInfo *info)
 
84
{
 
85
    Window xid = info->shapeWindow;
 
86
 
 
87
    if (info->nInputRects)
 
88
    {
 
89
        XShapeCombineRectangles (screen->dpy (), xid, ShapeInput, 0, 0,
 
90
                                 info->inputRects, info->nInputRects,
 
91
                                 ShapeSet, info->inputRectOrdering);
 
92
    }
 
93
    else
 
94
    {
 
95
        XShapeCombineMask (screen->dpy (), xid, ShapeInput,
 
96
                           0, 0, None, ShapeSet);
 
97
    }
 
98
 
 
99
    if (info->inputRects)
 
100
        XFree (info->inputRects);
 
101
 
 
102
    XShapeSelectInput (screen->dpy (), xid, info->shapeMask);
 
103
}
 
104
/*
 
105
 * groupSetWindowVisibility
 
106
 *
 
107
 */
 
108
void
 
109
WorkaroundsWindow::setVisibility (bool visible)
 
110
{
 
111
    if (!visible && !windowHideInfo)
 
112
    {
 
113
        HideInfo *info;
 
114
 
 
115
        windowHideInfo = info = new HideInfo ();
 
116
        if (!windowHideInfo)
 
117
            return;
 
118
 
 
119
        info->inputRects = NULL;
 
120
        info->nInputRects = 0;
 
121
        info->shapeMask = XShapeInputSelected (screen->dpy (), window->id ());
 
122
 
 
123
        /* We are a reparenting window manager now, which means that we either
 
124
         * shape the frame window, or if it does not exist, shape the window **/
 
125
 
 
126
        if (window->frame ())
 
127
            info->shapeWindow = window->frame ();
 
128
        else
 
129
            info->shapeWindow = window->id ();
 
130
 
 
131
        clearInputShape (info);
 
132
 
 
133
        info->skipState = window->state () & (CompWindowStateSkipPagerMask |
 
134
                                              CompWindowStateSkipTaskbarMask);
 
135
    }
 
136
    else if (visible && windowHideInfo)
 
137
    {
 
138
        HideInfo *info = windowHideInfo;
 
139
 
 
140
        restoreInputShape (info);
 
141
 
 
142
        XShapeSelectInput (screen->dpy (), window->id (), info->shapeMask);
 
143
        delete info;
 
144
        windowHideInfo = NULL;
 
145
    }
 
146
 
 
147
    cWindow->addDamage ();
 
148
    gWindow->glPaintSetEnabled (this, !visible);
 
149
}
 
150
 
 
151
bool
 
152
WorkaroundsWindow::isGroupTransient (Window clientLeader)
 
153
{
 
154
    if (!clientLeader)
 
155
        return false;
 
156
 
 
157
    if (window->transientFor () == None || window->transientFor () == screen->root ())
 
158
    {
 
159
        if (window->type () & (CompWindowTypeUtilMask    |
 
160
                                CompWindowTypeToolbarMask |
 
161
                                CompWindowTypeMenuMask    |
 
162
                                CompWindowTypeDialogMask  |
 
163
                                CompWindowTypeModalDialogMask))
 
164
        {
 
165
            if (window->clientLeader () == clientLeader)
 
166
                return true;
 
167
        }
 
168
    }
 
169
 
 
170
    return false;
 
171
}
 
172
 
 
173
 
 
174
void
 
175
WorkaroundsWindow::minimize ()
 
176
{
 
177
    if (!window->managed ())
 
178
        return;
 
179
 
 
180
    if (!isMinimized)
 
181
    {
 
182
        WORKAROUNDS_SCREEN (screen);
 
183
 
 
184
        unsigned long data[2];
 
185
        int           state = IconicState;
 
186
        CompOption::Vector propTemplate = ws->inputDisabledAtom.getReadTemplate ();
 
187
        CompOption::Value enabled = CompOption::Value (true);
 
188
 
 
189
        screen->handleCompizEventSetEnabled (ws, true);
 
190
 
 
191
        window->windowNotify (CompWindowNotifyMinimize);
 
192
        window->changeState (window->state () | CompWindowStateHiddenMask);
 
193
 
 
194
        foreach (CompWindow *w, screen->windows ())
 
195
        {
 
196
            if (w->transientFor () == window->id () ||
 
197
                WorkaroundsWindow::get (w)->isGroupTransient (window->clientLeader ()))
 
198
                w->unminimize ();
 
199
        }
 
200
 
 
201
        window->windowNotify (CompWindowNotifyHide);
 
202
 
 
203
        setVisibility (false);
 
204
 
 
205
        /* HACK ATTACK */
 
206
 
 
207
        data[0] = state;
 
208
        data[1] = None;
 
209
 
 
210
        XChangeProperty (screen->dpy (), window->id (),
 
211
                        Atoms::wmState, Atoms::wmState,
 
212
                        32, PropModeReplace, (unsigned char *) data, 2);
 
213
 
 
214
        propTemplate.at (0).set (enabled);
 
215
        ws->inputDisabledAtom.updateProperty (window->id (),
 
216
                                              propTemplate,
 
217
                                              XA_CARDINAL);
 
218
 
 
219
 
 
220
        isMinimized = true;
 
221
    }
 
222
}
 
223
 
 
224
void
 
225
WorkaroundsWindow::unminimize ()
 
226
{
 
227
    if (isMinimized)
 
228
    {
 
229
        WORKAROUNDS_SCREEN (screen);
 
230
 
 
231
        unsigned long data[2];
 
232
        int           state = NormalState;
 
233
        CompOption::Vector propTemplate = ws->inputDisabledAtom.getReadTemplate ();
 
234
        CompOption::Value enabled = CompOption::Value (false);
 
235
 
 
236
        window->windowNotify (CompWindowNotifyUnminimize);
 
237
        window->changeState (window->state () & ~CompWindowStateHiddenMask);
 
238
 
 
239
        isMinimized = false;
 
240
 
 
241
        window->windowNotify (CompWindowNotifyShow);
 
242
 
 
243
        setVisibility (true);
 
244
 
 
245
        if (!ws->skipTransients)
 
246
        {
 
247
            foreach (CompWindow *w, screen->windows ())
 
248
            {
 
249
                if (w->transientFor () == window->id () ||
 
250
                    WorkaroundsWindow::get (w)->isGroupTransient (window->clientLeader ()))
 
251
                    w->unminimize ();
 
252
            }
 
253
        }
 
254
 
 
255
        /* HACK ATTACK */
 
256
 
 
257
        data[0] = state;
 
258
        data[1] = None;
 
259
 
 
260
        XChangeProperty (screen->dpy (), window->id (),
 
261
                         Atoms::wmState, Atoms::wmState,
 
262
                         32, PropModeReplace, (unsigned char *) data, 2);
 
263
 
 
264
        propTemplate.at (0).set (enabled);
 
265
        ws->inputDisabledAtom.updateProperty (window->id (),
 
266
                                              propTemplate,
 
267
                                              XA_CARDINAL);
 
268
    }
 
269
}
 
270
 
 
271
bool
 
272
WorkaroundsWindow::minimized ()
 
273
{
 
274
    return isMinimized;
 
275
}
 
276
 
 
277
bool
 
278
WorkaroundsWindow::glPaint (const GLWindowPaintAttrib &attrib,
 
279
                            const GLMatrix            &transform,
 
280
                            const CompRegion          &region,
 
281
                            unsigned int              mask)
 
282
{
 
283
    if (isMinimized)
 
284
    {
 
285
        WORKAROUNDS_SCREEN (screen);
 
286
        bool doMask = true;
 
287
 
 
288
        foreach (CompWindow *w, ws->minimizingWindows)
 
289
        {
 
290
            if (w->id () == window->id ())
 
291
                doMask = false;
 
292
            break;
 
293
        }
 
294
 
 
295
        if (doMask)
 
296
            mask |= PAINT_WINDOW_NO_CORE_INSTANCE_MASK;
 
297
    }
 
298
 
 
299
    return gWindow->glPaint (attrib, transform, region, mask);
 
300
}
 
301
 
 
302
void
 
303
WorkaroundsScreen::checkFunctions (bool checkWindow, bool checkScreen)
 
304
{
 
305
    if (haveOpenGL && optionGetForceGlxSync () && checkScreen)
 
306
    {
 
307
        gScreen->glPaintOutputSetEnabled (this, true);
 
308
    }
 
309
    else if (haveOpenGL && checkScreen)
 
310
    {
 
311
        gScreen->glPaintOutputSetEnabled (this, false);
 
312
    }
 
313
 
 
314
    if (haveOpenGL && optionGetForceSwapBuffers () && checkScreen)
 
315
    {
 
316
        cScreen->preparePaintSetEnabled (this, true);
 
317
    }
 
318
    else if (haveOpenGL && checkScreen)
 
319
    {
 
320
        cScreen->preparePaintSetEnabled (this, false);
 
321
    }
 
322
 
 
323
    if ((optionGetLegacyFullscreen () ||
 
324
        optionGetFirefoxMenuFix ()   ||
 
325
        optionGetOooMenuFix ()       ||
 
326
        optionGetNotificationDaemonFix () ||
 
327
        optionGetJavaFix ()          ||
 
328
        optionGetQtFix ()            ||
 
329
        optionGetConvertUrgency ()   ) && checkScreen)
 
330
    {
 
331
        screen->handleEventSetEnabled (this, true);
 
332
    }
 
333
    else if (checkScreen)
 
334
    {
 
335
        screen->handleEventSetEnabled (this, false);
 
336
    }
 
337
 
 
338
    if (checkWindow)
 
339
    {
 
340
        bool legacyFullscreen = optionGetLegacyFullscreen ();
 
341
        bool keepMinimized = optionGetKeepMinimizedWindows ();
 
342
 
 
343
        foreach (CompWindow *w, screen->windows ())
 
344
        {
 
345
            WORKAROUNDS_WINDOW (w);
 
346
 
 
347
            bool m = ww->window->minimized ();
 
348
 
 
349
            ww->window->getAllowedActionsSetEnabled (ww, legacyFullscreen);
 
350
            ww->window->resizeNotifySetEnabled (ww, legacyFullscreen);
 
351
 
 
352
            if (m)
 
353
                ww->window->unminimize ();
 
354
            ww->window->minimizeSetEnabled (ww, keepMinimized);
 
355
            ww->window->unminimizeSetEnabled (ww, keepMinimized);
 
356
            ww->window->minimizedSetEnabled (ww, keepMinimized);
 
357
            if (m)
 
358
                ww->window->minimize ();
 
359
        }
 
360
    }
 
361
}
 
362
 
 
363
 
 
364
void
 
365
WorkaroundsScreen::addToFullscreenList (CompWindow *w)
 
366
{
 
367
    mfwList.push_back (w->id ());
 
368
}
 
369
 
 
370
void
 
371
WorkaroundsScreen::removeFromFullscreenList (CompWindow *w)
 
372
{
 
373
    mfwList.remove (w->id ());
 
374
}
 
375
 
 
376
static void
 
377
workaroundsProgramEnvParameter4f (GLenum  target,
 
378
                                  GLuint  index,
 
379
                                  GLfloat x,
 
380
                                  GLfloat y,
 
381
                                  GLfloat z,
 
382
                                  GLfloat w)
 
383
{
 
384
    WorkaroundsScreen *ws;
 
385
    GLdouble data[4];
 
386
 
 
387
    ws = WorkaroundsScreen::get (screen);
 
388
 
 
389
    data[0] = x;
 
390
    data[1] = y;
 
391
    data[2] = z;
 
392
    data[3] = w;
 
393
 
 
394
    (*ws->programEnvParameter4dv) (target, index, data);
 
395
}
 
396
 
 
397
void
 
398
WorkaroundsScreen::updateParameterFix ()
 
399
{
 
400
    if (!GL::programEnvParameter4f || !programEnvParameter4dv)
 
401
        return;
 
402
    if (optionGetAiglxFragmentFix ())
 
403
        GL::programEnvParameter4f = workaroundsProgramEnvParameter4f;
 
404
    else
 
405
        GL::programEnvParameter4f = origProgramEnvParameter4f;
 
406
}
 
407
 
 
408
void
 
409
WorkaroundsScreen::updateVideoSyncFix ()
 
410
{
 
411
    if ((!GL::getVideoSync || origGetVideoSync) ||
 
412
        (!GL::waitVideoSync || origWaitVideoSync))
 
413
        return;
 
414
    if (optionGetNoWaitForVideoSync ())
 
415
    {
 
416
        GL::getVideoSync = NULL;
 
417
        GL::waitVideoSync = NULL;
 
418
    }
 
419
    else
 
420
    {
 
421
        GL::getVideoSync = origGetVideoSync;
 
422
        GL::waitVideoSync = origWaitVideoSync;
 
423
    }
 
424
}
 
425
 
 
426
void
 
427
WorkaroundsScreen::preparePaint (int ms)
 
428
{
 
429
    if (optionGetForceSwapBuffers ())
 
430
        cScreen->damageScreen (); // Massive CPU usage here
 
431
 
 
432
    cScreen->preparePaint (ms);
 
433
}
 
434
 
 
435
bool
 
436
WorkaroundsScreen::glPaintOutput (const GLScreenPaintAttrib &attrib,
 
437
                                  const GLMatrix            &transform,
 
438
                                  const CompRegion          &region,
 
439
                                  CompOutput                *output,
 
440
                                  unsigned int              mask)
 
441
{
 
442
    if (optionGetForceGlxSync ())
 
443
        glXWaitX ();
 
444
 
 
445
    return gScreen->glPaintOutput (attrib, transform, region, output, mask);
 
446
}
 
447
 
 
448
CompString
 
449
WorkaroundsWindow::getRoleAtom ()
 
450
{
 
451
    Atom type;
 
452
    unsigned long nItems;
 
453
    unsigned long bytesAfter;
 
454
    unsigned char *str = NULL;
 
455
    int format, result;
 
456
    CompString retval;
 
457
 
 
458
    WORKAROUNDS_SCREEN (screen);
 
459
 
 
460
    result = XGetWindowProperty (screen->dpy (), window->id (), ws->roleAtom,
 
461
                                 0, LONG_MAX, FALSE, XA_STRING,
 
462
                                 &type, &format, &nItems, &bytesAfter,
 
463
                                 (unsigned char **) &str);
 
464
 
 
465
    if (result != Success)
 
466
        return "";
 
467
 
 
468
    if (type != XA_STRING)
 
469
    {
 
470
        XFree (str);
 
471
        return "";
 
472
    }
 
473
 
 
474
    retval = CompString ((const char *) str);
 
475
 
 
476
    return retval;
 
477
}
 
478
 
 
479
void
 
480
WorkaroundsWindow::removeSticky ()
 
481
{
 
482
    if (window->state () & CompWindowStateStickyMask && madeSticky)
 
483
        window->changeState (window->state () & ~CompWindowStateStickyMask);
 
484
    madeSticky = FALSE;
 
485
}
 
486
 
 
487
void
 
488
WorkaroundsWindow::updateSticky ()
 
489
{
 
490
    Bool makeSticky = FALSE;
 
491
 
 
492
    WORKAROUNDS_SCREEN (screen);
 
493
 
 
494
    if (ws->optionGetStickyAlldesktops () && window->desktop () == 0xffffffff &&
 
495
        ws->optionGetAlldesktopStickyMatch ().evaluate (window))
 
496
        makeSticky = TRUE;
 
497
 
 
498
    if (makeSticky)
 
499
    {
 
500
        if (!(window->state () & CompWindowStateStickyMask))
 
501
        {
 
502
            madeSticky = TRUE;
 
503
            window->changeState (
 
504
                                window->state () | CompWindowStateStickyMask);
 
505
        }
 
506
    }
 
507
    else
 
508
        removeSticky ();
 
509
}
 
510
 
 
511
void
 
512
WorkaroundsWindow::updateUrgencyState ()
 
513
{
 
514
    Bool     urgent;
 
515
    XWMHints *xwmh;
 
516
 
 
517
    xwmh = XGetWMHints (screen->dpy (), window->id ());
 
518
 
 
519
    if (!xwmh)
 
520
    {
 
521
        XFree (xwmh);
 
522
        return;
 
523
    }
 
524
 
 
525
    urgent = (xwmh->flags & XUrgencyHint);
 
526
 
 
527
    XFree (xwmh);
 
528
 
 
529
    if (urgent)
 
530
    {
 
531
        madeDemandAttention = TRUE;
 
532
        window->changeState (window->state () |
 
533
                             CompWindowStateDemandsAttentionMask);
 
534
    }
 
535
    else if (madeDemandAttention)
 
536
    {
 
537
        madeDemandAttention = FALSE;
 
538
        window->changeState (window->state () &
 
539
                             ~CompWindowStateDemandsAttentionMask);
 
540
    }
 
541
}
 
542
 
 
543
/* Use this function to forcibly refresh java window properties when they
 
544
 * have been unmarked as transient. This is just a copy of
 
545
 * PrivateScreen::setWindowState. I would use CompWindow::changeState, but
 
546
 * it checks whether oldstate==newstate
 
547
 */
 
548
void
 
549
WorkaroundsScreen::setWindowState (unsigned int state, Window id)
 
550
{
 
551
    Atom data[32];
 
552
    int  i = 0;
 
553
 
 
554
    if (state & CompWindowStateModalMask)
 
555
        data[i++] = Atoms::winStateModal;
 
556
    if (state & CompWindowStateStickyMask)
 
557
        data[i++] = Atoms::winStateSticky;
 
558
    if (state & CompWindowStateMaximizedVertMask)
 
559
        data[i++] = Atoms::winStateMaximizedVert;
 
560
    if (state & CompWindowStateMaximizedHorzMask)
 
561
        data[i++] = Atoms::winStateMaximizedHorz;
 
562
    if (state & CompWindowStateShadedMask)
 
563
        data[i++] = Atoms::winStateShaded;
 
564
    if (state & CompWindowStateSkipTaskbarMask)
 
565
        data[i++] = Atoms::winStateSkipTaskbar;
 
566
    if (state & CompWindowStateSkipPagerMask)
 
567
        data[i++] = Atoms::winStateSkipPager;
 
568
    if (state & CompWindowStateHiddenMask)
 
569
        data[i++] = Atoms::winStateHidden;
 
570
    if (state & CompWindowStateFullscreenMask)
 
571
        data[i++] = Atoms::winStateFullscreen;
 
572
    if (state & CompWindowStateAboveMask)
 
573
        data[i++] = Atoms::winStateAbove;
 
574
    if (state & CompWindowStateBelowMask)
 
575
        data[i++] = Atoms::winStateBelow;
 
576
    if (state & CompWindowStateDemandsAttentionMask)
 
577
        data[i++] = Atoms::winStateDemandsAttention;
 
578
    if (state & CompWindowStateDisplayModalMask)
 
579
        data[i++] = Atoms::winStateDisplayModal;
 
580
 
 
581
    XChangeProperty (screen->dpy (), id, Atoms::winState,
 
582
                     XA_ATOM, 32, PropModeReplace,
 
583
                     (unsigned char *) data, i);
 
584
}
 
585
 
 
586
void
 
587
WorkaroundsWindow::getAllowedActions (unsigned int &setActions,
 
588
                                      unsigned int &clearActions)
 
589
{
 
590
 
 
591
    window->getAllowedActions (setActions, clearActions);
 
592
 
 
593
    if (isFullscreen)
 
594
        setActions |= CompWindowActionFullscreenMask;
 
595
}
 
596
 
 
597
void
 
598
WorkaroundsWindow::fixupFullscreen ()
 
599
{
 
600
    Bool   isFullSize;
 
601
    BoxPtr box;
 
602
 
 
603
    WORKAROUNDS_SCREEN (screen);
 
604
 
 
605
    if (!ws->optionGetLegacyFullscreen ())
 
606
        return;
 
607
 
 
608
    if (window->wmType () & CompWindowTypeDesktopMask)
 
609
    {
 
610
        /* desktop windows are implicitly fullscreen */
 
611
        isFullSize = FALSE;
 
612
    }
 
613
    else
 
614
    {
 
615
        /* get output region for window */
 
616
        int output = screen->outputDeviceForGeometry (window->geometry ());
 
617
        box = &screen->outputDevs ().at (output).region ()->extents;
 
618
 
 
619
        /* does the size match the output rectangle? */
 
620
        isFullSize = (window->serverX () == box->x1) &&
 
621
                     (window->serverY () == box->y1) &&
 
622
                     (window->serverWidth () == (box->x2 - box->x1)) &&
 
623
                     (window->serverHeight () == (box->y2 - box->y1));
 
624
 
 
625
        /* if not, check if it matches the whole screen */
 
626
        if (!isFullSize)
 
627
        {
 
628
            if ((window->serverX () == 0) && (window->serverY () == 0) &&
 
629
                (window->serverWidth () == screen->width ()) &&
 
630
                (window->serverHeight () == screen->height ()))
 
631
            {
 
632
                isFullSize = TRUE;
 
633
            }
 
634
        }
 
635
    }
 
636
 
 
637
    isFullscreen = isFullSize;
 
638
    if (isFullSize && !(window->state () & CompWindowStateFullscreenMask))
 
639
    {
 
640
        unsigned int state = window->state () &
 
641
                                ~CompWindowStateFullscreenMask;
 
642
 
 
643
        if (isFullSize)
 
644
            state |= CompWindowStateFullscreenMask;
 
645
        madeFullscreen = isFullSize;
 
646
 
 
647
        if (state != window->state ())
 
648
        {
 
649
            window->changeState (state);
 
650
            window->updateAttributes (CompStackingUpdateModeNormal);
 
651
 
 
652
            /* keep track of windows that we interact with */
 
653
            ws->addToFullscreenList (window);
 
654
        }
 
655
    }
 
656
    else if (!isFullSize && !ws->mfwList.empty () &&
 
657
             (window->state () & CompWindowStateFullscreenMask))
 
658
    {
 
659
        /* did we set the flag? */
 
660
 
 
661
        foreach (Window mfw, ws->mfwList)
 
662
        {
 
663
            if (mfw == window->id ())
 
664
            {
 
665
                unsigned int state = window->state () &
 
666
                                        ~CompWindowStateFullscreenMask;
 
667
 
 
668
                if (isFullSize)
 
669
                    state |= CompWindowStateFullscreenMask;
 
670
 
 
671
                madeFullscreen = isFullSize;
 
672
 
 
673
                if (state != window->state ())
 
674
                {
 
675
                    window->changeState (state);
 
676
                    window->updateAttributes (CompStackingUpdateModeNormal);
 
677
                }
 
678
 
 
679
                ws->removeFromFullscreenList (window);
 
680
                break;
 
681
            }
 
682
        }
 
683
   }
 
684
}
 
685
 
 
686
void
 
687
WorkaroundsWindow::updateFixedWindow (unsigned int newWmType)
 
688
{
 
689
    if (newWmType != window->wmType ())
 
690
    {
 
691
        adjustedWinType = TRUE;
 
692
        oldWmType = window->wmType ();
 
693
 
 
694
        window->recalcType ();
 
695
        window->recalcActions ();
 
696
 
 
697
        screen->matchPropertyChanged (window);
 
698
 
 
699
        window->wmType () = newWmType;
 
700
    }
 
701
}
 
702
 
 
703
unsigned int
 
704
WorkaroundsWindow::getFixedWindowType ()
 
705
{
 
706
    unsigned int newWmType;
 
707
    XClassHint classHint;
 
708
    CompString resName;
 
709
 
 
710
    WORKAROUNDS_SCREEN (screen);
 
711
 
 
712
    newWmType = window->wmType ();
 
713
 
 
714
    if (!XGetClassHint (screen->dpy (), window->id (), &classHint))
 
715
        return newWmType;
 
716
 
 
717
    if (classHint.res_name)
 
718
    {
 
719
        resName = CompString (classHint.res_name);
 
720
        XFree (classHint.res_name);
 
721
    }
 
722
    
 
723
    if (classHint.res_class)
 
724
    {
 
725
        XFree (classHint.res_class);
 
726
    }
 
727
 
 
728
    /* FIXME: Is this the best way to detect a notification type window? */
 
729
    if (ws->optionGetNotificationDaemonFix ())
 
730
    {
 
731
        if (newWmType == CompWindowTypeNormalMask &&
 
732
            window->overrideRedirect () && !resName.empty () &&
 
733
            resName.compare("notification-daemon") == 0)
 
734
        {
 
735
            newWmType = CompWindowTypeNotificationMask;
 
736
            return newWmType;
 
737
        }
 
738
    }
 
739
 
 
740
    if (ws->optionGetFirefoxMenuFix ())
 
741
    {
 
742
        if (newWmType == CompWindowTypeNormalMask &&
 
743
            window->overrideRedirect () && !resName.empty ())
 
744
        {
 
745
            if ((resName.compare ( "gecko") == 0) ||
 
746
                (resName.compare ( "popup") == 0))
 
747
            {
 
748
                newWmType = CompWindowTypeDropdownMenuMask;
 
749
                return newWmType;
 
750
            }
 
751
        }
 
752
    }
 
753
 
 
754
    if (ws->optionGetOooMenuFix ())
 
755
    {
 
756
        if (newWmType == CompWindowTypeNormalMask &&
 
757
            window->overrideRedirect () && !resName.empty ())
 
758
        {
 
759
            if (resName.compare ( "VCLSalFrame") == 0)
 
760
            {
 
761
                newWmType = CompWindowTypeDropdownMenuMask;
 
762
                return newWmType;
 
763
            }
 
764
        }
 
765
    }
 
766
    /* FIXME: Basic hack to get Java windows working correctly. */
 
767
    if (ws->optionGetJavaFix () && !resName.empty ())
 
768
    {
 
769
        if ((resName.compare ( "sun-awt-X11-XMenuWindow") == 0) ||
 
770
            (resName.compare ( "sun-awt-X11-XWindowPeer") == 0))
 
771
        {
 
772
            newWmType = CompWindowTypeDropdownMenuMask;
 
773
            return newWmType;
 
774
        }
 
775
        else if (resName.compare ( "sun-awt-X11-XDialogPeer") == 0)
 
776
        {
 
777
            newWmType = CompWindowTypeDialogMask;
 
778
            return newWmType;
 
779
        }
 
780
        else if (resName.compare ( "sun-awt-X11-XFramePeer") == 0)
 
781
        {
 
782
            newWmType = CompWindowTypeNormalMask;
 
783
            return newWmType;
 
784
        }
 
785
    }
 
786
 
 
787
    if (ws->optionGetQtFix ())
 
788
    {
 
789
        CompString windowRole;
 
790
 
 
791
        /* fix tooltips */
 
792
        windowRole = getRoleAtom ();
 
793
        if (!windowRole.empty ())
 
794
        {
 
795
            if ((windowRole.compare ("toolTipTip") == 0) ||
 
796
                (windowRole.compare ("qtooltip_label") == 0))
 
797
            {
 
798
                newWmType = CompWindowTypeTooltipMask;
 
799
                return newWmType;
 
800
            }
 
801
        }
 
802
 
 
803
        /* fix Qt transients - FIXME: is there a better way to detect them? */
 
804
        if (resName.empty () && window->overrideRedirect () &&
 
805
            (window->windowClass () == InputOutput) &&
 
806
            (newWmType == CompWindowTypeUnknownMask))
 
807
        {
 
808
            newWmType = CompWindowTypeDropdownMenuMask;
 
809
            return newWmType;
 
810
        }
 
811
    }
 
812
 
 
813
    return newWmType;
 
814
}
 
815
 
 
816
void
 
817
WorkaroundsScreen::optionChanged (CompOption                  *opt,
 
818
                                  WorkaroundsOptions::Options num)
 
819
{
 
820
    checkFunctions (true, true);
 
821
 
 
822
    foreach (CompWindow *w, screen->windows ())
 
823
        WorkaroundsWindow::get (w)->updateSticky ();
 
824
 
 
825
    if (haveOpenGL)
 
826
    {
 
827
        updateParameterFix ();
 
828
        updateVideoSyncFix ();
 
829
 
 
830
        if (optionGetFglrxXglFix ())
 
831
            GL::copySubBuffer = NULL;
 
832
        else
 
833
            GL::copySubBuffer = origCopySubBuffer;
 
834
    }
 
835
 
 
836
    if (optionGetKeepMinimizedWindows ())
 
837
    {
 
838
        foreach (CompWindow *window, screen->windows ())
 
839
        {
 
840
            WORKAROUNDS_WINDOW (window);
 
841
            bool m = window->minimized ();
 
842
            if (m)
 
843
                window->unminimize ();
 
844
            window->minimizeSetEnabled (ww, true);
 
845
            window->unminimizeSetEnabled (ww, true);
 
846
            window->minimizedSetEnabled (ww, true);
 
847
            if (m)
 
848
                window->minimize ();
 
849
        }
 
850
    }
 
851
    else
 
852
    {
 
853
        foreach (CompWindow *window, screen->windows ())
 
854
        {
 
855
            WORKAROUNDS_WINDOW (window);
 
856
            bool m = window->minimized ();
 
857
            if (m)
 
858
                window->unminimize ();
 
859
            window->minimizeSetEnabled (ww, false);
 
860
            window->unminimizeSetEnabled (ww, false);
 
861
            window->minimizedSetEnabled (ww, false);
 
862
            if (m)
 
863
            {
 
864
                ww->isMinimized = false;
 
865
                window->minimize ();
 
866
            }
 
867
        }
 
868
    }
 
869
}
 
870
 
 
871
void
 
872
WorkaroundsScreen::handleCompizEvent (const char              *pluginName,
 
873
                                      const char              *eventName,
 
874
                                      CompOption::Vector      &o)
 
875
{
 
876
    if (strncmp (pluginName, "animation", 9) == 0 &&
 
877
        strncmp (eventName, "window_animation", 16) == 0)
 
878
    {
 
879
        if (CompOption::getStringOptionNamed (o, "type", "") == "minimize")
 
880
        {
 
881
            CompWindow *w = screen->findWindow (CompOption::getIntOptionNamed (
 
882
                                                      o, "window", 0));
 
883
            if (w)
 
884
            {
 
885
                if (CompOption::getBoolOptionNamed (o, "active", false))
 
886
                    minimizingWindows.push_back (w);
 
887
                else
 
888
                    minimizingWindows.remove (w);
 
889
            }
 
890
        }
 
891
    }
 
892
 
 
893
    if (!CompOption::getBoolOptionNamed (o, "active", false) &&
 
894
        minimizingWindows.empty ())
 
895
        screen->handleCompizEventSetEnabled (this, false);
 
896
 
 
897
    screen->handleCompizEvent (pluginName, eventName, o);
 
898
}
 
899
 
 
900
void
 
901
WorkaroundsScreen::handleEvent (XEvent *event)
 
902
{
 
903
    CompWindow *w;
 
904
 
 
905
    switch (event->type) {
 
906
    case ConfigureRequest:
 
907
        w = screen->findWindow (event->xconfigurerequest.window);
 
908
        if (w)
 
909
        {
 
910
            WORKAROUNDS_WINDOW (w);
 
911
 
 
912
            if (ww->madeFullscreen)
 
913
                w->changeState (w->state () &= ~CompWindowStateFullscreenMask);
 
914
        }
 
915
        break;
 
916
    case MapRequest:
 
917
        w = screen->findWindow (event->xmaprequest.window);
 
918
        if (w)
 
919
        {
 
920
            WORKAROUNDS_WINDOW (w);
 
921
            ww->updateSticky ();
 
922
            ww->updateFixedWindow (ww->getFixedWindowType ());
 
923
            ww->fixupFullscreen ();
 
924
        }
 
925
        break;
 
926
    case MapNotify:
 
927
        w = screen->findWindow (event->xmap.window);
 
928
        if (w && w->overrideRedirect ())
 
929
        {
 
930
            WORKAROUNDS_WINDOW (w);
 
931
            ww->updateFixedWindow (ww->getFixedWindowType ());
 
932
        }
 
933
        break;
 
934
    case DestroyNotify:
 
935
        w = screen->findWindow (event->xdestroywindow.window);
 
936
        if (w)
 
937
            removeFromFullscreenList (w);
 
938
        break;
 
939
    }
 
940
 
 
941
    screen->handleEvent (event);
 
942
 
 
943
    switch (event->type) {
 
944
    case ConfigureRequest:
 
945
        w = screen->findWindow (event->xconfigurerequest.window);
 
946
        if (w)
 
947
        {
 
948
            WORKAROUNDS_WINDOW (w);
 
949
 
 
950
            if (ww->madeFullscreen)
 
951
                w->state () |= CompWindowStateFullscreenMask;
 
952
        }
 
953
        break;
 
954
    case ClientMessage:
 
955
        if (event->xclient.message_type == Atoms::winDesktop)
 
956
        {
 
957
            w = screen->findWindow (event->xclient.window);
 
958
            if (w)
 
959
            {
 
960
                WORKAROUNDS_WINDOW (w);
 
961
                ww->updateSticky ();
 
962
            }
 
963
        }
 
964
        break;
 
965
    case PropertyNotify:
 
966
        if ((event->xproperty.atom == XA_WM_CLASS) ||
 
967
            (event->xproperty.atom == Atoms::winType))
 
968
        {
 
969
            w = screen->findWindow (event->xproperty.window);
 
970
            if (w)
 
971
            {
 
972
                WORKAROUNDS_WINDOW (w);
 
973
                ww->updateFixedWindow (ww->getFixedWindowType ());
 
974
            }
 
975
        }
 
976
        else if (event->xproperty.atom == XA_WM_HINTS)
 
977
        {
 
978
            if (optionGetConvertUrgency ())
 
979
            {
 
980
                w = screen->findWindow (event->xproperty.window);
 
981
                if (w)
 
982
                {
 
983
                    WORKAROUNDS_WINDOW (w);
 
984
                    ww->updateUrgencyState ();
 
985
                }
 
986
            }
 
987
        }
 
988
        else if (event->xproperty.atom == Atoms::clientList) {
 
989
            if (optionGetJavaTaskbarFix ()) {
 
990
                foreach (CompWindow *w, screen->windows ()) {
 
991
                    if (w->managed ())
 
992
                        setWindowState (w->state (), w->id ());
 
993
                }
 
994
            }
 
995
        }
 
996
        break;
 
997
    default:
 
998
        break;
 
999
    }
 
1000
}
 
1001
 
 
1002
void
 
1003
WorkaroundsWindow::resizeNotify (int dx, int dy,
 
1004
                                 int dwidth, int dheight)
 
1005
{
 
1006
    if (window->isViewable ())
 
1007
        fixupFullscreen ();
 
1008
 
 
1009
    window->resizeNotify (dx, dy, dwidth, dheight);
 
1010
}
 
1011
 
 
1012
WorkaroundsScreen::WorkaroundsScreen (CompScreen *screen) :
 
1013
    PluginClassHandler <WorkaroundsScreen, CompScreen> (screen),
 
1014
    cScreen (CompositeScreen::get (screen)),
 
1015
    gScreen (GLScreen::get (screen)),
 
1016
    roleAtom (XInternAtom (screen->dpy (), "WM_WINDOW_ROLE", 0)),
 
1017
    skipTransients (false)
 
1018
{
 
1019
    CompOption::Vector          propTemplate;
 
1020
 
 
1021
    ScreenInterface::setHandler (screen, false);
 
1022
    if (haveOpenGL)
 
1023
    {
 
1024
        CompositeScreenInterface::setHandler (cScreen, false);
 
1025
        GLScreenInterface::setHandler (gScreen, false);
 
1026
    }
 
1027
 
 
1028
    propTemplate.push_back (CompOption ("enabled", CompOption::TypeBool));
 
1029
    inputDisabledAtom = PropertyWriter ("COMPIZ_NET_WM_INPUT_DISABLED", propTemplate);
 
1030
 
 
1031
    optionSetStickyAlldesktopsNotify (boost::bind (
 
1032
                                        &WorkaroundsScreen::optionChanged, this,
 
1033
                                        _1, _2));
 
1034
    optionSetAlldesktopStickyMatchNotify (boost::bind (
 
1035
                                        &WorkaroundsScreen::optionChanged, this,
 
1036
                                        _1, _2));
 
1037
 
 
1038
    optionSetAiglxFragmentFixNotify (boost::bind (
 
1039
                                        &WorkaroundsScreen::optionChanged, this,
 
1040
                                        _1, _2));
 
1041
 
 
1042
    optionSetFglrxXglFixNotify (boost::bind (
 
1043
                                        &WorkaroundsScreen::optionChanged, this,
 
1044
                                        _1, _2));
 
1045
    optionSetForceSwapBuffersNotify (boost::bind (
 
1046
                                        &WorkaroundsScreen::optionChanged, this,
 
1047
                                        _1, _2));
 
1048
    optionSetNoWaitForVideoSyncNotify (boost::bind (
 
1049
                                        &WorkaroundsScreen::optionChanged, this,
 
1050
                                        _1, _2));
 
1051
    optionSetKeepMinimizedWindowsNotify (boost::bind (
 
1052
                                         &WorkaroundsScreen::optionChanged, this,
 
1053
                                         _1, _2));
 
1054
 
 
1055
    if (haveOpenGL)
 
1056
    {
 
1057
        origProgramEnvParameter4f = GL::programEnvParameter4f;
 
1058
        programEnvParameter4dv  = (GLProgramParameter4dvProc)
 
1059
                       gScreen->getProcAddress ("glProgramEnvParameter4dvARB");
 
1060
        origCopySubBuffer = GL::copySubBuffer;
 
1061
 
 
1062
        origGetVideoSync = GL::getVideoSync;
 
1063
        origWaitVideoSync = GL::waitVideoSync;
 
1064
 
 
1065
        updateParameterFix ();
 
1066
        updateVideoSyncFix ();
 
1067
    }
 
1068
 
 
1069
    if (optionGetFglrxXglFix () && haveOpenGL)
 
1070
        GL::copySubBuffer = NULL;
 
1071
 
 
1072
    checkFunctions (false, true);
 
1073
}
 
1074
 
 
1075
WorkaroundsScreen::~WorkaroundsScreen ()
 
1076
{
 
1077
    if (haveOpenGL)
 
1078
    {
 
1079
        GL::copySubBuffer = origCopySubBuffer;
 
1080
        GL::getVideoSync = origGetVideoSync;
 
1081
        GL::waitVideoSync = origWaitVideoSync;
 
1082
    }
 
1083
}
 
1084
 
 
1085
WorkaroundsWindow::WorkaroundsWindow (CompWindow *window) :
 
1086
    PluginClassHandler <WorkaroundsWindow, CompWindow> (window),
 
1087
    window (window),
 
1088
    cWindow (CompositeWindow::get (window)),
 
1089
    gWindow (GLWindow::get (window)),
 
1090
    adjustedWinType (false),
 
1091
    madeSticky (false),
 
1092
    madeFullscreen (false),
 
1093
    isFullscreen (false),
 
1094
    madeDemandAttention (false),
 
1095
    isMinimized (window->minimized ()),
 
1096
    oldWmType (window->wmType ()),
 
1097
    windowHideInfo (NULL)
 
1098
{
 
1099
    WindowInterface::setHandler (window, false);
 
1100
    GLWindowInterface::setHandler (gWindow, false);
 
1101
 
 
1102
    WORKAROUNDS_SCREEN (screen);
 
1103
 
 
1104
    if (ws->optionGetLegacyFullscreen ())
 
1105
    {
 
1106
        window->getAllowedActionsSetEnabled (this, false);
 
1107
        window->resizeNotifySetEnabled (this, false);
 
1108
    }
 
1109
    if (ws->optionGetKeepMinimizedWindows ())
 
1110
    {
 
1111
        window->minimizeSetEnabled (this, true);
 
1112
        window->unminimizeSetEnabled (this, true);
 
1113
        window->minimizedSetEnabled (this, true);
 
1114
    }
 
1115
}
 
1116
 
 
1117
 
 
1118
WorkaroundsWindow::~WorkaroundsWindow ()
 
1119
{
 
1120
    WORKAROUNDS_SCREEN (screen);
 
1121
 
 
1122
    /* It is not safe to loop the whole window list at this point
 
1123
     * to _also_ unminimize transient windows because this could
 
1124
     * be the plugin tear-down stage and other WorkaroundWindow
 
1125
     * structures could be destroyed.
 
1126
     *
 
1127
     * It is ok to skip transients in this case, since it is likely
 
1128
     * that we will be unminimizing every single window as
 
1129
     * WorkaroundsWindow is destroyed (in the case that the window
 
1130
     * itself has been destroyed while the plugin is enabled, this
 
1131
     * is not much of a problem since the transient windows go with
 
1132
     * the destroyed window in this case)
 
1133
     *
 
1134
     * FIXME: We need a ::fini stage before we do this!
 
1135
     */
 
1136
    ws->skipTransients = true;
 
1137
 
 
1138
    if (isMinimized)
 
1139
    {
 
1140
        unminimize ();
 
1141
        window->minimizeSetEnabled (this, false);
 
1142
        window->unminimizeSetEnabled (this, false);
 
1143
        window->minimizedSetEnabled (this, false);
 
1144
        window->minimize ();
 
1145
    }
 
1146
 
 
1147
    if (!window->destroyed ())
 
1148
    {
 
1149
        if (adjustedWinType)
 
1150
        {
 
1151
            window->wmType () = oldWmType;
 
1152
            window->recalcType ();
 
1153
            window->recalcActions ();
 
1154
        }
 
1155
 
 
1156
        if (window->state () & CompWindowStateStickyMask && madeSticky)
 
1157
        {
 
1158
            window->state () &= ~CompWindowStateStickyMask;
 
1159
        }
 
1160
    }
 
1161
 
 
1162
    ws->skipTransients = false;
 
1163
}
 
1164
 
 
1165
bool
 
1166
WorkaroundsPluginVTable::init ()
 
1167
{
 
1168
    if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION))
 
1169
        return false;
 
1170
 
 
1171
    if ((CompPlugin::checkPluginABI ("composite", COMPIZ_COMPOSITE_ABI)) &&
 
1172
        (CompPlugin::checkPluginABI ("opengl", COMPIZ_OPENGL_ABI)))
 
1173
        haveOpenGL = true;
 
1174
    else
 
1175
        haveOpenGL = false;
 
1176
 
 
1177
    return true;
 
1178
}