Index: NSScroller.m
===================================================================
RCS file: /cvsroot/gnustep/gnustep/core/gui/Source/NSScroller.m,v
retrieving revision 1.67
diff -u -r1.67 NSScroller.m
--- NSScroller.m	30 Mar 2003 17:24:47 -0000	1.67
+++ NSScroller.m	7 Apr 2003 05:58:53 -0000
@@ -243,7 +243,7 @@
   [upCell setImagePosition: NSImageOnly];
   [upCell setContinuous: YES];
   [upCell sendActionOn: (NSLeftMouseDownMask | NSPeriodicMask)];
-  [upCell setPeriodicDelay: 0.3 interval: 0.04];
+  [upCell setPeriodicDelay: 0.3 interval: 0.03];
 
   downCell = [NSButtonCell new];
   [downCell setHighlightsBy: NSChangeBackgroundCellMask|NSContentsCellMask];
@@ -252,7 +252,7 @@
   [downCell setImagePosition: NSImageOnly];
   [downCell setContinuous: YES];
   [downCell sendActionOn: (NSLeftMouseDownMask | NSPeriodicMask)];
-  [downCell setPeriodicDelay: 0.3 interval: 0.04];
+  [downCell setPeriodicDelay: 0.3 interval: 0.03];
 
   leftCell = [NSButtonCell new];
   [leftCell setHighlightsBy: NSChangeBackgroundCellMask|NSContentsCellMask];
@@ -261,7 +261,7 @@
   [leftCell setImagePosition: NSImageOnly];
   [leftCell setContinuous: YES];
   [leftCell sendActionOn: (NSLeftMouseDownMask | NSPeriodicMask)];
-  [leftCell setPeriodicDelay: 0.3 interval: 0.04];
+  [leftCell setPeriodicDelay: 0.3 interval: 0.03];
 
   rightCell = [NSButtonCell new];
   [rightCell setHighlightsBy: NSChangeBackgroundCellMask|NSContentsCellMask];
@@ -270,7 +270,7 @@
   [rightCell setImagePosition: NSImageOnly];
   [rightCell setContinuous: YES];
   [rightCell sendActionOn: (NSLeftMouseDownMask | NSPeriodicMask)];
-  [rightCell setPeriodicDelay: 0.3 interval: 0.04];
+  [rightCell setPeriodicDelay: 0.3 interval: 0.03];
 
   knobCell = [NSButtonCell new];
   [knobCell setButtonType: NSMomentaryChangeButton];
@@ -583,16 +583,14 @@
 - (void) trackKnob: (NSEvent*)theEvent
 {
   unsigned int eventMask = NSLeftMouseDownMask | NSLeftMouseUpMask
-			  | NSLeftMouseDraggedMask | NSMouseMovedMask
-			  | NSPeriodicMask;
+			  | NSLeftMouseDraggedMask | NSFlagsChangedMask;
   NSPoint	point;
   NSPoint	apoint;
   float		lastPosition;
   float		newPosition;
   float		floatValue;
   float		offset;
-  NSDate	*theDistantFuture = [NSDate distantFuture];
-  NSEventType	eventType;
+  NSEventType	eventType = [theEvent type];
   NSRect	knobRect;
   unsigned	flags = [theEvent modifierFlags];
 
@@ -612,137 +610,146 @@
     }
 
   _hitPart = NSScrollerKnob;
-  /*
-   * set periodic events rate to achieve max of ~30fps
-   */
-  [NSEvent startPeriodicEventsAfterDelay: 0.02 withPeriod: 0.03];
-  [[NSRunLoop currentRunLoop] limitDateForMode: NSEventTrackingRunLoopMode];
 
-  while ((eventType = [theEvent type]) != NSLeftMouseUp)
+  do
     {
-      CREATE_AUTORELEASE_POOL(arp);
-      if (eventType != NSPeriodic)
-	{
-	  apoint = [theEvent locationInWindow];
-	  flags = [theEvent modifierFlags];
-	}
-      else
-	{
-	  point = [self convertPoint: apoint fromView: nil];
-          if (_isHorizontal)
-	    newPosition = point.x + offset;
-          else
-	    newPosition = point.y + offset;
-
-          if (newPosition != lastPosition)
-            {
-              if (flags & NSAlternateKeyMask)
-	        {
-	          float	diff;
-
-	          diff = newPosition - lastPosition;
-	          diff = diff * 3 / 4;
-	          offset -= diff;
-	          newPosition -= diff;
-	        }
-
-              // only one coordinate (X or Y) is used to compute floatValue.
-              point = NSMakePoint(newPosition, newPosition);
-	      floatValue = [self _floatValueForMousePoint: point];
-
-	      if (floatValue != _floatValue)
-		{
-		  [self setFloatValue: floatValue];
-		  [self sendAction: _action to: _target];
-		}
+       /* Inner loop that gets and (quickly) handles all events that have
+          already arrived. */
+       while (theEvent && eventType != NSLeftMouseUp)
+         {
+	   switch (eventType)
+             {
+	       case NSLeftMouseDown:
+	       case NSLeftMouseDragged:
+       	         point = [self convertPoint: [theEvent locationInWindow] 
+			   fromView: nil];
+		 break;
+	       case NSFlagsChanged:
+		 flags = [theEvent modifierFlags];
+		 break;
+	       default:
+		 NSDebugLog(@"NSScroller: unhandled event");
+             }
+
+           /* Note the event here. Don't do any expensive handling. */
+
+           theEvent = [NSApp nextEventMatchingMask: eventMask
+                         untilDate: [NSDate distantPast] /* Only get events that have already arrived. */
+                         inMode: NSEventTrackingRunLoopMode
+                         dequeue: YES];
+	   eventType = [theEvent type];
+         }
+
+       if (eventType == NSLeftMouseUp)
+         break;
+
+   /* No more events right now. Do expensive handling, like drawing, here. */
+
+       if (_isHorizontal)
+         newPosition = point.x + offset;
+       else
+	 newPosition = point.y + offset;
+
+       if (newPosition != lastPosition)
+         {
+           if (flags & NSAlternateKeyMask)
+	     {
+	       float	diff;
+
+	       diff = newPosition - lastPosition;
+	       diff = diff * 3 / 4;
+	       offset -= diff;
+	       newPosition -= diff;
+	     }
+
+           // only one coordinate (X or Y) is used to compute floatValue.
+           point = NSMakePoint(newPosition, newPosition);
+	   floatValue = [self _floatValueForMousePoint: point];
+
+	   if (floatValue != _floatValue)
+	     {
+	       [self setFloatValue: floatValue];
+	       [self sendAction: _action to: _target];
+	     }
 	      
-	      lastPosition = newPosition;
-            }
-	}
+	     lastPosition = newPosition;
+         }
 
-      theEvent = [NSApp nextEventMatchingMask: eventMask
-				    untilDate: theDistantFuture
-				       inMode: NSEventTrackingRunLoopMode
-				      dequeue: YES];
-      DESTROY(arp);
-    }
-  [NSEvent stopPeriodicEvents];
+       /* Get the next event, blocking if necessary. */
+       theEvent = [NSApp nextEventMatchingMask: eventMask
+                     untilDate: nil /* No limit, block until we get an event. */
+                     inMode: NSEventTrackingRunLoopMode
+                     dequeue: YES];
+       eventType = [theEvent type];
+  } while (eventType != NSLeftMouseUp);
 }
 
 - (void) trackScrollButtons: (NSEvent*)theEvent
 {
-  NSApplication	*theApp = [NSApplication sharedApplication];
-  unsigned int	eventMask = NSLeftMouseDownMask | NSLeftMouseUpMask |
-			  NSLeftMouseDraggedMask | NSMouseMovedMask;
-  BOOL		shouldReturn = NO;
   id		theCell = nil;
   NSRect	rect;
 
   [self lockFocus];
 
   NSDebugLog (@"trackScrollButtons");
-  do
-    {
-      _hitPart = [self testPart: [theEvent locationInWindow]];
-      rect = [self rectForPart: _hitPart];
 
-      /*
-       * A hit on a scroller button should be a page movement
-       * if the alt key is pressed.
-       */
-      switch (_hitPart)
-	{
-	  case NSScrollerIncrementLine:
-	    if ([theEvent modifierFlags] & NSAlternateKeyMask)
-	      {
-		_hitPart = NSScrollerIncrementPage;
-	      }
-	    /* Fall through to next case */
-	  case NSScrollerIncrementPage:
-	    theCell = (_isHorizontal ? rightCell : downCell);
-	    break;
+  _hitPart = [self testPart: [theEvent locationInWindow]];
+  rect = [self rectForPart: _hitPart];
 
-	  case NSScrollerDecrementLine:
-	    if ([theEvent modifierFlags] & NSAlternateKeyMask)
-	      {
-		_hitPart = NSScrollerDecrementPage;
-	      }
-	    /* Fall through to next case */
-	  case NSScrollerDecrementPage:
-	    theCell = (_isHorizontal ? leftCell : upCell);
-	    break;
-
-	  default:
-	    theCell = nil;
-	    break;
-	}
+  /*
+   * A hit on a scroller button should be a page movement
+   * if the alt key is pressed.
+   */
+  switch (_hitPart)
+    {
+      case NSScrollerIncrementLine:
+        if ([theEvent modifierFlags] & NSAlternateKeyMask)
+	  {
+	    _hitPart = NSScrollerIncrementPage;
+	  }
+	/* Fall through to next case */
+      case NSScrollerIncrementPage:
+	theCell = (_isHorizontal ? rightCell : downCell);
+	break;
 
-      if (theCell)
-	{
-	  [theCell highlight: YES withFrame: rect inView: self];
-	  [_window flushWindow];
+      case NSScrollerDecrementLine:
+	if ([theEvent modifierFlags] & NSAlternateKeyMask)
+	  {
+	    _hitPart = NSScrollerDecrementPage;
+	  }
+	/* Fall through to next case */
+      case NSScrollerDecrementPage:
+	theCell = (_isHorizontal ? leftCell : upCell);
+	break;
 
-	  NSDebugLog (@"tracking cell %x", theCell);
+      default:
+	theCell = nil;
+	break;
+    }
 
-	  shouldReturn = [theCell trackMouse: theEvent
-				      inRect: rect
-				      ofView: self
-				untilMouseUp: YES];
+  /*
+   * If we don't find a cell this has been all for naught, but we 
+   * shouldn't ever be in that situation.
+   */
+  if (theCell)
+    {
+      [theCell highlight: YES withFrame: rect inView: self];
+      [_window flushWindow];
 
-	  [theCell highlight: NO withFrame: rect inView: self];
-	  [_window flushWindow];
-	}
+      NSDebugLog (@"tracking cell %x", theCell);
 
-      if (shouldReturn)
-	break;
+      /*
+       * The "tracking" in this method actually takes place within 
+       * NSCell's trackMouse: method. 
+       */
+      [theCell trackMouse: theEvent
+		   inRect: rect
+		   ofView: self
+	     untilMouseUp: YES];
 
-      theEvent = [theApp nextEventMatchingMask: eventMask
-				     untilDate: [NSDate distantFuture]
-					inMode: NSEventTrackingRunLoopMode
-				       dequeue: YES];
+      [theCell highlight: NO withFrame: rect inView: self];
+      [_window flushWindow];
     }
-  while ([theEvent type] != NSLeftMouseUp);
-
   [self unlockFocus];
 
   NSDebugLog (@"return from trackScrollButtons");
