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 SPECIAL, 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>
27
# include "../config.h"
35
#include <sys/types.h>
39
#include <X11/Xatom.h>
40
#include <X11/extensions/Xrandr.h>
41
#include <X11/cursorfont.h>
45
#define DETECT_REFRESH_RATE_DEFAULT TRUE
47
#define SCREEN_SIZE_DEFAULT 4
48
#define SCREEN_SIZE_MIN 4
49
#define SCREEN_SIZE_MAX 32
51
#define CLOSE_WINDOW_KEY_DEFAULT "F4"
52
#define CLOSE_WINDOW_MODIFIERS_DEFAULT (CompPressMask | CompAltMask)
54
#define MAIN_MENU_KEY_DEFAULT "F1"
55
#define MAIN_MENU_MODIFIERS_DEFAULT (CompPressMask | CompAltMask)
57
#define RUN_DIALOG_KEY_DEFAULT "F2"
58
#define RUN_DIALOG_MODIFIERS_DEFAULT (CompPressMask | CompAltMask)
60
#define NUM_OPTIONS(s) (sizeof ((s)->opt) / sizeof (CompOption))
63
reallocScreenPrivate (int size,
66
CompDisplay *d = (CompDisplay *) closure;
70
for (s = d->screens; s; s = s->next)
72
privates = realloc (s->privates, size * sizeof (CompPrivate));
76
s->privates = (CompPrivate *) privates;
83
allocateScreenPrivateIndex (CompDisplay *display)
85
return allocatePrivateIndex (&display->screenPrivateLen,
86
&display->screenPrivateIndices,
92
freeScreenPrivateIndex (CompDisplay *display,
95
freePrivateIndex (display->screenPrivateLen,
96
display->screenPrivateIndices,
101
setVirtualScreenSize (CompScreen *screen,
104
unsigned long data[2];
106
data[0] = screen->width * size;
107
data[1] = screen->height;
109
XChangeProperty (screen->display->display, screen->root,
110
screen->display->desktopGeometryAtom,
111
XA_CARDINAL, 32, PropModeReplace,
112
(unsigned char *) data, 2);
118
compGetScreenOptions (CompScreen *screen,
121
*count = NUM_OPTIONS (screen);
126
setScreenOption (CompScreen *screen,
128
CompOptionValue *value)
133
o = compFindOption (screen->opt, NUM_OPTIONS (screen), name, &index);
138
case COMP_SCREEN_OPTION_DETECT_REFRESH_RATE:
139
if (compSetBoolOption (o, value))
142
case COMP_SCREEN_OPTION_REFRESH_RATE:
143
if (screen->opt[COMP_SCREEN_OPTION_DETECT_REFRESH_RATE].value.b)
146
if (compSetIntOption (o, value))
148
screen->redrawTime = 1000 / o->value.i;
149
screen->optimalRedrawTime = screen->redrawTime;
153
case COMP_SCREEN_OPTION_SIZE:
154
if (compSetIntOption (o, value))
156
if (o->value.i * screen->width > MAXSHORT)
159
setVirtualScreenSize (screen, o->value.i);
163
case COMP_SCREEN_OPTION_COMMAND0:
164
case COMP_SCREEN_OPTION_COMMAND1:
165
if (compSetStringOption (o, value))
168
case COMP_SCREEN_OPTION_CLOSE_WINDOW:
169
case COMP_SCREEN_OPTION_MAIN_MENU:
170
case COMP_SCREEN_OPTION_RUN_DIALOG:
171
case COMP_SCREEN_OPTION_RUN_COMMAND0:
172
case COMP_SCREEN_OPTION_RUN_COMMAND1:
173
if (addScreenBinding (screen, &value->bind))
175
removeScreenBinding (screen, &o->value.bind);
177
if (compSetBindingOption (o, value))
188
setScreenOptionForPlugin (CompScreen *screen,
191
CompOptionValue *value)
195
p = findActivePlugin (plugin);
196
if (p && p->vTable->setScreenOption)
197
return (*p->vTable->setScreenOption) (screen, name, value);
203
compScreenInitOptions (CompScreen *screen)
207
o = &screen->opt[COMP_SCREEN_OPTION_DETECT_REFRESH_RATE];
208
o->name = "detect_refresh_rate";
209
o->shortDesc = "Detect Refresh Rate";
210
o->longDesc = "Automatic detection of refresh rate";
211
o->type = CompOptionTypeBool;
212
o->value.b = DETECT_REFRESH_RATE_DEFAULT;
214
o = &screen->opt[COMP_SCREEN_OPTION_REFRESH_RATE];
215
o->name = "refresh_rate";
216
o->shortDesc = "Refresh Rate";
217
o->longDesc = "The rate at which the screen is redrawn (times/second)";
218
o->type = CompOptionTypeInt;
219
o->value.i = defaultRefreshRate;
223
o = &screen->opt[COMP_SCREEN_OPTION_SIZE];
225
o->shortDesc = "Virtual Size";
226
o->longDesc = "Screen size multiplier for virtual size";
227
o->type = CompOptionTypeInt;
228
o->value.i = SCREEN_SIZE_DEFAULT;
229
o->rest.i.min = SCREEN_SIZE_MIN;
230
o->rest.i.max = SCREEN_SIZE_MAX;
232
o = &screen->opt[COMP_SCREEN_OPTION_CLOSE_WINDOW];
233
o->name = "close_window";
234
o->shortDesc = "Close Window";
235
o->longDesc = "Close active window";
236
o->type = CompOptionTypeBinding;
237
o->value.bind.type = CompBindingTypeKey;
238
o->value.bind.u.key.modifiers = CLOSE_WINDOW_MODIFIERS_DEFAULT;
239
o->value.bind.u.key.keycode =
240
XKeysymToKeycode (screen->display->display,
241
XStringToKeysym (CLOSE_WINDOW_KEY_DEFAULT));
243
o = &screen->opt[COMP_SCREEN_OPTION_MAIN_MENU];
244
o->name = "main_menu";
245
o->shortDesc = "Main Menu";
246
o->longDesc = "Open main menu";
247
o->type = CompOptionTypeBinding;
248
o->value.bind.type = CompBindingTypeKey;
249
o->value.bind.u.key.modifiers = MAIN_MENU_MODIFIERS_DEFAULT;
250
o->value.bind.u.key.keycode =
251
XKeysymToKeycode (screen->display->display,
252
XStringToKeysym (MAIN_MENU_KEY_DEFAULT));
254
o = &screen->opt[COMP_SCREEN_OPTION_RUN_DIALOG];
256
o->shortDesc = "Run";
257
o->longDesc = "Run application";
258
o->type = CompOptionTypeBinding;
259
o->value.bind.type = CompBindingTypeKey;
260
o->value.bind.u.key.modifiers = RUN_DIALOG_MODIFIERS_DEFAULT;
261
o->value.bind.u.key.keycode =
262
XKeysymToKeycode (screen->display->display,
263
XStringToKeysym (RUN_DIALOG_KEY_DEFAULT));
265
o = &screen->opt[COMP_SCREEN_OPTION_COMMAND0];
266
o->name = "command0";
267
o->shortDesc = "Command line";
268
o->longDesc = "Command line to be executed in shell";
269
o->type = CompOptionTypeString;
270
o->value.s = strdup ("");
271
o->rest.s.string = NULL;
272
o->rest.s.nString = 0;
274
o = &screen->opt[COMP_SCREEN_OPTION_RUN_COMMAND0];
275
o->name = "run_command0";
276
o->shortDesc = "Run command";
277
o->longDesc = "Run shell command";
278
o->type = CompOptionTypeBinding;
279
o->value.bind.type = CompBindingTypeKey;
280
o->value.bind.u.key.modifiers = 0;
281
o->value.bind.u.key.keycode = 0;
283
o = &screen->opt[COMP_SCREEN_OPTION_COMMAND1];
284
o->name = "command1";
285
o->shortDesc = "Command line";
286
o->longDesc = "Command line to be executed in shell";
287
o->type = CompOptionTypeString;
288
o->value.s = strdup ("");
289
o->rest.s.string = NULL;
290
o->rest.s.nString = 0;
292
o = &screen->opt[COMP_SCREEN_OPTION_RUN_COMMAND1];
293
o->name = "run_command1";
294
o->shortDesc = "Run command";
295
o->longDesc = "Run shell command";
296
o->type = CompOptionTypeBinding;
297
o->value.bind.type = CompBindingTypeKey;
298
o->value.bind.u.key.modifiers = 0;
299
o->value.bind.u.key.keycode = 0;
303
initPluginForScreen (CompPlugin *p,
306
if (p->vTable->initScreen)
307
return (*p->vTable->initScreen) (p, s);
313
finiPluginForScreen (CompPlugin *p,
316
if (p->vTable->finiScreen)
317
(*p->vTable->finiScreen) (p, s);
321
updateStartupFeedback (CompScreen *s)
323
if (s->startupSequences)
324
XDefineCursor (s->display->display, s->root, s->busyCursor);
326
XDefineCursor (s->display->display, s->root, s->normalCursor);
329
#define STARTUP_TIMEOUT_DELAY 15000
332
startupSequenceTimeout (void *data)
334
CompScreen *screen = data;
335
CompStartupSequence *s;
336
struct timeval now, active;
339
gettimeofday (&now, NULL);
341
for (s = screen->startupSequences; s; s = s->next)
343
sn_startup_sequence_get_last_active_time (s->sequence,
347
elapsed = ((((double) now.tv_sec - active.tv_sec) * 1000000.0 +
348
(now.tv_usec - active.tv_usec))) / 1000.0;
350
if (elapsed > STARTUP_TIMEOUT_DELAY)
351
sn_startup_sequence_complete (s->sequence);
358
addSequence (CompScreen *screen,
359
SnStartupSequence *sequence)
361
CompStartupSequence *s;
363
s = malloc (sizeof (CompStartupSequence));
367
sn_startup_sequence_ref (sequence);
369
s->next = screen->startupSequences;
370
s->sequence = sequence;
372
screen->startupSequences = s;
374
if (!screen->startupSequenceTimeoutHandle)
375
compAddTimeout (1000,
376
startupSequenceTimeout,
379
updateStartupFeedback (screen);
383
removeSequence (CompScreen *screen,
384
SnStartupSequence *sequence)
386
CompStartupSequence *s, *p = NULL;
388
for (s = screen->startupSequences; s; s = s->next)
390
if (s->sequence == sequence)
399
sn_startup_sequence_unref (sequence);
404
screen->startupSequences = NULL;
408
if (!screen->startupSequences && screen->startupSequenceTimeoutHandle)
410
compRemoveTimeout (screen->startupSequenceTimeoutHandle);
411
screen->startupSequenceTimeoutHandle = 0;
414
updateStartupFeedback (screen);
418
compScreenSnEvent (SnMonitorEvent *event,
421
CompScreen *screen = userData;
422
SnStartupSequence *sequence;
424
sequence = sn_monitor_event_get_startup_sequence (event);
426
switch (sn_monitor_event_get_type (event)) {
427
case SN_MONITOR_EVENT_INITIATED:
428
addSequence (screen, sequence);
430
case SN_MONITOR_EVENT_COMPLETED:
431
removeSequence (screen, sn_monitor_event_get_startup_sequence (event));
433
case SN_MONITOR_EVENT_CHANGED:
434
case SN_MONITOR_EVENT_CANCELED:
440
frustum (GLfloat left,
447
GLfloat x, y, a, b, c, d;
450
x = (2.0 * nearval) / (right - left);
451
y = (2.0 * nearval) / (top - bottom);
452
a = (right + left) / (right - left);
453
b = (top + bottom) / (top - bottom);
454
c = -(farval + nearval) / ( farval - nearval);
455
d = -(2.0 * farval * nearval) / (farval - nearval);
457
#define M(row,col) m[col*4+row]
458
M(0,0) = x; M(0,1) = 0.0F; M(0,2) = a; M(0,3) = 0.0F;
459
M(1,0) = 0.0F; M(1,1) = y; M(1,2) = b; M(1,3) = 0.0F;
460
M(2,0) = 0.0F; M(2,1) = 0.0F; M(2,2) = c; M(2,3) = d;
461
M(3,0) = 0.0F; M(3,1) = 0.0F; M(3,2) = -1.0F; M(3,3) = 0.0F;
468
perspective (GLfloat fovy,
473
GLfloat xmin, xmax, ymin, ymax;
475
ymax = zNear * tan (fovy * M_PI / 360.0);
477
xmin = ymin * aspect;
478
xmax = ymax * aspect;
480
frustum (xmin, xmax, ymin, ymax, zNear, zFar);
484
reshape (CompScreen *s,
491
glMatrixMode (GL_PROJECTION);
493
glMatrixMode (GL_MODELVIEW);
496
glViewport (-1, -1, 2, 2);
497
glRasterPos2f (0, 0);
499
s->rasterX = s->rasterY = 0;
501
glViewport (0, 0, w, h);
502
glMatrixMode (GL_PROJECTION);
504
perspective (60.0f, 1.0f, 0.1f, 100.0f);
505
glMatrixMode (GL_MODELVIEW);
507
s->region.rects = &s->region.extents;
508
s->region.numRects = 1;
509
s->region.extents.x1 = 0;
510
s->region.extents.y1 = 0;
511
s->region.extents.x2 = w;
512
s->region.extents.y2 = h;
515
updateWorkareaForScreen (s);
519
configureScreen (CompScreen *s,
522
if (s->attrib.width != ce->width ||
523
s->attrib.height != ce->height)
525
s->attrib.width = ce->width;
526
s->attrib.height = ce->height;
528
reshape (s, ce->width, ce->height);
535
getProcAddress (CompScreen *s,
538
static void *dlhand = NULL;
539
FuncPtr funcPtr = NULL;
541
if (s->getProcAddress)
542
funcPtr = s->getProcAddress ((GLubyte *) name);
547
dlhand = dlopen (NULL, RTLD_LAZY);
552
funcPtr = (FuncPtr) dlsym (dlhand, name);
553
if (dlerror () != NULL)
562
updateScreenBackground (CompScreen *screen,
563
CompTexture *texture)
565
Display *dpy = screen->display->display;
566
Atom pixmapAtom, actualType;
567
int actualFormat, i, status;
568
unsigned int width = 1, height = 1, depth = 0;
569
unsigned long nItems;
570
unsigned long bytesAfter;
574
pixmapAtom = XInternAtom (dpy, "PIXMAP", FALSE);
576
for (i = 0; pixmap == 0 && i < 2; i++)
578
status = XGetWindowProperty (dpy, screen->root,
579
screen->display->xBackgroundAtom[i],
580
0, 4, FALSE, AnyPropertyType,
581
&actualType, &actualFormat, &nItems,
584
if (status == Success && nItems && prop)
586
if (actualType == pixmapAtom &&
587
actualFormat == 32 &&
592
memcpy (&p, prop, 4);
600
if (XGetGeometry (dpy, p, &w, &i, &i,
601
&width, &height, &ui, &depth))
603
if (depth == screen->attrib.depth)
613
if (!testMode && pixmap)
615
if (pixmap == texture->pixmap)
618
finiTexture (screen, texture);
619
initTexture (screen, texture);
621
if (!bindPixmapToTexture (screen, texture, pixmap,
622
width, height, depth))
624
fprintf (stderr, "%s: Couldn't bind background pixmap 0x%x to "
625
"texture\n", programName, (int) pixmap);
630
finiTexture (screen, texture);
631
initTexture (screen, texture);
635
readImageToTexture (screen, texture, backgroundImage, &width, &height);
637
if (texture->target == GL_TEXTURE_2D)
639
glBindTexture (texture->target, texture->name);
640
glTexParameteri (texture->target, GL_TEXTURE_WRAP_S, GL_REPEAT);
641
glTexParameteri (texture->target, GL_TEXTURE_WRAP_T, GL_REPEAT);
642
glBindTexture (texture->target, 0);
647
detectRefreshRateOfScreen (CompScreen *s)
649
if (s->opt[COMP_SCREEN_OPTION_DETECT_REFRESH_RATE].value.b)
651
XRRScreenConfiguration *config;
653
CompOptionValue value;
655
config = XRRGetScreenInfo (s->display->display, s->root);
656
value.i = (int) XRRConfigCurrentRate (config);
658
XRRFreeScreenConfigInfo (config);
660
name = s->opt[COMP_SCREEN_OPTION_REFRESH_RATE].name;
662
s->opt[COMP_SCREEN_OPTION_DETECT_REFRESH_RATE].value.b = FALSE;
663
(*s->setScreenOption) (s, name, &value);
664
s->opt[COMP_SCREEN_OPTION_DETECT_REFRESH_RATE].value.b = TRUE;
669
setSupportingWmCheck (CompScreen *s)
671
CompDisplay *d = s->display;
673
XChangeProperty (d->display, s->grabWindow, d->supportingWmCheckAtom,
674
XA_WINDOW, 32, PropModeReplace,
675
(unsigned char *) &s->grabWindow, 1);
677
XChangeProperty (d->display, s->grabWindow, d->wmNameAtom,
678
d->utf8StringAtom, 8, PropModeReplace,
679
(unsigned char *) PACKAGE, strlen (PACKAGE));
680
XChangeProperty (d->display, s->grabWindow, d->winStateAtom,
681
XA_ATOM, 32, PropModeReplace,
682
(unsigned char *) &d->winStateSkipTaskbarAtom, 1);
683
XChangeProperty (d->display, s->grabWindow, d->winStateAtom,
684
XA_ATOM, 32, PropModeAppend,
685
(unsigned char *) &d->winStateSkipPagerAtom, 1);
686
XChangeProperty (d->display, s->grabWindow, d->winStateAtom,
687
XA_ATOM, 32, PropModeAppend,
688
(unsigned char *) &d->winStateHiddenAtom, 1);
690
XChangeProperty (d->display, s->root, d->supportingWmCheckAtom,
691
XA_WINDOW, 32, PropModeReplace,
692
(unsigned char *) &s->grabWindow, 1);
696
setSupported (CompScreen *s)
698
CompDisplay *d = s->display;
702
data[i++] = d->supportedAtom;
703
data[i++] = d->supportingWmCheckAtom;
705
data[i++] = d->utf8StringAtom;
707
data[i++] = d->clientListAtom;
708
data[i++] = d->clientListStackingAtom;
710
data[i++] = d->winActiveAtom;
712
data[i++] = d->desktopViewportAtom;
713
data[i++] = d->desktopGeometryAtom;
714
data[i++] = d->currentDesktopAtom;
715
data[i++] = d->numberOfDesktopsAtom;
716
data[i++] = d->showingDesktopAtom;
718
data[i++] = d->workareaAtom;
720
data[i++] = d->wmNameAtom;
722
data[i++] = d->wmVisibleNameAtom;
725
data[i++] = d->wmStrutAtom;
726
data[i++] = d->wmStrutPartialAtom;
729
data[i++] = d->wmPidAtom;
730
data[i++] = d->wmUserTimeAtom;
733
data[i++] = d->frameExtentsAtom;
734
data[i++] = d->frameWindowAtom;
736
data[i++] = d->winStateModalAtom;
737
data[i++] = d->winStateStickyAtom;
738
data[i++] = d->winStateMaximizedVertAtom;
739
data[i++] = d->winStateMaximizedHorzAtom;
740
data[i++] = d->winStateShadedAtom;
741
data[i++] = d->winStateSkipTaskbarAtom;
742
data[i++] = d->winStateSkipPagerAtom;
743
data[i++] = d->winStateHiddenAtom;
744
data[i++] = d->winStateFullscreenAtom;
745
data[i++] = d->winStateAboveAtom;
746
data[i++] = d->winStateBelowAtom;
747
data[i++] = d->winStateDemandsAttentionAtom;
749
data[i++] = d->winOpacityAtom;
750
data[i++] = d->winBrightnessAtom;
752
if (s->canDoSaturated)
754
data[i++] = d->winSaturationAtom;
755
data[i++] = d->winStateDisplayModalAtom;
758
data[i++] = d->wmAllowedActionsAtom;
760
data[i++] = d->winActionMoveAtom;
761
data[i++] = d->winActionResizeAtom;
762
data[i++] = d->winActionStickAtom;
763
data[i++] = d->winActionMinimizeAtom;
764
data[i++] = d->winActionMaximizeHorzAtom;
765
data[i++] = d->winActionMaximizeVertAtom;
766
data[i++] = d->winActionFullscreenAtom;
767
data[i++] = d->winActionCloseAtom;
769
data[i++] = d->winTypeAtom;
770
data[i++] = d->winTypeDesktopAtom;
771
data[i++] = d->winTypeDockAtom;
772
data[i++] = d->winTypeToolbarAtom;
773
data[i++] = d->winTypeMenuAtom;
774
data[i++] = d->winTypeSplashAtom;
775
data[i++] = d->winTypeDialogAtom;
776
data[i++] = d->winTypeUtilAtom;
777
data[i++] = d->winTypeNormalAtom;
779
data[i++] = d->wmDeleteWindowAtom;
780
data[i++] = d->wmPingAtom;
782
data[i++] = d->wmMoveResizeAtom;
783
data[i++] = d->moveResizeWindowAtom;
785
XChangeProperty (d->display, s->root, d->supportedAtom, XA_ATOM, 32,
786
PropModeReplace, (unsigned char *) data, i);
790
setDesktopHints (CompScreen *s)
792
CompDisplay *d = s->display;
793
unsigned long data[2];
796
unsigned long n, left;
797
unsigned char *propData;
799
result = XGetWindowProperty (s->display->display, s->root,
800
d->desktopViewportAtom, 0L, 2L, FALSE,
801
XA_CARDINAL, &actual, &format,
802
&n, &left, &propData);
804
if (result == Success && n && propData)
808
memcpy (data, propData, sizeof (unsigned long));
810
if (data[0] / s->width < s->size - 1)
811
s->x = data[0] / s->width;
817
data[0] = s->x * s->width;
820
XChangeProperty (d->display, s->root, d->desktopViewportAtom,
821
XA_CARDINAL, 32, PropModeReplace,
822
(unsigned char *) data, 2);
824
data[0] = s->width * s->size;
827
XChangeProperty (d->display, s->root, d->desktopGeometryAtom,
828
XA_CARDINAL, 32, PropModeReplace,
829
(unsigned char *) data, 2);
833
XChangeProperty (d->display, s->root, d->numberOfDesktopsAtom,
834
XA_CARDINAL, 32, PropModeReplace,
835
(unsigned char *) data, 1);
839
XChangeProperty (d->display, s->root, d->currentDesktopAtom,
840
XA_CARDINAL, 32, PropModeReplace,
841
(unsigned char *) data, 1);
845
result = XGetWindowProperty (s->display->display, s->root,
846
d->showingDesktopAtom, 0L, 1L, FALSE,
847
XA_CARDINAL, &actual, &format,
848
&n, &left, &propData);
850
if (result == Success && n && propData)
852
memcpy (data, propData, sizeof (unsigned long));
856
enterShowDesktopMode (s);
859
XChangeProperty (d->display, s->root, d->showingDesktopAtom,
860
XA_CARDINAL, 32, PropModeReplace,
861
(unsigned char *) data, 1);
865
addScreen (CompDisplay *display,
867
Window wmSnSelectionWindow,
872
Display *dpy = display->display;
873
static char data = 0;
877
XVisualInfo *visinfo;
878
VisualID visualIDs[MAX_DEPTH + 1];
879
Window rootReturn, parentReturn;
881
unsigned int nchildren;
882
int defaultDepth, nvisinfo, value, i;
883
const char *glxExtensions, *glExtensions;
885
XSetWindowAttributes attrib;
888
s = malloc (sizeof (CompScreen));
892
s->windowPrivateIndices = 0;
893
s->windowPrivateLen = 0;
895
if (display->screenPrivateLen)
897
s->privates = malloc (display->screenPrivateLen *
898
sizeof (CompPrivate));
908
s->display = display;
910
compScreenInitOptions (s);
912
s->damage = XCreateRegion ();
928
s->pendingDestroys = 0;
933
s->screenNum = screenNum;
934
s->colormap = DefaultColormap (dpy, screenNum);
935
s->root = XRootWindow (dpy, screenNum);
942
s->snContext = sn_monitor_context_new (display->snDisplay,
944
compScreenSnEvent, s,
947
s->startupSequences = NULL;
948
s->startupSequenceTimeoutHandle = 0;
950
s->wmSnSelectionWindow = wmSnSelectionWindow;
951
s->wmSnAtom = wmSnAtom;
952
s->wmSnTimestamp = wmSnTimestamp;
957
XSizeHints *normalHints;
958
XClassHint *classHint;
967
visinfo = glXChooseVisual (dpy, screenNum, glx_attrib);
970
int glx_attrib2[] = {
977
visinfo = glXChooseVisual (dpy, screenNum, glx_attrib2);
980
fprintf (stderr, "%s: Couldn't find a double buffered "
981
"RGB visual.\n", programName);
986
attrib.colormap = XCreateColormap (dpy, s->root, visinfo->visual,
989
normalHints = XAllocSizeHints ();
990
normalHints->flags = 0;
993
normalHints->width = 800;
994
normalHints->height = 600;
996
classHint = XAllocClassHint ();
997
classHint->res_name = "compiz";
998
classHint->res_class = "Compiz";
1000
wmHints = XAllocWMHints ();
1001
wmHints->flags = InputHint;
1002
wmHints->input = TRUE;
1004
s->root = XCreateWindow (dpy, s->root, 0, 0,
1005
normalHints->width, normalHints->height, 0,
1006
visinfo->depth, InputOutput, visinfo->visual,
1007
CWColormap, &attrib);
1009
XSelectInput (dpy, s->root,
1010
SubstructureNotifyMask |
1016
XRRSelectInput (dpy, s->root, RRScreenChangeNotifyMask);
1018
XSetWMProtocols (dpy, s->root, &display->wmDeleteWindowAtom, 1);
1020
XmbSetWMProperties (dpy, s->root,
1021
"glxcompmgr - Test mode", "glxcompmgr",
1022
programArgv, programArgc,
1023
normalHints, wmHints, classHint);
1025
XMapWindow (dpy, s->root);
1029
XFree (normalHints);
1032
s->fake[0] = s->fake[1] = 0;
1034
s->escapeKeyCode = XKeysymToKeycode (display->display,
1035
XStringToKeysym ("Escape"));
1037
s->damageMask = COMP_SCREEN_DAMAGE_ALL_MASK;
1047
s->reverseWindows = 0;
1049
s->stencilRef = 0x1;
1054
s->showingDesktopMask = 0;
1056
gettimeofday (&s->lastRedraw, 0);
1058
s->setScreenOption = setScreenOption;
1059
s->setScreenOptionForPlugin = setScreenOptionForPlugin;
1061
s->initPluginForScreen = initPluginForScreen;
1062
s->finiPluginForScreen = finiPluginForScreen;
1064
s->preparePaintScreen = preparePaintScreen;
1065
s->donePaintScreen = donePaintScreen;
1066
s->paintScreen = paintScreen;
1067
s->paintTransformedScreen = paintTransformedScreen;
1068
s->paintBackground = paintBackground;
1069
s->paintWindow = paintWindow;
1070
s->addWindowGeometry = addWindowGeometry;
1071
s->drawWindowGeometry = drawWindowGeometry;
1072
s->damageWindowRect = damageWindowRect;
1073
s->focusWindow = focusWindow;
1074
s->setWindowScale = setWindowScale;
1076
s->windowResizeNotify = windowResizeNotify;
1077
s->windowMoveNotify = windowMoveNotify;
1078
s->windowGrabNotify = windowGrabNotify;
1079
s->windowUngrabNotify = windowUngrabNotify;
1081
s->getProcAddress = 0;
1083
if (!XGetWindowAttributes (dpy, s->root, &s->attrib))
1088
s->workArea.width = s->attrib.width;
1089
s->workArea.height = s->attrib.height;
1091
s->grabWindow = None;
1093
templ.visualid = XVisualIDFromVisual (s->attrib.visual);
1095
visinfo = XGetVisualInfo (dpy, VisualIDMask, &templ, &nvisinfo);
1098
fprintf (stderr, "%s: Couldn't get visual info for default visual\n",
1103
defaultDepth = visinfo->depth;
1105
black.red = black.green = black.blue = 0;
1107
if (!XAllocColor (dpy, s->colormap, &black))
1109
fprintf (stderr, "%s: Couldn't allocate color\n", programName);
1113
bitmap = XCreateBitmapFromData (dpy, s->root, &data, 1, 1);
1116
fprintf (stderr, "%s: Couldn't create bitmap\n", programName);
1120
s->invisibleCursor = XCreatePixmapCursor (dpy, bitmap, bitmap,
1121
&black, &black, 0, 0);
1122
if (!s->invisibleCursor)
1124
fprintf (stderr, "%s: Couldn't create invisible cursor\n",
1129
XFreePixmap (dpy, bitmap);
1130
XFreeColors (dpy, s->colormap, &black.pixel, 1, 0);
1132
glXGetConfig (dpy, visinfo, GLX_USE_GL, &value);
1135
fprintf (stderr, "%s: Root visual is not a GL visual\n",
1140
addScreenBinding (s, &s->opt[COMP_SCREEN_OPTION_CLOSE_WINDOW].value.bind);
1141
addScreenBinding (s, &s->opt[COMP_SCREEN_OPTION_MAIN_MENU].value.bind);
1142
addScreenBinding (s, &s->opt[COMP_SCREEN_OPTION_RUN_DIALOG].value.bind);
1144
glXGetConfig (dpy, visinfo, GLX_DOUBLEBUFFER, &value);
1148
"%s: Root visual is not a double buffered GL visual\n",
1153
s->ctx = glXCreateContext (dpy, visinfo, NULL, TRUE);
1156
fprintf (stderr, "%s: glXCreateContext failed\n", programName);
1162
/* we don't want to allocate back, stencil or depth buffers for pixmaps
1163
so lets see if we can find an approriate visual without these buffers */
1164
for (i = 0; i <= MAX_DEPTH; i++)
1166
int j, db, stencil, depth;
1176
visinfo = XGetVisualInfo (dpy, VisualDepthMask, &templ, &nvisinfo);
1177
for (j = 0; j < nvisinfo; j++)
1179
glXGetConfig (dpy, &visinfo[j], GLX_USE_GL, &value);
1183
glXGetConfig (dpy, &visinfo[j], GLX_DOUBLEBUFFER, &value);
1188
glXGetConfig (dpy, &visinfo[j], GLX_STENCIL_SIZE, &value);
1189
if (value > stencil)
1193
glXGetConfig (dpy, &visinfo[j], GLX_DEPTH_SIZE, &value);
1198
visualIDs[i] = visinfo[j].visualid;
1205
/* create contexts for supported depths */
1206
for (i = 0; i <= MAX_DEPTH; i++)
1208
templ.visualid = visualIDs[i];
1209
s->glxPixmapVisuals[i] = XGetVisualInfo (dpy,
1215
if (!s->glxPixmapVisuals[defaultDepth])
1217
fprintf (stderr, "%s: No GL visual for default depth, "
1218
"this isn't going to work.\n", programName);
1222
glXMakeCurrent (dpy, s->root, s->ctx);
1223
currentRoot = s->root;
1225
glxExtensions = glXQueryExtensionsString (s->display->display, screenNum);
1226
if (!testMode && !strstr (glxExtensions, "GLX_EXT_texture_from_pixmap"))
1228
fprintf (stderr, "%s: GLX_EXT_texture_from_pixmap is missing\n",
1233
s->getProcAddress = (GLXGetProcAddressProc)
1234
getProcAddress (s, "glXGetProcAddressARB");
1235
s->bindTexImage = (GLXBindTexImageProc)
1236
getProcAddress (s, "glXBindTexImageEXT");
1237
s->releaseTexImage = (GLXReleaseTexImageProc)
1238
getProcAddress (s, "glXReleaseTexImageEXT");
1239
s->queryDrawable = (GLXQueryDrawableProc)
1240
getProcAddress (s, "glXQueryDrawable");
1242
if (!testMode && !s->bindTexImage)
1244
fprintf (stderr, "%s: glXBindTexImageEXT is missing\n", programName);
1248
if (!testMode && !s->releaseTexImage)
1250
fprintf (stderr, "%s: glXReleaseTexImageEXT is missing\n",
1255
if (!testMode && !s->queryDrawable)
1257
fprintf (stderr, "%s: glXQueryDrawable is missing\n", programName);
1261
s->textureRectangle = 0;
1262
glExtensions = (const char *) glGetString (GL_EXTENSIONS);
1263
if (strstr (glExtensions, "GL_NV_texture_rectangle") ||
1264
strstr (glExtensions, "GL_EXT_texture_rectangle") ||
1265
strstr (glExtensions, "GL_ARB_texture_rectangle"))
1266
s->textureRectangle = 1;
1268
s->textureNonPowerOfTwo = 0;
1269
if (strstr (glExtensions, "GL_ARB_texture_non_power_of_two"))
1270
s->textureNonPowerOfTwo = 1;
1272
if (!(s->textureRectangle || s->textureNonPowerOfTwo))
1274
fprintf (stderr, "%s: Support for non power of two textures missing\n",
1279
s->textureEnvCombine = s->textureEnvCrossbar = 0;
1280
if (strstr (glExtensions, "GL_ARB_texture_env_combine"))
1282
s->textureEnvCombine = 1;
1284
/* XXX: GL_NV_texture_env_combine4 need special code but it seams to
1285
be working anyway for now... */
1286
if (strstr (glExtensions, "GL_ARB_texture_env_crossbar") ||
1287
strstr (glExtensions, "GL_NV_texture_env_combine4"))
1288
s->textureEnvCrossbar = 1;
1291
s->textureBorderClamp = 0;
1292
if (strstr (glExtensions, "GL_ARB_texture_border_clamp") ||
1293
strstr (glExtensions, "GL_SGIS_texture_border_clamp"))
1294
s->textureBorderClamp = 1;
1296
s->maxTextureUnits = 1;
1297
if (strstr (glExtensions, "GL_ARB_multitexture"))
1299
s->activeTexture = (GLActiveTextureProc)
1300
getProcAddress (s, "glActiveTexture");
1301
s->clientActiveTexture = (GLClientActiveTextureProc)
1302
getProcAddress (s, "glClientActiveTexture");
1304
if (s->activeTexture && s->clientActiveTexture)
1305
glGetIntegerv (GL_MAX_TEXTURE_UNITS_ARB, &s->maxTextureUnits);
1308
initTexture (s, &s->backgroundTexture);
1310
s->desktopWindowCount = 0;
1312
glGetIntegerv (GL_STENCIL_BITS, &stencilBits);
1315
fprintf (stderr, "%s: No stencil buffer. Clipping of transformed "
1316
"windows is not going to be correct when screen is "
1317
"transformed.\n", programName);
1320
glClearColor (0.0, 0.0, 0.0, 1.0);
1321
glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1322
glEnable (GL_CULL_FACE);
1323
glDisable (GL_BLEND);
1324
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1325
glColor4usv (defaultColor);
1326
glEnableClientState (GL_VERTEX_ARRAY);
1327
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
1329
s->canDoSaturated = s->canDoSlightlySaturated = FALSE;
1330
if (s->textureEnvCombine && s->maxTextureUnits >= 2)
1332
s->canDoSaturated = TRUE;
1333
if (s->textureEnvCrossbar && s->maxTextureUnits >= 4)
1334
s->canDoSlightlySaturated = TRUE;
1337
s->redrawTime = 1000 / defaultRefreshRate;
1338
s->optimalRedrawTime = s->redrawTime;
1340
reshape (s, s->attrib.width, s->attrib.height);
1342
s->next = display->screens;
1343
display->screens = s;
1345
screenInitPlugins (s);
1347
detectRefreshRateOfScreen (s);
1351
XQueryTree (dpy, s->root,
1352
&rootReturn, &parentReturn,
1353
&children, &nchildren);
1355
for (i = 0; i < nchildren; i++)
1356
addWindow (s, children[i], i ? children[i - 1] : 0);
1358
for (w = s->windows; w; w = w->next)
1360
if (w->attrib.map_state == IsViewable)
1362
w->activeNum = s->activeNum++;
1365
w->invisible = WINDOW_INVISIBLE (w);
1367
else if (w->state & CompWindowStateHiddenMask)
1373
XUngrabServer (dpy);
1377
attrib.override_redirect = 1;
1378
s->grabWindow = XCreateWindow (dpy, s->root, -100, -100, 1, 1, 0,
1379
CopyFromParent, InputOnly,
1380
CopyFromParent, CWOverrideRedirect,
1383
XMapWindow (dpy, s->grabWindow);
1387
s->fake[0] = XCreateWindow (dpy, s->root, 64, 32, 1, 1, 0,
1388
CopyFromParent, InputOutput,
1389
CopyFromParent, 0, NULL);
1391
s->fake[1] = XCreateWindow (dpy, s->root, 256, 256, 1, 1, 0,
1392
CopyFromParent, InputOutput,
1393
CopyFromParent, 0, NULL);
1396
setDesktopHints (s);
1397
setSupportingWmCheck (s);
1400
s->normalCursor = XCreateFontCursor (dpy, XC_left_ptr);
1401
s->busyCursor = XCreateFontCursor (dpy, XC_watch);
1403
XDefineCursor (dpy, s->root, s->normalCursor);
1409
damageScreenRegion (CompScreen *screen,
1412
if (screen->damageMask & COMP_SCREEN_DAMAGE_ALL_MASK)
1415
XUnionRegion (screen->damage, region, screen->damage);
1417
screen->damageMask |= COMP_SCREEN_DAMAGE_REGION_MASK;
1421
damageScreen (CompScreen *s)
1423
s->damageMask |= COMP_SCREEN_DAMAGE_ALL_MASK;
1424
s->damageMask &= ~COMP_SCREEN_DAMAGE_REGION_MASK;
1428
damagePendingOnScreen (CompScreen *s)
1430
s->damageMask |= COMP_SCREEN_DAMAGE_PENDING_MASK;
1434
forEachWindowOnScreen (CompScreen *screen,
1435
ForEachWindowProc proc,
1440
for (w = screen->windows; w; w = w->next)
1441
(*proc) (w, closure);
1445
findWindowAtScreen (CompScreen *s,
1448
if (lastFoundWindow && lastFoundWindow->id == id)
1450
return lastFoundWindow;
1456
for (w = s->windows; w; w = w->next)
1458
return (lastFoundWindow = w);
1465
findTopLevelWindowAtScreen (CompScreen *s,
1468
CompWindow *found = NULL;
1470
if (lastFoundWindow && lastFoundWindow->id == id)
1472
found = lastFoundWindow;
1478
for (w = s->windows; w; w = w->next)
1482
found = (lastFoundWindow = w);
1491
if (found->attrib.override_redirect)
1493
/* likely a frame window */
1494
if (found->attrib.class == InputOnly)
1498
for (w = s->windows; w; w = w->next)
1510
insertWindowIntoScreen (CompScreen *s,
1520
w->next = s->windows;
1522
s->windows->prev = w;
1527
for (p = s->windows; p; p = p->next)
1531
if (p->id == aboveId && p->mapNum)
1546
s->reverseWindows = w;
1555
s->reverseWindows = s->windows = w;
1556
w->prev = w->next = NULL;
1561
unhookWindowFromScreen (CompScreen *s,
1564
CompWindow *next, *prev;
1592
s->reverseWindows = prev;
1599
s->windows = s->reverseWindows = NULL;
1602
if (w == lastFoundWindow)
1603
lastFoundWindow = NULL;
1604
if (w == lastDamagedWindow)
1605
lastDamagedWindow = NULL;
1608
#define POINTER_GRAB_MASK (ButtonReleaseMask | \
1612
pushScreenGrab (CompScreen *s,
1615
if (s->maxGrab == 0)
1619
status = XGrabPointer (s->display->display, s->grabWindow, TRUE,
1621
GrabModeAsync, GrabModeAsync,
1625
if (status == GrabSuccess)
1627
status = XGrabKeyboard (s->display->display,
1628
s->grabWindow, TRUE,
1629
GrabModeAsync, GrabModeAsync,
1631
if (status != GrabSuccess)
1633
XUngrabPointer (s->display->display, CurrentTime);
1642
XChangeActivePointerGrab (s->display->display, POINTER_GRAB_MASK,
1643
cursor, CurrentTime);
1646
if (s->grabSize <= s->maxGrab)
1648
s->grabs = realloc (s->grabs, sizeof (CompGrab) * (s->maxGrab + 1));
1652
s->grabSize = s->maxGrab + 1;
1655
s->grabs[s->maxGrab].cursor = cursor;
1656
s->grabs[s->maxGrab].active = TRUE;
1664
removeScreenGrab (CompScreen *s,
1666
XPoint *restorePointer)
1671
if (index < 0 || index >= s->maxGrab)
1674
s->grabs[index].cursor = None;
1675
s->grabs[index].active = FALSE;
1677
for (maxGrab = s->maxGrab; maxGrab; maxGrab--)
1678
if (s->grabs[maxGrab - 1].active)
1681
if (maxGrab != s->maxGrab)
1685
XChangeActivePointerGrab (s->display->display,
1687
s->grabs[s->maxGrab - 1].cursor,
1693
XWarpPointer (s->display->display, None, s->root, 0, 0, 0, 0,
1694
restorePointer->x, restorePointer->y);
1696
XUngrabPointer (s->display->display, CurrentTime);
1697
XUngrabKeyboard (s->display->display, CurrentTime);
1699
s->maxGrab = maxGrab;
1704
addPassiveKeyGrab (CompScreen *s,
1705
CompKeyBinding *key)
1707
CompKeyGrab *keyGrab;
1708
unsigned int modifiers, mask, ignore;
1711
modifiers = key->modifiers & ~(CompPressMask | CompReleaseMask);
1712
if (modifiers == key->modifiers)
1715
for (i = 0; i < s->nKeyGrab; i++)
1717
if (key->keycode == s->keyGrab[i].keycode &&
1718
modifiers == s->keyGrab[i].modifiers)
1720
s->keyGrab[i].count++;
1725
keyGrab = realloc (s->keyGrab, sizeof (CompKeyGrab) * (s->nKeyGrab + 1));
1729
s->keyGrab = keyGrab;
1731
mask = virtualToRealModMask (s->display, modifiers);
1732
if (!(mask & CompNoMask))
1734
compCheckForError (s->display->display);
1736
for (ignore = 0; ignore <= s->display->ignoredModMask; ignore++)
1738
if (ignore & ~s->display->ignoredModMask)
1741
XGrabKey (s->display->display,
1750
if (compCheckForError (s->display->display))
1757
keysym = XKeycodeToKeysym (s->display->display,
1760
keyname = XKeysymToString (keysym);
1762
fprintf (stderr, "XGrabKey failed: %s 0x%x\n",
1763
keyname, modifiers);
1770
s->keyGrab[s->nKeyGrab].keycode = key->keycode;
1771
s->keyGrab[s->nKeyGrab].modifiers = modifiers;
1772
s->keyGrab[s->nKeyGrab].count = 1;
1780
removePassiveKeyGrab (CompScreen *s,
1781
CompKeyBinding *key)
1783
unsigned int modifiers, mask, ignore;
1786
modifiers = key->modifiers & ~(CompPressMask | CompReleaseMask);
1787
if (modifiers == key->modifiers)
1790
for (i = 0; i < s->nKeyGrab; i++)
1792
if (key->keycode == s->keyGrab[i].keycode &&
1793
modifiers == s->keyGrab[i].modifiers)
1795
s->keyGrab[i].count--;
1796
if (s->keyGrab[i].count)
1800
s->keyGrab = realloc (s->keyGrab,
1801
sizeof (CompKeyGrab) * s->nKeyGrab);
1803
mask = virtualToRealModMask (s->display, modifiers);
1804
if (!(mask & CompNoMask))
1806
for (ignore = 0; ignore <= s->display->ignoredModMask; ignore++)
1808
if (ignore & ~s->display->ignoredModMask)
1811
XUngrabKey (s->display->display,
1822
updatePassiveKeyGrabs (CompScreen *s)
1824
unsigned int mask, ignore;
1827
XUngrabKey (s->display->display, AnyKey, AnyModifier, s->root);
1829
for (i = 0; i < s->nKeyGrab; i++)
1831
mask = virtualToRealModMask (s->display, s->keyGrab[i].modifiers);
1832
if (!(mask & CompNoMask))
1834
for (ignore = 0; ignore <= s->display->ignoredModMask; ignore++)
1836
if (ignore & ~s->display->ignoredModMask)
1839
XGrabKey (s->display->display,
1840
s->keyGrab[i].keycode,
1852
addPassiveButtonGrab (CompScreen *s,
1853
CompButtonBinding *button)
1855
CompButtonGrab *buttonGrab;
1856
unsigned int modifiers;
1859
modifiers = button->modifiers & ~(CompPressMask | CompReleaseMask);
1860
if (modifiers == button->modifiers)
1863
for (i = 0; i < s->nButtonGrab; i++)
1865
if (button->button == s->buttonGrab[i].button &&
1866
modifiers == s->buttonGrab[i].modifiers)
1868
s->buttonGrab[i].count++;
1873
buttonGrab = realloc (s->buttonGrab,
1874
sizeof (CompButtonGrab) * (s->nButtonGrab + 1));
1878
s->buttonGrab = buttonGrab;
1880
s->buttonGrab[s->nButtonGrab].button = button->button;
1881
s->buttonGrab[s->nButtonGrab].modifiers = modifiers;
1882
s->buttonGrab[s->nButtonGrab].count = 1;
1890
removePassiveButtonGrab (CompScreen *s,
1891
CompButtonBinding *button)
1893
unsigned int modifiers;
1896
modifiers = button->modifiers & ~(CompPressMask | CompReleaseMask);
1897
if (modifiers == button->modifiers)
1900
for (i = 0; i < s->nButtonGrab; i++)
1902
if (button->button == s->buttonGrab[i].button &&
1903
modifiers == s->buttonGrab[i].modifiers)
1905
s->buttonGrab[i].count--;
1906
if (s->buttonGrab[i].count)
1910
s->buttonGrab = realloc (s->buttonGrab,
1911
sizeof (CompButtonGrab) * s->nButtonGrab);
1917
addScreenBinding (CompScreen *s,
1918
CompBinding *binding)
1920
if (binding->type == CompBindingTypeKey)
1921
return addPassiveKeyGrab (s, &binding->u.key);
1922
else if (binding->type == CompBindingTypeButton)
1923
return addPassiveButtonGrab (s, &binding->u.button);
1929
removeScreenBinding (CompScreen *s,
1930
CompBinding *binding)
1932
if (binding->type == CompBindingTypeKey)
1933
removePassiveKeyGrab (s, &binding->u.key);
1934
else if (binding->type == CompBindingTypeButton)
1935
removePassiveButtonGrab (s, &binding->u.button);
1939
updatePassiveGrabs (CompScreen *s)
1941
updatePassiveKeyGrabs (s);
1945
updateWorkareaForScreen (CompScreen *s)
1948
int leftStrut, rightStrut, topStrut, bottomStrut;
1949
XRectangle workArea;
1956
for (w = s->windows; w; w = w->next)
1958
if (w->attrib.map_state == IsUnmapped)
1963
if (w->struts->left.width > leftStrut)
1964
leftStrut = w->struts->left.width;
1966
if (w->struts->right.width > rightStrut)
1967
rightStrut = w->struts->right.width;
1969
if (w->struts->top.height > topStrut)
1970
topStrut = w->struts->top.height;
1972
if (w->struts->bottom.height > bottomStrut)
1973
bottomStrut = w->struts->bottom.height;
1977
#define MIN_SANE_AREA 100
1979
if ((leftStrut + rightStrut) > (s->width - MIN_SANE_AREA))
1981
leftStrut = (s->width - MIN_SANE_AREA) / 2;
1982
rightStrut = leftStrut;
1985
if ((topStrut + bottomStrut) > (s->height - MIN_SANE_AREA))
1987
topStrut = (s->height - MIN_SANE_AREA) / 2;
1988
bottomStrut = topStrut;
1991
workArea.x = leftStrut;
1992
workArea.y = topStrut;
1993
workArea.width = s->width - leftStrut - rightStrut;
1994
workArea.height = s->height - topStrut - bottomStrut;
1996
if (memcmp (&workArea, &s->workArea, sizeof (XRectangle)))
1998
unsigned long data[4];
2000
data[0] = workArea.x;
2001
data[1] = workArea.y;
2002
data[2] = workArea.width;
2003
data[3] = workArea.height;
2005
XChangeProperty (s->display->display, s->root,
2006
s->display->workareaAtom, XA_CARDINAL, 32,
2007
PropModeReplace, (unsigned char *) data, 4);
2009
s->workArea = workArea;
2014
isClientListWindow (CompWindow *w)
2016
if (w->attrib.override_redirect)
2019
if (w->attrib.map_state != IsViewable)
2021
if (!(w->state & CompWindowStateHiddenMask))
2025
if (w->type & CompWindowTypeNormalMask)
2032
countClientListWindow (CompWindow *w,
2035
if (isClientListWindow (w))
2037
int *num = (int *) closure;
2044
addClientListWindow (CompWindow *w,
2047
if (isClientListWindow (w))
2049
int *num = (int *) closure;
2051
w->screen->clientList[*num] = w;
2057
compareMappingOrder (const void *w1,
2060
return (*((CompWindow **) w1))->mapNum - (*((CompWindow **) w2))->mapNum;
2064
updateClientListForScreen (CompScreen *s)
2067
Window *clientListStacking;
2068
Bool updateClientList = FALSE;
2069
Bool updateClientListStacking = FALSE;
2072
forEachWindowOnScreen (s, countClientListWindow, (void *) &n);
2076
if (n != s->nClientList)
2078
free (s->clientList);
2080
s->clientList = NULL;
2083
XChangeProperty (s->display->display, s->root,
2084
s->display->clientListAtom,
2085
XA_WINDOW, 32, PropModeReplace,
2086
(unsigned char *) &s->grabWindow, 1);
2087
XChangeProperty (s->display->display, s->root,
2088
s->display->clientListStackingAtom,
2089
XA_WINDOW, 32, PropModeReplace,
2090
(unsigned char *) &s->grabWindow, 1);
2096
if (n != s->nClientList)
2100
list = realloc (s->clientList,
2101
(sizeof (CompWindow *) + sizeof (Window) * 2) * n);
2105
s->clientList = list;
2108
updateClientList = updateClientListStacking = TRUE;
2111
clientList = (Window *) (s->clientList + n);
2112
clientListStacking = clientList + n;
2115
forEachWindowOnScreen (s, addClientListWindow, (void *) &i);
2117
for (i = 0; i < n; i++)
2119
if (!updateClientListStacking)
2121
if (clientListStacking[i] != s->clientList[i]->id)
2122
updateClientListStacking = TRUE;
2125
clientListStacking[i] = s->clientList[i]->id;
2128
/* sort window list in mapping order */
2129
qsort (s->clientList, n, sizeof (CompWindow *), compareMappingOrder);
2131
for (i = 0; i < n; i++)
2133
if (!updateClientList)
2135
if (clientList[i] != s->clientList[i]->id)
2136
updateClientList = TRUE;
2139
clientList[i] = s->clientList[i]->id;
2142
if (updateClientList)
2143
XChangeProperty (s->display->display, s->root,
2144
s->display->clientListAtom,
2145
XA_WINDOW, 32, PropModeReplace,
2146
(unsigned char *) clientList, s->nClientList);
2148
if (updateClientListStacking)
2149
XChangeProperty (s->display->display, s->root,
2150
s->display->clientListStackingAtom,
2151
XA_WINDOW, 32, PropModeReplace,
2152
(unsigned char *) clientListStacking, s->nClientList);
2156
getActiveWindow (CompDisplay *display,
2161
unsigned long n, left;
2162
unsigned char *data;
2165
result = XGetWindowProperty (display->display, root,
2166
display->winActiveAtom, 0L, 1L, FALSE,
2167
XA_WINDOW, &actual, &format,
2170
if (result == Success && n && data)
2172
memcpy (&w, data, sizeof (Window));
2180
closeActiveWindow (CompScreen *s)
2184
w = findWindowAtDisplay (s->display, s->display->activeWindow);
2190
panelAction (CompScreen *s,
2195
ev.type = ClientMessage;
2196
ev.xclient.window = s->root;
2197
ev.xclient.message_type = s->display->panelActionAtom;
2198
ev.xclient.format = 32;
2199
ev.xclient.data.l[0] = panelAction;
2200
ev.xclient.data.l[1] = CurrentTime;
2201
ev.xclient.data.l[2] = 0;
2202
ev.xclient.data.l[3] = 0;
2203
ev.xclient.data.l[4] = 0;
2205
XUngrabPointer (s->display->display, CurrentTime);
2206
XUngrabKeyboard (s->display->display, CurrentTime);
2208
XSendEvent (s->display->display, s->root, FALSE, StructureNotifyMask, &ev);
2212
runCommand (CompScreen *s,
2213
const char *command)
2215
if (*command == '\0')
2221
putenv (s->display->displayString);
2222
execl ("/bin/sh", "/bin/sh", "-c", command, NULL);
2228
moveScreenViewport (CompScreen *s,
2233
tx = MOD (tx, s->size);
2239
int m, wx, vWidth = s->width * s->size;
2245
for (w = s->windows; w; w = w->next)
2247
if (w->attrib.map_state != IsViewable)
2250
if (w->attrib.override_redirect)
2253
if (w->type & (CompWindowTypeDesktopMask | CompWindowTypeDockMask))
2256
if (w->state & CompWindowStateStickyMask)
2259
m = w->attrib.x + tx;
2260
if (m - w->output.left < s->width - vWidth)
2262
else if (m + w->width + w->output.right > vWidth)
2267
if (w->saveMask & CWX)
2270
moveWindow (w, wx, 0, sync);
2273
syncWindowPosition (w);
2278
unsigned long data[2];
2280
data[0] = s->x * s->width;
2283
XChangeProperty (s->display->display, s->root,
2284
s->display->desktopViewportAtom,
2285
XA_CARDINAL, 32, PropModeReplace,
2286
(unsigned char *) data, 2);
2292
moveWindowToViewportPosition (CompWindow *w,
2296
int tx, vWidth = w->screen->width * w->screen->size;
2298
x += w->screen->x * w->screen->width;
2299
x = MOD (x, vWidth);
2300
x -= w->screen->x * w->screen->width;
2302
tx = x - w->attrib.x;
2307
if (w->attrib.map_state != IsViewable)
2310
if (w->attrib.override_redirect)
2313
if (w->type & (CompWindowTypeDesktopMask | CompWindowTypeDockMask))
2316
if (w->state & CompWindowStateStickyMask)
2319
m = w->attrib.x + tx;
2320
if (m - w->output.left < w->screen->width - vWidth)
2322
else if (m + w->width + w->output.right > vWidth)
2327
if (w->saveMask & CWX)
2330
moveWindow (w, wx, 0, sync);
2333
syncWindowPosition (w);
2338
addGroupToScreen (CompScreen *s,
2343
group = malloc (sizeof (CompGroup));
2347
group->next = s->groups;
2357
removeGroupFromScreen (CompScreen *s,
2364
if (group == s->groups)
2366
s->groups = group->next;
2372
for (g = s->groups; g; g = g->next)
2374
if (g->next == group)
2376
g->next = group->next;
2386
findGroupAtScreen (CompScreen *s,
2391
for (g = s->groups; g; g = g->next)
2399
applyStartupProperties (CompScreen *screen,
2402
CompStartupSequence *s = NULL;
2403
const char *startupId = window->startupId;
2405
printf ("Applying startup props to %d id \"%s\"\n",
2406
(int) window->id, window->startupId ? window->startupId : "(none)");
2410
const char *wmClass;
2412
for (s = screen->startupSequences; s; s = s->next)
2414
wmClass = sn_startup_sequence_get_wmclass (s->sequence);
2418
if ((window->resClass && strcmp (wmClass, window->resClass) == 0) ||
2419
(window->resName && strcmp (wmClass, window->resName) == 0))
2421
startupId = sn_startup_sequence_get_id (s->sequence);
2423
window->startupId = strdup (startupId);
2425
printf ("Ending legacy sequence %s due to window %d\n",
2426
startupId, (int) window->id);
2428
sn_startup_sequence_complete (s->sequence);
2441
for (s = screen->startupSequences; s; s = s->next)
2443
id = sn_startup_sequence_get_id (s->sequence);
2445
if (strcmp (id, startupId) == 0)
2452
printf ("Found startup sequence for window %d ID \"%s\"\n",
2453
(int) window->id, startupId);
2457
printf ("Did not find startup sequence for window %d ID \"%s\"\n",
2458
(int) window->id, startupId);
2463
enterShowDesktopMode (CompScreen *s)
2466
unsigned long data = 1;
2468
s->showingDesktopMask = ~(CompWindowTypeDesktopMask |
2469
CompWindowTypeDockMask);
2471
for (w = s->windows; w; w = w->next)
2474
XChangeProperty (s->display->display, s->root,
2475
s->display->showingDesktopAtom,
2476
XA_CARDINAL, 32, PropModeReplace,
2477
(unsigned char *) &data, 1);
2481
leaveShowDesktopMode (CompScreen *s)
2484
unsigned long data = 0;
2486
s->showingDesktopMask = 0;
2488
for (w = s->windows; w; w = w->next)
2491
XChangeProperty (s->display->display, s->root,
2492
s->display->showingDesktopAtom,
2493
XA_CARDINAL, 32, PropModeReplace,
2494
(unsigned char *) &data, 1);
2498
sendWindowActivationRequest (CompScreen *s,
2503
xev.xclient.type = ClientMessage;
2504
xev.xclient.display = s->display->display;
2505
xev.xclient.format = 32;
2507
xev.xclient.message_type = s->display->winActiveAtom;
2508
xev.xclient.window = id;
2510
xev.xclient.data.l[0] = 2;
2511
xev.xclient.data.l[1] = 0;
2512
xev.xclient.data.l[2] = 0;
2513
xev.xclient.data.l[3] = 0;
2514
xev.xclient.data.l[4] = 0;
2516
XSendEvent (s->display->display,
2519
SubstructureRedirectMask | SubstructureNotifyMask,