]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/widgets/Composite.java
8289d434800dedff0bfd21e86a80f2cc38e61000
[simantics/platform.git] / bundles / org.eclipse.swt.win32.win32.x86_64 / src / org / eclipse / swt / widgets / Composite.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2019 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *******************************************************************************/
14 package org.eclipse.swt.widgets;
15
16
17 import org.eclipse.swt.*;
18 import org.eclipse.swt.graphics.*;
19 import org.eclipse.swt.internal.*;
20 import org.eclipse.swt.internal.win32.*;
21
22 /**
23  * Instances of this class are controls which are capable
24  * of containing other controls.
25  * <dl>
26  * <dt><b>Styles:</b></dt>
27  * <dd>NO_BACKGROUND, NO_FOCUS, NO_MERGE_PAINTS, NO_REDRAW_RESIZE, NO_RADIO_GROUP, EMBEDDED, DOUBLE_BUFFERED</dd>
28  * <dt><b>Events:</b></dt>
29  * <dd>(none)</dd>
30  * </dl>
31  * <p>
32  * Note: The <code>NO_BACKGROUND</code>, <code>NO_FOCUS</code>, <code>NO_MERGE_PAINTS</code>,
33  * and <code>NO_REDRAW_RESIZE</code> styles are intended for use with <code>Canvas</code>.
34  * They can be used with <code>Composite</code> if you are drawing your own, but their
35  * behavior is undefined if they are used with subclasses of <code>Composite</code> other
36  * than <code>Canvas</code>.
37  * </p><p>
38  * Note: The <code>CENTER</code> style, although undefined for composites, has the
39  * same value as <code>EMBEDDED</code> which is used to embed widgets from other
40  * widget toolkits into SWT.  On some operating systems (GTK), this may cause
41  * the children of this composite to be obscured.
42  * </p><p>
43  * This class may be subclassed by custom control implementors
44  * who are building controls that are constructed from aggregates
45  * of other controls.
46  * </p>
47  *
48  * @see Canvas
49  * @see <a href="http://www.eclipse.org/swt/snippets/#composite">Composite snippets</a>
50  * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
51  */
52 public class Composite extends Scrollable {
53         Layout layout;
54         WINDOWPOS [] lpwp;
55         Control [] tabList;
56         int layoutCount, backgroundMode;
57
58         static final int TOOLTIP_LIMIT = 4096;
59
60 /**
61  * Prevents uninitialized instances from being created outside the package.
62  */
63 Composite () {
64 }
65
66 /**
67  * Constructs a new instance of this class given its parent
68  * and a style value describing its behavior and appearance.
69  * <p>
70  * The style value is either one of the style constants defined in
71  * class <code>SWT</code> which is applicable to instances of this
72  * class, or must be built by <em>bitwise OR</em>'ing together
73  * (that is, using the <code>int</code> "|" operator) two or more
74  * of those <code>SWT</code> style constants. The class description
75  * lists the style constants that are applicable to the class.
76  * Style bits are also inherited from superclasses.
77  * </p>
78  *
79  * @param parent a widget which will be the parent of the new instance (cannot be null)
80  * @param style the style of widget to construct
81  *
82  * @exception IllegalArgumentException <ul>
83  *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
84  * </ul>
85  * @exception SWTException <ul>
86  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
87  * </ul>
88  *
89  * @see SWT#NO_BACKGROUND
90  * @see SWT#NO_FOCUS
91  * @see SWT#NO_MERGE_PAINTS
92  * @see SWT#NO_REDRAW_RESIZE
93  * @see SWT#NO_RADIO_GROUP
94  * @see SWT#EMBEDDED
95  * @see SWT#DOUBLE_BUFFERED
96  * @see Widget#getStyle
97  */
98 public Composite (Composite parent, int style) {
99         super (parent, style);
100 }
101
102 Control [] _getChildren () {
103         int count = 0;
104         long hwndChild = OS.GetWindow (handle, OS.GW_CHILD);
105         if (hwndChild == 0) return new Control [0];
106         while (hwndChild != 0) {
107                 count++;
108                 hwndChild = OS.GetWindow (hwndChild, OS.GW_HWNDNEXT);
109         }
110         Control [] children = new Control [count];
111         int index = 0;
112         hwndChild = OS.GetWindow (handle, OS.GW_CHILD);
113         while (hwndChild != 0) {
114                 Control control = display.getControl (hwndChild);
115                 if (control != null && control != this) {
116                         children [index++] = control;
117                 }
118                 hwndChild = OS.GetWindow (hwndChild, OS.GW_HWNDNEXT);
119         }
120         if (count == index) return children;
121         Control [] newChildren = new Control [index];
122         System.arraycopy (children, 0, newChildren, 0, index);
123         return newChildren;
124 }
125
126 Control [] _getTabList () {
127         if (tabList == null) return tabList;
128         int count = 0;
129         for (int i=0; i<tabList.length; i++) {
130                 if (!tabList [i].isDisposed ()) count++;
131         }
132         if (count == tabList.length) return tabList;
133         Control [] newList = new Control [count];
134         int index = 0;
135         for (int i=0; i<tabList.length; i++) {
136                 if (!tabList [i].isDisposed ()) {
137                         newList [index++] = tabList [i];
138                 }
139         }
140         tabList = newList;
141         return tabList;
142 }
143
144 /**
145  * Clears any data that has been cached by a Layout for all widgets that
146  * are in the parent hierarchy of the changed control up to and including the
147  * receiver.  If an ancestor does not have a layout, it is skipped.
148  *
149  * @param changed an array of controls that changed state and require a recalculation of size
150  *
151  * @exception IllegalArgumentException <ul>
152  *    <li>ERROR_INVALID_ARGUMENT - if the changed array is null any of its controls are null or have been disposed</li>
153  *    <li>ERROR_INVALID_PARENT - if any control in changed is not in the widget tree of the receiver</li>
154  * </ul>
155  * @exception SWTException <ul>
156  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
157  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
158  * </ul>
159  *
160  * @deprecated use {@link Composite#layout(Control[], int)} instead
161  * @since 3.1
162  */
163 @Deprecated
164 public void changed (Control[] changed) {
165         layout(changed, SWT.DEFER);
166 }
167
168 @Override
169 void checkBuffered () {
170         if ((state & CANVAS) == 0) {
171                 super.checkBuffered ();
172         }
173 }
174
175 @Override
176 void checkComposited () {
177         if ((state & CANVAS) != 0) {
178                 if ((style & SWT.TRANSPARENT) != 0) {
179                         long hwndParent = parent.handle;
180                         int bits = OS.GetWindowLong (hwndParent, OS.GWL_EXSTYLE);
181                         bits |= OS.WS_EX_COMPOSITED;
182                         OS.SetWindowLong (hwndParent, OS.GWL_EXSTYLE, bits);
183                 }
184         }
185 }
186
187 @Override
188 protected void checkSubclass () {
189         /* Do nothing - Subclassing is allowed */
190 }
191
192 @Override
193 Widget [] computeTabList () {
194         Widget result [] = super.computeTabList ();
195         if (result.length == 0) return result;
196         Control [] list = tabList != null ? _getTabList () : _getChildren ();
197         for (int i=0; i<list.length; i++) {
198                 Control child = list [i];
199                 Widget  [] childList = child.computeTabList ();
200                 if (childList.length != 0) {
201                         Widget [] newResult = new Widget [result.length + childList.length];
202                         System.arraycopy (result, 0, newResult, 0, result.length);
203                         System.arraycopy (childList, 0, newResult, result.length, childList.length);
204                         result = newResult;
205                 }
206         }
207         return result;
208 }
209
210 @Override
211 Point computeSizeInPixels (int wHint, int hHint, boolean changed) {
212         display.runSkin ();
213         Point size;
214         if (layout != null) {
215                 if (wHint == SWT.DEFAULT || hHint == SWT.DEFAULT) {
216                         changed |= (state & LAYOUT_CHANGED) != 0;
217                         state &= ~LAYOUT_CHANGED;
218                         size = DPIUtil.autoScaleUp(layout.computeSize (this, DPIUtil.autoScaleDown(wHint), DPIUtil.autoScaleDown(hHint), changed));
219                 } else {
220                         size = new Point (wHint, hHint);
221                 }
222         } else {
223                 size = minimumSize (wHint, hHint, changed);
224                 if (size.x == 0) size.x = DEFAULT_WIDTH;
225                 if (size.y == 0) size.y = DEFAULT_HEIGHT;
226         }
227         if (wHint != SWT.DEFAULT) size.x = wHint;
228         if (hHint != SWT.DEFAULT) size.y = hHint;
229         /*
230          * Since computeTrim can be overridden by subclasses, we cannot
231          * call computeTrimInPixels directly.
232          */
233         Rectangle trim = DPIUtil.autoScaleUp(computeTrim (0, 0, DPIUtil.autoScaleDown(size.x), DPIUtil.autoScaleDown(size.y)));
234         return new Point (trim.width, trim.height);
235 }
236
237 /**
238  * Copies a rectangular area of the receiver at the specified
239  * position using the gc.
240  *
241  * @param gc the gc where the rectangle is to be filled
242  * @param x the x coordinate of the rectangle to be filled
243  * @param y the y coordinate of the rectangle to be filled
244  * @param width the width of the rectangle to be filled
245  * @param height the height of the rectangle to be filled
246  *
247  * @exception IllegalArgumentException <ul>
248  *    <li>ERROR_NULL_ARGUMENT - if the gc is null</li>
249  *    <li>ERROR_INVALID_ARGUMENT - if the gc has been disposed</li>
250  * </ul>
251  * @exception SWTException <ul>
252  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
253  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
254  * </ul>
255  */
256 /*public*/ void copyArea (GC gc, int x, int y, int width, int height) {
257         checkWidget ();
258         if (gc == null) error (SWT.ERROR_NULL_ARGUMENT);
259         if (gc.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
260
261         //XP only, no GDI+
262         //#define PW_CLIENTONLY 0x00000001
263         //DCOrg() wrong
264         //topHandle wrong for Tree?
265         long hDC = gc.handle;
266         int nSavedDC = OS.SaveDC (hDC);
267         OS.IntersectClipRect (hDC, 0, 0, width, height);
268
269         //WRONG PARENT
270         POINT lpPoint = new POINT ();
271         long hwndParent = OS.GetParent (handle);
272         OS.MapWindowPoints (handle, hwndParent, lpPoint, 1);
273         RECT rect = new RECT ();
274         OS.GetWindowRect (handle, rect);
275         POINT lpPoint1 = new POINT (), lpPoint2 = new POINT ();
276         x = x + (lpPoint.x - rect.left);
277         y = y + (lpPoint.y - rect.top);
278         OS.SetWindowOrgEx (hDC, x, y, lpPoint1);
279         OS.SetBrushOrgEx (hDC, x, y, lpPoint2);
280         int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
281         if ((bits & OS.WS_VISIBLE) == 0) {
282                 OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0);
283         }
284         //NECESSARY?
285         OS.RedrawWindow (handle, null, 0, OS.RDW_UPDATENOW | OS.RDW_ALLCHILDREN);
286         OS.PrintWindow (handle, hDC, 0);//0x00000001);
287         if ((bits & OS.WS_VISIBLE) == 0) {
288                 OS.DefWindowProc(handle, OS.WM_SETREDRAW, 0, 0);
289         }
290         OS.RestoreDC (hDC, nSavedDC);
291 }
292
293 @Override
294 void createHandle () {
295         super.createHandle ();
296         state |= CANVAS;
297         if ((style & (SWT.H_SCROLL | SWT.V_SCROLL)) == 0 || findThemeControl () == parent) {
298                 state |= THEME_BACKGROUND;
299         }
300         if ((style & SWT.TRANSPARENT) != 0) {
301                 int bits = OS.GetWindowLong (handle, OS.GWL_EXSTYLE);
302                 bits |= OS.WS_EX_TRANSPARENT;
303                 OS.SetWindowLong (handle, OS.GWL_EXSTYLE, bits);
304         }
305 }
306
307 @Override
308 int applyThemeBackground () {
309         /*
310          * Composite with scrollbars would not inherit the theme because it was
311          * probably being used to implement a control similar to a Text, List,
312          * Table, or Tree, and those controls do not inherit the background theme.
313          * We assume that a Composite that did not have scrollbars was probably just
314          * being used to group some other controls, therefore it should inherit.
315          *
316          * But when Composite background is set to COLOR_TRANSPARENT (i.e.
317          * backgroundAlpha as '0') which means parent theme should be inherited, so
318          * enable the THEME_BACKGROUND in 'state' to support background transparent.
319          * Refer bug 463127 & related bug 234649.
320          */
321         return (backgroundAlpha == 0 || (style & (SWT.H_SCROLL | SWT.V_SCROLL)) == 0 || findThemeControl () == parent) ? 1 : 0;
322 }
323
324 /**
325  * Fills the interior of the rectangle specified by the arguments,
326  * with the receiver's background.
327  *
328  * <p>The <code>offsetX</code> and <code>offsetY</code> are used to map from
329  * the <code>gc</code> origin to the origin of the parent image background. This is useful
330  * to ensure proper alignment of the image background.</p>
331  *
332  * @param gc the gc where the rectangle is to be filled
333  * @param x the x coordinate of the rectangle to be filled
334  * @param y the y coordinate of the rectangle to be filled
335  * @param width the width of the rectangle to be filled
336  * @param height the height of the rectangle to be filled
337  * @param offsetX the image background x offset
338  * @param offsetY the image background y offset
339  *
340  * @exception IllegalArgumentException <ul>
341  *    <li>ERROR_NULL_ARGUMENT - if the gc is null</li>
342  *    <li>ERROR_INVALID_ARGUMENT - if the gc has been disposed</li>
343  * </ul>
344  * @exception SWTException <ul>
345  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
346  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
347  * </ul>
348  *
349  * @since 3.6
350  */
351 public void drawBackground (GC gc, int x, int y, int width, int height, int offsetX, int offsetY) {
352         checkWidget ();
353         x = DPIUtil.autoScaleUp(x);
354         y = DPIUtil.autoScaleUp(y);
355         width = DPIUtil.autoScaleUp(width);
356         height = DPIUtil.autoScaleUp(height);
357         offsetX = DPIUtil.autoScaleUp(offsetX);
358         offsetY = DPIUtil.autoScaleUp(offsetY);
359         drawBackgroundInPixels(gc, x, y, width, height, offsetX, offsetY);
360 }
361
362 void drawBackgroundInPixels(GC gc, int x, int y, int width, int height, int offsetX, int offsetY) {
363         if (gc == null) error (SWT.ERROR_NULL_ARGUMENT);
364         if (gc.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
365         RECT rect = new RECT ();
366         OS.SetRect (rect, x, y, x + width, y + height);
367         long hDC = gc.handle;
368         int pixel = background == -1 ? gc.getBackground ().handle : -1;
369         drawBackground (hDC, rect, pixel, offsetX, offsetY);
370 }
371
372 Composite findDeferredControl () {
373         return layoutCount > 0 ? this : parent.findDeferredControl ();
374 }
375
376 @Override
377 Menu [] findMenus (Control control) {
378         if (control == this) return new Menu [0];
379         Menu result [] = super.findMenus (control);
380         Control [] children = _getChildren ();
381         for (int i=0; i<children.length; i++) {
382                 Control child = children [i];
383                 Menu [] menuList = child.findMenus (control);
384                 if (menuList.length != 0) {
385                         Menu [] newResult = new Menu [result.length + menuList.length];
386                         System.arraycopy (result, 0, newResult, 0, result.length);
387                         System.arraycopy (menuList, 0, newResult, result.length, menuList.length);
388                         result = newResult;
389                 }
390         }
391         return result;
392 }
393
394 @Override
395 void fixChildren (Shell newShell, Shell oldShell, Decorations newDecorations, Decorations oldDecorations, Menu [] menus) {
396         super.fixChildren (newShell, oldShell, newDecorations, oldDecorations, menus);
397         Control [] children = _getChildren ();
398         for (int i=0; i<children.length; i++) {
399                 children [i].fixChildren (newShell, oldShell, newDecorations, oldDecorations, menus);
400         }
401 }
402
403 void fixTabList (Control control) {
404         if (tabList == null) return;
405         int count = 0;
406         for (int i=0; i<tabList.length; i++) {
407                 if (tabList [i] == control) count++;
408         }
409         if (count == 0) return;
410         Control [] newList = null;
411         int length = tabList.length - count;
412         if (length != 0) {
413                 newList = new Control [length];
414                 int index = 0;
415                 for (int i=0; i<tabList.length; i++) {
416                         if (tabList [i] != control) {
417                                 newList [index++] = tabList [i];
418                         }
419                 }
420         }
421         tabList = newList;
422 }
423
424 /**
425  * Returns the receiver's background drawing mode. This
426  * will be one of the following constants defined in class
427  * <code>SWT</code>:
428  * <code>INHERIT_NONE</code>, <code>INHERIT_DEFAULT</code>,
429  * <code>INHERIT_FORCE</code>.
430  *
431  * @return the background mode
432  *
433  * @exception SWTException <ul>
434  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
435  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
436  * </ul>
437  *
438  * @see SWT
439  *
440  * @since 3.2
441  */
442 public int getBackgroundMode () {
443         checkWidget ();
444         return backgroundMode;
445 }
446
447 /**
448  * Returns a (possibly empty) array containing the receiver's children.
449  * Children are returned in the order that they are drawn.  The topmost
450  * control appears at the beginning of the array.  Subsequent controls
451  * draw beneath this control and appear later in the array.
452  * <p>
453  * Note: This is not the actual structure used by the receiver
454  * to maintain its list of children, so modifying the array will
455  * not affect the receiver.
456  * </p>
457  *
458  * @return an array of children
459  *
460  * @see Control#moveAbove
461  * @see Control#moveBelow
462  *
463  * @exception SWTException <ul>
464  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
465  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
466  * </ul>
467  */
468 public Control [] getChildren () {
469         checkWidget ();
470         return _getChildren ();
471 }
472
473 int getChildrenCount () {
474         /*
475         * NOTE: The current implementation will count
476         * non-registered children.
477         */
478         int count = 0;
479         long hwndChild = OS.GetWindow (handle, OS.GW_CHILD);
480         while (hwndChild != 0) {
481                 count++;
482                 hwndChild = OS.GetWindow (hwndChild, OS.GW_HWNDNEXT);
483         }
484         return count;
485 }
486
487 /**
488  * Returns layout which is associated with the receiver, or
489  * null if one has not been set.
490  *
491  * @return the receiver's layout or null
492  *
493  * @exception SWTException <ul>
494  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
495  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
496  * </ul>
497  */
498 public Layout getLayout () {
499         checkWidget ();
500         return layout;
501 }
502
503 /**
504  * Gets the (possibly empty) tabbing order for the control.
505  *
506  * @return tabList the ordered list of controls representing the tab order
507  *
508  * @exception SWTException <ul>
509  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
510  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
511  * </ul>
512  *
513  * @see #setTabList
514  */
515 public Control [] getTabList () {
516         checkWidget ();
517         Control [] tabList = _getTabList ();
518         if (tabList == null) {
519                 int count = 0;
520                 Control [] list =_getChildren ();
521                 for (int i=0; i<list.length; i++) {
522                         if (list [i].isTabGroup ()) count++;
523                 }
524                 tabList = new Control [count];
525                 int index = 0;
526                 for (int i=0; i<list.length; i++) {
527                         if (list [i].isTabGroup ()) {
528                                 tabList [index++] = list [i];
529                         }
530                 }
531         }
532         return tabList;
533 }
534
535 boolean hooksKeys () {
536         return hooks (SWT.KeyDown) || hooks (SWT.KeyUp);
537 }
538
539 /**
540  * Returns <code>true</code> if the receiver has deferred
541  * the performing of layout, and <code>false</code> otherwise.
542  *
543  * @return the receiver's deferred layout state
544  *
545  * @exception SWTException <ul>
546  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
547  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
548  * </ul>
549  *
550  * @see #setLayoutDeferred(boolean)
551  * @see #isLayoutDeferred()
552  *
553  * @since 3.1
554  */
555 public boolean getLayoutDeferred () {
556         checkWidget ();
557         return layoutCount > 0 ;
558 }
559
560 /**
561  * Returns <code>true</code> if the receiver or any ancestor
562  * up to and including the receiver's nearest ancestor shell
563  * has deferred the performing of layouts.  Otherwise, <code>false</code>
564  * is returned.
565  *
566  * @return the receiver's deferred layout state
567  *
568  * @exception SWTException <ul>
569  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
570  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
571  * </ul>
572  *
573  * @see #setLayoutDeferred(boolean)
574  * @see #getLayoutDeferred()
575  *
576  * @since 3.1
577  */
578 public boolean isLayoutDeferred () {
579         checkWidget ();
580         return findDeferredControl () != null;
581 }
582
583 /**
584  * If the receiver has a layout, asks the layout to <em>lay out</em>
585  * (that is, set the size and location of) the receiver's children.
586  * If the receiver does not have a layout, do nothing.
587  * <p>
588  * Use of this method is discouraged since it is the least-efficient
589  * way to trigger a layout. The use of <code>layout(true)</code>
590  * discards all cached layout information, even from controls which
591  * have not changed. It is much more efficient to invoke
592  * {@link Control#requestLayout()} on every control which has changed
593  * in the layout than it is to invoke this method on the layout itself.
594  * </p>
595  * <p>
596  * This is equivalent to calling <code>layout(true)</code>.
597  * </p>
598  * <p>
599  * Note: Layout is different from painting. If a child is
600  * moved or resized such that an area in the parent is
601  * exposed, then the parent will paint. If no child is
602  * affected, the parent will not paint.
603  * </p>
604  *
605  * @exception SWTException <ul>
606  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
607  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
608  * </ul>
609  */
610 public void layout () {
611         checkWidget ();
612         layout (true);
613 }
614
615 /**
616  * If the receiver has a layout, asks the layout to <em>lay out</em>
617  * (that is, set the size and location of) the receiver's children.
618  * If the argument is <code>true</code> the layout must not rely
619  * on any information it has cached about the immediate children. If it
620  * is <code>false</code> the layout may (potentially) optimize the
621  * work it is doing by assuming that none of the receiver's
622  * children has changed state since the last layout.
623  * If the receiver does not have a layout, do nothing.
624  * <p>
625  * It is normally more efficient to invoke {@link Control#requestLayout()}
626  * on every control which has changed in the layout than it is to invoke
627  * this method on the layout itself. Clients are encouraged to use
628  * {@link Control#requestLayout()} where possible instead of calling
629  * this method.
630  * </p>
631  * <p>
632  * If a child is resized as a result of a call to layout, the
633  * resize event will invoke the layout of the child.  The layout
634  * will cascade down through all child widgets in the receiver's widget
635  * tree until a child is encountered that does not resize.  Note that
636  * a layout due to a resize will not flush any cached information
637  * (same as <code>layout(false)</code>).
638  * </p>
639  * <p>
640  * Note: Layout is different from painting. If a child is
641  * moved or resized such that an area in the parent is
642  * exposed, then the parent will paint. If no child is
643  * affected, the parent will not paint.
644  * </p>
645  *
646  * @param changed <code>true</code> if the layout must flush its caches, and <code>false</code> otherwise
647  *
648  * @exception SWTException <ul>
649  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
650  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
651  * </ul>
652  */
653 public void layout (boolean changed) {
654         checkWidget ();
655         if (layout == null) return;
656         layout (changed, false);
657 }
658
659 /**
660  * If the receiver has a layout, asks the layout to <em>lay out</em>
661  * (that is, set the size and location of) the receiver's children.
662  * If the changed argument is <code>true</code> the layout must not rely
663  * on any information it has cached about its children. If it
664  * is <code>false</code> the layout may (potentially) optimize the
665  * work it is doing by assuming that none of the receiver's
666  * children has changed state since the last layout.
667  * If the all argument is <code>true</code> the layout will cascade down
668  * through all child widgets in the receiver's widget tree, regardless of
669  * whether the child has changed size.  The changed argument is applied to
670  * all layouts.  If the all argument is <code>false</code>, the layout will
671  * <em>not</em> cascade down through all child widgets in the receiver's widget
672  * tree.  However, if a child is resized as a result of a call to layout, the
673  * resize event will invoke the layout of the child.  Note that
674  * a layout due to a resize will not flush any cached information
675  * (same as <code>layout(false)</code>).
676  * <p>
677  * It is normally more efficient to invoke {@link Control#requestLayout()}
678  * on every control which has changed in the layout than it is to invoke
679  * this method on the layout itself. Clients are encouraged to use
680  * {@link Control#requestLayout()} where possible instead of calling
681  * this method.
682  * </p>
683  * <p>
684  * Note: Layout is different from painting. If a child is
685  * moved or resized such that an area in the parent is
686  * exposed, then the parent will paint. If no child is
687  * affected, the parent will not paint.
688  * </p>
689  *
690  * @param changed <code>true</code> if the layout must flush its caches, and <code>false</code> otherwise
691  * @param all <code>true</code> if all children in the receiver's widget tree should be laid out, and <code>false</code> otherwise
692  *
693  * @exception SWTException <ul>
694  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
695  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
696  * </ul>
697  *
698  * @since 3.1
699  */
700 public void layout (boolean changed, boolean all) {
701         checkWidget ();
702         if (layout == null && !all) return;
703         markLayout (changed, all);
704         updateLayout (all);
705 }
706
707 /**
708  * Forces a lay out (that is, sets the size and location) of all widgets that
709  * are in the parent hierarchy of the changed control up to and including the
710  * receiver.  The layouts in the hierarchy must not rely on any information
711  * cached about the changed control or any of its ancestors.  The layout may
712  * (potentially) optimize the work it is doing by assuming that none of the
713  * peers of the changed control have changed state since the last layout.
714  * If an ancestor does not have a layout, skip it.
715  * <p>
716  * It is normally more efficient to invoke {@link Control#requestLayout()}
717  * on every control which has changed in the layout than it is to invoke
718  * this method on the layout itself. Clients are encouraged to use
719  * {@link Control#requestLayout()} where possible instead of calling
720  * this method.
721  * </p>
722  * <p>
723  * Note: Layout is different from painting. If a child is
724  * moved or resized such that an area in the parent is
725  * exposed, then the parent will paint. If no child is
726  * affected, the parent will not paint.
727  * </p>
728  *
729  * @param changed a control that has had a state change which requires a recalculation of its size
730  *
731  * @exception IllegalArgumentException <ul>
732  *    <li>ERROR_INVALID_ARGUMENT - if the changed array is null any of its controls are null or have been disposed</li>
733  *    <li>ERROR_INVALID_PARENT - if any control in changed is not in the widget tree of the receiver</li>
734  * </ul>
735  * @exception SWTException <ul>
736  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
737  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
738  * </ul>
739  *
740  * @since 3.1
741  */
742 public void layout (Control [] changed) {
743         checkWidget ();
744         if (changed == null) error (SWT.ERROR_INVALID_ARGUMENT);
745         layout (changed, SWT.NONE);
746 }
747
748 /**
749  * Forces a lay out (that is, sets the size and location) of all widgets that
750  * are in the parent hierarchy of the changed control up to and including the
751  * receiver.
752  * <p>
753  * The parameter <code>flags</code> may be a combination of:
754  * </p>
755  * <dl>
756  * <dt><b>SWT.ALL</b></dt>
757  * <dd>all children in the receiver's widget tree should be laid out</dd>
758  * <dt><b>SWT.CHANGED</b></dt>
759  * <dd>the layout must flush its caches</dd>
760  * <dt><b>SWT.DEFER</b></dt>
761  * <dd>layout will be deferred</dd>
762  * </dl>
763  * <p>
764  * When the <code>changed</code> array is specified, the flags <code>SWT.ALL</code>
765  * and <code>SWT.CHANGED</code> have no effect. In this case, the layouts in the
766  * hierarchy must not rely on any information cached about the changed control or
767  * any of its ancestors.  The layout may (potentially) optimize the
768  * work it is doing by assuming that none of the peers of the changed
769  * control have changed state since the last layout.
770  * If an ancestor does not have a layout, skip it.
771  * </p>
772  * <p>
773  * When the <code>changed</code> array is not specified, the flag <code>SWT.ALL</code>
774  * indicates that the whole widget tree should be laid out. And the flag
775  * <code>SWT.CHANGED</code> indicates that the layouts should flush any cached
776  * information for all controls that are laid out.
777  * </p>
778  * <p>
779  * The <code>SWT.DEFER</code> flag always causes the layout to be deferred by
780  * calling <code>Composite.setLayoutDeferred(true)</code> and scheduling a call
781  * to <code>Composite.setLayoutDeferred(false)</code>, which will happen when
782  * appropriate (usually before the next event is handled). When this flag is set,
783  * the application should not call <code>Composite.setLayoutDeferred(boolean)</code>.
784  * </p>
785  * <p>
786  * Note: Layout is different from painting. If a child is
787  * moved or resized such that an area in the parent is
788  * exposed, then the parent will paint. If no child is
789  * affected, the parent will not paint.
790  * </p>
791  *
792  * @param changed a control that has had a state change which requires a recalculation of its size
793  * @param flags the flags specifying how the layout should happen
794  *
795  * @exception IllegalArgumentException <ul>
796  *    <li>ERROR_INVALID_ARGUMENT - if any of the controls in changed is null or has been disposed</li>
797  *    <li>ERROR_INVALID_PARENT - if any control in changed is not in the widget tree of the receiver</li>
798  * </ul>
799  * @exception SWTException <ul>
800  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
801  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
802  * </ul>
803  *
804  * @since 3.6
805  */
806 public void layout (Control [] changed, int flags) {
807         checkWidget ();
808         if (changed != null) {
809                 for (int i=0; i<changed.length; i++) {
810                         Control control = changed [i];
811                         if (control == null) error (SWT.ERROR_INVALID_ARGUMENT);
812                         if (control.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
813                         boolean ancestor = false;
814                         Composite composite = control.parent;
815                         while (composite != null) {
816                                 ancestor = composite == this;
817                                 if (ancestor) break;
818                                 composite = composite.parent;
819                         }
820                         if (!ancestor) error (SWT.ERROR_INVALID_PARENT);
821                 }
822                 int updateCount = 0;
823                 Composite [] update = new Composite [16];
824                 for (int i=0; i<changed.length; i++) {
825                         Control child = changed [i];
826                         Composite composite = child.parent;
827                         // Update layout when the list of children has changed.
828                         // See bug 497812.
829                         child.markLayout(false, false);
830                         while (child != this) {
831                                 if (composite.layout != null) {
832                                         composite.state |= LAYOUT_NEEDED;
833                                         if (!composite.layout.flushCache (child)) {
834                                                 composite.state |= LAYOUT_CHANGED;
835                                         }
836                                 }
837                                 if (updateCount == update.length) {
838                                         Composite [] newUpdate = new Composite [update.length + 16];
839                                         System.arraycopy (update, 0, newUpdate, 0, update.length);
840                                         update = newUpdate;
841                                 }
842                                 child = update [updateCount++] = composite;
843                                 composite = child.parent;
844                         }
845                 }
846                 if (!display.externalEventLoop && (flags & SWT.DEFER) != 0) {
847                         setLayoutDeferred (true);
848                         display.addLayoutDeferred (this);
849                 }
850                 for (int i=updateCount-1; i>=0; i--) {
851                         update [i].updateLayout (false);
852                 }
853         } else {
854                 if (layout == null && (flags & SWT.ALL) == 0) return;
855                 markLayout ((flags & SWT.CHANGED) != 0, (flags & SWT.ALL) != 0);
856                 if (!display.externalEventLoop && (flags & SWT.DEFER) != 0) {
857                         setLayoutDeferred (true);
858                         display.addLayoutDeferred (this);
859                 }
860                 updateLayout ((flags & SWT.ALL) != 0);
861         }
862 }
863
864 @Override
865 void markLayout (boolean changed, boolean all) {
866         if (layout != null) {
867                 state |= LAYOUT_NEEDED;
868                 if (changed) state |= LAYOUT_CHANGED;
869         }
870         if (all) {
871                 Control [] children = _getChildren ();
872                 for (int i=0; i<children.length; i++) {
873                         children [i].markLayout (changed, all);
874                 }
875         }
876 }
877
878 Point minimumSize (int wHint, int hHint, boolean changed) {
879         Control [] children = _getChildren ();
880         /*
881          * Since getClientArea can be overridden by subclasses, we cannot
882          * call getClientAreaInPixels directly.
883          */
884         Rectangle clientArea = DPIUtil.autoScaleUp(getClientArea ());
885         int width = 0, height = 0;
886         for (int i=0; i<children.length; i++) {
887                 Rectangle rect = DPIUtil.autoScaleUp(children [i].getBounds ());
888                 width = Math.max (width, rect.x - clientArea.x + rect.width);
889                 height = Math.max (height, rect.y - clientArea.y + rect.height);
890         }
891         return new Point (width, height);
892 }
893
894 @Override
895 boolean redrawChildren () {
896         if (!super.redrawChildren ()) return false;
897         Control [] children = _getChildren ();
898         for (int i=0; i<children.length; i++) {
899                 children [i].redrawChildren ();
900         }
901         return true;
902 }
903
904 @Override
905 void releaseParent () {
906         super.releaseParent ();
907         if ((state & CANVAS) != 0) {
908                 if ((style & SWT.TRANSPARENT) != 0) {
909                         long hwndParent = parent.handle;
910                         long hwndChild = OS.GetWindow (hwndParent, OS.GW_CHILD);
911                         while (hwndChild != 0) {
912                                 if (hwndChild != handle) {
913                                         int bits = OS.GetWindowLong (hwndParent, OS.GWL_EXSTYLE);
914                                         if ((bits & OS.WS_EX_TRANSPARENT) != 0) return;
915                                 }
916                                 hwndChild = OS.GetWindow (hwndChild, OS.GW_HWNDNEXT);
917                         }
918                         int bits = OS.GetWindowLong (hwndParent, OS.GWL_EXSTYLE);
919                         bits &= ~OS.WS_EX_COMPOSITED;
920                         OS.SetWindowLong (hwndParent, OS.GWL_EXSTYLE, bits);
921                 }
922         }
923 }
924
925 @Override
926 void releaseChildren (boolean destroy) {
927         Control [] children = _getChildren ();
928         for (int i=0; i<children.length; i++) {
929                 Control child = children [i];
930                 if (child != null && !child.isDisposed ()) {
931                         child.release (false);
932                 }
933         }
934         super.releaseChildren (destroy);
935 }
936
937 @Override
938 void releaseWidget () {
939         super.releaseWidget ();
940         if ((state & CANVAS) != 0 && (style & SWT.EMBEDDED) != 0) {
941                 long hwndChild = OS.GetWindow (handle, OS.GW_CHILD);
942                 if (hwndChild != 0) {
943                         int threadId = OS.GetWindowThreadProcessId (hwndChild, null);
944                         if (threadId != OS.GetCurrentThreadId ()) {
945                                 OS.ShowWindow (hwndChild, OS.SW_HIDE);
946                                 OS.SetParent (hwndChild, 0);
947                         }
948                 }
949         }
950         layout = null;
951         tabList = null;
952         lpwp = null;
953 }
954
955 void removeControl (Control control) {
956         fixTabList (control);
957         resizeChildren ();
958 }
959
960 @Override
961 void reskinChildren (int flags) {
962         super.reskinChildren (flags);
963         Control [] children = _getChildren ();
964         for (int i=0; i<children.length; i++) {
965                 Control child = children [i];
966                 if (child != null) child.reskin (flags);
967         }
968 }
969
970 void resizeChildren () {
971         if (lpwp == null) return;
972         do {
973                 WINDOWPOS [] currentLpwp = lpwp;
974                 lpwp = null;
975                 if (!resizeChildren (true, currentLpwp)) {
976                         resizeChildren (false, currentLpwp);
977                 }
978         } while (lpwp != null);
979 }
980
981 boolean resizeChildren (boolean defer, WINDOWPOS [] pwp) {
982         if (pwp == null) return true;
983         long hdwp = 0;
984         if (defer) {
985                 hdwp = OS.BeginDeferWindowPos (pwp.length);
986                 if (hdwp == 0) return false;
987         }
988         for (int i=0; i<pwp.length; i++) {
989                 WINDOWPOS wp = pwp [i];
990                 if (wp != null) {
991                         /*
992                         * This code is intentionally commented.  All widgets that
993                         * are created by SWT have WS_CLIPSIBLINGS to ensure that
994                         * application code does not draw outside of the control.
995                         */
996 //                      int count = parent.getChildrenCount ();
997 //                      if (count > 1) {
998 //                              int bits = OS.GetWindowLong (handle, OS.GWL_STYLE);
999 //                              if ((bits & OS.WS_CLIPSIBLINGS) == 0) wp.flags |= OS.SWP_NOCOPYBITS;
1000 //                      }
1001                         if (defer) {
1002                                 hdwp = OS.DeferWindowPos (hdwp, wp.hwnd, 0, wp.x, wp.y, wp.cx, wp.cy, wp.flags);
1003                                 if (hdwp == 0) return false;
1004                         } else {
1005                                 OS.SetWindowPos (wp.hwnd, 0, wp.x, wp.y, wp.cx, wp.cy, wp.flags);
1006                         }
1007                 }
1008         }
1009         if (defer) return OS.EndDeferWindowPos (hdwp);
1010         return true;
1011 }
1012
1013 void resizeEmbeddedHandle(long embeddedHandle, int width, int height) {
1014         if (embeddedHandle == 0) return;
1015         int [] processID = new int [1];
1016         int threadId = OS.GetWindowThreadProcessId (embeddedHandle, processID);
1017         if (threadId != OS.GetCurrentThreadId ()) {
1018                 if (processID [0] == OS.GetCurrentProcessId ()) {
1019                         if (display.msgHook == 0) {
1020                                 display.getMsgCallback = new Callback (display, "getMsgProc", 3);
1021                                 display.getMsgProc = display.getMsgCallback.getAddress ();
1022                                 if (display.getMsgProc == 0) error (SWT.ERROR_NO_MORE_CALLBACKS);
1023                                 display.msgHook = OS.SetWindowsHookEx (OS.WH_GETMESSAGE, display.getMsgProc, OS.GetLibraryHandle(), threadId);
1024                                 OS.PostThreadMessage (threadId, OS.WM_NULL, 0, 0);
1025                         }
1026                 }
1027                 int flags = OS.SWP_NOZORDER | OS.SWP_DRAWFRAME | OS.SWP_NOACTIVATE | OS.SWP_ASYNCWINDOWPOS;
1028                 OS.SetWindowPos (embeddedHandle, 0, 0, 0, width, height, flags);
1029         }
1030 }
1031
1032 @Override
1033 void sendResize () {
1034         setResizeChildren (false);
1035         super.sendResize ();
1036         if (isDisposed ()) return;
1037         if (layout != null) {
1038                 markLayout (false, false);
1039                 updateLayout (false, false);
1040         }
1041         setResizeChildren (true);
1042 }
1043
1044 /**
1045  * Sets the background drawing mode to the argument which should
1046  * be one of the following constants defined in class <code>SWT</code>:
1047  * <code>INHERIT_NONE</code>, <code>INHERIT_DEFAULT</code>,
1048  * <code>INHERIT_FORCE</code>.
1049  *
1050  * @param mode the new background mode
1051  *
1052  * @exception SWTException <ul>
1053  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1054  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1055  * </ul>
1056  *
1057  * @see SWT
1058  *
1059  * @since 3.2
1060  */
1061 public void setBackgroundMode (int mode) {
1062         checkWidget ();
1063         backgroundMode = mode;
1064         Control [] children = _getChildren ();
1065         for (int i = 0; i < children.length; i++) {
1066                 children [i].updateBackgroundMode ();
1067         }
1068 }
1069
1070 @Override
1071 void setBoundsInPixels (int x, int y, int width, int height, int flags, boolean defer) {
1072         if (display.resizeCount > Display.RESIZE_LIMIT) {
1073                 defer = false;
1074         }
1075         if (!defer && (state & CANVAS) != 0) {
1076                 state &= ~(RESIZE_OCCURRED | MOVE_OCCURRED);
1077                 state |= RESIZE_DEFERRED | MOVE_DEFERRED;
1078         }
1079         super.setBoundsInPixels (x, y, width, height, flags, defer);
1080         if (!defer && (state & CANVAS) != 0) {
1081                 boolean wasMoved = (state & MOVE_OCCURRED) != 0;
1082                 boolean wasResized = (state & RESIZE_OCCURRED) != 0;
1083                 state &= ~(RESIZE_DEFERRED | MOVE_DEFERRED);
1084                 if (wasMoved && !isDisposed ()) sendMove ();
1085                 if (wasResized && !isDisposed ()) sendResize ();
1086         }
1087 }
1088
1089 @Override
1090 public boolean setFocus () {
1091         checkWidget ();
1092         Control [] children = _getChildren ();
1093         for (int i=0; i<children.length; i++) {
1094                 Control child = children [i];
1095                 if (child.setRadioFocus (false)) return true;
1096         }
1097         for (int i=0; i<children.length; i++) {
1098                 Control child = children [i];
1099                 if (child.setFocus ()) return true;
1100         }
1101         return super.setFocus ();
1102 }
1103
1104 /**
1105  * Sets the layout which is associated with the receiver to be
1106  * the argument which may be null.
1107  *
1108  * @param layout the receiver's new layout or null
1109  *
1110  * @exception SWTException <ul>
1111  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1112  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1113  * </ul>
1114  */
1115 public void setLayout (Layout layout) {
1116         checkWidget ();
1117         this.layout = layout;
1118 }
1119
1120 /**
1121  * If the argument is <code>true</code>, causes subsequent layout
1122  * operations in the receiver or any of its children to be ignored.
1123  * No layout of any kind can occur in the receiver or any of its
1124  * children until the flag is set to false.
1125  * Layout operations that occurred while the flag was
1126  * <code>true</code> are remembered and when the flag is set to
1127  * <code>false</code>, the layout operations are performed in an
1128  * optimized manner.  Nested calls to this method are stacked.
1129  *
1130  * @param defer the new defer state
1131  *
1132  * @exception SWTException <ul>
1133  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1134  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1135  * </ul>
1136  *
1137  * @see #layout(boolean)
1138  * @see #layout(Control[])
1139  *
1140  * @since 3.1
1141  */
1142 public void setLayoutDeferred (boolean defer) {
1143         checkWidget();
1144         if (!defer) {
1145                 if (--layoutCount == 0) {
1146                         if ((state & LAYOUT_CHILD) != 0 || (state & LAYOUT_NEEDED) != 0) {
1147                                 updateLayout (true);
1148                         }
1149                 }
1150         } else {
1151                 layoutCount++;
1152         }
1153 }
1154 /**
1155  * Sets the tabbing order for the specified controls to
1156  * match the order that they occur in the argument list.
1157  *
1158  * @param tabList the ordered list of controls representing the tab order or null
1159  *
1160  * @exception IllegalArgumentException <ul>
1161  *    <li>ERROR_INVALID_ARGUMENT - if a widget in the tabList is null or has been disposed</li>
1162  *    <li>ERROR_INVALID_PARENT - if widget in the tabList is not in the same widget tree</li>
1163  * </ul>
1164  * @exception SWTException <ul>
1165  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1166  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1167  * </ul>
1168  */
1169 public void setTabList (Control [] tabList) {
1170         checkWidget ();
1171         if (tabList != null) {
1172                 for (int i=0; i<tabList.length; i++) {
1173                         Control control = tabList [i];
1174                         if (control == null) error (SWT.ERROR_INVALID_ARGUMENT);
1175                         if (control.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
1176                         if (control.parent != this) error (SWT.ERROR_INVALID_PARENT);
1177                 }
1178                 Control [] newList = new Control [tabList.length];
1179                 System.arraycopy (tabList, 0, newList, 0, tabList.length);
1180                 tabList = newList;
1181         }
1182         this.tabList = tabList;
1183 }
1184
1185 void setResizeChildren (boolean resize) {
1186         if (resize) {
1187                 resizeChildren ();
1188         } else {
1189                 if (display.resizeCount > Display.RESIZE_LIMIT) {
1190                         return;
1191                 }
1192                 int count = getChildrenCount ();
1193                 if (count > 1 && lpwp == null) {
1194                         lpwp = new WINDOWPOS [count];
1195                 }
1196         }
1197 }
1198
1199 @Override
1200 boolean setTabGroupFocus () {
1201         if (isTabItem ()) return setTabItemFocus ();
1202         boolean takeFocus = (style & SWT.NO_FOCUS) == 0;
1203         if ((state & CANVAS) != 0) {
1204                 takeFocus = hooksKeys ();
1205                 if ((style & SWT.EMBEDDED) != 0) takeFocus = true;
1206         }
1207         if (takeFocus && setTabItemFocus ()) return true;
1208         Control [] children = _getChildren ();
1209         for (int i=0; i<children.length; i++) {
1210                 Control child = children [i];
1211                 if (child.isTabItem () && child.setRadioFocus (true)) return true;
1212         }
1213         for (int i=0; i<children.length; i++) {
1214                 Control child = children [i];
1215                 if (child.isTabItem () && !child.isTabGroup () && child.setTabItemFocus ()) {
1216                         return true;
1217                 }
1218         }
1219         return false;
1220 }
1221
1222 @Override
1223 boolean updateTextDirection(int textDirection) {
1224         super.updateTextDirection (textDirection);
1225         /*
1226          * Always continue, communicating the direction to the children since
1227          * OS.WS_EX_RTLREADING doesn't propagate to them natively, and since
1228          * the direction might need to be handled by each child individually.
1229          */
1230         Control[] children = _getChildren ();
1231         int i = children.length;
1232         while (i-- > 0) {
1233                 if (children[i] != null && !children[i].isDisposed ()) {
1234                         children[i].updateTextDirection(textDirection);
1235                 }
1236         }
1237         /*
1238          * Return value indicates whether or not to update derivatives, so in case
1239          * of AUTO always return true regardless of the actual update.
1240          */
1241         return true;
1242 }
1243
1244 String toolTipText (NMTTDISPINFO hdr) {
1245         Shell shell = getShell ();
1246         if ((hdr.uFlags & OS.TTF_IDISHWND) == 0) {
1247                 String string = null;
1248                 ToolTip toolTip = shell.findToolTip ((int)hdr.idFrom);
1249                 if (toolTip != null) {
1250                         string = toolTip.message;
1251                         if (string == null || string.length () == 0) string = " ";
1252                         /*
1253                         * Bug in Windows.  On Windows 7, tool tips hang when displaying large
1254                         * unwrapped strings. The fix is to wrap the string ourselves.
1255                         */
1256                         if (string.length () > TOOLTIP_LIMIT / 4) {
1257                                 string = display.wrapText (string, handle, toolTip.getWidth ());
1258                         }
1259                 }
1260                 return string;
1261         }
1262         shell.setToolTipTitle (hdr.hwndFrom, null, 0);
1263         OS.SendMessage (hdr.hwndFrom, OS.TTM_SETMAXTIPWIDTH, 0, 0x7FFF);
1264         Control control = display.getControl (hdr.idFrom);
1265         return control != null ? control.toolTipText : null;
1266 }
1267
1268 @Override
1269 boolean translateMnemonic (Event event, Control control) {
1270         if (super.translateMnemonic (event, control)) return true;
1271         if (control != null) {
1272                 Control [] children = _getChildren ();
1273                 for (int i=0; i<children.length; i++) {
1274                         Control child = children [i];
1275                         if (child.translateMnemonic (event, control)) return true;
1276                 }
1277         }
1278         return false;
1279 }
1280
1281 @Override
1282 boolean translateTraversal (MSG msg) {
1283         if ((state & CANVAS) != 0 ) {
1284                 if ((style & SWT.EMBEDDED) != 0) return false;
1285                 switch ((int)msg.wParam) {
1286                         case OS.VK_UP:
1287                         case OS.VK_LEFT:
1288                         case OS.VK_DOWN:
1289                         case OS.VK_RIGHT:
1290                         case OS.VK_PRIOR:
1291                         case OS.VK_NEXT:
1292                                 int uiState = (int)OS.SendMessage (msg.hwnd, OS.WM_QUERYUISTATE, 0, 0);
1293                                 if ((uiState & OS.UISF_HIDEFOCUS) != 0) {
1294                                         OS.SendMessage (msg.hwnd, OS.WM_UPDATEUISTATE, OS.MAKEWPARAM (OS.UIS_CLEAR, OS.UISF_HIDEFOCUS), 0);
1295                                 }
1296                                 break;
1297                 }
1298         }
1299         return super.translateTraversal (msg);
1300 }
1301
1302 @Override
1303 void updateBackgroundColor () {
1304         super.updateBackgroundColor ();
1305         Control [] children = _getChildren ();
1306         for (int i=0; i<children.length; i++) {
1307                 if ((children [i].state & PARENT_BACKGROUND) != 0) {
1308                         children [i].updateBackgroundColor ();
1309                 }
1310         }
1311 }
1312
1313 @Override
1314 void updateBackgroundImage () {
1315         super.updateBackgroundImage ();
1316         Control [] children = _getChildren ();
1317         for (int i=0; i<children.length; i++) {
1318                 if ((children [i].state & PARENT_BACKGROUND) != 0) {
1319                         children [i].updateBackgroundImage ();
1320                 }
1321         }
1322 }
1323
1324 @Override
1325 void updateBackgroundMode () {
1326         super.updateBackgroundMode ();
1327         Control [] children = _getChildren ();
1328         for (int i = 0; i < children.length; i++) {
1329                 children [i].updateBackgroundMode ();
1330         }
1331 }
1332
1333 @Override
1334 void updateFont (Font oldFont, Font newFont) {
1335         super.updateFont (oldFont, newFont);
1336         Control [] children = _getChildren ();
1337         for (int i=0; i<children.length; i++) {
1338                 Control control = children [i];
1339                 if (!control.isDisposed ()) {
1340                         control.updateFont (oldFont, newFont);
1341                 }
1342         }
1343 }
1344
1345 void updateLayout (boolean all) {
1346         updateLayout (true, all);
1347 }
1348
1349 @Override
1350 void updateLayout (boolean resize, boolean all) {
1351         Composite parent = findDeferredControl ();
1352         if (parent != null) {
1353                 parent.state |= LAYOUT_CHILD;
1354                 return;
1355         }
1356         if ((state & LAYOUT_NEEDED) != 0) {
1357                 boolean changed = (state & LAYOUT_CHANGED) != 0;
1358                 state &= ~(LAYOUT_NEEDED | LAYOUT_CHANGED);
1359                 display.runSkin();
1360                 if (resize) setResizeChildren (false);
1361                 layout.layout (this, changed);
1362                 if (resize) setResizeChildren (true);
1363         }
1364         if (all) {
1365                 state &= ~LAYOUT_CHILD;
1366                 Control [] children = _getChildren ();
1367                 for (int i=0; i<children.length; i++) {
1368                         children [i].updateLayout (resize, all);
1369                 }
1370         }
1371 }
1372
1373 @Override
1374 void updateOrientation () {
1375         Control [] controls = _getChildren ();
1376         RECT [] rects = new RECT [controls.length];
1377         for (int i=0; i<controls.length; i++) {
1378                 Control control = controls [i];
1379                 RECT rect = rects [i] = new RECT();
1380                 control.forceResize ();
1381                 OS.GetWindowRect (control.topHandle (), rect);
1382                 OS.MapWindowPoints (0, handle, rect, 2);
1383         }
1384         int orientation = style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT);
1385         super.updateOrientation ();
1386         for (int i=0; i<controls.length; i++) {
1387                 Control control = controls [i];
1388                 RECT rect = rects [i];
1389                 control.setOrientation (orientation);
1390                 int flags = OS.SWP_NOSIZE | OS.SWP_NOZORDER | OS.SWP_NOACTIVATE;
1391                 OS.SetWindowPos (control.topHandle (), 0, rect.left, rect.top, 0, 0, flags);
1392         }
1393 }
1394
1395 void updateUIState () {
1396         long hwndShell = getShell ().handle;
1397         int uiState = (int)OS.SendMessage (hwndShell, OS.WM_QUERYUISTATE, 0, 0);
1398         if ((uiState & OS.UISF_HIDEFOCUS) != 0) {
1399                 OS.SendMessage (hwndShell, OS.WM_CHANGEUISTATE, OS.MAKEWPARAM (OS.UIS_CLEAR, OS.UISF_HIDEFOCUS), 0);
1400         }
1401 }
1402
1403 @Override
1404 int widgetStyle () {
1405         /* Force clipping of children by setting WS_CLIPCHILDREN */
1406         return super.widgetStyle () | OS.WS_CLIPCHILDREN;
1407 }
1408
1409 @Override
1410 LRESULT WM_ERASEBKGND (long wParam, long lParam) {
1411         LRESULT result = super.WM_ERASEBKGND (wParam, lParam);
1412         if (result != null) return result;
1413         if ((state & CANVAS) != 0) {
1414                 /* Return zero to indicate that the background was not erased */
1415                 if ((style & (SWT.NO_BACKGROUND | SWT.TRANSPARENT)) != 0) {
1416                         return LRESULT.ZERO;
1417                 }
1418         }
1419         return result;
1420 }
1421
1422 @Override
1423 LRESULT WM_GETDLGCODE (long wParam, long lParam) {
1424         LRESULT result = super.WM_GETDLGCODE (wParam, lParam);
1425         if (result != null) return result;
1426         if ((state & CANVAS) != 0) {
1427                 int flags = 0;
1428                 if (hooksKeys ()) {
1429                         flags |= OS.DLGC_WANTALLKEYS | OS.DLGC_WANTARROWS | OS.DLGC_WANTTAB;
1430                 }
1431                 if ((style & SWT.NO_FOCUS) != 0) flags |= OS.DLGC_STATIC;
1432                 if (OS.GetWindow (handle, OS.GW_CHILD) != 0) flags |= OS.DLGC_STATIC;
1433                 if (flags != 0) return new LRESULT (flags);
1434         }
1435         return result;
1436 }
1437
1438 @Override
1439 LRESULT WM_GETFONT (long wParam, long lParam) {
1440         LRESULT result = super.WM_GETFONT (wParam, lParam);
1441         if (result != null) return result;
1442         long code = callWindowProc (handle, OS.WM_GETFONT, wParam, lParam);
1443         if (code != 0) return new LRESULT (code);
1444         return new LRESULT (font != null ? font.handle : defaultFont ());
1445 }
1446
1447 @Override
1448 LRESULT WM_LBUTTONDOWN (long wParam, long lParam) {
1449         LRESULT result = super.WM_LBUTTONDOWN (wParam, lParam);
1450         if (result == LRESULT.ZERO) return result;
1451
1452         /* Set focus for a canvas with no children */
1453         if ((state & CANVAS) != 0) {
1454                 if ((style & SWT.NO_FOCUS) == 0 && hooksKeys ()) {
1455                         if (OS.GetWindow (handle, OS.GW_CHILD) == 0) setFocus ();
1456                 }
1457         }
1458         return result;
1459 }
1460
1461 @Override
1462 LRESULT WM_NCHITTEST (long wParam, long lParam) {
1463         LRESULT result = super.WM_NCHITTEST (wParam, lParam);
1464         if (result != null) return result;
1465         /*
1466         * Bug in Windows.  For some reason, under circumstances
1467         * that are not understood, when one scrolled window is
1468         * embedded in another and the outer window scrolls the
1469         * inner horizontally by moving the location of the inner
1470         * one, the vertical scroll bars of the inner window no
1471         * longer function.  Specifically, WM_NCHITTEST returns
1472         * HTCLIENT instead of HTVSCROLL.  The fix is to detect
1473         * the case where the result of WM_NCHITTEST is HTCLIENT
1474         * and the point is not in the client area, and redraw
1475         * the trim, which somehow fixes the next WM_NCHITTEST.
1476         */
1477         if (OS.IsAppThemed ()) {
1478                 if ((state & CANVAS)!= 0) {
1479                         long code = callWindowProc (handle, OS.WM_NCHITTEST, wParam, lParam);
1480                         if (code == OS.HTCLIENT) {
1481                                 RECT rect = new RECT ();
1482                                 OS.GetClientRect (handle, rect);
1483                                 POINT pt = new POINT ();
1484                                 pt.x = OS.GET_X_LPARAM (lParam);
1485                                 pt.y = OS.GET_Y_LPARAM (lParam);
1486                                 OS.MapWindowPoints (0, handle, pt, 1);
1487                                 if (!OS.PtInRect (rect, pt)) {
1488                                         int flags = OS.RDW_FRAME | OS.RDW_INVALIDATE;
1489                                         OS.RedrawWindow (handle, null, 0, flags);
1490                                 }
1491                         }
1492                         return new LRESULT (code);
1493                 }
1494         }
1495         return result;
1496 }
1497
1498 @Override
1499 LRESULT WM_PARENTNOTIFY (long wParam, long lParam) {
1500         if ((state & CANVAS) != 0 && (style & SWT.EMBEDDED) != 0) {
1501                 if (OS.LOWORD (wParam) == OS.WM_CREATE) {
1502                         RECT rect = new RECT ();
1503                         OS.GetClientRect (handle, rect);
1504                         resizeEmbeddedHandle (lParam, rect.right - rect.left, rect.bottom - rect.top);
1505                 }
1506         }
1507         return super.WM_PARENTNOTIFY (wParam, lParam);
1508 }
1509
1510 @Override
1511 LRESULT WM_PAINT (long wParam, long lParam) {
1512         if ((state & DISPOSE_SENT) != 0) return LRESULT.ZERO;
1513         if ((state & CANVAS) == 0 || (state & FOREIGN_HANDLE) != 0) {
1514                 return super.WM_PAINT (wParam, lParam);
1515         }
1516
1517         /* Set the clipping bits */
1518         int oldBits = OS.GetWindowLong (handle, OS.GWL_STYLE);
1519         int newBits = oldBits | OS.WS_CLIPSIBLINGS | OS.WS_CLIPCHILDREN;
1520         if (newBits != oldBits) OS.SetWindowLong (handle, OS.GWL_STYLE, newBits);
1521
1522         /* Paint the control and the background */
1523         PAINTSTRUCT ps = new PAINTSTRUCT ();
1524         if (hooks (SWT.Paint) || filters (SWT.Paint)) {
1525
1526                 /* Use the buffered paint when possible */
1527                 boolean bufferedPaint = false;
1528                 if ((style & SWT.DOUBLE_BUFFERED) != 0) {
1529                         if ((style & (SWT.NO_MERGE_PAINTS | SWT.RIGHT_TO_LEFT | SWT.TRANSPARENT)) == 0) {
1530                                 bufferedPaint = true;
1531                         }
1532                 }
1533                 if (bufferedPaint) {
1534                         long hDC = OS.BeginPaint (handle, ps);
1535                         int width = ps.right - ps.left;
1536                         int height = ps.bottom - ps.top;
1537                         if (width != 0 && height != 0) {
1538                                 long [] phdc = new long [1];
1539                                 int flags = OS.BPBF_COMPATIBLEBITMAP;
1540                                 RECT prcTarget = new RECT ();
1541                                 OS.SetRect (prcTarget, ps.left, ps.top, ps.right, ps.bottom);
1542                                 long hBufferedPaint = OS.BeginBufferedPaint (hDC, prcTarget, flags, null, phdc);
1543                                 GCData data = new GCData ();
1544                                 data.device = display;
1545                                 data.foreground = getForegroundPixel ();
1546                                 Control control = findBackgroundControl ();
1547                                 if (control == null) control = this;
1548                                 data.background = control.getBackgroundPixel ();
1549                                 data.font = Font.win32_new(display, OS.SendMessage (handle, OS.WM_GETFONT, 0, 0));
1550                                 data.uiState = (int)OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
1551                                 if ((style & SWT.NO_BACKGROUND) != 0) {
1552                                         /* This code is intentionally commented because it may be slow to copy bits from the screen */
1553                                         //paintGC.copyArea (image, ps.left, ps.top);
1554                                 } else {
1555                                         RECT rect = new RECT ();
1556                                         OS.SetRect (rect, ps.left, ps.top, ps.right, ps.bottom);
1557                                         drawBackground (phdc [0], rect);
1558                                 }
1559                                 GC gc = GC.win32_new (phdc [0], data);
1560                                 Event event = new Event ();
1561                                 event.gc = gc;
1562                                 event.setBoundsInPixels(new Rectangle(ps.left, ps.top, width, height));
1563                                 sendEvent (SWT.Paint, event);
1564                                 if (data.focusDrawn && !isDisposed ()) updateUIState ();
1565                                 gc.dispose ();
1566                                 OS.EndBufferedPaint (hBufferedPaint, true);
1567                         }
1568                         OS.EndPaint (handle, ps);
1569                 } else {
1570
1571                         /* Create the paint GC */
1572                         GCData data = new GCData ();
1573                         data.ps = ps;
1574                         data.hwnd = handle;
1575                         GC gc = GC.win32_new (this, data);
1576
1577                         /* Get the system region for the paint HDC */
1578                         long sysRgn = 0;
1579                         if ((style & (SWT.DOUBLE_BUFFERED | SWT.TRANSPARENT)) != 0 || (style & SWT.NO_MERGE_PAINTS) != 0) {
1580                                 sysRgn = OS.CreateRectRgn (0, 0, 0, 0);
1581                                 if (OS.GetRandomRgn (gc.handle, sysRgn, OS.SYSRGN) == 1) {
1582                                         if ((OS.GetLayout (gc.handle) & OS.LAYOUT_RTL) != 0) {
1583                                                 int nBytes = OS.GetRegionData (sysRgn, 0, null);
1584                                                 int [] lpRgnData = new int [nBytes / 4];
1585                                                 OS.GetRegionData (sysRgn, nBytes, lpRgnData);
1586                                                 long newSysRgn = OS.ExtCreateRegion (new float [] {-1, 0, 0, 1, 0, 0}, nBytes, lpRgnData);
1587                                                 OS.DeleteObject (sysRgn);
1588                                                 sysRgn = newSysRgn;
1589                                         }
1590                                         POINT pt = new POINT();
1591                                         OS.MapWindowPoints (0, handle, pt, 1);
1592                                         OS.OffsetRgn (sysRgn, pt.x, pt.y);
1593                                 }
1594                         }
1595
1596                         /* Send the paint event */
1597                         int width = ps.right - ps.left;
1598                         int height = ps.bottom - ps.top;
1599                         if (width != 0 && height != 0) {
1600                                 GC paintGC = null;
1601                                 Image image = null;
1602                                 if ((style & (SWT.DOUBLE_BUFFERED | SWT.TRANSPARENT)) != 0) {
1603                                         image = new Image (display, width, height);
1604                                         paintGC = gc;
1605                                         gc = new GC (image, paintGC.getStyle() & SWT.RIGHT_TO_LEFT);
1606                                         GCData gcData = gc.getGCData ();
1607                                         gcData.uiState = data.uiState;
1608                                         gc.setForeground (getForeground ());
1609                                         gc.setBackground (getBackground ());
1610                                         gc.setFont (getFont ());
1611                                         if ((style & SWT.TRANSPARENT) != 0) {
1612                                                 OS.BitBlt (gc.handle, 0, 0, width, height, paintGC.handle, ps.left, ps.top, OS.SRCCOPY);
1613                                         }
1614                                         OS.OffsetRgn (sysRgn, -ps.left, -ps.top);
1615                                         OS.SelectClipRgn (gc.handle, sysRgn);
1616                                         OS.OffsetRgn (sysRgn, ps.left, ps.top);
1617                                         OS.SetMetaRgn (gc.handle);
1618                                         OS.SetWindowOrgEx (gc.handle, ps.left, ps.top, null);
1619                                         OS.SetBrushOrgEx (gc.handle, ps.left, ps.top, null);
1620                                         if ((style & (SWT.NO_BACKGROUND | SWT.TRANSPARENT)) != 0) {
1621                                                 /* This code is intentionally commented because it may be slow to copy bits from the screen */
1622                                                 //paintGC.copyArea (image, ps.left, ps.top);
1623                                         } else {
1624                                                 RECT rect = new RECT ();
1625                                                 OS.SetRect (rect, ps.left, ps.top, ps.right, ps.bottom);
1626                                                 drawBackground (gc.handle, rect);
1627                                         }
1628                                 }
1629                                 Event event = new Event ();
1630                                 event.gc = gc;
1631                                 RECT rect = null;
1632                                 if ((style & SWT.NO_MERGE_PAINTS) != 0 && OS.GetRgnBox (sysRgn, rect = new RECT ()) == OS.COMPLEXREGION) {
1633                                         int nBytes = OS.GetRegionData (sysRgn, 0, null);
1634                                         int [] lpRgnData = new int [nBytes / 4];
1635                                         OS.GetRegionData (sysRgn, nBytes, lpRgnData);
1636                                         int count = lpRgnData [2];
1637                                         for (int i=0; i<count; i++) {
1638                                                 int offset = 8 + (i << 2);
1639                                                 OS.SetRect (rect, lpRgnData [offset], lpRgnData [offset + 1], lpRgnData [offset + 2], lpRgnData [offset + 3]);
1640                                                 if ((style & (SWT.DOUBLE_BUFFERED | SWT.NO_BACKGROUND | SWT.TRANSPARENT)) == 0) {
1641                                                         drawBackground (gc.handle, rect);
1642                                                 }
1643                                                 event.setBoundsInPixels(new Rectangle(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top));
1644                                                 event.count = count - 1 - i;
1645                                                 sendEvent (SWT.Paint, event);
1646                                         }
1647                                 } else {
1648                                         if ((style & (SWT.DOUBLE_BUFFERED | SWT.NO_BACKGROUND | SWT.TRANSPARENT)) == 0) {
1649                                                 if (rect == null) rect = new RECT ();
1650                                                 OS.SetRect (rect, ps.left, ps.top, ps.right, ps.bottom);
1651                                                 drawBackground (gc.handle, rect);
1652                                         }
1653                                         event.setBoundsInPixels(new Rectangle(ps.left, ps.top, width, height));
1654                                         sendEvent (SWT.Paint, event);
1655                                 }
1656                                 // widget could be disposed at this point
1657                                 event.gc = null;
1658                                 if ((style & (SWT.DOUBLE_BUFFERED | SWT.TRANSPARENT)) != 0) {
1659                                         if (!gc.isDisposed ()) {
1660                                                 GCData gcData = gc.getGCData ();
1661                                                 if (gcData.focusDrawn && !isDisposed ()) updateUIState ();
1662                                         }
1663                                         gc.dispose();
1664                                         if (!isDisposed ()) paintGC.drawImage (image, DPIUtil.autoScaleDown(ps.left), DPIUtil.autoScaleDown(ps.top));
1665                                         image.dispose ();
1666                                         gc = paintGC;
1667                                 }
1668                         }
1669                         if (sysRgn != 0) OS.DeleteObject (sysRgn);
1670                         if (data.focusDrawn && !isDisposed ()) updateUIState ();
1671
1672                         /* Dispose the paint GC */
1673                         gc.dispose ();
1674                 }
1675         } else {
1676                 long hDC = OS.BeginPaint (handle, ps);
1677                 if ((style & (SWT.NO_BACKGROUND | SWT.TRANSPARENT)) == 0) {
1678                         RECT rect = new RECT ();
1679                         OS.SetRect (rect, ps.left, ps.top, ps.right, ps.bottom);
1680                         drawBackground (hDC, rect);
1681                 }
1682                 OS.EndPaint (handle, ps);
1683         }
1684
1685         /* Restore the clipping bits */
1686         if (!isDisposed ()) {
1687                 if (newBits != oldBits) {
1688                         /*
1689                         * It is possible (but unlikely), that application
1690                         * code could have disposed the widget in the paint
1691                         * event.  If this happens, don't attempt to restore
1692                         * the style.
1693                         */
1694                         if (!isDisposed ()) {
1695                                 OS.SetWindowLong (handle, OS.GWL_STYLE, oldBits);
1696                         }
1697                 }
1698         }
1699         return LRESULT.ZERO;
1700 }
1701
1702 @Override
1703 LRESULT WM_PRINTCLIENT (long wParam, long lParam) {
1704         LRESULT result = super.WM_PRINTCLIENT (wParam, lParam);
1705         if (result != null) return result;
1706         if ((state & CANVAS) != 0) {
1707                 forceResize ();
1708                 int nSavedDC = OS.SaveDC (wParam);
1709                 RECT rect = new RECT ();
1710                 OS.GetClientRect (handle, rect);
1711                 if ((style & (SWT.NO_BACKGROUND | SWT.TRANSPARENT)) == 0) {
1712                         drawBackground (wParam, rect);
1713                 }
1714                 if (hooks (SWT.Paint) || filters (SWT.Paint)) {
1715                         GCData data = new GCData ();
1716                         data.device = display;
1717                         data.foreground = getForegroundPixel ();
1718                         Control control = findBackgroundControl ();
1719                         if (control == null) control = this;
1720                         data.background = control.getBackgroundPixel ();
1721                         data.font = Font.win32_new(display, OS.SendMessage (handle, OS.WM_GETFONT, 0, 0));
1722                         data.uiState = (int)OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0);
1723                         GC gc = GC.win32_new (wParam, data);
1724                         Event event = new Event ();
1725                         event.gc = gc;
1726                         event.setBoundsInPixels(new Rectangle(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top));
1727                         sendEvent (SWT.Paint, event);
1728                         event.gc = null;
1729                         gc.dispose ();
1730                 }
1731                 OS.RestoreDC (wParam, nSavedDC);
1732         }
1733         return result;
1734 }
1735
1736 @Override
1737 LRESULT WM_SETFONT (long wParam, long lParam) {
1738         if (lParam != 0) OS.InvalidateRect (handle, null, true);
1739         return super.WM_SETFONT (wParam, lParam);
1740 }
1741
1742 @Override
1743 LRESULT WM_SIZE (long wParam, long lParam) {
1744         LRESULT result = null;
1745         if ((state & RESIZE_DEFERRED) != 0) {
1746                 result = super.WM_SIZE (wParam, lParam);
1747         } else {
1748                 /* Begin deferred window positioning */
1749                 setResizeChildren (false);
1750
1751                 /* Resize and Layout */
1752                 result = super.WM_SIZE (wParam, lParam);
1753                 /*
1754                 * It is possible (but unlikely), that application
1755                 * code could have disposed the widget in the resize
1756                 * event.  If this happens, end the processing of the
1757                 * Windows message by returning the result of the
1758                 * WM_SIZE message.
1759                 */
1760                 if (isDisposed ()) return result;
1761                 if (layout != null) {
1762                         markLayout (false, false);
1763                         updateLayout (false, false);
1764                 }
1765
1766                 /* End deferred window positioning */
1767                 setResizeChildren (true);
1768         }
1769
1770         /* Damage the widget to cause a repaint */
1771         if (OS.IsWindowVisible (handle)) {
1772                 if ((state & CANVAS) != 0) {
1773                         if ((style & SWT.NO_REDRAW_RESIZE) == 0) {
1774                                 if (hooks (SWT.Paint)) {
1775                                         OS.InvalidateRect (handle, null, true);
1776                                 }
1777                         }
1778                 }
1779                 if (OS.IsAppThemed ()) {
1780                         if (findThemeControl () != null) redrawChildren ();
1781                 }
1782         }
1783
1784         /* Resize the embedded window */
1785         if ((state & CANVAS) != 0 && (style & SWT.EMBEDDED) != 0) {
1786                 resizeEmbeddedHandle (OS.GetWindow (handle, OS.GW_CHILD), OS.LOWORD (lParam), OS.HIWORD (lParam));
1787         }
1788         return result;
1789 }
1790
1791 @Override
1792 LRESULT WM_SYSCOLORCHANGE (long wParam, long lParam) {
1793         LRESULT result = super.WM_SYSCOLORCHANGE (wParam, lParam);
1794         if (result != null) return result;
1795         long hwndChild = OS.GetWindow (handle, OS.GW_CHILD);
1796         while (hwndChild != 0) {
1797                 OS.SendMessage (hwndChild, OS.WM_SYSCOLORCHANGE, 0, 0);
1798                 hwndChild = OS.GetWindow (hwndChild, OS.GW_HWNDNEXT);
1799         }
1800         return result;
1801 }
1802
1803 @Override
1804 LRESULT WM_SYSCOMMAND (long wParam, long lParam) {
1805         LRESULT result = super.WM_SYSCOMMAND (wParam, lParam);
1806         if (result != null) return result;
1807
1808         /*
1809         * Check to see if the command is a system command or
1810         * a user menu item that was added to the system menu.
1811         *
1812         * NOTE: This is undocumented.
1813         */
1814         if ((wParam & 0xF000) == 0) return result;
1815
1816         /*
1817         * Bug in Windows.  When a vertical or horizontal scroll bar is
1818         * hidden or shown while the opposite scroll bar is being scrolled
1819         * by the user (with WM_HSCROLL code SB_LINEDOWN), the scroll bar
1820         * does not redraw properly.  The fix is to detect this case and
1821         * redraw the non-client area.
1822         */
1823         int cmd = (int)wParam & 0xFFF0;
1824         switch (cmd) {
1825                 case OS.SC_HSCROLL:
1826                 case OS.SC_VSCROLL:
1827                         boolean showHBar = horizontalBar != null && horizontalBar.getVisible ();
1828                         boolean showVBar = verticalBar != null && verticalBar.getVisible ();
1829                         long code = callWindowProc (handle, OS.WM_SYSCOMMAND, wParam, lParam);
1830                         if ((showHBar != (horizontalBar != null && horizontalBar.getVisible ())) ||
1831                                 (showVBar != (verticalBar != null && verticalBar.getVisible ()))) {
1832                                         int flags = OS.RDW_FRAME | OS.RDW_INVALIDATE | OS.RDW_UPDATENOW;
1833                                         OS.RedrawWindow (handle, null, 0, flags);
1834                                 }
1835                         if (code == 0) return LRESULT.ZERO;
1836                         return new LRESULT (code);
1837         }
1838
1839         /* Return the result */
1840         return result;
1841 }
1842
1843 @Override
1844 LRESULT WM_UPDATEUISTATE (long wParam, long lParam) {
1845         LRESULT result = super.WM_UPDATEUISTATE (wParam, lParam);
1846         if (result != null) return result;
1847         if ((state & CANVAS) != 0 && hooks (SWT.Paint)) {
1848                 OS.InvalidateRect (handle, null, true);
1849         }
1850         return result;
1851 }
1852
1853 @Override
1854 LRESULT wmNCPaint (long hwnd, long wParam, long lParam) {
1855         LRESULT result = super.wmNCPaint (hwnd, wParam, lParam);
1856         if (result != null) return result;
1857         long borderHandle = borderHandle ();
1858         if ((state & CANVAS) != 0 || (hwnd == borderHandle && handle != borderHandle)) {
1859                 if (OS.IsAppThemed ()) {
1860                         int bits1 = OS.GetWindowLong (hwnd, OS.GWL_EXSTYLE);
1861                         if ((bits1 & OS.WS_EX_CLIENTEDGE) != 0) {
1862                                 long code = 0;
1863                                 int bits2 = OS.GetWindowLong (hwnd, OS.GWL_STYLE);
1864                                 if ((bits2 & (OS.WS_HSCROLL | OS.WS_VSCROLL)) != 0) {
1865                                         code = callWindowProc (hwnd, OS.WM_NCPAINT, wParam, lParam);
1866                                 }
1867                                 long hDC = OS.GetWindowDC (hwnd);
1868                                 RECT rect = new RECT ();
1869                                 OS.GetWindowRect (hwnd, rect);
1870                                 rect.right -= rect.left;
1871                                 rect.bottom -= rect.top;
1872                                 rect.left = rect.top = 0;
1873                                 int border = OS.GetSystemMetrics (OS.SM_CXEDGE);
1874                                 OS.ExcludeClipRect (hDC, border, border, rect.right - border, rect.bottom - border);
1875                                 OS.DrawThemeBackground (display.hEditTheme (), hDC, OS.EP_EDITTEXT, OS.ETS_NORMAL, rect, null);
1876                                 OS.ReleaseDC (hwnd, hDC);
1877                                 return new LRESULT (code);
1878                         }
1879                 }
1880         }
1881         return result;
1882 }
1883
1884 @Override
1885 LRESULT wmNotify (NMHDR hdr, long wParam, long lParam) {
1886         switch (hdr.code) {
1887                 /*
1888                 * Feature in Windows.  When the tool tip control is
1889                 * created, the parent of the tool tip is the shell.
1890                 * If SetParent () is used to reparent the tool bar
1891                 * into a new shell, the tool tip is not reparented
1892                 * and pops up underneath the new shell.  The fix is
1893                 * to make sure the tool tip is a topmost window.
1894                 */
1895                 case OS.TTN_SHOW:
1896                 case OS.TTN_POP: {
1897                         /*
1898                         * Bug in Windows 98 and NT.  Setting the tool tip to be the
1899                         * top most window using HWND_TOPMOST can result in a parent
1900                         * dialog shell being moved behind its parent if the dialog
1901                         * has a sibling that is currently on top.  The fix is to
1902                         * lock the z-order of the active window.
1903                         *
1904                         * Feature in Windows.  Using SetWindowPos() with HWND_NOTOPMOST
1905                         * to clear the topmost state of a window whose parent is already
1906                         * topmost clears the topmost state of the parent.  The fix is to
1907                         * check if the parent is already on top and neither set or clear
1908                         * the topmost status of the tool tip.
1909                         */
1910                         long hwndParent = hdr.hwndFrom;
1911                         do {
1912                                 hwndParent = OS.GetParent (hwndParent);
1913                                 if (hwndParent == 0) break;
1914                                 int bits = OS.GetWindowLong (hwndParent, OS.GWL_EXSTYLE);
1915                                 if ((bits & OS.WS_EX_TOPMOST) != 0) break;
1916                         } while (true);
1917                         if (hwndParent != 0) break;
1918                         /*
1919                          * Bug in Windows.  TTN_SHOW is sent for inactive shells.  When
1920                          * SetWindowPos is called as a reaction, inactive shells can
1921                          * wrongly end up on top.  The fix is to swallow such requests.
1922                          *
1923                          * A visible effect is that spurious tool tips can show up and
1924                          * disappear in a split second.  This is a mostly harmless
1925                          * feature that can also be observed in the Windows Explorer.
1926                          * See bug 491627 for more details.
1927                          */
1928                         if (display.getActiveShell () == null) return LRESULT.ONE;
1929
1930                         display.lockActiveWindow = true;
1931                         int flags = OS.SWP_NOACTIVATE | OS.SWP_NOMOVE | OS.SWP_NOSIZE;
1932                         long hwndInsertAfter = hdr.code == OS.TTN_SHOW ? OS.HWND_TOPMOST : OS.HWND_NOTOPMOST;
1933                         OS.SetWindowPos (hdr.hwndFrom, hwndInsertAfter, 0, 0, 0, 0, flags);
1934                         display.lockActiveWindow = false;
1935                         break;
1936                 }
1937                 case OS.TTN_GETDISPINFO: {
1938                         NMTTDISPINFO lpnmtdi = new NMTTDISPINFO ();
1939                         OS.MoveMemory (lpnmtdi, lParam, NMTTDISPINFO.sizeof);
1940                         String string = toolTipText (lpnmtdi);
1941                         if (string != null) {
1942                                 Shell shell = getShell ();
1943                                 string = Display.withCrLf (string);
1944                                 /*
1945                                 * Bug in Windows.  On Windows 7, tool tips hang when displaying large
1946                                 * strings. The fix is to limit the tool tip string to 4Kb.
1947                                 */
1948                                 if (string.length() > TOOLTIP_LIMIT) {
1949                                         string = string.substring(0, TOOLTIP_LIMIT);
1950                                 }
1951                                 /*
1952                                  * Bug 475858: In Japanese like languages where mnemonics are not taken from the
1953                                  * source label text but appended in parentheses like "(&M)" at end. In order to
1954                                  * allow the reuse of such label text as a tool-tip text as well, "(&M)" like
1955                                  * character sequence has to be removed from the end of CJK-style mnemonics.
1956                                  */
1957                                 char [] chars = fixMnemonic (string, false, true);
1958
1959                                 /*
1960                                 * Ensure that the orientation of the tool tip matches
1961                                 * the orientation of the control.
1962                                 */
1963                                 Widget widget = null;
1964                                 long hwnd = hdr.idFrom;
1965                                 if ((lpnmtdi.uFlags & OS.TTF_IDISHWND) != 0) {
1966                                         widget = display.getControl (hwnd);
1967                                 } else {
1968                                         if (hdr.hwndFrom == shell.toolTipHandle || hdr.hwndFrom == shell.balloonTipHandle) {
1969                                                 widget = shell.findToolTip ((int)hdr.idFrom);
1970                                         }
1971                                 }
1972                                 if (widget != null) {
1973                                         int style = widget.getStyle();
1974                                         int flags = SWT.RIGHT_TO_LEFT | SWT.FLIP_TEXT_DIRECTION;
1975                                         if ((style & flags) != 0 && (style & flags) != flags) {
1976                                                 lpnmtdi.uFlags |= OS.TTF_RTLREADING;
1977                                         } else {
1978                                                 lpnmtdi.uFlags &= ~OS.TTF_RTLREADING;
1979                                         }
1980                                 }
1981                                 shell.setToolTipText (lpnmtdi, chars);
1982                                 OS.MoveMemory (lParam, lpnmtdi, NMTTDISPINFO.sizeof);
1983                                 return LRESULT.ZERO;
1984                         }
1985                         break;
1986                 }
1987         }
1988         return super.wmNotify (hdr, wParam, lParam);
1989 }
1990
1991 }