Subject: FVWM: FvwmButtons background

From: Patrice Fortier <[email-masked]>
Date: Fri, 7 Feb 1997 16:07:54 +0100 (MET)

Here is the patch I made to put a background pixmap or a transparent
background on an FvwmButtons bar. Anybody has a better name? :)

The new option is FvwmButtonsPixmap. You can use 

*FvwmButtonsPixmap <your_pixmap.xpm>
to put a background pixmap, or

*FvwmButtonsPixmap none 
to make the FvwmButtons background transparent (as with enlightment).

You can check this URL to see a (small) screen shot.
http://www.emi.u-bordeaux.fr/~fortier/Fvwm/index.html

As I go on holidays, I won't reply to any mail until a week.
Happy Buttoning ;)

Lokh.

---------------------------------cut here----------------------------
diff -cr FvwmButtons.orig/FvwmButtons.c FvwmButtons/FvwmButtons.c
*** FvwmButtons.orig/FvwmButtons.c	Tue Jan 14 17:30:43 1997
--- FvwmButtons/FvwmButtons.c	Fri Feb  7 14:10:36 1997
***************
*** 40,45 ****
--- 40,48 ----
  #ifdef XPM
  #include <X11/xpm.h>
  #endif
+ #ifdef SHAPE
+ #include <X11/extensions/shape.h>
+ #endif
  
  #include "../../configure.h"
  #include "../../fvwm/module.h"
***************
*** 230,241 ****
      {
        if(b->flags&b_Icon)
  	DestroyPicture(Dpy,b->icon);
- /*
        if(b->flags&b_IconBack)
  	DestroyPicture(Dpy,b->backicon);
!       if(b->flags&b_Container && b->c->flags&b_IconBack)
  	DestroyPicture(Dpy,b->c->backicon);
- */
      }
  
    exit(0);
--- 233,243 ----
      {
        if(b->flags&b_Icon)
  	DestroyPicture(Dpy,b->icon);
        if(b->flags&b_IconBack)
  	DestroyPicture(Dpy,b->backicon);
!       if(b->flags&b_Container && b->c->flags&b_IconBack
! 	 && !(b->c->flags&b_TransBack))
  	DestroyPicture(Dpy,b->c->backicon);
      }
  
    exit(0);
***************
*** 323,328 ****
--- 325,404 ----
    return b->action[n];
  }
  
+ #ifdef SHAPE
+ /**
+ *** SetTransparentBackground()
+ *** use the Shape extension to create a transparent background.
+ ***   Patrice Fortier
+ **/
+ void SetTransparentBackground(button_info *ub,int w,int h)
+ {
+   Pixmap pmap_mask;
+   button_info *b;
+   GC gc;
+   XGCValues gvals;
+   unsigned long gcm=0;
+   Window root_return;
+   int x_return, y_return;
+   unsigned int width_return, height_return;
+   unsigned int border_width_return;
+   unsigned int depth_return;
+   int number, i;
+   XFontStruct *font;
+   
+   pmap_mask = XCreatePixmap(Dpy,MyWindow,w,h,1);
+   gc = XCreateGC(Dpy,pmap_mask,(unsigned long)0,&gvals);
+   XSetForeground(Dpy,gc,0);
+   XFillRectangle(Dpy,pmap_mask,gc,0,0,w,h);
+   XSetForeground(Dpy,gc,1);
+   
+   /*
+    * if button has an icon, draw a rect with the same size as the icon
+    * (or the mask of the icon),
+    * else draw a rect with the same size as the button.
+    */
+   
+   i=-1;
+   while(NextButton(&ub,&b,&i,0))
+     {
+       if(b->flags&b_Icon) 
+ 	{
+ 	  XGetGeometry(Dpy,b->IconWin,&root_return,&x_return,&y_return,
+ 		       &width_return,&height_return,
+ 		       &border_width_return,&depth_return);
+ 	  
+ 	  number=buttonNum(b);
+ 	  if (b->icon->mask == None)
+ 	    XFillRectangle(Dpy,pmap_mask,gc,x_return, y_return,
+ 			   b->icon->width,b->icon->height);
+ 	  else
+ 	    XCopyArea(Dpy,b->icon->mask,pmap_mask,gc,0,0,
+ 		      b->icon->width,b->icon->height,x_return,y_return);
+ 	}
+       else
+ 	{
+ 	  number=buttonNum(b);
+ 	  XFillRectangle(Dpy,pmap_mask,gc,buttonXPos(b,number),
+ 			 buttonYPos(b,number),
+ 			 buttonWidth(b),buttonHeight(b));
+ 	}
+       
+       /* handle button's title */
+       font=buttonFont(b);
+       if(b->flags&b_Title && font)
+ 	{
+ 	  gcm = GCForeground | GCFont; 
+ 	  gvals.foreground=1;
+ 	  gvals.font = font->fid;
+ 	  XChangeGC(Dpy,gc,gcm,&gvals);
+ 	  DrawTitle(b,pmap_mask,gc);
+ 	}
+     }
+   XFreeGC(Dpy,gc);
+   XShapeCombineMask(Dpy,MyWindow,ShapeBounding,0,0,pmap_mask,ShapeSet);
+ }
+ #endif
+ 
  /**
  *** myErrorHandler()
  *** Shows X errors made by FvwmButtons.
***************
*** 467,472 ****
--- 543,553 ----
    while(NextButton(&ub,&b,&i,0))
      ConfigureIconWindow(b);
  
+ # ifdef SHAPE
+   if(UberButton->c->flags&b_TransBack)
+     SetTransparentBackground(UberButton,Width,Height);
+ # endif
+ 
  # ifdef DEBUG_INIT
    fprintf(stderr,"OK\n%s: Mapping windows...",MyName);
  # endif
***************
*** 815,826 ****
  	b->c->fc=GetColor(b->c->fore);
        if(b->c->flags&b_Back)
  	{
! 	  if(b->c->flags&b_IconBack)
  	    {
! 	      if(!LoadIconFile(b->c->back,&b->c->backicon))
! 		b->c->flags&=~b_Back;
  	    }
! 	  else
  	    {
  	      b->c->bc=GetColor(b->c->back);
  	      b->c->hc=GetHilite(b->c->bc);
--- 896,907 ----
  	b->c->fc=GetColor(b->c->fore);
        if(b->c->flags&b_Back)
  	{
! 	  if(b->c->flags&b_IconBack && !(b->c->flags&b_TransBack))
  	    {
! 	      if(!LoadIconFile(b->c->back_file,&b->c->backicon))
! 		b->c->flags&=~b_IconBack;
  	    }
! 
  	    {
  	      b->c->bc=GetColor(b->c->back);
  	      b->c->hc=GetHilite(b->c->bc);
***************
*** 1070,1075 ****
--- 1151,1160 ----
    MyWindow = XCreateSimpleWindow(Dpy,Root,mysizehints.x,mysizehints.y,
  				 mysizehints.width,mysizehints.height,
  				 1,fore_pix,back_pix);
+   if(ub->c->flags&b_IconBack && !(ub->c->flags&b_TransBack))
+     XSetWindowBackgroundPixmap(Dpy,MyWindow,ub->c->backicon->picture);
+ 
+ 
  # ifdef DEBUG_INIT
    fprintf(stderr,"properties...");
  # endif
diff -cr FvwmButtons.orig/FvwmButtons.h FvwmButtons/FvwmButtons.h
*** FvwmButtons.orig/FvwmButtons.h	Mon Apr 15 20:45:48 1996
--- FvwmButtons/FvwmButtons.h	Fri Feb  7 12:28:37 1997
***************
*** 53,58 ****
--- 53,60 ----
  #define b_Justify   0x0800 /* Has justification info */
  #define b_Size      0x1000 /* Has a minimum size, don't guess */
  #define b_IconBack  0x2000 /* Has an icon as background */
+ #define b_IconParent 0x4000 /* Parent button has an icon as background */
+ #define b_TransBack 0x8000 /* Transparent background */
  
  /* Flags for b->swallow */
  #define b_Count       0x03 /* Init counter for swallowing */
***************
*** 93,99 ****
    signed char framew;             /* b_Frame */
    XFontStruct *font;       /* b_Font */
    char *font_string;       /* b_Font */
!   char *back;              /* b_Back */
    char *fore;              /* b_Fore */
    Pixel fc;                /* b_Fore */
    Pixel bc,hc,sc;          /* b_Back && !b_IconBack */
--- 95,102 ----
    signed char framew;             /* b_Frame */
    XFontStruct *font;       /* b_Font */
    char *font_string;       /* b_Font */
!   char *back;              /* b_Back && !b_IconBack */
!   char *back_file;         /* b_Back && b_IconBack */
    char *fore;              /* b_Fore */
    Pixel fc;                /* b_Fore */
    Pixel bc,hc,sc;          /* b_Back && !b_IconBack */
diff -cr FvwmButtons.orig/button.c FvwmButtons/button.c
*** FvwmButtons.orig/button.c	Fri Apr 12 23:17:58 1996
--- FvwmButtons/button.c	Fri Feb  7 12:21:39 1997
***************
*** 354,360 ****
    b->c->xpos=0;
    b->c->ypos=0;
    if(b->parent != NULL)
!     b->c->flags=0;
    else /* This applies to the UberButton */
      {
        b->c->flags=b_Font|b_Padding|b_Frame|b_Back|b_Fore;
--- 354,365 ----
    b->c->xpos=0;
    b->c->ypos=0;
    if(b->parent != NULL)
!     {
!       if (b->parent->c->flags&b_IconBack || b->parent->c->flags&b_IconParent)
! 	b->c->flags=b_IconParent;
!       else
! 	b->c->flags=0;
!     }
    else /* This applies to the UberButton */
      {
        b->c->flags=b_Font|b_Padding|b_Frame|b_Back|b_Fore;
diff -cr FvwmButtons.orig/draw.c FvwmButtons/draw.c
*** FvwmButtons.orig/draw.c	Fri Mar 29 13:25:42 1996
--- FvwmButtons/draw.c	Fri Feb  7 14:29:53 1997
***************
*** 33,38 ****
--- 33,39 ----
  #include "misc.h" /* ConstrainSize() */
  #include "icons.h" /* ConfigureIconWindow() */
  #include "button.h"
+ #include "draw.h"
  
  /* ---------------- Functions that design and draw buttons ----------------- */
  
***************
*** 119,124 ****
--- 120,129 ----
    if(!(b->flags&b_Icon) && (buttonSwallowCount(b)<3))
      return;
  
+   /* Check if parent container has an icon as background */
+   if (b->parent->c->flags&b_IconBack || b->parent->c->flags&b_IconParent)
+     b->flags|=b_IconParent;
+ 
    font = buttonFont(b);
  
    GetInternalSize(b,&ix,&iy,&iw,&ih);
***************
*** 176,186 ****
    XGCValues gcv;
    unsigned long gcm=0;
    int rev=0;
!   int justify=buttonJustify(b);
! 
    BW = buttonWidth(b);
    BH = buttonHeight(b);
! 
    buttonInfo(b,&x,&y,&px,&py,&f);
    GetInternalSize(b,&ix,&iy,&iw,&ih);
  
--- 181,190 ----
    XGCValues gcv;
    unsigned long gcm=0;
    int rev=0;
!   
    BW = buttonWidth(b);
    BH = buttonHeight(b);
!   
    buttonInfo(b,&x,&y,&px,&py,&f);
    GetInternalSize(b,&ix,&iy,&iw,&ih);
  
***************
*** 216,222 ****
        gcm = GCForeground;
        gcv.foreground=buttonBack(b);
        XChangeGC(Dpy,NormalGC,gcm,&gcv);
! 
        if(b->flags&b_Container)
  	{
  	  int x1=x+f,y1=y+f;
--- 220,226 ----
        gcm = GCForeground;
        gcv.foreground=buttonBack(b);
        XChangeGC(Dpy,NormalGC,gcm,&gcv);
!       
        if(b->flags&b_Container)
  	{
  	  int x1=x+f,y1=y+f;
***************
*** 224,310 ****
  	  int w=BW-2*f,h=BH-2*f;
  	  w2+=iw - b->c->num_columns*b->c->ButtonWidth;
  	  h2+=ih - b->c->num_rows*b->c->ButtonHeight;
! 
  	  if(w1)XFillRectangle(Dpy,MyWindow,NormalGC,x1,y1,w1,h);
  	  if(w2)XFillRectangle(Dpy,MyWindow,NormalGC,x1+w-w2,y1,w2,h);
  	  if(h1)XFillRectangle(Dpy,MyWindow,NormalGC,x1,y1,w,h1);
  	  if(h2)XFillRectangle(Dpy,MyWindow,NormalGC,x1,y1+h-h2,w,h2);
  	}
!       else 
  	XFillRectangle(Dpy,MyWindow,NormalGC,x+f,y+f,BW-2*f,BH-2*f);
      }
! 
    /* ----------------------------------------------------------------------- */
! 
!   /* If a title is to be shown, truncate it until it fits */
    if(b->flags&b_Title && font)
      {
-       int l,i,xpos;
-       char *s;
-       int just=justify&b_TitleHoriz; /* Left, center, right */
- 
        gcm = GCForeground | GCFont; 
        gcv.foreground=buttonFore(b);
        gcv.font = font->fid;
        XChangeGC(Dpy,NormalGC,gcm,&gcv);
  
!       if(justify&b_Horizontal)
  	{
! 	  if(b->flags&b_Icon)
! 	    {
! 	      ix+=b->icon->width+buttonXPad(b);
! 	      iw-=b->icon->width+buttonXPad(b);
! 	    }
! 	  else if (buttonSwallowCount(b)==3)
! 	    {
! 	      ix+=b->icon_w+buttonXPad(b);
! 	      iw-=b->icon_w+buttonXPad(b);
! 	    }
  	}
! 
!       s=b->title;
!       l=strlen(s);
!       i=XTextWidth(font,s,l);
! 
!       if(i>iw)
  	{
! 	  if(just==2)
! 	    {
! 	      while(i>iw && *s)
! 		i=XTextWidth(font,++s,--l);
! 	    }
! 	  else /* Left or center - cut off its tail */
! 	    {
! 	      while(i>iw && l>0)
! 		i=XTextWidth(font,s,--l);
! 	    }
  	}
!       if(just==0) /* Left */
! 	xpos=ix;
!       else if(just==2) /* Right */
! 	xpos=max(ix,ix+iw-i);
!       else /* Centered, I guess */
!  	xpos=ix+(iw-i)/2;
! 
!       if(*s && l>0 && BH>=font->descent+font->ascent) /* Clip it somehow? */
  	{
! 	  /* If there is more than the title, put it at the bottom */
!           /* Unless stack flag is set, put it to the right of icon */
! 	  if((b->flags&b_Icon || (buttonSwallowCount(b)==3)) &&
! 	     !(justify&b_Horizontal))
! 	    {
! 	      XDrawString(Dpy,MyWindow,NormalGC,xpos,
! 			  iy+ih-font->descent,s,l);
! 	      /* Shrink the space available for icon/window */
! 	      ih-=font->descent+font->ascent;
! 	    }
! 	  /* Or else center vertically */
! 	  else
! 	    {
! 	      XDrawString(Dpy,MyWindow,NormalGC,xpos,
! 			  iy+(ih+font->ascent-font->descent)/2,s,l);
! 	    }
  	}
      }
  }
- 
--- 228,334 ----
  	  int w=BW-2*f,h=BH-2*f;
  	  w2+=iw - b->c->num_columns*b->c->ButtonWidth;
  	  h2+=ih - b->c->num_rows*b->c->ButtonHeight;
! 	  
  	  if(w1)XFillRectangle(Dpy,MyWindow,NormalGC,x1,y1,w1,h);
  	  if(w2)XFillRectangle(Dpy,MyWindow,NormalGC,x1+w-w2,y1,w2,h);
  	  if(h1)XFillRectangle(Dpy,MyWindow,NormalGC,x1,y1,w,h1);
  	  if(h2)XFillRectangle(Dpy,MyWindow,NormalGC,x1,y1+h-h2,w,h2);
  	}
!       else if(!(b->flags&b_IconBack) && !(b->flags&b_IconParent))
  	XFillRectangle(Dpy,MyWindow,NormalGC,x+f,y+f,BW-2*f,BH-2*f);
      }
!   
    /* ----------------------------------------------------------------------- */
!   
    if(b->flags&b_Title && font)
      {
        gcm = GCForeground | GCFont; 
        gcv.foreground=buttonFore(b);
        gcv.font = font->fid;
        XChangeGC(Dpy,NormalGC,gcm,&gcv);
+       DrawTitle(b,MyWindow,NormalGC);
+     }
+ }
  
! /**
! *** DrawTitle()
! *** Writes out title.
! **/
! void DrawTitle(button_info *b,Window win,GC gc)
! {
!   int BH;
!   int ix,iy,iw,ih;
!   XFontStruct *font=buttonFont(b);
!   int justify=buttonJustify(b);
!   int l,i,xpos;
!   char *s;
!   int just=justify&b_TitleHoriz; /* Left, center, right */
!   
!   BH = buttonHeight(b);
!   
!   GetInternalSize(b,&ix,&iy,&iw,&ih);
!   
!   /* ----------------------------------------------------------------------- */
!   
!   if(!(b->flags&b_Title) || !font)
!     return;
!   
!   /* If a title is to be shown, truncate it until it fits */
!   if(justify&b_Horizontal)
!     {
!       if(b->flags&b_Icon)
  	{
! 	  ix+=b->icon->width+buttonXPad(b);
! 	  iw-=b->icon->width+buttonXPad(b);
  	}
!       else if (buttonSwallowCount(b)==3)
  	{
! 	  ix+=b->icon_w+buttonXPad(b);
! 	  iw-=b->icon_w+buttonXPad(b);
  	}
!     }
!   
!   s=b->title;
!   l=strlen(s);
!   i=XTextWidth(font,s,l);
!   
!   if(i>iw)
!     {
!       if(just==2)
  	{
! 	  while(i>iw && *s)
! 	    i=XTextWidth(font,++s,--l);
! 	}
!       else /* Left or center - cut off its tail */
! 	{
! 	  while(i>iw && l>0)
! 	    i=XTextWidth(font,s,--l);
! 	}
!     }
!   if(just==0) /* Left */
!     xpos=ix;
!   else if(just==2) /* Right */
!     xpos=max(ix,ix+iw-i);
!   else /* Centered, I guess */
!     xpos=ix+(iw-i)/2;
!   
!   if(*s && l>0 && BH>=font->descent+font->ascent) /* Clip it somehow? */
!     {
!       /* If there is more than the title, put it at the bottom */
!       /* Unless stack flag is set, put it to the right of icon */
!       if((b->flags&b_Icon || (buttonSwallowCount(b)==3)) &&
! 	 !(justify&b_Horizontal))
! 	{
! 	  XDrawString(Dpy,win,gc,xpos,
! 		      iy+ih-font->descent,s,l);
! 	  /* Shrink the space available for icon/window */
! 	  ih-=font->descent+font->ascent;
! 	}
!       /* Or else center vertically */
!       else
! 	{
! 	  XDrawString(Dpy,win,gc,xpos,
! 		      iy+(ih+font->ascent-font->descent)/2,s,l);
  	}
      }
  }
diff -cr FvwmButtons.orig/draw.h FvwmButtons/draw.h
*** FvwmButtons.orig/draw.h	Fri Mar 29 13:25:42 1996
--- FvwmButtons/draw.h	Fri Feb  7 12:24:54 1997
***************
*** 15,18 ****
--- 15,19 ----
  void RelieveWindow(Window,int,int,int,int,int,Pixel,Pixel,int);
  void MakeButton(button_info*);
  void RedrawButton(button_info*,int);
+ void DrawTitle(button_info*,Window,GC);
  
diff -cr FvwmButtons.orig/parse.c FvwmButtons/parse.c
*** FvwmButtons.orig/parse.c	Thu Jun 27 16:46:22 1996
--- FvwmButtons/parse.c	Fri Feb  7 12:30:11 1997
***************
*** 695,701 ****
  {
    button_info *ub=*ubb;
    char *opts[]={"geometry","font","padding","columns","rows","back","fore",
! 		  "frame","file",NULL};
    int i,j,k;
  
    switch(MatchSeveralLines(s,opts,&s))
--- 695,701 ----
  {
    button_info *ub=*ubb;
    char *opts[]={"geometry","font","padding","columns","rows","back","fore",
! 		  "frame","file","pixmap",NULL};
    int i,j,k;
  
    switch(MatchSeveralLines(s,opts,&s))
***************
*** 748,753 ****
--- 748,761 ----
        trimleft(s);
        config_file=seekright(&s);
        break;
+     case 9:/* Pixmap */
+       trimleft(s);
+       if (mystrncasecmp(s,"none",4)==0)
+ 	ub->c->flags|=b_TransBack;
+       else
+         CopyString(&(ub->c->back_file),s);
+       ub->c->flags|=b_IconBack;
+       break;
      default:
        trimleft(s);
        match_string(ubb,s);
---------------------------------cut here----------------------------
--
Visit the official FVWM web page at <URL:http://www.hpc.uh.edu/fvwm/>.
To unsubscribe from the list, send "unsubscribe fvwm" in the body of a
message to [email-masked].
To report problems, send mail to [email-masked].