/*******************************************************************************
 * Copyright (c) 2000, 2017 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Stefan Xenos (Google) - bug 468854 - Add a requestLayout method to Control
 *******************************************************************************/
package org.eclipse.swt.widgets;

import org.eclipse.swt.*;
import org.eclipse.swt.accessibility.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.internal.*;
import org.eclipse.swt.internal.cocoa.*;

/**
 * Control is the abstract superclass of all windowed user interface classes.
 * <p>
 * <dl>
 * <dt><b>Styles:</b>
 * <dd>BORDER</dd>
 * <dd>LEFT_TO_RIGHT, RIGHT_TO_LEFT, FLIP_TEXT_DIRECTION</dd>
 * <dt><b>Events:</b>
 * <dd>DragDetect, FocusIn, FocusOut, Help, KeyDown, KeyUp, MenuDetect, MouseDoubleClick, MouseDown, MouseEnter,
 *     MouseExit, MouseHover, MouseUp, MouseMove, MouseWheel, MouseHorizontalWheel, MouseVerticalWheel, Move,
 *     Paint, Resize, Traverse</dd>
 * </dl>
 * </p><p>
 * Only one of LEFT_TO_RIGHT or RIGHT_TO_LEFT may be specified.
 * </p><p>
 * IMPORTANT: This class is intended to be subclassed <em>only</em>
 * within the SWT implementation.
 * </p>
 *
 * @see <a href="http://www.eclipse.org/swt/snippets/#control">Control snippets</a>
 * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
 * @noextend This class is not intended to be subclassed by clients.
 */
public abstract class Control extends Widget implements Drawable {
	/**
	 * the handle to the OS resource
	 * (Warning: This field is platform dependent)
	 * <p>
	 * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
	 * public API. It is marked public only so that it can be shared
	 * within the packages provided by SWT. It is not available on all
	 * platforms and should never be accessed from application code.
	 * </p>
	 *
	 * @noreference This field is not intended to be referenced by clients.
	 */
	public NSView view;
	Composite parent;
	String toolTipText;
	Object layoutData;
	int drawCount, backgroundAlpha = 255;
	Menu menu;
	double /*float*/ [] foreground, background;
	Image backgroundImage;
	Font font;
	Cursor cursor;
	Region region;
	NSBezierPath regionPath;
	long /*int*/ visibleRgn;
	Accessible accessible;
	boolean ignorePaint;
	boolean touchEnabled;

	final static int CLIPPING = 1 << 10;
	final static int VISIBLE_REGION = 1 << 12;

	/**
	 * Magic number comes from experience. There's no API for this value in Cocoa or Carbon.
	 */
	static final int DEFAULT_DRAG_HYSTERESIS = 5;

Control () {
	/* Do nothing */
}

/**
 * Constructs a new instance of this class given its parent
 * and a style value describing its behavior and appearance.
 * <p>
 * The style value is either one of the style constants defined in
 * class <code>SWT</code> which is applicable to instances of this
 * class, or must be built by <em>bitwise OR</em>'ing together
 * (that is, using the <code>int</code> "|" operator) two or more
 * of those <code>SWT</code> style constants. The class description
 * lists the style constants that are applicable to the class.
 * Style bits are also inherited from superclasses.
 * </p>
 *
 * @param parent a composite control which will be the parent of the new instance (cannot be null)
 * @param style the style of control to construct
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
 *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
 * </ul>
 *
 * @see SWT#BORDER
 * @see SWT#LEFT_TO_RIGHT
 * @see SWT#RIGHT_TO_LEFT
 * @see Widget#checkSubclass
 * @see Widget#getStyle
 */
public Control (Composite parent, int style) {
	super (parent, style);
	this.parent = parent;
	createWidget ();
}

@Override
boolean acceptsFirstMouse (long /*int*/ id, long /*int*/ sel, long /*int*/ theEvent) {
	Shell shell = getShell ();
	if ((shell.style & SWT.ON_TOP) != 0) return true;
	return super.acceptsFirstMouse (id, sel, theEvent);
}

@Override
long /*int*/ accessibleHandle() {
	long /*int*/ returnValue = view.id;

	if (view instanceof NSControl) {
		if (((NSControl) view).cell() != null) {
			returnValue = ((NSControl) view).cell().id;
		}

	}
	return returnValue;
}

@Override
long /*int*/ accessibilityActionDescription(long /*int*/ id, long /*int*/ sel, long /*int*/ arg0) {
	if (id == accessibleHandle() && accessible != null) {
		NSString actionName = new NSString(arg0);
		id returnValue = accessible.internal_accessibilityActionDescription(actionName, ACC.CHILDID_SELF);
		if (returnValue != null) return returnValue.id;
	}
	return super.accessibilityActionDescription(id, sel, arg0);
}

@Override
long /*int*/ accessibilityActionNames(long /*int*/ id, long /*int*/ sel) {
	long /*int*/ returnValue = super.accessibilityActionNames(id, sel);
	if (handleIsAccessible(id)) {
		if (accessible != null) {
			NSArray baseArray = accessible.internal_accessibilityActionNames(ACC.CHILDID_SELF);
			if (baseArray != null) returnValue = baseArray.id;
		}
		if (hooks(SWT.MenuDetect) || (menu != null && !menu.isDisposed())) {
			NSArray baseArray = new NSArray(returnValue);
			NSMutableArray ourNames = NSMutableArray.arrayWithCapacity(baseArray.count() + 1);
			ourNames.addObjectsFromArray(baseArray);
			ourNames.addObject(OS.NSAccessibilityShowMenuAction);
			returnValue = ourNames.id;
		}
	}
	return returnValue;
}

@Override
long /*int*/ accessibilityAttributeNames(long /*int*/ id, long /*int*/ sel) {

	long /*int*/ returnValue = 0;

	if (handleIsAccessible(id) && accessible != null) {
		// See if the accessible is defining the attribute set for the control.
		id value = accessible.internal_accessibilityAttributeNames(ACC.CHILDID_SELF);
		returnValue = (value != null ? value.id : 0);

		// If not, ask Cocoa for the set for this control.
		if (returnValue == 0) returnValue = super.accessibilityAttributeNames(id, sel);

		// Add relationship attributes.
		returnValue = accessible.internal_addRelationAttributes(returnValue);
	}

	// If the SWT accessibility didn't give us anything get the default for the view/cell.
	if (returnValue == 0) returnValue = super.accessibilityAttributeNames(id, sel);

	return returnValue;
}

/**
 * @param id NSView/NSCell that makes up this control. Could be the view itself.
 * @return true if id is something whose accessible properties can be augmented
 * or overridden by the SWT Accessible. false if the Cocoa defaults for the control should
 * be used.
 */
boolean handleIsAccessible(long /*int*/ id) {
	return id == accessibleHandle();
}

@Override
long /*int*/ accessibilityParameterizedAttributeNames(long /*int*/ id, long /*int*/ sel) {

	if (handleIsAccessible(id) && accessible != null) {
		NSArray returnValue = accessible.internal_accessibilityParameterizedAttributeNames(ACC.CHILDID_SELF);
		if (returnValue != null) return returnValue.id;
	}

	return super.accessibilityParameterizedAttributeNames(id, sel);
}

@Override
void accessibilityPerformAction(long /*int*/ id, long /*int*/ sel, long /*int*/ arg0) {
	if (handleIsAccessible(id) && accessible != null) {
		NSString action = new NSString(arg0);
		if (accessible.internal_accessibilityPerformAction(action, ACC.CHILDID_SELF)) return;
	}
	super.accessibilityPerformAction(id, sel, arg0);
}

@Override
long /*int*/ accessibilityFocusedUIElement(long /*int*/ id, long /*int*/ sel) {
	id returnValue = null;

	if (handleIsAccessible(id) && accessible != null) {
		returnValue = accessible.internal_accessibilityFocusedUIElement(ACC.CHILDID_SELF);
	}

	// If we had an accessible and it didn't handle the attribute request, let the
	// superclass handle it.
	if (returnValue == null)
		return super.accessibilityFocusedUIElement(id, sel);
	else
		return returnValue.id;
}

@Override
long /*int*/ accessibilityHitTest(long /*int*/ id, long /*int*/ sel, NSPoint point) {
	id returnValue = null;

	if (handleIsAccessible(id) && accessible != null) {
		returnValue = accessible.internal_accessibilityHitTest(point, ACC.CHILDID_SELF);
	}

	// If we had an accessible and it didn't handle the attribute request, let the
	// superclass handle it.
	if (returnValue == null)
		return super.accessibilityHitTest(id, sel, point);
	else
		return returnValue.id;
}

@Override
long /*int*/ accessibilityAttributeValue(long /*int*/ id, long /*int*/ sel, long /*int*/ arg0) {
	NSString attribute = new NSString(arg0);
	long /*int*/ returnValue = 0;
	id returnObject = null;

	if (handleIsAccessible(id) && accessible != null) {
		returnObject = accessible.internal_accessibilityAttributeValue(attribute, ACC.CHILDID_SELF);
	}

	// If we had an accessible and it didn't handle the attribute request, let the
	// superclass handle it.
	if (returnObject == null) {
		returnValue = super.accessibilityAttributeValue(id, sel, arg0);

		// Feature in Cocoa: SWT doesn't use setToolTip for tooltip support, so if the
		// help attribute was requested return toolTipText.
		if (returnObject == null) {
			if (attribute.isEqualToString(OS.NSAccessibilityHelpAttribute)) {
				if (toolTipText != null) returnValue = NSString.stringWith(toolTipText).id;
			}
		}

	} else {
		returnValue = returnObject.id;
	}

	return returnValue;
}

@Override
long /*int*/ accessibilityAttributeValue_forParameter(long /*int*/ id, long /*int*/ sel, long /*int*/ arg0, long /*int*/ arg1) {
	NSString attribute = new NSString(arg0);

	id returnValue = null;

	if (handleIsAccessible(id) && accessible != null) {
		id parameter = new id(arg1);
		returnValue = accessible.internal_accessibilityAttributeValue_forParameter(attribute, parameter, ACC.CHILDID_SELF);
	}

	// If we had an accessible and it didn't handle the attribute request, let the
	// superclass handle it.
	if (returnValue == null)
		return super.accessibilityAttributeValue_forParameter(id, sel, arg0, arg1);
	else
		return returnValue.id;
}

@Override
boolean accessibilityIsAttributeSettable(long /*int*/ id, long /*int*/ sel, long /*int*/ arg0) {
	boolean returnValue = false;
	if (handleIsAccessible(id) && accessible != null) {
		NSString attribute = new NSString (arg0);
		returnValue = accessible.internal_accessibilityIsAttributeSettable(attribute, ACC.CHILDID_SELF);
	}
	if (!returnValue) {
		returnValue = super.accessibilityIsAttributeSettable(id, sel, arg0);
	}
	return returnValue;
}

@Override
void accessibilitySetValue_forAttribute(long /*int*/ id, long /*int*/ sel, long /*int*/ arg0, long /*int*/ arg1) {
	if (handleIsAccessible(id) && accessible != null) {
		id value = new id(arg0);
		NSString attribute = new NSString(arg1);
		accessible.internal_accessibilitySetValue_forAttribute(value, attribute, ACC.CHILDID_SELF);
	} else {
		super.accessibilitySetValue_forAttribute(id, sel, arg0, arg1);
	}
}

/**
 * Adds the listener to the collection of listeners who will
 * be notified when the control is moved or resized, by sending
 * it one of the messages defined in the <code>ControlListener</code>
 * interface.
 *
 * @param listener the listener which should be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see ControlListener
 * @see #removeControlListener
 */
public void addControlListener(ControlListener listener) {
	checkWidget();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	TypedListener typedListener = new TypedListener (listener);
	addListener (SWT.Resize,typedListener);
	addListener (SWT.Move,typedListener);
}

/**
 * Adds the listener to the collection of listeners who will
 * be notified when a drag gesture occurs, by sending it
 * one of the messages defined in the <code>DragDetectListener</code>
 * interface.
 *
 * @param listener the listener which should be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see DragDetectListener
 * @see #removeDragDetectListener
 *
 * @since 3.3
 */
public void addDragDetectListener (DragDetectListener listener) {
	checkWidget ();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	TypedListener typedListener = new TypedListener (listener);
	addListener (SWT.DragDetect,typedListener);
}

/**
 * Adds the listener to the collection of listeners who will
 * be notified when the control gains or loses focus, by sending
 * it one of the messages defined in the <code>FocusListener</code>
 * interface.
 *
 * @param listener the listener which should be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see FocusListener
 * @see #removeFocusListener
 */
public void addFocusListener(FocusListener listener) {
	checkWidget();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	TypedListener typedListener = new TypedListener (listener);
	addListener(SWT.FocusIn,typedListener);
	addListener(SWT.FocusOut,typedListener);
}

/**
 * Adds the listener to the collection of listeners who will
 * be notified when gesture events are generated for the control,
 * by sending it one of the messages defined in the
 * <code>GestureListener</code> interface.
 * <p>
 * NOTE: If <code>setTouchEnabled(true)</code> has previously been
 * invoked on the receiver then <code>setTouchEnabled(false)</code>
 * must be invoked on it to specify that gesture events should be
 * sent instead of touch events.
 * </p>
 * <p>
 * <b>Warning</b>: This API is currently only implemented on Windows and Cocoa.
 * SWT doesn't send Gesture or Touch events on GTK.
 * </p>
 *
 * @param listener the listener which should be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see GestureListener
 * @see #removeGestureListener
 * @see #setTouchEnabled
 *
 * @since 3.7
 */
public void addGestureListener (GestureListener listener) {
	checkWidget();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	TypedListener typedListener = new TypedListener (listener);
	addListener (SWT.Gesture, typedListener);
}

/**
 * Adds the listener to the collection of listeners who will
 * be notified when help events are generated for the control,
 * by sending it one of the messages defined in the
 * <code>HelpListener</code> interface.
 *
 * @param listener the listener which should be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see HelpListener
 * @see #removeHelpListener
 */
public void addHelpListener (HelpListener listener) {
	checkWidget();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	TypedListener typedListener = new TypedListener (listener);
	addListener (SWT.Help, typedListener);
}

/**
 * Adds the listener to the collection of listeners who will
 * be notified when keys are pressed and released on the system keyboard, by sending
 * it one of the messages defined in the <code>KeyListener</code>
 * interface.
 * <p>
 * When a key listener is added to a control, the control
 * will take part in widget traversal.  By default, all
 * traversal keys (such as the tab key and so on) are
 * delivered to the control.  In order for a control to take
 * part in traversal, it should listen for traversal events.
 * Otherwise, the user can traverse into a control but not
 * out.  Note that native controls such as table and tree
 * implement key traversal in the operating system.  It is
 * not necessary to add traversal listeners for these controls,
 * unless you want to override the default traversal.
 * </p>
 * @param listener the listener which should be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see KeyListener
 * @see #removeKeyListener
 */
public void addKeyListener(KeyListener listener) {
	checkWidget();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	TypedListener typedListener = new TypedListener (listener);
	addListener(SWT.KeyUp,typedListener);
	addListener(SWT.KeyDown,typedListener);
}

/**
 * Adds the listener to the collection of listeners who will
 * be notified when the platform-specific context menu trigger
 * has occurred, by sending it one of the messages defined in
 * the <code>MenuDetectListener</code> interface.
 *
 * @param listener the listener which should be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see MenuDetectListener
 * @see #removeMenuDetectListener
 *
 * @since 3.3
 */
public void addMenuDetectListener (MenuDetectListener listener) {
	checkWidget ();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	TypedListener typedListener = new TypedListener (listener);
	addListener (SWT.MenuDetect, typedListener);
}

/**
 * Adds the listener to the collection of listeners who will
 * be notified when mouse buttons are pressed and released, by sending
 * it one of the messages defined in the <code>MouseListener</code>
 * interface.
 *
 * @param listener the listener which should be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see MouseListener
 * @see #removeMouseListener
 */
public void addMouseListener(MouseListener listener) {
	checkWidget();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	TypedListener typedListener = new TypedListener (listener);
	addListener(SWT.MouseDown,typedListener);
	addListener(SWT.MouseUp,typedListener);
	addListener(SWT.MouseDoubleClick,typedListener);
}

/**
 * Adds the listener to the collection of listeners who will
 * be notified when the mouse passes or hovers over controls, by sending
 * it one of the messages defined in the <code>MouseTrackListener</code>
 * interface.
 *
 * @param listener the listener which should be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see MouseTrackListener
 * @see #removeMouseTrackListener
 */
public void addMouseTrackListener (MouseTrackListener listener) {
	checkWidget();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	TypedListener typedListener = new TypedListener (listener);
	addListener (SWT.MouseEnter,typedListener);
	addListener (SWT.MouseExit,typedListener);
	addListener (SWT.MouseHover,typedListener);
}

/**
 * Adds the listener to the collection of listeners who will
 * be notified when the mouse moves, by sending it one of the
 * messages defined in the <code>MouseMoveListener</code>
 * interface.
 *
 * @param listener the listener which should be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see MouseMoveListener
 * @see #removeMouseMoveListener
 */
public void addMouseMoveListener(MouseMoveListener listener) {
	checkWidget();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	TypedListener typedListener = new TypedListener (listener);
	addListener(SWT.MouseMove,typedListener);
}

/**
 * Adds the listener to the collection of listeners who will
 * be notified when the mouse wheel is scrolled, by sending
 * it one of the messages defined in the
 * <code>MouseWheelListener</code> interface.
 *
 * @param listener the listener which should be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see MouseWheelListener
 * @see #removeMouseWheelListener
 *
 * @since 3.3
 */
public void addMouseWheelListener (MouseWheelListener listener) {
	checkWidget ();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	TypedListener typedListener = new TypedListener (listener);
	addListener (SWT.MouseWheel, typedListener);
}

void addRelation (Control control) {
}

/**
 * Adds the listener to the collection of listeners who will
 * be notified when the receiver needs to be painted, by sending it
 * one of the messages defined in the <code>PaintListener</code>
 * interface.
 *
 * @param listener the listener which should be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see PaintListener
 * @see #removePaintListener
 */
public void addPaintListener(PaintListener listener) {
	checkWidget();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	TypedListener typedListener = new TypedListener (listener);
	addListener(SWT.Paint,typedListener);
}

static final double SYNTHETIC_BOLD = -2.5;
static final double SYNTHETIC_ITALIC = 0.2;

void addTraits(NSMutableDictionary dict, Font font) {
	if ((font.extraTraits & OS.NSBoldFontMask) != 0) {
		dict.setObject(NSNumber.numberWithDouble(SYNTHETIC_BOLD), OS.NSStrokeWidthAttributeName);
	}
	if ((font.extraTraits & OS.NSItalicFontMask) != 0) {
		dict.setObject(NSNumber.numberWithDouble(SYNTHETIC_ITALIC), OS.NSObliquenessAttributeName);
	}
}

/**
 * Adds the listener to the collection of listeners who will
 * be notified when touch events occur, by sending it
 * one of the messages defined in the <code>TouchListener</code>
 * interface.
 * <p>
 * NOTE: You must also call <code>setTouchEnabled(true)</code> to
 * specify that touch events should be sent, which will cause gesture
 * events to not be sent.
 * </p>
 * <p>
 * <b>Warning</b>: This API is currently only implemented on Windows and Cocoa.
 * SWT doesn't send Gesture or Touch events on GTK.
 * </p>
 *
 * @param listener the listener which should be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see TouchListener
 * @see #removeTouchListener
 * @see #setTouchEnabled
 *
 * @since 3.7
 */
public void addTouchListener (TouchListener listener) {
	checkWidget();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	TypedListener typedListener = new TypedListener (listener);
	addListener (SWT.Touch,typedListener);
}

/**
 * Adds the listener to the collection of listeners who will
 * be notified when traversal events occur, by sending it
 * one of the messages defined in the <code>TraverseListener</code>
 * interface.
 *
 * @param listener the listener which should be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see TraverseListener
 * @see #removeTraverseListener
 */
public void addTraverseListener (TraverseListener listener) {
	checkWidget();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	TypedListener typedListener = new TypedListener (listener);
	addListener (SWT.Traverse,typedListener);
}

@Override
boolean becomeFirstResponder (long /*int*/ id, long /*int*/ sel) {
	if ((state & DISABLED) != 0) return false;
	return super.becomeFirstResponder (id, sel);
}

@Override
void beginGestureWithEvent (long /*int*/ id, long /*int*/ sel, long /*int*/ event) {
	if (!gestureEvent(id, event, SWT.GESTURE_BEGIN)) return;
	super.beginGestureWithEvent(id, sel, event);
}

@Override
void endGestureWithEvent (long /*int*/ id, long /*int*/ sel, long /*int*/ event) {
	if (!gestureEvent(id, event, SWT.GESTURE_END)) return;
	super.endGestureWithEvent(id, sel, event);
}

void calculateVisibleRegion (NSView view, long /*int*/ visibleRgn, boolean clipChildren) {
	long /*int*/ tempRgn = OS.NewRgn ();
	if (!view.isHiddenOrHasHiddenAncestor() && isDrawing()) {
		long /*int*/ childRgn = OS.NewRgn ();
		NSWindow window = view.window ();
		NSView contentView = window.contentView();
		NSView frameView = contentView.superview();
		NSRect bounds = contentView.visibleRect();
		bounds = contentView.convertRect_toView_(bounds, view);
		short[] rect = new short[4];
		OS.SetRect(rect, (short)bounds.x, (short)bounds.y, (short)(bounds.x + bounds.width), (short)(bounds.y + bounds.height));
		OS.RectRgn(visibleRgn, rect);
		NSView tempView = view, lastControl = null;
		while (tempView.id != frameView.id) {
			bounds = tempView.visibleRect();
			bounds = tempView.convertRect_toView_(bounds, view);
			OS.SetRect(rect, (short)bounds.x, (short)bounds.y, (short)(bounds.x + bounds.width), (short)(bounds.y + bounds.height));
			OS.RectRgn(tempRgn, rect);
			OS.SectRgn (tempRgn, visibleRgn, visibleRgn);
			if (OS.EmptyRgn (visibleRgn)) break;
			if (clipChildren || tempView.id != view.id) {
				NSArray subviews = tempView.subviews();
				long /*int*/ count = subviews.count();
				for (int i = 0; i < count; i++) {
					NSView child = new NSView (subviews.objectAtIndex(count - i - 1));
					if (lastControl != null && child.id == lastControl.id) break;
					if (child.isHidden()) continue;
					bounds = child.visibleRect();
					bounds = child.convertRect_toView_(bounds, view);
					OS.SetRect(rect, (short)bounds.x, (short)bounds.y, (short)(bounds.x + bounds.width), (short)(bounds.y + bounds.height));
					OS.RectRgn(tempRgn, rect);
					OS.UnionRgn (tempRgn, childRgn, childRgn);
				}
			}
			lastControl = tempView;
			tempView = tempView.superview();
		}
		OS.DiffRgn (visibleRgn, childRgn, visibleRgn);
		OS.DisposeRgn (childRgn);
	} else {
		OS.CopyRgn (tempRgn, visibleRgn);
	}
	OS.DisposeRgn (tempRgn);
}

@Override
void cancelOperation(long /*int*/ id, long /*int*/ sel, long /*int*/ sender) {
	// Cmd-. and escape arrive here. Forward the current event as a key event.
	if (hasKeyboardFocus(id)) {
		NSEvent nsEvent = NSApplication.sharedApplication().currentEvent();
		Shell s = this.getShell();
		s.keyInputHappened = false;
		boolean [] consume = new boolean [1];
		if (translateTraversal (nsEvent.keyCode (), nsEvent, consume)) return;
		if (isDisposed ()) return;
		if (!sendKeyEvent (nsEvent, SWT.KeyDown)) return;
	}
}

void checkBackground () {
	Shell shell = getShell ();
	if (this == shell) return;
	state &= ~PARENT_BACKGROUND;
	Composite composite = parent;
	do {
		int mode = composite.backgroundMode;
		if (mode != 0 || backgroundAlpha == 0) {
			if (mode == SWT.INHERIT_DEFAULT || backgroundAlpha == 0) {
				Control control = this;
				do {
					if ((control.state & THEME_BACKGROUND) == 0) {
						return;
					}
					control = control.parent;
				} while (control != composite);
			}
			state |= PARENT_BACKGROUND;
			return;
		}
		if (composite == shell) break;
		composite = composite.parent;
	} while (true);
}

void checkBuffered () {
	style |= SWT.DOUBLE_BUFFERED;
}

void checkToolTip (Widget target) {
	if (isVisible () && display.tooltipControl == this && (target == null || display.tooltipTarget == target)) {
		Shell shell = getShell ();
		shell.sendToolTipEvent (false);
		shell.sendToolTipEvent (true);
	}
}

/**
 * Returns the preferred size (in points) of the receiver.
 * <p>
 * The <em>preferred size</em> of a control is the size that it would
 * best be displayed at. The width hint and height hint arguments
 * allow the caller to ask a control questions such as "Given a particular
 * width, how high does the control need to be to show all of the contents?"
 * To indicate that the caller does not wish to constrain a particular
 * dimension, the constant <code>SWT.DEFAULT</code> is passed for the hint.
 * </p>
 *
 * @param wHint the width hint (can be <code>SWT.DEFAULT</code>)
 * @param hHint the height hint (can be <code>SWT.DEFAULT</code>)
 * @return the preferred size of the control
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see Layout
 * @see #getBorderWidth
 * @see #getBounds
 * @see #getSize
 * @see #pack(boolean)
 * @see "computeTrim, getClientArea for controls that implement them"
 */
public Point computeSize (int wHint, int hHint) {
	return computeSize (wHint, hHint, true);
}

/**
 * Returns the preferred size (in points) of the receiver.
 * <p>
 * The <em>preferred size</em> of a control is the size that it would
 * best be displayed at. The width hint and height hint arguments
 * allow the caller to ask a control questions such as "Given a particular
 * width, how high does the control need to be to show all of the contents?"
 * To indicate that the caller does not wish to constrain a particular
 * dimension, the constant <code>SWT.DEFAULT</code> is passed for the hint.
 * </p><p>
 * If the changed flag is <code>true</code>, it indicates that the receiver's
 * <em>contents</em> have changed, therefore any caches that a layout manager
 * containing the control may have been keeping need to be flushed. When the
 * control is resized, the changed flag will be <code>false</code>, so layout
 * manager caches can be retained.
 * </p>
 *
 * @param wHint the width hint (can be <code>SWT.DEFAULT</code>)
 * @param hHint the height hint (can be <code>SWT.DEFAULT</code>)
 * @param changed <code>true</code> if the control's contents have changed, and <code>false</code> otherwise
 * @return the preferred size of the control.
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see Layout
 * @see #getBorderWidth
 * @see #getBounds
 * @see #getSize
 * @see #pack(boolean)
 * @see "computeTrim, getClientArea for controls that implement them"
 */
public Point computeSize (int wHint, int hHint, boolean changed) {
	checkWidget ();
	int width = DEFAULT_WIDTH;
	int height = DEFAULT_HEIGHT;
	if (wHint != SWT.DEFAULT) width = wHint;
	if (hHint != SWT.DEFAULT) height = hHint;
	int border = getBorderWidth ();
	width += border * 2;
	height += border * 2;
	return new Point (width, height);
}

Widget computeTabGroup () {
	if (isTabGroup()) return this;
	return parent.computeTabGroup ();
}

Widget[] computeTabList() {
	if (isTabGroup()) {
		if (getVisible() && getEnabled()) {
			return new Widget[] {this};
		}
	}
	return new Widget[0];
}

Control computeTabRoot () {
	Control[] tabList = parent._getTabList();
	if (tabList != null) {
		int index = 0;
		while (index < tabList.length) {
			if (tabList [index] == this) break;
			index++;
		}
		if (index == tabList.length) {
			if (isTabGroup ()) return this;
		}
	}
	return parent.computeTabRoot ();
}

NSView contentView () {
	return view;
}

NSAttributedString createString (String string, Font font, double /*float*/ [] foreground, int alignment, boolean wrap, boolean enabled, boolean mnemonics) {
	NSMutableDictionary dict = ((NSMutableDictionary)new NSMutableDictionary().alloc()).initWithCapacity(5);
	if (font == null) font = this.font != null ? this.font : defaultFont();
	dict.setObject (font.handle, OS.NSFontAttributeName);
	addTraits(dict, font);
	if (enabled) {
		if (foreground != null) {
			NSColor color = NSColor.colorWithDeviceRed(foreground[0], foreground[1], foreground[2], foreground[3]);
			dict.setObject (color, OS.NSForegroundColorAttributeName);
		}
	} else {
		dict.setObject (NSColor.disabledControlTextColor (), OS.NSForegroundColorAttributeName);
	}
	NSMutableParagraphStyle paragraphStyle = (NSMutableParagraphStyle)new NSMutableParagraphStyle ().alloc ().init ();
	paragraphStyle.setLineBreakMode (wrap ? OS.NSLineBreakByWordWrapping : OS.NSLineBreakByClipping);
	if (alignment != 0) {
		int align = OS.NSLeftTextAlignment;
		if ((alignment & SWT.CENTER) != 0) {
			align = OS.NSCenterTextAlignment;
		} else if ((alignment & SWT.RIGHT) != 0) {
			align = OS.NSRightTextAlignment;
		}
		paragraphStyle.setAlignment (align);
	}
	if ((style & SWT.RIGHT_TO_LEFT) != 0) {
		paragraphStyle.setBaseWritingDirection(OS.NSWritingDirectionRightToLeft);
	} else {
		paragraphStyle.setBaseWritingDirection(OS.NSWritingDirectionLeftToRight);
	}
	dict.setObject (paragraphStyle, OS.NSParagraphStyleAttributeName);
	paragraphStyle.release ();
	int length = string.length ();
	char [] chars = new char [length];
	string.getChars (0, chars.length, chars, 0);
	if (mnemonics) length = fixMnemonic (chars);
	NSString str = ((NSString)new NSString().alloc()).initWithCharacters(chars, length);
	NSAttributedString attribStr = ((NSAttributedString) new NSAttributedString ().alloc ()).initWithString (str, dict);
	str.release();
	dict.release();
	return attribStr;
}

@Override
void createWidget () {
	state |= DRAG_DETECT;
	checkOrientation (parent);
	super.createWidget ();
	checkBackground ();
	checkBuffered ();
	setDefaultFont ();
	setZOrder ();
	setRelations ();
	if ((state & PARENT_BACKGROUND) != 0) {
		setBackground ();
	}
	display.clearPool ();
}

Color defaultBackground () {
	return display.getWidgetColor (SWT.COLOR_WIDGET_BACKGROUND);
}

Font defaultFont () {
	if (display.smallFonts) return display.getSystemFont ();
	return Font.cocoa_new (display, defaultNSFont ());
}

Color defaultForeground () {
	return display.getWidgetColor (SWT.COLOR_WIDGET_FOREGROUND);
}

NSFont defaultNSFont () {
	return display.getSystemFont().handle;
}

@Override
void deregister () {
	super.deregister ();
	display.removeWidget (view);
}

@Override
void destroyWidget () {
	NSView view = topView ();
	view.removeFromSuperview ();
	releaseHandle ();
}

@Override
void doCommandBySelector (long /*int*/ id, long /*int*/ sel, long /*int*/ selector) {
	if (hasKeyboardFocus(id)) {
		if (imeInComposition ()) return;
		Shell s = this.getShell();
		NSEvent nsEvent = NSApplication.sharedApplication ().currentEvent ();
		if (nsEvent != null && nsEvent.type () == OS.NSKeyDown) {
			/*
			 * Feature in Cocoa.  Pressing Alt+UpArrow invokes doCommandBySelector
			 * twice, with selectors moveBackward and moveToBeginningOfParagraph
			 * (Alt+DownArrow behaves similarly).  In order to avoid sending
			 * multiple events for these keys, do not send a KeyDown if we already sent one
			 * during this keystroke. This rule does not apply if the command key
			 * is down, because we likely triggered the current key sequence via flagsChanged.
			 */
			long /*int*/ modifiers = nsEvent.modifierFlags();
			if (s.keyInputHappened == false || (modifiers & OS.NSCommandKeyMask) != 0) {
				s.keyInputHappened = true;
				boolean [] consume = new boolean [1];
				if (translateTraversal (nsEvent.keyCode (), nsEvent, consume)) return;
				if (isDisposed ()) return;
				if (!sendKeyEvent (nsEvent, SWT.KeyDown)) return;
				if (consume [0]) return;
			}
		}
		if ((state & CANVAS) != 0) return;
	}
	super.doCommandBySelector (id, sel, selector);
}

/**
 * Detects a drag and drop gesture.  This method is used
 * to detect a drag gesture when called from within a mouse
 * down listener.
 *
 * <p>By default, a drag is detected when the gesture
 * occurs anywhere within the client area of a control.
 * Some controls, such as tables and trees, override this
 * behavior.  In addition to the operating system specific
 * drag gesture, they require the mouse to be inside an
 * item.  Custom widget writers can use <code>setDragDetect</code>
 * to disable the default detection, listen for mouse down,
 * and then call <code>dragDetect()</code> from within the
 * listener to conditionally detect a drag.
 * </p>
 *
 * @param event the mouse down event
 *
 * @return <code>true</code> if the gesture occurred, and <code>false</code> otherwise.
 *
 * @exception IllegalArgumentException <ul>
 *   <li>ERROR_NULL_ARGUMENT if the event is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see DragDetectListener
 * @see #addDragDetectListener
 *
 * @see #getDragDetect
 * @see #setDragDetect
 *
 * @since 3.3
 */
public boolean dragDetect (Event event) {
	checkWidget ();
	if (event == null) error (SWT.ERROR_NULL_ARGUMENT);
	return dragDetect (event.button, event.count, event.stateMask, event.x, event.y);
}

/**
 * Detects a drag and drop gesture.  This method is used
 * to detect a drag gesture when called from within a mouse
 * down listener.
 *
 * <p>By default, a drag is detected when the gesture
 * occurs anywhere within the client area of a control.
 * Some controls, such as tables and trees, override this
 * behavior.  In addition to the operating system specific
 * drag gesture, they require the mouse to be inside an
 * item.  Custom widget writers can use <code>setDragDetect</code>
 * to disable the default detection, listen for mouse down,
 * and then call <code>dragDetect()</code> from within the
 * listener to conditionally detect a drag.
 * </p>
 *
 * @param event the mouse down event
 *
 * @return <code>true</code> if the gesture occurred, and <code>false</code> otherwise.
 *
 * @exception IllegalArgumentException <ul>
 *   <li>ERROR_NULL_ARGUMENT if the event is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see DragDetectListener
 * @see #addDragDetectListener
 *
 * @see #getDragDetect
 * @see #setDragDetect
 *
 * @since 3.3
 */
public boolean dragDetect (MouseEvent event) {
	checkWidget ();
	if (event == null) error (SWT.ERROR_NULL_ARGUMENT);
	return dragDetect (event.button, event.count, event.stateMask, event.x, event.y);
}

boolean dragDetect (int button, int count, int stateMask, int x, int y) {
	if (button != 1 || count != 1) return false;
	if (!dragDetect (x, y, false, null)) return false;
	return sendDragEvent (button, stateMask, x, y);
}

boolean dragDetect (int x, int y, boolean filter, boolean [] consume) {
	/**
	 * Feature in Cocoa. Mouse drag events do not account for hysteresis.
	 * As soon as the mouse drags a mouse dragged event is fired.  Fix is to
	 * check for another mouse drag event that is at least 5 pixels away
	 * from the start of the drag.
	 */
	NSApplication application = NSApplication.sharedApplication();
	boolean dragging = false;
	long /*int*/ eventType = OS.NSLeftMouseDown;
	double /*float*/ dragX = x;
	double /*float*/ dragY = y;

	/**
	 * To check for an actual drag we need to pull off mouse moved and mouse up events
	 * to detect if the user dragged outside of a 10 x 10 box centered on the mouse down location.
	 * We still want the view to see the events, so save them and re-post when done checking.
	 * If no motion happens for .3 seconds, bail.
	 */
	NSEvent mouseUpEvent = null;
	NSMutableArray dragEvents = NSMutableArray.arrayWithCapacity(10);
	NSDate timeout = NSDate.dateWithTimeIntervalSinceNow(0.3);

	while (eventType != OS.NSLeftMouseUp) {
		NSEvent event = application.nextEventMatchingMask((OS.NSLeftMouseUpMask | OS.NSLeftMouseDraggedMask),
				timeout, OS.NSEventTrackingRunLoopMode, true);
		// No event means nextEventMatchingMask timed out.
		if (event == null) {
			dragging = true;
			break;
		}
		eventType = event.type();

		if (eventType == OS.NSLeftMouseDragged) {
			dragEvents.addObject(event);
			NSPoint windowLoc = event.locationInWindow();
			NSPoint viewLoc = view.convertPoint_fromView_(windowLoc, null);
			if (!view.isFlipped ()) {
				viewLoc.y = view.bounds().height - viewLoc.y;
			}
			if ((Math.abs(viewLoc.x - dragX) > DEFAULT_DRAG_HYSTERESIS) || (Math.abs(viewLoc.y - dragY) > DEFAULT_DRAG_HYSTERESIS)) {
				dragging = true;
				break;
			}
		} else if (eventType == OS.NSLeftMouseUp) {
			mouseUpEvent = event;
		}
	}

	// Push back any events we took out of the queue so the control can receive them.
	if (mouseUpEvent != null) application.postEvent(mouseUpEvent, true);

	if (dragEvents.count() > 0) {
		while (dragEvents.count() > 0) {
			NSEvent currEvent = new NSEvent(dragEvents.objectAtIndex(dragEvents.count() - 1).id);
			dragEvents.removeLastObject();
			application.postEvent(currEvent, true);
		}
	}

	return dragging;
}

boolean drawGripper (GC gc, int x, int y, int width, int height, boolean vertical) {
	return false;
}

boolean drawsBackground() {
    return true;
}

@Override
void drawWidget (long /*int*/ id, NSGraphicsContext context, NSRect rect) {
	if (ignorePaint) return;
	if (id != paintView().id) return;
	if (!hooks (SWT.Paint) && !filters (SWT.Paint)) return;

	/* Send paint event */
	GCData data = new GCData ();
	data.paintRect = rect;
	GC gc = GC.cocoa_new (this, data);
	Event event = new Event ();
	event.gc = gc;
	event.x = (int)rect.x;
	event.y = (int)rect.y;
	event.width = (int)rect.width;
	event.height = (int)rect.height;
	sendEvent (SWT.Paint, event);
	event.gc = null;
	gc.dispose ();
}

void enableWidget (boolean enabled) {
	if (view instanceof NSControl) {
		((NSControl)view).setEnabled(enabled);
	}
	updateCursorRects (isEnabled ());
}

boolean equals(double /*float*/ [] color1, double /*float*/ [] color2) {
	if (color1 == color2) return true;
	if (color1 == null) return color2 == null;
	if (color2 == null) return color1 == null;
	for (int i = 0; i < color1.length; i++) {
		if (color1 [i] != color2 [i]) return false;
	}
	return true;
}

NSView eventView () {
	return view;
}

void fillBackground (NSView view, NSGraphicsContext context, NSRect rect, int imgHeight) {
	fillBackground(view, context, rect, imgHeight, null, 0, 0);
}

void fillBackground (NSView view, NSGraphicsContext context, NSRect rect, int imgHeight, NSView gcView, int tx, int ty) {
	if (!drawsBackground()) return;
	Control control = findBackgroundControl();
	if (control == null) control = this;
	Image image = control.backgroundImage;
	if (image != null && !image.isDisposed()) {
		context.saveGraphicsState();
		NSColor.colorWithPatternImage(image.handle).setFill();
		NSPoint phase = new NSPoint();
		NSView controlView = control.view;
		if (!controlView.isFlipped()) {
			phase.y = controlView.bounds().height;
		}
		if (imgHeight == -1) {
			NSView contentView = controlView.window().contentView();
			phase = controlView.convertPoint_toView_(phase, contentView);
			phase.y = contentView.bounds().height - phase.y;
		} else {
			phase = view.convertPoint_toView_(phase, controlView);
			phase.y += imgHeight - backgroundImage.getBounds().height;
		}
		if (gcView != null) {
			NSPoint pt = gcView.convertPoint_toView_(new NSPoint(), view);
			phase.x += pt.x;
			phase.y -= pt.y;
		}
		phase.x -= tx;
		phase.y += ty;
		context.setPatternPhase(phase);
		NSBezierPath.fillRect(rect);
		context.restoreGraphicsState();
		return;
	}

	double /*float*/ [] background = control.background;
	double /*float*/ alpha;
	if (background == null) {
		if (isTransparent()) return;
		background = control.defaultBackground ().handle;
		alpha = getThemeAlpha ();
	} else {
		alpha = background[3];
	}
	context.saveGraphicsState ();
	NSColor.colorWithDeviceRed (background [0], background [1], background [2], alpha).setFill ();
	NSBezierPath.fillRect (rect);
	context.restoreGraphicsState ();
}

Cursor findCursor () {
	if (cursor != null) return cursor;
	return parent.findCursor ();
}

Control findBackgroundControl () {
	if ((backgroundImage != null || background != null) && backgroundAlpha > 0) return this;
	return (parent != null && !isTransparent() && (state & PARENT_BACKGROUND) != 0) ? parent.findBackgroundControl () : null;
}

Menu [] findMenus (Control control) {
	if (menu != null && this != control) return new Menu [] {menu};
	return new Menu [0];
}

Widget findTooltip (NSPoint pt) {
	return this;
}

void fixChildren (Shell newShell, Shell oldShell, Decorations newDecorations, Decorations oldDecorations, Menu [] menus) {
	oldShell.fixShell (newShell, this);
	oldDecorations.fixDecorations (newDecorations, this, menus);
}

void fixFocus (Control focusControl) {
	Shell shell = getShell ();
	Control control = this;
	while (control != shell && (control = control.parent) != null) {
		if (control.setFocus ()) return;
	}
	shell.setSavedFocus (focusControl);
	NSWindow window = view.window();
	if (!window.makeFirstResponder(null)) {
	    // Force first responder to resign.
	    window.endEditingFor(null);
	}
}

@Override
void flagsChanged (long /*int*/ id, long /*int*/ sel, long /*int*/ theEvent) {
	if (hasKeyboardFocus(id)) {
		if ((state & WEBKIT_EVENTS_FIX) == 0) {
			Shell s = this.getShell();
			s.keyInputHappened = false;
			int mask = 0;
			NSEvent nsEvent = new NSEvent (theEvent);
			long /*int*/ modifiers = nsEvent.modifierFlags ();
			int keyCode = Display.translateKey (nsEvent.keyCode ());
			switch (keyCode) {
				case SWT.ALT: mask = OS.NSAlternateKeyMask; break;
				case SWT.CONTROL: mask = OS.NSControlKeyMask; break;
				case SWT.COMMAND: mask = OS.NSCommandKeyMask; break;
				case SWT.SHIFT: mask = OS.NSShiftKeyMask; break;
				case SWT.CAPS_LOCK:
					Event event = new Event();
					event.keyCode = keyCode;
					setInputState (event, nsEvent, SWT.KeyDown);
					sendKeyEvent (SWT.KeyDown, event);
					setInputState (event, nsEvent, SWT.KeyUp);
					sendKeyEvent (SWT.KeyUp, event);
					break;
			}
			if (mask != 0) {
				s.keyInputHappened = true;
				int type = (mask & modifiers) != 0 ? SWT.KeyDown : SWT.KeyUp;
				Event event = new Event();
				event.keyCode = keyCode;
				setLocationMask(event, nsEvent);
				setInputState (event, nsEvent, type);
				if (!sendKeyEvent (type, event)) return;
			}
		}
	}
	super.flagsChanged (id, sel, theEvent);
}

NSView focusView () {
	return view;
}

/**
 * Forces the receiver to have the <em>keyboard focus</em>, causing
 * all keyboard events to be delivered to it.
 *
 * @return <code>true</code> if the control got focus, and <code>false</code> if it was unable to.
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see #setFocus
 */
public boolean forceFocus () {
	checkWidget();
	if (display.focusEvent == SWT.FocusOut) return false;
	Decorations shell = menuShell ();
	shell.setSavedFocus (this);
	if (!isEnabled () || !isVisible () || !isActive ()) return false;
	if (isFocusControl ()) return true;
	shell.setSavedFocus (null);
	NSView focusView = focusView ();
	if (!focusView.canBecomeKeyView()) return false;
	boolean result = forceFocus(focusView);
	if (isDisposed ()) return false;
	shell.setSavedFocus (this);
	/*
	 * Feature in Cocoa. If the window is inactive when forceFocus is called bringToTop
	 * eventually calls makeKeyAndOrderFront. This activates the window immediately, but unlike other platforms,
	 * it also immediately fire notifications that the window was activated, as opposed to posting an event
	 * to be handled on the next pass of readAndDispatch().
	 *
	 * Shell#windowDidBecomeKey will call Decorations#restoreFocus, so the saved focus must be set
	 * before the window is activated or the wrong control will get focus.
	 */
	shell.bringToTop (false);
	if (isDisposed ()) return false;
	return result;
}

boolean forceFocus (NSView focusView) {
	NSWindow window = view.window ();
	if(window == null) { return false; }
	return window.makeFirstResponder (focusView);
}

boolean gestureEvent(long /*int*/ id, long /*int*/ eventPtr, int detail) {
	if (!display.sendEvent) return true;
	display.sendEvent = false;
	// For cross-platform compatibility, touch events and gestures are mutually exclusive.
	// Don't send a gesture if touch events are enabled for this control.
	if (touchEnabled) return true;
	if (!isEventView (id)) return true;
	if (!hooks(SWT.Gesture) && !filters(SWT.Gesture)) return true;
	NSEvent nsEvent = new NSEvent(eventPtr);
	Event event = new Event();
	NSPoint windowPoint;
	NSView view = eventView ();
	windowPoint = nsEvent.locationInWindow();
	NSPoint point = view.convertPoint_fromView_(windowPoint, null);
	if (!view.isFlipped ()) {
		point.y = view.bounds().height - point.y;
	}
	event.x = (int) point.x;
	event.y = (int) point.y;
	setInputState (event, nsEvent, SWT.Gesture);
	event.detail = detail;

	if (detail == SWT.GESTURE_BEGIN) {
		display.rotation = 0.0;
		display.magnification = 1.0;
		display.gestureActive = true;
	} else if (detail == SWT.GESTURE_END) {
		display.gestureActive = false;
	}

	switch (detail) {
	case SWT.GESTURE_SWIPE:
		event.xDirection = (int) -nsEvent.deltaX();
		event.yDirection = (int) -nsEvent.deltaY();
		break;
	case SWT.GESTURE_ROTATE: {
		display.rotation += nsEvent.rotation();
		event.rotation = display.rotation;
		break;
	}
	case SWT.GESTURE_MAGNIFY:
		display.magnification *= (1.0 + nsEvent.magnification());
		event.magnification = display.magnification;
		break;
	case SWT.GESTURE_PAN:
		// Panning increment is expressed in terms of the direction of movement,
		// not in terms of scrolling increment.
		if (display.gestureActive) {
			event.xDirection = (int) nsEvent.deltaX();
			event.yDirection = (int) nsEvent.deltaY();
			if (event.xDirection == 0 && event.yDirection == 0) return true;
		}
		break;
	}

	sendEvent (SWT.Gesture, event);
	return event.doit;
}

/**
 * Returns the accessible object for the receiver.
 * <p>
 * If this is the first time this object is requested,
 * then the object is created and returned. The object
 * returned by getAccessible() does not need to be disposed.
 * </p>
 *
 * @return the accessible object
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see Accessible#addAccessibleListener
 * @see Accessible#addAccessibleControlListener
 *
 * @since 2.0
 */
public Accessible getAccessible () {
	checkWidget ();
	if (accessible == null) accessible = new_Accessible (this);
	return accessible;
}

/**
 * Returns the receiver's background color.
 * <p>
 * Note: This operation is a hint and may be overridden by the platform.
 * For example, on some versions of Windows the background of a TabFolder,
 * is a gradient rather than a solid color.
 * </p>
 * @return the background color
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public Color getBackground () {
	checkWidget();
	if (backgroundAlpha == 0) {
		Color color = Color.cocoa_new (display, background, 0);
		return color;
	}
	else {
		Control control = findBackgroundControl ();
		if (control == null) control = this;
		return control.getBackgroundColor ();
	}
}

Color getBackgroundColor () {
	return background != null ? Color.cocoa_new (display, background, backgroundAlpha) : defaultBackground ();
}

/**
 * Returns the receiver's background image.
 *
 * @return the background image
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @since 3.2
 */
public Image getBackgroundImage () {
	checkWidget();
	Control control = findBackgroundControl ();
	if (control == null) control = this;
	return control.backgroundImage;
}

/**
 * Returns the receiver's border width in points.
 *
 * @return the border width
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public int getBorderWidth () {
	checkWidget();
    return 0;
}

/**
 * Returns a rectangle describing the receiver's size and location in points
 * relative to its parent (or its display if its parent is null),
 * unless the receiver is a shell. In this case, the location is
 * relative to the display.
 *
 * @return the receiver's bounding rectangle
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public Rectangle getBounds () {
	checkWidget();
	NSRect rect = topView().frame();
	return new Rectangle((int)rect.x, (int)rect.y, (int)rect.width, (int)rect.height);
}

/**
 * Returns <code>true</code> if the receiver is detecting
 * drag gestures, and  <code>false</code> otherwise.
 *
 * @return the receiver's drag detect state
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @since 3.3
 */
public boolean getDragDetect () {
	checkWidget ();
	return (state & DRAG_DETECT) != 0;
}

@Override
boolean getDrawing () {
	return drawCount <= 0;
}

/**
 * Returns the receiver's cursor, or null if it has not been set.
 * <p>
 * When the mouse pointer passes over a control its appearance
 * is changed to match the control's cursor.
 * </p>
 *
 * @return the receiver's cursor or <code>null</code>
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @since 3.3
 */
public Cursor getCursor () {
	checkWidget();
	return cursor;
}

/**
 * Returns <code>true</code> if the receiver is enabled, and
 * <code>false</code> otherwise. A disabled control is typically
 * not selectable from the user interface and draws with an
 * inactive or "grayed" look.
 *
 * @return the receiver's enabled state
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see #isEnabled
 */
public boolean getEnabled () {
	checkWidget();
	return (state & DISABLED) == 0;
}

/**
 * Returns the font that the receiver will use to paint textual information.
 *
 * @return the receiver's font
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public Font getFont () {
	checkWidget();
	return font != null ? font : defaultFont ();
}

/**
 * Returns the foreground color that the receiver will use to draw.
 *
 * @return the receiver's foreground color
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public Color getForeground () {
	checkWidget();
	return getForegroundColor ();
}

Color getForegroundColor () {
	return foreground != null ? Color.cocoa_new (display, foreground) : defaultForeground ();
}

/**
 * Returns layout data which is associated with the receiver.
 *
 * @return the receiver's layout data
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public Object getLayoutData () {
	checkWidget();
	return layoutData;
}

/**
 * Returns a point describing the receiver's location relative
 * to its parent in points (or its display if its parent is null), unless
 * the receiver is a shell. In this case, the point is
 * relative to the display.
 *
 * @return the receiver's location
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public Point getLocation () {
	checkWidget();
	NSRect rect = topView().frame();
	return new Point((int)rect.x, (int)rect.y);
}

/**
 * Returns the receiver's pop up menu if it has one, or null
 * if it does not. All controls may optionally have a pop up
 * menu that is displayed when the user requests one for
 * the control. The sequence of key strokes, button presses
 * and/or button releases that are used to request a pop up
 * menu is platform specific.
 *
 * @return the receiver's menu
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public Menu getMenu () {
	checkWidget();
	return menu;
}

int getMininumHeight () {
	return 0;
}

/**
 * Returns the receiver's monitor.
 *
 * @return the receiver's monitor
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @since 3.0
 */
public Monitor getMonitor () {
	checkWidget();
	Monitor [] monitors = display.getMonitors ();
	if (monitors.length == 1) return monitors [0];
	int index = -1, value = -1;
	Rectangle bounds = getBounds ();
	if (this != getShell ()) {
		bounds = display.map (this.parent, null, bounds);
	}
	for (int i=0; i<monitors.length; i++) {
		Rectangle rect = bounds.intersection (monitors [i].getBounds ());
		int area = rect.width * rect.height;
		if (area > 0 && area > value) {
			index = i;
			value = area;
		}
	}
	if (index >= 0) return monitors [index];
	int centerX = bounds.x + bounds.width / 2, centerY = bounds.y + bounds.height / 2;
	for (int i=0; i<monitors.length; i++) {
		Rectangle rect = monitors [i].getBounds ();
		int x = centerX < rect.x ? rect.x - centerX : centerX > rect.x + rect.width ? centerX - rect.x - rect.width : 0;
		int y = centerY < rect.y ? rect.y - centerY : centerY > rect.y + rect.height ? centerY - rect.y - rect.height : 0;
		int distance = x * x + y * y;
		if (index == -1 || distance < value) {
			index = i;
			value = distance;
		}
	}
	return monitors [index];
}

/**
 * Returns the orientation of the receiver, which will be one of the
 * constants <code>SWT.LEFT_TO_RIGHT</code> or <code>SWT.RIGHT_TO_LEFT</code>.
 *
 * @return the orientation style
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @since 3.7
 */
public int getOrientation () {
	checkWidget ();
	return style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT);
}

/**
 * Returns the receiver's parent, which must be a <code>Composite</code>
 * or null when the receiver is a shell that was created with null or
 * a display for a parent.
 *
 * @return the receiver's parent
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public Composite getParent () {
	checkWidget();
	return parent;
}

Control [] getPath () {
	int count = 0;
	Shell shell = getShell ();
	Control control = this;
	while (control != shell) {
		count++;
		control = control.parent;
	}
	control = this;
	Control [] result = new Control [count];
	while (control != shell) {
		result [--count] = control;
		control = control.parent;
	}
	return result;
}

NSBezierPath getPath(Region region) {
	if (region == null) return null;
	return getPath(region.handle);
}

NSBezierPath getPath(long /*int*/ region) {
	Callback callback = new Callback(this, "regionToRects", 4);
	if (callback.getAddress() == 0) error(SWT.ERROR_NO_MORE_CALLBACKS);
	NSBezierPath path = NSBezierPath.bezierPath();
	path.retain();
	OS.QDRegionToRects(region, OS.kQDParseRegionFromTopLeft, callback.getAddress(), path.id);
	callback.dispose();
	if (path.isEmpty()) path.appendBezierPathWithRect(new NSRect());
	return path;
}

/**
 * Returns the region that defines the shape of the control,
 * or null if the control has the default shape.
 *
 * @return the region that defines the shape of the shell (or null)
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @since 3.4
 */
public Region getRegion () {
	checkWidget ();
	return region;
}

/**
 * Returns the receiver's shell. For all controls other than
 * shells, this simply returns the control's nearest ancestor
 * shell. Shells return themselves, even if they are children
 * of other shells.
 *
 * @return the receiver's shell
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see #getParent
 */
public Shell getShell () {
	checkWidget();
	return parent.getShell ();
}

/**
 * Returns a point describing the receiver's size in points. The
 * x coordinate of the result is the width of the receiver.
 * The y coordinate of the result is the height of the
 * receiver.
 *
 * @return the receiver's size
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public Point getSize () {
	checkWidget();
	NSRect rect = topView().frame();
	return new Point((int)rect.width, (int)rect.height);
}

/**
 * Returns the text direction of the receiver, which will be one of the
 * constants <code>SWT.LEFT_TO_RIGHT</code> or <code>SWT.RIGHT_TO_LEFT</code>.
 *
 * @return the text direction style
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @since 3.102
 */
public int getTextDirection() {
	checkWidget ();
	/* return the widget orientation */
	return style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT);
}

float getThemeAlpha () {
	return 1 * parent.getThemeAlpha ();
}

/**
 * Returns the receiver's tool tip text, or null if it has
 * not been set.
 *
 * @return the receiver's tool tip text
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public String getToolTipText () {
	checkWidget();
	return toolTipText;
}

/**
 * Returns <code>true</code> if this control is set to send touch events, or
 * <code>false</code> if it is set to send gesture events instead.  This method
 * also returns <code>false</code> if a touch-based input device is not detected
 * (this can be determined with <code>Display#getTouchEnabled()</code>).  Use
 * {@link #setTouchEnabled(boolean)} to switch the events that a control sends
 * between touch events and gesture events.
 *
 * @return <code>true</code> if the control is set to send touch events, or <code>false</code> otherwise
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see #setTouchEnabled
 * @see Display#getTouchEnabled
 *
 * @since 3.7
 */
public boolean getTouchEnabled() {
	checkWidget();
	return display.getTouchEnabled() && touchEnabled;
}

/**
 * Returns <code>true</code> if the receiver is visible, and
 * <code>false</code> otherwise.
 * <p>
 * If one of the receiver's ancestors is not visible or some
 * other condition makes the receiver not visible, this method
 * may still indicate that it is considered visible even though
 * it may not actually be showing.
 * </p>
 *
 * @return the receiver's visibility state
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public boolean getVisible () {
	checkWidget();
	return (state & HIDDEN) == 0;
}

long /*int*/ getVisibleRegion () {
	if (visibleRgn == 0) {
		visibleRgn = OS.NewRgn ();
		calculateVisibleRegion (view, visibleRgn, true);
	}
	long /*int*/ result = OS.NewRgn ();
	OS.CopyRgn (visibleRgn, result);
	return result;
}

boolean hasBorder () {
	return (style & SWT.BORDER) != 0;
}

boolean hasFocus () {
	return display.getFocusControl() == this;
}

boolean hasRegion () {
	return region != null || parent.hasRegion ();
}

@Override
long /*int*/ hitTest (long /*int*/ id, long /*int*/ sel, NSPoint point) {
	if ((state & DISABLED) != 0) return 0;
	if (!isActive ()) return 0;
	if (regionPath != null) {
		NSView rgnView = topView ();
		if (!rgnView.isFlipped()) rgnView = eventView ();
		NSPoint pt = rgnView.convertPoint_fromView_ (point, new NSView (id).superview());
		if (!regionPath.containsPoint(pt)) return 0;
	}
	return super.hitTest(id, sel, point);
}

boolean imeInComposition () {
	return false;
}

@Override
boolean insertText (long /*int*/ id, long /*int*/ sel, long /*int*/ string) {
	// sendKeyEvent may do something to run the event loop.  That would cause
	// 'string' to be released before any superclass could use it, so save it
	// until this method finishes.
	NSObject saver = new NSObject(string);
	saver.retain();
	try {
		if (hasKeyboardFocus(id)) {
			Shell s = this.getShell();
			NSEvent nsEvent = NSApplication.sharedApplication ().currentEvent ();
			if (nsEvent != null) {
				long /*int*/ type = nsEvent.type ();
				if (type == OS.NSKeyDown || type == OS.NSKeyUp || type == OS.NSSystemDefined) {
					NSString str = new NSString (string);
					if (str.isKindOfClass (OS.class_NSAttributedString)) {
						str = new NSAttributedString (string).string ();
					}
					int length = (int)/*64*/str.length ();
					char[] buffer = new char [length];
					str.getCharacters(buffer);
					for (int i = 0; i < buffer.length; i++) {
						s.keyInputHappened = true;
						Event event = new Event ();
						if (i == 0 && type == OS.NSKeyDown) setKeyState (event, SWT.KeyDown, nsEvent);
						event.character = buffer [i];
						if (!sendKeyEvent (SWT.KeyDown, event)) return false;
					}
				}
			}
			if ((state & CANVAS) != 0) return true;
		}

		return super.insertText (id, sel, string);
	} finally {
		saver.release();
	}
}

/**
 * Invokes platform specific functionality to allocate a new GC handle.
 * <p>
 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
 * API for <code>Control</code>. It is marked public only so that it
 * can be shared within the packages provided by SWT. It is not
 * available on all platforms, and should never be called from
 * application code.
 * </p>
 *
 * @param data the platform specific GC data
 * @return the platform specific GC handle
 *
 * @noreference This method is not intended to be referenced by clients.
 */
@Override
public long /*int*/ internal_new_GC (GCData data) {
	checkWidget();
	NSView view = paintView();
	NSGraphicsContext graphicsContext = null;
	if (data != null && data.paintRect != null) {
		graphicsContext = NSGraphicsContext.currentContext();
		if (!view.isFlipped()) data.state &= ~VISIBLE_REGION;
	}
	if (graphicsContext == null) {
		NSWindow window = view.window();
		/*
		 * Force the device to be created before attempting
		 * to create a GC on a deferred NSWindow.
		 */
		if (window.windowNumber() <= 0) {
			double /*float*/ alpha = window.alphaValue();
			window.setAlphaValue(0);
			window.orderBack(null);
			window.orderOut(null);
			window.setAlphaValue(alpha);
		}
		graphicsContext = NSGraphicsContext.graphicsContextWithWindow (window);
		NSGraphicsContext flippedContext = NSGraphicsContext.graphicsContextWithGraphicsPort(graphicsContext.graphicsPort(), true);
		graphicsContext = flippedContext;
		if (data != null) {
			data.flippedContext = flippedContext;
			data.state &= ~VISIBLE_REGION;
			data.visibleRgn = getVisibleRegion();
			display.addContext (data);
		}
	}
	if (data != null) {
		int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
		if ((data.style & mask) == 0) {
			data.style |= style & (mask | SWT.MIRRORED);
		}
		data.device = display;
		data.thread = display.thread;
		data.view = view;
		data.view.retain();
		data.view.window().retain();
		data.foreground = getForegroundColor ().handle;
		Control control = findBackgroundControl ();
		if (control == null) control = this;
		data.background = control.getBackgroundColor ().handle;
		data.font = font != null ? font : defaultFont ();
	}
	if (graphicsContext != null) {
		return graphicsContext.id;
	}
	return 0;
}

/**
 * Invokes platform specific functionality to dispose a GC handle.
 * <p>
 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
 * API for <code>Control</code>. It is marked public only so that it
 * can be shared within the packages provided by SWT. It is not
 * available on all platforms, and should never be called from
 * application code.
 * </p>
 *
 * @param hDC the platform specific GC handle
 * @param data the platform specific GC data
 *
 * @noreference This method is not intended to be referenced by clients.
 */
@Override
public void internal_dispose_GC (long /*int*/ hDC, GCData data) {
	checkWidget ();
	long /*int*/ context = hDC;
	NSGraphicsContext graphicsContext = new NSGraphicsContext (context);
	display.removeContext (data);
	if (data != null) {
		if (data.paintRect == null) graphicsContext.flushGraphics ();
		if (data.visibleRgn != 0) OS.DisposeRgn(data.visibleRgn);
		data.visibleRgn = 0;
		if (data.view != null) {
			data.view.window().release();
			data.view.release();
			data.view = null;
		}
	}
}

void invalidateChildrenVisibleRegion () {
}

void invalidateVisibleRegion () {
	int index = 0;
	Control[] siblings = parent._getChildren ();
	while (index < siblings.length && siblings [index] != this) index++;
	for (int i=index; i<siblings.length; i++) {
		Control sibling = siblings [i];
		sibling.resetVisibleRegion ();
		sibling.invalidateChildrenVisibleRegion ();
	}
	parent.resetVisibleRegion ();
}

@Override
boolean isActive () {
	if (getShell().getModalShell () != null) return false;
	Dialog dialog = display.getModalDialog();
	if (dialog == null) return true;
	NSPanel panel = display.getModalPanel();
	if (panel == null) return false;
	NSWindow parentWindow = view.window().parentWindow();
	return parentWindow == null || parentWindow.id == panel.id;
}

/*
 * Answers a boolean indicating whether a Label that precedes the receiver in
 * a layout should be read by screen readers as the recevier's label.
 */
boolean isDescribedByLabel () {
	return true;
}

@Override
boolean isDrawing () {
	return getDrawing() && parent.isDrawing();
}

/**
 * Returns <code>true</code> if the receiver is enabled and all
 * ancestors up to and including the receiver's nearest ancestor
 * shell are enabled.  Otherwise, <code>false</code> is returned.
 * A disabled control is typically not selectable from the user
 * interface and draws with an inactive or "grayed" look.
 *
 * @return the receiver's enabled state
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see #getEnabled
 */
public boolean isEnabled () {
	checkWidget();
	return getEnabled () && parent.isEnabled ();
}

boolean isEnabledCursor () {
	return isEnabled ();
}

boolean isFocusAncestor (Control control) {
	while (control != null && control != this && !(control instanceof Shell)) {
		control = control.parent;
	}
	return control == this;
}

/**
 * Returns <code>true</code> if the receiver has the user-interface
 * focus, and <code>false</code> otherwise.
 *
 * @return the receiver's focus state
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public boolean isFocusControl () {
	checkWidget();
	Control focusControl = display.focusControl;
	if (focusControl != null && !focusControl.isDisposed ()) {
		return this == focusControl;
	}
	return hasFocus ();
}

boolean isObscured () {
	long /*int*/ visibleRgn = getVisibleRegion(), boundsRgn = OS.NewRgn();
	short[] rect = new short[4];
	NSRect bounds = view.visibleRect();
	OS.SetRect(rect, (short)bounds.x, (short)bounds.y, (short)(bounds.x + bounds.width), (short)(bounds.y + bounds.height));
	OS.RectRgn(boundsRgn, rect);
	OS.DiffRgn(boundsRgn, visibleRgn, boundsRgn);
	boolean obscured = !OS.EmptyRgn (boundsRgn);
	OS.DisposeRgn(boundsRgn);
	OS.DisposeRgn(visibleRgn);
	return obscured;
}

/**
 * Returns <code>true</code> if the underlying operating
 * system supports this reparenting, otherwise <code>false</code>
 *
 * @return <code>true</code> if the widget can be reparented, otherwise <code>false</code>
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public boolean isReparentable () {
	checkWidget();
	return true;
}

boolean isResizing () {
	return (state & RESIZING) != 0 || parent.isResizing();
}

boolean isShowing () {
	/*
	* This is not complete.  Need to check if the
	* widget is obscurred by a parent or sibling.
	*/
	if (!isVisible ()) return false;
	Control control = this;
	while (control != null) {
		Point size = control.getSize ();
		if (size.x == 0 || size.y == 0) {
			return false;
		}
		control = control.parent;
	}
	return true;
}

boolean isTabGroup () {
	Control [] tabList = parent._getTabList ();
	if (tabList != null) {
		for (int i=0; i<tabList.length; i++) {
			if (tabList [i] == this) return true;
		}
	}
	int code = traversalCode (0, null);
	if ((code & (SWT.TRAVERSE_ARROW_PREVIOUS | SWT.TRAVERSE_ARROW_NEXT)) != 0) return false;
	return (code & (SWT.TRAVERSE_TAB_PREVIOUS | SWT.TRAVERSE_TAB_NEXT)) != 0;
}

boolean isTabItem () {
	Control [] tabList = parent._getTabList ();
	if (tabList != null) {
		for (int i=0; i<tabList.length; i++) {
			if (tabList [i] == this) return false;
		}
	}
	int code = traversalCode (0, null);
	return (code & (SWT.TRAVERSE_ARROW_PREVIOUS | SWT.TRAVERSE_ARROW_NEXT)) != 0;
}

boolean isTransparent() {
	if (background != null) return false;
	return parent.isTransparent();
}

boolean isTrim (NSView view) {
	return false;
}

/**
 * Returns <code>true</code> if the receiver is visible and all
 * ancestors up to and including the receiver's nearest ancestor
 * shell are visible. Otherwise, <code>false</code> is returned.
 *
 * @return the receiver's visibility state
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see #getVisible
 */
public boolean isVisible () {
	checkWidget();
	return getVisible () && parent.isVisible ();
}

@Override
void keyDown (long /*int*/ id, long /*int*/ sel, long /*int*/ theEvent) {
	if (hasKeyboardFocus(id)) {
		Shell s = this.getShell();
		s.keyInputHappened = false;
		boolean textInput = OS.objc_msgSend (id, OS.sel_conformsToProtocol_, OS.objc_getProtocol ("NSTextInput")) != 0;
		if (!textInput) {
			// Not a text field, so send a key event here.
			NSEvent nsEvent = new NSEvent (theEvent);
			boolean [] consume = new boolean [1];
			if (translateTraversal (nsEvent.keyCode (), nsEvent, consume)) return;
			if (isDisposed ()) return;
			if (!sendKeyEvent (nsEvent, SWT.KeyDown)) return;
			if (consume [0]) return;
		} else {
			// Control is some kind of text field, so the key event will be sent from insertText: or doCommandBySelector:
			super.keyDown (id, sel, theEvent);

			if (imeInComposition ()) return;
			// If none of those methods triggered a key event send one now.
			if (!s.keyInputHappened) {
				NSEvent nsEvent = new NSEvent (theEvent);
				boolean [] consume = new boolean [1];
				if (translateTraversal (nsEvent.keyCode (), nsEvent, consume)) return;
				if (isDisposed ()) return;
				if (!sendKeyEvent (nsEvent, SWT.KeyDown)) return;
				if (consume [0]) return;
			}

			return;
		}
	}
	super.keyDown (id, sel, theEvent);
}

boolean hasKeyboardFocus(long /*int*/ inId) {
	return view.window().firstResponder().id == inId;
}

@Override
void keyUp (long /*int*/ id, long /*int*/ sel, long /*int*/ theEvent) {
	if (hasKeyboardFocus(id)) {
		NSEvent nsEvent = new NSEvent (theEvent);
		if (!sendKeyEvent (nsEvent, SWT.KeyUp)) return;
	}
	super.keyUp (id, sel, theEvent);
}

@Override
void magnifyWithEvent(long /*int*/ id, long /*int*/ sel, long /*int*/ event) {
	if (!gestureEvent(id, event, SWT.GESTURE_MAGNIFY)) return;
	super.magnifyWithEvent(id, sel, event);
}

void markLayout (boolean changed, boolean all) {
	/* Do nothing */
}

@Override
long /*int*/ menuForEvent (long /*int*/ id, long /*int*/ sel, long /*int*/ theEvent) {
	if (!isEnabled ()) return 0;

	NSPoint pt = NSEvent.mouseLocation();
	pt.y = (int) (display.getPrimaryFrame().height - pt.y);
	int x = (int) pt.x;
	int y = (int) pt.y;
	Event event = new Event ();
	event.x = x;
	event.y = y;
	NSEvent nsEvent = new NSEvent(theEvent);
	event.detail = nsEvent.buttonNumber() > 0 ? SWT.MENU_MOUSE : SWT.MENU_KEYBOARD;

	int count = 0;
	if (display.popups != null) {
		while (count < display.popups.length && display.popups[count] != null) {
			count++;
		}
	}

	sendEvent(SWT.MenuDetect, event);
	//widget could be disposed at this point
	if (isDisposed ()) return 0;
	Menu menu = getMenu ();
	if (event.doit && menu != null && !menu.isDisposed ()) {
		if (x != event.x || y != event.y) {
			menu.setLocation (event.x, event.y);
		}
		return menu.nsMenu.id;
	}

	// There is either no popup menu set for the Control or event.doit = false.
	// If a popup was triggered in the MenuDetect listener, return it.
	int count2 = 0;
	if (display.popups != null) {
		while (count2 < display.popups.length && display.popups[count2] != null) {
			count2++;
		}
	}
	if (count2 != count && count2 > 0) {
		Menu menu1 = display.popups[count2 - 1];
		display.popups[count2 - 1] = null;
		return menu1.nsMenu.id;
	}
	if (!event.doit) return 0;
	return super.menuForEvent (id, sel, theEvent);
}

Decorations menuShell () {
	return parent.menuShell ();
}

@Override
void scrollWheel (long /*int*/ id, long /*int*/ sel, long /*int*/ theEvent) {
	boolean handled = false;
	if (id == view.id) {
		NSEvent nsEvent = new NSEvent(theEvent);
		if ((hooks(SWT.Gesture) || filters(SWT.Gesture))) {
			if (nsEvent.deltaY() != 0 || nsEvent.deltaX() != 0) {
				if (!gestureEvent(id, theEvent, SWT.GESTURE_PAN)) {
					handled = true;
				}
			}
		}
		if (!handled) {
			if (hooks (SWT.MouseWheel) || filters (SWT.MouseWheel)) {
				if (nsEvent.deltaY() != 0) {
					if (!sendMouseEvent(nsEvent, SWT.MouseWheel, true)) {
						handled = true;
					}
				}
			}
			if (hooks (SWT.MouseHorizontalWheel) || filters (SWT.MouseHorizontalWheel)) {
				if (nsEvent.deltaX() != 0) {
					if (!sendMouseEvent(nsEvent, SWT.MouseHorizontalWheel, true)) {
						handled = true;
					}
				}
			}
		}
	}
	if (!handled) super.scrollWheel(id, sel, theEvent);
}

boolean isEventView (long /*int*/ id) {
	return true;
}

boolean mouseEvent (long /*int*/ id, long /*int*/ sel, long /*int*/ theEvent, int type) {
	if (!display.sendEvent) return true;
	display.sendEvent = false;
	if (!isEventView (id)) return true;
	boolean dragging = false;
	boolean[] consume = null;
	NSEvent nsEvent = new NSEvent(theEvent);
	int nsType = (int)/*64*/nsEvent.type();
	NSInputManager manager = NSInputManager.currentInputManager ();
	if (manager != null && manager.wantsToHandleMouseEvents ()) {
		if (manager.handleMouseEvent (nsEvent)) {
			return true;
		}
	}

	boolean runEnterExit = false;
	Control runEnterExitControl = null;

	switch (nsType) {
		case OS.NSLeftMouseDown:
			if (nsEvent.clickCount() == 1 && (nsEvent.modifierFlags() & OS.NSControlKeyMask) == 0 && (state & DRAG_DETECT) != 0 && hooks (SWT.DragDetect)) {
				consume = new boolean[1];
				NSPoint location = view.convertPoint_fromView_(nsEvent.locationInWindow(), null);
				if (!view.isFlipped ()) {
					location.y = view.bounds().height - location.y;
				}
				dragging = dragDetect((int)location.x, (int)location.y, false, consume);
			}
			break;
		case OS.NSLeftMouseDragged:
		case OS.NSRightMouseDragged:
		case OS.NSOtherMouseDragged:
			runEnterExit = true;
			runEnterExitControl = this;
			break;
		case OS.NSLeftMouseUp:
		case OS.NSRightMouseUp:
		case OS.NSOtherMouseUp:
			if (display.clickCount == 2) {
				sendMouseEvent (nsEvent, SWT.MouseDoubleClick, false);
			}
			runEnterExit = true;
			runEnterExitControl = display.findControl(true);
			break;
	}
	sendMouseEvent (nsEvent, type, false);
	if (dragging) sendMouseEvent(nsEvent, SWT.DragDetect, false);
	if (runEnterExit) display.checkEnterExit (runEnterExitControl, nsEvent, false);
	if (consume != null && consume[0]) return false;
	return true;
}

@Override
void mouseDown(long /*int*/ id, long /*int*/ sel, long /*int*/ theEvent) {
	if (!mouseEvent(id, sel, theEvent, SWT.MouseDown)) return;
	boolean tracking = isEventView (id);
	Display display = this.display;
	if (tracking) display.trackingControl = this;
	super.mouseDown(id, sel, theEvent);
	if (tracking) display.trackingControl = null;
}

@Override
void mouseUp(long /*int*/ id, long /*int*/ sel, long /*int*/ theEvent) {
	if (!mouseEvent(id, sel, theEvent, SWT.MouseUp)) return;
	super.mouseUp(id, sel, theEvent);
}

@Override
void mouseDragged(long /*int*/ id, long /*int*/ sel, long /*int*/ theEvent) {
	if (!mouseEvent(id, sel, theEvent, SWT.MouseMove)) return;
	super.mouseDragged(id, sel, theEvent);
}

@Override
void rightMouseDown(long /*int*/ id, long /*int*/ sel, long /*int*/ theEvent) {
	if (!mouseEvent(id, sel, theEvent, SWT.MouseDown)) return;
	super.rightMouseDown(id, sel, theEvent);
}

@Override
void rightMouseUp(long /*int*/ id, long /*int*/ sel, long /*int*/ theEvent) {
	if (!mouseEvent(id, sel, theEvent, SWT.MouseUp)) return;
	super.rightMouseUp(id, sel, theEvent);
}

@Override
void rightMouseDragged(long /*int*/ id, long /*int*/ sel, long /*int*/ theEvent) {
	if (!mouseEvent(id, sel, theEvent, SWT.MouseMove)) return;
	super.rightMouseDragged(id, sel, theEvent);
}

@Override
void otherMouseDown(long /*int*/ id, long /*int*/ sel, long /*int*/ theEvent) {
	if (!mouseEvent(id, sel, theEvent, SWT.MouseDown)) return;
	super.otherMouseDown(id, sel, theEvent);
}

@Override
void otherMouseUp(long /*int*/ id, long /*int*/ sel, long /*int*/ theEvent) {
	if (!mouseEvent(id, sel, theEvent, SWT.MouseUp)) return;
	super.otherMouseUp(id, sel, theEvent);
}

@Override
void otherMouseDragged(long /*int*/ id, long /*int*/ sel, long /*int*/ theEvent) {
	if (!mouseEvent(id, sel, theEvent, SWT.MouseMove)) return;
	super.otherMouseDragged(id, sel, theEvent);
}

void moved () {
	sendEvent (SWT.Move);
}

/**
 * Moves the receiver above the specified control in the
 * drawing order. If the argument is null, then the receiver
 * is moved to the top of the drawing order. The control at
 * the top of the drawing order will not be covered by other
 * controls even if they occupy intersecting areas.
 *
 * @param control the sibling control (or null)
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_INVALID_ARGUMENT - if the control has been disposed</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see Control#moveBelow
 * @see Composite#getChildren
 */
public void moveAbove (Control control) {
	checkWidget();
	if (control != null) {
		if (control.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
		if (parent != control.parent) return;
	}
	setZOrder (control, true);
}

/**
 * Moves the receiver below the specified control in the
 * drawing order. If the argument is null, then the receiver
 * is moved to the bottom of the drawing order. The control at
 * the bottom of the drawing order will be covered by all other
 * controls which occupy intersecting areas.
 *
 * @param control the sibling control (or null)
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_INVALID_ARGUMENT - if the control has been disposed</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see Control#moveAbove
 * @see Composite#getChildren
 */
public void moveBelow (Control control) {
	checkWidget();
	if (control != null) {
		if (control.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
		if (parent != control.parent) return;
	}
	setZOrder (control, false);
}

Accessible new_Accessible (Control control) {
	return Accessible.internal_new_Accessible (this);
}

/**
 * Causes the receiver to be resized to its preferred size.
 * For a composite, this involves computing the preferred size
 * from its layout, if there is one.
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see #computeSize(int, int, boolean)
 */
public void pack () {
	checkWidget();
	pack (true);
}

/**
 * Causes the receiver to be resized to its preferred size.
 * For a composite, this involves computing the preferred size
 * from its layout, if there is one.
 * <p>
 * If the changed flag is <code>true</code>, it indicates that the receiver's
 * <em>contents</em> have changed, therefore any caches that a layout manager
 * containing the control may have been keeping need to be flushed. When the
 * control is resized, the changed flag will be <code>false</code>, so layout
 * manager caches can be retained.
 * </p>
 *
 * @param changed whether or not the receiver's contents have changed
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see #computeSize(int, int, boolean)
 */
public void pack (boolean changed) {
	checkWidget();
	setSize (computeSize (SWT.DEFAULT, SWT.DEFAULT, changed));
}

NSView paintView () {
	return eventView ();
}

/**
 * Prints the receiver and all children.
 *
 * @param gc the gc where the drawing occurs
 * @return <code>true</code> if the operation was successful and <code>false</code> otherwise
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the gc is null</li>
 *    <li>ERROR_INVALID_ARGUMENT - if the gc has been disposed</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @since 3.4
 */
public boolean print (GC gc) {
	checkWidget ();
	if (gc == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (gc.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);

	NSGraphicsContext.static_saveGraphicsState();
	NSGraphicsContext.setCurrentContext(gc.handle);
	NSAffineTransform transform = NSAffineTransform.transform ();
	transform.translateXBy (0, view.bounds().height);
	transform.scaleXBy (1, -1);
	transform.concat ();
	view.displayRectIgnoringOpacity(view.bounds(), gc.handle);
	NSGraphicsContext.static_restoreGraphicsState();
	return true;
}

/**
 * Requests that this control and all of its ancestors be repositioned by
 * their layouts at the earliest opportunity. This should be invoked after
 * modifying the control in order to inform any dependent layouts of
 * the change.
 * <p>
 * The control will not be repositioned synchronously. This method is
 * fast-running and only marks the control for future participation in
 * a deferred layout.
 * <p>
 * Invoking this method multiple times before the layout occurs is an
 * inexpensive no-op.
 *
 * @since 3.105
 */
public void requestLayout () {
	getShell ().layout (new Control[] {this}, SWT.DEFER);
}

/**
 * Causes the entire bounds of the receiver to be marked
 * as needing to be redrawn. The next time a paint request
 * is processed, the control will be completely painted,
 * including the background.
 * <p>
 * Schedules a paint request if the invalidated area is visible
 * or becomes visible later. It is not necessary for the caller
 * to explicitly call {@link #update()} after calling this method,
 * but depending on the platform, the automatic repaints may be
 * delayed considerably.
 * </p>
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see #update()
 * @see PaintListener
 * @see SWT#Paint
 * @see SWT#NO_BACKGROUND
 * @see SWT#NO_REDRAW_RESIZE
 * @see SWT#NO_MERGE_PAINTS
 * @see SWT#DOUBLE_BUFFERED
 */
public void redraw () {
	checkWidget();
	view.setNeedsDisplay(true);
}

void redraw (boolean children) {
//	checkWidget();
	view.setNeedsDisplay(true);
}

/**
 * Causes the rectangular area of the receiver specified by
 * the arguments to be marked as needing to be redrawn.
 * The next time a paint request is processed, that area of
 * the receiver will be painted, including the background.
 * If the <code>all</code> flag is <code>true</code>, any
 * children of the receiver which intersect with the specified
 * area will also paint their intersecting areas. If the
 * <code>all</code> flag is <code>false</code>, the children
 * will not be painted.
 * <p>
 * Schedules a paint request if the invalidated area is visible
 * or becomes visible later. It is not necessary for the caller
 * to explicitly call {@link #update()} after calling this method,
 * but depending on the platform, the automatic repaints may be
 * delayed considerably.
 * </p>
 *
 * @param x the x coordinate of the area to draw
 * @param y the y coordinate of the area to draw
 * @param width the width of the area to draw
 * @param height the height of the area to draw
 * @param all <code>true</code> if children should redraw, and <code>false</code> otherwise
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see #update()
 * @see PaintListener
 * @see SWT#Paint
 * @see SWT#NO_BACKGROUND
 * @see SWT#NO_REDRAW_RESIZE
 * @see SWT#NO_MERGE_PAINTS
 * @see SWT#DOUBLE_BUFFERED
 */
public void redraw (int x, int y, int width, int height, boolean all) {
	checkWidget ();
	NSRect rect = new NSRect();
	rect.x = x;
	rect.y = y;
	rect.width = width;
	rect.height = height;
	view.setNeedsDisplayInRect(rect);
}

long /*int*/ regionToRects(long /*int*/ message, long /*int*/ rgn, long /*int*/ r, long /*int*/ path) {
	NSPoint pt = new NSPoint();
	short[] rect = new short[4];
	if (message == OS.kQDRegionToRectsMsgParse) {
		C.memmove(rect, r, rect.length * 2);
		pt.x = rect[1];
		pt.y = rect[0];
		OS.objc_msgSend(path, OS.sel_moveToPoint_, pt);
		pt.x = rect[3];
		OS.objc_msgSend(path, OS.sel_lineToPoint_, pt);
		pt.x = rect[3];
		pt.y = rect[2];
		OS.objc_msgSend(path, OS.sel_lineToPoint_, pt);
		pt.x = rect[1];
		OS.objc_msgSend(path, OS.sel_lineToPoint_, pt);
		OS.objc_msgSend(path, OS.sel_closePath);
	}
	return 0;
}

@Override
void register () {
	super.register ();
	display.addWidget (view, this);
}

@Override
void release (boolean destroy) {
	Control next = null, previous = null;
	if (destroy && parent != null) {
		Control[] children = parent._getChildren ();
		int index = 0;
		while (index < children.length) {
			if (children [index] == this) break;
			index++;
		}
		if (0 < index && (index + 1) < children.length) {
			next = children [index + 1];
			previous = children [index - 1];
		}
	}
	super.release (destroy);
	if (destroy) {
		if (previous != null) previous.addRelation (next);
	}
}

@Override
void releaseHandle () {
	super.releaseHandle ();
	if (view != null) view.release();
	view = null;
	parent = null;
}

@Override
void releaseParent () {
	invalidateVisibleRegion ();
	parent.removeControl (this);
}

@Override
void releaseWidget () {
	super.releaseWidget ();
	if (display.currentControl == this) {
		display.currentControl = null;
		display.timerExec(-1, display.hoverTimer);
	}
	if (display.trackingControl == this) display.trackingControl = null;
	if (display.tooltipControl == this) display.tooltipControl = null;
	if (menu != null && !menu.isDisposed ()) {
		menu.dispose ();
	}
	menu = null;
	if (visibleRgn != 0) OS.DisposeRgn (visibleRgn);
	visibleRgn = 0;
	layoutData = null;
	if (accessible != null) {
		accessible.internal_dispose_Accessible ();
	}
	accessible = null;
	region = null;
	if (regionPath != null) regionPath.release();
	regionPath = null;
}

/**
 * Removes the listener from the collection of listeners who will
 * be notified when the control is moved or resized.
 *
 * @param listener the listener which should no longer be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see ControlListener
 * @see #addControlListener
 */
public void removeControlListener (ControlListener listener) {
	checkWidget();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (eventTable == null) return;
	eventTable.unhook (SWT.Move, listener);
	eventTable.unhook (SWT.Resize, listener);
}

/**
 * Removes the listener from the collection of listeners who will
 * be notified when a drag gesture occurs.
 *
 * @param listener the listener which should no longer be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see DragDetectListener
 * @see #addDragDetectListener
 *
 * @since 3.3
 */
public void removeDragDetectListener(DragDetectListener listener) {
	checkWidget ();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (eventTable == null) return;
	eventTable.unhook (SWT.DragDetect, listener);
}

/**
 * Removes the listener from the collection of listeners who will
 * be notified when the control gains or loses focus.
 *
 * @param listener the listener which should no longer be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see FocusListener
 * @see #addFocusListener
 */
public void removeFocusListener(FocusListener listener) {
	checkWidget();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (eventTable == null) return;
	eventTable.unhook(SWT.FocusIn, listener);
	eventTable.unhook(SWT.FocusOut, listener);
}

/**
 * Removes the listener from the collection of listeners who will
 * be notified when gesture events are generated for the control.
 *
 * @param listener the listener which should no longer be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see GestureListener
 * @see #addGestureListener
 *
 * @since 3.7
 */
public void removeGestureListener (GestureListener listener) {
	checkWidget();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (eventTable == null) return;
	eventTable.unhook(SWT.Gesture, listener);
}

/**
 * Removes the listener from the collection of listeners who will
 * be notified when the help events are generated for the control.
 *
 * @param listener the listener which should no longer be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see HelpListener
 * @see #addHelpListener
 */
public void removeHelpListener (HelpListener listener) {
	checkWidget();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (eventTable == null) return;
	eventTable.unhook (SWT.Help, listener);
}

/**
 * Removes the listener from the collection of listeners who will
 * be notified when keys are pressed and released on the system keyboard.
 *
 * @param listener the listener which should no longer be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see KeyListener
 * @see #addKeyListener
 */
public void removeKeyListener(KeyListener listener) {
	checkWidget();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (eventTable == null) return;
	eventTable.unhook(SWT.KeyUp, listener);
	eventTable.unhook(SWT.KeyDown, listener);
}

/**
 * Removes the listener from the collection of listeners who will
 * be notified when the platform-specific context menu trigger has
 * occurred.
 *
 * @param listener the listener which should no longer be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see MenuDetectListener
 * @see #addMenuDetectListener
 *
 * @since 3.3
 */
public void removeMenuDetectListener (MenuDetectListener listener) {
	checkWidget ();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (eventTable == null) return;
	eventTable.unhook (SWT.MenuDetect, listener);
}

/**
 * Removes the listener from the collection of listeners who will
 * be notified when mouse buttons are pressed and released.
 *
 * @param listener the listener which should no longer be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see MouseListener
 * @see #addMouseListener
 */
public void removeMouseListener(MouseListener listener) {
	checkWidget();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (eventTable == null) return;
	eventTable.unhook(SWT.MouseDown, listener);
	eventTable.unhook(SWT.MouseUp, listener);
	eventTable.unhook(SWT.MouseDoubleClick, listener);
}

/**
 * Removes the listener from the collection of listeners who will
 * be notified when the mouse moves.
 *
 * @param listener the listener which should no longer be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see MouseMoveListener
 * @see #addMouseMoveListener
 */
public void removeMouseMoveListener(MouseMoveListener listener) {
	checkWidget();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (eventTable == null) return;
	eventTable.unhook(SWT.MouseMove, listener);
}

/**
 * Removes the listener from the collection of listeners who will
 * be notified when the mouse passes or hovers over controls.
 *
 * @param listener the listener which should no longer be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see MouseTrackListener
 * @see #addMouseTrackListener
 */
public void removeMouseTrackListener(MouseTrackListener listener) {
	checkWidget();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (eventTable == null) return;
	eventTable.unhook (SWT.MouseEnter, listener);
	eventTable.unhook (SWT.MouseExit, listener);
	eventTable.unhook (SWT.MouseHover, listener);
}

/**
 * Removes the listener from the collection of listeners who will
 * be notified when the mouse wheel is scrolled.
 *
 * @param listener the listener which should no longer be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see MouseWheelListener
 * @see #addMouseWheelListener
 *
 * @since 3.3
 */
public void removeMouseWheelListener (MouseWheelListener listener) {
	checkWidget ();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (eventTable == null) return;
	eventTable.unhook (SWT.MouseWheel, listener);
}

/**
 * Removes the listener from the collection of listeners who will
 * be notified when the receiver needs to be painted.
 *
 * @param listener the listener which should no longer be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see PaintListener
 * @see #addPaintListener
 */
public void removePaintListener(PaintListener listener) {
	checkWidget();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (eventTable == null) return;
	eventTable.unhook(SWT.Paint, listener);
}

/*
 * Remove "Labeled by" relations from the receiver.
 */
void removeRelation () {
	if (!isDescribedByLabel()) return;
	NSObject accessibleElement = focusView();

	if (accessibleElement instanceof NSControl) {
		NSControl viewAsControl = (NSControl) accessibleElement;
		if (viewAsControl.cell() != null) accessibleElement = viewAsControl.cell();
	}

	accessibleElement.accessibilitySetOverrideValue(accessibleElement, OS.NSAccessibilityTitleUIElementAttribute);
}


/**
 * Removes the listener from the collection of listeners who will
 * be notified when touch events occur.
 *
 * @param listener the listener which should no longer be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see TouchListener
 * @see #addTouchListener
 *
 * @since 3.7
 */
public void removeTouchListener(TouchListener listener) {
	checkWidget();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (eventTable == null) return;
	eventTable.unhook (SWT.Touch, listener);
}

/**
 * Removes the listener from the collection of listeners who will
 * be notified when traversal events occur.
 *
 * @param listener the listener which should no longer be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see TraverseListener
 * @see #addTraverseListener
 */
public void removeTraverseListener(TraverseListener listener) {
	checkWidget();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (eventTable == null) return;
	eventTable.unhook (SWT.Traverse, listener);
}

void resetVisibleRegion () {
	if (visibleRgn != 0) {
		OS.DisposeRgn (visibleRgn);
		visibleRgn = 0;
	}
	GCData[] gcs = display.contexts;
	if (gcs != null) {
		long /*int*/ visibleRgn = 0;
		for (int i=0; i<gcs.length; i++) {
			GCData data = gcs [i];
			if (data != null) {
				if (data.view == view) {
					if (visibleRgn == 0) visibleRgn = getVisibleRegion ();
					data.state &= ~VISIBLE_REGION;
					OS.CopyRgn (visibleRgn, data.visibleRgn);
				}
			}
		}
		if (visibleRgn != 0) OS.DisposeRgn (visibleRgn);
	}
}

void resized () {
	sendEvent (SWT.Resize);
}

@Override
void rotateWithEvent(long /*int*/ id, long /*int*/ sel, long /*int*/ event) {
	if (!gestureEvent(id, event, SWT.GESTURE_ROTATE)) return;
	super.rotateWithEvent(id, sel, event);
}

boolean sendDragEvent (int button, int stateMask, int x, int y) {
	Event event = new Event ();
	event.button = button;
	event.x = x;
	event.y = y;
	event.stateMask = stateMask;
	postEvent (SWT.DragDetect, event);
	return event.doit;
}

void sendFocusEvent (int type) {
	Display display = this.display;
	Shell shell = getShell ();

	display.focusEvent = type;
	display.focusControl = this;
	sendEvent (type);
	// widget could be disposed at this point
	display.focusEvent = SWT.None;
	display.focusControl = null;

	/*
	* It is possible that the shell may be
	* disposed at this point.  If this happens
	* don't send the activate and deactivate
	* events.
	*/
	if (!shell.isDisposed ()) {
		switch (type) {
			case SWT.FocusIn:
				shell.setActiveControl (this);
				break;
			case SWT.FocusOut:
				if (shell != display.getActiveShell ()) {
					shell.setActiveControl (null);
				}
				break;
		}
	}
}

boolean sendMouseEvent (NSEvent nsEvent, int type, boolean send) {
	Shell shell = null;
	Event event = new Event ();
	switch (type) {
		case SWT.MouseDown:
			shell = getShell ();
			//FALL THROUGH
		case SWT.MouseUp:
		case SWT.MouseDoubleClick:
		case SWT.DragDetect:
			int button = (int)/*64*/nsEvent.buttonNumber();
			switch (button) {
				case 0: event.button = 1; break;
				case 1: event.button = 3; break;
				case 2: event.button = 2; break;
				case 3: event.button = 4; break;
				case 4: event.button = 5; break;
			}
			break;
		case SWT.MouseWheel: {
			event.detail = SWT.SCROLL_LINE;
			double /*float*/ delta = nsEvent.deltaY();
			event.count = delta > 0 ? Math.max (1, (int)delta) : Math.min (-1, (int)delta);
			break;
		}
		case SWT.MouseHorizontalWheel: {
			double /*float*/ delta = nsEvent.deltaX();
			event.count = delta > 0 ? Math.max (1, (int)delta) : Math.min (-1, (int)delta);
			break;
		}
	}
	if (event.button != 0) event.count = display.clickCount;
	NSPoint windowPoint;
	NSView view = eventView ();
	if (nsEvent == null || nsEvent.type() == OS.NSMouseMoved) {
		NSWindow window = view.window();
		windowPoint = window.convertScreenToBase(NSEvent.mouseLocation());
	} else {
		windowPoint = nsEvent.locationInWindow();
	}
	NSPoint point = view.convertPoint_fromView_(windowPoint, null);
	if (!view.isFlipped ()) {
		point.y = view.bounds().height - point.y;
	}
	event.x = (int) point.x;
	event.y = (int) point.y;
	setInputState (event, nsEvent, type);
	if (send) {
		sendEvent (type, event);
		if (isDisposed ()) return false;
	} else {
		postEvent (type, event);
	}
	if (shell != null) shell.setActiveControl(this, SWT.MouseDown);
	return event.doit;
}

Touch touchStateFromNSTouch(NSTouch touch) {
	TouchSource source = display.findTouchSource(touch);
	long /*int*/ osPhase = touch.phase();
	long identity = OS.objc_msgSend(touch.id, OS.sel_identity);
	int state = 0;

	switch ((int)osPhase) {
	case OS.NSTouchPhaseBegan:
		state = SWT.TOUCHSTATE_DOWN;
		break;
	case OS.NSTouchPhaseMoved:
		state = SWT.TOUCHSTATE_MOVE;
		break;
	case OS.NSTouchPhaseEnded:
	case OS.NSTouchPhaseCancelled:
		state = SWT.TOUCHSTATE_UP;
		break;
	}

	display.touchCounter++;
	boolean primary = false;
	NSPoint normalizedPos = touch.normalizedPosition();
    double normalizedX = normalizedPos.x;
    double normalizedY = 1 - normalizedPos.y;
    if (display.currentTouches().count() == 1) display.primaryIdentifier = identity;
    if (display.primaryIdentifier == identity) primary = true;
	NSSize deviceSize = touch.deviceSize();
	int deviceX = (int) (normalizedX * deviceSize.width);
	int deviceY = (int) (normalizedY * deviceSize.height);
	Touch newTS = new Touch(identity, source, state, primary, deviceX, deviceY);
	return newTS;
}

NSTouch findTouchWithId(NSArray touches, NSObject identity) {
	long /*int*/ count = touches.count();
	for (long /*int*/ i = 0; i < count; i++) {
		NSTouch aTouch = new NSTouch(touches.objectAtIndex(i).id);
		NSObject currIdentity = new NSObject(OS.objc_msgSend(aTouch.id, OS.sel_identity));
		if (currIdentity.isEqual(identity)) return aTouch;
	}
	return null;
}

void setBackground () {
	if (!drawsBackground()) return;
	Control control = findBackgroundControl ();
	if (control == null) control = this;
	if (control.backgroundImage != null) {
		setBackgroundImage (control.backgroundImage.handle);
	} else {
		double /*float*/ [] color = control.background != null ? control.background : control.defaultBackground().handle;
		NSColor nsColor = NSColor.colorWithDeviceRed(color[0], color[1], color[2], color[3]);
		setBackgroundColor (nsColor);
	}
}

/**
 * Sets the receiver's background color to the color specified
 * by the argument, or to the default system color for the control
 * if the argument is null.
 * <p>
 * Note: This operation is a hint and may be overridden by the platform.
 * </p>
 * @param color the new color (or null)
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setBackground (Color color) {
	checkWidget ();
	_setBackground (color);
	if (color != null) {
		this.updateBackgroundMode ();
	}
}

private void _setBackground (Color color) {
	if (color != null) {
		if (color.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
	}
	double /*float*/ [] background = color != null ? color.handle : null;
	int alpha = color != null ? color.getAlpha() : 255;
	if (equals (background, this.background) && alpha == this.backgroundAlpha) return;
	this.background = background;
	this.backgroundAlpha = alpha;
	updateBackgroundColor ();
	redrawWidget(view, true);
}

/**
 * Sets the receiver's background image to the image specified
 * by the argument, or to the default system color for the control
 * if the argument is null.  The background image is tiled to fill
 * the available space.
 * <p>
 * Note: This operation is a hint and may be overridden by the platform.
 * For example, on Windows the background of a Button cannot be changed.
 * </p>
 * @param image the new image (or null)
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
 *    <li>ERROR_INVALID_ARGUMENT - if the argument is not a bitmap</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @since 3.2
 */
public void setBackgroundImage (Image image) {
	checkWidget();
	if (image != null && image.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
	if (image == backgroundImage && backgroundAlpha > 0) return;
	backgroundAlpha = 255;
	backgroundImage = image;
	updateBackgroundImage();
}

void setBackgroundImage (NSImage image) {
	redrawWidget(view, true);
}

void setBackgroundColor (NSColor nsColor) {
}

/**
 * Sets the receiver's size and location in points to the rectangular
 * area specified by the arguments. The <code>x</code> and
 * <code>y</code> arguments are relative to the receiver's
 * parent (or its display if its parent is null), unless
 * the receiver is a shell. In this case, the <code>x</code>
 * and <code>y</code> arguments are relative to the display.
 * <p>
 * Note: Attempting to set the width or height of the
 * receiver to a negative number will cause that
 * value to be set to zero instead.
 * </p>
 * <p>
 * Note: On GTK, attempting to set the width or height of the
 * receiver to a number higher or equal 2^14 will cause them to be
 * set to (2^14)-1 instead.
 * </p>
 *
 * @param x the new x coordinate for the receiver
 * @param y the new y coordinate for the receiver
 * @param width the new width for the receiver
 * @param height the new height for the receiver
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setBounds (int x, int y, int width, int height) {
	checkWidget();
	setBounds (x, y, Math.max (0, width), Math.max (0, height), true, true);
}

void setBounds (int x, int y, int width, int height, boolean move, boolean resize) {
	/*
	* Bug in Cocoa. On Mac 10.8, a text control loses and gains focus
	* when its bounds changes.  The fix is to ignore these events.
	*/
	Display display = this.display;
	Control oldIgnoreFocusControl = display.ignoreFocusControl;
	display.ignoreFocusControl = this;
	NSView topView = topView();
	if (move && resize) {
		NSRect rect = new NSRect();
		rect.x = x;
		rect.y = y;
		rect.width = width;
		rect.height = height;
		topView.setFrame (rect);
	} else if (move) {
		NSPoint point = new NSPoint();
		point.x = x;
		point.y = y;
		topView.setFrameOrigin(point);
	} else if (resize) {
		NSSize size = new NSSize();
		size.width = width;
		size.height = height;
		topView.setFrameSize(size);
	}
	display.ignoreFocusControl = oldIgnoreFocusControl;
}

/**
 * Sets the receiver's size and location in points to the rectangular
 * area specified by the argument. The <code>x</code> and
 * <code>y</code> fields of the rectangle are relative to
 * the receiver's parent (or its display if its parent is null).
 * <p>
 * Note: Attempting to set the width or height of the
 * receiver to a negative number will cause that
 * value to be set to zero instead.
 * </p>
 * <p>
 * Note: On GTK, attempting to set the width or height of the
 * receiver to a number higher or equal 2^14 will cause them to be
 * set to (2^14)-1 instead.
 * </p>
 *
 * @param rect the new bounds for the receiver
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setBounds (Rectangle rect) {
	checkWidget ();
	if (rect == null) error (SWT.ERROR_NULL_ARGUMENT);
	setBounds (rect.x, rect.y, Math.max (0, rect.width), Math.max (0, rect.height), true, true);
}

/**
 * If the argument is <code>true</code>, causes the receiver to have
 * all mouse events delivered to it until the method is called with
 * <code>false</code> as the argument.  Note that on some platforms,
 * a mouse button must currently be down for capture to be assigned.
 *
 * @param capture <code>true</code> to capture the mouse, and <code>false</code> to release it
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setCapture (boolean capture) {
	checkWidget();
}

@Override
void setClipRegion (NSView view) {
	if (regionPath != null) {
		NSView rgnView = topView ();
		if (!rgnView.isFlipped ()) rgnView = eventView ();
		NSPoint pt = view.convertPoint_toView_(new NSPoint(), rgnView);
		NSAffineTransform transform = NSAffineTransform.transform();
		transform.translateXBy(-pt.x, -pt.y);
		regionPath.transformUsingAffineTransform(transform);
		regionPath.addClip();
		transform.translateXBy(2*pt.x, 2*pt.y);
		regionPath.transformUsingAffineTransform(transform);
	}
	parent.setClipRegion(view);
}

/**
 * Sets the receiver's cursor to the cursor specified by the
 * argument, or to the default cursor for that kind of control
 * if the argument is null.
 * <p>
 * When the mouse pointer passes over a control its appearance
 * is changed to match the control's cursor.
 * </p>
 *
 * @param cursor the new cursor (or null)
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setCursor (Cursor cursor) {
	checkWidget();
	if (cursor != null && cursor.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
	this.cursor = cursor;
	if (!isEnabled()) return;
	if (!view.window().areCursorRectsEnabled()) return;
	display.setCursor (display.currentControl);
}

void setDefaultFont () {
	if (display.smallFonts) {
		setFont (defaultFont ().handle);
		setSmallSize ();
	}
}

/**
 * Sets the receiver's drag detect state. If the argument is
 * <code>true</code>, the receiver will detect drag gestures,
 * otherwise these gestures will be ignored.
 *
 * @param dragDetect the new drag detect state
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @since 3.3
 */
public void setDragDetect (boolean dragDetect) {
	checkWidget ();
	if (dragDetect) {
		state |= DRAG_DETECT;
	} else {
		state &= ~DRAG_DETECT;
	}
}

/**
 * Enables the receiver if the argument is <code>true</code>,
 * and disables it otherwise. A disabled control is typically
 * not selectable from the user interface and draws with an
 * inactive or "grayed" look.
 *
 * @param enabled the new enabled state
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setEnabled (boolean enabled) {
	checkWidget();
	if (((state & DISABLED) == 0) == enabled) return;
	Control control = null;
	boolean fixFocus = false;
	if (!enabled) {
		if (display.focusEvent != SWT.FocusOut) {
			control = display.getFocusControl ();
			fixFocus = isFocusAncestor (control);
		}
	}
	if (enabled) {
		state &= ~DISABLED;
	} else {
		state |= DISABLED;
	}
	enableWidget (enabled);
	if (fixFocus) fixFocus (control);
}

/**
 * Causes the receiver to have the <em>keyboard focus</em>,
 * such that all keyboard events will be delivered to it.  Focus
 * reassignment will respect applicable platform constraints.
 *
 * @return <code>true</code> if the control got focus, and <code>false</code> if it was unable to.
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see #forceFocus
 */
public boolean setFocus () {
	checkWidget();
	if ((style & SWT.NO_FOCUS) != 0) return false;
	return forceFocus ();
}

/**
 * Sets the font that the receiver will use to paint textual information
 * to the font specified by the argument, or to the default font for that
 * kind of control if the argument is null.
 *
 * @param font the new font (or null)
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setFont (Font font) {
	checkWidget();
	if (font != null) {
		if (font.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
	}
	this.font = font;
	setFont (font != null ? font.handle : defaultFont().handle);
}

void setFont (NSFont font) {
	if (view instanceof NSControl) {
		((NSControl)view).setFont(font);
	}
}

/**
 * Sets the receiver's foreground color to the color specified
 * by the argument, or to the default system color for the control
 * if the argument is null.
 * <p>
 * Note: This operation is a hint and may be overridden by the platform.
 * </p>
 * @param color the new color (or null)
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setForeground (Color color) {
	checkWidget();
	if (color != null) {
		if (color.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
	}
	double /*float*/ [] foreground = color != null ? color.handle : null;
	if (equals (foreground, this.foreground)) return;
	this.foreground = foreground;
	setForeground (foreground);
	redrawWidget (view, false);
}

void setForeground (double /*float*/ [] color) {
}

@Override
void setFrameOrigin (long /*int*/ id, long /*int*/ sel, NSPoint point) {
	NSView topView = topView ();
	if (topView.id != id) {
		super.setFrameOrigin(id, sel, point);
		return;
	}
	NSRect frame = topView.frame();
	super.setFrameOrigin(id, sel, point);
	if (frame.x != point.x || frame.y != point.y) {
		invalidateVisibleRegion();
		moved ();
	}
}

@Override
void setFrameSize (long /*int*/ id, long /*int*/ sel, NSSize size) {
	NSView topView = topView ();
	if (topView.id != id) {
		super.setFrameSize(id, sel, size);
		return;
	}
	NSRect frame = topView.frame();
	super.setFrameSize(id, sel, size);
	if (frame.width != size.width || frame.height != size.height) {
		invalidateVisibleRegion();
		boolean oldResizing = (state & RESIZING) != 0;
		state |= RESIZING;
		resized ();
		if (!oldResizing) state &= ~RESIZING;
	}
}

@Override
void cacheDisplayInRect_toBitmapImageRep (long id, long sel, NSRect rect, long rep) {
	/*
	 * When a GC is created with a control as the Drawable and GC.copyArea() is
	 * called, a SWT.Paint event will be sent, unexpectedly. This happens because
	 * NSView.cacheDisplayInRect() calls drawRect() which causes a SWT.Paint event
	 * to be sent. The fix is to ignore this paint event and prevent SWT from
	 * sending it to the clients.
	 * In the callback, set the ignorePaint flag, then call the Cocoa
	 * implementation of cacheDisplayInRect_toBitmapImageRep(), then reset the ignorePaint flag.
	 */
	ignorePaint = true;
	super.cacheDisplayInRect_toBitmapImageRep(id, sel, rect, rep);
	ignorePaint = false;
}

/**
 * Sets the layout data associated with the receiver to the argument.
 *
 * @param layoutData the new layout data for the receiver.
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setLayoutData (Object layoutData) {
	checkWidget();
	this.layoutData = layoutData;
}

/**
 * Sets the receiver's location to the point specified by
 * the arguments which are relative to the receiver's
 * parent (or its display if its parent is null), unless
 * the receiver is a shell. In this case, the point is
 * relative to the display.
 *
 * @param x the new x coordinate for the receiver
 * @param y the new y coordinate for the receiver
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setLocation (int x, int y) {
	checkWidget();
	setBounds (x, y, 0, 0, true, false);
}

/**
 * Sets the receiver's location to the point specified by
 * the arguments which are relative to the receiver's
 * parent (or its display if its parent is null), unless
 * the receiver is a shell. In this case, the point is
 * relative to the display.
 *
 * @param location the new location for the receiver
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setLocation (Point location) {
	checkWidget();
	if (location == null) error (SWT.ERROR_NULL_ARGUMENT);
	setBounds (location.x, location.y, 0, 0, true, false);
}

/**
 * Sets the receiver's pop up menu to the argument.
 * All controls may optionally have a pop up
 * menu that is displayed when the user requests one for
 * the control. The sequence of key strokes, button presses
 * and/or button releases that are used to request a pop up
 * menu is platform specific.
 * <p>
 * Note: Disposing of a control that has a pop up menu will
 * dispose of the menu.  To avoid this behavior, set the
 * menu to null before the control is disposed.
 * </p>
 *
 * @param menu the new pop up menu
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_MENU_NOT_POP_UP - the menu is not a pop up menu</li>
 *    <li>ERROR_INVALID_PARENT - if the menu is not in the same widget tree</li>
 *    <li>ERROR_INVALID_ARGUMENT - if the menu has been disposed</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setMenu (Menu menu) {
	checkWidget();
	if (menu != null) {
		if (menu.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
		if ((menu.style & SWT.POP_UP) == 0) {
			error (SWT.ERROR_MENU_NOT_POP_UP);
		}
		if (menu.parent != menuShell ()) {
			error (SWT.ERROR_INVALID_PARENT);
		}
	}
	this.menu = menu;
}

/**
 * Sets the orientation of the receiver, which must be one
 * of the constants <code>SWT.LEFT_TO_RIGHT</code> or <code>SWT.RIGHT_TO_LEFT</code>.
 * <p>
 *
 * @param orientation new orientation style
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @since 3.7
 */
public void setOrientation (int orientation) {
	checkWidget ();
}

/**
 * Changes the parent of the widget to be the one provided.
 * Returns <code>true</code> if the parent is successfully changed.
 *
 * @param parent the new parent for the control.
 * @return <code>true</code> if the parent is changed and <code>false</code> otherwise.
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
 *    <li>ERROR_NULL_ARGUMENT - if the parent is <code>null</code></li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 *	</ul>
 */
public boolean setParent (Composite parent) {
	checkWidget();
	if (parent == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (parent.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
	if (this.parent == parent) return true;
	if (!isReparentable ()) return false;
	releaseParent ();
	Shell newShell = parent.getShell (), oldShell = getShell ();
	Decorations newDecorations = parent.menuShell (), oldDecorations = menuShell ();
	if (oldShell != newShell || oldDecorations != newDecorations) {
		Menu [] menus = oldShell.findMenus (this);
		fixChildren (newShell, oldShell, newDecorations, oldDecorations, menus);
	}
	NSView topView = topView ();
	topView.retain();
	topView.removeFromSuperview();
	parent.contentView().addSubview(topView, OS.NSWindowBelow, null);
	topView.release();
	this.parent = parent;
	reskin (SWT.ALL);
	return true;
}

/**
 * If the argument is <code>false</code>, causes subsequent drawing
 * operations in the receiver to be ignored. No drawing of any kind
 * can occur in the receiver until the flag is set to true.
 * Graphics operations that occurred while the flag was
 * <code>false</code> are lost. When the flag is set to <code>true</code>,
 * the entire widget is marked as needing to be redrawn.  Nested calls
 * to this method are stacked.
 * <p>
 * Note: This operation is a hint and may not be supported on some
 * platforms or for some widgets.
 * </p>
 *
 * @param redraw the new redraw state
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see #redraw(int, int, int, int, boolean)
 * @see #update()
 */
public void setRedraw (boolean redraw) {
	checkWidget();
	if (redraw) {
		if (--drawCount == 0) {
			invalidateVisibleRegion ();
			redrawWidget(topView (), true);
		}
	} else {
		if (drawCount == 0) {
			invalidateVisibleRegion ();
		}
		drawCount++;
	}
}

/**
 * Sets the shape of the control to the region specified
 * by the argument.  When the argument is null, the
 * default shape of the control is restored.
 *
 * @param region the region that defines the shape of the control (or null)
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_INVALID_ARGUMENT - if the region has been disposed</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @since 3.4
 */
public void setRegion (Region region) {
	checkWidget ();
	if (region != null && region.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
	this.region = region;
	if (regionPath != null) regionPath.release();
	regionPath = getPath(region);
	redrawWidget(view, true);
}

void setRelations () {
	if (parent == null) return;
	Control [] children = parent._getChildren ();
	int count = children.length;
	if (count > 1) {
		/*
		 * the receiver is the last item in the list, so its predecessor will
		 * be the second-last item in the list
		 */
		Control child = children [count - 2];
		if (child != this) {
			child.addRelation (this);
		}
	}
}

boolean setRadioSelection (boolean value){
	return false;
}

/**
 * Sets the receiver's size to the point specified by the arguments.
 * <p>
 * Note: Attempting to set the width or height of the
 * receiver to a negative number will cause that
 * value to be set to zero instead.
 * </p>
 * <p>
 * Note: On GTK, attempting to set the width or height of the
 * receiver to a number higher or equal 2^14 will cause them to be
 * set to (2^14)-1 instead.
 * </p>
 *
 * @param width the new width in points for the receiver
 * @param height the new height in points for the receiver
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setSize (int width, int height) {
	checkWidget();
	setBounds (0, 0, Math.max (0, width), Math.max (0, height), false, true);
}

/**
 * Sets the receiver's size to the point specified by the argument.
 * <p>
 * Note: Attempting to set the width or height of the
 * receiver to a negative number will cause them to be
 * set to zero instead.
 * </p>
 * <p>
 * Note: On GTK, attempting to set the width or height of the
 * receiver to a number higher or equal 2^14 will cause them to be
 * set to (2^14)-1 instead.
 * </p>
 *
 * @param size the new size in points for the receiver
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the point is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setSize (Point size) {
	checkWidget ();
	if (size == null) error (SWT.ERROR_NULL_ARGUMENT);
	setBounds (0, 0, Math.max (0, size.x), Math.max (0, size.y), false, true);
}

void setSmallSize () {
	if (view instanceof NSControl) {
		NSCell cell = ((NSControl)view).cell();
		if (cell != null) cell.setControlSize (OS.NSSmallControlSize);
	}
}

@Override
boolean setTabItemFocus () {
	if (!isShowing ()) return false;
	return forceFocus ();
}

/**
 * Sets the base text direction (a.k.a. "paragraph direction") of the receiver,
 * which must be one of the constants <code>SWT.LEFT_TO_RIGHT</code>,
 * <code>SWT.RIGHT_TO_LEFT</code>, or <code>SWT.AUTO_TEXT_DIRECTION</code>.
 * <p>
 * <code>setOrientation</code> would override this value with the text direction
 * that is consistent with the new orientation.
 * </p>
 * <p>
 * <b>Warning</b>: This API is currently only implemented on Windows.
 * It doesn't set the base text direction on GTK and Cocoa.
 * </p>
 *
 * @param textDirection the base text direction style
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see SWT#LEFT_TO_RIGHT
 * @see SWT#RIGHT_TO_LEFT
 * @see SWT#AUTO_TEXT_DIRECTION
 * @see SWT#FLIP_TEXT_DIRECTION
 *
 * @since 3.102
 */
public void setTextDirection(int textDirection) {
	checkWidget ();
}

/**
 * Sets the receiver's tool tip text to the argument, which
 * may be null indicating that the default tool tip for the
 * control will be shown. For a control that has a default
 * tool tip, such as the Tree control on Windows, setting
 * the tool tip text to an empty string replaces the default,
 * causing no tool tip text to be shown.
 * <p>
 * The mnemonic indicator (character '&amp;') is not displayed in a tool tip.
 * To display a single '&amp;' in the tool tip, the character '&amp;' can be
 * escaped by doubling it in the string.
 * </p>
 *
 * @param string the new tool tip text (or null)
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setToolTipText (String string) {
	checkWidget();
	toolTipText = string;
	checkToolTip (null);
}

/**
 * Sets whether this control should send touch events (by default controls do not).
 * Setting this to <code>false</code> causes the receiver to send gesture events
 * instead.  No exception is thrown if a touch-based input device is not
 * detected (this can be determined with <code>Display#getTouchEnabled()</code>).
 *
 * @param enabled the new touch-enabled state
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 *
 * @see Display#getTouchEnabled
 *
 * @since 3.7
 */
public void setTouchEnabled(boolean enabled) {
	checkWidget();
	eventView().setAcceptsTouchEvents(enabled);
	touchEnabled = enabled;
}

/**
 * Marks the receiver as visible if the argument is <code>true</code>,
 * and marks it invisible otherwise.
 * <p>
 * If one of the receiver's ancestors is not visible or some
 * other condition makes the receiver not visible, marking
 * it visible may not actually cause it to be displayed.
 * </p>
 *
 * @param visible the new visibility state
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setVisible (boolean visible) {
	checkWidget();
	if (visible) {
		if ((state & HIDDEN) == 0) return;
		state &= ~HIDDEN;
	} else {
		if ((state & HIDDEN) != 0) return;
		state |= HIDDEN;
	}
	if (visible) {
		/*
		* It is possible (but unlikely), that application
		* code could have disposed the widget in the show
		* event.  If this happens, just return.
		*/
		sendEvent (SWT.Show);
		if (isDisposed ()) return;
	}

	/*
	* Feature in the Macintosh.  If the receiver has focus, hiding
	* the receiver causes no control to have focus.  Also, the focus
	* needs to be cleared from any TXNObject so that it stops blinking
	* the caret.  The fix is to assign focus to the first ancestor
	* control that takes focus.  If no control will take focus, clear
	* the focus control.
	*/
	Control control = null;
	boolean fixFocus = false;
	if (!visible) {
		if (display.focusEvent != SWT.FocusOut) {
			control = display.getFocusControl ();
			fixFocus = isFocusAncestor (control);
		}
	}
	topView().setHidden(!visible);
	if (isDisposed ()) return;
	invalidateVisibleRegion();
	if (!visible) {
		/*
		* It is possible (but unlikely), that application
		* code could have disposed the widget in the show
		* event.  If this happens, just return.
		*/
		sendEvent (SWT.Hide);
		if (isDisposed ()) return;
	}
	if (fixFocus) fixFocus (control);
}

void setZOrder () {
	NSView topView = topView ();
	parent.contentView().addSubview(topView, OS.NSWindowBelow, null);
}

@Override
boolean shouldDelayWindowOrderingForEvent (long /*int*/ id, long /*int*/ sel, long /*int*/ theEvent) {
	Shell shell = getShell ();
	if ((shell.style & SWT.ON_TOP) != 0) return false;
	return super.shouldDelayWindowOrderingForEvent (id, sel, theEvent);
}

void setZOrder (Control sibling, boolean above) {
	int index = 0, siblingIndex = 0, oldNextIndex = -1;
	Control[] children = null;
	/* determine the receiver's and sibling's indexes in the parent */
	children = parent._getChildren ();
	while (index < children.length) {
		if (children [index] == this) break;
		index++;
	}
	if (sibling != null) {
		while (siblingIndex < children.length) {
			if (children [siblingIndex] == sibling) break;
			siblingIndex++;
		}
	}
	/* remove "Labeled by" relationships that will no longer be valid */
	removeRelation ();
	if (index + 1 < children.length) {
		oldNextIndex = index + 1;
		children [oldNextIndex].removeRelation ();
	}
	if (sibling != null) {
		if (above) {
			sibling.removeRelation ();
		} else {
			if (siblingIndex + 1 < children.length) {
				children [siblingIndex + 1].removeRelation ();
			}
		}
	}

	NSView otherView = sibling == null ? null : sibling.topView ();
	NSView topView = topView();
	topView.retain();
	topView.removeFromSuperview();
	parent.contentView().addSubview(topView, above ? OS.NSWindowAbove : OS.NSWindowBelow, otherView);
	topView.release();
	invalidateVisibleRegion();

	/* determine the receiver's new index in the parent */
	if (sibling != null) {
		if (above) {
			index = siblingIndex - (index < siblingIndex ? 1 : 0);
		} else {
			index = siblingIndex + (siblingIndex < index ? 1 : 0);
		}
	} else {
		if (above) {
			index = 0;
		} else {
			index = children.length - 1;
		}
	}

	/* add new "Labeled by" relations as needed */
	children = parent._getChildren ();
	if (0 < index) {
		children [index - 1].addRelation (this);
	}
	if (index + 1 < children.length) {
		addRelation (children [index + 1]);
	}
	if (oldNextIndex != -1) {
		if (oldNextIndex <= index) oldNextIndex--;
		/* the last two conditions below ensure that duplicate relations are not hooked */
		if (0 < oldNextIndex && oldNextIndex != index && oldNextIndex != index + 1) {
			children [oldNextIndex - 1].addRelation (children [oldNextIndex]);
		}
	}
}

void sort (int [] items) {
	/* Shell Sort from K&R, pg 108 */
	int length = items.length;
	for (int gap=length/2; gap>0; gap/=2) {
		for (int i=gap; i<length; i++) {
			for (int j=i-gap; j>=0; j-=gap) {
		   		if (items [j] <= items [j + gap]) {
					int swap = items [j];
					items [j] = items [j + gap];
					items [j + gap] = swap;
		   		}
	    	}
	    }
	}
}

@Override
void swipeWithEvent(long /*int*/ id, long /*int*/ sel, long /*int*/ event) {
	if (!gestureEvent(id, event, SWT.GESTURE_SWIPE)) return;
	super.swipeWithEvent(id, sel, event);
}

NSSize textExtent (String string) {
	NSAttributedString attribStr = createString(string, null, null, 0, false, true, false);
	NSSize size = attribStr.size();
	attribStr.release();
	return size;
}

@Override
String tooltipText () {
	return toolTipText;
}

/**
 * Returns a point which is the result of converting the
 * argument, which is specified in display relative coordinates,
 * to coordinates relative to the receiver.
 * <p>
 * NOTE: To properly map a rectangle or a corner of a rectangle on a right-to-left platform, use
 * {@link Display#map(Control, Control, Rectangle)}.
 * </p>
 *
 * @param x the x coordinate in points to be translated
 * @param y the y coordinate in points to be translated
 * @return the translated coordinates
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @since 2.1
 */
public Point toControl (int x, int y) {
	checkWidget();
    return display.map (null, this, x, y);
}

/**
 * Returns a point which is the result of converting the
 * argument, which is specified in display relative coordinates,
 * to coordinates relative to the receiver.
 * <p>
 * NOTE: To properly map a rectangle or a corner of a rectangle on a right-to-left platform, use
 * {@link Display#map(Control, Control, Rectangle)}.
 * </p>
 *
 * @param point the point to be translated (must not be null)
 * @return the translated coordinates
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the point is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public Point toControl (Point point) {
	checkWidget();
	if (point == null) error (SWT.ERROR_NULL_ARGUMENT);
    return toControl (point.x, point.y);
}

/**
 * Returns a point which is the result of converting the
 * argument, which is specified in coordinates relative to
 * the receiver, to display relative coordinates.
 * <p>
 * NOTE: To properly map a rectangle or a corner of a rectangle on a right-to-left platform, use
 * {@link Display#map(Control, Control, Rectangle)}.
 * </p>
 *
 * @param x the x coordinate to be translated
 * @param y the y coordinate to be translated
 * @return the translated coordinates
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @since 2.1
 */
public Point toDisplay (int x, int y) {
	checkWidget();
	return display.map (this, null, x, y);
}

/**
 * Returns a point which is the result of converting the
 * argument, which is specified in coordinates relative to
 * the receiver, to display relative coordinates.
 * <p>
 * NOTE: To properly map a rectangle or a corner of a rectangle on a right-to-left platform, use
 * {@link Display#map(Control, Control, Rectangle)}.
 * </p>
 *
 * @param point the point to be translated (must not be null)
 * @return the translated coordinates
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the point is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public Point toDisplay (Point point) {
	checkWidget();
	if (point == null) error (SWT.ERROR_NULL_ARGUMENT);
	return toDisplay (point.x, point.y);
}

NSView topView () {
	return view;
}

boolean touchEvent(long /*int*/ id, long /*int*/ sel, long /*int*/ eventPtr) {
	if (!display.sendEvent) return true;
	display.sendEvent = false;
	if (!(hooks(SWT.Touch) || filters(SWT.Touch))) return true;
	if (!isEventView (id)) return true;
	if (!touchEnabled) return true;
	NSEvent nsEvent = new NSEvent(eventPtr);
	NSMutableArray currentTouches = display.currentTouches();
	Event event = new Event ();
	NSPoint location = view.convertPoint_fromView_(nsEvent.locationInWindow(), null);
	if (!view.isFlipped ()) {
		location.y = view.bounds().height - location.y;
	}
	event.x = (int) location.x;
	event.y = (int) location.y;
	setInputState (event, nsEvent, SWT.Touch);
	NSSet allTouchesSet = nsEvent.touchesMatchingPhase(OS.NSTouchPhaseAny, null);
	long /*int*/ touchCount = allTouchesSet.count();
	Touch touches[] = new Touch[(int)/*64*/touchCount];
	int currTouchIndex = 0;

	// Process removed/cancelled touches first.
	NSArray endedTouches = nsEvent.touchesMatchingPhase(OS.NSTouchPhaseEnded | OS.NSTouchPhaseCancelled, null).allObjects();

	for (int i = 0; i < endedTouches.count(); i++) {
		NSTouch touch = new NSTouch(endedTouches.objectAtIndex(i).id);
		NSObject identity = new NSObject(OS.objc_msgSend(touch.id, OS.sel_identity));
		NSTouch endedTouch = findTouchWithId(currentTouches, identity);
		if (endedTouch != null) currentTouches.removeObject(endedTouch);
		touches[currTouchIndex++] = touchStateFromNSTouch(touch);
	}

	if (currentTouches.count() == 0) display.touchCounter = 0;

	// Process touches in progress or starting.
	NSArray activeTouches = nsEvent.touchesMatchingPhase(OS.NSTouchPhaseBegan | OS.NSTouchPhaseMoved | OS.NSTouchPhaseStationary, null).allObjects();

	for (int i = 0; i < activeTouches.count(); i++) {
		NSTouch touch = new NSTouch(activeTouches.objectAtIndex(i).id);
		NSObject identity = new NSObject(OS.objc_msgSend(touch.id, OS.sel_identity));
		NSTouch activeTouch = findTouchWithId(currentTouches, identity);
		if (activeTouch == null) currentTouches.addObject(touch);
		touches[currTouchIndex++] = touchStateFromNSTouch(touch);
	}

	if (activeTouches.count() != currentTouches.count()) {
		/**
		 * Bug in Cocoa. Under some situations we don't get the NSTouchPhaseEnded/Cancelled notification. Most commonly this happens
		 * if a 4-finger gesture occurs and the application switcher appears. Workaround is to generate a TOUCHSTATE_UP for the
		 * orphaned touch.
		 */
		for (long /*int*/ j = currentTouches.count() - 1; j >= 0 ; j--) {
			NSTouch touch = new NSTouch(currentTouches.objectAtIndex(j).id);
			NSObject identity = new NSObject(OS.objc_msgSend(touch.id, OS.sel_identity));
			NSTouch activeTouch = findTouchWithId(activeTouches, identity);
			if (activeTouch == null) {
				Touch fakeTouchUp = touchStateFromNSTouch(touch);
				fakeTouchUp.state = SWT.TOUCHSTATE_UP;

				if (currTouchIndex == touches.length) {
					Touch newTouchStates[] = new Touch[touches.length + 1];
					System.arraycopy(touches, 0, newTouchStates, 0, touches.length);
					touches = newTouchStates;
				}

				touches[currTouchIndex++] = fakeTouchUp;
				currentTouches.removeObject(activeTouch);
			}
		}
	}

	event.touches = touches;
	postEvent (SWT.Touch, event);
	return true;
}

@Override
void touchesBeganWithEvent (long /*int*/ id, long /*int*/ sel, long /*int*/ event) {
	if (!touchEvent(id, sel, event)) return;
	super.touchesBeganWithEvent(id, sel, event);
}

@Override
void touchesCancelledWithEvent (long /*int*/ id, long /*int*/ sel, long /*int*/ event) {
	if (!touchEvent(id, sel, event)) return;
	super.touchesCancelledWithEvent(id, sel, event);
}

@Override
void touchesEndedWithEvent (long /*int*/ id, long /*int*/ sel, long /*int*/ event) {
	if (!touchEvent(id, sel, event)) return;
	super.touchesEndedWithEvent(id, sel, event);
}

@Override
void touchesMovedWithEvent (long /*int*/ id, long /*int*/ sel, long /*int*/ event) {
	if (!touchEvent(id, sel, event)) return;
	super.touchesMovedWithEvent(id, sel, event);
}

boolean translateTraversal (int key, NSEvent theEvent, boolean [] consume) {
	int detail = SWT.TRAVERSE_NONE;
	int code = traversalCode (key, theEvent);
	boolean all = false;
	switch (key) {
		case 53: /* Esc */ {
			all = true;
			detail = SWT.TRAVERSE_ESCAPE;
			break;
		}
		case 76: /* KP Enter */
		case 36: /* Return */ {
			all = true;
			detail = SWT.TRAVERSE_RETURN;
			break;
		}
		case 48: /* Tab */ {
			long /*int*/ modifiers = theEvent.modifierFlags ();
			boolean next = (modifiers & OS.NSShiftKeyMask) == 0;
			detail = next ? SWT.TRAVERSE_TAB_NEXT : SWT.TRAVERSE_TAB_PREVIOUS;
			break;
		}
		case 126: /* Up arrow */
		case 123: /* Left arrow */
		case 125: /* Down arrow */
		case 124: /* Right arrow */ {
			boolean next = key == 125 /* Down arrow */ || key == 124 /* Right arrow */;
			detail = next ? SWT.TRAVERSE_ARROW_NEXT : SWT.TRAVERSE_ARROW_PREVIOUS;
			break;
		}
		case 116: /* Page up */
		case 121: /* Page down */ {
			all = true;
			long /*int*/ modifiers = theEvent.modifierFlags ();
			if ((modifiers & OS.NSControlKeyMask) == 0) return false;
			detail = key == 121 /* Page down */ ? SWT.TRAVERSE_PAGE_NEXT : SWT.TRAVERSE_PAGE_PREVIOUS;
			break;
		}
		default:
			return false;
	}
	Event event = new Event ();
	event.doit = consume [0] = (code & detail) != 0;
	event.detail = detail;
	if (!setKeyState (event, SWT.Traverse, theEvent)) return false;
	Shell shell = getShell ();
	Control control = this;
	do {
		if (control.traverse (event)) return true;
		if (!event.doit && control.hooks (SWT.Traverse)) {
			return false;
		}
		if (control == shell) return false;
		control = control.parent;
	} while (all && control != null);
	return false;
}

int traversalCode (int key, NSEvent theEvent) {
	int code = SWT.TRAVERSE_RETURN | SWT.TRAVERSE_TAB_NEXT | SWT.TRAVERSE_TAB_PREVIOUS | SWT.TRAVERSE_PAGE_NEXT | SWT.TRAVERSE_PAGE_PREVIOUS;
	Shell shell = getShell ();
	if (shell.parent != null) code |= SWT.TRAVERSE_ESCAPE;
	return code;
}

boolean traverseMnemonic (char key) {
	return false;
}

/**
 * Performs a platform traversal action corresponding to a <code>KeyDown</code> event.
 *
 * <p>Valid traversal values are
 * <code>SWT.TRAVERSE_NONE</code>, <code>SWT.TRAVERSE_MNEMONIC</code>,
 * <code>SWT.TRAVERSE_ESCAPE</code>, <code>SWT.TRAVERSE_RETURN</code>,
 * <code>SWT.TRAVERSE_TAB_NEXT</code>, <code>SWT.TRAVERSE_TAB_PREVIOUS</code>,
 * <code>SWT.TRAVERSE_ARROW_NEXT</code>, <code>SWT.TRAVERSE_ARROW_PREVIOUS</code>,
 * <code>SWT.TRAVERSE_PAGE_NEXT</code> and <code>SWT.TRAVERSE_PAGE_PREVIOUS</code>.
 * If <code>traversal</code> is <code>SWT.TRAVERSE_NONE</code> then the Traverse
 * event is created with standard values based on the KeyDown event.  If
 * <code>traversal</code> is one of the other traversal constants then the Traverse
 * event is created with this detail, and its <code>doit</code> is taken from the
 * KeyDown event.
 * </p>
 *
 * @param traversal the type of traversal, or <code>SWT.TRAVERSE_NONE</code> to compute
 * this from <code>event</code>
 * @param event the KeyDown event
 *
 * @return <code>true</code> if the traversal succeeded
 *
 * @exception IllegalArgumentException <ul>
 *   <li>ERROR_NULL_ARGUMENT if the event is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @since 3.6
 */
public boolean traverse (int traversal, Event event) {
	checkWidget ();
	if (event == null) error (SWT.ERROR_NULL_ARGUMENT);
	return traverse (traversal, event.character, event.keyCode, event.keyLocation, event.stateMask, event.doit);
}

/**
 * Performs a platform traversal action corresponding to a <code>KeyDown</code> event.
 *
 * <p>Valid traversal values are
 * <code>SWT.TRAVERSE_NONE</code>, <code>SWT.TRAVERSE_MNEMONIC</code>,
 * <code>SWT.TRAVERSE_ESCAPE</code>, <code>SWT.TRAVERSE_RETURN</code>,
 * <code>SWT.TRAVERSE_TAB_NEXT</code>, <code>SWT.TRAVERSE_TAB_PREVIOUS</code>,
 * <code>SWT.TRAVERSE_ARROW_NEXT</code>, <code>SWT.TRAVERSE_ARROW_PREVIOUS</code>,
 * <code>SWT.TRAVERSE_PAGE_NEXT</code> and <code>SWT.TRAVERSE_PAGE_PREVIOUS</code>.
 * If <code>traversal</code> is <code>SWT.TRAVERSE_NONE</code> then the Traverse
 * event is created with standard values based on the KeyDown event.  If
 * <code>traversal</code> is one of the other traversal constants then the Traverse
 * event is created with this detail, and its <code>doit</code> is taken from the
 * KeyDown event.
 * </p>
 *
 * @param traversal the type of traversal, or <code>SWT.TRAVERSE_NONE</code> to compute
 * this from <code>event</code>
 * @param event the KeyDown event
 *
 * @return <code>true</code> if the traversal succeeded
 *
 * @exception IllegalArgumentException <ul>
 *   <li>ERROR_NULL_ARGUMENT if the event is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @since 3.6
 */
public boolean traverse (int traversal, KeyEvent event) {
	checkWidget ();
	if (event == null) error (SWT.ERROR_NULL_ARGUMENT);
	return traverse (traversal, event.character, event.keyCode, event.keyLocation, event.stateMask, event.doit);
}

boolean traverse (int traversal, char character, int keyCode, int keyLocation, int stateMask, boolean doit) {
	if (traversal == SWT.TRAVERSE_NONE) {
		switch (keyCode) {
			case SWT.ESC: {
				traversal = SWT.TRAVERSE_ESCAPE;
				doit = true;
				break;
			}
			case SWT.CR: {
				traversal = SWT.TRAVERSE_RETURN;
				doit = true;
				break;
			}
			case SWT.ARROW_DOWN:
			case SWT.ARROW_RIGHT: {
				traversal = SWT.TRAVERSE_ARROW_NEXT;
				doit = false;
				break;
			}
			case SWT.ARROW_UP:
			case SWT.ARROW_LEFT: {
				traversal = SWT.TRAVERSE_ARROW_PREVIOUS;
				doit = false;
				break;
			}
			case SWT.TAB: {
				traversal = (stateMask & SWT.SHIFT) != 0 ? SWT.TRAVERSE_TAB_PREVIOUS : SWT.TRAVERSE_TAB_NEXT;
				doit = true;
				break;
			}
			case SWT.PAGE_DOWN: {
				if ((stateMask & SWT.CTRL) != 0) {
					traversal = SWT.TRAVERSE_PAGE_NEXT;
					doit = true;
				}
				break;
			}
			case SWT.PAGE_UP: {
				if ((stateMask & SWT.CTRL) != 0) {
					traversal = SWT.TRAVERSE_PAGE_PREVIOUS;
					doit = true;
				}
				break;
			}
			default: {
				/* keyCode does not have a corresponding traversal action */
				return false;
			}
		}
	}

	Event event = new Event ();
	event.character = character;
	event.detail = traversal;
	event.doit = doit;
	event.keyCode = keyCode;
	event.keyLocation = keyLocation;
	event.stateMask = stateMask;
	Shell shell = getShell ();

	boolean all = false;
	switch (traversal) {
		case SWT.TRAVERSE_ESCAPE:
		case SWT.TRAVERSE_RETURN:
		case SWT.TRAVERSE_PAGE_NEXT:
		case SWT.TRAVERSE_PAGE_PREVIOUS: {
			all = true;
			// FALL THROUGH
		}
		case SWT.TRAVERSE_ARROW_NEXT:
		case SWT.TRAVERSE_ARROW_PREVIOUS:
		case SWT.TRAVERSE_TAB_NEXT:
		case SWT.TRAVERSE_TAB_PREVIOUS: {
			/* traversal is a valid traversal action */
			break;
		}
		case SWT.TRAVERSE_MNEMONIC: /* not supported on OS X */
			// FALL THROUGH
		default: {
			/* traversal is not a valid traversal action */
			return false;
		}
	}

	Control control = this;
	do {
		if (control.traverse (event)) return true;
		if (!event.doit && control.hooks (SWT.Traverse)) return false;
		if (control == shell) return false;
		control = control.parent;
	} while (all && control != null);
	return false;
}

/**
 * Based on the argument, perform one of the expected platform
 * traversal action. The argument should be one of the constants:
 * <code>SWT.TRAVERSE_ESCAPE</code>, <code>SWT.TRAVERSE_RETURN</code>,
 * <code>SWT.TRAVERSE_TAB_NEXT</code>, <code>SWT.TRAVERSE_TAB_PREVIOUS</code>,
 * <code>SWT.TRAVERSE_ARROW_NEXT</code>, <code>SWT.TRAVERSE_ARROW_PREVIOUS</code>,
 * <code>SWT.TRAVERSE_PAGE_NEXT</code> and <code>SWT.TRAVERSE_PAGE_PREVIOUS</code>.
 *
 * @param traversal the type of traversal
 * @return true if the traversal succeeded
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public boolean traverse (int traversal) {
	checkWidget();
	Event event = new Event ();
	event.doit = true;
	event.detail = traversal;
	return traverse (event);
}

boolean traverse (Event event) {
	sendEvent (SWT.Traverse, event);
	if (isDisposed ()) return true;
	if (!event.doit) return false;
	switch (event.detail) {
		case SWT.TRAVERSE_NONE:				return true;
		case SWT.TRAVERSE_ESCAPE:			return traverseEscape ();
		case SWT.TRAVERSE_RETURN:			return traverseReturn ();
		case SWT.TRAVERSE_TAB_NEXT:			return traverseGroup (true);
		case SWT.TRAVERSE_TAB_PREVIOUS:		return traverseGroup (false);
		case SWT.TRAVERSE_ARROW_NEXT:		return traverseItem (true);
		case SWT.TRAVERSE_ARROW_PREVIOUS:	return traverseItem (false);
		case SWT.TRAVERSE_MNEMONIC:			return traverseMnemonic (event);
		case SWT.TRAVERSE_PAGE_NEXT:		return traversePage (true);
		case SWT.TRAVERSE_PAGE_PREVIOUS:	return traversePage (false);
	}
	return false;
}

boolean traverseEscape () {
	return false;
}

boolean traverseGroup (boolean next) {
	Control root = computeTabRoot ();
	Widget group = computeTabGroup ();
	Widget [] list = root.computeTabList ();
	int length = list.length;
	int index = 0;
	while (index < length) {
		if (list [index] == group) break;
		index++;
	}
	/*
	* It is possible (but unlikely), that application
	* code could have disposed the widget in focus in
	* or out events.  Ensure that a disposed widget is
	* not accessed.
	*/
	if (index == length) return false;
	int start = index, offset = (next) ? 1 : -1;
	while ((index = ((index + offset + length) % length)) != start) {
		Widget widget = list [index];
		if (!widget.isDisposed () && widget.setTabGroupFocus ()) {
			return true;
		}
	}
	if (group.isDisposed ()) return false;
	return group.setTabGroupFocus ();
}

boolean traverseItem (boolean next) {
	Control [] children = parent._getChildren ();
	int length = children.length;
	int index = 0;
	while (index < length) {
		if (children [index] == this) break;
		index++;
	}
	/*
	* It is possible (but unlikely), that application
	* code could have disposed the widget in focus in
	* or out events.  Ensure that a disposed widget is
	* not accessed.
	*/
	if (index == length) return false;
	int start = index, offset = (next) ? 1 : -1;
	while ((index = (index + offset + length) % length) != start) {
		Control child = children [index];
		if (!child.isDisposed () && child.isTabItem ()) {
			if (child.setTabItemFocus ()) return true;
		}
	}
	return false;
}

boolean traverseReturn () {
	return false;
}

boolean traversePage (boolean next) {
	return false;
}

boolean traverseMnemonic (Event event) {
	return false;
}

/**
 * Forces all outstanding paint requests for the widget
 * to be processed before this method returns. If there
 * are no outstanding paint request, this method does
 * nothing.
 * <p>
 * Note: This method does not cause a redraw.
 * </p>
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see #redraw()
 * @see #redraw(int, int, int, int, boolean)
 * @see PaintListener
 * @see SWT#Paint
 */
public void update () {
	checkWidget();
	update (false);
}

void update (boolean all) {
//	checkWidget();
	if (isResizing()) return;
	if (display.inPaint) return;
	Shell shell = getShell();
	NSWindow window = shell.deferFlushing && shell.scrolling ? view.window() : null;
	try {
		if (window != null) {
			window.retain();
			window.disableFlushWindow();
		}
		//TODO - not all
		view.displayIfNeeded ();
	} finally {
		if (window != null) {
			window.enableFlushWindow();
			window.release();
		}
	}
}

void updateBackgroundColor () {
	Control control = findBackgroundControl ();
	if (control == null) control = this;
	double /*float*/ [] color = control.background != null ? control.background : control.defaultBackground().handle;
	NSColor nsColor = NSColor.colorWithDeviceRed(color[0], color[1], color[2], color[3]);
	setBackgroundColor (nsColor);
}

void updateBackgroundImage () {
	Control control = findBackgroundControl ();
	Image image = control != null ? control.backgroundImage : backgroundImage;
	setBackgroundImage (image != null ? image.handle : null);
}

void updateBackgroundMode () {
	int oldState = state & PARENT_BACKGROUND;
	checkBackground ();
	if (oldState != (state & PARENT_BACKGROUND)) {
		setBackground ();
	}
}

@Override
void resetCursorRects (long /*int*/ id, long /*int*/ sel) {
	if (isEnabled ()) callSuper (id, sel);
}

@Override
void updateTrackingAreas (long /*int*/ id, long /*int*/ sel) {
	if (isEnabled ()) callSuper (id, sel);
}

void updateCursorRects (boolean enabled) {
	updateCursorRects (enabled, view);
}

void updateCursorRects (boolean enabled, NSView widget) {
	if (enabled) {
		widget.resetCursorRects ();
		widget.updateTrackingAreas ();
	} else {
		widget.discardCursorRects ();
		NSArray areas = widget.trackingAreas ();
		for (int i = 0; i < areas.count(); i++) {
			widget.removeTrackingArea (new NSTrackingArea (areas.objectAtIndex (i)));
		}
	}
}

void updateLayout (boolean all) {
	/* Do nothing */
}

static double /*float*/ calcDiff (double /*float*/ component, double /*float*/ factor, boolean wantDarker) {
	if (wantDarker) {
		return component * -1 * factor;
	} else {
		return (1f - component) * factor;
	}
}

static double /*float*/ [] getLighterOrDarkerColor (double /*float*/ [] pixel, double /*float*/ factor, boolean wantDarker) {
	double /*float*/ red = pixel[0];
	double /*float*/ green = pixel[1];
	double /*float*/ blue = pixel[2];
	red += calcDiff(red, factor, wantDarker);
	green += calcDiff(green, factor, wantDarker);
	blue += calcDiff(blue, factor, wantDarker);
	return new double /*float*/ [] { red, green, blue, pixel[3] };
}

/**
 * @return luma according to ITU BT.709: Y = 0.2126 R + 0.7152 G + 0.0722 B
 */
static double luma (double[] rgbColor) {
	return 0.2126f * rgbColor[0] + 0.7152f * rgbColor[1] + 0.0722f * rgbColor[2];
}
}
