2
* Copyright © 2008 Dennis Kasprzyk
3
* Copyright © 2007 Novell, Inc.
5
* Permission to use, copy, modify, distribute, and sell this software
6
* and its documentation for any purpose is hereby granted without
7
* fee, provided that the above copyright notice appear in all copies
8
* and that both that copyright notice and this permission notice
9
* appear in supporting documentation, and that the name of
10
* Dennis Kasprzyk not be used in advertising or publicity pertaining to
11
* distribution of the software without specific, written prior permission.
12
* Dennis Kasprzyk makes no representations about the suitability of this
13
* software for any purpose. It is provided "as is" without express or
16
* DENNIS KASPRZYK DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
18
* NO EVENT SHALL DENNIS KASPRZYK BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
20
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
21
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
22
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24
* Authors: Dennis Kasprzyk <onestone@compiz-fusion.org>
25
* David Reveman <davidr@novell.com>
30
CompositeWindow::CompositeWindow (CompWindow *w) :
31
PrivateHandler<CompositeWindow, CompWindow, COMPIZ_COMPOSITE_ABI> (w),
32
priv (new PrivateCompositeWindow (w, this))
34
CompScreen *s = screen;
36
if (w->windowClass () != InputOnly)
38
priv->damage = XDamageCreate (s->dpy (), w->id (),
39
XDamageReportRawRectangles);
46
priv->opacity = OPAQUE;
47
if (!(w->type () & CompWindowTypeDesktopMask))
48
priv->opacity = s->getWindowProp32 (w->id (),
49
Atoms::winOpacity, OPAQUE);
51
priv->brightness = s->getWindowProp32 (w->id (),
52
Atoms::winBrightness, BRIGHT);
54
priv->saturation = s->getWindowProp32 (w->id (),
55
Atoms::winSaturation, COLOR);
61
CompositeWindow::~CompositeWindow ()
65
XDamageDestroy (screen->dpy (), priv->damage);
67
if (!priv->redirected)
69
priv->cScreen->overlayWindowCount ()--;
71
if (priv->cScreen->overlayWindowCount () < 1)
72
priv->cScreen->showOutputWindow ();
79
if (lastDamagedWindow == priv->window)
80
lastDamagedWindow = NULL;
85
PrivateCompositeWindow::PrivateCompositeWindow (CompWindow *w,
86
CompositeWindow *cw) :
89
cScreen (CompositeScreen::get (screen)),
93
redirected (cScreen->compositingActive ()),
94
overlayWindow (false),
103
WindowInterface::setHandler (w);
106
PrivateCompositeWindow::~PrivateCompositeWindow ()
114
CompositeWindow::bind ()
116
if (!priv->cScreen->compositingActive ())
122
XWindowAttributes attr;
124
/* don't try to bind window again if it failed previously */
125
if (priv->bindFailed)
128
/* We have to grab the server here to make sure that window
129
is mapped when getting the window pixmap */
130
XGrabServer (screen->dpy ());
131
XGetWindowAttributes (screen->dpy (),
132
ROOTPARENT (priv->window), &attr);
133
if (attr.map_state != IsViewable)
135
XUngrabServer (screen->dpy ());
136
priv->bindFailed = true;
140
priv->pixmap = XCompositeNameWindowPixmap
141
(screen->dpy (), ROOTPARENT (priv->window));
143
XUngrabServer (screen->dpy ());
149
CompositeWindow::release ()
153
XFreePixmap (screen->dpy (), priv->pixmap);
159
CompositeWindow::pixmap ()
165
CompositeWindow::redirect ()
167
if (priv->redirected || !priv->cScreen->compositingActive ())
170
XCompositeRedirectWindow (screen->dpy (),
171
ROOTPARENT (priv->window),
172
CompositeRedirectManual);
174
priv->redirected = true;
176
if (priv->overlayWindow)
178
priv->cScreen->overlayWindowCount ()--;
179
priv->overlayWindow = false;
182
if (priv->cScreen->overlayWindowCount () < 1)
183
priv->cScreen->showOutputWindow ();
185
priv->cScreen->updateOutputWindow ();
189
CompositeWindow::unredirect ()
191
if (!priv->redirected || !priv->cScreen->compositingActive ())
196
XCompositeUnredirectWindow (screen->dpy (),
197
ROOTPARENT (priv->window),
198
CompositeRedirectManual);
200
priv->redirected = false;
201
priv->overlayWindow = true;
202
priv->cScreen->overlayWindowCount ()++;
204
if (priv->cScreen->overlayWindowCount () > 0)
205
priv->cScreen->updateOutputWindow ();
209
CompositeWindow::redirected ()
211
return priv->redirected;
215
CompositeWindow::overlayWindow ()
217
return priv->overlayWindow;
221
CompositeWindow::damageTransformedRect (float xScale,
225
const CompRect &rect)
229
x1 = (short) (rect.x1 () * xScale) - 1;
230
y1 = (short) (rect.y1 () * yScale) - 1;
231
x2 = (short) (rect.x2 () * xScale + 0.5f) + 1;
232
y2 = (short) (rect.y2 () * yScale + 0.5f) + 1;
234
x1 += (short) xTranslate;
235
y1 += (short) yTranslate;
236
x2 += (short) (xTranslate + 0.5f);
237
y2 += (short) (yTranslate + 0.5f);
239
if (x2 > x1 && y2 > y1)
241
CompWindow::Geometry geom = priv->window->geometry ();
243
x1 += geom.x () + geom.border ();
244
y1 += geom.y () + geom.border ();
245
x2 += geom.x () + geom.border ();
246
y2 += geom.y () + geom.border ();
248
priv->cScreen->damageRegion (CompRegion (CompRect (x1, y1, x2 - x1, y2 - y1)));
253
CompositeWindow::damageOutputExtents ()
255
if (priv->cScreen->damageMask () & COMPOSITE_SCREEN_DAMAGE_ALL_MASK)
258
if (priv->window->shaded () ||
259
(priv->window->isViewable () && priv->damaged))
263
CompWindow::Geometry geom = priv->window->geometry ();
264
CompWindowExtents output = priv->window->output ();
267
x1 = -output.left - geom.border ();
268
y1 = -output.top - geom.border ();
269
x2 = priv->window->size ().width () + output.right - geom.border ();
270
y2 = -geom.border ();
272
if (x1 < x2 && y1 < y2)
273
addDamageRect (CompRect (x1, y1, x2 - x1, y2 - y1));
276
y1 = priv->window->size ().height () - geom.border ();
277
y2 = y1 + output.bottom - geom.border ();
279
if (x1 < x2 && y1 < y2)
280
addDamageRect (CompRect (x1, y1, x2 - x1, y2 - y1));
283
x1 = -output.left - geom.border ();
284
y1 = -geom.border ();
285
x2 = -geom.border ();
286
y2 = priv->window->size ().height () - geom.border ();
288
if (x1 < x2 && y1 < y2)
289
addDamageRect (CompRect (x1, y1, x2 - x1, y2 - y1));
292
x1 = priv->window->size ().width () - geom.border ();
293
x2 = x1 + output.right - geom.border ();
295
if (x1 < x2 && y1 < y2)
296
addDamageRect (CompRect (x1, y1, x2 - x1, y2 - y1));
301
CompositeWindow::addDamageRect (const CompRect &rect)
305
if (priv->cScreen->damageMask () & COMPOSITE_SCREEN_DAMAGE_ALL_MASK)
308
if (!damageRect (false, rect))
313
CompWindow::Geometry geom = priv->window->geometry ();
314
x += geom.x () + geom.border ();
315
y += geom.y () + geom.border ();
317
priv->cScreen->damageRegion (CompRegion (CompRect (x, y,
324
CompositeWindow::addDamage (bool force)
326
if (priv->cScreen->damageMask () & COMPOSITE_SCREEN_DAMAGE_ALL_MASK)
329
if (priv->window->shaded () || force ||
330
(priv->window->isViewable () && priv->damaged))
332
int border = priv->window->geometry ().border ();
334
int x1 = -MAX (priv->window->output ().left,
335
priv->window->input ().left) - border;
336
int y1 = -MAX (priv->window->output ().top,
337
priv->window->input ().top) - border;
338
int x2 = priv->window->size ().width () +
339
MAX (priv->window->output ().right,
340
priv->window->input ().right) ;
341
int y2 = priv->window->size ().height () +
342
MAX (priv->window->output ().bottom,
343
priv->window->input ().bottom) ;
344
CompRect r (x1, y1, x2 - x1, y2 - y1);
351
CompositeWindow::damaged ()
353
return priv->damaged;
357
CompositeWindow::processDamage (XDamageNotifyEvent *de)
359
if (priv->window->syncWait ())
361
if (priv->nDamage == priv->sizeDamage)
363
priv->damageRects = (XRectangle *) realloc (priv->damageRects,
364
(priv->sizeDamage + 1) *
365
sizeof (XRectangle));
366
priv->sizeDamage += 1;
369
priv->damageRects[priv->nDamage].x = de->area.x;
370
priv->damageRects[priv->nDamage].y = de->area.y;
371
priv->damageRects[priv->nDamage].width = de->area.width;
372
priv->damageRects[priv->nDamage].height = de->area.height;
377
priv->handleDamageRect (this, de->area.x, de->area.y,
378
de->area.width, de->area.height);
383
PrivateCompositeWindow::handleDamageRect (CompositeWindow *w,
389
bool initial = false;
391
if (!w->priv->redirected)
394
if (!w->priv->damaged)
396
w->priv->damaged = initial = true;
399
if (!w->damageRect (initial, CompRect (x, y, width, height)))
401
CompWindow::Geometry geom = w->priv->window->geometry ();
403
x += geom.x () + geom.border ();
404
y += geom.y () + geom.border ();
406
w->priv->cScreen->damageRegion (CompRegion (CompRect (x, y, width, height)));
410
w->damageOutputExtents ();
414
CompositeWindow::updateOpacity ()
416
unsigned short opacity;
418
if (priv->window->type () & CompWindowTypeDesktopMask)
421
opacity = screen->getWindowProp32 (priv->window->id (),
422
Atoms::winOpacity, OPAQUE);
424
if (opacity != priv->opacity)
426
priv->opacity = opacity;
432
CompositeWindow::updateBrightness ()
434
unsigned short brightness;
436
brightness = screen->getWindowProp32 (priv->window->id (),
437
Atoms::winBrightness, BRIGHT);
439
if (brightness != priv->brightness)
441
priv->brightness = brightness;
447
CompositeWindow::updateSaturation ()
449
unsigned short saturation;
451
saturation = screen->getWindowProp32 (priv->window->id (),
452
Atoms::winSaturation, COLOR);
454
if (saturation != priv->saturation)
456
priv->saturation = saturation;
462
CompositeWindow::opacity ()
464
return priv->opacity;
468
CompositeWindow::brightness ()
470
return priv->brightness;
474
CompositeWindow::saturation ()
476
return priv->saturation;
480
CompositeWindow::damageRect (bool initial,
481
const CompRect &rect)
483
WRAPABLE_HND_FUNC_RETURN(0, bool, damageRect, initial, rect)
488
PrivateCompositeWindow::windowNotify (CompWindowNotify n)
492
case CompWindowNotifyMap:
496
case CompWindowNotifyUnmap:
497
cWindow->addDamage (true);
500
if (!redirected && cScreen->compositingActive ())
501
cWindow->redirect ();
503
case CompWindowNotifyRestack:
504
case CompWindowNotifyHide:
505
case CompWindowNotifyShow:
506
case CompWindowNotifyAliveChanged:
507
cWindow->addDamage (true);
509
case CompWindowNotifyReparent:
510
case CompWindowNotifyUnreparent:
515
cScreen->damageScreen ();
516
cWindow->addDamage (true);
518
case CompWindowNotifyFrameUpdate:
521
case CompWindowNotifySyncAlarm:
528
PrivateCompositeWindow::handleDamageRect (cWindow,
531
rects[nDamage].width,
532
rects[nDamage].height);
541
window->windowNotify (n);
545
PrivateCompositeWindow::resizeNotify (int dx, int dy, int dwidth, int dheight)
547
window->resizeNotify (dx, dy, dwidth, dheight);
549
Pixmap pixmap = None;
551
if (window->shaded () || (window->isViewable () && damaged))
553
int x, y, x1, x2, y1, y2;
555
x = window->geometry ().x ();
556
y = window->geometry ().y ();
558
x1 = x - window->output ().left - dx;
559
y1 = y - window->output ().top - dy;
560
x2 = x + window->size ().width () +
561
window->output ().right - dx - dwidth;
562
y2 = y + window->size ().height () +
563
window->output ().bottom - dy - dheight;
565
cScreen->damageRegion (CompRegion (CompRect (x1, y1, x2 - x1, y2 - y1)));
568
if (window->mapNum () && redirected)
570
unsigned int actualWidth, actualHeight, ui;
575
pixmap = XCompositeNameWindowPixmap (screen->dpy (), window->id ());
576
result = XGetGeometry (screen->dpy (), pixmap, &root, &i, &i,
577
&actualWidth, &actualHeight, &ui, &ui);
579
if (!result || actualWidth != window->size ().width () ||
580
actualHeight != window->size ().height ())
582
XFreePixmap (screen->dpy (), pixmap);
587
cWindow->addDamage ();
590
this->pixmap = pixmap;
594
PrivateCompositeWindow::moveNotify (int dx, int dy, bool now)
596
if (window->shaded () || (window->isViewable () && damaged))
598
int x, y, x1, x2, y1, y2;
600
x = window->geometry ().x ();
601
y = window->geometry ().y ();
603
x1 = x - window->output ().left - dx;
604
y1 = y - window->output ().top - dy;
605
x2 = x + window->size ().width () +
606
window->output ().right - dx;
607
y2 = y + window->size ().height () +
608
window->output ().bottom - dy;
610
cScreen->damageRegion (CompRegion (CompRect (x1, y1, x2 - x1, y2 - y1)));
612
cWindow->addDamage ();
614
window->moveNotify (dx, dy, now);
618
CompositeWindowInterface::damageRect (bool initial, const CompRect &rect)
619
WRAPABLE_DEF (damageRect, initial, rect)