3
* Description: Adds text to pixmap support to Compiz.
7
* Copyright: (C) 2006-2007 Patrick Niklaus, Danny Baumann, Dennis Kasprzyk
8
* Authors: Patrick Niklaus <marex@opencompsiting.org>
9
* Danny Baumann <maniac@opencompositing.org>
10
* Dennis Kasprzyk <onestone@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.
22
* You should have received a copy of the GNU General Public License
23
* along with this program; if not, write to the Free Software
24
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
30
#define PI 3.14159265359f
32
COMPIZ_PLUGIN_20090315 (text, TextPluginVTable);
35
PrivateTextScreen::getUtf8Property (Window id,
40
unsigned long nItems, bytesAfter;
44
result = XGetWindowProperty (screen->dpy (), id, atom, 0L, 65536, False,
45
utf8StringAtom, &type, &format, &nItems,
46
&bytesAfter, (unsigned char **) &val);
48
if (result != Success)
51
if (type == utf8StringAtom && format == 8 && val && nItems > 0)
53
char valueString[nItems + 1];
55
strncpy (valueString, val, nItems);
56
valueString[nItems] = 0;
68
PrivateTextScreen::getTextProperty (Window id,
75
if (XGetTextProperty (screen->dpy (), id, &text, atom))
79
char valueString[text.nitems + 1];
81
strncpy (valueString, (char *) text.value, text.nitems);
82
valueString[text.nitems] = 0;
94
PrivateTextScreen::getWindowName (Window id)
98
name = getUtf8Property (id, visibleNameAtom);
101
name = getUtf8Property (id, wmNameAtom);
104
name = getTextProperty (id, XA_WM_NAME);
109
/* Actual text rendering functions */
112
* Draw a rounded rectangle path
115
TextSurface::drawBackground (int x,
129
cairo_arc (cr, x0 + radius, y1 - radius, radius, PI / 2, PI);
130
cairo_line_to (cr, x0, y0 + radius);
131
cairo_arc (cr, x0 + radius, y0 + radius, radius, PI, 3 * PI / 2);
132
cairo_line_to (cr, x1 - radius, y0);
133
cairo_arc (cr, x1 - radius, y0 + radius, radius, 3 * PI / 2, 2 * PI);
134
cairo_line_to (cr, x1, y1 - radius);
135
cairo_arc (cr, x1 - radius, y1 - radius, radius, 0, PI / 2);
136
cairo_close_path (cr);
140
TextSurface::initCairo (int width,
143
Display *dpy = screen->dpy ();
146
if (width > 0 && height > 0)
147
mPixmap = XCreatePixmap (dpy, screen->root (), width, height, 32);
154
compLogMessage ("text", CompLogLevelError,
155
"Couldn't create %d x %d pixmap.", width, height);
159
surface = cairo_xlib_surface_create_with_xrender_format (dpy,
166
if (cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS)
168
compLogMessage ("text", CompLogLevelError, "Couldn't create surface.");
172
cr = cairo_create (surface);
173
if (cairo_status (cr) != CAIRO_STATUS_SUCCESS)
175
compLogMessage ("text", CompLogLevelError,
176
"Couldn't create cairo context.");
184
TextSurface::update (int width,
187
Display *dpy = screen->dpy ();
189
cairo_surface_destroy (surface);
195
XFreePixmap (dpy, mPixmap);
198
return initCairo (width, height);
202
TextSurface::render (const CompText::Attrib &attrib,
203
const CompString &text)
205
int width, height, layoutWidth;
210
pango_font_description_set_family (font, attrib.family);
211
pango_font_description_set_absolute_size (font,
212
attrib.size * PANGO_SCALE);
213
pango_font_description_set_style (font, PANGO_STYLE_NORMAL);
215
if (attrib.flags & CompText::StyleBold)
216
pango_font_description_set_weight (font, PANGO_WEIGHT_BOLD);
218
if (attrib.flags & CompText::StyleItalic)
219
pango_font_description_set_style (font, PANGO_STYLE_ITALIC);
221
pango_layout_set_font_description (layout, font);
223
if (attrib.flags & CompText::Ellipsized)
224
pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END);
226
pango_layout_set_auto_dir (layout, false);
227
pango_layout_set_text (layout, text.c_str (), -1);
229
pango_layout_get_pixel_size (layout, &width, &height);
231
if (attrib.flags & CompText::WithBackground)
233
width += 2 * attrib.bgHMargin;
234
height += 2 * attrib.bgVMargin;
237
width = MIN (attrib.maxWidth, width);
238
height = MIN (attrib.maxHeight, height);
240
/* update the size of the pango layout */
241
layoutWidth = attrib.maxWidth;
242
if (attrib.flags & CompText::WithBackground)
243
layoutWidth -= 2 * attrib.bgHMargin;
245
pango_layout_set_width (layout, layoutWidth * PANGO_SCALE);
247
if (!update (width, height))
250
pango_cairo_update_layout (cr, layout);
253
cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
257
cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
259
if (attrib.flags & CompText::WithBackground)
261
drawBackground (0, 0, width, height,
262
MIN (attrib.bgHMargin, attrib.bgVMargin));
263
cairo_set_source_rgba (cr,
264
attrib.bgColor[0] / 65535.0,
265
attrib.bgColor[1] / 65535.0,
266
attrib.bgColor[2] / 65535.0,
267
attrib.bgColor[3] / 65535.0);
269
cairo_move_to (cr, attrib.bgHMargin, attrib.bgVMargin);
272
cairo_set_source_rgba (cr,
273
attrib.color[0] / 65535.0,
274
attrib.color[1] / 65535.0,
275
attrib.color[2] / 65535.0,
276
attrib.color[3] / 65535.0);
278
pango_cairo_show_layout (cr, layout);
284
TextSurface::valid () const
286
return scrn && format && layout && font &&
287
cr && cairo_status (cr) == CAIRO_STATUS_SUCCESS &&
288
surface && cairo_surface_status (surface) == CAIRO_STATUS_SUCCESS;
291
TextSurface::TextSurface () :
302
Display *dpy = screen->dpy ();
304
scrn = ScreenOfDisplay (dpy, screen->screenNum ());
308
compLogMessage ("text", CompLogLevelError,
309
"Couldn't get screen for %d.", screen->screenNum ());
313
format = XRenderFindStandardFormat (dpy, PictStandardARGB32);
316
compLogMessage ("text", CompLogLevelError, "Couldn't get format.");
320
if (!initCairo (1, 1))
324
layout = pango_cairo_create_layout (cr);
327
compLogMessage ("text", CompLogLevelError,
328
"Couldn't create pango layout.");
332
font = pango_font_description_new ();
335
compLogMessage ("text", CompLogLevelError,
336
"Couldn't create font description.");
341
TextSurface::~TextSurface ()
344
g_object_unref (layout);
346
cairo_surface_destroy (surface);
350
pango_font_description_free (font);
357
XFreePixmap (screen->dpy (), pixmap);
364
CompText::renderText (CompString text,
365
const Attrib &attrib)
370
TEXT_SCREEN (screen);
375
if (!surface.valid ())
378
if (!(attrib.flags & NoAutoBinding) && !ts->gScreen)
381
if (surface.render (attrib, text))
383
if (!(attrib.flags & NoAutoBinding))
385
texture = GLTexture::bindPixmapToTexture (surface.mPixmap,
389
retval = !texture.empty ();
397
if (!retval && surface.mPixmap)
399
XFreePixmap (screen->dpy (), surface.mPixmap);
405
pixmap = surface.mPixmap;
406
width = surface.mWidth;
407
height = surface.mHeight;
413
CompText::renderWindowTitle (Window window,
414
bool withViewportNumber,
415
const CompText::Attrib &attrib)
419
TEXT_SCREEN (screen);
424
if (withViewportNumber)
427
CompPoint winViewport;
428
CompSize viewportSize;
430
title = ts->getWindowName (window);
435
w = screen->findWindow (window);
440
winViewport = w->defaultViewport ();
441
viewportSize = screen->vpSize ();
442
viewport = winViewport.y () * viewportSize.width () +
443
winViewport.x () + 1;
444
text = compPrintf ("%s -[%d]-", title.c_str (), viewport);
454
text = ts->getWindowName (window);
460
return renderText (text, attrib);
464
CompText::getPixmap ()
466
Pixmap retval = None;
468
if (texture.empty ())
478
CompText::getWidth () const
484
CompText::getHeight () const
490
CompText::draw (float x,
495
GLint oldBlendSrc, oldBlendDst;
497
if (texture.empty ())
500
glGetIntegerv (GL_BLEND_SRC, &oldBlendSrc);
501
glGetIntegerv (GL_BLEND_DST, &oldBlendDst);
503
wasBlend = glIsEnabled (GL_BLEND);
507
glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
509
glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
510
glColor4f (alpha, alpha, alpha, alpha);
512
for (unsigned int i = 0; i < texture.size (); i++)
514
GLTexture *tex = texture[i];
515
GLTexture::Matrix m = tex->matrix ();
517
tex->enable (GLTexture::Good);
521
glTexCoord2f (COMP_TEX_COORD_X (m, 0), COMP_TEX_COORD_Y (m, 0));
522
glVertex2f (x, y - height);
523
glTexCoord2f (COMP_TEX_COORD_X (m, 0), COMP_TEX_COORD_Y (m, height));
525
glTexCoord2f (COMP_TEX_COORD_X (m, width), COMP_TEX_COORD_Y (m, height));
526
glVertex2f (x + width, y);
527
glTexCoord2f (COMP_TEX_COORD_X (m, width), COMP_TEX_COORD_Y (m, 0));
528
glVertex2f (x + width, y - height);
535
glColor4usv (defaultColor);
538
glDisable (GL_BLEND);
539
glBlendFunc (oldBlendSrc, oldBlendDst);
542
CompText::CompText () :
549
CompText::~CompText ()
552
XFreePixmap (screen->dpy (), pixmap);
555
PrivateTextScreen::PrivateTextScreen (CompScreen *screen) :
556
PluginClassHandler <PrivateTextScreen, CompScreen, COMPIZ_TEXT_ABI> (screen),
557
gScreen (GLScreen::get (screen))
559
visibleNameAtom = XInternAtom (screen->dpy (), "_NET_WM_VISIBLE_NAME", 0);
560
utf8StringAtom = XInternAtom (screen->dpy (), "UTF8_STRING", 0);
561
wmNameAtom = XInternAtom (screen->dpy (), "_NET_WM_NAME", 0);
564
PrivateTextScreen::~PrivateTextScreen ()
569
TextPluginVTable::init ()
571
if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION))
575
p.uval = COMPIZ_TEXT_ABI;
576
screen->storeValue ("text_ABI", p);
582
TextPluginVTable::fini ()
584
screen->eraseValue ("text_ABI");