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>
36
#include <core/core.h>
37
#include <decoration.h>
40
#include <X11/Xatom.h>
41
#include <X11/extensions/shape.h>
43
COMPIZ_PLUGIN_20081216 (decor, DecorPluginVTable)
46
DecorWindow::glDraw (const GLMatrix &transform,
47
GLFragment::Attrib &attrib,
48
const CompRegion ®ion,
53
status = gWindow->glDraw (transform, attrib, region, mask);
55
const CompRegion reg = (mask & PAINT_WINDOW_TRANSFORMED_MASK) ?
56
infiniteRegion : region;
58
if (wd && !reg.isEmpty () &&
59
wd->decor->type == WINDOW_DECORATION_TYPE_PIXMAP)
62
GLTexture::MatrixList ml (1);
63
mask |= PAINT_WINDOW_BLEND_MASK;
65
gWindow->geometry ().reset ();
67
for (int i = 0; i < wd->nQuad; i++)
69
box.setGeometry (wd->quad[i].box.x1,
71
wd->quad[i].box.x2 - wd->quad[i].box.x1,
72
wd->quad[i].box.y2 - wd->quad[i].box.y1);
74
if (box.width () > 0 && box.height () > 0)
76
ml[0] = wd->quad[i].matrix;
77
gWindow->glAddGeometry (ml, CompRegion (box), reg);
81
if (gWindow->geometry ().vCount)
82
gWindow->glDrawTexture (wd->decor->texture->textures[0],
85
else if (wd && !reg.isEmpty () &&
86
wd->decor->type == WINDOW_DECORATION_TYPE_WINDOW)
88
GLTexture::MatrixList ml (1);
90
if (gWindow->textures ().empty ())
92
if (gWindow->textures ().empty ())
95
if (gWindow->textures ().size () == 1)
97
ml[0] = gWindow->matrices ()[0];
98
gWindow->geometry ().reset ();
99
gWindow->glAddGeometry (ml, window->frameRegion (), reg);
101
if (gWindow->geometry ().vCount)
102
gWindow->glDrawTexture (gWindow->textures ()[0], attrib, mask);
107
updateWindowRegions ();
108
for (unsigned int i = 0; i < gWindow->textures ().size (); i++)
110
ml[0] = gWindow->matrices ()[i];
111
gWindow->geometry ().reset ();
112
gWindow->glAddGeometry (ml, regions[i], reg);
114
if (gWindow->geometry ().vCount)
115
gWindow->glDrawTexture (gWindow->textures ()[i], attrib,
124
static bool bindFailed;
126
DecorTexture::DecorTexture (Pixmap pixmap) :
132
unsigned int width, height, depth, ui;
136
if (!XGetGeometry (screen->dpy (), pixmap, &root,
137
&i, &i, &width, &height, &ui, &depth))
144
textures = GLTexture::bindPixmapToTexture (pixmap, width, height, depth);
145
if (textures.size () != 1)
152
if (!DecorScreen::get (screen)->opt[DECOR_OPTION_MIPMAP].value ().b ())
153
textures[0]->setMipmap (false);
155
damage = XDamageCreate (screen->dpy (), pixmap,
156
XDamageReportRawRectangles);
159
DecorTexture::~DecorTexture ()
162
XDamageDestroy (screen->dpy (), damage);
166
DecorScreen::getTexture (Pixmap pixmap)
171
foreach (DecorTexture *t, textures)
172
if (t->pixmap == pixmap)
178
DecorTexture *texture = new DecorTexture (pixmap);
180
if (!texture->status)
186
textures.push_back (texture);
193
DecorScreen::releaseTexture (DecorTexture *texture)
196
if (texture->refCount)
199
std::list<DecorTexture *>::iterator it =
200
std::find (textures.begin (), textures.end (), texture);
202
if (it == textures.end ())
210
computeQuadBox (decor_quad_t *q,
224
decor_apply_gravity (q->p1.gravity, q->p1.x, q->p1.y, width, height,
226
decor_apply_gravity (q->p2.gravity, q->p2.x, q->p2.y, width, height,
229
if (q->clamp & CLAMP_HORZ)
237
if (q->clamp & CLAMP_VERT)
245
if (q->stretch & STRETCH_X)
247
sx = (float)q->max_width / ((float)(x2 - x1));
249
else if (q->max_width < x2 - x1)
251
if (q->align & ALIGN_RIGHT)
252
x1 = x2 - q->max_width;
254
x2 = x1 + q->max_width;
257
if (q->stretch & STRETCH_Y)
259
sy = (float)q->max_height / ((float)(y2 - y1));
261
else if (q->max_height < y2 - y1)
263
if (q->align & ALIGN_BOTTOM)
264
y1 = y2 - q->max_height;
266
y2 = y1 + q->max_height;
281
Decoration::create (Window id,
284
Decoration *decoration;
287
unsigned long n, nleft;
290
Pixmap pixmap = None;
291
decor_extents_t input;
292
decor_extents_t maxInput;
293
decor_quad_t *quad = NULL;
297
int left, right, top, bottom;
301
result = XGetWindowProperty (screen->dpy (), id,
302
decorAtom, 0L, 1024L, FALSE,
303
XA_INTEGER, &actual, &format,
306
if (result != Success || !n || !data)
309
prop = (long *) data;
311
if (decor_property_get_version (prop) != decor_version ())
313
compLogMessage ("decoration", CompLogLevelWarn,
314
"Property ignored because "
315
"version is %d and decoration plugin version is %d\n",
316
decor_property_get_version (prop), decor_version ());
322
type = decor_property_get_type (prop);
324
if (type == WINDOW_DECORATION_TYPE_PIXMAP &&
325
!DecorScreen::get (screen)->cmActive)
328
if (type == WINDOW_DECORATION_TYPE_PIXMAP)
331
nQuad = (n - BASE_PROP_SIZE) / QUAD_PROP_SIZE;
333
quad = new decor_quad_t [nQuad];
340
nQuad = decor_pixmap_property_to_quads (prop, n, &pixmap, &input,
341
&maxInput, &minWidth,
352
else if (type == WINDOW_DECORATION_TYPE_WINDOW)
354
if (!decor_window_property (prop, n, &input, &maxInput,
355
&minWidth, &minHeight))
365
decoration = new Decoration ();
373
decoration->texture = DecorScreen::get (screen)->getTexture (pixmap);
375
decoration->texture = NULL;
377
if (!decoration->texture && type == WINDOW_DECORATION_TYPE_PIXMAP)
384
decoration->minWidth = minWidth;
385
decoration->minHeight = minHeight;
386
decoration->quad = quad;
387
decoration->nQuad = nQuad;
389
if (type == WINDOW_DECORATION_TYPE_PIXMAP)
398
computeQuadBox (quad, minWidth, minHeight, &x1, &y1, &x2, &y2,
413
decoration->output.left = -left;
414
decoration->output.right = right - minWidth;
415
decoration->output.top = -top;
416
decoration->output.bottom = bottom - minHeight;
420
decoration->output.left = MAX (input.left, maxInput.left);
421
decoration->output.right = MAX (input.right, maxInput.right);
422
decoration->output.top = MAX (input.top, maxInput.top);
423
decoration->output.bottom = MAX (input.bottom, maxInput.bottom);
426
decoration->input.left = input.left;
427
decoration->input.right = input.right;
428
decoration->input.top = input.top;
429
decoration->input.bottom = input.bottom;
431
decoration->maxInput.left = maxInput.left;
432
decoration->maxInput.right = maxInput.right;
433
decoration->maxInput.top = maxInput.top;
434
decoration->maxInput.bottom = maxInput.bottom;
436
decoration->refCount = 1;
437
decoration->type = type;
443
Decoration::release (Decoration *decoration)
445
decoration->refCount--;
446
if (decoration->refCount)
449
if (decoration->texture)
450
DecorScreen::get (screen)->releaseTexture (decoration->texture);
452
delete [] decoration->quad;
457
DecorWindow::updateDecoration ()
459
Decoration *decoration;
462
decoration = Decoration::create (window->id (), dScreen->winDecorAtom);
465
Decoration::release (decor);
470
pixmapFailed = false;
476
WindowDecoration::create (Decoration *d)
478
WindowDecoration *wd;
480
wd = new WindowDecoration ();
484
if (d->type == WINDOW_DECORATION_TYPE_PIXMAP)
486
wd->quad = new ScaledQuad[d->nQuad];
500
wd->nQuad = d->nQuad;
506
WindowDecoration::destroy (WindowDecoration *wd)
508
Decoration::release (wd->decor);
514
DecorWindow::setDecorationMatrices ()
524
for (i = 0; i < wd->nQuad; i++)
526
wd->quad[i].matrix = wd->decor->texture->textures[0]->matrix ();
528
x0 = wd->decor->quad[i].m.x0;
529
y0 = wd->decor->quad[i].m.y0;
531
a = wd->decor->quad[i].m;
532
b = wd->quad[i].matrix;
534
wd->quad[i].matrix.xx = a.xx * b.xx + a.yx * b.xy;
535
wd->quad[i].matrix.yx = a.xx * b.yx + a.yx * b.yy;
536
wd->quad[i].matrix.xy = a.xy * b.xx + a.yy * b.xy;
537
wd->quad[i].matrix.yy = a.xy * b.yx + a.yy * b.yy;
538
wd->quad[i].matrix.x0 = x0 * b.xx + y0 * b.xy + b.x0;
539
wd->quad[i].matrix.y0 = x0 * b.yx + y0 * b.yy + b.y0;
541
wd->quad[i].matrix.xx *= wd->quad[i].sx;
542
wd->quad[i].matrix.yx *= wd->quad[i].sx;
543
wd->quad[i].matrix.xy *= wd->quad[i].sy;
544
wd->quad[i].matrix.yy *= wd->quad[i].sy;
546
if (wd->decor->quad[i].align & ALIGN_RIGHT)
547
x0 = wd->quad[i].box.x2 - wd->quad[i].box.x1;
551
if (wd->decor->quad[i].align & ALIGN_BOTTOM)
552
y0 = wd->quad[i].box.y2 - wd->quad[i].box.y1;
556
wd->quad[i].matrix.x0 -=
557
x0 * wd->quad[i].matrix.xx +
558
y0 * wd->quad[i].matrix.xy;
560
wd->quad[i].matrix.y0 -=
561
y0 * wd->quad[i].matrix.yy +
562
x0 * wd->quad[i].matrix.yx;
564
wd->quad[i].matrix.x0 -=
565
wd->quad[i].box.x1 * wd->quad[i].matrix.xx +
566
wd->quad[i].box.y1 * wd->quad[i].matrix.xy;
568
wd->quad[i].matrix.y0 -=
569
wd->quad[i].box.y1 * wd->quad[i].matrix.yy +
570
wd->quad[i].box.x1 * wd->quad[i].matrix.yx;
575
DecorWindow::updateDecorationScale ()
584
for (i = 0; i < wd->nQuad; i++)
588
computeQuadBox (&wd->decor->quad[i], window->size ().width (),
589
window->size ().height (),
590
&x1, &y1, &x2, &y2, &sx, &sy);
592
x = window->geometry ().x ();
593
y = window->geometry ().y ();
595
wd->quad[i].box.x1 = x1 + x;
596
wd->quad[i].box.y1 = y1 + y;
597
wd->quad[i].box.x2 = x2 + x;
598
wd->quad[i].box.y2 = y2 + y;
603
setDecorationMatrices ();
607
DecorWindow::checkSize (Decoration *decor)
609
return (decor->minWidth <= (int) window->size ().width () &&
610
decor->minHeight <= (int) window->size ().height ());
614
DecorWindow::shiftX ()
616
switch (window->sizeHints ().win_gravity) {
618
case NorthWestGravity:
619
case SouthWestGravity:
620
return window->input ().left;
622
case NorthEastGravity:
623
case SouthEastGravity:
624
return -window->input ().right;
631
DecorWindow::shiftY ()
633
switch (window->sizeHints ().win_gravity) {
635
case NorthWestGravity:
636
case NorthEastGravity:
637
return window->input ().top;
639
case SouthWestGravity:
640
case SouthEastGravity:
641
return -window->input ().bottom;
648
decorOffsetMove (CompWindow *w, XWindowChanges xwc, unsigned int mask)
650
w->configureXWindow (mask, &xwc);
655
DecorWindow::update (bool allowDecoration)
657
Decoration *old, *decoration = NULL;
658
bool decorate = false;
664
old = (wd) ? wd->decor : NULL;
666
switch (window->type ()) {
667
case CompWindowTypeDialogMask:
668
case CompWindowTypeModalDialogMask:
669
case CompWindowTypeUtilMask:
670
case CompWindowTypeMenuMask:
671
case CompWindowTypeNormalMask:
672
if (window->mwmDecor () & (MwmDecorAll | MwmDecorTitle))
673
decorate = window->managed ();
678
if (window->overrideRedirect ())
684
&dScreen->opt[DECOR_OPTION_DECOR_MATCH].value ().match ();
685
if (!match->evaluate (window))
691
if (decor && checkSize (decor))
698
if (dScreen->dmSupports & WINDOW_DECORATION_TYPE_PIXMAP &&
700
!(dScreen->dmSupports & WINDOW_DECORATION_TYPE_WINDOW &&
703
if (window->id () == screen->activeWindow ())
704
decoration = dScreen->decor[DECOR_ACTIVE];
706
decoration = dScreen->decor[DECOR_NORMAL];
708
else if (dScreen->dmSupports & WINDOW_DECORATION_TYPE_WINDOW)
709
decoration = &dScreen->windowDefault;
714
match = &dScreen->opt[DECOR_OPTION_SHADOW_MATCH].value ().match ();
715
if (match->evaluate (window))
717
if (window->region ().numRects () == 1 && !window->alpha ())
718
decoration = dScreen->decor[DECOR_BARE];
722
if (!checkSize (decoration))
728
if (!dScreen->dmWin || !allowDecoration)
731
if (decoration == old)
734
if (dScreen->cmActive)
735
cWindow->damageOutputExtents ();
739
oldShiftX = shiftX ();
740
oldShiftY = shiftY ();
742
WindowDecoration::destroy (wd);
749
wd = WindowDecoration::create (decoration);
753
if ((window->state () & MAXIMIZE_STATE) == MAXIMIZE_STATE)
754
window->setWindowFrameExtents (&wd->decor->maxInput);
756
window->setWindowFrameExtents (&wd->decor->input);
758
moveDx = shiftX () - oldShiftX;
759
moveDy = shiftY () - oldShiftY;
762
window->updateWindowOutputExtents ();
763
if (dScreen->cmActive)
764
cWindow->damageOutputExtents ();
765
updateDecorationScale ();
769
CompWindowExtents emptyExtents;
774
memset (&emptyExtents, 0, sizeof (CompWindowExtents));
776
window->setWindowFrameExtents (&emptyExtents);
782
if (window->placed () && !window->overrideRedirect () &&
786
unsigned int mask = CWX | CWY;
788
memset (&xwc, 0, sizeof (XWindowChanges));
790
xwc.x = window->serverGeometry ().x () + moveDx;
791
xwc.y = window->serverGeometry ().y () + moveDy;
793
if (window->state () & CompWindowStateFullscreenMask)
794
mask &= ~(CWX | CWY);
796
if (window->state () & CompWindowStateMaximizedHorzMask)
799
if (window->state () & CompWindowStateMaximizedVertMask)
802
if (window->saveMask () & CWX)
803
window->saveWc ().x += moveDx;
805
if (window->saveMask () & CWY)
806
window->saveWc ().y += moveDy;
809
moveUpdate.start (boost::bind (decorOffsetMove, window, xwc, mask), 0);
816
DecorWindow::updateFrame ()
818
if (!wd || !(window->input ().left || window->input ().right ||
819
window->input ().top || window->input ().bottom) ||
820
(wd->decor->type == WINDOW_DECORATION_TYPE_PIXMAP && outputFrame) ||
821
(wd->decor->type == WINDOW_DECORATION_TYPE_WINDOW && inputFrame))
825
XDeleteProperty (screen->dpy (), window->id (),
826
dScreen->inputFrameAtom);
827
XDestroyWindow (screen->dpy (), inputFrame);
829
frameRegion = CompRegion ();
838
XDamageDestroy (screen->dpy (), frameDamage);
839
XDeleteProperty (screen->dpy (), window->id (),
840
dScreen->outputFrameAtom);
841
XDestroyWindow (screen->dpy (), outputFrame);
842
dScreen->frames.erase (outputFrame);
845
frameRegion = CompRegion ();
853
if (wd && (window->input ().left || window->input ().right ||
854
window->input ().top || window->input ().bottom))
856
if (wd->decor->type == WINDOW_DECORATION_TYPE_PIXMAP)
858
else if (wd->decor->type == WINDOW_DECORATION_TYPE_WINDOW)
859
updateOutputFrame ();
864
DecorWindow::updateInputFrame ()
867
int x, y, width, height;
869
CompWindow::Geometry server = window->serverGeometry ();
870
int bw = server.border () * 2;
871
CompWindowExtents input;
873
if ((window->state () & MAXIMIZE_STATE) == MAXIMIZE_STATE)
874
input = wd->decor->maxInput;
876
input = wd->decor->input;
878
x = window->input ().left - input.left;
879
y = window->input ().top - input.top;
880
width = server.width () + input.left + input.right + bw;
881
height = server.height ()+ input.top + input.bottom + bw;
883
if (window->shaded ())
884
height = input.top + input.bottom;
886
XGrabServer (screen->dpy ());
890
XSetWindowAttributes attr;
892
attr.event_mask = StructureNotifyMask;
893
attr.override_redirect = TRUE;
895
inputFrame = XCreateWindow (screen->dpy (), window->frame (),
896
x, y, width, height, 0, CopyFromParent,
897
InputOnly, CopyFromParent,
898
CWOverrideRedirect | CWEventMask,
901
XGrabButton (screen->dpy (), AnyButton, AnyModifier, inputFrame,
902
TRUE, ButtonPressMask | ButtonReleaseMask |
903
ButtonMotionMask, GrabModeSync, GrabModeSync, None,
906
XMapWindow (screen->dpy (), inputFrame);
908
XChangeProperty (screen->dpy (), window->id (),
909
dScreen->inputFrameAtom, XA_WINDOW, 32,
910
PropModeReplace, (unsigned char *) &inputFrame, 1);
912
if (screen->XShape ())
913
XShapeSelectInput (screen->dpy (), inputFrame, ShapeNotifyMask);
921
if (x != oldX || y != oldY || width != oldWidth || height != oldHeight)
928
XMoveResizeWindow (screen->dpy (), inputFrame, x, y,
930
XLowerWindow (screen->dpy (), inputFrame);
935
rects[i].width = width;
936
rects[i].height = input.top;
938
if (rects[i].width && rects[i].height)
942
rects[i].y = input.top;
943
rects[i].width = input.left;
944
rects[i].height = height - input.top - input.bottom;
946
if (rects[i].width && rects[i].height)
949
rects[i].x = width - input.right;
950
rects[i].y = input.top;
951
rects[i].width = input.right;
952
rects[i].height = height - input.top - input.bottom;
954
if (rects[i].width && rects[i].height)
958
rects[i].y = height - input.bottom;
959
rects[i].width = width;
960
rects[i].height = input.bottom;
962
if (rects[i].width && rects[i].height)
965
XShapeCombineRectangles (screen->dpy (), inputFrame,
966
ShapeInput, 0, 0, rects, i,
969
frameRegion = CompRegion ();
972
XUngrabServer (screen->dpy ());
976
DecorWindow::updateOutputFrame ()
979
int x, y, width, height;
981
CompWindow::Geometry server = window->serverGeometry ();
982
int bw = server.border () * 2;
983
CompWindowExtents input;
985
if ((window->state () & MAXIMIZE_STATE) == MAXIMIZE_STATE)
986
input = wd->decor->maxInput;
988
input = wd->decor->input;
990
x = window->input ().left - input.left;
991
y = window->input ().top - input.top;
992
width = server.width () + input.left + input.right + bw;
993
height = server.height ()+ input.top + input.bottom + bw;
995
if (window->shaded ())
996
height = input.top + input.bottom;
998
XGrabServer (screen->dpy ());
1002
XSetWindowAttributes attr;
1004
attr.background_pixel = 0x0;
1005
attr.event_mask = StructureNotifyMask;
1006
attr.override_redirect = TRUE;
1008
outputFrame = XCreateWindow (screen->dpy (), window->frame (),
1009
x, y, width, height, 0, CopyFromParent,
1010
InputOutput, CopyFromParent,
1011
CWOverrideRedirect | CWEventMask,
1014
XGrabButton (screen->dpy (), AnyButton, AnyModifier, outputFrame,
1015
TRUE, ButtonPressMask | ButtonReleaseMask |
1016
ButtonMotionMask, GrabModeSync, GrabModeSync, None,
1019
XMapWindow (screen->dpy (), outputFrame);
1021
XChangeProperty (screen->dpy (), window->id (),
1022
dScreen->outputFrameAtom, XA_WINDOW, 32,
1023
PropModeReplace, (unsigned char *) &outputFrame, 1);
1025
if (screen->XShape ())
1026
XShapeSelectInput (screen->dpy (), outputFrame,
1034
frameDamage = XDamageCreate (screen->dpy (), outputFrame,
1035
XDamageReportRawRectangles);
1037
dScreen->frames[outputFrame] = this;
1040
if (x != oldX || y != oldY || width != oldWidth || height != oldHeight)
1047
XMoveResizeWindow (screen->dpy (), outputFrame, x, y, width, height);
1048
XLowerWindow (screen->dpy (), outputFrame);
1053
rects[i].width = width;
1054
rects[i].height = input.top;
1056
if (rects[i].width && rects[i].height)
1060
rects[i].y = input.top;
1061
rects[i].width = input.left;
1062
rects[i].height = height - input.top - input.bottom;
1064
if (rects[i].width && rects[i].height)
1067
rects[i].x = width - input.right;
1068
rects[i].y = input.top;
1069
rects[i].width = input.right;
1070
rects[i].height = height - input.top - input.bottom;
1072
if (rects[i].width && rects[i].height)
1076
rects[i].y = height - input.bottom;
1077
rects[i].width = width;
1078
rects[i].height = input.bottom;
1080
if (rects[i].width && rects[i].height)
1083
XShapeCombineRectangles (screen->dpy (), outputFrame,
1084
ShapeBounding, 0, 0, rects, i,
1085
ShapeSet, YXBanded);
1087
frameRegion = CompRegion ();
1090
XUngrabServer (screen->dpy ());
1094
DecorScreen::checkForDm (bool updateWindows)
1097
int result, format, dmSupports = 0;
1098
unsigned long n, left;
1099
unsigned char *data;
1100
Window dmWin = None;
1102
result = XGetWindowProperty (screen->dpy (), screen->root (),
1103
supportingDmCheckAtom, 0L, 1L, FALSE,
1104
XA_WINDOW, &actual, &format,
1107
if (result == Success && n && data)
1109
XWindowAttributes attr;
1111
memcpy (&dmWin, data, sizeof (Window));
1114
CompScreen::checkForError (screen->dpy ());
1116
XGetWindowAttributes (screen->dpy (), dmWin, &attr);
1118
if (CompScreen::checkForError (screen->dpy ()))
1122
result = XGetWindowProperty (screen->dpy (), dmWin,
1123
decorTypeAtom, 0L, 2L, FALSE,
1124
XA_ATOM, &actual, &format,
1126
if (result == Success && n && data)
1128
Atom *ret = (Atom *) data;
1130
for (unsigned long i = 0; i < n; i++)
1132
if (ret[i] == decorTypePixmapAtom)
1133
dmSupports |= WINDOW_DECORATION_TYPE_PIXMAP;
1134
else if (ret[i] == decorTypeWindowAtom)
1135
dmSupports |= WINDOW_DECORATION_TYPE_WINDOW;
1148
if (dmWin != this->dmWin)
1152
this->dmSupports = dmSupports;
1156
for (i = 0; i < DECOR_NUM; i++)
1157
decor[i] = Decoration::create (screen->root (), decorAtom[i]);
1161
for (i = 0; i < DECOR_NUM; i++)
1165
Decoration::release (decor[i]);
1170
foreach (CompWindow *w, screen->windows ())
1172
DecorWindow *dw = DecorWindow::get (w);
1176
Decoration::release (dw->decor);
1182
this->dmWin = dmWin;
1186
foreach (CompWindow *w, screen->windows ())
1187
if (w->shaded () || w->isViewable ())
1188
DecorWindow::get (w)->update (true);
1194
DecorWindow::updateFrameRegion (CompRegion ®ion)
1196
window->updateFrameRegion (region);
1199
if (!frameRegion.isEmpty ())
1203
x = window->geometry (). x ();
1204
y = window->geometry (). y ();
1206
region += frameRegion.translated (x - window->input ().left,
1207
y - window->input ().top);
1211
region += infiniteRegion;
1218
DecorWindow::updateWindowRegions ()
1220
if (regions.size () != gWindow->textures ().size ())
1221
regions.resize (gWindow->textures ().size ());
1222
for (unsigned int i = 0; i < gWindow->textures ().size (); i++)
1224
regions[i] = CompRegion (*gWindow->textures ()[i]);
1225
regions[i].translate (window->geometry ().x () - window->input ().left,
1226
window->geometry ().y () - window->input ().top);
1227
regions[i] &= window->frameRegion ();
1233
DecorScreen::handleEvent (XEvent *event)
1235
Window activeWindow = screen->activeWindow ();
1238
switch (event->type) {
1240
w = screen->findWindow (event->xdestroywindow.window);
1243
if (w->id () == dmWin)
1248
w = screen->findWindow (event->xdestroywindow.window);
1250
DecorWindow::get (w)->update (true);
1254
event->type == cScreen->damageEvent () + XDamageNotify)
1256
XDamageNotifyEvent *de = (XDamageNotifyEvent *) event;
1258
if (frames.find (de->drawable) != frames.end ())
1259
frames[de->drawable]->cWindow->damageOutputExtents ();
1261
foreach (DecorTexture *t, textures)
1263
if (t->pixmap == de->drawable)
1265
foreach (CompWindow *w, screen->windows ())
1267
if (w->shaded () || w->mapNum ())
1271
if (dw->wd && dw->wd->decor->texture == t)
1272
dw->cWindow->damageOutputExtents ();
1282
screen->handleEvent (event);
1284
if (screen->activeWindow () != activeWindow)
1286
w = screen->findWindow (activeWindow);
1288
DecorWindow::get (w)->update (true);
1290
w = screen->findWindow (screen->activeWindow ());
1292
DecorWindow::get (w)->update (true);
1295
switch (event->type) {
1296
case PropertyNotify:
1297
if (event->xproperty.atom == winDecorAtom)
1299
w = screen->findWindow (event->xproperty.window);
1303
dw->updateDecoration ();
1307
else if (event->xproperty.atom == Atoms::mwmHints)
1309
w = screen->findWindow (event->xproperty.window);
1311
DecorWindow::get (w)->update (true);
1315
if (event->xproperty.window == screen->root ())
1317
if (event->xproperty.atom == supportingDmCheckAtom)
1325
for (i = 0; i < DECOR_NUM; i++)
1327
if (event->xproperty.atom == decorAtom[i])
1330
Decoration::release (decor[i]);
1333
Decoration::create (screen->root (),
1336
foreach (CompWindow *w, screen->windows ())
1337
DecorWindow::get (w)->update (true);
1344
case ConfigureNotify:
1345
w = screen->findTopLevelWindow (event->xconfigure.window);
1356
w = screen->findTopLevelWindow (event->xproperty.window);
1360
if (dw->inputFrame &&
1361
dw->inputFrame == event->xdestroywindow.window)
1363
XDeleteProperty (screen->dpy (), w->id (),
1365
dw->inputFrame = None;
1367
else if (dw->outputFrame &&
1368
dw->outputFrame == event->xdestroywindow.window)
1370
XDeleteProperty (screen->dpy (), w->id (),
1372
dw->outputFrame = None;
1377
if (screen->XShape () && event->type ==
1378
screen->shapeEvent () + ShapeNotify)
1380
w = screen->findWindow (((XShapeEvent *) event)->window);
1382
DecorWindow::get (w)->update (true);
1385
foreach (w, screen->windows ())
1388
if (dw->inputFrame ==
1389
((XShapeEvent *) event)->window)
1391
XRectangle *shapeRects = 0;
1394
dw->frameRegion = CompRegion ();
1397
XShapeGetRectangles (screen->dpy (),
1398
dw->inputFrame, ShapeInput,
1400
if (!n || !shapeRects)
1403
for (int i = 0; i < n; i++)
1405
CompRegion (shapeRects[i].x,
1407
shapeRects[i].width,
1408
shapeRects[i].height);
1410
w->updateFrameRegion ();
1414
else if (dw->outputFrame ==
1415
((XShapeEvent *) event)->window)
1417
XRectangle *shapeRects = 0;
1420
dw->frameRegion = CompRegion ();
1423
XShapeGetRectangles (screen->dpy (),
1424
dw->outputFrame, ShapeBounding,
1426
if (!n || !shapeRects)
1429
for (int i = 0; i < n; i++)
1431
CompRegion (shapeRects[i].x,
1433
shapeRects[i].width,
1434
shapeRects[i].height);
1436
w->updateFrameRegion ();
1448
DecorWindow::damageRect (bool initial, const CompRect &rect)
1453
return cWindow->damageRect (initial, rect);
1457
DecorWindow::getOutputExtents (CompWindowExtents& output)
1459
window->getOutputExtents (output);
1463
CompWindowExtents *e = &wd->decor->output;
1465
if (e->left > output.left)
1466
output.left = e->left;
1467
if (e->right > output.right)
1468
output.right = e->right;
1469
if (e->top > output.top)
1470
output.top = e->top;
1471
if (e->bottom > output.bottom)
1472
output.bottom = e->bottom;
1476
CompOption::Vector &
1477
DecorScreen::getOptions ()
1483
DecorScreen::setOption (const char *name,
1484
CompOption::Value &value)
1489
o = CompOption::findOption (opt, name, &index);
1494
case DECOR_OPTION_COMMAND:
1499
screen->runCommand (o->value ().s ());
1503
case DECOR_OPTION_SHADOW_MATCH:
1505
CompString matchString;
1508
Make sure RGBA matching is always present and disable shadows
1509
for RGBA windows by default if the user didn't specify an
1511
Reasoning for that is that shadows are desired for some RGBA
1512
windows (e.g. rectangular windows that just happen to have an
1513
RGBA colormap), while it's absolutely undesired for others
1514
(especially shaped ones) ... by enforcing no shadows for RGBA
1515
windows by default, we are flexible to user desires while still
1516
making sure we don't show ugliness by default
1519
matchString = value.match ().toString ();
1520
if (matchString.find ("rgba=") == CompString::npos)
1522
CompMatch rgbaMatch("rgba=0");
1523
value.match () &= rgbaMatch;
1526
/* fall-through intended */
1527
case DECOR_OPTION_DECOR_MATCH:
1530
foreach (CompWindow *w, screen->windows ())
1531
DecorWindow::get (w)->update (true);
1535
return CompOption::setOption (*o, value);
1542
DecorWindow::moveNotify (int dx, int dy, bool immediate)
1548
for (i = 0; i < wd->nQuad; i++)
1550
wd->quad[i].box.x1 += dx;
1551
wd->quad[i].box.y1 += dy;
1552
wd->quad[i].box.x2 += dx;
1553
wd->quad[i].box.y2 += dy;
1556
setDecorationMatrices ();
1560
window->moveNotify (dx, dy, immediate);
1564
DecorWindow::resizeTimeout ()
1571
DecorWindow::resizeNotify (int dx, int dy, int dwidth, int dheight)
1573
/* FIXME: we should not need a timer for calling decorWindowUpdate,
1574
and only call updateWindowDecorationScale if decorWindowUpdate
1575
returns FALSE. Unfortunately, decorWindowUpdate may call
1576
updateWindowOutputExtents, which may call WindowResizeNotify. As
1577
we never should call a wrapped function that's currently
1578
processed, we need the timer for the moment. updateWindowOutputExtents
1579
should be fixed so that it does not emit a resize notification. */
1580
resizeUpdate.start (boost::bind (&DecorWindow::resizeTimeout, this), 0);
1581
updateDecorationScale ();
1584
window->resizeNotify (dx, dy, dwidth, dheight);
1588
DecorWindow::stateChangeNotify (unsigned int lastState)
1592
if (wd && wd->decor)
1594
if ((window->state () & MAXIMIZE_STATE) == MAXIMIZE_STATE)
1595
window->setWindowFrameExtents (&wd->decor->maxInput);
1597
window->setWindowFrameExtents (&wd->decor->input);
1603
window->stateChangeNotify (lastState);
1607
DecorScreen::matchPropertyChanged (CompWindow *w)
1609
DecorWindow::get (w)->update (true);
1611
screen->matchPropertyChanged (w);
1615
DecorScreen::decoratorStartTimeout ()
1618
screen->runCommand (opt[DECOR_OPTION_COMMAND].value ().s ());
1623
static const CompMetadata::OptionInfo decorOptionInfo[] = {
1624
{ "shadow_radius", "float", "<min>0.0</min><max>48.0</max>", 0, 0 },
1625
{ "shadow_opacity", "float", "<min>0.0</min>", 0, 0 },
1626
{ "shadow_color", "color", 0, 0, 0 },
1627
{ "shadow_x_offset", "int", "<min>-16</min><max>16</max>", 0, 0 },
1628
{ "shadow_y_offset", "int", "<min>-16</min><max>16</max>", 0, 0 },
1629
{ "command", "string", 0, 0, 0 },
1630
{ "mipmap", "bool", 0, 0, 0 },
1631
{ "decoration_match", "match", 0, 0, 0 },
1632
{ "shadow_match", "match", 0, 0, 0 }
1635
DecorScreen::DecorScreen (CompScreen *s) :
1636
PrivateHandler<DecorScreen,CompScreen> (s),
1637
cScreen (CompositeScreen::get (s)),
1642
opt (DECOR_OPTION_NUM)
1644
if (!decorVTable->getMetadata ()->initOptions (decorOptionInfo,
1645
DECOR_OPTION_NUM, opt))
1651
supportingDmCheckAtom =
1652
XInternAtom (s->dpy (), DECOR_SUPPORTING_DM_CHECK_ATOM_NAME, 0);
1654
XInternAtom (s->dpy (), DECOR_WINDOW_ATOM_NAME, 0);
1655
decorAtom[DECOR_BARE] =
1656
XInternAtom (s->dpy (), DECOR_BARE_ATOM_NAME, 0);
1657
decorAtom[DECOR_NORMAL] =
1658
XInternAtom (s->dpy (), DECOR_NORMAL_ATOM_NAME, 0);
1659
decorAtom[DECOR_ACTIVE] =
1660
XInternAtom (s->dpy (), DECOR_ACTIVE_ATOM_NAME, 0);
1662
XInternAtom (s->dpy (), DECOR_INPUT_FRAME_ATOM_NAME, 0);
1664
XInternAtom (s->dpy (), DECOR_OUTPUT_FRAME_ATOM_NAME, 0);
1666
XInternAtom (s->dpy (), DECOR_TYPE_ATOM_NAME, 0);
1667
decorTypePixmapAtom =
1668
XInternAtom (s->dpy (), DECOR_TYPE_PIXMAP_ATOM_NAME, 0);
1669
decorTypeWindowAtom =
1670
XInternAtom (s->dpy (), DECOR_TYPE_WINDOW_ATOM_NAME, 0);
1672
windowDefault.texture = NULL;
1673
windowDefault.minWidth = 0;
1674
windowDefault.minHeight = 0;
1675
windowDefault.quad = NULL;
1676
windowDefault.nQuad = 0;
1677
windowDefault.type = WINDOW_DECORATION_TYPE_WINDOW;
1679
windowDefault.input.left = 0;
1680
windowDefault.input.right = 0;
1681
windowDefault.input.top = 1;
1682
windowDefault.input.bottom = 0;
1684
windowDefault.maxInput = windowDefault.output = windowDefault.input;
1685
windowDefault.refCount = 1;
1687
cmActive = (cScreen) ? cScreen->compositingActive () &&
1688
GLScreen::get (s) != NULL : false;
1690
for (unsigned int i = 0; i < DECOR_NUM; i++)
1695
decoratorStart.start (boost::bind (&DecorScreen::decoratorStartTimeout,
1699
ScreenInterface::setHandler (s);
1702
DecorScreen::~DecorScreen ()
1704
for (unsigned int i = 0; i < DECOR_NUM; i++)
1706
Decoration::release (decor[i]);
1709
DecorWindow::DecorWindow (CompWindow *w) :
1710
PrivateHandler<DecorWindow,CompWindow> (w),
1712
gWindow (GLWindow::get (w)),
1713
cWindow (CompositeWindow::get (w)),
1714
dScreen (DecorScreen::get (screen)),
1719
pixmapFailed (false),
1723
WindowInterface::setHandler (window);
1725
if (dScreen->cmActive)
1727
gWindow = GLWindow::get (w);
1728
cWindow = CompositeWindow::get (w);
1729
CompositeWindowInterface::setHandler (cWindow);
1730
GLWindowInterface::setHandler (gWindow);
1733
if (!w->overrideRedirect ())
1734
updateDecoration ();
1736
if (w->shaded () || w->isViewable ())
1741
DecorWindow::~DecorWindow ()
1743
if (!window->destroyed ())
1747
WindowDecoration::destroy (wd);
1750
Decoration::release (decor);
1754
DecorPluginVTable::init ()
1756
if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION))
1759
getMetadata ()->addFromOptionInfo (decorOptionInfo, DECOR_OPTION_NUM);
1760
getMetadata ()->addFromFile (name ());