Drop-down mostly working in Cocoa
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/NSCell.java b/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/NSCell.java
index a846080..a8ba599 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/NSCell.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/cocoa/org/eclipse/swt/internal/cocoa/NSCell.java
@@ -36,6 +36,10 @@
 	return result;
 }
 
+public int /*long*/ controlSize() {
+	return OS.objc_msgSend(this.id, OS.sel_controlSize);
+}
+
 public void drawInteriorWithFrame(NSRect cellFrame, NSView controlView) {
 	OS.objc_msgSend(this.id, OS.sel_drawInteriorWithFrame_inView_, cellFrame, controlView != null ? controlView.id : 0);
 }
@@ -115,5 +119,4 @@
 public boolean wraps() {
 	return OS.objc_msgSend_bool(this.id, OS.sel_wraps);
 }
-
 }
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/DateTime.java b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/DateTime.java
index 60715d3..d76261c 100755
--- a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/DateTime.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/DateTime.java
@@ -48,11 +48,11 @@
 	
 	/* Emulated DROP_DOWN calendar fields for DATE */
 	NSButton buttonView;
-	boolean hasFocus;
-	int savedYear, savedMonth, savedDay;
 	Shell popupShell;
-	DateTime popupCalendar, popupOwner;
+	DateTime popupCalendar;
 	Listener popupListener, popupFilter;
+	boolean popupHasFocus;
+	int savedYear, savedMonth, savedDay;
 
 /**
  * Constructs a new instance of this class given its parent
@@ -141,18 +141,17 @@
 public Point computeSize (int wHint, int hHint, boolean changed) {
 	checkWidget ();
 	int width = 0, height = 0;
-	NSControl widget = (NSControl)view; //TODO: Ask SSQ why cast? The call to cell() works fine on view
+	NSControl widget = (NSControl)view;
 	NSSize size = widget.cell ().cellSize ();
 	width = (int)Math.ceil (size.width);
 	height = (int)Math.ceil (size.height);
-	if (width == 0) width = DEFAULT_WIDTH;
-	if (height == 0) height = DEFAULT_HEIGHT;
 	if ((style & SWT.DROP_DOWN) != 0) {
-		widget = (NSControl)buttonView;
-		size = widget.cell ().cellSize ();
-		width += (int)Math.ceil (size.width) - 8;
+		size = buttonView.cell ().cellSize ();
+		width += (int)Math.ceil (size.width) - getBezelSize() * 2;
 		height = Math.max(height, (int)Math.ceil (size.height));
 	}
+	if (width == 0) width = DEFAULT_WIDTH;
+	if (height == 0) height = DEFAULT_HEIGHT;
 	if (wHint != SWT.DEFAULT) width = wHint;
 	if (hHint != SWT.DEFAULT) height = hHint;
 	int border = getBorderWidth ();
@@ -205,7 +204,6 @@
 void createPopupShell(int year, int month, int day) {
 	popupShell = new Shell (getShell (), SWT.NO_TRIM | SWT.ON_TOP);
 	popupCalendar = new DateTime (popupShell, SWT.CALENDAR);
-	popupCalendar.popupOwner = this;
 	if (font != null) popupCalendar.setFont (font);
 
 	popupListener = new Listener () {
@@ -218,12 +216,8 @@
 				popupCalendarEvent (event);
 				return;
 			}
-			if (event.widget == DateTime.this) {
-				dateTimeEvent (event);
-				return;
-			}
 			if (event.widget == getShell ()) {
-				getDisplay().asyncExec(new Runnable() {
+				display.asyncExec(new Runnable() {
 					public void run() {
 						if (isDisposed()) return;
 						popupCalendarFocus (SWT.FocusOut);
@@ -245,44 +239,22 @@
 	for (int i=0; i < listeners.length; i++) {
 		popupShell.addListener (listeners [i], popupListener);
 	}
-	listeners = new int [] {SWT.MouseUp, SWT.Selection, SWT.Traverse, SWT.KeyDown, SWT.KeyUp, SWT.FocusIn, SWT.Dispose};
+	listeners = new int [] {SWT.Selection, SWT.Traverse, SWT.KeyDown, SWT.KeyUp, SWT.FocusIn, SWT.Dispose};
 	for (int i=0; i < listeners.length; i++) {
 		popupCalendar.addListener (listeners [i], popupListener);
 	}
-
-	if (year != -1) popupCalendar.setDate(year, month, day);
-}
-
-void dateTimeEvent (Event event) {
-	switch (event.type) {
-		case SWT.Dispose:
+	addListener (SWT.Dispose, new Listener() {
+		public void handleEvent(Event event) {
 			if (popupShell != null && !popupShell.isDisposed ()) {
-				popupCalendar.removeListener (SWT.Dispose, popupListener);
-				popupShell.dispose ();
+				disposePopupShell();
 			}
 			Shell shell = getShell ();
 			shell.removeListener (SWT.Deactivate, popupListener);
-			Display display = getDisplay ();
 			display.removeFilter (SWT.FocusIn, popupFilter);
-			popupShell = null;  
-			popupCalendar = null; 
-			break;
-		case SWT.FocusIn:
-			Control focusControl = getDisplay ().getFocusControl ();
-			if (focusControl == popupCalendar) return;
-			if (isDropped()) {
-				popupCalendar.setFocus();
-			} else {
-				setFocus();
-			}
-			break;
-		case SWT.Move:
-			dropDownCalendar (false);
-			break;
-//		case SWT.Resize:
-//			internalLayout (false);
-//			break;
-	}
+		}
+	});
+
+	if (year != -1) popupCalendar.setDate(year, month, day);
 }
 
 NSFont defaultNSFont() {
@@ -298,39 +270,26 @@
 
 }
 
-void dropDownCalendar(boolean drop) {
-	if (drop == isDropped ()) return;
-	if (!drop) {
-		popupShell.setVisible (false);
-		if (!isDisposed () && isFocusControl()) {
-			setFocus();
-		}
-		return;
-	}
+void disposePopupShell() {
+	popupCalendar.removeListener (SWT.Dispose, popupListener);
+	popupShell.dispose ();
+	popupShell = null;  
+	popupCalendar = null;
+}
 
+void showCalendar() {
+	if (isDropped ()) return;
 	savedYear = getYear ();
 	savedMonth = getMonth ();
 	savedDay = getDay ();
 	if (getShell() != popupShell.getParent ()) {
-		int year = popupCalendar.getYear ();
-		int month = popupCalendar.getMonth ();
-		int day = popupCalendar.getDay ();
-		popupCalendar.removeListener (SWT.Dispose, popupListener);
-		popupShell.dispose();
-		popupShell = null;
-		popupCalendar = null;
-		createPopupShell (year, month, day);
+		disposePopupShell();
+		createPopupShell (savedYear, savedMonth, savedDay);
 	}
-	
 	Point dateBounds = getSize ();
 	Point calendarSize = popupCalendar.computeSize (SWT.DEFAULT, SWT.DEFAULT, false);
 	popupCalendar.setBounds (1, 1, Math.max (dateBounds.x - 2, calendarSize.x), calendarSize.y);
-	
-	int year = popupCalendar.getYear ();
-	int month = popupCalendar.getMonth ();
-	int day = popupCalendar.getDay ();
-	popupCalendar.setDate(year, month, day);
-	Display display = getDisplay ();
+	popupCalendar.setDate(savedYear, savedMonth, savedDay);
 	Rectangle parentRect = display.map (getParent (), null, getBounds ());
 	Rectangle displayRect = getMonitor ().getClientArea ();
 	int width = Math.max (dateBounds.x, calendarSize.x + 2);
@@ -344,11 +303,34 @@
 	if (isFocusControl()) popupCalendar.setFocus ();
 }
 
+void hideCalendar() {
+	if (!isDropped ()) return;
+	popupShell.setVisible (false);
+	if (!isDisposed () && isFocusControl()) {
+		setFocus();
+	}
+}
+
+int getBezelInset() {
+	//TODO: Determine this value from the system instead of using constants
+	return (buttonView.cell ().controlSize () == OS.NSMiniControlSize) ? 3 : 1;
+}
+
+int getBezelSize() {
+	//TODO: Determine this value from the system instead of using constants
+	return (buttonView.cell ().controlSize () == OS.NSMiniControlSize) ? 6 : 4;
+}
+
 NSCalendarDate getCalendarDate () {
 	NSDate date = ((NSDatePicker)view).dateValue();
 	return date.dateWithCalendarFormat(null, null);
 }
 
+public Control [] getChildren () {
+	checkWidget();
+	return new Control [0];
+}
+
 /**
  * Returns the receiver's date, or day of the month.
  * <p>
@@ -470,6 +452,23 @@
 	return true;
 }
 
+void keyDown(int /*long*/ id, int /*long*/ sel, int /*long*/ theEvent) {
+	if ((style & SWT.DROP_DOWN) != 0) {
+		NSEvent nsEvent = new NSEvent (theEvent);
+		int keyCode = Display.translateKey (nsEvent.keyCode ());
+		boolean alt = (nsEvent.modifierFlags() & OS.NSAlternateKeyMask) != 0;
+		if (alt && (keyCode == SWT.ARROW_UP || keyCode == SWT.ARROW_DOWN)) {
+			if (isDropped ()) {
+				hideCalendar();
+			} else {
+				showCalendar();
+			}
+			return;
+		}
+	}
+	super.keyDown(id, sel, theEvent);
+}
+
 void popupCalendarEvent (Event event) {
 	switch (event.type) {
 		case SWT.Dispose:
@@ -486,11 +485,6 @@
 			popupCalendarFocus (SWT.FocusIn);
 			break;
 		}
-		case SWT.MouseUp: {
-			if (event.button != 1) return;
-			dropDownCalendar (false);
-			break;
-		}
 		case SWT.Selection: {
 			int year = popupCalendar.getYear ();
 			int month = popupCalendar.getMonth ();
@@ -498,25 +492,24 @@
 			setDate(year, month, day);
 			Event e = new Event ();
 			e.time = event.time;
-			e.stateMask = event.stateMask;
-			e.doit = event.doit;
 			notifyListeners (SWT.Selection, e);
-			event.doit = e.doit;
+			hideCalendar();
 			break;
 		}
 		case SWT.Traverse: {
 			switch (event.detail) {
 				case SWT.TRAVERSE_RETURN:
 				case SWT.TRAVERSE_ESCAPE:
+					event.doit = false;
+					break;
 				case SWT.TRAVERSE_ARROW_PREVIOUS:
 				case SWT.TRAVERSE_ARROW_NEXT:
-					event.doit = false;
 					break;
 				case SWT.TRAVERSE_TAB_NEXT:
 				case SWT.TRAVERSE_TAB_PREVIOUS:
-					event.doit = traverse(event.detail);
+					event.doit = traverse(event);
 					event.detail = SWT.TRAVERSE_NONE;
-					if (event.doit) dropDownCalendar (false);
+					if (event.doit) hideCalendar();
 					return;
 				case SWT.TRAVERSE_PAGE_NEXT:
 				case SWT.TRAVERSE_PAGE_PREVIOUS:
@@ -526,8 +519,6 @@
 			e.time = event.time;
 			e.detail = event.detail;
 			e.doit = event.doit;
-			e.character = event.character;
-			e.keyCode = event.keyCode;
 			notifyListeners (SWT.Traverse, e);
 			event.doit = e.doit;
 			event.detail = e.detail;
@@ -546,11 +537,13 @@
 			if (event.character == SWT.ESC) {
 				/* Escape key cancels popupCalendar and reverts date */
 				popupCalendar.setDate (savedYear, savedMonth, savedDay);
-				dropDownCalendar (false);
+				hideCalendar();
+				return;
 			}
 			if (event.keyCode == SWT.CR || (event.stateMask & SWT.ALT) != 0 && (event.keyCode == SWT.ARROW_UP || event.keyCode == SWT.ARROW_DOWN)) {
 				/* Return, Alt+Down, and Alt+Up cancel popupCalendar and select date. */
-				dropDownCalendar (false);
+				hideCalendar();
+				return;
 			}
 			/* At this point the widget may have been disposed.
 			 * If so, do not continue. */
@@ -570,12 +563,11 @@
 	if (isDisposed ()) return;
 	switch (type) {
 		case SWT.FocusIn: {
-			if (hasFocus) return;
-			hasFocus = true;
+			if (popupHasFocus) return;
+			popupHasFocus = true;
 			Shell shell = getShell ();
 			shell.removeListener (SWT.Deactivate, popupListener);
 			shell.addListener (SWT.Deactivate, popupListener);
-			Display display = getDisplay ();
 			display.removeFilter (SWT.FocusIn, popupFilter);
 			display.addFilter (SWT.FocusIn, popupFilter);
 			Event e = new Event ();
@@ -583,13 +575,12 @@
 			break;
 		}
 		case SWT.FocusOut: {
-			if (!hasFocus) return;
-			Control focusControl = getDisplay ().getFocusControl ();
+			if (!popupHasFocus) return;
+			Control focusControl = display.getFocusControl ();
 			if (focusControl == popupCalendar || focusControl == this) return;
-			hasFocus = false;
+			popupHasFocus = false;
 			Shell shell = getShell ();
 			shell.removeListener(SWT.Deactivate, popupListener);
-			Display display = getDisplay ();
 			display.removeFilter (SWT.FocusIn, popupFilter);
 			Event e = new Event ();
 			notifyListeners (SWT.FocusOut, e);
@@ -603,19 +594,16 @@
 		case SWT.Paint:
 			/* Draw black rectangle around popupCalendar */
 			Rectangle bounds = popupCalendar.getBounds();
-			Color black = getDisplay().getSystemColor(SWT.COLOR_BLACK);
+			Color black = display.getSystemColor(SWT.COLOR_BLACK);
 			event.gc.setForeground(black);
 			event.gc.drawRectangle(0, 0, bounds.width + 1, bounds.height + 1);
 			break;
 		case SWT.Close:
 			event.doit = false;
-			dropDownCalendar (false);
+			hideCalendar();
 			break;
 		case SWT.Deactivate:
-//			Point point = down.toControl(getDisplay().getCursorLocation());
-//			Point size = down.getSize();
-//			Rectangle rect = new Rectangle(0, 0, size.x, size.y);
-//			if (!rect.contains(point)) dropDownCalendar (false);
+			hideCalendar();
 			break;
 	}
 }
@@ -664,8 +652,8 @@
 	if (buttonView == null) return;
 	NSSize buttonSize = buttonView.cell ().cellSize ();
 	NSRect rect = view.bounds();
-	rect.x = rect.width - buttonSize.width + 4;
-	rect.y = -1;
+	rect.x = rect.width - buttonSize.width + getBezelSize();
+	rect.y = - getBezelInset();
 	rect.width = buttonSize.width;
 	rect.height = buttonSize.height;
 	buttonView.setFrame(rect);
@@ -675,8 +663,13 @@
 	postEvent (SWT.Selection);
 }
 
+/* Drop-down arrow button has been pressed. */
 void sendVerticalSelection () {
-	dropDownCalendar (!isDropped());
+	if (isDropped ()) {
+		hideCalendar();
+	} else {
+		showCalendar();
+	}
 }
 
 void setBackground (float /*double*/ [] color) {