Okay, here's a somewhat cleaned-up patch for nifty titlebars. I still wouldn't call it ready for general use (not enough testing, not enough review by the people who know what they're doing ;-), but the titleunder bug seems to be fixed and the config syntax is much more reasonable. Bonus: the patch is smaller!
The syntax is now: MultiPixmap [main] [under text] [left of text] [right of text] [far left] [far right] e.g.: TitleStyle ActiveUp MultiPixmap main.xpm under.xpm lt.xpm rt.xpm - - The read code has been integrated into ReadDecorFace, so now this can be combined with pretty much anything else TitleStyle supports (flags, defining multiple states at once, etc.) Suzanne -- [EMAIL PROTECTED] - http://www.igs.net/~tril/ "I'm aware of that, sweetheart. It's just that when I wake up to a hissing goat skull on my nightstand, and it hops off and runs across the floor on spider legs, I sleep a lot better knowing where it ran off to." - Ted (Red Meat)
--- ChangeLog.orig Wed Oct 3 20:36:03 2001 +++ ChangeLog Sun Oct 7 04:04:43 2001 @@ -1,3 +1,29 @@ +2001-10-07 Suzanne Britton <[EMAIL PROTECTED]> + + * config.h.in: Added FANCY_TITLEBARS option, off by default + + * fvwm/screen.h: + [All changes #ifdeffed FANCY_TITLEBARS] + Added TITLE_PADDING define for fancy titlebar rendering + Added tb_pixmap_enum + Added MultiPixmap to DecorFaceType enum + Added Picture **extra_pictures to DecorFace structure + + * fvwm/borders.c: + [All changes #ifdeffed FANCY_TITLEBARS] + (DrawButton): Handle UseTitleStyle where TitleStyle is MultiPixmap + (DrawMultiPixmapTitlebar): [new] + (RedrawTitle): + Call DrawFancyTitlebar for MultiPixmap style + Skip DrawString calls for MultiPixmap style (title is drawn inside + DrawMultiPixmapTitlebar) + + * fvwm/builtins.c: + [All changes #ifdeffed FANCY_TITLEBARS] + (FreeDecorFace): Free up all pictures for a MultiPixmap decor + (ReadDecorFace): Call ReadMultiPixmapDecor for a MultiPixmap TitleStyle + (ReadMultiPixmapDecor): [new] + 2001-09-16 Dominik Vogt <[EMAIL PROTECTED]> * configure.in: --- AUTHORS.orig Wed Oct 3 20:59:12 2001 +++ AUTHORS Wed Oct 3 20:58:41 2001 @@ -182,6 +182,8 @@ Echo. Improve modules: Make FvwmM4 pass args on to m4, font-related seg-fault bug fix in FvwmButtons. +Suzanne Britton: +Multi-pixmap titlebars patch. Along with a cast of thousands (well, dozens) mentioned in old ChangeLog entries. If you find your name below, please send an entry --- config.h.in.orig Wed Oct 3 20:05:40 2001 +++ config.h.in Sat Sep 29 20:59:34 2001 @@ -2,6 +2,9 @@ /* Suffix for config filenames */ #define FVWMRC ".fvwm2rc" +/* Define for fancy, multi-pixmap-themeable titlebars */ +#undef FANCY_TITLEBARS + /* Define if gdk-imlib is used */ #undef GDK_IMLIB --- fvwm/screen.h.orig Wed Oct 3 20:06:01 2001 +++ fvwm/screen.h Sun Oct 7 04:30:01 2001 @@ -54,6 +54,11 @@ #define COLORMAP_FOLLOWS_MOUSE 1 /* default */ #define COLORMAP_FOLLOWS_FOCUS 2 +#ifdef FANCY_TITLEBARS +#define TITLE_PADDING 5 +enum tb_pixmap_enum {TBP_MAIN, TBP_UNDER, TBP_LTEXT, TBP_RTEXT, TBP_LEFT, + TBP_RIGHT, NUM_TB_PIXMAPS}; +#endif typedef struct { @@ -70,6 +75,9 @@ GradientButton , PixmapButton , TiledPixmapButton , +#ifdef FANCY_TITLEBARS + MultiPixmap , +#endif #ifdef MINI_ICONS MiniIconButton , #endif @@ -123,6 +131,9 @@ struct { Picture *p; +#ifdef FANCY_TITLEBARS + Picture **extra_pictures; +#endif Pixel back; struct { --- fvwm/borders.c.orig Wed Oct 3 20:06:21 2001 +++ fvwm/borders.c Sun Oct 7 05:32:43 2001 @@ -271,7 +271,14 @@ case MiniIconButton: case PixmapButton: case TiledPixmapButton: - if (type == PixmapButton || type == TiledPixmapButton) +#ifdef FANCY_TITLEBARS + case MultiPixmap: /* in case of UseTitleStyle */ +#endif + if (type == PixmapButton || type == TiledPixmapButton +#ifdef FANCY_TITLEBARS + || type == MultiPixmap +#endif + ) { p = df->u.p; } @@ -448,6 +455,161 @@ return; } +#ifdef FANCY_TITLEBARS +/**************************************************************************** + * + * Redraws multi-pixmap titlebar ([EMAIL PROTECTED]) + * + ****************************************************************************/ +static void DrawMultiPixmapTitlebar(FvwmWindow *window, TitleButton *decor) +{ + Window title_win; + GC gc; + const char *title; + int title_width, title_height, text_width, text_offset, text_y_pos; + int left_space, right_space, under_offset, under_width; + int state; + mwm_flags state_flags; + Bool toggled; + Picture *main_pic, **extra_pics; + + state = BS_Inactive; + if (Scr.Hilite == window) { + if (PressedW == title_win) + state = BS_ActiveDown; + else + state = BS_ActiveUp; + } + state_flags = TB_MWM_DECOR_FLAGS(*decor); + toggled = (HAS_MWM_BUTTONS(window) && + ((state_flags & MWM_DECOR_MAXIMIZE && IS_MAXIMIZED(window)) || + (state_flags & MWM_DECOR_SHADE && IS_SHADED(window)) || + (state_flags & MWM_DECOR_STICK && IS_STICKY(window)))); + if (toggled) + state += BS_ToggledActiveUp; + + main_pic = decor->state[state].u.p; + extra_pics = decor->state[state].u.extra_pictures; + + gc = Scr.TitleGC; + XSetClipMask(dpy, gc, None); + title_win = window->title_w; + title = window->name; + title_width = window->title_g.width; + title_height = window->title_g.height; + + if (main_pic) { + Pixmap pm = CreateTiledPixmap(dpy, main_pic->picture, main_pic->width, + main_pic->height, title_width, title_height, + main_pic->depth, gc); + XCopyArea(dpy, pm, title_win, gc, 0, 0, title_width, title_height, 0, 0); + XFreePixmap(dpy, pm); + } + + if (title) { +#ifdef I18N_MB + text_width = XmbTextEscapement(window->title_font.fontset, title, + strlen(title)); +#else + text_width = XTextWidth(window->title_font.font, title, strlen(title)); +#endif + if (text_width > title_width) + text_width = title_width; + + switch (TB_JUSTIFICATION(*decor)) { + case JUST_LEFT: + text_offset = TITLE_PADDING; + if (extra_pics[TBP_LTEXT-1]) + text_offset += extra_pics[TBP_LTEXT-1]->width; + if (extra_pics[TBP_LEFT-1]) + text_offset += extra_pics[TBP_LEFT-1]->width; + if (text_offset > title_width - text_width) + text_offset = title_width - text_width; + break; + case JUST_RIGHT: + text_offset = title_width - text_width - TITLE_PADDING; + if (extra_pics[TBP_RTEXT-1]) + text_offset -= extra_pics[TBP_RTEXT-1]->width; + if (extra_pics[TBP_RIGHT-1]) + text_offset -= extra_pics[TBP_RIGHT-1]->width; + if (text_offset < 0) + text_offset = 0; + break; + default: + text_offset = (title_width - text_width) / 2; + break; + } + + under_offset = text_offset; + under_width = text_width; + if (under_offset >= TITLE_PADDING) { + under_offset -= TITLE_PADDING; + under_width += TITLE_PADDING; + } + if (under_offset + under_width + TITLE_PADDING <= title_width) + under_width += TITLE_PADDING; + left_space = under_offset; + right_space = title_width - left_space - under_width; + + if (extra_pics[TBP_UNDER-1]) { + Pixmap pm = CreateTiledPixmap(dpy, + extra_pics[TBP_UNDER-1]->picture, + extra_pics[TBP_UNDER-1]->width, + extra_pics[TBP_UNDER-1]->height, + under_width, title_height, + extra_pics[TBP_UNDER-1]->depth, + gc); + XCopyArea(dpy, pm, title_win, gc, 0, 0, under_width, title_height, + under_offset, 0); + XFreePixmap(dpy, pm); + } + if (extra_pics[TBP_LTEXT-1] && + extra_pics[TBP_LTEXT-1]->width <= left_space) { + XCopyArea(dpy, extra_pics[TBP_LTEXT-1]->picture, title_win, gc, 0, 0, + extra_pics[TBP_LTEXT-1]->width, title_height, + under_offset - extra_pics[TBP_LTEXT-1]->width, 0); + left_space -= extra_pics[TBP_LTEXT-1]->width; + } + if (extra_pics[TBP_RTEXT-1] && + extra_pics[TBP_RTEXT-1]->width <= right_space) { + XCopyArea(dpy, extra_pics[TBP_RTEXT-1]->picture, title_win, gc, 0, 0, + extra_pics[TBP_RTEXT-1]->width, title_height, + under_offset + under_width, 0); + right_space -= extra_pics[TBP_RTEXT-1]->width; + } + + text_y_pos = title_height + - (title_height - window->title_font.font->ascent) / 2 + - 1; + if (title_height > 19) + text_y_pos--; + if (text_y_pos < 0) + text_y_pos = 0; +#ifdef I18N_MB + XmbDrawString(dpy, title_win, window->title_font.fontset, gc, text_offset, + gc, text_offset, text_y_pos, title, strlen(title)); +#else + XDrawString(dpy, title_win, gc, text_offset, text_y_pos, title, + strlen(title)); +#endif + } + else + left_space = right_space = title_width; + + if (extra_pics[TBP_LEFT-1] && extra_pics[TBP_LEFT-1]->width <= left_space) { + XCopyArea(dpy, extra_pics[TBP_LEFT-1]->picture, title_win, gc, 0, 0, + extra_pics[TBP_LEFT-1]->width, title_height, 0, 0); + left_space -= extra_pics[TBP_LEFT-1]->width; + } + if (extra_pics[TBP_RIGHT-1] && extra_pics[TBP_RIGHT-1]->width <= right_space) { + XCopyArea(dpy, extra_pics[TBP_RIGHT-1]->picture, title_win, gc, 0, 0, + extra_pics[TBP_RIGHT-1]->width, title_height, + title_width - extra_pics[TBP_RIGHT-1]->width, 0); + right_space -= extra_pics[TBP_RIGHT-1]->width; + } +} +#endif /* FANCY_TITLEBARS */ + /* rules to get button state */ static enum ButtonState get_button_state( Bool has_focus, Bool toggled, Window w) @@ -1276,6 +1438,11 @@ /* draw compound titlebar ([EMAIL PROTECTED]) */ Bool is_lowest = True; +#ifdef FANCY_TITLEBARS + if (df->style.face_type == MultiPixmap) + DrawMultiPixmapTitlebar(t, &(GetDecor(t, titlebar))); + else +#endif if (PressedW == t->title_w) { #ifdef MULTISTYLE @@ -1319,6 +1486,11 @@ break; } +#ifdef FANCY_TITLEBARS + if (TB_STATE(GetDecor(t, titlebar))[title_state].style.face_type + != MultiPixmap) +#endif + { #ifdef I18N_MB if(t->name != (char *)NULL) XmbDrawString(dpy, t->title_w, t->title_font.fontset, @@ -1329,6 +1501,7 @@ XDrawString(dpy, t->title_w, Scr.TitleGC, hor_off, t->title_font.y + 1, t->name, strlen(t->name)); #endif + } } /* --- fvwm/builtins.c.orig Wed Oct 3 20:06:10 2001 +++ fvwm/builtins.c Sun Oct 7 06:31:27 2001 @@ -63,6 +63,9 @@ static char *ReadTitleButton( char *s, TitleButton *tb, Boolean append, int button); +#ifdef FANCY_TITLEBARS +static char *ReadMultiPixmapDecor(char *s, DecorFace *df); +#endif static void DestroyFvwmDecor(FvwmDecor *decor); extern float rgpctMovementDefault[32]; @@ -1401,6 +1404,10 @@ void FreeDecorFace(Display *dpy, DecorFace *df) { +#ifdef FANCY_TITLEBARS + int i; +#endif + switch (DFS_FACE_TYPE(df->style)) { case GradientButton: @@ -1418,6 +1425,20 @@ DestroyPicture(dpy, df->u.p); break; +#ifdef FANCY_TITLEBARS + case MultiPixmap: + if (df->u.p) + DestroyPicture(dpy, df->u.p); + if (df->u.extra_pictures) { + for (i=0; i < NUM_TB_PIXMAPS-1; i++) { + if (df->u.extra_pictures[i]) + DestroyPicture(dpy, df->u.extra_pictures[i]); + } + free(df->u.extra_pictures); + } + break; +#endif + case VectorButton: case DefaultVectorButton: if (df->u.vector.x) @@ -1649,6 +1670,19 @@ else DFS_FACE_TYPE(df->style) = PixmapButton; } +#ifdef FANCY_TITLEBARS + else if (strncasecmp(style,"MultiPixmap",11)==0) { + if (button != -1) { + if (verbose) + fvwm_msg(ERR, "ReadDecorFace", + "MultiPixmap is only valid for TitleStyle"); + return False; + } + s = ReadMultiPixmapDecor(s, df); + if (!s) + return False; + } +#endif #ifdef MINI_ICONS else if (strncasecmp (style, "MiniIcon", 8) == 0) { @@ -1956,6 +1990,49 @@ return end; } +#ifdef FANCY_TITLEBARS +/***************************************************************************** + * + * Reads a multi-pixmap titlebar config. This should consist of NUM_TB_PIXMAPS + * pixmap filenames, any of which may be '-' for "no pixmap". ([EMAIL PROTECTED]) + * + ****************************************************************************/ +static char *ReadMultiPixmapDecor(char *s, DecorFace *df) +{ + char *pixmap_filenames[NUM_TB_PIXMAPS]; + Picture **p; + int i; + + for (i=0; i < NUM_TB_PIXMAPS; i++) { + s = GetNextToken(s, &pixmap_filenames[i]); + if (!pixmap_filenames[i]) { + fvwm_msg(ERR, "ReadMultiPixmapDecor", + "Expecting %d pixmap filenames for MultiPixmap style (use '-' to specify 'no pixmap')", + NUM_TB_PIXMAPS); + return NULL; + } + } + if (!df->u.extra_pictures) + df->u.extra_pictures = (Picture**)safecalloc(NUM_TB_PIXMAPS-1, + sizeof(Picture*)); + df->style.face_type = MultiPixmap; + + for (i=0; i < NUM_TB_PIXMAPS; i++) { + if (StrEquals(pixmap_filenames[i], "-")) + continue; + p = (i == 0 ? &(df->u.p) : &(df->u.extra_pictures[i-1])); + *p = CachePicture(dpy, Scr.NoFocusWin, NULL, pixmap_filenames[i], + Scr.ColorLimit); + if (!(*p)) + fvwm_msg(WARN, "ReadMultiPixmapDecor", "Pixmap '%s' could not be loaded", + pixmap_filenames[i]); + } + + for (i=0; i < NUM_TB_PIXMAPS; i++) + free(pixmap_filenames[i]); + return s; +} +#endif /* FANCY_TITLEBARS */ #ifdef USEDECOR /*****************************************************************************