2
* Copyright © 2005 Novell, Inc.
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
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.
23
* Author: David Reveman <davidr@novell.com>
36
#include <sys/types.h>
44
#include <boost/bind.hpp>
45
#include <boost/foreach.hpp>
46
#define foreach BOOST_FOREACH
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>
55
#include <core/core.h>
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"
64
bool inHandleEvent = false;
66
bool screenInitalized = false;
68
CompScreen *targetScreen = NULL;
69
CompOutput *targetOutput;
76
#define MwmHintsFunctions (1L << 0)
77
#define MwmHintsDecorations (1L << 1)
78
#define PropMotifWmHintElements 3
82
unsigned long functions;
83
unsigned long decorations;
89
ModifierHandler *modHandler;
91
PluginClassStorage::Indices screenPluginClassIndices (0);
94
CompScreen::allocPluginClassIndex ()
96
unsigned int i = PluginClassStorage::allocatePluginClassIndex (screenPluginClassIndices);
98
if (screenPluginClassIndices.size () != screen->pluginClasses.size ())
99
screen->pluginClasses.resize (screenPluginClassIndices.size ());
105
CompScreen::freePluginClassIndex (unsigned int index)
107
PluginClassStorage::freePluginClassIndex (screenPluginClassIndices, index);
109
if (screenPluginClassIndices.size () != screen->pluginClasses.size ())
110
screen->pluginClasses.resize (screenPluginClassIndices.size ());
114
CompScreen::eventLoop ()
116
priv->ctx = Glib::MainContext::get_default ();
117
priv->mainloop = Glib::MainLoop::create (priv->ctx, false);
118
priv->source = CompEventSource::create ();
119
priv->timeout = CompTimeoutSource::create ();
121
priv->source->attach (priv->ctx);
123
/* Kick the event loop */
124
priv->ctx->iteration (false);
126
priv->mainloop->run ();
130
CompScreen::addFileWatch (const char *path,
132
FileWatchCallBack callBack)
134
CompFileWatch *fileWatch = new CompFileWatch ();
138
fileWatch->path = path;
139
fileWatch->mask = mask;
140
fileWatch->callBack = callBack;
141
fileWatch->handle = priv->lastFileWatchHandle++;
143
if (priv->lastFileWatchHandle == MAXSHORT)
144
priv->lastFileWatchHandle = 1;
146
priv->fileWatch.push_front (fileWatch);
148
fileWatchAdded (fileWatch);
150
return fileWatch->handle;
154
CompScreen::removeFileWatch (CompFileWatchHandle handle)
156
std::list<CompFileWatch *>::iterator it;
159
for (it = priv->fileWatch.begin (); it != priv->fileWatch.end (); it++)
160
if ((*it)->handle == handle)
163
if (it == priv->fileWatch.end ())
167
priv->fileWatch.erase (it);
169
fileWatchRemoved (w);
174
const CompFileWatchList &
175
CompScreen::getFileWatches () const
177
return priv->fileWatch;
181
PrivateScreen::addTimer (CompTimer *timer)
183
std::list<CompTimer *>::iterator it;
185
it = std::find (timers.begin (), timers.end (), timer);
187
if (it != timers.end ())
190
for (it = timers.begin (); it != timers.end (); it++)
192
if ((int) timer->mMinTime < (*it)->mMinLeft)
196
timer->mMinLeft = timer->mMinTime;
197
timer->mMaxLeft = timer->mMaxTime;
199
timers.insert (it, timer);
203
PrivateScreen::removeTimer (CompTimer *timer)
205
std::list<CompTimer *>::iterator it;
207
it = std::find (timers.begin (), timers.end (), timer);
209
if (it == timers.end ())
215
CompWatchFd::CompWatchFd (int fd,
216
Glib::IOCondition events,
217
FdWatchCallBack callback) :
218
Glib::IOSource (fd, events),
220
mCallBack (callback),
224
connect (sigc::mem_fun <Glib::IOCondition, bool>
225
(this, &CompWatchFd::internalCallback));
228
Glib::RefPtr <CompWatchFd>
229
CompWatchFd::create (int fd,
230
Glib::IOCondition events,
231
FdWatchCallBack callback)
233
return Glib::RefPtr <CompWatchFd> (new CompWatchFd (fd, events, callback));
237
CompScreen::addWatchFd (int fd,
239
FdWatchCallBack callBack)
241
Glib::IOCondition gEvents;
243
memset (&gEvents, 0, sizeof (Glib::IOCondition));
246
gEvents |= Glib::IO_IN;
247
if (events & POLLOUT)
248
gEvents |= Glib::IO_OUT;
249
if (events & POLLPRI)
250
gEvents |= Glib::IO_PRI;
251
if (events & POLLERR)
252
gEvents |= Glib::IO_ERR;
253
if (events & POLLHUP)
254
gEvents |= Glib::IO_HUP;
256
Glib::RefPtr <CompWatchFd> watchFd = CompWatchFd::create (fd, gEvents, callBack);
258
watchFd->attach (priv->ctx);
262
watchFd->mHandle = priv->lastWatchFdHandle++;
264
if (priv->lastWatchFdHandle == MAXSHORT)
265
priv->lastWatchFdHandle = 1;
267
priv->watchFds.push_front (watchFd);
269
return watchFd->mHandle;
273
CompScreen::removeWatchFd (CompWatchFdHandle handle)
275
std::list<Glib::RefPtr <CompWatchFd> >::iterator it;
276
Glib::RefPtr <CompWatchFd> w;
278
for (it = priv->watchFds.begin();
279
it != priv->watchFds.end (); it++)
281
if ((*it)->mHandle == handle)
285
if (it == priv->watchFds.end ())
292
w->mForceFail = true;
297
priv->watchFds.erase (it);
301
CompScreen::storeValue (CompString key, CompPrivate value)
303
std::map<CompString,CompPrivate>::iterator it;
305
it = priv->valueMap.find (key);
307
if (it != priv->valueMap.end ())
313
priv->valueMap.insert (std::pair<CompString,CompPrivate> (key, value));
318
CompScreen::hasValue (CompString key)
320
return (priv->valueMap.find (key) != priv->valueMap.end ());
324
CompScreen::getValue (CompString key)
328
std::map<CompString,CompPrivate>::iterator it;
329
it = priv->valueMap.find (key);
331
if (it != priv->valueMap.end ())
343
CompWatchFd::internalCallback (Glib::IOCondition events)
345
short int revents = 0;
347
if (events & Glib::IO_IN)
349
if (events & Glib::IO_OUT)
351
if (events & Glib::IO_PRI)
353
if (events & Glib::IO_ERR)
355
if (events & Glib::IO_HUP)
357
if (events & Glib::IO_NVAL)
366
/* FIXME: Need to find a way to properly remove the watchFd
367
* from the internal list in core */
368
//screen->priv->watchFds.remove (this);
376
CompScreen::eraseValue (CompString key)
378
std::map<CompString,CompPrivate>::iterator it;
379
it = priv->valueMap.find (key);
381
if (it != priv->valueMap.end ())
383
priv->valueMap.erase (key);
388
CompScreen::fileWatchAdded (CompFileWatch *watch)
389
WRAPABLE_HND_FUNC (0, fileWatchAdded, watch)
392
CompScreen::fileWatchRemoved (CompFileWatch *watch)
393
WRAPABLE_HND_FUNC (1, fileWatchRemoved, watch)
396
CompScreen::setOptionForPlugin (const char *plugin,
398
CompOption::Value &value)
400
WRAPABLE_HND_FUNC_RETURN (4, bool, setOptionForPlugin,
403
CompPlugin *p = CompPlugin::find (plugin);
405
return p->vTable->setOption (name, value);
411
CompScreen::sessionEvent (CompSession::Event event,
412
CompOption::Vector &arguments)
413
WRAPABLE_HND_FUNC (5, sessionEvent, event, arguments)
416
ScreenInterface::fileWatchAdded (CompFileWatch *watch)
417
WRAPABLE_DEF (fileWatchAdded, watch)
420
ScreenInterface::fileWatchRemoved (CompFileWatch *watch)
421
WRAPABLE_DEF (fileWatchRemoved, watch)
424
ScreenInterface::initPluginForScreen (CompPlugin *plugin)
425
WRAPABLE_DEF (initPluginForScreen, plugin)
428
ScreenInterface::finiPluginForScreen (CompPlugin *plugin)
429
WRAPABLE_DEF (finiPluginForScreen, plugin)
432
ScreenInterface::setOptionForPlugin (const char *plugin,
434
CompOption::Value &value)
435
WRAPABLE_DEF (setOptionForPlugin, plugin, name, value)
438
ScreenInterface::sessionEvent (CompSession::Event event,
439
CompOption::Vector &arguments)
440
WRAPABLE_DEF (sessionEvent, event, arguments)
443
static int errors = 0;
446
errorHandler (Display *dpy,
457
XGetErrorDatabaseText (dpy, "XlibMessage", "XError", "", str, 128);
458
fprintf (stderr, "%s", str);
460
XGetErrorText (dpy, e->error_code, str, 128);
461
fprintf (stderr, ": %s\n ", str);
463
XGetErrorDatabaseText (dpy, "XlibMessage", "MajorCode", "%d", str, 128);
464
fprintf (stderr, str, e->request_code);
466
sprintf (str, "%d", e->request_code);
467
XGetErrorDatabaseText (dpy, "XRequest", str, "", str, 128);
468
if (strcmp (str, ""))
469
fprintf (stderr, " (%s)", str);
470
fprintf (stderr, "\n ");
472
XGetErrorDatabaseText (dpy, "XlibMessage", "MinorCode", "%d", str, 128);
473
fprintf (stderr, str, e->minor_code);
474
fprintf (stderr, "\n ");
476
XGetErrorDatabaseText (dpy, "XlibMessage", "ResourceID", "%d", str, 128);
477
fprintf (stderr, str, e->resourceid);
478
fprintf (stderr, "\n");
487
CompScreen::checkForError (Display *dpy)
506
CompScreen::XRandr ()
508
return priv->randrExtension;
512
CompScreen::randrEvent ()
514
return priv->randrEvent;
518
CompScreen::XShape ()
520
return priv->shapeExtension;
524
CompScreen::shapeEvent ()
526
return priv->shapeEvent;
530
CompScreen::syncEvent ()
532
return priv->syncEvent;
536
CompScreen::snDisplay ()
538
return priv->snDisplay;
542
CompScreen::activeWindow ()
544
return priv->activeWindow;
548
CompScreen::autoRaiseWindow ()
550
return priv->autoRaiseWindow;
554
CompScreen::displayString ()
556
return priv->displayString;
560
PrivateScreen::updateScreenInfo ()
562
if (xineramaExtension)
565
XineramaScreenInfo *info = XineramaQueryScreens (dpy, &nInfo);
567
screenInfo = std::vector<XineramaScreenInfo> (info, info + nInfo);
575
PrivateScreen::setAudibleBell (bool audible)
578
XkbChangeEnabledControls (dpy,
581
audible ? XkbAudibleBellMask : 0);
585
PrivateScreen::handlePingTimeout ()
588
int ping = lastPing + 1;
590
ev.type = ClientMessage;
591
ev.xclient.window = 0;
592
ev.xclient.message_type = Atoms::wmProtocols;
593
ev.xclient.format = 32;
594
ev.xclient.data.l[0] = Atoms::wmPing;
595
ev.xclient.data.l[1] = ping;
596
ev.xclient.data.l[2] = 0;
597
ev.xclient.data.l[3] = 0;
598
ev.xclient.data.l[4] = 0;
600
foreach (CompWindow *w, windows)
602
if (w->priv->handlePingTimeout (lastPing))
604
ev.xclient.window = w->id ();
605
ev.xclient.data.l[2] = w->id ();
607
XSendEvent (dpy, w->id (), false, NoEventMask, &ev);
617
CompScreen::getOptions ()
619
return priv->getOptions ();
623
CompScreen::setOption (const CompString &name,
624
CompOption::Value &value)
626
return priv->setOption (name, value);
630
PrivateScreen::setOption (const CompString &name,
631
CompOption::Value &value)
635
bool rv = CoreOptions::setOption (name, value);
640
if (!CompOption::findOption (getOptions (), name, &index))
644
case CoreOptions::ActivePlugins:
645
dirtyPluginList = true;
647
case CoreOptions::PingDelay:
648
pingTimer.setTimes (optionGetPingDelay (),
649
optionGetPingDelay () + 500);
651
case CoreOptions::AudibleBell:
652
setAudibleBell (optionGetAudibleBell ());
654
case CoreOptions::DetectOutputs:
655
if (optionGetDetectOutputs ())
656
detectOutputDevices ();
658
case CoreOptions::Hsize:
659
case CoreOptions::Vsize:
661
if (optionGetHsize () * screen->width () > MAXSHORT)
663
if (optionGetVsize () * screen->height () > MAXSHORT)
666
setVirtualScreenSize (optionGetHsize (), optionGetVsize ());
668
case CoreOptions::NumberOfDesktops:
669
setNumberOfDesktops (optionGetNumberOfDesktops ());
671
case CoreOptions::DefaultIcon:
672
return screen->updateDefaultIcon ();
674
case CoreOptions::Outputs:
675
if (!noDetection && optionGetDetectOutputs ())
677
updateOutputDevices ();
687
PrivateScreen::processEvents ()
689
XEvent event, peekEvent;
691
/* remove destroyed windows */
697
while (XPending (dpy))
699
XNextEvent (dpy, &event);
701
switch (event.type) {
704
pointerX = event.xbutton.x_root;
705
pointerY = event.xbutton.y_root;
709
pointerX = event.xkey.x_root;
710
pointerY = event.xkey.y_root;
713
while (XPending (dpy))
715
XPeekEvent (dpy, &peekEvent);
717
if (peekEvent.type != MotionNotify)
720
XNextEvent (dpy, &event);
723
pointerX = event.xmotion.x_root;
724
pointerY = event.xmotion.y_root;
728
pointerX = event.xcrossing.x_root;
729
pointerY = event.xcrossing.y_root;
732
if (event.xclient.message_type == Atoms::xdndPosition)
734
pointerX = event.xclient.data.l[2] >> 16;
735
pointerY = event.xclient.data.l[2] & 0xffff;
741
sn_display_process_event (snDisplay, &event);
743
inHandleEvent = true;
744
screen->handleEvent (&event);
745
inHandleEvent = false;
747
lastPointerX = pointerX;
748
lastPointerY = pointerY;
753
PrivateScreen::updatePlugins ()
756
unsigned int nPop, i, j, pListCount = 1;
757
CompOption::Value::Vector pList;
758
CompPlugin::List pop;
762
dirtyPluginList = false;
764
CompOption::Value::Vector &list = optionGetActivePlugins ();
766
/* Determine the number of plugins, which is core +
767
* initial plugins + plugins in option list in addition
768
* to initial plugins */
769
foreach (CompString &pn, initialPlugins)
775
foreach (CompOption::Value &lp, list)
778
if (lp.s () == "core")
781
foreach (CompString &p, initialPlugins)
790
/* plugin not in initial list */
795
/* dupPluginCount is now the number of plugisn contained in both the
796
* initial and new plugins list */
797
pList.resize (pListCount);
801
screen->setOptionForPlugin ("core", "active_plugins", plugin);
805
/* Must have core as first plugin */
806
pList.at (0) = "core";
809
/* Add initial plugins */
810
foreach (CompString &p, initialPlugins)
814
pList.at (j).set (p);
818
/* Add plugins not in the initial list */
819
foreach (CompOption::Value &opt, list)
821
std::list <CompString>::iterator it = initialPlugins.begin ();
823
if (opt.s () == "core")
826
for (; it != initialPlugins.end (); it++)
828
if ((*it) == opt.s ())
836
pList.at (j++).set (opt.s ());
839
assert (j == pList.size ());
841
/* j is initialized to 1 to make sure we never pop the core plugin */
842
for (i = j = 1; j < plugin.list ().size () && i < pList.size (); i++, j++)
844
if (plugin.list ().at (j).s () != pList.at (i).s ())
848
nPop = plugin.list ().size () - j;
852
for (j = 0; j < nPop; j++)
854
pop.push_back (CompPlugin::pop ());
855
plugin.list ().pop_back ();
859
for (; i < pList.size (); i++)
863
foreach (CompPlugin *pp, pop)
865
if (pList[i]. s () == pp->vTable->name ())
867
if (CompPlugin::push (pp))
870
pop.erase (std::find (pop.begin (), pop.end (), pp));
875
pop.erase (std::find (pop.begin (), pop.end (), pp));
876
CompPlugin::unload (pp);
884
if (p == 0 && !failedPush)
886
p = CompPlugin::load (pList[i].s ().c_str ());
889
if (!CompPlugin::push (p))
891
CompPlugin::unload (p);
898
plugin.list ().push_back (p->vTable->name ());
901
foreach (CompPlugin *pp, pop)
902
CompPlugin::unload (pp);
904
if (!priv->dirtyPluginList)
905
screen->setOptionForPlugin ("core", "active_plugins", plugin);
908
/* from fvwm2, Copyright Matthias Clasen, Dominik Vogt */
910
convertProperty (Display *dpy,
919
Atom conversionTargets[N_TARGETS];
920
long icccmVersion[] = { 2, 0 };
922
conversionTargets[0] = Atoms::targets;
923
conversionTargets[1] = Atoms::multiple;
924
conversionTargets[2] = Atoms::timestamp;
925
conversionTargets[3] = Atoms::version;
927
if (target == Atoms::targets)
928
XChangeProperty (dpy, w, property,
929
XA_ATOM, 32, PropModeReplace,
930
(unsigned char *) conversionTargets, N_TARGETS);
931
else if (target == Atoms::timestamp)
932
XChangeProperty (dpy, w, property,
933
XA_INTEGER, 32, PropModeReplace,
934
(unsigned char *) &time, 1);
935
else if (target == Atoms::version)
936
XChangeProperty (dpy, w, property,
937
XA_INTEGER, 32, PropModeReplace,
938
(unsigned char *) icccmVersion, 2);
942
/* Be sure the PropertyNotify has arrived so we
943
* can send SelectionNotify
950
/* from fvwm2, Copyright Matthias Clasen, Dominik Vogt */
952
PrivateScreen::handleSelectionRequest (XEvent *event)
954
XSelectionEvent reply;
956
if (wmSnSelectionWindow != event->xselectionrequest.owner ||
957
wmSnAtom != event->xselectionrequest.selection)
960
reply.type = SelectionNotify;
962
reply.requestor = event->xselectionrequest.requestor;
963
reply.selection = event->xselectionrequest.selection;
964
reply.target = event->xselectionrequest.target;
965
reply.property = None;
966
reply.time = event->xselectionrequest.time;
968
if (event->xselectionrequest.target == Atoms::multiple)
970
if (event->xselectionrequest.property != None)
974
unsigned long num, rest;
977
if (XGetWindowProperty (dpy,
978
event->xselectionrequest.requestor,
979
event->xselectionrequest.property,
982
&type, &format, &num, &rest,
986
/* FIXME: to be 100% correct, should deal with rest > 0,
987
* but since we have 4 possible targets, we will hardly ever
988
* meet multiple requests with a length > 8
990
adata = (Atom *) data;
992
while (i < (int) num)
994
if (!convertProperty (dpy, wmSnTimestamp,
995
event->xselectionrequest.requestor,
996
adata[i], adata[i + 1]))
1002
XChangeProperty (dpy,
1003
event->xselectionrequest.requestor,
1004
event->xselectionrequest.property,
1006
32, PropModeReplace, data, num);
1014
if (event->xselectionrequest.property == None)
1015
event->xselectionrequest.property = event->xselectionrequest.target;
1017
if (convertProperty (dpy, wmSnTimestamp,
1018
event->xselectionrequest.requestor,
1019
event->xselectionrequest.target,
1020
event->xselectionrequest.property))
1021
reply.property = event->xselectionrequest.property;
1024
XSendEvent (dpy, event->xselectionrequest.requestor,
1025
false, 0L, (XEvent *) &reply);
1029
PrivateScreen::handleSelectionClear (XEvent *event)
1031
/* We need to unmanage the screen on which we lost the selection */
1032
if (wmSnSelectionWindow != event->xselectionclear.window ||
1033
wmSnAtom != event->xselectionclear.selection)
1039
#define HOME_IMAGEDIR ".compiz-1/images"
1042
CompScreen::readImageFromFile (CompString &name,
1049
status = fileToImage (name, size, stride, data);
1052
char *home = getenv ("HOME");
1058
path += HOME_IMAGEDIR;
1062
status = fileToImage (path, size, stride, data);
1071
status = fileToImage (path, size, stride, data);
1078
CompScreen::writeImageToFile (CompString &path,
1083
CompString formatString (format);
1084
return imageToFile (path, formatString, size, size.width () * 4, data);
1088
PrivateScreen::getActiveWindow (Window root)
1092
unsigned long n, left;
1093
unsigned char *data;
1096
result = XGetWindowProperty (priv->dpy, root,
1097
Atoms::winActive, 0L, 1L, false,
1098
XA_WINDOW, &actual, &format,
1101
if (result == Success && data)
1104
memcpy (&w, data, sizeof (Window));
1112
CompScreen::fileToImage (CompString &name,
1117
WRAPABLE_HND_FUNC_RETURN (8, bool, fileToImage, name, size, stride, data);
1122
CompScreen::imageToFile (CompString &path,
1128
WRAPABLE_HND_FUNC_RETURN (9, bool, imageToFile, path, format, size,
1134
logLevelToString (CompLogLevel level)
1137
case CompLogLevelFatal:
1139
case CompLogLevelError:
1141
case CompLogLevelWarn:
1143
case CompLogLevelInfo:
1145
case CompLogLevelDebug:
1155
logMessage (const char *componentName,
1157
const char *message)
1159
if (!debugOutput && level >= CompLogLevelDebug)
1162
fprintf (stderr, "%s (%s) - %s: %s\n",
1163
programName, componentName,
1164
logLevelToString (level), message);
1168
CompScreen::logMessage (const char *componentName,
1170
const char *message)
1172
WRAPABLE_HND_FUNC (13, logMessage, componentName, level, message)
1173
::logMessage (componentName, level, message);
1177
compLogMessage (const char *componentName,
1185
va_start (args, format);
1187
vsnprintf (message, 2048, format, args);
1190
screen->logMessage (componentName, level, message);
1192
logMessage (componentName, level, message);
1198
PrivateScreen::getWmState (Window id)
1202
unsigned long n, left;
1203
unsigned char *data;
1204
unsigned long state = NormalState;
1206
result = XGetWindowProperty (priv->dpy, id,
1207
Atoms::wmState, 0L, 2L, false,
1208
Atoms::wmState, &actual, &format,
1211
if (result == Success && data)
1214
memcpy (&state, data, sizeof (unsigned long));
1215
XFree ((void *) data);
1222
PrivateScreen::setWmState (int state, Window id)
1224
unsigned long data[2];
1229
XChangeProperty (priv->dpy, id,
1230
Atoms::wmState, Atoms::wmState,
1231
32, PropModeReplace, (unsigned char *) data, 2);
1235
PrivateScreen::windowStateMask (Atom state)
1237
if (state == Atoms::winStateModal)
1238
return CompWindowStateModalMask;
1239
else if (state == Atoms::winStateSticky)
1240
return CompWindowStateStickyMask;
1241
else if (state == Atoms::winStateMaximizedVert)
1242
return CompWindowStateMaximizedVertMask;
1243
else if (state == Atoms::winStateMaximizedHorz)
1244
return CompWindowStateMaximizedHorzMask;
1245
else if (state == Atoms::winStateShaded)
1246
return CompWindowStateShadedMask;
1247
else if (state == Atoms::winStateSkipTaskbar)
1248
return CompWindowStateSkipTaskbarMask;
1249
else if (state == Atoms::winStateSkipPager)
1250
return CompWindowStateSkipPagerMask;
1251
else if (state == Atoms::winStateHidden)
1252
return CompWindowStateHiddenMask;
1253
else if (state == Atoms::winStateFullscreen)
1254
return CompWindowStateFullscreenMask;
1255
else if (state == Atoms::winStateAbove)
1256
return CompWindowStateAboveMask;
1257
else if (state == Atoms::winStateBelow)
1258
return CompWindowStateBelowMask;
1259
else if (state == Atoms::winStateDemandsAttention)
1260
return CompWindowStateDemandsAttentionMask;
1261
else if (state == Atoms::winStateDisplayModal)
1262
return CompWindowStateDisplayModalMask;
1268
PrivateScreen::windowStateFromString (const char *str)
1270
if (strcasecmp (str, "modal") == 0)
1271
return CompWindowStateModalMask;
1272
else if (strcasecmp (str, "sticky") == 0)
1273
return CompWindowStateStickyMask;
1274
else if (strcasecmp (str, "maxvert") == 0)
1275
return CompWindowStateMaximizedVertMask;
1276
else if (strcasecmp (str, "maxhorz") == 0)
1277
return CompWindowStateMaximizedHorzMask;
1278
else if (strcasecmp (str, "shaded") == 0)
1279
return CompWindowStateShadedMask;
1280
else if (strcasecmp (str, "skiptaskbar") == 0)
1281
return CompWindowStateSkipTaskbarMask;
1282
else if (strcasecmp (str, "skippager") == 0)
1283
return CompWindowStateSkipPagerMask;
1284
else if (strcasecmp (str, "hidden") == 0)
1285
return CompWindowStateHiddenMask;
1286
else if (strcasecmp (str, "fullscreen") == 0)
1287
return CompWindowStateFullscreenMask;
1288
else if (strcasecmp (str, "above") == 0)
1289
return CompWindowStateAboveMask;
1290
else if (strcasecmp (str, "below") == 0)
1291
return CompWindowStateBelowMask;
1292
else if (strcasecmp (str, "demandsattention") == 0)
1293
return CompWindowStateDemandsAttentionMask;
1299
PrivateScreen::getWindowState (Window id)
1303
unsigned long n, left;
1304
unsigned char *data;
1305
unsigned int state = 0;
1307
result = XGetWindowProperty (priv->dpy, id,
1309
0L, 1024L, false, XA_ATOM, &actual, &format,
1312
if (result == Success && data)
1314
Atom *a = (Atom *) data;
1317
state |= windowStateMask (*a++);
1319
XFree ((void *) data);
1326
PrivateScreen::setWindowState (unsigned int state, Window id)
1331
if (state & CompWindowStateModalMask)
1332
data[i++] = Atoms::winStateModal;
1333
if (state & CompWindowStateStickyMask)
1334
data[i++] = Atoms::winStateSticky;
1335
if (state & CompWindowStateMaximizedVertMask)
1336
data[i++] = Atoms::winStateMaximizedVert;
1337
if (state & CompWindowStateMaximizedHorzMask)
1338
data[i++] = Atoms::winStateMaximizedHorz;
1339
if (state & CompWindowStateShadedMask)
1340
data[i++] = Atoms::winStateShaded;
1341
if (state & CompWindowStateSkipTaskbarMask)
1342
data[i++] = Atoms::winStateSkipTaskbar;
1343
if (state & CompWindowStateSkipPagerMask)
1344
data[i++] = Atoms::winStateSkipPager;
1345
if (state & CompWindowStateHiddenMask)
1346
data[i++] = Atoms::winStateHidden;
1347
if (state & CompWindowStateFullscreenMask)
1348
data[i++] = Atoms::winStateFullscreen;
1349
if (state & CompWindowStateAboveMask)
1350
data[i++] = Atoms::winStateAbove;
1351
if (state & CompWindowStateBelowMask)
1352
data[i++] = Atoms::winStateBelow;
1353
if (state & CompWindowStateDemandsAttentionMask)
1354
data[i++] = Atoms::winStateDemandsAttention;
1355
if (state & CompWindowStateDisplayModalMask)
1356
data[i++] = Atoms::winStateDisplayModal;
1358
XChangeProperty (priv->dpy, id, Atoms::winState,
1359
XA_ATOM, 32, PropModeReplace,
1360
(unsigned char *) data, i);
1364
PrivateScreen::getWindowType (Window id)
1366
Atom actual, a = None;
1368
unsigned long n, left;
1369
unsigned char *data;
1371
result = XGetWindowProperty (priv->dpy , id,
1373
0L, 1L, false, XA_ATOM, &actual, &format,
1376
if (result == Success && data)
1379
memcpy (&a, data, sizeof (Atom));
1380
XFree ((void *) data);
1385
if (a == Atoms::winTypeNormal)
1386
return CompWindowTypeNormalMask;
1387
else if (a == Atoms::winTypeMenu)
1388
return CompWindowTypeMenuMask;
1389
else if (a == Atoms::winTypeDesktop)
1390
return CompWindowTypeDesktopMask;
1391
else if (a == Atoms::winTypeDock)
1392
return CompWindowTypeDockMask;
1393
else if (a == Atoms::winTypeToolbar)
1394
return CompWindowTypeToolbarMask;
1395
else if (a == Atoms::winTypeUtil)
1396
return CompWindowTypeUtilMask;
1397
else if (a == Atoms::winTypeSplash)
1398
return CompWindowTypeSplashMask;
1399
else if (a == Atoms::winTypeDialog)
1400
return CompWindowTypeDialogMask;
1401
else if (a == Atoms::winTypeDropdownMenu)
1402
return CompWindowTypeDropdownMenuMask;
1403
else if (a == Atoms::winTypePopupMenu)
1404
return CompWindowTypePopupMenuMask;
1405
else if (a == Atoms::winTypeTooltip)
1406
return CompWindowTypeTooltipMask;
1407
else if (a == Atoms::winTypeNotification)
1408
return CompWindowTypeNotificationMask;
1409
else if (a == Atoms::winTypeCombo)
1410
return CompWindowTypeComboMask;
1411
else if (a == Atoms::winTypeDnd)
1412
return CompWindowTypeDndMask;
1415
return CompWindowTypeUnknownMask;
1419
PrivateScreen::getMwmHints (Window id,
1421
unsigned int *decor)
1425
unsigned long n, left;
1426
unsigned char *data;
1429
*decor = MwmDecorAll;
1431
result = XGetWindowProperty (priv->dpy, id,
1433
0L, 20L, false, Atoms::mwmHints,
1434
&actual, &format, &n, &left, &data);
1436
if (result == Success && data)
1438
MwmHints *mwmHints = (MwmHints *) data;
1440
if (n >= PropMotifWmHintElements)
1442
if (mwmHints->flags & MwmHintsDecorations)
1443
*decor = mwmHints->decorations;
1445
if (mwmHints->flags & MwmHintsFunctions)
1446
*func = mwmHints->functions;
1454
PrivateScreen::getProtocols (Window id)
1458
unsigned int protocols = 0;
1460
if (XGetWMProtocols (priv->dpy, id, &protocol, &count))
1464
for (i = 0; i < count; i++)
1466
if (protocol[i] == Atoms::wmDeleteWindow)
1467
protocols |= CompWindowProtocolDeleteMask;
1468
else if (protocol[i] == Atoms::wmTakeFocus)
1469
protocols |= CompWindowProtocolTakeFocusMask;
1470
else if (protocol[i] == Atoms::wmPing)
1471
protocols |= CompWindowProtocolPingMask;
1472
else if (protocol[i] == Atoms::wmSyncRequest)
1473
protocols |= CompWindowProtocolSyncRequestMask;
1483
CompScreen::getWindowProp (Window id,
1485
unsigned int defaultValue)
1489
unsigned long n, left;
1490
unsigned char *data;
1491
unsigned int retval = defaultValue;
1493
result = XGetWindowProperty (priv->dpy, id, property,
1494
0L, 1L, false, XA_CARDINAL, &actual, &format,
1497
if (result == Success && data)
1501
unsigned long value;
1502
memcpy (&value, data, sizeof (unsigned long));
1503
retval = (unsigned int) value;
1513
CompScreen::setWindowProp (Window id,
1517
unsigned long data = value;
1519
XChangeProperty (priv->dpy, id, property,
1520
XA_CARDINAL, 32, PropModeReplace,
1521
(unsigned char *) &data, 1);
1525
PrivateScreen::readWindowProp32 (Window id,
1527
unsigned short *returnValue)
1531
unsigned long n, left;
1532
unsigned char *data;
1533
bool retval = false;
1535
result = XGetWindowProperty (priv->dpy, id, property,
1536
0L, 1L, false, XA_CARDINAL, &actual, &format,
1539
if (result == Success && data)
1545
memcpy (&value, data, sizeof (CARD32));
1547
*returnValue = value >> 16;
1557
CompScreen::getWindowProp32 (Window id,
1559
unsigned short defaultValue)
1561
unsigned short result;
1563
if (priv->readWindowProp32 (id, property, &result))
1566
return defaultValue;
1570
CompScreen::setWindowProp32 (Window id,
1572
unsigned short value)
1576
value32 = value << 16 | value;
1578
XChangeProperty (priv->dpy, id, property,
1579
XA_CARDINAL, 32, PropModeReplace,
1580
(unsigned char *) &value32, 1);
1584
ScreenInterface::handleEvent (XEvent *event)
1585
WRAPABLE_DEF (handleEvent, event)
1588
ScreenInterface::handleCompizEvent (const char *plugin,
1590
CompOption::Vector &options)
1591
WRAPABLE_DEF (handleCompizEvent, plugin, event, options)
1594
ScreenInterface::fileToImage (CompString &name,
1598
WRAPABLE_DEF (fileToImage, name, size, stride, data)
1601
ScreenInterface::imageToFile (CompString &path,
1606
WRAPABLE_DEF (imageToFile, path, format, size, stride, data)
1608
CompMatch::Expression *
1609
ScreenInterface::matchInitExp (const CompString& value)
1610
WRAPABLE_DEF (matchInitExp, value)
1613
ScreenInterface::matchExpHandlerChanged ()
1614
WRAPABLE_DEF (matchExpHandlerChanged)
1617
ScreenInterface::matchPropertyChanged (CompWindow *window)
1618
WRAPABLE_DEF (matchPropertyChanged, window)
1621
ScreenInterface::logMessage (const char *componentName,
1623
const char *message)
1624
WRAPABLE_DEF (logMessage, componentName, level, message)
1628
PrivateScreen::desktopHintEqual (unsigned long *data,
1633
if (size != desktopHintSize)
1636
if (memcmp (data + offset,
1637
desktopHintData + offset,
1638
hintSize * sizeof (unsigned long)) == 0)
1645
PrivateScreen::setDesktopHints ()
1647
unsigned long *data;
1648
int dSize, offset, hintSize;
1651
dSize = nDesktop * 2 + nDesktop * 2 + nDesktop * 4 + 1;
1653
data = (unsigned long *) malloc (sizeof (unsigned long) * dSize);
1658
hintSize = nDesktop * 2;
1660
for (i = 0; i < nDesktop; i++)
1662
data[offset + i * 2 + 0] = vp.x () * screen->width ();
1663
data[offset + i * 2 + 1] = vp.y () * screen->height ();
1666
if (!desktopHintEqual (data, dSize, offset, hintSize))
1667
XChangeProperty (dpy, root,
1668
Atoms::desktopViewport,
1669
XA_CARDINAL, 32, PropModeReplace,
1670
(unsigned char *) &data[offset], hintSize);
1674
for (i = 0; i < nDesktop; i++)
1676
data[offset + i * 2 + 0] = screen->width () * vpSize.width ();
1677
data[offset + i * 2 + 1] = screen->height () * vpSize.height ();
1680
if (!desktopHintEqual (data, dSize, offset, hintSize))
1681
XChangeProperty (dpy, root,
1682
Atoms::desktopGeometry,
1683
XA_CARDINAL, 32, PropModeReplace,
1684
(unsigned char *) &data[offset], hintSize);
1687
hintSize = nDesktop * 4;
1689
for (i = 0; i < nDesktop; i++)
1691
data[offset + i * 4 + 0] = workArea.x ();
1692
data[offset + i * 4 + 1] = workArea.y ();
1693
data[offset + i * 4 + 2] = workArea.width ();
1694
data[offset + i * 4 + 3] = workArea.height ();
1697
if (!desktopHintEqual (data, dSize, offset, hintSize))
1698
XChangeProperty (dpy, root,
1700
XA_CARDINAL, 32, PropModeReplace,
1701
(unsigned char *) &data[offset], hintSize);
1705
data[offset] = nDesktop;
1708
if (!desktopHintEqual (data, dSize, offset, hintSize))
1709
XChangeProperty (dpy, root,
1710
Atoms::numberOfDesktops,
1711
XA_CARDINAL, 32, PropModeReplace,
1712
(unsigned char *) &data[offset], hintSize);
1714
if (desktopHintData)
1715
free (desktopHintData);
1717
desktopHintData = data;
1718
desktopHintSize = dSize;
1722
PrivateScreen::setVirtualScreenSize (int newh, int newv)
1724
/* if newh or newv is being reduced */
1725
if (newh < screen->vpSize ().width () ||
1726
newv < screen->vpSize ().height ())
1731
if (screen->vp ().x () >= newh)
1732
tx = screen->vp ().x () - (newh - 1);
1733
if (screen->vp ().y () >= newv)
1734
ty = screen->vp ().y () - (newv - 1);
1736
if (tx != 0 || ty != 0)
1737
screen->moveViewport (tx, ty, TRUE);
1739
/* Move windows that were in one of the deleted viewports into the
1741
foreach (CompWindow *w, screen->windows ())
1746
if (w->onAllViewports ())
1749
/* Find which viewport the (inner) window's top-left corner falls
1750
in, and check if it's outside the new viewport horizontal and
1751
vertical index range */
1752
if (newh < screen->vpSize ().width ())
1754
int vpX; /* x index of a window's vp */
1756
vpX = w->serverX () / screen->width ();
1757
if (w->serverX () < 0)
1760
vpX += screen->vp ().x (); /* Convert relative to absolute vp index */
1762
/* Move windows too far right to left */
1764
moveX = ((newh - 1) - vpX) * screen->width ();
1766
if (newv < screen->vpSize ().height ())
1768
int vpY; /* y index of a window's vp */
1770
vpY = w->serverY () / screen->height ();
1771
if (w->serverY () < 0)
1774
vpY += screen->vp ().y (); /* Convert relative to absolute vp index */
1776
/* Move windows too far right to left */
1778
moveY = ((newv - 1) - vpY) * screen->height ();
1781
if (moveX != 0 || moveY != 0)
1783
w->move (moveX, moveY, true);
1789
vpSize.setWidth (newh);
1790
vpSize.setHeight (newv);
1796
PrivateScreen::updateOutputDevices ()
1798
CompOption::Value::Vector &list = optionGetOutputs ();
1799
unsigned int nOutput = 0;
1801
unsigned int uWidth, uHeight;
1806
foreach (CompOption::Value &value, list)
1810
uWidth = (unsigned) screen->width ();
1811
uHeight = (unsigned) screen->height ();
1813
bits = XParseGeometry (value.s ().c_str (), &x, &y, &uWidth, &uHeight);
1814
width = (int) uWidth;
1815
height = (int) uHeight;
1817
if (bits & XNegative)
1818
x = screen->width () + x - width;
1820
if (bits & YNegative)
1821
y = screen->height () + y - height;
1832
if (x2 > screen->width ())
1833
x2 = screen->width ();
1834
if (y2 > screen->height ())
1835
y2 = screen->height ();
1837
if (x1 < x2 && y1 < y2)
1839
if (outputDevs.size () < nOutput + 1)
1840
outputDevs.resize (nOutput + 1);
1842
outputDevs[nOutput].setGeometry (x1, y1, x2 - x1, y2 - y1);
1847
/* make sure we have at least one output */
1850
if (outputDevs.size () < 1)
1851
outputDevs.resize (1);
1853
outputDevs[0].setGeometry (0, 0, screen->width (), screen->height ());
1857
if (outputDevs.size () > nOutput)
1858
outputDevs.resize (nOutput);
1860
/* set name, width, height and update rect pointers in all regions */
1861
for (unsigned int i = 0; i < nOutput; i++)
1863
snprintf (str, 10, "Output %d", i);
1864
outputDevs[i].setId (str, i);
1867
hasOverlappingOutputs = false;
1869
setCurrentOutput (currentOutputDev);
1871
/* clear out fullscreen monitor hints of all windows as
1872
suggested on monitor layout changes in EWMH */
1873
foreach (CompWindow *w, windows)
1874
if (w->priv->fullscreenMonitorsSet)
1875
w->priv->setFullscreenMonitors (NULL);
1877
for (unsigned int i = 0; i < nOutput - 1; i++)
1878
for (unsigned int j = i + 1; j < nOutput; j++)
1879
if (outputDevs[i].intersects (outputDevs[j]))
1880
hasOverlappingOutputs = true;
1882
screen->updateWorkarea ();
1884
screen->outputChangeNotify ();
1888
PrivateScreen::detectOutputDevices ()
1890
if (!noDetection && optionGetDetectOutputs ())
1893
CompOption::Value value;
1895
if (screenInfo.size ())
1897
CompOption::Value::Vector l;
1898
foreach (XineramaScreenInfo xi, screenInfo)
1900
l.push_back (compPrintf ("%dx%d+%d+%d", xi.width, xi.height,
1901
xi.x_org, xi.y_org));
1904
value.set (CompOption::TypeString, l);
1908
CompOption::Value::Vector l;
1909
l.push_back (compPrintf ("%dx%d+%d+%d", screen->width (),
1910
screen->height (), 0, 0));
1911
value.set (CompOption::TypeString, l);
1914
mOptions[CoreOptions::DetectOutputs].value ().set (false);
1915
screen->setOptionForPlugin ("core", "outputs", value);
1916
mOptions[CoreOptions::DetectOutputs].value ().set (true);
1921
updateOutputDevices ();
1927
PrivateScreen::updateStartupFeedback ()
1929
if (!startupSequences.empty ())
1930
XDefineCursor (dpy, root, busyCursor);
1932
XDefineCursor (dpy, root, normalCursor);
1935
#define STARTUP_TIMEOUT_DELAY 15000
1938
PrivateScreen::handleStartupSequenceTimeout ()
1940
struct timeval now, active;
1943
gettimeofday (&now, NULL);
1945
foreach (CompStartupSequence *s, startupSequences)
1947
sn_startup_sequence_get_last_active_time (s->sequence,
1951
elapsed = ((((double) now.tv_sec - active.tv_sec) * 1000000.0 +
1952
(now.tv_usec - active.tv_usec))) / 1000.0;
1954
if (elapsed > STARTUP_TIMEOUT_DELAY)
1955
sn_startup_sequence_complete (s->sequence);
1962
PrivateScreen::addSequence (SnStartupSequence *sequence)
1964
CompStartupSequence *s;
1966
s = new CompStartupSequence ();
1970
sn_startup_sequence_ref (sequence);
1972
s->sequence = sequence;
1973
s->viewportX = vp.x ();
1974
s->viewportY = vp.y ();
1976
startupSequences.push_front (s);
1978
if (!startupSequenceTimer.active ())
1979
startupSequenceTimer.start ();
1981
updateStartupFeedback ();
1985
PrivateScreen::removeSequence (SnStartupSequence *sequence)
1987
CompStartupSequence *s = NULL;
1989
std::list<CompStartupSequence *>::iterator it = startupSequences.begin ();
1991
for (; it != startupSequences.end (); it++)
1993
if ((*it)->sequence == sequence)
2003
sn_startup_sequence_unref (sequence);
2005
startupSequences.erase (it);
2009
if (startupSequences.empty () && startupSequenceTimer.active ())
2010
startupSequenceTimer.stop ();
2012
updateStartupFeedback ();
2016
PrivateScreen::removeAllSequences ()
2018
foreach (CompStartupSequence *s, startupSequences)
2020
sn_startup_sequence_unref (s->sequence);
2024
startupSequences.clear ();
2026
if (startupSequenceTimer.active ())
2027
startupSequenceTimer.stop ();
2029
updateStartupFeedback ();
2033
CompScreen::compScreenSnEvent (SnMonitorEvent *event,
2036
CompScreen *screen = (CompScreen *) userData;
2037
SnStartupSequence *sequence;
2039
sequence = sn_monitor_event_get_startup_sequence (event);
2041
switch (sn_monitor_event_get_type (event)) {
2042
case SN_MONITOR_EVENT_INITIATED:
2043
screen->priv->addSequence (sequence);
2045
case SN_MONITOR_EVENT_COMPLETED:
2046
screen->priv->removeSequence (sequence);
2048
case SN_MONITOR_EVENT_CHANGED:
2049
case SN_MONITOR_EVENT_CANCELED:
2055
PrivateScreen::updateScreenEdges ()
2057
struct screenEdgeGeometry {
2062
} geometry[SCREEN_EDGE_NUM] = {
2063
{ 0, 0, 0, 2, 0, 2, 1, -4 }, /* left */
2064
{ 1, -2, 0, 2, 0, 2, 1, -4 }, /* right */
2065
{ 0, 2, 0, 0, 1, -4, 0, 2 }, /* top */
2066
{ 0, 2, 1, -2, 1, -4, 0, 2 }, /* bottom */
2067
{ 0, 0, 0, 0, 0, 2, 0, 2 }, /* top-left */
2068
{ 1, -2, 0, 0, 0, 2, 0, 2 }, /* top-right */
2069
{ 0, 0, 1, -2, 0, 2, 0, 2 }, /* bottom-left */
2070
{ 1, -2, 1, -2, 0, 2, 0, 2 } /* bottom-right */
2074
for (i = 0; i < SCREEN_EDGE_NUM; i++)
2076
if (screenEdge[i].id)
2077
XMoveResizeWindow (dpy, screenEdge[i].id,
2078
geometry[i].xw * screen->width () +
2080
geometry[i].yh * screen->height () +
2082
geometry[i].ww * screen->width () +
2084
geometry[i].hh * screen->height () +
2090
PrivateScreen::setCurrentOutput (unsigned int outputNum)
2092
if (outputNum >= priv->outputDevs.size ())
2095
priv->currentOutputDev = outputNum;
2099
PrivateScreen::reshape (int w, int h)
2101
updateScreenInfo ();
2103
region = CompRegion (0, 0, w, h);
2105
screen->setWidth (w);
2106
screen->setHeight (h);
2108
fullscreenOutput.setId ("fullscreen", ~0);
2109
fullscreenOutput.setGeometry (0, 0, w, h);
2111
updateScreenEdges ();
2115
PrivateScreen::configure (XConfigureEvent *ce)
2117
if (priv->attrib.width != ce->width ||
2118
priv->attrib.height != ce->height)
2120
priv->attrib.width = ce->width;
2121
priv->attrib.height = ce->height;
2123
priv->reshape (ce->width, ce->height);
2125
priv->detectOutputDevices ();
2130
PrivateScreen::setSupportingWmCheck ()
2132
XChangeProperty (dpy, grabWindow,
2133
Atoms::supportingWmCheck,
2134
XA_WINDOW, 32, PropModeReplace,
2135
(unsigned char *) &grabWindow, 1);
2137
XChangeProperty (dpy, grabWindow, Atoms::wmName,
2138
Atoms::utf8String, 8, PropModeReplace,
2139
(unsigned char *) PACKAGE, strlen (PACKAGE));
2140
XChangeProperty (dpy, grabWindow, Atoms::winState,
2141
XA_ATOM, 32, PropModeReplace,
2142
(unsigned char *) &Atoms::winStateSkipTaskbar,
2144
XChangeProperty (dpy, grabWindow, Atoms::winState,
2145
XA_ATOM, 32, PropModeAppend,
2146
(unsigned char *) &Atoms::winStateSkipPager, 1);
2147
XChangeProperty (dpy, grabWindow, Atoms::winState,
2148
XA_ATOM, 32, PropModeAppend,
2149
(unsigned char *) &Atoms::winStateHidden, 1);
2151
XChangeProperty (dpy, root, Atoms::supportingWmCheck,
2152
XA_WINDOW, 32, PropModeReplace,
2153
(unsigned char *) &grabWindow, 1);
2157
CompScreen::updateSupportedWmHints ()
2159
std::vector<Atom> atoms;
2161
addSupportedAtoms (atoms);
2163
XChangeProperty (dpy (), root (), Atoms::supported,
2164
XA_ATOM, 32, PropModeReplace,
2165
(const unsigned char *) &atoms.at (0), atoms.size ());
2169
CompScreen::addSupportedAtoms (std::vector<Atom> &atoms)
2171
WRAPABLE_HND_FUNC (17, addSupportedAtoms, atoms);
2173
atoms.push_back (Atoms::supported);
2174
atoms.push_back (Atoms::supportingWmCheck);
2176
atoms.push_back (Atoms::utf8String);
2178
atoms.push_back (Atoms::clientList);
2179
atoms.push_back (Atoms::clientListStacking);
2181
atoms.push_back (Atoms::winActive);
2183
atoms.push_back (Atoms::desktopViewport);
2184
atoms.push_back (Atoms::desktopGeometry);
2185
atoms.push_back (Atoms::currentDesktop);
2186
atoms.push_back (Atoms::numberOfDesktops);
2187
atoms.push_back (Atoms::showingDesktop);
2189
atoms.push_back (Atoms::workarea);
2191
atoms.push_back (Atoms::wmName);
2193
atoms.push_back (Atoms::wmVisibleName);
2196
atoms.push_back (Atoms::wmStrut);
2197
atoms.push_back (Atoms::wmStrutPartial);
2200
atoms.push_back (Atoms::wmPid);
2203
atoms.push_back (Atoms::wmUserTime);
2204
atoms.push_back (Atoms::frameExtents);
2205
atoms.push_back (Atoms::frameWindow);
2207
atoms.push_back (Atoms::winState);
2208
atoms.push_back (Atoms::winStateModal);
2209
atoms.push_back (Atoms::winStateSticky);
2210
atoms.push_back (Atoms::winStateMaximizedVert);
2211
atoms.push_back (Atoms::winStateMaximizedHorz);
2212
atoms.push_back (Atoms::winStateShaded);
2213
atoms.push_back (Atoms::winStateSkipTaskbar);
2214
atoms.push_back (Atoms::winStateSkipPager);
2215
atoms.push_back (Atoms::winStateHidden);
2216
atoms.push_back (Atoms::winStateFullscreen);
2217
atoms.push_back (Atoms::winStateAbove);
2218
atoms.push_back (Atoms::winStateBelow);
2219
atoms.push_back (Atoms::winStateDemandsAttention);
2221
atoms.push_back (Atoms::winOpacity);
2222
atoms.push_back (Atoms::winBrightness);
2228
atoms.push_back (Atoms::winSaturation);
2229
atoms.push_back (Atoms::winStateDisplayModal);
2233
atoms.push_back (Atoms::wmAllowedActions);
2235
atoms.push_back (Atoms::winActionMove);
2236
atoms.push_back (Atoms::winActionResize);
2237
atoms.push_back (Atoms::winActionStick);
2238
atoms.push_back (Atoms::winActionMinimize);
2239
atoms.push_back (Atoms::winActionMaximizeHorz);
2240
atoms.push_back (Atoms::winActionMaximizeVert);
2241
atoms.push_back (Atoms::winActionFullscreen);
2242
atoms.push_back (Atoms::winActionClose);
2243
atoms.push_back (Atoms::winActionShade);
2244
atoms.push_back (Atoms::winActionChangeDesktop);
2245
atoms.push_back (Atoms::winActionAbove);
2246
atoms.push_back (Atoms::winActionBelow);
2248
atoms.push_back (Atoms::winType);
2249
atoms.push_back (Atoms::winTypeDesktop);
2250
atoms.push_back (Atoms::winTypeDock);
2251
atoms.push_back (Atoms::winTypeToolbar);
2252
atoms.push_back (Atoms::winTypeMenu);
2253
atoms.push_back (Atoms::winTypeSplash);
2254
atoms.push_back (Atoms::winTypeDialog);
2255
atoms.push_back (Atoms::winTypeUtil);
2256
atoms.push_back (Atoms::winTypeNormal);
2258
atoms.push_back (Atoms::wmDeleteWindow);
2259
atoms.push_back (Atoms::wmPing);
2261
atoms.push_back (Atoms::wmMoveResize);
2262
atoms.push_back (Atoms::moveResizeWindow);
2263
atoms.push_back (Atoms::restackWindow);
2265
atoms.push_back (Atoms::wmFullscreenMonitors);
2269
PrivateScreen::getDesktopHints ()
2271
unsigned long data[2];
2274
unsigned long n, left;
2275
unsigned char *propData;
2277
if (useDesktopHints)
2279
result = XGetWindowProperty (dpy, root,
2280
Atoms::numberOfDesktops,
2281
0L, 1L, false, XA_CARDINAL, &actual,
2282
&format, &n, &left, &propData);
2284
if (result == Success && propData)
2288
memcpy (data, propData, sizeof (unsigned long));
2289
if (data[0] > 0 && data[0] < 0xffffffff)
2296
result = XGetWindowProperty (dpy, root,
2297
Atoms::desktopViewport, 0L, 2L,
2298
false, XA_CARDINAL, &actual, &format,
2299
&n, &left, &propData);
2301
if (result == Success && propData)
2305
memcpy (data, propData, sizeof (unsigned long) * 2);
2307
if (data[0] / (unsigned int) screen->width () <
2308
(unsigned int) vpSize.width () - 1)
2309
vp.setX (data[0] / screen->width ());
2311
if (data[1] / (unsigned int) screen->height () <
2312
(unsigned int) vpSize.height () - 1)
2313
vp.setY (data[1] / screen->height ());
2319
result = XGetWindowProperty (dpy, root,
2320
Atoms::currentDesktop,
2321
0L, 1L, false, XA_CARDINAL, &actual,
2322
&format, &n, &left, &propData);
2324
if (result == Success && propData)
2328
memcpy (data, propData, sizeof (unsigned long));
2329
if (data[0] < nDesktop)
2330
currentDesktop = data[0];
2337
result = XGetWindowProperty (dpy, root,
2338
Atoms::showingDesktop,
2339
0L, 1L, false, XA_CARDINAL, &actual, &format,
2340
&n, &left, &propData);
2342
if (result == Success && propData)
2346
memcpy (data, propData, sizeof (unsigned long));
2348
screen->enterShowDesktopMode ();
2354
data[0] = currentDesktop;
2356
XChangeProperty (dpy, root, Atoms::currentDesktop,
2357
XA_CARDINAL, 32, PropModeReplace,
2358
(unsigned char *) data, 1);
2360
data[0] = showingDesktopMask ? true : false;
2362
XChangeProperty (dpy, root, Atoms::showingDesktop,
2363
XA_CARDINAL, 32, PropModeReplace,
2364
(unsigned char *) data, 1);
2368
CompScreen::enterShowDesktopMode ()
2370
WRAPABLE_HND_FUNC (14, enterShowDesktopMode)
2372
unsigned long data = 1;
2374
bool st = priv->optionGetHideSkipTaskbarWindows ();
2376
priv->showingDesktopMask = ~(CompWindowTypeDesktopMask |
2377
CompWindowTypeDockMask);
2379
foreach (CompWindow *w, priv->windows)
2381
if ((priv->showingDesktopMask & w->wmType ()) &&
2382
(!(w->state () & CompWindowStateSkipTaskbarMask) || st))
2384
if (!w->inShowDesktopMode () && !w->grabbed () &&
2385
w->managed () && w->focus ())
2387
w->setShowDesktopMode (true);
2388
w->windowNotify (CompWindowNotifyEnterShowDesktopMode);
2393
if (w->inShowDesktopMode ())
2399
priv->showingDesktopMask = 0;
2403
XChangeProperty (priv->dpy, priv->root,
2404
Atoms::showingDesktop,
2405
XA_CARDINAL, 32, PropModeReplace,
2406
(unsigned char *) &data, 1);
2410
CompScreen::leaveShowDesktopMode (CompWindow *window)
2412
WRAPABLE_HND_FUNC (15, leaveShowDesktopMode, window)
2414
unsigned long data = 0;
2418
if (!window->inShowDesktopMode ())
2421
window->setShowDesktopMode (false);
2422
window->windowNotify (CompWindowNotifyLeaveShowDesktopMode);
2423
window->priv->show ();
2425
/* return if some other window is still in show desktop mode */
2426
foreach (CompWindow *w, priv->windows)
2427
if (w->inShowDesktopMode ())
2430
priv->showingDesktopMask = 0;
2434
priv->showingDesktopMask = 0;
2436
foreach (CompWindow *w, priv->windows)
2438
if (!w->inShowDesktopMode ())
2441
w->setShowDesktopMode (false);
2442
w->windowNotify (CompWindowNotifyLeaveShowDesktopMode);
2446
/* focus default window - most likely this will be the window
2447
which had focus before entering showdesktop mode */
2448
focusDefaultWindow ();
2451
XChangeProperty (priv->dpy, priv->root,
2452
Atoms::showingDesktop,
2453
XA_CARDINAL, 32, PropModeReplace,
2454
(unsigned char *) &data, 1);
2458
CompScreen::forEachWindow (CompWindow::ForEach proc)
2460
foreach (CompWindow *w, priv->windows)
2465
CompScreen::focusDefaultWindow ()
2468
CompWindow *focus = NULL;
2470
if (!priv->optionGetClickToFocus ())
2472
w = findTopLevelWindow (priv->below);
2474
if (w && w->focus ())
2476
if (!(w->type () & (CompWindowTypeDesktopMask |
2477
CompWindowTypeDockMask)))
2483
Window rootReturn, childReturn;
2485
unsigned int dummyUInt;
2487
/* huh, we didn't find d->below ... perhaps it's out of date;
2488
try grabbing it through the server */
2490
status = XQueryPointer (dpy (), priv->root, &rootReturn,
2491
&childReturn, &dummyInt, &dummyInt,
2492
&dummyInt, &dummyInt, &dummyUInt);
2494
if (status && rootReturn == priv->root)
2496
w = findTopLevelWindow (childReturn);
2498
if (w && w->focus ())
2500
if (!(w->type () & (CompWindowTypeDesktopMask |
2501
CompWindowTypeDockMask)))
2510
for (CompWindowList::reverse_iterator rit = priv->windows.rbegin ();
2511
rit != priv->windows.rend (); rit++)
2515
if (w->type () & CompWindowTypeDockMask)
2522
if (w->type () & (CompWindowTypeNormalMask |
2523
CompWindowTypeDialogMask |
2524
CompWindowTypeModalDialogMask))
2526
if (PrivateWindow::compareWindowActiveness (focus, w) < 0)
2538
if (focus->id () != priv->activeWindow)
2539
focus->moveInputFocusTo ();
2543
XSetInputFocus (priv->dpy, priv->root, RevertToPointerRoot,
2549
CompScreen::findWindow (Window id)
2551
if (lastFoundWindow && lastFoundWindow->id () == id)
2553
return lastFoundWindow;
2557
CompWindow::Map::iterator it = priv->windowsMap.find (id);
2559
if (it != priv->windowsMap.end ())
2560
return (lastFoundWindow = it->second);
2567
CompScreen::findTopLevelWindow (Window id, bool override_redirect)
2571
w = findWindow (id);
2575
if (w->overrideRedirect () && !override_redirect)
2581
foreach (CompWindow *w, priv->windows)
2582
if (w->frame () == id)
2584
if (w->overrideRedirect () && !override_redirect)
2594
CompScreen::insertWindow (CompWindow *w, Window aboveId)
2599
if (!aboveId || priv->windows.empty ())
2601
if (!priv->windows.empty ())
2603
priv->windows.front ()->prev = w;
2604
w->next = priv->windows.front ();
2606
priv->windows.push_front (w);
2608
priv->windowsMap[w->id ()] = w;
2613
CompWindowList::iterator it = priv->windows.begin ();
2615
while (it != priv->windows.end ())
2617
if ((*it)->id () == aboveId ||
2618
((*it)->frame () && (*it)->frame () == aboveId))
2625
if (it == priv->windows.end ())
2633
w->next = (*it)->next;
2642
priv->windows.insert (++it, w);
2644
priv->windowsMap[w->id ()] = w;
2648
PrivateScreen::eraseWindowFromMap (Window id)
2651
priv->windowsMap.erase (id);
2655
CompScreen::unhookWindow (CompWindow *w)
2657
CompWindowList::iterator it =
2658
std::find (priv->windows.begin (), priv->windows.end (), w);
2660
priv->windows.erase (it);
2661
priv->eraseWindowFromMap (w->id ());
2664
w->next->prev = w->prev;
2667
w->prev->next = w->next;
2672
if (w == lastFoundWindow)
2673
lastFoundWindow = NULL;
2677
CompScreen::normalCursor ()
2679
return priv->normalCursor;
2683
CompScreen::invisibleCursor ()
2685
return priv->invisibleCursor;
2688
#define POINTER_GRAB_MASK (ButtonReleaseMask | \
2691
CompScreen::GrabHandle
2692
CompScreen::pushGrab (Cursor cursor, const char *name)
2694
if (priv->grabs.empty ())
2698
status = XGrabPointer (priv->dpy, priv->grabWindow, true,
2700
GrabModeAsync, GrabModeAsync,
2704
if (status == GrabSuccess)
2706
status = XGrabKeyboard (priv->dpy,
2707
priv->grabWindow, true,
2708
GrabModeAsync, GrabModeAsync,
2710
if (status != GrabSuccess)
2712
XUngrabPointer (priv->dpy, CurrentTime);
2721
XChangeActivePointerGrab (priv->dpy, POINTER_GRAB_MASK,
2722
cursor, CurrentTime);
2725
PrivateScreen::Grab *grab = new PrivateScreen::Grab ();
2726
grab->cursor = cursor;
2729
priv->grabs.push_back (grab);
2735
CompScreen::updateGrab (CompScreen::GrabHandle handle, Cursor cursor)
2740
XChangeActivePointerGrab (priv->dpy, POINTER_GRAB_MASK,
2741
cursor, CurrentTime);
2743
((PrivateScreen::Grab *) handle)->cursor = cursor;
2747
CompScreen::removeGrab (CompScreen::GrabHandle handle,
2748
CompPoint *restorePointer)
2753
std::list<PrivateScreen::Grab *>::iterator it;
2755
it = std::find (priv->grabs.begin (), priv->grabs.end (), handle);
2757
if (it != priv->grabs.end ())
2759
priv->grabs.erase (it);
2760
delete (static_cast<PrivateScreen::Grab *> (handle));
2762
if (!priv->grabs.empty ())
2764
XChangeActivePointerGrab (priv->dpy,
2766
priv->grabs.back ()->cursor,
2772
warpPointer (restorePointer->x () - pointerX,
2773
restorePointer->y () - pointerY);
2775
XUngrabPointer (priv->dpy, CurrentTime);
2776
XUngrabKeyboard (priv->dpy, CurrentTime);
2780
/* otherScreenGrabExist takes a series of strings terminated by a NULL.
2781
It returns true if a grab exists but it is NOT held by one of the
2782
plugins listed, returns false otherwise. */
2785
CompScreen::otherGrabExist (const char *first, ...)
2790
std::list<PrivateScreen::Grab *>::iterator it;
2792
for (it = priv->grabs.begin (); it != priv->grabs.end (); it++)
2794
va_start (ap, first);
2799
if (strcmp (name, (*it)->name) == 0)
2802
name = va_arg (ap, const char *);
2815
CompScreen::grabExist (const char *grab)
2817
foreach (PrivateScreen::Grab* g, priv->grabs)
2819
if (strcmp (g->name, grab) == 0)
2826
CompScreen::grabbed ()
2828
return priv->grabbed;
2832
PrivateScreen::grabUngrabOneKey (unsigned int modifiers,
2856
PrivateScreen::grabUngrabKeys (unsigned int modifiers,
2861
unsigned int ignore;
2863
CompScreen::checkForError (dpy);
2865
for (ignore = 0; ignore <= modHandler->ignoredModMask (); ignore++)
2867
if (ignore & ~modHandler->ignoredModMask ())
2872
grabUngrabOneKey (modifiers | ignore, keycode, grab);
2876
for (mod = 0; mod < 8; mod++)
2878
if (modifiers & (1 << mod))
2880
for (k = mod * modHandler->modMap ()->max_keypermod;
2881
k < (mod + 1) * modHandler->modMap ()->max_keypermod;
2884
if (modHandler->modMap ()->modifiermap[k])
2886
grabUngrabOneKey ((modifiers & ~(1 << mod)) |
2888
modHandler->modMap ()->modifiermap[k],
2896
if (CompScreen::checkForError (dpy))
2904
PrivateScreen::addPassiveKeyGrab (CompAction::KeyBinding &key)
2908
std::list<KeyGrab>::iterator it;
2910
mask = modHandler->virtualToRealModMask (key.modifiers ());
2912
for (it = keyGrabs.begin (); it != keyGrabs.end (); it++)
2914
if (key.keycode () == (*it).keycode &&
2915
mask == (*it).modifiers)
2924
if (!(mask & CompNoMask))
2926
if (!grabUngrabKeys (mask, key.keycode (), true))
2930
newKeyGrab.keycode = key.keycode ();
2931
newKeyGrab.modifiers = mask;
2932
newKeyGrab.count = 1;
2934
keyGrabs.push_back (newKeyGrab);
2940
PrivateScreen::removePassiveKeyGrab (CompAction::KeyBinding &key)
2943
std::list<KeyGrab>::iterator it;
2945
mask = modHandler->virtualToRealModMask (key.modifiers ());
2947
for (it = keyGrabs.begin (); it != keyGrabs.end (); it++)
2949
if (key.keycode () == (*it).keycode &&
2950
mask == (*it).modifiers)
2956
it = keyGrabs.erase (it);
2958
if (!(mask & CompNoMask))
2959
grabUngrabKeys (mask, key.keycode (), false);
2965
PrivateScreen::updatePassiveKeyGrabs ()
2967
std::list<KeyGrab>::iterator it;
2969
XUngrabKey (dpy, AnyKey, AnyModifier, root);
2971
for (it = keyGrabs.begin (); it != keyGrabs.end (); it++)
2973
if (!((*it).modifiers & CompNoMask))
2975
grabUngrabKeys ((*it).modifiers,
2976
(*it).keycode, true);
2982
PrivateScreen::addPassiveButtonGrab (CompAction::ButtonBinding &button)
2984
ButtonGrab newButtonGrab;
2985
std::list<ButtonGrab>::iterator it;
2987
for (it = buttonGrabs.begin (); it != buttonGrabs.end (); it++)
2989
if (button.button () == (*it).button &&
2990
button.modifiers () == (*it).modifiers)
2997
newButtonGrab.button = button.button ();
2998
newButtonGrab.modifiers = button.modifiers ();
2999
newButtonGrab.count = 1;
3001
buttonGrabs.push_back (newButtonGrab);
3003
foreach (CompWindow *w, screen->windows ())
3004
w->priv->updatePassiveButtonGrabs ();
3010
PrivateScreen::removePassiveButtonGrab (CompAction::ButtonBinding &button)
3012
std::list<ButtonGrab>::iterator it;
3014
for (it = buttonGrabs.begin (); it != buttonGrabs.end (); it++)
3016
if (button.button () == (*it).button &&
3017
button.modifiers () == (*it).modifiers)
3023
it = buttonGrabs.erase (it);
3025
foreach (CompWindow *w, screen->windows ())
3026
w->priv->updatePassiveButtonGrabs ();
3031
/* add actions that should be automatically added as no screens
3032
existed when they were initialized. */
3034
PrivateScreen::addScreenActions ()
3036
foreach (CompOption &o, mOptions)
3041
if (o.value ().action ().state () & CompAction::StateAutoGrab)
3042
screen->addAction (&o.value ().action ());
3047
CompScreen::addAction (CompAction *action)
3049
if (!screenInitalized || !priv->initialized)
3052
if (action->active ())
3055
if (action->type () & CompAction::BindingTypeKey)
3057
if (!priv->addPassiveKeyGrab (action->key ()))
3061
if (action->type () & CompAction::BindingTypeButton)
3063
if (!priv->addPassiveButtonGrab (action->button ()))
3065
if (action->type () & CompAction::BindingTypeKey)
3066
priv->removePassiveKeyGrab (action->key ());
3072
if (action->edgeMask ())
3076
for (i = 0; i < SCREEN_EDGE_NUM; i++)
3077
if (action->edgeMask () & (1 << i))
3078
priv->enableEdge (i);
3081
action->priv->active = true;
3087
CompScreen::removeAction (CompAction *action)
3089
if (!priv->initialized)
3092
if (!action->active ())
3095
if (action->type () & CompAction::BindingTypeKey)
3096
priv->removePassiveKeyGrab (action->key ());
3098
if (action->type () & CompAction::BindingTypeButton)
3099
priv->removePassiveButtonGrab (action->button ());
3101
if (action->edgeMask ())
3105
for (i = 0; i < SCREEN_EDGE_NUM; i++)
3106
if (action->edgeMask () & (1 << i))
3107
priv->disableEdge (i);
3110
action->priv->active = false;
3114
PrivateScreen::computeWorkareaForBox (const CompRect& box)
3121
foreach (CompWindow *w, windows)
3123
if (!w->isMapped ())
3128
x1 = w->struts ()->left.x;
3129
y1 = w->struts ()->left.y;
3130
x2 = x1 + w->struts ()->left.width;
3131
y2 = y1 + w->struts ()->left.height;
3133
if (y1 < box.y2 () && y2 > box.y1 ())
3134
region -= CompRect (x1, box.y1 (), x2 - x1, box.height ());
3136
x1 = w->struts ()->right.x;
3137
y1 = w->struts ()->right.y;
3138
x2 = x1 + w->struts ()->right.width;
3139
y2 = y1 + w->struts ()->right.height;
3141
if (y1 < box.y2 () && y2 > box.y1 ())
3142
region -= CompRect (x1, box.y1 (), x2 - x1, box.height ());
3144
x1 = w->struts ()->top.x;
3145
y1 = w->struts ()->top.y;
3146
x2 = x1 + w->struts ()->top.width;
3147
y2 = y1 + w->struts ()->top.height;
3149
if (x1 < box.x2 () && x2 > box.x1 ())
3150
region -= CompRect (box.x1 (), y1, box.width (), y2 - y1);
3152
x1 = w->struts ()->bottom.x;
3153
y1 = w->struts ()->bottom.y;
3154
x2 = x1 + w->struts ()->bottom.width;
3155
y2 = y1 + w->struts ()->bottom.height;
3157
if (x1 < box.x2 () && x2 > box.x1 ())
3158
region -= CompRect (box.x1 (), y1, box.width (), y2 - y1);
3162
if (region.isEmpty ())
3164
compLogMessage ("core", CompLogLevelWarn,
3165
"Empty box after applying struts, ignoring struts");
3169
return region.boundingRect ();
3173
CompScreen::updateWorkarea ()
3176
bool workAreaChanged = false;
3178
for (unsigned int i = 0; i < priv->outputDevs.size (); i++)
3180
CompRect oldWorkArea = priv->outputDevs[i].workArea ();
3182
workArea = priv->computeWorkareaForBox (priv->outputDevs[i]);
3184
if (workArea != oldWorkArea)
3186
workAreaChanged = true;
3187
priv->outputDevs[i].setWorkArea (workArea);
3191
workArea = priv->computeWorkareaForBox (CompRect (0, 0,
3193
screen->height ()));
3195
if (priv->workArea != workArea)
3197
workAreaChanged = true;
3198
priv->workArea = workArea;
3200
priv->setDesktopHints ();
3203
if (workAreaChanged)
3205
/* as work area changed, update all maximized windows on this
3206
screen to snap to the new work area */
3207
foreach (CompWindow *w, priv->windows)
3208
w->priv->updateSize ();
3213
isClientListWindow (CompWindow *w)
3215
/* windows with client id less than 2 have been destroyed and only exists
3216
because some plugin keeps a reference to them. they should not be in
3221
if (w->overrideRedirect ())
3224
if (!w->isViewable ())
3226
if (!(w->state () & CompWindowStateHiddenMask))
3234
countClientListWindow (CompWindow *w,
3237
if (isClientListWindow (w))
3244
compareMappingOrder (const CompWindow *w1,
3245
const CompWindow *w2)
3247
return w1->mapNum () < w2->mapNum ();
3251
PrivateScreen::updateClientList ()
3253
bool updateClientList = false;
3254
bool updateClientListStacking = false;
3257
screen->forEachWindow (boost::bind (countClientListWindow, _1, &n));
3261
if ((unsigned int) n != priv->clientList.size ())
3263
priv->clientList.clear ();
3264
priv->clientListStacking.clear ();
3265
priv->clientIdList.clear ();
3266
priv->clientIdListStacking.clear ();
3268
XChangeProperty (priv->dpy, priv->root,
3270
XA_WINDOW, 32, PropModeReplace,
3271
(unsigned char *) &priv->grabWindow, 1);
3272
XChangeProperty (priv->dpy, priv->root,
3273
Atoms::clientListStacking,
3274
XA_WINDOW, 32, PropModeReplace,
3275
(unsigned char *) &priv->grabWindow, 1);
3281
if ((unsigned int) n != priv->clientList.size ())
3283
priv->clientIdList.resize (n);
3284
priv->clientIdListStacking.resize (n);
3286
updateClientList = updateClientListStacking = true;
3289
priv->clientListStacking.clear ();
3291
foreach (CompWindow *w, priv->windows)
3292
if (isClientListWindow (w))
3293
priv->clientListStacking.push_back (w);
3295
/* clear clientList and copy clientListStacking into clientList */
3296
priv->clientList = priv->clientListStacking;
3298
/* sort clientList in mapping order */
3299
sort (priv->clientList.begin (), priv->clientList.end (),
3300
compareMappingOrder);
3302
/* make sure client id lists are up-to-date */
3303
for (int i = 0; i < n; i++)
3305
if (!updateClientList &&
3306
priv->clientIdList[i] != priv->clientList[i]->id ())
3308
updateClientList = true;
3311
priv->clientIdList[i] = priv->clientList[i]->id ();
3313
for (int i = 0; i < n; i++)
3315
if (!updateClientListStacking &&
3316
priv->clientIdListStacking[i] != priv->clientListStacking[i]->id ())
3318
updateClientListStacking = true;
3321
priv->clientIdListStacking[i] = priv->clientListStacking[i]->id ();
3324
if (updateClientList)
3325
XChangeProperty (priv->dpy, priv->root,
3327
XA_WINDOW, 32, PropModeReplace,
3328
(unsigned char *) &priv->clientIdList.at (0), n);
3330
if (updateClientListStacking)
3331
XChangeProperty (priv->dpy, priv->root,
3332
Atoms::clientListStacking,
3333
XA_WINDOW, 32, PropModeReplace,
3334
(unsigned char *) &priv->clientIdListStacking.at (0),
3338
const CompWindowVector &
3339
CompScreen::clientList (bool stackingOrder)
3341
return stackingOrder ? priv->clientListStacking : priv->clientList;
3345
CompScreen::toolkitAction (Atom toolkitAction,
3354
ev.type = ClientMessage;
3355
ev.xclient.window = window;
3356
ev.xclient.message_type = Atoms::toolkitAction;
3357
ev.xclient.format = 32;
3358
ev.xclient.data.l[0] = toolkitAction;
3359
ev.xclient.data.l[1] = eventTime;
3360
ev.xclient.data.l[2] = data0;
3361
ev.xclient.data.l[3] = data1;
3362
ev.xclient.data.l[4] = data2;
3364
XUngrabPointer (priv->dpy, CurrentTime);
3365
XUngrabKeyboard (priv->dpy, CurrentTime);
3367
XSendEvent (priv->dpy, priv->root, false,
3368
StructureNotifyMask, &ev);
3372
CompScreen::runCommand (CompString command)
3374
if (command.size () == 0)
3380
CompString env (priv->displayString);
3384
pos = env.find (':');
3385
if (pos != std::string::npos)
3387
if (env.find ('.', pos) != std::string::npos)
3389
env.erase (env.find ('.', pos));
3398
env.append (compPrintf (".%d", priv->screenNum));
3400
putenv (const_cast<char *> (env.c_str ()));
3402
exit (execl ("/bin/sh", "/bin/sh", "-c", command.c_str (), NULL));
3407
CompScreen::moveViewport (int tx, int ty, bool sync)
3411
tx = priv->vp.x () - tx;
3412
tx = MOD (tx, priv->vpSize.width ());
3413
tx -= priv->vp.x ();
3415
ty = priv->vp.y () - ty;
3416
ty = MOD (ty, priv->vpSize.height ());
3417
ty -= priv->vp.y ();
3422
priv->vp.setX (priv->vp.x () + tx);
3423
priv->vp.setY (priv->vp.y () + ty);
3428
foreach (CompWindow *w, priv->windows)
3430
if (w->onAllViewports ())
3433
pnt = w->getMovementForOffset (CompPoint (tx, ty));
3435
if (w->saveMask () & CWX)
3436
w->saveWc ().x += pnt.x ();
3438
if (w->saveMask () & CWY)
3439
w->saveWc ().y += pnt.y ();
3442
w->move (pnt.x (), pnt.y ());
3452
priv->setDesktopHints ();
3454
priv->setCurrentActiveWindowHistory (priv->vp.x (), priv->vp.y ());
3456
w = findWindow (priv->activeWindow);
3461
dvp = w->defaultViewport ();
3463
/* add window to current history if it's default viewport is
3464
still the current one. */
3465
if (priv->vp.x () == dvp.x () && priv->vp.y () == dvp.y ())
3466
priv->addToCurrentActiveWindowHistory (w->id ());
3472
PrivateScreen::addGroup (Window id)
3474
CompGroup *group = new CompGroup ();
3479
priv->groups.push_back (group);
3485
PrivateScreen::removeGroup (CompGroup *group)
3491
std::list<CompGroup *>::iterator it =
3492
std::find (priv->groups.begin (), priv->groups.end (), group);
3494
if (it != priv->groups.end ())
3496
priv->groups.erase (it);
3503
PrivateScreen::findGroup (Window id)
3505
foreach (CompGroup *g, priv->groups)
3513
PrivateScreen::applyStartupProperties (CompWindow *window)
3515
CompStartupSequence *s = NULL;
3516
const char *startupId = window->startupId ();
3522
leader = screen->findWindow (window->clientLeader ());
3524
startupId = leader->startupId ();
3530
foreach (CompStartupSequence *ss, priv->startupSequences)
3534
id = sn_startup_sequence_get_id (ss->sequence);
3535
if (strcmp (id, startupId) == 0)
3543
window->priv->applyStartupProperties (s);
3547
CompScreen::sendWindowActivationRequest (Window id)
3551
xev.xclient.type = ClientMessage;
3552
xev.xclient.display = priv->dpy;
3553
xev.xclient.format = 32;
3555
xev.xclient.message_type = Atoms::winActive;
3556
xev.xclient.window = id;
3558
xev.xclient.data.l[0] = ClientTypePager;
3559
xev.xclient.data.l[1] = 0;
3560
xev.xclient.data.l[2] = 0;
3561
xev.xclient.data.l[3] = 0;
3562
xev.xclient.data.l[4] = 0;
3564
XSendEvent (priv->dpy, priv->root, false,
3565
SubstructureRedirectMask | SubstructureNotifyMask, &xev);
3569
PrivateScreen::enableEdge (int edge)
3571
priv->screenEdge[edge].count++;
3572
if (priv->screenEdge[edge].count == 1)
3573
XMapRaised (priv->dpy, priv->screenEdge[edge].id);
3577
PrivateScreen::disableEdge (int edge)
3579
priv->screenEdge[edge].count--;
3580
if (priv->screenEdge[edge].count == 0)
3581
XUnmapWindow (priv->dpy, priv->screenEdge[edge].id);
3585
PrivateScreen::getTopWindow ()
3587
/* return first window that has not been destroyed */
3588
for (CompWindowList::reverse_iterator rit = priv->windows.rbegin ();
3589
rit != priv->windows.rend (); rit++)
3591
if ((*rit)->id () > 1)
3592
return (*rit)->id ();
3599
CompScreen::outputDeviceForPoint (const CompPoint &point)
3601
return outputDeviceForPoint (point.x (), point.y ());
3605
CompScreen::outputDeviceForPoint (int x, int y)
3607
CompWindow::Geometry geom (x, y, 1, 1, 0);
3609
return outputDeviceForGeometry (geom);
3613
CompScreen::getCurrentOutputExtents ()
3615
return priv->outputDevs[priv->currentOutputDev];
3619
PrivateScreen::setNumberOfDesktops (unsigned int nDesktop)
3621
if (nDesktop < 1 || nDesktop >= 0xffffffff)
3624
if (nDesktop == priv->nDesktop)
3627
if (priv->currentDesktop >= nDesktop)
3628
priv->currentDesktop = nDesktop - 1;
3630
foreach (CompWindow *w, priv->windows)
3632
if (w->desktop () == 0xffffffff)
3635
if (w->desktop () >= nDesktop)
3636
w->setDesktop (nDesktop - 1);
3639
priv->nDesktop = nDesktop;
3641
priv->setDesktopHints ();
3645
PrivateScreen::setCurrentDesktop (unsigned int desktop)
3649
if (desktop >= priv->nDesktop)
3652
if (desktop == priv->currentDesktop)
3655
priv->currentDesktop = desktop;
3657
foreach (CompWindow *w, priv->windows)
3659
if (w->desktop () == 0xffffffff)
3662
if (w->desktop () == desktop)
3670
XChangeProperty (priv->dpy, priv->root, Atoms::currentDesktop,
3671
XA_CARDINAL, 32, PropModeReplace,
3672
(unsigned char *) &data, 1);
3676
CompScreen::getWorkareaForOutput (unsigned int outputNum) const
3678
return priv->outputDevs[outputNum].workArea ();
3682
CompScreen::outputChangeNotify ()
3683
WRAPABLE_HND_FUNC (16, outputChangeNotify)
3687
/* Returns default viewport for some window geometry. If the window spans
3688
more than one viewport the most appropriate viewport is returned. How the
3689
most appropriate viewport is computed can be made optional if necessary. It
3690
is currently computed as the viewport where the center of the window is
3693
CompScreen::viewportForGeometry (const CompWindow::Geometry& gm,
3694
CompPoint& viewport)
3699
rect.setWidth (rect.width () + (gm.border () * 2));
3700
rect.setHeight (rect.height () + (gm.border () * 2));
3702
offset = rect.centerX () < 0 ? -1 : 0;
3703
viewport.setX (priv->vp.x () + ((rect.centerX () / width ()) + offset) %
3704
priv->vpSize.width ());
3706
offset = rect.centerY () < 0 ? -1 : 0;
3707
viewport.setY (priv->vp.y () + ((rect.centerY () / height ()) + offset ) %
3708
priv->vpSize.height ());
3712
CompScreen::outputDeviceForGeometry (const CompWindow::Geometry& gm)
3714
int overlapAreas[priv->outputDevs.size ()];
3715
int highest, seen, highestScore;
3720
if (priv->outputDevs.size () == 1)
3723
strategy = priv->optionGetOverlappingOutputs ();
3725
if (strategy == CoreOptions::OverlappingOutputsSmartMode)
3727
int centerX, centerY;
3729
/* for smart mode, calculate the overlap of the whole rectangle
3730
with the output device rectangle */
3731
geomRect.setWidth (gm.width () + 2 * gm.border ());
3732
geomRect.setHeight (gm.height () + 2 * gm.border ());
3734
x = gm.x () % width ();
3735
centerX = (x + (geomRect.width () / 2));
3738
else if (centerX > width ())
3742
y = gm.y () % height ();
3743
centerY = (y + (geomRect.height () / 2));
3746
else if (centerY > height ())
3752
/* for biggest/smallest modes, only use the window center to determine
3753
the correct output device */
3754
x = (gm.x () + (gm.width () / 2) + gm.border ()) % width ();
3757
y = (gm.y () + (gm.height () / 2) + gm.border ()) % height ();
3761
geomRect.setGeometry (x, y, 1, 1);
3764
/* get amount of overlap on all output devices */
3765
for (i = 0; i < priv->outputDevs.size (); i++)
3767
CompRect overlap = priv->outputDevs[i] & geomRect;
3768
overlapAreas[i] = overlap.area ();
3771
/* find output with largest overlap */
3772
for (i = 0, highest = 0, highestScore = 0;
3773
i < priv->outputDevs.size (); i++)
3775
if (overlapAreas[i] > highestScore)
3778
highestScore = overlapAreas[i];
3782
/* look if the highest score is unique */
3783
for (i = 0, seen = 0; i < priv->outputDevs.size (); i++)
3784
if (overlapAreas[i] == highestScore)
3789
/* it's not unique, select one output of the matching ones and use the
3790
user preferred strategy for that */
3791
unsigned int currentSize, bestOutputSize;
3795
(strategy != CoreOptions::OverlappingOutputsPreferSmallerOutput);
3800
bestOutputSize = UINT_MAX;
3802
for (i = 0, highest = 0; i < priv->outputDevs.size (); i++)
3803
if (overlapAreas[i] == highestScore)
3807
currentSize = priv->outputDevs[i].area ();
3810
bestFit = (currentSize > bestOutputSize);
3812
bestFit = (currentSize < bestOutputSize);
3817
bestOutputSize = currentSize;
3826
CompScreen::defaultIcon () const
3828
return priv->defaultIcon;
3832
CompScreen::updateDefaultIcon ()
3834
CompString file = priv->optionGetDefaultIcon ();
3838
if (priv->defaultIcon)
3840
delete priv->defaultIcon;
3841
priv->defaultIcon = NULL;
3844
if (!readImageFromFile (file, size, data))
3847
priv->defaultIcon = new CompIcon (screen, size.width (), size.height ());
3849
memcpy (priv->defaultIcon->data (), data,
3850
size.width () * size.height () * sizeof (CARD32));
3858
PrivateScreen::setCurrentActiveWindowHistory (int x, int y)
3862
for (i = 0; i < ACTIVE_WINDOW_HISTORY_NUM; i++)
3864
if (priv->history[i].x == x && priv->history[i].y == y)
3866
priv->currentHistory = i;
3871
for (i = 1; i < ACTIVE_WINDOW_HISTORY_NUM; i++)
3872
if (priv->history[i].activeNum < priv->history[min].activeNum)
3875
priv->currentHistory = min;
3877
priv->history[min].activeNum = priv->activeNum;
3878
priv->history[min].x = x;
3879
priv->history[min].y = y;
3881
memset (priv->history[min].id, 0, sizeof (priv->history[min].id));
3885
PrivateScreen::addToCurrentActiveWindowHistory (Window id)
3887
CompActiveWindowHistory *history = &priv->history[priv->currentHistory];
3888
Window tmp, next = id;
3891
/* walk and move history */
3892
for (i = 0; i < ACTIVE_WINDOW_HISTORY_SIZE; i++)
3894
tmp = history->id[i];
3895
history->id[i] = next;
3898
/* we're done when we find an old instance or an empty slot */
3899
if (tmp == id || tmp == None)
3903
history->activeNum = priv->activeNum;
3907
ScreenInterface::enterShowDesktopMode ()
3908
WRAPABLE_DEF (enterShowDesktopMode)
3911
ScreenInterface::leaveShowDesktopMode (CompWindow *window)
3912
WRAPABLE_DEF (leaveShowDesktopMode, window)
3915
ScreenInterface::outputChangeNotify ()
3916
WRAPABLE_DEF (outputChangeNotify)
3919
ScreenInterface::addSupportedAtoms (std::vector<Atom>& atoms)
3920
WRAPABLE_DEF (addSupportedAtoms, atoms)
3930
CompScreen::xkbEvent ()
3932
return priv->xkbEvent;
3936
CompScreen::warpPointer (int dx,
3944
if (pointerX >= width ())
3945
pointerX = width () - 1;
3946
else if (pointerX < 0)
3949
if (pointerY >= height ())
3950
pointerY = height () - 1;
3951
else if (pointerY < 0)
3954
XWarpPointer (priv->dpy,
3957
pointerX, pointerY);
3959
XSync (priv->dpy, false);
3961
while (XCheckMaskEvent (priv->dpy,
3969
lastPointerX = pointerX;
3970
lastPointerY = pointerY;
3975
CompScreen::windows ()
3977
return priv->windows;
3981
CompScreen::getCurrentTime ()
3985
XChangeProperty (priv->dpy, priv->grabWindow,
3986
XA_PRIMARY, XA_STRING, 8,
3987
PropModeAppend, NULL, 0);
3988
XWindowEvent (priv->dpy, priv->grabWindow,
3992
return event.xproperty.time;
3996
CompScreen::selectionWindow ()
3998
return priv->wmSnSelectionWindow;
4002
CompScreen::screenNum ()
4004
return priv->screenNum;
4014
CompScreen::vpSize ()
4016
return priv->vpSize;
4020
CompScreen::desktopWindowCount ()
4022
return priv->desktopWindowCount;
4026
CompScreen::activeNum () const
4028
return priv->activeNum;
4031
CompOutput::vector &
4032
CompScreen::outputDevs ()
4034
return priv->outputDevs;
4038
CompScreen::currentOutputDev () const
4040
return priv->outputDevs [priv->currentOutputDev];
4044
CompScreen::workArea () const
4046
return priv->workArea;
4050
CompScreen::currentDesktop ()
4052
return priv->currentDesktop;
4056
CompScreen::nDesktop ()
4058
return priv->nDesktop;
4061
CompActiveWindowHistory *
4062
CompScreen::currentHistory ()
4064
return &priv->history[priv->currentHistory];
4068
CompScreen::shouldSerializePlugins ()
4070
return priv->optionGetDoSerialize ();
4074
PrivateScreen::removeDestroyed ()
4076
while (pendingDestroys)
4078
foreach (CompWindow *w, windows)
4080
if (w->destroyed ())
4092
CompScreen::region () const
4094
return priv->region;
4098
CompScreen::hasOverlappingOutputs ()
4100
return priv->hasOverlappingOutputs;
4104
CompScreen::fullscreenOutput ()
4106
return priv->fullscreenOutput;
4111
CompScreen::attrib ()
4113
return priv->attrib;
4116
std::vector<XineramaScreenInfo> &
4117
CompScreen::screenInfo ()
4119
return priv->screenInfo;
4123
PrivateScreen::createFailed ()
4125
return !screenInitalized;
4128
CompScreen::CompScreen ():
4129
PluginClassStorage (screenPluginClassIndices),
4133
CompOption::Value::Vector vList;
4134
CompPlugin *corePlugin;
4136
priv = new PrivateScreen (this);
4139
screenInitalized = true;
4141
corePlugin = CompPlugin::load ("core");
4144
compLogMessage ("core", CompLogLevelFatal,
4145
"Couldn't load core plugin");
4146
screenInitalized = false;
4149
if (!CompPlugin::push (corePlugin))
4151
compLogMessage ("core", CompLogLevelFatal,
4152
"Couldn't activate core plugin");
4153
screenInitalized = false;
4156
p.uval = CORE_ABIVERSION;
4157
storeValue ("core_ABI", p);
4159
vList.push_back ("core");
4161
priv->plugin.set (CompOption::TypeString, vList);
4165
CompScreen::init (const char *name)
4172
Window newWmSnOwner = None;
4174
Time wmSnTimestamp = 0;
4176
XSetWindowAttributes attr;
4177
Window currentWmSnOwner;
4179
static char data = 0;
4183
XVisualInfo *visinfo;
4184
Window rootReturn, parentReturn;
4186
unsigned int nchildren;
4188
XSetWindowAttributes attrib;
4190
dpy = priv->dpy = XOpenDisplay (name);
4193
compLogMessage ("core", CompLogLevelFatal,
4194
"Couldn't open display %s", XDisplayName (name));
4198
// priv->connection = XGetXCBConnection (priv->dpy);
4200
snprintf (priv->displayString, 255, "DISPLAY=%s",
4201
DisplayString (dpy));
4204
XSynchronize (priv->dpy, true);
4207
Atoms::init (priv->dpy);
4209
XSetErrorHandler (errorHandler);
4211
priv->snDisplay = sn_display_new (dpy, NULL, NULL);
4212
if (!priv->snDisplay)
4217
if (!XSyncQueryExtension (dpy, &priv->syncEvent, &priv->syncError))
4219
compLogMessage ("core", CompLogLevelFatal,
4220
"No sync extension");
4224
priv->randrExtension = XRRQueryExtension (dpy, &priv->randrEvent,
4227
priv->shapeExtension = XShapeQueryExtension (dpy, &priv->shapeEvent,
4230
priv->xkbExtension = XkbQueryExtension (dpy, &xkbOpcode,
4231
&priv->xkbEvent, &priv->xkbError,
4233
if (priv->xkbExtension)
4235
XkbSelectEvents (dpy, XkbUseCoreKbd,
4236
XkbBellNotifyMask | XkbStateNotifyMask,
4241
compLogMessage ("core", CompLogLevelFatal,
4242
"No XKB extension");
4244
priv->xkbEvent = priv->xkbError = -1;
4247
priv->xineramaExtension = XineramaQueryExtension (dpy,
4248
&priv->xineramaEvent,
4249
&priv->xineramaError);
4251
priv->updateScreenInfo ();
4253
priv->escapeKeyCode = XKeysymToKeycode (dpy, XStringToKeysym ("Escape"));
4254
priv->returnKeyCode = XKeysymToKeycode (dpy, XStringToKeysym ("Return"));
4256
sprintf (buf, "WM_S%d", DefaultScreen (dpy));
4257
wmSnAtom = XInternAtom (dpy, buf, 0);
4259
currentWmSnOwner = XGetSelectionOwner (dpy, wmSnAtom);
4261
if (currentWmSnOwner != None)
4263
if (!replaceCurrentWm)
4265
compLogMessage ("core", CompLogLevelError,
4266
"Screen %d on display \"%s\" already "
4267
"has a window manager; try using the "
4268
"--replace option to replace the current "
4270
DefaultScreen (dpy), DisplayString (dpy));
4275
XSelectInput (dpy, currentWmSnOwner, StructureNotifyMask);
4278
root = XRootWindow (dpy, DefaultScreen (dpy));
4280
attr.override_redirect = true;
4281
attr.event_mask = PropertyChangeMask;
4284
XCreateWindow (dpy, root, -100, -100, 1, 1, 0,
4285
CopyFromParent, CopyFromParent,
4287
CWOverrideRedirect | CWEventMask,
4290
XChangeProperty (dpy, newWmSnOwner, Atoms::wmName, Atoms::utf8String, 8,
4291
PropModeReplace, (unsigned char *) PACKAGE,
4294
XWindowEvent (dpy, newWmSnOwner, PropertyChangeMask, &event);
4296
wmSnTimestamp = event.xproperty.time;
4298
XSetSelectionOwner (dpy, wmSnAtom, newWmSnOwner, wmSnTimestamp);
4300
if (XGetSelectionOwner (dpy, wmSnAtom) != newWmSnOwner)
4302
compLogMessage ("core", CompLogLevelError,
4303
"Could not acquire window manager "
4304
"selection on screen %d display \"%s\"",
4305
DefaultScreen (dpy), DisplayString (dpy));
4307
XDestroyWindow (dpy, newWmSnOwner);
4312
/* Send client message indicating that we are now the window manager */
4313
event.xclient.type = ClientMessage;
4314
event.xclient.window = root;
4315
event.xclient.message_type = Atoms::manager;
4316
event.xclient.format = 32;
4317
event.xclient.data.l[0] = wmSnTimestamp;
4318
event.xclient.data.l[1] = wmSnAtom;
4319
event.xclient.data.l[2] = 0;
4320
event.xclient.data.l[3] = 0;
4321
event.xclient.data.l[4] = 0;
4323
XSendEvent (dpy, root, FALSE, StructureNotifyMask, &event);
4325
/* Wait for old window manager to go away */
4326
if (currentWmSnOwner != None)
4329
XWindowEvent (dpy, currentWmSnOwner, StructureNotifyMask, &event);
4330
} while (event.type != DestroyNotify);
4333
modHandler->updateModifierMappings ();
4335
CompScreen::checkForError (dpy);
4339
XSelectInput (dpy, root,
4340
SubstructureRedirectMask |
4341
SubstructureNotifyMask |
4342
StructureNotifyMask |
4343
PropertyChangeMask |
4353
/* We need to register for EnterWindowMask |
4354
* ButtonPressMask | FocusChangeMask on other
4355
* root windows as well because focus happens
4356
* on a display level and we need to check
4357
* if the screen we are running on lost focus */
4359
for (unsigned int i = 0; i <= ScreenCount (dpy) - 1; i++)
4361
Window rt = XRootWindow (dpy, i);
4366
XSelectInput (dpy, rt,
4368
SubstructureNotifyMask);
4371
if (CompScreen::checkForError (dpy))
4373
compLogMessage ("core", CompLogLevelError,
4374
"Another window manager is "
4375
"already running on screen: %d", DefaultScreen (dpy));
4377
XUngrabServer (dpy);
4381
/* We only care about windows we're not going to
4382
* get a CreateNotify for later, so query the tree
4383
* here, init plugin screens, and then init windows */
4385
XQueryTree (dpy, root,
4386
&rootReturn, &parentReturn,
4387
&children, &nchildren);
4389
for (i = 0; i < SCREEN_EDGE_NUM; i++)
4391
priv->screenEdge[i].id = None;
4392
priv->screenEdge[i].count = 0;
4395
priv->screenNum = DefaultScreen (dpy);
4396
priv->colormap = DefaultColormap (dpy, priv->screenNum);
4399
priv->snContext = sn_monitor_context_new (priv->snDisplay, priv->screenNum,
4400
compScreenSnEvent, this, NULL);
4402
priv->wmSnSelectionWindow = newWmSnOwner;
4403
priv->wmSnAtom = wmSnAtom;
4404
priv->wmSnTimestamp = wmSnTimestamp;
4406
if (!XGetWindowAttributes (dpy, priv->root, &priv->attrib))
4409
priv->workArea.setWidth (priv->attrib.width);
4410
priv->workArea.setHeight (priv->attrib.height);
4412
priv->grabWindow = None;
4414
templ.visualid = XVisualIDFromVisual (priv->attrib.visual);
4416
visinfo = XGetVisualInfo (dpy, VisualIDMask, &templ, &nvisinfo);
4419
compLogMessage ("core", CompLogLevelFatal,
4420
"Couldn't get visual info for default visual");
4424
black.red = black.green = black.blue = 0;
4426
if (!XAllocColor (dpy, priv->colormap, &black))
4428
compLogMessage ("core", CompLogLevelFatal,
4429
"Couldn't allocate color");
4434
bitmap = XCreateBitmapFromData (dpy, priv->root, &data, 1, 1);
4437
compLogMessage ("core", CompLogLevelFatal,
4438
"Couldn't create bitmap");
4443
priv->invisibleCursor = XCreatePixmapCursor (dpy, bitmap, bitmap,
4444
&black, &black, 0, 0);
4445
if (!priv->invisibleCursor)
4447
compLogMessage ("core", CompLogLevelFatal,
4448
"Couldn't create invisible cursor");
4453
XFreePixmap (dpy, bitmap);
4454
XFreeColors (dpy, priv->colormap, &black.pixel, 1, 0);
4458
priv->reshape (priv->attrib.width, priv->attrib.height);
4460
priv->detectOutputDevices ();
4461
priv->updateOutputDevices ();
4463
priv->getDesktopHints ();
4465
attrib.override_redirect = 1;
4466
attrib.event_mask = PropertyChangeMask;
4468
priv->grabWindow = XCreateWindow (dpy, priv->root, -100, -100, 1, 1, 0,
4469
CopyFromParent, InputOnly, CopyFromParent,
4470
CWOverrideRedirect | CWEventMask,
4472
XMapWindow (dpy, priv->grabWindow);
4474
for (i = 0; i < SCREEN_EDGE_NUM; i++)
4476
long xdndVersion = 3;
4478
priv->screenEdge[i].id = XCreateWindow (dpy, priv->root,
4479
-100, -100, 1, 1, 0,
4480
CopyFromParent, InputOnly,
4485
XChangeProperty (dpy, priv->screenEdge[i].id, Atoms::xdndAware,
4486
XA_ATOM, 32, PropModeReplace,
4487
(unsigned char *) &xdndVersion, 1);
4489
XSelectInput (dpy, priv->screenEdge[i].id,
4497
priv->updateScreenEdges ();
4499
priv->setDesktopHints ();
4500
priv->setSupportingWmCheck ();
4501
updateSupportedWmHints ();
4503
priv->normalCursor = XCreateFontCursor (dpy, XC_left_ptr);
4504
priv->busyCursor = XCreateFontCursor (dpy, XC_watch);
4506
XDefineCursor (dpy, priv->root, priv->normalCursor);
4508
XUngrabServer (dpy);
4510
priv->setAudibleBell (priv->optionGetAudibleBell ());
4512
priv->pingTimer.setTimes (priv->optionGetPingDelay (),
4513
priv->optionGetPingDelay () + 500);
4515
priv->pingTimer.start ();
4517
priv->addScreenActions ();
4519
priv->initialized = true;
4521
/* TODO: Bailout properly when screenInitPlugins fails
4522
* TODO: It would be nicer if this line could mean
4523
* "init all the screens", but unfortunately it only inits
4524
* plugins loaded on the command line screen's and then
4525
* we need to call updatePlugins () to init the remaining
4526
* screens from option changes */
4527
assert (CompPlugin::screenInitPlugins (this));
4529
/* The active plugins list might have been changed - load any
4533
/* Start initializing windows here */
4535
for (unsigned int i = 0; i < nchildren; i++)
4537
CoreWindow *cw = new CoreWindow (children[i]);
4541
cw->manage (i ? children[i - 1] : 0);
4546
/* enforce restack on all windows */
4547
for (CompWindowList::reverse_iterator rit = priv->windows.rbegin ();
4548
rit != priv->windows.rend (); rit++)
4549
children[i] = (*rit)->id ();
4551
XRestackWindows (dpy, children, i);
4555
foreach (CompWindow *w, priv->windows)
4557
if (w->isViewable ())
4558
w->priv->activeNum = priv->activeNum++;
4561
priv->vpSize.setWidth (priv->optionGetHsize ());
4562
priv->vpSize.setHeight (priv->optionGetVsize ());
4564
XGetInputFocus (dpy, &focus, &revertTo);
4566
/* move input focus to root window so that we get a FocusIn event when
4567
moving it to the default window */
4568
XSetInputFocus (dpy, priv->root, RevertToPointerRoot, CurrentTime);
4570
if (focus == None || focus == PointerRoot)
4572
focusDefaultWindow ();
4578
w = findWindow (focus);
4580
w->moveInputFocusTo ();
4582
focusDefaultWindow ();
4588
CompScreen::~CompScreen ()
4592
priv->removeAllSequences ();
4594
while (!priv->windows.empty ())
4595
delete priv->windows.front ();
4597
while ((p = CompPlugin::pop ()))
4598
CompPlugin::unload (p);
4600
XUngrabKey (priv->dpy, AnyKey, AnyModifier, priv->root);
4602
priv->initialized = false;
4604
for (int i = 0; i < SCREEN_EDGE_NUM; i++)
4605
XDestroyWindow (priv->dpy, priv->screenEdge[i].id);
4607
XDestroyWindow (priv->dpy, priv->grabWindow);
4609
if (priv->defaultIcon)
4610
delete priv->defaultIcon;
4612
XFreeCursor (priv->dpy, priv->invisibleCursor);
4614
if (priv->desktopHintData)
4615
free (priv->desktopHintData);
4617
if (priv->snContext)
4618
sn_monitor_context_unref (priv->snContext);
4620
if (priv->snDisplay)
4621
sn_display_unref (priv->snDisplay);
4623
XSync (priv->dpy, False);
4624
XCloseDisplay (priv->dpy);
4631
PrivateScreen::PrivateScreen (CompScreen *screen) :
4634
lastFileWatchHandle (1),
4636
lastWatchFdHandle (1),
4642
autoRaiseWindow (0),
4645
dirtyPluginList (true),
4654
desktopWindowCount (0),
4658
currentOutputDev (0),
4659
hasOverlappingOutputs (false),
4662
startupSequences (0),
4663
startupSequenceTimer (),
4670
pendingDestroys (0),
4671
showingDesktopMask (0),
4672
desktopHintData (0),
4673
desktopHintSize (0),
4676
gettimeofday (&lastTimeout, 0);
4678
pingTimer.setCallback (
4679
boost::bind (&PrivateScreen::handlePingTimeout, this));
4681
startupSequenceTimer.setCallback (
4682
boost::bind (&PrivateScreen::handleStartupSequenceTimeout, this));
4683
startupSequenceTimer.setTimes (1000, 1500);
4685
optionSetCloseWindowKeyInitiate (CompScreen::closeWin);
4686
optionSetCloseWindowButtonInitiate (CompScreen::closeWin);
4687
optionSetRaiseWindowKeyInitiate (CompScreen::raiseWin);
4688
optionSetRaiseWindowButtonInitiate (CompScreen::raiseWin);
4689
optionSetLowerWindowKeyInitiate (CompScreen::lowerWin);
4690
optionSetLowerWindowButtonInitiate (CompScreen::lowerWin);
4692
optionSetUnmaximizeWindowKeyInitiate (CompScreen::unmaximizeWin);
4694
optionSetMinimizeWindowKeyInitiate (CompScreen::minimizeWin);
4695
optionSetMinimizeWindowButtonInitiate (CompScreen::minimizeWin);
4696
optionSetMaximizeWindowKeyInitiate (CompScreen::maximizeWin);
4697
optionSetMaximizeWindowHorizontallyKeyInitiate (
4698
CompScreen::maximizeWinHorizontally);
4699
optionSetMaximizeWindowVerticallyKeyInitiate (
4700
CompScreen::maximizeWinVertically);
4702
optionSetWindowMenuKeyInitiate (CompScreen::windowMenu);
4703
optionSetWindowMenuButtonInitiate (CompScreen::windowMenu);
4705
optionSetShowDesktopKeyInitiate (CompScreen::showDesktop);
4706
optionSetShowDesktopEdgeInitiate (CompScreen::showDesktop);
4708
optionSetToggleWindowMaximizedKeyInitiate (CompScreen::toggleWinMaximized);
4709
optionSetToggleWindowMaximizedButtonInitiate (CompScreen::toggleWinMaximized);
4711
optionSetToggleWindowMaximizedHorizontallyKeyInitiate (
4712
CompScreen::toggleWinMaximizedHorizontally);
4713
optionSetToggleWindowMaximizedVerticallyKeyInitiate (
4714
CompScreen::toggleWinMaximizedVertically);
4716
optionSetToggleWindowShadedKeyInitiate (CompScreen::shadeWin);
4719
PrivateScreen::~PrivateScreen ()