]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Composite.java
Work around SWT 4.13 - 4.18 Win32 DnD bug 567422
[simantics/platform.git] / bundles / org.eclipse.swt.win32.win32.x86_64 / src / org / eclipse / swt / widgets / Composite.java
diff --git a/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Composite.java b/bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Composite.java
new file mode 100644 (file)
index 0000000..8289d43
--- /dev/null
@@ -0,0 +1,1991 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 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 org.eclipse.swt.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.internal.*;
+import org.eclipse.swt.internal.win32.*;
+
+/**
+ * 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), 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;
+       WINDOWPOS [] lpwp;
+       Control [] tabList;
+       int layoutCount, backgroundMode;
+
+       static final int TOOLTIP_LIMIT = 4096;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+Composite () {
+}
+
+/**
+ * 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);
+}
+
+Control [] _getChildren () {
+       int count = 0;
+       long hwndChild = OS.GetWindow (handle, OS.GW_CHILD);
+       if (hwndChild == 0) return new Control [0];
+       while (hwndChild != 0) {
+               count++;
+               hwndChild = OS.GetWindow (hwndChild, OS.GW_HWNDNEXT);
+       }
+       Control [] children = new Control [count];
+       int index = 0;
+       hwndChild = OS.GetWindow (handle, OS.GW_CHILD);
+       while (hwndChild != 0) {
+               Control control = display.getControl (hwndChild);
+               if (control != null && control != this) {
+                       children [index++] = control;
+               }
+               hwndChild = OS.GetWindow (hwndChild, OS.GW_HWNDNEXT);
+       }
+       if (count == index) return children;
+       Control [] newChildren = new Control [index];
+       System.arraycopy (children, 0, newChildren, 0, index);
+       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;
+}
+
+/**
+ * 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>
+ *
+ * @deprecated use {@link Composite#layout(Control[], int)} instead
+ * @since 3.1
+ */
+@Deprecated
+public void changed (Control[] changed) {
+       layout(changed, SWT.DEFER);
+}
+
+@Override
+void checkBuffered () {
+       if ((state & CANVAS) == 0) {
+               super.checkBuffered ();
+       }
+}
+
+@Override
+void checkComposited () {
+       if ((state & CANVAS) != 0) {
+               if ((style & SWT.TRANSPARENT) != 0) {
+                       long hwndParent = parent.handle;
+                       int bits = OS.GetWindowLong (hwndParent, OS.GWL_EXSTYLE);
+                       bits |= OS.WS_EX_COMPOSITED;
+                       OS.SetWindowLong (hwndParent, OS.GWL_EXSTYLE, bits);
+               }
+       }
+}
+
+@Override
+protected void checkSubclass () {
+       /* Do nothing - Subclassing is allowed */
+}
+
+@Override
+Widget [] computeTabList () {
+       Widget 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];
+               Widget  [] childList = child.computeTabList ();
+               if (childList.length != 0) {
+                       Widget [] newResult = new Widget [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;
+}
+
+@Override
+Point computeSizeInPixels (int wHint, int hHint, boolean changed) {
+       display.runSkin ();
+       Point size;
+       if (layout != null) {
+               if (wHint == SWT.DEFAULT || hHint == SWT.DEFAULT) {
+                       changed |= (state & LAYOUT_CHANGED) != 0;
+                       state &= ~LAYOUT_CHANGED;
+                       size = DPIUtil.autoScaleUp(layout.computeSize (this, DPIUtil.autoScaleDown(wHint), DPIUtil.autoScaleDown(hHint), 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;
+       /*
+        * Since computeTrim can be overridden by subclasses, we cannot
+        * call computeTrimInPixels directly.
+        */
+       Rectangle trim = DPIUtil.autoScaleUp(computeTrim (0, 0, DPIUtil.autoScaleDown(size.x), DPIUtil.autoScaleDown(size.y)));
+       return new Point (trim.width, trim.height);
+}
+
+/**
+ * Copies a rectangular area of the receiver at the specified
+ * position using the gc.
+ *
+ * @param gc the gc where the rectangle is to be filled
+ * @param x the x coordinate of the rectangle to be filled
+ * @param y the y coordinate of the rectangle to be filled
+ * @param width the width of the rectangle to be filled
+ * @param height the height of the rectangle to be filled
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the gc is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the gc has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ */
+/*public*/ void copyArea (GC gc, int x, int y, int width, int height) {
+       checkWidget ();
+       if (gc == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (gc.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+
+       //XP only, no GDI+
+       //#define PW_CLIENTONLY 0x00000001
+       //DCOrg() wrong
+       //topHandle wrong for Tree?
+       long hDC = gc.handle;
+       int nSavedDC = OS.SaveDC (hDC);
+       OS.IntersectClipRect (hDC, 0, 0, width, height);
+
+       //WRONG PARENT
+       POINT lpPoint = new POINT ();
+       long hwndParent = OS.GetParent (handle);
+       OS.MapWindowPoints (handle, hwndParent, lpPoint, 1);
+       RECT rect = new RECT ();
+       OS.GetWindowRect (handle, rect);
+       POINT lpPoint1 = new POINT (), lpPoint2 = new POINT ();
+       x = x + (lpPoint.x - rect.left);
+       y = y + (lpPoint.y - rect.top);
+       OS.SetWindowOrgEx (hDC, x, y, lpPoint1);
+       OS.SetBrushOrgEx (hDC, x, y, lpPoint2);
+       int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+       if ((bits & OS.WS_VISIBLE) == 0) {
+               OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
+       }
+       //NECESSARY?
+       OS.RedrawWindow (handle, null, 0, OS.RDW_UPDATENOW | OS.RDW_ALLCHILDREN);
+       OS.PrintWindow (handle, hDC, 0);//0x00000001);
+       if ((bits & OS.WS_VISIBLE) == 0) {
+               OS.DefWindowProc(handle, OS.WM_SETREDRAW, 0, 0);
+       }
+       OS.RestoreDC (hDC, nSavedDC);
+}
+
+@Override
+void createHandle () {
+       super.createHandle ();
+       state |= CANVAS;
+       if ((style & (SWT.H_SCROLL | SWT.V_SCROLL)) == 0 || findThemeControl () == parent) {
+               state |= THEME_BACKGROUND;
+       }
+       if ((style & SWT.TRANSPARENT) != 0) {
+               int bits = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
+               bits |= OS.WS_EX_TRANSPARENT;
+               OS.SetWindowLong (handle, OS.GWL_EXSTYLE, bits);
+       }
+}
+
+@Override
+int applyThemeBackground () {
+       /*
+        * Composite with scrollbars would not inherit the theme because it was
+        * probably being used to implement a control similar to a Text, List,
+        * Table, or Tree, and those controls do not inherit the background theme.
+        * We assume that a Composite that did not have scrollbars was probably just
+        * being used to group some other controls, therefore it should inherit.
+        *
+        * But when Composite background is set to COLOR_TRANSPARENT (i.e.
+        * backgroundAlpha as '0') which means parent theme should be inherited, so
+        * enable the THEME_BACKGROUND in 'state' to support background transparent.
+        * Refer bug 463127 & related bug 234649.
+        */
+       return (backgroundAlpha == 0 || (style & (SWT.H_SCROLL | SWT.V_SCROLL)) == 0 || findThemeControl () == parent) ? 1 : 0;
+}
+
+/**
+ * Fills the interior of the rectangle specified by the arguments,
+ * with the receiver's background.
+ *
+ * <p>The <code>offsetX</code> and <code>offsetY</code> are used to map from
+ * the <code>gc</code> origin to the origin of the parent image background. This is useful
+ * to ensure proper alignment of the image background.</p>
+ *
+ * @param gc the gc where the rectangle is to be filled
+ * @param x the x coordinate of the rectangle to be filled
+ * @param y the y coordinate of the rectangle to be filled
+ * @param width the width of the rectangle to be filled
+ * @param height the height of the rectangle to be filled
+ * @param offsetX the image background x offset
+ * @param offsetY the image background y offset
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_NULL_ARGUMENT - if the gc is null</li>
+ *    <li>ERROR_INVALID_ARGUMENT - if the gc has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
+ * </ul>
+ *
+ * @since 3.6
+ */
+public void drawBackground (GC gc, int x, int y, int width, int height, int offsetX, int offsetY) {
+       checkWidget ();
+       x = DPIUtil.autoScaleUp(x);
+       y = DPIUtil.autoScaleUp(y);
+       width = DPIUtil.autoScaleUp(width);
+       height = DPIUtil.autoScaleUp(height);
+       offsetX = DPIUtil.autoScaleUp(offsetX);
+       offsetY = DPIUtil.autoScaleUp(offsetY);
+       drawBackgroundInPixels(gc, x, y, width, height, offsetX, offsetY);
+}
+
+void drawBackgroundInPixels(GC gc, int x, int y, int width, int height, int offsetX, int offsetY) {
+       if (gc == null) error (SWT.ERROR_NULL_ARGUMENT);
+       if (gc.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
+       RECT rect = new RECT ();
+       OS.SetRect (rect, x, y, x + width, y + height);
+       long hDC = gc.handle;
+       int pixel = background == -1 ? gc.getBackground ().handle : -1;
+       drawBackground (hDC, rect, pixel, offsetX, offsetY);
+}
+
+Composite findDeferredControl () {
+       return layoutCount > 0 ? this : parent.findDeferredControl ();
+}
+
+@Override
+Menu [] findMenus (Control control) {
+       if (control == this) return new Menu [0];
+       Menu result [] = super.findMenus (control);
+       Control [] children = _getChildren ();
+       for (int i=0; i<children.length; i++) {
+               Control child = children [i];
+               Menu [] menuList = child.findMenus (control);
+               if (menuList.length != 0) {
+                       Menu [] newResult = new Menu [result.length + menuList.length];
+                       System.arraycopy (result, 0, newResult, 0, result.length);
+                       System.arraycopy (menuList, 0, newResult, result.length, menuList.length);
+                       result = newResult;
+               }
+       }
+       return result;
+}
+
+@Override
+void fixChildren (Shell newShell, Shell oldShell, Decorations newDecorations, Decorations oldDecorations, Menu [] menus) {
+       super.fixChildren (newShell, oldShell, newDecorations, oldDecorations, menus);
+       Control [] children = _getChildren ();
+       for (int i=0; i<children.length; i++) {
+               children [i].fixChildren (newShell, oldShell, newDecorations, oldDecorations, menus);
+       }
+}
+
+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;
+}
+
+/**
+ * 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>INHERIT_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 ();
+}
+
+int getChildrenCount () {
+       /*
+       * NOTE: The current implementation will count
+       * non-registered children.
+       */
+       int count = 0;
+       long hwndChild = OS.GetWindow (handle, OS.GW_CHILD);
+       while (hwndChild != 0) {
+               count++;
+               hwndChild = OS.GetWindow (hwndChild, OS.GW_HWNDNEXT);
+       }
+       return count;
+}
+
+/**
+ * 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;
+}
+
+/**
+ * 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 hooksKeys () {
+       return hooks (SWT.KeyDown) || hooks (SWT.KeyUp);
+}
+
+/**
+ * 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 ;
+}
+
+/**
+ * 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;
+}
+
+/**
+ * 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>
+ * Use of this method is discouraged since it is the least-efficient
+ * way to trigger a layout. The use of <code>layout(true)</code>
+ * discards all cached layout information, even from controls which
+ * have not changed. It is much more efficient to invoke
+ * {@link Control#requestLayout()} on every control which has changed
+ * in the layout than it is to invoke this method on the layout itself.
+ * </p>
+ * <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>
+ * It is normally more efficient to invoke {@link Control#requestLayout()}
+ * on every control which has changed in the layout than it is to invoke
+ * this method on the layout itself. Clients are encouraged to use
+ * {@link Control#requestLayout()} where possible instead of calling
+ * this method.
+ * </p>
+ * <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>
+ * It is normally more efficient to invoke {@link Control#requestLayout()}
+ * on every control which has changed in the layout than it is to invoke
+ * this method on the layout itself. Clients are encouraged to use
+ * {@link Control#requestLayout()} where possible instead of calling
+ * this method.
+ * </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>
+ * It is normally more efficient to invoke {@link Control#requestLayout()}
+ * on every control which has changed in the layout than it is to invoke
+ * this method on the layout itself. Clients are encouraged to use
+ * {@link Control#requestLayout()} where possible instead of calling
+ * this method.
+ * </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 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);
+       layout (changed, SWT.NONE);
+}
+
+/**
+ * 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.
+ * <p>
+ * The parameter <code>flags</code> may be a combination of:
+ * </p>
+ * <dl>
+ * <dt><b>SWT.ALL</b></dt>
+ * <dd>all children in the receiver's widget tree should be laid out</dd>
+ * <dt><b>SWT.CHANGED</b></dt>
+ * <dd>the layout must flush its caches</dd>
+ * <dt><b>SWT.DEFER</b></dt>
+ * <dd>layout will be deferred</dd>
+ * </dl>
+ * <p>
+ * When the <code>changed</code> array is specified, the flags <code>SWT.ALL</code>
+ * and <code>SWT.CHANGED</code> have no effect. In this case, 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>
+ * <p>
+ * When the <code>changed</code> array is not specified, the flag <code>SWT.ALL</code>
+ * indicates that the whole widget tree should be laid out. And the flag
+ * <code>SWT.CHANGED</code> indicates that the layouts should flush any cached
+ * information for all controls that are laid out.
+ * </p>
+ * <p>
+ * The <code>SWT.DEFER</code> flag always causes the layout to be deferred by
+ * calling <code>Composite.setLayoutDeferred(true)</code> and scheduling a call
+ * to <code>Composite.setLayoutDeferred(false)</code>, which will happen when
+ * appropriate (usually before the next event is handled). When this flag is set,
+ * the application should not call <code>Composite.setLayoutDeferred(boolean)</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 a control that has had a state change which requires a recalculation of its size
+ * @param flags the flags specifying how the layout should happen
+ *
+ * @exception IllegalArgumentException <ul>
+ *    <li>ERROR_INVALID_ARGUMENT - if any of the controls in changed is null or has 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.6
+ */
+public void layout (Control [] changed, int flags) {
+       checkWidget ();
+       if (changed != null) {
+               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;
+                       // Update layout when the list of children has changed.
+                       // See bug 497812.
+                       child.markLayout(false, false);
+                       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;
+                       }
+               }
+               if (!display.externalEventLoop && (flags & SWT.DEFER) != 0) {
+                       setLayoutDeferred (true);
+                       display.addLayoutDeferred (this);
+               }
+               for (int i=updateCount-1; i>=0; i--) {
+                       update [i].updateLayout (false);
+               }
+       } else {
+               if (layout == null && (flags & SWT.ALL) == 0) return;
+               markLayout ((flags & SWT.CHANGED) != 0, (flags & SWT.ALL) != 0);
+               if (!display.externalEventLoop && (flags & SWT.DEFER) != 0) {
+                       setLayoutDeferred (true);
+                       display.addLayoutDeferred (this);
+               }
+               updateLayout ((flags & SWT.ALL) != 0);
+       }
+}
+
+@Override
+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 ();
+       /*
+        * Since getClientArea can be overridden by subclasses, we cannot
+        * call getClientAreaInPixels directly.
+        */
+       Rectangle clientArea = DPIUtil.autoScaleUp(getClientArea ());
+       int width = 0, height = 0;
+       for (int i=0; i<children.length; i++) {
+               Rectangle rect = DPIUtil.autoScaleUp(children [i].getBounds ());
+               width = Math.max (width, rect.x - clientArea.x + rect.width);
+               height = Math.max (height, rect.y - clientArea.y + rect.height);
+       }
+       return new Point (width, height);
+}
+
+@Override
+boolean redrawChildren () {
+       if (!super.redrawChildren ()) return false;
+       Control [] children = _getChildren ();
+       for (int i=0; i<children.length; i++) {
+               children [i].redrawChildren ();
+       }
+       return true;
+}
+
+@Override
+void releaseParent () {
+       super.releaseParent ();
+       if ((state & CANVAS) != 0) {
+               if ((style & SWT.TRANSPARENT) != 0) {
+                       long hwndParent = parent.handle;
+                       long hwndChild = OS.GetWindow (hwndParent, OS.GW_CHILD);
+                       while (hwndChild != 0) {
+                               if (hwndChild != handle) {
+                                       int bits = OS.GetWindowLong (hwndParent, OS.GWL_EXSTYLE);
+                                       if ((bits & OS.WS_EX_TRANSPARENT) != 0) return;
+                               }
+                               hwndChild = OS.GetWindow (hwndChild, OS.GW_HWNDNEXT);
+                       }
+                       int bits = OS.GetWindowLong (hwndParent, OS.GWL_EXSTYLE);
+                       bits &= ~OS.WS_EX_COMPOSITED;
+                       OS.SetWindowLong (hwndParent, OS.GWL_EXSTYLE, bits);
+               }
+       }
+}
+
+@Override
+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);
+}
+
+@Override
+void releaseWidget () {
+       super.releaseWidget ();
+       if ((state & CANVAS) != 0 && (style & SWT.EMBEDDED) != 0) {
+               long hwndChild = OS.GetWindow (handle, OS.GW_CHILD);
+               if (hwndChild != 0) {
+                       int threadId = OS.GetWindowThreadProcessId (hwndChild, null);
+                       if (threadId != OS.GetCurrentThreadId ()) {
+                               OS.ShowWindow (hwndChild, OS.SW_HIDE);
+                               OS.SetParent (hwndChild, 0);
+                       }
+               }
+       }
+       layout = null;
+       tabList = null;
+       lpwp = null;
+}
+
+void removeControl (Control control) {
+       fixTabList (control);
+       resizeChildren ();
+}
+
+@Override
+void reskinChildren (int flags) {
+       super.reskinChildren (flags);
+       Control [] children = _getChildren ();
+       for (int i=0; i<children.length; i++) {
+               Control child = children [i];
+               if (child != null) child.reskin (flags);
+       }
+}
+
+void resizeChildren () {
+       if (lpwp == null) return;
+       do {
+               WINDOWPOS [] currentLpwp = lpwp;
+               lpwp = null;
+               if (!resizeChildren (true, currentLpwp)) {
+                       resizeChildren (false, currentLpwp);
+               }
+       } while (lpwp != null);
+}
+
+boolean resizeChildren (boolean defer, WINDOWPOS [] pwp) {
+       if (pwp == null) return true;
+       long hdwp = 0;
+       if (defer) {
+               hdwp = OS.BeginDeferWindowPos (pwp.length);
+               if (hdwp == 0) return false;
+       }
+       for (int i=0; i<pwp.length; i++) {
+               WINDOWPOS wp = pwp [i];
+               if (wp != null) {
+                       /*
+                       * This code is intentionally commented.  All widgets that
+                       * are created by SWT have WS_CLIPSIBLINGS to ensure that
+                       * application code does not draw outside of the control.
+                       */
+//                     int count = parent.getChildrenCount ();
+//                     if (count > 1) {
+//                             int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+//                             if ((bits & OS.WS_CLIPSIBLINGS) == 0) wp.flags |= OS.SWP_NOCOPYBITS;
+//                     }
+                       if (defer) {
+                               hdwp = OS.DeferWindowPos (hdwp, wp.hwnd, 0, wp.x, wp.y, wp.cx, wp.cy, wp.flags);
+                               if (hdwp == 0) return false;
+                       } else {
+                               OS.SetWindowPos (wp.hwnd, 0, wp.x, wp.y, wp.cx, wp.cy, wp.flags);
+                       }
+               }
+       }
+       if (defer) return OS.EndDeferWindowPos (hdwp);
+       return true;
+}
+
+void resizeEmbeddedHandle(long embeddedHandle, int width, int height) {
+       if (embeddedHandle == 0) return;
+       int [] processID = new int [1];
+       int threadId = OS.GetWindowThreadProcessId (embeddedHandle, processID);
+       if (threadId != OS.GetCurrentThreadId ()) {
+               if (processID [0] == OS.GetCurrentProcessId ()) {
+                       if (display.msgHook == 0) {
+                               display.getMsgCallback = new Callback (display, "getMsgProc", 3);
+                               display.getMsgProc = display.getMsgCallback.getAddress ();
+                               if (display.getMsgProc == 0) error (SWT.ERROR_NO_MORE_CALLBACKS);
+                               display.msgHook = OS.SetWindowsHookEx (OS.WH_GETMESSAGE, display.getMsgProc, OS.GetLibraryHandle(), threadId);
+                               OS.PostThreadMessage (threadId, OS.WM_NULL, 0, 0);
+                       }
+               }
+               int flags = OS.SWP_NOZORDER | OS.SWP_DRAWFRAME | OS.SWP_NOACTIVATE | OS.SWP_ASYNCWINDOWPOS;
+               OS.SetWindowPos (embeddedHandle, 0, 0, 0, width, height, flags);
+       }
+}
+
+@Override
+void sendResize () {
+       setResizeChildren (false);
+       super.sendResize ();
+       if (isDisposed ()) return;
+       if (layout != null) {
+               markLayout (false, false);
+               updateLayout (false, false);
+       }
+       setResizeChildren (true);
+}
+
+/**
+ * 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 ();
+       }
+}
+
+@Override
+void setBoundsInPixels (int x, int y, int width, int height, int flags, boolean defer) {
+       if (display.resizeCount > Display.RESIZE_LIMIT) {
+               defer = false;
+       }
+       if (!defer && (state & CANVAS) != 0) {
+               state &= ~(RESIZE_OCCURRED | MOVE_OCCURRED);
+               state |= RESIZE_DEFERRED | MOVE_DEFERRED;
+       }
+       super.setBoundsInPixels (x, y, width, height, flags, defer);
+       if (!defer && (state & CANVAS) != 0) {
+               boolean wasMoved = (state & MOVE_OCCURRED) != 0;
+               boolean wasResized = (state & RESIZE_OCCURRED) != 0;
+               state &= ~(RESIZE_DEFERRED | MOVE_DEFERRED);
+               if (wasMoved && !isDisposed ()) sendMove ();
+               if (wasResized && !isDisposed ()) sendResize ();
+       }
+}
+
+@Override
+public boolean setFocus () {
+       checkWidget ();
+       Control [] children = _getChildren ();
+       for (int i=0; i<children.length; i++) {
+               Control child = children [i];
+               if (child.setRadioFocus (false)) return true;
+       }
+       for (int i=0; i<children.length; i++) {
+               Control child = children [i];
+               if (child.setFocus ()) return true;
+       }
+       return super.setFocus ();
+}
+
+/**
+ * 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) {
+       checkWidget();
+       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 setResizeChildren (boolean resize) {
+       if (resize) {
+               resizeChildren ();
+       } else {
+               if (display.resizeCount > Display.RESIZE_LIMIT) {
+                       return;
+               }
+               int count = getChildrenCount ();
+               if (count > 1 && lpwp == null) {
+                       lpwp = new WINDOWPOS [count];
+               }
+       }
+}
+
+@Override
+boolean setTabGroupFocus () {
+       if (isTabItem ()) return setTabItemFocus ();
+       boolean takeFocus = (style & SWT.NO_FOCUS) == 0;
+       if ((state & CANVAS) != 0) {
+               takeFocus = hooksKeys ();
+               if ((style & SWT.EMBEDDED) != 0) takeFocus = true;
+       }
+       if (takeFocus && setTabItemFocus ()) return true;
+       Control [] children = _getChildren ();
+       for (int i=0; i<children.length; i++) {
+               Control child = children [i];
+               if (child.isTabItem () && child.setRadioFocus (true)) return true;
+       }
+       for (int i=0; i<children.length; i++) {
+               Control child = children [i];
+               if (child.isTabItem () && !child.isTabGroup () && child.setTabItemFocus ()) {
+                       return true;
+               }
+       }
+       return false;
+}
+
+@Override
+boolean updateTextDirection(int textDirection) {
+       super.updateTextDirection (textDirection);
+       /*
+        * Always continue, communicating the direction to the children since
+        * OS.WS_EX_RTLREADING doesn't propagate to them natively, and since
+        * the direction might need to be handled by each child individually.
+        */
+       Control[] children = _getChildren ();
+       int i = children.length;
+       while (i-- > 0) {
+               if (children[i] != null && !children[i].isDisposed ()) {
+                       children[i].updateTextDirection(textDirection);
+               }
+       }
+       /*
+        * Return value indicates whether or not to update derivatives, so in case
+        * of AUTO always return true regardless of the actual update.
+        */
+       return true;
+}
+
+String toolTipText (NMTTDISPINFO hdr) {
+       Shell shell = getShell ();
+       if ((hdr.uFlags & OS.TTF_IDISHWND) == 0) {
+               String string = null;
+               ToolTip toolTip = shell.findToolTip ((int)hdr.idFrom);
+               if (toolTip != null) {
+                       string = toolTip.message;
+                       if (string == null || string.length () == 0) string = " ";
+                       /*
+                       * Bug in Windows.  On Windows 7, tool tips hang when displaying large
+                       * unwrapped strings. The fix is to wrap the string ourselves.
+                       */
+                       if (string.length () > TOOLTIP_LIMIT / 4) {
+                               string = display.wrapText (string, handle, toolTip.getWidth ());
+                       }
+               }
+               return string;
+       }
+       shell.setToolTipTitle (hdr.hwndFrom, null, 0);
+       OS.SendMessage (hdr.hwndFrom, OS.TTM_SETMAXTIPWIDTH, 0, 0x7FFF);
+       Control control = display.getControl (hdr.idFrom);
+       return control != null ? control.toolTipText : null;
+}
+
+@Override
+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;
+}
+
+@Override
+boolean translateTraversal (MSG msg) {
+       if ((state & CANVAS) != 0 ) {
+               if ((style & SWT.EMBEDDED) != 0) return false;
+               switch ((int)msg.wParam) {
+                       case OS.VK_UP:
+                       case OS.VK_LEFT:
+                       case OS.VK_DOWN:
+                       case OS.VK_RIGHT:
+                       case OS.VK_PRIOR:
+                       case OS.VK_NEXT:
+                               int uiState = (int)OS.SendMessage (msg.hwnd, OS.WM_QUERYUISTATE, 0, 0);
+                               if ((uiState & OS.UISF_HIDEFOCUS) != 0) {
+                                       OS.SendMessage (msg.hwnd, OS.WM_UPDATEUISTATE, OS.MAKEWPARAM (OS.UIS_CLEAR, OS.UISF_HIDEFOCUS), 0);
+                               }
+                               break;
+               }
+       }
+       return super.translateTraversal (msg);
+}
+
+@Override
+void updateBackgroundColor () {
+       super.updateBackgroundColor ();
+       Control [] children = _getChildren ();
+       for (int i=0; i<children.length; i++) {
+               if ((children [i].state & PARENT_BACKGROUND) != 0) {
+                       children [i].updateBackgroundColor ();
+               }
+       }
+}
+
+@Override
+void updateBackgroundImage () {
+       super.updateBackgroundImage ();
+       Control [] children = _getChildren ();
+       for (int i=0; i<children.length; i++) {
+               if ((children [i].state & PARENT_BACKGROUND) != 0) {
+                       children [i].updateBackgroundImage ();
+               }
+       }
+}
+
+@Override
+void updateBackgroundMode () {
+       super.updateBackgroundMode ();
+       Control [] children = _getChildren ();
+       for (int i = 0; i < children.length; i++) {
+               children [i].updateBackgroundMode ();
+       }
+}
+
+@Override
+void updateFont (Font oldFont, Font newFont) {
+       super.updateFont (oldFont, newFont);
+       Control [] children = _getChildren ();
+       for (int i=0; i<children.length; i++) {
+               Control control = children [i];
+               if (!control.isDisposed ()) {
+                       control.updateFont (oldFont, newFont);
+               }
+       }
+}
+
+void updateLayout (boolean all) {
+       updateLayout (true, all);
+}
+
+@Override
+void updateLayout (boolean resize, 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);
+               display.runSkin();
+               if (resize) setResizeChildren (false);
+               layout.layout (this, changed);
+               if (resize) setResizeChildren (true);
+       }
+       if (all) {
+               state &= ~LAYOUT_CHILD;
+               Control [] children = _getChildren ();
+               for (int i=0; i<children.length; i++) {
+                       children [i].updateLayout (resize, all);
+               }
+       }
+}
+
+@Override
+void updateOrientation () {
+       Control [] controls = _getChildren ();
+       RECT [] rects = new RECT [controls.length];
+       for (int i=0; i<controls.length; i++) {
+               Control control = controls [i];
+               RECT rect = rects [i] = new RECT();
+               control.forceResize ();
+               OS.GetWindowRect (control.topHandle (), rect);
+               OS.MapWindowPoints (0, handle, rect, 2);
+       }
+       int orientation = style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT);
+       super.updateOrientation ();
+       for (int i=0; i<controls.length; i++) {
+               Control control = controls [i];
+               RECT rect = rects [i];
+               control.setOrientation (orientation);
+               int flags = OS.SWP_NOSIZE | OS.SWP_NOZORDER | OS.SWP_NOACTIVATE;
+               OS.SetWindowPos (control.topHandle (), 0, rect.left, rect.top, 0, 0, flags);
+       }
+}
+
+void updateUIState () {
+       long hwndShell = getShell ().handle;
+       int uiState = (int)OS.SendMessage (hwndShell, OS.WM_QUERYUISTATE, 0, 0);
+       if ((uiState & OS.UISF_HIDEFOCUS) != 0) {
+               OS.SendMessage (hwndShell, OS.WM_CHANGEUISTATE, OS.MAKEWPARAM (OS.UIS_CLEAR, OS.UISF_HIDEFOCUS), 0);
+       }
+}
+
+@Override
+int widgetStyle () {
+       /* Force clipping of children by setting WS_CLIPCHILDREN */
+       return super.widgetStyle () | OS.WS_CLIPCHILDREN;
+}
+
+@Override
+LRESULT WM_ERASEBKGND (long wParam, long lParam) {
+       LRESULT result = super.WM_ERASEBKGND (wParam, lParam);
+       if (result != null) return result;
+       if ((state & CANVAS) != 0) {
+               /* Return zero to indicate that the background was not erased */
+               if ((style & (SWT.NO_BACKGROUND | SWT.TRANSPARENT)) != 0) {
+                       return LRESULT.ZERO;
+               }
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_GETDLGCODE (long wParam, long lParam) {
+       LRESULT result = super.WM_GETDLGCODE (wParam, lParam);
+       if (result != null) return result;
+       if ((state & CANVAS) != 0) {
+               int flags = 0;
+               if (hooksKeys ()) {
+                       flags |= OS.DLGC_WANTALLKEYS | OS.DLGC_WANTARROWS | OS.DLGC_WANTTAB;
+               }
+               if ((style & SWT.NO_FOCUS) != 0) flags |= OS.DLGC_STATIC;
+               if (OS.GetWindow (handle, OS.GW_CHILD) != 0) flags |= OS.DLGC_STATIC;
+               if (flags != 0) return new LRESULT (flags);
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_GETFONT (long wParam, long lParam) {
+       LRESULT result = super.WM_GETFONT (wParam, lParam);
+       if (result != null) return result;
+       long code = callWindowProc (handle, OS.WM_GETFONT, wParam, lParam);
+       if (code != 0) return new LRESULT (code);
+       return new LRESULT (font != null ? font.handle : defaultFont ());
+}
+
+@Override
+LRESULT WM_LBUTTONDOWN (long wParam, long lParam) {
+       LRESULT result = super.WM_LBUTTONDOWN (wParam, lParam);
+       if (result == LRESULT.ZERO) return result;
+
+       /* Set focus for a canvas with no children */
+       if ((state & CANVAS) != 0) {
+               if ((style & SWT.NO_FOCUS) == 0 && hooksKeys ()) {
+                       if (OS.GetWindow (handle, OS.GW_CHILD) == 0) setFocus ();
+               }
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_NCHITTEST (long wParam, long lParam) {
+       LRESULT result = super.WM_NCHITTEST (wParam, lParam);
+       if (result != null) return result;
+       /*
+       * Bug in Windows.  For some reason, under circumstances
+       * that are not understood, when one scrolled window is
+       * embedded in another and the outer window scrolls the
+       * inner horizontally by moving the location of the inner
+       * one, the vertical scroll bars of the inner window no
+       * longer function.  Specifically, WM_NCHITTEST returns
+       * HTCLIENT instead of HTVSCROLL.  The fix is to detect
+       * the case where the result of WM_NCHITTEST is HTCLIENT
+       * and the point is not in the client area, and redraw
+       * the trim, which somehow fixes the next WM_NCHITTEST.
+       */
+       if (OS.IsAppThemed ()) {
+               if ((state & CANVAS)!= 0) {
+                       long code = callWindowProc (handle, OS.WM_NCHITTEST, wParam, lParam);
+                       if (code == OS.HTCLIENT) {
+                               RECT rect = new RECT ();
+                               OS.GetClientRect (handle, rect);
+                               POINT pt = new POINT ();
+                               pt.x = OS.GET_X_LPARAM (lParam);
+                               pt.y = OS.GET_Y_LPARAM (lParam);
+                               OS.MapWindowPoints (0, handle, pt, 1);
+                               if (!OS.PtInRect (rect, pt)) {
+                                       int flags = OS.RDW_FRAME | OS.RDW_INVALIDATE;
+                                       OS.RedrawWindow (handle, null, 0, flags);
+                               }
+                       }
+                       return new LRESULT (code);
+               }
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_PARENTNOTIFY (long wParam, long lParam) {
+       if ((state & CANVAS) != 0 && (style & SWT.EMBEDDED) != 0) {
+               if (OS.LOWORD (wParam) == OS.WM_CREATE) {
+                       RECT rect = new RECT ();
+                       OS.GetClientRect (handle, rect);
+                       resizeEmbeddedHandle (lParam, rect.right - rect.left, rect.bottom - rect.top);
+               }
+       }
+       return super.WM_PARENTNOTIFY (wParam, lParam);
+}
+
+@Override
+LRESULT WM_PAINT (long wParam, long lParam) {
+       if ((state & DISPOSE_SENT) != 0) return LRESULT.ZERO;
+       if ((state & CANVAS) == 0 || (state & FOREIGN_HANDLE) != 0) {
+               return super.WM_PAINT (wParam, lParam);
+       }
+
+       /* Set the clipping bits */
+       int oldBits = OS.GetWindowLong (handle, OS.GWL_STYLE);
+       int newBits = oldBits | OS.WS_CLIPSIBLINGS | OS.WS_CLIPCHILDREN;
+       if (newBits != oldBits) OS.SetWindowLong (handle, OS.GWL_STYLE, newBits);
+
+       /* Paint the control and the background */
+       PAINTSTRUCT ps = new PAINTSTRUCT ();
+       if (hooks (SWT.Paint) || filters (SWT.Paint)) {
+
+               /* Use the buffered paint when possible */
+               boolean bufferedPaint = false;
+               if ((style & SWT.DOUBLE_BUFFERED) != 0) {
+                       if ((style & (SWT.NO_MERGE_PAINTS | SWT.RIGHT_TO_LEFT | SWT.TRANSPARENT)) == 0) {
+                               bufferedPaint = true;
+                       }
+               }
+               if (bufferedPaint) {
+                       long hDC = OS.BeginPaint (handle, ps);
+                       int width = ps.right - ps.left;
+                       int height = ps.bottom - ps.top;
+                       if (width != 0 && height != 0) {
+                               long [] phdc = new long [1];
+                               int flags = OS.BPBF_COMPATIBLEBITMAP;
+                               RECT prcTarget = new RECT ();
+                               OS.SetRect (prcTarget, ps.left, ps.top, ps.right, ps.bottom);
+                               long hBufferedPaint = OS.BeginBufferedPaint (hDC, prcTarget, flags, null, phdc);
+                               GCData data = new GCData ();
+                               data.device = display;
+                               data.foreground = getForegroundPixel ();
+                               Control control = findBackgroundControl ();
+                               if (control == null) control = this;
+                               data.background = control.getBackgroundPixel ();
+                               data.font = Font.win32_new(display, OS.SendMessage (handle, OS.WM_GETFONT, 0, 0));
+                               data.uiState = (int)OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
+                               if ((style & SWT.NO_BACKGROUND) != 0) {
+                                       /* This code is intentionally commented because it may be slow to copy bits from the screen */
+                                       //paintGC.copyArea (image, ps.left, ps.top);
+                               } else {
+                                       RECT rect = new RECT ();
+                                       OS.SetRect (rect, ps.left, ps.top, ps.right, ps.bottom);
+                                       drawBackground (phdc [0], rect);
+                               }
+                               GC gc = GC.win32_new (phdc [0], data);
+                               Event event = new Event ();
+                               event.gc = gc;
+                               event.setBoundsInPixels(new Rectangle(ps.left, ps.top, width, height));
+                               sendEvent (SWT.Paint, event);
+                               if (data.focusDrawn && !isDisposed ()) updateUIState ();
+                               gc.dispose ();
+                               OS.EndBufferedPaint (hBufferedPaint, true);
+                       }
+                       OS.EndPaint (handle, ps);
+               } else {
+
+                       /* Create the paint GC */
+                       GCData data = new GCData ();
+                       data.ps = ps;
+                       data.hwnd = handle;
+                       GC gc = GC.win32_new (this, data);
+
+                       /* Get the system region for the paint HDC */
+                       long sysRgn = 0;
+                       if ((style & (SWT.DOUBLE_BUFFERED | SWT.TRANSPARENT)) != 0 || (style & SWT.NO_MERGE_PAINTS) != 0) {
+                               sysRgn = OS.CreateRectRgn (0, 0, 0, 0);
+                               if (OS.GetRandomRgn (gc.handle, sysRgn, OS.SYSRGN) == 1) {
+                                       if ((OS.GetLayout (gc.handle) & OS.LAYOUT_RTL) != 0) {
+                                               int nBytes = OS.GetRegionData (sysRgn, 0, null);
+                                               int [] lpRgnData = new int [nBytes / 4];
+                                               OS.GetRegionData (sysRgn, nBytes, lpRgnData);
+                                               long newSysRgn = OS.ExtCreateRegion (new float [] {-1, 0, 0, 1, 0, 0}, nBytes, lpRgnData);
+                                               OS.DeleteObject (sysRgn);
+                                               sysRgn = newSysRgn;
+                                       }
+                                       POINT pt = new POINT();
+                                       OS.MapWindowPoints (0, handle, pt, 1);
+                                       OS.OffsetRgn (sysRgn, pt.x, pt.y);
+                               }
+                       }
+
+                       /* Send the paint event */
+                       int width = ps.right - ps.left;
+                       int height = ps.bottom - ps.top;
+                       if (width != 0 && height != 0) {
+                               GC paintGC = null;
+                               Image image = null;
+                               if ((style & (SWT.DOUBLE_BUFFERED | SWT.TRANSPARENT)) != 0) {
+                                       image = new Image (display, width, height);
+                                       paintGC = gc;
+                                       gc = new GC (image, paintGC.getStyle() & SWT.RIGHT_TO_LEFT);
+                                       GCData gcData = gc.getGCData ();
+                                       gcData.uiState = data.uiState;
+                                       gc.setForeground (getForeground ());
+                                       gc.setBackground (getBackground ());
+                                       gc.setFont (getFont ());
+                                       if ((style & SWT.TRANSPARENT) != 0) {
+                                               OS.BitBlt (gc.handle, 0, 0, width, height, paintGC.handle, ps.left, ps.top, OS.SRCCOPY);
+                                       }
+                                       OS.OffsetRgn (sysRgn, -ps.left, -ps.top);
+                                       OS.SelectClipRgn (gc.handle, sysRgn);
+                                       OS.OffsetRgn (sysRgn, ps.left, ps.top);
+                                       OS.SetMetaRgn (gc.handle);
+                                       OS.SetWindowOrgEx (gc.handle, ps.left, ps.top, null);
+                                       OS.SetBrushOrgEx (gc.handle, ps.left, ps.top, null);
+                                       if ((style & (SWT.NO_BACKGROUND | SWT.TRANSPARENT)) != 0) {
+                                               /* This code is intentionally commented because it may be slow to copy bits from the screen */
+                                               //paintGC.copyArea (image, ps.left, ps.top);
+                                       } else {
+                                               RECT rect = new RECT ();
+                                               OS.SetRect (rect, ps.left, ps.top, ps.right, ps.bottom);
+                                               drawBackground (gc.handle, rect);
+                                       }
+                               }
+                               Event event = new Event ();
+                               event.gc = gc;
+                               RECT rect = null;
+                               if ((style & SWT.NO_MERGE_PAINTS) != 0 && OS.GetRgnBox (sysRgn, rect = new RECT ()) == OS.COMPLEXREGION) {
+                                       int nBytes = OS.GetRegionData (sysRgn, 0, null);
+                                       int [] lpRgnData = new int [nBytes / 4];
+                                       OS.GetRegionData (sysRgn, nBytes, lpRgnData);
+                                       int count = lpRgnData [2];
+                                       for (int i=0; i<count; i++) {
+                                               int offset = 8 + (i << 2);
+                                               OS.SetRect (rect, lpRgnData [offset], lpRgnData [offset + 1], lpRgnData [offset + 2], lpRgnData [offset + 3]);
+                                               if ((style & (SWT.DOUBLE_BUFFERED | SWT.NO_BACKGROUND | SWT.TRANSPARENT)) == 0) {
+                                                       drawBackground (gc.handle, rect);
+                                               }
+                                               event.setBoundsInPixels(new Rectangle(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top));
+                                               event.count = count - 1 - i;
+                                               sendEvent (SWT.Paint, event);
+                                       }
+                               } else {
+                                       if ((style & (SWT.DOUBLE_BUFFERED | SWT.NO_BACKGROUND | SWT.TRANSPARENT)) == 0) {
+                                               if (rect == null) rect = new RECT ();
+                                               OS.SetRect (rect, ps.left, ps.top, ps.right, ps.bottom);
+                                               drawBackground (gc.handle, rect);
+                                       }
+                                       event.setBoundsInPixels(new Rectangle(ps.left, ps.top, width, height));
+                                       sendEvent (SWT.Paint, event);
+                               }
+                               // widget could be disposed at this point
+                               event.gc = null;
+                               if ((style & (SWT.DOUBLE_BUFFERED | SWT.TRANSPARENT)) != 0) {
+                                       if (!gc.isDisposed ()) {
+                                               GCData gcData = gc.getGCData ();
+                                               if (gcData.focusDrawn && !isDisposed ()) updateUIState ();
+                                       }
+                                       gc.dispose();
+                                       if (!isDisposed ()) paintGC.drawImage (image, DPIUtil.autoScaleDown(ps.left), DPIUtil.autoScaleDown(ps.top));
+                                       image.dispose ();
+                                       gc = paintGC;
+                               }
+                       }
+                       if (sysRgn != 0) OS.DeleteObject (sysRgn);
+                       if (data.focusDrawn && !isDisposed ()) updateUIState ();
+
+                       /* Dispose the paint GC */
+                       gc.dispose ();
+               }
+       } else {
+               long hDC = OS.BeginPaint (handle, ps);
+               if ((style & (SWT.NO_BACKGROUND | SWT.TRANSPARENT)) == 0) {
+                       RECT rect = new RECT ();
+                       OS.SetRect (rect, ps.left, ps.top, ps.right, ps.bottom);
+                       drawBackground (hDC, rect);
+               }
+               OS.EndPaint (handle, ps);
+       }
+
+       /* Restore the clipping bits */
+       if (!isDisposed ()) {
+               if (newBits != oldBits) {
+                       /*
+                       * It is possible (but unlikely), that application
+                       * code could have disposed the widget in the paint
+                       * event.  If this happens, don't attempt to restore
+                       * the style.
+                       */
+                       if (!isDisposed ()) {
+                               OS.SetWindowLong (handle, OS.GWL_STYLE, oldBits);
+                       }
+               }
+       }
+       return LRESULT.ZERO;
+}
+
+@Override
+LRESULT WM_PRINTCLIENT (long wParam, long lParam) {
+       LRESULT result = super.WM_PRINTCLIENT (wParam, lParam);
+       if (result != null) return result;
+       if ((state & CANVAS) != 0) {
+               forceResize ();
+               int nSavedDC = OS.SaveDC (wParam);
+               RECT rect = new RECT ();
+               OS.GetClientRect (handle, rect);
+               if ((style & (SWT.NO_BACKGROUND | SWT.TRANSPARENT)) == 0) {
+                       drawBackground (wParam, rect);
+               }
+               if (hooks (SWT.Paint) || filters (SWT.Paint)) {
+                       GCData data = new GCData ();
+                       data.device = display;
+                       data.foreground = getForegroundPixel ();
+                       Control control = findBackgroundControl ();
+                       if (control == null) control = this;
+                       data.background = control.getBackgroundPixel ();
+                       data.font = Font.win32_new(display, OS.SendMessage (handle, OS.WM_GETFONT, 0, 0));
+                       data.uiState = (int)OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
+                       GC gc = GC.win32_new (wParam, data);
+                       Event event = new Event ();
+                       event.gc = gc;
+                       event.setBoundsInPixels(new Rectangle(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top));
+                       sendEvent (SWT.Paint, event);
+                       event.gc = null;
+                       gc.dispose ();
+               }
+               OS.RestoreDC (wParam, nSavedDC);
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_SETFONT (long wParam, long lParam) {
+       if (lParam != 0) OS.InvalidateRect (handle, null, true);
+       return super.WM_SETFONT (wParam, lParam);
+}
+
+@Override
+LRESULT WM_SIZE (long wParam, long lParam) {
+       LRESULT result = null;
+       if ((state & RESIZE_DEFERRED) != 0) {
+               result = super.WM_SIZE (wParam, lParam);
+       } else {
+               /* Begin deferred window positioning */
+               setResizeChildren (false);
+
+               /* Resize and Layout */
+               result = super.WM_SIZE (wParam, lParam);
+               /*
+               * It is possible (but unlikely), that application
+               * code could have disposed the widget in the resize
+               * event.  If this happens, end the processing of the
+               * Windows message by returning the result of the
+               * WM_SIZE message.
+               */
+               if (isDisposed ()) return result;
+               if (layout != null) {
+                       markLayout (false, false);
+                       updateLayout (false, false);
+               }
+
+               /* End deferred window positioning */
+               setResizeChildren (true);
+       }
+
+       /* Damage the widget to cause a repaint */
+       if (OS.IsWindowVisible (handle)) {
+               if ((state & CANVAS) != 0) {
+                       if ((style & SWT.NO_REDRAW_RESIZE) == 0) {
+                               if (hooks (SWT.Paint)) {
+                                       OS.InvalidateRect (handle, null, true);
+                               }
+                       }
+               }
+               if (OS.IsAppThemed ()) {
+                       if (findThemeControl () != null) redrawChildren ();
+               }
+       }
+
+       /* Resize the embedded window */
+       if ((state & CANVAS) != 0 && (style & SWT.EMBEDDED) != 0) {
+               resizeEmbeddedHandle (OS.GetWindow (handle, OS.GW_CHILD), OS.LOWORD (lParam), OS.HIWORD (lParam));
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_SYSCOLORCHANGE (long wParam, long lParam) {
+       LRESULT result = super.WM_SYSCOLORCHANGE (wParam, lParam);
+       if (result != null) return result;
+       long hwndChild = OS.GetWindow (handle, OS.GW_CHILD);
+       while (hwndChild != 0) {
+               OS.SendMessage (hwndChild, OS.WM_SYSCOLORCHANGE, 0, 0);
+               hwndChild = OS.GetWindow (hwndChild, OS.GW_HWNDNEXT);
+       }
+       return result;
+}
+
+@Override
+LRESULT WM_SYSCOMMAND (long wParam, long lParam) {
+       LRESULT result = super.WM_SYSCOMMAND (wParam, lParam);
+       if (result != null) return result;
+
+       /*
+       * Check to see if the command is a system command or
+       * a user menu item that was added to the system menu.
+       *
+       * NOTE: This is undocumented.
+       */
+       if ((wParam & 0xF000) == 0) return result;
+
+       /*
+       * Bug in Windows.  When a vertical or horizontal scroll bar is
+       * hidden or shown while the opposite scroll bar is being scrolled
+       * by the user (with WM_HSCROLL code SB_LINEDOWN), the scroll bar
+       * does not redraw properly.  The fix is to detect this case and
+       * redraw the non-client area.
+       */
+       int cmd = (int)wParam & 0xFFF0;
+       switch (cmd) {
+               case OS.SC_HSCROLL:
+               case OS.SC_VSCROLL:
+                       boolean showHBar = horizontalBar != null && horizontalBar.getVisible ();
+                       boolean showVBar = verticalBar != null && verticalBar.getVisible ();
+                       long code = callWindowProc (handle, OS.WM_SYSCOMMAND, wParam, lParam);
+                       if ((showHBar != (horizontalBar != null && horizontalBar.getVisible ())) ||
+                               (showVBar != (verticalBar != null && verticalBar.getVisible ()))) {
+                                       int flags = OS.RDW_FRAME | OS.RDW_INVALIDATE | OS.RDW_UPDATENOW;
+                                       OS.RedrawWindow (handle, null, 0, flags);
+                               }
+                       if (code == 0) return LRESULT.ZERO;
+                       return new LRESULT (code);
+       }
+
+       /* Return the result */
+       return result;
+}
+
+@Override
+LRESULT WM_UPDATEUISTATE (long wParam, long lParam) {
+       LRESULT result = super.WM_UPDATEUISTATE (wParam, lParam);
+       if (result != null) return result;
+       if ((state & CANVAS) != 0 && hooks (SWT.Paint)) {
+               OS.InvalidateRect (handle, null, true);
+       }
+       return result;
+}
+
+@Override
+LRESULT wmNCPaint (long hwnd, long wParam, long lParam) {
+       LRESULT result = super.wmNCPaint (hwnd, wParam, lParam);
+       if (result != null) return result;
+       long borderHandle = borderHandle ();
+       if ((state & CANVAS) != 0 || (hwnd == borderHandle && handle != borderHandle)) {
+               if (OS.IsAppThemed ()) {
+                       int bits1 = OS.GetWindowLong (hwnd, OS.GWL_EXSTYLE);
+                       if ((bits1 & OS.WS_EX_CLIENTEDGE) != 0) {
+                               long code = 0;
+                               int bits2 = OS.GetWindowLong (hwnd, OS.GWL_STYLE);
+                               if ((bits2 & (OS.WS_HSCROLL | OS.WS_VSCROLL)) != 0) {
+                                       code = callWindowProc (hwnd, OS.WM_NCPAINT, wParam, lParam);
+                               }
+                               long hDC = OS.GetWindowDC (hwnd);
+                               RECT rect = new RECT ();
+                               OS.GetWindowRect (hwnd, rect);
+                               rect.right -= rect.left;
+                               rect.bottom -= rect.top;
+                               rect.left = rect.top = 0;
+                               int border = OS.GetSystemMetrics (OS.SM_CXEDGE);
+                               OS.ExcludeClipRect (hDC, border, border, rect.right - border, rect.bottom - border);
+                               OS.DrawThemeBackground (display.hEditTheme (), hDC, OS.EP_EDITTEXT, OS.ETS_NORMAL, rect, null);
+                               OS.ReleaseDC (hwnd, hDC);
+                               return new LRESULT (code);
+                       }
+               }
+       }
+       return result;
+}
+
+@Override
+LRESULT wmNotify (NMHDR hdr, long wParam, long lParam) {
+       switch (hdr.code) {
+               /*
+               * Feature in Windows.  When the tool tip control is
+               * created, the parent of the tool tip is the shell.
+               * If SetParent () is used to reparent the tool bar
+               * into a new shell, the tool tip is not reparented
+               * and pops up underneath the new shell.  The fix is
+               * to make sure the tool tip is a topmost window.
+               */
+               case OS.TTN_SHOW:
+               case OS.TTN_POP: {
+                       /*
+                       * Bug in Windows 98 and NT.  Setting the tool tip to be the
+                       * top most window using HWND_TOPMOST can result in a parent
+                       * dialog shell being moved behind its parent if the dialog
+                       * has a sibling that is currently on top.  The fix is to
+                       * lock the z-order of the active window.
+                       *
+                       * Feature in Windows.  Using SetWindowPos() with HWND_NOTOPMOST
+                       * to clear the topmost state of a window whose parent is already
+                       * topmost clears the topmost state of the parent.  The fix is to
+                       * check if the parent is already on top and neither set or clear
+                       * the topmost status of the tool tip.
+                       */
+                       long hwndParent = hdr.hwndFrom;
+                       do {
+                               hwndParent = OS.GetParent (hwndParent);
+                               if (hwndParent == 0) break;
+                               int bits = OS.GetWindowLong (hwndParent, OS.GWL_EXSTYLE);
+                               if ((bits & OS.WS_EX_TOPMOST) != 0) break;
+                       } while (true);
+                       if (hwndParent != 0) break;
+                       /*
+                        * Bug in Windows.  TTN_SHOW is sent for inactive shells.  When
+                        * SetWindowPos is called as a reaction, inactive shells can
+                        * wrongly end up on top.  The fix is to swallow such requests.
+                        *
+                        * A visible effect is that spurious tool tips can show up and
+                        * disappear in a split second.  This is a mostly harmless
+                        * feature that can also be observed in the Windows Explorer.
+                        * See bug 491627 for more details.
+                        */
+                       if (display.getActiveShell () == null) return LRESULT.ONE;
+
+                       display.lockActiveWindow = true;
+                       int flags = OS.SWP_NOACTIVATE | OS.SWP_NOMOVE | OS.SWP_NOSIZE;
+                       long hwndInsertAfter = hdr.code == OS.TTN_SHOW ? OS.HWND_TOPMOST : OS.HWND_NOTOPMOST;
+                       OS.SetWindowPos (hdr.hwndFrom, hwndInsertAfter, 0, 0, 0, 0, flags);
+                       display.lockActiveWindow = false;
+                       break;
+               }
+               case OS.TTN_GETDISPINFO: {
+                       NMTTDISPINFO lpnmtdi = new NMTTDISPINFO ();
+                       OS.MoveMemory (lpnmtdi, lParam, NMTTDISPINFO.sizeof);
+                       String string = toolTipText (lpnmtdi);
+                       if (string != null) {
+                               Shell shell = getShell ();
+                               string = Display.withCrLf (string);
+                               /*
+                               * Bug in Windows.  On Windows 7, tool tips hang when displaying large
+                               * strings. The fix is to limit the tool tip string to 4Kb.
+                               */
+                               if (string.length() > TOOLTIP_LIMIT) {
+                                       string = string.substring(0, TOOLTIP_LIMIT);
+                               }
+                               /*
+                                * Bug 475858: In Japanese like languages where mnemonics are not taken from the
+                                * source label text but appended in parentheses like "(&M)" at end. In order to
+                                * allow the reuse of such label text as a tool-tip text as well, "(&M)" like
+                                * character sequence has to be removed from the end of CJK-style mnemonics.
+                                */
+                               char [] chars = fixMnemonic (string, false, true);
+
+                               /*
+                               * Ensure that the orientation of the tool tip matches
+                               * the orientation of the control.
+                               */
+                               Widget widget = null;
+                               long hwnd = hdr.idFrom;
+                               if ((lpnmtdi.uFlags & OS.TTF_IDISHWND) != 0) {
+                                       widget = display.getControl (hwnd);
+                               } else {
+                                       if (hdr.hwndFrom == shell.toolTipHandle || hdr.hwndFrom == shell.balloonTipHandle) {
+                                               widget = shell.findToolTip ((int)hdr.idFrom);
+                                       }
+                               }
+                               if (widget != null) {
+                                       int style = widget.getStyle();
+                                       int flags = SWT.RIGHT_TO_LEFT | SWT.FLIP_TEXT_DIRECTION;
+                                       if ((style & flags) != 0 && (style & flags) != flags) {
+                                               lpnmtdi.uFlags |= OS.TTF_RTLREADING;
+                                       } else {
+                                               lpnmtdi.uFlags &= ~OS.TTF_RTLREADING;
+                                       }
+                               }
+                               shell.setToolTipText (lpnmtdi, chars);
+                               OS.MoveMemory (lParam, lpnmtdi, NMTTDISPINFO.sizeof);
+                               return LRESULT.ZERO;
+                       }
+                       break;
+               }
+       }
+       return super.wmNotify (hdr, wParam, lParam);
+}
+
+}