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

« back to all changes in this revision

Viewing changes to winrules/src/winrules.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
 * winrules plugin for compiz
 
3
 *
 
4
 * Copyright (C) 2007 Bellegarde Cedric (gnumdk (at) gmail.com)
 
5
 * This program is free software; you can redistribute it and/or
 
6
 * modify it under the terms of the GNU General Public License
 
7
 * as published by the Free Software Foundation; either version 2
 
8
 * of the License, or (at your option) any later version.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 * GNU General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License
 
16
 * along with this program; if not, write to the
 
17
 * Free Software Foundation, Inc.,
 
18
 * 51 Franklin Street, Fifth Floor,
 
19
 * Boston, MA  02110-1301, USA.
 
20
 */
 
21
 
 
22
#include "winrules.h"
 
23
 
 
24
COMPIZ_PLUGIN_20090315 (winrules, WinrulesPluginVTable);
 
25
 
 
26
void
 
27
WinrulesScreen::setProtocols (unsigned int protocols,
 
28
                              Window       id)
 
29
{
 
30
    Atom protocol[4];
 
31
    int  count = 0;
 
32
 
 
33
    if (protocols & CompWindowProtocolDeleteMask)
 
34
        protocol[count++] = Atoms::wmDeleteWindow;
 
35
    if (protocols & CompWindowProtocolTakeFocusMask)
 
36
        protocol[count++] = Atoms::wmTakeFocus;
 
37
    if (protocols & CompWindowProtocolPingMask)
 
38
        protocol[count++] = Atoms::wmPing;
 
39
    if (protocols & CompWindowProtocolSyncRequestMask)
 
40
        protocol[count++] = Atoms::wmSyncRequest;
 
41
 
 
42
    XSetWMProtocols (screen->dpy (), id, protocol, count);
 
43
}
 
44
 
 
45
bool
 
46
WinrulesWindow::is ()
 
47
{
 
48
    if (window->overrideRedirect ())
 
49
        return false;
 
50
 
 
51
    if (window->wmType () & CompWindowTypeDesktopMask)
 
52
        return false;
 
53
 
 
54
    return true;
 
55
}
 
56
 
 
57
bool
 
58
WinrulesWindow::isFocussable ()
 
59
{
 
60
    window->isFocussable ();
 
61
 
 
62
    return false; // We only want to return false else where we are not wrapped
 
63
}
 
64
 
 
65
bool
 
66
WinrulesWindow::focus ()
 
67
{
 
68
    window->focus ();
 
69
 
 
70
    return false; // We only want to return false for the window we are wrapped
 
71
}
 
72
 
 
73
bool
 
74
WinrulesWindow::alpha ()
 
75
{
 
76
    window->alpha ();
 
77
 
 
78
    return false; // We only want to return false else where we are not wrapped
 
79
}
 
80
 
 
81
void
 
82
WinrulesWindow::setNoFocus (int        optNum)
 
83
{
 
84
    unsigned int newProtocol = window->protocols ();
 
85
 
 
86
    WINRULES_SCREEN (screen);
 
87
 
 
88
    if (!is ())
 
89
        return;
 
90
 
 
91
    if (ws->getOptions ().at (optNum). value ().match ().evaluate (window))
 
92
    {
 
93
        if (window->protocols () & CompWindowProtocolTakeFocusMask)
 
94
        {
 
95
            protocolSetMask |= (window->protocols () &
 
96
                                CompWindowProtocolTakeFocusMask);
 
97
            newProtocol = window->protocols () & ~CompWindowProtocolTakeFocusMask;
 
98
        }
 
99
        window->isFocussableSetEnabled (this, true);// causes w->isFocussable ()
 
100
                                                    // to return false
 
101
        window->focusSetEnabled (this, true); // causes w->focus () to return
 
102
                                              // false for this window
 
103
    }
 
104
    else if ((protocolSetMask & CompWindowProtocolTakeFocusMask))
 
105
    {
 
106
        newProtocol = window->protocols () |
 
107
                      (protocolSetMask & CompWindowProtocolTakeFocusMask);
 
108
        protocolSetMask &= ~CompWindowProtocolTakeFocusMask;
 
109
        window->isFocussableSetEnabled (this, false);
 
110
        window->focusSetEnabled (this, false);
 
111
    }
 
112
 
 
113
    if (newProtocol != window->protocols ())
 
114
    {
 
115
        ws->setProtocols (newProtocol, window->id ());
 
116
    }
 
117
}
 
118
 
 
119
void
 
120
WinrulesWindow::setNoAlpha (int        optNum)
 
121
{
 
122
    WINRULES_SCREEN (screen);
 
123
 
 
124
    if (!is ())
 
125
        return;
 
126
 
 
127
    if (ws->getOptions ().at (optNum). value ().match ().evaluate (window))
 
128
    {
 
129
        window->alphaSetEnabled (this, true); // Causes w->alpha () to return
 
130
                                              // false
 
131
    }
 
132
    else
 
133
    {
 
134
        window->alphaSetEnabled (this, false);
 
135
    }
 
136
}
 
137
 
 
138
void
 
139
WinrulesWindow::updateState (int        optNum,
 
140
                             int        mask)
 
141
{
 
142
    unsigned int newState = window->state ();
 
143
 
 
144
    WINRULES_SCREEN (screen);
 
145
 
 
146
    if (!is ())
 
147
        return;
 
148
 
 
149
    if (ws->getOptions ().at (optNum). value ().match ().evaluate (window))
 
150
    {
 
151
        newState |= mask;
 
152
        newState = window->constrainWindowState (newState, window->actions ());
 
153
        stateSetMask |= (newState & mask);
 
154
    }
 
155
    else if (stateSetMask & mask)
 
156
    {
 
157
        newState &= ~mask;
 
158
        stateSetMask &= ~mask;
 
159
    }
 
160
 
 
161
    if (newState != window->state ())
 
162
    {
 
163
        window->changeState (newState);
 
164
 
 
165
        if (mask & (CompWindowStateFullscreenMask |
 
166
                    CompWindowStateAboveMask      |
 
167
                    CompWindowStateBelowMask       ))
 
168
            window->updateAttributes (CompStackingUpdateModeNormal);
 
169
        else
 
170
            window->updateAttributes (CompStackingUpdateModeNone);
 
171
    }
 
172
}
 
173
 
 
174
void
 
175
WinrulesWindow::setAllowedActions (int        optNum,
 
176
                                  int        action)
 
177
{
 
178
    WINRULES_SCREEN (screen);
 
179
 
 
180
    if (!is ())
 
181
        return;
 
182
 
 
183
    if (ws->getOptions ().at (optNum). value ().match ().evaluate (window))
 
184
        allowedActions &= ~action;
 
185
    else if (!(allowedActions & action))
 
186
        allowedActions |= action;
 
187
 
 
188
    window->recalcActions ();
 
189
}
 
190
 
 
191
bool
 
192
WinrulesWindow::matchSizeValue (CompOption::Value::Vector matches,
 
193
                                CompOption::Value::Vector widthValues,
 
194
                                CompOption::Value::Vector heightValues,
 
195
                                int        *width,
 
196
                                int        *height)
 
197
{
 
198
    int min;
 
199
 
 
200
    if (!is ())
 
201
        return false;
 
202
 
 
203
    if (window->type () & CompWindowTypeDesktopMask)
 
204
        return false;
 
205
 
 
206
    min = MIN (matches.size (), widthValues.size ());
 
207
    min = MIN ((unsigned int) min, heightValues.size ());
 
208
    min = MIN ((unsigned int) min, matches.size ());
 
209
 
 
210
    for (int i = 0; i < min; i++)
 
211
    {
 
212
        if ((matches.at (i).match ().evaluate (window)))
 
213
        {
 
214
            *width = widthValues.at (i).i ();
 
215
            *height = heightValues.at (i).i ();
 
216
        
 
217
            return true;
 
218
        }
 
219
    }
 
220
 
 
221
    return false;
 
222
}
 
223
 
 
224
bool
 
225
WinrulesWindow::matchSize (int        *width,
 
226
                           int        *height)
 
227
{
 
228
    WINRULES_SCREEN (screen);
 
229
 
 
230
    return matchSizeValue (ws->optionGetSizeMatches (),
 
231
                           ws->optionGetSizeWidthValues (),
 
232
                           ws->optionGetSizeHeightValues (),
 
233
                           width, height);
 
234
}
 
235
 
 
236
void
 
237
WinrulesWindow::updateWindowSize (int        width,
 
238
                                  int        height)
 
239
{
 
240
    XWindowChanges xwc;
 
241
    unsigned int   xwcm = 0;
 
242
 
 
243
    if (width != window->serverWidth ())
 
244
        xwcm |= CWWidth;
 
245
    if (height != window->serverHeight ())
 
246
        xwcm |= CWHeight;
 
247
 
 
248
    xwc.width = width;
 
249
    xwc.height = height;
 
250
 
 
251
    if (window->mapNum () && xwcm)
 
252
        window->sendSyncRequest ();
 
253
 
 
254
    window->configureXWindow (xwcm, &xwc);
 
255
}
 
256
 
 
257
void
 
258
WinrulesScreen::optionChanged (CompOption              *option,
 
259
                               WinrulesOptions::Options num)
 
260
{
 
261
 
 
262
    unsigned int updateStateMask = 0, updateActionsMask = 0;
 
263
 
 
264
    switch (num)
 
265
    {
 
266
        case WinrulesOptions::SkiptaskbarMatch:
 
267
            updateStateMask = CompWindowStateSkipTaskbarMask;
 
268
            break;
 
269
        case WinrulesOptions::SkippagerMatch:
 
270
            updateStateMask = CompWindowStateSkipPagerMask;
 
271
            break;
 
272
        case WinrulesOptions::AboveMatch:
 
273
            updateStateMask = CompWindowStateAboveMask;
 
274
        break;
 
275
        case WinrulesOptions::BelowMatch:
 
276
            updateStateMask = CompWindowStateBelowMask;
 
277
        break;
 
278
        case WinrulesOptions::StickyMatch:
 
279
            updateStateMask = CompWindowStateStickyMask;
 
280
        break;
 
281
        case WinrulesOptions::FullscreenMatch:
 
282
            updateStateMask = CompWindowStateFullscreenMask;
 
283
        break;
 
284
        case WinrulesOptions::MaximizeMatch:
 
285
            updateStateMask = CompWindowStateMaximizedHorzMask |
 
286
                              CompWindowStateMaximizedVertMask;
 
287
        break;
 
288
        case WinrulesOptions::NoMoveMatch:
 
289
            updateActionsMask = CompWindowActionMoveMask;
 
290
        break;
 
291
        case WinrulesOptions::NoResizeMatch:
 
292
            updateActionsMask = CompWindowActionResizeMask;
 
293
        break;
 
294
        case WinrulesOptions::NoMinimizeMatch:
 
295
            updateActionsMask = CompWindowActionMinimizeMask;
 
296
        break;
 
297
        case WinrulesOptions::NoMaximizeMatch:
 
298
            updateActionsMask = CompWindowActionMaximizeVertMask |
 
299
                                CompWindowActionMaximizeHorzMask;
 
300
        break;
 
301
        case WinrulesOptions::NoCloseMatch:
 
302
            updateActionsMask = CompWindowActionCloseMask;
 
303
        break;
 
304
        case WinrulesOptions::NoArgbMatch:
 
305
            foreach (CompWindow *w, screen->windows ())
 
306
            {
 
307
                WINRULES_WINDOW (w);
 
308
                ww->setNoAlpha (num);
 
309
            }
 
310
 
 
311
            return;
 
312
        break;
 
313
        case WinrulesOptions::SizeMatches:
 
314
            foreach (CompOption::Value &v, option->value ().list ())
 
315
            {
 
316
                CompMatch &m = v.match ();
 
317
                m.update ();
 
318
            }
 
319
            return;
 
320
        break;
 
321
        default:
 
322
            return;
 
323
        break;
 
324
    }
 
325
 
 
326
    if (updateStateMask)
 
327
    {
 
328
        /* We traverse a copy of the list here because windows can be unhooked
 
329
         * on state change rather than the delayed unhook that happens in <0.8.x
 
330
         */
 
331
 
 
332
        CompWindowList windows = screen->windows ();
 
333
 
 
334
        foreach (CompWindow *w, windows)
 
335
        {
 
336
            WINRULES_WINDOW (w);
 
337
            ww->updateState (num, updateStateMask);
 
338
        }
 
339
 
 
340
        return;
 
341
    }
 
342
 
 
343
    if (updateActionsMask)
 
344
    {
 
345
        foreach (CompWindow *w, screen->windows ())
 
346
        {
 
347
            WINRULES_WINDOW (w);
 
348
            ww->setAllowedActions (num, updateActionsMask);
 
349
        }
 
350
 
 
351
        return;
 
352
    }
 
353
 
 
354
    return;
 
355
}
 
356
 
 
357
 
 
358
bool
 
359
WinrulesWindow::applyRules ()
 
360
{
 
361
    int        width, height;
 
362
 
 
363
    updateState (WinrulesOptions::SkiptaskbarMatch,
 
364
                 CompWindowStateSkipTaskbarMask);
 
365
 
 
366
    updateState (WinrulesOptions::SkippagerMatch,
 
367
                 CompWindowStateSkipPagerMask);
 
368
 
 
369
    updateState (WinrulesOptions::AboveMatch,
 
370
                 CompWindowStateAboveMask);
 
371
 
 
372
    updateState (WinrulesOptions::BelowMatch,
 
373
                 CompWindowStateBelowMask);
 
374
 
 
375
    updateState (WinrulesOptions::StickyMatch,
 
376
                 CompWindowStateStickyMask);
 
377
 
 
378
    updateState (WinrulesOptions::FullscreenMatch,
 
379
                 CompWindowStateFullscreenMask);
 
380
 
 
381
    updateState (WinrulesOptions::MaximizeMatch,
 
382
                 CompWindowStateMaximizedHorzMask |
 
383
                 CompWindowStateMaximizedVertMask);
 
384
 
 
385
    setAllowedActions (WinrulesOptions::NoMoveMatch,
 
386
                       CompWindowActionMoveMask);
 
387
 
 
388
    setAllowedActions (WinrulesOptions::NoResizeMatch,
 
389
                       CompWindowActionResizeMask);
 
390
 
 
391
    setAllowedActions (WinrulesOptions::NoMinimizeMatch,
 
392
                       CompWindowActionMinimizeMask);
 
393
 
 
394
    setAllowedActions (WinrulesOptions::NoMaximizeMatch,
 
395
                       CompWindowActionMaximizeVertMask |
 
396
                       CompWindowActionMaximizeHorzMask);
 
397
 
 
398
    setAllowedActions (WinrulesOptions::NoCloseMatch,
 
399
                       CompWindowActionCloseMask);
 
400
 
 
401
    setNoAlpha (WinrulesOptions::NoArgbMatch);
 
402
 
 
403
    if (matchSize (&width, &height))
 
404
        updateWindowSize (width, height);
 
405
 
 
406
    return false;
 
407
}
 
408
 
 
409
 
 
410
void
 
411
WinrulesScreen::handleEvent (XEvent *event)
 
412
{
 
413
    if (event->type == MapRequest)
 
414
    {
 
415
        CompWindow *w = screen->findWindow (event->xmap.window);
 
416
        if (w)
 
417
        {
 
418
            WINRULES_WINDOW (w);
 
419
            ww->setNoFocus (WinrulesOptions::NoFocusMatch);
 
420
            ww->applyRules ();
 
421
        }
 
422
    }
 
423
 
 
424
    screen->handleEvent (event);
 
425
 
 
426
}
 
427
 
 
428
void
 
429
WinrulesWindow::getAllowedActions (unsigned int &setActions,
 
430
                                   unsigned int &clearActions)
 
431
{
 
432
    window->getAllowedActions (setActions, clearActions);
 
433
 
 
434
    clearActions |= ~allowedActions;
 
435
}
 
436
 
 
437
void
 
438
WinrulesScreen::matchExpHandlerChanged ()
 
439
{
 
440
    screen->matchExpHandlerChanged ();
 
441
 
 
442
    /* match options are up to date after the call to matchExpHandlerChanged */
 
443
    foreach (CompWindow *w, screen->windows ())
 
444
    {
 
445
        WINRULES_WINDOW (w);
 
446
        ww->applyRules ();
 
447
    }
 
448
}
 
449
 
 
450
void
 
451
WinrulesScreen::matchPropertyChanged (CompWindow *w)
 
452
{
 
453
    WINRULES_WINDOW (w);
 
454
 
 
455
    /* Re-apply rules on match property change */
 
456
    ww->applyRules ();
 
457
 
 
458
    screen->matchPropertyChanged (w);
 
459
}
 
460
 
 
461
WinrulesScreen::WinrulesScreen (CompScreen *screen) :
 
462
    PluginClassHandler <WinrulesScreen, CompScreen> (screen)
 
463
{
 
464
    ScreenInterface::setHandler (screen);
 
465
 
 
466
    optionSetSkiptaskbarMatchNotify (boost::bind
 
467
                                        (&WinrulesScreen::optionChanged, this,
 
468
                                         _1, _2));
 
469
 
 
470
    optionSetSkippagerMatchNotify (boost::bind
 
471
                                   (&WinrulesScreen::optionChanged, this,
 
472
                                    _1, _2));
 
473
 
 
474
    optionSetAboveMatchNotify (boost::bind
 
475
                                (&WinrulesScreen::optionChanged, this,
 
476
                                 _1, _2));
 
477
 
 
478
    optionSetBelowMatchNotify (boost::bind
 
479
                                (&WinrulesScreen::optionChanged, this,
 
480
                                 _1, _2));
 
481
 
 
482
    optionSetFullscreenMatchNotify (boost::bind
 
483
                                    (&WinrulesScreen::optionChanged, this,
 
484
                                     _1, _2));
 
485
 
 
486
    optionSetStickyMatchNotify (boost::bind
 
487
                                (&WinrulesScreen::optionChanged, this,
 
488
                                _1, _2));
 
489
 
 
490
    optionSetMaximizeMatchNotify (boost::bind
 
491
                                  (&WinrulesScreen::optionChanged, this,
 
492
                                   _1, _2));
 
493
 
 
494
    optionSetNoArgbMatchNotify (boost::bind
 
495
                                (&WinrulesScreen::optionChanged, this,
 
496
                                 _1, _2));
 
497
 
 
498
    optionSetNoMoveMatchNotify (boost::bind
 
499
                                (&WinrulesScreen::optionChanged, this,
 
500
                                 _1, _2));
 
501
 
 
502
    optionSetNoResizeMatchNotify (boost::bind
 
503
                                  (&WinrulesScreen::optionChanged, this,
 
504
                                   _1, _2));
 
505
 
 
506
    optionSetNoMinimizeMatchNotify (boost::bind
 
507
                                    (&WinrulesScreen::optionChanged, this,
 
508
                                     _1, _2));
 
509
 
 
510
    optionSetNoMaximizeMatchNotify (boost::bind
 
511
                                    (&WinrulesScreen::optionChanged, this,
 
512
                                     _1, _2));
 
513
 
 
514
    optionSetNoCloseMatchNotify (boost::bind
 
515
                                 (&WinrulesScreen::optionChanged, this,
 
516
                                  _1, _2));
 
517
 
 
518
    optionSetNoFocusMatchNotify (boost::bind
 
519
                                 (&WinrulesScreen::optionChanged, this,
 
520
                                  _1, _2));
 
521
 
 
522
}
 
523
 
 
524
WinrulesWindow::WinrulesWindow (CompWindow *window) :
 
525
    PluginClassHandler <WinrulesWindow, CompWindow> (window),
 
526
    window (window),
 
527
    allowedActions (~0),
 
528
    stateSetMask (0),
 
529
    protocolSetMask (0)
 
530
{
 
531
    CompTimer timer;
 
532
 
 
533
    WindowInterface::setHandler (window);
 
534
 
 
535
    window->isFocussableSetEnabled (this, false);
 
536
    window->alphaSetEnabled (this, false);
 
537
    window->focusSetEnabled (this, false);
 
538
 
 
539
    timer.setCallback (boost::bind(&WinrulesWindow::applyRules, this));
 
540
    timer.setTimes (0, 0);
 
541
 
 
542
    timer.start ();
 
543
 
 
544
}
 
545
 
 
546
bool
 
547
WinrulesPluginVTable::init ()
 
548
{
 
549
    if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION))
 
550
        return false;
 
551
 
 
552
    return true;
 
553
}
 
554