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

« back to all changes in this revision

Viewing changes to .pc/00_remove_printf.patch/src/screen.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Didier Roche
  • Date: 2011-04-15 17:08:40 UTC
  • mfrom: (0.168.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20110415170840-x56m5m6qs4b7n8rb
Tags: 1:0.9.4+bzr20110415-0ubuntu1
* New upstream snapshot
  - Focus problem with Thunderbird (LP: #753951)
  - Chromium fullscreen + Alt-TAB confuses the launcher (LP: #757434)
  - compiz hangs randomly several times per day (LP: #740126)
* debian/patches/00_*:
  - removed as part of upstream tarball

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