# HG changeset patch # User Stefan Monnier # Date 944790021 0 # Node ID 03a6016a38bf83cdf1ffac7c802fa2bb540447d4 # Parent 5e97315b6f1172e549bb6c7f9bc07c7cb788e14a (#includes): Allow compilation with only Xaw. (xaw3d_arrow_scroll, xaw3d_pick_top): New variables. (xt_action_hook): Replace XAW3D by XAW. (xaw3d_jump_callback): Renamed to xaw_jump_callback. (xaw_jump_callback): Renamed from xaw3d_jump_callback. Determine epsilon dynamically and don't try to be too clever. (xaw3d_scroll_callback): Renamed to xaw_scroll_callback. (xaw_scroll_callback): Renamed from xaw3d_scroll_callback. Handle both Xaw3d with arrow-scrollbars and with Xaw-style scrollbar (using `ratio'). (x_create_toolkit_scroll_bar): Try to detect which style of Xaw3d scrollbar we have so as to set it up more optimally and to fix xaw3d_arrow_scroll and xaw3d_pick_top. (x_set_toolkit_scroll_bar_thumb): Try to maintain 2 spare pixels at the bottom of the Xaw3d scrollbar, to work around its tendency to refuse shrinking the thumb. Also make sure that `XawScrollbarSetThumb' is not ignored, using a major gross hack. (x_initialize): Init default values for xaw3d_arrow_scroll and xaw3d_pick_top. diff -r 5e97315b6f11 -r 03a6016a38bf src/xterm.c --- a/src/xterm.c Fri Dec 10 01:39:53 1999 +0000 +++ b/src/xterm.c Fri Dec 10 01:40:21 1999 +0000 @@ -118,13 +118,21 @@ #include /* for LESSTIF_VERSION */ #include #include -#elif defined HAVE_XAW3D +#else /* !USE_MOTIF i.e. use Xaw */ + +#ifdef HAVE_XAW3D #include -#include #include #define ARROW_SCROLLBAR #include -#endif /* HAVE_XAW3D */ +#else /* !HAVE_XAW3D */ +#include +#include +#endif /* !HAVE_XAW3D */ +#ifndef XtNpickTop +#define XtNpickTop "pickTop" +#endif /* !XtNpickTop */ +#endif /* !USE_MOTIF */ #endif /* USE_TOOLKIT_SCROLL_BARS */ #endif /* USE_X_TOOLKIT */ @@ -7101,9 +7109,20 @@ static int last_scroll_bar_part; +/* Whether this is an Xaw with arrow-scrollbars. This should imply + that movements of 1/20 of the screen size are mapped to up/down. */ + +static Boolean xaw3d_arrow_scroll; + +/* Whether the drag scrolling maintains the mouse at the top of the + thumb. If not, resizing the thumb needs to be done more carefully + to avoid jerkyness. */ + +static Boolean xaw3d_pick_top; + /* Action hook installed via XtAppAddActionHook when toolkit scroll - bars are used.. The hoos is responsible for detecting when + bars are used.. The hook is responsible for detecting when the user ends an interaction with the scroll bar, and generates a `end-scroll' scroll_bar_click' event if so. */ @@ -7123,12 +7142,10 @@ #ifdef USE_MOTIF scroll_bar_p = XmIsScrollBar (widget); end_action = "Release"; -#elif defined HAVE_XAW3D +#else /* !USE_MOTIF i.e. use Xaw */ scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass); end_action = "EndScroll"; -#else - #error unknown scroll bar toolkit -#endif /* HAVE_XAW3D */ +#endif /* USE_MOTIF */ /* Although LessTif uses XtTimeouts like Xaw3d, the timer hack to let Xt timeouts be processed doesn't work. */ @@ -7313,40 +7330,39 @@ } -#else /* not USE_MOTIF, i.e. XAW3D. */ - - -/* Xaw3d scroll bar callback. Invoked when the thumb is dragged. +#else /* !USE_MOTIF, i.e. Xaw. */ + + +/* Xaw scroll bar callback. Invoked when the thumb is dragged. WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the scroll bar struct. CALL_DATA is a pointer to a float saying where the thumb is. */ static void -xaw3d_jump_callback (widget, client_data, call_data) +xaw_jump_callback (widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { struct scroll_bar *bar = (struct scroll_bar *) client_data; float top = *(float *) call_data; float shown; - int whole, portion; - int dragging_down_p, part; - double epsilon = 0.01; + int whole, portion, height; + int part; /* Get the size of the thumb, a value between 0 and 1. */ BLOCK_INPUT; - XtVaGetValues (widget, XtNshown, &shown, NULL); + XtVaGetValues (widget, XtNshown, &shown, XtNheight, &height, NULL); UNBLOCK_INPUT; whole = 10000000; portion = shown < 1 ? top * whole : 0; - dragging_down_p = (INTEGERP (bar->dragging) - && XINT (bar->dragging) < portion); - - if (shown < 1 - && (abs (top + shown - 1) < epsilon - || (dragging_down_p - && last_scroll_bar_part == scroll_bar_down_arrow))) + + if (shown < 1 && (abs (top + shown - 1) < 1.0/height)) + /* Some derivatives of Xaw refuse to shrink the thumb when you reach + the bottom, so we force the scrolling whenever we see that we're + too close to the bottom (in x_set_toolkit_scroll_bar_thumb + we try to ensure that we always stay two pixels away from the + bottom). */ part = scroll_bar_down_arrow; else part = scroll_bar_handle; @@ -7358,8 +7374,8 @@ } -/* Xaw3d scroll bar callback. Invoked for incremental scrolling., - i.e. line or page up or down. WIDGET is the Xaw3d scroll bar +/* Xaw scroll bar callback. Invoked for incremental scrolling., + i.e. line or page up or down. WIDGET is the Xaw scroll bar widget. CLIENT_DATA is a pointer to the scroll_bar structure for the scroll bar. CALL_DATA is an integer specifying the action that has taken place. It's magnitude is in the range 0..height of the @@ -7367,7 +7383,7 @@ Values < height of scroll bar mean line-wise movement. */ static void -xaw3d_scroll_callback (widget, client_data, call_data) +xaw_scroll_callback (widget, client_data, call_data) Widget widget; XtPointer client_data, call_data; { @@ -7381,25 +7397,20 @@ XtVaGetValues (widget, XtNheight, &height, NULL); UNBLOCK_INPUT; - if (position < 0) - { - if (abs (position) < height) - part = scroll_bar_up_arrow; - else - part = scroll_bar_above_handle; - } - else - { - if (abs (position) < height) - part = scroll_bar_down_arrow; - else - part = scroll_bar_below_handle; - } + if (abs (position) >= height) + part = (position < 0) ? scroll_bar_above_handle : scroll_bar_below_handle; + + /* If Xaw3d was compiled with ARROW_SCROLLBAR, + it maps line-movement to call_data = max(5, height/20). */ + else if (xaw3d_arrow_scroll && abs (position) <= max (5, height / 20)) + part = (position < 0) ? scroll_bar_up_arrow : scroll_bar_down_arrow; + else + part = scroll_bar_move_ratio; window_being_scrolled = bar->window; bar->dragging = Qnil; last_scroll_bar_part = part; - x_send_scroll_bar_event (bar->window, part, 0, 0); + x_send_scroll_bar_event (bar->window, part, position, height); } @@ -7482,7 +7493,7 @@ XDefineCursor (XtDisplay (widget), XtWindow (widget), f->output_data.x->nontext_cursor); -#elif defined HAVE_XAW3D +#else /* !USE_MOTIF i.e. use Xaw */ /* Set resources. Create the widget. The background of the Xaw3d scroll bar widget is a little bit light for my taste. @@ -7490,8 +7501,9 @@ to their taste with `emacs*verticalScrollBar.background: xxx'. */ XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac; XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac; - XtSetArg (av[ac], XtNcursorName, "left_ptr"); ++ac; - XtSetArg (av[ac], XtNbeNiceToColormap, True); ++ac; + /* For smoother scrolling with Xaw3d -sm */ + /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */ + /* XtSetArg (av[ac], XtNbeNiceToColormap, True); ++ac; */ pixel = f->output_data.x->scroll_bar_foreground_pixel; if (pixel != -1) @@ -7509,16 +7521,29 @@ widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass, f->output_data.x->edit_widget, av, ac); + + { + char *initial = ""; + char *val = initial; + XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val, + XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL); + if (val == initial) + { /* ARROW_SCROLL */ + xaw3d_arrow_scroll = True; + /* Isn't that just a personal preference ? -sm */ + XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL); + } + } /* Define callbacks. */ - XtAddCallback (widget, XtNjumpProc, xaw3d_jump_callback, (XtPointer) bar); - XtAddCallback (widget, XtNscrollProc, xaw3d_scroll_callback, + XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar); + XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback, (XtPointer) bar); /* Realize the widget. Only after that is the X window created. */ XtRealizeWidget (widget); -#endif /* HAVE_XAW3D */ +#endif /* !USE_MOTIF */ /* Install an action hook that let's us detect when the user finishes interacting with a scroll bar. */ @@ -7562,7 +7587,7 @@ unsigned char flags; XmScrollBarWidget sb; - /* Slider size. Must be in the range [1 .. MAX - MIN] where NAX + /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX is the scroll bar's maximum and MIN is the scroll bar's minimum value. */ size = shown * XM_SB_RANGE; @@ -7590,7 +7615,7 @@ XmScrollBarSetValues (widget, value, size, 0, 0, False); else if (last_scroll_bar_part == scroll_bar_down_arrow) /* This has the negative side effect that the slider value is - not would it would be if we scrolled here using line-wise or + not what it would be if we scrolled here using line-wise or page-wise movement. */ XmScrollBarSetValues (widget, value, XM_SB_RANGE - value, 0, 0, False); else @@ -7610,43 +7635,61 @@ sb->scrollBar.arrow2_selected = arrow2_selected; sb->scrollBar.flags = flags; } -#elif defined HAVE_XAW3D +#else /* !USE_MOTIF i.e. use Xaw */ { - /* Restrict to [0 1]. */ - top = max (0, min (1, top)); - shown = max (0, min (1, shown)); + float old_top, old_shown; + Dimension height; + XtVaGetValues (widget, + XtNtopOfThumb, &old_top, + XtNshown, &old_shown, + XtNheight, &height, + NULL); + + /* Massage the top+shown values. */ + if (NILP (bar->dragging) || last_scroll_bar_part == scroll_bar_down_arrow) + top = max (0, min (1, top)); + else + top = old_top; + /* Keep two pixels available for moving the thumb down. */ + shown = max (0, min (1 - top - (2.0 / height), shown)); /* If the call to XawScrollbarSetThumb below doesn't seem to work, check that your system's configuration file contains a define for `NARROWPROTO'. See s/freebsd.h for an example. */ - if (NILP (bar->dragging)) + if (top != old_top || shown != old_shown) { - float old_top, old_shown; - XtVaGetValues (widget, XtNtopOfThumb, &old_top, XtNshown, &old_shown, - NULL); - if (top != old_top || shown != old_shown) + if (NILP (bar->dragging)) XawScrollbarSetThumb (widget, top, shown); - } - else - { - ScrollbarWidget sb = (ScrollbarWidget) widget; - int scroll_mode = sb->scrollbar.scroll_mode; - - sb->scrollbar.scroll_mode = 0; - - if (last_scroll_bar_part == scroll_bar_down_arrow) - XawScrollbarSetThumb (widget, top, 1 - top); else { - float old_top; - XtVaGetValues (widget, XtNtopOfThumb, &old_top, NULL); - XawScrollbarSetThumb (widget, old_top, min (shown, 1 - old_top)); +#ifdef HAVE_XAW3D + ScrollbarWidget sb = (ScrollbarWidget) widget; + int scroll_mode; + + /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR. */ + if (xaw3d_arrow_scroll) + { + /* Xaw3d stupidly ignores resize requests while dragging + so we have to make it believe it's not in dragging mode. */ + scroll_mode = sb->scrollbar.scroll_mode; + if (scroll_mode == 2) + sb->scrollbar.scroll_mode = 0; + } +#endif + /* Try to make the scrolling a tad smoother. */ + if (!xaw3d_pick_top) + shown = min (shown, old_shown); + + XawScrollbarSetThumb (widget, top, shown); + +#ifdef HAVE_XAW3D + if (xaw3d_arrow_scroll && scroll_mode == 2) + sb->scrollbar.scroll_mode = scroll_mode; +#endif } - - sb->scrollbar.scroll_mode = scroll_mode; } } -#endif /* HAVE_XAW3D */ +#endif /* !USE_MOTIF */ UNBLOCK_INPUT; } @@ -12824,6 +12867,8 @@ XtToolkitInitialize (); Xt_app_con = XtCreateApplicationContext (); XtAppSetFallbackResources (Xt_app_con, Xt_default_resources); + xaw3d_arrow_scroll = False; + xaw3d_pick_top = True; #endif /* Note that there is no real way portable across R3/R4 to get the