~unity-team/compiz/plugins-main-trunk.fix_wrong_window_move_expo

« back to all changes in this revision

Viewing changes to opacify/src/opacify.cpp

  • Committer: David Barth
  • Date: 2011-03-29 16:36:40 UTC
  • Revision ID: david.barth@canonical.com-20110329163640-fpen5qsoo0lbjode
initial import from compiz-plugins-main_0.9.4git20110322.orig.tar.gz

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * Compiz Opacify
 
3
 *
 
4
 * opacify.cpp
 
5
 *
 
6
 * Copyright (c) 2006 Kristian Lyngstøl <kristian@beryl-project.org>
 
7
 * Ported to Compiz and BCOP usage by Danny Baumann <maniac@beryl-project.org>
 
8
 * Ported to Compiz 0.9 by Sam Spilsbury <smspillaz@gmail.com>
 
9
 *
 
10
 * This program is free software; you can redistribute it and/or
 
11
 * modify it under the terms of the GNU General Public License
 
12
 * as published by the Free Software Foundation; either version 2
 
13
 * of the License, or (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
 *
 
21
 * Opacify increases opacity on targeted windows and reduces it on
 
22
 * blocking windows, making whatever window you are targeting easily
 
23
 * visible.
 
24
 *
 
25
 */
 
26
 
 
27
#include "opacify.h"
 
28
 
 
29
COMPIZ_PLUGIN_20090315 (opacify, OpacifyPluginVTable);
 
30
 
 
31
void
 
32
setFunctions (bool enabled)
 
33
{
 
34
    OPACIFY_SCREEN (screen);
 
35
 
 
36
    screen->handleEventSetEnabled (os, enabled);
 
37
 
 
38
    foreach (CompWindow *w, screen->windows ())
 
39
    {
 
40
        OPACIFY_WINDOW (w);
 
41
 
 
42
        ow->gWindow->glPaintSetEnabled (ow, enabled);
 
43
    }
 
44
}
 
45
 
 
46
/* Core opacify functions. These do the real work. ---------------------*/
 
47
 
 
48
/* Sets the real opacity and damages the window if actual opacity and
 
49
 * requested opacity differs. */
 
50
 
 
51
void
 
52
OpacifyWindow::setOpacity (int fOpacity)
 
53
{
 
54
    if (opacified || (gWindow->paintAttrib ().opacity != opacity))
 
55
        cWindow->addDamage ();
 
56
 
 
57
    opacified = true;
 
58
    opacity = fOpacity;
 
59
}
 
60
 
 
61
/* Resets the Window to the original opacity if it still exists.
 
62
*/
 
63
 
 
64
void
 
65
OpacifyScreen::resetOpacity (Window  id)
 
66
{
 
67
    CompWindow *w;
 
68
 
 
69
    w = screen->findWindow (id);
 
70
    if (!w)
 
71
        return;
 
72
 
 
73
    OPACIFY_WINDOW (w);
 
74
 
 
75
    ow->opacified = false;
 
76
    ow->cWindow->addDamage ();
 
77
}
 
78
 
 
79
/* Resets the opacity of windows on the passive list.
 
80
*/
 
81
void
 
82
OpacifyScreen::clearPassive ()
 
83
{
 
84
    passive.clear ();
 
85
}
 
86
 
 
87
/* Dim an (inactive) window. Place it on the passive list and
 
88
 * update passiveNum. Then change the opacity.
 
89
 */
 
90
 
 
91
void
 
92
OpacifyWindow::dim ()
 
93
{
 
94
    OPACIFY_SCREEN (screen);
 
95
 
 
96
    os->passive.push_back (window->id ());
 
97
 
 
98
    setOpacity (MIN (OPAQUE * os->optionGetPassiveOpacity () / 100,
 
99
                     gWindow->paintAttrib ().opacity));
 
100
}
 
101
 
 
102
/* Walk through all windows, skip until we've passed the active
 
103
 * window, skip if it's invisible, hidden or minimized, skip if
 
104
 * it's not a window type we're looking for.
 
105
 * Dim it if it intersects.
 
106
 *
 
107
 * Returns number of changed windows.
 
108
 */
 
109
 
 
110
int
 
111
OpacifyScreen::passiveWindows (CompRegion     fRegion)
 
112
{
 
113
    bool       flag = false;
 
114
    int        i = 0;
 
115
 
 
116
    /* Clear the list first to prevent memleaks */
 
117
    foreach (Window xid, passive)
 
118
    {
 
119
        CompWindow *win = screen->findWindow (xid);
 
120
 
 
121
        if (!win)
 
122
            continue;
 
123
 
 
124
        OPACIFY_WINDOW (win);
 
125
 
 
126
        resetOpacity (xid);
 
127
        ow->setOpacity (MAX (OPAQUE * optionGetActiveOpacity () / 100,
 
128
                        ow->gWindow->paintAttrib ().opacity));
 
129
    }
 
130
    passive.clear ();
 
131
 
 
132
    foreach (CompWindow *w, screen->windows ())
 
133
    {
 
134
        if (w->id () == active)
 
135
        {
 
136
            flag = true;
 
137
            continue;
 
138
        }
 
139
        if (!flag)
 
140
            continue;
 
141
        if (!optionGetWindowMatch ().evaluate (w))
 
142
            continue;
 
143
        if (!w->isViewable () || w->minimized ())
 
144
            continue;
 
145
 
 
146
        intersect = w->region ().intersected (fRegion);
 
147
        if (!intersect.isEmpty ())
 
148
        {
 
149
            OpacifyWindow::get (w)->dim ();
 
150
            i++;
 
151
        }
 
152
    }
 
153
 
 
154
    return i;
 
155
}
 
156
 
 
157
/* Check if we switched active window, reset the old passive windows
 
158
 * if we did. If we have an active window and switched: reset that too.
 
159
 * If we have a window (w is true), update the active id and
 
160
 * passive list. justMoved is to make sure we recalculate opacity after
 
161
 * moving. We can't reset before moving because if we're using a delay
 
162
 * and the window being moved is not the active but overlapping, it will
 
163
 * be reset, which would conflict with move's opacity change.
 
164
 */
 
165
void
 
166
OpacifyWindow::handleEnter ()
 
167
{
 
168
    OPACIFY_SCREEN (screen);
 
169
 
 
170
    if (screen->otherGrabExist (NULL))
 
171
    {
 
172
        if (!screen->otherGrabExist ("move", NULL))
 
173
        {
 
174
            os->justMoved = true;
 
175
            return;
 
176
        }
 
177
 
 
178
        os->clearPassive ();
 
179
        os->resetOpacity (os->active);
 
180
        os->active = 0;
 
181
        return;
 
182
    }
 
183
 
 
184
    if (!window || os->active != window->id () || os->justMoved)
 
185
    {
 
186
        os->justMoved = false;
 
187
        os->resetOpacity (os->active);
 
188
        os->active = 0;
 
189
    }
 
190
 
 
191
    if (!window)
 
192
        return;
 
193
 
 
194
    if (window->id () != os->active && !window->shaded () &&
 
195
        os->optionGetWindowMatch ().evaluate (window))
 
196
    {
 
197
        int num;
 
198
 
 
199
        os->active = window->id ();
 
200
        num = os->passiveWindows (window->region ());
 
201
 
 
202
        if (num || os->optionGetOnlyIfBlock ())
 
203
            setOpacity (MAX (OPAQUE * os->optionGetActiveOpacity () / 100,
 
204
                                gWindow->paintAttrib ().opacity));
 
205
    }
 
206
}
 
207
 
 
208
/* Timeout-time! Unset the timeout handler, make sure we're on the same
 
209
 * screen, handle the event.
 
210
 */
 
211
bool
 
212
OpacifyScreen::handleTimeout ()
 
213
{
 
214
    if (newActive)
 
215
        OpacifyWindow::get (newActive)->handleEnter ();
 
216
 
 
217
    return false;
 
218
}
 
219
 
 
220
/* Checks whether we should delay or not.
 
221
 * Returns true if immediate execution.
 
222
 */
 
223
bool
 
224
OpacifyScreen::checkDelay ()
 
225
{
 
226
    if (optionGetFocusInstant () && newActive &&
 
227
        (newActive->id () == screen->activeWindow ()))
 
228
        return true;
 
229
    if (!optionGetTimeout ())
 
230
        return true;
 
231
    if (!newActive || (newActive->id () == screen->root ()))
 
232
        return false;
 
233
    if (newActive->type () & (CompWindowTypeDesktopMask |
 
234
                              CompWindowTypeDockMask))
 
235
    {
 
236
        return false;
 
237
    }
 
238
    if (optionGetNoDelayChange () && passive.size ())
 
239
        return true;
 
240
 
 
241
    return false;
 
242
}
 
243
 
 
244
bool
 
245
OpacifyWindow::glPaint (const GLWindowPaintAttrib &attrib,
 
246
                        const GLMatrix            &transform,
 
247
                        const CompRegion          &region,
 
248
                        unsigned int              mask)
 
249
{
 
250
    if (opacified)
 
251
    {
 
252
        GLWindowPaintAttrib wAttrib = attrib;
 
253
 
 
254
        wAttrib.opacity = opacity;
 
255
 
 
256
        return gWindow->glPaint (wAttrib, transform, region, mask);
 
257
    }
 
258
    else
 
259
    {
 
260
        return gWindow->glPaint (attrib, transform, region, mask);
 
261
    }
 
262
 
 
263
    return false;
 
264
}
 
265
 
 
266
/* Takes the inital event.
 
267
 * If we were configured, recalculate the opacify-windows if
 
268
 * it was our window.
 
269
 * If a window was entered: call upon handle_timeout after od->timeout
 
270
 * micro seconds, or directly if od->timeout is 0 (no delay).
 
271
 *
 
272
 */
 
273
 
 
274
void
 
275
OpacifyScreen::handleEvent (XEvent *event)
 
276
{
 
277
 
 
278
    screen->handleEvent (event);
 
279
 
 
280
    if (!isToggle)
 
281
        return;
 
282
 
 
283
    switch (event->type) {
 
284
    case EnterNotify:
 
285
        Window id;
 
286
 
 
287
        id = event->xcrossing.window;
 
288
            newActive = screen->findTopLevelWindow (id);
 
289
 
 
290
        if (timeoutHandle.active ())
 
291
            timeoutHandle.stop ();
 
292
 
 
293
        if (checkDelay ())
 
294
            handleTimeout ();
 
295
        else
 
296
            timeoutHandle.start ();
 
297
        break;
 
298
    case ConfigureNotify:
 
299
 
 
300
        if (active != event->xconfigure.window)
 
301
            break;
 
302
 
 
303
        clearPassive ();
 
304
        if (active)
 
305
        {
 
306
            CompWindow *w;
 
307
 
 
308
            w = screen->findWindow (active);
 
309
            if (w)
 
310
                passiveWindows (w->region ());
 
311
        }
 
312
        break;
 
313
    default:
 
314
        break;
 
315
    }
 
316
}
 
317
 
 
318
/* Toggle opacify on/off. We are in Display-context, make sure we handle all
 
319
 * screens.
 
320
 */
 
321
 
 
322
bool
 
323
OpacifyScreen::toggle (CompAction         *action,
 
324
                       CompAction::State  state,
 
325
                       CompOption::Vector options)
 
326
{
 
327
    isToggle = !isToggle;
 
328
    if (!isToggle && optionGetToggleReset ())
 
329
    {
 
330
        if (active)
 
331
        {
 
332
            clearPassive ();
 
333
            resetOpacity (active);
 
334
            active = 0;
 
335
        }
 
336
    }
 
337
 
 
338
    setFunctions (isToggle);
 
339
 
 
340
    return true;
 
341
}
 
342
 
 
343
/* Configuration, initialization, boring stuff. ----------------------- */
 
344
 
 
345
/** This is called when an option changes. The only option we are looking for
 
346
 *  here is 'init_toggle' so when that changes, we adjust our internal values
 
347
 *  appropriately
 
348
 */
 
349
 
 
350
void
 
351
OpacifyScreen::optionChanged (CompOption              *option,
 
352
                              OpacifyOptions::Options num)
 
353
{
 
354
    switch (num) {
 
355
    case OpacifyOptions::InitToggle:
 
356
        isToggle = option->value ().b ();
 
357
        setFunctions (isToggle);
 
358
        if (active)
 
359
        {
 
360
            clearPassive ();
 
361
            resetOpacity (active);
 
362
            active = 0;
 
363
        }
 
364
        break;
 
365
    default:
 
366
        break;
 
367
    }
 
368
}
 
369
 
 
370
/** Constructor for OpacifyWindow. This is called whenever a new window
 
371
 *  is created and we set our custom variables to it and also register to
 
372
 *  paint this window
 
373
 */
 
374
 
 
375
OpacifyWindow::OpacifyWindow (CompWindow *window) :
 
376
    PluginClassHandler <OpacifyWindow, CompWindow> (window),
 
377
    window (window),
 
378
    cWindow (CompositeWindow::get (window)),
 
379
    gWindow (GLWindow::get (window)),
 
380
    opacified (false),
 
381
    opacity (100)
 
382
{
 
383
    GLWindowInterface::setHandler (gWindow, false);
 
384
}
 
385
 
 
386
void
 
387
OpacifyScreen::postLoad ()
 
388
{
 
389
    setFunctions (isToggle);
 
390
}
 
391
 
 
392
/** Constructor for OpacifyScreen. This is called whenever a new screen
 
393
 *  is created and we set our custom variables to it and also register to
 
394
 *  handle X.org events when they come through
 
395
 */
 
396
 
 
397
OpacifyScreen::OpacifyScreen (CompScreen *screen) :
 
398
    PluginClassHandler <OpacifyScreen, CompScreen> (screen),
 
399
    PluginStateWriter <OpacifyScreen> (this, screen->root ()),
 
400
    isToggle (false),
 
401
    newActive (NULL),
 
402
    active (screen->activeWindow ()),
 
403
    intersect (emptyRegion),
 
404
    justMoved (false)
 
405
{
 
406
    ScreenInterface::setHandler (screen, false);
 
407
 
 
408
    timeoutHandle.setTimes (optionGetTimeout (), optionGetTimeout () * 1.2);
 
409
    timeoutHandle.setCallback (boost::bind (&OpacifyScreen::handleTimeout,
 
410
                                                                         this));
 
411
 
 
412
    optionSetToggleKeyInitiate (boost::bind (&OpacifyScreen::toggle, this, _1,
 
413
                                                                       _2, _3));
 
414
    optionSetInitToggleNotify (boost::bind (&OpacifyScreen::optionChanged,
 
415
                                                                 this, _1, _2));
 
416
}
 
417
 
 
418
OpacifyScreen::~OpacifyScreen ()
 
419
{
 
420
    writeSerializedData ();
 
421
}
 
422
 
 
423
bool
 
424
OpacifyPluginVTable::init ()
 
425
{
 
426
    if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION))
 
427
        return false;
 
428
    if (!CompPlugin::checkPluginABI ("composite", COMPIZ_COMPOSITE_ABI))
 
429
        return false;
 
430
    if (!CompPlugin::checkPluginABI ("opengl", COMPIZ_OPENGL_ABI))
 
431
        return false;
 
432
 
 
433
 
 
434
    return true;
 
435
}