9 /* undefine will disable the autoadjusting of the knob dimple to be
10 * directly below the cursor
12 #undef STRICT_NEXT_BEHAVIOUR
14 #define AUTOSCROLL_INITIAL_DELAY 200
16 #define AUTOSCROLL_DELAY 40
19 char *WMScrollerDidScrollNotification
= "WMScrollerDidScrollNotification";
23 typedef struct W_Scroller
{
33 WMHandlerID timerID
; /* for continuous scrolling mode */
35 #ifndef STRICT_NEXT_BEHAVIOUR
36 int dragPoint
; /* point where the knob is being
40 WMScrollArrowPosition arrowsPosition
:4;
42 unsigned int horizontal
:1;
44 WMScrollerPart hitPart
:4;
47 unsigned int documentFullyVisible
:1; /* document is fully visible */
49 unsigned int prevSelected
:1;
51 unsigned int pushed
:1;
53 unsigned int incrDown
:1; /* whether increment button is down */
55 unsigned int decrDown
:1;
57 unsigned int draggingKnob
:1;
59 unsigned int configured
:1;
61 unsigned int redrawPending
:1;
67 #define DEFAULT_HEIGHT 60
68 #define DEFAULT_WIDTH SCROLLER_WIDTH
69 #define DEFAULT_ARROWS_POSITION WSAMinEnd
73 static void destroyScroller(Scroller
*sPtr
);
74 static void paintScroller(Scroller
*sPtr
);
76 static void willResizeScroller();
77 static void handleEvents(XEvent
*event
, void *data
);
78 static void handleActionEvents(XEvent
*event
, void *data
);
80 static void handleMotion(Scroller
*sPtr
, int mouseX
, int mouseY
);
83 W_ViewDelegate _ScrollerViewDelegate
= {
95 WMCreateScroller(WMWidget
*parent
)
99 sPtr
= wmalloc(sizeof(Scroller
));
100 memset(sPtr
, 0, sizeof(Scroller
));
102 sPtr
->widgetClass
= WC_Scroller
;
104 sPtr
->view
= W_CreateView(W_VIEW(parent
));
109 sPtr
->view
->self
= sPtr
;
111 sPtr
->view
->delegate
= &_ScrollerViewDelegate
;
113 sPtr
->flags
.documentFullyVisible
= 1;
115 WMCreateEventHandler(sPtr
->view
, ExposureMask
|StructureNotifyMask
116 |ClientMessageMask
, handleEvents
, sPtr
);
118 W_ResizeView(sPtr
->view
, DEFAULT_WIDTH
, DEFAULT_WIDTH
);
119 sPtr
->flags
.arrowsPosition
= DEFAULT_ARROWS_POSITION
;
121 WMCreateEventHandler(sPtr
->view
, ButtonPressMask
|ButtonReleaseMask
122 |EnterWindowMask
|LeaveWindowMask
|ButtonMotionMask
,
123 handleActionEvents
, sPtr
);
125 sPtr
->flags
.hitPart
= WSNoPart
;
127 sPtr
->floatValue
= 0.0;
128 sPtr
->knobProportion
= 1.0;
136 WMSetScrollerArrowsPosition(WMScroller
*sPtr
, WMScrollArrowPosition position
)
138 sPtr
->flags
.arrowsPosition
= position
;
139 if (sPtr
->view
->flags
.realized
) {
146 willResizeScroller(W_ViewDelegate
*self
, WMView
*view
,
147 unsigned int *width
, unsigned int *height
)
149 WMScroller
*sPtr
= (WMScroller
*)view
->self
;
151 if (*width
> *height
) {
152 sPtr
->flags
.horizontal
= 1;
153 *height
= SCROLLER_WIDTH
;
155 sPtr
->flags
.horizontal
= 0;
156 *width
= SCROLLER_WIDTH
;
162 WMSetScrollerAction(WMScroller
*sPtr
, WMAction
*action
, void *clientData
)
164 CHECK_CLASS(sPtr
, WC_Scroller
);
166 sPtr
->action
= action
;
168 sPtr
->clientData
= clientData
;
173 WMSetScrollerParameters(WMScroller
*sPtr
, float floatValue
,
174 float knobProportion
)
176 CHECK_CLASS(sPtr
, WC_Scroller
);
178 assert(!isnan(floatValue
));
180 if (floatValue
< 0.0)
181 sPtr
->floatValue
= 0.0;
182 else if (floatValue
> 1.0)
183 sPtr
->floatValue
= 1.0;
185 sPtr
->floatValue
= floatValue
;
187 if (knobProportion
<= 0.0) {
189 sPtr
->knobProportion
= 0.0;
190 sPtr
->flags
.documentFullyVisible
= 0;
192 } else if (knobProportion
>= 1.0) {
194 sPtr
->knobProportion
= 1.0;
195 sPtr
->flags
.documentFullyVisible
= 1;
198 sPtr
->knobProportion
= knobProportion
;
199 sPtr
->flags
.documentFullyVisible
= 0;
202 if (sPtr
->view
->flags
.realized
)
205 /* WMPostNotificationName(WMScrollerDidScrollNotification, sPtr, NULL);*/
210 WMGetScrollerKnobProportion(WMScroller
*sPtr
)
212 CHECK_CLASS(sPtr
, WC_Scroller
);
214 return sPtr
->knobProportion
;
219 WMGetScrollerValue(WMScroller
*sPtr
)
221 CHECK_CLASS(sPtr
, WC_Scroller
);
223 return sPtr
->floatValue
;
228 WMGetScrollerHitPart(WMScroller
*sPtr
)
230 CHECK_CLASS(sPtr
, WC_Scroller
);
232 return sPtr
->flags
.hitPart
;
237 paintArrow(WMScroller
*sPtr
, Drawable d
, int part
)
239 * part- 0 paints the decrement arrow, 1 the increment arrow
242 WMView
*view
= sPtr
->view
;
243 WMScreen
*scr
= view
->screen
;
247 #ifndef DOUBLE_BUFFER
248 GC gc
= scr
->lightGC
;
251 bsize
= SCROLLER_WIDTH
- 4;
254 if (part
== 0) { /* decrement button */
255 if (sPtr
->flags
.horizontal
) {
256 if (sPtr
->flags
.arrowsPosition
== WSAMaxEnd
) {
257 ofs
= view
->size
.width
- 2*(bsize
+1) - 1;
261 if (sPtr
->flags
.decrDown
)
262 arrow
= scr
->hiLeftArrow
;
264 arrow
= scr
->leftArrow
;
267 if (sPtr
->flags
.arrowsPosition
== WSAMaxEnd
) {
268 ofs
= view
->size
.height
- 2*(bsize
+1) - 1;
272 if (sPtr
->flags
.decrDown
)
273 arrow
= scr
->hiUpArrow
;
275 arrow
= scr
->upArrow
;
278 #ifndef DOUBLE_BUFFER
279 if (sPtr
->flags
.decrDown
)
280 gc
= WMColorGC(scr
->white
);
282 } else { /* increment button */
283 if (sPtr
->flags
.horizontal
) {
284 if (sPtr
->flags
.arrowsPosition
== WSAMaxEnd
) {
285 ofs
= view
->size
.width
- bsize
+1 - 3;
289 if (sPtr
->flags
.incrDown
)
290 arrow
= scr
->hiRightArrow
;
292 arrow
= scr
->rightArrow
;
294 if (sPtr
->flags
.arrowsPosition
== WSAMaxEnd
) {
295 ofs
= view
->size
.height
- bsize
+1 - 3;
299 if (sPtr
->flags
.incrDown
)
300 arrow
= scr
->hiDownArrow
;
302 arrow
= scr
->downArrow
;
305 #ifndef DOUBLE_BUFFER
306 if (sPtr
->flags
.incrDown
)
312 if (sPtr
->flags
.horizontal
) {
315 #ifndef DOUBLE_BUFFER
316 XFillRectangle(scr
->display
, d
, gc
,
317 ofs
+1, 2+1, bsize
+1-3, bsize
-3);
319 if ((!part
&&sPtr
->flags
.decrDown
) || (part
&&sPtr
->flags
.incrDown
))
320 XFillRectangle(scr
->display
, d
, WMColorGC(scr
->white
),
321 ofs
+1, 2+1, bsize
+1-3, bsize
-3);
322 #endif /* DOUBLE_BUFFER */
323 W_DrawRelief(scr
, d
, ofs
, 2, bsize
, bsize
, WRRaised
);
326 XSetClipMask(scr
->display
, scr
->clipGC
, arrow
->mask
);
327 XSetClipOrigin(scr
->display
, scr
->clipGC
,
328 ofs
+ (bsize
- arrow
->width
) / 2,
329 2 + (bsize
- arrow
->height
) / 2);
331 XCopyArea(scr
->display
, arrow
->pixmap
, d
, scr
->clipGC
,
332 0, 0, arrow
->width
, arrow
->height
,
333 ofs
+ (bsize
- arrow
->width
) / 2,
334 2 + (bsize
- arrow
->height
) / 2);
336 } else { /* vertical */
339 #ifndef DOUBLE_BUFFER
340 XFillRectangle(scr
->display
, d
, gc
,
341 2+1, ofs
+1, bsize
-3, bsize
+1-3);
343 if ((!part
&&sPtr
->flags
.decrDown
) || (part
&&sPtr
->flags
.incrDown
))
344 XFillRectangle(scr
->display
, d
, WMColorGC(scr
->white
),
345 2+1, ofs
+1, bsize
-3, bsize
+1-3);
346 #endif /* DOUBLE_BUFFER */
347 W_DrawRelief(scr
, d
, 2, ofs
, bsize
, bsize
, WRRaised
);
351 XSetClipMask(scr
->display
, scr
->clipGC
, arrow
->mask
);
352 XSetClipOrigin(scr
->display
, scr
->clipGC
,
353 2 + (bsize
- arrow
->width
) / 2,
354 ofs
+ (bsize
- arrow
->height
) / 2);
355 XCopyArea(scr
->display
, arrow
->pixmap
, d
, scr
->clipGC
,
356 0, 0, arrow
->width
, arrow
->height
,
357 2 + (bsize
- arrow
->width
) / 2,
358 ofs
+ (bsize
- arrow
->height
) / 2);
364 knobLength(Scroller
*sPtr
)
369 if (sPtr
->flags
.horizontal
)
370 length
= sPtr
->view
->size
.width
- 4;
372 length
= sPtr
->view
->size
.height
- 4;
374 if (sPtr
->flags
.arrowsPosition
== WSAMaxEnd
) {
375 length
-= (SCROLLER_WIDTH
- 4 + 1)*2;
376 } else if (sPtr
->flags
.arrowsPosition
== WSAMinEnd
) {
377 length
-= (SCROLLER_WIDTH
- 4 + 1)*2;
380 tmp
= (int)((float)length
* sPtr
->knobProportion
+ 0.5);
381 /* keep minimum size */
382 if (tmp
< SCROLLER_WIDTH
-4)
383 tmp
= SCROLLER_WIDTH
-4;
390 paintScroller(Scroller
*sPtr
)
392 WMView
*view
= sPtr
->view
;
393 WMScreen
*scr
= view
->screen
;
397 Drawable d
= view
->window
;
404 d
= XCreatePixmap(scr
->display
, view
->window
, view
->size
.width
,
405 view
->size
.height
, scr
->depth
);
406 XFillRectangle(scr
->display
, d
, WMColorGC(scr
->gray
), 0, 0,
407 view
->size
.width
, view
->size
.height
);
410 XDrawRectangle(scr
->display
, d
, WMColorGC(scr
->black
), 0, 0,
411 view
->size
.width
-1, view
->size
.height
-1);
412 #ifndef DOUBLE_BUFFER
413 XDrawRectangle(scr
->display
, d
, WMColorGC(scr
->gray
), 1, 1,
414 view
->size
.width
-3, view
->size
.height
-3);
417 if (sPtr
->flags
.horizontal
)
418 length
= view
->size
.width
- 4;
420 length
= view
->size
.height
- 4;
422 if (sPtr
->flags
.documentFullyVisible
) {
423 XFillRectangle(scr
->display
, d
, scr
->stippleGC
, 2, 2,
424 view
->size
.width
-4, view
->size
.height
-4);
426 if (sPtr
->flags
.arrowsPosition
==WSAMaxEnd
) {
428 length
-= (SCROLLER_WIDTH
- 4 + 1)*2;
429 } else if (sPtr
->flags
.arrowsPosition
==WSAMinEnd
) {
430 ofs
= (SCROLLER_WIDTH
- 4 + 1)*2;
431 length
-= (SCROLLER_WIDTH
- 4 + 1)*2;
436 knobL
= (float)knobLength(sPtr
);
438 knobP
= sPtr
->floatValue
* ((float)length
- knobL
);
440 if (sPtr
->flags
.horizontal
) {
442 XFillRectangle(scr
->display
, d
, scr
->stippleGC
,
443 ofs
+2, 2, (int)knobP
, view
->size
.height
-4);
446 #ifndef DOUBLE_BUFFER
447 XFillRectangle(scr
->display
, d
, scr
->lightGC
,
448 ofs
+2+(int)knobP
+2, 2+2, (int)knobL
-4,
449 view
->size
.height
-4-4);
451 W_DrawRelief(scr
, d
, ofs
+2+(int)knobP
, 2, (int)knobL
,
452 view
->size
.height
-4, WRRaised
);
454 XCopyArea(scr
->display
, scr
->scrollerDimple
->pixmap
, d
,
456 scr
->scrollerDimple
->width
, scr
->scrollerDimple
->height
,
457 ofs
+2+(int)knobP
+((int)knobL
-scr
->scrollerDimple
->width
-1)/2,
458 (view
->size
.height
-scr
->scrollerDimple
->height
-1)/2);
461 if ((int)(knobP
+knobL
) < length
)
462 XFillRectangle(scr
->display
, d
, scr
->stippleGC
,
463 ofs
+2+(int)(knobP
+knobL
), 2,
464 length
-(int)(knobP
+knobL
),
465 view
->size
.height
-4);
469 XFillRectangle(scr
->display
, d
, scr
->stippleGC
,
470 2, ofs
+2, view
->size
.width
-4, (int)knobP
);
473 #ifndef DOUBLE_BUFFER
474 XFillRectangle(scr
->display
, d
, scr
->lightGC
,
475 2+2, ofs
+2+(int)knobP
+2,
476 view
->size
.width
-4-4, (int)knobL
-4);
478 XCopyArea(scr
->display
, scr
->scrollerDimple
->pixmap
, d
,
480 scr
->scrollerDimple
->width
, scr
->scrollerDimple
->height
,
481 (view
->size
.width
-scr
->scrollerDimple
->width
-1)/2,
482 ofs
+2+(int)knobP
+((int)knobL
-scr
->scrollerDimple
->height
-1)/2);
484 W_DrawRelief(scr
, d
, 2, ofs
+2+(int)knobP
,
485 view
->size
.width
-4, (int)knobL
, WRRaised
);
488 if ((int)(knobP
+knobL
) < length
)
489 XFillRectangle(scr
->display
, d
, scr
->stippleGC
,
490 2, ofs
+2+(int)(knobP
+knobL
),
492 length
-(int)(knobP
+knobL
));
495 if (sPtr
->flags
.arrowsPosition
!= WSANone
) {
496 paintArrow(sPtr
, d
, 0);
497 paintArrow(sPtr
, d
, 1);
502 XCopyArea(scr
->display
, d
, view
->window
, scr
->copyGC
, 0, 0,
503 view
->size
.width
, view
->size
.height
, 0, 0);
504 XFreePixmap(scr
->display
, d
);
511 handleEvents(XEvent
*event
, void *data
)
513 Scroller
*sPtr
= (Scroller
*)data
;
515 CHECK_CLASS(data
, WC_Scroller
);
518 switch (event
->type
) {
520 if (event
->xexpose
.count
==0)
525 destroyScroller(sPtr
);
533 * locatePointInScroller-
534 * Return the part of the scroller where the point is located.
536 static WMScrollerPart
537 locatePointInScroller(Scroller
*sPtr
, int x
, int y
, int alternate
)
539 int width
= sPtr
->view
->size
.width
;
540 int height
= sPtr
->view
->size
.height
;
541 int c
, p1
, p2
, p3
, p4
, p5
, p6
;
545 /* if there is no knob... */
546 if (sPtr
->flags
.documentFullyVisible
)
549 if (sPtr
->flags
.horizontal
)
555 * | | |###########| |#####| | |
556 * | < | > |###########| O |#####| < | > |
557 * | | |###########| |#####| | |
560 if (sPtr
->flags
.arrowsPosition
== WSAMinEnd
) {
564 if (sPtr
->flags
.horizontal
) {
572 } else if (sPtr
->flags
.arrowsPosition
== WSAMaxEnd
) {
573 if (sPtr
->flags
.horizontal
) {
587 if (sPtr
->flags
.horizontal
) {
588 slotL
= p5
= p6
= width
;
590 slotL
= p5
= p6
= height
;
594 knobL
= knobLength(sPtr
);
595 p3
= p2
+ (int)((float)(slotL
-knobL
) * sPtr
->floatValue
);
598 /* uses a mix of the NS and Win ways of doing scroll page */
600 return alternate
? WSDecrementPage
: WSDecrementLine
;
602 return alternate
? WSIncrementPage
: WSIncrementLine
;
604 return WSDecrementPage
;
608 return WSIncrementPage
;
610 return alternate
? WSDecrementPage
: WSDecrementLine
;
612 return alternate
? WSIncrementPage
: WSIncrementLine
;
618 handlePush(Scroller
*sPtr
, int pushX
, int pushY
, int alternate
)
623 part
= locatePointInScroller(sPtr
, pushX
, pushY
, alternate
);
625 sPtr
->flags
.hitPart
= part
;
628 case WSIncrementLine
:
629 sPtr
->flags
.incrDown
= 1;
633 case WSIncrementPage
:
637 case WSDecrementLine
:
638 sPtr
->flags
.decrDown
= 1;
642 case WSDecrementPage
:
647 sPtr
->flags
.draggingKnob
= 1;
648 #ifndef STRICT_NEXT_BEHAVIOUR
649 if (sPtr
->flags
.horizontal
)
650 sPtr
->dragPoint
= pushX
;
652 sPtr
->dragPoint
= pushY
;
655 int noButtons
= (sPtr
->flags
.arrowsPosition
== WSANone
);
658 if (sPtr
->flags
.horizontal
)
659 length
= sPtr
->view
->size
.width
- 4;
661 length
= sPtr
->view
->size
.height
- 4;
666 knobP
= (int)(sPtr
->floatValue
* (float)(length
-knobLength(sPtr
)));
668 if (sPtr
->flags
.arrowsPosition
== WSAMinEnd
)
669 sPtr
->dragPoint
-= 2 + (noButtons
? 0 : 36) + knobP
;
671 sPtr
->dragPoint
-= 2 + knobP
;
673 #endif /* STRICT_NEXT_BEHAVIOUR */
674 /* This does not seem necesary here since we don't know yet if the
675 * knob will be dragged later. -Dan
676 handleMotion(sPtr, pushX, pushY); */
685 if (doAction
&& sPtr
->action
) {
686 (*sPtr
->action
)(sPtr
, sPtr
->clientData
);
688 WMPostNotificationName(WMScrollerDidScrollNotification
, sPtr
, NULL
);
694 floatValueForPoint(int slotOfs
, int slotLength
, int knobLength
, int point
)
696 float floatValue
= 0;
699 #ifdef STRICT_NEXT_BEHAVIOUR
700 if (point
< slotOfs
+ knobLength
/2)
701 position
= (float)(slotOfs
+ knobLength
/2);
702 else if (point
> slotOfs
+ slotLength
- knobLength
/2)
703 position
= (float)(slotOfs
+ slotLength
- knobLength
/2);
705 position
= (float)point
;
707 floatValue
= (position
-(float)(slotOfs
+slotLength
/2))
708 /(float)(slotLength
-knobLength
);
710 /* Adjust the last point to lie inside the knob slot */
712 position
= (float)slotOfs
;
713 else if (point
> slotOfs
+ slotLength
)
714 position
= (float)(slotOfs
+ slotLength
);
716 position
= (float)point
;
718 /* Compute the float value */
719 floatValue
= (position
-(float)slotOfs
) / (float)(slotLength
-knobLength
);
722 assert(!isnan(floatValue
));
728 handleMotion(Scroller
*sPtr
, int mouseX
, int mouseY
)
732 int noButtons
= (sPtr
->flags
.arrowsPosition
== WSANone
);
734 if (sPtr
->flags
.arrowsPosition
== WSAMinEnd
)
735 slotOffset
= 2 + (noButtons
? 0 : 36);
739 if (sPtr
->flags
.draggingKnob
) {
741 #ifdef STRICT_NEXT_BEHAVIOUR
742 if (sPtr
->flags
.horizontal
) {
743 slotLength
= sPtr
->view
->size
.width
-4-(noButtons
? 0 : 36);
744 newFloatValue
= floatValueForPoint(slotOffset
, slotLength
,
745 (int)(slotLength
*sPtr
->knobProportion
),
748 slotLength
= sPtr
->view
->size
.height
-4-(noButtons
? 0 : 36);
749 newFloatValue
= floatValueForPoint(slotOffset
, slotLength
,
750 (int)(slotLength
*sPtr
->knobProportion
),
754 if (sPtr
->flags
.horizontal
) {
755 slotLength
= sPtr
->view
->size
.width
-4-(noButtons
? 0 : 36);
756 newFloatValue
= floatValueForPoint(slotOffset
, slotLength
,
757 (int)(slotLength
*sPtr
->knobProportion
),
758 mouseX
-sPtr
->dragPoint
);
760 slotLength
= sPtr
->view
->size
.height
-4-(noButtons
? 0 : 36);
761 newFloatValue
= floatValueForPoint(slotOffset
, slotLength
,
762 (int)(slotLength
*sPtr
->knobProportion
),
763 mouseY
-sPtr
->dragPoint
);
765 #endif /* !STRICT_NEXT_BEHAVIOUR */
766 WMSetScrollerParameters(sPtr
, newFloatValue
, sPtr
->knobProportion
);
768 (*sPtr
->action
)(sPtr
, sPtr
->clientData
);
769 WMPostNotificationName(WMScrollerDidScrollNotification
, sPtr
,
775 part
= locatePointInScroller(sPtr
, mouseX
, mouseY
, False
);
777 sPtr
->flags
.hitPart
= part
;
779 if (part
== WSIncrementLine
&& sPtr
->flags
.decrDown
) {
780 sPtr
->flags
.decrDown
= 0;
781 sPtr
->flags
.incrDown
= 1;
782 } else if (part
== WSDecrementLine
&& sPtr
->flags
.incrDown
) {
783 sPtr
->flags
.incrDown
= 0;
784 sPtr
->flags
.decrDown
= 1;
785 } else if (part
!= WSIncrementLine
&& part
!= WSDecrementLine
) {
786 sPtr
->flags
.incrDown
= 0;
787 sPtr
->flags
.decrDown
= 0;
794 autoScroll(void *clientData
)
796 Scroller
*sPtr
= (Scroller
*)clientData
;
799 (*sPtr
->action
)(sPtr
, sPtr
->clientData
);
800 WMPostNotificationName(WMScrollerDidScrollNotification
, sPtr
, NULL
);
802 sPtr
->timerID
= WMAddTimerHandler(AUTOSCROLL_DELAY
, autoScroll
, clientData
);
807 handleActionEvents(XEvent
*event
, void *data
)
809 Scroller
*sPtr
= (Scroller
*)data
;
813 /* check if we're really dealing with a scroller, as something
814 * might have gone wrong in the event dispatching stuff */
815 CHECK_CLASS(sPtr
, WC_Scroller
);
817 id
= sPtr
->flags
.incrDown
;
818 dd
= sPtr
->flags
.decrDown
;
820 switch (event
->type
) {
827 WMDeleteTimerHandler(sPtr
->timerID
);
828 sPtr
->timerID
= NULL
;
830 sPtr
->flags
.incrDown
= 0;
831 sPtr
->flags
.decrDown
= 0;
835 /* FIXME: change Mod1Mask with something else */
836 if (sPtr
->flags
.documentFullyVisible
)
838 if (event
->xbutton
.button
==WINGsConfiguration
.mouseWheelUp
) {
839 if (event
->xbutton
.state
& ControlMask
) {
840 sPtr
->flags
.hitPart
= WSDecrementPage
;
841 } else if (event
->xbutton
.state
& ShiftMask
) {
842 sPtr
->flags
.hitPart
= WSDecrementLine
;
844 sPtr
->flags
.hitPart
= WSDecrementWheel
;
847 (*sPtr
->action
)(sPtr
, sPtr
->clientData
);
848 WMPostNotificationName(WMScrollerDidScrollNotification
, sPtr
,
851 } else if (event
->xbutton
.button
==WINGsConfiguration
.mouseWheelDown
) {
852 if (event
->xbutton
.state
& ControlMask
) {
853 sPtr
->flags
.hitPart
= WSIncrementPage
;
854 } else if (event
->xbutton
.state
& ShiftMask
) {
855 sPtr
->flags
.hitPart
= WSIncrementLine
;
857 sPtr
->flags
.hitPart
= WSIncrementWheel
;
860 (*sPtr
->action
)(sPtr
, sPtr
->clientData
);
861 WMPostNotificationName(WMScrollerDidScrollNotification
, sPtr
,
865 handlePush(sPtr
, event
->xbutton
.x
, event
->xbutton
.y
,
866 (event
->xbutton
.state
& Mod1Mask
)
867 ||event
->xbutton
.button
==Button2
);
868 /* continue scrolling if pushed on the buttons */
869 if (sPtr
->flags
.hitPart
== WSIncrementLine
870 || sPtr
->flags
.hitPart
== WSDecrementLine
) {
871 sPtr
->timerID
= WMAddTimerHandler(AUTOSCROLL_INITIAL_DELAY
,
878 if (sPtr
->flags
.draggingKnob
) {
880 (*sPtr
->action
)(sPtr
, sPtr
->clientData
);
881 WMPostNotificationName(WMScrollerDidScrollNotification
, sPtr
,
886 WMDeleteTimerHandler(sPtr
->timerID
);
887 sPtr
->timerID
= NULL
;
889 sPtr
->flags
.incrDown
= 0;
890 sPtr
->flags
.decrDown
= 0;
891 sPtr
->flags
.draggingKnob
= 0;
895 handleMotion(sPtr
, event
->xbutton
.x
, event
->xbutton
.y
);
896 if (sPtr
->timerID
&& sPtr
->flags
.hitPart
!= WSIncrementLine
897 && sPtr
->flags
.hitPart
!= WSDecrementLine
) {
898 WMDeleteTimerHandler(sPtr
->timerID
);
899 sPtr
->timerID
= NULL
;
903 if (id
!= sPtr
->flags
.incrDown
|| dd
!= sPtr
->flags
.decrDown
)
910 destroyScroller(Scroller
*sPtr
)
912 /* we don't want autoscroll try to scroll a freed widget */
914 WMDeleteTimerHandler(sPtr
->timerID
);