aboutsummaryrefslogtreecommitdiffstats
path: root/matchbox/theme-engines/mb-wm-theme-simple.c
diff options
context:
space:
mode:
Diffstat (limited to 'matchbox/theme-engines/mb-wm-theme-simple.c')
-rw-r--r--matchbox/theme-engines/mb-wm-theme-simple.c766
1 files changed, 766 insertions, 0 deletions
diff --git a/matchbox/theme-engines/mb-wm-theme-simple.c b/matchbox/theme-engines/mb-wm-theme-simple.c
new file mode 100644
index 0000000..db4df7c
--- /dev/null
+++ b/matchbox/theme-engines/mb-wm-theme-simple.c
@@ -0,0 +1,766 @@
+#include "mb-wm-theme-simple.h"
+#include "mb-wm-theme-xml.h"
+
+#include <X11/Xft/Xft.h>
+
+#define FRAME_TITLEBAR_HEIGHT 20
+#define FRAME_EDGE_SIZE 3
+
+static void
+mb_wm_theme_simple_paint_decor (MBWMTheme *theme, MBWMDecor *decor);
+static void
+mb_wm_theme_simple_paint_button (MBWMTheme *theme, MBWMDecorButton *button);
+static void
+mb_wm_theme_simple_get_decor_dimensions (MBWMTheme *, MBWindowManagerClient *,
+ int *, int *, int *, int *);
+static void
+mb_wm_theme_simple_get_button_size (MBWMTheme *, MBWMDecor *,
+ MBWMDecorButtonType, int *, int *);
+
+static void
+mb_wm_theme_simple_get_button_position (MBWMTheme *, MBWMDecor *,
+ MBWMDecorButtonType, int*, int*);
+
+static MBWMDecor *
+mb_wm_theme_simple_create_decor (MBWMTheme *, MBWindowManagerClient *,
+ MBWMDecorType);
+
+
+static void
+mb_wm_theme_simple_class_init (MBWMObjectClass *klass)
+{
+ MBWMThemeClass *t_class = MB_WM_THEME_CLASS (klass);
+
+ t_class->paint_decor = mb_wm_theme_simple_paint_decor;
+ t_class->paint_button = mb_wm_theme_simple_paint_button;
+ t_class->decor_dimensions = mb_wm_theme_simple_get_decor_dimensions;
+ t_class->button_size = mb_wm_theme_simple_get_button_size;
+ t_class->button_position = mb_wm_theme_simple_get_button_position;
+ t_class->create_decor = mb_wm_theme_simple_create_decor;
+
+#ifdef MBWM_WANT_DEBUG
+ klass->klass_name = "MBWMThemeSimple";
+#endif
+}
+
+static void
+mb_wm_theme_simple_destroy (MBWMObject *obj)
+{
+}
+
+static int
+mb_wm_theme_simple_init (MBWMObject *obj, va_list vap)
+{
+ MBWMTheme *theme = MB_WM_THEME (obj);
+
+ /*
+ * We do not support shaped windows, so reset the flag to avoid unnecessary
+ * ops if the xml theme set this
+ */
+ theme->shaped = False;
+
+ return 1;
+}
+
+int
+mb_wm_theme_simple_class_type ()
+{
+ static int type = 0;
+
+ if (UNLIKELY(type == 0))
+ {
+ static MBWMObjectClassInfo info = {
+ sizeof (MBWMThemeSimpleClass),
+ sizeof (MBWMThemeSimple),
+ mb_wm_theme_simple_init,
+ mb_wm_theme_simple_destroy,
+ mb_wm_theme_simple_class_init
+ };
+
+ type = mb_wm_object_register_class (&info, MB_WM_TYPE_THEME, 0);
+ }
+
+ return type;
+}
+
+static void
+construct_buttons (MBWMThemeSimple * 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;
+ }
+
+ return;
+ }
+
+ button = mb_wm_decor_button_stock_new (wm,
+ MBWMDecorButtonClose,
+ MBWMDecorButtonPackEnd,
+ decor,
+ 0);
+
+ mb_wm_decor_button_show (button);
+ mb_wm_object_unref (MB_WM_OBJECT (button));
+
+#if 0
+ /*
+ * We probably do not want this in the default client, but for now
+ * it is useful for testing purposes
+ */
+ button = mb_wm_decor_button_stock_new (wm,
+ MBWMDecorButtonFullscreen,
+ MBWMDecorButtonPackEnd,
+ decor,
+ 0);
+
+ mb_wm_decor_button_show (button);
+ mb_wm_object_unref (MB_WM_OBJECT (button));
+
+ button = mb_wm_decor_button_stock_new (wm,
+ MBWMDecorButtonHelp,
+ MBWMDecorButtonPackEnd,
+ decor,
+ 0);
+
+ mb_wm_decor_button_show (button);
+ mb_wm_object_unref (MB_WM_OBJECT (button));
+
+ button = mb_wm_decor_button_stock_new (wm,
+ MBWMDecorButtonAccept,
+ MBWMDecorButtonPackEnd,
+ decor,
+ 0);
+
+ mb_wm_decor_button_show (button);
+ mb_wm_object_unref (MB_WM_OBJECT (button));
+
+ button = mb_wm_decor_button_stock_new (wm,
+ MBWMDecorButtonMinimize,
+ MBWMDecorButtonPackEnd,
+ decor,
+ 0);
+
+ mb_wm_decor_button_show (button);
+ mb_wm_object_unref (MB_WM_OBJECT (button));
+
+ button = mb_wm_decor_button_stock_new (wm,
+ MBWMDecorButtonMenu,
+ MBWMDecorButtonPackStart,
+ decor,
+ 0);
+
+ mb_wm_decor_button_show (button);
+ mb_wm_object_unref (MB_WM_OBJECT (button));
+#endif
+}
+
+struct DecorData
+{
+ Pixmap xpix;
+ XftDraw *xftdraw;
+ XftColor clr;
+ XftFont *font;
+};
+
+static void
+decordata_free (MBWMDecor * decor, void *data)
+{
+ struct DecorData * dd = data;
+ Display * xdpy = decor->parent_client->wmref->xdpy;
+
+ XFreePixmap (xdpy, dd->xpix);
+
+ XftDrawDestroy (dd->xftdraw);
+
+ if (dd->font)
+ XftFontClose (xdpy, dd->font);
+
+ free (dd);
+}
+
+static struct DecorData *
+decordata_new ()
+{
+ return mb_wm_util_malloc0 (sizeof (struct DecorData));
+}
+
+static MBWMDecor *
+mb_wm_theme_simple_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 (MB_WM_THEME (theme)->xml_clients &&
+ (c = mb_wm_xml_client_find_by_type (MB_WM_THEME (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);
+ mb_wm_decor_attach (decor, client);
+ construct_buttons (MB_WM_THEME_SIMPLE (theme), decor, d);
+ }
+
+ return decor;
+ }
+
+ switch (c_type)
+ {
+ case MBWMClientTypeApp:
+ switch (type)
+ {
+ case MBWMDecorTypeNorth:
+ decor = mb_wm_decor_new (wm, type);
+ mb_wm_decor_attach (decor, client);
+ construct_buttons (MB_WM_THEME_SIMPLE (theme), decor, NULL);
+ break;
+ default:
+ decor = mb_wm_decor_new (wm, type);
+ mb_wm_decor_attach (decor, client);
+ }
+ break;
+
+ case MBWMClientTypeDialog:
+ case MBWMClientTypePanel:
+ case MBWMClientTypeDesktop:
+ case MBWMClientTypeInput:
+ default:
+ decor = mb_wm_decor_new (wm, type);
+ mb_wm_decor_attach (decor, client);
+ }
+
+ return decor;
+}
+
+static void
+mb_wm_theme_simple_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);
+ 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;
+ }
+ }
+
+ /*
+ * These are defaults when no theme description was loaded
+ */
+ switch (c_type)
+ {
+ case MBWMClientTypeApp:
+ case MBWMClientTypeDialog:
+ case MBWMClientTypePanel:
+ case MBWMClientTypeDesktop:
+ case MBWMClientTypeInput:
+ default:
+ if (width)
+ *width = FRAME_TITLEBAR_HEIGHT-4;
+
+ if (height)
+ *height = FRAME_TITLEBAR_HEIGHT-4;
+ }
+}
+
+static void
+mb_wm_theme_simple_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);
+ 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)
+ if (b->x >= 0)
+ *x = b->x;
+ else
+ *x = 2;
+
+ if (y)
+ if (b->y >= 0)
+ *y = b->y;
+ else
+ *y = 2;
+
+ return;
+ }
+ }
+
+ if (x)
+ *x = 2;
+
+ if (y)
+ *y = 2;
+}
+
+static void
+mb_wm_theme_simple_get_decor_dimensions (MBWMTheme *theme,
+ MBWindowManagerClient *client,
+ int *north,
+ int *south,
+ int *west,
+ int *east)
+{
+ MBWMThemeSimple *c_theme = MB_WM_THEME_SIMPLE (theme);
+ MBWMClientType c_type = MB_WM_CLIENT_CLIENT_TYPE (client);
+ MBWMXmlClient * c;
+ MBWMXmlDecor * d;
+
+ if ((c = mb_wm_xml_client_find_by_type (theme->xml_clients, c_type)))
+ {
+ if (north)
+ if ((d = mb_wm_xml_decor_find_by_type (c->decors,MBWMDecorTypeNorth)))
+ *north = d->height;
+ else
+ *north = FRAME_TITLEBAR_HEIGHT;
+
+ if (south)
+ if ((d = mb_wm_xml_decor_find_by_type (c->decors,MBWMDecorTypeSouth)))
+ *south = d->height;
+ else
+ *south = FRAME_EDGE_SIZE;
+
+ if (west)
+ if ((d = mb_wm_xml_decor_find_by_type (c->decors, MBWMDecorTypeWest)))
+ *west = d->width;
+ else
+ *west = FRAME_EDGE_SIZE;
+
+ if (east)
+ if ((d = mb_wm_xml_decor_find_by_type (c->decors, MBWMDecorTypeEast)))
+ *east = d->width;
+ else
+ *east = FRAME_EDGE_SIZE;
+
+ return;
+ }
+
+ /*
+ * These are defaults when no theme description was loaded
+ */
+ switch (c_type)
+ {
+ case MBWMClientTypeApp:
+ if (north)
+ *north = FRAME_TITLEBAR_HEIGHT;
+
+ if (south)
+ *south = FRAME_EDGE_SIZE;
+
+ if (west)
+ *west = FRAME_EDGE_SIZE;
+
+ if (east)
+ *east = FRAME_EDGE_SIZE;
+ break;
+
+ case MBWMClientTypeDialog:
+ case MBWMClientTypePanel:
+ case MBWMClientTypeDesktop:
+ case MBWMClientTypeInput:
+ default:
+ if (north)
+ *north = 0;
+
+ if (south)
+ *south = 0;
+
+ if (west)
+ *west = 0;
+
+ if (east)
+ *east = 0;
+ }
+}
+
+static unsigned long
+pixel_from_clr (Display * dpy, int screen, MBWMColor * clr)
+{
+ XColor xcol;
+
+ xcol.red = (int)(clr->r * (double)0xffff);
+ xcol.green = (int)(clr->b * (double)0xffff);
+ xcol.blue = (int)(clr->b * (double)0xffff);
+ xcol.flags = DoRed|DoGreen|DoBlue;
+
+ XAllocColor (dpy, DefaultColormap (dpy, screen), &xcol);
+
+ return xcol.pixel;
+}
+
+static XftFont *
+xft_load_font (MBWMDecor * decor, const char * family, int size)
+{
+ char desc[512];
+ XftFont *font;
+ Display * xdpy = decor->parent_client->wmref->xdpy;
+ int xscreen = decor->parent_client->wmref->xscreen;
+
+ snprintf (desc, sizeof (desc), "%s-%i",
+ family ? family : "Sans",
+ size ? size : FRAME_TITLEBAR_HEIGHT / 2);
+
+ font = XftFontOpenName (xdpy, xscreen, desc);
+
+ return font;
+}
+
+static void
+mb_wm_theme_simple_paint_decor (MBWMTheme *theme, MBWMDecor *decor)
+{
+ MBWMDecorType type;
+ const MBGeometry *geom;
+ MBWindowManagerClient *client;
+ Window xwin;
+ MBWindowManager *wm = theme->wm;
+ MBWMColor clr_bg;
+ MBWMColor clr_fg;
+ MBWMColor clr_frame;
+ MBWMClientType c_type;
+ MBWMXmlClient *c = NULL;
+ MBWMXmlDecor *d = NULL;
+ int font_size = 0;
+ const char *font_family = "Sans Serif";
+ struct DecorData *dd;
+ int x, y, w, h;
+ GC gc;
+ Display *xdpy = wm->xdpy;
+ int xscreen = wm->xscreen;
+ const char *title;
+
+ clr_fg.r = 1.0;
+ clr_fg.g = 1.0;
+ clr_fg.b = 1.0;
+
+ clr_bg.r = 0.5;
+ clr_bg.g = 0.5;
+ clr_bg.b = 0.5;
+
+ clr_frame.r = 0.0;
+ clr_frame.g = 0.0;
+ clr_frame.b = 0.0;
+
+ client = mb_wm_decor_get_parent (decor);
+ xwin = mb_wm_decor_get_x_window (decor);
+
+ if (client == NULL || xwin == None)
+ return;
+
+ dd = mb_wm_decor_get_theme_data (decor);
+
+ type = mb_wm_decor_get_type (decor);
+ geom = mb_wm_decor_get_geometry (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)))
+ {
+ if (d->clr_fg.set)
+ {
+ clr_fg.r = d->clr_fg.r;
+ clr_fg.g = d->clr_fg.g;
+ clr_fg.b = d->clr_fg.b;
+ }
+
+ if (d->clr_bg.set)
+ {
+ clr_bg.r = d->clr_bg.r;
+ clr_bg.g = d->clr_bg.g;
+ clr_bg.b = d->clr_bg.b;
+ }
+
+ if (d->clr_frame.set)
+ {
+ clr_frame.r = d->clr_frame.r;
+ clr_frame.g = d->clr_frame.g;
+ clr_frame.b = d->clr_frame.b;
+ }
+
+ if (d->font_size)
+ font_size = d->font_size;
+
+ if (d->font_family)
+ font_family = d->font_family;
+ }
+
+ if (!dd)
+ {
+ XRenderColor rclr;
+
+ dd = malloc (sizeof (struct DecorData));
+ dd->xpix = XCreatePixmap(xdpy, xwin,
+ decor->geom.width, decor->geom.height,
+ DefaultDepth(xdpy, xscreen));
+
+ dd->xftdraw = XftDrawCreate (xdpy, dd->xpix,
+ DefaultVisual (xdpy, xscreen),
+ DefaultColormap (xdpy, xscreen));
+
+ rclr.red = (int)(clr_fg.r * (double)0xffff);
+ rclr.green = (int)(clr_fg.g * (double)0xffff);
+ rclr.blue = (int)(clr_fg.b * (double)0xffff);
+ rclr.alpha = 0xffff;
+
+ XftColorAllocValue (xdpy, DefaultVisual (xdpy, xscreen),
+ DefaultColormap (xdpy, xscreen),
+ &rclr, &dd->clr);
+
+ dd->font = xft_load_font (decor, font_family, font_size);
+
+ XSetWindowBackgroundPixmap(xdpy, xwin, dd->xpix);
+
+ mb_wm_decor_set_theme_data (decor, dd, decordata_free);
+ }
+
+ gc = XCreateGC (xdpy, dd->xpix, 0, NULL);
+
+ XSetLineAttributes (xdpy, gc, 1, LineSolid, CapProjecting, JoinMiter);
+ XSetForeground (xdpy, gc, pixel_from_clr (xdpy, xscreen, &clr_frame));
+ XSetBackground (xdpy, gc, pixel_from_clr (xdpy, xscreen, &clr_bg));
+
+ w = geom->width; h = geom->height; x = geom->x; y = geom->y;
+
+ XFillRectangle (xdpy, dd->xpix, gc, 0, 0, w, h);
+
+ XSetForeground (xdpy, gc, pixel_from_clr (xdpy, xscreen, &clr_bg));
+ XFillRectangle (xdpy, dd->xpix, gc, 0, 0, w, h);
+
+ if (mb_wm_decor_get_type(decor) == MBWMDecorTypeNorth &&
+ (title = mb_wm_client_get_name (client)))
+ {
+ 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 = (decor->geom.height -
+ (dd->font->ascent + dd->font->descent)) / 2
+ + dd->font->ascent;
+
+ rec.x = 0;
+ rec.y = 0;
+ rec.width = pack_end_x - 2;
+ rec.height = d ? d->height : FRAME_TITLEBAR_HEIGHT;
+
+ XftDrawSetClipRectangles (dd->xftdraw, 0, 0, &rec, 1);
+
+ XftDrawStringUtf8(dd->xftdraw,
+ &dd->clr,
+ dd->font,
+ west_width + pack_start_x + 2, y,
+ title, strlen (title));
+ }
+
+ XFreeGC (xdpy, gc);
+
+ XClearWindow (xdpy, xwin);
+}
+
+static void
+mb_wm_theme_simple_paint_button (MBWMTheme *theme, MBWMDecorButton *button)
+{
+ MBWMDecor *decor;
+ MBWindowManagerClient *client;
+ Window xwin;
+ MBWindowManager *wm = theme->wm;
+ int x, y, w, h;
+ MBWMColor clr_bg;
+ MBWMColor clr_fg;
+ MBWMClientType c_type;
+ MBWMXmlClient *c = NULL;
+ MBWMXmlDecor *d = NULL;
+ MBWMXmlButton *b = NULL;
+ struct DecorData * dd;
+ GC gc;
+ Display *xdpy = wm->xdpy;
+ int xscreen = wm->xscreen;
+
+ clr_fg.r = 1.0;
+ clr_fg.g = 1.0;
+ clr_fg.b = 1.0;
+
+ clr_bg.r = 0.0;
+ clr_bg.g = 0.0;
+ clr_bg.b = 0.0;
+
+ decor = button->decor;
+ client = mb_wm_decor_get_parent (decor);
+ xwin = decor->xwin;
+ dd = mb_wm_decor_get_theme_data (decor);
+
+ if (client == NULL || xwin == None || dd->xpix == None)
+ return;
+
+ 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)))
+ {
+ clr_fg.r = b->clr_fg.r;
+ clr_fg.g = b->clr_fg.g;
+ clr_fg.b = b->clr_fg.b;
+
+ clr_bg.r = b->clr_bg.r;
+ clr_bg.g = b->clr_bg.g;
+ clr_bg.b = b->clr_bg.b;
+ }
+
+ w = button->geom.width;
+ h = button->geom.height;
+ x = button->geom.x;
+ y = button->geom.y;
+
+ gc = XCreateGC (xdpy, dd->xpix, 0, NULL);
+
+ XSetLineAttributes (xdpy, gc, 1, LineSolid, CapRound, JoinRound);
+
+
+
+ if (button->state == MBWMDecorButtonStateInactive)
+ {
+ XSetForeground (xdpy, gc, pixel_from_clr (xdpy, xscreen, &clr_bg));
+ }
+ else
+ {
+ /* FIXME -- think of a better way of doing this */
+ MBWMColor clr;
+ clr.r = clr_bg.r + 0.2;
+ clr.g = clr_bg.g + 0.2;
+ clr.b = clr_bg.b + 0.2;
+
+ XSetForeground (xdpy, gc, pixel_from_clr (xdpy, xscreen, &clr));
+ }
+
+ XFillRectangle (xdpy, dd->xpix, gc, x, y, w+1, h+1);
+
+ XSetLineAttributes (xdpy, gc, 3, LineSolid, CapRound, JoinRound);
+ XSetForeground (xdpy, gc, pixel_from_clr (xdpy, xscreen, &clr_fg));
+
+ if (button->type == MBWMDecorButtonClose)
+ {
+ XDrawLine (xdpy, dd->xpix, gc, x + 3, y + 3, x + w - 3, y + h - 3);
+ XDrawLine (xdpy, dd->xpix, gc, x + 3, y + h - 3, x + w - 3, y + 3);
+ }
+ else if (button->type == MBWMDecorButtonFullscreen)
+ {
+ XDrawLine (xdpy, dd->xpix, gc, x + 3, y + 3, x + 3, y + h - 3);
+ XDrawLine (xdpy, dd->xpix, gc, x + 3, y + h - 3, x + w - 3, y + h - 3);
+ XDrawLine (xdpy, dd->xpix, gc, x + w - 3, y + h - 3, x + w - 3, y + 3);
+ XDrawLine (xdpy, dd->xpix, gc, x + w - 3, y + 3, x + 3, y + 3);
+ }
+ else if (button->type == MBWMDecorButtonMinimize)
+ {
+ XDrawLine (xdpy, dd->xpix, gc, x + 3, y + h - 5, x + w - 3, y + h - 5);
+ }
+ else if (button->type == MBWMDecorButtonHelp)
+ {
+ char desc[512];
+ XftFont *font;
+ XRenderColor rclr;
+ XftColor clr;
+ XRectangle rec;
+
+ snprintf (desc, sizeof (desc), "%s-%i:bold",
+ d && d->font_family ? d->font_family : "Sans", h*3/4);
+
+ font = XftFontOpenName (xdpy, xscreen, desc);
+
+ rclr.red = (int)(clr_fg.r * (double)0xffff);
+ rclr.green = (int)(clr_fg.g * (double)0xffff);
+ rclr.blue = (int)(clr_fg.b * (double)0xffff);
+ rclr.alpha = 0xffff;
+
+ XftColorAllocValue (xdpy, DefaultVisual (xdpy, xscreen),
+ DefaultColormap (xdpy, xscreen),
+ &rclr, &clr);
+
+ rec.x = x;
+ rec.y = y;
+ rec.width = w;
+ rec.height = h;
+
+ XftDrawSetClipRectangles (dd->xftdraw, 0, 0, &rec, 1);
+
+ XftDrawStringUtf8 (dd->xftdraw, &clr, font,
+ x + 4,
+ y + (h - (font->ascent + font->descent))/2 +
+ font->ascent,
+ "?", 1);
+
+ XftFontClose (xdpy, font);
+ }
+ else if (button->type == MBWMDecorButtonMenu)
+ {
+ XSetLineAttributes (xdpy, gc, 3, LineSolid, CapRound, JoinMiter);
+ XDrawLine (xdpy, dd->xpix, gc, x + 3, y + 5, x + w/2, y + h - 5);
+ XDrawLine (xdpy, dd->xpix, gc, x + w/2, y + h - 5, x + w - 3, y + 5);
+ }
+ else if (button->type == MBWMDecorButtonAccept)
+ {
+ XDrawArc (xdpy, dd->xpix, gc, x + 4, y + 4, w - 8, h - 8, 0, 64 * 360);
+ }
+
+ XFreeGC (xdpy, gc);
+
+ XClearWindow (wm->xdpy, xwin);
+}