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
72 #define BUTTON_SIZE ((SCROLLER_WIDTH) - 4)
75 static void destroyScroller(Scroller
*sPtr
);
76 static void paintScroller(Scroller
*sPtr
);
78 static void willResizeScroller();
79 static void handleEvents(XEvent
*event
, void *data
);
80 static void handleActionEvents(XEvent
*event
, void *data
);
82 static void handleMotion(Scroller
*sPtr
, int mouseX
, int mouseY
);
85 W_ViewDelegate _ScrollerViewDelegate
= {
97 WMCreateScroller(WMWidget
*parent
)
101 sPtr
= wmalloc(sizeof(Scroller
));
102 memset(sPtr
, 0, sizeof(Scroller
));
104 sPtr
->widgetClass
= WC_Scroller
;
106 sPtr
->view
= W_CreateView(W_VIEW(parent
));
111 sPtr
->view
->self
= sPtr
;
113 sPtr
->view
->delegate
= &_ScrollerViewDelegate
;
115 sPtr
->flags
.documentFullyVisible
= 1;
117 WMCreateEventHandler(sPtr
->view
, ExposureMask
|StructureNotifyMask
118 |ClientMessageMask
, handleEvents
, sPtr
);
120 W_ResizeView(sPtr
->view
, DEFAULT_WIDTH
, DEFAULT_WIDTH
);
121 sPtr
->flags
.arrowsPosition
= DEFAULT_ARROWS_POSITION
;
123 WMCreateEventHandler(sPtr
->view
, ButtonPressMask
|ButtonReleaseMask
124 |EnterWindowMask
|LeaveWindowMask
|ButtonMotionMask
,
125 handleActionEvents
, sPtr
);
127 sPtr
->flags
.hitPart
= WSNoPart
;
129 sPtr
->floatValue
= 0.0;
130 sPtr
->knobProportion
= 1.0;
138 WMSetScrollerArrowsPosition(WMScroller
*sPtr
, WMScrollArrowPosition position
)
140 sPtr
->flags
.arrowsPosition
= position
;
141 if (sPtr
->view
->flags
.realized
) {
148 willResizeScroller(W_ViewDelegate
*self
, WMView
*view
,
149 unsigned int *width
, unsigned int *height
)
151 WMScroller
*sPtr
= (WMScroller
*)view
->self
;
153 if (*width
> *height
) {
154 sPtr
->flags
.horizontal
= 1;
155 *height
= SCROLLER_WIDTH
;
157 sPtr
->flags
.horizontal
= 0;
158 *width
= SCROLLER_WIDTH
;
164 WMSetScrollerAction(WMScroller
*sPtr
, WMAction
*action
, void *clientData
)
166 CHECK_CLASS(sPtr
, WC_Scroller
);
168 sPtr
->action
= action
;
170 sPtr
->clientData
= clientData
;
175 WMSetScrollerParameters(WMScroller
*sPtr
, float floatValue
,
176 float knobProportion
)
178 CHECK_CLASS(sPtr
, WC_Scroller
);
180 assert(!isnan(floatValue
));
182 if (floatValue
< 0.0)
183 sPtr
->floatValue
= 0.0;
184 else if (floatValue
> 1.0)
185 sPtr
->floatValue
= 1.0;
187 sPtr
->floatValue
= floatValue
;
189 if (knobProportion
<= 0.0) {
191 sPtr
->knobProportion
= 0.0;
192 sPtr
->flags
.documentFullyVisible
= 0;
194 } else if (knobProportion
>= 1.0) {
196 sPtr
->knobProportion
= 1.0;
197 sPtr
->flags
.documentFullyVisible
= 1;
200 sPtr
->knobProportion
= knobProportion
;
201 sPtr
->flags
.documentFullyVisible
= 0;
204 if (sPtr
->view
->flags
.realized
)
207 /* WMPostNotificationName(WMScrollerDidScrollNotification, sPtr, NULL);*/
212 WMGetScrollerKnobProportion(WMScroller
*sPtr
)
214 CHECK_CLASS(sPtr
, WC_Scroller
);
216 return sPtr
->knobProportion
;
221 WMGetScrollerValue(WMScroller
*sPtr
)
223 CHECK_CLASS(sPtr
, WC_Scroller
);
225 return sPtr
->floatValue
;
230 WMGetScrollerHitPart(WMScroller
*sPtr
)
232 CHECK_CLASS(sPtr
, WC_Scroller
);
234 return sPtr
->flags
.hitPart
;
239 paintArrow(WMScroller
*sPtr
, Drawable d
, int part
)
241 * part- 0 paints the decrement arrow, 1 the increment arrow
244 WMView
*view
= sPtr
->view
;
245 WMScreen
*scr
= view
->screen
;
249 #ifndef DOUBLE_BUFFER
250 GC gc
= scr
->lightGC
;
253 if (part
== 0) { /* decrement button */
254 if (sPtr
->flags
.horizontal
) {
255 if (sPtr
->flags
.arrowsPosition
== WSAMaxEnd
) {
256 ofs
= view
->size
.width
- 2*(BUTTON_SIZE
+1) - 1;
260 if (sPtr
->flags
.decrDown
)
261 arrow
= scr
->hiLeftArrow
;
263 arrow
= scr
->leftArrow
;
266 if (sPtr
->flags
.arrowsPosition
== WSAMaxEnd
) {
267 ofs
= view
->size
.height
- 2*(BUTTON_SIZE
+1) - 1;
271 if (sPtr
->flags
.decrDown
)
272 arrow
= scr
->hiUpArrow
;
274 arrow
= scr
->upArrow
;
277 #ifndef DOUBLE_BUFFER
278 if (sPtr
->flags
.decrDown
)
279 gc
= WMColorGC(scr
->white
);
281 } else { /* increment button */
282 if (sPtr
->flags
.horizontal
) {
283 if (sPtr
->flags
.arrowsPosition
== WSAMaxEnd
) {
284 ofs
= view
->size
.width
- BUTTON_SIZE
+1 - 3;
286 ofs
= 2 + BUTTON_SIZE
+1;
288 if (sPtr
->flags
.incrDown
)
289 arrow
= scr
->hiRightArrow
;
291 arrow
= scr
->rightArrow
;
293 if (sPtr
->flags
.arrowsPosition
== WSAMaxEnd
) {
294 ofs
= view
->size
.height
- BUTTON_SIZE
+1 - 3;
296 ofs
= 2 + BUTTON_SIZE
+1;
298 if (sPtr
->flags
.incrDown
)
299 arrow
= scr
->hiDownArrow
;
301 arrow
= scr
->downArrow
;
304 #ifndef DOUBLE_BUFFER
305 if (sPtr
->flags
.incrDown
)
311 if (sPtr
->flags
.horizontal
) {
313 #ifndef DOUBLE_BUFFER
314 XFillRectangle(scr
->display
, d
, gc
,
315 ofs
+1, 2+1, BUTTON_SIZE
+1-3, BUTTON_SIZE
-3);
317 if ((!part
&&sPtr
->flags
.decrDown
) || (part
&&sPtr
->flags
.incrDown
))
318 XFillRectangle(scr
->display
, d
, WMColorGC(scr
->white
),
319 ofs
+1, 2+1, BUTTON_SIZE
+1-3, BUTTON_SIZE
-3);
320 #endif /* DOUBLE_BUFFER */
321 W_DrawRelief(scr
, d
, ofs
, 2, BUTTON_SIZE
, BUTTON_SIZE
, WRRaised
);
324 XSetClipMask(scr
->display
, scr
->clipGC
, arrow
->mask
);
325 XSetClipOrigin(scr
->display
, scr
->clipGC
,
326 ofs
+ (BUTTON_SIZE
- arrow
->width
) / 2,
327 2 + (BUTTON_SIZE
- arrow
->height
) / 2);
329 XCopyArea(scr
->display
, arrow
->pixmap
, d
, scr
->clipGC
,
330 0, 0, arrow
->width
, arrow
->height
,
331 ofs
+ (BUTTON_SIZE
- arrow
->width
) / 2,
332 2 + (BUTTON_SIZE
- arrow
->height
) / 2);
334 } else { /* vertical */
337 #ifndef DOUBLE_BUFFER
338 XFillRectangle(scr
->display
, d
, gc
,
339 2+1, ofs
+1, BUTTON_SIZE
-3, BUTTON_SIZE
+1-3);
341 if ((!part
&&sPtr
->flags
.decrDown
) || (part
&&sPtr
->flags
.incrDown
))
342 XFillRectangle(scr
->display
, d
, WMColorGC(scr
->white
),
343 2+1, ofs
+1, BUTTON_SIZE
-3, BUTTON_SIZE
+1-3);
344 #endif /* DOUBLE_BUFFER */
345 W_DrawRelief(scr
, d
, 2, ofs
, BUTTON_SIZE
, BUTTON_SIZE
, WRRaised
);
349 XSetClipMask(scr
->display
, scr
->clipGC
, arrow
->mask
);
350 XSetClipOrigin(scr
->display
, scr
->clipGC
,
351 2 + (BUTTON_SIZE
- arrow
->width
) / 2,
352 ofs
+ (BUTTON_SIZE
- arrow
->height
) / 2);
353 XCopyArea(scr
->display
, arrow
->pixmap
, d
, scr
->clipGC
,
354 0, 0, arrow
->width
, arrow
->height
,
355 2 + (BUTTON_SIZE
- arrow
->width
) / 2,
356 ofs
+ (BUTTON_SIZE
- arrow
->height
) / 2);
362 knobLength(Scroller
*sPtr
)
367 if (sPtr
->flags
.horizontal
)
368 length
= sPtr
->view
->size
.width
- 4;
370 length
= sPtr
->view
->size
.height
- 4;
372 if (sPtr
->flags
.arrowsPosition
!= WSANone
) {
373 length
-= 2*(BUTTON_SIZE
+1);
376 tmp
= (int)((float)length
* sPtr
->knobProportion
+ 0.5);
377 /* keep minimum size */
378 if (tmp
< BUTTON_SIZE
)
386 paintScroller(Scroller
*sPtr
)
388 WMView
*view
= sPtr
->view
;
389 WMScreen
*scr
= view
->screen
;
393 Drawable d
= view
->window
;
400 d
= XCreatePixmap(scr
->display
, view
->window
, view
->size
.width
,
401 view
->size
.height
, scr
->depth
);
402 XFillRectangle(scr
->display
, d
, WMColorGC(scr
->gray
), 0, 0,
403 view
->size
.width
, view
->size
.height
);
406 XDrawRectangle(scr
->display
, d
, WMColorGC(scr
->black
), 0, 0,
407 view
->size
.width
-1, view
->size
.height
-1);
408 #ifndef DOUBLE_BUFFER
409 XDrawRectangle(scr
->display
, d
, WMColorGC(scr
->gray
), 1, 1,
410 view
->size
.width
-3, view
->size
.height
-3);
413 if (sPtr
->flags
.horizontal
)
414 length
= view
->size
.width
- 4;
416 length
= view
->size
.height
- 4;
418 if (sPtr
->flags
.documentFullyVisible
) {
419 XFillRectangle(scr
->display
, d
, scr
->stippleGC
, 2, 2,
420 view
->size
.width
-4, view
->size
.height
-4);
423 if (sPtr
->flags
.arrowsPosition
==WSAMaxEnd
) {
424 length
-= (BUTTON_SIZE
+1)*2;
425 } else if (sPtr
->flags
.arrowsPosition
==WSAMinEnd
) {
426 ofs
+= (BUTTON_SIZE
+1)*2;
427 length
-= (BUTTON_SIZE
+1)*2;
430 knobL
= (float)knobLength(sPtr
);
432 knobP
= sPtr
->floatValue
* ((float)length
- knobL
);
434 if (sPtr
->flags
.horizontal
) {
436 XFillRectangle(scr
->display
, d
, scr
->stippleGC
,
437 ofs
, 2, (int)knobP
, view
->size
.height
-4);
440 #ifndef DOUBLE_BUFFER
441 XFillRectangle(scr
->display
, d
, scr
->lightGC
,
442 ofs
+(int)knobP
+2, 2+2, (int)knobL
-4,
443 view
->size
.height
-4-4);
445 W_DrawRelief(scr
, d
, ofs
+(int)knobP
, 2, (int)knobL
,
446 view
->size
.height
-4, WRRaised
);
448 XCopyArea(scr
->display
, scr
->scrollerDimple
->pixmap
, d
,
450 scr
->scrollerDimple
->width
, scr
->scrollerDimple
->height
,
451 ofs
+(int)knobP
+((int)knobL
-scr
->scrollerDimple
->width
-1)/2,
452 (view
->size
.height
-scr
->scrollerDimple
->height
-1)/2);
455 if ((int)(knobP
+knobL
) < length
)
456 XFillRectangle(scr
->display
, d
, scr
->stippleGC
,
457 ofs
+(int)(knobP
+knobL
), 2,
458 length
-(int)(knobP
+knobL
),
459 view
->size
.height
-4);
463 XFillRectangle(scr
->display
, d
, scr
->stippleGC
,
464 2, ofs
, view
->size
.width
-4, (int)knobP
);
467 #ifndef DOUBLE_BUFFER
468 XFillRectangle(scr
->display
, d
, scr
->lightGC
,
469 2+2, ofs
+(int)knobP
+2,
470 view
->size
.width
-4-4, (int)knobL
-4);
472 XCopyArea(scr
->display
, scr
->scrollerDimple
->pixmap
, d
,
474 scr
->scrollerDimple
->width
, scr
->scrollerDimple
->height
,
475 (view
->size
.width
-scr
->scrollerDimple
->width
-1)/2,
476 ofs
+(int)knobP
+((int)knobL
-scr
->scrollerDimple
->height
-1)/2);
478 W_DrawRelief(scr
, d
, 2, ofs
+(int)knobP
,
479 view
->size
.width
-4, (int)knobL
, WRRaised
);
482 if ((int)(knobP
+knobL
) < length
)
483 XFillRectangle(scr
->display
, d
, scr
->stippleGC
,
484 2, ofs
+(int)(knobP
+knobL
),
486 length
-(int)(knobP
+knobL
));
489 if (sPtr
->flags
.arrowsPosition
!= WSANone
) {
490 paintArrow(sPtr
, d
, 0);
491 paintArrow(sPtr
, d
, 1);
496 XCopyArea(scr
->display
, d
, view
->window
, scr
->copyGC
, 0, 0,
497 view
->size
.width
, view
->size
.height
, 0, 0);
498 XFreePixmap(scr
->display
, d
);
505 handleEvents(XEvent
*event
, void *data
)
507 Scroller
*sPtr
= (Scroller
*)data
;
509 CHECK_CLASS(data
, WC_Scroller
);
512 switch (event
->type
) {
514 if (event
->xexpose
.count
==0)
519 destroyScroller(sPtr
);
527 * locatePointInScroller-
528 * Return the part of the scroller where the point is located.
530 static WMScrollerPart
531 locatePointInScroller(Scroller
*sPtr
, int x
, int y
, int alternate
)
533 int width
= sPtr
->view
->size
.width
;
534 int height
= sPtr
->view
->size
.height
;
535 int c
, p1
, p2
, p3
, p4
, p5
, p6
;
539 /* if there is no knob... */
540 if (sPtr
->flags
.documentFullyVisible
)
543 if (sPtr
->flags
.horizontal
)
549 * | | |###########| |#####| | |
550 * | < | > |###########| O |#####| < | > |
551 * | | |###########| |#####| | |
554 if (sPtr
->flags
.arrowsPosition
== WSAMinEnd
) {
558 if (sPtr
->flags
.horizontal
) {
566 } else if (sPtr
->flags
.arrowsPosition
== WSAMaxEnd
) {
567 if (sPtr
->flags
.horizontal
) {
581 if (sPtr
->flags
.horizontal
) {
582 slotL
= p5
= p6
= width
;
584 slotL
= p5
= p6
= height
;
588 knobL
= knobLength(sPtr
);
589 p3
= p2
+ (int)((float)(slotL
-knobL
) * sPtr
->floatValue
);
592 /* uses a mix of the NS and Win ways of doing scroll page */
594 return alternate
? WSDecrementPage
: WSDecrementLine
;
596 return alternate
? WSIncrementPage
: WSIncrementLine
;
598 return WSDecrementPage
;
602 return WSIncrementPage
;
604 return alternate
? WSDecrementPage
: WSDecrementLine
;
606 return alternate
? WSIncrementPage
: WSIncrementLine
;
612 handlePush(Scroller
*sPtr
, int pushX
, int pushY
, int alternate
)
617 part
= locatePointInScroller(sPtr
, pushX
, pushY
, alternate
);
619 sPtr
->flags
.hitPart
= part
;
622 case WSIncrementLine
:
623 sPtr
->flags
.incrDown
= 1;
627 case WSIncrementPage
:
631 case WSDecrementLine
:
632 sPtr
->flags
.decrDown
= 1;
636 case WSDecrementPage
:
641 sPtr
->flags
.draggingKnob
= 1;
642 #ifndef STRICT_NEXT_BEHAVIOUR
643 if (sPtr
->flags
.horizontal
)
644 sPtr
->dragPoint
= pushX
;
646 sPtr
->dragPoint
= pushY
;
652 if (sPtr
->flags
.arrowsPosition
!= WSANone
)
653 buttonsLen
= 2*(BUTTON_SIZE
+1);
657 if (sPtr
->flags
.horizontal
)
658 length
= sPtr
->view
->size
.width
- 4 - buttonsLen
;
660 length
= sPtr
->view
->size
.height
- 4 - buttonsLen
;
662 knobP
= (int)(sPtr
->floatValue
* (float)(length
-knobLength(sPtr
)));
664 if (sPtr
->flags
.arrowsPosition
== WSAMinEnd
)
665 sPtr
->dragPoint
-= 2 + buttonsLen
+ knobP
;
667 sPtr
->dragPoint
-= 2 + knobP
;
669 #endif /* STRICT_NEXT_BEHAVIOUR */
670 /* This does not seem necesary here since we don't know yet if the
671 * knob will be dragged later. -Dan
672 handleMotion(sPtr, pushX, pushY); */
681 if (doAction
&& sPtr
->action
) {
682 (*sPtr
->action
)(sPtr
, sPtr
->clientData
);
684 WMPostNotificationName(WMScrollerDidScrollNotification
, sPtr
, NULL
);
690 floatValueForPoint(Scroller
*sPtr
, int point
)
692 float floatValue
= 0;
694 int slotOfs
, slotLength
, knobL
;
696 if (sPtr
->flags
.horizontal
)
697 slotLength
= sPtr
->view
->size
.width
- 4;
699 slotLength
= sPtr
->view
->size
.height
- 4;
702 if (sPtr
->flags
.arrowsPosition
==WSAMaxEnd
) {
703 slotLength
-= (BUTTON_SIZE
+1)*2;
704 } else if (sPtr
->flags
.arrowsPosition
==WSAMinEnd
) {
705 slotOfs
+= (BUTTON_SIZE
+1)*2;
706 slotLength
-= (BUTTON_SIZE
+1)*2;
709 knobL
= (float)knobLength(sPtr
);
710 #ifdef STRICT_NEXT_BEHAVIOUR
711 if (point
< slotOfs
+ knobL
/2)
712 position
= (float)(slotOfs
+ knobL
/2);
713 else if (point
> slotOfs
+ slotLength
- knobL
/2)
714 position
= (float)(slotOfs
+ slotLength
- knobL
/2);
716 position
= (float)point
;
718 floatValue
= (position
-(float)(slotOfs
+slotLength
/2))
719 /(float)(slotLength
-knobL
);
721 /* Adjust the last point to lie inside the knob slot */
723 position
= (float)slotOfs
;
724 else if (point
> slotOfs
+ slotLength
)
725 position
= (float)(slotOfs
+ slotLength
);
727 position
= (float)point
;
729 /* Compute the float value */
730 floatValue
= (position
-(float)slotOfs
) / (float)(slotLength
-knobL
);
733 assert(!isnan(floatValue
));
739 handleMotion(Scroller
*sPtr
, int mouseX
, int mouseY
)
741 if (sPtr
->flags
.draggingKnob
) {
745 if (sPtr
->flags
.horizontal
) {
751 #ifndef STRICT_NEXT_BEHAVIOUR
752 point
-= sPtr
->dragPoint
;
755 newFloatValue
= floatValueForPoint(sPtr
, point
);
756 WMSetScrollerParameters(sPtr
, newFloatValue
, sPtr
->knobProportion
);
758 (*sPtr
->action
)(sPtr
, sPtr
->clientData
);
759 WMPostNotificationName(WMScrollerDidScrollNotification
, sPtr
,
765 part
= locatePointInScroller(sPtr
, mouseX
, mouseY
, False
);
767 sPtr
->flags
.hitPart
= part
;
769 if (part
== WSIncrementLine
&& sPtr
->flags
.decrDown
) {
770 sPtr
->flags
.decrDown
= 0;
771 sPtr
->flags
.incrDown
= 1;
772 } else if (part
== WSDecrementLine
&& sPtr
->flags
.incrDown
) {
773 sPtr
->flags
.incrDown
= 0;
774 sPtr
->flags
.decrDown
= 1;
775 } else if (part
!= WSIncrementLine
&& part
!= WSDecrementLine
) {
776 sPtr
->flags
.incrDown
= 0;
777 sPtr
->flags
.decrDown
= 0;
784 autoScroll(void *clientData
)
786 Scroller
*sPtr
= (Scroller
*)clientData
;
789 (*sPtr
->action
)(sPtr
, sPtr
->clientData
);
790 WMPostNotificationName(WMScrollerDidScrollNotification
, sPtr
, NULL
);
792 sPtr
->timerID
= WMAddTimerHandler(AUTOSCROLL_DELAY
, autoScroll
, clientData
);
797 handleActionEvents(XEvent
*event
, void *data
)
799 Scroller
*sPtr
= (Scroller
*)data
;
800 int wheelDecrement
, wheelIncrement
;
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
) {
817 WMDeleteTimerHandler(sPtr
->timerID
);
818 sPtr
->timerID
= NULL
;
820 sPtr
->flags
.incrDown
= 0;
821 sPtr
->flags
.decrDown
= 0;
825 /* FIXME: change Mod1Mask with something else */
826 if (sPtr
->flags
.documentFullyVisible
)
829 if (sPtr
->flags
.horizontal
) {
830 wheelDecrement
= WINGsConfiguration
.mouseWheelDown
;
831 wheelIncrement
= WINGsConfiguration
.mouseWheelUp
;
833 wheelDecrement
= WINGsConfiguration
.mouseWheelUp
;
834 wheelIncrement
= WINGsConfiguration
.mouseWheelDown
;
837 if (event
->xbutton
.button
== wheelDecrement
) {
838 if (event
->xbutton
.state
& ControlMask
) {
839 sPtr
->flags
.hitPart
= WSDecrementPage
;
840 } else if (event
->xbutton
.state
& ShiftMask
) {
841 sPtr
->flags
.hitPart
= WSDecrementLine
;
843 sPtr
->flags
.hitPart
= WSDecrementWheel
;
846 (*sPtr
->action
)(sPtr
, sPtr
->clientData
);
847 WMPostNotificationName(WMScrollerDidScrollNotification
, sPtr
,
850 } else if (event
->xbutton
.button
== wheelIncrement
) {
851 if (event
->xbutton
.state
& ControlMask
) {
852 sPtr
->flags
.hitPart
= WSIncrementPage
;
853 } else if (event
->xbutton
.state
& ShiftMask
) {
854 sPtr
->flags
.hitPart
= WSIncrementLine
;
856 sPtr
->flags
.hitPart
= WSIncrementWheel
;
859 (*sPtr
->action
)(sPtr
, sPtr
->clientData
);
860 WMPostNotificationName(WMScrollerDidScrollNotification
, sPtr
,
864 handlePush(sPtr
, event
->xbutton
.x
, event
->xbutton
.y
,
865 (event
->xbutton
.state
& Mod1Mask
)
866 ||event
->xbutton
.button
==Button2
);
867 /* continue scrolling if pushed on the buttons */
868 if (sPtr
->flags
.hitPart
== WSIncrementLine
869 || sPtr
->flags
.hitPart
== WSDecrementLine
) {
870 sPtr
->timerID
= WMAddTimerHandler(AUTOSCROLL_INITIAL_DELAY
,
877 if (sPtr
->flags
.draggingKnob
) {
879 (*sPtr
->action
)(sPtr
, sPtr
->clientData
);
880 WMPostNotificationName(WMScrollerDidScrollNotification
, sPtr
,
885 WMDeleteTimerHandler(sPtr
->timerID
);
886 sPtr
->timerID
= NULL
;
888 sPtr
->flags
.incrDown
= 0;
889 sPtr
->flags
.decrDown
= 0;
890 sPtr
->flags
.draggingKnob
= 0;
894 handleMotion(sPtr
, event
->xbutton
.x
, event
->xbutton
.y
);
895 if (sPtr
->timerID
&& sPtr
->flags
.hitPart
!= WSIncrementLine
896 && sPtr
->flags
.hitPart
!= WSDecrementLine
) {
897 WMDeleteTimerHandler(sPtr
->timerID
);
898 sPtr
->timerID
= NULL
;
902 if (id
!= sPtr
->flags
.incrDown
|| dd
!= sPtr
->flags
.decrDown
)
909 destroyScroller(Scroller
*sPtr
)
911 /* we don't want autoscroll try to scroll a freed widget */
913 WMDeleteTimerHandler(sPtr
->timerID
);