diff options
Diffstat (limited to 'matchbox2/theme-engines/mb-wm-theme-png.c')
-rw-r--r-- | matchbox2/theme-engines/mb-wm-theme-png.c | 1306 |
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; -} |