/*******************************************************************************
 * Copyright (c) 2000, 2008 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
 *******************************************************************************/
package org.eclipse.swt.widgets;


import org.eclipse.swt.internal.*;
import org.eclipse.swt.internal.cairo.*;
import org.eclipse.swt.internal.motif.*;
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;

/**
 * Instances of this class are controls which are capable
 * of containing other controls.
 * <dl>
 * <dt><b>Styles:</b></dt>
 * <dd>NO_BACKGROUND, NO_FOCUS, NO_MERGE_PAINTS, NO_REDRAW_RESIZE, NO_RADIO_GROUP, EMBEDDED, DOUBLE_BUFFERED</dd>
 * <dt><b>Events:</b></dt>
 * <dd>(none)</dd>
 * </dl>
 * <p>
 * Note: The <code>NO_BACKGROUND</code>, <code>NO_FOCUS</code>, <code>NO_MERGE_PAINTS</code>,
 * and <code>NO_REDRAW_RESIZE</code> styles are intended for use with <code>Canvas</code>.
 * They can be used with <code>Composite</code> if you are drawing your own, but their
 * behavior is undefined if they are used with subclasses of <code>Composite</code> other
 * than <code>Canvas</code>.
 * </p><p>
 * Note: The <code>CENTER</code> style, although undefined for composites, has the
 * same value as <code>EMBEDDED</code> which is used to embed widgets from other
 * widget toolkits into SWT.  On some operating systems (GTK, Motif), this may cause
 * the children of this composite to be obscured.
 * </p><p>
 * This class may be subclassed by custom control implementors
 * who are building controls that are constructed from aggregates
 * of other controls.
 * </p>
 *
 * @see Canvas
 * @see <a href="http://www.eclipse.org/swt/snippets/#composite">Composite snippets</a>
 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
 */
public class Composite extends Scrollable {
	Layout layout;
	public int embeddedHandle;
	int focusHandle, damagedRegion, clientWindow;
	Control [] tabList;
	int layoutCount, backgroundMode;
	
	static byte [] _XEMBED_INFO = Converter.wcsToMbcs (null, "_XEMBED_INFO", true);
	static byte[] _XEMBED = Converter.wcsToMbcs (null, "_XEMBED", true);

Composite () {
	/* 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 widget which will be the parent of the new instance (cannot be null)
 * @param style the style of widget 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>
 * </ul>
 *
 * @see SWT#NO_BACKGROUND
 * @see SWT#NO_FOCUS
 * @see SWT#NO_MERGE_PAINTS
 * @see SWT#NO_REDRAW_RESIZE
 * @see SWT#NO_RADIO_GROUP
 * @see SWT#EMBEDDED
 * @see SWT#DOUBLE_BUFFERED
 * @see Widget#getStyle
 */
public Composite (Composite parent, int style) {
	super (parent, style);
}
static int checkStyle (int style) {
	style &= ~SWT.TRANSPARENT;
	return style;
}
Control [] _getChildren () {
	int [] argList = {OS.XmNchildren, 0, OS.XmNnumChildren, 0};
	OS.XtGetValues (handle, argList, argList.length / 2);
	int ptr = argList [1], count = argList [3];
	if (count == 0 || ptr == 0) return new Control [0];
	int [] handles = new int [count];
	OS.memmove (handles, ptr, count * 4);
	int length = focusHandle != 0 ? count - 1 : count;
	Control [] children = new Control [length];
	int i = 0, j = 0;
	while (i < count) {
		int handle = handles [i];
		if (handle != 0) {
			Widget widget = display.getWidget (handle);
			if (widget != null && widget != this) {
				if (widget instanceof Control) {
					children [j++] = (Control) widget;
				}
			}
		}
		i++;
	}
	if (j == length) return children;
	Control [] newChildren = new Control [j];
	System.arraycopy (children, 0, newChildren, 0, j);
	return newChildren;
}
Control [] _getTabList () {
	if (tabList == null) return tabList;
	int count = 0;
	for (int i=0; i<tabList.length; i++) {
		if (!tabList [i].isDisposed ()) count++;
	}
	if (count == tabList.length) return tabList;
	Control [] newList = new Control [count];
	int index = 0;
	for (int i=0; i<tabList.length; i++) {
		if (!tabList [i].isDisposed ()) {
			newList [index++] = tabList [i];
		}
	}
	tabList = newList;
	return tabList;
}
public Point computeSize (int wHint, int hHint, boolean changed) {
	checkWidget();
	Point size;
	if (layout != null) {
		if ((wHint == SWT.DEFAULT) || (hHint == SWT.DEFAULT)) {
			changed |= (state & LAYOUT_CHANGED) != 0;
			size = layout.computeSize (this, wHint, hHint, changed);
			state &= ~LAYOUT_CHANGED;
		} else {
			size = new Point (wHint, hHint);
		}
	} else {
		size = minimumSize (wHint, hHint, changed);
	}
	if (size.x == 0) size.x = DEFAULT_WIDTH;
	if (size.y == 0) size.y = DEFAULT_HEIGHT;
	if (wHint != SWT.DEFAULT) size.x = wHint;
	if (hHint != SWT.DEFAULT) size.y = hHint;
	Rectangle trim = computeTrim (0, 0, size.x, size.y);
	return new Point (trim.width, trim.height);
}
Control [] computeTabList () {
	Control result [] = super.computeTabList ();
	if (result.length == 0) return result;
	Control [] list = tabList != null ? _getTabList () : _getChildren ();
	for (int i=0; i<list.length; i++) {
		Control child = list [i];
		Control [] childList = child.computeTabList ();
		if (childList.length != 0) {
			Control [] newResult = new Control [result.length + childList.length];
			System.arraycopy (result, 0, newResult, 0, result.length);
			System.arraycopy (childList, 0, newResult, result.length, childList.length);
			result = newResult;
		}
	}
	return result;
}
/**
 * Clears any data that has been cached by a Layout for all widgets that 
 * are in the parent hierarchy of the changed control up to and including the 
 * receiver.  If an ancestor does not have a layout, it is skipped.
 * 
 * @param changed an array of controls that changed state and require a recalculation of size
 * 
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_INVALID_ARGUMENT - if the changed array is null any of its controls are null or have been disposed</li> 
 *    <li>ERROR_INVALID_PARENT - if any control in changed is not in the widget tree of the receiver</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 changed (Control[] changed) {
	checkWidget ();
	if (changed == null) error (SWT.ERROR_INVALID_ARGUMENT);
	for (int i=0; i<changed.length; i++) {
		Control control = changed [i];
		if (control == null) error (SWT.ERROR_INVALID_ARGUMENT);
		if (control.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
		boolean ancestor = false;
		Composite composite = control.parent;
		while (composite != null) {
			ancestor = composite == this;
			if (ancestor) break;
			composite = composite.parent;
		}
		if (!ancestor) error (SWT.ERROR_INVALID_PARENT);
	}
	for (int i=0; i<changed.length; i++) {
		Control child = changed [i];
		Composite composite = child.parent;
		while (child != this) {
			if (composite.layout == null || !composite.layout.flushCache (child)) {
				composite.state |= LAYOUT_CHANGED;
			}
			child = composite;
			composite = child.parent;
		}
	}
}
void checkBuffered () {
	if ((state & CANVAS) == 0) {
		super.checkBuffered ();
	}
}
protected void checkSubclass () {
	/* Do nothing - Subclassing is allowed */
}
void createHandle (int index) {
	state |= CANVAS;
	boolean scroll = (style & (SWT.H_SCROLL | SWT.V_SCROLL)) != 0;
	if (!scroll) state |= THEME_BACKGROUND;
	createHandle (index, parent.handle, scroll);
}
void createHandle (int index, int parentHandle, boolean scrolled) {
	if (scrolled) {
		int [] argList = {OS.XmNancestorSensitive, 1};
		scrolledHandle = OS.XmCreateMainWindow (parentHandle, null, argList, argList.length / 2);
		if (scrolledHandle == 0) error (SWT.ERROR_NO_HANDLES);
	}
	if ((style & (SWT.H_SCROLL | SWT.V_SCROLL)) != 0) {
		int [] argList1 = {
			OS.XmNmarginWidth, 3,
			OS.XmNmarginHeight, 3, 
			OS.XmNresizePolicy, OS.XmRESIZE_NONE,
			OS.XmNshadowType, OS.XmSHADOW_IN,
			OS.XmNshadowThickness, hasBorder () ? display.buttonShadowThickness : 0,
		};
		formHandle = OS.XmCreateForm (scrolledHandle, null, argList1, argList1.length / 2);
		if (formHandle == 0) error (SWT.ERROR_NO_HANDLES);
		int [] argList2 = {
			OS.XmNtopAttachment, OS.XmATTACH_FORM,
			OS.XmNbottomAttachment, OS.XmATTACH_FORM,
			OS.XmNleftAttachment, OS.XmATTACH_FORM,
			OS.XmNrightAttachment, OS.XmATTACH_FORM,
			OS.XmNresizable, 0,
			OS.XmNmarginWidth, 0,
			OS.XmNmarginHeight, 0,
			OS.XmNresizePolicy, OS.XmRESIZE_NONE,
			OS.XmNtraversalOn, (style & SWT.NO_FOCUS) != 0 ? 0 : 1,
		};
		handle = OS.XmCreateDrawingArea (formHandle, null, argList2, argList2.length / 2);
		if (handle == 0) error (SWT.ERROR_NO_HANDLES);
	} else {
		int [] argList = {
			OS.XmNancestorSensitive, 1,
			OS.XmNborderWidth, hasBorder () ? 1 : 0,
			OS.XmNmarginWidth, 0,
			OS.XmNmarginHeight, 0,
			OS.XmNresizePolicy, OS.XmRESIZE_NONE,
			OS.XmNtraversalOn, (style & SWT.NO_FOCUS) != 0 ? 0 : 1,
		};
		if (scrolledHandle != 0) parentHandle = scrolledHandle;
		handle = OS.XmCreateDrawingArea (parentHandle, null, argList, argList.length / 2);
		if (handle == 0) error (SWT.ERROR_NO_HANDLES);
	}
	int [] argList = {OS.XmNtraversalOn, 0};
	focusHandle = OS.XmCreateDrawingArea (handle, null, argList, argList.length / 2);
	if (focusHandle == 0) error (SWT.ERROR_NO_HANDLES);
	int [] argList1 = {OS.XmNforeground, 0, OS.XmNbackground, 0};
	OS.XtGetValues (handle, argList1, argList1.length / 2);
	if (formHandle != 0) OS.XtSetValues (formHandle, argList1, argList1.length / 2);
}
int defaultBackground () {
	return display.compositeBackground;
}
int defaultForeground () {
	return display.compositeForeground;
}
void deregister () {
	super.deregister ();
	if (focusHandle != 0) display.removeWidget (focusHandle);
}
void drawBackground (GC gc, int x, int y, int width, int height) {
	Control control = findBackgroundControl ();
	if (control != null) {
		GCData data = gc.getGCData ();
		int /*long*/ cairo = data.cairo;
		if (cairo != 0) {
			Cairo.cairo_save (cairo);
			if (control.backgroundImage != null) {
				short [] root_x = new short [1], root_y = new short [1];
				OS.XtTranslateCoords (handle, (short) 0, (short) 0, root_x, root_y);
				short [] control_x = new short [1], control_y = new short [1];
				OS.XtTranslateCoords (control.handle, (short) 0, (short) 0, control_x, control_y);
				int tileX = root_x[0] - control_x[0], tileY = root_y[0] - control_y[0];
				Cairo.cairo_translate (cairo, -tileX, -tileY);
				x += tileX;
				y += tileY;
				int xDisplay = OS.XtDisplay (handle);
				int xVisual = OS.XDefaultVisual(xDisplay, OS.XDefaultScreen(xDisplay));
				int xDrawable = control.backgroundImage.pixmap;				
				int [] unused = new int [1];  int [] w = new int [1];  int [] h = new int [1];
			 	OS.XGetGeometry (xDisplay, xDrawable, unused, unused, unused, w, h, unused, unused);
				int /*long*/ surface = Cairo.cairo_xlib_surface_create (xDisplay, xDrawable, xVisual, w [0], h [0]);
				if (surface == 0) error (SWT.ERROR_NO_HANDLES);
				int /*long*/ pattern = Cairo.cairo_pattern_create_for_surface (surface);
				if (pattern == 0) error (SWT.ERROR_NO_HANDLES);
				Cairo.cairo_pattern_set_extend (pattern, Cairo.CAIRO_EXTEND_REPEAT);
				Cairo.cairo_set_source (cairo, pattern);
				Cairo.cairo_surface_destroy (surface);
				Cairo.cairo_pattern_destroy (pattern);
			} else {
				XColor color = getXColor (control.getBackgroundPixel ());
				Cairo.cairo_set_source_rgba (cairo, (color.red & 0xFFFF) / (float)0xFFFF, (color.green & 0xFFFF) / (float)0xFFFF, (color.blue & 0xFFFF) / (float)0xFFFF, data.alpha / (float)0xFF);
			}			
			Cairo.cairo_rectangle (cairo, x, y, width, height);
			Cairo.cairo_fill (cairo);
			Cairo.cairo_restore (cairo);
		} else {
			int xDisplay = OS.XtDisplay (handle);
			if (xDisplay == 0) return;
			int xGC = gc.handle;
			XGCValues values = new XGCValues();
			if (control.backgroundImage != null) {
				OS.XGetGCValues (xDisplay, xGC, OS.GCFillStyle | OS.GCTile | OS.GCTileStipXOrigin | OS.GCTileStipYOrigin, values);
				short [] root_x = new short [1], root_y = new short [1];
				OS.XtTranslateCoords (handle, (short) 0, (short) 0, root_x, root_y);
				short [] control_x = new short [1], control_y = new short [1];
				OS.XtTranslateCoords (control.handle, (short) 0, (short) 0, control_x, control_y);
				int tileX = root_x[0] - control_x[0], tileY = root_y[0] - control_y[0];
				OS.XSetFillStyle (xDisplay, xGC, OS.FillTiled);
				OS.XSetTSOrigin (xDisplay, xGC, -tileX, -tileY);
				OS.XSetTile (xDisplay, xGC, control.backgroundImage.pixmap);
				OS.XFillRectangle (data.display, data.drawable, xGC, x, y, width, height);
				OS.XSetFillStyle (xDisplay, xGC, values.fill_style);
				OS.XSetTSOrigin (xDisplay, xGC, values.ts_x_origin, values.ts_y_origin);
			} else {
				OS.XGetGCValues (xDisplay, xGC, OS.GCForeground, values);
				OS.XSetForeground (xDisplay, xGC, control.getBackgroundPixel ());
				OS.XFillRectangle (data.display, data.drawable, xGC, x, y, width, height);
				OS.XSetForeground (xDisplay, xGC, values.foreground);
			}
		}
	} else {
		gc.fillRectangle (x, y, width, height);
	}
}
Composite findDeferredControl () {
	return layoutCount > 0 ? this : parent.findDeferredControl ();
}
void fixTabList (Control control) {
	if (tabList == null) return;
	int count = 0;
	for (int i=0; i<tabList.length; i++) {
		if (tabList [i] == control) count++;
	}
	if (count == 0) return;
	Control [] newList = null;
	int length = tabList.length - count;
	if (length != 0) {
		newList = new Control [length];
		int index = 0;
		for (int i=0; i<tabList.length; i++) {
			if (tabList [i] != control) {
				newList [index++] = tabList [i];
			}
		}
	}
	tabList = newList;
}
int focusHandle () {
	if (focusHandle == 0) return super.focusHandle ();
	return focusHandle;
}
int focusProc (int w, int client_data, int call_data, int continue_to_dispatch) {
	XFocusChangeEvent xEvent = new XFocusChangeEvent ();
	OS.memmove (xEvent, call_data, XFocusChangeEvent.sizeof);
	int handle = OS.XtWindowToWidget (xEvent.display, xEvent.window);
	Shell shell = getShell ();
	if (handle != shell.shellHandle) {
		return super.XFocusChange (w, client_data, call_data, continue_to_dispatch);
	}
	if (xEvent.mode != OS.NotifyNormal) return 0;
	switch (xEvent.detail) {
		case OS.NotifyNonlinear:
		case OS.NotifyNonlinearVirtual: {
			switch (xEvent.type) {
				case OS.FocusIn: 
					sendClientEvent (OS.CurrentTime, OS.XEMBED_WINDOW_ACTIVATE, 0, 0, 0);	
					break;
				case OS.FocusOut:
					sendClientEvent (OS.CurrentTime, OS.XEMBED_WINDOW_DEACTIVATE, 0, 0, 0);	
					break;
			}
		}
	}
	return 0;
}
boolean fowardKeyEvent (int event) {
	if (clientWindow == 0) return false;
	boolean warnings = display.getWarnings ();
	display.setWarnings (false);
	XKeyEvent xEvent = new XKeyEvent ();
	OS.memmove (xEvent, event, XKeyEvent.sizeof);
	xEvent.window = clientWindow;
	int newEvent = OS.XtMalloc (XEvent.sizeof);
	OS.memmove (newEvent, xEvent, XKeyEvent.sizeof);
	int xDisplay = OS.XtDisplay (handle);
	OS.XSendEvent (xDisplay, clientWindow, false, 0, newEvent);
	OS.XSync (xDisplay, false);
	OS.XtFree (newEvent);
	display.setWarnings (warnings);
	return true;
}
/**
 * Returns the receiver's background drawing mode. This
 * will be one of the following constants defined in class
 * <code>SWT</code>:
 * <code>INHERIT_NONE</code>, <code>INHERIT_DEFAULT</code>,
 * <code>INHERTIT_FORCE</code>.
 *
 * @return the background 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
 * 
 * @since 3.2
 */
public int getBackgroundMode () {
	checkWidget ();
	return backgroundMode;
}
/**
 * Returns a (possibly empty) array containing the receiver's children.
 * Children are returned in the order that they are drawn.  The topmost
 * control appears at the beginning of the array.  Subsequent controls
 * draw beneath this control and appear later in the array.
 * <p>
 * Note: This is not the actual structure used by the receiver
 * to maintain its list of children, so modifying the array will
 * not affect the receiver. 
 * </p>
 *
 * @return an array of children
 * 
 * @see Control#moveAbove
 * @see Control#moveBelow
 *
 * @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 Control [] getChildren () {
	checkWidget();
	return _getChildren ();
}
public Rectangle getClientArea () {
	checkWidget();
	/*
	* Bug in Motif. For some reason, if a form has not been realized,
	* calling XtResizeWidget () on the form does not lay out properly.
	* The fix is to force the widget to be realized by forcing the shell
	* to be realized. 
	*/
	if (formHandle != 0) {
		if (!OS.XtIsRealized (handle)) getShell ().realizeWidget ();
	}
	return super.getClientArea ();
}
int getChildrenCount () {
	/*
	* NOTE:  The current implementation will count
	* non-registered children.
	*/
	int [] argList = {OS.XmNnumChildren, 0};
	OS.XtGetValues (handle, argList, argList.length / 2);
	if (focusHandle != 0) return Math.max (0, argList [1] - 1);
	return argList [1];
}
/**
 * Returns layout which is associated with the receiver, or
 * null if one has not been set.
 *
 * @return the receiver's layout 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 Layout getLayout () {
	checkWidget();
	return layout;
}
/**
 * Returns <code>true</code> if the receiver has deferred
 * the performing of layout, and <code>false</code> otherwise.
 *
 * @return the receiver's deferred layout 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 #setLayoutDeferred(boolean)
 * @see #isLayoutDeferred()
 *
 * @since 3.1
 */
public boolean getLayoutDeferred () {
	checkWidget ();
	return layoutCount > 0 ;
}
/**
 * Gets the (possibly empty) tabbing order for the control.
 *
 * @return tabList the ordered list of controls representing the tab order
 *
 * @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 #setTabList
 */
public Control [] getTabList () {
	checkWidget ();
	Control [] tabList = _getTabList ();
	if (tabList == null) {
		int count = 0;
		Control [] list =_getChildren ();
		for (int i=0; i<list.length; i++) {
			if (list [i].isTabGroup ()) count++;
		}
		tabList = new Control [count];
		int index = 0;
		for (int i=0; i<list.length; i++) {
			if (list [i].isTabGroup ()) {
				tabList [index++] = list [i];
			}
		}
	}
	return tabList;
}
boolean hasBorder () {
	return (style & SWT.BORDER) != 0;
}
void hookEvents () {
	super.hookEvents ();
	if ((state & CANVAS) != 0) {
		OS.XtInsertEventHandler (handle, 0, true, display.windowProc, NON_MASKABLE, OS.XtListTail);
	}
	if ((state & CANVAS) != 0 && (style & SWT.EMBEDDED) != 0) {
		int focusProc = display.focusProc;
		int windowProc = display.windowProc;
		OS.XtInsertEventHandler (handle, OS.StructureNotifyMask | OS.SubstructureNotifyMask, false, windowProc, STRUCTURE_NOTIFY, OS.XtListTail);
		OS.XtInsertEventHandler (handle, OS.PropertyChangeMask, false, windowProc, PROPERTY_CHANGE, OS.XtListTail);
		OS.XtInsertEventHandler (handle, 0, true, windowProc, NON_MASKABLE, OS.XtListTail);
		Shell shell = getShell ();
		OS.XtInsertEventHandler (shell.shellHandle, OS.FocusChangeMask, false, focusProc, handle, OS.XtListTail);
	}
}

boolean hooksKeys () {
	return hooks (SWT.KeyDown) || hooks (SWT.KeyUp);
}
/**
 * Returns <code>true</code> if the receiver or any ancestor 
 * up to and including the receiver's nearest ancestor shell
 * has deferred the performing of layouts.  Otherwise, <code>false</code>
 * is returned.
 *
 * @return the receiver's deferred layout 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 #setLayoutDeferred(boolean)
 * @see #getLayoutDeferred()
 * 
 * @since 3.1
 */
public boolean isLayoutDeferred () {
	checkWidget ();
	return findDeferredControl () != null;
}
boolean isTabGroup () {
	if ((state & CANVAS) != 0) return true;
	return super.isTabGroup ();
}
/**
 * If the receiver has a layout, asks the layout to <em>lay out</em>
 * (that is, set the size and location of) the receiver's children. 
 * If the receiver does not have a layout, do nothing.
 * <p>
 * This is equivalent to calling <code>layout(true)</code>.
 * </p>
 * <p>
 * Note: Layout is different from painting. If a child is
 * moved or resized such that an area in the parent is
 * exposed, then the parent will paint. If no child is
 * affected, the parent will not paint.
 * </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>
 */
public void layout () {
	checkWidget ();
	layout (true);
}
/**
 * If the receiver has a layout, asks the layout to <em>lay out</em>
 * (that is, set the size and location of) the receiver's children. 
 * If the argument is <code>true</code> the layout must not rely
 * on any information it has cached about the immediate children. If it
 * is <code>false</code> the layout may (potentially) optimize the
 * work it is doing by assuming that none of the receiver's 
 * children has changed state since the last layout.
 * If the receiver does not have a layout, do nothing.
 * <p>
 * If a child is resized as a result of a call to layout, the 
 * resize event will invoke the layout of the child.  The layout
 * will cascade down through all child widgets in the receiver's widget 
 * tree until a child is encountered that does not resize.  Note that 
 * a layout due to a resize will not flush any cached information 
 * (same as <code>layout(false)</code>).
 * </p>
 * <p>
 * Note: Layout is different from painting. If a child is
 * moved or resized such that an area in the parent is
 * exposed, then the parent will paint. If no child is
 * affected, the parent will not paint.
 * </p>
 *
 * @param changed <code>true</code> if the layout must flush its caches, 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>
 */
public void layout (boolean changed) {
	checkWidget ();
	if (layout == null) return;
	layout (changed, false);
}
/**
 * If the receiver has a layout, asks the layout to <em>lay out</em>
 * (that is, set the size and location of) the receiver's children. 
 * If the changed argument is <code>true</code> the layout must not rely
 * on any information it has cached about its children. If it
 * is <code>false</code> the layout may (potentially) optimize the
 * work it is doing by assuming that none of the receiver's 
 * children has changed state since the last layout.
 * If the all argument is <code>true</code> the layout will cascade down
 * through all child widgets in the receiver's widget tree, regardless of
 * whether the child has changed size.  The changed argument is applied to 
 * all layouts.  If the all argument is <code>false</code>, the layout will
 * <em>not</em> cascade down through all child widgets in the receiver's widget 
 * tree.  However, if a child is resized as a result of a call to layout, the 
 * resize event will invoke the layout of the child.  Note that 
 * a layout due to a resize will not flush any cached information 
 * (same as <code>layout(false)</code>).
 * </p>
 * <p>
 * Note: Layout is different from painting. If a child is
 * moved or resized such that an area in the parent is
 * exposed, then the parent will paint. If no child is
 * affected, the parent will not paint.
 * </p>
 *
 * @param changed <code>true</code> if the layout must flush its caches, and <code>false</code> otherwise
 * @param all <code>true</code> if all children in the receiver's widget tree should be laid out, 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>
 *
 * @since 3.1
 */
public void layout (boolean changed, boolean all) {
	checkWidget ();
	if (layout == null && !all) return;
	markLayout (changed, all);
	updateLayout (all);
}
/**
 * Forces a lay out (that is, sets the size and location) of all widgets that 
 * are in the parent hierarchy of the changed control up to and including the 
 * receiver.  The layouts in the hierarchy must not rely on any information 
 * cached about the changed control or any of its ancestors.  The layout may 
 * (potentially) optimize the work it is doing by assuming that none of the 
 * peers of the changed control have changed state since the last layout.
 * If an ancestor does not have a layout, skip it.
 * <p>
 * Note: Layout is different from painting. If a child is
 * moved or resized such that an area in the parent is
 * exposed, then the parent will paint. If no child is
 * affected, the parent will not paint.
 * </p>
 * 
 * @param changed a control that has had a state change which requires a recalculation of its size
 * 
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_INVALID_ARGUMENT - if the changed array is null any of its controls are null or have been disposed</li> 
 *    <li>ERROR_INVALID_PARENT - if any control in changed is not in the widget tree of the receiver</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 layout (Control [] changed) {
	checkWidget ();
	if (changed == null) error (SWT.ERROR_INVALID_ARGUMENT);
	for (int i=0; i<changed.length; i++) {
		Control control = changed [i];
		if (control == null) error (SWT.ERROR_INVALID_ARGUMENT);
		if (control.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
		boolean ancestor = false;
		Composite composite = control.parent;
		while (composite != null) {
			ancestor = composite == this;
			if (ancestor) break;
			composite = composite.parent;
		}
		if (!ancestor) error (SWT.ERROR_INVALID_PARENT);
	}
	int updateCount = 0;
	Composite [] update = new Composite [16];
	for (int i=0; i<changed.length; i++) {
		Control child = changed [i];
		Composite composite = child.parent;
		while (child != this) {
			if (composite.layout != null) {
				composite.state |= LAYOUT_NEEDED;
				if (!composite.layout.flushCache (child)) {
					composite.state |= LAYOUT_CHANGED;
				}
			}
			if (updateCount == update.length) {
				Composite [] newUpdate = new Composite [update.length + 16];
				System.arraycopy (update, 0, newUpdate, 0, update.length);
				update = newUpdate;
			}
			child = update [updateCount++] = composite;
			composite = child.parent;
		}
	}
	for (int i=updateCount-1; i>=0; i--) {
		update [i].updateLayout (false);
	}
}
void manageChildren () {
	if (focusHandle != 0) {	
		OS.XtSetMappedWhenManaged (focusHandle, false);
		OS.XtManageChild (focusHandle);
	}
	super.manageChildren ();
	if (focusHandle != 0) {
		OS.XtConfigureWidget(focusHandle, 0, 0, 1, 1, 0);
		OS.XtSetMappedWhenManaged (focusHandle, true);
	}
	if ((state & CANVAS) != 0 && (style & SWT.EMBEDDED) != 0) {
		Shell shell = getShell ();
		shell.createFocusProxy ();
		if (!OS.XtIsRealized (handle)) shell.realizeWidget ();
		int xDisplay = OS.XtDisplay (handle);
		OS.XSync (xDisplay, false);
		embeddedHandle = OS.XtWindow (handle);
	}
}
void markLayout (boolean changed, boolean all) {
	if (layout != null) {
		state |= LAYOUT_NEEDED;
		if (changed) state |= LAYOUT_CHANGED;
	}
	if (all) {
		Control [] children = _getChildren ();
		for (int i=0; i<children.length; i++) {
			children [i].markLayout (changed, all);
		}
	}
}
Point minimumSize (int wHint, int hHint, boolean changed) {
	Control [] children = _getChildren ();
	int width = 0, height = 0;
	for (int i=0; i<children.length; i++) {
		Rectangle rect = children [i].getBounds ();
		width = Math.max (width, rect.x + rect.width);
		height = Math.max (height, rect.y + rect.height);
	}
	return new Point (width, height);
}
void moveAbove (int handle1, int handle2) {
	if (handle1 == handle2) return;
	int [] argList = {OS.XmNchildren, 0, OS.XmNnumChildren, 0};
	OS.XtGetValues (handle, argList, argList.length / 2);
	int ptr = argList [1], count = argList [3];
	if (count == 0 || ptr == 0) return;
	int [] handles = new int [count];
	OS.memmove (handles, ptr, count * 4);
	if (handle2 == 0) handle2 = handles [0];
	int i = 0, index1 = -1, index2 = -1;
	while (i < count) {
		int handle = handles [i];
		if (handle == handle1) index1 = i;
		if (handle == handle2) index2 = i;
		if (index1 != -1 && index2 != -1) break;
		i++;
	}
	if (index1 == -1 || index2 == -1) return;
	if (index1 == index2) return;
	if (index1 < index2) {
		System.arraycopy (handles, index1 + 1, handles, index1, index2 - index1 - 1);
		handles [index2 - 1] = handle1;
	} else {
		System.arraycopy (handles, index2, handles, index2 + 1, index1 - index2);
		handles [index2] = handle1;
	}
	OS.memmove (ptr, handles, count * 4);
}
void moveBelow (int handle1, int handle2) {
	if (handle1 == handle2) return;
	int [] argList = {OS.XmNchildren, 0, OS.XmNnumChildren, 0};
	OS.XtGetValues (handle, argList, argList.length / 2);
	int ptr = argList [1], count = argList [3];
	if (count == 0 || ptr == 0) return;
	int [] handles = new int [count];
	OS.memmove (handles, ptr, count * 4);
	if (handle2 == 0) handle2 = handles [count - 1];
	int i = 0, index1 = -1, index2 = -1;
	while (i < count) {
		int handle = handles [i];
		if (handle == handle1) index1 = i;
		if (handle == handle2) index2 = i;
		if (index1 != -1 && index2 != -1) break;
		i++;
	}
	if (index1 == -1 || index2 == -1) return;
	if (index1 == index2) return;
	if (index1 < index2) {
		System.arraycopy (handles, index1 + 1, handles, index1, index2 - index1);
		handles [index2] = handle1;
	} else {
		System.arraycopy (handles, index2 + 1, handles, index2 + 2, index1 - index2 - 1);
		handles [index2 + 1] = handle1;
	}
	OS.memmove (ptr, handles, count * 4);
}
void propagateChildren (boolean enabled) {
	super.propagateChildren (enabled);
	Control [] children = _getChildren ();
	for (int i = 0; i < children.length; i++) {
		Control child = children [i];
		if (child.getEnabled ()) {
			child.propagateChildren (enabled);
		}
	}
}
void realizeChildren () {
	super.realizeChildren ();
	Control [] children = _getChildren ();
	for (int i=0; i<children.length; i++) {
		children [i].realizeChildren ();
	}
	/*
	* Feature in Motif.  XmProcessTraversal() will not give focus to
	* a widget that is obscured so the focus handle must be inside the
	* client area of the parent.  This means that it is visible as a
	* single pixel widget in the parent.  The fix is to unmap the
	* focus handle so that it will be traversed by XmProcessTraversal()
	* and will accept focus but will not be visible in the parent.
	*/
	if (focusHandle != 0) OS.XtUnmapWidget (focusHandle);
	if ((state & CANVAS) != 0) {
		if ((style & (SWT.DOUBLE_BUFFERED | SWT.NO_BACKGROUND)) != 0 || (style & SWT.NO_REDRAW_RESIZE) == 0) {
			int xDisplay = OS.XtDisplay (handle);
			if (xDisplay == 0) return;
			int xWindow = OS.XtWindow (handle);
			if (xWindow == 0) return;
			int flags = 0;
			XSetWindowAttributes attributes = new XSetWindowAttributes ();
			if ((style & (SWT.NO_BACKGROUND | SWT.DOUBLE_BUFFERED)) != 0) {
				flags |= OS.CWBackPixmap;
				attributes.background_pixmap = OS.None;
			}
			if ((style & SWT.NO_REDRAW_RESIZE) == 0) {
				flags |= OS.CWBitGravity;
				attributes.bit_gravity = OS.ForgetGravity;
			}
			if (flags != 0) {
				OS.XChangeWindowAttributes (xDisplay, xWindow, flags, attributes);
			}
		}
	}
}
void redrawChildren () {
	super.redrawChildren ();
	Control [] children = _getChildren ();
	for (int i = 0; i < children.length; i++) {
		Control child = children [i];
		if ((child.state & PARENT_BACKGROUND) != 0) {
			child.redrawWidget (0, 0, 0, 0, true, false, true);
			child.redrawChildren ();
		}
	}
}
void register () {
	super.register ();
	if (focusHandle != 0) display.addWidget (focusHandle, this);
}
void redrawWidget (int x, int y, int width, int height, boolean redrawAll, boolean allChildren, boolean trim) {
	super.redrawWidget (x, y, width, height, redrawAll, allChildren, trim);
	if (!allChildren) return;
	Control [] children = _getChildren ();
	for (int i = 0; i < children.length; i++) {
		Control child = children [i];
		Point location = child.getClientLocation ();
		child.redrawWidget (x - location.x, y - location.y, width, height, redrawAll, allChildren, true);
	}
}
void release (boolean destroy) {
	if ((state & CANVAS) != 0 && (style & SWT.EMBEDDED) != 0) {
		Shell shell = getShell ();
		int focusProc = display.focusProc;
		OS.XtRemoveEventHandler (shell.shellHandle, OS.FocusChangeMask, false, focusProc, handle);
		if (clientWindow != 0) {
			boolean warnings = display.getWarnings ();
			display.setWarnings (false);
			int xDisplay = OS.XtDisplay (handle);
			OS.XUnmapWindow (xDisplay, clientWindow);
			OS.XReparentWindow (xDisplay, clientWindow, OS.XDefaultRootWindow (xDisplay), 0, 0);
			OS.XSync (xDisplay, false);
			display.setWarnings (warnings);
		}
		setClientWindow (0);
	}
	super.release (destroy);
}
void releaseChildren (boolean destroy) {
	Control [] children = _getChildren ();
	for (int i=0; i<children.length; i++) {
		Control child = children [i];
		if (child != null && !child.isDisposed ()) {
			child.release (false);
		}
	}
	super.releaseChildren (destroy);
}
void releaseHandle () {
	super.releaseHandle ();
	focusHandle = embeddedHandle = 0;
}
void releaseWidget () {
	super.releaseWidget ();
	layout = null;
	tabList = null;
	if (damagedRegion != 0) OS.XDestroyRegion (damagedRegion);
	damagedRegion = 0;
}
void removeControl (Control control) {
	fixTabList (control);
}
void resizeClientWindow	() {
	if (clientWindow == 0) return;
	boolean warnings = display.getWarnings ();
	display.setWarnings (false);
	int [] argList = {OS.XmNwidth, 0, OS.XmNheight, 0};
	OS.XtGetValues (handle, argList, argList.length / 2);
	int xDisplay = OS.XtDisplay (handle);
	OS.XMoveResizeWindow (xDisplay, clientWindow, 0, 0, Math.max(1, argList [1]), Math.max(1, argList [3]));
	display.setWarnings (warnings);
}
void sendClientEvent (int time, int message, int detail, int data1, int data2) {
	if (clientWindow == 0) return;
	boolean warnings = display.getWarnings ();
	display.setWarnings (false);
	int xDisplay = OS.XtDisplay (handle);
	XClientMessageEvent xEvent = new XClientMessageEvent ();
	xEvent.type = OS.ClientMessage;
	xEvent.window = clientWindow;
	xEvent.message_type = OS.XInternAtom (xDisplay, _XEMBED, false);
	xEvent.format = 32;
	xEvent.data [0] = time != 0 ? time : OS.XtLastTimestampProcessed (xDisplay);
	xEvent.data [1] = message;
	xEvent.data [2] = detail;
	xEvent.data [3] = data1;
	xEvent.data [4] = data2;
	int event = OS.XtMalloc (XEvent.sizeof);
	OS.memmove (event, xEvent, XClientMessageEvent.sizeof);
	OS.XSendEvent (xDisplay, clientWindow, false, 0, event);
	OS.XSync (xDisplay, false);
	OS.XtFree (event);
	display.setWarnings (warnings);
}
/**
 * Sets the background drawing mode to the argument which should
 * be one of the following constants defined in class <code>SWT</code>:
 * <code>INHERIT_NONE</code>, <code>INHERIT_DEFAULT</code>,
 * <code>INHERIT_FORCE</code>.
 *
 * @param mode the new background 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
 * 
 * @since 3.2
 */
public void setBackgroundMode (int mode) {
	checkWidget ();
	backgroundMode = mode;
	Control[] children = _getChildren ();
	for (int i = 0; i < children.length; i++) {
		children [i].updateBackgroundMode ();
	}
}
void setBackgroundPixel (int pixel) {
	super.setBackgroundPixel (pixel);
	if ((state & CANVAS) != 0) {
		if ((style & (SWT.NO_BACKGROUND | SWT.DOUBLE_BUFFERED)) != 0) {
			int xDisplay = OS.XtDisplay (handle);
			if (xDisplay == 0) return;
			int xWindow = OS.XtWindow (handle);
			if (xWindow == 0) return;
			XSetWindowAttributes attributes = new XSetWindowAttributes ();
			attributes.background_pixmap = OS.None;
			OS.XChangeWindowAttributes (xDisplay, xWindow, OS.CWBackPixmap, attributes);
		}
	}
}
boolean setBounds (int x, int y, int width, int height, boolean move, boolean resize) {
	boolean changed = super.setBounds (x, y, width, height, move, resize);
	if (changed && resize) {
		if (focusHandle != 0) {
			int [] argList = {OS.XmNwidth, 0, OS.XmNheight, 0};
			OS.XtGetValues (handle, argList, argList.length / 2);
			OS.XtConfigureWidget (focusHandle, 0, 0, argList [1], argList [3], 0);
		}
		if (layout != null) {
			markLayout (false, false);
			updateLayout (false);
		}
		if ((state & CANVAS) != 0 && (style & SWT.EMBEDDED) != 0) {
			resizeClientWindow ();
		}
	}
	return changed;
}
void setClientWindow (int window) {
	if (focusHandle != 0) {
		if (window == OS.XtWindow (focusHandle)) return;
	}
	boolean warnings = display.getWarnings ();
	display.setWarnings (false);
	int xDisplay = OS.XtDisplay (handle);
	if (window != 0) {
		if (clientWindow == 0) {
			clientWindow = window;
			sendClientEvent (0, OS.XEMBED_EMBEDDED_NOTIFY, 0, 0, 0);
			OS.XtRegisterDrawable (xDisplay, clientWindow, handle);
			OS.XSelectInput (xDisplay, clientWindow, OS.PropertyChangeMask);
			updateMapped ();		
			resizeClientWindow ();
			Shell shell = getShell ();
			if (shell == display.getActiveShell ()) {
				shell.bringToTop (true);
				sendClientEvent (0, OS.XEMBED_WINDOW_ACTIVATE, 0, 0, 0);
				if (this == display.getFocusControl ()) {
					sendClientEvent (0, OS.XEMBED_FOCUS_IN, OS.XEMBED_FOCUS_CURRENT, 0, 0);
				}
			}
		}
	} else {
		if (clientWindow != 0) OS.XtUnregisterDrawable (xDisplay, clientWindow);
		clientWindow = 0;
	}
	display.setWarnings (warnings);
}
public boolean setFocus () {
	checkWidget ();
	Control [] children = _getChildren ();
	for (int i=0; i<children.length; i++) {
		Control child = children [i];
		if (child.setFocus ()) return true;
	}
	return super.setFocus ();
}
public void setFont (Font font) {
	checkWidget();
	super.setFont (font);
	if ((state & CANVAS) != 0) {
		int xDisplay = OS.XtDisplay (handle);
		if (xDisplay == 0) return;
		int xWindow = OS.XtWindow (handle);
		if (xWindow == 0) return;
		OS.XClearArea (xDisplay, xWindow, 0, 0, 0, 0, true);
	}
}
void setForegroundPixel (int pixel) {
	super.setForegroundPixel (pixel);
	if ((state & CANVAS) != 0) {
		int xDisplay = OS.XtDisplay (handle);
		if (xDisplay == 0) return;
		int xWindow = OS.XtWindow (handle);
		if (xWindow == 0) return;
		OS.XClearArea (xDisplay, xWindow, 0, 0, 0, 0, true);
	}
}
/**
 * Sets the layout which is associated with the receiver to be
 * the argument which may be null.
 *
 * @param layout the receiver's new layout 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 setLayout (Layout layout) {
	checkWidget();
	this.layout = layout;
}
/**
 * If the argument is <code>true</code>, causes subsequent layout
 * operations in the receiver or any of its children to be ignored.
 * No layout of any kind can occur in the receiver or any of its
 * children until the flag is set to false.
 * Layout operations that occurred while the flag was
 * <code>true</code> are remembered and when the flag is set to 
 * <code>false</code>, the layout operations are performed in an
 * optimized manner.  Nested calls to this method are stacked.
 *
 * @param defer the new defer 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 #layout(boolean)
 * @see #layout(Control[])
 *
 * @since 3.1
 */
public void setLayoutDeferred (boolean defer) {
	if (!defer) {
		if (--layoutCount == 0) {
			if ((state & LAYOUT_CHILD) != 0 || (state & LAYOUT_NEEDED) != 0) {
				updateLayout (true);
			}
		}
	} else {
		layoutCount++;
	}
}
/**
 * Sets the tabbing order for the specified controls to
 * match the order that they occur in the argument list.
 *
 * @param tabList the ordered list of controls representing the tab order or null
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_INVALID_ARGUMENT - if a widget in the tabList is null or has been disposed</li> 
 *    <li>ERROR_INVALID_PARENT - if widget in the tabList is not in the same widget tree</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 setTabList (Control [] tabList) {
	checkWidget ();
	if (tabList != null) {
		for (int i=0; i<tabList.length; i++) {
			Control control = tabList [i];
			if (control == null) error (SWT.ERROR_INVALID_ARGUMENT);
			if (control.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
			if (control.parent != this) error (SWT.ERROR_INVALID_PARENT);
		}
		Control [] newList = new Control [tabList.length];
		System.arraycopy (tabList, 0, newList, 0, tabList.length);
		tabList = newList;
	} 
	this.tabList = tabList;
}
void setParentBackground () {
	super.setParentBackground ();	
	if (scrolledHandle != 0) setParentBackground (scrolledHandle);
	if (formHandle != 0) setParentBackground (formHandle);
}
boolean setScrollBarVisible (ScrollBar bar, boolean visible) {
	boolean changed = super.setScrollBarVisible (bar, visible);
	if (changed && layout != null) {
		markLayout (false, false);
		updateLayout (false);
	}
	return changed;
}
boolean setTabGroupFocus (boolean next) {
	if (isTabItem ()) return setTabItemFocus (next);
	boolean takeFocus = (style & SWT.NO_FOCUS) == 0;
	if ((state & CANVAS) != 0) {
		takeFocus = hooksKeys ();
		if ((style & SWT.EMBEDDED) != 0) takeFocus = true;
	}
	if (takeFocus && setTabItemFocus (next)) return true;
	Control [] children = _getChildren ();
	for (int i=0; i<children.length; i++) {
		Control child = children [i];
		if (child.isTabItem () && child.setTabItemFocus (next)) return true;
	}
	return false;
}
boolean setTabItemFocus (boolean next) {
	if (!super.setTabItemFocus (next)) return false;
	if (handle != 0) {
		if ((state & CANVAS) != 0 && (style & SWT.EMBEDDED) != 0) {
			int detail = next ? OS.XEMBED_FOCUS_FIRST : OS.XEMBED_FOCUS_LAST;
			sendClientEvent (0, OS.XEMBED_FOCUS_IN, detail, 0, 0);
		}
	}
	return true;
}
int traversalCode (int key, XKeyEvent xEvent) {
	if ((state & CANVAS) != 0) {
		if ((style & SWT.NO_FOCUS) != 0) return 0;
		if (hooksKeys ()) return 0;
	}
	return super.traversalCode (key, xEvent);
}
boolean translateMnemonic (Event event, Control control) {
	if (super.translateMnemonic (event, control)) return true;
	if (control != null) {
		Control [] children = _getChildren ();
		for (int i=0; i<children.length; i++) {
			Control child = children [i];
			if (child.translateMnemonic (event, control)) return true;
		}
	}
	return false;
}
boolean translateTraversal (int key, XKeyEvent xEvent) {
	if ((state & CANVAS) != 0 && (style & SWT.EMBEDDED) != 0) return false;
	return super.translateTraversal (key, xEvent);
}
void updateBackgroundMode () {
	super.updateBackgroundMode ();
	Control [] children = _getChildren ();
	for (int i = 0; i < children.length; i++) {
		children [i].updateBackgroundMode ();
	}
}
void updateLayout (boolean all) {
	Composite parent = findDeferredControl ();
	if (parent != null) {
		parent.state |= LAYOUT_CHILD;
		return;
	}
	if ((state & LAYOUT_NEEDED) != 0) {
		boolean changed = (state & LAYOUT_CHANGED) != 0;
		state &= ~(LAYOUT_NEEDED | LAYOUT_CHANGED);
		layout.layout (this, changed);
	}
	if (all) {
		state &= ~LAYOUT_CHILD;
		Control [] children = _getChildren ();
		for (int i=0; i<children.length; i++) {
			children [i].updateLayout (all);
		}
	}
}
int XButtonPress (int w, int client_data, int call_data, int continue_to_dispatch) {
	int result = super.XButtonPress (w, client_data, call_data, continue_to_dispatch);
	if (result != 0) return result;

	/* Set focus for a canvas with no children */
	if ((state & CANVAS) != 0) {
		XButtonEvent xEvent = new XButtonEvent ();
		OS.memmove (xEvent, call_data, XButtonEvent.sizeof);
		if ((style & SWT.NO_FOCUS) == 0 && hooksKeys ()) {
			if (xEvent.button == 1) {
				if (getChildrenCount () == 0) setFocus ();
			}
		}
		/*
		* Bug in Motif. On Solaris 8 only, stopping the other event
		* handlers from being invoked after a menu has been displayed
		* causes a segment fault.  The fix is to not stop the event for
		* button 3.
		*/
		if (xEvent.button != 3) {
			OS.memmove (continue_to_dispatch, new int [1], 4);
		}
		return 1;
	}
	return result;
}
int XExposure (int w, int client_data, int call_data, int continue_to_dispatch) {
	if ((state & CANVAS) == 0) {
		return super.XExposure (w, client_data, call_data, continue_to_dispatch);
	}
	if (!hooks (SWT.Paint) && !filters (SWT.Paint)) return 0;
	if (damagedRegion == 0) damagedRegion = OS.XCreateRegion ();
	OS.XtAddExposureToRegion (call_data, damagedRegion);
	if ((style & SWT.NO_MERGE_PAINTS) == 0) {
		XExposeEvent xEvent = new XExposeEvent ();
		OS.memmove (xEvent, call_data, XExposeEvent.sizeof);
		int exposeCount = xEvent.count;
		if (exposeCount == 0) {
			if (OS.XEventsQueued (xEvent.display, OS.QueuedAfterReading) != 0) {
				int xEvent1 = OS.XtMalloc (XEvent.sizeof);
				display.exposeCount = display.lastExpose = 0;
				int checkExposeProc = display.checkExposeProc;
				OS.XCheckIfEvent (xEvent.display, xEvent1, checkExposeProc, xEvent.window);
				exposeCount = display.exposeCount;
				int lastExpose = display.lastExpose;
				if (exposeCount != 0 && lastExpose != 0) {
					XExposeEvent xExposeEvent = display.xExposeEvent;
					OS.memmove (xExposeEvent, lastExpose, XExposeEvent.sizeof);
					xExposeEvent.count = 0;
					OS.memmove (lastExpose, xExposeEvent, XExposeEvent.sizeof);
				}
				OS.XtFree (xEvent1);
			}
		}
		if (exposeCount != 0) return 0;
	}
	int xDisplay = OS.XtDisplay (handle);
	if (xDisplay == 0) return 0;
	int damageRgn = damagedRegion;
	damagedRegion = 0;
	GCData data = new GCData ();
	data.damageRgn = damageRgn;
	GC gc = GC.motif_new (this, data);
	OS.XSetRegion (xDisplay, gc.handle, damageRgn);
	XRectangle rect = new XRectangle ();
	OS.XClipBox (damageRgn, rect);
	GC paintGC = null;
	Image image = null;
	if ((style & SWT.DOUBLE_BUFFERED) != 0) {
		Rectangle client = getClientArea ();
		int width = Math.max (1, Math.min (client.width, rect.x + rect.width));
		int height = Math.max (1, Math.min (client.height, rect.y + rect.height));
		image = new Image (display, width, height);
		paintGC = gc;
		GCData imageGCData = new GCData ();
		imageGCData.damageRgn = damageRgn; 
		gc = GC.motif_new (image, imageGCData);
		gc.setForeground (getForeground ());
		gc.setBackground (getBackground ());
		gc.setFont (getFont ());
		if ((style & SWT.NO_BACKGROUND) != 0) {
			/* This code is intentionaly commented because it is too slow to copy bits from the screen */
//			paintGC.copyArea(image, 0, 0);
		} else {
			drawBackground (gc, 0, 0, width, height);
		}
	}
	Event event = new Event ();
	event.x = rect.x;
	event.y = rect.y;
	event.width = rect.width;
	event.height = rect.height;
	event.gc = gc;
	sendEvent (SWT.Paint, event);
	event.gc = null;
	if ((style & SWT.DOUBLE_BUFFERED) != 0) {
		gc.dispose ();
		if (!isDisposed ()) {
			paintGC.drawImage (image, 0, 0);
		}
		image.dispose ();
		gc = paintGC;
	}	
	gc.dispose ();
	OS.XDestroyRegion (damageRgn);
	return 0;
}
int xFocusIn (XFocusChangeEvent xEvent) {
	int result = super.xFocusIn (xEvent);
	if (handle != 0) {
		if ((state & CANVAS) != 0 && (style & SWT.EMBEDDED) != 0) {
			sendClientEvent (0, OS.XEMBED_FOCUS_IN, OS.XEMBED_FOCUS_CURRENT, 0, 0);
		}
	}
	return result;
}
int xFocusOut (XFocusChangeEvent xEvent) {
	int result = super.xFocusOut (xEvent);
	if (handle != 0) {
		if ((state & CANVAS) != 0 && (style & SWT.EMBEDDED) != 0) {
			sendClientEvent (0, OS.XEMBED_FOCUS_OUT, 0, 0, 0);
		}
	}
	return result;
}
int XKeyPress (int w, int client_data, int call_data, int continue_to_dispatch) {
	int result = super.XKeyPress (w, client_data, call_data, continue_to_dispatch);
	if (result == 0) {
		if ((state & CANVAS) != 0 && (style & SWT.EMBEDDED) != 0) {
			if (fowardKeyEvent (call_data)) return 0;
		}
	}
	return result;
}
int XKeyRelease (int w, int client_data, int call_data, int continue_to_dispatch) {
	int result = super.XKeyRelease (w, client_data, call_data, continue_to_dispatch);
	if (result == 0) {
		if ((state & CANVAS) != 0 && (style & SWT.EMBEDDED) != 0) {
			if (fowardKeyEvent (call_data)) return 0;
		}
	}
	return result;
}
int XNonMaskable (int w, int client_data, int call_data, int continue_to_dispatch) {
	if ((state & CANVAS) != 0 && (style & SWT.EMBEDDED) != 0) {
		XEvent xEvent = new XEvent ();
		OS.memmove (xEvent, call_data, XEvent.sizeof);
		if (xEvent.type == OS.ClientMessage) {
			XClientMessageEvent xClientEvent = new XClientMessageEvent ();
			OS.memmove (xClientEvent, call_data, XClientMessageEvent.sizeof);
			int xDisplay = OS.XtDisplay (handle);
			if (xClientEvent.message_type == OS.XInternAtom (xDisplay, _XEMBED, false)) {
				int type = xClientEvent.data [1];
				switch (type) {
					case OS.XEMBED_REQUEST_FOCUS: {
						setFocus ();
						break;
					}
					case OS.XEMBED_FOCUS_PREV: {
						traverse (SWT.TRAVERSE_TAB_PREVIOUS);
						break;
					}
					case OS.XEMBED_FOCUS_NEXT: {
						traverse (SWT.TRAVERSE_TAB_NEXT);
						break;
					}
				}
			}
			return 0;
		}
	}
	if ((state & CANVAS) != 0) {
		XEvent xEvent = new XEvent ();
		OS.memmove (xEvent, call_data, XEvent.sizeof);
		if (xEvent.type == OS.GraphicsExpose) {
			return XExposure (w, client_data, call_data, continue_to_dispatch);
		}
	}
	return 0;
}
int XPropertyChange (int w, int client_data, int call_data, int continue_to_dispatch) {
	int result = super.XPropertyChange (w, client_data, call_data, continue_to_dispatch);
	if ((state & CANVAS) != 0 && (style & SWT.EMBEDDED) != 0) {
		XPropertyEvent xPropertyEvent = new XPropertyEvent ();
		OS.memmove(xPropertyEvent, call_data, XPropertyEvent.sizeof);
		if (xPropertyEvent.window == clientWindow) {
			int atom = xPropertyEvent.atom;
			int xDisplay = xPropertyEvent.display;
			if (atom == OS.XInternAtom (xDisplay, _XEMBED_INFO, false)) {
				updateMapped ();
			}
		}
	}
	return result;
}
int XStructureNotify (int w, int client_data, int call_data, int continue_to_dispatch) {
	int result = super.XStructureNotify (w, client_data, call_data, continue_to_dispatch);
	if ((state & CANVAS) != 0 && (style & SWT.EMBEDDED) != 0) {
		XEvent xEvent = new XEvent ();
		OS.memmove (xEvent, call_data, XEvent.sizeof);
		switch (xEvent.type) {
			case OS.ReparentNotify: {
				XReparentEvent xReparentEvent = new XReparentEvent ();
				OS.memmove (xReparentEvent, call_data, XReparentEvent.sizeof);
				if (clientWindow == 0) setClientWindow (xReparentEvent.window);
				break;
			}
			case OS.CreateNotify: {
				XCreateWindowEvent xCreateEvent = new XCreateWindowEvent ();
				OS.memmove (xCreateEvent, call_data, XCreateWindowEvent.sizeof);
				if (clientWindow == 0) setClientWindow (xCreateEvent.window);
				break;
			}
			case OS.DestroyNotify: {
				XDestroyWindowEvent xDestroyEvent = new XDestroyWindowEvent ();
				OS.memmove (xDestroyEvent, call_data, XDestroyWindowEvent.sizeof);
				if (xDestroyEvent.window == clientWindow) setClientWindow (0);
				break;
			}
			case OS.ConfigureNotify: {
				XConfigureEvent xConfigureEvent = new XConfigureEvent ();
				OS.memmove (xConfigureEvent, call_data, XConfigureEvent.sizeof);
				if (xConfigureEvent.window == clientWindow) resizeClientWindow ();
				break;
			}
		}
	}
	return result;
}
void updateMapped () {
	if (clientWindow == 0) return;
	boolean warnings = display.getWarnings ();
	display.setWarnings (false);
	int xDisplay = OS.XtDisplay (handle);
	int prop = OS.XInternAtom (xDisplay, _XEMBED_INFO, false);
	int [] type = new int [1], format = new int [1];
	int [] nitems = new int [1], bytes_after = new int [1], data = new int [1];
	if (OS.XGetWindowProperty (xDisplay, clientWindow, prop, 0, 2, false, prop, type, format, nitems, bytes_after, data) == 0) {
		if (type [0] == prop) {
			if (nitems [0] >= 2) {
				int [] buffer = new int [2];
				OS.memmove (buffer, data [0], buffer.length * 4);
				int flags = buffer [1];
				if ((flags & OS.XEMBED_MAPPED) != 0) {
					OS.XMapWindow (xDisplay, clientWindow);
				} else {
					OS.XUnmapWindow (xDisplay, clientWindow);
				}
			}
		}
	}
	if (data [0] != 0) OS.XFree (data [0]);
	display.setWarnings (warnings);
}
}
