aboutsummaryrefslogtreecommitdiffstats
path: root/matchbox2/theme-engines/mb-wm-theme-png.c
diff options
context:
space:
mode:
Diffstat (limited to 'matchbox2/theme-engines/mb-wm-theme-png.c')
-rw-r--r--matchbox2/theme-engines/mb-wm-theme-png.c1306
1 files changed, 0 insertions, 1306 deletions
diff --git a/matchbox2/theme-engines/mb-wm-theme-png.c b/matchbox2/theme-engines/mb-wm-theme-png.c
deleted file mode 100644
index a747691..0000000
--- a/matchbox2/theme-engines/mb-wm-theme-png.c
+++ /dev/null
@@ -1,1306 +0,0 @@
-#include <math.h>
-#include <png.h>
-
-#include "mb-wm-theme-png.h"
-#include "mb-wm-theme-xml.h"
-
-#include <X11/Xft/Xft.h>
-
-#ifdef HAVE_XEXT
-#include <X11/extensions/shape.h>
-#endif
-
-static int
-mb_wm_theme_png_ximg (MBWMThemePng * theme, const char * img);
-
-static unsigned char*
-mb_wm_theme_png_load_file (const char *file, int *width, int *height);
-
-static void
-mb_wm_theme_png_paint_decor (MBWMTheme *theme, MBWMDecor *decor);
-
-static void
-mb_wm_theme_png_paint_button (MBWMTheme *theme, MBWMDecorButton *button);
-
-static void
-mb_wm_theme_png_get_decor_dimensions (MBWMTheme *, MBWindowManagerClient *,
- int*, int*, int*, int*);
-
-static MBWMDecor *
-mb_wm_theme_png_create_decor (MBWMTheme*, MBWindowManagerClient *,
- MBWMDecorType);
-
-static void
-mb_wm_theme_png_resize_decor (MBWMTheme *theme, MBWMDecor *decor);
-
-static void
-mb_wm_theme_png_get_button_size (MBWMTheme *, MBWMDecor *,
- MBWMDecorButtonType, int *, int *);
-
-static void
-mb_wm_theme_png_get_button_position (MBWMTheme *, MBWMDecor *,
- MBWMDecorButtonType,
- int *, int *);
-
-static void
-mb_wm_theme_png_class_init (MBWMObjectClass *klass)
-{
- MBWMThemeClass *t_class = MB_WM_THEME_CLASS (klass);
-
- t_class->paint_decor = mb_wm_theme_png_paint_decor;
- t_class->paint_button = mb_wm_theme_png_paint_button;
- t_class->decor_dimensions = mb_wm_theme_png_get_decor_dimensions;
- t_class->button_size = mb_wm_theme_png_get_button_size;
- t_class->button_position = mb_wm_theme_png_get_button_position;
- t_class->create_decor = mb_wm_theme_png_create_decor;
- t_class->resize_decor = mb_wm_theme_png_resize_decor;
-
-#if MBWM_WANT_DEBUG
- klass->klass_name = "MBWMThemePng";
-#endif
-}
-
-static void
-mb_wm_theme_png_destroy (MBWMObject *obj)
-{
- MBWMThemePng * theme = MB_WM_THEME_PNG (obj);
- Display * dpy = MB_WM_THEME (obj)->wm->xdpy;
-
- XRenderFreePicture (dpy, theme->xpic);
- XFreePixmap (dpy, theme->xdraw);
-
- if (theme->shape_mask)
- XFreePixmap (dpy, theme->shape_mask);
-}
-
-static int
-mb_wm_theme_png_init (MBWMObject *obj, va_list vap)
-{
- MBWMThemePng *p_theme = MB_WM_THEME_PNG (obj);
- MBWMTheme *theme = MB_WM_THEME (obj);
- MBWMObjectProp prop;
- char *img = NULL;
-#if USE_PANGO
- Display *xdpy = theme->wm->xdpy;
- int xscreen = theme->wm->xscreen;
-#endif
-
- prop = va_arg(vap, MBWMObjectProp);
- while (prop)
- {
- switch (prop)
- {
- case MBWMObjectPropThemeImg:
- img = va_arg(vap, char *);
- break;
- default:
- MBWMO_PROP_EAT (vap, prop);
- }
-
- prop = va_arg(vap, MBWMObjectProp);
- }
-
- if (!img || !mb_wm_theme_png_ximg (p_theme, img))
- return 0;
-
-#if USE_PANGO
- p_theme->context = pango_xft_get_context (xdpy, xscreen);
- p_theme->fontmap = pango_xft_get_font_map (xdpy, xscreen);
-#endif
-
- return 1;
-}
-
-int
-mb_wm_theme_png_class_type ()
-{
- static int type = 0;
-
- if (UNLIKELY(type == 0))
- {
- static MBWMObjectClassInfo info = {
- sizeof (MBWMThemePngClass),
- sizeof (MBWMThemePng),
- mb_wm_theme_png_init,
- mb_wm_theme_png_destroy,
- mb_wm_theme_png_class_init
- };
-
- type = mb_wm_object_register_class (&info, MB_WM_TYPE_THEME, 0);
- }
-
- return type;
-}
-
-struct DecorData
-{
- Pixmap xpix;
- Pixmap shape_mask;
- GC gc_mask;
- XftDraw *xftdraw;
- XftColor clr;
-#if USE_PANGO
- PangoFont *font;
-#else
- XftFont *font;
-#endif
-};
-
-static void
-decordata_free (MBWMDecor * decor, void *data)
-{
- struct DecorData * dd = data;
- Display * xdpy = decor->parent_client->wmref->xdpy;
-
- XFreePixmap (xdpy, dd->xpix);
-
- if (dd->shape_mask)
- XFreePixmap (xdpy, dd->shape_mask);
-
- if (dd->gc_mask)
- XFreeGC (xdpy, dd->gc_mask);
-
- XftDrawDestroy (dd->xftdraw);
-
-#if USE_PANGO
- if (dd->font)
- g_object_unref (dd->font);
-#else
- if (dd->font)
- XftFontClose (xdpy, dd->font);
-#endif
-
- free (dd);
-}
-
-struct ButtonData
-{
- Pixmap xpix_i;
- XftDraw *xftdraw_i;
- Pixmap xpix_a;
- XftDraw *xftdraw_a;
-};
-
-static void
-buttondata_free (MBWMDecorButton * button, void *data)
-{
- struct ButtonData * bd = data;
- Display * xdpy = button->decor->parent_client->wmref->xdpy;
-
- XFreePixmap (xdpy, bd->xpix_i);
- XftDrawDestroy (bd->xftdraw_i);
- XFreePixmap (xdpy, bd->xpix_a);
- XftDrawDestroy (bd->xftdraw_a);
-
- free (bd);
-}
-
-#if !USE_PANGO
-static XftFont *
-xft_load_font(MBWMDecor * decor, MBWMXmlDecor *d)
-{
- char desc[512];
- XftFont *font;
- Display * xdpy = decor->parent_client->wmref->xdpy;
- int xscreen = decor->parent_client->wmref->xscreen;
- int font_size = d->font_size ? d->font_size : 18;
-
- if (d->font_units == MBWMXmlFontUnitsPixels)
- {
- font_size = mb_wm_util_pixels_to_points (decor->parent_client->wmref,
- font_size);
- }
-
- snprintf (desc, sizeof (desc), "%s-%i",
- d->font_family ? d->font_family : "Sans",
- font_size);
-
- font = XftFontOpenName (xdpy, xscreen, desc);
-
- return font;
-}
-#endif
-
-static void
-mb_wm_theme_png_paint_button (MBWMTheme *theme, MBWMDecorButton *button)
-{
- MBWMDecor * decor;
- MBWMThemePng * p_theme = MB_WM_THEME_PNG (theme);
- MBWindowManagerClient * client;
- MBWMClientType c_type;;
- MBWMXmlClient * c;
- MBWMXmlDecor * d;
- MBWMXmlButton * b;
-
- /*
- * We do not paint inactive buttons, as they get painted with the decor
- */
- decor = button->decor;
- client = mb_wm_decor_get_parent (decor);
- c_type = MB_WM_CLIENT_CLIENT_TYPE (client);
-
- if ((c = mb_wm_xml_client_find_by_type (theme->xml_clients, c_type)) &&
- (d = mb_wm_xml_decor_find_by_type (c->decors, decor->type)) &&
- (b = mb_wm_xml_button_find_by_type (d->buttons, button->type)))
- {
- Display * xdpy = theme->wm->xdpy;
- int xscreen = theme->wm->xscreen;
- struct DecorData * ddata = mb_wm_decor_get_theme_data (decor);
- struct ButtonData * bdata;
- int x, y;
-
- if (!ddata)
- return;
-
- bdata = mb_wm_decor_button_get_theme_data (button);
-
- if (!bdata)
- {
- int a_x = b->active_x > -1 ? b->active_x : b->x;
- int a_y = b->active_y > -1 ? b->active_y : b->y;
-
- int i_x = b->inactive_x > -1 ? b->inactive_x : b->x;
- int i_y = b->inactive_y > -1 ? b->inactive_y : b->y;
-
- bdata = malloc (sizeof (struct ButtonData));
-
- bdata->xpix_a = XCreatePixmap(xdpy, decor->xwin,
- button->geom.width, button->geom.height,
- DefaultDepth(xdpy, xscreen));
-
- bdata->xftdraw_a = XftDrawCreate (xdpy, bdata->xpix_a,
- DefaultVisual (xdpy, xscreen),
- DefaultColormap (xdpy, xscreen));
-
- bdata->xpix_i = XCreatePixmap(xdpy, decor->xwin,
- button->geom.width, button->geom.height,
- DefaultDepth(xdpy, xscreen));
-
- bdata->xftdraw_i = XftDrawCreate (xdpy, bdata->xpix_i,
- DefaultVisual (xdpy, xscreen),
- DefaultColormap (xdpy, xscreen));
-
- /*
- * If the background color is set for the parent decor, we do a fill
- * with the parent color first, then composite the decor image over,
- * and finally composite the button image. (This way we can paint the
- * button with a simple PictOpSrc, rather than having to do
- * composting on each draw).
- */
- if (d->clr_bg.set)
- {
- XRenderColor rclr2;
-
- rclr2.red = (int)(d->clr_bg.r * (double)0xffff);
- rclr2.green = (int)(d->clr_bg.g * (double)0xffff);
- rclr2.blue = (int)(d->clr_bg.b * (double)0xffff);
-
- /* Fill the inactive image */
- XRenderFillRectangle (xdpy, PictOpSrc,
- XftDrawPicture (bdata->xftdraw_i), &rclr2,
- 0, 0, b->width, b->height);
-
- /* Composite the decor over */
- XRenderComposite (xdpy, PictOpOver,
- p_theme->xpic,
- None,
- XftDrawPicture (bdata->xftdraw_i),
- b->x, b->y, 0, 0, 0, 0, b->width, b->height);
-
- /* Copy inactive button to the active one */
- XRenderComposite (xdpy, PictOpSrc,
- XftDrawPicture (bdata->xftdraw_i),
- None,
- XftDrawPicture (bdata->xftdraw_a),
- 0, 0, 0, 0, 0, 0, b->width, b->height);
-
- /* Composite inactive and active image on top */
- XRenderComposite (xdpy, PictOpOver,
- p_theme->xpic,
- None,
- XftDrawPicture (bdata->xftdraw_i),
- i_x, i_y, 0, 0, 0, 0, b->width, b->height);
-
- XRenderComposite (xdpy, PictOpOver,
- p_theme->xpic,
- None,
- XftDrawPicture (bdata->xftdraw_a),
- a_x, a_y, 0, 0, 0, 0, b->width, b->height);
- }
- else
- {
- XRenderComposite (xdpy, PictOpSrc,
- p_theme->xpic,
- None,
- XftDrawPicture (bdata->xftdraw_i),
- i_x, i_y, 0, 0, 0, 0, b->width, b->height);
-
- XRenderComposite (xdpy, PictOpSrc,
- p_theme->xpic,
- None,
- XftDrawPicture (bdata->xftdraw_a),
- a_x, a_y, 0, 0, 0, 0, b->width, b->height);
- }
-
- mb_wm_decor_button_set_theme_data (button, bdata, buttondata_free);
- }
-
- /* Here we automagically determine if the button should be left or
- * right aligned in the case that a decor is expanded wider than
- * the template image. If the coordinate comes before the point
- * where decor padding is added, it's left aligned else it's
- * right aligned. If no padding hints were given in the theme.xml,
- * then we assume padding happens in the center.
- * Note: we look at pad_length because pad_offset could be 0
- */
- x = b->x - d->x;
- if (x > (d->pad_length ? d->pad_offset : d->width/2) )
- x = decor->geom.width - (d->x + d->width - b->x);
-
- y = b->y - d->y;
-
- XRenderComposite (xdpy, PictOpSrc,
- button->state == MBWMDecorButtonStatePressed ?
- XftDrawPicture (bdata->xftdraw_a) :
- XftDrawPicture (bdata->xftdraw_i),
- None,
- XftDrawPicture (ddata->xftdraw),
- 0, 0, 0, 0, x, y, b->width, b->height);
-
- XClearWindow (xdpy, decor->xwin);
- }
-}
-
-static void
-mb_wm_theme_png_resize_decor (MBWMTheme *theme, MBWMDecor *decor)
-{
- /*
- * Clear any data we have stored with the theme; this will force
- * resize on the next paint
- */
- mb_wm_decor_set_theme_data (decor, NULL, NULL);
-}
-
-static void
-mb_wm_theme_png_paint_decor (MBWMTheme *theme, MBWMDecor *decor)
-{
- MBWMThemePng * p_theme = MB_WM_THEME_PNG (theme);
- MBWindowManagerClient * client = decor->parent_client;
- MBWMClientType c_type = MB_WM_CLIENT_CLIENT_TYPE (client);
- MBWMXmlClient * c;
- MBWMXmlDecor * d;
- Display * xdpy = theme->wm->xdpy;
- int xscreen = theme->wm->xscreen;
- struct DecorData * data = mb_wm_decor_get_theme_data (decor);
- const char * title;
- int x, y;
- int operator = PictOpSrc;
- Bool shaped;
-
- if (!((c = mb_wm_xml_client_find_by_type (theme->xml_clients, c_type)) &&
- (d = mb_wm_xml_decor_find_by_type (c->decors, decor->type))))
- return;
-
-#ifdef HAVE_XEXT
- shaped = theme->shaped && c->shaped && !mb_wm_client_is_argb32 (client);
-#endif
-
- if (data && (mb_wm_decor_get_dirty_state (decor) & MBWMDecorDirtyTitle))
- {
- /*
- * If the decor title is dirty, and we already have the data,
- * free it and recreate (since the old title is already composited
- * in the cached image).
- */
- mb_wm_decor_set_theme_data (decor, NULL, NULL);
- data = NULL;
- }
-
- if (!data)
- {
- XRenderColor rclr;
-
- data = mb_wm_util_malloc0 (sizeof (struct DecorData));
- data->xpix = XCreatePixmap(xdpy, decor->xwin,
- decor->geom.width, decor->geom.height,
- DefaultDepth(xdpy, xscreen));
-
-
-#ifdef HAVE_XEXT
- if (shaped)
- {
- data->shape_mask =
- XCreatePixmap(xdpy, decor->xwin,
- decor->geom.width, decor->geom.height, 1);
-
- data->gc_mask = XCreateGC (xdpy, data->shape_mask, 0, NULL);
- }
-#endif
- data->xftdraw = XftDrawCreate (xdpy, data->xpix,
- DefaultVisual (xdpy, xscreen),
- DefaultColormap (xdpy, xscreen));
-
- /*
- * If the background color is set, we fill the pixmaps with it,
- * and then overlay the the PNG image over (this allows a theme
- * to provide a monochromatic PNG that can be toned, e.g., Sato)
- */
- if (d->clr_bg.set)
- {
- XRenderColor rclr2;
-
- operator = PictOpOver;
-
- rclr2.red = (int)(d->clr_bg.r * (double)0xffff);
- rclr2.green = (int)(d->clr_bg.g * (double)0xffff);
- rclr2.blue = (int)(d->clr_bg.b * (double)0xffff);
-
- XRenderFillRectangle (xdpy, PictOpSrc,
- XftDrawPicture (data->xftdraw), &rclr2,
- 0, 0,
- decor->geom.width, decor->geom.height);
- }
-
- rclr.red = 0;
- rclr.green = 0;
- rclr.blue = 0;
- rclr.alpha = 0xffff;
-
- if (d->clr_fg.set)
- {
- rclr.red = (int)(d->clr_fg.r * (double)0xffff);
- rclr.green = (int)(d->clr_fg.g * (double)0xffff);
- rclr.blue = (int)(d->clr_fg.b * (double)0xffff);
- }
-
- XftColorAllocValue (xdpy, DefaultVisual (xdpy, xscreen),
- DefaultColormap (xdpy, xscreen),
- &rclr, &data->clr);
-
-#if USE_PANGO
- {
- PangoFontDescription * pdesc;
- char desc[512];
-
- snprintf (desc, sizeof (desc), "%s %i%s",
- d->font_family ? d->font_family : "Sans",
- d->font_size ? d->font_size : 18,
- d->font_units == MBWMXmlFontUnitsPoints ? "" : "px");
-
- pdesc = pango_font_description_from_string (desc);
-
- data->font = pango_font_map_load_font (p_theme->fontmap,
- p_theme->context,
- pdesc);
-
- pango_font_description_free (pdesc);
- }
-#else
- data->font = xft_load_font (decor, d);
-#endif
- XSetWindowBackgroundPixmap(xdpy, decor->xwin, data->xpix);
-
- mb_wm_decor_set_theme_data (decor, data, decordata_free);
- }
-
- /*
- * Since we want to support things like rounded corners, but still
- * have the decor resizable, we need to paint it in stages
- *
- * We assume that the decor image is exact in it's major axis,
- * i.e., North and South decors provide image of the exactly correct
- * height, and West and East of width.
- */
- if (decor->type == MBWMDecorTypeNorth ||
- decor->type == MBWMDecorTypeSouth)
- {
- if (decor->geom.width < d->width)
- {
- /* The decor is smaller than the template, cut bit from the
- * midle
- */
- int width1 = decor->geom.width / 2;
- int width2 = decor->geom.width - width1;
- int x2 = d->x + d->width - width2;
-
- XRenderComposite(xdpy, operator,
- p_theme->xpic,
- None,
- XftDrawPicture (data->xftdraw),
- d->x, d->y, 0, 0, 0, 0,
- width1, d->height);
-
- XRenderComposite(xdpy, operator,
- p_theme->xpic,
- None,
- XftDrawPicture (data->xftdraw),
- x2 , d->y, 0, 0,
- width1, 0,
- width2, d->height);
-
-#ifdef HAVE_XEXT
- if (shaped)
- {
- XCopyArea (xdpy, p_theme->shape_mask, data->shape_mask,
- data->gc_mask,
- d->x, d->y, width1, d->height, 0, 0);
- XCopyArea (xdpy, p_theme->shape_mask, data->shape_mask,
- data->gc_mask,
- x2, d->y, width2, d->height, width1, 0);
- }
-#endif
- }
- else if (decor->geom.width == d->width)
- {
- /* Exact match */
- XRenderComposite(xdpy, operator,
- p_theme->xpic,
- None,
- XftDrawPicture (data->xftdraw),
- d->x, d->y, 0, 0,
- 0, 0, d->width, d->height);
-
-#ifdef HAVE_XEXT
- if (shaped)
- {
- XCopyArea (xdpy, p_theme->shape_mask, data->shape_mask,
- data->gc_mask,
- d->x, d->y, d->width, d->height, 0, 0);
- }
-#endif
- }
- else
- {
- /* The decor is bigger than the template, draw extra bit from
- * the middle
- */
- int pad_offset = d->pad_offset;
- int pad_length = d->pad_length;
- int gap_length = decor->geom.width - d->width;
-
- if (!pad_length)
- {
- pad_length =
- decor->geom.width > 30 ? 10 : decor->geom.width / 4 + 1;
- pad_offset = (d->width / 2) - (pad_length / 2);
- }
-
- XRenderComposite(xdpy, operator,
- p_theme->xpic,
- None,
- XftDrawPicture (data->xftdraw),
- d->x, d->y, 0, 0,
- 0, 0,
- pad_offset, d->height);
-
- /* TODO: can we do this as one scaled operation? */
- for (x = pad_offset; x < pad_offset + gap_length; x += pad_length)
- XRenderComposite(xdpy, operator,
- p_theme->xpic,
- None,
- XftDrawPicture (data->xftdraw),
- d->x + pad_offset, d->y, 0, 0,
- x, 0,
- pad_length,
- d->height);
-
- XRenderComposite(xdpy, operator,
- p_theme->xpic,
- None,
- XftDrawPicture (data->xftdraw),
- d->x + pad_offset, d->y, 0, 0,
- pad_offset + gap_length, 0,
- d->width - pad_offset, d->height);
-
-#ifdef HAVE_XEXT
- if (shaped)
- {
- XCopyArea (xdpy, p_theme->shape_mask, data->shape_mask,
- data->gc_mask,
- d->x, d->y,
- pad_offset, d->height,
- 0, 0);
-
- for (x = pad_offset; x < pad_offset + gap_length; x += pad_length)
- XCopyArea (xdpy, p_theme->shape_mask, data->shape_mask,
- data->gc_mask,
- d->x + pad_offset, d->y,
- d->width - pad_offset, d->height,
- x, 0);
-
- XCopyArea (xdpy, p_theme->shape_mask, data->shape_mask,
- data->gc_mask,
- d->x + pad_offset, d->y,
- d->width - pad_offset, d->height,
- pad_offset + gap_length, 0);
- }
-#endif
- }
- }
- else
- {
- if (decor->geom.height < d->height)
- {
- /* The decor is smaller than the template, cut bit from the
- * midle
- */
- int height1 = decor->geom.height / 2;
- int height2 = decor->geom.height - height1;
- int y2 = d->y + d->height - height2;
-
- XRenderComposite(xdpy, operator,
- p_theme->xpic,
- None,
- XftDrawPicture (data->xftdraw),
- d->x, d->y, 0, 0,
- 0, 0,
- d->width, height1);
-
- XRenderComposite(xdpy, operator,
- p_theme->xpic,
- None,
- XftDrawPicture (data->xftdraw),
- d->x , y2, 0, 0,
- 0, height1,
- d->width, height2);
-
-#ifdef HAVE_XEXT
- if (shaped)
- {
- XCopyArea (xdpy, p_theme->shape_mask, data->shape_mask,
- data->gc_mask,
- d->x, d->y, d->width, height1, 0, 0);
- XCopyArea (xdpy, p_theme->shape_mask, data->shape_mask,
- data->gc_mask,
- d->x, y2, d->width, height2, 0, height1);
- }
-#endif
- }
- else if (decor->geom.height == d->height)
- {
- /* Exact match */
- XRenderComposite(xdpy, operator,
- p_theme->xpic,
- None,
- XftDrawPicture (data->xftdraw),
- d->x, d->y, 0, 0,
- 0, 0,
- d->width, d->height);
-
-#ifdef HAVE_XEXT
- if (shaped)
- {
- XCopyArea (xdpy, p_theme->shape_mask, data->shape_mask,
- data->gc_mask,
- d->x, d->y, d->width, d->height, 0, 0);
- }
-#endif
- }
- else
- {
- /* The decor is bigger than the template, draw extra bit from
- * the middle
- */
- int pad_offset = d->pad_offset;
- int pad_length = d->pad_length;
- int gap_length = decor->geom.height - d->height;
-
- if (!pad_length)
- {
- pad_length =
- decor->geom.height > 30 ? 10 : decor->geom.height / 4 + 1;
- pad_offset = (d->height / 2) - (pad_length / 2);
- }
-
- XRenderComposite(xdpy, operator,
- p_theme->xpic,
- None,
- XftDrawPicture (data->xftdraw),
- d->x, d->y, 0, 0, 0, 0,
- d->width, pad_offset);
-
- /* TODO: can we do this as one scaled operation? */
- for (y = pad_offset; y < pad_offset + gap_length; y += pad_length)
- XRenderComposite(xdpy, operator,
- p_theme->xpic,
- None,
- XftDrawPicture (data->xftdraw),
- d->x, d->y + pad_offset, 0, 0, 0, y,
- d->width,
- pad_length);
-
- XRenderComposite(xdpy, operator,
- p_theme->xpic,
- None,
- XftDrawPicture (data->xftdraw),
- d->x , d->y + pad_offset, 0, 0,
- 0, pad_offset + gap_length,
- d->width, d->height - pad_offset);
-
-#ifdef HAVE_XEXT
- if (shaped)
- {
- XCopyArea (xdpy, p_theme->shape_mask, data->shape_mask,
- data->gc_mask,
- d->x, d->y,
- d->width, pad_offset,
- 0, 0);
-
- for (y = pad_offset; y < pad_offset + gap_length; y += pad_length)
- XCopyArea (xdpy, p_theme->shape_mask, data->shape_mask,
- data->gc_mask,
- d->x, d->y + pad_offset,
- d->width, pad_length,
- 0, y);
-
- XCopyArea (xdpy, p_theme->shape_mask, data->shape_mask,
- data->gc_mask,
- d->x, d->y + pad_offset,
- d->width, d->height - pad_offset,
- 0, pad_offset + gap_length);
- }
-#endif
- }
- }
-
- if (d->show_title &&
- (title = mb_wm_client_get_name (client)) &&
- data->font)
- {
- XRectangle rec;
-
- int pack_start_x = mb_wm_decor_get_pack_start_x (decor);
- int pack_end_x = mb_wm_decor_get_pack_end_x (decor);
- int west_width = mb_wm_client_frame_west_width (client);
- int y, ascent, descent;
- int len = strlen (title);
-
-#if USE_PANGO
- PangoFontMetrics * mtx;
- PangoGlyphString * glyphs;
- GList * items, *l;
- PangoRectangle rect;
- int xoff = 0;
-
- mtx = pango_font_get_metrics (data->font, NULL);
-
- ascent = PANGO_PIXELS (pango_font_metrics_get_ascent (mtx));
- descent = PANGO_PIXELS (pango_font_metrics_get_descent (mtx));
-
- pango_font_metrics_unref (mtx);
-#else
- ascent = data->font->ascent;
- descent = data->font->descent;
-#endif
-
- y = (decor->geom.height - (ascent + descent)) / 2 + ascent;
-
- rec.x = 0;
- rec.y = 0;
- rec.width = pack_end_x - 2;
- rec.height = d->height;
-
- XftDrawSetClipRectangles (data->xftdraw, 0, 0, &rec, 1);
-
-#if USE_PANGO
- glyphs = pango_glyph_string_new ();
-
- /*
- * Run the pango rendering pipeline on this text and draw with
- * the xft backend (why Pango does not provide a convenience
- * API for something as common as drawing a string escapes me).
- */
- items = pango_itemize (p_theme->context, title, 0, len, NULL, NULL);
-
- l = items;
- while (l)
- {
- PangoItem * item = l->data;
-
- item->analysis.font = data->font;
-
- pango_shape (title, len, &item->analysis, glyphs);
-
- pango_xft_render (data->xftdraw,
- &data->clr,
- data->font,
- glyphs,
- xoff + west_width + pack_start_x, y);
-
- /* Advance position */
- pango_glyph_string_extents (glyphs, data->font, NULL, &rect);
- xoff += PANGO_PIXELS (rect.width);
-
- l = l->next;
- }
-
- if (glyphs)
- pango_glyph_string_free (glyphs);
-
- g_list_free (items);
-#else
- XftDrawStringUtf8(data->xftdraw,
- &data->clr,
- data->font,
- west_width + pack_start_x, y,
- title, len);
-#endif
-
- /* Unset the clipping rectangle */
- rec.width = decor->geom.width;
- rec.height = decor->geom.height;
-
- XftDrawSetClipRectangles (data->xftdraw, 0, 0, &rec, 1);
- }
-
-#ifdef HAVE_XEXT
- if (shaped)
- {
- XShapeCombineMask (xdpy, decor->xwin,
- ShapeBounding, 0, 0,
- data->shape_mask, ShapeSet);
-
- XShapeCombineShape (xdpy,
- client->xwin_frame,
- ShapeBounding, decor->geom.x, decor->geom.y,
- decor->xwin,
- ShapeBounding, ShapeUnion);
- }
-#endif
- XClearWindow (xdpy, decor->xwin);
-}
-
-static void
-construct_buttons (MBWMThemePng * theme, MBWMDecor * decor, MBWMXmlDecor *d)
-{
- MBWindowManagerClient *client = decor->parent_client;
- MBWindowManager *wm = client->wmref;
- MBWMDecorButton *button;
-
- if (d)
- {
- MBWMList * l = d->buttons;
- while (l)
- {
- MBWMXmlButton * b = l->data;
-
- button = mb_wm_decor_button_stock_new (wm,
- b->type,
- b->packing,
- decor,
- 0);
-
- mb_wm_decor_button_show (button);
- mb_wm_object_unref (MB_WM_OBJECT (button));
-
- l = l->next;
- }
- }
-}
-
-static MBWMDecor *
-mb_wm_theme_png_create_decor (MBWMTheme *theme,
- MBWindowManagerClient *client,
- MBWMDecorType type)
-{
- MBWMClientType c_type = MB_WM_CLIENT_CLIENT_TYPE (client);
- MBWMDecor *decor = NULL;
- MBWindowManager *wm = client->wmref;
- MBWMXmlClient *c;
-
- if ((c = mb_wm_xml_client_find_by_type (theme->xml_clients, c_type)))
- {
- MBWMXmlDecor *d;
-
- d = mb_wm_xml_decor_find_by_type (c->decors, type);
-
- if (d)
- {
- decor = mb_wm_decor_new (wm, type);
- decor->absolute_packing = True;
- mb_wm_decor_attach (decor, client);
- construct_buttons (MB_WM_THEME_PNG (theme), decor, d);
- }
- }
-
- return decor;
-}
-
-static void
-mb_wm_theme_png_get_button_size (MBWMTheme *theme,
- MBWMDecor *decor,
- MBWMDecorButtonType type,
- int *width,
- int *height)
-{
- MBWindowManagerClient * client = decor->parent_client;
- MBWMClientType c_type = MB_WM_CLIENT_CLIENT_TYPE (client);
- MBWMThemePng *p_theme = MB_WM_THEME_PNG (theme);
- MBWMXmlClient * c;
- MBWMXmlDecor * d;
-
- /* FIXME -- assumes button on the north decor only */
- if ((c = mb_wm_xml_client_find_by_type (theme->xml_clients, c_type)) &&
- (d = mb_wm_xml_decor_find_by_type (c->decors, decor->type)))
- {
- MBWMXmlButton * b = mb_wm_xml_button_find_by_type (d->buttons, type);
-
- if (b)
- {
- if (width)
- *width = b->width;
-
- if (height)
- *height = b->height;
-
- return;
- }
- }
-
- if (width)
- *width = 0;
-
- if (height)
- *height = 0;
-}
-
-static void
-mb_wm_theme_png_get_button_position (MBWMTheme *theme,
- MBWMDecor *decor,
- MBWMDecorButtonType type,
- int *x,
- int *y)
-{
- MBWindowManagerClient * client = decor->parent_client;
- MBWMClientType c_type = MB_WM_CLIENT_CLIENT_TYPE (client);
- MBWMThemePng *p_theme = MB_WM_THEME_PNG (theme);
- MBWMXmlClient * c;
- MBWMXmlDecor * d;
-
- /* FIXME -- assumes button on the north decor only */
- if ((c = mb_wm_xml_client_find_by_type (theme->xml_clients, c_type)) &&
- (d = mb_wm_xml_decor_find_by_type (c->decors, decor->type)))
- {
- MBWMXmlButton * b = mb_wm_xml_button_find_by_type (d->buttons, type);
-
- if (b)
- {
- if (x)
- {
- int button_x;
-
- /* Here we automagically determine if the button should be left or
- * right aligned in the case that a decor is expanded wider than
- * the template image. If the coordinate comes before the point
- * where decor padding is added, it's left aligned else it's
- * right aligned. If no padding hints were given in the theme.xml,
- * then we assume padding happens in the center.
- * Note: we look at pad_length because pad_offset could be 0
- */
- button_x = b->x - d->x;
- if (button_x > (d->pad_length ? d->pad_offset : d->width/2) )
- button_x = decor->geom.width - (d->x + d->width - b->x);
-
- *x = button_x;
- }
-
- if (y)
- *y = b->y - d->y;
-
- return;
- }
- }
-
- if (x)
- *x = 0;
-
- if (y)
- *y = 0;
-}
-
-static void
-mb_wm_theme_png_get_decor_dimensions (MBWMTheme *theme,
- MBWindowManagerClient *client,
- int *north,
- int *south,
- int *west,
- int *east)
-{
- MBWMClientType c_type = MB_WM_CLIENT_CLIENT_TYPE (client);
- MBWMThemePng *p_theme = MB_WM_THEME_PNG (theme);
- MBWMXmlClient * c;
- MBWMXmlDecor * d;
-
- /* FIXME -- assumes button on the north decor only */
- if ((c = mb_wm_xml_client_find_by_type (theme->xml_clients, c_type)))
- {
- if (north)
- {
- d = mb_wm_xml_decor_find_by_type (c->decors, MBWMDecorTypeNorth);
-
- if (d)
- *north = d->height;
- else
- *north = 0;
- }
-
- if (south)
- {
- d = mb_wm_xml_decor_find_by_type (c->decors, MBWMDecorTypeSouth);
-
- if (d)
- *south = d->height;
- else
- *south = 0;
- }
-
- if (west)
- {
- d = mb_wm_xml_decor_find_by_type (c->decors, MBWMDecorTypeWest);
-
- if (d)
- *west = d->width;
- else
- *west = 0;
- }
-
- if (east)
- {
- d = mb_wm_xml_decor_find_by_type (c->decors, MBWMDecorTypeEast);
-
- if (d)
- *east = d->width;
- else
- *east = 0;
- }
-
- return;
- }
-
- if (north)
- *north = 0;
-
- if (south)
- *south = 0;
-
- if (west)
- *west = 0;
-
- if (east)
- *east = 0;
-}
-
-/*
- * From matchbox-keyboard
- */
-static unsigned char*
-mb_wm_theme_png_load_file (const char *file,
- int *width,
- int *height)
-{
- FILE *fd;
- unsigned char *data;
- unsigned char header[8];
- int bit_depth, color_type;
-
- png_uint_32 png_width, png_height, i, rowbytes;
- png_structp png_ptr;
- png_infop info_ptr;
- png_bytep *row_pointers;
-
- if ((fd = fopen (file, "rb")) == NULL)
- return NULL;
-
- fread (header, 1, 8, fd);
- if (!png_check_sig (header, 8))
- {
- fclose(fd);
- return NULL;
- }
-
- png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
- if (!png_ptr)
- {
- fclose(fd);
- return NULL;
- }
-
- info_ptr = png_create_info_struct(png_ptr);
- if (!info_ptr)
- {
- png_destroy_read_struct (&png_ptr, NULL, NULL);
- fclose(fd);
- return NULL;
- }
-
- if (setjmp (png_ptr->jmpbuf))
- {
- png_destroy_read_struct( &png_ptr, &info_ptr, NULL);
- fclose(fd);
- return NULL;
- }
-
- png_init_io (png_ptr, fd);
- png_set_sig_bytes (png_ptr, 8);
- png_read_info (png_ptr, info_ptr);
- png_get_IHDR (png_ptr, info_ptr, &png_width, &png_height, &bit_depth,
- &color_type, NULL, NULL, NULL);
-
- *width = (int) png_width;
- *height = (int) png_height;
-
- if (bit_depth == 16)
- png_set_strip_16(png_ptr);
-
- if (bit_depth < 8)
- png_set_packing(png_ptr);
-
- if (color_type == PNG_COLOR_TYPE_GRAY ||
- color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
- png_set_gray_to_rgb(png_ptr);
-
- /* Add alpha */
- if (color_type == PNG_COLOR_TYPE_GRAY ||
- color_type == PNG_COLOR_TYPE_RGB)
- png_set_add_alpha (png_ptr, 0xff, PNG_FILLER_AFTER);
-
- if (color_type == PNG_COLOR_TYPE_PALETTE ||
- png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
- png_set_expand (png_ptr);
-
- png_read_update_info (png_ptr, info_ptr);
-
- /* allocate space for data and row pointers */
- rowbytes = png_get_rowbytes (png_ptr, info_ptr);
- data = (unsigned char*) malloc ((rowbytes * (*height + 1)));
- row_pointers = (png_bytep *) malloc ((*height) * sizeof (png_bytep));
-
- if (!data || !row_pointers)
- {
- png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
-
- if (data)
- free (data);
-
- if (row_pointers)
- free (row_pointers);
-
- return NULL;
- }
-
- for (i = 0; i < *height; i++)
- row_pointers[i] = data + i * rowbytes;
-
- png_read_image (png_ptr, row_pointers);
- png_read_end (png_ptr, NULL);
-
- free (row_pointers);
- png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
- fclose(fd);
-
- return data;
-}
-
-static int
-mb_wm_theme_png_ximg (MBWMThemePng * theme, const char * img)
-{
- MBWindowManager * wm = MB_WM_THEME (theme)->wm;
- Display * dpy = wm->xdpy;
- int screen = wm->xscreen;
-
- XImage * ximg, * shape_img;
- GC gc, gcm;
- int x;
- int y;
- int width;
- int height;
- XRenderPictFormat *ren_fmt;
- XRenderPictureAttributes ren_attr;
- unsigned char * p;
- unsigned char * png_data = mb_wm_theme_png_load_file (img, &width, &height);
- Bool shaped = MB_WM_THEME (theme)->shaped;
-
- if (!png_data || !width || !height)
- return 0;
-
- ren_fmt = XRenderFindStandardFormat(dpy, PictStandardARGB32);
-
- theme->xdraw =
- XCreatePixmap (dpy, RootWindow(dpy,screen), width, height, ren_fmt->depth);
-
- if (shaped)
- theme->shape_mask =
- XCreatePixmap (dpy, RootWindow(dpy,screen), width, height, 1);
-
- XSync (dpy, False);
-
- ren_attr.dither = True;
- ren_attr.component_alpha = True;
- ren_attr.repeat = False;
-
- gc = XCreateGC (dpy, theme->xdraw, 0, NULL);
-
- if (shaped)
- gcm = XCreateGC (dpy, theme->shape_mask, 0, NULL);
-
- ximg = XCreateImage (dpy, DefaultVisual (dpy, screen),
- ren_fmt->depth, ZPixmap,
- 0, NULL, width, height, 32, 0);
-
- ximg->data = malloc (ximg->bytes_per_line * ximg->height);
-
- if (shaped)
- {
- shape_img = XCreateImage (dpy, DefaultVisual (dpy, screen),
- 1, ZPixmap,
- 0, NULL, width, height, 8, 0);
-
- shape_img->data = malloc (shape_img->bytes_per_line * shape_img->height);
- }
-
- p = png_data;
-
- for (y = 0; y < height; y++)
- for (x = 0; x < width; x++)
- {
- unsigned char a, r, g, b;
- r = *p++; g = *p++; b = *p++; a = *p++;
- r = (r * (a + 1)) / 256;
- g = (g * (a + 1)) / 256;
- b = (b * (a + 1)) / 256;
-
- XPutPixel (ximg, x, y, (a << 24) | (r << 16) | (g << 8) | b);
-
- if (shaped)
- {
- XPutPixel (shape_img, x, y, a ? 1 : 0);
- }
- }
-
- XPutImage (dpy, theme->xdraw, gc, ximg, 0, 0, 0, 0, width, height);
-
- if (shaped)
- XPutImage (dpy, theme->shape_mask, gcm, shape_img,
- 0, 0, 0, 0, width, height);
-
- theme->xpic = XRenderCreatePicture (dpy, theme->xdraw, ren_fmt,
- CPRepeat|CPDither|CPComponentAlpha,
- &ren_attr);
-
- free (ximg->data);
- ximg->data = NULL;
- XDestroyImage (ximg);
- XFreeGC (dpy, gc);
-
- if (shaped)
- {
- free (shape_img->data);
- shape_img->data = NULL;
- XDestroyImage (shape_img);
- XFreeGC (dpy, gcm);
- }
-
- free (png_data);
-
- return 1;
-}