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
) {
314 #ifndef DOUBLE_BUFFER
315 XFillRectangle(scr
->display
, d
, gc
,
316 ofs
+1, 2+1, BUTTON_SIZE
+1-3, BUTTON_SIZE
-3);
318 if ((!part
&&sPtr
->flags
.decrDown
) || (part
&&sPtr
->flags
.incrDown
))
319 XFillRectangle(scr
->display
, d
, WMColorGC(scr
->white
),
320 ofs
+1, 2+1, BUTTON_SIZE
+1-3, BUTTON_SIZE
-3);
321 #endif /* DOUBLE_BUFFER */
322 W_DrawRelief(scr
, d
, ofs
, 2, BUTTON_SIZE
, BUTTON_SIZE
, WRRaised
);
325 XSetClipMask(scr
->display
, scr
->clipGC
, arrow
->mask
);
326 XSetClipOrigin(scr
->display
, scr
->clipGC
,
327 ofs
+ (BUTTON_SIZE
- arrow
->width
) / 2,
328 2 + (BUTTON_SIZE
- arrow
->height
) / 2);
330 XCopyArea(scr
->display
, arrow
->pixmap
, d
, scr
->clipGC
,
331 0, 0, arrow
->width
, arrow
->height
,
332 ofs
+ (BUTTON_SIZE
- arrow
->width
) / 2,
333 2 + (BUTTON_SIZE
- arrow
->height
) / 2);
335 } else { /* vertical */
338 #ifndef DOUBLE_BUFFER
339 XFillRectangle(scr
->display
, d
, gc
,
340 2+1, ofs
+1, BUTTON_SIZE
-3, BUTTON_SIZE
+1-3);
342 if ((!part
&&sPtr
->flags
.decrDown
) || (part
&&sPtr
->flags
.incrDown
))
343 XFillRectangle(scr
->display
, d
, WMColorGC(scr
->white
),
344 2+1, ofs
+1, BUTTON_SIZE
-3, BUTTON_SIZE
+1-3);
345 #endif /* DOUBLE_BUFFER */
346 W_DrawRelief(scr
, d
, 2, ofs
, BUTTON_SIZE
, BUTTON_SIZE
, WRRaised
);
350 XSetClipMask(scr
->display
, scr
->clipGC
, arrow
->mask
);
351 XSetClipOrigin(scr
->display
, scr
->clipGC
,
352 2 + (BUTTON_SIZE
- arrow
->width
) / 2,
353 ofs
+ (BUTTON_SIZE
- arrow
->height
) / 2);
354 XCopyArea(scr
->display
, arrow
->pixmap
, d
, scr
->clipGC
,
355 0, 0, arrow
->width
, arrow
->height
,
356 2 + (BUTTON_SIZE
- arrow
->width
) / 2,
357 ofs
+ (BUTTON_SIZE
- arrow
->height
) / 2);
363 knobLength(Scroller
*sPtr
)
368 if (sPtr
->flags
.horizontal
)
369 length
= sPtr
->view
->size
.width
- 4;
371 length
= sPtr
->view
->size
.height
- 4;
373 if (sPtr
->flags
.arrowsPosition
!= WSANone
) {
374 length
-= 2*(BUTTON_SIZE
+1);
377 tmp
= (int)((float)length
* sPtr
->knobProportion
+ 0.5);
378 /* keep minimum size */
379 if (tmp
< BUTTON_SIZE
)
387 paintScroller(Scroller
*sPtr
)
389 WMView
*view
= sPtr
->view
;
390 WMScreen
*scr
= view
->screen
;
394 Drawable d
= view
->window
;
401 d
= XCreatePixmap(scr
->display
, view
->window
, view
->size
.width
,
402 view
->size
.height
, scr
->depth
);
403 XFillRectangle(scr
->display
, d
, WMColorGC(scr
->gray
), 0, 0,
404 view
->size
.width
, view
->size
.height
);
407 XDrawRectangle(scr
->display
, d
, WMColorGC(scr
->black
), 0, 0,
408 view
->size
.width
-1, view
->size
.height
-1);
409 #ifndef DOUBLE_BUFFER
410 XDrawRectangle(scr
->display
, d
, WMColorGC(scr
->gray
), 1, 1,
411 view
->size
.width
-3, view
->size
.height
-3);
414 if (sPtr
->flags
.horizontal
)
415 length
= view
->size
.width
- 4;
417 length
= view
->size
.height
- 4;
419 if (sPtr
->flags
.documentFullyVisible
) {
420 XFillRectangle(scr
->display
, d
, scr
->stippleGC
, 2, 2,
421 view
->size
.width
-4, view
->size
.height
-4);
424 if (sPtr
->flags
.arrowsPosition
==WSAMaxEnd
) {
425 length
-= (BUTTON_SIZE
+1)*2;
426 } else if (sPtr
->flags
.arrowsPosition
==WSAMinEnd
) {
427 ofs
+= (BUTTON_SIZE
+1)*2;
428 length
-= (BUTTON_SIZE
+1)*2;
431 knobL
= (float)knobLength(sPtr
);
433 knobP
= sPtr
->floatValue
* ((float)length
- knobL
);
435 if (sPtr
->flags
.horizontal
) {
437 XFillRectangle(scr
->display
, d
, scr
->stippleGC
,
438 ofs
, 2, (int)knobP
, view
->size
.height
-4);
441 #ifndef DOUBLE_BUFFER
442 XFillRectangle(scr
->display
, d
, scr
->lightGC
,
443 ofs
+(int)knobP
+2, 2+2, (int)knobL
-4,
444 view
->size
.height
-4-4);
446 W_DrawRelief(scr
, d
, ofs
+(int)knobP
, 2, (int)knobL
,
447 view
->size
.height
-4, WRRaised
);
449 XCopyArea(scr
->display
, scr
->scrollerDimple
->pixmap
, d
,
451 scr
->scrollerDimple
->width
, scr
->scrollerDimple
->height
,
452 ofs
+(int)knobP
+((int)knobL
-scr
->scrollerDimple
->width
-1)/2,
453 (view
->size
.height
-scr
->scrollerDimple
->height
-1)/2);
456 if ((int)(knobP
+knobL
) < length
)
457 XFillRectangle(scr
->display
, d
, scr
->stippleGC
,
458 ofs
+(int)(knobP
+knobL
), 2,
459 length
-(int)(knobP
+knobL
),
460 view
->size
.height
-4);
464 XFillRectangle(scr
->display
, d
, scr
->stippleGC
,
465 2, ofs
, view
->size
.width
-4, (int)knobP
);
468 #ifndef DOUBLE_BUFFER
469 XFillRectangle(scr
->display
, d
, scr
->lightGC
,
470 2+2, ofs
+(int)knobP
+2,
471 view
->size
.width
-4-4, (int)knobL
-4);
473 XCopyArea(scr
->display
, scr
->scrollerDimple
->pixmap
, d
,
475 scr
->scrollerDimple
->width
, scr
->scrollerDimple
->height
,
476 (view
->size
.width
-scr
->scrollerDimple
->width
-1)/2,
477 ofs
+(int)knobP
+((int)knobL
-scr
->scrollerDimple
->height
-1)/2);
479 W_DrawRelief(scr
, d
, 2, ofs
+(int)knobP
,
480 view
->size
.width
-4, (int)knobL
, WRRaised
);
483 if ((int)(knobP
+knobL
) < length
)
484 XFillRectangle(scr
->display
, d
, scr
->stippleGC
,
485 2, ofs
+(int)(knobP
+knobL
),
487 length
-(int)(knobP
+knobL
));
490 if (sPtr
->flags
.arrowsPosition
!= WSANone
) {
491 paintArrow(sPtr
, d
, 0);
492 paintArrow(sPtr
, d
, 1);
497 XCopyArea(scr
->display
, d
, view
->window
, scr
->copyGC
, 0, 0,
498 view
->size
.width
, view
->size
.height
, 0, 0);
499 XFreePixmap(scr
->display
, d
);
506 handleEvents(XEvent
*event
, void *data
)
508 Scroller
*sPtr
= (Scroller
*)data
;
510 CHECK_CLASS(data
, WC_Scroller
);
513 switch (event
->type
) {
515 if (event
->xexpose
.count
==0)
520 destroyScroller(sPtr
);
528 * locatePointInScroller-
529 * Return the part of the scroller where the point is located.
531 static WMScrollerPart
532 locatePointInScroller(Scroller
*sPtr
, int x
, int y
, int alternate
)
534 int width
= sPtr
->view
->size
.width
;
535 int height
= sPtr
->view
->size
.height
;
536 int c
, p1
, p2
, p3
, p4
, p5
, p6
;
540 /* if there is no knob... */
541 if (sPtr
->flags
.documentFullyVisible
)
544 if (sPtr
->flags
.horizontal
)
550 * | | |###########| |#####| | |
551 * | < | > |###########| O |#####| < | > |
552 * | | |###########| |#####| | |
555 if (sPtr
->flags
.arrowsPosition
== WSAMinEnd
) {
559 if (sPtr
->flags
.horizontal
) {
567 } else if (sPtr
->flags
.arrowsPosition
== WSAMaxEnd
) {
568 if (sPtr
->flags
.horizontal
) {
582 if (sPtr
->flags
.horizontal
) {
583 slotL
= p5
= p6
= width
;
585 slotL
= p5
= p6
= height
;
589 knobL
= knobLength(sPtr
);
590 p3
= p2
+ (int)((float)(slotL
-knobL
) * sPtr
->floatValue
);
593 /* uses a mix of the NS and Win ways of doing scroll page */
595 return alternate
? WSDecrementPage
: WSDecrementLine
;
597 return alternate
? WSIncrementPage
: WSIncrementLine
;
599 return WSDecrementPage
;
603 return WSIncrementPage
;
605 return alternate
? WSDecrementPage
: WSDecrementLine
;
607 return alternate
? WSIncrementPage
: WSIncrementLine
;
613 handlePush(Scroller
*sPtr
, int pushX
, int pushY
, int alternate
)
618 part
= locatePointInScroller(sPtr
, pushX
, pushY
, alternate
);
620 sPtr
->flags
.hitPart
= part
;
623 case WSIncrementLine
:
624 sPtr
->flags
.incrDown
= 1;
628 case WSIncrementPage
:
632 case WSDecrementLine
:
633 sPtr
->flags
.decrDown
= 1;
637 case WSDecrementPage
:
642 sPtr
->flags
.draggingKnob
= 1;
643 #ifndef STRICT_NEXT_BEHAVIOUR
644 if (sPtr
->flags
.horizontal
)
645 sPtr
->dragPoint
= pushX
;
647 sPtr
->dragPoint
= pushY
;
653 if (sPtr
->flags
.arrowsPosition
!= WSANone
)
654 buttonsLen
= 2*(BUTTON_SIZE
+1);
658 if (sPtr
->flags
.horizontal
)
659 length
= sPtr
->view
->size
.width
- 4 - buttonsLen
;
661 length
= sPtr
->view
->size
.height
- 4 - buttonsLen
;
663 knobP
= (int)(sPtr
->floatValue
* (float)(length
-knobLength(sPtr
)));
665 if (sPtr
->flags
.arrowsPosition
== WSAMinEnd
)
666 sPtr
->dragPoint
-= 2 + buttonsLen
+ knobP
;
668 sPtr
->dragPoint
-= 2 + knobP
;
670 #endif /* STRICT_NEXT_BEHAVIOUR */
671 /* This does not seem necesary here since we don't know yet if the
672 * knob will be dragged later. -Dan
673 handleMotion(sPtr, pushX, pushY); */
682 if (doAction
&& sPtr
->action
) {
683 (*sPtr
->action
)(sPtr
, sPtr
->clientData
);
685 WMPostNotificationName(WMScrollerDidScrollNotification
, sPtr
, NULL
);
691 floatValueForPoint(Scroller
*sPtr
, int point
)
693 float floatValue
= 0;
695 int slotOfs
, slotLength
, knobL
;
697 if (sPtr
->flags
.horizontal
)
698 slotLength
= sPtr
->view
->size
.width
- 4;
700 slotLength
= sPtr
->view
->size
.height
- 4;
703 if (sPtr
->flags
.arrowsPosition
==WSAMaxEnd
) {
704 slotLength
-= (BUTTON_SIZE
+1)*2;
705 } else if (sPtr
->flags
.arrowsPosition
==WSAMinEnd
) {
706 slotOfs
+= (BUTTON_SIZE
+1)*2;
707 slotLength
-= (BUTTON_SIZE
+1)*2;
710 knobL
= (float)knobLength(sPtr
);
711 #ifdef STRICT_NEXT_BEHAVIOUR
712 if (point
< slotOfs
+ knobL
/2)
713 position
= (float)(slotOfs
+ knobL
/2);
714 else if (point
> slotOfs
+ slotLength
- knobL
/2)
715 position
= (float)(slotOfs
+ slotLength
- knobL
/2);
717 position
= (float)point
;
719 floatValue
= (position
-(float)(slotOfs
+slotLength
/2))
720 /(float)(slotLength
-knobL
);
722 /* Adjust the last point to lie inside the knob slot */
724 position
= (float)slotOfs
;
725 else if (point
> slotOfs
+ slotLength
)
726 position
= (float)(slotOfs
+ slotLength
);
728 position
= (float)point
;
730 /* Compute the float value */
731 floatValue
= (position
-(float)slotOfs
) / (float)(slotLength
-knobL
);
734 assert(!isnan(floatValue
));
740 handleMotion(Scroller
*sPtr
, int mouseX
, int mouseY
)
742 if (sPtr
->flags
.draggingKnob
) {
746 if (sPtr
->flags
.horizontal
) {
752 #ifndef STRICT_NEXT_BEHAVIOUR
753 point
-= sPtr
->dragPoint
;
756 newFloatValue
= floatValueForPoint(sPtr
, point
);
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
;
801 int wheelDecrement
, wheelIncrement
;
805 /* check if we're really dealing with a scroller, as something
806 * might have gone wrong in the event dispatching stuff */
807 CHECK_CLASS(sPtr
, WC_Scroller
);
809 id
= sPtr
->flags
.incrDown
;
810 dd
= sPtr
->flags
.decrDown
;
812 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
)
830 if (sPtr
->flags
.horizontal
) {
831 wheelDecrement
= WINGsConfiguration
.mouseWheelDown
;
832 wheelIncrement
= WINGsConfiguration
.mouseWheelUp
;
834 wheelDecrement
= WINGsConfiguration
.mouseWheelUp
;
835 wheelIncrement
= WINGsConfiguration
.mouseWheelDown
;
838 if (event
->xbutton
.button
== wheelDecrement
) {
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
== wheelIncrement
) {
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
);