3
* Compiz thumbnail plugin
7
* Copyright : (C) 2007 by Dennis Kasprzyk
8
* E-mail : onestone@beryl-project.org
10
* Ported to Compiz 0.9
11
* Copyright : (C) 2009 by Sam Spilsbury
12
* E-mail : smspillaz@gmail.com
14
* Based on thumbnail.c:
15
* Copyright : (C) 2007 Stjepan Glavina
16
* E-mail : stjepang@gmail.com
18
* This program is free software; you can redistribute it and/or
19
* modify it under the terms of the GNU General Public License
20
* as published by the Free Software Foundation; either version 2
21
* of the License, or (at your option) any later version.
23
* This program is distributed in the hope that it will be useful,
24
* but WITHOUT ANY WARRANTY; without even the implied warranty of
25
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26
* GNU General Public License for more details.
30
#include "thumbnail.h"
31
#include "thumbnail_tex.h"
33
COMPIZ_PLUGIN_20090315 (thumbnail, ThumbPluginVTable);
36
ThumbScreen::freeThumbText (Thumbnail *t)
46
ThumbScreen::renderThumbText (Thumbnail *t,
51
if (freeThumb || !t->text)
54
t->text = new CompText ();
57
if (!textPluginLoaded)
60
tA.maxWidth = t->width;
63
tA.size = optionGetFontSize ();
64
tA.color[0] = optionGetFontColorRed ();
65
tA.color[1] = optionGetFontColorGreen ();
66
tA.color[2] = optionGetFontColorBlue ();
67
tA.color[3] = optionGetFontColorAlpha ();
68
tA.flags = CompText::Ellipsized;
69
if (optionGetFontBold ())
70
tA.flags |= CompText::StyleBold;
73
t->textValid = t->text->renderWindowTitle (t->win->id (), false, tA);
77
ThumbScreen::damageThumbRegion (Thumbnail *t)
79
int x = t->x - t->offset;
80
int y = t->y - t->offset;
81
int width = t->width + (t->offset * 2);
82
int height = t->height + (t->offset * 2);
83
CompRect rect (x, y, width, height);
86
rect.setHeight (rect.height () + t->text->getHeight () + TEXT_DISTANCE);
88
CompRegion region (rect);
90
cScreen->damageRegion (region);
93
#define GET_DISTANCE(a,b) \
94
(sqrt((((a)[0] - (b)[0]) * ((a)[0] - (b)[0])) + \
95
(((a)[1] - (b)[1]) * ((a)[1] - (b)[1]))))
98
ThumbScreen::thumbUpdateThumbnail ()
100
int igMidPoint[2], tMidPoint[2];
101
int tPos[2], tmpPos[2];
102
float distance = 1000000;
103
int off, oDev, tHeight;
105
float maxSize = optionGetThumbSize ();
110
if (thumb.win == pointedWin)
113
if (thumb.opacity > 0.0 && oldThumb.opacity > 0.0)
117
damageThumbRegion (&thumb);
119
freeThumbText (&oldThumb);
123
tw = ThumbWindow::get (oldThumb.win);
125
/* Disable painting on the old thumb */
126
tw->cWindow->damageRectSetEnabled (tw, false);
127
tw->gWindow->glPaintSetEnabled (tw, false);
128
tw->window->resizeNotifySetEnabled (tw, false);
133
thumb.win = pointedWin;
136
if (!thumb.win || !dock)
144
tw = ThumbWindow::get (w);
146
tw->cWindow->damageRectSetEnabled (tw, true);
147
tw->gWindow->glPaintSetEnabled (tw, true);
148
tw->window->resizeNotifySetEnabled (tw, true);
150
/* do we nee to scale the window down? */
151
if (WIN_W (w) > maxSize || WIN_H (w) > maxSize)
153
if (WIN_W (w) >= WIN_H (w))
154
scale = maxSize / WIN_W (w);
156
scale = maxSize / WIN_H (w);
159
thumb.width = WIN_W (w)* scale;
160
thumb.height = WIN_H (w) * scale;
163
if (optionGetTitleEnabled ())
164
renderThumbText (&thumb, false);
166
freeThumbText (&thumb);
168
igMidPoint[0] = w->iconGeometry ().x () + (w->iconGeometry ().width () / 2);
169
igMidPoint[1] = w->iconGeometry ().y () + (w->iconGeometry ().height () / 2);
171
off = optionGetBorder ();
172
oDev = screen->outputDeviceForPoint (w->iconGeometry ().x () +
173
(w->iconGeometry ().width () / 2),
174
w->iconGeometry ().y () +
175
(w->iconGeometry ().height () / 2));
177
if (screen->outputDevs ().size () == 1 ||
178
(unsigned int) oDev > screen->outputDevs ().size ())
180
oGeom.setGeometry (0, 0, screen->width (), screen->height ());
184
oGeom = screen->outputDevs ()[oDev];
187
tHeight = thumb.height;
189
tHeight += thumb.text->getHeight () + TEXT_DISTANCE;
191
/* Could someone please explain how this works */
194
tPos[0] = igMidPoint[0] - (thumb.width / 2.0);
196
if (w->iconGeometry ().y () - tHeight >= 0)
197
tPos[1] = w->iconGeometry ().y () - tHeight;
199
tPos[1] = w->iconGeometry ().y () + w->iconGeometry ().height ();
202
tmpPos[0] = igMidPoint[0] - (thumb.width / 2.0);
204
if (tmpPos[0] - off < oGeom.x1 ())
205
tmpPos[0] = oGeom.x1 () + off;
207
if (tmpPos[0] + off + thumb.width > oGeom.x2 ())
209
if (thumb.width + (2 * off) <= oGeom.width ())
210
tmpPos[0] = oGeom.x2 () - thumb.width - off;
212
tmpPos[0] = oGeom.x1 () + off;
215
tMidPoint[0] = tmpPos[0] + (thumb.width / 2.0);
217
tmpPos[1] = WIN_Y (dock) - tHeight - off;
218
tMidPoint[1] = tmpPos[1] + (tHeight / 2.0);
220
if (tmpPos[1] > oGeom.y1 ())
224
distance = GET_DISTANCE (igMidPoint, tMidPoint);
228
tmpPos[1] = WIN_Y (dock) + WIN_H (dock) + off;
230
tMidPoint[1] = tmpPos[1] + (tHeight / 2.0);
232
if (tmpPos[1] + tHeight + off < oGeom.y2 () &&
233
GET_DISTANCE (igMidPoint, tMidPoint) < distance)
237
distance = GET_DISTANCE (igMidPoint, tMidPoint);
241
tmpPos[1] = igMidPoint[1] - (tHeight / 2.0);
243
if (tmpPos[1] - off < oGeom.y1 ())
244
tmpPos[1] = oGeom.y1 () + off;
246
if (tmpPos[1] + off + tHeight > oGeom.y2 ())
248
if (tHeight + (2 * off) <= oGeom.height ())
249
tmpPos[1] = oGeom.y2 () - thumb.height - off;
251
tmpPos[1] = oGeom.y1 () + off;
254
tMidPoint[1] = tmpPos[1] + (tHeight / 2.0);
256
tmpPos[0] = WIN_X (dock) - thumb.width - off;
257
tMidPoint[0] = tmpPos[0] + (thumb.width / 2.0);
259
if (tmpPos[0] > oGeom.x1 () && GET_DISTANCE (igMidPoint, tMidPoint) < distance)
263
distance = GET_DISTANCE (igMidPoint, tMidPoint);
267
tmpPos[0] = WIN_X (dock) + WIN_W (dock) + off;
269
tMidPoint[0] = tmpPos[0] + (thumb.width / 2.0);
271
if (tmpPos[0] + thumb.width + off < oGeom.x2 () &&
272
GET_DISTANCE (igMidPoint, tMidPoint) < distance)
276
distance = GET_DISTANCE (igMidPoint, tMidPoint);
284
damageThumbRegion (&thumb);
286
cScreen->preparePaintSetEnabled (this, true);
287
cScreen->donePaintSetEnabled (this, true);
288
gScreen->glPaintOutputSetEnabled (this, true);
292
ThumbScreen::thumbShowThumbnail ()
296
thumbUpdateThumbnail ();
297
damageThumbRegion (&thumb);
303
ThumbScreen::checkPosition (CompWindow *w)
305
if (optionGetCurrentViewport ())
307
if (w->serverX () >= screen->width () ||
308
w->serverX () + w->serverWidth () <= 0 ||
309
w->serverY () >= screen->height () ||
310
w->serverY () + w->serverHeight () <= 0)
320
ThumbScreen::positionUpdate (const CompPoint &p)
322
CompWindow *found = NULL;
324
foreach (CompWindow *cw, screen->windows ())
328
if (cw->destroyed ())
331
if (cw->iconGeometry ().isEmpty ())
334
if (!cw->isMapped ())
337
if (cw->state () & CompWindowStateSkipTaskbarMask)
340
if (cw->state () & CompWindowStateSkipPagerMask)
346
if (!tw->cWindow->pixmap ())
349
if (cw->iconGeometry ().contains (p) &&
360
!(thumb.opacity != 0.0 && thumb.win == found))
362
if (displayTimeout.active ())
365
if (pointedWin != found)
367
displayTimeout.stop ();
368
displayTimeout.start (boost::bind
369
(&ThumbScreen::thumbShowThumbnail,
371
optionGetShowDelay (),
372
optionGetShowDelay () + 500);
377
displayTimeout.stop ();
378
displayTimeout.start (boost::bind (&ThumbScreen::thumbShowThumbnail,
380
optionGetShowDelay (),
381
optionGetShowDelay () + 500);
386
thumbUpdateThumbnail ();
390
if (displayTimeout.active ())
392
displayTimeout.stop ();
396
showingThumb = false;
398
cScreen->preparePaintSetEnabled (this, true);
399
cScreen->donePaintSetEnabled (this, true);
405
ThumbWindow::resizeNotify (int dx,
410
THUMB_SCREEN (screen);
412
ts->thumbUpdateThumbnail ();
414
window->resizeNotify (dx, dy, dwidth, dheight);
418
ThumbScreen::handleEvent (XEvent * event)
421
screen->handleEvent (event);
428
if (event->xproperty.atom == Atoms::wmName)
430
w = screen->findWindow (event->xproperty.window);
434
if (thumb.win == w && optionGetTitleEnabled ())
435
renderThumbText (&thumb, true);
443
if (displayTimeout.active ())
445
displayTimeout.stop ();
449
showingThumb = false;
454
w = screen->findWindow (event->xcrossing.window);
457
if (w->wmType () & CompWindowTypeDockMask)
463
if (displayTimeout.active ())
465
displayTimeout.stop ();
469
showingThumb = false;
472
if (!poller.active ())
481
if (displayTimeout.active ())
483
displayTimeout.stop ();
487
showingThumb = false;
489
if (poller.active ())
497
w = screen->findWindow (event->xcrossing.window);
500
if (w->wmType () & CompWindowTypeDockMask)
504
if (displayTimeout.active ())
506
displayTimeout.stop ();
510
showingThumb = false;
512
cScreen->preparePaintSetEnabled (this, true);
513
cScreen->donePaintSetEnabled (this, true);
515
if (poller.active ())
532
ThumbScreen::paintTexture (int wx,
542
glVertex2f (wx, wy + height);
543
glVertex2f (wx + width, wy + height);
544
glVertex2f (wx + width, wy);
547
glVertex2f (wx - off, wy - off);
549
glVertex2f (wx - off, wy);
553
glVertex2f (wx, wy - off);
556
glVertex2f (wx + width, wy - off);
558
glVertex2f (wx + width, wy);
560
glVertex2f (wx + width + off, wy);
562
glVertex2f (wx + width + off, wy - off);
565
glVertex2f (wx - off, wy + height);
567
glVertex2f (wx - off, wy + height + off);
569
glVertex2f (wx, wy + height + off);
571
glVertex2f (wx, wy + height);
574
glVertex2f (wx + width, wy + height);
576
glVertex2f (wx + width, wy + height + off);
578
glVertex2f (wx + width + off, wy + height + off);
580
glVertex2f (wx + width + off, wy + height);
583
glVertex2f (wx, wy - off);
587
glVertex2f (wx + width, wy);
589
glVertex2f (wx + width, wy - off);
592
glVertex2f (wx, wy + height);
594
glVertex2f (wx, wy + height + off);
596
glVertex2f (wx + width, wy + height + off);
598
glVertex2f (wx + width, wy + height);
601
glVertex2f (wx - off, wy);
603
glVertex2f (wx - off, wy + height);
605
glVertex2f (wx, wy + height);
610
glVertex2f (wx + width, wy);
612
glVertex2f (wx + width, wy + height);
614
glVertex2f (wx + width + off, wy + height);
616
glVertex2f (wx + width + off, wy);
622
ThumbScreen::thumbPaintThumb (Thumbnail *t,
623
const GLMatrix *transform)
625
int addWindowGeometryIndex;
626
CompWindow *w = t->win;
629
float width = t->width;
630
float height = t->height;
631
GLWindowPaintAttrib sAttrib;
632
unsigned int mask = PAINT_WINDOW_TRANSFORMED_MASK |
633
PAINT_WINDOW_TRANSLUCENT_MASK;
634
GLWindow *gWindow = GLWindow::get (w);
639
sAttrib = gWindow->paintAttrib ();
642
height += t->text->getHeight () + TEXT_DISTANCE;
644
/* Wrap drawWindowGeometry to make sure the general
645
drawWindowGeometry function is used */
646
addWindowGeometryIndex =
647
gWindow->glAddGeometryGetCurrentIndex ();
649
if (!gWindow->textures ().empty ())
652
GLenum filter = gScreen->textureFilter ();
653
GLMatrix wTransform (*transform);
656
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
657
glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
658
glDisableClientState (GL_TEXTURE_COORD_ARRAY);
660
if (optionGetWindowLike ())
662
glColor4f (1.0, 1.0, 1.0, t->opacity);
663
foreach (GLTexture *tex, windowTexture)
665
tex->enable (GLTexture::Good);
666
paintTexture (wx, wy, width, height, off);
672
glColor4us (optionGetThumbColorRed (),
673
optionGetThumbColorGreen (),
674
optionGetThumbColorBlue (),
675
optionGetThumbColorAlpha () * t->opacity);
677
foreach (GLTexture *tex, glowTexture)
679
tex->enable (GLTexture::Good);
680
paintTexture (wx, wy, width, height, off);
685
glColor4usv (defaultColor);
687
glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
693
if (t->text->getWidth () < width)
694
ox = (width - t->text->getWidth ()) / 2.0;
696
t->text->draw (wx + ox, wy + height, t->opacity);
699
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
700
glDisable (GL_BLEND);
702
gScreen->setTexEnvMode (GL_REPLACE);
704
glColor4usv (defaultColor);
706
sAttrib.opacity *= t->opacity;
707
sAttrib.yScale = t->scale;
708
sAttrib.xScale = t->scale;
710
sAttrib.xTranslate = wx - w->x () + w->border ().left * sAttrib.xScale;
711
sAttrib.yTranslate = wy - w->y () + w->border ().top * sAttrib.yScale;
713
if (optionGetMipmap ())
714
gScreen->setTextureFilter (GL_LINEAR_MIPMAP_LINEAR);
716
GLFragment::Attrib fragment (sAttrib);
718
wTransform.translate (w->x (), w->y (), 0.0f);
719
wTransform.scale (sAttrib.xScale, sAttrib.yScale, 1.0f);
720
wTransform.translate (sAttrib.xTranslate / sAttrib.xScale - w->x (),
721
sAttrib.yTranslate / sAttrib.yScale - w->y (),
725
glLoadMatrixf (wTransform.getMatrix ());
726
/* XXX: replacing the addWindowGeometry function like this is
727
very ugly but necessary until the vertex stage has been made
729
gWindow->glAddGeometrySetCurrentIndex (MAXSHORT);
730
gWindow->glDraw (wTransform, fragment, infiniteRegion, mask);
733
gScreen->setTextureFilter (filter);
736
gWindow->glAddGeometrySetCurrentIndex (addWindowGeometryIndex);
739
/* From here onwards */
742
ThumbScreen::preparePaint (int ms)
747
val /= optionGetFadeSpeed ();
749
/*if (screen->otherGrabExist ("")) // shouldn't there be a s->grabs.empty () or something?
753
if (displayTimeout.active ())
755
displayTimeout.stop ();
759
showingThumb = false;
762
if (showingThumb && thumb.win == pointedWin)
764
thumb.opacity = MIN (1.0, thumb.opacity + val);
767
if (!showingThumb || thumb.win != pointedWin)
769
thumb.opacity = MAX (0.0, thumb.opacity - val);
770
if (thumb.opacity == 0.0)
774
if (oldThumb.opacity > 0.0f)
776
oldThumb.opacity = MAX (0.0, oldThumb.opacity - val);
777
if (oldThumb.opacity == 0.0)
779
damageThumbRegion (&oldThumb);
780
freeThumbText (&oldThumb);
785
if (oldThumb.win == NULL && thumb.win == NULL)
787
cScreen->preparePaintSetEnabled (this, false);
788
cScreen->donePaintSetEnabled (this, false);
789
gScreen->glPaintOutputSetEnabled (this, false);
792
cScreen->preparePaint (ms);
796
ThumbScreen::donePaint ()
798
std::vector <Thumbnail *> damageThumbs;
800
if (thumb.opacity > 0.0 && thumb.opacity < 1.0)
801
damageThumbs.push_back (&thumb);
803
if (oldThumb.opacity > 0.0 && oldThumb.opacity < 1.0)
804
damageThumbs.push_back (&oldThumb);
806
if (damageThumbs.size ())
808
foreach (Thumbnail *t, damageThumbs)
809
damageThumbRegion (t);
813
cScreen->preparePaintSetEnabled (this, false);
814
cScreen->donePaintSetEnabled (this, false);
817
cScreen->donePaint ();
821
ThumbScreen::glPaintOutput (const GLScreenPaintAttrib &attrib,
822
const GLMatrix &transform,
823
const CompRegion ®ion,
828
unsigned int newMask = mask;
832
x = screen->vp ().x ();
833
y = screen->vp ().y ();
835
if ((oldThumb.opacity > 0.0 && oldThumb.win) ||
836
(thumb.opacity > 0.0 && thumb.win))
838
newMask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS_MASK;
841
status = gScreen->glPaintOutput (attrib, transform, region, output, newMask);
843
if (optionGetAlwaysOnTop () && !painted)
845
if (oldThumb.opacity > 0.0 && oldThumb.win)
847
GLMatrix sTransform = transform;
849
sTransform.toScreenSpace (output, -DEFAULT_Z_CAMERA);
851
glLoadMatrixf (sTransform.getMatrix ());
852
thumbPaintThumb (&oldThumb, &sTransform);
856
if (thumb.opacity > 0.0 && thumb.win)
858
GLMatrix sTransform = transform;
860
sTransform.toScreenSpace (output, -DEFAULT_Z_CAMERA);
862
glLoadMatrixf (sTransform.getMatrix ());
863
thumbPaintThumb (&thumb, &sTransform);
872
ThumbScreen::glPaintTransformedOutput (const GLScreenPaintAttrib &attrib,
873
const GLMatrix &transform,
874
const CompRegion ®ion,
879
gScreen->glPaintTransformedOutput (attrib, transform, region, output, mask);
881
if (optionGetAlwaysOnTop () && x == screen->vp ().x () &&
882
y == screen->vp ().y ())
886
if (oldThumb.opacity > 0.0 && oldThumb.win)
888
GLMatrix sTransform = transform;
890
gScreen->glApplyTransform (attrib, output, &sTransform);
891
sTransform.toScreenSpace(output, -attrib.zTranslate);
893
glLoadMatrixf (sTransform.getMatrix ());
894
thumbPaintThumb (&oldThumb, &sTransform);
898
if (thumb.opacity > 0.0 && thumb.win)
900
GLMatrix sTransform = transform;
902
gScreen->glApplyTransform (attrib, output, &sTransform);
903
sTransform.toScreenSpace(output, -attrib.zTranslate);
905
glLoadMatrixf (sTransform.getMatrix ());
906
thumbPaintThumb (&thumb, &sTransform);
913
ThumbWindow::glPaint (const GLWindowPaintAttrib &attrib,
914
const GLMatrix &transform,
920
THUMB_SCREEN (screen);
922
status = gWindow->glPaint (attrib, transform, region, mask);
924
if (!ts->optionGetAlwaysOnTop () && ts->x == screen->vp ().x () &&
925
ts->y == screen->vp ().y ())
927
GLMatrix sTransform = transform;
928
if (ts->oldThumb.opacity > 0.0 && ts->oldThumb.win &&
929
ts->oldThumb.dock == window)
931
ts->thumbPaintThumb (&ts->oldThumb, &sTransform);
934
if (ts->thumb.opacity > 0.0 && ts->thumb.win && ts->thumb.dock == window)
936
ts->thumbPaintThumb (&ts->thumb, &sTransform);
944
ThumbWindow::damageRect (bool initial,
945
const CompRect &rect)
947
THUMB_SCREEN (screen);
949
if (ts->thumb.win == window && ts->thumb.opacity > 0.0)
950
ts->damageThumbRegion (&ts->thumb);
952
if (ts->oldThumb.win == window && ts->oldThumb.opacity > 0.0)
953
ts->damageThumbRegion (&ts->oldThumb);
955
return cWindow->damageRect (initial, rect);
958
ThumbScreen::ThumbScreen (CompScreen *screen) :
959
PluginClassHandler <ThumbScreen, CompScreen> (screen),
960
gScreen (GLScreen::get (screen)),
961
cScreen (CompositeScreen::get (screen)),
964
showingThumb (false),
966
glowTexture (GLTexture::imageDataToTexture
967
(glowTex, CompSize (32, 32), GL_RGBA, GL_UNSIGNED_BYTE)),
968
windowTexture (GLTexture::imageDataToTexture
969
(windowTex, CompSize (32, 32), GL_RGBA, GL_UNSIGNED_BYTE)),
973
ScreenInterface::setHandler (screen);
974
CompositeScreenInterface::setHandler (cScreen, false);
975
GLScreenInterface::setHandler (gScreen, false);
981
oldThumb.text = NULL;
983
thumb.opacity = 0.0f;
984
oldThumb.opacity = 0.0f;
986
poller.setCallback (boost::bind (&ThumbScreen::positionUpdate, this, _1));
989
ThumbScreen::~ThumbScreen ()
992
displayTimeout.stop ();
994
freeThumbText (&thumb);
995
freeThumbText (&oldThumb);
998
ThumbWindow::ThumbWindow (CompWindow *window) :
999
PluginClassHandler <ThumbWindow, CompWindow> (window),
1001
cWindow (CompositeWindow::get (window)),
1002
gWindow (GLWindow::get (window))
1004
WindowInterface::setHandler (window, false);
1005
CompositeWindowInterface::setHandler (cWindow, false);
1006
GLWindowInterface::setHandler (gWindow, false);
1010
ThumbWindow::~ThumbWindow ()
1012
THUMB_SCREEN (screen);
1014
if (ts->thumb.win == window)
1016
ts->damageThumbRegion (&ts->thumb);
1017
ts->thumb.win = NULL;
1018
ts->thumb.opacity = 0;
1021
if (ts->oldThumb.win == window)
1023
ts->damageThumbRegion (&ts->oldThumb);
1024
ts->oldThumb.win = NULL;
1025
ts->oldThumb.opacity = 0;
1028
if (ts->pointedWin == window)
1029
ts->pointedWin = NULL;
1034
ThumbPluginVTable::init ()
1036
if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION))
1038
if (!CompPlugin::checkPluginABI ("composite", COMPIZ_COMPOSITE_ABI))
1040
if (!CompPlugin::checkPluginABI ("opengl", COMPIZ_OPENGL_ABI))
1042
if (!CompPlugin::checkPluginABI ("mousepoll", COMPIZ_MOUSEPOLL_ABI))
1044
if (CompPlugin::checkPluginABI ("text", COMPIZ_TEXT_ABI))
1045
textPluginLoaded = true;
1047
textPluginLoaded = false;