emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Scrollbar thumbs


From: YAMAMOTO Mitsuharu
Subject: Re: Scrollbar thumbs
Date: Tue, 10 Nov 2009 08:14:57 +0900
User-agent: Wanderlust/2.14.0 (Africa) SEMI/1.14.6 (Maruoka) FLIM/1.14.8 (Shijō) APEL/10.6 Emacs/22.3 (sparc-sun-solaris2.8) MULE/5.0 (SAKAKI)

>>>>> On Thu, 05 Nov 2009 10:18:07 +0900, YAMAMOTO Mitsuharu <address@hidden> 
>>>>> said:

> What the Carbon port (and its descendants) does is to process the
> whole mouse events at the Emacs side.  It includes timer processing
> for repeated scrolling (e.g, pressing an arrow button for a while.)
> The toolkit is used only for displaying the scrollbar with
> highlighting, detecting which part of the bar is pressed, and
> getting the rectangle for a specified part of the bar.

> The result is like a sort of mixture of native and toolkit
> scrollbars on X11: it generates Lisp events and looks like the
> toolkit one, but the size of the thumb usually changes during
> dragging and also overscrolling at the bottom works as in the native
> one.

We can port this thumb handling to scroll bars on Xaw3d compiled with
ARROW_SCROLLBARS, because we can guess the rectangle of the thumb from
available widget resource values.

                                     YAMAMOTO Mitsuharu
                                address@hidden

Index: src/xterm.c
===================================================================
RCS file: /sources/emacs/emacs/src/xterm.c,v
retrieving revision 1.1051
diff -c -p -r1.1051 xterm.c
*** src/xterm.c 6 Nov 2009 08:30:45 -0000       1.1051
--- src/xterm.c 9 Nov 2009 20:33:21 -0000
*************** static void x_create_toolkit_scroll_bar 
*** 4101,4107 ****
                                             struct scroll_bar *));
  static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *,
                                                int, int, int));
! 
  
  /* Lisp window being scrolled.  Set when starting to interact with
     a toolkit scroll bar, reset to nil when ending the interaction.  */
--- 4101,4108 ----
                                             struct scroll_bar *));
  static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *,
                                                int, int, int));
! static int x_scroll_bar_handle_thumb_event P_ ((struct scroll_bar *, XEvent *,
!                                               struct input_event *));
  
  /* Lisp window being scrolled.  Set when starting to interact with
     a toolkit scroll bar, reset to nil when ending the interaction.  */
*************** x_set_toolkit_scroll_bar_thumb (bar, por
*** 4812,4817 ****
--- 4813,4851 ----
      }
  #else /* !USE_MOTIF i.e. use Xaw */
  
+   if (xaw3d_arrow_scroll)
+     {
+       float old_top, old_shown;
+       Dimension length, thickness, min_thumb, shadow_width;
+       Dimension margin, min_shown_length;
+ 
+       XtVaGetValues (widget, XtNtopOfThumb, &old_top, XtNshown, &old_shown,
+                    XtNlength, &length, XtNthickness, &thickness,
+                    XtNminimumThumb, &min_thumb,
+                    XtNshadowWidth, &shadow_width,
+                    NULL);
+       margin = thickness;
+       min_shown_length = min_thumb + 2 * shadow_width;
+       if (whole == 0 || length < 2 * margin + min_shown_length)
+       top = 0, shown = 1;
+       else
+       {
+         Dimension tzl;
+         float maximum, scale;
+ 
+         tzl = length - margin - margin;
+ 
+         maximum = tzl - min_shown_length;
+         scale = maximum / whole;
+         top = (position * scale) / tzl;
+         shown = (portion * scale + min_shown_length) / tzl;
+       }
+       if (top != old_top || shown != old_shown)
+       XawScrollbarSetThumb (widget, top, shown);
+     }
+   else
+     {
+ 
    if (whole == 0)
      top = 0, shown = 1;
    else
*************** x_set_toolkit_scroll_bar_thumb (bar, por
*** 4854,4865 ****
--- 4888,5025 ----
          }
        }
    }
+ 
+     }
  #endif /* !USE_MOTIF */
  
    UNBLOCK_INPUT;
  }
  #endif /* not USE_GTK */
  
+ /* Handle an X11 event EVENT if it is for the thumb of the scroll bar
+    BAR, and store an input event to *BUFP if necessary.  Return
+    non-zero if the X11 event is handled (i.e., no further handling at
+    the toolkit side needed).  */
+ 
+ static int
+ x_scroll_bar_handle_thumb_event (bar, event, bufp)
+      struct scroll_bar *bar;
+      XEvent *event;
+      struct input_event *bufp;
+ {
+ #if !defined (USE_GTK) && !defined (USE_MOTIF)
+   if (xaw3d_arrow_scroll)
+     switch (event->type)
+       {
+       case ButtonPress:
+       {
+         Widget widget = XtWindowToWidget (event->xbutton.display,
+                                           event->xbutton.window);
+         float top, shown;
+         Dimension length, thickness;
+         XtOrientation orientation;
+         Dimension margin, tzl;
+         Position top_loc, bottom_loc;
+         int pos;
+ 
+         XtVaGetValues (widget, XtNtopOfThumb, &top, XtNshown, &shown,
+                        XtNlength, &length, XtNthickness, &thickness,
+                        XtNorientation, &orientation,
+                        NULL);
+         margin = thickness;
+         if (length > 2 * margin)
+           tzl = length - margin - margin;
+         else
+           tzl = 0;
+         top_loc = margin + (int) (tzl * top);
+         bottom_loc = top_loc + (int) (tzl * shown);
+ 
+         pos = (orientation == XtorientHorizontal
+                ? event->xbutton.x : event->xbutton.y);
+         if (pos >= top_loc && pos <= bottom_loc)
+           {
+             bar->dragging = make_number (- (pos - top_loc) - 1);
+             bar->tracking_thumb_p = 1;
+ 
+             return 1;
+           }
+       }
+       break;
+ 
+       case ButtonRelease:
+       if (bar->tracking_thumb_p)
+         {
+           if (INTEGERP (bar->dragging) && XINT (bar->dragging) >= 0)
+             {
+               bufp->kind = SCROLL_BAR_CLICK_EVENT;
+               bufp->frame_or_window = bar->window;
+               bufp->arg = Qnil;
+               bufp->timestamp = event->xbutton.time;
+               bufp->part = scroll_bar_end_scroll;
+               bufp->code = 0;
+               XSETINT (bufp->x, 0);
+               XSETINT (bufp->y, 0);
+               bufp->modifiers = 0;
+             }
+           bar->dragging = Qnil;
+           bar->tracking_thumb_p = 0;
+ 
+           return 1;
+         }
+       break;
+ 
+       case MotionNotify:
+       if (bar->tracking_thumb_p)
+         {
+           Widget widget = XtWindowToWidget (event->xmotion.display,
+                                             event->xmotion.window);
+           Dimension length, thickness, min_thumb, shadow_width;
+           XtOrientation orientation;
+           Dimension margin, min_shown_length, tzl;
+           int pos;
+           int portion, whole;
+ 
+           if (INTEGERP (bar->dragging) && XINT (bar->dragging) < 0)
+             bar->dragging = make_number (- (XINT (bar->dragging) + 1));
+ 
+           XtVaGetValues (widget, XtNlength, &length, XtNthickness, &thickness,
+                          XtNminimumThumb, &min_thumb,
+                          XtNshadowWidth, &shadow_width,
+                          XtNorientation, &orientation,
+                          NULL);
+           margin = thickness;
+           min_shown_length = min_thumb + 2 * shadow_width;
+           tzl = length - margin - margin;
+ 
+           pos = (orientation == XtorientHorizontal
+                  ? event->xmotion.x : event->xmotion.y);
+           portion = pos - XINT (bar->dragging) - margin;
+           whole = tzl > min_shown_length ? tzl - min_shown_length : tzl;
+           if (portion < 0)
+             portion = 0;
+           if (portion > whole)
+             portion = whole;
+ 
+           bufp->kind = SCROLL_BAR_CLICK_EVENT;
+           bufp->frame_or_window = bar->window;
+           bufp->arg = Qnil;
+           bufp->timestamp = event->xmotion.time;
+           bufp->part = scroll_bar_handle;
+           bufp->code = 0;
+           XSETINT (bufp->x, portion);
+           XSETINT (bufp->y, whole);
+           bufp->modifiers = 0;
+         }
+ 
+       return 1;
+       break;
+ 
+       default:
+       abort ();
+       }
+ #endif        /* !USE_GTK && !USE_MOTIF */
+   return 0;
+ }
  #endif /* USE_TOOLKIT_SCROLL_BARS */
  
  
*************** x_scroll_bar_create (w, top, left, width
*** 4937,4942 ****
--- 5097,5103 ----
    bar->end = 0;
    bar->dragging = Qnil;
    bar->fringe_extended_p = 0;
+   bar->tracking_thumb_p = 0;
  
    /* Add bar to its frame's list of scroll bars.  */
    bar->next = FRAME_SCROLL_BARS (f);
*************** handle_one_xevent (dpyinfo, eventp, fini
*** 6729,6742 ****
            }
          else
            {
- #ifndef USE_TOOLKIT_SCROLL_BARS
              struct scroll_bar *bar
                = x_window_to_scroll_bar (event.xmotion.display,
                                          event.xmotion.window);
  
              if (bar)
                x_scroll_bar_note_movement (bar, &event);
! #endif /* USE_TOOLKIT_SCROLL_BARS */
  
              /* If we move outside the frame, then we're
                 certainly no longer on any text in the frame.  */
--- 6890,6906 ----
            }
          else
            {
              struct scroll_bar *bar
                = x_window_to_scroll_bar (event.xmotion.display,
                                          event.xmotion.window);
  
+ #ifdef USE_TOOLKIT_SCROLL_BARS
+             if (bar && x_scroll_bar_handle_thumb_event (bar, &event, 
&inev.ie))
+             *finish = X_EVENT_DROP;
+ #else  /* !USE_TOOLKIT_SCROLL_BARS */
              if (bar)
                x_scroll_bar_note_movement (bar, &event);
! #endif        /* !USE_TOOLKIT_SCROLL_BARS */
  
              /* If we move outside the frame, then we're
                 certainly no longer on any text in the frame.  */
*************** handle_one_xevent (dpyinfo, eventp, fini
*** 6891,6896 ****
--- 7055,7063 ----
                  x_scroll_bar_handle_click (bar, &event, &inev.ie);
                  *finish = X_EVENT_DROP;
                }
+           else if (bar
+                    && x_scroll_bar_handle_thumb_event (bar, &event, &inev.ie))
+             *finish = X_EVENT_DROP;
  #else /* not USE_TOOLKIT_SCROLL_BARS */
              if (bar)
                x_scroll_bar_handle_click (bar, &event, &inev.ie);
Index: src/xterm.h
===================================================================
RCS file: /sources/emacs/emacs/src/xterm.h,v
retrieving revision 1.217
diff -c -p -r1.217 xterm.h
*** src/xterm.h 21 Oct 2009 18:29:48 -0000      1.217
--- src/xterm.h 9 Nov 2009 20:33:21 -0000
*************** struct scroll_bar
*** 776,781 ****
--- 776,785 ----
    /* 1 if the background of the fringe that is adjacent to a scroll
       bar is extended to the gap between the fringe and the bar.  */
    unsigned int fringe_extended_p : 1;
+ 
+   /* 1 if the toolkit scroll bar thumb is currently being tracked at
+      the Emacs side. */
+   unsigned int tracking_thumb_p : 1;
  };
  
  /* The number of elements a vector holding a struct scroll_bar needs.  */




reply via email to

[Prev in Thread] Current Thread [Next in Thread]