/*******************************************************************************
 * Copyright (c) 2000, 2016 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.swt.widgets;

import java.util.*;

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

/**
 * Instances of this class represent the "windows"
 * which the desktop or "window manager" is managing.
 * Instances that do not have a parent (that is, they
 * are built using the constructor, which takes a
 * <code>Display</code> as the argument) are described
 * as <em>top level</em> shells. Instances that do have
 * a parent are described as <em>secondary</em> or
 * <em>dialog</em> shells.
 * <p>
 * Instances are always displayed in one of the maximized,
 * minimized or normal states:</p>
 * <ul>
 * <li>
 * When an instance is marked as <em>maximized</em>, the
 * window manager will typically resize it to fill the
 * entire visible area of the display, and the instance
 * is usually put in a state where it can not be resized
 * (even if it has style <code>RESIZE</code>) until it is
 * no longer maximized.
 * </li><li>
 * When an instance is in the <em>normal</em> state (neither
 * maximized or minimized), its appearance is controlled by
 * the style constants which were specified when it was created
 * and the restrictions of the window manager (see below).
 * </li><li>
 * When an instance has been marked as <em>minimized</em>,
 * its contents (client area) will usually not be visible,
 * and depending on the window manager, it may be
 * "iconified" (that is, replaced on the desktop by a small
 * simplified representation of itself), relocated to a
 * distinguished area of the screen, or hidden. Combinations
 * of these changes are also possible.
 * </li>
 * </ul>
 * <p>
 * The <em>modality</em> of an instance may be specified using
 * style bits. The modality style bits are used to determine
 * whether input is blocked for other shells on the display.
 * The <code>PRIMARY_MODAL</code> style allows an instance to block
 * input to its parent. The <code>APPLICATION_MODAL</code> style
 * allows an instance to block input to every other shell in the
 * display. The <code>SYSTEM_MODAL</code> style allows an instance
 * to block input to all shells, including shells belonging to
 * different applications.
 * </p><p>
 * Note: The styles supported by this class are treated
 * as <em>HINT</em>s, since the window manager for the
 * desktop on which the instance is visible has ultimate
 * control over the appearance and behavior of decorations
 * and modality. For example, some window managers only
 * support resizable windows and will always assume the
 * RESIZE style, even if it is not set. In addition, if a
 * modality style is not supported, it is "upgraded" to a
 * more restrictive modality style that is supported. For
 * example, if <code>PRIMARY_MODAL</code> is not supported,
 * it would be upgraded to <code>APPLICATION_MODAL</code>.
 * A modality style may also be "downgraded" to a less
 * restrictive style. For example, most operating systems
 * no longer support <code>SYSTEM_MODAL</code> because
 * it can freeze up the desktop, so this is typically
 * downgraded to <code>APPLICATION_MODAL</code>.</p>
 * <dl>
 * <dt><b>Styles:</b></dt>
 * <dd>BORDER, CLOSE, MIN, MAX, NO_MOVE, NO_TRIM, RESIZE, TITLE, ON_TOP, TOOL, SHEET</dd>
 * <dd>APPLICATION_MODAL, MODELESS, PRIMARY_MODAL, SYSTEM_MODAL</dd>
 * <dt><b>Events:</b></dt>
 * <dd>Activate, Close, Deactivate, Deiconify, Iconify</dd>
 * </dl>
 * <p>
 * Class <code>SWT</code> provides two "convenience constants"
 * for the most commonly required style combinations:</p>
 * <dl>
 * <dt><code>SHELL_TRIM</code></dt>
 * <dd>
 * the result of combining the constants which are required
 * to produce a typical application top level shell: (that
 * is, <code>CLOSE | TITLE | MIN | MAX | RESIZE</code>)
 * </dd>
 * <dt><code>DIALOG_TRIM</code></dt>
 * <dd>
 * the result of combining the constants which are required
 * to produce a typical application dialog shell: (that
 * is, <code>TITLE | CLOSE | BORDER</code>)
 * </dd>
 * </dl>
 * 
 * <p>
 * Note: Only one of the styles APPLICATION_MODAL, MODELESS,
 * PRIMARY_MODAL and SYSTEM_MODAL may be specified.
 * </p><p>
 * IMPORTANT: This class is <em>not</em> intended to be subclassed.
 * </p>
 *
 * @see Decorations
 * @see SWT
 * @see <a href="http://www.eclipse.org/swt/snippets/#shell">Shell 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.
 */
@SuppressWarnings({"rawtypes", "unchecked"})
public class Shell extends Decorations {
	NSWindow window;
	SWTWindowDelegate windowDelegate;
	long /*int*/ hostWindowClass;
	NSWindow hostWindow;
	long /*int*/ tooltipOwner, tooltipTag, tooltipUserData;
	int glContextCount;
	boolean opened, moved, resized, fullScreen, center, deferFlushing, scrolling, isPopup;
	Control lastActive;
	Rectangle normalBounds;
	boolean keyInputHappened;
	NSRect currentFrame;
	NSRect fullScreenFrame;
	ToolBar toolBar;
	Map windowEmbedCounts;
	MenuItem escMenuItem;

	static int DEFAULT_CLIENT_WIDTH = -1;
	static int DEFAULT_CLIENT_HEIGHT = -1;

/**
 * Constructs a new instance of this class. This is equivalent
 * to calling <code>Shell((Display) null)</code>.
 *
 * @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>
 */
public Shell () {
	this ((Display) null);
}

/**
 * Constructs a new instance of this class given only the style
 * value describing its behavior and appearance. This is equivalent
 * to calling <code>Shell((Display) null, style)</code>.
 * <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 style the style of control to construct
 *
 * @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#CLOSE
 * @see SWT#MIN
 * @see SWT#MAX
 * @see SWT#RESIZE
 * @see SWT#TITLE
 * @see SWT#TOOL
 * @see SWT#NO_TRIM
 * @see SWT#NO_MOVE
 * @see SWT#SHELL_TRIM
 * @see SWT#DIALOG_TRIM
 * @see SWT#ON_TOP
 * @see SWT#MODELESS
 * @see SWT#PRIMARY_MODAL
 * @see SWT#APPLICATION_MODAL
 * @see SWT#SYSTEM_MODAL
 * @see SWT#SHEET
 */
public Shell (int style) {
	this ((Display) null, style);
}

/**
 * Constructs a new instance of this class given only the display
 * to create it on. It is created with style <code>SWT.SHELL_TRIM</code>.
 * <p>
 * Note: Currently, null can be passed in for the display argument.
 * This has the effect of creating the shell on the currently active
 * display if there is one. If there is no current display, the
 * shell is created on a "default" display. <b>Passing in null as
 * the display argument is not considered to be good coding style,
 * and may not be supported in a future release of SWT.</b>
 * </p>
 *
 * @param display the display to create the shell on
 *
 * @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>
 */
public Shell (Display display) {
	this (display, SWT.SHELL_TRIM);
}

/**
 * Constructs a new instance of this class given the display
 * to create it on 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><p>
 * Note: Currently, null can be passed in for the display argument.
 * This has the effect of creating the shell on the currently active
 * display if there is one. If there is no current display, the
 * shell is created on a "default" display. <b>Passing in null as
 * the display argument is not considered to be good coding style,
 * and may not be supported in a future release of SWT.</b>
 * </p>
 *
 * @param display the display to create the shell on
 * @param style the style of control to construct
 *
 * @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#CLOSE
 * @see SWT#MIN
 * @see SWT#MAX
 * @see SWT#RESIZE
 * @see SWT#TITLE
 * @see SWT#TOOL
 * @see SWT#NO_TRIM
 * @see SWT#NO_MOVE
 * @see SWT#SHELL_TRIM
 * @see SWT#DIALOG_TRIM
 * @see SWT#ON_TOP
 * @see SWT#MODELESS
 * @see SWT#PRIMARY_MODAL
 * @see SWT#APPLICATION_MODAL
 * @see SWT#SYSTEM_MODAL
 * @see SWT#SHEET
 */
public Shell (Display display, int style) {
	this (display, null, style, 0, false);
}

Shell (Display display, Shell parent, int style, long /*int*/handle, boolean embedded) {
	super ();
	checkSubclass ();
	if (display == null) display = Display.getCurrent ();
	if (display == null) display = Display.getDefault ();
	if (!display.isValidThread ()) {
		error (SWT.ERROR_THREAD_INVALID_ACCESS);
	}
	if (parent != null && parent.isDisposed ()) {
		error (SWT.ERROR_INVALID_ARGUMENT);
	}
	if (!Display.getSheetEnabled ()) {
		this.center = parent != null && (style & SWT.SHEET) != 0;
	}
	this.style = checkStyle (parent, style);
	this.parent = parent;
	this.display = display;
	if (handle != 0) {
		if (embedded) {
			view = new NSView(handle);
		} else {
			window = new NSWindow(handle);
			state |= FOREIGN_HANDLE;
		}
	}
	reskinWidget();
	createWidget ();
}

/**
 * Constructs a new instance of this class given only its
 * parent. It is created with style <code>SWT.DIALOG_TRIM</code>.
 * <p>
 * Note: Currently, null can be passed in for the parent.
 * This has the effect of creating the shell on the currently active
 * display if there is one. If there is no current display, the
 * shell is created on a "default" display. <b>Passing in null as
 * the parent is not considered to be good coding style,
 * and may not be supported in a future release of SWT.</b>
 * </p>
 *
 * @param parent a shell which will be the parent of the new instance
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_INVALID_ARGUMENT - if the parent is disposed</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>
 */
public Shell (Shell parent) {
	this (parent, SWT.DIALOG_TRIM);
}

/**
 * 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><p>
 * Note: Currently, null can be passed in for the parent.
 * This has the effect of creating the shell on the currently active
 * display if there is one. If there is no current display, the
 * shell is created on a "default" display. <b>Passing in null as
 * the parent is not considered to be good coding style,
 * and may not be supported in a future release of SWT.</b>
 * </p>
 *
 * @param parent a shell which will be the parent of the new instance
 * @param style the style of control to construct
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_INVALID_ARGUMENT - if the parent is disposed</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#CLOSE
 * @see SWT#MIN
 * @see SWT#MAX
 * @see SWT#RESIZE
 * @see SWT#TITLE
 * @see SWT#NO_TRIM
 * @see SWT#NO_MOVE
 * @see SWT#SHELL_TRIM
 * @see SWT#DIALOG_TRIM
 * @see SWT#ON_TOP
 * @see SWT#TOOL
 * @see SWT#MODELESS
 * @see SWT#PRIMARY_MODAL
 * @see SWT#APPLICATION_MODAL
 * @see SWT#SYSTEM_MODAL
 * @see SWT#SHEET
 */
public Shell (Shell parent, int style) {
	this (parent != null ? parent.display : null, parent, style, 0, false);
}

/**
 * Invokes platform specific functionality to allocate a new shell
 * that is not embedded.
 * <p>
 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
 * API for <code>Shell</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 display the display for the shell
 * @param handle the handle for the shell
 * @return a new shell object containing the specified display and handle
 *
 * @noreference This method is not intended to be referenced by clients.
 *
 * @since 3.3
 */
public static Shell internal_new (Display display, long /*int*/ handle) {
	return new Shell (display, null, SWT.NO_TRIM, handle, false);
}

/**
 * Invokes platform specific functionality to allocate a new shell
 * that is 'embedded'.  In this case, the handle represents an NSView
 * that acts as an embedded SWT Shell in an AWT Canvas.
 * <p>
 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
 * API for <code>Shell</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 display the display for the shell
 * @param handle the handle for the shell
 * @return a new shell object containing the specified display and handle
 *
 * @noreference This method is not intended to be referenced by clients.
 *
 * @since 3.5
 */
public static Shell cocoa_new (Display display, long /*int*/ handle) {
	return new Shell (display, null, SWT.NO_TRIM, handle, true);
}

static int checkStyle (Shell parent, int style) {
	style = Decorations.checkStyle (style);
	style &= ~SWT.TRANSPARENT;
	int mask = SWT.SYSTEM_MODAL | SWT.APPLICATION_MODAL | SWT.PRIMARY_MODAL;
	if ((style & SWT.SHEET) != 0) {
		if (Display.getSheetEnabled ()) {
			style &= ~(SWT.CLOSE | SWT.TITLE | SWT.MIN | SWT.MAX);
			if (parent == null) {
				style &= ~SWT.SHEET;
				style |= SWT.SHELL_TRIM;
			}
		} else {
			style &= ~SWT.SHEET;
			style |= parent == null ? SWT.SHELL_TRIM : SWT.DIALOG_TRIM;
		}
		if ((style & mask) == 0) {
			style |= parent == null ? SWT.APPLICATION_MODAL : SWT.PRIMARY_MODAL;
		}
	}
	int bits = style & ~mask;
	if ((style & SWT.SYSTEM_MODAL) != 0) return bits | SWT.SYSTEM_MODAL;
	if ((style & SWT.APPLICATION_MODAL) != 0) return bits | SWT.APPLICATION_MODAL;
	if ((style & SWT.PRIMARY_MODAL) != 0) return bits | SWT.PRIMARY_MODAL;
	return bits;
}

@Override
boolean accessibilityIsIgnored(long /*int*/ id, long /*int*/ sel) {
	// The content view of a shell is always ignored.
	if (id == view.id) return true;
	return super.accessibilityIsIgnored(id, sel);
}

/**
 * Adds the listener to the collection of listeners who will
 * be notified when operations are performed on the receiver,
 * by sending the listener one of the messages defined in the
 * <code>ShellListener</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 ShellListener
 * @see #removeShellListener
 */
public void addShellListener(ShellListener listener) {
	checkWidget();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	TypedListener typedListener = new TypedListener (listener);
	addListener(SWT.Activate,typedListener);
	addListener(SWT.Close,typedListener);
	addListener(SWT.Deactivate,typedListener);
	addListener(SWT.Iconify,typedListener);
	addListener(SWT.Deiconify,typedListener);
}

void attachObserversToWindow(NSWindow newWindow) {
	if (newWindow == null || newWindow.id == 0) return;
	long /*int*/ newHostWindowClass = OS.object_getClass(newWindow.id);
	long /*int*/ sendEventImpl = OS.class_getMethodImplementation(newHostWindowClass, OS.sel_sendEvent_);
	if (sendEventImpl == Display.windowCallback3.getAddress()) return;
	hostWindow = newWindow;
	hostWindow.retain();
	long /*int*/ embeddedSubclass = display.createWindowSubclass(newHostWindowClass, "SWTAWTWindow", true);
	OS.object_setClass(hostWindow.id, embeddedSubclass);
	display.addWidget (hostWindow, this);
	hostWindowClass = newHostWindowClass;

	if (windowEmbedCounts == null) windowEmbedCounts = new HashMap();
	Integer embedCount = (Integer) windowEmbedCounts.get(hostWindow);
	if (embedCount == null) {
		embedCount = Integer.valueOf(0);
	}
	embedCount = Integer.valueOf(embedCount.intValue() + 1);
	windowEmbedCounts.put(hostWindow, embedCount);

	// Register for notifications. An embedded shell has no control over the host window,
	// so it isn't correct to install a delegate.
	NSNotificationCenter defaultCenter = NSNotificationCenter.defaultCenter();
	defaultCenter.addObserver(windowDelegate, OS.sel_windowDidBecomeKey_, OS.NSWindowDidBecomeKeyNotification, hostWindow);
	defaultCenter.addObserver(windowDelegate, OS.sel_windowDidDeminiaturize_, OS.NSWindowDidDeminiaturizeNotification, hostWindow);
	defaultCenter.addObserver(windowDelegate, OS.sel_windowDidMiniaturize_, OS.NSWindowDidMiniaturizeNotification, hostWindow);
	defaultCenter.addObserver(windowDelegate, OS.sel_windowDidMove_, OS.NSWindowDidMoveNotification, hostWindow);
	defaultCenter.addObserver(windowDelegate, OS.sel_windowDidResize_, OS.NSWindowDidResizeNotification, hostWindow);
	defaultCenter.addObserver(windowDelegate, OS.sel_windowDidResignKey_, OS.NSWindowDidResignKeyNotification, hostWindow);
	defaultCenter.addObserver(windowDelegate, OS.sel_windowWillClose_, OS.NSWindowWillCloseNotification, hostWindow);
}

@Override
void becomeKeyWindow (long /*int*/ id, long /*int*/ sel) {
	Shell modal = getModalShell();
	if (modal != null && modal.window != null) {
		modal.window.makeKeyAndOrderFront(null);
		return;
	}
	Display display = this.display;
	display.keyWindow = view.window();
	super.becomeKeyWindow(id, sel);
	display.checkFocus();
	display.keyWindow = null;
}

@Override
void bringToTop (boolean force) {
	if (getMinimized ()) return;
	if (force) {
		forceActive ();
	} else {
		setActive ();
	}
}

@Override
boolean canBecomeKeyWindow (long /*int*/ id, long /*int*/ sel) {
	if (isPopup) return false;
	// Only answer if SWT created the window.
	if (window != null) {
		if ((style & SWT.NO_FOCUS) != 0) {
			NSEvent nsEvent = NSApplication.sharedApplication().currentEvent();
			if (nsEvent != null && nsEvent.type() == OS.NSLeftMouseDown) {
				NSView contentView = window.contentView();
				if (contentView != null) {
					NSView view = contentView.hitTest(nsEvent.locationInWindow());
					if (view == contentView) return false;
				}
			}
		}
		long /*int*/ styleMask = window.styleMask();
		if (styleMask == OS.NSBorderlessWindowMask || (styleMask & (OS.NSNonactivatingPanelMask | OS.NSDocModalWindowMask | OS.NSResizableWindowMask)) != 0) return true;
	}
	return super.canBecomeKeyWindow (id, sel);
}

@Override
void checkOpen () {
	if (!opened) resized = false;
}

void center () {
	if (parent == null) return;
	Rectangle rect = getBounds ();
	Rectangle parentRect = display.map (parent, null, parent.getClientArea());
	int x = Math.max (parentRect.x, parentRect.x + (parentRect.width - rect.width) / 2);
	int y = Math.max (parentRect.y, parentRect.y + (parentRect.height - rect.height) / 2);
	Rectangle monitorRect = parent.getMonitor ().getClientArea();
	if (x + rect.width > monitorRect.x + monitorRect.width) {
		x = Math.max (monitorRect.x, monitorRect.x + monitorRect.width - rect.width);
	} else {
		x = Math.max (x, monitorRect.x);
	}
	if (y + rect.height > monitorRect.y + monitorRect.height) {
		y = Math.max (monitorRect.y, monitorRect.y + monitorRect.height - rect.height);
	} else {
		y = Math.max (y, monitorRect.y);
	}
	setLocation (x, y);
}

@Override
void clearDeferFlushing (long /*int*/ id, long /*int*/ sel) {
	deferFlushing = false;
	scrolling = false;
	if (window != null) window.flushWindowIfNeeded();
}

/**
 * Requests that the window manager close the receiver in
 * the same way it would be closed when the user clicks on
 * the "close box" or performs some other platform specific
 * key or mouse combination that indicates the window
 * should be removed.
 *
 * @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#Close
 * @see #dispose
 */
public void close () {
	checkWidget();
	closeWidget (false);
}

void closeWidget (boolean force) {
	if (display.isDisposed()) return;
	Event event = new Event ();
	sendEvent (SWT.Close, event);
	if ((force || event.doit) && !isDisposed ()) dispose ();
}

@Override
public Point computeSize (int wHint, int hHint, boolean changed) {
	Point size = super.computeSize (wHint, hHint, changed);
	if (toolBar != null) {
		if (wHint == SWT.DEFAULT && toolBar.itemCount > 0) {
			Point tbSize = toolBar.computeSize (SWT.DEFAULT, SWT.DEFAULT);
			size.x = Math.max (tbSize.x, size.x);
		}
	}
	return size;
}

@Override
public Rectangle computeTrim (int x, int y, int width, int height) {
	checkWidget();
	Rectangle trim = super.computeTrim(x, y, width, height);
	NSRect rect = new NSRect ();
	rect.x = trim.x;
	rect.y = trim.y;
	rect.width = trim.width;
	rect.height = trim.height;
	if (window != null) {
		if (!_getFullScreen() && !fixResize()) {
			double /*float*/ h = rect.height;
			rect = window.frameRectForContentRect(rect);
			rect.y += h-rect.height;
		}
	}
	return new Rectangle ((int)rect.x, (int)rect.y, (int)rect.width, (int)rect.height);
}

@Override
void createHandle () {
	state |= HIDDEN;
	if (window == null && view == null) {
		int styleMask = OS.NSBorderlessWindowMask;
		if ((style & (SWT.TOOL | SWT.SHEET)) != 0) {
			window = (NSWindow) new SWTPanel().alloc();
			if ((style & SWT.SHEET) != 0) {
				styleMask |= OS.NSDocModalWindowMask;
			} else {
				styleMask |= OS.NSUtilityWindowMask | OS.NSNonactivatingPanelMask;
			}
 		} else {
 			window = (NSWindow) new SWTWindow().alloc ();
 		}
		if ((style & SWT.NO_TRIM) == 0) {
			if ((style & SWT.TITLE) != 0) styleMask |= OS.NSTitledWindowMask;
			if ((style & SWT.CLOSE) != 0) styleMask |= OS.NSClosableWindowMask;
			if ((style & SWT.MIN) != 0) styleMask |= OS.NSMiniaturizableWindowMask;
			if ((style & SWT.MAX) != 0) styleMask |= OS.NSResizableWindowMask;
			if ((style & SWT.RESIZE) != 0) styleMask |= OS.NSResizableWindowMask;
		}
		NSScreen screen = null;
		NSScreen primaryScreen = new NSScreen(NSScreen.screens().objectAtIndex(0));
		if (parent != null) screen = parentWindow ().screen();
		if (screen == null) screen = primaryScreen;
		window = window.initWithContentRect(new NSRect(), styleMask, OS.NSBackingStoreBuffered, (style & SWT.ON_TOP) != 0, screen);
		if ((style & (SWT.NO_TRIM | SWT.BORDER | SWT.SHELL_TRIM)) == 0 || (style & (SWT.TOOL | SWT.SHEET)) != 0) {
			window.setHasShadow (true);
		}
		if ((style & SWT.NO_MOVE) != 0 && (OS.VERSION_MMB >= OS.VERSION_MMB(10, 6, 0))) {
			window.setMovable(false);
		}
		if ((style & SWT.TOOL) != 0) {
			// Feature in Cocoa: NSPanels that use NSUtilityWindowMask are always promoted to the floating window layer.
			// Fix is to call setFloatingPanel:NO, which turns off this behavior.
			((NSPanel)window).setFloatingPanel(false);
			// By default, panels hide on deactivation.
			((NSPanel)window).setHidesOnDeactivate(false);
			// Normally a panel doesn't become key unless something inside it needs to be first responder.
			// TOOL shells always become key, so disable that behavior.
			((NSPanel)window).setBecomesKeyOnlyIfNeeded(false);
		}
		window.setReleasedWhenClosed(true);
		if ((style & SWT.NO_TRIM) == 0) {
			NSSize size = window.minSize();
			size.width = NSWindow.minFrameWidthWithTitle(NSString.string(), styleMask);
			window.setMinSize(size);
		}
		if (fixResize ()) {
			if (window.respondsToSelector(OS.sel_setMovable_)) {
				OS.objc_msgSend(window.id, OS.sel_setMovable_, 0);
			}
		}
		if (OS.VERSION_MMB >= OS.VERSION_MMB(10, 12, 0)) {
			/*
			 * In macOS 10.12, a new system preference "prefer tabs when opening documents"
			 * has been added which causes automatic tabbing of windows in Eclipse.
			 * Disable automatic window tabbing, but setting the NSWindow.allowsAutomaticWindowTabbing
			 * property to false.
			 */
			OS.objc_msgSend(OS.class_NSWindow, OS.sel_setAllowsAutomaticWindowTabbing_, false);
		}
		display.cascadeWindow(window, screen);
		NSRect screenFrame = screen.frame();
		double /*float*/ width = screenFrame.width * 5 / 8, height = screenFrame.height * 5 / 8;;
		NSRect frame = window.frame();
		NSRect primaryFrame = primaryScreen.frame();
		frame.y = primaryFrame.height - ((primaryFrame.height - (frame.y + frame.height)) + height);
		frame.width = width;
		frame.height = height;
		window.setFrame(frame, false);
		if ((style & SWT.ON_TOP) != 0) {
			window.setLevel(OS.NSStatusWindowLevel);
		}
		super.createHandle ();
		topView ().setHidden (true);
	} else {
		state &= ~HIDDEN;

		if (window != null) {
			// In the FOREIGN_HANDLE case, 'window' is an NSWindow created on our behalf.
			// It may already have a content view, so if it does, grab and retain, since we release()
			// the view at disposal time.  Otherwise, create a new 'view' that will be used as the window's
			// content view in setZOrder.
			view = window.contentView();

			if (view == null) {
				super.createHandle();
			} else {
				view.retain();
			}
		} else {
			// In the embedded case, 'view' is already set to the NSView we should add the window's content view to as a subview.
			// In that case we will hold on to the foreign view, create our own SWTCanvasView (which overwrites 'view') and then
			// add it to the foreign view.
			NSView parentView = view;
			super.createHandle();
			parentView.addSubview(topView());
		}

		style |= SWT.NO_BACKGROUND;
	}

	windowDelegate = (SWTWindowDelegate)new SWTWindowDelegate().alloc().init();

	if (window == null) {
		NSWindow hostWindow = view.window();
		attachObserversToWindow(hostWindow);
	} else {
		int behavior = 0;
		if (parent != null) behavior |= OS.NSWindowCollectionBehaviorMoveToActiveSpace;
		if (OS.VERSION >= 0x1070) {
			if (parent == null) {
				if ((style & SWT.TOOL) != 0) {
					behavior = OS.NSWindowCollectionBehaviorFullScreenAuxiliary;
				} else {
					behavior = OS.NSWindowCollectionBehaviorFullScreenPrimary;
				}
			}
		}
		if (behavior != 0) window.setCollectionBehavior(behavior);
		window.setAcceptsMouseMovedEvents(true);
		window.setDelegate(windowDelegate);
	}

	if (OS.VERSION < 0x1060) {
		// Force a WindowRef to be created for this window so we can use
		// FindWindow() (see Display.findControl())
		if (window != null) window.windowRef();
	}

	NSWindow fieldEditorWindow = window;
	if (fieldEditorWindow == null) fieldEditorWindow = view.window();
	id id = fieldEditorWindow.fieldEditor (true, null);
	if (id != null) {
		OS.object_setClass (id.id, OS.objc_getClass ("SWTEditorView"));
		new NSTextView(id).setAllowsUndo(true);
	}

}

void deferFlushing () {
	deferFlushing = true;
	view.performSelector(OS.sel_clearDeferFlushing, null, 0.0, display.runLoopModes());
}

@Override
void deregister () {
	super.deregister ();
	if (window != null) display.removeWidget (window);
	if (windowDelegate != null) display.removeWidget (windowDelegate);
}

@Override
void destroyWidget () {
	NSWindow window = this.window;
	if (window != null) window.retain();
	Display display = this.display;
	NSView view = topView();
	if (view != null) view.retain();

	boolean sheet = (style & (SWT.SHEET)) != 0;
	releaseHandle ();
	if (window != null) {
		if (sheet) {
			NSApplication application = NSApplication.sharedApplication();
			application.endSheet(window, 0);
		}
		window.close();
	} else if (view != null) {
		view.removeFromSuperview();
	}
	if (view != null) view.release();

	// If another shell is not going to become active, clear the menu bar.
	// Don't modify the menu bar if we are an embedded Shell, though.
	if (window != null) {
		if (!display.isDisposed () && display.getShells ().length == 0) {
			display.setMenuBar (null);
		}
		window.release();
	}
}

@Override
void drawBackground (long /*int*/ id, NSGraphicsContext context, NSRect rect) {
	if (id != view.id) return;
	if (regionPath != null && background == null) {
		context.saveGraphicsState();
		NSColor.windowBackgroundColor().setFill();
		NSBezierPath.fillRect(rect);
		context.restoreGraphicsState();
		return;
	}
	super.drawBackground (id, context, rect);
}

@Override
Control findBackgroundControl () {
	return background != null || backgroundImage != null ? this : null;
}

@Override
Composite findDeferredControl () {
	return layoutCount > 0 ? this : null;
}

@Override
Cursor findCursor () {
	return cursor;
}

boolean fixResize () {
	/*
	* Feature in Cocoa.  It is not possible to have a resizable window
	* without the title bar.  The fix is to resize the content view on
	* top of the title bar.
	*
	* Never do this when the shell is embedded, because the window belongs to the AWT.
	*/
	if (window == null) return false;
	if ((style & SWT.NO_TRIM) == 0) {
		if ((style & SWT.RESIZE) != 0 && (style & (SWT.SHEET | SWT.TITLE | SWT.CLOSE | SWT.MIN | SWT.MAX)) == 0) {
			return true;
		}
	}
	return false;
}

void fixShell (Shell newShell, Control control) {
	if (this == newShell) return;
	if (control == lastActive) setActiveControl (null);
}

/**
 * If the receiver is visible, moves it to the top of the
 * drawing order for the display on which it was created
 * (so that all other shells on that display, which are not
 * the receiver's children will be drawn behind it) and forces
 * the window manager to make the shell active.
 *
 * @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.0
 * @see Control#moveAbove
 * @see Control#setFocus
 * @see Control#setVisible
 * @see Display#getActiveShell
 * @see Decorations#setDefaultButton(Button)
 * @see Shell#open
 * @see Shell#setActive
 */
public void forceActive () {
	checkWidget ();
	if (!isVisible()) return;
	if (window == null) return;
	makeKeyAndOrderFront ();
	NSApplication application = NSApplication.sharedApplication ();
	application.activateIgnoringOtherApps (true);
}

/**
 * Returns the receiver's alpha value. The alpha value
 * is between 0 (transparent) and 255 (opaque).
 *
 * @return the alpha value
 *
 * @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 int getAlpha () {
	checkWidget ();
	if (window == null) return 255;
	return (int)(window.alphaValue() * 255);
}

@Override
public Rectangle getBounds () {
	checkWidget();
	if (window != null) {
		NSRect frame = window.frame();
		double /*float*/ y = display.getPrimaryFrame().height - (int)(frame.y + frame.height);
		return new Rectangle ((int)frame.x, (int)y, (int)frame.width, (int)frame.height);
	} else {
		NSRect frame = view.frame();
		// Start from view's origin, (0, 0)
		NSPoint pt = new NSPoint();
		NSRect primaryFrame = display.getPrimaryFrame();
		if (!view.isFlipped ()) {
			pt.y = view.bounds().height - pt.y;
		}
		pt = view.convertPoint_toView_(pt, null);
		pt = view.window().convertBaseToScreen(pt);
		pt.y = primaryFrame.height - pt.y;
		return new Rectangle((int)pt.x, (int)pt.y, (int)frame.width, (int)frame.height);
	}
}

@Override
public Rectangle getClientArea () {
	checkWidget();
	NSRect rect;
	if (window != null) {
		if (!fixResize ()) {
			rect = window.contentView().frame();
		} else {
			rect = window.frame();
		}
	} else {
		rect = topView().frame();
	}
	int width = (int)rect.width, height = (int)rect.height;
	if (scrollView != null) {
		NSSize size = new NSSize();
		size.width = width;
		size.height = height;
		size = NSScrollView.contentSizeForFrameSize(size, (style & SWT.H_SCROLL) != 0, (style & SWT.V_SCROLL) != 0, OS.NSNoBorder);
		width = (int)size.width;
		height = (int)size.height;
	}
	return new Rectangle (0, 0, width, height);
}

/**
 * Returns <code>true</code> if the receiver is currently
 * in fullscreen state, and false otherwise.
 * <p>
 *
 * @return the fullscreen 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.4
 */
public boolean getFullScreen () {
	checkWidget();
	return _getFullScreen ();
}

boolean _getFullScreen () {
	if ((window.collectionBehavior() & OS.NSWindowCollectionBehaviorFullScreenPrimary) != 0) {
		return (window.styleMask() & OS.NSFullScreenWindowMask) != 0 ? true : false;
	}
	return fullScreen;
}

/**
 * Returns the receiver's input method editor mode. This
 * will be the result of bitwise OR'ing together one or
 * more of the following constants defined in class
 * <code>SWT</code>:
 * <code>NONE</code>, <code>ROMAN</code>, <code>DBCS</code>,
 * <code>PHONETIC</code>, <code>NATIVE</code>, <code>ALPHA</code>.
 *
 * @return the IME mode
 *
 * @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
 */
public int getImeInputMode () {
	checkWidget();
	return SWT.NONE;
}

@Override
public Point getLocation () {
	checkWidget();

	if (window != null) {
		NSRect frame = window.frame();
		double /*float*/ y = display.getPrimaryFrame().height - (int)(frame.y + frame.height);
		return new Point ((int)frame.x, (int)y);
	} else {
		// Start from view's origin, (0, 0)
		NSPoint pt = new NSPoint();
		NSRect primaryFrame = display.getPrimaryFrame();
		if (!view.isFlipped ()) {
			pt.y = view.bounds().height - pt.y;
		}
		pt = view.convertPoint_toView_(pt, null);
		pt = view.window().convertBaseToScreen(pt);
		pt.y = primaryFrame.height - pt.y;
		return new Point((int)pt.x, (int)pt.y);
	}
}

@Override
public boolean getMaximized () {
	checkWidget();
	if (window == null) return false;
	return !_getFullScreen() && window.isZoomed();
}

Shell getModalShell () {
	Shell shell = null;
	Shell [] modalShells = display.modalShells;
	if (modalShells != null) {
		int bits = SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL;
		int index = modalShells.length;
		while (--index >= 0) {
			Shell modal = modalShells [index];
			if (modal != null) {
				if ((modal.style & bits) != 0) {
					Control control = this;
					while (control != null) {
						if (control == modal) break;
						control = control.parent;
					}
					if (control != modal) return modal;
					break;
				}
				if ((modal.style & SWT.PRIMARY_MODAL) != 0) {
					if (shell == null) shell = getShell ();
					if (modal.parent == shell) return modal;
				}
			}
		}
	}
	return null;
}

/**
 * Gets the receiver's modified state.
 *
 * @return <code>true</code> if the receiver is marked as modified, 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>
 *
 * @since 3.5
 */
public boolean getModified () {
	checkWidget ();
	return window.isDocumentEdited ();
}

@Override
public boolean getMinimized () {
	checkWidget();
	if (!getVisible ()) return super.getMinimized ();
	if (window == null) return false;
	return window.isMiniaturized();
}

/**
 * Returns a point describing the minimum receiver's size. The
 * x coordinate of the result is the minimum width of the receiver.
 * The y coordinate of the result is the minimum 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>
 *
 * @since 3.1
 */
public Point getMinimumSize () {
	checkWidget();
	if (window == null) return new Point(0, 0);
	NSSize size = window.minSize();
	return new Point((int)size.width, (int)size.height);
}

/**
 * Returns the region that defines the shape of the shell,
 * or <code>null</code> if the shell has the default shape.
 *
 * @return the region that defines the shape of the shell, 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.0
 *
 */
@Override
public Region getRegion () {
	/* This method is needed for the @since 3.0 Javadoc */
	checkWidget ();
	return region;
}

@Override
public Shell getShell () {
	checkWidget();
	return this;
}

/**
 * Returns an array containing all shells which are
 * descendants of the receiver.
 * <p>
 * @return the dialog shells
 *
 * @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 Shell [] getShells () {
	checkWidget();
	int count = 0;
	Shell [] shells = display.getShells ();
	for (int i=0; i<shells.length; i++) {
		Control shell = shells [i];
		do {
			shell = shell.parent;
		} while (shell != null && shell != this);
		if (shell == this) count++;
	}
	int index = 0;
	Shell [] result = new Shell [count];
	for (int i=0; i<shells.length; i++) {
		Control shell = shells [i];
		do {
			shell = shell.parent;
		} while (shell != null && shell != this);
		if (shell == this) {
			result [index++] = shells [i];
		}
	}
	return result;
}

@Override
public Point getSize () {
	checkWidget();
	NSRect frame = (window != null ? window.frame() : view.frame());
	return new Point ((int) frame.width, (int) frame.height);
}

@Override
float getThemeAlpha () {
	return 1;
}

/**
 * Returns a ToolBar object representing the tool bar that can be shown in the receiver's
 * trim. This will return <code>null</code> if the platform does not support tool bars that
 * are not part of the content area of the shell, or if the Shell's style does not support
 * having a tool bar.
 * <p>
 *
 * @return a ToolBar object representing the Shell's tool bar, 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.7
 */
public ToolBar getToolBar() {
	checkWidget();
	if ((style & SWT.NO_TRIM) == 0) {
		if (toolBar == null) toolBar = new ToolBar(this, SWT.HORIZONTAL | SWT.SMOOTH, true);
	}
	return toolBar;
}

@Override
boolean hasBorder () {
	return false;
}

@Override
boolean hasRegion () {
	return region != null;
}

@Override
void helpRequested(long /*int*/ id, long /*int*/ sel, long /*int*/ theEvent) {
	Control control = display.getFocusControl();
	while (control != null) {
		if (control.hooks (SWT.Help)) {
			control.postEvent (SWT.Help);
			break;
		}
		control = control.parent;
	}
}

@Override
void invalidateVisibleRegion () {
	resetVisibleRegion ();
	if (toolBar != null) toolBar.resetVisibleRegion();
	invalidateChildrenVisibleRegion ();
}

@Override
boolean isDrawing () {
	return getDrawing ();
}

@Override
public boolean isEnabled () {
	checkWidget();
	return getEnabled ();
}

@Override
boolean isEnabledCursor () {
	return true;
}

@Override
boolean isResizing () {
	return (state & RESIZING) != 0;
}

@Override
boolean isTransparent() {
	return false;
}

@Override
public boolean isVisible () {
	checkWidget();
	return getVisible ();
}

@Override
boolean makeFirstResponder (long /*int*/ id, long /*int*/ sel, long /*int*/ responder) {
	Display display = this.display;
	boolean result = super.makeFirstResponder(id, sel, responder);
	if (!display.isDisposed()) display.checkFocus();
	return result;
}

void makeKeyAndOrderFront() {
	/*
	* Bug in Cocoa.  If a child window becomes the key window when its
	* parent window is miniaturized, the parent window appears as if
	* restored to its full size without actually being restored. In this
	* case the parent window does become active when its child is closed
	* and the user is forced to restore the window from the dock.
	* The fix is to be sure that the parent window is deminiaturized before
	* making the child a key window.
	*/
	if (parent != null) {
		NSWindow parentWindow = parentWindow ();
		if (parentWindow.isMiniaturized()) parentWindow.deminiaturize(null);
	}
	window.makeKeyAndOrderFront (null);
}

@Override
void mouseMoved(long /*int*/ id, long /*int*/ sel, long /*int*/ theEvent) {
	super.mouseMoved(id, sel, theEvent);

	/**
	 * Bug in AWT. WebViews need to have a mouseMove: handled by the window so it can generate
	 * DOMMouseMove events and also provide proper feedback to the window. However, the top-level
	 * view in an AWT window does not have the NSWindow as a next responder.
	 *
	 * Fix is to forward the message to the window if this is an embedded shell (that is, window == null)
	 */
	if (id == view.id && window == null) {
		view.window().mouseMoved(new NSEvent(theEvent));
	}
}

@Override
void noResponderFor(long /*int*/ id, long /*int*/ sel, long /*int*/ selector) {
	/**
	 * Feature in Cocoa.  If the selector is keyDown and nothing has handled the event
	 * a system beep is generated.  There's no need to beep, as many keystrokes in the SWT
	 * are listened for and acted upon but not explicitly handled in a keyDown handler.  Fix is to
	 * not call the default implementation when a keyDown: is being handled.
	 */
	if (selector != OS.sel_keyDown_) super.noResponderFor(id, sel, selector);
}

/**
 * Moves the receiver to the top of the drawing order for
 * the display on which it was created (so that all other
 * shells on that display, which are not the receiver's
 * children will be drawn behind it), marks it visible,
 * sets the focus and asks the window manager to make the
 * shell active.
 *
 * @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 Control#setFocus
 * @see Control#setVisible
 * @see Display#getActiveShell
 * @see Decorations#setDefaultButton(Button)
 * @see Shell#setActive
 * @see Shell#forceActive
 */
public void open () {
	checkWidget();
	int mask = SWT.PRIMARY_MODAL | SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL;
	if ((style & mask) != 0) {
		display.setModalShell (this);
	} else {
		updateModal ();
	}
	bringToTop (false);
	setWindowVisible (true, true);
	if (isDisposed ()) return;
	if (!restoreFocus () && !traverseGroup (true)) {
		// if the parent shell is minimized, setting focus will cause it
		// to become unminimized.
		if (parent == null || !parentWindow ().isMiniaturized()) {
			setFocus ();
		}
	}
}

NSWindow parentWindow () {
	if (parent == null) return null;
	return parent.view.window();
}

@Override
public boolean print (GC gc) {
	checkWidget ();
	if (gc == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (gc.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
	return false;
}

@Override
void register () {
	/*
	 * Note that if there are multiple SWT_AWT shells only the last one created
	 * will be associated with the NSWindow. This is okay, and intentional because
	 * all of the NSWindow overrides operate on the entire window.
	 */
	super.register ();
	if (window != null) display.addWidget (window, this);
	if (windowDelegate != null) display.addWidget (windowDelegate, this);
}

@Override
void releaseChildren (boolean destroy) {
	Shell [] shells = getShells ();
	for (int i=0; i<shells.length; i++) {
		Shell shell = shells [i];
		if (shell != null && !shell.isDisposed ()) {
			shell.dispose ();
		}
	}
	super.releaseChildren (destroy);
}

@Override
void releaseHandle () {
	if (window != null) window.setDelegate(null);
	removeObserversFromWindow();
	if (windowDelegate != null) windowDelegate.release();
	windowDelegate = null;

	super.releaseHandle ();
	window = null;
}

@Override
void releaseParent () {
	/* Do nothing */
}

@Override
void releaseWidget () {
	super.releaseWidget ();
	if (toolBar != null) {
		toolBar.dispose();
		toolBar = null;
	}
	if (tooltipTag != 0) {
		view.window().contentView().removeToolTip(tooltipTag);
		tooltipTag = 0;
	}
	display.clearModal (this);
	updateParent (false);
	display.updateQuitMenu();
	lastActive = null;
}

void removeObserversFromWindow () {
	NSNotificationCenter.defaultCenter().removeObserver(windowDelegate);

	if (hostWindow != null) {
		Integer embedCount = (Integer) windowEmbedCounts.get(hostWindow);
		if (embedCount == null) {
			embedCount = Integer.valueOf(0);
		}
		embedCount = Integer.valueOf(embedCount.intValue() - 1);
		windowEmbedCounts.put(hostWindow, embedCount);

		if (embedCount.intValue() <= 0) {
			windowEmbedCounts.remove(hostWindow);
			if (hostWindowClass != 0) OS.object_setClass(hostWindow.id, hostWindowClass);
			display.removeWidget(hostWindow);
			hostWindow.release();
			hostWindow = null;
			hostWindowClass = 0;
		}
	}
}


/**
 * Removes the listener from the collection of listeners who will
 * be notified when operations are performed on the receiver.
 *
 * @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 ShellListener
 * @see #addShellListener
 */
public void removeShellListener(ShellListener listener) {
	checkWidget();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (eventTable == null) return;
	eventTable.unhook(SWT.Activate, listener);
	eventTable.unhook(SWT.Close, listener);
	eventTable.unhook(SWT.Deactivate, listener);
	eventTable.unhook(SWT.Iconify,listener);
	eventTable.unhook(SWT.Deiconify,listener);
}

@Override
public void requestLayout () {
	layout (null, SWT.DEFER);
}

@Override
void reskinChildren (int flags) {
	if (toolBar != null) toolBar.reskin(flags);
	Shell [] shells = getShells ();
	for (int i=0; i<shells.length; i++) {
		Shell shell = shells [i];
		if (shell != null) shell.reskin (flags);
	}
	super.reskinChildren (flags);
}

void sendToolTipEvent (boolean enter) {
	if (!isVisible()) return;
	NSWindow eventWindow = view.window();
	if (tooltipTag == 0) {
		NSView view = eventWindow.contentView();
		tooltipTag = view.addToolTipRect(new NSRect(), eventWindow, 0);
		if (tooltipTag != 0) {
			NSTrackingArea trackingArea = new NSTrackingArea(tooltipTag);
			id owner = trackingArea.owner();
			if (owner != null) tooltipOwner = owner.id;
			id userInfo = trackingArea.userInfo();
			if (userInfo != null) {
				tooltipUserData = userInfo.id;
			} else {
				long /*int*/ [] value = new long /*int*/ [1];
				OS.object_getInstanceVariable(tooltipTag, new byte[]{'_','u', 's', 'e', 'r', 'I', 'n', 'f', 'o'}, value);
				tooltipUserData = value[0];
			}
		}
	}
	if (tooltipTag == 0 || tooltipOwner == 0 || tooltipUserData == 0) return;
	NSPoint pt = eventWindow.convertScreenToBase(NSEvent.mouseLocation());
	NSEvent event = NSEvent.enterExitEventWithType(enter ? OS.NSMouseEntered : OS.NSMouseExited, pt, 0, 0, eventWindow.windowNumber(), null, 0, tooltipTag, tooltipUserData);
	OS.objc_msgSend(tooltipOwner, enter ? OS.sel_mouseEntered_ : OS.sel_mouseExited_, event.id);
}

/**
 * If the receiver is visible, moves it to the top of the
 * drawing order for the display on which it was created
 * (so that all other shells on that display, which are not
 * the receiver's children will be drawn behind it) and asks
 * the window manager to make the shell active
 *
 * @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.0
 * @see Control#moveAbove
 * @see Control#setFocus
 * @see Control#setVisible
 * @see Display#getActiveShell
 * @see Decorations#setDefaultButton(Button)
 * @see Shell#open
 * @see Shell#setActive
 */
public void setActive () {
	if (window == null) return;
	checkWidget ();
	if (!isVisible()) return;
	makeKeyAndOrderFront ();
}

void setActiveControl (Control control) {
	setActiveControl (control, SWT.None);
}

void setActiveControl (Control control, int type) {
	if (control != null && control.isDisposed ()) control = null;
	if (lastActive != null && lastActive.isDisposed ()) lastActive = null;
	if (lastActive == control) return;

	/*
	* Compute the list of controls to be activated and
	* deactivated by finding the first common parent
	* control.
	*/
	Control [] activate = (control == null) ? new Control[0] : control.getPath ();
	Control [] deactivate = (lastActive == null) ? new Control[0] : lastActive.getPath ();
	lastActive = control;
	int index = 0, length = Math.min (activate.length, deactivate.length);
	while (index < length) {
		if (activate [index] != deactivate [index]) break;
		index++;
	}

	/*
	* It is possible (but unlikely), that application
	* code could have destroyed some of the widgets. If
	* this happens, keep processing those widgets that
	* are not disposed.
	*/
	for (int i=deactivate.length-1; i>=index; --i) {
		if (!deactivate [i].isDisposed ()) {
			deactivate [i].sendEvent (SWT.Deactivate);
		}
	}
	for (int i=activate.length-1; i>=index; --i) {
		if (!activate [i].isDisposed ()) {
			Event event = new Event ();
			event.detail = type;
			activate [i].sendEvent (SWT.Activate, event);
		}
	}
}

/**
 * Sets the receiver's alpha value which must be
 * between 0 (transparent) and 255 (opaque).
 * <p>
 * This operation requires the operating system's advanced
 * widgets subsystem which may not be available on some
 * platforms.
 * </p>
 * @param alpha the alpha value
 *
 * @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 setAlpha (int alpha) {
	if (window == null) return;
	checkWidget ();
	alpha &= 0xFF;
	window.setAlphaValue (alpha / 255f);
}

@Override
void setBounds (int x, int y, int width, int height, boolean move, boolean resize) {
	if (window == null) {
		// Embedded shells aren't movable.
		if (move) return;
		if (resize) {
			NSSize frameSize = new NSSize();
			frameSize.width = width;
			frameSize.height = height;
			view.setFrameSize(frameSize);
			return;
		}
	}
	if (_getFullScreen ()) setFullScreen (false);
	boolean sheet = window.isSheet();
	if (sheet && move && !resize) return;
	int screenHeight = (int) display.getPrimaryFrame().height;
	NSRect frame = window.frame();
	if (!move) {
		x = (int)frame.x;
		y = screenHeight - (int)(frame.y + frame.height);
	}
	if (resize) {
		NSSize minSize = window.minSize();
		width = Math.max(width, (int)minSize.width);
		height = Math.max(height, (int)minSize.height);
	} else {
		width = (int)frame.width;
		height = (int)frame.height;
	}
	if (sheet) {
		y = screenHeight - (int)(frame.y + frame.height);
		NSRect parentRect = parent.getShell().window.frame();
		frame.width = width;
		frame.height = height;
		frame.x = parentRect.x + (parentRect.width - frame.width) / 2;
		frame.y = screenHeight - (int)(y + frame.height);
		window.setFrame(frame, isVisible(), true);
	} else {
		frame.x = x;
		frame.y = screenHeight - (int)(y + height);
		frame.width = width;
		frame.height = height;
		window.setFrame(frame, isVisible());
	}
}

@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);
	}
}

@Override
public void setEnabled (boolean enabled) {
	checkWidget();
	if (((state & DISABLED) == 0) == enabled) return;
	super.setEnabled (enabled);
	if (enabled && window != null && window.isMainWindow()) {
		if (!restoreFocus ()) traverseGroup (false);
	}
}

/**
 * Sets the full screen state of the receiver.
 * If the argument is <code>true</code> causes the receiver
 * to switch to the full screen state, and if the argument is
 * <code>false</code> and the receiver was previously switched
 * into full screen state, causes the receiver to switch back
 * to either the maximized or normal states.
 * <p>
 * Note: The result of intermixing calls to <code>setFullScreen(true)</code>,
 * <code>setMaximized(true)</code> and <code>setMinimized(true)</code> will
 * vary by platform. Typically, the behavior will match the platform user's
 * expectations, but not always. This should be avoided if possible.
 * </p>
 *
 * @param fullScreen the new fullscreen 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.4
 */
public void setFullScreen (boolean fullScreen) {
	checkWidget ();
	if (window == null) return;
	if (_getFullScreen () == fullScreen) return;

	if ((window.collectionBehavior() & OS.NSWindowCollectionBehaviorFullScreenPrimary) != 0) {
		OS.objc_msgSend(window.id, OS.sel_toggleFullScreen_, 0);
		return;
	}

	this.fullScreen = fullScreen;
	if (fullScreen) {
		currentFrame = window.frame();
		window.setShowsResizeIndicator(false); //only hides resize indicator
		if (window.respondsToSelector(OS.sel_setMovable_)) {
			OS.objc_msgSend(window.id, OS.sel_setMovable_, 0);
		}

		fullScreenFrame = NSScreen.mainScreen().frame();
		if (getMonitor().equals(display.getPrimaryMonitor ())) {
			if (menuBar != null) {
				double /*float*/ menuBarHt = NSStatusBar.systemStatusBar().thickness();
				fullScreenFrame.height -= menuBarHt;
				OS.SetSystemUIMode(OS.kUIModeContentHidden, 0);
			}
			else {
				OS.SetSystemUIMode(OS.kUIModeAllHidden, 0);
			}
		}
		window.setFrame(fullScreenFrame, true);
		NSRect contentViewFrame = new NSRect();
		contentViewFrame.width = fullScreenFrame.width;
		contentViewFrame.height = fullScreenFrame.height;
		window.contentView().setFrame(contentViewFrame);
	} else {
		window.setShowsResizeIndicator(true);
		if (window.respondsToSelector(OS.sel_setMovable_)) {
			OS.objc_msgSend(window.id, OS.sel_setMovable_, 1);
		}
		OS.SetSystemUIMode(OS.kUIModeNormal, 0);
		window.setFrame(currentFrame, true);
	}
}

@Override
public void setMenuBar (Menu menu) {
	checkWidget();
	super.setMenuBar (menu);
	if (display.getActiveShell () == this) {
		display.setMenuBar (menuBar);
	}
}

/**
 * Sets the input method editor mode to the argument which
 * should be the result of bitwise OR'ing together one or more
 * of the following constants defined in class <code>SWT</code>:
 * <code>NONE</code>, <code>ROMAN</code>, <code>DBCS</code>,
 * <code>PHONETIC</code>, <code>NATIVE</code>, <code>ALPHA</code>.
 *
 * @param mode the new IME mode
 *
 * @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
 */
public void setImeInputMode (int mode) {
	checkWidget();
}

@Override
public void setMaximized (boolean maximized) {
	checkWidget();
	super.setMaximized (maximized);
	if (window == null) return;
	if (window.isZoomed () == maximized) return;
	window.zoom (null);
}

@Override
public void setMinimized (boolean minimized) {
	checkWidget();
	super.setMinimized (minimized);
	if (window == null) return;
	if (!getVisible()) return;
	if (minimized) {
		window.miniaturize (null);
	} else {
		window.deminiaturize (null);
	}
}

/**
 * Sets the receiver's minimum size to the size specified by the arguments.
 * If the new minimum size is larger than the current size of the receiver,
 * the receiver is resized to the new minimum size.
 *
 * @param width the new minimum width for the receiver
 * @param height the new minimum 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>
 *
 * @since 3.1
 */
public void setMinimumSize (int width, int height) {
	checkWidget();
	if (window == null) return;
	NSSize size = new NSSize();
	size.width = width;
	size.height = height;
	window.setMinSize(size);
	NSRect frame = window.frame();
	if (width > frame.width || height > frame.height) {
		width = (int)(width > frame.width ? width : frame.width);
		height = (int)(height > frame.height ? height : frame.height);
		setBounds(0, 0, width, height, false, true);
	}
}

/**
 * Sets the receiver's minimum size to the size specified by the argument.
 * If the new minimum size is larger than the current size of the receiver,
 * the receiver is resized to the new minimum size.
 *
 * @param size the new minimum size 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>
 *
 * @since 3.1
 */
public void setMinimumSize (Point size) {
	checkWidget();
	if (size == null) error (SWT.ERROR_NULL_ARGUMENT);
	setMinimumSize (size.x, size.y);
}

/**
 * Sets the receiver's modified state as specified by the argument.
 *
 * @param modified the new modified state for the receiver
 *
 * </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.5
 */
public void setModified (boolean modified) {
	checkWidget ();
	window.setDocumentEdited (modified);
}

/**
 * Sets the shape of the shell to the region specified
 * by the argument.  When the argument is null, the
 * default shape of the shell is restored.  The shell
 * must be created with the style SWT.NO_TRIM in order
 * to specify a region.
 * <p>
 * NOTE: This method also sets the size of the shell. Clients should
 * not call {@link #setSize} or {@link #setBounds} on this shell.
 * Furthermore, the passed region should not be modified any more.
 * </p>
 *
 * @param region the region that defines the shape of the shell (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.0
 */
@Override
public void setRegion (Region region) {
	checkWidget ();
	if ((style & SWT.NO_TRIM) == 0) return;
	if (window == null) return;
	if (region != null) {
		if (region.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT);
		Rectangle bounds = region.getBounds();
		setSize(bounds.x + bounds.width, bounds.y + bounds.height);
	}
	this.region = region;
	if (regionPath != null) regionPath.release();
	regionPath = getPath(region);
	if (region != null) {
		window.setBackgroundColor(NSColor.clearColor());
	} else {
		window.setBackgroundColor(NSColor.windowBackgroundColor());
	}
	updateOpaque ();
	window.contentView().setNeedsDisplay(true);
	if (isVisible() && window.hasShadow()) {
		window.display();
		window.invalidateShadow();
	}
}

void setScrolling () {
	scrolling = true;
	view.performSelector(OS.sel_clearDeferFlushing, null, 0.0, display.runLoopModes());
}

@Override
public void setText (String string) {
	checkWidget();
	if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (window == null) return;
	super.setText (string);
	NSString str = NSString.stringWith(string);
	window.setTitle(str);
}

@Override
public void setVisible (boolean visible) {
	checkWidget();
	int mask = SWT.PRIMARY_MODAL | SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL;
	if ((style & mask) != 0) {
		if (visible) {
			display.setModalShell (this);
		} else {
			display.clearModal (this);
		}
	} else {
		updateModal ();
	}
	if (window == null) {
		super.setVisible(visible);
	} else {
		setWindowVisible (visible, false);
	}
}

void setWindowVisible (boolean visible, boolean key) {
	if (visible) {
		if ((state & HIDDEN) == 0) return;
		state &= ~HIDDEN;
	} else {
		if ((state & HIDDEN) != 0) return;
		state |= HIDDEN;
	}
	if (window != null && (window.isVisible() == visible)) return;
	if (visible) {
		display.clearPool ();
		if (center && !moved) {
			if (isDisposed ()) return;
			center ();
		}
		sendEvent (SWT.Show);
		if (isDisposed ()) return;
		topView ().setHidden (false);
		invalidateVisibleRegion();
		if (window != null) {
			if ((style & (SWT.SHEET)) != 0) {
				NSApplication application = NSApplication.sharedApplication();
				application.beginSheet(window, parentWindow (), null, 0, 0);
				if (OS.VERSION <= 0x1060 && window.respondsToSelector(OS.sel__setNeedsToUseHeartBeatWindow_)) {
					OS.objc_msgSend(window.id, OS.sel__setNeedsToUseHeartBeatWindow_, 0);
				}
			} else {
				// If the parent window is miniaturized, the window will be shown
				// when its parent is shown.
				boolean parentMinimized = parent != null && parentWindow ().isMiniaturized();
				if (!parentMinimized) {
					if (key && (style & SWT.NO_FOCUS) == 0) {
						makeKeyAndOrderFront ();
					} else {
						window.orderFront (null);
					}
					if (isDisposed()) return;
					if (minimized != window.isMiniaturized()) {
						if (minimized) {
							window.miniaturize (null);
						} else {
							window.deminiaturize (null);
						}
					}
				}
			}
		}
		if (isDisposed()) return;
		updateParent (visible);
		opened = true;
		if (!moved) {
			moved = true;
			sendEvent (SWT.Move);
			if (isDisposed ()) return;
		}
		if (!resized) {
			resized = true;
			sendEvent (SWT.Resize);
			if (isDisposed ()) return;
			if (layout != null) {
				markLayout (false, false);
				updateLayout (false);
			}
		}
	} else {
		updateParent (visible);
		if (window != null) {
			if ((style & (SWT.SHEET)) != 0) {
				NSApplication application = NSApplication.sharedApplication();
				application.endSheet(window, 0);
			}
			window.orderOut (null);
		}
		if (isDisposed()) return;
		topView ().setHidden (true);
		invalidateVisibleRegion();
		sendEvent (SWT.Hide);
	}

	if (isDisposed()) return;
	display.updateQuitMenu();

	if (isDisposed()) return;
	NSView[] hitView = new NSView[1];
	Control control = display.findControl (false, hitView);
	if (control != null && (!control.isActive() || !control.isEnabled())) control = null;
	Control trimControl = control;
	if (trimControl != null && trimControl.isTrim (hitView[0])) trimControl = null;
	display.checkEnterExit (trimControl, null, false);
}

@Override
void setZOrder () {
	if (scrollView != null) scrollView.setDocumentView (view);
	if (window == null) return;
	window.setContentView (scrollView != null ? scrollView : view);
	if (fixResize ()) {
		NSRect rect = window.frame();
		rect.x = rect.y = 0;
		window.contentView().setFrame(rect);
	}
}

@Override
void setZOrder (Control control, boolean above) {
	if (window == null) return;
	if (!getVisible ()) return;
	if (control == null) {
		if (above) {
			window.orderFront(null);
		} else {
			window.orderBack(null);
		}
	} else {
		NSWindow otherWindow = control.getShell().window;
		window.orderWindow(above ? OS.NSWindowAbove : OS.NSWindowBelow, otherWindow.windowNumber());
	}
}

@Override
boolean traverseEscape () {
	if (parent == null) return false;
	if (!isVisible () || !isEnabled ()) return false;
	close ();
	return true;
}

@Override
void updateCursorRects(boolean enabled) {
	super.updateCursorRects(enabled);
	if (toolBar != null) toolBar.updateCursorRects(enabled);
};

void updateModal () {
	// do nothing
}

void updateOpaque () {
	if (window == null) return;
	window.setOpaque (region == null && glContextCount == 0);
}

void updateParent (boolean visible) {
	if (window != null) {
		if (visible) {
			if (parent != null && parent.getVisible ()) {
				NSWindow parentWindow = display.modalPanel != null ? display.modalPanel : parentWindow ();
				parentWindow.addChildWindow (window, OS.NSWindowAbove);

				/**
				 * Feature in Cocoa: When a window is added as a child window,
				 * its window level resets to its parent's window level. So, we
				 * have to set the level for ON_TOP child window again.
				 */
				if ((style & SWT.ON_TOP) != 0) {
					window.setLevel(OS.NSStatusWindowLevel);
				} else if (OS.VERSION_MMB >= OS.VERSION_MMB(10, 11, 0)) {
					/*
					 * Feature in Cocoa on 10.11: Second-level child windows of
					 * a full-screen window are sometimes shown behind their
					 * parent window, although they take keyboard focus.
					 *
					 * The exact circumstances are unknown. Could only be
					 * reproduced when the app was launched with the Eclipse
					 * launcher. This hack is a workaround for
					 * https://bugs.eclipse.org/478975 .
					 */
					Shell parentShell = (Shell) parent;
					while (parentShell.parent != null) {
						parentShell = (Shell) parentShell.parent;
						if (parentShell._getFullScreen()) {
							window.setLevel(OS.NSSubmenuWindowLevel);
							break;
						}
					}
				}
			}
		} else {
			NSWindow parentWindow = window.parentWindow ();
			if (parentWindow != null) parentWindow.removeChildWindow (window);
		}
	}
	Shell [] shells = getShells ();
	for (int i = 0; i < shells.length; i++) {
		Shell shell = shells [i];
		if (shell.parent == this && shell.getVisible ()) {
			shell.updateParent (visible);
		}
	}
}

void updateSystemUIMode () {
	if ((window.collectionBehavior() & OS.NSWindowCollectionBehaviorFullScreenPrimary) != 0) return;
	if (!getMonitor ().equals (display.getPrimaryMonitor ())) return;
	int mode = display.systemUIMode, options = display.systemUIOptions;
	if (fullScreen) {
		mode = OS.kUIModeAllHidden;
		if (menuBar != null) {
			mode = OS.kUIModeContentHidden;
		}
		options = 0;
	}
	int[] uiMode = new int[1], uiOptions = new int[1];
	OS.GetSystemUIMode(uiMode, uiOptions);
	if (uiMode[0] != mode || uiOptions[0] != options) OS.SetSystemUIMode (mode, options);
	if (fullScreen)	window.setFrame(fullScreenFrame, true);
}

@Override
long /*int*/ view_stringForToolTip_point_userData (long /*int*/ id, long /*int*/ sel, long /*int*/ view, long /*int*/ tag, long /*int*/ point, long /*int*/ userData) {
	NSPoint pt = new NSPoint();
	OS.memmove (pt, point, NSPoint.sizeof);
	Control control = display.findControl (false);
	if (control == null) return 0;
	Widget target = control.findTooltip (new NSView (view).convertPoint_toView_ (pt, null));
	String string = target.tooltipText ();
	if (string == null) return 0;
	char[] chars = new char [string.length ()];
	string.getChars (0, chars.length, chars, 0);
	int length = fixMnemonic (chars);
	return NSString.stringWithCharacters (chars, length).id;
}

@Override
void viewWillMoveToWindow(long /*int*/ id, long /*int*/ sel, long /*int*/ newWindow) {
	if (window == null) {
		long /*int*/ currentWindow = hostWindow != null ? hostWindow.id : 0;
		if (currentWindow != 0) {
			removeObserversFromWindow();
		}
		if (newWindow != 0) {
			attachObserversToWindow(new NSWindow(newWindow));
		}
	}
}

@Override
void windowDidBecomeKey(long /*int*/ id, long /*int*/ sel, long /*int*/ notification) {
	if (window != null) {
		Display display = this.display;
		display.setMenuBar (menuBar);
	}
	sendEvent (SWT.Activate);
	if (isDisposed ()) return;
	if (!restoreFocus () && !traverseGroup (true)) setFocus ();
	if (isDisposed ()) return;
	if ((window.collectionBehavior() & OS.NSWindowCollectionBehaviorFullScreenPrimary) == 0) {
		Shell parentShell = this;
		while (parentShell.parent != null) {
			parentShell = (Shell) parentShell.parent;
			if (parentShell._getFullScreen ()) {
				break;
			}
		}
		if (!parentShell._getFullScreen () || menuBar != null) {
			updateSystemUIMode ();
		} else {
			parentShell.updateSystemUIMode ();
		}
	}
}

@Override
void windowDidDeminiturize(long /*int*/ id, long /*int*/ sel, long /*int*/ notification) {
	minimized = false;
	sendEvent(SWT.Deiconify);
}

@Override
void windowDidMiniturize(long /*int*/ id, long /*int*/ sel, long /*int*/ notification) {
	minimized = true;
	sendEvent(SWT.Iconify);
}

@Override
void windowDidMove(long /*int*/ id, long /*int*/ sel, long /*int*/ notification) {
	moved = true;
	sendEvent(SWT.Move);
}

@Override
void windowDidResize(long /*int*/ id, long /*int*/ sel, long /*int*/ notification) {
	if (((window.collectionBehavior() & OS.NSWindowCollectionBehaviorFullScreenPrimary) == 0) && fullScreen) {
		window.setFrame(fullScreenFrame, true);
		NSRect contentViewFrame = new NSRect();
		contentViewFrame.width = fullScreenFrame.width;
		contentViewFrame.height = fullScreenFrame.height;
		window.contentView().setFrame(contentViewFrame);
	}
	if (fixResize ()) {
		NSRect rect = window.frame ();
		rect.x = rect.y = 0;
		window.contentView ().setFrame (rect);
	}
	resized = true;
	sendEvent (SWT.Resize);
	if (isDisposed ()) return;
	if (layout != null) {
		markLayout (false, false);
		updateLayout (false);
	}
}

@Override
void windowDidResignKey(long /*int*/ id, long /*int*/ sel, long /*int*/ notification) {
	if (display.isDisposed()) return;
	sendEvent (SWT.Deactivate);
	if (isDisposed ()) return;
	setActiveControl (null);
	if (isDisposed ()) return;
	saveFocus();
}

@Override
void windowSendEvent (long /*int*/ id, long /*int*/ sel, long /*int*/ event) {
	NSEvent nsEvent = new NSEvent (event);
	int type = (int)/*64*/nsEvent.type ();
	switch (type) {
		case OS.NSLeftMouseDown:
		case OS.NSRightMouseDown:
		case OS.NSOtherMouseDown:
			display.clickCount = (int)(display.clickCountButton == nsEvent.buttonNumber() ? nsEvent.clickCount() : 1);
			display.clickCountButton = (int)nsEvent.buttonNumber();
			break;
		case OS.NSLeftMouseUp:
		case OS.NSRightMouseUp:
		case OS.NSOtherMouseUp:
		case OS.NSMouseMoved:
			NSView[] hitView = new NSView[1];
			Control control = display.findControl (false, hitView);
			if (control != null && (!control.isActive() || !control.isEnabled())) control = null;
			if (type == OS.NSMouseMoved) {
				Control trimControl = control;
				if (trimControl != null && trimControl.isTrim (hitView[0])) trimControl = null;
				display.checkEnterExit (trimControl, nsEvent, false);
				// Browser will send MouseMoved in response to a DOM event, so don't send it here.
				if (trimControl != null && (trimControl.state & WEBKIT_EVENTS_FIX) != 0) trimControl = null;
				if (trimControl != null) trimControl.sendMouseEvent (nsEvent, type, false);
			}

			// Tooltip updating: Find the widget under the cursor. If it changed, clear the tooltip from
			// the last tracked item and send a tooltip event to make it visible on the new widget.
			Widget target = null;
			if (control != null) {
				NSPoint eventPoint = nsEvent.locationInWindow();
				if (hitView[0] != null) {
					NSWindow eventWindow = nsEvent.window();

					// If a NSMouseMoved happens on an inactive window, convert the
					// event coordinates to the window of the target view.
					if (eventWindow != null && eventWindow != hitView[0].window()) {
						eventPoint = eventWindow.convertBaseToScreen(eventPoint);
						eventPoint = hitView[0].window().convertScreenToBase(eventPoint);
					}
				}
				target = control.findTooltip (eventPoint);
			}

			if (display.tooltipControl != control || display.tooltipTarget != target) {
				Control oldControl = display.tooltipControl;
				Shell oldShell = oldControl != null && !oldControl.isDisposed() ? oldControl.getShell() : null;
				Shell shell = control != null && !control.isDisposed() ? control.getShell() : null;
				if (oldShell != null) oldShell.sendToolTipEvent (false);
				if (shell != null) shell.sendToolTipEvent (true);
			}
			display.tooltipControl = control;
			display.tooltipTarget = target;
			break;

		case OS.NSKeyDown:
			/*
			* Feature in Cocoa.  For some reason, Cocoa does not perform accelerators
			* with ESC key code.  The fix is to perform the accelerators ourselves.
			*/
			if (display.escAsAcceleratorPresent && nsEvent.keyCode() == 53 /* ESC */) {
				if (escMenuItem == null || escMenuItem.getAccelerator() != SWT.ESC) {
					updateEscMenuItem();
				}
				if (escMenuItem != null) {
					Menu parentMenu = escMenuItem.getParent();
					if (parentMenu != null) {
						NSMenu escNSMenu = parentMenu.nsMenu;
						if (escNSMenu != null) {
							escNSMenu.performKeyEquivalent(nsEvent);
						}
					}
				}
			}
			/**
			 * Feature in cocoa.  Control+Tab, Ctrl+Shift+Tab, Ctrl+PageDown and Ctrl+PageUp are
			 * swallowed to handle native traversal. If we find that, force the key event to
			 * the first responder.
			 */
			if ((nsEvent.modifierFlags() & OS.NSControlKeyMask) != 0) {
				NSString chars = nsEvent.characters();

				if (chars != null && chars.length() == 1) {
					int firstChar = (int)/*64*/chars.characterAtIndex(0);

					// Shift-tab appears as control-Y.
					switch (firstChar) {
						case '\t':
						case 25:
						case OS.NSPageDownFunctionKey:
						case OS.NSPageUpFunctionKey:
							view.window().firstResponder().keyDown(nsEvent);
							return;
					}
				}
			}
			break;
	}

	// Window may have been disposed at this point.
	if (isDisposed()) return;
	super.windowSendEvent (id, sel, event);
}

private void updateEscMenuItem() {
	if (menuBar != null && !menuBar.isDisposed()){
		searchForEscMenuItem(menuBar);
	} else if (display.appMenuBar != null && !display.appMenuBar.isDisposed()) {
		searchForEscMenuItem(display.appMenuBar);
	}
}

private boolean searchForEscMenuItem(Menu menu) {
	if (menu == null || menu.isDisposed()) return false;
	MenuItem[] items = menu.getItems();
	if (items == null) return false;
	for (MenuItem item:items) {
		if (item == null || item.isDisposed()) {
			continue;
		} else if (item.getAccelerator() == SWT.ESC) {
			escMenuItem = item;
			return true;
		} else if ((item.getStyle() & SWT.CASCADE) != 0) {
			Menu subMenu = item.getMenu();
			if (searchForEscMenuItem(subMenu)) return true;
		}
	}
	return false;
}

@Override
boolean windowShouldClose(long /*int*/ id, long /*int*/ sel, long /*int*/ window) {
	if (isEnabled()) closeWidget (false);
	return false;
}

@Override
void windowWillClose(long /*int*/ id, long /*int*/ sel, long /*int*/ notification) {
	closeWidget(true);
}

}
