LogoopenSUSE Build Service > Projects
Sign Up | Log In

View File xaw3d-thumb.patch of Package libXaw3d (Project X11:Utilities)

---
 include/X11/Xaw3d/Scrollbar.h  |    6 
 include/X11/Xaw3d/ScrollbarP.h |    3 
 include/X11/Xaw3d/SmeThreeD.h  |    3 
 include/X11/Xaw3d/SmeThreeDP.h |    1 
 include/X11/Xaw3d/ThreeD.h     |    3 
 include/X11/Xaw3d/ThreeDP.h    |    1 
 src/Layout.c                   |    2 
 src/Paned.c                    |    6 
 src/Scrollbar.c                |  533 ++++++++++++++++++++++++++++++-----------
 src/SmeThreeD.c                |   19 +
 src/ThreeD.c                   |    6 
 11 files changed, 436 insertions(+), 147 deletions(-)

Index: libXaw3d-1.6.2/include/X11/Xaw3d/Scrollbar.h
===================================================================
--- libXaw3d-1.6.2.orig/include/X11/Xaw3d/Scrollbar.h
+++ libXaw3d-1.6.2/include/X11/Xaw3d/Scrollbar.h
@@ -92,6 +92,7 @@ SOFTWARE.
  scrollRCursor	     Cursor		Cursor		XC_sb_right_arrow
  scrollUCursor	     Cursor		Cursor		XC_sb_up_arrow
  scrollVCursor	     Cursor		Cursor		XC_sb_v_double_arrow
+ scrollbarBackground ScrollbarBackground Pixel		XtDefaultForeground
  sensitive	     Sensitive		Boolean		True
  shown		     Shown		Float		0.0
  thickness	     Thickness		Dimension	14
@@ -99,6 +100,7 @@ SOFTWARE.
  thumbProc	     Callback		XtCallbackList	NULL
  topOfThumb	     TopOfThumb		Float		0.0
  pickTop	     PickTop		Boolean		False
+ pushThumb	     PushThumb		Boolean		True
  translations	     Translations	TranslationTable see source or doc
  width		     Width		Dimension	thickness or length
  x		     Position		Position	0
@@ -113,11 +115,15 @@ SOFTWARE.
 #define XtCMinimumThumb "MinimumThumb"
 #define XtCShown "Shown"
 #define XtCTopOfThumb "TopOfThumb"
+#define XtCScrollbarBackground "ScrollbarBackground"
 #define XtCPickTop "PickTop"
+#define XtCPushThumb "PushThumb"
 
 #define XtNminimumThumb "minimumThumb"
 #define XtNtopOfThumb "topOfThumb"
+#define XtNscrollbarBackground "scrollbarBackground"
 #define XtNpickTop "pickTop"
+#define XtNpushThumb "pushThumb"
 
 typedef struct _ScrollbarRec	  *ScrollbarWidget;
 typedef struct _ScrollbarClassRec *ScrollbarWidgetClass;
Index: libXaw3d-1.6.2/include/X11/Xaw3d/ScrollbarP.h
===================================================================
--- libXaw3d-1.6.2.orig/include/X11/Xaw3d/ScrollbarP.h
+++ libXaw3d-1.6.2/include/X11/Xaw3d/ScrollbarP.h
@@ -66,6 +66,7 @@ typedef struct {
     XtCallbackList thumbProc;	/* jump (to position) scroll */
     XtCallbackList jumpProc;	/* same as thumbProc but pass data by ref */
     Pixmap	  thumb;	/* thumb color */
+    Pixel 	  background;	/* background color */
 #ifndef XAW_ARROW_SCROLLBARS
     Cursor        upCursor;	/* scroll up cursor */
     Cursor        downCursor;	/* scroll down cursor */
@@ -91,9 +92,11 @@ typedef struct {
     char          direction;	/* a scroll has started; which direction */
 #endif
     GC		  gc;		/* a (shared) gc */
+    GC		  bgc;		/* a (shared) gc for background */
     Position	  topLoc;	/* Pixel that corresponds to top */
     Dimension	  shownLength;	/* Num pixels corresponding to shown */
     Boolean       pick_top;     /* pick thumb at top or anywhere*/
+    Boolean       push_thumb;   /* push thumb in or not */
 
 } ScrollbarPart;
 
Index: libXaw3d-1.6.2/include/X11/Xaw3d/SmeThreeD.h
===================================================================
--- libXaw3d-1.6.2.orig/include/X11/Xaw3d/SmeThreeD.h
+++ libXaw3d-1.6.2/include/X11/Xaw3d/SmeThreeD.h
@@ -46,6 +46,7 @@ SOFTWARE.
  bottomShadowContrast BottomShadowContrast Int           40
  userData             UserData             XtPointer     NULL
  beNiceToColormap     BeNiceToColormap     Boolean       False
+ invertBorder         InvertBorder         Boolean       False
 
 */
 
@@ -63,6 +64,8 @@ SOFTWARE.
 #define XtCBeNiceToColormap "BeNiceToColormap"
 #define XtNbeNiceToColourmap "beNiceToColormap"
 #define XtCBeNiceToColourmap "BeNiceToColormap"
+#define XtNinvertBorder "invertBorder"
+#define XtCInvertBorder "InvertBorder"
 #define XtNuserData "userData"
 #define XtCUserData "UserData"
 
Index: libXaw3d-1.6.2/include/X11/Xaw3d/SmeThreeDP.h
===================================================================
--- libXaw3d-1.6.2.orig/include/X11/Xaw3d/SmeThreeDP.h
+++ libXaw3d-1.6.2/include/X11/Xaw3d/SmeThreeDP.h
@@ -43,6 +43,7 @@ typedef struct {
     XtPointer	    user_data;
     Boolean	    be_nice_to_cmap;
     Boolean	    shadowed;
+    Boolean	    invert_border;
   } SmeThreeDPart;
 
 /* Full instance record declaration */
Index: libXaw3d-1.6.2/include/X11/Xaw3d/ThreeD.h
===================================================================
--- libXaw3d-1.6.2.orig/include/X11/Xaw3d/ThreeD.h
+++ libXaw3d-1.6.2/include/X11/Xaw3d/ThreeD.h
@@ -45,6 +45,7 @@ SOFTWARE.
  bottomShadowContrast BottomShadowContrast Int           40
  userData             UserData             XtPointer     NULL
  beNiceToColormap     BeNiceToColormap     Boolean       False
+ invertBorder	      InvertBorder	   Boolean	 False
  relief               Relief               XtRelief      XtReliefRaised
 
 */
@@ -63,6 +64,8 @@ SOFTWARE.
 #define XtCBeNiceToColormap "BeNiceToColormap"
 #define XtNbeNiceToColourmap "beNiceToColormap"
 #define XtCBeNiceToColourmap "BeNiceToColormap"
+#define XtNinvertBorder "invertBorder"
+#define XtCInvertBorder "InvertBorder"
 #define XtNuserData "userData"
 #define XtCUserData "UserData"
 #define XtNrelief "relief"
Index: libXaw3d-1.6.2/include/X11/Xaw3d/ThreeDP.h
===================================================================
--- libXaw3d-1.6.2.orig/include/X11/Xaw3d/ThreeDP.h
+++ libXaw3d-1.6.2/include/X11/Xaw3d/ThreeDP.h
@@ -43,6 +43,7 @@ typedef struct {
     GC		bot_shadow_GC;
     XtPointer	user_data;
     Boolean	be_nice_to_cmap;
+    Boolean	invert_border;
     XtRelief	relief;
   } ThreeDPart;
 
Index: libXaw3d-1.6.2/src/Layout.c
===================================================================
--- libXaw3d-1.6.2.orig/src/Layout.c
+++ libXaw3d-1.6.2/src/Layout.c
@@ -509,7 +509,7 @@ LookupVariable (BoxPtr child, XrmQuark q
 static double
 Evaluate (LayoutWidget l, BoxPtr box, ExprPtr expr, double natural)
 {
-    double	left, right, down;
+    double	left = 0.0, right = 0.0, down = 0.0;
     Widget	widget;
     SubInfoPtr	info;
 
Index: libXaw3d-1.6.2/src/Paned.c
===================================================================
--- libXaw3d-1.6.2.orig/src/Paned.c
+++ libXaw3d-1.6.2/src/Paned.c
@@ -1114,13 +1114,14 @@ ManageAndUnmanageGrips(PanedWidget pw)
    managedP = managed_grips = (WidgetList) XtMalloc(alloc_size);
    unmanagedP = unmanaged_grips = (WidgetList) XtMalloc(alloc_size);
 
-   ForAllChildren(pw, childP)
+   ForAllChildren(pw, childP) {
        if (IsPane(*childP) && HasGrip(*childP)) {
 	   if ( XtIsManaged(*childP) )
 	       *managedP++ = PaneInfo(*childP)->grip;
 	   else
 	       *unmanagedP++ = PaneInfo(*childP)->grip;
        }
+   }
 
    if (managedP != managed_grips) {
        *unmanagedP++ = *--managedP;   /* Last grip is never managed */
@@ -1615,7 +1616,7 @@ ChangeManaged(Widget w)
    ResortChildren(pw);
 
    pw->paned.num_panes = 0;
-   ForAllChildren(pw, childP)
+   ForAllChildren(pw, childP) {
        if ( IsPane(*childP) ) {
 	   if ( XtIsManaged(*childP) ) {
 	       Pane pane = PaneInfo(*childP);
@@ -1627,6 +1628,7 @@ ChangeManaged(Widget w)
 	   else
 	       break;		/* This list is already sorted. */
        }
+   }
 
    SetChildrenPrefSizes( (PanedWidget) w, size);
 
Index: libXaw3d-1.6.2/src/Scrollbar.c
===================================================================
--- libXaw3d-1.6.2.orig/src/Scrollbar.c
+++ libXaw3d-1.6.2/src/Scrollbar.c
@@ -134,14 +134,18 @@ static XtResource resources[] = {
        Offset(scrollbar.thumb), XtRImmediate, (XtPointer) XtUnspecifiedPixmap},
   {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
        Offset(scrollbar.foreground), XtRString, XtDefaultForeground},
+  {XtNscrollbarBackground, XtCScrollbarBackground, XtRPixel, sizeof(Pixel),
+       Offset(scrollbar.background), XtRString, XtDefaultForeground},
   {XtNshown, XtCShown, XtRFloat, sizeof(float),
        Offset(scrollbar.shown), XtRFloat, (XtPointer)&floatZero},
   {XtNtopOfThumb, XtCTopOfThumb, XtRFloat, sizeof(float),
        Offset(scrollbar.top), XtRFloat, (XtPointer)&floatZero},
   {XtNpickTop, XtCPickTop, XtRBoolean, sizeof(Boolean),
-       Offset(scrollbar.pick_top), XtRBoolean, (XtPointer) False},
+       Offset(scrollbar.pick_top), XtRImmediate, (XtPointer) False},
   {XtNminimumThumb, XtCMinimumThumb, XtRDimension, sizeof(Dimension),
-       Offset(scrollbar.min_thumb), XtRImmediate, (XtPointer) 7}
+       Offset(scrollbar.min_thumb), XtRImmediate, (XtPointer) 7},
+  {XtNpushThumb, XtCPushThumb, XtRBoolean, sizeof(Boolean),
+       Offset(scrollbar.push_thumb), XtRImmediate, (XtPointer) True}
 };
 #undef Offset
 
@@ -215,8 +219,7 @@ ScrollbarClassRec scrollbarClassRec = {
     /* change_sensitive	*/	XtInheritChangeSensitive
   },
   { /* threeD fields */
-    /* shadowdraw	*/	XtInheritXaw3dShadowDraw /*,*/
-    /* shadowboxdraw	*/	/*XtInheritXaw3dShadowBoxDraw*/
+    /* shadowdraw	*/	XtInheritXaw3dShadowDraw
   },
   { /* scrollbar fields */
     /* ignore		*/	0
@@ -228,7 +231,7 @@ WidgetClass scrollbarWidgetClass = (Widg
 
 #define NoButton -1
 #define PICKLENGTH(widget, x, y) \
-    ((widget->scrollbar.orientation == XtorientHorizontal) ? x : y)
+    ((widget->scrollbar.orientation == XtorientHorizontal) ? (x) : (y))
 #define MIN(x,y)	((x) < (y) ? (x) : (y))
 #define MAX(x,y)	((x) > (y) ? (x) : (y))
 
@@ -248,6 +251,23 @@ ClassInitialize(void)
 #endif
 
 /*
+   Used to swap X and Y coordinates when the scrollbar is horizontal.
+ */
+static void swap_short(short *a, short *b)
+{
+    short tmp = *a;
+    *a = *b;
+    *b = tmp;
+}
+static void swap(Dimension *a, Dimension *b)
+{
+    Dimension tmp = *a;
+    *a = *b;
+    *b = tmp;
+}
+
+
+/*
  The original Xaw Scrollbar's FillArea *really* relied on the fact that the
  server was going to clip at the window boundaries; so the logic was really
  rather sloppy.  To avoid drawing over the shadows and the arrows requires
@@ -297,161 +317,371 @@ FillArea (ScrollbarWidget sbw, Position
    erasing is done cleverly so that no flickering will occur. */
 
 static void
-PaintThumb (ScrollbarWidget sbw, XEvent *event)
+PaintThumb (ScrollbarWidget sbw, int pressed, int shadow)
 {
-    Dimension s                   = sbw->threeD.shadow_width;
-    Position  oldtop              = sbw->scrollbar.topLoc;
-    Position  oldbot              = oldtop + sbw->scrollbar.shownLength;
-    Dimension margin              = MARGIN (sbw);
-    Dimension tzl                 = sbw->scrollbar.length - margin - margin;
-    Position newtop, newbot;
-    Position  floor               = sbw->scrollbar.length - margin;
+    Dimension margin, tzl;
+    Position  floor;
+    Position  oldtop = sbw->scrollbar.topLoc;
+    Position  oldbot = oldtop + sbw->scrollbar.shownLength;
+    Position  newtop, newbot;
+    Dimension x, y;				/* upper-left corner of rectangle */
+    Dimension w, h;				/* size of rectangle */
+    Dimension sw = sbw->threeD.shadow_width;
+    Dimension th = sbw->scrollbar.thickness;
+    XPoint    ipt[4],opt[4];			/* inner and outer points of thumb */
+    XPoint    pt[4];				/* points used for drawing */
+    Display  *dpy = XtDisplay (sbw);
+    Window    win = XtWindow (sbw);
+    double    thumb_len;
+
+    margin = MARGIN (sbw);
+    tzl    = sbw->scrollbar.length - 2*margin;
+    floor  = sbw->scrollbar.length - margin;
 
     newtop = margin + (int)(tzl * sbw->scrollbar.top);
-    newbot = newtop + (int)(tzl * sbw->scrollbar.shown);
-    if (sbw->scrollbar.shown < 1.) newbot++;
-    if (newbot < newtop + (int)sbw->scrollbar.min_thumb +
-                        2 * (int)sbw->threeD.shadow_width)
-      newbot = newtop + sbw->scrollbar.min_thumb +
-                        2 * sbw->threeD.shadow_width;
-    if ( newbot >= floor ) {
-	newtop = floor-(newbot-newtop)+1;
+    thumb_len = tzl * sbw->scrollbar.shown;
+    newbot = newtop + (int)thumb_len;
+    if ((thumb_len - (int)thumb_len) > 0.5) ++newbot;
+
+    if (newbot < newtop + (int)sbw->scrollbar.min_thumb + 2 * (int)sw)
+	newbot = newtop + sbw->scrollbar.min_thumb + 2 * sw;
+
+    if (newbot >= floor) {
+	newtop = floor - (newbot-newtop) + 1;
 	newbot = floor;
     }
 
     sbw->scrollbar.topLoc = newtop;
     sbw->scrollbar.shownLength = newbot - newtop;
+
     if (XtIsRealized ((Widget) sbw)) {
-      /*  3D thumb wanted ?
-       */
-      if (s)
-	  {
-          if (newtop < oldtop) FillArea(sbw, oldtop, oldtop + s, 0);
-          if (newtop > oldtop) FillArea(sbw, oldtop, MIN(newtop, oldbot), 0);
-          if (newbot < oldbot) FillArea(sbw, MAX(newbot, oldtop), oldbot, 0);
-          if (newbot > oldbot) FillArea(sbw, oldbot - s, oldbot, 0);
-
-          if (sbw->scrollbar.orientation == XtorientHorizontal)
-	      {
-	      _ShadowSurroundedBox((Widget)sbw, (ThreeDWidget)sbw,
-		  newtop, s, newbot, sbw->core.height - s,
-		  sbw->threeD.relief, TRUE);
-	      }
-	  else
-	      {
-	      _ShadowSurroundedBox((Widget)sbw, (ThreeDWidget)sbw,
-		  s, newtop, sbw->core.width - s, newbot,
-		  sbw->threeD.relief, TRUE);
-	      }
-	  }
-      else
-	  {
-	  /*
-	    Note to Mitch: FillArea is (now) correctly implemented to
-	    not draw over shadows or the arrows. Therefore setting clipmasks
-	    doesn't seem to be necessary.  Correct me if I'm wrong!
-	  */
-          if (newtop < oldtop) FillArea(sbw, newtop, MIN(newbot, oldtop), 1);
-          if (newtop > oldtop) FillArea(sbw, oldtop, MIN(newtop, oldbot), 0);
-          if (newbot < oldbot) FillArea(sbw, MAX(newbot, oldtop), oldbot, 0);
-          if (newbot > oldbot) FillArea(sbw, MAX(newtop, oldbot), newbot, 1);
-	  }
+	/* 3D? */
+	if (sw) {
+	    GC top, bot;
+	    GC back = sbw->scrollbar.bgc;
+	    GC fore = sbw->scrollbar.gc;
+
+	    if ((pressed && sbw->scrollbar.push_thumb) ^ sbw->threeD.invert_border) {
+		top = sbw->threeD.bot_shadow_GC;
+		bot = sbw->threeD.top_shadow_GC;
+	    } else {
+		top = sbw->threeD.top_shadow_GC;
+		bot = sbw->threeD.bot_shadow_GC;
+	    }
+
+	    /* the space above the thumb */
+	    x = sw;
+	    y = margin;
+	    w = th - sw * 2;
+	    h = newtop - y;
+	    if (sbw->scrollbar.orientation == XtorientHorizontal) {
+		swap(&x, &y);
+		swap(&w, &h);
+	    }
+	    XFillRectangle(dpy, win, back, x, y, (unsigned int)w, (unsigned int)h);
+
+	    /* the space below the thumb */
+	    x = sw;
+	    y = newbot;
+	    w = th - sw * 2;
+	    h = tzl + margin - newbot;
+	    if (sbw->scrollbar.orientation == XtorientHorizontal) {
+		swap(&x, &y);
+		swap(&w, &h);
+	    }
+	    XFillRectangle(dpy, win, back, x, y, (unsigned int)w, (unsigned int)h);
+
+	    /* Return here if only the shadows should be repainted */
+	    if (shadow) return;
+
+	    /* the thumb itself */
+	    x = sw * 2;
+	    y = newtop + sw;
+	    w = th - sw * 4;
+	    h = newbot - newtop - 2 * sw;
+	    if (sbw->scrollbar.orientation == XtorientHorizontal) {
+		swap(&x, &y);
+		swap(&w, &h);
+	    }
+	    /* we can't use "w > 0" and "h > 0" because they are
+	    usually unsigned quantities */
+	    if (th - sw * 4 > 0 && newbot - newtop - 2 * sw > 0)
+            XFillRectangle(dpy, win, fore, x, y, (unsigned int)w, (unsigned int)h);
+
+	    /* the shades around the thumb
+
+	       o0 +--------------+ o3
+		  |\ i0      i3 /|
+   		  | +----------+ |
+  		  | |          | |
+		  | |          | |
+		  | |          | |
+		  | +----------+ |
+		  |/ i1      i2 \|
+	       o1 +--------------+ o2
+
+	     */
+	    opt[0].x = opt[1].x = sw;
+	    opt[0].y = opt[3].y = newtop;
+	    opt[2].x = opt[3].x = th - sw;
+	    opt[2].y = opt[1].y = newbot;
+
+	    ipt[0].x = ipt[1].x = opt[0].x + sw;
+	    ipt[0].y = ipt[3].y = opt[0].y + sw;
+	    ipt[2].x = ipt[3].x = opt[2].x - sw;
+	    ipt[2].y = ipt[1].y = opt[2].y - sw;
+
+	    /* make sure shades don't overlap */
+	    if (ipt[0].x > ipt[3].x)
+		ipt[3].x = ipt[2].x = ipt[1].x = ipt[0].x = (ipt[0].x + ipt[3].x) / 2;
+	    if (ipt[0].y > ipt[1].y)
+		ipt[3].y = ipt[2].y = ipt[1].y = ipt[0].y = (ipt[0].y + ipt[1].y) / 2;
+	    if (sbw->scrollbar.orientation == XtorientHorizontal) {
+		int n;
+		for (n = 0; n < 4; n++) {
+		    swap_short(&ipt[n].x, &ipt[n].y);
+		    swap_short(&opt[n].x, &opt[n].y);
+		}
+	    }
+
+	    /* left */
+	    pt[0] = opt[0];
+	    pt[1] = opt[1];
+	    pt[2] = ipt[1];
+	    pt[3] = ipt[0];
+	    XFillPolygon (dpy, win, top, pt, 4, Convex, CoordModeOrigin);
+
+	    /* top */
+ 	    pt[0] = opt[0];
+	    pt[1] = opt[3];
+	    pt[2] = ipt[3];
+ 	    pt[3] = ipt[0];
+ 	    XFillPolygon (dpy, win, top, pt, 4, Convex, CoordModeOrigin);
+
+	    /* bottom */
+	    pt[0] = opt[1];
+	    pt[1] = opt[2];
+	    pt[2] = ipt[2];
+	    pt[3] = ipt[1];
+	    XFillPolygon (dpy, win, bot, pt, 4, Convex, CoordModeOrigin);
+
+	    /* right */
+	    pt[0] = opt[3];
+	    pt[1] = opt[2];
+	    pt[2] = ipt[2];
+	    pt[3] = ipt[3];
+	    XFillPolygon (dpy, win, bot, pt, 4, Convex, CoordModeOrigin);
+
+
+	} else {
+	    /* Return here if only the shadows should be repainted */
+	    if (shadow) return;
+
+	    /*
+	     * Note to Mitch: FillArea is (now) correctly implemented to
+	     * not draw over shadows or the arrows. Therefore setting clipmasks
+	     * doesn't seem to be necessary.  Correct me if I'm wrong!
+	     */
+            if (newtop < oldtop) FillArea(sbw, newtop, MIN(newbot, oldtop), 1);
+            if (newtop > oldtop) FillArea(sbw, oldtop, MIN(newtop, oldbot), 0);
+            if (newbot < oldbot) FillArea(sbw, MAX(newbot, oldtop), oldbot, 0);
+            if (newbot > oldbot) FillArea(sbw, MAX(newtop, oldbot), newbot, 1);
+	}
     }
 }
 
 #ifdef XAW_ARROW_SCROLLBARS
 static void
-PaintArrows (ScrollbarWidget sbw)
-{
-    XPoint    pt[20];
-    Dimension s   = sbw->threeD.shadow_width;
-    Dimension t   = sbw->scrollbar.thickness;
-    Dimension l   = sbw->scrollbar.length;
-    Dimension tms = t - s, lms = l - s;
-    Dimension tm1 = t - 1;
-    Dimension lmt = l - t;
-    Dimension lp1 = lmt + 1;
-    Dimension sm1 = s - 1;
-    Dimension t2  = t / 2;
-    Dimension sa30 = (Dimension)(1.732 * s );  /* cotangent of 30 deg */
-    Display   *dpy = XtDisplay (sbw);
-    Window    win = XtWindow (sbw);
-    GC        top = sbw->threeD.top_shadow_GC;
-    GC        bot = sbw->threeD.bot_shadow_GC;
-
+PaintArrows (ScrollbarWidget sbw, int toppressed, int botpressed)
+{
+    XPoint	ipt[6], opt[6];	/* inner and outer points */
+    XPoint	rpt[4];		/* the rectangle around arrows */
+    XPoint	tpt[6];		/* temporary for args to XFillPolygon */
+    Dimension	sw = sbw->threeD.shadow_width;
+    Dimension	th = sbw->scrollbar.thickness;
+    Dimension	len = sbw->scrollbar.length;
+    Display    *dpy = XtDisplay (sbw);
+    Window	win = XtWindow (sbw);
+    GC		top, bot;
+    GC		back = sbw->scrollbar.bgc;
+    GC		fore = sbw->scrollbar.gc;
 
     if (XtIsRealized ((Widget) sbw)) {
 	/* 3D arrows?
          */
-	if (s) {
-	    /* upper/right arrow */
-	    pt[0].x = sm1;         pt[0].y = tm1;
-	    pt[1].x = t2;          pt[1].y = sm1;
-	    pt[2].x = t2;          pt[2].y = s + sa30;
-	    pt[3].x = sm1 + sa30;  pt[3].y = tms - 1;
-
-	    pt[4].x = sm1;         pt[4].y = tm1;
-	    pt[5].x = tms;         pt[5].y = tm1;
-	    pt[6].x = t2;          pt[6].y = sm1;
-	    pt[7].x = t2;          pt[7].y = s + sa30;
-	    pt[8].x = tms - sa30;  pt[8].y = tms - 1;
-	    pt[9].x = sm1 + sa30;  pt[9].y = tms - 1;
-
-	    /* lower/left arrow */
-	    pt[10].x = tms;        pt[10].y = lp1;
-	    pt[11].x = s;          pt[11].y = lp1;
-	    pt[12].x = t2;         pt[12].y = lms;
-	    pt[13].x = t2;         pt[13].y = lms - sa30;
-	    pt[14].x = s + sa30;   pt[14].y = lmt + s + 1;
-	    pt[15].x = tms - sa30; pt[15].y = lmt + s + 1;
-
-	    pt[16].x = tms;        pt[16].y = lp1;
-	    pt[17].x = t2;         pt[17].y = lms;
-	    pt[18].x = t2;         pt[18].y = lms - sa30;
-	    pt[19].x = tms - sa30; pt[19].y = lmt + s + 1;
+	if (sw) {
+	    /*
+		The points are numbered like this:
+
+		r0 +---------+ r3
+		   |    ^ o2 |
+		   |   /|\   |   a = i0
+		   |  /c^ \  |   b = i1
+		   | / / \ \ |   c = i2
+		   |/a<--->b\|
+		o0 +---------+ o1
+		   |         |
+		   |         |
+		o3 +---------+ o4
+		   |\d<--->e/|
+		   | \ \ / / |   d = i3
+		   |  \fv /  |   e = i4
+		   |   \|/   |   f = i5
+		   |    v o5 |
+		r1 +---------+ r2
+	     */
+
+	    rpt[0].x = rpt[1].x = opt[0].x = opt[3].x = sw;
+	    ipt[0].x = ipt[3].x = sw * 2.5;
+	    opt[2].x = opt[5].x = ipt[2].x = ipt[5].x = th / 2;
+	    ipt[1].x = ipt[4].x = th - (int)(sw * 2.5);
+	    rpt[2].x = rpt[3].x = opt[1].x = opt[4].x = th - sw;
+
+	    rpt[0].y = rpt[3].y = opt[2].y = sw;
+	    ipt[2].y = sw * 3.2;
+	    ipt[0].y = ipt[1].y = th - sw;
+	    opt[0].y = opt[1].y = th;
+	    opt[3].y = opt[4].y = len - th;
+	    ipt[3].y = ipt[4].y = len - th + sw;
+	    ipt[5].y = len - (int)(sw * 3.2);
+	    rpt[1].y = rpt[2].y = opt[5].y = len - sw;
+
+            /* some ugly kludges to make them look right */
+	    opt[2].y--;
+	    opt[0].x--;
+	    ipt[2].y--;
+	    ipt[0].x--;
+
+            /* make sure shades don't overlap */
+	    if (ipt[0].x > ipt[1].x) {
+		Dimension tmp = (ipt[0].x + ipt[1].x) / 2;
+		ipt[4].x = ipt[3].x = ipt[1].x = ipt[0].x = tmp;
+	    }
+            if (ipt[0].y < ipt[2].y) {
+		ipt[2].y = ipt[1].y = ipt[0].y = (ipt[0].y + ipt[2].y) / 2;
+		ipt[5].y = ipt[4].y = ipt[3].y = (ipt[3].y + ipt[5].y) / 2;
+            }
 
 	    /* horizontal arrows require that x and y coordinates be swapped */
 	    if (sbw->scrollbar.orientation == XtorientHorizontal) {
 		int n;
-		int swap;
-		for (n = 0; n < 20; n++) {
-		    swap = pt[n].x;
-		    pt[n].x = pt[n].y;
-		    pt[n].y = swap;
+		for (n = 0; n < 6; n++) {
+		    swap(&ipt[n].x, &ipt[n].y);
+		    swap(&opt[n].x, &opt[n].y);
 		}
+		for (n = 0; n < 4; n++)
+		swap(&rpt[n].x, &rpt[n].y);
+	    }
+
+	    if (toppressed ^ sbw->threeD.invert_border) {
+		top = sbw->threeD.bot_shadow_GC;
+		bot = sbw->threeD.top_shadow_GC;
+	    } else {
+		top = sbw->threeD.top_shadow_GC;
+		bot = sbw->threeD.bot_shadow_GC;
+	    }
+
+	    /* top-left background */
+	    tpt[0] = rpt[0];
+	    tpt[1] = opt[0];
+	    tpt[2] = opt[2];
+	    XFillPolygon (dpy, win, back, tpt, 3, Convex, CoordModeOrigin);
+
+	    /* top-right background */
+	    tpt[0] = rpt[3];
+	    tpt[1] = opt[2];
+	    tpt[2] = opt[1];
+	    XFillPolygon (dpy, win, back, tpt, 3, Convex, CoordModeOrigin);
+
+	    /* the right shade */
+	    tpt[0] = opt[1];
+	    tpt[1] = opt[2];
+	    tpt[2] = ipt[2];
+	    tpt[3] = ipt[1];
+	    XFillPolygon (dpy, win, bot, tpt, 4, Convex, CoordModeOrigin);
+
+	    /* the left shade */
+	    tpt[0] = opt[2];
+	    tpt[1] = opt[0];
+	    tpt[2] = ipt[0];
+	    tpt[3] = ipt[2];
+	    XFillPolygon (dpy, win, top, tpt, 4, Convex, CoordModeOrigin);
+
+	    /* the bottom shade */
+	    tpt[0] = opt[0];
+	    tpt[1] = opt[1];
+	    tpt[2] = ipt[1];
+	    tpt[3] = ipt[0];
+	    XFillPolygon (dpy, win, bot, tpt, 4, Convex, CoordModeOrigin);
+
+	    /* the arrow itself */
+	    XFillPolygon (dpy, win, fore, ipt, 3, Convex, CoordModeOrigin);
+
+	    if (botpressed ^ sbw->threeD.invert_border) {
+		top = sbw->threeD.bot_shadow_GC;
+		bot = sbw->threeD.top_shadow_GC;
+	    } else {
+		top = sbw->threeD.top_shadow_GC;
+		bot = sbw->threeD.bot_shadow_GC;
 	    }
-	    XFillPolygon (dpy, win, top, pt, 4, Complex, CoordModeOrigin);
-	    XFillPolygon (dpy, win, bot, pt + 4, 6, Complex, CoordModeOrigin);
-	    XFillPolygon (dpy, win, top, pt + 10, 6, Complex, CoordModeOrigin);
-	    XFillPolygon (dpy, win, bot, pt + 16, 4, Complex, CoordModeOrigin);
+
+	    /* bottom-left background */
+	    tpt[0] = rpt[1];
+	    tpt[1] = opt[5];
+	    tpt[2] = opt[3];
+	    XFillPolygon (dpy, win, back, tpt, 3, Convex, CoordModeOrigin);
+
+	    /* bottom-right background */
+	    tpt[0] = rpt[2];
+	    tpt[1] = opt[4];
+	    tpt[2] = opt[5];
+	    XFillPolygon (dpy, win, back, tpt, 3, Convex, CoordModeOrigin);
+
+	    /* the left shade */
+	    tpt[0] = opt[3];
+	    tpt[1] = opt[5];
+	    tpt[2] = ipt[5];
+	    tpt[3] = ipt[3];
+	    XFillPolygon (dpy, win, top, tpt, 4, Convex, CoordModeOrigin);
+
+	    /* the right shade */
+	    tpt[0] = opt[5];
+	    tpt[1] = opt[4];
+	    tpt[2] = ipt[4];
+	    tpt[3] = ipt[5];
+	    XFillPolygon (dpy, win, bot, tpt, 4, Convex, CoordModeOrigin);
+
+	    /* the top shade */
+	    tpt[0] = opt[4];
+	    tpt[1] = opt[3];
+	    tpt[2] = ipt[3];
+	    tpt[3] = ipt[4];
+	    XFillPolygon (dpy, win, top, tpt, 4, Convex, CoordModeOrigin);
+
+	    /* the arrow itself */
+	    XFillPolygon (dpy, win, fore, ipt+3, 3, Convex, CoordModeOrigin);
 
 	} else {
-	    pt[0].x = 0;      pt[0].y = tm1;
-	    pt[1].x = t;      pt[1].y = tm1;
-	    pt[2].x = t2;     pt[2].y = 0;
-
-	    pt[3].x = 0;      pt[3].y = lp1;
-	    pt[4].x = t;      pt[4].y = lp1;
-	    pt[5].x = t2;     pt[5].y = l;
+
+	    tpt[0] = opt[0];
+	    tpt[1] = opt[1];
+	    tpt[2] = opt[2];
+	    tpt[3] = opt[3];
+	    tpt[4] = opt[4];
+	    tpt[5] = opt[5];
 
 	    /* horizontal arrows require that x and y coordinates be swapped */
 	    if (sbw->scrollbar.orientation == XtorientHorizontal) {
 		int n;
-		int swap;
-		for (n = 0; n < 6; n++) {
-		    swap = pt[n].x;
-		    pt[n].x = pt[n].y;
-		    pt[n].y = swap;
-		}
+		for (n = 0; n < 6; n++)
+		    swap(&tpt[n].x, &tpt[n].y);
 	    }
 	    /* draw the up/left arrow */
-	    XFillPolygon (dpy, win, sbw->scrollbar.gc,
-			  pt, 3,
-			  Convex, CoordModeOrigin);
+	    XFillPolygon (dpy, win, fore, tpt, 3, Convex, CoordModeOrigin);
+
 	    /* draw the down/right arrow */
-	    XFillPolygon (dpy, win, sbw->scrollbar.gc,
-			  pt+3, 3,
-			  Convex, CoordModeOrigin);
+	    XFillPolygon (dpy, win, fore, tpt+3, 3, Convex, CoordModeOrigin);
+
 	}
     }
 }
@@ -471,6 +701,7 @@ Destroy (Widget w)
 	XtRemoveTimeOut (sbw->scrollbar.timer_id);
 #endif
     XtReleaseGC (w, sbw->scrollbar.gc);
+    XtReleaseGC (w, sbw->scrollbar.bgc);
 }
 
 /*	Function Name: CreateGC
@@ -487,9 +718,22 @@ CreateGC (Widget w)
     XtGCMask mask;
     unsigned int depth = 1;
 
+    /* make GC for scrollbar background */
+    if (sbw->threeD.be_nice_to_cmap ||
+	DefaultDepthOfScreen (XtScreen(w)) == 1) {
+	mask = GCTile | GCFillStyle;
+	gcValues.tile = sbw->threeD.bot_shadow_pxmap;
+	gcValues.fill_style = FillTiled;
+    } else {
+	mask = GCForeground;
+	gcValues.foreground = sbw->scrollbar.background;
+    }
+    sbw->scrollbar.bgc = XtGetGC(w, mask, &gcValues);
+
+    /* make GC for scrollbar foreground */
     if (sbw->scrollbar.thumb == XtUnspecifiedPixmap) {
         sbw->scrollbar.thumb = XmuCreateStippledPixmap (XtScreen(w),
-					(Pixel) 1, (Pixel) 0, depth);
+					(Pixel) 0, (Pixel) 0, depth);
     } else if (sbw->scrollbar.thumb != None) {
 	Window root;
 	int x, y;
@@ -520,6 +764,9 @@ CreateGC (Widget w)
     /* the creation should be non-caching, because */
     /* we now set and clear clip masks on the gc returned */
     sbw->scrollbar.gc = XtGetGC (w, mask, &gcValues);
+    gcValues.foreground = sbw->scrollbar.foreground;
+    gcValues.background = sbw->core.background_pixel;
+    mask = GCForeground | GCBackground;
 }
 
 static void
@@ -610,8 +857,10 @@ SetValues(Widget current, Widget request
     if (XtIsRealized (desired)) {
 	if (sbw->scrollbar.foreground != dsbw->scrollbar.foreground ||
 	    sbw->core.background_pixel != dsbw->core.background_pixel ||
-	    sbw->scrollbar.thumb != dsbw->scrollbar.thumb) {
+	    sbw->scrollbar.thumb != dsbw->scrollbar.thumb ||
+	    sbw->scrollbar.background != dsbw->scrollbar.background) {
 	    XtReleaseGC (desired, sbw->scrollbar.gc);
+	    XtReleaseGC (desired, sbw->scrollbar.bgc);
 	    CreateGC (desired);
 	    redraw = TRUE;
 	}
@@ -658,11 +907,14 @@ Redisplay(Widget w, XEvent *event, Regio
 	XRectInRegion (region, x, y, width, height) != RectangleOut) {
 	/* Forces entire thumb to be painted. */
 	sbw->scrollbar.topLoc = -(sbw->scrollbar.length + 1);
-	PaintThumb (sbw, event);
+	PaintThumb (sbw, 0, 0);
+    } else {
+	/* Redraw the surounding shadows of the thumb */
+	PaintThumb (sbw, 0, 1);
     }
 #ifdef XAW_ARROW_SCROLLBARS
     /* we'd like to be region aware here!!!! */
-    PaintArrows (sbw);
+    PaintArrows (sbw, 0, 0);
 #endif
 
 }
@@ -888,12 +1140,13 @@ NotifyScroll (Widget w, XEvent *event, S
     if (PICKLENGTH (sbw,x,y) < sbw->scrollbar.thickness) {
 	/* handle first arrow zone */
 	call_data = -MAX (A_FEW_PIXELS, sbw->scrollbar.length / 20);
-	XtCallCallbacks (w, XtNscrollProc, (XtPointer)(call_data));
+	XtCallCallbacks (w, XtNscrollProc, (XtPointer) call_data);
 	/* establish autoscroll */
 	sbw->scrollbar.timer_id =
 	    XtAppAddTimeOut (XtWidgetToApplicationContext (w),
 				(unsigned long) 300, RepeatNotify, (XtPointer)w);
 	sbw->scrollbar.scroll_mode = 1;
+	PaintArrows (sbw, 1, 0);
     } else if (PICKLENGTH (sbw,x,y) > sbw->scrollbar.length - sbw->scrollbar.thickness) {
 	/* handle last arrow zone */
 	call_data = MAX (A_FEW_PIXELS, sbw->scrollbar.length / 20);
@@ -903,6 +1156,7 @@ NotifyScroll (Widget w, XEvent *event, S
 	    XtAppAddTimeOut (XtWidgetToApplicationContext (w),
 				(unsigned long) 300, RepeatNotify, (XtPointer)w);
 	sbw->scrollbar.scroll_mode = 3;
+	PaintArrows (sbw, 0, 1);
     } else if (PICKLENGTH (sbw, x, y) < sbw->scrollbar.topLoc) {
 	/* handle zone "above" the thumb */
 	call_data = - sbw->scrollbar.length;
@@ -911,10 +1165,10 @@ NotifyScroll (Widget w, XEvent *event, S
 	/* handle zone "below" the thumb */
 	call_data = sbw->scrollbar.length;
 	XtCallCallbacks (w, XtNscrollProc, (XtPointer)(call_data));
-    } else
-	{
-	/* handle the thumb in the motion notify action */
-	}
+    } else {
+	/* but we need to re-paint it "pressed in" here */
+	PaintThumb (sbw, 1, 0);
+    }
     return;
 }
 #else /* XAW_ARROW_SCROLLBARS */
@@ -976,6 +1230,9 @@ EndScroll(Widget w, XEvent *event, Strin
     /* no need to remove any autoscroll timeout; it will no-op */
     /* because the scroll_mode is 0 */
     /* but be sure to remove timeout in destroy proc */
+    /* release all buttons */
+    PaintArrows (sbw, 0, 0);
+    PaintThumb (sbw, 0, 0);
 #else
     XtVaSetValues (w, XtNcursor, sbw->scrollbar.inactiveCursor, NULL);
     XFlush (XtDisplay (w));
@@ -1044,7 +1301,7 @@ MoveThumb (Widget w, XEvent *event, Stri
 #ifdef XAW_ARROW_SCROLLBARS
     sbw->scrollbar.scroll_mode = 2; /* indicate continuous scroll */
 #endif
-    PaintThumb (sbw, event);
+    PaintThumb (sbw, 1, 0);
     XFlush (XtDisplay (w));	/* re-draw it before Notifying */
 }
 
@@ -1131,6 +1388,6 @@ void XawScrollbarSetThumb (Widget w,
     sbw->scrollbar.shown = (shown > 1.0) ? 1.0 :
 				(shown >= 0.0) ? shown : sbw->scrollbar.shown;
 
-    PaintThumb (sbw, NULL);
+    PaintThumb (sbw, 0, 0);
 }
 
Index: libXaw3d-1.6.2/src/SmeThreeD.c
===================================================================
--- libXaw3d-1.6.2.orig/src/SmeThreeD.c
+++ libXaw3d-1.6.2/src/SmeThreeD.c
@@ -71,6 +71,9 @@ static XtResource resources[] = {
     {XtNborderWidth, XtCBorderWidth, XtRDimension, sizeof(Dimension),
 	XtOffsetOf(RectObjRec,rectangle.border_width), XtRImmediate,
 	(XtPointer)0}
+    ,
+    {XtNinvertBorder, XtCInvertBorder, XtRBoolean, sizeof(Boolean),
+	offset(sme_threeD.invert_border), XtRImmediate, (XtPointer) False},
 };
 
 #undef offset
@@ -210,7 +213,7 @@ AllocTopShadowPixmap (Widget new)
     Display		*dpy = XtDisplayOfObject (new);
     Screen		*scn = XtScreenOfObject (new);
     unsigned long	top_fg_pixel = 0, top_bg_pixel = 0;
-    char		*pm_data;
+    char		*pm_data = NULL;
     Boolean		create_pixmap = FALSE;
 
     /*
@@ -266,7 +269,7 @@ AllocBotShadowPixmap (Widget new)
     Display		*dpy = XtDisplayOfObject (new);
     Screen		*scn = XtScreenOfObject (new);
     unsigned long	bot_fg_pixel = 0, bot_bg_pixel = 0;
-    char		*pm_data;
+    char		*pm_data = NULL;
     Boolean		create_pixmap = FALSE;
 
     if (DefaultDepthOfScreen (scn) == 1) {
@@ -562,8 +565,16 @@ _XawSme3dDrawShadows(Widget gw)
 
 	if (tdo->sme_threeD.shadowed)
 	{
-	    top = tdo->sme_threeD.top_shadow_GC;
-	    bot = tdo->sme_threeD.bot_shadow_GC;
+	    if (tdo->sme_threeD.invert_border)
+	    {
+		bot = tdo->sme_threeD.top_shadow_GC;
+		top = tdo->sme_threeD.bot_shadow_GC;
+	    }
+	    else
+	    {
+		top = tdo->sme_threeD.top_shadow_GC;
+		bot = tdo->sme_threeD.bot_shadow_GC;
+	    }
 	}
 	else
 	    top = bot = tdo->sme_threeD.erase_GC;
Index: libXaw3d-1.6.2/src/ThreeD.c
===================================================================
--- libXaw3d-1.6.2.orig/src/ThreeD.c
+++ libXaw3d-1.6.2/src/ThreeD.c
@@ -73,6 +73,8 @@ static XtResource resources[] = {
     {XtNborderWidth, XtCBorderWidth, XtRDimension, sizeof(Dimension),
 	XtOffsetOf(RectObjRec,rectangle.border_width), XtRImmediate,
 	(XtPointer)0},
+    {XtNinvertBorder, XtCInvertBorder, XtRBoolean, sizeof(Boolean),
+	offset(threeD.invert_border), XtRImmediate, (XtPointer) False},
     {XtNrelief, XtCRelief, XtRRelief, sizeof(XtRelief),
 	offset(threeD.relief), XtRString, (XtPointer) defRelief}
 };
@@ -637,7 +639,7 @@ _Xaw3dDrawShadows (Widget gw, XEvent *ev
 	GC		realbot = tdw->threeD.bot_shadow_GC;
 	GC		top, bot;
 
-	if (out) {
+	if ((out ^ tdw->threeD.invert_border)) {
 	    top = tdw->threeD.top_shadow_GC;
 	    bot = tdw->threeD.bot_shadow_GC;
 	} else {
@@ -774,7 +776,7 @@ _ShadowSurroundedBox(Widget gw, ThreeDWi
 	Window win = XtWindow(gw);
 	GC top, bot;
 
-	if (out)
+	if ((out ^ tdw->threeD.invert_border))
 	{
 	    top = tdw->threeD.top_shadow_GC;
 	    bot = tdw->threeD.bot_shadow_GC;