--- 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;