161550 - Expanding a TreeItem on Mac OS X fires MouseUp-MouseDown in the wrong order
share code that sends fake mouse up events when the widget consumes it while tracking
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/carbon/org/eclipse/swt/widgets/Button.java b/bundles/org.eclipse.swt/Eclipse SWT/carbon/org/eclipse/swt/widgets/Button.java
index 300a4c1..4e6fb67 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/carbon/org/eclipse/swt/widgets/Button.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/carbon/org/eclipse/swt/widgets/Button.java
@@ -15,7 +15,6 @@
 import org.eclipse.swt.internal.carbon.ControlFontStyleRec;
 import org.eclipse.swt.internal.carbon.ControlButtonContentInfo;
 import org.eclipse.swt.internal.carbon.Rect;
-import org.eclipse.swt.internal.carbon.CGPoint;
 import org.eclipse.swt.internal.carbon.ThemeButtonDrawInfo;
 
 import org.eclipse.swt.*;
@@ -49,7 +48,7 @@
 	String text = "";
 	Image image;
 	int cIcon;
-	boolean isImage, tracking;
+	boolean isImage;
 	
 /**
  * Constructs a new instance of this class given its parent
@@ -440,61 +439,6 @@
 	return OS.eventNotHandledErr;
 }
 
-int kEventMouseDown (int nextHandler, int theEvent, int userData) {
-	int result = super.kEventMouseDown (nextHandler, theEvent, userData);
-	if (result == OS.noErr) return result;
-	/*
-	* Feature in the Macintosh.  Some controls call TrackControl() or
-	* HandleControlClick() to track the mouse.  Unfortunately, mouse move
-	* events and the mouse up events are consumed.  The fix is to call the
-	* default handler and send a fake mouse up when tracking is finished.
-	* 
-	* NOTE: No mouse move events are sent while tracking.  There is no
-	* fix for this at this time.
-	*/
-	display.grabControl = null;
-	display.runDeferredEvents ();
-	tracking = false;
-	result = OS.CallNextEventHandler (nextHandler, theEvent);
-	if (tracking) {
-		org.eclipse.swt.internal.carbon.Point outPt = new org.eclipse.swt.internal.carbon.Point ();
-		OS.GetGlobalMouse (outPt);
-		Rect rect = new Rect ();
-		int window = OS.GetControlOwner (handle);
-		int x, y;
-		if (OS.HIVIEW) {
-			CGPoint pt = new CGPoint ();
-			pt.x = outPt.h;
-			pt.y = outPt.v;
-			OS.HIViewConvertPoint (pt, 0, handle);
-			x = (int) pt.x;
-			y = (int) pt.y;
-			OS.GetWindowBounds (window, (short) OS.kWindowStructureRgn, rect);
-		} else {
-			OS.GetControlBounds (handle, rect);
-			x = outPt.h - rect.left;
-			y = outPt.v - rect.top;
-			OS.GetWindowBounds (window, (short) OS.kWindowContentRgn, rect);
-		}
-		x -= rect.left;
-		y -=  rect.top;
-		short [] button = new short [1];
-		OS.GetEventParameter (theEvent, OS.kEventParamMouseButton, OS.typeMouseButton, null, 2, null, button);
-		int chord = OS.GetCurrentEventButtonState ();
-		int modifiers = OS.GetCurrentEventKeyModifiers ();
-		sendMouseEvent (SWT.MouseUp, button [0], display.clickCount, true, chord, (short)x, (short)y, modifiers);
-	}
-	tracking = false;
-	return result;
-}
-
-int kEventControlTrack (int nextHandler, int theEvent, int userData) {
-	int result = super.kEventControlTrack (nextHandler, theEvent, userData);
-	if (result == OS.noErr) return result;
-	tracking = true;
-	return OS.eventNotHandledErr;
-}
-
 void releaseWidget () {
 	super.releaseWidget ();
 	if (cIcon != 0) {
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/carbon/org/eclipse/swt/widgets/Control.java b/bundles/org.eclipse.swt/Eclipse SWT/carbon/org/eclipse/swt/widgets/Control.java
index 79fed54..cffa38f 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/carbon/org/eclipse/swt/widgets/Control.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/carbon/org/eclipse/swt/widgets/Control.java
@@ -1722,8 +1722,56 @@
 }	
 
 int kEventControlTrack (int nextHandler, int theEvent, int userData) {
-//	if (isEnabledModal ()) sendMouseEvent (SWT.MouseMove, theEvent);
-	return OS.eventNotHandledErr;
+	int result = super.kEventControlTrack (nextHandler, theEvent, userData);
+	if (result == OS.noErr) return result;
+	/*
+	* Feature in the Macintosh.  Some controls call TrackControl() to track
+	* the mouse.  Unfortunately, mouse move events and the mouse up events are
+	* consumed.  The fix is to call the default handler and send a fake mouse up
+	* when tracking is finished if the mouse event was consumed.
+	* 
+	* NOTE: No mouse move events are sent while tracking.  There is no
+	* fix for this at this time.
+	*/
+	display.grabControl = null;
+	display.runDeferredEvents ();
+	int oldChord = OS.GetCurrentEventButtonState ();
+	result = OS.CallNextEventHandler (nextHandler, theEvent);
+	int newChord = OS.GetCurrentEventButtonState ();
+	if (newChord != oldChord) {
+		int [] masks = {OS.kEventClassMouse, OS.kEventMouseUp};
+		int mouseUpEvent = OS.AcquireFirstMatchingEventInQueue (OS.GetCurrentEventQueue (), masks.length, masks, OS.kEventQueueOptionsNone);
+		if (mouseUpEvent != 0) {
+			OS.ReleaseEvent (mouseUpEvent);
+		} else {
+			org.eclipse.swt.internal.carbon.Point outPt = new org.eclipse.swt.internal.carbon.Point ();
+			OS.GetGlobalMouse (outPt);
+			Rect rect = new Rect ();
+			int window = OS.GetControlOwner (handle);
+			int x, y;
+			if (OS.HIVIEW) {
+				CGPoint pt = new CGPoint ();
+				pt.x = outPt.h;
+				pt.y = outPt.v;
+				OS.HIViewConvertPoint (pt, 0, handle);
+				x = (int) pt.x;
+				y = (int) pt.y;
+				OS.GetWindowBounds (window, (short) OS.kWindowStructureRgn, rect);
+			} else {
+				OS.GetControlBounds (handle, rect);
+				x = outPt.h - rect.left;
+				y = outPt.v - rect.top;
+				OS.GetWindowBounds (window, (short) OS.kWindowContentRgn, rect);
+			}
+			x -= rect.left;
+			y -=  rect.top;
+			short [] button = new short [1];
+			OS.GetEventParameter (theEvent, OS.kEventParamMouseButton, OS.typeMouseButton, null, 2, null, button);
+			int modifiers = OS.GetCurrentEventKeyModifiers ();
+			sendMouseEvent (SWT.MouseUp, button [0], display.clickCount, false, newChord, (short)x, (short)y, modifiers);
+		}
+	}
+	return result;
 }
 
 int kEventMouseDown (int nextHandler, int theEvent, int userData) {
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/carbon/org/eclipse/swt/widgets/Slider.java b/bundles/org.eclipse.swt/Eclipse SWT/carbon/org/eclipse/swt/widgets/Slider.java
index 2308e69..e6bb0b4 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/carbon/org/eclipse/swt/widgets/Slider.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/carbon/org/eclipse/swt/widgets/Slider.java
@@ -12,8 +12,6 @@
 
  
 import org.eclipse.swt.internal.carbon.OS;
-import org.eclipse.swt.internal.carbon.Rect;
-import org.eclipse.swt.internal.carbon.CGPoint;
 
 import org.eclipse.swt.*;
 import org.eclipse.swt.events.*;
@@ -68,7 +66,7 @@
  * @see ScrollBar
  */
 public class Slider extends Control {
-	boolean dragging, tracking;
+	boolean dragging;
 	int increment = 1;
 	int pageIncrement = 10;
 
@@ -312,63 +310,16 @@
     return OS.GetControlViewSize (handle);
 }
 
-int kEventControlTrack (int nextHandler, int theEvent, int userData) {
-	int result = super.kEventControlTrack (nextHandler, theEvent, userData);
-	if (result == OS.noErr) return result;
-	tracking = true;
-	return OS.eventNotHandledErr;
-}
-
 int kEventMouseDown (int nextHandler, int theEvent, int userData) {
 	int status = super.kEventMouseDown (nextHandler, theEvent, userData);
 	if (status == OS.noErr) return status;
-	/*
-	* Feature in the Macintosh.  Some controls call TrackControl() or
-	* HandleControlClick() to track the mouse.  Unfortunately, mouse move
-	* events and the mouse up events are consumed.  The fix is to call the
-	* default handler and send a fake mouse up when tracking is finished.
-	* 
-	* NOTE: No mouse move events are sent while tracking.  There is no
-	* fix for this at this time.
-	*/
-	display.grabControl = null;
-	display.runDeferredEvents ();
-	dragging = tracking = false;
+	dragging = false;
 	status = OS.CallNextEventHandler (nextHandler, theEvent);
 	if (dragging) {
 		Event event = new Event ();
 		sendEvent (SWT.Selection, event);
 	}
 	dragging = false;
-	if (tracking) {
-		org.eclipse.swt.internal.carbon.Point outPt = new org.eclipse.swt.internal.carbon.Point ();
-		OS.GetGlobalMouse (outPt);
-		Rect rect = new Rect ();
-		int window = OS.GetControlOwner (handle);
-		int x, y;
-		if (OS.HIVIEW) {
-			CGPoint pt = new CGPoint ();
-			pt.x = outPt.h;
-			pt.y = outPt.v;
-			OS.HIViewConvertPoint (pt, 0, handle);
-			x = (int) pt.x;
-			y = (int) pt.y;
-			OS.GetWindowBounds (window, (short) OS.kWindowStructureRgn, rect);
-		} else {
-			OS.GetControlBounds (handle, rect);
-			x = outPt.h - rect.left;
-			y = outPt.v - rect.top;
-			OS.GetWindowBounds (window, (short) OS.kWindowContentRgn, rect);
-		}
-		x -= rect.left;
-		y -=  rect.top;
-		short [] button = new short [1];
-		OS.GetEventParameter (theEvent, OS.kEventParamMouseButton, OS.typeMouseButton, null, 2, null, button);
-		int chord = OS.GetCurrentEventButtonState ();
-		int modifiers = OS.GetCurrentEventKeyModifiers ();
-		sendMouseEvent (SWT.MouseUp, button [0], display.clickCount, true, chord, (short)x, (short)y, modifiers);
-	}
-	tracking = false;
 	return status;
 }
 
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/carbon/org/eclipse/swt/widgets/Spinner.java b/bundles/org.eclipse.swt/Eclipse SWT/carbon/org/eclipse/swt/widgets/Spinner.java
index 3a84573..64876a3 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/carbon/org/eclipse/swt/widgets/Spinner.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/carbon/org/eclipse/swt/widgets/Spinner.java
@@ -550,6 +550,7 @@
 	int [] mask = new int [] {
 		OS.kEventClassControl, OS.kEventControlDraw,
 		OS.kEventClassControl, OS.kEventControlSetFocusPart,
+		OS.kEventClassControl, OS.kEventControlTrack,
 	};
 	int controlTarget = OS.GetControlEventTarget (textHandle);
 	OS.InstallEventHandler (controlTarget, controlProc, mask.length / 2, mask, handle, null);
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/carbon/org/eclipse/swt/widgets/ToolItem.java b/bundles/org.eclipse.swt/Eclipse SWT/carbon/org/eclipse/swt/widgets/ToolItem.java
index 79c54b7..53661b0 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/carbon/org/eclipse/swt/widgets/ToolItem.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/carbon/org/eclipse/swt/widgets/ToolItem.java
@@ -51,7 +51,7 @@
 	Image hotImage, disabledImage;
 	String toolTipText;
 	Control control;
-	boolean tracking, selection;
+	boolean selection;
 
 	static final int DEFAULT_WIDTH = 24;
 	static final int DEFAULT_HEIGHT = 22;
@@ -765,8 +765,18 @@
 }
 
 int kEventControlTrack (int nextHandler, int theEvent, int userData) {
-	tracking = true;
-	return OS.eventNotHandledErr;
+	int result = parent.kEventControlTrack (nextHandler, theEvent, userData);
+	if (OS.HIVIEW) {
+		partCode = 0;
+		if (text.length () > 0 && labelHandle != 0) {
+			redrawWidget (labelHandle, false);
+		}
+		if (image != null && iconHandle != 0) {
+			OS.SetControlData (iconHandle, OS.kControlEntireControl, OS.kControlIconTransformTag, 2, new short [] {(short) 0});
+			redrawWidget (iconHandle, false);
+		}
+	}
+	return result;
 }
 
 int kEventMouseDown (int nextHandler, int theEvent, int userData) {
@@ -816,59 +826,7 @@
 				postEvent (SWT.Selection, event);
 			}
 		}
-	}
-	/*
-	* Feature in the Macintosh.  Some controls call TrackControl() or
-	* HandleControlClick() to track the mouse.  Unfortunately, mouse move
-	* events and the mouse up events are consumed.  The fix is to call the
-	* default handler and send a fake mouse up when tracking is finished.
-	* 
-	* NOTE: No mouse move events are sent while tracking.  There is no
-	* fix for this at this time.
-	*/
-	display.grabControl = null;
-	display.runDeferredEvents ();
-	tracking = false;
-	result = OS.CallNextEventHandler (nextHandler, theEvent);
-	if (tracking) {
-		if (OS.HIVIEW) {
-			partCode = 0;
-			if (text.length () > 0 && labelHandle != 0) {
-				redrawWidget (labelHandle, false);
-			}
-			if (image != null && iconHandle != 0) {
-				OS.SetControlData (iconHandle, OS.kControlEntireControl, OS.kControlIconTransformTag, 2, new short [] {(short) 0});
-				redrawWidget (iconHandle, false);
-			}
-		}
-		org.eclipse.swt.internal.carbon.Point outPt = new org.eclipse.swt.internal.carbon.Point ();
-		OS.GetGlobalMouse (outPt);
-		Rect rect = new Rect ();
-		int window = OS.GetControlOwner (handle);
-		int x, y;
-		if (OS.HIVIEW) {
-			CGPoint pt = new CGPoint ();
-			pt.x = outPt.h;
-			pt.y = outPt.v;
-			OS.HIViewConvertPoint (pt, 0, parent.handle);
-			x = (int) pt.x;
-			y = (int) pt.y;
-			OS.GetWindowBounds (window, (short) OS.kWindowStructureRgn, rect);
-		} else {
-			OS.GetControlBounds (parent.handle, rect);
-			x = outPt.h - rect.left;
-			y = outPt.v - rect.top;
-			OS.GetWindowBounds (window, (short) OS.kWindowContentRgn, rect);
-		}
-		x -= rect.left;
-		y -=  rect.top;
-		short [] button = new short [1];
-		OS.GetEventParameter (theEvent, OS.kEventParamMouseButton, OS.typeMouseButton, null, 2, null, button);
-		int chord = OS.GetCurrentEventButtonState ();
-		int modifiers = OS.GetCurrentEventKeyModifiers ();
-		parent.sendMouseEvent (SWT.MouseUp, button [0], display.clickCount, true, chord, (short)x, (short)y, modifiers);
-	}
-	tracking = false;
+	}	
 	return result;
 }
 
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/carbon/org/eclipse/swt/widgets/Tree.java b/bundles/org.eclipse.swt/Eclipse SWT/carbon/org/eclipse/swt/widgets/Tree.java
index 759c19f..0a260d3 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/carbon/org/eclipse/swt/widgets/Tree.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/carbon/org/eclipse/swt/widgets/Tree.java
@@ -2394,43 +2394,6 @@
 			}
 		}
 	}
-	/*
-	* Feature in the Macintosh.  Some controls call TrackControl() or
-	* HandleControlClick() to track the mouse.  Unfortunately, mouse move
-	* events and the mouse up events are consumed.  The fix is to call the
-	* default handler and send a fake mouse up when tracking is finished.
-	* 
-	* NOTE: No mouse move events are sent while tracking.  There is no
-	* fix for this at this time.
-	*/
-	if (wasExpanded) {
-		org.eclipse.swt.internal.carbon.Point outPt = new org.eclipse.swt.internal.carbon.Point ();
-		OS.GetGlobalMouse (outPt);
-		Rect rect = new Rect ();
-		int window = OS.GetControlOwner (handle);
-		int x, y;
-		if (OS.HIVIEW) {
-			CGPoint pt = new CGPoint ();
-			pt.x = outPt.h;
-			pt.y = outPt.v;
-			OS.HIViewConvertPoint (pt, 0, handle);
-			x = (int) pt.x;
-			y = (int) pt.y;
-			OS.GetWindowBounds (window, (short) OS.kWindowStructureRgn, rect);
-		} else {
-			OS.GetControlBounds (handle, rect);
-			x = outPt.h - rect.left;
-			y = outPt.v - rect.top;
-			OS.GetWindowBounds (window, (short) OS.kWindowContentRgn, rect);
-		}
-		x -= rect.left;
-		y -=  rect.top;
-		short [] button = new short [1];
-		OS.GetEventParameter (theEvent, OS.kEventParamMouseButton, OS.typeMouseButton, null, 2, null, button);
-		int chord = OS.GetCurrentEventButtonState ();
-		int modifiers = OS.GetCurrentEventKeyModifiers ();
-		sendMouseEvent (SWT.MouseUp, button [0], display.clickCount, true, chord, (short)x, (short)y, modifiers);
-	}
 	wasSelected = wasExpanded = false;
 	return result;
 }