~focus-follows-mouse/ubuntu/precise/compiz/fix-883383

« back to all changes in this revision

Viewing changes to .pc/102_git_fix_load_images.patch/src/screen.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Didier Roche
  • Date: 2011-03-22 21:45:34 UTC
  • mfrom: (0.168.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20110322214534-l6i6ds54os5uoqt1
Tags: 1:0.9.4git20110322-0ubuntu1
* New upstream bug fix snapshot:
  - Application windows can sometimes fail to display and will
    mask regions of the screen (LP: #709461)
  - Compiz switcher Alt-Tab order is not predictable - should
    maintain LIFO ordering in application switcher (LP: #175874)
  - after compiz crashed, gnome-panel isn't mapped again (LP: #711378)
  - invisible windows border problem (LP: #710271)
  - Compiz thinks you are clicking in an edge window when you
    are not (LP: #734250)
  - Add test case for invisible window regressions (LP: #736876)
  - often can't alt-click-dnd to move the focussed dialog (LP: #711911)
  - When windows open for the first time they should not hide (LP: #723878)
  - Unity Grid is broken for multi-monitor setups (LP: #709221)
  - Pixmaps trashed during animations when window is unmapped (LP: #733331)
  - Windows have blank decorations when rapidly closing and
    reopening (LP: #733328)
  - Unity is not restored on unity/compiz crash: compiz doesn't register
    properly with gnome-session (LP: #716462)
* remove the patch taken from upstream
* refresh u-w-d patch with latest upstream work
* debian/compiz-core.install:
  - image move to the final destination
* debian/patches/100_bump_core.h.patch:
  - bump for ABI breakage
* debian/compiz-decorator:
  - use gtk-window-decorator and not unity-window-decorator as it's really
    crashy for now (will probably redo an upload tomorrow with a fixed
    decorator)

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