7 /* undefine will disable the autoadjusting of the knob dimple to be
8 * directly below the cursor
10 #undef STRICT_NEXT_BEHAVIOUR
12 #define AUTOSCROLL_INITIAL_DELAY 200
14 #define AUTOSCROLL_DELAY 40
17 char *WMScrollerDidScrollNotification
= "WMScrollerDidScrollNotification";
21 typedef struct W_Scroller
{
31 WMHandlerID timerID
; /* for continuous scrolling mode */
33 #ifndef STRICT_NEXT_BEHAVIOUR
34 int dragPoint
; /* point where the knob is being
38 WMScrollArrowPosition arrowsPosition
:4;
40 unsigned int horizontal
:1;
42 WMScrollerPart hitPart
:4;
45 unsigned int documentFullyVisible
:1; /* document is fully visible */
47 unsigned int prevSelected
:1;
49 unsigned int pushed
:1;
51 unsigned int incrDown
:1; /* whether increment button is down */
53 unsigned int decrDown
:1;
55 unsigned int draggingKnob
:1;
57 unsigned int configured
:1;
59 unsigned int redrawPending
:1;
65 #define DEFAULT_HEIGHT 60
66 #define DEFAULT_WIDTH SCROLLER_WIDTH
67 #define DEFAULT_ARROWS_POSITION WSAMinEnd
71 static void destroyScroller(Scroller
*sPtr
);
72 static void paintScroller(Scroller
*sPtr
);
74 static void willResizeScroller();
75 static void handleEvents(XEvent
*event
, void *data
);
76 static void handleActionEvents(XEvent
*event
, void *data
);
78 static void handleMotion(Scroller
*sPtr
, int mouseX
, int mouseY
);
81 W_ViewDelegate _ScrollerViewDelegate
= {
93 WMCreateScroller(WMWidget
*parent
)
97 sPtr
= wmalloc(sizeof(Scroller
));
98 memset(sPtr
, 0, sizeof(Scroller
));
100 sPtr
->widgetClass
= WC_Scroller
;
102 sPtr
->view
= W_CreateView(W_VIEW(parent
));
107 sPtr
->view
->self
= sPtr
;
109 sPtr
->view
->delegate
= &_ScrollerViewDelegate
;
111 sPtr
->flags
.documentFullyVisible
= 1;
113 WMCreateEventHandler(sPtr
->view
, ExposureMask
|StructureNotifyMask
114 |ClientMessageMask
, handleEvents
, sPtr
);
116 W_ResizeView(sPtr
->view
, DEFAULT_WIDTH
, DEFAULT_WIDTH
);
117 sPtr
->flags
.arrowsPosition
= DEFAULT_ARROWS_POSITION
;
119 WMCreateEventHandler(sPtr
->view
, ButtonPressMask
|ButtonReleaseMask
120 |EnterWindowMask
|LeaveWindowMask
|ButtonMotionMask
,
121 handleActionEvents
, sPtr
);
123 sPtr
->flags
.hitPart
= WSNoPart
;
131 WMSetScrollerArrowsPosition(WMScroller
*sPtr
, WMScrollArrowPosition position
)
133 sPtr
->flags
.arrowsPosition
= position
;
134 if (sPtr
->view
->flags
.realized
) {
141 willResizeScroller(W_ViewDelegate
*self
, WMView
*view
,
142 unsigned int *width
, unsigned int *height
)
144 WMScroller
*sPtr
= (WMScroller
*)view
->self
;
146 if (*width
> *height
) {
147 sPtr
->flags
.horizontal
= 1;
148 *height
= SCROLLER_WIDTH
;
150 sPtr
->flags
.horizontal
= 0;
151 *width
= SCROLLER_WIDTH
;
157 WMSetScrollerAction(WMScroller
*sPtr
, WMAction
*action
, void *clientData
)
159 CHECK_CLASS(sPtr
, WC_Scroller
);
161 sPtr
->action
= action
;
163 sPtr
->clientData
= clientData
;
168 WMSetScrollerParameters(WMScroller
*sPtr
, float floatValue
,
169 float knobProportion
)
171 CHECK_CLASS(sPtr
, WC_Scroller
);
173 if (floatValue
< 0.0)
174 sPtr
->floatValue
= 0.0;
175 else if (floatValue
> 1.0)
176 sPtr
->floatValue
= 1.0;
178 sPtr
->floatValue
= floatValue
;
180 if (knobProportion
<= 0.0) {
182 sPtr
->knobProportion
= 0.0;
183 sPtr
->flags
.documentFullyVisible
= 0;
185 } else if (knobProportion
>= 1.0) {
187 sPtr
->knobProportion
= 1.0;
188 sPtr
->flags
.documentFullyVisible
= 1;
191 sPtr
->knobProportion
= knobProportion
;
192 sPtr
->flags
.documentFullyVisible
= 0;
195 if (sPtr
->view
->flags
.realized
)
201 WMGetScrollerKnobProportion(WMScroller
*sPtr
)
203 CHECK_CLASS(sPtr
, WC_Scroller
);
205 return sPtr
->knobProportion
;
210 WMGetScrollerValue(WMScroller
*sPtr
)
212 CHECK_CLASS(sPtr
, WC_Scroller
);
214 return sPtr
->floatValue
;
219 WMGetScrollerHitPart(WMScroller
*sPtr
)
221 CHECK_CLASS(sPtr
, WC_Scroller
);
223 return sPtr
->flags
.hitPart
;
228 paintArrow(WMScroller
*sPtr
, Drawable d
, int part
)
230 * part- 0 paints the decrement arrow, 1 the increment arrow
233 WMView
*view
= sPtr
->view
;
234 WMScreen
*scr
= view
->screen
;
238 #ifndef DOUBLE_BUFFER
239 GC gc
= scr
->lightGC
;
242 bsize
= SCROLLER_WIDTH
- 4;
245 if (part
== 0) { /* decrement button */
246 if (sPtr
->flags
.horizontal
) {
247 if (sPtr
->flags
.arrowsPosition
== WSAMaxEnd
) {
248 ofs
= view
->size
.width
- 2*(bsize
+1) - 1;
252 if (sPtr
->flags
.decrDown
)
253 arrow
= scr
->hiLeftArrow
;
255 arrow
= scr
->leftArrow
;
258 if (sPtr
->flags
.arrowsPosition
== WSAMaxEnd
) {
259 ofs
= view
->size
.height
- 2*(bsize
+1) - 1;
263 if (sPtr
->flags
.decrDown
)
264 arrow
= scr
->hiUpArrow
;
266 arrow
= scr
->upArrow
;
269 #ifndef DOUBLE_BUFFER
270 if (sPtr
->flags
.decrDown
)
271 gc
= WMColorGC(scr
->white
);
273 } else { /* increment button */
274 if (sPtr
->flags
.horizontal
) {
275 if (sPtr
->flags
.arrowsPosition
== WSAMaxEnd
) {
276 ofs
= view
->size
.width
- bsize
+1 - 3;
280 if (sPtr
->flags
.incrDown
)
281 arrow
= scr
->hiRightArrow
;
283 arrow
= scr
->rightArrow
;
285 if (sPtr
->flags
.arrowsPosition
== WSAMaxEnd
) {
286 ofs
= view
->size
.height
- bsize
+1 - 3;
290 if (sPtr
->flags
.incrDown
)
291 arrow
= scr
->hiDownArrow
;
293 arrow
= scr
->downArrow
;
296 #ifndef DOUBLE_BUFFER
297 if (sPtr
->flags
.incrDown
)
303 if (sPtr
->flags
.horizontal
) {
306 #ifndef DOUBLE_BUFFER
307 XFillRectangle(scr
->display
, d
, gc
,
308 ofs
+1, 2+1, bsize
+1-3, bsize
-3);
310 if ((!part
&&sPtr
->flags
.decrDown
) || (part
&&sPtr
->flags
.incrDown
))
311 XFillRectangle(scr
->display
, d
, WMColorGC(scr
->white
),
312 ofs
+1, 2+1, bsize
+1-3, bsize
-3);
313 #endif /* DOUBLE_BUFFER */
314 W_DrawRelief(scr
, d
, ofs
, 2, bsize
, bsize
, WRRaised
);
317 XSetClipMask(scr
->display
, scr
->clipGC
, arrow
->mask
);
318 XSetClipOrigin(scr
->display
, scr
->clipGC
,
319 ofs
+ (bsize
- arrow
->width
) / 2,
320 2 + (bsize
- arrow
->height
) / 2);
322 XCopyArea(scr
->display
, arrow
->pixmap
, d
, scr
->clipGC
,
323 0, 0, arrow
->width
, arrow
->height
,
324 ofs
+ (bsize
- arrow
->width
) / 2,
325 2 + (bsize
- arrow
->height
) / 2);
327 } else { /* vertical */
330 #ifndef DOUBLE_BUFFER
331 XFillRectangle(scr
->display
, d
, gc
,
332 2+1, ofs
+1, bsize
-3, bsize
+1-3);
334 if ((!part
&&sPtr
->flags
.decrDown
) || (part
&&sPtr
->flags
.incrDown
))
335 XFillRectangle(scr
->display
, d
, WMColorGC(scr
->white
),
336 2+1, ofs
+1, bsize
-3, bsize
+1-3);
337 #endif /* DOUBLE_BUFFER */
338 W_DrawRelief(scr
, d
, 2, ofs
, bsize
, bsize
, WRRaised
);
342 XSetClipMask(scr
->display
, scr
->clipGC
, arrow
->mask
);
343 XSetClipOrigin(scr
->display
, scr
->clipGC
,
344 2 + (bsize
- arrow
->width
) / 2,
345 ofs
+ (bsize
- arrow
->height
) / 2);
346 XCopyArea(scr
->display
, arrow
->pixmap
, d
, scr
->clipGC
,
347 0, 0, arrow
->width
, arrow
->height
,
348 2 + (bsize
- arrow
->width
) / 2,
349 ofs
+ (bsize
- arrow
->height
) / 2);
355 knobLength(Scroller
*sPtr
)
360 if (sPtr
->flags
.horizontal
)
361 length
= sPtr
->view
->size
.width
- 4;
363 length
= sPtr
->view
->size
.height
- 4;
365 if (sPtr
->flags
.arrowsPosition
== WSAMaxEnd
) {
366 length
-= (SCROLLER_WIDTH
- 4 + 1)*2;
367 } else if (sPtr
->flags
.arrowsPosition
== WSAMinEnd
) {
368 length
-= (SCROLLER_WIDTH
- 4 + 1)*2;
371 tmp
= (int)((float)length
* sPtr
->knobProportion
+ 0.5);
372 /* keep minimum size */
373 if (tmp
< SCROLLER_WIDTH
-4)
374 tmp
= SCROLLER_WIDTH
-4;
381 paintScroller(Scroller
*sPtr
)
383 WMView
*view
= sPtr
->view
;
384 WMScreen
*scr
= view
->screen
;
388 Drawable d
= view
->window
;
395 d
= XCreatePixmap(scr
->display
, view
->window
, view
->size
.width
,
396 view
->size
.height
, scr
->depth
);
397 XFillRectangle(scr
->display
, d
, WMColorGC(scr
->gray
), 0, 0,
398 view
->size
.width
, view
->size
.height
);
401 XDrawRectangle(scr
->display
, d
, WMColorGC(scr
->black
), 0, 0,
402 view
->size
.width
-1, view
->size
.height
-1);
403 #ifndef DOUBLE_BUFFER
404 XDrawRectangle(scr
->display
, d
, WMColorGC(scr
->gray
), 1, 1,
405 view
->size
.width
-3, view
->size
.height
-3);
408 if (sPtr
->flags
.horizontal
)
409 length
= view
->size
.width
- 4;
411 length
= view
->size
.height
- 4;
413 if (sPtr
->flags
.documentFullyVisible
) {
414 XFillRectangle(scr
->display
, d
, scr
->stippleGC
, 2, 2,
415 view
->size
.width
-4, view
->size
.height
-4);
417 if (sPtr
->flags
.arrowsPosition
==WSAMaxEnd
) {
419 length
-= (SCROLLER_WIDTH
- 4 + 1)*2;
420 } else if (sPtr
->flags
.arrowsPosition
==WSAMinEnd
) {
421 ofs
= (SCROLLER_WIDTH
- 4 + 1)*2;
422 length
-= (SCROLLER_WIDTH
- 4 + 1)*2;
427 knobL
= (float)knobLength(sPtr
);
429 knobP
= sPtr
->floatValue
* ((float)length
- knobL
);
432 if (sPtr
->flags
.horizontal
) {
434 XFillRectangle(scr
->display
, d
, scr
->stippleGC
,
435 ofs
+2, 2, (int)knobP
, view
->size
.height
-4);
438 #ifndef DOUBLE_BUFFER
439 XFillRectangle(scr
->display
, d
, scr
->lightGC
,
440 ofs
+2+(int)knobP
+2, 2+2, (int)knobL
-4,
441 view
->size
.height
-4-4);
443 W_DrawRelief(scr
, d
, ofs
+2+(int)knobP
, 2, (int)knobL
,
444 view
->size
.height
-4, WRRaised
);
446 XCopyArea(scr
->display
, scr
->scrollerDimple
->pixmap
, d
,
448 scr
->scrollerDimple
->width
, scr
->scrollerDimple
->height
,
449 ofs
+2+(int)knobP
+((int)knobL
-scr
->scrollerDimple
->width
-1)/2,
450 (view
->size
.height
-scr
->scrollerDimple
->height
-1)/2);
453 if ((int)(knobP
+knobL
) < length
)
454 XFillRectangle(scr
->display
, d
, scr
->stippleGC
,
455 ofs
+2+(int)(knobP
+knobL
), 2,
456 length
-(int)(knobP
+knobL
),
457 view
->size
.height
-4);
461 XFillRectangle(scr
->display
, d
, scr
->stippleGC
,
462 2, ofs
+2, view
->size
.width
-4, (int)knobP
);
465 #ifndef DOUBLE_BUFFER
466 XFillRectangle(scr
->display
, d
, scr
->lightGC
,
467 2+2, ofs
+2+(int)knobP
+2,
468 view
->size
.width
-4-4, (int)knobL
-4);
470 XCopyArea(scr
->display
, scr
->scrollerDimple
->pixmap
, d
,
472 scr
->scrollerDimple
->width
, scr
->scrollerDimple
->height
,
473 (view
->size
.width
-scr
->scrollerDimple
->width
-1)/2,
474 ofs
+2+(int)knobP
+((int)knobL
-scr
->scrollerDimple
->height
-1)/2);
476 W_DrawRelief(scr
, d
, 2, ofs
+2+(int)knobP
,
477 view
->size
.width
-4, (int)knobL
, WRRaised
);
480 if ((int)(knobP
+knobL
) < length
)
481 XFillRectangle(scr
->display
, d
, scr
->stippleGC
,
482 2, ofs
+2+(int)(knobP
+knobL
),
484 length
-(int)(knobP
+knobL
));
487 if (sPtr
->flags
.arrowsPosition
!= WSANone
) {
488 paintArrow(sPtr
, d
, 0);
489 paintArrow(sPtr
, d
, 1);
494 XCopyArea(scr
->display
, d
, view
->window
, scr
->copyGC
, 0, 0,
495 view
->size
.width
, view
->size
.height
, 0, 0);
496 XFreePixmap(scr
->display
, d
);
503 handleEvents(XEvent
*event
, void *data
)
505 Scroller
*sPtr
= (Scroller
*)data
;
507 CHECK_CLASS(data
, WC_Scroller
);
510 switch (event
->type
) {
512 if (event
->xexpose
.count
==0)
517 destroyScroller(sPtr
);
525 * locatePointInScroller-
526 * Return the part of the scroller where the point is located.
528 static WMScrollerPart
529 locatePointInScroller(Scroller
*sPtr
, int x
, int y
, int alternate
)
531 int width
= sPtr
->view
->size
.width
;
532 int height
= sPtr
->view
->size
.height
;
533 int c
, p1
, p2
, p3
, p4
, p5
, p6
;
537 /* if there is no knob... */
538 if (sPtr
->flags
.documentFullyVisible
)
541 if (sPtr
->flags
.horizontal
)
547 * | | |###########| |#####| | |
548 * | < | > |###########| O |#####| < | > |
549 * | | |###########| |#####| | |
552 if (sPtr
->flags
.arrowsPosition
== WSAMinEnd
) {
556 if (sPtr
->flags
.horizontal
) {
564 } else if (sPtr
->flags
.arrowsPosition
== WSAMaxEnd
) {
565 if (sPtr
->flags
.horizontal
) {
579 if (sPtr
->flags
.horizontal
) {
580 slotL
= p5
= p6
= width
;
582 slotL
= p5
= p6
= height
;
586 knobL
= knobLength(sPtr
);
587 p3
= p2
+ (int)((float)(slotL
-knobL
) * sPtr
->floatValue
);
590 /* uses a mix of the NS and Win ways of doing scroll page */
592 return alternate
? WSDecrementPage
: WSDecrementLine
;
594 return alternate
? WSIncrementPage
: WSIncrementLine
;
596 return WSDecrementPage
;
600 return WSIncrementPage
;
602 return alternate
? WSDecrementPage
: WSDecrementLine
;
604 return alternate
? WSIncrementPage
: WSIncrementLine
;
610 handlePush(Scroller
*sPtr
, int pushX
, int pushY
, int alternate
)
615 part
= locatePointInScroller(sPtr
, pushX
, pushY
, alternate
);
617 sPtr
->flags
.hitPart
= part
;
620 case WSIncrementLine
:
621 sPtr
->flags
.incrDown
= 1;
625 case WSIncrementPage
:
629 case WSDecrementLine
:
630 sPtr
->flags
.decrDown
= 1;
634 case WSDecrementPage
:
639 sPtr
->flags
.draggingKnob
= 1;
640 #ifndef STRICT_NEXT_BEHAVIOUR
641 if (sPtr
->flags
.horizontal
)
642 sPtr
->dragPoint
= pushX
;
644 sPtr
->dragPoint
= pushY
;
647 int noButtons
= (sPtr
->flags
.arrowsPosition
== WSANone
);
650 if (sPtr
->flags
.horizontal
)
651 length
= sPtr
->view
->size
.width
- 4;
653 length
= sPtr
->view
->size
.height
- 4;
658 knobP
= (int)(sPtr
->floatValue
* (float)(length
-knobLength(sPtr
)));
660 if (sPtr
->flags
.arrowsPosition
== WSAMinEnd
)
661 sPtr
->dragPoint
-= 2 + (noButtons
? 0 : 36) + knobP
;
663 sPtr
->dragPoint
-= 2 + knobP
;
665 #endif /* STRICT_NEXT_BEHAVIOUR */
666 /* This does not seem necesary here since we don't know yet if the
667 * knob will be dragged later. -Dan
668 handleMotion(sPtr, pushX, pushY); */
677 if (doAction
&& sPtr
->action
) {
678 (*sPtr
->action
)(sPtr
, sPtr
->clientData
);
680 WMPostNotificationName(WMScrollerDidScrollNotification
, sPtr
, NULL
);
686 floatValueForPoint(int slotOfs
, int slotLength
, int knobLength
, int point
)
688 float floatValue
= 0;
691 #ifdef STRICT_NEXT_BEHAVIOUR
692 if (point
< slotOfs
+ knobLength
/2)
693 position
= (float)(slotOfs
+ knobLength
/2);
694 else if (point
> slotOfs
+ slotLength
- knobLength
/2)
695 position
= (float)(slotOfs
+ slotLength
- knobLength
/2);
697 position
= (float)point
;
699 floatValue
= (position
-(float)(slotOfs
+slotLength
/2))
700 /(float)(slotLength
-knobLength
);
702 /* Adjust the last point to lie inside the knob slot */
704 position
= (float)slotOfs
;
705 else if (point
> slotOfs
+ slotLength
)
706 position
= (float)(slotOfs
+ slotLength
);
708 position
= (float)point
;
710 /* Compute the float value */
711 floatValue
= (position
-(float)slotOfs
) / (float)(slotLength
-knobLength
);
719 handleMotion(Scroller
*sPtr
, int mouseX
, int mouseY
)
723 int noButtons
= (sPtr
->flags
.arrowsPosition
== WSANone
);
725 if (sPtr
->flags
.arrowsPosition
== WSAMinEnd
)
726 slotOffset
= 2 + (noButtons
? 0 : 36);
730 if (sPtr
->flags
.draggingKnob
) {
732 #ifdef STRICT_NEXT_BEHAVIOUR
733 if (sPtr
->flags
.horizontal
) {
734 slotLength
= sPtr
->view
->size
.width
-4-(noButtons
? 0 : 36);
735 newFloatValue
= floatValueForPoint(slotOffset
, slotLength
,
736 (int)(slotLength
*sPtr
->knobProportion
),
739 slotLength
= sPtr
->view
->size
.height
-4-(noButtons
? 0 : 36);
740 newFloatValue
= floatValueForPoint(slotOffset
, slotLength
,
741 (int)(slotLength
*sPtr
->knobProportion
),
745 if (sPtr
->flags
.horizontal
) {
746 slotLength
= sPtr
->view
->size
.width
-4-(noButtons
? 0 : 36);
747 newFloatValue
= floatValueForPoint(slotOffset
, slotLength
,
748 (int)(slotLength
*sPtr
->knobProportion
),
749 mouseX
-sPtr
->dragPoint
);
751 slotLength
= sPtr
->view
->size
.height
-4-(noButtons
? 0 : 36);
752 newFloatValue
= floatValueForPoint(slotOffset
, slotLength
,
753 (int)(slotLength
*sPtr
->knobProportion
),
754 mouseY
-sPtr
->dragPoint
);
756 #endif /* !STRICT_NEXT_BEHAVIOUR */
757 WMSetScrollerParameters(sPtr
, newFloatValue
, sPtr
->knobProportion
);
759 (*sPtr
->action
)(sPtr
, sPtr
->clientData
);
760 WMPostNotificationName(WMScrollerDidScrollNotification
, sPtr
,
766 part
= locatePointInScroller(sPtr
, mouseX
, mouseY
, False
);
768 sPtr
->flags
.hitPart
= part
;
770 if (part
== WSIncrementLine
&& sPtr
->flags
.decrDown
) {
771 sPtr
->flags
.decrDown
= 0;
772 sPtr
->flags
.incrDown
= 1;
773 } else if (part
== WSDecrementLine
&& sPtr
->flags
.incrDown
) {
774 sPtr
->flags
.incrDown
= 0;
775 sPtr
->flags
.decrDown
= 1;
776 } else if (part
!= WSIncrementLine
&& part
!= WSDecrementLine
) {
777 sPtr
->flags
.incrDown
= 0;
778 sPtr
->flags
.decrDown
= 0;
785 autoScroll(void *clientData
)
787 Scroller
*sPtr
= (Scroller
*)clientData
;
790 (*sPtr
->action
)(sPtr
, sPtr
->clientData
);
791 WMPostNotificationName(WMScrollerDidScrollNotification
, sPtr
, NULL
);
793 sPtr
->timerID
= WMAddTimerHandler(AUTOSCROLL_DELAY
, autoScroll
, clientData
);
798 handleActionEvents(XEvent
*event
, void *data
)
800 Scroller
*sPtr
= (Scroller
*)data
;
804 /* check if we're really dealing with a scroller, as something
805 * might have gone wrong in the event dispatching stuff */
806 CHECK_CLASS(sPtr
, WC_Scroller
);
808 id
= sPtr
->flags
.incrDown
;
809 dd
= sPtr
->flags
.decrDown
;
811 switch (event
->type
) {
818 WMDeleteTimerHandler(sPtr
->timerID
);
819 sPtr
->timerID
= NULL
;
821 sPtr
->flags
.incrDown
= 0;
822 sPtr
->flags
.decrDown
= 0;
826 /* FIXME: change Mod1Mask with something else */
827 if (sPtr
->flags
.documentFullyVisible
)
829 if (event
->xbutton
.button
==WINGsConfiguration
.mouseWheelUp
) {
830 if (event
->xbutton
.state
& ControlMask
) {
831 sPtr
->flags
.hitPart
= WSDecrementPage
;
832 } else if (event
->xbutton
.state
& ShiftMask
) {
833 sPtr
->flags
.hitPart
= WSDecrementLine
;
835 sPtr
->flags
.hitPart
= WSDecrementWheel
;
838 (*sPtr
->action
)(sPtr
, sPtr
->clientData
);
839 WMPostNotificationName(WMScrollerDidScrollNotification
, sPtr
,
842 } else if (event
->xbutton
.button
==WINGsConfiguration
.mouseWheelDown
) {
843 if (event
->xbutton
.state
& ControlMask
) {
844 sPtr
->flags
.hitPart
= WSIncrementPage
;
845 } else if (event
->xbutton
.state
& ShiftMask
) {
846 sPtr
->flags
.hitPart
= WSIncrementLine
;
848 sPtr
->flags
.hitPart
= WSIncrementWheel
;
851 (*sPtr
->action
)(sPtr
, sPtr
->clientData
);
852 WMPostNotificationName(WMScrollerDidScrollNotification
, sPtr
,
856 handlePush(sPtr
, event
->xbutton
.x
, event
->xbutton
.y
,
857 (event
->xbutton
.state
& Mod1Mask
)
858 ||event
->xbutton
.button
==Button2
);
859 /* continue scrolling if pushed on the buttons */
860 if (sPtr
->flags
.hitPart
== WSIncrementLine
861 || sPtr
->flags
.hitPart
== WSDecrementLine
) {
862 sPtr
->timerID
= WMAddTimerHandler(AUTOSCROLL_INITIAL_DELAY
,
869 if (sPtr
->flags
.draggingKnob
) {
871 (*sPtr
->action
)(sPtr
, sPtr
->clientData
);
872 WMPostNotificationName(WMScrollerDidScrollNotification
, sPtr
,
877 WMDeleteTimerHandler(sPtr
->timerID
);
878 sPtr
->timerID
= NULL
;
880 sPtr
->flags
.incrDown
= 0;
881 sPtr
->flags
.decrDown
= 0;
882 sPtr
->flags
.draggingKnob
= 0;
886 handleMotion(sPtr
, event
->xbutton
.x
, event
->xbutton
.y
);
887 if (sPtr
->timerID
&& sPtr
->flags
.hitPart
!= WSIncrementLine
888 && sPtr
->flags
.hitPart
!= WSDecrementLine
) {
889 WMDeleteTimerHandler(sPtr
->timerID
);
890 sPtr
->timerID
= NULL
;
894 if (id
!= sPtr
->flags
.incrDown
|| dd
!= sPtr
->flags
.decrDown
)
901 destroyScroller(Scroller
*sPtr
)
903 /* we don't want autoscroll try to scroll a freed widget */
905 WMDeleteTimerHandler(sPtr
->timerID
);