3
* Compiz metacity like info during resize
7
* Copyright (c) 2007 Robert Carr <racarr@opencompositing.org>
9
* Compiz resize atom usage and general cleanups by
10
* Copyright (c) 2007 Danny Baumann <maniac@opencompositing.org>
12
* This program is free software; you can redistribute it and/or
13
* modify it under the terms of the GNU General Public License
14
* as published by the Free Software Foundation; either version 2
15
* of the License, or (at your option) any later version.
17
* This program is distributed in the hope that it will be useful,
18
* but WITHOUT ANY WARRANTY; without even the implied warranty of
19
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20
* GNU General Public License for more details.
24
#include "resizeinfo.h"
26
COMPIZ_PLUGIN_20090315 (resizeinfo, InfoPluginVTable);
28
/* Set up an InfoLayer to build a cairo->opengl texture pipeline */
29
InfoLayer::~InfoLayer ()
35
cairo_surface_destroy (surface);
38
XFreePixmap (screen->dpy (), pixmap);
41
/* Here 's' is Screen * 'screen' is 'CompScreen *' */
43
InfoLayer::InfoLayer () :
45
s (ScreenOfDisplay (screen->dpy (), screen->screenNum ())),
50
format = XRenderFindStandardFormat (screen->dpy (), PictStandardARGB32);
54
pixmap = XCreatePixmap (screen->dpy (), screen->root (),
55
RESIZE_POPUP_WIDTH, RESIZE_POPUP_HEIGHT, 32);
60
cairo_xlib_surface_create_with_xrender_format (screen->dpy (),
65
if (cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS)
67
compLogMessage ("resizeinfo", CompLogLevelWarn,
68
"Could not create cairo layer surface,");
72
texture = GLTexture::bindPixmapToTexture (pixmap,
74
RESIZE_POPUP_HEIGHT, 32);
77
compLogMessage ("resizeinfo", CompLogLevelWarn,
78
"Bind Pixmap to Texture failure");
82
cr = cairo_create (surface);
83
if (cairo_status (cr) != CAIRO_STATUS_SUCCESS)
85
compLogMessage ("resizeinfo", CompLogLevelWarn,
86
"Could not create cairo context");
93
/* Draw the window "size" derived from the window hints.
94
We calculate width or height - base_width or base_height and divide
95
it by the increment in each direction. For windows like terminals
96
setting the proper size hints this gives us the number of columns/rows. */
98
InfoLayer::renderText ()
100
unsigned int baseWidth, baseHeight;
101
unsigned int widthInc, heightInc;
102
unsigned int width, height, xv, yv;
103
unsigned short *color;
106
PangoFontDescription *font;
109
INFO_SCREEN (screen);
114
baseWidth = is->pWindow->sizeHints ().base_width;
115
baseHeight = is->pWindow->sizeHints ().base_height;
116
widthInc = is->pWindow->sizeHints ().width_inc;
117
heightInc = is->pWindow->sizeHints ().height_inc;
118
width = is->resizeGeometry.width;
119
height = is->resizeGeometry.height;
121
color = is->optionGetTextColor ();
123
xv = (widthInc > 1) ? (width - baseWidth) / widthInc : width;
124
yv = (heightInc > 1) ? (height - baseHeight) / heightInc : height;
126
/* Clear the context. */
128
cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
131
cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
133
snprintf (info, 50, "%d x %d", xv, yv);
135
font = pango_font_description_new ();
136
layout = pango_cairo_create_layout (is->textLayer.cr);
138
pango_font_description_set_family (font,"Sans");
139
pango_font_description_set_absolute_size (font, 12 * PANGO_SCALE);
140
pango_font_description_set_style (font, PANGO_STYLE_NORMAL);
141
pango_font_description_set_weight (font, PANGO_WEIGHT_BOLD);
143
pango_layout_set_font_description (layout, font);
144
pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END);
145
pango_layout_set_text (layout, info, -1);
147
pango_layout_get_pixel_size (layout, &w, &h);
150
RESIZE_POPUP_WIDTH / 2.0f - w / 2.0f,
151
RESIZE_POPUP_HEIGHT / 2.0f - h / 2.0f);
153
pango_layout_set_width (layout, RESIZE_POPUP_WIDTH * PANGO_SCALE);
154
pango_cairo_update_layout (cr, layout);
156
cairo_set_source_rgba (cr,
157
*(color) / (float)0xffff,
158
*(color + 1) / (float)0xffff,
159
*(color + 2) / (float)0xffff,
160
*(color + 3) / (float)0xffff);
162
pango_cairo_show_layout (cr, layout);
164
pango_font_description_free (font);
165
g_object_unref (layout);
168
/* Draw the background. We draw this on a second layer so that we do
169
not have to draw it each time we have to update. Granted we could
170
use some cairo trickery for this... */
172
InfoLayer::renderBackground ()
174
cairo_pattern_t *pattern;
176
int height = RESIZE_POPUP_HEIGHT;
177
int width = RESIZE_POPUP_WIDTH;
180
INFO_SCREEN (screen);
185
cairo_set_line_width (cr, 1.0f);
189
cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
192
cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
195
pattern = cairo_pattern_create_linear (0, 0, width, height);
197
r = is->optionGetGradient1Red () / (float)0xffff;
198
g = is->optionGetGradient1Green () / (float)0xffff;
199
b = is->optionGetGradient1Blue () / (float)0xffff;
200
a = is->optionGetGradient1Alpha () / (float)0xffff;
201
cairo_pattern_add_color_stop_rgba (pattern, 0.00f, r, g, b, a);
203
r = is->optionGetGradient1Red () / (float)0xffff;
204
g = is->optionGetGradient1Green () / (float)0xffff;
205
b = is->optionGetGradient1Blue () / (float)0xffff;
206
a = is->optionGetGradient1Alpha () / (float)0xffff;
207
cairo_pattern_add_color_stop_rgba (pattern, 0.65f, r, g, b, a);
209
r = is->optionGetGradient1Red () / (float)0xffff;
210
g = is->optionGetGradient1Green () / (float)0xffff;
211
b = is->optionGetGradient1Blue () / (float)0xffff;
212
a = is->optionGetGradient1Alpha () / (float)0xffff;
213
cairo_pattern_add_color_stop_rgba (pattern, 0.85f, r, g, b, a);
214
cairo_set_source (cr, pattern);
216
/* Rounded Rectangle! */
217
cairo_arc (cr, border, border, border, PI, 1.5f * PI);
218
cairo_arc (cr, border + width - 2 * border, border, border,
219
1.5f * PI, 2.0 * PI);
220
cairo_arc (cr, width - border, height - border, border, 0, PI / 2.0f);
221
cairo_arc (cr, border, height - border, border, PI / 2.0f, PI);
222
cairo_close_path (cr);
223
cairo_fill_preserve (cr);
226
cairo_set_source_rgba (cr, 0.9f, 0.9f, 0.9f, 1.0f);
229
cairo_pattern_destroy (pattern);
233
gradientChanged (CompOption *o,
234
ResizeinfoOptions::Options num)
236
INFO_SCREEN (screen);
238
is->backgroundLayer.renderBackground ();
242
InfoScreen::damagePaintRegion ()
246
if (!fadeTime && !drawing)
249
x = resizeGeometry.x + resizeGeometry.width / 2.0f -
250
RESIZE_POPUP_WIDTH / 2.0f;
251
y = resizeGeometry.y + resizeGeometry.height / 2.0f -
252
RESIZE_POPUP_HEIGHT / 2.0f;
254
CompRegion reg (x - 5, y - 5,
255
(x + RESIZE_POPUP_WIDTH + 5),
256
(y + RESIZE_POPUP_HEIGHT + 5));
258
cScreen->damageRegion (reg);
261
/* Handle the fade in /fade out. */
263
InfoScreen::preparePaint (int ms)
272
cScreen->preparePaint (ms);
276
InfoScreen::donePaint ()
281
damagePaintRegion ();
283
if (!fadeTime && !drawing)
287
cScreen->preparePaintSetEnabled (this, false);
288
gScreen->glPaintOutputSetEnabled (this, false);
289
cScreen->donePaintSetEnabled (this, false);
294
cScreen->donePaint ();
298
InfoWindow::grabNotify (int x,
303
INFO_SCREEN (screen);
305
if ((!is->pWindow || !is->drawing) && !(window->state () & MAXIMIZE_STATE))
308
showInfo = (((window->sizeHints ().width_inc != 1) &&
309
(window->sizeHints ().height_inc != 1)) ||
310
is->optionGetAlwaysShow ());
312
if (showInfo && (mask & CompWindowGrabResizeMask))
314
is->pWindow = window;
316
is->fadeTime = is->optionGetFadeTime () - is->fadeTime;
318
is->resizeGeometry.x = window->x ();
319
is->resizeGeometry.y = window->y ();
320
is->resizeGeometry.width = window->width ();
321
is->resizeGeometry.height = window->height ();
323
screen->handleEventSetEnabled (is, true);
327
window->grabNotify (x, y, state, mask);
331
InfoWindow::ungrabNotify ()
333
INFO_SCREEN (screen);
335
if (window == is->pWindow)
338
is->fadeTime = is->optionGetFadeTime () - is->fadeTime;
339
is->cScreen->damageScreen ();
341
screen->handleEventSetEnabled (is, false);
342
window->ungrabNotifySetEnabled (this, false);
345
window->ungrabNotify ();
348
/* Draw a texture at x/y on a quad of RESIZE_POPUP_WIDTH /
349
RESIZE_POPUP_HEIGHT with the opacity in InfoScreen. */
351
InfoLayer::draw (int x,
357
INFO_SCREEN (screen);
362
for (unsigned int i = 0; i < texture.size (); i++)
365
GLTexture *tex = texture[i];
366
GLTexture::Matrix matrix = tex->matrix ();
368
tex->enable (GLTexture::Good);
370
matrix.x0 -= x * matrix.xx;
371
matrix.y0 -= y * matrix.yy;
374
box.x2 = x + RESIZE_POPUP_WIDTH;
376
box.y2 = y + RESIZE_POPUP_HEIGHT;
378
opacity = (float) is->fadeTime / is->optionGetFadeTime ();
380
opacity = 1.0f - opacity;
382
glColor4f (opacity, opacity, opacity, opacity);
384
glTexCoord2f (COMP_TEX_COORD_X (matrix, box.x1),
385
COMP_TEX_COORD_Y (matrix, box.y2));
386
glVertex2i (box.x1, box.y2);
387
glTexCoord2f (COMP_TEX_COORD_X (matrix, box.x2),
388
COMP_TEX_COORD_Y (matrix, box.y2));
389
glVertex2i (box.x2, box.y2);
390
glTexCoord2f (COMP_TEX_COORD_X (matrix, box.x2),
391
COMP_TEX_COORD_Y (matrix, box.y1));
392
glVertex2i (box.x2, box.y1);
393
glTexCoord2f (COMP_TEX_COORD_X (matrix, box.x1),
394
COMP_TEX_COORD_Y (matrix, box.y1));
395
glVertex2i (box.x1, box.y1);
397
glColor4usv (defaultColor);
404
InfoScreen::glPaintOutput (const GLScreenPaintAttrib &attrib,
405
const GLMatrix &transform,
406
const CompRegion ®ion,
412
status = gScreen->glPaintOutput (attrib, transform, region, output, mask);
414
if ((drawing || fadeTime) && pWindow)
416
GLMatrix sTransform = transform;
419
x = resizeGeometry.x + resizeGeometry.width / 2.0f -
420
RESIZE_POPUP_WIDTH / 2.0f;
421
y = resizeGeometry.y + resizeGeometry.height / 2.0f -
422
RESIZE_POPUP_HEIGHT / 2.0f;
424
sTransform.toScreenSpace (output, -DEFAULT_Z_CAMERA);
427
glLoadMatrixf (sTransform.getMatrix ());
429
glDisableClientState (GL_TEXTURE_COORD_ARRAY);
431
gScreen->setTexEnvMode (GL_MODULATE);
433
backgroundLayer.draw (x, y);
434
textLayer.draw (x, y);
436
glDisable (GL_BLEND);
437
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
446
InfoScreen::handleEvent (XEvent *event)
448
switch (event->type) {
450
if (event->xclient.message_type == resizeInfoAtom)
454
w = screen->findWindow (event->xclient.window);
455
if (w && w == pWindow)
457
resizeGeometry.x = event->xclient.data.l[0];
458
resizeGeometry.y = event->xclient.data.l[1];
459
resizeGeometry.width = event->xclient.data.l[2];
460
resizeGeometry.height = event->xclient.data.l[3];
462
textLayer.renderText ();
464
cScreen->preparePaintSetEnabled (this, true);
465
gScreen->glPaintOutputSetEnabled (this, true);
466
cScreen->donePaintSetEnabled (this, true);
468
w->ungrabNotifySetEnabled (InfoWindow::get (w), true);
470
damagePaintRegion ();
478
screen->handleEvent (event);
481
InfoScreen::InfoScreen (CompScreen *screen) :
482
PluginClassHandler <InfoScreen, CompScreen> (screen),
483
ResizeinfoOptions (),
484
gScreen (GLScreen::get (screen)),
485
cScreen (CompositeScreen::get (screen)),
486
resizeInfoAtom (XInternAtom (screen->dpy (), "_COMPIZ_RESIZE_NOTIFY", 0)),
491
ScreenInterface::setHandler (screen);
492
CompositeScreenInterface::setHandler (cScreen);
493
GLScreenInterface::setHandler (gScreen);
495
memset (&resizeGeometry, 0, sizeof (resizeGeometry));
497
cScreen->preparePaintSetEnabled (this, false);
498
gScreen->glPaintOutputSetEnabled (this, false);
499
cScreen->donePaintSetEnabled (this, false);
501
screen->handleEventSetEnabled (this, false);
503
backgroundLayer.renderBackground ();
505
optionSetGradient1Notify (gradientChanged);
506
optionSetGradient2Notify (gradientChanged);
507
optionSetGradient3Notify (gradientChanged);
510
InfoWindow::InfoWindow (CompWindow *window) :
511
PluginClassHandler <InfoWindow, CompWindow> (window),
514
WindowInterface::setHandler (window);
516
window->ungrabNotifySetEnabled (this, false);
520
InfoPluginVTable::init ()
522
if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION) ||
523
!CompPlugin::checkPluginABI ("composite", COMPIZ_COMPOSITE_ABI) ||
524
!CompPlugin::checkPluginABI ("opengl", COMPIZ_OPENGL_ABI))