diff --unified --recursive --text fvwm-2.6.9/fvwm/borders.c fvwm-patched/fvwm/borders.c
--- fvwm-2.6.9/fvwm/borders.c	2020-08-21 16:09:27.172710920 -0600
+++ fvwm-patched/fvwm/borders.c	2020-08-21 16:15:29.887392857 -0600
@@ -1638,6 +1638,7 @@
 		True : False;
 	xgcv.fill_style = FillSolid;
 	valuemask = GCFillStyle;
+
 	if (!bg->flags.use_pixmap)
 	{
 		/* solid pixel */
@@ -1830,13 +1831,26 @@
 
 static void border_get_border_background(
 	pixmap_background_type *bg, common_decorations_type *cd,
-	rectangle *part_g, rectangle *relative_g, int *free_bg_pixmap, Window w, window_parts part)
+	rectangle *part_g, rectangle *relative_g, int *free_bg_pixmap, Window w, window_parts part, FvwmPicture *fp)
 {
 	*free_bg_pixmap = False;
 
-	if (cd->texture_pixmap)
+	if (fp)
 	{
 		bg->flags.use_pixmap = 1;
+        bg->pixmap.p = fp->picture;
+        bg->pixmap.g.width = fp->width;
+        bg->pixmap.g.height = fp->height;
+        bg->pixmap.shape = None;
+        bg->pixmap.alpha = None;
+        bg->pixmap.depth = fp->depth;
+        bg->pixmap.flags.is_tiled = 1;
+        bg->pixmap.flags.is_stretched = 0;
+        bg->pixmap.fra.mask = 0;
+    }
+    else if (cd->texture_pixmap)
+    {
+        bg->flags.use_pixmap = 1;
 		bg->pixmap.p = cd->texture_pixmap;
 		bg->pixmap.g.width = cd->texture_pixmap_width;
 		bg->pixmap.g.height = cd->texture_pixmap_height;
@@ -1931,6 +1945,18 @@
 	return;
 }
 
+#define DRAWBORDER(PIX,X,Y,WIDTH,HEIGHT) \
+	{ \
+		fp = df->u.mb.pixmaps[PIX]; \
+		border_get_border_background( \
+			&bg, cd, &part_g, &relative_g, &free_bg_pixmap, w, PART_NONE, fp); \
+		r.x = X; \
+		r.y = Y; \
+		r.width = WIDTH; \
+		r.height = HEIGHT; \
+		border_fill_pixmap_background(p, &r, &bg, cd); \
+	}
+
 static void border_draw_one_border_part(
 	common_decorations_type *cd, FvwmWindow *fw, rectangle *sidebar_g,
 	rectangle *frame_g, border_relief_descr *br, window_parts part,
@@ -1943,6 +1969,7 @@
 	Pixmap p;
 	Window w;
 	Bool free_bg_pixmap = False;
+	int x, y, width, height;
 
 	/* make a pixmap */
 	border_get_part_geometry(fw, part, sidebar_g, &part_g, &w);
@@ -1956,8 +1983,28 @@
 	relative_g.height = fw->g.frame.height;
 	relative_g.x = part_g.x;
 	relative_g.y = part_g.y;
-	border_get_border_background(
-		&bg, cd, &part_g, &relative_g, &free_bg_pixmap, w, part);
+
+    DecorFace* df;
+    FvwmPicture* fp = 0;
+    df = border_get_border_style(fw, (Scr.Hilite == fw));
+    if (DFS_FACE_TYPE(df->style) == MultiBorder)
+    {
+        int id = -1;
+        if (part==PART_BORDER_NW) id = 0;
+        if (part==PART_BORDER_N)  id = 1;
+        if (part==PART_BORDER_NE) id = 2;
+        if (part==PART_BORDER_E)  id = 3;
+        if (part==PART_BORDER_SE) id = 4;
+        if (part==PART_BORDER_S)  id = 5;
+        if (part==PART_BORDER_SW) id = 6;
+        if (part==PART_BORDER_W)  id = 7;
+
+        if (id>=0 && df->u.mb.pixmaps[id])
+        {
+            fp = df->u.mb.pixmaps[id];
+        }
+    }
+
 	if (cd->texture_pixmap)
 	{
 		switch (part)
@@ -2000,13 +2047,100 @@
 		bg.pixmap.g.x = 0;
 		bg.pixmap.g.y = 0;
 	}
-	/* set the geometry for drawing the Tiled pixmap; maybe add the relief
-	 * as offset? */
-	pix_g.x = 0;
-	pix_g.y = 0;
-	pix_g.width = part_g.width;
-	pix_g.height = part_g.height;
-	border_fill_pixmap_background(p, &pix_g, &bg, cd);
+
+	border_get_border_background(
+		&bg, cd, &part_g, &relative_g, &free_bg_pixmap, w, PART_NONE, fp);
+ 
+	int px = bg.pixmap.g.x;
+	int py = bg.pixmap.g.y;
+ 
+    if (fp)
+    {
+		/* Position pixmap so that it's aligned to the edge of the window */
+		if (part & PART_BOTTOM)
+		{
+             bg.pixmap.g.y = fp->height - sidebar_g->y;
+			 if (part == PART_BORDER_S)
+			 {
+				bg.pixmap.g.y = fp->height - fw->boundary_width;
+			 }
+		}
+		if (part & PART_RIGHT)
+		{
+			bg.pixmap.g.x = fp->width - sidebar_g->x;
+			if (part == PART_BORDER_E)
+			{
+				bg.pixmap.g.x = fp->width - fw->boundary_width;
+			}
+		}
+    }
+ 
+   	/* set the geometry for drawing the Tiled pixmap; maybe add the relief
+   	 * as offset? */
+   	pix_g.x = 0;
+   	pix_g.y = 0;
+   	pix_g.width = part_g.width;
+   	pix_g.height = part_g.height;
+ 
+   	border_fill_pixmap_background(p, &pix_g, &bg, cd);
+ 
+    bg.pixmap.g.x = px;
+    bg.pixmap.g.y = py;
+
+    if (fp)
+    {
+		height = pix_g.height;
+		width = pix_g.width;
+		x = pix_g.x;
+		y = pix_g.y;
+
+ 		/* draw parts from other borders that overflow because of their width/height */
+        rectangle r;
+        if (part==PART_BORDER_S)
+        {
+			DRAWBORDER(6, pix_g.x - sidebar_g->x, fw->boundary_width - fp->height, fp->width - sidebar_g->x, height);
+            DRAWBORDER(4, pix_g.width - fp->width + sidebar_g->x, fw->boundary_width - fp->height, fp->width - sidebar_g->x, height);
+		}
+		if (!IS_SHADED(fw))
+		{
+			if (part==PART_BORDER_E)
+			{
+			    DRAWBORDER(2, fw->boundary_width - fp->width, pix_g.y - sidebar_g->y, width, fp->height - sidebar_g->y);
+			    DRAWBORDER(4, fw->boundary_width - fp->width, pix_g.height - fp->height + sidebar_g->y, width, fp->height - sidebar_g->y);
+			}
+			if (part==PART_BORDER_W)
+			{
+			    DRAWBORDER(0, x, pix_g.y - sidebar_g->y, width, fp->height - sidebar_g->y);
+			    DRAWBORDER(6, x, pix_g.height - fp->height + sidebar_g->y, width, fp->height - sidebar_g->y);
+			}
+		}
+        if (part==PART_BORDER_N)
+        {
+			DRAWBORDER(2, pix_g.width - fp->width + sidebar_g->x, y, fp->width - sidebar_g->x, height);
+            DRAWBORDER(0, pix_g.x - fp->width + sidebar_g->x, y, fp->width - sidebar_g->x, height);
+        }
+		/* Use the top border for the whole height of the titlebar, overflowing to parts of the bottom corners if shaded */
+		if (IS_SHADED(fw))
+		{
+			if (part==PART_BORDER_W)
+			{
+				DRAWBORDER(0, 0, -height, width, height);
+			}
+			if (part==PART_BORDER_SW)
+			{
+				DRAWBORDER(0, 0, -height*2, width, height - fw->boundary_width);
+			}
+			if (part==PART_BORDER_E)
+			{
+				DRAWBORDER(2, fw->boundary_width - fp->width, -height, width, height);
+			}
+			if (part==PART_BORDER_SE)
+			{
+				DRAWBORDER(2, width - fp->width, -height*2, width, height - fw->boundary_width);
+			}
+		}
+     }
+ 
 	if (HAS_FLUXBOX_HANDLES(fw) && (part & PART_BOTTOM))
 	{
 		pix_g.y = part_g.height - fw->boundary_width;
@@ -2023,6 +2157,7 @@
 			border_fill_fluxbox_handle(p, &pix_g, cd, !(part & PART_BORDER_S));
 		}
 	}
+
 	if (free_bg_pixmap && bg.pixmap.p)
 	{
 		XFreePixmap(dpy, bg.pixmap.p);
@@ -2077,7 +2212,7 @@
                                         do_clear);
 		}
 	}
-
+	
 	return;
 }
 
@@ -3702,7 +3837,7 @@
 		relative_g.x = button_g->x;
 		relative_g.y = button_g->y;
 		border_get_border_background(
-			&bg, td->cd, button_g, &relative_g, &free_bg_pixmap, w, PART_NONE);
+			&bg, td->cd, button_g, &relative_g, &free_bg_pixmap, w, PART_NONE, (FvwmPicture *)NULL);
 		bg.pixmap.g.x = 0;
 		bg.pixmap.g.y = 0;
 		/* set the geometry for drawing the Tiled pixmap;
@@ -4149,7 +4284,7 @@
 		relative_g.y = td->layout.title_g.y;
 		border_get_border_background(
 			&bg, td->cd, &td->layout.title_g, &relative_g,
-			&free_bg_pixmap, w, PART_NONE);
+			&free_bg_pixmap, w, PART_NONE, (FvwmPicture *)NULL);
 		bg.pixmap.g.x = 0;
 		bg.pixmap.g.y = 0;
 		/* set the geometry for drawing the Tiled pixmap;
Only in fvwm-patched/fvwm: borders.c.orig
diff --unified --recursive --text fvwm-2.6.9/fvwm/builtins.c fvwm-patched/fvwm/builtins.c
--- fvwm-2.6.9/fvwm/builtins.c	2020-08-21 16:14:00.246833497 -0600
+++ fvwm-patched/fvwm/builtins.c	2020-08-21 16:15:29.887392857 -0600
@@ -782,6 +782,50 @@
 	return s;
 }
 
+static char *ReadMultiBorderDecor(char *s, DecorFace *df)
+{
+	FvwmPictureAttributes fpa;
+	FvwmPicture **pm;
+	char *token;
+	int x;
+	int y;
+	
+	pm = df->u.mb.pixmaps;
+	df->style.face_type = MultiBorder;
+	
+	for (x = 0; x < 8; x++)
+	{
+		s = DoPeekToken(s, &token, " ", NULL, NULL);
+		if (s == NULL)
+		{
+			break;
+		}
+		if (pm[x])
+		{
+			PDestroyFvwmPicture(dpy, pm[x]);
+		}
+		pm[x] = PCacheFvwmPicture(dpy, Scr.NoFocusWin, NULL,
+			token, fpa);
+		
+		if (!pm[x])
+		{
+			fvwm_msg(ERR, "ReadMultiBorderDecor",
+				"Pixmap '%s' could not be loaded",
+				token);
+			for(y = 0; y < x; y++)
+			{
+				if (pm[y])
+				{
+					PDestroyFvwmPicture(dpy, pm[y]);
+				}
+			}
+			return NULL;
+		}
+	}
+
+	return s;
+}
+
 /*
  *
  *  DestroyFvwmDecor -- frees all memory assocated with an FvwmDecor
@@ -1481,6 +1525,14 @@
 			free(df->u.mp.pixels);
 		}
 		break;
+	case MultiBorder:
+		for (i = 0; i < 8; i++)
+		{
+			if (df->u.mb.pixmaps[i])
+			{
+				PDestroyFvwmPicture(dpy, df->u.mb.pixmaps[i]);
+			}
+		}
 	case VectorButton:
 	case DefaultVectorButton:
 		if (df->u.vector.x)
@@ -1850,6 +1902,15 @@
 				return False;
 			}
 		}
+		else if (strncasecmp(style,"MultiBorder",11)==0)
+		{
+			s = ReadMultiBorderDecor(s, df);
+			if (!s)
+			{
+				return False;
+			}
+			DFS_FACE_TYPE(df->style) = MultiBorder;
+		}
 		else if (FMiniIconsSupported &&
 			 strncasecmp (style, "MiniIcon", 8) == 0)
 		{
Only in fvwm-patched/fvwm: builtins.c.orig
diff --unified --recursive --text fvwm-2.6.9/fvwm/menus.c fvwm-patched/fvwm/menus.c
--- fvwm-2.6.9/fvwm/menus.c	2020-08-21 16:09:27.176711008 -0600
+++ fvwm-patched/fvwm/menus.c	2020-08-21 16:15:29.887392857 -0600
@@ -2633,6 +2633,41 @@
 	return do_clear;
 }
 
+#define DRAWMENUBORDER(NUM, XX, YY) XCopyArea(\
+	dpy, pm[(NUM)]->picture, MR_WINDOW(mr), Scr.TransMaskGC,\
+	0, 0, pm[(NUM)]->width, pm[(NUM)]->height, (XX), (YY))
+static Bool paint_menu_multipixmap_background(
+	MenuRoot *mr, XEvent *pevent)
+{
+	MenuStyle *ms = MR_STYLE(mr);
+	int width, height, x, y;
+	int bw = MST_BORDER_WIDTH(mr);
+	FvwmPicture **pm;
+	pm = ST_FACE(ms).u.mb.pixmaps;
+
+	width = MR_WIDTH(mr);
+	height = MR_HEIGHT(mr);
+
+	FvwmPicture *p = pm[0];
+
+	width = MR_WIDTH(mr);
+	height = MR_HEIGHT(mr);
+
+	x = 0;
+
+	for (x = 0; x < width; x+=pm[1]->width) DRAWMENUBORDER(1, x, 0);
+	for (x = 0; x < width; x+=pm[5]->width) DRAWMENUBORDER(5, x, height-pm[5]->height);
+	for (x = 0; x < height; x+=pm[3]->height) DRAWMENUBORDER(3, width-pm[3]->height, x);
+	for (x = 0; x < height; x+=pm[7]->height) DRAWMENUBORDER(7, 0, x);
+
+	DRAWMENUBORDER(0, 0, 0);
+	DRAWMENUBORDER(2, width-pm[2]->width, 0);
+	DRAWMENUBORDER(4, width-pm[4]->width, height-pm[4]->height);
+	DRAWMENUBORDER(6, 0, height-pm[6]->height);
+
+	return False;
+}
+
 static Bool paint_menu_pixmap_background(
 	MenuRoot *mr, XEvent *pevent)
 {
@@ -2735,15 +2770,20 @@
 	{
 		/* Only the border was obscured. Redraw it centrally instead of
 		 * redrawing several menu items. */
-		RelieveRectangle(
-			dpy, MR_WINDOW(mr), 0, 0, MR_WIDTH(mr) - 1,
-			MR_HEIGHT(mr) - 1, (Pdepth < 2) ?
-			SHADOW_GC(MST_MENU_INACTIVE_GCS(mr)) :
-			HILIGHT_GC(MST_MENU_INACTIVE_GCS(mr)),
-			SHADOW_GC(MST_MENU_INACTIVE_GCS(mr)), bw);
+		if (ms && ST_FACE(ms).type == MultiPixmapMenu)
 		{
-			return;
+			paint_menu_multipixmap_background(mr, pevent);
 		}
+		else
+		{
+			RelieveRectangle(
+				dpy, MR_WINDOW(mr), 0, 0, MR_WIDTH(mr) - 1,
+				MR_HEIGHT(mr) - 1, (Pdepth < 2) ?
+				SHADOW_GC(MST_MENU_INACTIVE_GCS(mr)) :
+				HILIGHT_GC(MST_MENU_INACTIVE_GCS(mr)),
+				SHADOW_GC(MST_MENU_INACTIVE_GCS(mr)), bw);
+		}
+		return;
 	}
 	MR_IS_PAINTED(mr) = 1;
 	/* paint the menu background */
@@ -2808,6 +2848,9 @@
 		case PixmapMenu:
 			do_clear = paint_menu_pixmap_background(mr, pevent);
 			break;
+		case MultiPixmapMenu:
+			do_clear = paint_menu_multipixmap_background(mr, pevent);
+			break;
 		case TiledPixmapMenu:
 			XSetWindowBackgroundPixmap(
 				dpy, MR_WINDOW(mr), ST_FACE(ms).u.p->picture);
@@ -2820,11 +2863,14 @@
 		}
 	} /* if (ms) */
 	/* draw the relief */
-	RelieveRectangle(dpy, MR_WINDOW(mr), 0, 0, MR_WIDTH(mr) - 1,
-			 MR_HEIGHT(mr) - 1, (Pdepth < 2) ?
-			 SHADOW_GC(MST_MENU_INACTIVE_GCS(mr)) :
-			 HILIGHT_GC(MST_MENU_INACTIVE_GCS(mr)),
-			 SHADOW_GC(MST_MENU_INACTIVE_GCS(mr)), bw);
+	if (!(ms && ST_FACE(ms).type == MultiPixmapMenu))
+	{
+		RelieveRectangle(dpy, MR_WINDOW(mr), 0, 0, MR_WIDTH(mr) - 1,
+				 MR_HEIGHT(mr) - 1, (Pdepth < 2) ?
+				 SHADOW_GC(MST_MENU_INACTIVE_GCS(mr)) :
+				 HILIGHT_GC(MST_MENU_INACTIVE_GCS(mr)),
+				 SHADOW_GC(MST_MENU_INACTIVE_GCS(mr)), bw);
+	}
 	/* paint the menu items */
 	for (mi = MR_FIRST_ITEM(mr); mi != NULL; mi = MI_NEXT_ITEM(mi))
 	{
Only in fvwm-patched/fvwm: menus.c.orig
diff --unified --recursive --text fvwm-2.6.9/fvwm/menustyle.c fvwm-patched/fvwm/menustyle.c
--- fvwm-2.6.9/fvwm/menustyle.c	2020-08-21 16:09:27.176711008 -0600
+++ fvwm-patched/fvwm/menustyle.c	2020-08-21 16:15:29.887392857 -0600
@@ -159,6 +159,8 @@
 	char *token;
 	char *action = s;
 	FvwmPictureAttributes fpa;
+	FvwmPicture **pm;
+	int x, y;
 
 	s = GetNextToken(s, &style);
 	if (style && strncasecmp(style, "--", 2) == 0)
@@ -270,6 +272,58 @@
 			return False;
 		}
 	}
+	else if (StrEquals(style,"MultiBorder"))
+	{
+		fpa.mask = (Pdepth <= 8)? FPAM_DITHER:0;
+		pm = mf->u.mb.pixmaps;
+
+		for (x = 0; x < 8; x++)
+		{
+			if (pm[x])
+			{
+				PDestroyFvwmPicture(dpy, pm[x]);
+			}
+			s = GetNextToken(s, &token);
+			if (token)
+			{
+				pm[x] = PCacheFvwmPicture(dpy, Scr.NoFocusWin, NULL, token, fpa);
+				if (!pm[x])
+				{
+					fvwm_msg(ERR,
+						"menustyle_parse_face", "Pixmap '%s' could not be loaded",
+						token);
+				}
+			}
+			else
+			{
+				fvwm_msg(ERR,
+					"menustyle_parse_face", "Too few parameters for MultiBorder");
+			}
+			if (!token || !pm[x])
+			{
+				for (y = 0; y < x; y++)
+				{
+					if (pm[y])
+					{
+						PDestroyFvwmPicture(dpy, pm[y]);
+						pm[y] = 0;
+					}
+				}
+				free(style);
+				if (token)
+				{
+					free(token);
+				}
+				if (mf->type == MultiPixmapMenu)
+				{
+					mf->type = SimpleMenu;
+				}
+				return False;
+			}
+			mf->type = MultiPixmapMenu;
+			free(token);
+		}
+	}
 	else
 	{
 		if (verbose)
Only in fvwm-patched/fvwm: menustyle.c.orig
diff --unified --recursive --text fvwm-2.6.9/fvwm/menustyle.h fvwm-patched/fvwm/menustyle.h
--- fvwm-2.6.9/fvwm/menustyle.h	2020-08-21 16:09:27.176711008 -0600
+++ fvwm-patched/fvwm/menustyle.h	2020-08-21 16:15:29.887392857 -0600
@@ -195,6 +195,7 @@
 	GradientMenu,
 	PixmapMenu,
 	TiledPixmapMenu,
+	MultiPixmapMenu,
 	SolidMenu
 	/* max button is 8 (0x8) */
 } MenuFaceType;
@@ -245,6 +246,9 @@
 {
 	union
 	{
+		struct {
+			FvwmPicture *pixmaps[8];
+		} mb;
 		FvwmPicture *p;
 		Pixel back;
 		struct
diff --unified --recursive --text fvwm-2.6.9/fvwm/screen.h fvwm-patched/fvwm/screen.h
--- fvwm-2.6.9/fvwm/screen.h	2020-08-21 16:11:42.983734347 -0600
+++ fvwm-patched/fvwm/screen.h	2020-08-21 16:15:29.887392857 -0600
@@ -99,6 +99,7 @@
 	AdjustedPixmapButton,
 	ShrunkPixmapButton,
 	MultiPixmap,
+	MultiBorder,
 	MiniIconButton,
 	SolidButton,
 	ColorsetButton
@@ -158,6 +159,9 @@
 			Pixel *pixels;
 			unsigned short solid_flags;
 		} mp;
+		struct {
+			FvwmPicture *pixmaps[8];
+		} mb;
 		struct
 		{
 			int cs;
