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

« back to all changes in this revision

Viewing changes to .pc/09_git_valgrind_cleanage.patch/src/screen.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Didier Roche
  • Date: 2011-02-24 17:31:29 UTC
  • mfrom: (0.167.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20110224173129-hsczyk7yw7s21flf
Tags: 1:0.9.4-0ubuntu1
* New upstream release:
  - Fix no windows receiving the focus if someone got the focus then was
    destroyed
  - Fix crash when resizing using keybindings
  - Fix unresponsive inactive decorations (LP: #703755) 
  - Fix the long awaited gconf crash (LP: #691561)
  - gtk-window-decorator doesn't respect special decoration styles
    (LP: #290835)
* debian/compiz-core.links,
  debian/source_compiz.py,
  debian/compiz-core.install:
  - install again a richer apport hook to redirect nux/libunity/unityshell
    crash. It also asks the user to redirect unity issues against unity (still
    incuding xorg info when needed)
* Removed a bunch of patches either cherry-picked or pushed upstream. With the
  other fixes, the gconf workaround is hopefully not needed anymore.
* refresh existing patches to still apply
* debian/control:
  - rename dep on compiz-fusion* to compiz*
* debian/patches/085_add_grid_plugin.patch:
  - refresh the grid plugin from new release
* debian/patches/086_new_grid_defaults.patch
  - separate tweaking the default settings to only have the effect that were
    specified:
    top -> maximize, left (top or bottom left) -> window half left of the
    screen, right (top or bottom right) -> window half right of the screen,
    bottom -> do nothing

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 SPECI<<<<<fAL, 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
 
#ifdef HAVE_CONFIG_H
27
 
#  include <config.h>
28
 
#endif
29
 
 
30
 
#include <stdio.h>
31
 
#include <stdlib.h>
32
 
#include <stdarg.h>
33
 
#include <math.h>
34
 
#include <dlfcn.h>
35
 
#include <string.h>
36
 
#include <sys/types.h>
37
 
#include <sys/time.h>
38
 
#include <unistd.h>
39
 
#include <assert.h>
40
 
#include <limits.h>
41
 
#include <poll.h>
42
 
#include <algorithm>
43
 
 
44
 
#include <boost/bind.hpp>
45
 
#include <boost/foreach.hpp>
46
 
#define foreach BOOST_FOREACH
47
 
 
48
 
#include <X11/Xlib.h>
49
 
#include <X11/Xatom.h>
50
 
#include <X11/Xproto.h>
51
 
#include <X11/extensions/Xrandr.h>
52
 
#include <X11/extensions/shape.h>
53
 
#include <X11/cursorfont.h>
54
 
 
55
 
#include <core/core.h>
56
 
 
57
 
#include <core/screen.h>
58
 
#include <core/icon.h>
59
 
#include <core/atoms.h>
60
 
#include "privatescreen.h"
61
 
#include "privatewindow.h"
62
 
#include "privateaction.h"
63
 
 
64
 
bool inHandleEvent = false;
65
 
 
66
 
bool screenInitalized = false;
67
 
 
68
 
CompScreen *targetScreen = NULL;
69
 
CompOutput *targetOutput;
70
 
 
71
 
int lastPointerX = 0;
72
 
int lastPointerY = 0;
73
 
int pointerX     = 0;
74
 
int pointerY     = 0;
75
 
 
76
 
#define MwmHintsFunctions   (1L << 0)
77
 
#define MwmHintsDecorations (1L << 1)
78
 
#define PropMotifWmHintElements 3
79
 
 
80
 
typedef struct {
81
 
    unsigned long flags;
82
 
    unsigned long functions;
83
 
    unsigned long decorations;
84
 
} MwmHints;
85
 
 
86
 
 
87
 
 
88
 
CompScreen *screen;
89
 
ModifierHandler *modHandler;
90
 
 
91
 
PluginClassStorage::Indices screenPluginClassIndices (0);
92
 
 
93
 
unsigned int
94
 
CompScreen::allocPluginClassIndex ()
95
 
{
96
 
    unsigned int i = PluginClassStorage::allocatePluginClassIndex (screenPluginClassIndices);
97
 
 
98
 
    if (screenPluginClassIndices.size () != screen->pluginClasses.size ())
99
 
        screen->pluginClasses.resize (screenPluginClassIndices.size ());
100
 
 
101
 
    return i;
102
 
}
103
 
 
104
 
void
105
 
CompScreen::freePluginClassIndex (unsigned int index)
106
 
{
107
 
    PluginClassStorage::freePluginClassIndex (screenPluginClassIndices, index);
108
 
 
109
 
    if (screenPluginClassIndices.size () != screen->pluginClasses.size ())
110
 
        screen->pluginClasses.resize (screenPluginClassIndices.size ());
111
 
}
112
 
 
113
 
void
114
 
CompScreen::eventLoop ()
115
 
{
116
 
    priv->ctx = Glib::MainContext::get_default ();
117
 
    priv->mainloop = Glib::MainLoop::create (priv->ctx, false);
118
 
    priv->source = CompEventSource::create ();
119
 
    priv->timeout = CompTimeoutSource::create ();
120
 
 
121
 
    priv->source->attach (priv->ctx);
122
 
 
123
 
    /* Kick the event loop */
124
 
    priv->ctx->iteration (false);
125
 
 
126
 
    priv->mainloop->run ();
127
 
}
128
 
 
129
 
CompFileWatchHandle
130
 
CompScreen::addFileWatch (const char        *path,
131
 
                          int               mask,
132
 
                          FileWatchCallBack callBack)
133
 
{
134
 
    CompFileWatch *fileWatch = new CompFileWatch ();
135
 
    if (!fileWatch)
136
 
        return 0;
137
 
 
138
 
    fileWatch->path     = path;
139
 
    fileWatch->mask     = mask;
140
 
    fileWatch->callBack = callBack;
141
 
    fileWatch->handle   = priv->lastFileWatchHandle++;
142
 
 
143
 
    if (priv->lastFileWatchHandle == MAXSHORT)
144
 
        priv->lastFileWatchHandle = 1;
145
 
 
146
 
    priv->fileWatch.push_front (fileWatch);
147
 
 
148
 
    fileWatchAdded (fileWatch);
149
 
 
150
 
    return fileWatch->handle;
151
 
}
152
 
 
153
 
void
154
 
CompScreen::removeFileWatch (CompFileWatchHandle handle)
155
 
{
156
 
    std::list<CompFileWatch *>::iterator it;
157
 
    CompFileWatch                        *w;
158
 
 
159
 
    for (it = priv->fileWatch.begin (); it != priv->fileWatch.end (); it++)
160
 
        if ((*it)->handle == handle)
161
 
            break;
162
 
 
163
 
    if (it == priv->fileWatch.end ())
164
 
        return;
165
 
 
166
 
    w = (*it);
167
 
    priv->fileWatch.erase (it);
168
 
 
169
 
    fileWatchRemoved (w);
170
 
 
171
 
    delete w;
172
 
}
173
 
 
174
 
const CompFileWatchList &
175
 
CompScreen::getFileWatches () const
176
 
{
177
 
    return priv->fileWatch;
178
 
}
179
 
 
180
 
void
181
 
PrivateScreen::addTimer (CompTimer *timer)
182
 
{
183
 
    std::list<CompTimer *>::iterator it;
184
 
 
185
 
    it = std::find (timers.begin (), timers.end (), timer);
186
 
 
187
 
    if (it != timers.end ())
188
 
        return;
189
 
 
190
 
    for (it = timers.begin (); it != timers.end (); it++)
191
 
    {
192
 
        if ((int) timer->mMinTime < (*it)->mMinLeft)
193
 
            break;
194
 
    }
195
 
 
196
 
    timer->mMinLeft = timer->mMinTime;
197
 
    timer->mMaxLeft = timer->mMaxTime;
198
 
 
199
 
    timers.insert (it, timer);
200
 
}
201
 
 
202
 
void
203
 
PrivateScreen::removeTimer (CompTimer *timer)
204
 
{
205
 
    std::list<CompTimer *>::iterator it;
206
 
 
207
 
    it = std::find (timers.begin (), timers.end (), timer);
208
 
 
209
 
    if (it == timers.end ())
210
 
        return;
211
 
 
212
 
    timers.erase (it);
213
 
}
214
 
 
215
 
CompWatchFd::CompWatchFd (int               fd,
216
 
                          Glib::IOCondition events,
217
 
                          FdWatchCallBack   callback) :
218
 
    Glib::IOSource (fd, events),
219
 
    mFd (fd),
220
 
    mCallBack (callback),
221
 
    mForceFail (false),
222
 
    mExecuting (false)
223
 
{
224
 
    connect (sigc::mem_fun <Glib::IOCondition, bool>
225
 
             (this, &CompWatchFd::internalCallback));
226
 
}
227
 
 
228
 
Glib::RefPtr <CompWatchFd>
229
 
CompWatchFd::create (int               fd,
230
 
                     Glib::IOCondition events,
231
 
                     FdWatchCallBack   callback)
232
 
{
233
 
    return Glib::RefPtr <CompWatchFd> (new CompWatchFd (fd, events, callback));
234
 
}
235
 
 
236
 
CompWatchFdHandle
237
 
CompScreen::addWatchFd (int             fd,
238
 
                        short int       events,
239
 
                        FdWatchCallBack callBack)
240
 
{
241
 
    Glib::IOCondition gEvents;
242
 
    
243
 
    memset (&gEvents, 0, sizeof (Glib::IOCondition));
244
 
 
245
 
    if (events & POLLIN)
246
 
        gEvents |= Glib::IO_IN;
247
 
    if (events & POLLOUT)
248
 
        gEvents |= Glib::IO_OUT;
249
 
    if (events & POLLPRI)
250
 
        gEvents |= Glib::IO_PRI;
251
 
    if (events & POLLERR)
252
 
        gEvents |= Glib::IO_ERR;
253
 
    if (events & POLLHUP)
254
 
        gEvents |= Glib::IO_HUP;
255
 
 
256
 
    Glib::RefPtr <CompWatchFd> watchFd = CompWatchFd::create (fd, gEvents, callBack);
257
 
 
258
 
    watchFd->attach (priv->ctx);
259
 
 
260
 
    if (!watchFd)
261
 
        return 0;
262
 
    watchFd->mHandle   = priv->lastWatchFdHandle++;
263
 
 
264
 
    if (priv->lastWatchFdHandle == MAXSHORT)
265
 
        priv->lastWatchFdHandle = 1;
266
 
 
267
 
    priv->watchFds.push_front (watchFd);
268
 
 
269
 
    return watchFd->mHandle;
270
 
}
271
 
 
272
 
void
273
 
CompScreen::removeWatchFd (CompWatchFdHandle handle)
274
 
{
275
 
    std::list<Glib::RefPtr <CompWatchFd> >::iterator it;
276
 
    Glib::RefPtr <CompWatchFd>         w;
277
 
 
278
 
    for (it = priv->watchFds.begin();
279
 
         it != priv->watchFds.end (); it++)
280
 
    {
281
 
        if ((*it)->mHandle == handle)
282
 
            break;
283
 
    }
284
 
 
285
 
    if (it == priv->watchFds.end ())
286
 
        return;
287
 
 
288
 
    w = (*it);
289
 
 
290
 
    if (w->mExecuting)
291
 
    {
292
 
        w->mForceFail = true;
293
 
        return;
294
 
    }
295
 
 
296
 
    w.reset ();
297
 
    priv->watchFds.erase (it);
298
 
}
299
 
 
300
 
void
301
 
CompScreen::storeValue (CompString key, CompPrivate value)
302
 
{
303
 
    std::map<CompString,CompPrivate>::iterator it;
304
 
 
305
 
    it = priv->valueMap.find (key);
306
 
 
307
 
    if (it != priv->valueMap.end ())
308
 
    {
309
 
        it->second = value;
310
 
    }
311
 
    else
312
 
    {
313
 
        priv->valueMap.insert (std::pair<CompString,CompPrivate> (key, value));
314
 
    }
315
 
}
316
 
 
317
 
bool
318
 
CompScreen::hasValue (CompString key)
319
 
{
320
 
    return (priv->valueMap.find (key) != priv->valueMap.end ());
321
 
}
322
 
 
323
 
CompPrivate
324
 
CompScreen::getValue (CompString key)
325
 
{
326
 
    CompPrivate p;
327
 
 
328
 
    std::map<CompString,CompPrivate>::iterator it;
329
 
    it = priv->valueMap.find (key);
330
 
 
331
 
    if (it != priv->valueMap.end ())
332
 
    {
333
 
        return it->second;
334
 
    }
335
 
    else
336
 
    {
337
 
        p.uval = 0;
338
 
        return p;
339
 
    }
340
 
}
341
 
 
342
 
bool
343
 
CompWatchFd::internalCallback (Glib::IOCondition events)
344
 
{
345
 
    short int revents = 0;
346
 
 
347
 
    if (events & Glib::IO_IN)
348
 
        revents |= POLLIN;
349
 
    if (events & Glib::IO_OUT)
350
 
        revents |= POLLOUT;
351
 
    if (events & Glib::IO_PRI)
352
 
        revents |= POLLPRI;
353
 
    if (events & Glib::IO_ERR)
354
 
        revents |= POLLERR;
355
 
    if (events & Glib::IO_HUP)
356
 
        revents |= POLLHUP;
357
 
    if (events & Glib::IO_NVAL)
358
 
        return false;
359
 
 
360
 
    mExecuting = true;
361
 
    mCallBack (revents);
362
 
    mExecuting = false;
363
 
 
364
 
    if (mForceFail)
365
 
    {
366
 
        /* FIXME: Need to find a way to properly remove the watchFd
367
 
         * from the internal list in core */
368
 
        //screen->priv->watchFds.remove (this);
369
 
        return false;
370
 
    }
371
 
    
372
 
    return true;
373
 
}    
374
 
 
375
 
void
376
 
CompScreen::eraseValue (CompString key)
377
 
{
378
 
    std::map<CompString,CompPrivate>::iterator it;
379
 
    it = priv->valueMap.find (key);
380
 
 
381
 
    if (it != priv->valueMap.end ())
382
 
    {
383
 
        priv->valueMap.erase (key);
384
 
    }
385
 
}
386
 
 
387
 
void
388
 
CompScreen::fileWatchAdded (CompFileWatch *watch)
389
 
    WRAPABLE_HND_FUNC (0, fileWatchAdded, watch)
390
 
 
391
 
void
392
 
CompScreen::fileWatchRemoved (CompFileWatch *watch)
393
 
    WRAPABLE_HND_FUNC (1, fileWatchRemoved, watch)
394
 
 
395
 
bool
396
 
CompScreen::setOptionForPlugin (const char        *plugin,
397
 
                                const char        *name,
398
 
                                CompOption::Value &value)
399
 
{
400
 
    WRAPABLE_HND_FUNC_RETURN (4, bool, setOptionForPlugin,
401
 
                              plugin, name, value)
402
 
 
403
 
    CompPlugin *p = CompPlugin::find (plugin);
404
 
    if (p)
405
 
        return p->vTable->setOption (name, value);
406
 
 
407
 
    return false;
408
 
}
409
 
 
410
 
void
411
 
CompScreen::sessionEvent (CompSession::Event event,
412
 
                          CompOption::Vector &arguments)
413
 
    WRAPABLE_HND_FUNC (5, sessionEvent, event, arguments)
414
 
 
415
 
void
416
 
ScreenInterface::fileWatchAdded (CompFileWatch *watch)
417
 
    WRAPABLE_DEF (fileWatchAdded, watch)
418
 
 
419
 
void
420
 
ScreenInterface::fileWatchRemoved (CompFileWatch *watch)
421
 
    WRAPABLE_DEF (fileWatchRemoved, watch)
422
 
 
423
 
bool
424
 
ScreenInterface::initPluginForScreen (CompPlugin *plugin)
425
 
    WRAPABLE_DEF (initPluginForScreen, plugin)
426
 
 
427
 
void
428
 
ScreenInterface::finiPluginForScreen (CompPlugin *plugin)
429
 
    WRAPABLE_DEF (finiPluginForScreen, plugin)
430
 
 
431
 
bool
432
 
ScreenInterface::setOptionForPlugin (const char        *plugin,
433
 
                                     const char        *name,
434
 
                                     CompOption::Value &value)
435
 
    WRAPABLE_DEF (setOptionForPlugin, plugin, name, value)
436
 
 
437
 
void
438
 
ScreenInterface::sessionEvent (CompSession::Event event,
439
 
                               CompOption::Vector &arguments)
440
 
    WRAPABLE_DEF (sessionEvent, event, arguments)
441
 
 
442
 
 
443
 
static int errors = 0;
444
 
 
445
 
static int
446
 
errorHandler (Display     *dpy,
447
 
              XErrorEvent *e)
448
 
{
449
 
 
450
 
#ifdef DEBUG
451
 
    char str[128];
452
 
#endif
453
 
 
454
 
    errors++;
455
 
 
456
 
#ifdef DEBUG
457
 
    XGetErrorDatabaseText (dpy, "XlibMessage", "XError", "", str, 128);
458
 
    fprintf (stderr, "%s", str);
459
 
 
460
 
    XGetErrorText (dpy, e->error_code, str, 128);
461
 
    fprintf (stderr, ": %s\n  ", str);
462
 
 
463
 
    XGetErrorDatabaseText (dpy, "XlibMessage", "MajorCode", "%d", str, 128);
464
 
    fprintf (stderr, str, e->request_code);
465
 
 
466
 
    sprintf (str, "%d", e->request_code);
467
 
    XGetErrorDatabaseText (dpy, "XRequest", str, "", str, 128);
468
 
    if (strcmp (str, ""))
469
 
        fprintf (stderr, " (%s)", str);
470
 
    fprintf (stderr, "\n  ");
471
 
 
472
 
    XGetErrorDatabaseText (dpy, "XlibMessage", "MinorCode", "%d", str, 128);
473
 
    fprintf (stderr, str, e->minor_code);
474
 
    fprintf (stderr, "\n  ");
475
 
 
476
 
    XGetErrorDatabaseText (dpy, "XlibMessage", "ResourceID", "%d", str, 128);
477
 
    fprintf (stderr, str, e->resourceid);
478
 
    fprintf (stderr, "\n");
479
 
 
480
 
    /* abort (); */
481
 
#endif
482
 
 
483
 
    return 0;
484
 
}
485
 
 
486
 
int
487
 
CompScreen::checkForError (Display *dpy)
488
 
{
489
 
    int e;
490
 
 
491
 
    XSync (dpy, false);
492
 
 
493
 
    e = errors;
494
 
    errors = 0;
495
 
 
496
 
    return e;
497
 
}
498
 
 
499
 
Display *
500
 
CompScreen::dpy ()
501
 
{
502
 
    return priv->dpy;
503
 
}
504
 
 
505
 
bool
506
 
CompScreen::XRandr ()
507
 
{
508
 
    return priv->randrExtension;
509
 
}
510
 
 
511
 
int
512
 
CompScreen::randrEvent ()
513
 
{
514
 
    return priv->randrEvent;
515
 
}
516
 
 
517
 
bool
518
 
CompScreen::XShape ()
519
 
{
520
 
    return priv->shapeExtension;
521
 
}
522
 
 
523
 
int
524
 
CompScreen::shapeEvent ()
525
 
{
526
 
    return priv->shapeEvent;
527
 
}
528
 
 
529
 
int
530
 
CompScreen::syncEvent ()
531
 
{
532
 
    return priv->syncEvent;
533
 
}
534
 
 
535
 
SnDisplay *
536
 
CompScreen::snDisplay ()
537
 
{
538
 
    return priv->snDisplay;
539
 
}
540
 
 
541
 
Window
542
 
CompScreen::activeWindow ()
543
 
{
544
 
    return priv->activeWindow;
545
 
}
546
 
 
547
 
Window
548
 
CompScreen::autoRaiseWindow ()
549
 
{
550
 
    return priv->autoRaiseWindow;
551
 
}
552
 
 
553
 
const char *
554
 
CompScreen::displayString ()
555
 
{
556
 
    return priv->displayString;
557
 
}
558
 
 
559
 
void
560
 
PrivateScreen::updateScreenInfo ()
561
 
{
562
 
    if (xineramaExtension)
563
 
    {
564
 
        int nInfo;
565
 
        XineramaScreenInfo *info = XineramaQueryScreens (dpy, &nInfo);
566
 
 
567
 
        screenInfo = std::vector<XineramaScreenInfo> (info, info + nInfo);
568
 
 
569
 
        if (info)
570
 
            XFree (info);
571
 
    }
572
 
}
573
 
 
574
 
void
575
 
PrivateScreen::setAudibleBell (bool audible)
576
 
{
577
 
    if (xkbExtension)
578
 
        XkbChangeEnabledControls (dpy,
579
 
                                  XkbUseCoreKbd,
580
 
                                  XkbAudibleBellMask,
581
 
                                  audible ? XkbAudibleBellMask : 0);
582
 
}
583
 
 
584
 
bool
585
 
PrivateScreen::handlePingTimeout ()
586
 
{
587
 
    XEvent      ev;
588
 
    int         ping = lastPing + 1;
589
 
 
590
 
    ev.type                 = ClientMessage;
591
 
    ev.xclient.window       = 0;
592
 
    ev.xclient.message_type = Atoms::wmProtocols;
593
 
    ev.xclient.format       = 32;
594
 
    ev.xclient.data.l[0]    = Atoms::wmPing;
595
 
    ev.xclient.data.l[1]    = ping;
596
 
    ev.xclient.data.l[2]    = 0;
597
 
    ev.xclient.data.l[3]    = 0;
598
 
    ev.xclient.data.l[4]    = 0;
599
 
 
600
 
    foreach (CompWindow *w, windows)
601
 
    {
602
 
        if (w->priv->handlePingTimeout (lastPing))
603
 
        {
604
 
            ev.xclient.window    = w->id ();
605
 
            ev.xclient.data.l[2] = w->id ();
606
 
 
607
 
            XSendEvent (dpy, w->id (), false, NoEventMask, &ev);
608
 
        }
609
 
    }
610
 
 
611
 
    lastPing = ping;
612
 
 
613
 
    return true;
614
 
}
615
 
 
616
 
CompOption::Vector &
617
 
CompScreen::getOptions ()
618
 
{
619
 
    return priv->getOptions ();
620
 
}
621
 
 
622
 
bool
623
 
CompScreen::setOption (const CompString  &name,
624
 
                       CompOption::Value &value)
625
 
{
626
 
    return priv->setOption (name, value);
627
 
}
628
 
 
629
 
bool
630
 
PrivateScreen::setOption (const CompString  &name,
631
 
                          CompOption::Value &value)
632
 
{
633
 
    unsigned int index;
634
 
 
635
 
    bool rv = CoreOptions::setOption (name, value);
636
 
 
637
 
    if (!rv)
638
 
        return false;
639
 
 
640
 
    if (!CompOption::findOption (getOptions (), name, &index))
641
 
        return false;
642
 
 
643
 
    switch (index) {
644
 
        case CoreOptions::ActivePlugins:
645
 
            dirtyPluginList = true;
646
 
            break;
647
 
        case CoreOptions::PingDelay:
648
 
            pingTimer.setTimes (optionGetPingDelay (),
649
 
                                optionGetPingDelay () + 500);
650
 
            break;
651
 
        case CoreOptions::AudibleBell:
652
 
            setAudibleBell (optionGetAudibleBell ());
653
 
            break;
654
 
        case CoreOptions::DetectOutputs:
655
 
            if (optionGetDetectOutputs ())
656
 
                detectOutputDevices ();
657
 
            break;
658
 
        case CoreOptions::Hsize:
659
 
        case CoreOptions::Vsize:
660
 
 
661
 
            if (optionGetHsize () * screen->width () > MAXSHORT)
662
 
                return false;
663
 
            if (optionGetVsize () * screen->height () > MAXSHORT)
664
 
                return false;
665
 
 
666
 
            setVirtualScreenSize (optionGetHsize (), optionGetVsize ());
667
 
            break;
668
 
        case CoreOptions::NumberOfDesktops:
669
 
            setNumberOfDesktops (optionGetNumberOfDesktops ());
670
 
            break;
671
 
        case CoreOptions::DefaultIcon:
672
 
            return screen->updateDefaultIcon ();
673
 
            break;
674
 
        case CoreOptions::Outputs:
675
 
            if (!noDetection && optionGetDetectOutputs ())
676
 
                return false;
677
 
            updateOutputDevices ();
678
 
            break;
679
 
        default:
680
 
            break;
681
 
    }
682
 
 
683
 
    return rv;
684
 
}
685
 
 
686
 
void
687
 
PrivateScreen::processEvents ()
688
 
{
689
 
    XEvent event, peekEvent;
690
 
 
691
 
    /* remove destroyed windows */
692
 
    removeDestroyed ();
693
 
 
694
 
    if (dirtyPluginList)
695
 
        updatePlugins ();
696
 
 
697
 
    while (XPending (dpy))
698
 
    {
699
 
        XNextEvent (dpy, &event);
700
 
 
701
 
        switch (event.type) {
702
 
        case ButtonPress:
703
 
        case ButtonRelease:
704
 
            pointerX = event.xbutton.x_root;
705
 
            pointerY = event.xbutton.y_root;
706
 
            break;
707
 
        case KeyPress:
708
 
        case KeyRelease:
709
 
            pointerX = event.xkey.x_root;
710
 
            pointerY = event.xkey.y_root;
711
 
            break;
712
 
        case MotionNotify:
713
 
            while (XPending (dpy))
714
 
            {
715
 
                XPeekEvent (dpy, &peekEvent);
716
 
 
717
 
                if (peekEvent.type != MotionNotify)
718
 
                    break;
719
 
 
720
 
                XNextEvent (dpy, &event);
721
 
            }
722
 
 
723
 
            pointerX = event.xmotion.x_root;
724
 
            pointerY = event.xmotion.y_root;
725
 
            break;
726
 
        case EnterNotify:
727
 
        case LeaveNotify:
728
 
            pointerX = event.xcrossing.x_root;
729
 
            pointerY = event.xcrossing.y_root;
730
 
            break;
731
 
        case ClientMessage:
732
 
            if (event.xclient.message_type == Atoms::xdndPosition)
733
 
            {
734
 
                pointerX = event.xclient.data.l[2] >> 16;
735
 
                pointerY = event.xclient.data.l[2] & 0xffff;
736
 
            }
737
 
        default:
738
 
            break;
739
 
        }
740
 
 
741
 
        sn_display_process_event (snDisplay, &event);
742
 
 
743
 
        inHandleEvent = true;
744
 
        screen->handleEvent (&event);
745
 
        inHandleEvent = false;
746
 
 
747
 
        lastPointerX = pointerX;
748
 
        lastPointerY = pointerY;
749
 
    }
750
 
}
751
 
 
752
 
void
753
 
PrivateScreen::updatePlugins ()
754
 
{
755
 
    CompPlugin                *p;
756
 
    unsigned int              nPop, i, j, pListCount = 1;
757
 
    CompOption::Value::Vector pList;
758
 
    CompPlugin::List          pop;
759
 
    bool                      failedPush;
760
 
 
761
 
 
762
 
    dirtyPluginList = false;
763
 
 
764
 
    CompOption::Value::Vector &list = optionGetActivePlugins ();
765
 
 
766
 
    /* Determine the number of plugins, which is core +
767
 
     * initial plugins + plugins in option list in addition
768
 
     * to initial plugins */
769
 
    foreach (CompString &pn, initialPlugins)
770
 
    {
771
 
        if (pn != "core")
772
 
            pListCount++;
773
 
    }
774
 
 
775
 
    foreach (CompOption::Value &lp, list)
776
 
    {
777
 
        bool skip = false;
778
 
        if (lp.s () == "core")
779
 
            continue;
780
 
 
781
 
        foreach (CompString &p, initialPlugins)
782
 
        {
783
 
            if (p == lp.s ())
784
 
            {
785
 
                skip = true;
786
 
                break;
787
 
            }
788
 
        }
789
 
 
790
 
        /* plugin not in initial list */
791
 
        if (!skip)
792
 
            pListCount++;
793
 
    }
794
 
 
795
 
    /* dupPluginCount is now the number of plugisn contained in both the
796
 
     * initial and new plugins list */
797
 
    pList.resize (pListCount);
798
 
 
799
 
    if (pList.empty ())
800
 
    {
801
 
        screen->setOptionForPlugin ("core", "active_plugins", plugin);
802
 
        return;
803
 
    }
804
 
 
805
 
    /* Must have core as first plugin */
806
 
    pList.at (0) = "core";
807
 
    j = 1;
808
 
 
809
 
    /* Add initial plugins */
810
 
    foreach (CompString &p, initialPlugins)
811
 
    {
812
 
        if (p == "core")
813
 
            continue;
814
 
        pList.at (j).set (p);
815
 
        j++;
816
 
    }
817
 
 
818
 
    /* Add plugins not in the initial list */
819
 
    foreach (CompOption::Value &opt, list)
820
 
    {
821
 
        std::list <CompString>::iterator it = initialPlugins.begin ();
822
 
        bool                             skip = false;
823
 
        if (opt.s () == "core")
824
 
            continue;
825
 
 
826
 
        for (; it != initialPlugins.end (); it++)
827
 
        {
828
 
            if ((*it) == opt.s ())
829
 
            {
830
 
                skip = true;
831
 
                break;
832
 
            }
833
 
        }
834
 
 
835
 
        if (!skip)
836
 
            pList.at (j++).set (opt.s ());
837
 
    }
838
 
 
839
 
    assert (j == pList.size ());
840
 
 
841
 
    /* j is initialized to 1 to make sure we never pop the core plugin */
842
 
    for (i = j = 1; j < plugin.list ().size () && i < pList.size (); i++, j++)
843
 
    {
844
 
        if (plugin.list ().at (j).s () != pList.at (i).s ())
845
 
            break;
846
 
    }
847
 
 
848
 
    nPop = plugin.list ().size () - j;
849
 
 
850
 
    if (nPop)
851
 
    {
852
 
        for (j = 0; j < nPop; j++)
853
 
        {
854
 
            pop.push_back (CompPlugin::pop ());
855
 
            plugin.list ().pop_back ();
856
 
        }
857
 
    }
858
 
 
859
 
    for (; i < pList.size (); i++)
860
 
    {
861
 
        p = NULL;
862
 
        failedPush = false;
863
 
        foreach (CompPlugin *pp, pop)
864
 
        {
865
 
            if (pList[i]. s () == pp->vTable->name ())
866
 
            {
867
 
                if (CompPlugin::push (pp))
868
 
                {
869
 
                    p = pp;
870
 
                    pop.erase (std::find (pop.begin (), pop.end (), pp));
871
 
                    break;
872
 
                }
873
 
                else
874
 
                {
875
 
                    pop.erase (std::find (pop.begin (), pop.end (), pp));
876
 
                    CompPlugin::unload (pp);
877
 
                    p = NULL;
878
 
                    failedPush = true;
879
 
                    break;
880
 
                }
881
 
            }
882
 
        }
883
 
 
884
 
        if (p == 0 && !failedPush)
885
 
        {
886
 
            p = CompPlugin::load (pList[i].s ().c_str ());
887
 
            if (p)
888
 
            {
889
 
                if (!CompPlugin::push (p))
890
 
                {
891
 
                    CompPlugin::unload (p);
892
 
                    p = 0;
893
 
                }
894
 
            }
895
 
        }
896
 
 
897
 
        if (p)
898
 
            plugin.list ().push_back (p->vTable->name ());
899
 
    }
900
 
 
901
 
    foreach (CompPlugin *pp, pop)
902
 
        CompPlugin::unload (pp);
903
 
 
904
 
    if (!priv->dirtyPluginList)
905
 
        screen->setOptionForPlugin ("core", "active_plugins", plugin);
906
 
}
907
 
 
908
 
/* from fvwm2, Copyright Matthias Clasen, Dominik Vogt */
909
 
static bool
910
 
convertProperty (Display *dpy,
911
 
                 Time    time,
912
 
                 Window  w,
913
 
                 Atom    target,
914
 
                 Atom    property)
915
 
{
916
 
 
917
 
#define N_TARGETS 4
918
 
 
919
 
    Atom conversionTargets[N_TARGETS];
920
 
    long icccmVersion[] = { 2, 0 };
921
 
 
922
 
    conversionTargets[0] = Atoms::targets;
923
 
    conversionTargets[1] = Atoms::multiple;
924
 
    conversionTargets[2] = Atoms::timestamp;
925
 
    conversionTargets[3] = Atoms::version;
926
 
 
927
 
    if (target == Atoms::targets)
928
 
        XChangeProperty (dpy, w, property,
929
 
                         XA_ATOM, 32, PropModeReplace,
930
 
                         (unsigned char *) conversionTargets, N_TARGETS);
931
 
    else if (target == Atoms::timestamp)
932
 
        XChangeProperty (dpy, w, property,
933
 
                         XA_INTEGER, 32, PropModeReplace,
934
 
                         (unsigned char *) &time, 1);
935
 
    else if (target == Atoms::version)
936
 
        XChangeProperty (dpy, w, property,
937
 
                         XA_INTEGER, 32, PropModeReplace,
938
 
                         (unsigned char *) icccmVersion, 2);
939
 
    else
940
 
        return false;
941
 
 
942
 
    /* Be sure the PropertyNotify has arrived so we
943
 
     * can send SelectionNotify
944
 
     */
945
 
    XSync (dpy, false);
946
 
 
947
 
    return true;
948
 
}
949
 
 
950
 
/* from fvwm2, Copyright Matthias Clasen, Dominik Vogt */
951
 
void
952
 
PrivateScreen::handleSelectionRequest (XEvent *event)
953
 
{
954
 
    XSelectionEvent reply;
955
 
 
956
 
    if (wmSnSelectionWindow != event->xselectionrequest.owner ||
957
 
        wmSnAtom != event->xselectionrequest.selection)
958
 
        return;
959
 
 
960
 
    reply.type      = SelectionNotify;
961
 
    reply.display   = dpy;
962
 
    reply.requestor = event->xselectionrequest.requestor;
963
 
    reply.selection = event->xselectionrequest.selection;
964
 
    reply.target    = event->xselectionrequest.target;
965
 
    reply.property  = None;
966
 
    reply.time      = event->xselectionrequest.time;
967
 
 
968
 
    if (event->xselectionrequest.target == Atoms::multiple)
969
 
    {
970
 
        if (event->xselectionrequest.property != None)
971
 
        {
972
 
            Atom          type, *adata;
973
 
            int           i, format;
974
 
            unsigned long num, rest;
975
 
            unsigned char *data;
976
 
 
977
 
            if (XGetWindowProperty (dpy,
978
 
                                    event->xselectionrequest.requestor,
979
 
                                    event->xselectionrequest.property,
980
 
                                    0, 256, false,
981
 
                                    Atoms::atomPair,
982
 
                                    &type, &format, &num, &rest,
983
 
                                    &data) != Success)
984
 
                return;
985
 
 
986
 
            /* FIXME: to be 100% correct, should deal with rest > 0,
987
 
             * but since we have 4 possible targets, we will hardly ever
988
 
             * meet multiple requests with a length > 8
989
 
             */
990
 
            adata = (Atom *) data;
991
 
            i = 0;
992
 
            while (i < (int) num)
993
 
            {
994
 
                if (!convertProperty (dpy, wmSnTimestamp,
995
 
                                      event->xselectionrequest.requestor,
996
 
                                      adata[i], adata[i + 1]))
997
 
                    adata[i + 1] = None;
998
 
 
999
 
                i += 2;
1000
 
            }
1001
 
 
1002
 
            XChangeProperty (dpy,
1003
 
                             event->xselectionrequest.requestor,
1004
 
                             event->xselectionrequest.property,
1005
 
                             Atoms::atomPair,
1006
 
                             32, PropModeReplace, data, num);
1007
 
 
1008
 
            if (data)
1009
 
                XFree (data);
1010
 
        }
1011
 
    }
1012
 
    else
1013
 
    {
1014
 
        if (event->xselectionrequest.property == None)
1015
 
            event->xselectionrequest.property = event->xselectionrequest.target;
1016
 
 
1017
 
        if (convertProperty (dpy, wmSnTimestamp,
1018
 
                             event->xselectionrequest.requestor,
1019
 
                             event->xselectionrequest.target,
1020
 
                             event->xselectionrequest.property))
1021
 
            reply.property = event->xselectionrequest.property;
1022
 
    }
1023
 
 
1024
 
    XSendEvent (dpy, event->xselectionrequest.requestor,
1025
 
                false, 0L, (XEvent *) &reply);
1026
 
}
1027
 
 
1028
 
void
1029
 
PrivateScreen::handleSelectionClear (XEvent *event)
1030
 
{
1031
 
    /* We need to unmanage the screen on which we lost the selection */
1032
 
    if (wmSnSelectionWindow != event->xselectionclear.window ||
1033
 
        wmSnAtom != event->xselectionclear.selection)
1034
 
        return;
1035
 
 
1036
 
    shutDown = true;
1037
 
}
1038
 
 
1039
 
#define HOME_IMAGEDIR ".compiz-1/images"
1040
 
 
1041
 
bool
1042
 
CompScreen::readImageFromFile (CompString &name,
1043
 
                               CompSize   &size,
1044
 
                               void       *&data)
1045
 
{
1046
 
    bool status;
1047
 
    int  stride;
1048
 
 
1049
 
    status = fileToImage (name, size, stride, data);
1050
 
    if (!status)
1051
 
    {
1052
 
        char       *home = getenv ("HOME");
1053
 
        CompString path;
1054
 
        if (home)
1055
 
        {
1056
 
            path =  home;
1057
 
            path += "/";
1058
 
            path += HOME_IMAGEDIR;
1059
 
            path += "/";
1060
 
            path += name;
1061
 
 
1062
 
            status = fileToImage (path, size, stride, data);
1063
 
 
1064
 
            if (status)
1065
 
                return true;
1066
 
        }
1067
 
 
1068
 
        path = IMAGEDIR;
1069
 
        path += "/";
1070
 
        path += name;
1071
 
        status = fileToImage (path, size, stride, data);
1072
 
    }
1073
 
 
1074
 
    return status;
1075
 
}
1076
 
 
1077
 
bool
1078
 
CompScreen::writeImageToFile (CompString &path,
1079
 
                              const char *format,
1080
 
                              CompSize   &size,
1081
 
                              void       *data)
1082
 
{
1083
 
    CompString formatString (format);
1084
 
    return imageToFile (path, formatString, size, size.width () * 4, data);
1085
 
}
1086
 
 
1087
 
Window
1088
 
PrivateScreen::getActiveWindow (Window root)
1089
 
{
1090
 
    Atom          actual;
1091
 
    int           result, format;
1092
 
    unsigned long n, left;
1093
 
    unsigned char *data;
1094
 
    Window        w = None;
1095
 
 
1096
 
    result = XGetWindowProperty (priv->dpy, root,
1097
 
                                 Atoms::winActive, 0L, 1L, false,
1098
 
                                 XA_WINDOW, &actual, &format,
1099
 
                                 &n, &left, &data);
1100
 
 
1101
 
    if (result == Success && data)
1102
 
    {
1103
 
        if (n)
1104
 
            memcpy (&w, data, sizeof (Window));
1105
 
        XFree (data);
1106
 
    }
1107
 
 
1108
 
    return w;
1109
 
}
1110
 
 
1111
 
bool
1112
 
CompScreen::fileToImage (CompString &name,
1113
 
                         CompSize   &size,
1114
 
                         int        &stride,
1115
 
                         void       *&data)
1116
 
{
1117
 
    WRAPABLE_HND_FUNC_RETURN (8, bool, fileToImage, name, size, stride, data);
1118
 
    return false;
1119
 
}
1120
 
 
1121
 
bool
1122
 
CompScreen::imageToFile (CompString &path,
1123
 
                         CompString &format,
1124
 
                         CompSize   &size,
1125
 
                         int        stride,
1126
 
                         void       *data)
1127
 
{
1128
 
    WRAPABLE_HND_FUNC_RETURN (9, bool, imageToFile, path, format, size,
1129
 
                              stride, data)
1130
 
    return false;
1131
 
}
1132
 
 
1133
 
const char *
1134
 
logLevelToString (CompLogLevel level)
1135
 
{
1136
 
    switch (level) {
1137
 
    case CompLogLevelFatal:
1138
 
        return "Fatal";
1139
 
    case CompLogLevelError:
1140
 
        return "Error";
1141
 
    case CompLogLevelWarn:
1142
 
        return "Warn";
1143
 
    case CompLogLevelInfo:
1144
 
        return "Info";
1145
 
    case CompLogLevelDebug:
1146
 
        return "Debug";
1147
 
    default:
1148
 
        break;
1149
 
    }
1150
 
 
1151
 
    return "Unknown";
1152
 
}
1153
 
 
1154
 
static void
1155
 
logMessage (const char   *componentName,
1156
 
            CompLogLevel level,
1157
 
            const char   *message)
1158
 
{
1159
 
    if (!debugOutput && level >= CompLogLevelDebug)
1160
 
        return;
1161
 
 
1162
 
    fprintf (stderr, "%s (%s) - %s: %s\n",
1163
 
             programName, componentName,
1164
 
             logLevelToString (level), message);
1165
 
}
1166
 
 
1167
 
void
1168
 
CompScreen::logMessage (const char   *componentName,
1169
 
                        CompLogLevel level,
1170
 
                        const char   *message)
1171
 
{
1172
 
    WRAPABLE_HND_FUNC (13, logMessage, componentName, level, message)
1173
 
    ::logMessage (componentName, level, message);
1174
 
}
1175
 
 
1176
 
void
1177
 
compLogMessage (const char   *componentName,
1178
 
                CompLogLevel level,
1179
 
                const char   *format,
1180
 
                ...)
1181
 
{
1182
 
    va_list args;
1183
 
    char    message[2048];
1184
 
 
1185
 
    va_start (args, format);
1186
 
 
1187
 
    vsnprintf (message, 2048, format, args);
1188
 
 
1189
 
    if (screen)
1190
 
        screen->logMessage (componentName, level, message);
1191
 
    else
1192
 
        logMessage (componentName, level, message);
1193
 
 
1194
 
    va_end (args);
1195
 
}
1196
 
 
1197
 
int
1198
 
PrivateScreen::getWmState (Window id)
1199
 
{
1200
 
    Atom          actual;
1201
 
    int           result, format;
1202
 
    unsigned long n, left;
1203
 
    unsigned char *data;
1204
 
    unsigned long state = NormalState;
1205
 
 
1206
 
    result = XGetWindowProperty (priv->dpy, id,
1207
 
                                 Atoms::wmState, 0L, 2L, false,
1208
 
                                 Atoms::wmState, &actual, &format,
1209
 
                                 &n, &left, &data);
1210
 
 
1211
 
    if (result == Success && data)
1212
 
    {
1213
 
        if (n)
1214
 
            memcpy (&state, data, sizeof (unsigned long));
1215
 
        XFree ((void *) data);
1216
 
    }
1217
 
 
1218
 
    return state;
1219
 
}
1220
 
 
1221
 
void
1222
 
PrivateScreen::setWmState (int state, Window id)
1223
 
{
1224
 
    unsigned long data[2];
1225
 
 
1226
 
    data[0] = state;
1227
 
    data[1] = None;
1228
 
 
1229
 
    XChangeProperty (priv->dpy, id,
1230
 
                     Atoms::wmState, Atoms::wmState,
1231
 
                     32, PropModeReplace, (unsigned char *) data, 2);
1232
 
}
1233
 
 
1234
 
unsigned int
1235
 
PrivateScreen::windowStateMask (Atom state)
1236
 
{
1237
 
    if (state == Atoms::winStateModal)
1238
 
        return CompWindowStateModalMask;
1239
 
    else if (state == Atoms::winStateSticky)
1240
 
        return CompWindowStateStickyMask;
1241
 
    else if (state == Atoms::winStateMaximizedVert)
1242
 
        return CompWindowStateMaximizedVertMask;
1243
 
    else if (state == Atoms::winStateMaximizedHorz)
1244
 
        return CompWindowStateMaximizedHorzMask;
1245
 
    else if (state == Atoms::winStateShaded)
1246
 
        return CompWindowStateShadedMask;
1247
 
    else if (state == Atoms::winStateSkipTaskbar)
1248
 
        return CompWindowStateSkipTaskbarMask;
1249
 
    else if (state == Atoms::winStateSkipPager)
1250
 
        return CompWindowStateSkipPagerMask;
1251
 
    else if (state == Atoms::winStateHidden)
1252
 
        return CompWindowStateHiddenMask;
1253
 
    else if (state == Atoms::winStateFullscreen)
1254
 
        return CompWindowStateFullscreenMask;
1255
 
    else if (state == Atoms::winStateAbove)
1256
 
        return CompWindowStateAboveMask;
1257
 
    else if (state == Atoms::winStateBelow)
1258
 
        return CompWindowStateBelowMask;
1259
 
    else if (state == Atoms::winStateDemandsAttention)
1260
 
        return CompWindowStateDemandsAttentionMask;
1261
 
    else if (state == Atoms::winStateDisplayModal)
1262
 
        return CompWindowStateDisplayModalMask;
1263
 
 
1264
 
    return 0;
1265
 
}
1266
 
 
1267
 
unsigned int
1268
 
PrivateScreen::windowStateFromString (const char *str)
1269
 
{
1270
 
    if (strcasecmp (str, "modal") == 0)
1271
 
        return CompWindowStateModalMask;
1272
 
    else if (strcasecmp (str, "sticky") == 0)
1273
 
        return CompWindowStateStickyMask;
1274
 
    else if (strcasecmp (str, "maxvert") == 0)
1275
 
        return CompWindowStateMaximizedVertMask;
1276
 
    else if (strcasecmp (str, "maxhorz") == 0)
1277
 
        return CompWindowStateMaximizedHorzMask;
1278
 
    else if (strcasecmp (str, "shaded") == 0)
1279
 
        return CompWindowStateShadedMask;
1280
 
    else if (strcasecmp (str, "skiptaskbar") == 0)
1281
 
        return CompWindowStateSkipTaskbarMask;
1282
 
    else if (strcasecmp (str, "skippager") == 0)
1283
 
        return CompWindowStateSkipPagerMask;
1284
 
    else if (strcasecmp (str, "hidden") == 0)
1285
 
        return CompWindowStateHiddenMask;
1286
 
    else if (strcasecmp (str, "fullscreen") == 0)
1287
 
        return CompWindowStateFullscreenMask;
1288
 
    else if (strcasecmp (str, "above") == 0)
1289
 
        return CompWindowStateAboveMask;
1290
 
    else if (strcasecmp (str, "below") == 0)
1291
 
        return CompWindowStateBelowMask;
1292
 
    else if (strcasecmp (str, "demandsattention") == 0)
1293
 
        return CompWindowStateDemandsAttentionMask;
1294
 
 
1295
 
    return 0;
1296
 
}
1297
 
 
1298
 
unsigned int
1299
 
PrivateScreen::getWindowState (Window id)
1300
 
{
1301
 
    Atom          actual;
1302
 
    int           result, format;
1303
 
    unsigned long n, left;
1304
 
    unsigned char *data;
1305
 
    unsigned int  state = 0;
1306
 
 
1307
 
    result = XGetWindowProperty (priv->dpy, id,
1308
 
                                 Atoms::winState,
1309
 
                                 0L, 1024L, false, XA_ATOM, &actual, &format,
1310
 
                                 &n, &left, &data);
1311
 
 
1312
 
    if (result == Success && data)
1313
 
    {
1314
 
        Atom *a = (Atom *) data;
1315
 
 
1316
 
        while (n--)
1317
 
            state |= windowStateMask (*a++);
1318
 
 
1319
 
        XFree ((void *) data);
1320
 
    }
1321
 
 
1322
 
    return state;
1323
 
}
1324
 
 
1325
 
void
1326
 
PrivateScreen::setWindowState (unsigned int state, Window id)
1327
 
{
1328
 
    Atom data[32];
1329
 
    int  i = 0;
1330
 
 
1331
 
    if (state & CompWindowStateModalMask)
1332
 
        data[i++] = Atoms::winStateModal;
1333
 
    if (state & CompWindowStateStickyMask)
1334
 
        data[i++] = Atoms::winStateSticky;
1335
 
    if (state & CompWindowStateMaximizedVertMask)
1336
 
        data[i++] = Atoms::winStateMaximizedVert;
1337
 
    if (state & CompWindowStateMaximizedHorzMask)
1338
 
        data[i++] = Atoms::winStateMaximizedHorz;
1339
 
    if (state & CompWindowStateShadedMask)
1340
 
        data[i++] = Atoms::winStateShaded;
1341
 
    if (state & CompWindowStateSkipTaskbarMask)
1342
 
        data[i++] = Atoms::winStateSkipTaskbar;
1343
 
    if (state & CompWindowStateSkipPagerMask)
1344
 
        data[i++] = Atoms::winStateSkipPager;
1345
 
    if (state & CompWindowStateHiddenMask)
1346
 
        data[i++] = Atoms::winStateHidden;
1347
 
    if (state & CompWindowStateFullscreenMask)
1348
 
        data[i++] = Atoms::winStateFullscreen;
1349
 
    if (state & CompWindowStateAboveMask)
1350
 
        data[i++] = Atoms::winStateAbove;
1351
 
    if (state & CompWindowStateBelowMask)
1352
 
        data[i++] = Atoms::winStateBelow;
1353
 
    if (state & CompWindowStateDemandsAttentionMask)
1354
 
        data[i++] = Atoms::winStateDemandsAttention;
1355
 
    if (state & CompWindowStateDisplayModalMask)
1356
 
        data[i++] = Atoms::winStateDisplayModal;
1357
 
 
1358
 
    XChangeProperty (priv->dpy, id, Atoms::winState,
1359
 
                     XA_ATOM, 32, PropModeReplace,
1360
 
                     (unsigned char *) data, i);
1361
 
}
1362
 
 
1363
 
unsigned int
1364
 
PrivateScreen::getWindowType (Window id)
1365
 
{
1366
 
    Atom          actual, a = None;
1367
 
    int           result, format;
1368
 
    unsigned long n, left;
1369
 
    unsigned char *data;
1370
 
 
1371
 
    result = XGetWindowProperty (priv->dpy , id,
1372
 
                                 Atoms::winType,
1373
 
                                 0L, 1L, false, XA_ATOM, &actual, &format,
1374
 
                                 &n, &left, &data);
1375
 
 
1376
 
    if (result == Success && data)
1377
 
    {
1378
 
        if (n)
1379
 
            memcpy (&a, data, sizeof (Atom));
1380
 
        XFree ((void *) data);
1381
 
    }
1382
 
 
1383
 
    if (a)
1384
 
    {
1385
 
        if (a == Atoms::winTypeNormal)
1386
 
            return CompWindowTypeNormalMask;
1387
 
        else if (a == Atoms::winTypeMenu)
1388
 
            return CompWindowTypeMenuMask;
1389
 
        else if (a == Atoms::winTypeDesktop)
1390
 
            return CompWindowTypeDesktopMask;
1391
 
        else if (a == Atoms::winTypeDock)
1392
 
            return CompWindowTypeDockMask;
1393
 
        else if (a == Atoms::winTypeToolbar)
1394
 
            return CompWindowTypeToolbarMask;
1395
 
        else if (a == Atoms::winTypeUtil)
1396
 
            return CompWindowTypeUtilMask;
1397
 
        else if (a == Atoms::winTypeSplash)
1398
 
            return CompWindowTypeSplashMask;
1399
 
        else if (a == Atoms::winTypeDialog)
1400
 
            return CompWindowTypeDialogMask;
1401
 
        else if (a == Atoms::winTypeDropdownMenu)
1402
 
            return CompWindowTypeDropdownMenuMask;
1403
 
        else if (a == Atoms::winTypePopupMenu)
1404
 
            return CompWindowTypePopupMenuMask;
1405
 
        else if (a == Atoms::winTypeTooltip)
1406
 
            return CompWindowTypeTooltipMask;
1407
 
        else if (a == Atoms::winTypeNotification)
1408
 
            return CompWindowTypeNotificationMask;
1409
 
        else if (a == Atoms::winTypeCombo)
1410
 
            return CompWindowTypeComboMask;
1411
 
        else if (a == Atoms::winTypeDnd)
1412
 
            return CompWindowTypeDndMask;
1413
 
    }
1414
 
 
1415
 
    return CompWindowTypeUnknownMask;
1416
 
}
1417
 
 
1418
 
void
1419
 
PrivateScreen::getMwmHints (Window       id,
1420
 
                            unsigned int *func,
1421
 
                            unsigned int *decor)
1422
 
{
1423
 
    Atom          actual;
1424
 
    int           result, format;
1425
 
    unsigned long n, left;
1426
 
    unsigned char *data;
1427
 
 
1428
 
    *func  = MwmFuncAll;
1429
 
    *decor = MwmDecorAll;
1430
 
 
1431
 
    result = XGetWindowProperty (priv->dpy, id,
1432
 
                                 Atoms::mwmHints,
1433
 
                                 0L, 20L, false, Atoms::mwmHints,
1434
 
                                 &actual, &format, &n, &left, &data);
1435
 
 
1436
 
    if (result == Success && data)
1437
 
    {
1438
 
        MwmHints *mwmHints = (MwmHints *) data;
1439
 
 
1440
 
        if (n >= PropMotifWmHintElements)
1441
 
        {
1442
 
            if (mwmHints->flags & MwmHintsDecorations)
1443
 
                *decor = mwmHints->decorations;
1444
 
 
1445
 
            if (mwmHints->flags & MwmHintsFunctions)
1446
 
                *func = mwmHints->functions;
1447
 
        }
1448
 
 
1449
 
        XFree (data);
1450
 
    }
1451
 
}
1452
 
 
1453
 
unsigned int
1454
 
PrivateScreen::getProtocols (Window id)
1455
 
{
1456
 
    Atom         *protocol;
1457
 
    int          count;
1458
 
    unsigned int protocols = 0;
1459
 
 
1460
 
    if (XGetWMProtocols (priv->dpy, id, &protocol, &count))
1461
 
    {
1462
 
        int  i;
1463
 
 
1464
 
        for (i = 0; i < count; i++)
1465
 
        {
1466
 
            if (protocol[i] == Atoms::wmDeleteWindow)
1467
 
                protocols |= CompWindowProtocolDeleteMask;
1468
 
            else if (protocol[i] == Atoms::wmTakeFocus)
1469
 
                protocols |= CompWindowProtocolTakeFocusMask;
1470
 
            else if (protocol[i] == Atoms::wmPing)
1471
 
                protocols |= CompWindowProtocolPingMask;
1472
 
            else if (protocol[i] == Atoms::wmSyncRequest)
1473
 
                protocols |= CompWindowProtocolSyncRequestMask;
1474
 
        }
1475
 
 
1476
 
        XFree (protocol);
1477
 
    }
1478
 
 
1479
 
    return protocols;
1480
 
}
1481
 
 
1482
 
unsigned int
1483
 
CompScreen::getWindowProp (Window       id,
1484
 
                           Atom         property,
1485
 
                           unsigned int defaultValue)
1486
 
{
1487
 
    Atom          actual;
1488
 
    int           result, format;
1489
 
    unsigned long n, left;
1490
 
    unsigned char *data;
1491
 
    unsigned int  retval = defaultValue;
1492
 
 
1493
 
    result = XGetWindowProperty (priv->dpy, id, property,
1494
 
                                 0L, 1L, false, XA_CARDINAL, &actual, &format,
1495
 
                                 &n, &left, &data);
1496
 
 
1497
 
    if (result == Success && data)
1498
 
    {
1499
 
        if (n)
1500
 
        {
1501
 
            unsigned long value;
1502
 
            memcpy (&value, data, sizeof (unsigned long));
1503
 
            retval = (unsigned int) value;
1504
 
        }
1505
 
 
1506
 
        XFree (data);
1507
 
    }
1508
 
 
1509
 
    return retval;
1510
 
}
1511
 
 
1512
 
void
1513
 
CompScreen::setWindowProp (Window       id,
1514
 
                           Atom         property,
1515
 
                           unsigned int value)
1516
 
{
1517
 
    unsigned long data = value;
1518
 
 
1519
 
    XChangeProperty (priv->dpy, id, property,
1520
 
                     XA_CARDINAL, 32, PropModeReplace,
1521
 
                     (unsigned char *) &data, 1);
1522
 
}
1523
 
 
1524
 
bool
1525
 
PrivateScreen::readWindowProp32 (Window         id,
1526
 
                                 Atom           property,
1527
 
                                 unsigned short *returnValue)
1528
 
{
1529
 
    Atom          actual;
1530
 
    int           result, format;
1531
 
    unsigned long n, left;
1532
 
    unsigned char *data;
1533
 
    bool          retval = false;
1534
 
 
1535
 
    result = XGetWindowProperty (priv->dpy, id, property,
1536
 
                                 0L, 1L, false, XA_CARDINAL, &actual, &format,
1537
 
                                 &n, &left, &data);
1538
 
 
1539
 
    if (result == Success && data)
1540
 
    {
1541
 
        if (n)
1542
 
        {
1543
 
            CARD32 value;
1544
 
 
1545
 
            memcpy (&value, data, sizeof (CARD32));
1546
 
            retval       = true;
1547
 
            *returnValue = value >> 16;
1548
 
        }
1549
 
 
1550
 
        XFree (data);
1551
 
    }
1552
 
 
1553
 
    return retval;
1554
 
}
1555
 
 
1556
 
unsigned short
1557
 
CompScreen::getWindowProp32 (Window         id,
1558
 
                             Atom           property,
1559
 
                             unsigned short defaultValue)
1560
 
{
1561
 
    unsigned short result;
1562
 
 
1563
 
    if (priv->readWindowProp32 (id, property, &result))
1564
 
        return result;
1565
 
 
1566
 
    return defaultValue;
1567
 
}
1568
 
 
1569
 
void
1570
 
CompScreen::setWindowProp32 (Window         id,
1571
 
                             Atom           property,
1572
 
                             unsigned short value)
1573
 
{
1574
 
    CARD32 value32;
1575
 
 
1576
 
    value32 = value << 16 | value;
1577
 
 
1578
 
    XChangeProperty (priv->dpy, id, property,
1579
 
                     XA_CARDINAL, 32, PropModeReplace,
1580
 
                     (unsigned char *) &value32, 1);
1581
 
}
1582
 
 
1583
 
void
1584
 
ScreenInterface::handleEvent (XEvent *event)
1585
 
    WRAPABLE_DEF (handleEvent, event)
1586
 
 
1587
 
void
1588
 
ScreenInterface::handleCompizEvent (const char         *plugin,
1589
 
                                    const char         *event,
1590
 
                                    CompOption::Vector &options)
1591
 
    WRAPABLE_DEF (handleCompizEvent, plugin, event, options)
1592
 
 
1593
 
bool
1594
 
ScreenInterface::fileToImage (CompString &name,
1595
 
                              CompSize   &size,
1596
 
                              int        &stride,
1597
 
                              void       *&data)
1598
 
    WRAPABLE_DEF (fileToImage, name, size, stride, data)
1599
 
 
1600
 
bool
1601
 
ScreenInterface::imageToFile (CompString &path,
1602
 
                              CompString &format,
1603
 
                              CompSize   &size,
1604
 
                              int        stride,
1605
 
                              void       *data)
1606
 
    WRAPABLE_DEF (imageToFile, path, format, size, stride, data)
1607
 
 
1608
 
CompMatch::Expression *
1609
 
ScreenInterface::matchInitExp (const CompString& value)
1610
 
    WRAPABLE_DEF (matchInitExp, value)
1611
 
 
1612
 
void
1613
 
ScreenInterface::matchExpHandlerChanged ()
1614
 
    WRAPABLE_DEF (matchExpHandlerChanged)
1615
 
 
1616
 
void
1617
 
ScreenInterface::matchPropertyChanged (CompWindow *window)
1618
 
    WRAPABLE_DEF (matchPropertyChanged, window)
1619
 
 
1620
 
void
1621
 
ScreenInterface::logMessage (const char   *componentName,
1622
 
                             CompLogLevel level,
1623
 
                             const char   *message)
1624
 
    WRAPABLE_DEF (logMessage, componentName, level, message)
1625
 
 
1626
 
 
1627
 
bool
1628
 
PrivateScreen::desktopHintEqual (unsigned long *data,
1629
 
                                 int           size,
1630
 
                                 int           offset,
1631
 
                                 int           hintSize)
1632
 
{
1633
 
    if (size != desktopHintSize)
1634
 
        return false;
1635
 
 
1636
 
    if (memcmp (data + offset,
1637
 
                desktopHintData + offset,
1638
 
                hintSize * sizeof (unsigned long)) == 0)
1639
 
        return true;
1640
 
 
1641
 
    return false;
1642
 
}
1643
 
 
1644
 
void
1645
 
PrivateScreen::setDesktopHints ()
1646
 
{
1647
 
    unsigned long *data;
1648
 
    int           dSize, offset, hintSize;
1649
 
    unsigned int  i;
1650
 
 
1651
 
    dSize = nDesktop * 2 + nDesktop * 2 + nDesktop * 4 + 1;
1652
 
 
1653
 
    data = (unsigned long *) malloc (sizeof (unsigned long) * dSize);
1654
 
    if (!data)
1655
 
        return;
1656
 
 
1657
 
    offset   = 0;
1658
 
    hintSize = nDesktop * 2;
1659
 
 
1660
 
    for (i = 0; i < nDesktop; i++)
1661
 
    {
1662
 
        data[offset + i * 2 + 0] = vp.x () * screen->width ();
1663
 
        data[offset + i * 2 + 1] = vp.y () * screen->height ();
1664
 
    }
1665
 
 
1666
 
    if (!desktopHintEqual (data, dSize, offset, hintSize))
1667
 
        XChangeProperty (dpy, root,
1668
 
                         Atoms::desktopViewport,
1669
 
                         XA_CARDINAL, 32, PropModeReplace,
1670
 
                         (unsigned char *) &data[offset], hintSize);
1671
 
 
1672
 
    offset += hintSize;
1673
 
 
1674
 
    for (i = 0; i < nDesktop; i++)
1675
 
    {
1676
 
        data[offset + i * 2 + 0] = screen->width () * vpSize.width ();
1677
 
        data[offset + i * 2 + 1] = screen->height () * vpSize.height ();
1678
 
    }
1679
 
 
1680
 
    if (!desktopHintEqual (data, dSize, offset, hintSize))
1681
 
        XChangeProperty (dpy, root,
1682
 
                         Atoms::desktopGeometry,
1683
 
                         XA_CARDINAL, 32, PropModeReplace,
1684
 
                         (unsigned char *) &data[offset], hintSize);
1685
 
 
1686
 
    offset += hintSize;
1687
 
    hintSize = nDesktop * 4;
1688
 
 
1689
 
    for (i = 0; i < nDesktop; i++)
1690
 
    {
1691
 
        data[offset + i * 4 + 0] = workArea.x ();
1692
 
        data[offset + i * 4 + 1] = workArea.y ();
1693
 
        data[offset + i * 4 + 2] = workArea.width ();
1694
 
        data[offset + i * 4 + 3] = workArea.height ();
1695
 
    }
1696
 
 
1697
 
    if (!desktopHintEqual (data, dSize, offset, hintSize))
1698
 
        XChangeProperty (dpy, root,
1699
 
                         Atoms::workarea,
1700
 
                         XA_CARDINAL, 32, PropModeReplace,
1701
 
                         (unsigned char *) &data[offset], hintSize);
1702
 
 
1703
 
    offset += hintSize;
1704
 
 
1705
 
    data[offset] = nDesktop;
1706
 
    hintSize = 1;
1707
 
 
1708
 
    if (!desktopHintEqual (data, dSize, offset, hintSize))
1709
 
        XChangeProperty (dpy, root,
1710
 
                         Atoms::numberOfDesktops,
1711
 
                         XA_CARDINAL, 32, PropModeReplace,
1712
 
                         (unsigned char *) &data[offset], hintSize);
1713
 
 
1714
 
    if (desktopHintData)
1715
 
        free (desktopHintData);
1716
 
 
1717
 
    desktopHintData = data;
1718
 
    desktopHintSize = dSize;
1719
 
}
1720
 
 
1721
 
void
1722
 
PrivateScreen::setVirtualScreenSize (int newh, int newv)
1723
 
{
1724
 
    /* if newh or newv is being reduced */
1725
 
    if (newh < screen->vpSize ().width () ||
1726
 
        newv < screen->vpSize ().height ())
1727
 
    {
1728
 
        int        tx = 0;
1729
 
        int        ty = 0;
1730
 
 
1731
 
        if (screen->vp ().x () >= newh)
1732
 
            tx = screen->vp ().x () - (newh - 1);
1733
 
        if (screen->vp ().y () >= newv)
1734
 
            ty = screen->vp ().y () - (newv - 1);
1735
 
 
1736
 
        if (tx != 0 || ty != 0)
1737
 
            screen->moveViewport (tx, ty, TRUE);
1738
 
 
1739
 
        /* Move windows that were in one of the deleted viewports into the
1740
 
           closest viewport */
1741
 
        foreach (CompWindow *w, screen->windows ())
1742
 
        {
1743
 
            int moveX = 0;
1744
 
            int moveY = 0;
1745
 
 
1746
 
            if (w->onAllViewports ())
1747
 
                continue;
1748
 
 
1749
 
            /* Find which viewport the (inner) window's top-left corner falls
1750
 
               in, and check if it's outside the new viewport horizontal and
1751
 
               vertical index range */
1752
 
            if (newh < screen->vpSize ().width ())
1753
 
            {
1754
 
                int vpX;   /* x index of a window's vp */
1755
 
 
1756
 
                vpX = w->serverX () / screen->width ();
1757
 
                if (w->serverX () < 0)
1758
 
                    vpX -= 1;
1759
 
 
1760
 
                vpX += screen->vp ().x (); /* Convert relative to absolute vp index */
1761
 
 
1762
 
                /* Move windows too far right to left */
1763
 
                if (vpX >= newh)
1764
 
                    moveX = ((newh - 1) - vpX) * screen->width ();
1765
 
            }
1766
 
            if (newv < screen->vpSize ().height ())
1767
 
            {
1768
 
                int vpY;   /* y index of a window's vp */
1769
 
 
1770
 
                vpY = w->serverY () / screen->height ();
1771
 
                if (w->serverY () < 0)
1772
 
                    vpY -= 1;
1773
 
 
1774
 
                vpY += screen->vp ().y (); /* Convert relative to absolute vp index */
1775
 
 
1776
 
                /* Move windows too far right to left */
1777
 
                if (vpY >= newv)
1778
 
                    moveY = ((newv - 1) - vpY) * screen->height ();
1779
 
            }
1780
 
 
1781
 
            if (moveX != 0 || moveY != 0)
1782
 
            {
1783
 
                w->move (moveX, moveY, true);
1784
 
                w->syncPosition ();
1785
 
            }
1786
 
        }
1787
 
    }
1788
 
 
1789
 
    vpSize.setWidth (newh);
1790
 
    vpSize.setHeight (newv);
1791
 
 
1792
 
    setDesktopHints ();
1793
 
}
1794
 
 
1795
 
void
1796
 
PrivateScreen::updateOutputDevices ()
1797
 
{
1798
 
    CompOption::Value::Vector &list = optionGetOutputs ();
1799
 
    unsigned int              nOutput = 0;
1800
 
    int                       x, y, bits;
1801
 
    unsigned int              uWidth, uHeight;
1802
 
    int                       width, height;
1803
 
    int                       x1, y1, x2, y2;
1804
 
    char                      str[10];
1805
 
 
1806
 
    foreach (CompOption::Value &value, list)
1807
 
    {
1808
 
        x      = 0;
1809
 
        y      = 0;
1810
 
        uWidth  = (unsigned) screen->width ();
1811
 
        uHeight = (unsigned) screen->height ();
1812
 
 
1813
 
        bits = XParseGeometry (value.s ().c_str (), &x, &y, &uWidth, &uHeight);
1814
 
        width  = (int) uWidth;
1815
 
        height = (int) uHeight;
1816
 
 
1817
 
        if (bits & XNegative)
1818
 
            x = screen->width () + x - width;
1819
 
 
1820
 
        if (bits & YNegative)
1821
 
            y = screen->height () + y - height;
1822
 
 
1823
 
        x1 = x;
1824
 
        y1 = y;
1825
 
        x2 = x + width;
1826
 
        y2 = y + height;
1827
 
 
1828
 
        if (x1 < 0)
1829
 
            x1 = 0;
1830
 
        if (y1 < 0)
1831
 
            y1 = 0;
1832
 
        if (x2 > screen->width ())
1833
 
            x2 = screen->width ();
1834
 
        if (y2 > screen->height ())
1835
 
            y2 = screen->height ();
1836
 
 
1837
 
        if (x1 < x2 && y1 < y2)
1838
 
        {
1839
 
            if (outputDevs.size () < nOutput + 1)
1840
 
                outputDevs.resize (nOutput + 1);
1841
 
 
1842
 
            outputDevs[nOutput].setGeometry (x1, y1, x2 - x1, y2 - y1);
1843
 
            nOutput++;
1844
 
        }
1845
 
    }
1846
 
 
1847
 
    /* make sure we have at least one output */
1848
 
    if (!nOutput)
1849
 
    {
1850
 
        if (outputDevs.size () < 1)
1851
 
            outputDevs.resize (1);
1852
 
 
1853
 
        outputDevs[0].setGeometry (0, 0, screen->width (), screen->height ());
1854
 
        nOutput = 1;
1855
 
    }
1856
 
 
1857
 
    if (outputDevs.size () > nOutput)
1858
 
        outputDevs.resize (nOutput);
1859
 
 
1860
 
    /* set name, width, height and update rect pointers in all regions */
1861
 
    for (unsigned int i = 0; i < nOutput; i++)
1862
 
    {
1863
 
        snprintf (str, 10, "Output %d", i);
1864
 
        outputDevs[i].setId (str, i);
1865
 
    }
1866
 
 
1867
 
    hasOverlappingOutputs = false;
1868
 
 
1869
 
    setCurrentOutput (currentOutputDev);
1870
 
 
1871
 
    /* clear out fullscreen monitor hints of all windows as
1872
 
       suggested on monitor layout changes in EWMH */
1873
 
    foreach (CompWindow *w, windows)
1874
 
        if (w->priv->fullscreenMonitorsSet)
1875
 
            w->priv->setFullscreenMonitors (NULL);
1876
 
 
1877
 
    for (unsigned int i = 0; i < nOutput - 1; i++)
1878
 
        for (unsigned int j = i + 1; j < nOutput; j++)
1879
 
            if (outputDevs[i].intersects (outputDevs[j]))
1880
 
                hasOverlappingOutputs = true;
1881
 
 
1882
 
    screen->updateWorkarea ();
1883
 
 
1884
 
    screen->outputChangeNotify ();
1885
 
}
1886
 
 
1887
 
void
1888
 
PrivateScreen::detectOutputDevices ()
1889
 
{
1890
 
    if (!noDetection && optionGetDetectOutputs ())
1891
 
    {
1892
 
        CompString        name;
1893
 
        CompOption::Value value;
1894
 
 
1895
 
        if (screenInfo.size ())
1896
 
        {
1897
 
            CompOption::Value::Vector l;
1898
 
            foreach (XineramaScreenInfo xi, screenInfo)
1899
 
            {
1900
 
                l.push_back (compPrintf ("%dx%d+%d+%d", xi.width, xi.height,
1901
 
                                         xi.x_org, xi.y_org));
1902
 
            }
1903
 
 
1904
 
            value.set (CompOption::TypeString, l);
1905
 
        }
1906
 
        else
1907
 
        {
1908
 
            CompOption::Value::Vector l;
1909
 
            l.push_back (compPrintf ("%dx%d+%d+%d", screen->width (),
1910
 
                                     screen->height (), 0, 0));
1911
 
            value.set (CompOption::TypeString, l);
1912
 
        }
1913
 
 
1914
 
        mOptions[CoreOptions::DetectOutputs].value ().set (false);
1915
 
        screen->setOptionForPlugin ("core", "outputs", value);
1916
 
        mOptions[CoreOptions::DetectOutputs].value ().set (true);
1917
 
 
1918
 
    }
1919
 
    else
1920
 
    {
1921
 
        updateOutputDevices ();
1922
 
    }
1923
 
}
1924
 
 
1925
 
 
1926
 
void
1927
 
PrivateScreen::updateStartupFeedback ()
1928
 
{
1929
 
    if (!startupSequences.empty ())
1930
 
        XDefineCursor (dpy, root, busyCursor);
1931
 
    else
1932
 
        XDefineCursor (dpy, root, normalCursor);
1933
 
}
1934
 
 
1935
 
#define STARTUP_TIMEOUT_DELAY 15000
1936
 
 
1937
 
bool
1938
 
PrivateScreen::handleStartupSequenceTimeout ()
1939
 
{
1940
 
    struct timeval      now, active;
1941
 
    double              elapsed;
1942
 
 
1943
 
    gettimeofday (&now, NULL);
1944
 
 
1945
 
    foreach (CompStartupSequence *s, startupSequences)
1946
 
    {
1947
 
        sn_startup_sequence_get_last_active_time (s->sequence,
1948
 
                                                  &active.tv_sec,
1949
 
                                                  &active.tv_usec);
1950
 
 
1951
 
        elapsed = ((((double) now.tv_sec - active.tv_sec) * 1000000.0 +
1952
 
                    (now.tv_usec - active.tv_usec))) / 1000.0;
1953
 
 
1954
 
        if (elapsed > STARTUP_TIMEOUT_DELAY)
1955
 
            sn_startup_sequence_complete (s->sequence);
1956
 
    }
1957
 
 
1958
 
    return true;
1959
 
}
1960
 
 
1961
 
void
1962
 
PrivateScreen::addSequence (SnStartupSequence *sequence)
1963
 
{
1964
 
    CompStartupSequence *s;
1965
 
 
1966
 
    s = new CompStartupSequence ();
1967
 
    if (!s)
1968
 
        return;
1969
 
 
1970
 
    sn_startup_sequence_ref (sequence);
1971
 
 
1972
 
    s->sequence = sequence;
1973
 
    s->viewportX = vp.x ();
1974
 
    s->viewportY = vp.y ();
1975
 
 
1976
 
    startupSequences.push_front (s);
1977
 
 
1978
 
    if (!startupSequenceTimer.active ())
1979
 
        startupSequenceTimer.start ();
1980
 
 
1981
 
    updateStartupFeedback ();
1982
 
}
1983
 
 
1984
 
void
1985
 
PrivateScreen::removeSequence (SnStartupSequence *sequence)
1986
 
{
1987
 
    CompStartupSequence *s = NULL;
1988
 
 
1989
 
    std::list<CompStartupSequence *>::iterator it = startupSequences.begin ();
1990
 
 
1991
 
    for (; it != startupSequences.end (); it++)
1992
 
    {
1993
 
        if ((*it)->sequence == sequence)
1994
 
        {
1995
 
            s = (*it);
1996
 
            break;
1997
 
        }
1998
 
    }
1999
 
 
2000
 
    if (!s)
2001
 
        return;
2002
 
 
2003
 
    sn_startup_sequence_unref (sequence);
2004
 
 
2005
 
    startupSequences.erase (it);
2006
 
 
2007
 
    delete s;
2008
 
 
2009
 
    if (startupSequences.empty () && startupSequenceTimer.active ())
2010
 
        startupSequenceTimer.stop ();
2011
 
 
2012
 
    updateStartupFeedback ();
2013
 
}
2014
 
 
2015
 
void
2016
 
PrivateScreen::removeAllSequences ()
2017
 
{
2018
 
    foreach (CompStartupSequence *s, startupSequences)
2019
 
    {
2020
 
        sn_startup_sequence_unref (s->sequence);
2021
 
        delete s;
2022
 
    }
2023
 
 
2024
 
    startupSequences.clear ();
2025
 
 
2026
 
    if (startupSequenceTimer.active ())
2027
 
        startupSequenceTimer.stop ();
2028
 
 
2029
 
    updateStartupFeedback ();
2030
 
}
2031
 
 
2032
 
void
2033
 
CompScreen::compScreenSnEvent (SnMonitorEvent *event,
2034
 
                               void           *userData)
2035
 
{
2036
 
    CompScreen        *screen = (CompScreen *) userData;
2037
 
    SnStartupSequence *sequence;
2038
 
 
2039
 
    sequence = sn_monitor_event_get_startup_sequence (event);
2040
 
 
2041
 
    switch (sn_monitor_event_get_type (event)) {
2042
 
    case SN_MONITOR_EVENT_INITIATED:
2043
 
        screen->priv->addSequence (sequence);
2044
 
        break;
2045
 
    case SN_MONITOR_EVENT_COMPLETED:
2046
 
        screen->priv->removeSequence (sequence);
2047
 
        break;
2048
 
    case SN_MONITOR_EVENT_CHANGED:
2049
 
    case SN_MONITOR_EVENT_CANCELED:
2050
 
        break;
2051
 
    }
2052
 
}
2053
 
 
2054
 
void
2055
 
PrivateScreen::updateScreenEdges ()
2056
 
{
2057
 
    struct screenEdgeGeometry {
2058
 
        int xw, x0;
2059
 
        int yh, y0;
2060
 
        int ww, w0;
2061
 
        int hh, h0;
2062
 
    } geometry[SCREEN_EDGE_NUM] = {
2063
 
        { 0,  0,   0,  2,   0,  2,   1, -4 }, /* left */
2064
 
        { 1, -2,   0,  2,   0,  2,   1, -4 }, /* right */
2065
 
        { 0,  2,   0,  0,   1, -4,   0,  2 }, /* top */
2066
 
        { 0,  2,   1, -2,   1, -4,   0,  2 }, /* bottom */
2067
 
        { 0,  0,   0,  0,   0,  2,   0,  2 }, /* top-left */
2068
 
        { 1, -2,   0,  0,   0,  2,   0,  2 }, /* top-right */
2069
 
        { 0,  0,   1, -2,   0,  2,   0,  2 }, /* bottom-left */
2070
 
        { 1, -2,   1, -2,   0,  2,   0,  2 }  /* bottom-right */
2071
 
    };
2072
 
    int i;
2073
 
 
2074
 
    for (i = 0; i < SCREEN_EDGE_NUM; i++)
2075
 
    {
2076
 
        if (screenEdge[i].id)
2077
 
            XMoveResizeWindow (dpy, screenEdge[i].id,
2078
 
                               geometry[i].xw * screen->width () +
2079
 
                               geometry[i].x0,
2080
 
                               geometry[i].yh * screen->height () +
2081
 
                               geometry[i].y0,
2082
 
                               geometry[i].ww * screen->width () +
2083
 
                               geometry[i].w0,
2084
 
                               geometry[i].hh * screen->height () +
2085
 
                               geometry[i].h0);
2086
 
    }
2087
 
}
2088
 
 
2089
 
void
2090
 
PrivateScreen::setCurrentOutput (unsigned int outputNum)
2091
 
{
2092
 
    if (outputNum >= priv->outputDevs.size ())
2093
 
        outputNum = 0;
2094
 
 
2095
 
    priv->currentOutputDev = outputNum;
2096
 
}
2097
 
 
2098
 
void
2099
 
PrivateScreen::reshape (int w, int h)
2100
 
{
2101
 
    updateScreenInfo ();
2102
 
 
2103
 
    region = CompRegion (0, 0, w, h);
2104
 
 
2105
 
    screen->setWidth (w);
2106
 
    screen->setHeight (h);
2107
 
 
2108
 
    fullscreenOutput.setId ("fullscreen", ~0);
2109
 
    fullscreenOutput.setGeometry (0, 0, w, h);
2110
 
 
2111
 
    updateScreenEdges ();
2112
 
}
2113
 
 
2114
 
void
2115
 
PrivateScreen::configure (XConfigureEvent *ce)
2116
 
{
2117
 
    if (priv->attrib.width  != ce->width ||
2118
 
        priv->attrib.height != ce->height)
2119
 
    {
2120
 
        priv->attrib.width  = ce->width;
2121
 
        priv->attrib.height = ce->height;
2122
 
 
2123
 
        priv->reshape (ce->width, ce->height);
2124
 
 
2125
 
        priv->detectOutputDevices ();
2126
 
    }
2127
 
}
2128
 
 
2129
 
void
2130
 
PrivateScreen::setSupportingWmCheck ()
2131
 
{
2132
 
    XChangeProperty (dpy, grabWindow,
2133
 
                     Atoms::supportingWmCheck,
2134
 
                     XA_WINDOW, 32, PropModeReplace,
2135
 
                     (unsigned char *) &grabWindow, 1);
2136
 
 
2137
 
    XChangeProperty (dpy, grabWindow, Atoms::wmName,
2138
 
                     Atoms::utf8String, 8, PropModeReplace,
2139
 
                     (unsigned char *) PACKAGE, strlen (PACKAGE));
2140
 
    XChangeProperty (dpy, grabWindow, Atoms::winState,
2141
 
                     XA_ATOM, 32, PropModeReplace,
2142
 
                     (unsigned char *) &Atoms::winStateSkipTaskbar,
2143
 
                     1);
2144
 
    XChangeProperty (dpy, grabWindow, Atoms::winState,
2145
 
                     XA_ATOM, 32, PropModeAppend,
2146
 
                     (unsigned char *) &Atoms::winStateSkipPager, 1);
2147
 
    XChangeProperty (dpy, grabWindow, Atoms::winState,
2148
 
                     XA_ATOM, 32, PropModeAppend,
2149
 
                     (unsigned char *) &Atoms::winStateHidden, 1);
2150
 
 
2151
 
    XChangeProperty (dpy, root, Atoms::supportingWmCheck,
2152
 
                     XA_WINDOW, 32, PropModeReplace,
2153
 
                     (unsigned char *) &grabWindow, 1);
2154
 
}
2155
 
 
2156
 
void
2157
 
CompScreen::updateSupportedWmHints ()
2158
 
{
2159
 
    std::vector<Atom> atoms;
2160
 
 
2161
 
    addSupportedAtoms (atoms);
2162
 
 
2163
 
    XChangeProperty (dpy (), root (), Atoms::supported,
2164
 
                     XA_ATOM, 32, PropModeReplace,
2165
 
                     (const unsigned char *) &atoms.at (0), atoms.size ());
2166
 
}
2167
 
 
2168
 
void
2169
 
CompScreen::addSupportedAtoms (std::vector<Atom> &atoms)
2170
 
{
2171
 
    WRAPABLE_HND_FUNC (17, addSupportedAtoms, atoms);
2172
 
 
2173
 
    atoms.push_back (Atoms::supported);
2174
 
    atoms.push_back (Atoms::supportingWmCheck);
2175
 
 
2176
 
    atoms.push_back (Atoms::utf8String);
2177
 
 
2178
 
    atoms.push_back (Atoms::clientList);
2179
 
    atoms.push_back (Atoms::clientListStacking);
2180
 
 
2181
 
    atoms.push_back (Atoms::winActive);
2182
 
 
2183
 
    atoms.push_back (Atoms::desktopViewport);
2184
 
    atoms.push_back (Atoms::desktopGeometry);
2185
 
    atoms.push_back (Atoms::currentDesktop);
2186
 
    atoms.push_back (Atoms::numberOfDesktops);
2187
 
    atoms.push_back (Atoms::showingDesktop);
2188
 
 
2189
 
    atoms.push_back (Atoms::workarea);
2190
 
 
2191
 
    atoms.push_back (Atoms::wmName);
2192
 
/*
2193
 
    atoms.push_back (Atoms::wmVisibleName);
2194
 
*/
2195
 
 
2196
 
    atoms.push_back (Atoms::wmStrut);
2197
 
    atoms.push_back (Atoms::wmStrutPartial);
2198
 
 
2199
 
/*
2200
 
    atoms.push_back (Atoms::wmPid);
2201
 
*/
2202
 
 
2203
 
    atoms.push_back (Atoms::wmUserTime);
2204
 
    atoms.push_back (Atoms::frameExtents);
2205
 
    atoms.push_back (Atoms::frameWindow);
2206
 
 
2207
 
    atoms.push_back (Atoms::winState);
2208
 
    atoms.push_back (Atoms::winStateModal);
2209
 
    atoms.push_back (Atoms::winStateSticky);
2210
 
    atoms.push_back (Atoms::winStateMaximizedVert);
2211
 
    atoms.push_back (Atoms::winStateMaximizedHorz);
2212
 
    atoms.push_back (Atoms::winStateShaded);
2213
 
    atoms.push_back (Atoms::winStateSkipTaskbar);
2214
 
    atoms.push_back (Atoms::winStateSkipPager);
2215
 
    atoms.push_back (Atoms::winStateHidden);
2216
 
    atoms.push_back (Atoms::winStateFullscreen);
2217
 
    atoms.push_back (Atoms::winStateAbove);
2218
 
    atoms.push_back (Atoms::winStateBelow);
2219
 
    atoms.push_back (Atoms::winStateDemandsAttention);
2220
 
 
2221
 
    atoms.push_back (Atoms::winOpacity);
2222
 
    atoms.push_back (Atoms::winBrightness);
2223
 
 
2224
 
#warning fixme
2225
 
#if 0
2226
 
    if (canDoSaturated)
2227
 
    {
2228
 
        atoms.push_back (Atoms::winSaturation);
2229
 
        atoms.push_back (Atoms::winStateDisplayModal);
2230
 
    }
2231
 
#endif
2232
 
 
2233
 
    atoms.push_back (Atoms::wmAllowedActions);
2234
 
 
2235
 
    atoms.push_back (Atoms::winActionMove);
2236
 
    atoms.push_back (Atoms::winActionResize);
2237
 
    atoms.push_back (Atoms::winActionStick);
2238
 
    atoms.push_back (Atoms::winActionMinimize);
2239
 
    atoms.push_back (Atoms::winActionMaximizeHorz);
2240
 
    atoms.push_back (Atoms::winActionMaximizeVert);
2241
 
    atoms.push_back (Atoms::winActionFullscreen);
2242
 
    atoms.push_back (Atoms::winActionClose);
2243
 
    atoms.push_back (Atoms::winActionShade);
2244
 
    atoms.push_back (Atoms::winActionChangeDesktop);
2245
 
    atoms.push_back (Atoms::winActionAbove);
2246
 
    atoms.push_back (Atoms::winActionBelow);
2247
 
 
2248
 
    atoms.push_back (Atoms::winType);
2249
 
    atoms.push_back (Atoms::winTypeDesktop);
2250
 
    atoms.push_back (Atoms::winTypeDock);
2251
 
    atoms.push_back (Atoms::winTypeToolbar);
2252
 
    atoms.push_back (Atoms::winTypeMenu);
2253
 
    atoms.push_back (Atoms::winTypeSplash);
2254
 
    atoms.push_back (Atoms::winTypeDialog);
2255
 
    atoms.push_back (Atoms::winTypeUtil);
2256
 
    atoms.push_back (Atoms::winTypeNormal);
2257
 
 
2258
 
    atoms.push_back (Atoms::wmDeleteWindow);
2259
 
    atoms.push_back (Atoms::wmPing);
2260
 
 
2261
 
    atoms.push_back (Atoms::wmMoveResize);
2262
 
    atoms.push_back (Atoms::moveResizeWindow);
2263
 
    atoms.push_back (Atoms::restackWindow);
2264
 
 
2265
 
    atoms.push_back (Atoms::wmFullscreenMonitors);
2266
 
}
2267
 
 
2268
 
void
2269
 
PrivateScreen::getDesktopHints ()
2270
 
{
2271
 
    unsigned long data[2];
2272
 
    Atom          actual;
2273
 
    int           result, format;
2274
 
    unsigned long n, left;
2275
 
    unsigned char *propData;
2276
 
 
2277
 
    if (useDesktopHints)
2278
 
    {
2279
 
        result = XGetWindowProperty (dpy, root,
2280
 
                                     Atoms::numberOfDesktops,
2281
 
                                     0L, 1L, false, XA_CARDINAL, &actual,
2282
 
                                     &format, &n, &left, &propData);
2283
 
 
2284
 
        if (result == Success && propData)
2285
 
        {
2286
 
            if (n)
2287
 
            {
2288
 
                memcpy (data, propData, sizeof (unsigned long));
2289
 
                if (data[0] > 0 && data[0] < 0xffffffff)
2290
 
                    nDesktop = data[0];
2291
 
            }
2292
 
 
2293
 
            XFree (propData);
2294
 
        }
2295
 
 
2296
 
        result = XGetWindowProperty (dpy, root,
2297
 
                                     Atoms::desktopViewport, 0L, 2L,
2298
 
                                     false, XA_CARDINAL, &actual, &format,
2299
 
                                     &n, &left, &propData);
2300
 
 
2301
 
        if (result == Success && propData)
2302
 
        {
2303
 
            if (n == 2)
2304
 
            {
2305
 
                memcpy (data, propData, sizeof (unsigned long) * 2);
2306
 
 
2307
 
                if (data[0] / (unsigned int) screen->width () <
2308
 
                                             (unsigned int) vpSize.width () - 1)
2309
 
                    vp.setX (data[0] / screen->width ());
2310
 
 
2311
 
                if (data[1] / (unsigned int) screen->height () <
2312
 
                                            (unsigned int) vpSize.height () - 1)
2313
 
                    vp.setY (data[1] / screen->height ());
2314
 
            }
2315
 
 
2316
 
            XFree (propData);
2317
 
        }
2318
 
 
2319
 
        result = XGetWindowProperty (dpy, root,
2320
 
                                     Atoms::currentDesktop,
2321
 
                                     0L, 1L, false, XA_CARDINAL, &actual,
2322
 
                                     &format, &n, &left, &propData);
2323
 
 
2324
 
        if (result == Success && propData)
2325
 
        {
2326
 
            if (n)
2327
 
            {
2328
 
                memcpy (data, propData, sizeof (unsigned long));
2329
 
                if (data[0] < nDesktop)
2330
 
                    currentDesktop = data[0];
2331
 
            }
2332
 
 
2333
 
            XFree (propData);
2334
 
        }
2335
 
    }
2336
 
 
2337
 
    result = XGetWindowProperty (dpy, root,
2338
 
                                 Atoms::showingDesktop,
2339
 
                                 0L, 1L, false, XA_CARDINAL, &actual, &format,
2340
 
                                 &n, &left, &propData);
2341
 
 
2342
 
    if (result == Success && propData)
2343
 
    {
2344
 
        if (n)
2345
 
        {
2346
 
            memcpy (data, propData, sizeof (unsigned long));
2347
 
            if (data[0])
2348
 
                screen->enterShowDesktopMode ();
2349
 
        }
2350
 
 
2351
 
        XFree (propData);
2352
 
    }
2353
 
 
2354
 
    data[0] = currentDesktop;
2355
 
 
2356
 
    XChangeProperty (dpy, root, Atoms::currentDesktop,
2357
 
                     XA_CARDINAL, 32, PropModeReplace,
2358
 
                     (unsigned char *) data, 1);
2359
 
 
2360
 
    data[0] = showingDesktopMask ? true : false;
2361
 
 
2362
 
    XChangeProperty (dpy, root, Atoms::showingDesktop,
2363
 
                     XA_CARDINAL, 32, PropModeReplace,
2364
 
                     (unsigned char *) data, 1);
2365
 
}
2366
 
 
2367
 
void
2368
 
CompScreen::enterShowDesktopMode ()
2369
 
{
2370
 
    WRAPABLE_HND_FUNC (14, enterShowDesktopMode)
2371
 
 
2372
 
    unsigned long data = 1;
2373
 
    int           count = 0;
2374
 
    bool          st = priv->optionGetHideSkipTaskbarWindows ();
2375
 
 
2376
 
    priv->showingDesktopMask = ~(CompWindowTypeDesktopMask |
2377
 
                                 CompWindowTypeDockMask);
2378
 
 
2379
 
    foreach (CompWindow *w, priv->windows)
2380
 
    {
2381
 
        if ((priv->showingDesktopMask & w->wmType ()) &&
2382
 
            (!(w->state () & CompWindowStateSkipTaskbarMask) || st))
2383
 
        {
2384
 
            if (!w->inShowDesktopMode () && !w->grabbed () &&
2385
 
                w->managed () && w->focus ())
2386
 
            {
2387
 
                w->setShowDesktopMode (true);
2388
 
                w->windowNotify (CompWindowNotifyEnterShowDesktopMode);
2389
 
                w->priv->hide ();
2390
 
            }
2391
 
        }
2392
 
 
2393
 
        if (w->inShowDesktopMode ())
2394
 
            count++;
2395
 
    }
2396
 
 
2397
 
    if (!count)
2398
 
    {
2399
 
        priv->showingDesktopMask = 0;
2400
 
        data = 0;
2401
 
    }
2402
 
 
2403
 
    XChangeProperty (priv->dpy, priv->root,
2404
 
                     Atoms::showingDesktop,
2405
 
                     XA_CARDINAL, 32, PropModeReplace,
2406
 
                     (unsigned char *) &data, 1);
2407
 
}
2408
 
 
2409
 
void
2410
 
CompScreen::leaveShowDesktopMode (CompWindow *window)
2411
 
{
2412
 
    WRAPABLE_HND_FUNC (15, leaveShowDesktopMode, window)
2413
 
 
2414
 
    unsigned long data = 0;
2415
 
 
2416
 
    if (window)
2417
 
    {
2418
 
        if (!window->inShowDesktopMode ())
2419
 
            return;
2420
 
 
2421
 
        window->setShowDesktopMode (false);
2422
 
        window->windowNotify (CompWindowNotifyLeaveShowDesktopMode);
2423
 
        window->priv->show ();
2424
 
 
2425
 
        /* return if some other window is still in show desktop mode */
2426
 
        foreach (CompWindow *w, priv->windows)
2427
 
            if (w->inShowDesktopMode ())
2428
 
                return;
2429
 
 
2430
 
        priv->showingDesktopMask = 0;
2431
 
    }
2432
 
    else
2433
 
    {
2434
 
        priv->showingDesktopMask = 0;
2435
 
 
2436
 
        foreach (CompWindow *w, priv->windows)
2437
 
        {
2438
 
            if (!w->inShowDesktopMode ())
2439
 
                continue;
2440
 
 
2441
 
            w->setShowDesktopMode (false);
2442
 
            w->windowNotify (CompWindowNotifyLeaveShowDesktopMode);
2443
 
            w->priv->show ();
2444
 
        }
2445
 
 
2446
 
        /* focus default window - most likely this will be the window
2447
 
           which had focus before entering showdesktop mode */
2448
 
        focusDefaultWindow ();
2449
 
    }
2450
 
 
2451
 
    XChangeProperty (priv->dpy, priv->root,
2452
 
                     Atoms::showingDesktop,
2453
 
                     XA_CARDINAL, 32, PropModeReplace,
2454
 
                     (unsigned char *) &data, 1);
2455
 
}
2456
 
 
2457
 
void
2458
 
CompScreen::forEachWindow (CompWindow::ForEach proc)
2459
 
{
2460
 
    foreach (CompWindow *w, priv->windows)
2461
 
        proc (w);
2462
 
}
2463
 
 
2464
 
void
2465
 
CompScreen::focusDefaultWindow ()
2466
 
{
2467
 
    CompWindow  *w;
2468
 
    CompWindow  *focus = NULL;
2469
 
 
2470
 
    if (!priv->optionGetClickToFocus ())
2471
 
    {
2472
 
        w = findTopLevelWindow (priv->below);
2473
 
 
2474
 
        if (w && w->focus ())
2475
 
        {
2476
 
            if (!(w->type () & (CompWindowTypeDesktopMask |
2477
 
                                CompWindowTypeDockMask)))
2478
 
                focus = w;
2479
 
        }
2480
 
        else
2481
 
        {
2482
 
            bool         status;
2483
 
            Window       rootReturn, childReturn;
2484
 
            int          dummyInt;
2485
 
            unsigned int dummyUInt;
2486
 
 
2487
 
            /* huh, we didn't find d->below ... perhaps it's out of date;
2488
 
               try grabbing it through the server */
2489
 
 
2490
 
            status = XQueryPointer (dpy (), priv->root, &rootReturn,
2491
 
                                    &childReturn, &dummyInt, &dummyInt,
2492
 
                                    &dummyInt, &dummyInt, &dummyUInt);
2493
 
 
2494
 
            if (status && rootReturn == priv->root)
2495
 
            {
2496
 
                w = findTopLevelWindow (childReturn);
2497
 
 
2498
 
                if (w && w->focus ())
2499
 
                {
2500
 
                    if (!(w->type () & (CompWindowTypeDesktopMask |
2501
 
                                        CompWindowTypeDockMask)))
2502
 
                        focus = w;
2503
 
                }
2504
 
            }
2505
 
        }
2506
 
    }
2507
 
 
2508
 
    if (!focus)
2509
 
    {
2510
 
        for (CompWindowList::reverse_iterator rit = priv->windows.rbegin ();
2511
 
             rit != priv->windows.rend (); rit++)
2512
 
        {
2513
 
            w = (*rit);
2514
 
 
2515
 
            if (w->type () & CompWindowTypeDockMask)
2516
 
                continue;
2517
 
 
2518
 
            if (w->focus ())
2519
 
            {
2520
 
                if (focus)
2521
 
                {
2522
 
                    if (w->type () & (CompWindowTypeNormalMask |
2523
 
                                      CompWindowTypeDialogMask |
2524
 
                                      CompWindowTypeModalDialogMask))
2525
 
                    {
2526
 
                        if (PrivateWindow::compareWindowActiveness (focus, w) < 0)
2527
 
                            focus = w;
2528
 
                    }
2529
 
                }
2530
 
                else
2531
 
                    focus = w;
2532
 
            }
2533
 
        }
2534
 
    }
2535
 
 
2536
 
    if (focus)
2537
 
    {
2538
 
        if (focus->id () != priv->activeWindow)
2539
 
            focus->moveInputFocusTo ();
2540
 
    }
2541
 
    else
2542
 
    {
2543
 
        XSetInputFocus (priv->dpy, priv->root, RevertToPointerRoot,
2544
 
                        CurrentTime);
2545
 
    }
2546
 
}
2547
 
 
2548
 
CompWindow *
2549
 
CompScreen::findWindow (Window id)
2550
 
{
2551
 
    if (lastFoundWindow && lastFoundWindow->id () == id)
2552
 
    {
2553
 
        return lastFoundWindow;
2554
 
    }
2555
 
    else
2556
 
    {
2557
 
        CompWindow::Map::iterator it = priv->windowsMap.find (id);
2558
 
 
2559
 
        if (it != priv->windowsMap.end ())
2560
 
            return (lastFoundWindow = it->second);
2561
 
    }
2562
 
 
2563
 
    return 0;
2564
 
}
2565
 
 
2566
 
CompWindow *
2567
 
CompScreen::findTopLevelWindow (Window id, bool override_redirect)
2568
 
{
2569
 
    CompWindow *w;
2570
 
 
2571
 
    w = findWindow (id);
2572
 
 
2573
 
    if (w)
2574
 
    {
2575
 
        if (w->overrideRedirect () && !override_redirect)
2576
 
            return NULL;
2577
 
        else
2578
 
            return w;
2579
 
    }
2580
 
 
2581
 
    foreach (CompWindow *w, priv->windows)
2582
 
        if (w->frame () == id)
2583
 
        {
2584
 
            if (w->overrideRedirect () && !override_redirect)
2585
 
                return NULL;
2586
 
            else
2587
 
                return w;
2588
 
        }
2589
 
 
2590
 
    return NULL;
2591
 
}
2592
 
 
2593
 
void
2594
 
CompScreen::insertWindow (CompWindow *w, Window aboveId)
2595
 
{
2596
 
    w->prev = NULL;
2597
 
    w->next = NULL;
2598
 
 
2599
 
    if (!aboveId || priv->windows.empty ())
2600
 
    {
2601
 
        if (!priv->windows.empty ())
2602
 
        {
2603
 
            priv->windows.front ()->prev = w;
2604
 
            w->next = priv->windows.front ();
2605
 
        }
2606
 
        priv->windows.push_front (w);
2607
 
        if (w->id () != 1)
2608
 
            priv->windowsMap[w->id ()] = w;
2609
 
 
2610
 
        return;
2611
 
    }
2612
 
 
2613
 
    CompWindowList::iterator it = priv->windows.begin ();
2614
 
 
2615
 
    while (it != priv->windows.end ())
2616
 
    {
2617
 
        if ((*it)->id () == aboveId ||
2618
 
            ((*it)->frame () && (*it)->frame () == aboveId))
2619
 
        {
2620
 
            break;
2621
 
        }
2622
 
        it++;
2623
 
    }
2624
 
 
2625
 
    if (it == priv->windows.end ())
2626
 
    {
2627
 
#ifdef DEBUG
2628
 
        abort ();
2629
 
#endif
2630
 
        return;
2631
 
    }
2632
 
 
2633
 
    w->next = (*it)->next;
2634
 
    w->prev = (*it);
2635
 
    (*it)->next = w;
2636
 
 
2637
 
    if (w->next)
2638
 
    {
2639
 
        w->next->prev = w;
2640
 
    }
2641
 
 
2642
 
    priv->windows.insert (++it, w);
2643
 
    if (w->id () != 1)
2644
 
        priv->windowsMap[w->id ()] = w;
2645
 
}
2646
 
 
2647
 
void
2648
 
PrivateScreen::eraseWindowFromMap (Window id)
2649
 
{
2650
 
    if (id != 1)
2651
 
        priv->windowsMap.erase (id);
2652
 
}
2653
 
 
2654
 
void
2655
 
CompScreen::unhookWindow (CompWindow *w)
2656
 
{
2657
 
    CompWindowList::iterator it =
2658
 
        std::find (priv->windows.begin (), priv->windows.end (), w);
2659
 
 
2660
 
    priv->windows.erase (it);
2661
 
    priv->eraseWindowFromMap (w->id ());
2662
 
 
2663
 
    if (w->next)
2664
 
        w->next->prev = w->prev;
2665
 
 
2666
 
    if (w->prev)
2667
 
        w->prev->next = w->next;
2668
 
 
2669
 
    w->next = NULL;
2670
 
    w->prev = NULL;
2671
 
 
2672
 
    if (w == lastFoundWindow)
2673
 
        lastFoundWindow = NULL;
2674
 
}
2675
 
 
2676
 
Cursor
2677
 
CompScreen::normalCursor ()
2678
 
{
2679
 
    return priv->normalCursor;
2680
 
}
2681
 
 
2682
 
Cursor
2683
 
CompScreen::invisibleCursor ()
2684
 
{
2685
 
    return priv->invisibleCursor;
2686
 
}
2687
 
 
2688
 
#define POINTER_GRAB_MASK (ButtonReleaseMask | \
2689
 
                           ButtonPressMask   | \
2690
 
                           PointerMotionMask)
2691
 
CompScreen::GrabHandle
2692
 
CompScreen::pushGrab (Cursor cursor, const char *name)
2693
 
{
2694
 
    if (priv->grabs.empty ())
2695
 
    {
2696
 
        int status;
2697
 
 
2698
 
        status = XGrabPointer (priv->dpy, priv->grabWindow, true,
2699
 
                               POINTER_GRAB_MASK,
2700
 
                               GrabModeAsync, GrabModeAsync,
2701
 
                               priv->root, cursor,
2702
 
                               CurrentTime);
2703
 
 
2704
 
        if (status == GrabSuccess)
2705
 
        {
2706
 
            status = XGrabKeyboard (priv->dpy,
2707
 
                                    priv->grabWindow, true,
2708
 
                                    GrabModeAsync, GrabModeAsync,
2709
 
                                    CurrentTime);
2710
 
            if (status != GrabSuccess)
2711
 
            {
2712
 
                XUngrabPointer (priv->dpy, CurrentTime);
2713
 
                return NULL;
2714
 
            }
2715
 
        }
2716
 
        else
2717
 
            return NULL;
2718
 
    }
2719
 
    else
2720
 
    {
2721
 
        XChangeActivePointerGrab (priv->dpy, POINTER_GRAB_MASK,
2722
 
                                  cursor, CurrentTime);
2723
 
    }
2724
 
 
2725
 
    PrivateScreen::Grab *grab = new PrivateScreen::Grab ();
2726
 
    grab->cursor = cursor;
2727
 
    grab->name   = name;
2728
 
 
2729
 
    priv->grabs.push_back (grab);
2730
 
 
2731
 
    return grab;
2732
 
}
2733
 
 
2734
 
void
2735
 
CompScreen::updateGrab (CompScreen::GrabHandle handle, Cursor cursor)
2736
 
{
2737
 
    if (!handle)
2738
 
        return;
2739
 
 
2740
 
    XChangeActivePointerGrab (priv->dpy, POINTER_GRAB_MASK,
2741
 
                              cursor, CurrentTime);
2742
 
 
2743
 
    ((PrivateScreen::Grab *) handle)->cursor = cursor;
2744
 
}
2745
 
 
2746
 
void
2747
 
CompScreen::removeGrab (CompScreen::GrabHandle handle,
2748
 
                        CompPoint *restorePointer)
2749
 
{
2750
 
    if (!handle)
2751
 
        return;
2752
 
 
2753
 
    std::list<PrivateScreen::Grab *>::iterator it;
2754
 
 
2755
 
    it = std::find (priv->grabs.begin (), priv->grabs.end (), handle);
2756
 
 
2757
 
    if (it != priv->grabs.end ())
2758
 
    {
2759
 
        priv->grabs.erase (it);
2760
 
        delete (static_cast<PrivateScreen::Grab *> (handle));
2761
 
    }
2762
 
    if (!priv->grabs.empty ())
2763
 
    {
2764
 
        XChangeActivePointerGrab (priv->dpy,
2765
 
                                  POINTER_GRAB_MASK,
2766
 
                                  priv->grabs.back ()->cursor,
2767
 
                                  CurrentTime);
2768
 
    }
2769
 
    else
2770
 
    {
2771
 
        if (restorePointer)
2772
 
            warpPointer (restorePointer->x () - pointerX,
2773
 
                         restorePointer->y () - pointerY);
2774
 
 
2775
 
        XUngrabPointer (priv->dpy, CurrentTime);
2776
 
        XUngrabKeyboard (priv->dpy, CurrentTime);
2777
 
    }
2778
 
}
2779
 
 
2780
 
/* otherScreenGrabExist takes a series of strings terminated by a NULL.
2781
 
   It returns true if a grab exists but it is NOT held by one of the
2782
 
   plugins listed, returns false otherwise. */
2783
 
 
2784
 
bool
2785
 
CompScreen::otherGrabExist (const char *first, ...)
2786
 
{
2787
 
    va_list    ap;
2788
 
    const char *name;
2789
 
 
2790
 
    std::list<PrivateScreen::Grab *>::iterator it;
2791
 
 
2792
 
    for (it = priv->grabs.begin (); it != priv->grabs.end (); it++)
2793
 
    {
2794
 
        va_start (ap, first);
2795
 
 
2796
 
        name = first;
2797
 
        while (name)
2798
 
        {
2799
 
            if (strcmp (name, (*it)->name) == 0)
2800
 
                break;
2801
 
 
2802
 
            name = va_arg (ap, const char *);
2803
 
        }
2804
 
 
2805
 
        va_end (ap);
2806
 
 
2807
 
        if (!name)
2808
 
        return true;
2809
 
    }
2810
 
 
2811
 
    return false;
2812
 
}
2813
 
 
2814
 
bool
2815
 
CompScreen::grabExist (const char *grab)
2816
 
{
2817
 
    foreach (PrivateScreen::Grab* g, priv->grabs)
2818
 
    {
2819
 
        if (strcmp (g->name, grab) == 0)
2820
 
            return true;
2821
 
    }
2822
 
    return false;
2823
 
}
2824
 
 
2825
 
bool
2826
 
CompScreen::grabbed ()
2827
 
{
2828
 
    return priv->grabbed;
2829
 
}
2830
 
 
2831
 
void
2832
 
PrivateScreen::grabUngrabOneKey (unsigned int modifiers,
2833
 
                                 int          keycode,
2834
 
                                 bool         grab)
2835
 
{
2836
 
    if (grab)
2837
 
    {
2838
 
        XGrabKey (dpy,
2839
 
                  keycode,
2840
 
                  modifiers,
2841
 
                  root,
2842
 
                  true,
2843
 
                  GrabModeAsync,
2844
 
                  GrabModeAsync);
2845
 
    }
2846
 
    else
2847
 
    {
2848
 
        XUngrabKey (dpy,
2849
 
                    keycode,
2850
 
                    modifiers,
2851
 
                    root);
2852
 
    }
2853
 
}
2854
 
 
2855
 
bool
2856
 
PrivateScreen::grabUngrabKeys (unsigned int modifiers,
2857
 
                               int          keycode,
2858
 
                               bool         grab)
2859
 
{
2860
 
    int             mod, k;
2861
 
    unsigned int    ignore;
2862
 
 
2863
 
    CompScreen::checkForError (dpy);
2864
 
 
2865
 
    for (ignore = 0; ignore <= modHandler->ignoredModMask (); ignore++)
2866
 
    {
2867
 
        if (ignore & ~modHandler->ignoredModMask ())
2868
 
            continue;
2869
 
 
2870
 
        if (keycode != 0)
2871
 
        {
2872
 
            grabUngrabOneKey (modifiers | ignore, keycode, grab);
2873
 
        }
2874
 
        else
2875
 
        {
2876
 
            for (mod = 0; mod < 8; mod++)
2877
 
            {
2878
 
                if (modifiers & (1 << mod))
2879
 
                {
2880
 
                    for (k = mod * modHandler->modMap ()->max_keypermod;
2881
 
                         k < (mod + 1) * modHandler->modMap ()->max_keypermod;
2882
 
                         k++)
2883
 
                    {
2884
 
                        if (modHandler->modMap ()->modifiermap[k])
2885
 
                        {
2886
 
                            grabUngrabOneKey ((modifiers & ~(1 << mod)) |
2887
 
                                              ignore,
2888
 
                                              modHandler->modMap ()->modifiermap[k],
2889
 
                                              grab);
2890
 
                        }
2891
 
                    }
2892
 
                }
2893
 
            }
2894
 
        }
2895
 
 
2896
 
        if (CompScreen::checkForError (dpy))
2897
 
            return false;
2898
 
    }
2899
 
 
2900
 
    return true;
2901
 
}
2902
 
 
2903
 
bool
2904
 
PrivateScreen::addPassiveKeyGrab (CompAction::KeyBinding &key)
2905
 
{
2906
 
    KeyGrab                      newKeyGrab;
2907
 
    unsigned int                 mask;
2908
 
    std::list<KeyGrab>::iterator it;
2909
 
 
2910
 
    mask = modHandler->virtualToRealModMask (key.modifiers ());
2911
 
 
2912
 
    for (it = keyGrabs.begin (); it != keyGrabs.end (); it++)
2913
 
    {
2914
 
        if (key.keycode () == (*it).keycode &&
2915
 
            mask           == (*it).modifiers)
2916
 
        {
2917
 
            (*it).count++;
2918
 
            return true;
2919
 
        }
2920
 
    }
2921
 
 
2922
 
 
2923
 
 
2924
 
    if (!(mask & CompNoMask))
2925
 
    {
2926
 
        if (!grabUngrabKeys (mask, key.keycode (), true))
2927
 
            return false;
2928
 
    }
2929
 
 
2930
 
    newKeyGrab.keycode   = key.keycode ();
2931
 
    newKeyGrab.modifiers = mask;
2932
 
    newKeyGrab.count     = 1;
2933
 
 
2934
 
    keyGrabs.push_back (newKeyGrab);
2935
 
 
2936
 
    return true;
2937
 
}
2938
 
 
2939
 
void
2940
 
PrivateScreen::removePassiveKeyGrab (CompAction::KeyBinding &key)
2941
 
{
2942
 
    unsigned int                 mask;
2943
 
    std::list<KeyGrab>::iterator it;
2944
 
 
2945
 
    mask = modHandler->virtualToRealModMask (key.modifiers ());
2946
 
 
2947
 
    for (it = keyGrabs.begin (); it != keyGrabs.end (); it++)
2948
 
    {
2949
 
        if (key.keycode () == (*it).keycode &&
2950
 
            mask           == (*it).modifiers)
2951
 
        {
2952
 
            (*it).count--;
2953
 
            if ((*it).count)
2954
 
                return;
2955
 
 
2956
 
            it = keyGrabs.erase (it);
2957
 
 
2958
 
            if (!(mask & CompNoMask))
2959
 
                grabUngrabKeys (mask, key.keycode (), false);
2960
 
        }
2961
 
    }
2962
 
}
2963
 
 
2964
 
void
2965
 
PrivateScreen::updatePassiveKeyGrabs ()
2966
 
{
2967
 
    std::list<KeyGrab>::iterator it;
2968
 
 
2969
 
    XUngrabKey (dpy, AnyKey, AnyModifier, root);
2970
 
 
2971
 
    for (it = keyGrabs.begin (); it != keyGrabs.end (); it++)
2972
 
    {
2973
 
        if (!((*it).modifiers & CompNoMask))
2974
 
        {
2975
 
            grabUngrabKeys ((*it).modifiers,
2976
 
                            (*it).keycode, true);
2977
 
        }
2978
 
    }
2979
 
}
2980
 
 
2981
 
bool
2982
 
PrivateScreen::addPassiveButtonGrab (CompAction::ButtonBinding &button)
2983
 
{
2984
 
    ButtonGrab                      newButtonGrab;
2985
 
    std::list<ButtonGrab>::iterator it;
2986
 
 
2987
 
    for (it = buttonGrabs.begin (); it != buttonGrabs.end (); it++)
2988
 
    {
2989
 
        if (button.button ()    == (*it).button &&
2990
 
            button.modifiers () == (*it).modifiers)
2991
 
        {
2992
 
            (*it).count++;
2993
 
            return true;
2994
 
        }
2995
 
    }
2996
 
 
2997
 
    newButtonGrab.button    = button.button ();
2998
 
    newButtonGrab.modifiers = button.modifiers ();
2999
 
    newButtonGrab.count     = 1;
3000
 
 
3001
 
    buttonGrabs.push_back (newButtonGrab);
3002
 
 
3003
 
    foreach (CompWindow *w, screen->windows ())
3004
 
        w->priv->updatePassiveButtonGrabs ();
3005
 
 
3006
 
    return true;
3007
 
}
3008
 
 
3009
 
void
3010
 
PrivateScreen::removePassiveButtonGrab (CompAction::ButtonBinding &button)
3011
 
{
3012
 
    std::list<ButtonGrab>::iterator it;
3013
 
 
3014
 
    for (it = buttonGrabs.begin (); it != buttonGrabs.end (); it++)
3015
 
    {
3016
 
        if (button.button ()    == (*it).button &&
3017
 
            button.modifiers () == (*it).modifiers)
3018
 
        {
3019
 
            (*it).count--;
3020
 
            if ((*it).count)
3021
 
                return;
3022
 
 
3023
 
            it = buttonGrabs.erase (it);
3024
 
 
3025
 
            foreach (CompWindow *w, screen->windows ())
3026
 
                w->priv->updatePassiveButtonGrabs ();
3027
 
        }
3028
 
    }
3029
 
}
3030
 
 
3031
 
/* add actions that should be automatically added as no screens
3032
 
   existed when they were initialized. */
3033
 
void
3034
 
PrivateScreen::addScreenActions ()
3035
 
{
3036
 
    foreach (CompOption &o, mOptions)
3037
 
    {
3038
 
        if (!o.isAction ())
3039
 
            continue;
3040
 
 
3041
 
        if (o.value ().action ().state () & CompAction::StateAutoGrab)
3042
 
            screen->addAction (&o.value ().action ());
3043
 
    }
3044
 
}
3045
 
 
3046
 
bool
3047
 
CompScreen::addAction (CompAction *action)
3048
 
{
3049
 
    if (!screenInitalized || !priv->initialized)
3050
 
        return false;
3051
 
 
3052
 
    if (action->active ())
3053
 
        return false;
3054
 
 
3055
 
    if (action->type () & CompAction::BindingTypeKey)
3056
 
    {
3057
 
        if (!priv->addPassiveKeyGrab (action->key ()))
3058
 
            return false;
3059
 
    }
3060
 
 
3061
 
    if (action->type () & CompAction::BindingTypeButton)
3062
 
    {
3063
 
        if (!priv->addPassiveButtonGrab (action->button ()))
3064
 
        {
3065
 
            if (action->type () & CompAction::BindingTypeKey)
3066
 
                priv->removePassiveKeyGrab (action->key ());
3067
 
 
3068
 
            return false;
3069
 
        }
3070
 
    }
3071
 
 
3072
 
    if (action->edgeMask ())
3073
 
    {
3074
 
        int i;
3075
 
 
3076
 
        for (i = 0; i < SCREEN_EDGE_NUM; i++)
3077
 
            if (action->edgeMask () & (1 << i))
3078
 
                priv->enableEdge (i);
3079
 
    }
3080
 
 
3081
 
    action->priv->active = true;
3082
 
 
3083
 
    return true;
3084
 
}
3085
 
 
3086
 
void
3087
 
CompScreen::removeAction (CompAction *action)
3088
 
{
3089
 
    if (!priv->initialized)
3090
 
        return;
3091
 
 
3092
 
    if (!action->active ())
3093
 
        return;
3094
 
 
3095
 
    if (action->type () & CompAction::BindingTypeKey)
3096
 
        priv->removePassiveKeyGrab (action->key ());
3097
 
 
3098
 
    if (action->type () & CompAction::BindingTypeButton)
3099
 
        priv->removePassiveButtonGrab (action->button ());
3100
 
 
3101
 
    if (action->edgeMask ())
3102
 
    {
3103
 
        int i;
3104
 
 
3105
 
        for (i = 0; i < SCREEN_EDGE_NUM; i++)
3106
 
            if (action->edgeMask () & (1 << i))
3107
 
                priv->disableEdge (i);
3108
 
    }
3109
 
 
3110
 
    action->priv->active = false;
3111
 
}
3112
 
 
3113
 
CompRect
3114
 
PrivateScreen::computeWorkareaForBox (const CompRect& box)
3115
 
{
3116
 
    CompRegion region;
3117
 
    int        x1, y1, x2, y2;
3118
 
 
3119
 
    region += box;
3120
 
 
3121
 
    foreach (CompWindow *w, windows)
3122
 
    {
3123
 
        if (!w->isMapped ())
3124
 
            continue;
3125
 
 
3126
 
        if (w->struts ())
3127
 
        {
3128
 
            x1 = w->struts ()->left.x;
3129
 
            y1 = w->struts ()->left.y;
3130
 
            x2 = x1 + w->struts ()->left.width;
3131
 
            y2 = y1 + w->struts ()->left.height;
3132
 
 
3133
 
            if (y1 < box.y2 () && y2 > box.y1 ())
3134
 
                region -= CompRect (x1, box.y1 (), x2 - x1, box.height ());
3135
 
 
3136
 
            x1 = w->struts ()->right.x;
3137
 
            y1 = w->struts ()->right.y;
3138
 
            x2 = x1 + w->struts ()->right.width;
3139
 
            y2 = y1 + w->struts ()->right.height;
3140
 
 
3141
 
            if (y1 < box.y2 () && y2 > box.y1 ())
3142
 
                region -= CompRect (x1, box.y1 (), x2 - x1, box.height ());
3143
 
 
3144
 
            x1 = w->struts ()->top.x;
3145
 
            y1 = w->struts ()->top.y;
3146
 
            x2 = x1 + w->struts ()->top.width;
3147
 
            y2 = y1 + w->struts ()->top.height;
3148
 
 
3149
 
            if (x1 < box.x2 () && x2 > box.x1 ())
3150
 
                region -= CompRect (box.x1 (), y1, box.width (), y2 - y1);
3151
 
 
3152
 
            x1 = w->struts ()->bottom.x;
3153
 
            y1 = w->struts ()->bottom.y;
3154
 
            x2 = x1 + w->struts ()->bottom.width;
3155
 
            y2 = y1 + w->struts ()->bottom.height;
3156
 
 
3157
 
            if (x1 < box.x2 () && x2 > box.x1 ())
3158
 
                region -= CompRect (box.x1 (), y1, box.width (), y2 - y1);
3159
 
        }
3160
 
    }
3161
 
 
3162
 
    if (region.isEmpty ())
3163
 
    {
3164
 
        compLogMessage ("core", CompLogLevelWarn,
3165
 
                        "Empty box after applying struts, ignoring struts");
3166
 
        return box;
3167
 
    }
3168
 
 
3169
 
    return region.boundingRect ();
3170
 
}
3171
 
 
3172
 
void
3173
 
CompScreen::updateWorkarea ()
3174
 
{
3175
 
    CompRect workArea;
3176
 
    bool     workAreaChanged = false;
3177
 
 
3178
 
    for (unsigned int i = 0; i < priv->outputDevs.size (); i++)
3179
 
    {
3180
 
        CompRect oldWorkArea = priv->outputDevs[i].workArea ();
3181
 
 
3182
 
        workArea = priv->computeWorkareaForBox (priv->outputDevs[i]);
3183
 
 
3184
 
        if (workArea != oldWorkArea)
3185
 
        {
3186
 
            workAreaChanged = true;
3187
 
            priv->outputDevs[i].setWorkArea (workArea);
3188
 
        }
3189
 
    }
3190
 
 
3191
 
    workArea = priv->computeWorkareaForBox (CompRect (0, 0,
3192
 
                                                      screen->width (),
3193
 
                                                      screen->height ()));
3194
 
 
3195
 
    if (priv->workArea != workArea)
3196
 
    {
3197
 
        workAreaChanged = true;
3198
 
        priv->workArea = workArea;
3199
 
 
3200
 
        priv->setDesktopHints ();
3201
 
    }
3202
 
 
3203
 
    if (workAreaChanged)
3204
 
    {
3205
 
        /* as work area changed, update all maximized windows on this
3206
 
           screen to snap to the new work area */
3207
 
        foreach (CompWindow *w, priv->windows)
3208
 
            w->priv->updateSize ();
3209
 
    }
3210
 
}
3211
 
 
3212
 
static bool
3213
 
isClientListWindow (CompWindow *w)
3214
 
{
3215
 
    /* windows with client id less than 2 have been destroyed and only exists
3216
 
       because some plugin keeps a reference to them. they should not be in
3217
 
       client lists */
3218
 
    if (w->id () < 2)
3219
 
        return false;
3220
 
 
3221
 
    if (w->overrideRedirect ())
3222
 
        return false;
3223
 
 
3224
 
    if (!w->isViewable ())
3225
 
    {
3226
 
        if (!(w->state () & CompWindowStateHiddenMask))
3227
 
            return false;
3228
 
    }
3229
 
 
3230
 
    return true;
3231
 
}
3232
 
 
3233
 
static void
3234
 
countClientListWindow (CompWindow *w,
3235
 
                       int        *n)
3236
 
{
3237
 
    if (isClientListWindow (w))
3238
 
    {
3239
 
        *n = *n + 1;
3240
 
    }
3241
 
}
3242
 
 
3243
 
static bool
3244
 
compareMappingOrder (const CompWindow *w1,
3245
 
                     const CompWindow *w2)
3246
 
{
3247
 
    return w1->mapNum () < w2->mapNum ();
3248
 
}
3249
 
 
3250
 
void
3251
 
PrivateScreen::updateClientList ()
3252
 
{
3253
 
    bool   updateClientList = false;
3254
 
    bool   updateClientListStacking = false;
3255
 
    int    n = 0;
3256
 
 
3257
 
    screen->forEachWindow (boost::bind (countClientListWindow, _1, &n));
3258
 
 
3259
 
    if (n == 0)
3260
 
    {
3261
 
        if ((unsigned int) n != priv->clientList.size ())
3262
 
        {
3263
 
            priv->clientList.clear ();
3264
 
            priv->clientListStacking.clear ();
3265
 
            priv->clientIdList.clear ();
3266
 
            priv->clientIdListStacking.clear ();
3267
 
 
3268
 
            XChangeProperty (priv->dpy, priv->root,
3269
 
                             Atoms::clientList,
3270
 
                             XA_WINDOW, 32, PropModeReplace,
3271
 
                             (unsigned char *) &priv->grabWindow, 1);
3272
 
            XChangeProperty (priv->dpy, priv->root,
3273
 
                             Atoms::clientListStacking,
3274
 
                             XA_WINDOW, 32, PropModeReplace,
3275
 
                             (unsigned char *) &priv->grabWindow, 1);
3276
 
        }
3277
 
 
3278
 
        return;
3279
 
    }
3280
 
 
3281
 
    if ((unsigned int) n != priv->clientList.size ())
3282
 
    {
3283
 
        priv->clientIdList.resize (n);
3284
 
        priv->clientIdListStacking.resize (n);
3285
 
 
3286
 
        updateClientList = updateClientListStacking = true;
3287
 
    }
3288
 
 
3289
 
    priv->clientListStacking.clear ();
3290
 
 
3291
 
    foreach (CompWindow *w, priv->windows)
3292
 
        if (isClientListWindow (w))
3293
 
            priv->clientListStacking.push_back (w);
3294
 
 
3295
 
    /* clear clientList and copy clientListStacking into clientList */
3296
 
    priv->clientList = priv->clientListStacking;
3297
 
 
3298
 
    /* sort clientList in mapping order */
3299
 
    sort (priv->clientList.begin (), priv->clientList.end (),
3300
 
          compareMappingOrder);
3301
 
 
3302
 
    /* make sure client id lists are up-to-date */
3303
 
    for (int i = 0; i < n; i++)
3304
 
    {
3305
 
        if (!updateClientList &&
3306
 
            priv->clientIdList[i] != priv->clientList[i]->id ())
3307
 
        {
3308
 
            updateClientList = true;
3309
 
        }
3310
 
 
3311
 
        priv->clientIdList[i] = priv->clientList[i]->id ();
3312
 
    }
3313
 
    for (int i = 0; i < n; i++)
3314
 
    {
3315
 
        if (!updateClientListStacking &&
3316
 
            priv->clientIdListStacking[i] != priv->clientListStacking[i]->id ())
3317
 
        {
3318
 
            updateClientListStacking = true;
3319
 
        }
3320
 
 
3321
 
        priv->clientIdListStacking[i] = priv->clientListStacking[i]->id ();
3322
 
    }
3323
 
 
3324
 
    if (updateClientList)
3325
 
        XChangeProperty (priv->dpy, priv->root,
3326
 
                         Atoms::clientList,
3327
 
                         XA_WINDOW, 32, PropModeReplace,
3328
 
                         (unsigned char *) &priv->clientIdList.at (0), n);
3329
 
 
3330
 
    if (updateClientListStacking)
3331
 
        XChangeProperty (priv->dpy, priv->root,
3332
 
                         Atoms::clientListStacking,
3333
 
                         XA_WINDOW, 32, PropModeReplace,
3334
 
                         (unsigned char *) &priv->clientIdListStacking.at (0),
3335
 
                         n);
3336
 
}
3337
 
 
3338
 
const CompWindowVector &
3339
 
CompScreen::clientList (bool stackingOrder)
3340
 
{
3341
 
   return stackingOrder ? priv->clientListStacking : priv->clientList;
3342
 
}
3343
 
 
3344
 
void
3345
 
CompScreen::toolkitAction (Atom   toolkitAction,
3346
 
                           Time   eventTime,
3347
 
                           Window window,
3348
 
                           long   data0,
3349
 
                           long   data1,
3350
 
                           long   data2)
3351
 
{
3352
 
    XEvent ev;
3353
 
 
3354
 
    ev.type                 = ClientMessage;
3355
 
    ev.xclient.window       = window;
3356
 
    ev.xclient.message_type = Atoms::toolkitAction;
3357
 
    ev.xclient.format       = 32;
3358
 
    ev.xclient.data.l[0]    = toolkitAction;
3359
 
    ev.xclient.data.l[1]    = eventTime;
3360
 
    ev.xclient.data.l[2]    = data0;
3361
 
    ev.xclient.data.l[3]    = data1;
3362
 
    ev.xclient.data.l[4]    = data2;
3363
 
 
3364
 
    XUngrabPointer (priv->dpy, CurrentTime);
3365
 
    XUngrabKeyboard (priv->dpy, CurrentTime);
3366
 
 
3367
 
    XSendEvent (priv->dpy, priv->root, false,
3368
 
                StructureNotifyMask, &ev);
3369
 
}
3370
 
 
3371
 
void
3372
 
CompScreen::runCommand (CompString command)
3373
 
{
3374
 
    if (command.size () == 0)
3375
 
        return;
3376
 
 
3377
 
    if (fork () == 0)
3378
 
    {
3379
 
        size_t     pos;
3380
 
        CompString env (priv->displayString);
3381
 
 
3382
 
        setsid ();
3383
 
 
3384
 
        pos = env.find (':');
3385
 
        if (pos != std::string::npos)
3386
 
        {
3387
 
            if (env.find ('.', pos) != std::string::npos)
3388
 
            {
3389
 
                env.erase (env.find ('.', pos));
3390
 
            }
3391
 
            else
3392
 
            {
3393
 
                env.erase (pos);
3394
 
                env.append (":0");
3395
 
            }
3396
 
        }
3397
 
 
3398
 
        env.append (compPrintf (".%d", priv->screenNum));
3399
 
 
3400
 
        putenv (const_cast<char *> (env.c_str ()));
3401
 
 
3402
 
        exit (execl ("/bin/sh", "/bin/sh", "-c", command.c_str (), NULL));
3403
 
    }
3404
 
}
3405
 
 
3406
 
void
3407
 
CompScreen::moveViewport (int tx, int ty, bool sync)
3408
 
{
3409
 
    CompPoint pnt;
3410
 
 
3411
 
    tx = priv->vp.x () - tx;
3412
 
    tx = MOD (tx, priv->vpSize.width ());
3413
 
    tx -= priv->vp.x ();
3414
 
 
3415
 
    ty = priv->vp.y () - ty;
3416
 
    ty = MOD (ty, priv->vpSize.height ());
3417
 
    ty -= priv->vp.y ();
3418
 
 
3419
 
    if (!tx && !ty)
3420
 
        return;
3421
 
 
3422
 
    priv->vp.setX (priv->vp.x () + tx);
3423
 
    priv->vp.setY (priv->vp.y () + ty);
3424
 
 
3425
 
    tx *= -width ();
3426
 
    ty *= -height ();
3427
 
 
3428
 
    foreach (CompWindow *w, priv->windows)
3429
 
    {
3430
 
        if (w->onAllViewports ())
3431
 
            continue;
3432
 
 
3433
 
        pnt = w->getMovementForOffset (CompPoint (tx, ty));
3434
 
 
3435
 
        if (w->saveMask () & CWX)
3436
 
            w->saveWc ().x += pnt.x ();
3437
 
 
3438
 
        if (w->saveMask () & CWY)
3439
 
            w->saveWc ().y += pnt.y ();
3440
 
 
3441
 
        /* move */
3442
 
        w->move (pnt.x (), pnt.y ());
3443
 
 
3444
 
        if (sync)
3445
 
            w->syncPosition ();
3446
 
    }
3447
 
 
3448
 
    if (sync)
3449
 
    {
3450
 
        CompWindow *w;
3451
 
 
3452
 
        priv->setDesktopHints ();
3453
 
 
3454
 
        priv->setCurrentActiveWindowHistory (priv->vp.x (), priv->vp.y ());
3455
 
 
3456
 
        w = findWindow (priv->activeWindow);
3457
 
        if (w)
3458
 
        {
3459
 
            CompPoint dvp;
3460
 
 
3461
 
            dvp = w->defaultViewport ();
3462
 
 
3463
 
            /* add window to current history if it's default viewport is
3464
 
               still the current one. */
3465
 
            if (priv->vp.x () == dvp.x () && priv->vp.y () == dvp.y ())
3466
 
                priv->addToCurrentActiveWindowHistory (w->id ());
3467
 
        }
3468
 
    }
3469
 
}
3470
 
 
3471
 
CompGroup *
3472
 
PrivateScreen::addGroup (Window id)
3473
 
{
3474
 
    CompGroup *group = new CompGroup ();
3475
 
 
3476
 
    group->refCnt = 1;
3477
 
    group->id     = id;
3478
 
 
3479
 
    priv->groups.push_back (group);
3480
 
 
3481
 
    return group;
3482
 
}
3483
 
 
3484
 
void
3485
 
PrivateScreen::removeGroup (CompGroup *group)
3486
 
{
3487
 
    group->refCnt--;
3488
 
    if (group->refCnt)
3489
 
        return;
3490
 
 
3491
 
    std::list<CompGroup *>::iterator it =
3492
 
        std::find (priv->groups.begin (), priv->groups.end (), group);
3493
 
 
3494
 
    if (it != priv->groups.end ())
3495
 
    {
3496
 
        priv->groups.erase (it);
3497
 
    }
3498
 
 
3499
 
    delete group;
3500
 
}
3501
 
 
3502
 
CompGroup *
3503
 
PrivateScreen::findGroup (Window id)
3504
 
{
3505
 
    foreach (CompGroup *g, priv->groups)
3506
 
        if (g->id == id)
3507
 
            return g;
3508
 
 
3509
 
    return NULL;
3510
 
}
3511
 
 
3512
 
void
3513
 
PrivateScreen::applyStartupProperties (CompWindow *window)
3514
 
{
3515
 
    CompStartupSequence *s = NULL;
3516
 
    const char          *startupId = window->startupId ();
3517
 
 
3518
 
    if (!startupId)
3519
 
    {
3520
 
        CompWindow *leader;
3521
 
 
3522
 
        leader = screen->findWindow (window->clientLeader ());
3523
 
        if (leader)
3524
 
            startupId = leader->startupId ();
3525
 
 
3526
 
        if (!startupId)
3527
 
            return;
3528
 
    }
3529
 
 
3530
 
    foreach (CompStartupSequence *ss, priv->startupSequences)
3531
 
    {
3532
 
        const char *id;
3533
 
 
3534
 
        id = sn_startup_sequence_get_id (ss->sequence);
3535
 
        if (strcmp (id, startupId) == 0)
3536
 
        {
3537
 
            s = ss;
3538
 
            break;
3539
 
        }
3540
 
    }
3541
 
 
3542
 
    if (s)
3543
 
        window->priv->applyStartupProperties (s);
3544
 
}
3545
 
 
3546
 
void
3547
 
CompScreen::sendWindowActivationRequest (Window id)
3548
 
{
3549
 
    XEvent xev;
3550
 
 
3551
 
    xev.xclient.type    = ClientMessage;
3552
 
    xev.xclient.display = priv->dpy;
3553
 
    xev.xclient.format  = 32;
3554
 
 
3555
 
    xev.xclient.message_type = Atoms::winActive;
3556
 
    xev.xclient.window       = id;
3557
 
 
3558
 
    xev.xclient.data.l[0] = ClientTypePager;
3559
 
    xev.xclient.data.l[1] = 0;
3560
 
    xev.xclient.data.l[2] = 0;
3561
 
    xev.xclient.data.l[3] = 0;
3562
 
    xev.xclient.data.l[4] = 0;
3563
 
 
3564
 
    XSendEvent (priv->dpy, priv->root, false,
3565
 
                SubstructureRedirectMask | SubstructureNotifyMask, &xev);
3566
 
}
3567
 
 
3568
 
void
3569
 
PrivateScreen::enableEdge (int edge)
3570
 
{
3571
 
    priv->screenEdge[edge].count++;
3572
 
    if (priv->screenEdge[edge].count == 1)
3573
 
        XMapRaised (priv->dpy, priv->screenEdge[edge].id);
3574
 
}
3575
 
 
3576
 
void
3577
 
PrivateScreen::disableEdge (int edge)
3578
 
{
3579
 
    priv->screenEdge[edge].count--;
3580
 
    if (priv->screenEdge[edge].count == 0)
3581
 
        XUnmapWindow (priv->dpy, priv->screenEdge[edge].id);
3582
 
}
3583
 
 
3584
 
Window
3585
 
PrivateScreen::getTopWindow ()
3586
 
{
3587
 
    /* return first window that has not been destroyed */
3588
 
    for (CompWindowList::reverse_iterator rit = priv->windows.rbegin ();
3589
 
             rit != priv->windows.rend (); rit++)
3590
 
    {
3591
 
        if ((*rit)->id () > 1)
3592
 
            return (*rit)->id ();
3593
 
    }
3594
 
 
3595
 
    return None;
3596
 
}
3597
 
 
3598
 
int
3599
 
CompScreen::outputDeviceForPoint (const CompPoint &point)
3600
 
{
3601
 
    return outputDeviceForPoint (point.x (), point.y ());
3602
 
}
3603
 
 
3604
 
int
3605
 
CompScreen::outputDeviceForPoint (int x, int y)
3606
 
{
3607
 
    CompWindow::Geometry geom (x, y, 1, 1, 0);
3608
 
 
3609
 
    return outputDeviceForGeometry (geom);
3610
 
}
3611
 
 
3612
 
CompRect
3613
 
CompScreen::getCurrentOutputExtents ()
3614
 
{
3615
 
    return priv->outputDevs[priv->currentOutputDev];
3616
 
}
3617
 
 
3618
 
void
3619
 
PrivateScreen::setNumberOfDesktops (unsigned int nDesktop)
3620
 
{
3621
 
    if (nDesktop < 1 || nDesktop >= 0xffffffff)
3622
 
        return;
3623
 
 
3624
 
    if (nDesktop == priv->nDesktop)
3625
 
        return;
3626
 
 
3627
 
    if (priv->currentDesktop >= nDesktop)
3628
 
        priv->currentDesktop = nDesktop - 1;
3629
 
 
3630
 
    foreach (CompWindow *w, priv->windows)
3631
 
    {
3632
 
        if (w->desktop () == 0xffffffff)
3633
 
            continue;
3634
 
 
3635
 
        if (w->desktop () >= nDesktop)
3636
 
            w->setDesktop (nDesktop - 1);
3637
 
    }
3638
 
 
3639
 
    priv->nDesktop = nDesktop;
3640
 
 
3641
 
    priv->setDesktopHints ();
3642
 
}
3643
 
 
3644
 
void
3645
 
PrivateScreen::setCurrentDesktop (unsigned int desktop)
3646
 
{
3647
 
    unsigned long data;
3648
 
 
3649
 
    if (desktop >= priv->nDesktop)
3650
 
        return;
3651
 
 
3652
 
    if (desktop == priv->currentDesktop)
3653
 
        return;
3654
 
 
3655
 
    priv->currentDesktop = desktop;
3656
 
 
3657
 
    foreach (CompWindow *w, priv->windows)
3658
 
    {
3659
 
        if (w->desktop () == 0xffffffff)
3660
 
            continue;
3661
 
 
3662
 
        if (w->desktop () == desktop)
3663
 
            w->priv->show ();
3664
 
        else
3665
 
            w->priv->hide ();
3666
 
    }
3667
 
 
3668
 
    data = desktop;
3669
 
 
3670
 
    XChangeProperty (priv->dpy, priv->root, Atoms::currentDesktop,
3671
 
                     XA_CARDINAL, 32, PropModeReplace,
3672
 
                     (unsigned char *) &data, 1);
3673
 
}
3674
 
 
3675
 
const CompRect&
3676
 
CompScreen::getWorkareaForOutput (unsigned int outputNum) const
3677
 
{
3678
 
    return priv->outputDevs[outputNum].workArea ();
3679
 
}
3680
 
 
3681
 
void
3682
 
CompScreen::outputChangeNotify ()
3683
 
    WRAPABLE_HND_FUNC (16, outputChangeNotify)
3684
 
 
3685
 
 
3686
 
 
3687
 
/* Returns default viewport for some window geometry. If the window spans
3688
 
   more than one viewport the most appropriate viewport is returned. How the
3689
 
   most appropriate viewport is computed can be made optional if necessary. It
3690
 
   is currently computed as the viewport where the center of the window is
3691
 
   located. */
3692
 
void
3693
 
CompScreen::viewportForGeometry (const CompWindow::Geometry& gm,
3694
 
                                 CompPoint&                  viewport)
3695
 
{
3696
 
    CompRect rect (gm);
3697
 
    int      offset;
3698
 
 
3699
 
    rect.setWidth  (rect.width () + (gm.border () * 2));
3700
 
    rect.setHeight (rect.height () + (gm.border () * 2));
3701
 
 
3702
 
    offset = rect.centerX () < 0 ? -1 : 0;
3703
 
    viewport.setX (priv->vp.x () + ((rect.centerX () / width ()) + offset) %
3704
 
                   priv->vpSize.width ());
3705
 
 
3706
 
    offset = rect.centerY () < 0 ? -1 : 0;
3707
 
    viewport.setY (priv->vp.y () + ((rect.centerY () / height ()) + offset ) %
3708
 
                   priv->vpSize.height ());
3709
 
}
3710
 
 
3711
 
int
3712
 
CompScreen::outputDeviceForGeometry (const CompWindow::Geometry& gm)
3713
 
{
3714
 
    int          overlapAreas[priv->outputDevs.size ()];
3715
 
    int          highest, seen, highestScore;
3716
 
    int          x, y, strategy;
3717
 
    unsigned int i;
3718
 
    CompRect     geomRect;
3719
 
 
3720
 
    if (priv->outputDevs.size () == 1)
3721
 
        return 0;
3722
 
 
3723
 
    strategy = priv->optionGetOverlappingOutputs ();
3724
 
 
3725
 
    if (strategy == CoreOptions::OverlappingOutputsSmartMode)
3726
 
    {
3727
 
        int centerX, centerY;
3728
 
 
3729
 
        /* for smart mode, calculate the overlap of the whole rectangle
3730
 
           with the output device rectangle */
3731
 
        geomRect.setWidth (gm.width () + 2 * gm.border ());
3732
 
        geomRect.setHeight (gm.height () + 2 * gm.border ());
3733
 
 
3734
 
        x = gm.x () % width ();
3735
 
        centerX = (x + (geomRect.width () / 2));
3736
 
        if (centerX < 0)
3737
 
            x += width ();
3738
 
        else if (centerX > width ())
3739
 
            x -= width ();
3740
 
        geomRect.setX (x);
3741
 
 
3742
 
        y = gm.y () % height ();
3743
 
        centerY = (y + (geomRect.height () / 2));
3744
 
        if (centerY < 0)
3745
 
            y += height ();
3746
 
        else if (centerY > height ())
3747
 
            y -= height ();
3748
 
        geomRect.setY (y);
3749
 
    }
3750
 
    else
3751
 
    {
3752
 
        /* for biggest/smallest modes, only use the window center to determine
3753
 
           the correct output device */
3754
 
        x = (gm.x () + (gm.width () / 2) + gm.border ()) % width ();
3755
 
        if (x < 0)
3756
 
            x += width ();
3757
 
        y = (gm.y () + (gm.height () / 2) + gm.border ()) % height ();
3758
 
        if (y < 0)
3759
 
            y += height ();
3760
 
 
3761
 
        geomRect.setGeometry (x, y, 1, 1);
3762
 
    }
3763
 
 
3764
 
    /* get amount of overlap on all output devices */
3765
 
    for (i = 0; i < priv->outputDevs.size (); i++)
3766
 
    {
3767
 
        CompRect overlap = priv->outputDevs[i] & geomRect;
3768
 
        overlapAreas[i] = overlap.area ();
3769
 
    }
3770
 
 
3771
 
    /* find output with largest overlap */
3772
 
    for (i = 0, highest = 0, highestScore = 0;
3773
 
         i < priv->outputDevs.size (); i++)
3774
 
    {
3775
 
        if (overlapAreas[i] > highestScore)
3776
 
        {
3777
 
            highest = i;
3778
 
            highestScore = overlapAreas[i];
3779
 
        }
3780
 
    }
3781
 
 
3782
 
    /* look if the highest score is unique */
3783
 
    for (i = 0, seen = 0; i < priv->outputDevs.size (); i++)
3784
 
        if (overlapAreas[i] == highestScore)
3785
 
            seen++;
3786
 
 
3787
 
    if (seen > 1)
3788
 
    {
3789
 
        /* it's not unique, select one output of the matching ones and use the
3790
 
           user preferred strategy for that */
3791
 
        unsigned int currentSize, bestOutputSize;
3792
 
        bool         searchLargest;
3793
 
 
3794
 
        searchLargest =
3795
 
            (strategy != CoreOptions::OverlappingOutputsPreferSmallerOutput);
3796
 
 
3797
 
        if (searchLargest)
3798
 
            bestOutputSize = 0;
3799
 
        else
3800
 
            bestOutputSize = UINT_MAX;
3801
 
 
3802
 
        for (i = 0, highest = 0; i < priv->outputDevs.size (); i++)
3803
 
            if (overlapAreas[i] == highestScore)
3804
 
            {
3805
 
                bool bestFit;
3806
 
 
3807
 
                currentSize = priv->outputDevs[i].area ();
3808
 
 
3809
 
                if (searchLargest)
3810
 
                    bestFit = (currentSize > bestOutputSize);
3811
 
                else
3812
 
                    bestFit = (currentSize < bestOutputSize);
3813
 
 
3814
 
                if (bestFit)
3815
 
                {
3816
 
                    highest = i;
3817
 
                    bestOutputSize = currentSize;
3818
 
                }
3819
 
            }
3820
 
    }
3821
 
 
3822
 
    return highest;
3823
 
}
3824
 
 
3825
 
CompIcon *
3826
 
CompScreen::defaultIcon () const
3827
 
{
3828
 
    return priv->defaultIcon;
3829
 
}
3830
 
 
3831
 
bool
3832
 
CompScreen::updateDefaultIcon ()
3833
 
{
3834
 
    CompString file = priv->optionGetDefaultIcon ();
3835
 
    void       *data;
3836
 
    CompSize   size;
3837
 
 
3838
 
    if (priv->defaultIcon)
3839
 
    {
3840
 
        delete priv->defaultIcon;
3841
 
        priv->defaultIcon = NULL;
3842
 
    }
3843
 
 
3844
 
    if (!readImageFromFile (file, size, data))
3845
 
        return false;
3846
 
 
3847
 
    priv->defaultIcon = new CompIcon (screen, size.width (), size.height ());
3848
 
 
3849
 
    memcpy (priv->defaultIcon->data (), data,
3850
 
            size.width () * size.height () * sizeof (CARD32));
3851
 
 
3852
 
    free (data);
3853
 
 
3854
 
    return true;
3855
 
}
3856
 
 
3857
 
void
3858
 
PrivateScreen::setCurrentActiveWindowHistory (int x, int y)
3859
 
{
3860
 
    int i, min = 0;
3861
 
 
3862
 
    for (i = 0; i < ACTIVE_WINDOW_HISTORY_NUM; i++)
3863
 
    {
3864
 
        if (priv->history[i].x == x && priv->history[i].y == y)
3865
 
        {
3866
 
            priv->currentHistory = i;
3867
 
            return;
3868
 
        }
3869
 
    }
3870
 
 
3871
 
    for (i = 1; i < ACTIVE_WINDOW_HISTORY_NUM; i++)
3872
 
        if (priv->history[i].activeNum < priv->history[min].activeNum)
3873
 
            min = i;
3874
 
 
3875
 
    priv->currentHistory = min;
3876
 
 
3877
 
    priv->history[min].activeNum = priv->activeNum;
3878
 
    priv->history[min].x         = x;
3879
 
    priv->history[min].y         = y;
3880
 
 
3881
 
    memset (priv->history[min].id, 0, sizeof (priv->history[min].id));
3882
 
}
3883
 
 
3884
 
void
3885
 
PrivateScreen::addToCurrentActiveWindowHistory (Window id)
3886
 
{
3887
 
    CompActiveWindowHistory *history = &priv->history[priv->currentHistory];
3888
 
    Window                  tmp, next = id;
3889
 
    int                     i;
3890
 
 
3891
 
    /* walk and move history */
3892
 
    for (i = 0; i < ACTIVE_WINDOW_HISTORY_SIZE; i++)
3893
 
    {
3894
 
        tmp = history->id[i];
3895
 
        history->id[i] = next;
3896
 
        next = tmp;
3897
 
 
3898
 
        /* we're done when we find an old instance or an empty slot */
3899
 
        if (tmp == id || tmp == None)
3900
 
            break;
3901
 
    }
3902
 
 
3903
 
    history->activeNum = priv->activeNum;
3904
 
}
3905
 
 
3906
 
void
3907
 
ScreenInterface::enterShowDesktopMode ()
3908
 
    WRAPABLE_DEF (enterShowDesktopMode)
3909
 
 
3910
 
void
3911
 
ScreenInterface::leaveShowDesktopMode (CompWindow *window)
3912
 
    WRAPABLE_DEF (leaveShowDesktopMode, window)
3913
 
 
3914
 
void
3915
 
ScreenInterface::outputChangeNotify ()
3916
 
    WRAPABLE_DEF (outputChangeNotify)
3917
 
 
3918
 
void
3919
 
ScreenInterface::addSupportedAtoms (std::vector<Atom>& atoms)
3920
 
    WRAPABLE_DEF (addSupportedAtoms, atoms)
3921
 
 
3922
 
 
3923
 
Window
3924
 
CompScreen::root ()
3925
 
{
3926
 
    return priv->root;
3927
 
}
3928
 
 
3929
 
int
3930
 
CompScreen::xkbEvent ()
3931
 
{
3932
 
    return priv->xkbEvent;
3933
 
}
3934
 
 
3935
 
void
3936
 
CompScreen::warpPointer (int dx,
3937
 
                         int dy)
3938
 
{
3939
 
    XEvent      event;
3940
 
 
3941
 
    pointerX += dx;
3942
 
    pointerY += dy;
3943
 
 
3944
 
    if (pointerX >= width ())
3945
 
        pointerX = width () - 1;
3946
 
    else if (pointerX < 0)
3947
 
        pointerX = 0;
3948
 
 
3949
 
    if (pointerY >= height ())
3950
 
        pointerY = height () - 1;
3951
 
    else if (pointerY < 0)
3952
 
        pointerY = 0;
3953
 
 
3954
 
    XWarpPointer (priv->dpy,
3955
 
                  None, priv->root,
3956
 
                  0, 0, 0, 0,
3957
 
                  pointerX, pointerY);
3958
 
 
3959
 
    XSync (priv->dpy, false);
3960
 
 
3961
 
    while (XCheckMaskEvent (priv->dpy,
3962
 
                            LeaveWindowMask |
3963
 
                            EnterWindowMask |
3964
 
                            PointerMotionMask,
3965
 
                            &event));
3966
 
 
3967
 
    if (!inHandleEvent)
3968
 
    {
3969
 
        lastPointerX = pointerX;
3970
 
        lastPointerY = pointerY;
3971
 
    }
3972
 
}
3973
 
 
3974
 
CompWindowList &
3975
 
CompScreen::windows ()
3976
 
{
3977
 
    return priv->windows;
3978
 
}
3979
 
 
3980
 
Time
3981
 
CompScreen::getCurrentTime ()
3982
 
{
3983
 
    XEvent event;
3984
 
 
3985
 
    XChangeProperty (priv->dpy, priv->grabWindow,
3986
 
                     XA_PRIMARY, XA_STRING, 8,
3987
 
                     PropModeAppend, NULL, 0);
3988
 
    XWindowEvent (priv->dpy, priv->grabWindow,
3989
 
                  PropertyChangeMask,
3990
 
                  &event);
3991
 
 
3992
 
    return event.xproperty.time;
3993
 
}
3994
 
 
3995
 
Window
3996
 
CompScreen::selectionWindow ()
3997
 
{
3998
 
    return priv->wmSnSelectionWindow;
3999
 
}
4000
 
 
4001
 
int
4002
 
CompScreen::screenNum ()
4003
 
{
4004
 
    return priv->screenNum;
4005
 
}
4006
 
 
4007
 
CompPoint
4008
 
CompScreen::vp ()
4009
 
{
4010
 
    return priv->vp;
4011
 
}
4012
 
 
4013
 
CompSize
4014
 
CompScreen::vpSize ()
4015
 
{
4016
 
    return priv->vpSize;
4017
 
}
4018
 
 
4019
 
int
4020
 
CompScreen::desktopWindowCount ()
4021
 
{
4022
 
    return priv->desktopWindowCount;
4023
 
}
4024
 
 
4025
 
unsigned int
4026
 
CompScreen::activeNum () const
4027
 
{
4028
 
    return priv->activeNum;
4029
 
}
4030
 
 
4031
 
CompOutput::vector &
4032
 
CompScreen::outputDevs ()
4033
 
{
4034
 
    return priv->outputDevs;
4035
 
}
4036
 
 
4037
 
CompOutput &
4038
 
CompScreen::currentOutputDev () const
4039
 
{
4040
 
    return priv->outputDevs [priv->currentOutputDev];
4041
 
}
4042
 
 
4043
 
const CompRect &
4044
 
CompScreen::workArea () const
4045
 
{
4046
 
    return priv->workArea;
4047
 
}
4048
 
 
4049
 
unsigned int
4050
 
CompScreen::currentDesktop ()
4051
 
{
4052
 
    return priv->currentDesktop;
4053
 
}
4054
 
 
4055
 
unsigned int
4056
 
CompScreen::nDesktop ()
4057
 
{
4058
 
    return priv->nDesktop;
4059
 
}
4060
 
 
4061
 
CompActiveWindowHistory *
4062
 
CompScreen::currentHistory ()
4063
 
{
4064
 
    return &priv->history[priv->currentHistory];
4065
 
}
4066
 
 
4067
 
bool
4068
 
CompScreen::shouldSerializePlugins ()
4069
 
{
4070
 
    return priv->optionGetDoSerialize ();
4071
 
}
4072
 
 
4073
 
void
4074
 
PrivateScreen::removeDestroyed ()
4075
 
{
4076
 
    while (pendingDestroys)
4077
 
    {
4078
 
        foreach (CompWindow *w, windows)
4079
 
        {
4080
 
            if (w->destroyed ())
4081
 
            {
4082
 
                delete w;
4083
 
                break;
4084
 
            }
4085
 
        }
4086
 
 
4087
 
        pendingDestroys--;
4088
 
    }
4089
 
}
4090
 
 
4091
 
const CompRegion &
4092
 
CompScreen::region () const
4093
 
{
4094
 
    return priv->region;
4095
 
}
4096
 
 
4097
 
bool
4098
 
CompScreen::hasOverlappingOutputs ()
4099
 
{
4100
 
    return priv->hasOverlappingOutputs;
4101
 
}
4102
 
 
4103
 
CompOutput &
4104
 
CompScreen::fullscreenOutput ()
4105
 
{
4106
 
    return priv->fullscreenOutput;
4107
 
}
4108
 
 
4109
 
 
4110
 
XWindowAttributes
4111
 
CompScreen::attrib ()
4112
 
{
4113
 
    return priv->attrib;
4114
 
}
4115
 
 
4116
 
std::vector<XineramaScreenInfo> &
4117
 
CompScreen::screenInfo ()
4118
 
{
4119
 
    return priv->screenInfo;
4120
 
}
4121
 
 
4122
 
bool
4123
 
PrivateScreen::createFailed ()
4124
 
{
4125
 
    return !screenInitalized;
4126
 
}
4127
 
 
4128
 
CompScreen::CompScreen ():
4129
 
    PluginClassStorage (screenPluginClassIndices),
4130
 
    priv (NULL)
4131
 
{
4132
 
    CompPrivate p;
4133
 
    CompOption::Value::Vector vList;
4134
 
    CompPlugin  *corePlugin;
4135
 
 
4136
 
    priv = new PrivateScreen (this);
4137
 
    assert (priv);
4138
 
 
4139
 
    screenInitalized = true;
4140
 
 
4141
 
    corePlugin = CompPlugin::load ("core");
4142
 
    if (!corePlugin)
4143
 
    {
4144
 
        compLogMessage ("core", CompLogLevelFatal,
4145
 
                        "Couldn't load core plugin");
4146
 
        screenInitalized = false;
4147
 
    }
4148
 
 
4149
 
    if (!CompPlugin::push (corePlugin))
4150
 
    {
4151
 
        compLogMessage ("core", CompLogLevelFatal,
4152
 
                        "Couldn't activate core plugin");
4153
 
        screenInitalized = false;
4154
 
    }
4155
 
 
4156
 
    p.uval = CORE_ABIVERSION;
4157
 
    storeValue ("core_ABI", p);
4158
 
 
4159
 
    vList.push_back ("core");
4160
 
 
4161
 
    priv->plugin.set (CompOption::TypeString, vList);
4162
 
}
4163
 
 
4164
 
bool
4165
 
CompScreen::init (const char *name)
4166
 
{
4167
 
    Window               focus;
4168
 
    int                  revertTo, i;
4169
 
    int                  xkbOpcode;
4170
 
    Display              *dpy;
4171
 
    Window               root;
4172
 
    Window               newWmSnOwner = None;
4173
 
    Atom                 wmSnAtom = 0;
4174
 
    Time                 wmSnTimestamp = 0;
4175
 
    XEvent               event;
4176
 
    XSetWindowAttributes attr;
4177
 
    Window               currentWmSnOwner;
4178
 
    char                 buf[128];
4179
 
    static char          data = 0;
4180
 
    XColor               black;
4181
 
    Pixmap               bitmap;
4182
 
    XVisualInfo          templ;
4183
 
    XVisualInfo          *visinfo;
4184
 
    Window               rootReturn, parentReturn;
4185
 
    Window               *children;
4186
 
    unsigned int         nchildren;
4187
 
    int                  nvisinfo;
4188
 
    XSetWindowAttributes attrib;
4189
 
 
4190
 
    dpy = priv->dpy = XOpenDisplay (name);
4191
 
    if (!priv->dpy)
4192
 
    {
4193
 
        compLogMessage ("core", CompLogLevelFatal,
4194
 
                        "Couldn't open display %s", XDisplayName (name));
4195
 
        return false;
4196
 
    }
4197
 
 
4198
 
//    priv->connection = XGetXCBConnection (priv->dpy);
4199
 
 
4200
 
    snprintf (priv->displayString, 255, "DISPLAY=%s",
4201
 
              DisplayString (dpy));
4202
 
 
4203
 
#ifdef DEBUG
4204
 
    XSynchronize (priv->dpy, true);
4205
 
#endif
4206
 
 
4207
 
    Atoms::init (priv->dpy);
4208
 
 
4209
 
    XSetErrorHandler (errorHandler);
4210
 
 
4211
 
    priv->snDisplay = sn_display_new (dpy, NULL, NULL);
4212
 
    if (!priv->snDisplay)
4213
 
        return true;
4214
 
 
4215
 
    priv->lastPing = 1;
4216
 
 
4217
 
    if (!XSyncQueryExtension (dpy, &priv->syncEvent, &priv->syncError))
4218
 
    {
4219
 
        compLogMessage ("core", CompLogLevelFatal,
4220
 
                        "No sync extension");
4221
 
        return false;
4222
 
    }
4223
 
 
4224
 
    priv->randrExtension = XRRQueryExtension (dpy, &priv->randrEvent,
4225
 
                                              &priv->randrError);
4226
 
 
4227
 
    priv->shapeExtension = XShapeQueryExtension (dpy, &priv->shapeEvent,
4228
 
                                                 &priv->shapeError);
4229
 
 
4230
 
    priv->xkbExtension = XkbQueryExtension (dpy, &xkbOpcode,
4231
 
                                            &priv->xkbEvent, &priv->xkbError,
4232
 
                                            NULL, NULL);
4233
 
    if (priv->xkbExtension)
4234
 
    {
4235
 
        XkbSelectEvents (dpy, XkbUseCoreKbd,
4236
 
                         XkbBellNotifyMask | XkbStateNotifyMask,
4237
 
                         XkbAllEventsMask);
4238
 
    }
4239
 
    else
4240
 
    {
4241
 
        compLogMessage ("core", CompLogLevelFatal,
4242
 
                        "No XKB extension");
4243
 
 
4244
 
        priv->xkbEvent = priv->xkbError = -1;
4245
 
    }
4246
 
 
4247
 
    priv->xineramaExtension = XineramaQueryExtension (dpy,
4248
 
                                                      &priv->xineramaEvent,
4249
 
                                                      &priv->xineramaError);
4250
 
 
4251
 
    priv->updateScreenInfo ();
4252
 
 
4253
 
    priv->escapeKeyCode = XKeysymToKeycode (dpy, XStringToKeysym ("Escape"));
4254
 
    priv->returnKeyCode = XKeysymToKeycode (dpy, XStringToKeysym ("Return"));
4255
 
 
4256
 
    sprintf (buf, "WM_S%d", DefaultScreen (dpy));
4257
 
    wmSnAtom = XInternAtom (dpy, buf, 0);
4258
 
 
4259
 
    currentWmSnOwner = XGetSelectionOwner (dpy, wmSnAtom);
4260
 
 
4261
 
    if (currentWmSnOwner != None)
4262
 
    {
4263
 
        if (!replaceCurrentWm)
4264
 
        {
4265
 
            compLogMessage ("core", CompLogLevelError,
4266
 
                            "Screen %d on display \"%s\" already "
4267
 
                            "has a window manager; try using the "
4268
 
                            "--replace option to replace the current "
4269
 
                            "window manager.",
4270
 
                            DefaultScreen (dpy), DisplayString (dpy));
4271
 
 
4272
 
            return false;
4273
 
        }
4274
 
 
4275
 
        XSelectInput (dpy, currentWmSnOwner, StructureNotifyMask);
4276
 
    }
4277
 
 
4278
 
    root = XRootWindow (dpy, DefaultScreen (dpy));
4279
 
 
4280
 
    attr.override_redirect = true;
4281
 
    attr.event_mask        = PropertyChangeMask;
4282
 
 
4283
 
    newWmSnOwner =
4284
 
        XCreateWindow (dpy, root, -100, -100, 1, 1, 0,
4285
 
                       CopyFromParent, CopyFromParent,
4286
 
                       CopyFromParent,
4287
 
                       CWOverrideRedirect | CWEventMask,
4288
 
                       &attr);
4289
 
 
4290
 
    XChangeProperty (dpy, newWmSnOwner, Atoms::wmName, Atoms::utf8String, 8,
4291
 
                     PropModeReplace, (unsigned char *) PACKAGE,
4292
 
                     strlen (PACKAGE));
4293
 
 
4294
 
    XWindowEvent (dpy, newWmSnOwner, PropertyChangeMask, &event);
4295
 
 
4296
 
    wmSnTimestamp = event.xproperty.time;
4297
 
 
4298
 
    XSetSelectionOwner (dpy, wmSnAtom, newWmSnOwner, wmSnTimestamp);
4299
 
 
4300
 
    if (XGetSelectionOwner (dpy, wmSnAtom) != newWmSnOwner)
4301
 
    {
4302
 
        compLogMessage ("core", CompLogLevelError,
4303
 
                        "Could not acquire window manager "
4304
 
                        "selection on screen %d display \"%s\"",
4305
 
                        DefaultScreen (dpy), DisplayString (dpy));
4306
 
 
4307
 
        XDestroyWindow (dpy, newWmSnOwner);
4308
 
 
4309
 
        return false;
4310
 
    }
4311
 
 
4312
 
    /* Send client message indicating that we are now the window manager */
4313
 
    event.xclient.type         = ClientMessage;
4314
 
    event.xclient.window       = root;
4315
 
    event.xclient.message_type = Atoms::manager;
4316
 
    event.xclient.format       = 32;
4317
 
    event.xclient.data.l[0]    = wmSnTimestamp;
4318
 
    event.xclient.data.l[1]    = wmSnAtom;
4319
 
    event.xclient.data.l[2]    = 0;
4320
 
    event.xclient.data.l[3]    = 0;
4321
 
    event.xclient.data.l[4]    = 0;
4322
 
 
4323
 
    XSendEvent (dpy, root, FALSE, StructureNotifyMask, &event);
4324
 
 
4325
 
    /* Wait for old window manager to go away */
4326
 
    if (currentWmSnOwner != None)
4327
 
    {
4328
 
        do {
4329
 
            XWindowEvent (dpy, currentWmSnOwner, StructureNotifyMask, &event);
4330
 
        } while (event.type != DestroyNotify);
4331
 
    }
4332
 
 
4333
 
    modHandler->updateModifierMappings ();
4334
 
 
4335
 
    CompScreen::checkForError (dpy);
4336
 
 
4337
 
    XGrabServer (dpy);
4338
 
 
4339
 
    XSelectInput (dpy, root,
4340
 
                  SubstructureRedirectMask |
4341
 
                  SubstructureNotifyMask   |
4342
 
                  StructureNotifyMask      |
4343
 
                  PropertyChangeMask       |
4344
 
                  LeaveWindowMask          |
4345
 
                  EnterWindowMask          |
4346
 
                  KeyPressMask             |
4347
 
                  KeyReleaseMask           |
4348
 
                  ButtonPressMask          |
4349
 
                  ButtonReleaseMask        |
4350
 
                  FocusChangeMask          |
4351
 
                  ExposureMask);
4352
 
 
4353
 
    /* We need to register for EnterWindowMask |
4354
 
     * ButtonPressMask | FocusChangeMask on other
4355
 
     * root windows as well because focus happens
4356
 
     * on a display level and we need to check
4357
 
     * if the screen we are running on lost focus */
4358
 
 
4359
 
    for (unsigned int i = 0; i <= ScreenCount (dpy) - 1; i++)
4360
 
    {
4361
 
        Window rt = XRootWindow (dpy, i);
4362
 
 
4363
 
        if (rt == root)
4364
 
            continue;
4365
 
 
4366
 
        XSelectInput (dpy, rt,
4367
 
                      FocusChangeMask |
4368
 
                      SubstructureNotifyMask);
4369
 
    }
4370
 
 
4371
 
    if (CompScreen::checkForError (dpy))
4372
 
    {
4373
 
        compLogMessage ("core", CompLogLevelError,
4374
 
                        "Another window manager is "
4375
 
                        "already running on screen: %d", DefaultScreen (dpy));
4376
 
 
4377
 
        XUngrabServer (dpy);
4378
 
        return false;
4379
 
    }
4380
 
 
4381
 
    /* We only care about windows we're not going to
4382
 
     * get a CreateNotify for later, so query the tree
4383
 
     * here, init plugin screens, and then init windows */
4384
 
 
4385
 
    XQueryTree (dpy, root,
4386
 
                &rootReturn, &parentReturn,
4387
 
                &children, &nchildren);
4388
 
 
4389
 
    for (i = 0; i < SCREEN_EDGE_NUM; i++)
4390
 
    {
4391
 
        priv->screenEdge[i].id    = None;
4392
 
        priv->screenEdge[i].count = 0;
4393
 
    }
4394
 
 
4395
 
    priv->screenNum = DefaultScreen (dpy);
4396
 
    priv->colormap  = DefaultColormap (dpy, priv->screenNum);
4397
 
    priv->root      = root;
4398
 
 
4399
 
    priv->snContext = sn_monitor_context_new (priv->snDisplay, priv->screenNum,
4400
 
                                              compScreenSnEvent, this, NULL);
4401
 
 
4402
 
    priv->wmSnSelectionWindow = newWmSnOwner;
4403
 
    priv->wmSnAtom            = wmSnAtom;
4404
 
    priv->wmSnTimestamp       = wmSnTimestamp;
4405
 
 
4406
 
    if (!XGetWindowAttributes (dpy, priv->root, &priv->attrib))
4407
 
        return false;
4408
 
 
4409
 
    priv->workArea.setWidth (priv->attrib.width);
4410
 
    priv->workArea.setHeight (priv->attrib.height);
4411
 
 
4412
 
    priv->grabWindow = None;
4413
 
 
4414
 
    templ.visualid = XVisualIDFromVisual (priv->attrib.visual);
4415
 
 
4416
 
    visinfo = XGetVisualInfo (dpy, VisualIDMask, &templ, &nvisinfo);
4417
 
    if (!nvisinfo)
4418
 
    {
4419
 
        compLogMessage ("core", CompLogLevelFatal,
4420
 
                        "Couldn't get visual info for default visual");
4421
 
        return false;
4422
 
    }
4423
 
 
4424
 
    black.red = black.green = black.blue = 0;
4425
 
 
4426
 
    if (!XAllocColor (dpy, priv->colormap, &black))
4427
 
    {
4428
 
        compLogMessage ("core", CompLogLevelFatal,
4429
 
                        "Couldn't allocate color");
4430
 
        XFree (visinfo);
4431
 
        return false;
4432
 
    }
4433
 
 
4434
 
    bitmap = XCreateBitmapFromData (dpy, priv->root, &data, 1, 1);
4435
 
    if (!bitmap)
4436
 
    {
4437
 
        compLogMessage ("core", CompLogLevelFatal,
4438
 
                        "Couldn't create bitmap");
4439
 
        XFree (visinfo);
4440
 
        return false;
4441
 
    }
4442
 
 
4443
 
    priv->invisibleCursor = XCreatePixmapCursor (dpy, bitmap, bitmap,
4444
 
                                                 &black, &black, 0, 0);
4445
 
    if (!priv->invisibleCursor)
4446
 
    {
4447
 
        compLogMessage ("core", CompLogLevelFatal,
4448
 
                        "Couldn't create invisible cursor");
4449
 
        XFree (visinfo);
4450
 
        return false;
4451
 
    }
4452
 
 
4453
 
    XFreePixmap (dpy, bitmap);
4454
 
    XFreeColors (dpy, priv->colormap, &black.pixel, 1, 0);
4455
 
 
4456
 
    XFree (visinfo);
4457
 
 
4458
 
    priv->reshape (priv->attrib.width, priv->attrib.height);
4459
 
 
4460
 
    priv->detectOutputDevices ();
4461
 
    priv->updateOutputDevices ();
4462
 
 
4463
 
    priv->getDesktopHints ();
4464
 
 
4465
 
    attrib.override_redirect = 1;
4466
 
    attrib.event_mask        = PropertyChangeMask;
4467
 
 
4468
 
    priv->grabWindow = XCreateWindow (dpy, priv->root, -100, -100, 1, 1, 0,
4469
 
                                      CopyFromParent, InputOnly, CopyFromParent,
4470
 
                                      CWOverrideRedirect | CWEventMask,
4471
 
                                      &attrib);
4472
 
    XMapWindow (dpy, priv->grabWindow);
4473
 
 
4474
 
    for (i = 0; i < SCREEN_EDGE_NUM; i++)
4475
 
    {
4476
 
        long xdndVersion = 3;
4477
 
 
4478
 
        priv->screenEdge[i].id = XCreateWindow (dpy, priv->root,
4479
 
                                                -100, -100, 1, 1, 0,
4480
 
                                                CopyFromParent, InputOnly,
4481
 
                                                CopyFromParent,
4482
 
                                                CWOverrideRedirect,
4483
 
                                                &attrib);
4484
 
 
4485
 
        XChangeProperty (dpy, priv->screenEdge[i].id, Atoms::xdndAware,
4486
 
                         XA_ATOM, 32, PropModeReplace,
4487
 
                         (unsigned char *) &xdndVersion, 1);
4488
 
 
4489
 
        XSelectInput (dpy, priv->screenEdge[i].id,
4490
 
                      EnterWindowMask   |
4491
 
                      LeaveWindowMask   |
4492
 
                      ButtonPressMask   |
4493
 
                      ButtonReleaseMask |
4494
 
                      PointerMotionMask);
4495
 
    }
4496
 
 
4497
 
    priv->updateScreenEdges ();
4498
 
 
4499
 
    priv->setDesktopHints ();
4500
 
    priv->setSupportingWmCheck ();
4501
 
    updateSupportedWmHints ();
4502
 
 
4503
 
    priv->normalCursor = XCreateFontCursor (dpy, XC_left_ptr);
4504
 
    priv->busyCursor   = XCreateFontCursor (dpy, XC_watch);
4505
 
 
4506
 
    XDefineCursor (dpy, priv->root, priv->normalCursor);
4507
 
 
4508
 
    XUngrabServer (dpy);
4509
 
 
4510
 
    priv->setAudibleBell (priv->optionGetAudibleBell ());
4511
 
 
4512
 
    priv->pingTimer.setTimes (priv->optionGetPingDelay (),
4513
 
                              priv->optionGetPingDelay () + 500);
4514
 
 
4515
 
    priv->pingTimer.start ();
4516
 
 
4517
 
    priv->addScreenActions ();
4518
 
 
4519
 
    priv->initialized = true;
4520
 
 
4521
 
    /* TODO: Bailout properly when screenInitPlugins fails
4522
 
     * TODO: It would be nicer if this line could mean
4523
 
     * "init all the screens", but unfortunately it only inits
4524
 
     * plugins loaded on the command line screen's and then
4525
 
     * we need to call updatePlugins () to init the remaining
4526
 
     * screens from option changes */
4527
 
    assert (CompPlugin::screenInitPlugins (this));
4528
 
 
4529
 
    /* The active plugins list might have been changed - load any
4530
 
     * new plugins */
4531
 
 
4532
 
 
4533
 
    /* Start initializing windows here */
4534
 
 
4535
 
    for (unsigned int i = 0; i < nchildren; i++)
4536
 
    {
4537
 
        CoreWindow *cw = new CoreWindow (children[i]);
4538
 
 
4539
 
        if (cw)
4540
 
        {
4541
 
            cw->manage (i ? children[i - 1] : 0);
4542
 
            delete cw;
4543
 
        }
4544
 
    }
4545
 
 
4546
 
    /* enforce restack on all windows */
4547
 
    for (CompWindowList::reverse_iterator rit = priv->windows.rbegin ();
4548
 
         rit != priv->windows.rend (); rit++)
4549
 
        children[i] = (*rit)->id ();
4550
 
 
4551
 
    XRestackWindows (dpy, children, i);
4552
 
 
4553
 
    XFree (children);
4554
 
 
4555
 
    foreach (CompWindow *w, priv->windows)
4556
 
    {
4557
 
        if (w->isViewable ())
4558
 
            w->priv->activeNum = priv->activeNum++;
4559
 
    }
4560
 
 
4561
 
    priv->vpSize.setWidth (priv->optionGetHsize ());
4562
 
    priv->vpSize.setHeight (priv->optionGetVsize ());
4563
 
 
4564
 
    XGetInputFocus (dpy, &focus, &revertTo);
4565
 
 
4566
 
    /* move input focus to root window so that we get a FocusIn event when
4567
 
       moving it to the default window */
4568
 
    XSetInputFocus (dpy, priv->root, RevertToPointerRoot, CurrentTime);
4569
 
 
4570
 
    if (focus == None || focus == PointerRoot)
4571
 
    {
4572
 
        focusDefaultWindow ();
4573
 
    }
4574
 
    else
4575
 
    {
4576
 
        CompWindow *w;
4577
 
 
4578
 
        w = findWindow (focus);
4579
 
        if (w)
4580
 
            w->moveInputFocusTo ();
4581
 
        else
4582
 
            focusDefaultWindow ();
4583
 
    }
4584
 
 
4585
 
    return true;
4586
 
}
4587
 
 
4588
 
CompScreen::~CompScreen ()
4589
 
{
4590
 
    CompPlugin  *p;
4591
 
 
4592
 
    priv->removeAllSequences ();
4593
 
 
4594
 
    while (!priv->windows.empty ())
4595
 
        delete priv->windows.front ();
4596
 
 
4597
 
    while ((p = CompPlugin::pop ()))
4598
 
        CompPlugin::unload (p);
4599
 
 
4600
 
    XUngrabKey (priv->dpy, AnyKey, AnyModifier, priv->root);
4601
 
 
4602
 
    priv->initialized = false;
4603
 
 
4604
 
    for (int i = 0; i < SCREEN_EDGE_NUM; i++)
4605
 
        XDestroyWindow (priv->dpy, priv->screenEdge[i].id);
4606
 
 
4607
 
    XDestroyWindow (priv->dpy, priv->grabWindow);
4608
 
 
4609
 
    if (priv->defaultIcon)
4610
 
        delete priv->defaultIcon;
4611
 
 
4612
 
    XFreeCursor (priv->dpy, priv->invisibleCursor);
4613
 
 
4614
 
    if (priv->desktopHintData)
4615
 
        free (priv->desktopHintData);
4616
 
 
4617
 
    if (priv->snContext)
4618
 
        sn_monitor_context_unref (priv->snContext);
4619
 
 
4620
 
    if (priv->snDisplay)
4621
 
        sn_display_unref (priv->snDisplay);
4622
 
 
4623
 
    XSync (priv->dpy, False);
4624
 
    XCloseDisplay (priv->dpy);
4625
 
 
4626
 
    delete priv;
4627
 
 
4628
 
    screen = NULL;
4629
 
}
4630
 
 
4631
 
PrivateScreen::PrivateScreen (CompScreen *screen) :
4632
 
    priv (this),
4633
 
    fileWatch (0),
4634
 
    lastFileWatchHandle (1),
4635
 
    watchFds (0),
4636
 
    lastWatchFdHandle (1),
4637
 
    valueMap (),
4638
 
    screenInfo (0),
4639
 
    activeWindow (0),
4640
 
    below (None),
4641
 
    autoRaiseTimer (),
4642
 
    autoRaiseWindow (0),
4643
 
    edgeDelayTimer (),
4644
 
    plugin (),
4645
 
    dirtyPluginList (true),
4646
 
    screen (screen),
4647
 
    windows (),
4648
 
    vp (0, 0),
4649
 
    vpSize (1, 1),
4650
 
    nDesktop (1),
4651
 
    currentDesktop (0),
4652
 
    root (None),
4653
 
    grabWindow (None),
4654
 
    desktopWindowCount (0),
4655
 
    mapNum (1),
4656
 
    activeNum (1),
4657
 
    outputDevs (0),
4658
 
    currentOutputDev (0),
4659
 
    hasOverlappingOutputs (false),
4660
 
    currentHistory (0),
4661
 
    snContext (0),
4662
 
    startupSequences (0),
4663
 
    startupSequenceTimer (),
4664
 
    groups (0),
4665
 
    defaultIcon (0),
4666
 
    buttonGrabs (0),
4667
 
    keyGrabs (0),
4668
 
    grabs (0),
4669
 
    grabbed (false),
4670
 
    pendingDestroys (0),
4671
 
    showingDesktopMask (0),
4672
 
    desktopHintData (0),
4673
 
    desktopHintSize (0),
4674
 
    initialized (false)
4675
 
{
4676
 
    gettimeofday (&lastTimeout, 0);
4677
 
 
4678
 
    pingTimer.setCallback (
4679
 
        boost::bind (&PrivateScreen::handlePingTimeout, this));
4680
 
 
4681
 
    startupSequenceTimer.setCallback (
4682
 
        boost::bind (&PrivateScreen::handleStartupSequenceTimeout, this));
4683
 
    startupSequenceTimer.setTimes (1000, 1500);
4684
 
 
4685
 
    optionSetCloseWindowKeyInitiate (CompScreen::closeWin);
4686
 
    optionSetCloseWindowButtonInitiate (CompScreen::closeWin);
4687
 
    optionSetRaiseWindowKeyInitiate (CompScreen::raiseWin);
4688
 
    optionSetRaiseWindowButtonInitiate (CompScreen::raiseWin);
4689
 
    optionSetLowerWindowKeyInitiate (CompScreen::lowerWin);
4690
 
    optionSetLowerWindowButtonInitiate (CompScreen::lowerWin);
4691
 
 
4692
 
    optionSetUnmaximizeWindowKeyInitiate (CompScreen::unmaximizeWin);
4693
 
 
4694
 
    optionSetMinimizeWindowKeyInitiate (CompScreen::minimizeWin);
4695
 
    optionSetMinimizeWindowButtonInitiate (CompScreen::minimizeWin);
4696
 
    optionSetMaximizeWindowKeyInitiate (CompScreen::maximizeWin);
4697
 
    optionSetMaximizeWindowHorizontallyKeyInitiate (
4698
 
        CompScreen::maximizeWinHorizontally);
4699
 
    optionSetMaximizeWindowVerticallyKeyInitiate (
4700
 
        CompScreen::maximizeWinVertically);
4701
 
 
4702
 
    optionSetWindowMenuKeyInitiate (CompScreen::windowMenu);
4703
 
    optionSetWindowMenuButtonInitiate (CompScreen::windowMenu);
4704
 
 
4705
 
    optionSetShowDesktopKeyInitiate (CompScreen::showDesktop);
4706
 
    optionSetShowDesktopEdgeInitiate (CompScreen::showDesktop);
4707
 
 
4708
 
    optionSetToggleWindowMaximizedKeyInitiate (CompScreen::toggleWinMaximized);
4709
 
    optionSetToggleWindowMaximizedButtonInitiate (CompScreen::toggleWinMaximized);
4710
 
 
4711
 
    optionSetToggleWindowMaximizedHorizontallyKeyInitiate (
4712
 
        CompScreen::toggleWinMaximizedHorizontally);
4713
 
    optionSetToggleWindowMaximizedVerticallyKeyInitiate (
4714
 
        CompScreen::toggleWinMaximizedVertically);
4715
 
 
4716
 
    optionSetToggleWindowShadedKeyInitiate (CompScreen::shadeWin);
4717
 
}
4718
 
 
4719
 
PrivateScreen::~PrivateScreen ()
4720
 
{
4721
 
}